Survival analysis is used to predict the survival of a person,with respect to variables.

Titanic_data1=Titanic
head(Titanic_data1)
NA

Above is the head data which we are going to analyze.

summary(Titanic_data1)
  PassengerId       Survived          Pclass     
 Min.   :  1.0   Min.   :0.0000   Min.   :1.000  
 1st Qu.:223.5   1st Qu.:0.0000   1st Qu.:2.000  
 Median :446.0   Median :0.0000   Median :3.000  
 Mean   :446.0   Mean   :0.3838   Mean   :2.309  
 3rd Qu.:668.5   3rd Qu.:1.0000   3rd Qu.:3.000  
 Max.   :891.0   Max.   :1.0000   Max.   :3.000  
                                                 
     Name               Sex                 Age       
 Length:891         Length:891         Min.   : 0.42  
 Class :character   Class :character   1st Qu.:20.12  
 Mode  :character   Mode  :character   Median :28.00  
                                       Mean   :29.70  
                                       3rd Qu.:38.00  
                                       Max.   :80.00  
                                       NA's   :177    
     SibSp           Parch           Ticket         
 Min.   :0.000   Min.   :0.0000   Length:891        
 1st Qu.:0.000   1st Qu.:0.0000   Class :character  
 Median :0.000   Median :0.0000   Mode  :character  
 Mean   :0.523   Mean   :0.3816                     
 3rd Qu.:1.000   3rd Qu.:0.0000                     
 Max.   :8.000   Max.   :6.0000                     
                                                    
      Fare           Cabin             Embarked        
 Min.   :  0.00   Length:891         Length:891        
 1st Qu.:  7.91   Class :character   Class :character  
 Median : 14.45   Mode  :character   Mode  :character  
 Mean   : 32.20                                        
 3rd Qu.: 31.00                                        
 Max.   :512.33                                        
                                                       

Above shown is the descriptive analysis of the data.

str(Titanic_data1)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   891 obs. of  12 variables:
 $ PassengerId: num  1 2 3 4 5 6 7 8 9 10 ...
 $ Survived   : num  0 1 1 1 0 0 0 0 1 1 ...
 $ Pclass     : num  3 1 3 1 3 3 1 3 3 2 ...
 $ Name       : chr  "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...
 $ Sex        : chr  "male" "female" "female" "female" ...
 $ Age        : num  22 38 26 35 35 NA 54 2 27 14 ...
 $ SibSp      : num  1 1 0 1 0 0 0 3 0 1 ...
 $ Parch      : num  0 0 0 0 0 0 0 1 2 0 ...
 $ Ticket     : chr  "A/5 21171" "PC 17599" "STON/O2. 3101282" "113803" ...
 $ Fare       : num  7.25 71.28 7.92 53.1 8.05 ...
 $ Cabin      : chr  NA "C85" NA "C123" ...
 $ Embarked   : chr  "S" "C" "S" "S" ...

Table above shows the structure of the data, which tells that ticket name ,sex,embarked,cabin are character class and the rest are numeric.

#checking for the null values
colSums(is.na(Titanic_data1))
PassengerId    Survived      Pclass        Name         Sex 
          0           0           0           0           0 
        Age       SibSp       Parch      Ticket        Fare 
        177           0           0           0           0 
      Cabin    Embarked 
        687           2 

Anove table shows that Age is having 117 null values ,Cabin is having 687 and embarked is having 2 null values ,so we havde to treat the null values.

#treating null values
#removing cabin
Titanic_data1=Titanic_data1[,-11]
#removing null values
Titanic_data1=na.omit(Titanic_data1)

As the cabin coloumn is having a lot of null values (greater than 50%) , we removed cabin from our data and for null values in age and embarked we just omit the null values.

#graphical visualization of the data
library(ggplot2)
Registered S3 method overwritten by 'dplyr':
  method           from
  print.rowwise_df     
