Learning Objectives


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

  1. Using data to formulate a sampling distribution of an estimate.

  2. Perform the basics of randomization for hypothesis testing.


library(tidyverse)
library(openintro)
library(infer)
library(ggplot2)
library(gghighlight)


Case Study - Gender Discrimination

Load and preview gender_discrimination data which is part of the openintro package.

glimpse(gender_discrimination)
## Rows: 48
## Columns: 2
## $ gender   <fct> male, male, male, male, male, male, male, male, male, male, m…
## $ decision <fct> promoted, promoted, promoted, promoted, promoted, promoted, p…

The dataset have 48 rows and 2 columns. The variables are gender and decision. Both are categorical nominal variables. Next, we summarize the data.

Data Summarization

gender_discrimination_prop <- gender_discrimination %>%
  count(gender, decision) %>%
  group_by(gender) %>%
  mutate(prop = n / sum(n))
gender_discrimination_prop
## # A tibble: 4 × 4
## # Groups:   gender [2]
##   gender decision         n  prop
##   <fct>  <fct>        <int> <dbl>
## 1 male   promoted        21 0.875
## 2 male   not promoted     3 0.125
## 3 female promoted        14 0.583
## 4 female not promoted    10 0.417
p_male <- gender_discrimination_prop %>%
  filter(gender == "male", decision == "promoted") %>%
  pull(prop)

p_female <- gender_discrimination_prop %>%
  filter(gender == "female", decision == "promoted") %>%
  pull(prop)

p_diff <- p_male - p_female # difference in proportion
paste("Proportion of promoted males: ",p_male)
## [1] "Proportion of promoted males:  0.875"
paste("Proportion of promoted females: ",p_female)
## [1] "Proportion of promoted females:  0.583333333333333"
paste("Proportion difference: ",p_diff)
## [1] "Proportion difference:  0.291666666666667"

After summarizing the data, the difference in promotions can be identified using rates. That is, 0.5833333 (58.3333333%) of the women were promoted whereas 0.875 (87.5%) of the men were promoted. The important statistical question to ask after looking at the data is as follows: is it plausible to observe such a difference in proportions in a scenario where men and women are equally likely to be promoted?

All of the pieces of this code you’ve seen before, but let’s review them! First, we count the number of observations for each gender (male, female) and each decision (promoted, not) using the count() function. Next, we group these counts by gender, so that we can use mutate() to create a new variable that is the proportion of observations in each gender that received or didn’t receive a promotion.

We see in the results that 0.875 of males are promoted while 0.5833333 of females are promoted. The difference in proportion is 0.2916667.

Permutation

To help you understand the code used to create the randomization distribution, this section will walk you through the steps of the infer framework. In particular, you’ll see how differences in the generated replicates affect the calculated statistics.

For simplicity, we’ll keep our permutation to just 5 replicates – in reality we would want this value to be much larger.

In the code chunk below,

  • we start with our data frame: gender_discrimination,

  • then we specify our model where decision is the response variable and gender is the explanatory (grouping) variable, and we note that we’re calling "promoted" a success,

  • then we set our null hypothesis as "independence" (no gender discrimination), and

  • finally we permute 5 times under the specification we outlined so far.

gender_discrimination %>%
  specify(decision ~ gender, success = "promoted") %>%
  hypothesize(null = "independence") %>%
  generate(reps = 5, type = "permute")
## Response: decision (factor)
## Explanatory: gender (factor)
## Null Hypothesis: independence
## # A tibble: 240 × 3
## # Groups:   replicate [5]
##    decision     gender replicate
##    <fct>        <fct>      <int>
##  1 promoted     male           1
##  2 promoted     male           1
##  3 promoted     male           1
##  4 promoted     male           1
##  5 promoted     male           1
##  6 not promoted male           1
##  7 promoted     male           1
##  8 promoted     male           1
##  9 promoted     male           1
## 10 promoted     male           1
## # … with 230 more rows

The resulting data frame has 240 rows: 48 observations per replicate (just like in the original gender_discrimination data) * 5 replicates.

Distribution of statistics

Next, we generate multiple shuffles and compute the difference in proportions. Then, we show the distribution of differences the proportions. Here we are using the difference for simplicity but you can use the ratio as well.

set.seed(35) # set seed for replicability
shuffles <- gender_discrimination %>%
  specify(decision ~ gender, success = "promoted") %>%
  hypothesize(null = "independence") %>%
  generate(reps = 100, type = "permute") %>%
  calculate(stat = "diff in props", order = c("male", "female"))
shuffles %>%
  ggplot(aes(x = stat)) +
  geom_dotplot(binwidth = 0.015) +
  gghighlight(stat >= 0.292) +
  theme(
    axis.ticks.y = element_blank(),
    axis.text.y = element_blank()
  ) +
  labs(
    x = "Differences in promotion rates (male - female) across 100 shuffles",
    y = NULL
  )

This plot shows the distribution of the differences in proportions where \(\frac{2}{100}\) of the shuffles (shown in black dots) has difference in proportion larger than our observed statistic.

We can modify the above code to increase the number of shuffles to 1000 and use a histogram to show the distribution of the differences in proportions.

set.seed(35) # set seed for replicability
shuffles_more <- gender_discrimination %>%
  specify(decision ~ gender, success = "promoted") %>%
  hypothesize(null = "independence") %>%
  generate(reps = 1000, type = "permute") %>%
  calculate(stat = "diff in props", order = c("male", "female"))
