This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

install.packages("caTools")
Error in install.packages : Updating loaded packages
library(MASS)
library(tidyverse)
library(caTools)

Loading our Data

  data1 <- read.csv("data_synth.csv", header=TRUE, stringsAsFactors=FALSE)
#column_list<-list("age","single","inschool","arv_start","arv_dura","lifetime")
data<-data1%>%dplyr::select(age,single,inschool,arv_start,arv_dura,lifetime,male)%>%drop_na(arv_dura,arv_start)
summary(data)
      age            single         inschool        arv_start         arv_dura    
 Min.   :15.00   Min.   :0.000   Min.   :0.0000   Min.   : 1.000   Min.   : 0.00  
 1st Qu.:16.00   1st Qu.:1.000   1st Qu.:0.0000   1st Qu.: 1.000   1st Qu.:10.00  
 Median :17.00   Median :1.000   Median :1.0000   Median : 1.000   Median :14.00  
 Mean   :17.22   Mean   :0.962   Mean   :0.6899   Mean   : 4.848   Mean   :12.11  
 3rd Qu.:19.00   3rd Qu.:1.000   3rd Qu.:1.0000   3rd Qu.: 7.000   3rd Qu.:16.00  
 Max.   :23.00   Max.   :1.000   Max.   :1.0000   Max.   :20.000   Max.   :19.00  
    lifetime           male       
 Min.   :0.0000   Min.   :0.0000  
 1st Qu.:0.0000   1st Qu.:0.0000  
 Median :0.0000   Median :0.0000  
 Mean   :0.3101   Mean   :0.3608  
 3rd Qu.:1.0000   3rd Qu.:1.0000  
 Max.   :1.0000   Max.   :1.0000  

Task 1 Creating Summary Table

Step 2 : Functions for Preprocessing

rename1<-function(x){
    return (paste("Average",x,sep=" "))
}

rename2<-function(x){
    return (paste("Deviation",x,sep=" "))
}

rename3<-function(x)
{
  if (x==0)
  {
    return("Female")
  }
  else
  {
    return("Male")
  }
}

print(rename1("male"))
[1] "Average male"

Creating a Averages for our data

avg_data <- data %>% group_by(male) %>% summarise_each(funs(mean)) #data is skewed towards females
Warning: `summarise_each()` was deprecated in dplyr 0.7.0.
ℹ Please use `across()` instead.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
Warning: `funs()` was deprecated in dplyr 0.8.0.
ℹ Please use a list of either functions or lambdas:

# Simple named list: list(mean = mean, median = median)

# Auto named with `tibble::lst()`: tibble::lst(mean, median)

# Using lambdas list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
avg_data<-avg_data %>%rename_with(rename1)%>%rename(c("Sex"="Average male"))
print(avg_data)

Creating Deviation Data

dev_data <- data %>% group_by(male) %>% summarise_each(funs(sd)) #data is skewed towards females
Warning: `summarise_each()` was deprecated in dplyr 0.7.0.
ℹ Please use `across()` instead.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
Warning: `funs()` was deprecated in dplyr 0.8.0.
ℹ Please use a list of either functions or lambdas:

# Simple named list: list(mean = mean, median = median)

# Auto named with `tibble::lst()`: tibble::lst(mean, median)

# Using lambdas list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.
dev_data<-dev_data %>%rename_with(rename2)%>%rename(c("Sex"="Deviation male"))
print(dev_data)

Joining our Deviation and Average Tables

results_table<-left_join(dev_data,avg_data,by="Sex")
for (name in column_list)
{
  results_table<-results_table%>%relocate(paste("Average",name,sep=" "),.before=paste("Deviation",name,sep=" "))
}
results_table["Sex"]<-results_table%>%dplyr::select(Sex)%>%mutate(Sex=if_else(Sex==0,"Female","Male"))
print(results_table)
write.csv(results_table,"./results/task1.csv")

Task2 : Creating Logistic Regression

Feature Engineering

Inschool chisq test

