Statistical Learning

\[\\[1in]\]

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

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

This is a regression problem, and we are interested in inference. n = 500 and p = 3

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

This is a classification problem, and we are most interested in prediction. n = 20 (20 similar products previously launched) and p = 13 (price, marketing budget, competition price, and ten other variables).

  1. We are interesting in predicting the % change in the US dollar 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 dollar, the % change in the US market, the % change in the British market, and the % change in the German market.

This is a regression problem because % change in the US dollar is a quantitative DV. Also, it is a prediction problem as well because it states “we are interested in predicting the % change”. n = 52 (weekly data over 2012) and p = 3 (% change in US, % change in British, % change in German).

\[\\[1in]\]

Question 5. What are the advantages and disadvantages of a very flexible (versus a less flexible) approach for regression or classification? Under what circumstances might a more flexible approach be preferred to a less flexible approach? When might a less flexible approach be preferred?

-The advantages of a very flexible approach are that it decreases their bias, and it can also give a better fit for non-linear models.

-The disadvantages of this are that it requires estimating a larger number of parameters, therefore increasing the variance.

-A more flexible approach better when the relationship is highly non-linear. This is because you have several data points to find a pattern, and/or the irreducible error is low.

-A less flexible approach is best when the relationship is very linear since you don’t have that many data points, and/or the irreducible error is high.

-A less flexible approach would be preferred vs. a more flexible approach when we are looking for inference and the interpretability of the output.

\[\\[1in]\]

Question 6. Describe the differences between a parametric and a non-parametric statistical learning approach. What are the advantages of a parametric approach to regression or classification (as opposed to a non- parametric approach)? What are its disadvantages?

Because fewer assumptions are made regarding the data structure, a non-parametric method is better at fitting highly nonlinear patterns. However, in circumstances where there is a considerable risk of overfitting , this could be harmful. Furthermore, since you lack the interpretation structure of the parameters, you will find it difficult to understand the data.

\[\\[1in]\]

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

library(readr)
College <- read.csv("~/Downloads/College.csv", stringsAsFactors = FALSE)

(b). Look at the data using the view() 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. Try the following commands:

rownames(College) <- College[, 1] 
View(College)
College <- College[, -1]
View(College)

(c). i. Use the summary() function to produce a numerical summary of the variables in the data set.

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

  2. Use the plot() function to produce side-by-side boxplots of Outstate versus Private.

  3. Create a new qualitative variable, called Elite, by binning the Top10perc variable. We are going to divide universities into two groups based on whether or not the proportion of students coming from the top 10% of their high school classes exceeds 50 %.

 Elite <- rep("No", nrow(College))
 Elite[College$Top10perc > 50] <- "Yes"
 Elite <- as.factor(Elite)
College <- data.frame(College, Elite)
summary(Elite)
 No Yes 
699  78 

There are 78 Elite schools.

plot(Outstate ~ Elite, data = College, 
     xlab = "Elite University", 
     ylab = "Tuition in $")

  1. Use the hist() function to produce some histograms with differing numbers of bins for a few of the quantitative vari- ables. You may find the command par(mfrow = c(2, 2)) useful: it will divide the print window into four regions so that four plots can be made simultaneously. Modifying the arguments to this function will divide the screen in other ways.
par(mfrow=c(2,2))
hist(College$Top10perc, xlab = "Top 10%", main="")
hist(College$Top25perc, xlab = "Top 25%", main="")
hist(College$Grad.Rate, xlab = "Graduation rate", main="")
hist(College$PhD, xlab = "Proportion of faculty with Ph.D.’s", main="")

  1. Continue exploring the data, and provide a brief summary of what you discover.
summary(College$Books)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   96.0   470.0   500.0   549.4   600.0  2340.0 

The avarage amount of money that students spend on books is $549, which is a lot of money!

\[\\[1in]\]

Question 9. This exercise involves the Auto data set studied in the lab. Make sure that the missing values have been removed from the data.

data(Auto)
summary(Auto)
      mpg          cylinders      displacement     horsepower        weight    
 Min.   : 9.00   Min.   :3.000   Min.   : 68.0   Min.   : 46.0   Min.   :1613  
 1st Qu.:17.00   1st Qu.:4.000   1st Qu.:105.0   1st Qu.: 75.0   1st Qu.:2225  
 Median :22.75   Median :4.000   Median :151.0   Median : 93.5   Median :2804  
 Mean   :23.45   Mean   :5.472   Mean   :194.4   Mean   :104.5   Mean   :2978  
 3rd Qu.:29.00   3rd Qu.:8.000   3rd Qu.:275.8   3rd Qu.:126.0   3rd Qu.:3615  
 Max.   :46.60   Max.   :8.000   Max.   :455.0   Max.   :230.0   Max.   :5140  
                                                                               
  acceleration        year           origin                      name    
 Min.   : 8.00   Min.   :70.00   Min.   :1.000   amc matador       :  5  
 1st Qu.:13.78   1st Qu.:73.00   1st Qu.:1.000   ford pinto        :  5  
 Median :15.50   Median :76.00   Median :1.000   toyota corolla    :  5  
 Mean   :15.54   Mean   :75.98   Mean   :1.577   amc gremlin       :  4  
 3rd Qu.:17.02   3rd Qu.:79.00   3rd Qu.:2.000   amc hornet        :  4  
 Max.   :24.80   Max.   :82.00   Max.   :3.000   chevrolet chevette:  4  
                                                 (Other)           :365  
View(Auto)
  1. Which of the predictors are quantitative, and which are qualitative?
sapply(Auto, class)
         mpg    cylinders displacement   horsepower       weight acceleration         year 
   "numeric"    "integer"    "numeric"    "integer"    "integer"    "numeric"    "integer" 
      origin         name 
   "integer"     "factor" 

Quantitative: mpg, cylinders, displacement, horsepower, weight, acceleration, year.

Qualitative: name, origin

  1. What is the range of each quantitative predictor? You can answer this using the range() function.
#Selecting quantitative predictors
qualitative_columns <- which(names(Auto) %in% c('name', 'origin'))
qualitative_columns
[1] 8 9
# Apply the range function to the columns of auto data that are not qualitative
sapply(Auto[, -qualitative_columns], range)
      mpg cylinders displacement horsepower weight acceleration year
[1,]  9.0         3           68         46   1613          8.0   70
[2,] 46.6         8          455        230   5140         24.8   82
  1. What is the mean and standard deviation of each quantitative predictor?
sapply(Auto[, -qualitative_columns], mean)
         mpg    cylinders displacement   horsepower       weight acceleration         year 
   23.445918     5.471939   194.411990   104.469388  2977.584184    15.541327    75.979592 
