Aims of this notebook

Requirements

We assume that you have:

If you struggle with basics of R, you may also find this online book useful: https://bookdown.org/ndphillips/YaRrr/


Multiple regression

Load the fraud_data dataset using the load command. The dataset is located in the folder ./data (assuming you are in the homework folder) and contains 1000 cases of employee fraud in financial trading companies.

The columns of this dataset are:

Task: multiple regression recap

Build a regression model that models the damage cause through the employees’ gender and promotion status.

#your code here

What is the mean absolute error (MAE) of your model?

#your code here

Now add the additional predictor variable years_experience. How does this affect your model’s MAE? Did you expect this?

#your code here

Finally, build the full model (i.e. include all main effects and interaction effects). Plot the residuals of that model against the observed values.

#your code here

Task: multiple regression model selection

You can decide empirically, which combination of predictors results in the best model fit.

Start by building both a “null” model (i.e. only the intercept) and a “full” model (also called the saturated model).

#your code here

Now start from the full model and use backwards stepwise regression. Which model does this procedure result in?

#your code here

Do the same with forward stepwise regression. Does this result in the same model?

#your code here

Finally, try to implement the bidirectional stepwise regression (hint: use “both” for the direction argument).

#your code here

What do these findings tell you?

Task: multiple regression model comparison

You will often end up with different models of the same outcome variable. If these models are nested (i.e. one model can be derived from the other by removing model parameters), then you can use inferential statistics to determine whether one model is significantly worse than another.

In R, you can use the anova function to conduct an analysis of variance on two models to determine whether a simpler model is significantly worse than a more complex model.

Perform the model comparison test between (1) the full model vs the null model, (2) a ‘gender-only’ model and a ‘gender + promotion’ model, and (3) between the full model and the ‘gender + promotion’ model.

#your code here

Rank the models from best to worst (use equal ranks if there is no significant difference).

Ranks come here:

  1. … …

Logistic regression

Often you want to build a model to either understand relationships in the data, make predictions, or both, about an outcome variable that is scored as 0/1, present/not present, arrested/not arrested, etc. If such an outcome variable has only two levels, we also speak of a binary or dichotomous outcome.

Regression models can be applied in this context too. To understand what the special issue with binary outcome variables is, let’s have a look at a dataset.

Load the attack_data dataset from ./data. We use this dataset to revise concepts from the lecture. This dataset represents whether or not a website was hacked and the number of attempted hacking attacks Columns are:

Task: logistic regression - fitting the GLM

Build a logistic regression model that models whether or not a website was hacked through the number of attacks:

#your code here

Task: logistic regression - interpreting the model

Take a look at the model summary. Remember what the logit model does? If we model the “log-odds”, then the coefficients (what we call the intercept and slope in linear regression) need to be interpreted as such.

But because the log-odds are hard to interpret, we want to transform them back to the more interpretable odds.

From the video above, you will have learned that you can reverse the natural logarithm by taking e to the power of the logarithm.

Do this transformation:

#your code here

What does this yield (i.e. how do you intepret these values)?

What would the interpretation of these findings look like in your own words?

Task: logistic regression - curve fitting

Similar to the “line-fitting” of linear regression, we can also look at the fitted model visually.

You can see that the model (= the curve) predicts values exclusively in the 0:1 range. However, you can also see that while the majority of the predicted values is either 0 or 1, some values are in between (e.g. around attempts == 500). This is the reason why you need thresholds if you want to ascertain the accuracy of such a model. In Year 3, you will learn about applications of this thresholding for logistic regression in machine learning.

You can see the relationship between fitted values (i.e. probabilities of a case being in on eof the two outcome classes - hacked vs not hacked - given a certain number of attempts) and the observed values:

END


