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

Exercise 1

The cases (rows) in this dataset are students surveyed in the YRBSS for a particular year.

There are 13583 cases in this dataset.

glimpse(yrbss)
## Rows: 13,583
## Columns: 13
## $ age                      <int> 14, 14, 15, 15, 15, 15, 15, 14, 15, 15, 15...
## $ gender                   <chr> "female", "female", "female", "female", "f...
## $ grade                    <chr> "9", "9", "9", "9", "9", "9", "9", "9", "9...
## $ hispanic                 <chr> "not", "not", "hispanic", "not", "not", "n...
## $ race                     <chr> "Black or African American", "Black or Afr...
## $ height                   <dbl> NA, NA, 1.73, 1.60, 1.50, 1.57, 1.65, 1.88...
## $ weight                   <dbl> NA, NA, 84.37, 55.79, 46.72, 67.13, 131.54...
## $ helmet_12m               <chr> "never", "never", "never", "never", "did n...
## $ text_while_driving_30d   <chr> "0", NA, "30", "0", "did not drive", "did ...
## $ physically_active_7d     <int> 4, 2, 7, 0, 2, 1, 4, 4, 5, 0, 0, 0, 4, 7, ...
## $ hours_tv_per_school_day  <chr> "5+", "5+", "5+", "2", "3", "5+", "5+", "5...
## $ strength_training_7d     <int> 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 3, 0, 0, 7, ...
## $ school_night_hours_sleep <chr> "8", "6", "<5", "6", "9", "8", "9", "6", "...

Exercise 2

There are 1004 observations that are missing weight values. This represents about 8% of all cases.

summary(yrbss$weight)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##   29.94   56.25   64.41   67.91   76.20  180.99    1004
sum(!is.na(yrbss$weight))
## [1] 12579
sum(is.na(yrbss$weight))/sum(!is.na(yrbss$weight))
## [1] 0.07981557
yrbss_new <- filter(yrbss,!is.na(yrbss$weight),!is.na(yrbss$physically_active_7d), !is.na(height))

Creating a new variable physical_3plus that breaks students into 2 groups by whether they are physically active 3 or more days a week, we see that out of the 12,579 cases, about 2/3 of students are active 3 or more days a week and 1/3 are not.

yrbss_new <- yrbss_new %>% 
  mutate(physical_3plus = ifelse(yrbss_new$physically_active_7d >= 3, "yes", "no"))

table(yrbss_new$physical_3plus)
## 
##   no  yes 
## 4022 8342

Exercise 3

I would have expected there to be a linear relationship between weight and boolean variable +3days physically active where those with characteristic (value=1) would be more trim (weigh less) than those not physically active 3 or more days a week (value=0) would weigh more.

On initial visual comparison of side by side plot, the IQR looks fairly similar with a slightly larger mean weight for those who do exercise 3 or more days a week.

boxplot(yrbss_new$weight ~ yrbss_new$physical_3plus, xlab="3+ Days Active", ylab="Weight")

outlier_check <- yrbss_new %>%

  group_by(physical_3plus) %>% 
  summarise(n = n(),
            min = fivenum(weight)[1],
            Q1 = fivenum(weight)[2],
            median = fivenum(weight)[3],
            mean = round(mean(weight),2),
            Q3 = fivenum(weight)[4],
            max = fivenum(weight)[5],
            IQR = IQR(weight)
            )

outlier_check
## # A tibble: 2 x 9
##   physical_3plus     n   min    Q1 median  mean    Q3   max   IQR
##   <chr>          <int> <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 no              4022  29.9  54.4   62.6  66.7  74.8  181.  20.4
## 2 yes             8342  33.1  56.7   65.8  68.4  77.1  160.  20.4

Exercise 4

Technically no, the 2 conditions for numerical inference are not met.

We can assume independence because the data we are observing is a random sample.

However, we may not be able to assume normality of the data however because although the number of cases (sample size) we are inferring from is greater than 30, there are 14 and 15 extreme outliers in weight respectively from both groups of students (physcially active 3 or more days, not physically active 3 or more days).

# check for mild outliers 
#is min/max more extreme than mild outlier cut-off?
MOF1 = outlier_check$Q1 - 1.5*outlier_check$IQR
MOF2 = outlier_check$Q3 + 1.5*outlier_check$IQR
MOF1
## [1] 23.815 26.085
MOF2
## [1] 105.455 107.725
outlier_check$min < MOF1
## [1] FALSE FALSE
outlier_check$max > MOF2
## [1] TRUE TRUE
# check for extreme outliers
#is max more extreme than extreme outlier cut-off?

EOF2 = outlier_check$Q3 + 3*outlier_check$IQR
EOF2
## [1] 136.07 138.34
outlier_check$max > EOF2
## [1] TRUE TRUE
#calculate how many observed weights are considered extreme outliers in the dataset
yrbss_new %>% group_by(physical_3plus) %>% 
  summarise(extreme_outliers = sum(weight > EOF2))
