library(tidyverse)
# Reading in the nfl drives data
drives <- read.csv("https://raw.githubusercontent.com/Shammalamala/STA4504/refs/heads/main/data/ch2/nfl%20drives.csv")
Looking at the way drives can begin and end:
unique(drives$drive_start)
## [1] "Fumble" "Interception" "Kickoff" "Punt"
unique(drives$drive_end)
## [1] "Field Goal" "Punt" "Touchdown" "Turnover"
Motivating Question: Is a team more likely to score
a touchdown after a turnover compared to a punt or kickoff?
Relative risk is often used for two binary variables, so let’s
convert our data into two binary variables:
drive_start: turnover - Interception/Fumble vs kick -
Kickoff/Punt
drive_end: TD - Touchdown vs noTD - Field
Goal/Turnover/Punt
drives2 <-
drives |>
mutate(
drive_start = if_else(drive_start %in% c("Interception", "Fumble"),
true = "turnover",
false = "kick"),
# Converting drive_start to a factor with group order turnover, kick
drive_start = factor(drive_start,
levels = c("turnover", "kick")),
drive_end = if_else(drive_end == "Touchdown",
true = "TD",
false = "noTD"),
# Converting drive_end to a factor and ordering the groups as success then failure
drive_end = factor(drive_end,
levels = c("TD", "noTD"))
)
Next, let’s display the results in a two-way table using
xtabs()
# Displaying a two-way table using xtabs()
drive_freq <-
xtabs(formula = ~ drive_start + drive_end, data = drives2)
# The addmargins() function will add the margins to the table
drive_freq |>
addmargins()
## drive_end
## drive_start TD noTD Sum
## turnover 239 571 810
## kick 1200 4055 5255
## Sum 1439 4626 6065
And converting the table from counts to conditional proportions using
prop.table(margin = "drive_start")
drive_freq |>
prop.table(margin = "drive_start") |>
round(digits = 3)
## drive_end
## drive_start TD noTD
## turnover 0.295 0.705
## kick 0.228 0.772
Let’s create a bar chart to compare the probability of a touchdown
between the two groups:
drive_freq |>
# Calculate the conditional proportions
prop.table(margin = "drive_start") |>
# Convert the table to a data frame to be used by ggplot()
data.frame() |>
# Rename Freq to prop
rename(prop = Freq) |>
ggplot(mapping = aes(x = drive_start,
fill = drive_end,
y = prop)) +
geom_col(width = 0.5) +
labs(y = "Proportion",
x = "How Drive Began",
fill = "Drive \nResult") +
theme_test() +
scale_y_continuous(expand = c(0, 0, 0, 0.05)) +
scale_fill_manual(labels = c("Touchdown", "No Touchdown"),
values = c("steelblue", "darkorange"))

