Assignment 4
Question 1. Alumni Donation Data
Import Data and load libraries from URL: https://bgreenwell.github.io/uc-bana7052/data/alumni.csv
url <- "https://bgreenwell.github.io/uc-bana7052/data/alumni.csv"
alumni <- read.csv(url)
str(alumni)
attach(alumni)
library(tidyverse)
library(investr)
library(car)
library(lmtest)
library(gridExtra)
1) Does the assumption of error normality appear to be
violated?
To see if the error normality is violated or not, I am going to use a
QQ plot to diagnose it. First I am going to fit the data to a linear
regression model.
# fit the model
fit <- lm(alumni_giving_rate ~ percent_of_classes_under_20 + student_faculty_ratio)
# residual diagnostics
qqnorm(residuals(fit), main = "Right-skewed Distribution")
qqline(residuals(fit), col = "blue")

From the QQ plot we can see that the majority of the points are on
the straight line while some of the of points are above the line. This
tells us that it’s right-skewed.
We can also use the Shapiro-Wilk test to exam the p value:
shapiro.test(residuals(fit))
Shapiro-Wilk normality test
data: residuals(fit)
W = 0.94577, p-value = 0.02721
The P value from the Shapiro-Wilk normality test is 0.027, which is
less than the threshold value of 0.05, so it indicates the
non-normality.
2) Does the assumption of constant error variance appear to
be violated?
To diagnose that, I am going to compare the Residuals VS Fitted
Values plot. I will be getting the studentized residual and fitted
values.
# studentized residual
r.stu <- rstandard(fit)
# fitted value
f.val <- fitted(fit)
plot(f.val, y = r.stu, xlab = "Fitted Value", ylab = "Studentized Residual")
abline(h = c(-2, 0,2), lty = 2, col = 2)

From the Residual vs Fitted value plot, we can see that most points
are scattered around the 0 reference line and within the -2 to +2 range.
It suggests the assumtpion of constant variance may hold.
We can also use Breush-Pagan test to see if there is non-constant
variance.
bptest(fit)
studentized Breusch-Pagan test
data: fit
BP = 0.2723, df = 2, p-value = 0.8727
We can see that the P value is 0.8727 which is larger than the 0.05
threshold, this suggests that there is no strong evidence of
heteroscedasticity, so we can say that the constant variance is not
violated.
3) Does there appear to be any Y or X outliers or influential
points?
To detect if there are outliers or influential points, I am going to
use the Cook’s distance and leverage plots.
h <- hatvalues(fit)
out <- which(h > 2 * mean(h))
plot(h, type = "h", ylim = extendrange(h, f = 0.15), main = "High Leverage Points")
abline(h = 2 * mean(h), col = 2)
text(out, y = h[out], labels = out, pos = 3, col = 3)

influencePlot(fit)

We can see from the High Leverage Points plot that there are three
values that are greater than \(2\bar{h}\), which can be considered as
outliers with respect to the predictor values. Also from the influence
measure, We can see there are two more values that can be considered
influential and maybe outliers.
4) Is there any concern about multicollinearity?
To access the multicollinearity, I will use the vaiance inflation
factors (VIFs) to detect. VIF quantifies how much the variance of a
regression coefficient is inflated due to multicollinearity with other
predictors.
car::vif(fit)
percent_of_classes_under_20 student_faculty_ratio
2.611671 2.611671
From the result we can see that the VIF values for both predictors
are around 2.61, which is not large enough (normal 10) to be a major
concern. Therefore, we can say that there is not much of a concern about
multicollinearity.
e) What is the predicted alumni giving rate for an
observation with (𝑋1 = 40, 𝑋2 = 5)? Is there any concern about this
prediction? Please explain.
To find the predicted alumni giving rate, we are going to first
estimate the model.
MLR model with normal errors is given – \(Y_i = \beta_0 + \sum_{j=1}^{p-1} \beta_j X_{ij} +
\epsilon_i, i = 1,2, ..., n\).
coef(fit)
(Intercept) percent_of_classes_under_20 student_faculty_ratio
39.6555835 0.1661686 -1.7021103
From the coefficients result above, we can estimate that the final
model is \(\hat{Y} = 39.66 + 0.166 X_1 - 1.702
X_2\).
To find the predicted alumni giving rate:
X1 <- 40
X2 <- 5
Y <- 39.6555835 + 0.1661686 * X1 - 1.7021103 * X2
print(paste("The predicted alumni giving rate is",Y))
[1] "The predicted alumni giving rate is 37.791776"
boxplot(alumni$percent_of_classes_under_20, main = "Boxplot of percent of classes under 20", xlab = "percent of calsses under 20", ylab = "percentage")

boxplot(alumni$student_faculty_ratio, main = "Boxplot of student faculty ratio", xlab = "student faculty ratio", ylab = "ratio")

To determine if there is a concern about the prediction, I am going
to see it from two different aspects.
From the boxplot we can see the mean and the 1st and 3rd
quartiles of each predictors, which we can see that X1 = 40 and X2
equals to 5 is not within that range. If those are outliers of the
observed dataset, then the prediction may not be most reliable.
We have diagnosed that the residuals do not seem to have
normality. The model assumptions are linearity, normality of residuals
and constant variance. Since we have a violation against normality, the
prediction may not be reliable.
Question 2, Simulation Study. Assume mean function \(E(Y|X = 10 + 5X - 2X^2)\).
a) Generate data with \(X_1 \sim
N(\mu = 3, \sigma = 0.5)\), sample size \(n = 100\), and error term \(\epsilon \sim N(\mu = 0, \sigma =
0.5)\)
set.seed(7052)
x1 <- rnorm(100, mean = 3, sd = 0.5)
error <- rnorm(100, mean = 0, sd = 0.5)
y <- 10 + 5 * x1 - 2 * x1^2 + error
data <- data.frame(x1, y)
head(mdata, n=3)
b) Fit a SLR using just X. What is the estimated regression
equation? Please conduct model estimation, inference, and residual
diagnostics. What do you conclude?
To fit the simple linear regression model \(Y = \beta_0 + \beta_1 X +\epsilon\), I will
first use the lm() function to fit the model and run a
summary statistic on it to get the coefficient.
model.fit <- lm(y ~ x1, data = data)
summary(model.fit)
Call:
lm(formula = y ~ x1, data = data)
Residuals:
Min 1Q Median 3Q Max
-3.2342 -0.2929 0.1358 0.5694 1.9273
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 27.5188 0.4870 56.51 <2e-16 ***
x1 -6.9848 0.1588 -43.99 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.8617 on 98 degrees of freedom
Multiple R-squared: 0.9518, Adjusted R-squared: 0.9513
F-statistic: 1935 on 1 and 98 DF, p-value: < 2.2e-16
The intercept \(\beta_0 = 27.52\)
and slope value is \(\beta_1 = -6.98\),
so we can say the estimated model is \(\hat{y}
= 27.52 -6.98x_1\).
From the summary statistics, we can also see that the p-value for
both intercept and x1 are very small, both are less than \(2e^-16\), which is less than the 0.05
threshold, so it is statistically significant, there is a negative
linear relationship between the response and the predictor.
par(mfrow = c(2,2))
plot(model.fit)

