First we will download the dataset from the Kaggle Website. The dataset are train.csv and test.csv.

Now we set the directory to the directory folder

setwd("C:/Users/la5w7/Desktop/Spring 2018/CS-5565-Intro-to-Statistical-Learning/Project")

Now I can read the csv file.

titanic.train <-read.csv(file="train.csv",stringsAsFactors = FALSE,header = TRUE)

Here we have used the stringAsFactors = FALSE as we want to do some manupulation on the dataset whereas by deafult the R will transform that dataset into dataframe and convert all strings into categories. We do not want that we will do some manupulation on the dataset.

We will the methodology that we will combine the dataset both in one file and clean them together rather than cleaning the train and test seperately.

str(titanic.test)
'data.frame':   418 obs. of  11 variables:
 $ PassengerId: int  892 893 894 895 896 897 898 899 900 901 ...
 $ Pclass     : int  3 3 2 3 3 3 3 2 3 3 ...
 $ Name       : chr  "Kelly, Mr. James" "Wilkes, Mrs. James (Ellen Needs)" "Myles, Mr. Thomas Francis" "Wirz, Mr. Albert" ...
 $ Sex        : chr  "male" "female" "male" "male" ...
 $ Age        : num  34.5 47 62 27 22 14 30 26 18 21 ...
 $ SibSp      : int  0 1 0 0 1 0 0 1 0 2 ...
 $ Parch      : int  0 0 0 0 1 0 0 1 0 0 ...
 $ Ticket     : chr  "330911" "363272" "240276" "315154" ...
 $ Fare       : num  7.83 7 9.69 8.66 12.29 ...
 $ Cabin      : chr  "" "" "" "" ...
 $ Embarked   : chr  "Q" "S" "Q" "S" ...

you can see the survival is missing. So the aim of this project is to train the model of the dataset train and then apply that model on test dataset and compare the results with the dataset given and find the accuracy of our model.

Now we will combine the both files and clean the data. You can do the cleaning on both the test and train data alone.

After cleaning the data we will sepreate the data set again into train and test.

Now will make sure that number of columns on both dataset is equal.

names(titanic.train)
 [1] "PassengerId" "Survived"    "Pclass"      "Name"        "Sex"        
 [6] "Age"         "SibSp"       "Parch"       "Ticket"      "Fare"       
[11] "Cabin"       "Embarked"    "IsTrainSet" 
ncol(titanic.train)
[1] 13
names(titanic.test)
 [1] "PassengerId" "Pclass"      "Name"        "Sex"         "Age"        
 [6] "SibSp"       "Parch"       "Ticket"      "Fare"        "Cabin"      
[11] "Embarked"    "IsTrainSet" 
ncol(titanic.test)

So we will add column Survived in the test so that the number and name of both test and train be equal.

Now we will combined both dataset

Later we will split the data into train and test again. Now we will clean the data by filling out the empty details.

table(titanic.full$Embarked)

      C   Q   S 
  2 270 123 914 

so there are three types. C Q and S (which also mode). Let first make a filter where can find the empty values and fill those values with S.

titanic.full[titanic.full$Embarked=='',"Embarked"]<-'S'

Now if we table again the Embarked column we should not get any missing values. Now look at the age

table(is.na(titanic.full$Age))

FALSE  TRUE 
 1046   263 

We can see that there are 263 values are missing. We will find the mean of the age values and then replace the missing age values with mean of ages column.

Now if we see the missing values of Age colum we will not be able to see any missing values.

table(is.na(titanic.full$Age))

FALSE 
 1309 

There is another colum having missing values, that is Fare column.

table(is.na(titanic.full$Fare))

FALSE 
 1309 

Before splitting the data we will factorize the things

Now we will split the data back in train and test dataset.

So now we will factor the Survived column also

titanic.train$Survived <- as.factor(titanic.train$Survived)

so this shows that this is supervized binary classification prediction problem. Let first do the random forest model.

Now we will apply the model on the train dataset.

titanic.model <- randomForest(formula = survived.formula, data = titanic.train, ntree = 500, mtry = 3, nodesize = 0.01 * nrow(titanic.test))
The response has five or fewer unique values.  Are you sure you want to do regression?

Now we will apply model to the test dataset.

