HW 1 Write Up
library(tidyverse)

R4DS

3.3.1: 1-4

1. What’s gone wrong with this code? Why are the points not blue?

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy), color = "blue")

color isn’t being used as an aesthetic. It should be outside aes.

2. Which variables in mpg are categorical? Which variables are continuous? (Hint: type ?mpg to read the documentation for the dataset). How can you see this information when you run mpg?

head(mpg)

Categorical: Manufacturer, Model, Trans, Drv, fl, Class Continuous: hwy, cty, cyl, displ

3. Map a continuous variable to color, size, and shape. How do these aesthetics behave differently for categorical vs. continuous variables?

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy, size = cty))

Color turns into a gradient Continuous variable won’t map to shape size turns into a gradient

4. What happens if you map the same variable to multiple aesthetics?

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy, size = hwy, color = hwy))

I’m not sure exactly what the answer we’re looking for here is. It maps them to multiple aesthetics. This seems potentially useful to emphasize a relationship, but it doesn’t add any new information to the plot.

3.5.1: 1-4, 6

1. What happens if you facet on a continuous variable?

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy)) + 
  facet_wrap(~ cty, nrow = 2)

Nothing good. It will take each value from your data set and create a plot for it.

2. What do the empty cells in plot with facet_grid(drv ~ cyl) mean? How do they relate to this plot?


ggplot(data = mpg) + 
  geom_point(mapping = aes(x = drv, y = cyl))

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy)) + 
  facet_grid(drv ~ cyl)

Empty cells in facet_grid represent combinations of drv and cyl that don’t have any data in them. You can see which values don’t contain value in the initial plot like the missing points (r,4) and (r,5)

3. What plots does the following code make? What does . do?


ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy)) +
  facet_grid(drv ~ .)

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy)) +
  facet_grid(. ~ cyl)

The dot creates the facet without an x or y. In the first plot, (drv ~ .) facets by drv on the y axis.

4. Take the first faceted plot in this section. What are the advantages to using faceting instead of the colour aesthetic? What are the disadvantages? How might the balance change if you had a larger dataset?

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy)) + 
  facet_wrap(.~class)

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy, color = class), position = "jitter")

In the facet plot, you can clearly see the distribution of each class, while with the color plot it is easy to miss differences in the distributions. Many points are also covered by other points, but jitter can deal with that. The facet plot makes it harder to see overall trends though. As the size of the data set increases, both plots will likely need jitter or some other method for dealing with overlapping points. If the number of levels for class increases, colors will become harder and harder to distinguish.

6. When using facet_grid() you should usually put the variable with more unique levels in the columns. Why?

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy)) + 
  facet_grid(cyl~class)

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy)) + 
  facet_grid(class~cyl)

Modern computer screens have more horizontal space, so the variable with more levels will have more room in the columns. 3.7.1: 1-5

1. What is the default geom associated with stat_summary()? How could you rewrite the previous plot to use that geom function instead of the stat function?

ggplot(data = diamonds) + 
  stat_summary(
    mapping = aes(x = cut, y = depth),
    fun.min = min,
    fun.max = max,
    fun = median
  )

Default geom is pointrange

# ggplot(data = diamonds) + 
#   geom_pointrange(
#     mapping = aes(
#       x = cut, y=median(depth), ymin = min(depth), ymax = max(depth)
#     )
#   )

ggplot(data = diamonds) + 
  geom_pointrange(
    mapping = aes(x = cut, y = depth),
    stat = "summary",
    fun.min = min,
    fun.max = max,
    fun = median
    )

2. What does geom_col() do? How is it different to geom_bar()?

From the description,

There are two types of bar charts: geom_bar() and geom_col(). geom_bar() makes the height of the bar proportional to the number of cases in each group (or if the weight aesthetic is supplied, the sum of the weights). If you want the heights of the bars to represent values in the data, use geom_col() instead

ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut))

ggplot(data = diamonds) + 
  geom_col(mapping = aes(x = cut, y = price))

These graphs may look similar, but realize that for the 2nd price the height is the sum of the price for each data point split by cut.

3. Most geoms and stats come in pairs that are almost always used in concert. Read through the documentation and make a list of all the pairs. What do they have in common?

There are a bunch so I won’t list them, but they can be found at https://ggplot2.tidyverse.org/reference/ … except that this is a submitted problem so I guess I will

Geom Stat Pairs
Geom Stat
geom_bar() stat_count()
geom_bin2d() stat_bin_2d()
geom_boxplot() stat_boxplot()
geom_contour() stat_contour()
geom_count() stat_sum()
geom_density() stat_density()
geom_histogram() stat_bin()
geom_qq_line() stat_qq_line()
geom_quantile() stat_quantile()
geom_smooth() stat_smooth()
geom_function() stat_function()

They tend to have the same name like geom_boxplot() stat_boxplot()

4. What variables does stat_smooth() compute? What parameters control its behaviour?

Stat_smooth() computes y, the predicted value, ymin, ymax, and standard error. It is controled by the following:

Method - Function used for smoothing Formula - Formula to use in smoothing function Se - Display the CI around smooth

5. In our proportion bar chart, we need to set group = 1. Why? In other words what is the problem with these two graphs?

ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, y = after_stat(prop)))

ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, fill = color, y = after_stat(prop)))

Both plots aren’t actually proportional. Each level is made proportional accross the board, rather than by each level. First one needs group = 1 and the 2nd needs

ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, y = after_stat(prop), group = 1))

ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut, fill = color, y = ..count../sum(..count..), group = color))

Introduction to Statistical Learning

2.4: 1-3, 7, 8, 10

1. For each of parts (a) through (d), indicate whether we would generally expect the performance of a flexible statistical learning method to be better or worse than an inflexible method. Justify your answer.

(a) The sample size n is extremely large, and the number of predictors p is small.

Flexible should perform well since the data set is very large, but so should an inflexible method since the number of predictors is small.

(b) The number of predictors p is extremely large, and the number of observations n is small.

Both will perform poorly, but flexible method is bound to over fit and be really bad since n is small

(c) The relationship between the predictors and response is highly non-linear.

Flexible should perform better? I’m not sure about this one… there are inflexible models that are highly non-linear

(d) The variance of the error terms, i.e. σ2 = Var(ϵ), is extremely high

Inflexible, since var(e) is very high, flexible methods will chase those outliers that will be far from the true relationship.

2. Explain whether each scenario is a classification or regression problem, and indicate whether we are most interested in inference or prediction. Finally, provide n and p.

(a) We collect a set of data on the top 500 firms in the US. For each firm we record profit, number of employees, industry and the CEO salary. We are interested in understanding which factors affect CEO salary

Regression, inference n = 500 firms p = employees, industry, profit

(b) We are considering launching a new product and wish to know whether it will be a success or a failure. We collect data on 20 similar products that were previously launched. For each product we have recorded whether it was a success or failure, price charged for the product, marketing budget, competition price. and ten other variables

Classification, prediction n = 20 similar products p = Price charged, budget, competition price, 10 other variables

(c) We are interested in predicting the % change in the USD/Euro exchange rate in relation to the weekly changes in the world stock markets. Hence we collect weekly data for all of 2012. For each week we record the % change in the USD/Euro, the % change in the US market, the % change in the British market, and the % change in the German market

Regression, prediction n = number of weeks in 2012, 52 p = change US, change British, change German

3. We now revisit the bias-variance decomposition.

(a) Provide a sketch of typical (squared) bias, variance, training error, test error, and Bayes (or irreducible) error curves, on a single plot, as we go from less flexible statistical learning methods towards more flexible approaches. The x-axis should represent the amount of flexibility in the method, and the y-axis should represent the values for each curve. There should be five curves. Make sure to label each one.

(b) Explain why each of the five curves has the shape displayed in part (a).

Variance will always increase as we increase flexibility since more flexible models are more “wiggly” by definition Bias will always decrease as we increase flexibility since more flexible models approach the true values at points in the data This same reasoning applies to training error The test error will decrease until over fitting at which point it will increase Bayes error is the irreducible error and is the same no matter the flexibility

7. The table below provides a training data set containing six observations, three predictors, and one qualitative response variable. Suppose we wish to use this data set to make a prediction for Y when X1 = X2 = X3 = 0 using K-nearest neighbors.

x1 = c(0,2,0,0,-1,1)
x2 = c(3,0,1,1,0,1)
x3 = c(0,0,3,2,1,1)
y = c(0,0,0,1,1,0)

table7= tibble(x1,x2,x3,y)
typeof(table7$x1)
[1] "double"

(a) Compute the Euclidean distance between each observation and the test point, X1 = X2 = X3 = 0.

x0 = c(0,0,0)
dist.c <- function(x1,x2,x3){
  sum((c(x1,x2,x3)-x0)**2)
}
#dist.c(table7[,1],table7[,2],table7[,3])
table7%>%
  mutate(dist.to.x=pmap_dbl(list(table7$x1,table7$x2,table7$x3),dist.c))%>%#wow that took a lon time to figure out. I feels silly.
arrange(dist.to.x)
NA

(b) What is our prediction with K = 1? Why?

Green, the closest 1 is green.

(c) What is our prediction with K = 3? Why?

Red. Closest three have green green red so there are more greens then red.

(d) If the Bayes decision boundary in this problem is highly nonlinear, then would we expect the best value for K to be large or small? Why?

Small. As we saw in Thursday lecture, a large K value will create a line averaging the sets.

8. This exercise relates to the College data set, which can be found in the file College.csv. It contains a number of variables for 777 different universities and colleges in the US.

(a) Use the read.csv() function to read the data into R. Call the loaded data college. Make sure that you have the directory set to the correct location for the data

college = read.csv("College.csv")
head(college)

(b) Look at the data using the fix() function. You should notice that the first column is just the name of each university. We don’t really want R to treat this as data. However, it may be handy to have these names for later.

rownames(college) = college[,1]
fix(college)
college =college [,-1]
fix(college)

(c)

summary(college)
   Private               Apps           Accept          Enroll       Top10perc       Top25perc      F.Undergrad     P.Undergrad         Outstate    
 Length:777         Min.   :   81   Min.   :   72   Min.   :  35   Min.   : 1.00   Min.   :  9.0   Min.   :  139   Min.   :    1.0   Min.   : 2340  
 Class :character   1st Qu.:  776   1st Qu.:  604   1st Qu.: 242   1st Qu.:15.00   1st Qu.: 41.0   1st Qu.:  992   1st Qu.:   95.0   1st Qu.: 7320  
 Mode  :character   Median : 1558   Median : 1110   Median : 434   Median :23.00   Median : 54.0   Median : 1707   Median :  353.0   Median : 9990  
                    Mean   : 3002   Mean   : 2019   Mean   : 780   Mean   :27.56   Mean   : 55.8   Mean   : 3700   Mean   :  855.3   Mean   :10441  
                    3rd Qu.: 3624   3rd Qu.: 2424   3rd Qu.: 902   3rd Qu.:35.00   3rd Qu.: 69.0   3rd Qu.: 4005   3rd Qu.:  967.0   3rd Qu.:12925  
                    Max.   :48094   Max.   :26330   Max.   :6392   Max.   :96.00   Max.   :100.0   Max.   :31643   Max.   :21836.0   Max.   :21700  
   Room.Board       Books           Personal         PhD            Terminal       S.F.Ratio      perc.alumni        Expend        Grad.Rate     
 Min.   :1780   Min.   :  96.0   Min.   : 250   Min.   :  8.00   Min.   : 24.0   Min.   : 2.50   Min.   : 0.00   Min.   : 3186   Min.   : 10.00  
 1st Qu.:3597   1st Qu.: 470.0   1st Qu.: 850   1st Qu.: 62.00   1st Qu.: 71.0   1st Qu.:11.50   1st Qu.:13.00   1st Qu.: 6751   1st Qu.: 53.00  
 Median :4200   Median : 500.0   Median :1200   Median : 75.00   Median : 82.0   Median :13.60   Median :21.00   Median : 8377   Median : 65.00  
 Mean   :4358   Mean   : 549.4   Mean   :1341   Mean   : 72.66   Mean   : 79.7   Mean   :14.09   Mean   :22.74   Mean   : 9660   Mean   : 65.46  
 3rd Qu.:5050   3rd Qu.: 600.0   3rd Qu.:1700   3rd Qu.: 85.00   3rd Qu.: 92.0   3rd Qu.:16.50   3rd Qu.:31.00   3rd Qu.:10830   3rd Qu.: 78.00  
 Max.   :8124   Max.   :2340.0   Max.   :6800   Max.   :103.00   Max.   :100.0   Max.   :39.80   Max.   :64.00   Max.   :56233   Max.   :118.00  
pairs(college[,2:10]) #This is a terrible picture. Can gg plot do this?

