library(tidyverse)         # for plotting and summarizing
library(ggridges)          # for ridge plots
library(ggmosaic)          # for mosaic plots
library(moderndive)        # for nice model output
library(broom)             # for nice model output 
library(infer)             # NEW! for making inferences about models
theme_set(theme_minimal()) #changes the theme of ggplots to theme_minimal, my personal favorite

Introduction

We have spent A LOT of time this semester fitting and interpreting model output. This is a VERY important part of modeling. Now, we are going to focus on making inferences from our models, that is, drawing conclusions to a larger population from the model that was built on a sample of data. In order to do this, we will need to gain some understanding of sampling variation. We are going to start with a very simple example, one that does not involve a model, at least not in the way we have been thinking of them all semester.

Reese’s Pieces activity, Part 1

Complete the following and discuss with the people at your table.

  1. Reese’s Pieces candies have three colors: orange, brown, and yellow. Which color do you think has more candies in a package: orange, brown or yellow?

  2. Guess the proportion of each color (orange, brown, and yellow) in a bag and record your answer.

  3. If each student in the class takes a sample of 25 Reese’s Pieces, would you expect every student to have the same proportion of oranges in their sample? Why?

  4. Each student should now take a virtual sample of 25 Reese’s Pieces from this applet. Just click the “Draw Samples” icon without changing any settings. As you are doing this, you want to pretend that we are at the Reese’s Pieces factory pulling out a sample of 25 Reese’s Pieces (if you have a peanut allergy, pretend they are color coated candies instead). Record the number and proportion of orange candies, and number of browns and yellows (you’ll need to count those by hand) in your sample below.

number of oranges: proportion of oranges:

number of browns: number of yellows:

  1. Once everyone has done that, we will record all our observations in a “dotplot” (like a histogram but we see each individual data point) in this Google sheet. What does this distribution show us? Why is it important?

Reese’s Pieces activity, Part 2

We will continue to use this applet to help us with some simulations. You will see a big container of colored candies: that represents the POPULATION. What proportion are orange candies in the population? This is set in the Probability of orange box. Make sure this is at 0.5, which according to this Wikipedia article, is the true proportion.

  1. How does the population parameter, in this case the population proportion of orange candies, \(p\) compare to the sample statistic, the proportion of orange candies in your sample, \(\hat{p}\)? How does it compare to the center of the class distribution?

  2. Click the “Reset” button. Then choose “Proportion of orange” (rather than the default “Number of orange”). Now, turn off the animation by clicking on the box next to “Animate” so that there is no check mark there. Change the “Number of samples” to 200. Click on draw samples, and see the distribution created. This is called a sampling distribution of \(\hat{p}\). What does each dot represent? Describe the distribution’s shape, center and spread. How does this compare to the one our class constructed on the board?

  3. Click reset. What happens to the sampling distribution of \(\hat{p}\) if you change the number of candies in each sample? Try using a sample of size 10 and a sample of size 100 and discuss the following questions for each. How close is each \(\hat{p}\) to the POPULATION PARAMETER? How does the shape, center, and spread of the distribution change? Pay close attention to the x-axis.

Reese’s Pieces activity, Part 3

It was nice to be able to sample from the population over and over again, but in the real world, we can’t usually do that. We usually have just one sample. So, how do we learn about sampling variation without sampling from the population? We use a technique called bootstrapping!

Here is the general bootstrapping algorithm:

  • Collect a random sample.
  • Take a sample, WITH REPLACEMENT, of the original sample that is the same size as the original sample. This is called the resample or the bootstrap sample.
  • Compute the statistic you are interested in on the bootstrap sample. So, \(\hat{p}\), in this example.
  • Repeat the previous two steps a reasonable number of times, say at least 100 but more if you can.

If you’d like to see an example of doing a tactile bootstrap sample, please see the video here. You can speed it up or skip through some parts if desired.

  1. We are going to use R to help us do more simulations. Each of you will use the data from the original sample you took. We first create a dataset with two variables: obs is just the observation number, color is the color of that observation. The observations will be numbered 1, 2, …, 25. Replace my 14, 6, and 5 with the numbers you got for each color.
initial_random_sample <- tibble(obs = 1:25,
                                color = c(rep("o", 14), 
                                          rep("y", 6),
                                          rep("b", 5)))

What is the proportion of oranges (o’s) in this sample?