write.csv(output.df, file = "kaggle_submission.csv", row.name = FALSE)
Error in write.table(output.df, file = "kaggle_submission.csv", row.name = FALSE,  : 
  'col.names = NA' makes no sense when 'row.names = FALSE'

Since Kaggle want the answer to submit in the particular format in which there are two columns. PassengerId and Survived.

Now we will find predictive model for missing data. For Fare we will make a regression model

setwd("C:/Users/la5w7/Desktop/Spring 2018/CS-5565-Intro-to-Statistical-Learning/Project")
titanic.train <-read.csv(file="train.csv",stringsAsFactors = FALSE)
titanic.test <-read.csv(file="test.csv",stringsAsFactors = FALSE)
#str(titanic.test)
titanic.train$IsTrainSet <- TRUE
titanic.test$IsTrainSet <- FALSE
#names(titanic.train)
#ncol(titanic.train)
#names(titanic.test)
#ncol(titanic.test)
titanic.test$Survived <- NA
titanic.full <- rbind(titanic.train, titanic.test)
titanic.full[titanic.full$Embarked=='',"Embarked"]<-'S'
titanic.full$Pclass <- as.factor(titanic.full$Pclass)
titanic.full$Sex <- as.factor(titanic.full$Sex)
titanic.full$Embarked <- as.factor(titanic.full$Embarked)

First let check how many missing values are there in Fare. First let see the boxplot and see how many values are out of box

So we can see that there are lot of values which are outlined. So will get that data from boxplot.stat

boxplot.stats(titanic.full$Fare)$stats[5]
[1] 65

and make a filter as outlier.filter <-

now we will predict the values of fare accroding to the model trained for Fare prediction based on fare.equation.

titanic.full[is.na(titanic.full$Fare),"Fare"]
numeric(0)

Now we will make regression model for age prediction

boxplot(titanic.full$Age)

upper.whisker <- boxplot.stats(titanic.full$Age)$stats[5]
age.mean <- mean(titanic.full$Age, na.rm = TRUE)
titanic.full[is.na(titanic.full$Age),"Age"] <-age.mean
outlier.filter<- titanic.full$Age < upper.whisker
titanic.full[outlier.filter,]
age.equation = "Age ~ Pclass + Sex +  SibSp + Parch + Fare + Embarked"
age.model <- lm(formula = age.equation, data = titanic.full[outlier.filter,])
age.row <- titanic.full[is.na(titanic.full$Age),c("Pclass", "Sex" ,"SibSp","Parch","Fare","Embarked")]
age.predictions <-predict(age.model,newdata = age.row)
titanic.full[is.na(titanic.full$Age),"Fare"] <- age.predictions
titanic.train <-titanic.full[titanic.full$IsTrainSet == TRUE, ]
titanic.test <-titanic.full[titanic.full$IsTrainSet == FALSE, ]
titanic.train$Survived <- as.factor(titanic.train$Survived)
survived.equation <- "Survived ~ Pclass + Sex + Age + SibSp + Parch + Fare + Embarked "
survived.formula <- as.formula(survived.equation)
#install.packages("randomForest")
library(randomForest)
package <U+393C><U+3E31>randomForest<U+393C><U+3E32> was built under R version 3.4.4randomForest 4.6-14
Type rfNews() to see new features/changes/bug fixes.
titanic.model <- randomForest(formula = survived.formula, data = titanic.train, ntree = 500, mtry = 3, nodesize = 0.01 * nrow(titanic.test))
features.equation <- "Pclass + Sex + Age + SibSp + Parch +Fare +Embarked"
Survived <- predict(titanic.model, newdata = titanic.test)
PassengerId <- titanic.test$PassengerId
output.df <- as.data.frame(PassengerId)
output.df$Survived <- Survived
write.csv(output.df, file = "kaggle_submission1.csv", row.names = FALSE)
LS0tDQp0aXRsZTogIlByb2plY3QtIENTNTU2NS0gU3Vydml2YWwgb2YgVGl0YW5pYyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCg0KRmlyc3Qgd2Ugd2lsbCBkb3dubG9hZCB0aGUgZGF0YXNldCBmcm9tIHRoZSBbS2FnZ2xlIFdlYnNpdGVdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vYy90aXRhbmljKS4gVGhlIGRhdGFzZXQgYXJlICp0cmFpbi5jc3YqIGFuZCAqdGVzdC5jc3YqLiANCg0KTm93IHdlIHNldCB0aGUgZGlyZWN0b3J5IHRvIHRoZSBkaXJlY3RvcnkgZm9sZGVyDQpgYGB7cn0NCnNldHdkKCJDOi9Vc2Vycy9sYTV3Ny9EZXNrdG9wL1NwcmluZyAyMDE4L0NTLTU1NjUtSW50cm8tdG8tU3RhdGlzdGljYWwtTGVhcm5pbmcvUHJvamVjdCIpDQpgYGANCg0KTm93IEkgY2FuIHJlYWQgdGhlIGNzdiBmaWxlLg0KDQpgYGB7cn0NCnRpdGFuaWMudHJhaW4gPC1yZWFkLmNzdihmaWxlPSJ0cmFpbi5jc3YiLHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSxoZWFkZXIgPSBUUlVFKQ0KdGl0YW5pYy50ZXN0IDwtcmVhZC5jc3YoZmlsZT0idGVzdC5jc3YiLHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSxoZWFkZXIgPSBUUlVFKQ0KYGBgDQoNCkhlcmUgd2UgaGF2ZSB1c2VkIHRoZSBzdHJpbmdBc0ZhY3RvcnMgPSBGQUxTRSBhcyB3ZSB3YW50IHRvIGRvIHNvbWUgbWFudXB1bGF0aW9uIG9uIHRoZSBkYXRhc2V0IHdoZXJlYXMgYnkgZGVhZnVsdCB0aGUgUiB3aWxsIHRyYW5zZm9ybSB0aGF0IGRhdGFzZXQgaW50byBkYXRhZnJhbWUgYW5kIGNvbnZlcnQgYWxsIHN0cmluZ3MgaW50byBjYXRlZ29yaWVzLiBXZSBkbyBub3Qgd2FudCB0aGF0IHdlIHdpbGwgZG8gc29tZSBtYW51cHVsYXRpb24gb24gdGhlIGRhdGFzZXQuDQoNCldlIHdpbGwgdGhlIG1ldGhvZG9sb2d5IHRoYXQgd2Ugd2lsbCBjb21iaW5lIHRoZSBkYXRhc2V0IGJvdGggaW4gb25lIGZpbGUgYW5kIGNsZWFuIHRoZW0gdG9nZXRoZXIgcmF0aGVyIHRoYW4gY2xlYW5pbmcgdGhlIHRyYWluIGFuZCB0ZXN0IHNlcGVyYXRlbHkuICANCg0KYGBge3J9DQpzdHIodGl0YW5pYy50ZXN0KQ0KYGBgDQoNCnlvdSBjYW4gc2VlIHRoZSBzdXJ2aXZhbCBpcyBtaXNzaW5nLg0KU28gdGhlIGFpbSBvZiB0aGlzIHByb2plY3QgaXMgdG8gdHJhaW4gdGhlIG1vZGVsIG9mIHRoZSBkYXRhc2V0IHRyYWluIGFuZCB0aGVuIGFwcGx5IHRoYXQgbW9kZWwgb24gdGVzdCBkYXRhc2V0IGFuZCBjb21wYXJlIHRoZSByZXN1bHRzIHdpdGggdGhlIGRhdGFzZXQgZ2l2ZW4gYW5kIGZpbmQgdGhlIGFjY3VyYWN5IG9mIG91ciBtb2RlbC4gDQoNCk5vdyB3ZSB3aWxsIGNvbWJpbmUgdGhlIGJvdGggZmlsZXMgYW5kIGNsZWFuIHRoZSBkYXRhLiBZb3UgY2FuIGRvIHRoZSBjbGVhbmluZyBvbiBib3RoIHRoZSB0ZXN0IGFuZCB0cmFpbiBkYXRhIGFsb25lLiANCg0KQWZ0ZXIgY2xlYW5pbmcgdGhlIGRhdGEgd2Ugd2lsbCBzZXByZWF0ZSB0aGUgZGF0YSBzZXQgYWdhaW4gaW50byB0cmFpbiBhbmQgdGVzdC4NCg0KYGBge3J9DQp0aXRhbmljLnRyYWluJElzVHJhaW5TZXQgPC0gVFJVRQ0KdGl0YW5pYy50ZXN0JElzVHJhaW5TZXQgPC0gRkFMU0UNCmBgYA0KDQpOb3cgd2lsbCBtYWtlIHN1cmUgdGhhdCBudW1iZXIgb2YgY29sdW1ucyBvbiBib3RoIGRhdGFzZXQgaXMgZXF1YWwuDQpgYGB7cn0NCm5hbWVzKHRpdGFuaWMudHJhaW4pDQpgYGANCg0KYGBge3J9DQpuY29sKHRpdGFuaWMudHJhaW4pDQpgYGANCg0KDQoNCmBgYHtyfQ0KbmFtZXModGl0YW5pYy50ZXN0KQ0KYGBgDQogDQpgYGB7cn0NCm5jb2wodGl0YW5pYy50ZXN0KQ0KYGBgDQoNClNvIHdlIHdpbGwgYWRkIGNvbHVtbiBTdXJ2aXZlZCBpbiB0aGUgdGVzdCBzbyB0aGF0IHRoZSBudW1iZXIgYW5kIG5hbWUgb2YgYm90aCB0ZXN0IGFuZCB0cmFpbiBiZSBlcXVhbC4gDQpgYGB7cn0NCnRpdGFuaWMudGVzdCRTdXJ2aXZlZCA8LSBOQQ0KYGBgDQoNCk5vdyB3ZSB3aWxsIGNvbWJpbmVkIGJvdGggZGF0YXNldCANCg0KYGBge3J9DQp0aXRhbmljLmZ1bGwgPC0gcmJpbmQodGl0YW5pYy50cmFpbiwgdGl0YW5pYy50ZXN0KQ0KYGBgDQoNCkxhdGVyIHdlIHdpbGwgc3BsaXQgdGhlIGRhdGEgaW50byB0cmFpbiBhbmQgdGVzdCBhZ2Fpbi4gTm93IHdlIHdpbGwgY2xlYW4gdGhlIGRhdGEgYnkgZmlsbGluZyBvdXQgdGhlIGVtcHR5IGRldGFpbHMuIA0KYGBge3J9DQp0YWJsZSh0aXRhbmljLmZ1bGwkRW1iYXJrZWQpDQpgYGANCg0Kc28gdGhlcmUgYXJlIHRocmVlIHR5cGVzLiBDIFEgYW5kIFMgKHdoaWNoIGFsc28gbW9kZSkuIExldCBmaXJzdCBtYWtlIGEgZmlsdGVyIHdoZXJlIGNhbiBmaW5kIHRoZSBlbXB0eSB2YWx1ZXMgYW5kIGZpbGwgdGhvc2UgdmFsdWVzIHdpdGggUy4gDQpgYGB7cn0NCnRpdGFuaWMuZnVsbFt0aXRhbmljLmZ1bGwkRW1iYXJrZWQ9PScnLCJFbWJhcmtlZCJdPC0nUycNCmBgYA0KDQpOb3cgaWYgd2UgdGFibGUgYWdhaW4gdGhlIEVtYmFya2VkIGNvbHVtbiB3ZSBzaG91bGQgbm90IGdldCBhbnkgbWlzc2luZyB2YWx1ZXMuIA0KTm93IGxvb2sgYXQgdGhlIGFnZQ0KYGBge3J9DQp0YWJsZShpcy5uYSh0aXRhbmljLmZ1bGwkQWdlKSkNCmBgYA0KDQpXZSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIDI2MyB2YWx1ZXMgYXJlIG1pc3NpbmcuIFdlIHdpbGwgZmluZCB0aGUgbWVhbiBvZiB0aGUgYWdlIHZhbHVlcyBhbmQgdGhlbiByZXBsYWNlIHRoZSBtaXNzaW5nIGFnZSB2YWx1ZXMgd2l0aCBtZWFuIG9mIGFnZXMgY29sdW1uLg0KDQpgYGB7cn0NCmFnZS5tZWFuIDwtIG1lYW4odGl0YW5pYy5mdWxsJEFnZSwgbmEucm0gPSBUUlVFKQ0KdGl0YW5pYy5mdWxsW2lzLm5hKHRpdGFuaWMuZnVsbCRBZ2UpLCJBZ2UiXSA8LWFnZS5tZWFuDQpgYGANCg0KTm93IGlmIHdlIHNlZSB0aGUgbWlzc2luZyB2YWx1ZXMgb2YgQWdlIGNvbHVtIHdlIHdpbGwgbm90IGJlIGFibGUgdG8gc2VlIGFueSBtaXNzaW5nIHZhbHVlcy4gDQpgYGB7cn0NCnRhYmxlKGlzLm5hKHRpdGFuaWMuZnVsbCRBZ2UpKQ0KYGBgDQoNClRoZXJlIGlzIGFub3RoZXIgY29sdW0gaGF2aW5nIG1pc3NpbmcgdmFsdWVzLCB0aGF0IGlzIEZhcmUgY29sdW1uLg0KYGBge3J9DQp0YWJsZShpcy5uYSh0aXRhbmljLmZ1bGwkRmFyZSkpDQpmYXJlLm1lYW4gPC0gbWVhbih0aXRhbmljLmZ1bGwkRmFyZSwgbmEucm0gPSBUUlVFKQ0KdGl0YW5pYy5mdWxsW2lzLm5hKHRpdGFuaWMuZnVsbCRGYXJlKSwiRmFyZSJdIDwtZmFyZS5tZWFuDQoNCmBgYA0KDQpCZWZvcmUgc3BsaXR0aW5nIHRoZSBkYXRhIHdlIHdpbGwgZmFjdG9yaXplIHRoZSB0aGluZ3MNCmBgYHtyfQ0KdGl0YW5pYy5mdWxsJFBjbGFzcyA8LSBhcy5mYWN0b3IodGl0YW5pYy5mdWxsJFBjbGFzcykNCnRpdGFuaWMuZnVsbCRTZXggPC0gYXMuZmFjdG9yKHRpdGFuaWMuZnVsbCRTZXgpDQp0aXRhbmljLmZ1bGwkRW1iYXJrZWQgPC0gYXMuZmFjdG9yKHRpdGFuaWMuZnVsbCRFbWJhcmtlZCkNCmBgYA0KDQoNCk5vdyB3ZSB3aWxsIHNwbGl0IHRoZSBkYXRhIGJhY2sgaW4gdHJhaW4gYW5kIHRlc3QgZGF0YXNldC4gDQpgYGB7cn0NCnRpdGFuaWMudHJhaW4gPC10aXRhbmljLmZ1bGxbdGl0YW5pYy5mdWxsJElzVHJhaW5TZXQgPT0gVFJVRSwgXQ0KdGl0YW5pYy50ZXN0IDwtdGl0YW5pYy5mdWxsW3RpdGFuaWMuZnVsbCRJc1RyYWluU2V0ID09IEZBTFNFLCBdDQpgYGANCg0KU28gbm93IHdlIHdpbGwgZmFjdG9yIHRoZSBTdXJ2aXZlZCBjb2x1bW4gYWxzbyANCmBgYHtyfQ0KdGl0YW5pYy50cmFpbiRTdXJ2aXZlZCA8LSBhcy5mYWN0b3IodGl0YW5pYy50cmFpbiRTdXJ2aXZlZCkNCmBgYA0KDQpzbyB0aGlzIHNob3dzIHRoYXQgdGhpcyBpcyBzdXBlcnZpemVkIGJpbmFyeSBjbGFzc2lmaWNhdGlvbiBwcmVkaWN0aW9uIHByb2JsZW0uDQpMZXQgZmlyc3QgZG8gdGhlIHJhbmRvbSBmb3Jlc3QgbW9kZWwuDQoNCmBgYHtyfSANCnN1cnZpdmVkLmVxdWF0aW9uIDwtICJTdXJ2aXZlZCB+IFBjbGFzcyArIFNleCArIEFnZSArIFNpYlNwICsgUGFyY2ggK0ZhcmUgK0VtYmFya2VkICINCnN1cnZpdmVkLmZvcm11bGEgPC0gYXMuZm9ybXVsYShzdXJ2aXZlZC5lcXVhdGlvbikNCg0KYGBgDQoNCk5vdyB3ZSB3aWxsIGFwcGx5IHRoZSBtb2RlbCBvbiB0aGUgdHJhaW4gZGF0YXNldC4NCmBgYHtyfQ0KaW5zdGFsbC5wYWNrYWdlcygicmFuZG9tRm9yZXN0IikNCmxpYnJhcnkocmFuZG9tRm9yZXN0KQ0KdGl0YW5pYy5tb2RlbCA8LSByYW5kb21Gb3Jlc3QoZm9ybXVsYSA9IHN1cnZpdmVkLmZvcm11bGEsIGRhdGEgPSB0aXRhbmljLnRyYWluLCBudHJlZSA9IDUwMCwgbXRyeSA9IDMsIG5vZGVzaXplID0gMC4wMSAqIG5yb3codGl0YW5pYy50ZXN0KSkNCmBgYA0KDQpOb3cgd2Ugd2lsbCBhcHBseSBtb2RlbCB0byB0aGUgdGVzdCBkYXRhc2V0LiANCmBgYHtyfQ0KZmVhdHVyZXMuZXF1YXRpb24gPC0gIlBjbGFzcyArIFNleCArIEFnZSArIFNpYlNwICsgUGFyY2ggK0ZhcmUgK0VtYmFya2VkIg0KU3Vydml2ZWQgPC0gcHJlZGljdCh0aXRhbmljLm1vZGVsLCBuZXdkYXRhID0gdGl0YW5pYy50ZXN0KQ0KUGFzc2VuZ2VySWQgPC0gdGl0YW5pYy50ZXN0JFBhc3NlbmdlcklkDQpvdXRwdXQuZGYgPC0gYXMuZGF0YS5mcmFtZShQYXNzZW5nZXJJZCkNCm91dHB1dC5kZiRTdXJ2aXZlZCA8LSBTdXJ2aXZlZA0KDQp3cml0ZS5jc3Yob3V0cHV0LmRmLCBmaWxlID0gImthZ2dsZV9zdWJtaXNzaW9uLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KYGBgDQpTaW5jZSBLYWdnbGUgd2FudCB0aGUgYW5zd2VyIHRvIHN1Ym1pdCBpbiB0aGUgcGFydGljdWxhciBmb3JtYXQgaW4gd2hpY2ggdGhlcmUgYXJlIHR3byBjb2x1bW5zLiBQYXNzZW5nZXJJZCBhbmQgU3Vydml2ZWQuIA0KDQpOb3cgd2Ugd2lsbCBmaW5kIHByZWRpY3RpdmUgbW9kZWwgZm9yIG1pc3NpbmcgZGF0YS4gRm9yIEZhcmUgd2Ugd2lsbCBtYWtlIGEgcmVncmVzc2lvbiBtb2RlbA0KDQpgYGB7cn0NCnNldHdkKCJDOi9Vc2Vycy9sYTV3Ny9EZXNrdG9wL1NwcmluZyAyMDE4L0NTLTU1NjUtSW50cm8tdG8tU3RhdGlzdGljYWwtTGVhcm5pbmcvUHJvamVjdCIpDQp0aXRhbmljLnRyYWluIDwtcmVhZC5jc3YoZmlsZT0idHJhaW4uY3N2IixzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQp0aXRhbmljLnRlc3QgPC1yZWFkLmNzdihmaWxlPSJ0ZXN0LmNzdiIsc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KI3N0cih0aXRhbmljLnRlc3QpDQp0aXRhbmljLnRyYWluJElzVHJhaW5TZXQgPC0gVFJVRQ0KdGl0YW5pYy50ZXN0JElzVHJhaW5TZXQgPC0gRkFMU0UNCiNuYW1lcyh0aXRhbmljLnRyYWluKQ0KI25jb2wodGl0YW5pYy50cmFpbikNCiNuYW1lcyh0aXRhbmljLnRlc3QpDQojbmNvbCh0aXRhbmljLnRlc3QpDQp0aXRhbmljLnRlc3QkU3Vydml2ZWQgPC0gTkENCnRpdGFuaWMuZnVsbCA8LSByYmluZCh0aXRhbmljLnRyYWluLCB0aXRhbmljLnRlc3QpDQp0aXRhbmljLmZ1bGxbdGl0YW5pYy5mdWxsJEVtYmFya2VkPT0nJywiRW1iYXJrZWQiXTwtJ1MnDQoNCg0KdGl0YW5pYy5mdWxsJFBjbGFzcyA8LSBhcy5mYWN0b3IodGl0YW5pYy5mdWxsJFBjbGFzcykNCnRpdGFuaWMuZnVsbCRTZXggPC0gYXMuZmFjdG9yKHRpdGFuaWMuZnVsbCRTZXgpDQp0aXRhbmljLmZ1bGwkRW1iYXJrZWQgPC0gYXMuZmFjdG9yKHRpdGFuaWMuZnVsbCRFbWJhcmtlZCkNCg0KYGBgDQoNCkZpcnN0IGxldCBjaGVjayBob3cgbWFueSBtaXNzaW5nIHZhbHVlcyBhcmUgdGhlcmUgaW4gRmFyZS4gRmlyc3QgbGV0IHNlZSB0aGUgYm94cGxvdCBhbmQgc2VlIGhvdyBtYW55IHZhbHVlcyBhcmUgb3V0IG9mIGJveCANCg0KYGBge3J9DQpib3hwbG90KHRpdGFuaWMuZnVsbCRGYXJlKQ0KYGBgDQoNCg0KU28gd2UgY2FuIHNlZSB0aGF0IHRoZXJlIGFyZSBsb3Qgb2YgdmFsdWVzIHdoaWNoIGFyZSBvdXRsaW5lZC4gU28gd2lsbCBnZXQgdGhhdCBkYXRhIGZyb20gYm94cGxvdC5zdGF0DQoNCmBgYHtyfQ0KdXBwZXIud2hpc2tlciA8LSBib3hwbG90LnN0YXRzKHRpdGFuaWMuZnVsbCRGYXJlKSRzdGF0c1s1XQ0KYGBgDQoNCmFuZCBtYWtlIGEgZmlsdGVyIGFzDQpvdXRsaWVyLmZpbHRlciA8LQ0KYGBge3J9DQpvdXRsaWVyLmZpbHRlcjwtIHRpdGFuaWMuZnVsbCRGYXJlIDwgdXBwZXIud2hpc2tlcg0KdGl0YW5pYy5mdWxsW291dGxpZXIuZmlsdGVyLF0NCmZhcmUuZXF1YXRpb24gPSAiRmFyZSB+IFBjbGFzcyArIFNleCArIEFnZSArIFNpYlNwICsgUGFyY2ggKyBFbWJhcmtlZCINCmZhcmUubW9kZWwgPC0gbG0oZm9ybXVsYSA9IGZhcmUuZXF1YXRpb24sIGRhdGEgPSB0aXRhbmljLmZ1bGxbb3V0bGllci5maWx0ZXIsXSkNCmBgYA0KDQpub3cgd2Ugd2lsbCBwcmVkaWN0IHRoZSB2YWx1ZXMgb2YgZmFyZSBhY2Nyb2RpbmcgdG8gdGhlIG1vZGVsIHRyYWluZWQgZm9yIEZhcmUgcHJlZGljdGlvbiBiYXNlZCBvbiBmYXJlLmVxdWF0aW9uLg0KYGBge3J9DQpmYXJlLnJvdyA8LSB0aXRhbmljLmZ1bGxbaXMubmEodGl0YW5pYy5mdWxsJEZhcmUpLGMoIlBjbGFzcyIsICJTZXgiICwiQWdlIiwiU2liU3AiLCJQYXJjaCIsIkVtYmFya2VkIildDQpmYXJlLnByZWRpY3Rpb25zIDwtcHJlZGljdChmYXJlLm1vZGVsLG5ld2RhdGEgPSBmYXJlLnJvdykNCnRpdGFuaWMuZnVsbFtpcy5uYSh0aXRhbmljLmZ1bGwkRmFyZSksIkZhcmUiXSA8LSBmYXJlLnByZWRpY3Rpb25zDQoNCmBgYA0KDQpOb3cgd2Ugd2lsbCBtYWtlIHJlZ3Jlc3Npb24gbW9kZWwgZm9yIGFnZSBwcmVkaWN0aW9uIA0KYGBge3J9DQoNCmJveHBsb3QodGl0YW5pYy5mdWxsJEFnZSkNCnVwcGVyLndoaXNrZXIgPC0gYm94cGxvdC5zdGF0cyh0aXRhbmljLmZ1bGwkQWdlKSRzdGF0c1s1XQ0KDQphZ2UubWVhbiA8LSBtZWFuKHRpdGFuaWMuZnVsbCRBZ2UsIG5hLnJtID0gVFJVRSkNCnRpdGFuaWMuZnVsbFtpcy5uYSh0aXRhbmljLmZ1bGwkQWdlKSwiQWdlIl0gPC1hZ2UubWVhbg0KDQpvdXRsaWVyLmZpbHRlcjwtIHRpdGFuaWMuZnVsbCRBZ2UgPCB1cHBlci53aGlza2VyDQp0aXRhbmljLmZ1bGxbb3V0bGllci5maWx0ZXIsXQ0KDQoNCmFnZS5lcXVhdGlvbiA9ICJBZ2UgfiBQY2xhc3MgKyBTZXggKyAgU2liU3AgKyBQYXJjaCArIEZhcmUgKyBFbWJhcmtlZCINCmFnZS5tb2RlbCA8LSBsbShmb3JtdWxhID0gYWdlLmVxdWF0aW9uLCBkYXRhID0gdGl0YW5pYy5mdWxsW291dGxpZXIuZmlsdGVyLF0pDQphZ2Uucm93IDwtIHRpdGFuaWMuZnVsbFtpcy5uYSh0aXRhbmljLmZ1bGwkQWdlKSxjKCJQY2xhc3MiLCAiU2V4IiAsIlNpYlNwIiwiUGFyY2giLCJGYXJlIiwiRW1iYXJrZWQiKV0NCmFnZS5wcmVkaWN0aW9ucyA8LXByZWRpY3QoYWdlLm1vZGVsLG5ld2RhdGEgPSBhZ2Uucm93KQ0KdGl0YW5pYy5mdWxsW2lzLm5hKHRpdGFuaWMuZnVsbCRBZ2UpLCJGYXJlIl0gPC0gYWdlLnByZWRpY3Rpb25zDQoNCg0KdGl0YW5pYy50cmFpbiA8LXRpdGFuaWMuZnVsbFt0aXRhbmljLmZ1bGwkSXNUcmFpblNldCA9PSBUUlVFLCBdDQp0aXRhbmljLnRlc3QgPC10aXRhbmljLmZ1bGxbdGl0YW5pYy5mdWxsJElzVHJhaW5TZXQgPT0gRkFMU0UsIF0NCg0KdGl0YW5pYy50cmFpbiRTdXJ2aXZlZCA8LSBhcy5mYWN0b3IodGl0YW5pYy50cmFpbiRTdXJ2aXZlZCkNCg0Kc3Vydml2ZWQuZXF1YXRpb24gPC0gIlN1cnZpdmVkIH4gUGNsYXNzICsgU2V4ICsgQWdlICsgU2liU3AgKyBQYXJjaCArIEZhcmUgKyBFbWJhcmtlZCAiDQpzdXJ2aXZlZC5mb3JtdWxhIDwtIGFzLmZvcm11bGEoc3Vydml2ZWQuZXF1YXRpb24pDQoNCiNpbnN0YWxsLnBhY2thZ2VzKCJyYW5kb21Gb3Jlc3QiKQ0KbGlicmFyeShyYW5kb21Gb3Jlc3QpDQp0aXRhbmljLm1vZGVsIDwtIHJhbmRvbUZvcmVzdChmb3JtdWxhID0gc3Vydml2ZWQuZm9ybXVsYSwgZGF0YSA9IHRpdGFuaWMudHJhaW4sIG50cmVlID0gNTAwLCBtdHJ5ID0gMywgbm9kZXNpemUgPSAwLjAxICogbnJvdyh0aXRhbmljLnRlc3QpKQ0KDQpmZWF0dXJlcy5lcXVhdGlvbiA8LSAiUGNsYXNzICsgU2V4ICsgQWdlICsgU2liU3AgKyBQYXJjaCArRmFyZSArRW1iYXJrZWQiDQpTdXJ2aXZlZCA8LSBwcmVkaWN0KHRpdGFuaWMubW9kZWwsIG5ld2RhdGEgPSB0aXRhbmljLnRlc3QpDQpQYXNzZW5nZXJJZCA8LSB0aXRhbmljLnRlc3QkUGFzc2VuZ2VySWQNCm91dHB1dC5kZiA8LSBhcy5kYXRhLmZyYW1lKFBhc3NlbmdlcklkKQ0Kb3V0cHV0LmRmJFN1cnZpdmVkIDwtIFN1cnZpdmVkDQoNCndyaXRlLmNzdihvdXRwdXQuZGYsIGZpbGUgPSAia2FnZ2xlX3N1Ym1pc3Npb24xLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQ0KDQpgYGANCg0KDQo=