sapply(Auto[, -qualitative_columns], sd)
         mpg    cylinders displacement   horsepower       weight acceleration         year 
    7.805007     1.705783   104.644004    38.491160   849.402560     2.758864     3.683737 
  1. Now remove the 10th through 85th observations. What is the range, mean, and standard deviation of each predictor in the subset of the data that remains?
sapply(Auto[-seq(10, 85), -qualitative_columns], mean)
         mpg    cylinders displacement   horsepower       weight acceleration         year 
   24.404430     5.373418   187.240506   100.721519  2935.971519    15.726899    77.145570 
sapply(Auto[-seq(10, 85), -qualitative_columns], sd)
         mpg    cylinders displacement   horsepower       weight acceleration         year 
    7.867283     1.654179    99.678367    35.708853   811.300208     2.693721     3.106217 
  1. Using the full data set, investigate the predictors graphically, using scatterplots or other tools of your choice. Create some plots highlighting the relationships among the predictors. Comment on your findings.
pairs(Auto[, -qualitative_columns])

plot(mpg ~ weight, data = Auto)

# Heavier weight correlates with lower mpg.
plot(mpg ~ year, data = Auto)

# Cars become more efficient over time.
  1. Suppose that we wish to predict gas mileage (mpg) on the basis of the other variables. Do your plots suggest that any of the other variables might be useful in predicting mpg? Justify your answer.
pairs(Auto)

Yes, during that year, acceleration and origin would be good predictors of mpg.

\[\\[1in]\]

Question 10. This exercise involves the Boston housing data set.

  1. To begin, load in the Boston data set. The Boston data set is part of the ISLR2 library.
library(ISLR2)

Now the data set is contained in the object Boston.

Boston

Read about the data set:

?Boston

How many rows are in this data set? How many columns? What do the rows and columns represent?

There are 506 rows, and 13 columns. The rows represent the suburbs of Boston and the columns represent:

-crim: per capita crime rate by town.

-zn: proportion of residential land zoned for lots over 25,000 sq.ft.

-indus: proportion of non-retail business acres per town.

-chas: Charles River dummy variable (= 1 if tract bounds river; 0 otherwise).

-nox: nitrogen oxides concentration (parts per 10 million).

-rm: average number of rooms per dwelling.

-age: proportion of owner-occupied units built prior to 1940.

-dis: weighted mean of distances to five Boston employment centres.

-rad: index of accessibility to radial highways.

-tax: full-value property-tax rate per $10,000.

-ptratio: pupil-teacher ratio by town.

-lstat: lower status of the population (percent).

-medv: median value of owner-occupied homes in $1000s.

  1. Make some pairwise scatterplots of the predictors (columns) in this data set. Describe your findings.
pairs(Boston)

par(mfrow = c(2, 2))
plot(Boston$nox, Boston$crim)
plot(Boston$rm, Boston$crim)
plot(Boston$age, Boston$crim)
plot(Boston$dis, Boston$crim)

  1. Are any of the predictors associated with per capita crime rate? If so, explain the relationship.
plot(crim ~ age, data = Boston, log = "xy")

# Older homes, more crime
plot(crim ~ dis, data = Boston, log = "xy")

#Closer to work-area, more crime
  1. Do any of the census tracts of Boston appear to have particularly high crime rates? Tax rates? Pupil-teacher ratios? Comment on the range of each predictor.
par(mfrow=c(1,3))
hist(Boston$crim[Boston$crim > 1], breaks=25)
# most cities have low crime rates, but there is a long tail: 18 suburbs appear
# to have a crime rate > 20, reaching to above 80

hist(Boston$tax, breaks=25)
# there is a large divide between suburbs with low tax rates and a peak at 660-680

hist(Boston$ptratio, breaks=25)

  1. How many of the census tracts in this data set bound the Charles river?
summary(Boston$chas==1) 
   Mode   FALSE    TRUE 
logical     471      35 
  1. What is the median pupil-teacher ratio among the towns in this data set?
median(Boston$ptratio)
[1] 19.05
  1. Which census tract of Boston has lowest median value of owner- occupied homes? What are the values of the other predictors for that census tract, and how do those values compare to the overall ranges for those predictors? Comment on your findings.
which.min(Boston$medv)
[1] 399

Suburb #399 has the lowest median value of owner- occupied homes.

par(mfrow=c(5,3), mar=c(2, 2, 1, 0))
for (i in 1:ncol(Boston)){
  hist(Boston[, i], main=colnames(Boston)[i], breaks="FD")
  abline(v=Boston[399, i], col="red", lw=3)
}

  1. In this data set, how many of the census tracts average more than seven rooms per dwelling? More than eight rooms per dwelling? Comment on the census tracts that average more than eight rooms per dwelling.
summary(Boston$rm > 7)
   Mode   FALSE    TRUE 
logical     442      64 

There are 64 suburbs with more than 7 rooms per dwelling.

summary(Boston$rm > 8)
   Mode   FALSE    TRUE 
logical     493      13 

There are 13 suburbs with more than 8 rooms per dwelling

#Suburbs that average more than eight rooms per dwelling:#
summary(subset(Boston, rm > 8))
      crim               zn            indus             chas             nox        
 Min.   :0.02009   Min.   : 0.00   Min.   : 2.680   Min.   :0.0000   Min.   :0.4161  
 1st Qu.:0.33147   1st Qu.: 0.00   1st Qu.: 3.970   1st Qu.:0.0000   1st Qu.:0.5040  
 Median :0.52014   Median : 0.00   Median : 6.200   Median :0.0000   Median :0.5070  
 Mean   :0.71879   Mean   :13.62   Mean   : 7.078   Mean   :0.1538   Mean   :0.5392  
 3rd Qu.:0.57834   3rd Qu.:20.00   3rd Qu.: 6.200   3rd Qu.:0.0000   3rd Qu.:0.6050  
 Max.   :3.47428   Max.   :95.00   Max.   :19.580   Max.   :1.0000   Max.   :0.7180  
       rm             age             dis             rad              tax       
 Min.   :8.034   Min.   : 8.40   Min.   :1.801   Min.   : 2.000   Min.   :224.0  
 1st Qu.:8.247   1st Qu.:70.40   1st Qu.:2.288   1st Qu.: 5.000   1st Qu.:264.0  
 Median :8.297   Median :78.30   Median :2.894   Median : 7.000   Median :307.0  
 Mean   :8.349   Mean   :71.54   Mean   :3.430   Mean   : 7.462   Mean   :325.1  
 3rd Qu.:8.398   3rd Qu.:86.50   3rd Qu.:3.652   3rd Qu.: 8.000   3rd Qu.:307.0  
 Max.   :8.780   Max.   :93.90   Max.   :8.907   Max.   :24.000   Max.   :666.0  
    ptratio          lstat           medv     
 Min.   :13.00   Min.   :2.47   Min.   :21.9  
 1st Qu.:14.70   1st Qu.:3.32   1st Qu.:41.7  
 Median :17.40   Median :4.14   Median :48.3  
 Mean   :16.36   Mean   :4.31   Mean   :44.2  
 3rd Qu.:17.40   3rd Qu.:5.12   3rd Qu.:50.0  
 Max.   :20.20   Max.   :7.44   Max.   :50.0  
