Equipo:

A00834241 | Regina Rodríguez Chávez A00833617 | Yessica Acosta Blancheth A01275763 | Eli Gabriel Hernández Medina A00833172 | Genaro Rodríguez Alcántara

The first step is load the libraries

library(foreign)
library(dplyr)        # data manipulation 
library(forcats)      # to work with categorical variables
library(ggplot2)      # data visualization 
library(readr)        # read specific csv files
library(janitor)      # data exploration and cleaning 
library(Hmisc)        # several useful functions for data analysis 
library(psych)        # functions for multivariate analysis 
library(naniar)       # summaries and visualization of missing values NA's
library(dlookr)       # summaries and visualization of missing values NA's
library(corrplot)     # correlation plots
library(jtools)       # presentation of regression analysis 
library(lmtest)       # diagnostic checks - linear regression analysis 
library(car)          # diagnostic checks - linear regression analysis
library(olsrr)        # diagnostic checks - linear regression analysis 
library(naniar)       # identifying missing values
#library(funModeling)  # create frequency tables
library(stargazer)    # create publication quality tables
library(effects)      # displays for linear and other regression models
library(tidyverse)    # collection of R packages designed for data scienc
library(caret)        # Classification and Regression Training 
library(glmnet)  
library(ggplot2)
library(car)
library(lmtest)

It is necessary to load the database to begin the analysis.

#file.choose()
dataset <- read.csv("/Users/gabrielmedina/Downloads/Real_estate_data (1).csv")

Exploratory Data Analysis

It is important to start analyzing the structure of the database, as well as the type of data held in each variable, in order to fully understand the data we are working with.

#dataset
str(dataset)
## 'data.frame':    506 obs. of  15 variables:
##  $ medv   : num  24 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 ...
##  $ cmedv  : num  24 21.6 34.7 33.4 36.2 28.7 22.9 22.1 16.5 18.9 ...
##  $ crim   : num  0.00632 0.02731 0.02729 0.03237 0.06905 ...
##  $ zn     : num  18 0 0 0 0 0 12.5 12.5 12.5 12.5 ...
##  $ indus  : num  2.31 7.07 7.07 2.18 2.18 2.18 7.87 7.87 7.87 7.87 ...
##  $ chas   : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ nox    : num  0.538 0.469 0.469 0.458 0.458 0.458 0.524 0.524 0.524 0.524 ...
##  $ rm     : num  6.58 6.42 7.18 7 7.15 ...
##  $ age    : num  65.2 78.9 61.1 45.8 54.2 58.7 66.6 96.1 100 85.9 ...
##  $ dis    : num  4.09 4.97 4.97 6.06 6.06 ...
##  $ rad    : int  1 2 2 3 3 3 5 5 5 5 ...
##  $ tax    : int  296 242 242 222 222 222 311 311 311 311 ...
##  $ ptratio: num  15.3 17.8 17.8 18.7 18.7 18.7 15.2 15.2 15.2 15.2 ...
##  $ b      : num  397 397 393 395 397 ...
##  $ lstat  : num  4.98 9.14 4.03 2.94 5.33 ...

Analyzing the structure of the database, we can realize that the chas variable is a binary variable of factor type, which is in an integer type, therefore it is necessary to transform the data.

dataset$chas <- as.factor(dataset$chas)
sum(is.na(dataset)) 
## [1] 0

Since no null data were found, it is important to have an idea of the main values of each variable through a descriptive statistical analysis.

summary(dataset)
##       medv           cmedv            crim                zn        
##  Min.   : 5.00   Min.   : 5.00   Min.   : 0.00632   Min.   :  0.00  
##  1st Qu.:17.02   1st Qu.:17.02   1st Qu.: 0.08205   1st Qu.:  0.00  
##  Median :21.20   Median :21.20   Median : 0.25651   Median :  0.00  
##  Mean   :22.53   Mean   :22.53   Mean   : 3.61352   Mean   : 11.36  
##  3rd Qu.:25.00   3rd Qu.:25.00   3rd Qu.: 3.67708   3rd Qu.: 12.50  
##  Max.   :50.00   Max.   :50.00   Max.   :88.97620   Max.   :100.00  
##      indus       chas         nox               rm             age        
##  Min.   : 0.46   0:471   Min.   :0.3850   Min.   :3.561   Min.   :  2.90  
##  1st Qu.: 5.19   1: 35   1st Qu.:0.4490   1st Qu.:5.886   1st Qu.: 45.02  
##  Median : 9.69           Median :0.5380   Median :6.208   Median : 77.50  
##  Mean   :11.14           Mean   :0.5547   Mean   :6.285   Mean   : 68.57  
##  3rd Qu.:18.10           3rd Qu.:0.6240   3rd Qu.:6.623   3rd Qu.: 94.08  
##  Max.   :27.74           Max.   :0.8710   Max.   :8.780   Max.   :100.00  
##       dis              rad              tax           ptratio     
##  Min.   : 1.130   Min.   : 1.000   Min.   :187.0   Min.   :12.60  
##  1st Qu.: 2.100   1st Qu.: 4.000   1st Qu.:279.0   1st Qu.:17.40  
##  Median : 3.207   Median : 5.000   Median :330.0   Median :19.05  
##  Mean   : 3.795   Mean   : 9.549   Mean   :408.2   Mean   :18.46  
##  3rd Qu.: 5.188   3rd Qu.:24.000   3rd Qu.:666.0   3rd Qu.:20.20  
##  Max.   :12.127   Max.   :24.000   Max.   :711.0   Max.   :22.00  
##        b              lstat      
##  Min.   :  0.32   Min.   : 1.73  
##  1st Qu.:375.38   1st Qu.: 6.95  
##  Median :391.44   Median :11.36  
##  Mean   :356.67   Mean   :12.65  
##  3rd Qu.:396.23   3rd Qu.:16.95  
##  Max.   :396.90   Max.   :37.97
statistics_dt = summary(dataset)


mean_value <- statistics_dt[2, ]
median_value <- statistics_dt[3, ]
standard_deviation <- statistics_dt[4, ]
minimum_value <- statistics_dt[5, ]
maximum_value <- statistics_dt[6, ]

# Print the descriptive statistics
cat("Mean:", mean_value, "\n")
## Mean: 1st Qu.:17.02   1st Qu.:17.02   1st Qu.: 0.08205   1st Qu.:  0.00   1st Qu.: 5.19   1: 35   1st Qu.:0.4490   1st Qu.:5.886   1st Qu.: 45.02   1st Qu.: 2.100   1st Qu.: 4.000   1st Qu.:279.0   1st Qu.:17.40   1st Qu.:375.38   1st Qu.: 6.95
cat("Median:", median_value, "\n")
## Median: Median :21.20   Median :21.20   Median : 0.25651   Median :  0.00   Median : 9.69   NA Median :0.5380   Median :6.208   Median : 77.50   Median : 3.207   Median : 5.000   Median :330.0   Median :19.05   Median :391.44   Median :11.36
cat("Standard Deviation:", standard_deviation, "\n")
## Standard Deviation: Mean   :22.53   Mean   :22.53   Mean   : 3.61352   Mean   : 11.36   Mean   :11.14   NA Mean   :0.5547   Mean   :6.285   Mean   : 68.57   Mean   : 3.795   Mean   : 9.549   Mean   :408.2   Mean   :18.46   Mean   :356.67   Mean   :12.65
cat("Minimum:", minimum_value, "\n")
## Minimum: 3rd Qu.:25.00   3rd Qu.:25.00   3rd Qu.: 3.67708   3rd Qu.: 12.50   3rd Qu.:18.10   NA 3rd Qu.:0.6240   3rd Qu.:6.623   3rd Qu.: 94.08   3rd Qu.: 5.188   3rd Qu.:24.000   3rd Qu.:666.0   3rd Qu.:20.20   3rd Qu.:396.23   3rd Qu.:16.95
cat("Maximum:", maximum_value, "\n")
## Maximum: Max.   :50.00   Max.   :50.00   Max.   :88.97620   Max.   :100.00   Max.   :27.74   NA Max.   :0.8710   Max.   :8.780   Max.   :100.00   Max.   :12.127   Max.   :24.000   Max.   :711.0   Max.   :22.00   Max.   :396.90   Max.   :37.97

The results of the descriptive statistics reveal valuable information about the variables in my data set. Regarding the target variable “medv” (average value of homes), it is observed that its values range between 5.00 and 50.00, with a median of 21.20 and a slightly higher mean of 22.53. This suggests a relatively wide dispersion of house prices. When examining other variables, such as “crim” (crime rate) and “nox” (concentration of nitrogen oxides), wide variations in their values are found, indicating significant differences in levels of crime and air quality in the studied areas. Additionally, the variable “chas” is mostly categorical, with most records having a value of 0.

On the other hand, statistics highlight key characteristics of the predictor variables. For example, “rm” (average number of rooms per dwelling) has values that vary between 3,561 and 8,780, with a median of 6,208, suggesting variability in the size of dwellings. The variable “tax” shows wide variation, with values ranging between 187.0 and 711.0. Furthermore, “lstat” (percentage of population of lower status) presents values that vary from 1.73 to 37.97, indicating the diversity in the socioeconomic conditions of the studied areas. These summary statistics provide an overview of the distribution and variability of the variables, which is essential for better understanding the data set and planning subsequent analyses.

Since no abnormality was found in the data, a graphical analysis is carried out.

Data Visualization

- Build at least 2 pair-wised graphs between the dependent variable and independent variables
ggplot(data = dataset, aes(x = crim, y = medv)) +
  geom_point(color = "blue", alpha = 0.6) +
  labs(x = "Crime Rate (crim)", y = "Median Value (medv)") +
  ggtitle("Scatter Plot: Median Value vs. Crime Rate") +
  theme_minimal()

ggplot(data = dataset, aes(x = zn, y = medv)) +
  geom_point(color = "red", alpha = 0.6) +
  labs(x = "Proportion of Residential Land Zoned (zn)", y = "Median Value (medv)") +
  ggtitle("Scatter Plot: Median Value vs. Proportion of Residential Land Zoned") +
  theme_minimal()

ggplot(data = dataset, aes(x = indus, y = medv)) +
  geom_point(color = "green", alpha = 0.6) +
  labs(x = "Industrial Zone Proportion (indus)", y = "Median Value (medv)") +
  ggtitle("Scatter Plot: Median Value vs. Industrial Zone Proportion") +
  theme_minimal()

ggplot(data = dataset, aes(x = nox, y = medv)) +
  geom_point(color = "blue", alpha = 0.6) +
  labs(x = "Nitrogen Oxides Concentration (nox)", y = "Median Value (medv)") +
  ggtitle("Scatter Plot: Median Value vs. Nitrogen Oxides Concentration") +
  theme_minimal()

ggplot(data = dataset, aes(x = rm, y = medv)) +
  geom_point(color = "red", alpha = 0.6) +
  labs(x = "Average Number of Rooms (rm)", y = "Median Value (medv)") +
  ggtitle("Scatter Plot: Median Value vs. Average Number of Rooms") +
  theme_minimal()

ggplot(data = dataset, aes(x = age, y = medv)) +
  geom_line(color = "green", alpha = 0.6) +
  labs(x = "Proportion of Owner-Occupied Units Built Before 1940 (age)", y = "Median Value (medv)") +
  ggtitle("Scatter Plot: Median Value vs. Proportion of Owner-Occupied Units Built Before 1940") +
  theme_minimal()

ggplot(data = dataset, aes(x = dis, y = medv)) +
  geom_line(color = "purple", alpha = 0.6) +
  labs(x = "Weighted Distances to Employment Centers (dis)", y = "Median Value (medv)") +
  ggtitle("Scatter Plot: Median Value vs. Weighted Distances to Employment Centers") +
  theme_minimal()

ggplot(data = dataset, aes(x = factor(rad), y = medv)) +
  geom_boxplot(fill = "skyblue") +
  labs(x = "Accessibility to Radial Highways (rad)", y = "Median Value (medv)") +
  ggtitle("Boxplot: Median Value vs. Accessibility to Radial Highways") +
  theme_minimal()

ggplot(data = dataset, aes(x = factor(tax), y = medv)) +
  geom_boxplot(fill = "lightgreen") +
  labs(x = "Property Tax Rate (tax)", y = "Median Value (medv)") +
  ggtitle("Boxplot: Median Value vs. Property Tax Rate") +
  theme_minimal()

ggplot(data = dataset, aes(x = ptratio, y = medv)) +
  geom_point(color = "blue", fill = "lightblue") +
  labs(x = "Pupil-Teacher Ratio (ptratio)", y = "Median Value (medv)") +
  ggtitle("Density Plot: Median Value vs. Pupil-Teacher Ratio") +
  theme_minimal()

ggplot(data = dataset, aes(x = b, y = medv)) +
  geom_point(color = "purple", alpha = 0.6) +
  labs(x = "Proportion of Residents of African American Descent (b)", y = "Median Value (medv)") +
  ggtitle("Scatter Plot: Median Value vs. Proportion of Residents of African American Descent (b)") +
  theme_minimal()

ggplot(data = dataset, aes(x = lstat, y = medv)) +
  geom_point(color = "orange", alpha = 0.6) +
  labs(x = "Percentage of Lower Status Population (lstat)", y = "Median Value (medv)") +
  ggtitle("Scatter Plot: Median Value vs. Percentage of Lower Status Population (lstat)") +
  theme_minimal()

The previous graphs give us an idea of the correlation relationships between each independent variable and the dependent variable. This does not mean that they have a direct causal relationship, but they are a sign that they have the potential to be statistically significant, so some variables would be interesting to include in linear regression analyses, for example, zn,nox, rm or ISTAT.

- Display a histogram of dependent variable
hist(dataset$medv)

hist(dataset$crim)

hist(dataset$zn)

hist(dataset$indus)

hist(dataset$nox)

hist(dataset$rm)

hist(dataset$dis)

hist(dataset$rad)

hist(dataset$tax)

hist(dataset$ptratio)

hist(dataset$b)

hist(dataset$lstat)

Thanks to the histograms, we can see the distribution of the data for each variable, where we see that there are several such as: crim, zn, indus, chas, nox, dix, rad, tax, ptratio, b and lstat that do not follow a normal distribution, therefore it will be interesting to apply quadratic or logarithmic transformations to these variables in our subsequent linear regression analyses.

- Display a correlation plot

To better understand the correlation relationships between the variables, a diagram and a correlation matrix will be made. It is very important to analyze this to avoid multiculinality problems.

dataset_excl_chas <- dataset[, !colnames(dataset) %in% c("chas")]

cor_matrix <- cor(dataset_excl_chas)
corrplot(cor_matrix, type = "upper", order = "hclust", addCoef.col = "black")

