Introduction

This project is intended to extend and supplement what we talked about last week in discussing Linear Regression.

In some of the sections you will be asked to write R code to solve a particular problem. In some you will be asked to answer questions in your own words.

Single Variable Regression

We are trying to fit a straight line to a scatter plot. This means finding the equation of the line that comes closest to all the points. More specifically, the problem becomes, given \(X = \{x_1,x_1,\ldots,x_n\}\) and \(Y = \{y_1, y_2,\dots,y_n\}\) find \(\beta_0\) and \(beta_1\) such that \[ Y_i = \beta_0 + \beta_1 X_i + \epsilon_i\] where, \(\sum_{i}^{n}\epsilon_i = 0\) and \(\sigma^2 = \sum_{i}^{n}\epsilon_i ^2\) is as minimized. This is called least squares regression.

Given estimates of \(\beta_0\) and \(\beta_1\) called \(\hat{\beta_0}\) and \(\hat{\beta_1}\) we define: \[\hat{y_i} = \hat{\beta_0} + \hat{\beta_1}x_i\] The \(\hat{y_i}\) are called the predicted values.

The residuals, \(e_i\), are the differences between the predicted values and the actual values.\[e_i = y_i - \hat{y_i}\]

Note: the residuals are estimates of the \(\epsilon_i\) in the model.

Examining Residual variance.

Please work through this document before continuing with this project.

Section I Working with Simulated scatter plots.

There are four data sets in Project3 data folder the files section, problem1.csv, problem2.csv, problem3.csv, and problem4.csv These data are some of the groups from this data. You will need to load the files into your project using read_csv.