summary(Boston)
      crim                zn             indus            chas              nox        
 Min.   : 0.00632   Min.   :  0.00   Min.   : 0.46   Min.   :0.00000   Min.   :0.3850  
 1st Qu.: 0.08205   1st Qu.:  0.00   1st Qu.: 5.19   1st Qu.:0.00000   1st Qu.:0.4490  
 Median : 0.25651   Median :  0.00   Median : 9.69   Median :0.00000   Median :0.5380  
 Mean   : 3.61352   Mean   : 11.36   Mean   :11.14   Mean   :0.06917   Mean   :0.5547  
 3rd Qu.: 3.67708   3rd Qu.: 12.50   3rd Qu.:18.10   3rd Qu.:0.00000   3rd Qu.:0.6240  
 Max.   :88.97620   Max.   :100.00   Max.   :27.74   Max.   :1.00000   Max.   :0.8710  
       rm             age              dis              rad              tax       
 Min.   :3.561   Min.   :  2.90   Min.   : 1.130   Min.   : 1.000   Min.   :187.0  
 1st Qu.:5.886   1st Qu.: 45.02   1st Qu.: 2.100   1st Qu.: 4.000   1st Qu.:279.0  
 Median :6.208   Median : 77.50   Median : 3.207   Median : 5.000   Median :330.0  
 Mean   :6.285   Mean   : 68.57   Mean   : 3.795   Mean   : 9.549   Mean   :408.2  
 3rd Qu.:6.623   3rd Qu.: 94.08   3rd Qu.: 5.188   3rd Qu.:24.000   3rd Qu.:666.0  
 Max.   :8.780   Max.   :100.00   Max.   :12.127   Max.   :24.000   Max.   :711.0  
    ptratio          lstat            medv      
 Min.   :12.60   Min.   : 1.73   Min.   : 5.00  
 1st Qu.:17.40   1st Qu.: 6.95   1st Qu.:17.02  
 Median :19.05   Median :11.36   Median :21.20  
 Mean   :18.46   Mean   :12.65   Mean   :22.53  
 3rd Qu.:20.20   3rd Qu.:16.95   3rd Qu.:25.00  
 Max.   :22.00   Max.   :37.97   Max.   :50.00  

Relatively lower crime (comparing range), lower lstat (comparing range)