gr_titanic=Titanic_data1
gr_titanic$Survived=factor(gr_titanic$Survived)
qplot(Age,data = gr_titanic,geom = "density",fill=Survived,alpha=I(.7),main = "distribution of age",xlab = "Age",ylab = "density",na.rm=TRUE)

Density plot showing the people of different age survived.

# scatter plot
qplot(Age,Age,data=gr_titanic,shape=Survived,color=Survived,facets = Pclass~Sex,size=I(2),main = "survival scatterplot",na.rm=TRUE)

Above graph showing the male and female survived according to age.

#boxplot
gr_titanic$Age[is.na(gr_titanic$Age)]=mean(gr_titanic$Age,na.rm = TRUE)
ggplot(gr_titanic,aes(Age,Age,fill=Survived,na.rm=TRUE),na.rm=TRUE)+geom_boxplot()

Descriptive analysis of Age. Now moving over to analysis of our titanic data.

1)First we have to split the data into train and test data.

2)Creating a model or logistics equation for the suiting the data,considering survived as a dependent variable and rest as independent variable.

#removing some undesired variables
Titanic_data11=Titanic_data1[,-1]
Titanic_data11=Titanic_data11[,-3]
Titanic_data21=Titanic_data11[,-7]
Titanic_data3=Titanic_data21[,-7]
Titanic_data3

Now moving over to analysis of our titanic data.

1)First we have to split the data into train and test data.

2)Creating a model or logistics equation for the suiting the data,considering survived as a dependent variable and rest as independent variable.

#spliting the data using catools library
library(caTools)
split_ti=sample.split(Titanic_data3,SplitRatio = 0.7)
split_ti
[1]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE
Titanic_data3
train_ti=subset(Titanic_data3,split_ti=="TRUE")
Length of logical index must be 1 or 712, not 7
test_ti=subset(Titanic_data3,split_ti=="FALSE")
Length of logical index must be 1 or 712, not 7
#creating glm model
model_ti=glm(Survived~.,data = train_ti,family = binomial(link = "logit"))
summary(model_ti)

Call:
glm(formula = Survived ~ ., family = binomial(link = "logit"), 
    data = train_ti)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-2.6460  -0.6327  -0.4258   0.6290   2.3769  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  5.55703    0.73871   7.523 5.37e-14 ***
Pclass      -1.17220    0.19035  -6.158 7.36e-10 ***
Sexmale     -2.62834    0.29128  -9.023  < 2e-16 ***
Age         -0.04541    0.01090  -4.165 3.11e-05 ***
SibSp       -0.20302    0.16397  -1.238    0.216    
Parch       -0.10820    0.14960  -0.723    0.470    
EmbarkedQ   -0.38294    0.71954  -0.532    0.595    
EmbarkedS   -0.40457    0.36088  -1.121    0.262    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 544.48  on 405  degrees of freedom
Residual deviance: 364.98  on 398  degrees of freedom
AIC: 380.98

Number of Fisher Scoring iterations: 5

As from the above table,we came to know that according to p-value all the independent variables are significant but since in logistics regression not only p-value is considered but also we have to see the residual error and AIC.

#creating model with different variables for reducing residual error and accuracy
model_ti1=glm(Survived~.-Parch ,data = train_ti,family = binomial(link = "logit"))
summary(model_ti1)#though excluding sex led to increase in the value of residual error and AIC we are not omiting it

Call:
glm(formula = Survived ~ . - Parch, family = binomial(link = "logit"), 
    data = train_ti)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-2.6964  -0.6376  -0.4207   0.6434   2.3884  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  5.52434    0.73755   7.490 6.88e-14 ***
Pclass      -1.18280    0.19047  -6.210 5.31e-10 ***
Sexmale     -2.57598    0.28087  -9.171  < 2e-16 ***
Age         -0.04582    0.01090  -4.203 2.63e-05 ***
SibSp       -0.23574    0.15813  -1.491    0.136    
EmbarkedQ   -0.37711    0.71518  -0.527    0.598    
EmbarkedS   -0.40571    0.36054  -1.125    0.260    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 544.48  on 405  degrees of freedom
Residual deviance: 365.52  on 399  degrees of freedom
AIC: 379.52

