Predicting Customer Retention

Let’s load our required packages:

Our data structure we will be using for our models:

'data.frame':   1000 obs. of  10 variables:
 $ pick      : chr  "OCC" "ATT" "OCC" "OCC" ...
 $ income    : chr  "<7.5" "45-75" "" "" ...
 $ moves     : chr  "0" "2" "0" "2" ...
 $ age       : chr  "35-44" "25-34" "" "65+" ...
 $ education : chr  "HS" "HS" "" "<HS" ...
 $ employment: chr  "F" "F" "" "R" ...
 $ usage     : int  9 2 6 7 0 0 3 1 0 2 ...
 $ nonpub    : chr  "YES" "YES" "NO" "NO" ...
 $ reachout  : chr  "NO" "NO" "NO" "NO" ...
 $ card      : chr  "NO" "NO" "YES" "NO" ...
NULL

Converting blank character fields to missing data codes

Convert character fields to factor fields

Let’s check our revised structure of att data frame:

'data.frame':   1000 obs. of  10 variables:
 $ pick      : Factor w/ 2 levels "ATT","OCC": 2 1 2 2 2 2 2 2 2 2 ...
 $ income    : Factor w/ 7 levels "<7.5",">75","15-25",..: 1 6 NA NA NA NA 4 3 NA 4 ...
 $ moves     : Factor w/ 9 levels ">10","0","1",..: 2 4 2 4 2 2 2 2 2 2 ...
 $ age       : Factor w/ 6 levels "18-24","25-34",..: 3 2 NA 6 6 6 4 5 5 4 ...
 $ education : Factor w/ 6 levels "<HS",">BA","BA",..: 5 5 NA 1 5 NA 1 5 1 1 ...
 $ employment: Factor w/ 7 levels "D","F","H","P",..: 2 2 NA 5 3 NA 2 5 2 3 ...
 $ usage     : int  9 2 6 7 0 0 3 1 0 2 ...
 $ nonpub    : Factor w/ 2 levels "NO","YES": 2 2 1 1 1 1 1 1 1 1 ...
 $ reachout  : Factor w/ 2 levels "NO","YES": 1 1 1 1 1 1 1 1 1 1 ...
 $ card      : Factor w/ 2 levels "NO","YES": 1 1 2 1 1 1 1 2 1 1 ...
NULL

listwise case deletion for usage and marketing factors

  pick         usage        reachout   card    
 ATT:502   Min.   :  0.00   NO :919   NO :701  
 OCC:479   1st Qu.:  1.00   YES: 62   YES:280  
           Median :  6.00                      
           Mean   : 16.32                      
           3rd Qu.: 23.00                      
           Max.   :291.00                      

provide overview of data

  pick         income        moves        age      education    employment      usage       
 ATT:504   15-25  :185   0      :597   18-24: 61   <HS :153   F      :548   Min.   :  0.00  
 OCC:496   25-35  :171   1      :221   25-34:214   >BA : 60   R      :215   1st Qu.:  1.00  
           7.5-15 :114   2      : 88   35-44:203   BA  :150   H      : 93   Median :  6.00  
           35-45  :107   3      : 38   45-54:152   Coll:187   P      : 67   Mean   : 16.34  
           <7.5   : 96   4      : 16   55-64:153   HS  :361   U      : 26   3rd Qu.: 23.00  
           (Other):112   (Other): 23   65+  :184   Voc : 54   (Other): 25   Max.   :291.00  
           NA's   :215   NA's   : 17   NA's : 33   NA's: 35   NA's   : 26                   
  nonpub    reachout     card    
 NO  :808   NO  :919   NO  :702  
 YES :188   YES : 62   YES :281  
 NA's:  4   NA's: 19   NA's: 17  
                                 
                                 
                                 
                                 

Examine relationship between age and response to promotion. Switchers tend to have lower usage

Plotting the probability smooth for usage and switching:

Create a mosaic plot in using vcd package

Create a mosaic plot in using vcd package

Fittin our logistic regression model


Call:
glm(formula = att_spec, family = binomial, data = attwork)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.3240  -1.1878  -0.5689   1.0693   2.6588  

Coefficients:
             Estimate Std. Error z value Pr(>|z|)    
(Intercept)  0.338302   0.087095   3.884 0.000103 ***
usage       -0.013080   0.003362  -3.890 0.000100 ***
reachoutYES -0.869531   0.323727  -2.686 0.007231 ** 
cardYES     -0.475578   0.149350  -3.184 0.001451 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 1359.4  on 980  degrees of freedom
Residual deviance: 1307.0  on 977  degrees of freedom
AIC: 1315

Number of Fisher Scoring iterations: 4

Printing ANOVA tests

Analysis of Deviance Table

Model: binomial, link: logit

Response: pick

Terms added sequentially (first to last)

         Df Deviance Resid. Df Resid. Dev  Pr(>Chi)    
NULL                       980     1359.4              
usage     1   33.303       979     1326.1 7.886e-09 ***
reachout  1    8.872       978     1317.2  0.002895 ** 
card      1   10.227       977     1307.0  0.001384 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Compute predicted probability of switching service providers

Plotting Predicted Probability of Switching


