Question 1: Set the random seed at 470.

Develop a linear regression model to predict heart_disease_mortality_per_100k using the LASSO method based on the training data set, using 10-fold cross validation to select lambda.

How many variables are selected if we use lambda.1se?

glmnet

install.packages("glmnet")
WARNING: Rtools is required to build R packages but is not currently installed. Please download and install the appropriate version of Rtools before proceeding:

https://cran.rstudio.com/bin/windows/Rtools/
Installing package into ‘C:/Users/grace/AppData/Local/R/win-library/4.5’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/bin/windows/contrib/4.5/glmnet_4.1-8.zip'
Content type 'application/zip' length 2474797 bytes (2.4 MB)
downloaded 2.4 MB
package ‘glmnet’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\grace\AppData\Local\Temp\RtmpkNTMn8\downloaded_packages
library(glmnet)
Loading required package: Matrix
Loaded glmnet 4.1-8

set seed

set.seed(470)

Data

library(janitor)

Attaching package: ‘janitor’

The following objects are masked from ‘package:stats’:

    chisq.test, fisher.test
train_data <- Heart_disease_mortality_train
Error: object 'Heart_disease_mortality_train' not found
train_data <- na.omit(train_data)

Prep

y <- train_data$heart_disease_mortality_per_100k
X <- model.matrix(heart_disease_mortality_per_100k ~ ., train_data)[, -1]

Lasso

lasso_cv <- cv.glmnet(X, y, alpha = 1, nfolds = 10)

Lambda

coef_lasso <- coef(lasso_cv, s = "lambda.1se")
num_selected <- sum(coef_lasso != 0) - 1

Output

cat("Number of variables selected at lambda.1se:", num_selected, "\n")
Number of variables selected at lambda.1se: 13 

Question 2:

coef_paths <- coef(lasso_cv)
plot(lasso_cv)
``
lambda_values <- lasso_cv$lambda
coef_paths <- coef(lasso_cv)
variable_names <- c(
  "econ__economic_typologyFederal/State government-dependent",
  "econ__economic_typologyManufacturing-dependent",
  "econ__economic_typologyMining-dependent",
  "econ__economic_typologyNonspecialized",
  "econ__economic_typologyRecreation",
  "econ__pct_civilian_labor",
  "demo__pct_aged_65_years_and_older",
  "demo__pct_hispanic",
  "demo__pct_american_indian_or_alaskan_native",
  "demo__pct_adults_bachelors_or_higher",
  "demo__birth_rate_per_1k",
  "demo__death_rate_per_1k",
  "health__pct_adult_obesity",
  "health__pct_adult_smoking",
  "health__pct_diabetes",
  "health__pct_excessive_drinking",
  "health__pct_physical_inacticity",
  "health__air_pollution_particulate_matter",
  "health__motor_vehicle_crash_deaths_per_100k",
  "health__pop_per_primary_care_physician"
)
coef_matrix <- coef_paths
elimination_order <- apply(coef_matrix, 1, function(x) which(x == 0)[1])
last_variable_index <- which.max(elimination_order)
last_variable <- variable_names[last_variable_index]
print(last_variable)
[1] "econ__economic_typologyManufacturing-dependent"

Question 3: Use the LASSO model (lambda.1se) to predict the observations in the testing data set. What is the MSE?

Predict

predictions <- predict(lasso_cv, s = "lambda.1se", newx = X)
mse <- mean((predictions - y)^2)

cat

cat("Mean Squared Error (MSE) on the test set:", mse, "\n")
Mean Squared Error (MSE) on the test set: 685.3974 

Question 4: Use the LASSO model (lambda.min) to predict the observations in the testing data set. What is the MSE?

predictions_lambda_min <- predict(lasso_cv, s = "lambda.min", newx = X)
mse_lambda_min <- mean((predictions_lambda_min - y)^2)
cat("Mean Squared Error (MSE) on the test set using lambda.min:", mse_lambda_min, "\n")
Mean Squared Error (MSE) on the test set using lambda.min: 644.2104 

