Notebook Instructions


About

  • In a given year, if it rains more, we may see that there might be an increase in crop production. This is because more water may lead to more plants.

  • This is a direct relationship; the number of fruits may be able to be predicted by amount of waterfall in a certain year.

  • This example represents simple linear regression, which is an extremely useful concept that allows us to predict values of a certain variable based off another variable.

  • This lab will explore the concepts of simple linear regression, multiple linear regression, and watson analytics.

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.7.2     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: plotly

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

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

    last_plot

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

    filter

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

    layout

Task 1: Correlation 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() rename() head()

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

mydata = read.csv(file="data/Advertising.csv")
head(mydata)

1B) Create a correlation table for your to compare the correlations between all variables. Remove any variables where correlation between variables is irrelevant or inaccurate

  • Commands: cor() mydata[ -c(“COLUMN_NAME OR COLUMN_NUMBER”) ]
#corr = cor( MYDATA )
#corr
corr = cor(mydata)
corr
                    X         TV       radio   newspaper       sales
X          1.00000000 0.01771469 -0.11068044 -0.15494414 -0.05161625
TV         0.01771469 1.00000000  0.05480866  0.05664787  0.78222442
radio     -0.11068044 0.05480866  1.00000000  0.35410375  0.57622257
newspaper -0.15494414 0.05664787  0.35410375  1.00000000  0.22829903
sales     -0.05161625 0.78222442  0.57622257  0.22829903  1.00000000

1C) Why is the value “1.0” down the diagonal? Which pairs seem to have the strongest correlations, list the pairs.

These variables are correlated with themselves. Pairs with the strongest correlations: Radio and TV Newspaper and TV Sales and TV

1D-a) Identifying the dependent variable (y) and one independent variable (x_i) using the correlation table to identify a variable with a coefficient greater than 0.20 and lower than 0.60. Use those two variables to create a scatterplot to visualize the data. Note any patterns or relation between the two variables

  • Commands: qplot( x = VARIABLE, y = VARIABLE, data = mydata)
qplot( x = mydata$radio, y = mydata$sales, data = mydata)

qplot
function (x, y = NULL, ..., data, facets = NULL, margins = FALSE, 
    geom = "auto", xlim = c(NA, NA), ylim = c(NA, NA), log = "", 
    main = NULL, xlab = deparse(substitute(x)), ylab = deparse(substitute(y)), 
    asp = NA, stat = NULL, position = NULL) 
{
    if (!missing(stat)) 
        warning("`stat` is deprecated", call. = FALSE)
    if (!missing(position)) 
        warning("`position` is deprecated", call. = FALSE)
    if (!is.character(geom)) 
        stop("`geom` must be a character vector", call. = FALSE)
    argnames <- names(as.list(match.call(expand.dots = FALSE)[-1]))
    arguments <- as.list(match.call()[-1])
    env <- parent.frame()
    aesthetics <- compact(arguments[.all_aesthetics])
    aesthetics <- aesthetics[!is.constant(aesthetics)]
    aes_names <- names(aesthetics)
    aesthetics <- rename_aes(aesthetics)
    class(aesthetics) <- "uneval"
    if (missing(data)) {
        data <- data.frame()
        facetvars <- all.vars(facets)
        facetvars <- facetvars[facetvars != "."]
        names(facetvars) <- facetvars
        facetsdf <- as.data.frame(mget(facetvars, envir = env))
        if (nrow(facetsdf)) 
            data <- facetsdf
    }
    if ("auto" %in% geom) {
        if ("sample" %in% aes_names) {
            geom[geom == "auto"] <- "qq"
        }
        else if (missing(y)) {
            x <- eval(aesthetics$x, data, env)
            if (is.discrete(x)) {
                geom[geom == "auto"] <- "bar"
            }
            else {
                geom[geom == "auto"] <- "histogram"
            }
            if (missing(ylab)) 
                ylab <- "count"
        }
        else {
            if (missing(x)) {
                aesthetics$x <- bquote(seq_along(.(y)), aesthetics)
            }
            geom[geom == "auto"] <- "point"
        }
    }
    p <- ggplot(data, aesthetics, environment = env)
    if (is.null(facets)) {
        p <- p + facet_null()
    }
    else if (is.formula(facets) && length(facets) == 2) {
        p <- p + facet_wrap(facets)
    }
    else {
        p <- p + facet_grid(facets = deparse(facets), margins = margins)
    }
    if (!is.null(main)) 
        p <- p + ggtitle(main)
    for (g in geom) {
        params <- arguments[setdiff(names(arguments), c(aes_names, 
            argnames))]
        params <- lapply(params, eval, parent.frame())
        p <- p + do.call(paste0("geom_", g), params)
    }
    logv <- function(var) var %in% strsplit(log, "")[[1]]
    if (logv("x")) 
        p <- p + scale_x_log10()
    if (logv("y")) 
        p <- p + scale_y_log10()
    if (!is.na(asp)) 
        p <- p + theme(aspect.ratio = asp)
    if (!missing(xlab)) 
        p <- p + xlab(xlab)
    if (!missing(ylab)) 
        p <- p + ylab(ylab)
    if (!missing(xlim)) 
        p <- p + xlim(xlim)
    if (!missing(ylim)) 
        p <- p + ylim(ylim)
    p
}
<environment: namespace:ggplot2>

According to this graph, there appears to be a general positive trend between radio and sales. This implies that increase in radio advertisements generates more sales.

1D-b) Create a 3D scatterplot between the two of the strongest correlated variables to the dependent variable. Note any patterns and the coordinates of three points with the heights values (x,y,z)

#p <- plot_ly(mydata, x = ~VARIBLE_1, y = ~VARIBLE_2, z = ~VARIBLE_3, marker = list(size = 5)) %>%
#  add_markers() %>% 
#p
p <- plot_ly(mydata, x = ~mydata$radio, y = ~mydata$TV, z =~mydata$sales , marker = list(size = 5)) %>%
  add_markers()