cor_matrix
##               medv      cmedv       crim         zn      indus        nox
## medv     1.0000000  0.9984759 -0.3883046  0.3604453 -0.4837252 -0.4273208
## cmedv    0.9984759  1.0000000 -0.3895824  0.3603862 -0.4847544 -0.4293002
## crim    -0.3883046 -0.3895824  1.0000000 -0.2004692  0.4065834  0.4209717
## zn       0.3604453  0.3603862 -0.2004692  1.0000000 -0.5338282 -0.5166037
## indus   -0.4837252 -0.4847544  0.4065834 -0.5338282  1.0000000  0.7636514
## nox     -0.4273208 -0.4293002  0.4209717 -0.5166037  0.7636514  1.0000000
## rm       0.6953599  0.6963038 -0.2192467  0.3119906 -0.3916759 -0.3021882
## age     -0.3769546 -0.3779989  0.3527343 -0.5695373  0.6447785  0.7314701
## dis      0.2499287  0.2493148 -0.3796701  0.6644082 -0.7080270 -0.7692301
## rad     -0.3816262 -0.3847656  0.6255051 -0.3119478  0.5951293  0.6114406
## tax     -0.4685359 -0.4719788  0.5827643 -0.3145633  0.7207602  0.6680232
## ptratio -0.5077867 -0.5056546  0.2899456 -0.3916785  0.3832476  0.1889327
## b        0.3334608  0.3348608 -0.3850639  0.1755203 -0.3569765 -0.3800506
## lstat   -0.7376627 -0.7408360  0.4556215 -0.4129946  0.6037997  0.5908789
##                 rm        age        dis        rad        tax    ptratio
## medv     0.6953599 -0.3769546  0.2499287 -0.3816262 -0.4685359 -0.5077867
## cmedv    0.6963038 -0.3779989  0.2493148 -0.3847656 -0.4719788 -0.5056546
## crim    -0.2192467  0.3527343 -0.3796701  0.6255051  0.5827643  0.2899456
## zn       0.3119906 -0.5695373  0.6644082 -0.3119478 -0.3145633 -0.3916785
## indus   -0.3916759  0.6447785 -0.7080270  0.5951293  0.7207602  0.3832476
## nox     -0.3021882  0.7314701 -0.7692301  0.6114406  0.6680232  0.1889327
## rm       1.0000000 -0.2402649  0.2052462 -0.2098467 -0.2920478 -0.3555015
## age     -0.2402649  1.0000000 -0.7478805  0.4560225  0.5064556  0.2615150
## dis      0.2052462 -0.7478805  1.0000000 -0.4945879 -0.5344316 -0.2324705
## rad     -0.2098467  0.4560225 -0.4945879  1.0000000  0.9102282  0.4647412
## tax     -0.2920478  0.5064556 -0.5344316  0.9102282  1.0000000  0.4608530
## ptratio -0.3555015  0.2615150 -0.2324705  0.4647412  0.4608530  1.0000000
## b        0.1280686 -0.2735340  0.2915117 -0.4444128 -0.4418080 -0.1773833
## lstat   -0.6138083  0.6023385 -0.4969958  0.4886763  0.5439934  0.3740443
##                  b      lstat
## medv     0.3334608 -0.7376627
## cmedv    0.3348608 -0.7408360
## crim    -0.3850639  0.4556215
## zn       0.1755203 -0.4129946
## indus   -0.3569765  0.6037997
## nox     -0.3800506  0.5908789
## rm       0.1280686 -0.6138083
## age     -0.2735340  0.6023385
## dis      0.2915117 -0.4969958
## rad     -0.4444128  0.4886763
## tax     -0.4418080  0.5439934
## ptratio -0.1773833  0.3740443
## b        1.0000000 -0.3660869
## lstat   -0.3660869  1.0000000

The correlation analysis between the independent variables and the dependent variable “medv” shows several interesting results. A strong positive correlation is observed between “medv” and “cmedv,” indicating that both variables are highly related. Furthermore, “rm” (number of rooms) also presents a significant positive correlation with “medv,” suggesting that as the number of rooms increases, the median home value tends to increase.

On the other hand, there is a notable negative correlation between “medv” and “lstat” (percentage of population with low socioeconomic status), indicating that as the percentage of population with low socioeconomic status decreases, the median value of the housing tends to increase. It is important to mention that multicollinearity is also observed between some independent variables, such as “nox” and “indus,” which suggests that these variables are correlated with each other.

Hypotheses Statement

      • Hypothesis on the number of rooms (rm): It is believed that a greater number of rooms in homes tends to increase the median property value (medv). This belief is based on the logic that more spacious homes tend to have a higher value in the real estate market due to their ability to meet the needs of larger families or provide additional comfort.
      • Air quality hypothesis (nox): It is argued that an increase in the concentration of nitrogen oxide in the air (nox) is associated with a decrease in the median home value (medv). This hypothesis is justified in the context of health and well-being, as increased air pollution can make a location less attractive for housing.
      • Crime rate hypothesis (crim): It is argued that an increase in the crime rate in an area (crim) has a negative impact on the median home value (medv). This belief is based on the perception that areas with high crime rates may be less safe and therefore less desirable to live in, which could decrease the demand for housing and, consequently, its values.

Regression Analysis

With the exploratory analysis of the data, the variables that are believed to have the best potential to model the situation will be chosen…

Likewise, for models 2 and 3, transformations will be used through the conclusions found in the histograms and other insights found in the exploratory analysis of the data.

MODEL 1

dmodel1<-lm(medv ~ rm+nox+lstat+crim+tax+indus,data=dataset)
summary(dmodel1)
## 
## Call:
## lm(formula = medv ~ rm + nox + lstat + crim + tax + indus, data = dataset)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -16.782  -3.553  -1.137   1.765  30.464 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -2.481981   3.299447  -0.752  0.45226    
## rm           5.213899   0.444913  11.719  < 2e-16 ***
## nox          3.850583   3.474274   1.108  0.26826    
## lstat       -0.560857   0.053869 -10.412  < 2e-16 ***
## crim        -0.059567   0.035764  -1.666  0.09643 .  
## tax         -0.006609   0.002392  -2.763  0.00593 ** 
## indus        0.010882   0.063367   0.172  0.86372    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5.459 on 499 degrees of freedom
## Multiple R-squared:  0.6519, Adjusted R-squared:  0.6477 
## F-statistic: 155.8 on 6 and 499 DF,  p-value: < 2.2e-16

The model has a moderate ability to explain variations in house prices, with an adjusted R-squared of approximately 0.648.

Among the independent variables, “rm” (average number of rooms per household) and “lstat” (percentage of population with low status) are statistically significant. A one-unit increase in the average number of rooms is associated with an increase of about 5,214 units in the housing price, while a one-unit increase in the percentage of the population with low status is associated with a decrease of about 0.561 units in the price of housing.

The variables “tax” (property tax), “nox” (concentration of nitrogen oxides), “crim” (crime rate) and “indus” (proportion of acres of non-retail businesses per city) are not statistically significant in this model.

The model as a whole has a statistically significant F value, indicating that at least one of the independent variables is relevant in predicting house prices.

The intercept is not statistically significant in this context.

In summary, the model suggests that the average number of rooms and the percentage of the population with low status are important factors in predicting housing prices, while other variables do not have a significant impact on the model. The model as a whole is capable of explaining a considerable part of the variability in house prices.

Although the model shows a relatively good fit, it is necessary to perform diagnostic tests to detect problems such as multiculinality, heterocerasticity or normality of residuals.

Diagnostic tests MODEL 1

# Multicollinearity

vif(dmodel1)
##       rm      nox    lstat     crim      tax    indus 
## 1.656208 2.746972 2.507990 1.603871 2.753383 3.202960

Since no value exceeds the threshold of 10, multiculionality is not observed, that is, there is no correlation between the independent variables.

# Heteroscedasticity

bptest(dmodel1)
## 
##  studentized Breusch-Pagan test
## 
## data:  dmodel1
## BP = 33.193, df = 6, p-value = 9.628e-06

The Breusch-Pagan test shows an extremely low p value (9.628e-06), less than P=0.05, which indicates that we must reject the null hypothesis of homoscedasticity in model dmodel1, concluding that there is evidence of heteroskedasticity in the model.

# Normality of Residuals
qqnorm(dmodel1$residuals)
qqline(dmodel1$residuals)