Number of Fisher Scoring iterations: 5
model_ti2=glm(Survived~.-Embarked,data = train_ti,family = "binomial")
summary(model_ti2)

Call:
glm(formula = Survived ~ . - Embarked, family = "binomial", data = train_ti)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-2.6972  -0.6423  -0.4261   0.6256   2.3674  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)    
(Intercept)  5.35726    0.70860   7.560 4.02e-14 ***
Pclass      -1.22952    0.18331  -6.707 1.98e-11 ***
Sexmale     -2.62681    0.28889  -9.093  < 2e-16 ***
Age         -0.04568    0.01086  -4.208 2.58e-05 ***
SibSp       -0.20795    0.16355  -1.271    0.204    
Parch       -0.10888    0.14925  -0.730    0.466    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 544.48  on 405  degrees of freedom
Residual deviance: 366.23  on 400  degrees of freedom
AIC: 378.23

Number of Fisher Scoring iterations: 5

Now we get to know that after removing Parch AIC is reducing but after removing embarked value AIC and BIC are increased so we have to exclude parch only from our mode and hence “model_ti1” is best model for prediction .

pred_ti1=predict(model_ti1,test_ti,type = "response")
head(pred_ti1)
         1          2          3          4          5          6 
0.59358923 0.89053948 0.06852521 0.75973102 0.78211895 0.12761505 

above data shows the prediction in probablity, which is not understandable,So for better undertanding we are making a table for prediction and actual value.

#confusion matrix
table_ti=table(actualvalue=test_ti$Survived,predictedvalue=pred_ti1>0.5)
table_ti
           predictedvalue
actualvalue FALSE TRUE
          0   155   23
          1    34   94

from above confusion matrix shows the number of values truely predicted and falsely predicted

A11=TRUE NEGATIVE (truely predicted as “not survived” )

A22=TRUE POSITIVE (truely predicted as “survived”)

A12=FALSE POSITIVE (falsely predicted as “survived”)

A21=FALSE NEGATIVE (falsely predicted as “not survived”)

Now based on the set threshold we have to check its accuracy and find the best threshold value for max accuracy.

#determining accuracy of the prediction
acc=sum(diag(table_ti))/sum(table_ti)
print(paste("Accuracy of prediction =",acc*100,"%"))
[1] "Accuracy of prediction = 81.3725490196078 %"
#since accuracy is 80% we can increase it by selecting optimal threshold
library(ROCR)
Loading required package: gplots

Attaching package: 㤼㸱gplots㤼㸲

The following object is masked from 㤼㸱package:stats㤼㸲:

    lowess
rocr_ti=prediction(pred_ti1,test_ti$Survived)
rocr_ti_per=performance(rocr_ti,"acc")
rocr_ti_per1=performance(rocr_ti,"tpr","fpr")
plot(rocr_ti_per1,colorize=TRUE)

from the above chart we can say that threshold must b in between 0.6to0.8. So again we are making table by setting threshold in between 0.5to0.6.

table_ti1=table(actualvalue=test_ti$Survived,predictedvalue=pred_ti1>0.60)
table_ti1
           predictedvalue
actualvalue FALSE TRUE
          0   162   16
          1    42   86
accuracy_ti1=sum(diag(table_ti1))/sum(table_ti1)
print(paste("Accuracy of prediction =",round(accuracy_ti1*100),"%"))
[1] "Accuracy of prediction = 81 %"

So the accuracy of pprediction is 83% with threshold optimal 0.60.

Now can see the table in graphical view.

plot(table_ti1,col=c("red","green"))

The graph represents the table in the graphical view showing green(predicted as “survived”) and red(predicted as “died”)