p

According to this graph, we can see a clearer visualization of a general positive trend between sales, radio and TV. We can infer that both TV and radio generate greater sales.

Task 2: Regression Analysis


2A) Create a linear regression model by identifying the dependent variable (y) and for independent variable (x_i) use the correlation table to identify a variable with a coefficient greater than 0.20 and lower than 0.60. (same variables as 1D-a)

  • Commands: lm( y ~ x )
#Simple Linear Regression Model
#reg <- lm( DEPENDENT_VARIABLE ~ INDEPENDENT_VARIABLE )
reg <- lm(mydata$sales ~ mydata$radio)
reg

Call:
lm(formula = mydata$sales ~ mydata$radio)

Coefficients:
 (Intercept)  mydata$radio  
      9.3116        0.2025  

2B) Use the regression model to create a report. Note the R-Squared and Adjusted R-Squared values, determine if this is a good or bad fit for your data?

  • Commands: Use the summary() function to create a report for the linear model
#Summary of Simple Linear Regression Model
#summary(MODEL)
summary(reg)

Call:
lm(formula = mydata$sales ~ mydata$radio)

Residuals:
     Min       1Q   Median       3Q      Max 
-15.7305  -2.1324   0.7707   2.7775   8.1810 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   9.31164    0.56290  16.542   <2e-16 ***
mydata$radio  0.20250    0.02041   9.921   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.275 on 198 degrees of freedom
Multiple R-squared:  0.332, Adjusted R-squared:  0.3287 
F-statistic: 98.42 on 1 and 198 DF,  p-value: < 2.2e-16

From this summary, we can identify that the R-squared value is 0.332 and the adjusted R-squared value is 0.3287, which means these variables aren’t a good fit for the dataset. As we know from statistics, correlation coefficients less than 0.5 represent a weak relationship between variables.

2C) Create a plot for the dependent (y) and independent (x) variables Note any patterns or relation between the two variables describe the trend line.

  • The trend line will show how far the predictions are from the actual value
  • The distance from the actual versus the predicted is the residual
#p <- qplot( x = INDEPENDENT_VARIABLE, y = DEPENDENT_VARIABLE, data = mydata) + geom_point()
p <- qplot( x = mydata$radio, y = mydata$sales, data = mydata) + geom_point()
#Add a trend line plot using the a linear model
#p + geom_smooth(method = "lm", formula = y ~ x)
p + geom_smooth(method="lm")

This trendline demonstrates a positive linear relationship between radio and sales.

2D-a) Create a Multiple linear regression model and summary report using the two strongest correlated variables and the dependent variable. Note the R-Squared and Adjusted R-Squared values, determine if this is a good or bad fit for your data? Compared this model to the previous model, which model is better?

  • Sometimes, one variable is very good at predicting another variable. But most times, there are more than one factors that affect the prediction of another variable.
  • While increased rainfall is a good predictor of increased crop supply, decreased herbivores can also result in an increase of crops.
  • This idea is a loose metaphor for multiple linear regression.

  • Multiple linear regression lm(y ~ x_0 + x_1 + x_2 + … x_i )
  • Where y is the predicted/dependent variable and the x variables are the predictors/independent variable

  • commands: lm( y ~ x_1 + x_2 ) summary( reg_model )

#Multiple Linear Regression Model
#mlr1 <- lm( DEPENDENT_VARIABLE ~ INDEPENDENT_VARIABLE1 + INDEPENDENT_VARIABLE2 )
mlrl <- lm(mydata$sales ~ mydata$radio)
mlrl

Call:
lm(formula = mydata$sales ~ mydata$radio)

Coefficients:
 (Intercept)  mydata$radio  
      9.3116        0.2025  
#Summary of Multiple Linear Regression Model
summary(mlrl)

Call:
lm(formula = mydata$sales ~ mydata$radio)

Residuals:
     Min       1Q   Median       3Q      Max 
-15.7305  -2.1324   0.7707   2.7775   8.1810 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   9.31164    0.56290  16.542   <2e-16 ***
mydata$radio  0.20250    0.02041   9.921   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.275 on 198 degrees of freedom
Multiple R-squared:  0.332, Adjusted R-squared:  0.3287 
F-statistic: 98.42 on 1 and 198 DF,  p-value: < 2.2e-16

For mlr1, the R-Squared values is 0.8972 and the Adj R-Squared is 0.8962.

Y_sales_predicted = 9.31164 + 0.20250*(radio)

2D-b) Create a Multiple Linear Regression Model using all relevant independent variables and the dependent variable. Note the R-Squared and Adjusted R-Squared values, determine if this is a good or bad fit for your data?

mlr2 <-lm(mydata$sales ~ mydata$radio + mydata$TV)
summary(mlr2)

Call:
lm(formula = mydata$sales ~ mydata$radio + mydata$TV)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.7977 -0.8752  0.2422  1.1708  2.8328 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   2.92110    0.29449   9.919   <2e-16 ***
mydata$radio  0.18799    0.00804  23.382   <2e-16 ***
mydata$TV     0.04575    0.00139  32.909   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.681 on 197 degrees of freedom
Multiple R-squared:  0.8972,    Adjusted R-squared:  0.8962 
F-statistic: 859.6 on 2 and 197 DF,  p-value: < 2.2e-16

Y_sales_predicted = 2.92110 + 0.18799(radio) + 0.04575(TV)

mlr3 <-lm(mydata$sales ~ mydata$radio + mydata$TV + mydata$newspaper)
summary(mlr3)

Call:
lm(formula = mydata$sales ~ mydata$radio + mydata$TV + mydata$newspaper)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.8277 -0.8908  0.2418  1.1893  2.8292 

Coefficients:
                  Estimate Std. Error t value Pr(>|t|)    