Question 5: Apply the LASSO model (lambda.min) to the testing data set. On average, the predicted county-level heart disease mortality per 100K is off by _________ per 100k. (Round your answer to the nearest integer if needed)

New data prep

library(janitor)
test_data <-Heart_disease_mortality_test_1_
y_new <- test_data$heart_disease_mortality_per_100k
X_new <- model.matrix(heart_disease_mortality_per_100k ~ ., test_data)[, -1]

Predict

predictions_lambda_min_new <- predict(lasso_cv, s = "lambda.min", newx = X_new)
absolute_errors_new <- abs(predictions_lambda_min_new - y_new)
mae_lambda_min_new <- mean(absolute_errors_new)
mae_lambda_min_new_rounded <- round(mae_lambda_min_new)
cat("On average, the predicted county-level heart disease mortality per 100K is off by", mae_lambda_min_new_rounded, "per 100k.\n")
On average, the predicted county-level heart disease mortality per 100K is off by 22 per 100k.

Question 6: Recall the regression model you developed in Quiz 4, where you used all variables in the training data set as the candidates to predict heart_disease_mortality_per_100k. Let’s call this model a classic model. Use the classic model to predict the observations in the testing data set. What is the MSE?

y_test <- test_data$heart_disease_mortality_per_100k
classic_model <- lm(heart_disease_mortality_per_100k ~ ., data = train_data)
predictions_classic <- predict(classic_model, newdata = test_data)
if(length(predictions_classic) == length(y_test)) {
  mse_classic <- mean((predictions_classic - y_test)^2)

  cat("Mean Squared Error (MSE) on the test set using the classic model:", mse_classic, "\n")
} else {
  cat("The lengths of predictions and actual values do not match. Check the data.\n")
}
Mean Squared Error (MSE) on the test set using the classic model: 785.5377 

Question 7: Which model you develop above (i.e., classic model, LASSO using lambda.min, LASSO using lambda.1se) has the best prediction performance (i.e., MSE) on the testing data set?

mse_classic <- 785.5377
mse_lambda_min <- 644.2104 
predictions_lambda_1se <- predict(lasso_cv, s = "lambda.1se", newx = X)
mse_lambda_1se <- mean((predictions_lambda_1se - y)^2)
cat("MSE of Classic Model:", mse_classic, "\n")
MSE of Classic Model: 785.5377 
cat("MSE of LASSO using lambda.min:", mse_lambda_min, "\n")
MSE of LASSO using lambda.min: 644.2104 
cat("MSE of LASSO using lambda.1se:", mse_lambda_1se, "\n")
MSE of LASSO using lambda.1se: 685.3974 
mse_values <- c(classic = mse_classic, lambda_min = mse_lambda_min, lambda_1se = mse_lambda_1se)
best_model <- names(mse_values)[which.min(mse_values)]
cat("The best model based on MSE is:", best_model, "\n")
The best model based on MSE is: lambda_min 

Question 8: According to the model you identified in the previous question, if the health_air_pollution_particulate_matter increases, would heart_disease_mortality_per_100k increase or decrease, assuming all other variables stay constant?