## # A tibble: 2 x 2
##   physical_3plus extreme_outliers
##   <chr>                     <int>
## 1 no                           15
## 2 yes                          14

Exercise 5

The sampling distribution of bootstrap approximates a normally distributed bell curve per CLT.

First, need to set seed and initialize

set.seed(74996)
obs_diff <- yrbss_new %>%
  specify(weight ~ physical_3plus) %>%
  calculate(stat = "diff in means", order = c("yes", "no"))
null_dist <- yrbss_new %>%
  specify(weight ~ physical_3plus) %>%
  hypothesize(null = "independence") %>%
  generate(reps = 1000, type = "permute") %>%
  calculate(stat = "diff in means", order = c("yes", "no"))

Viewing the histogram, we can see that the sample mean differences congregate around 0 as center of the distribution. This makes sense assuming null hypothesis that there is no difference between the 2 groups of students and therefore no statistically significant difference in the sample means of the 2 groups.

ggplot(data = null_dist, aes(x = stat)) +
  geom_histogram()

Exercise 6

The null hypothesis being tested is that there is no statistical relationship between days of physical activity and weight in the population high school students. Under the null hypothesis, the mean weight of group A - students who are physically active 3 or more days a week is not statistically different than the mean weight of group B students who are NOT physically active 3 or more days a week.

To test the null hypothesis, we generate many sets of simulated data assuming null hypothesis is true. In each simulation, a sample mean is calculated from group A (physical_3plus = yes) and group B (physcial_3plus = “no”). The difference between the sample means is calculated and recorded as the test statistic.

If the groups are in fact the same, then the simulated sample mean difference generated will rarely be as or more extreme than the empirical mean difference of the 2 groups.

Out of the 1000 test statistics that are generated, we want to see how many sample mean differences were observed as being more extreme in value than the actual/empirical group mean difference.

This proportion is the p-value or the probability of obtaining a test statistic at least as extreme as the observed mean difference, assuming that the 2 groups of students have the same weight.

null_dist %>%
  get_p_value(obs_stat = obs_diff, direction = "two_sided")
## Warning: Please be cautious in reporting a p-value of 0. This result is an
## approximation based on the number of `reps` chosen in the `generate()` step. See
## `?get_p_value()` for more information.
## # A tibble: 1 x 1
##   p_value
##     <dbl>
## 1       0

The p-value in this case came back as 0 and can be interpreted as 3 or fewer actual sample differences out of the total number generated (1000 in this case) were actually less extreme than the observed group mean difference.

With a probability so low, can safely reject the null hypothesis that there is no weight difference in students who are physically active and students who are not.

Exercise 7

The Confidence Interval generated here states that in 95% of samples taken, the actual population mean difference between the 2 groups of students will fall within -.64 kilogram and .65 kilogram.

null_dist %>%
  get_ci(level=0.95)
## # A tibble: 1 x 2
##   lower_ci upper_ci
##      <dbl>    <dbl>
## 1   -0.650    0.643

Exercise 8

Generating a 95% confidence interval for the average height of students in the YRBSS survey, we are confident that 95 times out of 100, the mean height of the high school student population will be within 1.6891 meters and 1.6928 meters

avg_height_dist <- yrbss_new %>%
 specify(response = height) %>%
 generate(reps = 1000, type = "bootstrap") %>%
 calculate(stat = "mean")

ci_95 <- avg_height_dist %>%
 get_ci(level = 0.95)
ci_95
## # A tibble: 1 x 2
##   lower_ci upper_ci
##      <dbl>    <dbl>
## 1     1.69     1.69
avg_height_dist %>%
  visualize(ci_fill="turquoise") + shade_confidence_interval(ci_95, color="turquoise")

This appears to be in line with the frequency histogram of height out of the entire students surveyed

fivenum(yrbss_new$height)
## [1] 1.27 1.60 1.68 1.78 2.11
ggplot(yrbss_new, aes(x=height)) + geom_histogram()

Exercise 9

At a 90% confidence interval, the mean height of the high school student population will be within 1.6894 meters and 1.6925 meters. This is a slightly narrower range as there is less accountability to capture the population mean at 90% than there is at 95%.

ci_90 <- avg_height_dist %>%
 get_ci(level = 0.90)
ci_90
## # A tibble: 1 x 2
##   lower_ci upper_ci
##      <dbl>    <dbl>
## 1     1.69     1.69
avg_height_dist %>%
  visualize() + shade_confidence_interval(ci_90, color="aquamarine")

Exercise 10

boxplot(yrbss_new$height ~ yrbss_new$physical_3plus, xlab="3+ Days Active", ylab="Height")

yrbss_new %>%
  group_by(physical_3plus) %>% 
  summarise(n = n(),
            min = fivenum(height)[1],
            Q1 = fivenum(height)[2],
            median = fivenum(height)[3],
            mean = round(mean(height),2),
            Q3 = fivenum(height)[4],
            max = fivenum(height)[5],
            IQR = IQR(height)
            )
