Learning Objectives


Upon completing today’s lab activity, students should be able to do the following using R and RStudio:

  1. Perform Bootstrapping procedure to compute p-values and confidence intervals for one proportion.


library(tidyverse)
library(openintro)
library(dplyr)
library(infer)


Inference for One Proportion


Null and Alternative Hypothesis

The problem shown below was taken and slightly modified from your textbook OpenIntro: Introduction to Modern Statistics Section 16.4.

Consider the research study described below.

A Kaiser Family Foundation poll for a random sample of US adults in 2019 found that 79% of Democrats, 55% of Independents, and 24% of Republicans supported a generic “National Health Plan.” There were 347 Democrats, 298 Republicans, and 617 Independents surveyed. K. F. Foundation 2019

Claim: A majority of independents support the National Health Plan (NHP).

The Null and Alternative Hypothesis:

  • Null Hypothesis Neither a majority nor minority of independents support the NHP.
    \[H_0: p = 0.50\]

  • Alternative Hypothesis A majority or minority of independents support the NHP. A majority means that more than 50% of independents support NHP. \[H_A: p \ne 0.50\]

Point-Estimate: \(\hat{p} = 0.55\)

Null Value: \(p_0 = 0.50\)

Conditions:

  • Independence: The sample is randomly sampled because it says “random sample of US adults in 2019”, meaning our observation is just a small fraction of all US adults.

  • success-failure: Among independents, \(617(0.55) = 340\) support and \(617(1-0.55) = 277\) don’t support. Both are greater than 10.

Define Numbers

n <- 617 # number of trials/samples
N <- 1000 # number of bootstrapped simulations
p_hat <- 0.55 # point estimate
p_0 <- 0.50 # null value

Using Parametric Bootstrapping Method

Perform Bootstrapping Procedure.

set.seed(42)
ind_sim_dist <- tibble(stat = rbinom(N, n, p_0)/n)
ind_n_sim <- ind_sim_dist %>%
  filter(stat > p_hat) %>%
  nrow()

Compute p-value using the Bootstrapped Simulations.

ind_p_val <- 2*(round(ind_n_sim / N, 4))
ind_p_val
## [1] 0.01

Compute 95% confidence interval using the Bootstrapped Simulations.

set.seed(42)
ind_sim_dist_phat <- tibble(stat = rbinom(N, n, p_hat)/n)
ci_level <- 0.95 # confidence level

Way 1: Percentile Method

\[\text{95% CI} = (2.5th \text{ quantile}, 97.5th \text{ quantile}) \]

left_quantile <- (1-ci_level)/2
right_quantile <- ci_level + left_quantile
ci_interval_perc_boot <- quantile(ind_sim_dist_phat$stat, c(left_quantile,right_quantile))
ci_interval_perc_boot
##      2.5%     97.5% 
## 0.5121556 0.5867099

Using the percentile method, we are 95% confident that the true population proportion is between 0.4619 and 0.5380.

Way 2: Standard Error Method

\[\text{95% CI} = (\hat{p}-z^* SE, \hat{p}+z^* SE)\] where SE is the standard error and the \(z^*\) is the z-score for the standard normal distribution corresponding to the 95% confidence interval.

standard_deviation <- sd(ind_sim_dist_phat$stat)
z <- qnorm(0.975,0,1)
ci_interval_se_boot <- c(p_hat-z*standard_deviation,p_hat+z*standard_deviation)
ci_interval_se_boot
## [1] 0.5117514 0.5882486

Using the standard error method, we are 95% confident that the true population proportion is between 0.5113 and 0.5888.

Using prop.test Function

The prop.test function is an R built-in function for inference for proportions.

prop.test(n*p_hat, n, p = p_0, conf.level = ci_level, alternative = c("two.sided"))
## 
##  1-sample proportions test with continuity correction
## 
## data:  n * p_hat out of n, null probability p_0
## X-squared = 5.9716, df = 1, p-value = 0.01454
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
##  0.5097445 0.5896240
## sample estimates:
##    p 
## 0.55

