Loading the packages:
# Loading the tidyverse package
library(tidyverse)
Reading in the NFL drives data from github
# Read in the nfl drive data
drives <- read.csv("https://raw.githubusercontent.com/Shammalamala/STA4504/refs/heads/main/data/ch1/nfl%20drives.csv")
# Looking at the different ways drives can end
unique(drives$drive_end)
## [1] "Field Goal" "Turnover" "Touchdown" "Punt"
We will be focusing on the variable drive_end
There are 4 ways in the data that a touchdown can end: Touchdown,
Field Goal, Punt, Turnover
Summary Statistics
Let’s start by getting the needed statistics from the sample: \(y\), \(n\), and \(\hat{\pi}\)
# total touchdowns
td_total <- sum(drives$drive_end == "Touchdown")
# sample size
n <- nrow(drives)
# Sample proportion
td_prop <- mean(drives$drive_end == "Touchdown")
c('y' = td_total, 'n' = n, 'pi_hat' = td_prop)
## y n pi_hat
## 300.00 1250.00 0.24
Confidence Intervals for a proportion
If we reject our null hypothesis, we often followup with a confidence
interval to narrow down what \(\pi\)
could be.
We’ll look at 3 different intervals:
Wald interval - the most common interval
Score interval - Equivalent to the score test
Agresti-Coull interval - Tends to work better than the previous
two for smaller samples when the sample proportion is close to 0 or
1
We’ll be using a 95% confidence level for our examples, but these
work for any chosen level!
Wald Interval
\[\hat{\pi} \pm z_{\alpha/2}
\sqrt{\frac{\hat{\pi}(1-\hat{\pi})}{n}}\]
# Start by finding the critical value of a 95% CI:
z95 <- qnorm(1 - 0.05/2)
wald_se <- sqrt(td_prop*(1-td_prop)/n)
# Next the confidence interval!
wald_ci_td <-
c(
lower = td_prop - z95*wald_se,
upper = td_prop + z95*wald_se
)
wald_ci_td |> signif(digits = 3)
## lower upper
## 0.216 0.264
Using a Wald confidence interval, we can be 95% confident that
between 21.6% to 26.4% of all NFL drives end in touchdowns.
Score CI
How do we calculate a Score confidence interval?
We find the values of \(\pi_0\) that
would cause us to not reject the null hypothesis. The
easiest way to find that is find the values of \(\pi_0\) that give a test stat less than or
equal to our critical value we found earlier!
score_df <-
tibble(
pi0 = seq(0, 1, by = 0.001), # Create a range of pi_0 values to test
se0 = sqrt(pi0*(1-pi0)/n), # Calculating the standard errors for the different pi0
z = (td_prop - pi0)/se0 # Finding the Score test stat for the various pi0
)
score_df
## # A tibble: 1,001 × 3
## pi0 se0 z
## <dbl> <dbl> <dbl>
## 1 0 0 Inf
## 2 0.001 0.000894 267.
## 3 0.002 0.00126 188.
## 4 0.003 0.00155 153.
## 5 0.004 0.00179 132.
## 6 0.005 0.00199 118.
## 7 0.006 0.00218 107.
## 8 0.007 0.00236 98.8
## 9 0.008 0.00252 92.1
## 10 0.009 0.00267 86.5
## # ℹ 991 more rows
# Next we want to find the values of pi0 that have a test stat below z95
score_df |>
filter(abs(z) <= z95) |>
summarize(
lower = min(pi0),
upper = max(pi0)
)
## # A tibble: 1 × 2
## lower upper
## <dbl> <dbl>
## 1 0.218 0.264
When rounding to 3 decimal places, we get a very similar confidence
interval to the Wald interval earlier!
There is also a formula we can use in place of conducting a grid
search:
\[\frac{y +\left(z^*\right)^2/2}{n +
\left(z^*\right)^2} \pm \frac{z^*}{n + \left(z^*\right)^2}
\sqrt{\frac{y(n - y)}{n} + \frac{\left(z^*\right)^2}{4}}\]
where \(y\) is the count, not
proportion
# First, find the "statistic"
score_stat <- (td_total + z95^2/2)/(n + z95^2)
# Next find the standard error
score_se <- sqrt(td_total *(n - td_total)/n + z95^2/4)
# Then margin of error
me_formula <- z95/(n + z95^2) * score_se
# Then interval:
tribble(
~'result', ~'value',
'y', td_total,
'n', n,
'score stat', score_stat,
'Score SE', score_se,
'Score ME', me_formula,
'lower bound', score_stat - me_formula,
'upper bound', score_stat + me_formula
) |>
mutate(
value = round(value, 3)
)
## # A tibble: 7 × 2
## result value
## <chr> <dbl>
## 1 y 300
## 2 n 1250
## 3 score stat 0.241
## 4 Score SE 15.1
## 5 Score ME 0.024
## 6 lower bound 0.217
## 7 upper bound 0.264
Our two answers are slight different due to rounding and only
searching to the nearest 0.001. If we used enough digits in our
“search”, the answer will be identical!
Agresti-Coull
The Agresti-Coull (AC) interval ‘mixes’ the score and Wald intervals
together.
How? It keeps the same general form of the Wald interval:
\[\hat{\pi} \pm z_{\alpha/2}
\sqrt{\frac{\hat{\pi}(1-\hat{\pi})}{n}}\]
but it updates \(y\) and \(n\):
\[\tilde{y} = y + (z^*)^2/2 \\ \tilde{n} =
n + (z^*)^2 \\ \tilde{\pi} = \tilde{y} / \tilde{n}\]
# Calculating the 'new' point estimate
y_tilde <- td_total + (z95^2)/2
n_tilde <- n + z95^2
pi_tilde <- y_tilde / n_tilde
# The standard error
AG_se <- sqrt(pi_tilde * (1-pi_tilde) / n)
# Lower and upper bounds
AG_ci <-
c('lower' = pi_tilde - z95 * AG_se,
'upper' = pi_tilde + z95 * AG_se
)
AG_ci
## lower upper
## 0.2170939 0.2644992
Just like the score and Wald interval, it’s very, very similar!
Built-in Functions
If you want one function to rule them all, we can use the
binom.confint() function in the binom
package.
It works similarly to prop.test(), in that we need to
specify x and n. However, we can also specify
methods as a way to tell it which method to build the
confidence interval:
- ‘asymptotic’ = Wald
- ‘wilson’ = score
- ‘ac’ = Agresti-Coull
library(binom)
binom.confint(
x = td_total,
n = n,
conf.level = 0.95,
methods = 'asymptotic'
)
## method x n mean lower upper
## 1 asymptotic 300 1250 0.24 0.2163242 0.2636758
binom.confint(
x = td_total,
n = n,
conf.level = 0.95,
methods = 'wilson'
)
## method x n mean lower upper
## 1 wilson 300 1250 0.24 0.2171436 0.2644495
binom.confint(
x = td_total,
n = n,
conf.level = 0.95,
methods = 'ac'
)
## method x n mean lower upper
## 1 agresti-coull 300 1250 0.24 0.2171302 0.2644629
You can also give it all three methods in one function by giving
methods a vector:
binom.confint(
x = td_total,
n = n,
conf.level = 0.95,
methods = c('asymptotic', 'wilson', 'ac')
)
## method x n mean lower upper
## 1 agresti-coull 300 1250 0.24 0.2171302 0.2644629
## 2 asymptotic 300 1250 0.24 0.2163242 0.2636758
## 3 wilson 300 1250 0.24 0.2171436 0.2644495
LS0tDQp0aXRsZTogIkNvbmZpZGVuY2UgSW50ZXJ2YWxzIGZvciBhIFNpbmdsZSBQcm9wb3J0aW9uIg0KYXV0aG9yOiAiQ2hhcHRlciAxIg0KZGF0ZTogIlNUQSA0NTA0Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGZpZ193aWR0aDogNg0KICAgIGZpZ19oZWlnaHQ6IDYNCiAgICBmaWdfY2FwdGlvbjogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICAgIHRoZW1lOiBsdW1lbg0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ24gPSAiY2VudGVyIikNCmBgYA0KDQpMb2FkaW5nIHRoZSBwYWNrYWdlczoNCg0KYGBge3IgcGFja2FnZXMsIG1lc3NhZ2UgPSBGLCB3YXJuaW5nID0gRn0NCiMgTG9hZGluZyB0aGUgdGlkeXZlcnNlIHBhY2thZ2UNCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQoNClJlYWRpbmcgaW4gdGhlIE5GTCBkcml2ZXMgZGF0YSBmcm9tIGdpdGh1Yg0KDQpgYGB7ciBkYXRhfQ0KIyBSZWFkIGluIHRoZSBuZmwgZHJpdmUgZGF0YQ0KZHJpdmVzIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vU2hhbW1hbGFtYWxhL1NUQTQ1MDQvcmVmcy9oZWFkcy9tYWluL2RhdGEvY2gxL25mbCUyMGRyaXZlcy5jc3YiKQ0KDQojIExvb2tpbmcgYXQgdGhlIGRpZmZlcmVudCB3YXlzIGRyaXZlcyBjYW4gZW5kDQp1bmlxdWUoZHJpdmVzJGRyaXZlX2VuZCkNCg0KYGBgDQoNCldlIHdpbGwgYmUgZm9jdXNpbmcgb24gdGhlIHZhcmlhYmxlIGBkcml2ZV9lbmRgDQoNClRoZXJlIGFyZSA0IHdheXMgaW4gdGhlIGRhdGEgdGhhdCBhIHRvdWNoZG93biBjYW4gZW5kOiBUb3VjaGRvd24sIEZpZWxkIEdvYWwsIFB1bnQsIFR1cm5vdmVyDQoNCg0KIyMgU3VtbWFyeSBTdGF0aXN0aWNzDQoNCkxldCdzIHN0YXJ0IGJ5IGdldHRpbmcgdGhlIG5lZWRlZCBzdGF0aXN0aWNzIGZyb20gdGhlIHNhbXBsZTogJHkkLCAkbiQsIGFuZCAkXGhhdHtccGl9JA0KDQpgYGB7ciB0ZF9wcm9wfQ0KIyB0b3RhbCB0b3VjaGRvd25zDQp0ZF90b3RhbCA8LSBzdW0oZHJpdmVzJGRyaXZlX2VuZCA9PSAiVG91Y2hkb3duIikNCg0KIyBzYW1wbGUgc2l6ZQ0KbiA8LSBucm93KGRyaXZlcykNCg0KIyBTYW1wbGUgcHJvcG9ydGlvbg0KdGRfcHJvcCA8LSBtZWFuKGRyaXZlcyRkcml2ZV9lbmQgPT0gIlRvdWNoZG93biIpDQoNCmMoJ3knID0gdGRfdG90YWwsICduJyA9IG4sICdwaV9oYXQnID0gdGRfcHJvcCkNCmBgYA0KDQoNCiMjIENvbmZpZGVuY2UgSW50ZXJ2YWxzIGZvciBhIHByb3BvcnRpb24NCg0KSWYgd2UgcmVqZWN0IG91ciBudWxsIGh5cG90aGVzaXMsIHdlIG9mdGVuIGZvbGxvd3VwIHdpdGggYSBjb25maWRlbmNlIGludGVydmFsIHRvIG5hcnJvdyBkb3duIHdoYXQgJFxwaSQgY291bGQgYmUuDQoNCldlJ2xsIGxvb2sgYXQgMyBkaWZmZXJlbnQgaW50ZXJ2YWxzOg0KDQoxKSBXYWxkIGludGVydmFsIC0gdGhlIG1vc3QgY29tbW9uIGludGVydmFsDQoNCjIpIFNjb3JlIGludGVydmFsIC0gRXF1aXZhbGVudCB0byB0aGUgc2NvcmUgdGVzdA0KDQozKSBBZ3Jlc3RpLUNvdWxsIGludGVydmFsIC0gVGVuZHMgdG8gd29yayBiZXR0ZXIgdGhhbiB0aGUgcHJldmlvdXMgdHdvIGZvciBzbWFsbGVyIHNhbXBsZXMgd2hlbiB0aGUgc2FtcGxlIHByb3BvcnRpb24gaXMgY2xvc2UgdG8gMCBvciAxDQoNCg0KV2UnbGwgYmUgdXNpbmcgYSA5NSUgY29uZmlkZW5jZSBsZXZlbCBmb3Igb3VyIGV4YW1wbGVzLCBidXQgdGhlc2Ugd29yayBmb3IgYW55IGNob3NlbiBsZXZlbCENCg0KDQoNCg0KIyMjIFdhbGQgSW50ZXJ2YWwNCg0KJCRcaGF0e1xwaX0gXHBtIHpfe1xhbHBoYS8yfSBcc3FydHtcZnJhY3tcaGF0e1xwaX0oMS1caGF0e1xwaX0pfXtufX0kJA0KDQoNCg0KYGBge3Igd2FsZF9DSX0NCiMgU3RhcnQgYnkgZmluZGluZyB0aGUgY3JpdGljYWwgdmFsdWUgb2YgYSA5NSUgQ0k6DQp6OTUgPC0gcW5vcm0oMSAtIDAuMDUvMikNCg0Kd2FsZF9zZSA8LSBzcXJ0KHRkX3Byb3AqKDEtdGRfcHJvcCkvbikNCg0KIyBOZXh0IHRoZSBjb25maWRlbmNlIGludGVydmFsIQ0Kd2FsZF9jaV90ZCA8LSANCiAgYygNCiAgICBsb3dlciA9IHRkX3Byb3AgLSB6OTUqd2FsZF9zZSwNCiAgICB1cHBlciA9IHRkX3Byb3AgKyB6OTUqd2FsZF9zZQ0KICApDQoNCndhbGRfY2lfdGQgfD4gc2lnbmlmKGRpZ2l0cyA9IDMpDQpgYGANCg0KVXNpbmcgYSBXYWxkIGNvbmZpZGVuY2UgaW50ZXJ2YWwsIHdlIGNhbiBiZSA5NSUgY29uZmlkZW50IHRoYXQgYmV0d2VlbiAyMS42JSB0byAyNi40JSBvZiBhbGwgTkZMIGRyaXZlcyBlbmQgaW4gdG91Y2hkb3ducy4NCg0KIyMjIFNjb3JlIENJDQoNCkhvdyBkbyB3ZSBjYWxjdWxhdGUgYSBTY29yZSBjb25maWRlbmNlIGludGVydmFsPw0KDQpXZSBmaW5kIHRoZSB2YWx1ZXMgb2YgJFxwaV8wJCB0aGF0IHdvdWxkIGNhdXNlIHVzIHRvICoqbm90KiogcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMuIFRoZSBlYXNpZXN0IHdheSB0byBmaW5kIHRoYXQgaXMgZmluZCB0aGUgdmFsdWVzIG9mICRccGlfMCQgdGhhdCBnaXZlIGEgdGVzdCBzdGF0IGxlc3MgdGhhbiBvciBlcXVhbCB0byBvdXIgY3JpdGljYWwgdmFsdWUgd2UgZm91bmQgZWFybGllciENCg0KYGBge3Igc2NvcmVfY2l9DQpzY29yZV9kZiA8LSANCiAgdGliYmxlKA0KICAgIHBpMCA9IHNlcSgwLCAxLCBieSA9IDAuMDAxKSwgICAgIyBDcmVhdGUgYSByYW5nZSBvZiBwaV8wIHZhbHVlcyB0byB0ZXN0DQogICAgc2UwID0gc3FydChwaTAqKDEtcGkwKS9uKSwgIyBDYWxjdWxhdGluZyB0aGUgc3RhbmRhcmQgZXJyb3JzIGZvciB0aGUgZGlmZmVyZW50IHBpMA0KICAgIHogPSAodGRfcHJvcCAtIHBpMCkvc2UwICAgICMgRmluZGluZyB0aGUgU2NvcmUgdGVzdCBzdGF0IGZvciB0aGUgdmFyaW91cyBwaTANCiAgKSAgICAgICAgDQoNCnNjb3JlX2RmDQoNCiMgTmV4dCB3ZSB3YW50IHRvIGZpbmQgdGhlIHZhbHVlcyBvZiBwaTAgdGhhdCBoYXZlIGEgdGVzdCBzdGF0IGJlbG93IHo5NQ0Kc2NvcmVfZGYgfD4gDQogIGZpbHRlcihhYnMoeikgPD0gejk1KSB8PiANCiAgc3VtbWFyaXplKA0KICAgIGxvd2VyID0gbWluKHBpMCksDQogICAgdXBwZXIgPSBtYXgocGkwKQ0KICApDQpgYGANCg0KV2hlbiByb3VuZGluZyB0byAzIGRlY2ltYWwgcGxhY2VzLCB3ZSBnZXQgYSB2ZXJ5IHNpbWlsYXIgY29uZmlkZW5jZSBpbnRlcnZhbCB0byB0aGUgV2FsZCBpbnRlcnZhbCBlYXJsaWVyIQ0KDQoNCg0KVGhlcmUgaXMgYWxzbyBhIGZvcm11bGEgd2UgY2FuIHVzZSBpbiBwbGFjZSBvZiBjb25kdWN0aW5nIGEgZ3JpZCBzZWFyY2g6DQoNCiQkXGZyYWN7eSArXGxlZnQoel4qXHJpZ2h0KV4yLzJ9e24gKyBcbGVmdCh6XipccmlnaHQpXjJ9IFxwbSBcZnJhY3t6Xip9e24gKyBcbGVmdCh6XipccmlnaHQpXjJ9IFxzcXJ0e1xmcmFje3kobiAtIHkpfXtufSArIFxmcmFje1xsZWZ0KHpeKlxyaWdodCleMn17NH19JCQNCg0Kd2hlcmUgJHkkIGlzIHRoZSBjb3VudCwgbm90IHByb3BvcnRpb24NCg0KYGBge3Igc2NvcmVfZm9ybXVsYX0NCiMgRmlyc3QsIGZpbmQgdGhlICJzdGF0aXN0aWMiDQpzY29yZV9zdGF0IDwtICh0ZF90b3RhbCArIHo5NV4yLzIpLyhuICsgejk1XjIpDQoNCg0KIyBOZXh0IGZpbmQgdGhlIHN0YW5kYXJkIGVycm9yDQpzY29yZV9zZSA8LSBzcXJ0KHRkX3RvdGFsICoobiAtIHRkX3RvdGFsKS9uICsgejk1XjIvNCkNCg0KDQojIFRoZW4gbWFyZ2luIG9mIGVycm9yDQptZV9mb3JtdWxhIDwtIHo5NS8obiArIHo5NV4yKSAqIHNjb3JlX3NlDQoNCg0KIyBUaGVuIGludGVydmFsOg0KdHJpYmJsZSgNCiAgICAgIH4ncmVzdWx0JywgICAgICAgICAgICAgICAgfid2YWx1ZScsDQogICAgICAgICAgICAneScsICAgICAgICAgICAgICAgIHRkX3RvdGFsLA0KICAgICAgICAgICAgJ24nLCAgICAgICAgICAgICAgICAgICAgICAgbiwNCiAgICdzY29yZSBzdGF0JywgICAgICAgICAgICAgIHNjb3JlX3N0YXQsDQogICAgICdTY29yZSBTRScsICAgICAgICAgICAgICAgIHNjb3JlX3NlLA0KICAgICAnU2NvcmUgTUUnLCAgICAgICAgICAgICAgbWVfZm9ybXVsYSwNCiAgJ2xvd2VyIGJvdW5kJywgc2NvcmVfc3RhdCAtIG1lX2Zvcm11bGEsDQogICd1cHBlciBib3VuZCcsIHNjb3JlX3N0YXQgKyBtZV9mb3JtdWxhDQopIHw+IA0KICBtdXRhdGUoDQogICAgdmFsdWUgPSByb3VuZCh2YWx1ZSwgMykNCiAgKQ0KDQpgYGANCg0KT3VyIHR3byBhbnN3ZXJzIGFyZSBzbGlnaHQgZGlmZmVyZW50IGR1ZSB0byByb3VuZGluZyBhbmQgb25seSBzZWFyY2hpbmcgdG8gdGhlIG5lYXJlc3QgMC4wMDEuIElmIHdlIHVzZWQgZW5vdWdoIGRpZ2l0cyBpbiBvdXIgInNlYXJjaCIsIHRoZSBhbnN3ZXIgd2lsbCBiZSBpZGVudGljYWwhDQoNCg0KIyMjIEFncmVzdGktQ291bGwNCg0KVGhlIEFncmVzdGktQ291bGwgKEFDKSBpbnRlcnZhbCAnbWl4ZXMnIHRoZSBzY29yZSBhbmQgV2FsZCBpbnRlcnZhbHMgdG9nZXRoZXIuDQoNCkhvdz8gSXQga2VlcHMgdGhlIHNhbWUgZ2VuZXJhbCBmb3JtIG9mIHRoZSBXYWxkIGludGVydmFsOg0KDQokJFxoYXR7XHBpfSBccG0gel97XGFscGhhLzJ9IFxzcXJ0e1xmcmFje1xoYXR7XHBpfSgxLVxoYXR7XHBpfSl9e259fSQkDQoNCmJ1dCBpdCB1cGRhdGVzICR5JCBhbmQgJG4kOg0KDQokJFx0aWxkZXt5fSA9IHkgKyAoel4qKV4yLzIgXFwgXHRpbGRle259ID0gbiArICh6XiopXjIgXFwgXHRpbGRle1xwaX0gPSBcdGlsZGV7eX0gLyBcdGlsZGV7bn0kJA0KDQpgYGB7ciBBQ19pbnRlcnZhbH0NCiMgQ2FsY3VsYXRpbmcgdGhlICduZXcnIHBvaW50IGVzdGltYXRlDQp5X3RpbGRlIDwtIHRkX3RvdGFsICsgKHo5NV4yKS8yDQpuX3RpbGRlIDwtICBuICsgejk1XjINCnBpX3RpbGRlIDwtIHlfdGlsZGUgLyBuX3RpbGRlDQoNCiMgVGhlIHN0YW5kYXJkIGVycm9yDQpBR19zZSA8LSBzcXJ0KHBpX3RpbGRlICogKDEtcGlfdGlsZGUpIC8gbikNCg0KIyBMb3dlciBhbmQgdXBwZXIgYm91bmRzDQpBR19jaSA8LSANCiAgYygnbG93ZXInID0gcGlfdGlsZGUgLSB6OTUgKiBBR19zZSwNCiAgICAndXBwZXInID0gcGlfdGlsZGUgKyB6OTUgKiBBR19zZQ0KICAgICkNCg0KQUdfY2kNCg0KYGBgDQoNCkp1c3QgbGlrZSB0aGUgc2NvcmUgYW5kIFdhbGQgaW50ZXJ2YWwsIGl0J3MgdmVyeSwgdmVyeSBzaW1pbGFyIQ0KDQojIyBCdWlsdC1pbiBGdW5jdGlvbnMNCg0KSWYgeW91IHdhbnQgKm9uZSBmdW5jdGlvbiB0byBydWxlIHRoZW0gYWxsKiwgd2UgY2FuIHVzZSB0aGUgYGJpbm9tLmNvbmZpbnQoKWAgZnVuY3Rpb24gaW4gdGhlIGBiaW5vbWAgcGFja2FnZS4NCg0KSXQgd29ya3Mgc2ltaWxhcmx5IHRvIGBwcm9wLnRlc3QoKWAsIGluIHRoYXQgd2UgbmVlZCB0byBzcGVjaWZ5IGB4YCBhbmQgYG5gLiBIb3dldmVyLCB3ZSBjYW4gYWxzbyBzcGVjaWZ5IGBtZXRob2RzYCBhcyBhIHdheSB0byB0ZWxsIGl0IHdoaWNoIG1ldGhvZCB0byBidWlsZCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbDoNCg0KLSAnYXN5bXB0b3RpYycgPSBXYWxkDQotICd3aWxzb24nID0gc2NvcmUNCi0gJ2FjJyA9IEFncmVzdGktQ291bGwNCg0KDQpgYGB7ciBidWlsdGluX3dhbGR9DQpsaWJyYXJ5KGJpbm9tKQ0KYmlub20uY29uZmludCgNCiAgeCA9IHRkX3RvdGFsLA0KICBuID0gbiwNCiAgY29uZi5sZXZlbCA9IDAuOTUsDQogIG1ldGhvZHMgPSAnYXN5bXB0b3RpYycNCikNCmBgYA0KDQoNCg0KYGBge3IgYnVpbHRpbl9zY29yZX0NCmJpbm9tLmNvbmZpbnQoDQogIHggPSB0ZF90b3RhbCwNCiAgbiA9IG4sDQogIGNvbmYubGV2ZWwgPSAwLjk1LA0KICBtZXRob2RzID0gJ3dpbHNvbicNCikNCmBgYA0KDQpgYGB7ciBidWlsdGluX2FjfQ0KYmlub20uY29uZmludCgNCiAgeCA9IHRkX3RvdGFsLA0KICBuID0gbiwNCiAgY29uZi5sZXZlbCA9IDAuOTUsDQogIG1ldGhvZHMgPSAnYWMnDQopDQpgYGANCg0KDQpZb3UgY2FuIGFsc28gZ2l2ZSBpdCBhbGwgdGhyZWUgbWV0aG9kcyBpbiBvbmUgZnVuY3Rpb24gYnkgZ2l2aW5nIGBtZXRob2RzYCBhIHZlY3RvcjoNCg0KYGBge3IgYnVpbHRpbl9hbGwzfQ0KYmlub20uY29uZmludCgNCiAgeCA9IHRkX3RvdGFsLA0KICBuID0gbiwNCiAgY29uZi5sZXZlbCA9IDAuOTUsDQogIG1ldGhvZHMgPSBjKCdhc3ltcHRvdGljJywgJ3dpbHNvbicsICdhYycpDQopDQpgYGANCg0KDQoNCg0KDQoNCg==