## # A tibble: 2 x 9
##   physical_3plus     n   min    Q1 median  mean    Q3   max   IQR
##   <chr>          <int> <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 no              4022  1.27  1.6    1.65  1.67  1.73  2.11 0.130
## 2 yes             8342  1.27  1.63   1.7   1.7   1.78  2.11 0.15

Actual observed sample mean difference is .03 meters in height.

obs_diff_height <- yrbss_new %>%
  specify(height ~ physical_3plus) %>%
  calculate(stat = "diff in means", order = c("yes", "no"))

null_dist_height <- yrbss_new %>%
  specify(height ~ physical_3plus) %>%
  hypothesize(null = "independence") %>%
  generate(reps = 1000, type = "permute") %>%
  calculate(stat = "diff in means", order = c("yes", "no"))

ggplot(data = null_dist_height, aes(x = stat)) +
  geom_histogram()

The probability of observing a value more extreme than observed empirical mean difference is extremely low. A p-value of 0 as calculated here indicates that only 3 or less simulations out of 1000 produced a mean difference greater than actual observed difference. We reject the null hypothesis that there is no difference in mean height between students who are physically active and students who are not.

null_dist_height %>%
  get_p_value(obs_stat = obs_diff_height, direction = "two_sided")
## Warning: Please be cautious in reporting a p-value of 0. This result is an
## approximation based on the number of `reps` chosen in the `generate()` step. See
## `?get_p_value()` for more information.
## # A tibble: 1 x 1
##   p_value
##     <dbl>
## 1       0