lasso_lambda_min_coefficients <- coef(lasso_cv, s = "lambda.min")
air_pollution_coeff <- lasso_lambda_min_coefficients["health__air_pollution_particulate_matter", ]
if (air_pollution_coeff > 0) {
  cat("If health_air_pollution_particulate_matter increases, heart_disease_mortality_per_100k would increase.\n")
} else {
  cat("If health_air_pollution_particulate_matter increases, heart_disease_mortality_per_100k would decrease.\n")
}
If health_air_pollution_particulate_matter increases, heart_disease_mortality_per_100k would decrease.
LS0tDQp0aXRsZTogUXVpeiA1DQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNClF1ZXN0aW9uIDE6IFNldCB0aGUgcmFuZG9tIHNlZWQgYXQgNDcwLiANCg0KRGV2ZWxvcCBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIHRvIHByZWRpY3QgaGVhcnRfZGlzZWFzZV9tb3J0YWxpdHlfcGVyXzEwMGsgdXNpbmcgdGhlIExBU1NPIG1ldGhvZCBiYXNlZCBvbiB0aGUgdHJhaW5pbmcgZGF0YSBzZXQsIHVzaW5nIDEwLWZvbGQgY3Jvc3MgdmFsaWRhdGlvbiB0byBzZWxlY3QgbGFtYmRhLg0KDQpIb3cgbWFueSB2YXJpYWJsZXMgYXJlIHNlbGVjdGVkIGlmIHdlIHVzZSBsYW1iZGEuMXNlPw0KDQpnbG1uZXQNCmBgYHtyfQ0KaW5zdGFsbC5wYWNrYWdlcygiZ2xtbmV0IikNCg0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShnbG1uZXQpDQpgYGANCg0Kc2V0IHNlZWQNCmBgYHtyfQ0Kc2V0LnNlZWQoNDcwKQ0KYGBgDQoNCkRhdGENCmBgYHtyfQ0KbGlicmFyeShqYW5pdG9yKQ0KdHJhaW5fZGF0YSA8LSBIZWFydF9kaXNlYXNlX21vcnRhbGl0eV90cmFpbg0KYGBgDQoNCmBgYHtyfQ0KdHJhaW5fZGF0YSA8LSBuYS5vbWl0KHRyYWluX2RhdGEpDQpgYGANCg0KUHJlcA0KYGBge3J9DQp5IDwtIHRyYWluX2RhdGEkaGVhcnRfZGlzZWFzZV9tb3J0YWxpdHlfcGVyXzEwMGsNClggPC0gbW9kZWwubWF0cml4KGhlYXJ0X2Rpc2Vhc2VfbW9ydGFsaXR5X3Blcl8xMDBrIH4gLiwgdHJhaW5fZGF0YSlbLCAtMV0NCmBgYA0KDQpMYXNzbw0KYGBge3J9DQpsYXNzb19jdiA8LSBjdi5nbG1uZXQoWCwgeSwgYWxwaGEgPSAxLCBuZm9sZHMgPSAxMCkNCmBgYA0KDQpMYW1iZGENCmBgYHtyfQ0KY29lZl9sYXNzbyA8LSBjb2VmKGxhc3NvX2N2LCBzID0gImxhbWJkYS4xc2UiKQ0KbnVtX3NlbGVjdGVkIDwtIHN1bShjb2VmX2xhc3NvICE9IDApIC0gMQ0KYGBgDQoNCk91dHB1dA0KYGBge3J9DQpjYXQoIk51bWJlciBvZiB2YXJpYWJsZXMgc2VsZWN0ZWQgYXQgbGFtYmRhLjFzZToiLCBudW1fc2VsZWN0ZWQsICJcbiIpDQpgYGANCg0KDQpRdWVzdGlvbiAyOg0KYGBge3J9DQpjb2VmX3BhdGhzIDwtIGNvZWYobGFzc29fY3YpDQpwbG90KGxhc3NvX2N2KQ0KYGANCmBgYA0KDQpgYGB7cn0NCmxhbWJkYV92YWx1ZXMgPC0gbGFzc29fY3YkbGFtYmRhDQpgYGANCmBgYHtyfQ0KY29lZl9wYXRocyA8LSBjb2VmKGxhc3NvX2N2KQ0KYGBgDQpgYGB7cn0NCnZhcmlhYmxlX25hbWVzIDwtIGMoDQogICJlY29uX19lY29ub21pY190eXBvbG9neUZlZGVyYWwvU3RhdGUgZ292ZXJubWVudC1kZXBlbmRlbnQiLA0KICAiZWNvbl9fZWNvbm9taWNfdHlwb2xvZ3lNYW51ZmFjdHVyaW5nLWRlcGVuZGVudCIsDQogICJlY29uX19lY29ub21pY190eXBvbG9neU1pbmluZy1kZXBlbmRlbnQiLA0KICAiZWNvbl9fZWNvbm9taWNfdHlwb2xvZ3lOb25zcGVjaWFsaXplZCIsDQogICJlY29uX19lY29ub21pY190eXBvbG9neVJlY3JlYXRpb24iLA0KICAiZWNvbl9fcGN0X2NpdmlsaWFuX2xhYm9yIiwNCiAgImRlbW9fX3BjdF9hZ2VkXzY1X3llYXJzX2FuZF9vbGRlciIsDQogICJkZW1vX19wY3RfaGlzcGFuaWMiLA0KICAiZGVtb19fcGN0X2FtZXJpY2FuX2luZGlhbl9vcl9hbGFza2FuX25hdGl2ZSIsDQogICJkZW1vX19wY3RfYWR1bHRzX2JhY2hlbG9yc19vcl9oaWdoZXIiLA0KICAiZGVtb19fYmlydGhfcmF0ZV9wZXJfMWsiLA0KICAiZGVtb19fZGVhdGhfcmF0ZV9wZXJfMWsiLA0KICAiaGVhbHRoX19wY3RfYWR1bHRfb2Jlc2l0eSIsDQogICJoZWFsdGhfX3BjdF9hZHVsdF9zbW9raW5nIiwNCiAgImhlYWx0aF9fcGN0X2RpYWJldGVzIiwNCiAgImhlYWx0aF9fcGN0X2V4Y2Vzc2l2ZV9kcmlua2luZyIsDQogICJoZWFsdGhfX3BjdF9waHlzaWNhbF9pbmFjdGljaXR5IiwNCiAgImhlYWx0aF9fYWlyX3BvbGx1dGlvbl9wYXJ0aWN1bGF0ZV9tYXR0ZXIiLA0KICAiaGVhbHRoX19tb3Rvcl92ZWhpY2xlX2NyYXNoX2RlYXRoc19wZXJfMTAwayIsDQogICJoZWFsdGhfX3BvcF9wZXJfcHJpbWFyeV9jYXJlX3BoeXNpY2lhbiINCikNCmBgYA0KYGBge3J9DQpjb2VmX21hdHJpeCA8LSBjb2VmX3BhdGhzDQplbGltaW5hdGlvbl9vcmRlciA8LSBhcHBseShjb2VmX21hdHJpeCwgMSwgZnVuY3Rpb24oeCkgd2hpY2goeCA9PSAwKVsxXSkNCmBgYA0KDQpgYGB7cn0NCmxhc3RfdmFyaWFibGVfaW5kZXggPC0gd2hpY2gubWF4KGVsaW1pbmF0aW9uX29yZGVyKQ0KYGBgDQoNCmBgYHtyfQ0KbGFzdF92YXJpYWJsZSA8LSB2YXJpYWJsZV9uYW1lc1tsYXN0X3ZhcmlhYmxlX2luZGV4XQ0KcHJpbnQobGFzdF92YXJpYWJsZSkNCmBgYA0KDQpRdWVzdGlvbiAzOiBVc2UgdGhlIExBU1NPIG1vZGVsIChsYW1iZGEuMXNlKSB0byBwcmVkaWN0IHRoZSBvYnNlcnZhdGlvbnMgaW4gdGhlIHRlc3RpbmcgZGF0YSBzZXQuIFdoYXQgaXMgdGhlIE1TRT8NCg0KUHJlZGljdA0KYGBge3J9DQpwcmVkaWN0aW9ucyA8LSBwcmVkaWN0KGxhc3NvX2N2LCBzID0gImxhbWJkYS4xc2UiLCBuZXd4ID0gWCkNCmBgYA0KYGBge3J9DQptc2UgPC0gbWVhbigocHJlZGljdGlvbnMgLSB5KV4yKQ0KYGBgDQoNCmNhdA0KYGBge3J9DQpjYXQoIk1lYW4gU3F1YXJlZCBFcnJvciAoTVNFKSBvbiB0aGUgdGVzdCBzZXQ6IiwgbXNlLCAiXG4iKQ0KYGBgDQoNClF1ZXN0aW9uIDQ6IFVzZSB0aGUgTEFTU08gbW9kZWwgKGxhbWJkYS5taW4pIHRvIHByZWRpY3QgdGhlIG9ic2VydmF0aW9ucyBpbiB0aGUgdGVzdGluZyBkYXRhIHNldC4gV2hhdCBpcyB0aGUgTVNFPw0KDQpgYGB7cn0NCnByZWRpY3Rpb25zX2xhbWJkYV9taW4gPC0gcHJlZGljdChsYXNzb19jdiwgcyA9ICJsYW1iZGEubWluIiwgbmV3eCA9IFgpDQpgYGANCg0KYGBge3J9DQptc2VfbGFtYmRhX21pbiA8LSBtZWFuKChwcmVkaWN0aW9uc19sYW1iZGFfbWluIC0geSleMikNCmBgYA0KYGBge3J9DQpjYXQoIk1lYW4gU3F1YXJlZCBFcnJvciAoTVNFKSBvbiB0aGUgdGVzdCBzZXQgdXNpbmcgbGFtYmRhLm1pbjoiLCBtc2VfbGFtYmRhX21pbiwgIlxuIikNCmBgYA0KDQpRdWVzdGlvbiA1OiBBcHBseSB0aGUgTEFTU08gbW9kZWwgKGxhbWJkYS5taW4pIHRvIHRoZSB0ZXN0aW5nIGRhdGEgc2V0LiBPbiBhdmVyYWdlLCB0aGUgcHJlZGljdGVkIGNvdW50eS1sZXZlbCBoZWFydCBkaXNlYXNlIG1vcnRhbGl0eSBwZXIgMTAwSyBpcyBvZmYgYnkgX19fX19fX19fIHBlciAxMDBrLiAoUm91bmQgeW91ciBhbnN3ZXIgdG8gdGhlIG5lYXJlc3QgaW50ZWdlciBpZiBuZWVkZWQpDQoNCk5ldyBkYXRhIHByZXANCmBgYHtyfQ0KbGlicmFyeShqYW5pdG9yKQ0KdGVzdF9kYXRhIDwtSGVhcnRfZGlzZWFzZV9tb3J0YWxpdHlfdGVzdF8xXw0KYGBgDQoNCmBgYHtyfQ0KeV9uZXcgPC0gdGVzdF9kYXRhJGhlYXJ0X2Rpc2Vhc2VfbW9ydGFsaXR5X3Blcl8xMDBrDQpYX25ldyA8LSBtb2RlbC5tYXRyaXgoaGVhcnRfZGlzZWFzZV9tb3J0YWxpdHlfcGVyXzEwMGsgfiAuLCB0ZXN0X2RhdGEpWywgLTFdDQpgYGANClByZWRpY3QNCmBgYHtyfQ0KcHJlZGljdGlvbnNfbGFtYmRhX21pbl9uZXcgPC0gcHJlZGljdChsYXNzb19jdiwgcyA9ICJsYW1iZGEubWluIiwgbmV3eCA9IFhfbmV3KQ0KYGBgDQoNCmBgYHtyfQ0KYWJzb2x1dGVfZXJyb3JzX25ldyA8LSBhYnMocHJlZGljdGlvbnNfbGFtYmRhX21pbl9uZXcgLSB5X25ldykNCmBgYA0KDQpgYGB7cn0NCm1hZV9sYW1iZGFfbWluX25ldyA8LSBtZWFuKGFic29sdXRlX2Vycm9yc19uZXcpDQpgYGANCg0KYGBge3J9DQptYWVfbGFtYmRhX21pbl9uZXdfcm91bmRlZCA8LSByb3VuZChtYWVfbGFtYmRhX21pbl9uZXcpDQpgYGANCg0KYGBge3J9DQpjYXQoIk9uIGF2ZXJhZ2UsIHRoZSBwcmVkaWN0ZWQgY291bnR5LWxldmVsIGhlYXJ0IGRpc2Vhc2UgbW9ydGFsaXR5IHBlciAxMDBLIGlzIG9mZiBieSIsIG1hZV9sYW1iZGFfbWluX25ld19yb3VuZGVkLCAicGVyIDEwMGsuXG4iKQ0KYGBgDQoNClF1ZXN0aW9uIDY6IFJlY2FsbCB0aGUgcmVncmVzc2lvbiBtb2RlbCB5b3UgZGV2ZWxvcGVkIGluIFF1aXogNCwgd2hlcmUgeW91IHVzZWQgYWxsIHZhcmlhYmxlcyBpbiB0aGUgdHJhaW5pbmcgZGF0YSBzZXQgYXMgdGhlIGNhbmRpZGF0ZXMgdG8gcHJlZGljdCBoZWFydF9kaXNlYXNlX21vcnRhbGl0eV9wZXJfMTAway4gIExldCdzIGNhbGwgdGhpcyBtb2RlbCBhIGNsYXNzaWMgbW9kZWwuDQpVc2UgdGhlIGNsYXNzaWMgbW9kZWwgdG8gcHJlZGljdCB0aGUgb2JzZXJ2YXRpb25zIGluIHRoZSB0ZXN0aW5nIGRhdGEgc2V0LiBXaGF0IGlzIHRoZSBNU0U/DQoNCmBgYHtyfQ0KeV90ZXN0IDwtIHRlc3RfZGF0YSRoZWFydF9kaXNlYXNlX21vcnRhbGl0eV9wZXJfMTAwaw0KYGBgDQoNCg0KYGBge3J9DQpjbGFzc2ljX21vZGVsIDwtIGxtKGhlYXJ0X2Rpc2Vhc2VfbW9ydGFsaXR5X3Blcl8xMDBrIH4gLiwgZGF0YSA9IHRyYWluX2RhdGEpDQpgYGANCg0KYGBge3J9DQpwcmVkaWN0aW9uc19jbGFzc2ljIDwtIHByZWRpY3QoY2xhc3NpY19tb2RlbCwgbmV3ZGF0YSA9IHRlc3RfZGF0YSkNCmBgYA0KDQpgYGB7cn0NCmlmKGxlbmd0aChwcmVkaWN0aW9uc19jbGFzc2ljKSA9PSBsZW5ndGgoeV90ZXN0KSkgew0KICBtc2VfY2xhc3NpYyA8LSBtZWFuKChwcmVkaWN0aW9uc19jbGFzc2ljIC0geV90ZXN0KV4yKQ0KDQogIGNhdCgiTWVhbiBTcXVhcmVkIEVycm9yIChNU0UpIG9uIHRoZSB0ZXN0IHNldCB1c2luZyB0aGUgY2xhc3NpYyBtb2RlbDoiLCBtc2VfY2xhc3NpYywgIlxuIikNCn0gZWxzZSB7DQogIGNhdCgiVGhlIGxlbmd0aHMgb2YgcHJlZGljdGlvbnMgYW5kIGFjdHVhbCB2YWx1ZXMgZG8gbm90IG1hdGNoLiBDaGVjayB0aGUgZGF0YS5cbiIpDQp9DQpgYGANCg0KUXVlc3Rpb24gNzogV2hpY2ggbW9kZWwgeW91IGRldmVsb3AgYWJvdmUgKGkuZS4sIGNsYXNzaWMgbW9kZWwsIExBU1NPIHVzaW5nIGxhbWJkYS5taW4sIExBU1NPIHVzaW5nIGxhbWJkYS4xc2UpIGhhcyB0aGUgYmVzdCBwcmVkaWN0aW9uIHBlcmZvcm1hbmNlIChpLmUuLCBNU0UpIG9uIHRoZSB0ZXN0aW5nIGRhdGEgc2V0Pw0KDQpgYGB7cn0NCm1zZV9jbGFzc2ljIDwtIDc4NS41Mzc3DQptc2VfbGFtYmRhX21pbiA8LSA2NDQuMjEwNCANCnByZWRpY3Rpb25zX2xhbWJkYV8xc2UgPC0gcHJlZGljdChsYXNzb19jdiwgcyA9ICJsYW1iZGEuMXNlIiwgbmV3eCA9IFgpDQptc2VfbGFtYmRhXzFzZSA8LSBtZWFuKChwcmVkaWN0aW9uc19sYW1iZGFfMXNlIC0geSleMikNCg0KYGBgDQoNCmBgYHtyfQ0KY2F0KCJNU0Ugb2YgQ2xhc3NpYyBNb2RlbDoiLCBtc2VfY2xhc3NpYywgIlxuIikNCmNhdCgiTVNFIG9mIExBU1NPIHVzaW5nIGxhbWJkYS5taW46IiwgbXNlX2xhbWJkYV9taW4sICJcbiIpDQpjYXQoIk1TRSBvZiBMQVNTTyB1c2luZyBsYW1iZGEuMXNlOiIsIG1zZV9sYW1iZGFfMXNlLCAiXG4iKQ0KYGBgDQpgYGB7cn0NCm1zZV92YWx1ZXMgPC0gYyhjbGFzc2ljID0gbXNlX2NsYXNzaWMsIGxhbWJkYV9taW4gPSBtc2VfbGFtYmRhX21pbiwgbGFtYmRhXzFzZSA9IG1zZV9sYW1iZGFfMXNlKQ0KYmVzdF9tb2RlbCA8LSBuYW1lcyhtc2VfdmFsdWVzKVt3aGljaC5taW4obXNlX3ZhbHVlcyldDQoNCmBgYA0KDQpgYGB7cn0NCmNhdCgiVGhlIGJlc3QgbW9kZWwgYmFzZWQgb24gTVNFIGlzOiIsIGJlc3RfbW9kZWwsICJcbiIpDQpgYGANCg0KUXVlc3Rpb24gODogQWNjb3JkaW5nIHRvIHRoZSBtb2RlbCB5b3UgaWRlbnRpZmllZCBpbiB0aGUgcHJldmlvdXMgcXVlc3Rpb24sIGlmIHRoZSBoZWFsdGhfYWlyX3BvbGx1dGlvbl9wYXJ0aWN1bGF0ZV9tYXR0ZXIgaW5jcmVhc2VzLCB3b3VsZCBoZWFydF9kaXNlYXNlX21vcnRhbGl0eV9wZXJfMTAwayBpbmNyZWFzZSBvciBkZWNyZWFzZSwgYXNzdW1pbmcgYWxsIG90aGVyIHZhcmlhYmxlcyBzdGF5IGNvbnN0YW50Pw0KDQpgYGB7cn0NCmxhc3NvX2xhbWJkYV9taW5fY29lZmZpY2llbnRzIDwtIGNvZWYobGFzc29fY3YsIHMgPSAibGFtYmRhLm1pbiIpDQpgYGANCg0KYGBge3J9DQphaXJfcG9sbHV0aW9uX2NvZWZmIDwtIGxhc3NvX2xhbWJkYV9taW5fY29lZmZpY2llbnRzWyJoZWFsdGhfX2Fpcl9wb2xsdXRpb25fcGFydGljdWxhdGVfbWF0dGVyIiwgXQ0KDQpgYGANCg0KYGBge3J9DQppZiAoYWlyX3BvbGx1dGlvbl9jb2VmZiA+IDApIHsNCiAgY2F0KCJJZiBoZWFsdGhfYWlyX3BvbGx1dGlvbl9wYXJ0aWN1bGF0ZV9tYXR0ZXIgaW5jcmVhc2VzLCBoZWFydF9kaXNlYXNlX21vcnRhbGl0eV9wZXJfMTAwayB3b3VsZCBpbmNyZWFzZS5cbiIpDQp9IGVsc2Ugew0KICBjYXQoIklmIGhlYWx0aF9haXJfcG9sbHV0aW9uX3BhcnRpY3VsYXRlX21hdHRlciBpbmNyZWFzZXMsIGhlYXJ0X2Rpc2Vhc2VfbW9ydGFsaXR5X3Blcl8xMDBrIHdvdWxkIGRlY3JlYXNlLlxuIikNCn0NCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0K