shuffles_more %>% ggplot(aes(x = stat)) +
  geom_histogram(bins=20) +
  gghighlight(stat >= 0.292) +
  labs(
    x = "Differences in promotion rates (male - female) across 1000 shuffles",
    y = "Frequency"
  )

In the histogram, the black bars indicate shuffles with values greater than our observed statistic.

Null and Alternative Hypothesis

Let \(\widehat{p}_M\) be the proportion of promoted males and \(\widehat{p}_F\) be the proportion of promoted females.

  • \(H_0:\) Null hypothesis. The variables gender and decision are independent. They have no relationship, and the observed difference between the proportion of males and females who were promoted, 0.2916667, was due to the natural variability inherent in the population. \[p_M - p_F = 0\]
  • \(H_A:\) Alternative hypothesis. The variables gender and decision are not independent. The difference in promotion rates of 0.2916667 was not due to natural variability, and equally qualified female personnel are less likely to be promoted than male personnel. \[p_M - p_F > 0\]

In the 100 shuffles example, we determined that there was only a \(\approx\) 2% probability of obtaining a sample where \(\geq\) 29.2% more male candidates than female candidates get promoted under the null hypothesis.

After some rigorous computations and formal studies (we skipped it here but we will go on to more details later), we can conclude that the data provide strong evidence of sex discrimination against female candidates by the male supervisors. In this case, we reject the null hypothesis in favor of the alternative.

When we simulated a world with no sex discrimination, we showed that the expected difference is 0 and the observed statistic is a “rare” occurrence, which means that only a \(\approx\) 2% probability of obtaining a sample where 29.2% more male candidates.


Lab Exercises


Note: You must include your code and results to answer the exercise problems.


I. Gender Discrimination

As the first step of any analysis, you should look at and summarize the data. Categorical variables are often summarized using proportions, and it is always important to understand the denominator of the proportion.

The discrimination study data are available as gender_discrimination using the openintro package.

  1. Using the count() function, tabulate the variables gender and decision. Group the data by gender. Calculate the proportion of those who were and were not promoted in each gender and call this variable prop_row. Print out your results.

  2. Using the count() function, tabulate the variables gender and decision. Group the data by decision. Calculate the proportion of those who males and females in each decision and call this variable prop_col. Print out your results.

  3. From your calculations in the previous two points, what is the numerator and denominator for each?

II. Opportunity Cost

One-hundred and fifty students were recruited for the study, and each was given the following statement:

“Imagine that you have been saving some extra money on the side to make some purchases, and on your most recent visit to the video store you come across a special sale on a new video. This video is one with your favorite actor or actress, and your favorite type of movie (such as a comedy, drama, thriller, etc.). This particular video that you are considering is one you have been thinking about buying for a long time. It is available for a special sale price of $14.99. What would you do in this situation? Please circle one of the options below.”

Half of the 150 students were randomized into a control group and were given the following two options:

  1. Buy this entertaining video.

  2. Not buy this entertaining video.

The remaining 75 students were placed in the treatment group, and they saw a slightly modified option (B):

  1. Buy this entertaining video.

  2. Not buy this entertaining video. Keep the $14.99 for other purchases.

Would the extra statement reminding students of an obvious fact impact the purchasing decision?

In this exercise, use the opportunity_cost data set, which is available through the openintro package. Answer the following questions.

  1. How many rows and columns does this data set have? What are the variables? If you have categorical variables, state the levels. What type of study is this particular example?

  2. Using the count() function, tabulate the variables group and decision. Group the data by group. Calculate the proportion of those who bought and not bought the video in each group and call this variable prop_row. Print out your results.

  3. Suppose a success in this study is a student who chooses not to buy the video. Construct a point estimate for this difference as (T for treatment and C for control). State the null and alternative hypothesis.

  4. Perform a randomization test (also known as the permutation test). Use at least 1000 shuffles and plot the distribution of the difference in proportions using a histogram. What can you conclude based on your results? Can we make causal statement in this study?


