#load excel file with rio
UptimeData<- rio::import("/Users/nanaakwasiabayieboateng/Documents/memphisclassesbooks/Time series/Manpower/Uptimebycategories08-29-2017b.xlsx")
# replace white spaces in column names with _
names(UptimeData)<-stringr::str_replace_all(names(UptimeData),"\\s", "_")
UptimeData
UptimeData=UptimeData%>%dplyr::mutate(Month=stringr:: str_sub(`Month-Yr`, 1, 3))%>%mutate_if(is.character,factor)
UptimeData%>%head()
Durability=UptimeData%>%dplyr::filter(`Dur/EBRG`=="Durability")%>%rename(Dur=`Dur/EBRG`)
Durability=na.omit(Durability)
library(h2o)
h2o.init(nthreads = -1, #Number of threads -1 means use all cores on your machine
         max_mem_size = "8G")  #max mem size is the maximum memory to allocate to H2O
 Connection successful!

R is connected to the H2O cluster: 
    H2O cluster uptime:         2 hours 3 minutes 
    H2O cluster version:        3.10.5.3 
    H2O cluster version age:    2 months and 3 days  
    H2O cluster name:           H2O_started_from_R_nanaakwasiabayieboateng_sux705 
    H2O cluster total nodes:    1 
    H2O cluster total memory:   6.87 GB 
    H2O cluster total cores:    8 
    H2O cluster allowed cores:  8 
    H2O cluster healthy:        TRUE 
    H2O Connection ip:          localhost 
    H2O Connection port:        54321 
    H2O Connection proxy:       NA 
    H2O Internal Security:      FALSE 
    R Version:                  R version 3.4.0 (2017-04-21) 
#==========================================================================================================
# import R object to the H2O cloud.
#convert r data to h2o object
#==========================================================================================================
datah20=as.h2o(Durability)

  |                                                                      
  |                                                                |   0%
  |                                                                      
  |================================================================| 100%
#==========================================================================================================
# Partition the data into training, validation and test sets
#==========================================================================================================
splits <- h2o.splitFrame(data = datah20, 
                         ratios = c(0.7, 0.15),  #partition data into 70%, 15%, 15% chunks
                         seed = 1)  #setting a seed will guarantee reproducibility
train <- splits[[1]]
valid <- splits[[2]]
test <- splits[[3]]
# Identify response and predictor variables
y <- "APG_Uptime"
x <- setdiff(names(datah20), y)  
print(x)
[1] "Month-Yr"             "Dur"                  "priority_category_cd"
[4] "build_phase"          "Build_Category"       "Day_of_Week"         
[7] "vehicle_family_ref"   "Month"               
#====================================================================================================================================
# Next we will do some automatic tuning by passing in a validation frame and setting 
# `lambda_search = True`.  Since we are training a GLM with regularization, we should 
# try to find the right amount of regularization (to avoid overfitting).  The model 
# parameter, `lambda`, controls the amount of regularization in a GLM model and we can 
# find the optimal value for `lambda` automatically by setting `lambda_search = TRUE` 
# and passing in a validation frame (which is used to evaluate model performance using a 
# particular value of lambda).
#=====================================================================================================================================
glm_fit2 <- h2o.glm(x = x, 
                    y = y, 
                    training_frame = train,
                    model_id = "glm_fit2",
                    validation_frame = valid,
                    family = "gaussian",
                    lambda_search = TRUE) 
Dropping bad and constant columns: [Dur].

  |                                                                      
  |                                                                |   0%
  |                                                                      
  |===================================                             |  55%
  |                                                                      
  |================================================================| 100%
#==========================================================================================================
# Let's compare the performance of the two GLMs
#==========================================================================================================
glm_perf2 <- h2o.performance(model = glm_fit2,
                             newdata = test)
#==========================================================================================================
# Instead of printing the entire model performance metrics object, 
# it is probably easier to print just the metric that you are interested in comparing.
# Retreive test set AUC
#==========================================================================================================
 
 
glm_fit2@model$validation_metrics 
H2ORegressionMetrics: glm
** Reported on validation data. **

