Notebook Instructions


Load Packages in R/RStudio

We are going to use tidyverse a collection of R packages designed for data science.

Loading required package: tidyverse
-- Attaching packages --------------------------------------- tidyverse 1.2.1 --
v ggplot2 2.2.1     v purrr   0.2.4
v tibble  1.4.2     v dplyr   0.7.4
v tidyr   0.8.0     v stringr 1.2.0
v readr   1.1.1     v forcats 0.2.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
Loading required package: gridExtra

Attaching package: <U+393C><U+3E31>gridExtra<U+393C><U+3E32>

The following object is masked from <U+393C><U+3E31>package:dplyr<U+393C><U+3E32>:

    combine

Task 1: Quantitative Analysis


1A) Read the csv file into R Studio and display the dataset.

  • Name your dataset ‘mydata’ so it easy to work with.

  • Commands: read_csv() head() max() min() var() sd()

Extract the assigned features (columns) to perform some analytics.

mydata <- read_csv("data/Advertising.csv")
Missing column names filled in: 'X1' [1]Parsed with column specification:
cols(
  X1 = col_integer(),
  TV = col_double(),
  radio = col_double(),
  newspaper = col_double(),
  sales = col_double()
)
head(mydata)

Change the variable name “X1” to case_number using the function rename()

  • mydata <- rename(mydata, “NEW_VAR_NAME” = “OLD_VAR_NAME”)
mydata <- rename(mydata, "case_number" = "X1")
Error: `X1` contains unknown variables

1B) Find the range ( difference between min and max ), min, max, standard deviation and variance for each assigned feature ( Use separate chunks for each feature ). Compare each feature and note any significant differences

SALES

sales <- mydata$sales
#variable_max
sales_max <- max(mydata$sales)
sales_max
[1] 27
#variable_min
sales_min <- min(mydata$sales)
sales_min
[1] 1.6
#variable_Range max-min
sales_Range <- sales_max - sales_min
sales_Range
[1] 25.4
#variable_mean 
sales_mean <- mean(mydata$sales)
sales_mean
[1] 14.0225
#variable_sd Standard Deviation
sales_sd <- sd(mydata$sales)
sales_sd
[1] 5.217457
#variable_variance
sales_variance <- var(mydata$sales)
sales_variance
[1] 27.22185

TV

tv <- mydata$TV
#variable_max
tv_max <- max(mydata$TV)
tv_max
[1] 296.4
#variable_min
tv_min <- min(mydata$TV)
tv_min
[1] 0.7
#variable_Range max-min
tv_Range <- tv_max - tv_min
tv_Range
[1] 295.7
#variable_mean 
tv_mean <- mean(mydata$TV)
tv_mean
[1] 147.0425
#variable_sd Standard Deviation
tv_sd <- sd(mydata$TV)
tv_sd
[1] 85.85424
#variable_variance
tv_variance <- var(mydata$TV)
tv_variance
[1] 7370.95

Radio

radio <- mydata$radio
#variable_max
radio_max <- max(mydata$radio)
radio_max
[1] 49.6
#variable_min
radio_min <- min(mydata$radio)
radio_min
[1] 0
#variable_Range max-min
radio_Range <- radio_max - radio_min
radio_Range
[1] 49.6
#variable_mean 
radio_mean <- mean(mydata$radio)
radio_mean
[1] 23.264
#variable_sd Standard Deviation
radio_sd <- sd(mydata$radio)
radio_sd
[1] 14.84681
#variable_variance
radio_variance <- var(mydata$radio)
radio_variance
[1] 220.4277

newspaper

newspaper <- mydata$newspaper
#variable_max
newspaper_max <- max(mydata$newspaper)
newspaper_max
[1] 114
#variable_min
newspaper_min <- min(mydata$newspaper)
newspaper_min
[1] 0.3
#variable_Range max-min
newspaper_Range <- newspaper_max - newspaper_min
newspaper_Range
[1] 113.7
#variable_mean 
newspaper_mean <- mean(mydata$newspaper)
newspaper_mean
[1] 30.554
#variable_sd Standard Deviation
newspaper_sd <- sd(mydata$newspaper)
newspaper_sd
[1] 21.77862
#variable_variance
newspaper_variance <- var(mydata$newspaper)
newspaper_variance
[1] 474.3083

1C) Use the summary() function on all the dataset to give you a general description of the data. Note any differences between features.

summary(mydata)
  case_number           TV             radio          newspaper          sales      
 Min.   :  1.00   Min.   :  0.70   Min.   : 0.000   Min.   :  0.30   Min.   : 1.60  
 1st Qu.: 50.75   1st Qu.: 74.38   1st Qu.: 9.975   1st Qu.: 12.75   1st Qu.:10.38  
 Median :100.50   Median :149.75   Median :22.900   Median : 25.75   Median :12.90  
 Mean   :100.50   Mean   :147.04   Mean   :23.264   Mean   : 30.55   Mean   :14.02  
 3rd Qu.:150.25   3rd Qu.:218.82   3rd Qu.:36.525   3rd Qu.: 45.10   3rd Qu.:17.40  
 Max.   :200.00   Max.   :296.40   Max.   :49.600   Max.   :114.00   Max.   :27.00  

Are there any outliers, if not explain the lack of outliers? if any explain what the outliers represent and how many records are outliers? ( Use code from notebook-03 to find outliers)

quantile(sales, na.rm = TRUE)
    0%    25%    50%    75%   100% 
 1.600 10.375 12.900 17.400 27.000 
quantile(tv, na.rm = TRUE)
     0%     25%     50%     75%    100% 
  0.700  74.375 149.750 218.825 296.400 
quantile(radio, na.rm = TRUE)
    0%    25%    50%    75%   100% 
 0.000  9.975 22.900 36.525 49.600 
quantile(newspaper, na.rm = TRUE)
    0%    25%    50%    75%   100% 
  0.30  12.75  25.75  45.10 114.00 
lowerqsales = quantile(sales, na.rm = TRUE)[2]
lowerqtv = quantile(tv, na.rm = TRUE)[2]
lowerqradio = quantile(radio, na.rm = TRUE)[2]
lowerqnewspaper = quantile(newspaper, na.rm = TRUE)[2]
upperqsales = quantile(sales, na.rm = TRUE)[4]
upperqtv = quantile(tv, na.rm = TRUE)[4]
upperqradio = quantile(radio, na.rm = TRUE)[4]
upperqnewspaper = quantile(newspaper, na.rm = TRUE)[4]
salesiqr = upperqsales - lowerqsales
salesiqr
  75% 