You will also need to read in the file `bdism.csv’ to do the problems in Section II.

problem1 <- read_csv("problem1.csv")

-- Column specification ----------------------------------------------------------------------------------
cols(
  group = col_double(),
  x = col_double(),
  y = col_double()
)
problem2 <- read_csv("problem2.csv")

-- Column specification ----------------------------------------------------------------------------------
cols(
  group = col_double(),
  x = col_double(),
  y = col_double()
)
problem3 <- read_csv("problem3.csv")

-- Column specification ----------------------------------------------------------------------------------
cols(
  group = col_double(),
  x = col_double(),
  y = col_double()
)
problem4 <- read_csv("problem4.csv")

-- Column specification ----------------------------------------------------------------------------------
cols(
  group = col_double(),
  x = col_double(),
  y = col_double()
)
bdism <- read_csv("bdims.csv")

-- Column specification ----------------------------------------------------------------------------------
cols(
  .default = col_double()
)
i Use `spec()` for the full column specifications.

For each of the four files:

  1. plot the scatter plot of x and y (x on the horizontal axis.)
problem1 %>% 
  ggplot(aes (x = x, y = y)) + 
  geom_point()

problem2 %>% 
  ggplot(aes (x = x, y = y)) + 
  geom_point()

problem3 %>% 
  ggplot(aes (x = x, y = y)) + 
  geom_point()

problem4 %>% 
  ggplot(aes (x = x, y = y)) + 
  geom_point()

  1. fit a regression model using lm report the coefficients, and plot the regression line over the scatter plot.
problem1 %>% 
  ggplot(aes (x = x, y = y)) + 
  geom_point() + 
  geom_smooth(method = "lm", color = "red")
`geom_smooth()` using formula 'y ~ x'

problem2 %>% 
  ggplot(aes (x = x, y = y)) + 
  geom_point() + 
  geom_smooth(method = "lm", color = "red")
`geom_smooth()` using formula 'y ~ x'

problem3 %>% 
  ggplot(aes (x = x, y = y)) + 
  geom_point() + 
  geom_smooth(method = "lm", color = "red")
`geom_smooth()` using formula 'y ~ x'

problem4 %>% 
  ggplot(aes (x = x, y = y)) + 
  geom_point() + 
  geom_smooth(method = "lm", color = "red")
`geom_smooth()` using formula 'y ~ x'

  1. Plot the residuals versus x.
problem1 %>% 
  ggplot(aes(x = x, y = y)) +
    geom_point() +
    geom_hline(aes(yintercept = 0), color = "blue")

problem2 %>% 
  ggplot(aes(x = x, y = y)) +
    geom_point() +
    geom_hline(aes(yintercept = 0), color = "blue")

problem3 %>% 
  ggplot(aes(x = x, y = y)) +
    geom_point() +
    geom_hline(aes(yintercept = 0), color = "blue")

problem4 %>% 
  ggplot(aes(x = x, y = y)) +
    geom_point() +
    geom_hline(aes(yintercept = 0), color = "blue")

Record any observations you have in this document.

I noticed that only problem 1 and problem 2 had more two or more points at the x intercept. Problems 1 and 3 on the other hand were the only two that had correlations.

  1. Calculate the correlation between x and y.
x_1 <- problem1$x
y_1 <- problem1$y
cor(x_1,y_1)
[1] -0.8998508
x_2 <- problem2$x
y_2 <- problem2$y
cor(x_2,y_2)
[1] 2.961786e-16
x_3 <- problem3$x
y_3 <- problem3$y
cor(x_3,y_3)
[1] 1
x_4 <- problem4$x
y_4 <- problem4$y
cor(x_4,y_4)
[1] 0.4967192
  1. Does the calculation indicate a strong linear relationship between x and y?

Problem 1 has a strong positive linear relationship. Problem 2 has no linear relationship. Problem 3 has a strong negative linear relationship. Problem 4 has a weak linear relationship.

  1. Normalize the x and y data, this means calculate the z-score for each \(x_i\) and \(y_i\), it is possible to do this with one line of R code.

Hint the z-score of a vector of data, x, is the vector \(z\) given by \(z = \frac{x - \bar{x}}{s_x}\) where \(s_x\) is the standard deviation of \(x\).

fit_1 <- lm( y_1 ~  x_1, data = problem1)
summary(fit_1)

Call:
lm(formula = y_1 ~ x_1, data = problem1)

Residuals:
     Min       1Q   Median       3Q      Max 
-28.2072  -7.7558   0.3587   7.9145  23.7530 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 13.52478    1.48347   9.117 1.12e-13 ***
x_1         -0.80463    0.04565 -17.626  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 11.37 on 73 degrees of freedom
Multiple R-squared:  0.8097,    Adjusted R-squared:  0.8071 
F-statistic: 310.7 on 1 and 73 DF,  p-value: < 2.2e-16
x_1
 [1] -15.7438027   6.3466511  24.5400111 -22.0203522  22.4608333  16.9940902  18.8187851  52.8481370
 [9] -24.2222947  57.8231678  -8.5777927 -21.3302128  -7.6398302  24.3375282  21.0175083   5.8473378
[17] -15.4495719  -5.3920128  56.4023496  22.5937831  -3.0899628 -15.0959242   9.2769701 -38.9936697
[25]   0.0129814  -8.4553978  54.3003207  49.3982151  13.6214104 -21.5138158  45.7206161  44.1084248
[33]  40.0146007  40.3045708   4.3797226  39.2820119  58.9118136  17.2623165 -16.3163644  42.1941206
[41]  41.9547268   5.7547167  72.0631999 -10.2215924  27.4984446 -58.7582354  10.6472258  53.3185447
[49]   0.9669828 -13.6724884  39.9856838 -10.7115498  24.8138088 -41.3297024 -30.5770295   1.0328095
[57] -18.1712121  60.9507155  46.2760723  -9.9096913  34.9260997  46.3004749  24.4574800  27.6148963
[65]  54.7531328   0.1320696   2.1786192  47.5187225 -26.5372182  22.1445153  14.9662584  31.4142112
[73]  49.7985232  24.8228289  23.6502614
mean(x_1)
[1] 15.13373
sd(x_1)
[1] 28.95073
z_score_1 =  (x_1 - mean(x_1))/sd(x_1)
z_score_1
 [1] -1.06655437 -0.30351828  0.32490658 -1.28335543  0.25308878  0.06425960  0.12728719  1.30271002
 [9] -1.35941370  1.47455475 -0.81903006 -1.25951702 -0.78663149  0.31791252  0.20323426 -0.32076528
[17] -1.05639122 -0.70898864  1.42547764  0.25768106 -0.62947252 -1.04417572 -0.20230084 -1.86963827
[25] -0.52229236 -0.81480237  1.35287053  1.18354475 -0.05223762 -1.26585894  1.05651518  1.00082777
[33]  0.85942119  0.86943717 -0.37145882  0.83411652  1.51215814  0.07352452 -1.08633148  0.93470495
[41]  0.92643594 -0.32396455  1.96642596 -0.87580927  0.42709513 -2.55233483 -0.15497024  1.31895858
[49] -0.48933977 -0.99500819  0.85842236 -0.89273311  0.33436394 -1.95032820 -1.57891539 -0.48706602
[57] -1.15040059  1.58258475  1.07570144 -0.86503576  0.68365704  1.07654433  0.32205583  0.43111754
[65]  1.36851131 -0.51817888 -0.44748811  1.11862436 -1.43937449  0.24216270 -0.00578463  0.56235135
[73]  1.19737196  0.33467551  0.29417334
  1. Using lm calculate the regression coefficients. What do you notice?
summary(lm(x_1 ~ y_1, data = problem1)) 

Call:
lm(formula = x_1 ~ y_1, data = problem1)

Residuals:
    Min      1Q  Median      3Q     Max 
-31.914  -6.822  -0.336   7.087  27.507 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  16.4901     1.4702   11.22   <2e-16 ***
y_1          -1.0063     0.0571  -17.63   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 12.71 on 73 degrees of freedom
Multiple R-squared:  0.8097,    Adjusted R-squared:  0.8071 
F-statistic: 310.7 on 1 and 73 DF,  p-value: < 2.2e-16
  1. Calculate Total Variation and \(R^2\)
fit_1 <- lm(x_1 ~ y_1, data = problem1)
summary(fit_1)

Call:
lm(formula = x_1 ~ y_1, data = problem1)

Residuals:
    Min      1Q  Median      3Q     Max 
-31.914  -6.822  -0.336   7.087  27.507 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  16.4901     1.4702   11.22   <2e-16 ***
y_1          -1.0063     0.0571  -17.63   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 12.71 on 73 degrees of freedom
Multiple R-squared:  0.8097,    Adjusted R-squared:  0.8071 
F-statistic: 310.7 on 1 and 73 DF,  p-value: < 2.2e-16
df <- nrow(problem1) - 1
df
[1] 74
res_var1 = sum(residuals(fit_1)^2)
x_hat1 = predict(fit_1)
reg_var1 = sum((x_hat1 - mean(x_1))^2)
tot_var1 = sum((x_1 - mean(x_1))^2)
tot_var1
[1] 62022.72
res_var1 + reg_var1
[1] 62022.72
tot_var1 - (res_var1 + reg_var1)
[1] -2.182787e-11
Rsq = reg_var1/tot_var1
Rsq
[1] 0.8097315
cor(x_1,y_1)^2 #square of the correlation coefficient
[1] 0.8097315
Rsq - cor(x_1,y_1)^2
[1] 4.440892e-16

#8.b)

fit_2 <- lm(x_2 ~ y_2, data = problem2)
summary(fit_2)

Call:
lm(formula = x_2 ~ y_2, data = problem2)

Residuals:
   Min     1Q Median     3Q    Max 
 -45.0  -22.5    0.0   22.5   45.0 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 4.500e+01  1.191e+01   3.778 0.000975 ***
y_2         1.474e-15  1.170e+00   0.000 1.000000    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 28.19 on 23 degrees of freedom
Multiple R-squared:  4.419e-32, Adjusted R-squared:  -0.04348 
F-statistic: 1.016e-30 on 1 and 23 DF,  p-value: 1
res_var2 = sum(residuals(fit_2)^2)
x_hat2 = predict(fit_2)
reg_var2 = sum((x_hat2 - mean(x_2))^2)
tot_var2 = sum((x_2 - mean(x_2))^2)
tot_var2
[1] 18281.25
res_var2 + reg_var2
[1] 18281.25
tot_var2 - (res_var2 + reg_var2)
[1] 0
Rsq2 = reg_var2/tot_var2
Rsq2
[1] 8.008893e-32
cor(x_2,y_2)^2 #square of the correlation coefficient
[1] 8.772177e-32
Rsq2 - cor(x_2,y_2)^2
[1] -7.632839e-33

#8.c)

fit_3 <- lm(x_3 ~ y_3, data = problem3)
summary(fit_3)
Warning in summary.lm(fit_3) :
  essentially perfect fit: summary may be unreliable

Call:
lm(formula = x_3 ~ y_3, data = problem3)

Residuals:
       Min         1Q     Median         3Q        Max 
-4.956e-16 -2.600e-19  8.510e-18  1.609e-17  5.663e-17 

Coefficients:
              Estimate Std. Error    t value Pr(>|t|)    
(Intercept) -1.256e-16  1.896e-17 -6.626e+00 2.76e-08 ***
y_3          1.000e+00  3.405e-17  2.937e+16  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 7.402e-17 on 48 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 8.625e+32 on 1 and 48 DF,  p-value: < 2.2e-16
res_var3 = sum(residuals(fit_3)^2)
x_hat3 = predict(fit_3)
reg_var3 = sum((x_hat3 - mean(x_3))^2)
tot_var3 = sum((x_3 - mean(x_3))^2)
tot_var3
[1] 4.725709
res_var3 + reg_var3
[1] 4.725709
tot_var3 - (res_var3 + reg_var3)
[1] -2.664535e-15
Rsq3 = reg_var3/tot_var3
Rsq3
[1] 1
cor(x_3,y_3)^2 #square of the correlation coefficient
[1] 1
Rsq3 - cor(x_3,y_3)^2
[1] 6.661338e-16

8.d)

fit_4 <- lm(x_4 ~ y_4, data = problem4)
summary(fit_4)

Call:
lm(formula = x_4 ~ y_4, data = problem4)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.1522 -1.1929  0.3144  1.0636  2.0662 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.09574    0.37736   0.254 0.800720    
y_4          1.31191    0.31788   4.127 0.000133 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.337 on 52 degrees of freedom
Multiple R-squared:  0.2467,    Adjusted R-squared:  0.2322 
F-statistic: 17.03 on 1 and 52 DF,  p-value: 0.0001332
res_var4 = sum(residuals(fit_4)^2)
x_hat4 = predict(fit_4)
reg_var4 = sum((x_hat4 - mean(x_4))^2)
tot_var4 = sum((x_4 - mean(x_4))^2)
tot_var4
[1] 123.4709
res_var4 + reg_var4
[1] 123.4709
tot_var4 - (res_var4 + reg_var4)
[1] -1.421085e-14
Rsq4 = reg_var4/tot_var4
Rsq4
[1] 0.24673
cor(x_4,y_4)^2 #square of the correlation coefficient
[1] 0.24673
Rsq4 - cor(x_4,y_4)^2
[1] 1.387779e-16
  1. Assess your results.

Section II Body measurement study

Anthropological researchers collected body measurements from 507 individuals (247 men and 260 women.) The data are contained in the file bdims.csv. A description of the variables can be found here

bdims <- read.csv("bdims.csv")

Using R Perform the following tasks, give the most complete specific answers you can given the data.

  1. Describe the relationship between shoulder girth and height.
head(bdims)
bdims %>%
  ggplot(aes(x = sho_gi, y = hgt)) +
  geom_point()

As shoulder girth increases height increases.

  1. How would the relationship change if shoulder girth were measured in inches while the units of height remained in centimeters?

The relationship would not change because the variables would still remain a positive relationship between shoulder girth and height.

  1. Write the equation of the regression line for predicting height. How would you find the coefficients without using lm?

slope <- cor(bdims$sho_gi,bdims$hgt) * (sd(bdims$hgt)/ sd(bdims$sho_gi))
slope
[1] 0.6036442
intercept <- mean(bdims$hgt) - slope * mean(bdims$sho_gi)
intercept
[1] 105.8325
height <- (intercept + (slope*bdims$sho_gi))
  1. Interpret the slope and intercept in this context.

The slope is an 0.6 height increase for each unit of shoulder girth.

  1. Calculate \(R^2\) of the regression line for predicting height for shoulder girth
x_4 = problem4$x
y_4 = problem4$y

beta = sum(x*y)/sum(x^2)
beta
[1] 0.4409789
  1. A randomly selected student from your class has a shoulder girth of 100cm. Predict the height of this student using this model.
intercept + slope * 100
[1] 166.1969
  1. If the selected student is actually 160 cm tall, calculate the residual and explain it’s meaning.
160 - 166.1969
[1] -6.1969

The students height was about 6.2 cm taller than the expected height.

  1. A one year old has has a shoulder girth of 56 cm. Would it be appropriate to use this linear model to predict the height of this child?
intercept + slope * 59
[1] 141.4475
min(bdims$sho_gi)
[1] 85.9
max(bdims$sho_gi)
[1] 134.8

No because 56cm would not fit within the range of the model and cannot be used to predict height.

Murders and Poverty

murders %>%
  ggplot(aes(x = perc_pov, y = annual_murders_per_mil)) +
  geom_point()

summary(lm(annual_murders_per_mil~ perc_pov, data = murders))

Call:
lm(formula = annual_murders_per_mil ~ perc_pov, data = murders)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.1663 -2.5613 -0.9552  2.8887 12.3475 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  -29.901      7.789  -3.839   0.0012 ** 
perc_pov       2.559      0.390   6.562 3.64e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 5.512 on 18 degrees of freedom
Multiple R-squared:  0.7052,    Adjusted R-squared:  0.6889 
F-statistic: 43.06 on 1 and 18 DF,  p-value: 3.638e-06

Just referring to the plot and the summary above:

  1. Write out the linear model: Y = annual_murders_per_mil X = perc_pov * (b)slope =2.559 # (a)intercept = -29.901 # annual_murders_per_mil = 2.559 * perc_pov - 29.901
  2. Interpret the intercept: The intercept is not possible because when the poverty level is zero the murders would be -29.901.
  3. Interpret the slope: for every unit of poverty murders will increase by 2.559
  4. Interpret \(R^2\) The dependent variable murders has a relationship with the independent variable poverty.
  5. Calculate the correlation coefficient
cor(murders$annual_murders_per_mil,murders$perc_pov)
[1] 0.8397782
LS0tDQp0aXRsZTogIlByb2plY3QgMyBSZWdyZXNzaW9uIg0KYXV0aG9yOiAiUmljaG1vbmQgWWVib2FoIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3IsIGluY2x1ZGUgPSBGQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShvcGVuaW50cm8pDQpgYGANCg0KIyMgSW50cm9kdWN0aW9uDQoNClRoaXMgcHJvamVjdCBpcyBpbnRlbmRlZCB0byBleHRlbmQgYW5kIHN1cHBsZW1lbnQgd2hhdCB3ZSB0YWxrZWQgYWJvdXQgbGFzdCB3ZWVrIGluIGRpc2N1c3NpbmcgTGluZWFyIFJlZ3Jlc3Npb24uDQoNCkluIHNvbWUgb2YgdGhlIHNlY3Rpb25zIHlvdSB3aWxsIGJlIGFza2VkIHRvIHdyaXRlIFIgY29kZSB0byBzb2x2ZSBhIHBhcnRpY3VsYXIgcHJvYmxlbS4gSW4gc29tZSB5b3Ugd2lsbCBiZSBhc2tlZCB0byBhbnN3ZXIgcXVlc3Rpb25zIGluIHlvdXIgb3duIHdvcmRzLiANCg0KDQojIyMgU2luZ2xlIFZhcmlhYmxlIFJlZ3Jlc3Npb24NCg0KV2UgYXJlIHRyeWluZyB0byBmaXQgYSBzdHJhaWdodCBsaW5lIHRvIGEgc2NhdHRlciBwbG90LiBUaGlzIG1lYW5zIGZpbmRpbmcgdGhlIGVxdWF0aW9uIG9mIHRoZSBsaW5lIHRoYXQgY29tZXMgY2xvc2VzdCB0byBhbGwgdGhlIHBvaW50cy4gTW9yZSBzcGVjaWZpY2FsbHksIHRoZSBwcm9ibGVtIGJlY29tZXMsIGdpdmVuICRYID0gXHt4XzEseF8xLFxsZG90cyx4X25cfSQgYW5kICRZID0gXHt5XzEsIHlfMixcZG90cyx5X25cfSQgZmluZCAkXGJldGFfMCQgYW5kICRiZXRhXzEkIHN1Y2ggdGhhdA0KJCQgWV9pID0gXGJldGFfMCArIFxiZXRhXzEgWF9pICsgXGVwc2lsb25faSQkDQp3aGVyZSwgJFxzdW1fe2l9XntufVxlcHNpbG9uX2kgPSAwJCBhbmQgJFxzaWdtYV4yID0gXHN1bV97aX1ee259XGVwc2lsb25faSBeMiQgaXMgYXMgbWluaW1pemVkLiBUaGlzIGlzIGNhbGxlZCAqbGVhc3Qgc3F1YXJlcyogcmVncmVzc2lvbi4NCg0KR2l2ZW4gZXN0aW1hdGVzIG9mICRcYmV0YV8wJCBhbmQgJFxiZXRhXzEkIGNhbGxlZCAkXGhhdHtcYmV0YV8wfSQgYW5kICRcaGF0e1xiZXRhXzF9JCB3ZSBkZWZpbmU6ICQkXGhhdHt5X2l9ID0gXGhhdHtcYmV0YV8wfSArIFxoYXR7XGJldGFfMX14X2kkJA0KVGhlICRcaGF0e3lfaX0kIGFyZSBjYWxsZWQgdGhlIHByZWRpY3RlZCB2YWx1ZXMuDQoNClRoZSByZXNpZHVhbHMsICRlX2kkLCBhcmUgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHByZWRpY3RlZCB2YWx1ZXMgYW5kIHRoZSBhY3R1YWwgdmFsdWVzLiQkZV9pID0geV9pIC0gXGhhdHt5X2l9JCQNCg0KTm90ZTogdGhlIHJlc2lkdWFscyBhcmUgKmVzdGltYXRlcyogb2YgdGhlICRcZXBzaWxvbl9pJCBpbiB0aGUgbW9kZWwuDQoNCg0KIyMgRXhhbWluaW5nIFJlc2lkdWFsIHZhcmlhbmNlLg0KDQpQbGVhc2Ugd29yayB0aHJvdWdoIHRoaXMgW2RvY3VtZW50XShodHRwOi8vcnB1YnMuY29tL1Byb2ZDZWxpYS83OTQ5MTkpIGJlZm9yZSBjb250aW51aW5nIHdpdGggdGhpcyBwcm9qZWN0Lg0KDQoNCiMjIFNlY3Rpb24gSSBXb3JraW5nIHdpdGggU2ltdWxhdGVkIHNjYXR0ZXIgcGxvdHMuDQoNCg0KVGhlcmUgYXJlIGZvdXIgZGF0YSBzZXRzIGluIFByb2plY3QzIGRhdGEgZm9sZGVyIHRoZSBmaWxlcyBzZWN0aW9uLCBgcHJvYmxlbTEuY3N2YCwgYHByb2JsZW0yLmNzdmAsIGBwcm9ibGVtMy5jc3ZgLCBhbmQgYHByb2JsZW00LmNzdmANClRoZXNlIGRhdGEgYXJlIHNvbWUgb2YgdGhlICBncm91cHMgZnJvbSBbdGhpc10oaHR0cHM6Ly93d3cub3BlbmludHJvLm9yZy9kYXRhL2luZGV4LnBocD9kYXRhPXNpbXVsYXRlZF9zY2F0dGVyKSBkYXRhLiBZb3Ugd2lsbCBuZWVkIHRvIGxvYWQgdGhlIGZpbGVzIGludG8geW91ciBwcm9qZWN0IHVzaW5nIGByZWFkX2NzdmAuDQoNCllvdSB3aWxsIGFsc28gbmVlZCB0byByZWFkIGluIHRoZSBmaWxlIGBiZGlzbS5jc3YnIHRvIGRvIHRoZSBwcm9ibGVtcyBpbiBTZWN0aW9uIElJLg0KDQpgYGB7cn0NCnByb2JsZW0xIDwtIHJlYWRfY3N2KCJwcm9ibGVtMS5jc3YiKQ0KcHJvYmxlbTIgPC0gcmVhZF9jc3YoInByb2JsZW0yLmNzdiIpDQpwcm9ibGVtMyA8LSByZWFkX2NzdigicHJvYmxlbTMuY3N2IikNCnByb2JsZW00IDwtIHJlYWRfY3N2KCJwcm9ibGVtNC5jc3YiKQ0KYmRpc20gPC0gcmVhZF9jc3YoImJkaW1zLmNzdiIpDQpgYGANCg0KIyMjIEZvciBlYWNoIG9mIHRoZSBmb3VyIGZpbGVzOg0KDQoxLiBwbG90IHRoZSBzY2F0dGVyIHBsb3Qgb2YgYHhgIGFuZCBgeWAgKGB4YCBvbiB0aGUgaG9yaXpvbnRhbCBheGlzLikNCg0KYGBge3J9DQpwcm9ibGVtMSAlPiUgDQogIGdncGxvdChhZXMgKHggPSB4LCB5ID0geSkpICsgDQogIGdlb21fcG9pbnQoKQ0KYGBgDQpgYGB7cn0NCnByb2JsZW0yICU+JSANCiAgZ2dwbG90KGFlcyAoeCA9IHgsIHkgPSB5KSkgKyANCiAgZ2VvbV9wb2ludCgpDQpgYGANCg0KYGBge3J9DQpwcm9ibGVtMyAlPiUgDQogIGdncGxvdChhZXMgKHggPSB4LCB5ID0geSkpICsgDQogIGdlb21fcG9pbnQoKQ0KYGBgDQoNCmBgYHtyfQ0KcHJvYmxlbTQgJT4lIA0KICBnZ3Bsb3QoYWVzICh4ID0geCwgeSA9IHkpKSArIA0KICBnZW9tX3BvaW50KCkNCmBgYA0KDQoNCjIuIGZpdCBhIHJlZ3Jlc3Npb24gbW9kZWwgdXNpbmcgYGxtYCByZXBvcnQgdGhlIGNvZWZmaWNpZW50cywgYW5kIHBsb3QgdGhlIHJlZ3Jlc3Npb24gbGluZSBvdmVyIHRoZSBzY2F0dGVyIHBsb3QuDQoNCmBgYHtyfQ0KcHJvYmxlbTEgJT4lIA0KICBnZ3Bsb3QoYWVzICh4ID0geCwgeSA9IHkpKSArIA0KICBnZW9tX3BvaW50KCkgKyANCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3IgPSAicmVkIikNCmBgYA0KDQpgYGB7cn0NCnByb2JsZW0yICU+JSANCiAgZ2dwbG90KGFlcyAoeCA9IHgsIHkgPSB5KSkgKyANCiAgZ2VvbV9wb2ludCgpICsgDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gInJlZCIpDQpgYGANCg0KYGBge3J9DQpwcm9ibGVtMyAlPiUgDQogIGdncGxvdChhZXMgKHggPSB4LCB5ID0geSkpICsgDQogIGdlb21fcG9pbnQoKSArIA0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICJyZWQiKQ0KYGBgDQpgYGB7cn0NCnByb2JsZW00ICU+JSANCiAgZ2dwbG90KGFlcyAoeCA9IHgsIHkgPSB5KSkgKyANCiAgZ2VvbV9wb2ludCgpICsgDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gInJlZCIpDQpgYGANCg0KDQoNCg0KMy4gUGxvdCB0aGUgcmVzaWR1YWxzIHZlcnN1cyBgeGAuDQoNCmBgYHtyfQ0KcHJvYmxlbTEgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICBnZW9tX3BvaW50KCkgKw0KICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwKSwgY29sb3IgPSAiYmx1ZSIpDQpgYGANCmBgYHtyfQ0KcHJvYmxlbTIgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsNCiAgICBnZW9tX3BvaW50KCkgKw0KICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwKSwgY29sb3IgPSAiYmx1ZSIpDQpgYGANCg0KYGBge3J9DQpwcm9ibGVtMyAlPiUgDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgIGdlb21fcG9pbnQoKSArDQogICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDApLCBjb2xvciA9ICJibHVlIikNCmBgYA0KYGBge3J9DQpwcm9ibGVtNCAlPiUgDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKw0KICAgIGdlb21fcG9pbnQoKSArDQogICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDApLCBjb2xvciA9ICJibHVlIikNCmBgYA0KDQpSZWNvcmQgYW55IG9ic2VydmF0aW9ucyB5b3UgaGF2ZSBpbiB0aGlzIGRvY3VtZW50Lg0KDQpJIG5vdGljZWQgdGhhdCBvbmx5IHByb2JsZW0gMSBhbmQgcHJvYmxlbSAyIGhhZCBtb3JlIHR3byBvciBtb3JlIHBvaW50cyBhdCB0aGUgeCBpbnRlcmNlcHQuIFByb2JsZW1zIDEgYW5kIDMgb24gdGhlIG90aGVyIGhhbmQgd2VyZSB0aGUgb25seSB0d28gdGhhdCBoYWQgY29ycmVsYXRpb25zLg0KDQo0LiBDYWxjdWxhdGUgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gYHhgIGFuZCBgeWAuDQoNCmBgYHtyfQ0KeF8xIDwtIHByb2JsZW0xJHgNCnlfMSA8LSBwcm9ibGVtMSR5DQpjb3IoeF8xLHlfMSkNCmBgYA0KDQpgYGB7cn0NCnhfMiA8LSBwcm9ibGVtMiR4DQp5XzIgPC0gcHJvYmxlbTIkeQ0KY29yKHhfMix5XzIpDQpgYGANCmBgYHtyfQ0KeF8zIDwtIHByb2JsZW0zJHgNCnlfMyA8LSBwcm9ibGVtMyR5DQpjb3IoeF8zLHlfMykNCmBgYA0KDQpgYGB7cn0NCnhfNCA8LSBwcm9ibGVtNCR4DQp5XzQgPC0gcHJvYmxlbTQkeQ0KY29yKHhfNCx5XzQpDQpgYGANCg0KNS4gRG9lcyB0aGUgY2FsY3VsYXRpb24gaW5kaWNhdGUgYSBzdHJvbmcgbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGB4YCBhbmQgYHlgPw0KDQpQcm9ibGVtIDEgaGFzIGEgc3Ryb25nIHBvc2l0aXZlIGxpbmVhciByZWxhdGlvbnNoaXAuIFByb2JsZW0gMiBoYXMgbm8gbGluZWFyIHJlbGF0aW9uc2hpcC4gUHJvYmxlbSAzIGhhcyBhIHN0cm9uZyBuZWdhdGl2ZSBsaW5lYXIgcmVsYXRpb25zaGlwLiBQcm9ibGVtIDQgaGFzIGEgd2VhayBsaW5lYXIgcmVsYXRpb25zaGlwLg0KDQo2LiBOb3JtYWxpemUgdGhlIGB4YCBhbmQgYHlgIGRhdGEsIHRoaXMgbWVhbnMgY2FsY3VsYXRlIHRoZSB6LXNjb3JlIGZvciBlYWNoICR4X2kkIGFuZCAkeV9pJCwgaXQgaXMgcG9zc2libGUgdG8gZG8gdGhpcyB3aXRoIG9uZSBsaW5lIG9mIFIgY29kZS4NCg0KKipIaW50KiogdGhlIHotc2NvcmUgb2YgYSB2ZWN0b3Igb2YgZGF0YSwgeCwgaXMgdGhlIHZlY3RvciAkeiQgZ2l2ZW4gYnkgICR6ID0gXGZyYWN7eCAtIFxiYXJ7eH19e3NfeH0kIHdoZXJlICRzX3gkIGlzIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgJHgkLg0KDQpgYGB7cn0NCmZpdF8xIDwtIGxtKCB5XzEgfiAgeF8xLCBkYXRhID0gcHJvYmxlbTEpDQpzdW1tYXJ5KGZpdF8xKQ0KYGBgDQpgYGB7cn0NCnhfMQ0KYGBgDQoNCg0KYGBge3J9DQptZWFuKHhfMSkNCmBgYA0KYGBge3J9DQpzZCh4XzEpDQpgYGANCg0KDQoNCmBgYHtyfQ0Kel9zY29yZV8xID0gICh4XzEgLSBtZWFuKHhfMSkpL3NkKHhfMSkNCnpfc2NvcmVfMQ0KYGBgDQoNCg0KNy4gVXNpbmcgYGxtYCBjYWxjdWxhdGUgdGhlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzLiBXaGF0IGRvIHlvdSBub3RpY2U/DQoNCmBgYHtyfQ0Kc3VtbWFyeShsbSh4XzEgfiB5XzEsIGRhdGEgPSBwcm9ibGVtMSkpIA0KYGBgDQo4LiBDYWxjdWxhdGUgVG90YWwgVmFyaWF0aW9uIGFuZCAkUl4yJCANCg0KYGBge3J9DQpmaXRfMSA8LSBsbSh4XzEgfiB5XzEsIGRhdGEgPSBwcm9ibGVtMSkNCnN1bW1hcnkoZml0XzEpDQpgYGANCg0KYGBge3J9DQpkZiA8LSBucm93KHByb2JsZW0xKSAtIDENCmRmDQpgYGANCg0KDQpgYGB7cn0NCnJlc192YXIxID0gc3VtKHJlc2lkdWFscyhmaXRfMSleMikNCnhfaGF0MSA9IHByZWRpY3QoZml0XzEpDQpyZWdfdmFyMSA9IHN1bSgoeF9oYXQxIC0gbWVhbih4XzEpKV4yKQ0KdG90X3ZhcjEgPSBzdW0oKHhfMSAtIG1lYW4oeF8xKSleMikNCnRvdF92YXIxDQpgYGANCmBgYHtyfQ0KcmVzX3ZhcjEgKyByZWdfdmFyMQ0KYGBgDQoNCmBgYHtyfQ0KdG90X3ZhcjEgLSAocmVzX3ZhcjEgKyByZWdfdmFyMSkNCmBgYA0KDQpgYGB7cn0NClJzcSA9IHJlZ192YXIxL3RvdF92YXIxDQpSc3ENCmBgYA0KDQpgYGB7cn0NCmNvcih4XzEseV8xKV4yICNzcXVhcmUgb2YgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50DQpgYGANCmBgYHtyfQ0KUnNxIC0gY29yKHhfMSx5XzEpXjINCmBgYA0KDQojOC5iKSANCg0KYGBge3J9DQpmaXRfMiA8LSBsbSh4XzIgfiB5XzIsIGRhdGEgPSBwcm9ibGVtMikNCnN1bW1hcnkoZml0XzIpDQpgYGANCg0KYGBge3J9DQpyZXNfdmFyMiA9IHN1bShyZXNpZHVhbHMoZml0XzIpXjIpDQp4X2hhdDIgPSBwcmVkaWN0KGZpdF8yKQ0KcmVnX3ZhcjIgPSBzdW0oKHhfaGF0MiAtIG1lYW4oeF8yKSleMikNCnRvdF92YXIyID0gc3VtKCh4XzIgLSBtZWFuKHhfMikpXjIpDQp0b3RfdmFyMg0KYGBgDQoNCg0KYGBge3J9DQpyZXNfdmFyMiArIHJlZ192YXIyDQpgYGANCg0KYGBge3J9DQp0b3RfdmFyMiAtIChyZXNfdmFyMiArIHJlZ192YXIyKQ0KYGBgDQoNCmBgYHtyfQ0KUnNxMiA9IHJlZ192YXIyL3RvdF92YXIyDQpSc3EyDQpgYGANCg0KYGBge3J9DQpjb3IoeF8yLHlfMileMiAjc3F1YXJlIG9mIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudA0KYGBgDQoNCmBgYHtyfQ0KUnNxMiAtIGNvcih4XzIseV8yKV4yDQpgYGANCiM4LmMpIA0KYGBge3J9DQpmaXRfMyA8LSBsbSh4XzMgfiB5XzMsIGRhdGEgPSBwcm9ibGVtMykNCnN1bW1hcnkoZml0XzMpDQpgYGANCg0KYGBge3J9DQpyZXNfdmFyMyA9IHN1bShyZXNpZHVhbHMoZml0XzMpXjIpDQp4X2hhdDMgPSBwcmVkaWN0KGZpdF8zKQ0KcmVnX3ZhcjMgPSBzdW0oKHhfaGF0MyAtIG1lYW4oeF8zKSleMikNCnRvdF92YXIzID0gc3VtKCh4XzMgLSBtZWFuKHhfMykpXjIpDQp0b3RfdmFyMw0KYGBgDQoNCg0KYGBge3J9DQpyZXNfdmFyMyArIHJlZ192YXIzDQpgYGANCg0KYGBge3J9DQp0b3RfdmFyMyAtIChyZXNfdmFyMyArIHJlZ192YXIzKQ0KYGBgDQoNCmBgYHtyfQ0KUnNxMyA9IHJlZ192YXIzL3RvdF92YXIzDQpSc3EzDQpgYGANCg0KYGBge3J9DQpjb3IoeF8zLHlfMyleMiAjc3F1YXJlIG9mIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudA0KYGBgDQoNCmBgYHtyfQ0KUnNxMyAtIGNvcih4XzMseV8zKV4yDQpgYGANCg0KOC5kKQ0KDQpgYGB7cn0NCmZpdF80IDwtIGxtKHhfNCB+IHlfNCwgZGF0YSA9IHByb2JsZW00KQ0Kc3VtbWFyeShmaXRfNCkNCmBgYA0KDQpgYGB7cn0NCnJlc192YXI0ID0gc3VtKHJlc2lkdWFscyhmaXRfNCleMikNCnhfaGF0NCA9IHByZWRpY3QoZml0XzQpDQpyZWdfdmFyNCA9IHN1bSgoeF9oYXQ0IC0gbWVhbih4XzQpKV4yKQ0KdG90X3ZhcjQgPSBzdW0oKHhfNCAtIG1lYW4oeF80KSleMikNCnRvdF92YXI0DQpgYGANCg0KDQpgYGB7cn0NCnJlc192YXI0ICsgcmVnX3ZhcjQNCmBgYA0KDQpgYGB7cn0NCnRvdF92YXI0IC0gKHJlc192YXI0ICsgcmVnX3ZhcjQpDQpgYGANCg0KYGBge3J9DQpSc3E0ID0gcmVnX3ZhcjQvdG90X3ZhcjQNClJzcTQNCmBgYA0KDQpgYGB7cn0NCmNvcih4XzQseV80KV4yICNzcXVhcmUgb2YgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50DQpgYGANCg0KYGBge3J9DQpSc3E0IC0gY29yKHhfNCx5XzQpXjINCmBgYA0KDQo5LiBBc3Nlc3MgeW91ciByZXN1bHRzLg0KDQojIyBTZWN0aW9uIElJIEJvZHkgbWVhc3VyZW1lbnQgc3R1ZHkNCg0KQW50aHJvcG9sb2dpY2FsIHJlc2VhcmNoZXJzIGNvbGxlY3RlZCBib2R5IG1lYXN1cmVtZW50cyBmcm9tIDUwNyBpbmRpdmlkdWFscyAoMjQ3IG1lbiBhbmQgMjYwIHdvbWVuLikgVGhlIGRhdGEgYXJlIGNvbnRhaW5lZCBpbiB0aGUgZmlsZSBgYmRpbXMuY3N2YC4gQSBkZXNjcmlwdGlvbiBvZiB0aGUgdmFyaWFibGVzIGNhbiBiZSBmb3VuZCBbaGVyZV0oaHR0cHM6Ly93d3cub3BlbmludHJvLm9yZy9kYXRhL2luZGV4LnBocD9kYXRhPWJkaW1zKQ0KDQpgYGB7cn0NCmJkaW1zIDwtIHJlYWQuY3N2KCJiZGltcy5jc3YiKQ0KYGBgDQogDQpVc2luZyBSIFBlcmZvcm0gdGhlIGZvbGxvd2luZyB0YXNrcywgZ2l2ZSB0aGUgbW9zdCBjb21wbGV0ZSBzcGVjaWZpYyBhbnN3ZXJzIHlvdSBjYW4gZ2l2ZW4gdGhlIGRhdGEuDQoNCjEuIERlc2NyaWJlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzaG91bGRlciBnaXJ0aCBhbmQgaGVpZ2h0Lg0KDQpgYGB7cn0NCmhlYWQoYmRpbXMpDQpgYGANCg0KDQpgYGB7cn0NCmJkaW1zICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBzaG9fZ2ksIHkgPSBoZ3QpKSArDQogIGdlb21fcG9pbnQoKQ0KYGBgDQoNCiMjIyBBcyBzaG91bGRlciBnaXJ0aCBpbmNyZWFzZXMgaGVpZ2h0IGluY3JlYXNlcy4NCg0KMi4gSG93IHdvdWxkIHRoZSByZWxhdGlvbnNoaXAgY2hhbmdlIGlmIHNob3VsZGVyIGdpcnRoIHdlcmUgbWVhc3VyZWQgaW4gaW5jaGVzIHdoaWxlIHRoZSB1bml0cyBvZiBoZWlnaHQgcmVtYWluZWQgaW4gY2VudGltZXRlcnM/DQoNCiMjIyBUaGUgcmVsYXRpb25zaGlwIHdvdWxkIG5vdCBjaGFuZ2UgYmVjYXVzZSB0aGUgdmFyaWFibGVzIHdvdWxkIHN0aWxsIHJlbWFpbiBhIHBvc2l0aXZlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNob3VsZGVyIGdpcnRoIGFuZCBoZWlnaHQuDQoNCjMuIFdyaXRlIHRoZSBlcXVhdGlvbiBvZiB0aGUgcmVncmVzc2lvbiBsaW5lIGZvciBwcmVkaWN0aW5nIGhlaWdodC4gSG93IHdvdWxkIHlvdSBmaW5kIHRoZSBjb2VmZmljaWVudHMgKip3aXRob3V0KiogdXNpbmcgYGxtYD8NCg0KYGBge3J9DQpzbG9wZSA8LSBjb3IoYmRpbXMkc2hvX2dpLGJkaW1zJGhndCkgKiAoc2QoYmRpbXMkaGd0KS8gc2QoYmRpbXMkc2hvX2dpKSkNCnNsb3BlDQpgYGANCmBgYHtyfQ0KaW50ZXJjZXB0IDwtIG1lYW4oYmRpbXMkaGd0KSAtIHNsb3BlICogbWVhbihiZGltcyRzaG9fZ2kpDQppbnRlcmNlcHQNCmBgYA0KYGBge3J9DQpoZWlnaHQgPC0gKGludGVyY2VwdCArIChzbG9wZSpiZGltcyRzaG9fZ2kpKQ0KYGBgDQoNCg0KNC4gSW50ZXJwcmV0IHRoZSBzbG9wZSBhbmQgaW50ZXJjZXB0IGluIHRoaXMgY29udGV4dC4NCg0KIyMjIFRoZSBzbG9wZSBpcyBhbiAwLjYgaGVpZ2h0IGluY3JlYXNlIGZvciBlYWNoIHVuaXQgb2Ygc2hvdWxkZXIgZ2lydGguDQoNCjUuIENhbGN1bGF0ZSAkUl4yJCBvZiB0aGUgcmVncmVzc2lvbiBsaW5lIGZvciBwcmVkaWN0aW5nIGhlaWdodCBmb3Igc2hvdWxkZXIgZ2lydGgNCmBgYHtyfQ0KeF80ID0gcHJvYmxlbTQkeA0KeV80ID0gcHJvYmxlbTQkeQ0KDQpiZXRhID0gc3VtKHgqeSkvc3VtKHheMikNCmJldGENCmBgYA0KDQoNCjYuIEEgcmFuZG9tbHkgc2VsZWN0ZWQgc3R1ZGVudCBmcm9tIHlvdXIgY2xhc3MgaGFzIGEgc2hvdWxkZXIgZ2lydGggb2YgMTAwY20uIFByZWRpY3QgdGhlIGhlaWdodCBvZiB0aGlzIHN0dWRlbnQgdXNpbmcgdGhpcyBtb2RlbC4NCg0KYGBge3J9DQppbnRlcmNlcHQgKyBzbG9wZSAqIDEwMA0KYGBgDQoNCjcuIElmIHRoZSBzZWxlY3RlZCBzdHVkZW50IGlzIGFjdHVhbGx5IDE2MCBjbSB0YWxsLCBjYWxjdWxhdGUgdGhlIHJlc2lkdWFsIGFuZCBleHBsYWluIGl0J3MgbWVhbmluZy4NCg0KYGBge3J9DQoxNjAgLSAxNjYuMTk2OQ0KYGBgDQoNCiMjIyBUaGUgc3R1ZGVudHMgaGVpZ2h0IHdhcyBhYm91dCA2LjIgY20gdGFsbGVyIHRoYW4gdGhlIGV4cGVjdGVkIGhlaWdodC4gDQoNCjguIEEgb25lIHllYXIgb2xkIGhhcyBoYXMgYSBzaG91bGRlciBnaXJ0aCBvZiA1NiBjbS4gV291bGQgaXQgYmUgYXBwcm9wcmlhdGUgdG8gdXNlIHRoaXMgbGluZWFyIG1vZGVsIHRvIHByZWRpY3QgdGhlIGhlaWdodCBvZiB0aGlzIGNoaWxkPw0KDQpgYGB7cn0NCmludGVyY2VwdCArIHNsb3BlICogNTkNCmBgYA0KDQpgYGB7cn0NCm1pbihiZGltcyRzaG9fZ2kpDQptYXgoYmRpbXMkc2hvX2dpKQ0KYGBgDQoNCiMjIyBObyBiZWNhdXNlIDU2Y20gd291bGQgbm90IGZpdCB3aXRoaW4gdGhlIHJhbmdlIG9mIHRoZSBtb2RlbCBhbmQgY2Fubm90IGJlIHVzZWQgdG8gcHJlZGljdCBoZWlnaHQuDQoNCiMjIyBNdXJkZXJzIGFuZCBQb3ZlcnR5DQoNCmBgYHtyfQ0KbXVyZGVycyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gcGVyY19wb3YsIHkgPSBhbm51YWxfbXVyZGVyc19wZXJfbWlsKSkgKw0KICBnZW9tX3BvaW50KCkNCmBgYA0KDQpgYGB7cn0NCnN1bW1hcnkobG0oYW5udWFsX211cmRlcnNfcGVyX21pbH4gcGVyY19wb3YsIGRhdGEgPSBtdXJkZXJzKSkNCmBgYA0KDQpKdXN0IHJlZmVycmluZyB0byB0aGUgcGxvdCBhbmQgdGhlIHN1bW1hcnkgYWJvdmU6DQoNCmEuIFdyaXRlIG91dCB0aGUgbGluZWFyIG1vZGVsOiBZID0gYW5udWFsX211cmRlcnNfcGVyX21pbCBYID0gcGVyY19wb3YgKiAoYilzbG9wZSA9Mi41NTkgIyAoYSlpbnRlcmNlcHQgPSAtMjkuOTAxICMgYW5udWFsX211cmRlcnNfcGVyX21pbCA9IDIuNTU5ICogcGVyY19wb3YgLSAyOS45MDENCmIuIEludGVycHJldCB0aGUgaW50ZXJjZXB0OiBUaGUgaW50ZXJjZXB0IGlzIG5vdCBwb3NzaWJsZSBiZWNhdXNlIHdoZW4gdGhlIHBvdmVydHkgbGV2ZWwgaXMgemVybyB0aGUgbXVyZGVycyB3b3VsZCBiZSAtMjkuOTAxLg0KYy4gSW50ZXJwcmV0IHRoZSBzbG9wZTogZm9yIGV2ZXJ5IHVuaXQgb2YgcG92ZXJ0eSBtdXJkZXJzIHdpbGwgaW5jcmVhc2UgYnkgMi41NTkNCmQuIEludGVycHJldCAkUl4yJCBUaGUgZGVwZW5kZW50IHZhcmlhYmxlIG11cmRlcnMgaGFzIGEgcmVsYXRpb25zaGlwIHdpdGggdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlIHBvdmVydHkuDQplLiBDYWxjdWxhdGUgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50DQoNCmBgYHtyfQ0KY29yKG11cmRlcnMkYW5udWFsX211cmRlcnNfcGVyX21pbCxtdXJkZXJzJHBlcmNfcG92KQ0KYGBgDQoNCg==