From the residual diagnostic plots, we can see that:
There is a violation to the normality. From the QQ plot, we can
see points below the trend line, which indicats a left-skewed
distribution.
There is a violation of constant variance. While the fitted value
between 5-10 has consistent small residuals, there are also quite a lot
points that below the reference line and drop out of the standardized
residual threshold \(r_i^{(stan)} <
3\).
From the Residuals vs Leverage plot we can see that there are
presence of outliers and influential points. Such as 14, 85, 68 labed in
the plot.
c) Update the model from part b by adding a quadratic term.
Conduct model estimation, inference, and residual diagnostics. What do
you conclude? Does this model seem to fit the data better?
To fit the quadratic model, we can say \(\hat{y} = \beta_0 + \beta_1 x_1 + \beta_2 x^2 +
\epsilon\). I am going to assign x_squared to be
\(x_1^2\).
data2 <- mutate(data, x_squared = x1^2)
head(data2, n=3)
fit2 <- lm(y ~ x1 + x_squared, data = data2)
summary(fit2)
Call:
lm(formula = y ~ x1 + x_squared, data = data2)
Residuals:
Min 1Q Median 3Q Max
-1.19046 -0.30582 0.03546 0.31477 1.38463
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 10.7438 1.0707 10.034 < 2e-16 ***
x1 4.4770 0.7154 6.258 1.06e-08 ***
x_squared -1.8949 0.1175 -16.131 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.4513 on 97 degrees of freedom
Multiple R-squared: 0.9869, Adjusted R-squared: 0.9866
F-statistic: 3656 on 2 and 97 DF, p-value: < 2.2e-16
After refitting the linear model and run the summary statistics, we
can estimate based on the \(\beta_0, \beta_1,
and \beta_2\) value. \(\beta_0 = 10.74,
\beta_1 = 4.48, \beta_2 = -1.89\), therefore, the estimated model
is \(\hat{y} = 10.74 + 4.48x_1 -
1.89x_1^2\).
The p value of three coefficients are very small, indicates
statistical significance. We can also look at the \(R^2\) value, the \(R^2\) value from the single linear
regression model is 0.95 and this model’s \(R^2\) value is increased to 0.99, which
increased quite a bit. When \(R^2\)
value increase, it indicates a better fit of the model.
par(mfrow = c(2,2))
plot(fit2)