Confusion Matrix (rows=Predicted Service Provider, columns=Actual Service Provider
      
       ATT OCC
  AT&T 250 159
  OCC  252 320

Percent Accuracy:  58.1
            pick
Predict_Pick ATT OCC <NA>
        AT&T 250 159    0
        OCC  252 320    0
        <NA>   0   0    0

Plot predicted Service Provider (50 percent cut-off)

Ploting classification tree result from rpart

cex 1   xlim c(-0.2, 1.2)   ylim c(0, 1)

Visual of fit random forest model to the training data

Ensuring complete data in both partitions were created


ATT OCC 
502 479 

ATT OCC 
168 160 

ATT OCC 
334 319 

Plotting ROC for logistic regression

Plotting ROC for support vector machines

Plotting ROC for random forest

Plotting ROC for Naive Bayes

Plotting ROC for Neural Network

LS0tDQp0aXRsZTogIkN1c3RvbWVyIFJldGVudGlvbiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQogDQojIFByZWRpY3RpbmcgQ3VzdG9tZXIgUmV0ZW50aW9uDQoNCkxldCdzIGxvYWQgb3VyIHJlcXVpcmVkIHBhY2thZ2VzOg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KGxhdHRpY2UpICAjIGxhdHRpY2UgcGxvdA0KbGlicmFyeSh2Y2QpICAjIG1vc2FpYyBwbG90cw0KbGlicmFyeShnYW0pICAjIGdlbmVyYWxpemVkIGFkZGl0aXZlIG1vZGVscyBmb3IgcHJvYmFiaWxpdHkgc21vb3RoDQpsaWJyYXJ5KHJwYXJ0KSAgIyB0cmVlLXN0cnVjdHVyZWQgbW9kZWxpbmcNCmxpYnJhcnkoZTEwNzEpICAjIHN1cHBvcnQgdmVjdG9yIG1hY2hpbmVzDQpsaWJyYXJ5KHJhbmRvbUZvcmVzdCkgICMgcmFuZG9tIGZvcmVzdHMNCmxpYnJhcnkobm5ldCkgICMgbmV1cmFsIG5ldHdvcmtzDQpsaWJyYXJ5KHJwYXJ0LnBsb3QpICAjIHBsb3QgdHJlZS1zdHJ1Y3R1cmVkIG1vZGVsIGluZm9ybWF0aW9uDQpsaWJyYXJ5KFJPQ1IpICAjIFJPQyBjdXJ2ZSBvYmplY3RzIGZvciBiaW5hcnkgY2xhc3NpZmljYXRpb24gDQoNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIHVzZXItZGVmaW5lZCBmdW5jdGlvbiBmb3IgcGxvdHRpbmcgUk9DIGN1cnZlIHVzaW5nIFJPQyBvYmplY3RzIGZyb20gUk9DUg0KcGxvdF9yb2MgPC0gZnVuY3Rpb24odHJhaW5fcm9jLCB0cmFpbl9hdWMsIHRlc3Rfcm9jLCB0ZXN0X2F1Yykgew0KICAgIHBsb3QodHJhaW5fcm9jLCBjb2wgPSAiYmx1ZSIsIGx0eSA9ICJzb2xpZCIsIG1haW4gPSAiIiwgbHdkID0gMiwNCiAgICAgICAgeGxhYiA9ICJGYWxzZSBQb3NpdGl2ZSBSYXRlIiwNCiAgICAgICAgeWxhYiA9ICJUcnVlIFBvc2l0aXZlIFJhdGUiKQ0KICAgICAgICBwbG90KHRlc3Rfcm9jLCBjb2wgPSAicmVkIiwgbHR5ID0gImRhc2hlZCIsIGx3ZCA9IDIsIGFkZCA9IFRSVUUpDQogICAgICAgIGFibGluZShjKDAsMSkpDQogICAgICAgIyBEcmF3IGEgbGVnZW5kLg0KICAgICAgIHRyYWluLmxlZ2VuZCA8LSBwYXN0ZSgiVHJhaW5pbmcgQVVDID0gIiwgcm91bmQodHJhaW5fYXVjLCBkaWdpdHM9MykpDQogICAgICAgdGVzdC5sZWdlbmQgPC0gcGFzdGUoIlRlc3QgQVVDID0iLCByb3VuZCh0ZXN0X2F1YywgZGlnaXRzPTMpKQ0KICAgICAgIGxlZ2VuZCgiYm90dG9tcmlnaHQiLCBsZWdlbmQgPSBjKHRyYWluLmxlZ2VuZCwgdGVzdC5sZWdlbmQpLA0KICAgICAgICAgICBsdHkgPSBjKCJzb2xpZCIsICJkYXNoZWQiKSwgbHdkID0gMiwgY29sID0gYygiYmx1ZSIsICJyZWQiKSkNCiAgICB9ICAgICAgIA0KDQpgYGANCg0KT3VyIGRhdGEgc3RydWN0dXJlIHdlIHdpbGwgYmUgdXNpbmcgZm9yIG91ciBtb2RlbHM6DQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgcmVhZCBpbiBjb21tYS1kZWxpbWl0ZWQgdGV4dCBmaWxlIGFuZCBjcmVhdGUgZGF0YSBmcmFtZQ0KIyB0aGVyZSBhcmUgYmxhbmsgY2hhcmFjdGVyIGZpZWxkcyBmb3IgbWlzc2luZyBkYXRhDQojIHJlYWQgdGhlbSBhcyBjaGFyYWN0ZXIgZmllbGRzIGluaXRpYWxseQ0KYXR0IDwtIHJlYWQuY3N2KCJhdHQuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KcHJpbnQoc3RyKGF0dCkpDQoNCmBgYA0KDQpDb252ZXJ0aW5nIGJsYW5rIGNoYXJhY3RlciBmaWVsZHMgdG8gbWlzc2luZyBkYXRhIGNvZGVzDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgDQphdHRbYXR0ID09ICIiXSA8LSBOQQ0KYGBgDQoNCkNvbnZlcnQgY2hhcmFjdGVyIGZpZWxkcyB0byBmYWN0b3IgZmllbGRzDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0gDQphdHQkcGljayA8LSBmYWN0b3IoYXR0JHBpY2spDQphdHQkaW5jb21lIDwtIGZhY3RvcihhdHQkaW5jb21lKQ0KYXR0JG1vdmVzIDwtIGZhY3RvcihhdHQkbW92ZXMpDQphdHQkYWdlIDwtIGZhY3RvcihhdHQkYWdlKQ0KYXR0JGVkdWNhdGlvbiA8LSBmYWN0b3IoYXR0JGVkdWNhdGlvbikNCmF0dCRlbXBsb3ltZW50IDwtIGZhY3RvcihhdHQkZW1wbG95bWVudCkNCmF0dCRub25wdWIgPC0gZmFjdG9yKGF0dCRub25wdWIpDQphdHQkcmVhY2hvdXQgPC0gZmFjdG9yKGF0dCRyZWFjaG91dCkNCmF0dCRjYXJkIDwtIGZhY3RvcihhdHQkY2FyZCkNCg0KYGBgDQoNCkxldCdzIGNoZWNrIG91ciByZXZpc2VkIHN0cnVjdHVyZSBvZiBhdHQgZGF0YSBmcmFtZToNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KcHJpbnQoc3RyKGF0dCkpDQoNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIHNlbGVjdCB1c2FnZSBhbmQgQVQmVCBtYXJrZXRpbmcgcGxhbiBmYWN0b3JzDQphdHR3b3JrIDwtIHN1YnNldChhdHQsIHNlbGVjdCA9IGMoInBpY2siLCAidXNhZ2UiLCAicmVhY2hvdXQiLCAiY2FyZCIpKQ0KYXR0d29yayA8LSBuYS5vbWl0KGF0dHdvcmspDQoNCmBgYA0KDQpsaXN0d2lzZSBjYXNlIGRlbGV0aW9uIGZvciB1c2FnZSBhbmQgbWFya2V0aW5nIGZhY3RvcnMNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyANCmF0dHdvcmsgPC0gbmEub21pdChhdHR3b3JrKQ0KcHJpbnQoc3VtbWFyeShhdHR3b3JrKSkNCmBgYA0KDQpwcm92aWRlIG92ZXJ2aWV3IG9mIGRhdGENCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyBwcm92aWRlIG92ZXJ2aWV3IG9mIGRhdGENCnByaW50KHN1bW1hcnkoYXR0KSkNCg0KYGBgDQoNCkV4YW1pbmUgcmVsYXRpb25zaGlwIGJldHdlZW4gYWdlIGFuZCByZXNwb25zZSB0byBwcm9tb3Rpb24uIFN3aXRjaGVycyB0ZW5kIHRvIGhhdmUgbG93ZXIgdXNhZ2UNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLQ0KIyB1c2FnZSBhbmQgcGljaw0KIyAtLS0tLS0tLS0tLS0tLS0tLQ0KIyBleGFtaW5lIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGFnZSBhbmQgcmVzcG9uc2UgdG8gcHJvbW90aW9uDQpwZGYoZmlsZSA9ICJmaWdfcmV0YWluaW5nX2N1c3RvbWVyc191c2FnZV9sYXR0aWNlLnBkZiIsIA0KICAgIHdpZHRoID0gOC41LCBoZWlnaHQgPSA4LjUpDQoNCmxhdHRpY2VfcGxvdF9vYmplY3QgPC0gaGlzdG9ncmFtKH51c2FnZSB8IHBpY2ssIGRhdGEgPSBhdHQsDQogICAgdHlwZSA9ICJkZW5zaXR5IiwgeGxhYiA9ICJUZWxlcGhvbmUgVXNhZ2UgKE1pbnV0ZXMgcGVyIE1vbnRoKSIsIA0KICAgIGxheW91dCA9IGMoMSwyKSkNCg0KcHJpbnQobGF0dGljZV9wbG90X29iamVjdCkgICMgc3dpdGNoZXJzIHRlbmQgdG8gaGF2ZSBsb3dlciB1c2FnZQ0KDQoNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQphdHRfZ2FtX21vZGVsIDwtIGdhbShwaWNrID09ICJPQ0MiICB+IHModXNhZ2UpLCBmYW1pbHk9Ymlub21pYWwsZGF0YT1hdHQpDQpgYGANCg0KUGxvdHRpbmcgdGhlIHByb2JhYmlsaXR5IHNtb290aCBmb3IgdXNhZ2UgYW5kIHN3aXRjaGluZzoNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyBwcm9iYWJpbGl0eSBzbW9vdGggZm9yIHVzYWdlIGFuZCBzd2l0Y2hpbmcNCnBkZihmaWxlID0gImZpZ19yZXRhaW5pbmdfY3VzdG9tZXJzX3VzYWdlX3Byb2JhYmlsaXR5X3Ntb290aC5wZGYiLCANCiAgICB3aWR0aCA9IDguNSwgaGVpZ2h0ID0gOC41KQ0KDQpwbG90KGF0dCR1c2FnZSwgYXR0JHBpY2sgPT0gIk9DQyIsIHR5cGU9Im4iLCANCiAgICAgeWxpbT1jKC0wLjEsMS4xKSwgeWF4dD0ibiIsIA0KICAgICB5bGFiPSJFc3RpbWF0ZWQgUHJvYmFiaWxpdHkgb2YgU3dpdGNoaW5nIiwgDQogICAgIHhsYWI9IlRlbGVwaG9uZSBVc2FnZSAoTWludXRlcyBwZXIgTW9udGgpIikgDQogICAgIGF4aXMoMiwgYXQ9YygwLC41LDEpKSANCiAgICAgcG9pbnRzKGppdHRlcihhdHQkdXNhZ2UpLCANCiAgICAgYXR0JHBpY2s9PSJPQ0MiLHBjaD0ifCIpIA0KICAgICBvIDwtIG9yZGVyKGF0dCR1c2FnZSkgDQogICAgIGxpbmVzKGF0dCR1c2FnZVtvXSxmaXR0ZWQoYXR0X2dhbV9tb2RlbClbb10pIA0KICAgICANCg0KDQpgYGANCg0KQ3JlYXRlIGEgbW9zYWljIHBsb3QgaW4gdXNpbmcgdmNkIHBhY2thZ2UNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLQ0KIyByZWFjaG91dCBhbmQgcGljaw0KIyAtLS0tLS0tLS0tLS0tLS0tLQ0KDQojIGNyZWF0ZSBhIG1vc2FpYyBwbG90IGluIHVzaW5nIHZjZCBwYWNrYWdlDQpwZGYoZmlsZSA9ICJmaWdfcmV0YWluaW5nX2N1c3RvbWVyc19yZWFjaG91dF9tb3NhaWMucGRmIiwgDQogICAgd2lkdGggPSA4LjUsIGhlaWdodCA9IDguNSkNCg0KbW9zYWljKCB+IHBpY2sgKyByZWFjaG91dCwgZGF0YSA9IGF0dHdvcmssDQogIGxhYmVsaW5nX2FyZ3MgPSBsaXN0KHNldF92YXJuYW1lcyA9IGMocGljayA9ICJTZXJ2aWNlIFByb3ZpZGVyIENob2ljZSIsIA0KICByZWFjaG91dCA9ICJBVCZUIFJlYWNoIE91dCBBbWVyaWNhIFBsYW4iKSksDQogIGhpZ2hsaWdodGluZyA9ICJyZWFjaG91dCIsDQogIGhpZ2hsaWdodGluZ19maWxsID0gYygiY29ybnNpbGsiLCJ2aW9sZXQiKSwNCiAgcm90X2xhYmVscyA9IGMobGVmdCA9IDAsIHRvcCA9IDApLA0KICBwb3NfbGFiZWxzID0gYygiY2VudGVyIiwiY2VudGVyIiksDQogIG9mZnNldF9sYWJlbHMgPSBjKDAuMCwwLjYpKQ0KDQoNCg0KYGBgDQoNCkNyZWF0ZSBhIG1vc2FpYyBwbG90IGluIHVzaW5nIHZjZCBwYWNrYWdlDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgY3JlYXRlIGEgbW9zYWljIHBsb3QgaW4gdXNpbmcgdmNkIHBhY2thZ2UNCnBkZihmaWxlID0gImZpZ19yZXRhaW5pbmdfY3VzdG9tZXJzX2NhcmRfbW9zYWljLnBkZiIsIA0KICAgIHdpZHRoID0gOC41LCBoZWlnaHQgPSA4LjUpDQoNCm1vc2FpYyggfiBwaWNrICsgY2FyZCwgZGF0YSA9IGF0dHdvcmssDQogIGxhYmVsaW5nX2FyZ3MgPSBsaXN0KHNldF92YXJuYW1lcyA9IGMocGljayA9ICJTZXJ2aWNlIFByb3ZpZGVyIENob2ljZSIsIA0KICBjYXJkID0gIkFUJlQgQ3JlZGl0IENhcmQiKSksDQogIGhpZ2hsaWdodGluZyA9ICJjYXJkIiwNCiAgaGlnaGxpZ2h0aW5nX2ZpbGwgPSBjKCJjb3Juc2lsayIsInZpb2xldCIpLA0KICByb3RfbGFiZWxzID0gYyhsZWZ0ID0gMCwgdG9wID0gMCksDQogIHBvc19sYWJlbHMgPSBjKCJjZW50ZXIiLCJjZW50ZXIiKSwNCiAgb2Zmc2V0X2xhYmVscyA9IGMoMC4wLDAuNikpDQoNCg0KDQpgYGANCg0KRml0dGluIG91ciBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBmaXQgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCANCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KYXR0X3NwZWMgPC0ge3BpY2sgfiB1c2FnZSArIHJlYWNob3V0ICsgY2FyZH0NCmF0dF9maXQgPC0gZ2xtKGF0dF9zcGVjLCBmYW1pbHk9Ymlub21pYWwsIGRhdGE9YXR0d29yaykNCnByaW50KHN1bW1hcnkoYXR0X2ZpdCkpDQoNCmBgYA0KDQpQcmludGluZyBBTk9WQSB0ZXN0cw0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQpwcmludChhbm92YShhdHRfZml0LCB0ZXN0PSJDaGlzcSIpKQ0KDQpgYGANCg0KQ29tcHV0ZSBwcmVkaWN0ZWQgcHJvYmFiaWxpdHkgb2Ygc3dpdGNoaW5nIHNlcnZpY2UgcHJvdmlkZXJzDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgY29tcHV0ZSBwcmVkaWN0ZWQgcHJvYmFiaWxpdHkgb2Ygc3dpdGNoaW5nIHNlcnZpY2UgcHJvdmlkZXJzIA0KYXR0d29yayRQcmVkaWN0X1Byb2JfU3dpdGNoaW5nIDwtIHByZWRpY3QuZ2xtKGF0dF9maXQsIHR5cGUgPSAicmVzcG9uc2UiKSANCmBgYA0KDQpQbG90dGluZyBQcmVkaWN0ZWQgUHJvYmFiaWxpdHkgb2YgU3dpdGNoaW5nDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCnBkZihmaWxlID0gImZpZ19yZXRhaW5pbmdfY3VzdG9tZXJzX2xvZ19yZWdfZGVuc2l0eV9ldmFsdWF0aW9uLnBkZiIsIA0KICAgIHdpZHRoID0gOC41LCBoZWlnaHQgPSA4LjUpDQoNCnBsb3R0aW5nX29iamVjdCA8LSBkZW5zaXR5cGxvdCggfiBQcmVkaWN0X1Byb2JfU3dpdGNoaW5nIHwgcGljaywgDQogICAgICAgICAgICAgICBkYXRhID0gYXR0d29yaywgDQogICAgICAgICAgICAgICBsYXlvdXQgPSBjKDEsMiksIGFzcGVjdD0xLCBjb2wgPSAiZGFya2JsdWUiLCANCiAgICAgICAgICAgICAgIHBsb3QucG9pbnRzID0gInJ1ZyIsDQogICAgICAgICAgICAgICBzdHJpcD1mdW5jdGlvbiguLi4pIHN0cmlwLmRlZmF1bHQoLi4uLCBzdHlsZT0xKSwNCiAgICAgICAgICAgICAgIHhsYWI9IlByZWRpY3RlZCBQcm9iYWJpbGl0eSBvZiBTd2l0Y2hpbmciKSANCg0KcHJpbnQocGxvdHRpbmdfb2JqZWN0KSANCg0KDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyB1c2UgYSAwLjUgY3V0LW9mZiBpbiB0aGlzIHByb2JsZW0NCmF0dHdvcmskUHJlZGljdF9QaWNrIDwtIA0KICAgIGlmZWxzZSgoYXR0d29yayRQcmVkaWN0X1Byb2JfU3dpdGNoaW5nID4gMC41KSwgMiwgMSkNCg0KYXR0d29yayRQcmVkaWN0X1BpY2sgPC0gZmFjdG9yKGF0dHdvcmskUHJlZGljdF9QaWNrLA0KICAgIGxldmVscyA9IGMoMSwgMiksIGxhYmVscyA9IGMoIkFUJlQiLCAiT0NDIikpICANCg0KY29uZnVzaW9uX21hdHJpeCA8LSB0YWJsZShhdHR3b3JrJFByZWRpY3RfUGljaywgYXR0d29yayRwaWNrKQ0KY2F0KCJcbkNvbmZ1c2lvbiBNYXRyaXggKHJvd3M9UHJlZGljdGVkIFNlcnZpY2UgUHJvdmlkZXIsIiwNCiAgICJjb2x1bW5zPUFjdHVhbCBTZXJ2aWNlIFByb3ZpZGVyXG4iKQ0KDQpwcmludChjb25mdXNpb25fbWF0cml4KQ0KDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KcHJlZGljdGl2ZV9hY2N1cmFjeSA8LSAoY29uZnVzaW9uX21hdHJpeFsxLDFdICsgY29uZnVzaW9uX21hdHJpeFsyLDJdKS8NCiAgICAgICAgICAgICAgICAgICAgICAgIHN1bShjb25mdXNpb25fbWF0cml4KSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KY2F0KCJcblBlcmNlbnQgQWNjdXJhY3k6ICIsIHJvdW5kKHByZWRpY3RpdmVfYWNjdXJhY3kgKiAxMDAsIGRpZ2l0cyA9IDEpKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgbW9zYWljIHJlbmRlcmluZyBvZiB0aGUgY2xhc3NpZmllciB3aXRoIDAuMTAgY3V0b2ZmDQp3aXRoKGF0dHdvcmssIHByaW50KHRhYmxlKFByZWRpY3RfUGljaywgcGljaywgdXNlTkEgPSBjKCJhbHdheXMiKSkpKQ0KYGBgDQoNClBsb3QgcHJlZGljdGVkIFNlcnZpY2UgUHJvdmlkZXIgKDUwIHBlcmNlbnQgY3V0LW9mZikNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KcGRmKGZpbGUgPSAiZmlnX3JldGFpbmluZ19jdXN0b21lcnNfY29uZnVzaW9uX21vc2FpY181MF9wZXJjZW50LnBkZiIsIA0KICAgIHdpZHRoID0gOC41LCBoZWlnaHQgPSA4LjUpDQoNCm1vc2FpYyggfiBQcmVkaWN0X1BpY2sgKyBwaWNrLCBkYXRhID0gYXR0d29yaywNCiAgbGFiZWxpbmdfYXJncyA9IGxpc3Qoc2V0X3Zhcm5hbWVzID0gDQogIGMoUHJlZGljdF9QaWNrID0gDQogICAgICAiUHJlZGljdGVkIFNlcnZpY2UgUHJvdmlkZXIgKDUwIHBlcmNlbnQgY3V0LW9mZikiLA0KICAgICAgIHBpY2sgPSAiQWN0dWFsIFNlcnZpY2UgUHJvdmlkZXIiKSksDQogIGhpZ2hsaWdodGluZyA9IGMoIlByZWRpY3RfUGljayIsICJwaWNrIiksDQogIGhpZ2hsaWdodGluZ19maWxsID0gYygiZ3JlZW4iLCJjb3Juc2lsayIsImNvcm5zaWxrIiwiZ3JlZW4iKSwNCiAgcm90X2xhYmVscyA9IGMobGVmdCA9IDAsIHRvcCA9IDApLA0KICBwb3NfbGFiZWxzID0gYygiY2VudGVyIiwiY2VudGVyIiksDQogIG9mZnNldF9sYWJlbHMgPSBjKDAuMCwwLjYpKQ0KDQoNCg0KYGBgDQoNClBsb3RpbmcgY2xhc3NpZmljYXRpb24gdHJlZSByZXN1bHQgZnJvbSBycGFydA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIGV4YW1wbGUgb2YgdHJlZS1zdHJ1Y3R1cmVkIGNsYXNzaWZpY2F0aW9uIA0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KYXR0X3RyZWVfZml0IDwtIHJwYXJ0KGF0dF9zcGVjLCBkYXRhID0gYXR0d29yaywgDQogICAgY29udHJvbCA9IHJwYXJ0LmNvbnRyb2woY3AgPSAwLjAwMjUpKQ0KDQojIHBsb3QgY2xhc3NpZmljYXRpb24gdHJlZSByZXN1bHQgZnJvbSBycGFydA0KcGRmKGZpbGUgPSAiZmlnX3JldGFpbmluZ19jdXN0b21lcnNfdHJlZV9jbGFzc2lmaWVyLnBkZiIsIA0KICAgIHdpZHRoID0gOC41LCBoZWlnaHQgPSA4LjUpDQoNCnBycChhdHRfdHJlZV9maXQsIG1haW49IiIsDQogICAgZGlnaXRzID0gMywgICMgZGlnaXRzIHRvIGRpc3BsYXkgaW4gdGVybWluYWwgbm9kZXMNCiAgICBubiA9IFRSVUUsICAjIGRpc3BsYXkgdGhlIG5vZGUgbnVtYmVycw0KICAgIGJyYW5jaCA9IDAuNSwgICMgY2hhbmdlIGFuZ2xlIG9mIGJyYW5jaCBsaW5lcw0KICAgIGJyYW5jaC5sd2QgPSAyLCAgIyB3aWR0aCBvZiBicmFuY2ggbGluZXMNCiAgICBmYWNsZW4gPSAwLCAgIyBkbyBub3QgYWJicmV2aWF0ZSBmYWN0b3IgbGV2ZWxzDQogICAgdHJhY2UgPSAxLCAgIyBwcmludCB0aGUgYXV0b21hdGljYWxseSBjYWxjdWxhdGVkIGNleA0KICAgIHNoYWRvdy5jb2wgPSAwLCAgIyBubyBzaGFkb3dzIHVuZGVyIHRoZSBsZWF2ZXMNCiAgICBicmFuY2gubHR5ID0gMSwgICMgZHJhdyBicmFuY2hlcyB1c2luZyBkb3R0ZWQgbGluZXMNCiAgICBzcGxpdC5jZXggPSAxLjIsICAjIG1ha2UgdGhlIHNwbGl0IHRleHQgbGFyZ2VyIHRoYW4gdGhlIG5vZGUgdGV4dA0KICAgIHNwbGl0LnByZWZpeCA9ICJpcyAiLCAgIyBwdXQgImlzIiBiZWZvcmUgc3BsaXQgdGV4dA0KICAgIHNwbGl0LnN1ZmZpeCA9ICI/IiwgICMgcHV0ICI/IiBhZnRlciBzcGxpdCB0ZXh0DQogICAgc3BsaXQuYm94LmNvbCA9ICJibHVlIiwgICMgbGlnaHRncmF5IHNwbGl0IGJveGVzIChkZWZhdWx0IGlzIHdoaXRlKQ0KICAgIHNwbGl0LmNvbCA9ICJ3aGl0ZSIsICAjIGNvbG9yIG9mIHRleHQgaW4gc3BsaXQgYm94IA0KICAgIHNwbGl0LmJvcmRlci5jb2wgPSAiYmx1ZSIsICAjIGRhcmtncmF5IGJvcmRlciBvbiBzcGxpdCBib3hlcw0KICAgIHNwbGl0LnJvdW5kID0gLjI1KSAgIyByb3VuZCB0aGUgc3BsaXQgYm94IGNvcm5lcnMgYSB0YWQNCg0KDQoNCmBgYA0KDQpWaXN1YWwgb2YgZml0IHJhbmRvbSBmb3Jlc3QgbW9kZWwgdG8gdGhlIHRyYWluaW5nIGRhdGENCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgZXhhbXBsZSBvZiByYW5kb20gZm9yZXN0IG1vZGVsIGZvciBpbXBvcnRhbmNlDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBmaXQgcmFuZG9tIGZvcmVzdCBtb2RlbCB0byB0aGUgdHJhaW5pbmcgZGF0YQ0Kc2V0LnNlZWQgKDk5OTkpICAjIGZvciByZXByb2R1Y2liaWxpdHkNCg0KYXR0d29ya19yZl9maXQgPC0gcmFuZG9tRm9yZXN0KGF0dF9zcGVjLCBkYXRhID0gYXR0d29yaywgDQogICBtdHJ5PTMsIGltcG9ydGFuY2U9VFJVRSwgbmEuYWN0aW9uPW5hLm9taXQpIA0KDQojIGNoZWNrIGltcG9ydGFuY2Ugb2YgdGhlIGluZGl2aWR1YWwgZXhwbGFuYXRvcnkgdmFyaWFibGVzIA0KcGRmKGZpbGUgPSAiZmlnX3JldGFpbmluZ19jdXN0b21lcnNfcmFuZG9tX2ZvcmVzdF9pbXBvcnRhbmNlLnBkZiIsIA0Kd2lkdGggPSAxMSwgaGVpZ2h0ID0gOC41KQ0KDQp2YXJJbXBQbG90KGF0dHdvcmtfcmZfZml0LCBtYWluID0gIiIsIHBjaCA9IDIwLCBjZXggPSAxLjI1KQ0KDQoNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyB0cmFpbmluZy1hbmQtdGVzdCBmb3IgZXZhbHVhdGluZyBhbHRlcm5hdGl2ZSBtb2RlbGluZyBtZXRob2RzIA0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnNldC5zZWVkKDIwMjApDQoNCnBhcnRpdGlvbiA8LSBzYW1wbGUobnJvdyhhdHR3b3JrKSkgIyBwZXJtdXRlZCBsaXN0IG9mIHJvdyBpbmRleCBudW1iZXJzDQoNCmF0dHdvcmskZ3JvdXAgPC0gaWZlbHNlKChwYXJ0aXRpb24gPCBucm93KGF0dHdvcmspLygzLzIpKSwxLDIpDQoNCmF0dHdvcmskZ3JvdXAgPC0gZmFjdG9yKGF0dHdvcmskZ3JvdXAsIGxldmVscz1jKDEsMiksIA0KICAgIGxhYmVscz1jKCJUUkFJTiIsIlRFU1QiKSkNCg0KdHJhaW4gPC0gc3Vic2V0KGF0dHdvcmssIHN1YnNldCA9IChncm91cCA9PSAiVFJBSU4iKSwgDQogICAgc2VsZWN0ID0gYygicGljayIsICJ1c2FnZSIsICJyZWFjaG91dCIsICJjYXJkIikpDQoNCnRlc3QgPC0gc3Vic2V0KGF0dHdvcmssIHN1YnNldCA9IChncm91cCA9PSAiVEVTVCIpLCANCiAgICBzZWxlY3QgPSBjKCJwaWNrIiwgInVzYWdlIiwgInJlYWNob3V0IiwgImNhcmQiKSkNCg0KYGBgDQoNCkVuc3VyaW5nIGNvbXBsZXRlIGRhdGEgaW4gYm90aCBwYXJ0aXRpb25zIHdlcmUgY3JlYXRlZA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIGVuc3VyZSBjb21wbGV0ZSBkYXRhIGluIGJvdGggcGFydGl0aW9ucw0KdHJhaW4gPC0gbmEub21pdCh0cmFpbikNCnRlc3QgPC0gbmEub21pdCh0ZXN0KQ0KDQojIGNoZWNrIHBhcnRpdGlvbnMgZm9yIG5vLW92ZXJsYXAgYW5kIGNvcnJlY3QgcGljayBmcmVxdWVuY2llcw0KaWYobGVuZ3RoKGludGVyc2VjdChyb3duYW1lcyh0cmFpbiksIHJvd25hbWVzKHRlc3QpKSkgIT0gMCkgDQogICAgcHJpbnQoIlxuUHJvYmxlbSB3aXRoIHBhcnRpdGlvbiIpICANCg0KcHJpbnQodGFibGUoYXR0d29yayRwaWNrKSkNCg0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCnByaW50KHRhYmxlKHRlc3QkcGljaykpIA0KDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KcHJpbnQodGFibGUodHJhaW4kcGljaykpICANCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIExvZ2lzdGljIHJlZ3Jlc3Npb24gdHJhaW5pbmctYW5kLXRlc3QNCiMgYXVjID0gYXJlYSB1bmRlciBST0MgY3VydmUNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgZml0IGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgdG8gdGhlIHRyYWluaW5nIHNldCANCnRyYWluX2xyX2ZpdCA8LSBnbG0oYXR0X3NwZWMsIGZhbWlseT1iaW5vbWlhbCwgZGF0YT10cmFpbikNCnRyYWluJGxyX3ByZWRpY3RfcHJvYiA8LSBwcmVkaWN0KHRyYWluX2xyX2ZpdCwgdHlwZSA9ICJyZXNwb25zZSIpDQp0cmFpbl9scl9wcmVkaWN0aW9uIDwtIHByZWRpY3Rpb24odHJhaW4kbHJfcHJlZGljdF9wcm9iLCB0cmFpbiRwaWNrKQ0KdHJhaW5fbHJfYXVjIDwtIGFzLm51bWVyaWMocGVyZm9ybWFuY2UodHJhaW5fbHJfcHJlZGljdGlvbiwgImF1YyIpQHkudmFsdWVzKQ0KDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyB1c2UgbW9kZWwgZml0IHRvIHRyYWluaW5nIHNldCB0byBldmFsdWF0ZSBvbiB0ZXN0IGRhdGENCnRlc3QkbHJfcHJlZGljdF9wcm9iIDwtIGFzLm51bWVyaWMocHJlZGljdCh0cmFpbl9scl9maXQsIG5ld2RhdGEgPSB0ZXN0LCANCiAgICB0eXBlID0gInJlc3BvbnNlIikpDQp0ZXN0X2xyX3ByZWRpY3Rpb24gPC0gcHJlZGljdGlvbih0ZXN0JGxyX3ByZWRpY3RfcHJvYiwgdGVzdCRwaWNrKQ0KdGVzdF9scl9hdWMgPC0gYXMubnVtZXJpYyhwZXJmb3JtYW5jZSh0ZXN0X2xyX3ByZWRpY3Rpb24sICJhdWMiKUB5LnZhbHVlcykNCg0KYGBgDQoNClBsb3R0aW5nIFJPQyBmb3IgbG9naXN0aWMgcmVncmVzc2lvbg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgUk9DIGZvciBsb2dpc3RpYyByZWdyZXNzaW9uDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnRyYWluX2xyX3JvYyA8LSBwZXJmb3JtYW5jZSh0cmFpbl9scl9wcmVkaWN0aW9uLCAidHByIiwgImZwciIpDQp0ZXN0X2xyX3JvYyA8LSBwZXJmb3JtYW5jZSh0ZXN0X2xyX3ByZWRpY3Rpb24sICJ0cHIiLCAiZnByIikNCnBkZihmaWxlID0gImZpZ19yZXRhaW5pbmdfY3VzdG9tZXJzX2xvZ2lzdGljX3JlZ3Jlc3Npb25fcm9jLnBkZiIsIA0KICAgIHdpZHRoID0gOC41LCBoZWlnaHQgPSA4LjUpDQoNCnBsb3Rfcm9jKHRyYWluX3JvYyA9IHRyYWluX2xyX3JvYywgDQogICAgdHJhaW5fYXVjID0gdHJhaW5fbHJfYXVjLCANCiAgICB0ZXN0X3JvYyA9IHRlc3RfbHJfcm9jLCANCiAgICB0ZXN0X2F1YyA9IHRlc3RfbHJfYXVjKSAgICAgICANCiAgICANCg0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBTdXBwb3J0IHZlY3RvciBtYWNoaW5lIHRyYWluaW5nLWFuZC10ZXN0DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnNldC5zZWVkICg5OTk5KSAgIyBmb3IgcmVwcm9kdWNpYmlsaXR5DQoNCiMgZGV0ZXJtaW5lIHR1bmluZyBwYXJhbWV0ZXJzIHByaW9yIHRvIGZpdHRpbmcgbW9kZWwgdG8gdHJhaW5pbmcgc2V0DQp0cmFpbl9zdm1fdHVuZSA8LSB0dW5lKHN2bSwgYXR0X3NwZWMsIGRhdGEgPSB0cmFpbiwNCiAgICAgICAgICAgICAgICAgICByYW5nZXMgPSBsaXN0KGdhbW1hID0gMl4oLTg6MSksIGNvc3QgPSAyXigwOjQpKSwNCiAgICAgICAgICAgICAgICAgICB0dW5lY29udHJvbCA9IHR1bmUuY29udHJvbChzYW1wbGluZyA9ICJmaXgiKSkNCg0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgZml0IHRoZSBzdXBwb3J0IHZlY3RvciBtYWNoaW5lIHRvIHRoZSB0cmFpbmluZyBzZXQgdXNpbmcgdHVuaW5nIHBhcmFtZXRlcnMNCnRyYWluX3N2bV9maXQgPC0gc3ZtKGF0dF9zcGVjLCBkYXRhID0gdHJhaW4sIA0KICAgIGNvc3QgPSB0cmFpbl9zdm1fdHVuZSRiZXN0LnBhcmFtZXRlcnMkY29zdCwgDQogICAgZ2FtbWE9dHJhaW5fc3ZtX3R1bmUkYmVzdC5wYXJhbWV0ZXJzJGdhbW1hLCANCiAgICBwcm9iYWJpbGl0eSA9IFRSVUUpICANCg0KdHJhaW5fc3ZtX3ByZWRpY3QgPC0gcHJlZGljdCh0cmFpbl9zdm1fZml0LCB0cmFpbiwgcHJvYmFiaWxpdHkgPSBUUlVFKQ0KdHJhaW4kc3ZtX3ByZWRpY3RfcHJvYiA8LSBhdHRyKHRyYWluX3N2bV9wcmVkaWN0LCAicHJvYmFiaWxpdGllcyIpWywxXQ0KdHJhaW5fc3ZtX3ByZWRpY3Rpb24gPC0gcHJlZGljdGlvbih0cmFpbiRzdm1fcHJlZGljdF9wcm9iLCB0cmFpbiRwaWNrKQ0KdHJhaW5fc3ZtX2F1YyA8LSBhcy5udW1lcmljKHBlcmZvcm1hbmNlKHRyYWluX3N2bV9wcmVkaWN0aW9uLCAiYXVjIilAeS52YWx1ZXMpDQoNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIHVzZSBtb2RlbCBmaXQgdG8gdHJhaW5pbmcgZGF0YSB0byBldmFsdWF0ZSBvbiB0ZXN0IHNldA0KdGVzdF9zdm1fcHJlZGljdCA8LSBwcmVkaWN0KHRyYWluX3N2bV9maXQsIHRlc3QsIHByb2JhYmlsaXR5ID0gVFJVRSkNCnRlc3Qkc3ZtX3ByZWRpY3RfcHJvYiA8LSBhdHRyKHRlc3Rfc3ZtX3ByZWRpY3QsICJwcm9iYWJpbGl0aWVzIilbLDFdDQp0ZXN0X3N2bV9wcmVkaWN0aW9uIDwtIHByZWRpY3Rpb24odGVzdCRzdm1fcHJlZGljdF9wcm9iLCB0ZXN0JHBpY2spDQp0ZXN0X3N2bV9hdWMgPC0gYXMubnVtZXJpYyhwZXJmb3JtYW5jZSh0ZXN0X3N2bV9wcmVkaWN0aW9uLCAiYXVjIilAeS52YWx1ZXMpDQoNCmBgYA0KDQpQbG90dGluZyBST0MgZm9yIHN1cHBvcnQgdmVjdG9yIG1hY2hpbmVzDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgUk9DIGZvciBzdXBwb3J0IHZlY3RvciBtYWNoaW5lcw0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KdHJhaW5fc3ZtX3JvYyA8LSBwZXJmb3JtYW5jZSh0cmFpbl9zdm1fcHJlZGljdGlvbiwgInRwciIsICJmcHIiKQ0KdGVzdF9zdm1fcm9jIDwtIHBlcmZvcm1hbmNlKHRlc3Rfc3ZtX3ByZWRpY3Rpb24sICJ0cHIiLCAiZnByIikNCg0KcGRmKGZpbGUgPSAiZmlnX3JldGFpbmluZ19jdXN0b21lcnNfc3VwcG9ydF92ZWN0b3JfbWFjaGluZV9yb2MucGRmIiwgDQogICAgd2lkdGggPSA4LjUsIGhlaWdodCA9IDguNSkNCg0KcGxvdF9yb2ModHJhaW5fcm9jID0gdHJhaW5fc3ZtX3JvYywgDQogICAgdHJhaW5fYXVjID0gdHJhaW5fc3ZtX2F1YywgDQogICAgdGVzdF9yb2MgPSB0ZXN0X3N2bV9yb2MsIA0KICAgIHRlc3RfYXVjID0gdGVzdF9zdm1fYXVjKSAgICANCg0KDQpgYGANCg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgUmFuZG9tIGZvcmVzdCB0cmFpbmluZy1hbmQtdGVzdA0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpzZXQuc2VlZCAoOTk5OSkgICMgZm9yIHJlcHJvZHVjaWJpbGl0eQ0KdHJhaW5fcmZfZml0IDwtIHJhbmRvbUZvcmVzdChhdHRfc3BlYywgZGF0YSA9IHRyYWluLCANCiAgIG10cnk9MywgaW1wb3J0YW5jZT1GQUxTRSwgbmEuYWN0aW9uPW5hLm9taXQpIA0KDQp0cmFpbiRyZl9wcmVkaWN0X3Byb2IgPC0gYXMubnVtZXJpYyhwcmVkaWN0KHRyYWluX3JmX2ZpdCwgdHlwZSA9ICJwcm9iIilbLDJdKQ0KdHJhaW5fcmZfcHJlZGljdGlvbiA8LSBwcmVkaWN0aW9uKHRyYWluJHJmX3ByZWRpY3RfcHJvYiwgdHJhaW4kcGljaykNCnRyYWluX3JmX2F1YyA8LSBhcy5udW1lcmljKHBlcmZvcm1hbmNlKHRyYWluX3JmX3ByZWRpY3Rpb24sICJhdWMiKUB5LnZhbHVlcykNCg0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgdXNlIG1vZGVsIGZpdCB0byB0cmFpbmluZyBzZXQgdG8gZXZhbHVhdGUgb24gdGVzdCBkYXRhDQp0ZXN0JHJmX3ByZWRpY3RfcHJvYiA8LSBhcy5udW1lcmljKHByZWRpY3QodHJhaW5fcmZfZml0LCBuZXdkYXRhID0gdGVzdCwgDQogICAgdHlwZSA9ICJwcm9iIilbLDJdKQ0KDQp0ZXN0X3JmX3ByZWRpY3Rpb24gPC0gcHJlZGljdGlvbih0ZXN0JHJmX3ByZWRpY3RfcHJvYiwgdGVzdCRwaWNrKQ0KdGVzdF9yZl9hdWMgPC0gYXMubnVtZXJpYyhwZXJmb3JtYW5jZSh0ZXN0X3JmX3ByZWRpY3Rpb24sICJhdWMiKUB5LnZhbHVlcykNCg0KYGBgDQoNClBsb3R0aW5nIFJPQyBmb3IgcmFuZG9tIGZvcmVzdA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIFJPQyBmb3IgcmFuZG9tIGZvcmVzdA0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KdHJhaW5fcmZfcm9jIDwtIHBlcmZvcm1hbmNlKHRyYWluX3JmX3ByZWRpY3Rpb24sICJ0cHIiLCAiZnByIikNCnRlc3RfcmZfcm9jIDwtIHBlcmZvcm1hbmNlKHRlc3RfcmZfcHJlZGljdGlvbiwgInRwciIsICJmcHIiKQ0KDQpwZGYoZmlsZSA9ICJmaWdfcmV0YWluaW5nX2N1c3RvbWVyc19yYW5kb21fZm9yZXN0X3JvYy5wZGYiLCANCiAgICB3aWR0aCA9IDguNSwgaGVpZ2h0ID0gOC41KQ0KDQpwbG90X3JvYyh0cmFpbl9yb2MgPSB0cmFpbl9yZl9yb2MsIA0KICAgIHRyYWluX2F1YyA9IHRyYWluX3JmX2F1YywgDQogICAgdGVzdF9yb2MgPSB0ZXN0X3JmX3JvYywgDQogICAgdGVzdF9hdWMgPSB0ZXN0X3JmX2F1YykgIA0KDQpgYGANCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIE5haXZlIEJheWVzIHRyYWluaW5nLWFuZC10ZXN0DQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCnNldC5zZWVkICg5OTk5KSAgIyBmb3IgcmVwcm9kdWNpYmlsaXR5DQp0cmFpbl9uYl9maXQgPC0gbmFpdmVCYXllcyhhdHRfc3BlYywgZGF0YSA9IHRyYWluKSANCnRyYWluJG5iX3ByZWRpY3RfcHJvYiA8LSBhcy5udW1lcmljKHByZWRpY3QodHJhaW5fbmJfZml0LCBuZXdkYXRhID0gdHJhaW4sDQogICAgdHlwZSA9ICJyYXciKVssMl0pDQp0cmFpbl9uYl9wcmVkaWN0aW9uIDwtIHByZWRpY3Rpb24odHJhaW4kbmJfcHJlZGljdF9wcm9iLCB0cmFpbiRwaWNrKQ0KdHJhaW5fbmJfYXVjIDwtIGFzLm51bWVyaWMocGVyZm9ybWFuY2UodHJhaW5fbmJfcHJlZGljdGlvbiwgImF1YyIpQHkudmFsdWVzKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgdXNlIG1vZGVsIGZpdCB0byB0cmFpbmluZyBzZXQgdG8gZXZhbHVhdGUgb24gdGVzdCBkYXRhDQp0ZXN0JG5iX3ByZWRpY3RfcHJvYiA8LSBhcy5udW1lcmljKHByZWRpY3QodHJhaW5fbmJfZml0LCBuZXdkYXRhID0gdGVzdCwgDQogICAgdHlwZSA9ICJyYXciKVssMl0pDQp0ZXN0X25iX3ByZWRpY3Rpb24gPC0gcHJlZGljdGlvbih0ZXN0JG5iX3ByZWRpY3RfcHJvYiwgdGVzdCRwaWNrKQ0KdGVzdF9uYl9hdWMgPC0gYXMubnVtZXJpYyhwZXJmb3JtYW5jZSh0ZXN0X25iX3ByZWRpY3Rpb24sICJhdWMiKUB5LnZhbHVlcykNCg0KYGBgDQoNClBsb3R0aW5nIFJPQyBmb3IgTmFpdmUgQmF5ZXMNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBST0MgZm9yIE5haXZlIEJheWVzDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQp0cmFpbl9uYl9yb2MgPC0gcGVyZm9ybWFuY2UodHJhaW5fbmJfcHJlZGljdGlvbiwgInRwciIsICJmcHIiKQ0KdGVzdF9uYl9yb2MgPC0gcGVyZm9ybWFuY2UodGVzdF9uYl9wcmVkaWN0aW9uLCAidHByIiwgImZwciIpDQoNCnBkZihmaWxlID0gImZpZ19yZXRhaW5pbmdfY3VzdG9tZXJzX25haXZlX2JheWVzX3JvYy5wZGYiLCANCiAgICB3aWR0aCA9IDguNSwgaGVpZ2h0ID0gOC41KQ0KDQpwbG90X3JvYyh0cmFpbl9yb2MgPSB0cmFpbl9uYl9yb2MsIA0KICAgIHRyYWluX2F1YyA9IHRyYWluX25iX2F1YywgDQogICAgdGVzdF9yb2MgPSB0ZXN0X25iX3JvYywgDQogICAgdGVzdF9hdWMgPSB0ZXN0X25iX2F1YykgICAgDQoNCg0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBOZXVyYWwgTmV0d29yayB0cmFpbmluZy1hbmQtdGVzdA0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpzZXQuc2VlZCAoOTk5OSkgICMgZm9yIHJlcHJvZHVjaWJpbGl0eQ0KdHJhaW5fbm5ldF9maXQgPC0gbm5ldChhdHRfc3BlYywgZGF0YSA9IHRyYWluLCBzaXplID0gMywgZGVjYXkgPSAwLjAsDQogICAgcHJvYmFiaWxpdHkgPSBUUlVFLCB0cmFjZSA9IEZBTFNFKSANCg0KdHJhaW4kbm5ldF9wcmVkaWN0X3Byb2IgPC0gYXMubnVtZXJpYyhwcmVkaWN0KHRyYWluX25uZXRfZml0LCBuZXdkYXRhID0gdHJhaW4pKQ0KdHJhaW5fbm5ldF9wcmVkaWN0aW9uIDwtIHByZWRpY3Rpb24odHJhaW4kbm5ldF9wcmVkaWN0X3Byb2IsIHRyYWluJHBpY2spDQp0cmFpbl9ubmV0X2F1YyA8LSBhcy5udW1lcmljKHBlcmZvcm1hbmNlKHRyYWluX25uZXRfcHJlZGljdGlvbiwgImF1YyIpQHkudmFsdWVzKQ0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgdXNlIG1vZGVsIGZpdCB0byB0cmFpbmluZyBzZXQgdG8gZXZhbHVhdGUgb24gdGVzdCBkYXRhDQp0ZXN0JG5uZXRfcHJlZGljdF9wcm9iIDwtIGFzLm51bWVyaWMocHJlZGljdCh0cmFpbl9ubmV0X2ZpdCwgbmV3ZGF0YSA9IHRlc3QpKQ0KdGVzdF9ubmV0X3ByZWRpY3Rpb24gPC0gcHJlZGljdGlvbih0ZXN0JG5uZXRfcHJlZGljdF9wcm9iLCB0ZXN0JHBpY2spDQp0ZXN0X25uZXRfYXVjIDwtIGFzLm51bWVyaWMocGVyZm9ybWFuY2UodGVzdF9ubmV0X3ByZWRpY3Rpb24sICJhdWMiKUB5LnZhbHVlcykNCmBgYA0KDQpQbG90dGluZyBST0MgZm9yIE5ldXJhbCBOZXR3b3JrDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgUk9DIGZvciBOZXVyYWwgTmV0d29yaw0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KdHJhaW5fbm5ldF9yb2MgPC0gcGVyZm9ybWFuY2UodHJhaW5fbm5ldF9wcmVkaWN0aW9uLCAidHByIiwgImZwciIpDQp0ZXN0X25uZXRfcm9jIDwtIHBlcmZvcm1hbmNlKHRlc3Rfbm5ldF9wcmVkaWN0aW9uLCAidHByIiwgImZwciIpDQoNCnBkZihmaWxlID0gImZpZ19yZXRhaW5pbmdfY3VzdG9tZXJzX25ldXJhbF9uZXR3b3JrX3JvYy5wZGYiLCANCiAgICB3aWR0aCA9IDguNSwgaGVpZ2h0ID0gOC41KQ0KDQpwbG90X3JvYyh0cmFpbl9yb2MgPSB0cmFpbl9ubmV0X3JvYywgdHJhaW5fYXVjID0gdHJhaW5fbm5ldF9hdWMsIA0KICAgIHRlc3Rfcm9jID0gdGVzdF9ubmV0X3JvYywgdGVzdF9hdWMgPSB0ZXN0X25uZXRfYXVjKSAgIA0KDQoNCmBgYA0K