library(dplyr)
library(tidyr)
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
library(flexdashboard)
## Warning: package 'flexdashboard' was built under R version 4.3.3
library(tidyverse)

library(gapminder)
## Warning: package 'gapminder' was built under R version 4.3.3
library(ggthemes)
## Warning: package 'ggthemes' was built under R version 4.3.3
library(ggthemes)

library(lessR)
## Warning: package 'lessR' was built under R version 4.3.3
library(dplyr)          
library(ggplot2)        
library(caret)

library(DataExplorer)

library(car)

library(ggcorrplot)

library(GGally)
library(kableExtra)
library(dplyr)
library(GGally)
library(ggcorrplot)

library(MLmetrics)

library(performance)

library(lmtest)

library(highcharter)
library(RColorBrewer)

library(DT)

library(moments)

#library(see)
library(MASS)

library(psych)

library(Hmisc)
library(corrplot)
library(ROCR) 
library(broom)

library(WVPlots)

library(randomForest)
library(pROC)
Insurance <- read.csv("https://raw.githubusercontent.com/uplotnik/DATA621/main/insurance_data.csv")

str(Insurance)
## 'data.frame':    10008 obs. of  13 variables:
##  $ age                            : num  45 64 19 36 19 34 47 63 19 20 ...
##  $ sex                            : chr  "male" "male" "female" "male" ...
##  $ bmi                            : num  28.7 34.5 32.1 28.9 24.6 ...
##  $ children                       : num  2 0 0 3 1 0 1 0 1 0 ...
##  $ smoker                         : chr  "no" "no" "no" "no" ...
##  $ Claim_Amount                   : num  32994 38448 50778 33741 12198 ...
##  $ past_consultations             : num  16 8 15 10 16 5 23 7 3 10 ...
##  $ num_of_steps                   : num  902022 956604 758688 879560 793026 ...
##  $ Hospital_expenditure           : num  8640895 11022389 1642626 1985637 10009377 ...
##  $ NUmber_of_past_hospitalizations: num  1 1 0 1 1 1 1 1 0 0 ...
##  $ Anual_Salary                   : num  94365914 230021899 46443495 130616936 61133917 ...
##  $ region                         : chr  "southwest" "southwest" "northwest" "northeast" ...
##  $ charges                        : num  8028 13823 2131 6749 2709 ...
summary(Insurance)
##       age         sex                 bmi           children    
##  Min.   :18   Length:10008       Min.   :15.96   Min.   :0.000  
##  1st Qu.:26   Class :character   1st Qu.:26.12   1st Qu.:0.000  
##  Median :39   Mode  :character   Median :30.03   Median :1.000  
##  Mean   :39                      Mean   :30.44   Mean   :1.063  
##  3rd Qu.:51                      3rd Qu.:34.32   3rd Qu.:2.000  
##  Max.   :64                      Max.   :53.13   Max.   :5.000  
##  NA's   :73                      NA's   :24      NA's   :45     
##     smoker           Claim_Amount   past_consultations  num_of_steps    
##  Length:10008       Min.   : 1920   Min.   : 1.00      Min.   : 695430  
##  Class :character   1st Qu.:19541   1st Qu.: 9.00      1st Qu.: 841902  
##  Mode  :character   Median :32800   Median :14.00      Median : 903769  
##                     Mean   :32221   Mean   :14.42      Mean   : 896863  
##                     3rd Qu.:44148   3rd Qu.:19.00      3rd Qu.: 949238  
##                     Max.   :77278   Max.   :40.00      Max.   :1107872  
##                     NA's   :99      NA's   :51         NA's   :24       
##  Hospital_expenditure NUmber_of_past_hospitalizations  Anual_Salary       
##  Min.   :    29453    Min.   :0.0000                  Min.   :   2747072  
##  1st Qu.:  3776053    1st Qu.:1.0000                  1st Qu.:  73542243  
##  Median :  6894887    Median :1.0000                  Median : 125901988  
##  Mean   : 11198901    Mean   :0.9725                  Mean   : 263017112  
##  3rd Qu.:  9721549    3rd Qu.:1.0000                  3rd Qu.: 224741452  
##  Max.   :261631699    Max.   :3.0000                  Max.   :4117196637  
##  NA's   :30           NA's   :10                      NA's   :37          
##     region             charges     
##  Length:10008       Min.   : 1122  
##  Class :character   1st Qu.: 4441  
##  Mode  :character   Median : 8550  
##                     Mean   :11025  
##                     3rd Qu.:13224  
##                     Max.   :63770  
## 
introduce(Insurance)
##    rows columns discrete_columns continuous_columns all_missing_columns
## 1 10008      13                3                 10                   0
##   total_missing_values complete_rows total_observations memory_usage
## 1                  393          9618             130104      1044952
plot_intro(Insurance, 
           ggtheme = theme_minimal(),
  title = "Missing Data",
  theme_config = theme(plot.title = element_text(color = "orange")),
  geom_label_args = c(hjust = "inward")
)

