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=