Introduction

In the lesson on measures of central tendency we found the minimum value, mean value, median value, mode value, and maximum value of the weight variable in our hypothetical sample of students. We’ll go ahead start this lesson by rerunning that analysis below, but this time we will analyze heights instead of weights.

# Load the Tidyverse package
library(tidyverse)
# Simulate some data
height_and_weight_20 <- tribble(
  ~id,   ~sex,     ~ht_in, ~wt_lbs,
  "001", "Male",   71,     190,
  "002", "Male",   69,     177,
  "003", "Female", 64,     130,
  "004", "Female", 65,     153,
  "005", NA,       73,     173,
  "006", "Male",   69,     182,
  "007", "Female", 68,     186,
  "008", NA,       73,     185,
  "009", "Female", 71,     157,
  "010", "Male",   66,     155,
  "011", "Male",   71,     213,
  "012", "Female", 69,     151,
  "013", "Female", 66,     147,
  "014", "Female", 68,     196,
  "015", "Male",   75,     212,
  "016", "Female", 69,     19000,
  "017", "Female", 66,     194,
  "018", "Female", 65,     176,
  "019", "Female", 65,     176,
  "020", "Female", 65,     102
)
# Recreate our mode function
mode_val <- function(x) {
  value_counts <- table(x)
  result <- names(value_counts)[value_counts == max(value_counts)]
  if (length(value_counts) == length(result)) {
    result <- NA
  }
  result
}
height_and_weight_20 %>% 
  summarise(
    min_height    = min(ht_in),
    mean_height   = mean(ht_in),
    median_height = median(ht_in),
    mode_height   = mode_val(ht_in) %>% paste(collapse = " , "),
    max_height    = max(ht_in)
  )

Note: To get both mode height values to display in the output above I used the paste() function with the collapse argument set to " , " (notices the spaces). This forces R to display our mode values as a character string. The downside is that the “mode_height” variable no longer has any numeric value to R – it’s simply a character string. However, this isn’t a problem for us. We won’t be using the mode in this lesson – and it is rarely used in practice.

Keep in mind that our interest is in describing the “typical” or “average” person in our sample. The results of our analysis above tells us that the average person who answered the height question in our hypothetical class was: 68.4 inches. This information gets us reasonably close to understanding the typical height of the students in our hypothetical class. But remember, our average person does not necessarily have the same height as any actual person in our class. So a natural extension of our original question is: “how much like the average person, are the other people in class.”

For example, is everyone in class 68.4 inches?

Or are there differences in everyone’s height, with the average person’s height always having a value in the middle of everyone else’s?

The measures used to answer this question are called measures of dispersion, which we can say is the amount of difference between people in the class or more generally, the amount of variability in the data.

Three common measures of dispersion used are the:

  • Range
  • Variance
  • Standard Deviation

Range

The range is simply the difference between the maximum and minimum value in the data.

height_and_weight_20 %>% 
  summarise(
    min_height  = min(ht_in),
    mean_height = mean(ht_in),
    max_height  = max(ht_in),
    range       = max_height - min_height
  )

In this case, 11 The range can be useful - it tells us how much difference there is between the tallest person in our class and the shortest person in our class: 11 inches. But it doesn’t tell us, how close, or far away, to 68.4 inches “most” people in the class are.

In other words, are most people in the class out at the edges of the range of values in the data?

Or are people “evenly distributed” across the range of heights for the class?

Or something else entirely?

Variance

The variance is a measure of dispersion that is slightly more complicated to calculate, although not much, but gives us a number we can use to quantify the dispersion of heights around the mean. To do this, let’s work through a simple example that only includes six observations: 3 people who are 58 inches tall and 3 people who are 78 inches tall. In this sample of six people from our population the average height is 68 inches.

Next, let’s draw an imaginary line straight up from the mean.

Then, let’s measure the difference, or distance, between each person’s height and the mean height.

Then we square the differences.

Then we add up all the squared differences.

Note: The sample variance is often written as \(s^2\).

And finally, we divide by n, the number of non-missing observations, minus 1. In this case n equals six, so n-1 equals five.

Note: If the 6 observations here represented our entire population of interest, then we could simply divide by n instead of n-1.

Getting R to do this math for us is really straightforward. We simply use base R’s var() function.

var(c(rep(58, 3), rep(78, 3)))
[1] 120

Here’s what we did above:

  • We created a numeric vector of heights using the c() function.

  • Instead of typing c(58, 58, 58, 78, 78, 78) I chose to use the rep() function. rep(58, 3) is equivalent to typing c(58, 58, 58) and rep(78, 3) is equivalent to typing c(78, 78, 78).

  • We passed this numeric vector to the var() function and R returned the variance – 120

So, 600 divided by 5 equals 120. Therefore, the sample variance in this case is 120. However, because the variance is expressed in squared units, instead of the original units, it isn’t necessarily intuitive to interpret.

Standard deviation

If we take the square root of the variance, we get the standard deviation.

Note: The sample standard deviation is often written as \(s\).

The standard deviation is 10.95 inches, which is much easier to interpret, and compare with other samples. Now that we know the sample standard deviation, we can use it to describe a value’s distance from the mean. Additionally, when our data is approximately normally distributed, then the proportion of values within each standard deviation from the mean follow the rules displayed in this table:

That is, about 68% of all the observations fall within one standard deviation of the mean. About 95% of all observations are within 2 standard deviations of the mean, and about 99.9% of all observations are within 3 standard deviations of the mean.

Don’t forget that these percentage rules apply to values around the mean. In other words, half the values will be greater than the mean and half the values will be lower than the mean. You will often see this graphically illustrated with a “normal curve” or “bell curve.”

Unfortunately, the current data is nowhere near normally distributed and does not make for a good example of this rule.

Comparing distributions

Now that you understand what the different measures of distribution are and how they are calculated, let’s further develop your “feel” for interpreting them. I like to do this by comparing different simulated distributions.

sim_data <- tibble(
  all_68     = rep(68, 20),
  half_58_78 = c(rep(58, 10), rep(78, 10)),
  even_58_78 = seq(from = 58, to = 78, length.out = 20),
  half_48_88 = c(rep(48, 10), rep(88, 10)),
  even_48_88 = seq(from = 48, to = 88, length.out = 20)
)
sim_data