(Intercept)       2.938889   0.311908   9.422   <2e-16 ***
mydata$radio      0.188530   0.008611  21.893   <2e-16 ***
mydata$TV         0.045765   0.001395  32.809   <2e-16 ***
mydata$newspaper -0.001037   0.005871  -0.177     0.86    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.686 on 196 degrees of freedom
Multiple R-squared:  0.8972,    Adjusted R-squared:  0.8956 
F-statistic: 570.3 on 3 and 196 DF,  p-value: < 2.2e-16

Y_sales_predicted = 2.938889 + 0.188530(radio) + 0.045765(TV) -0.001037*(newspaper)

Based purely on the values for R-Squared and Adjusted R-Squared, which linear regression model is best in predicting the dependent variable? Explain why

Between these models, it appears mlr is the better regression line, as the adjusted R-squared value is lower.

2E) Use the three different models to predicted the dependent variable for the given values of the independent variables.

  • Variable: Radio = 69
  • Variable: TV = 255
  • Variable: newspaper = 75

MODEL 1

radio=69
TV=255
newspaper=75
Smlr1= 9.31164  + 0.20250*(radio)
Smlr1
[1] 23.28414

MODEL 2

Smlr2 = 2.92110  + 0.18799*(radio) + 0.04575*(TV)
Smlr2
[1] 27.55866

MODEL 3

Smlr3 = 2.938889 + 0.188530*(radio) + 0.045765*(TV) -0.001037*(newspaper)
Smlr3
[1] 27.53976

Task 3: Watson Analysis


To complete the last task, follow the directions found below. Make sure to screenshot and attach any pictures of the results obtained or any questions asked.

3A) Use the Predictive module to analyze the given data. Note any interesting patterns add an screenshot of what you found.

knitr::include_graphics('C:\\Users\\hp\\Documents\\Spring 2018\\BSAD 343H\\Labs\\Lab 5\\data\\img1.png')

3B) Note the predictive power strength of reported variables. Consider the one field predictive model only, describe your findings and add and screenshot

Predictive strength of TV =59% Predictive strength of Radio = 32% Predictive strength of radio and TV = 94%

3C) How do Watson results reconcile with your findings based on the R regression analysis in task 2? Explain how.

To test Watson’s results, let’s analyze each independent variable against sales. As we’ve previously seen, mlrl (model 1) illustrates the relationship between sales and radio. Let’s now analyze sales and TV:

summary(mlrl4)

Call:
lm(formula = mydata$sales ~ mydata$TV)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.3860 -1.9545 -0.1913  2.0671  7.2124 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 7.032594   0.457843   15.36   <2e-16 ***
mydata$TV   0.047537   0.002691   17.67   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.259 on 198 degrees of freedom
Multiple R-squared:  0.6119,    Adjusted R-squared:  0.6099 
F-statistic: 312.1 on 1 and 198 DF,  p-value: < 2.2e-16

Here, we notice the relationship between these variables. From these findings, we can deduce whether or not they adhere to Watson’s results.

According to our models, we will look at the R squared value, as this describes how well the dataset fits our regression model. For sales vs. TV, r-squared = 0.6119 ~ 61.19% (Watson = 59%) For sales vs. radio, r-squared = 0.332 ~ 33.2% (Waton = 32%) For sales vs. TV vs. radio, r-squared = 0.8972 ~ 89.72% (Watson = 94%)

while there may be some variance due to different methods of calculating predictive strength, results from the regression analysis and Watson results match well enough to be considered as a valid relationship between these variables.