There are some differences, but it isn’t a very noticeable
difference.
Risk Difference: \(p_1 - p_2\)
The basic test for comparing “risks” is by using the risk
difference:
\[P(Y = 1|X = 1) - P(Y = 1|X = 2) = \pi_1
- \pi_2\]
which is the difference in the “success” rate of the response
variable between two groups of the explanatory variable:
- 1|1 = Success given in group 1 of the explanatory variable
- 1|2 = Success given in group 2 of the explanatory variable
Our best estimate of the risk difference is:
\[p_{1} - p_{2} =
\frac{n_{11}}{n_{1\bullet}} - \frac{n_{21}}{n_{2\bullet}}\]
Let’s use prop_test() from the rstatix
package again to calculate the risk difference, p-value, and confidence
interval. The arguments for 2 binary variables are:
x = a table of counts with 1st column = success and 2nd
column = failures
detailed = T to report the individual proportions and
confidence interval
rstatix::prop_test(x = drive_freq,
detailed = T)
## # A tibble: 1 × 13
## n n1 n2 estimate1 estimate2 statistic p df conf.low
## * <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 6065 810 5255 0.295 0.228 16.9 0.0000396 1 0.0326
## # ℹ 4 more variables: conf.high <dbl>, method <chr>, alternative <chr>,
## # p.signif <chr>
Let’s improve the names and add the risk difference to the
results
risk_diff_results <-
rstatix::prop_test(
x = drive_freq,
detailed = T
) |>
# Renaming n1 and n2 to their respective group names
rename(
turnover_n = n1,
kick_n = n2,
turnover_p = estimate1,
kick_p = estimate2,
test_stat = statistic,
p_val = p
) |>
# Calculating the risk difference
mutate(risk_diff = turnover_p - kick_p) |>
# Picking with columns to display:
dplyr::select(
n,
turnover_n,
kick_n,
turnover_p,
kick_p,
risk_diff,
test_stat,
p_val,
conf.low,
conf.high
)
risk_diff_results |>
signif(digits = 3)
## # A tibble: 1 × 10
## n turnover_n kick_n turnover_p kick_p risk_diff test_stat p_val conf.low
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 6060 810 5260 0.295 0.228 0.0667 16.9 3.96e-5 0.0326
## # ℹ 1 more variable: conf.high <dbl>
From our results, we can see that there is a statistically
significant difference in how often drives end in touchdowns depending
if they start from a turnover or a kick.
We can be 95% confidence that drives that start from a turnover are
3.3% to 10.1% more likely to end in a touchdown than drives that start
from a kickoff or a punt
Risk Ratio
An alternative to risk difference is risk ratio:
\[RR = \frac{P(Y = 1|X = 1)}{P(Y = 1|X =
2)} = \frac{\pi_{1}}{\pi_{2}}\]
The probability of success in group 1 over the probability of success
of group 2
Relative risk using the riskratio() function
We can compute the relative risk using the riskratio()
function in the epitools package. The arguments are:
x = a 2x2 table with:
- column order of Failure/Success
- row order of baseline group/interest group
conf.level = the confidence level
verbose = T if you want additional results
returned
Note: riskratio() wants the row and
column order swapped from prop_test(). We can swap the
order of the rows and columns using the additional argument
rev = both
pacman::p_load(epitools)
drives_rr <-
riskratio(
x = drive_freq,
verbose = F,
conf.level = 0.95,
rev = "both"
)
drives_rr
## $data
## drive_end
## drive_start noTD TD Total
## kick 4055 1200 5255
## turnover 571 239 810
## Total 4626 1439 6065
##
## $measure
## risk ratio with 95% C.I.
## drive_start estimate lower upper
## kick 1.000000 NA NA
## turnover 1.292124 1.148907 1.453194
##
## $p.value
## two-sided
## drive_start midp.exact fisher.exact chi.square
## kick NA NA NA
## turnover 4.724261e-05 5.233613e-05 3.264256e-05
##
## $correction
## [1] FALSE
##
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"
riskratio() has a lot of output. You can specify a
specific quantity by using $ followed by the named table
you want to display:
Confidence interval: $measure
# Risk ratio estimate and Confidence interval from $measure
data.frame(drives_rr$measure)
## estimate lower upper
## kick 1.000000 NA NA
## turnover 1.292124 1.148907 1.453194
The first row is the reference group (“kick”) and the proceeding rows
are the risk ratio of that group vs the reference group.
We can interpret the estimate as
“We estimate drives are 1.29 times more likely to result in a
touchdown if they start by a turnover compared to a punt or
kickoff”
Likewise, we can interpret the confidence interval as
“We are 95% confident that drives that begin from a turnover
are 1.15 to 1.45 times more likely to result in a touchdown that drives
that begin from a punt or kickoff”
For the p-value of a hypothesis test, we use
$p.value
# Hypothesis test results using $p.value
data.frame(drives_rr$p.value)
## midp.exact fisher.exact chi.square
## kick NA NA NA
## turnover 4.724261e-05 5.233613e-05 3.264256e-05
note that there are 3 different p-values. We’ll look at
midp.exact and fisher.exact soon, but the
chi.square p-value is the one that uses the Normal
approximation of \(\ln\hat{R}\)
LS0tDQp0aXRsZTogIlR3byBCaW5hcnkgVmFyaWFibGVzIC0gUmlzayBSYXRpbyINCmF1dGhvcjogIkNoYXB0ZXIgMiINCmRhdGU6ICJTVEEgNDUwNCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBmaWdfd2lkdGg6IDEwDQogICAgZmlnX2hlaWdodDogNg0KICAgIGZpZ19jYXB0aW9uOiB0cnVlDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBzbW9vdGhfc2Nyb2xsOiB0cnVlDQogICAgdGhlbWU6IGx1bWVuDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIpDQpgYGANCg0KDQpgYGB7ciBwYWNrYWdlc19kYXRhLCBtZXNzYWdlID0gRiwgd2FybmluZyA9IEZ9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KIyBSZWFkaW5nIGluIHRoZSBuZmwgZHJpdmVzIGRhdGENCmRyaXZlcyA8LSByZWFkLmNzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL1NoYW1tYWxhbWFsYS9TVEE0NTA0L3JlZnMvaGVhZHMvbWFpbi9kYXRhL2NoMi9uZmwlMjBkcml2ZXMuY3N2IikgDQpgYGANCg0KDQpMb29raW5nIGF0IHRoZSB3YXkgZHJpdmVzIGNhbiBiZWdpbiBhbmQgZW5kOg0KDQoNCmBgYHtyIGRyaXZlX3N0YXJ0X2VuZH0NCnVuaXF1ZShkcml2ZXMkZHJpdmVfc3RhcnQpDQp1bmlxdWUoZHJpdmVzJGRyaXZlX2VuZCkNCg0KYGBgDQoNCioqTW90aXZhdGluZyBRdWVzdGlvbjoqKiBJcyBhIHRlYW0gbW9yZSBsaWtlbHkgdG8gc2NvcmUgYSB0b3VjaGRvd24gYWZ0ZXIgYSB0dXJub3ZlciBjb21wYXJlZCB0byBhIHB1bnQgb3Iga2lja29mZj8NCg0KDQoNClJlbGF0aXZlIHJpc2sgaXMgb2Z0ZW4gdXNlZCBmb3IgdHdvIGJpbmFyeSB2YXJpYWJsZXMsIHNvIGxldCdzIGNvbnZlcnQgb3VyIGRhdGEgaW50byB0d28gYmluYXJ5IHZhcmlhYmxlczoNCg0KLSBgZHJpdmVfc3RhcnRgOiB0dXJub3ZlciAtIEludGVyY2VwdGlvbi9GdW1ibGUgdnMga2ljayAtIEtpY2tvZmYvUHVudA0KLSBgZHJpdmVfZW5kYDogVEQgLSBUb3VjaGRvd24gdnMgbm9URCAtIEZpZWxkIEdvYWwvVHVybm92ZXIvUHVudCANCg0KYGBge3IgZHJpdmVzMn0NCmRyaXZlczIgPC0gDQogIGRyaXZlcyB8PiANCiAgbXV0YXRlKA0KICAgIGRyaXZlX3N0YXJ0ID0gaWZfZWxzZShkcml2ZV9zdGFydCAlaW4lIGMoIkludGVyY2VwdGlvbiIsICJGdW1ibGUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ1ZSA9ICJ0dXJub3ZlciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGZhbHNlID0gImtpY2siKSwNCiAgICAjIENvbnZlcnRpbmcgZHJpdmVfc3RhcnQgdG8gYSBmYWN0b3Igd2l0aCBncm91cCBvcmRlciB0dXJub3Zlciwga2ljaw0KICAgIGRyaXZlX3N0YXJ0ID0gZmFjdG9yKGRyaXZlX3N0YXJ0LA0KICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoInR1cm5vdmVyIiwgImtpY2siKSksDQogICAgDQogICAgDQogICAgZHJpdmVfZW5kID0gaWZfZWxzZShkcml2ZV9lbmQgPT0gIlRvdWNoZG93biIsDQogICAgICAgICAgICAgICAgICAgICAgICB0cnVlID0gIlREIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIGZhbHNlID0gIm5vVEQiKSwNCiAgICAjIENvbnZlcnRpbmcgZHJpdmVfZW5kIHRvIGEgZmFjdG9yIGFuZCBvcmRlcmluZyB0aGUgZ3JvdXBzIGFzIHN1Y2Nlc3MgdGhlbiBmYWlsdXJlDQogICAgZHJpdmVfZW5kID0gZmFjdG9yKGRyaXZlX2VuZCwNCiAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiVEQiLCAibm9URCIpKQ0KICApDQpgYGANCg0KTmV4dCwgbGV0J3MgZGlzcGxheSB0aGUgcmVzdWx0cyBpbiBhIHR3by13YXkgdGFibGUgdXNpbmcgYHh0YWJzKClgIA0KDQpgYGB7ciBkcml2ZV9mcmVxfQ0KIyBEaXNwbGF5aW5nIGEgdHdvLXdheSB0YWJsZSB1c2luZyB4dGFicygpDQpkcml2ZV9mcmVxIDwtIA0KICB4dGFicyhmb3JtdWxhID0gfiBkcml2ZV9zdGFydCArIGRyaXZlX2VuZCwgZGF0YSA9IGRyaXZlczIpDQoNCiMgVGhlIGFkZG1hcmdpbnMoKSBmdW5jdGlvbiB3aWxsIGFkZCB0aGUgbWFyZ2lucyB0byB0aGUgdGFibGUNCmRyaXZlX2ZyZXEgfD4gDQogIGFkZG1hcmdpbnMoKSANCmBgYA0KDQoNCkFuZCBjb252ZXJ0aW5nIHRoZSB0YWJsZSBmcm9tIGNvdW50cyB0byBjb25kaXRpb25hbCBwcm9wb3J0aW9ucyB1c2luZyBgcHJvcC50YWJsZShtYXJnaW4gPSAiZHJpdmVfc3RhcnQiKWANCg0KYGBge3IgZHJpdmVfcHJvcH0NCmRyaXZlX2ZyZXEgfD4gDQogIHByb3AudGFibGUobWFyZ2luID0gImRyaXZlX3N0YXJ0IikgfD4gDQogIA0KICByb3VuZChkaWdpdHMgPSAzKQ0KDQpgYGANCg0KTGV0J3MgY3JlYXRlIGEgYmFyIGNoYXJ0IHRvIGNvbXBhcmUgdGhlIHByb2JhYmlsaXR5IG9mIGEgdG91Y2hkb3duIGJldHdlZW4gdGhlIHR3byBncm91cHM6DQoNCmBgYHtyIGJhcl9jaGFydH0NCmRyaXZlX2ZyZXEgfD4gDQogICMgQ2FsY3VsYXRlIHRoZSBjb25kaXRpb25hbCBwcm9wb3J0aW9ucw0KICBwcm9wLnRhYmxlKG1hcmdpbiA9ICJkcml2ZV9zdGFydCIpIHw+IA0KICAjIENvbnZlcnQgdGhlIHRhYmxlIHRvIGEgZGF0YSBmcmFtZSB0byBiZSB1c2VkIGJ5IGdncGxvdCgpDQogIGRhdGEuZnJhbWUoKSB8PiANCiAgIyBSZW5hbWUgRnJlcSB0byBwcm9wDQogIHJlbmFtZShwcm9wID0gRnJlcSkgfD4gDQogIA0KICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gZHJpdmVfc3RhcnQsDQogICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBkcml2ZV9lbmQsDQogICAgICAgICAgICAgICAgICAgICAgIHkgPSBwcm9wKSkgKyANCiAgDQogIGdlb21fY29sKHdpZHRoID0gMC41KSArIA0KICANCiAgbGFicyh5ID0gIlByb3BvcnRpb24iLA0KICAgICAgIHggPSAiSG93IERyaXZlIEJlZ2FuIiwNCiAgICAgICBmaWxsID0gIkRyaXZlIFxuUmVzdWx0IikgKyANCiAgDQogIHRoZW1lX3Rlc3QoKSArIA0KICANCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCwgMCwgMC4wNSkpICsgDQogIA0KICBzY2FsZV9maWxsX21hbnVhbChsYWJlbHMgPSBjKCJUb3VjaGRvd24iLCAiTm8gVG91Y2hkb3duIiksDQogICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IGMoInN0ZWVsYmx1ZSIsICJkYXJrb3JhbmdlIikpDQoNCg0KYGBgDQoNClRoZXJlIGFyZSBzb21lIGRpZmZlcmVuY2VzLCBidXQgaXQgaXNuJ3QgYSB2ZXJ5IG5vdGljZWFibGUgZGlmZmVyZW5jZS4gDQoNCg0KDQoNCiMjIFJpc2sgRGlmZmVyZW5jZTogJHBfMSAtIHBfMiQgDQoNClRoZSBiYXNpYyB0ZXN0IGZvciBjb21wYXJpbmcgInJpc2tzIiBpcyBieSB1c2luZyB0aGUgcmlzayBkaWZmZXJlbmNlOg0KDQokJFAoWSA9IDF8WCA9IDEpIC0gUChZID0gMXxYID0gMikgPSBccGlfMSAtIFxwaV8yJCQNCg0Kd2hpY2ggaXMgdGhlIGRpZmZlcmVuY2UgaW4gdGhlICJzdWNjZXNzIiByYXRlIG9mIHRoZSByZXNwb25zZSB2YXJpYWJsZSBiZXR3ZWVuIHR3byBncm91cHMgb2YgdGhlIGV4cGxhbmF0b3J5IHZhcmlhYmxlOg0KDQotIDF8MSA9IFN1Y2Nlc3MgZ2l2ZW4gaW4gZ3JvdXAgMSBvZiB0aGUgZXhwbGFuYXRvcnkgdmFyaWFibGUNCi0gMXwyID0gU3VjY2VzcyBnaXZlbiBpbiBncm91cCAyIG9mIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZQ0KDQpPdXIgYmVzdCBlc3RpbWF0ZSBvZiB0aGUgcmlzayBkaWZmZXJlbmNlIGlzOg0KDQokJHBfezF9IC0gcF97Mn0gPSBcZnJhY3tuX3sxMX19e25fezFcYnVsbGV0fX0gLSBcZnJhY3tuX3syMX19e25fezJcYnVsbGV0fX0kJA0KDQpMZXQncyB1c2UgYHByb3BfdGVzdCgpYCBmcm9tIHRoZSBgcnN0YXRpeGAgcGFja2FnZSBhZ2FpbiB0byBjYWxjdWxhdGUgdGhlIHJpc2sgZGlmZmVyZW5jZSwgcC12YWx1ZSwgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWwuIFRoZSBhcmd1bWVudHMgZm9yIDIgYmluYXJ5IHZhcmlhYmxlcyBhcmU6DQoNCi0gYHggPSBgIGEgdGFibGUgb2YgY291bnRzIHdpdGggMXN0IGNvbHVtbiA9IHN1Y2Nlc3MgYW5kIDJuZCBjb2x1bW4gPSBmYWlsdXJlcw0KLSBgZGV0YWlsZWQgPSBUYCB0byByZXBvcnQgdGhlIGluZGl2aWR1YWwgcHJvcG9ydGlvbnMgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWwNCg0KYGBge3IgcHJvcF90ZXN0fQ0KcnN0YXRpeDo6cHJvcF90ZXN0KHggPSBkcml2ZV9mcmVxLA0KICAgICAgICAgICAgICAgICAgIGRldGFpbGVkID0gVCkNCmBgYA0KDQpMZXQncyBpbXByb3ZlIHRoZSBuYW1lcyBhbmQgYWRkIHRoZSByaXNrIGRpZmZlcmVuY2UgdG8gdGhlIHJlc3VsdHMNCg0KYGBge3IgaW1wcm92ZWRfcHJvcF90ZXN0fQ0Kcmlza19kaWZmX3Jlc3VsdHMgPC0gDQogIHJzdGF0aXg6OnByb3BfdGVzdCgNCiAgICB4ID0gZHJpdmVfZnJlcSwNCiAgICBkZXRhaWxlZCA9IFQNCiAgKSB8PiANCiAgIyBSZW5hbWluZyBuMSBhbmQgbjIgdG8gdGhlaXIgcmVzcGVjdGl2ZSBncm91cCBuYW1lcw0KICByZW5hbWUoDQogICAgdHVybm92ZXJfbiA9IG4xLA0KICAgIGtpY2tfbiA9IG4yLA0KICAgIHR1cm5vdmVyX3AgPSBlc3RpbWF0ZTEsDQogICAga2lja19wID0gZXN0aW1hdGUyLA0KICAgIHRlc3Rfc3RhdCA9IHN0YXRpc3RpYywNCiAgICBwX3ZhbCA9IHANCiAgKSB8PiANCiAgDQogICMgQ2FsY3VsYXRpbmcgdGhlIHJpc2sgZGlmZmVyZW5jZQ0KICBtdXRhdGUocmlza19kaWZmID0gdHVybm92ZXJfcCAtIGtpY2tfcCkgfD4gDQogIA0KICAjIFBpY2tpbmcgd2l0aCBjb2x1bW5zIHRvIGRpc3BsYXk6DQogIGRwbHlyOjpzZWxlY3QoDQogICAgbiwgDQogICAgdHVybm92ZXJfbiwgDQogICAga2lja19uLCANCiAgICB0dXJub3Zlcl9wLCANCiAgICBraWNrX3AsIA0KICAgIHJpc2tfZGlmZiwgDQogICAgdGVzdF9zdGF0LCANCiAgICBwX3ZhbCwgDQogICAgY29uZi5sb3csIA0KICAgIGNvbmYuaGlnaA0KICApDQoNCg0Kcmlza19kaWZmX3Jlc3VsdHMgfD4gDQogIHNpZ25pZihkaWdpdHMgPSAzKQ0KYGBgDQoNCkZyb20gb3VyIHJlc3VsdHMsIHdlIGNhbiBzZWUgdGhhdCB0aGVyZSBpcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBpbiBob3cgb2Z0ZW4gZHJpdmVzIGVuZCBpbiB0b3VjaGRvd25zIGRlcGVuZGluZyBpZiB0aGV5IHN0YXJ0IGZyb20gYSB0dXJub3ZlciBvciBhIGtpY2suDQoNCldlIGNhbiBiZSA5NSUgY29uZmlkZW5jZSB0aGF0IGRyaXZlcyB0aGF0IHN0YXJ0IGZyb20gYSB0dXJub3ZlciBhcmUgMy4zJSB0byAxMC4xJSBtb3JlIGxpa2VseSB0byBlbmQgaW4gYSB0b3VjaGRvd24gdGhhbiBkcml2ZXMgdGhhdCBzdGFydCBmcm9tIGEga2lja29mZiBvciBhIHB1bnQNCg0KDQojIyBSaXNrIFJhdGlvDQoNCg0KQW4gYWx0ZXJuYXRpdmUgdG8gcmlzayBkaWZmZXJlbmNlIGlzIHJpc2sgcmF0aW86DQoNCiQkUlIgPSBcZnJhY3tQKFkgPSAxfFggPSAxKX17UChZID0gMXxYID0gMil9ID0gXGZyYWN7XHBpX3sxfX17XHBpX3syfX0kJA0KDQpUaGUgcHJvYmFiaWxpdHkgb2Ygc3VjY2VzcyBpbiBncm91cCAxIG92ZXIgdGhlIHByb2JhYmlsaXR5IG9mIHN1Y2Nlc3Mgb2YgZ3JvdXAgMg0KDQoNCg0KIyMjIEZvcm11bGE6IExvZyBSZWxhdGl2ZSBSaXNrDQoNCkh5cG90aGVzaXMgdGVzdHMgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFyZSBkb25lIHVzaW5nIHRoZSBuYXR1cmFsIGxvZyBvZiB0aGUgcmVsYXRpdmUgcmlzaywgJFxsbiBSJCwgc2luY2UgaXQgaXMgc3ltbWV0cmljIGFyb3VuZCAwIGFuZCB3aWxsIGZvbGxvdyBhIE5vcm1hbCBkaXN0cmlidXRpb24gaWYgdGhlIHNhbXBsZSBzaXplIGlzIGxhcmdlIGVub3VnaCAoYWxsICRuX3tpan0gXGdlIDEwJCBpcyB0aGUgcnVsZSBvZiB0aHVtYikNCg0KVGhlIFdhbGQgc3RhbmRhcmQgZXJyb3IgZm9yIHRoZSBlc3RpbWF0ZWQgbG9nIHJlbGF0aXZlIHJpc2sgaXM6DQoNCiQkU0UoXGxuIFx3aWRlaGF0e1JSfSkgPSBcc3FydHtcZnJhY3sxfXtuX3sxMX19IC0gXGZyYWN7MX17bl97MVxidWxsZXR9fSArIFxmcmFjezF9e25fezIxfX0gLSBcZnJhY3sxfXtuX3syXGJ1bGxldH19fSAkJA0KDQp3aGVyZSANCg0KLSAkbl97MTF9JCBhbmQgJG5fezIxfSQgYXJlIHRoZSBjb3VudHMgb2Ygc3VjY2Vzc2VzIGZvciBncm91cHMgMSBhbmQgMiwgcmVzcGVjdGl2ZWx5DQoNCi0gJG5fezFcYnVsbGV0fSQgYW5kICRuX3syXGJ1bGxldH0kIGFyZSB0aGUgdG90YWwgc2FtcGxlIHNpemVzIG9mIGdyb3VwcyAxIGFuZCAyLCByZXNwZWN0aXZlbHkgDQoNCiMjIyMgSHlwb3RoZXNpcyBUZXN0DQoNCk91ciBudWxsIGh5cG90aGVzaXMgaXMgdGhhdCB0aGVyZSBpcyBubyBhc3NvY2lhdGlvbiBiZXR3ZWVuIFkgYW5kIFguIA0KDQokJFJSID0gMSBcdGV4dHJteyAgb3IgIH0gICAgXGxuIFJSID0gMCQkDQoNCkluIG91ciBjb250ZXh0LCB0aGUgcHJvYmFiaWxpdHkgb2YgYSBkcml2ZSBlbmRzIGluIGEgdG91Y2hkb3duIGlzIHRoZSBzYW1lIGlmIHRoZSBkcml2ZSBzdGFydHMgYXMgYSByZXN1bHQgb2YgYSB0dXJub3ZlciBvciBhIGtpY2sNCg0KVGhlIHRlc3Qgc3RhdGlzdGljIGlzOg0KDQokJHogPSBcZnJhY3tcbG4gXHdpZGVoYXR7UlJ9fXtcc3FydHtcZnJhY3sxfXtuX3sxMX19IC0gXGZyYWN7MX17bl97MVxidWxsZXR9fSArIFxmcmFjezF9e25fezIxfX0gLSBcZnJhY3sxfXtuX3syXGJ1bGxldH19fX0kJA0KDQojIyMjIENvbmZpZGVuY2UgaW50ZXJ2YWwNCg0KVGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9ybXVsYSB1c2VzIHRoZSBsb2cgcmlzayByYXRpbyBhbmQgdGhlbiBjb252ZXJ0cyB0aGUgcmVzdWx0cyBiYWNrIGJ5IGNhbGN1bGF0aW5nIHRoZSBleHBvbmVudGlhdGlvbiBvZiB0aGUgZW5kIHBvaW50cy4NCg0KVGhlIGNvbmZpZGVuY2UgZm9ybXVsYSBmb3IgJFxsbiBSJCBpczoNCg0KJCRcbG57XHdpZGVoYXR7UlJ9fSBcICBccG0gXCB6XiogXHNxcnR7XGZyYWN7MX17bl97MTF9fSAtIFxmcmFjezF9e25fezFcYnVsbGV0fX0gKyBcZnJhY3sxfXtuX3syMX19IC0gXGZyYWN7MX17bl97MlxidWxsZXR9fX0kJA0KDQpXaGlsZSB5b3UgbWF5IGJlIGV4cGVjdGVkIHRvIGNhbGN1bGF0ZSB0aGUgQ29uZmlkZW5jZSBJbnRlcnZhbCBvciBoeXBvdGhlc2lzIHRlc3QgYnkgaGFuZCBvbiBleGFtcywgd2Ugd29uJ3QgZG8gdGhhdCBpbiAqKlIqKi4gV2UnbGwgdXNlIGEgY2FubmVkIGZ1bmN0aW9uIGZvciBvdXIgcHVycG9zZXMhDQoNClxcDQoNCg0KDQojIyMgUmVsYXRpdmUgcmlzayB1c2luZyB0aGUgYHJpc2tyYXRpbygpYCBmdW5jdGlvbg0KDQpXZSBjYW4gY29tcHV0ZSB0aGUgcmVsYXRpdmUgcmlzayB1c2luZyB0aGUgYHJpc2tyYXRpbygpYCBmdW5jdGlvbiBpbiB0aGUgYGVwaXRvb2xzYCBwYWNrYWdlLiBUaGUgYXJndW1lbnRzIGFyZToNCg0KMSkgYHggPSBgIGEgMngyIHRhYmxlIHdpdGg6DQogICAgLSBjb2x1bW4gb3JkZXIgb2YgRmFpbHVyZS9TdWNjZXNzIA0KICAgIC0gcm93IG9yZGVyIG9mIGJhc2VsaW5lIGdyb3VwL2ludGVyZXN0IGdyb3VwDQoNCjIpIGBjb25mLmxldmVsID0gYCB0aGUgY29uZmlkZW5jZSBsZXZlbA0KDQozKSBgdmVyYm9zZSA9IFRgIGlmIHlvdSB3YW50IGFkZGl0aW9uYWwgcmVzdWx0cyByZXR1cm5lZA0KDQoNCioqTm90ZToqKiBgcmlza3JhdGlvKClgIHdhbnRzIHRoZSByb3cgYW5kIGNvbHVtbiBvcmRlciBzd2FwcGVkIGZyb20gYHByb3BfdGVzdCgpYC4gV2UgY2FuIHN3YXAgdGhlIG9yZGVyIG9mIHRoZSByb3dzIGFuZCBjb2x1bW5zIHVzaW5nIHRoZSBhZGRpdGlvbmFsIGFyZ3VtZW50IGByZXYgPSBib3RoYA0KDQpgYGB7ciByZWxfcmlza30NCnBhY21hbjo6cF9sb2FkKGVwaXRvb2xzKQ0KDQpkcml2ZXNfcnIgPC0gDQogIHJpc2tyYXRpbygNCiAgICB4ID0gZHJpdmVfZnJlcSwNCiAgICB2ZXJib3NlID0gRiwNCiAgICBjb25mLmxldmVsID0gMC45NSwNCiAgICByZXYgPSAiYm90aCINCiAgKQ0KDQpkcml2ZXNfcnINCmBgYA0KDQpgcmlza3JhdGlvKClgIGhhcyBhIGxvdCBvZiBvdXRwdXQuIFlvdSBjYW4gc3BlY2lmeSBhIHNwZWNpZmljIHF1YW50aXR5IGJ5IHVzaW5nIGAkYCBmb2xsb3dlZCBieSB0aGUgbmFtZWQgdGFibGUgeW91IHdhbnQgdG8gZGlzcGxheToNCg0KQ29uZmlkZW5jZSBpbnRlcnZhbDogYCRtZWFzdXJlYA0KDQpgYGB7ciByaXNrcmF0aW9fQ0l9DQojIFJpc2sgcmF0aW8gZXN0aW1hdGUgYW5kIENvbmZpZGVuY2UgaW50ZXJ2YWwgZnJvbSAkbWVhc3VyZQ0KZGF0YS5mcmFtZShkcml2ZXNfcnIkbWVhc3VyZSkNCmBgYA0KDQpUaGUgZmlyc3Qgcm93IGlzIHRoZSByZWZlcmVuY2UgZ3JvdXAgKCJraWNrIikgYW5kIHRoZSBwcm9jZWVkaW5nIHJvd3MgYXJlIHRoZSByaXNrIHJhdGlvIG9mIHRoYXQgZ3JvdXAgdnMgdGhlIHJlZmVyZW5jZSBncm91cC4gDQoNCldlIGNhbiBpbnRlcnByZXQgdGhlIGVzdGltYXRlIGFzIA0KDQoqKiJXZSBlc3RpbWF0ZSBkcml2ZXMgYXJlIDEuMjkgdGltZXMgbW9yZSBsaWtlbHkgdG8gcmVzdWx0IGluIGEgdG91Y2hkb3duIGlmIHRoZXkgc3RhcnQgYnkgYSB0dXJub3ZlciBjb21wYXJlZCB0byBhIHB1bnQgb3Iga2lja29mZiIqKg0KDQpMaWtld2lzZSwgd2UgY2FuIGludGVycHJldCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBhcyANCg0KKioiV2UgYXJlIDk1JSBjb25maWRlbnQgdGhhdCBkcml2ZXMgdGhhdCBiZWdpbiBmcm9tIGEgdHVybm92ZXIgYXJlIDEuMTUgdG8gMS40NSB0aW1lcyBtb3JlIGxpa2VseSB0byByZXN1bHQgaW4gYSB0b3VjaGRvd24gdGhhdCBkcml2ZXMgdGhhdCBiZWdpbiBmcm9tIGEgcHVudCBvciBraWNrb2ZmIioqDQoNCg0KDQoNCkZvciB0aGUgcC12YWx1ZSBvZiBhIGh5cG90aGVzaXMgdGVzdCwgd2UgdXNlIGAkcC52YWx1ZWANCg0KYGBge3Igcmlza3JhdGlvX0hUfQ0KIyBIeXBvdGhlc2lzIHRlc3QgcmVzdWx0cyB1c2luZyAkcC52YWx1ZQ0KZGF0YS5mcmFtZShkcml2ZXNfcnIkcC52YWx1ZSkNCg0KYGBgDQoNCm5vdGUgdGhhdCB0aGVyZSBhcmUgMyBkaWZmZXJlbnQgcC12YWx1ZXMuIFdlJ2xsIGxvb2sgYXQgYG1pZHAuZXhhY3RgIGFuZCBgZmlzaGVyLmV4YWN0YCBzb29uLCBidXQgdGhlIGBjaGkuc3F1YXJlYCBwLXZhbHVlIGlzIHRoZSBvbmUgdGhhdCB1c2VzIHRoZSBOb3JtYWwgYXBwcm94aW1hdGlvbiBvZiAkXGxuXGhhdHtSfSQNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==