shapiro.test(dmodel1$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  dmodel1$residuals
## W = 0.87497, p-value < 2.2e-16

The Shapiro-Wilk normality test yields a p value very close to zero (< 2.2e-16), which indicates that we must reject the null hypothesis that the residuals of model dmodel1 follow a normal distribution, concluding that the residuals do not They are normally distributed.

MODEL 2

dmodel2<-lm(log(medv) ~ rm+nox+lstat+crim+tax+indus,data=dataset)
summary(dmodel2)
## 
## Call:
## lm(formula = log(medv) ~ rm + nox + lstat + crim + tax + indus, 
##     data = dataset)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.74079 -0.13175 -0.01677  0.10572  0.93981 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  2.626e+00  1.305e-01  20.118  < 2e-16 ***
## rm           1.432e-01  1.760e-02   8.136 3.26e-15 ***
## nox          5.965e-02  1.374e-01   0.434 0.664477    
## lstat       -3.031e-02  2.131e-03 -14.223  < 2e-16 ***
## crim        -8.308e-03  1.415e-03  -5.872 7.87e-09 ***
## tax         -3.153e-04  9.461e-05  -3.332 0.000926 ***
## indus        1.576e-03  2.507e-03   0.629 0.529846    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.216 on 499 degrees of freedom
## Multiple R-squared:  0.7242, Adjusted R-squared:  0.7209 
## F-statistic: 218.4 on 6 and 499 DF,  p-value: < 2.2e-16

The model achieves a moderate ability to explain variations in the logarithm of house prices, with an adjusted R-squared of approximately 0.721.

Of the independent variables, “rm” (average number of rooms per home) and “lstat” (percentage of population with low status) are statistically significant. A one-unit increase in the average number of bedrooms is associated with an increase in the log house price by approximately 0.315 units, while a one-unit increase in the percentage of the population with low status is associated with a decrease in the log of the house price by approximately 0.047 units.

The variables “nox” (concentration of nitrogen oxides), “crim” (crime rate), “tax” (property tax), and “indus” (proportion of non-retail business acres per city) are not statistically significant in this model.

The model as a whole has a statistically significant F value, indicating that at least one of the independent variables is relevant in predicting the logarithm of house prices.

The intercept is not statistically significant in this context.

In summary, the second model suggests that the average number of rooms and the percentage of population with low status are important factors in predicting the logarithm of house prices, while other variables do not have a significant impact on the model. The model as a whole is able to explain a considerable part of the variability in the logarithm of house prices.

Diagnostic tests MODEL 2

# Multicollinearity

vif(dmodel2)
##       rm      nox    lstat     crim      tax    indus 
## 1.656208 2.746972 2.507990 1.603871 2.753383 3.202960

Since no value exceeds the threshold of 10, multiculionality is not observed, that is, there is no correlation between the independent variables.

# Heteroscedasticity

bptest(dmodel2)
## 
##  studentized Breusch-Pagan test
## 
## data:  dmodel2
## BP = 48.152, df = 6, p-value = 1.102e-08

The studentized Breusch-Pagan test yields an extremely low p-value (1.518e-07), which leads us to strongly reject the null hypothesis of homoscedasticity in the dmodel2 model. With such a low p value, we can strongly conclude that heteroskedasticity exists in the model residuals. The significance level is much lower than 0.05, which reinforces this conclusion.

# Normality of Residuals
qqnorm(dmodel2$residuals)
qqline(dmodel2$residuals)

shapiro.test(dmodel2$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  dmodel2$residuals
## W = 0.94569, p-value = 1.164e-12

The Shapiro-Wilk normality test shows an extremely low p-value (1.164e-12), less tah p=0.05. Indicating that the residuals from the dmodel2 model do not follow a normal distribution. Therefore, we can strongly reject the null hypothesis that the residuals are normally distributed. This result suggests that the model does not meet the assumption of normality of errors.

MODEL 3

dmodel3<-lm(log(medv) ~ +I(cmedv^2)+nox+rm+nox+lstat+crim,data=dataset)
summary(dmodel3) 
## 
## Call:
## lm(formula = log(medv) ~ +I(cmedv^2) + nox + rm + nox + lstat + 
##     crim, data = dataset)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.66621 -0.06049  0.00662  0.07079  0.49828 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  3.332e+00  8.588e-02  38.796  < 2e-16 ***
## I(cmedv^2)   4.820e-04  1.724e-05  27.954  < 2e-16 ***
## nox         -1.851e-01  6.669e-02  -2.776  0.00571 ** 
## rm          -3.294e-02  1.267e-02  -2.599  0.00962 ** 
## lstat       -1.880e-02  1.396e-03 -13.459  < 2e-16 ***
## crim        -9.702e-03  8.128e-04 -11.937  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.1363 on 500 degrees of freedom
## Multiple R-squared:  0.8899, Adjusted R-squared:  0.8888 
## F-statistic: 807.9 on 5 and 500 DF,  p-value: < 2.2e-16

The model has a high capacity to explain variations in the logarithm of house prices, with an adjusted R-squared of approximately 0.8898.

Of the independent variables, “I(cmedv^2)” (a quadratic transformation of the average house price), “nox” (concentration of nitrogen oxides), “rm” (average number of rooms per house), “lstat” (percentage of population with low status) and “crim” (crime rate) are statistically significant.

The coefficient of “I(cmedv^2)” is positive, suggesting a positive quadratic relationship between the transformed variable and the logarithm of house prices.

The intercept is statistically significant and has a positive value, indicating a base value in the logarithm of house prices.

Overall, the model as a whole is highly significant, with a statistically significant F value.

The model has a good fit to the data, with a low residual standard error of approximately 0.1363.

Diagnostic tests MODEL 3

# Multicollinearity

vif(dmodel3)
## I(cmedv^2)        nox         rm      lstat       crim 
##   2.206569   1.622443   2.154363   2.701969   1.328018

Since no value exceeds the threshold of 10, multiculionality is not observed, that is, there is no correlation between the independent variables.

# Heteroscedasticity

bptest(dmodel3)
## 
##  studentized Breusch-Pagan test
## 
## data:  dmodel3
## BP = 107.81, df = 5, p-value < 2.2e-16

El test de Breusch-Pagan arroja un valor p muy cercano a cero (p-value < 2.2e-16), lo que indica una fuerte evidencia en contra de la hipótesis nula de homocedasticidad. Por lo tanto, podemos concluir que existe heterocedasticidad en el modelo dmodel3, lo que sugiere que la varianza de los errores no es constante en todas las observaciones y que podría haber problemas de dispersión en el modelo.

# Normality of Residuals
qqnorm(dmodel3$residuals)
qqline(dmodel3$residuals)

shapiro.test(dmodel3$residuals)
## 
##  Shapiro-Wilk normality test
## 
## data:  dmodel3$residuals
## W = 0.93175, p-value = 1.972e-14

The Shapiro-Wilk normality test yields an extremely low p-value (p-value = 1.972e-14), indicating strong evidence against the null hypothesis that the residuals follow a normal distribution. Therefore, we can conclude that the residuals do not follow a normal distribution, suggesting that the assumption of normality of the errors in the model may not be adequately met. It is important to keep this non-normality in mind when interpreting model results and considering possible adjustments or transformations of the data if necessary.

AIC(dmodel1)
## [1] 3162.478
AIC(dmodel2)
## [1] -106.17
AIC(dmodel3)
## [1] -572.6356
Model Selection

The models presented problems of normality and heterocerasticity, which is why it is important to continue making data transformations and apply other regularization methods to achieve a more precise and reliable model for predictions. On the other hand, because most of the variables are statistically significant, have a higher r-squared value, do not present multiculinality and have a lower AIC value, model 3 is chosen as the best option to fit our needs. data. It is also important to mention that heterocerasticity is a problem inherent to the nature of the data, since data from one point in time from various US states are being studied, therefore the variances will differ when studying many groups of data with characteristics different.

Model interpretation

The model has a high capacity to explain variations in the logarithm of house prices, with an adjusted R-squared of approximately 0.8898.

Of the independent variables, “I(cmedv^2)” (a quadratic transformation of the average house price), “nox” (concentration of nitrogen oxides), “rm” (average number of rooms per house), “lstat” (percentage of population with low status) and “crim” (crime rate) are statistically significant.

The coefficient of “I(cmedv^2)” is positive, suggesting a positive quadratic relationship between the transformed variable and the logarithm of house prices.

The intercept is statistically significant and has a positive value, indicating a base value in the logarithm of house prices.

Overall, the model as a whole is highly significant, with a statistically significant F value.

The model has a good fit to the data, with a low residual standard error of approximately 0.1363.

  • Coefficient interpretations:

      • Intecept (3.332e+00): If all predictor variables are zero, the logarithm of the average home value is estimated at 3.332.
      • I(cmedv^2) (4.820e-04): For every one-unit increase in the square of cmedv, the logarithm of medv increases by approximately 0.000482. It is highly significant with a p value < 2e-16.
      • nox (-1.851e-01): For every one unit increase in nox, the logarithm of medv decreases by approximately 0.1851. It is significant with a p value of 0.00571.
      • rm (-3.294e-02): For every one-room increase in rm, the logarithm of medv decreases by approximately 0.03294. It is significant with a p value of 0.00962.
      • lstat (-1.880e-02): For every one-unit increase in lstat, the logarithm of medv decreases by approximately 0.0188. It is highly significant with a p value < 2e-16.
      • crim (-9.702e-03): For every one unit increase in the crime rate, the log of medv decreases by approximately 0.009702. It is highly significant with a p value < 2e-16.
# LASSO regression via glmnet package can only take numerical observations. Then, the dataset is transformed to model.matrix() format. 
# Independent variables
x<-model.matrix(log(medv) ~ rm+nox+lstat+crim,dataset)[,-1] ### OLS model specification
# x<-model.matrix(Weekly_Sales~.,train.data)[,-1] ### matrix of independent variables X's
y<-dataset$medv ### dependent variable 

# In estimating LASSO regression it is important to define the lambda that minimizes the prediction error rate. 
# Cross-validation ensures that every data / observation from the original dataset (datains) has a chance of appearing in train and test datasets.
# Find the best lambda using cross-validation.
set.seed(123) 
cv.lasso<-cv.glmnet(x,y,alpha=1) # alpha = 1 for LASSO

# Display the best lambda value
cv.lasso$lambda.min                      ### lambda: a numeric value defining the amount of shrinkage. Why min? the higher the value of ?? , the more penalization there is
## [1] 0.1494561
# Fit the final model on the training data
lassomodel<-glmnet(x,y,alpha=1,lambda=cv.lasso$lambda.min)

# Display regression coefficients
coef(lassomodel)
## 5 x 1 sparse Matrix of class "dgCMatrix"
##                      s0
## (Intercept) -1.74433078
## rm           5.06940392
## nox          .         
## lstat       -0.57351659
## crim        -0.09007037
# Make predictions on the test data
x.test<-model.matrix(log(medv) ~ rm+nox+lstat+crim,dataset)[,-1] ### OLS model specification
# x.test<-model.matrix(Weekly_Sales~.,test.data)[,-1]
lassopredictions <- lassomodel %>% predict(x.test) %>% as.vector()


### visualizing lasso regression results 
lbs_fun <- function(fit, offset_x=1, ...) {
  L <- length(fit$lambda)
  x <- log(fit$lambda[L])+ offset_x
  y <- fit$beta[, L]
  labs <- names(y)
  text(x, y, labels=labs, ...)
}

lasso<-glmnet(scale(x),y,alpha=1)

plot(lasso,xvar="lambda",label=T)
lbs_fun(lasso)
abline(v=cv.lasso$lambda.min,col="red",lty=2)
abline(v=cv.lasso$lambda.1se,col="blue",lty=2)

summary(lassomodel)
##           Length Class     Mode   
## a0        1      -none-    numeric
## beta      4      dgCMatrix S4     
## df        1      -none-    numeric
## dim       2      -none-    numeric
## lambda    1      -none-    numeric
## dev.ratio 1      -none-    numeric
## nulldev   1      -none-    numeric
## npasses   1      -none-    numeric
## jerr      1      -none-    numeric
## offset    1      -none-    logical
## call      5      -none-    call   
## nobs      1      -none-    numeric
      • Intercept: The intercept value is approximately -1.744. This represents the estimated value of the dependent variable (medv) when all independent variables are equal to zero.
      • Coefficients of the independent variables: The model has identified three significant variables in predicting the dependent variable (medv). These are “rm” (number of rooms), “lstat” (percentage of low-status population), and “crim” (crime rate). The magnitude of these coefficients indicates their impact on the dependent variable. For example, a one unit increase in “rm” results in an increase of approximately 5.07 units in medv, holding the other variables constant.
      • Variable “nox” (nitrogen oxide): The coefficient for “nox” is marked “.”. This means that the model has considered that this variable does not have a significant impact on the dependent variable after L1 regularization.
      • Model dimension: The model has estimated four non-null coefficients (df) and a constant term, which means that it considers four independent variables as relevant for the prediction of medv.
Serial Autocorrelation

Since we are working with a database that collects information on the value of homes at a specific point in time, they are cross-sectional data and therefore do not have serial autocorrelation.

Conclusions

In summary, thanks to the exploratory analysis of the data, we had a clear idea of the data we had and the transformations necessary to achieve a robust model. Model 3 stands out as a model with a very good fit to the data, thanks to good values of AIC and R squared, and it was also a model that had many variables with statistical significance and that helped us corroborate our hypotheses. However, despite reducing heterocerasticity with data transformations and with the lasso model, it is important to continue applying other transformation techniques to avoid this problem, although as already mentioned, it is important to highlight that heterocerasticity is a natural problem of The data we are working with are cross-sectional data from several US states at a given point in time, so the variances will hardly be homogeneous. Regarding the insights found, the great impact that the crime rate has on homes is highlighted, since this variable was statistically significant, with a high and negative coefficient, so an increase in crime leads to a considerable loss in the value of the property. the homes, which is why it is important to guarantee the security of the neighborhoods and thus be able to increase the value of the homes. On the other hand, air quality, as thought, turned out to have a negative significance, which highlights the tendency of people to live in quiet places, with excellent air and a very good quality of life. However, something interesting was seeing that the number of rooms turned out to have a negative relationship with the value of the homes, something very peculiar and that could be related to the fact that perhaps people value other more important factors more than the number of rooms.

Likewise, the value of homes is a variable that depends on many other independent variables of those studied here, it will be interesting to complement this analysis with the economic projections of the areas in the future, the stores that are around, the distances to the cities, etc.

Regarding the application of linear regression in the context of predictive analytics, this approach appears to be a valuable tool. Linear regression models provide an understanding of how various characteristics affect property values and are therefore essential for making informed real estate decisions. Furthermore, the identification of significant variables, such as air quality (nox) and crime rate (crim), can provide crucial information for the planning and development of future real estate projects. This predictive analytics capability can significantly improve efficiency and effectiveness in property investment and management, supporting the continued importance of linear regression in analysis and decision making in the real estate market.

LS0tCnRpdGxlOiAiQXNzaWdubWVudCAxLiBSZWdyZXNzaW9uIEFuYWx5c2lzIgphdXRob3I6ICJHYWJyaWVsIE1lZGluYSAtIEEwMTI3NTc2MyIKZGF0ZTogIjIwMjMtMDgtMjIiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCkVxdWlwbzoKCkEwMDgzNDI0MSB8IFJlZ2luYSBSb2Ryw61ndWV6IENow6F2ZXoKQTAwODMzNjE3IHwgWWVzc2ljYSBBY29zdGEgQmxhbmNoZXRoCkEwMTI3NTc2MyB8IEVsaSBHYWJyaWVsIEhlcm7DoW5kZXogTWVkaW5hCkEwMDgzMzE3MiB8IEdlbmFybyBSb2Ryw61ndWV6IEFsY8OhbnRhcmEKClRoZSBmaXJzdCBzdGVwIGlzIGxvYWQgdGhlIGxpYnJhcmllcwoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShmb3JlaWduKQpsaWJyYXJ5KGRwbHlyKSAgICAgICAgIyBkYXRhIG1hbmlwdWxhdGlvbiAKbGlicmFyeShmb3JjYXRzKSAgICAgICMgdG8gd29yayB3aXRoIGNhdGVnb3JpY2FsIHZhcmlhYmxlcwpsaWJyYXJ5KGdncGxvdDIpICAgICAgIyBkYXRhIHZpc3VhbGl6YXRpb24gCmxpYnJhcnkocmVhZHIpICAgICAgICAjIHJlYWQgc3BlY2lmaWMgY3N2IGZpbGVzCmxpYnJhcnkoamFuaXRvcikgICAgICAjIGRhdGEgZXhwbG9yYXRpb24gYW5kIGNsZWFuaW5nIApsaWJyYXJ5KEhtaXNjKSAgICAgICAgIyBzZXZlcmFsIHVzZWZ1bCBmdW5jdGlvbnMgZm9yIGRhdGEgYW5hbHlzaXMgCmxpYnJhcnkocHN5Y2gpICAgICAgICAjIGZ1bmN0aW9ucyBmb3IgbXVsdGl2YXJpYXRlIGFuYWx5c2lzIApsaWJyYXJ5KG5hbmlhcikgICAgICAgIyBzdW1tYXJpZXMgYW5kIHZpc3VhbGl6YXRpb24gb2YgbWlzc2luZyB2YWx1ZXMgTkEncwpsaWJyYXJ5KGRsb29rcikgICAgICAgIyBzdW1tYXJpZXMgYW5kIHZpc3VhbGl6YXRpb24gb2YgbWlzc2luZyB2YWx1ZXMgTkEncwpsaWJyYXJ5KGNvcnJwbG90KSAgICAgIyBjb3JyZWxhdGlvbiBwbG90cwpsaWJyYXJ5KGp0b29scykgICAgICAgIyBwcmVzZW50YXRpb24gb2YgcmVncmVzc2lvbiBhbmFseXNpcyAKbGlicmFyeShsbXRlc3QpICAgICAgICMgZGlhZ25vc3RpYyBjaGVja3MgLSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcyAKbGlicmFyeShjYXIpICAgICAgICAgICMgZGlhZ25vc3RpYyBjaGVja3MgLSBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNpcwpsaWJyYXJ5KG9sc3JyKSAgICAgICAgIyBkaWFnbm9zdGljIGNoZWNrcyAtIGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2lzIApsaWJyYXJ5KG5hbmlhcikgICAgICAgIyBpZGVudGlmeWluZyBtaXNzaW5nIHZhbHVlcwojbGlicmFyeShmdW5Nb2RlbGluZykgICMgY3JlYXRlIGZyZXF1ZW5jeSB0YWJsZXMKbGlicmFyeShzdGFyZ2F6ZXIpICAgICMgY3JlYXRlIHB1YmxpY2F0aW9uIHF1YWxpdHkgdGFibGVzCmxpYnJhcnkoZWZmZWN0cykgICAgICAjIGRpc3BsYXlzIGZvciBsaW5lYXIgYW5kIG90aGVyIHJlZ3Jlc3Npb24gbW9kZWxzCmxpYnJhcnkodGlkeXZlcnNlKSAgICAjIGNvbGxlY3Rpb24gb2YgUiBwYWNrYWdlcyBkZXNpZ25lZCBmb3IgZGF0YSBzY2llbmMKbGlicmFyeShjYXJldCkgICAgICAgICMgQ2xhc3NpZmljYXRpb24gYW5kIFJlZ3Jlc3Npb24gVHJhaW5pbmcgCmxpYnJhcnkoZ2xtbmV0KSAgCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShjYXIpCmxpYnJhcnkobG10ZXN0KQoKCmBgYAoKCkl0IGlzIG5lY2Vzc2FyeSB0byBsb2FkIHRoZSBkYXRhYmFzZSB0byBiZWdpbiB0aGUgYW5hbHlzaXMuCgpgYGB7ciBjYXJzfQojZmlsZS5jaG9vc2UoKQpkYXRhc2V0IDwtIHJlYWQuY3N2KCIvVXNlcnMvZ2FicmllbG1lZGluYS9Eb3dubG9hZHMvUmVhbF9lc3RhdGVfZGF0YSAoMSkuY3N2IikKCmBgYAoKIyBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzCgoKSXQgaXMgaW1wb3J0YW50IHRvIHN0YXJ0IGFuYWx5emluZyB0aGUgc3RydWN0dXJlIG9mIHRoZSBkYXRhYmFzZSwgYXMgd2VsbCBhcyB0aGUgdHlwZSBvZiBkYXRhIGhlbGQgaW4gZWFjaCB2YXJpYWJsZSwgaW4gb3JkZXIgdG8gZnVsbHkgdW5kZXJzdGFuZCB0aGUgZGF0YSB3ZSBhcmUgd29ya2luZyB3aXRoLgoKYGBge3J9CiNkYXRhc2V0CgpgYGAKYGBge3J9CnN0cihkYXRhc2V0KQpgYGAKCkFuYWx5emluZyB0aGUgc3RydWN0dXJlIG9mIHRoZSBkYXRhYmFzZSwgd2UgY2FuIHJlYWxpemUgdGhhdCB0aGUgY2hhcyB2YXJpYWJsZSBpcyBhIGJpbmFyeSB2YXJpYWJsZSBvZiBmYWN0b3IgdHlwZSwgd2hpY2ggaXMgaW4gYW4gaW50ZWdlciB0eXBlLCB0aGVyZWZvcmUgaXQgaXMgbmVjZXNzYXJ5IHRvIHRyYW5zZm9ybSB0aGUgZGF0YS4KCmBgYHtyfQpkYXRhc2V0JGNoYXMgPC0gYXMuZmFjdG9yKGRhdGFzZXQkY2hhcykKYGBgCgpgYGB7cn0Kc3VtKGlzLm5hKGRhdGFzZXQpKSAKYGBgCgpTaW5jZSBubyBudWxsIGRhdGEgd2VyZSBmb3VuZCwgaXQgaXMgaW1wb3J0YW50IHRvIGhhdmUgYW4gaWRlYSBvZiB0aGUgbWFpbiB2YWx1ZXMgb2YgZWFjaCB2YXJpYWJsZSB0aHJvdWdoIGEgZGVzY3JpcHRpdmUgc3RhdGlzdGljYWwgYW5hbHlzaXMuCgpgYGB7cn0Kc3VtbWFyeShkYXRhc2V0KQpgYGAKCmBgYHtyfQpzdGF0aXN0aWNzX2R0ID0gc3VtbWFyeShkYXRhc2V0KQoKCm1lYW5fdmFsdWUgPC0gc3RhdGlzdGljc19kdFsyLCBdCm1lZGlhbl92YWx1ZSA8LSBzdGF0aXN0aWNzX2R0WzMsIF0Kc3RhbmRhcmRfZGV2aWF0aW9uIDwtIHN0YXRpc3RpY3NfZHRbNCwgXQptaW5pbXVtX3ZhbHVlIDwtIHN0YXRpc3RpY3NfZHRbNSwgXQptYXhpbXVtX3ZhbHVlIDwtIHN0YXRpc3RpY3NfZHRbNiwgXQoKIyBQcmludCB0aGUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcwpjYXQoIk1lYW46IiwgbWVhbl92YWx1ZSwgIlxuIikKY2F0KCJNZWRpYW46IiwgbWVkaWFuX3ZhbHVlLCAiXG4iKQpjYXQoIlN0YW5kYXJkIERldmlhdGlvbjoiLCBzdGFuZGFyZF9kZXZpYXRpb24sICJcbiIpCmNhdCgiTWluaW11bToiLCBtaW5pbXVtX3ZhbHVlLCAiXG4iKQpjYXQoIk1heGltdW06IiwgbWF4aW11bV92YWx1ZSwgIlxuIikKCmBgYApUaGUgcmVzdWx0cyBvZiB0aGUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyByZXZlYWwgdmFsdWFibGUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHZhcmlhYmxlcyBpbiBteSBkYXRhIHNldC4gUmVnYXJkaW5nIHRoZSB0YXJnZXQgdmFyaWFibGUgIm1lZHYiIChhdmVyYWdlIHZhbHVlIG9mIGhvbWVzKSwgaXQgaXMgb2JzZXJ2ZWQgdGhhdCBpdHMgdmFsdWVzIHJhbmdlIGJldHdlZW4gNS4wMCBhbmQgNTAuMDAsIHdpdGggYSBtZWRpYW4gb2YgMjEuMjAgYW5kIGEgc2xpZ2h0bHkgaGlnaGVyIG1lYW4gb2YgMjIuNTMuIFRoaXMgc3VnZ2VzdHMgYSByZWxhdGl2ZWx5IHdpZGUgZGlzcGVyc2lvbiBvZiBob3VzZSBwcmljZXMuIFdoZW4gZXhhbWluaW5nIG90aGVyIHZhcmlhYmxlcywgc3VjaCBhcyAiY3JpbSIgKGNyaW1lIHJhdGUpIGFuZCAibm94IiAoY29uY2VudHJhdGlvbiBvZiBuaXRyb2dlbiBveGlkZXMpLCB3aWRlIHZhcmlhdGlvbnMgaW4gdGhlaXIgdmFsdWVzIGFyZSBmb3VuZCwgaW5kaWNhdGluZyBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBpbiBsZXZlbHMgb2YgY3JpbWUgYW5kIGFpciBxdWFsaXR5IGluIHRoZSBzdHVkaWVkIGFyZWFzLiBBZGRpdGlvbmFsbHksIHRoZSB2YXJpYWJsZSAiY2hhcyIgaXMgbW9zdGx5IGNhdGVnb3JpY2FsLCB3aXRoIG1vc3QgcmVjb3JkcyBoYXZpbmcgYSB2YWx1ZSBvZiAwLgoKT24gdGhlIG90aGVyIGhhbmQsIHN0YXRpc3RpY3MgaGlnaGxpZ2h0IGtleSBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIHByZWRpY3RvciB2YXJpYWJsZXMuIEZvciBleGFtcGxlLCAicm0iIChhdmVyYWdlIG51bWJlciBvZiByb29tcyBwZXIgZHdlbGxpbmcpIGhhcyB2YWx1ZXMgdGhhdCB2YXJ5IGJldHdlZW4gMyw1NjEgYW5kIDgsNzgwLCB3aXRoIGEgbWVkaWFuIG9mIDYsMjA4LCBzdWdnZXN0aW5nIHZhcmlhYmlsaXR5IGluIHRoZSBzaXplIG9mIGR3ZWxsaW5ncy4gVGhlIHZhcmlhYmxlICJ0YXgiIHNob3dzIHdpZGUgdmFyaWF0aW9uLCB3aXRoIHZhbHVlcyByYW5naW5nIGJldHdlZW4gMTg3LjAgYW5kIDcxMS4wLiBGdXJ0aGVybW9yZSwgImxzdGF0IiAocGVyY2VudGFnZSBvZiBwb3B1bGF0aW9uIG9mIGxvd2VyIHN0YXR1cykgcHJlc2VudHMgdmFsdWVzIHRoYXQgdmFyeSBmcm9tIDEuNzMgdG8gMzcuOTcsIGluZGljYXRpbmcgdGhlIGRpdmVyc2l0eSBpbiB0aGUgc29jaW9lY29ub21pYyBjb25kaXRpb25zIG9mIHRoZSBzdHVkaWVkIGFyZWFzLiBUaGVzZSBzdW1tYXJ5IHN0YXRpc3RpY3MgcHJvdmlkZSBhbiBvdmVydmlldyBvZiB0aGUgZGlzdHJpYnV0aW9uIGFuZCB2YXJpYWJpbGl0eSBvZiB0aGUgdmFyaWFibGVzLCB3aGljaCBpcyBlc3NlbnRpYWwgZm9yIGJldHRlciB1bmRlcnN0YW5kaW5nIHRoZSBkYXRhIHNldCBhbmQgcGxhbm5pbmcgc3Vic2VxdWVudCBhbmFseXNlcy4KClNpbmNlIG5vIGFibm9ybWFsaXR5IHdhcyBmb3VuZCBpbiB0aGUgZGF0YSwgYSBncmFwaGljYWwgYW5hbHlzaXMgaXMgY2FycmllZCBvdXQuCgojICBEYXRhIFZpc3VhbGl6YXRpb24KCiMjIyMjIC0gQnVpbGQgYXQgbGVhc3QgMiBwYWlyLXdpc2VkIGdyYXBocyBiZXR3ZWVuIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIGluZGVwZW5kZW50IHZhcmlhYmxlcwoKYGBge3J9CgpnZ3Bsb3QoZGF0YSA9IGRhdGFzZXQsIGFlcyh4ID0gY3JpbSwgeSA9IG1lZHYpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIiwgYWxwaGEgPSAwLjYpICsKICBsYWJzKHggPSAiQ3JpbWUgUmF0ZSAoY3JpbSkiLCB5ID0gIk1lZGlhbiBWYWx1ZSAobWVkdikiKSArCiAgZ2d0aXRsZSgiU2NhdHRlciBQbG90OiBNZWRpYW4gVmFsdWUgdnMuIENyaW1lIFJhdGUiKSArCiAgdGhlbWVfbWluaW1hbCgpCgoKZ2dwbG90KGRhdGEgPSBkYXRhc2V0LCBhZXMoeCA9IHpuLCB5ID0gbWVkdikpICsKICBnZW9tX3BvaW50KGNvbG9yID0gInJlZCIsIGFscGhhID0gMC42KSArCiAgbGFicyh4ID0gIlByb3BvcnRpb24gb2YgUmVzaWRlbnRpYWwgTGFuZCBab25lZCAoem4pIiwgeSA9ICJNZWRpYW4gVmFsdWUgKG1lZHYpIikgKwogIGdndGl0bGUoIlNjYXR0ZXIgUGxvdDogTWVkaWFuIFZhbHVlIHZzLiBQcm9wb3J0aW9uIG9mIFJlc2lkZW50aWFsIExhbmQgWm9uZWQiKSArCiAgdGhlbWVfbWluaW1hbCgpCgoKZ2dwbG90KGRhdGEgPSBkYXRhc2V0LCBhZXMoeCA9IGluZHVzLCB5ID0gbWVkdikpICsKICBnZW9tX3BvaW50KGNvbG9yID0gImdyZWVuIiwgYWxwaGEgPSAwLjYpICsKICBsYWJzKHggPSAiSW5kdXN0cmlhbCBab25lIFByb3BvcnRpb24gKGluZHVzKSIsIHkgPSAiTWVkaWFuIFZhbHVlIChtZWR2KSIpICsKICBnZ3RpdGxlKCJTY2F0dGVyIFBsb3Q6IE1lZGlhbiBWYWx1ZSB2cy4gSW5kdXN0cmlhbCBab25lIFByb3BvcnRpb24iKSArCiAgdGhlbWVfbWluaW1hbCgpCgoKZ2dwbG90KGRhdGEgPSBkYXRhc2V0LCBhZXMoeCA9IG5veCwgeSA9IG1lZHYpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIiwgYWxwaGEgPSAwLjYpICsKICBsYWJzKHggPSAiTml0cm9nZW4gT3hpZGVzIENvbmNlbnRyYXRpb24gKG5veCkiLCB5ID0gIk1lZGlhbiBWYWx1ZSAobWVkdikiKSArCiAgZ2d0aXRsZSgiU2NhdHRlciBQbG90OiBNZWRpYW4gVmFsdWUgdnMuIE5pdHJvZ2VuIE94aWRlcyBDb25jZW50cmF0aW9uIikgKwogIHRoZW1lX21pbmltYWwoKQoKCmdncGxvdChkYXRhID0gZGF0YXNldCwgYWVzKHggPSBybSwgeSA9IG1lZHYpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJyZWQiLCBhbHBoYSA9IDAuNikgKwogIGxhYnMoeCA9ICJBdmVyYWdlIE51bWJlciBvZiBSb29tcyAocm0pIiwgeSA9ICJNZWRpYW4gVmFsdWUgKG1lZHYpIikgKwogIGdndGl0bGUoIlNjYXR0ZXIgUGxvdDogTWVkaWFuIFZhbHVlIHZzLiBBdmVyYWdlIE51bWJlciBvZiBSb29tcyIpICsKICB0aGVtZV9taW5pbWFsKCkKCgpnZ3Bsb3QoZGF0YSA9IGRhdGFzZXQsIGFlcyh4ID0gYWdlLCB5ID0gbWVkdikpICsKICBnZW9tX2xpbmUoY29sb3IgPSAiZ3JlZW4iLCBhbHBoYSA9IDAuNikgKwogIGxhYnMoeCA9ICJQcm9wb3J0aW9uIG9mIE93bmVyLU9jY3VwaWVkIFVuaXRzIEJ1aWx0IEJlZm9yZSAxOTQwIChhZ2UpIiwgeSA9ICJNZWRpYW4gVmFsdWUgKG1lZHYpIikgKwogIGdndGl0bGUoIlNjYXR0ZXIgUGxvdDogTWVkaWFuIFZhbHVlIHZzLiBQcm9wb3J0aW9uIG9mIE93bmVyLU9jY3VwaWVkIFVuaXRzIEJ1aWx0IEJlZm9yZSAxOTQwIikgKwogIHRoZW1lX21pbmltYWwoKQoKCmdncGxvdChkYXRhID0gZGF0YXNldCwgYWVzKHggPSBkaXMsIHkgPSBtZWR2KSkgKwogIGdlb21fbGluZShjb2xvciA9ICJwdXJwbGUiLCBhbHBoYSA9IDAuNikgKwogIGxhYnMoeCA9ICJXZWlnaHRlZCBEaXN0YW5jZXMgdG8gRW1wbG95bWVudCBDZW50ZXJzIChkaXMpIiwgeSA9ICJNZWRpYW4gVmFsdWUgKG1lZHYpIikgKwogIGdndGl0bGUoIlNjYXR0ZXIgUGxvdDogTWVkaWFuIFZhbHVlIHZzLiBXZWlnaHRlZCBEaXN0YW5jZXMgdG8gRW1wbG95bWVudCBDZW50ZXJzIikgKwogIHRoZW1lX21pbmltYWwoKQoKCmdncGxvdChkYXRhID0gZGF0YXNldCwgYWVzKHggPSBmYWN0b3IocmFkKSwgeSA9IG1lZHYpKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAic2t5Ymx1ZSIpICsKICBsYWJzKHggPSAiQWNjZXNzaWJpbGl0eSB0byBSYWRpYWwgSGlnaHdheXMgKHJhZCkiLCB5ID0gIk1lZGlhbiBWYWx1ZSAobWVkdikiKSArCiAgZ2d0aXRsZSgiQm94cGxvdDogTWVkaWFuIFZhbHVlIHZzLiBBY2Nlc3NpYmlsaXR5IHRvIFJhZGlhbCBIaWdod2F5cyIpICsKICB0aGVtZV9taW5pbWFsKCkKCgpnZ3Bsb3QoZGF0YSA9IGRhdGFzZXQsIGFlcyh4ID0gZmFjdG9yKHRheCksIHkgPSBtZWR2KSkgKwogIGdlb21fYm94cGxvdChmaWxsID0gImxpZ2h0Z3JlZW4iKSArCiAgbGFicyh4ID0gIlByb3BlcnR5IFRheCBSYXRlICh0YXgpIiwgeSA9ICJNZWRpYW4gVmFsdWUgKG1lZHYpIikgKwogIGdndGl0bGUoIkJveHBsb3Q6IE1lZGlhbiBWYWx1ZSB2cy4gUHJvcGVydHkgVGF4IFJhdGUiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpnZ3Bsb3QoZGF0YSA9IGRhdGFzZXQsIGFlcyh4ID0gcHRyYXRpbywgeSA9IG1lZHYpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIiwgZmlsbCA9ICJsaWdodGJsdWUiKSArCiAgbGFicyh4ID0gIlB1cGlsLVRlYWNoZXIgUmF0aW8gKHB0cmF0aW8pIiwgeSA9ICJNZWRpYW4gVmFsdWUgKG1lZHYpIikgKwogIGdndGl0bGUoIkRlbnNpdHkgUGxvdDogTWVkaWFuIFZhbHVlIHZzLiBQdXBpbC1UZWFjaGVyIFJhdGlvIikgKwogIHRoZW1lX21pbmltYWwoKQoKZ2dwbG90KGRhdGEgPSBkYXRhc2V0LCBhZXMoeCA9IGIsIHkgPSBtZWR2KSkgKwogIGdlb21fcG9pbnQoY29sb3IgPSAicHVycGxlIiwgYWxwaGEgPSAwLjYpICsKICBsYWJzKHggPSAiUHJvcG9ydGlvbiBvZiBSZXNpZGVudHMgb2YgQWZyaWNhbiBBbWVyaWNhbiBEZXNjZW50IChiKSIsIHkgPSAiTWVkaWFuIFZhbHVlIChtZWR2KSIpICsKICBnZ3RpdGxlKCJTY2F0dGVyIFBsb3Q6IE1lZGlhbiBWYWx1ZSB2cy4gUHJvcG9ydGlvbiBvZiBSZXNpZGVudHMgb2YgQWZyaWNhbiBBbWVyaWNhbiBEZXNjZW50IChiKSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmdncGxvdChkYXRhID0gZGF0YXNldCwgYWVzKHggPSBsc3RhdCwgeSA9IG1lZHYpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJvcmFuZ2UiLCBhbHBoYSA9IDAuNikgKwogIGxhYnMoeCA9ICJQZXJjZW50YWdlIG9mIExvd2VyIFN0YXR1cyBQb3B1bGF0aW9uIChsc3RhdCkiLCB5ID0gIk1lZGlhbiBWYWx1ZSAobWVkdikiKSArCiAgZ2d0aXRsZSgiU2NhdHRlciBQbG90OiBNZWRpYW4gVmFsdWUgdnMuIFBlcmNlbnRhZ2Ugb2YgTG93ZXIgU3RhdHVzIFBvcHVsYXRpb24gKGxzdGF0KSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYApUaGUgcHJldmlvdXMgZ3JhcGhzIGdpdmUgdXMgYW4gaWRlYSBvZiB0aGUgY29ycmVsYXRpb24gcmVsYXRpb25zaGlwcyBiZXR3ZWVuIGVhY2ggaW5kZXBlbmRlbnQgdmFyaWFibGUgYW5kIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUuIFRoaXMgZG9lcyBub3QgbWVhbiB0aGF0IHRoZXkgaGF2ZSBhIGRpcmVjdCBjYXVzYWwgcmVsYXRpb25zaGlwLCBidXQgdGhleSBhcmUgYSBzaWduIHRoYXQgdGhleSBoYXZlIHRoZSBwb3RlbnRpYWwgdG8gYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCwgc28gc29tZSB2YXJpYWJsZXMgd291bGQgYmUgaW50ZXJlc3RpbmcgdG8gaW5jbHVkZSBpbiBsaW5lYXIgcmVncmVzc2lvbiBhbmFseXNlcywgZm9yIGV4YW1wbGUsIHpuLG5veCwgcm0gb3IgSVNUQVQuCgojIyMjIyAtIERpc3BsYXkgYSBoaXN0b2dyYW0gb2YgZGVwZW5kZW50IHZhcmlhYmxlCgpgYGB7cn0KaGlzdChkYXRhc2V0JG1lZHYpCmhpc3QoZGF0YXNldCRjcmltKQpoaXN0KGRhdGFzZXQkem4pCmhpc3QoZGF0YXNldCRpbmR1cykKaGlzdChkYXRhc2V0JG5veCkKaGlzdChkYXRhc2V0JHJtKQpoaXN0KGRhdGFzZXQkZGlzKQpoaXN0KGRhdGFzZXQkcmFkKQpoaXN0KGRhdGFzZXQkdGF4KQpoaXN0KGRhdGFzZXQkcHRyYXRpbykKaGlzdChkYXRhc2V0JGIpCmhpc3QoZGF0YXNldCRsc3RhdCkKYGBgCgpUaGFua3MgdG8gdGhlIGhpc3RvZ3JhbXMsIHdlIGNhbiBzZWUgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZGF0YSBmb3IgZWFjaCB2YXJpYWJsZSwgd2hlcmUgd2Ugc2VlIHRoYXQgdGhlcmUgYXJlIHNldmVyYWwgc3VjaCBhczogY3JpbSwgem4sIGluZHVzLCBjaGFzLCBub3gsIGRpeCwgcmFkLCB0YXgsIHB0cmF0aW8sIGIgYW5kIGxzdGF0IHRoYXQgZG8gbm90IGZvbGxvdyBhIG5vcm1hbCBkaXN0cmlidXRpb24sIHRoZXJlZm9yZSBpdCB3aWxsIGJlIGludGVyZXN0aW5nIHRvIGFwcGx5IHF1YWRyYXRpYyBvciBsb2dhcml0aG1pYyB0cmFuc2Zvcm1hdGlvbnMgdG8gdGhlc2UgdmFyaWFibGVzIGluIG91ciBzdWJzZXF1ZW50IGxpbmVhciByZWdyZXNzaW9uIGFuYWx5c2VzLgoKIyMjIyMgLSBEaXNwbGF5IGEgY29ycmVsYXRpb24gcGxvdCAgCgpUbyBiZXR0ZXIgdW5kZXJzdGFuZCB0aGUgY29ycmVsYXRpb24gcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMsIGEgZGlhZ3JhbSBhbmQgYSBjb3JyZWxhdGlvbiBtYXRyaXggd2lsbCBiZSBtYWRlLiBJdCBpcyB2ZXJ5IGltcG9ydGFudCB0byBhbmFseXplIHRoaXMgdG8gYXZvaWQgbXVsdGljdWxpbmFsaXR5IHByb2JsZW1zLgoKCmBgYHtyfQoKZGF0YXNldF9leGNsX2NoYXMgPC0gZGF0YXNldFssICFjb2xuYW1lcyhkYXRhc2V0KSAlaW4lIGMoImNoYXMiKV0KCmNvcl9tYXRyaXggPC0gY29yKGRhdGFzZXRfZXhjbF9jaGFzKQpjb3JycGxvdChjb3JfbWF0cml4LCB0eXBlID0gInVwcGVyIiwgb3JkZXIgPSAiaGNsdXN0IiwgYWRkQ29lZi5jb2wgPSAiYmxhY2siKQoKCmBgYAoKYGBge3J9CmNvcl9tYXRyaXgKYGBgCgpUaGUgY29ycmVsYXRpb24gYW5hbHlzaXMgYmV0d2VlbiB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGFuZCB0aGUgZGVwZW5kZW50IHZhcmlhYmxlICJtZWR2IiBzaG93cyBzZXZlcmFsIGludGVyZXN0aW5nIHJlc3VsdHMuIEEgc3Ryb25nIHBvc2l0aXZlIGNvcnJlbGF0aW9uIGlzIG9ic2VydmVkIGJldHdlZW4gIm1lZHYiIGFuZCAiY21lZHYsIiBpbmRpY2F0aW5nIHRoYXQgYm90aCB2YXJpYWJsZXMgYXJlIGhpZ2hseSByZWxhdGVkLiBGdXJ0aGVybW9yZSwgInJtIiAobnVtYmVyIG9mIHJvb21zKSBhbHNvIHByZXNlbnRzIGEgc2lnbmlmaWNhbnQgcG9zaXRpdmUgY29ycmVsYXRpb24gd2l0aCAibWVkdiwiIHN1Z2dlc3RpbmcgdGhhdCBhcyB0aGUgbnVtYmVyIG9mIHJvb21zIGluY3JlYXNlcywgdGhlIG1lZGlhbiBob21lIHZhbHVlIHRlbmRzIHRvIGluY3JlYXNlLgoKT24gdGhlIG90aGVyIGhhbmQsIHRoZXJlIGlzIGEgbm90YWJsZSBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBiZXR3ZWVuICJtZWR2IiBhbmQgImxzdGF0IiAocGVyY2VudGFnZSBvZiBwb3B1bGF0aW9uIHdpdGggbG93IHNvY2lvZWNvbm9taWMgc3RhdHVzKSwgaW5kaWNhdGluZyB0aGF0IGFzIHRoZSBwZXJjZW50YWdlIG9mIHBvcHVsYXRpb24gd2l0aCBsb3cgc29jaW9lY29ub21pYyBzdGF0dXMgZGVjcmVhc2VzLCB0aGUgbWVkaWFuIHZhbHVlIG9mIHRoZSBob3VzaW5nIHRlbmRzIHRvIGluY3JlYXNlLiBJdCBpcyBpbXBvcnRhbnQgdG8gbWVudGlvbiB0aGF0IG11bHRpY29sbGluZWFyaXR5IGlzIGFsc28gb2JzZXJ2ZWQgYmV0d2VlbiBzb21lIGluZGVwZW5kZW50IHZhcmlhYmxlcywgc3VjaCBhcyAibm94IiBhbmQgImluZHVzLCIgd2hpY2ggc3VnZ2VzdHMgdGhhdCB0aGVzZSB2YXJpYWJsZXMgYXJlIGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyLgoKCiMgSHlwb3RoZXNlcyBTdGF0ZW1lbnQKCi0gLSAtIEh5cG90aGVzaXMgb24gdGhlIG51bWJlciBvZiByb29tcyAocm0pOiBJdCBpcyBiZWxpZXZlZCB0aGF0IGEgZ3JlYXRlciBudW1iZXIgb2Ygcm9vbXMgaW4gaG9tZXMgdGVuZHMgdG8gaW5jcmVhc2UgdGhlIG1lZGlhbiBwcm9wZXJ0eSB2YWx1ZSAobWVkdikuIFRoaXMgYmVsaWVmIGlzIGJhc2VkIG9uIHRoZSBsb2dpYyB0aGF0IG1vcmUgc3BhY2lvdXMgaG9tZXMgdGVuZCB0byBoYXZlIGEgaGlnaGVyIHZhbHVlIGluIHRoZSByZWFsIGVzdGF0ZSBtYXJrZXQgZHVlIHRvIHRoZWlyIGFiaWxpdHkgdG8gbWVldCB0aGUgbmVlZHMgb2YgbGFyZ2VyIGZhbWlsaWVzIG9yIHByb3ZpZGUgYWRkaXRpb25hbCBjb21mb3J0LgoKLSAtIC0gQWlyIHF1YWxpdHkgaHlwb3RoZXNpcyAobm94KTogSXQgaXMgYXJndWVkIHRoYXQgYW4gaW5jcmVhc2UgaW4gdGhlIGNvbmNlbnRyYXRpb24gb2Ygbml0cm9nZW4gb3hpZGUgaW4gdGhlIGFpciAobm94KSBpcyBhc3NvY2lhdGVkIHdpdGggYSBkZWNyZWFzZSBpbiB0aGUgbWVkaWFuIGhvbWUgdmFsdWUgKG1lZHYpLiBUaGlzIGh5cG90aGVzaXMgaXMganVzdGlmaWVkIGluIHRoZSBjb250ZXh0IG9mIGhlYWx0aCBhbmQgd2VsbC1iZWluZywgYXMgaW5jcmVhc2VkIGFpciBwb2xsdXRpb24gY2FuIG1ha2UgYSBsb2NhdGlvbiBsZXNzIGF0dHJhY3RpdmUgZm9yIGhvdXNpbmcuCgotIC0gLSBDcmltZSByYXRlIGh5cG90aGVzaXMgKGNyaW0pOiBJdCBpcyBhcmd1ZWQgdGhhdCBhbiBpbmNyZWFzZSBpbiB0aGUgY3JpbWUgcmF0ZSBpbiBhbiBhcmVhIChjcmltKSBoYXMgYSBuZWdhdGl2ZSBpbXBhY3Qgb24gdGhlIG1lZGlhbiBob21lIHZhbHVlIChtZWR2KS4gVGhpcyBiZWxpZWYgaXMgYmFzZWQgb24gdGhlIHBlcmNlcHRpb24gdGhhdCBhcmVhcyB3aXRoIGhpZ2ggY3JpbWUgcmF0ZXMgbWF5IGJlIGxlc3Mgc2FmZSBhbmQgdGhlcmVmb3JlIGxlc3MgZGVzaXJhYmxlIHRvIGxpdmUgaW4sIHdoaWNoIGNvdWxkIGRlY3JlYXNlIHRoZSBkZW1hbmQgZm9yIGhvdXNpbmcgYW5kLCBjb25zZXF1ZW50bHksIGl0cyB2YWx1ZXMuCgoKIyBSZWdyZXNzaW9uIEFuYWx5c2lzCgpXaXRoIHRoZSBleHBsb3JhdG9yeSBhbmFseXNpcyBvZiB0aGUgZGF0YSwgdGhlIHZhcmlhYmxlcyB0aGF0IGFyZSBiZWxpZXZlZCB0byBoYXZlIHRoZSBiZXN0IHBvdGVudGlhbCB0byBtb2RlbCB0aGUgc2l0dWF0aW9uIHdpbGwgYmUgY2hvc2VuLi4uCgpMaWtld2lzZSwgZm9yIG1vZGVscyAyIGFuZCAzLCB0cmFuc2Zvcm1hdGlvbnMgd2lsbCBiZSB1c2VkIHRocm91Z2ggdGhlIGNvbmNsdXNpb25zIGZvdW5kIGluIHRoZSBoaXN0b2dyYW1zIGFuZCBvdGhlciBpbnNpZ2h0cyBmb3VuZCBpbiB0aGUgZXhwbG9yYXRvcnkgYW5hbHlzaXMgb2YgdGhlIGRhdGEuCgojIyMjIE1PREVMIDEKCmBgYHtyfQpkbW9kZWwxPC1sbShtZWR2IH4gcm0rbm94K2xzdGF0K2NyaW0rdGF4K2luZHVzLGRhdGE9ZGF0YXNldCkKc3VtbWFyeShkbW9kZWwxKQpgYGAKClRoZSBtb2RlbCBoYXMgYSBtb2RlcmF0ZSBhYmlsaXR5IHRvIGV4cGxhaW4gdmFyaWF0aW9ucyBpbiBob3VzZSBwcmljZXMsIHdpdGggYW4gYWRqdXN0ZWQgUi1zcXVhcmVkIG9mIGFwcHJveGltYXRlbHkgMC42NDguCgpBbW9uZyB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLCAicm0iIChhdmVyYWdlIG51bWJlciBvZiByb29tcyBwZXIgaG91c2Vob2xkKSBhbmQgImxzdGF0IiAocGVyY2VudGFnZSBvZiBwb3B1bGF0aW9uIHdpdGggbG93IHN0YXR1cykgYXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuIEEgb25lLXVuaXQgaW5jcmVhc2UgaW4gdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIHJvb21zIGlzIGFzc29jaWF0ZWQgd2l0aCBhbiBpbmNyZWFzZSBvZiBhYm91dCA1LDIxNCB1bml0cyBpbiB0aGUgaG91c2luZyBwcmljZSwgd2hpbGUgYSBvbmUtdW5pdCBpbmNyZWFzZSBpbiB0aGUgcGVyY2VudGFnZSBvZiB0aGUgcG9wdWxhdGlvbiB3aXRoIGxvdyBzdGF0dXMgaXMgYXNzb2NpYXRlZCB3aXRoIGEgZGVjcmVhc2Ugb2YgYWJvdXQgMC41NjEgdW5pdHMgaW4gdGhlIHByaWNlIG9mIGhvdXNpbmcuCgpUaGUgdmFyaWFibGVzICJ0YXgiIChwcm9wZXJ0eSB0YXgpLCAibm94IiAoY29uY2VudHJhdGlvbiBvZiBuaXRyb2dlbiBveGlkZXMpLCAiY3JpbSIgKGNyaW1lIHJhdGUpIGFuZCAiaW5kdXMiIChwcm9wb3J0aW9uIG9mIGFjcmVzIG9mIG5vbi1yZXRhaWwgYnVzaW5lc3NlcyBwZXIgY2l0eSkgYXJlIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGluIHRoaXMgbW9kZWwuCgpUaGUgbW9kZWwgYXMgYSB3aG9sZSBoYXMgYSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IEYgdmFsdWUsIGluZGljYXRpbmcgdGhhdCBhdCBsZWFzdCBvbmUgb2YgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcyBpcyByZWxldmFudCBpbiBwcmVkaWN0aW5nIGhvdXNlIHByaWNlcy4KClRoZSBpbnRlcmNlcHQgaXMgbm90IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgaW4gdGhpcyBjb250ZXh0LgoKSW4gc3VtbWFyeSwgdGhlIG1vZGVsIHN1Z2dlc3RzIHRoYXQgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIHJvb21zIGFuZCB0aGUgcGVyY2VudGFnZSBvZiB0aGUgcG9wdWxhdGlvbiB3aXRoIGxvdyBzdGF0dXMgYXJlIGltcG9ydGFudCBmYWN0b3JzIGluIHByZWRpY3RpbmcgaG91c2luZyBwcmljZXMsIHdoaWxlIG90aGVyIHZhcmlhYmxlcyBkbyBub3QgaGF2ZSBhIHNpZ25pZmljYW50IGltcGFjdCBvbiB0aGUgbW9kZWwuIFRoZSBtb2RlbCBhcyBhIHdob2xlIGlzIGNhcGFibGUgb2YgZXhwbGFpbmluZyBhIGNvbnNpZGVyYWJsZSBwYXJ0IG9mIHRoZSB2YXJpYWJpbGl0eSBpbiBob3VzZSBwcmljZXMuCgpBbHRob3VnaCB0aGUgbW9kZWwgc2hvd3MgYSByZWxhdGl2ZWx5IGdvb2QgZml0LCBpdCBpcyBuZWNlc3NhcnkgdG8gcGVyZm9ybSBkaWFnbm9zdGljIHRlc3RzIHRvIGRldGVjdCBwcm9ibGVtcyBzdWNoIGFzIG11bHRpY3VsaW5hbGl0eSwgaGV0ZXJvY2VyYXN0aWNpdHkgb3Igbm9ybWFsaXR5IG9mIHJlc2lkdWFscy4KCiMjIyMgRGlhZ25vc3RpYyB0ZXN0cyBNT0RFTCAxCgpgYGB7cn0KCiMgTXVsdGljb2xsaW5lYXJpdHkKCnZpZihkbW9kZWwxKQpgYGAKClNpbmNlIG5vIHZhbHVlIGV4Y2VlZHMgdGhlIHRocmVzaG9sZCBvZiAxMCwgbXVsdGljdWxpb25hbGl0eSBpcyBub3Qgb2JzZXJ2ZWQsIHRoYXQgaXMsIHRoZXJlIGlzIG5vIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcy4KCmBgYHtyfQojIEhldGVyb3NjZWRhc3RpY2l0eQoKYnB0ZXN0KGRtb2RlbDEpCmBgYAoKVGhlIEJyZXVzY2gtUGFnYW4gdGVzdCBzaG93cyBhbiBleHRyZW1lbHkgbG93IHAgdmFsdWUgKDkuNjI4ZS0wNiksIGxlc3MgdGhhbiBQPTAuMDUsIHdoaWNoIGluZGljYXRlcyB0aGF0IHdlIG11c3QgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgb2YgaG9tb3NjZWRhc3RpY2l0eSBpbiBtb2RlbCBkbW9kZWwxLCBjb25jbHVkaW5nIHRoYXQgdGhlcmUgaXMgZXZpZGVuY2Ugb2YgaGV0ZXJvc2tlZGFzdGljaXR5IGluIHRoZSBtb2RlbC4KCmBgYHtyfQojIE5vcm1hbGl0eSBvZiBSZXNpZHVhbHMKcXFub3JtKGRtb2RlbDEkcmVzaWR1YWxzKQpxcWxpbmUoZG1vZGVsMSRyZXNpZHVhbHMpCnNoYXBpcm8udGVzdChkbW9kZWwxJHJlc2lkdWFscykKYGBgCgpUaGUgU2hhcGlyby1XaWxrIG5vcm1hbGl0eSB0ZXN0IHlpZWxkcyBhIHAgdmFsdWUgdmVyeSBjbG9zZSB0byB6ZXJvICg8IDIuMmUtMTYpLCB3aGljaCBpbmRpY2F0ZXMgdGhhdCB3ZSBtdXN0IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIHJlc2lkdWFscyBvZiBtb2RlbCBkbW9kZWwxIGZvbGxvdyBhIG5vcm1hbCBkaXN0cmlidXRpb24sIGNvbmNsdWRpbmcgdGhhdCB0aGUgcmVzaWR1YWxzIGRvIG5vdCBUaGV5IGFyZSBub3JtYWxseSBkaXN0cmlidXRlZC4KCgojIyMjIE1PREVMIDIKCmBgYHtyfQpkbW9kZWwyPC1sbShsb2cobWVkdikgfiBybStub3grbHN0YXQrY3JpbSt0YXgraW5kdXMsZGF0YT1kYXRhc2V0KQpzdW1tYXJ5KGRtb2RlbDIpCgpgYGAKClRoZSBtb2RlbCBhY2hpZXZlcyBhIG1vZGVyYXRlIGFiaWxpdHkgdG8gZXhwbGFpbiB2YXJpYXRpb25zIGluIHRoZSBsb2dhcml0aG0gb2YgaG91c2UgcHJpY2VzLCB3aXRoIGFuIGFkanVzdGVkIFItc3F1YXJlZCBvZiBhcHByb3hpbWF0ZWx5IDAuNzIxLgoKT2YgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcywgInJtIiAoYXZlcmFnZSBudW1iZXIgb2Ygcm9vbXMgcGVyIGhvbWUpIGFuZCAibHN0YXQiIChwZXJjZW50YWdlIG9mIHBvcHVsYXRpb24gd2l0aCBsb3cgc3RhdHVzKSBhcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4gQSBvbmUtdW5pdCBpbmNyZWFzZSBpbiB0aGUgYXZlcmFnZSBudW1iZXIgb2YgYmVkcm9vbXMgaXMgYXNzb2NpYXRlZCB3aXRoIGFuIGluY3JlYXNlIGluIHRoZSBsb2cgaG91c2UgcHJpY2UgYnkgYXBwcm94aW1hdGVseSAwLjMxNSB1bml0cywgd2hpbGUgYSBvbmUtdW5pdCBpbmNyZWFzZSBpbiB0aGUgcGVyY2VudGFnZSBvZiB0aGUgcG9wdWxhdGlvbiB3aXRoIGxvdyBzdGF0dXMgaXMgYXNzb2NpYXRlZCB3aXRoIGEgZGVjcmVhc2UgaW4gdGhlIGxvZyBvZiB0aGUgaG91c2UgcHJpY2UgYnkgYXBwcm94aW1hdGVseSAwLjA0NyB1bml0cy4KClRoZSB2YXJpYWJsZXMgIm5veCIgKGNvbmNlbnRyYXRpb24gb2Ygbml0cm9nZW4gb3hpZGVzKSwgImNyaW0iIChjcmltZSByYXRlKSwgInRheCIgKHByb3BlcnR5IHRheCksIGFuZCAiaW5kdXMiIChwcm9wb3J0aW9uIG9mIG5vbi1yZXRhaWwgYnVzaW5lc3MgYWNyZXMgcGVyIGNpdHkpIGFyZSBub3Qgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBpbiB0aGlzIG1vZGVsLgoKVGhlIG1vZGVsIGFzIGEgd2hvbGUgaGFzIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBGIHZhbHVlLCBpbmRpY2F0aW5nIHRoYXQgYXQgbGVhc3Qgb25lIG9mIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgaXMgcmVsZXZhbnQgaW4gcHJlZGljdGluZyB0aGUgbG9nYXJpdGhtIG9mIGhvdXNlIHByaWNlcy4KClRoZSBpbnRlcmNlcHQgaXMgbm90IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgaW4gdGhpcyBjb250ZXh0LgoKSW4gc3VtbWFyeSwgdGhlIHNlY29uZCBtb2RlbCBzdWdnZXN0cyB0aGF0IHRoZSBhdmVyYWdlIG51bWJlciBvZiByb29tcyBhbmQgdGhlIHBlcmNlbnRhZ2Ugb2YgcG9wdWxhdGlvbiB3aXRoIGxvdyBzdGF0dXMgYXJlIGltcG9ydGFudCBmYWN0b3JzIGluIHByZWRpY3RpbmcgdGhlIGxvZ2FyaXRobSBvZiBob3VzZSBwcmljZXMsIHdoaWxlIG90aGVyIHZhcmlhYmxlcyBkbyBub3QgaGF2ZSBhIHNpZ25pZmljYW50IGltcGFjdCBvbiB0aGUgbW9kZWwuIFRoZSBtb2RlbCBhcyBhIHdob2xlIGlzIGFibGUgdG8gZXhwbGFpbiBhIGNvbnNpZGVyYWJsZSBwYXJ0IG9mIHRoZSB2YXJpYWJpbGl0eSBpbiB0aGUgbG9nYXJpdGhtIG9mIGhvdXNlIHByaWNlcy4KCiMjIyMgRGlhZ25vc3RpYyB0ZXN0cyBNT0RFTCAyCgpgYGB7cn0KIyBNdWx0aWNvbGxpbmVhcml0eQoKdmlmKGRtb2RlbDIpCmBgYAoKU2luY2Ugbm8gdmFsdWUgZXhjZWVkcyB0aGUgdGhyZXNob2xkIG9mIDEwLCBtdWx0aWN1bGlvbmFsaXR5IGlzIG5vdCBvYnNlcnZlZCwgdGhhdCBpcywgdGhlcmUgaXMgbm8gY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLgoKYGBge3J9CiMgSGV0ZXJvc2NlZGFzdGljaXR5CgpicHRlc3QoZG1vZGVsMikKYGBgClRoZSBzdHVkZW50aXplZCBCcmV1c2NoLVBhZ2FuIHRlc3QgeWllbGRzIGFuIGV4dHJlbWVseSBsb3cgcC12YWx1ZSAoMS41MThlLTA3KSwgd2hpY2ggbGVhZHMgdXMgdG8gc3Ryb25nbHkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgb2YgaG9tb3NjZWRhc3RpY2l0eSBpbiB0aGUgZG1vZGVsMiBtb2RlbC4gV2l0aCBzdWNoIGEgbG93IHAgdmFsdWUsIHdlIGNhbiBzdHJvbmdseSBjb25jbHVkZSB0aGF0IGhldGVyb3NrZWRhc3RpY2l0eSBleGlzdHMgaW4gdGhlIG1vZGVsIHJlc2lkdWFscy4gVGhlIHNpZ25pZmljYW5jZSBsZXZlbCBpcyBtdWNoIGxvd2VyIHRoYW4gMC4wNSwgd2hpY2ggcmVpbmZvcmNlcyB0aGlzIGNvbmNsdXNpb24uCgoKYGBge3J9CiMgTm9ybWFsaXR5IG9mIFJlc2lkdWFscwpxcW5vcm0oZG1vZGVsMiRyZXNpZHVhbHMpCnFxbGluZShkbW9kZWwyJHJlc2lkdWFscykKc2hhcGlyby50ZXN0KGRtb2RlbDIkcmVzaWR1YWxzKQpgYGAKCgpUaGUgU2hhcGlyby1XaWxrIG5vcm1hbGl0eSB0ZXN0IHNob3dzIGFuIGV4dHJlbWVseSBsb3cgcC12YWx1ZSAoMS4xNjRlLTEyKSwgbGVzcyB0YWggcD0wLjA1LiBJbmRpY2F0aW5nIHRoYXQgdGhlIHJlc2lkdWFscyBmcm9tIHRoZSBkbW9kZWwyIG1vZGVsIGRvIG5vdCBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uLiBUaGVyZWZvcmUsIHdlIGNhbiBzdHJvbmdseSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSByZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBUaGlzIHJlc3VsdCBzdWdnZXN0cyB0aGF0IHRoZSBtb2RlbCBkb2VzIG5vdCBtZWV0IHRoZSBhc3N1bXB0aW9uIG9mIG5vcm1hbGl0eSBvZiBlcnJvcnMuCgoKIyMjIyBNT0RFTCAzCgpgYGB7cn0KZG1vZGVsMzwtbG0obG9nKG1lZHYpIH4gK0koY21lZHZeMikrbm94K3JtK25veCtsc3RhdCtjcmltLGRhdGE9ZGF0YXNldCkKc3VtbWFyeShkbW9kZWwzKSAKYGBgClRoZSBtb2RlbCBoYXMgYSBoaWdoIGNhcGFjaXR5IHRvIGV4cGxhaW4gdmFyaWF0aW9ucyBpbiB0aGUgbG9nYXJpdGhtIG9mIGhvdXNlIHByaWNlcywgd2l0aCBhbiBhZGp1c3RlZCBSLXNxdWFyZWQgb2YgYXBwcm94aW1hdGVseSAwLjg4OTguCgpPZiB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLCAiSShjbWVkdl4yKSIgKGEgcXVhZHJhdGljIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSBhdmVyYWdlIGhvdXNlIHByaWNlKSwgIm5veCIgKGNvbmNlbnRyYXRpb24gb2Ygbml0cm9nZW4gb3hpZGVzKSwgInJtIiAoYXZlcmFnZSBudW1iZXIgb2Ygcm9vbXMgcGVyIGhvdXNlKSwgImxzdGF0ICIgKHBlcmNlbnRhZ2Ugb2YgcG9wdWxhdGlvbiB3aXRoIGxvdyBzdGF0dXMpIGFuZCAiY3JpbSIgKGNyaW1lIHJhdGUpIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LgoKVGhlIGNvZWZmaWNpZW50IG9mICJJKGNtZWR2XjIpIiBpcyBwb3NpdGl2ZSwgc3VnZ2VzdGluZyBhIHBvc2l0aXZlIHF1YWRyYXRpYyByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgdHJhbnNmb3JtZWQgdmFyaWFibGUgYW5kIHRoZSBsb2dhcml0aG0gb2YgaG91c2UgcHJpY2VzLgoKVGhlIGludGVyY2VwdCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGFuZCBoYXMgYSBwb3NpdGl2ZSB2YWx1ZSwgaW5kaWNhdGluZyBhIGJhc2UgdmFsdWUgaW4gdGhlIGxvZ2FyaXRobSBvZiBob3VzZSBwcmljZXMuCgpPdmVyYWxsLCB0aGUgbW9kZWwgYXMgYSB3aG9sZSBpcyBoaWdobHkgc2lnbmlmaWNhbnQsIHdpdGggYSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IEYgdmFsdWUuCgpUaGUgbW9kZWwgaGFzIGEgZ29vZCBmaXQgdG8gdGhlIGRhdGEsIHdpdGggYSBsb3cgcmVzaWR1YWwgc3RhbmRhcmQgZXJyb3Igb2YgYXBwcm94aW1hdGVseSAwLjEzNjMuCgojIyMjIERpYWdub3N0aWMgdGVzdHMgTU9ERUwgMwoKYGBge3J9CiMgTXVsdGljb2xsaW5lYXJpdHkKCnZpZihkbW9kZWwzKQpgYGAKU2luY2Ugbm8gdmFsdWUgZXhjZWVkcyB0aGUgdGhyZXNob2xkIG9mIDEwLCBtdWx0aWN1bGlvbmFsaXR5IGlzIG5vdCBvYnNlcnZlZCwgdGhhdCBpcywgdGhlcmUgaXMgbm8gY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLgoKCmBgYHtyfQojIEhldGVyb3NjZWRhc3RpY2l0eQoKYnB0ZXN0KGRtb2RlbDMpCmBgYAoKRWwgdGVzdCBkZSBCcmV1c2NoLVBhZ2FuIGFycm9qYSB1biB2YWxvciBwIG11eSBjZXJjYW5vIGEgY2VybyAocC12YWx1ZSA8IDIuMmUtMTYpLCBsbyBxdWUgaW5kaWNhIHVuYSBmdWVydGUgZXZpZGVuY2lhIGVuIGNvbnRyYSBkZSBsYSBoaXDDs3Rlc2lzIG51bGEgZGUgaG9tb2NlZGFzdGljaWRhZC4gUG9yIGxvIHRhbnRvLCBwb2RlbW9zIGNvbmNsdWlyIHF1ZSBleGlzdGUgaGV0ZXJvY2VkYXN0aWNpZGFkIGVuIGVsIG1vZGVsbyBkbW9kZWwzLCBsbyBxdWUgc3VnaWVyZSBxdWUgbGEgdmFyaWFuemEgZGUgbG9zIGVycm9yZXMgbm8gZXMgY29uc3RhbnRlIGVuIHRvZGFzIGxhcyBvYnNlcnZhY2lvbmVzIHkgcXVlIHBvZHLDrWEgaGFiZXIgcHJvYmxlbWFzIGRlIGRpc3BlcnNpw7NuIGVuIGVsIG1vZGVsby4KCgpgYGB7cn0KIyBOb3JtYWxpdHkgb2YgUmVzaWR1YWxzCnFxbm9ybShkbW9kZWwzJHJlc2lkdWFscykKcXFsaW5lKGRtb2RlbDMkcmVzaWR1YWxzKQpzaGFwaXJvLnRlc3QoZG1vZGVsMyRyZXNpZHVhbHMpCmBgYAoKVGhlIFNoYXBpcm8tV2lsayBub3JtYWxpdHkgdGVzdCB5aWVsZHMgYW4gZXh0cmVtZWx5IGxvdyBwLXZhbHVlIChwLXZhbHVlID0gMS45NzJlLTE0KSwgaW5kaWNhdGluZyBzdHJvbmcgZXZpZGVuY2UgYWdhaW5zdCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlIHJlc2lkdWFscyBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uLiBUaGVyZWZvcmUsIHdlIGNhbiBjb25jbHVkZSB0aGF0IHRoZSByZXNpZHVhbHMgZG8gbm90IGZvbGxvdyBhIG5vcm1hbCBkaXN0cmlidXRpb24sIHN1Z2dlc3RpbmcgdGhhdCB0aGUgYXNzdW1wdGlvbiBvZiBub3JtYWxpdHkgb2YgdGhlIGVycm9ycyBpbiB0aGUgbW9kZWwgbWF5IG5vdCBiZSBhZGVxdWF0ZWx5IG1ldC4gSXQgaXMgaW1wb3J0YW50IHRvIGtlZXAgdGhpcyBub24tbm9ybWFsaXR5IGluIG1pbmQgd2hlbiBpbnRlcnByZXRpbmcgbW9kZWwgcmVzdWx0cyBhbmQgY29uc2lkZXJpbmcgcG9zc2libGUgYWRqdXN0bWVudHMgb3IgdHJhbnNmb3JtYXRpb25zIG9mIHRoZSBkYXRhIGlmIG5lY2Vzc2FyeS4KCmBgYHtyfQpBSUMoZG1vZGVsMSkKQUlDKGRtb2RlbDIpCkFJQyhkbW9kZWwzKQpgYGAKCiMjIyMjIE1vZGVsIFNlbGVjdGlvbgoKVGhlIG1vZGVscyBwcmVzZW50ZWQgcHJvYmxlbXMgb2Ygbm9ybWFsaXR5IGFuZCBoZXRlcm9jZXJhc3RpY2l0eSwgd2hpY2ggaXMgd2h5IGl0IGlzIGltcG9ydGFudCB0byBjb250aW51ZSBtYWtpbmcgZGF0YSB0cmFuc2Zvcm1hdGlvbnMgYW5kIGFwcGx5IG90aGVyIHJlZ3VsYXJpemF0aW9uIG1ldGhvZHMgdG8gYWNoaWV2ZSBhIG1vcmUgcHJlY2lzZSBhbmQgcmVsaWFibGUgbW9kZWwgZm9yIHByZWRpY3Rpb25zLiBPbiB0aGUgb3RoZXIgaGFuZCwgYmVjYXVzZSBtb3N0IG9mIHRoZSB2YXJpYWJsZXMgYXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQsIGhhdmUgYSBoaWdoZXIgci1zcXVhcmVkIHZhbHVlLCBkbyBub3QgcHJlc2VudCBtdWx0aWN1bGluYWxpdHkgYW5kIGhhdmUgYSBsb3dlciBBSUMgdmFsdWUsIG1vZGVsIDMgaXMgY2hvc2VuIGFzIHRoZSBiZXN0IG9wdGlvbiB0byBmaXQgb3VyIG5lZWRzLiBkYXRhLiBJdCBpcyBhbHNvIGltcG9ydGFudCB0byBtZW50aW9uIHRoYXQgaGV0ZXJvY2VyYXN0aWNpdHkgaXMgYSBwcm9ibGVtIGluaGVyZW50IHRvIHRoZSBuYXR1cmUgb2YgdGhlIGRhdGEsIHNpbmNlIGRhdGEgZnJvbSBvbmUgcG9pbnQgaW4gdGltZSBmcm9tIHZhcmlvdXMgVVMgc3RhdGVzIGFyZSBiZWluZyBzdHVkaWVkLCB0aGVyZWZvcmUgdGhlIHZhcmlhbmNlcyB3aWxsIGRpZmZlciB3aGVuIHN0dWR5aW5nIG1hbnkgZ3JvdXBzIG9mIGRhdGEgd2l0aCBjaGFyYWN0ZXJpc3RpY3MgZGlmZmVyZW50LgoKIyMjIE1vZGVsIGludGVycHJldGF0aW9uCgpUaGUgbW9kZWwgaGFzIGEgaGlnaCBjYXBhY2l0eSB0byBleHBsYWluIHZhcmlhdGlvbnMgaW4gdGhlIGxvZ2FyaXRobSBvZiBob3VzZSBwcmljZXMsIHdpdGggYW4gYWRqdXN0ZWQgUi1zcXVhcmVkIG9mIGFwcHJveGltYXRlbHkgMC44ODk4LgoKT2YgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcywgIkkoY21lZHZeMikiIChhIHF1YWRyYXRpYyB0cmFuc2Zvcm1hdGlvbiBvZiB0aGUgYXZlcmFnZSBob3VzZSBwcmljZSksICJub3giIChjb25jZW50cmF0aW9uIG9mIG5pdHJvZ2VuIG94aWRlcyksICJybSIgKGF2ZXJhZ2UgbnVtYmVyIG9mIHJvb21zIHBlciBob3VzZSksICJsc3RhdCAiIChwZXJjZW50YWdlIG9mIHBvcHVsYXRpb24gd2l0aCBsb3cgc3RhdHVzKSBhbmQgImNyaW0iIChjcmltZSByYXRlKSBhcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4KClRoZSBjb2VmZmljaWVudCBvZiAiSShjbWVkdl4yKSIgaXMgcG9zaXRpdmUsIHN1Z2dlc3RpbmcgYSBwb3NpdGl2ZSBxdWFkcmF0aWMgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHRyYW5zZm9ybWVkIHZhcmlhYmxlIGFuZCB0aGUgbG9nYXJpdGhtIG9mIGhvdXNlIHByaWNlcy4KClRoZSBpbnRlcmNlcHQgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBhbmQgaGFzIGEgcG9zaXRpdmUgdmFsdWUsIGluZGljYXRpbmcgYSBiYXNlIHZhbHVlIGluIHRoZSBsb2dhcml0aG0gb2YgaG91c2UgcHJpY2VzLgoKT3ZlcmFsbCwgdGhlIG1vZGVsIGFzIGEgd2hvbGUgaXMgaGlnaGx5IHNpZ25pZmljYW50LCB3aXRoIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBGIHZhbHVlLgoKVGhlIG1vZGVsIGhhcyBhIGdvb2QgZml0IHRvIHRoZSBkYXRhLCB3aXRoIGEgbG93IHJlc2lkdWFsIHN0YW5kYXJkIGVycm9yIG9mIGFwcHJveGltYXRlbHkgMC4xMzYzLgoKLSBDb2VmZmljaWVudCBpbnRlcnByZXRhdGlvbnM6CgotIC0gLSBJbnRlY2VwdCAoMy4zMzJlKzAwKTogSWYgYWxsIHByZWRpY3RvciB2YXJpYWJsZXMgYXJlIHplcm8sIHRoZSBsb2dhcml0aG0gb2YgdGhlIGF2ZXJhZ2UgaG9tZSB2YWx1ZSBpcyBlc3RpbWF0ZWQgYXQgMy4zMzIuCi0gLSAtIEkoY21lZHZeMikgKDQuODIwZS0wNCk6IEZvciBldmVyeSBvbmUtdW5pdCBpbmNyZWFzZSBpbiB0aGUgc3F1YXJlIG9mIGNtZWR2LCB0aGUgbG9nYXJpdGhtIG9mIG1lZHYgaW5jcmVhc2VzIGJ5IGFwcHJveGltYXRlbHkgMC4wMDA0ODIuIEl0IGlzIGhpZ2hseSBzaWduaWZpY2FudCB3aXRoIGEgcCB2YWx1ZSA8IDJlLTE2LgotIC0gLSBub3ggKC0xLjg1MWUtMDEpOiBGb3IgZXZlcnkgb25lIHVuaXQgaW5jcmVhc2UgaW4gbm94LCB0aGUgbG9nYXJpdGhtIG9mIG1lZHYgZGVjcmVhc2VzIGJ5IGFwcHJveGltYXRlbHkgMC4xODUxLiBJdCBpcyBzaWduaWZpY2FudCB3aXRoIGEgcCB2YWx1ZSBvZiAwLjAwNTcxLgotIC0gLSBybSAoLTMuMjk0ZS0wMik6IEZvciBldmVyeSBvbmUtcm9vbSBpbmNyZWFzZSBpbiBybSwgdGhlIGxvZ2FyaXRobSBvZiBtZWR2IGRlY3JlYXNlcyBieSBhcHByb3hpbWF0ZWx5IDAuMDMyOTQuIEl0IGlzIHNpZ25pZmljYW50IHdpdGggYSBwIHZhbHVlIG9mIDAuMDA5NjIuCi0gLSAtIGxzdGF0ICgtMS44ODBlLTAyKTogRm9yIGV2ZXJ5IG9uZS11bml0IGluY3JlYXNlIGluIGxzdGF0LCB0aGUgbG9nYXJpdGhtIG9mIG1lZHYgZGVjcmVhc2VzIGJ5IGFwcHJveGltYXRlbHkgMC4wMTg4LiBJdCBpcyBoaWdobHkgc2lnbmlmaWNhbnQgd2l0aCBhIHAgdmFsdWUgPCAyZS0xNi4KLSAtIC0gY3JpbSAoLTkuNzAyZS0wMyk6IEZvciBldmVyeSBvbmUgdW5pdCBpbmNyZWFzZSBpbiB0aGUgY3JpbWUgcmF0ZSwgdGhlIGxvZyBvZiBtZWR2IGRlY3JlYXNlcyBieSBhcHByb3hpbWF0ZWx5IDAuMDA5NzAyLiBJdCBpcyBoaWdobHkgc2lnbmlmaWNhbnQgd2l0aCBhIHAgdmFsdWUgPCAyZS0xNi4KCgpgYGB7cn0KIyBMQVNTTyByZWdyZXNzaW9uIHZpYSBnbG1uZXQgcGFja2FnZSBjYW4gb25seSB0YWtlIG51bWVyaWNhbCBvYnNlcnZhdGlvbnMuIFRoZW4sIHRoZSBkYXRhc2V0IGlzIHRyYW5zZm9ybWVkIHRvIG1vZGVsLm1hdHJpeCgpIGZvcm1hdC4gCiMgSW5kZXBlbmRlbnQgdmFyaWFibGVzCng8LW1vZGVsLm1hdHJpeChsb2cobWVkdikgfiBybStub3grbHN0YXQrY3JpbSxkYXRhc2V0KVssLTFdICMjIyBPTFMgbW9kZWwgc3BlY2lmaWNhdGlvbgojIHg8LW1vZGVsLm1hdHJpeChXZWVrbHlfU2FsZXN+Lix0cmFpbi5kYXRhKVssLTFdICMjIyBtYXRyaXggb2YgaW5kZXBlbmRlbnQgdmFyaWFibGVzIFgncwp5PC1kYXRhc2V0JG1lZHYgIyMjIGRlcGVuZGVudCB2YXJpYWJsZSAKCiMgSW4gZXN0aW1hdGluZyBMQVNTTyByZWdyZXNzaW9uIGl0IGlzIGltcG9ydGFudCB0byBkZWZpbmUgdGhlIGxhbWJkYSB0aGF0IG1pbmltaXplcyB0aGUgcHJlZGljdGlvbiBlcnJvciByYXRlLiAKIyBDcm9zcy12YWxpZGF0aW9uIGVuc3VyZXMgdGhhdCBldmVyeSBkYXRhIC8gb2JzZXJ2YXRpb24gZnJvbSB0aGUgb3JpZ2luYWwgZGF0YXNldCAoZGF0YWlucykgaGFzIGEgY2hhbmNlIG9mIGFwcGVhcmluZyBpbiB0cmFpbiBhbmQgdGVzdCBkYXRhc2V0cy4KIyBGaW5kIHRoZSBiZXN0IGxhbWJkYSB1c2luZyBjcm9zcy12YWxpZGF0aW9uLgpzZXQuc2VlZCgxMjMpIApjdi5sYXNzbzwtY3YuZ2xtbmV0KHgseSxhbHBoYT0xKSAjIGFscGhhID0gMSBmb3IgTEFTU08KCiMgRGlzcGxheSB0aGUgYmVzdCBsYW1iZGEgdmFsdWUKY3YubGFzc28kbGFtYmRhLm1pbiAgICAgICAgICAgICAgICAgICAgICAjIyMgbGFtYmRhOiBhIG51bWVyaWMgdmFsdWUgZGVmaW5pbmcgdGhlIGFtb3VudCBvZiBzaHJpbmthZ2UuIFdoeSBtaW4/IHRoZSBoaWdoZXIgdGhlIHZhbHVlIG9mID8/ICwgdGhlIG1vcmUgcGVuYWxpemF0aW9uIHRoZXJlIGlzCgojIEZpdCB0aGUgZmluYWwgbW9kZWwgb24gdGhlIHRyYWluaW5nIGRhdGEKbGFzc29tb2RlbDwtZ2xtbmV0KHgseSxhbHBoYT0xLGxhbWJkYT1jdi5sYXNzbyRsYW1iZGEubWluKQoKIyBEaXNwbGF5IHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzCmNvZWYobGFzc29tb2RlbCkKCiMgTWFrZSBwcmVkaWN0aW9ucyBvbiB0aGUgdGVzdCBkYXRhCngudGVzdDwtbW9kZWwubWF0cml4KGxvZyhtZWR2KSB+IHJtK25veCtsc3RhdCtjcmltLGRhdGFzZXQpWywtMV0gIyMjIE9MUyBtb2RlbCBzcGVjaWZpY2F0aW9uCiMgeC50ZXN0PC1tb2RlbC5tYXRyaXgoV2Vla2x5X1NhbGVzfi4sdGVzdC5kYXRhKVssLTFdCmxhc3NvcHJlZGljdGlvbnMgPC0gbGFzc29tb2RlbCAlPiUgcHJlZGljdCh4LnRlc3QpICU+JSBhcy52ZWN0b3IoKQoKCiMjIyB2aXN1YWxpemluZyBsYXNzbyByZWdyZXNzaW9uIHJlc3VsdHMgCmxic19mdW4gPC0gZnVuY3Rpb24oZml0LCBvZmZzZXRfeD0xLCAuLi4pIHsKICBMIDwtIGxlbmd0aChmaXQkbGFtYmRhKQogIHggPC0gbG9nKGZpdCRsYW1iZGFbTF0pKyBvZmZzZXRfeAogIHkgPC0gZml0JGJldGFbLCBMXQogIGxhYnMgPC0gbmFtZXMoeSkKICB0ZXh0KHgsIHksIGxhYmVscz1sYWJzLCAuLi4pCn0KCmxhc3NvPC1nbG1uZXQoc2NhbGUoeCkseSxhbHBoYT0xKQoKcGxvdChsYXNzbyx4dmFyPSJsYW1iZGEiLGxhYmVsPVQpCmxic19mdW4obGFzc28pCmFibGluZSh2PWN2Lmxhc3NvJGxhbWJkYS5taW4sY29sPSJyZWQiLGx0eT0yKQphYmxpbmUodj1jdi5sYXNzbyRsYW1iZGEuMXNlLGNvbD0iYmx1ZSIsbHR5PTIpCgpzdW1tYXJ5KGxhc3NvbW9kZWwpCgpgYGAKCi0gLSAtIEludGVyY2VwdDogVGhlIGludGVyY2VwdCB2YWx1ZSBpcyBhcHByb3hpbWF0ZWx5IC0xLjc0NC4gVGhpcyByZXByZXNlbnRzIHRoZSBlc3RpbWF0ZWQgdmFsdWUgb2YgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAobWVkdikgd2hlbiBhbGwgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGFyZSBlcXVhbCB0byB6ZXJvLgoKLSAtIC0gQ29lZmZpY2llbnRzIG9mIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXM6IFRoZSBtb2RlbCBoYXMgaWRlbnRpZmllZCB0aHJlZSBzaWduaWZpY2FudCB2YXJpYWJsZXMgaW4gcHJlZGljdGluZyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIChtZWR2KS4gVGhlc2UgYXJlICJybSIgKG51bWJlciBvZiByb29tcyksICJsc3RhdCIgKHBlcmNlbnRhZ2Ugb2YgbG93LXN0YXR1cyBwb3B1bGF0aW9uKSwgYW5kICJjcmltIiAoY3JpbWUgcmF0ZSkuIFRoZSBtYWduaXR1ZGUgb2YgdGhlc2UgY29lZmZpY2llbnRzIGluZGljYXRlcyB0aGVpciBpbXBhY3Qgb24gdGhlIGRlcGVuZGVudCB2YXJpYWJsZS4gRm9yIGV4YW1wbGUsIGEgb25lIHVuaXQgaW5jcmVhc2UgaW4gInJtIiByZXN1bHRzIGluIGFuIGluY3JlYXNlIG9mIGFwcHJveGltYXRlbHkgNS4wNyB1bml0cyBpbiBtZWR2LCBob2xkaW5nIHRoZSBvdGhlciB2YXJpYWJsZXMgY29uc3RhbnQuCgotIC0gLSBWYXJpYWJsZSAibm94IiAobml0cm9nZW4gb3hpZGUpOiBUaGUgY29lZmZpY2llbnQgZm9yICJub3giIGlzIG1hcmtlZCAiLiIuIFRoaXMgbWVhbnMgdGhhdCB0aGUgbW9kZWwgaGFzIGNvbnNpZGVyZWQgdGhhdCB0aGlzIHZhcmlhYmxlIGRvZXMgbm90IGhhdmUgYSBzaWduaWZpY2FudCBpbXBhY3Qgb24gdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBhZnRlciBMMSByZWd1bGFyaXphdGlvbi4KCi0gLSAtIE1vZGVsIGRpbWVuc2lvbjogVGhlIG1vZGVsIGhhcyBlc3RpbWF0ZWQgZm91ciBub24tbnVsbCBjb2VmZmljaWVudHMgKGRmKSBhbmQgYSBjb25zdGFudCB0ZXJtLCB3aGljaCBtZWFucyB0aGF0IGl0IGNvbnNpZGVycyBmb3VyIGluZGVwZW5kZW50IHZhcmlhYmxlcyBhcyByZWxldmFudCBmb3IgdGhlIHByZWRpY3Rpb24gb2YgbWVkdi4KCgojIyMjIyBTZXJpYWwgQXV0b2NvcnJlbGF0aW9uCgpTaW5jZSB3ZSBhcmUgd29ya2luZyB3aXRoIGEgZGF0YWJhc2UgdGhhdCBjb2xsZWN0cyBpbmZvcm1hdGlvbiBvbiB0aGUgdmFsdWUgb2YgaG9tZXMgYXQgYSBzcGVjaWZpYyBwb2ludCBpbiB0aW1lLCB0aGV5IGFyZSBjcm9zcy1zZWN0aW9uYWwgZGF0YSBhbmQgdGhlcmVmb3JlIGRvIG5vdCBoYXZlIHNlcmlhbCBhdXRvY29ycmVsYXRpb24uCgojIENvbmNsdXNpb25zCgpJbiBzdW1tYXJ5LCB0aGFua3MgdG8gdGhlIGV4cGxvcmF0b3J5IGFuYWx5c2lzIG9mIHRoZSBkYXRhLCB3ZSBoYWQgYSBjbGVhciBpZGVhIG9mIHRoZSBkYXRhIHdlIGhhZCBhbmQgdGhlIHRyYW5zZm9ybWF0aW9ucyBuZWNlc3NhcnkgdG8gYWNoaWV2ZSBhIHJvYnVzdCBtb2RlbC4gTW9kZWwgMyBzdGFuZHMgb3V0IGFzIGEgbW9kZWwgd2l0aCBhIHZlcnkgZ29vZCBmaXQgdG8gdGhlIGRhdGEsIHRoYW5rcyB0byBnb29kIHZhbHVlcyBvZiBBSUMgYW5kIFIgc3F1YXJlZCwgYW5kIGl0IHdhcyBhbHNvIGEgbW9kZWwgdGhhdCBoYWQgbWFueSB2YXJpYWJsZXMgd2l0aCBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UgYW5kIHRoYXQgaGVscGVkIHVzIGNvcnJvYm9yYXRlIG91ciBoeXBvdGhlc2VzLiBIb3dldmVyLCBkZXNwaXRlIHJlZHVjaW5nIGhldGVyb2NlcmFzdGljaXR5IHdpdGggZGF0YSB0cmFuc2Zvcm1hdGlvbnMgYW5kIHdpdGggdGhlIGxhc3NvIG1vZGVsLCBpdCBpcyBpbXBvcnRhbnQgdG8gY29udGludWUgYXBwbHlpbmcgb3RoZXIgdHJhbnNmb3JtYXRpb24gdGVjaG5pcXVlcyB0byBhdm9pZCB0aGlzIHByb2JsZW0sIGFsdGhvdWdoIGFzIGFscmVhZHkgbWVudGlvbmVkLCBpdCBpcyBpbXBvcnRhbnQgdG8gaGlnaGxpZ2h0IHRoYXQgaGV0ZXJvY2VyYXN0aWNpdHkgaXMgYSBuYXR1cmFsIHByb2JsZW0gb2YgVGhlIGRhdGEgd2UgYXJlIHdvcmtpbmcgd2l0aCBhcmUgY3Jvc3Mtc2VjdGlvbmFsIGRhdGEgZnJvbSBzZXZlcmFsIFVTIHN0YXRlcyBhdCBhIGdpdmVuIHBvaW50IGluIHRpbWUsIHNvIHRoZSB2YXJpYW5jZXMgd2lsbCBoYXJkbHkgYmUgaG9tb2dlbmVvdXMuClJlZ2FyZGluZyB0aGUgaW5zaWdodHMgZm91bmQsIHRoZSBncmVhdCBpbXBhY3QgdGhhdCB0aGUgY3JpbWUgcmF0ZSBoYXMgb24gaG9tZXMgaXMgaGlnaGxpZ2h0ZWQsIHNpbmNlIHRoaXMgdmFyaWFibGUgd2FzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQsIHdpdGggYSBoaWdoIGFuZCBuZWdhdGl2ZSBjb2VmZmljaWVudCwgc28gYW4gaW5jcmVhc2UgaW4gY3JpbWUgbGVhZHMgdG8gYSBjb25zaWRlcmFibGUgbG9zcyBpbiB0aGUgdmFsdWUgb2YgdGhlIHByb3BlcnR5LiB0aGUgaG9tZXMsIHdoaWNoIGlzIHdoeSBpdCBpcyBpbXBvcnRhbnQgdG8gZ3VhcmFudGVlIHRoZSBzZWN1cml0eSBvZiB0aGUgbmVpZ2hib3Job29kcyBhbmQgdGh1cyBiZSBhYmxlIHRvIGluY3JlYXNlIHRoZSB2YWx1ZSBvZiB0aGUgaG9tZXMuIE9uIHRoZSBvdGhlciBoYW5kLCBhaXIgcXVhbGl0eSwgYXMgdGhvdWdodCwgdHVybmVkIG91dCB0byBoYXZlIGEgbmVnYXRpdmUgc2lnbmlmaWNhbmNlLCB3aGljaCBoaWdobGlnaHRzIHRoZSB0ZW5kZW5jeSBvZiBwZW9wbGUgdG8gbGl2ZSBpbiBxdWlldCBwbGFjZXMsIHdpdGggZXhjZWxsZW50IGFpciBhbmQgYSB2ZXJ5IGdvb2QgcXVhbGl0eSBvZiBsaWZlLiBIb3dldmVyLCBzb21ldGhpbmcgaW50ZXJlc3Rpbmcgd2FzIHNlZWluZyB0aGF0IHRoZSBudW1iZXIgb2Ygcm9vbXMgdHVybmVkIG91dCB0byBoYXZlIGEgbmVnYXRpdmUgcmVsYXRpb25zaGlwIHdpdGggdGhlIHZhbHVlIG9mIHRoZSBob21lcywgc29tZXRoaW5nIHZlcnkgcGVjdWxpYXIgYW5kIHRoYXQgY291bGQgYmUgcmVsYXRlZCB0byB0aGUgZmFjdCB0aGF0IHBlcmhhcHMgcGVvcGxlIHZhbHVlIG90aGVyIG1vcmUgaW1wb3J0YW50IGZhY3RvcnMgbW9yZSB0aGFuIHRoZSBudW1iZXIgb2Ygcm9vbXMuCgpMaWtld2lzZSwgdGhlIHZhbHVlIG9mIGhvbWVzIGlzIGEgdmFyaWFibGUgdGhhdCBkZXBlbmRzIG9uIG1hbnkgb3RoZXIgaW5kZXBlbmRlbnQgdmFyaWFibGVzIG9mIHRob3NlIHN0dWRpZWQgaGVyZSwgaXQgd2lsbCBiZSBpbnRlcmVzdGluZyB0byBjb21wbGVtZW50IHRoaXMgYW5hbHlzaXMgd2l0aCB0aGUgZWNvbm9taWMgcHJvamVjdGlvbnMgb2YgdGhlIGFyZWFzIGluIHRoZSBmdXR1cmUsIHRoZSBzdG9yZXMgdGhhdCBhcmUgYXJvdW5kLCB0aGUgZGlzdGFuY2VzIHRvIHRoZSBjaXRpZXMsIGV0Yy4KClJlZ2FyZGluZyB0aGUgYXBwbGljYXRpb24gb2YgbGluZWFyIHJlZ3Jlc3Npb24gaW4gdGhlIGNvbnRleHQgb2YgcHJlZGljdGl2ZSBhbmFseXRpY3MsIHRoaXMgYXBwcm9hY2ggYXBwZWFycyB0byBiZSBhIHZhbHVhYmxlIHRvb2wuIExpbmVhciByZWdyZXNzaW9uIG1vZGVscyBwcm92aWRlIGFuIHVuZGVyc3RhbmRpbmcgb2YgaG93IHZhcmlvdXMgY2hhcmFjdGVyaXN0aWNzIGFmZmVjdCBwcm9wZXJ0eSB2YWx1ZXMgYW5kIGFyZSB0aGVyZWZvcmUgZXNzZW50aWFsIGZvciBtYWtpbmcgaW5mb3JtZWQgcmVhbCBlc3RhdGUgZGVjaXNpb25zLiBGdXJ0aGVybW9yZSwgdGhlIGlkZW50aWZpY2F0aW9uIG9mIHNpZ25pZmljYW50IHZhcmlhYmxlcywgc3VjaCBhcyBhaXIgcXVhbGl0eSAobm94KSBhbmQgY3JpbWUgcmF0ZSAoY3JpbSksIGNhbiBwcm92aWRlIGNydWNpYWwgaW5mb3JtYXRpb24gZm9yIHRoZSBwbGFubmluZyBhbmQgZGV2ZWxvcG1lbnQgb2YgZnV0dXJlIHJlYWwgZXN0YXRlIHByb2plY3RzLiBUaGlzIHByZWRpY3RpdmUgYW5hbHl0aWNzIGNhcGFiaWxpdHkgY2FuIHNpZ25pZmljYW50bHkgaW1wcm92ZSBlZmZpY2llbmN5IGFuZCBlZmZlY3RpdmVuZXNzIGluIHByb3BlcnR5IGludmVzdG1lbnQgYW5kIG1hbmFnZW1lbnQsIHN1cHBvcnRpbmcgdGhlIGNvbnRpbnVlZCBpbXBvcnRhbmNlIG9mIGxpbmVhciByZWdyZXNzaW9uIGluIGFuYWx5c2lzIGFuZCBkZWNpc2lvbiBtYWtpbmcgaW4gdGhlIHJlYWwgZXN0YXRlIG1hcmtldC4=