-A survey of NFL field goal attempts from 2005 to 2015-

A compilation of NFL specific data, with over eleven thousand field goal attempts in observation, is explored in this report. Intuitive questions of interest, the statistical significance of explanatory variables offered by the data source, and what predictive aptitude the modeling of this information enables are all covered in the report that follows.

Abstract

The field of information offered in this data file contributes to General Linear Modeling (GLM) with hopes of discovering, specifically, what factors most significantly influence the outcome of a given try and, generally, with what accuracy this causality can be assigned.

Of particular interest to the researcher was the relationship between multiple explanatory variables that may persuade or dissuade a field goal attempt.
Without question, this decision is embedded in the likelihood of either of the binary outcomes given to a field goal tray. The chess moves required of opposing teams on game-day play the balance of necessity and probability.

Ultimately, the purpose of a field goal try is to add three points to the kicking team’s score. In order to gauge the likelihood of accomplishing this feat, specific inputs offered within the data allow for sound mathematical approaches toward the discovery of what factors most significantly influence the probabilities at hand. With what accuracy this causality can be assigned is of primary importance throughout the analysis.

The purpose of this study having been revealed, the methods for achieving these ends will be explored in the ensuing section. These efforts were fruitful.
In the graphs, formulas, and broader analysis that follow, a veritable equation was derived by which the odds of a particular attempt can be assessed based on such agents as distance (in yards) of the attempt, the temperature at time of kick, and more.

Data Cleaning

library(ggplot2)
library(GGally)
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
library(RCurl) 
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✓ tibble  3.1.6     ✓ dplyr   1.0.8
## ✓ tidyr   1.2.0     ✓ stringr 1.4.0
## ✓ readr   2.1.2     ✓ forcats 0.5.1
## ✓ purrr   0.3.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x tidyr::complete() masks RCurl::complete()
## x dplyr::filter()   masks stats::filter()
## x dplyr::lag()      masks stats::lag()
nfl_kick <- read.csv("nflkick.csv")
attach(nfl_kick)

The data for this study was procured from Github.
https://raw.githubusercontent.com/statsbylopez/StatsSports/master/Data/nfl_fg.csv

Source data was utilized to extend the applications for its assessment by adding a columnar attribute for the likely percentage of an attempt per the corresponding observation. The formula for calculating this ‘Prediction_Percentage’ will be described later in the report. For preliminary disclosure, the predicted percentage is derived, per row, by the corresponding input variables weighted according to regression modeling on the eleven years (ten seasons) supervised by this data pool.

Immediate manipulation of the data, shown immediately below, transforms the object Success for purposes of regression modeling. Binary outcomes are labeled and made into factors. The first output cofirms the class change in Success.

nfl_kick$Success  = ifelse(nfl_kick$Success == 0, 'Miss','Make') # Create levels for Success Variable
nfl_kick$Success = as.factor(nfl_kick$Success)

class(nfl_kick$Success)
## [1] "factor"

The levels of Success are then confirmed.

nfl_kick$Success <- factor(nfl_kick$Success, levels =c('Miss', 'Make'))
contrasts(nfl_kick$Success)
##      Make
## Miss    0
## Make    1

The manipulation of columns, aforementioned, will reflect in the abridged view of the data arrangement below. Note, the last column of the extended field goal data is labeled ‘Prediction_Percent’.Again, the process for ascertaining the weighting of these parameters will be covered in more detail.

ext.fg.d8a <- mutate(nfl_kick, Prediction_Percent = round(exp(-106.2 - (.1046 *Distance) + (.05574 *Year)) / 
                                                   (1 + exp(-106.2 - (.1046 *Distance) + (.05574 *Year))), 4) *100)

head(ext.fg.d8a, 15)

Graphical Interpretations

Initial graphical reviews of the headed inputs provides insight into the co-relationships of these influencing components and shed light on the approach for determining what variables are most additive in the approach to estimating the outcome of a field goal attempt. A few basic statistics are presented now.

Number of kicks observed:

nrow(nfl_kick)
## [1] 11187

Discrete listing of field goal attempts (in yards):

all.dist.attempted <- sort(unique(Distance))

In the scatter plot that ensues, we explore the relationship between the score differential and distance. Of question was the tendency to attempt longer field goals when trailing as opposed to when the kicking team is ahead. The relationship seems evident. The relationship should prove negative. But the strength of their interaction was not so strong as supposed (correlation coefficient -.0513, see output after scatter).

ggplot(nfl_kick, aes(x =ScoreDiff, y =Distance)) +
  geom_point(color ='red', size =1) +
  geom_smooth(method ='lm', formula =y ~x, se =TRUE, level =.95)

cor.test(nfl_kick$ScoreDiff, nfl_kick$Distance)
## 
##  Pearson's product-moment correlation
## 
## data:  nfl_kick$ScoreDiff and nfl_kick$Distance
## t = -5.4355, df = 11185, p-value = 5.58e-08
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.06979159 -0.03282712
## sample estimates:
##         cor 
## -0.05132693

One relationships to consider is the distribution of attempted field goals relative to temperature. Here, temperature may serve as a substitute variable that acts as a partial surrogate for weather and stadium-dependent factors. A histogram to this effect is provided here.

ggplot(nfl_kick, aes(x =nfl_kick$Temp, color =nfl_kick$Success, fill =nfl_kick$Success)) +
  geom_histogram(alpha =.4)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

The existence of negative skew reveals the less frequent occurrence of extremely high temperatures. Curiously, a non-linear relationship may exist here including the inability to maintain field goal percentage (all else equal) once temperature exceeds a certain threshold. A quadratic term for temperature was tested but did not prove statistically significant.

Another lens into the possibility of a stadium-effect is captured, at least in part, by the relationship between temperature and field surfaces, denoted true and false for grass and artificial turf, respectively. Notice the similar but unequal distributions between grassed and not-grassed fields.