ggplot(data = college) + 
  geom_boxplot(mapping = aes(x = Private, y = Outstate))

Elite=rep("No",nrow(college ))
Elite[college$Top10perc >50]=" Yes"
Elite=as.factor(Elite)
college=data.frame( college , Elite)
summary(college)
   Private               Apps           Accept          Enroll       Top10perc       Top25perc      F.Undergrad     P.Undergrad         Outstate    
 Length:777         Min.   :   81   Min.   :   72   Min.   :  35   Min.   : 1.00   Min.   :  9.0   Min.   :  139   Min.   :    1.0   Min.   : 2340  
 Class :character   1st Qu.:  776   1st Qu.:  604   1st Qu.: 242   1st Qu.:15.00   1st Qu.: 41.0   1st Qu.:  992   1st Qu.:   95.0   1st Qu.: 7320  
 Mode  :character   Median : 1558   Median : 1110   Median : 434   Median :23.00   Median : 54.0   Median : 1707   Median :  353.0   Median : 9990  
                    Mean   : 3002   Mean   : 2019   Mean   : 780   Mean   :27.56   Mean   : 55.8   Mean   : 3700   Mean   :  855.3   Mean   :10441  
                    3rd Qu.: 3624   3rd Qu.: 2424   3rd Qu.: 902   3rd Qu.:35.00   3rd Qu.: 69.0   3rd Qu.: 4005   3rd Qu.:  967.0   3rd Qu.:12925  
                    Max.   :48094   Max.   :26330   Max.   :6392   Max.   :96.00   Max.   :100.0   Max.   :31643   Max.   :21836.0   Max.   :21700  
   Room.Board       Books           Personal         PhD            Terminal       S.F.Ratio      perc.alumni        Expend        Grad.Rate     
 Min.   :1780   Min.   :  96.0   Min.   : 250   Min.   :  8.00   Min.   : 24.0   Min.   : 2.50   Min.   : 0.00   Min.   : 3186   Min.   : 10.00  
 1st Qu.:3597   1st Qu.: 470.0   1st Qu.: 850   1st Qu.: 62.00   1st Qu.: 71.0   1st Qu.:11.50   1st Qu.:13.00   1st Qu.: 6751   1st Qu.: 53.00  
 Median :4200   Median : 500.0   Median :1200   Median : 75.00   Median : 82.0   Median :13.60   Median :21.00   Median : 8377   Median : 65.00  
 Mean   :4358   Mean   : 549.4   Mean   :1341   Mean   : 72.66   Mean   : 79.7   Mean   :14.09   Mean   :22.74   Mean   : 9660   Mean   : 65.46  
 3rd Qu.:5050   3rd Qu.: 600.0   3rd Qu.:1700   3rd Qu.: 85.00   3rd Qu.: 92.0   3rd Qu.:16.50   3rd Qu.:31.00   3rd Qu.:10830   3rd Qu.: 78.00  
 Max.   :8124   Max.   :2340.0   Max.   :6800   Max.   :103.00   Max.   :100.0   Max.   :39.80   Max.   :64.00   Max.   :56233   Max.   :118.00  
  Elite     Elite.1   
  Yes: 78    Yes: 78  
 No  :699   No  :699  
                      
                      
                      
                      
ggplot(data = college) + 
  geom_boxplot(mapping = aes(x = Elite, y = Outstate))

ggplot(data = college) + 
  geom_histogram(mapping = aes(x = Outstate),bins = 50)

ggplot(data = college) + 
  geom_histogram(mapping = aes(x = Outstate),bins = 10)

ggplot(data = college) + 
  geom_histogram(mapping = aes(x = Accept),bins = 100)

ggplot(data = college) + 
  geom_boxplot(mapping = aes(x = Private, y = Grad.Rate))

Private schools have a much higher graduation rate. Could it be that there is some sort of pressure to pass in private schools!?

ggplot(data = college) + 
  geom_boxplot(mapping = aes(x = Private, y = Expend))

Not really a surprise, but private schools spend more per student and the variance of what they spend is much higher.

3.7: 3, 10

3. Suppose we have a data set with five predictors, X1 = GPA, X2 = IQ, X3 = Gender (1 for Female and 0 for Male), X4 = Interaction between GPA and IQ, and X5 = Interaction between GPA and Gender. The response is starting salary after graduation (in thousands of dollars). Suppose we use least squares to fit the model, and get βˆ0 = 50, βˆ1 = 20, βˆ2 = 0.07, βˆ3 = 35, βˆ4 = 0.01, βˆ5 = −10.

(a) Which answer is correct, and why?fgv

i. For a fixed value of IQ and GPA, males earn more on average than females.

ii. For a fixed value of IQ and GPA, females earn more on average than males.

iii. For a fixed value of IQ and GPA, males earn more on average than females provided that the GPA is high enough.

True! if we consider the function y = 50 + 20 * gpa + .07 * iq + 35 * gender + .01 * (gpa * iq) -10 * (gpa * gender) so if we have an iq of 100, the interaction term will subtract 100 while being a women only adds 35.

iv. For a fixed value of IQ and GPA, females earn more on average than males provided that the GPA is high enough.

(b) Predict the salary of a female with IQ of 110 and a GPA of 4.0.

50+20*4+.07*110+35*1+.01*(4 * 110) -10*(4*1)
[1] 137.1

(c) True or false: Since the coefficient for the GPA/IQ interaction term is very small, there is very little evidence of an interaction effect. Justify your answer.

False, there could be an interaction effect if the pval is small, but it just doesn’t have a very large coefficient.

10. This question should be answered using the Carseats data set.

library(ISLR)
data("Carseats")
car = Carseats
car

(a) Fit a multiple regression model to predict Sales using Price, Urban, and US.

summary(model1 <- lm(Sales~Price + Urban + US, data = car))

Call:
lm(formula = Sales ~ Price + Urban + US, data = car)

Residuals:
    Min      1Q  Median      3Q     Max 
-6.9206 -1.6220 -0.0564  1.5786  7.0581 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 13.043469   0.651012  20.036  < 2e-16 ***
Price       -0.054459   0.005242 -10.389  < 2e-16 ***
UrbanYes    -0.021916   0.271650  -0.081    0.936    
USYes        1.200573   0.259042   4.635 4.86e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.472 on 396 degrees of freedom
Multiple R-squared:  0.2393,    Adjusted R-squared:  0.2335 
F-statistic: 41.52 on 3 and 396 DF,  p-value: < 2.2e-16

(b) Provide an interpretation of each coefficient in the model. Be careful—some of the variables in the model are qualitative!

(c) Write out the model in equation form, being careful to handle the qualitative variables properly.

Sales = 13.043469 - .054459 * Price - 0.021916 (if urban) + 1.200573 (if US)

(d) For which of the predictors can you reject the null hypothesis H0 : βj = 0?

Price, US

(e) On the basis of your response to the previous question, fit a smaller model that only uses the predictors for which there is evidence of association with the outcome.

summary(model2 <- lm(Sales~Price + US, data = car))

Call:
lm(formula = Sales ~ Price + US, data = car)

Residuals:
    Min      1Q  Median      3Q     Max 
-6.9269 -1.6286 -0.0574  1.5766  7.0515 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 13.03079    0.63098  20.652  < 2e-16 ***
Price       -0.05448    0.00523 -10.416  < 2e-16 ***
USYes        1.19964    0.25846   4.641 4.71e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.469 on 397 degrees of freedom
Multiple R-squared:  0.2393,    Adjusted R-squared:  0.2354 
F-statistic: 62.43 on 2 and 397 DF,  p-value: < 2.2e-16

(f) How well do the models in (a) and (e) fit the data?

Very poorly. R squ is terrible for both models.

(g) Using the model from (e), obtain 95 % confidence intervals for the coefficient(s).

confint(model2)
                  2.5 %      97.5 %
(Intercept) 11.79032020 14.27126531
Price       -0.06475984 -0.04419543
USYes        0.69151957  1.70776632

(h) Is there evidence of outliers or high leverage observations in the model from (e)?

par(mfrow=c(2,2))
plot(model2)

No.

4.7: 1, 3, 4, 9, 10a-d

1. Using a little bit of algebra, prove that (4.2) is equivalent to (4.3). In other words, the logistic function representation and logit representation for the logistic regression model are equivalent.

This is straight forward and I’d have to insert a picture so…

3. This problem relates to the QDA model, in which the observations within each class are drawn from a normal distribution with a classspecific mean vector and a class specific covariance matrix. We consider the simple case where p = 1; i.e. there is only one feature. Suppose that we have K classes, and that if an observation belongs to the kth class then X comes from a one-dimensional normal distribution, X ∼ N(µk, σ2 k). Recall that the density function for the one-dimensional normal distribution is given in (4.11). Prove that in this case, the Bayes’ classifier is not linear. Argue that it is in fact quadratic. Hint: For this problem, you should follow the arguments laid out in Section 4.4.2, but without making the assumption that σ^21 = … = σ^2K.

We end up with a x^2 from the expansion that is multiplied by sigma_k which must stay in our equation since it is in terms of k.

4. When the number of features p is large, there tends to be a deterioration in the performance of KNN and other local approaches that perform prediction using only observations that are near the test observation for which a prediction must be made. This phenomenon is known as the curse of dimensionality, and it ties into the fact that curse of dinon-parametric approaches often perform poorly when p is large. We will now investigate this curse.

(a) Suppose that we have a set of observations, each with measurements on p = 1 feature, X. We assume that X is uniformly (evenly) distributed on [0, 1]. Associated with each observation is a response value. Suppose that we wish to predict a test observation’s response using only observations that are within 10 % of the range of X closest to that test observation. For instance, in order to predict the response for a test observation with X = 0.6, we will use observations in the range [0.55, 0.65]. On average, what fraction of the available observations will we use to make the prediction?

10%

(b) Now suppose that we have a set of observations, each with measurements on p = 2 features, X1 and X2. We assume that (X1, X2) are uniformly distributed on [0, 1] × [0, 1]. We wish to predict a test observation’s response using only observations that are within 10 % of the range of X1 and within 10 % of the range of X2 closest to that test observation. For instance, in order to predict the response for a test observation with X1 = 0.6 and X2 = 0.35, we will use observations in the range [0.55, 0.65] for X1 and in the range [0.3, 0.4] for X2. On average, what fraction of the available observations will we use to make the prediction?

10% * 10% = 1%

(c) Now suppose that we have a set of observations on p = 100 features. Again the observations are uniformly distributed on each feature, and again each feature ranges in value from 0 to 1. We wish to predict a test observation’s response using observations within the 10 % of each feature’s range that is closest to that test observation. What fraction of the available observations will we use to make the prediction?

10%^100

.1**100
[1] 1e-100

(d) Using your answers to parts (a)–(c), argue that a drawback of KNN when p is large is that there are very few training observations “near” any given test observation.

As p increases, the number of of “near” observations decreases exponentially.

(e) Now suppose that we wish to make a prediction for a test observation by creating a p-dimensional hypercube centered around the test observation that contains, on average, 10 % of the training observations. For p = 1, 2, and 100, what is the length of each side of the hypercube? Comment on your answer.

Note: A hypercube is a generalization of a cube to an arbitrary number of dimensions. When p = 1, a hypercube is simply a line segment, when p = 2 it is a square, and when p = 100 it is a 100-dimensional cube.

p = 1: .1 p = 2:

.1**(1/2)
[1] 0.3162278

p=100:

.1**(1/100)
[1] 0.9772372

As p increases, we need more and more data. When p = 100, we need to use almost our entire data set.

9. This problem has to do with odds

(a) On average, what fraction of people with an odds of 0.37 of defaulting on their credit card payment will in fact default?

.37/(.37+1)
[1] 0.270073

(b) Suppose that an individual has a 16 % chance of defaulting on her credit card payment. What are the odds that she will default?

.16 = odds/(1+odds) .16 + .16odds = odds .16 = .84odds odds = .16/.84

.16/.84
[1] 0.1904762

Simply

.16/(1-.16)
[1] 0.1904762

10. This question should be answered using the Weekly data set, which is part of the ISLR package. This data is similar in nature to the Smarket data from this chapter’s lab, except that it contains 1, 089 weekly returns for 21 years, from the beginning of 1990 to the end of 2010.

data("Weekly")
Weekly

(a) Produce some numerical and graphical summaries of the Weekly data. Do there appear to be any patterns?