initial_random_sample %>% 
  count(color) %>% 
  mutate(prop = n/sum(n))
  1. Next, use the sample_n() function to draw a sample, with replacement, from the original sample and of the same size as the original sample. How many times does observation 12 show up in the resample? How many times does observation 1 show up in the resample? NOTE: The set.seed() function at the beginning allows you to replicate the random sampling process so that you get the same random sample every time the code runs (including when you knit the document). This also means that if someone else uses that same seed, they will get the same result, as long as they started with the same data. It is very important to use set.seed() anytime we conduct a random process so that we can replicate it. It does not matter what number we put in there.
set.seed(1211)

bootstrap_sample1 <- 
  initial_random_sample %>% 
  sample_n(size = 25, #sample size
           replace = TRUE #sample with replacement
           )

bootstrap_sample1 %>% 
  count(obs, sort = TRUE)
  1. What proportion of observations in bootstrap_sample1 are orange? Is it the same proportion as in initial_random_sample?
bootstrap_sample1 %>% 
  count(color) %>% 
  mutate(prop = n/sum(n))
  1. Now, we want to take MANY bootstrap samples. There is a function that will help us do that: rep_sample_n() from the infer library. Initially, we’ll just take 2 bootstrap samples. We set a seed again because we’re performing a random process.
set.seed(14)
bootstrap_2samps <- 
  initial_random_sample %>% 
  rep_sample_n(size = 25, #size of each sample
               replace = TRUE, #sample with replacement
               reps = 2 #how many samples of size 25 to take 
                        #(different from sample size)
               )

bootstrap_2samps

Notice the rep_sample_n() function created a column called replicate. Now, we can find the proportion of oranges for each replicate. Describe what each piece of the code does below. It might help to only run part of the code. To do that, highlight the part you want to run and do cmd + return (Mac) or control + enter (Windows)

bootstrap_2samps %>% 
  count(replicate, color) %>% 
  group_by(replicate) %>% 
  mutate(prop = n/sum(n)) %>% 
  filter(color == "o")
  1. Now, take 200 bootstrap samples and find the proportion of oranges in each of the bootstrap samples. I started the code below. Be sure to remove the eval=FALSE from the code chunk options.
set.seed(14)
bootstrap_200samps <- 
  initial_random_sample %>% 
  rep_sample_n(size = ?, #size of each sample
               replace = ?, #sample with replacement
               reps = ? #how many samples of size 25 to take 
                        #(different from sample size)
               )

phats_200 <- #put the code that finds the proportion of oranges in each bootstramp sample here.

#Show the first ten rows of phats_200
phats_200 %>% 
  slice(1:10)
  1. Make a histogram to examine the distribution of \(\hat{p}\). This is called the bootstrap distribution of \(\hat{p}\). How is this different from the true sampling distribution?

  2. Start from the beginning. What happens if you start with a larger initial sample? A smaller initial sample? (You can use the applet to generate new samples.)

