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:
- 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.
- 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.
- 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