summary(Weekly)
      Year           Lag1               Lag2               Lag3               Lag4               Lag5              Volume            Today         
 Min.   :1990   Min.   :-18.1950   Min.   :-18.1950   Min.   :-18.1950   Min.   :-18.1950   Min.   :-18.1950   Min.   :0.08747   Min.   :-18.1950  
 1st Qu.:1995   1st Qu.: -1.1540   1st Qu.: -1.1540   1st Qu.: -1.1580   1st Qu.: -1.1580   1st Qu.: -1.1660   1st Qu.:0.33202   1st Qu.: -1.1540  
 Median :2000   Median :  0.2410   Median :  0.2410   Median :  0.2410   Median :  0.2380   Median :  0.2340   Median :1.00268   Median :  0.2410  
 Mean   :2000   Mean   :  0.1506   Mean   :  0.1511   Mean   :  0.1472   Mean   :  0.1458   Mean   :  0.1399   Mean   :1.57462   Mean   :  0.1499  
 3rd Qu.:2005   3rd Qu.:  1.4050   3rd Qu.:  1.4090   3rd Qu.:  1.4090   3rd Qu.:  1.4090   3rd Qu.:  1.4050   3rd Qu.:2.05373   3rd Qu.:  1.4050  
 Max.   :2010   Max.   : 12.0260   Max.   : 12.0260   Max.   : 12.0260   Max.   : 12.0260   Max.   : 12.0260   Max.   :9.32821   Max.   : 12.0260  
 Direction 
 Down:484  
 Up  :605  
           
           
           
           
ggplot(Weekly)+
  geom_point(mapping = aes(x = Lag1, y = Today, shape = Direction, color = Volume))

(b) Use the full data set to perform a logistic regression with Direction as the response and the five lag variables plus Volume as predictors. Use the summary function to print the results. Do any of the predictors appear to be statistically significant? If so,which ones?

logit1 = glm(Direction~. -Today -Year, data=Weekly, family=binomial)
summary(logit1)

Call:
glm(formula = Direction ~ . - Today - Year, family = binomial, 
    data = Weekly)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.6949  -1.2565   0.9913   1.0849   1.4579  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)   
(Intercept)  0.26686    0.08593   3.106   0.0019 **
Lag1        -0.04127    0.02641  -1.563   0.1181   
Lag2         0.05844    0.02686   2.175   0.0296 * 
Lag3        -0.01606    0.02666  -0.602   0.5469   
Lag4        -0.02779    0.02646  -1.050   0.2937   
Lag5        -0.01447    0.02638  -0.549   0.5833   
Volume      -0.02274    0.03690  -0.616   0.5377   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 1496.2  on 1088  degrees of freedom
Residual deviance: 1486.4  on 1082  degrees of freedom
AIC: 1500.4

Number of Fisher Scoring iterations: 4

Lag 2 appears statistically significant.

(c) Compute the confusion matrix and overall fraction of correct predictions. Explain what the confusion matrix is telling you about the types of mistakes made by logistic regression.

Weekly%>%mutate(up.hat = fitted(logit1))%>%
  mutate(dir.hat = up.hat >.5)%>%
  xtabs(~dir.hat+Direction, data = .)
       Direction
dir.hat Down  Up
  FALSE   54  48
  TRUE   430 557
typeof(fitted(logit1))
[1] "double"
(54+557)/(54+48+430+557)
[1] 0.5610652

(d) Now fit the logistic regression model using a training data period from 1990 to 2008, with Lag2 as the only predictor. Compute the confusion matrix and the overall fraction of correct predictions for the held out data (that is, the data from 2009 and 2010).

train = Weekly[Weekly$Year<2009,]
test = Weekly[Weekly$Year>2008,]
logit2 = glm(Direction~Lag2, data=train, family=binomial)
summary(logit2)

Call:
glm(formula = Direction ~ Lag2, family = binomial, data = train)

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.536  -1.264   1.021   1.091   1.368  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)   
(Intercept)  0.20326    0.06428   3.162  0.00157 **
Lag2         0.05810    0.02870   2.024  0.04298 * 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 1354.7  on 984  degrees of freedom
Residual deviance: 1350.5  on 983  degrees of freedom
AIC: 1354.5

Number of Fisher Scoring iterations: 4
up.hat = predict(logit2, test, type="response")
dir.hat = up.hat>.5
xtabs(~dir.hat+Weekly$Direction[Weekly$Year>2008])
       Weekly$Direction[Weekly$Year > 2008]
dir.hat Down Up
  FALSE    9  5
  TRUE    34 56
