Assignment Objectives

  • Understand the theoretical basis of Bootstrap sampling methods for approximating sampling distributions.

  • Assess the performance of Bootstrap sampling distributions against exact and asymptotic sampling distributions.

  • Implement Bootstrap sampling algorithm and construct sampling distributions using R.


Use of AI Tools

Policy on AI Tool Use: Students must adhere to the AI tool policy specified in the course syllabus. The direct copying of AI-generated content is strictly prohibited. All submitted work must reflect your own understanding; where external tools are consulted, content must be thoroughly rephrased and synthesized in your own words.

Code Inclusion Requirement: Any code included in your essay must be properly commented to explain the purpose and/or expected output of key code lines. Submitting AI-generated code without meaningful, student-added comments will not be accepted.


Asymptotic Distribution of Sample Variance

Assume that \(\{ x_1, x_2, \cdots, x_n \} \to F(x)\) with \(\mu = E[X]\) and \(\sigma^2 = \text{var}(X)\). Denote

\[ s^2 = \frac{1}{n-1}\sum_{i=1}^n (x_i - \mu)^2 \]

If \(n\) is large,

\[ s^2 \to N\left(\sigma^2, \frac{\mu_4-\sigma^4}{n} \right) \]

where \(\mu_4 = E[(X_i - \mu)^4]\) is tje 4th central moment which can be estimated by

\[ \hat{\mu}_4 = \frac{1}{n}\sum_{i=1}^n(x_i-\bar{x})^4. \]

Note: This describes the asymptotic convergence of the sample variance, following from the central limit theorem (CLT). The sample size required for this approximation to hold is situation-dependent.


Question 1: Asymptotic vs Bootstrap Sampling Distributions

Write an essay summarizing the concepts of Asymptotic and Bootstrap Sampling Distributions, along with their key applications. Your discussion should be grounded in your personal understanding of the material. Any external sources including AI tools consulted must be clearly cited.

Essay Prompt: Discuss the concepts of the bootstrap sampling plan, the bootstrap sampling distribution, and the asymptotic sampling distribution in the context of statistics (e.g., sample mean and variance) computed from an independent and identically distributed (i.i.d.) sample. Your discussion should:

  • Clearly outline the key assumptions required for each method.

  • Explain the practical application of each distribution.

  • Provide guidance on when and why one should be preferred over the other in statistical inference.


Asymptotic Sampling Distrubutions

We use sampling distributions when we want to make statistical inferences about the population. Often running statistics on the true population is extremely expensive, or impossible. Often the true population is unknown, so running statistics on the true population soley, is impractical. To compensate, often we take a random sample from our population of interest to make a statistical inference to the population. We assume our sample can provide us with information about the population.

An Asymptotic Sampling Distribution is an example of a type of sampling distribution we use to make statistical inferences about the population. When we use an asymptotic sampling distribution we assume a large sample size with an independently and identically distributed sample. We can use an underlining non-parametric or unknown population shape and standardize the normal distribution to approximate the distribution and parameters of interest for the samples collected.

We model raw collected datasets or samples with a Empirical Cumulative Distribution Function (ECDF). This is a distribution directly from observed sample data, with no inherently assumed shape about the sample or population distribution.

The asymptotic distribution converges to a normal distribution as the sample size increases, although we standardize each observation in the distribution to approximate a normal distribution to make inferences about the distribution using our normal distribution as a guide to do so using the following formulas:

When our standard deviation is known for the population, we standardize a Asymptotic Distribution using the formula $$

Z= _{} N(0, 1)

$$

When our standard deviation is not known for the population, we assume the standard deviation is approximately normally distributed (with a large sample size), we standardize a Asymptotic Distribution using the formula which happens to be a T-distrubution:

\[ T = \frac{\bar{X}-\mu}{S/\sqrt{n}} \overset{d}{\to} t_{n-1} \] We estimate the sample variance to apply to the T distribution which the \(\sqrt(S^2)\) can be placed in the T distribution formula.

\[ S^2 \stackrel{d}{\to} N\left(\sigma^2, \frac{\mu_4 - \sigma^4}{n}\right) \quad \text{as } n \to \infty, \] When our distribution is subset with a proportion (Bernoulli Random Variable), we a Asymptotic Distribution standardize using the formula \[ Z_n = \frac{\hat{p}_n - p}{\sqrt{\frac{p(1-p)}{n}}} \stackrel{d}{\to} N(0,1) \quad \text{as } n \to \infty \]

The Asymptotic Distribution is very valuable for approximating sample statistics for example, the sample statistic, mean can be approximated using the following formula where \(\mu_4 = E[(X_i - \mu)^4]\) is tje 4th central moment which can be estimated as:

$$ 4 = {i=1}n(x_i-{x})4.

$$ While our asymptotic distribution can make approximations on sample statistics, when distributions become more complex, for example paired observations, unbounded populations, and unknowns about the true population, direct computation of the asymptotic distributions can become incredibly complex and non-time efficient. Instead of direct computations and approximations for the distribution we can run simulations within the datasets we have to simulate and summary the statistics after repeated resamples to estimate a sample statistic (for example mean or variance) through the behavior seen through repeated measurements instead through direct computation. One way we demonstrate this simulated resampling is through Bootstrap Sampling Distributions.

Bootstrap Sampling Distrubutions

A bootstrap sampling distribution is a simulated approach into analyzing sample statistics (ig. mean, variance, etc.). Instead of organizing a distribution directly to derive one mean or other sample statistic, we repeatably sample (with replacement) from the originally collected sample to derived a variety of the sample statistic of interest values to compile and compute into a even more robust value for the sample statistic of interest.

We select a random sample from the true population. We use the collected random sample as a representative population to draw samples from. With this originally captured sample we take

We choose to randomly select random samples from the original random sample to compute a bootstrap samples statistic. We will ultimately use all the simulated bootstrap statistics to compute the statistic of interest onto the simulated bootstrap statistics.

Below is the simulation of a bootstrap statistic from an original dataset, to find a bootstrap distribution we can calculate a statistic from

#creating a simulated bootstrap

url = "https://pengdsci.github.io/STA506/w04/w02-wcuheights.txt"


height = read.table(url, header = TRUE) #the Population of the heights at west chester university 

original.sample = sample(height$Height, 81, replace = FALSE) #Take a random sample of the original population to act as the population proxy for our bootstrap

#our sample size is 81
# we do not need to replace our samples from the true population. We would like consistent values to repeatedly sample from for our bootstrap sampling

bt.sample.mean = NULL #create an empty vector to hold our sample into when we compute the bootstrap mean during our for loop

for(i in 1:1000)
{
  
  ith.bt.sample = x=sample(x=original.sample, size = 81, replace= TRUE) #take repeated samples from our original sample aka the sample acting as a proxy for our original population
  
  #our sample size is 81, the same size of the original population
  #we want to take values from this sample repeated so we do replace our samples 
  
  bt.sample.mean[i] = mean(ith.bt.sample)
  
  
}


hist(bt.sample.mean,
     breaks = 12,
     probability = TRUE,
     xlab = "Bootstrap sample means", #x axis lable
   main="Bootstrap Sampling Distribution \n of Sample Means Example",
          cex.main = 0.9,
       col.main = "darkgreen")   
lines(density(bt.sample.mean), col = "skyblue", lwd = 2)

The Bootstrap Sampling Distribution has value because it allows us to make inferences about a population based on a large independent identically distrubtued random sample in which we are unsure about the true population and most likely have complexity in the organization of our distribution. We may find value in using a bootstrap when

When we do not have complex attributes in our distribution a Asymptotic Distribution may be better fitted. A simulation may cause higher likelihood f type I error, due to the need to run more simulation tests

Assess the performance of Bootstrap sampling distributions against exact and asymptotic sampling distributions.

An exact distribution has similar qualities to an asymptotic distribution, although an exact distribution is specific to a small sample size, with a normally distributed sample that is an identically and interdependent samples distribution. In comparison to both exact and asymptotic distributions, a boot strap sampling distribution is valuable because we can simulate a distribution to reach a statistic for a distributions that would otherwise be too complex to model through parametric approximation. Although an exact test is small and a parametric test, at times an exact test may be more applicable if there are no complex distributions, a small sample size that does not meet the large sample size assumption of the Bootstrap Assumptions and there also be little need to approximate the distribution as the distribution already known. A Bootstrap sampling distribution may be more appropriate for complex asymptotic distributions with large sample sizes.

Question 2: Daily Coffee Sales (in mL) at Two Different Cafe Locations

This data set represents the volume of regular brewed coffee sold per day (in milliliters) at two different cafe locations over a period of 50 days.

2850, 3200, 2900, 3100, 2950, 7800, 8100, 7900, 3300, 3050, 4000, 4200, 3150, 3400, 7700, 8200, 
3250, 4400, 3100, 4200, 4500, 4800, 4300, 8500, 8200, 8900, 8700, 3250, 3000, 4600, 4100, 8400, 
8800, 3350, 4700, 3100, 8100, 3050, 8300, 4100, 3100, 8300, 8900, 8200, 4400, 4500, 3250, 4600, 
8400, 3300, 4200, 4500, 4800, 4300, 8500

We are interested in finding the sampling distribution of sample means that will be used for various inferences about the underlying population mean.

  1. Based on the given data, can the Central Limit Theorem be used to derive the asymptotic sampling distribution of the sample mean? Justify your answer.

The asymptotic sampling distribution allows a non-parametric approximation that uses the assumption that the larger the sample size the, greater the likelihood the sample mean will be normally distrusted. The Central Limit Theorem is a tool the asymptotic sampling distribution uses a as an approximation for the sampling distribution. In many cases both an asymptotic sampling distribution or bootstrap distribution can be used, although which is most accessible depends on the complexity of the distribution and parameter of interest. As this sampling distribution, does not look complex in regards to paired observation for example, the central limit theorem can be used because the sample we are assuming is our population is not normally distributed; the asymptotic sampling distribution does not assume shape of population, unlike the exact normal distribution.

This is the use of the central limit theory for the asymptotic distribution

coffees = c(2850, 3200, 2900, 3100, 2950, 7800, 8100, 7900, 3300, 3050, 4000, 4200, 3150, 3400, 7700, 8200, 3250, 4400, 3100, 4200, 4500, 4800, 4300, 8500, 8200, 8900, 8700, 3250, 3000, 4600, 4100, 8400, 8800, 3350, 4700, 3100, 8100, 3050, 8300, 4100, 3100, 8300, 8900, 8200, 4400, 4500, 3250, 4600, 8400, 3300, 4200, 4500, 4800, 4300, 8500)