From the residual diagnostic plots, we can also see that:
The QQ plot is behaving better, most of the points are right on
the line, indicates a normal distribution, there is one value slightly
outside of the line, but there is not big influence for that
one.
The fitted value vs standardized residual also seems to be
better, most of the values are within the -1.5 - +1.5 range, which
indicates a constant variance.
For cook’s distance and leverages, we can see there are still a
couple of outliers but it’s also behaving better than the previous
model. Most of the points are on the lefts ide which has a lower score.
We could do something to the outliers to make the data more accurate,
but these outliers may not be as significant.
From all the reasons above, the 2nd model fit is a better fit of the
data.
d) What is the variance inflation factor (VIF) for the
quadratic model? Any concern of multicollinearity?
car::vif(fit2)
x1 x_squared
73.97863 73.97863
By using the vif() function, we can see that the VIF
value for both \(x_1\) and \(x_1^2\) are very high, the values are
almost 74, which is way pass the normal value of 10. It strongly
suggests that there are multicollinearity, which could affect
codfficient stability.
e) Now enter the X variable and compare the VIF from d. What
did you find? Which VIF is smaller? Please brifly explain the
reason.
#method 1:
fit3 <- lm(y ~ x1 + I(x1^2), data = data2)
fit_centered1 <- lm(y ~ I(x1 - mean(x1)) + I((x1 - mean(x1))^2), data = data2)
# Method 2: center x in the training data
data2$x1_centered <- data2$x1 - mean(data2$x1)
fit_centered2 <- lm(y ~ x1_centered + I(x1_centered^2), data = data2)
car::vif(fit_centered1)
I(x1 - mean(x1)) I((x1 - mean(x1))^2)
1.000295 1.000295
car::vif(fit_centered2)
x1_centered I(x1_centered^2)
1.000295 1.000295
After center the X variable, the VIF scores dropped tremendously. I
used both methods to calculate the VIF and the results are almost equal
to 1, which is small enough to say that there is now no
multicollinearity, becuase the quadratic term is less correlated with
the centered X.
Question 3.
a) What are the assumptions of the normal linear regression
model?
The typical assumptions are:
Independence: The observation are independent of each
other.
Constant variance: the variance of the error term is constant
across all levels of the predictors. Therefore the residuals should be
roughly the same at all fitted values.
Normally distributed error. The error term are normally
distributed, particularly for inference purposes. When we do t test and
obtain confidence intervals, we normally assume that the error is
normally distributed.
We assume that we have the correct model or at least a useful
one.
Other assumptions like linearity, meaning the response variable
is linearly related to the predictors; and no multicollinearity, meaning
predictor variables are not highly correlated with each other are also
some common assumptions.
b) Are the residuals from linear regression uncorrelated in
general? Please explain. What is the distribution of
residuals?
Yes, in a correctly specified linear regression model, the residuals
are assumed to be uncorrelated with each other and the assumption of
independence holds. When we assume the observations are independent, we
imply that the errors should be uncorrelated across observations. The
residuals don’t necessarily be normally distributed, but if the error
terms are normally distributed, then the residuals will approximate a
normal distribution. Residuals should ideally have a mean of zero and
unit variance.
c) Why do we plot the residuals against the fitted value
rather than against the observed response value?
We can spot the pattern in a residuals vs fitted value plot, it
can indicate non-linearity or non-constant variance in the data. If
residuals are plotted against observed values, it’s harder to detect
htese issues related to model fit.
Fitted values are the best estimates provided by the model for y.
Checking how the residuals behave relative to these values helps assess
whether the model’s linear fit is appropriate.
The plot can also help spot outliers. The points are deviate
significantly from the test of the residuals at high or low fitted
values may have a large impact on the model.
d) What is multicollinearity? Computationally, what kind of
problems can multicollinearity cause when using ordinary lease
squares?
Multicollinearity happens when predictor variables are correlated
among themselves. When the correlation is high, there is a significant
multicollinearity. Although, multicollinearity does not always prevent
us from obtaining a good fit, it could cause some issues:
It can cause some of the estimated coefficients to become
unstable, like high standard errors. The estimates may become highly
sensitive to small changes in the data. It could also increase the
variance of the estimated regression coefficients which can make them
unstable and sensitive to minor changes in the model.
It can complicate the interpretation of the estimated
coefficients, because a change in one predictor will almost always
correspond with a change in another. It becomes hard to detect the true
effect of predictors because their p value become less
reliable.
LS0tCnRpdGxlOiAiQkFOQSA3MDUyIEFzc2lnbm1lbnQgNCAtIFJGaXNjaGVyIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCgoqKlRoZSBSIGNvZGUgaXMgaGlkZGVuIGJ5IGRlZmF1bHQuIFBsZWFzZSBjbGljayBvbiBTaG93IHRvIHZpZXcgYWxsIGNvZGVzLiBUaGFuayB5b3UuKioKCiMjIyBBc3NpZ25tZW50IDQKCiMjIyMgUXVlc3Rpb24gMS4gQWx1bW5pIERvbmF0aW9uIERhdGEKCkltcG9ydCBEYXRhIGFuZCBsb2FkIGxpYnJhcmllcyBmcm9tIFVSTDogaHR0cHM6Ly9iZ3JlZW53ZWxsLmdpdGh1Yi5pby91Yy1iYW5hNzA1Mi9kYXRhL2FsdW1uaS5jc3YKYGBge3IgSW1wb3J0IERhdGEgQWx1bW5pfQp1cmwgPC0gImh0dHBzOi8vYmdyZWVud2VsbC5naXRodWIuaW8vdWMtYmFuYTcwNTIvZGF0YS9hbHVtbmkuY3N2IgphbHVtbmkgPC0gcmVhZC5jc3YodXJsKQpzdHIoYWx1bW5pKQphdHRhY2goYWx1bW5pKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShpbnZlc3RyKQpsaWJyYXJ5KGNhcikKbGlicmFyeShsbXRlc3QpCmxpYnJhcnkoZ3JpZEV4dHJhKQpgYGAKCioqMSkgRG9lcyB0aGUgYXNzdW1wdGlvbiBvZiBlcnJvciBub3JtYWxpdHkgYXBwZWFyIHRvIGJlIHZpb2xhdGVkPyoqCgpUbyBzZWUgaWYgdGhlIGVycm9yIG5vcm1hbGl0eSBpcyB2aW9sYXRlZCBvciBub3QsIEkgYW0gZ29pbmcgdG8gdXNlIGEgUVEgcGxvdCB0byBkaWFnbm9zZSBpdC4gRmlyc3QgSSBhbSBnb2luZyB0byBmaXQgdGhlIGRhdGEgdG8gYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbC4KCmBgYHtyfQojIGZpdCB0aGUgbW9kZWwKZml0IDwtIGxtKGFsdW1uaV9naXZpbmdfcmF0ZSB+IHBlcmNlbnRfb2ZfY2xhc3Nlc191bmRlcl8yMCArIHN0dWRlbnRfZmFjdWx0eV9yYXRpbykKCiMgcmVzaWR1YWwgZGlhZ25vc3RpY3MKcXFub3JtKHJlc2lkdWFscyhmaXQpLCBtYWluID0gIlJpZ2h0LXNrZXdlZCBEaXN0cmlidXRpb24iKQpxcWxpbmUocmVzaWR1YWxzKGZpdCksIGNvbCA9ICJibHVlIikKYGBgCgpGcm9tIHRoZSBRUSBwbG90IHdlIGNhbiBzZWUgdGhhdCB0aGUgbWFqb3JpdHkgb2YgdGhlIHBvaW50cyBhcmUgb24gdGhlIHN0cmFpZ2h0IGxpbmUgd2hpbGUgc29tZSBvZiB0aGUgb2YgcG9pbnRzIGFyZSBhYm92ZSB0aGUgbGluZS4gVGhpcyB0ZWxscyB1cyB0aGF0IGl0J3MgcmlnaHQtc2tld2VkLiAKCldlIGNhbiBhbHNvIHVzZSB0aGUgU2hhcGlyby1XaWxrIHRlc3QgdG8gZXhhbSB0aGUgcCB2YWx1ZToKCmBgYHtyIHNoYXBpcm8gdGVzdH0Kc2hhcGlyby50ZXN0KHJlc2lkdWFscyhmaXQpKQpgYGAKClRoZSBQIHZhbHVlIGZyb20gdGhlIFNoYXBpcm8tV2lsayBub3JtYWxpdHkgdGVzdCBpcyAwLjAyNywgd2hpY2ggaXMgbGVzcyB0aGFuIHRoZSB0aHJlc2hvbGQgdmFsdWUgb2YgMC4wNSwgc28gaXQgaW5kaWNhdGVzIHRoZSBub24tbm9ybWFsaXR5LgoKKioyKSBEb2VzIHRoZSBhc3N1bXB0aW9uIG9mIGNvbnN0YW50IGVycm9yIHZhcmlhbmNlIGFwcGVhciB0byBiZSB2aW9sYXRlZD8qKgoKVG8gZGlhZ25vc2UgdGhhdCwgSSBhbSBnb2luZyB0byBjb21wYXJlIHRoZSBSZXNpZHVhbHMgVlMgRml0dGVkIFZhbHVlcyBwbG90LiBJIHdpbGwgYmUgZ2V0dGluZyB0aGUgc3R1ZGVudGl6ZWQgcmVzaWR1YWwgYW5kIGZpdHRlZCB2YWx1ZXMuCgpgYGB7ciByZXNpZHVhbCB2cyBmaXR0ZWQgdmFsdWV9CiMgc3R1ZGVudGl6ZWQgcmVzaWR1YWwKci5vcmQgPC0gcnN0YW5kYXJkKGZpdCkKIyBmaXR0ZWQgdmFsdWUKZi52YWwgPC0gZml0dGVkKGZpdCkKcGxvdChmLnZhbCwgeSA9IHIuc3R1LCB4bGFiID0gIkZpdHRlZCBWYWx1ZSIsIHlsYWIgPSAiU3R1ZGVudGl6ZWQgUmVzaWR1YWwiLCBtYWluID0gIlJlc2lkdWFscyB2cyBGaXR0ZWQiKQphYmxpbmUoaCA9IGMoLTIsIDAsMiksIGx0eSA9IDIsIGNvbCA9IDIpCmBgYAoKRnJvbSB0aGUgUmVzaWR1YWwgdnMgRml0dGVkIHZhbHVlIHBsb3QsIHdlIGNhbiBzZWUgdGhhdCBtb3N0IHBvaW50cyBhcmUgc2NhdHRlcmVkIGFyb3VuZCB0aGUgMCByZWZlcmVuY2UgbGluZSBhbmQgd2l0aGluIHRoZSAtMiB0byArMiByYW5nZS4gSXQgc3VnZ2VzdHMgdGhlIGFzc3VtdHBpb24gb2YgY29uc3RhbnQgdmFyaWFuY2UgbWF5IGhvbGQuCgpXZSBjYW4gYWxzbyB1c2UgQnJldXNoLVBhZ2FuIHRlc3QgdG8gc2VlIGlmIHRoZXJlIGlzIG5vbi1jb25zdGFudCB2YXJpYW5jZS4KCmBgYHtyIGJwdGVzdH0KYnB0ZXN0KGZpdCkKYGBgCgpXZSBjYW4gc2VlIHRoYXQgdGhlIFAgdmFsdWUgaXMgMC44NzI3IHdoaWNoIGlzIGxhcmdlciB0aGFuIHRoZSAwLjA1IHRocmVzaG9sZCwgdGhpcyBzdWdnZXN0cyB0aGF0IHRoZXJlIGlzIG5vIHN0cm9uZyBldmlkZW5jZSBvZiBoZXRlcm9zY2VkYXN0aWNpdHksIHNvIHdlIGNhbiBzYXkgdGhhdCB0aGUgY29uc3RhbnQgdmFyaWFuY2UgaXMgbm90IHZpb2xhdGVkLgoKKiozKSBEb2VzIHRoZXJlIGFwcGVhciB0byBiZSBhbnkgWSBvciBYIG91dGxpZXJzIG9yIGluZmx1ZW50aWFsIHBvaW50cz8qKgoKVG8gZGV0ZWN0IGlmIHRoZXJlIGFyZSBvdXRsaWVycyBvciBpbmZsdWVudGlhbCBwb2ludHMsIEkgYW0gZ29pbmcgdG8gdXNlIHRoZSBDb29rJ3MgZGlzdGFuY2UgYW5kIGxldmVyYWdlIHBsb3RzLgoKYGBge3J9CmggPC0gaGF0dmFsdWVzKGZpdCkKb3V0IDwtIHdoaWNoKGggPiAyICogbWVhbihoKSkKcGxvdChoLCB0eXBlID0gImgiLCB5bGltID0gZXh0ZW5kcmFuZ2UoaCwgZiA9IDAuMTUpLCBtYWluID0gIkhpZ2ggTGV2ZXJhZ2UgUG9pbnRzIikKYWJsaW5lKGggPSAyICogbWVhbihoKSwgY29sID0gMikKdGV4dChvdXQsIHkgPSBoW291dF0sIGxhYmVscyA9IG91dCwgcG9zID0gMywgY29sID0gMykKYGBgCgpgYGB7cn0KaW5mbHVlbmNlUGxvdChmaXQpCmBgYAoKV2UgY2FuIHNlZSBmcm9tIHRoZSBIaWdoIExldmVyYWdlIFBvaW50cyBwbG90IHRoYXQgdGhlcmUgYXJlIHRocmVlIHZhbHVlcyB0aGF0IGFyZSBncmVhdGVyIHRoYW4gJDJcYmFye2h9JCwgd2hpY2ggY2FuIGJlIGNvbnNpZGVyZWQgYXMgb3V0bGllcnMgd2l0aCByZXNwZWN0IHRvIHRoZSBwcmVkaWN0b3IgdmFsdWVzLiBBbHNvIGZyb20gdGhlIGluZmx1ZW5jZSBtZWFzdXJlLCBXZSBjYW4gc2VlIHRoZXJlIGFyZSB0d28gbW9yZSB2YWx1ZXMgdGhhdCBjYW4gYmUgY29uc2lkZXJlZCBpbmZsdWVudGlhbCBhbmQgbWF5YmUgb3V0bGllcnMuCgoqKjQpIElzIHRoZXJlIGFueSBjb25jZXJuIGFib3V0IG11bHRpY29sbGluZWFyaXR5PyoqCgpUbyBhY2Nlc3MgdGhlIG11bHRpY29sbGluZWFyaXR5LCBJIHdpbGwgdXNlIHRoZSB2YWlhbmNlIGluZmxhdGlvbiBmYWN0b3JzIChWSUZzKSB0byBkZXRlY3QuIFZJRiBxdWFudGlmaWVzIGhvdyBtdWNoIHRoZSB2YXJpYW5jZSBvZiBhIHJlZ3Jlc3Npb24gY29lZmZpY2llbnQgaXMgaW5mbGF0ZWQgZHVlIHRvIG11bHRpY29sbGluZWFyaXR5IHdpdGggb3RoZXIgcHJlZGljdG9ycy4gCgpgYGB7ciBtdWx0aWNvbGxpbmVhcml0eX0KY2FyOjp2aWYoZml0KQpgYGAKCkZyb20gdGhlIHJlc3VsdCB3ZSBjYW4gc2VlIHRoYXQgdGhlIFZJRiB2YWx1ZXMgZm9yIGJvdGggcHJlZGljdG9ycyBhcmUgYXJvdW5kIDIuNjEsIHdoaWNoIGlzIG5vdCBsYXJnZSBlbm91Z2ggKG5vcm1hbCAxMCkgdG8gYmUgYSBtYWpvciBjb25jZXJuLiBUaGVyZWZvcmUsIHdlIGNhbiBzYXkgdGhhdCB0aGVyZSBpcyBub3QgbXVjaCBvZiBhIGNvbmNlcm4gYWJvdXQgbXVsdGljb2xsaW5lYXJpdHkuCgoqKmUpIFdoYXQgaXMgdGhlIHByZWRpY3RlZCBhbHVtbmkgZ2l2aW5nIHJhdGUgZm9yIGFuIG9ic2VydmF0aW9uIHdpdGggKPCdkYsxID0gNDAsIPCdkYsyID0gNSk/IElzIHRoZXJlIGFueSBjb25jZXJuIGFib3V0IHRoaXMgcHJlZGljdGlvbj8gUGxlYXNlIGV4cGxhaW4uKioKClRvIGZpbmQgdGhlIHByZWRpY3RlZCBhbHVtbmkgZ2l2aW5nIHJhdGUsIHdlIGFyZSBnb2luZyB0byBmaXJzdCBlc3RpbWF0ZSB0aGUgbW9kZWwuCgpNTFIgbW9kZWwgd2l0aCBub3JtYWwgZXJyb3JzIGlzIGdpdmVuIC0tICRZX2kgPSBcYmV0YV8wICsgXHN1bV97aj0xfV57cC0xfSBcYmV0YV9qIFhfe2lqfSArIFxlcHNpbG9uX2ksIGkgPSAxLDIsIC4uLiwgbiQuCgpgYGB7ciBmaXQgTUxSfQpjb2VmKGZpdCkKYGBgCgpGcm9tIHRoZSBjb2VmZmljaWVudHMgcmVzdWx0IGFib3ZlLCB3ZSBjYW4gZXN0aW1hdGUgdGhhdCB0aGUgZmluYWwgbW9kZWwgaXMgJFxoYXR7WX0gPSAzOS42NiArIDAuMTY2IFhfMSAtIDEuNzAyIFhfMiQuCgpUbyBmaW5kIHRoZSBwcmVkaWN0ZWQgYWx1bW5pIGdpdmluZyByYXRlOgoKYGBge3J9ClgxIDwtIDQwClgyIDwtIDUKWSA8LSAzOS42NTU1ODM1ICsgMC4xNjYxNjg2ICogWDEgLSAxLjcwMjExMDMgKiBYMgpwcmludChwYXN0ZSgiVGhlIHByZWRpY3RlZCBhbHVtbmkgZ2l2aW5nIHJhdGUgaXMiLFkpKQpgYGAKCmBgYHtyfQpib3hwbG90KGFsdW1uaSRwZXJjZW50X29mX2NsYXNzZXNfdW5kZXJfMjAsIG1haW4gPSAiQm94cGxvdCBvZiBwZXJjZW50IG9mIGNsYXNzZXMgdW5kZXIgMjAiLCB4bGFiID0gInBlcmNlbnQgb2YgY2Fsc3NlcyB1bmRlciAyMCIsIHlsYWIgPSAicGVyY2VudGFnZSIpCmJveHBsb3QoYWx1bW5pJHN0dWRlbnRfZmFjdWx0eV9yYXRpbywgbWFpbiA9ICJCb3hwbG90IG9mIHN0dWRlbnQgZmFjdWx0eSByYXRpbyIsIHhsYWIgPSAic3R1ZGVudCBmYWN1bHR5IHJhdGlvIiwgeWxhYiA9ICJyYXRpbyIpCmBgYAoKVG8gZGV0ZXJtaW5lIGlmIHRoZXJlIGlzIGEgY29uY2VybiBhYm91dCB0aGUgcHJlZGljdGlvbiwgSSBhbSBnb2luZyB0byBzZWUgaXQgZnJvbSB0d28gZGlmZmVyZW50IGFzcGVjdHMuCgoxLiBGcm9tIHRoZSBib3hwbG90IHdlIGNhbiBzZWUgdGhlIG1lYW4gYW5kIHRoZSAxc3QgYW5kIDNyZCBxdWFydGlsZXMgb2YgZWFjaCBwcmVkaWN0b3JzLCB3aGljaCB3ZSBjYW4gc2VlIHRoYXQgWDEgPSA0MCBhbmQgWDIgZXF1YWxzIHRvIDUgaXMgbm90IHdpdGhpbiB0aGF0IHJhbmdlLiBJZiB0aG9zZSBhcmUgb3V0bGllcnMgb2YgdGhlIG9ic2VydmVkIGRhdGFzZXQsIHRoZW4gdGhlIHByZWRpY3Rpb24gbWF5IG5vdCBiZSBtb3N0IHJlbGlhYmxlLgoKMi4gV2UgaGF2ZSBkaWFnbm9zZWQgdGhhdCB0aGUgcmVzaWR1YWxzIGRvIG5vdCBzZWVtIHRvIGhhdmUgbm9ybWFsaXR5LiBUaGUgbW9kZWwgYXNzdW1wdGlvbnMgYXJlIGxpbmVhcml0eSwgbm9ybWFsaXR5IG9mIHJlc2lkdWFscyBhbmQgY29uc3RhbnQgdmFyaWFuY2UuIFNpbmNlIHdlIGhhdmUgYSB2aW9sYXRpb24gYWdhaW5zdCBub3JtYWxpdHksIHRoZSBwcmVkaWN0aW9uIG1heSBub3QgYmUgcmVsaWFibGUuCgojIyMjIFF1ZXN0aW9uIDIsIFNpbXVsYXRpb24gU3R1ZHkuIEFzc3VtZSBtZWFuIGZ1bmN0aW9uICRFKFl8WCA9IDEwICsgNVggLSAyWF4yKSQuCgoqKmEpIEdlbmVyYXRlIGRhdGEgd2l0aCAkWF8xIFxzaW0gTihcbXUgPSAzLCBcc2lnbWEgPSAwLjUpJCwgc2FtcGxlIHNpemUgJG4gPSAxMDAkLCBhbmQgZXJyb3IgdGVybSAkXGVwc2lsb24gXHNpbSBOKFxtdSA9IDAsIFxzaWdtYSA9IDAuNSkkKioKCmBgYHtyIHNhbXBsZX0Kc2V0LnNlZWQoNzA1MikKeDEgPC0gcm5vcm0oMTAwLCBtZWFuID0gMywgc2QgPSAwLjUpCmVycm9yIDwtIHJub3JtKDEwMCwgbWVhbiA9IDAsIHNkID0gMC41KQp5IDwtIDEwICsgNSAqIHgxIC0gMiAqIHgxXjIgKyBlcnJvcgpkYXRhIDwtIGRhdGEuZnJhbWUoeDEsIHkpCmhlYWQobWRhdGEsIG49MykKYGBgCgoqKmIpIEZpdCBhIFNMUiB1c2luZyBqdXN0IFguIFdoYXQgaXMgdGhlIGVzdGltYXRlZCByZWdyZXNzaW9uIGVxdWF0aW9uPyBQbGVhc2UgY29uZHVjdCBtb2RlbCBlc3RpbWF0aW9uLCBpbmZlcmVuY2UsIGFuZCByZXNpZHVhbCBkaWFnbm9zdGljcy4gV2hhdCBkbyB5b3UgY29uY2x1ZGU/KioKClRvIGZpdCB0aGUgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsICRZID0gXGJldGFfMCArIFxiZXRhXzEgWCArXGVwc2lsb24kLCBJIHdpbGwgZmlyc3QgdXNlIHRoZSBgbG0oKWAgZnVuY3Rpb24gdG8gZml0IHRoZSBtb2RlbCBhbmQgcnVuIGEgc3VtbWFyeSBzdGF0aXN0aWMgb24gaXQgdG8gZ2V0IHRoZSBjb2VmZmljaWVudC4KCmBgYHtyIGZpdCBtb2RlbH0KbW9kZWwuZml0IDwtIGxtKHkgfiB4MSwgZGF0YSA9IGRhdGEpCnN1bW1hcnkobW9kZWwuZml0KQpgYGAKClRoZSBpbnRlcmNlcHQgJFxiZXRhXzAgPSAyNy41MiQgYW5kIHNsb3BlIHZhbHVlIGlzICRcYmV0YV8xID0gLTYuOTgkLCBzbyB3ZSBjYW4gc2F5IHRoZSBlc3RpbWF0ZWQgbW9kZWwgaXMgJFxoYXR7eX0gPSAyNy41MiAtNi45OHhfMSQuIAoKRnJvbSB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzLCB3ZSBjYW4gYWxzbyBzZWUgdGhhdCB0aGUgcC12YWx1ZSBmb3IgYm90aCBpbnRlcmNlcHQgYW5kIHgxIGFyZSB2ZXJ5IHNtYWxsLCBib3RoIGFyZSBsZXNzIHRoYW4gJDJlXi0xNiQsIHdoaWNoIGlzIGxlc3MgdGhhbiB0aGUgMC4wNSB0aHJlc2hvbGQsIHNvIGl0IGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQsIHRoZXJlIGlzIGEgbmVnYXRpdmUgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSByZXNwb25zZSBhbmQgdGhlIHByZWRpY3Rvci4KCmBgYHtyIHJlc2lkdWFsIGRpYWd9CnBhcihtZnJvdyA9IGMoMiwyKSkKcGxvdChtb2RlbC5maXQpCmBgYAoKRnJvbSB0aGUgcmVzaWR1YWwgZGlhZ25vc3RpYyBwbG90cywgd2UgY2FuIHNlZSB0aGF0OiAKCjEuIFRoZXJlIGlzIGEgdmlvbGF0aW9uIHRvIHRoZSBub3JtYWxpdHkuIEZyb20gdGhlIFFRIHBsb3QsIHdlIGNhbiBzZWUgcG9pbnRzIGJlbG93IHRoZSB0cmVuZCBsaW5lLCB3aGljaCBpbmRpY2F0cyBhIGxlZnQtc2tld2VkIGRpc3RyaWJ1dGlvbi4KCjIuIFRoZXJlIGlzIGEgdmlvbGF0aW9uIG9mIGNvbnN0YW50IHZhcmlhbmNlLiBXaGlsZSB0aGUgZml0dGVkIHZhbHVlIGJldHdlZW4gNS0xMCBoYXMgY29uc2lzdGVudCBzbWFsbCByZXNpZHVhbHMsIHRoZXJlIGFyZSBhbHNvIHF1aXRlIGEgbG90IHBvaW50cyB0aGF0IGJlbG93IHRoZSByZWZlcmVuY2UgbGluZSBhbmQgZHJvcCBvdXQgb2YgdGhlIHN0YW5kYXJkaXplZCByZXNpZHVhbCB0aHJlc2hvbGQgJHJfaV57KHN0YW4pfSA8IDMkLgoKMy4gRnJvbSB0aGUgUmVzaWR1YWxzIHZzIExldmVyYWdlIHBsb3Qgd2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSBwcmVzZW5jZSBvZiBvdXRsaWVycyBhbmQgaW5mbHVlbnRpYWwgcG9pbnRzLiBTdWNoIGFzIDE0LCA4NSwgNjggbGFiZWQgaW4gdGhlIHBsb3QuCgoqKmMpIFVwZGF0ZSB0aGUgbW9kZWwgZnJvbSBwYXJ0IGIgYnkgYWRkaW5nIGEgcXVhZHJhdGljIHRlcm0uIENvbmR1Y3QgbW9kZWwgZXN0aW1hdGlvbiwgaW5mZXJlbmNlLCBhbmQgcmVzaWR1YWwgZGlhZ25vc3RpY3MuIFdoYXQgZG8geW91IGNvbmNsdWRlPyBEb2VzIHRoaXMgbW9kZWwgc2VlbSB0byBmaXQgdGhlIGRhdGEgYmV0dGVyPyoqCgpUbyBmaXQgdGhlIHF1YWRyYXRpYyBtb2RlbCwgd2UgY2FuIHNheSAkXGhhdHt5fSA9IFxiZXRhXzAgKyBcYmV0YV8xIHhfMSArIFxiZXRhXzIgeF4yICsgXGVwc2lsb24kLiBJIGFtIGdvaW5nIHRvIGFzc2lnbiBgeF9zcXVhcmVkYCB0byBiZSAkeF8xXjIkLgoKYGBge3J9CmRhdGEyIDwtIG11dGF0ZShkYXRhLCB4X3NxdWFyZWQgPSB4MV4yKQpoZWFkKGRhdGEyLCBuPTMpCmBgYAoKYGBge3IgcmVmaXQgbW9kZWx9CmZpdDIgPC0gbG0oeSB+IHgxICsgeF9zcXVhcmVkLCBkYXRhID0gZGF0YTIpCnN1bW1hcnkoZml0MikKYGBgCgpBZnRlciByZWZpdHRpbmcgdGhlIGxpbmVhciBtb2RlbCBhbmQgcnVuIHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MsIHdlIGNhbiBlc3RpbWF0ZSBiYXNlZCBvbiB0aGUgJFxiZXRhXzAsIFxiZXRhXzEsIGFuZCBcYmV0YV8yJCB2YWx1ZS4gJFxiZXRhXzAgPSAxMC43NCwgXGJldGFfMSA9IDQuNDgsIFxiZXRhXzIgPSAtMS44OSQsIHRoZXJlZm9yZSwgdGhlIGVzdGltYXRlZCBtb2RlbCBpcyAkXGhhdHt5fSA9IDEwLjc0ICsgNC40OHhfMSAtIDEuODl4XzFeMiQuCgpUaGUgcCB2YWx1ZSBvZiB0aHJlZSBjb2VmZmljaWVudHMgYXJlIHZlcnkgc21hbGwsIGluZGljYXRlcyBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuIFdlIGNhbiBhbHNvIGxvb2sgYXQgdGhlICRSXjIkIHZhbHVlLCB0aGUgJFJeMiQgdmFsdWUgZnJvbSB0aGUgc2luZ2xlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIGlzIDAuOTUgYW5kIHRoaXMgbW9kZWwncyAkUl4yJCB2YWx1ZSBpcyBpbmNyZWFzZWQgdG8gMC45OSwgd2hpY2ggaW5jcmVhc2VkIHF1aXRlIGEgYml0LiBXaGVuICRSXjIkIHZhbHVlIGluY3JlYXNlLCBpdCBpbmRpY2F0ZXMgYSBiZXR0ZXIgZml0IG9mIHRoZSBtb2RlbC4KCmBgYHtyIHJlc2lkdWFsIG9mIGZpdDJ9CnBhcihtZnJvdyA9IGMoMiwyKSkKcGxvdChmaXQyKQpgYGAKCkZyb20gdGhlIHJlc2lkdWFsIGRpYWdub3N0aWMgcGxvdHMsIHdlIGNhbiBhbHNvIHNlZSB0aGF0OgoKMS4gVGhlIFFRIHBsb3QgaXMgYmVoYXZpbmcgYmV0dGVyLCBtb3N0IG9mIHRoZSBwb2ludHMgYXJlIHJpZ2h0IG9uIHRoZSBsaW5lLCBpbmRpY2F0ZXMgYSBub3JtYWwgZGlzdHJpYnV0aW9uLCB0aGVyZSBpcyBvbmUgdmFsdWUgc2xpZ2h0bHkgb3V0c2lkZSBvZiB0aGUgbGluZSwgYnV0IHRoZXJlIGlzIG5vdCBiaWcgaW5mbHVlbmNlIGZvciB0aGF0IG9uZS4gCgoyLiBUaGUgZml0dGVkIHZhbHVlIHZzIHN0YW5kYXJkaXplZCByZXNpZHVhbCBhbHNvIHNlZW1zIHRvIGJlIGJldHRlciwgbW9zdCBvZiB0aGUgdmFsdWVzIGFyZSB3aXRoaW4gdGhlIC0xLjUgLSArMS41IHJhbmdlLCB3aGljaCBpbmRpY2F0ZXMgYSBjb25zdGFudCB2YXJpYW5jZS4KCjMuIEZvciBjb29rJ3MgZGlzdGFuY2UgYW5kIGxldmVyYWdlcywgd2UgY2FuIHNlZSB0aGVyZSBhcmUgc3RpbGwgYSBjb3VwbGUgb2Ygb3V0bGllcnMgYnV0IGl0J3MgYWxzbyBiZWhhdmluZyBiZXR0ZXIgdGhhbiB0aGUgcHJldmlvdXMgbW9kZWwuIE1vc3Qgb2YgdGhlIHBvaW50cyBhcmUgb24gdGhlIGxlZnRzIGlkZSB3aGljaCBoYXMgYSBsb3dlciBzY29yZS4gV2UgY291bGQgZG8gc29tZXRoaW5nIHRvIHRoZSBvdXRsaWVycyB0byBtYWtlIHRoZSBkYXRhIG1vcmUgYWNjdXJhdGUsIGJ1dCB0aGVzZSBvdXRsaWVycyBtYXkgbm90IGJlIGFzIHNpZ25pZmljYW50LgoKRnJvbSBhbGwgdGhlIHJlYXNvbnMgYWJvdmUsIHRoZSAybmQgbW9kZWwgZml0IGlzIGEgYmV0dGVyIGZpdCBvZiB0aGUgZGF0YS4KCioqZCkgV2hhdCBpcyB0aGUgdmFyaWFuY2UgaW5mbGF0aW9uIGZhY3RvciAoVklGKSBmb3IgdGhlIHF1YWRyYXRpYyBtb2RlbD8gQW55IGNvbmNlcm4gb2YgbXVsdGljb2xsaW5lYXJpdHk/KioKCmBgYHtyIFZJRiBmaXQyfQpjYXI6OnZpZihmaXQyKQpgYGAKCkJ5IHVzaW5nIHRoZSBgdmlmKClgIGZ1bmN0aW9uLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIFZJRiB2YWx1ZSBmb3IgYm90aCAkeF8xJCBhbmQgJHhfMV4yJCBhcmUgdmVyeSBoaWdoLCB0aGUgdmFsdWVzIGFyZSBhbG1vc3QgNzQsIHdoaWNoIGlzIHdheSBwYXNzIHRoZSBub3JtYWwgdmFsdWUgb2YgMTAuIEl0IHN0cm9uZ2x5IHN1Z2dlc3RzIHRoYXQgdGhlcmUgYXJlIG11bHRpY29sbGluZWFyaXR5LCB3aGljaCBjb3VsZCBhZmZlY3QgY29kZmZpY2llbnQgc3RhYmlsaXR5LgoKKiplKSBOb3cgZW50ZXIgdGhlIFggdmFyaWFibGUgYW5kIGNvbXBhcmUgdGhlIFZJRiBmcm9tIGQuIFdoYXQgZGlkIHlvdSBmaW5kPyBXaGljaCBWSUYgaXMgc21hbGxlcj8gUGxlYXNlIGJyaWZseSBleHBsYWluIHRoZSByZWFzb24uKioKCmBgYHtyfQojbWV0aG9kIDE6CmZpdDMgPC0gbG0oeSB+IHgxICsgSSh4MV4yKSwgZGF0YSA9IGRhdGEyKQpmaXRfY2VudGVyZWQxIDwtIGxtKHkgfiBJKHgxIC0gbWVhbih4MSkpICsgSSgoeDEgLSBtZWFuKHgxKSleMiksIGRhdGEgPSBkYXRhMikKIyBNZXRob2QgMjogY2VudGVyIHggaW4gdGhlIHRyYWluaW5nIGRhdGEKZGF0YTIkeDFfY2VudGVyZWQgPC0gZGF0YTIkeDEgLSBtZWFuKGRhdGEyJHgxKQpmaXRfY2VudGVyZWQyIDwtIGxtKHkgfiB4MV9jZW50ZXJlZCArIEkoeDFfY2VudGVyZWReMiksIGRhdGEgPSBkYXRhMikKCmNhcjo6dmlmKGZpdF9jZW50ZXJlZDEpCmNhcjo6dmlmKGZpdF9jZW50ZXJlZDIpCmBgYAoKQWZ0ZXIgY2VudGVyIHRoZSBYIHZhcmlhYmxlLCB0aGUgVklGIHNjb3JlcyBkcm9wcGVkIHRyZW1lbmRvdXNseS4gSSB1c2VkIGJvdGggbWV0aG9kcyB0byBjYWxjdWxhdGUgdGhlIFZJRiBhbmQgdGhlIHJlc3VsdHMgYXJlIGFsbW9zdCBlcXVhbCB0byAxLCB3aGljaCBpcyBzbWFsbCBlbm91Z2ggdG8gc2F5IHRoYXQgdGhlcmUgaXMgbm93IG5vIG11bHRpY29sbGluZWFyaXR5LCBiZWN1YXNlIHRoZSBxdWFkcmF0aWMgdGVybSBpcyBsZXNzIGNvcnJlbGF0ZWQgd2l0aCB0aGUgY2VudGVyZWQgWC4KCiMjIyMgUXVlc3Rpb24gMy4KCioqYSkgV2hhdCBhcmUgdGhlIGFzc3VtcHRpb25zIG9mIHRoZSBub3JtYWwgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWw/KioKClRoZSB0eXBpY2FsIGFzc3VtcHRpb25zIGFyZToKCjEuIEluZGVwZW5kZW5jZTogVGhlIG9ic2VydmF0aW9uIGFyZSBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyLiAKCjIuIENvbnN0YW50IHZhcmlhbmNlOiB0aGUgdmFyaWFuY2Ugb2YgdGhlIGVycm9yIHRlcm0gaXMgY29uc3RhbnQgYWNyb3NzIGFsbCBsZXZlbHMgb2YgdGhlIHByZWRpY3RvcnMuIFRoZXJlZm9yZSB0aGUgcmVzaWR1YWxzIHNob3VsZCBiZSByb3VnaGx5IHRoZSBzYW1lIGF0IGFsbCBmaXR0ZWQgdmFsdWVzLgoKMy4gTm9ybWFsbHkgZGlzdHJpYnV0ZWQgZXJyb3IuIFRoZSBlcnJvciB0ZXJtIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZCwgcGFydGljdWxhcmx5IGZvciBpbmZlcmVuY2UgcHVycG9zZXMuIFdoZW4gd2UgZG8gdCB0ZXN0IGFuZCBvYnRhaW4gY29uZmlkZW5jZSBpbnRlcnZhbHMsIHdlIG5vcm1hbGx5IGFzc3VtZSB0aGF0IHRoZSBlcnJvciBpcyBub3JtYWxseSBkaXN0cmlidXRlZC4KCjQuIFdlIGFzc3VtZSB0aGF0IHdlIGhhdmUgdGhlIGNvcnJlY3QgbW9kZWwgb3IgYXQgbGVhc3QgYSB1c2VmdWwgb25lLgoKNS4gT3RoZXIgYXNzdW1wdGlvbnMgbGlrZSBsaW5lYXJpdHksIG1lYW5pbmcgdGhlIHJlc3BvbnNlIHZhcmlhYmxlIGlzIGxpbmVhcmx5IHJlbGF0ZWQgdG8gdGhlIHByZWRpY3RvcnM7IGFuZCBubyBtdWx0aWNvbGxpbmVhcml0eSwgbWVhbmluZyBwcmVkaWN0b3IgdmFyaWFibGVzIGFyZSBub3QgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyIGFyZSBhbHNvIHNvbWUgY29tbW9uIGFzc3VtcHRpb25zLgoKKipiKSBBcmUgdGhlIHJlc2lkdWFscyBmcm9tIGxpbmVhciByZWdyZXNzaW9uIHVuY29ycmVsYXRlZCBpbiBnZW5lcmFsPyBQbGVhc2UgZXhwbGFpbi4gV2hhdCBpcyB0aGUgZGlzdHJpYnV0aW9uIG9mIHJlc2lkdWFscz8qKgoKWWVzLCBpbiBhIGNvcnJlY3RseSBzcGVjaWZpZWQgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwsIHRoZSByZXNpZHVhbHMgYXJlIGFzc3VtZWQgdG8gYmUgdW5jb3JyZWxhdGVkIHdpdGggZWFjaCBvdGhlciBhbmQgdGhlIGFzc3VtcHRpb24gb2YgaW5kZXBlbmRlbmNlIGhvbGRzLiBXaGVuIHdlIGFzc3VtZSB0aGUgb2JzZXJ2YXRpb25zIGFyZSBpbmRlcGVuZGVudCwgd2UgaW1wbHkgdGhhdCB0aGUgZXJyb3JzIHNob3VsZCBiZSB1bmNvcnJlbGF0ZWQgYWNyb3NzIG9ic2VydmF0aW9ucy4gVGhlIHJlc2lkdWFscyBkb24ndCBuZWNlc3NhcmlseSBiZSBub3JtYWxseSBkaXN0cmlidXRlZCwgYnV0IGlmIHRoZSBlcnJvciB0ZXJtcyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQsIHRoZW4gdGhlIHJlc2lkdWFscyB3aWxsIGFwcHJveGltYXRlIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gUmVzaWR1YWxzIHNob3VsZCBpZGVhbGx5IGhhdmUgYSBtZWFuIG9mIHplcm8gYW5kIHVuaXQgdmFyaWFuY2UuCgoqKmMpIFdoeSBkbyB3ZSBwbG90IHRoZSByZXNpZHVhbHMgYWdhaW5zdCB0aGUgZml0dGVkIHZhbHVlIHJhdGhlciB0aGFuIGFnYWluc3QgdGhlIG9ic2VydmVkIHJlc3BvbnNlIHZhbHVlPyoqCgoxLiBXZSBjYW4gc3BvdCB0aGUgcGF0dGVybiBpbiBhIHJlc2lkdWFscyB2cyBmaXR0ZWQgdmFsdWUgcGxvdCwgaXQgY2FuIGluZGljYXRlIG5vbi1saW5lYXJpdHkgb3Igbm9uLWNvbnN0YW50IHZhcmlhbmNlIGluIHRoZSBkYXRhLiBJZiByZXNpZHVhbHMgYXJlIHBsb3R0ZWQgYWdhaW5zdCBvYnNlcnZlZCB2YWx1ZXMsIGl0J3MgaGFyZGVyIHRvIGRldGVjdCBodGVzZSBpc3N1ZXMgcmVsYXRlZCB0byBtb2RlbCBmaXQuCgoyLiBGaXR0ZWQgdmFsdWVzIGFyZSB0aGUgYmVzdCBlc3RpbWF0ZXMgcHJvdmlkZWQgYnkgdGhlIG1vZGVsIGZvciB5LiBDaGVja2luZyBob3cgdGhlIHJlc2lkdWFscyBiZWhhdmUgcmVsYXRpdmUgdG8gdGhlc2UgdmFsdWVzIGhlbHBzIGFzc2VzcyB3aGV0aGVyIHRoZSBtb2RlbCdzIGxpbmVhciBmaXQgaXMgYXBwcm9wcmlhdGUuCgozLiBUaGUgcGxvdCBjYW4gYWxzbyBoZWxwIHNwb3Qgb3V0bGllcnMuIFRoZSBwb2ludHMgYXJlIGRldmlhdGUgc2lnbmlmaWNhbnRseSBmcm9tIHRoZSB0ZXN0IG9mIHRoZSByZXNpZHVhbHMgYXQgaGlnaCBvciBsb3cgZml0dGVkIHZhbHVlcyBtYXkgaGF2ZSBhIGxhcmdlIGltcGFjdCBvbiB0aGUgbW9kZWwuCgoqKmQpIFdoYXQgaXMgbXVsdGljb2xsaW5lYXJpdHk/IENvbXB1dGF0aW9uYWxseSwgd2hhdCBraW5kIG9mIHByb2JsZW1zIGNhbiBtdWx0aWNvbGxpbmVhcml0eSBjYXVzZSB3aGVuIHVzaW5nIG9yZGluYXJ5IGxlYXNlIHNxdWFyZXM/KioKCk11bHRpY29sbGluZWFyaXR5IGhhcHBlbnMgd2hlbiBwcmVkaWN0b3IgdmFyaWFibGVzIGFyZSBjb3JyZWxhdGVkIGFtb25nIHRoZW1zZWx2ZXMuIFdoZW4gdGhlIGNvcnJlbGF0aW9uIGlzIGhpZ2gsIHRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgbXVsdGljb2xsaW5lYXJpdHkuIEFsdGhvdWdoLCBtdWx0aWNvbGxpbmVhcml0eSBkb2VzIG5vdCBhbHdheXMgcHJldmVudCB1cyBmcm9tIG9idGFpbmluZyBhIGdvb2QgZml0LCBpdCBjb3VsZCBjYXVzZSBzb21lIGlzc3VlczoKCjEuIEl0IGNhbiBjYXVzZSBzb21lIG9mIHRoZSBlc3RpbWF0ZWQgY29lZmZpY2llbnRzIHRvIGJlY29tZSB1bnN0YWJsZSwgbGlrZSBoaWdoIHN0YW5kYXJkIGVycm9ycy4gVGhlIGVzdGltYXRlcyBtYXkgYmVjb21lIGhpZ2hseSBzZW5zaXRpdmUgdG8gc21hbGwgY2hhbmdlcyBpbiB0aGUgZGF0YS4gSXQgY291bGQgYWxzbyBpbmNyZWFzZSB0aGUgdmFyaWFuY2Ugb2YgdGhlIGVzdGltYXRlZCByZWdyZXNzaW9uIGNvZWZmaWNpZW50cyB3aGljaCBjYW4gbWFrZSB0aGVtIHVuc3RhYmxlIGFuZCBzZW5zaXRpdmUgdG8gbWlub3IgY2hhbmdlcyBpbiB0aGUgbW9kZWwuIAoKMi4gSXQgY2FuIGNvbXBsaWNhdGUgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSBlc3RpbWF0ZWQgY29lZmZpY2llbnRzLCBiZWNhdXNlIGEgY2hhbmdlIGluIG9uZSBwcmVkaWN0b3Igd2lsbCBhbG1vc3QgYWx3YXlzIGNvcnJlc3BvbmQgd2l0aCBhIGNoYW5nZSBpbiBhbm90aGVyLiBJdCBiZWNvbWVzIGhhcmQgdG8gZGV0ZWN0IHRoZSB0cnVlIGVmZmVjdCBvZiBwcmVkaWN0b3JzIGJlY2F1c2UgdGhlaXIgcCB2YWx1ZSBiZWNvbWUgbGVzcyByZWxpYWJsZS4KCgoKCgoKCgoKCgoKCgoKCg==