LS0tCnRpdGxlOiAiU2FtcGxpbmcgRGlzdHJpYnV0aW9ucyBhbmQgQm9vdHN0cmFwcGluZyBJbnRyb2R1Y3Rpb246IFJlZXNlJ3MgUGllY2VzIEFjdGl2aXR5IgpuYW1lOiAiUFVUIE5BTUUoUykgSEVSRSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKSAgICAgICAgICMgZm9yIHBsb3R0aW5nIGFuZCBzdW1tYXJpemluZwpsaWJyYXJ5KGdncmlkZ2VzKSAgICAgICAgICAjIGZvciByaWRnZSBwbG90cwpsaWJyYXJ5KGdnbW9zYWljKSAgICAgICAgICAjIGZvciBtb3NhaWMgcGxvdHMKbGlicmFyeShtb2Rlcm5kaXZlKSAgICAgICAgIyBmb3IgbmljZSBtb2RlbCBvdXRwdXQKbGlicmFyeShicm9vbSkgICAgICAgICAgICAgIyBmb3IgbmljZSBtb2RlbCBvdXRwdXQgCmxpYnJhcnkoaW5mZXIpICAgICAgICAgICAgICMgTkVXISBmb3IgbWFraW5nIGluZmVyZW5jZXMgYWJvdXQgbW9kZWxzCnRoZW1lX3NldCh0aGVtZV9taW5pbWFsKCkpICNjaGFuZ2VzIHRoZSB0aGVtZSBvZiBnZ3Bsb3RzIHRvIHRoZW1lX21pbmltYWwsIG15IHBlcnNvbmFsIGZhdm9yaXRlCmBgYAoKIyBJbnRyb2R1Y3Rpb24KCldlIGhhdmUgc3BlbnQgQSBMT1Qgb2YgdGltZSB0aGlzIHNlbWVzdGVyIGZpdHRpbmcgYW5kIGludGVycHJldGluZyBtb2RlbCBvdXRwdXQuIFRoaXMgaXMgYSBWRVJZIGltcG9ydGFudCBwYXJ0IG9mIG1vZGVsaW5nLiBOb3csIHdlIGFyZSBnb2luZyB0byBmb2N1cyBvbiBtYWtpbmcgaW5mZXJlbmNlcyBmcm9tIG91ciBtb2RlbHMsIHRoYXQgaXMsIGRyYXdpbmcgY29uY2x1c2lvbnMgdG8gYSBsYXJnZXIgcG9wdWxhdGlvbiBmcm9tIHRoZSBtb2RlbCB0aGF0IHdhcyBidWlsdCBvbiBhIHNhbXBsZSBvZiBkYXRhLiBJbiBvcmRlciB0byBkbyB0aGlzLCB3ZSB3aWxsIG5lZWQgdG8gZ2FpbiBzb21lIHVuZGVyc3RhbmRpbmcgb2Ygc2FtcGxpbmcgdmFyaWF0aW9uLiBXZSBhcmUgZ29pbmcgdG8gc3RhcnQgd2l0aCBhIHZlcnkgc2ltcGxlIGV4YW1wbGUsIG9uZSB0aGF0IGRvZXMgbm90IGludm9sdmUgYSBtb2RlbCwgYXQgbGVhc3Qgbm90IGluIHRoZSB3YXkgd2UgaGF2ZSBiZWVuIHRoaW5raW5nIG9mIHRoZW0gYWxsIHNlbWVzdGVyLgoKIyBSZWVzZSdzIFBpZWNlcyBhY3Rpdml0eSwgUGFydCAxCgpDb21wbGV0ZSB0aGUgZm9sbG93aW5nIGFuZCBkaXNjdXNzIHdpdGggdGhlIHBlb3BsZSBhdCB5b3VyIHRhYmxlLiAKCjEuIFJlZXNlJ3MgUGllY2VzIGNhbmRpZXMgaGF2ZSB0aHJlZSBjb2xvcnM6IG9yYW5nZSwgYnJvd24sIGFuZCB5ZWxsb3cuIFdoaWNoIGNvbG9yIGRvIHlvdSB0aGluayBoYXMgbW9yZSBjYW5kaWVzIGluIGEgcGFja2FnZTogb3JhbmdlLCBicm93biBvciB5ZWxsb3c/IAoKMi4gR3Vlc3MgdGhlIHByb3BvcnRpb24gb2YgZWFjaCBjb2xvciAob3JhbmdlLCBicm93biwgYW5kIHllbGxvdykgaW4gYSBiYWcgYW5kIHJlY29yZCB5b3VyIGFuc3dlci4KCjMuIElmIGVhY2ggc3R1ZGVudCBpbiB0aGUgY2xhc3MgdGFrZXMgYSBzYW1wbGUgb2YgMjUgUmVlc2UncyBQaWVjZXMsIHdvdWxkIHlvdSBleHBlY3QgZXZlcnkgc3R1ZGVudCB0byBoYXZlIHRoZSBzYW1lIHByb3BvcnRpb24gb2Ygb3JhbmdlcyBpbiB0aGVpciBzYW1wbGU/IFdoeT8KCjQuIEVhY2ggc3R1ZGVudCBzaG91bGQgbm93IHRha2UgYSB2aXJ0dWFsIHNhbXBsZSBvZiAyNSBSZWVzZSdzIFBpZWNlcyBmcm9tIFt0aGlzXShodHRwOi8vd3d3LnJvc3NtYW5jaGFuY2UuY29tL2FwcGxldHMvT25lUHJvcC9PbmVQcm9wLmh0bT9jYW5keT0xKSBhcHBsZXQuIEp1c3QgY2xpY2sgdGhlICJEcmF3IFNhbXBsZXMiIGljb24gd2l0aG91dCBjaGFuZ2luZyBhbnkgc2V0dGluZ3MuIEFzIHlvdSBhcmUgZG9pbmcgdGhpcywgeW91IHdhbnQgdG8gcHJldGVuZCB0aGF0IHdlIGFyZSBhdCB0aGUgUmVlc2UncyBQaWVjZXMgZmFjdG9yeSBwdWxsaW5nIG91dCBhIHNhbXBsZSBvZiAyNSBSZWVzZSdzIFBpZWNlcyAoaWYgeW91IGhhdmUgYSBwZWFudXQgYWxsZXJneSwgcHJldGVuZCB0aGV5IGFyZSBjb2xvciBjb2F0ZWQgY2FuZGllcyBpbnN0ZWFkKS4gUmVjb3JkIHRoZSBudW1iZXIgYW5kIHByb3BvcnRpb24gb2Ygb3JhbmdlIGNhbmRpZXMsIGFuZCBudW1iZXIgb2YgYnJvd25zIGFuZCB5ZWxsb3dzICh5b3UnbGwgbmVlZCB0byBjb3VudCB0aG9zZSBieSBoYW5kKSBpbiB5b3VyIHNhbXBsZSBiZWxvdy4gCgpudW1iZXIgb2Ygb3JhbmdlczoKcHJvcG9ydGlvbiBvZiBvcmFuZ2VzOgoKbnVtYmVyIG9mIGJyb3duczoKbnVtYmVyIG9mIHllbGxvd3M6Cgo1LiBPbmNlIGV2ZXJ5b25lIGhhcyBkb25lIHRoYXQsIHdlIHdpbGwgcmVjb3JkIGFsbCBvdXIgb2JzZXJ2YXRpb25zIGluIGEgImRvdHBsb3QiIChsaWtlIGEgaGlzdG9ncmFtIGJ1dCB3ZSBzZWUgZWFjaCBpbmRpdmlkdWFsIGRhdGEgcG9pbnQpIGluIFt0aGlzIEdvb2dsZSBzaGVldF0oaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMWFNdVh1M3gwYnMyVko1ZUZiWkY4VjNZa0xMS0RtY2NnNWV6Y2xOcUN6TGsvZWRpdD91c3A9c2hhcmluZykuIFdoYXQgZG9lcyB0aGlzIGRpc3RyaWJ1dGlvbiBzaG93IHVzPyBXaHkgaXMgaXQgaW1wb3J0YW50PyAKCiMgUmVlc2UncyBQaWVjZXMgYWN0aXZpdHksIFBhcnQgMgoKV2Ugd2lsbCBjb250aW51ZSB0byB1c2UgW3RoaXNdKGh0dHA6Ly93d3cucm9zc21hbmNoYW5jZS5jb20vYXBwbGV0cy9PbmVQcm9wL09uZVByb3AuaHRtP2NhbmR5PTEpIGFwcGxldCB0byBoZWxwIHVzIHdpdGggc29tZSBzaW11bGF0aW9ucy4gWW91IHdpbGwgc2VlIGEgYmlnIGNvbnRhaW5lciBvZiBjb2xvcmVkIGNhbmRpZXM6IHRoYXQgcmVwcmVzZW50cyB0aGUgUE9QVUxBVElPTi4gV2hhdCBwcm9wb3J0aW9uIGFyZSBvcmFuZ2UgY2FuZGllcyBpbiB0aGUgcG9wdWxhdGlvbj8gVGhpcyBpcyBzZXQgaW4gdGhlIFByb2JhYmlsaXR5IG9mIG9yYW5nZSBib3guIE1ha2Ugc3VyZSB0aGlzIGlzIGF0IDAuNSwgd2hpY2ggYWNjb3JkaW5nIHRvIFt0aGlzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9SZWVzZSUyN3NfUGllY2VzI0V4dGVybmFsX2xpbmtzKSBXaWtpcGVkaWEgYXJ0aWNsZSwgaXMgdGhlIHRydWUgcHJvcG9ydGlvbi4KCjYuIEhvdyBkb2VzIHRoZSBwb3B1bGF0aW9uIHBhcmFtZXRlciwgaW4gdGhpcyBjYXNlIHRoZSBwb3B1bGF0aW9uIHByb3BvcnRpb24gb2Ygb3JhbmdlIGNhbmRpZXMsICRwJCBjb21wYXJlIHRvIHRoZSBzYW1wbGUgc3RhdGlzdGljLCB0aGUgcHJvcG9ydGlvbiBvZiBvcmFuZ2UgY2FuZGllcyBpbiB5b3VyIHNhbXBsZSwgJFxoYXR7cH0kPyBIb3cgZG9lcyBpdCBjb21wYXJlIHRvIHRoZSBjZW50ZXIgb2YgdGhlIGNsYXNzIGRpc3RyaWJ1dGlvbj8KCjcuIENsaWNrIHRoZSAiUmVzZXQiIGJ1dHRvbi4gVGhlbiBjaG9vc2UgIlByb3BvcnRpb24gb2Ygb3JhbmdlIiAocmF0aGVyIHRoYW4gdGhlIGRlZmF1bHQgIk51bWJlciBvZiBvcmFuZ2UiKS4gTm93LCB0dXJuIG9mZiB0aGUgYW5pbWF0aW9uIGJ5IGNsaWNraW5nIG9uIHRoZSBib3ggbmV4dCB0byAiQW5pbWF0ZSIgc28gdGhhdCB0aGVyZSBpcyBubyBjaGVjayBtYXJrIHRoZXJlLiAgQ2hhbmdlIHRoZSAiTnVtYmVyIG9mIHNhbXBsZXMiIHRvIDIwMC4gQ2xpY2sgb24gZHJhdyBzYW1wbGVzLCBhbmQgc2VlIHRoZSBkaXN0cmlidXRpb24gY3JlYXRlZC4gVGhpcyBpcyBjYWxsZWQgYSAqKnNhbXBsaW5nIGRpc3RyaWJ1dGlvbioqIG9mICRcaGF0e3B9JC4gV2hhdCBkb2VzIGVhY2ggZG90IHJlcHJlc2VudD8gRGVzY3JpYmUgdGhlIGRpc3RyaWJ1dGlvbidzIHNoYXBlLCBjZW50ZXIgYW5kIHNwcmVhZC4gSG93IGRvZXMgdGhpcyBjb21wYXJlIHRvIHRoZSBvbmUgb3VyIGNsYXNzIGNvbnN0cnVjdGVkIG9uIHRoZSBib2FyZD8KCjguIENsaWNrIHJlc2V0LiBXaGF0IGhhcHBlbnMgdG8gdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiAkXGhhdHtwfSQgaWYgeW91IGNoYW5nZSB0aGUgbnVtYmVyIG9mIGNhbmRpZXMgaW4gZWFjaCBzYW1wbGU/IFRyeSB1c2luZyBhIHNhbXBsZSBvZiBzaXplIDEwIGFuZCBhIHNhbXBsZSBvZiBzaXplIDEwMCBhbmQgZGlzY3VzcyB0aGUgZm9sbG93aW5nIHF1ZXN0aW9ucyBmb3IgZWFjaC4gSG93IGNsb3NlIGlzIGVhY2ggJFxoYXR7cH0kIHRvIHRoZSBQT1BVTEFUSU9OIFBBUkFNRVRFUj8gSG93IGRvZXMgdGhlIHNoYXBlLCBjZW50ZXIsIGFuZCBzcHJlYWQgb2YgdGhlIGRpc3RyaWJ1dGlvbiBjaGFuZ2U/IFBheSBjbG9zZSBhdHRlbnRpb24gdG8gdGhlIHgtYXhpcy4gCgojIFJlZXNlJ3MgUGllY2VzIGFjdGl2aXR5LCBQYXJ0IDMKCkl0IHdhcyBuaWNlIHRvIGJlIGFibGUgdG8gc2FtcGxlIGZyb20gdGhlIHBvcHVsYXRpb24gb3ZlciBhbmQgb3ZlciBhZ2FpbiwgYnV0IGluIHRoZSByZWFsIHdvcmxkLCB3ZSBjYW4ndCB1c3VhbGx5IGRvIHRoYXQuIFdlIHVzdWFsbHkgaGF2ZSBqdXN0IG9uZSBzYW1wbGUuIFNvLCBob3cgZG8gd2UgbGVhcm4gYWJvdXQgc2FtcGxpbmcgdmFyaWF0aW9uIHdpdGhvdXQgc2FtcGxpbmcgZnJvbSB0aGUgcG9wdWxhdGlvbj8gV2UgdXNlIGEgdGVjaG5pcXVlIGNhbGxlZCBib290c3RyYXBwaW5nIQoKSGVyZSBpcyB0aGUgZ2VuZXJhbCBib290c3RyYXBwaW5nIGFsZ29yaXRobToKCiogQ29sbGVjdCBhIHJhbmRvbSBzYW1wbGUuICAKKiBUYWtlIGEgc2FtcGxlLCBXSVRIIFJFUExBQ0VNRU5ULCBvZiB0aGUgb3JpZ2luYWwgc2FtcGxlIHRoYXQgaXMgdGhlIHNhbWUgc2l6ZSBhcyB0aGUgb3JpZ2luYWwgc2FtcGxlLiBUaGlzIGlzIGNhbGxlZCB0aGUgcmVzYW1wbGUgb3IgdGhlIGJvb3RzdHJhcCBzYW1wbGUuICAKKiBDb21wdXRlIHRoZSBzdGF0aXN0aWMgeW91IGFyZSBpbnRlcmVzdGVkIGluIG9uIHRoZSBib290c3RyYXAgc2FtcGxlLiBTbywgJFxoYXR7cH0kLCBpbiB0aGlzIGV4YW1wbGUuICAKKiBSZXBlYXQgdGhlIHByZXZpb3VzIHR3byBzdGVwcyBhIHJlYXNvbmFibGUgbnVtYmVyIG9mIHRpbWVzLCBzYXkgYXQgbGVhc3QgMTAwIGJ1dCBtb3JlIGlmIHlvdSBjYW4uIAoKSWYgeW91J2QgbGlrZSB0byBzZWUgYW4gZXhhbXBsZSBvZiBkb2luZyBhIHRhY3RpbGUgYm9vdHN0cmFwIHNhbXBsZSwgcGxlYXNlIHNlZSB0aGUgdmlkZW8gW2hlcmVdKGh0dHBzOi8vbWFjYWxlc3Rlci52b2ljZXRocmVhZC5jb20vc2hhcmUvMTQwMDYyNDgvKS4gWW91IGNhbiBzcGVlZCBpdCB1cCBvciBza2lwIHRocm91Z2ggc29tZSBwYXJ0cyBpZiBkZXNpcmVkLgoKOS4gV2UgYXJlIGdvaW5nIHRvIHVzZSBSIHRvIGhlbHAgdXMgZG8gbW9yZSBzaW11bGF0aW9ucy4gRWFjaCBvZiB5b3Ugd2lsbCB1c2UgdGhlIGRhdGEgZnJvbSB0aGUgb3JpZ2luYWwgc2FtcGxlIHlvdSB0b29rLiBXZSBmaXJzdCBjcmVhdGUgYSBkYXRhc2V0IHdpdGggdHdvIHZhcmlhYmxlczogYG9ic2AgaXMganVzdCB0aGUgb2JzZXJ2YXRpb24gbnVtYmVyLCBgY29sb3JgIGlzIHRoZSBjb2xvciBvZiB0aGF0IG9ic2VydmF0aW9uLiBUaGUgb2JzZXJ2YXRpb25zIHdpbGwgYmUgbnVtYmVyZWQgMSwgMiwgLi4uLCAyNS4gUmVwbGFjZSBteSAxNCwgNiwgYW5kIDUgd2l0aCB0aGUgbnVtYmVycyB5b3UgZ290IGZvciBlYWNoIGNvbG9yLgoKYGBge3J9CmluaXRpYWxfcmFuZG9tX3NhbXBsZSA8LSB0aWJibGUob2JzID0gMToyNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGMocmVwKCJvIiwgMTQpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwKCJ5IiwgNiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiYiIsIDUpKSkKYGBgCgpXaGF0IGlzIHRoZSBwcm9wb3J0aW9uIG9mIG9yYW5nZXMgKG8ncykgaW4gdGhpcyBzYW1wbGU/CgpgYGB7cn0KaW5pdGlhbF9yYW5kb21fc2FtcGxlICU+JSAKICBjb3VudChjb2xvcikgJT4lIAogIG11dGF0ZShwcm9wID0gbi9zdW0obikpCmBgYAoKMTAuIE5leHQsIHVzZSB0aGUgYHNhbXBsZV9uKClgIGZ1bmN0aW9uIHRvIGRyYXcgYSBzYW1wbGUsIHdpdGggcmVwbGFjZW1lbnQsIGZyb20gdGhlIG9yaWdpbmFsIHNhbXBsZSBhbmQgb2YgdGhlIHNhbWUgc2l6ZSBhcyB0aGUgb3JpZ2luYWwgc2FtcGxlLiBIb3cgbWFueSB0aW1lcyBkb2VzIG9ic2VydmF0aW9uIDEyIHNob3cgdXAgaW4gdGhlIHJlc2FtcGxlPyBIb3cgbWFueSB0aW1lcyBkb2VzIG9ic2VydmF0aW9uIDEgc2hvdyB1cCBpbiB0aGUgcmVzYW1wbGU/ICpOT1RFKjogVGhlIGBzZXQuc2VlZCgpYCBmdW5jdGlvbiBhdCB0aGUgYmVnaW5uaW5nIGFsbG93cyB5b3UgdG8gcmVwbGljYXRlIHRoZSByYW5kb20gc2FtcGxpbmcgcHJvY2VzcyBzbyB0aGF0IHlvdSBnZXQgdGhlIHNhbWUgcmFuZG9tIHNhbXBsZSBldmVyeSB0aW1lIHRoZSBjb2RlIHJ1bnMgKGluY2x1ZGluZyB3aGVuIHlvdSBrbml0IHRoZSBkb2N1bWVudCkuIFRoaXMgYWxzbyBtZWFucyB0aGF0IGlmIHNvbWVvbmUgZWxzZSB1c2VzIHRoYXQgc2FtZSBzZWVkLCB0aGV5IHdpbGwgZ2V0IHRoZSBzYW1lIHJlc3VsdCwgYXMgbG9uZyBhcyB0aGV5IHN0YXJ0ZWQgd2l0aCB0aGUgc2FtZSBkYXRhLiBJdCBpcyB2ZXJ5IGltcG9ydGFudCB0byB1c2UgYHNldC5zZWVkKClgIGFueXRpbWUgd2UgY29uZHVjdCBhIHJhbmRvbSBwcm9jZXNzIHNvIHRoYXQgd2UgY2FuIHJlcGxpY2F0ZSBpdC4gSXQgZG9lcyBub3QgbWF0dGVyIHdoYXQgbnVtYmVyIHdlIHB1dCBpbiB0aGVyZS4gIAoKYGBge3J9CnNldC5zZWVkKDEyMTEpCgpib290c3RyYXBfc2FtcGxlMSA8LSAKICBpbml0aWFsX3JhbmRvbV9zYW1wbGUgJT4lIAogIHNhbXBsZV9uKHNpemUgPSAyNSwgI3NhbXBsZSBzaXplCiAgICAgICAgICAgcmVwbGFjZSA9IFRSVUUgI3NhbXBsZSB3aXRoIHJlcGxhY2VtZW50CiAgICAgICAgICAgKQoKYm9vdHN0cmFwX3NhbXBsZTEgJT4lIAogIGNvdW50KG9icywgc29ydCA9IFRSVUUpCmBgYAoKCjExLiBXaGF0IHByb3BvcnRpb24gb2Ygb2JzZXJ2YXRpb25zIGluIGBib290c3RyYXBfc2FtcGxlMWAgYXJlIG9yYW5nZT8gSXMgaXQgdGhlIHNhbWUgcHJvcG9ydGlvbiBhcyBpbiBgaW5pdGlhbF9yYW5kb21fc2FtcGxlYD8KCmBgYHtyfQpib290c3RyYXBfc2FtcGxlMSAlPiUgCiAgY291bnQoY29sb3IpICU+JSAKICBtdXRhdGUocHJvcCA9IG4vc3VtKG4pKQpgYGAKCjEyLiBOb3csIHdlIHdhbnQgdG8gdGFrZSBNQU5ZIGJvb3RzdHJhcCBzYW1wbGVzLiBUaGVyZSBpcyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBoZWxwIHVzIGRvIHRoYXQ6IGByZXBfc2FtcGxlX24oKWAgZnJvbSB0aGUgYGluZmVyYCBsaWJyYXJ5LiBJbml0aWFsbHksIHdlJ2xsIGp1c3QgdGFrZSAyIGJvb3RzdHJhcCBzYW1wbGVzLiBXZSBzZXQgYSBzZWVkIGFnYWluIGJlY2F1c2Ugd2UncmUgcGVyZm9ybWluZyBhIHJhbmRvbSBwcm9jZXNzLgoKYGBge3J9CnNldC5zZWVkKDE0KQpib290c3RyYXBfMnNhbXBzIDwtIAogIGluaXRpYWxfcmFuZG9tX3NhbXBsZSAlPiUgCiAgcmVwX3NhbXBsZV9uKHNpemUgPSAyNSwgI3NpemUgb2YgZWFjaCBzYW1wbGUKICAgICAgICAgICAgICAgcmVwbGFjZSA9IFRSVUUsICNzYW1wbGUgd2l0aCByZXBsYWNlbWVudAogICAgICAgICAgICAgICByZXBzID0gMiAjaG93IG1hbnkgc2FtcGxlcyBvZiBzaXplIDI1IHRvIHRha2UgCiAgICAgICAgICAgICAgICAgICAgICAgICMoZGlmZmVyZW50IGZyb20gc2FtcGxlIHNpemUpCiAgICAgICAgICAgICAgICkKCmJvb3RzdHJhcF8yc2FtcHMKYGBgCgpOb3RpY2UgdGhlIGByZXBfc2FtcGxlX24oKWAgZnVuY3Rpb24gY3JlYXRlZCBhIGNvbHVtbiBjYWxsZWQgYHJlcGxpY2F0ZWAuIE5vdywgd2UgY2FuIGZpbmQgdGhlIHByb3BvcnRpb24gb2Ygb3JhbmdlcyBmb3IgZWFjaCByZXBsaWNhdGUuIERlc2NyaWJlIHdoYXQgZWFjaCBwaWVjZSBvZiB0aGUgY29kZSBkb2VzIGJlbG93LiBJdCBtaWdodCBoZWxwIHRvIG9ubHkgcnVuIHBhcnQgb2YgdGhlIGNvZGUuIFRvIGRvIHRoYXQsIGhpZ2hsaWdodCB0aGUgcGFydCB5b3Ugd2FudCB0byBydW4gYW5kIGRvIGNtZCArIHJldHVybiAoTWFjKSBvciBjb250cm9sICsgZW50ZXIgKFdpbmRvd3MpCgpgYGB7cn0KYm9vdHN0cmFwXzJzYW1wcyAlPiUgCiAgY291bnQocmVwbGljYXRlLCBjb2xvcikgJT4lIAogIGdyb3VwX2J5KHJlcGxpY2F0ZSkgJT4lIAogIG11dGF0ZShwcm9wID0gbi9zdW0obikpICU+JSAKICBmaWx0ZXIoY29sb3IgPT0gIm8iKQpgYGAKCgoxMy4gTm93LCB0YWtlIDIwMCBib290c3RyYXAgc2FtcGxlcyBhbmQgZmluZCB0aGUgcHJvcG9ydGlvbiBvZiBvcmFuZ2VzIGluIGVhY2ggb2YgdGhlIGJvb3RzdHJhcCBzYW1wbGVzLiBJIHN0YXJ0ZWQgdGhlIGNvZGUgYmVsb3cuIEJlIHN1cmUgdG8gcmVtb3ZlIHRoZSBgZXZhbD1GQUxTRWAgZnJvbSB0aGUgY29kZSBjaHVuayBvcHRpb25zLgoKYGBge3IsIGV2YWw9RkFMU0V9CnNldC5zZWVkKDE0KQpib290c3RyYXBfMjAwc2FtcHMgPC0gCiAgaW5pdGlhbF9yYW5kb21fc2FtcGxlICU+JSAKICByZXBfc2FtcGxlX24oc2l6ZSA9ID8sICNzaXplIG9mIGVhY2ggc2FtcGxlCiAgICAgICAgICAgICAgIHJlcGxhY2UgPSA/LCAjc2FtcGxlIHdpdGggcmVwbGFjZW1lbnQKICAgICAgICAgICAgICAgcmVwcyA9ID8gI2hvdyBtYW55IHNhbXBsZXMgb2Ygc2l6ZSAyNSB0byB0YWtlIAogICAgICAgICAgICAgICAgICAgICAgICAjKGRpZmZlcmVudCBmcm9tIHNhbXBsZSBzaXplKQogICAgICAgICAgICAgICApCgpwaGF0c18yMDAgPC0gI3B1dCB0aGUgY29kZSB0aGF0IGZpbmRzIHRoZSBwcm9wb3J0aW9uIG9mIG9yYW5nZXMgaW4gZWFjaCBib290c3RyYW1wIHNhbXBsZSBoZXJlLgoKI1Nob3cgdGhlIGZpcnN0IHRlbiByb3dzIG9mIHBoYXRzXzIwMApwaGF0c18yMDAgJT4lIAogIHNsaWNlKDE6MTApCgpgYGAKCjE0LiBNYWtlIGEgaGlzdG9ncmFtIHRvIGV4YW1pbmUgdGhlIGRpc3RyaWJ1dGlvbiBvZiAkXGhhdHtwfSQuIFRoaXMgaXMgY2FsbGVkIHRoZSBib290c3RyYXAgZGlzdHJpYnV0aW9uIG9mICRcaGF0e3B9JC4gSG93IGlzIHRoaXMgZGlmZmVyZW50IGZyb20gdGhlIHRydWUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uPwoKMTUuIFN0YXJ0IGZyb20gdGhlIGJlZ2lubmluZy4gV2hhdCBoYXBwZW5zIGlmIHlvdSBzdGFydCB3aXRoIGEgbGFyZ2VyIGluaXRpYWwgc2FtcGxlPyBBIHNtYWxsZXIgaW5pdGlhbCBzYW1wbGU/IChZb3UgY2FuIHVzZSB0aGUgYXBwbGV0IHRvIGdlbmVyYXRlIG5ldyBzYW1wbGVzLikK