Name : Mst Nigar Sultana

Part 1 :

2) Loading dataset :

heart = read.csv('heart.csv')
heart

3) Few sentences to explain the dataset :a)Identify numerical columns. b)Identify categorical columns.c)Identify target variable (normally the last column is the target variable)

print("The dataset contains information on 918 individuals with 12 variables, including Age, Sex, ChestPainType, RestingBP, Cholesterol, FastingBS, RestingECG, MaxHR, ExerciseAngina, Oldpeak, ST_Slope, and HeartDisease. The individuals' ages range from 28 to 77 years. There are 5 numerical features (Ages, RestingBP, Cholesterol, MaxHR, and Oldpeak ), while others are categorical (Sex, ChestPainType, FastingBS,RestingECG,ExerciseAngina,ST_Slope,HeartDisease). The last column 'HeartDisease' is the target variable .The dataset provides a comprehensive overview of various health-related attributes for the individuals studied.")
[1] "The dataset contains information on 918 individuals with 12 variables, including Age, Sex, ChestPainType, RestingBP, Cholesterol, FastingBS, RestingECG, MaxHR, ExerciseAngina, Oldpeak, ST_Slope, and HeartDisease. The individuals' ages range from 28 to 77 years. There are 5 numerical features (Ages, RestingBP, Cholesterol, MaxHR, and Oldpeak ), while others are categorical (Sex, ChestPainType, FastingBS,RestingECG,ExerciseAngina,ST_Slope,HeartDisease). The last column 'HeartDisease' is the target variable .The dataset provides a comprehensive overview of various health-related attributes for the individuals studied."
numeric_columns = heart[ ,c(1,4,5,8,10)]
numeric_columns
categorical_columns = heart[ ,c(2,3,6,7,9,11,12)]
categorical_columns
target_variable = heart[ ,12]
target_variable
  [1] 0 1 0 1 0 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0
 [49] 0 1 1 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 1 0 1
 [97] 0 0 0 0 1 0 1 1 1 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 0 0 1 0 0 0 0 0 0 0 1 1 1 0 1 0 0 1 1 1 1 1 0
[145] 1 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 0 1 0 1 0 1 0 0
[193] 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 1 1 1
[241] 0 1 1 0 1 0 1 1 1 1 1 1 0 0 1 0 0 0 0 0 0 0 1 1 1 0 1 0 1 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0
[289] 0 0 0 0 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1
[337] 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[385] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 0 1 0 1 1 0 1 1 1 1 0
[433] 1 1 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 0 1 1 1 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 1 1
[481] 1 1 1 1 1 1 0 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 0 1 1 0 1 0 1 1 0 1 1 1 1 0 1 1 1 0 0 1 0
[529] 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 1 0 1 1 0 1 0 1 1 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1
[577] 1 1 1 1 1 1 1 0 1 1 1 0 1 1 0 0 1 1 1 1 1 0 1 1 0 1 1 1 0 0 1 1 1 1 1 0 1 0 1 1 0 1 0 0 0 1 1 1
[625] 1 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 0 1 1 1 1 1 0 0 0 0 0 1
[673] 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 1 1 1 1 1 0 1 0 0 0 1 0 1 1
[721] 1 0 1 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 0 0 0 1 0 0 1 1 1 0 1 0 0 0 1 0 0 1 0 1 0 1 1 1 1 1 0 0 0 0
[769] 0 0 0 1 0 0 1 1 1 0 1 0 0 0 0 0 1 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 0 1 0 1 0 0 0 0 0 1 0
[817] 1 1 1 1 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 0 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 0 1
[865] 1 1 0 1 0 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0 1 0 0 1 1 1 0 0 0 1 0 1 0 1 0 1 1 1 0 0 0 1 0 1 1 1 0 1
[913] 1 1 1 1 1 0

4. Remove all the categorical columns (not the target column) from the dataset. Now we will call all the numerical columns as features and the last column as target or class.

Examine_data = heart[ ,c(-2,-3,-6,-7,-9,-11)]
Examine_data
target = heart$HeartDisease
target
  [1] 0 1 0 1 0 0 0 0 1 0 0 1 0 1 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 1 0 0 0 0 1 0 0 1 0 0 0
 [49] 0 1 1 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 0 1 0 0 0 0 1 0 1
 [97] 0 0 0 0 1 0 1 1 1 0 0 0 0 0 0 1 0 0 0 1 1 1 0 1 1 0 0 1 0 0 0 0 0 0 0 1 1 1 0 1 0 0 1 1 1 1 1 0
[145] 1 0 0 0 0 1 0 0 0 0 0 1 1 0 1 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 1 0 0 1 0 1 0 1 0 0
[193] 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 1 0 0 1 0 1 0 0 0 1 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 1 1 1
[241] 0 1 1 0 1 0 1 1 1 1 1 1 0 0 1 0 0 0 0 0 0 0 1 1 1 0 1 0 1 0 0 0 1 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0
[289] 0 0 0 0 0 1 1 1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1
[337] 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[385] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 0 1 0 1 1 0 1 1 1 1 0
[433] 1 1 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 0 1 1 1 0 1 0 1 0 1 0 1 1 1 1 0 1 0 1 1 1
[481] 1 1 1 1 1 1 0 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 0 1 1 0 1 0 1 1 0 1 1 1 1 0 1 1 1 0 0 1 0
[529] 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 0 1 0 1 1 0 1 0 1 1 1 0 0 0 1 1 1 0 1 1 1 1 1 1 1 1 1
[577] 1 1 1 1 1 1 1 0 1 1 1 0 1 1 0 0 1 1 1 1 1 0 1 1 0 1 1 1 0 0 1 1 1 1 1 0 1 0 1 1 0 1 0 0 0 1 1 1
[625] 1 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 0 1 1 1 1 1 0 0 0 0 0 1
[673] 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 1 1 1 1 1 0 1 0 0 0 1 0 1 1
[721] 1 0 1 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 0 0 0 1 0 0 1 1 1 0 1 0 0 0 1 0 0 1 0 1 0 1 1 1 1 1 0 0 0 0
[769] 0 0 0 1 0 0 1 1 1 0 1 0 0 0 0 0 1 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 0 1 0 0 1 0 1 0 1 0 0 0 0 0 1 0
[817] 1 1 1 1 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 0 1 0 0 1 1 0 0 1 1 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 0 1
[865] 1 1 0 1 0 0 0 0 1 1 0 0 1 1 0 1 0 0 0 0 1 0 0 1 1 1 0 0 0 1 0 1 0 1 0 1 1 1 0 0 0 1 0 1 1 1 0 1
[913] 1 1 1 1 1 0

5.Scatter plot of any two features - each class (target) should be represented with different colors.

target_color = as.numeric(factor(heart$HeartDisease))
plot(heart$Age,heart$Cholesterol,
     
    col = target_color,
     pch = 2,
     cex = 0.5,
     xlim = c(20,80),
     ylim = c(1, 500),
     xlab = "Age" ,
     ylab = "Cholesterol",
     main = "Visualization of Age and Cholesterol",
     col.main = 'blue',
     col.axis = 'black',
     col.lab = 'red',
     cex.main = 1.5,
     cex.axis = 1,
     cex.lab = 1,
    )

a. Histogram plot of any single feature.

hist(heart$MaxHR, main = "Histogram plot", xlab = "MaxHR", col = "blue")

b. Boxplot of any single feature

boxplot(heart$MaxHR, ylab = 'MaxHR' , xlab='Age', main='Box plot', col = 'red')

6. Use the ggplot library functions to plot the following and explain each figure in (2-3) sentences.

(i) Sclater plot between Age and MaxHR

library(ggplot2)
heart = read.csv('heart.csv')
target_color = as.character(heart$HeartDisease)
ggplot(heart, aes(x = Age, y = MaxHR, color = target_color)) +
  geom_point(size = 2)+
 scale_color_manual(values = c("0" = "green", "1" = "red")) +