The output shows that the p-value is 0.01454 and the 95% CI is (0.5097,0.5896).

Using the infer Package


# actual data for demonstration purposes
data_example <- tibble(response = c(rep("yes", 340), rep("no", 277)))
boot_dist_yes <- data_example %>%
  # specify the response and the "success"
  specify(response = response, success = "yes") %>%
  # define the null hypothesis and the null value
  hypothesise(null = "point", p = p_0) %>%
  # generate samples for the null distribution
  generate(reps = 1000, type = "draw") %>%
  # calculate the proportions for the null distribution
  calculate(stat = "prop")
# compute p-value using a two-sided alterntive hypothesis
p_value <- boot_dist_yes %>% get_pvalue(obs_stat = p_hat, direction = "two-sided")
p_value
## # A tibble: 1 × 1
##   p_value
##     <dbl>
## 1   0.004
boot_dist_pe <- data_example %>%
  # specify the response and the "success"
  specify(response = response, success = "yes") %>%
  # generate bootstrap samples
  generate(reps = 1000, type = "bootstrap") %>%
  # calculate the proportions for the point-estimate distribution
  calculate(stat = "prop")
# compute 95% confidence interval using the percentile method
ci_interval_perc_boot <- boot_dist_pe %>% get_confidence_interval(level = 0.95, type = "percentile")
ci_interval_perc_boot
## # A tibble: 1 × 2
##   lower_ci upper_ci
##      <dbl>    <dbl>
## 1    0.509    0.590
# compute 95% confidence interval using the standard error method
ci_interval_se_boot <- boot_dist_pe %>% get_confidence_interval(level = 0.95, type = "se", point_estimate = p_hat)
ci_interval_se_boot
## # A tibble: 1 × 2
##   lower_ci upper_ci
##      <dbl>    <dbl>
## 1    0.510    0.590


Mini Activities


Is college worth it?

Among a simple random sample of 331 American adults who do not have a four-year college degree and are not currently enrolled in school, 48% said they decided not to go to college because they could not afford school. Pew Research Center 2011

  • A newspaper article states that only a minority of the Americans who decide not to go to college do so because they cannot afford it and uses the point estimate from this survey as evidence. Conduct a hypothesis test to determine if these data provide strong evidence supporting this statement.
  1. Perform a parameteric bootstrap simulations to compute the p-value and 95% confidence interval.
  2. Use the theoretical method to compute the p-value and 95% confidence interval. (You can refer to the textbook or lecture slides for the formulas.)
  3. Compare the values computed using the bootstrapping method and the theoretical method.