(9+56)/(34+5+9+56)
[1] 0.625
LS0tDQp0aXRsZTogIkhXIDEgV3JpdGUgVXAiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQoNCiMgUjREUw0KDQojIyAzLjMuMTogMS00DQoNCiMjIyAxLiBXaGF04oCZcyBnb25lIHdyb25nIHdpdGggdGhpcyBjb2RlPyBXaHkgYXJlIHRoZSBwb2ludHMgbm90IGJsdWU/DQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpLCBjb2xvciA9ICJibHVlIikNCmBgYA0KY29sb3IgaXNuJ3QgYmVpbmcgdXNlZCBhcyBhbiBhZXN0aGV0aWMuIEl0IHNob3VsZCBiZSBvdXRzaWRlIGFlcy4NCg0KIyMjIDIuIFdoaWNoIHZhcmlhYmxlcyBpbiBtcGcgYXJlIGNhdGVnb3JpY2FsPyBXaGljaCB2YXJpYWJsZXMgYXJlIGNvbnRpbnVvdXM/IChIaW50OiB0eXBlID9tcGcgdG8gcmVhZCB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgdGhlIGRhdGFzZXQpLiBIb3cgY2FuIHlvdSBzZWUgdGhpcyBpbmZvcm1hdGlvbiB3aGVuIHlvdSBydW4gbXBnPw0KDQpgYGB7cn0NCmhlYWQobXBnKQ0KYGBgDQoNCkNhdGVnb3JpY2FsOiBNYW51ZmFjdHVyZXIsIE1vZGVsLCBUcmFucywgRHJ2LCBmbCwgQ2xhc3MNCkNvbnRpbnVvdXM6IGh3eSwgY3R5LCBjeWwsIGRpc3BsDQoNCiMjIyAzLiBNYXAgYSBjb250aW51b3VzIHZhcmlhYmxlIHRvIGNvbG9yLCBzaXplLCBhbmQgc2hhcGUuIEhvdyBkbyB0aGVzZSBhZXN0aGV0aWNzIGJlaGF2ZSBkaWZmZXJlbnRseSBmb3IgY2F0ZWdvcmljYWwgdnMuIGNvbnRpbnVvdXMgdmFyaWFibGVzPw0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbXBnKSArIA0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBzaXplID0gY3R5KSkNCmBgYA0KQ29sb3IgdHVybnMgaW50byBhIGdyYWRpZW50DQpDb250aW51b3VzIHZhcmlhYmxlIHdvbid0IG1hcCB0byBzaGFwZQ0Kc2l6ZSB0dXJucyBpbnRvIGEgZ3JhZGllbnQNCg0KIyMjIDQuIFdoYXQgaGFwcGVucyBpZiB5b3UgbWFwIHRoZSBzYW1lIHZhcmlhYmxlIHRvIG11bHRpcGxlIGFlc3RoZXRpY3M/DQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3ksIHNpemUgPSBod3ksIGNvbG9yID0gaHd5KSkNCmBgYA0KSSdtIG5vdCBzdXJlIGV4YWN0bHkgd2hhdCB0aGUgYW5zd2VyIHdlJ3JlIGxvb2tpbmcgZm9yIGhlcmUgaXMuIEl0IG1hcHMgdGhlbSB0byBtdWx0aXBsZSBhZXN0aGV0aWNzLiBUaGlzIHNlZW1zIHBvdGVudGlhbGx5IHVzZWZ1bCB0byBlbXBoYXNpemUgYSByZWxhdGlvbnNoaXAsIGJ1dCBpdCBkb2Vzbid0IGFkZCBhbnkgbmV3IGluZm9ybWF0aW9uIHRvIHRoZSBwbG90Lg0KDQozLjUuMTogMS00LCA2DQoNCiMjIyAxLiBXaGF0IGhhcHBlbnMgaWYgeW91IGZhY2V0IG9uIGEgY29udGludW91cyB2YXJpYWJsZT8NCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpKSArIA0KICBmYWNldF93cmFwKH4gY3R5LCBucm93ID0gMikNCmBgYA0KTm90aGluZyBnb29kLiBJdCB3aWxsIHRha2UgZWFjaCB2YWx1ZSBmcm9tIHlvdXIgZGF0YSBzZXQgYW5kIGNyZWF0ZSBhIHBsb3QgZm9yIGl0Lg0KDQojIyMgMi4gV2hhdCBkbyB0aGUgZW1wdHkgY2VsbHMgaW4gcGxvdCB3aXRoIGZhY2V0X2dyaWQoZHJ2IH4gY3lsKSBtZWFuPyBIb3cgZG8gdGhleSByZWxhdGUgdG8gdGhpcyBwbG90Pw0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbXBnKSArIA0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGRydiwgeSA9IGN5bCkpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IG1wZykgKyANCiAgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHggPSBkaXNwbCwgeSA9IGh3eSkpICsgDQogIGZhY2V0X2dyaWQoZHJ2IH4gY3lsKQ0KYGBgDQoNCg0KRW1wdHkgY2VsbHMgaW4gZmFjZXRfZ3JpZCByZXByZXNlbnQgY29tYmluYXRpb25zIG9mIGRydiBhbmQgY3lsIHRoYXQgZG9uJ3QgaGF2ZSBhbnkgZGF0YSBpbiB0aGVtLiBZb3UgY2FuIHNlZSB3aGljaCB2YWx1ZXMgZG9uJ3QgY29udGFpbiB2YWx1ZSBpbiB0aGUgaW5pdGlhbCBwbG90IGxpa2UgdGhlIG1pc3NpbmcgcG9pbnRzIChyLDQpIGFuZCAociw1KQ0KDQojIyMgMy4gV2hhdCBwbG90cyBkb2VzIHRoZSBmb2xsb3dpbmcgY29kZSBtYWtlPyBXaGF0IGRvZXMgLiBkbz8NCg0KYGBge3J9DQoNCmdncGxvdChkYXRhID0gbXBnKSArIA0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkgKw0KICBmYWNldF9ncmlkKGRydiB+IC4pDQpgYGANCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpKSArDQogIGZhY2V0X2dyaWQoLiB+IGN5bCkNCmBgYA0KVGhlIGRvdCBjcmVhdGVzIHRoZSBmYWNldCB3aXRob3V0IGFuIHggb3IgeS4gSW4gdGhlIGZpcnN0IHBsb3QsIChkcnYgfiAuKSBmYWNldHMgYnkgZHJ2IG9uIHRoZSB5IGF4aXMuDQoNCiMjIyA0LiBUYWtlIHRoZSBmaXJzdCBmYWNldGVkIHBsb3QgaW4gdGhpcyBzZWN0aW9uLiBXaGF0IGFyZSB0aGUgYWR2YW50YWdlcyB0byB1c2luZyBmYWNldGluZyBpbnN0ZWFkIG9mIHRoZSBjb2xvdXIgYWVzdGhldGljPyBXaGF0IGFyZSB0aGUgZGlzYWR2YW50YWdlcz8gSG93IG1pZ2h0IHRoZSBiYWxhbmNlIGNoYW5nZSBpZiB5b3UgaGFkIGEgbGFyZ2VyIGRhdGFzZXQ/DQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpKSArIA0KICBmYWNldF93cmFwKGNsYXNzfiAsIG5yb3cgPSAyKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3ksIGNvbG9yID0gY2xhc3MpLCBwb3NpdGlvbiA9ICJqaXR0ZXIiKQ0KYGBgDQpJbiB0aGUgZmFjZXQgcGxvdCwgeW91IGNhbiBjbGVhcmx5IHNlZSB0aGUgZGlzdHJpYnV0aW9uIG9mIGVhY2ggY2xhc3MsIHdoaWxlIHdpdGggdGhlIGNvbG9yIHBsb3QgaXQgaXMgZWFzeSB0byBtaXNzIGRpZmZlcmVuY2VzIGluIHRoZSBkaXN0cmlidXRpb25zLiBNYW55IHBvaW50cyBhcmUgYWxzbyBjb3ZlcmVkIGJ5IG90aGVyIHBvaW50cywgYnV0IGppdHRlciBjYW4gZGVhbCB3aXRoIHRoYXQuIFRoZSBmYWNldCBwbG90IG1ha2VzIGl0IGhhcmRlciB0byBzZWUgb3ZlcmFsbCB0cmVuZHMgdGhvdWdoLiBBcyB0aGUgc2l6ZSBvZiB0aGUgZGF0YSBzZXQgaW5jcmVhc2VzLCBib3RoIHBsb3RzIHdpbGwgbGlrZWx5IG5lZWQgaml0dGVyIG9yIHNvbWUgb3RoZXIgbWV0aG9kIGZvciBkZWFsaW5nIHdpdGggb3ZlcmxhcHBpbmcgcG9pbnRzLiBJZiB0aGUgbnVtYmVyIG9mIGxldmVscyBmb3IgY2xhc3MgaW5jcmVhc2VzLCBjb2xvcnMgd2lsbCBiZWNvbWUgaGFyZGVyIGFuZCBoYXJkZXIgdG8gZGlzdGluZ3Vpc2guDQoNCg0KIyMjIDYuIFdoZW4gdXNpbmcgZmFjZXRfZ3JpZCgpIHlvdSBzaG91bGQgdXN1YWxseSBwdXQgdGhlIHZhcmlhYmxlIHdpdGggbW9yZSB1bmlxdWUgbGV2ZWxzIGluIHRoZSBjb2x1bW5zLiBXaHk/DQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBtcGcpICsgDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gZGlzcGwsIHkgPSBod3kpKSArIA0KICBmYWNldF9ncmlkKGN5bH5jbGFzcykNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gbXBnKSArIA0KICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkgKyANCiAgZmFjZXRfZ3JpZChjbGFzc35jeWwpDQpgYGANCg0KTW9kZXJuIGNvbXB1dGVyIHNjcmVlbnMgaGF2ZSBtb3JlIGhvcml6b250YWwgc3BhY2UsIHNvIHRoZSB2YXJpYWJsZSB3aXRoIG1vcmUgbGV2ZWxzIHdpbGwgaGF2ZSBtb3JlIHJvb20gaW4gdGhlIGNvbHVtbnMuDQozLjcuMTogMS01DQoNCiMjIyAxLiBXaGF0IGlzIHRoZSBkZWZhdWx0IGdlb20gYXNzb2NpYXRlZCB3aXRoIHN0YXRfc3VtbWFyeSgpPyBIb3cgY291bGQgeW91IHJld3JpdGUgdGhlIHByZXZpb3VzIHBsb3QgdG8gdXNlIHRoYXQgZ2VvbSBmdW5jdGlvbiBpbnN0ZWFkIG9mIHRoZSBzdGF0IGZ1bmN0aW9uPw0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArIA0KICBzdGF0X3N1bW1hcnkoDQogICAgbWFwcGluZyA9IGFlcyh4ID0gY3V0LCB5ID0gZGVwdGgpLA0KICAgIGZ1bi5taW4gPSBtaW4sDQogICAgZnVuLm1heCA9IG1heCwNCiAgICBmdW4gPSBtZWRpYW4NCiAgKQ0KYGBgDQoNCkRlZmF1bHQgZ2VvbSBpcyBwb2ludHJhbmdlDQoNCmBgYHtyfQ0KIyBnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArIA0KIyAgIGdlb21fcG9pbnRyYW5nZSgNCiMgICAgIG1hcHBpbmcgPSBhZXMoDQojICAgICAgIHggPSBjdXQsIHk9bWVkaWFuKGRlcHRoKSwgeW1pbiA9IG1pbihkZXB0aCksIHltYXggPSBtYXgoZGVwdGgpDQojICAgICApDQojICAgKQ0KI2ZpcnN0IGF0dGVtcHQgZGlkbid0IHdvcmsuIFRoZSB5bWluLCB5bWF4IGFyZSBwaWNraW5nIHRoZSBtYXggYW5kIG1pbiBvZiB0aGUgZW50aXJlIGRhdGEgc2V0IGluc3RlYWQgb2YgZnJvbSB0aGUgc3Vic2V0Lg0KDQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArIA0KICBnZW9tX3BvaW50cmFuZ2UoDQogICAgbWFwcGluZyA9IGFlcyh4ID0gY3V0LCB5ID0gZGVwdGgpLA0KICAgIHN0YXQgPSAic3VtbWFyeSIsDQogICAgZnVuLm1pbiA9IG1pbiwNCiAgICBmdW4ubWF4ID0gbWF4LA0KICAgIGZ1biA9IG1lZGlhbg0KICAgICkNCmBgYA0KDQojIyMgMi4gV2hhdCBkb2VzIGdlb21fY29sKCkgZG8/IEhvdyBpcyBpdCBkaWZmZXJlbnQgdG8gZ2VvbV9iYXIoKT8NCkZyb20gdGhlIGRlc2NyaXB0aW9uLCANCg0KKlRoZXJlIGFyZSB0d28gdHlwZXMgb2YgYmFyIGNoYXJ0czogZ2VvbV9iYXIoKSBhbmQgZ2VvbV9jb2woKS4gZ2VvbV9iYXIoKSBtYWtlcyB0aGUgaGVpZ2h0IG9mIHRoZSBiYXIgcHJvcG9ydGlvbmFsIHRvIHRoZSBudW1iZXIgb2YgY2FzZXMgaW4gZWFjaCBncm91cCAob3IgaWYgdGhlIHdlaWdodCBhZXN0aGV0aWMgaXMgc3VwcGxpZWQsIHRoZSBzdW0gb2YgdGhlIHdlaWdodHMpLiBJZiB5b3Ugd2FudCB0aGUgaGVpZ2h0cyBvZiB0aGUgYmFycyB0byByZXByZXNlbnQgdmFsdWVzIGluIHRoZSBkYXRhLCB1c2UgZ2VvbV9jb2woKSBpbnN0ZWFkKg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGlhbW9uZHMpICsgDQogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IGN1dCkpDQpgYGANCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBkaWFtb25kcykgKyANCiAgZ2VvbV9jb2wobWFwcGluZyA9IGFlcyh4ID0gY3V0LCB5ID0gcHJpY2UpKQ0KYGBgDQpUaGVzZSBncmFwaHMgbWF5IGxvb2sgc2ltaWxhciwgYnV0IHJlYWxpemUgdGhhdCBmb3IgdGhlIDJuZCBwcmljZSB0aGUgaGVpZ2h0IGlzIHRoZSBzdW0gb2YgdGhlIHByaWNlIGZvciBlYWNoIGRhdGEgcG9pbnQgc3BsaXQgYnkgY3V0Lg0KDQojIyMgMy4gTW9zdCBnZW9tcyBhbmQgc3RhdHMgY29tZSBpbiBwYWlycyB0aGF0IGFyZSBhbG1vc3QgYWx3YXlzIHVzZWQgaW4gY29uY2VydC4gUmVhZCB0aHJvdWdoIHRoZSBkb2N1bWVudGF0aW9uIGFuZCBtYWtlIGEgbGlzdCBvZiBhbGwgdGhlIHBhaXJzLiBXaGF0IGRvIHRoZXkgaGF2ZSBpbiBjb21tb24/DQoNClRoZXJlIGFyZSBhIGJ1bmNoIHNvIEkgd29uJ3QgbGlzdCB0aGVtLCBidXQgdGhleSBjYW4gYmUgZm91bmQgYXQgaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlLyAuLi4gZXhjZXB0IHRoYXQgdGhpcyBpcyBhIHN1Ym1pdHRlZCBwcm9ibGVtIHNvIEkgZ3Vlc3MgSSB3aWxsDQoNCkdlb20gICAgICAgICAgICAgICAgU3RhdCAgICANCi0tLS0tLS0gICAgICAgICAgICAgLS0tLS0tIA0KZ2VvbV9iYXIoKSAgICAgICAgICBzdGF0X2NvdW50KCkNCmdlb21fYmluMmQoKSAgICAgICAgc3RhdF9iaW5fMmQoKQ0KZ2VvbV9ib3hwbG90KCkgICAgICBzdGF0X2JveHBsb3QoKQ0KZ2VvbV9jb250b3VyKCkgICAgICBzdGF0X2NvbnRvdXIoKQ0KZ2VvbV9jb3VudCgpICAgICAgICBzdGF0X3N1bSgpDQpnZW9tX2RlbnNpdHkoKSAgICAgIHN0YXRfZGVuc2l0eSgpDQpnZW9tX2hpc3RvZ3JhbSgpICAgIHN0YXRfYmluKCkNCmdlb21fcXFfbGluZSgpICAgICAgc3RhdF9xcV9saW5lKCkNCmdlb21fcXVhbnRpbGUoKSAgICAgc3RhdF9xdWFudGlsZSgpDQpnZW9tX3Ntb290aCgpICAgICAgIHN0YXRfc21vb3RoKCkNCmdlb21fZnVuY3Rpb24oKSAgICAgc3RhdF9mdW5jdGlvbigpDQoNClRhYmxlOiAgR2VvbSBTdGF0IFBhaXJzDQoNClRoZXkgdGVuZCB0byBoYXZlIHRoZSBzYW1lIG5hbWUgbGlrZSBnZW9tX2JveHBsb3QoKSBzdGF0X2JveHBsb3QoKQ0KDQoNCiMjIyA0LiBXaGF0IHZhcmlhYmxlcyBkb2VzIHN0YXRfc21vb3RoKCkgY29tcHV0ZT8gV2hhdCBwYXJhbWV0ZXJzIGNvbnRyb2wgaXRzIGJlaGF2aW91cj8NCg0KU3RhdF9zbW9vdGgoKSBjb21wdXRlcyB5LCB0aGUgcHJlZGljdGVkIHZhbHVlLCB5bWluLCB5bWF4LCBhbmQgc3RhbmRhcmQgZXJyb3IuIEl0IGlzIGNvbnRyb2xlZCBieSB0aGUgZm9sbG93aW5nOg0KDQpNZXRob2QgLSBGdW5jdGlvbiB1c2VkIGZvciBzbW9vdGhpbmcNCkZvcm11bGEgLSBGb3JtdWxhIHRvIHVzZSBpbiBzbW9vdGhpbmcgZnVuY3Rpb24NClNlIC0gRGlzcGxheSB0aGUgQ0kgYXJvdW5kIHNtb290aA0KDQojIyMgNS4gSW4gb3VyIHByb3BvcnRpb24gYmFyIGNoYXJ0LCB3ZSBuZWVkIHRvIHNldCBncm91cCA9IDEuIFdoeT8gSW4gb3RoZXIgd29yZHMgd2hhdCBpcyB0aGUgcHJvYmxlbSB3aXRoIHRoZXNlIHR3byBncmFwaHM/DQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBkaWFtb25kcykgKyANCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyh4ID0gY3V0LCB5ID0gYWZ0ZXJfc3RhdChwcm9wKSkpDQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArIA0KICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHggPSBjdXQsIGZpbGwgPSBjb2xvciwgeSA9IGFmdGVyX3N0YXQocHJvcCkpKQ0KYGBgDQoNCkJvdGggcGxvdHMgYXJlbid0IGFjdHVhbGx5IHByb3BvcnRpb25hbC4gRWFjaCBsZXZlbCBpcyBtYWRlIHByb3BvcnRpb25hbCBhY2Nyb3NzIHRoZSBib2FyZCwgcmF0aGVyIHRoYW4gYnkgZWFjaCBsZXZlbC4gRmlyc3Qgb25lIG5lZWRzIGdyb3VwID0gMSBhbmQgdGhlIDJuZCBuZWVkcw0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGlhbW9uZHMpICsgDQogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IGN1dCwgeSA9IGFmdGVyX3N0YXQocHJvcCksIGdyb3VwID0gMSkpDQpnZ3Bsb3QoZGF0YSA9IGRpYW1vbmRzKSArIA0KICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHggPSBjdXQsIGZpbGwgPSBjb2xvciwgeSA9IC4uY291bnQuLi9zdW0oLi5jb3VudC4uKSwgZ3JvdXAgPSBjb2xvcikpICMgZm91bmQgdGhpcyBvbmxpbmUgQGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzQ2ODQ3NjUyL2dncGxvdDItcGxvdC1jb3JyZWN0LXByb3BvcnRpb25zLXVzaW5nLWdlb20tYmFyIGFuZCBJJ20gbm90IHN1cmUgd2hhdCB0aGUgLi4uY291bnQuLi4gaXMNCmBgYA0KDQpgYGB7cn0NCg0KYGBgDQoNCiMgSW50cm9kdWN0aW9uIHRvIFN0YXRpc3RpY2FsIExlYXJuaW5nDQoNCiMjIDIuNDogMS0qKjMqKiwgKio3KiosIDgsICoqMTAqKg0KDQojIyMgMS4gRm9yIGVhY2ggb2YgcGFydHMgKGEpIHRocm91Z2ggKGQpLCBpbmRpY2F0ZSB3aGV0aGVyIHdlIHdvdWxkIGdlbmVyYWxseSBleHBlY3QgdGhlIHBlcmZvcm1hbmNlIG9mIGEgZmxleGlibGUgc3RhdGlzdGljYWwgbGVhcm5pbmcgbWV0aG9kIHRvIGJlIGJldHRlciBvciB3b3JzZSB0aGFuIGFuIGluZmxleGlibGUgbWV0aG9kLiBKdXN0aWZ5IHlvdXIgYW5zd2VyLg0KDQojIyMjIChhKSBUaGUgc2FtcGxlIHNpemUgbiBpcyBleHRyZW1lbHkgbGFyZ2UsIGFuZCB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgcCBpcyBzbWFsbC4NCg0KRmxleGlibGUgc2hvdWxkIHBlcmZvcm0gd2VsbCBzaW5jZSB0aGUgZGF0YSBzZXQgaXMgdmVyeSBsYXJnZSwgYnV0IHNvIHNob3VsZCBhbiBpbmZsZXhpYmxlIG1ldGhvZCBzaW5jZSB0aGUgbnVtYmVyIG9mIHByZWRpY3RvcnMgaXMgc21hbGwuDQoNCiMjIyMgKGIpIFRoZSBudW1iZXIgb2YgcHJlZGljdG9ycyBwIGlzIGV4dHJlbWVseSBsYXJnZSwgYW5kIHRoZSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIG4gaXMgc21hbGwuDQoNCkJvdGggd2lsbCBwZXJmb3JtIHBvb3JseSwgYnV0IGZsZXhpYmxlIG1ldGhvZCBpcyBib3VuZCB0byBvdmVyIGZpdCBhbmQgYmUgcmVhbGx5IGJhZCBzaW5jZSBuIGlzIHNtYWxsDQoNCiMjIyMgKGMpIFRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgcHJlZGljdG9ycyBhbmQgcmVzcG9uc2UgaXMgaGlnaGx5IG5vbi1saW5lYXIuDQoNCkZsZXhpYmxlIHNob3VsZCBwZXJmb3JtIGJldHRlcj8gSSdtIG5vdCBzdXJlIGFib3V0IHRoaXMgb25lLi4uIHRoZXJlIGFyZSBpbmZsZXhpYmxlIG1vZGVscyB0aGF0IGFyZSBoaWdobHkgbm9uLWxpbmVhcg0KDQojIyMjIChkKSBUaGUgdmFyaWFuY2Ugb2YgdGhlIGVycm9yIHRlcm1zLCBpLmUuIM+DMiA9IFZhcijPtSksIGlzIGV4dHJlbWVseSBoaWdoDQoNCkluZmxleGlibGUsIHNpbmNlIHZhcihlKSBpcyB2ZXJ5IGhpZ2gsIGZsZXhpYmxlIG1ldGhvZHMgd2lsbCBjaGFzZSB0aG9zZSBvdXRsaWVycyB0aGF0IHdpbGwgYmUgZmFyIGZyb20gdGhlIHRydWUgcmVsYXRpb25zaGlwLg0KDQoNCiMjIyAyLiBFeHBsYWluIHdoZXRoZXIgZWFjaCBzY2VuYXJpbyBpcyBhIGNsYXNzaWZpY2F0aW9uIG9yIHJlZ3Jlc3Npb24gcHJvYmxlbSwgYW5kIGluZGljYXRlIHdoZXRoZXIgd2UgYXJlIG1vc3QgaW50ZXJlc3RlZCBpbiBpbmZlcmVuY2Ugb3IgcHJlZGljdGlvbi4gRmluYWxseSwgcHJvdmlkZSBuIGFuZCBwLg0KDQojIyMjIChhKSBXZSBjb2xsZWN0IGEgc2V0IG9mIGRhdGEgb24gdGhlIHRvcCA1MDAgZmlybXMgaW4gdGhlIFVTLiBGb3IgZWFjaCBmaXJtIHdlIHJlY29yZCBwcm9maXQsIG51bWJlciBvZiBlbXBsb3llZXMsIGluZHVzdHJ5IGFuZCB0aGUgQ0VPIHNhbGFyeS4gV2UgYXJlIGludGVyZXN0ZWQgaW4gdW5kZXJzdGFuZGluZyB3aGljaCBmYWN0b3JzIGFmZmVjdCBDRU8gc2FsYXJ5DQoNClJlZ3Jlc3Npb24sIGluZmVyZW5jZQ0KbiA9IDUwMCBmaXJtcw0KcCA9IGVtcGxveWVlcywgaW5kdXN0cnksIHByb2ZpdA0KDQojIyMjIChiKSBXZSBhcmUgY29uc2lkZXJpbmcgbGF1bmNoaW5nIGEgbmV3IHByb2R1Y3QgYW5kIHdpc2ggdG8ga25vdyB3aGV0aGVyIGl0IHdpbGwgYmUgYSBzdWNjZXNzIG9yIGEgZmFpbHVyZS4gV2UgY29sbGVjdCBkYXRhIG9uIDIwIHNpbWlsYXIgcHJvZHVjdHMgdGhhdCB3ZXJlIHByZXZpb3VzbHkgbGF1bmNoZWQuIEZvciBlYWNoIHByb2R1Y3Qgd2UgaGF2ZSByZWNvcmRlZCB3aGV0aGVyIGl0IHdhcyBhIHN1Y2Nlc3Mgb3IgZmFpbHVyZSwgcHJpY2UgY2hhcmdlZCBmb3IgdGhlIHByb2R1Y3QsIG1hcmtldGluZyBidWRnZXQsIGNvbXBldGl0aW9uIHByaWNlLiBhbmQgdGVuIG90aGVyIHZhcmlhYmxlcw0KDQpDbGFzc2lmaWNhdGlvbiwgcHJlZGljdGlvbg0KbiA9IDIwIHNpbWlsYXIgcHJvZHVjdHMNCnAgPSBQcmljZSBjaGFyZ2VkLCBidWRnZXQsIGNvbXBldGl0aW9uIHByaWNlLCAxMCBvdGhlciB2YXJpYWJsZXMNCg0KIyMjIyAoYykgV2UgYXJlIGludGVyZXN0ZWQgaW4gcHJlZGljdGluZyB0aGUgJSBjaGFuZ2UgaW4gdGhlIFVTRC9FdXJvIGV4Y2hhbmdlIHJhdGUgaW4gcmVsYXRpb24gdG8gdGhlIHdlZWtseSBjaGFuZ2VzIGluIHRoZSB3b3JsZCBzdG9jayBtYXJrZXRzLiBIZW5jZSB3ZSBjb2xsZWN0IHdlZWtseSBkYXRhIGZvciBhbGwgb2YgMjAxMi4gRm9yIGVhY2ggd2VlayB3ZSByZWNvcmQgdGhlICUgY2hhbmdlIGluIHRoZSBVU0QvRXVybywgdGhlICUgY2hhbmdlIGluIHRoZSBVUyBtYXJrZXQsIHRoZSAlIGNoYW5nZSBpbiB0aGUgQnJpdGlzaCBtYXJrZXQsIGFuZCB0aGUgJSBjaGFuZ2UgaW4gdGhlIEdlcm1hbiBtYXJrZXQNCg0KUmVncmVzc2lvbiwgcHJlZGljdGlvbg0KbiA9IG51bWJlciBvZiB3ZWVrcyBpbiAyMDEyLCA1Mg0KcCA9IGNoYW5nZSBVUywgY2hhbmdlIEJyaXRpc2gsIGNoYW5nZSBHZXJtYW4NCg0KIyMjIDMuIFdlIG5vdyByZXZpc2l0IHRoZSBiaWFzLXZhcmlhbmNlIGRlY29tcG9zaXRpb24uDQoNCiMjIyMgKGEpIFByb3ZpZGUgYSBza2V0Y2ggb2YgdHlwaWNhbCAoc3F1YXJlZCkgYmlhcywgdmFyaWFuY2UsIHRyYWluaW5nIGVycm9yLCB0ZXN0IGVycm9yLCBhbmQgQmF5ZXMgKG9yIGlycmVkdWNpYmxlKSBlcnJvciBjdXJ2ZXMsIG9uIGEgc2luZ2xlIHBsb3QsIGFzIHdlIGdvIGZyb20gbGVzcyBmbGV4aWJsZSBzdGF0aXN0aWNhbCBsZWFybmluZyBtZXRob2RzIHRvd2FyZHMgbW9yZSBmbGV4aWJsZSBhcHByb2FjaGVzLiBUaGUgeC1heGlzIHNob3VsZCByZXByZXNlbnQgdGhlIGFtb3VudCBvZiBmbGV4aWJpbGl0eSBpbiB0aGUgbWV0aG9kLCBhbmQgdGhlIHktYXhpcyBzaG91bGQgcmVwcmVzZW50IHRoZSB2YWx1ZXMgZm9yIGVhY2ggY3VydmUuIFRoZXJlIHNob3VsZCBiZSBmaXZlIGN1cnZlcy4gTWFrZSBzdXJlIHRvIGxhYmVsIGVhY2ggb25lLg0KDQoNCiMjIyMgKGIpIEV4cGxhaW4gd2h5IGVhY2ggb2YgdGhlIGZpdmUgY3VydmVzIGhhcyB0aGUgc2hhcGUgZGlzcGxheWVkIGluIHBhcnQgKGEpLg0KDQpWYXJpYW5jZSB3aWxsIGFsd2F5cyBpbmNyZWFzZSBhcyB3ZSBpbmNyZWFzZSBmbGV4aWJpbGl0eSBzaW5jZSBtb3JlIGZsZXhpYmxlIG1vZGVscyBhcmUgbW9yZSAid2lnZ2x5IiBieSBkZWZpbml0aW9uDQpCaWFzIHdpbGwgYWx3YXlzIGRlY3JlYXNlIGFzIHdlIGluY3JlYXNlIGZsZXhpYmlsaXR5IHNpbmNlIG1vcmUgZmxleGlibGUgbW9kZWxzIGFwcHJvYWNoIHRoZSB0cnVlIHZhbHVlcyBhdCBwb2ludHMgaW4gdGhlIGRhdGENClRoaXMgc2FtZSByZWFzb25pbmcgYXBwbGllcyB0byB0cmFpbmluZyBlcnJvcg0KVGhlIHRlc3QgZXJyb3Igd2lsbCBkZWNyZWFzZSB1bnRpbCBvdmVyIGZpdHRpbmcgYXQgd2hpY2ggcG9pbnQgaXQgd2lsbCBpbmNyZWFzZQ0KQmF5ZXMgZXJyb3IgaXMgdGhlIGlycmVkdWNpYmxlIGVycm9yIGFuZCBpcyB0aGUgc2FtZSBubyBtYXR0ZXIgdGhlIGZsZXhpYmlsaXR5DQoNCiMjIyA3LiBUaGUgdGFibGUgYmVsb3cgcHJvdmlkZXMgYSB0cmFpbmluZyBkYXRhIHNldCBjb250YWluaW5nIHNpeCBvYnNlcnZhdGlvbnMsIHRocmVlIHByZWRpY3RvcnMsIGFuZCBvbmUgcXVhbGl0YXRpdmUgcmVzcG9uc2UgdmFyaWFibGUuIFN1cHBvc2Ugd2Ugd2lzaCB0byB1c2UgdGhpcyBkYXRhIHNldCB0byBtYWtlIGEgcHJlZGljdGlvbiBmb3IgWSB3aGVuIFgxID0gWDIgPSBYMyA9IDAgdXNpbmcgSy1uZWFyZXN0IG5laWdoYm9ycy4NCg0KDQpgYGB7cn0NCngxID0gYygwLDIsMCwwLC0xLDEpDQp4MiA9IGMoMywwLDEsMSwwLDEpDQp4MyA9IGMoMCwwLDMsMiwxLDEpDQp5ID0gYygwLDAsMCwxLDEsMCkNCg0KdGFibGU3PSB0aWJibGUoeDEseDIseDMseSkNCnR5cGVvZih0YWJsZTckeDEpDQpgYGANCg0KIyMjIyAoYSkgQ29tcHV0ZSB0aGUgRXVjbGlkZWFuIGRpc3RhbmNlIGJldHdlZW4gZWFjaCBvYnNlcnZhdGlvbiBhbmQgdGhlIHRlc3QgcG9pbnQsIFgxID0gWDIgPSBYMyA9IDAuDQoNCmBgYHtyfQ0KeDAgPSBjKDAsMCwwKQ0KZGlzdC5jIDwtIGZ1bmN0aW9uKHgxLHgyLHgzKXsNCiAgc3VtKChjKHgxLHgyLHgzKS14MCkqKjIpDQp9DQojZGlzdC5jKHRhYmxlN1ssMV0sdGFibGU3WywyXSx0YWJsZTdbLDNdKQ0KdGFibGU3JT4lDQogIG11dGF0ZShkaXN0LnRvLng9cG1hcF9kYmwobGlzdCh0YWJsZTckeDEsdGFibGU3JHgyLHRhYmxlNyR4MyksZGlzdC5jKSklPiUjd293IHRoYXQgdG9vayBhIGxvbiB0aW1lIHRvIGZpZ3VyZSBvdXQuIEkgZmVlbHMgc2lsbHkuDQphcnJhbmdlKGRpc3QudG8ueCkNCg0KYGBgDQoNCiMjIyMgKGIpIFdoYXQgaXMgb3VyIHByZWRpY3Rpb24gd2l0aCBLID0gMT8gV2h5Pw0KDQpHcmVlbiwgdGhlIGNsb3Nlc3QgMSBpcyBncmVlbi4NCg0KIyMjIyAoYykgV2hhdCBpcyBvdXIgcHJlZGljdGlvbiB3aXRoIEsgPSAzPyBXaHk/DQoNClJlZC4gQ2xvc2VzdCB0aHJlZSBoYXZlIGdyZWVuIGdyZWVuIHJlZCBzbyB0aGVyZSBhcmUgbW9yZSBncmVlbnMgdGhlbiByZWQuDQoNCiMjIyMgKGQpIElmIHRoZSBCYXllcyBkZWNpc2lvbiBib3VuZGFyeSBpbiB0aGlzIHByb2JsZW0gaXMgaGlnaGx5IG5vbmxpbmVhciwgdGhlbiB3b3VsZCB3ZSBleHBlY3QgdGhlIGJlc3QgdmFsdWUgZm9yIEsgdG8gYmUgbGFyZ2Ugb3Igc21hbGw/IFdoeT8NCg0KU21hbGwuIEFzIHdlIHNhdyBpbiBUaHVyc2RheSBsZWN0dXJlLCBhIGxhcmdlIEsgdmFsdWUgd2lsbCBjcmVhdGUgYSBsaW5lIGF2ZXJhZ2luZyB0aGUgc2V0cy4NCg0KIyMjIDguIFRoaXMgZXhlcmNpc2UgcmVsYXRlcyB0byB0aGUgQ29sbGVnZSBkYXRhIHNldCwgd2hpY2ggY2FuIGJlIGZvdW5kIGluIHRoZSBmaWxlIENvbGxlZ2UuY3N2LiBJdCBjb250YWlucyBhIG51bWJlciBvZiB2YXJpYWJsZXMgZm9yIDc3NyBkaWZmZXJlbnQgdW5pdmVyc2l0aWVzIGFuZCBjb2xsZWdlcyBpbiB0aGUgVVMuDQoNCiMjIyMgKGEpIFVzZSB0aGUgcmVhZC5jc3YoKSBmdW5jdGlvbiB0byByZWFkIHRoZSBkYXRhIGludG8gUi4gQ2FsbCB0aGUgbG9hZGVkIGRhdGEgY29sbGVnZS4gTWFrZSBzdXJlIHRoYXQgeW91IGhhdmUgdGhlIGRpcmVjdG9yeSBzZXQgdG8gdGhlIGNvcnJlY3QgbG9jYXRpb24gZm9yIHRoZSBkYXRhDQoNCmBgYHtyfQ0KY29sbGVnZSA9IHJlYWQuY3N2KCJDb2xsZWdlLmNzdiIpDQpoZWFkKGNvbGxlZ2UpDQpgYGANCg0KIyMjIyAoYikgIExvb2sgYXQgdGhlIGRhdGEgdXNpbmcgdGhlIGZpeCgpIGZ1bmN0aW9uLiBZb3Ugc2hvdWxkIG5vdGljZSB0aGF0IHRoZSBmaXJzdCBjb2x1bW4gaXMganVzdCB0aGUgbmFtZSBvZiBlYWNoIHVuaXZlcnNpdHkuIFdlIGRvbuKAmXQgcmVhbGx5IHdhbnQgUiB0byB0cmVhdCB0aGlzIGFzIGRhdGEuIEhvd2V2ZXIsIGl0IG1heSBiZSBoYW5keSB0byBoYXZlIHRoZXNlIG5hbWVzIGZvciBsYXRlci4NCg0KYGBge3J9DQpyb3duYW1lcyhjb2xsZWdlKSA9IGNvbGxlZ2VbLDFdDQpmaXgoY29sbGVnZSkNCmNvbGxlZ2UgPWNvbGxlZ2UgWywtMV0NCmZpeChjb2xsZWdlKQ0KYGBgDQoNCiMjIyMgKGMpDQoNCmBgYHtyfQ0Kc3VtbWFyeShjb2xsZWdlKQ0KYGBgDQpgYGB7cn0NCnBhaXJzKGNvbGxlZ2VbLDI6MTBdKSAjVGhpcyBpcyBhIHRlcnJpYmxlIHBpY3R1cmUuIENhbiBnZyBwbG90IGRvIHRoaXM/DQpgYGANCg0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gY29sbGVnZSkgKyANCiAgZ2VvbV9ib3hwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFByaXZhdGUsIHkgPSBPdXRzdGF0ZSkpDQpgYGANCg0KYGBge3J9DQpFbGl0ZT1yZXAoIk5vIixucm93KGNvbGxlZ2UgKSkNCkVsaXRlW2NvbGxlZ2UkVG9wMTBwZXJjID41MF09IiBZZXMiDQpFbGl0ZT1hcy5mYWN0b3IoRWxpdGUpDQpjb2xsZWdlPWRhdGEuZnJhbWUoIGNvbGxlZ2UgLCBFbGl0ZSkNCnN1bW1hcnkoY29sbGVnZSkNCmBgYA0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGNvbGxlZ2UpICsgDQogIGdlb21fYm94cGxvdChtYXBwaW5nID0gYWVzKHggPSBFbGl0ZSwgeSA9IE91dHN0YXRlKSkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gY29sbGVnZSkgKyANCiAgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyh4ID0gT3V0c3RhdGUpLGJpbnMgPSA1MCkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gY29sbGVnZSkgKyANCiAgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyh4ID0gT3V0c3RhdGUpLGJpbnMgPSAxMCkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gY29sbGVnZSkgKyANCiAgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyh4ID0gQWNjZXB0KSxiaW5zID0gMTAwKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChkYXRhID0gY29sbGVnZSkgKyANCiAgZ2VvbV9ib3hwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFByaXZhdGUsIHkgPSBHcmFkLlJhdGUpKQ0KYGBgDQpQcml2YXRlIHNjaG9vbHMgaGF2ZSBhIG11Y2ggaGlnaGVyIGdyYWR1YXRpb24gcmF0ZS4gQ291bGQgaXQgYmUgdGhhdCB0aGVyZSBpcyBzb21lIHNvcnQgb2YgcHJlc3N1cmUgdG8gcGFzcyBpbiBwcml2YXRlIHNjaG9vbHMhPw0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gY29sbGVnZSkgKyANCiAgZ2VvbV9ib3hwbG90KG1hcHBpbmcgPSBhZXMoeCA9IFByaXZhdGUsIHkgPSBFeHBlbmQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSkNCmBgYA0KDQpOb3QgcmVhbGx5IGEgc3VycHJpc2UsIGJ1dCBwcml2YXRlIHNjaG9vbHMgc3BlbmQgbW9yZSBwZXIgc3R1ZGVudCBhbmQgdGhlIHZhcmlhbmNlIG9mIHdoYXQgdGhleSBzcGVuZCBpcyAqbXVjaCogaGlnaGVyLg0KDQojIyAzLjc6IDMsIDEwDQoNCiMjIyAzLiBTdXBwb3NlIHdlIGhhdmUgYSBkYXRhIHNldCB3aXRoIGZpdmUgcHJlZGljdG9ycywgWDEgPSBHUEEsIFgyID0gSVEsIFgzID0gR2VuZGVyICgxIGZvciBGZW1hbGUgYW5kIDAgZm9yIE1hbGUpLCBYNCA9IEludGVyYWN0aW9uIGJldHdlZW4gR1BBIGFuZCBJUSwgYW5kIFg1ID0gSW50ZXJhY3Rpb24gYmV0d2VlbiBHUEEgYW5kIEdlbmRlci4gVGhlIHJlc3BvbnNlIGlzIHN0YXJ0aW5nIHNhbGFyeSBhZnRlciBncmFkdWF0aW9uIChpbiB0aG91c2FuZHMgb2YgZG9sbGFycykuIFN1cHBvc2Ugd2UgdXNlIGxlYXN0IHNxdWFyZXMgdG8gZml0IHRoZSBtb2RlbCwgYW5kIGdldCDOssuGMCA9IDUwLCDOssuGMSA9IDIwLCDOssuGMiA9IDAuMDcsIM6yy4YzID0gMzUsIM6yy4Y0ID0gMC4wMSwgzrLLhjUgPSDiiJIxMC4NCg0KIyMjIyAoYSkgV2hpY2ggYW5zd2VyIGlzIGNvcnJlY3QsIGFuZCB3aHk/Zmd2DQoNCioqaS4gRm9yIGEgZml4ZWQgdmFsdWUgb2YgSVEgYW5kIEdQQSwgbWFsZXMgZWFybiBtb3JlIG9uIGF2ZXJhZ2UgdGhhbiBmZW1hbGVzLioqDQoNCioqaWkuIEZvciBhIGZpeGVkIHZhbHVlIG9mIElRIGFuZCBHUEEsIGZlbWFsZXMgZWFybiBtb3JlIG9uIGF2ZXJhZ2UgdGhhbiBtYWxlcy4qKg0KDQoNCioqaWlpLiBGb3IgYSBmaXhlZCB2YWx1ZSBvZiBJUSBhbmQgR1BBLCBtYWxlcyBlYXJuIG1vcmUgb24gYXZlcmFnZSB0aGFuIGZlbWFsZXMgcHJvdmlkZWQgdGhhdCB0aGUgR1BBIGlzIGhpZ2ggZW5vdWdoLioqDQoNClRydWUhIGlmIHdlIGNvbnNpZGVyIHRoZSBmdW5jdGlvbiB5ID0gNTAgKyAyMCAqIGdwYSArIC4wNyAqIGlxICsgMzUgKiBnZW5kZXIgKyAuMDEgKiAoZ3BhICogaXEpIC0xMCAqIChncGEgKiBnZW5kZXIpIHNvIGlmIHdlIGhhdmUgYW4gaXEgb2YgMTAwLCB0aGUgaW50ZXJhY3Rpb24gdGVybSB3aWxsIHN1YnRyYWN0IDEwMCB3aGlsZSBiZWluZyBhIHdvbWVuIG9ubHkgYWRkcyAzNS4NCg0KKippdi4gRm9yIGEgZml4ZWQgdmFsdWUgb2YgSVEgYW5kIEdQQSwgZmVtYWxlcyBlYXJuIG1vcmUgb24gYXZlcmFnZSB0aGFuIG1hbGVzIHByb3ZpZGVkIHRoYXQgdGhlIEdQQSBpcyBoaWdoIGVub3VnaC4qKg0KDQojIyMjIChiKSBQcmVkaWN0IHRoZSBzYWxhcnkgb2YgYSBmZW1hbGUgd2l0aCBJUSBvZiAxMTAgYW5kIGEgR1BBIG9mIDQuMC4NCg0KYGBge3J9DQo1MCsyMCo0Ky4wNyoxMTArMzUqMSsuMDEqKDQgKiAxMTApIC0xMCooNCoxKQ0KYGBgDQoNCg0KIyMjIyAoYykgVHJ1ZSBvciBmYWxzZTogU2luY2UgdGhlIGNvZWZmaWNpZW50IGZvciB0aGUgR1BBL0lRIGludGVyYWN0aW9uIHRlcm0gaXMgdmVyeSBzbWFsbCwgdGhlcmUgaXMgdmVyeSBsaXR0bGUgZXZpZGVuY2Ugb2YgYW4gaW50ZXJhY3Rpb24gZWZmZWN0LiBKdXN0aWZ5IHlvdXIgYW5zd2VyLg0KDQpGYWxzZSwgdGhlcmUgY291bGQgYmUgYW4gaW50ZXJhY3Rpb24gZWZmZWN0IGlmIHRoZSBwdmFsIGlzIHNtYWxsLCBidXQgaXQganVzdCBkb2Vzbid0IGhhdmUgYSB2ZXJ5IGxhcmdlIGNvZWZmaWNpZW50Lg0KDQojIyMgMTAuIFRoaXMgcXVlc3Rpb24gc2hvdWxkIGJlIGFuc3dlcmVkIHVzaW5nIHRoZSBDYXJzZWF0cyBkYXRhIHNldC4NCg0KYGBge3J9DQpsaWJyYXJ5KElTTFIpDQpkYXRhKCJDYXJzZWF0cyIpDQpjYXIgPSBDYXJzZWF0cw0KY2FyDQpgYGANCg0KIyMjIyAoYSkgRml0IGEgbXVsdGlwbGUgcmVncmVzc2lvbiBtb2RlbCB0byBwcmVkaWN0IFNhbGVzIHVzaW5nIFByaWNlLCBVcmJhbiwgYW5kIFVTLg0KDQpgYGB7cn0NCnN1bW1hcnkobW9kZWwxIDwtIGxtKFNhbGVzflByaWNlICsgVXJiYW4gKyBVUywgZGF0YSA9IGNhcikpDQpgYGANCg0KDQojIyMjIChiKSBQcm92aWRlIGFuIGludGVycHJldGF0aW9uIG9mIGVhY2ggY29lZmZpY2llbnQgaW4gdGhlIG1vZGVsLiBCZSBjYXJlZnVs4oCUc29tZSBvZiB0aGUgdmFyaWFibGVzIGluIHRoZSBtb2RlbCBhcmUgcXVhbGl0YXRpdmUhDQoNCiMjIyMgKGMpIFdyaXRlIG91dCB0aGUgbW9kZWwgaW4gZXF1YXRpb24gZm9ybSwgYmVpbmcgY2FyZWZ1bCB0byBoYW5kbGUgdGhlIHF1YWxpdGF0aXZlIHZhcmlhYmxlcyBwcm9wZXJseS4NCg0KU2FsZXMgPSAxMy4wNDM0NjkgLSAuMDU0NDU5ICogUHJpY2UgLSAwLjAyMTkxNiAoaWYgdXJiYW4pICsgMS4yMDA1NzMgKGlmIFVTKQ0KDQojIyMjIChkKSBGb3Igd2hpY2ggb2YgdGhlIHByZWRpY3RvcnMgY2FuIHlvdSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBIMCA6IM6yaiA9IDA/DQoNClByaWNlLCBVUw0KDQojIyMjIChlKSBPbiB0aGUgYmFzaXMgb2YgeW91ciByZXNwb25zZSB0byB0aGUgcHJldmlvdXMgcXVlc3Rpb24sIGZpdCBhIHNtYWxsZXIgbW9kZWwgdGhhdCBvbmx5IHVzZXMgdGhlIHByZWRpY3RvcnMgZm9yIHdoaWNoIHRoZXJlIGlzIGV2aWRlbmNlIG9mIGFzc29jaWF0aW9uIHdpdGggdGhlIG91dGNvbWUuDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RlbDIgPC0gbG0oU2FsZXN+UHJpY2UgKyBVUywgZGF0YSA9IGNhcikpDQpgYGANCg0KIyMjIyAoZikgSG93IHdlbGwgZG8gdGhlIG1vZGVscyBpbiAoYSkgYW5kIChlKSBmaXQgdGhlIGRhdGE/DQoNClZlcnkgcG9vcmx5LiBSIHNxdSBpcyB0ZXJyaWJsZSBmb3IgYm90aCBtb2RlbHMuDQoNCiMjIyMgKGcpIFVzaW5nIHRoZSBtb2RlbCBmcm9tIChlKSwgb2J0YWluIDk1ICUgY29uZmlkZW5jZSBpbnRlcnZhbHMgZm9yIHRoZSBjb2VmZmljaWVudChzKS4NCg0KYGBge3J9DQpjb25maW50KG1vZGVsMikNCmBgYA0KDQojIyMjIChoKSBJcyB0aGVyZSBldmlkZW5jZSBvZiBvdXRsaWVycyBvciBoaWdoIGxldmVyYWdlIG9ic2VydmF0aW9ucyBpbiB0aGUgbW9kZWwgZnJvbSAoZSk/DQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMiwyKSkNCnBsb3QobW9kZWwyKQ0KYGBgDQpOby4NCg0KIyMgNC43OiAxLCAzLCAqKjQqKiwgOSwgKioxMGEtZCoqDQoNCiMjIyAxLiBVc2luZyBhIGxpdHRsZSBiaXQgb2YgYWxnZWJyYSwgcHJvdmUgdGhhdCAoNC4yKSBpcyBlcXVpdmFsZW50IHRvICg0LjMpLiBJbiBvdGhlciB3b3JkcywgdGhlIGxvZ2lzdGljIGZ1bmN0aW9uIHJlcHJlc2VudGF0aW9uIGFuZCBsb2dpdCByZXByZXNlbnRhdGlvbiBmb3IgdGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgYXJlIGVxdWl2YWxlbnQuDQoNClRoaXMgaXMgc3RyYWlnaHQgZm9yd2FyZCBhbmQgSSdkIGhhdmUgdG8gaW5zZXJ0IGEgcGljdHVyZSBzby4uLg0KDQojIyMgMy4gVGhpcyBwcm9ibGVtIHJlbGF0ZXMgdG8gdGhlIFFEQSBtb2RlbCwgaW4gd2hpY2ggdGhlIG9ic2VydmF0aW9ucyB3aXRoaW4gZWFjaCBjbGFzcyBhcmUgZHJhd24gZnJvbSBhIG5vcm1hbCBkaXN0cmlidXRpb24gd2l0aCBhIGNsYXNzc3BlY2lmaWMgbWVhbiB2ZWN0b3IgYW5kIGEgY2xhc3Mgc3BlY2lmaWMgY292YXJpYW5jZSBtYXRyaXguIFdlIGNvbnNpZGVyIHRoZSBzaW1wbGUgY2FzZSB3aGVyZSBwID0gMTsgaS5lLiB0aGVyZSBpcyBvbmx5IG9uZSBmZWF0dXJlLiBTdXBwb3NlIHRoYXQgd2UgaGF2ZSBLIGNsYXNzZXMsIGFuZCB0aGF0IGlmIGFuIG9ic2VydmF0aW9uIGJlbG9uZ3MgdG8gdGhlIGt0aCBjbGFzcyB0aGVuIFggY29tZXMgZnJvbSBhIG9uZS1kaW1lbnNpb25hbCBub3JtYWwgZGlzdHJpYnV0aW9uLCBYIOKIvCBOKMK1aywgz4MyIGspLiBSZWNhbGwgdGhhdCB0aGUgZGVuc2l0eSBmdW5jdGlvbiBmb3IgdGhlIG9uZS1kaW1lbnNpb25hbCBub3JtYWwgZGlzdHJpYnV0aW9uIGlzIGdpdmVuIGluICg0LjExKS4gUHJvdmUgdGhhdCBpbiB0aGlzIGNhc2UsIHRoZSBCYXllc+KAmSBjbGFzc2lmaWVyIGlzIG5vdCBsaW5lYXIuIEFyZ3VlIHRoYXQgaXQgaXMgaW4gZmFjdCBxdWFkcmF0aWMuIEhpbnQ6IEZvciB0aGlzIHByb2JsZW0sIHlvdSBzaG91bGQgZm9sbG93IHRoZSBhcmd1bWVudHMgbGFpZCBvdXQgaW4gU2VjdGlvbiA0LjQuMiwgYnV0IHdpdGhvdXQgbWFraW5nIHRoZSBhc3N1bXB0aW9uIHRoYXQgz4NeMjEgPSAuLi4gPSDPg14ySy4NCg0KV2UgZW5kIHVwIHdpdGggYSB4XjIgZnJvbSB0aGUgZXhwYW5zaW9uIHRoYXQgaXMgbXVsdGlwbGllZCBieSBzaWdtYV9rIHdoaWNoIG11c3Qgc3RheSBpbiBvdXIgZXF1YXRpb24gc2luY2UgaXQgaXMgaW4gdGVybXMgb2Ygay4NCg0KIyMjIDQuIFdoZW4gdGhlIG51bWJlciBvZiBmZWF0dXJlcyBwIGlzIGxhcmdlLCB0aGVyZSB0ZW5kcyB0byBiZSBhIGRldGVyaW9yYXRpb24gaW4gdGhlIHBlcmZvcm1hbmNlIG9mIEtOTiBhbmQgb3RoZXIgbG9jYWwgYXBwcm9hY2hlcyB0aGF0IHBlcmZvcm0gcHJlZGljdGlvbiB1c2luZyBvbmx5IG9ic2VydmF0aW9ucyB0aGF0IGFyZSBuZWFyIHRoZSB0ZXN0IG9ic2VydmF0aW9uIGZvciB3aGljaCBhIHByZWRpY3Rpb24gbXVzdCBiZSBtYWRlLiBUaGlzIHBoZW5vbWVub24gaXMga25vd24gYXMgdGhlIGN1cnNlIG9mIGRpbWVuc2lvbmFsaXR5LCBhbmQgaXQgdGllcyBpbnRvIHRoZSBmYWN0IHRoYXQgY3Vyc2Ugb2YgZGlub24tcGFyYW1ldHJpYyBhcHByb2FjaGVzIG9mdGVuIHBlcmZvcm0gcG9vcmx5IHdoZW4gcCBpcyBsYXJnZS4gV2Ugd2lsbCBub3cgaW52ZXN0aWdhdGUgdGhpcyBjdXJzZS4NCg0KIyMjIyAoYSkgU3VwcG9zZSB0aGF0IHdlIGhhdmUgYSBzZXQgb2Ygb2JzZXJ2YXRpb25zLCBlYWNoIHdpdGggbWVhc3VyZW1lbnRzIG9uIHAgPSAxIGZlYXR1cmUsIFguIFdlIGFzc3VtZSB0aGF0IFggaXMgdW5pZm9ybWx5IChldmVubHkpIGRpc3RyaWJ1dGVkIG9uIFswLCAxXS4gQXNzb2NpYXRlZCB3aXRoIGVhY2ggb2JzZXJ2YXRpb24gaXMgYSByZXNwb25zZSB2YWx1ZS4gU3VwcG9zZSB0aGF0IHdlIHdpc2ggdG8gcHJlZGljdCBhIHRlc3Qgb2JzZXJ2YXRpb27igJlzIHJlc3BvbnNlIHVzaW5nIG9ubHkgb2JzZXJ2YXRpb25zIHRoYXQgYXJlIHdpdGhpbiAxMCAlIG9mIHRoZSByYW5nZSBvZiBYIGNsb3Nlc3QgdG8gdGhhdCB0ZXN0IG9ic2VydmF0aW9uLiBGb3IgaW5zdGFuY2UsIGluIG9yZGVyIHRvIHByZWRpY3QgdGhlIHJlc3BvbnNlIGZvciBhIHRlc3Qgb2JzZXJ2YXRpb24gd2l0aCBYID0gMC42LCB3ZSB3aWxsIHVzZSBvYnNlcnZhdGlvbnMgaW4gdGhlIHJhbmdlIFswLjU1LCAwLjY1XS4gT24gYXZlcmFnZSwgd2hhdCBmcmFjdGlvbiBvZiB0aGUgYXZhaWxhYmxlIG9ic2VydmF0aW9ucyB3aWxsIHdlIHVzZSB0byBtYWtlIHRoZSBwcmVkaWN0aW9uPw0KDQoxMCUNCg0KDQojIyMjIChiKSBOb3cgc3VwcG9zZSB0aGF0IHdlIGhhdmUgYSBzZXQgb2Ygb2JzZXJ2YXRpb25zLCBlYWNoIHdpdGggbWVhc3VyZW1lbnRzIG9uIHAgPSAyIGZlYXR1cmVzLCBYMSBhbmQgWDIuIFdlIGFzc3VtZSB0aGF0IChYMSwgWDIpIGFyZSB1bmlmb3JtbHkgZGlzdHJpYnV0ZWQgb24gWzAsIDFdIMOXIFswLCAxXS4gV2Ugd2lzaCB0byBwcmVkaWN0IGEgdGVzdCBvYnNlcnZhdGlvbuKAmXMgcmVzcG9uc2UgdXNpbmcgb25seSBvYnNlcnZhdGlvbnMgdGhhdCBhcmUgd2l0aGluIDEwICUgb2YgdGhlIHJhbmdlIG9mIFgxIGFuZCB3aXRoaW4gMTAgJSBvZiB0aGUgcmFuZ2Ugb2YgWDIgY2xvc2VzdCB0byB0aGF0IHRlc3Qgb2JzZXJ2YXRpb24uIEZvciBpbnN0YW5jZSwgaW4gb3JkZXIgdG8gcHJlZGljdCB0aGUgcmVzcG9uc2UgZm9yIGEgdGVzdCBvYnNlcnZhdGlvbiB3aXRoIFgxID0gMC42IGFuZCBYMiA9IDAuMzUsIHdlIHdpbGwgdXNlIG9ic2VydmF0aW9ucyBpbiB0aGUgcmFuZ2UgWzAuNTUsIDAuNjVdIGZvciBYMSBhbmQgaW4gdGhlIHJhbmdlIFswLjMsIDAuNF0gZm9yIFgyLiBPbiBhdmVyYWdlLCB3aGF0IGZyYWN0aW9uIG9mIHRoZSBhdmFpbGFibGUgb2JzZXJ2YXRpb25zIHdpbGwgd2UgdXNlIHRvIG1ha2UgdGhlIHByZWRpY3Rpb24/DQoNCjEwJSAqIDEwJSA9IDElDQoNCiMjIyMgKGMpIE5vdyBzdXBwb3NlIHRoYXQgd2UgaGF2ZSBhIHNldCBvZiBvYnNlcnZhdGlvbnMgb24gcCA9IDEwMCBmZWF0dXJlcy4gQWdhaW4gdGhlIG9ic2VydmF0aW9ucyBhcmUgdW5pZm9ybWx5IGRpc3RyaWJ1dGVkIG9uIGVhY2ggZmVhdHVyZSwgYW5kIGFnYWluIGVhY2ggZmVhdHVyZSByYW5nZXMgaW4gdmFsdWUgZnJvbSAwIHRvIDEuIFdlIHdpc2ggdG8gcHJlZGljdCBhIHRlc3Qgb2JzZXJ2YXRpb27igJlzIHJlc3BvbnNlIHVzaW5nIG9ic2VydmF0aW9ucyB3aXRoaW4gdGhlIDEwICUgb2YgZWFjaCBmZWF0dXJl4oCZcyByYW5nZSB0aGF0IGlzIGNsb3Nlc3QgdG8gdGhhdCB0ZXN0IG9ic2VydmF0aW9uLiBXaGF0IGZyYWN0aW9uIG9mIHRoZSBhdmFpbGFibGUgb2JzZXJ2YXRpb25zIHdpbGwgd2UgdXNlIHRvIG1ha2UgdGhlIHByZWRpY3Rpb24/DQoNCjEwJV4xMDANCg0KYGBge3J9DQouMSoqMTAwDQpgYGANCg0KDQojIyMjIChkKSBVc2luZyB5b3VyIGFuc3dlcnMgdG8gcGFydHMgKGEp4oCTKGMpLCBhcmd1ZSB0aGF0IGEgZHJhd2JhY2sgb2YgS05OIHdoZW4gcCBpcyBsYXJnZSBpcyB0aGF0IHRoZXJlIGFyZSB2ZXJ5IGZldyB0cmFpbmluZyBvYnNlcnZhdGlvbnMg4oCcbmVhcuKAnSBhbnkgZ2l2ZW4gdGVzdCBvYnNlcnZhdGlvbi4NCg0KQXMgcCBpbmNyZWFzZXMsIHRoZSBudW1iZXIgb2Ygb2YgIm5lYXIiIG9ic2VydmF0aW9ucyBkZWNyZWFzZXMgZXhwb25lbnRpYWxseS4NCg0KIyMjIyAoZSkgTm93IHN1cHBvc2UgdGhhdCB3ZSB3aXNoIHRvIG1ha2UgYSBwcmVkaWN0aW9uIGZvciBhIHRlc3Qgb2JzZXJ2YXRpb24gYnkgY3JlYXRpbmcgYSBwLWRpbWVuc2lvbmFsIGh5cGVyY3ViZSBjZW50ZXJlZCBhcm91bmQgdGhlIHRlc3Qgb2JzZXJ2YXRpb24gdGhhdCBjb250YWlucywgb24gYXZlcmFnZSwgMTAgJSBvZiB0aGUgdHJhaW5pbmcgb2JzZXJ2YXRpb25zLiBGb3IgcCA9IDEsIDIsIGFuZCAxMDAsIHdoYXQgaXMgdGhlIGxlbmd0aCBvZiBlYWNoIHNpZGUgb2YgdGhlIGh5cGVyY3ViZT8gQ29tbWVudCBvbiB5b3VyIGFuc3dlci4NCipOb3RlOiBBIGh5cGVyY3ViZSBpcyBhIGdlbmVyYWxpemF0aW9uIG9mIGEgY3ViZSB0byBhbiBhcmJpdHJhcnkgbnVtYmVyIG9mIGRpbWVuc2lvbnMuIFdoZW4gcCA9IDEsIGEgaHlwZXJjdWJlIGlzIHNpbXBseSBhIGxpbmUgc2VnbWVudCwgd2hlbiBwID0gMiBpdCBpcyBhIHNxdWFyZSwgYW5kIHdoZW4gcCA9IDEwMCBpdCBpcyBhIDEwMC1kaW1lbnNpb25hbCBjdWJlLioNCg0KcCA9IDE6IC4xDQpwID0gMjoNCmBgYHtyfQ0KLjEqKigxLzIpDQpgYGANCnA9MTAwOg0KYGBge3J9DQouMSoqKDEvMTAwKQ0KYGBgDQpBcyBwIGluY3JlYXNlcywgd2UgbmVlZCBtb3JlIGFuZCBtb3JlIGRhdGEuIFdoZW4gcCA9IDEwMCwgd2UgbmVlZCB0byB1c2UgYWxtb3N0IG91ciBlbnRpcmUgZGF0YSBzZXQuDQoNCg0KIyMjIDkuIFRoaXMgcHJvYmxlbSBoYXMgdG8gZG8gd2l0aCBvZGRzDQoNCiMjIyMgKGEpIE9uIGF2ZXJhZ2UsIHdoYXQgZnJhY3Rpb24gb2YgcGVvcGxlIHdpdGggYW4gb2RkcyBvZiAwLjM3IG9mIGRlZmF1bHRpbmcgb24gdGhlaXIgY3JlZGl0IGNhcmQgcGF5bWVudCB3aWxsIGluIGZhY3QgZGVmYXVsdD8NCg0KYGBge3J9DQouMzcvKC4zNysxKQ0KYGBgDQoNCg0KDQojIyMjIChiKSBTdXBwb3NlIHRoYXQgYW4gaW5kaXZpZHVhbCBoYXMgYSAxNiAlIGNoYW5jZSBvZiBkZWZhdWx0aW5nIG9uIGhlciBjcmVkaXQgY2FyZCBwYXltZW50LiBXaGF0IGFyZSB0aGUgb2RkcyB0aGF0IHNoZSB3aWxsIGRlZmF1bHQ/DQoNCi4xNiA9IG9kZHMvKDErb2RkcykNCi4xNiArIC4xNm9kZHMgPSBvZGRzDQouMTYgPSAuODRvZGRzDQpvZGRzID0gLjE2Ly44NA0KDQpgYGB7cn0NCi4xNi8uODQNCmBgYA0KU2ltcGx5DQoNCmBgYHtyfQ0KLjE2LygxLS4xNikNCmBgYA0KDQoNCiMjIyAxMC4gVGhpcyBxdWVzdGlvbiBzaG91bGQgYmUgYW5zd2VyZWQgdXNpbmcgdGhlIFdlZWtseSBkYXRhIHNldCwgd2hpY2ggaXMgcGFydCBvZiB0aGUgSVNMUiBwYWNrYWdlLiBUaGlzIGRhdGEgaXMgc2ltaWxhciBpbiBuYXR1cmUgdG8gdGhlIFNtYXJrZXQgZGF0YSBmcm9tIHRoaXMgY2hhcHRlcuKAmXMgbGFiLCBleGNlcHQgdGhhdCBpdCBjb250YWlucyAxLCAwODkgd2Vla2x5IHJldHVybnMgZm9yIDIxIHllYXJzLCBmcm9tIHRoZSBiZWdpbm5pbmcgb2YgMTk5MCB0byB0aGUgZW5kIG9mIDIwMTAuDQoNCmBgYHtyfQ0KZGF0YSgiV2Vla2x5IikNCldlZWtseQ0KYGBgDQoNCg0KIyMjIyAoYSkgUHJvZHVjZSBzb21lIG51bWVyaWNhbCBhbmQgZ3JhcGhpY2FsIHN1bW1hcmllcyBvZiB0aGUgV2Vla2x5IGRhdGEuIERvIHRoZXJlIGFwcGVhciB0byBiZSBhbnkgcGF0dGVybnM/DQoNCmBgYHtyfQ0Kc3VtbWFyeShXZWVrbHkpDQpgYGANCmBgYHtyfQ0KZ2dwbG90KFdlZWtseSkrDQogIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gTGFnMSwgeSA9IFRvZGF5LCBzaGFwZSA9IERpcmVjdGlvbiwgY29sb3IgPSBWb2x1bWUpKQ0KYGBgDQoNCg0KIyMjIyAoYikgVXNlIHRoZSBmdWxsIGRhdGEgc2V0IHRvIHBlcmZvcm0gYSBsb2dpc3RpYyByZWdyZXNzaW9uIHdpdGggRGlyZWN0aW9uIGFzIHRoZSByZXNwb25zZSBhbmQgdGhlIGZpdmUgbGFnIHZhcmlhYmxlcyBwbHVzIFZvbHVtZSBhcyBwcmVkaWN0b3JzLiBVc2UgdGhlIHN1bW1hcnkgZnVuY3Rpb24gdG8gcHJpbnQgdGhlIHJlc3VsdHMuIERvIGFueSBvZiB0aGUgcHJlZGljdG9ycyBhcHBlYXIgdG8gYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudD8gSWYgc28sd2hpY2ggb25lcz8NCg0KYGBge3J9DQpsb2dpdDEgPSBnbG0oRGlyZWN0aW9ufi4gLVRvZGF5IC1ZZWFyLCBkYXRhPVdlZWtseSwgZmFtaWx5PWJpbm9taWFsKQ0Kc3VtbWFyeShsb2dpdDEpDQpgYGANCkxhZyAyIGFwcGVhcnMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4NCg0KIyMjIyAoYykgQ29tcHV0ZSB0aGUgY29uZnVzaW9uIG1hdHJpeCBhbmQgb3ZlcmFsbCBmcmFjdGlvbiBvZiBjb3JyZWN0IHByZWRpY3Rpb25zLiBFeHBsYWluIHdoYXQgdGhlIGNvbmZ1c2lvbiBtYXRyaXggaXMgdGVsbGluZyB5b3UgYWJvdXQgdGhlIHR5cGVzIG9mIG1pc3Rha2VzIG1hZGUgYnkgbG9naXN0aWMgcmVncmVzc2lvbi4NCg0KYGBge3J9DQpXZWVrbHklPiVtdXRhdGUodXAuaGF0ID0gZml0dGVkKGxvZ2l0MSkpJT4lDQogIG11dGF0ZShkaXIuaGF0ID0gdXAuaGF0ID4uNSklPiUNCiAgeHRhYnMofmRpci5oYXQrRGlyZWN0aW9uLCBkYXRhID0gLikNCmBgYA0KYGBge3J9DQooNTQrNTU3KS8oNTQrNDgrNDMwKzU1NykgIyBEb24ndCBmb3JnZXQhIERpYWdvbmFscyBhcmUgY29ycmVjdCBwcmVkaWN0aW9ucywgb2ZmIGRpYWdvbmFscyBhcmUgd3JvbmcuIEZBTFNFIHJlcHJlc2VudHMgYSBwcmVkaWN0aW9uIG9mIERvd24sIFRSVUUgYSBwcmVkaWN0aW9uIG9mIFRSVUUNCmBgYA0KDQoNCiMjIyMgKGQpIE5vdyBmaXQgdGhlIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgdXNpbmcgYSB0cmFpbmluZyBkYXRhIHBlcmlvZCBmcm9tIDE5OTAgdG8gMjAwOCwgd2l0aCBMYWcyIGFzIHRoZSBvbmx5IHByZWRpY3Rvci4gQ29tcHV0ZSB0aGUgY29uZnVzaW9uIG1hdHJpeCBhbmQgdGhlIG92ZXJhbGwgZnJhY3Rpb24gb2YgY29ycmVjdCBwcmVkaWN0aW9ucyBmb3IgdGhlIGhlbGQgb3V0IGRhdGEgKHRoYXQgaXMsIHRoZSBkYXRhIGZyb20gMjAwOSBhbmQgMjAxMCkuDQoNCmBgYHtyfQ0KdHJhaW4gPSBXZWVrbHlbV2Vla2x5JFllYXI8MjAwOSxdDQp0ZXN0ID0gV2Vla2x5W1dlZWtseSRZZWFyPjIwMDgsXQ0KbG9naXQyID0gZ2xtKERpcmVjdGlvbn5MYWcyLCBkYXRhPXRyYWluLCBmYW1pbHk9Ymlub21pYWwpDQpzdW1tYXJ5KGxvZ2l0MikNCmBgYA0KYGBge3J9DQp1cC5oYXQgPSBwcmVkaWN0KGxvZ2l0MiwgdGVzdCwgdHlwZT0icmVzcG9uc2UiKQ0KZGlyLmhhdCA9IHVwLmhhdD4uNQ0KeHRhYnMofmRpci5oYXQrV2Vla2x5JERpcmVjdGlvbltXZWVrbHkkWWVhcj4yMDA4XSkNCmBgYA0KYGBge3J9DQooOSs1NikvKDM0KzUrOSs1NikNCmBgYA0KDQoNCg0KDQoNCg0K