7.025 
tviqr = upperqtv - lowerqtv
tviqr
   75% 
144.45 
radioiqr = upperqradio - lowerqradio
radioiqr
  75% 
26.55 
newspaperiqr = upperqnewspaper - lowerqnewspaper
newspaperiqr
  75% 
32.35 
upper_threshold_sales = (salesiqr * 1.5) + upperqsales
upper_threshold_sales
    75% 
27.9375 
upper_threshold_tv = (tviqr * 1.5) + upperqtv
upper_threshold_tv
  75% 
435.5 
upper_threshold_radio = (radioiqr * 1.5) + upperqradio
upper_threshold_radio
  75% 
76.35 
upper_threshold_newspaper = (newspaperiqr * 1.5) + upperqnewspaper
upper_threshold_newspaper
   75% 
93.625 
lower_threshold_sales = lowerqsales - (salesiqr * 1.5) 
lower_threshold_sales
    25% 
-0.1625 
lower_threshold_tv = lowerqtv - (tviqr * 1.5)
lower_threshold_tv
   25% 
-142.3 
lower_threshold_radio = lowerqradio - (radioiqr * 1.5)
lower_threshold_radio
   25% 
-29.85 
lower_threshold_newspaper = lowerqnewspaper - (newspaperiqr * 1.5)
lower_threshold_newspaper
    25% 
-35.775 
sales[ sales > upper_threshold_sales][1:10]
 [1] NA NA NA NA NA NA NA NA NA NA
radio[ radio > upper_threshold_radio][1:10]
 [1] NA NA NA NA NA NA NA NA NA NA
tv[ tv > upper_threshold_tv][1:10]
 [1] NA NA NA NA NA NA NA NA NA NA
newspaper[ newspaper > upper_threshold_newspaper][1:10]
 [1] 114.0 100.9    NA    NA    NA    NA    NA    NA    NA    NA
sales[ sales < lower_threshold_sales][1:10]
 [1] NA NA NA NA NA NA NA NA NA NA
tv[ tv < lower_threshold_tv][1:10]
 [1] NA NA NA NA NA NA NA NA NA NA
radio[ radio < lower_threshold_radio][1:10]
 [1] NA NA NA NA NA NA NA NA NA NA
newspaper[ newspaper < lower_threshold_newspaper][1:10]
 [1] NA NA NA NA NA NA NA NA NA NA
mydata[ sales > upper_threshold_sales, ]
mydata[ tv > upper_threshold_tv, ]
mydata[ radio > upper_threshold_radio, ]
mydata[ newspaper > upper_threshold_newspaper, ]
mydata[ sales < lower_threshold_sales, ]
mydata[ tv < lower_threshold_tv, ]
mydata[ radio < lower_threshold_radio, ]
mydata[ newspaper < lower_threshold_newspaper, ]
count(mydata[ sales > upper_threshold_sales, ])
count(mydata[ tv > upper_threshold_tv, ])
count(mydata[ radio > upper_threshold_radio, ])
count(mydata[ newspaper > upper_threshold_newspaper, ])
count(mydata[ sales < lower_threshold_sales, ])
count(mydata[ tv < lower_threshold_tv, ])
count(mydata[ radio < lower_threshold_radio, ])
count(mydata[ newspaper < lower_threshold_newspaper, ])

There are no outliers for sales, tv, or radio. However, there are 2 outliers above the upperthreshold of Newspaper. This means there are 2 points that are far away from the majority of the other points.

1D) Write a general description of the dataset using the statistics found in the steps above. Use the min,max range to compare the features, note any significant differences.

Tv had the highest maximum of 296.4 followed by newspaper, then radio, then sales of 27. Radio had a minimum of 0, newspaper 0.3, tv 0.7, and sales 1.6. This shows that most money for advertising was spent on TV which makes sense because it is an easy way to reach people today.


Task 2: Qualitative Analysis


2A) Plot all the assigned features as y-axis for x-axis use case_number. Use the given commands to create each plot and create a grid to plot all features Note any trends/patters in the data

  • Commands: VARIABLE_plot <- ggplot(data = mydata, aes(x = VARIABLE, y = VARIABLE)) + geom_point()
  • Commands: grid.arrange(VARIABLE_plot1, VARIABLE_plot2, VARIABLE_plot3, VARIABLE_plot4, ncol=2)
sales_plot <- ggplot(data = mydata, aes(x = case_number, y = sales)) + geom_point()
tv_plot <- ggplot(data = mydata, aes(x = case_number, y = tv)) + geom_point()
radio_plot <- ggplot(data = mydata, aes(x = case_number, y = radio)) + geom_point()
newspaper_plot <- ggplot(data = mydata, aes(x = case_number, y = newspaper)) + geom_point()
grid.arrange(sales_plot, tv_plot, radio_plot, newspaper_plot, ncol=2)

  • When looking at these plots it is hard to see a particular trend.
  • One way to observe any possible trend in the sales data would be to re-order the data from low to high.
  • The 200 months observations are in no particular chronological time sequence.
  • The case numbers are independent sequentially generated numbers. Since each case is independent, we can reorder them.

2B) Re-order sales from low to high, and save re-ordered data in a new set. As sales data is re-reorded associated other column fields follow.

  • Commands: newdata <- mydata[ order(mydata$VARIABLE), ]
# Extract case_number from the newdata
newdata = mydata[ order(mydata$sales), ]
case_number <- newdata$case_number
head(newdata)

Extract the variables from the new data

# new_VARIABLE = newdata$VARIABLE
new_sales = newdata$sales
new_tv = newdata$TV
new_radio = newdata$radio
new_newspaper = newdata$newspaper

# It is much easier to see the increasing trend in sales and tv with the new order. Radio has a bit more of a identifiable pattern, but newspaper does not.

Task 3: Standardized Z-Value


3A) Create a histogram of the assigned feature z-scores. Describe the output note any relevant values.

  • Command: z_score = ( VARIABLE - mean(VARIABLE) ) / sd(VARIABLE)
  • Commands: qplot( x = VARIABLE ,geom=“histogram”, binwidth = 0.3)
z_score_sales = ( sales - mean(sales) ) / sd(sales)
z_score_tv = ( tv - mean(tv) ) / sd(tv)
z_score_radio = ( radio - mean(radio) ) / sd(radio)
z_score_newspaper = ( newspaper - mean(newspaper) ) / sd(newspaper)
qplot( x = z_score_sales ,geom="histogram", binwidth = 0.3)

qplot( x = z_score_tv ,geom="histogram", binwidth = 0.3)