ggplot(train_ti,aes(x=Pclass,y=Survived))+geom_point()+stat_smooth(method = "glm",method.args = list(family="binomial"),se=TRUE)

This graph shows that passenger in higher pclass are having more chances of survival.

CONCLUSION: So our model is predicting survival with the accurace of 81%.

LS0tDQp0aXRsZTogIlN1cnZpdmFsIEFuYWx5c2lzIHdpdGggVGl0YW5pYyBkYXRhIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NClN1cnZpdmFsIGFuYWx5c2lzIGlzIHVzZWQgdG8gcHJlZGljdCB0aGUgc3Vydml2YWwgb2YgYSBwZXJzb24sd2l0aCByZXNwZWN0IHRvICB2YXJpYWJsZXMuIA0KDQpgYGB7cn0NClRpdGFuaWNfZGF0YTE9VGl0YW5pYw0KaGVhZChUaXRhbmljX2RhdGExKQ0KDQpgYGANCkFib3ZlIGlzIHRoZSBoZWFkIGRhdGEgd2hpY2ggd2UgYXJlIGdvaW5nIHRvIGFuYWx5emUuDQoNCmBgYHtyfQ0Kc3VtbWFyeShUaXRhbmljX2RhdGExKQ0KYGBgDQpBYm92ZSBzaG93biBpcyB0aGUgZGVzY3JpcHRpdmUgYW5hbHlzaXMgb2YgdGhlIGRhdGEuDQoNCmBgYHtyfQ0Kc3RyKFRpdGFuaWNfZGF0YTEpDQpgYGANClRhYmxlIGFib3ZlIHNob3dzIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGEsIHdoaWNoIHRlbGxzIHRoYXQgdGlja2V0IG5hbWUgLHNleCxlbWJhcmtlZCxjYWJpbiBhcmUgY2hhcmFjdGVyIGNsYXNzIGFuZCB0aGUgcmVzdCBhcmUgbnVtZXJpYy4NCmBgYHtyfQ0KI2NoZWNraW5nIGZvciB0aGUgbnVsbCB2YWx1ZXMNCmNvbFN1bXMoaXMubmEoVGl0YW5pY19kYXRhMSkpDQpgYGANCkFub3ZlIHRhYmxlIHNob3dzIHRoYXQgQWdlIGlzIGhhdmluZyAxMTcgbnVsbCB2YWx1ZXMgLENhYmluIGlzICBoYXZpbmcgNjg3IGFuZCBlbWJhcmtlZCBpcyBoYXZpbmcgMiBudWxsIHZhbHVlcyAsc28gd2UgaGF2ZGUgdG8gdHJlYXQgdGhlIG51bGwgdmFsdWVzLg0KYGBge3J9DQojdHJlYXRpbmcgbnVsbCB2YWx1ZXMNCiNyZW1vdmluZyBjYWJpbg0KVGl0YW5pY19kYXRhMT1UaXRhbmljX2RhdGExWywtMTFdDQojcmVtb3ZpbmcgbnVsbCB2YWx1ZXMNClRpdGFuaWNfZGF0YTE9bmEub21pdChUaXRhbmljX2RhdGExKQ0KYGBgDQpBcyB0aGUgY2FiaW4gY29sb3VtbiBpcyBoYXZpbmcgYSBsb3Qgb2YgbnVsbCB2YWx1ZXMgKGdyZWF0ZXIgdGhhbiA1MCUpICwgd2UgcmVtb3ZlZCBjYWJpbiBmcm9tIG91ciBkYXRhIGFuZCBmb3IgbnVsbCB2YWx1ZXMgaW4gYWdlIGFuZCBlbWJhcmtlZCB3ZSBqdXN0IG9taXQgdGhlIG51bGwgdmFsdWVzLg0KYGBge3J9DQojZ3JhcGhpY2FsIHZpc3VhbGl6YXRpb24gb2YgdGhlIGRhdGENCmxpYnJhcnkoZ2dwbG90MikNCmdyX3RpdGFuaWM9VGl0YW5pY19kYXRhMQ0KZ3JfdGl0YW5pYyRTdXJ2aXZlZD1mYWN0b3IoZ3JfdGl0YW5pYyRTdXJ2aXZlZCkNCnFwbG90KEFnZSxkYXRhID0gZ3JfdGl0YW5pYyxnZW9tID0gImRlbnNpdHkiLGZpbGw9U3Vydml2ZWQsYWxwaGE9SSguNyksbWFpbiA9ICJkaXN0cmlidXRpb24gb2YgYWdlIix4bGFiID0gIkFnZSIseWxhYiA9ICJkZW5zaXR5IixuYS5ybT1UUlVFKQ0KDQpgYGANCkRlbnNpdHkgcGxvdCBzaG93aW5nIHRoZSBwZW9wbGUgb2YgZGlmZmVyZW50IGFnZSBzdXJ2aXZlZC4NCmBgYHtyfSANCiMgc2NhdHRlciBwbG90DQpxcGxvdChBZ2UsQWdlLGRhdGE9Z3JfdGl0YW5pYyxzaGFwZT1TdXJ2aXZlZCxjb2xvcj1TdXJ2aXZlZCxmYWNldHMgPSBQY2xhc3N+U2V4LHNpemU9SSgyKSxtYWluID0gInN1cnZpdmFsIHNjYXR0ZXJwbG90IixuYS5ybT1UUlVFKQ0KYGBgDQpBYm92ZSBncmFwaCBzaG93aW5nIHRoZSBtYWxlIGFuZCBmZW1hbGUgc3Vydml2ZWQgYWNjb3JkaW5nIHRvIGFnZS4NCmBgYHtyfQ0KI2JveHBsb3QNCmdyX3RpdGFuaWMkQWdlW2lzLm5hKGdyX3RpdGFuaWMkQWdlKV09bWVhbihncl90aXRhbmljJEFnZSxuYS5ybSA9IFRSVUUpDQpnZ3Bsb3QoZ3JfdGl0YW5pYyxhZXMoQWdlLEFnZSxmaWxsPVN1cnZpdmVkLG5hLnJtPVRSVUUpLG5hLnJtPVRSVUUpK2dlb21fYm94cGxvdCgpDQpgYGANCkRlc2NyaXB0aXZlIGFuYWx5c2lzIG9mIEFnZS4NCk5vdyBtb3Zpbmcgb3ZlciB0byBhbmFseXNpcyBvZiBvdXIgdGl0YW5pYyBkYXRhLg0KDQoxKUZpcnN0IHdlIGhhdmUgdG8gc3BsaXQgdGhlIGRhdGEgaW50byB0cmFpbiBhbmQgdGVzdCBkYXRhLg0KDQoyKUNyZWF0aW5nIGEgbW9kZWwgb3IgbG9naXN0aWNzIGVxdWF0aW9uIGZvciB0aGUgc3VpdGluZyB0aGUgZGF0YSxjb25zaWRlcmluZyBzdXJ2aXZlZCBhcyBhIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgcmVzdCBhcyBpbmRlcGVuZGVudCB2YXJpYWJsZS4NCg0KYGBge3J9DQojcmVtb3Zpbmcgc29tZSB1bmRlc2lyZWQgdmFyaWFibGVzDQpUaXRhbmljX2RhdGExMT1UaXRhbmljX2RhdGExWywtMV0NClRpdGFuaWNfZGF0YTExPVRpdGFuaWNfZGF0YTExWywtM10NClRpdGFuaWNfZGF0YTIxPVRpdGFuaWNfZGF0YTExWywtN10NClRpdGFuaWNfZGF0YTM9VGl0YW5pY19kYXRhMjFbLC03XQ0KVGl0YW5pY19kYXRhMw0KYGBgDQpOb3cgbW92aW5nIG92ZXIgdG8gYW5hbHlzaXMgb2Ygb3VyIHRpdGFuaWMgZGF0YS4NCg0KMSlGaXJzdCB3ZSBoYXZlIHRvIHNwbGl0IHRoZSBkYXRhIGludG8gdHJhaW4gYW5kIHRlc3QgZGF0YS4NCg0KMilDcmVhdGluZyBhIG1vZGVsIG9yIGxvZ2lzdGljcyBlcXVhdGlvbiBmb3IgdGhlIHN1aXRpbmcgdGhlIGRhdGEsY29uc2lkZXJpbmcgc3Vydml2ZWQgYXMgYSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIHJlc3QgYXMgaW5kZXBlbmRlbnQgdmFyaWFibGUuDQpgYGB7cn0NCiNzcGxpdGluZyB0aGUgZGF0YSB1c2luZyBjYXRvb2xzIGxpYnJhcnkNCmxpYnJhcnkoY2FUb29scykNCnNwbGl0X3RpPXNhbXBsZS5zcGxpdChUaXRhbmljX2RhdGEzLFNwbGl0UmF0aW8gPSAwLjcpDQpzcGxpdF90aQ0KVGl0YW5pY19kYXRhMw0KdHJhaW5fdGk9c3Vic2V0KFRpdGFuaWNfZGF0YTMsc3BsaXRfdGk9PSJUUlVFIikNCnRlc3RfdGk9c3Vic2V0KFRpdGFuaWNfZGF0YTMsc3BsaXRfdGk9PSJGQUxTRSIpDQojY3JlYXRpbmcgZ2xtIG1vZGVsDQptb2RlbF90aT1nbG0oU3Vydml2ZWR+LixkYXRhID0gdHJhaW5fdGksZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpKQ0Kc3VtbWFyeShtb2RlbF90aSkNCmBgYA0KQXMgZnJvbSB0aGUgYWJvdmUgdGFibGUsd2UgY2FtZSB0byBrbm93IHRoYXQgYWNjb3JkaW5nIHRvIHAtdmFsdWUgYWxsIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgYXJlIHNpZ25pZmljYW50IGJ1dCBzaW5jZSBpbiBsb2dpc3RpY3MgcmVncmVzc2lvbiBub3Qgb25seSBwLXZhbHVlIGlzIGNvbnNpZGVyZWQgYnV0IGFsc28gd2UgaGF2ZSB0byBzZWUgdGhlIHJlc2lkdWFsIGVycm9yIGFuZCBBSUMuIA0KYGBge3J9DQojY3JlYXRpbmcgbW9kZWwgd2l0aCBkaWZmZXJlbnQgdmFyaWFibGVzIGZvciByZWR1Y2luZyByZXNpZHVhbCBlcnJvciBhbmQgYWNjdXJhY3kNCm1vZGVsX3RpMT1nbG0oU3Vydml2ZWR+Li1QYXJjaCAsZGF0YSA9IHRyYWluX3RpLGZhbWlseSA9IGJpbm9taWFsKGxpbmsgPSAibG9naXQiKSkNCnN1bW1hcnkobW9kZWxfdGkxKSN0aG91Z2ggZXhjbHVkaW5nIHNleCBsZWQgdG8gaW5jcmVhc2UgaW4gdGhlIHZhbHVlIG9mIHJlc2lkdWFsIGVycm9yIGFuZCBBSUMgd2UgYXJlIG5vdCBvbWl0aW5nIGl0DQptb2RlbF90aTI9Z2xtKFN1cnZpdmVkfi4tRW1iYXJrZWQsZGF0YSA9IHRyYWluX3RpLGZhbWlseSA9ICJiaW5vbWlhbCIpDQpzdW1tYXJ5KG1vZGVsX3RpMikNCg0KYGBgDQpOb3cgd2UgZ2V0IHRvIGtub3cgdGhhdCBhZnRlciByZW1vdmluZyBQYXJjaCBBSUMgaXMgcmVkdWNpbmcgYnV0IGFmdGVyIHJlbW92aW5nIGVtYmFya2VkIHZhbHVlIEFJQyBhbmQgQklDIGFyZSBpbmNyZWFzZWQgc28gd2UgaGF2ZSB0byBleGNsdWRlIHBhcmNoIG9ubHkgZnJvbSBvdXIgbW9kZSBhbmQgaGVuY2UgIm1vZGVsX3RpMSIgaXMgYmVzdCBtb2RlbCBmb3IgcHJlZGljdGlvbiAuDQpgYGB7cn0NCnByZWRfdGkxPXByZWRpY3QobW9kZWxfdGkxLHRlc3RfdGksdHlwZSA9ICJyZXNwb25zZSIpDQpoZWFkKHByZWRfdGkxKQ0KYGBgDQphYm92ZSBkYXRhIHNob3dzIHRoZSBwcmVkaWN0aW9uIGluIHByb2JhYmxpdHksIHdoaWNoIGlzIG5vdCB1bmRlcnN0YW5kYWJsZSxTbyBmb3IgYmV0dGVyIHVuZGVydGFuZGluZyB3ZSBhcmUgbWFraW5nIGEgdGFibGUgZm9yIHByZWRpY3Rpb24gYW5kIGFjdHVhbCB2YWx1ZS4NCmBgYHtyfQ0KI2NvbmZ1c2lvbiBtYXRyaXgNCnRhYmxlX3RpPXRhYmxlKGFjdHVhbHZhbHVlPXRlc3RfdGkkU3Vydml2ZWQscHJlZGljdGVkdmFsdWU9cHJlZF90aTE+MC41KQ0KdGFibGVfdGkNCmBgYA0KZnJvbSBhYm92ZSBjb25mdXNpb24gbWF0cml4IHNob3dzIHRoZSBudW1iZXIgb2YgdmFsdWVzIHRydWVseSBwcmVkaWN0ZWQgYW5kIGZhbHNlbHkgcHJlZGljdGVkDQoNCkExMT1UUlVFIE5FR0FUSVZFICh0cnVlbHkgcHJlZGljdGVkIGFzICJub3Qgc3Vydml2ZWQiICkNCg0KQTIyPVRSVUUgUE9TSVRJVkUgKHRydWVseSBwcmVkaWN0ZWQgYXMgInN1cnZpdmVkIikNCg0KQTEyPUZBTFNFIFBPU0lUSVZFIChmYWxzZWx5IHByZWRpY3RlZCBhcyAic3Vydml2ZWQiKQ0KDQpBMjE9RkFMU0UgTkVHQVRJVkUgKGZhbHNlbHkgcHJlZGljdGVkIGFzICJub3Qgc3Vydml2ZWQiKQ0KDQpOb3cgYmFzZWQgb24gdGhlIHNldCB0aHJlc2hvbGQgd2UgaGF2ZSB0byBjaGVjayBpdHMgYWNjdXJhY3kgYW5kIGZpbmQgdGhlIGJlc3QgdGhyZXNob2xkIHZhbHVlIGZvciBtYXggYWNjdXJhY3kuDQpgYGB7cn0NCiNkZXRlcm1pbmluZyBhY2N1cmFjeSBvZiB0aGUgcHJlZGljdGlvbg0KYWNjPXN1bShkaWFnKHRhYmxlX3RpKSkvc3VtKHRhYmxlX3RpKQ0KcHJpbnQocGFzdGUoIkFjY3VyYWN5IG9mIHByZWRpY3Rpb24gPSIsYWNjKjEwMCwiJSIpKQ0KDQpgYGANCmBgYHtyfQ0KI3NpbmNlIGFjY3VyYWN5IGlzIDgwJSB3ZSBjYW4gaW5jcmVhc2UgaXQgYnkgc2VsZWN0aW5nIG9wdGltYWwgdGhyZXNob2xkDQpsaWJyYXJ5KFJPQ1IpDQpyb2NyX3RpPXByZWRpY3Rpb24ocHJlZF90aTEsdGVzdF90aSRTdXJ2aXZlZCkNCnJvY3JfdGlfcGVyPXBlcmZvcm1hbmNlKHJvY3JfdGksImFjYyIpDQpyb2NyX3RpX3BlcjE9cGVyZm9ybWFuY2Uocm9jcl90aSwidHByIiwiZnByIikNCnBsb3Qocm9jcl90aV9wZXIxLGNvbG9yaXplPVRSVUUpDQpgYGANCg0KZnJvbSB0aGUgYWJvdmUgY2hhcnQgd2UgY2FuIHNheSB0aGF0IHRocmVzaG9sZCBtdXN0IGIgaW4gYmV0d2VlbiAwLjZ0bzAuOC4NClNvIGFnYWluIHdlIGFyZSBtYWtpbmcgdGFibGUgYnkgc2V0dGluZyB0aHJlc2hvbGQgaW4gYmV0d2VlbiAwLjV0bzAuNi4NCmBgYHtyfQ0KdGFibGVfdGkxPXRhYmxlKGFjdHVhbHZhbHVlPXRlc3RfdGkkU3Vydml2ZWQscHJlZGljdGVkdmFsdWU9cHJlZF90aTE+MC42MCkNCnRhYmxlX3RpMQ0KYWNjdXJhY3lfdGkxPXN1bShkaWFnKHRhYmxlX3RpMSkpL3N1bSh0YWJsZV90aTEpDQpwcmludChwYXN0ZSgiQWNjdXJhY3kgb2YgcHJlZGljdGlvbiA9Iixyb3VuZChhY2N1cmFjeV90aTEqMTAwKSwiJSIpKQ0KYGBgDQpTbyB0aGUgYWNjdXJhY3kgb2YgcHByZWRpY3Rpb24gaXMgODMlIHdpdGggdGhyZXNob2xkIG9wdGltYWwgMC42MC4NCg0KTm93IGNhbiBzZWUgdGhlIHRhYmxlIGluIGdyYXBoaWNhbCB2aWV3Lg0KYGBge3J9DQpwbG90KHRhYmxlX3RpMSxjb2w9YygicmVkIiwiZ3JlZW4iKSkNCmBgYA0KVGhlIGdyYXBoIHJlcHJlc2VudHMgdGhlIHRhYmxlIGluIHRoZSBncmFwaGljYWwgdmlldyBzaG93aW5nIGdyZWVuKHByZWRpY3RlZCBhcyAic3Vydml2ZWQiKSBhbmQgcmVkKHByZWRpY3RlZCBhcyAiZGllZCIpDQpgYGB7cn0NCmdncGxvdCh0cmFpbl90aSxhZXMoeD1QY2xhc3MseT1TdXJ2aXZlZCkpK2dlb21fcG9pbnQoKStzdGF0X3Ntb290aChtZXRob2QgPSAiZ2xtIixtZXRob2QuYXJncyA9IGxpc3QoZmFtaWx5PSJiaW5vbWlhbCIpLHNlPVRSVUUpDQpgYGANClRoaXMgZ3JhcGggc2hvd3MgdGhhdCBwYXNzZW5nZXIgaW4gaGlnaGVyIHBjbGFzcyBhcmUgaGF2aW5nIG1vcmUgY2hhbmNlcyBvZiBzdXJ2aXZhbC4NCg0KQ09OQ0xVU0lPTjoNClNvIG91ciBtb2RlbCBpcyBwcmVkaWN0aW5nIHN1cnZpdmFsIHdpdGggdGhlIGFjY3VyYWNlIG9mIDgxJS4NCg0K