boxplot(nfl_kick$Temp ~nfl_kick$Grass, ylab ='Temperature in degrees F', 
        xlab ='Field Surface: F =Turf, T =Sod',
        main ='Boxplot of Temperature relative to Field Surface', 
        boxlwd =2, outlwd =2, col ='darkorange1', outpch =21, outbg ='cyan')

It is expected that kicking percentage should decrease inversely to yardage of attempted distance. A density plot of all kicks follows and then a printout of the correlation between yardage distance of attempts relative to temperature

ggplot(nfl_kick, aes(x =nfl_kick$Distance, fill =nfl_kick$Success)) +
  geom_density(alpha =.4)

cor.test(nfl_kick$Temp, nfl_kick$Distance)
## 
##  Pearson's product-moment correlation
## 
## data:  nfl_kick$Temp and nfl_kick$Distance
## t = 3.8978, df = 9126, p-value = 9.776e-05
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.02027001 0.06123177
## sample estimates:
##        cor 
## 0.04076802

Methodologies

The initial process was to establish linear strength between the most intuitive factors influencing the outcomes of field goal tries. Distance, as was shown in the early findings, seemed to have the strongest association with success, the designated column for attempt outcome.

This binary response variable was first fitted against yardage with a basic GLM and the relationship was proven significant (p-value, 2e-16).

fg.glm <- glm(nfl_kick$Success ~nfl_kick$Distance, family =binomial)

summary(fg.glm)
## 
## Call:
## glm(formula = nfl_kick$Success ~ nfl_kick$Distance, family = binomial)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.7193   0.2479   0.4086   0.6297   1.5497  
## 
## Coefficients:
##                    Estimate Std. Error z value Pr(>|z|)    
## (Intercept)        5.724620   0.137223   41.72   <2e-16 ***
## nfl_kick$Distance -0.102615   0.003135  -32.73   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 10105.0  on 11186  degrees of freedom
## Residual deviance:  8748.4  on 11185  degrees of freedom
## AIC: 8752.4
## 
## Number of Fisher Scoring iterations: 5

More inclusive logistic regression was then attempted to subset an equation to verily anticipate field goal outcomes as a function of the pertinent explanatory variables. A fuller, optimized model was rendered as follows.

fg.fuller.glm <- glm(nfl_kick$Success ~Distance + Year + 
                    Grass + Temp, family =binomial)

summary(fg.fuller.glm)
## 
## Call:
## glm(formula = nfl_kick$Success ~ Distance + Year + Grass + Temp, 
##     family = binomial)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.8171   0.2351   0.3905   0.6400   1.7264  
## 
## Coefficients:
##               Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -1.185e+02  1.935e+01  -6.123 9.20e-10 ***
## Distance    -1.095e-01  3.596e-03 -30.454  < 2e-16 ***
## Year         6.175e-02  9.636e-03   6.408 1.47e-10 ***
## GrassTRUE   -1.818e-01  6.294e-02  -2.888  0.00387 ** 
## Temp         8.386e-03  1.876e-03   4.469 7.85e-06 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 8256.5  on 9127  degrees of freedom
## Residual deviance: 7028.7  on 9123  degrees of freedom
##   (2059 observations deleted due to missingness)
## AIC: 7038.7
## 
## Number of Fisher Scoring iterations: 5

Incomplete data (NA values) in the case of temperature and overlap between this and the grass (field surface) variable prompted the decision to pare the model in such a way as to efficiently construct a predictive model (strength) that would capture the trending focus within the league to build ever more weather neutral stadiums. With this consideration, distance and year constituted an ideal model for constructing the Predicted_Percent output that allowed for generalized mapping of odds and percentage likelihoods of kicks per the data that was assessed. This model is presented here.

fg.optimal.glm <- glm(nfl_kick$Success ~Distance + Year, family =binomial)

summary(fg.optimal.glm)
## 
## Call:
## glm(formula = nfl_kick$Success ~ Distance + Year, family = binomial)
## 
## Deviance Residuals: 
##     Min       1Q   Median       3Q      Max  
## -2.7744   0.2491   0.3980   0.6431   1.5753  
## 
## Coefficients:
##               Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -1.062e+02  1.731e+01  -6.137 8.39e-10 ***
## Distance    -1.046e-01  3.171e-03 -32.973  < 2e-16 ***
## Year         5.574e-02  8.620e-03   6.467 1.00e-10 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 10105.0  on 11186  degrees of freedom
## Residual deviance:  8706.3  on 11184  degrees of freedom
## AIC: 8712.3
## 
## Number of Fisher Scoring iterations: 5

Lastly, the verity of this model was compared to the simple model with which this section started. An Analysis of Variance (ANOVA) test was conducted and it supported (p-value, 7.260e-10) the inclusion of Year in modeling a prediction for what percentage to assign a specified kick.

anova(fg.optimal.glm, fg.glm)
1 - pchisq(42.087, 2)
## [1] 7.259791e-10

Results

Pictoral Revelations

As the various regression models demonstrated, a competent model can be orchestrated with respectable accuracy in determining the likelihood of a field goal attempt, dependent upon a host of variables. Distance is the primary determinant in these odds, as the plot below makes evident. Here, the odds of field goals against the distance in yards of the kick show the relationship.

nfl.odds <- mutate(nfl_kick, Odds = exp(5.72462 - (.102615 * Distance)))

ggplot(nfl.odds, aes(x =Distance, y =Odds)) +
  geom_point(color ='deeppink3', size =3.5, pch =19)

fg.odds <- mutate(nfl_kick, Odds =exp(-1.062e2 - (1.046e-1 *Distance) + (5.57e-2 *Year)))
#head(fg.odds, 3)
ggplot(fg.odds, aes(x =Distance, y =Odds)) +
  geom_point(color ='deeppink3', size =3.5, pch =21)

