#Inference for categorical data

library(tidyverse)
library(openintro)
library(infer)
library(scales)

Exercise 1

What are the counts within each category for the amount of days these students have texted while driving within the past 30 days?

data(yrbss)

text_while_driving <- yrbss %>%
  filter(text_while_driving_30d == 30)

summary(text_while_driving)
##       age           gender             grade             hispanic        
##  Min.   :12.00   Length:827         Length:827         Length:827        
##  1st Qu.:16.00   Class :character   Class :character   Class :character  
##  Median :17.00   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :16.92                                                           
##  3rd Qu.:18.00                                                           
##  Max.   :18.00                                                           
##  NA's   :5                                                               
##      race               height          weight        helmet_12m       
##  Length:827         Min.   :1.370   Min.   : 38.56   Length:827        
##  Class :character   1st Qu.:1.630   1st Qu.: 58.97   Class :character  
##  Mode  :character   Median :1.730   Median : 69.85   Mode  :character  
##                     Mean   :1.721   Mean   : 72.66                     
##                     3rd Qu.:1.800   3rd Qu.: 81.65                     
##                     Max.   :2.110   Max.   :180.99                     
##                     NA's   :71      NA's   :71                         
##  text_while_driving_30d physically_active_7d hours_tv_per_school_day
##  Length:827             Min.   :0.000        Length:827             
##  Class :character       1st Qu.:2.000        Class :character       
##  Mode  :character       Median :5.000        Mode  :character       
##                         Mean   :4.269                               
##                         3rd Qu.:7.000                               
##                         Max.   :7.000                               
##                         NA's   :16                                  
##  strength_training_7d school_night_hours_sleep
##  Min.   :0.000        Length:827              
##  1st Qu.:0.000        Class :character        
##  Median :3.000        Mode  :character        
##  Mean   :3.447                                
##  3rd Qu.:7.000                                
##  Max.   :7.000                                
##  NA's   :78
twd_counts <- yrbss %>%
  count(text_while_driving_30d) %>%
  mutate(p = n /sum(n))

twd_counts
## # A tibble: 9 x 3
##   text_while_driving_30d     n      p
##   <chr>                  <int>  <dbl>
## 1 0                       4792 0.353 
## 2 1-2                      925 0.0681
## 3 10-19                    373 0.0275
## 4 20-29                    298 0.0219
## 5 3-5                      493 0.0363
## 6 30                       827 0.0609
## 7 6-9                      311 0.0229
## 8 did not drive           4646 0.342 
## 9 <NA>                     918 0.0676

Exercise 2

What is the proportion of people who have texted while driving every day in the past 30 days and never wear helmets?

no_helmet <- yrbss %>%
  filter(helmet_12m == "never") %>%
  count(text_while_driving_30d) %>%
  mutate(p = n /sum(n))

# no_helmet

percent(no_helmet$p[6], accuracy = 0.01)
## [1] "6.64%"

6.64% of those who drove while texting also reported no helmet.

Exercise 3

no_helmet <- yrbss %>%
  filter(helmet_12m == "never")

no_helmet <- no_helmet %>%
  mutate(text_ind = ifelse(text_while_driving_30d == "30", "yes", "no"))

no_helmet %>%
  specify(response = text_ind, success = "yes") %>%
  generate(reps = 1000, type = "bootstrap") %>%
  calculate(stat = "prop") %>%
  get_ci(level = 0.95)
## # A tibble: 1 x 2
##   lower_ci upper_ci
##      <dbl>    <dbl>
## 1   0.0655   0.0774

Exercise 3

What is the margin of error for the estimate of the proportion of non-helmet wearers that have texted while driving each day for the past 30 days based on this survey?

p <- 463/6977
cv <- 1.96
n <- 6977

me <- 1.96 * sqrt((p*(1-p))/n)

me
## [1] 0.005840733

ME = 0.00584

Exercise 4

