1 Introduction

In this project we will be looking at binary predictive modeling using the logistic regression model. We will look to see if we need to transform any variables and do cross validation before finding our final model. We want to look at wins as our response variable and want to look at what betting odds factor helps with that.

1.1 Data and Variable Descriptions

This data set is on the NBA game betting odds and outcomes of the 2014-2015 Season. There is 1230 observations and 17 variables. The variables in this data set are

  • Datenum (categorical)- This is the amount of days since January 1, 1960
  • Team (categorical)- Where the home team is from
  • OppTeam (categorical)- Where the away team is from
  • TeamPts (numerical)- Home team points scored
  • OppPts (numerical)- Away team points scored
  • Wins (binary response)- If the home team won (1 means they won, 0 means they lost)
  • TeamCov (binary response) - If the home team covered the spread (1 means they covered, 0 means a “push”, and -1 means they didn’t cover)
  • TeamSprd (numerical)- The Vegas point spread for the home team
  • OvrUndr (numerical)- The over/under Vegas line for the total points in the game
  • TeamDiff (numerical)- Home Points minus Away Points
  • TotalPts (numerical)- Home Points plus Away Points

We only used a certain number of these variables like TeamPts, OppPts, TeamWin, TeamSprd, and OvrUndr due to my past experiences. The other variables were either not important for this project or they were a combination of others.

1.2 Research Question

The objective of this case study is to build a logistic regression model to predict wins using various risk factors associated with the game.

2 Exploratory Analysis

We first make the following pairwise scatter plots to inspect the potential issues with predictor variables.

Looking at the scatter plots we can see that none look skewed and are all unimodal besides our binary response variable which is team wins. This means that we do not need to transform any of our predictor variables.

2.1 Standizing Numerical Predictor Variables

Since this is a predictive model, we don’t worry about the interpretation of the coefficients. The objective is to identify a model that has the best predictive performance.

2.2 Data Split - Training and Testing Data

We randomly split the data into two subsets. 80% of the data will be used as training data. We will use the training data to search the candidate models, validate them and identify the final model using the cross-validation method. The 20% of the hold-up sample will be used for assessing the performance of the final model.

2.3 Best Model Identification

In the past modules, we introduced full and reduced models to set up the scope for searching for the final model. In this case study, we use the full, reduced, and final models obtained based on the step-wise variable selection as the three candidate models.

2.3.1 Cross-Validation for Model Identification

Since our training data is relatively small, I will use 5-fold cross-validation to ensure the validation data set has enough diabetes cases.

Average of prediction errors of candidate models
PE1 PE2 PE3
1 1 1

The average predictive errors of both model 1 and model 2 are the same. Since model 2 is simpler than model 1, we choose model 2 as the final predictive model. This selection of the final model is based on the cut-off probability 0.5.

2.3.2 Final Model Reporting

The previous cross-validation procedure identified the best model with pre-selected cut-off 0.5. The actual accuracy of the final model is given by

The actual accuracy of the final model
x
1

Looking at these results, it tells us that this model has a 100% accuracy of predicting the outcome in the final model. This seems correct because how many points you score affects the outcome of the game greatly and how mnay points you can hold your opponent too.

3 Conclusion

In this project we were trying to make a model that predicts wins. The final result for the accuracy of our final model was 100%. An accuracy of 100% shows that the model is identifying if an observation falls into win (1) or loss (0) for 100% of the time.

