Predicting Commuter Transportation Choices

Consumer choice is part of life and fundamental of markeing data science. To predict consumer choice, we use explanatory variables from the marketing mix, such as product characteristics, advertising and promotion, or the type of distribution channel. We note consumer characteristics, observable behaviors, survey responses, and demographic data. We build the discrete choice models of economics and generalized linear models of statistics - essential tools of mrketing data science.

To demonstrate choice methods, we will use the Sydney Transportation Study. Commuters can choose to go into the city by CAR or TRAIN The y response variabe (choice) is binary, so we can use logistic regression, a generalized linear model with a logit link. The logit is the natural logarithm of the odds ratio - mapping the set of positive numbers onto the set of all real numbers. The dataset contains 333 observations and 5 variables.

'data.frame':   333 obs. of  5 variables:
 $ cartime  : int  70 50 50 60 70 20 40 15 60 29 ...
 $ carcost  : int  50 230 70 108 60 32 30 8 60 20 ...
 $ traintime: int  64 60 58 93 68 72 60 22 83 40 ...
 $ traincost: int  39 32 40 62 26 65 37 20 31 17 ...
 $ choice   : Factor w/ 2 levels "CAR","TRAIN": 2 2 1 1 2 1 2 1 2 1 ...

Let’s rename our column names into something more readable and place them into a data frame.

Next, let’s create a scatter plot matrix and correlation heat map for a nice visualizations into a PDF file. In these visualizations, it shows pairwise relationships among these explanatory variables. As you can see below, CAR_TIME and CAR_COST are related; TRAIN_TIME and TRAIN_COST are related - or high positive correlation. Additionally, CAR_TIME are associated with longer TRAIN_TIME.

We will use a linear combination of the four explanatory variables to predict consumer choice. The fitted logistic regression model is show below.


Call:
glm(formula = sydney_model, family = binomial, data = sydney)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-2.1291  -0.6151  -0.1621   0.6166   2.8337  

Coefficients:
             Estimate Std. Error z value Pr(>|z|)    
(Intercept) -1.444027   0.584971  -2.469   0.0136 *  
Car_Time     0.056507   0.010911   5.179 2.23e-07 ***
Car_Cost     0.029842   0.006968   4.283 1.84e-05 ***
Train_Time   0.014918   0.009482   1.573   0.1156    
Train_Cost  -0.111293   0.016521  -6.737 1.62e-11 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 458.36  on 332  degrees of freedom
Residual deviance: 272.63  on 328  degrees of freedom
AIC: 282.63

Number of Fisher Scoring iterations: 5

Let’s create an ANOVA in accordance to logit link function:

Analysis of Deviance Table

Model: binomial, link: logit

Response: Choice

Terms added sequentially (first to last)

           Df Deviance Resid. Df Resid. Dev  Pr(>Chi)    
NULL                         332     458.36              
Car_Time    1   90.402       331     367.96 < 2.2e-16 ***
Car_Cost    1   22.822       330     345.14 1.778e-06 ***
Train_Time  1    7.563       329     337.57  0.005956 ** 
Train_Cost  1   64.938       328     272.63 7.727e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Next, compute predicted probability of taking the train using ‘predict.glm’ to create a density lattice conditioned on an actual commuter car-or-train choices showing the degree to which these predictions are correct:

To obtain a car-or-train prediction for each commuter, we set a predicted probability cut-off. Suppose we classify commuters with a 0.50 cut-off. That is, if the predicted probability of taking the train is > 0.50, then we predict that the commuter will take the train. Otherwise, we predict the commuter will take the car.

Let’s create a Confusion Matrix which result in a four-fold table to show that we have correctly predicted transportation choice: 82.6 percent of the time.

       
        CAR TRAIN
  CAR   155    30
  TRAIN  28   120

Percent Accuracy:  82.6

Next, let’s create some management questions by analyzing the choices that consumers make - choices in the marketplace, choices in response to marketing action, and choices in response to consumer surveys. In this case, we often use logistic regression and multinomial logit models to analyze choice data.