LS0tDQp0aXRsZTogIkxhYiA3IC0gTnVtZXJpY2FsIEluZmVyZW5jZSINCmF1dGhvcjogIkNhc3NpZSBCb3lsYW4iDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IG9wZW5pbnRybzo6bGFiX3JlcG9ydA0KLS0tDQoNCmBgYHtyIGxvYWQtcGFja2FnZXMsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkob3BlbmludHJvKQ0KbGlicmFyeShpbmZlcikNCmBgYA0KDQojIEV4ZXJjaXNlIDENClRoZSBjYXNlcyAocm93cykgaW4gdGhpcyBkYXRhc2V0IGFyZSBzdHVkZW50cyBzdXJ2ZXllZCBpbiB0aGUgWVJCU1MgZm9yIGEgcGFydGljdWxhciB5ZWFyLiAgDQoNClRoZXJlIGFyZSAxMzU4MyBjYXNlcyBpbiB0aGlzIGRhdGFzZXQuDQpgYGB7cn0NCmdsaW1wc2UoeXJic3MpDQpgYGANCg0KDQojIEV4ZXJjaXNlIDINCg0KVGhlcmUgYXJlIDEwMDQgb2JzZXJ2YXRpb25zIHRoYXQgYXJlIG1pc3Npbmcgd2VpZ2h0IHZhbHVlcy4gIFRoaXMgcmVwcmVzZW50cyBhYm91dCA4JSBvZiBhbGwgY2FzZXMuDQogDQoNCmBgYHtyfQ0Kc3VtbWFyeSh5cmJzcyR3ZWlnaHQpDQpgYGANCg0KYGBge3J9DQpzdW0oIWlzLm5hKHlyYnNzJHdlaWdodCkpDQpzdW0oaXMubmEoeXJic3Mkd2VpZ2h0KSkvc3VtKCFpcy5uYSh5cmJzcyR3ZWlnaHQpKQ0KDQp5cmJzc19uZXcgPC0gZmlsdGVyKHlyYnNzLCFpcy5uYSh5cmJzcyR3ZWlnaHQpLCFpcy5uYSh5cmJzcyRwaHlzaWNhbGx5X2FjdGl2ZV83ZCksICFpcy5uYShoZWlnaHQpKQ0KDQpgYGANCkNyZWF0aW5nIGEgbmV3IHZhcmlhYmxlIHBoeXNpY2FsXzNwbHVzIHRoYXQgYnJlYWtzIHN0dWRlbnRzIGludG8gMiBncm91cHMgYnkgd2hldGhlciB0aGV5IGFyZSBwaHlzaWNhbGx5IGFjdGl2ZSAzIG9yIG1vcmUgZGF5cyBhIHdlZWssIHdlIHNlZSB0aGF0IG91dCBvZiB0aGUgMTIsNTc5IGNhc2VzLCBhYm91dCAyLzMgb2Ygc3R1ZGVudHMgYXJlIGFjdGl2ZSAzIG9yIG1vcmUgZGF5cyBhIHdlZWsgYW5kIDEvMyBhcmUgbm90Lg0KYGBge3J9DQp5cmJzc19uZXcgPC0geXJic3NfbmV3ICU+JSANCiAgbXV0YXRlKHBoeXNpY2FsXzNwbHVzID0gaWZlbHNlKHlyYnNzX25ldyRwaHlzaWNhbGx5X2FjdGl2ZV83ZCA+PSAzLCAieWVzIiwgIm5vIikpDQoNCnRhYmxlKHlyYnNzX25ldyRwaHlzaWNhbF8zcGx1cykNCmBgYA0KDQojIEV4ZXJjaXNlIDMgDQpJIHdvdWxkIGhhdmUgZXhwZWN0ZWQgdGhlcmUgdG8gYmUgYSBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gd2VpZ2h0IGFuZCBib29sZWFuIHZhcmlhYmxlICszZGF5cyBwaHlzaWNhbGx5IGFjdGl2ZSB3aGVyZSB0aG9zZSB3aXRoIGNoYXJhY3RlcmlzdGljICh2YWx1ZT0xKSB3b3VsZCBiZSBtb3JlIHRyaW0gKHdlaWdoIGxlc3MpIHRoYW4gdGhvc2Ugbm90IHBoeXNpY2FsbHkgYWN0aXZlIDMgb3IgbW9yZSBkYXlzIGEgd2VlayAodmFsdWU9MCkgd291bGQgd2VpZ2ggbW9yZS4NCg0KT24gaW5pdGlhbCB2aXN1YWwgY29tcGFyaXNvbiBvZiBzaWRlIGJ5IHNpZGUgcGxvdCwgdGhlIElRUiBsb29rcyBmYWlybHkgc2ltaWxhciB3aXRoIGEgc2xpZ2h0bHkgbGFyZ2VyIG1lYW4gd2VpZ2h0IGZvciB0aG9zZSB3aG8gZG8gZXhlcmNpc2UgMyBvciBtb3JlIGRheXMgYSB3ZWVrLg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KYm94cGxvdCh5cmJzc19uZXckd2VpZ2h0IH4geXJic3NfbmV3JHBoeXNpY2FsXzNwbHVzLCB4bGFiPSIzKyBEYXlzIEFjdGl2ZSIsIHlsYWI9IldlaWdodCIpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCm91dGxpZXJfY2hlY2sgPC0geXJic3NfbmV3ICU+JQ0KDQogIGdyb3VwX2J5KHBoeXNpY2FsXzNwbHVzKSAlPiUgDQogIHN1bW1hcmlzZShuID0gbigpLA0KICAgICAgICAgICAgbWluID0gZml2ZW51bSh3ZWlnaHQpWzFdLA0KICAgICAgICAgICAgUTEgPSBmaXZlbnVtKHdlaWdodClbMl0sDQogICAgICAgICAgICBtZWRpYW4gPSBmaXZlbnVtKHdlaWdodClbM10sDQogICAgICAgICAgICBtZWFuID0gcm91bmQobWVhbih3ZWlnaHQpLDIpLA0KICAgICAgICAgICAgUTMgPSBmaXZlbnVtKHdlaWdodClbNF0sDQogICAgICAgICAgICBtYXggPSBmaXZlbnVtKHdlaWdodClbNV0sDQogICAgICAgICAgICBJUVIgPSBJUVIod2VpZ2h0KQ0KICAgICAgICAgICAgKQ0KDQpvdXRsaWVyX2NoZWNrDQpgYGANCiMgRXhlcmNpc2UgNA0KVGVjaG5pY2FsbHkgbm8sIHRoZSAyIGNvbmRpdGlvbnMgZm9yIG51bWVyaWNhbCBpbmZlcmVuY2UgYXJlIG5vdCBtZXQuDQoNCldlIGNhbiBhc3N1bWUgaW5kZXBlbmRlbmNlIGJlY2F1c2UgdGhlIGRhdGEgd2UgYXJlIG9ic2VydmluZyBpcyBhIHJhbmRvbSBzYW1wbGUuDQoNCkhvd2V2ZXIsIHdlIG1heSBub3QgYmUgYWJsZSB0byBhc3N1bWUgbm9ybWFsaXR5IG9mIHRoZSBkYXRhIGhvd2V2ZXIgYmVjYXVzZSBhbHRob3VnaCB0aGUgbnVtYmVyIG9mIGNhc2VzIChzYW1wbGUgc2l6ZSkgd2UgYXJlIGluZmVycmluZyBmcm9tIGlzIGdyZWF0ZXIgdGhhbiAzMCwgdGhlcmUgYXJlIDE0IGFuZCAxNSBleHRyZW1lIG91dGxpZXJzIGluIHdlaWdodCByZXNwZWN0aXZlbHkgZnJvbSBib3RoIGdyb3VwcyBvZiBzdHVkZW50cyAocGh5c2NpYWxseSBhY3RpdmUgMyBvciBtb3JlIGRheXMsIG5vdCBwaHlzaWNhbGx5IGFjdGl2ZSAzIG9yIG1vcmUgZGF5cykuDQoNCmBgYHtyIG91dGxpZXItY2hlY2t9DQojIGNoZWNrIGZvciBtaWxkIG91dGxpZXJzIA0KI2lzIG1pbi9tYXggbW9yZSBleHRyZW1lIHRoYW4gbWlsZCBvdXRsaWVyIGN1dC1vZmY/DQpNT0YxID0gb3V0bGllcl9jaGVjayRRMSAtIDEuNSpvdXRsaWVyX2NoZWNrJElRUg0KTU9GMiA9IG91dGxpZXJfY2hlY2skUTMgKyAxLjUqb3V0bGllcl9jaGVjayRJUVINCk1PRjENCk1PRjINCm91dGxpZXJfY2hlY2skbWluIDwgTU9GMQ0Kb3V0bGllcl9jaGVjayRtYXggPiBNT0YyDQpgYGANCg0KYGBge3IgZXh0cmVtZS1vdXRsaWVyLWNoZWNrfQ0KIyBjaGVjayBmb3IgZXh0cmVtZSBvdXRsaWVycw0KI2lzIG1heCBtb3JlIGV4dHJlbWUgdGhhbiBleHRyZW1lIG91dGxpZXIgY3V0LW9mZj8NCg0KRU9GMiA9IG91dGxpZXJfY2hlY2skUTMgKyAzKm91dGxpZXJfY2hlY2skSVFSDQpFT0YyDQpvdXRsaWVyX2NoZWNrJG1heCA+IEVPRjINCmBgYA0KDQpgYGB7ciBjYWxjLWV4dHJlbWUtb3V0bGllcnMsIG1lc3NhZ2U9RkFMU0V9DQojY2FsY3VsYXRlIGhvdyBtYW55IG9ic2VydmVkIHdlaWdodHMgYXJlIGNvbnNpZGVyZWQgZXh0cmVtZSBvdXRsaWVycyBpbiB0aGUgZGF0YXNldA0KeXJic3NfbmV3ICU+JSBncm91cF9ieShwaHlzaWNhbF8zcGx1cykgJT4lIA0KICBzdW1tYXJpc2UoZXh0cmVtZV9vdXRsaWVycyA9IHN1bSh3ZWlnaHQgPiBFT0YyKSkNCg0KYGBgDQoNCiMgRXhlcmNpc2UgNQ0KVGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiBib290c3RyYXAgYXBwcm94aW1hdGVzIGEgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgYmVsbCBjdXJ2ZSBwZXIgQ0xULg0KDQpGaXJzdCwgbmVlZCB0byBzZXQgc2VlZCBhbmQgaW5pdGlhbGl6ZQ0KYGBge3J9DQpzZXQuc2VlZCg3NDk5NikNCmBgYA0KDQpgYGB7cn0NCm9ic19kaWZmIDwtIHlyYnNzX25ldyAlPiUNCiAgc3BlY2lmeSh3ZWlnaHQgfiBwaHlzaWNhbF8zcGx1cykgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gbWVhbnMiLCBvcmRlciA9IGMoInllcyIsICJubyIpKQ0KYGBgDQoNCmBgYHtyfQ0KbnVsbF9kaXN0IDwtIHlyYnNzX25ldyAlPiUNCiAgc3BlY2lmeSh3ZWlnaHQgfiBwaHlzaWNhbF8zcGx1cykgJT4lDQogIGh5cG90aGVzaXplKG51bGwgPSAiaW5kZXBlbmRlbmNlIikgJT4lDQogIGdlbmVyYXRlKHJlcHMgPSAxMDAwLCB0eXBlID0gInBlcm11dGUiKSAlPiUNCiAgY2FsY3VsYXRlKHN0YXQgPSAiZGlmZiBpbiBtZWFucyIsIG9yZGVyID0gYygieWVzIiwgIm5vIikpDQpgYGANCg0KVmlld2luZyB0aGUgaGlzdG9ncmFtLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIHNhbXBsZSBtZWFuIGRpZmZlcmVuY2VzIGNvbmdyZWdhdGUgYXJvdW5kIDAgYXMgY2VudGVyIG9mIHRoZSBkaXN0cmlidXRpb24uICBUaGlzIG1ha2VzIHNlbnNlIGFzc3VtaW5nIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vICBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIDIgZ3JvdXBzIG9mIHN0dWRlbnRzIGFuZCB0aGVyZWZvcmUgbm8gc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHRoZSBzYW1wbGUgbWVhbnMgb2YgdGhlIDIgZ3JvdXBzLg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCmdncGxvdChkYXRhID0gbnVsbF9kaXN0LCBhZXMoeCA9IHN0YXQpKSArDQogIGdlb21faGlzdG9ncmFtKCkNCmBgYA0KDQojIEV4ZXJjaXNlIDYNClRoZSBudWxsIGh5cG90aGVzaXMgYmVpbmcgdGVzdGVkIGlzIHRoYXQgdGhlcmUgaXMgbm8gc3RhdGlzdGljYWwgcmVsYXRpb25zaGlwIGJldHdlZW4gZGF5cyBvZiBwaHlzaWNhbCBhY3Rpdml0eSBhbmQgd2VpZ2h0IGluIHRoZSBwb3B1bGF0aW9uIGhpZ2ggc2Nob29sIHN0dWRlbnRzLiAgVW5kZXIgdGhlIG51bGwgaHlwb3RoZXNpcywgdGhlIG1lYW4gd2VpZ2h0IG9mIGdyb3VwIEEgLSBzdHVkZW50cyB3aG8gYXJlIHBoeXNpY2FsbHkgYWN0aXZlIDMgb3IgbW9yZSBkYXlzIGEgd2VlayBpcyBub3Qgc3RhdGlzdGljYWxseSBkaWZmZXJlbnQgdGhhbiB0aGUgbWVhbiB3ZWlnaHQgb2YgZ3JvdXAgQiBzdHVkZW50cyB3aG8gYXJlIE5PVCBwaHlzaWNhbGx5IGFjdGl2ZSAzIG9yIG1vcmUgZGF5cyBhIHdlZWsuDQoNClRvIHRlc3QgdGhlIG51bGwgaHlwb3RoZXNpcywgd2UgZ2VuZXJhdGUgbWFueSBzZXRzIG9mIHNpbXVsYXRlZCBkYXRhIGFzc3VtaW5nIG51bGwgaHlwb3RoZXNpcyBpcyB0cnVlLiAgSW4gZWFjaCBzaW11bGF0aW9uLCBhIHNhbXBsZSBtZWFuIGlzIGNhbGN1bGF0ZWQgZnJvbSBncm91cCBBIChwaHlzaWNhbF8zcGx1cyA9IHllcykgYW5kIGdyb3VwIEIgKHBoeXNjaWFsXzNwbHVzID0gIm5vIikuICBUaGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBzYW1wbGUgbWVhbnMgaXMgY2FsY3VsYXRlZCBhbmQgcmVjb3JkZWQgYXMgdGhlIHRlc3Qgc3RhdGlzdGljLg0KDQpJZiB0aGUgZ3JvdXBzIGFyZSBpbiBmYWN0IHRoZSBzYW1lLCB0aGVuIHRoZSBzaW11bGF0ZWQgc2FtcGxlIG1lYW4gZGlmZmVyZW5jZSBnZW5lcmF0ZWQgd2lsbCByYXJlbHkgYmUgYXMgb3IgbW9yZSBleHRyZW1lIHRoYW4gdGhlIGVtcGlyaWNhbCBtZWFuIGRpZmZlcmVuY2Ugb2YgdGhlIDIgZ3JvdXBzLg0KDQpPdXQgb2YgdGhlIDEwMDAgdGVzdCBzdGF0aXN0aWNzIHRoYXQgYXJlIGdlbmVyYXRlZCwgd2Ugd2FudCB0byBzZWUgaG93IG1hbnkgc2FtcGxlIG1lYW4gZGlmZmVyZW5jZXMgd2VyZSBvYnNlcnZlZCBhcyBiZWluZyBtb3JlIGV4dHJlbWUgaW4gdmFsdWUgdGhhbiB0aGUgYWN0dWFsL2VtcGlyaWNhbCBncm91cCBtZWFuIGRpZmZlcmVuY2UuICANCg0KVGhpcyBwcm9wb3J0aW9uIGlzIHRoZSBwLXZhbHVlIG9yIHRoZSBwcm9iYWJpbGl0eSBvZiBvYnRhaW5pbmcgYSB0ZXN0IHN0YXRpc3RpYyBhdCBsZWFzdCBhcyBleHRyZW1lIGFzIHRoZSBvYnNlcnZlZCBtZWFuIGRpZmZlcmVuY2UsIGFzc3VtaW5nIHRoYXQgdGhlIDIgZ3JvdXBzIG9mIHN0dWRlbnRzIGhhdmUgdGhlIHNhbWUgd2VpZ2h0Lg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KbnVsbF9kaXN0ICU+JQ0KICBnZXRfcF92YWx1ZShvYnNfc3RhdCA9IG9ic19kaWZmLCBkaXJlY3Rpb24gPSAidHdvX3NpZGVkIikNCmBgYA0KDQpUaGUgcC12YWx1ZSBpbiB0aGlzIGNhc2UgY2FtZSBiYWNrIGFzIDAgYW5kIGNhbiBiZSBpbnRlcnByZXRlZCBhcyAzIG9yIGZld2VyIGFjdHVhbCBzYW1wbGUgZGlmZmVyZW5jZXMgb3V0IG9mIHRoZSB0b3RhbCBudW1iZXIgZ2VuZXJhdGVkICgxMDAwIGluIHRoaXMgY2FzZSkgd2VyZSBhY3R1YWxseSAqbGVzcyogZXh0cmVtZSB0aGFuIHRoZSBvYnNlcnZlZCBncm91cCBtZWFuIGRpZmZlcmVuY2UuDQoNCldpdGggYSBwcm9iYWJpbGl0eSBzbyBsb3csIGNhbiBzYWZlbHkgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGVyZSBpcyBubyB3ZWlnaHQgZGlmZmVyZW5jZSBpbiBzdHVkZW50cyB3aG8gYXJlIHBoeXNpY2FsbHkgYWN0aXZlIGFuZCBzdHVkZW50cyB3aG8gYXJlIG5vdC4NCg0KIyBFeGVyY2lzZSA3DQoNClRoZSBDb25maWRlbmNlIEludGVydmFsIGdlbmVyYXRlZCBoZXJlIHN0YXRlcyB0aGF0IGluIDk1JSBvZiBzYW1wbGVzIHRha2VuLCB0aGUgYWN0dWFsIHBvcHVsYXRpb24gbWVhbiBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIDIgZ3JvdXBzIG9mIHN0dWRlbnRzIHdpbGwgZmFsbCB3aXRoaW4gLS42NCBraWxvZ3JhbSBhbmQgLjY1IGtpbG9ncmFtLg0KYGBge3J9DQpudWxsX2Rpc3QgJT4lDQogIGdldF9jaShsZXZlbD0wLjk1KQ0KYGBgDQojIEV4ZXJjaXNlIDgNCg0KR2VuZXJhdGluZyBhIDk1JSBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgYXZlcmFnZSBoZWlnaHQgb2Ygc3R1ZGVudHMgaW4gdGhlIFlSQlNTIHN1cnZleSwgd2UgYXJlIGNvbmZpZGVudCB0aGF0IDk1IHRpbWVzIG91dCBvZiAxMDAsIHRoZSBtZWFuIGhlaWdodCBvZiB0aGUgaGlnaCBzY2hvb2wgc3R1ZGVudCBwb3B1bGF0aW9uIHdpbGwgYmUgd2l0aGluIDEuNjg5MSBtZXRlcnMgYW5kIDEuNjkyOCBtZXRlcnMNCg0KYGBge3J9DQoNCmF2Z19oZWlnaHRfZGlzdCA8LSB5cmJzc19uZXcgJT4lDQogc3BlY2lmeShyZXNwb25zZSA9IGhlaWdodCkgJT4lDQogZ2VuZXJhdGUocmVwcyA9IDEwMDAsIHR5cGUgPSAiYm9vdHN0cmFwIikgJT4lDQogY2FsY3VsYXRlKHN0YXQgPSAibWVhbiIpDQoNCmNpXzk1IDwtIGF2Z19oZWlnaHRfZGlzdCAlPiUNCiBnZXRfY2kobGV2ZWwgPSAwLjk1KQ0KY2lfOTUNCg0KYXZnX2hlaWdodF9kaXN0ICU+JQ0KICB2aXN1YWxpemUoY2lfZmlsbD0idHVycXVvaXNlIikgKyBzaGFkZV9jb25maWRlbmNlX2ludGVydmFsKGNpXzk1LCBjb2xvcj0idHVycXVvaXNlIikNCg0KYGBgDQpUaGlzIGFwcGVhcnMgdG8gYmUgaW4gbGluZSB3aXRoIHRoZSBmcmVxdWVuY3kgaGlzdG9ncmFtIG9mIGhlaWdodCBvdXQgb2YgdGhlIGVudGlyZSBzdHVkZW50cyBzdXJ2ZXllZA0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCmZpdmVudW0oeXJic3NfbmV3JGhlaWdodCkNCmdncGxvdCh5cmJzc19uZXcsIGFlcyh4PWhlaWdodCkpICsgZ2VvbV9oaXN0b2dyYW0oKQ0KYGBgDQoNCiMgRXhlcmNpc2UgOQ0KQXQgYSA5MCUgY29uZmlkZW5jZSBpbnRlcnZhbCwgdGhlIG1lYW4gaGVpZ2h0IG9mIHRoZSBoaWdoIHNjaG9vbCBzdHVkZW50IHBvcHVsYXRpb24gd2lsbCBiZSB3aXRoaW4gMS42ODk0IG1ldGVycyBhbmQgMS42OTI1IG1ldGVycy4gIFRoaXMgaXMgYSBzbGlnaHRseSBuYXJyb3dlciByYW5nZSBhcyB0aGVyZSBpcyBsZXNzIGFjY291bnRhYmlsaXR5IHRvIGNhcHR1cmUgdGhlIHBvcHVsYXRpb24gbWVhbiBhdCA5MCUgdGhhbiB0aGVyZSBpcyBhdCA5NSUuDQoNCmBgYHtyfQ0KY2lfOTAgPC0gYXZnX2hlaWdodF9kaXN0ICU+JQ0KIGdldF9jaShsZXZlbCA9IDAuOTApDQpjaV85MA0KDQphdmdfaGVpZ2h0X2Rpc3QgJT4lDQogIHZpc3VhbGl6ZSgpICsgc2hhZGVfY29uZmlkZW5jZV9pbnRlcnZhbChjaV85MCwgY29sb3I9ImFxdWFtYXJpbmUiKQ0KDQpgYGANCg0KIyBFeGVyY2lzZSAxMA0KYGBge3IgYWN0aXZpdHktaGVpZ2h0LCBtZXNzYWdlPUZBTFNFfQ0KDQpib3hwbG90KHlyYnNzX25ldyRoZWlnaHQgfiB5cmJzc19uZXckcGh5c2ljYWxfM3BsdXMsIHhsYWI9IjMrIERheXMgQWN0aXZlIiwgeWxhYj0iSGVpZ2h0IikNCg0KeXJic3NfbmV3ICU+JQ0KICBncm91cF9ieShwaHlzaWNhbF8zcGx1cykgJT4lIA0KICBzdW1tYXJpc2UobiA9IG4oKSwNCiAgICAgICAgICAgIG1pbiA9IGZpdmVudW0oaGVpZ2h0KVsxXSwNCiAgICAgICAgICAgIFExID0gZml2ZW51bShoZWlnaHQpWzJdLA0KICAgICAgICAgICAgbWVkaWFuID0gZml2ZW51bShoZWlnaHQpWzNdLA0KICAgICAgICAgICAgbWVhbiA9IHJvdW5kKG1lYW4oaGVpZ2h0KSwyKSwNCiAgICAgICAgICAgIFEzID0gZml2ZW51bShoZWlnaHQpWzRdLA0KICAgICAgICAgICAgbWF4ID0gZml2ZW51bShoZWlnaHQpWzVdLA0KICAgICAgICAgICAgSVFSID0gSVFSKGhlaWdodCkNCiAgICAgICAgICAgICkNCmBgYA0KQWN0dWFsIG9ic2VydmVkIHNhbXBsZSBtZWFuIGRpZmZlcmVuY2UgaXMgLjAzIG1ldGVycyBpbiBoZWlnaHQuDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0Kb2JzX2RpZmZfaGVpZ2h0IDwtIHlyYnNzX25ldyAlPiUNCiAgc3BlY2lmeShoZWlnaHQgfiBwaHlzaWNhbF8zcGx1cykgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gbWVhbnMiLCBvcmRlciA9IGMoInllcyIsICJubyIpKQ0KDQpudWxsX2Rpc3RfaGVpZ2h0IDwtIHlyYnNzX25ldyAlPiUNCiAgc3BlY2lmeShoZWlnaHQgfiBwaHlzaWNhbF8zcGx1cykgJT4lDQogIGh5cG90aGVzaXplKG51bGwgPSAiaW5kZXBlbmRlbmNlIikgJT4lDQogIGdlbmVyYXRlKHJlcHMgPSAxMDAwLCB0eXBlID0gInBlcm11dGUiKSAlPiUNCiAgY2FsY3VsYXRlKHN0YXQgPSAiZGlmZiBpbiBtZWFucyIsIG9yZGVyID0gYygieWVzIiwgIm5vIikpDQoNCmdncGxvdChkYXRhID0gbnVsbF9kaXN0X2hlaWdodCwgYWVzKHggPSBzdGF0KSkgKw0KICBnZW9tX2hpc3RvZ3JhbSgpDQoNCmBgYA0KVGhlIHByb2JhYmlsaXR5IG9mIG9ic2VydmluZyBhIHZhbHVlIG1vcmUgZXh0cmVtZSB0aGFuIG9ic2VydmVkIGVtcGlyaWNhbCBtZWFuIGRpZmZlcmVuY2UgaXMgZXh0cmVtZWx5IGxvdy4gIEEgcC12YWx1ZSBvZiAwIGFzIGNhbGN1bGF0ZWQgaGVyZSBpbmRpY2F0ZXMgdGhhdCBvbmx5IDMgb3IgbGVzcyBzaW11bGF0aW9ucyBvdXQgb2YgMTAwMCBwcm9kdWNlZCBhIG1lYW4gZGlmZmVyZW5jZSBncmVhdGVyIHRoYW4gYWN0dWFsIG9ic2VydmVkIGRpZmZlcmVuY2UuICBXZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgaW4gbWVhbiBoZWlnaHQgYmV0d2VlbiBzdHVkZW50cyB3aG8gYXJlIHBoeXNpY2FsbHkgYWN0aXZlIGFuZCBzdHVkZW50cyB3aG8gYXJlIG5vdC4NCmBgYHtyIG1lc3NhZ2U9RkFMU0V9DQpudWxsX2Rpc3RfaGVpZ2h0ICU+JQ0KICBnZXRfcF92YWx1ZShvYnNfc3RhdCA9IG9ic19kaWZmX2hlaWdodCwgZGlyZWN0aW9uID0gInR3b19zaWRlZCIpDQpgYGANCg0KLi4uDQoNCg==