1.Introduction

Say you work for a major social media website. Your boss comes to you with two questions:

1.does the demographic of users on your site match the company’s expectation?

2.did the new interface update affect user engagement?

With terabytes of user data at your hands, you decide the best way to answer these questions is with statistical hypothesis tests!

Statistical hypothesis testing is a process that allows you to evaluate if a change or difference seen in a dataset is “real”, or if it’s just a result of random fluctuation in the data.

Hypothesis testing can be an integral component of any decision making process. It provides a framework for evaluating how confident one can be in making conclusions based on data. Some instances where this might come up include:

1.a professor expects an exam average to be roughly 75%, and wants to know if the actual scores line up with this expectation. Was the test actually too easy or too hard?

2.a product manager for a website wants to compare the time spent on different versions of a homepage. Does one version make users stay on the page significantly longer?

In this lesson, you will cover the fundamental concepts that will help you run and evaluate hypothesis tests:

1.Sample and Population Mean

2.P-Values

3.Significance Level

4.Type I and Type II Errors

You will then learn about three different hypothesis tests you can perform to answer the kinds of questions discussed above:

1.One Sample T-Test

2.Two Sample T-Test

3.ANOVA (Analysis of Variance)

Let’s get started!

Instructions

The code in notebook.Rmd performs a hypothesis test on data for a company BuyPie.com. The test evaluates whether the time spent per visitor on the website changes significantly between two weeks.

Read the output at the bottom of the rendered notebook. Do you think there is a difference in time spent per visitor between Week 1 and Week 2?

By the end of the lesson, you will be able to perform and interpret such hypothesis tests yourself!

# load data
load("week_1.Rda")
load("week_2.Rda")
# calculate week_1_mean and week_2_mean:
week_1_mean <- mean(week_1)
week_1_mean
week_2_mean <- mean(week_2)
week_2_mean

[1] 25.44806

[1] 29.02157

# calculate week_1_sd and week_2_sd:
week_1_sd <- sd(week_1)
week_1_sd
week_2_sd <- sd(week_2)
week_2_sd

[1] 4.577702

[1] 5.553785

# run two sample t-test:
results <- t.test(week_1,week_2)
results

Welch Two Sample t-test

data: week_1 and week_2 t = -3.5109, df = 94.554, p-value = 0.0006863 alternative hypothesis: true difference in means is not equal to 0 95 percent confidence interval: -5.594299 -1.552718 sample estimates: mean of x mean of y 25.44806 29.02157

2.Sample Mean and Population Mean - I

Suppose you want to know the average height of an oak tree in your local park. On Monday, you measure 10 trees and get an average height of 32 ft. On Tuesday, you measure 12 different trees and reach an average height of 35 ft. On Wednesday, you measure the remaining 11 trees in the park, whose average height is 31 ft. The average height for all 33 trees in your local park is 32.8 ft.

The collection of individual height measurements on Monday, Tuesday, and Wednesday are each called samples. A sample is a subset of the entire population (all the oak trees in the park). The mean of each sample is a sample mean and it is an estimate of the population mean.

Note: the sample means (32 ft., 35 ft., and 31 ft.) were all close to the population mean (32.8 ft.), but were all slightly different from the population mean and from each other.

For a population, the mean is a constant value no matter how many times it’s recalculated. But with a set of samples, the mean will depend on exactly which samples are selected. From a sample mean, we can then extrapolate the mean of the population as a whole. There are three main reasons we might use sampling:

1.data on the entire population is not available

2.data on the entire population is available, but it is so large that it is unfeasible to analyze

3.meaningful answers to questions can be found faster with sampling

Instructions

1.In the workspace, we’ve generated a random population of size 300 that follows a normal distribution with a mean of 65. Update the value of population_mean to store the mean() of population. Does it closely match your expectation?

# generate random population
population <- rnorm(300, mean=65, sd=3.5)

# calculate population mean here:
population_mean <- mean(population)
population_mean
[1] 64.90532

2.Let’s look at how the means of different samples can vary within the same population.

The code in the notebook generates 5 random samples from population. sample_1 is displayed and sample_1_mean has been calculated.

Replace the “Not calculated” strings with calculations of the means for sample_2, sample_3, sample_4, and sample_5.

Look at the population mean and the sample means. Are they all the same? All different? Why?

# generate sample 1
sample_1 <- sample(population, size=30)
sample_1
 [1] 67.54371 70.74646 58.92483 66.32206 70.76844 61.03942 61.92440 65.01594 66.31625 66.64947 67.29845 70.28490
[13] 61.20255 63.25246 62.48976 65.40590 65.50519 58.48546 64.96503 63.32665 63.64597 65.27635 64.68773 64.14368
[25] 65.83720 60.94812 56.08455 64.11198 67.19988 64.40878
# calculate sample 1 mean
sample_1_mean <- mean(sample_1)
sample_1_mean
[1] 64.46039
# generate samples 2,3,4 and 5
sample_2 <- sample(population, size=30)
sample_3 <- sample(population, size=30)
sample_4 <- sample(population, size=30)
sample_5 <- sample(population, size=30)
# calculate sample means here:
sample_2_mean <- mean(sample_2)
sample_2_mean
[1] 65.82616
sample_3_mean <- mean(sample_3)
sample_3_mean
[1] 64.76717
sample_4_mean <- mean(sample_4)
sample_4_mean
[1] 65.69348
sample_5_mean <- mean(sample_5)
sample_5_mean
[1] 64.93156

3.Sample Mean and Population Mean - II

In the previous exercise, the sample means you calculated closely approximated the population mean. This won’t always be the case!

Consider a tailor of school uniforms at a school for students aged 11 to 13. The tailor needs to know the average height of all the students in order to know which sizes to make the uniforms.

The tailor measures the heights of a random sample of 20 students out of the 300 in the school. The average height of the sample is 57.5 inches. Using this sample mean, the tailor makes uniforms that fit students of this height, some smaller, and some larger.

After delivering the uniforms, the tailor starts to receive some feedback — many of the uniforms are too small! They go back to take measurements on the rest of the students, collecting the following data:

1.11 year olds average height: 56.7 inches

2.12 year olds average height: 59 inches

3.13 year olds average height: 62.8 inches

4.All students average height (population mean): 59.5 inches

The original sample mean was off from the population mean by 2 inches! How did this happen?

The random sample of 20 students was skewed to one direction of the total population. More 11 year olds were chosen in the sample than is representative of the whole school, bringing down the average height of the sample. This is called a sampling error, and occurs when a sample is not representative of the population it comes from. How do you get an average sample height that looks more like the average population height, and reduce the chance of a sampling error?

Selecting only 20 students for the sample allowed for the chance that only younger, shorter students were included. This is a natural consequence of the fact that a sample has less data than the population to which it belongs. If the sample selection is poor, then you will have a sample mean seriously skewed from the population mean.

There is one surefire way to mitigate the risk of having a skewed sample mean — take a larger set of samples! The sample mean of a larger sample set will more closely approximate the population mean, and reduce the chance of a sampling error.

Instructions

In the workspace, we have a population that is normally distributed. Generate samples of different sizes and see how the sample mean could differ from the population mean.

What happens to the difference between the sample mean and the population mean as you increase the sample size?

knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Hypo1.png")

knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Hypo2.png")

knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Hypo3.png")

knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Hypo4.png")

4.Hypothesis Formulation

You begin the statistical hypothesis testing process by defining a hypothesis, or an assumption about your population that you want to test. A hypothesis can be written in words, but can also be explained in terms of the sample and population means you just learned about.

Say you are developing a website and want to compare the time spent on different versions of a homepage. You could run a hypothesis test to see if version A or B makes users stay on the page significantly longer. Your hypothesis might be:

“The average time spent on homepage A is greater than the average time spent on homepage B.”

While this is a fine hypothesis to make, data analysts are often very hesitant people. They don’t like to make bold claims without having data to back them up! Thus when constructing hypotheses for a hypothesis test, you want to formulate a null hypothesis. A null hypothesis states that there is no difference between the populations you are comparing, and it implies that any difference seen in the sample data is due to sampling error. A null hypothesis for the same scenario is as follows:

“The average time spent on homepage A is the same as the average time spent on homepage B.”

You could also restate this in terms of population mean:

“The population mean of time spent on homepage A is the same as the population mean of time spent on homepage B.”

After collecting some sample data on how users interact with each homepage, you can then run a hypothesis test using the data collected to determine whether your null hypothesis is true or false, or can be rejected (i.e. there is a difference in time spent on homepage A or B).

Instructions

1.A researcher at a pharmaceutical company is working on the development of a new medication to lower blood pressure, DeePressurize. They run an experiment with a control group of 100 patients that receive a placebo (a sugar pill), and an experimental group of 100 patients that receive DeePressurize. Blood pressure measurements are taken after a 3 month period on both groups of patients.

The researcher wants to run a hypothesis test to compare the resulting datasets. Two hypotheses, hypo_a and hypo_b, are given in notebook.Rmd. Which could be a null hypothesis for comparing the two sets of data? Update the value of null_hypo_1 to the string “hypo_a” or “hypo_b” based on your answer.

# experiment 1
hypo_a <- "DeePressurize lowers blood pressure in patients."
hypo_b <- "DeePressurize has no effect on blood pressure in patients."
null_hypo_1 <- "hypo_b"
null_hypo_1
[1] "hypo_b"

2.A product manager at a dating app company is developing a new user profile page with a different picture layout. They want to see if the new layout results in more matches between users than the current layout. 50% of profiles are updated to the new layout, and over a 1 month period the number of matches for users with the new layout and the original layout are recorded.

The product manager wants to run a hypothesis test to compare the resulting datasets. Two hypotheses, hypo_c and hypo_d, are given in notebook.Rmd. Which could be a null hypothesis for comparing the two sets of data? Update the value of null_hypo_2 to the string “hypo_c” or “hypo_d” based on your answer.

# experiment 2
hypo_c <- "The new profile layout has no effect on number of matches with other users."
hypo_d <- "The new profile layout results in more matches with other users than the original layout."
null_hypo_2 <- "hypo_c"
null_hypo_2
[1] "hypo_c"

5.Designing an Experiment

Suppose you want to know if students who study history are more interested in volleyball than students who study chemistry. Before doing anything else to answer your original question, you come up with a null hypothesis: “History and chemistry students are interested in volleyball at the same rates.”

To test this hypothesis, you need to design an experiment and collect data. You invite 100 history majors and 100 chemistry majors from your university to join an extracurricular volleyball team. After one week, 34 history majors sign up (34%), and 39 chemistry majors sign up (39%). More chemistry majors than history majors signed up, but is this a “real”, or significant difference? Can you conclude that students who study chemistry are more interested in volleyball than students who study history?

In your experiment, the 100 history and 100 chemistry majors at your university are samples of their respective populations (all history and chemistry majors). The sample means are the percentages of history majors (34%) and chemistry majors (39%) that signed up for the team, and the difference in sample means is 39% - 34% = 5%. The population means are the percentage of history and chemistry majors worldwide that would sign up for an extracurricular volleyball team if given the chance.

You want to know if the difference you observed in these sample means (5%) reflects a difference in the population means, or if the difference was caused by sampling error, and the samples of students you chose do not represent the greater populations of history and chemistry students.

Restating the null hypothesis in terms of the population means yields the following:

“The percentage of all history majors who would sign up for volleyball is the same as the percentage of all chemistry majors who would sign up for volleyball, and the observed difference in sample means is due to sampling error.”

This is the same as saying, “If you gave the same volleyball invitation to every history and chemistry major in the world, they would sign up at the same rate, and the sample of 200 students you selected are not representative of their populations.”

Instrctions

1.Your friend is a dog walker that specializes in working with Golden Retrievers and Goldendoodles. They are interested in knowing if there is a signficant difference in the lengths of the two breeds. After a few weeks of data collection, they give you a spreadsheet of 10 Golden Retrievers’ lengths and 10 Goldendoodles’ lengths.

The lengths of the dogs are given in retriever_lengths and doodle_lengths. Calculate the mean of each breed and save the results to mean_retriever_l and mean_doodle_l. View mean_retriever_l and mean_doodle_l.

# load data
load("retriever_lengths.Rda")
load("doodle_lengths.Rda")
# calculate mean_retriever_l and mean_doodle_l here:
mean_retriever_l <- mean(retriever_lengths)
mean_retriever_l
mean_doodle_l <- mean(doodle_lengths)
mean_doodle_l

[1] 23

[1] 20.5

2.Calculate the difference between mean_retriever_l and mean_doodle_l and save the result to mean_difference. View mean_difference.

# calculate mean_difference here:
mean_difference <- mean_retriever_l - mean_doodle_l
mean_difference

[1] 2.5

3.You want to run a hypothesis test to see if there is a significant difference in the lengths of Golden Retrievers and Goldendoodles. Which of the two statements could be a formulation of the null hypothesis?

Update the value of null_hypo with “st_1” or “st_2” depending on your answer.

# statements:
st_1 <- "The average length of Golden Retrievers is 2.5 inches longer than the average length of Goldendoodles."
st_2 <- "The average length of Golden Retrievers is the same as the average length of Goldendoodles."

# update null_hypo here:
null_hypo <- "st_2"
null_hypo
[1] "st_2"

6.Type I and Type II Errors

When using automated processes to make decisions, you need to be aware of how this automation can lead to mistakes. Computer programs can be as fallible as the humans who design them. Because of this, there is a responsibility to understand what can go wrong and what can be done to contain these foreseeable problems.

In statistical hypothesis testing, there are two types of error. A Type I error occurs when a hypothesis test finds a correlation between things that are not related. This error is sometimes called a “false positive” and occurs when the null hypothesis is rejected even though it is true.

For example, consider the history and chemistry major experiment from the previous exercise. Say you run a hypothesis test on the sample data you collected and conclude that there is a significant difference in interest in volleyball between history and chemistry majors. You have rejected the null hypothesis that there is no difference between the two populations of students. If, in reality, your results were due to the groups you happened to pick (sampling error), and there actually is no significant difference in interest in volleyball between history and chemistry majors in the greater population, you have become the victim of a false positive, or a Type I error.

The second kind of error, a Type II error, is failing to find a correlation between things that are actually related. This error is referred to as a “false negative” and occurs when the null hypothesis is not rejected even though it is false.

For example, with the history and chemistry student experiment, say that after you perform the hypothesis test, you conclude that there is no significant difference in interest in volleyball between history and chemistry majors. You did not reject the null hypothesis. If there actually is a difference in the populations as a whole, and there is a significant difference in interest in volleyball between history and chemistry majors, your test has resulted in a false negative, or a Type II error.

Instructions

# the true positives and negatives:
actual_positive <- c(2, 5, 6, 7, 8, 10, 18, 21, 24, 25, 29, 30, 32, 33, 38, 39, 42, 44, 45, 47)
actual_negative <- c(1, 3, 4, 9, 11, 12, 13, 14, 15, 16, 17, 19, 20, 22, 23, 26, 27, 28, 31, 34, 35, 36, 37, 40, 41, 43, 46, 48, 49)

# the positives and negatives we determine by running the experiment:
experimental_positive <- c(2, 4, 5, 7, 8, 9, 10, 11, 13, 15, 16, 17, 18, 19, 20, 21, 22, 24, 26, 27, 28, 32, 35, 36, 38, 39, 40, 45, 46, 49)
experimental_negative <- c(1, 3, 6, 12, 14, 23, 25, 29, 30, 31, 33, 34, 37, 41, 42, 43, 44, 47, 48)
# define type_i_errors and type_ii_errors here:
type_i_errors <- intersect(actual_negative, experimental_positive)
print('fales positives')
[1] "fales positives"
type_i_errors
 [1]  4  9 11 13 15 16 17 19 20 22 26 27 28 35 36 40 46 49

2.Now, define type_ii_errors, the list representing the false negatives of the experiment.

type_ii_errors <- intersect(actual_positive, experimental_negative)
print('fales negative')
[1] "fales negative"
type_ii_errors
[1]  6 25 29 30 33 42 44 47

7.P-Values

You know that a hypothesis test is used to determine the validity of a null hypothesis. Once again, the null hypothesis states that there is no actual difference between the two populations of data. But what result does a hypothesis test actually return, and how can you interpret it?

A hypothesis test returns a few numeric measures, most of which are out of the scope of this introductory lesson. Here we will focus on one: p-values. P-values help determine how confident you can be in validating the null hypothesis. In this context, a p-value is the probability that, assuming the null hypothesis is true, you would see at least such a difference in the sample means of your data.

Consider the experiment on history and chemistry majors and their interest in volleyball from a previous exercise:

Null Hypothesis: “History and chemistry students are interested in volleyball at the same rates” Experiment Sample Means: 34% of history majors and 39% of chemistry majors sign up for the volleyball class Assuming the null hypothesis is true, there is no actual difference in preference for volleyball between all history and chemistry majors, and any difference present in the experiment data is the result of sampling error. Imagine you run a hypothesis test on this experiment data and it returns a p-value of 0.04. A p-value of 0.04 indicates that you could expect to see a difference of at least 5% (calculated as 39% - 34% = 5%) in the sample means only 4% of the time.

Essentially, if you ran this same experiment 100 times, you would expect to see as large a difference in the sample means only 4 times given the assumption that there is no actual difference between the populations (i.e. they have the same mean).

Seems like a really small probability, right? Are you thinking about rejecting the null hypothesis you originally stated?

value ≠ probability your result is wrong

value = probability of your data (or more extreme) if the null is true

The p-value itself is not the probability that the null is wrong.

Yes—in practice, when the p-value is very small, it suggests that the null hypothesis is likely wrong.

Instrctions

1.You are big fan of apples, so you gather 10 green and 10 red apples to compare their weights. The green apples average 150 grams in weight, and the red apples average 160 grams in weight.

You run a hypothesis test to see if there is a significant difference in the weight of green and red apples. The test returns a p-value of 0.2. Which statement (st_1, st_2, st_3, or st_4) indicates how this p-value can be interpreted?

Update the value of interpretation with the string “st_1”, “st_2”, “st_3”, or “st_4” depending on your answer.

# possible interpretations
st_1 <- "There is a 20% chance that the difference in average weight of green and red apples is due to random sampling."
st_2 <- "There is a 20% chance that green and red apples have the same average weight."
st_3 <- "There is a 20% chance red apples weigh more than green apples."
st_4 <- "There is a 20% chance green apples weigh more than green apples."

# update the value of interpretation here:
interpretation <- "st_1"
interpretation
[1] "st_1"

A p-value of 0.2 means:

If green and red apples really weigh the same on average, there is a 20% chance of seeing a difference of 10 grams (or more) just due to random variation.

8.Significance Level

While a hypothesis test will return a p-value indicating a level of confidence in the null hypothesis, it does not definitively claim whether you should reject the null hypothesis. To make this decision, you need to determine a threshold p-value for which all p-values below it will result in rejecting the null hypothesis. This threshold is known as the significance level.

A higher significance level is more likely to give a false positive, as it makes it “easier” to state that there is a difference in the populations of your data when such a difference might not actually exist. If you want to be very sure that the result is not due to sampling error, you should select a very small significance level.

It is important to choose the significance level before you perform a statistical hypothesis test. If you wait until after you receive a p-value from a test, you might pick a significance level such that you get the result you want to see. For instance, if someone is trying to publish the results of their scientific study in a journal, they might set a higher significance level that makes their results appear statistically significant. Choosing a significance level in advance helps keep everyone honest.

It is an industry-standard to set a significance level of 0.05 or less, meaning that there is a 5% or less chance that your result is due to sampling error.

The p-value is the probability of getting results at least as extreme as the observed ones, just by random chance, if the null hypothesis is true.

The p-value tells you the probability that the result (or something more extreme) could happen just by chance, assuming the null hypothesis is true.

Instrctions

1.Before you run a hypothesis test on a set of data, you set your significance level to 0.05. The hypothesis test then returns a p-value of 0.1. Can you reject the null hypothesis? Update the value of reject_hypothesis to TRUE or FALSE depending on your answer.

A 0.1 possibility that the result is just by chance.

# update reject_hypothesis here:
reject_hypothesis <- FALSE
reject_hypothesis

9.One Sample T-Test

Consider the fictional business BuyPie, which sends ingredients for pies to your household so that you can make them from scratch. Suppose that a product manager hypothesizes the average age of visitors to BuyPie.com is 30. In the past hour, the website had 100 visitors and the average age was 31. Are the visitors older than expected? Or is this just the result of chance (sampling error) and a small sample size?

You can test this using a One Sample T-Test. A One Sample T-Test compares a sample mean to a hypothetical population mean. It answers the question “What is the probability that the sample came from a distribution with the desired mean?”

The first step is formulating a null hypothesis, which again is the hypothesis that there is no difference between the populations you are comparing. The second population in a One Sample T-Test is the hypothetical population you choose. The null hypothesis that this test examines can be phrased as follows: “The set of samples belongs to a population with the target mean”.

One result of a One Sample T-Test will be a p-value, which tells you whether or not you can reject this null hypothesis. If the p-value you receive is less than your significance level, normally 0.05, you can reject the null hypothesis and state that there is a significant difference.

R has a function called t.test() in the stats package which can perform a One Sample T-Test for you.

t.test() requires two arguments, a distribution of values and an expected mean:

results <- t.test(sample_distribution, mu = expected_mean)

1.sample_distribution is the sample of values that were collected

2.mu is an argument indicating the desired mean of the hypothetical population

3.expected_mean is the value of the desired mean

t.test() will return, among other information we will not cover here, a p-value — this tells you how confident you can be that the sample of values came from a distribution with the specified mean.

P-values give you an idea of how confident you can be in a result. Just because you don’t have enough data to detect a difference doesn’t mean that there isn’t one. Generally, the more samples you have, the smaller a difference you can detect.

Instructions

1.We have provided a small dataset called ages, representing the ages of customers to BuyPie.com in the past hour, in notebook.Rmd.

Even with a small dataset like this, it is hard to make judgments from just looking at the numbers.

To understand the data better, let’s look at the mean. Calculate the mean of ages, and store the result in a variable called ages_mean. View ages_mean.

