Introduction
In this project we are trying to look at the research question, is
there an association between greens in regulation and the predictor
values available in the data set. We will look for the best model, do
bootstraping, and look at the bootstrap confidence intervals.
Data Description
The data I am using is about statistics on lpga golfers and how they
have done in the 2024 season. I got this data set off of the website (https://users.stat.ufl.edu/~winner/datasets.html).
The variables in this data set are
- Golfer- Name of the Golfer
- Nation- Where the golfer is from
- Region- What region the golfer is from
- fairways- How many fairways the golfer hit in regulation
- fairAtt- How many attempts the golfer took to get to the
fairway
- fairPct- The percent of fairways hit in regulation
- totPutts- Total amount of putts the golfer had
- totRounds- Total amouint of rounds played by the golfer
- avePutts- Average amount of putts when you reached the green per
hole
- greenReg- How many greens were hit in regulation
- totPrize- Amount of money won
- events- How many events the golfer went to
- driveDist- The average distance that the golfer hit with their
drive
- sandSaves- The amount of sand saves the golfer had
- sandAtt- The amount of shots taken from the sand
- sandPct- The percentage of shots that made it out of the sand
In this data set, we have sufficient information to address my
research question.
Research
Question
The point of this study is to figure out the association between
greens in regulation and the predictor values available in this data
set.
Data Preperation
We are going to take out some variables from the model. We will start
with Golfer, Nation, Region, totPrize, totRounds, and events due to
these variables either being categorical or insignificant to the model.
The number of events, number of rounds, and total prize will not be able
to influence getting on the green in regulation. We also need to drop
the variables totPutts, avePutts, sandSaves, and fairAtt because they
are also not variables that can affect a persons ability to get on the
green in regulation. This is due to them either being not directly
correlated or they happen after you get onto the green.
Model Building
Now we need to make the full model of the data and look to see if we
need to use a Box-Cox transformation on it.
Regression Coefficients
| (Intercept) |
-9.9257920 |
8.8445752 |
-1.122246 |
0.2635273 |
| fairway |
0.0191607 |
0.0018383 |
10.423042 |
0.0000000 |
| fairPct |
0.1406976 |
0.0467571 |
3.009119 |
0.0030680 |
| driveDist |
0.2407452 |
0.0253429 |
9.499498 |
0.0000000 |
| sandAtt |
-0.1105811 |
0.0172524 |
-6.409602 |
0.0000000 |
| sandPct |
0.0525978 |
0.0249874 |
2.104974 |
0.0369384 |

In these residual plots we can see that Q-Q residual plot is a
positive linear trend. The residuals vs fitted shows the points not
going in a cone shape and this makes the variance constant. Due to this
we do not need to do any box cox transformations.
Goodness-of-Fit
Now we should look at the goodness of fit measures to try and help
find the final model.
Goodness-of-fit Measures of Full Model
| full.model |
787.5965 |
0.6780546 |
0.6674643 |
6 |
265.8098 |
284.1853 |
862.4798 |
We have a sample size of 158 which is large. We can see from the
above table that the goodness-of-fit measures of the first model are
significant. This shows that the model has a 67% predictive ability to
predict greens in regulation.
Bootstrap
Here we will use the bootstrap method to get a confidence interval of
the coefficients in our selected model.
We will now make visual representations of histograms for each of the
regression coefficients in the final model.

Since both of the density curves in the histograms are close
together, we can conclude that the bootstrap confidence intervals will
be consistent with the significance tests.
The code below will get a 95% bootstrap confidence interval for the
final model.
Bootstrap CI
| (Intercept) |
-9.9258 |
8.8446 |
-1.1222 |
0.2635 |
[ 38.5803 , 81.9638 ] |
| fairway |
0.0192 |
0.0018 |
10.4230 |
0.0000 |
[ 0.0121 , 0.0128 ] |
| fairPct |
0.1407 |
0.0468 |
3.0091 |
0.0031 |
[ -0.1037 , 0.0992 ] |
| driveDist |
0.2407 |
0.0253 |
9.4995 |
0.0000 |
[ -0.0651 , 0.0633 ] |
| sandAtt |
-0.1106 |
0.0173 |
-6.4096 |
0.0000 |
[ -0.0266 , 0.0263 ] |
| sandPct |
0.0526 |
0.0250 |
2.1050 |
0.0369 |
[ -0.0666 , 0.0635 ] |
We can see that since some confidence intervals contain 0 that the
intervals are not consistent.
Residual
Bootstrap
Below is a histogram that shows the distribution of the bootstrap
residuals.

Looking at the histogram you can see that it is slightly left skewed
and there is one outlier on the far left.
We must make histograms to show the residual bootstrap estimates.

Looking at the histograms the density curves in the histograms are
close together, we can conclude that the bootstrap confidence intervals
will be consistent with the significance tests.
The 95% residual bootstrap confidence interval is shown below.
Regression Matrix with a 95% Residual Bootstrap CI
| (Intercept) |
-9.9258 |
8.8446 |
-1.1222 |
0.2635 |
[ -26.799 , 7.4838 ] |
| fairway |
0.0192 |
0.0018 |
10.4230 |
0.0000 |
[ 0.0155 , 0.0228 ] |
| fairPct |
0.1407 |
0.0468 |
3.0091 |
0.0031 |
[ 0.0479 , 0.2326 ] |
| driveDist |
0.2407 |
0.0253 |
9.4995 |
0.0000 |
[ 0.1908 , 0.2887 ] |
| sandAtt |
-0.1106 |
0.0173 |
-6.4096 |
0.0000 |
[ -0.1434 , -0.0759 ] |
| sandPct |
0.0526 |
0.0250 |
2.1050 |
0.0369 |
[ 0.0059 , 0.0996 ] |
The residual bootstrap confidence intervals look better than the none
residual confidence intervals. This is due to how every interval besides
the intercept do not contain 0. This is because the sample size is large
enough so that the sampling distributions of estimated coefficients have
sufficiently good approximations of normal distributions.
Combining
Results
Finally, we put all inferential statistics in a single table so we
can compare these results.
Final Combined Inferential Statistics
| (Intercept) |
-9.9258 |
8.8446 |
0.2635 |
[ 38.5803 , 81.9638 ] |
[ -26.799 , 7.4838 ] |
| fairway |
0.0192 |
0.0018 |
0.0000 |
[ 0.0121 , 0.0128 ] |
[ 0.0155 , 0.0228 ] |
| fairPct |
0.1407 |
0.0468 |
0.0031 |
[ -0.1037 , 0.0992 ] |
[ 0.0479 , 0.2326 ] |
| driveDist |
0.2407 |
0.0253 |
0.0000 |
[ -0.0651 , 0.0633 ] |
[ 0.1908 , 0.2887 ] |
| sandAtt |
-0.1106 |
0.0173 |
0.0000 |
[ -0.0266 , 0.0263 ] |
[ -0.1434 , -0.0759 ] |
| sandPct |
0.0526 |
0.0250 |
0.0369 |
[ -0.0666 , 0.0635 ] |
[ 0.0059 , 0.0996 ] |
This table shows the results side by side of the two bootstrap
confidence intervals. Looking at them side to side you can see how much
better the intervals for the residual bootstrap are compared to the
regular bootstrap confidence interval.
width of the two bootstrap confidence intervals
| 43.3835 |
0.1301 |
| 0.0008 |
0.1301 |
| 0.2029 |
0.1301 |
| 0.1284 |
0.1301 |
| 0.0529 |
0.1301 |
| 0.1301 |
0.1301 |
Looking at this table you can see that the widths of the residual
bootstrap are more consistent than the regular bootstrap.
Summary and
Discussion
We didn’t have to use many different techniques such as Box-Cox to
transform the response variables. This was due to the assumption of
constant variance being met. We got rid of all the variables that would
not be significant or have any association in evaluating getting on the
green in regulation due to my past experience.
Looking at the response variable we can see most variables besides
fairways hit contain 0 in the confidence interval for the combined
inferential statistics. This shows that fairways hit is the most
statistically significant variable in comparison to greens in
regulation.
I had no drawbacks or improvements I can think of.
In the future I will use total prize as my response variable. This is
because you can see then what statistic in golf is the most important
factor in how much you win in games.
LS0tCnRpdGxlOiAiV2hhdCBoZWxwcyBhIGdvbGZlciBnZXQgdG8gZ3JlZW5zIGluIHJlZ3VsYXRpb24/IgphdXRob3I6ICJSeWFuIExlYm8iCmRhdGU6ICIyMDI0LTEwLTIyIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICB0b2NfZmxvYXQ6IHllcwogICAgZmlnX3dpZHRoOiA0CiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdG9jX2NvbGxhcHNlZDogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgc21vb3RoX3Njcm9sbDogeWVzCiAgICB0aGVtZTogbHVtZW4KICB3b3JkX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNAogICAgZmlnX2NhcHRpb246IHllcwogICAga2VlcF9tZDogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNAogICAgZmlnX2NhcHRpb246IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIGZpZ193aWR0aDogMwogICAgZmlnX2hlaWdodDogMwplZGl0b3Jfb3B0aW9uczoKICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lCnNsd2F5c19hbGxvd19odG1sOiB0cnVlCi0tLQoKCgpgYGB7PWh0bWx9Cgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoKLyogQ2FzY2FkaW5nIFN0eWxlIFNoZWV0cyAoQ1NTKSBpcyBhIHN0eWxlc2hlZXQgbGFuZ3VhZ2UgdXNlZCB0byBkZXNjcmliZSB0aGUgcHJlc2VudGF0aW9uIG9mIGEgZG9jdW1lbnQgd3JpdHRlbiBpbiBIVE1MIG9yIFhNTC4gaXQgaXMgYSBzaW1wbGUgbWVjaGFuaXNtIGZvciBhZGRpbmcgc3R5bGUgKGUuZy4sIGZvbnRzLCBjb2xvcnMsIHNwYWNpbmcpIHRvIFdlYiBkb2N1bWVudHMuICovCgpoMS50aXRsZSB7ICAvKiBUaXRsZSAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgdGhlIHJlcG9ydCB0aXRsZSAqLwogIGZvbnQtc2l6ZTogMjRweDsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOwp9Cmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgYXV0aG9ycyAgKi8KICBmb250LXNpemU6IDIwcHg7CiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgdGhlIGRhdGUgICovCiAgZm9udC1zaXplOiAxOHB4OwogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7CiAgY29sb3I6IERhcmtCbHVlOwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQpoMSB7IC8qIEhlYWRlciAxIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMSBzZWN0aW9uIHRpdGxlICAqLwogICAgZm9udC1zaXplOiAyMnB4OwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGNlbnRlcjsKfQpoMiB7IC8qIEhlYWRlciAyIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBmb3IgbGV2ZWwgMiBzZWN0aW9uIHRpdGxlICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQoKaDMgeyAvKiBIZWFkZXIgMyAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgbGV2ZWwgMyBzZWN0aW9uIHRpdGxlICAqLwogICAgZm9udC1zaXplOiAxOHB4OwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBmb250IHNwZWNpZmljYXRpb25zIG9mIGxldmVsIDQgc2VjdGlvbiB0aXRsZSAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9Cgpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQoKLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0KCnAgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9Cgo8L3N0eWxlPgpgYGAKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiMgRGV0ZWN0LCBpbnN0YWxsLCBhbmQgbG9hZCBwYWNrYWdlcyBpZiBuZWVkZWQuCmlmICghcmVxdWlyZSgia25pdHIiKSkgewogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpCiAgIGxpYnJhcnkoa25pdHIpCn0KaWYgKCFyZXF1aXJlKCJsZWFmbGV0IikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygibGVhZmxldCIpCiAgIGxpYnJhcnkobGVhZmxldCkKfQppZiAoIXJlcXVpcmUoIkVudlN0YXRzIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygiRW52U3RhdHMiKQogICBsaWJyYXJ5KEVudlN0YXRzKQp9CmlmICghcmVxdWlyZSgiTUFTUyIpKSB7CiAgIGluc3RhbGwucGFja2FnZXMoIk1BU1MiKQogICBsaWJyYXJ5KE1BU1MpCn0KaWYgKCFyZXF1aXJlKCJwaHl0b29scyIpKSB7CiAgIGluc3RhbGwucGFja2FnZXMoInBoeXRvb2xzIikKICAgbGlicmFyeShwaHl0b29scykKfQojCiMgU3BlY2lmaWNhdGlvbnMgb2Ygb3V0cHV0cyBvZiBjb2RlIGluIGNvZGUgY2h1bmtzCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UsICAjIGluY2x1ZGUgY29kZSBjaHVuayBpbiB0aGUgb3V0cHV0IGZpbGUKICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICMgU29tZXRpbWVzLCB5b3VyIGNvZGUgbWF5IHByb2R1Y2UgYSB3YXJuaW5nCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG1lc3NhZ2VzLCB5b3UgY2FuIGNob29zZSB0byBpbmNsdWRlIHRoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB3YXJuaW5nIG1lc3NhZ2VzIGluIHRoZSBvdXRwdXQgZmlsZS4gCiAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsICAKICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBvdXRwdXQgaW4gdGhlIG91dHB1dCBmaWxlLgogICAgICAgICAgICAgICAgICAgY29tbWVudCA9IEZBTFNFICAgIyBTdXBwcmVzcyBoYXNoLXRhZ3MgaW4gdGhlIG91dHB1dCByZXN1bHRzLgogICAgICAgICAgICAgICAgICAgICAgKSAgIApgYGAKCiMgSW50cm9kdWN0aW9uCkluIHRoaXMgcHJvamVjdCB3ZSBhcmUgdHJ5aW5nIHRvIGxvb2sgYXQgdGhlIHJlc2VhcmNoIHF1ZXN0aW9uLCBpcyB0aGVyZSBhbiBhc3NvY2lhdGlvbiBiZXR3ZWVuIGdyZWVucyBpbiByZWd1bGF0aW9uIGFuZCB0aGUgcHJlZGljdG9yIHZhbHVlcyBhdmFpbGFibGUgaW4gdGhlIGRhdGEgc2V0LiBXZSB3aWxsIGxvb2sgZm9yIHRoZSBiZXN0IG1vZGVsLCBkbyBib290c3RyYXBpbmcsIGFuZCBsb29rIGF0IHRoZSBib290c3RyYXAgY29uZmlkZW5jZSBpbnRlcnZhbHMuCgoKIyMgRGF0YSBEZXNjcmlwdGlvbgpUaGUgZGF0YSBJIGFtIHVzaW5nIGlzIGFib3V0IHN0YXRpc3RpY3Mgb24gbHBnYSBnb2xmZXJzIGFuZCBob3cgdGhleSBoYXZlIGRvbmUgaW4gdGhlIDIwMjQgc2Vhc29uLiBJIGdvdCB0aGlzIGRhdGEgc2V0IG9mZiBvZiB0aGUgd2Vic2l0ZSAoaHR0cHM6Ly91c2Vycy5zdGF0LnVmbC5lZHUvfndpbm5lci9kYXRhc2V0cy5odG1sKS4KClRoZSB2YXJpYWJsZXMgaW4gdGhpcyBkYXRhIHNldCBhcmUgCgoqIEdvbGZlci0gTmFtZSBvZiB0aGUgR29sZmVyCiogTmF0aW9uLSBXaGVyZSB0aGUgZ29sZmVyIGlzIGZyb20KKiBSZWdpb24tIFdoYXQgcmVnaW9uIHRoZSBnb2xmZXIgaXMgZnJvbQoqIGZhaXJ3YXlzLSBIb3cgbWFueSBmYWlyd2F5cyB0aGUgZ29sZmVyIGhpdCBpbiByZWd1bGF0aW9uCiogZmFpckF0dC0gSG93IG1hbnkgYXR0ZW1wdHMgdGhlIGdvbGZlciB0b29rIHRvIGdldCB0byB0aGUgZmFpcndheQoqIGZhaXJQY3QtIFRoZSBwZXJjZW50IG9mIGZhaXJ3YXlzIGhpdCBpbiByZWd1bGF0aW9uCiogdG90UHV0dHMtIFRvdGFsIGFtb3VudCBvZiBwdXR0cyB0aGUgZ29sZmVyIGhhZCAKKiB0b3RSb3VuZHMtIFRvdGFsIGFtb3VpbnQgb2Ygcm91bmRzIHBsYXllZCBieSB0aGUgZ29sZmVyCiogYXZlUHV0dHMtIEF2ZXJhZ2UgYW1vdW50IG9mIHB1dHRzIHdoZW4geW91IHJlYWNoZWQgdGhlIGdyZWVuIHBlciBob2xlCiogZ3JlZW5SZWctIEhvdyBtYW55IGdyZWVucyB3ZXJlIGhpdCBpbiByZWd1bGF0aW9uCiogdG90UHJpemUtIEFtb3VudCBvZiBtb25leSB3b24KKiBldmVudHMtIEhvdyBtYW55IGV2ZW50cyB0aGUgZ29sZmVyIHdlbnQgdG8KKiBkcml2ZURpc3QtIFRoZSBhdmVyYWdlIGRpc3RhbmNlIHRoYXQgdGhlIGdvbGZlciBoaXQgd2l0aCB0aGVpciBkcml2ZQoqIHNhbmRTYXZlcy0gVGhlIGFtb3VudCBvZiBzYW5kIHNhdmVzIHRoZSBnb2xmZXIgaGFkCiogc2FuZEF0dC0gVGhlIGFtb3VudCBvZiBzaG90cyB0YWtlbiBmcm9tIHRoZSBzYW5kCiogc2FuZFBjdC0gVGhlIHBlcmNlbnRhZ2Ugb2Ygc2hvdHMgdGhhdCBtYWRlIGl0IG91dCBvZiB0aGUgc2FuZAoKSW4gdGhpcyBkYXRhIHNldCwgd2UgaGF2ZSBzdWZmaWNpZW50IGluZm9ybWF0aW9uIHRvIGFkZHJlc3MgbXkgcmVzZWFyY2ggcXVlc3Rpb24uCgojIyBSZXNlYXJjaCBRdWVzdGlvbgpUaGUgcG9pbnQgb2YgdGhpcyBzdHVkeSBpcyB0byBmaWd1cmUgb3V0IHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGdyZWVucyBpbiByZWd1bGF0aW9uIGFuZCB0aGUgcHJlZGljdG9yIHZhbHVlcyBhdmFpbGFibGUgaW4gdGhpcyBkYXRhIHNldC4gCgojIyBEYXRhIFByZXBlcmF0aW9uCgpXZSBhcmUgZ29pbmcgdG8gdGFrZSBvdXQgc29tZSB2YXJpYWJsZXMgZnJvbSB0aGUgbW9kZWwuIFdlIHdpbGwgc3RhcnQgd2l0aCBHb2xmZXIsIE5hdGlvbiwgUmVnaW9uLCB0b3RQcml6ZSwgdG90Um91bmRzLCBhbmQgZXZlbnRzIGR1ZSB0byB0aGVzZSB2YXJpYWJsZXMgZWl0aGVyIGJlaW5nIGNhdGVnb3JpY2FsIG9yIGluc2lnbmlmaWNhbnQgdG8gdGhlIG1vZGVsLiBUaGUgbnVtYmVyIG9mIGV2ZW50cywgbnVtYmVyIG9mIHJvdW5kcywgYW5kIHRvdGFsIHByaXplIHdpbGwgbm90IGJlIGFibGUgdG8gaW5mbHVlbmNlIGdldHRpbmcgb24gdGhlIGdyZWVuIGluIHJlZ3VsYXRpb24uIFdlIGFsc28gbmVlZCB0byBkcm9wIHRoZSB2YXJpYWJsZXMgdG90UHV0dHMsIGF2ZVB1dHRzLCBzYW5kU2F2ZXMsIGFuZCBmYWlyQXR0IGJlY2F1c2UgdGhleSBhcmUgYWxzbyBub3QgdmFyaWFibGVzIHRoYXQgY2FuIGFmZmVjdCBhIHBlcnNvbnMgYWJpbGl0eSB0byBnZXQgb24gdGhlIGdyZWVuIGluIHJlZ3VsYXRpb24uIFRoaXMgaXMgZHVlIHRvIHRoZW0gZWl0aGVyIGJlaW5nIG5vdCBkaXJlY3RseSBjb3JyZWxhdGVkIG9yIHRoZXkgaGFwcGVuIGFmdGVyIHlvdSBnZXQgb250byB0aGUgZ3JlZW4uCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcid9CmxwZ2EwIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vUnlhbkxlYm8vU1RBLTMyMS9yZWZzL2hlYWRzL21haW4vbHBnYTIwMjIuY3N2IiwgaGVhZGVyID0gVFJVRSkKbHBnYSA8LSBscGdhMFssIC0xXQoKZmFpcndheTwtIGxwZ2EkZmFpcndheXMKZ3JlZW5zIDwtIGxwZ2EkZ3JlZW5SZWcgCgoKYGBgCgoKIyBNb2RlbCBCdWlsZGluZwoKTm93IHdlIG5lZWQgdG8gbWFrZSB0aGUgZnVsbCBtb2RlbCBvZiB0aGUgZGF0YSBhbmQgbG9vayB0byBzZWUgaWYgd2UgbmVlZCB0byB1c2UgYSBCb3gtQ294IHRyYW5zZm9ybWF0aW9uIG9uIGl0LgoKCmBgYHtyfQpmdWxsLm1vZGVsID0gbG0oZ3JlZW5zIH4gZmFpcndheSsgZmFpclBjdCsgZHJpdmVEaXN0KyBzYW5kQXR0KyBzYW5kUGN0LCBkYXRhID0gbHBnYSkKa2FibGUoc3VtbWFyeShmdWxsLm1vZGVsKSRjb2VmLCBjYXB0aW9uID0iUmVncmVzc2lvbiBDb2VmZmljaWVudHMiKQoKYGBgCgoKYGBge3J9CnBhcihtZnJvdz1jKDIsMikpCnBsb3QoZnVsbC5tb2RlbCkKCmBgYAoKSW4gdGhlc2UgcmVzaWR1YWwgcGxvdHMgd2UgY2FuIHNlZSB0aGF0IFEtUSByZXNpZHVhbCBwbG90IGlzIGEgcG9zaXRpdmUgbGluZWFyIHRyZW5kLiBUaGUgcmVzaWR1YWxzIHZzIGZpdHRlZCBzaG93cyB0aGUgcG9pbnRzIG5vdCBnb2luZyBpbiBhIGNvbmUgc2hhcGUgYW5kIHRoaXMgbWFrZXMgdGhlIHZhcmlhbmNlIGNvbnN0YW50LiBEdWUgdG8gdGhpcyB3ZSBkbyBub3QgbmVlZCB0byBkbyBhbnkgYm94IGNveCB0cmFuc2Zvcm1hdGlvbnMuCgojIyBHb29kbmVzcy1vZi1GaXQKCk5vdyB3ZSBzaG91bGQgbG9vayBhdCB0aGUgZ29vZG5lc3Mgb2YgZml0IG1lYXN1cmVzIHRvIHRyeSBhbmQgaGVscCBmaW5kIHRoZSBmaW5hbCBtb2RlbC4KCmBgYHtyfQpzZWxlY3Q9ZnVuY3Rpb24obSl7IAogZSA9IG0kcmVzaWQgICAgICAgICAgICAgICAgICAgICAgICAgCiBuMCA9IGxlbmd0aChlKSAgICAgICAgICAgICAgICAgICAgICAgIAogU1NFPShtJGRmKSooc3VtbWFyeShtKSRzaWdtYSleMiAgICAgIAogUi5zcT1zdW1tYXJ5KG0pJHIuc3F1YXJlZCAgICAgICAgICAgICAKIFIuYWRqPXN1bW1hcnkobSkkYWRqLnIgICAgICAgICAgICAgICAgCiBNU0U9KHN1bW1hcnkobSkkc2lnbWEpXjIgICAgICAgICAgICAgIAogQ3A9KFNTRS9NU0UpLShuMC0yKihuMC1tJGRmKSkgICAgICAgIAogQUlDPW4wKmxvZyhTU0UpLW4wKmxvZyhuMCkrMioobjAtbSRkZikgICAgICAgICAKIFNCQz1uMCpsb2coU1NFKS1uMCpsb2cobjApKyhsb2cobjApKSoobjAtbSRkZikgIAogWD1tb2RlbC5tYXRyaXgobSkgICAgICAgICAgICAgICAgICAgICAKIEg9WCUqJXNvbHZlKHQoWCklKiVYKSUqJXQoWCkgICAgICAgICAKIGQ9ZS8oMS1kaWFnKEgpKSAgICAgICAgICAgICAgICAgICAgICAgCiBQUkVTUz10KGQpJSolZCAgIAogdGJsID0gYXMuZGF0YS5mcmFtZShjYmluZChTU0U9U1NFLCBSLnNxPVIuc3EsIFIuYWRqID0gUi5hZGosIENwID0gQ3AsIEFJQyA9IEFJQywgU0JDID0gU0JDLCBQUkQgPSBQUkVTUykpCiBuYW1lcyh0YmwpPWMoIlNTRSIsICJSLnNxIiwgIlIuYWRqIiwgIkNwIiwgIkFJQyIsICJTQkMiLCAiUFJFU1MiKQogdGJsCiB9CgpgYGAKCmBgYHtyfQpvdXRwdXQuc3VtID0gcmJpbmQoc2VsZWN0KGZ1bGwubW9kZWwpKQpyb3cubmFtZXMob3V0cHV0LnN1bSkgPSBjKCJmdWxsLm1vZGVsIikKa2FibGUob3V0cHV0LnN1bSwgY2FwdGlvbiA9ICJHb29kbmVzcy1vZi1maXQgTWVhc3VyZXMgb2YgRnVsbCBNb2RlbCIpCmBgYAoKV2UgaGF2ZSBhIHNhbXBsZSBzaXplIG9mIDE1OCB3aGljaCBpcyBsYXJnZS4gV2UgY2FuIHNlZSBmcm9tIHRoZSBhYm92ZSB0YWJsZSB0aGF0IHRoZSBnb29kbmVzcy1vZi1maXQgbWVhc3VyZXMgb2YgdGhlIGZpcnN0IG1vZGVsIGFyZSBzaWduaWZpY2FudC4gVGhpcyBzaG93cyB0aGF0IHRoZSBtb2RlbCBoYXMgYSA2NyUgcHJlZGljdGl2ZSBhYmlsaXR5IHRvIHByZWRpY3QgZ3JlZW5zIGluIHJlZ3VsYXRpb24uCgoKIyBCb290c3RyYXAKCkhlcmUgd2Ugd2lsbCB1c2UgdGhlIGJvb3RzdHJhcCBtZXRob2QgdG8gZ2V0IGEgY29uZmlkZW5jZSBpbnRlcnZhbCBvZiB0aGUgY29lZmZpY2llbnRzIGluIG91ciBzZWxlY3RlZCBtb2RlbC4gCgpgYGB7cn0KZnVsbCA9IGxtKGdyZWVucyB+IGZhaXJ3YXkrIGZhaXJQY3QrIGRyaXZlRGlzdCsgc2FuZEF0dCsgc2FuZFBjdCwgZGF0YSA9IGxwZ2EpCgpCID0gMTAwMCAgICAgIAoKcGFyYV9mdWxsID0gZGltKG1vZGVsLmZyYW1lKGZ1bGwpKVsyXSAgCnNhbXBfZnVsbCA9IGRpbShtb2RlbC5mcmFtZShmdWxsKSlbMV0gCmNvZWYubXRyeCA9IG1hdHJpeChyZXAoMCwgQipwYXJhX2Z1bGwpLCBuY29sID0gcGFyYV9mdWxsKSAgICAgICAKCmZvciAoaSBpbiAxOkIpewogIGJvb3RjLmlkID0gc2FtcGxlKDE6c2FtcF9mdWxsLCBzYW1wX2Z1bGwsIHJlcGxhY2UgPSBUUlVFKSAKIGJ0X2Z1bGwgPWxtKGdyZWVucyB+IGZhaXJ3YXkrIGZhaXJQY3QrIGRyaXZlRGlzdCsgc2FuZEF0dCsgc2FuZFBjdCwgZGF0YSA9IGxwZ2FbYm9vdGMuaWQsXSkKICAKICBjb2VmLm10cnhbaSxdID0gY29lZihidF9mdWxsKSAgICAKfQpgYGAKCgpgYGB7cn0KYm9vdF9oaXN0ID0gZnVuY3Rpb24obG9nX3RyeCwgYnQuY29lZi5tdHJ4LCB2YXIuaWQsIHZhci5ubSl7CiAKICB4MS4xIDwtIHNlcShtaW4oYnQuY29lZi5tdHJ4Wyx2YXIuaWRdKSwgbWF4KGJ0LmNvZWYubXRyeFssdmFyLmlkXSksIGxlbmd0aD0zMDAgKQogIHkxLjEgPC0gZG5vcm0oeDEuMSwgbWVhbihidC5jb2VmLm10cnhbLHZhci5pZF0pLCBzZChidC5jb2VmLm10cnhbLHZhci5pZF0pKQoKICBoaWdoZXN0YmFyID0gbWF4KGhpc3QoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdLCBwbG90ID0gRkFMU0UpJGRlbnNpdHkpIAogIHlsaW1pdCA8LSBtYXgoYyh5MS4xLGhpZ2hlc3RiYXIpKQogIGhpc3QoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdLCBwcm9iYWJpbGl0eSA9IFRSVUUsIG1haW4gPSB2YXIubm0sIHhsYWI9IiIsIAogICAgICAgY29sID0gImF6dXJlMSIseWxpbT1jKDAseWxpbWl0KSwgYm9yZGVyPSJsaWdodHNlYWdyZWVuIikKICBsaW5lcyh4ID0geDEuMSwgeSA9IHkxLjEsIGNvbCA9ICJyZWQzIikKICBsaW5lcyhkZW5zaXR5KGJ0LmNvZWYubXRyeFssdmFyLmlkXSwgYWRqdXN0PTIpLCBjb2w9ImJsdWUiKSAKCn0KYGBgCgpXZSB3aWxsIG5vdyBtYWtlIHZpc3VhbCByZXByZXNlbnRhdGlvbnMgb2YgaGlzdG9ncmFtcyBmb3IgZWFjaCBvZiB0aGUgcmVncmVzc2lvbiBjb2VmZmljaWVudHMgaW4gdGhlIGZpbmFsIG1vZGVsLgoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD01fQpwYXIobWZyb3c9YygyLDMpKSAgCmJvb3RfaGlzdChidC5jb2VmLm10cng9Y29lZi5tdHJ4LCB2YXIuaWQ9MSwgdmFyLm5tID0iSW50ZXJjZXB0IiApCmJvb3RfaGlzdChidC5jb2VmLm10cng9Y29lZi5tdHJ4LCB2YXIuaWQ9MiwgdmFyLm5tID0iRmFpcndheSIgKQpib290X2hpc3QoYnQuY29lZi5tdHJ4PWNvZWYubXRyeCwgdmFyLmlkPTMsIHZhci5ubSA9IkRyaXZlIERpc3RhbmNlIiApCmJvb3RfaGlzdChidC5jb2VmLm10cng9Y29lZi5tdHJ4LCB2YXIuaWQ9NCwgdmFyLm5tID0iU2FuZCBBdHRlbXB0cyIgKQpib290X2hpc3QoYnQuY29lZi5tdHJ4PWNvZWYubXRyeCwgdmFyLmlkPTUsIHZhci5ubSA9IlNhbmQgUGVyY2VudCIgKQpib290X2hpc3QoYnQuY29lZi5tdHJ4PWNvZWYubXRyeCwgdmFyLmlkPTYsIHZhci5ubSA9IkZhaXJ3YXkgUGVyY2VudCIgKQoKYGBgCgpTaW5jZSBib3RoIG9mIHRoZSBkZW5zaXR5IGN1cnZlcyBpbiB0aGUgaGlzdG9ncmFtcyBhcmUgY2xvc2UgdG9nZXRoZXIsIHdlIGNhbiBjb25jbHVkZSB0aGF0IHRoZSBib290c3RyYXAgY29uZmlkZW5jZSBpbnRlcnZhbHMgd2lsbCBiZSBjb25zaXN0ZW50IHdpdGggdGhlIHNpZ25pZmljYW5jZSB0ZXN0cy4KClRoZSBjb2RlIGJlbG93IHdpbGwgZ2V0IGEgOTUlIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgZmluYWwgbW9kZWwuCgpgYGB7cn0KY210cnggPC0gc3VtbWFyeShmdWxsKSRjb2VmCnBhcmFfZnVsbDIgPSBkaW0oY29lZi5tdHJ4KVsyXSAgCmJvb3RfY29uZiA9IE5VTEwKYm9vdF93ZCA9IE5VTEwKZm9yIChpIGluIDE6cGFyYV9mdWxsMil7CiAgbG93X2NvbmYgPSByb3VuZChxdWFudGlsZShjb2VmLm10cnhbLCBpXSwgMC4wMjUsIHR5cGUgPSAyKSw4KQogIHVwX2NvbmYgPSByb3VuZChxdWFudGlsZShjb2VmLm10cnhbLCBpXSwwLjk3NSwgdHlwZSA9IDIgKSw4KQogIGJvb3Rfd2RbaV0gPSAgdXBfY29uZiAtIGxvd19jb25mCiAgYm9vdF9jb25mW2ldID0gcGFzdGUoIlsiLCByb3VuZChsb3dfY29uZiw0KSwiLCAiLCByb3VuZCh1cF9jb25mLDQpLCJdIikKIH0KCmthYmxlKGFzLmRhdGEuZnJhbWUoY2JpbmQoZm9ybWF0QyhjbXRyeCw0LGZvcm1hdD0iZiIpLCBib290X2NvbmYuOTU9Ym9vdF9jb25mKSksIAogICAgICBjYXB0aW9uID0gIkJvb3RzdHJhcCBDSSIpCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHNpbmNlIHNvbWUgY29uZmlkZW5jZSBpbnRlcnZhbHMgY29udGFpbiAwIHRoYXQgdGhlIGludGVydmFscyBhcmUgbm90IGNvbnNpc3RlbnQuCgojIyBSZXNpZHVhbCBCb290c3RyYXAKCkJlbG93IGlzIGEgaGlzdG9ncmFtIHRoYXQgc2hvd3MgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgYm9vdHN0cmFwIHJlc2lkdWFscy4KCmBgYHtyIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9NH0KaGlzdChzb3J0KGZ1bGwkcmVzaWR1YWxzKSxuPTQwLAogICAgIHhsYWI9IlJlc2lkdWFscyIsCiAgICAgY29sID0gImxpZ2h0Ymx1ZSIsCiAgICAgYm9yZGVyPSJyZWQiLAogICAgIG1haW4gPSAiSGlzdG9ncmFtIG9mIEJvb3RzdHJhcCBSZXNpZHVhbHMiKQpgYGAKCkxvb2tpbmcgYXQgdGhlIGhpc3RvZ3JhbSB5b3UgY2FuIHNlZSB0aGF0IGl0IGlzIHNsaWdodGx5IGxlZnQgc2tld2VkIGFuZCB0aGVyZSBpcyBvbmUgb3V0bGllciBvbiB0aGUgZmFyIGxlZnQuCgoKYGBge3J9CmZ1bGwyID0gbG0oZ3JlZW5zIH4gZmFpcndheSsgZmFpclBjdCsgZHJpdmVEaXN0KyBzYW5kQXR0KyBzYW5kUGN0LCBkYXRhID0gbHBnYSkKCm1vZGVsX3Jlc2lkID0gZnVsbDIkcmVzaWR1YWxzCgpCID0gMTAwMCAgICAgIAoKcGFyYV9mdWxsMyA9IGRpbShtb2RlbC5tYXRyaXgoZnVsbDIpKVsyXSAgCnNhbXBfZnVsbDIgPSBkaW0obW9kZWwubWF0cml4KGZ1bGwyKSlbMV0gCmJ0ci5tdHJ4ID0gbWF0cml4KHJlcCgwLCBwYXJhX2Z1bGwzICogQiksIG5jb2wgPSBwYXJhX2Z1bGwzKQoKZm9yIChpIGluIDE6Qil7CiAgIGJ0LmZ1bGwuZ3JlZW4gPSBmdWxsMiRmaXR0ZWQudmFsdWVzICsKICAgICAgICBzYW1wbGUoZnVsbDIkcmVzaWR1YWxzLCBzYW1wX2Z1bGwyLCByZXBsYWNlID0gVFJVRSkgCiAgIGJ0ci5tb2RlbCA9IGxtKGJ0LmZ1bGwuZ3JlZW4gfmZhaXJ3YXkrZmFpclBjdCsgZHJpdmVEaXN0KyBzYW5kQXR0KyBzYW5kUGN0LCBkYXRhID0gbHBnYSkgCiAgYnRyLm10cnhbaSxdPWJ0ci5tb2RlbCRjb2VmZmljaWVudHMgCn0KYGBgCgoKV2UgbXVzdCBtYWtlIGhpc3RvZ3JhbXMgdG8gc2hvdyB0aGUgcmVzaWR1YWwgYm9vdHN0cmFwIGVzdGltYXRlcy4KCmBgYHtyfQpib290Lmhpc3QgPSBmdW5jdGlvbihidC5jb2VmLm10cngsIHZhci5pZCwgdmFyLm5tKXsKIAogIHgxLjEgPC0gc2VxKG1pbihidC5jb2VmLm10cnhbLHZhci5pZF0pLCBtYXgoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdKSwgbGVuZ3RoPTMwMCApCiAgeTEuMSA8LSBkbm9ybSh4MS4xLCBtZWFuKGJ0LmNvZWYubXRyeFssdmFyLmlkXSksIHNkKGJ0LmNvZWYubXRyeFssdmFyLmlkXSkpCgogIGhpZ2hlc3RiYXIgPSBtYXgoaGlzdChidC5jb2VmLm10cnhbLHZhci5pZF0sIHBsb3QgPSBGQUxTRSkkZGVuc2l0eSkgCiAgeWxpbWl0IDwtIG1heChjKHkxLjEsaGlnaGVzdGJhcikpCiAgaGlzdChidC5jb2VmLm10cnhbLHZhci5pZF0sIHByb2JhYmlsaXR5ID0gVFJVRSwgbWFpbiA9IHZhci5ubSwgeGxhYj0iIiwgCiAgICAgICBjb2wgPSAiYXp1cmUxIix5bGltPWMoMCx5bGltaXQpLCBib3JkZXI9ImxpZ2h0c2VhZ3JlZW4iKQogIGxpbmVzKHggPSB4MS4xLCB5ID0geTEuMSwgY29sID0gInJlZDMiKQogIGxpbmVzKGRlbnNpdHkoYnQuY29lZi5tdHJ4Wyx2YXIuaWRdLCBhZGp1c3Q9MiksIGNvbD0iYmx1ZSIpIAoKfQpgYGAKCgoKYGBge3IgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD01fQpwYXIobWZyb3c9YygyLDMpKSAgCmJvb3QuaGlzdChidC5jb2VmLm10cng9YnRyLm10cngsIHZhci5pZD0xLCB2YXIubm0gPSJJbnRlcmNlcHQiICkKYm9vdC5oaXN0KGJ0LmNvZWYubXRyeD1idHIubXRyeCwgdmFyLmlkPTIsIHZhci5ubSA9IkZhaXJ3YXkiICkKYm9vdC5oaXN0KGJ0LmNvZWYubXRyeD1idHIubXRyeCwgdmFyLmlkPTMsIHZhci5ubSA9IkRyaXZlIERpc3RhbmNlIiApCmJvb3QuaGlzdChidC5jb2VmLm10cng9YnRyLm10cngsIHZhci5pZD00LCB2YXIubm0gPSJTYW5kIEF0dGVtcHRzIiApCmJvb3QuaGlzdChidC5jb2VmLm10cng9YnRyLm10cngsIHZhci5pZD01LCB2YXIubm0gPSJTYW5kIFBlcmNlbnQiICkKYm9vdC5oaXN0KGJ0LmNvZWYubXRyeD1idHIubXRyeCwgdmFyLmlkPTYsIHZhci5ubSA9IkZhaXJ3YXkgUGVyY2VudCIgKQoKCmBgYAoKTG9va2luZyBhdCB0aGUgaGlzdG9ncmFtcyB0aGUgZGVuc2l0eSBjdXJ2ZXMgaW4gdGhlIGhpc3RvZ3JhbXMgYXJlIGNsb3NlIHRvZ2V0aGVyLCB3ZSBjYW4gY29uY2x1ZGUgdGhhdCB0aGUgYm9vdHN0cmFwIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHdpbGwgYmUgY29uc2lzdGVudCB3aXRoIHRoZSBzaWduaWZpY2FuY2UgdGVzdHMuCgpUaGUgOTUlIHJlc2lkdWFsIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFsIGlzIHNob3duIGJlbG93LgoKYGBge3J9CgpwYXJhX2Z1bGw0ID0gZGltKGNvZWYubXRyeClbMl0gIApib290X2NvbmYyID0gTlVMTApib290X3dkMiA9IE5VTEwKZm9yIChpIGluIDE6cGFyYV9mdWxsNCl7CiAgbG93X2NvbmYyID0gcm91bmQocXVhbnRpbGUoYnRyLm10cnhbLCBpXSwgMC4wMjUsIHR5cGUgPSAyKSw4KQogIHVwX2NvbmYyID0gcm91bmQocXVhbnRpbGUoYnRyLm10cnhbLCBpXSwwLjk3NSwgdHlwZSA9IDIgKSw4KQogIGJvb3Rfd2QyW2ldID0gdXBfY29uZiAtIGxvd19jb25mCiAgYm9vdF9jb25mMltpXSA9IHBhc3RlKCJbIiwgcm91bmQobG93X2NvbmYyLDQpLCIsICIsIHJvdW5kKHVwX2NvbmYyLDQpLCJdIikKfQoKa2FibGUoYXMuZGF0YS5mcmFtZShjYmluZChmb3JtYXRDKGNtdHJ4LDQsZm9ybWF0PSJmIiksIGJvb3RfY29uZi45NT1ib290X2NvbmYyKSksIAogICAgICBjYXB0aW9uID0gIlJlZ3Jlc3Npb24gTWF0cml4IHdpdGggYSA5NSUgUmVzaWR1YWwgQm9vdHN0cmFwIENJIikKYGBgCgpUaGUgcmVzaWR1YWwgYm9vdHN0cmFwIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGxvb2sgYmV0dGVyIHRoYW4gdGhlIG5vbmUgcmVzaWR1YWwgY29uZmlkZW5jZSBpbnRlcnZhbHMuIFRoaXMgaXMgZHVlIHRvIGhvdyBldmVyeSBpbnRlcnZhbCBiZXNpZGVzIHRoZSBpbnRlcmNlcHQgZG8gbm90IGNvbnRhaW4gMC4gIFRoaXMgaXMgYmVjYXVzZSB0aGUgc2FtcGxlIHNpemUgaXMgbGFyZ2UgZW5vdWdoIHNvIHRoYXQgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMgb2YgZXN0aW1hdGVkIGNvZWZmaWNpZW50cyBoYXZlIHN1ZmZpY2llbnRseSBnb29kIGFwcHJveGltYXRpb25zIG9mIG5vcm1hbCBkaXN0cmlidXRpb25zLgoKCiMjIENvbWJpbmluZyBSZXN1bHRzCgpGaW5hbGx5LCB3ZSBwdXQgYWxsIGluZmVyZW50aWFsIHN0YXRpc3RpY3MgaW4gYSBzaW5nbGUgdGFibGUgc28gd2UgY2FuIGNvbXBhcmUgdGhlc2UgcmVzdWx0cy4KCmBgYHtyfQprYWJsZShhcy5kYXRhLmZyYW1lKGNiaW5kKGZvcm1hdEMoY210cnhbLC0zXSw0LGZvcm1hdD0iZiIpLCBidGMuY2kuOTU9Ym9vdF9jb25mLGJ0ci5jaS45NT1ib290X2NvbmYyKSksIAogICAgICBjYXB0aW9uPSJGaW5hbCBDb21iaW5lZCBJbmZlcmVudGlhbCBTdGF0aXN0aWNzIikKYGBgCgpUaGlzIHRhYmxlIHNob3dzIHRoZSByZXN1bHRzIHNpZGUgYnkgc2lkZSBvZiB0aGUgdHdvIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFscy4gTG9va2luZyBhdCB0aGVtIHNpZGUgdG8gc2lkZSB5b3UgY2FuIHNlZSBob3cgbXVjaCBiZXR0ZXIgdGhlIGludGVydmFscyBmb3IgdGhlIHJlc2lkdWFsIGJvb3RzdHJhcCBhcmUgY29tcGFyZWQgdG8gdGhlIHJlZ3VsYXIgYm9vdHN0cmFwIGNvbmZpZGVuY2UgaW50ZXJ2YWwuCgoKYGBge3J9CmthYmxlKHJvdW5kKGNiaW5kKGJvb3Rfd2QsIGJvb3Rfd2QyKSw0KSwgY2FwdGlvbj0id2lkdGggb2YgdGhlIHR3byBib290c3RyYXAgY29uZmlkZW5jZSBpbnRlcnZhbHMiKQpgYGAKCkxvb2tpbmcgYXQgdGhpcyB0YWJsZSB5b3UgY2FuIHNlZSB0aGF0IHRoZSB3aWR0aHMgb2YgdGhlIHJlc2lkdWFsIGJvb3RzdHJhcCBhcmUgbW9yZSBjb25zaXN0ZW50IHRoYW4gdGhlIHJlZ3VsYXIgYm9vdHN0cmFwLgoKCiMgU3VtbWFyeSBhbmQgRGlzY3Vzc2lvbgoKV2UgZGlkbid0IGhhdmUgdG8gdXNlIG1hbnkgZGlmZmVyZW50IHRlY2huaXF1ZXMgc3VjaCBhcyBCb3gtQ294IHRvIHRyYW5zZm9ybSB0aGUgcmVzcG9uc2UgdmFyaWFibGVzLiBUaGlzIHdhcyBkdWUgdG8gdGhlIGFzc3VtcHRpb24gb2YgY29uc3RhbnQgdmFyaWFuY2UgYmVpbmcgbWV0LiBXZSBnb3QgcmlkIG9mIGFsbCB0aGUgdmFyaWFibGVzIHRoYXQgd291bGQgbm90IGJlIHNpZ25pZmljYW50IG9yIGhhdmUgYW55IGFzc29jaWF0aW9uIGluIGV2YWx1YXRpbmcgZ2V0dGluZyBvbiB0aGUgZ3JlZW4gaW4gcmVndWxhdGlvbiBkdWUgdG8gbXkgcGFzdCBleHBlcmllbmNlLgoKTG9va2luZyBhdCB0aGUgcmVzcG9uc2UgdmFyaWFibGUgd2UgY2FuIHNlZSBtb3N0IHZhcmlhYmxlcyBiZXNpZGVzIGZhaXJ3YXlzIGhpdCBjb250YWluIDAgaW4gdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRoZSBjb21iaW5lZCBpbmZlcmVudGlhbCBzdGF0aXN0aWNzLiBUaGlzIHNob3dzIHRoYXQgZmFpcndheXMgaGl0IGlzIHRoZSBtb3N0IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgdmFyaWFibGUgaW4gY29tcGFyaXNvbiB0byBncmVlbnMgaW4gcmVndWxhdGlvbi4KCkkgaGFkIG5vIGRyYXdiYWNrcyBvciBpbXByb3ZlbWVudHMgSSBjYW4gdGhpbmsgb2YuCgpJbiB0aGUgZnV0dXJlIEkgd2lsbCB1c2UgdG90YWwgcHJpemUgYXMgbXkgcmVzcG9uc2UgdmFyaWFibGUuIFRoaXMgaXMgYmVjYXVzZSB5b3UgY2FuIHNlZSB0aGVuIHdoYXQgc3RhdGlzdGljIGluIGdvbGYgaXMgdGhlIG1vc3QgaW1wb3J0YW50IGZhY3RvciBpbiBob3cgbXVjaCB5b3Ugd2luIGluIGdhbWVzLgoKCgoK