s.coffee=sort(coffees) #sorting the dataset in increasing ordering

hist(s.coffee, main = "Histogram of Coffee Volume" )#bimodal distribution

#Building Z distribution to Approximate for Asymptotic sampling 
n_coffee=length(s.coffee) #sample size is 55
sd_coffee = sd(s.coffee) #standard deviation of sorted coffee

var_coffee = var(s.coffee) #calculating sample variance of coffee

se_coffee <- sd_coffee / sqrt(n_coffee) #standard error of coffee

mean.coffee=mean(s.coffee) #coffee mean is 5250

ecdf(s.coffee)
Empirical CDF 
Call: ecdf(s.coffee)
 x[1:32] =   2850,   2900,   2950,  ...,   8800,   8900
freq_coff=table(coffees)



my.ECDF <- function(indat, outx){
  # outx - a vector of given values
  freq.table <- table(indat)                          # frequency table
  uniq <- as.numeric(names(freq.table))          # unique data values
  rep.time <- as.vector(freq.table)                   # frequencies of the unique data values
  cum.rel.feq <- cumsum(rep.time)/sum(rep.time)       # cumulative relative frequencies: CDF
  cum.prob <- NULL
  for (i in 1:length(outx)){
    intvl.id <- which(uniq <= outx[i])      # identify the index meeting the condition
    cum.prob[i] <- cum.rel.feq[max(intvl.id)] # extract the cumulative prob according to CDF 
  }
  cum.prob             
}

plot(s.coffee, my.ECDF(indat = coffees, outx = s.coffee), type = "s",
     main = "ECDF of Coffee Volume",
     xlab = "Coffee Volume",
     ylab = "Cumulative Probability")

In the histogram of coffee volume the distribution is not normally distributed but, bimodal, meaning having two peaks. There is most likely a separation in our dataset that causes the volumes to sit in two different ‘subsets’.

Our coffee volume sample mean using the CLT approximation distribution is 5250 mL.

  1. Apply the bootstrap method to estimate the sampling distribution (often called the bootstrap sampling distribution) of the sample mean. Generate a kernel density estimate from the bootstrap sample means and plot it. Then, use this bootstrap distribution to validate your conclusion from part (a). Make sure your visuals are effective in enhancing the presentation of these results.
#Apply the bootstrap method to the sample mean
#Generate a kernel density estimate from the bootstrap and sample plot

#call the sample from the population
set.seed(142)

s.coffee
 [1] 2850 2900 2950 3000 3050 3050 3100 3100 3100 3100 3150 3200 3250 3250 3250
[16] 3300 3300 3350 3400 4000 4100 4100 4200 4200 4200 4300 4300 4400 4400 4500
[31] 4500 4500 4600 4600 4700 4800 4800 7700 7800 7900 8100 8100 8200 8200 8200
[46] 8300 8300 8400 8400 8500 8500 8700 8800 8900 8900
#create an  empty vector to calculate the bootstrap distribution mean in the for loop

s.coffee.vec.mean = NULL

#sample from the population

for(i in 1:1000)
{
 
ith.coffee.sample=sample(s.coffee, 55, replace= TRUE) #randomly select from original sample
#Our sample size is 55
#replace our sample each loop because we do not have a large sample

s.coffee.vec.mean[i] = mean(ith.coffee.sample) #calculated mean: 5207.273
  
}

kde = density(s.coffee.vec.mean, bw = sd_coffee)

#generate a kernel density estimate from the bootstrap from the sample means and plot it

hist(s.coffee.vec.mean, #datapoint aka statistic we just generated, we want to see its simulated distrubution
        probability = TRUE,  #identify the relative frequency (always say true)
        breaks = 14,
        xlab = "sample means of repeated samples", #label the x axis
        main= "Approximated Sampling Distrubution \n of Sample Means - Bootstrap Resampling",
     cex.main = 0.9,
     col.main = "darkgreen"
     )
lines(density(s.coffee.vec.mean, kernel = "gaussian"), col= "skyblue", lwd=2) #what the bootstrap distribution looks like 

# KDE based on built-in function density(): bandwidth = 0.4

########### plot what the bootstrap distribution looks like what kernel ####

The simulated bootstrap resampling mean for the coffee volume is 5207.273 mL.

We see our bootstrap distribution gave is a approximately normal distribution of the means, our parameter statistic of interest.

Our calculated mean of coffee volume using the bootstrap distribution is 5217.273 mL.

boot_df <- data.frame(boot_means = s.coffee.vec.mean) #Create a comparison dataframe to compare the CLT Asymptotic Distribution and the Bootstrap Disrtubution


mean.coffee <- mean(s.coffee)    # Center (5250) #Call the CLT asymptotic   parameters for comparison
se_coffee <- sd(s.coffee) / sqrt(length(s.coffee))  

 
ggplot(boot_df, aes(x = boot_means)) + #create plot using coffee mean aka  boots_mean
  #creating a histogram based on the bootstrap distribution 
  geom_histogram(aes(y = after_stat(density)), bins = 30, 
                 fill = "darkgray", alpha = 0.4, color = "black") +
  
  # B: The KDE (Gaussian Kernel - Smoothing the Bootstrap results)
  # R defaults to a Gaussian kernel here
  geom_density(color = "blue", linewidth = 1.2) + #add a layer for a Gaussian line with a 
  
  # C: The CLT Normal Curve (Validation from Part A)
  #based on the mean of coffee and standard error for a Asymptotic distribution
  stat_function(fun = dnorm, args = list(mean = mean.coffee, sd = se_coffee), 
                color = "red", linetype = "dashed", linewidth = 1) +
  
  # Labels and Theme
  labs(title = "Approximated Sampling Distribution of Sample Means",
       subtitle = "Gray: Bootstrap Hist | Blue: Gaussian KDE | Red: CLT Normal",
       x = "Sample Mean Volume (mL)", 
       y = "Density") +
  theme_minimal()

As mentioned prior, both the bootstrap and the CLT Asymptotic Sampling Distribution can be used on this non-complex distribution type, thus the distributions for taken both for the bootstrap and asymptotic present similar results. A

  1. Repeat the analysis in parts (a) and (b) for the sample variance.
options(scipen = 0)

#Part a for Variance
var_coffee = var(s.coffee) #calculating sample variance of coffee = 5030833

##Part B for Variance  

#call the sample from the population
set.seed(142)

s.coffee
 [1] 2850 2900 2950 3000 3050 3050 3100 3100 3100 3100 3150 3200 3250 3250 3250
[16] 3300 3300 3350 3400 4000 4100 4100 4200 4200 4200 4300 4300 4400 4400 4500
[31] 4500 4500 4600 4600 4700 4800 4800 7700 7800 7900 8100 8100 8200 8200 8200
[46] 8300 8300 8400 8400 8500 8500 8700 8800 8900 8900
#create an  empty vector to calculate the bootstrap distribution mean in the for loop

s.coffee.vec.var = NULL

#sample from the population

for(i in 1:1000)
{
 
ith.coffee.sample.v=sample(s.coffee, 55, replace= TRUE) #randomly select from original sample
#Our sample size is 55
#replace our sample each loop because we do not have a large sample

s.coffee.vec.var[i] = var(ith.coffee.sample.v) #calculated variance: 4844761
  
}

kdeV = density(s.coffee.vec.var)

#generate a kernel density estimate from the bootstrap from the sample means and plot it

hist(s.coffee.vec.var, #datapoint aka statistic we just generated, we want to see its simulated distrubution
        probability = TRUE,  #identify the relative frequency (always say true)
        breaks = 14,
        xlab = "sample varience of repeated samples", #label the x axis
        main= "Approximated Sampling Distrubution \n of Sample Varience - Bootstrap Resampling",
     cex.main = 0.9,
     col.main = "darkgreen"
     )
lines(density(s.coffee.vec.var, kernel = "gaussian"), col= "skyblue", lwd=2) #what the bootstrap distribution looks like 

The asymptotic sampling distribution is a distribution better represented for non-complex values. As the variance is a squared parameter that adds complexity a asymptotic sampling distribution is not a strong distribution type for identifying a variance parameter. A bootstrap resampling distribution is a better suited distribution type for identifying a variance’s added complexity.

LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgMzogRUNERiBhbmQgQm9vdHN0cmFwIFNhbXBsaW5nIGFuZCBBcHBsaWNhdGlvbnMiDQphdXRob3I6ICJFemFuYSBSaXZlcnMgIg0KZGF0ZTogIiAyLTE3LTIwMjYiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vDQogICAgdG9jX2NvbGxhcHNlZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgdGhlbWU6IGx1bWVuDQogIHBkZl9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBmaWdfd2lkdGg6IDMNCiAgICBmaWdfaGVpZ2h0OiAzDQogIHdvcmRfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIGtlZXBfbWQ6IHllcw0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KYGBge2NzcywgZWNobyA9IEZBTFNFfQ0KI1RPQzo6YmVmb3JlIHsNCiAgY29udGVudDogIlRhYmxlIG9mIENvbnRlbnRzIjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtc2l6ZTogMS4yZW07DQogIGRpc3BsYXk6IGJsb2NrOw0KICBjb2xvcjogbmF2eTsNCiAgbWFyZ2luLWJvdHRvbTogMTBweDsNCn0NCg0KDQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovDQogICAgbGlzdC1zdHlsZTp1cHBlci1yb21hbjsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQp9DQoNCmgxLnRpdGxlIHsgICAgLyogbGV2ZWwgMSBoZWFkZXIgb2YgdGl0bGUgICovDQogIGZvbnQtc2l6ZTogMjJweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCn0NCg0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxNXB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsNCiAgY29sb3I6IG5hdnk7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgxIHsgLyogSGVhZGVyIDEgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDIwcHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMiB7IC8qIEhlYWRlciAyIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE2cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KLyogQWRkIGRvdHMgYWZ0ZXIgbnVtYmVyZWQgaGVhZGVycyAqLw0KLmhlYWRlci1zZWN0aW9uLW51bWJlcjo6YWZ0ZXIgew0KICBjb250ZW50OiAiLiI7DQoNCmJvZHkgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQoNCi5oaWdobGlnaHRtZSB7IGJhY2tncm91bmQtY29sb3I6eWVsbG93OyB9DQoNCnAgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQoNCn0NCmBgYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwYW5kZXIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygicGFuZGVyIikNCiAgIGxpYnJhcnkocGFuZGVyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQogIGxpYnJhcnkoZ2dwbG90MikNCn0NCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiAgbGlicmFyeSh0aWR5dmVyc2UpDQp9DQoNCmlmICghcmVxdWlyZSgicGxvdGx5IikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikNCiAgbGlicmFyeShwbG90bHkpDQp9DQojIyMjDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgICMgaW5jbHVkZSBjb2RlIGNodW5rIGluIHRoZSBvdXRwdXQgZmlsZQ0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICAjIHNvbWV0aW1lcywgeW91IGNvZGUgbWF5IHByb2R1Y2Ugd2FybmluZyBtZXNzYWdlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3UgY2FuIGNob29zZSB0byBpbmNsdWRlIHRoZSB3YXJuaW5nIG1lc3NhZ2VzIGluDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhlIG91dHB1dCBmaWxlLiANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gVFJVRSwgICAgIyB5b3UgY2FuIGFsc28gZGVjaWRlIHdoZXRoZXIgdG8gaW5jbHVkZSB0aGUgb3V0cHV0DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW4gdGhlIG91dHB1dCBmaWxlLg0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkENCiAgICAgICAgICAgICAgICAgICAgICApICANCmBgYA0KIA0KIFwNCiANCiMjICoqQXNzaWdubWVudCBPYmplY3RpdmVzKiogDQoNCiogVW5kZXJzdGFuZCB0aGUgdGhlb3JldGljYWwgYmFzaXMgb2YgQm9vdHN0cmFwIHNhbXBsaW5nIG1ldGhvZHMgZm9yIGFwcHJveGltYXRpbmcgc2FtcGxpbmcgZGlzdHJpYnV0aW9ucy4NCg0KKiBBc3Nlc3MgdGhlIHBlcmZvcm1hbmNlIG9mIEJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb25zIGFnYWluc3QgZXhhY3QgYW5kIGFzeW1wdG90aWMgc2FtcGxpbmcgZGlzdHJpYnV0aW9ucy4NCg0KKiBJbXBsZW1lbnQgQm9vdHN0cmFwIHNhbXBsaW5nIGFsZ29yaXRobSBhbmQgY29uc3RydWN0IHNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMgdXNpbmcgUi4NCg0KXA0KDQoqKlVzZSBvZiBBSSBUb29scyoqDQoNCioqUG9saWN5IG9uIEFJIFRvb2wgVXNlKio6IFN0dWRlbnRzIG11c3QgYWRoZXJlIHRvIHRoZSBBSSB0b29sIHBvbGljeSBzcGVjaWZpZWQgaW4gdGhlIGNvdXJzZSBzeWxsYWJ1cy4gVGhlIGRpcmVjdCBjb3B5aW5nIG9mIEFJLWdlbmVyYXRlZCBjb250ZW50IGlzIHN0cmljdGx5IHByb2hpYml0ZWQuIEFsbCBzdWJtaXR0ZWQgd29yayBtdXN0IHJlZmxlY3QgeW91ciBvd24gdW5kZXJzdGFuZGluZzsgd2hlcmUgZXh0ZXJuYWwgdG9vbHMgYXJlIGNvbnN1bHRlZCwgY29udGVudCBtdXN0IGJlIHRob3JvdWdobHkgcmVwaHJhc2VkIGFuZCBzeW50aGVzaXplZCBpbiB5b3VyIG93biB3b3Jkcy4NCg0KKipDb2RlIEluY2x1c2lvbiBSZXF1aXJlbWVudCoqOiBBbnkgY29kZSBpbmNsdWRlZCBpbiB5b3VyIGVzc2F5IG11c3QgYmUgcHJvcGVybHkgY29tbWVudGVkIHRvIGV4cGxhaW4gdGhlIHB1cnBvc2UgYW5kL29yIGV4cGVjdGVkIG91dHB1dCBvZiBrZXkgY29kZSBsaW5lcy4gU3VibWl0dGluZyBBSS1nZW5lcmF0ZWQgY29kZSB3aXRob3V0IG1lYW5pbmdmdWwsIHN0dWRlbnQtYWRkZWQgY29tbWVudHMgd2lsbCBub3QgYmUgYWNjZXB0ZWQuDQoNClwNCg0KKipBc3ltcHRvdGljIERpc3RyaWJ1dGlvbiBvZiBTYW1wbGUgVmFyaWFuY2UqKg0KDQpBc3N1bWUgdGhhdCAkXHsgeF8xLCB4XzIsIFxjZG90cywgeF9uIFx9IFx0byBGKHgpJCB3aXRoICRcbXUgPSBFW1hdJCBhbmQgJFxzaWdtYV4yID0gXHRleHR7dmFyfShYKSQuIERlbm90ZSANCg0KJCQNCnNeMiA9IFxmcmFjezF9e24tMX1cc3VtX3tpPTF9Xm4gKHhfaSAtIFxtdSleMg0KJCQNCg0KSWYgJG4kIGlzIGxhcmdlLCANCg0KJCQNCnNeMiBcdG8gTlxsZWZ0KFxzaWdtYV4yLCAgXGZyYWN7XG11XzQtXHNpZ21hXjR9e259IFxyaWdodCkNCiQkDQoNCndoZXJlICRcbXVfNCA9IEVbKFhfaSAtIFxtdSleNF0kIGlzIHRqZSA0dGggY2VudHJhbCBtb21lbnQgd2hpY2ggY2FuIGJlIGVzdGltYXRlZCBieQ0KDQokJA0KXGhhdHtcbXV9XzQgPSBcZnJhY3sxfXtufVxzdW1fe2k9MX1ebih4X2ktXGJhcnt4fSleNC4NCiQkDQoNCioqTm90ZSoqOiBUaGlzIGRlc2NyaWJlcyB0aGUgYXN5bXB0b3RpYyBjb252ZXJnZW5jZSBvZiB0aGUgc2FtcGxlIHZhcmlhbmNlLCBmb2xsb3dpbmcgZnJvbSB0aGUgY2VudHJhbCBsaW1pdCB0aGVvcmVtIChDTFQpLiBUaGUgc2FtcGxlIHNpemUgcmVxdWlyZWQgZm9yIHRoaXMgYXBwcm94aW1hdGlvbiB0byBob2xkIGlzIHNpdHVhdGlvbi1kZXBlbmRlbnQuDQoNCg0KXA0KDQojIyAqKlF1ZXN0aW9uIDE6IEFzeW1wdG90aWMgdnMgQm9vdHN0cmFwIFNhbXBsaW5nIERpc3RyaWJ1dGlvbnMqKg0KDQpXcml0ZSBhbiBlc3NheSBzdW1tYXJpemluZyB0aGUgY29uY2VwdHMgb2YgQXN5bXB0b3RpYyBhbmQgQm9vdHN0cmFwIFNhbXBsaW5nIERpc3RyaWJ1dGlvbnMsIGFsb25nIHdpdGggdGhlaXIga2V5IGFwcGxpY2F0aW9ucy4gWW91ciBkaXNjdXNzaW9uIHNob3VsZCBiZSBncm91bmRlZCBpbiB5b3VyIHBlcnNvbmFsIHVuZGVyc3RhbmRpbmcgb2YgdGhlIG1hdGVyaWFsLiBBbnkgZXh0ZXJuYWwgc291cmNlcyBpbmNsdWRpbmcgQUkgdG9vbHMgY29uc3VsdGVkIG11c3QgYmUgY2xlYXJseSBjaXRlZC4gDQoNCg0KKipFc3NheSBQcm9tcHQqKjogRGlzY3VzcyB0aGUgY29uY2VwdHMgb2YgdGhlIGJvb3RzdHJhcCBzYW1wbGluZyBwbGFuLCB0aGUgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiwgYW5kIHRoZSBhc3ltcHRvdGljIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBpbiB0aGUgY29udGV4dCBvZiBzdGF0aXN0aWNzIChlLmcuLCBzYW1wbGUgbWVhbiBhbmQgdmFyaWFuY2UpIGNvbXB1dGVkIGZyb20gYW4gaW5kZXBlbmRlbnQgYW5kIGlkZW50aWNhbGx5IGRpc3RyaWJ1dGVkIChpLmkuZC4pIHNhbXBsZS4gWW91ciBkaXNjdXNzaW9uIHNob3VsZDoNCg0KKiBDbGVhcmx5IG91dGxpbmUgdGhlIGtleSBhc3N1bXB0aW9ucyByZXF1aXJlZCBmb3IgZWFjaCBtZXRob2QuDQoNCiogRXhwbGFpbiB0aGUgcHJhY3RpY2FsIGFwcGxpY2F0aW9uIG9mIGVhY2ggZGlzdHJpYnV0aW9uLg0KDQoqIFByb3ZpZGUgZ3VpZGFuY2Ugb24gd2hlbiBhbmQgd2h5IG9uZSBzaG91bGQgYmUgcHJlZmVycmVkIG92ZXIgdGhlIG90aGVyIGluIHN0YXRpc3RpY2FsIGluZmVyZW5jZS4NCg0KDQoNClwNCg0KIyMgQXN5bXB0b3RpYyBTYW1wbGluZyBEaXN0cnVidXRpb25zDQoNCg0KV2UgdXNlICoqc2FtcGxpbmcgZGlzdHJpYnV0aW9ucyoqIHdoZW4gd2Ugd2FudCB0byBtYWtlIHN0YXRpc3RpY2FsIGluZmVyZW5jZXMgYWJvdXQgdGhlIHBvcHVsYXRpb24uIE9mdGVuIHJ1bm5pbmcgc3RhdGlzdGljcyBvbiB0aGUgdHJ1ZSBwb3B1bGF0aW9uIGlzIGV4dHJlbWVseSBleHBlbnNpdmUsIG9yIGltcG9zc2libGUuIE9mdGVuIHRoZSB0cnVlIHBvcHVsYXRpb24gaXMgdW5rbm93biwgc28gcnVubmluZyBzdGF0aXN0aWNzIG9uIHRoZSB0cnVlIHBvcHVsYXRpb24gc29sZXksIGlzIGltcHJhY3RpY2FsLiBUbyBjb21wZW5zYXRlLCBvZnRlbiB3ZSB0YWtlIGEgcmFuZG9tIHNhbXBsZSBmcm9tIG91ciBwb3B1bGF0aW9uIG9mIGludGVyZXN0IHRvIG1ha2UgYSBzdGF0aXN0aWNhbCBpbmZlcmVuY2UgdG8gdGhlIHBvcHVsYXRpb24uIFdlIGFzc3VtZSBvdXIgc2FtcGxlIGNhbiBwcm92aWRlIHVzIHdpdGggaW5mb3JtYXRpb24gYWJvdXQgdGhlIHBvcHVsYXRpb24uDQoNCkFuICoqQXN5bXB0b3RpYyBTYW1wbGluZyBEaXN0cmlidXRpb24qKiBpcyBhbiBleGFtcGxlIG9mIGEgdHlwZSBvZiBzYW1wbGluZyBkaXN0cmlidXRpb24gd2UgdXNlIHRvIG1ha2Ugc3RhdGlzdGljYWwgaW5mZXJlbmNlcyBhYm91dCB0aGUgcG9wdWxhdGlvbi4gV2hlbiB3ZSB1c2UgYW4gYXN5bXB0b3RpYyBzYW1wbGluZyBkaXN0cmlidXRpb24gd2UgYXNzdW1lIGEgbGFyZ2Ugc2FtcGxlIHNpemUgd2l0aCBhbiBpbmRlcGVuZGVudGx5IGFuZCBpZGVudGljYWxseSBkaXN0cmlidXRlZCBzYW1wbGUuIFdlIGNhbiB1c2UgYW4gdW5kZXJsaW5pbmcgbm9uLXBhcmFtZXRyaWMgb3IgdW5rbm93biBwb3B1bGF0aW9uIHNoYXBlIGFuZCBzdGFuZGFyZGl6ZSB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiB0byBhcHByb3hpbWF0ZSB0aGUgZGlzdHJpYnV0aW9uIGFuZCBwYXJhbWV0ZXJzIG9mIGludGVyZXN0IGZvciB0aGUgc2FtcGxlcyBjb2xsZWN0ZWQuIA0KDQpXZSBtb2RlbCByYXcgY29sbGVjdGVkIGRhdGFzZXRzIG9yIHNhbXBsZXMgd2l0aCBhICoqRW1waXJpY2FsIEN1bXVsYXRpdmUgRGlzdHJpYnV0aW9uIEZ1bmN0aW9uIChFQ0RGKSoqLiBUaGlzIGlzIGEgZGlzdHJpYnV0aW9uIGRpcmVjdGx5IGZyb20gb2JzZXJ2ZWQgc2FtcGxlIGRhdGEsIHdpdGggbm8gaW5oZXJlbnRseSBhc3N1bWVkIHNoYXBlIGFib3V0IHRoZSBzYW1wbGUgb3IgcG9wdWxhdGlvbiBkaXN0cmlidXRpb24uICANCg0KVGhlIGFzeW1wdG90aWMgZGlzdHJpYnV0aW9uIGNvbnZlcmdlcyB0byBhIG5vcm1hbCBkaXN0cmlidXRpb24gYXMgdGhlIHNhbXBsZSBzaXplIGluY3JlYXNlcywgYWx0aG91Z2ggd2Ugc3RhbmRhcmRpemUgZWFjaCBvYnNlcnZhdGlvbiBpbiB0aGUgZGlzdHJpYnV0aW9uIHRvIGFwcHJveGltYXRlIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiB0byBtYWtlIGluZmVyZW5jZXMgYWJvdXQgdGhlIGRpc3RyaWJ1dGlvbiB1c2luZyBvdXIgbm9ybWFsIGRpc3RyaWJ1dGlvbiBhcyBhIGd1aWRlIHRvIGRvIHNvIHVzaW5nIHRoZSBmb2xsb3dpbmcgZm9ybXVsYXM6DQoNCg0KV2hlbiBvdXIgc3RhbmRhcmQgZGV2aWF0aW9uIGlzIGtub3duIGZvciB0aGUgcG9wdWxhdGlvbiwgd2Ugc3RhbmRhcmRpemUgYSBBc3ltcHRvdGljIERpc3RyaWJ1dGlvbiAgdXNpbmcgdGhlIGZvcm11bGENCiQkDQoNClo9IFxmcmFje1xiYXJ7WH0tXG11fXtcc2lnbWEvXHNxcnR7bn19IFx0b197XHRleHR7YXBwcm94fX0gTigwLCAxKQ0KDQoNCiQkDQoNCg0KV2hlbiBvdXIgc3RhbmRhcmQgZGV2aWF0aW9uIGlzIG5vdCBrbm93biBmb3IgdGhlIHBvcHVsYXRpb24sIHdlIGFzc3VtZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIGlzIGFwcHJveGltYXRlbHkgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgKHdpdGggYSBsYXJnZSBzYW1wbGUgc2l6ZSksIHdlIHN0YW5kYXJkaXplIGEgQXN5bXB0b3RpYyBEaXN0cmlidXRpb24gdXNpbmcgdGhlIGZvcm11bGEgd2hpY2ggaGFwcGVucyB0byBiZSBhIFQtZGlzdHJ1YnV0aW9uOiANCg0KJCQNClQgPSBcZnJhY3tcYmFye1h9LVxtdX17Uy9cc3FydHtufX0gXG92ZXJzZXR7ZH17XHRvfSAgdF97bi0xfQ0KJCQNCldlIGVzdGltYXRlIHRoZSBzYW1wbGUgdmFyaWFuY2UgdG8gYXBwbHkgdG8gdGhlIFQgZGlzdHJpYnV0aW9uIHdoaWNoIHRoZSAkXHNxcnQoU14yKSQgY2FuIGJlIHBsYWNlZCBpbiB0aGUgVCBkaXN0cmlidXRpb24gZm9ybXVsYS4gDQoNCiQkDQpTXjIgXHN0YWNrcmVse2R9e1x0b30gTlxsZWZ0KFxzaWdtYV4yLCBcZnJhY3tcbXVfNCAtIFxzaWdtYV40fXtufVxyaWdodCkgXHF1YWQgXHRleHR7YXMgfSBuIFx0byBcaW5mdHksDQokJA0KV2hlbiBvdXIgZGlzdHJpYnV0aW9uIGlzIHN1YnNldCB3aXRoIGEgcHJvcG9ydGlvbiAoQmVybm91bGxpIFJhbmRvbSBWYXJpYWJsZSksIHdlIGEgQXN5bXB0b3RpYyBEaXN0cmlidXRpb24gc3RhbmRhcmRpemUgdXNpbmcgdGhlIGZvcm11bGENCiQkDQpaX24gPSBcZnJhY3tcaGF0e3B9X24gLSBwfXtcc3FydHtcZnJhY3twKDEtcCl9e259fX0gXHN0YWNrcmVse2R9e1x0b30gTigwLDEpIFxxdWFkIFx0ZXh0e2FzIH0gbiBcdG8gXGluZnR5DQokJA0KDQpUaGUgQXN5bXB0b3RpYyBEaXN0cmlidXRpb24gaXMgdmVyeSB2YWx1YWJsZSBmb3IgYXBwcm94aW1hdGluZyBzYW1wbGUgc3RhdGlzdGljcyBmb3IgZXhhbXBsZSwgdGhlIHNhbXBsZSBzdGF0aXN0aWMsIG1lYW4gY2FuIGJlIGFwcHJveGltYXRlZCB1c2luZyB0aGUgZm9sbG93aW5nIGZvcm11bGEgd2hlcmUgJFxtdV80ID0gRVsoWF9pIC0gXG11KV40XSQgaXMgdGplIDR0aCBjZW50cmFsIG1vbWVudCB3aGljaCBjYW4gYmUgZXN0aW1hdGVkIGFzOg0KDQokJA0KXGhhdHtcbXV9XzQgPSBcZnJhY3sxfXtufVxzdW1fe2k9MX1ebih4X2ktXGJhcnt4fSleNC4NCg0KJCQNCldoaWxlIG91ciBhc3ltcHRvdGljIGRpc3RyaWJ1dGlvbiBjYW4gbWFrZSBhcHByb3hpbWF0aW9ucyBvbiBzYW1wbGUgc3RhdGlzdGljcywgd2hlbiBkaXN0cmlidXRpb25zIGJlY29tZSBtb3JlIGNvbXBsZXgsIGZvciBleGFtcGxlIHBhaXJlZCBvYnNlcnZhdGlvbnMsIHVuYm91bmRlZCBwb3B1bGF0aW9ucywgYW5kIHVua25vd25zIGFib3V0IHRoZSB0cnVlIHBvcHVsYXRpb24sIGRpcmVjdCBjb21wdXRhdGlvbiBvZiB0aGUgYXN5bXB0b3RpYyBkaXN0cmlidXRpb25zIGNhbiBiZWNvbWUgaW5jcmVkaWJseSBjb21wbGV4IGFuZCBub24tdGltZSBlZmZpY2llbnQuIEluc3RlYWQgb2YgZGlyZWN0IGNvbXB1dGF0aW9ucyBhbmQgYXBwcm94aW1hdGlvbnMgZm9yIHRoZSBkaXN0cmlidXRpb24gd2UgY2FuIHJ1biBzaW11bGF0aW9ucyB3aXRoaW4gdGhlIGRhdGFzZXRzIHdlIGhhdmUgdG8gc2ltdWxhdGUgYW5kIHN1bW1hcnkgdGhlIHN0YXRpc3RpY3MgYWZ0ZXIgcmVwZWF0ZWQgcmVzYW1wbGVzIHRvIGVzdGltYXRlIGEgc2FtcGxlIHN0YXRpc3RpYyAoZm9yIGV4YW1wbGUgbWVhbiBvciB2YXJpYW5jZSkgdGhyb3VnaCB0aGUgYmVoYXZpb3Igc2VlbiB0aHJvdWdoIHJlcGVhdGVkIG1lYXN1cmVtZW50cyBpbnN0ZWFkIHRocm91Z2ggZGlyZWN0IGNvbXB1dGF0aW9uLiBPbmUgd2F5IHdlIGRlbW9uc3RyYXRlIHRoaXMgc2ltdWxhdGVkIHJlc2FtcGxpbmcgaXMgdGhyb3VnaCAqKkJvb3RzdHJhcCBTYW1wbGluZyBEaXN0cmlidXRpb25zKiouIA0KDQoNCg0KIyMgQm9vdHN0cmFwIFNhbXBsaW5nIERpc3RydWJ1dGlvbnMgDQpBIGJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24gaXMgYSBzaW11bGF0ZWQgYXBwcm9hY2ggaW50byBhbmFseXppbmcgc2FtcGxlIHN0YXRpc3RpY3MgKGlnLiBtZWFuLCB2YXJpYW5jZSwgZXRjLikuIEluc3RlYWQgb2Ygb3JnYW5pemluZyBhIGRpc3RyaWJ1dGlvbiBkaXJlY3RseSB0byBkZXJpdmUgb25lIG1lYW4gb3Igb3RoZXIgc2FtcGxlIHN0YXRpc3RpYywgd2UgcmVwZWF0YWJseSBzYW1wbGUgKHdpdGggcmVwbGFjZW1lbnQpIGZyb20gdGhlIG9yaWdpbmFsbHkgY29sbGVjdGVkIHNhbXBsZSB0byBkZXJpdmVkIGEgdmFyaWV0eSBvZiB0aGUgc2FtcGxlIHN0YXRpc3RpYyBvZiBpbnRlcmVzdCB2YWx1ZXMgdG8gY29tcGlsZSBhbmQgY29tcHV0ZSBpbnRvIGEgZXZlbiBtb3JlIHJvYnVzdCB2YWx1ZSBmb3IgdGhlIHNhbXBsZSBzdGF0aXN0aWMgb2YgaW50ZXJlc3QuICANCg0KV2Ugc2VsZWN0IGEgcmFuZG9tIHNhbXBsZSBmcm9tIHRoZSB0cnVlIHBvcHVsYXRpb24uICBXZSB1c2UgdGhlIGNvbGxlY3RlZCByYW5kb20gc2FtcGxlIGFzIGEgcmVwcmVzZW50YXRpdmUgcG9wdWxhdGlvbiB0byBkcmF3IHNhbXBsZXMgZnJvbS4gV2l0aCB0aGlzIG9yaWdpbmFsbHkgY2FwdHVyZWQgc2FtcGxlIHdlIHRha2UgDQoNCg0KV2UgY2hvb3NlIHRvIHJhbmRvbWx5IHNlbGVjdCByYW5kb20gc2FtcGxlcyBmcm9tIHRoZSBvcmlnaW5hbCByYW5kb20gc2FtcGxlIHRvIGNvbXB1dGUgYSBib290c3RyYXAgc2FtcGxlcyBzdGF0aXN0aWMuIFdlIHdpbGwgdWx0aW1hdGVseSB1c2UgYWxsIHRoZSBzaW11bGF0ZWQgYm9vdHN0cmFwIHN0YXRpc3RpY3MgdG8gY29tcHV0ZSB0aGUgc3RhdGlzdGljIG9mIGludGVyZXN0IG9udG8gdGhlIHNpbXVsYXRlZCBib290c3RyYXAgc3RhdGlzdGljcy4gDQoNCg0KQmVsb3cgaXMgdGhlIHNpbXVsYXRpb24gb2YgYSBib290c3RyYXAgc3RhdGlzdGljIGZyb20gYW4gb3JpZ2luYWwgZGF0YXNldCwgdG8gZmluZCBhIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gd2UgY2FuIGNhbGN1bGF0ZSBhIHN0YXRpc3RpYyBmcm9tDQoNCmBgYHtyfQ0KDQojY3JlYXRpbmcgYSBzaW11bGF0ZWQgYm9vdHN0cmFwDQoNCnVybCA9ICJodHRwczovL3Blbmdkc2NpLmdpdGh1Yi5pby9TVEE1MDYvdzA0L3cwMi13Y3VoZWlnaHRzLnR4dCINCg0KDQpoZWlnaHQgPSByZWFkLnRhYmxlKHVybCwgaGVhZGVyID0gVFJVRSkgI3RoZSBQb3B1bGF0aW9uIG9mIHRoZSBoZWlnaHRzIGF0IHdlc3QgY2hlc3RlciB1bml2ZXJzaXR5IA0KDQpvcmlnaW5hbC5zYW1wbGUgPSBzYW1wbGUoaGVpZ2h0JEhlaWdodCwgODEsIHJlcGxhY2UgPSBGQUxTRSkgI1Rha2UgYSByYW5kb20gc2FtcGxlIG9mIHRoZSBvcmlnaW5hbCBwb3B1bGF0aW9uIHRvIGFjdCBhcyB0aGUgcG9wdWxhdGlvbiBwcm94eSBmb3Igb3VyIGJvb3RzdHJhcA0KDQojb3VyIHNhbXBsZSBzaXplIGlzIDgxDQojIHdlIGRvIG5vdCBuZWVkIHRvIHJlcGxhY2Ugb3VyIHNhbXBsZXMgZnJvbSB0aGUgdHJ1ZSBwb3B1bGF0aW9uLiBXZSB3b3VsZCBsaWtlIGNvbnNpc3RlbnQgdmFsdWVzIHRvIHJlcGVhdGVkbHkgc2FtcGxlIGZyb20gZm9yIG91ciBib290c3RyYXAgc2FtcGxpbmcNCg0KYnQuc2FtcGxlLm1lYW4gPSBOVUxMICNjcmVhdGUgYW4gZW1wdHkgdmVjdG9yIHRvIGhvbGQgb3VyIHNhbXBsZSBpbnRvIHdoZW4gd2UgY29tcHV0ZSB0aGUgYm9vdHN0cmFwIG1lYW4gZHVyaW5nIG91ciBmb3IgbG9vcA0KDQpmb3IoaSBpbiAxOjEwMDApDQp7DQogIA0KICBpdGguYnQuc2FtcGxlID0geD1zYW1wbGUoeD1vcmlnaW5hbC5zYW1wbGUsIHNpemUgPSA4MSwgcmVwbGFjZT0gVFJVRSkgI3Rha2UgcmVwZWF0ZWQgc2FtcGxlcyBmcm9tIG91ciBvcmlnaW5hbCBzYW1wbGUgYWthIHRoZSBzYW1wbGUgYWN0aW5nIGFzIGEgcHJveHkgZm9yIG91ciBvcmlnaW5hbCBwb3B1bGF0aW9uDQogIA0KICAjb3VyIHNhbXBsZSBzaXplIGlzIDgxLCB0aGUgc2FtZSBzaXplIG9mIHRoZSBvcmlnaW5hbCBwb3B1bGF0aW9uDQogICN3ZSB3YW50IHRvIHRha2UgdmFsdWVzIGZyb20gdGhpcyBzYW1wbGUgcmVwZWF0ZWQgc28gd2UgZG8gcmVwbGFjZSBvdXIgc2FtcGxlcyANCiAgDQogIGJ0LnNhbXBsZS5tZWFuW2ldID0gbWVhbihpdGguYnQuc2FtcGxlKQ0KICANCiAgDQp9DQoNCg0KaGlzdChidC5zYW1wbGUubWVhbiwNCiAgICAgYnJlYWtzID0gMTIsDQogICAgIHByb2JhYmlsaXR5ID0gVFJVRSwNCiAgICAgeGxhYiA9ICJCb290c3RyYXAgc2FtcGxlIG1lYW5zIiwgI3ggYXhpcyBsYWJsZQ0KICAgbWFpbj0iQm9vdHN0cmFwIFNhbXBsaW5nIERpc3RyaWJ1dGlvbiBcbiBvZiBTYW1wbGUgTWVhbnMgRXhhbXBsZSIsDQogICAgICAgICAgY2V4Lm1haW4gPSAwLjksDQogICAgICAgY29sLm1haW4gPSAiZGFya2dyZWVuIikgICANCmxpbmVzKGRlbnNpdHkoYnQuc2FtcGxlLm1lYW4pLCBjb2wgPSAic2t5Ymx1ZSIsIGx3ZCA9IDIpDQoNCmBgYA0KDQoNCg0KVGhlIEJvb3RzdHJhcCBTYW1wbGluZyBEaXN0cmlidXRpb24gaGFzIHZhbHVlIGJlY2F1c2UgaXQgYWxsb3dzIHVzIHRvIG1ha2UgaW5mZXJlbmNlcyBhYm91dCBhIHBvcHVsYXRpb24gYmFzZWQgb24gYSBsYXJnZSBpbmRlcGVuZGVudCBpZGVudGljYWxseSBkaXN0cnVidHVlZCByYW5kb20gc2FtcGxlIGluIHdoaWNoIHdlIGFyZSB1bnN1cmUgYWJvdXQgdGhlIHRydWUgcG9wdWxhdGlvbiBhbmQgbW9zdCBsaWtlbHkgaGF2ZSBjb21wbGV4aXR5IGluIHRoZSBvcmdhbml6YXRpb24gb2Ygb3VyIGRpc3RyaWJ1dGlvbi4gV2UgbWF5IGZpbmQgdmFsdWUgaW4gdXNpbmcgYSBib290c3RyYXAgd2hlbiANCg0KV2hlbiB3ZSBkbyBub3QgaGF2ZSBjb21wbGV4IGF0dHJpYnV0ZXMgaW4gb3VyIGRpc3RyaWJ1dGlvbiBhIEFzeW1wdG90aWMgRGlzdHJpYnV0aW9uIG1heSBiZSBiZXR0ZXIgZml0dGVkLiBBIHNpbXVsYXRpb24gbWF5IGNhdXNlIGhpZ2hlciBsaWtlbGlob29kIGYgdHlwZSBJIGVycm9yLCBkdWUgdG8gdGhlIG5lZWQgdG8gcnVuIG1vcmUgc2ltdWxhdGlvbiB0ZXN0cw0KDQoNCkFzc2VzcyB0aGUgcGVyZm9ybWFuY2Ugb2YgQm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMgYWdhaW5zdCBleGFjdCBhbmQgYXN5bXB0b3RpYyBzYW1wbGluZyBkaXN0cmlidXRpb25zLg0KDQpBbiBleGFjdCBkaXN0cmlidXRpb24gaGFzIHNpbWlsYXIgcXVhbGl0aWVzIHRvIGFuIGFzeW1wdG90aWMgZGlzdHJpYnV0aW9uLCBhbHRob3VnaCBhbiBleGFjdCBkaXN0cmlidXRpb24gaXMgc3BlY2lmaWMgdG8gYSBzbWFsbCBzYW1wbGUgc2l6ZSwgd2l0aCBhIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIHNhbXBsZSB0aGF0IGlzIGFuIGlkZW50aWNhbGx5IGFuZCBpbnRlcmRlcGVuZGVudCBzYW1wbGVzIGRpc3RyaWJ1dGlvbi4gSW4gY29tcGFyaXNvbiB0byBib3RoIGV4YWN0IGFuZCBhc3ltcHRvdGljIGRpc3RyaWJ1dGlvbnMsIGEgYm9vdCBzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24gaXMgdmFsdWFibGUgYmVjYXVzZSB3ZSBjYW4gc2ltdWxhdGUgYSBkaXN0cmlidXRpb24gdG8gcmVhY2ggYSBzdGF0aXN0aWMgZm9yIGEgZGlzdHJpYnV0aW9ucyB0aGF0IHdvdWxkIG90aGVyd2lzZSBiZSB0b28gY29tcGxleCB0byBtb2RlbCB0aHJvdWdoIHBhcmFtZXRyaWMgYXBwcm94aW1hdGlvbi4gQWx0aG91Z2ggYW4gZXhhY3QgdGVzdCBpcyBzbWFsbCBhbmQgYSBwYXJhbWV0cmljIHRlc3QsIGF0IHRpbWVzIGFuIGV4YWN0IHRlc3QgbWF5IGJlIG1vcmUgYXBwbGljYWJsZSBpZiB0aGVyZSBhcmUgbm8gY29tcGxleCBkaXN0cmlidXRpb25zLCBhIHNtYWxsIHNhbXBsZSBzaXplIHRoYXQgZG9lcyBub3QgbWVldCB0aGUgbGFyZ2Ugc2FtcGxlIHNpemUgYXNzdW1wdGlvbiBvZiB0aGUgQm9vdHN0cmFwIEFzc3VtcHRpb25zIGFuZCB0aGVyZSBhbHNvIGJlIGxpdHRsZSBuZWVkIHRvIGFwcHJveGltYXRlIHRoZSBkaXN0cmlidXRpb24gYXMgdGhlIGRpc3RyaWJ1dGlvbiBhbHJlYWR5IGtub3duLiBBIEJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24gbWF5IGJlIG1vcmUgYXBwcm9wcmlhdGUgZm9yIGNvbXBsZXggYXN5bXB0b3RpYyBkaXN0cmlidXRpb25zIHdpdGggbGFyZ2Ugc2FtcGxlIHNpemVzLg0KDQoNCg0KIyMgKipRdWVzdGlvbiAyOiBEYWlseSBDb2ZmZWUgU2FsZXMgKGluIG1MKSBhdCBUd28gRGlmZmVyZW50IENhZmUgTG9jYXRpb25zKioNCg0KVGhpcyBkYXRhIHNldCByZXByZXNlbnRzIHRoZSB2b2x1bWUgb2YgcmVndWxhciBicmV3ZWQgY29mZmVlIHNvbGQgcGVyIGRheSAoaW4gbWlsbGlsaXRlcnMpIGF0IHR3byBkaWZmZXJlbnQgY2FmZSBsb2NhdGlvbnMgb3ZlciBhIHBlcmlvZCBvZiA1MCBkYXlzLiANCg0KYGBgDQoyODUwLCAzMjAwLCAyOTAwLCAzMTAwLCAyOTUwLCA3ODAwLCA4MTAwLCA3OTAwLCAzMzAwLCAzMDUwLCA0MDAwLCA0MjAwLCAzMTUwLCAzNDAwLCA3NzAwLCA4MjAwLCANCjMyNTAsIDQ0MDAsIDMxMDAsIDQyMDAsIDQ1MDAsIDQ4MDAsIDQzMDAsIDg1MDAsIDgyMDAsIDg5MDAsIDg3MDAsIDMyNTAsIDMwMDAsIDQ2MDAsIDQxMDAsIDg0MDAsIA0KODgwMCwgMzM1MCwgNDcwMCwgMzEwMCwgODEwMCwgMzA1MCwgODMwMCwgNDEwMCwgMzEwMCwgODMwMCwgODkwMCwgODIwMCwgNDQwMCwgNDUwMCwgMzI1MCwgNDYwMCwgDQo4NDAwLCAzMzAwLCA0MjAwLCA0NTAwLCA0ODAwLCA0MzAwLCA4NTAwDQpgYGANCldlIGFyZSBpbnRlcmVzdGVkIGluIGZpbmRpbmcgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiBzYW1wbGUgbWVhbnMgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIHZhcmlvdXMgaW5mZXJlbmNlcyBhYm91dCB0aGUgdW5kZXJseWluZyBwb3B1bGF0aW9uIG1lYW4uDQoNCmEpIEJhc2VkIG9uIHRoZSBnaXZlbiBkYXRhLCBjYW4gdGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSBiZSB1c2VkIHRvIGRlcml2ZSB0aGUgYXN5bXB0b3RpYyBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgdGhlIHNhbXBsZSBtZWFuPyBKdXN0aWZ5IHlvdXIgYW5zd2VyLg0KDQpUaGUgYXN5bXB0b3RpYyBzYW1wbGluZyBkaXN0cmlidXRpb24gYWxsb3dzIGEgbm9uLXBhcmFtZXRyaWMgYXBwcm94aW1hdGlvbiB0aGF0IHVzZXMgdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgbGFyZ2VyIHRoZSBzYW1wbGUgc2l6ZSB0aGUsIGdyZWF0ZXIgdGhlIGxpa2VsaWhvb2QgdGhlIHNhbXBsZSBtZWFuIHdpbGwgYmUgbm9ybWFsbHkgZGlzdHJ1c3RlZC4gVGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSBpcyBhIHRvb2wgdGhlIGFzeW1wdG90aWMgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIHVzZXMgYSBhcyBhbiBhcHByb3hpbWF0aW9uIGZvciB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uLiBJbiBtYW55IGNhc2VzIGJvdGggYW4gYXN5bXB0b3RpYyBzYW1wbGluZyBkaXN0cmlidXRpb24gb3IgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbiBjYW4gYmUgdXNlZCwgYWx0aG91Z2ggd2hpY2ggaXMgbW9zdCBhY2Nlc3NpYmxlIGRlcGVuZHMgb24gdGhlIGNvbXBsZXhpdHkgb2YgdGhlIGRpc3RyaWJ1dGlvbiBhbmQgcGFyYW1ldGVyIG9mIGludGVyZXN0LiBBcyB0aGlzIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiwgZG9lcyBub3QgbG9vayBjb21wbGV4IGluIHJlZ2FyZHMgdG8gcGFpcmVkIG9ic2VydmF0aW9uIGZvciBleGFtcGxlLCB0aGUgY2VudHJhbCBsaW1pdCB0aGVvcmVtIGNhbiBiZSB1c2VkIGJlY2F1c2UgdGhlIHNhbXBsZSB3ZSBhcmUgYXNzdW1pbmcgaXMgb3VyIHBvcHVsYXRpb24gaXMgbm90IG5vcm1hbGx5IGRpc3RyaWJ1dGVkOyB0aGUgYXN5bXB0b3RpYyBzYW1wbGluZyBkaXN0cmlidXRpb24gZG9lcyBub3QgYXNzdW1lIHNoYXBlIG9mIHBvcHVsYXRpb24sIHVubGlrZSB0aGUgZXhhY3Qgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gDQoNCg0KVGhpcyBpcyB0aGUgdXNlIG9mIHRoZSBjZW50cmFsIGxpbWl0IHRoZW9yeSBmb3IgdGhlIGFzeW1wdG90aWMgZGlzdHJpYnV0aW9uIA0KDQpgYGB7cn0NCg0KY29mZmVlcyA9IGMoMjg1MCwgMzIwMCwgMjkwMCwgMzEwMCwgMjk1MCwgNzgwMCwgODEwMCwgNzkwMCwgMzMwMCwgMzA1MCwgNDAwMCwgNDIwMCwgMzE1MCwgMzQwMCwgNzcwMCwgODIwMCwgMzI1MCwgNDQwMCwgMzEwMCwgNDIwMCwgNDUwMCwgNDgwMCwgNDMwMCwgODUwMCwgODIwMCwgODkwMCwgODcwMCwgMzI1MCwgMzAwMCwgNDYwMCwgNDEwMCwgODQwMCwgODgwMCwgMzM1MCwgNDcwMCwgMzEwMCwgODEwMCwgMzA1MCwgODMwMCwgNDEwMCwgMzEwMCwgODMwMCwgODkwMCwgODIwMCwgNDQwMCwgNDUwMCwgMzI1MCwgNDYwMCwgODQwMCwgMzMwMCwgNDIwMCwgNDUwMCwgNDgwMCwgNDMwMCwgODUwMCkNCg0KDQoNCnMuY29mZmVlPXNvcnQoY29mZmVlcykgI3NvcnRpbmcgdGhlIGRhdGFzZXQgaW4gaW5jcmVhc2luZyBvcmRlcmluZw0KDQpoaXN0KHMuY29mZmVlLCBtYWluID0gIkhpc3RvZ3JhbSBvZiBDb2ZmZWUgVm9sdW1lIiApI2JpbW9kYWwgZGlzdHJpYnV0aW9uDQoNCg0KDQojQnVpbGRpbmcgWiBkaXN0cmlidXRpb24gdG8gQXBwcm94aW1hdGUgZm9yIEFzeW1wdG90aWMgc2FtcGxpbmcgDQpuX2NvZmZlZT1sZW5ndGgocy5jb2ZmZWUpICNzYW1wbGUgc2l6ZSBpcyA1NQ0Kc2RfY29mZmVlID0gc2Qocy5jb2ZmZWUpICNzdGFuZGFyZCBkZXZpYXRpb24gb2Ygc29ydGVkIGNvZmZlZQ0KDQp2YXJfY29mZmVlID0gdmFyKHMuY29mZmVlKSAjY2FsY3VsYXRpbmcgc2FtcGxlIHZhcmlhbmNlIG9mIGNvZmZlZQ0KDQpzZV9jb2ZmZWUgPC0gc2RfY29mZmVlIC8gc3FydChuX2NvZmZlZSkgI3N0YW5kYXJkIGVycm9yIG9mIGNvZmZlZQ0KDQptZWFuLmNvZmZlZT1tZWFuKHMuY29mZmVlKSAjY29mZmVlIG1lYW4gaXMgNTI1MA0KDQplY2RmKHMuY29mZmVlKQ0KDQpmcmVxX2NvZmY9dGFibGUoY29mZmVlcykNCg0KDQoNCm15LkVDREYgPC0gZnVuY3Rpb24oaW5kYXQsIG91dHgpew0KICAjIG91dHggLSBhIHZlY3RvciBvZiBnaXZlbiB2YWx1ZXMNCiAgZnJlcS50YWJsZSA8LSB0YWJsZShpbmRhdCkgICAgICAgICAgICAgICAgICAgICAgICAgICMgZnJlcXVlbmN5IHRhYmxlDQogIHVuaXEgPC0gYXMubnVtZXJpYyhuYW1lcyhmcmVxLnRhYmxlKSkgICAgICAgICAgIyB1bmlxdWUgZGF0YSB2YWx1ZXMNCiAgcmVwLnRpbWUgPC0gYXMudmVjdG9yKGZyZXEudGFibGUpICAgICAgICAgICAgICAgICAgICMgZnJlcXVlbmNpZXMgb2YgdGhlIHVuaXF1ZSBkYXRhIHZhbHVlcw0KICBjdW0ucmVsLmZlcSA8LSBjdW1zdW0ocmVwLnRpbWUpL3N1bShyZXAudGltZSkgICAgICAgIyBjdW11bGF0aXZlIHJlbGF0aXZlIGZyZXF1ZW5jaWVzOiBDREYNCiAgY3VtLnByb2IgPC0gTlVMTA0KICBmb3IgKGkgaW4gMTpsZW5ndGgob3V0eCkpew0KICAgIGludHZsLmlkIDwtIHdoaWNoKHVuaXEgPD0gb3V0eFtpXSkgICAgICAjIGlkZW50aWZ5IHRoZSBpbmRleCBtZWV0aW5nIHRoZSBjb25kaXRpb24NCiAgICBjdW0ucHJvYltpXSA8LSBjdW0ucmVsLmZlcVttYXgoaW50dmwuaWQpXSAjIGV4dHJhY3QgdGhlIGN1bXVsYXRpdmUgcHJvYiBhY2NvcmRpbmcgdG8gQ0RGIA0KICB9DQogIGN1bS5wcm9iICAgICAgICAgICAgIA0KfQ0KDQpwbG90KHMuY29mZmVlLCBteS5FQ0RGKGluZGF0ID0gY29mZmVlcywgb3V0eCA9IHMuY29mZmVlKSwgdHlwZSA9ICJzIiwNCiAgICAgbWFpbiA9ICJFQ0RGIG9mIENvZmZlZSBWb2x1bWUiLA0KICAgICB4bGFiID0gIkNvZmZlZSBWb2x1bWUiLA0KICAgICB5bGFiID0gIkN1bXVsYXRpdmUgUHJvYmFiaWxpdHkiKQ0KDQoNCg0KYGBgDQoNCkluIHRoZSBoaXN0b2dyYW0gb2YgY29mZmVlIHZvbHVtZSB0aGUgZGlzdHJpYnV0aW9uIGlzIG5vdCBub3JtYWxseSBkaXN0cmlidXRlZCBidXQsIGJpbW9kYWwsIG1lYW5pbmcgaGF2aW5nIHR3byBwZWFrcy4gVGhlcmUgaXMgbW9zdCBsaWtlbHkgYSBzZXBhcmF0aW9uIGluIG91ciBkYXRhc2V0IHRoYXQgY2F1c2VzIHRoZSB2b2x1bWVzIHRvIHNpdCBpbiB0d28gZGlmZmVyZW50ICdzdWJzZXRzJy4NCg0KDQpPdXIgY29mZmVlIHZvbHVtZSBzYW1wbGUgbWVhbiB1c2luZyB0aGUgQ0xUIGFwcHJveGltYXRpb24gZGlzdHJpYnV0aW9uIGlzIDUyNTAgbUwuDQogDQoNCg0KDQpiKSBBcHBseSB0aGUgYm9vdHN0cmFwIG1ldGhvZCB0byBlc3RpbWF0ZSB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIChvZnRlbiBjYWxsZWQgdGhlIGJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24pIG9mIHRoZSBzYW1wbGUgbWVhbi4gR2VuZXJhdGUgYSBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSBmcm9tIHRoZSBib290c3RyYXAgc2FtcGxlIG1lYW5zIGFuZCBwbG90IGl0LiBUaGVuLCB1c2UgdGhpcyBib290c3RyYXAgZGlzdHJpYnV0aW9uIHRvIHZhbGlkYXRlIHlvdXIgY29uY2x1c2lvbiBmcm9tIHBhcnQgKGEpLiBNYWtlIHN1cmUgeW91ciB2aXN1YWxzIGFyZSBlZmZlY3RpdmUgaW4gZW5oYW5jaW5nIHRoZSBwcmVzZW50YXRpb24gb2YgdGhlc2UgcmVzdWx0cy4NCg0KYGBge3J9DQojQXBwbHkgdGhlIGJvb3RzdHJhcCBtZXRob2QgdG8gdGhlIHNhbXBsZSBtZWFuDQojR2VuZXJhdGUgYSBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSBmcm9tIHRoZSBib290c3RyYXAgYW5kIHNhbXBsZSBwbG90DQoNCiNjYWxsIHRoZSBzYW1wbGUgZnJvbSB0aGUgcG9wdWxhdGlvbg0Kc2V0LnNlZWQoMTQyKQ0KDQpzLmNvZmZlZQ0KI2NyZWF0ZSBhbiAgZW1wdHkgdmVjdG9yIHRvIGNhbGN1bGF0ZSB0aGUgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbiBtZWFuIGluIHRoZSBmb3IgbG9vcA0KDQpzLmNvZmZlZS52ZWMubWVhbiA9IE5VTEwNCg0KI3NhbXBsZSBmcm9tIHRoZSBwb3B1bGF0aW9uDQoNCmZvcihpIGluIDE6MTAwMCkNCnsNCiANCml0aC5jb2ZmZWUuc2FtcGxlPXNhbXBsZShzLmNvZmZlZSwgNTUsIHJlcGxhY2U9IFRSVUUpICNyYW5kb21seSBzZWxlY3QgZnJvbSBvcmlnaW5hbCBzYW1wbGUNCiNPdXIgc2FtcGxlIHNpemUgaXMgNTUNCiNyZXBsYWNlIG91ciBzYW1wbGUgZWFjaCBsb29wIGJlY2F1c2Ugd2UgZG8gbm90IGhhdmUgYSBsYXJnZSBzYW1wbGUNCg0Kcy5jb2ZmZWUudmVjLm1lYW5baV0gPSBtZWFuKGl0aC5jb2ZmZWUuc2FtcGxlKSAjY2FsY3VsYXRlZCBtZWFuOiA1MjA3LjI3Mw0KICANCn0NCg0Ka2RlID0gZGVuc2l0eShzLmNvZmZlZS52ZWMubWVhbiwgYncgPSBzZF9jb2ZmZWUpDQoNCiNnZW5lcmF0ZSBhIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlIGZyb20gdGhlIGJvb3RzdHJhcCBmcm9tIHRoZSBzYW1wbGUgbWVhbnMgYW5kIHBsb3QgaXQNCg0KaGlzdChzLmNvZmZlZS52ZWMubWVhbiwgI2RhdGFwb2ludCBha2Egc3RhdGlzdGljIHdlIGp1c3QgZ2VuZXJhdGVkLCB3ZSB3YW50IHRvIHNlZSBpdHMgc2ltdWxhdGVkIGRpc3RydWJ1dGlvbg0KICAgICAgICBwcm9iYWJpbGl0eSA9IFRSVUUsICAjaWRlbnRpZnkgdGhlIHJlbGF0aXZlIGZyZXF1ZW5jeSAoYWx3YXlzIHNheSB0cnVlKQ0KICAgICAgICBicmVha3MgPSAxNCwNCiAgICAgICAgeGxhYiA9ICJzYW1wbGUgbWVhbnMgb2YgcmVwZWF0ZWQgc2FtcGxlcyIsICNsYWJlbCB0aGUgeCBheGlzDQogICAgICAgIG1haW49ICJBcHByb3hpbWF0ZWQgU2FtcGxpbmcgRGlzdHJ1YnV0aW9uIFxuIG9mIFNhbXBsZSBNZWFucyAtIEJvb3RzdHJhcCBSZXNhbXBsaW5nIiwNCiAgICAgY2V4Lm1haW4gPSAwLjksDQogICAgIGNvbC5tYWluID0gImRhcmtncmVlbiINCiAgICAgKQ0KbGluZXMoZGVuc2l0eShzLmNvZmZlZS52ZWMubWVhbiwga2VybmVsID0gImdhdXNzaWFuIiksIGNvbD0gInNreWJsdWUiLCBsd2Q9MikgI3doYXQgdGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gbG9va3MgbGlrZSANCg0KDQoNCg0KDQojIEtERSBiYXNlZCBvbiBidWlsdC1pbiBmdW5jdGlvbiBkZW5zaXR5KCk6IGJhbmR3aWR0aCA9IDAuNA0KDQojIyMjIyMjIyMjIyBwbG90IHdoYXQgdGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gbG9va3MgbGlrZSB3aGF0IGtlcm5lbCAjIyMjDQogIA0KDQoNCmBgYA0KDQpUaGUgc2ltdWxhdGVkIGJvb3RzdHJhcCByZXNhbXBsaW5nIG1lYW4gZm9yIHRoZSBjb2ZmZWUgdm9sdW1lIGlzIDUyMDcuMjczIG1MLg0KDQoNCldlIHNlZSBvdXIgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbiBnYXZlIGlzIGEgYXBwcm94aW1hdGVseSBub3JtYWwgZGlzdHJpYnV0aW9uIG9mIHRoZSBtZWFucywgb3VyIHBhcmFtZXRlciBzdGF0aXN0aWMgb2YgaW50ZXJlc3QuIA0KDQpPdXIgY2FsY3VsYXRlZCBtZWFuIG9mIGNvZmZlZSB2b2x1bWUgdXNpbmcgdGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gaXMgNTIxNy4yNzMgbUwuDQoNCg0KYGBge3J9DQoNCmJvb3RfZGYgPC0gZGF0YS5mcmFtZShib290X21lYW5zID0gcy5jb2ZmZWUudmVjLm1lYW4pICNDcmVhdGUgYSBjb21wYXJpc29uIGRhdGFmcmFtZSB0byBjb21wYXJlIHRoZSBDTFQgQXN5bXB0b3RpYyBEaXN0cmlidXRpb24gYW5kIHRoZSBCb290c3RyYXAgRGlzcnR1YnV0aW9uDQoNCg0KbWVhbi5jb2ZmZWUgPC0gbWVhbihzLmNvZmZlZSkgICAgIyBDZW50ZXIgKDUyNTApICNDYWxsIHRoZSBDTFQgYXN5bXB0b3RpYyAgIHBhcmFtZXRlcnMgZm9yIGNvbXBhcmlzb24NCnNlX2NvZmZlZSA8LSBzZChzLmNvZmZlZSkgLyBzcXJ0KGxlbmd0aChzLmNvZmZlZSkpICANCg0KIA0KZ2dwbG90KGJvb3RfZGYsIGFlcyh4ID0gYm9vdF9tZWFucykpICsgI2NyZWF0ZSBwbG90IHVzaW5nIGNvZmZlZSBtZWFuIGFrYSAgYm9vdHNfbWVhbg0KICAjY3JlYXRpbmcgYSBoaXN0b2dyYW0gYmFzZWQgb24gdGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gYWZ0ZXJfc3RhdChkZW5zaXR5KSksIGJpbnMgPSAzMCwgDQogICAgICAgICAgICAgICAgIGZpbGwgPSAiZGFya2dyYXkiLCBhbHBoYSA9IDAuNCwgY29sb3IgPSAiYmxhY2siKSArDQogIA0KICAjIEI6IFRoZSBLREUgKEdhdXNzaWFuIEtlcm5lbCAtIFNtb290aGluZyB0aGUgQm9vdHN0cmFwIHJlc3VsdHMpDQogICMgUiBkZWZhdWx0cyB0byBhIEdhdXNzaWFuIGtlcm5lbCBoZXJlDQogIGdlb21fZGVuc2l0eShjb2xvciA9ICJibHVlIiwgbGluZXdpZHRoID0gMS4yKSArICNhZGQgYSBsYXllciBmb3IgYSBHYXVzc2lhbiBsaW5lIHdpdGggYSANCiAgDQogICMgQzogVGhlIENMVCBOb3JtYWwgQ3VydmUgKFZhbGlkYXRpb24gZnJvbSBQYXJ0IEEpDQogICNiYXNlZCBvbiB0aGUgbWVhbiBvZiBjb2ZmZWUgYW5kIHN0YW5kYXJkIGVycm9yIGZvciBhIEFzeW1wdG90aWMgZGlzdHJpYnV0aW9uDQogIHN0YXRfZnVuY3Rpb24oZnVuID0gZG5vcm0sIGFyZ3MgPSBsaXN0KG1lYW4gPSBtZWFuLmNvZmZlZSwgc2QgPSBzZV9jb2ZmZWUpLCANCiAgICAgICAgICAgICAgICBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBsaW5ld2lkdGggPSAxKSArDQogIA0KICAjIExhYmVscyBhbmQgVGhlbWUNCiAgbGFicyh0aXRsZSA9ICJBcHByb3hpbWF0ZWQgU2FtcGxpbmcgRGlzdHJpYnV0aW9uIG9mIFNhbXBsZSBNZWFucyIsDQogICAgICAgc3VidGl0bGUgPSAiR3JheTogQm9vdHN0cmFwIEhpc3QgfCBCbHVlOiBHYXVzc2lhbiBLREUgfCBSZWQ6IENMVCBOb3JtYWwiLA0KICAgICAgIHggPSAiU2FtcGxlIE1lYW4gVm9sdW1lIChtTCkiLCANCiAgICAgICB5ID0gIkRlbnNpdHkiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KQXMgbWVudGlvbmVkIHByaW9yLCBib3RoIHRoZSBib290c3RyYXAgYW5kIHRoZSBDTFQgQXN5bXB0b3RpYyBTYW1wbGluZyBEaXN0cmlidXRpb24gY2FuIGJlIHVzZWQgb24gdGhpcyBub24tY29tcGxleCBkaXN0cmlidXRpb24gdHlwZSwgdGh1cyB0aGUgZGlzdHJpYnV0aW9ucyBmb3IgdGFrZW4gYm90aCBmb3IgdGhlIGJvb3RzdHJhcCBhbmQgYXN5bXB0b3RpYyBwcmVzZW50IHNpbWlsYXIgcmVzdWx0cy4gQQ0KDQoNCg0KDQpjKSBSZXBlYXQgdGhlIGFuYWx5c2lzIGluIHBhcnRzIChhKSBhbmQgKGIpIGZvciB0aGUgc2FtcGxlIHZhcmlhbmNlLg0KDQoNCmBgYHtyfQ0Kb3B0aW9ucyhzY2lwZW4gPSAwKQ0KDQojUGFydCBhIGZvciBWYXJpYW5jZQ0KdmFyX2NvZmZlZSA9IHZhcihzLmNvZmZlZSkgI2NhbGN1bGF0aW5nIHNhbXBsZSB2YXJpYW5jZSBvZiBjb2ZmZWUgPSA1MDMwODMzDQoNCiMjUGFydCBCIGZvciBWYXJpYW5jZSAgDQoNCiNjYWxsIHRoZSBzYW1wbGUgZnJvbSB0aGUgcG9wdWxhdGlvbg0Kc2V0LnNlZWQoMTQyKQ0KDQpzLmNvZmZlZQ0KI2NyZWF0ZSBhbiAgZW1wdHkgdmVjdG9yIHRvIGNhbGN1bGF0ZSB0aGUgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbiBtZWFuIGluIHRoZSBmb3IgbG9vcA0KDQpzLmNvZmZlZS52ZWMudmFyID0gTlVMTA0KDQojc2FtcGxlIGZyb20gdGhlIHBvcHVsYXRpb24NCg0KZm9yKGkgaW4gMToxMDAwKQ0Kew0KIA0KaXRoLmNvZmZlZS5zYW1wbGUudj1zYW1wbGUocy5jb2ZmZWUsIDU1LCByZXBsYWNlPSBUUlVFKSAjcmFuZG9tbHkgc2VsZWN0IGZyb20gb3JpZ2luYWwgc2FtcGxlDQojT3VyIHNhbXBsZSBzaXplIGlzIDU1DQojcmVwbGFjZSBvdXIgc2FtcGxlIGVhY2ggbG9vcCBiZWNhdXNlIHdlIGRvIG5vdCBoYXZlIGEgbGFyZ2Ugc2FtcGxlDQoNCnMuY29mZmVlLnZlYy52YXJbaV0gPSB2YXIoaXRoLmNvZmZlZS5zYW1wbGUudikgI2NhbGN1bGF0ZWQgdmFyaWFuY2U6IDQ4NDQ3NjENCiAgDQp9DQoNCmtkZVYgPSBkZW5zaXR5KHMuY29mZmVlLnZlYy52YXIpDQoNCiNnZW5lcmF0ZSBhIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlIGZyb20gdGhlIGJvb3RzdHJhcCBmcm9tIHRoZSBzYW1wbGUgbWVhbnMgYW5kIHBsb3QgaXQNCg0KaGlzdChzLmNvZmZlZS52ZWMudmFyLCAjZGF0YXBvaW50IGFrYSBzdGF0aXN0aWMgd2UganVzdCBnZW5lcmF0ZWQsIHdlIHdhbnQgdG8gc2VlIGl0cyBzaW11bGF0ZWQgZGlzdHJ1YnV0aW9uDQogICAgICAgIHByb2JhYmlsaXR5ID0gVFJVRSwgICNpZGVudGlmeSB0aGUgcmVsYXRpdmUgZnJlcXVlbmN5IChhbHdheXMgc2F5IHRydWUpDQogICAgICAgIGJyZWFrcyA9IDE0LA0KICAgICAgICB4bGFiID0gInNhbXBsZSB2YXJpZW5jZSBvZiByZXBlYXRlZCBzYW1wbGVzIiwgI2xhYmVsIHRoZSB4IGF4aXMNCiAgICAgICAgbWFpbj0gIkFwcHJveGltYXRlZCBTYW1wbGluZyBEaXN0cnVidXRpb24gXG4gb2YgU2FtcGxlIFZhcmllbmNlIC0gQm9vdHN0cmFwIFJlc2FtcGxpbmciLA0KICAgICBjZXgubWFpbiA9IDAuOSwNCiAgICAgY29sLm1haW4gPSAiZGFya2dyZWVuIg0KICAgICApDQpsaW5lcyhkZW5zaXR5KHMuY29mZmVlLnZlYy52YXIsIGtlcm5lbCA9ICJnYXVzc2lhbiIpLCBjb2w9ICJza3libHVlIiwgbHdkPTIpICN3aGF0IHRoZSBib290c3RyYXAgZGlzdHJpYnV0aW9uIGxvb2tzIGxpa2UgDQoNCg0KDQpgYGANCg0KDQpUaGUgYXN5bXB0b3RpYyBzYW1wbGluZyBkaXN0cmlidXRpb24gaXMgYSBkaXN0cmlidXRpb24gYmV0dGVyIHJlcHJlc2VudGVkIGZvciBub24tY29tcGxleCB2YWx1ZXMuIEFzIHRoZSB2YXJpYW5jZSBpcyBhIHNxdWFyZWQgcGFyYW1ldGVyIHRoYXQgYWRkcyBjb21wbGV4aXR5IGEgYXN5bXB0b3RpYyBzYW1wbGluZyBkaXN0cmlidXRpb24gaXMgbm90IGEgc3Ryb25nIGRpc3RyaWJ1dGlvbiB0eXBlIGZvciBpZGVudGlmeWluZyBhIHZhcmlhbmNlIHBhcmFtZXRlci4gQSBib290c3RyYXAgcmVzYW1wbGluZyBkaXN0cmlidXRpb24gaXMgYSBiZXR0ZXIgc3VpdGVkIGRpc3RyaWJ1dGlvbiB0eXBlIGZvciBpZGVudGlmeWluZyBhIHZhcmlhbmNlJ3MgYWRkZWQgY29tcGxleGl0eS4gDQoNCg0KDQo=