To start, let’s look at the standard normal distribution. R is very good (using the norm functions) at generating a simulated data set with a normal distribution. The standard normal distribution is a normal distribution with a mean of 0 and standard deviation of 1.
x.values = seq(-4,4, length = 1000)
y.values = dnorm(x.values)
plot(x.values, y.values, type="l", lty=1, xlab="Z value", ylab="Probability", main="Normal Distribution")

To start, for each of the 3 lines of code, reason out what is happening. What variables were created and how did we ensure that the data generated followed a normal distribution?
Now, just like in the past with pbinom, we can ask how much of the curve falls below a particular value.In this case we’ll ask about the value 0 before running the code, think to yourself what the answer should be.
pnorm(0)
[1] 0.5
A. Probabilities associated with values < or > z ———————— In the examples below, we’ll use z values of + 1.96 and -1.96 because we know that these approximate values mark off the upper and lower 2.5% of the standard normal distribution. Therefore, this corresponds to a typical alpha = 0.05 for a two-tailed hypothesis test (which we will learn more about in the coming weeks).
pnorm(1.96, lower.tail=TRUE)
[1] 0.9750021
The answer tells us what we already know: 97.5% of the normal distribution occurs below the z-value of 1.96.
We can add a line to the plot to show where this would be using abline. 97.5% of the distribution falls below this line
plot(x.values, y.values, type="l", lty=1, xlab="Z value", ylab="Probability", main="Normal Distribution")
abline(v = 1.96)

Exercise 1: Use the abline() function to add lines at the appropriate z-score to demonstrate the 68-95-99.7 of this standard normal curve.
plot(x.values, y.values, type="l", lty=1, xlab="Z value", ylab="Probability", main="Normal Distribution")
abline(v = 1)
abline(v = -1)
abline(v = 2)
abline(v = -2)
abline(v = 3)
abline(v = -3)

As discussed on Tuesday, We can also do the reverse, deciding first how much probability we want (percentile) and then calculating what critical values are associated with those probabilities. This uses the qnorm function. If we want to know what z value marked off the lower 2.5% of a standard normal distribution, we would use:
qnorm(0.025)
[1] -1.959964
This tells us that the z value of -1.96 marks off the lower 2.5% of thestandard normal distribution. To determine the z value that marks off the upper 2.5% of the distribution, I type:
qnorm(0.975)
[1] 1.959964
Exercise 2: So far we have demonstrated everything with a standard normal distribution. But most normal curves are not standard normal. Generate a curve (like we did above for the standard normal distribution) and plot it with a mean of 20 and a standard deviation of 1.65. Identify the value at which 97.5% of the distribution falls below this value.
x.values = seq(10,30, length = 1000)
y.values = dnorm(x.values, 20, 1.65)
plot(x.values, y.values, type="l", lty=1, xlab="Z value", ylab="Probability", main="Normal Distribution")

qnorm(.975, 20, 1.65)
[1] 23.23394
Now that we have generated normal distributions, lets take a look at some read data and compare it to the normal distribution. Run the following lines of code, which will download and load a dataset of measurements from 247 men and 260 women, most of whom were considered healthy young adults. You’ll see that for every observation we have 25 measurements, many of which are either diameters or girths. A key to the variable names can be found at http://www.openintro.org/stat/data/bdims.php, but we’ll be focusing on just three columns to get started: weight in kg (wgt), height in cm (hgt), and sex (1 indicates male, 0 indicates female).
download.file("http://www.openintro.org/stat/data/bdims.RData", destfile = "bdims.RData")
trying URL 'http://www.openintro.org/stat/data/bdims.RData'
Content type 'unknown' length 20982 bytes (20 KB)
==================================================
downloaded 20 KB
load("bdims.RData")
Since this dataset contains both men and women, it would be helpful to seperate the data into two sets, one of females and one of males. There is a great function in R that can subset by a categorical varaible. After running the code below, determine what datasets are newly generated and the purpose of each of the arguments in subset(). Does the number of observations in each of the new dataframes agree with the number of men and women I told you were in the total dataset?
mdims <- subset(bdims, sex == 1)
fdims <- subset(bdims, sex == 0)
Exercise 1: Make a histogram of men’s heights and a histogram of women’s heights. How would you compare the various aspects of the two distributions?
hist(mdims$hgt, xlim = c(150,200))

hist(fdims$hgt, xlim = c(140,190))

Exercise 2: scale is a function in R, and can be applied to any numeric vector (list of numbers in R). Generate the two histograms below, this time graphing the scale() of the heights and determine how the scaled version of the heights correspond to the original heights. What is scale calculating for each point?
hist(scale(mdims$hgt))

hist(scale(fdims$hgt))

We would like to compare the distribution of heights in this dataset to the normal distribution. To each of the histograms of heights (not scaled) plot a normal curve on top of the histogram. 1. calcualte the mean and standard deviation for the female heights and save them as variables, fhgtmean and fhgtsd, respectively. 2. Determine the list of x values (the range of the X-axis) and save this vector (list). You can easily make a list of numbers using the seq() function as we have done before, or having the lower limit:upper limit. For example, to generate a vector (list of numbers) of 1 to 10 and save it as one_ten I would one_ten <- 1:10. 3. As above, use dnorm() to take in the list of x values and find the corresponding y value if it were a perfect normal distribution. Save this vector as the variable y. lines() can plot a line on another graph. 4. Replot your histogram and then in the next line use lines(x = x, y = y, col = “blue”) to draw a normal distribution on top of it. How would you change the y-axis so that the normal curve is not cut off?
fhgtmean <- mean(fdims$hgt)
fhgtsd <- sd(fdims$hgt)
hist(fdims$hgt, probability = TRUE)
x <- 140:190
y <- dnorm(x = x, mean = fhgtmean, sd = fhgtsd)
lines(x = x, y = y, col = "blue")