# load and view data
ages <- c(32, 34, 29, 29, 22, 39, 38, 37, 38, 36, 30, 26, 22, 22)
ages
 [1] 32 34 29 29 22 39 38 37 38 36 30 26 22 22
# calculate ages_mean here:
ages_mean <- mean(ages)
ages_mean
[1] 31

2.Use the t.test() function with ages to see what p-value the experiment returns for this distribution, where we expect the mean to be 30.

Store the results of the test in a variable called results.

Does the p-value you got with the One Sample T-Test make sense, knowing the mean of ages?

# perform t-test here:
results <- t.test(ages, mu = 30)
results

    One Sample t-test

data:  ages
t = 0.59738, df = 13, p-value = 0.5605
alternative hypothesis: true mean is not equal to 30
95 percent confidence interval:
 27.38359 34.61641
sample estimates:
mean of x 
       31 

If the true mean is really 30 (null hypothesis is true), then there is about a 56% chance you’d see a sample mean as far from 30 as 31 (or even farther) just by chance.

It means this observed difference (mean of 31 instead of 30) is completely plausible as random sampling error.

So you fail to reject the null hypothesis.

The data is consistent with the population mean being 30.

10.Two Sample T-Test

Suppose that last week, the average amount of time spent per visitor to a website was 25 minutes. This week, the average amount of time spent per visitor to a website was 29 minutes. Did the average time spent per visitor change (i.e. was there a statistically significant bump in user time on the site)? Or is this just part of natural fluctuations?

One way of testing whether this difference is significant is by using a Two Sample T-Test. A Two Sample T-Test compares two sets of data, which are both approximately normally distributed.

The null hypothesis, in this case, is that the two distributions have the same mean.

You can use R’s t.test() function to perform a Two Sample T-Test, as shown below:

results <- t.test(distribution_1, distribution_2)

When performing a Two Sample T-Test, t.test() takes two distributions as arguments and returns, among other information, a p-value.

Remember, the p-value let’s you know the probability that the difference in the means happened by chance (sampling error).

Instructions

1.We’ve created two distributions representing the time spent per visitor to BuyPie.com last week, week_1, and the time spent per visitor to BuyPie.com this week, week_2.

Find the means of these two distributions. Store them in week_1_mean and week_2_mean. View both means.

# load data
week_1 <- c(23.90507, 26.67632, 27.27434, 24.25757, 32.40423, 39.56919, 23.07010, 29.82068, 27.59434, 28.05640, 27.06757, 30.41193, 25.71359, 24.94295, 28.23124, 24.95338, 18.51232, 27.46235, 28.38017, 13.91206, 29.02616, 26.90747, 22.86777, 24.89383, 25.96948, 26.86870, 20.72676, 27.35988, 20.68409, 21.19846, 16.25801, 23.92518, 24.47923, 29.47051, 27.28425, 26.93339, 28.61027, 18.88377, 33.65469, 25.69470, 20.98291, 22.69700, 28.60279, 21.36000, 30.77685, 20.83416, 23.79367, 19.75567, 29.54421, 20.14331)
week_1
 [1] 23.90507 26.67632 27.27434 24.25757 32.40423 39.56919 23.07010 29.82068 27.59434 28.05640 27.06757 30.41193
[13] 25.71359 24.94295 28.23124 24.95338 18.51232 27.46235 28.38017 13.91206 29.02616 26.90747 22.86777 24.89383
[25] 25.96948 26.86870 20.72676 27.35988 20.68409 21.19846 16.25801 23.92518 24.47923 29.47051 27.28425 26.93339
[37] 28.61027 18.88377 33.65469 25.69470 20.98291 22.69700 28.60279 21.36000 30.77685 20.83416 23.79367 19.75567
[49] 29.54421 20.14331
week_2 <- c( 18.63432, 31.28788, 34.96798, 21.81678, 28.21620, 39.39314, 35.52223, 27.54222, 33.64395, 25.31674, 28.81392, 30.73580, 26.37242, 26.09456, 26.34073, 19.42196, 32.58798, 24.84002, 28.93348, 20.43668, 22.72496, 32.31728, 35.38431, 29.66710, 24.53513, 30.91406, 19.56118, 24.90817, 30.13164, 31.47466, 27.77684, 16.51307, 35.07702, 31.74818, 36.36053, 27.70501, 29.49870, 27.65575, 37.18504, 25.16055, 29.26554, 38.22163, 28.92102, 24.82154, 38.30155, 34.76021, 22.26869, 28.82594, 32.00975, 36.46438)
week_2
 [1] 18.63432 31.28788 34.96798 21.81678 28.21620 39.39314 35.52223 27.54222 33.64395 25.31674 28.81392 30.73580
[13] 26.37242 26.09456 26.34073 19.42196 32.58798 24.84002 28.93348 20.43668 22.72496 32.31728 35.38431 29.66710
[25] 24.53513 30.91406 19.56118 24.90817 30.13164 31.47466 27.77684 16.51307 35.07702 31.74818 36.36053 27.70501
[37] 29.49870 27.65575 37.18504 25.16055 29.26554 38.22163 28.92102 24.82154 38.30155 34.76021 22.26869 28.82594
[49] 32.00975 36.46438
# calculate week_1_mean and week_2_mean here:
week_1_mean <- mean(week_1)
week_1_mean
[1] 25.44806
week_2_mean <- mean(week_2)
week_2_mean
[1] 29.02157

2.Find the standard deviations of these two distributions. Store them in week_1_sd and week_2_sd. View both standard deviations.

# calculate week_1_sd and week_2_sd here:
week_1_sd <- sd(week_1)
week_1_sd
[1] 4.577702
week_2_sd <- sd(week_2)
week_2_sd
[1] 5.553785

3.Run a Two Sample T-Test using the t.test() function.

Save the results to a variable called results and view it. Does the p-value make sense, knowing what you know about these datasets?

# run two sample t-test here:
results<- t.test(week_1, week_2)
results

Assuming there is no real difference in average time spent between the two weeks (null hypothesis), the probability of seeing a difference as large as ~3.57 minutes (or more extreme) just by random sampling is about 0.07%.

There is strong evidence that the average time per visitor changed between week_1 and week_2.

11.Dangers of Multiple T-Tests

Suppose that you own a chain of stores that sell ants, called VeryAnts. There are three different locations: A, B, and C. You want to know if the average ant sales over the past year are significantly different between the three locations.

At first, it seems that you could perform T-tests between each pair of stores.

You know that the p-value is the probability that you incorrectly reject the null hypothesis on each t-test. The more t-tests you perform, the more likely that you are to get a false positive, a Type I error.

For a p-value of 0.05, if the null hypothesis is true, then the probability of obtaining a significant result is 1 – 0.05 = 0.95. When you run another t-test, the probability of still getting a correct result is 0.95 * 0.95, or 0.9025. That means your probability of making an error is now close to 10%! This error probability only gets bigger with the more t-tests you do.

Instructions

1.We have created samples store_a, store_b, and store_c, representing the sales at VeryAnts at locations A, B, and C, respectively. We want to see if there’s a significant difference in sales between the three locations.

Explore datasets store_a, store_b, and store_c by finding and viewing the means and standard deviations of each one. Store the means in variables called store_a_mean, store_b_mean, and store_c_mean. Store the standard deviations in variables called store_a_sd, store_b_sd, and store_c_sd.

# load data
load("store_a.Rda")
load("store_b.Rda")
load("store_c.Rda")
# calculate means here:
store_a_mean <- mean(store_a)
store_a_mean
store_b_mean <- mean(store_b)
store_b_mean
store_c_mean <- mean(store_c)
store_c_mean

[1] 58.34964

[1] 65.62629

[1] 62.36117

# calculate standard deviations here:
store_a_sd <- sd(store_a)
store_a_sd
store_b_sd <- sd(store_b)
store_b_sd
store_c_sd <- sd(store_c)
store_c_sd

[1] 14.80313

[1] 14.79597

[1] 15.14302

2.Perform a Two Sample T-test between each pair of location data.

Store the results of the tests in variables called a_b_results, a_c_results, and b_c_results. View the results for each test.

# perform two sample t-test here:
a_b_results <- t.test(store_a, store_b)
a_b_results
a_c_results <- t.test(store_a, store_c)
a_c_results
b_c_results <- t.test(store_b, store_c)
b_c_results

Welch Two Sample t-test

data: store_a and store_b t = -4.2581, df = 298, p-value = 2.767e-05 alternative hypothesis: true difference in means is not equal to 0 95 percent confidence interval: -10.639701 -3.913601 sample estimates: mean of x mean of y 58.34964 65.62629

Welch Two Sample t-test

data: store_a and store_c t = -2.3201, df = 297.85, p-value = 0.02101 alternative hypothesis: true difference in means is not equal to 0 95 percent confidence interval: -7.4142456 -0.6088286 sample estimates: mean of x mean of y 58.34964 62.36117

Welch Two Sample t-test

data: store_b and store_c t = 1.8888, df = 297.84, p-value = 0.05989 alternative hypothesis: true difference in means is not equal to 0 95 percent confidence interval: -0.1367903 6.6670182 sample estimates: mean of x mean of y 65.62629 62.36117

3.Store the probability of error for running three T-Tests in a variable called error_prob. View error_prob.

# calculate error_prob here:
error_prob <- (1-(0.95**3))
error_prob
[1] 0.142625

[1] 0.142625

12.ANOVA

In the last exercise, you saw that the probability of making a Type I error got dangerously high as you performed more t-tests.

When comparing more than two numerical datasets, the best way to preserve a Type I error probability of 0.05 is to use ANOVA. ANOVA (Analysis of Variance) tests the null hypothesis that all of the datasets you are considering have the same mean. If you reject the null hypothesis with ANOVA, you’re saying that at least one of the sets has a different mean; however, it does not tell you which datasets are different.

You can use the stats package function aov() to perform ANOVA on multiple datasets. aov() takes the different datasets combined into a data frame as an argument. For example, if you were comparing scores on a video game between math majors, writing majors, and psychology majors, you could format the data in a data frame df_scores as follows:

group score

math major 88

math major 81

writing major 92

writing major 80

psychology major 94

psychology major 83

You can then run an ANOVA test with this line:

results <- aov(score ~ group, data = df_scores)

Note: score ~ group indicates the relationship you want to analyze (i.e. how each group, or major, relates to score on the video game)

To retrieve the p-value from the results of calling aov(), use the summary() function:

summary(results)

The null hypothesis, in this case, is that all three populations have the same mean score on this video game. If you reject this null hypothesis (if the p-value is less than 0.05), you can say you are reasonably confident that a pair of datasets is significantly different. After using only ANOVA, however, you can’t make any conclusions on which two populations have a significant difference.

Let’s look at an example of ANOVA in action.

Instructions

# load libraries
library(tidyr)
# load data
load("stores.Rda")
load("stores_new.Rda")
# inspect stores here:
stores
knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Hypo5.png")

2.Perform an ANOVA on the stores data and save the test results to a variable results. Use the summary() function to view the p-value of the test. Does this p-value lead you to reject the null hypothesis?

# perform anova on stores here:
results <- aov(sales ~ store, data = stores)
summary(results)
         Df Sum Sq Mean Sq F value   Pr(>F)    

store 2 3985 1992.6 8.957 0.000153 *** Residuals 447 99437 222.5
— Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1

The column labeled Pr(>F) is the p-value for the F-test.

3.Let’s say the sales at location B have suddenly soared (maybe there’s an ant convention happening nearby). The new sales for location B have been updated in the stores_new data frame.

Re-run the ANOVA test on stores_new and save the test results to a variable results_new. Use the summary() function to see what the p-value is now. Does this new value make sense?

# perform anova on stores_new here:
results_new <- aov(sales ~ store, data = stores_new)
summary(results_new)
         Df Sum Sq Mean Sq F value Pr(>F)    

store 2 775599 387799 1805 <2e-16 *** Residuals 447 96058 215
— Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1

Key value: Pr(>F) = < 2e-16 This is shorthand for a p-value less than 0.0000000000000002

Way below any common significance level (like 0.05 or 0.01)

Reject the null hypothesis

There is a statistically significant difference between the group means for the different stores

The difference is extremely unlikely to be due to chance

There’s overwhelming evidence that the average value (whatever you’re measuring) differs significantly among the three stores.

13.Assumptions of Numerical Hypothesis Tests

Before you use numerical hypothesis tests, you need to be sure that the following things are true:

  1. The samples should each be normally distributed…ish Data analysts in the real world often still perform hypothesis tests on datasets that aren’t exactly normally distributed. What is more important is to recognize if there is some reason to believe that a normal distribution is especially unlikely. If your dataset is definitively not normal, the numerical hypothesis tests won’t work as intended.

For example, imagine you have three datasets, each representing a day of traffic data in three different cities. Each dataset is independent, as traffic in one city should not impact traffic in another city. However, it is unlikely that each dataset is normally distributed. In fact, each dataset probably has two distinct peaks, one at the morning rush hour and one during the evening rush hour. The histogram of a day of traffic data might look something like this:

knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Hypo6.png")

In this scenario, using a numerical hypothesis test would be inappropriate.

  1. The population standard deviations of the groups should be equal For ANOVA and Two Sample T-Tests, using datasets with standard deviations that are significantly different from each other will often obscure the differences in group means.

To check for similarity between the standard deviations, it is normally sufficient to divide the two standard deviations and see if the ratio is “close enough” to 1. “Close enough” may differ in different contexts, but generally staying within 10% should suffice.

  1. The samples must be independent When comparing two or more datasets, the values in one distribution should not affect the values in another distribution. In other words, knowing more about one distribution should not give you any information about any other distribution.

Here are some examples where it would seem the samples are not independent:

1.the number of goals scored per soccer player before, during, and after undergoing a rigorous training regimen

2.a group of patients’ blood pressure levels before, during, and after the administration of a drug

It is important to understand your datasets before you begin conducting hypothesis tests on them so that you know you are choosing the right test.

Instrctions

1.Use the base R hist() function to display the histograms for dist_one, dist_two, dist_three, and dist_four.

# load data
load("dist_one.Rda")
load("dist_two.Rda")
load("dist_three.Rda")
load("dist_four.Rda")
# plot histograms and define not_normal here:
hist(dist_one)
knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Hypo7.png")

hist(dist_two)
knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Hypo8.png")

hist(dist_three)
knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Hypo9.png")

hist(dist_four)
knitr::include_graphics("C:/Users/kuoan/Desktop/R Code/Hypo10.png")

2.Do the distributions look normal?

One of these distributions would probably not be a good choice to use in an ANOVA comparison. Create a variable called not_normal and set it equal to the distribution number (1, 2, 3, or 4) that would be least suited for use in an ANOVA test.

*Hint : A normal distribution will have a bell shaped curve with one mean.

not_normal <- 4
not_normal 
[1] 4

3.Calculate the ratio of standard deviations between dist_two and dist_three, and store the value in a variable called ratio. View ratio. Is this “close enough” to perform a numerical hypothesis test between the two datasets?

# define ratio here:
ratio <- sd(dist_two) / sd(dist_three)
ratio

[1] 0.5784782

One of the assumptions of a numerical hypothesis test is that the ratio of the standard deviations of the datasets are close to 1.

Since the ratio is not close to 1, these datasets should not be used together in a numerical hypothesis test.

14.Review

Phew! Nobody said hypothesis testing is easy, but you made it to the end of the lesson. Congratulations! The world of hypothesis testing is vast. There is much more you can learn, and so many applications where you can use them.

Let’s review what you’ve learned in this lesson:

1.Samples are subsets of an entire population, and the sample mean can be used to approximate the population mean

2.The null hypothesis is an assumption that there is no difference between the populations you are comparing in a hypothesis test

3.Type I Errors occur when a hypothesis test finds a correlation between things that are not related, and Type II Errors occur when a hypothesis test fails to find a correlation between things that are actually related

4.P-Values indicate the probability that, assuming the null hypothesis is true, such differences in the samples you are comparing would exist

5.The Significance Level is a threshold p-value for which all p-values below it will result in rejecting the null hypothesis

6.One Sample T-Tests indicate whether a dataset belongs to a distribution with a given mean

7.Two Sample T-Tests indicate whether there is a significant difference between two datasets

8.ANOVA (Analysis of Variance) allows you to detect if there is a significant difference between one of multiple datasets