#inschool's relationship (chisq test)
in_school_data<-data1%>%dplyr::select(inschool,hiv_talk_friend)
in_school_data<-table(in_school_data$inschool,in_school_data$hiv_talk_friend)
print(in_school_data)
   
     0  1
  0 16 37
  1 71 43
print(chisq.test(in_school_data))

    Pearson's Chi-squared test with Yates' continuity correction

data:  in_school_data
X-squared = 13.673, df = 1, p-value = 0.0002176
#inschool does look pretty significant

#age spearmans corellation

df_plot<-data1%>%dplyr::select(age,hiv_talk_friend)%>%group_by(age)%>%summarise(percentage=mean(hiv_talk_friend))
age<-df_plot["age"]$age
hiv_talk_friend<-df_plot["percentage"]$percentage
plot(age,hiv_talk_friend)

#age is significant

Lifetime chisq test

lifetime_data<-data1%>%dplyr::select(lifetime,hiv_talk_friend)
lifetime_data<-table(lifetime_data$lifetime,lifetime_data$hiv_talk_friend)
print(lifetime_data)
   
     0  1
  0 75 38
  1 12 42
print(chisq.test(lifetime_data))

    Pearson's Chi-squared test with Yates' continuity correction

data:  lifetime_data
X-squared = 26.797, df = 1, p-value = 2.26e-07
#lifetime sex is vary significant

Single chisq test

single_data<-data1%>%dplyr::select(single,hiv_talk_friend)
single_data<-table(single_data$single,single_data$hiv_talk_friend)
print(single_data)
   
     0  1
  0  0  6
  1 87 74
print(chisq.test(single_data))
Warning in chisq.test(single_data) :
  Chi-squared approximation may be incorrect

    Pearson's Chi-squared test with Yates' continuity correction

data:  single_data
X-squared = 4.7761, df = 1, p-value = 0.02886
#being single is significant

Male chisq test

male_data<-data1%>%dplyr::select(male,hiv_talk_friend)
male_data<-table(male_data$male,male_data$hiv_talk_friend)
print(male_data)
   
     0  1
  0 49 58
  1 38 22
print(chisq.test(male_data))

    Pearson's Chi-squared test with Yates' continuity correction

data:  male_data
X-squared = 4.0619, df = 1, p-value = 0.04386
#not that significant

Education chisq test

edu_data<-data1%>%dplyr::select(education_4cat,hiv_talk_friend)
edu_data<-table(edu_data$education_4cat,edu_data$hiv_talk_friend)
print(edu_data)
   
     0  1
  0  0  2
  1 37 41
  2 45 26
  3  5 11
print(chisq.test(edu_data))
Warning in chisq.test(edu_data) :
  Chi-squared approximation may be incorrect

    Pearson's Chi-squared test

data:  edu_data
X-squared = 9.2625, df = 3, p-value = 0.026

Logit Regression

# Splitting dataset
split <- sample.split(data1, SplitRatio = 0.8)
 
train_reg <- subset(data1, split == "TRUE")
test_reg <- subset(data1, split == "FALSE")
#head(test_reg)
model<-glm(hiv_talk_friend~single+lifetime+age+inschool,family = "binomial",data=train_reg)
summary(model)

Call:
glm(formula = hiv_talk_friend ~ single + lifetime + age + inschool, 
    family = "binomial", data = train_reg)

Coefficients:
            Estimate Std. Error z value Pr(>|z|)   
(Intercept)   8.0303   952.9790   0.008  0.99328   
single      -15.6733   952.9759  -0.016  0.98688   
lifetime      1.0246     0.5361   1.911  0.05597 . 
age           0.4154     0.1457   2.851  0.00436 **
inschool     -0.1922     0.5289  -0.363  0.71628   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 180.31  on 130  degrees of freedom
Residual deviance: 139.15  on 126  degrees of freedom
AIC: 149.15

Number of Fisher Scoring iterations: 15

Evaluating our Model

Function to calculate Metric based on threshold