LS0tCnRpdGxlOiAiV2hhdCBpbmZsdWVuY2VzIHdpbm5pbmcgaW4gdGhlIE5CQT8iCmF1dGhvcjogIlJ5YW4gTGVibyIKZGF0ZTogIjIwMjQtMTAtMjMiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIHRvY19mbG9hdDogeWVzCiAgICBmaWdfd2lkdGg6IDQKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMKICAgIHRoZW1lOiBsdW1lbgogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBrZWVwX21kOiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgZmlnX3dpZHRoOiAzCiAgICBmaWdfaGVpZ2h0OiAzCmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKc2x3YXlzX2FsbG93X2h0bWw6IHRydWUKLS0tCgpgYGB7PWh0bWx9Cgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoKLyogQ2FzY2FkaW5nIFN0eWxlIFNoZWV0cyAoQ1NTKSBpcyBhIHN0eWxlc2hlZXQgbGFuZ3VhZ2UgdXNlZCB0byBkZXNjcmliZSB0aGUgcHJlc2VudGF0aW9uIG9mIGEgZG9jdW1lbnQgd3JpdHRlbiBpbiBIVE1MIG9yIFhNTC4gaXQgaXMgYSBzaW1wbGUgbWVjaGFuaXNtIGZvciBhZGRpbmcgc3R5bGUgKGUuZy4sIGZvbnRzLCBjb2xvcnMsIHNwYWNpbmcpIHRvIFdlYiBkb2N1bWVudHMuICovCgpoMS50aXRsZSB7ICAvKiBUaXRsZSAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgdGhlIHJlcG9ydCB0aXRsZSAqLwogIGZvbnQtc2l6ZTogMjRweDsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOwp9Cmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgYXV0aG9ycyAgKi8KICBmb250LXNpemU6IDIwcHg7CiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgdGhlIGRhdGUgICovCiAgZm9udC1zaXplOiAxOHB4OwogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7CiAgY29sb3I6IERhcmtCbHVlOwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQpoMSB7IC8qIEhlYWRlciAxIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMSBzZWN0aW9uIHRpdGxlICAqLwogICAgZm9udC1zaXplOiAyMnB4OwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGNlbnRlcjsKfQpoMiB7IC8qIEhlYWRlciAyIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMiBzZWN0aW9uIHRpdGxlICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQoKaDMgeyAvKiBIZWFkZXIgMyAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgbGV2ZWwgMyBzZWN0aW9uIHRpdGxlICAqLwogICAgZm9udC1zaXplOiAxOHB4OwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBmb250IHNwZWNpZmljYXRpb25zIG9mIGxldmVsIDQgc2VjdGlvbiB0aXRsZSAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9Cgpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQoKLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0KCnAgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9Cgo8L3N0eWxlPgpgYGAKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CgppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQogICBsaWJyYXJ5KGtuaXRyKQp9CmlmICghcmVxdWlyZSgibGVhZmxldCIpKSB7CiAgIGluc3RhbGwucGFja2FnZXMoImxlYWZsZXQiKQogICBsaWJyYXJ5KGxlYWZsZXQpCn0KaWYgKCFyZXF1aXJlKCJFbnZTdGF0cyIpKSB7CiAgIGluc3RhbGwucGFja2FnZXMoIkVudlN0YXRzIikKICAgbGlicmFyeShFbnZTdGF0cykKfQppZiAoIXJlcXVpcmUoIk1BU1MiKSkgewogICBpbnN0YWxsLnBhY2thZ2VzKCJNQVNTIikKICAgbGlicmFyeShNQVNTKQp9CmlmICghcmVxdWlyZSgicGh5dG9vbHMiKSkgewogICBpbnN0YWxsLnBhY2thZ2VzKCJwaHl0b29scyIpCiAgIGxpYnJhcnkocGh5dG9vbHMpCn0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgewogICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQogICBsaWJyYXJ5KHRpZHl2ZXJzZSkKfQppZiAoIXJlcXVpcmUoIm1sYmVuY2giKSkgewogICBpbnN0YWxsLnBhY2thZ2VzKCJtbGJlbmNoIikKICAgbGlicmFyeShtbGJlbmNoKQp9CmlmICghcmVxdWlyZSgicGFuZGVyIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygicGFuZGVyIikKICAgbGlicmFyeShwYW5kZXIpCn0KaWYgKCFyZXF1aXJlKCJwUk9DIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygicFJPQyIpCiAgIGxpYnJhcnkocFJPQykKfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IEZBTFNFLCAgCiAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgIAogICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgY29tbWVudCA9IEZBTFNFICAKICAgICAgICAgICAgICAgICAgICAgICkgICAKYGBgCgoKYGBge3J9CmJldHMgPC0gcmVhZC5jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9SeWFuTGViby9TVEEtMzIxL3JlZnMvaGVhZHMvbWFpbi9Qcm9qZWN0JTIwMiUyMERhdGEiLCBoZWFkZXIgPSBUUlVFKQp3aW5zPC0gYmV0cyRUZWFtV2luCm5ld19kYXRhIDwtIGJldHMgJT4lCiAgc2VsZWN0KC1PVCwgLVRlYW0sIC1PcHBUZWFtLCAtRGF0ZW51bSwgLURhdGVzbGFzaCwgLUhvbWUsIC1UZWFtQ292LCAtT1VDb3YsIC1UZWFtX2lkLCAtT3BwVGVhbV9pZCwtVGVhbURpZmYsIC1Ub3RhbFB0cykKYGBgCgojIEludHJvZHVjdGlvbgpJbiB0aGlzIHByb2plY3Qgd2Ugd2lsbCBiZSBsb29raW5nIGF0IGJpbmFyeSBwcmVkaWN0aXZlIG1vZGVsaW5nIHVzaW5nIHRoZSBsb2dpc3RpYyByZWdyZXNzaW9uIG1vZGVsLiBXZSB3aWxsIGxvb2sgdG8gc2VlIGlmIHdlIG5lZWQgdG8gdHJhbnNmb3JtIGFueSB2YXJpYWJsZXMgYW5kIGRvIGNyb3NzIHZhbGlkYXRpb24gYmVmb3JlIGZpbmRpbmcgb3VyIGZpbmFsIG1vZGVsLiBXZSB3YW50IHRvIGxvb2sgYXQgd2lucyBhcyBvdXIgcmVzcG9uc2UgdmFyaWFibGUgYW5kIHdhbnQgdG8gbG9vayBhdCB3aGF0IGJldHRpbmcgb2RkcyBmYWN0b3IgaGVscHMgd2l0aCB0aGF0LiAKCiMjIERhdGEgYW5kIFZhcmlhYmxlIERlc2NyaXB0aW9ucwoKVGhpcyBkYXRhIHNldCBpcyBvbiB0aGUgTkJBIGdhbWUgYmV0dGluZyBvZGRzIGFuZCBvdXRjb21lcyBvZiB0aGUgMjAxNC0yMDE1IFNlYXNvbi4gVGhlcmUgaXMgMTIzMCBvYnNlcnZhdGlvbnMgYW5kIDE3IHZhcmlhYmxlcy4gVGhlIHZhcmlhYmxlcyBpbiB0aGlzIGRhdGEgc2V0IGFyZSAKCiogRGF0ZW51bSAoY2F0ZWdvcmljYWwpLSBUaGlzIGlzIHRoZSBhbW91bnQgb2YgZGF5cyBzaW5jZSBKYW51YXJ5IDEsIDE5NjAKKiBUZWFtIChjYXRlZ29yaWNhbCktIFdoZXJlIHRoZSBob21lIHRlYW0gaXMgZnJvbQoqIE9wcFRlYW0gKGNhdGVnb3JpY2FsKS0gV2hlcmUgdGhlIGF3YXkgdGVhbSBpcyBmcm9tCiogVGVhbVB0cyAobnVtZXJpY2FsKS0gSG9tZSB0ZWFtIHBvaW50cyBzY29yZWQKKiBPcHBQdHMgKG51bWVyaWNhbCktIEF3YXkgdGVhbSBwb2ludHMgc2NvcmVkCiogV2lucyAoYmluYXJ5IHJlc3BvbnNlKS0gSWYgdGhlIGhvbWUgdGVhbSB3b24gKDEgbWVhbnMgdGhleSB3b24sIDAgbWVhbnMgdGhleSBsb3N0KQoqIFRlYW1Db3YgKGJpbmFyeSByZXNwb25zZSkgLSBJZiB0aGUgaG9tZSB0ZWFtIGNvdmVyZWQgdGhlIHNwcmVhZCAoMSBtZWFucyB0aGV5IGNvdmVyZWQsIDAgbWVhbnMgYSAicHVzaCIsIGFuZCAtMSBtZWFucyB0aGV5IGRpZG4ndCBjb3ZlcikKKiBUZWFtU3ByZCAobnVtZXJpY2FsKS0gVGhlIFZlZ2FzIHBvaW50IHNwcmVhZCBmb3IgdGhlIGhvbWUgdGVhbQoqIE92clVuZHIgKG51bWVyaWNhbCktIFRoZSBvdmVyL3VuZGVyIFZlZ2FzIGxpbmUgZm9yIHRoZSB0b3RhbCBwb2ludHMgaW4gdGhlIGdhbWUKKiBUZWFtRGlmZiAobnVtZXJpY2FsKS0gSG9tZSBQb2ludHMgbWludXMgQXdheSBQb2ludHMKKiBUb3RhbFB0cyAobnVtZXJpY2FsKS0gSG9tZSBQb2ludHMgcGx1cyBBd2F5IFBvaW50cwoKV2Ugb25seSB1c2VkIGEgY2VydGFpbiBudW1iZXIgb2YgdGhlc2UgdmFyaWFibGVzIGxpa2UgVGVhbVB0cywgT3BwUHRzLCBUZWFtV2luLCBUZWFtU3ByZCwgYW5kIE92clVuZHIgZHVlIHRvIG15IHBhc3QgZXhwZXJpZW5jZXMuIFRoZSBvdGhlciB2YXJpYWJsZXMgd2VyZSBlaXRoZXIgbm90IGltcG9ydGFudCBmb3IgdGhpcyBwcm9qZWN0IG9yIHRoZXkgd2VyZSBhIGNvbWJpbmF0aW9uIG9mIG90aGVycy4KCiMjIFJlc2VhcmNoIFF1ZXN0aW9uClRoZSBvYmplY3RpdmUgb2YgdGhpcyBjYXNlIHN0dWR5IGlzIHRvIGJ1aWxkIGEgbG9naXN0aWMgcmVncmVzc2lvbiBtb2RlbCB0byBwcmVkaWN0IHdpbnMgdXNpbmcgdmFyaW91cyByaXNrIGZhY3RvcnMgYXNzb2NpYXRlZCB3aXRoIHRoZSBnYW1lLgoKIyBFeHBsb3JhdG9yeSBBbmFseXNpcwoKV2UgZmlyc3QgbWFrZSB0aGUgZm9sbG93aW5nIHBhaXJ3aXNlIHNjYXR0ZXIgcGxvdHMgdG8gaW5zcGVjdCB0aGUgcG90ZW50aWFsIGlzc3VlcyB3aXRoIHByZWRpY3RvciB2YXJpYWJsZXMuCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTd9CmxpYnJhcnkocHN5Y2gpCnBhaXJzLnBhbmVscyhuZXdfZGF0YVssLTldLCAKICAgICAgICAgICAgIG1ldGhvZCA9ICJwZWFyc29uIiwgCiAgICAgICAgICAgICBoaXN0LmNvbCA9ICIjMDBBRkJCIiwKICAgICAgICAgICAgIGRlbnNpdHkgPSBUUlVFLCAgCiAgICAgICAgICAgICBlbGxpcHNlcyA9IFRSVUUgCiAgICAgICAgICAgICApCmBgYAoKTG9va2luZyBhdCB0aGUgc2NhdHRlciBwbG90cyB3ZSBjYW4gc2VlIHRoYXQgbm9uZSBsb29rIHNrZXdlZCBhbmQgYXJlIGFsbCB1bmltb2RhbCBiZXNpZGVzIG91ciBiaW5hcnkgcmVzcG9uc2UgdmFyaWFibGUgd2hpY2ggaXMgdGVhbSB3aW5zLiBUaGlzIG1lYW5zIHRoYXQgd2UgZG8gbm90IG5lZWQgdG8gdHJhbnNmb3JtIGFueSBvZiBvdXIgcHJlZGljdG9yIHZhcmlhYmxlcy4gCgojIyBTdGFuZGl6aW5nIE51bWVyaWNhbCBQcmVkaWN0b3IgVmFyaWFibGVzCgpTaW5jZSB0aGlzIGlzIGEgcHJlZGljdGl2ZSBtb2RlbCwgd2UgZG9uJ3Qgd29ycnkgYWJvdXQgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSBjb2VmZmljaWVudHMuIFRoZSBvYmplY3RpdmUgaXMgdG8gaWRlbnRpZnkgYSBtb2RlbCB0aGF0IGhhcyB0aGUgYmVzdCBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlLgoKYGBge3J9CgpuZXdfZGF0YSRzZC5UZWFtUHRzID0gKG5ld19kYXRhJFRlYW1QdHMtbWVhbihuZXdfZGF0YSRUZWFtUHRzKSkvc2QobmV3X2RhdGEkVGVhbVB0cykKbmV3X2RhdGEkc2QuT3BwUHRzID0gKG5ld19kYXRhJE9wcFB0cy1tZWFuKG5ld19kYXRhJE9wcFB0cykpL3NkKG5ld19kYXRhJE9wcFB0cykKbmV3X2RhdGEkc2QuVGVhbVNwcmQgPSAobmV3X2RhdGEkVGVhbVNwcmQtbWVhbihuZXdfZGF0YSRUZWFtU3ByZCkpL3NkKG5ld19kYXRhJFRlYW1TcHJkKQpuZXdfZGF0YSRzZC5PdnJVbmRyID0gKG5ld19kYXRhJE92clVuZHItbWVhbihuZXdfZGF0YSRPdnJVbmRyKSkvc2QobmV3X2RhdGEkT3ZyVW5kcikKCnNkLm5ld19kYXRhID0gbmV3X2RhdGFbLCAtYygxOjIsNDo1KV0KYGBgCgoKIyMgRGF0YSBTcGxpdCAtIFRyYWluaW5nIGFuZCBUZXN0aW5nIERhdGEKCldlIHJhbmRvbWx5IHNwbGl0IHRoZSBkYXRhIGludG8gdHdvIHN1YnNldHMuIDgwJSBvZiB0aGUgZGF0YSB3aWxsIGJlIHVzZWQgYXMgdHJhaW5pbmcgZGF0YS4gV2Ugd2lsbCB1c2UgdGhlIHRyYWluaW5nIGRhdGEgdG8gc2VhcmNoIHRoZSBjYW5kaWRhdGUgbW9kZWxzLCB2YWxpZGF0ZSB0aGVtIGFuZCBpZGVudGlmeSB0aGUgZmluYWwgbW9kZWwgdXNpbmcgdGhlIGNyb3NzLXZhbGlkYXRpb24gbWV0aG9kLiBUaGUgMjAlIG9mIHRoZSBob2xkLXVwIHNhbXBsZSB3aWxsIGJlIHVzZWQgZm9yIGFzc2Vzc2luZyB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIGZpbmFsIG1vZGVsLgoKYGBge3J9CgpuIDwtIGRpbShzZC5uZXdfZGF0YSlbMV0KdHJhaW4ubiA8LSByb3VuZCgwLjgqbikKdHJhaW4uaWQgPC0gc2FtcGxlKDE6biwgdHJhaW4ubiwgcmVwbGFjZSA9IEZBTFNFKQoKdHJhaW4gPC0gc2QubmV3X2RhdGFbdHJhaW4uaWQsIF0KdGVzdCA8LSBzZC5uZXdfZGF0YVstdHJhaW4uaWQsIF0KCmBgYAoKCiMjIEJlc3QgTW9kZWwgSWRlbnRpZmljYXRpb24KCkluIHRoZSBwYXN0IG1vZHVsZXMsIHdlIGludHJvZHVjZWQgZnVsbCBhbmQgcmVkdWNlZCBtb2RlbHMgdG8gc2V0IHVwIHRoZSBzY29wZSBmb3Igc2VhcmNoaW5nIGZvciB0aGUgZmluYWwgbW9kZWwuIEluIHRoaXMgY2FzZSBzdHVkeSwgd2UgdXNlIHRoZSBmdWxsLCByZWR1Y2VkLCBhbmQgZmluYWwgbW9kZWxzIG9idGFpbmVkIGJhc2VkIG9uIHRoZSBzdGVwLXdpc2UgdmFyaWFibGUgc2VsZWN0aW9uIGFzIHRoZSB0aHJlZSBjYW5kaWRhdGUgbW9kZWxzLgoKIyMjIENyb3NzLVZhbGlkYXRpb24gZm9yIE1vZGVsIElkZW50aWZpY2F0aW9uCgpTaW5jZSBvdXIgdHJhaW5pbmcgZGF0YSBpcyByZWxhdGl2ZWx5IHNtYWxsLCBJIHdpbGwgdXNlIDUtZm9sZCBjcm9zcy12YWxpZGF0aW9uIHRvIGVuc3VyZSB0aGUgdmFsaWRhdGlvbiBkYXRhIHNldCBoYXMgZW5vdWdoIGRpYWJldGVzIGNhc2VzLgoKYGBge3J9CgprPTUKZm9sZC5zaXplID0gZmxvb3IoZGltKHRyYWluKVsxXS9rKQoKUEUxID0gcmVwKDAsNSkKUEUyID0gcmVwKDAsNSkKUEUzID0gcmVwKDAsNSkKZm9yKGkgaW4gMTprKXsKCiAgdmFsaWQuaWQgPSAoZm9sZC5zaXplKihpLTEpKzEpOihmb2xkLnNpemUqaSkKICB2YWxpZCA9IHRyYWluW3ZhbGlkLmlkLCBdCiAgdHJhaW4uZGF0ID0gdHJhaW5bLXZhbGlkLmlkLF0KICAKCiAgY2FuZGlkYXRlMDEgPSBnbG0oVGVhbVdpbiB+c2QuVGVhbVB0cytzZC5PcHBQdHMrc2QuVGVhbVNwcmQrc2QuT3ZyVW5kciwgCiAgICAgICAgICAgICAgICAgICAgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpLAogICAgICAgICAgICAgICAgICAgIGRhdGEgPSB0cmFpbi5kYXQpICAKCiAgY2FuZGlkYXRlMDMgPSBnbG0oVGVhbVdpbiB+IHNkLlRlYW1QdHMrc2QuT3BwUHRzLCAKICAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBiaW5vbWlhbChsaW5rID0gImxvZ2l0IiksICAKICAgICAgICAgICAgICAgICAgICBkYXRhID0gdHJhaW4uZGF0KSAKCiAgIGNhbmRpZGF0ZTAyID0gc3RlcEFJQyhjYW5kaWRhdGUwMSwgCiAgICAgICAgICAgICAgICAgICAgICBzY29wZSA9IGxpc3QobG93ZXI9Zm9ybXVsYShjYW5kaWRhdGUwMyksdXBwZXI9Zm9ybXVsYShjYW5kaWRhdGUwMSkpLAogICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gImZvcndhcmQiLCAgIAogICAgICAgICAgICAgICAgICAgICAgdHJhY2UgPSAwICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgKQogCiAgIHByZWQwMSA9IHByZWRpY3QoY2FuZGlkYXRlMDEsIG5ld2RhdGEgPSB2YWxpZCwgdHlwZT0icmVzcG9uc2UiKQogICBwcmVkMDIgPSBwcmVkaWN0KGNhbmRpZGF0ZTAyLCBuZXdkYXRhID0gdmFsaWQsIHR5cGU9InJlc3BvbnNlIikKICAgcHJlZDAzID0gcHJlZGljdChjYW5kaWRhdGUwMywgbmV3ZGF0YSA9IHZhbGlkLCB0eXBlPSJyZXNwb25zZSIpCiAgIAogICBwcmUub3V0Y29tZTAxID0gaWZlbHNlKGFzLnZlY3RvcihwcmVkMDEpID4gMC41LCAxLCAwKQogICBwcmUub3V0Y29tZTAyID0gaWZlbHNlKGFzLnZlY3RvcihwcmVkMDIpID4gMC41LCAxLCAwKQogICBwcmUub3V0Y29tZTAzID0gaWZlbHNlKGFzLnZlY3RvcihwcmVkMDMpID4gMC41LCAxLCAwKQogICAKICAgUEUxW2ldID0gc3VtKHByZS5vdXRjb21lMDEgPT0gdmFsaWQkVGVhbVdpbiApL2xlbmd0aChwcmVkMDEpCiAgIFBFMltpXSA9IHN1bShwcmUub3V0Y29tZTAyID09IHZhbGlkJFRlYW1XaW4gKS9sZW5ndGgocHJlZDAyKQogICBQRTNbaV0gPSBzdW0ocHJlLm91dGNvbWUwMiA9PSB2YWxpZCRUZWFtV2luICkvbGVuZ3RoKHByZWQwMykKfQphdmcucGUgPSBjYmluZChQRTEgPSBtZWFuKFBFMSksIFBFMiA9IG1lYW4oUEUyKSwgUEUzID0gbWVhbihQRTMpKQprYWJsZShhdmcucGUsIGNhcHRpb24gPSAiQXZlcmFnZSBvZiBwcmVkaWN0aW9uIGVycm9ycyBvZiBjYW5kaWRhdGUgbW9kZWxzIikKCmBgYAoKVGhlIGF2ZXJhZ2UgcHJlZGljdGl2ZSBlcnJvcnMgb2YgYm90aCBtb2RlbCAxIGFuZCBtb2RlbCAyIGFyZSB0aGUgc2FtZS4gU2luY2UgbW9kZWwgMiBpcyBzaW1wbGVyIHRoYW4gbW9kZWwgMSwgd2UgY2hvb3NlIG1vZGVsIDIgYXMgdGhlIGZpbmFsIHByZWRpY3RpdmUgbW9kZWwuIFRoaXMgc2VsZWN0aW9uIG9mIHRoZSBmaW5hbCBtb2RlbCBpcyBiYXNlZCBvbiB0aGUgY3V0LW9mZiBwcm9iYWJpbGl0eSAwLjUuCgoKIyMjIEZpbmFsIE1vZGVsIFJlcG9ydGluZwoKVGhlIHByZXZpb3VzIGNyb3NzLXZhbGlkYXRpb24gcHJvY2VkdXJlIGlkZW50aWZpZWQgdGhlIGJlc3QgbW9kZWwgd2l0aCBwcmUtc2VsZWN0ZWQgY3V0LW9mZiAwLjUuIFRoZSBhY3R1YWwgYWNjdXJhY3kgb2YgdGhlIGZpbmFsIG1vZGVsIGlzIGdpdmVuIGJ5CgpgYGB7cn0KcHJlZDAyID0gcHJlZGljdChjYW5kaWRhdGUwMiwgbmV3ZGF0YSA9IHRlc3QsIHR5cGU9InJlc3BvbnNlIikKcHJlZDAyLm91dGNvbWUgPSBpZmVsc2UoYXMudmVjdG9yKHByZWQwMik+MC41LCAxLCAwKQoKYWNjdXJhY3kgPSBzdW0ocHJlZDAyLm91dGNvbWUgPT0gdGVzdCRUZWFtV2luKS9sZW5ndGgocHJlZDAyKQprYWJsZShhY2N1cmFjeSwgY2FwdGlvbj0iVGhlIGFjdHVhbCBhY2N1cmFjeSBvZiB0aGUgZmluYWwgbW9kZWwiKQoKCmBgYAoKTG9va2luZyBhdCB0aGVzZSByZXN1bHRzLCBpdCB0ZWxscyB1cyB0aGF0IHRoaXMgbW9kZWwgaGFzIGEgMTAwJSBhY2N1cmFjeSBvZiBwcmVkaWN0aW5nIHRoZSBvdXRjb21lIGluIHRoZSBmaW5hbCBtb2RlbC4gVGhpcyBzZWVtcyBjb3JyZWN0IGJlY2F1c2UgaG93IG1hbnkgcG9pbnRzIHlvdSBzY29yZSBhZmZlY3RzIHRoZSBvdXRjb21lIG9mIHRoZSBnYW1lIGdyZWF0bHkgYW5kIGhvdyBtbmF5IHBvaW50cyB5b3UgY2FuIGhvbGQgeW91ciBvcHBvbmVudCB0b28uIAoKCiMgQ29uY2x1c2lvbgoKSW4gdGhpcyBwcm9qZWN0IHdlIHdlcmUgdHJ5aW5nIHRvIG1ha2UgYSBtb2RlbCB0aGF0IHByZWRpY3RzIHdpbnMuIFRoZSBmaW5hbCByZXN1bHQgZm9yIHRoZSBhY2N1cmFjeSBvZiBvdXIgZmluYWwgbW9kZWwgd2FzIDEwMCUuIEFuIGFjY3VyYWN5IG9mIDEwMCUgc2hvd3MgdGhhdCB0aGUgbW9kZWwgaXMgaWRlbnRpZnlpbmcgaWYgYW4gb2JzZXJ2YXRpb24gZmFsbHMgaW50byB3aW4gKDEpIG9yIGxvc3MgKDApIGZvciAxMDAlIG9mIHRoZSB0aW1lLiAKCg==