Simulations in R
Carrying out simulations in R is actually quite straightforward. We will walk through the steps involved one at a time.
π» Suppose that we are interested in the random variable \(X \sim N(0, 1)\) - in other words, here \(X\) follows the standard normal distribution.
We can generate a sample of 100 observations from this distribution using the following R code:
set.seed(1)
n <- 100
x <- rnorm(n)
Run this code now.
Note: The default mean and standard deviation values used by rnorm
are 0 and 1 respectively, so we do not need to specify them in this instance.
π» We can plot our generated data using the hist
function, as shown below.
hist(x, freq = FALSE, col = "chartreuse3", xlim = c(-3, 3),
main = paste("Histogram of random sample \n from standard Normal distribution, n = ", n))
# Overlay standard normal curve
curve(dnorm(x), add = TRUE, col = "blue", lwd = 2)
# Add line denoting sample mean
abline(v = round(mean(x), 3), col = "red", lwd = 2, lty = 2)

Note that we have also used the curve
and dnorm
functions here to overlay the standard normal distribution probability density curve.
π» Our main interest here is the sample mean, not the variability of the sample values.
If we check the sample mean of our data set x
, we find that this is equal to approximately 0.109 (shown by the red dashed line in the plot above). Since this is the sample mean for just one sample of 100 observations, we canβt be too confident in using this estimate as an accurate estimate of the population mean (which we know was specified to be 0
).
Rather than relying on just the one sample of 100 observations, we will now simulate a number of random samples from \(X\), in order to obtain multiple sample mean estimates, which we can use in turn to obtain more accurate estimate of the population mean.
π» To begin, suppose we sample just 5 observations of \(X\), rather than 100, and then compute the sample mean of these 5 observations.
Using the code in 2.1, it follows that this process is quite straightforward:
set.seed(1)
n <- 5 # Specify sample size
x <- rnorm(n) # Generate n samples from the standard normal distribution
norm_mean <- mean(x) # Store the mean of the samples in a new object
π§ Online students
π¬ Run your object norm_mean
and post your result in the chat.
for loops
π» Since our underlying data is generated from a standard normal distribution, it follows that the distribution of the sample mean will also be normal (we can think of this result as a precursor to the Central Limit Theorem).
To accurately visualise the distribution of the sample mean, we will need to repeat the process outlined in 2.4 many times. This is where our simulations can really shine.
Suppose, rather than conducting the process outlined in 2.4 once, we instead conduct it 10,000 times. It would take a while to write this code out line by line in R (over 9000 lines potentially!).
Instead, to save time, we will use a for loop
. A for loop
is a function that will repeat a specified set of operations a specified number of times.
The Code
chunk below provides a simple example of the R syntax for a for loop
.
for(i in 1:10){
x <- rnorm(i)
mean(x)}
How do we interpret this code?
Well,we have specified that for some input i
, where i
can take the integer values 1 up to 10, the for loop
will simulate i
random values from the standard Normal distribution, store them in the object x
, and then compute the mean of x
.
Thus, our for loop
runs like this:
- The
for loop
starts with the first specified value, 1, and simulates 1 random value from the standard Normal distribution.
- The mean of
x
is now computed. This is the last operation in the for loop
.
- Since the specified operations inside the loop have been finished for that value of
i
, the loop starts again, with i=2
now.
- This process continues, until the final specified value of
i
, namely i=10
, has been used.
- At this point, the
for loop
is complete.
Note: We do not have to use the letter i
here, it is simply convention. You can use a different letter, but remember, make sure you have not used your chosen letter as a name for a previous object in which you have stored data.
π» The Code
chunk below expands upon the for loop
example discussed above in 2.5. Take a look at this code, read the comments carefully, and make sure you understand what the code does (note some values are missing, as denoted by the ...
).
#Specify sample size
ns <- ...
# Specify number of times to conduct process
trials <- ...
# create object in which to store sample means once they are generated
norm.means <- rep(0, trials) # Note length is equal to the number of trials
# Run for loop
for(i in 1:trials){
# Randomly generate ns samples from the normal distribution
x <- rnorm(ns)
# Compute mean of samples, store in the norm.means object, in ith position
norm.means[i] <- mean(x)}
Once you feel confident in your understanding of this code, replace the ...
missing details for ns
and trials
, using the following details:
- You want to take 10,000 samples of randomly generated values from the standard Normal distribution.
- Each sample should have a sample size of 5.
Once you have filled in the details, run your code.
Hint: If you have given this a decent shot, but are stuck, you can check the Code
chunk below:
#Specify sample size
ns <- 5
# Specify number of times to conduct process
trials <- 10000
# create object in which to store sample means once they are generated
norm.means <- rep(0, trials) # Note length is equal to the number of trials
# Run for loop
for(i in 1:trials){
# Randomly generate ns samples from the normal distribution
x <- rnorm(ns)
# Compute mean of samples, store in the norm.means object, in ith position
norm.means[i] <- mean(x)}
π» To visualise our results, we can use the following code:
hist(norm.means, freq = FALSE, breaks = 20, col = "red",
xlim = c(-3, 3),
xlab = expression(bar(x)),
main = paste("Histogram of means, n = ", ns))
We can also overlay a normal density curve, that, since our underlying data is normal,
will reflect the distribution of the sample mean.
curve(dnorm(x,
mean = 0, sd = 1/sqrt(ns)),
add = TRUE, col = "blue", lwd = 2)
Run these code chunks now, and check your results. Are our simulated sample means close to the population mean of 0?
π»Repeat steps 2.6 and 2.7, using a sample of 30 instead of 5. What do you notice about the distribution of the simulated sample means?
π§ Online students
π¬ Leave a comment in the chat about the changes you observe in the distribution, changing from \(n=5\) to \(n=30\).
π» Finally, repeat steps 2.6 and 2.7, using a sample of 60. What do you notice about the distribution of the simulated sample means now?
π§ Online students
π¬ Leave a comment in the chat about the changes you observe in the distribution, changing from \(n=30\) to \(n=60\).
CLT Simulation - Exponential Distribution
π» To demonstrate the versatility of the Central Limit Theorem, letβs carry out some simulations involving data generated from the Exponential distribution, which (unlike the Normal distribution) is highly skewed (i.e.Β asymmetric).
π» Recall from Topic 3 that the Exponential distribution is defined by one parameter, known as the rate parameter. The rate parameter is denoted by the Greek letter \(\lambda\).
If a random variable \(X\) follows an Exponential distribution with rate parameter \(\lambda\), we write \(X\sim Exp(\lambda)\).
Suppose now that our random variable \(X\) follows an exponential distribution with rate parameter \(\lambda = 10\). In other words, suppose \(X \sim \text{Exp}(10)\).
We can generate a sample of 100 observations from this distribution using the following R code:
set.seed(1)
n <- 100
rate = 10
x <- rexp(n, rate = rate)
Note that we use rexp
to randomly generate values from the exponential distribution, instead of using rnorm
(which is for the normal distribution).
Run this code now.
π» Our generated data from 3.1 is highly skewed, and clearly different to data generated from the symmetric normal distribution. This disparity can be seen in Figure 3.1 below, which shows a histogram of the data, with a normal distribution probability density curve overlaid in blue (similar to in 2.2), based on appropriate mean and variance values.
Clearly, we cannot fit a normal curve well to data generated from an Exponential distribution. However, as we work through this question, we will find that when we model the distribution of the sample means of data generated from an Exponential distribution, this distribution of sample means can be fitted well by a normal curve, especially as our sample size increases. This (somewhat unintuitive) result is due to the Central Limit Theorem!
The Rate Parameter and Population Mean
π» Instead of considering the individual data points generated from the Exponential distribution, letβs shift our focus to the sample mean of these data points.
For data generated from an Exponential distribution, the population mean \(\mu\) is in theory equal to 1 divided by the rate parameter \(\lambda\). I.e., for \(X\sim Exp(\lambda)\), the population mean of \(X\) equals \(\frac{1}{\lambda}\).
If we check the sample mean of x
, we find that this is equal to 0.1030676 - this sample mean is quite a good estimate of the population mean (\(\mu = 1/10 = 0.1\)), given the theory.
π» Let us now conduct the simulation process used in 2.6, for our data sampled from \(X \sim \text{Exp}(10)\).
Using the code in 2.6 as a guide, simulate 10,000 sample means of \(X\), using samples of size 5.
Plot your results, using the code in 2.7 as a guide.
Note: You will have to change the x-axis range for the histogram (via the xlim
argument). Try using a range of 0 to 0.4.
Note 2: Use the code in the Code
chunk below to overlay the appropriate Normal distribution probability density curve:
curve(dnorm(x, mean = 1/rate, sd = 1/rate/sqrt(ns)), add = TRUE,
col = "blue", lwd = 2)
π» What do you notice about your resultant plot?
π» Repeats 3.4 for \(X \sim Exp(10)\), using a sample of 30 instead of 5. What do you notice about the distribution of the simulated sample means?
π§ Online students
π¬ Leave a comment in the chat about the changes you observe in the distribution, changing from \(n=5\) to \(n=30\).
π» Finally, repeat 3.4 for \(X \sim Exp(10)\), using a sample of 60. What do you notice about the distribution of the simulated sample means now?
π§ Online students
π¬ Leave a comment in the chat about the changes you observe in the distribution, changing from \(n=30\) to \(n=60\).
CLT Simulation - Bernoulli Distribution
π» As discussed in Section 3.3 of Topic 4, the Central Limit Theorem even applies to discrete random variables.
Suppose that our random variable \(X\) now follows a Bernoulli distribution with success parameter \(p = 0.3\). In other words, suppose \(X \sim \text{BERN}(0.3)\).
π» If we generate a sample of 100 observations from this distribution (see the R code below) and then visualise our generated data, we see a roughly 70/30 split of observations between \(x=0\) and \(x=1\). Clearly, (just as in the Exponential distribution case), the normal distribution probability density curve, with appropriate parameter specifications, (shown in blue), is an extremely poor fit for this data.
set.seed(1)
n <- 100
p = 0.3
x <- rbinom(n, 1, p)
Note that we use rbinom
to randomly generate values from the Bernoulli distribution, instead of using rnorm
(which is for the normal distribution).