metric<-function(threshold)
{
  print("")
  print(paste("Threshold value choosen : ",threshold))
predict_reg <- predict(model,
                       test_reg, type = "response")
#print(predict_reg)
predict_reg <- ifelse(predict_reg >threshold, 1, 0)
# Evaluating model accuracy
# using confusion matrix
cm<-table(test_reg$hiv_talk_friend, predict_reg)
missing_classerr <- mean(predict_reg != test_reg$hiv_talk_friend)
print(paste('Accuracy =', 1 - missing_classerr))
all_p=sum(predict_reg==1,na.rm=TRUE)
tp=sum(predict_reg[(test_reg$hiv_talk_friend==1)]==1,na.rm=TRUE)
fn=sum(test_reg$hiv_talk_friend[predict_reg==0],na.rm=TRUE)
print(paste("Precision = ",tp/all_p))
print(paste("Recall = ",tp/(tp+fn)))
print("")
}

Metrics for various thresholds

metric(0.2)
[1] ""
[1] "Threshold value choosen :  0.2"
[1] "Accuracy = 0.527777777777778"
[1] "Precision =  0.571428571428571"
[1] "Recall =  0.761904761904762"
[1] ""
metric(0.3)
[1] ""
[1] "Threshold value choosen :  0.3"
[1] "Accuracy = 0.666666666666667"
[1] "Precision =  0.714285714285714"
[1] "Recall =  0.714285714285714"
[1] ""
metric(0.4)
[1] ""
[1] "Threshold value choosen :  0.4"
[1] "Accuracy = 0.666666666666667"
[1] "Precision =  0.736842105263158"
[1] "Recall =  0.666666666666667"
[1] ""
metric(0.5)
[1] ""
[1] "Threshold value choosen :  0.5"
[1] "Accuracy = 0.694444444444444"
[1] "Precision =  0.857142857142857"
[1] "Recall =  0.571428571428571"
[1] ""
metric(0.6)
[1] ""
[1] "Threshold value choosen :  0.6"
[1] "Accuracy = 0.638888888888889"
[1] "Precision =  0.833333333333333"
[1] "Recall =  0.476190476190476"
[1] ""

Task3 : Plotting our Results for age