LS0tCnRpdGxlOiAiMyAtIEh5cG90aGVzaXMgVGVzdGluZyB3aXRoIFJhbmRvbWl6YXRpb24iCmF1dGhvcjogIkFsZXggSm9obiBRdWlqYW5vIgpkYXRlOiAiMDkvMjgvMjAyMSIKb3V0cHV0OiBvcGVuaW50cm86OmxhYl9yZXBvcnQKLS0tCgojIyAqKkxlYXJuaW5nIE9iamVjdGl2ZXMqKgoKPGJyPgoKVXBvbiBjb21wbGV0aW5nIHRvZGF5J3MgbGFiIGFjdGl2aXR5LCBzdHVkZW50cyBzaG91bGQgYmUgYWJsZSB0byBkbyB0aGUgZm9sbG93aW5nIHVzaW5nIFIgYW5kIFJTdHVkaW86CgogIDEuIFVzaW5nIGRhdGEgdG8gZm9ybXVsYXRlIGEgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIG9mIGFuIGVzdGltYXRlLgogIAogIDIuIFBlcmZvcm0gdGhlIGJhc2ljcyBvZiByYW5kb21pemF0aW9uIGZvciBoeXBvdGhlc2lzIHRlc3RpbmcuCgo8YnI+CgpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG9wZW5pbnRybykKbGlicmFyeShpbmZlcikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnaGlnaGxpZ2h0KQpgYGAKCjxicj4KCiMjICoqQ2FzZSBTdHVkeSAtIEdlbmRlciBEaXNjcmltaW5hdGlvbioqCgogIC0gVGhpcyBleGFtcGxlIGlzIGZyb20geW91ciB0ZXh0Ym9vaywgW09wZW5JbnRybzogSU1TIFNlY3Rpb24gMTEuMV0oaHR0cHM6Ly9vcGVuaW50cm8taW1zLm5ldGxpZnkuYXBwL2ZvdW5kYXRpb25zLXJhbmRvbWl6YXRpb24uaHRtbCNjYXNlU3R1ZHlTZXhEaXNjcmltaW5hdGlvbil7dGFyZ2V0PSJfYmxhbmsifS4KCiAgLSBUaGUgZXhhbXBsZSBpbiB0aGlzIGxlc3NvbiBpcyB0YWtlbiBmcm9tIGEgcGFwZXIgb24gdGhlIFtSb3NlbiwgQmVuc29uLCBhbmQgVGhvbWFzIEggSmVyZGVlLiAxOTc0LiDigJxJbmZsdWVuY2Ugb2YgU2V4IFJvbGUgU3RlcmVvdHlwZXMgb24gUGVyc29ubmVsIERlY2lzaW9ucy7igJ0gSm91cm5hbCBvZiBBcHBsaWVkIFBzeWNob2xvZ3kgNTkgKDEpOiA5Ll0oaHR0cHM6Ly9kb2kub3JnL2RvaS5vcmcvMTAuMTAzNy9oMDAzNTgzNCl7dGFyZ2V0PSJfYmxhbmsifS4KCkxvYWQgYW5kIHByZXZpZXcgYGdlbmRlcl9kaXNjcmltaW5hdGlvbmAgZGF0YSB3aGljaCBpcyBwYXJ0IG9mIHRoZSBgb3BlbmludHJvYCBwYWNrYWdlLgoKYGBge3J9CmdsaW1wc2UoZ2VuZGVyX2Rpc2NyaW1pbmF0aW9uKQpgYGAKClRoZSBkYXRhc2V0IGhhdmUgNDggcm93cyBhbmQgMiBjb2x1bW5zLiBUaGUgdmFyaWFibGVzIGFyZSBgZ2VuZGVyYCBhbmQgYGRlY2lzaW9uYC4gQm90aCBhcmUgY2F0ZWdvcmljYWwgbm9taW5hbCB2YXJpYWJsZXMuIE5leHQsIHdlIHN1bW1hcml6ZSB0aGUgZGF0YS4KICAgIAojIyMgRGF0YSBTdW1tYXJpemF0aW9uCgpgYGB7cn0KZ2VuZGVyX2Rpc2NyaW1pbmF0aW9uX3Byb3AgPC0gZ2VuZGVyX2Rpc2NyaW1pbmF0aW9uICU+JQogIGNvdW50KGdlbmRlciwgZGVjaXNpb24pICU+JQogIGdyb3VwX2J5KGdlbmRlcikgJT4lCiAgbXV0YXRlKHByb3AgPSBuIC8gc3VtKG4pKQpnZW5kZXJfZGlzY3JpbWluYXRpb25fcHJvcApgYGAKCmBgYHtyfQpwX21hbGUgPC0gZ2VuZGVyX2Rpc2NyaW1pbmF0aW9uX3Byb3AgJT4lCiAgZmlsdGVyKGdlbmRlciA9PSAibWFsZSIsIGRlY2lzaW9uID09ICJwcm9tb3RlZCIpICU+JQogIHB1bGwocHJvcCkKCnBfZmVtYWxlIDwtIGdlbmRlcl9kaXNjcmltaW5hdGlvbl9wcm9wICU+JQogIGZpbHRlcihnZW5kZXIgPT0gImZlbWFsZSIsIGRlY2lzaW9uID09ICJwcm9tb3RlZCIpICU+JQogIHB1bGwocHJvcCkKCnBfZGlmZiA8LSBwX21hbGUgLSBwX2ZlbWFsZSAjIGRpZmZlcmVuY2UgaW4gcHJvcG9ydGlvbgpgYGAKCmBgYHtyfQpwYXN0ZSgiUHJvcG9ydGlvbiBvZiBwcm9tb3RlZCBtYWxlczogIixwX21hbGUpCnBhc3RlKCJQcm9wb3J0aW9uIG9mIHByb21vdGVkIGZlbWFsZXM6ICIscF9mZW1hbGUpCnBhc3RlKCJQcm9wb3J0aW9uIGRpZmZlcmVuY2U6ICIscF9kaWZmKQpgYGAKCkFmdGVyIHN1bW1hcml6aW5nIHRoZSBkYXRhLCB0aGUgZGlmZmVyZW5jZSBpbiBwcm9tb3Rpb25zIGNhbiBiZSBpZGVudGlmaWVkIHVzaW5nIHJhdGVzLiBUaGF0IGlzLCBgciBwX2ZlbWFsZWAgKGByIHBfZmVtYWxlKjEwMGBcJSkgb2YgdGhlIHdvbWVuIHdlcmUgcHJvbW90ZWQgd2hlcmVhcyBgciBwX21hbGVgIChgciBwX21hbGUqMTAwYFwlKSBvZiB0aGUgbWVuIHdlcmUgcHJvbW90ZWQuIFRoZSBpbXBvcnRhbnQgc3RhdGlzdGljYWwgcXVlc3Rpb24gdG8gYXNrIGFmdGVyIGxvb2tpbmcgYXQgdGhlIGRhdGEgaXMgYXMgZm9sbG93czogaXMgaXQgcGxhdXNpYmxlIHRvIG9ic2VydmUgc3VjaCBhIGRpZmZlcmVuY2UgaW4gcHJvcG9ydGlvbnMgaW4gYSBzY2VuYXJpbyB3aGVyZSBtZW4gYW5kIHdvbWVuIGFyZSBlcXVhbGx5IGxpa2VseSB0byBiZSBwcm9tb3RlZD8KCkFsbCBvZiB0aGUgcGllY2VzIG9mIHRoaXMgY29kZSB5b3XigJl2ZSBzZWVuIGJlZm9yZSwgYnV0IGxldOKAmXMgcmV2aWV3IHRoZW0hIEZpcnN0LCB3ZSBjb3VudCB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBmb3IgZWFjaCBgZ2VuZGVyYCAoYG1hbGVgLCBgZmVtYWxlYCkgYW5kIGVhY2ggYGRlY2lzaW9uYCAocHJvbW90ZWQsIG5vdCkgdXNpbmcgdGhlIGBjb3VudCgpYCBmdW5jdGlvbi4gTmV4dCwgd2UgZ3JvdXAgdGhlc2UgY291bnRzIGJ5IGBnZW5kZXJgLCBzbyB0aGF0IHdlIGNhbiB1c2UgYG11dGF0ZSgpYCB0byBjcmVhdGUgYSBuZXcgdmFyaWFibGUgdGhhdCBpcyB0aGUgcHJvcG9ydGlvbiBvZiBvYnNlcnZhdGlvbnMgaW4gZWFjaCBnZW5kZXIgdGhhdCByZWNlaXZlZCBvciBkaWRu4oCZdCByZWNlaXZlIGEgcHJvbW90aW9uLgoKV2Ugc2VlIGluIHRoZSByZXN1bHRzIHRoYXQgYHIgcF9tYWxlYCBvZiBtYWxlcyBhcmUgcHJvbW90ZWQgd2hpbGUgYHIgcF9mZW1hbGVgIG9mIGZlbWFsZXMgYXJlIHByb21vdGVkLiBUaGUgZGlmZmVyZW5jZSBpbiBwcm9wb3J0aW9uIGlzIGByIHBfZGlmZmAuCiAgICAKIyMjIFBlcm11dGF0aW9uCgpUbyBoZWxwIHlvdSB1bmRlcnN0YW5kIHRoZSBjb2RlIHVzZWQgdG8gY3JlYXRlIHRoZSByYW5kb21pemF0aW9uIGRpc3RyaWJ1dGlvbiwgdGhpcyBzZWN0aW9uIHdpbGwgd2FsayB5b3UgdGhyb3VnaCB0aGUgc3RlcHMgb2YgdGhlIGBpbmZlcmAgZnJhbWV3b3JrLiBJbiBwYXJ0aWN1bGFyLCB5b3XigJlsbCBzZWUgaG93IGRpZmZlcmVuY2VzIGluIHRoZSBnZW5lcmF0ZWQgcmVwbGljYXRlcyBhZmZlY3QgdGhlIGNhbGN1bGF0ZWQgc3RhdGlzdGljcy4KCkZvciBzaW1wbGljaXR5LCB3ZeKAmWxsIGtlZXAgb3VyIHBlcm11dGF0aW9uIHRvIGp1c3QgNSByZXBsaWNhdGVzIOKAkyBpbiByZWFsaXR5IHdlIHdvdWxkIHdhbnQgdGhpcyB2YWx1ZSB0byBiZSBtdWNoIGxhcmdlci4KCkluIHRoZSBjb2RlIGNodW5rIGJlbG93LAoKICAtIHdlIHN0YXJ0IHdpdGggb3VyIGRhdGEgZnJhbWU6IGBnZW5kZXJfZGlzY3JpbWluYXRpb25gLAogIAogIC0gdGhlbiB3ZSBzcGVjaWZ5IG91ciBtb2RlbCB3aGVyZSBgZGVjaXNpb25gIGlzIHRoZSByZXNwb25zZSB2YXJpYWJsZSBhbmQgYGdlbmRlcmAgaXMgdGhlIGV4cGxhbmF0b3J5IChncm91cGluZykgdmFyaWFibGUsIGFuZCB3ZSBub3RlIHRoYXQgd2XigJlyZSBjYWxsaW5nIGAicHJvbW90ZWQiYCBhIHN1Y2Nlc3MsCgogIC0gdGhlbiB3ZSBzZXQgb3VyIG51bGwgaHlwb3RoZXNpcyBhcyBgImluZGVwZW5kZW5jZSJgIChubyBnZW5kZXIgZGlzY3JpbWluYXRpb24pLCBhbmQKCiAgLSBmaW5hbGx5IHdlIHBlcm11dGUgNSB0aW1lcyB1bmRlciB0aGUgc3BlY2lmaWNhdGlvbiB3ZSBvdXRsaW5lZCBzbyBmYXIuCgpgYGB7cn0KZ2VuZGVyX2Rpc2NyaW1pbmF0aW9uICU+JQogIHNwZWNpZnkoZGVjaXNpb24gfiBnZW5kZXIsIHN1Y2Nlc3MgPSAicHJvbW90ZWQiKSAlPiUKICBoeXBvdGhlc2l6ZShudWxsID0gImluZGVwZW5kZW5jZSIpICU+JQogIGdlbmVyYXRlKHJlcHMgPSA1LCB0eXBlID0gInBlcm11dGUiKQpgYGAKClRoZSByZXN1bHRpbmcgZGF0YSBmcmFtZSBoYXMgMjQwIHJvd3M6IDQ4IG9ic2VydmF0aW9ucyBwZXIgcmVwbGljYXRlIChqdXN0IGxpa2UgaW4gdGhlIG9yaWdpbmFsIGBnZW5kZXJfZGlzY3JpbWluYXRpb25gIGRhdGEpICogNSByZXBsaWNhdGVzLgoKIyMjIERpc3RyaWJ1dGlvbiBvZiBzdGF0aXN0aWNzCgpOZXh0LCB3ZSBnZW5lcmF0ZSBtdWx0aXBsZSBzaHVmZmxlcyBhbmQgY29tcHV0ZSB0aGUgZGlmZmVyZW5jZSBpbiBwcm9wb3J0aW9ucy4gVGhlbiwgd2Ugc2hvdyB0aGUgZGlzdHJpYnV0aW9uIG9mIGRpZmZlcmVuY2VzIHRoZSBwcm9wb3J0aW9ucy4gSGVyZSB3ZSBhcmUgdXNpbmcgdGhlIGRpZmZlcmVuY2UgZm9yIHNpbXBsaWNpdHkgYnV0IHlvdSBjYW4gdXNlIHRoZSByYXRpbyBhcyB3ZWxsLgoKYGBge3J9CnNldC5zZWVkKDM1KSAjIHNldCBzZWVkIGZvciByZXBsaWNhYmlsaXR5CnNodWZmbGVzIDwtIGdlbmRlcl9kaXNjcmltaW5hdGlvbiAlPiUKICBzcGVjaWZ5KGRlY2lzaW9uIH4gZ2VuZGVyLCBzdWNjZXNzID0gInByb21vdGVkIikgJT4lCiAgaHlwb3RoZXNpemUobnVsbCA9ICJpbmRlcGVuZGVuY2UiKSAlPiUKICBnZW5lcmF0ZShyZXBzID0gMTAwLCB0eXBlID0gInBlcm11dGUiKSAlPiUKICBjYWxjdWxhdGUoc3RhdCA9ICJkaWZmIGluIHByb3BzIiwgb3JkZXIgPSBjKCJtYWxlIiwgImZlbWFsZSIpKQpgYGAKCmBgYHtyfQpzaHVmZmxlcyAlPiUKICBnZ3Bsb3QoYWVzKHggPSBzdGF0KSkgKwogIGdlb21fZG90cGxvdChiaW53aWR0aCA9IDAuMDE1KSArCiAgZ2doaWdobGlnaHQoc3RhdCA+PSAwLjI5MikgKwogIHRoZW1lKAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkKICApICsKICBsYWJzKAogICAgeCA9ICJEaWZmZXJlbmNlcyBpbiBwcm9tb3Rpb24gcmF0ZXMgKG1hbGUgLSBmZW1hbGUpIGFjcm9zcyAxMDAgc2h1ZmZsZXMiLAogICAgeSA9IE5VTEwKICApCmBgYAoKVGhpcyBwbG90IHNob3dzICoqdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZGlmZmVyZW5jZXMgaW4gcHJvcG9ydGlvbnMqKiB3aGVyZSAkXGZyYWN7Mn17MTAwfSQgb2YgdGhlIHNodWZmbGVzIChzaG93biBpbiBibGFjayBkb3RzKSBoYXMgZGlmZmVyZW5jZSBpbiBwcm9wb3J0aW9uIGxhcmdlciB0aGFuIG91ciBvYnNlcnZlZCBzdGF0aXN0aWMuCgpXZSBjYW4gbW9kaWZ5IHRoZSBhYm92ZSBjb2RlIHRvIGluY3JlYXNlIHRoZSBudW1iZXIgb2Ygc2h1ZmZsZXMgdG8gMTAwMCBhbmQgdXNlIGEgaGlzdG9ncmFtIHRvIHNob3cgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZGlmZmVyZW5jZXMgaW4gcHJvcG9ydGlvbnMuCgpgYGB7cn0Kc2V0LnNlZWQoMzUpICMgc2V0IHNlZWQgZm9yIHJlcGxpY2FiaWxpdHkKc2h1ZmZsZXNfbW9yZSA8LSBnZW5kZXJfZGlzY3JpbWluYXRpb24gJT4lCiAgc3BlY2lmeShkZWNpc2lvbiB+IGdlbmRlciwgc3VjY2VzcyA9ICJwcm9tb3RlZCIpICU+JQogIGh5cG90aGVzaXplKG51bGwgPSAiaW5kZXBlbmRlbmNlIikgJT4lCiAgZ2VuZXJhdGUocmVwcyA9IDEwMDAsIHR5cGUgPSAicGVybXV0ZSIpICU+JQogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gcHJvcHMiLCBvcmRlciA9IGMoIm1hbGUiLCAiZmVtYWxlIikpCmBgYAoKYGBge3J9CnNodWZmbGVzX21vcmUgJT4lIGdncGxvdChhZXMoeCA9IHN0YXQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlucz0yMCkgKwogIGdnaGlnaGxpZ2h0KHN0YXQgPj0gMC4yOTIpICsKICBsYWJzKAogICAgeCA9ICJEaWZmZXJlbmNlcyBpbiBwcm9tb3Rpb24gcmF0ZXMgKG1hbGUgLSBmZW1hbGUpIGFjcm9zcyAxMDAwIHNodWZmbGVzIiwKICAgIHkgPSAiRnJlcXVlbmN5IgogICkKYGBgCgpJbiB0aGUgaGlzdG9ncmFtLCB0aGUgYmxhY2sgYmFycyBpbmRpY2F0ZSBzaHVmZmxlcyB3aXRoIHZhbHVlcyBncmVhdGVyIHRoYW4gb3VyIG9ic2VydmVkIHN0YXRpc3RpYy4KCiMjIyBOdWxsIGFuZCBBbHRlcm5hdGl2ZSBIeXBvdGhlc2lzCgpMZXQgJFx3aWRlaGF0e3B9X00kIGJlIHRoZSBwcm9wb3J0aW9uIG9mIHByb21vdGVkIG1hbGVzIGFuZCAkXHdpZGVoYXR7cH1fRiQgYmUgdGhlIHByb3BvcnRpb24gb2YgcHJvbW90ZWQgZmVtYWxlcy4KCi0gICAkSF8wOiQgKipOdWxsIGh5cG90aGVzaXMqKi4KICAgIFRoZSB2YXJpYWJsZXMgYGdlbmRlcmAgYW5kIGBkZWNpc2lvbmAgYXJlIGluZGVwZW5kZW50LgogICAgVGhleSBoYXZlIG5vIHJlbGF0aW9uc2hpcCwgYW5kIHRoZSBvYnNlcnZlZCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHByb3BvcnRpb24gb2YgbWFsZXMgYW5kIGZlbWFsZXMgd2hvIHdlcmUgcHJvbW90ZWQsIGByIHBfZGlmZmAsIHdhcyBkdWUgdG8gdGhlIG5hdHVyYWwgdmFyaWFiaWxpdHkgaW5oZXJlbnQgaW4gdGhlIHBvcHVsYXRpb24uCiAgICAkJHBfTSAtIHBfRiA9IDAkJAotICAgJEhfQTokICoqQWx0ZXJuYXRpdmUgaHlwb3RoZXNpcyoqLgogICAgVGhlIHZhcmlhYmxlcyBgZ2VuZGVyYCBhbmQgYGRlY2lzaW9uYCBhcmUgKm5vdCogaW5kZXBlbmRlbnQuCiAgICBUaGUgZGlmZmVyZW5jZSBpbiBwcm9tb3Rpb24gcmF0ZXMgb2YgYHIgcF9kaWZmYCB3YXMgbm90IGR1ZSB0byBuYXR1cmFsIHZhcmlhYmlsaXR5LCBhbmQgZXF1YWxseSBxdWFsaWZpZWQgZmVtYWxlIHBlcnNvbm5lbCBhcmUgbGVzcyBsaWtlbHkgdG8gYmUgcHJvbW90ZWQgdGhhbiBtYWxlIHBlcnNvbm5lbC4KICAgICQkcF9NIC0gcF9GID4gMCQkCgpJbiB0aGUgMTAwIHNodWZmbGVzIGV4YW1wbGUsIHdlIGRldGVybWluZWQgdGhhdCB0aGVyZSB3YXMgb25seSBhICRcYXBwcm94JCAyJSBwcm9iYWJpbGl0eSBvZiBvYnRhaW5pbmcgYSBzYW1wbGUgd2hlcmUgJFxnZXEkIDI5LjIlIG1vcmUgbWFsZSBjYW5kaWRhdGVzIHRoYW4gZmVtYWxlIGNhbmRpZGF0ZXMgZ2V0IHByb21vdGVkIHVuZGVyIHRoZSBudWxsIGh5cG90aGVzaXMuCiAgCkFmdGVyIHNvbWUgcmlnb3JvdXMgY29tcHV0YXRpb25zIGFuZCBmb3JtYWwgc3R1ZGllcyAoKndlIHNraXBwZWQgaXQgaGVyZSBidXQgd2Ugd2lsbCBnbyBvbiB0byBtb3JlIGRldGFpbHMgbGF0ZXIqKSwgd2UgY2FuIGNvbmNsdWRlIHRoYXQgdGhlIGRhdGEgcHJvdmlkZSBzdHJvbmcgZXZpZGVuY2Ugb2Ygc2V4IGRpc2NyaW1pbmF0aW9uIGFnYWluc3QgZmVtYWxlIGNhbmRpZGF0ZXMgYnkgdGhlIG1hbGUgc3VwZXJ2aXNvcnMuIEluIHRoaXMgY2FzZSwgd2UgKipyZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBpbiBmYXZvciBvZiB0aGUgYWx0ZXJuYXRpdmUuKioKCldoZW4gd2Ugc2ltdWxhdGVkIGEgd29ybGQgd2l0aCBubyBzZXggZGlzY3JpbWluYXRpb24sIHdlIHNob3dlZCB0aGF0IHRoZSBleHBlY3RlZCBkaWZmZXJlbmNlIGlzIDAgYW5kIHRoZSBvYnNlcnZlZCBzdGF0aXN0aWMgaXMgYSAicmFyZSIgb2NjdXJyZW5jZSwgd2hpY2ggbWVhbnMgdGhhdCAqKm9ubHkgYSAkXGFwcHJveCQgMiUgcHJvYmFiaWxpdHkgb2Ygb2J0YWluaW5nIGEgc2FtcGxlIHdoZXJlIDI5LjIlIG1vcmUgbWFsZSBjYW5kaWRhdGVzLioqCgo8YnI+CgojIyAqKkxhYiBFeGVyY2lzZXMqKgoKPGJyPgoKTm90ZTogWW91IG11c3QgaW5jbHVkZSB5b3VyIGNvZGUgYW5kIHJlc3VsdHMgdG8gYW5zd2VyIHRoZSBleGVyY2lzZSBwcm9ibGVtcy4KCjxicj4KCiMjIyBJLiBHZW5kZXIgRGlzY3JpbWluYXRpb24KCkFzIHRoZSBmaXJzdCBzdGVwIG9mIGFueSBhbmFseXNpcywgeW91IHNob3VsZCBsb29rIGF0IGFuZCBzdW1tYXJpemUgdGhlIGRhdGEuIENhdGVnb3JpY2FsIHZhcmlhYmxlcyBhcmUgb2Z0ZW4gc3VtbWFyaXplZCB1c2luZyBwcm9wb3J0aW9ucywgYW5kIGl0IGlzIGFsd2F5cyBpbXBvcnRhbnQgdG8gdW5kZXJzdGFuZCB0aGUgZGVub21pbmF0b3Igb2YgdGhlIHByb3BvcnRpb24uCgpUaGUgZGlzY3JpbWluYXRpb24gc3R1ZHkgZGF0YSBhcmUgYXZhaWxhYmxlIGFzIGBnZW5kZXJfZGlzY3JpbWluYXRpb25gIHVzaW5nIHRoZSBgb3BlbmludHJvYCBwYWNrYWdlLgoKICAxLiBVc2luZyB0aGUgYGNvdW50KClgIGZ1bmN0aW9uLCB0YWJ1bGF0ZSB0aGUgdmFyaWFibGVzIGdlbmRlciBhbmQgZGVjaXNpb24uIEdyb3VwIHRoZSBkYXRhIGJ5IGBnZW5kZXJgLiBDYWxjdWxhdGUgdGhlIHByb3BvcnRpb24gb2YgdGhvc2Ugd2hvIHdlcmUgYW5kIHdlcmUgbm90IHByb21vdGVkIGluIGVhY2ggZ2VuZGVyIGFuZCBjYWxsIHRoaXMgdmFyaWFibGUgYHByb3Bfcm93YC4gUHJpbnQgb3V0IHlvdXIgcmVzdWx0cy4KICAKICAyLiBVc2luZyB0aGUgYGNvdW50KClgIGZ1bmN0aW9uLCB0YWJ1bGF0ZSB0aGUgdmFyaWFibGVzIGdlbmRlciBhbmQgZGVjaXNpb24uIEdyb3VwIHRoZSBkYXRhIGJ5IGBkZWNpc2lvbmAuIENhbGN1bGF0ZSB0aGUgcHJvcG9ydGlvbiBvZiB0aG9zZSB3aG8gbWFsZXMgYW5kIGZlbWFsZXMgaW4gZWFjaCBkZWNpc2lvbiBhbmQgY2FsbCB0aGlzIHZhcmlhYmxlIGBwcm9wX2NvbGAuIFByaW50IG91dCB5b3VyIHJlc3VsdHMuCgogIDMuIEZyb20geW91ciBjYWxjdWxhdGlvbnMgaW4gdGhlIHByZXZpb3VzIHR3byBwb2ludHMsIHdoYXQgaXMgdGhlIG51bWVyYXRvciBhbmQgZGVub21pbmF0b3IgZm9yIGVhY2g/CgojIyMgSUkuIE9wcG9ydHVuaXR5IENvc3QKCk9uZS1odW5kcmVkIGFuZCBmaWZ0eSBzdHVkZW50cyB3ZXJlIHJlY3J1aXRlZCBmb3IgdGhlIHN0dWR5LCBhbmQgZWFjaCB3YXMgZ2l2ZW4gdGhlIGZvbGxvd2luZyBzdGF0ZW1lbnQ6CgoiSW1hZ2luZSB0aGF0IHlvdSBoYXZlIGJlZW4gc2F2aW5nIHNvbWUgZXh0cmEgbW9uZXkgb24gdGhlIHNpZGUgdG8gbWFrZSBzb21lIHB1cmNoYXNlcywgYW5kIG9uIHlvdXIgbW9zdCByZWNlbnQgdmlzaXQgdG8gdGhlIHZpZGVvIHN0b3JlIHlvdSBjb21lIGFjcm9zcyBhIHNwZWNpYWwgc2FsZSBvbiBhIG5ldyB2aWRlby4gVGhpcyB2aWRlbyBpcyBvbmUgd2l0aCB5b3VyIGZhdm9yaXRlIGFjdG9yIG9yIGFjdHJlc3MsIGFuZCB5b3VyIGZhdm9yaXRlIHR5cGUgb2YgbW92aWUgKHN1Y2ggYXMgYSBjb21lZHksIGRyYW1hLCB0aHJpbGxlciwgZXRjLikuIFRoaXMgcGFydGljdWxhciB2aWRlbyB0aGF0IHlvdSBhcmUgY29uc2lkZXJpbmcgaXMgb25lIHlvdSBoYXZlIGJlZW4gdGhpbmtpbmcgYWJvdXQgYnV5aW5nIGZvciBhIGxvbmcgdGltZS4gSXQgaXMgYXZhaWxhYmxlIGZvciBhIHNwZWNpYWwgc2FsZSBwcmljZSBvZiAkMTQuOTkuIFdoYXQgd291bGQgeW91IGRvIGluIHRoaXMgc2l0dWF0aW9uPyBQbGVhc2UgY2lyY2xlIG9uZSBvZiB0aGUgb3B0aW9ucyBiZWxvdy4iCgpIYWxmIG9mIHRoZSAxNTAgc3R1ZGVudHMgd2VyZSByYW5kb21pemVkIGludG8gYSBjb250cm9sIGdyb3VwIGFuZCB3ZXJlIGdpdmVuIHRoZSBmb2xsb3dpbmcgdHdvIG9wdGlvbnM6CgphLiBCdXkgdGhpcyBlbnRlcnRhaW5pbmcgdmlkZW8uCgpiLiBOb3QgYnV5IHRoaXMgZW50ZXJ0YWluaW5nIHZpZGVvLgoKVGhlIHJlbWFpbmluZyA3NSBzdHVkZW50cyB3ZXJlIHBsYWNlZCBpbiB0aGUgdHJlYXRtZW50IGdyb3VwLCBhbmQgdGhleSBzYXcgYSBzbGlnaHRseSBtb2RpZmllZCBvcHRpb24gKEIpOgoKYS4gQnV5IHRoaXMgZW50ZXJ0YWluaW5nIHZpZGVvLgoKYi4gTm90IGJ1eSB0aGlzIGVudGVydGFpbmluZyB2aWRlby4gS2VlcCB0aGUgJDE0Ljk5IGZvciBvdGhlciBwdXJjaGFzZXMuCgpXb3VsZCB0aGUgZXh0cmEgc3RhdGVtZW50IHJlbWluZGluZyBzdHVkZW50cyBvZiBhbiBvYnZpb3VzIGZhY3QgaW1wYWN0IHRoZSBwdXJjaGFzaW5nIGRlY2lzaW9uPwoKSW4gdGhpcyBleGVyY2lzZSwgdXNlIHRoZSBgb3Bwb3J0dW5pdHlfY29zdGAgZGF0YSBzZXQsIHdoaWNoIGlzIGF2YWlsYWJsZSB0aHJvdWdoIHRoZSBgb3BlbmludHJvYCBwYWNrYWdlLiBBbnN3ZXIgdGhlIGZvbGxvd2luZyBxdWVzdGlvbnMuCgogIDEuIEhvdyBtYW55IHJvd3MgYW5kIGNvbHVtbnMgZG9lcyB0aGlzIGRhdGEgc2V0IGhhdmU/IFdoYXQgYXJlIHRoZSB2YXJpYWJsZXM/IElmIHlvdSBoYXZlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcywgc3RhdGUgdGhlIGxldmVscy4gV2hhdCB0eXBlIG9mIHN0dWR5IGlzIHRoaXMgcGFydGljdWxhciBleGFtcGxlPwogIAogIDIuICAgVXNpbmcgdGhlIGBjb3VudCgpYCBmdW5jdGlvbiwgdGFidWxhdGUgdGhlIHZhcmlhYmxlcyBncm91cCBhbmQgZGVjaXNpb24uIEdyb3VwIHRoZSBkYXRhIGJ5IGBncm91cGAuIENhbGN1bGF0ZSB0aGUgcHJvcG9ydGlvbiBvZiB0aG9zZSB3aG8gYm91Z2h0IGFuZCBub3QgYm91Z2h0IHRoZSB2aWRlbyBpbiBlYWNoIGdyb3VwIGFuZCBjYWxsIHRoaXMgdmFyaWFibGUgYHByb3Bfcm93YC4gUHJpbnQgb3V0IHlvdXIgcmVzdWx0cy4KICAKICAzLiBTdXBwb3NlIGEgc3VjY2VzcyBpbiB0aGlzIHN0dWR5IGlzIGEgc3R1ZGVudCB3aG8gY2hvb3NlcyBub3QgdG8gYnV5IHRoZSB2aWRlby4gQ29uc3RydWN0IGEgcG9pbnQgZXN0aW1hdGUgZm9yIHRoaXMgZGlmZmVyZW5jZSBhcyAoVCBmb3IgdHJlYXRtZW50IGFuZCBDIGZvciBjb250cm9sKS4gU3RhdGUgdGhlIG51bGwgYW5kIGFsdGVybmF0aXZlIGh5cG90aGVzaXMuCiAgCiAgNC4gUGVyZm9ybSBhIHJhbmRvbWl6YXRpb24gdGVzdCAoYWxzbyBrbm93biBhcyB0aGUgcGVybXV0YXRpb24gdGVzdCkuIFVzZSBhdCBsZWFzdCAxMDAwIHNodWZmbGVzIGFuZCBwbG90IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIGRpZmZlcmVuY2UgaW4gcHJvcG9ydGlvbnMgdXNpbmcgYSBoaXN0b2dyYW0uIFdoYXQgY2FuIHlvdSBjb25jbHVkZSBiYXNlZCBvbiB5b3VyIHJlc3VsdHM/IENhbiB3ZSBtYWtlIGNhdXNhbCBzdGF0ZW1lbnQgaW4gdGhpcyBzdHVkeT8KCjxicj4K