Here’s what we did above:

  • We created a data frame with 5 simulated distributions:

    • all_68 has a value of 68 repeated 20 times

    • half_58_78 is made up of the values 58 and 78, each repeated 10 times (similar to our example above)

    • even_58_78 is 20 evenly distributed numbers between 58 and 78

    • half_48_88 is made up of the values 48 and 88, each repeated 10 times

    • even_48_88 is 20 evenly distributed numbers between 48 and 88

I can use this simulated data to quickly demonstrate a couple of these concepts for you. Let’s use R to calculate and compare the mean, variance, and standard deviation of each variable.

tibble(
  Column = names(sim_data),
  Mean = map_dbl(sim_data, mean),
  Variance = map_dbl(sim_data, var),
  SD = map_dbl(sim_data, sd)
)

Here’s what we did above:

  • We created a data frame to hold some summary statistics about each column in the “sim_data” data frame.

  • We used map_dbl() to iterate over each column in the data. Check out R4DS, Chapter 21 if you need a refresher on iteration.

So, for all the columns the mean is 68 inches. And that makes sense, right? We set the middle value and/or most commonly occurring value to be 68 inches for each of these variables. However, the variance and standard deviation are quite different.

For the column “all_68” the variance and standard deviation are both zero. If you think about it, this should make perfect sense: all the values are 68 – they don’t vary – and each observations distance from the mean (68) is zero.

When comparing the rest of the columns notice that all of them have a non-zero variance. This is because not all people have the same value in that column – they vary. Additionally, we can see very clearly that variance (and standard deviation) are affected by at least two things:

  1. First is the distribution of values across the range of possible values. For example, half_58_78 and half_48_88 have a larger variance than even_58_78 and even_48_88 because all the values are clustered at the min and max - far away from the mean.

  2. The second property of the data that is clearly influencing variance is the width of the range of values included in the distribution. For example, even_48_88 has a larger variance and standard deviation than even_58_78, even though both are evenly distributed across the range of possible values. The reason is because the range of possible values is larger, and therefore the range of distances from the mean is larger too.

In summary, although the variance and standard deviation don’t always have a really intuitive meaning all by themselves, we can get some useful information by comparing them. Generally speaking, the variance is larger when values are clustered at very low or very high values away from the mean, or when values are spread across a wider range.