df_plot<-data1%>%dplyr::select(age,hiv_talk_friend)%>%group_by(age)%>%summarise(percentage=mean(hiv_talk_friend))
age<-df_plot["age"]$age
hiv_talk_friend<-df_plot["percentage"]$percentage
plot(age,hiv_talk_friend,pch="o", col="blue")
predict_reg<-predict(model,data1,type = "response")
age_cont<-data1%>%dplyr::select(age)
names(predict_reg)<-NULL
data1["predy"]<-predict_reg
df_predy<-data1%>%dplyr::select(age,predy)%>%group_by(age)%>%summarise(percentage=mean(predy))
predy<-df_predy$percentage
#head(df_predy)
points(df_predy$age,predy,col="red", pch="P")
lines(smooth.spline(df_predy$age,predy),col="orange",lwd=2)
legend(19.5,0.4,legend=c("Predicted Percentage","Ground Truth Percentage"),col=c("red","blue"),pch=c("P","o"),lty=c(1,0))

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiANCg0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCJjYVRvb2xzIikNCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShjYVRvb2xzKQ0KYGBgDQojIExvYWRpbmcgb3VyIERhdGENCg0KYGBge3J9DQogIGRhdGExIDwtIHJlYWQuY3N2KCJkYXRhX3N5bnRoLmNzdiIsIGhlYWRlcj1UUlVFLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQ0KYGBgDQpgYGB7cn0NCiNjb2x1bW5fbGlzdDwtbGlzdCgiYWdlIiwic2luZ2xlIiwiaW5zY2hvb2wiLCJhcnZfc3RhcnQiLCJhcnZfZHVyYSIsImxpZmV0aW1lIikNCmRhdGE8LWRhdGExJT4lZHBseXI6OnNlbGVjdChhZ2Usc2luZ2xlLGluc2Nob29sLGFydl9zdGFydCxhcnZfZHVyYSxsaWZldGltZSxtYWxlKSU+JWRyb3BfbmEoYXJ2X2R1cmEsYXJ2X3N0YXJ0KQ0Kc3VtbWFyeShkYXRhKQ0KYGBgDQoNCiMgVGFzayAxICBDcmVhdGluZyBTdW1tYXJ5IFRhYmxlIA0KIyMgU3RlcCAyIDogRnVuY3Rpb25zIGZvciBQcmVwcm9jZXNzaW5nDQpgYGB7cn0NCnJlbmFtZTE8LWZ1bmN0aW9uKHgpew0KICAgIHJldHVybiAocGFzdGUoIkF2ZXJhZ2UiLHgsc2VwPSIgIikpDQp9DQoNCnJlbmFtZTI8LWZ1bmN0aW9uKHgpew0KICAgIHJldHVybiAocGFzdGUoIkRldmlhdGlvbiIseCxzZXA9IiAiKSkNCn0NCg0KcmVuYW1lMzwtZnVuY3Rpb24oeCkNCnsNCiAgaWYgKHg9PTApDQogIHsNCiAgICByZXR1cm4oIkZlbWFsZSIpDQogIH0NCiAgZWxzZQ0KICB7DQogICAgcmV0dXJuKCJNYWxlIikNCiAgfQ0KfQ0KDQpwcmludChyZW5hbWUxKCJtYWxlIikpDQpgYGANCiMjIENyZWF0aW5nIGEgQXZlcmFnZXMgZm9yIG91ciBkYXRhDQpgYGB7cn0gDQphdmdfZGF0YSA8LSBkYXRhICU+JSBncm91cF9ieShtYWxlKSAlPiUgc3VtbWFyaXNlX2VhY2goZnVucyhtZWFuKSkgI2RhdGEgaXMgc2tld2VkIHRvd2FyZHMgZmVtYWxlcw0KYXZnX2RhdGE8LWF2Z19kYXRhICU+JXJlbmFtZV93aXRoKHJlbmFtZTEpJT4lcmVuYW1lKGMoIlNleCI9IkF2ZXJhZ2UgbWFsZSIpKQ0KcHJpbnQoYXZnX2RhdGEpDQpgYGANCiMjIENyZWF0aW5nIERldmlhdGlvbiBEYXRhDQpgYGB7cn0NCmRldl9kYXRhIDwtIGRhdGEgJT4lIGdyb3VwX2J5KG1hbGUpICU+JSBzdW1tYXJpc2VfZWFjaChmdW5zKHNkKSkgI2RhdGEgaXMgc2tld2VkIHRvd2FyZHMgZmVtYWxlcw0KZGV2X2RhdGE8LWRldl9kYXRhICU+JXJlbmFtZV93aXRoKHJlbmFtZTIpJT4lcmVuYW1lKGMoIlNleCI9IkRldmlhdGlvbiBtYWxlIikpDQpwcmludChkZXZfZGF0YSkNCmBgYA0KIyMgSm9pbmluZyBvdXIgRGV2aWF0aW9uIGFuZCBBdmVyYWdlIFRhYmxlcw0KYGBge3J9DQpyZXN1bHRzX3RhYmxlPC1sZWZ0X2pvaW4oZGV2X2RhdGEsYXZnX2RhdGEsYnk9IlNleCIpDQpmb3IgKG5hbWUgaW4gY29sdW1uX2xpc3QpDQp7DQogIHJlc3VsdHNfdGFibGU8LXJlc3VsdHNfdGFibGUlPiVyZWxvY2F0ZShwYXN0ZSgiQXZlcmFnZSIsbmFtZSxzZXA9IiAiKSwuYmVmb3JlPXBhc3RlKCJEZXZpYXRpb24iLG5hbWUsc2VwPSIgIikpDQp9DQpyZXN1bHRzX3RhYmxlWyJTZXgiXTwtcmVzdWx0c190YWJsZSU+JWRwbHlyOjpzZWxlY3QoU2V4KSU+JW11dGF0ZShTZXg9aWZfZWxzZShTZXg9PTAsIkZlbWFsZSIsIk1hbGUiKSkNCnByaW50KHJlc3VsdHNfdGFibGUpDQp3cml0ZS5jc3YocmVzdWx0c190YWJsZSwiLi9yZXN1bHRzL3Rhc2sxLmNzdiIpDQpgYGANCg0KIyBUYXNrMiA6IENyZWF0aW5nIExvZ2lzdGljIFJlZ3Jlc3Npb24NCiMjIEZlYXR1cmUgRW5naW5lZXJpbmcNCiMjIyBJbnNjaG9vbCBjaGlzcSB0ZXN0DQpgYGB7cn0NCiNpbnNjaG9vbCdzIHJlbGF0aW9uc2hpcCAoY2hpc3EgdGVzdCkNCmluX3NjaG9vbF9kYXRhPC1kYXRhMSU+JWRwbHlyOjpzZWxlY3QoaW5zY2hvb2wsaGl2X3RhbGtfZnJpZW5kKQ0KaW5fc2Nob29sX2RhdGE8LXRhYmxlKGluX3NjaG9vbF9kYXRhJGluc2Nob29sLGluX3NjaG9vbF9kYXRhJGhpdl90YWxrX2ZyaWVuZCkNCnByaW50KGluX3NjaG9vbF9kYXRhKQ0KcHJpbnQoY2hpc3EudGVzdChpbl9zY2hvb2xfZGF0YSkpDQojaW5zY2hvb2wgZG9lcyBsb29rIHByZXR0eSBzaWduaWZpY2FudA0KYGBgDQojYWdlIHNwZWFybWFucyBjb3JlbGxhdGlvbg0KYGBge3J9DQpkZl9wbG90PC1kYXRhMSU+JWRwbHlyOjpzZWxlY3QoYWdlLGhpdl90YWxrX2ZyaWVuZCklPiVncm91cF9ieShhZ2UpJT4lc3VtbWFyaXNlKHBlcmNlbnRhZ2U9bWVhbihoaXZfdGFsa19mcmllbmQpKQ0KYWdlPC1kZl9wbG90WyJhZ2UiXSRhZ2UNCmhpdl90YWxrX2ZyaWVuZDwtZGZfcGxvdFsicGVyY2VudGFnZSJdJHBlcmNlbnRhZ2UNCnBsb3QoYWdlLGhpdl90YWxrX2ZyaWVuZCkNCiNhZ2UgaXMgc2lnbmlmaWNhbnQNCmBgYA0KDQojIyMgTGlmZXRpbWUgY2hpc3EgdGVzdA0KYGBge3J9DQpsaWZldGltZV9kYXRhPC1kYXRhMSU+JWRwbHlyOjpzZWxlY3QobGlmZXRpbWUsaGl2X3RhbGtfZnJpZW5kKQ0KbGlmZXRpbWVfZGF0YTwtdGFibGUobGlmZXRpbWVfZGF0YSRsaWZldGltZSxsaWZldGltZV9kYXRhJGhpdl90YWxrX2ZyaWVuZCkNCnByaW50KGxpZmV0aW1lX2RhdGEpDQpwcmludChjaGlzcS50ZXN0KGxpZmV0aW1lX2RhdGEpKQ0KI2xpZmV0aW1lIHNleCBpcyB2YXJ5IHNpZ25pZmljYW50DQpgYGANCiMjIyBTaW5nbGUgY2hpc3EgdGVzdA0KYGBge3J9DQpzaW5nbGVfZGF0YTwtZGF0YTElPiVkcGx5cjo6c2VsZWN0KHNpbmdsZSxoaXZfdGFsa19mcmllbmQpDQpzaW5nbGVfZGF0YTwtdGFibGUoc2luZ2xlX2RhdGEkc2luZ2xlLHNpbmdsZV9kYXRhJGhpdl90YWxrX2ZyaWVuZCkNCnByaW50KHNpbmdsZV9kYXRhKQ0KcHJpbnQoY2hpc3EudGVzdChzaW5nbGVfZGF0YSkpDQojYmVpbmcgc2luZ2xlIGlzIHNpZ25pZmljYW50DQpgYGANCiMjIyBNYWxlIGNoaXNxIHRlc3QNCmBgYHtyfQ0KbWFsZV9kYXRhPC1kYXRhMSU+JWRwbHlyOjpzZWxlY3QobWFsZSxoaXZfdGFsa19mcmllbmQpDQptYWxlX2RhdGE8LXRhYmxlKG1hbGVfZGF0YSRtYWxlLG1hbGVfZGF0YSRoaXZfdGFsa19mcmllbmQpDQpwcmludChtYWxlX2RhdGEpDQpwcmludChjaGlzcS50ZXN0KG1hbGVfZGF0YSkpDQojbm90IHRoYXQgc2lnbmlmaWNhbnQNCmBgYA0KIyMjIEVkdWNhdGlvbiBjaGlzcSB0ZXN0DQpgYGB7cn0NCmVkdV9kYXRhPC1kYXRhMSU+JWRwbHlyOjpzZWxlY3QoZWR1Y2F0aW9uXzRjYXQsaGl2X3RhbGtfZnJpZW5kKQ0KZWR1X2RhdGE8LXRhYmxlKGVkdV9kYXRhJGVkdWNhdGlvbl80Y2F0LGVkdV9kYXRhJGhpdl90YWxrX2ZyaWVuZCkNCnByaW50KGVkdV9kYXRhKQ0KcHJpbnQoY2hpc3EudGVzdChlZHVfZGF0YSkpDQpgYGANCg0KIyMgTG9naXQgUmVncmVzc2lvbg0KYGBge3J9DQojIFNwbGl0dGluZyBkYXRhc2V0DQpzcGxpdCA8LSBzYW1wbGUuc3BsaXQoZGF0YTEsIFNwbGl0UmF0aW8gPSAwLjgpDQogDQp0cmFpbl9yZWcgPC0gc3Vic2V0KGRhdGExLCBzcGxpdCA9PSAiVFJVRSIpDQp0ZXN0X3JlZyA8LSBzdWJzZXQoZGF0YTEsIHNwbGl0ID09ICJGQUxTRSIpDQojaGVhZCh0ZXN0X3JlZykNCm1vZGVsPC1nbG0oaGl2X3RhbGtfZnJpZW5kfnNpbmdsZStsaWZldGltZSthZ2UraW5zY2hvb2wsZmFtaWx5ID0gImJpbm9taWFsIixkYXRhPXRyYWluX3JlZykNCnN1bW1hcnkobW9kZWwpDQpgYGANCiMjIEV2YWx1YXRpbmcgb3VyIE1vZGVsIA0KIyMjIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBNZXRyaWMgYmFzZWQgb24gdGhyZXNob2xkDQpgYGB7cn0NCm1ldHJpYzwtZnVuY3Rpb24odGhyZXNob2xkKQ0Kew0KICBwcmludCgiIikNCiAgcHJpbnQocGFzdGUoIlRocmVzaG9sZCB2YWx1ZSBjaG9vc2VuIDogIix0aHJlc2hvbGQpKQ0KcHJlZGljdF9yZWcgPC0gcHJlZGljdChtb2RlbCwNCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdF9yZWcsIHR5cGUgPSAicmVzcG9uc2UiKQ0KI3ByaW50KHByZWRpY3RfcmVnKQ0KcHJlZGljdF9yZWcgPC0gaWZlbHNlKHByZWRpY3RfcmVnID50aHJlc2hvbGQsIDEsIDApDQojIEV2YWx1YXRpbmcgbW9kZWwgYWNjdXJhY3kNCiMgdXNpbmcgY29uZnVzaW9uIG1hdHJpeA0KY208LXRhYmxlKHRlc3RfcmVnJGhpdl90YWxrX2ZyaWVuZCwgcHJlZGljdF9yZWcpDQptaXNzaW5nX2NsYXNzZXJyIDwtIG1lYW4ocHJlZGljdF9yZWcgIT0gdGVzdF9yZWckaGl2X3RhbGtfZnJpZW5kKQ0KcHJpbnQocGFzdGUoJ0FjY3VyYWN5ID0nLCAxIC0gbWlzc2luZ19jbGFzc2VycikpDQphbGxfcD1zdW0ocHJlZGljdF9yZWc9PTEsbmEucm09VFJVRSkNCnRwPXN1bShwcmVkaWN0X3JlZ1sodGVzdF9yZWckaGl2X3RhbGtfZnJpZW5kPT0xKV09PTEsbmEucm09VFJVRSkNCmZuPXN1bSh0ZXN0X3JlZyRoaXZfdGFsa19mcmllbmRbcHJlZGljdF9yZWc9PTBdLG5hLnJtPVRSVUUpDQpwcmludChwYXN0ZSgiUHJlY2lzaW9uID0gIix0cC9hbGxfcCkpDQpwcmludChwYXN0ZSgiUmVjYWxsID0gIix0cC8odHArZm4pKSkNCnByaW50KCIiKQ0KfQ0KYGBgDQojIyMgTWV0cmljcyBmb3IgdmFyaW91cyB0aHJlc2hvbGRzDQpgYGB7cn0NCm1ldHJpYygwLjIpDQptZXRyaWMoMC4zKQ0KbWV0cmljKDAuNCkNCm1ldHJpYygwLjUpDQptZXRyaWMoMC42KQ0KYGBgDQojIFRhc2szIDogUGxvdHRpbmcgb3VyIFJlc3VsdHMgZm9yIGFnZQ0KYGBge3J9DQpkZl9wbG90PC1kYXRhMSU+JWRwbHlyOjpzZWxlY3QoYWdlLGhpdl90YWxrX2ZyaWVuZCklPiVncm91cF9ieShhZ2UpJT4lc3VtbWFyaXNlKHBlcmNlbnRhZ2U9bWVhbihoaXZfdGFsa19mcmllbmQpKQ0KYWdlPC1kZl9wbG90WyJhZ2UiXSRhZ2UNCmhpdl90YWxrX2ZyaWVuZDwtZGZfcGxvdFsicGVyY2VudGFnZSJdJHBlcmNlbnRhZ2UNCnBsb3QoYWdlLGhpdl90YWxrX2ZyaWVuZCxwY2g9Im8iLCBjb2w9ImJsdWUiKQ0KcHJlZGljdF9yZWc8LXByZWRpY3QobW9kZWwsZGF0YTEsdHlwZSA9ICJyZXNwb25zZSIpDQphZ2VfY29udDwtZGF0YTElPiVkcGx5cjo6c2VsZWN0KGFnZSkNCm5hbWVzKHByZWRpY3RfcmVnKTwtTlVMTA0KZGF0YTFbInByZWR5Il08LXByZWRpY3RfcmVnDQpkZl9wcmVkeTwtZGF0YTElPiVkcGx5cjo6c2VsZWN0KGFnZSxwcmVkeSklPiVncm91cF9ieShhZ2UpJT4lc3VtbWFyaXNlKHBlcmNlbnRhZ2U9bWVhbihwcmVkeSkpDQpwcmVkeTwtZGZfcHJlZHkkcGVyY2VudGFnZQ0KI2hlYWQoZGZfcHJlZHkpDQpwb2ludHMoZGZfcHJlZHkkYWdlLHByZWR5LGNvbD0icmVkIiwgcGNoPSJQIikNCmxpbmVzKHNtb290aC5zcGxpbmUoZGZfcHJlZHkkYWdlLHByZWR5KSxjb2w9Im9yYW5nZSIsbHdkPTIpDQpsZWdlbmQoMTkuNSwwLjQsbGVnZW5kPWMoIlByZWRpY3RlZCBQZXJjZW50YWdlIiwiR3JvdW5kIFRydXRoIFBlcmNlbnRhZ2UiKSxjb2w9YygicmVkIiwiYmx1ZSIpLHBjaD1jKCJQIiwibyIpLGx0eT1jKDEsMCkpDQpgYGANCg0KDQoNCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDdHJsK0FsdCtJKi4NCg0KV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDdHJsK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuDQoNClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4NCg==