LS0tCnRpdGxlOiAiNiAtIEluZmVyZW5jZSBmb3IgUHJvcG9ydGlvbnMiCmF1dGhvcjogIkFsZXggSm9obiBRdWlqYW5vIgpkYXRlOiAiMTEvMDkvMjAyMSIKb3V0cHV0OiBvcGVuaW50cm86OmxhYl9yZXBvcnQKLS0tCgojIyAqKkxlYXJuaW5nIE9iamVjdGl2ZXMqKgoKPGJyPgoKVXBvbiBjb21wbGV0aW5nIHRvZGF5J3MgbGFiIGFjdGl2aXR5LCBzdHVkZW50cyBzaG91bGQgYmUgYWJsZSB0byBkbyB0aGUgZm9sbG93aW5nIHVzaW5nIFIgYW5kIFJTdHVkaW86CiAgCiAgMS4gUGVyZm9ybSBCb290c3RyYXBwaW5nIHByb2NlZHVyZSB0byBjb21wdXRlIHAtdmFsdWVzIGFuZCBjb25maWRlbmNlIGludGVydmFscyBmb3Igb25lIHByb3BvcnRpb24uCgo8YnI+CgpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG9wZW5pbnRybykKbGlicmFyeShkcGx5cikKbGlicmFyeShpbmZlcikKYGBgCgo8YnI+CgojIyAqKkluZmVyZW5jZSBmb3IgT25lIFByb3BvcnRpb24qKgoKPGJyPgoKIyMjIE51bGwgYW5kIEFsdGVybmF0aXZlIEh5cG90aGVzaXMKClRoZSBwcm9ibGVtIHNob3duIGJlbG93IHdhcyB0YWtlbiBhbmQgc2xpZ2h0bHkgbW9kaWZpZWQgZnJvbSB5b3VyIHRleHRib29rIFtPcGVuSW50cm86IEludHJvZHVjdGlvbiB0byBNb2Rlcm4gU3RhdGlzdGljcyBTZWN0aW9uIDE2LjRdKGh0dHBzOi8vb3BlbmludHJvLWltcy5uZXRsaWZ5LmFwcC9pbmZlcmVuY2Utb25lLXByb3AuaHRtbCNjaHAxNi1leGVyY2lzZXMpe3RhcmdldD0iX2JsYW5rIn0uCgpDb25zaWRlciB0aGUgcmVzZWFyY2ggc3R1ZHkgZGVzY3JpYmVkIGJlbG93LgoKPiBBIEthaXNlciBGYW1pbHkgRm91bmRhdGlvbiBwb2xsIGZvciBhIHJhbmRvbSBzYW1wbGUgb2YgVVMgYWR1bHRzIGluIDIwMTkgZm91bmQgdGhhdCA3OSUgb2YgRGVtb2NyYXRzLCA1NSUgb2YgSW5kZXBlbmRlbnRzLCBhbmQgMjQlIG9mIFJlcHVibGljYW5zIHN1cHBvcnRlZCBhIGdlbmVyaWMg4oCcTmF0aW9uYWwgSGVhbHRoIFBsYW4u4oCdIFRoZXJlIHdlcmUgMzQ3IERlbW9jcmF0cywgMjk4IFJlcHVibGljYW5zLCBhbmQgNjE3IEluZGVwZW5kZW50cyBzdXJ2ZXllZC4gW0suIEYuIEZvdW5kYXRpb24gMjAxOV0oaHR0cHM6Ly93d3cua2ZmLm9yZy9oZWFsdGgtcmVmb3JtL3BvbGwtZmluZGluZy9rZmYtaGVhbHRoLXRyYWNraW5nLXBvbGwtamFudWFyeS0yMDE5Lyl7dGFyZ2V0PSJfYmxhbmsifQoKKipDbGFpbToqKiBBIG1ham9yaXR5IG9mIGluZGVwZW5kZW50cyBzdXBwb3J0IHRoZSBOYXRpb25hbCBIZWFsdGggUGxhbiAoTkhQKS4KCioqVGhlIE51bGwgYW5kIEFsdGVybmF0aXZlIEh5cG90aGVzaXM6KioKCiAgKiAqKk51bGwgSHlwb3RoZXNpcyoqIE5laXRoZXIgYSBtYWpvcml0eSBub3IgbWlub3JpdHkgb2YgaW5kZXBlbmRlbnRzIHN1cHBvcnQgdGhlIE5IUC4gPGJyPgogICAgJCRIXzA6IHAgPSAwLjUwJCQKICAgIAogICogKipBbHRlcm5hdGl2ZSBIeXBvdGhlc2lzKiogQSBtYWpvcml0eSBvciBtaW5vcml0eSBvZiBpbmRlcGVuZGVudHMgc3VwcG9ydCB0aGUgTkhQLiBBIG1ham9yaXR5IG1lYW5zIHRoYXQgbW9yZSB0aGFuIDUwXCUgb2YgaW5kZXBlbmRlbnRzIHN1cHBvcnQgTkhQLgogICAgJCRIX0E6IHAgXG5lIDAuNTAkJAogICAgCioqUG9pbnQtRXN0aW1hdGU6KiogJFxoYXR7cH0gPSAwLjU1JAoKKipOdWxsIFZhbHVlOiAqKiAkcF8wID0gMC41MCQKCioqQ29uZGl0aW9uczoqKgoKICAqICpJbmRlcGVuZGVuY2U6KiBUaGUgc2FtcGxlIGlzIHJhbmRvbWx5IHNhbXBsZWQgYmVjYXVzZSBpdCBzYXlzICJyYW5kb20gc2FtcGxlIG9mIFVTIGFkdWx0cyBpbiAyMDE5IiwgbWVhbmluZyBvdXIgb2JzZXJ2YXRpb24gaXMganVzdCBhIHNtYWxsIGZyYWN0aW9uIG9mIGFsbCBVUyBhZHVsdHMuCiAgCiAgKiAqc3VjY2Vzcy1mYWlsdXJlOiogQW1vbmcgaW5kZXBlbmRlbnRzLCAkNjE3KDAuNTUpID0gMzQwJCBzdXBwb3J0IGFuZCAkNjE3KDEtMC41NSkgPSAyNzckIGRvbid0IHN1cHBvcnQuIEJvdGggYXJlIGdyZWF0ZXIgdGhhbiAxMC4KICAgIAojIyMgRGVmaW5lIE51bWJlcnMKCmBgYHtyfQpuIDwtIDYxNyAjIG51bWJlciBvZiB0cmlhbHMvc2FtcGxlcwpOIDwtIDEwMDAgIyBudW1iZXIgb2YgYm9vdHN0cmFwcGVkIHNpbXVsYXRpb25zCnBfaGF0IDwtIDAuNTUgIyBwb2ludCBlc3RpbWF0ZQpwXzAgPC0gMC41MCAjIG51bGwgdmFsdWUKYGBgCgojIyMgVXNpbmcgUGFyYW1ldHJpYyBCb290c3RyYXBwaW5nIE1ldGhvZAoKUGVyZm9ybSBCb290c3RyYXBwaW5nIFByb2NlZHVyZS4KCmBgYHtyfQpzZXQuc2VlZCg0MikKaW5kX3NpbV9kaXN0IDwtIHRpYmJsZShzdGF0ID0gcmJpbm9tKE4sIG4sIHBfMCkvbikKaW5kX25fc2ltIDwtIGluZF9zaW1fZGlzdCAlPiUKICBmaWx0ZXIoc3RhdCA+IHBfaGF0KSAlPiUKICBucm93KCkKYGBgCgpDb21wdXRlIHAtdmFsdWUgdXNpbmcgdGhlIEJvb3RzdHJhcHBlZCBTaW11bGF0aW9ucy4KCmBgYHtyfQppbmRfcF92YWwgPC0gMioocm91bmQoaW5kX25fc2ltIC8gTiwgNCkpCmluZF9wX3ZhbApgYGAKCkNvbXB1dGUgOTVcJSBjb25maWRlbmNlIGludGVydmFsIHVzaW5nIHRoZSBCb290c3RyYXBwZWQgU2ltdWxhdGlvbnMuCgpgYGB7cn0Kc2V0LnNlZWQoNDIpCmluZF9zaW1fZGlzdF9waGF0IDwtIHRpYmJsZShzdGF0ID0gcmJpbm9tKE4sIG4sIHBfaGF0KS9uKQpgYGAKCmBgYHtyfQpjaV9sZXZlbCA8LSAwLjk1ICMgY29uZmlkZW5jZSBsZXZlbApgYGAKCipXYXkgMToqIFBlcmNlbnRpbGUgTWV0aG9kCgokJFx0ZXh0ezk1JSBDSX0gPSAoMi41dGggXHRleHR7IHF1YW50aWxlfSwgOTcuNXRoIFx0ZXh0eyBxdWFudGlsZX0pICQkCgpgYGB7cn0KbGVmdF9xdWFudGlsZSA8LSAoMS1jaV9sZXZlbCkvMgpyaWdodF9xdWFudGlsZSA8LSBjaV9sZXZlbCArIGxlZnRfcXVhbnRpbGUKY2lfaW50ZXJ2YWxfcGVyY19ib290IDwtIHF1YW50aWxlKGluZF9zaW1fZGlzdF9waGF0JHN0YXQsIGMobGVmdF9xdWFudGlsZSxyaWdodF9xdWFudGlsZSkpCmNpX2ludGVydmFsX3BlcmNfYm9vdApgYGAKClVzaW5nIHRoZSBwZXJjZW50aWxlIG1ldGhvZCwgd2UgYXJlIDk1XCUgY29uZmlkZW50IHRoYXQgdGhlIHRydWUgcG9wdWxhdGlvbiBwcm9wb3J0aW9uIGlzIGJldHdlZW4gMC40NjE5IGFuZCAwLjUzODAuCgoqV2F5IDI6KiBTdGFuZGFyZCBFcnJvciBNZXRob2QKCiQkXHRleHR7OTUlIENJfSA9IChcaGF0e3B9LXpeKiBTRSwgXGhhdHtwfSt6XiogU0UpJCQKd2hlcmUgU0UgaXMgdGhlIHN0YW5kYXJkIGVycm9yIGFuZCB0aGUgJHpeKiQgaXMgdGhlIHotc2NvcmUgZm9yIHRoZSBzdGFuZGFyZCBub3JtYWwgZGlzdHJpYnV0aW9uIGNvcnJlc3BvbmRpbmcgdG8gdGhlIDk1XCUgY29uZmlkZW5jZSBpbnRlcnZhbC4KCmBgYHtyfQpzdGFuZGFyZF9kZXZpYXRpb24gPC0gc2QoaW5kX3NpbV9kaXN0X3BoYXQkc3RhdCkKeiA8LSBxbm9ybSgwLjk3NSwwLDEpCmNpX2ludGVydmFsX3NlX2Jvb3QgPC0gYyhwX2hhdC16KnN0YW5kYXJkX2RldmlhdGlvbixwX2hhdCt6KnN0YW5kYXJkX2RldmlhdGlvbikKY2lfaW50ZXJ2YWxfc2VfYm9vdApgYGAKClVzaW5nIHRoZSBzdGFuZGFyZCBlcnJvciBtZXRob2QsIHdlIGFyZSA5NVwlIGNvbmZpZGVudCB0aGF0IHRoZSB0cnVlIHBvcHVsYXRpb24gcHJvcG9ydGlvbiBpcyBiZXR3ZWVuIDAuNTExMyBhbmQgMC41ODg4LgoKIyMjIFVzaW5nIGBwcm9wLnRlc3RgIEZ1bmN0aW9uCgpUaGUgYHByb3AudGVzdGAgZnVuY3Rpb24gaXMgYW4gUiBidWlsdC1pbiBmdW5jdGlvbiBmb3IgaW5mZXJlbmNlIGZvciBwcm9wb3J0aW9ucy4KCmBgYHtyfQpwcm9wLnRlc3QobipwX2hhdCwgbiwgcCA9IHBfMCwgY29uZi5sZXZlbCA9IGNpX2xldmVsLCBhbHRlcm5hdGl2ZSA9IGMoInR3by5zaWRlZCIpKQpgYGAKClRoZSBvdXRwdXQgc2hvd3MgdGhhdCB0aGUgcC12YWx1ZSBpcyAwLjAxNDU0IGFuZCB0aGUgOTVcJSBDSSBpcyAoMC41MDk3LDAuNTg5NikuCgojIyMgVXNpbmcgdGhlIGBpbmZlcmAgUGFja2FnZQoKPGJyPgoKYGBge3J9CiMgYWN0dWFsIGRhdGEgZm9yIGRlbW9uc3RyYXRpb24gcHVycG9zZXMKZGF0YV9leGFtcGxlIDwtIHRpYmJsZShyZXNwb25zZSA9IGMocmVwKCJ5ZXMiLCAzNDApLCByZXAoIm5vIiwgMjc3KSkpCmBgYAoKYGBge3J9CmJvb3RfZGlzdF95ZXMgPC0gZGF0YV9leGFtcGxlICU+JQogICMgc3BlY2lmeSB0aGUgcmVzcG9uc2UgYW5kIHRoZSAic3VjY2VzcyIKICBzcGVjaWZ5KHJlc3BvbnNlID0gcmVzcG9uc2UsIHN1Y2Nlc3MgPSAieWVzIikgJT4lCiAgIyBkZWZpbmUgdGhlIG51bGwgaHlwb3RoZXNpcyBhbmQgdGhlIG51bGwgdmFsdWUKICBoeXBvdGhlc2lzZShudWxsID0gInBvaW50IiwgcCA9IHBfMCkgJT4lCiAgIyBnZW5lcmF0ZSBzYW1wbGVzIGZvciB0aGUgbnVsbCBkaXN0cmlidXRpb24KICBnZW5lcmF0ZShyZXBzID0gMTAwMCwgdHlwZSA9ICJkcmF3IikgJT4lCiAgIyBjYWxjdWxhdGUgdGhlIHByb3BvcnRpb25zIGZvciB0aGUgbnVsbCBkaXN0cmlidXRpb24KICBjYWxjdWxhdGUoc3RhdCA9ICJwcm9wIikKYGBgCgpgYGB7cn0KIyBjb21wdXRlIHAtdmFsdWUgdXNpbmcgYSB0d28tc2lkZWQgYWx0ZXJudGl2ZSBoeXBvdGhlc2lzCnBfdmFsdWUgPC0gYm9vdF9kaXN0X3llcyAlPiUgZ2V0X3B2YWx1ZShvYnNfc3RhdCA9IHBfaGF0LCBkaXJlY3Rpb24gPSAidHdvLXNpZGVkIikKcF92YWx1ZQpgYGAKCmBgYHtyfQpib290X2Rpc3RfcGUgPC0gZGF0YV9leGFtcGxlICU+JQogICMgc3BlY2lmeSB0aGUgcmVzcG9uc2UgYW5kIHRoZSAic3VjY2VzcyIKICBzcGVjaWZ5KHJlc3BvbnNlID0gcmVzcG9uc2UsIHN1Y2Nlc3MgPSAieWVzIikgJT4lCiAgIyBnZW5lcmF0ZSBib290c3RyYXAgc2FtcGxlcwogIGdlbmVyYXRlKHJlcHMgPSAxMDAwLCB0eXBlID0gImJvb3RzdHJhcCIpICU+JQogICMgY2FsY3VsYXRlIHRoZSBwcm9wb3J0aW9ucyBmb3IgdGhlIHBvaW50LWVzdGltYXRlIGRpc3RyaWJ1dGlvbgogIGNhbGN1bGF0ZShzdGF0ID0gInByb3AiKQpgYGAKCmBgYHtyfQojIGNvbXB1dGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgdXNpbmcgdGhlIHBlcmNlbnRpbGUgbWV0aG9kCmNpX2ludGVydmFsX3BlcmNfYm9vdCA8LSBib290X2Rpc3RfcGUgJT4lIGdldF9jb25maWRlbmNlX2ludGVydmFsKGxldmVsID0gMC45NSwgdHlwZSA9ICJwZXJjZW50aWxlIikKY2lfaW50ZXJ2YWxfcGVyY19ib290CmBgYAoKYGBge3J9CiMgY29tcHV0ZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCB1c2luZyB0aGUgc3RhbmRhcmQgZXJyb3IgbWV0aG9kCmNpX2ludGVydmFsX3NlX2Jvb3QgPC0gYm9vdF9kaXN0X3BlICU+JSBnZXRfY29uZmlkZW5jZV9pbnRlcnZhbChsZXZlbCA9IDAuOTUsIHR5cGUgPSAic2UiLCBwb2ludF9lc3RpbWF0ZSA9IHBfaGF0KQpjaV9pbnRlcnZhbF9zZV9ib290CmBgYAoKPGJyPgoKIyMgKipNaW5pIEFjdGl2aXRpZXMqKgoKPGJyPgoKKipJcyBjb2xsZWdlIHdvcnRoIGl0PyoqCgo+IEFtb25nIGEgc2ltcGxlIHJhbmRvbSBzYW1wbGUgb2YgMzMxIEFtZXJpY2FuIGFkdWx0cyB3aG8gZG8gbm90IGhhdmUgYSBmb3VyLXllYXIgY29sbGVnZSBkZWdyZWUgYW5kIGFyZSBub3QgY3VycmVudGx5IGVucm9sbGVkIGluIHNjaG9vbCwgNDglIHNhaWQgdGhleSBkZWNpZGVkIG5vdCB0byBnbyB0byBjb2xsZWdlIGJlY2F1c2UgdGhleSBjb3VsZCBub3QgYWZmb3JkIHNjaG9vbC4gW1BldyBSZXNlYXJjaCBDZW50ZXIgMjAxMV0oaHR0cHM6Ly93d3cucGV3cmVzZWFyY2gub3JnL3NvY2lhbC10cmVuZHMvMjAxMS8wNS8xNS9pcy1jb2xsZWdlLXdvcnRoLWl0Lyl7dGFyZ2V0PSJfYmxhbmsifQoKICAqIEEgbmV3c3BhcGVyIGFydGljbGUgc3RhdGVzIHRoYXQgb25seSBhIG1pbm9yaXR5IG9mIHRoZSBBbWVyaWNhbnMgd2hvIGRlY2lkZSBub3QgdG8gZ28gdG8gY29sbGVnZSBkbyBzbyBiZWNhdXNlIHRoZXkgY2Fubm90IGFmZm9yZCBpdCBhbmQgdXNlcyB0aGUgcG9pbnQgZXN0aW1hdGUgZnJvbSB0aGlzIHN1cnZleSBhcyBldmlkZW5jZS4gQ29uZHVjdCBhIGh5cG90aGVzaXMgdGVzdCB0byBkZXRlcm1pbmUgaWYgdGhlc2UgZGF0YSBwcm92aWRlIHN0cm9uZyBldmlkZW5jZSBzdXBwb3J0aW5nIHRoaXMgc3RhdGVtZW50LgogIAogIDEuIFBlcmZvcm0gYSBwYXJhbWV0ZXJpYyBib290c3RyYXAgc2ltdWxhdGlvbnMgdG8gY29tcHV0ZSB0aGUgcC12YWx1ZSBhbmQgOTVcJSBjb25maWRlbmNlIGludGVydmFsLgogIDIuIFVzZSB0aGUgdGhlb3JldGljYWwgbWV0aG9kIHRvIGNvbXB1dGUgdGhlIHAtdmFsdWUgYW5kIDk1XCUgY29uZmlkZW5jZSBpbnRlcnZhbC4gKFlvdSBjYW4gcmVmZXIgdG8gdGhlIHRleHRib29rIG9yIGxlY3R1cmUgc2xpZGVzIGZvciB0aGUgZm9ybXVsYXMuKQogIDMuIENvbXBhcmUgdGhlIHZhbHVlcyBjb21wdXRlZCB1c2luZyB0aGUgYm9vdHN0cmFwcGluZyBtZXRob2QgYW5kIHRoZSB0aGVvcmV0aWNhbCBtZXRob2QuCgo8YnI+Cg==