How would you change the y-axis so that the normal curve is not cut off?
hist(fdims$hgt, probability = TRUE, ylim = c(0, .07))
x <- 140:190
y <- dnorm(x = x, mean = fhgtmean, sd = fhgtsd)
lines(x = x, y = y, col = "blue")

Based on the this plot, does it appear that the data follow a nearly normal distribution? Do the same thing for the male heights.
Answer: Overall yes, I would consider these values to be following a nearly normal distribution as the histogram fits the curve pretty well.
Eyeballing the shape of the histogram is one way to determine if the data appear to be nearly normally distributed, but it can be frustrating to decide just how close the histogram is to the curve. An alternative approach involves constructing a normal probability plot, also called a normal Q-Q plot for “quantile-quantile” (as we discussed in class). Run both lines together than run qqline() after qqnorm() to determine what qqline() is doing.
qqnorm(fdims$hgt)
qqline(fdims$hgt)

It can be hard to determine even from a Q-Q plot if the data is normally distributed. Thus, it can be helpful to run a normal simulation (like the binomial simulations we ran in the last exercise!) and look at their Q-Q plots to see if the read data looks pretty similar or not. A useful way to address this question is to rephrase it as: what do probability plots look like for data that I know came from a normal distribution? We can answer this by simulating data from a normal distribution using rnorm. Run the code below and look at the output to determine what each part of the code is doing. Run a similar simulation for the male heights.
sim_norm_f <- rnorm(n = length(fdims$hgt), mean = fhgtmean, sd = fhgtsd)
Make a normal probability plot of sim_norm. Do all of the points fall on the line? How does this plot compare to the probability plot for the real data?
qqnorm(sim_norm_f)
qqline(sim_norm_f)

It can be helpful to look at multiple simulations of QQ plots to determine if your data is distributed normally. R has a built in function (so you don’t have to run mulitple simulations and plot each of them individually) called qqnormsim. Run the line below and look at the output. Does the normal probability plot for fdims$hgt look similar to the plots created for the simulated data? That is, do plots provide evidence that the female heights are nearly normal? Do the same for the male heights.
qqnormsim(fdims$hgt)