plot_missing(Insurance)

DataExplorer::plot_bar(
  data = Insurance,
         order_bar = T,
         ggtheme=theme_bw())

DataExplorer::plot_histogram(
  geom_histogram_args = list(alpha = 0.5),
   data = Insurance,
         ggtheme=theme_bw())

categ_cols <- Insurance %>% select_if(~ class(.) == "factor")
for (col in names(categ_cols)) {
  t <- Insurance %>%
    group_by_(col) %>%
    summarise(count = n()) %>%
    mutate(frequency = paste0(round(100 * count / sum(count), 0), "%")) %>% 
    knitr::kable("html", align = "lcc") %>%
    kableExtra::kable_styling(full_width = F, position = "left") %>% 
    print()
}
categ_cols
## data frame with 0 columns and 10008 rows
Insurance[ , c("sex", "smoker", "region")] <- 
  lapply(Insurance[ , c("sex", "smoker", "region")], as.factor)
str(Insurance)
## 'data.frame':    10008 obs. of  13 variables:
##  $ age                            : num  45 64 19 36 19 34 47 63 19 20 ...
##  $ sex                            : Factor w/ 2 levels "female","male": 2 2 1 2 1 2 1 1 1 1 ...
##  $ bmi                            : num  28.7 34.5 32.1 28.9 24.6 ...
##  $ children                       : num  2 0 0 3 1 0 1 0 1 0 ...
##  $ smoker                         : Factor w/ 2 levels "no","yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ Claim_Amount                   : num  32994 38448 50778 33741 12198 ...
##  $ past_consultations             : num  16 8 15 10 16 5 23 7 3 10 ...
##  $ num_of_steps                   : num  902022 956604 758688 879560 793026 ...
##  $ Hospital_expenditure           : num  8640895 11022389 1642626 1985637 10009377 ...
##  $ NUmber_of_past_hospitalizations: num  1 1 0 1 1 1 1 1 0 0 ...
##  $ Anual_Salary                   : num  94365914 230021899 46443495 130616936 61133917 ...
##  $ region                         : Factor w/ 4 levels "northeast","northwest",..: 4 4 2 1 2 3 4 2 4 3 ...
##  $ charges                        : num  8028 13823 2131 6749 2709 ...
clean<-Insurance %>% 
   mutate_at(vars(c('age', 'bmi', 'children', 'Claim_Amount', 'past_consultations', 
                   'num_of_steps', 'Hospital_expenditure', 'NUmber_of_past_hospitalizations', 'Anual_Salary')), ~ifelse(is.na(.), median(., na.rm = TRUE), .))
print("Count of total missing values in after imputation ")
## [1] "Count of total missing values in after imputation "
sum(is.na(clean))
## [1] 0
age_group <- cut(clean$age, 
                  breaks = seq(10, 100, by = 10), 
                  include.lowest = TRUE)

InsuranceData <- cbind(clean, age_group)
group<-InsuranceData%>% 
  count(age_group)
group %>% 
  hchart('column', hcaes(x = 'age_group', y = 'n'))%>% hc_chart(type = "column", options3d = list(enabled = TRUE, alpha = 15, beta = 15), dataLabels=list(enabled=TRUE))%>%
    hc_plotOptions(series = list(
        borderWidth= 0,
        dataLabels = list(
            enabled = TRUE,
            color = "black",
            format = '{point.y}')))
sm<-Insurance %>% 
  count(smoker) 

sm %>% 
  hchart('pie', hcaes(x = 'smoker', y = 'n'))%>% hc_chart(type = "column", options3d = list(enabled = TRUE, alpha = 15, beta = 15), dataLabels=list(enabled=TRUE))
BMI<-clean  %>% mutate(bmi_cat = cut(bmi,
  breaks = c(0, 18.5, 25, 30, 60),
  labels = c("Under Weight", "Normal Weight", "Overweight", "Obese")
))
BMI %>% 
  count(bmi_cat) %>% 
  hchart('bar', hcaes(x = 'bmi_cat', y = 'n'))%>% hc_chart(type = "bar", options3d = list(enabled = TRUE, alpha = 30, beta = 0))%>%
    hc_plotOptions(series = list(
        borderWidth= 0,
        dataLabels = list(
            enabled = TRUE,
            color = "black",
            format = '{point.y}')))