π» However, despite our data being generated from a discrete distribution, we can still use the Central Limit Theorem to obtain an accurate estimate of the population mean by considering the distribution of \(\bar{X}\)!
Let us now conduct the simulation process used in 2.6, for our Bernoulli-distributed data.
Using the code in 2.6 as a guide, simulate 10000 sample means of \(X\), using samples of size 5.
Then, plot your results, using the code in 2.7 as a guide.
Note: You will have to change the x-axis range for the histogram (via the xlim
argument).
Note 2: Use the code in the Code
chunk below to overlay a normal distribution probability density curve with the appropriate parameter specifications:
# Set mu and sigma for the approximating normal distribution
mu <- p
sigma <- sqrt(p*(1 - p))
# Overlay the normal density
curve(dnorm(x, mu, sigma/sqrt(ns)), add = TRUE, col = "blue", lwd = 2)
π» What do you notice about your resultant plot?
π» Repeat 3.4 for \(X \sim BERN(0.3)\), using a sample of 30 instead of 5. What do you notice about the distribution of the simulated sample means?
π§ Online students
π¬ Leave a comment in the chat about the changes you observe in the distribution, changing from \(n=5\) to \(n=30\).
π» Finally, repeat 3.4 for \(X \sim BERN(0.3)\), using a sample of 60. What do you notice about the distribution of the simulated sample means now?
π§ Online students
π¬ Leave a comment in the chat about the changes you observe in the distribution, changing from \(n=30\) to \(n=60\).
Extension: Average Diamond Prices
π» Letβs consider how we can apply the Central Limit Theorem to real data.
For this question, we will consider data on approximately 54,000 round cut diamonds. This data is stored in the diamonds
data set in the ggplot2
R package. We will treat this data as the population data.
Install and load the ggplot2
R package now.
Hint: If you need a refresher on installing and loading packages in R, check the Code
chunk below:
install.packages("ggplot2")
library(ggplot2)
π» If we plot the price of round cut diamonds using a histogram, we can see that the data is clearly not normally distributed.
Make sure to run this code before continuing.
hist(diamonds$price, col = "skyblue", xlab = "Diamond Price ($)",
main = "Histogram of Diamond Prices ($)", freq = F)