qplot( x = z_score_radio ,geom="histogram", binwidth = 0.3)

qplot( x = z_score_newspaper ,geom="histogram", binwidth = 0.3)

Sales is the most normally distributed. Radio and TV are both seem to vary throughout the graph. Newspaper is right skewed which makes sense since it was the only variable with ooutliers.

3B) Given a sales value of $26700, calculate the corresponding z-value or z-score.

  • Command: z_score = ( VARIABLE - mean(VARIABLE) ) / sd(VARIABLE)
x = 26.7
 z_score_calculatecor = ( x - mean(sales) ) / sd(sales)
 z_score_calculatecor
[1] 2.429824

3C) Based on the z-value, how would you rate a $26700 sales value: poor, average, good, or very good performance? Explain your logic.

I think this is a good performance because since it’s a positive z-score it will bring about a profit and it will do the same the next time which is good for business.

LS0tDQp0aXRsZTogIkRlc2NyaXB0aXZlIEFuYWx5dGljcyINCmF1dGhvcjogIkFzaGxleSBLcmVueiINCmRhdGU6ICJGZWJydWFyeSAyNiwgMjAxOCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCnN1YnRpdGxlOiBDTUUgR3JvdXAgRm91bmRhdGlvbiBCdXNpbmVzcyBBbmFseXRpY3MgTGFiDQotLS0NCg0KLS0tLS0tLS0tLS0tLQ0KDQojIyBOb3RlYm9vayBJbnN0cnVjdGlvbnMNCg0KLS0tLS0tLS0tLS0tLQ0KDQoqIEZvciB5b3VyIGFzc2lnbm1lbnQgeW91IG1heSBiZSB1c2luZyBkaWZmZXJlbnQgZGF0YXNldCB0aGFuIHdoYXQgaXMgaW5jbHVkZWQgaGVyZS4gDQoNCiogQWx3YXlzIHJlYWQgY2FyZWZ1bGx5IHRoZSBpbnN0cnVjdGlvbnMgb24gU2FrYWkuICANCg0KKiBUYXNrcy9xdWVzdGlvbnMgdG8gYmUgY29tcGxldGVkL2Fuc3dlcmVkIGFyZSBoaWdobGlnaHRlZCBpbiBsYXJnZXIgYm9sZGVkIGZvbnRzIGFuZCBudW1iZXJlZCBhY2NvcmRpbmcgdG8gdGhlaXIgc2VjdGlvbi4NCg0KIyMjIExvYWQgUGFja2FnZXMgaW4gUi9SU3R1ZGlvIA0KDQpXZSBhcmUgZ29pbmcgdG8gdXNlIHRpZHl2ZXJzZSBhIGNvbGxlY3Rpb24gb2YgUiBwYWNrYWdlcyBkZXNpZ25lZCBmb3IgZGF0YSBzY2llbmNlLiANCg0KKiBJbmZvOiBodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLw0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCg0KIyBIZXJlIHdlIGFyZSBjaGVja2luZyBpZiB0aGUgcGFja2FnZSBpcyBpbnN0YWxsZWQNCmlmKCFyZXF1aXJlKHRpZHl2ZXJzZSkpew0KICANCiAgIyBJZiB0aGUgcGFja2FnZSBpcyBub3QgaW4gdGhlIHN5c3RlbSB0aGVuIGl0IHdpbGwgYmUgaW5zdGFsbA0KICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiLCBkZXBlbmRlbmNpZXMgPSBUUlVFKQ0KICANCiAgIyBIZXJlIHdlIGFyZSBsb2FkaW5nIHRoZSBwYWNrYWdlDQogIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KDQppZighcmVxdWlyZShncmlkRXh0cmEpKXsNCiAgDQogICMgSWYgdGhlIHBhY2thZ2UgaXMgbm90IGluIHRoZSBzeXN0ZW0gdGhlbiBpdCB3aWxsIGJlIGluc3RhbGwNCiAgaW5zdGFsbC5wYWNrYWdlcygiZ3JpZEV4dHJhIiwgZGVwZW5kZW5jaWVzID0gVFJVRSkNCiAgDQogICMgSGVyZSB3ZSBhcmUgbG9hZGluZyB0aGUgcGFja2FnZQ0KICBsaWJyYXJ5KGdyaWRFeHRyYSkNCn0NCg0KYGBgDQoNCi0tLS0tLS0tLS0tLS0NCg0KIyMgVGFzayAxOiBRdWFudGl0YXRpdmUgQW5hbHlzaXMNCg0KLS0tLS0tLS0tLS0tLQ0KDQojIyMgMUEpIFJlYWQgdGhlIGNzdiBmaWxlIGludG8gUiBTdHVkaW8gYW5kIGRpc3BsYXkgdGhlIGRhdGFzZXQuIA0KDQoqIE5hbWUgeW91ciBkYXRhc2V0ICdteWRhdGEnIHNvIGl0IGVhc3kgdG8gd29yayB3aXRoLg0KDQoqIENvbW1hbmRzOiByZWFkX2NzdigpIGhlYWQoKSBtYXgoKSBtaW4oKSB2YXIoKSBzZCgpDQoNCiMjIyMgRXh0cmFjdCB0aGUgYXNzaWduZWQgZmVhdHVyZXMgKGNvbHVtbnMpIHRvIHBlcmZvcm0gc29tZSBhbmFseXRpY3MuIA0KDQpgYGB7cn0gDQpteWRhdGEgPC0gcmVhZF9jc3YoImRhdGEvQWR2ZXJ0aXNpbmcuY3N2IikNCmBgYA0KYGBge3J9DQpoZWFkKG15ZGF0YSkNCmBgYA0KDQoNCiMjIyMgQ2hhbmdlIHRoZSB2YXJpYWJsZSBuYW1lICJYMSIgdG8gY2FzZV9udW1iZXIgdXNpbmcgdGhlIGZ1bmN0aW9uIHJlbmFtZSgpDQoNCiogbXlkYXRhIDwtIHJlbmFtZShteWRhdGEsICJORVdfVkFSX05BTUUiID0gIk9MRF9WQVJfTkFNRSIpDQoNCmBgYHtyfSANCm15ZGF0YSA8LSByZW5hbWUobXlkYXRhLCAiY2FzZV9udW1iZXIiID0gIlgxIikNCmBgYA0KDQojIyMgMUIpIEZpbmQgdGhlIHJhbmdlICggZGlmZmVyZW5jZSBiZXR3ZWVuIG1pbiBhbmQgbWF4ICksIG1pbiwgbWF4LCBzdGFuZGFyZCBkZXZpYXRpb24gYW5kIHZhcmlhbmNlIGZvciBlYWNoIGFzc2lnbmVkIGZlYXR1cmUgKCBVc2Ugc2VwYXJhdGUgY2h1bmtzIGZvciBlYWNoIGZlYXR1cmUgKS4gQ29tcGFyZSBlYWNoIGZlYXR1cmUgYW5kIG5vdGUgYW55IHNpZ25pZmljYW50IGRpZmZlcmVuY2VzDQoNCioqU0FMRVMqKg0KYGBge3J9DQpzYWxlcyA8LSBteWRhdGEkc2FsZXMNCiN2YXJpYWJsZV9tYXgNCnNhbGVzX21heCA8LSBtYXgobXlkYXRhJHNhbGVzKQ0Kc2FsZXNfbWF4DQojdmFyaWFibGVfbWluDQpzYWxlc19taW4gPC0gbWluKG15ZGF0YSRzYWxlcykNCnNhbGVzX21pbg0KI3ZhcmlhYmxlX1JhbmdlIG1heC1taW4NCnNhbGVzX1JhbmdlIDwtIHNhbGVzX21heCAtIHNhbGVzX21pbg0Kc2FsZXNfUmFuZ2UNCiN2YXJpYWJsZV9tZWFuIA0Kc2FsZXNfbWVhbiA8LSBtZWFuKG15ZGF0YSRzYWxlcykNCnNhbGVzX21lYW4NCiN2YXJpYWJsZV9zZCBTdGFuZGFyZCBEZXZpYXRpb24NCnNhbGVzX3NkIDwtIHNkKG15ZGF0YSRzYWxlcykNCnNhbGVzX3NkDQojdmFyaWFibGVfdmFyaWFuY2UNCnNhbGVzX3ZhcmlhbmNlIDwtIHZhcihteWRhdGEkc2FsZXMpDQpzYWxlc192YXJpYW5jZQ0KYGBgDQoNCioqVFYqKg0KYGBge3J9DQp0diA8LSBteWRhdGEkVFYNCiN2YXJpYWJsZV9tYXgNCnR2X21heCA8LSBtYXgobXlkYXRhJFRWKQ0KdHZfbWF4DQojdmFyaWFibGVfbWluDQp0dl9taW4gPC0gbWluKG15ZGF0YSRUVikNCnR2X21pbg0KI3ZhcmlhYmxlX1JhbmdlIG1heC1taW4NCnR2X1JhbmdlIDwtIHR2X21heCAtIHR2X21pbg0KdHZfUmFuZ2UNCiN2YXJpYWJsZV9tZWFuIA0KdHZfbWVhbiA8LSBtZWFuKG15ZGF0YSRUVikNCnR2X21lYW4NCiN2YXJpYWJsZV9zZCBTdGFuZGFyZCBEZXZpYXRpb24NCnR2X3NkIDwtIHNkKG15ZGF0YSRUVikNCnR2X3NkDQojdmFyaWFibGVfdmFyaWFuY2UNCnR2X3ZhcmlhbmNlIDwtIHZhcihteWRhdGEkVFYpDQp0dl92YXJpYW5jZQ0KYGBgDQoNCioqUmFkaW8qKg0KYGBge3J9DQpyYWRpbyA8LSBteWRhdGEkcmFkaW8NCiN2YXJpYWJsZV9tYXgNCnJhZGlvX21heCA8LSBtYXgobXlkYXRhJHJhZGlvKQ0KcmFkaW9fbWF4DQojdmFyaWFibGVfbWluDQpyYWRpb19taW4gPC0gbWluKG15ZGF0YSRyYWRpbykNCnJhZGlvX21pbg0KI3ZhcmlhYmxlX1JhbmdlIG1heC1taW4NCnJhZGlvX1JhbmdlIDwtIHJhZGlvX21heCAtIHJhZGlvX21pbg0KcmFkaW9fUmFuZ2UNCiN2YXJpYWJsZV9tZWFuIA0KcmFkaW9fbWVhbiA8LSBtZWFuKG15ZGF0YSRyYWRpbykNCnJhZGlvX21lYW4NCiN2YXJpYWJsZV9zZCBTdGFuZGFyZCBEZXZpYXRpb24NCnJhZGlvX3NkIDwtIHNkKG15ZGF0YSRyYWRpbykNCnJhZGlvX3NkDQojdmFyaWFibGVfdmFyaWFuY2UNCnJhZGlvX3ZhcmlhbmNlIDwtIHZhcihteWRhdGEkcmFkaW8pDQpyYWRpb192YXJpYW5jZQ0KYGBgDQoNCioqbmV3c3BhcGVyKioNCmBgYHtyfQ0KbmV3c3BhcGVyIDwtIG15ZGF0YSRuZXdzcGFwZXINCiN2YXJpYWJsZV9tYXgNCm5ld3NwYXBlcl9tYXggPC0gbWF4KG15ZGF0YSRuZXdzcGFwZXIpDQpuZXdzcGFwZXJfbWF4DQojdmFyaWFibGVfbWluDQpuZXdzcGFwZXJfbWluIDwtIG1pbihteWRhdGEkbmV3c3BhcGVyKQ0KbmV3c3BhcGVyX21pbg0KI3ZhcmlhYmxlX1JhbmdlIG1heC1taW4NCm5ld3NwYXBlcl9SYW5nZSA8LSBuZXdzcGFwZXJfbWF4IC0gbmV3c3BhcGVyX21pbg0KbmV3c3BhcGVyX1JhbmdlDQojdmFyaWFibGVfbWVhbiANCm5ld3NwYXBlcl9tZWFuIDwtIG1lYW4obXlkYXRhJG5ld3NwYXBlcikNCm5ld3NwYXBlcl9tZWFuDQojdmFyaWFibGVfc2QgU3RhbmRhcmQgRGV2aWF0aW9uDQpuZXdzcGFwZXJfc2QgPC0gc2QobXlkYXRhJG5ld3NwYXBlcikNCm5ld3NwYXBlcl9zZA0KI3ZhcmlhYmxlX3ZhcmlhbmNlDQpuZXdzcGFwZXJfdmFyaWFuY2UgPC0gdmFyKG15ZGF0YSRuZXdzcGFwZXIpDQpuZXdzcGFwZXJfdmFyaWFuY2UNCmBgYA0KDQojIyMgMUMpIFVzZSB0aGUgc3VtbWFyeSgpIGZ1bmN0aW9uIG9uIGFsbCB0aGUgZGF0YXNldCB0byBnaXZlIHlvdSBhIGdlbmVyYWwgZGVzY3JpcHRpb24gb2YgdGhlIGRhdGEuIE5vdGUgYW55IGRpZmZlcmVuY2VzIGJldHdlZW4gZmVhdHVyZXMuDQoNCmBgYHtyfQ0Kc3VtbWFyeShteWRhdGEpDQpgYGANCg0KIyMjIyBBcmUgdGhlcmUgYW55IG91dGxpZXJzLCBpZiBub3QgZXhwbGFpbiB0aGUgbGFjayBvZiBvdXRsaWVycz8gaWYgYW55IGV4cGxhaW4gd2hhdCB0aGUgb3V0bGllcnMgcmVwcmVzZW50IGFuZCBob3cgbWFueSByZWNvcmRzIGFyZSBvdXRsaWVycz8gKCBVc2UgY29kZSBmcm9tIG5vdGVib29rLTAzIHRvIGZpbmQgb3V0bGllcnMpIA0KDQoNCg0KYGBge3J9DQpxdWFudGlsZShzYWxlcywgbmEucm0gPSBUUlVFKQ0KcXVhbnRpbGUodHYsIG5hLnJtID0gVFJVRSkNCnF1YW50aWxlKHJhZGlvLCBuYS5ybSA9IFRSVUUpDQpxdWFudGlsZShuZXdzcGFwZXIsIG5hLnJtID0gVFJVRSkNCmBgYA0KDQpgYGB7cn0NCmxvd2VycXNhbGVzID0gcXVhbnRpbGUoc2FsZXMsIG5hLnJtID0gVFJVRSlbMl0NCmxvd2VycXR2ID0gcXVhbnRpbGUodHYsIG5hLnJtID0gVFJVRSlbMl0NCmxvd2VycXJhZGlvID0gcXVhbnRpbGUocmFkaW8sIG5hLnJtID0gVFJVRSlbMl0NCmxvd2VycW5ld3NwYXBlciA9IHF1YW50aWxlKG5ld3NwYXBlciwgbmEucm0gPSBUUlVFKVsyXQ0KYGBgDQoNCmBgYHtyfQ0KdXBwZXJxc2FsZXMgPSBxdWFudGlsZShzYWxlcywgbmEucm0gPSBUUlVFKVs0XQ0KdXBwZXJxdHYgPSBxdWFudGlsZSh0diwgbmEucm0gPSBUUlVFKVs0XQ0KdXBwZXJxcmFkaW8gPSBxdWFudGlsZShyYWRpbywgbmEucm0gPSBUUlVFKVs0XQ0KdXBwZXJxbmV3c3BhcGVyID0gcXVhbnRpbGUobmV3c3BhcGVyLCBuYS5ybSA9IFRSVUUpWzRdDQpgYGANCg0KYGBge3J9DQpzYWxlc2lxciA9IHVwcGVycXNhbGVzIC0gbG93ZXJxc2FsZXMNCnNhbGVzaXFyDQp0dmlxciA9IHVwcGVycXR2IC0gbG93ZXJxdHYNCnR2aXFyDQpyYWRpb2lxciA9IHVwcGVycXJhZGlvIC0gbG93ZXJxcmFkaW8NCnJhZGlvaXFyDQpuZXdzcGFwZXJpcXIgPSB1cHBlcnFuZXdzcGFwZXIgLSBsb3dlcnFuZXdzcGFwZXINCm5ld3NwYXBlcmlxcg0KYGBgDQoNCmBgYHtyfQ0KdXBwZXJfdGhyZXNob2xkX3NhbGVzID0gKHNhbGVzaXFyICogMS41KSArIHVwcGVycXNhbGVzDQp1cHBlcl90aHJlc2hvbGRfc2FsZXMNCnVwcGVyX3RocmVzaG9sZF90diA9ICh0dmlxciAqIDEuNSkgKyB1cHBlcnF0dg0KdXBwZXJfdGhyZXNob2xkX3R2DQp1cHBlcl90aHJlc2hvbGRfcmFkaW8gPSAocmFkaW9pcXIgKiAxLjUpICsgdXBwZXJxcmFkaW8NCnVwcGVyX3RocmVzaG9sZF9yYWRpbw0KdXBwZXJfdGhyZXNob2xkX25ld3NwYXBlciA9IChuZXdzcGFwZXJpcXIgKiAxLjUpICsgdXBwZXJxbmV3c3BhcGVyDQp1cHBlcl90aHJlc2hvbGRfbmV3c3BhcGVyDQoNCmxvd2VyX3RocmVzaG9sZF9zYWxlcyA9IGxvd2VycXNhbGVzIC0gKHNhbGVzaXFyICogMS41KSANCmxvd2VyX3RocmVzaG9sZF9zYWxlcw0KbG93ZXJfdGhyZXNob2xkX3R2ID0gbG93ZXJxdHYgLSAodHZpcXIgKiAxLjUpDQpsb3dlcl90aHJlc2hvbGRfdHYNCmxvd2VyX3RocmVzaG9sZF9yYWRpbyA9IGxvd2VycXJhZGlvIC0gKHJhZGlvaXFyICogMS41KQ0KbG93ZXJfdGhyZXNob2xkX3JhZGlvDQpsb3dlcl90aHJlc2hvbGRfbmV3c3BhcGVyID0gbG93ZXJxbmV3c3BhcGVyIC0gKG5ld3NwYXBlcmlxciAqIDEuNSkNCmxvd2VyX3RocmVzaG9sZF9uZXdzcGFwZXINCmBgYA0KDQpgYGB7cn0NCnNhbGVzWyBzYWxlcyA+IHVwcGVyX3RocmVzaG9sZF9zYWxlc11bMToxMF0NCnJhZGlvWyByYWRpbyA+IHVwcGVyX3RocmVzaG9sZF9yYWRpb11bMToxMF0NCnR2WyB0diA+IHVwcGVyX3RocmVzaG9sZF90dl1bMToxMF0NCm5ld3NwYXBlclsgbmV3c3BhcGVyID4gdXBwZXJfdGhyZXNob2xkX25ld3NwYXBlcl1bMToxMF0NCg0Kc2FsZXNbIHNhbGVzIDwgbG93ZXJfdGhyZXNob2xkX3NhbGVzXVsxOjEwXQ0KdHZbIHR2IDwgbG93ZXJfdGhyZXNob2xkX3R2XVsxOjEwXQ0KcmFkaW9bIHJhZGlvIDwgbG93ZXJfdGhyZXNob2xkX3JhZGlvXVsxOjEwXQ0KbmV3c3BhcGVyWyBuZXdzcGFwZXIgPCBsb3dlcl90aHJlc2hvbGRfbmV3c3BhcGVyXVsxOjEwXQ0KYGBgDQoNCmBgYHtyfQ0KbXlkYXRhWyBzYWxlcyA+IHVwcGVyX3RocmVzaG9sZF9zYWxlcywgXQ0KbXlkYXRhWyB0diA+IHVwcGVyX3RocmVzaG9sZF90diwgXQ0KbXlkYXRhWyByYWRpbyA+IHVwcGVyX3RocmVzaG9sZF9yYWRpbywgXQ0KbXlkYXRhWyBuZXdzcGFwZXIgPiB1cHBlcl90aHJlc2hvbGRfbmV3c3BhcGVyLCBdDQpgYGANCg0KYGBge3J9DQpteWRhdGFbIHNhbGVzIDwgbG93ZXJfdGhyZXNob2xkX3NhbGVzLCBdDQpteWRhdGFbIHR2IDwgbG93ZXJfdGhyZXNob2xkX3R2LCBdDQpteWRhdGFbIHJhZGlvIDwgbG93ZXJfdGhyZXNob2xkX3JhZGlvLCBdDQpteWRhdGFbIG5ld3NwYXBlciA8IGxvd2VyX3RocmVzaG9sZF9uZXdzcGFwZXIsIF0NCmBgYA0KDQoNCmBgYHtyfQ0KY291bnQobXlkYXRhWyBzYWxlcyA+IHVwcGVyX3RocmVzaG9sZF9zYWxlcywgXSkNCmBgYA0KDQpgYGB7cn0NCmNvdW50KG15ZGF0YVsgdHYgPiB1cHBlcl90aHJlc2hvbGRfdHYsIF0pDQpgYGANCmBgYHtyfQ0KY291bnQobXlkYXRhWyByYWRpbyA+IHVwcGVyX3RocmVzaG9sZF9yYWRpbywgXSkNCmBgYA0KYGBge3J9DQpjb3VudChteWRhdGFbIG5ld3NwYXBlciA+IHVwcGVyX3RocmVzaG9sZF9uZXdzcGFwZXIsIF0pDQpgYGANCg0KDQpgYGB7cn0NCmNvdW50KG15ZGF0YVsgc2FsZXMgPCBsb3dlcl90aHJlc2hvbGRfc2FsZXMsIF0pDQpgYGANCmBgYHtyfQ0KY291bnQobXlkYXRhWyB0diA8IGxvd2VyX3RocmVzaG9sZF90diwgXSkNCmBgYA0KYGBge3J9DQpjb3VudChteWRhdGFbIHJhZGlvIDwgbG93ZXJfdGhyZXNob2xkX3JhZGlvLCBdKQ0KYGBgDQoNCmBgYHtyfQ0KY291bnQobXlkYXRhWyBuZXdzcGFwZXIgPCBsb3dlcl90aHJlc2hvbGRfbmV3c3BhcGVyLCBdKQ0KYGBgDQojIFRoZXJlIGFyZSBubyBvdXRsaWVycyBmb3Igc2FsZXMsIHR2LCBvciByYWRpby4gSG93ZXZlciwgdGhlcmUgYXJlIDIgb3V0bGllcnMgYWJvdmUgdGhlIHVwcGVydGhyZXNob2xkIG9mIE5ld3NwYXBlci4gVGhpcyBtZWFucyB0aGVyZSBhcmUgMiBwb2ludHMgdGhhdCBhcmUgZmFyIGF3YXkgZnJvbSB0aGUgbWFqb3JpdHkgb2YgdGhlIG90aGVyIHBvaW50cy4gDQoNCiMjIyAxRCkgV3JpdGUgYSBnZW5lcmFsIGRlc2NyaXB0aW9uIG9mIHRoZSBkYXRhc2V0IHVzaW5nIHRoZSBzdGF0aXN0aWNzIGZvdW5kIGluIHRoZSBzdGVwcyBhYm92ZS4gVXNlIHRoZSBtaW4sbWF4IHJhbmdlIHRvIGNvbXBhcmUgdGhlIGZlYXR1cmVzLCBub3RlIGFueSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcy4NCg0KIyBUdiBoYWQgdGhlIGhpZ2hlc3QgbWF4aW11bSBvZiAyOTYuNCBmb2xsb3dlZCBieSBuZXdzcGFwZXIsIHRoZW4gcmFkaW8sIHRoZW4gc2FsZXMgb2YgMjcuIFJhZGlvIGhhZCBhIG1pbmltdW0gb2YgMCwgbmV3c3BhcGVyIDAuMywgdHYgMC43LCBhbmQgc2FsZXMgMS42LiBUaGlzIHNob3dzIHRoYXQgbW9zdCBtb25leSBmb3IgYWR2ZXJ0aXNpbmcgd2FzIHNwZW50IG9uIFRWIHdoaWNoIG1ha2VzIHNlbnNlIGJlY2F1c2UgaXQgaXMgYW4gZWFzeSB3YXkgdG8gcmVhY2ggcGVvcGxlIHRvZGF5LiANCg0KLS0tLS0tLS0tLS0tLQ0KDQojIyBUYXNrIDI6IFF1YWxpdGF0aXZlIEFuYWx5c2lzDQoNCi0tLS0tLS0tLS0tLS0NCg0KDQojIyMgMkEpIFBsb3QgYWxsIHRoZSBhc3NpZ25lZCBmZWF0dXJlcyBhcyB5LWF4aXMgZm9yIHgtYXhpcyB1c2UgY2FzZV9udW1iZXIuIFVzZSB0aGUgZ2l2ZW4gY29tbWFuZHMgdG8gY3JlYXRlIGVhY2ggcGxvdCBhbmQgY3JlYXRlIGEgZ3JpZCB0byBwbG90IGFsbCBmZWF0dXJlcyBOb3RlIGFueSB0cmVuZHMvcGF0dGVycyBpbiB0aGUgZGF0YQ0KDQoqIENvbW1hbmRzOiBWQVJJQUJMRV9wbG90IDwtIGdncGxvdChkYXRhID0gbXlkYXRhLCBhZXMoeCA9IFZBUklBQkxFLCB5ID0gVkFSSUFCTEUpKSArIGdlb21fcG9pbnQoKQ0KKiBDb21tYW5kczogZ3JpZC5hcnJhbmdlKFZBUklBQkxFX3Bsb3QxLCBWQVJJQUJMRV9wbG90MiwgVkFSSUFCTEVfcGxvdDMsIFZBUklBQkxFX3Bsb3Q0LCBuY29sPTIpDQoNCmBgYHtyfQ0Kc2FsZXNfcGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IG15ZGF0YSwgYWVzKHggPSBjYXNlX251bWJlciwgeSA9IHNhbGVzKSkgKyBnZW9tX3BvaW50KCkNCnR2X3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBteWRhdGEsIGFlcyh4ID0gY2FzZV9udW1iZXIsIHkgPSB0dikpICsgZ2VvbV9wb2ludCgpDQpyYWRpb19wbG90IDwtIGdncGxvdChkYXRhID0gbXlkYXRhLCBhZXMoeCA9IGNhc2VfbnVtYmVyLCB5ID0gcmFkaW8pKSArIGdlb21fcG9pbnQoKQ0KbmV3c3BhcGVyX3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBteWRhdGEsIGFlcyh4ID0gY2FzZV9udW1iZXIsIHkgPSBuZXdzcGFwZXIpKSArIGdlb21fcG9pbnQoKQ0KZ3JpZC5hcnJhbmdlKHNhbGVzX3Bsb3QsIHR2X3Bsb3QsIHJhZGlvX3Bsb3QsIG5ld3NwYXBlcl9wbG90LCBuY29sPTIpDQpgYGANCg0KDQoqIFdoZW4gbG9va2luZyBhdCB0aGVzZSBwbG90cyBpdCBpcyBoYXJkIHRvIHNlZSBhIHBhcnRpY3VsYXIgdHJlbmQuIA0KKiBPbmUgd2F5IHRvIG9ic2VydmUgYW55IHBvc3NpYmxlIHRyZW5kIGluIHRoZSBzYWxlcyBkYXRhIHdvdWxkIGJlIHRvIHJlLW9yZGVyIHRoZSBkYXRhIGZyb20gbG93IHRvIGhpZ2guIA0KKiBUaGUgMjAwIG1vbnRocyBvYnNlcnZhdGlvbnMgYXJlIGluIG5vIHBhcnRpY3VsYXIgY2hyb25vbG9naWNhbCB0aW1lIHNlcXVlbmNlLiANCiogVGhlIGNhc2UgbnVtYmVycyBhcmUgaW5kZXBlbmRlbnQgc2VxdWVudGlhbGx5IGdlbmVyYXRlZCBudW1iZXJzLiBTaW5jZSBlYWNoIGNhc2UgaXMgaW5kZXBlbmRlbnQsIHdlIGNhbiByZW9yZGVyIHRoZW0uIA0KDQoNCiMjIyAyQikgUmUtb3JkZXIgc2FsZXMgZnJvbSBsb3cgdG8gaGlnaCwgYW5kIHNhdmUgcmUtb3JkZXJlZCBkYXRhIGluIGEgbmV3IHNldC4gQXMgc2FsZXMgZGF0YSBpcyByZS1yZW9yZGVkIGFzc29jaWF0ZWQgb3RoZXIgY29sdW1uIGZpZWxkcyBmb2xsb3cuDQoNCiogQ29tbWFuZHM6IG5ld2RhdGEgPC0gbXlkYXRhWyBvcmRlcihteWRhdGEkVkFSSUFCTEUpLCBdDQoNCmBgYHtyfQ0KDQojIEV4dHJhY3QgY2FzZV9udW1iZXIgZnJvbSB0aGUgbmV3ZGF0YQ0KbmV3ZGF0YSA9IG15ZGF0YVsgb3JkZXIobXlkYXRhJHNhbGVzKSwgXQ0KY2FzZV9udW1iZXIgPC0gbmV3ZGF0YSRjYXNlX251bWJlcg0KDQpoZWFkKG5ld2RhdGEpDQpgYGANCg0KDQojIyMjIEV4dHJhY3QgdGhlIHZhcmlhYmxlcyBmcm9tIHRoZSBuZXcgZGF0YQ0KDQpgYGB7cn0NCiMgbmV3X1ZBUklBQkxFID0gbmV3ZGF0YSRWQVJJQUJMRQ0KbmV3X3NhbGVzID0gbmV3ZGF0YSRzYWxlcw0KbmV3X3R2ID0gbmV3ZGF0YSRUVg0KbmV3X3JhZGlvID0gbmV3ZGF0YSRyYWRpbw0KbmV3X25ld3NwYXBlciA9IG5ld2RhdGEkbmV3c3BhcGVyDQpgYGANCg0KIyMjIDJDKSBSZXBlYXQgdGhlIDQgZ3JhcGhzIHdpdGggdGhlIG5ld2RhdGEgdG8gc3BvdCBhbnkgdHJlbmRzLiBOb3RlIHlvdXIgb2JzZXJ2YXRpb25zIG9uIHdoYXQgdGhlIG5ldyBwbG90cyBhcmUgcmV2ZWFsaW5nIGluIHRlcm1zIG9mIHRyZW5kaW5nIHJlbGF0aW9uc2hpcC4gDQoNCiogQ29tbWFuZHM6IFZBUklBQkxFX3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBteWRhdGEsIGFlcyh4ID0gVkFSSUFCTEUsIHkgPSBWQVJJQUJMRSkpICsgZ2VvbV9wb2ludCgpDQoqIENvbW1hbmRzOiBGb3IgeCB2YXJpYWJsZSBpbiB0aGUgcGxvdCB1c2U6IGFlcyh4ID0gY2FzZV9udW1iZXJbb3JkZXIoY2FzZV9udW1iZXIpXSkNCiogQ29tbWFuZHM6IGdyaWQuYXJyYW5nZShWQVJJQUJMRV9wbG90MSwgVkFSSUFCTEVfcGxvdDIsIFZBUklBQkxFX3Bsb3QzLCBWQVJJQUJMRV9wbG90NCwgbmNvbD0yKQ0KDQpgYGB7cn0NCm5ld3NhbGVzX3Bsb3QgPC0gZ2dwbG90KGRhdGEgPSBuZXdkYXRhLCBhZXMoeCA9IGNhc2VfbnVtYmVyW29yZGVyKGNhc2VfbnVtYmVyKV0sIHkgPSBuZXdfc2FsZXMpKSArIGdlb21fcG9pbnQoKQ0KbmV3dHZfcGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IG5ld2RhdGEsIGFlcyh4ID0gY2FzZV9udW1iZXJbb3JkZXIoY2FzZV9udW1iZXIpXSwgeSA9IG5ld190dikpICsgZ2VvbV9wb2ludCgpDQpuZXdyYWRpb19wbG90IDwtIGdncGxvdChkYXRhID0gbmV3ZGF0YSwgYWVzKHggPSBjYXNlX251bWJlcltvcmRlcihjYXNlX251bWJlcildLCB5ID0gbmV3X3JhZGlvKSkgKyBnZW9tX3BvaW50KCkNCm5ld25ld3NwYXBlcl9wbG90IDwtIGdncGxvdChkYXRhID0gbmV3ZGF0YSwgYWVzKHggPSBjYXNlX251bWJlcltvcmRlcihjYXNlX251bWJlcildLCB5ID0gbmV3X25ld3NwYXBlcikpICsgZ2VvbV9wb2ludCgpDQpncmlkLmFycmFuZ2UobmV3c2FsZXNfcGxvdCwgbmV3dHZfcGxvdCwgbmV3cmFkaW9fcGxvdCwgbmV3bmV3c3BhcGVyX3Bsb3QsIG5jb2w9MikNCmBgYA0KIyBJdCBpcyBtdWNoIGVhc2llciB0byBzZWUgdGhlIGluY3JlYXNpbmcgdHJlbmQgaW4gc2FsZXMgYW5kIHR2IHdpdGggdGhlIG5ldyBvcmRlci4gUmFkaW8gaGFzIGEgYml0IG1vcmUgb2YgYSBpZGVudGlmaWFibGUgcGF0dGVybiwgYnV0IG5ld3NwYXBlciBkb2VzIG5vdC4gDQotLS0tLS0tLS0tDQoNCiMjIFRhc2sgMzogU3RhbmRhcmRpemVkIFotVmFsdWUNCg0KLS0tLS0tLS0tLQ0KDQoNCiMjIyAzQSkgQ3JlYXRlIGEgaGlzdG9ncmFtIG9mIHRoZSBhc3NpZ25lZCBmZWF0dXJlIHotc2NvcmVzLiBEZXNjcmliZSB0aGUgb3V0cHV0IG5vdGUgYW55IHJlbGV2YW50IHZhbHVlcy4NCg0KKiBDb21tYW5kOiB6X3Njb3JlID0gKCBWQVJJQUJMRSAtIG1lYW4oVkFSSUFCTEUpICkgLyBzZChWQVJJQUJMRSkNCiogQ29tbWFuZHM6IHFwbG90KCB4ID0gVkFSSUFCTEUgLGdlb209Imhpc3RvZ3JhbSIsIGJpbndpZHRoID0gMC4zKQ0KDQpgYGB7cn0NCnpfc2NvcmVfc2FsZXMgPSAoIHNhbGVzIC0gbWVhbihzYWxlcykgKSAvIHNkKHNhbGVzKQ0Kel9zY29yZV90diA9ICggdHYgLSBtZWFuKHR2KSApIC8gc2QodHYpDQp6X3Njb3JlX3JhZGlvID0gKCByYWRpbyAtIG1lYW4ocmFkaW8pICkgLyBzZChyYWRpbykNCnpfc2NvcmVfbmV3c3BhcGVyID0gKCBuZXdzcGFwZXIgLSBtZWFuKG5ld3NwYXBlcikgKSAvIHNkKG5ld3NwYXBlcikNCmBgYA0KDQpgYGB7cn0NCnFwbG90KCB4ID0gel9zY29yZV9zYWxlcyAsZ2VvbT0iaGlzdG9ncmFtIiwgYmlud2lkdGggPSAwLjMpDQpgYGANCmBgYHtyfQ0KcXBsb3QoIHggPSB6X3Njb3JlX3R2ICxnZW9tPSJoaXN0b2dyYW0iLCBiaW53aWR0aCA9IDAuMykNCmBgYA0KYGBge3J9DQpxcGxvdCggeCA9IHpfc2NvcmVfcmFkaW8gLGdlb209Imhpc3RvZ3JhbSIsIGJpbndpZHRoID0gMC4zKQ0KYGBgDQpgYGB7cn0NCnFwbG90KCB4ID0gel9zY29yZV9uZXdzcGFwZXIgLGdlb209Imhpc3RvZ3JhbSIsIGJpbndpZHRoID0gMC4zKQ0KYGBgDQojIFNhbGVzIGlzIHRoZSBtb3N0IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBSYWRpbyBhbmQgVFYgYXJlIGJvdGggc2VlbSB0byB2YXJ5IHRocm91Z2hvdXQgdGhlIGdyYXBoLiBOZXdzcGFwZXIgaXMgcmlnaHQgc2tld2VkIHdoaWNoIG1ha2VzIHNlbnNlIHNpbmNlIGl0IHdhcyB0aGUgb25seSB2YXJpYWJsZSB3aXRoIG9vdXRsaWVycy4gIA0KDQojIyMgM0IpIEdpdmVuIGEgc2FsZXMgdmFsdWUgb2YgJDI2NzAwLCBjYWxjdWxhdGUgdGhlIGNvcnJlc3BvbmRpbmcgei12YWx1ZSBvciB6LXNjb3JlLiANCg0KKiBDb21tYW5kOiB6X3Njb3JlID0gKCBWQVJJQUJMRSAtIG1lYW4oVkFSSUFCTEUpICkgLyBzZChWQVJJQUJMRSkNCg0KYGBge3J9DQp4ID0gMjYuNw0KIHpfc2NvcmVfY2FsY3VsYXRlY29yID0gKCB4IC0gbWVhbihzYWxlcykgKSAvIHNkKHNhbGVzKQ0KIHpfc2NvcmVfY2FsY3VsYXRlY29yDQpgYGANCg0KDQojIyMgM0MpIEJhc2VkIG9uIHRoZSB6LXZhbHVlLCBob3cgd291bGQgeW91IHJhdGUgYSAkMjY3MDAgc2FsZXMgdmFsdWU6IHBvb3IsIGF2ZXJhZ2UsIGdvb2QsIG9yIHZlcnkgZ29vZCBwZXJmb3JtYW5jZT8gRXhwbGFpbiB5b3VyIGxvZ2ljLiANCg0KIyBJIHRoaW5rIHRoaXMgaXMgYSBnb29kIHBlcmZvcm1hbmNlIGJlY2F1c2Ugc2luY2UgaXQncyBhIHBvc2l0aXZlIHotc2NvcmUgaXQgd2lsbCBicmluZyBhYm91dCBhIHByb2ZpdCBhbmQgaXQgd2lsbCBkbyB0aGUgc2FtZSB0aGUgbmV4dCB0aW1lIHdoaWNoIGlzIGdvb2QgZm9yIGJ1c2luZXNzLiANCg0KDQo=