Using the infer package, calculate confidence intervals for two other categorical variables (you’ll need to decide which level to call “success”, and report the associated margins of error. Interpet the interval in context of the data. It may be helpful to create new data sets for each of the two countries first, and then use these data sets to construct the confidence intervals.

good_sleep <- yrbss %>%
  mutate(slept_well = ifelse(school_night_hours_sleep > 5, "yes", "no") )

good_sleep %>%
  specify(response = slept_well, success = "yes") %>%
  generate(reps = 1000, type = "bootstrap") %>%
  calculate(stat = "prop") %>%
  get_ci(level = 0.95)
## Warning: Removed 1248 rows containing missing values.
## # A tibble: 1 x 2
##   lower_ci upper_ci
##      <dbl>    <dbl>
## 1    0.769    0.784
total_slept <- good_sleep %>%
  filter(!is.na(slept_well)) %>%
  count(slept_well) %>%
  mutate( p = n/sum(n))

p <- 0.7761654
cv <- 1.96
n <- 12335

me <- 1.96 * sqrt((p*(1-p))/n)

me
## [1] 0.007355755

ME= 0.007355

no_tv <- yrbss %>%
  mutate(did_not_watch = ifelse(hours_tv_per_school_day == "do not watch", "yes", "no") )

no_tv %>%
  specify(response = did_not_watch, success = "yes") %>%
  generate(reps = 1000, type = "bootstrap") %>%
  calculate(stat = "prop") %>%
  get_ci(level = 0.95)
## Warning: Removed 338 rows containing missing values.
## # A tibble: 1 x 2
##   lower_ci upper_ci
##      <dbl>    <dbl>
## 1    0.133    0.145
total_no_tv <- no_tv %>%
  filter(!is.na(did_not_watch)) %>%
  count(did_not_watch) %>%
  mutate( p = n/sum(n))

p <- 0.1389203
cv <- 1.96
n <- 13245

me <- 1.96 * sqrt((p*(1-p))/n)

me
## [1] 0.005890262

ME = 0.00589

Exercise 5

Describe the relationship between p and me. Include the margin of error vs. population proportion plot you constructed in your answer. For a given sample size, for which value of p is margin of error maximized?

n <- 1000

p <- seq(from = 0, to = 1, by = 0.01)
me <- 2 * sqrt(p * (1 - p)/n)

dd <- data.frame(p = p, me = me)
ggplot(data = dd, aes(x = p, y = me)) + 
  geom_line() +
  labs(x = "Population Proportion", y = "Margin of Error")

The margin of error appears to increase as the population proportion increases until the population proportion reaches 50%, from that point on, the margin of error decreases as the ME increases.

Exercise 6

Describe the sampling distribution of sample proportions at n=300 and p=0.1. Be sure to note the center, spread, and shape.

p <- 0.1
n <- 300
p_hats <- rep(0, 1000)

for (i in 1:1000) {
    samp <- sample(c("A", "B"), n, replace = TRUE, 
        prob = c(p, 1 - p))
    p_hats[i] <- sum(samp == "A")/n
}

hist(p_hats, main = "p = 0.1, n = 300", xlim = c(0, 0.2))

The sampling distribution appears normal, unimodal, centered at around 0.1 with values between 0.04 and 0.16.

Exercise 7

Keep n constant and change p. How does the shape, center, and spread of the sampling distribution vary as p changes. You might want to adjust min and max for the x-axis for a better view of the distribution.

p <- 0.15
n <- 300
p_hats <- rep(0, 1000)

for (i in 1:1000) {
    samp <- sample(c("A", "B"), n, replace = TRUE, 
        prob = c(p, 1 - p))
    p_hats[i] <- sum(samp == "A")/n
}

hist(p_hats, main = "p = 0.15, n = 300", xlim = c(0, 0.30))

The spread and center of the distribution move with p. When I tried a lower p, the shape of the distribution changed slightly but still appeared normal and unimodal.

Exercise 8

Now also change n. How does n appear to affect the distribution of p^?

p <- 0.15
n <- 50
p_hats <- rep(0, 1000)

for (i in 1:1000) {
    samp <- sample(c("A", "B"), n, replace = TRUE, 
        prob = c(p, 1 - p))
    p_hats[i] <- sum(samp == "A")/n
}

hist(p_hats, main = "p = 0.15, n = 50", xlim = c(0, 0.30))

As n lowers, the distribution’s spread grows. If n increases the spread gets smaller.

Exercise 9

Is there convincing evidence that those who sleep 10+ hours per day are more likely to strength train every day of the week? As always, write out the hypotheses for any tests you conduct and outline the status of the conditions for inference. If you find a significant difference, also quantify this difference with a confidence interval.

slept_10 <- yrbss %>%
  mutate(slept_10 = ifelse(school_night_hours_sleep == "10+", "yes", "no")) %>%
  filter(!is.na(slept_10))

total_slept <- slept_10 %>%
  count(slept_10) %>%
  mutate( p = n/sum(n))

p <- 0.02561816

slept_10 %>%
  specify(response = slept_10, success = "yes") %>%
  generate(reps = 1000, type = "bootstrap") %>%
  calculate(stat = "prop") %>%
  get_ci(level = 0.95)
## # A tibble: 1 x 2
##   lower_ci upper_ci
##      <dbl>    <dbl>
## 1   0.0230   0.0282
n <- nrow(slept_10)
z <- 1.96
se <- z*sqrt((p*(1-p))/n)

me_sleep<- z * se
me_sleep
## [1] 0.005464886

We’re 95% confident the mean of people that sleep 10 hours or more is between 0.0229 and 0.0285 with a margin of error of 0.0054.

strength_trained <- yrbss %>%
  mutate(trained = ifelse(strength_training_7d == 7, "yes", "no")) %>%
  filter(!is.na(trained)) 

total_trained <- strength_trained %>%
  count(trained) %>%
  mutate( p = n/sum(n))

p <- 0.1680503

strength_trained %>%
  specify(response = trained, success = "yes") %>%
  generate(reps = 1000, type = "bootstrap") %>%
  calculate(stat = "prop") %>%
  get_ci(level = 0.95)
## # A tibble: 1 x 2
##   lower_ci upper_ci
##      <dbl>    <dbl>
## 1    0.161    0.175
n <- nrow(strength_trained)
z <- 1.96
se <- z*sqrt((p*(1-p))/n)

me_trained<- z * se
me_trained
## [1] 0.01289576

We’re 95% confident the mean of people that strength trained everyday is between 0.1611 and 0.01744 with a margin of error of 0.0129.

There doesn’t seem to be conclusive evidence to state that those that slept over 10 hours are more likely to strength train as the numbers are very disimilar.

Exercise 10

There would be a 5% chance of detecting a change. A type 1 error is also known as a false positive and occurs when a researcher incorrectly rejects a true null hypothesis. This means that your report that your findings are significant when in fact they have occurred by chance.

Exercise 11

Suppose you’re hired by the local government to estimate the proportion of residents that attend a religious service on a weekly basis. According to the guidelines, the estimate must have a margin of error no greater than 1% with 95% confidence. You have no idea what to expect for p. How many people would you have to sample to ensure that you are within the guidelines? Hint: Refer to your plot of the relationship between p and margin of error. This question does not require using a dataset.

# margin of error is maximized when p = 0.5 
p <- 0.5
me <- 0.01
z <- 1.96 #95% confidence cv

n <- (p ** 2)/((me/1.96)** 2)

n
## [1] 9604

I would need to sample 9,604 people.

LS0tDQp0aXRsZTogIkRTNjA2LUxhYiA2Ig0KYXV0aG9yOiAiR2VvcmdlIENydXoiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydA0KLS0tDQoNCiNJbmZlcmVuY2UgZm9yIGNhdGVnb3JpY2FsIGRhdGENCmBgYHtyIGxvYWQtcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkob3BlbmludHJvKQ0KbGlicmFyeShpbmZlcikNCmxpYnJhcnkoc2NhbGVzKQ0KYGBgDQoNCiMjIyBFeGVyY2lzZSAxDQoNCldoYXQgYXJlIHRoZSBjb3VudHMgd2l0aGluIGVhY2ggY2F0ZWdvcnkgZm9yIHRoZSBhbW91bnQgb2YgZGF5cyB0aGVzZSBzdHVkZW50cyBoYXZlIHRleHRlZCB3aGlsZSBkcml2aW5nIHdpdGhpbiB0aGUgcGFzdCAzMCBkYXlzPw0KDQpgYGB7ciBjb2RlLWNodW5rLWxhYmVsfQ0KZGF0YSh5cmJzcykNCg0KdGV4dF93aGlsZV9kcml2aW5nIDwtIHlyYnNzICU+JQ0KICBmaWx0ZXIodGV4dF93aGlsZV9kcml2aW5nXzMwZCA9PSAzMCkNCg0Kc3VtbWFyeSh0ZXh0X3doaWxlX2RyaXZpbmcpDQpgYGANCg0KYGBge3J9DQp0d2RfY291bnRzIDwtIHlyYnNzICU+JQ0KICBjb3VudCh0ZXh0X3doaWxlX2RyaXZpbmdfMzBkKSAlPiUNCiAgbXV0YXRlKHAgPSBuIC9zdW0obikpDQoNCnR3ZF9jb3VudHMNCmBgYA0KDQojIyMgRXhlcmNpc2UgMg0KV2hhdCBpcyB0aGUgcHJvcG9ydGlvbiBvZiBwZW9wbGUgd2hvIGhhdmUgdGV4dGVkIHdoaWxlIGRyaXZpbmcgZXZlcnkgZGF5IGluIHRoZSBwYXN0IDMwIGRheXMgYW5kIG5ldmVyIHdlYXIgaGVsbWV0cz8NCg0KYGBge3J9DQpub19oZWxtZXQgPC0geXJic3MgJT4lDQogIGZpbHRlcihoZWxtZXRfMTJtID09ICJuZXZlciIpICU+JQ0KICBjb3VudCh0ZXh0X3doaWxlX2RyaXZpbmdfMzBkKSAlPiUNCiAgbXV0YXRlKHAgPSBuIC9zdW0obikpDQoNCiMgbm9faGVsbWV0DQoNCnBlcmNlbnQobm9faGVsbWV0JHBbNl0sIGFjY3VyYWN5ID0gMC4wMSkNCmBgYA0KDQo2LjY0JSBvZiB0aG9zZSB3aG8gZHJvdmUgd2hpbGUgdGV4dGluZyBhbHNvIHJlcG9ydGVkIG5vIGhlbG1ldC4NCg0KIyMjIEV4ZXJjaXNlIDMNCg0KYGBge3Igd2FybmluZz1GQUxTRX0NCm5vX2hlbG1ldCA8LSB5cmJzcyAlPiUNCiAgZmlsdGVyKGhlbG1ldF8xMm0gPT0gIm5ldmVyIikNCg0Kbm9faGVsbWV0IDwtIG5vX2hlbG1ldCAlPiUNCiAgbXV0YXRlKHRleHRfaW5kID0gaWZlbHNlKHRleHRfd2hpbGVfZHJpdmluZ18zMGQgPT0gIjMwIiwgInllcyIsICJubyIpKQ0KDQpub19oZWxtZXQgJT4lDQogIHNwZWNpZnkocmVzcG9uc2UgPSB0ZXh0X2luZCwgc3VjY2VzcyA9ICJ5ZXMiKSAlPiUNCiAgZ2VuZXJhdGUocmVwcyA9IDEwMDAsIHR5cGUgPSAiYm9vdHN0cmFwIikgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gInByb3AiKSAlPiUNCiAgZ2V0X2NpKGxldmVsID0gMC45NSkNCmBgYA0KDQojIyMgRXhlcmNpc2UgMw0KV2hhdCBpcyB0aGUgbWFyZ2luIG9mIGVycm9yIGZvciB0aGUgZXN0aW1hdGUgb2YgdGhlIHByb3BvcnRpb24gb2Ygbm9uLWhlbG1ldCB3ZWFyZXJzIHRoYXQgaGF2ZSB0ZXh0ZWQgd2hpbGUgZHJpdmluZyBlYWNoIGRheSBmb3IgdGhlIHBhc3QgMzAgZGF5cyBiYXNlZCBvbiB0aGlzIHN1cnZleT8NCg0KYGBge3J9DQpwIDwtIDQ2My82OTc3DQpjdiA8LSAxLjk2DQpuIDwtIDY5NzcNCg0KbWUgPC0gMS45NiAqIHNxcnQoKHAqKDEtcCkpL24pDQoNCm1lDQoNCmBgYA0KDQpNRSA9IDAuMDA1ODQNCg0KIyMjIEV4ZXJjaXNlIDQNClVzaW5nIHRoZSBpbmZlciBwYWNrYWdlLCBjYWxjdWxhdGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgZm9yIHR3byBvdGhlciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgKHlvdeKAmWxsIG5lZWQgdG8gZGVjaWRlIHdoaWNoIGxldmVsIHRvIGNhbGwg4oCcc3VjY2Vzc+KAnSwgYW5kIHJlcG9ydCB0aGUgYXNzb2NpYXRlZCBtYXJnaW5zIG9mIGVycm9yLiBJbnRlcnBldCB0aGUgaW50ZXJ2YWwgaW4gY29udGV4dCBvZiB0aGUgZGF0YS4gSXQgbWF5IGJlIGhlbHBmdWwgdG8gY3JlYXRlIG5ldyBkYXRhIHNldHMgZm9yIGVhY2ggb2YgdGhlIHR3byBjb3VudHJpZXMgZmlyc3QsIGFuZCB0aGVuIHVzZSB0aGVzZSBkYXRhIHNldHMgdG8gY29uc3RydWN0IHRoZSBjb25maWRlbmNlIGludGVydmFscy4NCg0KYGBge3Igd2FybmluZ3M9RkFMU0V9DQpnb29kX3NsZWVwIDwtIHlyYnNzICU+JQ0KICBtdXRhdGUoc2xlcHRfd2VsbCA9IGlmZWxzZShzY2hvb2xfbmlnaHRfaG91cnNfc2xlZXAgPiA1LCAieWVzIiwgIm5vIikgKQ0KDQpnb29kX3NsZWVwICU+JQ0KICBzcGVjaWZ5KHJlc3BvbnNlID0gc2xlcHRfd2VsbCwgc3VjY2VzcyA9ICJ5ZXMiKSAlPiUNCiAgZ2VuZXJhdGUocmVwcyA9IDEwMDAsIHR5cGUgPSAiYm9vdHN0cmFwIikgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gInByb3AiKSAlPiUNCiAgZ2V0X2NpKGxldmVsID0gMC45NSkNCg0KYGBgDQoNCmBgYHtyfQ0KDQp0b3RhbF9zbGVwdCA8LSBnb29kX3NsZWVwICU+JQ0KICBmaWx0ZXIoIWlzLm5hKHNsZXB0X3dlbGwpKSAlPiUNCiAgY291bnQoc2xlcHRfd2VsbCkgJT4lDQogIG11dGF0ZSggcCA9IG4vc3VtKG4pKQ0KDQpwIDwtIDAuNzc2MTY1NA0KY3YgPC0gMS45Ng0KbiA8LSAxMjMzNQ0KDQptZSA8LSAxLjk2ICogc3FydCgocCooMS1wKSkvbikNCg0KbWUNCmBgYA0KDQpNRT0gMC4wMDczNTUNCg0KYGBge3J9DQoNCm5vX3R2IDwtIHlyYnNzICU+JQ0KICBtdXRhdGUoZGlkX25vdF93YXRjaCA9IGlmZWxzZShob3Vyc190dl9wZXJfc2Nob29sX2RheSA9PSAiZG8gbm90IHdhdGNoIiwgInllcyIsICJubyIpICkNCg0Kbm9fdHYgJT4lDQogIHNwZWNpZnkocmVzcG9uc2UgPSBkaWRfbm90X3dhdGNoLCBzdWNjZXNzID0gInllcyIpICU+JQ0KICBnZW5lcmF0ZShyZXBzID0gMTAwMCwgdHlwZSA9ICJib290c3RyYXAiKSAlPiUNCiAgY2FsY3VsYXRlKHN0YXQgPSAicHJvcCIpICU+JQ0KICBnZXRfY2kobGV2ZWwgPSAwLjk1KQ0KDQpgYGANCg0KDQpgYGB7cn0NCnRvdGFsX25vX3R2IDwtIG5vX3R2ICU+JQ0KICBmaWx0ZXIoIWlzLm5hKGRpZF9ub3Rfd2F0Y2gpKSAlPiUNCiAgY291bnQoZGlkX25vdF93YXRjaCkgJT4lDQogIG11dGF0ZSggcCA9IG4vc3VtKG4pKQ0KDQpwIDwtIDAuMTM4OTIwMw0KY3YgPC0gMS45Ng0KbiA8LSAxMzI0NQ0KDQptZSA8LSAxLjk2ICogc3FydCgocCooMS1wKSkvbikNCg0KbWUNCmBgYA0KDQpNRSA9IDAuMDA1ODkNCg0KDQojIyMgRXhlcmNpc2UgNQ0KRGVzY3JpYmUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHAgYW5kIG1lLiBJbmNsdWRlIHRoZSBtYXJnaW4gb2YgZXJyb3IgdnMuIHBvcHVsYXRpb24gcHJvcG9ydGlvbiBwbG90IHlvdSBjb25zdHJ1Y3RlZCBpbiB5b3VyIGFuc3dlci4gRm9yIGEgZ2l2ZW4gc2FtcGxlIHNpemUsIGZvciB3aGljaCB2YWx1ZSBvZiBwIGlzIG1hcmdpbiBvZiBlcnJvciBtYXhpbWl6ZWQ/DQoNCg0KYGBge3J9DQpuIDwtIDEwMDANCg0KcCA8LSBzZXEoZnJvbSA9IDAsIHRvID0gMSwgYnkgPSAwLjAxKQ0KbWUgPC0gMiAqIHNxcnQocCAqICgxIC0gcCkvbikNCg0KZGQgPC0gZGF0YS5mcmFtZShwID0gcCwgbWUgPSBtZSkNCmdncGxvdChkYXRhID0gZGQsIGFlcyh4ID0gcCwgeSA9IG1lKSkgKyANCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHggPSAiUG9wdWxhdGlvbiBQcm9wb3J0aW9uIiwgeSA9ICJNYXJnaW4gb2YgRXJyb3IiKQ0KDQpgYGANCg0KVGhlIG1hcmdpbiBvZiBlcnJvciBhcHBlYXJzIHRvIGluY3JlYXNlIGFzIHRoZSBwb3B1bGF0aW9uIHByb3BvcnRpb24gaW5jcmVhc2VzIHVudGlsIHRoZSBwb3B1bGF0aW9uIHByb3BvcnRpb24gKipyZWFjaGVzIDUwJSoqLCBmcm9tIHRoYXQgcG9pbnQgb24sIHRoZSBtYXJnaW4gb2YgZXJyb3IgZGVjcmVhc2VzIGFzIHRoZSBNRSBpbmNyZWFzZXMuDQoNCiMjIyBFeGVyY2lzZSA2DQpEZXNjcmliZSB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIG9mIHNhbXBsZSBwcm9wb3J0aW9ucyBhdCBuPTMwMCBhbmQgcD0wLjEuIEJlIHN1cmUgdG8gbm90ZSB0aGUgY2VudGVyLCBzcHJlYWQsIGFuZCBzaGFwZS4NCg0KYGBge3J9DQpwIDwtIDAuMQ0KbiA8LSAzMDANCnBfaGF0cyA8LSByZXAoMCwgMTAwMCkNCg0KZm9yIChpIGluIDE6MTAwMCkgew0KICAgIHNhbXAgPC0gc2FtcGxlKGMoIkEiLCAiQiIpLCBuLCByZXBsYWNlID0gVFJVRSwgDQogICAgICAgIHByb2IgPSBjKHAsIDEgLSBwKSkNCiAgICBwX2hhdHNbaV0gPC0gc3VtKHNhbXAgPT0gIkEiKS9uDQp9DQoNCmhpc3QocF9oYXRzLCBtYWluID0gInAgPSAwLjEsIG4gPSAzMDAiLCB4bGltID0gYygwLCAwLjIpKQ0KYGBgDQoNClRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gYXBwZWFycyBub3JtYWwsIHVuaW1vZGFsLCBjZW50ZXJlZCBhdCBhcm91bmQgMC4xIHdpdGggdmFsdWVzIGJldHdlZW4gMC4wNCBhbmQgMC4xNi4NCg0KIyMjIEV4ZXJjaXNlIDcNCktlZXAgbiBjb25zdGFudCBhbmQgY2hhbmdlIHAuIEhvdyBkb2VzIHRoZSBzaGFwZSwgY2VudGVyLCBhbmQgc3ByZWFkIG9mIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gdmFyeSBhcyBwIGNoYW5nZXMuIFlvdSBtaWdodCB3YW50IHRvIGFkanVzdCBtaW4gYW5kIG1heCBmb3IgdGhlIHgtYXhpcyBmb3IgYSBiZXR0ZXIgdmlldyBvZiB0aGUgZGlzdHJpYnV0aW9uLg0KDQpgYGB7cn0NCg0KcCA8LSAwLjE1DQpuIDwtIDMwMA0KcF9oYXRzIDwtIHJlcCgwLCAxMDAwKQ0KDQpmb3IgKGkgaW4gMToxMDAwKSB7DQogICAgc2FtcCA8LSBzYW1wbGUoYygiQSIsICJCIiksIG4sIHJlcGxhY2UgPSBUUlVFLCANCiAgICAgICAgcHJvYiA9IGMocCwgMSAtIHApKQ0KICAgIHBfaGF0c1tpXSA8LSBzdW0oc2FtcCA9PSAiQSIpL24NCn0NCg0KaGlzdChwX2hhdHMsIG1haW4gPSAicCA9IDAuMTUsIG4gPSAzMDAiLCB4bGltID0gYygwLCAwLjMwKSkNCg0KYGBgDQoNClRoZSBzcHJlYWQgYW5kIGNlbnRlciBvZiB0aGUgZGlzdHJpYnV0aW9uIG1vdmUgd2l0aCBwLiAgV2hlbiBJIHRyaWVkIGEgbG93ZXIgcCwgdGhlIHNoYXBlIG9mIHRoZSBkaXN0cmlidXRpb24gY2hhbmdlZCBzbGlnaHRseSBidXQgc3RpbGwgYXBwZWFyZWQgbm9ybWFsIGFuZCB1bmltb2RhbC4gDQoNCiMjIyBFeGVyY2lzZSA4DQpOb3cgYWxzbyBjaGFuZ2Ugbi4gSG93IGRvZXMgbiBhcHBlYXIgdG8gYWZmZWN0IHRoZSBkaXN0cmlidXRpb24gb2YgcF4/DQoNCmBgYHtyfQ0KcCA8LSAwLjE1DQpuIDwtIDUwDQpwX2hhdHMgPC0gcmVwKDAsIDEwMDApDQoNCmZvciAoaSBpbiAxOjEwMDApIHsNCiAgICBzYW1wIDwtIHNhbXBsZShjKCJBIiwgIkIiKSwgbiwgcmVwbGFjZSA9IFRSVUUsIA0KICAgICAgICBwcm9iID0gYyhwLCAxIC0gcCkpDQogICAgcF9oYXRzW2ldIDwtIHN1bShzYW1wID09ICJBIikvbg0KfQ0KDQpoaXN0KHBfaGF0cywgbWFpbiA9ICJwID0gMC4xNSwgbiA9IDUwIiwgeGxpbSA9IGMoMCwgMC4zMCkpDQpgYGANCg0KQXMgbiBsb3dlcnMsIHRoZSBkaXN0cmlidXRpb24ncyBzcHJlYWQgZ3Jvd3MuICBJZiBuIGluY3JlYXNlcyB0aGUgc3ByZWFkIGdldHMgc21hbGxlci4gDQoNCiMjIyBFeGVyY2lzZSA5DQoqKklzIHRoZXJlIGNvbnZpbmNpbmcgZXZpZGVuY2UgdGhhdCB0aG9zZSB3aG8gc2xlZXAgMTArIGhvdXJzIHBlciBkYXkgYXJlIG1vcmUgbGlrZWx5IHRvIHN0cmVuZ3RoIHRyYWluIGV2ZXJ5IGRheSBvZiB0aGUgd2Vlaz8gQXMgYWx3YXlzLCB3cml0ZSBvdXQgdGhlIGh5cG90aGVzZXMgZm9yIGFueSB0ZXN0cyB5b3UgY29uZHVjdCBhbmQgb3V0bGluZSB0aGUgc3RhdHVzIG9mIHRoZSBjb25kaXRpb25zIGZvciBpbmZlcmVuY2UuIElmIHlvdSBmaW5kIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSwgYWxzbyBxdWFudGlmeSB0aGlzIGRpZmZlcmVuY2Ugd2l0aCBhIGNvbmZpZGVuY2UgaW50ZXJ2YWwuKioNCg0KYGBge3J9DQoNCg0Kc2xlcHRfMTAgPC0geXJic3MgJT4lDQogIG11dGF0ZShzbGVwdF8xMCA9IGlmZWxzZShzY2hvb2xfbmlnaHRfaG91cnNfc2xlZXAgPT0gIjEwKyIsICJ5ZXMiLCAibm8iKSkgJT4lDQogIGZpbHRlcighaXMubmEoc2xlcHRfMTApKQ0KDQp0b3RhbF9zbGVwdCA8LSBzbGVwdF8xMCAlPiUNCiAgY291bnQoc2xlcHRfMTApICU+JQ0KICBtdXRhdGUoIHAgPSBuL3N1bShuKSkNCg0KcCA8LSAwLjAyNTYxODE2DQoNCnNsZXB0XzEwICU+JQ0KICBzcGVjaWZ5KHJlc3BvbnNlID0gc2xlcHRfMTAsIHN1Y2Nlc3MgPSAieWVzIikgJT4lDQogIGdlbmVyYXRlKHJlcHMgPSAxMDAwLCB0eXBlID0gImJvb3RzdHJhcCIpICU+JQ0KICBjYWxjdWxhdGUoc3RhdCA9ICJwcm9wIikgJT4lDQogIGdldF9jaShsZXZlbCA9IDAuOTUpDQoNCm4gPC0gbnJvdyhzbGVwdF8xMCkNCnogPC0gMS45Ng0Kc2UgPC0geipzcXJ0KChwKigxLXApKS9uKQ0KDQptZV9zbGVlcDwtIHogKiBzZQ0KbWVfc2xlZXANCg0KYGBgDQoNCldlJ3JlIDk1JSBjb25maWRlbnQgdGhlIG1lYW4gb2YgcGVvcGxlIHRoYXQgc2xlZXAgMTAgaG91cnMgb3IgbW9yZSBpcyBiZXR3ZWVuIDAuMDIyOSBhbmQgMC4wMjg1IHdpdGggYSBtYXJnaW4gb2YgZXJyb3Igb2YgMC4wMDU0Lg0KDQpgYGB7cn0NCg0Kc3RyZW5ndGhfdHJhaW5lZCA8LSB5cmJzcyAlPiUNCiAgbXV0YXRlKHRyYWluZWQgPSBpZmVsc2Uoc3RyZW5ndGhfdHJhaW5pbmdfN2QgPT0gNywgInllcyIsICJubyIpKSAlPiUNCiAgZmlsdGVyKCFpcy5uYSh0cmFpbmVkKSkgDQoNCnRvdGFsX3RyYWluZWQgPC0gc3RyZW5ndGhfdHJhaW5lZCAlPiUNCiAgY291bnQodHJhaW5lZCkgJT4lDQogIG11dGF0ZSggcCA9IG4vc3VtKG4pKQ0KDQpwIDwtIDAuMTY4MDUwMw0KDQpzdHJlbmd0aF90cmFpbmVkICU+JQ0KICBzcGVjaWZ5KHJlc3BvbnNlID0gdHJhaW5lZCwgc3VjY2VzcyA9ICJ5ZXMiKSAlPiUNCiAgZ2VuZXJhdGUocmVwcyA9IDEwMDAsIHR5cGUgPSAiYm9vdHN0cmFwIikgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gInByb3AiKSAlPiUNCiAgZ2V0X2NpKGxldmVsID0gMC45NSkNCg0KbiA8LSBucm93KHN0cmVuZ3RoX3RyYWluZWQpDQp6IDwtIDEuOTYNCnNlIDwtIHoqc3FydCgocCooMS1wKSkvbikNCg0KbWVfdHJhaW5lZDwtIHogKiBzZQ0KbWVfdHJhaW5lZA0KDQpgYGANCg0KV2UncmUgOTUlIGNvbmZpZGVudCB0aGUgbWVhbiBvZiBwZW9wbGUgdGhhdCBzdHJlbmd0aCB0cmFpbmVkIGV2ZXJ5ZGF5IGlzIGJldHdlZW4gMC4xNjExIGFuZCAwLjAxNzQ0IHdpdGggYSBtYXJnaW4gb2YgZXJyb3Igb2YgMC4wMTI5Lg0KDQpUaGVyZSBkb2Vzbid0IHNlZW0gdG8gYmUgY29uY2x1c2l2ZSBldmlkZW5jZSB0byBzdGF0ZSB0aGF0IHRob3NlIHRoYXQgc2xlcHQgb3ZlciAxMCBob3VycyBhcmUgbW9yZSBsaWtlbHkgdG8gc3RyZW5ndGggdHJhaW4gYXMgdGhlIG51bWJlcnMgYXJlIHZlcnkgZGlzaW1pbGFyLiANCg0KIyMjIEV4ZXJjaXNlIDEwIA0KDQpUaGVyZSB3b3VsZCBiZSBhIDUlIGNoYW5jZSBvZiBkZXRlY3RpbmcgYSBjaGFuZ2UuIA0KQSB0eXBlIDEgZXJyb3IgaXMgYWxzbyBrbm93biBhcyBhIGZhbHNlIHBvc2l0aXZlIGFuZCBvY2N1cnMgd2hlbiBhIHJlc2VhcmNoZXIgaW5jb3JyZWN0bHkgcmVqZWN0cyBhIHRydWUgbnVsbCBoeXBvdGhlc2lzLiBUaGlzIG1lYW5zIHRoYXQgeW91ciByZXBvcnQgdGhhdCB5b3VyIGZpbmRpbmdzIGFyZSBzaWduaWZpY2FudCB3aGVuIGluIGZhY3QgdGhleSBoYXZlIG9jY3VycmVkIGJ5IGNoYW5jZS4NCg0KDQojIyMgRXhlcmNpc2UgMTENCg0KU3VwcG9zZSB5b3XigJlyZSBoaXJlZCBieSB0aGUgbG9jYWwgZ292ZXJubWVudCB0byBlc3RpbWF0ZSB0aGUgcHJvcG9ydGlvbiBvZiByZXNpZGVudHMgdGhhdCBhdHRlbmQgYSByZWxpZ2lvdXMgc2VydmljZSBvbiBhIHdlZWtseSBiYXNpcy4gQWNjb3JkaW5nIHRvIHRoZSBndWlkZWxpbmVzLCB0aGUgZXN0aW1hdGUgbXVzdCBoYXZlIGEgbWFyZ2luIG9mIGVycm9yIG5vIGdyZWF0ZXIgdGhhbiAxJSB3aXRoIDk1JSBjb25maWRlbmNlLiBZb3UgaGF2ZSBubyBpZGVhIHdoYXQgdG8gZXhwZWN0IGZvciBwLiBIb3cgbWFueSBwZW9wbGUgd291bGQgeW91IGhhdmUgdG8gc2FtcGxlIHRvIGVuc3VyZSB0aGF0IHlvdSBhcmUgd2l0aGluIHRoZSBndWlkZWxpbmVzPw0KSGludDogUmVmZXIgdG8geW91ciBwbG90IG9mIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBwIGFuZCBtYXJnaW4gb2YgZXJyb3IuIFRoaXMgcXVlc3Rpb24gZG9lcyBub3QgcmVxdWlyZSB1c2luZyBhIGRhdGFzZXQuDQoNCmBgYHtyfQ0KIyBtYXJnaW4gb2YgZXJyb3IgaXMgbWF4aW1pemVkIHdoZW4gcCA9IDAuNSANCnAgPC0gMC41DQptZSA8LSAwLjAxDQp6IDwtIDEuOTYgIzk1JSBjb25maWRlbmNlIGN2DQoNCm4gPC0gKHAgKiogMikvKChtZS8xLjk2KSoqIDIpDQoNCm4NCg0KYGBgDQoNCkkgd291bGQgbmVlZCB0byBzYW1wbGUgOSw2MDQgcGVvcGxlLiANCg0KDQouLi4NCg0K