π» Suppose that you are interested in estimating the population mean price for round cut diamonds, but do not have access to the full diamonds
data set.
Instead, you can only sample prices for 5 round cut diamonds at a time, represented by the code below:
x <- sample(diamonds$price, 5)
Using this code and the code in 2.6 as a guide, obtain 100 sample means from 100 simulated samples of 5 random round cut diamond sale prices. Plot a histogram of these sample means. What do you observe?
π§ Online students
π¬ Volunteer to share your screen to show your histogram and discuss your results, if you got to this stage before the end of the lab.
π» Repeat 5.2, but this time suppose that you are able to take samples of 30 diamonds at a time, instead of 5. What changes do you observe?
Great job, thatβs everything for today!
Hopefully, this computer lab has helped cement your understanding of the Central Limit Theorem.
LS0tDQp0aXRsZTogIlNUTTEwMDE6IENvbXB1dGVyIExhYiA1QiINCm91dHB1dDoNCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOiANCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdGhlbWU6IHJlYWRhYmxlDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQpiaWJsaW9ncmFwaHk6IFNUTTEwMDFfRFNfQ0xfcmVmZXJlbmNlcy5iaWIgDQpsaW5rLWNpdGF0aW9uczogeWVzDQotLS0NCg0KPHN0eWxlPg0KI1RPQyB7DQogIGJhY2tncm91bmQ6IHVybCgiaHR0cHM6Ly93d3cubGF0cm9iZS5lZHUuYXUvX21lZGlhL2xhLXRyb2JlLWFwaS92NS9pbWcvbG9nby5zdmciKTsNCiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOw0KICBwYWRkaW5nLXRvcDogODBweCAhaW1wb3J0YW50Ow0KICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0Ow0KfQ0KPC9zdHlsZT4NCg0KIyMjIERhdGEgU2NpZW5jZSBTdHJlYW0gey19DQoNCiMjIyBUb3BpYyA1QjogU2ltdWxhdGlvbnMgaW4gUiB7LX0NCg0KPGJyPg0KDQpXZWxjb21lIHRvIHRoZSBmaWZ0aCBjb21wdXRlciBsYWIgZm9yIHRoZSBEYXRhIFNjaWVuY2Ugc3RyZWFtIG9mIFNUTTEwMDEuDQoNCkluIFtUb3BpYyA0XShodHRwczovL2Jvb2tkb3duLm9yZy9jb250ZW50Lzg4ZWY5YjdjLTU4MzMtNGE3MC04NGYyLTkzNDcwOTU3ZDFmOS8pLCB3ZSBpbnRyb2R1Y2VkIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMgYW5kIHRoZSBjb25jZXB0IG9mIHRoZSAqQ2VudHJhbCBMaW1pdCBUaGVvcmVtKi4gDQoNCkluIHRoaXMgY29tcHV0ZXIgbGFiIHdlIHdpbGwgdXNlIFIgdG8gY29uZHVjdCB0aGUgc2ltdWxhdGlvbnMgZGlzY3Vzc2VkIGluIFtDaGFwdGVyIDMgb2YgVG9waWMgNF0oaHR0cHM6Ly9ib29rZG93bi5vcmcvY29udGVudC84OGVmOWI3Yy01ODMzLTRhNzAtODRmMi05MzQ3MDk1N2QxZjkvMy10aGUtY2VudHJhbC1saW1pdC10aGVvcmVtLmh0bWwpLiANCg0KICAqICpJdCBtaWdodCBiZSBoZWxwZnVsIHRvIGtlZXAgdGhpcyBjb250ZW50IG9wZW4gaW4gYSBzZXBhcmF0ZSB0YWIgd2hpbGUgeW91IHdvcmsgdGhyb3VnaCB0aGUgbGFiIG1hdGVyaWFsLCBpbiBjYXNlIHlvdSB3b3VsZCBsaWtlIHRvIHF1aWNrbHkgZG91YmxlLWNoZWNrIHlvdXIgdW5kZXJzdGFuZGluZyBvZiBhbnkgY29uY2VwdHMuKg0KDQpCeSB0aGUgZW5kIG9mIHRoaXMgbGFiLCB5b3Ugc2hvdWxkIGJlIGFibGUgdG8gY29uZHVjdCBzaW1wbGUgc2ltdWxhdGlvbnMgaW4gUi4gTGV0J3MgZ2V0IHN0YXJ0ZWQhDQoNCiMgU2FtcGxpbmcgRGlzdHJpYnV0aW9ucw0KDQojIyBTYW1wbGluZw0KDQpgciBlbW86OmppKCJob3VzZV93aXRoX2dhcmRlbiIpYCBSZWNhbGwgdGhhdCBhICoqc2FtcGxlKiogaXMgYSByYW5kb20gc2VsZWN0aW9uIG9mIHVuaXRzIGZyb20gYSBjaG9zZW4gcG9wdWxhdGlvbi4NCg0KICAqIEZvciBleGFtcGxlLCBpZiB0aGUgU1RNMTAwMSBjb2hvcnQgd2FzIG91ciBjaG9zZW4gcG9wdWxhdGlvbiwgdGhlbiBhIHJhbmRvbSBzZWxlY3Rpb24gb2YgU1RNMTAwMSBzdHVkZW50cyB3b3VsZCBiZSBhICoqc2FtcGxlKiogZnJvbSB0aGlzIHBvcHVsYXRpb24uDQoNCkJlY2F1c2UgaXQgaXMgdHlwaWNhbGx5IHVuZmVhc2libGUgdG8gY29sbGVjdCBkYXRhIG9uIGFuIGVudGlyZSBwb3B1bGF0aW9uIG9mIGludGVyZXN0LCB3ZSBpbnN0ZWFkIGNvbmR1Y3QgYW5hbHlzZXMgdXNpbmcgYSBzYW1wbGUuIFdlIGhvcGUgdGhhdCB0aGUgaW5mZXJlbmNlcyB3ZSBtYWtlIHVzaW5nIHRoZSBzYW1wbGUgZGF0YSBjYW4gYmUgZXh0cmFwb2xhdGVkIHRvIHByb3ZpZGUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHBvcHVsYXRpb24sIGFuZCB3ZSBjYW4gdXNlIHN0YXRpc3RpY2FsIHRlY2huaXF1ZXMgdG8gYXNjZXJ0YWluIHRoZSBhY2N1cmFjeSBvZiB0aGVzZSBpbmZlcmVuY2VzLiANCg0KT25lIHN1Y2ggc3RhdGlzdGljYWwgdGVjaG5pcXVlIHdlIGNhbiB1dGlsaXNlIGlzIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0uDQoNCiMjIFRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0geyNDTFR9DQoNCmByIGVtbzo6amkoImhvdXNlX3dpdGhfZ2FyZGVuIilgIFJlY2FsbCB0aGUgZGVmaW5pdGlvbiBvZiB0aGUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtIChDTFQpOg0KDQo8Y2VudGVyPg0KTGV0ICRYXzEsIFxsZG90cywgWF9uJCBiZSBhIHJhbmRvbSBzYW1wbGUgZnJvbSBhIGRpc3RyaWJ1dGlvbiB3aXRoIGZpbml0ZSBtZWFuICRcbXUkIGFuZCBmaW5pdGUgdmFyaWFuY2UgJFxzaWdtYV4yJC4gDQoNCkZvciAkXG92ZXJsaW5le1h9JCBkZW5vdGluZyB0aGUgc2FtcGxlIG1lYW4sIGlmICRuJCBpcyBzdWZmaWNpZW50bHkgbGFyZ2UgdGhlbg0KJCRcb3ZlcmxpbmV7WH1cc3RhY2tyZWx7XHRpbnkgXHRleHR7YXBwcm94Ln19XHNpbSBOXGxlZnQoXG11LFxmcmFje1xzaWdtYV4yfXtufVxyaWdodCkgLCAkJA0Kd2hlcmUgJFxzdGFja3JlbHtcdGlueSBcdGV4dHthcHByb3gufX1cc2ltJCBkZW5vdGVzICdhcHByb3hpbWF0ZWx5IGRpc3RyaWJ1dGVkIGFzJy4NCjwvY2VudGVyPg0KPGJyPg0KDQpCeSB0aGUgQ0xULCBpdCBmb2xsb3dzIHRoYXQgYXMgd2UgaW5jcmVhc2Ugb3VyIHNhbXBsZSBzaXplLCB0aGUgc2FtcGxlIG1lYW4gJFxvdmVybGluZXtYfSQgd2lsbCBnZXQgaW5jcmVhc2luZ2x5IGNsb3NlciAoaS5lLiBjb252ZXJnZSkgdG8gdGhlIHBvcHVsYXRpb24gbWVhbiAkXG11JC4gQXMgJG4kIGluY3JlYXNlcywgdGhlIHZhcmlhbmNlIG9mIHRoZSBzYW1wbGUgbWVhbiAkXG92ZXJsaW5le1h9JCB3aWxsIGFsc28gZGVjcmVhc2UuDQoNCkluIG90aGVyIHdvcmRzLCB3aGlsZSBzYW1wbGVzIG9mIGluZGl2aWR1YWxzIGNhbiBleGhpYml0IHNpZ25pZmljYW50IHZhcmlhdGlvbiwgc2FtcGxlcyBvZiBtZWFucyB0ZW5kIHRvIGhhdmUgbGVzcyB2YXJpYWJpbGl0eSAoYXMgZWFjaCBtZWFuIGlzIGNhbGN1bGF0ZWQgZnJvbSBhIHNhbXBsZSBvZiBpbmRpdmlkdWFscywgcmVkdWNpbmcgdGhlIGltcGFjdCBvZiBvdXRsaWVycykuDQoNCkxldCdzIHZpc3VhbGlzZSB0aGlzIHByb2Nlc3MgaW4gUiB1c2luZyBzb21lIHNpbXVsYXRpb25zLg0KDQojIFNpbXVsYXRpb25zIGluIFINCg0KQ2Fycnlpbmcgb3V0IHNpbXVsYXRpb25zIGluIFIgaXMgYWN0dWFsbHkgcXVpdGUgc3RyYWlnaHRmb3J3YXJkLiBXZSB3aWxsIHdhbGsgdGhyb3VnaCB0aGUgc3RlcHMgaW52b2x2ZWQgb25lIGF0IGEgdGltZS4NCg0KIyMgeyNiYXNlfQ0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYCBTdXBwb3NlIHRoYXQgd2UgYXJlIGludGVyZXN0ZWQgaW4gdGhlIHJhbmRvbSB2YXJpYWJsZSAkWCBcc2ltIE4oMCwgMSkkIC0gaW4gb3RoZXIgd29yZHMsIGhlcmUgJFgkIGZvbGxvd3MgdGhlIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24uDQoNCldlIGNhbiBnZW5lcmF0ZSBhIHNhbXBsZSBvZiAxMDAgb2JzZXJ2YXRpb25zIGZyb20gdGhpcyBkaXN0cmlidXRpb24gdXNpbmcgdGhlIGZvbGxvd2luZyBSIGNvZGU6DQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFR9DQpzZXQuc2VlZCgxKQ0KbiA8LSAxMDANCnggPC0gcm5vcm0obikNCmBgYA0KDQpSdW4gdGhpcyBjb2RlIG5vdy4NCg0KKk5vdGU6IFRoZSBkZWZhdWx0IG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiB2YWx1ZXMgdXNlZCBieSBgcm5vcm1gIGFyZSAwIGFuZCAxIHJlc3BlY3RpdmVseSwgc28gd2UgZG8gbm90IG5lZWQgdG8gc3BlY2lmeSB0aGVtIGluIHRoaXMgaW5zdGFuY2UuKg0KDQojIyB7I2Jhc2VoaXN0fQ0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYCBXZSBjYW4gcGxvdCBvdXIgZ2VuZXJhdGVkIGRhdGEgdXNpbmcgdGhlIGBoaXN0YCBmdW5jdGlvbiwgYXMgc2hvd24gYmVsb3cuDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFR9DQpoaXN0KHgsIGZyZXEgPSBGQUxTRSwgY29sID0gImNoYXJ0cmV1c2UzIiwgeGxpbSA9IGMoLTMsIDMpLA0KICAgICBtYWluID0gcGFzdGUoIkhpc3RvZ3JhbSBvZiByYW5kb20gc2FtcGxlIFxuIGZyb20gc3RhbmRhcmQgTm9ybWFsIGRpc3RyaWJ1dGlvbiwgbiA9ICIsIG4pKSANCiMgT3ZlcmxheSBzdGFuZGFyZCBub3JtYWwgY3VydmUNCmN1cnZlKGRub3JtKHgpLCBhZGQgPSBUUlVFLCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIpDQojIEFkZCBsaW5lIGRlbm90aW5nIHNhbXBsZSBtZWFuDQphYmxpbmUodiA9IHJvdW5kKG1lYW4oeCksIDMpLCBjb2wgPSAicmVkIiwgbHdkID0gMiwgbHR5ID0gMikNCmBgYA0KDQoqTm90ZSB0aGF0IHdlIGhhdmUgYWxzbyB1c2VkIHRoZSBgY3VydmVgIGFuZCBgZG5vcm1gIGZ1bmN0aW9ucyBoZXJlIHRvIG92ZXJsYXkgdGhlIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24gcHJvYmFiaWxpdHkgZGVuc2l0eSBjdXJ2ZS4qDQoNCiMjDQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIE91ciBtYWluIGludGVyZXN0IGhlcmUgaXMgdGhlICoqc2FtcGxlIG1lYW4qKiwgbm90IHRoZSB2YXJpYWJpbGl0eSBvZiB0aGUgc2FtcGxlIHZhbHVlcy4gDQoNCklmIHdlIGNoZWNrIHRoZSBzYW1wbGUgbWVhbiBvZiBvdXIgZGF0YSBzZXQgYHhgLCB3ZSBmaW5kIHRoYXQgdGhpcyBpcyBlcXVhbCB0byBhcHByb3hpbWF0ZWx5IGByIHJvdW5kKG1lYW4oeCksIDMpYCAoc2hvd24gYnkgdGhlIHJlZCBkYXNoZWQgbGluZSBpbiB0aGUgcGxvdCBhYm92ZSkuIFNpbmNlIHRoaXMgaXMgdGhlIHNhbXBsZSBtZWFuIGZvciBqdXN0IG9uZSBzYW1wbGUgb2YgMTAwIG9ic2VydmF0aW9ucywgd2UgY2FuJ3QgYmUgdG9vIGNvbmZpZGVudCBpbiB1c2luZyB0aGlzIGVzdGltYXRlIGFzIGFuIGFjY3VyYXRlIGVzdGltYXRlIG9mIHRoZSBwb3B1bGF0aW9uIG1lYW4gKHdoaWNoIHdlIGtub3cgd2FzIHNwZWNpZmllZCB0byBiZSBgMGApLg0KDQpSYXRoZXIgdGhhbiByZWx5aW5nIG9uIGp1c3QgdGhlIG9uZSBzYW1wbGUgb2YgMTAwIG9ic2VydmF0aW9ucywgd2Ugd2lsbCBub3cgc2ltdWxhdGUgYSBudW1iZXIgb2YgcmFuZG9tIHNhbXBsZXMgZnJvbSAkWCQsIGluIG9yZGVyIHRvIG9idGFpbiBtdWx0aXBsZSBzYW1wbGUgbWVhbiBlc3RpbWF0ZXMsIHdoaWNoIHdlIGNhbiB1c2UgaW4gdHVybiB0byBvYnRhaW4gbW9yZSBhY2N1cmF0ZSBlc3RpbWF0ZSBvZiB0aGUgcG9wdWxhdGlvbiBtZWFuLg0KDQojIyB7I3N0YXJ0fQ0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYCBUbyBiZWdpbiwgc3VwcG9zZSB3ZSBzYW1wbGUganVzdCA1IG9ic2VydmF0aW9ucyBvZiAkWCQsIHJhdGhlciB0aGFuIDEwMCwgYW5kIHRoZW4gY29tcHV0ZSB0aGUgc2FtcGxlIG1lYW4gb2YgdGhlc2UgNSBvYnNlcnZhdGlvbnMuDQoNClVzaW5nIHRoZSBjb2RlIGluIFxAcmVmKGJhc2UpLCBpdCBmb2xsb3dzIHRoYXQgdGhpcyBwcm9jZXNzIGlzIHF1aXRlIHN0cmFpZ2h0Zm9yd2FyZDoNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVH0NCnNldC5zZWVkKDEpDQpuIDwtIDUgIyBTcGVjaWZ5IHNhbXBsZSBzaXplDQp4IDwtIHJub3JtKG4pICMgR2VuZXJhdGUgbiBzYW1wbGVzIGZyb20gdGhlIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24NCm5vcm1fbWVhbiA8LSBtZWFuKHgpICMgU3RvcmUgdGhlIG1lYW4gb2YgdGhlIHNhbXBsZXMgaW4gYSBuZXcgb2JqZWN0DQpgYGANCg0KPGJyPg0KDQo8ZGV0YWlscz4NCiAgPHN1bW1hcnk+YHIgZW1vOjpqaSgiaGVhZHBob25lcyIpYCAqKk9ubGluZSBzdHVkZW50cyoqPC9zdW1tYXJ5Pg0KYHIgZW1vOjpqaSgic3BlZWNoX2JhbGxvb24iKWAgIFJ1biB5b3VyIG9iamVjdCBgbm9ybV9tZWFuYCBhbmQgcG9zdCB5b3VyIHJlc3VsdCBpbiB0aGUgY2hhdC4gIA0KPC9kZXRhaWxzPiANCg0KPGJyPg0KDQojIyBgZm9yIGxvb3BzYCB7I3NpbXN0YXJ0fQ0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYCBTaW5jZSBvdXIgdW5kZXJseWluZyBkYXRhIGlzIGdlbmVyYXRlZCBmcm9tIGEgc3RhbmRhcmQgbm9ybWFsIGRpc3RyaWJ1dGlvbiwgaXQgZm9sbG93cyB0aGF0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHNhbXBsZSBtZWFuIHdpbGwgYWxzbyBiZSBub3JtYWwgKHdlIGNhbiB0aGluayBvZiB0aGlzIHJlc3VsdCBhcyBhIHByZWN1cnNvciB0byB0aGUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtKS4gDQoNClRvIGFjY3VyYXRlbHkgdmlzdWFsaXNlIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHNhbXBsZSBtZWFuLCB3ZSB3aWxsIG5lZWQgdG8gcmVwZWF0IHRoZSBwcm9jZXNzIG91dGxpbmVkIGluIFxAcmVmKHN0YXJ0KSAqKm1hbnkgdGltZXMqKi4gVGhpcyBpcyB3aGVyZSBvdXIgc2ltdWxhdGlvbnMgY2FuIHJlYWxseSBzaGluZS4NCg0KU3VwcG9zZSwgcmF0aGVyIHRoYW4gY29uZHVjdGluZyB0aGUgcHJvY2VzcyBvdXRsaW5lZCBpbiBcQHJlZihzdGFydCkgb25jZSwgd2UgaW5zdGVhZCBjb25kdWN0IGl0IDEwLDAwMCB0aW1lcy4gSXQgd291bGQgdGFrZSBhIHdoaWxlIHRvIHdyaXRlIHRoaXMgY29kZSBvdXQgbGluZSBieSBsaW5lIGluIFIgKG92ZXIgOTAwMCBsaW5lcyBwb3RlbnRpYWxseSEpLg0KDQpJbnN0ZWFkLCB0byBzYXZlIHRpbWUsIHdlIHdpbGwgdXNlIGEgYGZvciBsb29wYC4gQSBgZm9yIGxvb3BgIGlzIGEgZnVuY3Rpb24gdGhhdCB3aWxsIHJlcGVhdCBhIHNwZWNpZmllZCBzZXQgb2Ygb3BlcmF0aW9ucyBhIHNwZWNpZmllZCBudW1iZXIgb2YgdGltZXMuDQoNClRoZSBgQ29kZWAgY2h1bmsgYmVsb3cgcHJvdmlkZXMgYSBzaW1wbGUgZXhhbXBsZSBvZiB0aGUgUiBzeW50YXggZm9yIGEgYGZvciBsb29wYC4NCg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KZm9yKGkgaW4gMToxMCl7DQogIHggPC0gcm5vcm0oaSkNCiAgbWVhbih4KX0NCmBgYA0KDQpIb3cgZG8gd2UgaW50ZXJwcmV0IHRoaXMgY29kZT8NCldlbGwsd2UgaGF2ZSBzcGVjaWZpZWQgdGhhdCBmb3Igc29tZSBpbnB1dCBgaWAsIHdoZXJlIGBpYCBjYW4gdGFrZSB0aGUgaW50ZWdlciB2YWx1ZXMgMSB1cCB0byAxMCwgdGhlIGBmb3IgbG9vcGAgd2lsbCBzaW11bGF0ZSBgaWAgcmFuZG9tIHZhbHVlcyBmcm9tIHRoZSBzdGFuZGFyZCBOb3JtYWwgZGlzdHJpYnV0aW9uLCBzdG9yZSB0aGVtIGluIHRoZSBvYmplY3QgYHhgLCBhbmQgdGhlbiBjb21wdXRlIHRoZSBtZWFuIG9mIGB4YC4gDQoNClRodXMsIG91ciBgZm9yIGxvb3BgIHJ1bnMgbGlrZSB0aGlzOg0KDQoqIFRoZSBgZm9yIGxvb3BgIHN0YXJ0cyB3aXRoIHRoZSBmaXJzdCBzcGVjaWZpZWQgdmFsdWUsIDEsIGFuZCBzaW11bGF0ZXMgMSByYW5kb20gdmFsdWUgZnJvbSB0aGUgc3RhbmRhcmQgTm9ybWFsIGRpc3RyaWJ1dGlvbi4gDQoqIFRoZSBtZWFuIG9mIGB4YCBpcyBub3cgY29tcHV0ZWQuIFRoaXMgaXMgdGhlIGxhc3Qgb3BlcmF0aW9uIGluIHRoZSBgZm9yIGxvb3BgLg0KKiBTaW5jZSB0aGUgc3BlY2lmaWVkIG9wZXJhdGlvbnMgaW5zaWRlIHRoZSBsb29wIGhhdmUgYmVlbiBmaW5pc2hlZCBmb3IgdGhhdCB2YWx1ZSBvZiBgaWAsIHRoZSBsb29wIHN0YXJ0cyBhZ2Fpbiwgd2l0aCBgaT0yYCBub3cuIA0KKiBUaGlzIHByb2Nlc3MgY29udGludWVzLCB1bnRpbCB0aGUgZmluYWwgc3BlY2lmaWVkIHZhbHVlIG9mIGBpYCwgbmFtZWx5IGBpPTEwYCwgaGFzIGJlZW4gdXNlZC4gDQoqIEF0IHRoaXMgcG9pbnQsIHRoZSBgZm9yIGxvb3BgIGlzIGNvbXBsZXRlLg0KDQoqTm90ZTogV2UgZG8gbm90IGhhdmUgdG8gdXNlIHRoZSBsZXR0ZXIgYGlgIGhlcmUsIGl0IGlzIHNpbXBseSBjb252ZW50aW9uLiBZb3UgY2FuIHVzZSBhIGRpZmZlcmVudCBsZXR0ZXIsIGJ1dCByZW1lbWJlciwgbWFrZSBzdXJlIHlvdSBoYXZlIG5vdCB1c2VkIHlvdXIgY2hvc2VuIGxldHRlciBhcyBhIG5hbWUgZm9yIGEgcHJldmlvdXMgb2JqZWN0IGluIHdoaWNoIHlvdSBoYXZlIHN0b3JlZCBkYXRhLioNCg0KIyMgIHsjc2ltfQ0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYCBUaGUgYENvZGVgIGNodW5rIGJlbG93IGV4cGFuZHMgdXBvbiB0aGUgYGZvciBsb29wYCBleGFtcGxlIGRpc2N1c3NlZCBhYm92ZSBpbiBcQHJlZihzaW1zdGFydCkuIFRha2UgYSBsb29rIGF0IHRoaXMgY29kZSwgcmVhZCB0aGUgY29tbWVudHMgY2FyZWZ1bGx5LCBhbmQgbWFrZSBzdXJlIHlvdSB1bmRlcnN0YW5kIHdoYXQgdGhlIGNvZGUgZG9lcyAobm90ZSBzb21lIHZhbHVlcyBhcmUgbWlzc2luZywgYXMgZGVub3RlZCBieSB0aGUgYC4uLmApLg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KI1NwZWNpZnkgc2FtcGxlIHNpemUNCm5zIDwtIC4uLg0KIyBTcGVjaWZ5IG51bWJlciBvZiB0aW1lcyB0byBjb25kdWN0IHByb2Nlc3MgIA0KdHJpYWxzIDwtIC4uLg0KIyBjcmVhdGUgb2JqZWN0IGluIHdoaWNoIHRvIHN0b3JlIHNhbXBsZSBtZWFucyBvbmNlIHRoZXkgYXJlIGdlbmVyYXRlZA0Kbm9ybS5tZWFucyA8LSByZXAoMCwgdHJpYWxzKSAjIE5vdGUgbGVuZ3RoIGlzIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgdHJpYWxzDQojIFJ1biBmb3IgbG9vcCAgDQpmb3IoaSBpbiAxOnRyaWFscyl7DQogICAgIyBSYW5kb21seSBnZW5lcmF0ZSBucyBzYW1wbGVzIGZyb20gdGhlIG5vcm1hbCBkaXN0cmlidXRpb24NCiAgICB4IDwtIHJub3JtKG5zKSANCiAgICAjIENvbXB1dGUgbWVhbiBvZiBzYW1wbGVzLCBzdG9yZSBpbiB0aGUgbm9ybS5tZWFucyBvYmplY3QsIGluIGl0aCBwb3NpdGlvbiANCiAgICBub3JtLm1lYW5zW2ldIDwtIG1lYW4oeCl9DQpgYGANCg0KT25jZSB5b3UgZmVlbCBjb25maWRlbnQgaW4geW91ciB1bmRlcnN0YW5kaW5nIG9mIHRoaXMgY29kZSwgcmVwbGFjZSB0aGUgYC4uLmAgbWlzc2luZyBkZXRhaWxzIGZvciBgbnNgIGFuZCBgdHJpYWxzYCwgdXNpbmcgdGhlIGZvbGxvd2luZyBkZXRhaWxzOg0KDQoqIFlvdSB3YW50IHRvIHRha2UgMTAsMDAwIHNhbXBsZXMgb2YgcmFuZG9tbHkgZ2VuZXJhdGVkIHZhbHVlcyBmcm9tIHRoZSBzdGFuZGFyZCBOb3JtYWwgZGlzdHJpYnV0aW9uLg0KKiBFYWNoIHNhbXBsZSBzaG91bGQgaGF2ZSBhIHNhbXBsZSBzaXplIG9mIDUuDQoNCk9uY2UgeW91IGhhdmUgZmlsbGVkIGluIHRoZSBkZXRhaWxzLCBydW4geW91ciBjb2RlLg0KDQoqSGludDogSWYgeW91IGhhdmUgZ2l2ZW4gdGhpcyBhIGRlY2VudCBzaG90LCBidXQgYXJlIHN0dWNrLCB5b3UgY2FuIGNoZWNrIHRoZSBgQ29kZWAgY2h1bmsgYmVsb3c6Kg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIiwgZXZhbCA9IFQsIGVjaG8gPSBUfQ0KI1NwZWNpZnkgc2FtcGxlIHNpemUNCm5zIDwtIDUNCiMgU3BlY2lmeSBudW1iZXIgb2YgdGltZXMgdG8gY29uZHVjdCBwcm9jZXNzICANCnRyaWFscyA8LSAxMDAwMA0KIyBjcmVhdGUgb2JqZWN0IGluIHdoaWNoIHRvIHN0b3JlIHNhbXBsZSBtZWFucyBvbmNlIHRoZXkgYXJlIGdlbmVyYXRlZA0Kbm9ybS5tZWFucyA8LSByZXAoMCwgdHJpYWxzKSAjIE5vdGUgbGVuZ3RoIGlzIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgdHJpYWxzDQojIFJ1biBmb3IgbG9vcCAgDQpmb3IoaSBpbiAxOnRyaWFscyl7DQogICAgIyBSYW5kb21seSBnZW5lcmF0ZSBucyBzYW1wbGVzIGZyb20gdGhlIG5vcm1hbCBkaXN0cmlidXRpb24NCiAgICB4IDwtIHJub3JtKG5zKSANCiAgICAjIENvbXB1dGUgbWVhbiBvZiBzYW1wbGVzLCBzdG9yZSBpbiB0aGUgbm9ybS5tZWFucyBvYmplY3QsIGluIGl0aCBwb3NpdGlvbiANCiAgICBub3JtLm1lYW5zW2ldIDwtIG1lYW4oeCl9DQpgYGANCg0KIyMgeyN2aXp9DQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIFRvIHZpc3VhbGlzZSBvdXIgcmVzdWx0cywgd2UgY2FuIHVzZSB0aGUgZm9sbG93aW5nIGNvZGU6DQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IFR9DQpoaXN0KG5vcm0ubWVhbnMsIGZyZXEgPSBGQUxTRSwgYnJlYWtzID0gMjAsIGNvbCA9ICJyZWQiLCANCiAgICAgeGxpbSA9IGMoLTMsIDMpLA0KICAgICB4bGFiID0gZXhwcmVzc2lvbihiYXIoeCkpLA0KICAgICBtYWluID0gcGFzdGUoIkhpc3RvZ3JhbSBvZiBtZWFucywgbiA9ICIsIG5zKSkgDQpgYGANCg0KV2UgY2FuIGFsc28gb3ZlcmxheSBhIG5vcm1hbCBkZW5zaXR5IGN1cnZlLCB0aGF0LCBzaW5jZSBvdXIgdW5kZXJseWluZyBkYXRhIGlzIG5vcm1hbCwNCndpbGwgcmVmbGVjdCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBzYW1wbGUgbWVhbi4gDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IFR9ICANCmN1cnZlKGRub3JtKHgsIA0KICAgICAgbWVhbiA9IDAsIHNkID0gMS9zcXJ0KG5zKSksIA0KICAgICAgYWRkID0gVFJVRSwgY29sID0gImJsdWUiLCBsd2QgPSAyKSANCmBgYA0KDQpSdW4gdGhlc2UgY29kZSBjaHVua3Mgbm93LCBhbmQgY2hlY2sgeW91ciByZXN1bHRzLiBBcmUgb3VyIHNpbXVsYXRlZCBzYW1wbGUgbWVhbnMgY2xvc2UgdG8gdGhlIHBvcHVsYXRpb24gbWVhbiBvZiAwPw0KDQojIw0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYFJlcGVhdCBzdGVwcyBcQHJlZihzaW0pIGFuZCBcQHJlZih2aXopLCB1c2luZyBhIHNhbXBsZSBvZiAzMCBpbnN0ZWFkIG9mIDUuIFdoYXQgZG8geW91IG5vdGljZSBhYm91dCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBzaW11bGF0ZWQgc2FtcGxlIG1lYW5zPw0KDQo8YnI+DQoNCjxkZXRhaWxzPg0KICA8c3VtbWFyeT5gciBlbW86OmppKCJoZWFkcGhvbmVzIilgICoqT25saW5lIHN0dWRlbnRzKio8L3N1bW1hcnk+DQpgciBlbW86OmppKCJzcGVlY2hfYmFsbG9vbiIpYCAgTGVhdmUgYSBjb21tZW50IGluIHRoZSBjaGF0IGFib3V0IHRoZSBjaGFuZ2VzIHlvdSBvYnNlcnZlIGluIHRoZSBkaXN0cmlidXRpb24sIGNoYW5naW5nIGZyb20gJG49NSQgdG8gJG49MzAkLg0KPC9kZXRhaWxzPiANCg0KPGJyPg0KDQojIw0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYCBGaW5hbGx5LCByZXBlYXQgc3RlcHMgXEByZWYoc2ltKSBhbmQgXEByZWYodml6KSwgdXNpbmcgYSBzYW1wbGUgb2YgNjAuIFdoYXQgZG8geW91IG5vdGljZSBhYm91dCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBzaW11bGF0ZWQgc2FtcGxlIG1lYW5zIG5vdz8NCg0KPGJyPg0KDQo8ZGV0YWlscz4NCiAgPHN1bW1hcnk+YHIgZW1vOjpqaSgiaGVhZHBob25lcyIpYCAqKk9ubGluZSBzdHVkZW50cyoqPC9zdW1tYXJ5Pg0KYHIgZW1vOjpqaSgic3BlZWNoX2JhbGxvb24iKWAgIExlYXZlIGEgY29tbWVudCBpbiB0aGUgY2hhdCBhYm91dCB0aGUgY2hhbmdlcyB5b3Ugb2JzZXJ2ZSBpbiB0aGUgZGlzdHJpYnV0aW9uLCBjaGFuZ2luZyBmcm9tICRuPTMwJCB0byAkbj02MCQuDQo8L2RldGFpbHM+IA0KDQo8YnI+DQoNCiMgQ0xUIFNpbXVsYXRpb24gLSBFeHBvbmVudGlhbCBEaXN0cmlidXRpb24NCg0KYHIgZW1vOjpqaSgiY29tcHV0ZXIiKWAgVG8gZGVtb25zdHJhdGUgdGhlIHZlcnNhdGlsaXR5IG9mIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0sIGxldCdzIGNhcnJ5IG91dCBzb21lIHNpbXVsYXRpb25zIGludm9sdmluZyBkYXRhIGdlbmVyYXRlZCBmcm9tIHRoZSAqKkV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbioqLCB3aGljaCAodW5saWtlIHRoZSBOb3JtYWwgZGlzdHJpYnV0aW9uKSBpcyBoaWdobHkgc2tld2VkIChpLmUuIGFzeW1tZXRyaWMpLiANCg0KIyMgeyNleHBzaW1zdGFydH0NCg0KYHIgZW1vOjpqaSgiY29tcHV0ZXIiKWAgUmVjYWxsIGZyb20gW1RvcGljIDNdKGh0dHBzOi8vYm9va2Rvd24ub3JnL2Ffc2hha2VyL1NUTTEwMDFfVG9waWNfMy81LW90aGVyLWNvbnRpbnVvdXMtZGlzdHJpYnV0aW9ucy5odG1sKSB0aGF0IHRoZSBFeHBvbmVudGlhbCBkaXN0cmlidXRpb24gaXMgZGVmaW5lZCBieSBvbmUgcGFyYW1ldGVyLCBrbm93biBhcyB0aGUgKnJhdGUgcGFyYW1ldGVyKi4gVGhlIHJhdGUgcGFyYW1ldGVyIGlzIGRlbm90ZWQgYnkgdGhlIEdyZWVrIGxldHRlciAkXGxhbWJkYSQuIA0KDQpJZiBhIHJhbmRvbSB2YXJpYWJsZSAkWCQgZm9sbG93cyBhbiBFeHBvbmVudGlhbCBkaXN0cmlidXRpb24gd2l0aCByYXRlIHBhcmFtZXRlciAkXGxhbWJkYSQsIHdlIHdyaXRlICRYXHNpbSBFeHAoXGxhbWJkYSkkLg0KDQpTdXBwb3NlIG5vdyB0aGF0IG91ciByYW5kb20gdmFyaWFibGUgJFgkIGZvbGxvd3MgYW4gZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uIHdpdGggcmF0ZSBwYXJhbWV0ZXIgJFxsYW1iZGEgPSAxMCQuIEluIG90aGVyIHdvcmRzLCBzdXBwb3NlICRYIFxzaW0gXHRleHR7RXhwfSgxMCkkLg0KDQpXZSBjYW4gZ2VuZXJhdGUgYSBzYW1wbGUgb2YgMTAwIG9ic2VydmF0aW9ucyBmcm9tIHRoaXMgZGlzdHJpYnV0aW9uIHVzaW5nIHRoZSBmb2xsb3dpbmcgUiBjb2RlOg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IFQsIGVjaG8gPSBUfQ0Kc2V0LnNlZWQoMSkNCm4gPC0gMTAwDQpyYXRlID0gMTANCnggPC0gcmV4cChuLCByYXRlID0gcmF0ZSkNCmBgYA0KDQoqTm90ZSB0aGF0IHdlIHVzZSBgcmV4cGAgdG8gcmFuZG9tbHkgZ2VuZXJhdGUgdmFsdWVzIGZyb20gdGhlIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiwgaW5zdGVhZCBvZiB1c2luZyBgcm5vcm1gICh3aGljaCBpcyBmb3IgdGhlIG5vcm1hbCBkaXN0cmlidXRpb24pLioNCg0KUnVuIHRoaXMgY29kZSBub3cuDQoNCiMjDQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIE91ciBnZW5lcmF0ZWQgZGF0YSBmcm9tIFxAcmVmKGV4cHNpbXN0YXJ0KSBpcyBoaWdobHkgc2tld2VkLCBhbmQgY2xlYXJseSBkaWZmZXJlbnQgdG8gZGF0YSBnZW5lcmF0ZWQgZnJvbSB0aGUgc3ltbWV0cmljIG5vcm1hbCBkaXN0cmlidXRpb24uIFRoaXMgZGlzcGFyaXR5IGNhbiBiZSBzZWVuIGluIEZpZ3VyZSAzLjEgYmVsb3csIHdoaWNoIHNob3dzIGEgaGlzdG9ncmFtIG9mIHRoZSBkYXRhLCB3aXRoIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBwcm9iYWJpbGl0eSBkZW5zaXR5IGN1cnZlIG92ZXJsYWlkIGluIGJsdWUgKHNpbWlsYXIgdG8gaW4gXEByZWYoYmFzZWhpc3QpKSwgYmFzZWQgb24gYXBwcm9wcmlhdGUgbWVhbiBhbmQgdmFyaWFuY2UgdmFsdWVzLg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IFQsIGVjaG8gPSBGLCBmaWcuZGltID0gYyg2LDYpLCBmaWcuY2FwID0gIkRhdGEgZ2VuZXJhdGVkIGZyb20gYW4gRXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uLCB3aXRoIGEgbm9ybWFsIGN1cnZlIG92ZXJsYWlkLiJ9DQpoaXN0KHgsIGZyZXEgPSBGQUxTRSwgY29sID0gImNoYXJ0cmV1c2UzIiwgeGxpbSA9IGMoMCwgMC41KSwNCiAgICAgbWFpbiA9IHBhc3RlKCJIaXN0b2dyYW0gb2YgcmFuZG9tIHNhbXBsZSBcbiBmcm9tIEV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiwgbiA9ICIsIG4pKQ0KY3VydmUoZG5vcm0oeCwgMS9yYXRlLCAxL3JhdGUpLCBhZGQgPSBUUlVFLCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIpDQpgYGANCg0KDQpDbGVhcmx5LCB3ZSBjYW5ub3QgZml0IGEgbm9ybWFsIGN1cnZlIHdlbGwgdG8gZGF0YSBnZW5lcmF0ZWQgZnJvbSBhbiBFeHBvbmVudGlhbCBkaXN0cmlidXRpb24uIEhvd2V2ZXIsIGFzIHdlIHdvcmsgdGhyb3VnaCB0aGlzIHF1ZXN0aW9uLCB3ZSB3aWxsIGZpbmQgdGhhdCB3aGVuIHdlIG1vZGVsIHRoZSAqKmRpc3RyaWJ1dGlvbiBvZiB0aGUgc2FtcGxlIG1lYW5zKiogb2YgZGF0YSBnZW5lcmF0ZWQgZnJvbSBhbiBFeHBvbmVudGlhbCBkaXN0cmlidXRpb24sIHRoaXMgZGlzdHJpYnV0aW9uIG9mIHNhbXBsZSBtZWFucyAqKmNhbioqIGJlIGZpdHRlZCB3ZWxsIGJ5IGEgbm9ybWFsIGN1cnZlLCBlc3BlY2lhbGx5IGFzIG91ciBzYW1wbGUgc2l6ZSBpbmNyZWFzZXMuIFRoaXMgKHNvbWV3aGF0IHVuaW50dWl0aXZlKSByZXN1bHQgaXMgZHVlIHRvIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0hDQoNCiMjIFRoZSBSYXRlIFBhcmFtZXRlciBhbmQgUG9wdWxhdGlvbiBNZWFuDQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIEluc3RlYWQgb2YgY29uc2lkZXJpbmcgdGhlIGluZGl2aWR1YWwgZGF0YSBwb2ludHMgZ2VuZXJhdGVkIGZyb20gdGhlIEV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiwgbGV0J3Mgc2hpZnQgb3VyIGZvY3VzIHRvIHRoZSBzYW1wbGUgbWVhbiBvZiB0aGVzZSBkYXRhIHBvaW50cy4NCg0KRm9yIGRhdGEgZ2VuZXJhdGVkIGZyb20gYW4gRXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uLCB0aGUgcG9wdWxhdGlvbiBtZWFuICRcbXUkIGlzIGluIHRoZW9yeSBlcXVhbCB0byAxIGRpdmlkZWQgYnkgdGhlIHJhdGUgcGFyYW1ldGVyICRcbGFtYmRhJC4gSS5lLiwgZm9yICRYXHNpbSBFeHAoXGxhbWJkYSkkLCB0aGUgcG9wdWxhdGlvbiBtZWFuIG9mICRYJCBlcXVhbHMgJFxmcmFjezF9e1xsYW1iZGF9JC4gDQoNCklmIHdlIGNoZWNrIHRoZSBzYW1wbGUgbWVhbiBvZiBgeGAsIHdlIGZpbmQgdGhhdCB0aGlzIGlzIGVxdWFsIHRvIGByIG1lYW4oeClgIC0gdGhpcyBzYW1wbGUgbWVhbiBpcyBxdWl0ZSBhIGdvb2QgZXN0aW1hdGUgb2YgdGhlIHBvcHVsYXRpb24gbWVhbiAoJFxtdSA9IDEvMTAgPSAwLjEkKSwgZ2l2ZW4gdGhlIHRoZW9yeS4NCg0KIyMgeyNleHBzaW19DQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIExldCB1cyBub3cgY29uZHVjdCB0aGUgc2ltdWxhdGlvbiBwcm9jZXNzIHVzZWQgaW4gXEByZWYoc2ltKSwgZm9yIG91ciBkYXRhIHNhbXBsZWQgZnJvbSAkWCBcc2ltIFx0ZXh0e0V4cH0oMTApJC4NCg0KVXNpbmcgdGhlIGNvZGUgaW4gXEByZWYoc2ltKSBhcyBhIGd1aWRlLCBzaW11bGF0ZSAxMCwwMDAgc2FtcGxlIG1lYW5zIG9mICRYJCwgdXNpbmcgc2FtcGxlcyBvZiBzaXplIDUuDQoNClBsb3QgeW91ciByZXN1bHRzLCB1c2luZyB0aGUgY29kZSBpbiBcQHJlZih2aXopIGFzIGEgZ3VpZGUuDQoNCipOb3RlOiBZb3Ugd2lsbCBoYXZlIHRvIGNoYW5nZSB0aGUgeC1heGlzIHJhbmdlIGZvciB0aGUgaGlzdG9ncmFtICh2aWEgdGhlIGB4bGltYCBhcmd1bWVudCkuIFRyeSB1c2luZyBhIHJhbmdlIG9mIDAgdG8gMC40LioNCg0KKk5vdGUgMjogVXNlIHRoZSBjb2RlIGluIHRoZSBgQ29kZWAgY2h1bmsgYmVsb3cgdG8gb3ZlcmxheSB0aGUgYXBwcm9wcmlhdGUgTm9ybWFsIGRpc3RyaWJ1dGlvbiBwcm9iYWJpbGl0eSBkZW5zaXR5IGN1cnZlOioNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVH0NCmN1cnZlKGRub3JtKHgsIG1lYW4gPSAxL3JhdGUsIHNkID0gMS9yYXRlL3NxcnQobnMpKSwgYWRkID0gVFJVRSwNCiAgICAgICAgY29sID0gImJsdWUiLCBsd2QgPSAyKQ0KYGBgDQoNCiMjDQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIFdoYXQgZG8geW91IG5vdGljZSBhYm91dCB5b3VyIHJlc3VsdGFudCBwbG90Pw0KDQojIw0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYCBSZXBlYXRzIFxAcmVmKGV4cHNpbSkgZm9yICRYIFxzaW0gRXhwKDEwKSQsIHVzaW5nIGEgc2FtcGxlIG9mIDMwIGluc3RlYWQgb2YgNS4gV2hhdCBkbyB5b3Ugbm90aWNlIGFib3V0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHNpbXVsYXRlZCBzYW1wbGUgbWVhbnM/DQoNCjxicj4NCg0KPGRldGFpbHM+DQogIDxzdW1tYXJ5PmByIGVtbzo6amkoImhlYWRwaG9uZXMiKWAgKipPbmxpbmUgc3R1ZGVudHMqKjwvc3VtbWFyeT4NCmByIGVtbzo6amkoInNwZWVjaF9iYWxsb29uIilgICBMZWF2ZSBhIGNvbW1lbnQgaW4gdGhlIGNoYXQgYWJvdXQgdGhlIGNoYW5nZXMgeW91IG9ic2VydmUgaW4gdGhlIGRpc3RyaWJ1dGlvbiwgY2hhbmdpbmcgZnJvbSAkbj01JCB0byAkbj0zMCQuDQo8L2RldGFpbHM+IA0KDQo8YnI+DQoNCiMjDQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIEZpbmFsbHksIHJlcGVhdCBcQHJlZihleHBzaW0pIGZvciAkWCBcc2ltIEV4cCgxMCkkLCB1c2luZyBhIHNhbXBsZSBvZiA2MC4gV2hhdCBkbyB5b3Ugbm90aWNlIGFib3V0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHNpbXVsYXRlZCBzYW1wbGUgbWVhbnMgbm93Pw0KDQo8YnI+DQoNCjxkZXRhaWxzPg0KICA8c3VtbWFyeT5gciBlbW86OmppKCJoZWFkcGhvbmVzIilgICoqT25saW5lIHN0dWRlbnRzKio8L3N1bW1hcnk+DQpgciBlbW86OmppKCJzcGVlY2hfYmFsbG9vbiIpYCAgTGVhdmUgYSBjb21tZW50IGluIHRoZSBjaGF0IGFib3V0IHRoZSBjaGFuZ2VzIHlvdSBvYnNlcnZlIGluIHRoZSBkaXN0cmlidXRpb24sIGNoYW5naW5nIGZyb20gJG49MzAkIHRvICRuPTYwJC4NCjwvZGV0YWlscz4gDQoNCjxicj4NCg0KIyBDTFQgU2ltdWxhdGlvbiAtIEJlcm5vdWxsaSBEaXN0cmlidXRpb24NCg0KYHIgZW1vOjpqaSgiY29tcHV0ZXIiKWAgQXMgZGlzY3Vzc2VkIGluIFtTZWN0aW9uIDMuMyBvZiBUb3BpYyA0XShodHRwczovL2Jvb2tkb3duLm9yZy9jb250ZW50Lzg4ZWY5YjdjLTU4MzMtNGE3MC04NGYyLTkzNDcwOTU3ZDFmOS8zLTMtY2x0LXNpbXVsYXRlZC1leGFtcGxlLXdpdGgtYmVybm91bGxpLWRpc3RyaWJ1dGVkLXBvcHVsYXRpb24uaHRtbCksIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gZXZlbiBhcHBsaWVzIHRvIGRpc2NyZXRlIHJhbmRvbSB2YXJpYWJsZXMuDQoNClN1cHBvc2UgdGhhdCBvdXIgcmFuZG9tIHZhcmlhYmxlICRYJCBub3cgZm9sbG93cyBhIEJlcm5vdWxsaSBkaXN0cmlidXRpb24gd2l0aCBzdWNjZXNzIHBhcmFtZXRlciAkcCA9IDAuMyQuIEluIG90aGVyIHdvcmRzLCBzdXBwb3NlICRYIFxzaW0gXHRleHR7QkVSTn0oMC4zKSQuDQoNCiMjDQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIElmIHdlIGdlbmVyYXRlIGEgc2FtcGxlIG9mIDEwMCBvYnNlcnZhdGlvbnMgZnJvbSB0aGlzIGRpc3RyaWJ1dGlvbiAoc2VlIHRoZSBSIGNvZGUgYmVsb3cpIGFuZCB0aGVuIHZpc3VhbGlzZSBvdXIgZ2VuZXJhdGVkIGRhdGEsIHdlIHNlZSBhIHJvdWdobHkgNzAvMzAgc3BsaXQgb2Ygb2JzZXJ2YXRpb25zIGJldHdlZW4gJHg9MCQgYW5kICR4PTEkLiBDbGVhcmx5LCAoanVzdCBhcyBpbiB0aGUgRXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uIGNhc2UpLCB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBwcm9iYWJpbGl0eSBkZW5zaXR5IGN1cnZlLCB3aXRoIGFwcHJvcHJpYXRlIHBhcmFtZXRlciBzcGVjaWZpY2F0aW9ucywgKHNob3duIGluIGJsdWUpLCBpcyBhbiBleHRyZW1lbHkgcG9vciBmaXQgZm9yIHRoaXMgZGF0YS4NCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVH0NCnNldC5zZWVkKDEpDQpuIDwtIDEwMA0KcCA9IDAuMw0KeCA8LSByYmlub20obiwgMSwgcCkNCmBgYA0KDQoqTm90ZSB0aGF0IHdlIHVzZSBgcmJpbm9tYCB0byByYW5kb21seSBnZW5lcmF0ZSB2YWx1ZXMgZnJvbSB0aGUgQmVybm91bGxpIGRpc3RyaWJ1dGlvbiwgaW5zdGVhZCBvZiB1c2luZyBgcm5vcm1gICh3aGljaCBpcyBmb3IgdGhlIG5vcm1hbCBkaXN0cmlidXRpb24pLioNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gRn0NCmhpc3QoeCwgZnJlcSA9IEZBTFNFLCBjb2wgPSAiY2hhcnRyZXVzZTMiLCB4bGltID0gYygwLCAxKSwNCiAgICAgbWFpbiA9IHBhc3RlKCJIaXN0b2dyYW0gb2YgcmFuZG9tIHNhbXBsZSBcbiBmcm9tIEJlcm5vdWxsaSBkaXN0cmlidXRpb24sIG4gPSAiLCBuKSkgDQpjdXJ2ZShkbm9ybSh4LCBwLCBzZCA9IHNxcnQocCooMSAtIHApKSksIGFkZCA9IFRSVUUsIGNvbCA9ICJibHVlIiwgbHdkID0gMikNCmBgYA0KDQojIw0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYCBIb3dldmVyLCBkZXNwaXRlIG91ciBkYXRhIGJlaW5nIGdlbmVyYXRlZCBmcm9tIGEgZGlzY3JldGUgZGlzdHJpYnV0aW9uLCB3ZSBjYW4gc3RpbGwgdXNlIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gdG8gb2J0YWluIGFuIGFjY3VyYXRlIGVzdGltYXRlIG9mIHRoZSBwb3B1bGF0aW9uIG1lYW4gYnkgY29uc2lkZXJpbmcgdGhlIGRpc3RyaWJ1dGlvbiBvZiAkXGJhcntYfSQhDQoNCkxldCB1cyBub3cgY29uZHVjdCB0aGUgc2ltdWxhdGlvbiBwcm9jZXNzIHVzZWQgaW4gXEByZWYoc2ltKSwgZm9yIG91ciBCZXJub3VsbGktZGlzdHJpYnV0ZWQgZGF0YS4NCg0KVXNpbmcgdGhlIGNvZGUgaW4gXEByZWYoc2ltKSBhcyBhIGd1aWRlLCBzaW11bGF0ZSAxMDAwMCBzYW1wbGUgbWVhbnMgb2YgJFgkLCB1c2luZyBzYW1wbGVzIG9mIHNpemUgNS4NClRoZW4sIHBsb3QgeW91ciByZXN1bHRzLCB1c2luZyB0aGUgY29kZSBpbiBcQHJlZih2aXopIGFzIGEgZ3VpZGUuDQoNCipOb3RlOiBZb3Ugd2lsbCBoYXZlIHRvIGNoYW5nZSB0aGUgeC1heGlzIHJhbmdlIGZvciB0aGUgaGlzdG9ncmFtICh2aWEgdGhlIGB4bGltYCBhcmd1bWVudCkuKg0KDQoqTm90ZSAyOiBVc2UgdGhlIGNvZGUgaW4gdGhlIGBDb2RlYCBjaHVuayBiZWxvdyB0byBvdmVybGF5IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBwcm9iYWJpbGl0eSBkZW5zaXR5IGN1cnZlIHdpdGggdGhlIGFwcHJvcHJpYXRlIHBhcmFtZXRlciBzcGVjaWZpY2F0aW9uczoqDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IFR9DQojIFNldCBtdSBhbmQgc2lnbWEgZm9yIHRoZSBhcHByb3hpbWF0aW5nIG5vcm1hbCBkaXN0cmlidXRpb24NCm11IDwtIHANCnNpZ21hIDwtIHNxcnQocCooMSAtIHApKQ0KIyBPdmVybGF5IHRoZSBub3JtYWwgZGVuc2l0eQ0KY3VydmUoZG5vcm0oeCwgbXUsIHNpZ21hL3NxcnQobnMpKSwgYWRkID0gVFJVRSwgY29sID0gImJsdWUiLCBsd2QgPSAyKQ0KYGBgDQoNCiMjDQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIFdoYXQgZG8geW91IG5vdGljZSBhYm91dCB5b3VyIHJlc3VsdGFudCBwbG90Pw0KDQojIw0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYCBSZXBlYXQgXEByZWYoZXhwc2ltKSBmb3IgJFggXHNpbSBCRVJOKDAuMykkLCB1c2luZyBhIHNhbXBsZSBvZiAzMCBpbnN0ZWFkIG9mIDUuIFdoYXQgZG8geW91IG5vdGljZSBhYm91dCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBzaW11bGF0ZWQgc2FtcGxlIG1lYW5zPw0KDQo8YnI+DQoNCjxkZXRhaWxzPg0KICA8c3VtbWFyeT5gciBlbW86OmppKCJoZWFkcGhvbmVzIilgICoqT25saW5lIHN0dWRlbnRzKio8L3N1bW1hcnk+DQpgciBlbW86OmppKCJzcGVlY2hfYmFsbG9vbiIpYCAgTGVhdmUgYSBjb21tZW50IGluIHRoZSBjaGF0IGFib3V0IHRoZSBjaGFuZ2VzIHlvdSBvYnNlcnZlIGluIHRoZSBkaXN0cmlidXRpb24sIGNoYW5naW5nIGZyb20gJG49NSQgdG8gJG49MzAkLg0KPC9kZXRhaWxzPiANCg0KPGJyPg0KDQojIw0KDQpgciBlbW86OmppKCJjb21wdXRlciIpYCBGaW5hbGx5LCByZXBlYXQgXEByZWYoZXhwc2ltKSBmb3IgJFggXHNpbSBCRVJOKDAuMykkLCB1c2luZyBhIHNhbXBsZSBvZiA2MC4gV2hhdCBkbyB5b3Ugbm90aWNlIGFib3V0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHNpbXVsYXRlZCBzYW1wbGUgbWVhbnMgbm93Pw0KDQo8YnI+DQoNCjxkZXRhaWxzPg0KICA8c3VtbWFyeT5gciBlbW86OmppKCJoZWFkcGhvbmVzIilgICoqT25saW5lIHN0dWRlbnRzKio8L3N1bW1hcnk+DQpgciBlbW86OmppKCJzcGVlY2hfYmFsbG9vbiIpYCAgTGVhdmUgYSBjb21tZW50IGluIHRoZSBjaGF0IGFib3V0IHRoZSBjaGFuZ2VzIHlvdSBvYnNlcnZlIGluIHRoZSBkaXN0cmlidXRpb24sIGNoYW5naW5nIGZyb20gJG49MzAkIHRvICRuPTYwJC4NCjwvZGV0YWlscz4gDQoNCjxicj4NCg0KIyBFeHRlbnNpb246IEF2ZXJhZ2UgRGlhbW9uZCBQcmljZXMNCg0KYHIgZW1vOjpqaSgiY29tcHV0ZXIiKWAgTGV0J3MgY29uc2lkZXIgaG93IHdlIGNhbiBhcHBseSB0aGUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtIHRvIHJlYWwgZGF0YS4NCg0KRm9yIHRoaXMgcXVlc3Rpb24sIHdlIHdpbGwgY29uc2lkZXIgZGF0YSBvbiBhcHByb3hpbWF0ZWx5IDU0LDAwMCByb3VuZCBjdXQgZGlhbW9uZHMuIFRoaXMgZGF0YSBpcyBzdG9yZWQgaW4gdGhlIGBkaWFtb25kc2AgZGF0YSBzZXQgaW4gdGhlIGBnZ3Bsb3QyYCBSIHBhY2thZ2UuIFdlIHdpbGwgdHJlYXQgdGhpcyBkYXRhIGFzIHRoZSBwb3B1bGF0aW9uIGRhdGEuDQoNCkluc3RhbGwgYW5kIGxvYWQgdGhlIGBnZ3Bsb3QyYCBSIHBhY2thZ2Ugbm93Lg0KDQoqSGludDogSWYgeW91IG5lZWQgYSByZWZyZXNoZXIgb24gaW5zdGFsbGluZyBhbmQgbG9hZGluZyBwYWNrYWdlcyBpbiBSLCBjaGVjayB0aGUgYENvZGVgIGNodW5rIGJlbG93OioNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSIsIGV2YWwgPSBGLCBlY2hvID0gVH0NCmluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KYGBgDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLWhpZGUiLCBldmFsID0gVCwgaW5jbHVkZSA9IEZ9DQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KIyMNCg0KYHIgZW1vOjpqaSgiY29tcHV0ZXIiKWAgSWYgd2UgcGxvdCB0aGUgcHJpY2Ugb2Ygcm91bmQgY3V0IGRpYW1vbmRzIHVzaW5nIGEgaGlzdG9ncmFtLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGRhdGEgaXMgY2xlYXJseSBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuDQoNCipNYWtlIHN1cmUgdG8gcnVuIHRoaXMgY29kZSBiZWZvcmUgY29udGludWluZy4qDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFR9DQpoaXN0KGRpYW1vbmRzJHByaWNlLCBjb2wgPSAic2t5Ymx1ZSIsIHhsYWIgPSAiRGlhbW9uZCBQcmljZSAoJCkiLA0KICAgICBtYWluID0gIkhpc3RvZ3JhbSBvZiBEaWFtb25kIFByaWNlcyAoJCkiLCBmcmVxID0gRikNCmBgYA0KDQojIyB7I2RpYW1vbmRzaW19DQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIFN1cHBvc2UgdGhhdCB5b3UgYXJlIGludGVyZXN0ZWQgaW4gZXN0aW1hdGluZyB0aGUgcG9wdWxhdGlvbiBtZWFuIHByaWNlIGZvciByb3VuZCBjdXQgZGlhbW9uZHMsIGJ1dCBkbyBub3QgaGF2ZSBhY2Nlc3MgdG8gdGhlIGZ1bGwgYGRpYW1vbmRzYCBkYXRhIHNldC4NCg0KSW5zdGVhZCwgeW91IGNhbiBvbmx5IHNhbXBsZSBwcmljZXMgZm9yIDUgcm91bmQgY3V0IGRpYW1vbmRzIGF0IGEgdGltZSwgcmVwcmVzZW50ZWQgYnkgdGhlIGNvZGUgYmVsb3c6DQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFR9DQp4IDwtIHNhbXBsZShkaWFtb25kcyRwcmljZSwgNSkNCmBgYA0KDQpVc2luZyB0aGlzIGNvZGUgYW5kIHRoZSBjb2RlIGluIFxAcmVmKHNpbSkgYXMgYSBndWlkZSwgb2J0YWluIDEwMCBzYW1wbGUgbWVhbnMgZnJvbSAxMDAgc2ltdWxhdGVkIHNhbXBsZXMgb2YgNSByYW5kb20gcm91bmQgY3V0IGRpYW1vbmQgc2FsZSBwcmljZXMuIFBsb3QgYSBoaXN0b2dyYW0gb2YgdGhlc2Ugc2FtcGxlIG1lYW5zLiBXaGF0IGRvIHlvdSBvYnNlcnZlPw0KDQo8YnI+DQoNCjxkZXRhaWxzPg0KICA8c3VtbWFyeT5gciBlbW86OmppKCJoZWFkcGhvbmVzIilgICoqT25saW5lIHN0dWRlbnRzKio8L3N1bW1hcnk+DQpgciBlbW86OmppKCJzcGVlY2hfYmFsbG9vbiIpYCAgVm9sdW50ZWVyIHRvIHNoYXJlIHlvdXIgc2NyZWVuIHRvIHNob3cgeW91ciBoaXN0b2dyYW0gYW5kIGRpc2N1c3MgeW91ciByZXN1bHRzLCBpZiB5b3UgZ290IHRvIHRoaXMgc3RhZ2UgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIGxhYi4NCjwvZGV0YWlscz4gDQoNCjxicj4NCg0KIyMgeyNkaWFtb25kc2ltbGFyZ2V9DQoNCmByIGVtbzo6amkoImNvbXB1dGVyIilgIFJlcGVhdCBcQHJlZihkaWFtb25kc2ltKSwgYnV0IHRoaXMgdGltZSBzdXBwb3NlIHRoYXQgeW91IGFyZSBhYmxlIHRvIHRha2Ugc2FtcGxlcyBvZiAzMCBkaWFtb25kcyBhdCBhIHRpbWUsIGluc3RlYWQgb2YgNS4gV2hhdCBjaGFuZ2VzIGRvIHlvdSBvYnNlcnZlPyANCg0KPGJyPg0KDQojIyMjIEdyZWF0IGpvYiwgdGhhdCdzIGV2ZXJ5dGhpbmcgZm9yIHRvZGF5ISAjIyMjIHstfQ0KDQpIb3BlZnVsbHksIHRoaXMgY29tcHV0ZXIgbGFiIGhhcyBoZWxwZWQgY2VtZW50IHlvdXIgdW5kZXJzdGFuZGluZyBvZiB0aGUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtLg0KDQo8YnI+DQoNCiMgUmVmZXJlbmNlcyB7LSAjUmVmfQ0KPGRpdiBpZD0icmVmcyI+PC9kaXY+DQoNCjxicj4NCg0KPGZvbnQgY29sb3IgPSAiZ3JleSI+DQpUaGVzZSBub3RlcyBoYXZlIGJlZW4gcHJlcGFyZWQgYnkgUnVwZXJ0IEt1dmVrZSBhbmQgQW1hbmRhIFNoYWtlci4gVGhlIGNvcHlyaWdodCBmb3IgdGhlIG1hdGVyaWFsIGluIHRoZXNlIG5vdGVzIHJlc2lkZXMgd2l0aCB0aGUgYXV0aG9ycyBuYW1lZCBhYm92ZSwgd2l0aCB0aGUgRGVwYXJ0bWVudCBvZiBNYXRoZW1hdGljYWwgYW5kIFBoeXNpY2FsIFNjaWVuY2VzIGFuZCB3aXRoIExhIFRyb2JlIFVuaXZlcnNpdHkuIENvcHlyaWdodCBpbiB0aGlzIHdvcmsgaXMgdmVzdGVkIGluIExhIFRyb2JlIFVuaXZlcnNpdHkgaW5jbHVkaW5nIGFsbCBMYSBUcm9iZSBVbml2ZXJzaXR5IGJyYW5kaW5nIGFuZCBuYW1pbmcuIFVubGVzcyBvdGhlcndpc2Ugc3RhdGVkLCBtYXRlcmlhbCB3aXRoaW4gdGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVyIGEgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob24gQ29tbWVyY2lhbC1Ob24gRGVyaXZhdGl2ZXMgTGljZW5zZSANCjxhIGhyZWYgPSAiaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLW5kLzQuMC9DQyIgdGFyZ2V0PSJfYmxhbmsiPiBCWS1OQy1ORC4gPC9hPg0KPC9mb250Pg==