LS0tDQp0aXRsZTogIkh5cG90aGVzaXMgVGVzdGluZyBpbiBSIg0KYXV0aG9yOiAiQW5uYWJlbCBLdW8iDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclWS0lbS0lZCAlSDolTScpYCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMgMS5JbnRyb2R1Y3Rpb24NCg0KU2F5IHlvdSB3b3JrIGZvciBhIG1ham9yIHNvY2lhbCBtZWRpYSB3ZWJzaXRlLiBZb3VyIGJvc3MgY29tZXMgdG8geW91IHdpdGggdHdvIHF1ZXN0aW9uczoNCg0KMS5kb2VzIHRoZSBkZW1vZ3JhcGhpYyBvZiB1c2VycyBvbiB5b3VyIHNpdGUgbWF0Y2ggdGhlIGNvbXBhbnnigJlzIGV4cGVjdGF0aW9uPw0KDQoyLmRpZCB0aGUgbmV3IGludGVyZmFjZSB1cGRhdGUgYWZmZWN0IHVzZXIgZW5nYWdlbWVudD8NCg0KV2l0aCB0ZXJhYnl0ZXMgb2YgdXNlciBkYXRhIGF0IHlvdXIgaGFuZHMsIHlvdSBkZWNpZGUgdGhlIGJlc3Qgd2F5IHRvIGFuc3dlciB0aGVzZSBxdWVzdGlvbnMgaXMgd2l0aCBzdGF0aXN0aWNhbCBoeXBvdGhlc2lzIHRlc3RzIQ0KDQpTdGF0aXN0aWNhbCBoeXBvdGhlc2lzIHRlc3RpbmcgaXMgYSBwcm9jZXNzIHRoYXQgYWxsb3dzIHlvdSB0byBldmFsdWF0ZSBpZiBhIGNoYW5nZSBvciBkaWZmZXJlbmNlIHNlZW4gaW4gYSBkYXRhc2V0IGlzIOKAnHJlYWzigJ0sIG9yIGlmIGl04oCZcyBqdXN0IGEgcmVzdWx0IG9mIHJhbmRvbSBmbHVjdHVhdGlvbiBpbiB0aGUgZGF0YS4NCg0KSHlwb3RoZXNpcyB0ZXN0aW5nIGNhbiBiZSBhbiBpbnRlZ3JhbCBjb21wb25lbnQgb2YgYW55IGRlY2lzaW9uIG1ha2luZyBwcm9jZXNzLiBJdCBwcm92aWRlcyBhIGZyYW1ld29yayBmb3IgZXZhbHVhdGluZyBob3cgY29uZmlkZW50IG9uZSBjYW4gYmUgaW4gbWFraW5nIGNvbmNsdXNpb25zIGJhc2VkIG9uIGRhdGEuIFNvbWUgaW5zdGFuY2VzIHdoZXJlIHRoaXMgbWlnaHQgY29tZSB1cCBpbmNsdWRlOg0KDQoxLmEgcHJvZmVzc29yIGV4cGVjdHMgYW4gZXhhbSBhdmVyYWdlIHRvIGJlIHJvdWdobHkgNzUlLCBhbmQgd2FudHMgdG8ga25vdyBpZiB0aGUgYWN0dWFsIHNjb3JlcyBsaW5lIHVwIHdpdGggdGhpcyBleHBlY3RhdGlvbi4gV2FzIHRoZSB0ZXN0IGFjdHVhbGx5IHRvbyBlYXN5IG9yIHRvbyBoYXJkPw0KDQoyLmEgcHJvZHVjdCBtYW5hZ2VyIGZvciBhIHdlYnNpdGUgd2FudHMgdG8gY29tcGFyZSB0aGUgdGltZSBzcGVudCBvbiBkaWZmZXJlbnQgdmVyc2lvbnMgb2YgYSBob21lcGFnZS4gRG9lcyBvbmUgdmVyc2lvbiBtYWtlIHVzZXJzIHN0YXkgb24gdGhlIHBhZ2Ugc2lnbmlmaWNhbnRseSBsb25nZXI/DQoNCkluIHRoaXMgbGVzc29uLCB5b3Ugd2lsbCBjb3ZlciB0aGUgZnVuZGFtZW50YWwgY29uY2VwdHMgdGhhdCB3aWxsIGhlbHAgeW91IHJ1biBhbmQgZXZhbHVhdGUgaHlwb3RoZXNpcyB0ZXN0czoNCg0KMS5TYW1wbGUgYW5kIFBvcHVsYXRpb24gTWVhbg0KDQoyLlAtVmFsdWVzDQoNCjMuU2lnbmlmaWNhbmNlIExldmVsDQoNCjQuVHlwZSBJIGFuZCBUeXBlIElJIEVycm9ycw0KDQpZb3Ugd2lsbCB0aGVuIGxlYXJuIGFib3V0IHRocmVlIGRpZmZlcmVudCBoeXBvdGhlc2lzIHRlc3RzIHlvdSBjYW4gcGVyZm9ybSB0byBhbnN3ZXIgdGhlIGtpbmRzIG9mIHF1ZXN0aW9ucyBkaXNjdXNzZWQgYWJvdmU6DQoNCjEuT25lIFNhbXBsZSBULVRlc3QNCg0KMi5Ud28gU2FtcGxlIFQtVGVzdA0KDQozLkFOT1ZBIChBbmFseXNpcyBvZiBWYXJpYW5jZSkNCg0KTGV04oCZcyBnZXQgc3RhcnRlZCENCg0KIyMgSW5zdHJ1Y3Rpb25zDQoNClRoZSBjb2RlIGluIG5vdGVib29rLlJtZCBwZXJmb3JtcyBhIGh5cG90aGVzaXMgdGVzdCBvbiBkYXRhIGZvciBhIGNvbXBhbnkgQnV5UGllLmNvbS4gVGhlIHRlc3QgZXZhbHVhdGVzIHdoZXRoZXIgdGhlIHRpbWUgc3BlbnQgcGVyIHZpc2l0b3Igb24gdGhlIHdlYnNpdGUgY2hhbmdlcyBzaWduaWZpY2FudGx5IGJldHdlZW4gdHdvIHdlZWtzLg0KDQpSZWFkIHRoZSBvdXRwdXQgYXQgdGhlIGJvdHRvbSBvZiB0aGUgcmVuZGVyZWQgbm90ZWJvb2suIERvIHlvdSB0aGluayB0aGVyZSBpcyBhIGRpZmZlcmVuY2UgaW4gdGltZSBzcGVudCBwZXIgdmlzaXRvciBiZXR3ZWVuIFdlZWsgMSBhbmQgV2VlayAyPw0KDQpCeSB0aGUgZW5kIG9mIHRoZSBsZXNzb24sIHlvdSB3aWxsIGJlIGFibGUgdG8gcGVyZm9ybSBhbmQgaW50ZXJwcmV0IHN1Y2ggaHlwb3RoZXNpcyB0ZXN0cyB5b3Vyc2VsZiENCg0KYGBge3IgbWVzc2FnZSA9IEZBTFNFfQ0KIyBsb2FkIGRhdGENCmxvYWQoIndlZWtfMS5SZGEiKQ0KbG9hZCgid2Vla18yLlJkYSIpDQpgYGANCg0KYGBge3J9DQojIGNhbGN1bGF0ZSB3ZWVrXzFfbWVhbiBhbmQgd2Vla18yX21lYW46DQp3ZWVrXzFfbWVhbiA8LSBtZWFuKHdlZWtfMSkNCndlZWtfMV9tZWFuDQp3ZWVrXzJfbWVhbiA8LSBtZWFuKHdlZWtfMikNCndlZWtfMl9tZWFuDQpgYGANCg0KWzFdIDI1LjQ0ODA2DQoNClsxXSAyOS4wMjE1Nw0KDQpgYGB7cn0NCiMgY2FsY3VsYXRlIHdlZWtfMV9zZCBhbmQgd2Vla18yX3NkOg0Kd2Vla18xX3NkIDwtIHNkKHdlZWtfMSkNCndlZWtfMV9zZA0Kd2Vla18yX3NkIDwtIHNkKHdlZWtfMikNCndlZWtfMl9zZA0KYGBgDQoNClsxXSA0LjU3NzcwMg0KDQpbMV0gNS41NTM3ODUNCg0KDQpgYGB7cn0NCiMgcnVuIHR3byBzYW1wbGUgdC10ZXN0Og0KcmVzdWx0cyA8LSB0LnRlc3Qod2Vla18xLHdlZWtfMikNCnJlc3VsdHMNCmBgYA0KDQogICBXZWxjaCBUd28gU2FtcGxlIHQtdGVzdA0KDQpkYXRhOiAgd2Vla18xIGFuZCB3ZWVrXzINCnQgPSAtMy41MTA5LCBkZiA9IDk0LjU1NCwgcC12YWx1ZSA9IDAuMDAwNjg2Mw0KYWx0ZXJuYXRpdmUgaHlwb3RoZXNpczogdHJ1ZSBkaWZmZXJlbmNlIGluIG1lYW5zIGlzIG5vdCBlcXVhbCB0byAwDQo5NSBwZXJjZW50IGNvbmZpZGVuY2UgaW50ZXJ2YWw6DQogLTUuNTk0Mjk5IC0xLjU1MjcxOA0Kc2FtcGxlIGVzdGltYXRlczoNCm1lYW4gb2YgeCBtZWFuIG9mIHkgDQogMjUuNDQ4MDYgIDI5LjAyMTU3IA0KIA0KIA0KIyAyLlNhbXBsZSBNZWFuIGFuZCBQb3B1bGF0aW9uIE1lYW4gLSBJDQoNClN1cHBvc2UgeW91IHdhbnQgdG8ga25vdyB0aGUgYXZlcmFnZSBoZWlnaHQgb2YgYW4gb2FrIHRyZWUgaW4geW91ciBsb2NhbCBwYXJrLiBPbiBNb25kYXksIHlvdSBtZWFzdXJlIDEwIHRyZWVzIGFuZCBnZXQgYW4gYXZlcmFnZSBoZWlnaHQgb2YgMzIgZnQuIE9uIFR1ZXNkYXksIHlvdSBtZWFzdXJlIDEyIGRpZmZlcmVudCB0cmVlcyBhbmQgcmVhY2ggYW4gYXZlcmFnZSBoZWlnaHQgb2YgMzUgZnQuIE9uIFdlZG5lc2RheSwgeW91IG1lYXN1cmUgdGhlIHJlbWFpbmluZyAxMSB0cmVlcyBpbiB0aGUgcGFyaywgd2hvc2UgYXZlcmFnZSBoZWlnaHQgaXMgMzEgZnQuIFRoZSBhdmVyYWdlIGhlaWdodCBmb3IgYWxsIDMzIHRyZWVzIGluIHlvdXIgbG9jYWwgcGFyayBpcyAzMi44IGZ0Lg0KDQpUaGUgY29sbGVjdGlvbiBvZiBpbmRpdmlkdWFsIGhlaWdodCBtZWFzdXJlbWVudHMgb24gTW9uZGF5LCBUdWVzZGF5LCBhbmQgV2VkbmVzZGF5IGFyZSBlYWNoIGNhbGxlZCBzYW1wbGVzLiBBIHNhbXBsZSBpcyBhIHN1YnNldCBvZiB0aGUgZW50aXJlIHBvcHVsYXRpb24gKGFsbCB0aGUgb2FrIHRyZWVzIGluIHRoZSBwYXJrKS4gVGhlIG1lYW4gb2YgZWFjaCBzYW1wbGUgaXMgYSBzYW1wbGUgbWVhbiBhbmQgaXQgaXMgYW4gZXN0aW1hdGUgb2YgdGhlIHBvcHVsYXRpb24gbWVhbi4NCg0KTm90ZTogdGhlIHNhbXBsZSBtZWFucyAoMzIgZnQuLCAzNSBmdC4sIGFuZCAzMSBmdC4pIHdlcmUgYWxsIGNsb3NlIHRvIHRoZSBwb3B1bGF0aW9uIG1lYW4gKDMyLjggZnQuKSwgYnV0IHdlcmUgYWxsIHNsaWdodGx5IGRpZmZlcmVudCBmcm9tIHRoZSBwb3B1bGF0aW9uIG1lYW4gYW5kIGZyb20gZWFjaCBvdGhlci4NCg0KRm9yIGEgcG9wdWxhdGlvbiwgdGhlIG1lYW4gaXMgYSBjb25zdGFudCB2YWx1ZSBubyBtYXR0ZXIgaG93IG1hbnkgdGltZXMgaXTigJlzIHJlY2FsY3VsYXRlZC4gQnV0IHdpdGggYSBzZXQgb2Ygc2FtcGxlcywgdGhlIG1lYW4gd2lsbCBkZXBlbmQgb24gZXhhY3RseSB3aGljaCBzYW1wbGVzIGFyZSBzZWxlY3RlZC4gRnJvbSBhIHNhbXBsZSBtZWFuLCB3ZSBjYW4gdGhlbiBleHRyYXBvbGF0ZSB0aGUgbWVhbiBvZiB0aGUgcG9wdWxhdGlvbiBhcyBhIHdob2xlLiBUaGVyZSBhcmUgdGhyZWUgbWFpbiByZWFzb25zIHdlIG1pZ2h0IHVzZSBzYW1wbGluZzoNCg0KMS5kYXRhIG9uIHRoZSBlbnRpcmUgcG9wdWxhdGlvbiBpcyBub3QgYXZhaWxhYmxlDQoNCjIuZGF0YSBvbiB0aGUgZW50aXJlIHBvcHVsYXRpb24gaXMgYXZhaWxhYmxlLCBidXQgaXQgaXMgc28gbGFyZ2UgdGhhdCBpdCBpcyB1bmZlYXNpYmxlIHRvIGFuYWx5emUNCg0KMy5tZWFuaW5nZnVsIGFuc3dlcnMgdG8gcXVlc3Rpb25zIGNhbiBiZSBmb3VuZCBmYXN0ZXIgd2l0aCBzYW1wbGluZw0KDQojIyBJbnN0cnVjdGlvbnMNCg0KMS5JbiB0aGUgd29ya3NwYWNlLCB3ZeKAmXZlIGdlbmVyYXRlZCBhIHJhbmRvbSBwb3B1bGF0aW9uIG9mIHNpemUgMzAwIHRoYXQgZm9sbG93cyBhIG5vcm1hbCBkaXN0cmlidXRpb24gd2l0aCBhIG1lYW4gb2YgNjUuIFVwZGF0ZSB0aGUgdmFsdWUgb2YgcG9wdWxhdGlvbl9tZWFuIHRvIHN0b3JlIHRoZSBtZWFuKCkgb2YgcG9wdWxhdGlvbi4gRG9lcyBpdCBjbG9zZWx5IG1hdGNoIHlvdXIgZXhwZWN0YXRpb24/DQoNCmBgYHtyfQ0KIyBnZW5lcmF0ZSByYW5kb20gcG9wdWxhdGlvbg0KcG9wdWxhdGlvbiA8LSBybm9ybSgzMDAsIG1lYW49NjUsIHNkPTMuNSkNCg0KIyBjYWxjdWxhdGUgcG9wdWxhdGlvbiBtZWFuIGhlcmU6DQpwb3B1bGF0aW9uX21lYW4gPC0gbWVhbihwb3B1bGF0aW9uKQ0KcG9wdWxhdGlvbl9tZWFuDQpgYGANCjIuTGV04oCZcyBsb29rIGF0IGhvdyB0aGUgbWVhbnMgb2YgZGlmZmVyZW50IHNhbXBsZXMgY2FuIHZhcnkgd2l0aGluIHRoZSBzYW1lIHBvcHVsYXRpb24uDQoNClRoZSBjb2RlIGluIHRoZSBub3RlYm9vayBnZW5lcmF0ZXMgNSByYW5kb20gc2FtcGxlcyBmcm9tIHBvcHVsYXRpb24uIHNhbXBsZV8xIGlzIGRpc3BsYXllZCBhbmQgc2FtcGxlXzFfbWVhbiBoYXMgYmVlbiBjYWxjdWxhdGVkLg0KDQpSZXBsYWNlIHRoZSAiTm90IGNhbGN1bGF0ZWQiIHN0cmluZ3Mgd2l0aCBjYWxjdWxhdGlvbnMgb2YgdGhlIG1lYW5zIGZvciBzYW1wbGVfMiwgc2FtcGxlXzMsIHNhbXBsZV80LCBhbmQgc2FtcGxlXzUuDQoNCkxvb2sgYXQgdGhlIHBvcHVsYXRpb24gbWVhbiBhbmQgdGhlIHNhbXBsZSBtZWFucy4gQXJlIHRoZXkgYWxsIHRoZSBzYW1lPyBBbGwgZGlmZmVyZW50PyBXaHk/DQoNCmBgYHtyfQ0KIyBnZW5lcmF0ZSBzYW1wbGUgMQ0Kc2FtcGxlXzEgPC0gc2FtcGxlKHBvcHVsYXRpb24sIHNpemU9MzApDQpzYW1wbGVfMQ0KDQojIGNhbGN1bGF0ZSBzYW1wbGUgMSBtZWFuDQpzYW1wbGVfMV9tZWFuIDwtIG1lYW4oc2FtcGxlXzEpDQpzYW1wbGVfMV9tZWFuDQpgYGANCg0KYGBge3J9DQojIGdlbmVyYXRlIHNhbXBsZXMgMiwzLDQgYW5kIDUNCnNhbXBsZV8yIDwtIHNhbXBsZShwb3B1bGF0aW9uLCBzaXplPTMwKQ0Kc2FtcGxlXzMgPC0gc2FtcGxlKHBvcHVsYXRpb24sIHNpemU9MzApDQpzYW1wbGVfNCA8LSBzYW1wbGUocG9wdWxhdGlvbiwgc2l6ZT0zMCkNCnNhbXBsZV81IDwtIHNhbXBsZShwb3B1bGF0aW9uLCBzaXplPTMwKQ0KYGBgDQoNCmBgYHtyfQ0KIyBjYWxjdWxhdGUgc2FtcGxlIG1lYW5zIGhlcmU6DQpzYW1wbGVfMl9tZWFuIDwtIG1lYW4oc2FtcGxlXzIpDQpzYW1wbGVfMl9tZWFuDQpzYW1wbGVfM19tZWFuIDwtIG1lYW4oc2FtcGxlXzMpDQpzYW1wbGVfM19tZWFuDQpzYW1wbGVfNF9tZWFuIDwtIG1lYW4oc2FtcGxlXzQpDQpzYW1wbGVfNF9tZWFuDQpzYW1wbGVfNV9tZWFuIDwtIG1lYW4oc2FtcGxlXzUpDQpzYW1wbGVfNV9tZWFuDQpgYGANCg0KIyAzLlNhbXBsZSBNZWFuIGFuZCBQb3B1bGF0aW9uIE1lYW4gLSBJSQ0KDQpJbiB0aGUgcHJldmlvdXMgZXhlcmNpc2UsIHRoZSBzYW1wbGUgbWVhbnMgeW91IGNhbGN1bGF0ZWQgY2xvc2VseSBhcHByb3hpbWF0ZWQgdGhlIHBvcHVsYXRpb24gbWVhbi4gVGhpcyB3b27igJl0IGFsd2F5cyBiZSB0aGUgY2FzZSENCg0KQ29uc2lkZXIgYSB0YWlsb3Igb2Ygc2Nob29sIHVuaWZvcm1zIGF0IGEgc2Nob29sIGZvciBzdHVkZW50cyBhZ2VkIDExIHRvIDEzLiBUaGUgdGFpbG9yIG5lZWRzIHRvIGtub3cgdGhlIGF2ZXJhZ2UgaGVpZ2h0IG9mIGFsbCB0aGUgc3R1ZGVudHMgaW4gb3JkZXIgdG8ga25vdyB3aGljaCBzaXplcyB0byBtYWtlIHRoZSB1bmlmb3Jtcy4NCg0KVGhlIHRhaWxvciBtZWFzdXJlcyB0aGUgaGVpZ2h0cyBvZiBhIHJhbmRvbSBzYW1wbGUgb2YgMjAgc3R1ZGVudHMgb3V0IG9mIHRoZSAzMDAgaW4gdGhlIHNjaG9vbC4gVGhlIGF2ZXJhZ2UgaGVpZ2h0IG9mIHRoZSBzYW1wbGUgaXMgNTcuNSBpbmNoZXMuIFVzaW5nIHRoaXMgc2FtcGxlIG1lYW4sIHRoZSB0YWlsb3IgbWFrZXMgdW5pZm9ybXMgdGhhdCBmaXQgc3R1ZGVudHMgb2YgdGhpcyBoZWlnaHQsIHNvbWUgc21hbGxlciwgYW5kIHNvbWUgbGFyZ2VyLg0KDQpBZnRlciBkZWxpdmVyaW5nIHRoZSB1bmlmb3JtcywgdGhlIHRhaWxvciBzdGFydHMgdG8gcmVjZWl2ZSBzb21lIGZlZWRiYWNrIOKAlCBtYW55IG9mIHRoZSB1bmlmb3JtcyBhcmUgdG9vIHNtYWxsISBUaGV5IGdvIGJhY2sgdG8gdGFrZSBtZWFzdXJlbWVudHMgb24gdGhlIHJlc3Qgb2YgdGhlIHN0dWRlbnRzLCBjb2xsZWN0aW5nIHRoZSBmb2xsb3dpbmcgZGF0YToNCg0KMS4xMSB5ZWFyIG9sZHMgYXZlcmFnZSBoZWlnaHQ6IDU2LjcgaW5jaGVzDQoNCjIuMTIgeWVhciBvbGRzIGF2ZXJhZ2UgaGVpZ2h0OiA1OSBpbmNoZXMNCg0KMy4xMyB5ZWFyIG9sZHMgYXZlcmFnZSBoZWlnaHQ6IDYyLjggaW5jaGVzDQoNCjQuQWxsIHN0dWRlbnRzIGF2ZXJhZ2UgaGVpZ2h0IChwb3B1bGF0aW9uIG1lYW4pOiA1OS41IGluY2hlcw0KDQpUaGUgb3JpZ2luYWwgc2FtcGxlIG1lYW4gd2FzIG9mZiBmcm9tIHRoZSBwb3B1bGF0aW9uIG1lYW4gYnkgMiBpbmNoZXMhIEhvdyBkaWQgdGhpcyBoYXBwZW4/DQoNClRoZSByYW5kb20gc2FtcGxlIG9mIDIwIHN0dWRlbnRzIHdhcyBza2V3ZWQgdG8gb25lIGRpcmVjdGlvbiBvZiB0aGUgdG90YWwgcG9wdWxhdGlvbi4gTW9yZSAxMSB5ZWFyIG9sZHMgd2VyZSBjaG9zZW4gaW4gdGhlIHNhbXBsZSB0aGFuIGlzIHJlcHJlc2VudGF0aXZlIG9mIHRoZSB3aG9sZSBzY2hvb2wsIGJyaW5naW5nIGRvd24gdGhlIGF2ZXJhZ2UgaGVpZ2h0IG9mIHRoZSBzYW1wbGUuIFRoaXMgaXMgY2FsbGVkIGEgc2FtcGxpbmcgZXJyb3IsIGFuZCBvY2N1cnMgd2hlbiBhIHNhbXBsZSBpcyBub3QgcmVwcmVzZW50YXRpdmUgb2YgdGhlIHBvcHVsYXRpb24gaXQgY29tZXMgZnJvbS4gSG93IGRvIHlvdSBnZXQgYW4gYXZlcmFnZSBzYW1wbGUgaGVpZ2h0IHRoYXQgbG9va3MgbW9yZSBsaWtlIHRoZSBhdmVyYWdlIHBvcHVsYXRpb24gaGVpZ2h0LCBhbmQgcmVkdWNlIHRoZSBjaGFuY2Ugb2YgYSBzYW1wbGluZyBlcnJvcj8NCg0KU2VsZWN0aW5nIG9ubHkgMjAgc3R1ZGVudHMgZm9yIHRoZSBzYW1wbGUgYWxsb3dlZCBmb3IgdGhlIGNoYW5jZSB0aGF0IG9ubHkgeW91bmdlciwgc2hvcnRlciBzdHVkZW50cyB3ZXJlIGluY2x1ZGVkLiBUaGlzIGlzIGEgbmF0dXJhbCBjb25zZXF1ZW5jZSBvZiB0aGUgZmFjdCB0aGF0IGEgc2FtcGxlIGhhcyBsZXNzIGRhdGEgdGhhbiB0aGUgcG9wdWxhdGlvbiB0byB3aGljaCBpdCBiZWxvbmdzLiBJZiB0aGUgc2FtcGxlIHNlbGVjdGlvbiBpcyBwb29yLCB0aGVuIHlvdSB3aWxsIGhhdmUgYSBzYW1wbGUgbWVhbiBzZXJpb3VzbHkgc2tld2VkIGZyb20gdGhlIHBvcHVsYXRpb24gbWVhbi4NCg0KVGhlcmUgaXMgb25lIHN1cmVmaXJlIHdheSB0byBtaXRpZ2F0ZSB0aGUgcmlzayBvZiBoYXZpbmcgYSBza2V3ZWQgc2FtcGxlIG1lYW4g4oCUIHRha2UgYSBsYXJnZXIgc2V0IG9mIHNhbXBsZXMhIFRoZSBzYW1wbGUgbWVhbiBvZiBhIGxhcmdlciBzYW1wbGUgc2V0IHdpbGwgbW9yZSBjbG9zZWx5IGFwcHJveGltYXRlIHRoZSBwb3B1bGF0aW9uIG1lYW4sIGFuZCByZWR1Y2UgdGhlIGNoYW5jZSBvZiBhIHNhbXBsaW5nIGVycm9yLg0KDQoNCiMjIEluc3RydWN0aW9ucw0KDQpJbiB0aGUgd29ya3NwYWNlLCB3ZSBoYXZlIGEgcG9wdWxhdGlvbiB0aGF0IGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBHZW5lcmF0ZSBzYW1wbGVzIG9mIGRpZmZlcmVudCBzaXplcyBhbmQgc2VlIGhvdyB0aGUgc2FtcGxlIG1lYW4gY291bGQgZGlmZmVyIGZyb20gdGhlIHBvcHVsYXRpb24gbWVhbi4NCg0KV2hhdCBoYXBwZW5zIHRvIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHNhbXBsZSBtZWFuIGFuZCB0aGUgcG9wdWxhdGlvbiBtZWFuIGFzIHlvdSBpbmNyZWFzZSB0aGUgc2FtcGxlIHNpemU/DQoNCmBgYHtyIEh5cG8xLCBvdXQud2lkdGg9IjYwJSJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiQzovVXNlcnMva3VvYW4vRGVza3RvcC9SIENvZGUvSHlwbzEucG5nIikNCmBgYA0KYGBge3IgSHlwbzIsIG91dC53aWR0aD0iNjAlIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9rdW9hbi9EZXNrdG9wL1IgQ29kZS9IeXBvMi5wbmciKQ0KYGBgDQpgYGB7ciBIeXBvMywgb3V0LndpZHRoPSI2MCUifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkM6L1VzZXJzL2t1b2FuL0Rlc2t0b3AvUiBDb2RlL0h5cG8zLnBuZyIpDQpgYGANCmBgYHtyIEh5cG80LCBvdXQud2lkdGg9IjYwJSJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiQzovVXNlcnMva3VvYW4vRGVza3RvcC9SIENvZGUvSHlwbzQucG5nIikNCmBgYA0KDQojIDQuSHlwb3RoZXNpcyBGb3JtdWxhdGlvbg0KDQpZb3UgYmVnaW4gdGhlIHN0YXRpc3RpY2FsIGh5cG90aGVzaXMgdGVzdGluZyBwcm9jZXNzIGJ5IGRlZmluaW5nIGEgaHlwb3RoZXNpcywgb3IgYW4gYXNzdW1wdGlvbiBhYm91dCB5b3VyIHBvcHVsYXRpb24gdGhhdCB5b3Ugd2FudCB0byB0ZXN0LiBBIGh5cG90aGVzaXMgY2FuIGJlIHdyaXR0ZW4gaW4gd29yZHMsIGJ1dCBjYW4gYWxzbyBiZSBleHBsYWluZWQgaW4gdGVybXMgb2YgdGhlIHNhbXBsZSBhbmQgcG9wdWxhdGlvbiBtZWFucyB5b3UganVzdCBsZWFybmVkIGFib3V0Lg0KDQpTYXkgeW91IGFyZSBkZXZlbG9waW5nIGEgd2Vic2l0ZSBhbmQgd2FudCB0byBjb21wYXJlIHRoZSB0aW1lIHNwZW50IG9uIGRpZmZlcmVudCB2ZXJzaW9ucyBvZiBhIGhvbWVwYWdlLiBZb3UgY291bGQgcnVuIGEgaHlwb3RoZXNpcyB0ZXN0IHRvIHNlZSBpZiB2ZXJzaW9uIEEgb3IgQiBtYWtlcyB1c2VycyBzdGF5IG9uIHRoZSBwYWdlIHNpZ25pZmljYW50bHkgbG9uZ2VyLiBZb3VyIGh5cG90aGVzaXMgbWlnaHQgYmU6DQoNCiJUaGUgYXZlcmFnZSB0aW1lIHNwZW50IG9uIGhvbWVwYWdlIEEgaXMgZ3JlYXRlciB0aGFuIHRoZSBhdmVyYWdlIHRpbWUgc3BlbnQgb24gaG9tZXBhZ2UgQi4iDQoNCldoaWxlIHRoaXMgaXMgYSBmaW5lIGh5cG90aGVzaXMgdG8gbWFrZSwgZGF0YSBhbmFseXN0cyBhcmUgb2Z0ZW4gdmVyeSBoZXNpdGFudCBwZW9wbGUuIFRoZXkgZG9u4oCZdCBsaWtlIHRvIG1ha2UgYm9sZCBjbGFpbXMgd2l0aG91dCBoYXZpbmcgZGF0YSB0byBiYWNrIHRoZW0gdXAhIFRodXMgd2hlbiBjb25zdHJ1Y3RpbmcgaHlwb3RoZXNlcyBmb3IgYSBoeXBvdGhlc2lzIHRlc3QsIHlvdSB3YW50IHRvIGZvcm11bGF0ZSBhIG51bGwgaHlwb3RoZXNpcy4gQSBudWxsIGh5cG90aGVzaXMgc3RhdGVzIHRoYXQgdGhlcmUgaXMgbm8gZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBwb3B1bGF0aW9ucyB5b3UgYXJlIGNvbXBhcmluZywgYW5kIGl0IGltcGxpZXMgdGhhdCBhbnkgZGlmZmVyZW5jZSBzZWVuIGluIHRoZSBzYW1wbGUgZGF0YSBpcyBkdWUgdG8gc2FtcGxpbmcgZXJyb3IuIEEgbnVsbCBoeXBvdGhlc2lzIGZvciB0aGUgc2FtZSBzY2VuYXJpbyBpcyBhcyBmb2xsb3dzOg0KDQoiVGhlIGF2ZXJhZ2UgdGltZSBzcGVudCBvbiBob21lcGFnZSBBIGlzIHRoZSBzYW1lIGFzIHRoZSBhdmVyYWdlIHRpbWUgc3BlbnQgb24gaG9tZXBhZ2UgQi4iDQoNCllvdSBjb3VsZCBhbHNvIHJlc3RhdGUgdGhpcyBpbiB0ZXJtcyBvZiBwb3B1bGF0aW9uIG1lYW46DQoNCiJUaGUgcG9wdWxhdGlvbiBtZWFuIG9mIHRpbWUgc3BlbnQgb24gaG9tZXBhZ2UgQSBpcyB0aGUgc2FtZSBhcyB0aGUgcG9wdWxhdGlvbiBtZWFuIG9mIHRpbWUgc3BlbnQgb24gaG9tZXBhZ2UgQi4iDQoNCkFmdGVyIGNvbGxlY3Rpbmcgc29tZSBzYW1wbGUgZGF0YSBvbiBob3cgdXNlcnMgaW50ZXJhY3Qgd2l0aCBlYWNoIGhvbWVwYWdlLCB5b3UgY2FuIHRoZW4gcnVuIGEgaHlwb3RoZXNpcyB0ZXN0IHVzaW5nIHRoZSBkYXRhIGNvbGxlY3RlZCB0byBkZXRlcm1pbmUgd2hldGhlciB5b3VyIG51bGwgaHlwb3RoZXNpcyBpcyB0cnVlIG9yIGZhbHNlLCBvciBjYW4gYmUgcmVqZWN0ZWQgKGkuZS4gdGhlcmUgaXMgYSBkaWZmZXJlbmNlIGluIHRpbWUgc3BlbnQgb24gaG9tZXBhZ2UgQSBvciBCKS4NCg0KIyMgSW5zdHJ1Y3Rpb25zDQoNCjEuQSByZXNlYXJjaGVyIGF0IGEgcGhhcm1hY2V1dGljYWwgY29tcGFueSBpcyB3b3JraW5nIG9uIHRoZSBkZXZlbG9wbWVudCBvZiBhIG5ldyBtZWRpY2F0aW9uIHRvIGxvd2VyIGJsb29kIHByZXNzdXJlLCBEZWVQcmVzc3VyaXplLiBUaGV5IHJ1biBhbiBleHBlcmltZW50IHdpdGggYSBjb250cm9sIGdyb3VwIG9mIDEwMCBwYXRpZW50cyB0aGF0IHJlY2VpdmUgYSBwbGFjZWJvIChhIHN1Z2FyIHBpbGwpLCBhbmQgYW4gZXhwZXJpbWVudGFsIGdyb3VwIG9mIDEwMCBwYXRpZW50cyB0aGF0IHJlY2VpdmUgRGVlUHJlc3N1cml6ZS4gQmxvb2QgcHJlc3N1cmUgbWVhc3VyZW1lbnRzIGFyZSB0YWtlbiBhZnRlciBhIDMgbW9udGggcGVyaW9kIG9uIGJvdGggZ3JvdXBzIG9mIHBhdGllbnRzLg0KDQpUaGUgcmVzZWFyY2hlciB3YW50cyB0byBydW4gYSBoeXBvdGhlc2lzIHRlc3QgdG8gY29tcGFyZSB0aGUgcmVzdWx0aW5nIGRhdGFzZXRzLiBUd28gaHlwb3RoZXNlcywgaHlwb19hIGFuZCBoeXBvX2IsIGFyZSBnaXZlbiBpbiBub3RlYm9vay5SbWQuIFdoaWNoIGNvdWxkIGJlIGEgbnVsbCBoeXBvdGhlc2lzIGZvciBjb21wYXJpbmcgdGhlIHR3byBzZXRzIG9mIGRhdGE/IFVwZGF0ZSB0aGUgdmFsdWUgb2YgbnVsbF9oeXBvXzEgdG8gdGhlIHN0cmluZyAiaHlwb19hIiBvciAiaHlwb19iIiBiYXNlZCBvbiB5b3VyIGFuc3dlci4NCg0KYGBge3J9DQojIGV4cGVyaW1lbnQgMQ0KaHlwb19hIDwtICJEZWVQcmVzc3VyaXplIGxvd2VycyBibG9vZCBwcmVzc3VyZSBpbiBwYXRpZW50cy4iDQpoeXBvX2IgPC0gIkRlZVByZXNzdXJpemUgaGFzIG5vIGVmZmVjdCBvbiBibG9vZCBwcmVzc3VyZSBpbiBwYXRpZW50cy4iDQpudWxsX2h5cG9fMSA8LSAiaHlwb19iIg0KbnVsbF9oeXBvXzENCmBgYA0KDQoyLkEgcHJvZHVjdCBtYW5hZ2VyIGF0IGEgZGF0aW5nIGFwcCBjb21wYW55IGlzIGRldmVsb3BpbmcgYSBuZXcgdXNlciBwcm9maWxlIHBhZ2Ugd2l0aCBhIGRpZmZlcmVudCBwaWN0dXJlIGxheW91dC4gVGhleSB3YW50IHRvIHNlZSBpZiB0aGUgbmV3IGxheW91dCByZXN1bHRzIGluIG1vcmUgbWF0Y2hlcyBiZXR3ZWVuIHVzZXJzIHRoYW4gdGhlIGN1cnJlbnQgbGF5b3V0LiA1MCUgb2YgcHJvZmlsZXMgYXJlIHVwZGF0ZWQgdG8gdGhlIG5ldyBsYXlvdXQsIGFuZCBvdmVyIGEgMSBtb250aCBwZXJpb2QgdGhlIG51bWJlciBvZiBtYXRjaGVzIGZvciB1c2VycyB3aXRoIHRoZSBuZXcgbGF5b3V0IGFuZCB0aGUgb3JpZ2luYWwgbGF5b3V0IGFyZSByZWNvcmRlZC4NCg0KVGhlIHByb2R1Y3QgbWFuYWdlciB3YW50cyB0byBydW4gYSBoeXBvdGhlc2lzIHRlc3QgdG8gY29tcGFyZSB0aGUgcmVzdWx0aW5nIGRhdGFzZXRzLiBUd28gaHlwb3RoZXNlcywgaHlwb19jIGFuZCBoeXBvX2QsIGFyZSBnaXZlbiBpbiBub3RlYm9vay5SbWQuIFdoaWNoIGNvdWxkIGJlIGEgbnVsbCBoeXBvdGhlc2lzIGZvciBjb21wYXJpbmcgdGhlIHR3byBzZXRzIG9mIGRhdGE/IFVwZGF0ZSB0aGUgdmFsdWUgb2YgbnVsbF9oeXBvXzIgdG8gdGhlIHN0cmluZyAiaHlwb19jIiBvciAiaHlwb19kIiBiYXNlZCBvbiB5b3VyIGFuc3dlci4NCg0KYGBge3J9DQojIGV4cGVyaW1lbnQgMg0KaHlwb19jIDwtICJUaGUgbmV3IHByb2ZpbGUgbGF5b3V0IGhhcyBubyBlZmZlY3Qgb24gbnVtYmVyIG9mIG1hdGNoZXMgd2l0aCBvdGhlciB1c2Vycy4iDQpoeXBvX2QgPC0gIlRoZSBuZXcgcHJvZmlsZSBsYXlvdXQgcmVzdWx0cyBpbiBtb3JlIG1hdGNoZXMgd2l0aCBvdGhlciB1c2VycyB0aGFuIHRoZSBvcmlnaW5hbCBsYXlvdXQuIg0KbnVsbF9oeXBvXzIgPC0gImh5cG9fYyINCm51bGxfaHlwb18yDQpgYGANCg0KIyA1LkRlc2lnbmluZyBhbiBFeHBlcmltZW50DQoNClN1cHBvc2UgeW91IHdhbnQgdG8ga25vdyBpZiBzdHVkZW50cyB3aG8gc3R1ZHkgaGlzdG9yeSBhcmUgbW9yZSBpbnRlcmVzdGVkIGluIHZvbGxleWJhbGwgdGhhbiBzdHVkZW50cyB3aG8gc3R1ZHkgY2hlbWlzdHJ5LiBCZWZvcmUgZG9pbmcgYW55dGhpbmcgZWxzZSB0byBhbnN3ZXIgeW91ciBvcmlnaW5hbCBxdWVzdGlvbiwgeW91IGNvbWUgdXAgd2l0aCBhIG51bGwgaHlwb3RoZXNpczogIkhpc3RvcnkgYW5kIGNoZW1pc3RyeSBzdHVkZW50cyBhcmUgaW50ZXJlc3RlZCBpbiB2b2xsZXliYWxsIGF0IHRoZSBzYW1lIHJhdGVzLiINCg0KVG8gdGVzdCB0aGlzIGh5cG90aGVzaXMsIHlvdSBuZWVkIHRvIGRlc2lnbiBhbiBleHBlcmltZW50IGFuZCBjb2xsZWN0IGRhdGEuIFlvdSBpbnZpdGUgMTAwIGhpc3RvcnkgbWFqb3JzIGFuZCAxMDAgY2hlbWlzdHJ5IG1ham9ycyBmcm9tIHlvdXIgdW5pdmVyc2l0eSB0byBqb2luIGFuIGV4dHJhY3VycmljdWxhciB2b2xsZXliYWxsIHRlYW0uIEFmdGVyIG9uZSB3ZWVrLCAzNCBoaXN0b3J5IG1ham9ycyBzaWduIHVwICgzNCUpLCBhbmQgMzkgY2hlbWlzdHJ5IG1ham9ycyBzaWduIHVwICgzOSUpLiBNb3JlIGNoZW1pc3RyeSBtYWpvcnMgdGhhbiBoaXN0b3J5IG1ham9ycyBzaWduZWQgdXAsIGJ1dCBpcyB0aGlzIGEg4oCccmVhbOKAnSwgb3Igc2lnbmlmaWNhbnQgZGlmZmVyZW5jZT8gQ2FuIHlvdSBjb25jbHVkZSB0aGF0IHN0dWRlbnRzIHdobyBzdHVkeSBjaGVtaXN0cnkgYXJlIG1vcmUgaW50ZXJlc3RlZCBpbiB2b2xsZXliYWxsIHRoYW4gc3R1ZGVudHMgd2hvIHN0dWR5IGhpc3Rvcnk/DQoNCkluIHlvdXIgZXhwZXJpbWVudCwgdGhlIDEwMCBoaXN0b3J5IGFuZCAxMDAgY2hlbWlzdHJ5IG1ham9ycyBhdCB5b3VyIHVuaXZlcnNpdHkgYXJlIHNhbXBsZXMgb2YgdGhlaXIgcmVzcGVjdGl2ZSBwb3B1bGF0aW9ucyAoYWxsIGhpc3RvcnkgYW5kIGNoZW1pc3RyeSBtYWpvcnMpLiBUaGUgc2FtcGxlIG1lYW5zIGFyZSB0aGUgcGVyY2VudGFnZXMgb2YgaGlzdG9yeSBtYWpvcnMgKDM0JSkgYW5kIGNoZW1pc3RyeSBtYWpvcnMgKDM5JSkgdGhhdCBzaWduZWQgdXAgZm9yIHRoZSB0ZWFtLCBhbmQgdGhlIGRpZmZlcmVuY2UgaW4gc2FtcGxlIG1lYW5zIGlzIDM5JSAtIDM0JSA9IDUlLiBUaGUgcG9wdWxhdGlvbiBtZWFucyBhcmUgdGhlIHBlcmNlbnRhZ2Ugb2YgaGlzdG9yeSBhbmQgY2hlbWlzdHJ5IG1ham9ycyB3b3JsZHdpZGUgdGhhdCB3b3VsZCBzaWduIHVwIGZvciBhbiBleHRyYWN1cnJpY3VsYXIgdm9sbGV5YmFsbCB0ZWFtIGlmIGdpdmVuIHRoZSBjaGFuY2UuDQoNCllvdSB3YW50IHRvIGtub3cgaWYgdGhlIGRpZmZlcmVuY2UgeW91IG9ic2VydmVkIGluIHRoZXNlIHNhbXBsZSBtZWFucyAoNSUpIHJlZmxlY3RzIGEgZGlmZmVyZW5jZSBpbiB0aGUgcG9wdWxhdGlvbiBtZWFucywgb3IgaWYgdGhlIGRpZmZlcmVuY2Ugd2FzIGNhdXNlZCBieSBzYW1wbGluZyBlcnJvciwgYW5kIHRoZSBzYW1wbGVzIG9mIHN0dWRlbnRzIHlvdSBjaG9zZSBkbyBub3QgcmVwcmVzZW50IHRoZSBncmVhdGVyIHBvcHVsYXRpb25zIG9mIGhpc3RvcnkgYW5kIGNoZW1pc3RyeSBzdHVkZW50cy4NCg0KUmVzdGF0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMgaW4gdGVybXMgb2YgdGhlIHBvcHVsYXRpb24gbWVhbnMgeWllbGRzIHRoZSBmb2xsb3dpbmc6DQoNCiJUaGUgcGVyY2VudGFnZSBvZiBhbGwgaGlzdG9yeSBtYWpvcnMgd2hvIHdvdWxkIHNpZ24gdXAgZm9yIHZvbGxleWJhbGwgaXMgdGhlIHNhbWUgYXMgdGhlIHBlcmNlbnRhZ2Ugb2YgYWxsIGNoZW1pc3RyeSBtYWpvcnMgd2hvIHdvdWxkIHNpZ24gdXAgZm9yIHZvbGxleWJhbGwsIGFuZCB0aGUgb2JzZXJ2ZWQgZGlmZmVyZW5jZSBpbiBzYW1wbGUgbWVhbnMgaXMgZHVlIHRvIHNhbXBsaW5nIGVycm9yLiINCg0KVGhpcyBpcyB0aGUgc2FtZSBhcyBzYXlpbmcsIOKAnElmIHlvdSBnYXZlIHRoZSBzYW1lIHZvbGxleWJhbGwgaW52aXRhdGlvbiB0byBldmVyeSBoaXN0b3J5IGFuZCBjaGVtaXN0cnkgbWFqb3IgaW4gdGhlIHdvcmxkLCB0aGV5IHdvdWxkIHNpZ24gdXAgYXQgdGhlIHNhbWUgcmF0ZSwgYW5kIHRoZSBzYW1wbGUgb2YgMjAwIHN0dWRlbnRzIHlvdSBzZWxlY3RlZCBhcmUgbm90IHJlcHJlc2VudGF0aXZlIG9mIHRoZWlyIHBvcHVsYXRpb25zLuKAnQ0KDQojIyBJbnN0cmN0aW9ucw0KDQoxLllvdXIgZnJpZW5kIGlzIGEgZG9nIHdhbGtlciB0aGF0IHNwZWNpYWxpemVzIGluIHdvcmtpbmcgd2l0aCBHb2xkZW4gUmV0cmlldmVycyBhbmQgR29sZGVuZG9vZGxlcy4gVGhleSBhcmUgaW50ZXJlc3RlZCBpbiBrbm93aW5nIGlmIHRoZXJlIGlzIGEgc2lnbmZpY2FudCBkaWZmZXJlbmNlIGluIHRoZSBsZW5ndGhzIG9mIHRoZSB0d28gYnJlZWRzLiBBZnRlciBhIGZldyB3ZWVrcyBvZiBkYXRhIGNvbGxlY3Rpb24sIHRoZXkgZ2l2ZSB5b3UgYSBzcHJlYWRzaGVldCBvZiAxMCBHb2xkZW4gUmV0cmlldmVyc+KAmSBsZW5ndGhzIGFuZCAxMCBHb2xkZW5kb29kbGVz4oCZIGxlbmd0aHMuDQoNClRoZSBsZW5ndGhzIG9mIHRoZSBkb2dzIGFyZSBnaXZlbiBpbiByZXRyaWV2ZXJfbGVuZ3RocyBhbmQgZG9vZGxlX2xlbmd0aHMuIENhbGN1bGF0ZSB0aGUgbWVhbiBvZiBlYWNoIGJyZWVkIGFuZCBzYXZlIHRoZSByZXN1bHRzIHRvIG1lYW5fcmV0cmlldmVyX2wgYW5kIG1lYW5fZG9vZGxlX2wuIFZpZXcgbWVhbl9yZXRyaWV2ZXJfbCBhbmQgbWVhbl9kb29kbGVfbC4NCg0KYGBge3J9DQojIGxvYWQgZGF0YQ0KbG9hZCgicmV0cmlldmVyX2xlbmd0aHMuUmRhIikNCmxvYWQoImRvb2RsZV9sZW5ndGhzLlJkYSIpDQpgYGANCg0KYGBge3J9DQojIGNhbGN1bGF0ZSBtZWFuX3JldHJpZXZlcl9sIGFuZCBtZWFuX2Rvb2RsZV9sIGhlcmU6DQptZWFuX3JldHJpZXZlcl9sIDwtIG1lYW4ocmV0cmlldmVyX2xlbmd0aHMpDQptZWFuX3JldHJpZXZlcl9sDQptZWFuX2Rvb2RsZV9sIDwtIG1lYW4oZG9vZGxlX2xlbmd0aHMpDQptZWFuX2Rvb2RsZV9sDQpgYGANCg0KWzFdIDIzDQoNClsxXSAyMC41DQoNCg0KMi5DYWxjdWxhdGUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBtZWFuX3JldHJpZXZlcl9sIGFuZCBtZWFuX2Rvb2RsZV9sIGFuZCBzYXZlIHRoZSByZXN1bHQgdG8gbWVhbl9kaWZmZXJlbmNlLiBWaWV3IG1lYW5fZGlmZmVyZW5jZS4NCg0KYGBge3J9DQojIGNhbGN1bGF0ZSBtZWFuX2RpZmZlcmVuY2UgaGVyZToNCm1lYW5fZGlmZmVyZW5jZSA8LSBtZWFuX3JldHJpZXZlcl9sIC0gbWVhbl9kb29kbGVfbA0KbWVhbl9kaWZmZXJlbmNlDQpgYGANCg0KWzFdIDIuNQ0KDQozLllvdSB3YW50IHRvIHJ1biBhIGh5cG90aGVzaXMgdGVzdCB0byBzZWUgaWYgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHRoZSBsZW5ndGhzIG9mIEdvbGRlbiBSZXRyaWV2ZXJzIGFuZCBHb2xkZW5kb29kbGVzLiBXaGljaCBvZiB0aGUgdHdvIHN0YXRlbWVudHMgY291bGQgYmUgYSBmb3JtdWxhdGlvbiBvZiB0aGUgbnVsbCBoeXBvdGhlc2lzPw0KDQpVcGRhdGUgdGhlIHZhbHVlIG9mIG51bGxfaHlwbyB3aXRoICJzdF8xIiBvciAic3RfMiIgZGVwZW5kaW5nIG9uIHlvdXIgYW5zd2VyLg0KDQpgYGB7cn0NCiMgc3RhdGVtZW50czoNCnN0XzEgPC0gIlRoZSBhdmVyYWdlIGxlbmd0aCBvZiBHb2xkZW4gUmV0cmlldmVycyBpcyAyLjUgaW5jaGVzIGxvbmdlciB0aGFuIHRoZSBhdmVyYWdlIGxlbmd0aCBvZiBHb2xkZW5kb29kbGVzLiINCnN0XzIgPC0gIlRoZSBhdmVyYWdlIGxlbmd0aCBvZiBHb2xkZW4gUmV0cmlldmVycyBpcyB0aGUgc2FtZSBhcyB0aGUgYXZlcmFnZSBsZW5ndGggb2YgR29sZGVuZG9vZGxlcy4iDQoNCiMgdXBkYXRlIG51bGxfaHlwbyBoZXJlOg0KbnVsbF9oeXBvIDwtICJzdF8yIg0KbnVsbF9oeXBvDQpgYGANCg0KIyA2LlR5cGUgSSBhbmQgVHlwZSBJSSBFcnJvcnMNCg0KV2hlbiB1c2luZyBhdXRvbWF0ZWQgcHJvY2Vzc2VzIHRvIG1ha2UgZGVjaXNpb25zLCB5b3UgbmVlZCB0byBiZSBhd2FyZSBvZiBob3cgdGhpcyBhdXRvbWF0aW9uIGNhbiBsZWFkIHRvIG1pc3Rha2VzLiBDb21wdXRlciBwcm9ncmFtcyBjYW4gYmUgYXMgZmFsbGlibGUgYXMgdGhlIGh1bWFucyB3aG8gZGVzaWduIHRoZW0uIEJlY2F1c2Ugb2YgdGhpcywgdGhlcmUgaXMgYSByZXNwb25zaWJpbGl0eSB0byB1bmRlcnN0YW5kIHdoYXQgY2FuIGdvIHdyb25nIGFuZCB3aGF0IGNhbiBiZSBkb25lIHRvIGNvbnRhaW4gdGhlc2UgZm9yZXNlZWFibGUgcHJvYmxlbXMuDQoNCkluIHN0YXRpc3RpY2FsIGh5cG90aGVzaXMgdGVzdGluZywgdGhlcmUgYXJlIHR3byB0eXBlcyBvZiBlcnJvci4gQSBUeXBlIEkgZXJyb3Igb2NjdXJzIHdoZW4gYSBoeXBvdGhlc2lzIHRlc3QgZmluZHMgYSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoaW5ncyB0aGF0IGFyZSBub3QgcmVsYXRlZC4gVGhpcyBlcnJvciBpcyBzb21ldGltZXMgY2FsbGVkIGEg4oCcZmFsc2UgcG9zaXRpdmXigJ0gYW5kIG9jY3VycyB3aGVuIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgcmVqZWN0ZWQgZXZlbiB0aG91Z2ggaXQgaXMgdHJ1ZS4NCg0KRm9yIGV4YW1wbGUsIGNvbnNpZGVyIHRoZSBoaXN0b3J5IGFuZCBjaGVtaXN0cnkgbWFqb3IgZXhwZXJpbWVudCBmcm9tIHRoZSBwcmV2aW91cyBleGVyY2lzZS4gU2F5IHlvdSBydW4gYSBoeXBvdGhlc2lzIHRlc3Qgb24gdGhlIHNhbXBsZSBkYXRhIHlvdSBjb2xsZWN0ZWQgYW5kIGNvbmNsdWRlIHRoYXQgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIGludGVyZXN0IGluIHZvbGxleWJhbGwgYmV0d2VlbiBoaXN0b3J5IGFuZCBjaGVtaXN0cnkgbWFqb3JzLiBZb3UgaGF2ZSByZWplY3RlZCB0aGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhlcmUgaXMgbm8gZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gcG9wdWxhdGlvbnMgb2Ygc3R1ZGVudHMuIElmLCBpbiByZWFsaXR5LCB5b3VyIHJlc3VsdHMgd2VyZSBkdWUgdG8gdGhlIGdyb3VwcyB5b3UgaGFwcGVuZWQgdG8gcGljayAoc2FtcGxpbmcgZXJyb3IpLCBhbmQgdGhlcmUgYWN0dWFsbHkgaXMgbm8gc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBpbiBpbnRlcmVzdCBpbiB2b2xsZXliYWxsIGJldHdlZW4gaGlzdG9yeSBhbmQgY2hlbWlzdHJ5IG1ham9ycyBpbiB0aGUgZ3JlYXRlciBwb3B1bGF0aW9uLCB5b3UgaGF2ZSBiZWNvbWUgdGhlIHZpY3RpbSBvZiBhIGZhbHNlIHBvc2l0aXZlLCBvciBhIFR5cGUgSSBlcnJvci4NCg0KVGhlIHNlY29uZCBraW5kIG9mIGVycm9yLCBhIFR5cGUgSUkgZXJyb3IsIGlzIGZhaWxpbmcgdG8gZmluZCBhIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhpbmdzIHRoYXQgYXJlIGFjdHVhbGx5IHJlbGF0ZWQuIFRoaXMgZXJyb3IgaXMgcmVmZXJyZWQgdG8gYXMgYSDigJxmYWxzZSBuZWdhdGl2ZeKAnSBhbmQgb2NjdXJzIHdoZW4gdGhlIG51bGwgaHlwb3RoZXNpcyBpcyBub3QgcmVqZWN0ZWQgZXZlbiB0aG91Z2ggaXQgaXMgZmFsc2UuDQoNCkZvciBleGFtcGxlLCB3aXRoIHRoZSBoaXN0b3J5IGFuZCBjaGVtaXN0cnkgc3R1ZGVudCBleHBlcmltZW50LCBzYXkgdGhhdCBhZnRlciB5b3UgcGVyZm9ybSB0aGUgaHlwb3RoZXNpcyB0ZXN0LCB5b3UgY29uY2x1ZGUgdGhhdCB0aGVyZSBpcyBubyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIGludGVyZXN0IGluIHZvbGxleWJhbGwgYmV0d2VlbiBoaXN0b3J5IGFuZCBjaGVtaXN0cnkgbWFqb3JzLiBZb3UgZGlkIG5vdCByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gSWYgdGhlcmUgYWN0dWFsbHkgaXMgYSBkaWZmZXJlbmNlIGluIHRoZSBwb3B1bGF0aW9ucyBhcyBhIHdob2xlLCBhbmQgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIGludGVyZXN0IGluIHZvbGxleWJhbGwgYmV0d2VlbiBoaXN0b3J5IGFuZCBjaGVtaXN0cnkgbWFqb3JzLCB5b3VyIHRlc3QgaGFzIHJlc3VsdGVkIGluIGEgZmFsc2UgbmVnYXRpdmUsIG9yIGEgVHlwZSBJSSBlcnJvci4NCg0KIyMgSW5zdHJ1Y3Rpb25zDQoNCmBgYHtyfQ0KIyB0aGUgdHJ1ZSBwb3NpdGl2ZXMgYW5kIG5lZ2F0aXZlczoNCmFjdHVhbF9wb3NpdGl2ZSA8LSBjKDIsIDUsIDYsIDcsIDgsIDEwLCAxOCwgMjEsIDI0LCAyNSwgMjksIDMwLCAzMiwgMzMsIDM4LCAzOSwgNDIsIDQ0LCA0NSwgNDcpDQphY3R1YWxfbmVnYXRpdmUgPC0gYygxLCAzLCA0LCA5LCAxMSwgMTIsIDEzLCAxNCwgMTUsIDE2LCAxNywgMTksIDIwLCAyMiwgMjMsIDI2LCAyNywgMjgsIDMxLCAzNCwgMzUsIDM2LCAzNywgNDAsIDQxLCA0MywgNDYsIDQ4LCA0OSkNCg0KIyB0aGUgcG9zaXRpdmVzIGFuZCBuZWdhdGl2ZXMgd2UgZGV0ZXJtaW5lIGJ5IHJ1bm5pbmcgdGhlIGV4cGVyaW1lbnQ6DQpleHBlcmltZW50YWxfcG9zaXRpdmUgPC0gYygyLCA0LCA1LCA3LCA4LCA5LCAxMCwgMTEsIDEzLCAxNSwgMTYsIDE3LCAxOCwgMTksIDIwLCAyMSwgMjIsIDI0LCAyNiwgMjcsIDI4LCAzMiwgMzUsIDM2LCAzOCwgMzksIDQwLCA0NSwgNDYsIDQ5KQ0KZXhwZXJpbWVudGFsX25lZ2F0aXZlIDwtIGMoMSwgMywgNiwgMTIsIDE0LCAyMywgMjUsIDI5LCAzMCwgMzEsIDMzLCAzNCwgMzcsIDQxLCA0MiwgNDMsIDQ0LCA0NywgNDgpDQpgYGANCg0KYGBge3J9DQojIGRlZmluZSB0eXBlX2lfZXJyb3JzIGFuZCB0eXBlX2lpX2Vycm9ycyBoZXJlOg0KdHlwZV9pX2Vycm9ycyA8LSBpbnRlcnNlY3QoYWN0dWFsX25lZ2F0aXZlLCBleHBlcmltZW50YWxfcG9zaXRpdmUpDQpwcmludCgnZmFsZXMgcG9zaXRpdmVzJykNCnR5cGVfaV9lcnJvcnMNCmBgYA0KDQoyLk5vdywgZGVmaW5lIHR5cGVfaWlfZXJyb3JzLCB0aGUgbGlzdCByZXByZXNlbnRpbmcgdGhlIGZhbHNlIG5lZ2F0aXZlcyBvZiB0aGUgZXhwZXJpbWVudC4NCg0KYGBge3J9DQp0eXBlX2lpX2Vycm9ycyA8LSBpbnRlcnNlY3QoYWN0dWFsX3Bvc2l0aXZlLCBleHBlcmltZW50YWxfbmVnYXRpdmUpDQpwcmludCgnZmFsZXMgbmVnYXRpdmUnKQ0KdHlwZV9paV9lcnJvcnMNCmBgYA0KDQojIDcuUC1WYWx1ZXMNCg0KWW91IGtub3cgdGhhdCBhIGh5cG90aGVzaXMgdGVzdCBpcyB1c2VkIHRvIGRldGVybWluZSB0aGUgdmFsaWRpdHkgb2YgYSBudWxsIGh5cG90aGVzaXMuIE9uY2UgYWdhaW4sIHRoZSBudWxsIGh5cG90aGVzaXMgc3RhdGVzIHRoYXQgdGhlcmUgaXMgbm8gYWN0dWFsIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIHBvcHVsYXRpb25zIG9mIGRhdGEuIEJ1dCB3aGF0IHJlc3VsdCBkb2VzIGEgaHlwb3RoZXNpcyB0ZXN0IGFjdHVhbGx5IHJldHVybiwgYW5kIGhvdyBjYW4geW91IGludGVycHJldCBpdD8NCg0KQSBoeXBvdGhlc2lzIHRlc3QgcmV0dXJucyBhIGZldyBudW1lcmljIG1lYXN1cmVzLCBtb3N0IG9mIHdoaWNoIGFyZSBvdXQgb2YgdGhlIHNjb3BlIG9mIHRoaXMgaW50cm9kdWN0b3J5IGxlc3Nvbi4gSGVyZSB3ZSB3aWxsIGZvY3VzIG9uIG9uZTogcC12YWx1ZXMuIFAtdmFsdWVzIGhlbHAgZGV0ZXJtaW5lIGhvdyBjb25maWRlbnQgeW91IGNhbiBiZSBpbiB2YWxpZGF0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMuIEluIHRoaXMgY29udGV4dCwgYSBwLXZhbHVlIGlzIHRoZSBwcm9iYWJpbGl0eSB0aGF0LCBhc3N1bWluZyB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUsIHlvdSB3b3VsZCBzZWUgYXQgbGVhc3Qgc3VjaCBhIGRpZmZlcmVuY2UgaW4gdGhlIHNhbXBsZSBtZWFucyBvZiB5b3VyIGRhdGEuDQoNCkNvbnNpZGVyIHRoZSBleHBlcmltZW50IG9uIGhpc3RvcnkgYW5kIGNoZW1pc3RyeSBtYWpvcnMgYW5kIHRoZWlyIGludGVyZXN0IGluIHZvbGxleWJhbGwgZnJvbSBhIHByZXZpb3VzIGV4ZXJjaXNlOg0KDQpOdWxsIEh5cG90aGVzaXM6ICJIaXN0b3J5IGFuZCBjaGVtaXN0cnkgc3R1ZGVudHMgYXJlIGludGVyZXN0ZWQgaW4gdm9sbGV5YmFsbCBhdCB0aGUgc2FtZSByYXRlcyINCkV4cGVyaW1lbnQgU2FtcGxlIE1lYW5zOiAzNCUgb2YgaGlzdG9yeSBtYWpvcnMgYW5kIDM5JSBvZiBjaGVtaXN0cnkgbWFqb3JzIHNpZ24gdXAgZm9yIHRoZSB2b2xsZXliYWxsIGNsYXNzDQpBc3N1bWluZyB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUsIHRoZXJlIGlzIG5vIGFjdHVhbCBkaWZmZXJlbmNlIGluIHByZWZlcmVuY2UgZm9yIHZvbGxleWJhbGwgYmV0d2VlbiBhbGwgaGlzdG9yeSBhbmQgY2hlbWlzdHJ5IG1ham9ycywgYW5kIGFueSBkaWZmZXJlbmNlIHByZXNlbnQgaW4gdGhlIGV4cGVyaW1lbnQgZGF0YSBpcyB0aGUgcmVzdWx0IG9mIHNhbXBsaW5nIGVycm9yLiBJbWFnaW5lIHlvdSBydW4gYSBoeXBvdGhlc2lzIHRlc3Qgb24gdGhpcyBleHBlcmltZW50IGRhdGEgYW5kIGl0IHJldHVybnMgYSBwLXZhbHVlIG9mIDAuMDQuIEEgcC12YWx1ZSBvZiAwLjA0IGluZGljYXRlcyB0aGF0IHlvdSBjb3VsZCBleHBlY3QgdG8gc2VlIGEgZGlmZmVyZW5jZSBvZiBhdCBsZWFzdCA1JSAoY2FsY3VsYXRlZCBhcyAzOSUgLSAzNCUgPSA1JSkgaW4gdGhlIHNhbXBsZSBtZWFucyBvbmx5IDQlIG9mIHRoZSB0aW1lLg0KDQpFc3NlbnRpYWxseSwgaWYgeW91IHJhbiB0aGlzIHNhbWUgZXhwZXJpbWVudCAxMDAgdGltZXMsIHlvdSB3b3VsZCBleHBlY3QgdG8gc2VlIGFzIGxhcmdlIGEgZGlmZmVyZW5jZSBpbiB0aGUgc2FtcGxlIG1lYW5zIG9ubHkgNCB0aW1lcyBnaXZlbiB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZXJlIGlzIG5vIGFjdHVhbCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHBvcHVsYXRpb25zIChpLmUuIHRoZXkgaGF2ZSB0aGUgc2FtZSBtZWFuKS4NCg0KU2VlbXMgbGlrZSBhIHJlYWxseSBzbWFsbCBwcm9iYWJpbGl0eSwgcmlnaHQ/IEFyZSB5b3UgdGhpbmtpbmcgYWJvdXQgcmVqZWN0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMgeW91IG9yaWdpbmFsbHkgc3RhdGVkPw0KDQoNCnZhbHVlIOKJoCBwcm9iYWJpbGl0eSB5b3VyIHJlc3VsdCBpcyB3cm9uZw0KDQp2YWx1ZSA9IHByb2JhYmlsaXR5IG9mIHlvdXIgZGF0YSAob3IgbW9yZSBleHRyZW1lKSBpZiB0aGUgbnVsbCBpcyB0cnVlDQoNClRoZSBwLXZhbHVlIGl0c2VsZiBpcyBub3QgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlIG51bGwgaXMgd3JvbmcuDQoNClllc+KAlGluIHByYWN0aWNlLCB3aGVuIHRoZSBwLXZhbHVlIGlzIHZlcnkgc21hbGwsIGl0IHN1Z2dlc3RzIHRoYXQgdGhlIG51bGwgaHlwb3RoZXNpcyBpcyBsaWtlbHkgd3JvbmcuDQoNCiMjIEluc3RyY3Rpb25zDQoNCjEuWW91IGFyZSBiaWcgZmFuIG9mIGFwcGxlcywgc28geW91IGdhdGhlciAxMCBncmVlbiBhbmQgMTAgcmVkIGFwcGxlcyB0byBjb21wYXJlIHRoZWlyIHdlaWdodHMuIFRoZSBncmVlbiBhcHBsZXMgYXZlcmFnZSAxNTAgZ3JhbXMgaW4gd2VpZ2h0LCBhbmQgdGhlIHJlZCBhcHBsZXMgYXZlcmFnZSAxNjAgZ3JhbXMgaW4gd2VpZ2h0Lg0KDQpZb3UgcnVuIGEgaHlwb3RoZXNpcyB0ZXN0IHRvIHNlZSBpZiB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gdGhlIHdlaWdodCBvZiBncmVlbiBhbmQgcmVkIGFwcGxlcy4gVGhlIHRlc3QgcmV0dXJucyBhIHAtdmFsdWUgb2YgMC4yLiBXaGljaCBzdGF0ZW1lbnQgKHN0XzEsIHN0XzIsIHN0XzMsIG9yIHN0XzQpIGluZGljYXRlcyBob3cgdGhpcyBwLXZhbHVlIGNhbiBiZSBpbnRlcnByZXRlZD8NCg0KVXBkYXRlIHRoZSB2YWx1ZSBvZiBpbnRlcnByZXRhdGlvbiB3aXRoIHRoZSBzdHJpbmcgInN0XzEiLCAic3RfMiIsICJzdF8zIiwgb3IgInN0XzQiIGRlcGVuZGluZyBvbiB5b3VyIGFuc3dlci4NCg0KYGBge3J9DQojIHBvc3NpYmxlIGludGVycHJldGF0aW9ucw0Kc3RfMSA8LSAiVGhlcmUgaXMgYSAyMCUgY2hhbmNlIHRoYXQgdGhlIGRpZmZlcmVuY2UgaW4gYXZlcmFnZSB3ZWlnaHQgb2YgZ3JlZW4gYW5kIHJlZCBhcHBsZXMgaXMgZHVlIHRvIHJhbmRvbSBzYW1wbGluZy4iDQpzdF8yIDwtICJUaGVyZSBpcyBhIDIwJSBjaGFuY2UgdGhhdCBncmVlbiBhbmQgcmVkIGFwcGxlcyBoYXZlIHRoZSBzYW1lIGF2ZXJhZ2Ugd2VpZ2h0LiINCnN0XzMgPC0gIlRoZXJlIGlzIGEgMjAlIGNoYW5jZSByZWQgYXBwbGVzIHdlaWdoIG1vcmUgdGhhbiBncmVlbiBhcHBsZXMuIg0Kc3RfNCA8LSAiVGhlcmUgaXMgYSAyMCUgY2hhbmNlIGdyZWVuIGFwcGxlcyB3ZWlnaCBtb3JlIHRoYW4gZ3JlZW4gYXBwbGVzLiINCg0KIyB1cGRhdGUgdGhlIHZhbHVlIG9mIGludGVycHJldGF0aW9uIGhlcmU6DQppbnRlcnByZXRhdGlvbiA8LSAic3RfMSINCmludGVycHJldGF0aW9uDQpgYGANCg0KQSBwLXZhbHVlIG9mIDAuMiBtZWFuczoNCg0KSWYgZ3JlZW4gYW5kIHJlZCBhcHBsZXMgcmVhbGx5IHdlaWdoIHRoZSBzYW1lIG9uIGF2ZXJhZ2UsIHRoZXJlIGlzIGEgMjAlIGNoYW5jZSBvZiBzZWVpbmcgYSBkaWZmZXJlbmNlIG9mIDEwIGdyYW1zIChvciBtb3JlKSBqdXN0IGR1ZSB0byByYW5kb20gdmFyaWF0aW9uLg0KDQojIDguU2lnbmlmaWNhbmNlIExldmVsDQoNCldoaWxlIGEgaHlwb3RoZXNpcyB0ZXN0IHdpbGwgcmV0dXJuIGEgcC12YWx1ZSBpbmRpY2F0aW5nIGEgbGV2ZWwgb2YgY29uZmlkZW5jZSBpbiB0aGUgbnVsbCBoeXBvdGhlc2lzLCBpdCBkb2VzIG5vdCBkZWZpbml0aXZlbHkgY2xhaW0gd2hldGhlciB5b3Ugc2hvdWxkIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBUbyBtYWtlIHRoaXMgZGVjaXNpb24sIHlvdSBuZWVkIHRvIGRldGVybWluZSBhIHRocmVzaG9sZCBwLXZhbHVlIGZvciB3aGljaCBhbGwgcC12YWx1ZXMgYmVsb3cgaXQgd2lsbCByZXN1bHQgaW4gcmVqZWN0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMuIFRoaXMgdGhyZXNob2xkIGlzIGtub3duIGFzIHRoZSBzaWduaWZpY2FuY2UgbGV2ZWwuDQoNCkEgaGlnaGVyIHNpZ25pZmljYW5jZSBsZXZlbCBpcyBtb3JlIGxpa2VseSB0byBnaXZlIGEgZmFsc2UgcG9zaXRpdmUsIGFzIGl0IG1ha2VzIGl0IOKAnGVhc2llcuKAnSB0byBzdGF0ZSB0aGF0IHRoZXJlIGlzIGEgZGlmZmVyZW5jZSBpbiB0aGUgcG9wdWxhdGlvbnMgb2YgeW91ciBkYXRhIHdoZW4gc3VjaCBhIGRpZmZlcmVuY2UgbWlnaHQgbm90IGFjdHVhbGx5IGV4aXN0LiBJZiB5b3Ugd2FudCB0byBiZSB2ZXJ5IHN1cmUgdGhhdCB0aGUgcmVzdWx0IGlzIG5vdCBkdWUgdG8gc2FtcGxpbmcgZXJyb3IsIHlvdSBzaG91bGQgc2VsZWN0IGEgdmVyeSBzbWFsbCBzaWduaWZpY2FuY2UgbGV2ZWwuDQoNCkl0IGlzIGltcG9ydGFudCB0byBjaG9vc2UgdGhlIHNpZ25pZmljYW5jZSBsZXZlbCBiZWZvcmUgeW91IHBlcmZvcm0gYSBzdGF0aXN0aWNhbCBoeXBvdGhlc2lzIHRlc3QuIElmIHlvdSB3YWl0IHVudGlsIGFmdGVyIHlvdSByZWNlaXZlIGEgcC12YWx1ZSBmcm9tIGEgdGVzdCwgeW91IG1pZ2h0IHBpY2sgYSBzaWduaWZpY2FuY2UgbGV2ZWwgc3VjaCB0aGF0IHlvdSBnZXQgdGhlIHJlc3VsdCB5b3Ugd2FudCB0byBzZWUuIEZvciBpbnN0YW5jZSwgaWYgc29tZW9uZSBpcyB0cnlpbmcgdG8gcHVibGlzaCB0aGUgcmVzdWx0cyBvZiB0aGVpciBzY2llbnRpZmljIHN0dWR5IGluIGEgam91cm5hbCwgdGhleSBtaWdodCBzZXQgYSBoaWdoZXIgc2lnbmlmaWNhbmNlIGxldmVsIHRoYXQgbWFrZXMgdGhlaXIgcmVzdWx0cyBhcHBlYXIgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4gQ2hvb3NpbmcgYSBzaWduaWZpY2FuY2UgbGV2ZWwgaW4gYWR2YW5jZSBoZWxwcyBrZWVwIGV2ZXJ5b25lIGhvbmVzdC4NCg0KSXQgaXMgYW4gaW5kdXN0cnktc3RhbmRhcmQgdG8gc2V0IGEgc2lnbmlmaWNhbmNlIGxldmVsIG9mIDAuMDUgb3IgbGVzcywgbWVhbmluZyB0aGF0IHRoZXJlIGlzIGEgNSUgb3IgbGVzcyBjaGFuY2UgdGhhdCB5b3VyIHJlc3VsdCBpcyBkdWUgdG8gc2FtcGxpbmcgZXJyb3IuDQoNClRoZSBwLXZhbHVlIGlzIHRoZSBwcm9iYWJpbGl0eSBvZiBnZXR0aW5nIHJlc3VsdHMgYXQgbGVhc3QgYXMgZXh0cmVtZSBhcyB0aGUgb2JzZXJ2ZWQgb25lcywganVzdCBieSByYW5kb20gY2hhbmNlLCBpZiB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUuDQoNClRoZSBwLXZhbHVlIHRlbGxzIHlvdSB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgcmVzdWx0IChvciBzb21ldGhpbmcgbW9yZSBleHRyZW1lKSBjb3VsZCBoYXBwZW4ganVzdCBieSBjaGFuY2UsIGFzc3VtaW5nIHRoZSBudWxsIGh5cG90aGVzaXMgaXMgdHJ1ZS4NCg0KIyMgSW5zdHJjdGlvbnMNCg0KMS5CZWZvcmUgeW91IHJ1biBhIGh5cG90aGVzaXMgdGVzdCBvbiBhIHNldCBvZiBkYXRhLCB5b3Ugc2V0IHlvdXIgc2lnbmlmaWNhbmNlIGxldmVsIHRvIDAuMDUuIFRoZSBoeXBvdGhlc2lzIHRlc3QgdGhlbiByZXR1cm5zIGEgcC12YWx1ZSBvZiAwLjEuIENhbiB5b3UgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXM/IFVwZGF0ZSB0aGUgdmFsdWUgb2YgcmVqZWN0X2h5cG90aGVzaXMgdG8gVFJVRSBvciBGQUxTRSBkZXBlbmRpbmcgb24geW91ciBhbnN3ZXIuDQoNCkEgMC4xIHBvc3NpYmlsaXR5IHRoYXQgdGhlIHJlc3VsdCBpcyBqdXN0IGJ5IGNoYW5jZS4NCg0KYGBge3J9DQojIHVwZGF0ZSByZWplY3RfaHlwb3RoZXNpcyBoZXJlOg0KcmVqZWN0X2h5cG90aGVzaXMgPC0gRkFMU0UNCnJlamVjdF9oeXBvdGhlc2lzDQpgYGANCg0KIyA5Lk9uZSBTYW1wbGUgVC1UZXN0DQoNCkNvbnNpZGVyIHRoZSBmaWN0aW9uYWwgYnVzaW5lc3MgQnV5UGllLCB3aGljaCBzZW5kcyBpbmdyZWRpZW50cyBmb3IgcGllcyB0byB5b3VyIGhvdXNlaG9sZCBzbyB0aGF0IHlvdSBjYW4gbWFrZSB0aGVtIGZyb20gc2NyYXRjaC4gU3VwcG9zZSB0aGF0IGEgcHJvZHVjdCBtYW5hZ2VyIGh5cG90aGVzaXplcyB0aGUgYXZlcmFnZSBhZ2Ugb2YgdmlzaXRvcnMgdG8gQnV5UGllLmNvbSBpcyAzMC4gSW4gdGhlIHBhc3QgaG91ciwgdGhlIHdlYnNpdGUgaGFkIDEwMCB2aXNpdG9ycyBhbmQgdGhlIGF2ZXJhZ2UgYWdlIHdhcyAzMS4gQXJlIHRoZSB2aXNpdG9ycyBvbGRlciB0aGFuIGV4cGVjdGVkPyBPciBpcyB0aGlzIGp1c3QgdGhlIHJlc3VsdCBvZiBjaGFuY2UgKHNhbXBsaW5nIGVycm9yKSBhbmQgYSBzbWFsbCBzYW1wbGUgc2l6ZT8NCg0KWW91IGNhbiB0ZXN0IHRoaXMgdXNpbmcgYSBPbmUgU2FtcGxlIFQtVGVzdC4gQSBPbmUgU2FtcGxlIFQtVGVzdCBjb21wYXJlcyBhIHNhbXBsZSBtZWFuIHRvIGEgaHlwb3RoZXRpY2FsIHBvcHVsYXRpb24gbWVhbi4gSXQgYW5zd2VycyB0aGUgcXVlc3Rpb24g4oCcV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgc2FtcGxlIGNhbWUgZnJvbSBhIGRpc3RyaWJ1dGlvbiB3aXRoIHRoZSBkZXNpcmVkIG1lYW4/4oCdDQoNClRoZSBmaXJzdCBzdGVwIGlzIGZvcm11bGF0aW5nIGEgbnVsbCBoeXBvdGhlc2lzLCB3aGljaCBhZ2FpbiBpcyB0aGUgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcG9wdWxhdGlvbnMgeW91IGFyZSBjb21wYXJpbmcuIFRoZSBzZWNvbmQgcG9wdWxhdGlvbiBpbiBhIE9uZSBTYW1wbGUgVC1UZXN0IGlzIHRoZSBoeXBvdGhldGljYWwgcG9wdWxhdGlvbiB5b3UgY2hvb3NlLiBUaGUgbnVsbCBoeXBvdGhlc2lzIHRoYXQgdGhpcyB0ZXN0IGV4YW1pbmVzIGNhbiBiZSBwaHJhc2VkIGFzIGZvbGxvd3M6ICJUaGUgc2V0IG9mIHNhbXBsZXMgYmVsb25ncyB0byBhIHBvcHVsYXRpb24gd2l0aCB0aGUgdGFyZ2V0IG1lYW4iLg0KDQpPbmUgcmVzdWx0IG9mIGEgT25lIFNhbXBsZSBULVRlc3Qgd2lsbCBiZSBhIHAtdmFsdWUsIHdoaWNoIHRlbGxzIHlvdSB3aGV0aGVyIG9yIG5vdCB5b3UgY2FuIHJlamVjdCB0aGlzIG51bGwgaHlwb3RoZXNpcy4gSWYgdGhlIHAtdmFsdWUgeW91IHJlY2VpdmUgaXMgbGVzcyB0aGFuIHlvdXIgc2lnbmlmaWNhbmNlIGxldmVsLCBub3JtYWxseSAwLjA1LCB5b3UgY2FuIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIGFuZCBzdGF0ZSB0aGF0IHRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZS4NCg0KUiBoYXMgYSBmdW5jdGlvbiBjYWxsZWQgdC50ZXN0KCkgaW4gdGhlIHN0YXRzIHBhY2thZ2Ugd2hpY2ggY2FuIHBlcmZvcm0gYSBPbmUgU2FtcGxlIFQtVGVzdCBmb3IgeW91Lg0KDQp0LnRlc3QoKSByZXF1aXJlcyB0d28gYXJndW1lbnRzLCBhIGRpc3RyaWJ1dGlvbiBvZiB2YWx1ZXMgYW5kIGFuIGV4cGVjdGVkIG1lYW46DQoNCmBgYHtyfQ0KcmVzdWx0cyA8LSB0LnRlc3Qoc2FtcGxlX2Rpc3RyaWJ1dGlvbiwgbXUgPSBleHBlY3RlZF9tZWFuKQ0KYGBgDQoNCjEuc2FtcGxlX2Rpc3RyaWJ1dGlvbiBpcyB0aGUgc2FtcGxlIG9mIHZhbHVlcyB0aGF0IHdlcmUgY29sbGVjdGVkDQoNCjIubXUgaXMgYW4gYXJndW1lbnQgaW5kaWNhdGluZyB0aGUgZGVzaXJlZCBtZWFuIG9mIHRoZSBoeXBvdGhldGljYWwgcG9wdWxhdGlvbg0KDQozLmV4cGVjdGVkX21lYW4gaXMgdGhlIHZhbHVlIG9mIHRoZSBkZXNpcmVkIG1lYW4NCg0KdC50ZXN0KCkgd2lsbCByZXR1cm4sIGFtb25nIG90aGVyIGluZm9ybWF0aW9uIHdlIHdpbGwgbm90IGNvdmVyIGhlcmUsIGEgcC12YWx1ZSDigJQgdGhpcyB0ZWxscyB5b3UgaG93IGNvbmZpZGVudCB5b3UgY2FuIGJlIHRoYXQgdGhlIHNhbXBsZSBvZiB2YWx1ZXMgY2FtZSBmcm9tIGEgZGlzdHJpYnV0aW9uIHdpdGggdGhlIHNwZWNpZmllZCBtZWFuLg0KDQpQLXZhbHVlcyBnaXZlIHlvdSBhbiBpZGVhIG9mIGhvdyBjb25maWRlbnQgeW91IGNhbiBiZSBpbiBhIHJlc3VsdC4gSnVzdCBiZWNhdXNlIHlvdSBkb27igJl0IGhhdmUgZW5vdWdoIGRhdGEgdG8gZGV0ZWN0IGEgZGlmZmVyZW5jZSBkb2VzbuKAmXQgbWVhbiB0aGF0IHRoZXJlIGlzbuKAmXQgb25lLiBHZW5lcmFsbHksIHRoZSBtb3JlIHNhbXBsZXMgeW91IGhhdmUsIHRoZSBzbWFsbGVyIGEgZGlmZmVyZW5jZSB5b3UgY2FuIGRldGVjdC4NCg0KIyMgSW5zdHJ1Y3Rpb25zDQoNCjEuV2UgaGF2ZSBwcm92aWRlZCBhIHNtYWxsIGRhdGFzZXQgY2FsbGVkIGFnZXMsIHJlcHJlc2VudGluZyB0aGUgYWdlcyBvZiBjdXN0b21lcnMgdG8gQnV5UGllLmNvbSBpbiB0aGUgcGFzdCBob3VyLCBpbiBub3RlYm9vay5SbWQuDQoNCkV2ZW4gd2l0aCBhIHNtYWxsIGRhdGFzZXQgbGlrZSB0aGlzLCBpdCBpcyBoYXJkIHRvIG1ha2UganVkZ21lbnRzIGZyb20ganVzdCBsb29raW5nIGF0IHRoZSBudW1iZXJzLg0KDQpUbyB1bmRlcnN0YW5kIHRoZSBkYXRhIGJldHRlciwgbGV04oCZcyBsb29rIGF0IHRoZSBtZWFuLiBDYWxjdWxhdGUgdGhlIG1lYW4gb2YgYWdlcywgYW5kIHN0b3JlIHRoZSByZXN1bHQgaW4gYSB2YXJpYWJsZSBjYWxsZWQgYWdlc19tZWFuLiBWaWV3IGFnZXNfbWVhbi4NCg0KDQpgYGB7ciBtZXNzYWdlID0gRkFMU0V9DQojIGxvYWQgYW5kIHZpZXcgZGF0YQ0KYWdlcyA8LSBjKDMyLCAzNCwgMjksIDI5LCAyMiwgMzksIDM4LCAzNywgMzgsIDM2LCAzMCwgMjYsIDIyLCAyMikNCmFnZXMNCmBgYA0KIA0KYGBge3J9DQojIGNhbGN1bGF0ZSBhZ2VzX21lYW4gaGVyZToNCmFnZXNfbWVhbiA8LSBtZWFuKGFnZXMpDQphZ2VzX21lYW4NCmBgYA0KMi5Vc2UgdGhlIHQudGVzdCgpIGZ1bmN0aW9uIHdpdGggYWdlcyB0byBzZWUgd2hhdCBwLXZhbHVlIHRoZSBleHBlcmltZW50IHJldHVybnMgZm9yIHRoaXMgZGlzdHJpYnV0aW9uLCB3aGVyZSB3ZSBleHBlY3QgdGhlIG1lYW4gdG8gYmUgMzAuDQoNClN0b3JlIHRoZSByZXN1bHRzIG9mIHRoZSB0ZXN0IGluIGEgdmFyaWFibGUgY2FsbGVkIHJlc3VsdHMuDQoNCkRvZXMgdGhlIHAtdmFsdWUgeW91IGdvdCB3aXRoIHRoZSBPbmUgU2FtcGxlIFQtVGVzdCBtYWtlIHNlbnNlLCBrbm93aW5nIHRoZSBtZWFuIG9mIGFnZXM/DQoNCmBgYHtyfQ0KIyBwZXJmb3JtIHQtdGVzdCBoZXJlOg0KcmVzdWx0cyA8LSB0LnRlc3QoYWdlcywgbXUgPSAzMCkNCnJlc3VsdHMNCmBgYA0KDQpJZiB0aGUgdHJ1ZSBtZWFuIGlzIHJlYWxseSAzMCAobnVsbCBoeXBvdGhlc2lzIGlzIHRydWUpLCB0aGVuIHRoZXJlIGlzIGFib3V0IGEgNTYlIGNoYW5jZSB5b3XigJlkIHNlZSBhIHNhbXBsZSBtZWFuIGFzIGZhciBmcm9tIDMwIGFzIDMxIChvciBldmVuIGZhcnRoZXIpIGp1c3QgYnkgY2hhbmNlLg0KDQpJdCBtZWFucyB0aGlzIG9ic2VydmVkIGRpZmZlcmVuY2UgKG1lYW4gb2YgMzEgaW5zdGVhZCBvZiAzMCkgaXMgY29tcGxldGVseSBwbGF1c2libGUgYXMgcmFuZG9tIHNhbXBsaW5nIGVycm9yLg0KDQpTbyB5b3UgZmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4NCg0KVGhlIGRhdGEgaXMgY29uc2lzdGVudCB3aXRoIHRoZSBwb3B1bGF0aW9uIG1lYW4gYmVpbmcgMzAuDQoNCiMgMTAuVHdvIFNhbXBsZSBULVRlc3QNCg0KU3VwcG9zZSB0aGF0IGxhc3Qgd2VlaywgdGhlIGF2ZXJhZ2UgYW1vdW50IG9mIHRpbWUgc3BlbnQgcGVyIHZpc2l0b3IgdG8gYSB3ZWJzaXRlIHdhcyAyNSBtaW51dGVzLiBUaGlzIHdlZWssIHRoZSBhdmVyYWdlIGFtb3VudCBvZiB0aW1lIHNwZW50IHBlciB2aXNpdG9yIHRvIGEgd2Vic2l0ZSB3YXMgMjkgbWludXRlcy4gRGlkIHRoZSBhdmVyYWdlIHRpbWUgc3BlbnQgcGVyIHZpc2l0b3IgY2hhbmdlIChpLmUuIHdhcyB0aGVyZSBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgYnVtcCBpbiB1c2VyIHRpbWUgb24gdGhlIHNpdGUpPyBPciBpcyB0aGlzIGp1c3QgcGFydCBvZiBuYXR1cmFsIGZsdWN0dWF0aW9ucz8NCg0KT25lIHdheSBvZiB0ZXN0aW5nIHdoZXRoZXIgdGhpcyBkaWZmZXJlbmNlIGlzIHNpZ25pZmljYW50IGlzIGJ5IHVzaW5nIGEgVHdvIFNhbXBsZSBULVRlc3QuIEEgVHdvIFNhbXBsZSBULVRlc3QgY29tcGFyZXMgdHdvIHNldHMgb2YgZGF0YSwgd2hpY2ggYXJlIGJvdGggYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZC4NCg0KVGhlIG51bGwgaHlwb3RoZXNpcywgaW4gdGhpcyBjYXNlLCBpcyB0aGF0IHRoZSB0d28gZGlzdHJpYnV0aW9ucyBoYXZlIHRoZSBzYW1lIG1lYW4uDQoNCllvdSBjYW4gdXNlIFLigJlzIHQudGVzdCgpIGZ1bmN0aW9uIHRvIHBlcmZvcm0gYSBUd28gU2FtcGxlIFQtVGVzdCwgYXMgc2hvd24gYmVsb3c6DQoNCmBgYHtyfQ0KcmVzdWx0cyA8LSB0LnRlc3QoZGlzdHJpYnV0aW9uXzEsIGRpc3RyaWJ1dGlvbl8yKQ0KYGBgDQoNCldoZW4gcGVyZm9ybWluZyBhIFR3byBTYW1wbGUgVC1UZXN0LCB0LnRlc3QoKSB0YWtlcyB0d28gZGlzdHJpYnV0aW9ucyBhcyBhcmd1bWVudHMgYW5kIHJldHVybnMsIGFtb25nIG90aGVyIGluZm9ybWF0aW9uLCBhIHAtdmFsdWUuIA0KDQpSZW1lbWJlciwgdGhlIHAtdmFsdWUgbGV04oCZcyB5b3Uga25vdyB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aGUgZGlmZmVyZW5jZSBpbiB0aGUgbWVhbnMgaGFwcGVuZWQgYnkgY2hhbmNlIChzYW1wbGluZyBlcnJvcikuDQoNCg0KIyMgSW5zdHJ1Y3Rpb25zDQoNCjEuV2XigJl2ZSBjcmVhdGVkIHR3byBkaXN0cmlidXRpb25zIHJlcHJlc2VudGluZyB0aGUgdGltZSBzcGVudCBwZXIgdmlzaXRvciB0byBCdXlQaWUuY29tIGxhc3Qgd2Vlaywgd2Vla18xLCBhbmQgdGhlIHRpbWUgc3BlbnQgcGVyIHZpc2l0b3IgdG8gQnV5UGllLmNvbSB0aGlzIHdlZWssIHdlZWtfMi4NCg0KRmluZCB0aGUgbWVhbnMgb2YgdGhlc2UgdHdvIGRpc3RyaWJ1dGlvbnMuIFN0b3JlIHRoZW0gaW4gd2Vla18xX21lYW4gYW5kIHdlZWtfMl9tZWFuLiBWaWV3IGJvdGggbWVhbnMuDQoNCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRX0NCiMgbG9hZCBkYXRhDQp3ZWVrXzEgPC0gYygyMy45MDUwNywgMjYuNjc2MzIsIDI3LjI3NDM0LCAyNC4yNTc1NywgMzIuNDA0MjMsIDM5LjU2OTE5LCAyMy4wNzAxMCwgMjkuODIwNjgsIDI3LjU5NDM0LCAyOC4wNTY0MCwgMjcuMDY3NTcsIDMwLjQxMTkzLCAyNS43MTM1OSwgMjQuOTQyOTUsIDI4LjIzMTI0LCAyNC45NTMzOCwgMTguNTEyMzIsIDI3LjQ2MjM1LCAyOC4zODAxNywgMTMuOTEyMDYsIDI5LjAyNjE2LCAyNi45MDc0NywgMjIuODY3NzcsIDI0Ljg5MzgzLCAyNS45Njk0OCwgMjYuODY4NzAsIDIwLjcyNjc2LCAyNy4zNTk4OCwgMjAuNjg0MDksIDIxLjE5ODQ2LCAxNi4yNTgwMSwgMjMuOTI1MTgsIDI0LjQ3OTIzLCAyOS40NzA1MSwgMjcuMjg0MjUsIDI2LjkzMzM5LCAyOC42MTAyNywgMTguODgzNzcsIDMzLjY1NDY5LCAyNS42OTQ3MCwgMjAuOTgyOTEsIDIyLjY5NzAwLCAyOC42MDI3OSwgMjEuMzYwMDAsIDMwLjc3Njg1LCAyMC44MzQxNiwgMjMuNzkzNjcsIDE5Ljc1NTY3LCAyOS41NDQyMSwgMjAuMTQzMzEpDQp3ZWVrXzENCndlZWtfMiA8LSBjKCAxOC42MzQzMiwgMzEuMjg3ODgsIDM0Ljk2Nzk4LCAyMS44MTY3OCwgMjguMjE2MjAsIDM5LjM5MzE0LCAzNS41MjIyMywgMjcuNTQyMjIsIDMzLjY0Mzk1LCAyNS4zMTY3NCwgMjguODEzOTIsIDMwLjczNTgwLCAyNi4zNzI0MiwgMjYuMDk0NTYsIDI2LjM0MDczLCAxOS40MjE5NiwgMzIuNTg3OTgsIDI0Ljg0MDAyLCAyOC45MzM0OCwgMjAuNDM2NjgsIDIyLjcyNDk2LCAzMi4zMTcyOCwgMzUuMzg0MzEsIDI5LjY2NzEwLCAyNC41MzUxMywgMzAuOTE0MDYsIDE5LjU2MTE4LCAyNC45MDgxNywgMzAuMTMxNjQsIDMxLjQ3NDY2LCAyNy43NzY4NCwgMTYuNTEzMDcsIDM1LjA3NzAyLCAzMS43NDgxOCwgMzYuMzYwNTMsIDI3LjcwNTAxLCAyOS40OTg3MCwgMjcuNjU1NzUsIDM3LjE4NTA0LCAyNS4xNjA1NSwgMjkuMjY1NTQsIDM4LjIyMTYzLCAyOC45MjEwMiwgMjQuODIxNTQsIDM4LjMwMTU1LCAzNC43NjAyMSwgMjIuMjY4NjksIDI4LjgyNTk0LCAzMi4wMDk3NSwgMzYuNDY0MzgpDQp3ZWVrXzINCmBgYA0KDQpgYGB7cn0NCiMgY2FsY3VsYXRlIHdlZWtfMV9tZWFuIGFuZCB3ZWVrXzJfbWVhbiBoZXJlOg0Kd2Vla18xX21lYW4gPC0gbWVhbih3ZWVrXzEpDQp3ZWVrXzFfbWVhbg0Kd2Vla18yX21lYW4gPC0gbWVhbih3ZWVrXzIpDQp3ZWVrXzJfbWVhbg0KYGBgDQoNCjIuRmluZCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiB0aGVzZSB0d28gZGlzdHJpYnV0aW9ucy4gU3RvcmUgdGhlbSBpbiB3ZWVrXzFfc2QgYW5kIHdlZWtfMl9zZC4gVmlldyBib3RoIHN0YW5kYXJkIGRldmlhdGlvbnMuDQoNCmBgYHtyfQ0KIyBjYWxjdWxhdGUgd2Vla18xX3NkIGFuZCB3ZWVrXzJfc2QgaGVyZToNCndlZWtfMV9zZCA8LSBzZCh3ZWVrXzEpDQp3ZWVrXzFfc2QNCndlZWtfMl9zZCA8LSBzZCh3ZWVrXzIpDQp3ZWVrXzJfc2QNCmBgYA0KDQozLlJ1biBhIFR3byBTYW1wbGUgVC1UZXN0IHVzaW5nIHRoZSB0LnRlc3QoKSBmdW5jdGlvbi4NCg0KU2F2ZSB0aGUgcmVzdWx0cyB0byBhIHZhcmlhYmxlIGNhbGxlZCByZXN1bHRzIGFuZCB2aWV3IGl0LiBEb2VzIHRoZSBwLXZhbHVlIG1ha2Ugc2Vuc2UsIGtub3dpbmcgd2hhdCB5b3Uga25vdyBhYm91dCB0aGVzZSBkYXRhc2V0cz8NCg0KYGBge3J9DQojIHJ1biB0d28gc2FtcGxlIHQtdGVzdCBoZXJlOg0KcmVzdWx0czwtIHQudGVzdCh3ZWVrXzEsIHdlZWtfMikNCnJlc3VsdHMNCmBgYA0KDQpBc3N1bWluZyB0aGVyZSBpcyBubyByZWFsIGRpZmZlcmVuY2UgaW4gYXZlcmFnZSB0aW1lIHNwZW50IGJldHdlZW4gdGhlIHR3byB3ZWVrcyAobnVsbCBoeXBvdGhlc2lzKSwgdGhlIHByb2JhYmlsaXR5IG9mIHNlZWluZyBhIGRpZmZlcmVuY2UgYXMgbGFyZ2UgYXMgfjMuNTcgbWludXRlcyAob3IgbW9yZSBleHRyZW1lKSBqdXN0IGJ5IHJhbmRvbSBzYW1wbGluZyBpcyBhYm91dCAwLjA3JS4NCg0KVGhlcmUgaXMgc3Ryb25nIGV2aWRlbmNlIHRoYXQgdGhlIGF2ZXJhZ2UgdGltZSBwZXIgdmlzaXRvciBjaGFuZ2VkIGJldHdlZW4gd2Vla18xIGFuZCB3ZWVrXzIuDQoNCg0KIyAxMS5EYW5nZXJzIG9mIE11bHRpcGxlIFQtVGVzdHMNCg0KU3VwcG9zZSB0aGF0IHlvdSBvd24gYSBjaGFpbiBvZiBzdG9yZXMgdGhhdCBzZWxsIGFudHMsIGNhbGxlZCBWZXJ5QW50cy4gVGhlcmUgYXJlIHRocmVlIGRpZmZlcmVudCBsb2NhdGlvbnM6IEEsIEIsIGFuZCBDLiBZb3Ugd2FudCB0byBrbm93IGlmIHRoZSBhdmVyYWdlIGFudCBzYWxlcyBvdmVyIHRoZSBwYXN0IHllYXIgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGJldHdlZW4gdGhlIHRocmVlIGxvY2F0aW9ucy4NCg0KQXQgZmlyc3QsIGl0IHNlZW1zIHRoYXQgeW91IGNvdWxkIHBlcmZvcm0gVC10ZXN0cyBiZXR3ZWVuIGVhY2ggcGFpciBvZiBzdG9yZXMuDQoNCllvdSBrbm93IHRoYXQgdGhlIHAtdmFsdWUgaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQgeW91IGluY29ycmVjdGx5IHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzIG9uIGVhY2ggdC10ZXN0LiBUaGUgbW9yZSB0LXRlc3RzIHlvdSBwZXJmb3JtLCB0aGUgbW9yZSBsaWtlbHkgdGhhdCB5b3UgYXJlIHRvIGdldCBhIGZhbHNlIHBvc2l0aXZlLCBhIFR5cGUgSSBlcnJvci4NCg0KRm9yIGEgcC12YWx1ZSBvZiAwLjA1LCBpZiB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUsIHRoZW4gdGhlIHByb2JhYmlsaXR5IG9mIG9idGFpbmluZyBhIHNpZ25pZmljYW50IHJlc3VsdCBpcyAxIOKAkyAwLjA1ID0gMC45NS4gV2hlbiB5b3UgcnVuIGFub3RoZXIgdC10ZXN0LCB0aGUgcHJvYmFiaWxpdHkgb2Ygc3RpbGwgZ2V0dGluZyBhIGNvcnJlY3QgcmVzdWx0IGlzIDAuOTUgKiAwLjk1LCBvciAwLjkwMjUuIFRoYXQgbWVhbnMgeW91ciBwcm9iYWJpbGl0eSBvZiBtYWtpbmcgYW4gZXJyb3IgaXMgbm93IGNsb3NlIHRvIDEwJSEgVGhpcyBlcnJvciBwcm9iYWJpbGl0eSBvbmx5IGdldHMgYmlnZ2VyIHdpdGggdGhlIG1vcmUgdC10ZXN0cyB5b3UgZG8uDQoNCiMjIEluc3RydWN0aW9ucw0KDQoxLldlIGhhdmUgY3JlYXRlZCBzYW1wbGVzIHN0b3JlX2EsIHN0b3JlX2IsIGFuZCBzdG9yZV9jLCByZXByZXNlbnRpbmcgdGhlIHNhbGVzIGF0IFZlcnlBbnRzIGF0IGxvY2F0aW9ucyBBLCBCLCBhbmQgQywgcmVzcGVjdGl2ZWx5LiBXZSB3YW50IHRvIHNlZSBpZiB0aGVyZeKAmXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHNhbGVzIGJldHdlZW4gdGhlIHRocmVlIGxvY2F0aW9ucy4NCg0KRXhwbG9yZSBkYXRhc2V0cyBzdG9yZV9hLCBzdG9yZV9iLCBhbmQgc3RvcmVfYyBieSBmaW5kaW5nIGFuZCB2aWV3aW5nIHRoZSBtZWFucyBhbmQgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiBlYWNoIG9uZS4gU3RvcmUgdGhlIG1lYW5zIGluIHZhcmlhYmxlcyBjYWxsZWQgc3RvcmVfYV9tZWFuLCBzdG9yZV9iX21lYW4sIGFuZCBzdG9yZV9jX21lYW4uIFN0b3JlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb25zIGluIHZhcmlhYmxlcyBjYWxsZWQgc3RvcmVfYV9zZCwgc3RvcmVfYl9zZCwgYW5kIHN0b3JlX2Nfc2QuDQoNCmBgYHtyIG1lc3NhZ2UgPSBGQUxTRX0NCiMgbG9hZCBkYXRhDQpsb2FkKCJzdG9yZV9hLlJkYSIpDQpsb2FkKCJzdG9yZV9iLlJkYSIpDQpsb2FkKCJzdG9yZV9jLlJkYSIpDQpgYGANCg0KYGBge3J9DQojIGNhbGN1bGF0ZSBtZWFucyBoZXJlOg0Kc3RvcmVfYV9tZWFuIDwtIG1lYW4oc3RvcmVfYSkNCnN0b3JlX2FfbWVhbg0Kc3RvcmVfYl9tZWFuIDwtIG1lYW4oc3RvcmVfYikNCnN0b3JlX2JfbWVhbg0Kc3RvcmVfY19tZWFuIDwtIG1lYW4oc3RvcmVfYykNCnN0b3JlX2NfbWVhbg0KYGBgDQoNClsxXSA1OC4zNDk2NA0KDQpbMV0gNjUuNjI2MjkNCg0KWzFdIDYyLjM2MTE3DQoNCmBgYHtyfQ0KIyBjYWxjdWxhdGUgc3RhbmRhcmQgZGV2aWF0aW9ucyBoZXJlOg0Kc3RvcmVfYV9zZCA8LSBzZChzdG9yZV9hKQ0Kc3RvcmVfYV9zZA0Kc3RvcmVfYl9zZCA8LSBzZChzdG9yZV9iKQ0Kc3RvcmVfYl9zZA0Kc3RvcmVfY19zZCA8LSBzZChzdG9yZV9jKQ0Kc3RvcmVfY19zZA0KYGBgDQoNClsxXSAxNC44MDMxMw0KDQpbMV0gMTQuNzk1OTcNCg0KWzFdIDE1LjE0MzAyDQoNCjIuUGVyZm9ybSBhIFR3byBTYW1wbGUgVC10ZXN0IGJldHdlZW4gZWFjaCBwYWlyIG9mIGxvY2F0aW9uIGRhdGEuDQoNClN0b3JlIHRoZSByZXN1bHRzIG9mIHRoZSB0ZXN0cyBpbiB2YXJpYWJsZXMgY2FsbGVkIGFfYl9yZXN1bHRzLCBhX2NfcmVzdWx0cywgYW5kIGJfY19yZXN1bHRzLiBWaWV3IHRoZSByZXN1bHRzIGZvciBlYWNoIHRlc3QuDQoNCmBgYHtyfQ0KIyBwZXJmb3JtIHR3byBzYW1wbGUgdC10ZXN0IGhlcmU6DQphX2JfcmVzdWx0cyA8LSB0LnRlc3Qoc3RvcmVfYSwgc3RvcmVfYikNCmFfYl9yZXN1bHRzDQphX2NfcmVzdWx0cyA8LSB0LnRlc3Qoc3RvcmVfYSwgc3RvcmVfYykNCmFfY19yZXN1bHRzDQpiX2NfcmVzdWx0cyA8LSB0LnRlc3Qoc3RvcmVfYiwgc3RvcmVfYykNCmJfY19yZXN1bHRzDQpgYGANCg0KICBXZWxjaCBUd28gU2FtcGxlIHQtdGVzdA0KDQpkYXRhOiAgc3RvcmVfYSBhbmQgc3RvcmVfYg0KdCA9IC00LjI1ODEsIGRmID0gMjk4LCBwLXZhbHVlID0gMi43NjdlLTA1DQphbHRlcm5hdGl2ZSBoeXBvdGhlc2lzOiB0cnVlIGRpZmZlcmVuY2UgaW4gbWVhbnMgaXMgbm90IGVxdWFsIHRvIDANCjk1IHBlcmNlbnQgY29uZmlkZW5jZSBpbnRlcnZhbDoNCiAtMTAuNjM5NzAxICAtMy45MTM2MDENCnNhbXBsZSBlc3RpbWF0ZXM6DQptZWFuIG9mIHggbWVhbiBvZiB5IA0KIDU4LjM0OTY0ICA2NS42MjYyOSANCiANCiBXZWxjaCBUd28gU2FtcGxlIHQtdGVzdA0KDQpkYXRhOiAgc3RvcmVfYSBhbmQgc3RvcmVfYw0KdCA9IC0yLjMyMDEsIGRmID0gMjk3Ljg1LCBwLXZhbHVlID0gMC4wMjEwMQ0KYWx0ZXJuYXRpdmUgaHlwb3RoZXNpczogdHJ1ZSBkaWZmZXJlbmNlIGluIG1lYW5zIGlzIG5vdCBlcXVhbCB0byAwDQo5NSBwZXJjZW50IGNvbmZpZGVuY2UgaW50ZXJ2YWw6DQogLTcuNDE0MjQ1NiAtMC42MDg4Mjg2DQpzYW1wbGUgZXN0aW1hdGVzOg0KbWVhbiBvZiB4IG1lYW4gb2YgeSANCiA1OC4zNDk2NCAgNjIuMzYxMTcgDQogDQogDQoNCiAgV2VsY2ggVHdvIFNhbXBsZSB0LXRlc3QNCg0KZGF0YTogIHN0b3JlX2IgYW5kIHN0b3JlX2MNCnQgPSAxLjg4ODgsIGRmID0gMjk3Ljg0LCBwLXZhbHVlID0gMC4wNTk4OQ0KYWx0ZXJuYXRpdmUgaHlwb3RoZXNpczogdHJ1ZSBkaWZmZXJlbmNlIGluIG1lYW5zIGlzIG5vdCBlcXVhbCB0byAwDQo5NSBwZXJjZW50IGNvbmZpZGVuY2UgaW50ZXJ2YWw6DQogLTAuMTM2NzkwMyAgNi42NjcwMTgyDQpzYW1wbGUgZXN0aW1hdGVzOg0KbWVhbiBvZiB4IG1lYW4gb2YgeSANCiA2NS42MjYyOSAgNjIuMzYxMTcgDQogDQogDQozLlN0b3JlIHRoZSBwcm9iYWJpbGl0eSBvZiBlcnJvciBmb3IgcnVubmluZyB0aHJlZSBULVRlc3RzIGluIGEgdmFyaWFibGUgY2FsbGVkIGVycm9yX3Byb2IuIFZpZXcgZXJyb3JfcHJvYi4NCg0KYGBge3J9DQojIGNhbGN1bGF0ZSBlcnJvcl9wcm9iIGhlcmU6DQplcnJvcl9wcm9iIDwtICgxLSgwLjk1KiozKSkNCmVycm9yX3Byb2INCmBgYA0KWzFdIDAuMTQyNjI1DQoNCg0KIyAxMi5BTk9WQQ0KDQpJbiB0aGUgbGFzdCBleGVyY2lzZSwgeW91IHNhdyB0aGF0IHRoZSBwcm9iYWJpbGl0eSBvZiBtYWtpbmcgYSBUeXBlIEkgZXJyb3IgZ290IGRhbmdlcm91c2x5IGhpZ2ggYXMgeW91IHBlcmZvcm1lZCBtb3JlIHQtdGVzdHMuDQoNCldoZW4gY29tcGFyaW5nIG1vcmUgdGhhbiB0d28gbnVtZXJpY2FsIGRhdGFzZXRzLCB0aGUgYmVzdCB3YXkgdG8gcHJlc2VydmUgYSBUeXBlIEkgZXJyb3IgcHJvYmFiaWxpdHkgb2YgMC4wNSBpcyB0byB1c2UgQU5PVkEuIEFOT1ZBIChBbmFseXNpcyBvZiBWYXJpYW5jZSkgdGVzdHMgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IGFsbCBvZiB0aGUgZGF0YXNldHMgeW91IGFyZSBjb25zaWRlcmluZyBoYXZlIHRoZSBzYW1lIG1lYW4uIElmIHlvdSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB3aXRoIEFOT1ZBLCB5b3XigJlyZSBzYXlpbmcgdGhhdCBhdCBsZWFzdCBvbmUgb2YgdGhlIHNldHMgaGFzIGEgZGlmZmVyZW50IG1lYW47IGhvd2V2ZXIsIGl0IGRvZXMgbm90IHRlbGwgeW91IHdoaWNoIGRhdGFzZXRzIGFyZSBkaWZmZXJlbnQuDQoNCllvdSBjYW4gdXNlIHRoZSBzdGF0cyBwYWNrYWdlIGZ1bmN0aW9uIGFvdigpIHRvIHBlcmZvcm0gQU5PVkEgb24gbXVsdGlwbGUgZGF0YXNldHMuIGFvdigpIHRha2VzIHRoZSBkaWZmZXJlbnQgZGF0YXNldHMgY29tYmluZWQgaW50byBhIGRhdGEgZnJhbWUgYXMgYW4gYXJndW1lbnQuIEZvciBleGFtcGxlLCBpZiB5b3Ugd2VyZSBjb21wYXJpbmcgc2NvcmVzIG9uIGEgdmlkZW8gZ2FtZSBiZXR3ZWVuIG1hdGggbWFqb3JzLCB3cml0aW5nIG1ham9ycywgYW5kIHBzeWNob2xvZ3kgbWFqb3JzLCB5b3UgY291bGQgZm9ybWF0IHRoZSBkYXRhIGluIGEgZGF0YSBmcmFtZSBkZl9zY29yZXMgYXMgZm9sbG93czoNCg0KZ3JvdXAJICAgICAgICAgICAgICAgICAgc2NvcmUNCg0KbWF0aCBtYWpvcgkgICAgICAgICAgICA4OA0KDQptYXRoIG1ham9yCSAgICAgICAgICAgIDgxDQoNCndyaXRpbmcgbWFqb3IJICAgICAgICAgIDkyDQoNCndyaXRpbmcgbWFqb3IJICAgICAgICAgIDgwDQoNCnBzeWNob2xvZ3kgbWFqb3IJICAgICAgOTQNCg0KcHN5Y2hvbG9neSBtYWpvcgkgICAgICA4Mw0KDQpZb3UgY2FuIHRoZW4gcnVuIGFuIEFOT1ZBIHRlc3Qgd2l0aCB0aGlzIGxpbmU6DQoNCmBgYHtyfQ0KcmVzdWx0cyA8LSBhb3Yoc2NvcmUgfiBncm91cCwgZGF0YSA9IGRmX3Njb3JlcykNCmBgYA0KDQpOb3RlOiBzY29yZSB+IGdyb3VwIGluZGljYXRlcyB0aGUgcmVsYXRpb25zaGlwIHlvdSB3YW50IHRvIGFuYWx5emUgKGkuZS4gaG93IGVhY2ggZ3JvdXAsIG9yIG1ham9yLCByZWxhdGVzIHRvIHNjb3JlIG9uIHRoZSB2aWRlbyBnYW1lKQ0KDQpUbyByZXRyaWV2ZSB0aGUgcC12YWx1ZSBmcm9tIHRoZSByZXN1bHRzIG9mIGNhbGxpbmcgYW92KCksIHVzZSB0aGUgc3VtbWFyeSgpIGZ1bmN0aW9uOg0KDQpgYGB7cn0NCnN1bW1hcnkocmVzdWx0cykNCmBgYA0KDQpUaGUgbnVsbCBoeXBvdGhlc2lzLCBpbiB0aGlzIGNhc2UsIGlzIHRoYXQgYWxsIHRocmVlIHBvcHVsYXRpb25zIGhhdmUgdGhlIHNhbWUgbWVhbiBzY29yZSBvbiB0aGlzIHZpZGVvIGdhbWUuIElmIHlvdSByZWplY3QgdGhpcyBudWxsIGh5cG90aGVzaXMgKGlmIHRoZSBwLXZhbHVlIGlzIGxlc3MgdGhhbiAwLjA1KSwgeW91IGNhbiBzYXkgeW91IGFyZSByZWFzb25hYmx5IGNvbmZpZGVudCB0aGF0IGEgcGFpciBvZiBkYXRhc2V0cyBpcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudC4gQWZ0ZXIgdXNpbmcgb25seSBBTk9WQSwgaG93ZXZlciwgeW91IGNhbuKAmXQgbWFrZSBhbnkgY29uY2x1c2lvbnMgb24gd2hpY2ggdHdvIHBvcHVsYXRpb25zIGhhdmUgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlLg0KDQpMZXTigJlzIGxvb2sgYXQgYW4gZXhhbXBsZSBvZiBBTk9WQSBpbiBhY3Rpb24uDQoNCiMjIEluc3RydWN0aW9ucw0KDQpgYGB7cn0NCiMgbG9hZCBsaWJyYXJpZXMNCmxpYnJhcnkodGlkeXIpDQpgYGANCg0KYGBge3IgbWVzc2FnZSA9IEZBTFNFfQ0KIyBsb2FkIGRhdGENCmxvYWQoInN0b3Jlcy5SZGEiKQ0KbG9hZCgic3RvcmVzX25ldy5SZGEiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBpbnNwZWN0IHN0b3JlcyBoZXJlOg0Kc3RvcmVzDQpgYGANCg0KDQpgYGB7ciBIeXBvNSwgb3V0LndpZHRoPSI2MCUifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkM6L1VzZXJzL2t1b2FuL0Rlc2t0b3AvUiBDb2RlL0h5cG81LnBuZyIpDQpgYGANCg0KMi5QZXJmb3JtIGFuIEFOT1ZBIG9uIHRoZSBzdG9yZXMgZGF0YSBhbmQgc2F2ZSB0aGUgdGVzdCByZXN1bHRzIHRvIGEgdmFyaWFibGUgcmVzdWx0cy4gVXNlIHRoZSBzdW1tYXJ5KCkgZnVuY3Rpb24gdG8gdmlldyB0aGUgcC12YWx1ZSBvZiB0aGUgdGVzdC4gRG9lcyB0aGlzIHAtdmFsdWUgbGVhZCB5b3UgdG8gcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXM/DQoNCmBgYHtyfQ0KIyBwZXJmb3JtIGFub3ZhIG9uIHN0b3JlcyBoZXJlOg0KcmVzdWx0cyA8LSBhb3Yoc2FsZXMgfiBzdG9yZSwgZGF0YSA9IHN0b3JlcykNCnN1bW1hcnkocmVzdWx0cykNCmBgYA0KDQogICAgICAgICAgICAgRGYgU3VtIFNxIE1lYW4gU3EgRiB2YWx1ZSAgIFByKD5GKSAgICANCnN0b3JlICAgICAgICAgMiAgIDM5ODUgIDE5OTIuNiAgIDguOTU3IDAuMDAwMTUzICoqKg0KUmVzaWR1YWxzICAgNDQ3ICA5OTQzNyAgIDIyMi41ICAgICAgICAgICAgICAgICAgICAgDQotLS0NClNpZ25pZi4gY29kZXM6ICAwICcqKionIDAuMDAxICcqKicgMC4wMSAnKicgMC4wNSAnLicgMC4xICcgJyAxDQoNCg0KVGhlIGNvbHVtbiBsYWJlbGVkIFByKD5GKSBpcyB0aGUgcC12YWx1ZSBmb3IgdGhlIEYtdGVzdC4NCg0KDQozLkxldOKAmXMgc2F5IHRoZSBzYWxlcyBhdCBsb2NhdGlvbiBCIGhhdmUgc3VkZGVubHkgc29hcmVkIChtYXliZSB0aGVyZeKAmXMgYW4gYW50IGNvbnZlbnRpb24gaGFwcGVuaW5nIG5lYXJieSkuIFRoZSBuZXcgc2FsZXMgZm9yIGxvY2F0aW9uIEIgaGF2ZSBiZWVuIHVwZGF0ZWQgaW4gdGhlIHN0b3Jlc19uZXcgZGF0YSBmcmFtZS4NCg0KUmUtcnVuIHRoZSBBTk9WQSB0ZXN0IG9uIHN0b3Jlc19uZXcgYW5kIHNhdmUgdGhlIHRlc3QgcmVzdWx0cyB0byBhIHZhcmlhYmxlIHJlc3VsdHNfbmV3LiBVc2UgdGhlIHN1bW1hcnkoKSBmdW5jdGlvbiB0byBzZWUgd2hhdCB0aGUgcC12YWx1ZSBpcyBub3cuIERvZXMgdGhpcyBuZXcgdmFsdWUgbWFrZSBzZW5zZT8NCg0KDQpgYGB7cn0NCiMgcGVyZm9ybSBhbm92YSBvbiBzdG9yZXNfbmV3IGhlcmU6DQpyZXN1bHRzX25ldyA8LSBhb3Yoc2FsZXMgfiBzdG9yZSwgZGF0YSA9IHN0b3Jlc19uZXcpDQpzdW1tYXJ5KHJlc3VsdHNfbmV3KQ0KYGBgDQoNCiAgICAgICAgICAgICBEZiBTdW0gU3EgTWVhbiBTcSBGIHZhbHVlIFByKD5GKSAgICANCnN0b3JlICAgICAgICAgMiA3NzU1OTkgIDM4Nzc5OSAgICAxODA1IDwyZS0xNiAqKioNClJlc2lkdWFscyAgIDQ0NyAgOTYwNTggICAgIDIxNSAgICAgICAgICAgICAgICAgICANCi0tLQ0KU2lnbmlmLiBjb2RlczogIDAgJyoqKicgMC4wMDEgJyoqJyAwLjAxICcqJyAwLjA1ICcuJyAwLjEgJyAnIDENCg0KDQpLZXkgdmFsdWU6IFByKD5GKSA9IDwgMmUtMTYNClRoaXMgaXMgc2hvcnRoYW5kIGZvciBhIHAtdmFsdWUgbGVzcyB0aGFuIDAuMDAwMDAwMDAwMDAwMDAwMg0KDQpXYXkgYmVsb3cgYW55IGNvbW1vbiBzaWduaWZpY2FuY2UgbGV2ZWwgKGxpa2UgMC4wNSBvciAwLjAxKQ0KDQpSZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcw0KDQpUaGVyZSBpcyBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBncm91cCBtZWFucyBmb3IgdGhlIGRpZmZlcmVudCBzdG9yZXMNCg0KVGhlIGRpZmZlcmVuY2UgaXMgZXh0cmVtZWx5IHVubGlrZWx5IHRvIGJlIGR1ZSB0byBjaGFuY2UNCg0KVGhlcmXigJlzIG92ZXJ3aGVsbWluZyBldmlkZW5jZSB0aGF0IHRoZSBhdmVyYWdlIHZhbHVlICh3aGF0ZXZlciB5b3UncmUgbWVhc3VyaW5nKSBkaWZmZXJzIHNpZ25pZmljYW50bHkgYW1vbmcgdGhlIHRocmVlIHN0b3Jlcy4NCg0KIyAxMy5Bc3N1bXB0aW9ucyBvZiBOdW1lcmljYWwgSHlwb3RoZXNpcyBUZXN0cw0KDQpCZWZvcmUgeW91IHVzZSBudW1lcmljYWwgaHlwb3RoZXNpcyB0ZXN0cywgeW91IG5lZWQgdG8gYmUgc3VyZSB0aGF0IHRoZSBmb2xsb3dpbmcgdGhpbmdzIGFyZSB0cnVlOg0KDQoxLiBUaGUgc2FtcGxlcyBzaG91bGQgZWFjaCBiZSBub3JtYWxseSBkaXN0cmlidXRlZOKApmlzaA0KRGF0YSBhbmFseXN0cyBpbiB0aGUgcmVhbCB3b3JsZCBvZnRlbiBzdGlsbCBwZXJmb3JtIGh5cG90aGVzaXMgdGVzdHMgb24gZGF0YXNldHMgdGhhdCBhcmVu4oCZdCBleGFjdGx5IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBXaGF0IGlzIG1vcmUgaW1wb3J0YW50IGlzIHRvIHJlY29nbml6ZSBpZiB0aGVyZSBpcyBzb21lIHJlYXNvbiB0byBiZWxpZXZlIHRoYXQgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGlzIGVzcGVjaWFsbHkgdW5saWtlbHkuIElmIHlvdXIgZGF0YXNldCBpcyBkZWZpbml0aXZlbHkgbm90IG5vcm1hbCwgdGhlIG51bWVyaWNhbCBoeXBvdGhlc2lzIHRlc3RzIHdvbuKAmXQgd29yayBhcyBpbnRlbmRlZC4NCg0KRm9yIGV4YW1wbGUsIGltYWdpbmUgeW91IGhhdmUgdGhyZWUgZGF0YXNldHMsIGVhY2ggcmVwcmVzZW50aW5nIGEgZGF5IG9mIHRyYWZmaWMgZGF0YSBpbiB0aHJlZSBkaWZmZXJlbnQgY2l0aWVzLiBFYWNoIGRhdGFzZXQgaXMgaW5kZXBlbmRlbnQsIGFzIHRyYWZmaWMgaW4gb25lIGNpdHkgc2hvdWxkIG5vdCBpbXBhY3QgdHJhZmZpYyBpbiBhbm90aGVyIGNpdHkuIEhvd2V2ZXIsIGl0IGlzIHVubGlrZWx5IHRoYXQgZWFjaCBkYXRhc2V0IGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBJbiBmYWN0LCBlYWNoIGRhdGFzZXQgcHJvYmFibHkgaGFzIHR3byBkaXN0aW5jdCBwZWFrcywgb25lIGF0IHRoZSBtb3JuaW5nIHJ1c2ggaG91ciBhbmQgb25lIGR1cmluZyB0aGUgZXZlbmluZyBydXNoIGhvdXIuIFRoZSBoaXN0b2dyYW0gb2YgYSBkYXkgb2YgdHJhZmZpYyBkYXRhIG1pZ2h0IGxvb2sgc29tZXRoaW5nIGxpa2UgdGhpczoNCg0KYGBge3IgSHlwbzYsIG91dC53aWR0aD0iNjAlIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9rdW9hbi9EZXNrdG9wL1IgQ29kZS9IeXBvNi5wbmciKQ0KYGBgDQoNCkluIHRoaXMgc2NlbmFyaW8sIHVzaW5nIGEgbnVtZXJpY2FsIGh5cG90aGVzaXMgdGVzdCB3b3VsZCBiZSBpbmFwcHJvcHJpYXRlLg0KDQoyLiBUaGUgcG9wdWxhdGlvbiBzdGFuZGFyZCBkZXZpYXRpb25zIG9mIHRoZSBncm91cHMgc2hvdWxkIGJlIGVxdWFsDQpGb3IgQU5PVkEgYW5kIFR3byBTYW1wbGUgVC1UZXN0cywgdXNpbmcgZGF0YXNldHMgd2l0aCBzdGFuZGFyZCBkZXZpYXRpb25zIHRoYXQgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gZWFjaCBvdGhlciB3aWxsIG9mdGVuIG9ic2N1cmUgdGhlIGRpZmZlcmVuY2VzIGluIGdyb3VwIG1lYW5zLg0KDQpUbyBjaGVjayBmb3Igc2ltaWxhcml0eSBiZXR3ZWVuIHRoZSBzdGFuZGFyZCBkZXZpYXRpb25zLCBpdCBpcyBub3JtYWxseSBzdWZmaWNpZW50IHRvIGRpdmlkZSB0aGUgdHdvIHN0YW5kYXJkIGRldmlhdGlvbnMgYW5kIHNlZSBpZiB0aGUgcmF0aW8gaXMg4oCcY2xvc2UgZW5vdWdo4oCdIHRvIDEuIOKAnENsb3NlIGVub3VnaOKAnSBtYXkgZGlmZmVyIGluIGRpZmZlcmVudCBjb250ZXh0cywgYnV0IGdlbmVyYWxseSBzdGF5aW5nIHdpdGhpbiAxMCUgc2hvdWxkIHN1ZmZpY2UuDQoNCjMuIFRoZSBzYW1wbGVzIG11c3QgYmUgaW5kZXBlbmRlbnQNCldoZW4gY29tcGFyaW5nIHR3byBvciBtb3JlIGRhdGFzZXRzLCB0aGUgdmFsdWVzIGluIG9uZSBkaXN0cmlidXRpb24gc2hvdWxkIG5vdCBhZmZlY3QgdGhlIHZhbHVlcyBpbiBhbm90aGVyIGRpc3RyaWJ1dGlvbi4gSW4gb3RoZXIgd29yZHMsIGtub3dpbmcgbW9yZSBhYm91dCBvbmUgZGlzdHJpYnV0aW9uIHNob3VsZCBub3QgZ2l2ZSB5b3UgYW55IGluZm9ybWF0aW9uIGFib3V0IGFueSBvdGhlciBkaXN0cmlidXRpb24uDQoNCkhlcmUgYXJlIHNvbWUgZXhhbXBsZXMgd2hlcmUgaXQgd291bGQgc2VlbSB0aGUgc2FtcGxlcyBhcmUgbm90IGluZGVwZW5kZW50Og0KDQoxLnRoZSBudW1iZXIgb2YgZ29hbHMgc2NvcmVkIHBlciBzb2NjZXIgcGxheWVyIGJlZm9yZSwgZHVyaW5nLCBhbmQgYWZ0ZXIgdW5kZXJnb2luZyBhIHJpZ29yb3VzIHRyYWluaW5nIHJlZ2ltZW4NCg0KMi5hIGdyb3VwIG9mIHBhdGllbnRz4oCZIGJsb29kIHByZXNzdXJlIGxldmVscyBiZWZvcmUsIGR1cmluZywgYW5kIGFmdGVyIHRoZSBhZG1pbmlzdHJhdGlvbiBvZiBhIGRydWcNCg0KSXQgaXMgaW1wb3J0YW50IHRvIHVuZGVyc3RhbmQgeW91ciBkYXRhc2V0cyBiZWZvcmUgeW91IGJlZ2luIGNvbmR1Y3RpbmcgaHlwb3RoZXNpcyB0ZXN0cyBvbiB0aGVtIHNvIHRoYXQgeW91IGtub3cgeW91IGFyZSBjaG9vc2luZyB0aGUgcmlnaHQgdGVzdC4NCg0KIyMgSW5zdHJjdGlvbnMNCg0KMS5Vc2UgdGhlIGJhc2UgUiBoaXN0KCkgZnVuY3Rpb24gdG8gZGlzcGxheSB0aGUgaGlzdG9ncmFtcyBmb3IgZGlzdF9vbmUsIGRpc3RfdHdvLCBkaXN0X3RocmVlLCBhbmQgZGlzdF9mb3VyLg0KDQpgYGB7ciBtZXNzYWdlID0gRkFMU0V9DQojIGxvYWQgZGF0YQ0KbG9hZCgiZGlzdF9vbmUuUmRhIikNCmxvYWQoImRpc3RfdHdvLlJkYSIpDQpsb2FkKCJkaXN0X3RocmVlLlJkYSIpDQpsb2FkKCJkaXN0X2ZvdXIuUmRhIikNCmBgYA0KDQpgYGB7cn0NCiMgcGxvdCBoaXN0b2dyYW1zIGFuZCBkZWZpbmUgbm90X25vcm1hbCBoZXJlOg0KaGlzdChkaXN0X29uZSkNCmBgYA0KDQpgYGB7ciBIeXBvNywgb3V0LndpZHRoPSI2MCUifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkM6L1VzZXJzL2t1b2FuL0Rlc2t0b3AvUiBDb2RlL0h5cG83LnBuZyIpDQpgYGANCg0KYGBge3J9DQpoaXN0KGRpc3RfdHdvKQ0KYGBgDQoNCmBgYHtyIEh5cG84LCBvdXQud2lkdGg9IjYwJSJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiQzovVXNlcnMva3VvYW4vRGVza3RvcC9SIENvZGUvSHlwbzgucG5nIikNCmBgYA0KDQpgYGB7cn0NCmhpc3QoZGlzdF90aHJlZSkNCmBgYA0KDQpgYGB7ciBIeXBvOSwgb3V0LndpZHRoPSI2MCUifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkM6L1VzZXJzL2t1b2FuL0Rlc2t0b3AvUiBDb2RlL0h5cG85LnBuZyIpDQpgYGANCg0KYGBge3J9DQpoaXN0KGRpc3RfZm91cikNCmBgYA0KDQpgYGB7ciBIeXBvMTAsIG91dC53aWR0aD0iNjAlIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9rdW9hbi9EZXNrdG9wL1IgQ29kZS9IeXBvMTAucG5nIikNCmBgYA0KDQoNCjIuRG8gdGhlIGRpc3RyaWJ1dGlvbnMgbG9vayBub3JtYWw/DQoNCk9uZSBvZiB0aGVzZSBkaXN0cmlidXRpb25zIHdvdWxkIHByb2JhYmx5IG5vdCBiZSBhIGdvb2QgY2hvaWNlIHRvIHVzZSBpbiBhbiBBTk9WQSBjb21wYXJpc29uLiBDcmVhdGUgYSB2YXJpYWJsZSBjYWxsZWQgbm90X25vcm1hbCBhbmQgc2V0IGl0IGVxdWFsIHRvIHRoZSBkaXN0cmlidXRpb24gbnVtYmVyICgxLCAyLCAzLCBvciA0KSB0aGF0IHdvdWxkIGJlIGxlYXN0IHN1aXRlZCBmb3IgdXNlIGluIGFuIEFOT1ZBIHRlc3QuDQoNCipIaW50IDogQSBub3JtYWwgZGlzdHJpYnV0aW9uIHdpbGwgaGF2ZSBhIGJlbGwgc2hhcGVkIGN1cnZlIHdpdGggb25lIG1lYW4uDQoNCg0KYGBge3J9DQpub3Rfbm9ybWFsIDwtIDQNCm5vdF9ub3JtYWwgDQpgYGANCg0KMy5DYWxjdWxhdGUgdGhlIHJhdGlvIG9mIHN0YW5kYXJkIGRldmlhdGlvbnMgYmV0d2VlbiBkaXN0X3R3byBhbmQgZGlzdF90aHJlZSwgYW5kIHN0b3JlIHRoZSB2YWx1ZSBpbiBhIHZhcmlhYmxlIGNhbGxlZCByYXRpby4gVmlldyByYXRpby4gSXMgdGhpcyDigJxjbG9zZSBlbm91Z2jigJ0gdG8gcGVyZm9ybSBhIG51bWVyaWNhbCBoeXBvdGhlc2lzIHRlc3QgYmV0d2VlbiB0aGUgdHdvIGRhdGFzZXRzPw0KDQpgYGB7cn0NCiMgZGVmaW5lIHJhdGlvIGhlcmU6DQpyYXRpbyA8LSBzZChkaXN0X3R3bykgLyBzZChkaXN0X3RocmVlKQ0KcmF0aW8NCmBgYA0KDQpbMV0gMC41Nzg0NzgyDQoNCk9uZSBvZiB0aGUgYXNzdW1wdGlvbnMgb2YgYSBudW1lcmljYWwgaHlwb3RoZXNpcyB0ZXN0IGlzIHRoYXQgdGhlIHJhdGlvIG9mIHRoZSBzdGFuZGFyZCBkZXZpYXRpb25zIG9mIHRoZSBkYXRhc2V0cyBhcmUgY2xvc2UgdG8gMS4NCg0KU2luY2UgdGhlIHJhdGlvIGlzIG5vdCBjbG9zZSB0byAxLCB0aGVzZSBkYXRhc2V0cyBzaG91bGQgbm90IGJlIHVzZWQgdG9nZXRoZXIgaW4gYSBudW1lcmljYWwgaHlwb3RoZXNpcyB0ZXN0Lg0KDQojIDE0LlJldmlldw0KDQpQaGV3ISBOb2JvZHkgc2FpZCBoeXBvdGhlc2lzIHRlc3RpbmcgaXMgZWFzeSwgYnV0IHlvdSBtYWRlIGl0IHRvIHRoZSBlbmQgb2YgdGhlIGxlc3Nvbi4gQ29uZ3JhdHVsYXRpb25zISBUaGUgd29ybGQgb2YgaHlwb3RoZXNpcyB0ZXN0aW5nIGlzIHZhc3QuIFRoZXJlIGlzIG11Y2ggbW9yZSB5b3UgY2FuIGxlYXJuLCBhbmQgc28gbWFueSBhcHBsaWNhdGlvbnMgd2hlcmUgeW91IGNhbiB1c2UgdGhlbS4NCg0KTGV04oCZcyByZXZpZXcgd2hhdCB5b3XigJl2ZSBsZWFybmVkIGluIHRoaXMgbGVzc29uOg0KDQoxLlNhbXBsZXMgYXJlIHN1YnNldHMgb2YgYW4gZW50aXJlIHBvcHVsYXRpb24sIGFuZCB0aGUgc2FtcGxlIG1lYW4gY2FuIGJlIHVzZWQgdG8gYXBwcm94aW1hdGUgdGhlIHBvcHVsYXRpb24gbWVhbg0KDQoyLlRoZSBudWxsIGh5cG90aGVzaXMgaXMgYW4gYXNzdW1wdGlvbiB0aGF0IHRoZXJlIGlzIG5vIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcG9wdWxhdGlvbnMgeW91IGFyZSBjb21wYXJpbmcgaW4gYSBoeXBvdGhlc2lzIHRlc3QNCg0KMy5UeXBlIEkgRXJyb3JzIG9jY3VyIHdoZW4gYSBoeXBvdGhlc2lzIHRlc3QgZmluZHMgYSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoaW5ncyB0aGF0IGFyZSBub3QgcmVsYXRlZCwgYW5kIFR5cGUgSUkgRXJyb3JzIG9jY3VyIHdoZW4gYSBoeXBvdGhlc2lzIHRlc3QgZmFpbHMgdG8gZmluZCBhIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhpbmdzIHRoYXQgYXJlIGFjdHVhbGx5IHJlbGF0ZWQNCg0KNC5QLVZhbHVlcyBpbmRpY2F0ZSB0aGUgcHJvYmFiaWxpdHkgdGhhdCwgYXNzdW1pbmcgdGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0cnVlLCBzdWNoIGRpZmZlcmVuY2VzIGluIHRoZSBzYW1wbGVzIHlvdSBhcmUgY29tcGFyaW5nIHdvdWxkIGV4aXN0DQoNCjUuVGhlIFNpZ25pZmljYW5jZSBMZXZlbCBpcyBhIHRocmVzaG9sZCBwLXZhbHVlIGZvciB3aGljaCBhbGwgcC12YWx1ZXMgYmVsb3cgaXQgd2lsbCByZXN1bHQgaW4gcmVqZWN0aW5nIHRoZSBudWxsIGh5cG90aGVzaXMNCg0KNi5PbmUgU2FtcGxlIFQtVGVzdHMgaW5kaWNhdGUgd2hldGhlciBhIGRhdGFzZXQgYmVsb25ncyB0byBhIGRpc3RyaWJ1dGlvbiB3aXRoIGEgZ2l2ZW4gbWVhbg0KDQo3LlR3byBTYW1wbGUgVC1UZXN0cyBpbmRpY2F0ZSB3aGV0aGVyIHRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHR3byBkYXRhc2V0cw0KDQo4LkFOT1ZBIChBbmFseXNpcyBvZiBWYXJpYW5jZSkgYWxsb3dzIHlvdSB0byBkZXRlY3QgaWYgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gb25lIG9mIG11bHRpcGxlIGRhdGFzZXRzDQoNCg0K