Part I: Research Question

Which variables are the most important in regards to predicting which patients are at a high risk of readmission?


Variables:

library(readr)
df_raw <- read.csv('~/Documents/WGU MSDA/D206/medical_raw_data.csv')
str(df_raw)
'data.frame':   10000 obs. of  53 variables:
 $ X                 : int  1 2 3 4 5 6 7 8 9 10 ...
 $ CaseOrder         : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Customer_id       : chr  "C412403" "Z919181" "F995323" "A879973" ...
 $ Interaction       : chr  "8cd49b13-f45a-4b47-a2bd-173ffa932c2f" "d2450b70-0337-4406-bdbb-bc1037f1734c" "a2057123-abf5-4a2c-abad-8ffe33512562" "1dec528d-eb34-4079-adce-0d7a40e82205" ...
 $ UID               : chr  "3a83ddb66e2ae73798bdf1d705dc0932" "176354c5eef714957d486009feabf195" "e19a0fa00aeda885b8a436757e889bc9" "cd17d7b6d152cb6f23957346d11c3f07" ...
 $ City              : chr  "Eva" "Marianna" "Sioux Falls" "New Richland" ...
 $ State             : chr  "AL" "FL" "SD" "MN" ...
 $ County            : chr  "Morgan" "Jackson" "Minnehaha" "Waseca" ...
 $ Zip               : int  35621 32446 57110 56072 23181 74423 44086 22641 32404 56362 ...
 $ Lat               : num  34.3 30.8 43.5 43.9 37.6 ...
 $ Lng               : num  -86.7 -85.2 -96.6 -93.5 -76.9 ...
 $ Population        : int  2951 11303 17125 2162 5287 981 2558 479 40029 5840 ...
 $ Area              : chr  "Suburban" "Urban" "Suburban" "Suburban" ...
 $ Timezone          : chr  "America/Chicago" "America/Chicago" "America/Chicago" "America/Chicago" ...
 $ Job               : chr  "Psychologist, sport and exercise" "Community development worker" "Chief Executive Officer" "Early years teacher" ...
 $ Children          : int  1 3 3 0 NA NA 0 7 NA 2 ...
 $ Age               : int  53 51 53 78 22 76 50 40 48 78 ...
 $ Education         : chr  "Some College, Less than 1 Year" "Some College, 1 or More Years, No Degree" "Some College, 1 or More Years, No Degree" "GED or Alternative Credential" ...
 $ Employment        : chr  "Full Time" "Full Time" "Retired" "Retired" ...
 $ Income            : num  86576 46806 14370 39741 1210 ...
 $ Marital           : chr  "Divorced" "Married" "Widowed" "Married" ...
 $ Gender            : chr  "Male" "Female" "Female" "Male" ...
 $ ReAdmis           : chr  "No" "No" "No" "No" ...
 $ VitD_levels       : num  17.8 19 17.4 17.4 16.9 ...
 $ Doc_visits        : int  6 4 4 4 5 6 6 7 6 7 ...
 $ Full_meals_eaten  : int  0 2 1 1 0 0 0 2 3 1 ...
 $ VitD_supp         : int  0 1 0 0 2 0 0 0 0 2 ...
 $ Soft_drink        : chr  NA "No" "No" "No" ...
 $ Initial_admin     : chr  "Emergency Admission" "Emergency Admission" "Elective Admission" "Elective Admission" ...
 $ HighBlood         : chr  "Yes" "Yes" "Yes" "No" ...
 $ Stroke            : chr  "No" "No" "No" "Yes" ...
 $ Complication_risk : chr  "Medium" "High" "Medium" "Medium" ...
 $ Overweight        : int  0 1 1 0 0 1 1 1 1 1 ...
 $ Arthritis         : chr  "Yes" "No" "No" "Yes" ...
 $ Diabetes          : chr  "Yes" "No" "Yes" "No" ...
 $ Hyperlipidemia    : chr  "No" "No" "No" "No" ...
 $ BackPain          : chr  "Yes" "No" "No" "No" ...
 $ Anxiety           : int  1 NA NA NA 0 0 1 0 NA 0 ...
 $ Allergic_rhinitis : chr  "Yes" "No" "No" "No" ...
 $ Reflux_esophagitis: chr  "No" "Yes" "No" "Yes" ...
 $ Asthma            : chr  "Yes" "No" "No" "Yes" ...
 $ Services          : chr  "Blood Work" "Intravenous" "Blood Work" "Blood Work" ...
 $ Initial_days      : num  10.59 15.13 4.77 1.71 1.25 ...
 $ TotalCharge       : num  3191 4215 2178 2465 1886 ...
 $ Additional_charges: num  17939 17613 17505 12993 3717 ...
 $ Item1             : int  3 3 2 3 2 4 4 1 3 5 ...
 $ Item2             : int  3 4 4 5 1 5 3 2 3 5 ...
 $ Item3             : int  2 3 4 5 3 4 3 2 2 5 ...
 $ Item4             : int  2 4 4 3 3 4 2 5 3 3 ...
 $ Item5             : int  4 4 3 4 5 3 3 4 3 4 ...
 $ Item6             : int  3 4 4 5 3 5 4 2 3 2 ...
 $ Item7             : int  3 3 3 5 4 4 5 4 4 3 ...
 $ Item8             : int  4 3 3 5 3 6 5 2 2 2 ...

Unnamed: integer index
CaseOrder: integer index to preserve original order of raw data
Customer_id: character string unique to patient
Interaction: character string unique to patient transactions, procedures and admissions
UID: character string unique to patient transactions, procedures and admissions
City: character string indicating patient’s city of residence as listed on the billing statement
State: character string indicating patient’s state of residence as listed on the billing statement
County: character string indicating patient’s county of residence as listed on the billing statement
Zip: integer indicating patient’s zip code of residence as listed on the billing statement
Lat: continuous numeric GPS coordinates indicating latitude of patient’s residence as listed on the billing statement
Lng: continuous numeric GPS coordinates indicating longitude of patient’s residence as listed on the billing statement
Population: integer value indicating population within a mile radius of patient- based on census data
Area: nominal categorical - character string indicating area type- based on census data

unique(df_raw$Area)
[1] "Suburban" "Urban"    "Rural"   

Timezone: nominal categorical - character string indicating timezone of patient’s residence as provided by patient

unique(df_raw$Timezone)
 [1] "America/Chicago"                "America/New_York"               "America/Los_Angeles"           
 [4] "America/Indiana/Indianapolis"   "America/Detroit"                "America/Denver"                
 [7] "America/Nome"                   "America/Anchorage"              "America/Phoenix"               
[10] "America/Boise"                  "America/Puerto_Rico"            "America/Yakutat"               
[13] "Pacific/Honolulu"               "America/Menominee"              "America/Kentucky/Louisville"   
[16] "America/Indiana/Vincennes"      "America/Toronto"                "America/Indiana/Marengo"       
[19] "America/Indiana/Winamac"        "America/Indiana/Tell_City"      "America/Sitka"                 
[22] "America/Indiana/Knox"           "America/North_Dakota/New_Salem" "America/Indiana/Vevay"         
[25] "America/Adak"                   "America/North_Dakota/Beulah"   

Job: nominal categorical - character string indicating patient’s (or primary insurance holder’s) job as provided by patient
Children: integer indicating number of children in patient’s household as provided by patient
Age: integer indicating patient’s age as provided by patient
Education: nominal categorical - character string indicating patient’s highest earned degree as provided by patient

unique(df_raw$Education)
 [1] "Some College, Less than 1 Year"           "Some College, 1 or More Years, No Degree"
 [3] "GED or Alternative Credential"            "Regular High School Diploma"             
 [5] "Bachelor's Degree"                        "Master's Degree"                         
 [7] "Nursery School to 8th Grade"              "9th Grade to 12th Grade, No Diploma"     
 [9] "Doctorate Degree"                         "Associate's Degree"                      
[11] "Professional School Degree"               "No Schooling Completed"                  

Employment: categorical - character string indicating patient’s employment status as provided by patient

unique(df_raw$Employment)
[1] "Full Time"  "Retired"    "Unemployed" "Student"    "Part Time" 

Income: - numeric value indicating annual income of patient (or primary insurance holder) as provided by patient
Marital: nominal categorical - character string indicating patient’s (or primary insurance holder’s) marital status as provided by patient

unique(df_raw$Marital)
[1] "Divorced"      "Married"       "Widowed"       "Never Married" "Separated"    

Gender: nominal categorical - character string indicating patient’s gender as provided by patient

unique(df_raw$Gender)
[1] "Male"                 "Female"               "Prefer not to answer"

ReAdmis: binary categorical - character string indicating whether or not patient was readmitted within a month of release [Yes, No] *target variable
VitD_levels: continuous numeric value indicating patient’s vitamin D levels as measured in ng/mL
Doc_visits: integer indicating number of times the primary physician visited the patient during the initial hospitalization
Full_meals_eaten: integer indicating number of full meals eaten (partial meals count as 0) VitD_supp: integer indicating number of times that vitamin D supplements were administered to patient
Soft_drink: binary categorical - character string indicating whether or not patient regularly drinks three or more sodas in a day [Yes, No]
Initial_admin: nominal categorical - character string indicating the means by which the patient was initially admitted into the hospital

unique(df_raw$Initial_admin)
[1] "Emergency Admission"   "Elective Admission"    "Observation Admission"

HighBlood: binary categorical - character string indicating whether or not the patient has high blood pressure [Yes, No]
Stroke: binary categorical - character string indicating whether or not the patient has had a stroke [Yes, No]
Complication_risk: ordinal categorical - character string indicating level of complication risk [High, Medium, Low]
Overweight: binary categorical - integer indicating whether (1) or not (0) the patient is overweight, as determined by age, gender, and height
Arthritis: binary categorical - character string indicating whether or not the patient has arthritis [Yes, No]
Diabetes: binary categorical - character string indicating whether or not the patient has diabetes [Yes, No]
Hyperlipidemia: binary categorical - character string indicating whether or not the patient has hyperlipidemia [Yes, No]
BackPain: binary categorical - character string indicating whether or not the patient has chronic backpain [Yes, No]
Anxiety: binary categorical - integer indicating whether (1) or not (0) the patient has an anxiety disorder
Allergic_rhinitis: binary categorical - character string indicating whether or not the patient has allergic rhinitis [Yes, No]
Reflux_esophagitis: binary categorical - character string indicating whether or not the patient has reflux esophagitis [Yes, No]
Asthma: binary categorical - character string indicating whether or not the patient has asthma [Yes, No]
Services: nominal categorical - character string indicating the primary service the patient received while hospitalized

unique(df_raw$Services)
[1] "Blood Work"  "Intravenous" "CT Scan"     "MRI"        

Initial_days: numeric value indicating number of days the patient stayed in the hospital during the initial visit
TotalCharge: numeric value indicating patient’s average daily charges for typical (not specialized) treatments and services during the initial visit
Additional_charges: numeric value indicating patient’s average daily charges for additional treatments and services during the initial visit
Item1: integer value indicating the level of importance of timely admission from most important (1) to least important (8), as reported by patient
Item2: integer value indicating the level of importance of timely treatment from most important (1) to least important (8), as reported by patient
Item3: integer value indicating the level of importance of timely visits from most important (1) to least important (8), as reported by patient
Item4: integer value indicating the level of importance of reliability from most important (1) to least important (8), as reported by patient
Item5: integer value indicating the level of importance of options from most important (1) to least important (8), as reported by patient
Item6: integer value indicating the level of importance of hours of treatment from most important (1) to least important (8), as reported by patient
Item7: integer value indicating the level of importance of courteous staff from most important (1) to least important (8), as reported by patient
Item8: integer value indicating the level of importance of evidence of active listeing from doctor from most important (1) to least important (8), as reported by patient

Data-Cleaning Plan

In order to asses the quality of- and clean- the data, I will be using R. R was created by statisticians, making it ideal for statistical analysis. R also allows for interpretable visualizations, and packages built for cleaning data and identifying outliers. Some of these packages include readr for reading the raw data file into R, caret for one hot encoding using dummy variables, and dplyr and ggplot2, for various calculations and visualizations.

