You may discuss homework questions with other students, but whatever
you end up submitting has to be your own work. Please combine all of
your answers, the computer code and the figures into one PDF file, and
submit everything via EMail at aleksey@binghamton.edu. Due date: 11:59 PM October 10,
2025 (Friday evening).
Question 1
This question is from the textbook: Chatterjee and Hadi (CH) page 23,
Exercises 1.2. Give an example in any area of interest to you where
regression analysis can be used as a data analytic tool to answer some
questions of interest.
- What is the question of interest.
- Identify the response and the predictor variables.
- Classify each of the variables as either quantitative or
qualitative.
- Which type of regression (see CH page 18, Table 1.15) can be used to
analyze the data?
- Give a possible form of the model and identify its parameters.
Provide your answers below this horizontal line.
- Can we predict a pregnant woman’s risk level based on her age, body
temperature, blood glucose levels, blood pressure, and heart rate?
- Predictor variables (X): age, body temperature, blood glucose
levels, blood pressure, and heart rate. Response variable (Y): pregnant
woman’s risk level
- Age: Quantitative Body temperature: Quantitative Blood glucose
levels: Quantitative Blood pressure: Quantitative Heart rate:
Quantitative Pregnant woman’s risk level: Qualitative
- A logistic regression model could be used to analyze the data.
- A possible form of the model would be yhat = β0 + Age(β1) +
BodyTemp(β2) + GlucoseLevel(β3) + BloodPressure(β4) + HeartRate(β5) +
Error Parameters: β0-5 and Error
Question 2
On Groundhog Day, February 2, a famous groundhog in Punxsutawney, PA
is used to predict whether a winter will be long or not based on whether
or not he sees his shadow. Jonathan Taylor collected data on whether
Phil saw his shadow or not from here. Some of the data are saved in this
table. Although Phil is on the East Coast, Jonathan (based in the bay
area) wondered if the information says anything about whether or not he
will experience a rainy winter out here in California. For this,
Jonathan found rainfall data. The dataset is available for download at
here. Here is how this was extracted using R packages.
library(rvest)
url = "http://cdec.water.ca.gov/cgi-progs/precip1/8STATIONHIST"
webpage = readLines(url)[476:593]
ind_of_rows_with_space = which(webpage == webpage[2])
webpage = webpage[-ind_of_rows_with_space]
# remove white space in each line
webpage = lapply(as.list(webpage), function(x){trimws(x)}) %>% unlist()
library(stringr)
temp = lapply(as.list(webpage), function(x){strsplit(x, " ", fixed = TRUE)}) %>% unlist()
temp = temp[-which(temp == temp[2])]
df = matrix(temp, ncol = 14, byrow = TRUE)
col.names.df = df[1, ]
df = df[-1, ] %>% data.frame()
colnames(df) = col.names.df
df = apply(df, 2, function(x){x = as.numeric(x)}) %>% data.frame()
write.csv(df, file = "rainfall.csv", row.names = FALSE)
- Using the ggplot2 package, make a box plot of the mean monthly
rainfall (total annual rainfall divided by 12 months) rainfall in
Northern California comparing the years Phil sees his shadow versus the
years he does not. [Read Phil’s data from this link. Download and read
rainfall data from here. [Use dplyr::filter to select years of rainfall
data that Phil sees his shadow or not. Use dplyr::left_join to merge
Phil’s shadow data and rainfall data.]
Below, I am providing my answer for you. Study what each line
does
library(dplyr)
url_groundhog = 'http://people.math.binghamton.edu/qiao/data501/data/groundhog.table'
url_rainfall = 'http://people.math.binghamton.edu/qiao/data501/data/rainfall.csv'
groundhog <- read.csv(url(url_groundhog))
rainfall <- read.csv(url(url_rainfall))
names(rainfall)[1] <- "year" # change the name of the first column so that left_join below
# knows how to merge the two tables.
merged <- left_join(groundhog,rainfall)
print(head(merged))
merged$mean_rainfall = merged$Total / 12
## group_by, then summarise. This is not needed by this question. Just a showcase of how it is used.
## Note that this is similar to the groupby method in pandas
merged %>% group_by(shadow) %>% summarise(mean(mean_rainfall))
library(ggplot2)
ggplot(data = merged, aes(y=mean_rainfall, x =shadow, color=shadow)) + geom_boxplot()

- Construct a 95% confidence interval for the difference between the
mean monthly rainfall (total annual rainfall divided by 12 months) in
years Phil sees his shadow and years he does not. This is a test
comparing the means of two population. Feel free to use existing
built-in function in R for this part, or use formula provided in the
class. In any case, assume that the two groups have the same
variance.
t.test(mean_rainfall ~ shadow, data = merged, var.equal = TRUE)
Two Sample t-test
data: mean_rainfall by shadow
t = 0.54731, df = 19, p-value = 0.5905
alternative hypothesis: true difference in means between group N and group Y is not equal to 0
95 percent confidence interval:
-1.139317 1.946150
sample estimates:
mean in group N mean in group Y
4.701333 4.297917
- Interpret the procedure used to construct in part 2. What do we
really know about confidence intervals? What do confidence intervals
promise to achieve?
I used a two sample t-test to test the difference in rain fall
between the years that Phil sees his shadow and the ones that he doesn’t
see his shadow. When Phil did not see his shadow, there was 4.70 inches
of rainfall per month. When he did see his shadow, there was 4.30 inches
of rainfall per month. The confidence interval is (-1.14, 1.95).
Confidence intervals provide us with a range of values likely to
contain a population parameter that is unknown. For this problem, the
confidence intervals of 95% shows us a range of values likely to contain
the difference in mean rainfall between shadow and no-shadow years. The
95% confidence interval means that if we were to repeat this study over
and over again, 95% of the resulting intervals would contain the true
parameter value.
- At level, α = 0.05 would you reject the null hypothesis that the
average rainfall in Northern California during the month of February was
the same in years Phil sees his shadow versus years he does not?
I would fail to reject the null hypothesis at α = 0.05 because the
p-value is greater than 0.05, so it is not statistically
significant.
What assumptions are you making in forming your confidence
interval and in your hypothesis test?
The data should be collected using a random sampling
method.
Each observation in the data set should be independent of every
other observation.
The two groups have the same population variance of monthly
rainfall.
Question 3
The data set walleye in the package alr4 (remember you may have to
run install.packages(“alr4”)) of data measured on walleye fish in
Wisconsin.
- Create a box plot (use ggplot2) of length, for age in 5:8
separately. Use filter in dplyr package to filter rows from the data
frame.
library(dplyr)
library(magrittr)
library(ggplot2)
library(alr4)
head(walleye)
str(walleye)
'data.frame': 3198 obs. of 3 variables:
$ age : int 1 1 1 1 1 1 1 1 1 1 ...
$ length: num 215 193 203 201 232 ...
$ period: int 1 1 1 1 1 1 1 1 1 1 ...
walleye_sub = walleye %>% filter(age >= 5 & age <= 8)
walleye_sub$age = factor(walleye_sub$age)
ggplot(data = walleye_sub, aes(y = length , x = age)) + geom_boxplot(fill = "orange")

- Compute the sample mean and the sample standard deviation length in
the four age groups (5:8) respectively (use dplyr). Your answer should
make use of the group_by and summarise functions and take up only one
line.
walleye_sub %>% group_by(age) %>% summarise(mean_length = mean(length, na.rm = TRUE), sd_length = sd(length, na.rm = TRUE))
- Create a histogram (use ggplot2) of length within age of 5:8 putting
the plots in a 2x2 grid in one file.
ggplot(walleye_sub, aes(x = length)) + geom_histogram(binwidth=3, color="white") + facet_wrap(~ age)

- Compute a 95% confidence interval for the difference in the mean
length in years 5 and 7. What assumptions are you making?
age5 = walleye %>% filter(age == 5) %>% .$length
age7 = walleye %>% filter(age == 7) %>% .$length
t.test(age5, age7, alternative = "two.sided", conf.level = 0.95)$conf.int
[1] -44.37574 -33.28132
attr(,"conf.level")
[1] 0.95
The confidence interval is (-44.38, -33.28). We assume independent
observations, approximately normal length distributions within each age
group, and no equal-variance requirement.
- At level α = 10%, test the null hypothesis that the average length
in the group age==5 is the same as the in the group age==7. What
assumptions are you making? What can you conclude?
t.test(age5, age7)$p.value
[1] 3.896149e-34
The p-value is 3.896149e-34, which is less than 0.05. So we will
reject the null hypothesis at α = 10%. We assume that there are
independent observations in each group and between groups and
approximate normality of lengths within each age. We can conclude that
there is average length of age 5 is significantly different from average
length of age 7.
- Repeat the test in 5. using the function lm. Hint: use the subset
with age 5 and age 7 only, fit a regression model of length on age (in
which age is a factor/categorical variable). Then check the significance
of the slope.
age57 = walleye %>% filter(age == c("5", "7")) %>% .[,c("age","length")]
age57$age = factor(age57$age)
summary(lm(length ~ age - 1, data = age57))
Call:
lm(formula = length ~ age - 1, data = age57)
Residuals:
Min 1Q Median 3Q Max
-60.776 -18.275 -2.989 17.538 78.658
Coefficients:
Estimate Std. Error t value Pr(>|t|)
age5 364.762 2.203 165.6 <2e-16 ***
age7 401.020 3.255 123.2 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 28.38 on 240 degrees of freedom
Multiple R-squared: 0.9944, Adjusted R-squared: 0.9944
F-statistic: 2.13e+04 on 2 and 240 DF, p-value: < 2.2e-16
The p-value < 2e-16 for the slope of the above regression
suggesting that we reject the null hypothesis at α = 10% and conclude
that the mean length differs between ages 5 and 7.
Question 4
The following questions are based on the anscombe data in R.
- Plot the 4 data sets (x1, y1), (x2, y2), (x3, y3), (x4, y4) on a
2-by-2 grid of plots using ggplot2 and gridExtra package. The results
should look like Figure 2.3 in the textbook on page 30. Add the two
variable names to each plot as the main title on each plot. Add the
axis-labels using bquote to each plot. For example,
library(ggplot2)
library(magrittr)
library(dplyr)
head(anscombe)
p1 <- ggplot(data = anscombe) +
geom_point(aes(x = x1, y = y1)) +
xlab(bquote(x[1])) +
ylab(bquote(y[1])) +
ggtitle(bquote(x[1]~"versus"~y[1])) +
theme(plot.title = element_text(hjust = 0.5))
p1

Hint: use the gridExtra package to display multiple plots in the same
figure.
p1 <- ggplot(data = anscombe) +
geom_point(aes(x = x1, y = y1)) +
xlab(bquote(x[1])) +
ylab(bquote(y[1])) +
ggtitle(bquote(x[1]~"versus"~y[1])) +
theme(plot.title = element_text(hjust = 0.5))
p2 <- ggplot(data = anscombe) +
geom_point(aes(x = x2, y = y2)) +
xlab(bquote(x[2])) +
ylab(bquote(y[2])) +
ggtitle(bquote(x[2]~"versus"~y[2])) +
theme(plot.title = element_text(hjust = 0.5))
p3 <- ggplot(data = anscombe) +
geom_point(aes(x = x3, y = y3)) +
xlab(bquote(x[3])) +
ylab(bquote(y[3])) +
ggtitle(bquote(x[3]~"versus"~y[3])) +
theme(plot.title = element_text(hjust = 0.5))
p4 <- ggplot(data = anscombe) +
geom_point(aes(x = x4, y = y4)) +
xlab(bquote(x[4])) +
ylab(bquote(y[4])) +
ggtitle(bquote(x[4]~"versus"~y[4])) +
theme(plot.title = element_text(hjust = 0.5))
library(gridExtra)
grid.arrange(p1, p2, p3, p4, nrow = 2)

- Fit a regression model to the data sets:
- y1 ∼ x1
fit1 = lm(y1 ~ x1, data = anscombe)
summary(fit1)
Call:
lm(formula = y1 ~ x1, data = anscombe)
Residuals:
Min 1Q Median 3Q Max
-1.92127 -0.45577 -0.04136 0.70941 1.83882
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.0001 1.1247 2.667 0.02573 *
x1 0.5001 0.1179 4.241 0.00217 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.237 on 9 degrees of freedom
Multiple R-squared: 0.6665, Adjusted R-squared: 0.6295
F-statistic: 17.99 on 1 and 9 DF, p-value: 0.00217
- y2 ∼ x2
fit2 = lm(y2 ~ x2, data = anscombe)
summary(fit2)
Call:
lm(formula = y2 ~ x2, data = anscombe)
Residuals:
Min 1Q Median 3Q Max
-1.9009 -0.7609 0.1291 0.9491 1.2691
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.001 1.125 2.667 0.02576 *
x2 0.500 0.118 4.239 0.00218 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.237 on 9 degrees of freedom
Multiple R-squared: 0.6662, Adjusted R-squared: 0.6292
F-statistic: 17.97 on 1 and 9 DF, p-value: 0.002179
- y3 ∼ x3
fit3 = lm(y3 ~ x3, data = anscombe)
summary(fit3)
Call:
lm(formula = y3 ~ x3, data = anscombe)
Residuals:
Min 1Q Median 3Q Max
-1.1586 -0.6146 -0.2303 0.1540 3.2411
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.0025 1.1245 2.670 0.02562 *
x3 0.4997 0.1179 4.239 0.00218 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.236 on 9 degrees of freedom
Multiple R-squared: 0.6663, Adjusted R-squared: 0.6292
F-statistic: 17.97 on 1 and 9 DF, p-value: 0.002176
- y4 ∼ x4
fit4 = lm(y4 ~ x4, data = anscombe)
summary(fit4)
Call:
lm(formula = y4 ~ x4, data = anscombe)
Residuals:
Min 1Q Median 3Q Max
-1.751 -0.831 0.000 0.809 1.839
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.0017 1.1239 2.671 0.02559 *
x4 0.4999 0.1178 4.243 0.00216 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.236 on 9 degrees of freedom
Multiple R-squared: 0.6667, Adjusted R-squared: 0.6297
F-statistic: 18 on 1 and 9 DF, p-value: 0.002165
using the command lm. Verify that all the fitted models have the
exact same coefficients (up to numerical tolerance).
- Using the command cor, compute the sample correlation for each data
set.
attach(anscombe)
cor(x1,y1)
[1] 0.8164205
cor(x2,y2)
[1] 0.8162365
cor(x3,y3)
[1] 0.8162867
cor(x4,y4)
[1] 0.8165214
- Fit the same models in 2. but with the x and y reversed. Using the
command summary, does anything about the results stay the same when you
reverse x and y?
When you reverse x and y, t-value and p-value for the predictor, the
R^2 and adjusted R^2, the F-statistic, and the significance conclusion
stays the same. However, the coefficients differ drastically, along with
the residual standard error and standard error of the coefficients.
- x1 ∼ y1
reversefit1 = lm(x1 ~ y1, data = anscombe)
summary(reversefit1)
Call:
lm(formula = x1 ~ y1, data = anscombe)
Residuals:
Min 1Q Median 3Q Max
-2.6522 -1.5117 -0.2657 1.2341 3.8946
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.9975 2.4344 -0.410 0.69156
y1 1.3328 0.3142 4.241 0.00217 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.019 on 9 degrees of freedom
Multiple R-squared: 0.6665, Adjusted R-squared: 0.6295
F-statistic: 17.99 on 1 and 9 DF, p-value: 0.00217
- x2 ∼ y2
reversefit2 = lm(x2 ~ y2, data = anscombe)
summary(reversefit2)
Call:
lm(formula = x2 ~ y2, data = anscombe)
Residuals:
Min 1Q Median 3Q Max
-1.8516 -1.4315 -0.3440 0.8467 4.2017
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.9948 2.4354 -0.408 0.69246
y2 1.3325 0.3144 4.239 0.00218 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.02 on 9 degrees of freedom
Multiple R-squared: 0.6662, Adjusted R-squared: 0.6292
F-statistic: 17.97 on 1 and 9 DF, p-value: 0.002179
- x3 ∼ y3
reversefit3 = lm(x3 ~ y3, data = anscombe)
summary(reversefit3)
Call:
lm(formula = x3 ~ y3, data = anscombe)
Residuals:
Min 1Q Median 3Q Max
-2.9869 -1.3733 -0.0266 1.3200 3.2133
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.0003 2.4362 -0.411 0.69097
y3 1.3334 0.3145 4.239 0.00218 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.019 on 9 degrees of freedom
Multiple R-squared: 0.6663, Adjusted R-squared: 0.6292
F-statistic: 17.97 on 1 and 9 DF, p-value: 0.002176
- x4 ∼ y4
reversefit4 = lm(x4 ~ y4, data = anscombe)
summary(reversefit4)
Call:
lm(formula = x4 ~ y4, data = anscombe)
Residuals:
Min 1Q Median 3Q Max
-2.7859 -1.4122 -0.1853 1.4551 3.3329
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.0036 2.4349 -0.412 0.68985
y4 1.3337 0.3143 4.243 0.00216 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.018 on 9 degrees of freedom
Multiple R-squared: 0.6667, Adjusted R-squared: 0.6297
F-statistic: 18 on 1 and 9 DF, p-value: 0.002165
- Compute the SSE, SST and R2 value for each data set. Use the
commands mean, sum, predict and / or resid. (Use the original models,
i.e. yi ∼ xi so only 4 SSE values)
lm1 = lm(y1 ~ x1, data = anscombe)
SSE = sum((resid(lm1))^2)
SST = sum((anscombe$y1 - mean(anscombe$y1))^2)
SSR = SST - SSE
R2 = 1 - SSE / SST
c(SSE,SSR,SST,R2)
[1] 13.7626900 27.5100009 41.2726909 0.6665425
lm2 = lm(y2 ~ x2, data = anscombe)
SSE = sum((resid(lm2))^2)
SST = sum((anscombe$y2 - mean(anscombe$y2))^2)
SSR = SST - SSE
R2 = 1 - SSE / SST
c(SSE,SSR,SST,R2)
[1] 13.776291 27.500000 41.276291 0.666242
lm3 = lm(y3 ~ x3, data = anscombe)
SSE = sum((resid(lm3))^2)
SST = sum((anscombe$y3 - mean(anscombe$y3))^2)
SSR = SST - SSE
R2 = 1 - SSE / SST
c(SSE,SSR,SST,R2)
[1] 13.756192 27.470008 41.226200 0.666324
lm4 = lm(y4 ~ x4, data = anscombe)
SSE = sum((resid(lm4))^2)
SST = sum((anscombe$y4 - mean(anscombe$y4))^2)
SSR = SST - SSE
R2 = 1 - SSE / SST
c(SSE,SSR,SST,R2)
[1] 13.7424900 27.4900009 41.2324909 0.6667073
- Using the ggplot2 package, re-plot the data, adding the regression
line to each plot. (Use the original models, i.e. yi ∼ xi so only 4
plots)
p1 <- ggplot(data = anscombe) +
geom_point(aes(x = x1, y = y1)) +
xlab(bquote(x[1])) +
ylab(bquote(y[1])) +
ggtitle(bquote(x[1]~"versus"~y[1])) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_abline(intercept = coef(lm1)[["(Intercept)"]], slope = coef(lm1)[["x1"]])
p2 <- ggplot(data = anscombe) +
geom_point(aes(x = x2, y = y2)) +
xlab(bquote(x[2])) +
ylab(bquote(y[2])) +
ggtitle(bquote(x[2]~"versus"~y[2])) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_abline(intercept = coef(lm2)[["(Intercept)"]], slope = coef(lm2)[["x2"]])
p3 <- ggplot(data = anscombe) +
geom_point(aes(x = x3, y = y3)) +
xlab(bquote(x[3])) +
ylab(bquote(y[3])) +
ggtitle(bquote(x[3]~"versus"~y[3])) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_abline(intercept = coef(lm3)[["(Intercept)"]], slope = coef(lm3)[["x3"]])
p4 <- ggplot(data = anscombe) +
geom_point(aes(x = x4, y = y4)) +
xlab(bquote(x[4])) +
ylab(bquote(y[4])) +
ggtitle(bquote(x[4]~"versus"~y[4])) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_abline(intercept = coef(lm4)[["(Intercept)"]], slope = coef(lm4)[["x4"]])
library(gridExtra)
grid.arrange(p1, p2, p3, p4, nrow = 2)

Question 5
In a recent, exciting, but also controversial Science article,
Tomasetti and Vogelstein attempt to explain why cancer incidence varies
drastically across tissues (e.g. why one is much more likely to develop
lung cancer rather than pelvic bone cancer). The authors show that a
higher average lifetime risk for a cancer in a given tissue correlates
with the rate of replication of stem cells in that tissue. The main
inferential tool for their statistical analysis was a simple linear
regression, which we will replicate here.
You can download the dataset as follows:
tomasetti = read.csv("http://people.math.binghamton.edu/qiao/data501/data/Tomasetti.csv")
head(tomasetti)
The dataset contains information about 31 tumor types. The Lscd
(Lifetime stem cell divisions) column refers to the total number of stem
cell divisions during the average lifetime, while Risk refers to the
lifetime risk for cancer of that tissue type.
- Fit a simple linear regression model to the data with log(Risk) as
the response variable and log(Lscd) as the predictor variable.
tomasettifit = lm(log(Risk) ~ log(Lscd), data = tomasetti)
summary(tomasettifit)
Call:
lm(formula = log(Risk) ~ log(Lscd), data = tomasetti)
Residuals:
Min 1Q Median 3Q Max
-3.8013 -1.0721 0.1434 0.9945 2.7873
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -17.52379 1.66436 -10.53 2.02e-11 ***
log(Lscd) 0.53260 0.07316 7.28 5.12e-08 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.725 on 29 degrees of freedom
Multiple R-squared: 0.6463, Adjusted R-squared: 0.6341
F-statistic: 53 on 1 and 29 DF, p-value: 5.117e-08
- Plot the estimated regression line and the data.
tomasettiplot <- ggplot(data = tomasetti) +
geom_point(aes(x = log(Lscd), y = log(Risk))) +
xlab(bquote(log(Lscd))) +
ylab(bquote(log(Risk))) +
ggtitle(bquote(log(Lscd)~"versus"~log(Risk))) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_abline(intercept = coef(tomasettifit)[["(Intercept)"]], slope = coef(tomasettifit)[["log(Lscd)"]])
tomasettiplot

- Add upper and lower 95% prediction bands to predict the response
given a range of covariates on the plot, using predict(). That is,
produce one line for the upper limit of each interval over a sequence of
densities, and one line for the lower limits of the intervals.
newdata = data.frame(Lscd = seq(min(tomasetti$Lscd), max(tomasetti$Lscd), length.out = 200))
newdata[,2:4] = predict(tomasettifit, newdata, interval = "prediction")
colnames(newdata)[2:4] = c("fit","pred.lwr","pred.upr")
library(ggplot2)
predictplot = ggplot(data = tomasetti) +
geom_point(mapping = aes(x = log(Lscd), y = log(Risk)), size = 2) +
geom_line(data = newdata, aes(x = log(Lscd), y = pred.lwr), color = "red", linetype = "dotted", linewidth = 1) +
geom_line(data = newdata, aes(x = log(Lscd), y = pred.upr), color = "red", linetype = "dotted", linewidth = 1) +
theme_bw()
predictplot

- Interpret the above bands at a Lscd = 10^10.
predict(tomasettifit, newdata = data.frame(Lscd = 1e10), interval="predict")
fit lwr upr
1 -5.260253 -8.845771 -1.674736
- Add upper and lower 95% confidence bands for the conditional mean
response on the plot, using predict(). That is, produce one line for the
upper limit of each interval over a sequence of densities, and one line
for the lower limits of the intervals.
newdata[,5:6] = predict(tomasettifit, newdata, interval = "confidence")[,2:3]
colnames(newdata)[5:6] = c("conf.lwr", "conf.upr")
library(ggplot2)
plot = ggplot(data = tomasetti) +
geom_point(mapping = aes(x = log(Lscd), y = log(Risk)), size = 2) +
geom_line(data = newdata, aes(x = log(Lscd), y = conf.lwr), color = "blue", linetype = "dashed", linewidth = .75) +
geom_line(data = newdata, aes(x = log(Lscd), y = conf.upr), color = "blue", linetype = "dashed", linewidth = .75) +
theme_bw() +
geom_line(data = newdata, aes(x = log(Lscd), y = pred.lwr), color = "red", linetype = "dotted", linewidth = .75) +
geom_line(data = newdata, aes(x = log(Lscd), y = pred.upr), color = "red", linetype = "dotted", linewidth = .75)
plot

- Interpret the above bands at a Lscd = 10^10.
predict(tomasettifit, newdata = data.frame(Lscd = 1e10), interval="confidence")
fit lwr upr
1 -5.260253 -5.901806 -4.618701
- Test whether the slope in this regression is equal to 0 at level α =
0.05. State the null hypothesis, the alternative hypothesis, the
conclusion, and the p-value.
summary(tomasettifit)
Call:
lm(formula = log(Risk) ~ log(Lscd), data = tomasetti)
Residuals:
Min 1Q Median 3Q Max
-3.8013 -1.0721 0.1434 0.9945 2.7873
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -17.52379 1.66436 -10.53 2.02e-11 ***
log(Lscd) 0.53260 0.07316 7.28 5.12e-08 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 1.725 on 29 degrees of freedom
Multiple R-squared: 0.6463, Adjusted R-squared: 0.6341
F-statistic: 53 on 1 and 29 DF, p-value: 5.117e-08
H0: β1 = 0 H1: β1 ≠ 0
The p-value is 5.12e-08, which is less than .05, so we would reject
the null hypothesis. Therefore, there is strong evidence that the slope
is not zero.
- What are assumptions you made for part (7) above.
I assumed linearity, that observations are independent, and that
error variance is constant across values of log(Lscd).
- Give a 95% confidence interval for the slope of the regression
line.
confint(tomasettifit, level = 0.95)
2.5 % 97.5 %
(Intercept) -20.9277953 -14.1197921
log(Lscd) 0.3829708 0.6822268
- Interpret your interval in (9). What does this interval promise to
achieve?
Since the interval does not include 0, the relationship is positive
and statistically significant.The interval promises that if we repeat
the study over and over again, about 95% of those intervals would
contain the true slope β1.
- Report the R2 of the model.
summary(tomasettifit)$r.squared
[1] 0.6463325
- Report the adjusted R2 of the model.
summary(tomasettifit)$adj.r.squared
[1] 0.6341371
- Report an estimate of the variance of the errors in the model.
summary(tomasettifit)$sigma^2
[1] 2.975007
- Provide an interpretation of the R2 you calculated above, ideally to
your neighbor who does not know much about statistics.
About 65% of the differences in log(lifetime cancer risk) across
these 31 tissues can be explained by differences in log(lifetime
stem-cell divisions). The remaining 35% of the variation is likely due
to other factors and noise not in the model.
- According to a Reuters article “Plain old bad luck plays a major
role in determining who gets cancer and who does not, according to
researchers who found that two-thirds of cancer incidence of various
types can be blamed on random mutations and not heredity or risky habits
like smoking.” Is this a correct interpretation of R2?
No it’s no the correct interpretation of R2.
Question 6
This question is from our textbook CH Exercises 2.1, Page 53.
In order to investigate the feasibility of starting a Sunday edition
for a large metropolitan newspaper, information was obtained from a
sample of 34 newspapers concerning their daily and Sunday circulations
(in thousands) (Source: Gale Directory of Publications, 1994). The data
can be read from the book’s Website: http://www1.aucegypt.edu/faculty/hadi/RABE5/Data5/P054.txt.
- Read the data using read.table (separator of column is tab and the
data frame has variable names).
newspaper = read.table("https://www1.aucegypt.edu/faculty/hadi/RABE5/Data5/P054.txt", sep = "\t", header = TRUE)
head(newspaper)
- Construct a scatter plot of Sunday circulation versus daily
circulation.
library(ggplot2)
newsplot <- ggplot(data = newspaper) +
geom_point(aes(x = Daily, y = Sunday)) +
xlab("Daily Circulation") +
ylab("Sunday Circulation") +
ggtitle(bquote("Daily Circulation versus Sunday Circulation")) +
theme(plot.title = element_text(hjust = 0.5))
newsplot

- Does the plot suggest a linear relationship between daily and Sunday
circulation?
Yes, it does suggest a linear relationship between the two
variables.
- Fit a regression line predicting Sunday circulation from daily
circulation (Use lm()).
newsfit = lm(Sunday ~ Daily, data = newspaper)
new_newsplot <- ggplot(data = newspaper) +
geom_point(aes(x = Daily, y = Sunday)) +
xlab("Daily Circulation") +
ylab("Sunday Circulation") +
ggtitle(bquote("Daily Circulation versus Sunday Circulation")) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_abline(intercept = coef(newsfit)[["(Intercept)"]], slope = coef(newsfit)[["Daily"]])
new_newsplot

- Is there a significant relationship between Sunday circulation and
daily circulation? Justify your answer by a statistical test (Use F test
in anova()).
There is a significant relationship between Sunday circulation and
daily circulation because the F critical value is 4.15 and the F
computed value is 358.53, and F computed value is greater than F
critical value. Also, the p-value is less than .05 which shows a
significant relationship.
anova(newsfit)
Analysis of Variance Table
Response: Sunday
Df Sum Sq Mean Sq F value Pr(>F)
Daily 1 4292653 4292653 358.53 < 2.2e-16 ***
Residuals 32 383136 11973
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
qf(0.95, 1, 32)
[1] 4.149097
- Indicate what hypothesis your are testing and your conclusion for
the test in part (5).
H0: There is no relationship between Sunday circulation and Daily
circulation. (β1 = 0) H1: There is a relationship between Sunday
circulation and Daily circulation. (β1 ≠ 0)
We reject the null hypothesis and accept the alternative.
- Using the anova table produced in part (5), compute the proportion
of the variability in Sunday circulation is accounted for by daily
circulation.
SSR <- anova(newsfit)["Daily", "Sum Sq"]
SSE <- anova(newsfit)["Residuals", "Sum Sq"]
R2 <- SSR / (SSR + SSE)
R2
[1] 0.9180597
LS0tCnRpdGxlOiAiQXNzaWdubWVudCAxIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KCllvdSBtYXkgZGlzY3VzcyBob21ld29yayBxdWVzdGlvbnMgd2l0aCBvdGhlciBzdHVkZW50cywgYnV0IHdoYXRldmVyIHlvdSBlbmQgdXAgc3VibWl0dGluZwpoYXMgdG8gYmUgeW91ciBvd24gd29yay4KUGxlYXNlIGNvbWJpbmUgYWxsIG9mIHlvdXIgYW5zd2VycywgdGhlIGNvbXB1dGVyIGNvZGUgYW5kIHRoZSBmaWd1cmVzIGludG8gb25lIFBERiBmaWxlLCBhbmQKc3VibWl0IGV2ZXJ5dGhpbmcgdmlhIEVNYWlsIGF0IGFsZWtzZXlAYmluZ2hhbXRvbi5lZHUuCkR1ZSBkYXRlOiAxMTo1OSBQTSBPY3RvYmVyIDEwLCAyMDI1IChGcmlkYXkgZXZlbmluZykuCgpRdWVzdGlvbiAxCgpUaGlzIHF1ZXN0aW9uIGlzIGZyb20gdGhlIHRleHRib29rOiBDaGF0dGVyamVlIGFuZCBIYWRpIChDSCkgcGFnZSAyMywgRXhlcmNpc2VzIDEuMi4KR2l2ZSBhbiBleGFtcGxlIGluIGFueSBhcmVhIG9mIGludGVyZXN0IHRvIHlvdSB3aGVyZSByZWdyZXNzaW9uIGFuYWx5c2lzIGNhbiBiZSB1c2VkIGFzIGEgZGF0YSBhbmFseXRpYyB0b29sCnRvIGFuc3dlciBzb21lIHF1ZXN0aW9ucyBvZiBpbnRlcmVzdC4KCiAgMS4gV2hhdCBpcyB0aGUgcXVlc3Rpb24gb2YgaW50ZXJlc3QuCiAgMi4gSWRlbnRpZnkgdGhlIHJlc3BvbnNlIGFuZCB0aGUgcHJlZGljdG9yIHZhcmlhYmxlcy4KICAzLiBDbGFzc2lmeSBlYWNoIG9mIHRoZSB2YXJpYWJsZXMgYXMgZWl0aGVyIHF1YW50aXRhdGl2ZSBvciBxdWFsaXRhdGl2ZS4KICA0LiBXaGljaCB0eXBlIG9mIHJlZ3Jlc3Npb24gKHNlZSBDSCBwYWdlIDE4LCBUYWJsZSAxLjE1KSBjYW4gYmUgdXNlZCB0byBhbmFseXplIHRoZSBkYXRhPwogIDUuIEdpdmUgYSBwb3NzaWJsZSBmb3JtIG9mIHRoZSBtb2RlbCBhbmQgaWRlbnRpZnkgaXRzIHBhcmFtZXRlcnMuCiAgClByb3ZpZGUgeW91ciBhbnN3ZXJzIGJlbG93IHRoaXMgaG9yaXpvbnRhbCBsaW5lLgoKICAxLiBDYW4gd2UgcHJlZGljdCBhIHByZWduYW50IHdvbWFuJ3MgcmlzayBsZXZlbCBiYXNlZCBvbiBoZXIgYWdlLCBib2R5IHRlbXBlcmF0dXJlLCBibG9vZCBnbHVjb3NlIGxldmVscywgYmxvb2QgcHJlc3N1cmUsIGFuZCBoZWFydCByYXRlPwogIDIuIFByZWRpY3RvciB2YXJpYWJsZXMgKFgpOiBhZ2UsIGJvZHkgdGVtcGVyYXR1cmUsIGJsb29kIGdsdWNvc2UgbGV2ZWxzLCBibG9vZCBwcmVzc3VyZSwgYW5kIGhlYXJ0IHJhdGUuCiAgICAgUmVzcG9uc2UgdmFyaWFibGUgKFkpOiBwcmVnbmFudCB3b21hbidzIHJpc2sgbGV2ZWwKICAzLiBBZ2U6IFF1YW50aXRhdGl2ZQogICAgIEJvZHkgdGVtcGVyYXR1cmU6IFF1YW50aXRhdGl2ZQogICAgIEJsb29kIGdsdWNvc2UgbGV2ZWxzOiBRdWFudGl0YXRpdmUKICAgICBCbG9vZCBwcmVzc3VyZTogUXVhbnRpdGF0aXZlCiAgICAgSGVhcnQgcmF0ZTogUXVhbnRpdGF0aXZlCiAgICAgUHJlZ25hbnQgd29tYW4ncyByaXNrIGxldmVsOiBRdWFsaXRhdGl2ZQogIDQuIEEgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCBjb3VsZCBiZSB1c2VkIHRvIGFuYWx5emUgdGhlIGRhdGEuCiAgNS4gQSBwb3NzaWJsZSBmb3JtIG9mIHRoZSBtb2RlbCB3b3VsZCBiZSB5aGF0ID0gzrIwICsgQWdlKM6yMSkgKyBCb2R5VGVtcCjOsjIpICsgR2x1Y29zZUxldmVsKM6yMykgKyBCbG9vZFByZXNzdXJlKM6yNCkgKyBIZWFydFJhdGUozrI1KSArIEVycm9yCiAgICAgUGFyYW1ldGVyczogzrIwLTUgYW5kIEVycm9yCiAgICAgCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KClF1ZXN0aW9uIDIKCk9uIEdyb3VuZGhvZyBEYXksIEZlYnJ1YXJ5IDIsIGEgZmFtb3VzIGdyb3VuZGhvZyBpbiBQdW54c3V0YXduZXksIFBBIGlzIHVzZWQgdG8gcHJlZGljdCB3aGV0aGVyIGEKd2ludGVyIHdpbGwgYmUgbG9uZyBvciBub3QgYmFzZWQgb24gd2hldGhlciBvciBub3QgaGUgc2VlcyBoaXMgc2hhZG93LiBKb25hdGhhbiBUYXlsb3IgY29sbGVjdGVkIGRhdGEgb24Kd2hldGhlciBQaGlsIHNhdyBoaXMgc2hhZG93IG9yIG5vdCBmcm9tIGhlcmUuIFNvbWUgb2YgdGhlIGRhdGEgYXJlIHNhdmVkIGluIHRoaXMgdGFibGUuCkFsdGhvdWdoIFBoaWwgaXMgb24gdGhlIEVhc3QgQ29hc3QsIEpvbmF0aGFuIChiYXNlZCBpbiB0aGUgYmF5IGFyZWEpIHdvbmRlcmVkIGlmIHRoZSBpbmZvcm1hdGlvbiBzYXlzCmFueXRoaW5nIGFib3V0IHdoZXRoZXIgb3Igbm90IGhlIHdpbGwgZXhwZXJpZW5jZSBhIHJhaW55IHdpbnRlciBvdXQgaGVyZSBpbiBDYWxpZm9ybmlhLiBGb3IgdGhpcywgSm9uYXRoYW4KZm91bmQgcmFpbmZhbGwgZGF0YS4KVGhlIGRhdGFzZXQgaXMgYXZhaWxhYmxlIGZvciBkb3dubG9hZCBhdCBoZXJlLiBIZXJlIGlzIGhvdyB0aGlzIHdhcyBleHRyYWN0ZWQgdXNpbmcgUiBwYWNrYWdlcy4KCmBgYHtyfQpsaWJyYXJ5KHJ2ZXN0KQp1cmwgPSAiaHR0cDovL2NkZWMud2F0ZXIuY2EuZ292L2NnaS1wcm9ncy9wcmVjaXAxLzhTVEFUSU9OSElTVCIKd2VicGFnZSA9IHJlYWRMaW5lcyh1cmwpWzQ3Njo1OTNdCmluZF9vZl9yb3dzX3dpdGhfc3BhY2UgPSB3aGljaCh3ZWJwYWdlID09IHdlYnBhZ2VbMl0pCndlYnBhZ2UgPSB3ZWJwYWdlWy1pbmRfb2Zfcm93c193aXRoX3NwYWNlXQojIHJlbW92ZSB3aGl0ZSBzcGFjZSBpbiBlYWNoIGxpbmUKd2VicGFnZSA9IGxhcHBseShhcy5saXN0KHdlYnBhZ2UpLCBmdW5jdGlvbih4KXt0cmltd3MoeCl9KSAlPiUgdW5saXN0KCkKbGlicmFyeShzdHJpbmdyKQp0ZW1wID0gbGFwcGx5KGFzLmxpc3Qod2VicGFnZSksIGZ1bmN0aW9uKHgpe3N0cnNwbGl0KHgsICIgIiwgZml4ZWQgPSBUUlVFKX0pICU+JSB1bmxpc3QoKQp0ZW1wID0gdGVtcFstd2hpY2godGVtcCA9PSB0ZW1wWzJdKV0KZGYgPSBtYXRyaXgodGVtcCwgbmNvbCA9IDE0LCBieXJvdyA9IFRSVUUpCmBgYApgYGB7cn0KY29sLm5hbWVzLmRmID0gZGZbMSwgXQpkZiA9IGRmWy0xLCBdICU+JSBkYXRhLmZyYW1lKCkKY29sbmFtZXMoZGYpID0gY29sLm5hbWVzLmRmCmRmID0gYXBwbHkoZGYsIDIsIGZ1bmN0aW9uKHgpe3ggPSBhcy5udW1lcmljKHgpfSkgJT4lIGRhdGEuZnJhbWUoKQpgYGAKYGBge3J9CndyaXRlLmNzdihkZiwgZmlsZSA9ICJyYWluZmFsbC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgoxLiBVc2luZyB0aGUgZ2dwbG90MiBwYWNrYWdlLCBtYWtlIGEgYm94IHBsb3Qgb2YgdGhlIG1lYW4gbW9udGhseSByYWluZmFsbCAodG90YWwgYW5udWFsIHJhaW5mYWxsIGRpdmlkZWQKYnkgMTIgbW9udGhzKSByYWluZmFsbCBpbiBOb3J0aGVybiBDYWxpZm9ybmlhIGNvbXBhcmluZyB0aGUgeWVhcnMgUGhpbCBzZWVzIGhpcyBzaGFkb3cgdmVyc3VzIHRoZQp5ZWFycyBoZSBkb2VzIG5vdC4gW1JlYWQgUGhpbOKAmXMgZGF0YSBmcm9tIHRoaXMgbGluay4gRG93bmxvYWQgYW5kIHJlYWQgcmFpbmZhbGwgZGF0YSBmcm9tIGhlcmUuIFtVc2UKZHBseXI6OmZpbHRlciB0byBzZWxlY3QgeWVhcnMgb2YgcmFpbmZhbGwgZGF0YSB0aGF0IFBoaWwgc2VlcyBoaXMgc2hhZG93IG9yIG5vdC4gVXNlIGRwbHlyOjpsZWZ0X2pvaW4KdG8gbWVyZ2UgUGhpbOKAmXMgc2hhZG93IGRhdGEgYW5kIHJhaW5mYWxsIGRhdGEuXQoKQmVsb3csIEkgYW0gcHJvdmlkaW5nIG15IGFuc3dlciBmb3IgeW91LiBTdHVkeSB3aGF0IGVhY2ggbGluZSBkb2VzCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQoKdXJsX2dyb3VuZGhvZyA9ICdodHRwOi8vcGVvcGxlLm1hdGguYmluZ2hhbXRvbi5lZHUvcWlhby9kYXRhNTAxL2RhdGEvZ3JvdW5kaG9nLnRhYmxlJwp1cmxfcmFpbmZhbGwgPSAnaHR0cDovL3Blb3BsZS5tYXRoLmJpbmdoYW10b24uZWR1L3FpYW8vZGF0YTUwMS9kYXRhL3JhaW5mYWxsLmNzdicKZ3JvdW5kaG9nIDwtIHJlYWQuY3N2KHVybCh1cmxfZ3JvdW5kaG9nKSkKcmFpbmZhbGwgPC0gcmVhZC5jc3YodXJsKHVybF9yYWluZmFsbCkpCm5hbWVzKHJhaW5mYWxsKVsxXSA8LSAieWVhciIgIyBjaGFuZ2UgdGhlIG5hbWUgb2YgdGhlIGZpcnN0IGNvbHVtbiBzbyB0aGF0IGxlZnRfam9pbiBiZWxvdwojIGtub3dzIGhvdyB0byBtZXJnZSB0aGUgdHdvIHRhYmxlcy4KbWVyZ2VkIDwtIGxlZnRfam9pbihncm91bmRob2cscmFpbmZhbGwpCmBgYAoKYGBge3J9CnByaW50KGhlYWQobWVyZ2VkKSkKYGBgCgpgYGB7cn0KbWVyZ2VkJG1lYW5fcmFpbmZhbGwgPSBtZXJnZWQkVG90YWwgLyAxMgojIyBncm91cF9ieSwgdGhlbiBzdW1tYXJpc2UuIFRoaXMgaXMgbm90IG5lZWRlZCBieSB0aGlzIHF1ZXN0aW9uLiBKdXN0IGEgc2hvd2Nhc2Ugb2YgaG93IGl0IGlzIHVzZWQuCiMjIE5vdGUgdGhhdCB0aGlzIGlzIHNpbWlsYXIgdG8gdGhlIGdyb3VwYnkgbWV0aG9kIGluIHBhbmRhcwptZXJnZWQgJT4lIGdyb3VwX2J5KHNoYWRvdykgJT4lIHN1bW1hcmlzZShtZWFuKG1lYW5fcmFpbmZhbGwpKQpgYGAKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKZ2dwbG90KGRhdGEgPSBtZXJnZWQsIGFlcyh5PW1lYW5fcmFpbmZhbGwsIHggPXNoYWRvdywgY29sb3I9c2hhZG93KSkgKyBnZW9tX2JveHBsb3QoKQpgYGAKMi4gQ29uc3RydWN0IGEgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1lYW4gbW9udGhseSByYWluZmFsbCAodG90YWwgYW5udWFsCnJhaW5mYWxsIGRpdmlkZWQgYnkgMTIgbW9udGhzKSBpbiB5ZWFycyBQaGlsIHNlZXMgaGlzIHNoYWRvdyBhbmQgeWVhcnMgaGUgZG9lcyBub3QuIFRoaXMgaXMgYSB0ZXN0CmNvbXBhcmluZyB0aGUgbWVhbnMgb2YgdHdvIHBvcHVsYXRpb24uIEZlZWwgZnJlZSB0byB1c2UgZXhpc3RpbmcgYnVpbHQtaW4gZnVuY3Rpb24gaW4gUiBmb3IgdGhpcyBwYXJ0LCBvcgp1c2UgZm9ybXVsYSBwcm92aWRlZCBpbiB0aGUgY2xhc3MuIEluIGFueSBjYXNlLCBhc3N1bWUgdGhhdCB0aGUgdHdvIGdyb3VwcyBoYXZlIHRoZSBzYW1lIHZhcmlhbmNlLgoKYGBge3J9CnQudGVzdChtZWFuX3JhaW5mYWxsIH4gc2hhZG93LCBkYXRhID0gbWVyZ2VkLCB2YXIuZXF1YWwgPSBUUlVFKQpgYGAKCjMuIEludGVycHJldCB0aGUgcHJvY2VkdXJlIHVzZWQgdG8gY29uc3RydWN0IGluIHBhcnQgMi4gV2hhdCBkbyB3ZSByZWFsbHkga25vdyBhYm91dCBjb25maWRlbmNlIGludGVydmFscz8KV2hhdCBkbyBjb25maWRlbmNlIGludGVydmFscyBwcm9taXNlIHRvIGFjaGlldmU/CgpJIHVzZWQgYSB0d28gc2FtcGxlIHQtdGVzdCB0byB0ZXN0IHRoZSBkaWZmZXJlbmNlIGluIHJhaW4gZmFsbCBiZXR3ZWVuIHRoZSB5ZWFycyB0aGF0IFBoaWwgc2VlcyBoaXMgc2hhZG93CmFuZCB0aGUgb25lcyB0aGF0IGhlIGRvZXNuJ3Qgc2VlIGhpcyBzaGFkb3cuIFdoZW4gUGhpbCBkaWQgbm90IHNlZSBoaXMgc2hhZG93LCB0aGVyZSB3YXMgNC43MCBpbmNoZXMgb2YgCnJhaW5mYWxsIHBlciBtb250aC4gV2hlbiBoZSBkaWQgc2VlIGhpcyBzaGFkb3csIHRoZXJlIHdhcyA0LjMwIGluY2hlcyBvZiByYWluZmFsbCBwZXIgbW9udGguIFRoZSBjb25maWRlbmNlCmludGVydmFsIGlzICgtMS4xNCwgMS45NSkuCgpDb25maWRlbmNlIGludGVydmFscyBwcm92aWRlIHVzIHdpdGggYSByYW5nZSBvZiB2YWx1ZXMgbGlrZWx5IHRvIGNvbnRhaW4gYSBwb3B1bGF0aW9uIHBhcmFtZXRlciB0aGF0IGlzIHVua25vd24uCkZvciB0aGlzIHByb2JsZW0sIHRoZSBjb25maWRlbmNlIGludGVydmFscyBvZiA5NSUgc2hvd3MgdXMgYSByYW5nZSBvZiB2YWx1ZXMgbGlrZWx5IHRvIGNvbnRhaW4gdGhlIGRpZmZlcmVuY2UgaW4gbWVhbgpyYWluZmFsbCBiZXR3ZWVuIHNoYWRvdyBhbmQgbm8tc2hhZG93IHllYXJzLiBUaGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgbWVhbnMgdGhhdCBpZiB3ZSB3ZXJlIHRvIHJlcGVhdCB0aGlzCnN0dWR5IG92ZXIgYW5kIG92ZXIgYWdhaW4sIDk1JSBvZiB0aGUgcmVzdWx0aW5nIGludGVydmFscyB3b3VsZCBjb250YWluIHRoZSB0cnVlIHBhcmFtZXRlciB2YWx1ZS4gCgo0LiBBdCBsZXZlbCwgzrEgPSAwLjA1IHdvdWxkIHlvdSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSBhdmVyYWdlIHJhaW5mYWxsIGluIE5vcnRoZXJuIENhbGlmb3JuaWEKZHVyaW5nIHRoZSBtb250aCBvZiBGZWJydWFyeSB3YXMgdGhlIHNhbWUgaW4geWVhcnMgUGhpbCBzZWVzIGhpcyBzaGFkb3cgdmVyc3VzIHllYXJzIGhlIGRvZXMgbm90PwoKSSB3b3VsZCBmYWlsIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIGF0IM6xID0gMC4wNSBiZWNhdXNlIHRoZSBwLXZhbHVlIGlzIGdyZWF0ZXIgdGhhbiAwLjA1LCBzbwppdCBpcyBub3Qgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4KCjUuIFdoYXQgYXNzdW1wdGlvbnMgYXJlIHlvdSBtYWtpbmcgaW4gZm9ybWluZyB5b3VyIGNvbmZpZGVuY2UgaW50ZXJ2YWwgYW5kIGluIHlvdXIgaHlwb3RoZXNpcyB0ZXN0PwoKICAxLiBUaGUgZGF0YSBzaG91bGQgYmUgY29sbGVjdGVkIHVzaW5nIGEgcmFuZG9tIHNhbXBsaW5nIG1ldGhvZC4KICAyLiBFYWNoIG9ic2VydmF0aW9uIGluIHRoZSBkYXRhIHNldCBzaG91bGQgYmUgaW5kZXBlbmRlbnQgb2YgZXZlcnkgb3RoZXIgb2JzZXJ2YXRpb24uCiAgMy4gVGhlIHR3byBncm91cHMgaGF2ZSB0aGUgc2FtZSBwb3B1bGF0aW9uIHZhcmlhbmNlIG9mIG1vbnRobHkgcmFpbmZhbGwuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpRdWVzdGlvbiAzCgpUaGUgZGF0YSBzZXQgd2FsbGV5ZSBpbiB0aGUgcGFja2FnZSBhbHI0IChyZW1lbWJlciB5b3UgbWF5IGhhdmUgdG8gcnVuIGluc3RhbGwucGFja2FnZXMoImFscjQiKSkgb2YKZGF0YSBtZWFzdXJlZCBvbiB3YWxsZXllIGZpc2ggaW4gV2lzY29uc2luLgoKMS4gQ3JlYXRlIGEgYm94IHBsb3QgKHVzZSBnZ3Bsb3QyKSBvZiBsZW5ndGgsIGZvciBhZ2UgaW4gNTo4IHNlcGFyYXRlbHkuIFVzZSBmaWx0ZXIgaW4gZHBseXIgcGFja2FnZQp0byBmaWx0ZXIgcm93cyBmcm9tIHRoZSBkYXRhIGZyYW1lLgoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShhbHI0KQpgYGAKCmBgYHtyfQpoZWFkKHdhbGxleWUpCmBgYAoKYGBge3J9CnN0cih3YWxsZXllKQpgYGAKYGBge3J9CndhbGxleWVfc3ViID0gd2FsbGV5ZSAlPiUgZmlsdGVyKGFnZSA+PSA1ICYgYWdlIDw9IDgpCndhbGxleWVfc3ViJGFnZSA9IGZhY3Rvcih3YWxsZXllX3N1YiRhZ2UpCmdncGxvdChkYXRhID0gd2FsbGV5ZV9zdWIsIGFlcyh5ID0gbGVuZ3RoICwgeCA9IGFnZSkpICsgZ2VvbV9ib3hwbG90KGZpbGwgPSAib3JhbmdlIikKYGBgCgoyLiBDb21wdXRlIHRoZSBzYW1wbGUgbWVhbiBhbmQgdGhlIHNhbXBsZSBzdGFuZGFyZCBkZXZpYXRpb24gbGVuZ3RoIGluIHRoZSBmb3VyIGFnZSBncm91cHMgKDU6OCkKcmVzcGVjdGl2ZWx5ICh1c2UgZHBseXIpLiBZb3VyIGFuc3dlciBzaG91bGQgbWFrZSB1c2Ugb2YgdGhlIGdyb3VwX2J5IGFuZCBzdW1tYXJpc2UgZnVuY3Rpb25zIGFuZAp0YWtlIHVwIG9ubHkgb25lIGxpbmUuCgpgYGB7cn0Kd2FsbGV5ZV9zdWIgJT4lIGdyb3VwX2J5KGFnZSkgJT4lIHN1bW1hcmlzZShtZWFuX2xlbmd0aCA9IG1lYW4obGVuZ3RoLCBuYS5ybSA9IFRSVUUpLCBzZF9sZW5ndGggPSBzZChsZW5ndGgsIG5hLnJtID0gVFJVRSkpCmBgYAoKMy4gQ3JlYXRlIGEgaGlzdG9ncmFtICh1c2UgZ2dwbG90Mikgb2YgbGVuZ3RoIHdpdGhpbiBhZ2Ugb2YgNTo4IHB1dHRpbmcgdGhlIHBsb3RzIGluIGEgMngyIGdyaWQgaW4gb25lCmZpbGUuCgpgYGB7cn0KZ2dwbG90KHdhbGxleWVfc3ViLCBhZXMoeCA9IGxlbmd0aCkpICsgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGg9MywgY29sb3I9IndoaXRlIikgKyBmYWNldF93cmFwKH4gYWdlKQpgYGAKCjQuIENvbXB1dGUgYSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgdGhlIGRpZmZlcmVuY2UgaW4gdGhlIG1lYW4gbGVuZ3RoIGluIHllYXJzIDUgYW5kIDcuIFdoYXQKYXNzdW1wdGlvbnMgYXJlIHlvdSBtYWtpbmc/CgpgYGB7cn0KYWdlNSA9IHdhbGxleWUgJT4lIGZpbHRlcihhZ2UgPT0gNSkgJT4lIC4kbGVuZ3RoCmFnZTcgPSB3YWxsZXllICU+JSBmaWx0ZXIoYWdlID09IDcpICU+JSAuJGxlbmd0aAp0LnRlc3QoYWdlNSwgYWdlNywgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIiwgY29uZi5sZXZlbCA9IDAuOTUpJGNvbmYuaW50CmBgYAoKVGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgKC00NC4zOCwgLTMzLjI4KS4gV2UgYXNzdW1lIGluZGVwZW5kZW50IG9ic2VydmF0aW9ucywgYXBwcm94aW1hdGVseQpub3JtYWwgbGVuZ3RoIGRpc3RyaWJ1dGlvbnMgd2l0aGluIGVhY2ggYWdlIGdyb3VwLCBhbmQgbm8gZXF1YWwtdmFyaWFuY2UgcmVxdWlyZW1lbnQuCgo1LiBBdCBsZXZlbCDOsSA9IDEwJSwgdGVzdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIGF2ZXJhZ2UgbGVuZ3RoIGluIHRoZSBncm91cCBhZ2U9PTUgaXMgdGhlIHNhbWUgYXMKdGhlIGluIHRoZSBncm91cCBhZ2U9PTcuIFdoYXQgYXNzdW1wdGlvbnMgYXJlIHlvdSBtYWtpbmc/IFdoYXQgY2FuIHlvdSBjb25jbHVkZT8KCmBgYHtyfQp0LnRlc3QoYWdlNSwgYWdlNykkcC52YWx1ZQpgYGAKClRoZSBwLXZhbHVlIGlzIDMuODk2MTQ5ZS0zNCwgd2hpY2ggaXMgbGVzcyB0aGFuIDAuMDUuIFNvIHdlIHdpbGwgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgYXQgzrEgPSAxMCUuIFdlCmFzc3VtZSB0aGF0IHRoZXJlIGFyZSBpbmRlcGVuZGVudCBvYnNlcnZhdGlvbnMgaW4gZWFjaCBncm91cCBhbmQgYmV0d2VlbiBncm91cHMgYW5kIGFwcHJveGltYXRlIG5vcm1hbGl0eQpvZiBsZW5ndGhzIHdpdGhpbiBlYWNoIGFnZS4gV2UgY2FuIGNvbmNsdWRlIHRoYXQgdGhlcmUgaXMgYXZlcmFnZSBsZW5ndGggb2YgYWdlIDUgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQKZnJvbSBhdmVyYWdlIGxlbmd0aCBvZiBhZ2UgNy4KCjYuIFJlcGVhdCB0aGUgdGVzdCBpbiA1LiB1c2luZyB0aGUgZnVuY3Rpb24gbG0uIEhpbnQ6IHVzZSB0aGUgc3Vic2V0IHdpdGggYWdlIDUgYW5kIGFnZSA3IG9ubHksIGZpdCBhCnJlZ3Jlc3Npb24gbW9kZWwgb2YgbGVuZ3RoIG9uIGFnZSAoaW4gd2hpY2ggYWdlIGlzIGEgZmFjdG9yL2NhdGVnb3JpY2FsIHZhcmlhYmxlKS4gVGhlbiBjaGVjayB0aGUKc2lnbmlmaWNhbmNlIG9mIHRoZSBzbG9wZS4KCmBgYHtyfQphZ2U1NyA9IHdhbGxleWUgJT4lIGZpbHRlcihhZ2UgPT0gYygiNSIsICI3IikpICU+JSAuWyxjKCJhZ2UiLCJsZW5ndGgiKV0KYWdlNTckYWdlID0gZmFjdG9yKGFnZTU3JGFnZSkKc3VtbWFyeShsbShsZW5ndGggfiBhZ2UgLSAxLCBkYXRhID0gYWdlNTcpKQpgYGAKClRoZSBwLXZhbHVlIDwgMmUtMTYgZm9yIHRoZSBzbG9wZSBvZiB0aGUgYWJvdmUgcmVncmVzc2lvbiBzdWdnZXN0aW5nIHRoYXQgd2UgcmVqZWN0IHRoZSBudWxsCmh5cG90aGVzaXMgYXQgzrEgPSAxMCUgYW5kIGNvbmNsdWRlIHRoYXQgdGhlIG1lYW4gbGVuZ3RoIGRpZmZlcnMgYmV0d2VlbiBhZ2VzIDUgYW5kIDcuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpRdWVzdGlvbiA0CgpUaGUgZm9sbG93aW5nIHF1ZXN0aW9ucyBhcmUgYmFzZWQgb24gdGhlIGFuc2NvbWJlIGRhdGEgaW4gUi4KCjEuIFBsb3QgdGhlIDQgZGF0YSBzZXRzICh4MSwgeTEpLCAoeDIsIHkyKSwgKHgzLCB5MyksICh4NCwgeTQpIG9uIGEgMi1ieS0yIGdyaWQgb2YgcGxvdHMgdXNpbmcgZ2dwbG90MiBhbmQKZ3JpZEV4dHJhIHBhY2thZ2UuIFRoZSByZXN1bHRzIHNob3VsZCBsb29rIGxpa2UgRmlndXJlIDIuMyBpbiB0aGUgdGV4dGJvb2sgb24gcGFnZSAzMC4KQWRkIHRoZSB0d28gdmFyaWFibGUgbmFtZXMgdG8gZWFjaCBwbG90IGFzIHRoZSBtYWluIHRpdGxlIG9uIGVhY2ggcGxvdC4KQWRkIHRoZSBheGlzLWxhYmVscyB1c2luZyBicXVvdGUgdG8gZWFjaCBwbG90LiBGb3IgZXhhbXBsZSwKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoZHBseXIpCmhlYWQoYW5zY29tYmUpCmBgYApgYGB7cn0KcDEgPC0gZ2dwbG90KGRhdGEgPSBhbnNjb21iZSkgKwpnZW9tX3BvaW50KGFlcyh4ID0geDEsIHkgPSB5MSkpICsKeGxhYihicXVvdGUoeFsxXSkpICsKeWxhYihicXVvdGUoeVsxXSkpICsKZ2d0aXRsZShicXVvdGUoeFsxXX4idmVyc3VzIn55WzFdKSkgKwp0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCnAxCmBgYApIaW50OiB1c2UgdGhlIGdyaWRFeHRyYSBwYWNrYWdlIHRvIGRpc3BsYXkgbXVsdGlwbGUgcGxvdHMgaW4gdGhlIHNhbWUgZmlndXJlLgoKYGBge3J9CnAxIDwtIGdncGxvdChkYXRhID0gYW5zY29tYmUpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHgxLCB5ID0geTEpKSArCiAgeGxhYihicXVvdGUoeFsxXSkpICsKICB5bGFiKGJxdW90ZSh5WzFdKSkgKwogIGdndGl0bGUoYnF1b3RlKHhbMV1+InZlcnN1cyJ+eVsxXSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCnAyIDwtIGdncGxvdChkYXRhID0gYW5zY29tYmUpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHgyLCB5ID0geTIpKSArCiAgeGxhYihicXVvdGUoeFsyXSkpICsKICB5bGFiKGJxdW90ZSh5WzJdKSkgKwogIGdndGl0bGUoYnF1b3RlKHhbMl1+InZlcnN1cyJ+eVsyXSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCnAzIDwtIGdncGxvdChkYXRhID0gYW5zY29tYmUpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHgzLCB5ID0geTMpKSArCiAgeGxhYihicXVvdGUoeFszXSkpICsKICB5bGFiKGJxdW90ZSh5WzNdKSkgKwogIGdndGl0bGUoYnF1b3RlKHhbM11+InZlcnN1cyJ+eVszXSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCnA0IDwtIGdncGxvdChkYXRhID0gYW5zY29tYmUpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHg0LCB5ID0geTQpKSArCiAgeGxhYihicXVvdGUoeFs0XSkpICsKICB5bGFiKGJxdW90ZSh5WzRdKSkgKwogIGdndGl0bGUoYnF1b3RlKHhbNF1+InZlcnN1cyJ+eVs0XSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCgpsaWJyYXJ5KGdyaWRFeHRyYSkKCmdyaWQuYXJyYW5nZShwMSwgcDIsIHAzLCBwNCwgbnJvdyA9IDIpCmBgYAoKMi4gRml0IGEgcmVncmVzc2lvbiBtb2RlbCB0byB0aGUgZGF0YSBzZXRzOgphLiB5MSDiiLwgeDEKCmBgYHtyfQpmaXQxID0gbG0oeTEgfiB4MSwgZGF0YSA9IGFuc2NvbWJlKQpzdW1tYXJ5KGZpdDEpCmBgYAoKYi4geTIg4oi8IHgyCgpgYGB7cn0KZml0MiA9IGxtKHkyIH4geDIsIGRhdGEgPSBhbnNjb21iZSkKc3VtbWFyeShmaXQyKQpgYGAKCmMuIHkzIOKIvCB4MwoKYGBge3J9CmZpdDMgPSBsbSh5MyB+IHgzLCBkYXRhID0gYW5zY29tYmUpCnN1bW1hcnkoZml0MykKYGBgCgpkLiB5NCDiiLwgeDQKCmBgYHtyfQpmaXQ0ID0gbG0oeTQgfiB4NCwgZGF0YSA9IGFuc2NvbWJlKQpzdW1tYXJ5KGZpdDQpCmBgYAoKdXNpbmcgdGhlIGNvbW1hbmQgbG0uIFZlcmlmeSB0aGF0IGFsbCB0aGUgZml0dGVkIG1vZGVscyBoYXZlIHRoZSBleGFjdCBzYW1lIGNvZWZmaWNpZW50cyAodXAgdG8gbnVtZXJpY2FsCnRvbGVyYW5jZSkuCgozLiBVc2luZyB0aGUgY29tbWFuZCBjb3IsIGNvbXB1dGUgdGhlIHNhbXBsZSBjb3JyZWxhdGlvbiBmb3IgZWFjaCBkYXRhIHNldC4KCmBgYHtyfQphdHRhY2goYW5zY29tYmUpCmNvcih4MSx5MSkKY29yKHgyLHkyKQpjb3IoeDMseTMpCmNvcih4NCx5NCkKYGBgCgo0LiBGaXQgdGhlIHNhbWUgbW9kZWxzIGluIDIuIGJ1dCB3aXRoIHRoZSB4IGFuZCB5IHJldmVyc2VkLiBVc2luZyB0aGUgY29tbWFuZCBzdW1tYXJ5LCBkb2VzIGFueXRoaW5nCmFib3V0IHRoZSByZXN1bHRzIHN0YXkgdGhlIHNhbWUgd2hlbiB5b3UgcmV2ZXJzZSB4IGFuZCB5PwoKV2hlbiB5b3UgcmV2ZXJzZSB4IGFuZCB5LCB0LXZhbHVlIGFuZCBwLXZhbHVlIGZvciB0aGUgcHJlZGljdG9yLCB0aGUgUl4yIGFuZCBhZGp1c3RlZCBSXjIsIHRoZSBGLXN0YXRpc3RpYywgYW5kIHRoZSAKc2lnbmlmaWNhbmNlIGNvbmNsdXNpb24gc3RheXMgdGhlIHNhbWUuIEhvd2V2ZXIsIHRoZSBjb2VmZmljaWVudHMgZGlmZmVyIGRyYXN0aWNhbGx5LCBhbG9uZyB3aXRoIHRoZSByZXNpZHVhbCBzdGFuZGFyZAplcnJvciBhbmQgc3RhbmRhcmQgZXJyb3Igb2YgdGhlIGNvZWZmaWNpZW50cy4KCmEuIHgxIOKIvCB5MQpgYGB7cn0KcmV2ZXJzZWZpdDEgPSBsbSh4MSB+IHkxLCBkYXRhID0gYW5zY29tYmUpCnN1bW1hcnkocmV2ZXJzZWZpdDEpCmBgYAoKYi4geDIg4oi8IHkyCmBgYHtyfQpyZXZlcnNlZml0MiA9IGxtKHgyIH4geTIsIGRhdGEgPSBhbnNjb21iZSkKc3VtbWFyeShyZXZlcnNlZml0MikKYGBgCgpjLiB4MyDiiLwgeTMKYGBge3J9CnJldmVyc2VmaXQzID0gbG0oeDMgfiB5MywgZGF0YSA9IGFuc2NvbWJlKQpzdW1tYXJ5KHJldmVyc2VmaXQzKQpgYGAKCmQuIHg0IOKIvCB5NApgYGB7cn0KcmV2ZXJzZWZpdDQgPSBsbSh4NCB+IHk0LCBkYXRhID0gYW5zY29tYmUpCnN1bW1hcnkocmV2ZXJzZWZpdDQpCmBgYAoKCjUuIENvbXB1dGUgdGhlIFNTRSwgU1NUIGFuZCBSMiB2YWx1ZSBmb3IgZWFjaCBkYXRhIHNldC4gVXNlIHRoZSBjb21tYW5kcyBtZWFuLCBzdW0sIHByZWRpY3QgYW5kIC8Kb3IgcmVzaWQuIChVc2UgdGhlIG9yaWdpbmFsIG1vZGVscywgaS5lLiB5aSDiiLwgeGkgc28gb25seSA0IFNTRSB2YWx1ZXMpCgpgYGB7cn0KbG0xID0gbG0oeTEgfiB4MSwgZGF0YSA9IGFuc2NvbWJlKQpTU0UgPSBzdW0oKHJlc2lkKGxtMSkpXjIpClNTVCA9IHN1bSgoYW5zY29tYmUkeTEgLSBtZWFuKGFuc2NvbWJlJHkxKSleMikKU1NSID0gU1NUIC0gU1NFClIyID0gMSAtIFNTRSAvIFNTVApjKFNTRSxTU1IsU1NULFIyKQpgYGAKCmBgYHtyfQpsbTIgPSBsbSh5MiB+IHgyLCBkYXRhID0gYW5zY29tYmUpClNTRSA9IHN1bSgocmVzaWQobG0yKSleMikKU1NUID0gc3VtKChhbnNjb21iZSR5MiAtIG1lYW4oYW5zY29tYmUkeTIpKV4yKQpTU1IgPSBTU1QgLSBTU0UKUjIgPSAxIC0gU1NFIC8gU1NUCmMoU1NFLFNTUixTU1QsUjIpCmBgYAoKYGBge3J9CmxtMyA9IGxtKHkzIH4geDMsIGRhdGEgPSBhbnNjb21iZSkKU1NFID0gc3VtKChyZXNpZChsbTMpKV4yKQpTU1QgPSBzdW0oKGFuc2NvbWJlJHkzIC0gbWVhbihhbnNjb21iZSR5MykpXjIpClNTUiA9IFNTVCAtIFNTRQpSMiA9IDEgLSBTU0UgLyBTU1QKYyhTU0UsU1NSLFNTVCxSMikKYGBgCgpgYGB7cn0KbG00ID0gbG0oeTQgfiB4NCwgZGF0YSA9IGFuc2NvbWJlKQpTU0UgPSBzdW0oKHJlc2lkKGxtNCkpXjIpClNTVCA9IHN1bSgoYW5zY29tYmUkeTQgLSBtZWFuKGFuc2NvbWJlJHk0KSleMikKU1NSID0gU1NUIC0gU1NFClIyID0gMSAtIFNTRSAvIFNTVApjKFNTRSxTU1IsU1NULFIyKQpgYGAKNi4gVXNpbmcgdGhlIGdncGxvdDIgcGFja2FnZSwgcmUtcGxvdCB0aGUgZGF0YSwgYWRkaW5nIHRoZSByZWdyZXNzaW9uIGxpbmUgdG8gZWFjaCBwbG90LiAoVXNlIHRoZSBvcmlnaW5hbAptb2RlbHMsIGkuZS4geWkg4oi8IHhpIHNvIG9ubHkgNCBwbG90cykKCmBgYHtyfQpwMSA8LSBnZ3Bsb3QoZGF0YSA9IGFuc2NvbWJlKSArIAogIGdlb21fcG9pbnQoYWVzKHggPSB4MSwgeSA9IHkxKSkgKwogIHhsYWIoYnF1b3RlKHhbMV0pKSArCiAgeWxhYihicXVvdGUoeVsxXSkpICsKICBnZ3RpdGxlKGJxdW90ZSh4WzFdfiJ2ZXJzdXMifnlbMV0pKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsKICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSBjb2VmKGxtMSlbWyIoSW50ZXJjZXB0KSJdXSwgc2xvcGUgPSBjb2VmKGxtMSlbWyJ4MSJdXSkKCnAyIDwtIGdncGxvdChkYXRhID0gYW5zY29tYmUpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IHgyLCB5ID0geTIpKSArCiAgeGxhYihicXVvdGUoeFsyXSkpICsKICB5bGFiKGJxdW90ZSh5WzJdKSkgKwogIGdndGl0bGUoYnF1b3RlKHhbMl1+InZlcnN1cyJ+eVsyXSkpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IGNvZWYobG0yKVtbIihJbnRlcmNlcHQpIl1dLCBzbG9wZSA9IGNvZWYobG0yKVtbIngyIl1dKQoKcDMgPC0gZ2dwbG90KGRhdGEgPSBhbnNjb21iZSkgKyAKICBnZW9tX3BvaW50KGFlcyh4ID0geDMsIHkgPSB5MykpICsKICB4bGFiKGJxdW90ZSh4WzNdKSkgKwogIHlsYWIoYnF1b3RlKHlbM10pKSArCiAgZ2d0aXRsZShicXVvdGUoeFszXX4idmVyc3VzIn55WzNdKSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gY29lZihsbTMpW1siKEludGVyY2VwdCkiXV0sIHNsb3BlID0gY29lZihsbTMpW1sieDMiXV0pCgpwNCA8LSBnZ3Bsb3QoZGF0YSA9IGFuc2NvbWJlKSArIAogIGdlb21fcG9pbnQoYWVzKHggPSB4NCwgeSA9IHk0KSkgKwogIHhsYWIoYnF1b3RlKHhbNF0pKSArCiAgeWxhYihicXVvdGUoeVs0XSkpICsKICBnZ3RpdGxlKGJxdW90ZSh4WzRdfiJ2ZXJzdXMifnlbNF0pKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsKICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSBjb2VmKGxtNClbWyIoSW50ZXJjZXB0KSJdXSwgc2xvcGUgPSBjb2VmKGxtNClbWyJ4NCJdXSkKCgpsaWJyYXJ5KGdyaWRFeHRyYSkKCmdyaWQuYXJyYW5nZShwMSwgcDIsIHAzLCBwNCwgbnJvdyA9IDIpCmBgYAoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKUXVlc3Rpb24gNQoKSW4gYSByZWNlbnQsIGV4Y2l0aW5nLCBidXQgYWxzbyBjb250cm92ZXJzaWFsIFNjaWVuY2UgYXJ0aWNsZSwgVG9tYXNldHRpIGFuZCBWb2dlbHN0ZWluIGF0dGVtcHQgdG8gZXhwbGFpbiB3aHkKY2FuY2VyIGluY2lkZW5jZSB2YXJpZXMgZHJhc3RpY2FsbHkgYWNyb3NzIHRpc3N1ZXMgKGUuZy4gd2h5IG9uZSBpcyBtdWNoIG1vcmUgbGlrZWx5IHRvIGRldmVsb3AgbHVuZyBjYW5jZXIKcmF0aGVyIHRoYW4gcGVsdmljIGJvbmUgY2FuY2VyKS4gVGhlIGF1dGhvcnMgc2hvdyB0aGF0IGEgaGlnaGVyIGF2ZXJhZ2UgbGlmZXRpbWUgcmlzayBmb3IgYSBjYW5jZXIgaW4gYSBnaXZlbgp0aXNzdWUgY29ycmVsYXRlcyB3aXRoIHRoZSByYXRlIG9mIHJlcGxpY2F0aW9uIG9mIHN0ZW0gY2VsbHMgaW4gdGhhdCB0aXNzdWUuIFRoZSBtYWluIGluZmVyZW50aWFsIHRvb2wgZm9yIHRoZWlyCnN0YXRpc3RpY2FsIGFuYWx5c2lzIHdhcyBhIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbiwgd2hpY2ggd2Ugd2lsbCByZXBsaWNhdGUgaGVyZS4KCllvdSBjYW4gZG93bmxvYWQgdGhlIGRhdGFzZXQgYXMgZm9sbG93czoKCmBgYHtyfQp0b21hc2V0dGkgPSByZWFkLmNzdigiaHR0cDovL3Blb3BsZS5tYXRoLmJpbmdoYW10b24uZWR1L3FpYW8vZGF0YTUwMS9kYXRhL1RvbWFzZXR0aS5jc3YiKQpoZWFkKHRvbWFzZXR0aSkKYGBgCgpUaGUgZGF0YXNldCBjb250YWlucyBpbmZvcm1hdGlvbiBhYm91dCAzMSB0dW1vciB0eXBlcy4gVGhlIExzY2QgKExpZmV0aW1lIHN0ZW0gY2VsbCBkaXZpc2lvbnMpIGNvbHVtbgpyZWZlcnMgdG8gdGhlIHRvdGFsIG51bWJlciBvZiBzdGVtIGNlbGwgZGl2aXNpb25zIGR1cmluZyB0aGUgYXZlcmFnZSBsaWZldGltZSwgd2hpbGUgUmlzayByZWZlcnMgdG8gdGhlIGxpZmV0aW1lCnJpc2sgZm9yIGNhbmNlciBvZiB0aGF0IHRpc3N1ZSB0eXBlLgoKMS4gRml0IGEgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHRvIHRoZSBkYXRhIHdpdGggbG9nKFJpc2spIGFzIHRoZSByZXNwb25zZSB2YXJpYWJsZSBhbmQgbG9nKExzY2QpCmFzIHRoZSBwcmVkaWN0b3IgdmFyaWFibGUuCgpgYGB7cn0KdG9tYXNldHRpZml0ID0gbG0obG9nKFJpc2spIH4gbG9nKExzY2QpLCBkYXRhID0gdG9tYXNldHRpKQpzdW1tYXJ5KHRvbWFzZXR0aWZpdCkKYGBgCgoyLiBQbG90IHRoZSBlc3RpbWF0ZWQgcmVncmVzc2lvbiBsaW5lIGFuZCB0aGUgZGF0YS4KCmBgYHtyfQp0b21hc2V0dGlwbG90IDwtIGdncGxvdChkYXRhID0gdG9tYXNldHRpKSArIAogIGdlb21fcG9pbnQoYWVzKHggPSBsb2coTHNjZCksIHkgPSBsb2coUmlzaykpKSArCiAgeGxhYihicXVvdGUobG9nKExzY2QpKSkgKwogIHlsYWIoYnF1b3RlKGxvZyhSaXNrKSkpICsKICBnZ3RpdGxlKGJxdW90ZShsb2coTHNjZCl+InZlcnN1cyJ+bG9nKFJpc2spKSkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gY29lZih0b21hc2V0dGlmaXQpW1siKEludGVyY2VwdCkiXV0sIHNsb3BlID0gY29lZih0b21hc2V0dGlmaXQpW1sibG9nKExzY2QpIl1dKQoKdG9tYXNldHRpcGxvdApgYGAKCjMuIEFkZCB1cHBlciBhbmQgbG93ZXIgOTUlIHByZWRpY3Rpb24gYmFuZHMgdG8gcHJlZGljdCB0aGUgcmVzcG9uc2UgZ2l2ZW4gYSByYW5nZSBvZiBjb3ZhcmlhdGVzIG9uIHRoZQpwbG90LCB1c2luZyBwcmVkaWN0KCkuIFRoYXQgaXMsIHByb2R1Y2Ugb25lIGxpbmUgZm9yIHRoZSB1cHBlciBsaW1pdCBvZiBlYWNoIGludGVydmFsIG92ZXIgYSBzZXF1ZW5jZSBvZgpkZW5zaXRpZXMsIGFuZCBvbmUgbGluZSBmb3IgdGhlIGxvd2VyIGxpbWl0cyBvZiB0aGUgaW50ZXJ2YWxzLgoKYGBge3J9Cm5ld2RhdGEgPSBkYXRhLmZyYW1lKExzY2QgPSBzZXEobWluKHRvbWFzZXR0aSRMc2NkKSwgbWF4KHRvbWFzZXR0aSRMc2NkKSwgbGVuZ3RoLm91dCA9IDIwMCkpCm5ld2RhdGFbLDI6NF0gPSBwcmVkaWN0KHRvbWFzZXR0aWZpdCwgbmV3ZGF0YSwgaW50ZXJ2YWwgPSAicHJlZGljdGlvbiIpCmNvbG5hbWVzKG5ld2RhdGEpWzI6NF0gPSBjKCJmaXQiLCJwcmVkLmx3ciIsInByZWQudXByIikKCmxpYnJhcnkoZ2dwbG90MikKCnByZWRpY3RwbG90ID0gZ2dwbG90KGRhdGEgPSB0b21hc2V0dGkpICsgCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBsb2coTHNjZCksIHkgPSBsb2coUmlzaykpLCBzaXplID0gMikgKwogIGdlb21fbGluZShkYXRhID0gbmV3ZGF0YSwgYWVzKHggPSBsb2coTHNjZCksIHkgPSBwcmVkLmx3ciksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRvdHRlZCIsIGxpbmV3aWR0aCA9IDEpICsKICBnZW9tX2xpbmUoZGF0YSA9IG5ld2RhdGEsIGFlcyh4ID0gbG9nKExzY2QpLCB5ID0gcHJlZC51cHIpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkb3R0ZWQiLCBsaW5ld2lkdGggPSAxKSArCiAgdGhlbWVfYncoKQoKcHJlZGljdHBsb3QKCmBgYAoKNC4gSW50ZXJwcmV0IHRoZSBhYm92ZSBiYW5kcyBhdCBhIExzY2QgPSAxMF4xMC4KCmBgYHtyfQpwcmVkaWN0KHRvbWFzZXR0aWZpdCwgbmV3ZGF0YSA9IGRhdGEuZnJhbWUoTHNjZCA9IDFlMTApLCBpbnRlcnZhbD0icHJlZGljdCIpCmBgYAoKNS4gQWRkIHVwcGVyIGFuZCBsb3dlciA5NSUgY29uZmlkZW5jZSBiYW5kcyBmb3IgdGhlIGNvbmRpdGlvbmFsIG1lYW4gcmVzcG9uc2Ugb24gdGhlIHBsb3QsIHVzaW5nCnByZWRpY3QoKS4gVGhhdCBpcywgcHJvZHVjZSBvbmUgbGluZSBmb3IgdGhlIHVwcGVyIGxpbWl0IG9mIGVhY2ggaW50ZXJ2YWwgb3ZlciBhIHNlcXVlbmNlIG9mIGRlbnNpdGllcywKYW5kIG9uZSBsaW5lIGZvciB0aGUgbG93ZXIgbGltaXRzIG9mIHRoZSBpbnRlcnZhbHMuCgpgYGB7cn0KbmV3ZGF0YVssNTo2XSA9IHByZWRpY3QodG9tYXNldHRpZml0LCBuZXdkYXRhLCBpbnRlcnZhbCA9ICJjb25maWRlbmNlIilbLDI6M10KY29sbmFtZXMobmV3ZGF0YSlbNTo2XSA9IGMoImNvbmYubHdyIiwgImNvbmYudXByIikKCmxpYnJhcnkoZ2dwbG90MikKCnBsb3QgPSBnZ3Bsb3QoZGF0YSA9IHRvbWFzZXR0aSkgKyAKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGxvZyhMc2NkKSwgeSA9IGxvZyhSaXNrKSksIHNpemUgPSAyKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBuZXdkYXRhLCBhZXMoeCA9IGxvZyhMc2NkKSwgeSA9IGNvbmYubHdyKSwgY29sb3IgPSAiYmx1ZSIsIGxpbmV0eXBlID0gImRhc2hlZCIsIGxpbmV3aWR0aCA9IC43NSkgKwogIGdlb21fbGluZShkYXRhID0gbmV3ZGF0YSwgYWVzKHggPSBsb2coTHNjZCksIHkgPSBjb25mLnVwciksIGNvbG9yID0gImJsdWUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAuNzUpICsKICB0aGVtZV9idygpICsKICBnZW9tX2xpbmUoZGF0YSA9IG5ld2RhdGEsIGFlcyh4ID0gbG9nKExzY2QpLCB5ID0gcHJlZC5sd3IpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkb3R0ZWQiLCBsaW5ld2lkdGggPSAuNzUpICsKICBnZW9tX2xpbmUoZGF0YSA9IG5ld2RhdGEsIGFlcyh4ID0gbG9nKExzY2QpLCB5ID0gcHJlZC51cHIpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkb3R0ZWQiLCBsaW5ld2lkdGggPSAuNzUpCgpwbG90CmBgYAoKNi4gSW50ZXJwcmV0IHRoZSBhYm92ZSBiYW5kcyBhdCBhIExzY2QgPSAxMF4xMC4KCmBgYHtyfQpwcmVkaWN0KHRvbWFzZXR0aWZpdCwgbmV3ZGF0YSA9IGRhdGEuZnJhbWUoTHNjZCA9IDFlMTApLCBpbnRlcnZhbD0iY29uZmlkZW5jZSIpCmBgYAoKNy4gVGVzdCB3aGV0aGVyIHRoZSBzbG9wZSBpbiB0aGlzIHJlZ3Jlc3Npb24gaXMgZXF1YWwgdG8gMCBhdCBsZXZlbCDOsSA9IDAuMDUuIFN0YXRlIHRoZSBudWxsIGh5cG90aGVzaXMsIHRoZQphbHRlcm5hdGl2ZSBoeXBvdGhlc2lzLCB0aGUgY29uY2x1c2lvbiwgYW5kIHRoZSBwLXZhbHVlLgoKYGBge3J9CnN1bW1hcnkodG9tYXNldHRpZml0KQpgYGAKSDA6IM6yMSA9IDAKSDE6IM6yMSDiiaAgMAoKVGhlIHAtdmFsdWUgaXMgNS4xMmUtMDgsIHdoaWNoIGlzIGxlc3MgdGhhbiAuMDUsIHNvIHdlIHdvdWxkIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUaGVyZWZvcmUsIHRoZXJlIGlzIHN0cm9uZyAKZXZpZGVuY2UgdGhhdCB0aGUgc2xvcGUgaXMgbm90IHplcm8uCgo4LiBXaGF0IGFyZSBhc3N1bXB0aW9ucyB5b3UgbWFkZSBmb3IgcGFydCAoNykgYWJvdmUuCgpJIGFzc3VtZWQgbGluZWFyaXR5LCB0aGF0IG9ic2VydmF0aW9ucyBhcmUgaW5kZXBlbmRlbnQsIGFuZCB0aGF0IGVycm9yIHZhcmlhbmNlIGlzIGNvbnN0YW50IGFjcm9zcyB2YWx1ZXMgb2YgbG9nKExzY2QpLgoKOS4gR2l2ZSBhIDk1JSBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgc2xvcGUgb2YgdGhlIHJlZ3Jlc3Npb24gbGluZS4KCmBgYHtyfQpjb25maW50KHRvbWFzZXR0aWZpdCwgbGV2ZWwgPSAwLjk1KQpgYGAKCjEwLiBJbnRlcnByZXQgeW91ciBpbnRlcnZhbCBpbiAoOSkuIFdoYXQgZG9lcyB0aGlzIGludGVydmFsIHByb21pc2UgdG8gYWNoaWV2ZT8KClNpbmNlIHRoZSBpbnRlcnZhbCBkb2VzIG5vdCBpbmNsdWRlIDAsIHRoZSByZWxhdGlvbnNoaXAgaXMgcG9zaXRpdmUgYW5kIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuVGhlIGludGVydmFsIHByb21pc2VzIHRoYXQKaWYgd2UgcmVwZWF0IHRoZSBzdHVkeSBvdmVyIGFuZCBvdmVyIGFnYWluLCBhYm91dCA5NSUgb2YgdGhvc2UgaW50ZXJ2YWxzIHdvdWxkIGNvbnRhaW4gdGhlIHRydWUgc2xvcGUgzrIxLgoKMTEuIFJlcG9ydCB0aGUgUjIgb2YgdGhlIG1vZGVsLgoKYGBge3J9CnN1bW1hcnkodG9tYXNldHRpZml0KSRyLnNxdWFyZWQKYGBgCgoxMi4gUmVwb3J0IHRoZSBhZGp1c3RlZCBSMiBvZiB0aGUgbW9kZWwuCgpgYGB7cn0Kc3VtbWFyeSh0b21hc2V0dGlmaXQpJGFkai5yLnNxdWFyZWQKYGBgCgoxMy4gUmVwb3J0IGFuIGVzdGltYXRlIG9mIHRoZSB2YXJpYW5jZSBvZiB0aGUgZXJyb3JzIGluIHRoZSBtb2RlbC4KCmBgYHtyfQpzdW1tYXJ5KHRvbWFzZXR0aWZpdCkkc2lnbWFeMgpgYGAKCjE0LiBQcm92aWRlIGFuIGludGVycHJldGF0aW9uIG9mIHRoZSBSMiB5b3UgY2FsY3VsYXRlZCBhYm92ZSwgaWRlYWxseSB0byB5b3VyIG5laWdoYm9yIHdobyBkb2VzIG5vdCBrbm93Cm11Y2ggYWJvdXQgc3RhdGlzdGljcy4KCkFib3V0IDY1JSBvZiB0aGUgZGlmZmVyZW5jZXMgaW4gbG9nKGxpZmV0aW1lIGNhbmNlciByaXNrKSBhY3Jvc3MgdGhlc2UgMzEgdGlzc3VlcyBjYW4gYmUgZXhwbGFpbmVkIGJ5IGRpZmZlcmVuY2VzCmluIGxvZyhsaWZldGltZSBzdGVtLWNlbGwgZGl2aXNpb25zKS4gVGhlIHJlbWFpbmluZyAzNSUgb2YgdGhlIHZhcmlhdGlvbiBpcyBsaWtlbHkgZHVlIHRvIG90aGVyIGZhY3RvcnMgYW5kIG5vaXNlIG5vdCAKaW4gdGhlIG1vZGVsLgoKMTUuIEFjY29yZGluZyB0byBhIFJldXRlcnMgYXJ0aWNsZSDigJxQbGFpbiBvbGQgYmFkIGx1Y2sgcGxheXMgYSBtYWpvciByb2xlIGluIGRldGVybWluaW5nIHdobyBnZXRzIGNhbmNlcgphbmQgd2hvIGRvZXMgbm90LCBhY2NvcmRpbmcgdG8gcmVzZWFyY2hlcnMgd2hvIGZvdW5kIHRoYXQgdHdvLXRoaXJkcyBvZiBjYW5jZXIgaW5jaWRlbmNlIG9mIHZhcmlvdXMKdHlwZXMgY2FuIGJlIGJsYW1lZCBvbiByYW5kb20gbXV0YXRpb25zIGFuZCBub3QgaGVyZWRpdHkgb3Igcmlza3kgaGFiaXRzIGxpa2Ugc21va2luZy7igJ0gSXMgdGhpcyBhCmNvcnJlY3QgaW50ZXJwcmV0YXRpb24gb2YgUjI/CgpObyBpdCdzIG5vIHRoZSBjb3JyZWN0IGludGVycHJldGF0aW9uIG9mIFIyLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKUXVlc3Rpb24gNgoKVGhpcyBxdWVzdGlvbiBpcyBmcm9tIG91ciB0ZXh0Ym9vayBDSCBFeGVyY2lzZXMgMi4xLCBQYWdlIDUzLgoKSW4gb3JkZXIgdG8gaW52ZXN0aWdhdGUgdGhlIGZlYXNpYmlsaXR5IG9mIHN0YXJ0aW5nIGEgU3VuZGF5IGVkaXRpb24gZm9yIGEgbGFyZ2UgbWV0cm9wb2xpdGFuIG5ld3NwYXBlciwKaW5mb3JtYXRpb24gd2FzIG9idGFpbmVkIGZyb20gYSBzYW1wbGUgb2YgMzQgbmV3c3BhcGVycyBjb25jZXJuaW5nIHRoZWlyIGRhaWx5IGFuZCBTdW5kYXkgY2lyY3VsYXRpb25zIChpbgp0aG91c2FuZHMpIChTb3VyY2U6IEdhbGUgRGlyZWN0b3J5IG9mIFB1YmxpY2F0aW9ucywgMTk5NCkuIFRoZSBkYXRhIGNhbiBiZSByZWFkIGZyb20gdGhlIGJvb2vigJlzIFdlYnNpdGU6Cmh0dHA6Ly93d3cxLmF1Y2VneXB0LmVkdS9mYWN1bHR5L2hhZGkvUkFCRTUvRGF0YTUvUDA1NC50eHQuCgoxLiBSZWFkIHRoZSBkYXRhIHVzaW5nIHJlYWQudGFibGUgKHNlcGFyYXRvciBvZiBjb2x1bW4gaXMgdGFiIGFuZCB0aGUgZGF0YSBmcmFtZSBoYXMgdmFyaWFibGUgbmFtZXMpLgoKYGBge3J9Cm5ld3NwYXBlciA9IHJlYWQudGFibGUoImh0dHBzOi8vd3d3MS5hdWNlZ3lwdC5lZHUvZmFjdWx0eS9oYWRpL1JBQkU1L0RhdGE1L1AwNTQudHh0Iiwgc2VwID0gIlx0IiwgaGVhZGVyID0gVFJVRSkKaGVhZChuZXdzcGFwZXIpCmBgYAoKMi4gQ29uc3RydWN0IGEgc2NhdHRlciBwbG90IG9mIFN1bmRheSBjaXJjdWxhdGlvbiB2ZXJzdXMgZGFpbHkgY2lyY3VsYXRpb24uCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKbmV3c3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBuZXdzcGFwZXIpICsgCiAgZ2VvbV9wb2ludChhZXMoeCA9IERhaWx5LCB5ID0gU3VuZGF5KSkgKwogIHhsYWIoIkRhaWx5IENpcmN1bGF0aW9uIikgKwogIHlsYWIoIlN1bmRheSBDaXJjdWxhdGlvbiIpICsKICBnZ3RpdGxlKGJxdW90ZSgiRGFpbHkgQ2lyY3VsYXRpb24gdmVyc3VzIFN1bmRheSBDaXJjdWxhdGlvbiIpKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgpuZXdzcGxvdApgYGAKCjMuIERvZXMgdGhlIHBsb3Qgc3VnZ2VzdCBhIGxpbmVhciByZWxhdGlvbnNoaXAgYmV0d2VlbiBkYWlseSBhbmQgU3VuZGF5IGNpcmN1bGF0aW9uPwoKWWVzLCBpdCBkb2VzIHN1Z2dlc3QgYSBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHR3byB2YXJpYWJsZXMuCgo0LiBGaXQgYSByZWdyZXNzaW9uIGxpbmUgcHJlZGljdGluZyBTdW5kYXkgY2lyY3VsYXRpb24gZnJvbSBkYWlseSBjaXJjdWxhdGlvbiAoVXNlIGxtKCkpLgoKYGBge3J9Cm5ld3NmaXQgPSBsbShTdW5kYXkgfiBEYWlseSwgZGF0YSA9IG5ld3NwYXBlcikKCm5ld19uZXdzcGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IG5ld3NwYXBlcikgKyAKICBnZW9tX3BvaW50KGFlcyh4ID0gRGFpbHksIHkgPSBTdW5kYXkpKSArCiAgeGxhYigiRGFpbHkgQ2lyY3VsYXRpb24iKSArCiAgeWxhYigiU3VuZGF5IENpcmN1bGF0aW9uIikgKwogIGdndGl0bGUoYnF1b3RlKCJEYWlseSBDaXJjdWxhdGlvbiB2ZXJzdXMgU3VuZGF5IENpcmN1bGF0aW9uIikpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IGNvZWYobmV3c2ZpdClbWyIoSW50ZXJjZXB0KSJdXSwgc2xvcGUgPSBjb2VmKG5ld3NmaXQpW1siRGFpbHkiXV0pCgpuZXdfbmV3c3Bsb3QKCmBgYAoKNS4gSXMgdGhlcmUgYSBzaWduaWZpY2FudCByZWxhdGlvbnNoaXAgYmV0d2VlbiBTdW5kYXkgY2lyY3VsYXRpb24gYW5kIGRhaWx5IGNpcmN1bGF0aW9uPyBKdXN0aWZ5IHlvdXIgYW5zd2VyCmJ5IGEgc3RhdGlzdGljYWwgdGVzdCAoVXNlIEYgdGVzdCBpbiBhbm92YSgpKS4KClRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwIGJldHdlZW4gU3VuZGF5IGNpcmN1bGF0aW9uIGFuZCBkYWlseSBjaXJjdWxhdGlvbiBiZWNhdXNlIHRoZSBGIGNyaXRpY2FsIHZhbHVlIGlzIDQuMTUgYW5kIHRoZQpGIGNvbXB1dGVkIHZhbHVlIGlzIDM1OC41MywgYW5kIEYgY29tcHV0ZWQgdmFsdWUgaXMgZ3JlYXRlciB0aGFuIEYgY3JpdGljYWwgdmFsdWUuIEFsc28sIHRoZSBwLXZhbHVlIGlzIGxlc3MgdGhhbiAuMDUgd2hpY2ggc2hvd3MKYSBzaWduaWZpY2FudCByZWxhdGlvbnNoaXAuCgpgYGB7cn0KYW5vdmEobmV3c2ZpdCkKYGBgCmBgYHtyfQpxZigwLjk1LCAxLCAzMikKYGBgCgo2LiBJbmRpY2F0ZSB3aGF0IGh5cG90aGVzaXMgeW91ciBhcmUgdGVzdGluZyBhbmQgeW91ciBjb25jbHVzaW9uIGZvciB0aGUgdGVzdCBpbiBwYXJ0ICg1KS4KCkgwOiBUaGVyZSBpcyBubyByZWxhdGlvbnNoaXAgYmV0d2VlbiBTdW5kYXkgY2lyY3VsYXRpb24gYW5kIERhaWx5IGNpcmN1bGF0aW9uLiAozrIxID0gMCkKSDE6IFRoZXJlIGlzIGEgcmVsYXRpb25zaGlwIGJldHdlZW4gU3VuZGF5IGNpcmN1bGF0aW9uIGFuZCBEYWlseSBjaXJjdWxhdGlvbi4gKM6yMSDiiaAgMCkKCldlIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIGFuZCBhY2NlcHQgdGhlIGFsdGVybmF0aXZlLgoKNy4gVXNpbmcgdGhlIGFub3ZhIHRhYmxlIHByb2R1Y2VkIGluIHBhcnQgKDUpLCBjb21wdXRlIHRoZSBwcm9wb3J0aW9uIG9mIHRoZSB2YXJpYWJpbGl0eSBpbiBTdW5kYXkKY2lyY3VsYXRpb24gaXMgYWNjb3VudGVkIGZvciBieSBkYWlseSBjaXJjdWxhdGlvbi4KCmBgYHtyfQpTU1IgPC0gYW5vdmEobmV3c2ZpdClbIkRhaWx5IiwgIlN1bSBTcSJdClNTRSA8LSBhbm92YShuZXdzZml0KVsiUmVzaWR1YWxzIiwgIlN1bSBTcSJdClIyICA8LSBTU1IgLyAoU1NSICsgU1NFKQpSMgpgYGAKCg==