MSE:  0.08187123
RMSE:  0.2861315
MAE:  0.219839
RMSLE:  0.1992424
Mean Residual Deviance :  0.08187123
R^2 :  0.2184632
Null Deviance :13.81938
Null D.o.F. :126
Residual Deviance :10.39765
Residual D.o.F. :79
AIC :140.5792
#============================================================================================
# We will again set `ntrees = 500`, however, this time we will use early stopping in order to 
# prevent overfitting (from too many trees).  All of H2O's algorithms have early stopping available, 
# however early stopping is not enabled by default (with the exception of Deep Learning).  
# There are several parameters that should be used to control early stopping.  The three that are 
# common to all the algorithms are: `stopping_rounds`, `stopping_metric` and `stopping_tolerance`.  
# The stopping metric is the metric by which you'd like to measure performance, and so we will choose 
# AUC here.  The `score_tree_interval` is a parameter specific to the Random Forest model and the GBM.  
# Setting `score_tree_interval = 5` will score the model after every five trees.  The parameters we 
# have set below specify that the model will stop training after there have been three scoring intervals 
# where the AUC has not increased more than 0.0005.  Since we have specified a validation frame, 
# the stopping tolerance will be computed on validation AUC rather than training AUC. 
#===============================================================================================
gbm_fit3 <- h2o.gbm(x = x,
                    y = y,
                    training_frame = train,
                    model_id = "gbm_fit2",
                    #validation_frame = valid,  #only used if stopping_rounds > 0
                    ntrees = 500,
                    seed = 1)
Dropping bad and constant columns: [Dur].

  |                                                                      
  |                                                                |   0%
  |                                                                      
  |==                                                              |   2%
  |                                                                      
  |======================                                          |  34%
  |                                                                      
  |=================================================               |  77%
  |                                                                      
  |================================================================| 100%
#==========================================================================================================
# Let's compare the performance of the two GBMs
#==========================================================================================================
gbm_perf3 <- h2o.performance(model = gbm_fit3,
                             newdata = test)
#==========================================================================================================
# Print model performance
#==========================================================================================================
gbm_perf3
H2ORegressionMetrics: gbm

MSE:  0.07664392
RMSE:  0.2768464
MAE:  0.2075424
RMSLE:  0.1820383
Mean Residual Deviance :  0.07664392
#==========================================================================================================
# Look at scoring history for third GBM model
#==========================================================================================================
plot(gbm_fit3, 
     timestep = "number_of_trees")

#==========================================================================================================
# Train a DL with early stopping
# This example will use the same model parameters as `dl_fit2`. This time, we will turn on 
# early stopping and specify the stopping criterion.  We will also pass a validation set, as is
# recommended for early stopping.
#==========================================================================================================
dl_fit3 <- h2o.deeplearning(x = x,
                            y = y,
                            training_frame = train,
                            model_id = "dl_fit2",
                            #validation_frame = valid,  #only used if stopping_rounds > 0
                            epochs = 20,
                            hidden= c(10,10),
                            stopping_rounds = 0,  # disable early stopping
                            seed = 1) 
Dropping bad and constant columns: [Dur].

  |                                                                      
  |                                                                |   0%
  |                                                                      
  |================================================================| 100%
dl_perf3 <- h2o.performance(model = dl_fit3,
                            newdata = test)
#==========================================================================================================
# Print model performance
#==========================================================================================================
dl_perf3
H2ORegressionMetrics: deeplearning

MSE:  0.07325338
RMSE:  0.2706536
MAE:  0.2157389
RMSLE:  0.1793604
Mean Residual Deviance :  0.07325338
#==========================================================================================================
# Scoring history
#==========================================================================================================
h2o.scoreHistory(dl_fit3)
Scoring History: 
            timestamp   duration training_speed   epochs iterations