LS0tCnRpdGxlOiAiTXVsdGlwbGUgcmVncmVzc2lvbiwgbG9naXN0aWMgcmVncmVzc2lvbiIKYXV0aG9yOiAiQiBLbGVpbmJlcmciCnN1YnRpdGxlOiBEZXB0IG9mIFNlY3VyaXR5IGFuZCBDcmltZSBTY2llbmNlLCBVQ0wKb3V0cHV0OgogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgojIyBBaW1zIG9mIHRoaXMgbm90ZWJvb2sKCi0gbXVsdGlwbGUgcmVncmVzc2lvbgogICAgLSByZWNhcCAKICAgIC0gbW9kZWwgc2VsZWN0aW9uCiAgICAtIG1vZGVsIGNvbXBhcmlzb24KLSBsb2dpc3RpYyByZWdyZXNzaW9uCiAgICAtIGxpbmsgZnVuY3Rpb24KICAgIC0gZml0dGluZyB0aGUgR0xNCiAgICAtIGludGVycHJldGluZyB0aGUgbW9kZWwKICAgIC0gbW9kZWwgY29tcGFyaXNvbgoKIyMgUmVxdWlyZW1lbnRzCgpXZSBhc3N1bWUgdGhhdCB5b3UgaGF2ZToKCi0gcmVhZCB0aGUgcmVxdWlyZWQgbGl0ZXJhdHVyZSBmb3Igd2Vla3MgMS0zCi0gcmV2aXNlZCB0aGUgbGVjdHVyZXMKLSBjb21wbGV0ZWQgdGhlIGludHJvZHVjdG9yeSBSIHR1dG9yaWFscyAoMTIgc3RlcHMgJiBIb3cgdG8gc29sdmUgcHJvYmxlbXMpIGFzIHdlbGwgYXMgdGhlIHR1dG9yaWFsIGZyb20gd2VlayAyCi0gY29tcGxldGVkIHRoZSBob21ld29yayBpbiB0aGlzIG1vZHVsZSBzbyBmYXIKLSByZXBsaWNhdGVkIHRoZSBjb2RlIGZyb20gdGhlIGxlY3R1cmVzIChpZiBjb25jZXB0cy9SIGltcGxlbWVudGF0aW9uIGlzIHVuY2xlYXIpCgpJZiB5b3Ugc3RydWdnbGUgd2l0aCBiYXNpY3Mgb2YgUiwgeW91IG1heSBhbHNvIGZpbmQgdGhpcyBvbmxpbmUgYm9vayB1c2VmdWw6IFtodHRwczovL2Jvb2tkb3duLm9yZy9uZHBoaWxsaXBzL1lhUnJyL10oaHR0cHM6Ly9ib29rZG93bi5vcmcvbmRwaGlsbGlwcy9ZYVJyci8pCgotLS0KCiMjIE11bHRpcGxlIHJlZ3Jlc3Npb24KCkxvYWQgdGhlIGBmcmF1ZF9kYXRhYCBkYXRhc2V0IHVzaW5nIHRoZSBgbG9hZGAgY29tbWFuZC4gVGhlIGRhdGFzZXQgaXMgbG9jYXRlZCBpbiB0aGUgZm9sZGVyIGAuL2RhdGFgIChhc3N1bWluZyB5b3UgYXJlIGluIHRoZSBob21ld29yayBmb2xkZXIpIGFuZCBjb250YWlucyAxMDAwIGNhc2VzIG9mIGVtcGxveWVlIGZyYXVkIGluIGZpbmFuY2lhbCB0cmFkaW5nIGNvbXBhbmllcy4KClRoZSBjb2x1bW5zIG9mIHRoaXMgZGF0YXNldCBhcmU6CgotIGRhbWFnZTogZGFtYWdlIGNhdXNlZCBpbiBVU0QKLSBnZW5kZXI6IDAgPSBmZW1hbGUsIDEgPSBtYWxlCi0gcHJvbW90ZWQ6IHdoZXRoZXIgdGhlIGVtcGxveWVlIHdhcyBwcm9tb3RlZCBpbiB0aGUgcGFzdCA1IHllYXJzICgwID0gbm8sIDEgPSB5ZXMpCi0geWVhcnNfZXhwZXJpZW5jZTogbnVtYmVyIG9mIHllYXJzIG9mIG92ZXJhbGwgam9iIGV4cGVyaWVuY2UgaW4gdGhpcyBvciBhIHJlbGF0ZWQgcG9zaXRpb24KCiMjIyBUYXNrOiBtdWx0aXBsZSByZWdyZXNzaW9uIHJlY2FwCgpCdWlsZCBhIHJlZ3Jlc3Npb24gbW9kZWwgdGhhdCBtb2RlbHMgdGhlIGRhbWFnZSBjYXVzZSB0aHJvdWdoIHRoZSBlbXBsb3llZXMnIGdlbmRlciBhbmQgcHJvbW90aW9uIHN0YXR1cy4KCmBgYHtyfQojeW91ciBjb2RlIGhlcmUKCmBgYAoKV2hhdCBpcyB0aGUgbWVhbiBhYnNvbHV0ZSBlcnJvciAoTUFFKSBvZiB5b3VyIG1vZGVsPwoKYGBge3J9CiN5b3VyIGNvZGUgaGVyZQoKYGBgCgpOb3cgYWRkIHRoZSBhZGRpdGlvbmFsIHByZWRpY3RvciB2YXJpYWJsZSBgeWVhcnNfZXhwZXJpZW5jZWAuIEhvdyBkb2VzIHRoaXMgYWZmZWN0IHlvdXIgbW9kZWwncyBNQUU/IERpZCB5b3UgZXhwZWN0IHRoaXM/CgpgYGB7cn0KI3lvdXIgY29kZSBoZXJlCgpgYGAKCkZpbmFsbHksIGJ1aWxkIHRoZSBmdWxsIG1vZGVsIChpLmUuIGluY2x1ZGUgYWxsIG1haW4gZWZmZWN0cyBhbmQgaW50ZXJhY3Rpb24gZWZmZWN0cykuIFBsb3QgdGhlIHJlc2lkdWFscyBvZiB0aGF0IG1vZGVsIGFnYWluc3QgdGhlIG9ic2VydmVkIHZhbHVlcy4KCmBgYHtyfQojeW91ciBjb2RlIGhlcmUKCmBgYAoKIyMjIFRhc2s6IG11bHRpcGxlIHJlZ3Jlc3Npb24gbW9kZWwgc2VsZWN0aW9uCgpZb3UgY2FuIGRlY2lkZSBlbXBpcmljYWxseSwgd2hpY2ggY29tYmluYXRpb24gb2YgcHJlZGljdG9ycyByZXN1bHRzIGluIHRoZSBiZXN0IG1vZGVsIGZpdC4KClN0YXJ0IGJ5IGJ1aWxkaW5nIGJvdGggYSAibnVsbCIgbW9kZWwgKGkuZS4gb25seSB0aGUgaW50ZXJjZXB0KSBhbmQgYSAiZnVsbCIgbW9kZWwgKGFsc28gY2FsbGVkIHRoZSBzYXR1cmF0ZWQgbW9kZWwpLgoKYGBge3J9CiN5b3VyIGNvZGUgaGVyZQoKYGBgCgpOb3cgc3RhcnQgZnJvbSB0aGUgZnVsbCBtb2RlbCBhbmQgdXNlIGJhY2t3YXJkcyBzdGVwd2lzZSByZWdyZXNzaW9uLiBXaGljaCBtb2RlbCBkb2VzIHRoaXMgcHJvY2VkdXJlIHJlc3VsdCBpbj8KCmBgYHtyfQojeW91ciBjb2RlIGhlcmUKCmBgYAoKRG8gdGhlIHNhbWUgd2l0aCBmb3J3YXJkIHN0ZXB3aXNlIHJlZ3Jlc3Npb24uIERvZXMgdGhpcyByZXN1bHQgaW4gdGhlIHNhbWUgbW9kZWw/CgpgYGB7cn0KI3lvdXIgY29kZSBoZXJlCgpgYGAKCkZpbmFsbHksIHRyeSB0byBpbXBsZW1lbnQgdGhlIGJpZGlyZWN0aW9uYWwgc3RlcHdpc2UgcmVncmVzc2lvbiAoaGludDogdXNlICJib3RoIiBmb3IgdGhlIGBkaXJlY3Rpb25gIGFyZ3VtZW50KS4KCmBgYHtyfQojeW91ciBjb2RlIGhlcmUKCmBgYAoKV2hhdCBkbyB0aGVzZSBmaW5kaW5ncyB0ZWxsIHlvdT8KCgojIyMgVGFzazogbXVsdGlwbGUgcmVncmVzc2lvbiBtb2RlbCBjb21wYXJpc29uCgpZb3Ugd2lsbCBvZnRlbiBlbmQgdXAgd2l0aCBkaWZmZXJlbnQgbW9kZWxzIG9mIHRoZSBzYW1lIG91dGNvbWUgdmFyaWFibGUuIElmIHRoZXNlIG1vZGVscyBhcmUgbmVzdGVkIChpLmUuIG9uZSBtb2RlbCBjYW4gYmUgZGVyaXZlZCBmcm9tIHRoZSBvdGhlciBieSByZW1vdmluZyBtb2RlbCBwYXJhbWV0ZXJzKSwgdGhlbiB5b3UgY2FuIHVzZSBpbmZlcmVudGlhbCBzdGF0aXN0aWNzIHRvIGRldGVybWluZSB3aGV0aGVyIG9uZSBtb2RlbCBpcyBzaWduaWZpY2FudGx5IHdvcnNlIHRoYW4gYW5vdGhlci4KCkluIFIsIHlvdSBjYW4gdXNlIHRoZSBgYW5vdmFgIGZ1bmN0aW9uIHRvIGNvbmR1Y3QgYW4gYW5hbHlzaXMgb2YgdmFyaWFuY2Ugb24gdHdvIG1vZGVscyB0byBkZXRlcm1pbmUgd2hldGhlciBhIHNpbXBsZXIgbW9kZWwgaXMgc2lnbmlmaWNhbnRseSB3b3JzZSB0aGFuIGEgbW9yZSBjb21wbGV4IG1vZGVsLgoKUGVyZm9ybSB0aGUgbW9kZWwgY29tcGFyaXNvbiB0ZXN0IGJldHdlZW4gKDEpIHRoZSBmdWxsIG1vZGVsIHZzIHRoZSBudWxsIG1vZGVsLCAoMikgYSAnZ2VuZGVyLW9ubHknIG1vZGVsIGFuZCBhICdnZW5kZXIgKyBwcm9tb3Rpb24nIG1vZGVsLCBhbmQgKDMpIGJldHdlZW4gdGhlIGZ1bGwgbW9kZWwgYW5kIHRoZSAnZ2VuZGVyICsgcHJvbW90aW9uJyBtb2RlbC4KCmBgYHtyfQojeW91ciBjb2RlIGhlcmUKCmBgYAoKUmFuayB0aGUgbW9kZWxzIGZyb20gYmVzdCB0byB3b3JzdCAodXNlIGVxdWFsIHJhbmtzIGlmIHRoZXJlIGlzIG5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2UpLgoKUmFua3MgY29tZSBoZXJlOgoKMS4gLi4uCjIuIC4uLgozLiAuLi4KLi4uCgoKLS0tCgojIyBMb2dpc3RpYyByZWdyZXNzaW9uCgpPZnRlbiB5b3Ugd2FudCB0byBidWlsZCBhIG1vZGVsIHRvIGVpdGhlciB1bmRlcnN0YW5kIHJlbGF0aW9uc2hpcHMgaW4gdGhlIGRhdGEsIG1ha2UgcHJlZGljdGlvbnMsIG9yIGJvdGgsIGFib3V0IGFuIG91dGNvbWUgdmFyaWFibGUgdGhhdCBpcyBzY29yZWQgYXMgMC8xLCBwcmVzZW50L25vdCBwcmVzZW50LCBhcnJlc3RlZC9ub3QgYXJyZXN0ZWQsIGV0Yy4gSWYgc3VjaCBhbiBvdXRjb21lIHZhcmlhYmxlIGhhcyBvbmx5IHR3byBsZXZlbHMsIHdlIGFsc28gc3BlYWsgb2YgYSBiaW5hcnkgb3IgZGljaG90b21vdXMgb3V0Y29tZS4KClJlZ3Jlc3Npb24gbW9kZWxzIGNhbiBiZSBhcHBsaWVkIGluIHRoaXMgY29udGV4dCB0b28uIFRvIHVuZGVyc3RhbmQgd2hhdCB0aGUgc3BlY2lhbCBpc3N1ZSB3aXRoIGJpbmFyeSBvdXRjb21lIHZhcmlhYmxlcyBpcywgbGV0J3MgaGF2ZSBhIGxvb2sgYXQgYSBkYXRhc2V0LgoKTG9hZCB0aGUgYGF0dGFja19kYXRhYCBkYXRhc2V0IGZyb20gYC4vZGF0YWAuIFdlIHVzZSB0aGlzIGRhdGFzZXQgdG8gcmV2aXNlIGNvbmNlcHRzIGZyb20gdGhlIGxlY3R1cmUuIFRoaXMgZGF0YXNldCByZXByZXNlbnRzIHdoZXRoZXIgb3Igbm90IGEgd2Vic2l0ZSB3YXMgaGFja2VkIGFuZCB0aGUgbnVtYmVyIG9mIGF0dGVtcHRlZCBoYWNraW5nIGF0dGFja3MgQ29sdW1ucyBhcmU6CgotIGhhY2tlZDogMCA9IG5vLCAxID0geWVzCi0gYXR0ZW1wdHMKCgojIyMgVGFzazogbG9naXN0aWMgcmVncmVzc2lvbiAtIGxpbmsgZnVuY3Rpb24gCgpTdXBwb3NlIHlvdSB3YW50IHRvIG1vZGVsIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBgaGFja2VkYCBhbmQgYGF0dGVtcHRzYC4gSWYgeW91IGxvb2sgYXQgdGhlIHBsb3QsIHlvdSBzZWUgdGhhdCB0aGVzZSBkYXRhIGRvIG5vdCBzdGVtIGZyb20gYSBub3JtYWwgZGlzdHJpYnV0aW9uOgoKYGBge3J9CmxvYWQoJy4vZGF0YS9hdHRhY2tfZGF0YS5SRGF0YScpCmhpc3QoYXR0YWNrX2RhdGEkaGFja2VkKQpgYGAKCkEgZGlzdHJpYnV0aW9uIG9mIGEgdmFyaWFibGUgIHRoYXQgY2FuIHRha2Ugb25seSAwIGFuZCAxLAoKCldlIGNhbiBhbHNvIGxvb2sgYXQgdGhlICdyYXcnIGRhdGEgdG8gZ2V0IGEgYmV0dGVyIHVuZGVyc3RhbmRpbmcgb2YgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMgYGhhY2tlZGAgYW5kIGBhdHRlbXB0c2A6CgpgYGB7cn0KcGxvdChhdHRhY2tfZGF0YSRhdHRlbXB0cywgYXR0YWNrX2RhdGEkaGFja2VkKQpgYGAKClNvIGxldCdzIHN0YXJ0IHdpdGggd2hhdCB3ZSBrbm93IGZyb20gcmVncmVzc2lvbiBtb2RlbGxpbmcgYW5kICdmaXQnIGFuIG9yZGluYXJ5IGxpbmVhciBtb2RlbDoKCmBgYHtyfQpvcmRpbmFyeV9tb2RlbCA9IGdsbShoYWNrZWQgfiBhdHRlbXB0cwogICAgICAgICAgICAgICAgICAgICAsIGRhdGEgPSBhdHRhY2tfZGF0YQogICAgICAgICAgICAgICAgICAgICAsIGZhbWlseSA9IGdhdXNzaWFuCiAgICAgICAgICAgICAgICAgICAgKQpzdW1tYXJ5KG9yZGluYXJ5X21vZGVsKQpgYGAKCk5vdGUgdGhhdCBhIEdMTSB3aXRoIGZhbWlseSAiZ2F1c3NpYW4iIGlzIGlkZW50aWNhbCB0byBhIG5vcm1hbCBsaW5lYXIgbW9kZWwuIFRoaXMgaXMgYmVjYXVzZSB0aGUgb3JkaW5hcnkgbGluZWFyIG1vZGVsIGFzc3VtZXMgdGhhdCB0aGUgb3V0Y29tZSB2YXJpYWJsZSBpcyBub3JtYWxseSBkaXN0cmlidXRlZCAoaS5lLiBmb2xsb3dzIGEgR2F1c3NpYW4gZGlzdHJpYnV0aW9uKS4KClRvIHNlZSB3aGF0IG1pZ2h0IGJlIHByb2JsZW1hdGljLCBoYXZlIGEgbG9vayBhdCB0aGUgcHJlZGljdGVkIHZhbHVlczoKCmBgYHtyfQpwbG90KG9yZGluYXJ5X21vZGVsJG1vZGVsJGF0dGVtcHRzLCBvcmRpbmFyeV9tb2RlbCRmaXR0ZWQudmFsdWVzKQpgYGAKCllvdSB3aWxsIG5vdGljZSB0aGF0IHRoZSB2YWx1ZXMgcHJlZGljdGVkIHRocm91Z2ggdGhlIG1vZGVsIGFyZSAoMSkgbm90IG9ubHkgMXMgYW5kIDBzIGFuZCAoMikgZXhjZWVkIDEgYW5kIGFyZSBldmVuIHNtYWxsZXIgdGhhbiAwLiBDbGVhcmx5LCBmb3IgYSBkYXRhc2V0IHdoZXJlIHRoZSBvdXRjb21lIHZhcmlhYmxlIGNhbiBvbmx5IHRha2UgdGhlIHZhbHVlIDAgYW5kIDEsIHRoaXMgaXMgYW4gaW5hZGVxdWF0ZSB3YXkgdG8gbW9kZWwgdGhlIGRhdGEuCgpZb3UgY2FuIGFsc28gbG9vayBhdCB0aGUgYWN0dWFsIHJlZ3Jlc3Npb24gbGluZSBmaXR0ZWQgdG8gdGhlIHJhdyBkYXRhOgoKYGBge3J9CntwbG90KGF0dGFja19kYXRhJGF0dGVtcHRzLCBhdHRhY2tfZGF0YSRoYWNrZWQpCiAgYWJsaW5lKG9yZGluYXJ5X21vZGVsKX0KYGBgCgpTbyB3ZSBuZWVkIGEgc29sdXRpb24gdG8gdGhhdCBpc3N1ZS4KCkx1Y2tpbHksIHRoZXJlIGlzIGEgd2F5IHRvIHRyYW5zZm9ybSB0aGUgMS8wIG91dGNvbWUgdmFyaWFibGUgdG8gYSBjb250aW51b3VzIHZhcmlhYmxlIHNvIHRoYXQgdGhlIG1vZGVsIGNhbiBtYWtlIHByZWRpY3Rpb25zIG9uIGEgY29udGludW91cyBzY2FsZS4KCkEgbmVhdCB3YXkgdG8gZG8gdGhpcywgaXMgdGhlIGxvZ2l0IGZ1bmN0aW9uIHRoYXQgcGVyZm9ybXMgdGhlIGZvbGxvd2luZyBzdGVwczoKCjEuIGl0IGFzc3VtZXMgdGhhdCBlYWNoIGNhc2UgaGFzIGEgcHJvYmFiaWxpdHkgb2YgYmVpbmcgMSBvciAwCgpMZXQncyBkbyB0aGlzIGZvciBhIHNlcXVlbmNlIGZybyAwLjAgdG8gMS4wIGluIHN0ZXBzIG9mIDAuMQoKYGBge3J9CnByb2JhYmlsaXRpZXMgPSBzZXEoZnJvbSA9IDAuMDEsIHRvID0gMC45OSwgYnk9MC4wMSkKYGBgCgpUaGlzIGJyaW5ncyB0aGUgdHJhbnNmb3JtZWQgb3V0Y29tZSB2YXJpYWJsZSBmcm9tIGEgMCwxIHNjYWxlIHRvIGEgMDoxIHNjYWxlIChub3RlOiB0aGUgYDpgIHJlYWRzIGFzICJ0byIpLgoKMi4gaXQgdHJhbnNmb3JtcyB0aGVzZSBwcm9iYWJpbGl0aWVzIHRvIHRoZSBvZGRzOiBgb2RkcyA9IFAvKDEtUClgCgpgYGB7cn0Kb2RkcyA9IHByb2JhYmlsaXRpZXMvKDEtcHJvYmFiaWxpdGllcykKYGBgCgpUaGlzIHRyYW5zZm9ybXMgdGhlIG91dGNvbWUgdmFyaWFibGUgdG8gYSBzY2FsZSByYW5naW5nIGZyb20gMDpJbmYuCgpgYGB7cn0KcGxvdChvZGRzLCBwcm9iYWJpbGl0aWVzKQpgYGAKCgozLiBpdCBjYWxjdWxhdGVzIHRoZSBsb2dhcml0aG0gb2YgdGhlIG9kZHMgKGlmIHlvdSBuZWVkIHRvIHJlY2FwIHRoZSBjb25jZXB0IG9mIGEgbG9nYXJpdGhtLCBwbGVzZSB0YWtlIGEgbG9vayBhdCBbdGhpcyB2aWRlbyB0dXRvcmlhbF0oaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1tUVRXekxwQ2NXMCkpLiBNb3JlIHNwZWNpZmljYWxseSwgd2UgdGFrZSB0aGUgW25hdHVyYWwgbG9nYXJpdGhtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9OYXR1cmFsX2xvZ2FyaXRobSkuCgpgYGB7cn0KbG9nX29kZHMgPSBsb2cob2RkcykKYGBgCgpgYGB7cn0KcGxvdChsb2dfb2RkcywgcHJvYmFiaWxpdGllcykKYGBgCgpZb3UgY2FuIHNlZSB0aGF0IG5vdyB3ZSB0cmFuc2Zvcm1lZCB0aGUgb3V0Y29tZSB2YXJpYWJsZSBmdXJ0aGVyIHRvIGEgc2NhbGUgcmFuZ2luZyBmcm9tIC1JbmY6SW5mLgoKSXQgaXMgdGhpcyBsb2dpdCBmdW5jdGlvbiB0aGF0IGlzIHVzZWQgdG8gdHJhbnNmb3JtIHRoZSBvdXRjb21lIHZhcmlhYmxlIGZyb20gYSAxLDAgZGlzY3JldGUgcmFuZ2UgdG8gYSBjb250aW51b3VzIHJhbmdlIGZyb20gLUluZjpJbmYuCgpZb3Ugd2lsbCBzZWUgdGhpcyBpbiBhY3Rpb24gZnVydGhlciBiZWxvdy4uLgoKSW4gdGhlIEdMTSBmdW5jdGlvbiwgeW91IGNhbiBzcGVjaWZ5IHRoaXMgYnkgdXNpbmcgdGhlIGBmYW1pbHkgPSBgIGFyZ3VtZW50IGFuZCBzZXR0aW5nIGl0IHRvICJiaW5vbWlhbCIgKHNpbmNlIG91ciBvdXRjb21lIHZhcmlhYmxlIHN0ZW1zIGZyb20gYSBiaW5vbWlhbCBkaXN0cmlidXRpb24pLgoKIyMjIFRhc2s6IGxvZ2lzdGljIHJlZ3Jlc3Npb24gLSBmaXR0aW5nIHRoZSBHTE0KCkJ1aWxkIGEgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCB0aGF0IG1vZGVscyB3aGV0aGVyIG9yIG5vdCBhIHdlYnNpdGUgd2FzIGhhY2tlZCB0aHJvdWdoIHRoZSBudW1iZXIgb2YgYXR0YWNrczoKCmBgYHtyfQojeW91ciBjb2RlIGhlcmUKCmBgYAoKIyMjIFRhc2s6IGxvZ2lzdGljIHJlZ3Jlc3Npb24gLSBpbnRlcnByZXRpbmcgdGhlIG1vZGVsCgpUYWtlIGEgbG9vayBhdCB0aGUgbW9kZWwgc3VtbWFyeS4gUmVtZW1iZXIgd2hhdCB0aGUgbG9naXQgbW9kZWwgZG9lcz8gSWYgd2UgbW9kZWwgdGhlICJsb2ctb2RkcyIsIHRoZW4gdGhlIGNvZWZmaWNpZW50cyAod2hhdCB3ZSBjYWxsIHRoZSBpbnRlcmNlcHQgYW5kIHNsb3BlIGluIGxpbmVhciByZWdyZXNzaW9uKSBuZWVkIHRvIGJlIGludGVycHJldGVkIGFzIHN1Y2guCgpCdXQgYmVjYXVzZSB0aGUgbG9nLW9kZHMgYXJlIGhhcmQgdG8gaW50ZXJwcmV0LCB3ZSB3YW50IHRvIHRyYW5zZm9ybSB0aGVtIGJhY2sgdG8gdGhlIG1vcmUgaW50ZXJwcmV0YWJsZSBvZGRzLgoKRnJvbSB0aGUgdmlkZW8gYWJvdmUsIHlvdSB3aWxsIGhhdmUgbGVhcm5lZCB0aGF0IHlvdSBjYW4gcmV2ZXJzZSB0aGUgbmF0dXJhbCBsb2dhcml0aG0gYnkgdGFraW5nIFtlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9FXyhtYXRoZW1hdGljYWxfY29uc3RhbnQpKSB0byB0aGUgcG93ZXIgb2YgdGhlIGxvZ2FyaXRobS4KCkRvIHRoaXMgdHJhbnNmb3JtYXRpb246CgpgYGB7cn0KI3lvdXIgY29kZSBoZXJlCgpgYGAKCldoYXQgZG9lcyB0aGlzIHlpZWxkIChpLmUuIGhvdyBkbyB5b3UgaW50ZXByZXQgdGhlc2UgdmFsdWVzKT8KCldoYXQgd291bGQgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZXNlIGZpbmRpbmdzIGxvb2sgbGlrZSBpbiB5b3VyIG93biB3b3Jkcz8KCiMjIyBUYXNrOiBsb2dpc3RpYyByZWdyZXNzaW9uIC0gY3VydmUgZml0dGluZwoKU2ltaWxhciB0byB0aGUgImxpbmUtZml0dGluZyIgb2YgbGluZWFyIHJlZ3Jlc3Npb24sIHdlIGNhbiBhbHNvIGxvb2sgYXQgdGhlIGZpdHRlZCBtb2RlbCB2aXN1YWxseS4KCmBgYHtyfQpsb2dyZWcgPSBnbG0oaGFja2VkIH4gYXR0ZW1wdHMKICAgICAgICAgICAgICwgZmFtaWx5PWJpbm9taWFsCiAgICAgICAgICAgICAsIGRhdGEgPSBhdHRhY2tfZGF0YSkKe3Bsb3QoYXR0YWNrX2RhdGEkYXR0ZW1wdHMsIGF0dGFja19kYXRhJGhhY2tlZCkKICBjdXJ2ZShwcmVkaWN0KGxvZ3JlZwogICAgICAgICAgICAgICAgLCBkYXRhLmZyYW1lKGF0dGVtcHRzPXgpCiAgICAgICAgICAgICAgICAsIHR5cGU9InJlc3AiKQogICAgICAgICwgYWRkPVRSVUUpfQpgYGAKCgpZb3UgY2FuIHNlZSB0aGF0IHRoZSBtb2RlbCAoPSB0aGUgY3VydmUpIHByZWRpY3RzIHZhbHVlcyBleGNsdXNpdmVseSBpbiB0aGUgMDoxIHJhbmdlLiBIb3dldmVyLCB5b3UgY2FuIGFsc28gc2VlIHRoYXQgd2hpbGUgdGhlIG1ham9yaXR5IG9mIHRoZSBwcmVkaWN0ZWQgdmFsdWVzIGlzIGVpdGhlciAwIG9yIDEsIHNvbWUgdmFsdWVzIGFyZSBpbiBiZXR3ZWVuIChlLmcuIGFyb3VuZCBhdHRlbXB0cyA9PSA1MDApLiBUaGlzIGlzIHRoZSByZWFzb24gd2h5IHlvdSBuZWVkIHRocmVzaG9sZHMgaWYgeW91IHdhbnQgdG8gYXNjZXJ0YWluIHRoZSBhY2N1cmFjeSBvZiBzdWNoIGEgbW9kZWwuIEluIFllYXIgMywgeW91IHdpbGwgbGVhcm4gYWJvdXQgYXBwbGljYXRpb25zIG9mIHRoaXMgdGhyZXNob2xkaW5nIGZvciBsb2dpc3RpYyByZWdyZXNzaW9uIGluIG1hY2hpbmUgbGVhcm5pbmcuCgpZb3UgY2FuIHNlZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gZml0dGVkIHZhbHVlcyAoaS5lLiBwcm9iYWJpbGl0aWVzIG9mIGEgY2FzZSBiZWluZyBpbiBvbiBlb2YgdGhlIHR3byBvdXRjb21lIGNsYXNzZXMgIC0gaGFja2VkIHZzIG5vdCBoYWNrZWQgLSBnaXZlbiBhIGNlcnRhaW4gbnVtYmVyIG9mIGF0dGVtcHRzKSBhbmQgdGhlIG9ic2VydmVkIHZhbHVlczoKCmBgYHtyfQpwbG90KGxvZ3JlZyRmaXR0ZWQudmFsdWVzLCBsb2dyZWckbW9kZWwkaGFja2VkKQpgYGAKCgojIyBFTkQKCi0tLQ==