#Correlation table

library(corrr)
cor<-clean %>% 
  correlate() %>% 
  focus(charges) %>%arrange(desc(charges))

knitr::kable(
 cor, caption = "Correlation Table")%>%
  kable_styling("striped", full_width = F)
Correlation Table
term charges
Anual_Salary 0.9284001
num_of_steps 0.8758246
Hospital_expenditure 0.8315979
NUmber_of_past_hospitalizations 0.7621982
past_consultations 0.5392697
Claim_Amount 0.3502274
age 0.3216199
bmi 0.1274681
children 0.0772186
clean%>%
  hchart(type = "column", hcaes(x = smoker, y = charges))%>% hc_chart(type = "column", options3d = list(enabled = TRUE, alpha = 30, beta = 0))%>% hc_title(text='The cost of health insurance for smokers vs. nonsmokers')
clean%>%
  hchart(type = "scatter", hcaes(x = age, y = charges))%>% hc_chart(type = "scatter", options3d = list(enabled = TRUE, alpha = 30, beta = 0))%>% hc_title(text='Health Insurance Charges by Age')
clean%>%
  hchart(type = "scatter", hcaes(x = bmi, y = charges))%>% hc_chart(type = "scatter", options3d = list(enabled = TRUE, alpha = 30, beta = 0))%>% hc_title(text='BMI and Health Insurance Charges')
clean%>%
  hchart(type = "scatter", hcaes(x = children, y = charges))%>% hc_chart(type = "scatter", options3d = list(enabled = TRUE, alpha = 30, beta = 0))%>% hc_title(text='Amount of children and Health Insurance Charges')
RNGkind(sample.kind = "Rounding")
set.seed(100) 
index_ins <- sample(x = nrow(clean) , size = nrow(clean)*0.8) 
data_train <- clean[index_ins , ]
data_test <- clean[-index_ins, ]
cat(" Size of data train:",dim(data_train),"\n","Size of data test :",dim(data_test))
##  Size of data train: 8006 13 
##  Size of data test : 2002 13

Building models

  1. Simple Linear Regression:
#Selecting predictor variable (age) and target variable (charges)
simple_linear_model <- lm(charges ~ age, data = Insurance)

#Summary of the model
summary(simple_linear_model)
## 
## Call:
## lm(formula = charges ~ age, data = Insurance)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
##  -6035  -4758  -3886  -2258  50159 
## 
## Coefficients:
##             Estimate Std. Error t value            Pr(>|t|)    
## (Intercept) 2328.490    273.902   8.501 <0.0000000000000002 ***
## age          224.575      6.613  33.962 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 9193 on 9933 degrees of freedom
##   (73 observations deleted due to missingness)
## Multiple R-squared:  0.104,  Adjusted R-squared:  0.1039 
## F-statistic:  1153 on 1 and 9933 DF,  p-value: < 0.00000000000000022

Overall, the model suggests that there is a statistically significant relationship between age and charges. However, the relatively low R-squared value indicates that age alone explains only a small portion of the variability in charges.

  1. Multiple Linear Regression:
#Selecting predictor variables (age, bmi, smoker, etc.) and target variable (charges)
multiple_linear_model <- lm(charges ~ age + bmi + smoker + children + region, data = Insurance)

#Summary of the model
summary(multiple_linear_model)
## 
## Call:
## lm(formula = charges ~ age + bmi + smoker + children + region, 
##     data = Insurance)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
##  -9731  -2205   -945    555  32699 
## 
## Coefficients:
##                  Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)     -9186.847    311.490 -29.493 < 0.0000000000000002 ***
## age               248.326      3.857  64.388 < 0.0000000000000002 ***
## bmi               243.004      9.207  26.393 < 0.0000000000000002 ***
## smokeryes       21258.245    150.796 140.973 < 0.0000000000000002 ***
## children          460.197     44.555  10.329 < 0.0000000000000002 ***
## regionnorthwest  -218.764    151.075  -1.448                0.148    
## regionsoutheast  -729.285    153.830  -4.741           0.00000216 ***
## regionsouthwest  -646.144    152.342  -4.241           0.00002242 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5269 on 9858 degrees of freedom
##   (142 observations deleted due to missingness)
## Multiple R-squared:  0.707,  Adjusted R-squared:  0.7068 
## F-statistic:  3398 on 7 and 9858 DF,  p-value: < 0.00000000000000022

