There are 4 ways in the data that a touchdown can end: Touchdown,
Field Goal, Punt, Turnover
Hypothesis Test
Let’s perform a hypothesis test to answer the question “Do 20% of all
drives end in touchdowns?”
\[H_0: \pi = 0.20 \\ H_1: \pi \ne
0.20\]
For a single parameter, test statistics follow the same general
pattern:
\[z = \frac{\textrm{statistic} -
\textrm{null value}}{\textrm{standard error}}\]
If we are interested in learning about a single proportion, our test
statistic is:
\[z = \frac{\hat{\pi} -
\pi_0}{\sqrt{\frac{\pi(1-\pi)}{n}}}\]
We have \(\pi_0\), but need to
calculate our sample proportion:
# Calculating the total number of tds
td_total <- sum(drives$drive_end == "Touchdown")
# Calculating the sample proportion using mean(drives$drive_end = "Touchdown")
td_prop <- mean(drives$drive_end == "Touchdown")
td_prop
## [1] 0.24
Let’s save the sample size, \(n\),
and the null hypothesis value, \(\pi_0\):
n <- nrow(drives); pi0 <- 0.20
We have a sample proportion of \(\hat{\pi}
= 0.24\) (24%). Our null hypothesis is 0.20 (\(\pi_0 = 0.20\)).
So we have the top of our test statistic fraction, but what about the
denominator:
\[SE =
\sqrt{\frac{\pi(1-\pi)}{n}}\]
We don’t have \(\pi\) (hence the
hypothesis test). So what do we replace it with?
There are two choices:
- Replace the unknown parameter with the sample statistic: \(\pi \rightarrow \hat{\pi}\)
- This is our Wald standard error
- Replace the unknown parameter with the null hypothesis value: \(\pi \rightarrow \pi_0\)$
- This is our Score, sometimes called
Wilson, standard error
For larger sample sizes, the two won’t be that different. But for
smaller sample sizes, the standard errors can be very different.
When performing a hypothesis test, a Score standard error is
typically used and the test is then called a Score Test
(unsurprising!)
Wald Test and Score Tests
Let’s start with the Wald test:
\[z = \frac{\hat{\pi} -
\pi_0}{\sqrt{\frac{\hat{\pi}(1-\hat{\pi})}{n}}}\]
wald_se <- sqrt(td_prop * (1 - td_prop)/n)
wald_se
## [1] 0.01207974
Next, we’ll find the test statistic:
wald_z <- (td_prop - pi0) / wald_se
wald_z
## [1] 3.311331
Then we can find the p-value: \(P(|Z| >
3.311)\)
wald_pval <- 2 * pnorm(abs(wald_z), lower.tail = F)
wald_pval
## [1] 0.0009285334
The Wald test rejects the null hypothesis!
Score Test
Up next: Score Test
\[z = \frac{\hat{\pi} -
\pi_0}{\sqrt{\frac{\pi_0(1-\pi_0)}{n}}}\]
score_se <- sqrt(pi0 * (1 - pi0)/n)
score_se
## [1] 0.01131371
Next, we’ll find the test statistic:
score_z <- (td_prop - pi0) / score_se
score_z
## [1] 3.535534
Then we can find the p-value: \(P(|Z| >
3.536)\)
score_pval <- 2 * pnorm(abs(score_z), lower.tail = F)
score_pval
## [1] 0.000406952
The test statistic is larger and the p-value smaller for the score
test compared to the Wald test!
Likelihood Ratio Test
The likelihood ratio test (LRT) takes a different approach than the
typical \(\frac{\hat{\pi} - pi_0}{SE}\)
test statistic. Instead, for a binomial random variable, it is a ratio
of two different binomial distributions:
\[\frac{\ell_1}{\ell_0} = \frac{{n \choose
y} \hat{\pi}^y(1-\hat{\pi})^{n-y}}{{n \choose y}
(\pi_0)^y(1-\pi_0)^{n-y}}\]
We can find the numerator and denominator using
dbinom(...) with prob = the corresponding
probabilities
# unrestricted likelihood
ell1 <- dbinom(td_total, size = n, prob = td_prop)
# restricted likelihood
ell0 <- dbinom(td_total, size = n, prob = pi0)
# LRT test stat
lrt_test_stat <- ell1 / ell0
lrt_test_stat
## [1] 390.6599
In order to find a p-value, we need to know that distribution the
test statistic follows.
While \(\ell_1 / \ell_0\) itself
doesn’t have a defined distribution, we can use Wilk’s
Theorem to find a test statistic and distribution:
\[2\log\left(\frac{\ell_1}{\ell_0}\right)
\sim \chi^2_v\]
For a single binomial random, there is one ‘unrestrained’ parameter
in \(\ell_1\), so \(v = 1\)
The LRT p-value is:
\[P(\chi^2_1 > 11.936)\]
log_lrt_test_stat <- 2 * log(lrt_test_stat)
lrt_pval <- pchisq(q = log_lrt_test_stat, df = 1, lower.tail = F)
lrt_pval
## [1] 0.0005506918
The p-value for the LRT test is similar to the score test
statistic.
Comparing the three tests:
If we compare the three exams:
tibble(
test = c('Wald', 'Score', 'LRT'),
test_stat = round(c(wald_z, score_z, log_lrt_test_stat), 5),
p_value = round(c(wald_pval, score_pval, lrt_pval), 5)
)
## # A tibble: 3 × 3
## test test_stat p_value
## <chr> <dbl> <dbl>
## 1 Wald 3.31 0.00093
## 2 Score 3.54 0.00041
## 3 LRT 11.9 0.00055
Built-in functions for tests:
Note: Regardless of which test we use, the functions
will return the \(\chi^2\) version of
the test statistic, \(z^2\).
Wald test:
There isn’t one :(
That’s because using the Wald test for a single proportion is a bad
idea. We did it (and you’ll do it on the homework) to show that it
exists, but you shouldn’t use it!
Why?
What happens if \(y = n\)?
Score test:
For the score test, you can use prop.test() in
base R, or prop_test() in
rstatix. prop_test() is very similar to
prop.test(), but it gives the results in a data frame that
is easier to work with than the object created by
prop.test().
Both functions have the following arguments:
x = the number of successes (we denote as \(y\))
n = the sample size
p = the null hypothesis value, \(\pi_0\)
correct = F to have it do a score test without a
binomial correction
prop.test(
x = td_total,
n = n,
p = pi0,
alternative = 'two.sided',
correct = F
)
##
## 1-sample proportions test without continuity correction
##
## data: td_total out of n, null probability pi0
## X-squared = 12.5, df = 1, p-value = 0.000407
## alternative hypothesis: true p is not equal to 0.2
## 95 percent confidence interval:
## 0.2171436 0.2644495
## sample estimates:
## p
## 0.24
rstatix::prop_test(
x = td_total,
n = n,
p = pi0,
correct = F
)
## # A tibble: 1 × 5
## n statistic df p p.signif
## * <int> <dbl> <int> <dbl> <chr>
## 1 1250 12.5 1 0.000407 ***
LRT Built-in:
To conduct a likelihood ratio test using a built-in function, we need
to install the DescTools package and use the
GTest(...)
The GTest(...) function doesn’t do a one-proportion
test, but it will do a goodness-of-fit test. What good is that to
us?
If the number of categories in a GoF test is 2, then it is equivalent
to a one prop test!
That does mean instead of just giving it the number of successes and
the hypothesized probability, we need to give it both \(y\) and \(n-y\) along with \(\pi_0\) and \(1-\pi_0\) in two vectors for x
and p, as seen below:
DescTools::GTest(
x = c(td_total, n - td_total),
p = c(pi0, 1-pi0)
)
##
## Log likelihood ratio (G-test) goodness of fit test
##
## data: c(td_total, n - td_total)
## G = 11.936, X-squared df = 1, p-value = 0.0005507
LS0tDQp0aXRsZTogIkluZmVyZW5jZSBmb3IgMSBDYXRlZ29yaWNhbCBWYXJpYWJsZSAtIFNpbmdsZSBQcm9wb3J0aW9uIg0KYXV0aG9yOiAiQ2hhcHRlciAxIg0KZGF0ZTogIlNUQSA0NTA0Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGZpZ193aWR0aDogNg0KICAgIGZpZ19oZWlnaHQ6IDYNCiAgICBmaWdfY2FwdGlvbjogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICAgIHRoZW1lOiBsdW1lbg0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ24gPSAiY2VudGVyIikNCmBgYA0KDQpgYGB7ciBwYWNrYWdlc30NCiMgTG9hZGluZyB0aGUgdGlkeXZlcnNlIHBhY2thZ2UNCmxpYnJhcnkodGlkeXZlcnNlKQ0KYGBgDQoNClJlYWRpbmcgaW4gdGhlIE5GTCBkcml2ZXMgZGF0YSBmcm9tIGdpdGh1Yg0KDQpgYGB7ciBkYXRhfQ0KIyBSZWFkIGluIHRoZSBuZmwgZHJpdmUgZGF0YQ0KZHJpdmVzIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vU2hhbW1hbGFtYWxhL1NUQTQ1MDQvcmVmcy9oZWFkcy9tYWluL2RhdGEvY2gxL25mbCUyMGRyaXZlcy5jc3YiKQ0KDQojIExvb2tpbmcgYXQgdGhlIGRpZmZlcmVudCB3YXlzIGRyaXZlcyBjYW4gZW5kDQp1bmlxdWUoZHJpdmVzJGRyaXZlX2VuZCkNCg0KYGBgDQoNCldlIHdpbGwgYmUgZm9jdXNpbmcgb24gdGhlIHZhcmlhYmxlIGBkcml2ZV9lbmRgDQoNClRoZXJlIGFyZSA0IHdheXMgaW4gdGhlIGRhdGEgdGhhdCBhIHRvdWNoZG93biBjYW4gZW5kOiBUb3VjaGRvd24sIEZpZWxkIEdvYWwsIFB1bnQsIFR1cm5vdmVyDQoNCiMjIEh5cG90aGVzaXMgVGVzdA0KDQpMZXQncyBwZXJmb3JtIGEgaHlwb3RoZXNpcyB0ZXN0IHRvIGFuc3dlciB0aGUgcXVlc3Rpb24gIkRvIDIwJSBvZiBhbGwgZHJpdmVzIGVuZCBpbiB0b3VjaGRvd25zPyINCg0KJCRIXzA6IFxwaSA9IDAuMjAgXFwgSF8xOiBccGkgXG5lIDAuMjAkJA0KDQpGb3IgYSBzaW5nbGUgcGFyYW1ldGVyLCB0ZXN0IHN0YXRpc3RpY3MgZm9sbG93IHRoZSBzYW1lIGdlbmVyYWwgcGF0dGVybjoNCg0KJCR6ID0gXGZyYWN7XHRleHRybXtzdGF0aXN0aWN9IC0gXHRleHRybXtudWxsIHZhbHVlfX17XHRleHRybXtzdGFuZGFyZCBlcnJvcn19JCQNCg0KSWYgd2UgYXJlIGludGVyZXN0ZWQgaW4gbGVhcm5pbmcgYWJvdXQgYSBzaW5nbGUgcHJvcG9ydGlvbiwgb3VyIHRlc3Qgc3RhdGlzdGljIGlzOg0KDQokJHogPSBcZnJhY3tcaGF0e1xwaX0gLSBccGlfMH17XHNxcnR7XGZyYWN7XHBpKDEtXHBpKX17bn19fSQkDQoNCldlIGhhdmUgJFxwaV8wJCwgYnV0IG5lZWQgdG8gY2FsY3VsYXRlIG91ciBzYW1wbGUgcHJvcG9ydGlvbjoNCg0KYGBge3IgdGRfcHJvcH0NCiMgQ2FsY3VsYXRpbmcgdGhlIHRvdGFsIG51bWJlciBvZiB0ZHMNCnRkX3RvdGFsIDwtIHN1bShkcml2ZXMkZHJpdmVfZW5kID09ICJUb3VjaGRvd24iKQ0KDQojIENhbGN1bGF0aW5nIHRoZSBzYW1wbGUgcHJvcG9ydGlvbiB1c2luZyBtZWFuKGRyaXZlcyRkcml2ZV9lbmQgPSAiVG91Y2hkb3duIikNCnRkX3Byb3AgPC0gbWVhbihkcml2ZXMkZHJpdmVfZW5kID09ICJUb3VjaGRvd24iKQ0KDQp0ZF9wcm9wDQpgYGANCg0KTGV0J3Mgc2F2ZSB0aGUgc2FtcGxlIHNpemUsICRuJCwgYW5kIHRoZSBudWxsIGh5cG90aGVzaXMgdmFsdWUsICRccGlfMCQ6DQoNCmBgYHtyIHNhbXBsZV9zaXplfQ0KbiA8LSBucm93KGRyaXZlcyk7IHBpMCA8LSAwLjIwDQoNCmBgYA0KDQpXZSBoYXZlIGEgc2FtcGxlIHByb3BvcnRpb24gb2YgJFxoYXR7XHBpfSA9IDAuMjQkICgyNCUpLiBPdXIgbnVsbCBoeXBvdGhlc2lzIGlzIDAuMjAgKCRccGlfMCA9IDAuMjAkKS4NCg0KU28gd2UgaGF2ZSB0aGUgdG9wIG9mIG91ciB0ZXN0IHN0YXRpc3RpYyBmcmFjdGlvbiwgYnV0IHdoYXQgYWJvdXQgdGhlIGRlbm9taW5hdG9yOg0KDQokJFNFID0gXHNxcnR7XGZyYWN7XHBpKDEtXHBpKX17bn19JCQNCg0KV2UgZG9uJ3QgaGF2ZSAkXHBpJCAoaGVuY2UgdGhlIGh5cG90aGVzaXMgdGVzdCkuIFNvIHdoYXQgZG8gd2UgcmVwbGFjZSBpdCB3aXRoPw0KDQpUaGVyZSBhcmUgdHdvIGNob2ljZXM6DQoNCjEpICBSZXBsYWNlIHRoZSB1bmtub3duIHBhcmFtZXRlciB3aXRoIHRoZSBzYW1wbGUgc3RhdGlzdGljOiAkXHBpIFxyaWdodGFycm93IFxoYXR7XHBpfSQNCg0KLSBUaGlzIGlzIG91ciAqKldhbGQqKiBzdGFuZGFyZCBlcnJvcg0KDQoyKSAgUmVwbGFjZSB0aGUgdW5rbm93biBwYXJhbWV0ZXIgd2l0aCB0aGUgbnVsbCBoeXBvdGhlc2lzIHZhbHVlOiAkXHBpIFxyaWdodGFycm93IFxwaV8wJFwkDQoNCi0gVGhpcyBpcyBvdXIgKipTY29yZSoqLCBzb21ldGltZXMgY2FsbGVkICoqV2lsc29uKiosIHN0YW5kYXJkIGVycm9yDQoNCkZvciBsYXJnZXIgc2FtcGxlIHNpemVzLCB0aGUgdHdvIHdvbid0IGJlIHRoYXQgZGlmZmVyZW50LiBCdXQgZm9yIHNtYWxsZXIgc2FtcGxlIHNpemVzLCB0aGUgc3RhbmRhcmQgZXJyb3JzIGNhbiBiZSB2ZXJ5IGRpZmZlcmVudC4NCg0KV2hlbiBwZXJmb3JtaW5nIGEgaHlwb3RoZXNpcyB0ZXN0LCBhIFNjb3JlIHN0YW5kYXJkIGVycm9yIGlzIHR5cGljYWxseSB1c2VkIGFuZCB0aGUgdGVzdCBpcyB0aGVuIGNhbGxlZCBhICoqU2NvcmUgVGVzdCoqICh1bnN1cnByaXNpbmchKQ0KDQojIyMgV2FsZCBUZXN0IGFuZCBTY29yZSBUZXN0cw0KDQpMZXQncyBzdGFydCB3aXRoIHRoZSBXYWxkIHRlc3Q6DQoNCiQkeiA9IFxmcmFje1xoYXR7XHBpfSAtIFxwaV8wfXtcc3FydHtcZnJhY3tcaGF0e1xwaX0oMS1caGF0e1xwaX0pfXtufX19JCQNCg0KYGBge3Igd2FsZF9zZX0NCndhbGRfc2UgPC0gc3FydCh0ZF9wcm9wICogKDEgLSB0ZF9wcm9wKS9uKQ0Kd2FsZF9zZQ0KYGBgDQoNCk5leHQsIHdlJ2xsIGZpbmQgdGhlIHRlc3Qgc3RhdGlzdGljOg0KDQpgYGB7ciBXYWxkX3Rlc3RTdGF0fQ0Kd2FsZF96IDwtICh0ZF9wcm9wIC0gcGkwKSAvIHdhbGRfc2UNCndhbGRfeg0KYGBgDQoNClRoZW4gd2UgY2FuIGZpbmQgdGhlIHAtdmFsdWU6ICRQKHxafCA+IGByIHJvdW5kKHdhbGRfeiwgMylgKSQNCg0KYGBge3Igd2FsZF9wdmFsfQ0Kd2FsZF9wdmFsIDwtIDIgKiBwbm9ybShhYnMod2FsZF96KSwgbG93ZXIudGFpbCA9IEYpDQp3YWxkX3B2YWwNCmBgYA0KDQpUaGUgV2FsZCB0ZXN0IHJlamVjdHMgdGhlIG51bGwgaHlwb3RoZXNpcyENCg0KIyMjIFNjb3JlIFRlc3QNCg0KVXAgbmV4dDogU2NvcmUgVGVzdA0KDQokJHogPSBcZnJhY3tcaGF0e1xwaX0gLSBccGlfMH17XHNxcnR7XGZyYWN7XHBpXzAoMS1ccGlfMCl9e259fX0kJA0KDQpgYGB7ciBzY29yZV9zZX0NCnNjb3JlX3NlIDwtIHNxcnQocGkwICogKDEgLSBwaTApL24pDQpzY29yZV9zZQ0KYGBgDQoNCk5leHQsIHdlJ2xsIGZpbmQgdGhlIHRlc3Qgc3RhdGlzdGljOg0KDQpgYGB7ciBzY29yZV90ZXN0U3RhdH0NCnNjb3JlX3ogPC0gKHRkX3Byb3AgLSBwaTApIC8gc2NvcmVfc2UNCnNjb3JlX3oNCmBgYA0KDQpUaGVuIHdlIGNhbiBmaW5kIHRoZSBwLXZhbHVlOiAkUCh8WnwgPiBgciByb3VuZChzY29yZV96LCAzKWApJA0KDQpgYGB7ciBzY29yZV9wdmFsfQ0Kc2NvcmVfcHZhbCA8LSAyICogcG5vcm0oYWJzKHNjb3JlX3opLCBsb3dlci50YWlsID0gRikNCnNjb3JlX3B2YWwNCmBgYA0KDQpUaGUgdGVzdCBzdGF0aXN0aWMgaXMgbGFyZ2VyIGFuZCB0aGUgcC12YWx1ZSBzbWFsbGVyIGZvciB0aGUgc2NvcmUgdGVzdCBjb21wYXJlZCB0byB0aGUgV2FsZCB0ZXN0IQ0KDQoNCiMjIyBMaWtlbGlob29kIFJhdGlvIFRlc3QNCg0KVGhlIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCAoTFJUKSB0YWtlcyBhIGRpZmZlcmVudCBhcHByb2FjaCB0aGFuIHRoZSB0eXBpY2FsICRcZnJhY3tcaGF0e1xwaX0gLSBwaV8wfXtTRX0kIHRlc3Qgc3RhdGlzdGljLiBJbnN0ZWFkLCBmb3IgYSBiaW5vbWlhbCByYW5kb20gdmFyaWFibGUsIGl0IGlzIGEgcmF0aW8gb2YgdHdvIGRpZmZlcmVudCBiaW5vbWlhbCBkaXN0cmlidXRpb25zOg0KDQokJFxmcmFje1xlbGxfMX17XGVsbF8wfSA9IFxmcmFje3tuIFxjaG9vc2UgeX0gXGhhdHtccGl9XnkoMS1caGF0e1xwaX0pXntuLXl9fXt7biBcY2hvb3NlIHl9IChccGlfMCleeSgxLVxwaV8wKV57bi15fX0kJA0KDQpXZSBjYW4gZmluZCB0aGUgbnVtZXJhdG9yIGFuZCBkZW5vbWluYXRvciB1c2luZyBgZGJpbm9tKC4uLilgIHdpdGggYHByb2IgPSBgIHRoZSBjb3JyZXNwb25kaW5nIHByb2JhYmlsaXRpZXMNCg0KYGBge3IgbHJ0X3Rlc3RTdGF0fQ0KIyB1bnJlc3RyaWN0ZWQgbGlrZWxpaG9vZA0KZWxsMSA8LSBkYmlub20odGRfdG90YWwsIHNpemUgPSBuLCBwcm9iID0gdGRfcHJvcCkNCg0KIyByZXN0cmljdGVkIGxpa2VsaWhvb2QNCmVsbDAgPC0gZGJpbm9tKHRkX3RvdGFsLCBzaXplID0gbiwgcHJvYiA9IHBpMCkNCg0KIyBMUlQgdGVzdCBzdGF0IA0KbHJ0X3Rlc3Rfc3RhdCA8LSBlbGwxIC8gZWxsMA0KbHJ0X3Rlc3Rfc3RhdA0KYGBgDQoNCkluIG9yZGVyIHRvIGZpbmQgYSBwLXZhbHVlLCB3ZSBuZWVkIHRvIGtub3cgdGhhdCBkaXN0cmlidXRpb24gdGhlIHRlc3Qgc3RhdGlzdGljIGZvbGxvd3MuDQoNCldoaWxlICRcZWxsXzEgLyBcZWxsXzAkIGl0c2VsZiBkb2Vzbid0IGhhdmUgYSBkZWZpbmVkIGRpc3RyaWJ1dGlvbiwgd2UgY2FuIHVzZSAqKldpbGsncyBUaGVvcmVtKiogdG8gZmluZCBhIHRlc3Qgc3RhdGlzdGljIGFuZCBkaXN0cmlidXRpb246DQoNCiQkMlxsb2dcbGVmdChcZnJhY3tcZWxsXzF9e1xlbGxfMH1ccmlnaHQpIFxzaW0gXGNoaV4yX3YkJA0KDQpGb3IgYSBzaW5nbGUgYmlub21pYWwgcmFuZG9tLCB0aGVyZSBpcyBvbmUgJ3VucmVzdHJhaW5lZCcgcGFyYW1ldGVyIGluICRcZWxsXzEkLCBzbyAkdiA9IDEkDQoNClRoZSBMUlQgcC12YWx1ZSBpczoNCg0KJCRQKFxjaGleMl8xID4gYHIgcm91bmQoMiAqIGxvZyhscnRfdGVzdF9zdGF0KSwgMylgKSQkDQoNCmBgYHtyIGxydF9wdmFsfQ0KbG9nX2xydF90ZXN0X3N0YXQgPC0gMiAqIGxvZyhscnRfdGVzdF9zdGF0KQ0KbHJ0X3B2YWwgPC0gcGNoaXNxKHEgPSBsb2dfbHJ0X3Rlc3Rfc3RhdCwgZGYgPSAxLCBsb3dlci50YWlsID0gRikNCmxydF9wdmFsDQpgYGANCg0KVGhlIHAtdmFsdWUgZm9yIHRoZSBMUlQgdGVzdCBpcyBzaW1pbGFyIHRvIHRoZSBzY29yZSB0ZXN0IHN0YXRpc3RpYy4NCg0KIyMjIENvbXBhcmluZyB0aGUgdGhyZWUgdGVzdHM6DQoNCklmIHdlIGNvbXBhcmUgdGhlIHRocmVlIGV4YW1zOg0KDQpgYGB7ciB0aHJlZV90ZXN0X2NvbXBhcmV9DQp0aWJibGUoDQogIHRlc3QgPSBjKCdXYWxkJywgJ1Njb3JlJywgJ0xSVCcpLA0KICB0ZXN0X3N0YXQgPSByb3VuZChjKHdhbGRfeiwgc2NvcmVfeiwgbG9nX2xydF90ZXN0X3N0YXQpLCA1KSwNCiAgcF92YWx1ZSA9IHJvdW5kKGMod2FsZF9wdmFsLCBzY29yZV9wdmFsLCBscnRfcHZhbCksIDUpDQopDQpgYGANCg0KDQojIyBCdWlsdC1pbiBmdW5jdGlvbnMgZm9yIHRlc3RzOg0KDQoNCg0KKipOb3RlOioqIFJlZ2FyZGxlc3Mgb2Ygd2hpY2ggdGVzdCB3ZSB1c2UsIHRoZSBmdW5jdGlvbnMgd2lsbCByZXR1cm4gdGhlICRcY2hpXjIkIHZlcnNpb24gb2YgdGhlIHRlc3Qgc3RhdGlzdGljLCAkel4yJC4NCg0KIyMjIFdhbGQgdGVzdDoNCg0KVGhlcmUgaXNuJ3Qgb25lIDooDQoNClRoYXQncyBiZWNhdXNlIHVzaW5nIHRoZSBXYWxkIHRlc3QgZm9yIGEgc2luZ2xlIHByb3BvcnRpb24gaXMgYSBiYWQgaWRlYS4gV2UgZGlkIGl0IChhbmQgeW91J2xsIGRvIGl0IG9uIHRoZSBob21ld29yaykgdG8gc2hvdyB0aGF0IGl0IGV4aXN0cywgYnV0IHlvdSBzaG91bGRuJ3QgdXNlIGl0IQ0KDQpXaHk/DQoNCldoYXQgaGFwcGVucyBpZiAkeSA9IG4kPw0KDQojIyMgU2NvcmUgdGVzdDoNCg0KRm9yIHRoZSBzY29yZSB0ZXN0LCB5b3UgY2FuIHVzZSBgcHJvcC50ZXN0KClgIGluIGBiYXNlYCBSLCBvciBgcHJvcF90ZXN0KClgIGluIGByc3RhdGl4YC4gYHByb3BfdGVzdCgpYCBpcyB2ZXJ5IHNpbWlsYXIgdG8gYHByb3AudGVzdCgpYCwgYnV0IGl0IGdpdmVzIHRoZSByZXN1bHRzIGluIGEgZGF0YSBmcmFtZSB0aGF0IGlzIGVhc2llciB0byB3b3JrIHdpdGggdGhhbiB0aGUgb2JqZWN0IGNyZWF0ZWQgYnkgYHByb3AudGVzdCgpYC4NCg0KQm90aCBmdW5jdGlvbnMgaGF2ZSB0aGUgZm9sbG93aW5nIGFyZ3VtZW50czoNCg0KLSBgeCA9IGAgdGhlIG51bWJlciBvZiBzdWNjZXNzZXMgKHdlIGRlbm90ZSBhcyAkeSQpDQotIGBuID0gYCB0aGUgc2FtcGxlIHNpemUNCi0gYHAgPSBgIHRoZSBudWxsIGh5cG90aGVzaXMgdmFsdWUsICRccGlfMCQNCi0gYGNvcnJlY3QgPSBGYCB0byBoYXZlIGl0IGRvIGEgc2NvcmUgdGVzdCB3aXRob3V0IGEgYmlub21pYWwgY29ycmVjdGlvbg0KDQpgYGB7ciBwcm9wLnRlc3R9DQpwcm9wLnRlc3QoDQogIHggPSB0ZF90b3RhbCwNCiAgbiA9IG4sIA0KICBwID0gcGkwLA0KICBhbHRlcm5hdGl2ZSA9ICd0d28uc2lkZWQnLA0KICBjb3JyZWN0ID0gRg0KKQ0KYGBgDQoNCmBgYHtyIHByb3BfdGVzdH0NCnJzdGF0aXg6OnByb3BfdGVzdCgNCiAgeCA9IHRkX3RvdGFsLA0KICBuID0gbiwgDQogIHAgPSBwaTAsDQogIGNvcnJlY3QgPSBGDQopIA0KDQpgYGANCg0KDQojIyMgTFJUIEJ1aWx0LWluOg0KDQpUbyBjb25kdWN0IGEgbGlrZWxpaG9vZCByYXRpbyB0ZXN0IHVzaW5nIGEgYnVpbHQtaW4gZnVuY3Rpb24sIHdlIG5lZWQgdG8gaW5zdGFsbCB0aGUgYERlc2NUb29sc2AgcGFja2FnZSBhbmQgdXNlIHRoZSBgR1Rlc3QoLi4uKWANCg0KVGhlIGBHVGVzdCguLi4pYCBmdW5jdGlvbiBkb2Vzbid0IGRvIGEgb25lLXByb3BvcnRpb24gdGVzdCwgYnV0IGl0IHdpbGwgZG8gYSBnb29kbmVzcy1vZi1maXQgdGVzdC4gV2hhdCBnb29kIGlzIHRoYXQgdG8gdXM/DQoNCklmIHRoZSBudW1iZXIgb2YgY2F0ZWdvcmllcyBpbiBhIEdvRiB0ZXN0IGlzIDIsIHRoZW4gaXQgaXMgZXF1aXZhbGVudCB0byBhIG9uZSBwcm9wIHRlc3QhDQoNClRoYXQgZG9lcyBtZWFuIGluc3RlYWQgb2YganVzdCBnaXZpbmcgaXQgdGhlIG51bWJlciBvZiBzdWNjZXNzZXMgYW5kIHRoZSBoeXBvdGhlc2l6ZWQgcHJvYmFiaWxpdHksIHdlIG5lZWQgdG8gZ2l2ZSBpdCBib3RoICR5JCBhbmQgJG4teSQgYWxvbmcgd2l0aCAkXHBpXzAkIGFuZCAkMS1ccGlfMCQgaW4gdHdvIHZlY3RvcnMgZm9yIGB4YCBhbmQgYHBgLCBhcyBzZWVuIGJlbG93Og0KDQpgYGB7ciBscnRfYnVpbHRpbn0NCkRlc2NUb29sczo6R1Rlc3QoDQogIHggPSBjKHRkX3RvdGFsLCBuIC0gdGRfdG90YWwpLA0KICBwID0gYyhwaTAsIDEtcGkwKQ0KKQ0KYGBgDQoNCg0KDQoNCg0KDQoNCg0K