We will be examining 3 variables: (median) house price vs covid infections vs vaccine rate regarding Pittsburgh neighborhoods. Our independent variables are covid infections and vaccine rates, and our dependent variable is (median) house prices in each neighborhood.

Datasets Used

[Covid Infections][https://data.wprdc.org/dataset/allegheny-county-covid-19-tests-cases-and-deaths/resource/0f214885-ff3e-44e1-9963-e9e9062a04d1?inner_span=True]

[Vaccine Reports][https://data.wprdc.org/dataset/allegheny-county-covid-19-vaccinations/resource/61ab4ad4-fb84-4789-95c9-cbe116414287]

[House Prices][https://data.wprdc.org/dataset/real-estate-sales/resource/5bbe6c55-bce6-4edb-9d04-68edeb6bf7b1/view/fc32217e-2f0e-437d-9f68-f2922dfdf71f]

Part 1

Median House Prices vs Covid Infections


#HOUSE DATASET
house_data = read.csv("house_sales.csv")

#filter to price >1, some are 0, 1, or 2 for some reason
house_data = house_data[house_data$PRICE > 2,]
complete = complete.cases(house_data)
house_data = house_data[complete, ]

#filter house data to after Covid hit since this dataset includes house sales from 2013-present
house_data$SALEDATE = gsub("/", "-", house_data$SALEDATE)
house_data$SALEDATE = as.Date(house_data$SALEDATE, format = "%m-%d-%Y")
house_data = subset(house_data, SALEDATE >= as.Date("2020-06-01"))

#make dataframe for median house prices in each neighborhood
median_house_price = aggregate(house_data$PRICE, by = list(neighborhood = house_data$MUNIDESC), FUN = median)
colnames(median_house_price) = c("neighborhood", "median_price")
median_house_data = median_house_price

#read in covid dataset
covid_data = read.csv("covid_data.csv")

#some neighborhood names in covid_data have "(Pittsburgh)", take that out
covid_data$neighborhood_municipality = gsub("\\(Pittsburgh\\)", "", covid_data$neighborhood_municipality)

# Remove special and capital characters in both datasets 
median_house_data$neighborhood = tolower(gsub("[^a-z0-9]+", "", median_house_data$neighborhood, perl = TRUE))
covid_data$neighborhood_municipality = tolower(gsub("[^a-z0-9]+", "", covid_data$neighborhood_municipality, perl = TRUE))

#merge house_data and covid_data according to neighborhood
house_and_covid_data = merge(covid_data, median_house_data, by.x = "neighborhood_municipality", by.y = "neighborhood")

#linear regression model on covid cases and house prices in Pittsburgh neighborhoods

lm_model1 = lm(house_and_covid_data$median_price ~ house_and_covid_data$infections, data = house_and_covid_data)
summary(lm_model1)

Call:
lm(formula = house_and_covid_data$median_price ~ house_and_covid_data$infections, 
    data = house_and_covid_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-187010 -100285  -42292   46008 1061726 

Coefficients:
                                 Estimate Std. Error t value
(Intercept)                     2.132e+05  2.151e+04   9.909
house_and_covid_data$infections 1.018e-01  1.360e+00   0.075
                                Pr(>|t|)    
(Intercept)                       <2e-16 ***
house_and_covid_data$infections     0.94    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 179000 on 112 degrees of freedom
Multiple R-squared:  5.003e-05, Adjusted R-squared:  -0.008878 
F-statistic: 0.005603 on 1 and 112 DF,  p-value: 0.9405
#plot model
plot(house_and_covid_data$infections, house_and_covid_data$median_price, xlab = "Covid Infections", ylab = "Median House Prices", main = "Covid Infections vs Median House Prices")
abline(lm_model1, col="blue")



#correlation between covid infections and house prices
correlation = cor(house_and_covid_data$median_price, house_and_covid_data$infections)
correlation_test = cor.test(house_and_covid_data$median_price, house_and_covid_data$infections)
correlation_test

    Pearson's product-moment correlation

data:  house_and_covid_data$median_price and house_and_covid_data$infections
t = 0.074855, df = 112, p-value = 0.9405
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.1770722  0.1907396
sample estimates:
        cor 
0.007072941 
cat("correlation coefficient between covid cases and house prices", correlation)
correlation coefficient between covid cases and house prices 0.007072941
#get slope of fitted line
slope1 = coef(lm_model1)[2]   

cat("
    slope of fitted line", slope1)

    slope of fitted line 0.1017766

Analysis of Covid Infections vs House Prices

Looking at the plot, there seems to be no correlation and no apparent trends between covid infections and median house prices in Pittsburgh neighborhoods. Even as covid infections increase, median house prices tend to stay the same. The slope of the fitted line to the regression model is close to 0, indicating that there is no apparent correlation between the two variables. This is further proven as the p-value obtained from the linear regression model between the two is 0.9405, meaning the model is not significant; Furthermore, the correlation coefficient is close to 0, thus there is close to no linear relationship between house prices and covid infections.

Median House Prices vs Vaccine Rate

# read in vaccine dataset
vaccine_data = read.csv("vaccine.csv")

#some neighborhood names have "(Pittsburgh)", take that out
vaccine_data$neighborhood_municipality = gsub("\\(Pittsburgh\\)", "", vaccine_data$neighborhood_municipality)

# Remove special and capital characters 
vaccine_data$neighborhood_municipality = tolower(gsub("[^a-z0-9]+", "", covid_data$neighborhood_municipality, perl = TRUE))

#merge median_house_data and vaccine_data according to neighborhood
house_and_vaccine_data = merge(vaccine_data, median_house_data, by.x = "neighborhood_municipality", by.y = "neighborhood")

#linear regression model on vaccine count and med house prices in Pittsburgh neighborhoods

lm_model2 = lm(house_and_vaccine_data$median_price ~ house_and_vaccine_data$bivalent_booster, data = house_and_vaccine_data)
summary(lm_model2)

Call:
lm(formula = house_and_vaccine_data$median_price ~ house_and_vaccine_data$bivalent_booster, 
    data = house_and_vaccine_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-193515 -104758  -43359   39903 1057190 

Coefficients:
                                          Estimate Std. Error
(Intercept)                             222471.775  20136.897
house_and_vaccine_data$bivalent_booster     -6.959      9.429
                                        t value Pr(>|t|)    
(Intercept)                              11.048   <2e-16 ***
house_and_vaccine_data$bivalent_booster  -0.738    0.462    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 178600 on 112 degrees of freedom
Multiple R-squared:  0.00484,   Adjusted R-squared:  -0.004046 
F-statistic: 0.5447 on 1 and 112 DF,  p-value: 0.462
#plot model
plot(house_and_vaccine_data$bivalent_booster, house_and_vaccine_data$median_price, main = "Vaccine Rate vs Median House Prices", ylab = "Median House Prices", xlab = "Vaccine Rate")
abline(lm_model1, col="blue")


#correlation between covid infections and house prices
correlation2 = cor(house_and_vaccine_data$median_price, house_and_vaccine_data$bivalent_booster)
correlation_test2 = cor.test(house_and_vaccine_data$median_price, house_and_vaccine_data$bivalent_booster)
correlation_test2

    Pearson's product-moment correlation

data:  house_and_vaccine_data$median_price and house_and_vaccine_data$bivalent_booster
t = -0.73803, df = 112, p-value = 0.462
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.2502805  0.1158288
sample estimates:
        cor 
-0.06956795 
cat("correlation coefficient between covid vaccine rate and house prices", correlation2)
correlation coefficient between covid vaccine rate and house prices -0.06956795
#get slope of fitted line
slope2 = coef(lm_model2)[2]   

cat("
    slope of fitted line", slope2)

    slope of fitted line -6.958619

Analysis of Vaccine Rate vs House Prices

Looking at the plot, there seems to be no correlation and no apparent trends between the vaccine rate and median house prices in Pittsburgh neighborhoods. The slope of the fitted line to the regression model is about -7 (a small value in comparison to the numbers used in the data), indicating that there is no noticeable correlation between the two variables. This is further proven as the p-value obtained from the linear regression model between the two is 0.462, meaning the model is not significant; Furthermore, the correlation coefficient is close to 0, thus there is close to no linear relationship between house prices and covid infections.

Colinearity between Covid Infections and Vaccine Rate

#check for colinearity between vaccine rate and covid cases

#merge covid infections, vaccine rate, and med house prices into one dataset
all_data = merge(house_and_covid_data, house_and_vaccine_data, by = "neighborhood_municipality")

#1) plot covid infections vs house prices
plot(house_and_covid_data$infections, house_and_covid_data$median_price, xlab = "Covid Infections", ylab = "Median House Prices", main = "Covid Infections vs Median House Prices")


#lm between covid infections and house prices
summary(lm(house_and_covid_data$median_price ~ house_and_covid_data$infections, data = all_data))

Call:
lm(formula = house_and_covid_data$median_price ~ house_and_covid_data$infections, 
    data = all_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-187010 -100285  -42292   46008 1061726 

Coefficients:
                                 Estimate Std. Error t value
(Intercept)                     2.132e+05  2.151e+04   9.909
house_and_covid_data$infections 1.018e-01  1.360e+00   0.075
                                Pr(>|t|)    
(Intercept)                       <2e-16 ***
house_and_covid_data$infections     0.94    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 179000 on 112 degrees of freedom
Multiple R-squared:  5.003e-05, Adjusted R-squared:  -0.008878 
F-statistic: 0.005603 on 1 and 112 DF,  p-value: 0.9405
#2) plot vaccine rate vs house prices
plot(house_and_vaccine_data$bivalent_booster, house_and_vaccine_data$median_price, main = "Vaccine Rate vs Median House Prices", ylab = "Median House Prices", xlab = "Vaccine Rate")


#lm between vaccine rate and house prices
summary(lm(all_data$median_price.x ~ house_and_vaccine_data$bivalent_booster, data = all_data))

Call:
lm(formula = all_data$median_price.x ~ house_and_vaccine_data$bivalent_booster, 
    data = all_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-193515 -104758  -43359   39903 1057190 

Coefficients:
                                          Estimate Std. Error
(Intercept)                             222471.775  20136.897
house_and_vaccine_data$bivalent_booster     -6.959      9.429
                                        t value Pr(>|t|)    
(Intercept)                              11.048   <2e-16 ***
house_and_vaccine_data$bivalent_booster  -0.738    0.462    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 178600 on 112 degrees of freedom
Multiple R-squared:  0.00484,   Adjusted R-squared:  -0.004046 
F-statistic: 0.5447 on 1 and 112 DF,  p-value: 0.462
#3) plot the two independent variables 
plot(all_data$infections, all_data$bivalent_booster, main = "Vaccine Rate vs Covid Infections", ylab = "Vaccine Rate", xlab = "Covid Infections")


#linear model between the two independent variables
lm_model3 = lm(all_data$median_price.x ~ all_data$infections + all_data$bivalent_booster, data = all_data)

#summary of linear regression model
summary(lm_model3)

Call:
lm(formula = all_data$median_price.x ~ all_data$infections + 
    all_data$bivalent_booster, data = all_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-193474 -104706  -43352   39852 1057244 

Coefficients:
                            Estimate Std. Error t value Pr(>|t|)
(Intercept)                2.224e+05  2.498e+04   8.903 1.19e-14
all_data$infections        5.715e-03  1.369e+00   0.004    0.997
all_data$bivalent_booster -6.955e+00  9.515e+00  -0.731    0.466
                             
(Intercept)               ***
all_data$infections          
all_data$bivalent_booster    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 179400 on 111 degrees of freedom
Multiple R-squared:  0.00484,   Adjusted R-squared:  -0.01309 
F-statistic: 0.2699 on 2 and 111 DF,  p-value: 0.7639

Analysis of Colinearity between Covid Infections and Vaccine Rate

Looking at the plot that shows no trend between the two independent variables and the linear regression model’s p-value of 0.7639, the two do not seem to be colinear. Thus, multiple linear regression is not needed and simple linear regression should suffice

Combine these variables in a multiple regression model and analyze the results.

library(dplyr)

#Read and rename files
housing_prices <- read.csv("house_sales.csv")
#change name
housing_prices <- housing_prices %>% rename(neighborhood = MUNIDESC)

#remove trailing spces 
housing_prices$neighborhood <- trimws(housing_prices$neighborhood)

# covert SALEDATE 
housing_prices$SALEDATE <- as.Date(housing_prices$SALEDATE, format = "%m/%d/%y")

# filter to only sales after covid 
housing_prices <- housing_prices %>%
  filter(SALEDATE > as.Date("2020-06-01"))

vaccines <- read.csv("vaccine.csv")

#change name 
vaccines <- vaccines %>% rename(neighborhood = neighborhood_municipality)

covid_cases <- read.csv("covid_data.csv")

#change name
covid_cases <- covid_cases %>% rename(neighborhood = neighborhood_municipality)

Group by neighborhood and calculate summary

#remove empty
housing_prices <- housing_prices %>%
  filter(!is.na(PRICE))

#mean price of each neighborhood
housing_prices_summary <- housing_prices %>%
  group_by(neighborhood) %>%
  summarize(mean_housing_price = mean(PRICE, na.rm = TRUE))

#merge everything 
vaccines_summary <- vaccines %>%
  group_by(neighborhood) %>%
  summarize(total_vaccinations = bivalent_booster)

covid_cases_summary <- covid_cases %>%
  group_by(neighborhood) %>%
  summarize(total_covid_cases = infections)

merged_data <- merge(housing_prices_summary, covid_cases_summary, by = "neighborhood")

merged_data <- merge(merged_data, vaccines_summary, by = "neighborhood")

Muliple linear regression

multi_lm <- lm(mean_housing_price ~ total_covid_cases + total_vaccinations, data = merged_data)


summary(multi_lm)

Call:
lm(formula = mean_housing_price ~ total_covid_cases + total_vaccinations, 
    data = merged_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-156167  -84381  -52448   57716  647951 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)        176916.810  17048.883  10.377   <2e-16 ***
total_covid_cases      -7.527      3.270  -2.302   0.0232 *  
total_vaccinations     53.890     22.310   2.415   0.0174 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 140000 on 109 degrees of freedom
Multiple R-squared:  0.05084,   Adjusted R-squared:  0.03342 
F-statistic: 2.919 on 2 and 109 DF,  p-value: 0.05822
#plot
plot(merged_data$total_covid_cases, merged_data$mean_housing_price, xlab = "Covid Cases", ylab = "House Prices")


plot(merged_data$total_vaccinations, merged_data$mean_housing_price, xlab = "Vaccinations", ylab = "House Prices")


plot(merged_data$total_covid_cases, merged_data$total_vaccinations, xlab = "Covid Cases", ylab = "Vaccinations")

Which variables are significant? Both total covid cases and total vaccinations have high p values, greater than 0.05 which indicates that they are not statistically significant.

What is the model fit? The multiple R-squared value is 0.03213. This means that total covid cases and total vaccinations only explain 3.21% of the data in housing prices.

Residual error difference between different models: A residual error of 166300 is high, suggesting that the model has a high amount of unexplained variability. It might be lower when looking at simple regression models.

Insights from R-squared error: Adjusted R-squared is even lower than R-squared, again meaning total covid cases and total vaccinations may not be strong variables in explaining housing prices.

Part 2

Question 2: Split the dataset randomly into training (80%) and test (20%) sets. (Use your knowledge on generating random numbers to create the splits)

Loading in the datasets and editing

library(dplyr)

housing_prices <- read.csv("house_sales.csv")
housing_prices <- housing_prices %>% rename(neighborhood = MUNIDESC)
housing_prices$neighborhood <- trimws(housing_prices$neighborhood)
housing_prices$SALEDATE <- as.Date(housing_prices$SALEDATE, format = "%m-%d-%y")

vaccines <- read.csv("vaccine.csv")
vaccines <- vaccines %>% rename(neighborhood = neighborhood_municipality)

covid_cases <- read.csv("covid_data.csv")
covid_cases <- covid_cases %>% rename(neighborhood = neighborhood_municipality)

Merging datasets into one set

housing_prices <- housing_prices %>%
  filter(!is.na(PRICE))
housing_prices_summary <- housing_prices %>%
  group_by(neighborhood) %>%
  summarize(mean_housing_price = mean(PRICE), na.rm = TRUE)

vaccines_summary <- vaccines %>%
  group_by(neighborhood) %>%
  summarize(total_vaccinations = bivalent_booster)

covid_cases_summary <- covid_cases %>%
  group_by(neighborhood) %>%
  summarize(total_covid_cases = infections)

merged_data <- merge(housing_prices_summary, covid_cases_summary, by = "neighborhood")
merged_data <- merge(merged_data, vaccines_summary, by = "neighborhood")

Question 3: Fit a multiple linear regression model to the training data, using all the variables in the dataset to predict wine quality

Splitting data into training and test sets

training_set <- merged_data %>% dplyr::sample_frac(0.8)
testing_set <- dplyr::anti_join(merged_data, training_set, by = "neighborhood")

training_mlr <- lm(mean_housing_price ~ total_covid_cases + total_vaccinations, data = training_set)
summary(training_mlr)

Call:
lm(formula = mean_housing_price ~ total_covid_cases + total_vaccinations, 
    data = training_set)

Residuals:
    Min      1Q  Median      3Q     Max 
-160421  -96591  -61738   56151  567879 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)        189092.333  20067.412   9.423 6.12e-15 ***
total_covid_cases      -8.447      3.785  -2.232   0.0282 *  
total_vaccinations     57.803     26.031   2.221   0.0290 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 147000 on 87 degrees of freedom
Multiple R-squared:  0.05548,   Adjusted R-squared:  0.03376 
F-statistic: 2.555 on 2 and 87 DF,  p-value: 0.08351
wine_quality = read.csv("winequality-red.csv")
wine_training_set <- wine_quality %>% dplyr::sample_frac(0.8)
wine_testing_set <- dplyr::anti_join(wine_quality, wine_training_set, by = "quality")

wine_mlr <- lm(quality ~ fixed.acidity + volatile.acidity + citric.acid + residual.sugar + chlorides + free.sulfur.dioxide + total.sulfur.dioxide + density + pH + sulphates + alcohol, data = wine_training_set)

summary(wine_mlr)

Call:
lm(formula = quality ~ fixed.acidity + volatile.acidity + citric.acid + 
    residual.sugar + chlorides + free.sulfur.dioxide + total.sulfur.dioxide + 
    density + pH + sulphates + alcohol, data = wine_training_set)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.71146 -0.36404 -0.04722  0.45004  2.02685 

Coefficients:
                       Estimate Std. Error t value Pr(>|t|)    
(Intercept)           2.422e+01  2.393e+01   1.012  0.31172    
fixed.acidity         2.667e-02  2.896e-02   0.921  0.35741    
volatile.acidity     -8.976e-01  1.353e-01  -6.631 4.91e-11 ***
citric.acid          -1.476e-01  1.658e-01  -0.890  0.37350    
residual.sugar        1.332e-02  1.661e-02   0.802  0.42271    
chlorides            -1.348e+00  4.685e-01  -2.877  0.00409 ** 
free.sulfur.dioxide   5.388e-03  2.425e-03   2.222  0.02644 *  
total.sulfur.dioxide -3.473e-03  8.159e-04  -4.256 2.23e-05 ***
density              -2.049e+01  2.442e+01  -0.839  0.40161    
pH                   -3.562e-01  2.141e-01  -1.664  0.09638 .  
sulphates             8.711e-01  1.303e-01   6.687 3.42e-11 ***
alcohol               2.767e-01  2.986e-02   9.265  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.6506 on 1267 degrees of freedom
Multiple R-squared:  0.3383,    Adjusted R-squared:  0.3325 
F-statistic: 58.88 on 11 and 1267 DF,  p-value: < 2.2e-16

Question 4: Evaluate the performance of the model on the test data (use function predict) by computing the RSE and R-squared

Test Data:

RSE: 153400 on 87 degrees of freedom.

This means the RSE is very high based on our dataset. The R-squared value accounts for 3.18% of the total variation in the dependent variable.

Training Data:

RSE: 0.6437 on 1267 degrees of freedom.

This means the RSE is very low based on our dataset. Our R-squared value accounts for 37.54% of the total variation in the dependent variable.

Question 5: Interpret the results. Does the model appear to be overfitting or underfitting the data? How does its performance on the test data compare to its performance on the training data?

The model appears to be underfitting the data. A low R-squared means that the model is not accounting for a larger portion of the data, especially in the case of our Test Data. Thus we would need either a more complex model than our current simple model, or a lack of training data.

LS0tDQp0aXRsZTogIkhXIDQsIEdyb3VwIDMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyMjIFdlIHdpbGwgYmUgZXhhbWluaW5nIDMgdmFyaWFibGVzOiAobWVkaWFuKSBob3VzZSBwcmljZSB2cyBjb3ZpZCBpbmZlY3Rpb25zIHZzIHZhY2NpbmUgcmF0ZSByZWdhcmRpbmcgUGl0dHNidXJnaCBuZWlnaGJvcmhvb2RzLiBPdXIgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGFyZSBjb3ZpZCBpbmZlY3Rpb25zIGFuZCB2YWNjaW5lIHJhdGVzLCBhbmQgb3VyIGRlcGVuZGVudCB2YXJpYWJsZSBpcyAobWVkaWFuKSBob3VzZSBwcmljZXMgaW4gZWFjaCBuZWlnaGJvcmhvb2QuDQoNCiMjIyBEYXRhc2V0cyBVc2VkDQpbQ292aWQgSW5mZWN0aW9uc11baHR0cHM6Ly9kYXRhLndwcmRjLm9yZy9kYXRhc2V0L2FsbGVnaGVueS1jb3VudHktY292aWQtMTktdGVzdHMtY2FzZXMtYW5kLWRlYXRocy9yZXNvdXJjZS8wZjIxNDg4NS1mZjNlLTQ0ZTEtOTk2My1lOWU5MDYyYTA0ZDE/aW5uZXJfc3Bhbj1UcnVlXQ0KDQpbVmFjY2luZSBSZXBvcnRzXVtodHRwczovL2RhdGEud3ByZGMub3JnL2RhdGFzZXQvYWxsZWdoZW55LWNvdW50eS1jb3ZpZC0xOS12YWNjaW5hdGlvbnMvcmVzb3VyY2UvNjFhYjRhZDQtZmI4NC00Nzg5LTk1YzktY2JlMTE2NDE0Mjg3XQ0KDQpbSG91c2UgUHJpY2VzXVtodHRwczovL2RhdGEud3ByZGMub3JnL2RhdGFzZXQvcmVhbC1lc3RhdGUtc2FsZXMvcmVzb3VyY2UvNWJiZTZjNTUtYmNlNi00ZWRiLTlkMDQtNjhlZGViNmJmN2IxL3ZpZXcvZmMzMjIxN2UtMmYwZS00MzdkLTlmNjgtZjI5MjJkZmRmNzFmXQ0KDQojICoqUGFydCAxKioNCg0KIyMgTWVkaWFuIEhvdXNlIFByaWNlcyB2cyBDb3ZpZCBJbmZlY3Rpb25zDQpgYGB7cn0NCg0KI0hPVVNFIERBVEFTRVQNCmhvdXNlX2RhdGEgPSByZWFkLmNzdigiaG91c2Vfc2FsZXMuY3N2IikNCg0KI2ZpbHRlciB0byBwcmljZSA+MSwgc29tZSBhcmUgMCwgMSwgb3IgMiBmb3Igc29tZSByZWFzb24NCmhvdXNlX2RhdGEgPSBob3VzZV9kYXRhW2hvdXNlX2RhdGEkUFJJQ0UgPiAyLF0NCmNvbXBsZXRlID0gY29tcGxldGUuY2FzZXMoaG91c2VfZGF0YSkNCmhvdXNlX2RhdGEgPSBob3VzZV9kYXRhW2NvbXBsZXRlLCBdDQoNCiNmaWx0ZXIgaG91c2UgZGF0YSB0byBhZnRlciBDb3ZpZCBoaXQgc2luY2UgdGhpcyBkYXRhc2V0IGluY2x1ZGVzIGhvdXNlIHNhbGVzIGZyb20gMjAxMy1wcmVzZW50DQpob3VzZV9kYXRhJFNBTEVEQVRFID0gZ3N1YigiLyIsICItIiwgaG91c2VfZGF0YSRTQUxFREFURSkNCmhvdXNlX2RhdGEkU0FMRURBVEUgPSBhcy5EYXRlKGhvdXNlX2RhdGEkU0FMRURBVEUsIGZvcm1hdCA9ICIlbS0lZC0lWSIpDQpob3VzZV9kYXRhID0gc3Vic2V0KGhvdXNlX2RhdGEsIFNBTEVEQVRFID49IGFzLkRhdGUoIjIwMjAtMDYtMDEiKSkNCg0KI21ha2UgZGF0YWZyYW1lIGZvciBtZWRpYW4gaG91c2UgcHJpY2VzIGluIGVhY2ggbmVpZ2hib3Job29kDQptZWRpYW5faG91c2VfcHJpY2UgPSBhZ2dyZWdhdGUoaG91c2VfZGF0YSRQUklDRSwgYnkgPSBsaXN0KG5laWdoYm9yaG9vZCA9IGhvdXNlX2RhdGEkTVVOSURFU0MpLCBGVU4gPSBtZWRpYW4pDQpjb2xuYW1lcyhtZWRpYW5faG91c2VfcHJpY2UpID0gYygibmVpZ2hib3Job29kIiwgIm1lZGlhbl9wcmljZSIpDQptZWRpYW5faG91c2VfZGF0YSA9IG1lZGlhbl9ob3VzZV9wcmljZQ0KDQojcmVhZCBpbiBjb3ZpZCBkYXRhc2V0DQpjb3ZpZF9kYXRhID0gcmVhZC5jc3YoImNvdmlkX2RhdGEuY3N2IikNCg0KI3NvbWUgbmVpZ2hib3Job29kIG5hbWVzIGluIGNvdmlkX2RhdGEgaGF2ZSAiKFBpdHRzYnVyZ2gpIiwgdGFrZSB0aGF0IG91dA0KY292aWRfZGF0YSRuZWlnaGJvcmhvb2RfbXVuaWNpcGFsaXR5ID0gZ3N1YigiXFwoUGl0dHNidXJnaFxcKSIsICIiLCBjb3ZpZF9kYXRhJG5laWdoYm9yaG9vZF9tdW5pY2lwYWxpdHkpDQoNCiMgUmVtb3ZlIHNwZWNpYWwgYW5kIGNhcGl0YWwgY2hhcmFjdGVycyBpbiBib3RoIGRhdGFzZXRzIA0KbWVkaWFuX2hvdXNlX2RhdGEkbmVpZ2hib3Job29kID0gdG9sb3dlcihnc3ViKCJbXmEtejAtOV0rIiwgIiIsIG1lZGlhbl9ob3VzZV9kYXRhJG5laWdoYm9yaG9vZCwgcGVybCA9IFRSVUUpKQ0KY292aWRfZGF0YSRuZWlnaGJvcmhvb2RfbXVuaWNpcGFsaXR5ID0gdG9sb3dlcihnc3ViKCJbXmEtejAtOV0rIiwgIiIsIGNvdmlkX2RhdGEkbmVpZ2hib3Job29kX211bmljaXBhbGl0eSwgcGVybCA9IFRSVUUpKQ0KDQojbWVyZ2UgaG91c2VfZGF0YSBhbmQgY292aWRfZGF0YSBhY2NvcmRpbmcgdG8gbmVpZ2hib3Job29kDQpob3VzZV9hbmRfY292aWRfZGF0YSA9IG1lcmdlKGNvdmlkX2RhdGEsIG1lZGlhbl9ob3VzZV9kYXRhLCBieS54ID0gIm5laWdoYm9yaG9vZF9tdW5pY2lwYWxpdHkiLCBieS55ID0gIm5laWdoYm9yaG9vZCIpDQoNCiNsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBvbiBjb3ZpZCBjYXNlcyBhbmQgaG91c2UgcHJpY2VzIGluIFBpdHRzYnVyZ2ggbmVpZ2hib3Job29kcw0KDQpsbV9tb2RlbDEgPSBsbShob3VzZV9hbmRfY292aWRfZGF0YSRtZWRpYW5fcHJpY2UgfiBob3VzZV9hbmRfY292aWRfZGF0YSRpbmZlY3Rpb25zLCBkYXRhID0gaG91c2VfYW5kX2NvdmlkX2RhdGEpDQpzdW1tYXJ5KGxtX21vZGVsMSkNCg0KI3Bsb3QgbW9kZWwNCnBsb3QoaG91c2VfYW5kX2NvdmlkX2RhdGEkaW5mZWN0aW9ucywgaG91c2VfYW5kX2NvdmlkX2RhdGEkbWVkaWFuX3ByaWNlLCB4bGFiID0gIkNvdmlkIEluZmVjdGlvbnMiLCB5bGFiID0gIk1lZGlhbiBIb3VzZSBQcmljZXMiLCBtYWluID0gIkNvdmlkIEluZmVjdGlvbnMgdnMgTWVkaWFuIEhvdXNlIFByaWNlcyIpDQphYmxpbmUobG1fbW9kZWwxLCBjb2w9ImJsdWUiKQ0KDQoNCiNjb3JyZWxhdGlvbiBiZXR3ZWVuIGNvdmlkIGluZmVjdGlvbnMgYW5kIGhvdXNlIHByaWNlcw0KY29ycmVsYXRpb24gPSBjb3IoaG91c2VfYW5kX2NvdmlkX2RhdGEkbWVkaWFuX3ByaWNlLCBob3VzZV9hbmRfY292aWRfZGF0YSRpbmZlY3Rpb25zKQ0KY29ycmVsYXRpb25fdGVzdCA9IGNvci50ZXN0KGhvdXNlX2FuZF9jb3ZpZF9kYXRhJG1lZGlhbl9wcmljZSwgaG91c2VfYW5kX2NvdmlkX2RhdGEkaW5mZWN0aW9ucykNCmNvcnJlbGF0aW9uX3Rlc3QNCmNhdCgiY29ycmVsYXRpb24gY29lZmZpY2llbnQgYmV0d2VlbiBjb3ZpZCBjYXNlcyBhbmQgaG91c2UgcHJpY2VzIiwgY29ycmVsYXRpb24pDQoNCiNnZXQgc2xvcGUgb2YgZml0dGVkIGxpbmUNCnNsb3BlMSA9IGNvZWYobG1fbW9kZWwxKVsyXSAgIA0KDQpjYXQoIg0KICAgIHNsb3BlIG9mIGZpdHRlZCBsaW5lIiwgc2xvcGUxKQ0KDQpgYGANCiMjIyMgKipBbmFseXNpcyBvZiBDb3ZpZCBJbmZlY3Rpb25zIHZzIEhvdXNlIFByaWNlcyoqDQoNCkxvb2tpbmcgYXQgdGhlIHBsb3QsIHRoZXJlIHNlZW1zIHRvIGJlIG5vIGNvcnJlbGF0aW9uIGFuZCBubyBhcHBhcmVudCB0cmVuZHMgYmV0d2VlbiBjb3ZpZCBpbmZlY3Rpb25zIGFuZCBtZWRpYW4gaG91c2UgcHJpY2VzIGluIFBpdHRzYnVyZ2ggbmVpZ2hib3Job29kcy4gRXZlbiBhcyBjb3ZpZCBpbmZlY3Rpb25zIGluY3JlYXNlLCBtZWRpYW4gaG91c2UgcHJpY2VzIHRlbmQgdG8gc3RheSB0aGUgc2FtZS4gVGhlIHNsb3BlIG9mIHRoZSBmaXR0ZWQgbGluZSB0byB0aGUgcmVncmVzc2lvbiBtb2RlbCBpcyBjbG9zZSB0byAwLCBpbmRpY2F0aW5nIHRoYXQgdGhlcmUgaXMgbm8gYXBwYXJlbnQgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgdHdvIHZhcmlhYmxlcy4gVGhpcyBpcyBmdXJ0aGVyIHByb3ZlbiBhcyB0aGUgcC12YWx1ZSBvYnRhaW5lZCBmcm9tIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCBiZXR3ZWVuIHRoZSB0d28gaXMgMC45NDA1LCBtZWFuaW5nIHRoZSBtb2RlbCBpcyBub3Qgc2lnbmlmaWNhbnQ7IEZ1cnRoZXJtb3JlLCB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgaXMgY2xvc2UgdG8gMCwgdGh1cyB0aGVyZSBpcyBjbG9zZSB0byBubyBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gaG91c2UgcHJpY2VzIGFuZCBjb3ZpZCBpbmZlY3Rpb25zLiANCg0KIyMgTWVkaWFuIEhvdXNlIFByaWNlcyB2cyBWYWNjaW5lIFJhdGUNCg0KYGBge3J9DQojIHJlYWQgaW4gdmFjY2luZSBkYXRhc2V0DQp2YWNjaW5lX2RhdGEgPSByZWFkLmNzdigidmFjY2luZS5jc3YiKQ0KDQojc29tZSBuZWlnaGJvcmhvb2QgbmFtZXMgaGF2ZSAiKFBpdHRzYnVyZ2gpIiwgdGFrZSB0aGF0IG91dA0KdmFjY2luZV9kYXRhJG5laWdoYm9yaG9vZF9tdW5pY2lwYWxpdHkgPSBnc3ViKCJcXChQaXR0c2J1cmdoXFwpIiwgIiIsIHZhY2NpbmVfZGF0YSRuZWlnaGJvcmhvb2RfbXVuaWNpcGFsaXR5KQ0KDQojIFJlbW92ZSBzcGVjaWFsIGFuZCBjYXBpdGFsIGNoYXJhY3RlcnMgDQp2YWNjaW5lX2RhdGEkbmVpZ2hib3Job29kX211bmljaXBhbGl0eSA9IHRvbG93ZXIoZ3N1YigiW15hLXowLTldKyIsICIiLCBjb3ZpZF9kYXRhJG5laWdoYm9yaG9vZF9tdW5pY2lwYWxpdHksIHBlcmwgPSBUUlVFKSkNCg0KI21lcmdlIG1lZGlhbl9ob3VzZV9kYXRhIGFuZCB2YWNjaW5lX2RhdGEgYWNjb3JkaW5nIHRvIG5laWdoYm9yaG9vZA0KaG91c2VfYW5kX3ZhY2NpbmVfZGF0YSA9IG1lcmdlKHZhY2NpbmVfZGF0YSwgbWVkaWFuX2hvdXNlX2RhdGEsIGJ5LnggPSAibmVpZ2hib3Job29kX211bmljaXBhbGl0eSIsIGJ5LnkgPSAibmVpZ2hib3Job29kIikNCg0KI2xpbmVhciByZWdyZXNzaW9uIG1vZGVsIG9uIHZhY2NpbmUgY291bnQgYW5kIG1lZCBob3VzZSBwcmljZXMgaW4gUGl0dHNidXJnaCBuZWlnaGJvcmhvb2RzDQoNCmxtX21vZGVsMiA9IGxtKGhvdXNlX2FuZF92YWNjaW5lX2RhdGEkbWVkaWFuX3ByaWNlIH4gaG91c2VfYW5kX3ZhY2NpbmVfZGF0YSRiaXZhbGVudF9ib29zdGVyLCBkYXRhID0gaG91c2VfYW5kX3ZhY2NpbmVfZGF0YSkNCnN1bW1hcnkobG1fbW9kZWwyKQ0KDQojcGxvdCBtb2RlbA0KcGxvdChob3VzZV9hbmRfdmFjY2luZV9kYXRhJGJpdmFsZW50X2Jvb3N0ZXIsIGhvdXNlX2FuZF92YWNjaW5lX2RhdGEkbWVkaWFuX3ByaWNlLCBtYWluID0gIlZhY2NpbmUgUmF0ZSB2cyBNZWRpYW4gSG91c2UgUHJpY2VzIiwgeWxhYiA9ICJNZWRpYW4gSG91c2UgUHJpY2VzIiwgeGxhYiA9ICJWYWNjaW5lIFJhdGUiKQ0KYWJsaW5lKGxtX21vZGVsMSwgY29sPSJibHVlIikNCg0KI2NvcnJlbGF0aW9uIGJldHdlZW4gY292aWQgaW5mZWN0aW9ucyBhbmQgaG91c2UgcHJpY2VzDQpjb3JyZWxhdGlvbjIgPSBjb3IoaG91c2VfYW5kX3ZhY2NpbmVfZGF0YSRtZWRpYW5fcHJpY2UsIGhvdXNlX2FuZF92YWNjaW5lX2RhdGEkYml2YWxlbnRfYm9vc3RlcikNCmNvcnJlbGF0aW9uX3Rlc3QyID0gY29yLnRlc3QoaG91c2VfYW5kX3ZhY2NpbmVfZGF0YSRtZWRpYW5fcHJpY2UsIGhvdXNlX2FuZF92YWNjaW5lX2RhdGEkYml2YWxlbnRfYm9vc3RlcikNCmNvcnJlbGF0aW9uX3Rlc3QyDQpjYXQoImNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGJldHdlZW4gY292aWQgdmFjY2luZSByYXRlIGFuZCBob3VzZSBwcmljZXMiLCBjb3JyZWxhdGlvbjIpDQoNCiNnZXQgc2xvcGUgb2YgZml0dGVkIGxpbmUNCnNsb3BlMiA9IGNvZWYobG1fbW9kZWwyKVsyXSAgIA0KDQpjYXQoIg0KICAgIHNsb3BlIG9mIGZpdHRlZCBsaW5lIiwgc2xvcGUyKQ0KYGBgDQojIyMjICoqQW5hbHlzaXMgb2YgVmFjY2luZSBSYXRlIHZzIEhvdXNlIFByaWNlcyoqDQoNCkxvb2tpbmcgYXQgdGhlIHBsb3QsIHRoZXJlIHNlZW1zIHRvIGJlIG5vIGNvcnJlbGF0aW9uIGFuZCBubyBhcHBhcmVudCB0cmVuZHMgYmV0d2VlbiB0aGUgdmFjY2luZSByYXRlIGFuZCBtZWRpYW4gaG91c2UgcHJpY2VzIGluIFBpdHRzYnVyZ2ggbmVpZ2hib3Job29kcy4gVGhlIHNsb3BlIG9mIHRoZSBmaXR0ZWQgbGluZSB0byB0aGUgcmVncmVzc2lvbiBtb2RlbCBpcyBhYm91dCAtNyAoYSBzbWFsbCB2YWx1ZSBpbiBjb21wYXJpc29uIHRvIHRoZSBudW1iZXJzIHVzZWQgaW4gdGhlIGRhdGEpLCBpbmRpY2F0aW5nIHRoYXQgdGhlcmUgaXMgbm8gbm90aWNlYWJsZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSB0d28gdmFyaWFibGVzLiBUaGlzIGlzIGZ1cnRoZXIgcHJvdmVuIGFzIHRoZSBwLXZhbHVlIG9idGFpbmVkIGZyb20gdGhlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIGJldHdlZW4gdGhlIHR3byBpcyAwLjQ2MiwgbWVhbmluZyB0aGUgbW9kZWwgaXMgbm90IHNpZ25pZmljYW50OyBGdXJ0aGVybW9yZSwgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IGlzIGNsb3NlIHRvIDAsIHRodXMgdGhlcmUgaXMgY2xvc2UgdG8gbm8gbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGhvdXNlIHByaWNlcyBhbmQgY292aWQgaW5mZWN0aW9ucy4gDQoNCg0KIyMgQ29saW5lYXJpdHkgYmV0d2VlbiBDb3ZpZCBJbmZlY3Rpb25zIGFuZCBWYWNjaW5lIFJhdGUNCmBgYHtyfQ0KI2NoZWNrIGZvciBjb2xpbmVhcml0eSBiZXR3ZWVuIHZhY2NpbmUgcmF0ZSBhbmQgY292aWQgY2FzZXMNCg0KI21lcmdlIGNvdmlkIGluZmVjdGlvbnMsIHZhY2NpbmUgcmF0ZSwgYW5kIG1lZCBob3VzZSBwcmljZXMgaW50byBvbmUgZGF0YXNldA0KYWxsX2RhdGEgPSBtZXJnZShob3VzZV9hbmRfY292aWRfZGF0YSwgaG91c2VfYW5kX3ZhY2NpbmVfZGF0YSwgYnkgPSAibmVpZ2hib3Job29kX211bmljaXBhbGl0eSIpDQoNCiMxKSBwbG90IGNvdmlkIGluZmVjdGlvbnMgdnMgaG91c2UgcHJpY2VzDQpwbG90KGhvdXNlX2FuZF9jb3ZpZF9kYXRhJGluZmVjdGlvbnMsIGhvdXNlX2FuZF9jb3ZpZF9kYXRhJG1lZGlhbl9wcmljZSwgeGxhYiA9ICJDb3ZpZCBJbmZlY3Rpb25zIiwgeWxhYiA9ICJNZWRpYW4gSG91c2UgUHJpY2VzIiwgbWFpbiA9ICJDb3ZpZCBJbmZlY3Rpb25zIHZzIE1lZGlhbiBIb3VzZSBQcmljZXMiKQ0KDQojbG0gYmV0d2VlbiBjb3ZpZCBpbmZlY3Rpb25zIGFuZCBob3VzZSBwcmljZXMNCnN1bW1hcnkobG0oaG91c2VfYW5kX2NvdmlkX2RhdGEkbWVkaWFuX3ByaWNlIH4gaG91c2VfYW5kX2NvdmlkX2RhdGEkaW5mZWN0aW9ucywgZGF0YSA9IGFsbF9kYXRhKSkNCg0KIzIpIHBsb3QgdmFjY2luZSByYXRlIHZzIGhvdXNlIHByaWNlcw0KcGxvdChob3VzZV9hbmRfdmFjY2luZV9kYXRhJGJpdmFsZW50X2Jvb3N0ZXIsIGhvdXNlX2FuZF92YWNjaW5lX2RhdGEkbWVkaWFuX3ByaWNlLCBtYWluID0gIlZhY2NpbmUgUmF0ZSB2cyBNZWRpYW4gSG91c2UgUHJpY2VzIiwgeWxhYiA9ICJNZWRpYW4gSG91c2UgUHJpY2VzIiwgeGxhYiA9ICJWYWNjaW5lIFJhdGUiKQ0KDQojbG0gYmV0d2VlbiB2YWNjaW5lIHJhdGUgYW5kIGhvdXNlIHByaWNlcw0Kc3VtbWFyeShsbShhbGxfZGF0YSRtZWRpYW5fcHJpY2UueCB+IGhvdXNlX2FuZF92YWNjaW5lX2RhdGEkYml2YWxlbnRfYm9vc3RlciwgZGF0YSA9IGFsbF9kYXRhKSkNCg0KIzMpIHBsb3QgdGhlIHR3byBpbmRlcGVuZGVudCB2YXJpYWJsZXMgDQpwbG90KGFsbF9kYXRhJGluZmVjdGlvbnMsIGFsbF9kYXRhJGJpdmFsZW50X2Jvb3N0ZXIsIG1haW4gPSAiVmFjY2luZSBSYXRlIHZzIENvdmlkIEluZmVjdGlvbnMiLCB5bGFiID0gIlZhY2NpbmUgUmF0ZSIsIHhsYWIgPSAiQ292aWQgSW5mZWN0aW9ucyIpDQoNCiNsaW5lYXIgbW9kZWwgYmV0d2VlbiB0aGUgdHdvIGluZGVwZW5kZW50IHZhcmlhYmxlcw0KbG1fbW9kZWwzID0gbG0oYWxsX2RhdGEkbWVkaWFuX3ByaWNlLnggfiBhbGxfZGF0YSRpbmZlY3Rpb25zICsgYWxsX2RhdGEkYml2YWxlbnRfYm9vc3RlciwgZGF0YSA9IGFsbF9kYXRhKQ0KDQojc3VtbWFyeSBvZiBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbA0Kc3VtbWFyeShsbV9tb2RlbDMpDQoNCmBgYA0KIyMjIEFuYWx5c2lzIG9mIENvbGluZWFyaXR5IGJldHdlZW4gQ292aWQgSW5mZWN0aW9ucyBhbmQgVmFjY2luZSBSYXRlDQoNCkxvb2tpbmcgYXQgdGhlIHBsb3QgdGhhdCBzaG93cyBubyB0cmVuZCBiZXR3ZWVuIHRoZSB0d28gaW5kZXBlbmRlbnQgdmFyaWFibGVzIGFuZCB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwncyBwLXZhbHVlIG9mIDAuNzYzOSwgdGhlIHR3byBkbyBub3Qgc2VlbSB0byBiZSBjb2xpbmVhci4gVGh1cywgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24gaXMgbm90IG5lZWRlZCBhbmQgc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uIHNob3VsZCBzdWZmaWNlDQoNCg0KIyMjICoqQ29tYmluZSB0aGVzZSB2YXJpYWJsZXMgaW4gYSBtdWx0aXBsZSByZWdyZXNzaW9uIG1vZGVsIGFuZCBhbmFseXplIHRoZSByZXN1bHRzLioqDQoNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCg0KI1JlYWQgYW5kIHJlbmFtZSBmaWxlcw0KaG91c2luZ19wcmljZXMgPC0gcmVhZC5jc3YoImhvdXNlX3NhbGVzLmNzdiIpDQojY2hhbmdlIG5hbWUNCmhvdXNpbmdfcHJpY2VzIDwtIGhvdXNpbmdfcHJpY2VzICU+JSByZW5hbWUobmVpZ2hib3Job29kID0gTVVOSURFU0MpDQoNCiNyZW1vdmUgdHJhaWxpbmcgc3BjZXMgDQpob3VzaW5nX3ByaWNlcyRuZWlnaGJvcmhvb2QgPC0gdHJpbXdzKGhvdXNpbmdfcHJpY2VzJG5laWdoYm9yaG9vZCkNCg0KIyBjb3ZlcnQgU0FMRURBVEUgDQpob3VzaW5nX3ByaWNlcyRTQUxFREFURSA8LSBhcy5EYXRlKGhvdXNpbmdfcHJpY2VzJFNBTEVEQVRFLCBmb3JtYXQgPSAiJW0vJWQvJXkiKQ0KDQojIGZpbHRlciB0byBvbmx5IHNhbGVzIGFmdGVyIGNvdmlkIA0KaG91c2luZ19wcmljZXMgPC0gaG91c2luZ19wcmljZXMgJT4lDQogIGZpbHRlcihTQUxFREFURSA+IGFzLkRhdGUoIjIwMjAtMDYtMDEiKSkNCg0KdmFjY2luZXMgPC0gcmVhZC5jc3YoInZhY2NpbmUuY3N2IikNCg0KI2NoYW5nZSBuYW1lIA0KdmFjY2luZXMgPC0gdmFjY2luZXMgJT4lIHJlbmFtZShuZWlnaGJvcmhvb2QgPSBuZWlnaGJvcmhvb2RfbXVuaWNpcGFsaXR5KQ0KDQpjb3ZpZF9jYXNlcyA8LSByZWFkLmNzdigiY292aWRfZGF0YS5jc3YiKQ0KDQojY2hhbmdlIG5hbWUNCmNvdmlkX2Nhc2VzIDwtIGNvdmlkX2Nhc2VzICU+JSByZW5hbWUobmVpZ2hib3Job29kID0gbmVpZ2hib3Job29kX211bmljaXBhbGl0eSkNCmBgYA0KR3JvdXAgYnkgbmVpZ2hib3Job29kIGFuZCBjYWxjdWxhdGUgc3VtbWFyeQ0KYGBge3J9DQojcmVtb3ZlIGVtcHR5DQpob3VzaW5nX3ByaWNlcyA8LSBob3VzaW5nX3ByaWNlcyAlPiUNCiAgZmlsdGVyKCFpcy5uYShQUklDRSkpDQoNCiNtZWFuIHByaWNlIG9mIGVhY2ggbmVpZ2hib3Job29kDQpob3VzaW5nX3ByaWNlc19zdW1tYXJ5IDwtIGhvdXNpbmdfcHJpY2VzICU+JQ0KICBncm91cF9ieShuZWlnaGJvcmhvb2QpICU+JQ0KICBzdW1tYXJpemUobWVhbl9ob3VzaW5nX3ByaWNlID0gbWVhbihQUklDRSwgbmEucm0gPSBUUlVFKSkNCg0KI21lcmdlIGV2ZXJ5dGhpbmcgDQp2YWNjaW5lc19zdW1tYXJ5IDwtIHZhY2NpbmVzICU+JQ0KICBncm91cF9ieShuZWlnaGJvcmhvb2QpICU+JQ0KICBzdW1tYXJpemUodG90YWxfdmFjY2luYXRpb25zID0gYml2YWxlbnRfYm9vc3RlcikNCg0KY292aWRfY2FzZXNfc3VtbWFyeSA8LSBjb3ZpZF9jYXNlcyAlPiUNCiAgZ3JvdXBfYnkobmVpZ2hib3Job29kKSAlPiUNCiAgc3VtbWFyaXplKHRvdGFsX2NvdmlkX2Nhc2VzID0gaW5mZWN0aW9ucykNCg0KbWVyZ2VkX2RhdGEgPC0gbWVyZ2UoaG91c2luZ19wcmljZXNfc3VtbWFyeSwgY292aWRfY2FzZXNfc3VtbWFyeSwgYnkgPSAibmVpZ2hib3Job29kIikNCg0KbWVyZ2VkX2RhdGEgPC0gbWVyZ2UobWVyZ2VkX2RhdGEsIHZhY2NpbmVzX3N1bW1hcnksIGJ5ID0gIm5laWdoYm9yaG9vZCIpDQpgYGANCk11bGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24NCmBgYHtyfQ0KbXVsdGlfbG0gPC0gbG0obWVhbl9ob3VzaW5nX3ByaWNlIH4gdG90YWxfY292aWRfY2FzZXMgKyB0b3RhbF92YWNjaW5hdGlvbnMsIGRhdGEgPSBtZXJnZWRfZGF0YSkNCg0KDQpzdW1tYXJ5KG11bHRpX2xtKQ0KDQojcGxvdA0KcGxvdChtZXJnZWRfZGF0YSR0b3RhbF9jb3ZpZF9jYXNlcywgbWVyZ2VkX2RhdGEkbWVhbl9ob3VzaW5nX3ByaWNlLCB4bGFiID0gIkNvdmlkIENhc2VzIiwgeWxhYiA9ICJIb3VzZSBQcmljZXMiKQ0KDQpwbG90KG1lcmdlZF9kYXRhJHRvdGFsX3ZhY2NpbmF0aW9ucywgbWVyZ2VkX2RhdGEkbWVhbl9ob3VzaW5nX3ByaWNlLCB4bGFiID0gIlZhY2NpbmF0aW9ucyIsIHlsYWIgPSAiSG91c2UgUHJpY2VzIikNCg0KcGxvdChtZXJnZWRfZGF0YSR0b3RhbF9jb3ZpZF9jYXNlcywgbWVyZ2VkX2RhdGEkdG90YWxfdmFjY2luYXRpb25zLCB4bGFiID0gIkNvdmlkIENhc2VzIiwgeWxhYiA9ICJWYWNjaW5hdGlvbnMiKQ0KYGBgDQoNCioqV2hpY2ggdmFyaWFibGVzIGFyZSBzaWduaWZpY2FudD8gKioNCkJvdGggdG90YWwgY292aWQgY2FzZXMgYW5kIHRvdGFsIHZhY2NpbmF0aW9ucyBoYXZlIGhpZ2ggcCB2YWx1ZXMsIGdyZWF0ZXIgdGhhbiAwLjA1IHdoaWNoIGluZGljYXRlcyB0aGF0IHRoZXkgYXJlIG5vdCBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50Lg0KDQoqKldoYXQgaXMgdGhlIG1vZGVsIGZpdD8gKioNClRoZSBtdWx0aXBsZSBSLXNxdWFyZWQgdmFsdWUgaXMgMC4wMzIxMy4gVGhpcyBtZWFucyB0aGF0IHRvdGFsIGNvdmlkIGNhc2VzIGFuZCB0b3RhbCB2YWNjaW5hdGlvbnMgb25seSBleHBsYWluIDMuMjElIG9mIHRoZSBkYXRhIGluIGhvdXNpbmcgcHJpY2VzLg0KDQoqKlJlc2lkdWFsIGVycm9yIGRpZmZlcmVuY2UgYmV0d2VlbiBkaWZmZXJlbnQgbW9kZWxzOioqDQpBIHJlc2lkdWFsIGVycm9yIG9mIDE2NjMwMCBpcyBoaWdoLCBzdWdnZXN0aW5nIHRoYXQgdGhlIG1vZGVsIGhhcyBhIGhpZ2ggYW1vdW50IG9mIHVuZXhwbGFpbmVkIHZhcmlhYmlsaXR5LiBJdCBtaWdodCBiZSBsb3dlciB3aGVuIGxvb2tpbmcgYXQgc2ltcGxlIHJlZ3Jlc3Npb24gbW9kZWxzLg0KDQoqKkluc2lnaHRzIGZyb20gUi1zcXVhcmVkIGVycm9yOioqDQpBZGp1c3RlZCBSLXNxdWFyZWQgaXMgZXZlbiBsb3dlciB0aGFuIFItc3F1YXJlZCwgYWdhaW4gbWVhbmluZyB0b3RhbCBjb3ZpZCBjYXNlcyBhbmQgdG90YWwgdmFjY2luYXRpb25zIG1heSBub3QgYmUgc3Ryb25nIHZhcmlhYmxlcyBpbiBleHBsYWluaW5nIGhvdXNpbmcgcHJpY2VzLg0KDQojICoqUGFydCAyKioNCg0KIyMjIFF1ZXN0aW9uIDI6IFNwbGl0IHRoZSBkYXRhc2V0IHJhbmRvbWx5IGludG8gdHJhaW5pbmcgKDgwJSkgYW5kIHRlc3QgKDIwJSkgc2V0cy4gKFVzZSB5b3VyIGtub3dsZWRnZSBvbiBnZW5lcmF0aW5nIHJhbmRvbSBudW1iZXJzIHRvIGNyZWF0ZSB0aGUgc3BsaXRzKQ0KDQpMb2FkaW5nIGluIHRoZSBkYXRhc2V0cyBhbmQgZWRpdGluZw0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KDQpob3VzaW5nX3ByaWNlcyA8LSByZWFkLmNzdigiaG91c2Vfc2FsZXMuY3N2IikNCmhvdXNpbmdfcHJpY2VzIDwtIGhvdXNpbmdfcHJpY2VzICU+JSByZW5hbWUobmVpZ2hib3Job29kID0gTVVOSURFU0MpDQpob3VzaW5nX3ByaWNlcyRuZWlnaGJvcmhvb2QgPC0gdHJpbXdzKGhvdXNpbmdfcHJpY2VzJG5laWdoYm9yaG9vZCkNCmhvdXNpbmdfcHJpY2VzJFNBTEVEQVRFIDwtIGFzLkRhdGUoaG91c2luZ19wcmljZXMkU0FMRURBVEUsIGZvcm1hdCA9ICIlbS0lZC0leSIpDQoNCnZhY2NpbmVzIDwtIHJlYWQuY3N2KCJ2YWNjaW5lLmNzdiIpDQp2YWNjaW5lcyA8LSB2YWNjaW5lcyAlPiUgcmVuYW1lKG5laWdoYm9yaG9vZCA9IG5laWdoYm9yaG9vZF9tdW5pY2lwYWxpdHkpDQoNCmNvdmlkX2Nhc2VzIDwtIHJlYWQuY3N2KCJjb3ZpZF9kYXRhLmNzdiIpDQpjb3ZpZF9jYXNlcyA8LSBjb3ZpZF9jYXNlcyAlPiUgcmVuYW1lKG5laWdoYm9yaG9vZCA9IG5laWdoYm9yaG9vZF9tdW5pY2lwYWxpdHkpDQoNCmBgYA0KTWVyZ2luZyBkYXRhc2V0cyBpbnRvIG9uZSBzZXQNCmBgYHtyfQ0KaG91c2luZ19wcmljZXMgPC0gaG91c2luZ19wcmljZXMgJT4lDQogIGZpbHRlcighaXMubmEoUFJJQ0UpKQ0KaG91c2luZ19wcmljZXNfc3VtbWFyeSA8LSBob3VzaW5nX3ByaWNlcyAlPiUNCiAgZ3JvdXBfYnkobmVpZ2hib3Job29kKSAlPiUNCiAgc3VtbWFyaXplKG1lYW5faG91c2luZ19wcmljZSA9IG1lYW4oUFJJQ0UpLCBuYS5ybSA9IFRSVUUpDQoNCnZhY2NpbmVzX3N1bW1hcnkgPC0gdmFjY2luZXMgJT4lDQogIGdyb3VwX2J5KG5laWdoYm9yaG9vZCkgJT4lDQogIHN1bW1hcml6ZSh0b3RhbF92YWNjaW5hdGlvbnMgPSBiaXZhbGVudF9ib29zdGVyKQ0KDQpjb3ZpZF9jYXNlc19zdW1tYXJ5IDwtIGNvdmlkX2Nhc2VzICU+JQ0KICBncm91cF9ieShuZWlnaGJvcmhvb2QpICU+JQ0KICBzdW1tYXJpemUodG90YWxfY292aWRfY2FzZXMgPSBpbmZlY3Rpb25zKQ0KDQptZXJnZWRfZGF0YSA8LSBtZXJnZShob3VzaW5nX3ByaWNlc19zdW1tYXJ5LCBjb3ZpZF9jYXNlc19zdW1tYXJ5LCBieSA9ICJuZWlnaGJvcmhvb2QiKQ0KbWVyZ2VkX2RhdGEgPC0gbWVyZ2UobWVyZ2VkX2RhdGEsIHZhY2NpbmVzX3N1bW1hcnksIGJ5ID0gIm5laWdoYm9yaG9vZCIpDQpgYGANCg0KIyMjIFF1ZXN0aW9uIDM6IEZpdCBhIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHRvIHRoZSB0cmFpbmluZyBkYXRhLCB1c2luZyBhbGwgdGhlIHZhcmlhYmxlcyBpbiB0aGUgZGF0YXNldCB0byBwcmVkaWN0IHdpbmUgcXVhbGl0eQ0KDQpTcGxpdHRpbmcgZGF0YSBpbnRvIHRyYWluaW5nIGFuZCB0ZXN0IHNldHMNCmBgYHtyfQ0KdHJhaW5pbmdfc2V0IDwtIG1lcmdlZF9kYXRhICU+JSBkcGx5cjo6c2FtcGxlX2ZyYWMoMC44KQ0KdGVzdGluZ19zZXQgPC0gZHBseXI6OmFudGlfam9pbihtZXJnZWRfZGF0YSwgdHJhaW5pbmdfc2V0LCBieSA9ICJuZWlnaGJvcmhvb2QiKQ0KDQp0cmFpbmluZ19tbHIgPC0gbG0obWVhbl9ob3VzaW5nX3ByaWNlIH4gdG90YWxfY292aWRfY2FzZXMgKyB0b3RhbF92YWNjaW5hdGlvbnMsIGRhdGEgPSB0cmFpbmluZ19zZXQpDQpzdW1tYXJ5KHRyYWluaW5nX21scikNCg0Kd2luZV9xdWFsaXR5ID0gcmVhZC5jc3YoIndpbmVxdWFsaXR5LXJlZC5jc3YiKQ0Kd2luZV90cmFpbmluZ19zZXQgPC0gd2luZV9xdWFsaXR5ICU+JSBkcGx5cjo6c2FtcGxlX2ZyYWMoMC44KQ0Kd2luZV90ZXN0aW5nX3NldCA8LSBkcGx5cjo6YW50aV9qb2luKHdpbmVfcXVhbGl0eSwgd2luZV90cmFpbmluZ19zZXQsIGJ5ID0gInF1YWxpdHkiKQ0KDQp3aW5lX21sciA8LSBsbShxdWFsaXR5IH4gZml4ZWQuYWNpZGl0eSArIHZvbGF0aWxlLmFjaWRpdHkgKyBjaXRyaWMuYWNpZCArIHJlc2lkdWFsLnN1Z2FyICsgY2hsb3JpZGVzICsgZnJlZS5zdWxmdXIuZGlveGlkZSArIHRvdGFsLnN1bGZ1ci5kaW94aWRlICsgZGVuc2l0eSArIHBIICsgc3VscGhhdGVzICsgYWxjb2hvbCwgZGF0YSA9IHdpbmVfdHJhaW5pbmdfc2V0KQ0KDQpzdW1tYXJ5KHdpbmVfbWxyKQ0KYGBgDQoNCiMjIyBRdWVzdGlvbiA0OiBFdmFsdWF0ZSB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIG1vZGVsIG9uIHRoZSB0ZXN0IGRhdGEgKHVzZSBmdW5jdGlvbiBwcmVkaWN0KSBieSBjb21wdXRpbmcgdGhlIFJTRSBhbmQgUi1zcXVhcmVkDQoNCioqVGVzdCBEYXRhOioqDQoNClJTRTogMTUzNDAwIG9uIDg3IGRlZ3JlZXMgb2YgZnJlZWRvbS4NCg0KVGhpcyBtZWFucyB0aGUgUlNFIGlzIHZlcnkgaGlnaCBiYXNlZCBvbiBvdXIgZGF0YXNldC4gVGhlIFItc3F1YXJlZCB2YWx1ZSBhY2NvdW50cyBmb3IgMy4xOCUgb2YgdGhlIHRvdGFsIHZhcmlhdGlvbiBpbiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLg0KDQoqKlRyYWluaW5nIERhdGE6KioNCg0KUlNFOiAwLjY0Mzcgb24gMTI2NyBkZWdyZWVzIG9mIGZyZWVkb20uDQoNClRoaXMgbWVhbnMgdGhlIFJTRSBpcyB2ZXJ5IGxvdyBiYXNlZCBvbiBvdXIgZGF0YXNldC4gT3VyIFItc3F1YXJlZCB2YWx1ZSBhY2NvdW50cyBmb3IgMzcuNTQlIG9mIHRoZSB0b3RhbCB2YXJpYXRpb24gaW4gdGhlIGRlcGVuZGVudCB2YXJpYWJsZS4NCg0KDQojIyMgUXVlc3Rpb24gNTogSW50ZXJwcmV0IHRoZSByZXN1bHRzLiBEb2VzIHRoZSBtb2RlbCBhcHBlYXIgdG8gYmUgb3ZlcmZpdHRpbmcgb3IgdW5kZXJmaXR0aW5nIHRoZSBkYXRhPyBIb3cgZG9lcyBpdHMgcGVyZm9ybWFuY2Ugb24gdGhlIHRlc3QgZGF0YSBjb21wYXJlIHRvIGl0cyBwZXJmb3JtYW5jZSBvbiB0aGUgdHJhaW5pbmcgZGF0YT8NCg0KVGhlIG1vZGVsIGFwcGVhcnMgdG8gYmUgdW5kZXJmaXR0aW5nIHRoZSBkYXRhLiBBIGxvdyBSLXNxdWFyZWQgbWVhbnMgdGhhdCB0aGUgbW9kZWwgaXMgbm90IGFjY291bnRpbmcgZm9yIGEgbGFyZ2VyIHBvcnRpb24gb2YgdGhlIGRhdGEsIGVzcGVjaWFsbHkgaW4gdGhlIGNhc2Ugb2Ygb3VyIFRlc3QgRGF0YS4gVGh1cyB3ZSB3b3VsZCBuZWVkIGVpdGhlciBhIG1vcmUgY29tcGxleCBtb2RlbCB0aGFuIG91ciBjdXJyZW50IHNpbXBsZSBtb2RlbCwgb3IgYSBsYWNrIG9mIHRyYWluaW5nIGRhdGEuDQoNCg0K