guides(color = guide_legend(order = 1),
         size = guide_legend(order = 2),
         shape = guide_legend(order = 3))+
  
  labs(title = "Sclater plot between Age and MaxHR",
       x = "Age",
       y = "MaxHR",
       caption = "Source: Iskulghar") + 
  
  theme(
  
    legend.position = "top", 
    text = element_text(colour = 'black', size = 15),
    axis.text.x = element_text(color = "blue", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

NA
NA

(ii) Sclater plot between Age and Cholesterol

ggplot(heart, aes(x = Age, y = Cholesterol, color = target_color)) +
  geom_point(size = 2)+
  scale_color_manual(values = c("0"="pink","1"= "purple"))+
guides(color = guide_legend(order = 1),
         size = guide_legend(order = 2),
         shape = guide_legend(order = 3))+
  
  labs(title = "Sclater plot between Age and Cholesterol",
       x = "Age",
       y = "Cholesterol",
       caption = "Source: Iskulghar") + 
  
  theme(
  
    legend.position = "top", 
    text = element_text(colour = "blue", size = 15),
    axis.text.x = element_text(color = "black", size = 10),
    axis.text.y = element_text(color = "black", size = 10))

NA

(iii) Sclater plot between Age and RestingBP

Heartdisease= as.character(heart$HeartDisease)
ggplot(heart, aes(x = Age, y = RestingBP, color = Heartdisease)) +
  geom_point(size = 2)+
  scale_color_manual(values = c("0"="cyan3","1"= "darkblue"))+  
guides(color = guide_legend(order = 1),
         size = guide_legend(order = 2),
         shape = guide_legend(order = 2))+
  
  labs(title = "Sclater plot between Age and RestingBP",
       x = "Age",
       y = "RestingBP",
       caption = "Source: Iskulghar") + 

  theme(
  plot.title = element_text(size = 20, color = "darkblue"), 
    legend.position = "top",
  
    text = element_text(colour = 'black', size = 15),
    axis.text.x = element_text(color = "blue", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

NA

(iv) Sclater plot between Age and Oldpeak

ggplot(heart, aes(x = Age, y = Oldpeak, color = Heartdisease)) +
  geom_point(size = 2)+
  
guides(color = guide_legend(order = 1),
         size = guide_legend(order = 2),
         shape = guide_legend(order = 3))+
  
  labs(title = "Sclater plot between Age and Oldpeak",
       x = "Age",
       y = "Oldpeak",
       caption = "Source: Iskulghar") + 
  
  theme(
 plot.title = element_text(size = 20, color = "red"), 
    legend.position = "top", 
    text = element_text(colour = 'black', size = 15),
    axis.text.x = element_text(color = "blue", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

(v) Sclater plot between RestingBP and Cholesterol

ggplot(heart, aes(x = RestingBP, y = Cholesterol, color = Heartdisease)) +
  geom_point(size = 2)+
  scale_color_manual(values = c("0"="darkolivegreen3","1"= "darkolivegreen4"))+  
guides(color = guide_legend(order = 1),
         size = guide_legend(order = 2),
         shape = guide_legend(order = 3))+
  
  labs(title = "Sclater plot between RestingBP and Cholesterol",
       x = "RestingBP",
       y = "Cholesterol",
       caption = "Source: Iskulghar") + 
  
  theme(
  plot.title = element_text(colour = 'darkgreen', size = 20),
    legend.position = "top", 
    text = element_text(colour = 'brown', size = 12),
    axis.text.x = element_text(color = "brown4", size = 10),
    axis.text.y = element_text(color = "brown4", size = 10))

(vi) Sclater plot between RestingBP and MaxHR

ggplot(heart, aes(x = RestingBP, y = MaxHR, color = Heartdisease)) +
  geom_point(size = 2)+
  
guides(color = guide_legend(order = 1),
         size = guide_legend(order = 2),
         shape = guide_legend(order = 3))+
  
  labs(title = "Sclater plot between RestingBP and MaxHR",
       x = "RestingBP",
       y = "MaxHR",
       caption = "Source: Iskulghar") + 
  
  theme(
   plot.title = element_text(colour = 'blue', size = 20),
    legend.position = "top", 
    text = element_text(colour = 'black', size = 15),
    axis.text.x = element_text(color = "red", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

(vii) Sclater plot between RestingBP and Oldpeak

ggplot(heart, aes(x = RestingBP, y =Oldpeak, color = Heartdisease)) +
  geom_point(size = 2)+
  
guides(color = guide_legend(order = 1),
         size = guide_legend(order = 2),
         shape = guide_legend(order = 3))+
  
  labs(title = "Sclater plot between RestingBP and Oldpeak",
       x = "RestingBP",
       y = "Oldpeak",
       caption = "Source: Iskulghar") + 
  
  theme(
  plot.title = element_text(colour = 'blue', size = 20),
    legend.position = "top", 
    text = element_text(colour = 'red', size = 15),
    axis.text.x = element_text(color = "blue", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

(viii) “Sclater plot between Cholesterol and MaxHR

ggplot(heart, aes(x = Cholesterol, y = MaxHR, color = Heartdisease)) +
  geom_point(size = 2)+

  scale_color_manual(values = c("0" = "cadetblue","1" = "darkorange"))+
  labs(title = "Sclater plot between Cholesterol and MaxHR",
       x = "Cholesterol",
       y = "MaxHR",
       caption = "Source: Iskulghar") + 
  
  theme(
  plot.title = element_text(colour = 'black', size = 20),
    legend.position = "top", 
    text = element_text(colour = 'darkblue', size = 15),
    axis.text.x = element_text(color = "red", size = 10),
    axis.text.y = element_text(color = "red", size = 10))

(ix)Sclater plot between Cholesterol and Oldpeak

ggplot(heart, aes(x = Cholesterol, y = Oldpeak, color = Heartdisease)) +
  geom_point(size = 2)+
  
guides(color = guide_legend(order = 1),
         size = guide_legend(order = 2),
         shape = guide_legend(order = 3))+
  
  labs(title = "Sclater plot between Cholesterol and Oldpeak",
       x = "Cholesterol",
       y = "Oldpeak",
       caption = "Source: Iskulghar") + 
  
  theme(
  plot.title = element_text(colour = 'red', size = 20),
    legend.position = "top", 
    text = element_text(colour = 'gray', size = 15),
    axis.text.x = element_text(color = "blue", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

(x)Sclater plot between Oldpeak and MaxHR

ggplot(heart, aes(x =Oldpeak, y = MaxHR, color = Heartdisease)) +
  geom_point(size = 2)+
  
  labs(title = "Sclater plot between Oldpeak and MaxHR",
       x = "Oldpeak",
       y = "MaxHR",
       caption = "Source: Iskulghar") + 
  
  theme(
  plot.title = element_text(colour = 'blue', size = 20),
    legend.position = "top", 
    text = element_text(colour = 'black', size = 15),
    axis.text.x = element_text(color = "blue", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

a. Boxplot of all columns

(i) Box plot of Age

ggplot(data = heart, aes(x = Heartdisease, y=Age)) +  
  geom_boxplot(fill = c("cyan2","darkblue"), alpha = 0.5) +
 
  labs(title = "Box plot of Age",
       x = "HeartDisease",
       y = "Age",
       caption = "Source: Iskulghar") + 
  
  theme(
  
    legend.position = "top", 
    plot.title.position = "panel",
    plot.title = element_text(colour = 'darkblue', size = 20),
    text = element_text(colour = 'blue', size = 15),
    axis.text.x = element_text(color = "black", size = 10),
    axis.text.y = element_text(color = "black", size = 10))

(ii) Box plot of RestingBP

ggplot(data = heart, aes(x = Heartdisease, y=RestingBP)) +  
  geom_boxplot(fill = c("brown2","darkcyan"), alpha = 0.5) +
 
  labs(title = "Box plot of RestingBP",
       x = "HeartDisease",
       y = "RestingBP",
       caption = "Source: Iskulghar") + 
  
  theme(
  plot.title = element_text(colour = 'darkblue', size = 20),
    legend.position = "top", 
    text = element_text(colour = 'black', size = 15),
    axis.text.x = element_text(color = "blue", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

(iii) Box plot of Cholesterol

ggplot(data = heart, aes(x = Heartdisease, y=Cholesterol)) +  
  geom_boxplot(fill = c("green","red"), alpha = 0.5) +
 
  labs(title = "Box plot of Cholesterol",
       x = "HeartDisease",
       y = "Cholesterol",
       caption = "Source: Iskulghar") + 
  
  theme(
  
    legend.position = "top", 
    text = element_text(colour = 'black', size = 15),
    axis.text.x = element_text(color = "blue", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

(iv) Box plot of MaxHR

ggplot(data = heart, aes(x = Heartdisease, y=MaxHR)) +  
  geom_boxplot(fill = c("red","blue"), alpha = 0.5) +
 
  labs(title = "Box plot of MaxHR",
       x = "HeartDisease",
       y = "MaxHR",
       caption = "Source: Iskulghar") + 
  theme(
  
    legend.position = "top", 
    text = element_text(colour = 'black', size = 15),
    axis.text.x = element_text(color = "blue", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

(v) Box plot of Oldpeak

ggplot(data = heart, aes(x = Heartdisease, y=Cholesterol)) +  
  geom_boxplot(fill = c("darkorange2","blue"), alpha = 0.5) +
 
  labs(title = "Box plot of Oldpeak",
       x = "HeartDisease",
       y = "Oldpeak",
       caption = "Source: Iskulghar") + 
  
  theme(
  
    legend.position = "top", 
    plot.title = element_text(colour = 'darkblue', size = 15),
    text = element_text(colour = 'black', size = 15),
    axis.text.x = element_text(color = "blue", size = 10),
    axis.text.y = element_text(color = "blue", size = 10))

Project Part - 2

a. Interactive violin plot of all features

library(plotly)

plot_ly(heart, x= Heartdisease, y = ~Age, type = 'violin')
plot_ly(heart, x= Heartdisease, y = ~RestingBP, type = 'violin')
plot_ly(heart, x= Heartdisease, y = ~Cholesterol, type = 'violin')
plot_ly(heart, x= Heartdisease, y = ~MaxHR, type = 'violin')
plot_ly(heart, x= Heartdisease, y = ~Oldpeak, type = 'violin')

b.Interactive boxplot of all features

plot_ly(heart, x= Heartdisease, y = ~Age, type = 'box')
plot_ly(heart, x= Heartdisease, y = ~RestingBP, type = 'box')
plot_ly(heart, x= Heartdisease, y = ~Cholesterol, type = 'box')
plot_ly(heart, x= Heartdisease, y = ~MaxHR, type = 'box')
plot_ly(heart, x= Heartdisease, y = ~Oldpeak, type = 'box')

c. Calculate correlation matrix and print the matrix. Explain strong and weak correlation

cor_matrix = cor(numeric_columns[ ,1:5])
cor_matrix
                    Age  RestingBP Cholesterol      MaxHR     Oldpeak
Age          1.00000000  0.2543994 -0.09528177 -0.3820447  0.25861154
RestingBP    0.25439936  1.0000000  0.10089294 -0.1121350  0.16480304
Cholesterol -0.09528177  0.1008929  1.00000000  0.2357924  0.05014811
MaxHR       -0.38204468 -0.1121350  0.23579240  1.0000000 -0.16069055
Oldpeak      0.25861154  0.1648030  0.05014811 -0.1606906  1.00000000
# strong correlation  is 0.258 which is between Age and Oldpeak. Weak correlation is -0.382 which is between Age and MaxHR.

d.Plot correlation matrix (lower triangle) with values

library(ggcorrplot)
ggcorrplot(cor_matrix, 
           type = "lower",
           colors = c("red", "white", "blue"),
           lab = TRUE)

e. Pair plot of all feature

library(GGally)
ggpairs(numeric_columns, aes(colour = Heartdisease))

f. Apply principal component analysis (PCA) and explain the PCAs

library(stats)

heart_pca = prcomp(numeric_columns, scale = TRUE, center = TRUE)
heart_pca
Standard deviations (1, .., p=5):
[1] 1.3065648 1.0926990 0.9117941 0.8314805 0.7590579

Rotation (n x k) = (5 x 5):
                   PC1         PC2         PC3        PC4        PC5
Age          0.6026536 0.009353273 -0.07505093  0.3172132  0.7283298
RestingBP    0.3742414 0.474166841 -0.64215210 -0.4299469 -0.1946676
Cholesterol -0.1779956 0.743454901  0.06375770  0.6283270 -0.1293543
MaxHR       -0.5391946 0.343937374  0.03735596 -0.4329406  0.6341477
Oldpeak      0.4175389 0.322583657  0.75930727 -0.3637157 -0.1129796
summary(heart_pca)
Importance of components:
                          PC1    PC2    PC3    PC4    PC5
Standard deviation     1.3066 1.0927 0.9118 0.8315 0.7591
Proportion of Variance 0.3414 0.2388 0.1663 0.1383 0.1152
Cumulative Proportion  0.3414 0.5802 0.7465 0.8848 1.0000
pca_12 = as.data.frame(heart_pca$x[ , 1:2])
pca_12_class = cbind(pca_12, Heartdisease = Heartdisease)
pca_12_class

i. Bar plot of PCAs (Percentage of explained variance vs PCs)

library(factoextra)
fviz_eig(heart_pca, addlabels = TRUE)

ii. Contribution plot of PCs (Circular plot)

fviz_pca_var(heart_pca,
             col.var = "contrib")

iii. Contribution plot as Heatmap


ggcorrplot(cor_matrix, 
           type = "lower",
           colors = c("purple", "white", "red"),
           lab = TRUE)

library("corrplot")
var = get_pca_var(heart_pca)
corrplot(var$cos2)

iv. Cluster plot after PCA

fviz_pca_ind(heart_pca,
             geom.ind = "point",
             col.ind = Heartdisease,
             addEllipses = TRUE)

g.Use SVM to train a model to classify the target variable. Explain the results

i. Plot the confusion matrix

library(lattice)
library(e1071)
library(caret)
heart = read.csv('heart.csv')
heart_data = heart[ ,c(1,4,5,8,10,12)]
train_ix = createDataPartition(heart$HeartDisease, p = 0.8, list = FALSE)
train_data = heart_data[train_ix, ]
test_data = heart_data[-train_ix, ]
train_data
test_data
svm_model = svm(HeartDisease ~ Age+RestingBP+Cholesterol+MaxHR+Oldpeak, data = train_data, kernel = "linear")
test_data[12, ]
NA
predict(svm_model, newdata = test_data[5, ])
        48 
0.07287127 
predictions = predict(svm_model, newdata = test_data)

2. Using regression dataset called “US Admission” (US Admission.csv).Remove the “Serial No” column from the dataset

US_Admission = read.csv('US Admission.csv')
US_Admission
Admission = US_Admission[ ,-1]
Admission
lm_model = lm(Chance.of.Admit ~ GRE.Score, data = Admission)
summary(lm_model)

Call:
lm(formula = Chance.of.Admit ~ GRE.Score, data = Admission)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.33613 -0.04604  0.00408  0.05644  0.18339 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -2.4360842  0.1178141  -20.68   <2e-16 ***
GRE.Score    0.0099759  0.0003716   26.84   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.08517 on 398 degrees of freedom
Multiple R-squared:  0.6442,    Adjusted R-squared:  0.6433 
F-statistic: 720.6 on 1 and 398 DF,  p-value: < 2.2e-16
library(datasets)


x = US_Admission$Chance.of.Admit
y = US_Admission$CGPA

pred = predict(ln_model)
ix = sort(x, index.return = T)

plot(x, y)

lines(x[ix], pred[ix])
Error in x[ix] : invalid subscript type 'list'
library(ggplot2)
library(GGally)
data(Admission)
Warning: data set ‘Admission’ not found
ggpairs(Admission, aes(colour = Admission$Chance.of.Admit))
Error in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm,  : 
  `mapping` color column must be categorical, not numeric

a. Pair plot of all features

b. Plot linear regression with each feature. For example: y = GRE Score, x = Chance of Admit. Do this for all different features (only y will change). Explain the result.

(i) Plot of Linear Regression with “chanche of admit” and “GRE.Score”.

ggplot(Admission, aes(x = Chance.of.Admit, y = GRE.Score, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", level = 0.90)

(ii) Plot of Linear Regression with “chanche of admit” and “TOEFL Score”.

ggplot(Admission, aes(x = Chance.of.Admit, y = TOEFL.Score, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", level = 0.95)

(iii) Plot of Linear Regression with “chanche of admit” and “University Rating”.

ggplot(Admission, aes(x = Chance.of.Admit, y = University.Rating, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", level = 0.95)

(iv) Plot of Linear Regression with “chanche of admit” and “SOP”.

ggplot(Admission, aes(x = Chance.of.Admit, y = SOP, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", level = 0.95)

(v) Plot of Linear Regression with “chanche of admit” and “LOR”.

ggplot(Admission, aes(x = Chance.of.Admit, y = LOR, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", level = 0.90)

(vi) Plot of Linear Regression with “chanche of admit” and “CGPA”.

ggplot(Admission, aes(x = Chance.of.Admit, y = CGPA, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", level = 0.95)

  1. Plot of Linear Regression with “chanche of admit” and “Research”.
ggplot(Admission, aes(x = Chance.of.Admit, y = Research, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", level = 0.95)

c. Plot polynomial regression of power 2 with each feature. For example: y = Chance of Admit, x = Chance of Admit. Do this for all different features (only y will change). Explain the result.

(i) Polynomial Plot of Linear Regression with “chanche of admit” and “GRE.Score”.

ggplot(Admission, aes(x = Chance.of.Admit, y = GRE.Score, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", formula = y~poly(x, 2),level = 0.90)

(ii) Polynomial Plot of Linear Regression with “chanche of admit” and “TOEFL Score”.

ggplot(Admission, aes(x = Chance.of.Admit, y = TOEFL.Score, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm",formula = y~poly(x, 2), level = 0.95)

(iii) Polynomial Plot of Linear Regression with “chanche of admit” and “University Rating”.

(iv) Polynomial Plot of Linear Regression with “chanche of admit” and “SOP”.

(v) Polynomial Plot of Linear Regression with “chanche of admit” and “LOR”.

ggplot(Admission, aes(x = Chance.of.Admit, y = LOR, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", formula = y~poly(x, 2),level = 0.90)

(vi) Polynomial Plot of Linear Regression with “chanche of admit” and “CGPA”.

ggplot(Admission, aes(x = Chance.of.Admit, y = CGPA, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", formula = y~poly(x, 2),level = 0.95)

(vii) Polynomial Plot of Linear Regression with “chanche of admit” and “Research”.

ggplot(Admission, aes(x = Chance.of.Admit, y = Research, color = Chance.of.Admit)) + 
  geom_point() +
  geom_smooth(method = "lm", formula = y~poly(x, 2),level = 0.95)

d. Use all features together to create a regression model and explain the result. For example: lm(y ~ x1+x2+x3….+xn, data = US_Admission), here x represents a single feature and y represents the target variable.

lm_model_all = lm(Chance.of.Admit ~ GRE.Score+TOEFL.Score+ University.Rating+ SOP+LOR+CGPA+Research, data = Admission)
summary(lm_model)

Call:
lm(formula = Chance.of.Admit ~ GRE.Score, data = Admission)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.33613 -0.04604  0.00408  0.05644  0.18339 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -2.4360842  0.1178141  -20.68   <2e-16 ***
GRE.Score    0.0099759  0.0003716   26.84   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.08517 on 398 degrees of freedom
Multiple R-squared:  0.6442,    Adjusted R-squared:  0.6433 
F-statistic: 720.6 on 1 and 398 DF,  p-value: < 2.2e-16
LS0tDQp0aXRsZTogIkRhdGEgU2NpZW5jZSBQcm9qZWN0Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMgTmFtZSA6IE1zdCBOaWdhciBTdWx0YW5hDQojIyMgRW1haSA6IG5pZ2FyLm1hdGguZHVAZ21haWwuY29tDQoNCg0KDQojIFBhcnQgMSA6DQojIyMgMikgTG9hZGluZyBkYXRhc2V0IDoNCmBgYHtyfQ0KaGVhcnQgPSByZWFkLmNzdignaGVhcnQuY3N2JykNCmhlYXJ0DQpgYGANCg0KIyMjIDMpIEZldyBzZW50ZW5jZXMgdG8gZXhwbGFpbiB0aGUgZGF0YXNldCA6YSlJZGVudGlmeSBudW1lcmljYWwgY29sdW1ucy4gYilJZGVudGlmeSBjYXRlZ29yaWNhbCBjb2x1bW5zLmMpSWRlbnRpZnkgdGFyZ2V0IHZhcmlhYmxlIChub3JtYWxseSB0aGUgbGFzdCBjb2x1bW4gaXMgdGhlIHRhcmdldCB2YXJpYWJsZSkNCmBgYHtyfQ0KcHJpbnQoIlRoZSBkYXRhc2V0IGNvbnRhaW5zIGluZm9ybWF0aW9uIG9uIDkxOCBpbmRpdmlkdWFscyB3aXRoIDEyIHZhcmlhYmxlcywgaW5jbHVkaW5nIEFnZSwgU2V4LCBDaGVzdFBhaW5UeXBlLCBSZXN0aW5nQlAsIENob2xlc3Rlcm9sLCBGYXN0aW5nQlMsIFJlc3RpbmdFQ0csIE1heEhSLCBFeGVyY2lzZUFuZ2luYSwgT2xkcGVhaywgU1RfU2xvcGUsIGFuZCBIZWFydERpc2Vhc2UuIFRoZSBpbmRpdmlkdWFscycgYWdlcyByYW5nZSBmcm9tIDI4IHRvIDc3IHllYXJzLiBUaGVyZSBhcmUgNSBudW1lcmljYWwgZmVhdHVyZXMgKEFnZXMsIFJlc3RpbmdCUCwgQ2hvbGVzdGVyb2wsIE1heEhSLCBhbmQgT2xkcGVhayApLCB3aGlsZSBvdGhlcnMgYXJlIGNhdGVnb3JpY2FsIChTZXgsIENoZXN0UGFpblR5cGUsIEZhc3RpbmdCUyxSZXN0aW5nRUNHLEV4ZXJjaXNlQW5naW5hLFNUX1Nsb3BlLEhlYXJ0RGlzZWFzZSkuIFRoZSBsYXN0IGNvbHVtbiAnSGVhcnREaXNlYXNlJyBpcyB0aGUgdGFyZ2V0IHZhcmlhYmxlIC5UaGUgZGF0YXNldCBwcm92aWRlcyBhIGNvbXByZWhlbnNpdmUgb3ZlcnZpZXcgb2YgdmFyaW91cyBoZWFsdGgtcmVsYXRlZCBhdHRyaWJ1dGVzIGZvciB0aGUgaW5kaXZpZHVhbHMgc3R1ZGllZC4iKQ0KYGBgDQpgYGB7cn0NCm51bWVyaWNfY29sdW1ucyA9IGhlYXJ0WyAsYygxLDQsNSw4LDEwKV0NCm51bWVyaWNfY29sdW1ucw0KYGBgDQpgYGB7cn0NCmNhdGVnb3JpY2FsX2NvbHVtbnMgPSBoZWFydFsgLGMoMiwzLDYsNyw5LDExLDEyKV0NCmNhdGVnb3JpY2FsX2NvbHVtbnMNCmBgYA0KYGBge3J9DQp0YXJnZXRfdmFyaWFibGUgPSBoZWFydFsgLDEyXQ0KdGFyZ2V0X3ZhcmlhYmxlDQpgYGANCiMjIDQuCVJlbW92ZSBhbGwgdGhlIGNhdGVnb3JpY2FsIGNvbHVtbnMgKG5vdCB0aGUgdGFyZ2V0IGNvbHVtbikgZnJvbSB0aGUgZGF0YXNldC4gTm93IHdlIHdpbGwgY2FsbCBhbGwgdGhlIG51bWVyaWNhbCBjb2x1bW5zIGFzIGZlYXR1cmVzIGFuZCB0aGUgbGFzdCBjb2x1bW4gYXMgdGFyZ2V0IG9yIGNsYXNzLg0KDQpgYGB7cn0NCkV4YW1pbmVfZGF0YSA9IGhlYXJ0WyAsYygtMiwtMywtNiwtNywtOSwtMTEpXQ0KRXhhbWluZV9kYXRhDQp0YXJnZXQgPSBoZWFydCRIZWFydERpc2Vhc2UNCnRhcmdldA0KDQpgYGANCg0KDQoNCg0KIyMgNS5TY2F0dGVyIHBsb3Qgb2YgYW55IHR3byBmZWF0dXJlcyAtIGVhY2ggY2xhc3MgKHRhcmdldCkgc2hvdWxkIGJlIHJlcHJlc2VudGVkIHdpdGggZGlmZmVyZW50IGNvbG9ycy4NCg0KYGBge3J9DQp0YXJnZXRfY29sb3IgPSBhcy5udW1lcmljKGZhY3RvcihoZWFydCRIZWFydERpc2Vhc2UpKQ0KcGxvdChoZWFydCRBZ2UsaGVhcnQkQ2hvbGVzdGVyb2wsDQogICAgIA0KICAgIGNvbCA9IHRhcmdldF9jb2xvciwNCiAgICAgcGNoID0gMiwNCiAgICAgY2V4ID0gMC41LA0KICAgICB4bGltID0gYygyMCw4MCksDQogICAgIHlsaW0gPSBjKDEsIDUwMCksDQogICAgIHhsYWIgPSAiQWdlIiAsDQogICAgIHlsYWIgPSAiQ2hvbGVzdGVyb2wiLA0KICAgICBtYWluID0gIlZpc3VhbGl6YXRpb24gb2YgQWdlIGFuZCBDaG9sZXN0ZXJvbCIsDQogICAgIGNvbC5tYWluID0gJ2JsdWUnLA0KICAgICBjb2wuYXhpcyA9ICdibGFjaycsDQogICAgIGNvbC5sYWIgPSAncmVkJywNCiAgICAgY2V4Lm1haW4gPSAxLjUsDQogICAgIGNleC5heGlzID0gMSwNCiAgICAgY2V4LmxhYiA9IDEsDQogICAgKQ0KYGBgDQojIyBhLglIaXN0b2dyYW0gcGxvdCBvZiBhbnkgc2luZ2xlIGZlYXR1cmUuDQpgYGB7cn0NCmhpc3QoaGVhcnQkTWF4SFIsIG1haW4gPSAiSGlzdG9ncmFtIHBsb3QiLCB4bGFiID0gIk1heEhSIiwgY29sID0gImJsdWUiKQ0KYGBgDQojIyBiLglCb3hwbG90IG9mIGFueSBzaW5nbGUgZmVhdHVyZQ0KYGBge3J9DQpib3hwbG90KGhlYXJ0JE1heEhSLCB5bGFiID0gJ01heEhSJyAsIHhsYWI9J0FnZScsIG1haW49J0JveCBwbG90JywgY29sID0gJ3JlZCcpDQpgYGANCg0KIyMgNi4JVXNlIHRoZSBnZ3Bsb3QgbGlicmFyeSBmdW5jdGlvbnMgdG8gcGxvdCB0aGUgZm9sbG93aW5nIGFuZCBleHBsYWluIGVhY2ggZmlndXJlIGluICgyLTMpIHNlbnRlbmNlcy4NCiMjIyAoaSkgU2NsYXRlciBwbG90IGJldHdlZW4gQWdlIGFuZCBNYXhIUg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpoZWFydCA9IHJlYWQuY3N2KCdoZWFydC5jc3YnKQ0KdGFyZ2V0X2NvbG9yID0gYXMuY2hhcmFjdGVyKGhlYXJ0JEhlYXJ0RGlzZWFzZSkNCmdncGxvdChoZWFydCwgYWVzKHggPSBBZ2UsIHkgPSBNYXhIUiwgY29sb3IgPSB0YXJnZXRfY29sb3IpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDIpKw0KIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIwIiA9ICJncmVlbiIsICIxIiA9ICJyZWQiKSkgKw0KZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG9yZGVyID0gMSksDQogICAgICAgICBzaXplID0gZ3VpZGVfbGVnZW5kKG9yZGVyID0gMiksDQogICAgICAgICBzaGFwZSA9IGd1aWRlX2xlZ2VuZChvcmRlciA9IDMpKSsNCiAgDQogIGxhYnModGl0bGUgPSAiU2NsYXRlciBwbG90IGJldHdlZW4gQWdlIGFuZCBNYXhIUiIsDQogICAgICAgeCA9ICJBZ2UiLA0KICAgICAgIHkgPSAiTWF4SFIiLA0KICAgICAgIGNhcHRpb24gPSAiU291cmNlOiBJc2t1bGdoYXIiKSArIA0KICANCiAgdGhlbWUoDQogIA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLCANCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICdibGFjaycsIHNpemUgPSAxNSksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxMCksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxMCkpDQogIA0KDQpgYGANCg0KIyMjIChpaSkgU2NsYXRlciBwbG90IGJldHdlZW4gQWdlIGFuZCBDaG9sZXN0ZXJvbA0KYGBge3J9DQpnZ3Bsb3QoaGVhcnQsIGFlcyh4ID0gQWdlLCB5ID0gQ2hvbGVzdGVyb2wsIGNvbG9yID0gdGFyZ2V0X2NvbG9yKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAyKSsNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIjAiPSJwaW5rIiwiMSI9ICJwdXJwbGUiKSkrDQpndWlkZXMoY29sb3IgPSBndWlkZV9sZWdlbmQob3JkZXIgPSAxKSwNCiAgICAgICAgIHNpemUgPSBndWlkZV9sZWdlbmQob3JkZXIgPSAyKSwNCiAgICAgICAgIHNoYXBlID0gZ3VpZGVfbGVnZW5kKG9yZGVyID0gMykpKw0KICANCiAgbGFicyh0aXRsZSA9ICJTY2xhdGVyIHBsb3QgYmV0d2VlbiBBZ2UgYW5kIENob2xlc3Rlcm9sIiwNCiAgICAgICB4ID0gIkFnZSIsDQogICAgICAgeSA9ICJDaG9sZXN0ZXJvbCIsDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IElza3VsZ2hhciIpICsgDQogIA0KICB0aGVtZSgNCiAgDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImJsdWUiLCBzaXplID0gMTUpLA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxMCkpDQogIA0KYGBgDQoNCiMjIyAoaWlpKSBTY2xhdGVyIHBsb3QgYmV0d2VlbiBBZ2UgYW5kIFJlc3RpbmdCUA0KYGBge3J9DQpIZWFydGRpc2Vhc2U9IGFzLmNoYXJhY3RlcihoZWFydCRIZWFydERpc2Vhc2UpDQpnZ3Bsb3QoaGVhcnQsIGFlcyh4ID0gQWdlLCB5ID0gUmVzdGluZ0JQLCBjb2xvciA9IEhlYXJ0ZGlzZWFzZSkpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMikrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIwIj0iY3lhbjMiLCIxIj0gImRhcmtibHVlIikpKyAgDQpndWlkZXMoY29sb3IgPSBndWlkZV9sZWdlbmQob3JkZXIgPSAxKSwNCiAgICAgICAgIHNpemUgPSBndWlkZV9sZWdlbmQob3JkZXIgPSAyKSwNCiAgICAgICAgIHNoYXBlID0gZ3VpZGVfbGVnZW5kKG9yZGVyID0gMikpKw0KICANCiAgbGFicyh0aXRsZSA9ICJTY2xhdGVyIHBsb3QgYmV0d2VlbiBBZ2UgYW5kIFJlc3RpbmdCUCIsDQogICAgICAgeCA9ICJBZ2UiLA0KICAgICAgIHkgPSAiUmVzdGluZ0JQIiwNCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogSXNrdWxnaGFyIikgKyANCg0KICB0aGVtZSgNCiAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGNvbG9yID0gImRhcmtibHVlIiksIA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLA0KICANCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICdibGFjaycsIHNpemUgPSAxNSksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxMCksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxMCkpDQogIA0KYGBgDQoNCg0KIyMjIChpdikgU2NsYXRlciBwbG90IGJldHdlZW4gQWdlIGFuZCBPbGRwZWFrDQpgYGB7cn0NCmdncGxvdChoZWFydCwgYWVzKHggPSBBZ2UsIHkgPSBPbGRwZWFrLCBjb2xvciA9IEhlYXJ0ZGlzZWFzZSkpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMikrDQogIA0KZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG9yZGVyID0gMSksDQogICAgICAgICBzaXplID0gZ3VpZGVfbGVnZW5kKG9yZGVyID0gMiksDQogICAgICAgICBzaGFwZSA9IGd1aWRlX2xlZ2VuZChvcmRlciA9IDMpKSsNCiAgDQogIGxhYnModGl0bGUgPSAiU2NsYXRlciBwbG90IGJldHdlZW4gQWdlIGFuZCBPbGRwZWFrIiwNCiAgICAgICB4ID0gIkFnZSIsDQogICAgICAgeSA9ICJPbGRwZWFrIiwNCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogSXNrdWxnaGFyIikgKyANCiAgDQogIHRoZW1lKA0KIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBjb2xvciA9ICJyZWQiKSwgDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2JsYWNrJywgc2l6ZSA9IDE1KSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSkNCmBgYA0KDQojIyMgKHYpIFNjbGF0ZXIgcGxvdCBiZXR3ZWVuIFJlc3RpbmdCUCBhbmQgQ2hvbGVzdGVyb2wNCmBgYHtyfQ0KZ2dwbG90KGhlYXJ0LCBhZXMoeCA9IFJlc3RpbmdCUCwgeSA9IENob2xlc3Rlcm9sLCBjb2xvciA9IEhlYXJ0ZGlzZWFzZSkpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMikrDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIwIj0iZGFya29saXZlZ3JlZW4zIiwiMSI9ICJkYXJrb2xpdmVncmVlbjQiKSkrICANCmd1aWRlcyhjb2xvciA9IGd1aWRlX2xlZ2VuZChvcmRlciA9IDEpLA0KICAgICAgICAgc2l6ZSA9IGd1aWRlX2xlZ2VuZChvcmRlciA9IDIpLA0KICAgICAgICAgc2hhcGUgPSBndWlkZV9sZWdlbmQob3JkZXIgPSAzKSkrDQogIA0KICBsYWJzKHRpdGxlID0gIlNjbGF0ZXIgcGxvdCBiZXR3ZWVuIFJlc3RpbmdCUCBhbmQgQ2hvbGVzdGVyb2wiLA0KICAgICAgIHggPSAiUmVzdGluZ0JQIiwNCiAgICAgICB5ID0gIkNob2xlc3Rlcm9sIiwNCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogSXNrdWxnaGFyIikgKyANCiAgDQogIHRoZW1lKA0KICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICdkYXJrZ3JlZW4nLCBzaXplID0gMjApLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLCANCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICdicm93bicsIHNpemUgPSAxMiksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYnJvd240Iiwgc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJicm93bjQiLCBzaXplID0gMTApKQ0KYGBgDQoNCg0KIyMjICh2aSkgU2NsYXRlciBwbG90IGJldHdlZW4gUmVzdGluZ0JQIGFuZCBNYXhIUg0KDQpgYGB7cn0NCmdncGxvdChoZWFydCwgYWVzKHggPSBSZXN0aW5nQlAsIHkgPSBNYXhIUiwgY29sb3IgPSBIZWFydGRpc2Vhc2UpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDIpKw0KICANCmd1aWRlcyhjb2xvciA9IGd1aWRlX2xlZ2VuZChvcmRlciA9IDEpLA0KICAgICAgICAgc2l6ZSA9IGd1aWRlX2xlZ2VuZChvcmRlciA9IDIpLA0KICAgICAgICAgc2hhcGUgPSBndWlkZV9sZWdlbmQob3JkZXIgPSAzKSkrDQogIA0KICBsYWJzKHRpdGxlID0gIlNjbGF0ZXIgcGxvdCBiZXR3ZWVuIFJlc3RpbmdCUCBhbmQgTWF4SFIiLA0KICAgICAgIHggPSAiUmVzdGluZ0JQIiwNCiAgICAgICB5ID0gIk1heEhSIiwNCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogSXNrdWxnaGFyIikgKyANCiAgDQogIHRoZW1lKA0KICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAnYmx1ZScsIHNpemUgPSAyMCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2JsYWNrJywgc2l6ZSA9IDE1KSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJyZWQiLCBzaXplID0gMTApLA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsdWUiLCBzaXplID0gMTApKQ0KYGBgDQojIyMgKHZpaSkgU2NsYXRlciBwbG90IGJldHdlZW4gUmVzdGluZ0JQIGFuZCBPbGRwZWFrDQoNCmBgYHtyfQ0KZ2dwbG90KGhlYXJ0LCBhZXMoeCA9IFJlc3RpbmdCUCwgeSA9T2xkcGVhaywgY29sb3IgPSBIZWFydGRpc2Vhc2UpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDIpKw0KICANCmd1aWRlcyhjb2xvciA9IGd1aWRlX2xlZ2VuZChvcmRlciA9IDEpLA0KICAgICAgICAgc2l6ZSA9IGd1aWRlX2xlZ2VuZChvcmRlciA9IDIpLA0KICAgICAgICAgc2hhcGUgPSBndWlkZV9sZWdlbmQob3JkZXIgPSAzKSkrDQogIA0KICBsYWJzKHRpdGxlID0gIlNjbGF0ZXIgcGxvdCBiZXR3ZWVuIFJlc3RpbmdCUCBhbmQgT2xkcGVhayIsDQogICAgICAgeCA9ICJSZXN0aW5nQlAiLA0KICAgICAgIHkgPSAiT2xkcGVhayIsDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IElza3VsZ2hhciIpICsgDQogIA0KICB0aGVtZSgNCiAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAnYmx1ZScsIHNpemUgPSAyMCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ3JlZCcsIHNpemUgPSAxNSksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxMCksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxMCkpDQpgYGANCiMjIyAodmlpaSkgIlNjbGF0ZXIgcGxvdCBiZXR3ZWVuIENob2xlc3Rlcm9sIGFuZCBNYXhIUg0KDQpgYGB7cn0NCmdncGxvdChoZWFydCwgYWVzKHggPSBDaG9sZXN0ZXJvbCwgeSA9IE1heEhSLCBjb2xvciA9IEhlYXJ0ZGlzZWFzZSkpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMikrDQoNCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIjAiID0gImNhZGV0Ymx1ZSIsIjEiID0gImRhcmtvcmFuZ2UiKSkrDQogIGxhYnModGl0bGUgPSAiU2NsYXRlciBwbG90IGJldHdlZW4gQ2hvbGVzdGVyb2wgYW5kIE1heEhSIiwNCiAgICAgICB4ID0gIkNob2xlc3Rlcm9sIiwNCiAgICAgICB5ID0gIk1heEhSIiwNCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogSXNrdWxnaGFyIikgKyANCiAgDQogIHRoZW1lKA0KICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICdibGFjaycsIHNpemUgPSAyMCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2RhcmtibHVlJywgc2l6ZSA9IDE1KSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJyZWQiLCBzaXplID0gMTApLA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gInJlZCIsIHNpemUgPSAxMCkpDQpgYGANCg0KIyMjIChpeClTY2xhdGVyIHBsb3QgYmV0d2VlbiBDaG9sZXN0ZXJvbCBhbmQgT2xkcGVhaw0KYGBge3J9DQpnZ3Bsb3QoaGVhcnQsIGFlcyh4ID0gQ2hvbGVzdGVyb2wsIHkgPSBPbGRwZWFrLCBjb2xvciA9IEhlYXJ0ZGlzZWFzZSkpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMikrDQogIA0KZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG9yZGVyID0gMSksDQogICAgICAgICBzaXplID0gZ3VpZGVfbGVnZW5kKG9yZGVyID0gMiksDQogICAgICAgICBzaGFwZSA9IGd1aWRlX2xlZ2VuZChvcmRlciA9IDMpKSsNCiAgDQogIGxhYnModGl0bGUgPSAiU2NsYXRlciBwbG90IGJldHdlZW4gQ2hvbGVzdGVyb2wgYW5kIE9sZHBlYWsiLA0KICAgICAgIHggPSAiQ2hvbGVzdGVyb2wiLA0KICAgICAgIHkgPSAiT2xkcGVhayIsDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IElza3VsZ2hhciIpICsgDQogIA0KICB0aGVtZSgNCiAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAncmVkJywgc2l6ZSA9IDIwKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgDQogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAnZ3JheScsIHNpemUgPSAxNSksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxMCksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxMCkpDQpgYGANCiMjIyAoeClTY2xhdGVyIHBsb3QgYmV0d2VlbiBPbGRwZWFrIGFuZCBNYXhIUg0KYGBge3J9DQpnZ3Bsb3QoaGVhcnQsIGFlcyh4ID1PbGRwZWFrLCB5ID0gTWF4SFIsIGNvbG9yID0gSGVhcnRkaXNlYXNlKSkgKw0KICBnZW9tX3BvaW50KHNpemUgPSAyKSsNCiAgDQogIGxhYnModGl0bGUgPSAiU2NsYXRlciBwbG90IGJldHdlZW4gT2xkcGVhayBhbmQgTWF4SFIiLA0KICAgICAgIHggPSAiT2xkcGVhayIsDQogICAgICAgeSA9ICJNYXhIUiIsDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IElza3VsZ2hhciIpICsgDQogIA0KICB0aGVtZSgNCiAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAnYmx1ZScsIHNpemUgPSAyMCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2JsYWNrJywgc2l6ZSA9IDE1KSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSkNCmBgYA0KDQoNCiMjIGEuCUJveHBsb3Qgb2YgYWxsIGNvbHVtbnMgDQoNCiMjIyAoaSkgQm94IHBsb3Qgb2YgQWdlDQpgYGB7cn0NCmdncGxvdChkYXRhID0gaGVhcnQsIGFlcyh4ID0gSGVhcnRkaXNlYXNlLCB5PUFnZSkpICsgIA0KICBnZW9tX2JveHBsb3QoZmlsbCA9IGMoImN5YW4yIiwiZGFya2JsdWUiKSwgYWxwaGEgPSAwLjUpICsNCiANCiAgbGFicyh0aXRsZSA9ICJCb3ggcGxvdCBvZiBBZ2UiLA0KICAgICAgIHggPSAiSGVhcnREaXNlYXNlIiwNCiAgICAgICB5ID0gIkFnZSIsDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IElza3VsZ2hhciIpICsgDQogIA0KICB0aGVtZSgNCiAgDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIA0KICAgIHBsb3QudGl0bGUucG9zaXRpb24gPSAicGFuZWwiLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2RhcmtibHVlJywgc2l6ZSA9IDIwKSwNCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICdibHVlJywgc2l6ZSA9IDE1KSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIsIHNpemUgPSAxMCksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMTApKQ0KYGBgDQojIyMgKGlpKSBCb3ggcGxvdCBvZiBSZXN0aW5nQlANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGhlYXJ0LCBhZXMoeCA9IEhlYXJ0ZGlzZWFzZSwgeT1SZXN0aW5nQlApKSArICANCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSBjKCJicm93bjIiLCJkYXJrY3lhbiIpLCBhbHBoYSA9IDAuNSkgKw0KIA0KICBsYWJzKHRpdGxlID0gIkJveCBwbG90IG9mIFJlc3RpbmdCUCIsDQogICAgICAgeCA9ICJIZWFydERpc2Vhc2UiLA0KICAgICAgIHkgPSAiUmVzdGluZ0JQIiwNCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogSXNrdWxnaGFyIikgKyANCiAgDQogIHRoZW1lKA0KICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICdkYXJrYmx1ZScsIHNpemUgPSAyMCksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2JsYWNrJywgc2l6ZSA9IDE1KSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSkNCmBgYA0KIyMjIChpaWkpIEJveCBwbG90IG9mIENob2xlc3Rlcm9sDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBoZWFydCwgYWVzKHggPSBIZWFydGRpc2Vhc2UsIHk9Q2hvbGVzdGVyb2wpKSArICANCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSBjKCJncmVlbiIsInJlZCIpLCBhbHBoYSA9IDAuNSkgKw0KIA0KICBsYWJzKHRpdGxlID0gIkJveCBwbG90IG9mIENob2xlc3Rlcm9sIiwNCiAgICAgICB4ID0gIkhlYXJ0RGlzZWFzZSIsDQogICAgICAgeSA9ICJDaG9sZXN0ZXJvbCIsDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IElza3VsZ2hhciIpICsgDQogIA0KICB0aGVtZSgNCiAgDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2JsYWNrJywgc2l6ZSA9IDE1KSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSkNCg0KYGBgDQojIyMgKGl2KSBCb3ggcGxvdCBvZiBNYXhIUg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGhlYXJ0LCBhZXMoeCA9IEhlYXJ0ZGlzZWFzZSwgeT1NYXhIUikpICsgIA0KICBnZW9tX2JveHBsb3QoZmlsbCA9IGMoInJlZCIsImJsdWUiKSwgYWxwaGEgPSAwLjUpICsNCiANCiAgbGFicyh0aXRsZSA9ICJCb3ggcGxvdCBvZiBNYXhIUiIsDQogICAgICAgeCA9ICJIZWFydERpc2Vhc2UiLA0KICAgICAgIHkgPSAiTWF4SFIiLA0KICAgICAgIGNhcHRpb24gPSAiU291cmNlOiBJc2t1bGdoYXIiKSArIA0KICB0aGVtZSgNCiAgDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2JsYWNrJywgc2l6ZSA9IDE1KSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSkNCmBgYA0KIyMjICh2KSBCb3ggcGxvdCBvZiBPbGRwZWFrDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBoZWFydCwgYWVzKHggPSBIZWFydGRpc2Vhc2UsIHk9Q2hvbGVzdGVyb2wpKSArICANCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSBjKCJkYXJrb3JhbmdlMiIsImJsdWUiKSwgYWxwaGEgPSAwLjUpICsNCiANCiAgbGFicyh0aXRsZSA9ICJCb3ggcGxvdCBvZiBPbGRwZWFrIiwNCiAgICAgICB4ID0gIkhlYXJ0RGlzZWFzZSIsDQogICAgICAgeSA9ICJPbGRwZWFrIiwNCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogSXNrdWxnaGFyIikgKyANCiAgDQogIHRoZW1lKA0KICANCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAnZGFya2JsdWUnLCBzaXplID0gMTUpLA0KICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gJ2JsYWNrJywgc2l6ZSA9IDE1KSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSwNCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDEwKSkNCmBgYA0KIyBQcm9qZWN0IFBhcnQgLSAyDQoNCiMjIGEuCUludGVyYWN0aXZlIHZpb2xpbiBwbG90IG9mIGFsbCBmZWF0dXJlcw0KDQpgYGB7cn0NCmxpYnJhcnkocGxvdGx5KQ0KDQpwbG90X2x5KGhlYXJ0LCB4PSBIZWFydGRpc2Vhc2UsIHkgPSB+QWdlLCB0eXBlID0gJ3Zpb2xpbicpDQpwbG90X2x5KGhlYXJ0LCB4PSBIZWFydGRpc2Vhc2UsIHkgPSB+UmVzdGluZ0JQLCB0eXBlID0gJ3Zpb2xpbicpDQpwbG90X2x5KGhlYXJ0LCB4PSBIZWFydGRpc2Vhc2UsIHkgPSB+Q2hvbGVzdGVyb2wsIHR5cGUgPSAndmlvbGluJykNCnBsb3RfbHkoaGVhcnQsIHg9IEhlYXJ0ZGlzZWFzZSwgeSA9IH5NYXhIUiwgdHlwZSA9ICd2aW9saW4nKQ0KcGxvdF9seShoZWFydCwgeD0gSGVhcnRkaXNlYXNlLCB5ID0gfk9sZHBlYWssIHR5cGUgPSAndmlvbGluJykNCmBgYA0KDQoNCiMjIGIuSW50ZXJhY3RpdmUgYm94cGxvdCBvZiBhbGwgZmVhdHVyZXMNCg0KYGBge3J9DQpwbG90X2x5KGhlYXJ0LCB4PSBIZWFydGRpc2Vhc2UsIHkgPSB+QWdlLCB0eXBlID0gJ2JveCcpDQpwbG90X2x5KGhlYXJ0LCB4PSBIZWFydGRpc2Vhc2UsIHkgPSB+UmVzdGluZ0JQLCB0eXBlID0gJ2JveCcpDQpwbG90X2x5KGhlYXJ0LCB4PSBIZWFydGRpc2Vhc2UsIHkgPSB+Q2hvbGVzdGVyb2wsIHR5cGUgPSAnYm94JykNCnBsb3RfbHkoaGVhcnQsIHg9IEhlYXJ0ZGlzZWFzZSwgeSA9IH5NYXhIUiwgdHlwZSA9ICdib3gnKQ0KcGxvdF9seShoZWFydCwgeD0gSGVhcnRkaXNlYXNlLCB5ID0gfk9sZHBlYWssIHR5cGUgPSAnYm94JykNCmBgYA0KDQojIyBjLglDYWxjdWxhdGUgY29ycmVsYXRpb24gbWF0cml4IGFuZCBwcmludCB0aGUgbWF0cml4LiBFeHBsYWluIHN0cm9uZyBhbmQgd2VhayBjb3JyZWxhdGlvbg0KDQpgYGB7cn0NCmNvcl9tYXRyaXggPSBjb3IobnVtZXJpY19jb2x1bW5zWyAsMTo1XSkNCmNvcl9tYXRyaXgNCiMgc3Ryb25nIGNvcnJlbGF0aW9uICBpcyAwLjI1OCB3aGljaCBpcyBiZXR3ZWVuIEFnZSBhbmQgT2xkcGVhay4gV2VhayBjb3JyZWxhdGlvbiBpcyAtMC4zODIgd2hpY2ggaXMgYmV0d2VlbiBBZ2UgYW5kIE1heEhSLg0KYGBgDQoNCiMgZC5QbG90IGNvcnJlbGF0aW9uIG1hdHJpeCAobG93ZXIgdHJpYW5nbGUpIHdpdGggdmFsdWVzDQpgYGB7cn0NCmxpYnJhcnkoZ2djb3JycGxvdCkNCmdnY29ycnBsb3QoY29yX21hdHJpeCwgDQogICAgICAgICAgIHR5cGUgPSAibG93ZXIiLA0KICAgICAgICAgICBjb2xvcnMgPSBjKCJyZWQiLCAid2hpdGUiLCAiYmx1ZSIpLA0KICAgICAgICAgICBsYWIgPSBUUlVFKQ0KYGBgDQoNCg0KIyMgZS4JUGFpciBwbG90IG9mIGFsbCBmZWF0dXJlDQoNCmBgYHtyfQ0KbGlicmFyeShHR2FsbHkpDQpnZ3BhaXJzKG51bWVyaWNfY29sdW1ucywgYWVzKGNvbG91ciA9IEhlYXJ0ZGlzZWFzZSkpDQpgYGANCg0KDQoNCiMjIGYuCUFwcGx5IHByaW5jaXBhbCBjb21wb25lbnQgYW5hbHlzaXMgKFBDQSkgYW5kIGV4cGxhaW4gdGhlIFBDQXMNCmBgYHtyfQ0KbGlicmFyeShzdGF0cykNCg0KaGVhcnRfcGNhID0gcHJjb21wKG51bWVyaWNfY29sdW1ucywgc2NhbGUgPSBUUlVFLCBjZW50ZXIgPSBUUlVFKQ0KaGVhcnRfcGNhDQpzdW1tYXJ5KGhlYXJ0X3BjYSkNCmBgYA0KDQpgYGB7cn0NCnBjYV8xMiA9IGFzLmRhdGEuZnJhbWUoaGVhcnRfcGNhJHhbICwgMToyXSkNCnBjYV8xMl9jbGFzcyA9IGNiaW5kKHBjYV8xMiwgSGVhcnRkaXNlYXNlID0gSGVhcnRkaXNlYXNlKQ0KcGNhXzEyX2NsYXNzDQpgYGANCg0KDQoNCiMjIyBpLglCYXIgcGxvdCBvZiBQQ0FzIChQZXJjZW50YWdlIG9mIGV4cGxhaW5lZCB2YXJpYW5jZSB2cyBQQ3MpDQpgYGB7cn0NCmxpYnJhcnkoZmFjdG9leHRyYSkNCmZ2aXpfZWlnKGhlYXJ0X3BjYSwgYWRkbGFiZWxzID0gVFJVRSkNCmBgYA0KDQoNCiMjIyBpaS4JQ29udHJpYnV0aW9uIHBsb3Qgb2YgUENzIChDaXJjdWxhciBwbG90KQ0KDQpgYGB7cn0NCmZ2aXpfcGNhX3ZhcihoZWFydF9wY2EsDQogICAgICAgICAgICAgY29sLnZhciA9ICJjb250cmliIikNCg0KYGBgDQoNCiMjIyBpaWkuCUNvbnRyaWJ1dGlvbiBwbG90IGFzIEhlYXRtYXANCmBgYHtyfQ0KDQpnZ2NvcnJwbG90KGNvcl9tYXRyaXgsIA0KICAgICAgICAgICB0eXBlID0gImxvd2VyIiwNCiAgICAgICAgICAgY29sb3JzID0gYygicHVycGxlIiwgIndoaXRlIiwgInJlZCIpLA0KICAgICAgICAgICBsYWIgPSBUUlVFKQ0KYGBgDQoNCiAgICAgICAgICAgDQpgYGB7cn0NCmxpYnJhcnkoImNvcnJwbG90IikNCnZhciA9IGdldF9wY2FfdmFyKGhlYXJ0X3BjYSkNCmNvcnJwbG90KHZhciRjb3MyKQ0KYGBgDQogICAgICAgICAgIA0KICAgICAgICAgICANCiAgICAgICAgICAgDQojIyMgaXYuCUNsdXN0ZXIgcGxvdCBhZnRlciBQQ0ENCg0KYGBge3J9DQpmdml6X3BjYV9pbmQoaGVhcnRfcGNhLA0KICAgICAgICAgICAgIGdlb20uaW5kID0gInBvaW50IiwNCiAgICAgICAgICAgICBjb2wuaW5kID0gSGVhcnRkaXNlYXNlLA0KICAgICAgICAgICAgIGFkZEVsbGlwc2VzID0gVFJVRSkNCmBgYA0KDQojIyBnLlVzZSBTVk0gdG8gdHJhaW4gYSBtb2RlbCB0byBjbGFzc2lmeSB0aGUgdGFyZ2V0IHZhcmlhYmxlLglFeHBsYWluIHRoZSByZXN1bHRzDQojIyMgaS4JUGxvdCB0aGUgY29uZnVzaW9uIG1hdHJpeA0KYGBge3J9DQpsaWJyYXJ5KGxhdHRpY2UpDQpsaWJyYXJ5KGUxMDcxKQ0KbGlicmFyeShjYXJldCkNCmhlYXJ0ID0gcmVhZC5jc3YoJ2hlYXJ0LmNzdicpDQpoZWFydF9kYXRhID0gaGVhcnRbICxjKDEsNCw1LDgsMTAsMTIpXQ0KdHJhaW5faXggPSBjcmVhdGVEYXRhUGFydGl0aW9uKGhlYXJ0JEhlYXJ0RGlzZWFzZSwgcCA9IDAuOCwgbGlzdCA9IEZBTFNFKQ0KdHJhaW5fZGF0YSA9IGhlYXJ0X2RhdGFbdHJhaW5faXgsIF0NCnRlc3RfZGF0YSA9IGhlYXJ0X2RhdGFbLXRyYWluX2l4LCBdDQp0cmFpbl9kYXRhDQp0ZXN0X2RhdGENCnN2bV9tb2RlbCA9IHN2bShIZWFydERpc2Vhc2UgfiBBZ2UrUmVzdGluZ0JQK0Nob2xlc3Rlcm9sK01heEhSK09sZHBlYWssIGRhdGEgPSB0cmFpbl9kYXRhLCBrZXJuZWwgPSAibGluZWFyIikNCnRlc3RfZGF0YVsxMiwgXQ0KDQpgYGANCmBgYHtyfQ0KcHJlZGljdChzdm1fbW9kZWwsIG5ld2RhdGEgPSB0ZXN0X2RhdGFbNSwgXSkNCg0KcHJlZGljdGlvbnMgPSBwcmVkaWN0KHN2bV9tb2RlbCwgbmV3ZGF0YSA9IHRlc3RfZGF0YSkNCg0KYGBgDQoNCg0KDQojIyAyLglVc2luZyByZWdyZXNzaW9uIGRhdGFzZXQgY2FsbGVkIOKAnFVTIEFkbWlzc2lvbuKAnSAoVVMgQWRtaXNzaW9uLmNzdikuUmVtb3ZlIHRoZSDigJxTZXJpYWwgTm/igJ0gY29sdW1uIGZyb20gdGhlIGRhdGFzZXQNCmBgYHtyfQ0KVVNfQWRtaXNzaW9uID0gcmVhZC5jc3YoJ1VTIEFkbWlzc2lvbi5jc3YnKQ0KVVNfQWRtaXNzaW9uDQpBZG1pc3Npb24gPSBVU19BZG1pc3Npb25bICwtMV0NCkFkbWlzc2lvbg0KbG1fbW9kZWwgPSBsbShDaGFuY2Uub2YuQWRtaXQgfiBHUkUuU2NvcmUsIGRhdGEgPSBBZG1pc3Npb24pDQpzdW1tYXJ5KGxtX21vZGVsKQ0KYGBgDQpgYGB7cn0NCmxpYnJhcnkoZGF0YXNldHMpDQoNCg0KeCA9IFVTX0FkbWlzc2lvbiRDaGFuY2Uub2YuQWRtaXQNCnkgPSBVU19BZG1pc3Npb24kQ0dQQQ0KDQpwcmVkID0gcHJlZGljdChsbl9tb2RlbCkNCml4ID0gc29ydCh4LCBpbmRleC5yZXR1cm4gPSBUKQ0KDQpwbG90KHgsIHkpDQpsaW5lcyh4W2l4XSwgcHJlZFtpeF0pDQoNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoR0dhbGx5KQ0KZGF0YShBZG1pc3Npb24pDQpnZ3BhaXJzKEFkbWlzc2lvbiwgYWVzKGNvbG91ciA9IEFkbWlzc2lvbiRDaGFuY2Uub2YuQWRtaXQpKQ0KDQpgYGANCg0KDQoNCiMjIGEuCVBhaXIgcGxvdCBvZiBhbGwgZmVhdHVyZXMNCg0KDQoNCg0KDQojIyBiLglQbG90IGxpbmVhciByZWdyZXNzaW9uIHdpdGggZWFjaCBmZWF0dXJlLiBGb3IgZXhhbXBsZTogeSA9IEdSRSBTY29yZSwgeCA9IENoYW5jZSBvZiBBZG1pdC4gRG8gdGhpcyBmb3IgYWxsIGRpZmZlcmVudCBmZWF0dXJlcyAob25seSB5IHdpbGwgY2hhbmdlKS4gRXhwbGFpbiB0aGUgcmVzdWx0LiANCiMjIyAoaSkgUGxvdCBvZiBMaW5lYXIgUmVncmVzc2lvbiB3aXRoICJjaGFuY2hlIG9mIGFkbWl0IiBhbmQgIkdSRS5TY29yZSIuDQpgYGB7cn0NCmdncGxvdChBZG1pc3Npb24sIGFlcyh4ID0gQ2hhbmNlLm9mLkFkbWl0LCB5ID0gR1JFLlNjb3JlLCBjb2xvciA9IENoYW5jZS5vZi5BZG1pdCkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGxldmVsID0gMC45MCkNCmBgYA0KDQojIyMgKGlpKSAgUGxvdCBvZiBMaW5lYXIgUmVncmVzc2lvbiB3aXRoICJjaGFuY2hlIG9mIGFkbWl0IiBhbmQgIlRPRUZMIFNjb3JlIi4NCmBgYHtyfQ0KZ2dwbG90KEFkbWlzc2lvbiwgYWVzKHggPSBDaGFuY2Uub2YuQWRtaXQsIHkgPSBUT0VGTC5TY29yZSwgY29sb3IgPSBDaGFuY2Uub2YuQWRtaXQpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBsZXZlbCA9IDAuOTUpDQpgYGANCg0KIyMjIChpaWkpICBQbG90IG9mIExpbmVhciBSZWdyZXNzaW9uIHdpdGggImNoYW5jaGUgb2YgYWRtaXQiIGFuZCAiVW5pdmVyc2l0eSBSYXRpbmciLg0KYGBge3J9DQpnZ3Bsb3QoQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeSA9IFVuaXZlcnNpdHkuUmF0aW5nLCBjb2xvciA9IENoYW5jZS5vZi5BZG1pdCkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGxldmVsID0gMC45NSkNCmBgYA0KIyMjIChpdikgIFBsb3Qgb2YgTGluZWFyIFJlZ3Jlc3Npb24gd2l0aCAiY2hhbmNoZSBvZiBhZG1pdCIgYW5kICJTT1AiLg0KYGBge3J9DQpnZ3Bsb3QoQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeSA9IFNPUCwgY29sb3IgPSBDaGFuY2Uub2YuQWRtaXQpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBsZXZlbCA9IDAuOTUpDQpgYGANCg0KIyMjICh2KSAgUGxvdCBvZiBMaW5lYXIgUmVncmVzc2lvbiB3aXRoICJjaGFuY2hlIG9mIGFkbWl0IiBhbmQgIkxPUiIuDQpgYGB7cn0NCmdncGxvdChBZG1pc3Npb24sIGFlcyh4ID0gQ2hhbmNlLm9mLkFkbWl0LCB5ID0gTE9SLCBjb2xvciA9IENoYW5jZS5vZi5BZG1pdCkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGxldmVsID0gMC45MCkNCmBgYA0KDQojIyMgKHZpKSAgUGxvdCBvZiBMaW5lYXIgUmVncmVzc2lvbiB3aXRoICJjaGFuY2hlIG9mIGFkbWl0IiBhbmQgIkNHUEEiLg0KYGBge3J9DQpnZ3Bsb3QoQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeSA9IENHUEEsIGNvbG9yID0gQ2hhbmNlLm9mLkFkbWl0KSkgKyANCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbGV2ZWwgPSAwLjk1KQ0KDQpgYGANCih2aWkpICBQbG90IG9mIExpbmVhciBSZWdyZXNzaW9uIHdpdGggImNoYW5jaGUgb2YgYWRtaXQiIGFuZCAiUmVzZWFyY2giLg0KYGBge3J9DQpnZ3Bsb3QoQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeSA9IFJlc2VhcmNoLCBjb2xvciA9IENoYW5jZS5vZi5BZG1pdCkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGxldmVsID0gMC45NSkNCmBgYA0KDQoNCiMjIGMuCVBsb3QgcG9seW5vbWlhbCByZWdyZXNzaW9uIG9mIHBvd2VyIDIgd2l0aCBlYWNoIGZlYXR1cmUuIEZvciBleGFtcGxlOiB5ID0gQ2hhbmNlIG9mIEFkbWl0LCB4ID0gQ2hhbmNlIG9mIEFkbWl0LiBEbyB0aGlzIGZvciBhbGwgZGlmZmVyZW50IGZlYXR1cmVzIChvbmx5IHkgd2lsbCBjaGFuZ2UpLiBFeHBsYWluIHRoZSByZXN1bHQuIA0KIyMjIChpKSBQb2x5bm9taWFsIFBsb3Qgb2YgTGluZWFyIFJlZ3Jlc3Npb24gd2l0aCAiY2hhbmNoZSBvZiBhZG1pdCIgYW5kICJHUkUuU2NvcmUiLg0KYGBge3J9DQpnZ3Bsb3QoQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeSA9IEdSRS5TY29yZSwgY29sb3IgPSBDaGFuY2Uub2YuQWRtaXQpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0geX5wb2x5KHgsIDIpLGxldmVsID0gMC45MCkNCmBgYA0KDQojIyMgKGlpKSAgUG9seW5vbWlhbCBQbG90IG9mIExpbmVhciBSZWdyZXNzaW9uIHdpdGggImNoYW5jaGUgb2YgYWRtaXQiIGFuZCAiVE9FRkwgU2NvcmUiLg0KYGBge3J9DQpnZ3Bsb3QoQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeSA9IFRPRUZMLlNjb3JlLCBjb2xvciA9IENoYW5jZS5vZi5BZG1pdCkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsZm9ybXVsYSA9IHl+cG9seSh4LCAyKSwgbGV2ZWwgPSAwLjk1KQ0KYGBgDQoNCiMjIyAoaWlpKSAgUG9seW5vbWlhbCBQbG90IG9mIExpbmVhciBSZWdyZXNzaW9uIHdpdGggImNoYW5jaGUgb2YgYWRtaXQiIGFuZCAiVW5pdmVyc2l0eSBSYXRpbmciLg0KYGBge3J9DQpnZ3Bsb3QoQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeSA9IFVuaXZlcnNpdHkuUmF0aW5nLCBjb2xvciA9IENoYW5jZS5vZi5BZG1pdCkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5fnBvbHkoeCwgMiksbGV2ZWwgPSAwLjk1KQ0KYGBgDQojIyMgKGl2KSBQb2x5bm9taWFsIFBsb3Qgb2YgTGluZWFyIFJlZ3Jlc3Npb24gd2l0aCAiY2hhbmNoZSBvZiBhZG1pdCIgYW5kICJTT1AiLg0KYGBge3J9DQpnZ3Bsb3QoQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeSA9IFNPUCwgY29sb3IgPSBDaGFuY2Uub2YuQWRtaXQpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0geX5wb2x5KHgsIDIpLGxldmVsID0gMC45NSkNCmBgYA0KDQojIyMgKHYpIFBvbHlub21pYWwgUGxvdCBvZiBMaW5lYXIgUmVncmVzc2lvbiB3aXRoICJjaGFuY2hlIG9mIGFkbWl0IiBhbmQgIkxPUiIuDQpgYGB7cn0NCmdncGxvdChBZG1pc3Npb24sIGFlcyh4ID0gQ2hhbmNlLm9mLkFkbWl0LCB5ID0gTE9SLCBjb2xvciA9IENoYW5jZS5vZi5BZG1pdCkpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5fnBvbHkoeCwgMiksbGV2ZWwgPSAwLjkwKQ0KYGBgDQoNCiMjIyAodmkpIFBvbHlub21pYWwgUGxvdCBvZiBMaW5lYXIgUmVncmVzc2lvbiB3aXRoICJjaGFuY2hlIG9mIGFkbWl0IiBhbmQgIkNHUEEiLg0KYGBge3J9DQpnZ3Bsb3QoQWRtaXNzaW9uLCBhZXMoeCA9IENoYW5jZS5vZi5BZG1pdCwgeSA9IENHUEEsIGNvbG9yID0gQ2hhbmNlLm9mLkFkbWl0KSkgKyANCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgZm9ybXVsYSA9IHl+cG9seSh4LCAyKSxsZXZlbCA9IDAuOTUpDQoNCmBgYA0KIyMjICh2aWkpIFBvbHlub21pYWwgUGxvdCBvZiBMaW5lYXIgUmVncmVzc2lvbiB3aXRoICJjaGFuY2hlIG9mIGFkbWl0IiBhbmQgIlJlc2VhcmNoIi4NCmBgYHtyfQ0KZ2dwbG90KEFkbWlzc2lvbiwgYWVzKHggPSBDaGFuY2Uub2YuQWRtaXQsIHkgPSBSZXNlYXJjaCwgY29sb3IgPSBDaGFuY2Uub2YuQWRtaXQpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0geX5wb2x5KHgsIDIpLGxldmVsID0gMC45NSkNCmBgYA0KDQoNCiMjIGQuCVVzZSBhbGwgZmVhdHVyZXMgdG9nZXRoZXIgdG8gY3JlYXRlIGEgcmVncmVzc2lvbiBtb2RlbCBhbmQgZXhwbGFpbiB0aGUgcmVzdWx0LiBGb3IgZXhhbXBsZTogbG0oeSB+IHgxK3gyK3gz4oCmLit4biwgZGF0YSA9IFVTX0FkbWlzc2lvbiksIGhlcmUgeCByZXByZXNlbnRzIGEgc2luZ2xlIGZlYXR1cmUgYW5kIHkgcmVwcmVzZW50cyB0aGUgdGFyZ2V0IHZhcmlhYmxlLiANCg0KYGBge3J9DQpsbV9tb2RlbF9hbGwgPSBsbShDaGFuY2Uub2YuQWRtaXQgfiBHUkUuU2NvcmUrVE9FRkwuU2NvcmUrIFVuaXZlcnNpdHkuUmF0aW5nKyBTT1ArTE9SK0NHUEErUmVzZWFyY2gsIGRhdGEgPSBBZG1pc3Npb24pDQpzdW1tYXJ5KGxtX21vZGVsKQ0KDQpgYGANCg0KDQo=