Overall, the model suggests that age, BMI, smoking status, and the number of children have significant effects on insurance charges. However, the region variable may not have a significant effect on charges after considering other variables in the model.

  1. Simple Logistic Regression:
#Categorizing charges into two classes based on a threshold value
#For demonstration, let's consider charges above the median as high and all other charges as low
Insurance$charge_category_binary <- ifelse(Insurance$charges > median(Insurance$charges), 1, 0)

#Building logistic regression model with binary target variable
logistic_model <- glm(charge_category_binary ~ age + bmi + smoker + children + region, 
                      data = Insurance, family = binomial(link = "logit"))

#Summary of the model
summary(logistic_model)
## 
## Call:
## glm(formula = charge_category_binary ~ age + bmi + smoker + children + 
##     region, family = binomial(link = "logit"), data = Insurance)
## 
## Coefficients:
##                   Estimate Std. Error z value             Pr(>|z|)    
## (Intercept)      -8.589383   0.251923 -34.095 < 0.0000000000000002 ***
## age               0.189844   0.003975  47.760 < 0.0000000000000002 ***
## bmi               0.019540   0.005882   3.322             0.000894 ***
## smokeryes        22.504310 216.354581   0.104             0.917157    
## children          0.207776   0.028368   7.324 0.000000000000240026 ***
## regionnorthwest  -0.485189   0.096851  -5.010 0.000000545292976719 ***
## regionsoutheast  -0.909917   0.099955  -9.103 < 0.0000000000000002 ***
## regionsouthwest  -0.796180   0.097371  -8.177 0.000000000000000292 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 13675.6  on 9865  degrees of freedom
## Residual deviance:  5631.1  on 9858  degrees of freedom
##   (142 observations deleted due to missingness)
## AIC: 5647.1
## 
## Number of Fisher Scoring iterations: 18

In the context of the provided data and the target variable (charge_category_binary), running a logistic regression model might not be the most appropriate choice. Logistic regression is typically used for binary classification problems where the outcome variable is categorical and binary, meaning it has only two possible outcomes or classes.