LS0tDQp0aXRsZTogIlByZWRpY3RpdmUgQW5hbHl0aWNzIg0KYXV0aG9yOiAiQ2hleWVubmUgUGVubnkiDQpkYXRlOiAiRmVicnVhcnkgMjIsIDIwMTgiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0Kc3VidGl0bGU6IENNRSBHcm91cCBGb3VuZGF0aW9uIEJ1c2luZXNzIEFuYWx5dGljcyBMYWINCi0tLQ0KDQotLS0tLS0tLS0tLS0tDQoNCiMjIE5vdGVib29rIEluc3RydWN0aW9ucw0KDQotLS0tLS0tLS0tLS0tDQoNCiogRm9yIHlvdXIgYXNzaWdubWVudCB5b3UgbWF5IGJlIHVzaW5nIGRpZmZlcmVudCBkYXRhc2V0IHRoYW4gd2hhdCBpcyBpbmNsdWRlZCBoZXJlLiANCg0KKiBBbHdheXMgcmVhZCBjYXJlZnVsbHkgdGhlIGluc3RydWN0aW9ucyBvbiBTYWthaS4gIA0KDQoqIFRhc2tzL3F1ZXN0aW9ucyB0byBiZSBjb21wbGV0ZWQvYW5zd2VyZWQgYXJlIGhpZ2hsaWdodGVkIGluIGxhcmdlciBib2xkZWQgZm9udHMgYW5kIG51bWJlcmVkIGFjY29yZGluZyB0byB0aGVpciBzZWN0aW9uLg0KDQojIyMgQWJvdXQNCg0KKiBJbiBhIGdpdmVuIHllYXIsIGlmIGl0IHJhaW5zIG1vcmUsIHdlIG1heSBzZWUgdGhhdCB0aGVyZSBtaWdodCBiZSBhbiBpbmNyZWFzZSBpbiBjcm9wIHByb2R1Y3Rpb24uIFRoaXMgaXMgYmVjYXVzZSBtb3JlIHdhdGVyIG1heSBsZWFkIHRvIG1vcmUgcGxhbnRzLiANCg0KKiBUaGlzIGlzIGEgZGlyZWN0IHJlbGF0aW9uc2hpcDsgdGhlIG51bWJlciBvZiBmcnVpdHMgbWF5IGJlIGFibGUgdG8gYmUgcHJlZGljdGVkIGJ5IGFtb3VudCBvZiB3YXRlcmZhbGwgaW4gYSBjZXJ0YWluIHllYXIuIA0KDQoqIFRoaXMgZXhhbXBsZSByZXByZXNlbnRzIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbiwgd2hpY2ggaXMgYW4gZXh0cmVtZWx5IHVzZWZ1bCBjb25jZXB0IHRoYXQgYWxsb3dzIHVzIHRvIHByZWRpY3QgdmFsdWVzIG9mIGEgY2VydGFpbiB2YXJpYWJsZSBiYXNlZCBvZmYgYW5vdGhlciB2YXJpYWJsZS4gDQoNCiogVGhpcyBsYWIgd2lsbCBleHBsb3JlIHRoZSBjb25jZXB0cyBvZiBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24sIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uLCBhbmQgd2F0c29uIGFuYWx5dGljcy4gDQoNCg0KIyMjIExvYWQgUGFja2FnZXMgaW4gUi9SU3R1ZGlvIA0KDQpXZSBhcmUgZ29pbmcgdG8gdXNlIHRpZHl2ZXJzZSBhIGNvbGxlY3Rpb24gb2YgUiBwYWNrYWdlcyBkZXNpZ25lZCBmb3IgZGF0YSBzY2llbmNlLiANCg0KKiBJbmZvOiBodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLw0KDQpgYGB7ciwgZWNobyA9IEZBTFNFfQ0KDQojIEhlcmUgd2UgYXJlIGNoZWNraW5nIGlmIHRoZSBwYWNrYWdlIGlzIGluc3RhbGxlZA0KaWYoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKXsNCiAgDQogICMgSWYgdGhlIHBhY2thZ2UgaXMgbm90IGluIHRoZSBzeXN0ZW0gdGhlbiBpdCB3aWxsIGJlIGluc3RhbGwNCiAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIiwgZGVwZW5kZW5jaWVzID0gVFJVRSkNCiAgDQogICMgSGVyZSB3ZSBhcmUgbG9hZGluZyB0aGUgcGFja2FnZQ0KICBsaWJyYXJ5KCJ0aWR5dmVyc2UiKQ0KfQ0KDQojIEhlcmUgd2UgYXJlIGNoZWNraW5nIGlmIHRoZSBwYWNrYWdlIGlzIGluc3RhbGxlZA0KaWYoIXJlcXVpcmUoInBsb3RseSIpKXsNCiAgDQogICMgSWYgdGhlIHBhY2thZ2UgaXMgbm90IGluIHRoZSBzeXN0ZW0gdGhlbiBpdCB3aWxsIGJlIGluc3RhbGwNCiAgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IiwgZGVwZW5kZW5jaWVzID0gVFJVRSkNCiAgDQogICMgSGVyZSB3ZSBhcmUgbG9hZGluZyB0aGUgcGFja2FnZQ0KICBsaWJyYXJ5KCJwbG90bHkiKQ0KfQ0KDQpgYGANCg0KLS0tLS0tLS0tLS0tLQ0KDQojIyBUYXNrIDE6IENvcnJlbGF0aW9uIEFuYWx5c2lzDQoNCi0tLS0tLS0tLS0tLS0NCg0KIyMjIDFBKSBSZWFkIHRoZSBjc3YgZmlsZSBpbnRvIFIgU3R1ZGlvIGFuZCBkaXNwbGF5IHRoZSBkYXRhc2V0LiANCg0KKiBOYW1lIHlvdXIgZGF0YXNldCAnbXlkYXRhJyBzbyBpdCBlYXN5IHRvIHdvcmsgd2l0aC4NCg0KKiBDb21tYW5kczogcmVhZF9jc3YoKSByZW5hbWUoKSBoZWFkKCkNCg0KIyMjIyBFeHRyYWN0IHRoZSBhc3NpZ25lZCBmZWF0dXJlcyAoY29sdW1ucykgdG8gcGVyZm9ybSBzb21lIGFuYWx5dGljcy4gDQoNCmBgYHtyfQ0KDQpteWRhdGEgPSByZWFkLmNzdihmaWxlPSJkYXRhL0FkdmVydGlzaW5nLmNzdiIpDQpoZWFkKG15ZGF0YSkNCg0KYGBgDQoNCiMjIyAxQikgQ3JlYXRlIGEgY29ycmVsYXRpb24gdGFibGUgZm9yIHlvdXIgdG8gY29tcGFyZSB0aGUgY29ycmVsYXRpb25zIGJldHdlZW4gYWxsIHZhcmlhYmxlcy4gUmVtb3ZlIGFueSB2YXJpYWJsZXMgd2hlcmUgY29ycmVsYXRpb24gYmV0d2VlbiB2YXJpYWJsZXMgaXMgaXJyZWxldmFudCBvciBpbmFjY3VyYXRlDQoNCiogQ29tbWFuZHM6IGNvcigpIG15ZGF0YVsgLWMoIkNPTFVNTl9OQU1FIE9SIENPTFVNTl9OVU1CRVIiKSBdDQoNCmBgYHtyfQ0KDQojY29yciA9IGNvciggTVlEQVRBICkNCiNjb3JyDQoNCmNvcnIgPSBjb3IobXlkYXRhKQ0KY29ycg0KYGBgDQoNCiMjIyAxQykgV2h5IGlzIHRoZSB2YWx1ZSAiMS4wIiBkb3duIHRoZSBkaWFnb25hbD8gV2hpY2ggcGFpcnMgc2VlbSB0byBoYXZlIHRoZSBzdHJvbmdlc3QgY29ycmVsYXRpb25zLCBsaXN0IHRoZSBwYWlycy4gDQoNClRoZXNlIHZhcmlhYmxlcyBhcmUgY29ycmVsYXRlZCB3aXRoIHRoZW1zZWx2ZXMuIA0KUGFpcnMgd2l0aCB0aGUgc3Ryb25nZXN0IGNvcnJlbGF0aW9uczoNClJhZGlvIGFuZCBUVg0KTmV3c3BhcGVyIGFuZCBUVg0KU2FsZXMgYW5kIFRWDQoNCiMjIyAxRC1hKSBJZGVudGlmeWluZyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlICh5KSBhbmQgb25lIGluZGVwZW5kZW50IHZhcmlhYmxlICh4X2kpIHVzaW5nIHRoZSBjb3JyZWxhdGlvbiB0YWJsZSB0byBpZGVudGlmeSBhIHZhcmlhYmxlIHdpdGggYSBjb2VmZmljaWVudCBncmVhdGVyIHRoYW4gMC4yMCBhbmQgbG93ZXIgdGhhbiAwLjYwLiBVc2UgdGhvc2UgdHdvIHZhcmlhYmxlcyB0byBjcmVhdGUgYSBzY2F0dGVycGxvdCB0byB2aXN1YWxpemUgdGhlIGRhdGEuIE5vdGUgYW55IHBhdHRlcm5zIG9yIHJlbGF0aW9uIGJldHdlZW4gdGhlIHR3byB2YXJpYWJsZXMNCg0KKiBDb21tYW5kczogcXBsb3QoIHggPSBWQVJJQUJMRSwgeSA9IFZBUklBQkxFLCBkYXRhID0gbXlkYXRhKQ0KDQpgYGB7cn0NCg0KcXBsb3QoIHggPSBteWRhdGEkcmFkaW8sIHkgPSBteWRhdGEkc2FsZXMsIGRhdGEgPSBteWRhdGEpDQpxcGxvdA0KDQpgYGANCg0KQWNjb3JkaW5nIHRvIHRoaXMgZ3JhcGgsIHRoZXJlIGFwcGVhcnMgdG8gYmUgYSBnZW5lcmFsIHBvc2l0aXZlIHRyZW5kIGJldHdlZW4gcmFkaW8gYW5kIHNhbGVzLiBUaGlzIGltcGxpZXMgdGhhdCBpbmNyZWFzZSBpbiByYWRpbyBhZHZlcnRpc2VtZW50cyBnZW5lcmF0ZXMgbW9yZSBzYWxlcy4gDQoNCiMjIyAxRC1iKSBDcmVhdGUgYSAzRCBzY2F0dGVycGxvdCBiZXR3ZWVuIHRoZSB0d28gb2YgdGhlIHN0cm9uZ2VzdCBjb3JyZWxhdGVkIHZhcmlhYmxlcyB0byB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLiBOb3RlIGFueSBwYXR0ZXJucyBhbmQgdGhlIGNvb3JkaW5hdGVzIG9mIHRocmVlIHBvaW50cyB3aXRoIHRoZSBoZWlnaHRzIHZhbHVlcyAoeCx5LHopDQoNCmBgYHtyfQ0KDQojcCA8LSBwbG90X2x5KG15ZGF0YSwgeCA9IH5WQVJJQkxFXzEsIHkgPSB+VkFSSUJMRV8yLCB6ID0gflZBUklCTEVfMywgbWFya2VyID0gbGlzdChzaXplID0gNSkpICU+JQ0KIyAgYWRkX21hcmtlcnMoKSAlPiUgDQojcA0KDQoNCnAgPC0gcGxvdF9seShteWRhdGEsIHggPSB+bXlkYXRhJHJhZGlvLCB5ID0gfm15ZGF0YSRUViwgeiA9fm15ZGF0YSRzYWxlcyAsIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDUpKSAlPiUNCiAgYWRkX21hcmtlcnMoKQ0KDQpwDQpgYGANCg0KQWNjb3JkaW5nIHRvIHRoaXMgZ3JhcGgsIHdlIGNhbiBzZWUgYSBjbGVhcmVyIHZpc3VhbGl6YXRpb24gb2YgYSBnZW5lcmFsIHBvc2l0aXZlIHRyZW5kIGJldHdlZW4gc2FsZXMsIHJhZGlvIGFuZCBUVi4gV2UgY2FuIGluZmVyIHRoYXQgYm90aCBUViBhbmQgcmFkaW8gZ2VuZXJhdGUgZ3JlYXRlciBzYWxlcy4NCi0tLS0tLS0tLS0tLS0NCg0KIyMgVGFzayAyOiBSZWdyZXNzaW9uIEFuYWx5c2lzDQoNCi0tLS0tLS0tLS0tLS0NCg0KKiBUbyBjcmVhdGUgYSByZWdyZXNzaW9uIG1vZGVsIHdlIHVzZSB0aGUgZnVuY3Rpb24gbG0oKSwgc3VjaCBhcyBsbSggeSB+IHggKQ0KKiBXaGVyZSB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGUgb3IgdmFyaWFibGVzIFsgeF8xLCB4XzIsIC4uLiB4X2kgXSwgcHJlZGljdCB0aGUgdmFsdWVzIG9mIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgeS4NCg0KIyMjIDJBKSBDcmVhdGUgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBieSBpZGVudGlmeWluZyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlICh5KSBhbmQgZm9yIGluZGVwZW5kZW50IHZhcmlhYmxlICh4X2kpIHVzZSB0aGUgY29ycmVsYXRpb24gdGFibGUgdG8gaWRlbnRpZnkgYSB2YXJpYWJsZSB3aXRoIGEgY29lZmZpY2llbnQgZ3JlYXRlciB0aGFuIDAuMjAgYW5kIGxvd2VyIHRoYW4gMC42MC4gKHNhbWUgdmFyaWFibGVzIGFzIDFELWEpDQoNCiogQ29tbWFuZHM6IGxtKCB5IH4geCApIA0KDQpgYGB7cn0NCiNTaW1wbGUgTGluZWFyIFJlZ3Jlc3Npb24gTW9kZWwNCg0KI3JlZyA8LSBsbSggREVQRU5ERU5UX1ZBUklBQkxFIH4gSU5ERVBFTkRFTlRfVkFSSUFCTEUgKQ0KcmVnIDwtIGxtKG15ZGF0YSRzYWxlcyB+IG15ZGF0YSRyYWRpbykNCnJlZw0KYGBgDQoNCg0KIyMjIDJCKSBVc2UgdGhlIHJlZ3Jlc3Npb24gbW9kZWwgdG8gY3JlYXRlIGEgcmVwb3J0LiBOb3RlIHRoZSBSLVNxdWFyZWQgYW5kIEFkanVzdGVkIFItU3F1YXJlZCB2YWx1ZXMsIGRldGVybWluZSBpZiB0aGlzIGlzIGEgZ29vZCBvciBiYWQgZml0IGZvciB5b3VyIGRhdGE/DQoNCiogQ29tbWFuZHM6IFVzZSB0aGUgc3VtbWFyeSgpIGZ1bmN0aW9uIHRvIGNyZWF0ZSBhIHJlcG9ydCBmb3IgdGhlIGxpbmVhciBtb2RlbA0KDQpgYGB7cn0NCiNTdW1tYXJ5IG9mIFNpbXBsZSBMaW5lYXIgUmVncmVzc2lvbiBNb2RlbA0KDQojc3VtbWFyeShNT0RFTCkNCg0Kc3VtbWFyeShyZWcpDQoNCmBgYA0KDQpGcm9tIHRoaXMgc3VtbWFyeSwgd2UgY2FuIGlkZW50aWZ5IHRoYXQgdGhlIFItc3F1YXJlZCB2YWx1ZSBpcyAwLjMzMiBhbmQgdGhlIGFkanVzdGVkIFItc3F1YXJlZCB2YWx1ZSBpcyAwLjMyODcsIHdoaWNoIG1lYW5zIHRoZXNlIHZhcmlhYmxlcyBhcmVuJ3QgYSBnb29kIGZpdCBmb3IgdGhlIGRhdGFzZXQuIEFzIHdlIGtub3cgZnJvbSBzdGF0aXN0aWNzLCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgbGVzcyB0aGFuIDAuNSByZXByZXNlbnQgYSB3ZWFrIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHZhcmlhYmxlcy4gDQoNCiMjIyAyQykgQ3JlYXRlIGEgcGxvdCBmb3IgdGhlIGRlcGVuZGVudCAoeSkgYW5kIGluZGVwZW5kZW50ICh4KSB2YXJpYWJsZXMgTm90ZSBhbnkgcGF0dGVybnMgb3IgcmVsYXRpb24gYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcyBkZXNjcmliZSB0aGUgdHJlbmQgbGluZS4NCg0KKiBUaGUgdHJlbmQgbGluZSB3aWxsIHNob3cgaG93IGZhciB0aGUgcHJlZGljdGlvbnMgYXJlIGZyb20gdGhlIGFjdHVhbCB2YWx1ZQ0KKiBUaGUgZGlzdGFuY2UgZnJvbSB0aGUgYWN0dWFsIHZlcnN1cyB0aGUgcHJlZGljdGVkIGlzIHRoZSByZXNpZHVhbA0KDQpgYGB7cn0NCg0KI3AgPC0gcXBsb3QoIHggPSBJTkRFUEVOREVOVF9WQVJJQUJMRSwgeSA9IERFUEVOREVOVF9WQVJJQUJMRSwgZGF0YSA9IG15ZGF0YSkgKyBnZW9tX3BvaW50KCkNCg0KcCA8LSBxcGxvdCggeCA9IG15ZGF0YSRyYWRpbywgeSA9IG15ZGF0YSRzYWxlcywgZGF0YSA9IG15ZGF0YSkgKyBnZW9tX3BvaW50KCkNCg0KDQojQWRkIGEgdHJlbmQgbGluZSBwbG90IHVzaW5nIHRoZSBhIGxpbmVhciBtb2RlbA0KI3AgKyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0geSB+IHgpDQoNCnAgKyBnZW9tX3Ntb290aChtZXRob2Q9ImxtIikNCg0KYGBgDQpUaGlzIHRyZW5kbGluZSBkZW1vbnN0cmF0ZXMgYSBwb3NpdGl2ZSBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gcmFkaW8gYW5kIHNhbGVzLiANCg0KDQoNCiMjIyAyRC1hKSBDcmVhdGUgYSBNdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBhbmQgc3VtbWFyeSByZXBvcnQgdXNpbmcgdGhlIHR3byBzdHJvbmdlc3QgY29ycmVsYXRlZCB2YXJpYWJsZXMgYW5kIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIE5vdGUgdGhlIFItU3F1YXJlZCBhbmQgQWRqdXN0ZWQgUi1TcXVhcmVkIHZhbHVlcywgZGV0ZXJtaW5lIGlmIHRoaXMgaXMgYSBnb29kIG9yIGJhZCBmaXQgZm9yIHlvdXIgZGF0YT8gQ29tcGFyZWQgdGhpcyBtb2RlbCB0byB0aGUgcHJldmlvdXMgbW9kZWwsIHdoaWNoIG1vZGVsIGlzIGJldHRlcj8gDQoNCiogU29tZXRpbWVzLCBvbmUgdmFyaWFibGUgaXMgdmVyeSBnb29kIGF0IHByZWRpY3RpbmcgYW5vdGhlciB2YXJpYWJsZS4gQnV0IG1vc3QgdGltZXMsIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lIGZhY3RvcnMgdGhhdCBhZmZlY3QgdGhlIHByZWRpY3Rpb24gb2YgYW5vdGhlciB2YXJpYWJsZS4NCiogV2hpbGUgaW5jcmVhc2VkIHJhaW5mYWxsIGlzIGEgZ29vZCBwcmVkaWN0b3Igb2YgaW5jcmVhc2VkIGNyb3Agc3VwcGx5LCBkZWNyZWFzZWQgaGVyYml2b3JlcyBjYW4gYWxzbyByZXN1bHQgaW4gYW4gaW5jcmVhc2Ugb2YgY3JvcHMuIA0KKiBUaGlzIGlkZWEgaXMgYSBsb29zZSBtZXRhcGhvciBmb3IgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24uIA0KDQoqIE11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIGxtKHkgfiB4XzAgKyB4XzEgKyB4XzIgKyAuLi4geF9pICkNCiogV2hlcmUgeSBpcyB0aGUgcHJlZGljdGVkL2RlcGVuZGVudCB2YXJpYWJsZSBhbmQgdGhlIHggdmFyaWFibGVzIGFyZSB0aGUgcHJlZGljdG9ycy9pbmRlcGVuZGVudCB2YXJpYWJsZSANCg0KKiBjb21tYW5kczogbG0oIHkgfiB4XzEgKyB4XzIgKSBzdW1tYXJ5KCByZWdfbW9kZWwgKQ0KDQpgYGB7cn0NCg0KI011bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uIE1vZGVsDQojbWxyMSA8LSBsbSggREVQRU5ERU5UX1ZBUklBQkxFIH4gSU5ERVBFTkRFTlRfVkFSSUFCTEUxICsgSU5ERVBFTkRFTlRfVkFSSUFCTEUyICkNCm1scmwgPC0gbG0obXlkYXRhJHNhbGVzIH4gbXlkYXRhJHJhZGlvKQ0KbWxybA0KI1N1bW1hcnkgb2YgTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb24gTW9kZWwNCnN1bW1hcnkobWxybCkNCg0KYGBgDQpGb3IgbWxyMSwgdGhlIFItU3F1YXJlZCB2YWx1ZXMgaXMgMC44OTcyIGFuZCB0aGUgQWRqIFItU3F1YXJlZCBpcyAwLjg5NjIuDQoNCllfc2FsZXNfcHJlZGljdGVkID0gOS4zMTE2NCAgKyAwLjIwMjUwKihyYWRpbykNCg0KIyMjIDJELWIpIENyZWF0ZSBhIE11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uIE1vZGVsIHVzaW5nIGFsbCByZWxldmFudCBpbmRlcGVuZGVudCB2YXJpYWJsZXMgYW5kIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIE5vdGUgdGhlIFItU3F1YXJlZCBhbmQgQWRqdXN0ZWQgUi1TcXVhcmVkIHZhbHVlcywgZGV0ZXJtaW5lIGlmIHRoaXMgaXMgYSBnb29kIG9yIGJhZCBmaXQgZm9yIHlvdXIgZGF0YT8NCmBgYHtyfQ0KbWxyMiA8LWxtKG15ZGF0YSRzYWxlcyB+IG15ZGF0YSRyYWRpbyArIG15ZGF0YSRUVikNCnN1bW1hcnkobWxyMikNCmBgYA0KDQpZX3NhbGVzX3ByZWRpY3RlZCA9IDIuOTIxMTAgICsgMC4xODc5OSoocmFkaW8pICsgMC4wNDU3NSooVFYpDQoNCg0KYGBge3J9DQptbHIzIDwtbG0obXlkYXRhJHNhbGVzIH4gbXlkYXRhJHJhZGlvICsgbXlkYXRhJFRWICsgbXlkYXRhJG5ld3NwYXBlcikNCnN1bW1hcnkobWxyMykNCmBgYA0KWV9zYWxlc19wcmVkaWN0ZWQgPSAyLjkzODg4OSArIDAuMTg4NTMwKihyYWRpbykgKyAwLjA0NTc2NSooVFYpIC0wLjAwMTAzNyoobmV3c3BhcGVyKQ0KDQojIyMjIEJhc2VkIHB1cmVseSBvbiB0aGUgdmFsdWVzIGZvciBSLVNxdWFyZWQgYW5kIEFkanVzdGVkIFItU3F1YXJlZCwgd2hpY2ggbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgaXMgYmVzdCBpbiBwcmVkaWN0aW5nIHRoZSBkZXBlbmRlbnQgdmFyaWFibGU/IEV4cGxhaW4gd2h5DQpCZXR3ZWVuIHRoZXNlIG1vZGVscywgaXQgYXBwZWFycyBtbHIgaXMgdGhlIGJldHRlciByZWdyZXNzaW9uIGxpbmUsIGFzIHRoZSBhZGp1c3RlZCBSLXNxdWFyZWQgdmFsdWUgaXMgbG93ZXIuICANCg0KDQojIyMgMkUpIFVzZSB0aGUgdGhyZWUgZGlmZmVyZW50IG1vZGVscyB0byBwcmVkaWN0ZWQgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBmb3IgdGhlIGdpdmVuIHZhbHVlcyBvZiB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLiANCg0KKiBWYXJpYWJsZTogUmFkaW8gPSA2OQ0KKiBWYXJpYWJsZTogVFYgPSAyNTUNCiogVmFyaWFibGU6IG5ld3NwYXBlciA9IDc1DQoNCioqTU9ERUwgMSoqDQpgYGB7cn0NCg0KcmFkaW89NjkNClRWPTI1NQ0KbmV3c3BhcGVyPTc1DQoNClNtbHIxPSA5LjMxMTY0ICArIDAuMjAyNTAqKHJhZGlvKQ0KDQpTbWxyMQ0KYGBgDQoNCioqTU9ERUwgMioqDQpgYGB7cn0NClNtbHIyID0gMi45MjExMCAgKyAwLjE4Nzk5KihyYWRpbykgKyAwLjA0NTc1KihUVikNCg0KU21scjINCmBgYA0KDQoqKk1PREVMIDMqKg0KYGBge3J9DQpTbWxyMyA9IDIuOTM4ODg5ICsgMC4xODg1MzAqKHJhZGlvKSArIDAuMDQ1NzY1KihUVikgLTAuMDAxMDM3KihuZXdzcGFwZXIpDQpTbWxyMw0KYGBgDQoNCg0KLS0tLS0tLS0tLS0tLQ0KDQojIyBUYXNrIDM6IFdhdHNvbiBBbmFseXNpcw0KDQotLS0tLS0tLS0tLS0tDQoNClRvIGNvbXBsZXRlIHRoZSBsYXN0IHRhc2ssIGZvbGxvdyB0aGUgZGlyZWN0aW9ucyBmb3VuZCBiZWxvdy4gTWFrZSBzdXJlIHRvIHNjcmVlbnNob3QgYW5kIGF0dGFjaCBhbnkgcGljdHVyZXMgb2YgdGhlIHJlc3VsdHMgb2J0YWluZWQgb3IgYW55IHF1ZXN0aW9ucyBhc2tlZC4gDQoNCiMjIyAzQSkgVXNlIHRoZSBQcmVkaWN0aXZlIG1vZHVsZSB0byBhbmFseXplIHRoZSBnaXZlbiBkYXRhLiBOb3RlIGFueSBpbnRlcmVzdGluZyBwYXR0ZXJucyBhZGQgYW4gc2NyZWVuc2hvdCBvZiB3aGF0IHlvdSBmb3VuZC4NCg0KYGBge3J9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygnQzpcXFVzZXJzXFxocFxcRG9jdW1lbnRzXFxTcHJpbmcgMjAxOFxcQlNBRCAzNDNIXFxMYWJzXFxMYWIgNVxcZGF0YVxcaW1nMS5wbmcnKQ0KDQpgYGANCg0KDQojIyMgM0IpIE5vdGUgdGhlIHByZWRpY3RpdmUgcG93ZXIgc3RyZW5ndGggb2YgcmVwb3J0ZWQgdmFyaWFibGVzLiBDb25zaWRlciB0aGUgb25lIGZpZWxkIHByZWRpY3RpdmUgbW9kZWwgb25seSwgZGVzY3JpYmUgeW91ciBmaW5kaW5ncyBhbmQgYWRkIGFuZCBzY3JlZW5zaG90DQpQcmVkaWN0aXZlIHN0cmVuZ3RoIG9mIFRWID01OSUNClByZWRpY3RpdmUgc3RyZW5ndGggb2YgUmFkaW8gPSAzMiUNClByZWRpY3RpdmUgc3RyZW5ndGggb2YgcmFkaW8gYW5kIFRWID0gOTQlDQoNCg0KIyMjIDNDKSBIb3cgZG8gV2F0c29uIHJlc3VsdHMgcmVjb25jaWxlIHdpdGggeW91ciBmaW5kaW5ncyBiYXNlZCBvbiB0aGUgUiByZWdyZXNzaW9uIGFuYWx5c2lzIGluIHRhc2sgMj8gRXhwbGFpbiBob3cuDQpUbyB0ZXN0IFdhdHNvbidzIHJlc3VsdHMsIGxldCdzIGFuYWx5emUgZWFjaCBpbmRlcGVuZGVudCB2YXJpYWJsZSBhZ2FpbnN0IHNhbGVzLiBBcyB3ZSd2ZSBwcmV2aW91c2x5IHNlZW4sIG1scmwgKG1vZGVsIDEpIGlsbHVzdHJhdGVzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzYWxlcyBhbmQgcmFkaW8uIExldCdzIG5vdyBhbmFseXplIHNhbGVzIGFuZCBUVjoNCg0KYGBge3J9DQptbHJsNCA8LSBsbShteWRhdGEkc2FsZXMgfiBteWRhdGEkVFYpDQpzdW1tYXJ5KG1scmw0KQ0KDQpgYGANCg0KSGVyZSwgd2Ugbm90aWNlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGVzZSB2YXJpYWJsZXMuIEZyb20gdGhlc2UgZmluZGluZ3MsIHdlIGNhbiBkZWR1Y2Ugd2hldGhlciBvciBub3QgdGhleSBhZGhlcmUgdG8gV2F0c29uJ3MgcmVzdWx0cy4NCg0KQWNjb3JkaW5nIHRvIG91ciBtb2RlbHMsIHdlIHdpbGwgbG9vayBhdCB0aGUgUiBzcXVhcmVkIHZhbHVlLCBhcyB0aGlzIGRlc2NyaWJlcyBob3cgd2VsbCB0aGUgZGF0YXNldCBmaXRzIG91ciByZWdyZXNzaW9uIG1vZGVsLg0KRm9yIHNhbGVzIHZzLiBUViwgci1zcXVhcmVkID0gMC42MTE5IH4gNjEuMTklIChXYXRzb24gPSA1OSUpDQpGb3Igc2FsZXMgdnMuIHJhZGlvLCByLXNxdWFyZWQgPSAwLjMzMiB+IDMzLjIlIChXYXRvbiA9IDMyJSkNCkZvciBzYWxlcyB2cy4gVFYgdnMuIHJhZGlvLCByLXNxdWFyZWQgPSAwLjg5NzIgfiA4OS43MiUgKFdhdHNvbiA9IDk0JSkNCg0Kd2hpbGUgdGhlcmUgbWF5IGJlIHNvbWUgdmFyaWFuY2UgZHVlIHRvIGRpZmZlcmVudCBtZXRob2RzIG9mIGNhbGN1bGF0aW5nIHByZWRpY3RpdmUgc3RyZW5ndGgsIHJlc3VsdHMgZnJvbSB0aGUgcmVncmVzc2lvbiBhbmFseXNpcyBhbmQgV2F0c29uIHJlc3VsdHMgbWF0Y2ggd2VsbCBlbm91Z2ggdG8gYmUgY29uc2lkZXJlZCBhcyBhIHZhbGlkIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZXNlIHZhcmlhYmxlcy4gDQo=