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 . 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.

  1. What is the question of interest.
  2. Identify the response and the predictor variables.
  3. Classify each of the variables as either quantitative or qualitative.
  4. Which type of regression (see CH page 18, Table 1.15) can be used to analyze the data?
  5. Give a possible form of the model and identify its parameters.

Provide your answers below this horizontal line.

  1. Can we predict a pregnant woman’s risk level based on her age, body temperature, blood glucose levels, blood pressure, and heart rate?
  2. Predictor variables (X): age, body temperature, blood glucose levels, blood pressure, and heart rate. Response variable (Y): pregnant woman’s risk level
  3. Age: Quantitative Body temperature: Quantitative Blood glucose levels: Quantitative Blood pressure: Quantitative Heart rate: Quantitative Pregnant woman’s risk level: Qualitative
  4. A logistic regression model could be used to analyze the data.
  5. 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)
  1. 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()

  1. 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 
  1. 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.

  1. 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.

  1. What assumptions are you making in forming your confidence interval and in your hypothesis test?

  2. The data should be collected using a random sampling method.

  3. Each observation in the data set should be independent of every other observation.

  4. 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.

  1. 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")

  1. 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))
  1. 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)

  1. 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.

  1. 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.

  1. 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.

  1. 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)

  1. Fit a regression model to the data sets:
  1. 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
  1. 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
  1. 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
  1. 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).

  1. 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
  1. 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.

  1. 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
  1. 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
  1. 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
  1. 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
  1. 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
  1. 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.

  1. 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
  1. 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

  1. 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

  1. 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
  1. 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

  1. 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
  1. 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.

  1. 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).

  1. 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
  1. 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.

  1. Report the R2 of the model.
summary(tomasettifit)$r.squared
[1] 0.6463325
  1. Report the adjusted R2 of the model.
summary(tomasettifit)$adj.r.squared
[1] 0.6341371
  1. Report an estimate of the variance of the errors in the model.
summary(tomasettifit)$sigma^2
[1] 2.975007
  1. 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.

  1. 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.

  1. 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)
  1. 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

  1. Does the plot suggest a linear relationship between daily and Sunday circulation?

Yes, it does suggest a linear relationship between the two variables.

  1. 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

  1. 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
  1. 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.

  1. 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==