LS0tDQp0aXRsZTogIkZpbmFsIC1tb2RlbHMiDQphdXRob3I6ICJUZWFtIDUiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydA0KLS0tDQoNCmBgYHtyIGxvYWQtcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh0aWR5cikNCmxpYnJhcnkoZ2dwbG90MikNCg0KbGlicmFyeShmbGV4ZGFzaGJvYXJkKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQoNCmxpYnJhcnkoZ2FwbWluZGVyKQ0KDQpsaWJyYXJ5KGdndGhlbWVzKQ0KbGlicmFyeShnZ3RoZW1lcykNCg0KbGlicmFyeShsZXNzUikNCmxpYnJhcnkoZHBseXIpICAgICAgICAgIA0KbGlicmFyeShnZ3Bsb3QyKSAgICAgICAgDQpsaWJyYXJ5KGNhcmV0KQ0KDQpsaWJyYXJ5KERhdGFFeHBsb3JlcikNCg0KbGlicmFyeShjYXIpDQoNCmxpYnJhcnkoZ2djb3JycGxvdCkNCg0KbGlicmFyeShHR2FsbHkpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShHR2FsbHkpDQpsaWJyYXJ5KGdnY29ycnBsb3QpDQoNCmxpYnJhcnkoTUxtZXRyaWNzKQ0KDQpsaWJyYXJ5KHBlcmZvcm1hbmNlKQ0KDQpsaWJyYXJ5KGxtdGVzdCkNCg0KbGlicmFyeShoaWdoY2hhcnRlcikNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KDQpsaWJyYXJ5KERUKQ0KDQpsaWJyYXJ5KG1vbWVudHMpDQoNCiNsaWJyYXJ5KHNlZSkNCmxpYnJhcnkoTUFTUykNCg0KbGlicmFyeShwc3ljaCkNCg0KbGlicmFyeShIbWlzYykNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KFJPQ1IpIA0KbGlicmFyeShicm9vbSkNCg0KbGlicmFyeShXVlBsb3RzKQ0KDQpsaWJyYXJ5KHJhbmRvbUZvcmVzdCkNCmxpYnJhcnkocFJPQykNCkluc3VyYW5jZSA8LSByZWFkLmNzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3VwbG90bmlrL0RBVEE2MjEvbWFpbi9pbnN1cmFuY2VfZGF0YS5jc3YiKQ0KDQpzdHIoSW5zdXJhbmNlKQ0Kc3VtbWFyeShJbnN1cmFuY2UpDQppbnRyb2R1Y2UoSW5zdXJhbmNlKQ0KcGxvdF9pbnRybyhJbnN1cmFuY2UsIA0KICAgICAgICAgICBnZ3RoZW1lID0gdGhlbWVfbWluaW1hbCgpLA0KICB0aXRsZSA9ICJNaXNzaW5nIERhdGEiLA0KICB0aGVtZV9jb25maWcgPSB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIm9yYW5nZSIpKSwNCiAgZ2VvbV9sYWJlbF9hcmdzID0gYyhoanVzdCA9ICJpbndhcmQiKQ0KKQ0KcGxvdF9taXNzaW5nKEluc3VyYW5jZSkNCkRhdGFFeHBsb3Jlcjo6cGxvdF9iYXIoDQogIGRhdGEgPSBJbnN1cmFuY2UsDQogICAgICAgICBvcmRlcl9iYXIgPSBULA0KICAgICAgICAgZ2d0aGVtZT10aGVtZV9idygpKQ0KICAgICAgICAgDQpEYXRhRXhwbG9yZXI6OnBsb3RfaGlzdG9ncmFtKA0KICBnZW9tX2hpc3RvZ3JhbV9hcmdzID0gbGlzdChhbHBoYSA9IDAuNSksDQogICBkYXRhID0gSW5zdXJhbmNlLA0KICAgICAgICAgZ2d0aGVtZT10aGVtZV9idygpKQ0KDQoNCmNhdGVnX2NvbHMgPC0gSW5zdXJhbmNlICU+JSBzZWxlY3RfaWYofiBjbGFzcyguKSA9PSAiZmFjdG9yIikNCmZvciAoY29sIGluIG5hbWVzKGNhdGVnX2NvbHMpKSB7DQogIHQgPC0gSW5zdXJhbmNlICU+JQ0KICAgIGdyb3VwX2J5Xyhjb2wpICU+JQ0KICAgIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lDQogICAgbXV0YXRlKGZyZXF1ZW5jeSA9IHBhc3RlMChyb3VuZCgxMDAgKiBjb3VudCAvIHN1bShjb3VudCksIDApLCAiJSIpKSAlPiUgDQogICAga25pdHI6OmthYmxlKCJodG1sIiwgYWxpZ24gPSAibGNjIikgJT4lDQogICAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRiwgcG9zaXRpb24gPSAibGVmdCIpICU+JSANCiAgICBwcmludCgpDQp9DQpjYXRlZ19jb2xzDQpJbnN1cmFuY2VbICwgYygic2V4IiwgInNtb2tlciIsICJyZWdpb24iKV0gPC0gDQogIGxhcHBseShJbnN1cmFuY2VbICwgYygic2V4IiwgInNtb2tlciIsICJyZWdpb24iKV0sIGFzLmZhY3RvcikNCnN0cihJbnN1cmFuY2UpDQpjbGVhbjwtSW5zdXJhbmNlICU+JSANCiAgIG11dGF0ZV9hdCh2YXJzKGMoJ2FnZScsICdibWknLCAnY2hpbGRyZW4nLCAnQ2xhaW1fQW1vdW50JywgJ3Bhc3RfY29uc3VsdGF0aW9ucycsIA0KICAgICAgICAgICAgICAgICAgICdudW1fb2Zfc3RlcHMnLCAnSG9zcGl0YWxfZXhwZW5kaXR1cmUnLCAnTlVtYmVyX29mX3Bhc3RfaG9zcGl0YWxpemF0aW9ucycsICdBbnVhbF9TYWxhcnknKSksIH5pZmVsc2UoaXMubmEoLiksIG1lZGlhbiguLCBuYS5ybSA9IFRSVUUpLCAuKSkNCnByaW50KCJDb3VudCBvZiB0b3RhbCBtaXNzaW5nIHZhbHVlcyBpbiBhZnRlciBpbXB1dGF0aW9uICIpDQpzdW0oaXMubmEoY2xlYW4pKQ0KDQphZ2VfZ3JvdXAgPC0gY3V0KGNsZWFuJGFnZSwgDQogICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMTAsIDEwMCwgYnkgPSAxMCksIA0KICAgICAgICAgICAgICAgICAgaW5jbHVkZS5sb3dlc3QgPSBUUlVFKQ0KDQpJbnN1cmFuY2VEYXRhIDwtIGNiaW5kKGNsZWFuLCBhZ2VfZ3JvdXApDQpncm91cDwtSW5zdXJhbmNlRGF0YSU+JSANCiAgY291bnQoYWdlX2dyb3VwKQ0KZ3JvdXAgJT4lIA0KICBoY2hhcnQoJ2NvbHVtbicsIGhjYWVzKHggPSAnYWdlX2dyb3VwJywgeSA9ICduJykpJT4lIGhjX2NoYXJ0KHR5cGUgPSAiY29sdW1uIiwgb3B0aW9uczNkID0gbGlzdChlbmFibGVkID0gVFJVRSwgYWxwaGEgPSAxNSwgYmV0YSA9IDE1KSwgZGF0YUxhYmVscz1saXN0KGVuYWJsZWQ9VFJVRSkpJT4lDQogICAgaGNfcGxvdE9wdGlvbnMoc2VyaWVzID0gbGlzdCgNCiAgICAgICAgYm9yZGVyV2lkdGg9IDAsDQogICAgICAgIGRhdGFMYWJlbHMgPSBsaXN0KA0KICAgICAgICAgICAgZW5hYmxlZCA9IFRSVUUsDQogICAgICAgICAgICBjb2xvciA9ICJibGFjayIsDQogICAgICAgICAgICBmb3JtYXQgPSAne3BvaW50Lnl9JykpKQ0Kc208LUluc3VyYW5jZSAlPiUgDQogIGNvdW50KHNtb2tlcikgDQoNCnNtICU+JSANCiAgaGNoYXJ0KCdwaWUnLCBoY2Flcyh4ID0gJ3Ntb2tlcicsIHkgPSAnbicpKSU+JSBoY19jaGFydCh0eXBlID0gImNvbHVtbiIsIG9wdGlvbnMzZCA9IGxpc3QoZW5hYmxlZCA9IFRSVUUsIGFscGhhID0gMTUsIGJldGEgPSAxNSksIGRhdGFMYWJlbHM9bGlzdChlbmFibGVkPVRSVUUpKQ0KQk1JPC1jbGVhbiAgJT4lIG11dGF0ZShibWlfY2F0ID0gY3V0KGJtaSwNCiAgYnJlYWtzID0gYygwLCAxOC41LCAyNSwgMzAsIDYwKSwNCiAgbGFiZWxzID0gYygiVW5kZXIgV2VpZ2h0IiwgIk5vcm1hbCBXZWlnaHQiLCAiT3ZlcndlaWdodCIsICJPYmVzZSIpDQopKQ0KQk1JICU+JSANCiAgY291bnQoYm1pX2NhdCkgJT4lIA0KICBoY2hhcnQoJ2JhcicsIGhjYWVzKHggPSAnYm1pX2NhdCcsIHkgPSAnbicpKSU+JSBoY19jaGFydCh0eXBlID0gImJhciIsIG9wdGlvbnMzZCA9IGxpc3QoZW5hYmxlZCA9IFRSVUUsIGFscGhhID0gMzAsIGJldGEgPSAwKSklPiUNCiAgICBoY19wbG90T3B0aW9ucyhzZXJpZXMgPSBsaXN0KA0KICAgICAgICBib3JkZXJXaWR0aD0gMCwNCiAgICAgICAgZGF0YUxhYmVscyA9IGxpc3QoDQogICAgICAgICAgICBlbmFibGVkID0gVFJVRSwNCiAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwNCiAgICAgICAgICAgIGZvcm1hdCA9ICd7cG9pbnQueX0nKSkpDQojQ29ycmVsYXRpb24gdGFibGUNCg0KbGlicmFyeShjb3JycikNCmNvcjwtY2xlYW4gJT4lIA0KICBjb3JyZWxhdGUoKSAlPiUgDQogIGZvY3VzKGNoYXJnZXMpICU+JWFycmFuZ2UoZGVzYyhjaGFyZ2VzKSkNCg0Ka25pdHI6OmthYmxlKA0KIGNvciwgY2FwdGlvbiA9ICJDb3JyZWxhdGlvbiBUYWJsZSIpJT4lDQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gRikNCmNsZWFuJT4lDQogIGhjaGFydCh0eXBlID0gImNvbHVtbiIsIGhjYWVzKHggPSBzbW9rZXIsIHkgPSBjaGFyZ2VzKSklPiUgaGNfY2hhcnQodHlwZSA9ICJjb2x1bW4iLCBvcHRpb25zM2QgPSBsaXN0KGVuYWJsZWQgPSBUUlVFLCBhbHBoYSA9IDMwLCBiZXRhID0gMCkpJT4lIGhjX3RpdGxlKHRleHQ9J1RoZSBjb3N0IG9mIGhlYWx0aCBpbnN1cmFuY2UgZm9yIHNtb2tlcnMgdnMuIG5vbnNtb2tlcnMnKQ0KY2xlYW4lPiUNCiAgaGNoYXJ0KHR5cGUgPSAic2NhdHRlciIsIGhjYWVzKHggPSBhZ2UsIHkgPSBjaGFyZ2VzKSklPiUgaGNfY2hhcnQodHlwZSA9ICJzY2F0dGVyIiwgb3B0aW9uczNkID0gbGlzdChlbmFibGVkID0gVFJVRSwgYWxwaGEgPSAzMCwgYmV0YSA9IDApKSU+JSBoY190aXRsZSh0ZXh0PSdIZWFsdGggSW5zdXJhbmNlIENoYXJnZXMgYnkgQWdlJykNCmNsZWFuJT4lDQogIGhjaGFydCh0eXBlID0gInNjYXR0ZXIiLCBoY2Flcyh4ID0gYm1pLCB5ID0gY2hhcmdlcykpJT4lIGhjX2NoYXJ0KHR5cGUgPSAic2NhdHRlciIsIG9wdGlvbnMzZCA9IGxpc3QoZW5hYmxlZCA9IFRSVUUsIGFscGhhID0gMzAsIGJldGEgPSAwKSklPiUgaGNfdGl0bGUodGV4dD0nQk1JIGFuZCBIZWFsdGggSW5zdXJhbmNlIENoYXJnZXMnKQ0KDQpjbGVhbiU+JQ0KICBoY2hhcnQodHlwZSA9ICJzY2F0dGVyIiwgaGNhZXMoeCA9IGNoaWxkcmVuLCB5ID0gY2hhcmdlcykpJT4lIGhjX2NoYXJ0KHR5cGUgPSAic2NhdHRlciIsIG9wdGlvbnMzZCA9IGxpc3QoZW5hYmxlZCA9IFRSVUUsIGFscGhhID0gMzAsIGJldGEgPSAwKSklPiUgaGNfdGl0bGUodGV4dD0nQW1vdW50IG9mIGNoaWxkcmVuIGFuZCBIZWFsdGggSW5zdXJhbmNlIENoYXJnZXMnKQ0KUk5Ha2luZChzYW1wbGUua2luZCA9ICJSb3VuZGluZyIpDQpzZXQuc2VlZCgxMDApIA0KaW5kZXhfaW5zIDwtIHNhbXBsZSh4ID0gbnJvdyhjbGVhbikgLCBzaXplID0gbnJvdyhjbGVhbikqMC44KSANCmRhdGFfdHJhaW4gPC0gY2xlYW5baW5kZXhfaW5zICwgXQ0KZGF0YV90ZXN0IDwtIGNsZWFuWy1pbmRleF9pbnMsIF0NCmNhdCgiIFNpemUgb2YgZGF0YSB0cmFpbjoiLGRpbShkYXRhX3RyYWluKSwiXG4iLCJTaXplIG9mIGRhdGEgdGVzdCA6IixkaW0oZGF0YV90ZXN0KSkNCmBgYA0KDQoNCiMjIEJ1aWxkaW5nIG1vZGVscw0KDQoxLiBTaW1wbGUgTGluZWFyIFJlZ3Jlc3Npb246DQoNCmBgYHtyfQ0KI1NlbGVjdGluZyBwcmVkaWN0b3IgdmFyaWFibGUgKGFnZSkgYW5kIHRhcmdldCB2YXJpYWJsZSAoY2hhcmdlcykNCnNpbXBsZV9saW5lYXJfbW9kZWwgPC0gbG0oY2hhcmdlcyB+IGFnZSwgZGF0YSA9IEluc3VyYW5jZSkNCg0KI1N1bW1hcnkgb2YgdGhlIG1vZGVsDQpzdW1tYXJ5KHNpbXBsZV9saW5lYXJfbW9kZWwpDQoNCmBgYA0KDQpPdmVyYWxsLCB0aGUgbW9kZWwgc3VnZ2VzdHMgdGhhdCB0aGVyZSBpcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwIGJldHdlZW4gYWdlIGFuZCBjaGFyZ2VzLiBIb3dldmVyLCB0aGUgcmVsYXRpdmVseSBsb3cgUi1zcXVhcmVkIHZhbHVlIGluZGljYXRlcyB0aGF0IGFnZSBhbG9uZSBleHBsYWlucyBvbmx5IGEgc21hbGwgcG9ydGlvbiBvZiB0aGUgdmFyaWFiaWxpdHkgaW4gY2hhcmdlcy4NCg0KMi4gTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb246DQoNCmBgYHtyfQ0KI1NlbGVjdGluZyBwcmVkaWN0b3IgdmFyaWFibGVzIChhZ2UsIGJtaSwgc21va2VyLCBldGMuKSBhbmQgdGFyZ2V0IHZhcmlhYmxlIChjaGFyZ2VzKQ0KbXVsdGlwbGVfbGluZWFyX21vZGVsIDwtIGxtKGNoYXJnZXMgfiBhZ2UgKyBibWkgKyBzbW9rZXIgKyBjaGlsZHJlbiArIHJlZ2lvbiwgZGF0YSA9IEluc3VyYW5jZSkNCg0KI1N1bW1hcnkgb2YgdGhlIG1vZGVsDQpzdW1tYXJ5KG11bHRpcGxlX2xpbmVhcl9tb2RlbCkNCg0KYGBgDQoNCk92ZXJhbGwsIHRoZSBtb2RlbCBzdWdnZXN0cyB0aGF0IGFnZSwgQk1JLCBzbW9raW5nIHN0YXR1cywgYW5kIHRoZSBudW1iZXIgb2YgY2hpbGRyZW4gaGF2ZSBzaWduaWZpY2FudCBlZmZlY3RzIG9uIGluc3VyYW5jZSBjaGFyZ2VzLiBIb3dldmVyLCB0aGUgcmVnaW9uIHZhcmlhYmxlIG1heSBub3QgaGF2ZSBhIHNpZ25pZmljYW50IGVmZmVjdCBvbiBjaGFyZ2VzIGFmdGVyIGNvbnNpZGVyaW5nIG90aGVyIHZhcmlhYmxlcyBpbiB0aGUgbW9kZWwuDQoNCg0KMy4gU2ltcGxlIExvZ2lzdGljIFJlZ3Jlc3Npb246DQoNCmBgYHtyfQ0KI0NhdGVnb3JpemluZyBjaGFyZ2VzIGludG8gdHdvIGNsYXNzZXMgYmFzZWQgb24gYSB0aHJlc2hvbGQgdmFsdWUNCiNGb3IgZGVtb25zdHJhdGlvbiwgbGV0J3MgY29uc2lkZXIgY2hhcmdlcyBhYm92ZSB0aGUgbWVkaWFuIGFzIGhpZ2ggYW5kIGFsbCBvdGhlciBjaGFyZ2VzIGFzIGxvdw0KSW5zdXJhbmNlJGNoYXJnZV9jYXRlZ29yeV9iaW5hcnkgPC0gaWZlbHNlKEluc3VyYW5jZSRjaGFyZ2VzID4gbWVkaWFuKEluc3VyYW5jZSRjaGFyZ2VzKSwgMSwgMCkNCg0KI0J1aWxkaW5nIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBiaW5hcnkgdGFyZ2V0IHZhcmlhYmxlDQpsb2dpc3RpY19tb2RlbCA8LSBnbG0oY2hhcmdlX2NhdGVnb3J5X2JpbmFyeSB+IGFnZSArIGJtaSArIHNtb2tlciArIGNoaWxkcmVuICsgcmVnaW9uLCANCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gSW5zdXJhbmNlLCBmYW1pbHkgPSBiaW5vbWlhbChsaW5rID0gImxvZ2l0IikpDQoNCiNTdW1tYXJ5IG9mIHRoZSBtb2RlbA0Kc3VtbWFyeShsb2dpc3RpY19tb2RlbCkNCg0KDQpgYGANCg0KDQpJbiB0aGUgY29udGV4dCBvZiB0aGUgcHJvdmlkZWQgZGF0YSBhbmQgdGhlIHRhcmdldCB2YXJpYWJsZSAoY2hhcmdlX2NhdGVnb3J5X2JpbmFyeSksIHJ1bm5pbmcgYSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsIG1pZ2h0IG5vdCBiZSB0aGUgbW9zdCBhcHByb3ByaWF0ZSBjaG9pY2UuIExvZ2lzdGljIHJlZ3Jlc3Npb24gaXMgdHlwaWNhbGx5IHVzZWQgZm9yIGJpbmFyeSBjbGFzc2lmaWNhdGlvbiBwcm9ibGVtcyB3aGVyZSB0aGUgb3V0Y29tZSB2YXJpYWJsZSBpcyBjYXRlZ29yaWNhbCBhbmQgYmluYXJ5LCBtZWFuaW5nIGl0IGhhcyBvbmx5IHR3byBwb3NzaWJsZSBvdXRjb21lcyBvciBjbGFzc2VzLg0KDQo=