How much lower would train ticket prices have to be to increase public transportation usage (TRAIN) by 10 percent?


Solution Price:  33.84685
[1] 38.21922

How much do administrators need to lower prices?

Error in int_abline(a = a, b = b, h = h, v = v, untf = untf, ...) : 
  plot.new has not been called yet
LS0tDQp0aXRsZTogIk1hcmtldGluZyBBbmFseXRpY3MgLSBQcmVkaWN0aW5nIENvbnN1bWVyIENob2ljZSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiNQcmVkaWN0aW5nIENvbW11dGVyIFRyYW5zcG9ydGF0aW9uIENob2ljZXMgDQoNCkNvbnN1bWVyIGNob2ljZSBpcyBwYXJ0IG9mIGxpZmUgYW5kIGZ1bmRhbWVudGFsIG9mIG1hcmtlaW5nIGRhdGEgc2NpZW5jZS4gVG8gcHJlZGljdCBjb25zdW1lciBjaG9pY2UsIHdlIHVzZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgZnJvbSB0aGUgbWFya2V0aW5nIG1peCwgc3VjaCBhcyBwcm9kdWN0IGNoYXJhY3RlcmlzdGljcywgYWR2ZXJ0aXNpbmcgYW5kIHByb21vdGlvbiwgb3IgdGhlIHR5cGUgb2YgZGlzdHJpYnV0aW9uIGNoYW5uZWwuIFdlIG5vdGUgY29uc3VtZXIgY2hhcmFjdGVyaXN0aWNzLCBvYnNlcnZhYmxlIGJlaGF2aW9ycywgc3VydmV5IHJlc3BvbnNlcywgYW5kIGRlbW9ncmFwaGljIGRhdGEuIFdlIGJ1aWxkIHRoZSBkaXNjcmV0ZSBjaG9pY2UgbW9kZWxzIG9mIGVjb25vbWljcyBhbmQgZ2VuZXJhbGl6ZWQgbGluZWFyIG1vZGVscyBvZiBzdGF0aXN0aWNzIC0gZXNzZW50aWFsIHRvb2xzIG9mIG1ya2V0aW5nIGRhdGEgc2NpZW5jZS4NCg0KVG8gZGVtb25zdHJhdGUgY2hvaWNlIG1ldGhvZHMsIHdlIHdpbGwgdXNlIHRoZSBTeWRuZXkgVHJhbnNwb3J0YXRpb24gU3R1ZHkuIENvbW11dGVycyBjYW4gY2hvb3NlIHRvIGdvIGludG8gdGhlIGNpdHkgYnkgQ0FSIG9yIFRSQUlOIFRoZSB5IHJlc3BvbnNlIHZhcmlhYmUgKGNob2ljZSkgaXMgYmluYXJ5LCBzbyB3ZSBjYW4gdXNlIGxvZ2lzdGljIHJlZ3Jlc3Npb24sIGEgZ2VuZXJhbGl6ZWQgbGluZWFyIG1vZGVsIHdpdGggYSBsb2dpdCBsaW5rLiBUaGUgbG9naXQgaXMgdGhlIG5hdHVyYWwgbG9nYXJpdGhtIG9mIHRoZSBvZGRzIHJhdGlvIC0gbWFwcGluZyB0aGUgc2V0IG9mIHBvc2l0aXZlIG51bWJlcnMgb250byB0aGUgc2V0IG9mIGFsbCByZWFsIG51bWJlcnMuIFRoZSBkYXRhc2V0IGNvbnRhaW5zIDMzMyBvYnNlcnZhdGlvbnMgYW5kIDUgdmFyaWFibGVzLg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQpsaWJyYXJ5KGxhdHRpY2UpICAjIG11bHRpdmFyaWF0ZSBkYXRhIHZpc3VhbGl6YXRpb24NCmxvYWQoImNvcnJlbGF0aW9uX2hlYXRfbWFwLlJEYXRhIikgICMgZnJvbSBSIHV0aWxpdHkgcHJvZ3JhbXMNCg0KIyByZWFkIGRhdGEgZnJvbSBjb21tYS1kZWxpbWl0ZWQgdGV4dCBmaWxlLi4uIGNyZWF0ZSBkYXRhIGZyYW1lIG9iamVjdA0Kc3lkbmV5IDwtIHJlYWQuY3N2KCJzeWRuZXkuY3N2IikNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQpzdHIoc3lkbmV5KQ0KYGBgDQoNCkxldCdzIHJlbmFtZSBvdXIgY29sdW1uIG5hbWVzIGludG8gc29tZXRoaW5nIG1vcmUgcmVhZGFibGUgYW5kIHBsYWNlIHRoZW0gaW50byBhIGRhdGEgZnJhbWUuDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiNyZW5hbWUgbGFiZWxzDQpuYW1lcyhzeWRuZXkpIDwtIGMoIkNhcl9UaW1lIiwgIkNhcl9Db3N0IiwgIlRyYWluX1RpbWUiLCAiVHJhaW5fQ29zdCIsICJDaG9pY2UiKQ0KDQojY3JlYXRlIGRhdGEgZnJhbWUgb2JqZWN0IGZvciB2YXJpYWJsZXMgKCJDYXJfVGltZSIsICJDYXJfQ29zdCIsICJUcmFpbl9UaW1lIiwgIlRyYWluX0Nvc3QiKQ0KcGxvdHRpbmdfZGF0YV9mcmFtZSA8LSBzeWRuZXlbLCAxOjRdDQpwbG90dGluZ19kYXRhX2ZyYW1lDQpgYGANCg0KTmV4dCwgbGV0J3MgY3JlYXRlIGEgc2NhdHRlciBwbG90IG1hdHJpeCBhbmQgY29ycmVsYXRpb24gaGVhdCBtYXAgZm9yIGEgbmljZSB2aXN1YWxpemF0aW9ucyBpbnRvIGEgUERGIGZpbGUuIEluIHRoZXNlIHZpc3VhbGl6YXRpb25zLCBpdCBzaG93cyBwYWlyd2lzZSByZWxhdGlvbnNoaXBzIGFtb25nIHRoZXNlIGV4cGxhbmF0b3J5IHZhcmlhYmxlcy4gQXMgeW91IGNhbiBzZWUgYmVsb3csIENBUl9USU1FIGFuZCBDQVJfQ09TVCBhcmUgcmVsYXRlZDsgVFJBSU5fVElNRSBhbmQgVFJBSU5fQ09TVCBhcmUgcmVsYXRlZCAtIG9yIGhpZ2ggcG9zaXRpdmUgY29ycmVsYXRpb24uIEFkZGl0aW9uYWxseSwgQ0FSX1RJTUUgYXJlIGFzc29jaWF0ZWQgd2l0aCBsb25nZXIgVFJBSU5fVElNRS4NCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyBzY2F0dGVyIHBsb3QgbWF0cml4IHdpdGggc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uDQojIG1vZGVscyBhbmQgbG93ZXNzIHNtb290aCBmaXRzIGZvciB2YXJpYWJsZSBwYWlycw0KcGRmKGZpbGUgPSAiZmlnX3ByZWRpY3RpbmdfY2hvaWNlX3NjYXR0ZXJfcGxvdF9tYXRyaXgucGRmIiwgDQogICAgd2lkdGggPSA4LjUsIGhlaWdodCA9IDguNSkNCg0KcGFpcnMocGxvdHRpbmdfZGF0YV9mcmFtZSwNCiAgICBwYW5lbCA9IGZ1bmN0aW9uKHgsIHkpIHsNCiAgICAgICAgcG9pbnRzKHgsIHksIGNleCA9IDAuNSkNCiAgICAgICAgYWJsaW5lKGxtKHkgfiB4KSwgbHR5ID0gInNvbGlkIiwgY29sID0gInJlZCIpDQogICAgICAgIGxpbmVzKGxvd2Vzcyh4LCB5KSkNCiAgICAgICAgfSkNCg0KZGV2Lm9mZigpIA0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgY29ycmVsYXRpb24gaGVhdCBtYXAgZm9yIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMNCnBkZihmaWxlID0gImZpZ19wcmVkaWN0aW5nX2Nob2ljZV9jb3JyZWxhdGlvbl9oZWF0X21hcC5wZGYiLA0KICAgIHdpZHRoID0gOC41LCBoZWlnaHQgPSA4LjUpDQoNCnN5ZG5leV9jb3JtYXQgPC0gY29yKHN5ZG5leVssIGMoIkNhcl9UaW1lIiwgIkNhcl9Db3N0IiwgIlRyYWluX1RpbWUiLCAiVHJhaW5fQ29zdCIpXSkNCg0KY29ycmVsYXRpb25faGVhdF9tYXAoc3lkbmV5X2Nvcm1hdCkNCg0KZGV2Lm9mZigpDQpgYGANCg0KV2Ugd2lsbCB1c2UgYSBsaW5lYXIgY29tYmluYXRpb24gb2YgdGhlIGZvdXIgZXhwbGFuYXRvcnkgdmFyaWFibGVzIHRvIHByZWRpY3QgY29uc3VtZXIgY2hvaWNlLiBUaGUgZml0dGVkIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgaXMgc2hvdyBiZWxvdy4NCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyBzcGVjaWZ5IGFuZCBmaXQgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbA0Kc3lkbmV5X21vZGVsIDwtIHtDaG9pY2UgfiBDYXJfVGltZSArIENhcl9Db3N0ICsgVHJhaW5fVGltZSArIFRyYWluX0Nvc3R9DQoNCnN5ZG5leV9maXQgPC0gZ2xtKHN5ZG5leV9tb2RlbCwgZmFtaWx5PWJpbm9taWFsLCBkYXRhPXN5ZG5leSkNCg0KcHJpbnQoc3VtbWFyeShzeWRuZXlfZml0KSkNCmBgYA0KDQpMZXQncyBjcmVhdGUgYW4gQU5PVkEgaW4gYWNjb3JkYW5jZSB0byBsb2dpdCBsaW5rIGZ1bmN0aW9uOg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQpwcmludChhbm92YShzeWRuZXlfZml0LCB0ZXN0PSJDaGlzcSIpKQ0KYGBgDQoNCk5leHQsIGNvbXB1dGUgcHJlZGljdGVkIHByb2JhYmlsaXR5IG9mIHRha2luZyB0aGUgdHJhaW4gdXNpbmcgJ3ByZWRpY3QuZ2xtJyB0byBjcmVhdGUgYSBkZW5zaXR5IGxhdHRpY2UgY29uZGl0aW9uZWQgb24gYW4gYWN0dWFsIGNvbW11dGVyIGNhci1vci10cmFpbiBjaG9pY2VzIHNob3dpbmcgdGhlIGRlZ3JlZSB0byB3aGljaCB0aGVzZSBwcmVkaWN0aW9ucyBhcmUgY29ycmVjdDoNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0Kc3lkbmV5JFByZWRpY3RfUHJvYl9UUkFJTiA8LSBwcmVkaWN0LmdsbShzeWRuZXlfZml0LCB0eXBlID0gInJlc3BvbnNlIikgDQoNCnBkZihmaWxlID0gImZpZ19wcmVkaWN0aW5nX2Nob2ljZV9kZW5zaXR5X2V2YWx1YXRpb24ucGRmIiwgDQogICAgd2lkdGggPSA4LjUsIGhlaWdodCA9IDguNSkNCg0KcGxvdHRpbmdfb2JqZWN0IDwtIGRlbnNpdHlwbG90KCB+IFByZWRpY3RfUHJvYl9UUkFJTiB8IENob2ljZSwgDQogICAgICAgICAgICAgICBkYXRhID0gc3lkbmV5LCANCiAgICAgICAgICAgICAgIGxheW91dCA9IGMoMSwyKSwgYXNwZWN0PTEsIGNvbCA9ICJkYXJrYmx1ZSIsIA0KICAgICAgICAgICAgICAgcGxvdC5wb2ludHMgPSAicnVnIiwNCiAgICAgICAgICAgICAgIHN0cmlwPWZ1bmN0aW9uKC4uLikgc3RyaXAuZGVmYXVsdCguLi4sIHN0eWxlPTEpLA0KICAgICAgICAgICAgICAgeGxhYj0iUHJlZGljdGVkIFByb2JhYmlsaXR5IG9mIFRha2luZyBUcmFpbiIpIA0KDQpwcmludChwbG90dGluZ19vYmplY3QpIA0KDQpkZXYub2ZmKCkNCmBgYA0KDQpUbyBvYnRhaW4gYSBjYXItb3ItdHJhaW4gcHJlZGljdGlvbiBmb3IgZWFjaCBjb21tdXRlciwgd2Ugc2V0IGEgcHJlZGljdGVkIHByb2JhYmlsaXR5IGN1dC1vZmYuIFN1cHBvc2Ugd2UgY2xhc3NpZnkgY29tbXV0ZXJzIHdpdGggYSAwLjUwIGN1dC1vZmYuIFRoYXQgaXMsIGlmIHRoZSBwcmVkaWN0ZWQgcHJvYmFiaWxpdHkgb2YgdGFraW5nIHRoZSB0cmFpbiBpcyA+IDAuNTAsIHRoZW4gd2UgcHJlZGljdCB0aGF0IHRoZSBjb21tdXRlciB3aWxsIHRha2UgdGhlIHRyYWluLiBPdGhlcndpc2UsIHdlIHByZWRpY3QgdGhlIGNvbW11dGVyIHdpbGwgdGFrZSB0aGUgY2FyLg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIHByZWRpY3RlZCBjYXItb3ItdHJhaW4gY2hvaWNlIHVzaW5nIDAuNSBjdXQtb2ZmDQpzeWRuZXkkUHJlZGljdF9DaG9pY2UgPC0gaWZlbHNlKChzeWRuZXkkUHJlZGljdF9Qcm9iX1RSQUlOID4gMC41KSwgMiwgMSkNCnN5ZG5leSRQcmVkaWN0X0Nob2ljZSA8LSBmYWN0b3Ioc3lkbmV5JFByZWRpY3RfQ2hvaWNlLCBsZXZlbHMgPSBjKDEsIDIpLCBsYWJlbHMgPSBjKCJDQVIiLCAiVFJBSU4iKSkNCmBgYA0KDQpMZXQncyBjcmVhdGUgYSBDb25mdXNpb24gTWF0cml4IHdoaWNoIHJlc3VsdCBpbiBhIGZvdXItZm9sZCB0YWJsZSB0byBzaG93IHRoYXQgd2UgaGF2ZSBjb3JyZWN0bHkgcHJlZGljdGVkIHRyYW5zcG9ydGF0aW9uIGNob2ljZTogODIuNiBwZXJjZW50IG9mIHRoZSB0aW1lLg0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQpjb25mdXNpb25fbWF0cml4IDwtIHRhYmxlKHN5ZG5leSRQcmVkaWN0X0Nob2ljZSwgc3lkbmV5JENob2ljZSkNCg0KY2F0KCJcbkNvbmZ1c2lvbiBNYXRyaXggKHJvd3MgPSBQcmVkaWN0ZWQgQ2hvaWNlLCBjb2x1bW5zID0gQWN0dWFsIENob2ljZVxuIikNCg0KcHJpbnQoY29uZnVzaW9uX21hdHJpeCkNCg0KYGBgDQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCnByZWRpY3RpdmVfYWNjdXJhY3kgPC0gKGNvbmZ1c2lvbl9tYXRyaXhbMSwxXSArIGNvbmZ1c2lvbl9tYXRyaXhbMiwyXSkvc3VtKGNvbmZ1c2lvbl9tYXRyaXgpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KY2F0KCJcblBlcmNlbnQgQWNjdXJhY3k6ICIsIHJvdW5kKHByZWRpY3RpdmVfYWNjdXJhY3kgKiAxMDAsIGRpZ2l0cyA9IDEpKQ0KDQpgYGANCg0KTmV4dCwgbGV0J3MgY3JlYXRlIHNvbWUgbWFuYWdlbWVudCBxdWVzdGlvbnMgYnkgYW5hbHl6aW5nIHRoZSBjaG9pY2VzIHRoYXQgY29uc3VtZXJzIG1ha2UgLSBjaG9pY2VzIGluIHRoZSBtYXJrZXRwbGFjZSwgY2hvaWNlcyBpbiByZXNwb25zZSB0byBtYXJrZXRpbmcgYWN0aW9uLCBhbmQgY2hvaWNlcyBpbiByZXNwb25zZSB0byBjb25zdW1lciBzdXJ2ZXlzLiBJbiB0aGlzIGNhc2UsIHdlIG9mdGVuIHVzZSBsb2dpc3RpYyByZWdyZXNzaW9uIGFuZCBtdWx0aW5vbWlhbCBsb2dpdCBtb2RlbHMgdG8gYW5hbHl6ZSBjaG9pY2UgZGF0YS4NCg0KIyNIb3cgbXVjaCBsb3dlciB3b3VsZCB0cmFpbiB0aWNrZXQgcHJpY2VzIGhhdmUgdG8gYmUgdG8gaW5jcmVhc2UgcHVibGljIHRyYW5zcG9ydGF0aW9uIHVzYWdlIChUUkFJTikgYnkgMTAgcGVyY2VudD8NCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KdHJhaW5fY29zdF92ZWN0b3IgPC0gc2VxKG1pbihzeWRuZXkkVHJhaW5fQ29zdCksIG1heChzeWRuZXkkVHJhaW5fQ29zdCksIGxlbmd0aD0xMDAwKQ0KDQpiZXRhLnZlY3RvciA8LSBzeWRuZXlfZml0JGNvZWZmaWNpZW50cw0KDQp0cmFpbl9wcm9iYWJpbGl0eV92ZWN0b3IgPC0gbnVtZXJpYygxMDAwKQ0KZm9yIChpIGluIDE6MTAwMCkgew0KICAgICAgIFgudmVjdG9yIDwtIGMoMSwgbWVhbihzeWRuZXkkQ2FyX1RpbWUpLCBtZWFuKHN5ZG5leSRUcmFpbl9UaW1lKSwNCiAgICAgICAgICAgbWVhbihzeWRuZXkkQ2FyX0Nvc3QpLCB0cmFpbl9jb3N0X3ZlY3RvcltpXSkNCiAgICAgICB0cmFpbl9wcm9iYWJpbGl0eV92ZWN0b3JbaV0gPC0gDQogICAgICAgICAgIGV4cChYLnZlY3RvciAlKiUgYmV0YS52ZWN0b3IpLw0KICAgICAgICAgICAgICAgKDEgKyBleHAoWC52ZWN0b3IgJSolIGJldGEudmVjdG9yKSkNCiAgICAgICB9IA0KYGBgDQoNCg0KYGBge3IgZXZhbD1UUlVFLCBlY2hvPUZBTFNFfQ0KIyBjdXJyZW50bHkgMTUwIG91dCBvZiAzMzMgY29tbXV0ZXJzICg0NSBwZXJjZW50KSB1c2UgdGhlIHRyYWluICAgICAgIA0KIyBkZXRlcm1pbmUgcHJpY2UgcmVxdWlyZWQgZm9yIDU1IHBlcmNlbnQgb2YgY29tbXV0ZXJzIHRvIHRha2UgdGhlIHRyYWluIA0KIyB0aGlzIGlzIHRoZSBkZXNpcmVkIHF1b3RhIHNldCBieSBwdWJsaWMgYWRtaW5pc3RyYXRvcnMNCmluZGV4IDwtIDEgICMgYmVnaW5uaW5nIGluZGV4IGZvciBzZWFyY2gNCndoaWxlICh0cmFpbl9wcm9iYWJpbGl0eV92ZWN0b3JbaW5kZXhdID4gMC41NSkgaW5kZXggPC0gaW5kZXggKyAxDQpTb2x1dGlvbl9QcmljZSA8LSB0cmFpbl9jb3N0X3ZlY3RvcltpbmRleF0NCmNhdCgiXG5Tb2x1dGlvbiBQcmljZTogIiwgU29sdXRpb25fUHJpY2UpDQoNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQpDdXJyZW50X01lYW5fUHJpY2UgPC0gbWVhbihzeWRuZXkkVHJhaW5fQ29zdCkNCkN1cnJlbnRfTWVhbl9QcmljZQ0KYGBgDQoNCiMjSG93IG11Y2ggZG8gYWRtaW5pc3RyYXRvcnMgbmVlZCB0byBsb3dlciBwcmljZXM/DQoNCmBgYHtyIGV2YWw9VFJVRSwgZWNobz1GQUxTRX0NCiMgdXNlIGdyZWF0ZXN0IGludGVnZXIgZnVuY3Rpb24gdG8gZW5zdXJlIHF1b3RhIGlzIGV4Y2VlZGVkDQpDZW50c19Mb3dlciA8LSBjZWlsaW5nKEN1cnJlbnRfTWVhbl9QcmljZSAtIFNvbHV0aW9uX1ByaWNlKQ0KY2F0KCJcbkxvd2VyIHByaWNlcyBieSAiLCBDZW50c19Mb3dlciwgImNlbnRzXG4iKQ0KIA0KcGRmKGZpbGUgPSAiZmlnX3ByZWRpY3RpbmdfY2hvaWNlX3RpY2tldF9wcmljZV9zb2x1dGlvbi5wZGYiLCANCiAgICB3aWR0aCA9IDguNSwgaGVpZ2h0ID0gOC41KSANCg0KcGxvdCh0cmFpbl9jb3N0X3ZlY3RvciwgdHJhaW5fcHJvYmFiaWxpdHlfdmVjdG9yLA0KICAgICB0eXBlPSJsIix5bGltPWMoMCwxLjApLCBsYXMgPSAxLCANCiAgICAgeGxhYj0iQ29zdCBvZiBUYWtpbmcgdGhlIFRyYWluIChpbiBjZW50cykiLA0KICAgICB5bGFiPSJFc3RpbWF0ZWQgUHJvYmFiaWxpdHkgb2YgVGFraW5nIHRoZSBUcmFpbiIpDQoNCmBgYA0KDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0V9DQojIHBsb3QgY3VycmVudCBhdmVyYWdlIHRyYWluIHRpY2tldCBwcmljZSBhcyB2ZXJ0aWNhbCBsaW5lICAgICANCmFibGluZSh2ID0gQ3VycmVudF9NZWFuX1ByaWNlLCBjb2wgPSAicmVkIiwgbHR5ID0gInNvbGlkIiwgbHdkID0gMikgICAgDQphYmxpbmUodiA9IFNvbHV0aW9uX1ByaWNlLCBjb2wgPSAiYmx1ZSIsIGx0eSA9ICJkYXNoZWQiLCBsd2QgPSAyKQ0KDQpsZWdlbmQoInRvcHJpZ2h0IiwgbGVnZW5kID0gYygiQ3VycmVudCBNZWFuIFRyYWluIFRpY2tldCBQcmljZSIsIA0KICAgICAgICBwYXN0ZSgiU29sdXRpb24gUHJpY2UgKCIsIENlbnRzX0xvd2VyLCAiIENlbnRzIExvd2VyKSIsIHNlcCA9ICIiKSksIA0KICAgIGNvbCA9IGMoInJlZCIsICJibHVlIiksIHBjaCA9IGMoTkEsIE5BKSwgbHdkID0gYygyLCAyKSwNCiAgICBib3JkZXIgPSAiYmxhY2siLCBsdHkgPSBjKCJzb2xpZCIsICJkYXNoZWQiKSwgY2V4ID0gMS4yNSkNCmRldi5vZmYoKSAgICAgICANCg0KYGBgDQoNCiA=