It turns out that statisticians know a lot about the normal distribution. Once we decide that a random variable is approximately normal, we can answer all sorts of questions about that variable related to probability. Take, for example, the question of, “What is the probability that a randomly chosen young adult female is taller than 6 feet (about 182 cm)?” (The study that published this data set is clear to point out that the sample was not random and therefore inference to a general population is not suggested. We do so here only as an exercise.)
If we assume that female heights are normally distributed (a very close approximation is also okay), we can find this probability by calculating a Z score and consulting a Z table (also called a normal probability table). In R, this is done in one step with the function pnorm (as we did above for the standard normal distribution).
1 - pnorm(q = 182, mean = fhgtmean, sd = fhgtsd)
[1] 0.004434387
Why did we use 1 - pnorm() in this example?
Assuming a normal distribution has allowed us to calculate a theoretical probability. If we want to calculate the probability empirically, we simply need to determine how many observations fall above 182 then divide this number by the total sample size.
sum(fdims$hgt > 182) / length(fdims$hgt)
[1] 0.003846154
Although the probabilities are not exactly the same, they are reasonably close. The closer that your distribution is to being normal, the more accurate the theoretical probabilities will be.
Determine the probability of a female being under 5 feet 2 inches tall. What about male? What is the probability that a female is between 5 feet 2 inches and 5 feet 7 inches tall?
pnorm(157.48, fhgtmean, fhgtsd)
[1] 0.1293377
What is the height in which 95% of females are shorter than this height?
qnorm(.95, fhgtmean, fhgtsd)
[1] 175.6372
At 5 feet 9 inches, 95% of women are below this height.
For the dataset bdims, choose 4 more of the variables to assess whether or not you think the datasets are normal using the strategy above. To take a look at what the variables are (and their abbreviated headers) you can look here: http://www.openintro.org/stat/data/bdims.php Additionally, for each variable consider whether you think it is most reasonable to evaluate the entire dataset together or the males and females seperately as we did for height.
You could do a lot of different datasets here, using the same techniques as above. I really encourage you to do this so that you can get familiar with modeling the normal distribution in R.
LS0tCnRpdGxlOiAiTm9ybWFsIERpc3RyaWJ1dGlvbiBpbiBSIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUbyBzdGFydCwgbGV0J3MgbG9vayBhdCB0aGUgc3RhbmRhcmQgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gUiBpcyB2ZXJ5IGdvb2QgKHVzaW5nIHRoZSBub3JtIGZ1bmN0aW9ucykgYXQgZ2VuZXJhdGluZyBhIHNpbXVsYXRlZCBkYXRhIHNldCB3aXRoIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gVGhlIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24gaXMgYSBub3JtYWwgZGlzdHJpYnV0aW9uIHdpdGggYSBtZWFuIG9mIDAgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAxLiAKCmBgYHtyfQp4LnZhbHVlcyA9IHNlcSgtNCw0LCBsZW5ndGggPSAxMDAwKQp5LnZhbHVlcyA9IGRub3JtKHgudmFsdWVzKQpwbG90KHgudmFsdWVzLCB5LnZhbHVlcywgdHlwZT0ibCIsIGx0eT0xLCB4bGFiPSJaIHZhbHVlIiwgeWxhYj0iUHJvYmFiaWxpdHkiLCBtYWluPSJOb3JtYWwgRGlzdHJpYnV0aW9uIikKYGBgCgpUbyBzdGFydCwgZm9yIGVhY2ggb2YgdGhlIDMgbGluZXMgb2YgY29kZSwgcmVhc29uIG91dCB3aGF0IGlzIGhhcHBlbmluZy4gV2hhdCB2YXJpYWJsZXMgd2VyZSBjcmVhdGVkIGFuZCBob3cgZGlkIHdlIGVuc3VyZSB0aGF0IHRoZSBkYXRhIGdlbmVyYXRlZCBmb2xsb3dlZCBhIG5vcm1hbCBkaXN0cmlidXRpb24/CgpOb3csIGp1c3QgbGlrZSBpbiB0aGUgcGFzdCB3aXRoIHBiaW5vbSwgd2UgY2FuIGFzayBob3cgbXVjaCBvZiB0aGUgY3VydmUgZmFsbHMgYmVsb3cgYSBwYXJ0aWN1bGFyIHZhbHVlLkluIHRoaXMgY2FzZSB3ZSdsbCBhc2sgYWJvdXQgdGhlIHZhbHVlIDAgYmVmb3JlIHJ1bm5pbmcgdGhlIGNvZGUsIHRoaW5rIHRvIHlvdXJzZWxmIHdoYXQgdGhlIGFuc3dlciBzaG91bGQgYmUuCgpgYGB7cn0KcG5vcm0oMCkKYGBgCgoKQS4gUHJvYmFiaWxpdGllcyBhc3NvY2lhdGVkIHdpdGggdmFsdWVzIDwgb3IgPiB6IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpJbiB0aGUgZXhhbXBsZXMgYmVsb3csIHdlJ2xsIHVzZSB6IHZhbHVlcyBvZiArIDEuOTYgYW5kIC0xLjk2IGJlY2F1c2Ugd2Uga25vdyB0aGF0IHRoZXNlIGFwcHJveGltYXRlIHZhbHVlcyBtYXJrIG9mZiB0aGUgdXBwZXIgYW5kIGxvd2VyIDIuNSUgb2YgdGhlIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24uIFRoZXJlZm9yZSwgdGhpcyBjb3JyZXNwb25kcyB0byBhICB0eXBpY2FsIGFscGhhID0gMC4wNSBmb3IgYSB0d28tdGFpbGVkIGh5cG90aGVzaXMgdGVzdCAod2hpY2ggd2Ugd2lsbCBsZWFybiBtb3JlIGFib3V0IGluIHRoZSBjb21pbmcgd2Vla3MpLgoKYGBge3J9CnBub3JtKDEuOTYsIGxvd2VyLnRhaWw9VFJVRSkKYGBgCgoKVGhlIGFuc3dlciB0ZWxscyB1cyB3aGF0IHdlIGFscmVhZHkga25vdzogOTcuNSUgb2YgdGhlIG5vcm1hbCBkaXN0cmlidXRpb24gb2NjdXJzIGJlbG93IHRoZSB6LXZhbHVlIG9mIDEuOTYuCgpXZSBjYW4gYWRkIGEgbGluZSB0byB0aGUgcGxvdCB0byBzaG93IHdoZXJlIHRoaXMgd291bGQgYmUgdXNpbmcgYWJsaW5lLgo5Ny41JSBvZiB0aGUgZGlzdHJpYnV0aW9uIGZhbGxzIGJlbG93IHRoaXMgbGluZQoKYGBge3J9CnBsb3QoeC52YWx1ZXMsIHkudmFsdWVzLCB0eXBlPSJsIiwgbHR5PTEsIHhsYWI9IlogdmFsdWUiLCB5bGFiPSJQcm9iYWJpbGl0eSIsIG1haW49Ik5vcm1hbCBEaXN0cmlidXRpb24iKQphYmxpbmUodiA9IDEuOTYpCmBgYAoKRXhlcmNpc2UgMTogVXNlIHRoZSBhYmxpbmUoKSBmdW5jdGlvbiB0byBhZGQgbGluZXMgYXQgdGhlIGFwcHJvcHJpYXRlIHotc2NvcmUgdG8gZGVtb25zdHJhdGUgdGhlIDY4LTk1LTk5Ljcgb2YgdGhpcyBzdGFuZGFyZCBub3JtYWwgY3VydmUuCmBgYHtyfQpwbG90KHgudmFsdWVzLCB5LnZhbHVlcywgdHlwZT0ibCIsIGx0eT0xLCB4bGFiPSJaIHZhbHVlIiwgeWxhYj0iUHJvYmFiaWxpdHkiLCBtYWluPSJOb3JtYWwgRGlzdHJpYnV0aW9uIikKYWJsaW5lKHYgPSAxKQphYmxpbmUodiA9IC0xKQphYmxpbmUodiA9IDIpCmFibGluZSh2ID0gLTIpCmFibGluZSh2ID0gMykKYWJsaW5lKHYgPSAtMykKYGBgCgoKQXMgZGlzY3Vzc2VkIG9uIFR1ZXNkYXksIFdlIGNhbiBhbHNvIGRvIHRoZSByZXZlcnNlLCBkZWNpZGluZyBmaXJzdCBob3cgbXVjaCBwcm9iYWJpbGl0eSB3ZSB3YW50IChwZXJjZW50aWxlKSBhbmQgdGhlbiBjYWxjdWxhdGluZyB3aGF0IGNyaXRpY2FsIHZhbHVlcyBhcmUgYXNzb2NpYXRlZCB3aXRoIHRob3NlIHByb2JhYmlsaXRpZXMuIFRoaXMgdXNlcyB0aGUgcW5vcm0gZnVuY3Rpb24uIElmIHdlIHdhbnQgdG8ga25vdyB3aGF0IHogdmFsdWUgbWFya2VkIG9mZiB0aGUgbG93ZXIgMi41JSBvZiBhIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24sIHdlIHdvdWxkIHVzZToKCmBgYHtyfQpxbm9ybSgwLjAyNSkKYGBgCgpUaGlzIHRlbGxzIHVzIHRoYXQgdGhlIHogdmFsdWUgb2YgLTEuOTYgbWFya3Mgb2ZmIHRoZSBsb3dlciAyLjUlIG9mIHRoZXN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24uIFRvIGRldGVybWluZSB0aGUgeiB2YWx1ZSB0aGF0IG1hcmtzIG9mZiB0aGUgdXBwZXIgMi41JSBvZiB0aGUgZGlzdHJpYnV0aW9uLCBJIHR5cGU6CgpgYGB7cn0KcW5vcm0oMC45NzUpCmBgYAoKRXhlcmNpc2UgMjogU28gZmFyIHdlIGhhdmUgZGVtb25zdHJhdGVkIGV2ZXJ5dGhpbmcgd2l0aCBhIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24uIEJ1dCBtb3N0IG5vcm1hbCBjdXJ2ZXMgYXJlIG5vdCBzdGFuZGFyZCBub3JtYWwuIEdlbmVyYXRlIGEgY3VydmUgKGxpa2Ugd2UgZGlkIGFib3ZlIGZvciB0aGUgc3RhbmRhcmQgbm9ybWFsIGRpc3RyaWJ1dGlvbikgYW5kIHBsb3QgaXQgd2l0aCBhIG1lYW4gb2YgMjAgYW5kIGEgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIDEuNjUuIElkZW50aWZ5IHRoZSB2YWx1ZSBhdCB3aGljaCA5Ny41JSBvZiB0aGUgZGlzdHJpYnV0aW9uIGZhbGxzIGJlbG93IHRoaXMgdmFsdWUuIAoKYGBge3J9CngudmFsdWVzID0gc2VxKDEwLDMwLCBsZW5ndGggPSAxMDAwKQp5LnZhbHVlcyA9IGRub3JtKHgudmFsdWVzLCAyMCwgMS42NSkKcGxvdCh4LnZhbHVlcywgeS52YWx1ZXMsIHR5cGU9ImwiLCBsdHk9MSwgeGxhYj0iWiB2YWx1ZSIsIHlsYWI9IlByb2JhYmlsaXR5IiwgbWFpbj0iTm9ybWFsIERpc3RyaWJ1dGlvbiIpCmBgYApgYGB7cn0KcW5vcm0oLjk3NSwgMjAsIDEuNjUpCmBgYAoKCk5vdyB0aGF0IHdlIGhhdmUgZ2VuZXJhdGVkIG5vcm1hbCBkaXN0cmlidXRpb25zLCBsZXRzIHRha2UgYSBsb29rIGF0IHNvbWUgcmVhZCBkYXRhIGFuZCBjb21wYXJlIGl0IHRvIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uLiBSdW4gdGhlIGZvbGxvd2luZyBsaW5lcyBvZiBjb2RlLCB3aGljaCB3aWxsIGRvd25sb2FkIGFuZCBsb2FkIGEgZGF0YXNldCBvZiBtZWFzdXJlbWVudHMgZnJvbSAyNDcgbWVuIGFuZCAyNjAgd29tZW4sIG1vc3Qgb2Ygd2hvbSB3ZXJlIGNvbnNpZGVyZWQgaGVhbHRoeSB5b3VuZyBhZHVsdHMuIFlvdeKAmWxsIHNlZSB0aGF0IGZvciBldmVyeSBvYnNlcnZhdGlvbiB3ZSBoYXZlIDI1IG1lYXN1cmVtZW50cywgbWFueSBvZiB3aGljaCBhcmUgZWl0aGVyIGRpYW1ldGVycyBvciBnaXJ0aHMuIEEga2V5IHRvIHRoZSB2YXJpYWJsZSBuYW1lcyBjYW4gYmUgZm91bmQgYXQgaHR0cDovL3d3dy5vcGVuaW50cm8ub3JnL3N0YXQvZGF0YS9iZGltcy5waHAsIGJ1dCB3ZeKAmWxsIGJlIGZvY3VzaW5nIG9uIGp1c3QgdGhyZWUgY29sdW1ucyB0byBnZXQgc3RhcnRlZDogd2VpZ2h0IGluIGtnICh3Z3QpLCBoZWlnaHQgaW4gY20gKGhndCksIGFuZCBzZXggKDEgaW5kaWNhdGVzIG1hbGUsIDAgaW5kaWNhdGVzIGZlbWFsZSkuCgpgYGB7cn0KZG93bmxvYWQuZmlsZSgiaHR0cDovL3d3dy5vcGVuaW50cm8ub3JnL3N0YXQvZGF0YS9iZGltcy5SRGF0YSIsIGRlc3RmaWxlID0gImJkaW1zLlJEYXRhIikKbG9hZCgiYmRpbXMuUkRhdGEiKQpgYGAKClNpbmNlIHRoaXMgZGF0YXNldCBjb250YWlucyBib3RoIG1lbiBhbmQgd29tZW4sIGl0IHdvdWxkIGJlIGhlbHBmdWwgdG8gc2VwZXJhdGUgdGhlIGRhdGEgaW50byB0d28gc2V0cywgb25lIG9mIGZlbWFsZXMgYW5kIG9uZSBvZiBtYWxlcy4gVGhlcmUgaXMgYSBncmVhdCBmdW5jdGlvbiBpbiBSIHRoYXQgY2FuIHN1YnNldCBieSBhIGNhdGVnb3JpY2FsIHZhcmFpYmxlLiBBZnRlciBydW5uaW5nIHRoZSBjb2RlIGJlbG93LCBkZXRlcm1pbmUgd2hhdCBkYXRhc2V0cyBhcmUgbmV3bHkgZ2VuZXJhdGVkIGFuZCB0aGUgcHVycG9zZSBvZiBlYWNoIG9mIHRoZSBhcmd1bWVudHMgaW4gc3Vic2V0KCkuIERvZXMgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgaW4gZWFjaCBvZiB0aGUgbmV3IGRhdGFmcmFtZXMgYWdyZWUgd2l0aCB0aGUgbnVtYmVyIG9mIG1lbiBhbmQgd29tZW4gSSB0b2xkIHlvdSB3ZXJlIGluIHRoZSB0b3RhbCBkYXRhc2V0PwoKYGBge3J9Cm1kaW1zIDwtIHN1YnNldChiZGltcywgc2V4ID09IDEpCmZkaW1zIDwtIHN1YnNldChiZGltcywgc2V4ID09IDApCmBgYAoKRXhlcmNpc2UgMTogTWFrZSBhIGhpc3RvZ3JhbSBvZiBtZW7igJlzIGhlaWdodHMgYW5kIGEgaGlzdG9ncmFtIG9mIHdvbWVu4oCZcyBoZWlnaHRzLiBIb3cgd291bGQgeW91IGNvbXBhcmUgdGhlIHZhcmlvdXMgYXNwZWN0cyBvZiB0aGUgdHdvIGRpc3RyaWJ1dGlvbnM/CgpgYGB7cn0KaGlzdChtZGltcyRoZ3QsIHhsaW0gPSBjKDE1MCwyMDApKQpoaXN0KGZkaW1zJGhndCwgeGxpbSA9IGMoMTQwLDE5MCkpCmBgYAoKRXhlcmNpc2UgMjogc2NhbGUgaXMgYSBmdW5jdGlvbiBpbiBSLCBhbmQgY2FuIGJlIGFwcGxpZWQgdG8gYW55IG51bWVyaWMgdmVjdG9yIChsaXN0IG9mIG51bWJlcnMgaW4gUikuIEdlbmVyYXRlIHRoZSB0d28gaGlzdG9ncmFtcyBiZWxvdywgdGhpcyB0aW1lIGdyYXBoaW5nIHRoZSBzY2FsZSgpIG9mIHRoZSBoZWlnaHRzIGFuZCBkZXRlcm1pbmUgaG93IHRoZSBzY2FsZWQgdmVyc2lvbiBvZiB0aGUgaGVpZ2h0cyBjb3JyZXNwb25kIHRvIHRoZSBvcmlnaW5hbCBoZWlnaHRzLiBXaGF0IGlzIHNjYWxlIGNhbGN1bGF0aW5nIGZvciBlYWNoIHBvaW50PwpgYGB7cn0KaGlzdChzY2FsZShtZGltcyRoZ3QpKQpoaXN0KHNjYWxlKGZkaW1zJGhndCkpCmBgYAoKCldlIHdvdWxkIGxpa2UgdG8gY29tcGFyZSB0aGUgZGlzdHJpYnV0aW9uIG9mIGhlaWdodHMgaW4gdGhpcyBkYXRhc2V0IHRvIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uLiBUbyBlYWNoIG9mIHRoZSBoaXN0b2dyYW1zIG9mIGhlaWdodHMgKG5vdCBzY2FsZWQpIHBsb3QgYSBub3JtYWwgY3VydmUgb24gdG9wIG9mIHRoZSBoaXN0b2dyYW0uIAoxLiBjYWxjdWFsdGUgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBmb3IgdGhlIGZlbWFsZSBoZWlnaHRzIGFuZCBzYXZlIHRoZW0gYXMgdmFyaWFibGVzLCBmaGd0bWVhbiBhbmQgZmhndHNkLCByZXNwZWN0aXZlbHkuIAoyLiBEZXRlcm1pbmUgdGhlIGxpc3Qgb2YgeCB2YWx1ZXMgKHRoZSByYW5nZSBvZiB0aGUgWC1heGlzKSBhbmQgc2F2ZSB0aGlzIHZlY3RvciAobGlzdCkuIFlvdSBjYW4gZWFzaWx5IG1ha2UgYSBsaXN0IG9mIG51bWJlcnMgdXNpbmcgdGhlIHNlcSgpIGZ1bmN0aW9uIGFzIHdlIGhhdmUgZG9uZSBiZWZvcmUsIG9yIGhhdmluZyB0aGUgbG93ZXIgbGltaXQ6dXBwZXIgbGltaXQuIEZvciBleGFtcGxlLCB0byBnZW5lcmF0ZSBhIHZlY3RvciAobGlzdCBvZiBudW1iZXJzKSBvZiAxIHRvIDEwIGFuZCBzYXZlIGl0IGFzIG9uZV90ZW4gSSB3b3VsZCBvbmVfdGVuIDwtIDE6MTAuCjMuIEFzIGFib3ZlLCB1c2UgZG5vcm0oKSB0byB0YWtlIGluIHRoZSBsaXN0IG9mIHggdmFsdWVzIGFuZCBmaW5kIHRoZSBjb3JyZXNwb25kaW5nIHkgdmFsdWUgaWYgaXQgd2VyZSBhIHBlcmZlY3Qgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gU2F2ZSB0aGlzIHZlY3RvciBhcyB0aGUgdmFyaWFibGUgeS4gbGluZXMoKSBjYW4gcGxvdCBhIGxpbmUgb24gYW5vdGhlciBncmFwaC4KNC4gUmVwbG90IHlvdXIgaGlzdG9ncmFtIGFuZCB0aGVuIGluIHRoZSBuZXh0IGxpbmUgdXNlIGxpbmVzKHggPSB4LCB5ID0geSwgY29sID0gImJsdWUiKSB0byBkcmF3IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBvbiB0b3Agb2YgaXQuIEhvdyB3b3VsZCB5b3UgY2hhbmdlIHRoZSB5LWF4aXMgc28gdGhhdCB0aGUgbm9ybWFsIGN1cnZlIGlzIG5vdCBjdXQgb2ZmPwoKYGBge3J9CmZoZ3RtZWFuIDwtIG1lYW4oZmRpbXMkaGd0KQpmaGd0c2QgICA8LSBzZChmZGltcyRoZ3QpCmhpc3QoZmRpbXMkaGd0LCBwcm9iYWJpbGl0eSA9IFRSVUUpCnggPC0gMTQwOjE5MAp5IDwtIGRub3JtKHggPSB4LCBtZWFuID0gZmhndG1lYW4sIHNkID0gZmhndHNkKQpsaW5lcyh4ID0geCwgeSA9IHksIGNvbCA9ICJibHVlIikKYGBgCgpIb3cgd291bGQgeW91IGNoYW5nZSB0aGUgeS1heGlzIHNvIHRoYXQgdGhlIG5vcm1hbCBjdXJ2ZSBpcyBub3QgY3V0IG9mZj8KCmBgYHtyfQpoaXN0KGZkaW1zJGhndCwgcHJvYmFiaWxpdHkgPSBUUlVFLCB5bGltID0gYygwLCAuMDcpKQp4IDwtIDE0MDoxOTAKeSA8LSBkbm9ybSh4ID0geCwgbWVhbiA9IGZoZ3RtZWFuLCBzZCA9IGZoZ3RzZCkKbGluZXMoeCA9IHgsIHkgPSB5LCBjb2wgPSAiYmx1ZSIpCmBgYAoKCkJhc2VkIG9uIHRoZSB0aGlzIHBsb3QsIGRvZXMgaXQgYXBwZWFyIHRoYXQgdGhlIGRhdGEgZm9sbG93IGEgbmVhcmx5IG5vcm1hbCBkaXN0cmlidXRpb24/IERvIHRoZSBzYW1lIHRoaW5nIGZvciB0aGUgbWFsZSBoZWlnaHRzLgoKQW5zd2VyOiBPdmVyYWxsIHllcywgSSB3b3VsZCBjb25zaWRlciB0aGVzZSB2YWx1ZXMgdG8gYmUgZm9sbG93aW5nIGEgbmVhcmx5IG5vcm1hbCBkaXN0cmlidXRpb24gYXMgdGhlIGhpc3RvZ3JhbSBmaXRzIHRoZSBjdXJ2ZSBwcmV0dHkgd2VsbC4KCkV5ZWJhbGxpbmcgdGhlIHNoYXBlIG9mIHRoZSBoaXN0b2dyYW0gaXMgb25lIHdheSB0byBkZXRlcm1pbmUgaWYgdGhlIGRhdGEgYXBwZWFyIHRvIGJlIG5lYXJseSBub3JtYWxseSBkaXN0cmlidXRlZCwgYnV0IGl0IGNhbiBiZSBmcnVzdHJhdGluZyB0byBkZWNpZGUganVzdCBob3cgY2xvc2UgdGhlIGhpc3RvZ3JhbSBpcyB0byB0aGUgY3VydmUuIEFuIGFsdGVybmF0aXZlIGFwcHJvYWNoIGludm9sdmVzIGNvbnN0cnVjdGluZyBhIG5vcm1hbCBwcm9iYWJpbGl0eSBwbG90LCBhbHNvIGNhbGxlZCBhIG5vcm1hbCBRLVEgcGxvdCBmb3Ig4oCccXVhbnRpbGUtcXVhbnRpbGXigJ0gKGFzIHdlIGRpc2N1c3NlZCBpbiBjbGFzcykuIFJ1biBib3RoIGxpbmVzIHRvZ2V0aGVyIHRoYW4gcnVuIHFxbGluZSgpIGFmdGVyIHFxbm9ybSgpIHRvIGRldGVybWluZSB3aGF0IHFxbGluZSgpIGlzIGRvaW5nLgoKYGBge3J9CnFxbm9ybShmZGltcyRoZ3QpCnFxbGluZShmZGltcyRoZ3QpCmBgYAoKSXQgY2FuIGJlIGhhcmQgdG8gZGV0ZXJtaW5lIGV2ZW4gZnJvbSBhIFEtUSBwbG90IGlmIHRoZSBkYXRhIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBUaHVzLCBpdCBjYW4gYmUgaGVscGZ1bCB0byBydW4gYSBub3JtYWwgc2ltdWxhdGlvbiAobGlrZSB0aGUgYmlub21pYWwgc2ltdWxhdGlvbnMgd2UgcmFuIGluIHRoZSBsYXN0IGV4ZXJjaXNlISkgYW5kIGxvb2sgYXQgdGhlaXIgUS1RIHBsb3RzIHRvIHNlZSBpZiB0aGUgcmVhZCBkYXRhIGxvb2tzIHByZXR0eSBzaW1pbGFyIG9yIG5vdC4gQSB1c2VmdWwgd2F5IHRvIGFkZHJlc3MgdGhpcyBxdWVzdGlvbiBpcyB0byByZXBocmFzZSBpdCBhczogd2hhdCBkbyBwcm9iYWJpbGl0eSBwbG90cyBsb29rIGxpa2UgZm9yIGRhdGEgdGhhdCBJIGtub3cgY2FtZSBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbj8gV2UgY2FuIGFuc3dlciB0aGlzIGJ5IHNpbXVsYXRpbmcgZGF0YSBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiB1c2luZyBybm9ybS4gUnVuIHRoZSBjb2RlIGJlbG93IGFuZCBsb29rIGF0IHRoZSBvdXRwdXQgdG8gZGV0ZXJtaW5lIHdoYXQgZWFjaCBwYXJ0IG9mIHRoZSBjb2RlIGlzIGRvaW5nLiBSdW4gYSBzaW1pbGFyIHNpbXVsYXRpb24gZm9yIHRoZSBtYWxlIGhlaWdodHMuCgpgYGB7cn0Kc2ltX25vcm1fZiA8LSBybm9ybShuID0gbGVuZ3RoKGZkaW1zJGhndCksIG1lYW4gPSBmaGd0bWVhbiwgc2QgPSBmaGd0c2QpCmBgYAoKTWFrZSBhIG5vcm1hbCBwcm9iYWJpbGl0eSBwbG90IG9mIHNpbV9ub3JtLiBEbyBhbGwgb2YgdGhlIHBvaW50cyBmYWxsIG9uIHRoZSBsaW5lPyBIb3cgZG9lcyB0aGlzIHBsb3QgY29tcGFyZSB0byB0aGUgcHJvYmFiaWxpdHkgcGxvdCBmb3IgdGhlIHJlYWwgZGF0YT8KCmBgYHtyfQpxcW5vcm0oc2ltX25vcm1fZikKcXFsaW5lKHNpbV9ub3JtX2YpCmBgYAoKCkl0IGNhbiBiZSBoZWxwZnVsIHRvIGxvb2sgYXQgbXVsdGlwbGUgc2ltdWxhdGlvbnMgb2YgUVEgcGxvdHMgdG8gZGV0ZXJtaW5lIGlmIHlvdXIgZGF0YSBpcyBkaXN0cmlidXRlZCBub3JtYWxseS4gUiBoYXMgYSBidWlsdCBpbiBmdW5jdGlvbiAoc28geW91IGRvbid0IGhhdmUgdG8gcnVuIG11bGl0cGxlIHNpbXVsYXRpb25zIGFuZCBwbG90IGVhY2ggb2YgdGhlbSBpbmRpdmlkdWFsbHkpIGNhbGxlZCBxcW5vcm1zaW0uIFJ1biB0aGUgbGluZSBiZWxvdyBhbmQgbG9vayBhdCB0aGUgb3V0cHV0LiBEb2VzIHRoZSBub3JtYWwgcHJvYmFiaWxpdHkgcGxvdCBmb3IgZmRpbXMkaGd0IGxvb2sgc2ltaWxhciB0byB0aGUgcGxvdHMgY3JlYXRlZCBmb3IgdGhlIHNpbXVsYXRlZCBkYXRhPyBUaGF0IGlzLCBkbyBwbG90cyBwcm92aWRlIGV2aWRlbmNlIHRoYXQgdGhlIGZlbWFsZSBoZWlnaHRzIGFyZSBuZWFybHkgbm9ybWFsPyBEbyB0aGUgc2FtZSBmb3IgdGhlIG1hbGUgaGVpZ2h0cy4gCgpgYGB7cn0KcXFub3Jtc2ltKGZkaW1zJGhndCkKYGBgCgpJdCB0dXJucyBvdXQgdGhhdCBzdGF0aXN0aWNpYW5zIGtub3cgYSBsb3QgYWJvdXQgdGhlIG5vcm1hbCBkaXN0cmlidXRpb24uIE9uY2Ugd2UgZGVjaWRlIHRoYXQgYSByYW5kb20gdmFyaWFibGUgaXMgYXBwcm94aW1hdGVseSBub3JtYWwsIHdlIGNhbiBhbnN3ZXIgYWxsIHNvcnRzIG9mIHF1ZXN0aW9ucyBhYm91dCB0aGF0IHZhcmlhYmxlIHJlbGF0ZWQgdG8gcHJvYmFiaWxpdHkuIFRha2UsIGZvciBleGFtcGxlLCB0aGUgcXVlc3Rpb24gb2YsIOKAnFdoYXQgaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQgYSByYW5kb21seSBjaG9zZW4geW91bmcgYWR1bHQgZmVtYWxlIGlzIHRhbGxlciB0aGFuIDYgZmVldCAoYWJvdXQgMTgyIGNtKT/igJ0gKFRoZSBzdHVkeSB0aGF0IHB1Ymxpc2hlZCB0aGlzIGRhdGEgc2V0IGlzIGNsZWFyIHRvIHBvaW50IG91dCB0aGF0IHRoZSBzYW1wbGUgd2FzIG5vdCByYW5kb20gYW5kIHRoZXJlZm9yZSBpbmZlcmVuY2UgdG8gYSBnZW5lcmFsIHBvcHVsYXRpb24gaXMgbm90IHN1Z2dlc3RlZC4gV2UgZG8gc28gaGVyZSBvbmx5IGFzIGFuIGV4ZXJjaXNlLikKCklmIHdlIGFzc3VtZSB0aGF0IGZlbWFsZSBoZWlnaHRzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZCAoYSB2ZXJ5IGNsb3NlIGFwcHJveGltYXRpb24gaXMgYWxzbyBva2F5KSwgd2UgY2FuIGZpbmQgdGhpcyBwcm9iYWJpbGl0eSBieSBjYWxjdWxhdGluZyBhIFogc2NvcmUgYW5kIGNvbnN1bHRpbmcgYSBaIHRhYmxlIChhbHNvIGNhbGxlZCBhIG5vcm1hbCBwcm9iYWJpbGl0eSB0YWJsZSkuIEluIFIsIHRoaXMgaXMgZG9uZSBpbiBvbmUgc3RlcCB3aXRoIHRoZSBmdW5jdGlvbiBwbm9ybSAoYXMgd2UgZGlkIGFib3ZlIGZvciB0aGUgc3RhbmRhcmQgbm9ybWFsIGRpc3RyaWJ1dGlvbikuCgpgYGB7cn0KMSAtIHBub3JtKHEgPSAxODIsIG1lYW4gPSBmaGd0bWVhbiwgc2QgPSBmaGd0c2QpCmBgYAoKV2h5IGRpZCB3ZSB1c2UgMSAtIHBub3JtKCkgaW4gdGhpcyBleGFtcGxlPwoKQXNzdW1pbmcgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGhhcyBhbGxvd2VkIHVzIHRvIGNhbGN1bGF0ZSBhIHRoZW9yZXRpY2FsIHByb2JhYmlsaXR5LiBJZiB3ZSB3YW50IHRvIGNhbGN1bGF0ZSB0aGUgcHJvYmFiaWxpdHkgZW1waXJpY2FsbHksIHdlIHNpbXBseSBuZWVkIHRvIGRldGVybWluZSBob3cgbWFueSBvYnNlcnZhdGlvbnMgZmFsbCBhYm92ZSAxODIgdGhlbiBkaXZpZGUgdGhpcyBudW1iZXIgYnkgdGhlIHRvdGFsIHNhbXBsZSBzaXplLgoKYGBge3J9CnN1bShmZGltcyRoZ3QgPiAxODIpIC8gbGVuZ3RoKGZkaW1zJGhndCkKYGBgCgpBbHRob3VnaCB0aGUgcHJvYmFiaWxpdGllcyBhcmUgbm90IGV4YWN0bHkgdGhlIHNhbWUsIHRoZXkgYXJlIHJlYXNvbmFibHkgY2xvc2UuIFRoZSBjbG9zZXIgdGhhdCB5b3VyIGRpc3RyaWJ1dGlvbiBpcyB0byBiZWluZyBub3JtYWwsIHRoZSBtb3JlIGFjY3VyYXRlIHRoZSB0aGVvcmV0aWNhbCBwcm9iYWJpbGl0aWVzIHdpbGwgYmUuCgpEZXRlcm1pbmUgdGhlIHByb2JhYmlsaXR5IG9mIGEgZmVtYWxlIGJlaW5nIHVuZGVyIDUgZmVldCAyIGluY2hlcyB0YWxsLiBXaGF0IGFib3V0IG1hbGU/IFdoYXQgaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQgYSBmZW1hbGUgaXMgYmV0d2VlbiA1IGZlZXQgMiBpbmNoZXMgYW5kIDUgZmVldCA3IGluY2hlcyB0YWxsPwoKYGBge3J9CnBub3JtKDE1Ny40OCwgZmhndG1lYW4sIGZoZ3RzZCkKYGBgCgoKV2hhdCBpcyB0aGUgaGVpZ2h0IGluIHdoaWNoIDk1JSBvZiBmZW1hbGVzIGFyZSBzaG9ydGVyIHRoYW4gdGhpcyBoZWlnaHQ/CgpgYGB7cn0KcW5vcm0oLjk1LCBmaGd0bWVhbiwgZmhndHNkKQpgYGAKQXQgNSBmZWV0IDkgaW5jaGVzLCA5NSUgb2Ygd29tZW4gYXJlIGJlbG93IHRoaXMgaGVpZ2h0LiAKCkZvciB0aGUgZGF0YXNldCBiZGltcywgY2hvb3NlIDQgbW9yZSBvZiB0aGUgdmFyaWFibGVzIHRvIGFzc2VzcyB3aGV0aGVyIG9yIG5vdCB5b3UgdGhpbmsgdGhlIGRhdGFzZXRzIGFyZSBub3JtYWwgdXNpbmcgdGhlIHN0cmF0ZWd5IGFib3ZlLiBUbyB0YWtlIGEgbG9vayBhdCB3aGF0IHRoZSB2YXJpYWJsZXMgYXJlIChhbmQgdGhlaXIgYWJicmV2aWF0ZWQgaGVhZGVycykgeW91IGNhbiBsb29rIGhlcmU6IGh0dHA6Ly93d3cub3BlbmludHJvLm9yZy9zdGF0L2RhdGEvYmRpbXMucGhwIEFkZGl0aW9uYWxseSwgZm9yIGVhY2ggdmFyaWFibGUgY29uc2lkZXIgd2hldGhlciB5b3UgdGhpbmsgaXQgaXMgbW9zdCByZWFzb25hYmxlIHRvIGV2YWx1YXRlIHRoZSBlbnRpcmUgZGF0YXNldCB0b2dldGhlciBvciB0aGUgbWFsZXMgYW5kIGZlbWFsZXMgc2VwZXJhdGVseSBhcyB3ZSBkaWQgZm9yIGhlaWdodC4gCgpZb3UgY291bGQgZG8gYSBsb3Qgb2YgZGlmZmVyZW50IGRhdGFzZXRzIGhlcmUsIHVzaW5nIHRoZSBzYW1lIHRlY2huaXF1ZXMgYXMgYWJvdmUuIEkgcmVhbGx5IGVuY291cmFnZSB5b3UgdG8gZG8gdGhpcyBzbyB0aGF0IHlvdSBjYW4gZ2V0IGZhbWlsaWFyIHdpdGggbW9kZWxpbmcgdGhlIG5vcm1hbCBkaXN0cmlidXRpb24gaW4gUi4gCgo=