LS0tCnRpdGxlOiAiQXNzaWdubWVudCAxIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCiMjIFN0YXRpc3RpY2FsIExlYXJuaW5nCgokJFxcWzFpbl0kJAoKKipRdWVzdGlvbiAyKiouIEV4cGxhaW4gd2hldGhlciBlYWNoIHNjZW5hcmlvIGlzIGEgY2xhc3NpZmljYXRpb24gb3IgcmVncmVzc2lvbiBwcm9ibGVtLCBhbmQgaW5kaWNhdGUgd2hldGhlciB3ZSBhcmUgbW9zdCBpbnRlcmVzdGVkIGluIGluZmVyZW5jZSBvciBwcmVkaWN0aW9uLiBGaW5hbGx5LCBwcm92aWRlIG4gYW5kIHAuCgooYSkgV2UgY29sbGVjdCBhIHNldCBvZiBkYXRhIG9uIHRoZSB0b3AgNTAwIGZpcm1zIGluIHRoZSBVUy4gRm9yIGVhY2ggZmlybSB3ZSByZWNvcmQgcHJvZml0LCBudW1iZXIgb2YgZW1wbG95ZWVzLCBpbmR1c3RyeSBhbmQgdGhlIENFTyBzYWxhcnkuIFdlIGFyZSBpbnRlcmVzdGVkIGluIHVuZGVyc3RhbmRpbmcgd2hpY2ggZmFjdG9ycyBhZmZlY3QgQ0VPIHNhbGFyeS4gCgpUaGlzIGlzIGEgcmVncmVzc2lvbiBwcm9ibGVtLCBhbmQgd2UgYXJlIGludGVyZXN0ZWQgaW4gaW5mZXJlbmNlLiBuID0gNTAwIGFuZCBwID0gMyAKCihiKSBXZSBhcmUgY29uc2lkZXJpbmcgbGF1bmNoaW5nIGEgbmV3IHByb2R1Y3QgYW5kIHdpc2ggdG8ga25vdyB3aGV0aGVyIGl0IHdpbGwgYmUgYSBzdWNjZXNzIG9yIGEgZmFpbHVyZS4gV2UgY29sbGVjdCBkYXRhIG9uIDIwIHNpbWlsYXIgcHJvZHVjdHMgdGhhdCB3ZXJlIHByZXZpb3VzbHkgbGF1bmNoZWQuIEZvciBlYWNoIHByb2R1Y3Qgd2UgaGF2ZSByZWNvcmRlZCB3aGV0aGVyIGl0IHdhcyBhIHN1Y2Nlc3Mgb3IgZmFpbHVyZSwgcHJpY2UgY2hhcmdlZCBmb3IgdGhlIHByb2R1Y3QsIG1hcmtldGluZyBidWRnZXQsIGNvbXBldGl0aW9uIHByaWNlLCBhbmQgdGVuIG90aGVyIHZhcmlhYmxlcy4gCgpUaGlzIGlzIGEgY2xhc3NpZmljYXRpb24gcHJvYmxlbSwgYW5kIHdlIGFyZSBtb3N0IGludGVyZXN0ZWQgaW4gcHJlZGljdGlvbi4gbiA9IDIwICgyMCBzaW1pbGFyIHByb2R1Y3RzIHByZXZpb3VzbHkgbGF1bmNoZWQpIGFuZCBwID0gMTMgKHByaWNlLCBtYXJrZXRpbmcgYnVkZ2V0LCBjb21wZXRpdGlvbiBwcmljZSwgYW5kIHRlbiBvdGhlciB2YXJpYWJsZXMpLgoKKGMpIFdlIGFyZSBpbnRlcmVzdGluZyBpbiBwcmVkaWN0aW5nIHRoZSAlIGNoYW5nZSBpbiB0aGUgVVMgZG9sbGFyIGluIHJlbGF0aW9uIHRvIHRoZSB3ZWVrbHkgY2hhbmdlcyBpbiB0aGUgd29ybGQgc3RvY2sgbWFya2V0cy4gSGVuY2Ugd2UgY29sbGVjdCB3ZWVrbHkgZGF0YSBmb3IgYWxsIG9mIDIwMTIuIEZvciBlYWNoIHdlZWsgd2UgcmVjb3JkIHRoZSAlIGNoYW5nZSBpbiB0aGUgZG9sbGFyLCB0aGUgJSBjaGFuZ2UgaW4gdGhlIFVTIG1hcmtldCwgdGhlICUgY2hhbmdlIGluIHRoZSBCcml0aXNoIG1hcmtldCwgYW5kIHRoZSAlIGNoYW5nZSBpbiB0aGUgR2VybWFuIG1hcmtldC4KClRoaXMgaXMgYSByZWdyZXNzaW9uIHByb2JsZW0gYmVjYXVzZSAlIGNoYW5nZSBpbiB0aGUgVVMgZG9sbGFyIGlzIGEgcXVhbnRpdGF0aXZlIERWLiBBbHNvLCBpdCBpcyBhIHByZWRpY3Rpb24gcHJvYmxlbSBhcyB3ZWxsIGJlY2F1c2UgaXQgc3RhdGVzICJ3ZSBhcmUgaW50ZXJlc3RlZCBpbiBwcmVkaWN0aW5nIHRoZSAlIGNoYW5nZSIuIG4gPSA1MiAod2Vla2x5IGRhdGEgb3ZlciAyMDEyKSBhbmQgcCA9IDMgKCUgY2hhbmdlIGluIFVTLCAlIGNoYW5nZSBpbiBCcml0aXNoLCAlIGNoYW5nZSBpbiBHZXJtYW4pLgoKJCRcXFsxaW5dJCQKCioqUXVlc3Rpb24gNSoqLiBXaGF0IGFyZSB0aGUgYWR2YW50YWdlcyBhbmQgZGlzYWR2YW50YWdlcyBvZiBhIHZlcnkgZmxleGlibGUgKHZlcnN1cyBhIGxlc3MgZmxleGlibGUpIGFwcHJvYWNoIGZvciByZWdyZXNzaW9uIG9yIGNsYXNzaWZpY2F0aW9uPyBVbmRlciB3aGF0IGNpcmN1bXN0YW5jZXMgbWlnaHQgYSBtb3JlIGZsZXhpYmxlIGFwcHJvYWNoIGJlIHByZWZlcnJlZCB0byBhIGxlc3MgZmxleGlibGUgYXBwcm9hY2g/IFdoZW4gbWlnaHQgYSBsZXNzIGZsZXhpYmxlIGFwcHJvYWNoIGJlIHByZWZlcnJlZD8KCi1UaGUgYWR2YW50YWdlcyBvZiBhIHZlcnkgZmxleGlibGUgYXBwcm9hY2ggYXJlIHRoYXQgaXQgZGVjcmVhc2VzIHRoZWlyIGJpYXMsIGFuZCBpdCBjYW4gYWxzbyBnaXZlIGEgYmV0dGVyIGZpdCBmb3Igbm9uLWxpbmVhciBtb2RlbHMuIAoKLVRoZSBkaXNhZHZhbnRhZ2VzIG9mIHRoaXMgYXJlIHRoYXQgaXQgcmVxdWlyZXMgZXN0aW1hdGluZyBhIGxhcmdlciBudW1iZXIgb2YgcGFyYW1ldGVycywgdGhlcmVmb3JlIGluY3JlYXNpbmcgdGhlIHZhcmlhbmNlLgoKLUEgbW9yZSBmbGV4aWJsZSBhcHByb2FjaCBiZXR0ZXIgd2hlbiB0aGUgcmVsYXRpb25zaGlwIGlzIGhpZ2hseSBub24tbGluZWFyLiBUaGlzIGlzIGJlY2F1c2UgeW91IGhhdmUgc2V2ZXJhbCBkYXRhIHBvaW50cyB0byBmaW5kIGEgcGF0dGVybiwgYW5kL29yIHRoZSBpcnJlZHVjaWJsZSBlcnJvciBpcyBsb3cuIAoKLUEgbGVzcyBmbGV4aWJsZSBhcHByb2FjaCBpcyBiZXN0IHdoZW4gdGhlIHJlbGF0aW9uc2hpcCBpcyB2ZXJ5IGxpbmVhciBzaW5jZSB5b3UgZG9uJ3QgaGF2ZSB0aGF0IG1hbnkgZGF0YSBwb2ludHMsIGFuZC9vciB0aGUgaXJyZWR1Y2libGUgZXJyb3IgaXMgaGlnaC4KCi1BIGxlc3MgZmxleGlibGUgYXBwcm9hY2ggd291bGQgYmUgcHJlZmVycmVkIHZzLiBhIG1vcmUgZmxleGlibGUgYXBwcm9hY2ggd2hlbiB3ZSBhcmUgbG9va2luZyBmb3IgaW5mZXJlbmNlIGFuZCB0aGUgaW50ZXJwcmV0YWJpbGl0eSBvZiB0aGUgb3V0cHV0LgoKJCRcXFsxaW5dJCQKCioqUXVlc3Rpb24gNioqLiBEZXNjcmliZSB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBhIHBhcmFtZXRyaWMgYW5kIGEgbm9uLXBhcmFtZXRyaWMgc3RhdGlzdGljYWwgbGVhcm5pbmcgYXBwcm9hY2guIFdoYXQgYXJlIHRoZSBhZHZhbnRhZ2VzIG9mIGEgcGFyYW1ldHJpYyBhcHByb2FjaCB0byByZWdyZXNzaW9uIG9yIGNsYXNzaWZpY2F0aW9uIChhcyBvcHBvc2VkIHRvIGEgbm9uLSBwYXJhbWV0cmljIGFwcHJvYWNoKT8gV2hhdCBhcmUgaXRzIGRpc2FkdmFudGFnZXM/CgpCZWNhdXNlIGZld2VyIGFzc3VtcHRpb25zIGFyZSBtYWRlIHJlZ2FyZGluZyB0aGUgZGF0YSBzdHJ1Y3R1cmUsIGEgbm9uLXBhcmFtZXRyaWMgbWV0aG9kIGlzIGJldHRlciBhdCBmaXR0aW5nIGhpZ2hseSBub25saW5lYXIgcGF0dGVybnMuIEhvd2V2ZXIsIGluIGNpcmN1bXN0YW5jZXMgd2hlcmUgdGhlcmUgaXMgYSBjb25zaWRlcmFibGUgcmlzayBvZiBvdmVyZml0dGluZyAsIHRoaXMgY291bGQgYmUgaGFybWZ1bC4gRnVydGhlcm1vcmUsIHNpbmNlIHlvdSBsYWNrIHRoZSBpbnRlcnByZXRhdGlvbiBzdHJ1Y3R1cmUgb2YgdGhlIHBhcmFtZXRlcnMsIHlvdSB3aWxsIGZpbmQgaXQgZGlmZmljdWx0IHRvIHVuZGVyc3RhbmQgdGhlIGRhdGEuCgokJFxcWzFpbl0kJAoKKipRdWVzdGlvbiA4KiouIFRoaXMgZXhlcmNpc2UgcmVsYXRlcyB0byB0aGUg4oCcQ29sbGVnZeKAnSBkYXRhIHNldCwgd2hpY2ggY2FuIGJlIGZvdW5kIGluIHRoZSBmaWxlIOKAnENvbGxlZ2UuY3N24oCdLiBJdCBjb250YWlucyBhIG51bWJlciBvZiB2YXJpYWJsZXMgZm9yIDc3NyBkaWZmZXJlbnQgdW5pdmVyc2l0aWVzIGFuZCBjb2xsZWdlcyBpbiB0aGUgVVMuCgooYSkuIFVzZSB0aGUgcmVhZC5jc3YoKSBmdW5jdGlvbiB0byByZWFkIHRoZSBkYXRhIGludG8gUi4gQ2FsbCB0aGUgbG9hZGVkIGRhdGEg4oCcY29sbGVnZeKAnS4gTWFrZSBzdXJlIHRoYXQgeW91IGhhdmUgdGhlIGRpcmVjdG9yeSBzZXQgdG8gdGhlIGNvcnJlY3QgbG9jYXRpb24gZm9yIHRoZSBkYXRhLgpgYGB7cn0KbGlicmFyeShyZWFkcikKQ29sbGVnZSA8LSByZWFkLmNzdigifi9Eb3dubG9hZHMvQ29sbGVnZS5jc3YiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmBgYAoKKGIpLiBMb29rIGF0IHRoZSBkYXRhIHVzaW5nIHRoZSB2aWV3KCkgZnVuY3Rpb24uIFlvdSBzaG91bGQgbm90aWNlIHRoYXQgdGhlIGZpcnN0IGNvbHVtbiBpcyBqdXN0IHRoZSBuYW1lIG9mIGVhY2ggdW5pdmVyc2l0eS4gV2UgZG9u4oCZdCByZWFsbHkgd2FudCBSIHRvIHRyZWF0IHRoaXMgYXMgZGF0YS4gSG93ZXZlciwgaXQgbWF5IGJlIGhhbmR5IHRvIGhhdmUgdGhlc2UgbmFtZXMgZm9yIGxhdGVyLiBUcnkgdGhlIGZvbGxvd2luZyBjb21tYW5kczoKCmBgYHtyfQpyb3duYW1lcyhDb2xsZWdlKSA8LSBDb2xsZWdlWywgMV0gClZpZXcoQ29sbGVnZSkKYGBgCmBgYHtyfQpDb2xsZWdlIDwtIENvbGxlZ2VbLCAtMV0KVmlldyhDb2xsZWdlKQpgYGAKCihjKS4KaS4gVXNlIHRoZSBzdW1tYXJ5KCkgZnVuY3Rpb24gdG8gcHJvZHVjZSBhIG51bWVyaWNhbCBzdW1tYXJ5IG9mIHRoZSB2YXJpYWJsZXMgaW4gdGhlIGRhdGEgc2V0LgpgYGB7cn0Kc3VtbWFyeShDb2xsZWdlKQpgYGAKCgoKaWkuIFVzZSB0aGUgcGFpcnMoKSBmdW5jdGlvbiB0byBwcm9kdWNlIGEgc2NhdHRlcnBsb3QgbWF0cml4IG9mIHRoZSBmaXJzdCB0ZW4gY29sdW1ucyBvciB2YXJpYWJsZXMgb2YgdGhlIGRhdGEuIFJlY2FsbCB0aGF0IHlvdSBjYW4gcmVmZXJlbmNlIHRoZSBmaXJzdCB0ZW4gY29sdW1ucyBvZiBhIG1hdHJpeCBBIHVzaW5nIEFbLDE6MTBdLgoKCgoKaWlpLiBVc2UgdGhlIHBsb3QoKSBmdW5jdGlvbiB0byBwcm9kdWNlIHNpZGUtYnktc2lkZSBib3hwbG90cyBvZiBPdXRzdGF0ZSB2ZXJzdXMgUHJpdmF0ZS4KCgoKaXYuIENyZWF0ZSBhIG5ldyBxdWFsaXRhdGl2ZSB2YXJpYWJsZSwgY2FsbGVkICoqRWxpdGUqKiwgYnkgYmlubmluZyB0aGUgKipUb3AxMHBlcmMqKiB2YXJpYWJsZS4gV2UgYXJlIGdvaW5nIHRvIGRpdmlkZSB1bml2ZXJzaXRpZXMgaW50byB0d28gZ3JvdXBzIGJhc2VkIG9uIHdoZXRoZXIgb3Igbm90IHRoZSBwcm9wb3J0aW9uIG9mIHN0dWRlbnRzIGNvbWluZyBmcm9tIHRoZSB0b3AgMTAlIG9mIHRoZWlyIGhpZ2ggc2Nob29sIGNsYXNzZXMgZXhjZWVkcyA1MCAlLgoKYGBge3J9CiBFbGl0ZSA8LSByZXAoIk5vIiwgbnJvdyhDb2xsZWdlKSkKIEVsaXRlW0NvbGxlZ2UkVG9wMTBwZXJjID4gNTBdIDwtICJZZXMiCiBFbGl0ZSA8LSBhcy5mYWN0b3IoRWxpdGUpCkNvbGxlZ2UgPC0gZGF0YS5mcmFtZShDb2xsZWdlLCBFbGl0ZSkKYGBgCgpgYGB7cn0Kc3VtbWFyeShFbGl0ZSkKYGBgCgpUaGVyZSBhcmUgNzggRWxpdGUgc2Nob29scy4gCgoKYGBge3J9CnBsb3QoT3V0c3RhdGUgfiBFbGl0ZSwgZGF0YSA9IENvbGxlZ2UsIAogICAgIHhsYWIgPSAiRWxpdGUgVW5pdmVyc2l0eSIsIAogICAgIHlsYWIgPSAiVHVpdGlvbiBpbiAkIikKYGBgCgp2LiBVc2UgdGhlIGhpc3QoKSBmdW5jdGlvbiB0byBwcm9kdWNlIHNvbWUgaGlzdG9ncmFtcyB3aXRoIGRpZmZlcmluZyBudW1iZXJzIG9mIGJpbnMgZm9yIGEgZmV3IG9mIHRoZSBxdWFudGl0YXRpdmUgdmFyaS0gYWJsZXMuIFlvdSBtYXkgZmluZCB0aGUgY29tbWFuZCBwYXIobWZyb3cgPSBjKDIsIDIpKSB1c2VmdWw6IGl0IHdpbGwgZGl2aWRlIHRoZSBwcmludCB3aW5kb3cgaW50byBmb3VyIHJlZ2lvbnMgc28gdGhhdCBmb3VyIHBsb3RzIGNhbiBiZSBtYWRlIHNpbXVsdGFuZW91c2x5LiBNb2RpZnlpbmcgdGhlIGFyZ3VtZW50cyB0byB0aGlzIGZ1bmN0aW9uIHdpbGwgZGl2aWRlIHRoZSBzY3JlZW4gaW4gb3RoZXIgd2F5cy4KCmBgYHtyfQpwYXIobWZyb3c9YygyLDIpKQpoaXN0KENvbGxlZ2UkVG9wMTBwZXJjLCB4bGFiID0gIlRvcCAxMCUiLCBtYWluPSIiKQpoaXN0KENvbGxlZ2UkVG9wMjVwZXJjLCB4bGFiID0gIlRvcCAyNSUiLCBtYWluPSIiKQpoaXN0KENvbGxlZ2UkR3JhZC5SYXRlLCB4bGFiID0gIkdyYWR1YXRpb24gcmF0ZSIsIG1haW49IiIpCmhpc3QoQ29sbGVnZSRQaEQsIHhsYWIgPSAiUHJvcG9ydGlvbiBvZiBmYWN1bHR5IHdpdGggUGguRC7igJlzIiwgbWFpbj0iIikKYGBgCgp2aS4gQ29udGludWUgZXhwbG9yaW5nIHRoZSBkYXRhLCBhbmQgcHJvdmlkZSBhIGJyaWVmIHN1bW1hcnkgb2Ygd2hhdCB5b3UgZGlzY292ZXIuCgpgYGB7cn0Kc3VtbWFyeShDb2xsZWdlJEJvb2tzKQpgYGAKVGhlIGF2YXJhZ2UgYW1vdW50IG9mIG1vbmV5IHRoYXQgc3R1ZGVudHMgc3BlbmQgb24gYm9va3MgaXMgJDU0OSwgd2hpY2ggaXMgYSBsb3Qgb2YgbW9uZXkhCgokJFxcWzFpbl0kJAoKKipRdWVzdGlvbiA5KiouIFRoaXMgZXhlcmNpc2UgaW52b2x2ZXMgdGhlIEF1dG8gZGF0YSBzZXQgc3R1ZGllZCBpbiB0aGUgbGFiLiBNYWtlIHN1cmUgdGhhdCB0aGUgbWlzc2luZyB2YWx1ZXMgaGF2ZSBiZWVuIHJlbW92ZWQgZnJvbSB0aGUgZGF0YS4KCmBgYHtyfQpkYXRhKEF1dG8pCnN1bW1hcnkoQXV0bykKYGBgCgpgYGB7cn0KVmlldyhBdXRvKQpgYGAKCihhKSBXaGljaCBvZiB0aGUgcHJlZGljdG9ycyBhcmUgcXVhbnRpdGF0aXZlLCBhbmQgd2hpY2ggYXJlIHF1YWxpdGF0aXZlPwoKYGBge3J9CnNhcHBseShBdXRvLCBjbGFzcykKYGBgCioqUXVhbnRpdGF0aXZlOioqIG1wZywgY3lsaW5kZXJzLCBkaXNwbGFjZW1lbnQsIGhvcnNlcG93ZXIsIHdlaWdodCwgYWNjZWxlcmF0aW9uLCB5ZWFyLgoKKipRdWFsaXRhdGl2ZToqKiBuYW1lLCBvcmlnaW4KCihiKSBXaGF0IGlzIHRoZSByYW5nZSBvZiBlYWNoIHF1YW50aXRhdGl2ZSBwcmVkaWN0b3I/IFlvdSBjYW4gYW5zd2VyIHRoaXMgdXNpbmcgdGhlIHJhbmdlKCkgZnVuY3Rpb24uCgpgYGB7cn0KI1NlbGVjdGluZyBxdWFudGl0YXRpdmUgcHJlZGljdG9ycwpxdWFsaXRhdGl2ZV9jb2x1bW5zIDwtIHdoaWNoKG5hbWVzKEF1dG8pICVpbiUgYygnbmFtZScsICdvcmlnaW4nKSkKcXVhbGl0YXRpdmVfY29sdW1ucwpgYGAKYGBge3J9CiMgQXBwbHkgdGhlIHJhbmdlIGZ1bmN0aW9uIHRvIHRoZSBjb2x1bW5zIG9mIGF1dG8gZGF0YSB0aGF0IGFyZSBub3QgcXVhbGl0YXRpdmUKc2FwcGx5KEF1dG9bLCAtcXVhbGl0YXRpdmVfY29sdW1uc10sIHJhbmdlKQpgYGAKCgooYykgV2hhdCBpcyB0aGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGVhY2ggcXVhbnRpdGF0aXZlIHByZWRpY3Rvcj8KCmBgYHtyfQpzYXBwbHkoQXV0b1ssIC1xdWFsaXRhdGl2ZV9jb2x1bW5zXSwgbWVhbikKYGBgCmBgYHtyfQpzYXBwbHkoQXV0b1ssIC1xdWFsaXRhdGl2ZV9jb2x1bW5zXSwgc2QpCmBgYAoKCihkKSBOb3cgcmVtb3ZlIHRoZSAxMHRoIHRocm91Z2ggODV0aCBvYnNlcnZhdGlvbnMuIFdoYXQgaXMgdGhlIHJhbmdlLCBtZWFuLCBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGVhY2ggcHJlZGljdG9yIGluIHRoZSBzdWJzZXQgb2YgdGhlIGRhdGEgdGhhdCByZW1haW5zPwoKYGBge3J9CnNhcHBseShBdXRvWy1zZXEoMTAsIDg1KSwgLXF1YWxpdGF0aXZlX2NvbHVtbnNdLCBtZWFuKQpgYGAKYGBge3J9CnNhcHBseShBdXRvWy1zZXEoMTAsIDg1KSwgLXF1YWxpdGF0aXZlX2NvbHVtbnNdLCBzZCkKYGBgCgoKKGUpIFVzaW5nIHRoZSBmdWxsIGRhdGEgc2V0LCBpbnZlc3RpZ2F0ZSB0aGUgcHJlZGljdG9ycyBncmFwaGljYWxseSwgdXNpbmcgc2NhdHRlcnBsb3RzIG9yIG90aGVyIHRvb2xzIG9mIHlvdXIgY2hvaWNlLiBDcmVhdGUgc29tZSBwbG90cyBoaWdobGlnaHRpbmcgdGhlIHJlbGF0aW9uc2hpcHMgYW1vbmcgdGhlIHByZWRpY3RvcnMuIENvbW1lbnQgb24geW91ciBmaW5kaW5ncy4KIApgYGB7cn0KcGFpcnMoQXV0b1ssIC1xdWFsaXRhdGl2ZV9jb2x1bW5zXSkKYGBgCgpgYGB7cn0KcGxvdChtcGcgfiB3ZWlnaHQsIGRhdGEgPSBBdXRvKQojIEhlYXZpZXIgd2VpZ2h0IGNvcnJlbGF0ZXMgd2l0aCBsb3dlciBtcGcuCmBgYAoKYGBge3J9CnBsb3QobXBnIH4geWVhciwgZGF0YSA9IEF1dG8pCiMgQ2FycyBiZWNvbWUgbW9yZSBlZmZpY2llbnQgb3ZlciB0aW1lLgpgYGAKCihmKSBTdXBwb3NlIHRoYXQgd2Ugd2lzaCB0byBwcmVkaWN0IGdhcyBtaWxlYWdlIChtcGcpIG9uIHRoZSBiYXNpcyBvZiB0aGUgb3RoZXIgdmFyaWFibGVzLiBEbyB5b3VyIHBsb3RzIHN1Z2dlc3QgdGhhdCBhbnkgb2YgdGhlIG90aGVyIHZhcmlhYmxlcyBtaWdodCBiZSB1c2VmdWwgaW4gcHJlZGljdGluZyBtcGc/IEp1c3RpZnkgeW91ciBhbnN3ZXIuCgpgYGB7cn0KcGFpcnMoQXV0bykKYGBgClllcywgZHVyaW5nIHRoYXQgeWVhciwgYWNjZWxlcmF0aW9uIGFuZCBvcmlnaW4gd291bGQgYmUgZ29vZCBwcmVkaWN0b3JzIG9mIG1wZy4gCgoKJCRcXFsxaW5dJCQKCioqUXVlc3Rpb24gMTAqKi4gVGhpcyBleGVyY2lzZSBpbnZvbHZlcyB0aGUgQm9zdG9uIGhvdXNpbmcgZGF0YSBzZXQuCgooYSkgVG8gYmVnaW4sIGxvYWQgaW4gdGhlIEJvc3RvbiBkYXRhIHNldC4gVGhlIEJvc3RvbiBkYXRhIHNldCBpcwpwYXJ0IG9mIHRoZSBJU0xSMiBsaWJyYXJ5LgoKCmBgYHtyfQpsaWJyYXJ5KElTTFIyKQpgYGAKCk5vdyB0aGUgZGF0YSBzZXQgaXMgY29udGFpbmVkIGluIHRoZSBvYmplY3QgQm9zdG9uLgpgYGB7cn0KQm9zdG9uCmBgYAoKUmVhZCBhYm91dCB0aGUgZGF0YSBzZXQ6CmBgYHtyfQo/Qm9zdG9uCmBgYAoKSG93IG1hbnkgcm93cyBhcmUgaW4gdGhpcyBkYXRhIHNldD8gSG93IG1hbnkgY29sdW1ucz8gV2hhdCBkbyB0aGUgcm93cyBhbmQgY29sdW1ucyByZXByZXNlbnQ/CgpUaGVyZSBhcmUgNTA2IHJvd3MsIGFuZCAxMyBjb2x1bW5zLiBUaGUgcm93cyByZXByZXNlbnQgdGhlIHN1YnVyYnMgb2YgQm9zdG9uIGFuZCB0aGUgY29sdW1ucyByZXByZXNlbnQ6CgotY3JpbTogcGVyIGNhcGl0YSBjcmltZSByYXRlIGJ5IHRvd24uCgotem46IHByb3BvcnRpb24gb2YgcmVzaWRlbnRpYWwgbGFuZCB6b25lZCBmb3IgbG90cyBvdmVyIDI1LDAwMCBzcS5mdC4KCi1pbmR1czogcHJvcG9ydGlvbiBvZiBub24tcmV0YWlsIGJ1c2luZXNzIGFjcmVzIHBlciB0b3duLgoKLWNoYXM6IENoYXJsZXMgUml2ZXIgZHVtbXkgdmFyaWFibGUgKD0gMSBpZiB0cmFjdCBib3VuZHMgcml2ZXI7IDAgb3RoZXJ3aXNlKS4KCi1ub3g6IG5pdHJvZ2VuIG94aWRlcyBjb25jZW50cmF0aW9uIChwYXJ0cyBwZXIgMTAgbWlsbGlvbikuCgotcm06IGF2ZXJhZ2UgbnVtYmVyIG9mIHJvb21zIHBlciBkd2VsbGluZy4KCi1hZ2U6IHByb3BvcnRpb24gb2Ygb3duZXItb2NjdXBpZWQgdW5pdHMgYnVpbHQgcHJpb3IgdG8gMTk0MC4KCi1kaXM6IHdlaWdodGVkIG1lYW4gb2YgZGlzdGFuY2VzIHRvIGZpdmUgQm9zdG9uIGVtcGxveW1lbnQgY2VudHJlcy4KCi1yYWQ6IGluZGV4IG9mIGFjY2Vzc2liaWxpdHkgdG8gcmFkaWFsIGhpZ2h3YXlzLgoKLXRheDogZnVsbC12YWx1ZSBwcm9wZXJ0eS10YXggcmF0ZSBwZXIgJDEwLDAwMC4KCi1wdHJhdGlvOiBwdXBpbC10ZWFjaGVyIHJhdGlvIGJ5IHRvd24uCgotbHN0YXQ6IGxvd2VyIHN0YXR1cyBvZiB0aGUgcG9wdWxhdGlvbiAocGVyY2VudCkuCgotbWVkdjogbWVkaWFuIHZhbHVlIG9mIG93bmVyLW9jY3VwaWVkIGhvbWVzIGluICQxMDAwcy4KCgoKKGIpIE1ha2Ugc29tZSBwYWlyd2lzZSBzY2F0dGVycGxvdHMgb2YgdGhlIHByZWRpY3RvcnMgKGNvbHVtbnMpIGluIHRoaXMgZGF0YSBzZXQuIERlc2NyaWJlIHlvdXIgZmluZGluZ3MuCgpgYGB7cn0KcGFpcnMoQm9zdG9uKQpgYGAKCmBgYHtyfQpwYXIobWZyb3cgPSBjKDIsIDIpKQpwbG90KEJvc3RvbiRub3gsIEJvc3RvbiRjcmltKQpwbG90KEJvc3RvbiRybSwgQm9zdG9uJGNyaW0pCnBsb3QoQm9zdG9uJGFnZSwgQm9zdG9uJGNyaW0pCnBsb3QoQm9zdG9uJGRpcywgQm9zdG9uJGNyaW0pCmBgYAoKCihjKSBBcmUgYW55IG9mIHRoZSBwcmVkaWN0b3JzIGFzc29jaWF0ZWQgd2l0aCBwZXIgY2FwaXRhIGNyaW1lIHJhdGU/IElmIHNvLCBleHBsYWluIHRoZSByZWxhdGlvbnNoaXAuCgpgYGB7cn0KcGxvdChjcmltIH4gYWdlLCBkYXRhID0gQm9zdG9uLCBsb2cgPSAieHkiKQojIE9sZGVyIGhvbWVzLCBtb3JlIGNyaW1lCmBgYAoKYGBge3J9CnBsb3QoY3JpbSB+IGRpcywgZGF0YSA9IEJvc3RvbiwgbG9nID0gInh5IikKI0Nsb3NlciB0byB3b3JrLWFyZWEsIG1vcmUgY3JpbWUKYGBgCgoKKGQpIERvIGFueSBvZiB0aGUgY2Vuc3VzIHRyYWN0cyBvZiBCb3N0b24gYXBwZWFyIHRvIGhhdmUgcGFydGljdWxhcmx5IGhpZ2ggY3JpbWUgcmF0ZXM/IFRheCByYXRlcz8gUHVwaWwtdGVhY2hlciByYXRpb3M/IENvbW1lbnQgb24gdGhlIHJhbmdlIG9mIGVhY2ggcHJlZGljdG9yLgoKYGBge3J9CnBhcihtZnJvdz1jKDEsMykpCmhpc3QoQm9zdG9uJGNyaW1bQm9zdG9uJGNyaW0gPiAxXSwgYnJlYWtzPTI1KQojIG1vc3QgY2l0aWVzIGhhdmUgbG93IGNyaW1lIHJhdGVzLCBidXQgdGhlcmUgaXMgYSBsb25nIHRhaWw6IDE4IHN1YnVyYnMgYXBwZWFyCiMgdG8gaGF2ZSBhIGNyaW1lIHJhdGUgPiAyMCwgcmVhY2hpbmcgdG8gYWJvdmUgODAKCmhpc3QoQm9zdG9uJHRheCwgYnJlYWtzPTI1KQojIHRoZXJlIGlzIGEgbGFyZ2UgZGl2aWRlIGJldHdlZW4gc3VidXJicyB3aXRoIGxvdyB0YXggcmF0ZXMgYW5kIGEgcGVhayBhdCA2NjAtNjgwCgpoaXN0KEJvc3RvbiRwdHJhdGlvLCBicmVha3M9MjUpCmBgYAoKCihlKSBIb3cgbWFueSBvZiB0aGUgY2Vuc3VzIHRyYWN0cyBpbiB0aGlzIGRhdGEgc2V0IGJvdW5kIHRoZSBDaGFybGVzIHJpdmVyPwpgYGB7cn0Kc3VtbWFyeShCb3N0b24kY2hhcz09MSkgCmBgYAoKCihmKSBXaGF0IGlzIHRoZSBtZWRpYW4gcHVwaWwtdGVhY2hlciByYXRpbyBhbW9uZyB0aGUgdG93bnMgaW4gdGhpcyBkYXRhIHNldD8KYGBge3J9Cm1lZGlhbihCb3N0b24kcHRyYXRpbykKYGBgCgoKKGcpIFdoaWNoIGNlbnN1cyB0cmFjdCBvZiBCb3N0b24gaGFzIGxvd2VzdCBtZWRpYW4gdmFsdWUgb2Ygb3duZXItIG9jY3VwaWVkIGhvbWVzPyBXaGF0IGFyZSB0aGUgdmFsdWVzIG9mIHRoZSBvdGhlciBwcmVkaWN0b3JzIGZvciB0aGF0IGNlbnN1cyB0cmFjdCwgYW5kIGhvdyBkbyB0aG9zZSB2YWx1ZXMgY29tcGFyZSB0byB0aGUgb3ZlcmFsbCByYW5nZXMgZm9yIHRob3NlIHByZWRpY3RvcnM/IENvbW1lbnQgb24geW91ciBmaW5kaW5ncy4KCmBgYHtyfQp3aGljaC5taW4oQm9zdG9uJG1lZHYpCmBgYApTdWJ1cmIgIzM5OSBoYXMgdGhlIGxvd2VzdCBtZWRpYW4gdmFsdWUgb2Ygb3duZXItIG9jY3VwaWVkIGhvbWVzLiAKCmBgYHtyfQpwYXIobWZyb3c9Yyg1LDMpLCBtYXI9YygyLCAyLCAxLCAwKSkKZm9yIChpIGluIDE6bmNvbChCb3N0b24pKXsKICBoaXN0KEJvc3RvblssIGldLCBtYWluPWNvbG5hbWVzKEJvc3RvbilbaV0sIGJyZWFrcz0iRkQiKQogIGFibGluZSh2PUJvc3RvblszOTksIGldLCBjb2w9InJlZCIsIGx3PTMpCn0KYGBgCgooaCkgSW4gdGhpcyBkYXRhIHNldCwgaG93IG1hbnkgb2YgdGhlIGNlbnN1cyB0cmFjdHMgYXZlcmFnZSBtb3JlIHRoYW4gc2V2ZW4gcm9vbXMgcGVyIGR3ZWxsaW5nPyBNb3JlIHRoYW4gZWlnaHQgcm9vbXMgcGVyIGR3ZWxsaW5nPyBDb21tZW50IG9uIHRoZSBjZW5zdXMgdHJhY3RzIHRoYXQgYXZlcmFnZSBtb3JlIHRoYW4gZWlnaHQgcm9vbXMgcGVyIGR3ZWxsaW5nLgoKYGBge3J9CnN1bW1hcnkoQm9zdG9uJHJtID4gNykKYGBgClRoZXJlIGFyZSA2NCBzdWJ1cmJzIHdpdGggbW9yZSB0aGFuIDcgcm9vbXMgcGVyIGR3ZWxsaW5nLgoKCmBgYHtyfQpzdW1tYXJ5KEJvc3RvbiRybSA+IDgpCmBgYApUaGVyZSBhcmUgMTMgc3VidXJicyB3aXRoIG1vcmUgdGhhbiA4IHJvb21zIHBlciBkd2VsbGluZwoKCmBgYHtyfQojU3VidXJicyB0aGF0IGF2ZXJhZ2UgbW9yZSB0aGFuIGVpZ2h0IHJvb21zIHBlciBkd2VsbGluZzojCnN1bW1hcnkoc3Vic2V0KEJvc3Rvbiwgcm0gPiA4KSkKYGBgCmBgYHtyfQpzdW1tYXJ5KEJvc3RvbikKYGBgClJlbGF0aXZlbHkgbG93ZXIgY3JpbWUgKGNvbXBhcmluZyByYW5nZSksIGxvd2VyIGxzdGF0IChjb21wYXJpbmcgcmFuZ2UpCgoKCgo=