LS0tCnRpdGxlOiAiRGVzY3JpYmluZyBEaXNwZXJzaW9uIgphdXRob3I6ICJCcmFkIENhbm5lbGwiCmRhdGU6ICJDcmVhdGVkOiAyMDE5LTA0LTIyIDxicj4gVXBkYXRlZDogYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazogCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY3NzOiAiLi4vLi4vY3NzL2xtLW1hcmtkb3duLXN0eWxlcy5jc3MiCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgojIEludHJvZHVjdGlvbgoKSW4gdGhlIGxlc3NvbiBvbiBtZWFzdXJlcyBvZiBjZW50cmFsIHRlbmRlbmN5IHdlIGZvdW5kIHRoZSBtaW5pbXVtIHZhbHVlLCBtZWFuIHZhbHVlLCBtZWRpYW4gdmFsdWUsIG1vZGUgdmFsdWUsIGFuZCBtYXhpbXVtIHZhbHVlIG9mIHRoZSB3ZWlnaHQgdmFyaWFibGUgaW4gb3VyIGh5cG90aGV0aWNhbCBzYW1wbGUgb2Ygc3R1ZGVudHMuIFdlJ2xsIGdvIGFoZWFkIHN0YXJ0IHRoaXMgbGVzc29uIGJ5IHJlcnVubmluZyB0aGF0IGFuYWx5c2lzIGJlbG93LCBidXQgdGhpcyB0aW1lIHdlIHdpbGwgYW5hbHl6ZSBoZWlnaHRzIGluc3RlYWQgb2Ygd2VpZ2h0cy4KCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CiMgTG9hZCB0aGUgVGlkeXZlcnNlIHBhY2thZ2UKbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKYGBge3J9CiMgU2ltdWxhdGUgc29tZSBkYXRhCmhlaWdodF9hbmRfd2VpZ2h0XzIwIDwtIHRyaWJibGUoCiAgfmlkLCAgIH5zZXgsICAgICB+aHRfaW4sIH53dF9sYnMsCiAgIjAwMSIsICJNYWxlIiwgICA3MSwgICAgIDE5MCwKICAiMDAyIiwgIk1hbGUiLCAgIDY5LCAgICAgMTc3LAogICIwMDMiLCAiRmVtYWxlIiwgNjQsICAgICAxMzAsCiAgIjAwNCIsICJGZW1hbGUiLCA2NSwgICAgIDE1MywKICAiMDA1IiwgTkEsICAgICAgIDczLCAgICAgMTczLAogICIwMDYiLCAiTWFsZSIsICAgNjksICAgICAxODIsCiAgIjAwNyIsICJGZW1hbGUiLCA2OCwgICAgIDE4NiwKICAiMDA4IiwgTkEsICAgICAgIDczLCAgICAgMTg1LAogICIwMDkiLCAiRmVtYWxlIiwgNzEsICAgICAxNTcsCiAgIjAxMCIsICJNYWxlIiwgICA2NiwgICAgIDE1NSwKICAiMDExIiwgIk1hbGUiLCAgIDcxLCAgICAgMjEzLAogICIwMTIiLCAiRmVtYWxlIiwgNjksICAgICAxNTEsCiAgIjAxMyIsICJGZW1hbGUiLCA2NiwgICAgIDE0NywKICAiMDE0IiwgIkZlbWFsZSIsIDY4LCAgICAgMTk2LAogICIwMTUiLCAiTWFsZSIsICAgNzUsICAgICAyMTIsCiAgIjAxNiIsICJGZW1hbGUiLCA2OSwgICAgIDE5MDAwLAogICIwMTciLCAiRmVtYWxlIiwgNjYsICAgICAxOTQsCiAgIjAxOCIsICJGZW1hbGUiLCA2NSwgICAgIDE3NiwKICAiMDE5IiwgIkZlbWFsZSIsIDY1LCAgICAgMTc2LAogICIwMjAiLCAiRmVtYWxlIiwgNjUsICAgICAxMDIKKQpgYGAKCmBgYHtyfQojIFJlY3JlYXRlIG91ciBtb2RlIGZ1bmN0aW9uCm1vZGVfdmFsIDwtIGZ1bmN0aW9uKHgpIHsKICB2YWx1ZV9jb3VudHMgPC0gdGFibGUoeCkKICByZXN1bHQgPC0gbmFtZXModmFsdWVfY291bnRzKVt2YWx1ZV9jb3VudHMgPT0gbWF4KHZhbHVlX2NvdW50cyldCiAgaWYgKGxlbmd0aCh2YWx1ZV9jb3VudHMpID09IGxlbmd0aChyZXN1bHQpKSB7CiAgICByZXN1bHQgPC0gTkEKICB9CiAgcmVzdWx0Cn0KYGBgCgpgYGB7cn0KaGVpZ2h0X2FuZF93ZWlnaHRfMjAgJT4lIAogIHN1bW1hcmlzZSgKICAgIG1pbl9oZWlnaHQgICAgPSBtaW4oaHRfaW4pLAogICAgbWVhbl9oZWlnaHQgICA9IG1lYW4oaHRfaW4pLAogICAgbWVkaWFuX2hlaWdodCA9IG1lZGlhbihodF9pbiksCiAgICBtb2RlX2hlaWdodCAgID0gbW9kZV92YWwoaHRfaW4pICU+JSBwYXN0ZShjb2xsYXBzZSA9ICIgLCAiKSwKICAgIG1heF9oZWlnaHQgICAgPSBtYXgoaHRfaW4pCiAgKQpgYGAKCjxkaXYgY2xhc3M9Im1vcmUtaW5mbyI+Ck5vdGU6IFRvIGdldCBib3RoIG1vZGUgaGVpZ2h0IHZhbHVlcyB0byBkaXNwbGF5IGluIHRoZSBvdXRwdXQgYWJvdmUgSSB1c2VkIHRoZSBgcGFzdGUoKWAgZnVuY3Rpb24gd2l0aCB0aGUgY29sbGFwc2UgYXJndW1lbnQgc2V0IHRvICIgLCAiIChub3RpY2VzIHRoZSBzcGFjZXMpLiBUaGlzIGZvcmNlcyBSIHRvIGRpc3BsYXkgb3VyIG1vZGUgdmFsdWVzIGFzIGEgY2hhcmFjdGVyIHN0cmluZy4gVGhlIGRvd25zaWRlIGlzIHRoYXQgdGhlIOKAnG1vZGVfaGVpZ2h04oCdIHZhcmlhYmxlIG5vIGxvbmdlciBoYXMgYW55IG51bWVyaWMgdmFsdWUgdG8gUiAtLSBpdCdzIHNpbXBseSBhIGNoYXJhY3RlciBzdHJpbmcuIEhvd2V2ZXIsIHRoaXMgaXNuJ3QgYSBwcm9ibGVtIGZvciB1cy4gV2Ugd29uJ3QgYmUgdXNpbmcgdGhlIG1vZGUgaW4gdGhpcyBsZXNzb24gLS0gYW5kIGl0IGlzIHJhcmVseSB1c2VkIGluIHByYWN0aWNlLgo8L2Rpdj4KCktlZXAgaW4gbWluZCB0aGF0IG91ciBpbnRlcmVzdCBpcyBpbiBkZXNjcmliaW5nIHRoZSDigJx0eXBpY2Fs4oCdIG9yIOKAnGF2ZXJhZ2XigJ0gcGVyc29uIGluIG91ciBzYW1wbGUuIFRoZSByZXN1bHRzIG9mIG91ciBhbmFseXNpcyBhYm92ZSB0ZWxscyB1cyB0aGF0IHRoZSBhdmVyYWdlIHBlcnNvbiB3aG8gYW5zd2VyZWQgdGhlIGhlaWdodCBxdWVzdGlvbiBpbiBvdXIgaHlwb3RoZXRpY2FsIGNsYXNzIHdhczogNjguNCBpbmNoZXMuIFRoaXMgaW5mb3JtYXRpb24gZ2V0cyB1cyByZWFzb25hYmx5IGNsb3NlIHRvIHVuZGVyc3RhbmRpbmcgdGhlIHR5cGljYWwgaGVpZ2h0IG9mIHRoZSBzdHVkZW50cyBpbiBvdXIgaHlwb3RoZXRpY2FsIGNsYXNzLiBCdXQgcmVtZW1iZXIsIG91ciBhdmVyYWdlIHBlcnNvbiBkb2VzIG5vdCBuZWNlc3NhcmlseSBoYXZlIHRoZSBzYW1lIGhlaWdodCBhcyBhbnkgX19hY3R1YWwgcGVyc29uX18gaW4gb3VyIGNsYXNzLiBTbyBhIG5hdHVyYWwgZXh0ZW5zaW9uIG9mIG91ciBvcmlnaW5hbCBxdWVzdGlvbiBpczog4oCcaG93IG11Y2ggbGlrZSB0aGUgYXZlcmFnZSBwZXJzb24sIGFyZSB0aGUgb3RoZXIgcGVvcGxlIGluIGNsYXNzLuKAnQoKRm9yIGV4YW1wbGUsIGlzIGV2ZXJ5b25lIGluIGNsYXNzIDY4LjQgaW5jaGVzPyAKCiFbXShpbWdfZGVzY3JpcHRpdmVfYW5hbHlzaXMvZGlzcGVyc2lvbl8wMV9wZW9wbGUucG5nKQoKT3IgYXJlIHRoZXJlIGRpZmZlcmVuY2VzIGluIGV2ZXJ5b25l4oCZcyBoZWlnaHQsIHdpdGggdGhlIGF2ZXJhZ2UgcGVyc29u4oCZcyBoZWlnaHQgYWx3YXlzIGhhdmluZyBhIHZhbHVlIGluIHRoZSBtaWRkbGUgb2YgZXZlcnlvbmUgZWxzZeKAmXM/CgohW10oaW1nX2Rlc2NyaXB0aXZlX2FuYWx5c2lzL2Rpc3BlcnNpb25fMDJfcGVvcGxlLnBuZykKClRoZSBtZWFzdXJlcyB1c2VkIHRvIGFuc3dlciB0aGlzIHF1ZXN0aW9uIGFyZSBjYWxsZWQgbWVhc3VyZXMgb2YgZGlzcGVyc2lvbiwgd2hpY2ggd2UgY2FuIHNheSBpcyB0aGUgYW1vdW50IG9mIGRpZmZlcmVuY2UgYmV0d2VlbiBwZW9wbGUgaW4gdGhlIGNsYXNzIG9yIG1vcmUgZ2VuZXJhbGx5LCB0aGUgYW1vdW50IG9mIHZhcmlhYmlsaXR5IGluIHRoZSBkYXRhLgoKVGhyZWUgY29tbW9uIG1lYXN1cmVzIG9mIGRpc3BlcnNpb24gdXNlZCBhcmUgdGhlOgoKKiAqKlJhbmdlKiogICAKKiAqKlZhcmlhbmNlKiogICAKKiAqKlN0YW5kYXJkIERldmlhdGlvbioqICAKCiFbXShpbWdfZGVzY3JpcHRpdmVfYW5hbHlzaXMvZGlzcGVyc2lvbl8wM19vdmVydmlldy5wbmcpCgojIFJhbmdlCgpUaGUgcmFuZ2UgaXMgc2ltcGx5IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG1heGltdW0gYW5kIG1pbmltdW0gdmFsdWUgaW4gdGhlIGRhdGEuIAoKYGBge3J9CmhlaWdodF9hbmRfd2VpZ2h0XzIwICU+JSAKICBzdW1tYXJpc2UoCiAgICBtaW5faGVpZ2h0ICA9IG1pbihodF9pbiksCiAgICBtZWFuX2hlaWdodCA9IG1lYW4oaHRfaW4pLAogICAgbWF4X2hlaWdodCAgPSBtYXgoaHRfaW4pLAogICAgcmFuZ2UgICAgICAgPSBtYXhfaGVpZ2h0IC0gbWluX2hlaWdodAogICkKYGBgCgpJbiB0aGlzIGNhc2UsIDExIFRoZSByYW5nZSBjYW4gYmUgdXNlZnVsIC0gaXQgdGVsbHMgdXMgaG93IG11Y2ggZGlmZmVyZW5jZSB0aGVyZSBpcyBiZXR3ZWVuIHRoZSB0YWxsZXN0IHBlcnNvbiBpbiBvdXIgY2xhc3MgYW5kIHRoZSBzaG9ydGVzdCBwZXJzb24gaW4gb3VyIGNsYXNzOiAxMSBpbmNoZXMuIEJ1dCBpdCBkb2VzbuKAmXQgdGVsbCB1cywgaG93IGNsb3NlLCBvciBmYXIgYXdheSwgdG8gNjguNCBpbmNoZXMg4oCcbW9zdOKAnSBwZW9wbGUgaW4gdGhlIGNsYXNzIGFyZS4KCkluIG90aGVyIHdvcmRzLCBhcmUgbW9zdCBwZW9wbGUgaW4gdGhlIGNsYXNzIG91dCBhdCB0aGUgZWRnZXMgb2YgdGhlIHJhbmdlIG9mIHZhbHVlcyBpbiB0aGUgZGF0YT8gCgohW10oaW1nX2Rlc2NyaXB0aXZlX2FuYWx5c2lzL2Rpc3BlcnNpb25fMDRfZWRnZXMucG5nKQoKT3IgYXJlIHBlb3BsZSDigJxldmVubHkgZGlzdHJpYnV0ZWTigJ0gYWNyb3NzIHRoZSByYW5nZSBvZiBoZWlnaHRzIGZvciB0aGUgY2xhc3M/IAoKIVtdKGltZ19kZXNjcmlwdGl2ZV9hbmFseXNpcy9kaXNwZXJzaW9uXzA1X2V2ZW4ucG5nKQoKT3Igc29tZXRoaW5nIGVsc2UgZW50aXJlbHk/CgojIFZhcmlhbmNlCgpUaGUgdmFyaWFuY2UgaXMgYSBtZWFzdXJlIG9mIGRpc3BlcnNpb24gdGhhdCBpcyBzbGlnaHRseSBtb3JlIGNvbXBsaWNhdGVkIHRvIGNhbGN1bGF0ZSwgYWx0aG91Z2ggbm90IG11Y2gsIGJ1dCBnaXZlcyB1cyBhIG51bWJlciB3ZSBjYW4gdXNlIHRvIHF1YW50aWZ5IHRoZSBkaXNwZXJzaW9uIG9mIGhlaWdodHMgYXJvdW5kIHRoZSBtZWFuLiBUbyBkbyB0aGlzLCBsZXTigJlzIHdvcmsgdGhyb3VnaCBhIHNpbXBsZSBleGFtcGxlIHRoYXQgb25seSBpbmNsdWRlcyBzaXggb2JzZXJ2YXRpb25zOiAzIHBlb3BsZSB3aG8gYXJlIDU4IGluY2hlcyB0YWxsIGFuZCAzIHBlb3BsZSB3aG8gYXJlIDc4IGluY2hlcyB0YWxsLiBJbiB0aGlzIHNhbXBsZSBvZiBzaXggcGVvcGxlIGZyb20gb3VyIHBvcHVsYXRpb24gdGhlIGF2ZXJhZ2UgaGVpZ2h0IGlzIDY4IGluY2hlcy4KCiFbXShpbWdfZGVzY3JpcHRpdmVfYW5hbHlzaXMvZGlzcGVyc2lvbl8wNF9lZGdlcy5wbmcpCgpOZXh0LCBsZXTigJlzIGRyYXcgYW4gaW1hZ2luYXJ5IGxpbmUgc3RyYWlnaHQgdXAgZnJvbSB0aGUgbWVhbi4KCiFbXShpbWdfZGVzY3JpcHRpdmVfYW5hbHlzaXMvZGlzcGVyc2lvbl8wNl92YXJpYW5jZS5wbmcpCgpUaGVuLCBsZXTigJlzIG1lYXN1cmUgdGhlIGRpZmZlcmVuY2UsIG9yIGRpc3RhbmNlLCBiZXR3ZWVuIGVhY2ggcGVyc29u4oCZcyBoZWlnaHQgYW5kIHRoZSBtZWFuIGhlaWdodC4KCiFbXShpbWdfZGVzY3JpcHRpdmVfYW5hbHlzaXMvZGlzcGVyc2lvbl8wN192YXJpYW5jZS5wbmcpCgpUaGVuIHdlIHNxdWFyZSB0aGUgZGlmZmVyZW5jZXMuIAoKIVtdKGltZ19kZXNjcmlwdGl2ZV9hbmFseXNpcy9kaXNwZXJzaW9uXzA4X3ZhcmlhbmNlLnBuZykKClRoZW4gd2UgYWRkIHVwIGFsbCB0aGUgc3F1YXJlZCBkaWZmZXJlbmNlcy4KCiFbXShpbWdfZGVzY3JpcHRpdmVfYW5hbHlzaXMvZGlzcGVyc2lvbl8wOV92YXJpYW5jZS5wbmcpCgo8ZGl2IGNsYXNzPSJtb3JlLWluZm8iPgpOb3RlOiBUaGUgc2FtcGxlIHZhcmlhbmNlIGlzIG9mdGVuIHdyaXR0ZW4gYXMgJHNeMiQuCjwvZGl2PgoKQW5kIGZpbmFsbHksIHdlIGRpdmlkZSBieSBuLCB0aGUgbnVtYmVyIG9mIG5vbi1taXNzaW5nIG9ic2VydmF0aW9ucywgbWludXMgMS4gSW4gdGhpcyBjYXNlIG4gZXF1YWxzIHNpeCwgc28gbi0xIGVxdWFscyBmaXZlLgoKIVtdKGltZ19kZXNjcmlwdGl2ZV9hbmFseXNpcy9kaXNwZXJzaW9uXzEwX3ZhcmlhbmNlLnBuZykKCjxkaXYgY2xhc3M9Im1vcmUtaW5mbyI+Ck5vdGU6IElmIHRoZSA2IG9ic2VydmF0aW9ucyBoZXJlIHJlcHJlc2VudGVkIG91ciBlbnRpcmUgcG9wdWxhdGlvbiBvZiBpbnRlcmVzdCwgdGhlbiB3ZSBjb3VsZCBzaW1wbHkgZGl2aWRlIGJ5IG4gaW5zdGVhZCBvZiBuLTEuCjwvZGl2PgoKR2V0dGluZyBSIHRvIGRvIHRoaXMgbWF0aCBmb3IgdXMgaXMgcmVhbGx5IHN0cmFpZ2h0Zm9yd2FyZC4gV2Ugc2ltcGx5IHVzZSBiYXNlIFIncyBgdmFyKClgIGZ1bmN0aW9uLgoKYGBge3J9CnZhcihjKHJlcCg1OCwgMyksIHJlcCg3OCwgMykpKQpgYGAKCioqSGVyZSdzIHdoYXQgd2UgZGlkIGFib3ZlOioqICAgCgoqIFdlIGNyZWF0ZWQgYSBudW1lcmljIHZlY3RvciBvZiBoZWlnaHRzIHVzaW5nIHRoZSBgYygpYCBmdW5jdGlvbi4gCgoqIEluc3RlYWQgb2YgdHlwaW5nIGBjKDU4LCA1OCwgNTgsIDc4LCA3OCwgNzgpYCBJIGNob3NlIHRvIHVzZSB0aGUgYHJlcCgpYCBmdW5jdGlvbi4gYHJlcCg1OCwgMylgIGlzIGVxdWl2YWxlbnQgdG8gdHlwaW5nIGBjKDU4LCA1OCwgNTgpYCBhbmQgYHJlcCg3OCwgMylgIGlzIGVxdWl2YWxlbnQgdG8gdHlwaW5nIGBjKDc4LCA3OCwgNzgpYC4KCiogV2UgcGFzc2VkIHRoaXMgbnVtZXJpYyB2ZWN0b3IgdG8gdGhlIGB2YXIoKWAgZnVuY3Rpb24gYW5kIFIgcmV0dXJuZWQgdGhlIHZhcmlhbmNlIC0tIDEyMAoKU28sIDYwMCBkaXZpZGVkIGJ5IDUgZXF1YWxzIDEyMC4gVGhlcmVmb3JlLCB0aGUgc2FtcGxlIHZhcmlhbmNlIGluIHRoaXMgY2FzZSBpcyAxMjAuIEhvd2V2ZXIsIGJlY2F1c2UgdGhlIHZhcmlhbmNlIGlzIGV4cHJlc3NlZCBpbiBzcXVhcmVkIHVuaXRzLCBpbnN0ZWFkIG9mIHRoZSBvcmlnaW5hbCB1bml0cywgaXQgaXNu4oCZdCBuZWNlc3NhcmlseSBpbnR1aXRpdmUgdG8gaW50ZXJwcmV0LgoKIyBTdGFuZGFyZCBkZXZpYXRpb24KCklmIHdlIHRha2UgdGhlIHNxdWFyZSByb290IG9mIHRoZSB2YXJpYW5jZSwgd2UgZ2V0IHRoZSBzdGFuZGFyZCBkZXZpYXRpb24uIAoKIVtdKGltZ19kZXNjcmlwdGl2ZV9hbmFseXNpcy9kaXNwZXJzaW9uXzExX3NkLnBuZykKCjxkaXYgY2xhc3M9Im1vcmUtaW5mbyI+Ck5vdGU6IFRoZSBzYW1wbGUgc3RhbmRhcmQgZGV2aWF0aW9uIGlzIG9mdGVuIHdyaXR0ZW4gYXMgJHMkLgo8L2Rpdj4KClRoZSBzdGFuZGFyZCBkZXZpYXRpb24gaXMgMTAuOTUgaW5jaGVzLCB3aGljaCBpcyBtdWNoIGVhc2llciB0byBpbnRlcnByZXQsIGFuZCBjb21wYXJlIHdpdGggb3RoZXIgc2FtcGxlcy4gTm93IHRoYXQgd2Uga25vdyB0aGUgc2FtcGxlIHN0YW5kYXJkIGRldmlhdGlvbiwgd2UgY2FuIHVzZSBpdCB0byBkZXNjcmliZSBhIHZhbHVl4oCZcyBkaXN0YW5jZSBmcm9tIHRoZSBtZWFuLiBBZGRpdGlvbmFsbHksIHdoZW4gb3VyIGRhdGEgaXMgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZCwgdGhlbiB0aGUgcHJvcG9ydGlvbiBvZiB2YWx1ZXMgd2l0aGluIGVhY2ggc3RhbmRhcmQgZGV2aWF0aW9uIGZyb20gdGhlIG1lYW4gZm9sbG93IHRoZSBydWxlcyBkaXNwbGF5ZWQgaW4gdGhpcyB0YWJsZToKCiFbXShpbWdfZGVzY3JpcHRpdmVfYW5hbHlzaXMvZGlzcGVyc2lvbl8xMl9zZC5wbmcpCgpUaGF0IGlzLCBhYm91dCA2OCUgb2YgYWxsIHRoZSBvYnNlcnZhdGlvbnMgZmFsbCB3aXRoaW4gb25lIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgbWVhbi4gQWJvdXQgOTUlIG9mIGFsbCBvYnNlcnZhdGlvbnMgYXJlIHdpdGhpbiAyIHN0YW5kYXJkIGRldmlhdGlvbnMgb2YgdGhlIG1lYW4sIGFuZCBhYm91dCA5OS45JSBvZiBhbGwgb2JzZXJ2YXRpb25zIGFyZSB3aXRoaW4gMyBzdGFuZGFyZCBkZXZpYXRpb25zIG9mIHRoZSBtZWFuLgoKRG9uJ3QgZm9yZ2V0IHRoYXQgdGhlc2UgcGVyY2VudGFnZSBydWxlcyBhcHBseSB0byB2YWx1ZXMgX19hcm91bmRfXyB0aGUgbWVhbi4gSW4gb3RoZXIgd29yZHMsIGhhbGYgdGhlIHZhbHVlcyB3aWxsIGJlIGdyZWF0ZXIgdGhhbiB0aGUgbWVhbiBhbmQgaGFsZiB0aGUgdmFsdWVzIHdpbGwgYmUgbG93ZXIgdGhhbiB0aGUgbWVhbi4gWW91IHdpbGwgb2Z0ZW4gc2VlIHRoaXMgZ3JhcGhpY2FsbHkgaWxsdXN0cmF0ZWQgd2l0aCBhICJub3JtYWwgY3VydmUiIG9yICJiZWxsIGN1cnZlLiIKCjwhLS0gSGVscGZ1bCBzaXRlOiBodHRwOi8vdC1yZWRhY3R5bC5pby9ibG9nLzIwMTYvMDMvY3JlYXRpbmctcGxvdHMtaW4tci11c2luZy1nZ3Bsb3QyLXBhcnQtOS1mdW5jdGlvbi1wbG90cy5odG1sIC0tPgoKYGBge3IgZWNobz1GQUxTRX0KbWVhbiAgICAgIDwtIDY4CnNkICAgICAgICA8LSAxMC45NQpsaW1pdHMgICAgPC0gYyhtZWFuIC0gNCAqIHNkLCBtZWFuICsgNCAqIHNkKQpteV9icmVha3MgPC0gcHVycnI6Om1hcF9kYmwoc2VxKC00LCA0LCAxKSwgfiBtZWFuICsgLiAqIHNkKQpwZWFrICAgICAgPC0gZG5vcm0obWVhbiwgbWVhbiA9IG1lYW4sIHNkID0gc2QpCgpzaGFkZWQgPC0gZnVuY3Rpb24oeCwgbl9zZHMpIHsKICB5IDwtIGRub3JtKHgsIG1lYW4gPSBtZWFuLCBzZCA9IHNkKQogIHlbeCA8IChtZWFuIC0gbl9zZHMgKiBzZCkgfCB4ID4gKG1lYW4gKyBuX3NkcyAqIHNkKV0gPC0gTkEKICB5Cn0KCnlfbGFiZWxzIDwtIGZ1bmN0aW9uKHgpIHsKICBvdXQgPC0gZG5vcm0oeCwgbWVhbiA9IG1lYW4sIHNkID0gc2QpCiAgb3V0Cn0KCmdncGxvdChkYXRhLmZyYW1lKHggPSBjKGxpbWl0c1sxXSwgbGltaXRzWzJdKSksIGFlcyh4ID0geCkpICsgCiAgc3RhdF9mdW5jdGlvbihmdW4gPSBkbm9ybSwgYXJncyA9IGxpc3QobWVhbiA9IG1lYW4sIHNkID0gc2QpKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gNjgsIHkgPSAwLCB4ZW5kID0gNjgsIHllbmQgPSBwZWFrKSwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKwogIHNjYWxlX3hfY29udGludW91cygiSGVpZ2h0cyIsIGJyZWFrcyA9IG15X2JyZWFrcykgKwogICMgQWRkIHNoYWRlZCBhcmVhIGZvciA2OCUKICBzdGF0X2Z1bmN0aW9uKGZ1biA9IHNoYWRlZCwgYXJncyA9IGxpc3Qobl9zZHMgPSAzKSwgZ2VvbSA9ICJhcmVhIiwgZmlsbCA9ICIjMDA1NDkzIiwgYWxwaGEgPSAwLjIpICsKICBnZW9tX3RleHQoYWVzKHggPSBteV9icmVha3NbYyg0LCA2KV0sIHkgPSB5X2xhYmVscyhteV9icmVha3NbYyg0LCA2KV0pLCBsYWJlbCA9ICIxIFNEIFxuIDY4JSIpLCBudWRnZV95ID0gMC4wMDcpICsKICAjIEFkZCBzaGFkZWQgYXJlYSBmb3IgOTUlCiAgc3RhdF9mdW5jdGlvbihmdW4gPSBzaGFkZWQsIGFyZ3MgPSBsaXN0KG5fc2RzID0gMiksIGdlb20gPSAiYXJlYSIsIGZpbGwgPSAiIzAwNTQ5MyIsIGFscGhhID0gMC4yKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gbXlfYnJlYWtzW2MoMywgNyldLCB5ID0geV9sYWJlbHMobXlfYnJlYWtzW2MoMywgNyldKSwgbGFiZWwgPSAiMiBTRCBcbiA5NSUiKSwgbnVkZ2VfeSA9IDAuMDA1KSArCiAgIyBBZGQgc2hhZGVkIGFyZWEgZm9yIDk5JQogIHN0YXRfZnVuY3Rpb24oZnVuID0gc2hhZGVkLCBhcmdzID0gbGlzdChuX3NkcyA9IDEpLCBnZW9tID0gImFyZWEiLCBmaWxsID0gIiMwMDU0OTMiLCBhbHBoYSA9IDAuMikgKwogIGdlb21fdGV4dChhZXMoeCA9IG15X2JyZWFrc1tjKDIsIDgpXSwgeSA9IHlfbGFiZWxzKG15X2JyZWFrc1tjKDIsIDgpXSksIGxhYmVsID0gIjMgU0QgXG4gOTklIiksIG51ZGdlX3kgPSAwLjAwMykgKwogICMgQ2hhbmdlIHRoZW1lCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZSgKICAgIGF4aXMubGluZS55ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKQogICkKCnJtKG1lYW4sIHNkLCBsaW1pdHMsIG15X2JyZWFrcywgcGVhaywgc2hhZGVkLCB5X2xhYmVscykKYGBgCgpVbmZvcnR1bmF0ZWx5LCB0aGUgY3VycmVudCBkYXRhIGlzIG5vd2hlcmUgbmVhciBub3JtYWxseSBkaXN0cmlidXRlZCBhbmQgZG9lcyBub3QgbWFrZSBmb3IgYSBnb29kIGV4YW1wbGUgb2YgdGhpcyBydWxlLgoKIyBDb21wYXJpbmcgZGlzdHJpYnV0aW9ucwoKTm93IHRoYXQgeW91IHVuZGVyc3RhbmQgd2hhdCB0aGUgZGlmZmVyZW50IG1lYXN1cmVzIG9mIGRpc3RyaWJ1dGlvbiBhcmUgYW5kIGhvdyB0aGV5IGFyZSBjYWxjdWxhdGVkLCBsZXQncyBmdXJ0aGVyIGRldmVsb3AgeW91ciAiZmVlbCIgZm9yIGludGVycHJldGluZyB0aGVtLiBJIGxpa2UgdG8gZG8gdGhpcyBieSBjb21wYXJpbmcgZGlmZmVyZW50IHNpbXVsYXRlZCBkaXN0cmlidXRpb25zLgoKYGBge3J9CnNpbV9kYXRhIDwtIHRpYmJsZSgKICBhbGxfNjggICAgID0gcmVwKDY4LCAyMCksCiAgaGFsZl81OF83OCA9IGMocmVwKDU4LCAxMCksIHJlcCg3OCwgMTApKSwKICBldmVuXzU4Xzc4ID0gc2VxKGZyb20gPSA1OCwgdG8gPSA3OCwgbGVuZ3RoLm91dCA9IDIwKSwKICBoYWxmXzQ4Xzg4ID0gYyhyZXAoNDgsIDEwKSwgcmVwKDg4LCAxMCkpLAogIGV2ZW5fNDhfODggPSBzZXEoZnJvbSA9IDQ4LCB0byA9IDg4LCBsZW5ndGgub3V0ID0gMjApCikKc2ltX2RhdGEKYGBgCgoqKkhlcmUncyB3aGF0IHdlIGRpZCBhYm92ZToqKiAgIAoKKiBXZSBjcmVhdGVkIGEgZGF0YSBmcmFtZSB3aXRoIDUgc2ltdWxhdGVkIGRpc3RyaWJ1dGlvbnM6CgogIC0gYWxsXzY4IGhhcyBhIHZhbHVlIG9mIDY4IHJlcGVhdGVkIDIwIHRpbWVzCiAgCiAgLSBoYWxmXzU4Xzc4IGlzIG1hZGUgdXAgb2YgdGhlIHZhbHVlcyA1OCBhbmQgNzgsIGVhY2ggcmVwZWF0ZWQgMTAgdGltZXMgKHNpbWlsYXIgdG8gb3VyIGV4YW1wbGUgYWJvdmUpCiAgCiAgLSBldmVuXzU4Xzc4IGlzIDIwIGV2ZW5seSBkaXN0cmlidXRlZCBudW1iZXJzIGJldHdlZW4gNTggYW5kIDc4CiAgCiAgLSBoYWxmXzQ4Xzg4IGlzIG1hZGUgdXAgb2YgdGhlIHZhbHVlcyA0OCBhbmQgODgsIGVhY2ggcmVwZWF0ZWQgMTAgdGltZXMKICAKICAtIGV2ZW5fNDhfODggaXMgMjAgZXZlbmx5IGRpc3RyaWJ1dGVkIG51bWJlcnMgYmV0d2VlbiA0OCBhbmQgODgKCkkgY2FuIHVzZSB0aGlzIHNpbXVsYXRlZCBkYXRhIHRvIHF1aWNrbHkgZGVtb25zdHJhdGUgYSBjb3VwbGUgb2YgdGhlc2UgY29uY2VwdHMgZm9yIHlvdS4gTGV04oCZcyB1c2UgUiB0byBjYWxjdWxhdGUgYW5kIGNvbXBhcmUgdGhlIG1lYW4sIHZhcmlhbmNlLCBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGVhY2ggdmFyaWFibGUuCgpgYGB7cn0KdGliYmxlKAogIENvbHVtbiA9IG5hbWVzKHNpbV9kYXRhKSwKICBNZWFuID0gbWFwX2RibChzaW1fZGF0YSwgbWVhbiksCiAgVmFyaWFuY2UgPSBtYXBfZGJsKHNpbV9kYXRhLCB2YXIpLAogIFNEID0gbWFwX2RibChzaW1fZGF0YSwgc2QpCikKYGBgCgoqKkhlcmUncyB3aGF0IHdlIGRpZCBhYm92ZToqKiAgIAoKKiBXZSBjcmVhdGVkIGEgZGF0YSBmcmFtZSB0byBob2xkIHNvbWUgc3VtbWFyeSBzdGF0aXN0aWNzIGFib3V0IGVhY2ggY29sdW1uIGluIHRoZSAic2ltX2RhdGEiIGRhdGEgZnJhbWUuCgoqIFdlIHVzZWQgYG1hcF9kYmwoKWAgdG8gaXRlcmF0ZSBvdmVyIGVhY2ggY29sdW1uIGluIHRoZSBkYXRhLiBDaGVjayBvdXQgW1I0RFMsIENoYXB0ZXIgMjFdKGh0dHBzOi8vcjRkcy5oYWQuY28ubnovaXRlcmF0aW9uLmh0bWwjZm9yLWxvb3BzLXZzLmZ1bmN0aW9uYWxzKSBpZiB5b3UgbmVlZCBhIHJlZnJlc2hlciBvbiBpdGVyYXRpb24uCgpTbywgZm9yIGFsbCB0aGUgY29sdW1ucyB0aGUgbWVhbiBpcyA2OCBpbmNoZXMuIEFuZCB0aGF0IG1ha2VzIHNlbnNlLCByaWdodD8gV2Ugc2V0IHRoZSBtaWRkbGUgdmFsdWUgYW5kL29yIG1vc3QgY29tbW9ubHkgb2NjdXJyaW5nIHZhbHVlIHRvIGJlIDY4IGluY2hlcyBmb3IgZWFjaCBvZiB0aGVzZSB2YXJpYWJsZXMuIEhvd2V2ZXIsIHRoZSB2YXJpYW5jZSBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIGFyZSBxdWl0ZSBkaWZmZXJlbnQuCgpGb3IgdGhlIGNvbHVtbiAiYWxsXzY4IiB0aGUgdmFyaWFuY2UgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBhcmUgYm90aCB6ZXJvLiBJZiB5b3UgdGhpbmsgYWJvdXQgaXQsIHRoaXMgc2hvdWxkIG1ha2UgcGVyZmVjdCBzZW5zZTogYWxsIHRoZSB2YWx1ZXMgYXJlIDY4IOKAkyB0aGV5IGRvbuKAmXQgdmFyeSDigJMgYW5kIGVhY2ggb2JzZXJ2YXRpb25zIGRpc3RhbmNlIGZyb20gdGhlIG1lYW4gKDY4KSBpcyB6ZXJvLgoKV2hlbiBjb21wYXJpbmcgdGhlIHJlc3Qgb2YgdGhlIGNvbHVtbnMgbm90aWNlIHRoYXQgYWxsIG9mIHRoZW0gaGF2ZSBhIG5vbi16ZXJvIHZhcmlhbmNlLiBUaGlzIGlzIGJlY2F1c2Ugbm90IGFsbCBwZW9wbGUgaGF2ZSB0aGUgc2FtZSB2YWx1ZSBpbiB0aGF0IGNvbHVtbiDigJMgdGhleSB2YXJ5LiBBZGRpdGlvbmFsbHksIHdlIGNhbiBzZWUgdmVyeSBjbGVhcmx5IHRoYXQgdmFyaWFuY2UgKGFuZCBzdGFuZGFyZCBkZXZpYXRpb24pIGFyZSBhZmZlY3RlZCBieSBhdCBsZWFzdCB0d28gdGhpbmdzOgoKMS4gRmlyc3QgaXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiB2YWx1ZXMgYWNyb3NzIHRoZSByYW5nZSBvZiBwb3NzaWJsZSB2YWx1ZXMuIEZvciBleGFtcGxlLCBoYWxmXzU4Xzc4IGFuZCBoYWxmXzQ4Xzg4IGhhdmUgYSBsYXJnZXIgdmFyaWFuY2UgdGhhbiBldmVuXzU4Xzc4IGFuZCBldmVuXzQ4Xzg4IGJlY2F1c2UgYWxsIHRoZSB2YWx1ZXMgYXJlIGNsdXN0ZXJlZCBhdCB0aGUgbWluIGFuZCBtYXggLSBmYXIgYXdheSBmcm9tIHRoZSBtZWFuLgoKMi4gVGhlIHNlY29uZCBwcm9wZXJ0eSBvZiB0aGUgZGF0YSB0aGF0IGlzIGNsZWFybHkgaW5mbHVlbmNpbmcgdmFyaWFuY2UgaXMgdGhlIHdpZHRoIG9mIHRoZSByYW5nZSBvZiB2YWx1ZXMgaW5jbHVkZWQgaW4gdGhlIGRpc3RyaWJ1dGlvbi4gRm9yIGV4YW1wbGUsIGV2ZW5fNDhfODggaGFzIGEgbGFyZ2VyIHZhcmlhbmNlIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gdGhhbiBldmVuXzU4Xzc4LCBldmVuIHRob3VnaCBib3RoIGFyZSBldmVubHkgZGlzdHJpYnV0ZWQgYWNyb3NzIHRoZSByYW5nZSBvZiBwb3NzaWJsZSB2YWx1ZXMuIFRoZSByZWFzb24gaXMgYmVjYXVzZSB0aGUgcmFuZ2Ugb2YgcG9zc2libGUgdmFsdWVzIGlzIGxhcmdlciwgYW5kIHRoZXJlZm9yZSB0aGUgcmFuZ2Ugb2YgZGlzdGFuY2VzIGZyb20gdGhlIG1lYW4gaXMgbGFyZ2VyIHRvby4KCkluIHN1bW1hcnksIGFsdGhvdWdoIHRoZSB2YXJpYW5jZSBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIGRvbuKAmXQgYWx3YXlzIGhhdmUgYSByZWFsbHkgaW50dWl0aXZlIG1lYW5pbmcgYWxsIGJ5IHRoZW1zZWx2ZXMsIHdlIGNhbiBnZXQgc29tZSB1c2VmdWwgaW5mb3JtYXRpb24gYnkgX19jb21wYXJpbmdfXyB0aGVtLiBHZW5lcmFsbHkgc3BlYWtpbmcsIHRoZSB2YXJpYW5jZSBpcyBsYXJnZXIgd2hlbiB2YWx1ZXMgYXJlIGNsdXN0ZXJlZCBhdCB2ZXJ5IGxvdyBvciB2ZXJ5IGhpZ2ggdmFsdWVzIGF3YXkgZnJvbSB0aGUgbWVhbiwgb3Igd2hlbiB2YWx1ZXMgYXJlIHNwcmVhZCBhY3Jvc3MgYSB3aWRlciByYW5nZS4K