A similar plot of the predicted percentages of a field goal try, as explained by the two principal variables - namely, distance and year - shows a progressive trend in accuracy every five years. This trend is showcased beneath. Note the improvement in field goal percentages across the span of the eleven years supplied by the data set.

ggplot(ext.fg.d8a, aes(x =Distance, y =Prediction_Percent, color =Year)) +
  geom_point(size =2.5, pch =21) 

Conclusions

From the years observed and the variables collected, we are able to devise a model by which to forecast an attempted field goal in the year(s) immediately following the 2015 NFL season. What was revealed, even if short its due consideration at the onset of the study, is the improvement in accuracy over the timeline in question.

As this aspect of special teams play continues to build, the chess pieces existent within the game of football will be employed with enhanced attention. The valuation of a kick, based on expected outcome, changes the mechanics of real time decisions. The strength of the model as revealed by this study prompts an even more comprehensive retention of information and subsequent analysis.

LS0tCnRpdGxlOiAiQW5hbHlzaXMgb2YgTkZMIEZpZWxkIEdvYWwgRGF0YSIKYXV0aG9yOiAiV2FsbCwgU2V0aCIKZGF0ZTogIjUvNC8yMDIyIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogZmxhdGx5CiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID1GQUxTRSkKYGBgCgojICAtQSBzdXJ2ZXkgb2YgTkZMIGZpZWxkIGdvYWwgYXR0ZW1wdHMgZnJvbSAyMDA1IHRvIDIwMTUtIHsudGFic2V0IC50YWJzZXQtcGlsbHN9CgpBIGNvbXBpbGF0aW9uIG9mIE5GTCBzcGVjaWZpYyBkYXRhLCB3aXRoIG92ZXIgZWxldmVuIHRob3VzYW5kIGZpZWxkIGdvYWwgYXR0ZW1wdHMgCmluIG9ic2VydmF0aW9uLCBpcyBleHBsb3JlZCBpbiB0aGlzIHJlcG9ydC4gIEludHVpdGl2ZSBxdWVzdGlvbnMgb2YgaW50ZXJlc3QsIHRoZSAKc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlIG9mIGV4cGxhbmF0b3J5IHZhcmlhYmxlcyBvZmZlcmVkIGJ5IHRoZSBkYXRhIHNvdXJjZSwgYW5kIAp3aGF0IHByZWRpY3RpdmUgYXB0aXR1ZGUgdGhlIG1vZGVsaW5nIG9mIHRoaXMgaW5mb3JtYXRpb24gZW5hYmxlcyBhcmUgYWxsIGNvdmVyZWQgCmluIHRoZSByZXBvcnQgdGhhdCBmb2xsb3dzLiAgCgoKIyMgIEFic3RyYWN0IAoKVGhlIGZpZWxkIG9mIGluZm9ybWF0aW9uIG9mZmVyZWQgaW4gdGhpcyBkYXRhIGZpbGUgY29udHJpYnV0ZXMgdG8gR2VuZXJhbCBMaW5lYXIgCk1vZGVsaW5nIChHTE0pIHdpdGggaG9wZXMgb2YgZGlzY292ZXJpbmcsIHNwZWNpZmljYWxseSwgd2hhdCBmYWN0b3JzIG1vc3QgCnNpZ25pZmljYW50bHkgaW5mbHVlbmNlIHRoZSBvdXRjb21lIG9mIGEgZ2l2ZW4gdHJ5IGFuZCwgZ2VuZXJhbGx5LCB3aXRoIHdoYXQgCmFjY3VyYWN5IHRoaXMgY2F1c2FsaXR5IGNhbiBiZSBhc3NpZ25lZC4gIAoKT2YgcGFydGljdWxhciBpbnRlcmVzdCB0byB0aGUgcmVzZWFyY2hlciB3YXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG11bHRpcGxlIApleHBsYW5hdG9yeSB2YXJpYWJsZXMgdGhhdCBtYXkgcGVyc3VhZGUgb3IgZGlzc3VhZGUgYSBmaWVsZCBnb2FsIGF0dGVtcHQuICAKV2l0aG91dCBxdWVzdGlvbiwgdGhpcyBkZWNpc2lvbiBpcyBlbWJlZGRlZCBpbiB0aGUgbGlrZWxpaG9vZCBvZiBlaXRoZXIgb2YgdGhlIApiaW5hcnkgb3V0Y29tZXMgZ2l2ZW4gdG8gYSBmaWVsZCBnb2FsIHRyYXkuIFRoZSBjaGVzcyBtb3ZlcyByZXF1aXJlZCBvZiBvcHBvc2luZyAKdGVhbXMgb24gZ2FtZS1kYXkgcGxheSB0aGUgYmFsYW5jZSBvZiBuZWNlc3NpdHkgYW5kIHByb2JhYmlsaXR5LiAgCgpVbHRpbWF0ZWx5LCB0aGUgcHVycG9zZSBvZiBhIGZpZWxkIGdvYWwgdHJ5IGlzIHRvIGFkZCB0aHJlZSBwb2ludHMgdG8gdGhlIApraWNraW5nIHRlYW0ncyBzY29yZS4gIEluIG9yZGVyIHRvIGdhdWdlIHRoZSBsaWtlbGlob29kIG9mIGFjY29tcGxpc2hpbmcgdGhpcyAKZmVhdCwgc3BlY2lmaWMgaW5wdXRzIG9mZmVyZWQgd2l0aGluIHRoZSBkYXRhIGFsbG93IGZvciBzb3VuZCBtYXRoZW1hdGljYWwgCmFwcHJvYWNoZXMgdG93YXJkIHRoZSBkaXNjb3Zlcnkgb2Ygd2hhdCBmYWN0b3JzIG1vc3Qgc2lnbmlmaWNhbnRseSBpbmZsdWVuY2UgCnRoZSBwcm9iYWJpbGl0aWVzIGF0IGhhbmQuICBXaXRoIHdoYXQgYWNjdXJhY3kgdGhpcyBjYXVzYWxpdHkgY2FuIGJlIGFzc2lnbmVkIGlzIApvZiBwcmltYXJ5IGltcG9ydGFuY2UgdGhyb3VnaG91dCB0aGUgYW5hbHlzaXMuICAKClRoZSBwdXJwb3NlIG9mIHRoaXMgc3R1ZHkgaGF2aW5nIGJlZW4gcmV2ZWFsZWQsIHRoZSBtZXRob2RzIGZvciBhY2hpZXZpbmcgdGhlc2UKZW5kcyB3aWxsIGJlIGV4cGxvcmVkIGluIHRoZSBlbnN1aW5nIHNlY3Rpb24uICBUaGVzZSBlZmZvcnRzIHdlcmUgZnJ1aXRmdWwuICAKSW4gdGhlIGdyYXBocywgZm9ybXVsYXMsIGFuZCBicm9hZGVyIGFuYWx5c2lzIHRoYXQgZm9sbG93LCBhIHZlcml0YWJsZSBlcXVhdGlvbiAKd2FzIGRlcml2ZWQgYnkgd2hpY2ggdGhlIG9kZHMgb2YgYSBwYXJ0aWN1bGFyIGF0dGVtcHQgY2FuIGJlIGFzc2Vzc2VkIGJhc2VkIG9uIApzdWNoIGFnZW50cyBhcyBkaXN0YW5jZSAoaW4geWFyZHMpIG9mIHRoZSBhdHRlbXB0LCB0aGUgdGVtcGVyYXR1cmUgYXQgdGltZSBvZiAKa2ljaywgYW5kIG1vcmUuICAKCgojIyBEYXRhIENsZWFuaW5nIHsuYWN0aXZlfQoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShHR2FsbHkpCmxpYnJhcnkoUkN1cmwpIApsaWJyYXJ5KHRpZHl2ZXJzZSkKCm5mbF9raWNrIDwtIHJlYWQuY3N2KCJuZmxraWNrLmNzdiIpCmF0dGFjaChuZmxfa2ljaykKYGBgCgpUaGUgZGF0YSBmb3IgdGhpcyBzdHVkeSB3YXMgcHJvY3VyZWQgZnJvbSBHaXRodWIuICAKImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9zdGF0c2J5bG9wZXovU3RhdHNTcG9ydHMvbWFzdGVyL0RhdGEvbmZsX2ZnLmNzdiIKClNvdXJjZSBkYXRhIHdhcyB1dGlsaXplZCB0byBleHRlbmQgdGhlIGFwcGxpY2F0aW9ucyBmb3IgaXRzIGFzc2Vzc21lbnQgYnkgYWRkaW5nCmEgY29sdW1uYXIgYXR0cmlidXRlIGZvciB0aGUgbGlrZWx5IHBlcmNlbnRhZ2Ugb2YgYW4gYXR0ZW1wdCBwZXIgdGhlIApjb3JyZXNwb25kaW5nIG9ic2VydmF0aW9uLiAgVGhlIGZvcm11bGEgZm9yIGNhbGN1bGF0aW5nIHRoaXMgCidQcmVkaWN0aW9uX1BlcmNlbnRhZ2UnIHdpbGwgYmUgZGVzY3JpYmVkIGxhdGVyIGluIHRoZSByZXBvcnQuICBGb3IgcHJlbGltaW5hcnkgCmRpc2Nsb3N1cmUsIHRoZSBwcmVkaWN0ZWQgcGVyY2VudGFnZSBpcyBkZXJpdmVkLCBwZXIgcm93LCBieSB0aGUgY29ycmVzcG9uZGluZyAKaW5wdXQgdmFyaWFibGVzIHdlaWdodGVkIGFjY29yZGluZyB0byByZWdyZXNzaW9uIG1vZGVsaW5nIG9uIHRoZSBlbGV2ZW4geWVhcnMgCih0ZW4gc2Vhc29ucykgc3VwZXJ2aXNlZCBieSB0aGlzIGRhdGEgcG9vbC4gIAoKSW1tZWRpYXRlIG1hbmlwdWxhdGlvbiBvZiB0aGUgZGF0YSwgc2hvd24gaW1tZWRpYXRlbHkgYmVsb3csIHRyYW5zZm9ybXMgdGhlIApvYmplY3QgU3VjY2VzcyBmb3IgcHVycG9zZXMgb2YgcmVncmVzc2lvbiBtb2RlbGluZy4gIEJpbmFyeSBvdXRjb21lcyBhcmUgbGFiZWxlZAphbmQgbWFkZSBpbnRvIGZhY3RvcnMuICBUaGUgZmlyc3Qgb3V0cHV0IGNvZmlybXMgdGhlIGNsYXNzIGNoYW5nZSBpbiBTdWNjZXNzLgpgYGB7cn0KbmZsX2tpY2skU3VjY2VzcyAgPSBpZmVsc2UobmZsX2tpY2skU3VjY2VzcyA9PSAwLCAnTWlzcycsJ01ha2UnKSAjIENyZWF0ZSBsZXZlbHMgZm9yIFN1Y2Nlc3MgVmFyaWFibGUKbmZsX2tpY2skU3VjY2VzcyA9IGFzLmZhY3RvcihuZmxfa2ljayRTdWNjZXNzKQoKY2xhc3MobmZsX2tpY2skU3VjY2VzcykKYGBgCgpUaGUgbGV2ZWxzIG9mIFN1Y2Nlc3MgYXJlIHRoZW4gY29uZmlybWVkLiAgCmBgYHtyfQpuZmxfa2ljayRTdWNjZXNzIDwtIGZhY3RvcihuZmxfa2ljayRTdWNjZXNzLCBsZXZlbHMgPWMoJ01pc3MnLCAnTWFrZScpKQpjb250cmFzdHMobmZsX2tpY2skU3VjY2VzcykKYGBgCgpUaGUgbWFuaXB1bGF0aW9uIG9mIGNvbHVtbnMsIGFmb3JlbWVudGlvbmVkLCB3aWxsIHJlZmxlY3QgaW4gdGhlIGFicmlkZ2VkIHZpZXcgCm9mIHRoZSBkYXRhIGFycmFuZ2VtZW50IGJlbG93LiAgTm90ZSwgdGhlIGxhc3QgY29sdW1uIG9mIHRoZSBleHRlbmRlZCBmaWVsZCBnb2FsCmRhdGEgaXMgbGFiZWxlZCAnUHJlZGljdGlvbl9QZXJjZW50Jy5BZ2FpbiwgdGhlIHByb2Nlc3MgZm9yIGFzY2VydGFpbmluZyB0aGUgCndlaWdodGluZyBvZiB0aGVzZSBwYXJhbWV0ZXJzIHdpbGwgYmUgY292ZXJlZCBpbiBtb3JlIGRldGFpbC4KYGBge3J9CmV4dC5mZy5kOGEgPC0gbXV0YXRlKG5mbF9raWNrLCBQcmVkaWN0aW9uX1BlcmNlbnQgPSByb3VuZChleHAoLTEwNi4yIC0gKC4xMDQ2ICpEaXN0YW5jZSkgKyAoLjA1NTc0ICpZZWFyKSkgLyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDEgKyBleHAoLTEwNi4yIC0gKC4xMDQ2ICpEaXN0YW5jZSkgKyAoLjA1NTc0ICpZZWFyKSkpLCA0KSAqMTAwKQoKaGVhZChleHQuZmcuZDhhLCAxNSkKYGBgCgojIyBHcmFwaGljYWwgSW50ZXJwcmV0YXRpb25zIHsuYWN0aXZlfQoKSW5pdGlhbCBncmFwaGljYWwgcmV2aWV3cyBvZiB0aGUgaGVhZGVkIGlucHV0cyBwcm92aWRlcyBpbnNpZ2h0IGludG8gdGhlIApjby1yZWxhdGlvbnNoaXBzIG9mIHRoZXNlIGluZmx1ZW5jaW5nIGNvbXBvbmVudHMgYW5kIHNoZWQgbGlnaHQgb24gdGhlIGFwcHJvYWNoCmZvciBkZXRlcm1pbmluZyB3aGF0IHZhcmlhYmxlcyBhcmUgbW9zdCBhZGRpdGl2ZSBpbiB0aGUgYXBwcm9hY2ggdG8gZXN0aW1hdGluZyAKdGhlIG91dGNvbWUgb2YgYSBmaWVsZCBnb2FsIGF0dGVtcHQuICBBIGZldyBiYXNpYyBzdGF0aXN0aWNzIGFyZSBwcmVzZW50ZWQgbm93LgoKTnVtYmVyIG9mIGtpY2tzIG9ic2VydmVkOgpgYGB7cn0KbnJvdyhuZmxfa2ljaykKYGBgCgpEaXNjcmV0ZSBsaXN0aW5nIG9mIGZpZWxkIGdvYWwgYXR0ZW1wdHMgKGluIHlhcmRzKToKYGBge3J9CmFsbC5kaXN0LmF0dGVtcHRlZCA8LSBzb3J0KHVuaXF1ZShEaXN0YW5jZSkpCmBgYAoKSW4gdGhlIHNjYXR0ZXIgcGxvdCB0aGF0IGVuc3Vlcywgd2UgZXhwbG9yZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHNjb3JlIApkaWZmZXJlbnRpYWwgYW5kIGRpc3RhbmNlLiBPZiBxdWVzdGlvbiB3YXMgdGhlIHRlbmRlbmN5IHRvIGF0dGVtcHQgbG9uZ2VyIGZpZWxkIApnb2FscyB3aGVuIHRyYWlsaW5nIGFzIG9wcG9zZWQgdG8gd2hlbiB0aGUga2lja2luZyB0ZWFtIGlzIGFoZWFkLiAgVGhlIApyZWxhdGlvbnNoaXAgc2VlbXMgZXZpZGVudC4gIFRoZSByZWxhdGlvbnNoaXAgc2hvdWxkIHByb3ZlIG5lZ2F0aXZlLiBCdXQgdGhlIApzdHJlbmd0aCBvZiB0aGVpciBpbnRlcmFjdGlvbiB3YXMgbm90IHNvIHN0cm9uZyBhcyBzdXBwb3NlZCAoY29ycmVsYXRpb24gCmNvZWZmaWNpZW50IC0uMDUxMywgc2VlIG91dHB1dCBhZnRlciBzY2F0dGVyKS4KYGBge3J9CmdncGxvdChuZmxfa2ljaywgYWVzKHggPVNjb3JlRGlmZiwgeSA9RGlzdGFuY2UpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9J3JlZCcsIHNpemUgPTEpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSdsbScsIGZvcm11bGEgPXkgfngsIHNlID1UUlVFLCBsZXZlbCA9Ljk1KQpgYGAKCmBgYHtyfQpjb3IudGVzdChuZmxfa2ljayRTY29yZURpZmYsIG5mbF9raWNrJERpc3RhbmNlKQpgYGAKCk9uZSByZWxhdGlvbnNoaXBzIHRvIGNvbnNpZGVyIGlzIHRoZSBkaXN0cmlidXRpb24gb2YgYXR0ZW1wdGVkIGZpZWxkIGdvYWxzIApyZWxhdGl2ZSB0byB0ZW1wZXJhdHVyZS4gIEhlcmUsIHRlbXBlcmF0dXJlIG1heSBzZXJ2ZSBhcyBhIHN1YnN0aXR1dGUgdmFyaWFibGUgCnRoYXQgYWN0cyBhcyBhIHBhcnRpYWwgc3Vycm9nYXRlIGZvciB3ZWF0aGVyIGFuZCBzdGFkaXVtLWRlcGVuZGVudCBmYWN0b3JzLiBBIApoaXN0b2dyYW0gdG8gdGhpcyBlZmZlY3QgaXMgcHJvdmlkZWQgaGVyZS4gIApgYGB7cn0KZ2dwbG90KG5mbF9raWNrLCBhZXMoeCA9bmZsX2tpY2skVGVtcCwgY29sb3IgPW5mbF9raWNrJFN1Y2Nlc3MsIGZpbGwgPW5mbF9raWNrJFN1Y2Nlc3MpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWxwaGEgPS40KQpgYGAKVGhlIGV4aXN0ZW5jZSBvZiBuZWdhdGl2ZSBza2V3IHJldmVhbHMgdGhlIGxlc3MgZnJlcXVlbnQgb2NjdXJyZW5jZSBvZiBleHRyZW1lbHkgCmhpZ2ggdGVtcGVyYXR1cmVzLiAgQ3VyaW91c2x5LCBhIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwIG1heSBleGlzdCBoZXJlIAppbmNsdWRpbmcgdGhlIGluYWJpbGl0eSB0byBtYWludGFpbiBmaWVsZCBnb2FsIHBlcmNlbnRhZ2UgKGFsbCBlbHNlIGVxdWFsKSBvbmNlIAp0ZW1wZXJhdHVyZSBleGNlZWRzIGEgY2VydGFpbiB0aHJlc2hvbGQuICBBIHF1YWRyYXRpYyB0ZXJtIGZvciB0ZW1wZXJhdHVyZSB3YXMgCnRlc3RlZCBidXQgZGlkIG5vdCBwcm92ZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiAgCgpBbm90aGVyIGxlbnMgaW50byB0aGUgcG9zc2liaWxpdHkgb2YgYSBzdGFkaXVtLWVmZmVjdCBpcyBjYXB0dXJlZCwgYXQgbGVhc3QgaW4KcGFydCwgYnkgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRlbXBlcmF0dXJlIGFuZCBmaWVsZCBzdXJmYWNlcywgZGVub3RlZCB0cnVlIAphbmQgZmFsc2UgZm9yIGdyYXNzIGFuZCBhcnRpZmljaWFsIHR1cmYsIHJlc3BlY3RpdmVseS4gIE5vdGljZSB0aGUgc2ltaWxhciBidXQgCnVuZXF1YWwgZGlzdHJpYnV0aW9ucyBiZXR3ZWVuIGdyYXNzZWQgYW5kIG5vdC1ncmFzc2VkIGZpZWxkcy4gIApgYGB7cn0KYm94cGxvdChuZmxfa2ljayRUZW1wIH5uZmxfa2ljayRHcmFzcywgeWxhYiA9J1RlbXBlcmF0dXJlIGluIGRlZ3JlZXMgRicsIAogICAgICAgIHhsYWIgPSdGaWVsZCBTdXJmYWNlOiBGID1UdXJmLCBUID1Tb2QnLAogICAgICAgIG1haW4gPSdCb3hwbG90IG9mIFRlbXBlcmF0dXJlIHJlbGF0aXZlIHRvIEZpZWxkIFN1cmZhY2UnLCAKICAgICAgICBib3hsd2QgPTIsIG91dGx3ZCA9MiwgY29sID0nZGFya29yYW5nZTEnLCBvdXRwY2ggPTIxLCBvdXRiZyA9J2N5YW4nKQpgYGAKCkl0IGlzIGV4cGVjdGVkIHRoYXQga2lja2luZyBwZXJjZW50YWdlIHNob3VsZCBkZWNyZWFzZSBpbnZlcnNlbHkgdG8geWFyZGFnZSBvZiAKYXR0ZW1wdGVkIGRpc3RhbmNlLiAgQSBkZW5zaXR5IHBsb3Qgb2YgYWxsIGtpY2tzIGZvbGxvd3MgYW5kIHRoZW4gYSBwcmludG91dCBvZiAKdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4geWFyZGFnZSBkaXN0YW5jZSBvZiBhdHRlbXB0cyByZWxhdGl2ZSB0byB0ZW1wZXJhdHVyZQpgYGB7cn0KZ2dwbG90KG5mbF9raWNrLCBhZXMoeCA9bmZsX2tpY2skRGlzdGFuY2UsIGZpbGwgPW5mbF9raWNrJFN1Y2Nlc3MpKSArCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0uNCkKYGBgCgpgYGB7cn0KY29yLnRlc3QobmZsX2tpY2skVGVtcCwgbmZsX2tpY2skRGlzdGFuY2UpCmBgYAoKCiMjIE1ldGhvZG9sb2dpZXMgey5hY3RpdmV9CgpUaGUgaW5pdGlhbCBwcm9jZXNzIHdhcyB0byBlc3RhYmxpc2ggbGluZWFyIHN0cmVuZ3RoIGJldHdlZW4gdGhlIG1vc3QgaW50dWl0aXZlCmZhY3RvcnMgaW5mbHVlbmNpbmcgdGhlIG91dGNvbWVzIG9mIGZpZWxkIGdvYWwgdHJpZXMuICBEaXN0YW5jZSwgYXMgd2FzIHNob3duCmluIHRoZSBlYXJseSBmaW5kaW5ncywgc2VlbWVkIHRvIGhhdmUgdGhlIHN0cm9uZ2VzdCBhc3NvY2lhdGlvbiB3aXRoIHN1Y2Nlc3MsCnRoZSBkZXNpZ25hdGVkIGNvbHVtbiBmb3IgYXR0ZW1wdCBvdXRjb21lLiAgCgpUaGlzIGJpbmFyeSByZXNwb25zZSB2YXJpYWJsZSB3YXMgZmlyc3QgZml0dGVkIGFnYWluc3QgeWFyZGFnZSB3aXRoIGEgYmFzaWMgCkdMTSBhbmQgdGhlIHJlbGF0aW9uc2hpcCB3YXMgcHJvdmVuIHNpZ25pZmljYW50IChwLXZhbHVlLCAyZS0xNikuCmBgYHtyfQpmZy5nbG0gPC0gZ2xtKG5mbF9raWNrJFN1Y2Nlc3Mgfm5mbF9raWNrJERpc3RhbmNlLCBmYW1pbHkgPWJpbm9taWFsKQoKc3VtbWFyeShmZy5nbG0pCmBgYAoKTW9yZSBpbmNsdXNpdmUgbG9naXN0aWMgcmVncmVzc2lvbiB3YXMgdGhlbiBhdHRlbXB0ZWQgdG8gc3Vic2V0IGFuIGVxdWF0aW9uIHRvCnZlcmlseSBhbnRpY2lwYXRlIGZpZWxkIGdvYWwgb3V0Y29tZXMgYXMgYSBmdW5jdGlvbiBvZiB0aGUgcGVydGluZW50IGV4cGxhbmF0b3J5IAp2YXJpYWJsZXMuICBBIGZ1bGxlciwgb3B0aW1pemVkIG1vZGVsIHdhcyByZW5kZXJlZCBhcyBmb2xsb3dzLiAgCmBgYHtyfQpmZy5mdWxsZXIuZ2xtIDwtIGdsbShuZmxfa2ljayRTdWNjZXNzIH5EaXN0YW5jZSArIFllYXIgKyAKICAgICAgICAgICAgICAgICAgICBHcmFzcyArIFRlbXAsIGZhbWlseSA9Ymlub21pYWwpCgpzdW1tYXJ5KGZnLmZ1bGxlci5nbG0pCmBgYAoKSW5jb21wbGV0ZSBkYXRhIChOQSB2YWx1ZXMpIGluIHRoZSBjYXNlIG9mIHRlbXBlcmF0dXJlIGFuZCBvdmVybGFwIGJldHdlZW4gdGhpcyAKYW5kIHRoZSBncmFzcyAoZmllbGQgc3VyZmFjZSkgdmFyaWFibGUgcHJvbXB0ZWQgdGhlIGRlY2lzaW9uIHRvIHBhcmUgdGhlIG1vZGVsCmluIHN1Y2ggYSB3YXkgYXMgdG8gZWZmaWNpZW50bHkgY29uc3RydWN0IGEgcHJlZGljdGl2ZSBtb2RlbCAoc3RyZW5ndGgpIHRoYXQgCndvdWxkIGNhcHR1cmUgdGhlIHRyZW5kaW5nIGZvY3VzIHdpdGhpbiB0aGUgbGVhZ3VlIHRvIGJ1aWxkIGV2ZXIgbW9yZSB3ZWF0aGVyCm5ldXRyYWwgc3RhZGl1bXMuICBXaXRoIHRoaXMgY29uc2lkZXJhdGlvbiwgZGlzdGFuY2UgYW5kIHllYXIgY29uc3RpdHV0ZWQgYW4KaWRlYWwgbW9kZWwgZm9yIGNvbnN0cnVjdGluZyB0aGUgUHJlZGljdGVkX1BlcmNlbnQgb3V0cHV0IHRoYXQgYWxsb3dlZCBmb3IgCmdlbmVyYWxpemVkIG1hcHBpbmcgb2Ygb2RkcyBhbmQgcGVyY2VudGFnZSBsaWtlbGlob29kcyBvZiBraWNrcyBwZXIgdGhlIGRhdGEKdGhhdCB3YXMgYXNzZXNzZWQuICBUaGlzIG1vZGVsIGlzIHByZXNlbnRlZCBoZXJlLgpgYGB7cn0KZmcub3B0aW1hbC5nbG0gPC0gZ2xtKG5mbF9raWNrJFN1Y2Nlc3MgfkRpc3RhbmNlICsgWWVhciwgZmFtaWx5ID1iaW5vbWlhbCkKCnN1bW1hcnkoZmcub3B0aW1hbC5nbG0pCmBgYAoKTGFzdGx5LCB0aGUgdmVyaXR5IG9mIHRoaXMgbW9kZWwgd2FzIGNvbXBhcmVkIHRvIHRoZSBzaW1wbGUgbW9kZWwgd2l0aCB3aGljaCAKdGhpcyBzZWN0aW9uIHN0YXJ0ZWQuICBBbiBBbmFseXNpcyBvZiBWYXJpYW5jZSAoQU5PVkEpIHRlc3Qgd2FzIGNvbmR1Y3RlZCBhbmQKaXQgc3VwcG9ydGVkIChwLXZhbHVlLCA3LjI2MGUtMTApIHRoZSBpbmNsdXNpb24gb2YgWWVhciBpbiBtb2RlbGluZyBhIHByZWRpY3Rpb24gCmZvciB3aGF0IHBlcmNlbnRhZ2UgdG8gYXNzaWduIGEgc3BlY2lmaWVkIGtpY2suICAKYGBge3J9CmFub3ZhKGZnLm9wdGltYWwuZ2xtLCBmZy5nbG0pCmBgYAoKYGBge3J9CjEgLSBwY2hpc3EoNDIuMDg3LCAyKQpgYGAKCiMjIFJlc3VsdHMgey5hY3RpdmV9CgpQaWN0b3JhbCBSZXZlbGF0aW9ucwogIApBcyB0aGUgdmFyaW91cyByZWdyZXNzaW9uIG1vZGVscyBkZW1vbnN0cmF0ZWQsIGEgY29tcGV0ZW50IG1vZGVsIGNhbiBiZSBvcmNoZXN0cmF0ZWQgd2l0aCByZXNwZWN0YWJsZSBhY2N1cmFjeSBpbiBkZXRlcm1pbmluZyB0aGUgbGlrZWxpaG9vZCBvZiBhIGZpZWxkIGdvYWwgYXR0ZW1wdCwgZGVwZW5kZW50IHVwb24gYSBob3N0IG9mIHZhcmlhYmxlcy4gIERpc3RhbmNlIGlzIHRoZSBwcmltYXJ5IGRldGVybWluYW50IGluIHRoZXNlIG9kZHMsIGFzIHRoZSBwbG90IGJlbG93IG1ha2VzIGV2aWRlbnQuICBIZXJlLCB0aGUgb2RkcyBvZiBmaWVsZCBnb2FscyBhZ2FpbnN0IHRoZSBkaXN0YW5jZSBpbiB5YXJkcyBvZiB0aGUga2ljayBzaG93IHRoZSByZWxhdGlvbnNoaXAuCmBgYHtyfQpuZmwub2RkcyA8LSBtdXRhdGUobmZsX2tpY2ssIE9kZHMgPSBleHAoNS43MjQ2MiAtICguMTAyNjE1ICogRGlzdGFuY2UpKSkKCmdncGxvdChuZmwub2RkcywgYWVzKHggPURpc3RhbmNlLCB5ID1PZGRzKSkgKwogIGdlb21fcG9pbnQoY29sb3IgPSdkZWVwcGluazMnLCBzaXplID0zLjUsIHBjaCA9MTkpCmBgYAoKYGBge3J9CmZnLm9kZHMgPC0gbXV0YXRlKG5mbF9raWNrLCBPZGRzID1leHAoLTEuMDYyZTIgLSAoMS4wNDZlLTEgKkRpc3RhbmNlKSArICg1LjU3ZS0yICpZZWFyKSkpCiNoZWFkKGZnLm9kZHMsIDMpCmBgYAoKYGBge3J9CmdncGxvdChmZy5vZGRzLCBhZXMoeCA9RGlzdGFuY2UsIHkgPU9kZHMpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9J2RlZXBwaW5rMycsIHNpemUgPTMuNSwgcGNoID0yMSkKYGBgCgpBIHNpbWlsYXIgcGxvdCBvZiB0aGUgcHJlZGljdGVkIHBlcmNlbnRhZ2VzIG9mIGEgZmllbGQgZ29hbCB0cnksIGFzIGV4cGxhaW5lZCBieQp0aGUgdHdvIHByaW5jaXBhbCB2YXJpYWJsZXMgLSBuYW1lbHksIGRpc3RhbmNlIGFuZCB5ZWFyIC0gc2hvd3MgYSBwcm9ncmVzc2l2ZSAKdHJlbmQgaW4gYWNjdXJhY3kgZXZlcnkgZml2ZSB5ZWFycy4gIFRoaXMgdHJlbmQgaXMgc2hvd2Nhc2VkIGJlbmVhdGguICBOb3RlIHRoZSAKaW1wcm92ZW1lbnQgaW4gZmllbGQgZ29hbCBwZXJjZW50YWdlcyBhY3Jvc3MgdGhlIHNwYW4gb2YgdGhlIGVsZXZlbiB5ZWFycyAKc3VwcGxpZWQgYnkgdGhlIGRhdGEgc2V0LgpgYGB7cn0KZ2dwbG90KGV4dC5mZy5kOGEsIGFlcyh4ID1EaXN0YW5jZSwgeSA9UHJlZGljdGlvbl9QZXJjZW50LCBjb2xvciA9WWVhcikpICsKICBnZW9tX3BvaW50KHNpemUgPTIuNSwgcGNoID0yMSkgCmBgYAoKQ29uY2x1c2lvbnMKCkZyb20gdGhlIHllYXJzIG9ic2VydmVkIGFuZCB0aGUgdmFyaWFibGVzIGNvbGxlY3RlZCwgd2UgYXJlIGFibGUgdG8gZGV2aXNlIGEgbW9kZWwgYnkgd2hpY2ggdG8gZm9yZWNhc3QgYW4gYXR0ZW1wdGVkIGZpZWxkIGdvYWwgaW4gdGhlIHllYXIocykgaW1tZWRpYXRlbHkgZm9sbG93aW5nIHRoZSAyMDE1IE5GTCBzZWFzb24uIFdoYXQgd2FzIHJldmVhbGVkLCBldmVuIGlmIHNob3J0IGl0cyBkdWUgY29uc2lkZXJhdGlvbiBhdCB0aGUgb25zZXQgb2YgdGhlIHN0dWR5LCBpcyB0aGUgaW1wcm92ZW1lbnQgaW4gYWNjdXJhY3kgb3ZlciB0aGUgdGltZWxpbmUgaW4gcXVlc3Rpb24uICAKCkFzIHRoaXMgYXNwZWN0IG9mIHNwZWNpYWwgdGVhbXMgcGxheSBjb250aW51ZXMgdG8gYnVpbGQsIHRoZSBjaGVzcyBwaWVjZXMgZXhpc3RlbnQgd2l0aGluIHRoZSBnYW1lIG9mIGZvb3RiYWxsIHdpbGwgYmUgZW1wbG95ZWQgd2l0aCBlbmhhbmNlZCBhdHRlbnRpb24uICBUaGUgdmFsdWF0aW9uIG9mIGEga2ljaywgYmFzZWQgb24gZXhwZWN0ZWQgb3V0Y29tZSwgY2hhbmdlcyB0aGUgbWVjaGFuaWNzIG9mIHJlYWwgdGltZSBkZWNpc2lvbnMuICBUaGUgc3RyZW5ndGggb2YgdGhlIG1vZGVsIGFzIHJldmVhbGVkIGJ5IHRoaXMgc3R1ZHkgcHJvbXB0cyBhbiBldmVuIG1vcmUgY29tcHJlaGVuc2l2ZSByZXRlbnRpb24gb2YgaW5mb3JtYXRpb24gYW5kIHN1YnNlcXVlbnQgYW5hbHlzaXMuICAKCgo=