- Reset index
- Removal of redundant, irrelevant, or misleading variables
-‘X’, ‘Customer_id’, ‘Interaction_id’, ‘Job’, ‘Income’, ‘Marital’
- Data was collected on the job and marital status of either the patient or the primary insurance holder. The inconsistency of this data may lead to false conclusions, and will therefore be removed.
- Renaming misleading variables -Data was collected on the income of either the patient or the primary insurance holder, so the field name will be renamed to reflect this. - Re-expression of categorical data as numeric data
- Change character values to numeric values or separate into separate variables using dummy variables
(ref: https://stackoverflow.com/questions/54602192/make-only-some-features-dummyvars) - Imputation of NULL values
- Change NULL values of patient-provided data to reflect a “0” response - MICE imputation for all other NULL values
(ref: https://www.rdocumentation.org/packages/mice/versions/2.25/topics/mice) - Detection of outliers
- View summary of univariate statistics, search for flags
- Visualize potential outliers with boxplots
- Run hypothesis test on potential outliers (grubbs test)
- Standardize variables, when necessary
- No data will be deleted or changed unless it was an obvious mistake. Changing available data will skew models toward a conclusion that may not generalize if data has been overly-manipulated.

Data Cleaning

head(df_raw)

Remove irrelevant columns

library(dplyr)

Attaching package: ‘dplyr’

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

    filter, lag

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

    intersect, setdiff, setequal, union
df <- df_raw[,c(6:53)]
df <- select(df, c(-Job, -Marital))

Rename misleading variable names

names(df)[names(df) == 'Income'] <- 'Income_household'
names(df)[names(df) == 'Item1'] <- 'Survey_TimelyAdmin'
names(df)[names(df) == 'Item2'] <- 'Survey_TimelyTreatment'
names(df)[names(df) == 'Item3'] <- 'Survey_TimelyVisits'
names(df)[names(df) == 'Item4'] <- 'Survey_Reliability'
names(df)[names(df) == 'Item5'] <- 'Survey_Options'
names(df)[names(df) == 'Item6'] <- 'Survey_HoursTreatment'
names(df)[names(df) == 'Item7'] <- 'Survey_CourteousStaff'
names(df)[names(df) == 'Item8'] <- 'Survey_ActiveListening'
head(df)

Set index

num_rows <- dim(df)[1]
row.names(df) <- c(1:num_rows)
head(df)

Re-expression of categorical data as numeric data

State

x <- df[order(df$State),"State"]
unique(x)
 [1] "AK" "AL" "AR" "AZ" "CA" "CO" "CT" "DC" "DE" "FL" "GA" "HI" "IA" "ID" "IL" "IN" "KS" "KY" "LA" "MA" "MD"
[22] "ME" "MI" "MN" "MO" "MS" "MT" "NC" "ND" "NE" "NH" "NJ" "NM" "NV" "NY" "OH" "OK" "OR" "PA" "PR" "RI" "SC"
[43] "SD" "TN" "TX" "UT" "VA" "VT" "WA" "WI" "WV" "WY"
library(plyr)
-------------------------------------------------------------------------------------------------------------
You have loaded plyr after dplyr - this is likely to cause problems.
If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
library(plyr); library(dplyr)
-------------------------------------------------------------------------------------------------------------

Attaching package: ‘plyr’

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

    arrange, count, desc, failwith, id, mutate, rename, summarise, summarize
data <- df$State
state_dict <- c(
  "AL" = 1, "AK" = 2, "AZ" = 3, "AR" = 4, "CA" = 5, "CO" = 6, "CT" = 7, "DE" = 8, "DC" = 9, "FL" = 10, 
  "GA" = 11, "HI" = 12, "ID" = 13, "IL" = 14, "IN" = 15, "IA" = 16, "KS" = 17, "KY" = 18, "LA" = 19, "ME" = 20, 
  "MD" = 21, "MA" = 22, "MI" = 23, "MN" = 24, "MS" = 25, "MO" = 26, "MT" = 27, "NE" = 28, "NV" = 29, "NH" = 30, 
  "NJ" = 31, "NM" = 32, "NY" = 33, "NC" = 34, "ND" = 35, "OH" = 36, "OK" = 37, "OR" = 38, "PA" = 39, "PR" = 40,
  "RI" = 41, "SC" = 42, "SD" = 43, "TN" = 44, "TX" = 45, "UT" = 46, "VT" = 47, "VA" = 48, "WA" = 49, "WV" = 50,
  "WI" = 51, "WY" = 52)
state_val <- revalue(x= data, replace = state_dict)
df$State <- as.numeric(state_val)

Area

unique(df$Area)
[1] "Suburban" "Urban"    "Rural"   
data <- df$Area
my_dict <- c(
  "Rural" = 1,
  "Suburban" = 2,
  "Urban" = 3)
area_val <- revalue(x= data, replace = my_dict)
df$Area <- as.numeric(area_val)

Timezone

unique(df$Timezone)
 [1] "America/Chicago"                "America/New_York"               "America/Los_Angeles"           
 [4] "America/Indiana/Indianapolis"   "America/Detroit"                "America/Denver"                
 [7] "America/Nome"                   "America/Anchorage"              "America/Phoenix"               
[10] "America/Boise"                  "America/Puerto_Rico"            "America/Yakutat"               
[13] "Pacific/Honolulu"               "America/Menominee"              "America/Kentucky/Louisville"   
[16] "America/Indiana/Vincennes"      "America/Toronto"                "America/Indiana/Marengo"       
[19] "America/Indiana/Winamac"        "America/Indiana/Tell_City"      "America/Sitka"                 
[22] "America/Indiana/Knox"           "America/North_Dakota/New_Salem" "America/Indiana/Vevay"         
[25] "America/Adak"                   "America/North_Dakota/Beulah"   
data <- df$Timezone
my_dict <- c(
  "America/Puerto_Rico" = -4,
  "America/Detroit" = -5,
  "America/Indiana/Indianapolis" = -5,
  "America/Indiana/Marengo" = -5,
  "America/Indiana/Vincennes" = -5,
  "America/Indiana/Vevay" = -5,
  "America/Indiana/Winamac" = -5,
  "America/Kentucky/Louisville" = -5,
  "America/New_York" = -5,
  "America/Toronto" = -5,
  "America/Chicago" = -6,
  "America/Indiana/Knox" = -6,
  "America/Indiana/Tell_City" = -6,
  "America/Menominee" = -6,
  "America/North_Dakota/Beulah" = -6,
  "America/North_Dakota/New_Salem" = -6,
  "America/Boise" = -7,
  "America/Denver" = -7,
  "America/Phoenix" = -7,
  "America/Los_Angeles" = -8,
  "America/Anchorage" = -9,
  "America/Nome" = -9,
  "America/Sitka" = -9,
  "America/Yakutat" = -9,
  "America/Adak" = -10,
  "Pacific/Honolulu" = -10)
timezone_val <- revalue(x= data, replace = my_dict)
df$Timezone <- as.numeric(timezone_val)

Education

unique(df$Education)
 [1] "Some College, Less than 1 Year"           "Some College, 1 or More Years, No Degree"
 [3] "GED or Alternative Credential"            "Regular High School Diploma"             
 [5] "Bachelor's Degree"                        "Master's Degree"                         
 [7] "Nursery School to 8th Grade"              "9th Grade to 12th Grade, No Diploma"     
 [9] "Doctorate Degree"                         "Associate's Degree"                      
[11] "Professional School Degree"               "No Schooling Completed"                  
data <- df$Education
my_dict <- c(
  "No Schooling Completed" = 0,
  "Nursery School to 8th Grade" = 8,
  "9th Grade to 12th Grade, No Diploma" = 12,
  "GED or Alternative Credential" = 12,
  "Regular High School Diploma" = 12,
  "Some College, Less than 1 Year" = 13,
  "Some College, 1 or More Years, No Degree" = 14,
  "Associate's Degree" = 15,
  "Bachelor's Degree" = 16,
  "Master's Degree" = 18,
  "Professional School Degree" = 20,
  "Doctorate Degree" = 24
  )
education_val <- revalue(x= data, replace = my_dict)
df$Education <- as.numeric(education_val)

Employment

unique(df$Employment)
[1] "Full Time"  "Retired"    "Unemployed" "Student"    "Part Time" 
library(caret)
Loading required package: lattice
Loading required package: ggplot2
dmy <- dummyVars(" ~ Employment", data = df)
oh_encoded <- data.frame(predict(dmy, newdata = df))
df$Employment_FullTime <- oh_encoded$EmploymentFull.Time
df$Employment_PartTime <- oh_encoded$EmploymentPart.Time
df$Employment_Retired <- oh_encoded$EmploymentRetired
df$Student <- oh_encoded$EmploymentStudent
df$Unemployed <- oh_encoded$EmploymentUnemployed
df <- select(df, -Employment)

Gender

unique(df$Gender)
[1] "Male"                 "Female"               "Prefer not to answer"
dmy <- dummyVars(" ~ Gender", data = df)
oh_encoded <- data.frame(predict(dmy, newdata = df))
df$Female <- oh_encoded$GenderFemale
df$Male <- oh_encoded$GenderMale
df <- select(df, -Gender)

Readmission

unique(df$ReAdmis)
[1] "No"  "Yes"
data <- df$ReAdmis
bi_dict <- c(
  "No" = 0,
  "Yes" = 1
  )
binary_val <- revalue(x= data, replace = bi_dict)
df$ReAdmis <- as.numeric(binary_val)

Soft Drink

unique(df$Soft_drink)
[1] NA    "No"  "Yes"
data <- df$Soft_drink
binary_val <- revalue(x= data, replace = bi_dict)
df$Soft_drink <- as.numeric(binary_val)

Initial Admission

unique(df$Initial_admin)
[1] "Emergency Admission"   "Elective Admission"    "Observation Admission"
dmy <- dummyVars(" ~ Initial_admin", data = df)
oh_encoded <- data.frame(predict(dmy, newdata = df))
df$Admin_elective <- oh_encoded$Initial_adminElective.Admission
df$Admin_observation <- oh_encoded$Initial_adminObservation.Admission
df$Admin_emergency <- oh_encoded$Initial_adminEmergency.Admission
df <- select(df, -Initial_admin)

High blood pressure

data <- df$HighBlood
binary_val <- revalue(x= data, replace = bi_dict)
df$HighBlood <- as.numeric(binary_val)

Stroke

data <- df$Stroke
binary_val <- revalue(x= data, replace = bi_dict)
df$Stroke <- as.numeric(binary_val)

Complication Risk

unique(df$Complication_risk)
[1] "Medium" "High"   "Low"   
data <- df$Complication_risk
my_dict <- c(
  "Low" = 1,
  "Medium" = 2,
  "High" = 3)
risk_val <- revalue(x= data, replace = my_dict)
df$Complication_risk <- as.numeric(risk_val)

Arthritis

data <- df$Arthritis
binary_val <- revalue(x= data, replace = bi_dict)
df$Arthritis <- as.numeric(binary_val)

Diabetes

data <- df$Diabetes
binary_val <- revalue(x= data, replace = bi_dict)
df$Diabetes <- as.numeric(binary_val)

Hyperlipidemia

data <- df$Hyperlipidemia
binary_val <- revalue(x= data, replace = bi_dict)
df$Hyperlipidemia <- as.numeric(binary_val)

Back Pain

data <- df$BackPain
binary_val <- revalue(x= data, replace = bi_dict)
df$BackPain <- as.numeric(binary_val)

Allergic rhinitis

data <- df$Allergic_rhinitis
binary_val <- revalue(x= data, replace = bi_dict)
df$Allergic_rhinitis <- as.numeric(binary_val)

Reflux esophagitis

data <- df$Reflux_esophagitis
binary_val <- revalue(x= data, replace = bi_dict)
df$Reflux_esophagitis <- as.numeric(binary_val)

Asthma

data <- df$Asthma
binary_val <- revalue(x= data, replace = bi_dict)
df$Asthma <- as.numeric(binary_val)

Services

unique(df$Services)
[1] "Blood Work"  "Intravenous" "CT Scan"     "MRI"        
data <- df$Services
my_dict <- c(
  "Blood Work" = 1,
  "Intravenous" = 2,
  "CT Scan" = 3,
  "MRI" = 4)
risk_val <- revalue(x= data, replace = my_dict)
df$Services <- as.numeric(risk_val)

Imputation of NULL values

summary(df)
     City               State          County               Zip             Lat             Lng         
 Length:10000       Min.   : 1.00   Length:10000       Min.   :  610   Min.   :17.97   Min.   :-174.21  
 Class :character   1st Qu.:14.00   Class :character   1st Qu.:27592   1st Qu.:35.26   1st Qu.: -97.35  
 Mode  :character   Median :26.00   Mode  :character   Median :50207   Median :39.42   Median : -88.40  
                    Mean   :26.84                      Mean   :50159   Mean   :38.75   Mean   : -91.24  
                    3rd Qu.:39.00                      3rd Qu.:72412   3rd Qu.:42.04   3rd Qu.: -80.44  
                    Max.   :52.00                      Max.   :99929   Max.   :70.56   Max.   : -65.29  
                                                                                                        
   Population            Area          Timezone          Children           Age         Education    
 Min.   :     0.0   Min.   :1.000   Min.   :-10.000   Min.   : 0.000   Min.   :18.0   Min.   : 0.00  
 1st Qu.:   694.8   1st Qu.:1.000   1st Qu.: -6.000   1st Qu.: 0.000   1st Qu.:35.0   1st Qu.:12.00  
 Median :  2769.0   Median :2.000   Median : -6.000   Median : 1.000   Median :53.0   Median :14.00  
 Mean   :  9965.2   Mean   :1.993   Mean   : -5.861   Mean   : 2.098   Mean   :53.3   Mean   :13.61  
 3rd Qu.: 13945.0   3rd Qu.:3.000   3rd Qu.: -5.000   3rd Qu.: 3.000   3rd Qu.:71.0   3rd Qu.:16.00  
 Max.   :122814.0   Max.   :3.000   Max.   : -4.000   Max.   :10.000   Max.   :89.0   Max.   :24.00  
                                                      NA's   :2588     NA's   :2414                  
 Income_household      ReAdmis        VitD_levels       Doc_visits    Full_meals_eaten   VitD_supp     
 Min.   :   154.1   Min.   :0.0000   Min.   : 9.519   Min.   :1.000   Min.   :0.000    Min.   :0.0000  
 1st Qu.: 19450.8   1st Qu.:0.0000   1st Qu.:16.513   1st Qu.:4.000   1st Qu.:0.000    1st Qu.:0.0000  
 Median : 33942.3   Median :0.0000   Median :18.081   Median :5.000   Median :1.000    Median :0.0000  
 Mean   : 40484.4   Mean   :0.3669   Mean   :19.413   Mean   :5.012   Mean   :1.001    Mean   :0.3989  
 3rd Qu.: 54075.2   3rd Qu.:1.0000   3rd Qu.:19.790   3rd Qu.:6.000   3rd Qu.:2.000    3rd Qu.:1.0000  
 Max.   :207249.1   Max.   :1.0000   Max.   :53.019   Max.   :9.000   Max.   :7.000    Max.   :5.0000  
 NA's   :2464                                                                                          
   Soft_drink       HighBlood         Stroke       Complication_risk   Overweight       Arthritis     
 Min.   :0.0000   Min.   :0.000   Min.   :0.0000   Min.   :1.000     Min.   :0.0000   Min.   :0.0000  
 1st Qu.:0.0000   1st Qu.:0.000   1st Qu.:0.0000   1st Qu.:2.000     1st Qu.:0.0000   1st Qu.:0.0000  
 Median :0.0000   Median :0.000   Median :0.0000   Median :2.000     Median :1.0000   Median :0.0000  
 Mean   :0.2581   Mean   :0.409   Mean   :0.1993   Mean   :2.123     Mean   :0.7091   Mean   :0.3574  
 3rd Qu.:1.0000   3rd Qu.:1.000   3rd Qu.:0.0000   3rd Qu.:3.000     3rd Qu.:1.0000   3rd Qu.:1.0000  
 Max.   :1.0000   Max.   :1.000   Max.   :1.0000   Max.   :3.000     Max.   :1.0000   Max.   :1.0000  
 NA's   :2467                                                        NA's   :982                      
    Diabetes      Hyperlipidemia      BackPain         Anxiety       Allergic_rhinitis Reflux_esophagitis
 Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000    Min.   :0.0000    
 1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000    1st Qu.:0.0000    
 Median :0.0000   Median :0.0000   Median :0.0000   Median :0.0000   Median :0.0000    Median :0.0000    
 Mean   :0.2738   Mean   :0.3372   Mean   :0.4114   Mean   :0.3223   Mean   :0.3941    Mean   :0.4135    
 3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:1.0000    3rd Qu.:1.0000    
 Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000    Max.   :1.0000    
                                                    NA's   :984                                          
     Asthma          Services      Initial_days     TotalCharge    Additional_charges Survey_TimelyAdmin
 Min.   :0.0000   Min.   :1.000   Min.   : 1.002   Min.   : 1257   Min.   : 3126      Min.   :1.000     
 1st Qu.:0.0000   1st Qu.:1.000   1st Qu.: 7.912   1st Qu.: 3253   1st Qu.: 7986      1st Qu.:3.000     
 Median :0.0000   Median :1.000   Median :34.447   Median : 5852   Median :11574      Median :4.000     
 Mean   :0.2893   Mean   :1.672   Mean   :34.432   Mean   : 5892   Mean   :12935      Mean   :3.519     
 3rd Qu.:1.0000   3rd Qu.:2.000   3rd Qu.:61.125   3rd Qu.: 7615   3rd Qu.:15626      3rd Qu.:4.000     
 Max.   :1.0000   Max.   :4.000   Max.   :71.981   Max.   :21524   Max.   :30566      Max.   :8.000     
                                  NA's   :1056                                                          
 Survey_TimelyTreatment Survey_TimelyVisits Survey_Reliability Survey_Options  Survey_HoursTreatment
 Min.   :1.000          Min.   :1.000       Min.   :1.000      Min.   :1.000   Min.   :1.000        
 1st Qu.:3.000          1st Qu.:3.000       1st Qu.:3.000      1st Qu.:3.000   1st Qu.:3.000        
 Median :3.000          Median :4.000       Median :4.000      Median :3.000   Median :4.000        
 Mean   :3.507          Mean   :3.511       Mean   :3.515      Mean   :3.497   Mean   :3.522        
 3rd Qu.:4.000          3rd Qu.:4.000       3rd Qu.:4.000      3rd Qu.:4.000   3rd Qu.:4.000        
 Max.   :7.000          Max.   :8.000       Max.   :7.000      Max.   :7.000   Max.   :7.000        
                                                                                                    
 Survey_CourteousStaff Survey_ActiveListening Employment_FullTime Employment_PartTime Employment_Retired
 Min.   :1.000         Min.   :1.00           Min.   :0.0000      Min.   :0.0000      Min.   :0.000     
 1st Qu.:3.000         1st Qu.:3.00           1st Qu.:0.0000      1st Qu.:0.0000      1st Qu.:0.000     
 Median :3.000         Median :3.00           Median :1.0000      Median :0.0000      Median :0.000     
 Mean   :3.494         Mean   :3.51           Mean   :0.6029      Mean   :0.0991      Mean   :0.098     
 3rd Qu.:4.000         3rd Qu.:4.00           3rd Qu.:1.0000      3rd Qu.:0.0000      3rd Qu.:0.000     
 Max.   :7.000         Max.   :7.00           Max.   :1.0000      Max.   :1.0000      Max.   :1.000     
                                                                                                        
    Student         Unemployed         Female            Male        Admin_elective   Admin_observation
 Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   
 1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   
 Median :0.0000   Median :0.0000   Median :1.0000   Median :0.0000   Median :0.0000   Median :0.0000   
 Mean   :0.1017   Mean   :0.0983   Mean   :0.5018   Mean   :0.4768   Mean   :0.2504   Mean   :0.2436   
 3rd Qu.:0.0000   3rd Qu.:0.0000   3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:0.0000   
 Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   
                                                                                                       
 Admin_emergency
 Min.   :0.000  
 1st Qu.:0.000  
 Median :1.000  
 Mean   :0.506  
 3rd Qu.:1.000  
 Max.   :1.000  
                

NULL values are found in 7 columns :
- Children - Age - Income_household - Soft_drink - Overweight - Anxiety - Initial_days

NULL values of the variables “Children”, “Soft_drink”, and “Anxiety” will be changed to 0. These variables consist of yes/no data, as reported by the patient. It is reasonable to believe that these variables would be left blank by the patient -and therefore recorded as null- if they did not apply to the patient (0).

var <- df$Soft_drink
df$Soft_drink <- replace(var, is.na(var), 0)
var <- df$Anxiety
df$Anxiety <- replace(var, is.na(var), 0)
var <- df$Children
df$Children <- replace(var, is.na(var), 0)

All other NULL values will be filled using MICE

library(mice)

Attaching package: ‘mice’

The following object is masked from ‘package:stats’:

    filter

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

    cbind, rbind
md.pattern(df)
     City State County Zip Lat Lng Population Area Timezone Children Education ReAdmis VitD_levels Doc_visits
4618    1     1      1   1   1   1          1    1        1        1         1       1           1          1
1496    1     1      1   1   1   1          1    1        1        1         1       1           1          1
1481    1     1      1   1   1   1          1    1        1        1         1       1           1          1
467     1     1      1   1   1   1          1    1        1        1         1       1           1          1
535     1     1      1   1   1   1          1    1        1        1         1       1           1          1
187     1     1      1   1   1   1          1    1        1        1         1       1           1          1
165     1     1      1   1   1   1          1    1        1        1         1       1           1          1
69      1     1      1   1   1   1          1    1        1        1         1       1           1          1
509     1     1      1   1   1   1          1    1        1        1         1       1           1          1
166     1     1      1   1   1   1          1    1        1        1         1       1           1          1
153     1     1      1   1   1   1          1    1        1        1         1       1           1          1
54      1     1      1   1   1   1          1    1        1        1         1       1           1          1
53      1     1      1   1   1   1          1    1        1        1         1       1           1          1
22      1     1      1   1   1   1          1    1        1        1         1       1           1          1
22      1     1      1   1   1   1          1    1        1        1         1       1           1          1
3       1     1      1   1   1   1          1    1        1        1         1       1           1          1
        0     0      0   0   0   0          0    0        0        0         0       0           0          0
     Full_meals_eaten VitD_supp Soft_drink HighBlood Stroke Complication_risk Arthritis Diabetes
4618                1         1          1         1      1                 1         1        1
1496                1         1          1         1      1                 1         1        1
1481                1         1          1         1      1                 1         1        1
467                 1         1          1         1      1                 1         1        1
535                 1         1          1         1      1                 1         1        1
187                 1         1          1         1      1                 1         1        1
165                 1         1          1         1      1                 1         1        1
69                  1         1          1         1      1                 1         1        1
509                 1         1          1         1      1                 1         1        1
166                 1         1          1         1      1                 1         1        1
153                 1         1          1         1      1                 1         1        1
54                  1         1          1         1      1                 1         1        1
53                  1         1          1         1      1                 1         1        1
22                  1         1          1         1      1                 1         1        1
22                  1         1          1         1      1                 1         1        1
3                   1         1          1         1      1                 1         1        1
                    0         0          0         0      0                 0         0        0
     Hyperlipidemia BackPain Anxiety Allergic_rhinitis Reflux_esophagitis Asthma Services TotalCharge
4618              1        1       1                 1                  1      1        1           1
1496              1        1       1                 1                  1      1        1           1
1481              1        1       1                 1                  1      1        1           1
467               1        1       1                 1                  1      1        1           1
535               1        1       1                 1                  1      1        1           1
187               1        1       1                 1                  1      1        1           1
165               1        1       1                 1                  1      1        1           1
69                1        1       1                 1                  1      1        1           1
509               1        1       1                 1                  1      1        1           1
166               1        1       1                 1                  1      1        1           1
153               1        1       1                 1                  1      1        1           1
54                1        1       1                 1                  1      1        1           1
53                1        1       1                 1                  1      1        1           1
22                1        1       1                 1                  1      1        1           1
22                1        1       1                 1                  1      1        1           1
3                 1        1       1                 1                  1      1        1           1
                  0        0       0                 0                  0      0        0           0
     Additional_charges Survey_TimelyAdmin Survey_TimelyTreatment Survey_TimelyVisits Survey_Reliability
4618                  1                  1                      1                   1                  1
1496                  1                  1                      1                   1                  1
1481                  1                  1                      1                   1                  1
467                   1                  1                      1                   1                  1
535                   1                  1                      1                   1                  1
187                   1                  1                      1                   1                  1
165                   1                  1                      1                   1                  1
69                    1                  1                      1                   1                  1
509                   1                  1                      1                   1                  1
166                   1                  1                      1                   1                  1
153                   1                  1                      1                   1                  1
54                    1                  1                      1                   1                  1
53                    1                  1                      1                   1                  1
22                    1                  1                      1                   1                  1
22                    1                  1                      1                   1                  1
3                     1                  1                      1                   1                  1
                      0                  0                      0                   0                  0
     Survey_Options Survey_HoursTreatment Survey_CourteousStaff Survey_ActiveListening Employment_FullTime
4618              1                     1                     1                      1                   1
1496              1                     1                     1                      1                   1
1481              1                     1                     1                      1                   1
467               1                     1                     1                      1                   1
535               1                     1                     1                      1                   1
187               1                     1                     1                      1                   1
165               1                     1                     1                      1                   1
69                1                     1                     1                      1                   1
509               1                     1                     1                      1                   1
166               1                     1                     1                      1                   1
153               1                     1                     1                      1                   1
54                1                     1                     1                      1                   1
53                1                     1                     1                      1                   1
22                1                     1                     1                      1                   1
22                1                     1                     1                      1                   1
3                 1                     1                     1                      1                   1
                  0                     0                     0                      0                   0
     Employment_PartTime Employment_Retired Student Unemployed Female Male Admin_elective Admin_observation
4618                   1                  1       1          1      1    1              1                 1
1496                   1                  1       1          1      1    1              1                 1
1481                   1                  1       1          1      1    1              1                 1
467                    1                  1       1          1      1    1              1                 1
535                    1                  1       1          1      1    1              1                 1
187                    1                  1       1          1      1    1              1                 1
165                    1                  1       1          1      1    1              1                 1
69                     1                  1       1          1      1    1              1                 1
509                    1                  1       1          1      1    1              1                 1
166                    1                  1       1          1      1    1              1                 1
153                    1                  1       1          1      1    1              1                 1
54                     1                  1       1          1      1    1              1                 1
53                     1                  1       1          1      1    1              1                 1
22                     1                  1       1          1      1    1              1                 1
22                     1                  1       1          1      1    1              1                 1
3                      1                  1       1          1      1    1              1                 1
                       0                  0       0          0      0    0              0                 0
     Admin_emergency Overweight Initial_days  Age Income_household     
4618               1          1            1    1                1    0
1496               1          1            1    1                0    1
1481               1          1            1    0                1    1
467                1          1            1    0                0    2
535                1          1            0    1                1    1
187                1          1            0    1                0    2
165                1          1            0    0                1    2
69                 1          1            0    0                0    3
509                1          0            1    1                1    1
166                1          0            1    1                0    2
153                1          0            1    0                1    2
54                 1          0            1    0                0    3
53                 1          0            0    1                1    2
22                 1          0            0    1                0    3
22                 1          0            0    0                1    3
3                  1          0            0    0                0    4
                   0        982         1056 2414             2464 6916

mymicecomplete <- complete(mymice, 2)
df<- mymicecomplete

Identifying Outliers

df <- df[,c(14, 1, 3, 2, 4:12, 44, 45, 46, 48, 47, 49, 50, 13, 15, 18, 16, 17, 19:32, 51:53, 33:43)]
head(df)
Check for outliers using boxplots

Population

library(ggplot2)
uni_out <- qplot(data = df, y= Population, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='Population') +
  geom_text(aes(label=ifelse(Population %in% boxplot.stats(Population)$out,
                             as.character(Zip), "")), hjust = 1.5)
uni_out

After a quick Google search of the populations in the top four zip codes, these populations are accurate, but they are outliers that may restrict the effectiveness of a model, so this variable will be standardized.

df$Population <- scale(x = df$Population)

Children

uni_out <- qplot(data = df, y= Children, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='Children')
uni_out

Perform a grubbs test on these outliers

library(outliers)
x <- df$Children
grubbs.test(x)

    Grubbs test for one outlier

data:  x
G = 4.07815, U = 0.99834, p-value = 0.2254
alternative hypothesis: highest value 10 is an outlier
The p-value is above 0.05, these values will remain as-is.

Age

uni_out <- qplot(data = df, y= Age, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='Age')
uni_out

There are no outliers within this variable

Education

uni_out <- qplot(data = df, y= Education, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='Education')
uni_out

Extremely low and extremely high levels of education are outliers, so this variable will be standardized, so as to reduce any negative impact to the model.

df$Education <- scale(x = df$Education)

Income_household

uni_out <- qplot(data = df, y= Income_household, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='Income_household')
uni_out

x <- df$Income_household
grubbs.test(x)

    Grubbs test for one outlier

data:  x
G = 5.79209, U = 0.99664, p-value = 3.379e-05
alternative hypothesis: highest value 207249.13 is an outlier

These values differ from the mean significantly- they will be standardized.

df$Income_household <- scale(x = df$Income_household)

VitD_levels

uni_out <- qplot(data = df, y= VitD_levels, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='VitD_levels')
uni_out

Check for correlation between VitD_levels and VitD_supp

plot(df$VitD_levels, df$VitD_supp, 
     main ='Vitamin D Levels and Supplements', 
     xlab ='Levels', 
     ylab = 'Supplements Administered')

There seem to be two separate clusters of data, so the cluster consisting of patients with high vitamin D levels that also received vitamin D supplements will be checked against potential reasons for the supplementation of vitamin D for patients with seemingly-normal levels of vitamin D.

high_VitD <- which(df$VitD_levels > 30 & df$VitD_supp>1)
out <- df[high_VitD,] ; out
plot(out$Age, out$Overweight)

All these potential outliers are plausible, given that patients over 50 and/or overweight are at higher risk for health issues that would require calcium supplementation (which in turn requires more Vitamin D in order to absorb the calcium). These are natural outliers and pertinent to analysis, given the possibility that patients are more likely to be readmitted if they are not given the proper supplementation. These values will remain as-is in the clean data.

Doc_visits

uni_out <- qplot(data = df, y= Doc_visits, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='Doc_visits') +
  geom_text(aes(label=ifelse(Doc_visits %in% boxplot.stats(Doc_visits)$out,
                             as.character(ReAdmis), "")), hjust = 1.5)
uni_out

There are no outliers within this variable

Full Meals Eaten

uni_out <- qplot(data = df, y= Full_meals_eaten, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='Full_meals_eaten')
uni_out

Hypothesis test

x <- df$Full_meals_eaten
grubbs.test(x)

    Grubbs test for one outlier

data:  x
G = 5.95030, U = 0.99646, p-value = 1.297e-05
alternative hypothesis: highest value 7 is an outlier

Standardize values

df$Full_meals_eaten <- scale(x = df$Full_meals_eaten)


Complication_risk

uni_out <- qplot(data = df, y= Complication_risk, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='Complication_risk') +
  geom_text(aes(label=ifelse(Complication_risk %in% boxplot.stats(Complication_risk)$out,
                             as.character(ReAdmis), "")), hjust = 1.5)
uni_out

There are no outliers within this variable.

Initial_days

uni_out <- qplot(data = df, y= Initial_days, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='Initial_days') +
  geom_text(aes(label=ifelse(Initial_days %in% boxplot.stats(Initial_days)$out,
                             as.character(Initial_days), "")), hjust = 1.5)
uni_out

There are no outliers within this variable

TotalCharge

uni_out <- qplot(data = df, y= TotalCharge, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='TotalCharge') +
  geom_text(aes(label=ifelse(TotalCharge %in% boxplot.stats(TotalCharge)$out,
                             as.character(ReAdmis), "")), hjust = 1.5)
uni_out

There are outliers within the TotalCharge variable, but there seems to be a correlation between Readmission and total charge, so this data will not be altered.

Additional_charges

uni_out <- qplot(data = df, y= Additional_charges, x=1,
                 geom='boxplot', 
                 outlier.color='deeppink2',
                 xlim=c(0,2), 
                 main='Additional_charges') +
  geom_text(aes(label=ifelse(Additional_charges %in% boxplot.stats(Additional_charges)$out,
                             as.character(ReAdmis), "")), hjust = 1.5)
uni_out

Standardize variable

df$Additional_charges <- scale(x = df$Additional_charges)

names(df)[names(df) == ‘Item1’] <- ‘Survey_TimelyAdmin’ names(df)[names(df) == ‘Item2’] <- ‘Survey_TimelyTreatment’ names(df)[names(df) == ‘Item3’] <- ‘Survey_TimelyVisits’ names(df)[names(df) == ‘Item4’] <- ‘Survey_Reliability’ names(df)[names(df) == ‘Item5’] <- ‘Survey_Options’ names(df)[names(df) == ‘Item6’] <- ‘Survey_HoursTreatment’ names(df)[names(df) == ‘Item7’] <- ‘Survey_CourteousStaff’ names(df)[names(df) == ‘Item8’] <- ‘Survey_ActiveListening’

Survey Results

survey_results <- df[,46:53]
for (col in survey_results){
  uni_out <- qplot(data = survey_results, y= col, x=1,
                    geom='boxplot', 
                    outlier.color='deeppink2',
                    xlim=c(0,2))
  print(uni_out)
}

for (col in survey_results){
  x <- col
  print(grubbs.test(x))
}

    Grubbs test for one outlier

data:  x
G = 4.34239, U = 0.99811, p-value = 0.06985
alternative hypothesis: highest value 8 is an outlier


    Grubbs test for one outlier

data:  x
G = 3.37574, U = 0.99886, p-value = 1
alternative hypothesis: highest value 7 is an outlier


    Grubbs test for one outlier

data:  x
G = 4.34653, U = 0.99811, p-value = 0.06854
alternative hypothesis: highest value 8 is an outlier


    Grubbs test for one outlier

data:  x
G = 3.36289, U = 0.99887, p-value = 1
alternative hypothesis: highest value 7 is an outlier


    Grubbs test for one outlier

data:  x
G = 3.40043, U = 0.99884, p-value = 1
alternative hypothesis: highest value 7 is an outlier


    Grubbs test for one outlier

data:  x
G = 3.36844, U = 0.99887, p-value = 1
alternative hypothesis: highest value 7 is an outlier


    Grubbs test for one outlier

data:  x
G = 3.43253, U = 0.99882, p-value = 1
alternative hypothesis: highest value 7 is an outlier


    Grubbs test for one outlier

data:  x
G = 3.34861, U = 0.99888, p-value = 1
alternative hypothesis: highest value 7 is an outlier

These values will remain.


Data Cleaning Strengths & Weaknesses
The strengths of this clean data are that nearly all values are numeric, allowing easy calculations and visualizations, and there are no null values remaining. The weaknesses are that not all new numeric values are not easily interpreted without a data dictionary.
The major limitation when cleaning the data set was not having access to the individuals that collected the data. Many more decisions could have been made had the variables been better explained. For example, VitD_supp is described as the “number of times” a patient is administered a vitamin D supplement. It was not clarified if this number was daily, over the course of the entire initial stay, or any specific dosage. This may affect the analysis in that results may be skewed in unanticipated directions due to unbalanced data.

Principle Component Analysis
(ref: http://factominer.free.fr/factomethods/principal-components-analysis.html)

head(df)

I will not use the target variable (ReAdmis), the qualititative variables (City and County), or the redundant variables (State, Lat, Lng, Timezone) Standardization

df_sub <- scale(x = df[,c(5, 8, 9, 11:53)])
head(df_sub)
            Zip Population         Area   Children         Age  Education Employment_FullTime
[1,] -0.5292516 -0.4731446  0.008079945 -0.2681162 -0.02526499 -0.1970790           0.8115319
[2,] -0.6448340  0.0902373  1.232313962  0.6977202 -0.12221431  0.1264787           0.8115319
[3,]  0.2530317  0.4829587  0.008079945  0.6977202 -0.02526499  0.1264787          -1.2321143
[4,]  0.2152444 -0.5263663  0.008079945 -0.7510343  1.18660144 -0.5206366          -1.2321143
[5,] -0.9821161 -0.3155703 -1.216154073 -0.7510343 -1.52797937 -0.5206366           0.8115319
[6,]  0.8832923 -0.6060304  1.232313962 -0.7510343  1.08965213 -0.5206366          -1.2321143
     Employment_PartTime Employment_Retired Unemployed    Student     Female       Male Income_household
[1,]          -0.3316476         -0.3296006 -0.3301597 -0.3364558 -1.0035563  1.0474759       1.59418085
[2,]          -0.3316476         -0.3296006 -0.3301597 -0.3364558  0.9963566 -0.9545805       0.21068775
[3,]          -0.3316476          3.0336712 -0.3301597 -0.3364558  0.9963566 -0.9545805      -0.91767138
[4,]          -0.3316476          3.0336712 -0.3301597 -0.3364558 -1.0035563  1.0474759      -0.03506789
[5,]          -0.3316476         -0.3296006 -0.3301597 -0.3364558  0.9963566 -0.9545805      -1.37549383
[6,]          -0.3316476          3.0336712 -0.3301597 -0.3364558 -1.0035563  1.0474759      -0.95951123
     VitD_levels  VitD_supp  Doc_visits Full_meals_eaten Soft_drink  HighBlood     Stroke Complication_risk
[1,] -0.23951785 -0.6346809  0.94459928     -0.993337188 -0.4912094  1.2020163 -0.4988811        -0.1688644
[2,] -0.06217740  0.9563968 -0.96793217      0.990559733 -0.4912094  1.2020163 -0.4988811         1.2006768
[3,] -0.29699603 -0.6346809 -0.96793217     -0.001388728 -0.4912094  1.2020163 -0.4988811        -0.1688644
[4,] -0.29637274 -0.6346809 -0.96793217     -0.001388728 -0.4912094 -0.8318523  2.0042853        -0.1688644
[5,] -0.37811197  2.5474746 -0.01166644     -0.993337188  2.0355880 -0.8318523 -0.4988811        -1.5384057
[6,]  0.08083369 -0.6346809  0.94459928     -0.993337188 -0.4912094 -0.8318523 -0.4988811        -0.1688644
     Overweight  Arthritis   Diabetes Hyperlipidemia   BackPain    Anxiety Allergic_rhinitis
[1,] -1.5900719  1.3408228  1.6285072      -0.713232  1.1960691  1.5623419         1.2398683
[2,]  0.6288395 -0.7457362 -0.6139979      -0.713232 -0.8359885 -0.6400008        -0.8064566
[3,]  0.6288395 -0.7457362  1.6285072      -0.713232 -0.8359885 -0.6400008        -0.8064566
[4,] -1.5900719  1.3408228 -0.6139979      -0.713232 -0.8359885 -0.6400008        -0.8064566
[5,] -1.5900719 -0.7457362 -0.6139979       1.401928 -0.8359885 -0.6400008         1.2398683
[6,]  0.6288395  1.3408228  1.6285072      -0.713232  1.1960691 -0.6400008         1.2398683
     Reflux_esophagitis     Asthma   Services Admin_elective Admin_observation Admin_emergency Initial_days
[1,]         -0.8396186  1.5672823 -0.8069574     -0.5779372        -0.5674677       0.9880217   -0.9073416
[2,]          1.1908979 -0.6379833  0.3938721     -0.5779372        -0.5674677       0.9880217   -0.7347159
[3,]         -0.8396186 -0.6379833 -0.8069574      1.7301187        -0.5674677      -1.0120223   -1.1282089
[4,]          1.1908979  1.5672823 -0.8069574      1.7301187        -0.5674677      -1.0120223   -1.2443604
[5,]         -0.8396186 -0.6379833  1.5947016      1.7301187        -0.5674677      -1.0120223   -1.2618392
[6,]         -0.8396186 -0.6379833 -0.8069574     -0.5779372         1.7620385      -1.0120223   -1.0831862
     TotalCharge Additional_charges Survey_TimelyAdmin Survey_TimelyTreatment Survey_TimelyVisits
[1,]  -0.7995390        0.764967085         -0.5027299             -0.4896481          -1.4631734
[2,]  -0.4964039        0.715077864         -0.5027299              0.4766991          -0.4948898
[3,]  -1.0995966        0.698600372         -1.4717544              0.4766991           0.4733939
[4,]  -1.0144664        0.009003875         -0.5027299              1.4430463           1.4416775
[5,]  -1.1860294       -1.408920097         -1.4717544             -2.4223426          -0.4948898
[6,]  -0.9229888       -0.029336751          0.4662946              1.4430463           0.4733939
     Survey_Reliability Survey_Options Survey_HoursTreatment Survey_CourteousStaff Survey_ActiveListening
[1,]         -1.4620544      0.4883553            -0.5061140            -0.4836475              0.4703965
[2,]          0.4679230      0.4883553             0.4625253            -0.4836475             -0.4890090
[3,]          0.4679230     -0.4823371             0.4625253            -0.4836475             -0.4890090
[4,]         -0.4970657      0.4883553             1.4311645             1.4744395              1.4298020
[5,]         -0.4970657      1.4590477            -0.5061140             0.4953960             -0.4890090
[6,]          0.4679230     -0.4823371             1.4311645             0.4953960              2.3892076


Principal Component Analysis

library(FactoMineR)
df_sub.pca <- PCA(df_sub, scale.unit=TRUE, graph=F)


Scree Plot

eig.val <- df_sub.pca$eig

barplot(eig.val[, 2],

        main = "Explained Variance (%)",

        xlab = "Principal Components",

        ylab = "(%) of Variance",

        col = "darkblue")


Graph of Individuals

plot(df_sub.pca, choix = "ind", autoLab = "auto", habillage = "cos2", col.ind="darkblue", label="var", graph.type = "ggplot")


Graph of Variables

plot(df_sub.pca, choix = "var", autoLab = "auto", col.var="darkblue", label="var", graph.type = "ggplot", select="cos2 0.40")

plot(df_sub.pca, choix = "ind", autoLab = "auto", habillage = "TotalCharge", col.ind="darkblue", label="var", graph.type = "ggplot")


plot(df_sub.pca, choix = "ind", autoLab = "auto", habillage = "Additional_charges", col.ind="darkblue", label="var", graph.type = "ggplot")


plot(df_sub.pca, choix = "ind", autoLab = "auto", habillage = "Survey_HoursTreatment", col.ind="darkblue", label="var", graph.type = "ggplot")


plot(df_sub.pca, choix = "ind", autoLab = "auto", habillage = "Survey_TimelyVisits", col.ind="darkblue", label="var", graph.type = "ggplot")


plot(df_sub.pca, choix = "ind", autoLab = "auto", habillage = "Survey_TimelyAdmin", col.ind="darkblue", label="var", graph.type = "ggplot")


plot(df_sub.pca, choix = "ind", autoLab = "auto", habillage = "Survey_TimelyTreatment", col.ind="darkblue", label="var", graph.type = "ggplot")


In order to determine the principal components, I ran the PCA using the package FactoMineR and viewed the Scree plot. The PCA graphs of individuals and variables allowed me to reduce the data to the most important variables in terms of the original vector of variables. The variables with cos2 over 0.4 were those that I identified as “most important,” and they were determined to be

- TotalCharge - Additional_charges - Survey_HoursTreatment - Survey_TimelyVisits - Survey_TimelyAdmin - Survey_TimelyTreatment

Hospitals can benefit from researching these components and analyzing the correlation between these principal components and readmission rates. Pending results of an in-depth analysis, the organization can obtain actionable insights and attempt to reduce readmission rates.

LS0tCnRpdGxlOiAiRDIwNiBQZXJmb3JtYW5jZSBBc3Nlc3NtZW50IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KPGI+PGZvbnQgc2l6ZT0iKzMiPlBhcnQgSTogUmVzZWFyY2ggUXVlc3Rpb248L2I+PC9mb250Pjxicj4KCjxiPjxwIHN0eWxlPSJjb2xvcjpkYXJrYmx1ZTsiPjxmb250IHNpemU9IisyIj4gV2hpY2ggdmFyaWFibGVzIGFyZSB0aGUgbW9zdCBpbXBvcnRhbnQgaW4gcmVnYXJkcyB0byBwcmVkaWN0aW5nIHdoaWNoIHBhdGllbnRzIGFyZSBhdCBhIGhpZ2ggcmlzayBvZiByZWFkbWlzc2lvbj88L2ZvbnQ+PC9iPjwvcD48YnI+Cgo8Yj48Zm9udCBzaXplPSIrMiI+VmFyaWFibGVzOjwvZm9udD48L2I+CmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpkZl9yYXcgPC0gcmVhZC5jc3YoJ34vRG9jdW1lbnRzL1dHVSBNU0RBL0QyMDYvbWVkaWNhbF9yYXdfZGF0YS5jc3YnKQpzdHIoZGZfcmF3KQpgYGAKPGI+VW5uYW1lZDo8L2I+IGludGVnZXIgaW5kZXggPGJyPgo8Yj5DYXNlT3JkZXI6PC9iPiBpbnRlZ2VyIGluZGV4IHRvIHByZXNlcnZlIG9yaWdpbmFsIG9yZGVyIG9mIHJhdyBkYXRhIDxicj4KPGI+Q3VzdG9tZXJfaWQ6PC9iPiBjaGFyYWN0ZXIgc3RyaW5nIHVuaXF1ZSB0byBwYXRpZW50IDxicj4KPGI+SW50ZXJhY3Rpb246PC9iPiBjaGFyYWN0ZXIgc3RyaW5nIHVuaXF1ZSB0byBwYXRpZW50IHRyYW5zYWN0aW9ucywgcHJvY2VkdXJlcyBhbmQgYWRtaXNzaW9ucyA8YnI+CjxiPlVJRDo8L2I+IGNoYXJhY3RlciBzdHJpbmcgdW5pcXVlIHRvIHBhdGllbnQgdHJhbnNhY3Rpb25zLCBwcm9jZWR1cmVzIGFuZCBhZG1pc3Npb25zIDxicj4KPGI+Q2l0eTo8L2I+IGNoYXJhY3RlciBzdHJpbmcgaW5kaWNhdGluZyBwYXRpZW50J3MgY2l0eSBvZiByZXNpZGVuY2UgYXMgbGlzdGVkIG9uIHRoZSBiaWxsaW5nIHN0YXRlbWVudCA8YnI+CjxiPlN0YXRlOjwvYj4gY2hhcmFjdGVyIHN0cmluZyBpbmRpY2F0aW5nIHBhdGllbnQncyBzdGF0ZSBvZiByZXNpZGVuY2UgYXMgbGlzdGVkIG9uIHRoZSBiaWxsaW5nIHN0YXRlbWVudCA8YnI+CjxiPkNvdW50eTo8L2I+IGNoYXJhY3RlciBzdHJpbmcgaW5kaWNhdGluZyBwYXRpZW50J3MgY291bnR5IG9mIHJlc2lkZW5jZSBhcyBsaXN0ZWQgb24gdGhlIGJpbGxpbmcgc3RhdGVtZW50IDxicj4KPGI+WmlwOjwvYj4gaW50ZWdlciBpbmRpY2F0aW5nIHBhdGllbnQncyB6aXAgY29kZSBvZiByZXNpZGVuY2UgYXMgbGlzdGVkIG9uIHRoZSBiaWxsaW5nIHN0YXRlbWVudCA8YnI+CjxiPkxhdDo8L2I+IGNvbnRpbnVvdXMgbnVtZXJpYyBHUFMgY29vcmRpbmF0ZXMgaW5kaWNhdGluZyBsYXRpdHVkZSBvZiBwYXRpZW50J3MgcmVzaWRlbmNlIGFzIGxpc3RlZCBvbiB0aGUgYmlsbGluZyBzdGF0ZW1lbnQgPGJyPgo8Yj5Mbmc6PC9iPiBjb250aW51b3VzIG51bWVyaWMgR1BTIGNvb3JkaW5hdGVzIGluZGljYXRpbmcgbG9uZ2l0dWRlIG9mIHBhdGllbnQncyByZXNpZGVuY2UgYXMgbGlzdGVkIG9uIHRoZSBiaWxsaW5nIHN0YXRlbWVudCA8YnI+CjxiPlBvcHVsYXRpb246PC9iPiBpbnRlZ2VyIHZhbHVlIGluZGljYXRpbmcgcG9wdWxhdGlvbiB3aXRoaW4gYSBtaWxlIHJhZGl1cyBvZiBwYXRpZW50LSBiYXNlZCBvbiBjZW5zdXMgZGF0YSA8YnI+CjxiPkFyZWE6PC9iPiA8aT5ub21pbmFsIGNhdGVnb3JpY2FsPC9pPiAtIGNoYXJhY3RlciBzdHJpbmcgaW5kaWNhdGluZyBhcmVhIHR5cGUtIGJhc2VkIG9uIGNlbnN1cyBkYXRhCmBgYHtyfQp1bmlxdWUoZGZfcmF3JEFyZWEpCmBgYAo8Yj5UaW1lem9uZTo8L2I+IDxpPm5vbWluYWwgY2F0ZWdvcmljYWw8L2k+IC0gY2hhcmFjdGVyIHN0cmluZyBpbmRpY2F0aW5nIHRpbWV6b25lIG9mIHBhdGllbnQncyByZXNpZGVuY2UgYXMgcHJvdmlkZWQgYnkgcGF0aWVudApgYGB7cn0KdW5pcXVlKGRmX3JhdyRUaW1lem9uZSkKYGBgCjxiPkpvYjo8L2I+IDxpPm5vbWluYWwgY2F0ZWdvcmljYWw8L2k+IC0gY2hhcmFjdGVyIHN0cmluZyBpbmRpY2F0aW5nIHBhdGllbnQncyAob3IgcHJpbWFyeSBpbnN1cmFuY2UgaG9sZGVyJ3MpIGpvYiBhcyBwcm92aWRlZCBieSBwYXRpZW50IDxicj4KPGI+Q2hpbGRyZW46PC9iPiBpbnRlZ2VyIGluZGljYXRpbmcgbnVtYmVyIG9mIGNoaWxkcmVuIGluIHBhdGllbnQncyBob3VzZWhvbGQgYXMgcHJvdmlkZWQgYnkgcGF0aWVudCA8YnI+CjxiPkFnZTo8L2I+IGludGVnZXIgaW5kaWNhdGluZyBwYXRpZW50J3MgYWdlIGFzIHByb3ZpZGVkIGJ5IHBhdGllbnQgPGJyPgo8Yj5FZHVjYXRpb246PC9iPiA8aT5ub21pbmFsIGNhdGVnb3JpY2FsPC9pPiAtIGNoYXJhY3RlciBzdHJpbmcgaW5kaWNhdGluZyBwYXRpZW50J3MgaGlnaGVzdCBlYXJuZWQgZGVncmVlIGFzIHByb3ZpZGVkIGJ5IHBhdGllbnQgCmBgYHtyfQp1bmlxdWUoZGZfcmF3JEVkdWNhdGlvbikKYGBgCjxiPkVtcGxveW1lbnQ6PC9iPiA8aT5jYXRlZ29yaWNhbDwvaT4gLSBjaGFyYWN0ZXIgc3RyaW5nIGluZGljYXRpbmcgcGF0aWVudCdzIGVtcGxveW1lbnQgc3RhdHVzIGFzIHByb3ZpZGVkIGJ5IHBhdGllbnQKYGBge3J9CnVuaXF1ZShkZl9yYXckRW1wbG95bWVudCkKYGBgCjxiPkluY29tZTo8L2I+IC0gbnVtZXJpYyB2YWx1ZSBpbmRpY2F0aW5nIGFubnVhbCBpbmNvbWUgb2YgcGF0aWVudCAob3IgcHJpbWFyeSBpbnN1cmFuY2UgaG9sZGVyKSBhcyBwcm92aWRlZCBieSBwYXRpZW50IDxicj4KPGI+TWFyaXRhbDo8L2I+IDxpPm5vbWluYWwgY2F0ZWdvcmljYWw8L2k+IC0gY2hhcmFjdGVyIHN0cmluZyBpbmRpY2F0aW5nIHBhdGllbnQncyAob3IgcHJpbWFyeSBpbnN1cmFuY2UgaG9sZGVyJ3MpIG1hcml0YWwgc3RhdHVzIGFzIHByb3ZpZGVkIGJ5IHBhdGllbnQKYGBge3J9CnVuaXF1ZShkZl9yYXckTWFyaXRhbCkKYGBgCjxiPkdlbmRlcjo8L2I+IDxpPm5vbWluYWwgY2F0ZWdvcmljYWw8L2k+IC0gY2hhcmFjdGVyIHN0cmluZyBpbmRpY2F0aW5nIHBhdGllbnQncyBnZW5kZXIgYXMgcHJvdmlkZWQgYnkgcGF0aWVudApgYGB7cn0KdW5pcXVlKGRmX3JhdyRHZW5kZXIpCmBgYAo8Yj5SZUFkbWlzOjwvYj4gPGk+YmluYXJ5IGNhdGVnb3JpY2FsPC9pPiAtIGNoYXJhY3RlciBzdHJpbmcgaW5kaWNhdGluZyB3aGV0aGVyIG9yIG5vdCBwYXRpZW50IHdhcyByZWFkbWl0dGVkIHdpdGhpbiBhIG1vbnRoIG9mIHJlbGVhc2UgW1llcywgTm9dICA8Yj4qdGFyZ2V0IHZhcmlhYmxlPC9iPiA8YnI+CjxiPlZpdERfbGV2ZWxzOjwvYj4gY29udGludW91cyBudW1lcmljIHZhbHVlIGluZGljYXRpbmcgcGF0aWVudCdzIHZpdGFtaW4gRCBsZXZlbHMgYXMgbWVhc3VyZWQgaW4gbmcvbUwgPGJyPgo8Yj5Eb2NfdmlzaXRzOjwvYj4gaW50ZWdlciBpbmRpY2F0aW5nIG51bWJlciBvZiB0aW1lcyB0aGUgcHJpbWFyeSBwaHlzaWNpYW4gdmlzaXRlZCB0aGUgcGF0aWVudCBkdXJpbmcgdGhlIGluaXRpYWwgaG9zcGl0YWxpemF0aW9uIDxicj4KPGI+RnVsbF9tZWFsc19lYXRlbjo8L2I+IGludGVnZXIgaW5kaWNhdGluZyBudW1iZXIgb2YgZnVsbCBtZWFscyBlYXRlbiAocGFydGlhbCBtZWFscyBjb3VudCBhcyAwKQo8Yj5WaXREX3N1cHA6PC9iPiBpbnRlZ2VyIGluZGljYXRpbmcgbnVtYmVyIG9mIHRpbWVzIHRoYXQgdml0YW1pbiBEIHN1cHBsZW1lbnRzIHdlcmUgYWRtaW5pc3RlcmVkIHRvIHBhdGllbnQgPGJyPgo8Yj5Tb2Z0X2RyaW5rOjwvYj4gPGk+YmluYXJ5IGNhdGVnb3JpY2FsPC9pPiAtIGNoYXJhY3RlciBzdHJpbmcgaW5kaWNhdGluZyB3aGV0aGVyIG9yIG5vdCBwYXRpZW50IHJlZ3VsYXJseSBkcmlua3MgdGhyZWUgb3IgbW9yZSBzb2RhcyBpbiBhIGRheSBbWWVzLCBOb10gPGJyPgo8Yj5Jbml0aWFsX2FkbWluOjwvYj4gPGk+bm9taW5hbCBjYXRlZ29yaWNhbDwvaT4gLSBjaGFyYWN0ZXIgc3RyaW5nIGluZGljYXRpbmcgdGhlIG1lYW5zIGJ5IHdoaWNoIHRoZSBwYXRpZW50IHdhcyBpbml0aWFsbHkgYWRtaXR0ZWQgaW50byB0aGUgaG9zcGl0YWwKYGBge3J9CnVuaXF1ZShkZl9yYXckSW5pdGlhbF9hZG1pbikKYGBgCjxiPkhpZ2hCbG9vZDo8L2I+IDxpPmJpbmFyeSBjYXRlZ29yaWNhbDwvaT4gLSBjaGFyYWN0ZXIgc3RyaW5nIGluZGljYXRpbmcgd2hldGhlciBvciBub3QgdGhlIHBhdGllbnQgaGFzIGhpZ2ggYmxvb2QgcHJlc3N1cmUgW1llcywgTm9dIDxicj4KPGI+U3Ryb2tlOjwvYj4gPGk+YmluYXJ5IGNhdGVnb3JpY2FsPC9pPiAtIGNoYXJhY3RlciBzdHJpbmcgaW5kaWNhdGluZyB3aGV0aGVyIG9yIG5vdCB0aGUgcGF0aWVudCBoYXMgaGFkIGEgc3Ryb2tlIFtZZXMsIE5vXSA8YnI+CjxiPkNvbXBsaWNhdGlvbl9yaXNrOjwvYj4gPGk+b3JkaW5hbCBjYXRlZ29yaWNhbDwvaT4gLSBjaGFyYWN0ZXIgc3RyaW5nIGluZGljYXRpbmcgbGV2ZWwgb2YgY29tcGxpY2F0aW9uIHJpc2sgW0hpZ2gsIE1lZGl1bSwgTG93XSA8YnI+CjxiPk92ZXJ3ZWlnaHQ6PC9iPiA8aT5iaW5hcnkgY2F0ZWdvcmljYWw8L2k+IC0gaW50ZWdlciBpbmRpY2F0aW5nIHdoZXRoZXIgKDEpIG9yIG5vdCAoMCkgdGhlIHBhdGllbnQgaXMgb3ZlcndlaWdodCwgYXMgZGV0ZXJtaW5lZCBieSBhZ2UsIGdlbmRlciwgYW5kIGhlaWdodCA8YnI+CjxiPkFydGhyaXRpczo8L2I+IDxpPmJpbmFyeSBjYXRlZ29yaWNhbDwvaT4gLSBjaGFyYWN0ZXIgc3RyaW5nIGluZGljYXRpbmcgd2hldGhlciBvciBub3QgdGhlIHBhdGllbnQgaGFzIGFydGhyaXRpcyBbWWVzLCBOb10gPGJyPgo8Yj5EaWFiZXRlczo8L2I+IDxpPmJpbmFyeSBjYXRlZ29yaWNhbDwvaT4gLSBjaGFyYWN0ZXIgc3RyaW5nIGluZGljYXRpbmcgd2hldGhlciBvciBub3QgdGhlIHBhdGllbnQgaGFzIGRpYWJldGVzIFtZZXMsIE5vXSA8YnI+CjxiPkh5cGVybGlwaWRlbWlhOjwvYj4gPGk+YmluYXJ5IGNhdGVnb3JpY2FsPC9pPiAtIGNoYXJhY3RlciBzdHJpbmcgaW5kaWNhdGluZyB3aGV0aGVyIG9yIG5vdCB0aGUgcGF0aWVudCBoYXMgaHlwZXJsaXBpZGVtaWEgW1llcywgTm9dIDxicj4KPGI+QmFja1BhaW46PC9iPiA8aT5iaW5hcnkgY2F0ZWdvcmljYWw8L2k+IC0gY2hhcmFjdGVyIHN0cmluZyBpbmRpY2F0aW5nIHdoZXRoZXIgb3Igbm90IHRoZSBwYXRpZW50IGhhcyBjaHJvbmljIGJhY2twYWluIFtZZXMsIE5vXSA8YnI+CjxiPkFueGlldHk6PC9iPiAgPGk+YmluYXJ5IGNhdGVnb3JpY2FsPC9pPiAtIGludGVnZXIgaW5kaWNhdGluZyB3aGV0aGVyICgxKSBvciBub3QgKDApIHRoZSBwYXRpZW50IGhhcyBhbiBhbnhpZXR5IGRpc29yZGVyIDxicj4KPGI+QWxsZXJnaWNfcmhpbml0aXM6PC9iPiA8aT5iaW5hcnkgY2F0ZWdvcmljYWw8L2k+IC0gY2hhcmFjdGVyIHN0cmluZyBpbmRpY2F0aW5nIHdoZXRoZXIgb3Igbm90IHRoZSBwYXRpZW50IGhhcyBhbGxlcmdpYyByaGluaXRpcyBbWWVzLCBOb10gPGJyPgo8Yj5SZWZsdXhfZXNvcGhhZ2l0aXM6PC9iPiA8aT5iaW5hcnkgY2F0ZWdvcmljYWw8L2k+IC0gY2hhcmFjdGVyIHN0cmluZyBpbmRpY2F0aW5nIHdoZXRoZXIgb3Igbm90IHRoZSBwYXRpZW50IGhhcyByZWZsdXggZXNvcGhhZ2l0aXMgW1llcywgTm9dIDxicj4KPGI+QXN0aG1hOjwvYj4gPGk+YmluYXJ5IGNhdGVnb3JpY2FsPC9pPiAtIGNoYXJhY3RlciBzdHJpbmcgaW5kaWNhdGluZyB3aGV0aGVyIG9yIG5vdCB0aGUgcGF0aWVudCBoYXMgYXN0aG1hIFtZZXMsIE5vXSA8YnI+CjxiPlNlcnZpY2VzOjwvYj4gPGk+bm9taW5hbCBjYXRlZ29yaWNhbDwvaT4gLSBjaGFyYWN0ZXIgc3RyaW5nIGluZGljYXRpbmcgdGhlIHByaW1hcnkgc2VydmljZSB0aGUgcGF0aWVudCByZWNlaXZlZCB3aGlsZSBob3NwaXRhbGl6ZWQKYGBge3J9CnVuaXF1ZShkZl9yYXckU2VydmljZXMpCmBgYAo8Yj5Jbml0aWFsX2RheXM6PC9iPiBudW1lcmljIHZhbHVlIGluZGljYXRpbmcgbnVtYmVyIG9mIGRheXMgdGhlIHBhdGllbnQgc3RheWVkIGluIHRoZSBob3NwaXRhbCBkdXJpbmcgdGhlIGluaXRpYWwgdmlzaXQgPGJyPgo8Yj5Ub3RhbENoYXJnZTo8L2I+IG51bWVyaWMgdmFsdWUgaW5kaWNhdGluZyBwYXRpZW50J3MgYXZlcmFnZSBkYWlseSBjaGFyZ2VzIGZvciB0eXBpY2FsIChub3Qgc3BlY2lhbGl6ZWQpIHRyZWF0bWVudHMgYW5kIHNlcnZpY2VzIGR1cmluZyB0aGUgaW5pdGlhbCB2aXNpdCA8YnI+CjxiPkFkZGl0aW9uYWxfY2hhcmdlczo8L2I+IG51bWVyaWMgdmFsdWUgaW5kaWNhdGluZyBwYXRpZW50J3MgYXZlcmFnZSBkYWlseSBjaGFyZ2VzIGZvciBhZGRpdGlvbmFsIHRyZWF0bWVudHMgYW5kIHNlcnZpY2VzIGR1cmluZyB0aGUgaW5pdGlhbCB2aXNpdCA8YnI+CjxiPkl0ZW0xOjwvYj4gaW50ZWdlciB2YWx1ZSBpbmRpY2F0aW5nIHRoZSBsZXZlbCBvZiBpbXBvcnRhbmNlIG9mIDxiPnRpbWVseSBhZG1pc3Npb248L2I+IGZyb20gbW9zdCBpbXBvcnRhbnQgKDEpIHRvIGxlYXN0IGltcG9ydGFudCAoOCksIGFzIHJlcG9ydGVkIGJ5IHBhdGllbnQgPGJyPgo8Yj5JdGVtMjo8L2I+IGludGVnZXIgdmFsdWUgaW5kaWNhdGluZyB0aGUgbGV2ZWwgb2YgaW1wb3J0YW5jZSBvZiA8Yj50aW1lbHkgdHJlYXRtZW50PC9iPiBmcm9tIG1vc3QgaW1wb3J0YW50ICgxKSB0byBsZWFzdCBpbXBvcnRhbnQgKDgpLCBhcyByZXBvcnRlZCBieSBwYXRpZW50IDxicj4KPGI+SXRlbTM6PC9iPiBpbnRlZ2VyIHZhbHVlIGluZGljYXRpbmcgdGhlIGxldmVsIG9mIGltcG9ydGFuY2Ugb2YgPGI+dGltZWx5IHZpc2l0czwvYj4gZnJvbSBtb3N0IGltcG9ydGFudCAoMSkgdG8gbGVhc3QgaW1wb3J0YW50ICg4KSwgYXMgcmVwb3J0ZWQgYnkgcGF0aWVudCA8YnI+CjxiPkl0ZW00OjwvYj4gaW50ZWdlciB2YWx1ZSBpbmRpY2F0aW5nIHRoZSBsZXZlbCBvZiBpbXBvcnRhbmNlIG9mIDxiPnJlbGlhYmlsaXR5PC9iPiBmcm9tIG1vc3QgaW1wb3J0YW50ICgxKSB0byBsZWFzdCBpbXBvcnRhbnQgKDgpLCBhcyByZXBvcnRlZCBieSBwYXRpZW50IDxicj4KPGI+SXRlbTU6PC9iPiBpbnRlZ2VyIHZhbHVlIGluZGljYXRpbmcgdGhlIGxldmVsIG9mIGltcG9ydGFuY2Ugb2YgPGI+b3B0aW9uczwvYj4gZnJvbSBtb3N0IGltcG9ydGFudCAoMSkgdG8gbGVhc3QgaW1wb3J0YW50ICg4KSwgYXMgcmVwb3J0ZWQgYnkgcGF0aWVudCA8YnI+CjxiPkl0ZW02OjwvYj4gaW50ZWdlciB2YWx1ZSBpbmRpY2F0aW5nIHRoZSBsZXZlbCBvZiBpbXBvcnRhbmNlIG9mIDxiPmhvdXJzIG9mIHRyZWF0bWVudDwvYj4gZnJvbSBtb3N0IGltcG9ydGFudCAoMSkgdG8gbGVhc3QgaW1wb3J0YW50ICg4KSwgYXMgcmVwb3J0ZWQgYnkgcGF0aWVudCA8YnI+CjxiPkl0ZW03OjwvYj4gaW50ZWdlciB2YWx1ZSBpbmRpY2F0aW5nIHRoZSBsZXZlbCBvZiBpbXBvcnRhbmNlIG9mIDxiPmNvdXJ0ZW91cyBzdGFmZjwvYj4gZnJvbSBtb3N0IGltcG9ydGFudCAoMSkgdG8gbGVhc3QgaW1wb3J0YW50ICg4KSwgYXMgcmVwb3J0ZWQgYnkgcGF0aWVudCA8YnI+CjxiPkl0ZW04OjwvYj4gaW50ZWdlciB2YWx1ZSBpbmRpY2F0aW5nIHRoZSBsZXZlbCBvZiBpbXBvcnRhbmNlIG9mIDxiPmV2aWRlbmNlIG9mIGFjdGl2ZSBsaXN0ZWluZyBmcm9tIGRvY3RvcjwvYj4gZnJvbSBtb3N0IGltcG9ydGFudCAoMSkgdG8gbGVhc3QgaW1wb3J0YW50ICg4KSwgYXMgcmVwb3J0ZWQgYnkgcGF0aWVudAoKCjxiPjxmb250IHNpemU9IisyIj5EYXRhLUNsZWFuaW5nIFBsYW48L2ZvbnQ+PC9iPjxicj4KPGJyPgo8aT5JbiBvcmRlciB0byBhc3NlcyB0aGUgcXVhbGl0eSBvZi0gYW5kIGNsZWFuLSB0aGUgZGF0YSwgSSB3aWxsIGJlIHVzaW5nIFIuICBSIHdhcyBjcmVhdGVkIGJ5IHN0YXRpc3RpY2lhbnMsIG1ha2luZyBpdCBpZGVhbCBmb3Igc3RhdGlzdGljYWwgYW5hbHlzaXMuIFIgYWxzbyBhbGxvd3MgZm9yIGludGVycHJldGFibGUgdmlzdWFsaXphdGlvbnMsICBhbmQgcGFja2FnZXMgYnVpbHQgZm9yIGNsZWFuaW5nIGRhdGEgYW5kIGlkZW50aWZ5aW5nIG91dGxpZXJzLiAgU29tZSBvZiB0aGVzZSBwYWNrYWdlcyBpbmNsdWRlIHJlYWRyIGZvciByZWFkaW5nIHRoZSByYXcgZGF0YSBmaWxlIGludG8gUiwgIGNhcmV0IGZvciBvbmUgaG90IGVuY29kaW5nIHVzaW5nIGR1bW15IHZhcmlhYmxlcywgYW5kIGRwbHlyIGFuZCBnZ3Bsb3QyLCBmb3IgdmFyaW91cyBjYWxjdWxhdGlvbnMgYW5kIHZpc3VhbGl6YXRpb25zLjwvaT48YnI+Cjxicj4KLSBSZXNldCBpbmRleDxicj4KLSBSZW1vdmFsIG9mIHJlZHVuZGFudCwgaXJyZWxldmFudCwgb3IgbWlzbGVhZGluZyB2YXJpYWJsZXM8YnI+CiAgICAtJ1gnLCAnQ3VzdG9tZXJfaWQnLCAnSW50ZXJhY3Rpb25faWQnLCAnSm9iJywgJ0luY29tZScsICdNYXJpdGFsJzxicj4KICAgICAgICAtIERhdGEgd2FzIGNvbGxlY3RlZCBvbiB0aGUgam9iIGFuZCBtYXJpdGFsIHN0YXR1cyBvZiBlaXRoZXIgdGhlIHBhdGllbnQgb3IgdGhlIHByaW1hcnkgaW5zdXJhbmNlIGhvbGRlci4gIFRoZSBpbmNvbnNpc3RlbmN5IG9mIHRoaXMgZGF0YSBtYXkgbGVhZCB0byBmYWxzZSBjb25jbHVzaW9ucywgYW5kIHdpbGwgdGhlcmVmb3JlIGJlIHJlbW92ZWQuPGJyPgotIFJlbmFtaW5nIG1pc2xlYWRpbmcgdmFyaWFibGVzCiAgLURhdGEgd2FzIGNvbGxlY3RlZCBvbiB0aGUgaW5jb21lIG9mIGVpdGhlciB0aGUgcGF0aWVudCBvciB0aGUgcHJpbWFyeSBpbnN1cmFuY2UgaG9sZGVyLCBzbyB0aGUgZmllbGQgbmFtZSB3aWxsIGJlIHJlbmFtZWQgdG8gcmVmbGVjdCB0aGlzLgotIFJlLWV4cHJlc3Npb24gb2YgY2F0ZWdvcmljYWwgZGF0YSBhcyBudW1lcmljIGRhdGEgPGJyPgogIC0gQ2hhbmdlIGNoYXJhY3RlciB2YWx1ZXMgdG8gbnVtZXJpYyB2YWx1ZXMgb3Igc2VwYXJhdGUgaW50byBzZXBhcmF0ZSB2YXJpYWJsZXMgdXNpbmcgZHVtbXkgdmFyaWFibGVzIDxicj4KICA8aT4ocmVmOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy81NDYwMjE5Mi9tYWtlLW9ubHktc29tZS1mZWF0dXJlcy1kdW1teXZhcnMpPC9pPgotIEltcHV0YXRpb24gb2YgTlVMTCB2YWx1ZXMgPGJyPgogIC0gQ2hhbmdlIE5VTEwgdmFsdWVzIG9mIHBhdGllbnQtcHJvdmlkZWQgZGF0YSB0byByZWZsZWN0IGEgIjAiIHJlc3BvbnNlCiAgLSBNSUNFIGltcHV0YXRpb24gZm9yIGFsbCBvdGhlciBOVUxMIHZhbHVlcyA8YnI+CiAgPGk+KHJlZjogaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL21pY2UvdmVyc2lvbnMvMi4yNS90b3BpY3MvbWljZSk8L2k+Ci0gRGV0ZWN0aW9uIG9mIG91dGxpZXJzIDxicj4KICAgIC0gVmlldyBzdW1tYXJ5IG9mIHVuaXZhcmlhdGUgc3RhdGlzdGljcywgc2VhcmNoIGZvciBmbGFncyA8YnI+CiAgICAtIFZpc3VhbGl6ZSBwb3RlbnRpYWwgb3V0bGllcnMgd2l0aCBib3hwbG90czxicj4KICAgIC0gUnVuIGh5cG90aGVzaXMgdGVzdCBvbiBwb3RlbnRpYWwgb3V0bGllcnMgKGdydWJicyB0ZXN0KSA8YnI+CiAgICAtIFN0YW5kYXJkaXplIHZhcmlhYmxlcywgd2hlbiBuZWNlc3NhcnkgPGJyPgogICAgICAtIE5vIGRhdGEgd2lsbCBiZSBkZWxldGVkIG9yIGNoYW5nZWQgdW5sZXNzIGl0IHdhcyBhbiBvYnZpb3VzIG1pc3Rha2UuICBDaGFuZ2luZyBhdmFpbGFibGUgZGF0YSB3aWxsIHNrZXcgbW9kZWxzIHRvd2FyZCBhIGNvbmNsdXNpb24gdGhhdCBtYXkgbm90IGdlbmVyYWxpemUgaWYgZGF0YSBoYXMgYmVlbiBvdmVybHktbWFuaXB1bGF0ZWQuCgo8Yj48Zm9udCBzaXplPSIrMiI+RGF0YSBDbGVhbmluZzwvZm9udD48L2I+PGJyPgpgYGB7cn0KaGVhZChkZl9yYXcpCmBgYAo8Yj48Zm9udCBzaXplPSIrMSI+UmVtb3ZlIGlycmVsZXZhbnQgY29sdW1uczwvZm9udD48L2I+PGJyPgpgYGB7cn0KbGlicmFyeShkcGx5cikKZGYgPC0gZGZfcmF3WyxjKDY6NTMpXQpkZiA8LSBzZWxlY3QoZGYsIGMoLUpvYiwgLU1hcml0YWwpKQpgYGAKPGI+PGZvbnQgc2l6ZT0iKzEiPlJlbmFtZSBtaXNsZWFkaW5nIHZhcmlhYmxlIG5hbWVzPC9mb250PjwvYj48YnI+CmBgYHtyfQpuYW1lcyhkZilbbmFtZXMoZGYpID09ICdJbmNvbWUnXSA8LSAnSW5jb21lX2hvdXNlaG9sZCcKbmFtZXMoZGYpW25hbWVzKGRmKSA9PSAnSXRlbTEnXSA8LSAnU3VydmV5X1RpbWVseUFkbWluJwpuYW1lcyhkZilbbmFtZXMoZGYpID09ICdJdGVtMiddIDwtICdTdXJ2ZXlfVGltZWx5VHJlYXRtZW50JwpuYW1lcyhkZilbbmFtZXMoZGYpID09ICdJdGVtMyddIDwtICdTdXJ2ZXlfVGltZWx5VmlzaXRzJwpuYW1lcyhkZilbbmFtZXMoZGYpID09ICdJdGVtNCddIDwtICdTdXJ2ZXlfUmVsaWFiaWxpdHknCm5hbWVzKGRmKVtuYW1lcyhkZikgPT0gJ0l0ZW01J10gPC0gJ1N1cnZleV9PcHRpb25zJwpuYW1lcyhkZilbbmFtZXMoZGYpID09ICdJdGVtNiddIDwtICdTdXJ2ZXlfSG91cnNUcmVhdG1lbnQnCm5hbWVzKGRmKVtuYW1lcyhkZikgPT0gJ0l0ZW03J10gPC0gJ1N1cnZleV9Db3VydGVvdXNTdGFmZicKbmFtZXMoZGYpW25hbWVzKGRmKSA9PSAnSXRlbTgnXSA8LSAnU3VydmV5X0FjdGl2ZUxpc3RlbmluZycKaGVhZChkZikKYGBgCgo8Yj48Zm9udCBzaXplPSIrMSI+U2V0IGluZGV4PC9mb250PjwvYj48YnI+CmBgYHtyfQpudW1fcm93cyA8LSBkaW0oZGYpWzFdCnJvdy5uYW1lcyhkZikgPC0gYygxOm51bV9yb3dzKQpoZWFkKGRmKQpgYGAKPGI+PGZvbnQgc2l6ZT0iKzEiPlJlLWV4cHJlc3Npb24gb2YgY2F0ZWdvcmljYWwgZGF0YSBhcyBudW1lcmljIGRhdGE8L2ZvbnQ+PC9iPjxicj4KPGJyPgo8Yj5TdGF0ZTwvYj4KYGBge3J9CnggPC0gZGZbb3JkZXIoZGYkU3RhdGUpLCJTdGF0ZSJdCnVuaXF1ZSh4KQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHBseXIpCmRhdGEgPC0gZGYkU3RhdGUKc3RhdGVfZGljdCA8LSBjKAogICJBTCIgPSAxLCAiQUsiID0gMiwgIkFaIiA9IDMsICJBUiIgPSA0LCAiQ0EiID0gNSwgIkNPIiA9IDYsICJDVCIgPSA3LCAiREUiID0gOCwgIkRDIiA9IDksICJGTCIgPSAxMCwgCiAgIkdBIiA9IDExLCAiSEkiID0gMTIsICJJRCIgPSAxMywgIklMIiA9IDE0LCAiSU4iID0gMTUsICJJQSIgPSAxNiwgIktTIiA9IDE3LCAiS1kiID0gMTgsICJMQSIgPSAxOSwgIk1FIiA9IDIwLCAKICAiTUQiID0gMjEsICJNQSIgPSAyMiwgIk1JIiA9IDIzLCAiTU4iID0gMjQsICJNUyIgPSAyNSwgIk1PIiA9IDI2LCAiTVQiID0gMjcsICJORSIgPSAyOCwgIk5WIiA9IDI5LCAiTkgiID0gMzAsIAogICJOSiIgPSAzMSwgIk5NIiA9IDMyLCAiTlkiID0gMzMsICJOQyIgPSAzNCwgIk5EIiA9IDM1LCAiT0giID0gMzYsICJPSyIgPSAzNywgIk9SIiA9IDM4LCAiUEEiID0gMzksICJQUiIgPSA0MCwKICAiUkkiID0gNDEsICJTQyIgPSA0MiwgIlNEIiA9IDQzLCAiVE4iID0gNDQsICJUWCIgPSA0NSwgIlVUIiA9IDQ2LCAiVlQiID0gNDcsICJWQSIgPSA0OCwgIldBIiA9IDQ5LCAiV1YiID0gNTAsCiAgIldJIiA9IDUxLCAiV1kiID0gNTIpCnN0YXRlX3ZhbCA8LSByZXZhbHVlKHg9IGRhdGEsIHJlcGxhY2UgPSBzdGF0ZV9kaWN0KQpkZiRTdGF0ZSA8LSBhcy5udW1lcmljKHN0YXRlX3ZhbCkKYGBgCgo8Yj5BcmVhPC9iPjxicj4KYGBge3J9CnVuaXF1ZShkZiRBcmVhKQpgYGAKYGBge3J9CmRhdGEgPC0gZGYkQXJlYQpteV9kaWN0IDwtIGMoCiAgIlJ1cmFsIiA9IDEsCiAgIlN1YnVyYmFuIiA9IDIsCiAgIlVyYmFuIiA9IDMpCmFyZWFfdmFsIDwtIHJldmFsdWUoeD0gZGF0YSwgcmVwbGFjZSA9IG15X2RpY3QpCmRmJEFyZWEgPC0gYXMubnVtZXJpYyhhcmVhX3ZhbCkKYGBgCjxiPlRpbWV6b25lPC9iPjxicj4KYGBge3J9CnVuaXF1ZShkZiRUaW1lem9uZSkKYGBgCgpgYGB7cn0KZGF0YSA8LSBkZiRUaW1lem9uZQpteV9kaWN0IDwtIGMoCiAgIkFtZXJpY2EvUHVlcnRvX1JpY28iID0gLTQsCiAgIkFtZXJpY2EvRGV0cm9pdCIgPSAtNSwKICAiQW1lcmljYS9JbmRpYW5hL0luZGlhbmFwb2xpcyIgPSAtNSwKICAiQW1lcmljYS9JbmRpYW5hL01hcmVuZ28iID0gLTUsCiAgIkFtZXJpY2EvSW5kaWFuYS9WaW5jZW5uZXMiID0gLTUsCiAgIkFtZXJpY2EvSW5kaWFuYS9WZXZheSIgPSAtNSwKICAiQW1lcmljYS9JbmRpYW5hL1dpbmFtYWMiID0gLTUsCiAgIkFtZXJpY2EvS2VudHVja3kvTG91aXN2aWxsZSIgPSAtNSwKICAiQW1lcmljYS9OZXdfWW9yayIgPSAtNSwKICAiQW1lcmljYS9Ub3JvbnRvIiA9IC01LAogICJBbWVyaWNhL0NoaWNhZ28iID0gLTYsCiAgIkFtZXJpY2EvSW5kaWFuYS9Lbm94IiA9IC02LAogICJBbWVyaWNhL0luZGlhbmEvVGVsbF9DaXR5IiA9IC02LAogICJBbWVyaWNhL01lbm9taW5lZSIgPSAtNiwKICAiQW1lcmljYS9Ob3J0aF9EYWtvdGEvQmV1bGFoIiA9IC02LAogICJBbWVyaWNhL05vcnRoX0Rha290YS9OZXdfU2FsZW0iID0gLTYsCiAgIkFtZXJpY2EvQm9pc2UiID0gLTcsCiAgIkFtZXJpY2EvRGVudmVyIiA9IC03LAogICJBbWVyaWNhL1Bob2VuaXgiID0gLTcsCiAgIkFtZXJpY2EvTG9zX0FuZ2VsZXMiID0gLTgsCiAgIkFtZXJpY2EvQW5jaG9yYWdlIiA9IC05LAogICJBbWVyaWNhL05vbWUiID0gLTksCiAgIkFtZXJpY2EvU2l0a2EiID0gLTksCiAgIkFtZXJpY2EvWWFrdXRhdCIgPSAtOSwKICAiQW1lcmljYS9BZGFrIiA9IC0xMCwKICAiUGFjaWZpYy9Ib25vbHVsdSIgPSAtMTApCnRpbWV6b25lX3ZhbCA8LSByZXZhbHVlKHg9IGRhdGEsIHJlcGxhY2UgPSBteV9kaWN0KQpkZiRUaW1lem9uZSA8LSBhcy5udW1lcmljKHRpbWV6b25lX3ZhbCkKYGBgCjxiPkVkdWNhdGlvbjwvYj48YnI+CmBgYHtyfQp1bmlxdWUoZGYkRWR1Y2F0aW9uKQpgYGAKCmBgYHtyfQpkYXRhIDwtIGRmJEVkdWNhdGlvbgpteV9kaWN0IDwtIGMoCiAgIk5vIFNjaG9vbGluZyBDb21wbGV0ZWQiID0gMCwKICAiTnVyc2VyeSBTY2hvb2wgdG8gOHRoIEdyYWRlIiA9IDgsCiAgIjl0aCBHcmFkZSB0byAxMnRoIEdyYWRlLCBObyBEaXBsb21hIiA9IDEyLAogICJHRUQgb3IgQWx0ZXJuYXRpdmUgQ3JlZGVudGlhbCIgPSAxMiwKICAiUmVndWxhciBIaWdoIFNjaG9vbCBEaXBsb21hIiA9IDEyLAogICJTb21lIENvbGxlZ2UsIExlc3MgdGhhbiAxIFllYXIiID0gMTMsCiAgIlNvbWUgQ29sbGVnZSwgMSBvciBNb3JlIFllYXJzLCBObyBEZWdyZWUiID0gMTQsCiAgIkFzc29jaWF0ZSdzIERlZ3JlZSIgPSAxNSwKICAiQmFjaGVsb3IncyBEZWdyZWUiID0gMTYsCiAgIk1hc3RlcidzIERlZ3JlZSIgPSAxOCwKICAiUHJvZmVzc2lvbmFsIFNjaG9vbCBEZWdyZWUiID0gMjAsCiAgIkRvY3RvcmF0ZSBEZWdyZWUiID0gMjQKICApCmVkdWNhdGlvbl92YWwgPC0gcmV2YWx1ZSh4PSBkYXRhLCByZXBsYWNlID0gbXlfZGljdCkKZGYkRWR1Y2F0aW9uIDwtIGFzLm51bWVyaWMoZWR1Y2F0aW9uX3ZhbCkKYGBgCjxiPkVtcGxveW1lbnQ8L2I+PGJyPgpgYGB7cn0KdW5pcXVlKGRmJEVtcGxveW1lbnQpCmBgYAoKYGBge3J9CmxpYnJhcnkoY2FyZXQpCmRteSA8LSBkdW1teVZhcnMoIiB+IEVtcGxveW1lbnQiLCBkYXRhID0gZGYpCm9oX2VuY29kZWQgPC0gZGF0YS5mcmFtZShwcmVkaWN0KGRteSwgbmV3ZGF0YSA9IGRmKSkKZGYkRW1wbG95bWVudF9GdWxsVGltZSA8LSBvaF9lbmNvZGVkJEVtcGxveW1lbnRGdWxsLlRpbWUKZGYkRW1wbG95bWVudF9QYXJ0VGltZSA8LSBvaF9lbmNvZGVkJEVtcGxveW1lbnRQYXJ0LlRpbWUKZGYkRW1wbG95bWVudF9SZXRpcmVkIDwtIG9oX2VuY29kZWQkRW1wbG95bWVudFJldGlyZWQKZGYkU3R1ZGVudCA8LSBvaF9lbmNvZGVkJEVtcGxveW1lbnRTdHVkZW50CmRmJFVuZW1wbG95ZWQgPC0gb2hfZW5jb2RlZCRFbXBsb3ltZW50VW5lbXBsb3llZApkZiA8LSBzZWxlY3QoZGYsIC1FbXBsb3ltZW50KQpgYGAKPGI+R2VuZGVyPC9iPjxicj4KYGBge3J9CnVuaXF1ZShkZiRHZW5kZXIpCmBgYApgYGB7cn0KZG15IDwtIGR1bW15VmFycygiIH4gR2VuZGVyIiwgZGF0YSA9IGRmKQpvaF9lbmNvZGVkIDwtIGRhdGEuZnJhbWUocHJlZGljdChkbXksIG5ld2RhdGEgPSBkZikpCmRmJEZlbWFsZSA8LSBvaF9lbmNvZGVkJEdlbmRlckZlbWFsZQpkZiRNYWxlIDwtIG9oX2VuY29kZWQkR2VuZGVyTWFsZQpkZiA8LSBzZWxlY3QoZGYsIC1HZW5kZXIpCmBgYAo8Yj5SZWFkbWlzc2lvbjwvYj48YnI+CmBgYHtyfQp1bmlxdWUoZGYkUmVBZG1pcykKYGBgCgpgYGB7cn0KZGF0YSA8LSBkZiRSZUFkbWlzCmJpX2RpY3QgPC0gYygKICAiTm8iID0gMCwKICAiWWVzIiA9IDEKICApCmJpbmFyeV92YWwgPC0gcmV2YWx1ZSh4PSBkYXRhLCByZXBsYWNlID0gYmlfZGljdCkKZGYkUmVBZG1pcyA8LSBhcy5udW1lcmljKGJpbmFyeV92YWwpCmBgYAo8Yj5Tb2Z0IERyaW5rPC9iPjxicj4KYGBge3J9CnVuaXF1ZShkZiRTb2Z0X2RyaW5rKQpgYGAKCmBgYHtyfQpkYXRhIDwtIGRmJFNvZnRfZHJpbmsKYmluYXJ5X3ZhbCA8LSByZXZhbHVlKHg9IGRhdGEsIHJlcGxhY2UgPSBiaV9kaWN0KQpkZiRTb2Z0X2RyaW5rIDwtIGFzLm51bWVyaWMoYmluYXJ5X3ZhbCkKYGBgCjxiPkluaXRpYWwgQWRtaXNzaW9uPC9iPjxicj4KYGBge3J9CnVuaXF1ZShkZiRJbml0aWFsX2FkbWluKQpgYGAKYGBge3J9CmRteSA8LSBkdW1teVZhcnMoIiB+IEluaXRpYWxfYWRtaW4iLCBkYXRhID0gZGYpCm9oX2VuY29kZWQgPC0gZGF0YS5mcmFtZShwcmVkaWN0KGRteSwgbmV3ZGF0YSA9IGRmKSkKZGYkQWRtaW5fZWxlY3RpdmUgPC0gb2hfZW5jb2RlZCRJbml0aWFsX2FkbWluRWxlY3RpdmUuQWRtaXNzaW9uCmRmJEFkbWluX29ic2VydmF0aW9uIDwtIG9oX2VuY29kZWQkSW5pdGlhbF9hZG1pbk9ic2VydmF0aW9uLkFkbWlzc2lvbgpkZiRBZG1pbl9lbWVyZ2VuY3kgPC0gb2hfZW5jb2RlZCRJbml0aWFsX2FkbWluRW1lcmdlbmN5LkFkbWlzc2lvbgpkZiA8LSBzZWxlY3QoZGYsIC1Jbml0aWFsX2FkbWluKQpgYGAKPGI+SGlnaCBibG9vZCBwcmVzc3VyZTwvYj4KYGBge3J9CmRhdGEgPC0gZGYkSGlnaEJsb29kCmJpbmFyeV92YWwgPC0gcmV2YWx1ZSh4PSBkYXRhLCByZXBsYWNlID0gYmlfZGljdCkKZGYkSGlnaEJsb29kIDwtIGFzLm51bWVyaWMoYmluYXJ5X3ZhbCkKYGBgCjxiPlN0cm9rZTwvYj4KYGBge3J9CmRhdGEgPC0gZGYkU3Ryb2tlCmJpbmFyeV92YWwgPC0gcmV2YWx1ZSh4PSBkYXRhLCByZXBsYWNlID0gYmlfZGljdCkKZGYkU3Ryb2tlIDwtIGFzLm51bWVyaWMoYmluYXJ5X3ZhbCkKYGBgCjxiPkNvbXBsaWNhdGlvbiBSaXNrPC9iPgpgYGB7cn0KdW5pcXVlKGRmJENvbXBsaWNhdGlvbl9yaXNrKQpgYGAKYGBge3J9CmRhdGEgPC0gZGYkQ29tcGxpY2F0aW9uX3Jpc2sKbXlfZGljdCA8LSBjKAogICJMb3ciID0gMSwKICAiTWVkaXVtIiA9IDIsCiAgIkhpZ2giID0gMykKcmlza192YWwgPC0gcmV2YWx1ZSh4PSBkYXRhLCByZXBsYWNlID0gbXlfZGljdCkKZGYkQ29tcGxpY2F0aW9uX3Jpc2sgPC0gYXMubnVtZXJpYyhyaXNrX3ZhbCkKYGBgCgo8Yj5BcnRocml0aXM8L2I+CmBgYHtyfQpkYXRhIDwtIGRmJEFydGhyaXRpcwpiaW5hcnlfdmFsIDwtIHJldmFsdWUoeD0gZGF0YSwgcmVwbGFjZSA9IGJpX2RpY3QpCmRmJEFydGhyaXRpcyA8LSBhcy5udW1lcmljKGJpbmFyeV92YWwpCmBgYAo8Yj5EaWFiZXRlczwvYj4KYGBge3J9CmRhdGEgPC0gZGYkRGlhYmV0ZXMKYmluYXJ5X3ZhbCA8LSByZXZhbHVlKHg9IGRhdGEsIHJlcGxhY2UgPSBiaV9kaWN0KQpkZiREaWFiZXRlcyA8LSBhcy5udW1lcmljKGJpbmFyeV92YWwpCmBgYAo8Yj5IeXBlcmxpcGlkZW1pYTwvYj4KYGBge3J9CmRhdGEgPC0gZGYkSHlwZXJsaXBpZGVtaWEKYmluYXJ5X3ZhbCA8LSByZXZhbHVlKHg9IGRhdGEsIHJlcGxhY2UgPSBiaV9kaWN0KQpkZiRIeXBlcmxpcGlkZW1pYSA8LSBhcy5udW1lcmljKGJpbmFyeV92YWwpCmBgYAo8Yj5CYWNrIFBhaW48L2I+CmBgYHtyfQpkYXRhIDwtIGRmJEJhY2tQYWluCmJpbmFyeV92YWwgPC0gcmV2YWx1ZSh4PSBkYXRhLCByZXBsYWNlID0gYmlfZGljdCkKZGYkQmFja1BhaW4gPC0gYXMubnVtZXJpYyhiaW5hcnlfdmFsKQpgYGAKPGI+QWxsZXJnaWMgcmhpbml0aXM8L2I+CmBgYHtyfQpkYXRhIDwtIGRmJEFsbGVyZ2ljX3JoaW5pdGlzCmJpbmFyeV92YWwgPC0gcmV2YWx1ZSh4PSBkYXRhLCByZXBsYWNlID0gYmlfZGljdCkKZGYkQWxsZXJnaWNfcmhpbml0aXMgPC0gYXMubnVtZXJpYyhiaW5hcnlfdmFsKQpgYGAKPGI+UmVmbHV4IGVzb3BoYWdpdGlzPC9iPgpgYGB7cn0KZGF0YSA8LSBkZiRSZWZsdXhfZXNvcGhhZ2l0aXMKYmluYXJ5X3ZhbCA8LSByZXZhbHVlKHg9IGRhdGEsIHJlcGxhY2UgPSBiaV9kaWN0KQpkZiRSZWZsdXhfZXNvcGhhZ2l0aXMgPC0gYXMubnVtZXJpYyhiaW5hcnlfdmFsKQpgYGAKPGI+QXN0aG1hPC9iPgpgYGB7cn0KZGF0YSA8LSBkZiRBc3RobWEKYmluYXJ5X3ZhbCA8LSByZXZhbHVlKHg9IGRhdGEsIHJlcGxhY2UgPSBiaV9kaWN0KQpkZiRBc3RobWEgPC0gYXMubnVtZXJpYyhiaW5hcnlfdmFsKQpgYGAKPGI+U2VydmljZXM8L2I+CmBgYHtyfQp1bmlxdWUoZGYkU2VydmljZXMpCmBgYAoKYGBge3J9CmRhdGEgPC0gZGYkU2VydmljZXMKbXlfZGljdCA8LSBjKAogICJCbG9vZCBXb3JrIiA9IDEsCiAgIkludHJhdmVub3VzIiA9IDIsCiAgIkNUIFNjYW4iID0gMywKICAiTVJJIiA9IDQpCnJpc2tfdmFsIDwtIHJldmFsdWUoeD0gZGF0YSwgcmVwbGFjZSA9IG15X2RpY3QpCmRmJFNlcnZpY2VzIDwtIGFzLm51bWVyaWMocmlza192YWwpCmBgYAoKPGI+PGZvbnQgc2l6ZT0iKzEiPkltcHV0YXRpb24gb2YgTlVMTCB2YWx1ZXM8L2ZvbnQ+PC9iPjxicj4KPGJyPgpgYGB7cn0Kc3VtbWFyeShkZikKYGBgCgo8Yj5OVUxMIHZhbHVlcyBhcmUgZm91bmQgaW4gNyBjb2x1bW5zIDogPC9iPjxicj4KLSBDaGlsZHJlbgotIEFnZQotIEluY29tZV9ob3VzZWhvbGQKLSBTb2Z0X2RyaW5rCi0gT3ZlcndlaWdodAotIEFueGlldHkKLSBJbml0aWFsX2RheXMKCk5VTEwgdmFsdWVzIG9mIHRoZSB2YXJpYWJsZXMgPGI+IkNoaWxkcmVuIjwvYj4sIDxiPiJTb2Z0X2RyaW5rIjwvYj4sIGFuZCA8Yj4iQW54aWV0eSI8L2I+IHdpbGwgYmUgY2hhbmdlZCB0byAwLiAgVGhlc2UgdmFyaWFibGVzIGNvbnNpc3Qgb2YgeWVzL25vIGRhdGEsIDxpPmFzIHJlcG9ydGVkIGJ5IHRoZSBwYXRpZW50PC9pPi4gSXQgaXMgcmVhc29uYWJsZSB0byBiZWxpZXZlIHRoYXQgdGhlc2UgdmFyaWFibGVzIHdvdWxkIGJlIGxlZnQgYmxhbmsgYnkgdGhlIHBhdGllbnQgLWFuZCB0aGVyZWZvcmUgcmVjb3JkZWQgYXMgbnVsbC0gaWYgdGhleSBkaWQgbm90IGFwcGx5IHRvIHRoZSBwYXRpZW50ICgwKS4KYGBge3J9CnZhciA8LSBkZiRTb2Z0X2RyaW5rCmRmJFNvZnRfZHJpbmsgPC0gcmVwbGFjZSh2YXIsIGlzLm5hKHZhciksIDApCnZhciA8LSBkZiRBbnhpZXR5CmRmJEFueGlldHkgPC0gcmVwbGFjZSh2YXIsIGlzLm5hKHZhciksIDApCnZhciA8LSBkZiRDaGlsZHJlbgpkZiRDaGlsZHJlbiA8LSByZXBsYWNlKHZhciwgaXMubmEodmFyKSwgMCkKYGBgCkFsbCBvdGhlciBOVUxMIHZhbHVlcyB3aWxsIGJlIGZpbGxlZCB1c2luZyBNSUNFCmBgYHtyfQpsaWJyYXJ5KG1pY2UpCm1kLnBhdHRlcm4oZGYpCmBgYApgYGB7ciBpbmNsdWRlPUZBTFNFfQogbXltaWNlIDwtIG1pY2UoZGYsIG09MywgCiAgICAgICAgICAgICAgIG1ldGhvZD0ncmYnKQpgYGAKYGBge3J9Cm15bWljZWNvbXBsZXRlIDwtIGNvbXBsZXRlKG15bWljZSwgMikKZGY8LSBteW1pY2Vjb21wbGV0ZQpgYGAKCjxiPjxmb250IHNpemU9IisxIj5JZGVudGlmeWluZyBPdXRsaWVyczwvZm9udD48L2I+PGJyPgpgYGB7cn0KZGYgPC0gZGZbLGMoMTQsIDEsIDMsIDIsIDQ6MTIsIDQ0LCA0NSwgNDYsIDQ4LCA0NywgNDksIDUwLCAxMywgMTUsIDE4LCAxNiwgMTcsIDE5OjMyLCA1MTo1MywgMzM6NDMpXQpgYGAKCmBgYHtyfQpoZWFkKGRmKQpgYGAKPGI+Q2hlY2sgZm9yIG91dGxpZXJzIHVzaW5nIGJveHBsb3RzPC9iPjxicj4KPGJyPgo8cCBzdHlsZT0iY29sb3I6I2ZmMzY5YiI+UG9wdWxhdGlvbjwvcD4KYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKdW5pX291dCA8LSBxcGxvdChkYXRhID0gZGYsIHk9IFBvcHVsYXRpb24sIHg9MSwKICAgICAgICAgICAgICAgICBnZW9tPSdib3hwbG90JywgCiAgICAgICAgICAgICAgICAgb3V0bGllci5jb2xvcj0nZGVlcHBpbmsyJywKICAgICAgICAgICAgICAgICB4bGltPWMoMCwyKSwgCiAgICAgICAgICAgICAgICAgbWFpbj0nUG9wdWxhdGlvbicpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsPWlmZWxzZShQb3B1bGF0aW9uICVpbiUgYm94cGxvdC5zdGF0cyhQb3B1bGF0aW9uKSRvdXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMuY2hhcmFjdGVyKFppcCksICIiKSksIGhqdXN0ID0gMS41KQp1bmlfb3V0CmBgYApBZnRlciBhIHF1aWNrIEdvb2dsZSBzZWFyY2ggb2YgdGhlIHBvcHVsYXRpb25zIGluIHRoZSB0b3AgZm91ciB6aXAgY29kZXMsIHRoZXNlIHBvcHVsYXRpb25zIGFyZSBhY2N1cmF0ZSwgYnV0IHRoZXkgYXJlIG91dGxpZXJzIHRoYXQgbWF5IHJlc3RyaWN0IHRoZSBlZmZlY3RpdmVuZXNzIG9mIGEgbW9kZWwsIHNvIHRoaXMgdmFyaWFibGUgd2lsbCBiZSBzdGFuZGFyZGl6ZWQuCmBgYHtyfQpkZiRQb3B1bGF0aW9uIDwtIHNjYWxlKHggPSBkZiRQb3B1bGF0aW9uKQpgYGAKPHAgc3R5bGU9ImNvbG9yOiNmZjM2OWIiPkNoaWxkcmVuPC9wPgpgYGB7cn0KdW5pX291dCA8LSBxcGxvdChkYXRhID0gZGYsIHk9IENoaWxkcmVuLCB4PTEsCiAgICAgICAgICAgICAgICAgZ2VvbT0nYm94cGxvdCcsIAogICAgICAgICAgICAgICAgIG91dGxpZXIuY29sb3I9J2RlZXBwaW5rMicsCiAgICAgICAgICAgICAgICAgeGxpbT1jKDAsMiksIAogICAgICAgICAgICAgICAgIG1haW49J0NoaWxkcmVuJykKdW5pX291dApgYGAKUGVyZm9ybSBhIGdydWJicyB0ZXN0IG9uIHRoZXNlIG91dGxpZXJzCmBgYHtyfQpsaWJyYXJ5KG91dGxpZXJzKQp4IDwtIGRmJENoaWxkcmVuCmdydWJicy50ZXN0KHgpCmBgYApUaGUgcC12YWx1ZSBpcyBhYm92ZSAwLjA1LCB0aGVzZSB2YWx1ZXMgd2lsbCByZW1haW4gYXMtaXMuPGJyPgo8YnI+CjxwIHN0eWxlPSJjb2xvcjojZmYzNjliIj5BZ2U8L3A+CmBgYHtyfQp1bmlfb3V0IDwtIHFwbG90KGRhdGEgPSBkZiwgeT0gQWdlLCB4PTEsCiAgICAgICAgICAgICAgICAgZ2VvbT0nYm94cGxvdCcsIAogICAgICAgICAgICAgICAgIG91dGxpZXIuY29sb3I9J2RlZXBwaW5rMicsCiAgICAgICAgICAgICAgICAgeGxpbT1jKDAsMiksIAogICAgICAgICAgICAgICAgIG1haW49J0FnZScpCnVuaV9vdXQKYGBgClRoZXJlIGFyZSBubyBvdXRsaWVycyB3aXRoaW4gdGhpcyB2YXJpYWJsZSA8YnI+Cjxicj4KPHAgc3R5bGU9ImNvbG9yOiNmZjM2OWIiPkVkdWNhdGlvbjwvcD4KYGBge3J9CnVuaV9vdXQgPC0gcXBsb3QoZGF0YSA9IGRmLCB5PSBFZHVjYXRpb24sIHg9MSwKICAgICAgICAgICAgICAgICBnZW9tPSdib3hwbG90JywgCiAgICAgICAgICAgICAgICAgb3V0bGllci5jb2xvcj0nZGVlcHBpbmsyJywKICAgICAgICAgICAgICAgICB4bGltPWMoMCwyKSwgCiAgICAgICAgICAgICAgICAgbWFpbj0nRWR1Y2F0aW9uJykKdW5pX291dApgYGAKRXh0cmVtZWx5IGxvdyBhbmQgZXh0cmVtZWx5IGhpZ2ggbGV2ZWxzIG9mIGVkdWNhdGlvbiBhcmUgb3V0bGllcnMsIHNvIHRoaXMgdmFyaWFibGUgd2lsbCBiZSBzdGFuZGFyZGl6ZWQsIHNvIGFzIHRvIHJlZHVjZSBhbnkgbmVnYXRpdmUgaW1wYWN0IHRvIHRoZSBtb2RlbC4KYGBge3J9CmRmJEVkdWNhdGlvbiA8LSBzY2FsZSh4ID0gZGYkRWR1Y2F0aW9uKQpgYGAKPGJyPgo8cCBzdHlsZT0iY29sb3I6I2ZmMzY5YiI+SW5jb21lX2hvdXNlaG9sZDwvcD4KYGBge3J9CnVuaV9vdXQgPC0gcXBsb3QoZGF0YSA9IGRmLCB5PSBJbmNvbWVfaG91c2Vob2xkLCB4PTEsCiAgICAgICAgICAgICAgICAgZ2VvbT0nYm94cGxvdCcsIAogICAgICAgICAgICAgICAgIG91dGxpZXIuY29sb3I9J2RlZXBwaW5rMicsCiAgICAgICAgICAgICAgICAgeGxpbT1jKDAsMiksIAogICAgICAgICAgICAgICAgIG1haW49J0luY29tZV9ob3VzZWhvbGQnKQp1bmlfb3V0CmBgYApgYGB7cn0KeCA8LSBkZiRJbmNvbWVfaG91c2Vob2xkCmdydWJicy50ZXN0KHgpCmBgYApUaGVzZSB2YWx1ZXMgZGlmZmVyIGZyb20gdGhlIG1lYW4gc2lnbmlmaWNhbnRseS0gdGhleSB3aWxsIGJlIHN0YW5kYXJkaXplZC4KYGBge3J9CmRmJEluY29tZV9ob3VzZWhvbGQgPC0gc2NhbGUoeCA9IGRmJEluY29tZV9ob3VzZWhvbGQpCmBgYAo8YnI+CjxwIHN0eWxlPSJjb2xvcjojZmYzNjliIj5WaXREX2xldmVsczwvcD4KYGBge3J9CnVuaV9vdXQgPC0gcXBsb3QoZGF0YSA9IGRmLCB5PSBWaXREX2xldmVscywgeD0xLAogICAgICAgICAgICAgICAgIGdlb209J2JveHBsb3QnLCAKICAgICAgICAgICAgICAgICBvdXRsaWVyLmNvbG9yPSdkZWVwcGluazInLAogICAgICAgICAgICAgICAgIHhsaW09YygwLDIpLCAKICAgICAgICAgICAgICAgICBtYWluPSdWaXREX2xldmVscycpCnVuaV9vdXQKYGBgCjxiPkNoZWNrIGZvciBjb3JyZWxhdGlvbiBiZXR3ZWVuIFZpdERfbGV2ZWxzIGFuZCBWaXREX3N1cHA8L2I+CmBgYHtyfQpwbG90KGRmJFZpdERfbGV2ZWxzLCBkZiRWaXREX3N1cHAsIAogICAgIG1haW4gPSdWaXRhbWluIEQgTGV2ZWxzIGFuZCBTdXBwbGVtZW50cycsIAogICAgIHhsYWIgPSdMZXZlbHMnLCAKICAgICB5bGFiID0gJ1N1cHBsZW1lbnRzIEFkbWluaXN0ZXJlZCcpCmBgYApUaGVyZSBzZWVtIHRvIGJlIHR3byBzZXBhcmF0ZSBjbHVzdGVycyBvZiBkYXRhLCBzbyB0aGUgY2x1c3RlciBjb25zaXN0aW5nIG9mIHBhdGllbnRzIHdpdGggaGlnaCB2aXRhbWluIEQgbGV2ZWxzIHRoYXQgYWxzbyByZWNlaXZlZCB2aXRhbWluIEQgc3VwcGxlbWVudHMgd2lsbCBiZSBjaGVja2VkIGFnYWluc3QgcG90ZW50aWFsIHJlYXNvbnMgZm9yIHRoZSBzdXBwbGVtZW50YXRpb24gb2Ygdml0YW1pbiBEIGZvciBwYXRpZW50cyB3aXRoIHNlZW1pbmdseS1ub3JtYWwgbGV2ZWxzIG9mIHZpdGFtaW4gRC4KYGBge3J9CmhpZ2hfVml0RCA8LSB3aGljaChkZiRWaXREX2xldmVscyA+IDMwICYgZGYkVml0RF9zdXBwPjEpCm91dCA8LSBkZltoaWdoX1ZpdEQsXSA7IG91dApwbG90KG91dCRBZ2UsIG91dCRPdmVyd2VpZ2h0KQpgYGAKQWxsIHRoZXNlIHBvdGVudGlhbCBvdXRsaWVycyBhcmUgcGxhdXNpYmxlLCBnaXZlbiB0aGF0IHBhdGllbnRzIG92ZXIgNTAgYW5kL29yIG92ZXJ3ZWlnaHQgYXJlIGF0IGhpZ2hlciByaXNrIGZvciBoZWFsdGggaXNzdWVzIHRoYXQgd291bGQgcmVxdWlyZSBjYWxjaXVtIHN1cHBsZW1lbnRhdGlvbiAod2hpY2ggaW4gdHVybiByZXF1aXJlcyBtb3JlIFZpdGFtaW4gRCBpbiBvcmRlciB0byBhYnNvcmIgdGhlIGNhbGNpdW0pLiAgVGhlc2UgYXJlIG5hdHVyYWwgb3V0bGllcnMgYW5kIHBlcnRpbmVudCB0byBhbmFseXNpcywgZ2l2ZW4gdGhlIHBvc3NpYmlsaXR5IHRoYXQgcGF0aWVudHMgYXJlIG1vcmUgbGlrZWx5IHRvIGJlIHJlYWRtaXR0ZWQgaWYgdGhleSBhcmUgbm90IGdpdmVuIHRoZSBwcm9wZXIgc3VwcGxlbWVudGF0aW9uLiAgVGhlc2UgdmFsdWVzIHdpbGwgcmVtYWluIGFzLWlzIGluIHRoZSBjbGVhbiBkYXRhLjxicj4KPGJyPgo8cCBzdHlsZT0iY29sb3I6I2ZmMzY5YiI+RG9jX3Zpc2l0czwvcD4KYGBge3J9CnVuaV9vdXQgPC0gcXBsb3QoZGF0YSA9IGRmLCB5PSBEb2NfdmlzaXRzLCB4PTEsCiAgICAgICAgICAgICAgICAgZ2VvbT0nYm94cGxvdCcsIAogICAgICAgICAgICAgICAgIG91dGxpZXIuY29sb3I9J2RlZXBwaW5rMicsCiAgICAgICAgICAgICAgICAgeGxpbT1jKDAsMiksIAogICAgICAgICAgICAgICAgIG1haW49J0RvY192aXNpdHMnKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1pZmVsc2UoRG9jX3Zpc2l0cyAlaW4lIGJveHBsb3Quc3RhdHMoRG9jX3Zpc2l0cykkb3V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmNoYXJhY3RlcihSZUFkbWlzKSwgIiIpKSwgaGp1c3QgPSAxLjUpCnVuaV9vdXQKYGBgClRoZXJlIGFyZSBubyBvdXRsaWVycyB3aXRoaW4gdGhpcyB2YXJpYWJsZTxicj4KPGJyPgo8cCBzdHlsZT0iY29sb3I6I2ZmMzY5YiI+RnVsbCBNZWFscyBFYXRlbjwvcD4KYGBge3J9CnVuaV9vdXQgPC0gcXBsb3QoZGF0YSA9IGRmLCB5PSBGdWxsX21lYWxzX2VhdGVuLCB4PTEsCiAgICAgICAgICAgICAgICAgZ2VvbT0nYm94cGxvdCcsIAogICAgICAgICAgICAgICAgIG91dGxpZXIuY29sb3I9J2RlZXBwaW5rMicsCiAgICAgICAgICAgICAgICAgeGxpbT1jKDAsMiksIAogICAgICAgICAgICAgICAgIG1haW49J0Z1bGxfbWVhbHNfZWF0ZW4nKQp1bmlfb3V0CmBgYApIeXBvdGhlc2lzIHRlc3QKYGBge3J9CnggPC0gZGYkRnVsbF9tZWFsc19lYXRlbgpncnViYnMudGVzdCh4KQpgYGAKU3RhbmRhcmRpemUgdmFsdWVzCmBgYHtyfQpkZiRGdWxsX21lYWxzX2VhdGVuIDwtIHNjYWxlKHggPSBkZiRGdWxsX21lYWxzX2VhdGVuKQpgYGAKPGJyPgoKPHAgc3R5bGU9ImNvbG9yOiNmZjM2OWIiPkNvbXBsaWNhdGlvbl9yaXNrPC9wPgpgYGB7cn0KdW5pX291dCA8LSBxcGxvdChkYXRhID0gZGYsIHk9IENvbXBsaWNhdGlvbl9yaXNrLCB4PTEsCiAgICAgICAgICAgICAgICAgZ2VvbT0nYm94cGxvdCcsIAogICAgICAgICAgICAgICAgIG91dGxpZXIuY29sb3I9J2RlZXBwaW5rMicsCiAgICAgICAgICAgICAgICAgeGxpbT1jKDAsMiksIAogICAgICAgICAgICAgICAgIG1haW49J0NvbXBsaWNhdGlvbl9yaXNrJykgKwogIGdlb21fdGV4dChhZXMobGFiZWw9aWZlbHNlKENvbXBsaWNhdGlvbl9yaXNrICVpbiUgYm94cGxvdC5zdGF0cyhDb21wbGljYXRpb25fcmlzaykkb3V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmNoYXJhY3RlcihSZUFkbWlzKSwgIiIpKSwgaGp1c3QgPSAxLjUpCnVuaV9vdXQKYGBgClRoZXJlIGFyZSBubyBvdXRsaWVycyB3aXRoaW4gdGhpcyB2YXJpYWJsZS48YnI+Cjxicj4KCjxwIHN0eWxlPSJjb2xvcjojZmYzNjliIj5Jbml0aWFsX2RheXM8L3A+CmBgYHtyfQp1bmlfb3V0IDwtIHFwbG90KGRhdGEgPSBkZiwgeT0gSW5pdGlhbF9kYXlzLCB4PTEsCiAgICAgICAgICAgICAgICAgZ2VvbT0nYm94cGxvdCcsIAogICAgICAgICAgICAgICAgIG91dGxpZXIuY29sb3I9J2RlZXBwaW5rMicsCiAgICAgICAgICAgICAgICAgeGxpbT1jKDAsMiksIAogICAgICAgICAgICAgICAgIG1haW49J0luaXRpYWxfZGF5cycpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsPWlmZWxzZShJbml0aWFsX2RheXMgJWluJSBib3hwbG90LnN0YXRzKEluaXRpYWxfZGF5cykkb3V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmNoYXJhY3RlcihJbml0aWFsX2RheXMpLCAiIikpLCBoanVzdCA9IDEuNSkKdW5pX291dApgYGAKVGhlcmUgYXJlIG5vIG91dGxpZXJzIHdpdGhpbiB0aGlzIHZhcmlhYmxlCgo8cCBzdHlsZT0iY29sb3I6I2ZmMzY5YiI+VG90YWxDaGFyZ2U8L3A+CmBgYHtyfQp1bmlfb3V0IDwtIHFwbG90KGRhdGEgPSBkZiwgeT0gVG90YWxDaGFyZ2UsIHg9MSwKICAgICAgICAgICAgICAgICBnZW9tPSdib3hwbG90JywgCiAgICAgICAgICAgICAgICAgb3V0bGllci5jb2xvcj0nZGVlcHBpbmsyJywKICAgICAgICAgICAgICAgICB4bGltPWMoMCwyKSwgCiAgICAgICAgICAgICAgICAgbWFpbj0nVG90YWxDaGFyZ2UnKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1pZmVsc2UoVG90YWxDaGFyZ2UgJWluJSBib3hwbG90LnN0YXRzKFRvdGFsQ2hhcmdlKSRvdXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMuY2hhcmFjdGVyKFJlQWRtaXMpLCAiIikpLCBoanVzdCA9IDEuNSkKdW5pX291dApgYGAKVGhlcmUgYXJlIG91dGxpZXJzIHdpdGhpbiB0aGUgVG90YWxDaGFyZ2UgdmFyaWFibGUsIGJ1dCB0aGVyZSBzZWVtcyB0byBiZSBhIGNvcnJlbGF0aW9uIGJldHdlZW4gUmVhZG1pc3Npb24gYW5kIHRvdGFsIGNoYXJnZSwgc28gdGhpcyBkYXRhIHdpbGwgbm90IGJlIGFsdGVyZWQuPGJyPgo8YnI+CjxwIHN0eWxlPSJjb2xvcjojZmYzNjliIj5BZGRpdGlvbmFsX2NoYXJnZXM8L3A+CmBgYHtyfQp1bmlfb3V0IDwtIHFwbG90KGRhdGEgPSBkZiwgeT0gQWRkaXRpb25hbF9jaGFyZ2VzLCB4PTEsCiAgICAgICAgICAgICAgICAgZ2VvbT0nYm94cGxvdCcsIAogICAgICAgICAgICAgICAgIG91dGxpZXIuY29sb3I9J2RlZXBwaW5rMicsCiAgICAgICAgICAgICAgICAgeGxpbT1jKDAsMiksIAogICAgICAgICAgICAgICAgIG1haW49J0FkZGl0aW9uYWxfY2hhcmdlcycpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsPWlmZWxzZShBZGRpdGlvbmFsX2NoYXJnZXMgJWluJSBib3hwbG90LnN0YXRzKEFkZGl0aW9uYWxfY2hhcmdlcykkb3V0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLmNoYXJhY3RlcihSZUFkbWlzKSwgIiIpKSwgaGp1c3QgPSAxLjUpCnVuaV9vdXQKYGBgClN0YW5kYXJkaXplIHZhcmlhYmxlCmBgYHtyfQpkZiRBZGRpdGlvbmFsX2NoYXJnZXMgPC0gc2NhbGUoeCA9IGRmJEFkZGl0aW9uYWxfY2hhcmdlcykKYGBgCjxicj4KbmFtZXMoZGYpW25hbWVzKGRmKSA9PSAnSXRlbTEnXSA8LSAnU3VydmV5X1RpbWVseUFkbWluJwpuYW1lcyhkZilbbmFtZXMoZGYpID09ICdJdGVtMiddIDwtICdTdXJ2ZXlfVGltZWx5VHJlYXRtZW50JwpuYW1lcyhkZilbbmFtZXMoZGYpID09ICdJdGVtMyddIDwtICdTdXJ2ZXlfVGltZWx5VmlzaXRzJwpuYW1lcyhkZilbbmFtZXMoZGYpID09ICdJdGVtNCddIDwtICdTdXJ2ZXlfUmVsaWFiaWxpdHknCm5hbWVzKGRmKVtuYW1lcyhkZikgPT0gJ0l0ZW01J10gPC0gJ1N1cnZleV9PcHRpb25zJwpuYW1lcyhkZilbbmFtZXMoZGYpID09ICdJdGVtNiddIDwtICdTdXJ2ZXlfSG91cnNUcmVhdG1lbnQnCm5hbWVzKGRmKVtuYW1lcyhkZikgPT0gJ0l0ZW03J10gPC0gJ1N1cnZleV9Db3VydGVvdXNTdGFmZicKbmFtZXMoZGYpW25hbWVzKGRmKSA9PSAnSXRlbTgnXSA8LSAnU3VydmV5X0FjdGl2ZUxpc3RlbmluZycKPHAgc3R5bGU9ImNvbG9yOiNmZjM2OWIiPlN1cnZleSBSZXN1bHRzPC9wPgpgYGB7cn0Kc3VydmV5X3Jlc3VsdHMgPC0gZGZbLDQ2OjUzXQpmb3IgKGNvbCBpbiBzdXJ2ZXlfcmVzdWx0cyl7CiAgdW5pX291dCA8LSBxcGxvdChkYXRhID0gc3VydmV5X3Jlc3VsdHMsIHk9IGNvbCwgeD0xLAogICAgICAgICAgICAgICAgICAgIGdlb209J2JveHBsb3QnLCAKICAgICAgICAgICAgICAgICAgICBvdXRsaWVyLmNvbG9yPSdkZWVwcGluazInLAogICAgICAgICAgICAgICAgICAgIHhsaW09YygwLDIpKQogIHByaW50KHVuaV9vdXQpCn0KCmBgYApgYGB7cn0KZm9yIChjb2wgaW4gc3VydmV5X3Jlc3VsdHMpewogIHggPC0gY29sCiAgcHJpbnQoZ3J1YmJzLnRlc3QoeCkpCn0KYGBgClRoZXNlIHZhbHVlcyB3aWxsIHJlbWFpbi48YnI+Cjxicj4KPGJyPgo8Yj48Zm9udCBzaXplPSIrMiI+RGF0YSBDbGVhbmluZyBTdHJlbmd0aHMgJiBXZWFrbmVzc2VzPC9mb250PjwvYj48YnI+ClRoZSBzdHJlbmd0aHMgb2YgdGhpcyBjbGVhbiBkYXRhIGFyZSB0aGF0IG5lYXJseSBhbGwgdmFsdWVzIGFyZSBudW1lcmljLCBhbGxvd2luZyBlYXN5IGNhbGN1bGF0aW9ucyBhbmQgdmlzdWFsaXphdGlvbnMsIGFuZCB0aGVyZSBhcmUgbm8gbnVsbCB2YWx1ZXMgcmVtYWluaW5nLiAgVGhlIHdlYWtuZXNzZXMgYXJlIHRoYXQgbm90IGFsbCBuZXcgbnVtZXJpYyB2YWx1ZXMgYXJlIG5vdCBlYXNpbHkgaW50ZXJwcmV0ZWQgd2l0aG91dCBhIGRhdGEgZGljdGlvbmFyeS48YnI+ClRoZSBtYWpvciBsaW1pdGF0aW9uIHdoZW4gY2xlYW5pbmcgdGhlIGRhdGEgc2V0IHdhcyBub3QgaGF2aW5nIGFjY2VzcyB0byB0aGUgaW5kaXZpZHVhbHMgdGhhdCBjb2xsZWN0ZWQgdGhlIGRhdGEuICBNYW55IG1vcmUgZGVjaXNpb25zIGNvdWxkIGhhdmUgYmVlbiBtYWRlIGhhZCB0aGUgdmFyaWFibGVzIGJlZW4gYmV0dGVyIGV4cGxhaW5lZC4gIEZvciBleGFtcGxlLCBWaXREX3N1cHAgaXMgZGVzY3JpYmVkIGFzIHRoZSAibnVtYmVyIG9mIHRpbWVzIiBhIHBhdGllbnQgaXMgYWRtaW5pc3RlcmVkIGEgdml0YW1pbiBEIHN1cHBsZW1lbnQuICBJdCB3YXMgbm90IGNsYXJpZmllZCBpZiB0aGlzIG51bWJlciB3YXMgZGFpbHksIG92ZXIgdGhlIGNvdXJzZSBvZiB0aGUgZW50aXJlIGluaXRpYWwgc3RheSwgb3IgYW55IHNwZWNpZmljIGRvc2FnZS4gIFRoaXMgbWF5IGFmZmVjdCB0aGUgYW5hbHlzaXMgaW4gdGhhdCByZXN1bHRzIG1heSBiZSBza2V3ZWQgaW4gdW5hbnRpY2lwYXRlZCBkaXJlY3Rpb25zIGR1ZSB0byB1bmJhbGFuY2VkIGRhdGEuPGJyPgo8YnI+CjxiPjxmb250IHNpemU9IisyIj5QcmluY2lwbGUgQ29tcG9uZW50IEFuYWx5c2lzPC9mb250PjwvYj48YnI+CjxpPihyZWY6IGh0dHA6Ly9mYWN0b21pbmVyLmZyZWUuZnIvZmFjdG9tZXRob2RzL3ByaW5jaXBhbC1jb21wb25lbnRzLWFuYWx5c2lzLmh0bWwpPC9pPjxicj4KPGJyPgpgYGB7cn0KaGVhZChkZikKYGBgCkkgd2lsbCBub3QgdXNlIHRoZSB0YXJnZXQgdmFyaWFibGUgKFJlQWRtaXMpLCB0aGUgcXVhbGl0aXRhdGl2ZSB2YXJpYWJsZXMgKENpdHkgYW5kIENvdW50eSksIG9yIHRoZSByZWR1bmRhbnQgdmFyaWFibGVzIChTdGF0ZSwgTGF0LCBMbmcsIFRpbWV6b25lKQo8Yj5TdGFuZGFyZGl6YXRpb248L2I+CmBgYHtyfQpkZl9zdWIgPC0gc2NhbGUoeCA9IGRmWyxjKDUsIDgsIDksIDExOjUzKV0pCmhlYWQoZGZfc3ViKQpgYGAKPGJyPgo8Yj5QcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzPC9iPgpgYGB7cn0KbGlicmFyeShGYWN0b01pbmVSKQpkZl9zdWIucGNhIDwtIFBDQShkZl9zdWIsIHNjYWxlLnVuaXQ9VFJVRSwgZ3JhcGg9RikKYGBgCjxicj4KPGI+IFNjcmVlIFBsb3Q8L2I+CmBgYHtyfQplaWcudmFsIDwtIGRmX3N1Yi5wY2EkZWlnCgpiYXJwbG90KGVpZy52YWxbLCAyXSwKCiAgICAgICAgbWFpbiA9ICJFeHBsYWluZWQgVmFyaWFuY2UgKCUpIiwKCiAgICAgICAgeGxhYiA9ICJQcmluY2lwYWwgQ29tcG9uZW50cyIsCgogICAgICAgIHlsYWIgPSAiKCUpIG9mIFZhcmlhbmNlIiwKCiAgICAgICAgY29sID0gImRhcmtibHVlIikKYGBgCjxicj4KPGI+IEdyYXBoIG9mIEluZGl2aWR1YWxzIDwvYj4KYGBge3J9CnBsb3QoZGZfc3ViLnBjYSwgY2hvaXggPSAiaW5kIiwgYXV0b0xhYiA9ICJhdXRvIiwgaGFiaWxsYWdlID0gImNvczIiLCBjb2wuaW5kPSJkYXJrYmx1ZSIsIGxhYmVsPSJ2YXIiLCBncmFwaC50eXBlID0gImdncGxvdCIpCmBgYAo8YnI+CjxiPiBHcmFwaCBvZiBWYXJpYWJsZXMgPC9iPgpgYGB7cn0KcGxvdChkZl9zdWIucGNhLCBjaG9peCA9ICJ2YXIiLCBhdXRvTGFiID0gImF1dG8iLCBjb2wudmFyPSJkYXJrYmx1ZSIsIGxhYmVsPSJ2YXIiLCBncmFwaC50eXBlID0gImdncGxvdCIsIHNlbGVjdD0iY29zMiAwLjQwIikKYGBgCmBgYHtyfQpwbG90KGRmX3N1Yi5wY2EsIGNob2l4ID0gImluZCIsIGF1dG9MYWIgPSAiYXV0byIsIGhhYmlsbGFnZSA9ICJUb3RhbENoYXJnZSIsIGNvbC5pbmQ9ImRhcmtibHVlIiwgbGFiZWw9InZhciIsIGdyYXBoLnR5cGUgPSAiZ2dwbG90IikKCnBsb3QoZGZfc3ViLnBjYSwgY2hvaXggPSAiaW5kIiwgYXV0b0xhYiA9ICJhdXRvIiwgaGFiaWxsYWdlID0gIkFkZGl0aW9uYWxfY2hhcmdlcyIsIGNvbC5pbmQ9ImRhcmtibHVlIiwgbGFiZWw9InZhciIsIGdyYXBoLnR5cGUgPSAiZ2dwbG90IikKCnBsb3QoZGZfc3ViLnBjYSwgY2hvaXggPSAiaW5kIiwgYXV0b0xhYiA9ICJhdXRvIiwgaGFiaWxsYWdlID0gIlN1cnZleV9Ib3Vyc1RyZWF0bWVudCIsIGNvbC5pbmQ9ImRhcmtibHVlIiwgbGFiZWw9InZhciIsIGdyYXBoLnR5cGUgPSAiZ2dwbG90IikKCnBsb3QoZGZfc3ViLnBjYSwgY2hvaXggPSAiaW5kIiwgYXV0b0xhYiA9ICJhdXRvIiwgaGFiaWxsYWdlID0gIlN1cnZleV9UaW1lbHlWaXNpdHMiLCBjb2wuaW5kPSJkYXJrYmx1ZSIsIGxhYmVsPSJ2YXIiLCBncmFwaC50eXBlID0gImdncGxvdCIpCgpwbG90KGRmX3N1Yi5wY2EsIGNob2l4ID0gImluZCIsIGF1dG9MYWIgPSAiYXV0byIsIGhhYmlsbGFnZSA9ICJTdXJ2ZXlfVGltZWx5QWRtaW4iLCBjb2wuaW5kPSJkYXJrYmx1ZSIsIGxhYmVsPSJ2YXIiLCBncmFwaC50eXBlID0gImdncGxvdCIpCgpwbG90KGRmX3N1Yi5wY2EsIGNob2l4ID0gImluZCIsIGF1dG9MYWIgPSAiYXV0byIsIGhhYmlsbGFnZSA9ICJTdXJ2ZXlfVGltZWx5VHJlYXRtZW50IiwgY29sLmluZD0iZGFya2JsdWUiLCBsYWJlbD0idmFyIiwgZ3JhcGgudHlwZSA9ICJnZ3Bsb3QiKQpgYGAKCjxicj4KPGI+IEluIG9yZGVyIHRvIGRldGVybWluZSB0aGUgcHJpbmNpcGFsIGNvbXBvbmVudHMsIEkgcmFuIHRoZSBQQ0EgdXNpbmcgdGhlIHBhY2thZ2UgRmFjdG9NaW5lUiBhbmQgdmlld2VkIHRoZSBTY3JlZSBwbG90LiAgVGhlIFBDQSBncmFwaHMgb2YgaW5kaXZpZHVhbHMgYW5kIHZhcmlhYmxlcyBhbGxvd2VkIG1lIHRvIHJlZHVjZSB0aGUgZGF0YSB0byB0aGUgbW9zdCBpbXBvcnRhbnQgdmFyaWFibGVzIGluIHRlcm1zIG9mIHRoZSBvcmlnaW5hbCB2ZWN0b3Igb2YgdmFyaWFibGVzLiAgVGhlIHZhcmlhYmxlcyB3aXRoIGNvczIgb3ZlciAwLjQgd2VyZSB0aG9zZSB0aGF0IEkgaWRlbnRpZmllZCBhcyAibW9zdCBpbXBvcnRhbnQsIiBhbmQgdGhleSB3ZXJlIGRldGVybWluZWQgdG8gYmU8YnI+Cjxicj4KLSBUb3RhbENoYXJnZQotIEFkZGl0aW9uYWxfY2hhcmdlcwotIFN1cnZleV9Ib3Vyc1RyZWF0bWVudAotIFN1cnZleV9UaW1lbHlWaXNpdHMKLSBTdXJ2ZXlfVGltZWx5QWRtaW4KLSBTdXJ2ZXlfVGltZWx5VHJlYXRtZW50Cjxicj4KPGJyPgpIb3NwaXRhbHMgY2FuIGJlbmVmaXQgZnJvbSByZXNlYXJjaGluZyB0aGVzZSBjb21wb25lbnRzIGFuZCBhbmFseXppbmcgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlc2UgcHJpbmNpcGFsIGNvbXBvbmVudHMgYW5kIHJlYWRtaXNzaW9uIHJhdGVzLiAgUGVuZGluZyByZXN1bHRzIG9mIGFuIGluLWRlcHRoIGFuYWx5c2lzLCB0aGUgb3JnYW5pemF0aW9uIGNhbiBvYnRhaW4gYWN0aW9uYWJsZSBpbnNpZ2h0cyBhbmQgYXR0ZW1wdCB0byByZWR1Y2UgcmVhZG1pc3Npb24gcmF0ZXMuCgoKCgo=