1 2017-09-02 19:29:39  0.000 sec                 0.00000          0
2 2017-09-02 19:29:39  0.027 sec 231200 obs/sec  2.00000          1
3 2017-09-02 19:29:39  0.084 sec 214074 obs/sec 20.00000         10
       samples training_rmse training_deviance training_mae
1     0.000000                                             
2  1156.000000       0.28044           0.07865      0.22619
3 11560.000000       0.23176           0.05371      0.18164
#==========================================================================================================
# Look at scoring history for third DL model
#==========================================================================================================
plot(dl_fit3, 
     timestep = "epochs")

LS0tCnRpdGxlOiAiTWFjaGluZSBMZWFybmluZyB3aXRoIEgyMCIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjogTmFuYSBCb2F0ZW5nCi0tLQoKCmBgYHtyfQojbG9hZCBleGNlbCBmaWxlIHdpdGggcmlvClVwdGltZURhdGE8LSByaW86OmltcG9ydCgiL1VzZXJzL25hbmFha3dhc2lhYmF5aWVib2F0ZW5nL0RvY3VtZW50cy9tZW1waGlzY2xhc3Nlc2Jvb2tzL1RpbWUgc2VyaWVzL01hbnBvd2VyL1VwdGltZWJ5Y2F0ZWdvcmllczA4LTI5LTIwMTdiLnhsc3giKQoKIyByZXBsYWNlIHdoaXRlIHNwYWNlcyBpbiBjb2x1bW4gbmFtZXMgd2l0aCBfCgpuYW1lcyhVcHRpbWVEYXRhKTwtc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKG5hbWVzKFVwdGltZURhdGEpLCJcXHMiLCAiXyIpCgpVcHRpbWVEYXRhCgoKVXB0aW1lRGF0YT1VcHRpbWVEYXRhJT4lZHBseXI6Om11dGF0ZShNb250aD1zdHJpbmdyOjogc3RyX3N1YihgTW9udGgtWXJgLCAxLCAzKSklPiVtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLGZhY3RvcikKCgpVcHRpbWVEYXRhJT4laGVhZCgpCgoKRHVyYWJpbGl0eT1VcHRpbWVEYXRhJT4lZHBseXI6OmZpbHRlcihgRHVyL0VCUkdgPT0iRHVyYWJpbGl0eSIpJT4lcmVuYW1lKER1cj1gRHVyL0VCUkdgKQoKCkR1cmFiaWxpdHk9bmEub21pdChEdXJhYmlsaXR5KQoKCmBgYAoKCgoKYGBge3IsbWVzc2FnZT1GQUxTRSx3YXJuaW5nPUZBTFNFfQoKCgpsaWJyYXJ5KGgybykKCmgyby5pbml0KG50aHJlYWRzID0gLTEsICNOdW1iZXIgb2YgdGhyZWFkcyAtMSBtZWFucyB1c2UgYWxsIGNvcmVzIG9uIHlvdXIgbWFjaGluZQogICAgICAgICBtYXhfbWVtX3NpemUgPSAiOEciKSAgI21heCBtZW0gc2l6ZSBpcyB0aGUgbWF4aW11bSBtZW1vcnkgdG8gYWxsb2NhdGUgdG8gSDJPCgojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIGltcG9ydCBSIG9iamVjdCB0byB0aGUgSDJPIGNsb3VkLgojY29udmVydCByIGRhdGEgdG8gaDJvIG9iamVjdAojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKZGF0YWgyMD1hcy5oMm8oRHVyYWJpbGl0eSkKCgojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIFBhcnRpdGlvbiB0aGUgZGF0YSBpbnRvIHRyYWluaW5nLCB2YWxpZGF0aW9uIGFuZCB0ZXN0IHNldHMKIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCnNwbGl0cyA8LSBoMm8uc3BsaXRGcmFtZShkYXRhID0gZGF0YWgyMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICByYXRpb3MgPSBjKDAuNywgMC4xNSksICAjcGFydGl0aW9uIGRhdGEgaW50byA3MCUsIDE1JSwgMTUlIGNodW5rcwogICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEpICAjc2V0dGluZyBhIHNlZWQgd2lsbCBndWFyYW50ZWUgcmVwcm9kdWNpYmlsaXR5CnRyYWluIDwtIHNwbGl0c1tbMV1dCnZhbGlkIDwtIHNwbGl0c1tbMl1dCnRlc3QgPC0gc3BsaXRzW1szXV0KCgojIElkZW50aWZ5IHJlc3BvbnNlIGFuZCBwcmVkaWN0b3IgdmFyaWFibGVzCnkgPC0gIkFQR19VcHRpbWUiCnggPC0gc2V0ZGlmZihuYW1lcyhkYXRhaDIwKSwgeSkgIApwcmludCh4KQoKCmBgYAoKCgpgYGB7cn0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIE5leHQgd2Ugd2lsbCBkbyBzb21lIGF1dG9tYXRpYyB0dW5pbmcgYnkgcGFzc2luZyBpbiBhIHZhbGlkYXRpb24gZnJhbWUgYW5kIHNldHRpbmcgCiMgYGxhbWJkYV9zZWFyY2ggPSBUcnVlYC4gIFNpbmNlIHdlIGFyZSB0cmFpbmluZyBhIEdMTSB3aXRoIHJlZ3VsYXJpemF0aW9uLCB3ZSBzaG91bGQgCiMgdHJ5IHRvIGZpbmQgdGhlIHJpZ2h0IGFtb3VudCBvZiByZWd1bGFyaXphdGlvbiAodG8gYXZvaWQgb3ZlcmZpdHRpbmcpLiAgVGhlIG1vZGVsIAojIHBhcmFtZXRlciwgYGxhbWJkYWAsIGNvbnRyb2xzIHRoZSBhbW91bnQgb2YgcmVndWxhcml6YXRpb24gaW4gYSBHTE0gbW9kZWwgYW5kIHdlIGNhbiAKIyBmaW5kIHRoZSBvcHRpbWFsIHZhbHVlIGZvciBgbGFtYmRhYCBhdXRvbWF0aWNhbGx5IGJ5IHNldHRpbmcgYGxhbWJkYV9zZWFyY2ggPSBUUlVFYCAKIyBhbmQgcGFzc2luZyBpbiBhIHZhbGlkYXRpb24gZnJhbWUgKHdoaWNoIGlzIHVzZWQgdG8gZXZhbHVhdGUgbW9kZWwgcGVyZm9ybWFuY2UgdXNpbmcgYSAKIyBwYXJ0aWN1bGFyIHZhbHVlIG9mIGxhbWJkYSkuCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgoKZ2xtX2ZpdDIgPC0gaDJvLmdsbSh4ID0geCwgCiAgICAgICAgICAgICAgICAgICAgeSA9IHksIAogICAgICAgICAgICAgICAgICAgIHRyYWluaW5nX2ZyYW1lID0gdHJhaW4sCiAgICAgICAgICAgICAgICAgICAgbW9kZWxfaWQgPSAiZ2xtX2ZpdDIiLAogICAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb25fZnJhbWUgPSB2YWxpZCwKICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSAiZ2F1c3NpYW4iLAogICAgICAgICAgICAgICAgICAgIGxhbWJkYV9zZWFyY2ggPSBUUlVFKSAKCgojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIExldCdzIGNvbXBhcmUgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSB0d28gR0xNcwojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKCmdsbV9wZXJmMiA8LSBoMm8ucGVyZm9ybWFuY2UobW9kZWwgPSBnbG1fZml0MiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdkYXRhID0gdGVzdCkKCgoKIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyBJbnN0ZWFkIG9mIHByaW50aW5nIHRoZSBlbnRpcmUgbW9kZWwgcGVyZm9ybWFuY2UgbWV0cmljcyBvYmplY3QsIAojIGl0IGlzIHByb2JhYmx5IGVhc2llciB0byBwcmludCBqdXN0IHRoZSBtZXRyaWMgdGhhdCB5b3UgYXJlIGludGVyZXN0ZWQgaW4gY29tcGFyaW5nLgojIFJldHJlaXZlIHRlc3Qgc2V0IEFVQwojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKCiAKIAoKZ2xtX2ZpdDJAbW9kZWwkdmFsaWRhdGlvbl9tZXRyaWNzIAoKYGBgCgoKYGBge3J9CiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIFdlIHdpbGwgYWdhaW4gc2V0IGBudHJlZXMgPSA1MDBgLCBob3dldmVyLCB0aGlzIHRpbWUgd2Ugd2lsbCB1c2UgZWFybHkgc3RvcHBpbmcgaW4gb3JkZXIgdG8gCiMgcHJldmVudCBvdmVyZml0dGluZyAoZnJvbSB0b28gbWFueSB0cmVlcykuICBBbGwgb2YgSDJPJ3MgYWxnb3JpdGhtcyBoYXZlIGVhcmx5IHN0b3BwaW5nIGF2YWlsYWJsZSwgCiMgaG93ZXZlciBlYXJseSBzdG9wcGluZyBpcyBub3QgZW5hYmxlZCBieSBkZWZhdWx0ICh3aXRoIHRoZSBleGNlcHRpb24gb2YgRGVlcCBMZWFybmluZykuICAKIyBUaGVyZSBhcmUgc2V2ZXJhbCBwYXJhbWV0ZXJzIHRoYXQgc2hvdWxkIGJlIHVzZWQgdG8gY29udHJvbCBlYXJseSBzdG9wcGluZy4gIFRoZSB0aHJlZSB0aGF0IGFyZSAKIyBjb21tb24gdG8gYWxsIHRoZSBhbGdvcml0aG1zIGFyZTogYHN0b3BwaW5nX3JvdW5kc2AsIGBzdG9wcGluZ19tZXRyaWNgIGFuZCBgc3RvcHBpbmdfdG9sZXJhbmNlYC4gIAojIFRoZSBzdG9wcGluZyBtZXRyaWMgaXMgdGhlIG1ldHJpYyBieSB3aGljaCB5b3UnZCBsaWtlIHRvIG1lYXN1cmUgcGVyZm9ybWFuY2UsIGFuZCBzbyB3ZSB3aWxsIGNob29zZSAKIyBBVUMgaGVyZS4gIFRoZSBgc2NvcmVfdHJlZV9pbnRlcnZhbGAgaXMgYSBwYXJhbWV0ZXIgc3BlY2lmaWMgdG8gdGhlIFJhbmRvbSBGb3Jlc3QgbW9kZWwgYW5kIHRoZSBHQk0uICAKIyBTZXR0aW5nIGBzY29yZV90cmVlX2ludGVydmFsID0gNWAgd2lsbCBzY29yZSB0aGUgbW9kZWwgYWZ0ZXIgZXZlcnkgZml2ZSB0cmVlcy4gIFRoZSBwYXJhbWV0ZXJzIHdlIAojIGhhdmUgc2V0IGJlbG93IHNwZWNpZnkgdGhhdCB0aGUgbW9kZWwgd2lsbCBzdG9wIHRyYWluaW5nIGFmdGVyIHRoZXJlIGhhdmUgYmVlbiB0aHJlZSBzY29yaW5nIGludGVydmFscyAKIyB3aGVyZSB0aGUgQVVDIGhhcyBub3QgaW5jcmVhc2VkIG1vcmUgdGhhbiAwLjAwMDUuICBTaW5jZSB3ZSBoYXZlIHNwZWNpZmllZCBhIHZhbGlkYXRpb24gZnJhbWUsIAojIHRoZSBzdG9wcGluZyB0b2xlcmFuY2Ugd2lsbCBiZSBjb21wdXRlZCBvbiB2YWxpZGF0aW9uIEFVQyByYXRoZXIgdGhhbiB0cmFpbmluZyBBVUMuIAojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCgpnYm1fZml0MyA8LSBoMm8uZ2JtKHggPSB4LAogICAgICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgICAgIHRyYWluaW5nX2ZyYW1lID0gdHJhaW4sCiAgICAgICAgICAgICAgICAgICAgbW9kZWxfaWQgPSAiZ2JtX2ZpdDIiLAogICAgICAgICAgICAgICAgICAgICN2YWxpZGF0aW9uX2ZyYW1lID0gdmFsaWQsICAjb25seSB1c2VkIGlmIHN0b3BwaW5nX3JvdW5kcyA+IDAKICAgICAgICAgICAgICAgICAgICBudHJlZXMgPSA1MDAsCiAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEpCgojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIExldCdzIGNvbXBhcmUgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSB0d28gR0JNcwojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKCgpnYm1fcGVyZjMgPC0gaDJvLnBlcmZvcm1hbmNlKG1vZGVsID0gZ2JtX2ZpdDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3ZGF0YSA9IHRlc3QpCgoKIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyBQcmludCBtb2RlbCBwZXJmb3JtYW5jZQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKCgpnYm1fcGVyZjMKCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojIExvb2sgYXQgc2NvcmluZyBoaXN0b3J5IGZvciB0aGlyZCBHQk0gbW9kZWwKIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCnBsb3QoZ2JtX2ZpdDMsIAogICAgIHRpbWVzdGVwID0gIm51bWJlcl9vZl90cmVlcyIpCgpgYGAKCgoKYGBge3J9CiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojIFRyYWluIGEgREwgd2l0aCBlYXJseSBzdG9wcGluZwojIFRoaXMgZXhhbXBsZSB3aWxsIHVzZSB0aGUgc2FtZSBtb2RlbCBwYXJhbWV0ZXJzIGFzIGBkbF9maXQyYC4gVGhpcyB0aW1lLCB3ZSB3aWxsIHR1cm4gb24gCiMgZWFybHkgc3RvcHBpbmcgYW5kIHNwZWNpZnkgdGhlIHN0b3BwaW5nIGNyaXRlcmlvbi4gIFdlIHdpbGwgYWxzbyBwYXNzIGEgdmFsaWRhdGlvbiBzZXQsIGFzIGlzCiMgcmVjb21tZW5kZWQgZm9yIGVhcmx5IHN0b3BwaW5nLgojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKCmRsX2ZpdDMgPC0gaDJvLmRlZXBsZWFybmluZyh4ID0geCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhaW5pbmdfZnJhbWUgPSB0cmFpbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX2lkID0gImRsX2ZpdDIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgI3ZhbGlkYXRpb25fZnJhbWUgPSB2YWxpZCwgICNvbmx5IHVzZWQgaWYgc3RvcHBpbmdfcm91bmRzID4gMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXBvY2hzID0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWRkZW49IGMoMTAsMTApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcHBpbmdfcm91bmRzID0gMCwgICMgZGlzYWJsZSBlYXJseSBzdG9wcGluZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VlZCA9IDEpIAoKZGxfcGVyZjMgPC0gaDJvLnBlcmZvcm1hbmNlKG1vZGVsID0gZGxfZml0MywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld2RhdGEgPSB0ZXN0KQoKCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojIFByaW50IG1vZGVsIHBlcmZvcm1hbmNlCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgpkbF9wZXJmMwoKIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiMgU2NvcmluZyBoaXN0b3J5CiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgoKCmgyby5zY29yZUhpc3RvcnkoZGxfZml0MykKCgoKIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiMgTG9vayBhdCBzY29yaW5nIGhpc3RvcnkgZm9yIHRoaXJkIERMIG1vZGVsCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgoKcGxvdChkbF9maXQzLCAKICAgICB0aW1lc3RlcCA9ICJlcG9jaHMiKQoKCmBgYAoKCgpgYGB7cn0KCmBgYAoK