1 Introduction

This note covers the definitions and inter-relationships of normal, t, chi-square, and F distributions, and their assumptions.

2 Normal Distrubtions

A normal distribution is a parametric distribution. A parametric distribution assumes the shape of the distribution. In other words, a parametric model assumes how the data is organized to make analyses from.

A normal distribution assumes about:
* 68% of data is 1 standard deviation of the mean
* 95% of the data is 2 standard deviations of the mean
* 99.7% of the data is 3 standard deviations of the mean
(Wackery, Mendenhall, Scheaffer, 1945, p.10).

 Normal Distrubtion

Normal Distrubtion

The assumed normal distribution takes on a bell curve. Demonstrated by the formula:

\[ f(y) = \frac{1}{\sigma\sqrt{2\pi}} e^{-\frac{(y-\mu)^2}{2\sigma^2}} \]

Note: What is a standard deviation? - A standard deviation measures how much variation (or how dispersed) a set of values is from the mean. A lower standard deviation (ig. 1 standard deviation from the mean) is a value closer to the mean. A value closer the the mean as well as lower variance may suggest a stronger value or model. As lower variance may suggest points are clustered tightly around the the mean while higher variance suggests the data is spread out, potentially containing outliers.

2.1 Assumptions for Normal Distrubutions

  1. Data is continuous
  2. Symmetric with one peak
  3. Bell Shaped
  4. Mean, median and mode all assumed to be equal

3 Using Normal Distrubutions for Estimation

As the majority of random samples take on a normal distribution as using a parametric normal distribution as a sole estimator for a true Cumulative density function (CDF) should come with causation because assuming the shape of sample may add noise or bias into the estimator and or analysis, as adding a parameter test may not best hit the sample and or population.

-Note in most cases the population parameters and or distribution is unknown.

Although the majority of random samples take on a normal distribution inherently taking on a parametric distribution as a estimator for a true Cumulative density function (CDF), always assuming a normal distribution should come with caution. Assuming the shape of sample, when the sample distribution shape may be unknown may add noise or bias into the estimator and or analysis. The a parameter test may not best fit the sample and or population. If we force a bell-curve onto data that is actually skewed (leaning to one side instead of symmetric and non-naturally bell-shaped) our conclusions will hold bias.

Note in many cases the true population’s parameters or distributions are unknown so assuming shape may increase chance of error.

# https://www.biologyforlife.com/skew.html

knitr::include_graphics("C:/Users/75ER969287/OneDrive - West Chester University of PA/STA 506 - Mathematical Statistics II/Weekly Modules/Week 3/Homework/skewness image image 2.png")

3.1 Normal Distrubution Advantages

Despite a normal distribution being a parametric distribution that assumes shape, there are many advantages to using a normal distribution.***********

Uses for a normal distribution

  • A normal distribution has act as a comparison and validity checker
    • A normal distribution
      Often the case for linear regression, t-test and ANOVA residual tests /
    • We will later discuss an normal distribution assumption to assess the quality of two models by their variance ratio, also known as an F distribution /
    • Overall we often use normal distribution as the bases to make conclusions or approximations about our distributions because often samples or population often approach normal distributions and we can standardize our distributions relatively easily to match a universal scale for standard deviations. Regardless of the data’s original units, we can standardize within our data to digest how rare or common a data point is in respect to the other values.
  • Estimation for the Cumulative Distribution Function A normal distribution can act as an estimator for the cumulative distribution function. if an empirical CDF is used, the theoretical normal distribution function can be a base comparison to see if these two are statistically different.

In this case the empirical CDF is model based on the data observed. We can compare how well an empirical model compares to a theoretical normal distribution model to help us understand any nuance in our observed data.

set.seed(45)
# Generate sample data
sample_data <- rnorm(100, mean = 0, sd = 1)

# Create empirical CDF
empirical_cdf <- ecdf(sample_data)

# Plot empirical vs theoretical CDF
plot_df <- data.frame(
  x = seq(-5, 5, length.out = 2500),
  Empirical = empirical_cdf(seq(-15, 15, length.out = 2500)),
  Theoretical = pnorm(seq(-15, 15, length.out = 2500))
)

plot_df_long <- plot_df %>%
  pivot_longer(cols = c(Empirical, Theoretical), 
               names_to = "Type", values_to = "CDF")

Fn.plt <- ggplot(plot_df_long, aes(x = x, y = CDF, color = Type)) +
  geom_line(linewidth = 1) +
  scale_color_manual(values = c("Empirical" = "green", "Theoretical" = "purple")) +
  labs(title = "Empirical vs Theoretical CDF",
       subtitle = "Sample size n = 100 from Standard Normal",
       x = "x", y = "CDF") +
  theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))
ggplotly(Fn.plt)

While the Normal distribution is the foundation of parametric inference, it can be applied to describe a sampling distribution in two distinct capacities:

  1. Exact Distribution: our population distribution is known to be normally distributed with random variables that are identically and independently distributed within a small sample size or

Because we know our population distribution is normal we can standardize our distribution sample to be under one.

\[ Z = \frac{\bar{X} - \mu}{\sigma / \sqrt{n}} \rightarrow^d N(0,1) \]

  1. Asymptotic Distribution our population distribution is unknown but our sample size is large

3.2 Extract Distrubtion

A exact distribution assumes a normally distributed population with random variables that are identically and independently distributed within a small sample size. Our random variables are collected and treated independently, as the probability of the one value does not effect the probability of the next value.

3.3 Asymptotic Distribution Relation in Normal Distrubution

As mentioned earlier, there are some advantages to using the normal distribution despite its shape assumption.

As we take a random sample from the population in which we are not sure of its distribution, we use the normal distribution as an approximation for the true distribution.

Due to the large sample size, we can use the Central Limit Theorem to assume our sample statistic (often our sample mean) approaches and reaches a normal distribution. Even if in smaller quantities the distribution may not appear normal, with a large sample size our distribution my converge to a normal distribution. If an original population contains skew in its distribution, with a large enough sample the distribution can place into a bell curve.

# Set a seed so the random results are the same every time you 'knit'
set.seed(12)

# Define number of simulations and different sample sizes to test
n_simulations <- 10000
sample_sizes <- c(2, 5, 20, 50)

# Set up a 2x2 grid for the graphs
par(mfrow = c(2, 2))

for (n in sample_sizes) {
  # 1. Take 10,000 random samples of size 'n' from a skewed population
  # 2. Calculate the mean for each of those 10,000 samples
  sample_means <- replicate(n_simulations, mean(rexp(n, rate = 1)))
  
  # 3. Create the histogram
  hist(sample_means, 
       breaks = 40, 
       freq = FALSE, 
       main = paste("Sample Size n =", n),
       xlab = "Value of Sample Mean", 
       col = "skyblue", 
       border = "white")
  
  # 4. Add a theoretical Normal Curve (Red line) to see the fit
  # The mean of our population is 1, and SD is 1.
  curve(dnorm(x, mean = 1, sd = 1/sqrt(n)), 
        add = TRUE, col = "red", lwd = 2)
}

In these images we see as the sample size (n) increases,the distribution to moves to be less skewed into a more normal distribution.

As the observed distribution, may not follow a normal distribution directly we standardize our values into a normal distribution, using the following formula. Note this formula is an approximation. An approximation acts as best estimate considering we do not know the true distribution, unlike the exact distribution.

\[ Z = \frac{\bar{X} - \mu}{\sigma / \sqrt{n}} \rightarrow^{aprox} N(0,1) \]

By standardizing our values into Z scores, we can approximate our probability distribution sample statistics, which are values like the mean, proportion, or regression coefficient.

4 t-distubution

We used a normal distribution when our population standard deviation \(\sigma^2\) was known. When we do not know our population’s standard deviation we use a t distribution.

When we do not know our population’s standard deviation we estimate using the sample variance \(S^2\) .
\[ T = \frac{\bar{X} - \mu}{\ S/ \sqrt{n}} \rightarrow t_{n-1} \] Our formula for out sample variance \(S^2\) is :

\[ S^2 = \frac {1}{n-1} \sum_{i=1}^{n} ({x_i -\bar{X}})^2 \] In our T distribution since we do not know our population standard deviation and divide by the sample standard deviation, we must consider the variation within the sample, which is why we divide \(S\) by the square root of the sample size.

As the shape of a t-distribution and normal distribution by the naked eye follow highly similar shapes the formulaic difference of the \(S /\sqrt{n}\) ,in the t distribution denominator, causes more uncertainty in the distribution leading to wider “fatter” tails in the t- distribution rather than the normal distribution. Unlike in the normal distribution where we know the variance, or spread of data, with the goal of finding the sample mean, in a t-distribution we neither know the variance nor the sample mean, leading to a greater chance of uncertainty. Greater uncertainty ultimately leads us to have fatter tails showing higher variance, although as n increases this uncertainty is reduced, giving a smaller standard deviation \(S^2\) ultimately decreasing the spread in the distribution.

Note as our sample size grows, the tails of the t-distribution get less fat, often converging closer the a normal distribution. Similar to our Central Limit Theron where the larger our sample size, the more our model converges to the normal distribution. The formula component of \(\sqrt{n}\) assists in changing the distribution shape, as the level of n contributes to the degrees of freedom, the only parameter in the t-distribution formula.

Below we compare a t-distribution with a normal distribution. Note the t-distribution has ‘fatter’ tails.

set.seed(359)
n <- 15
mu <- 5
sigma <- 2

# Generate t-statistics
n.samples <- 10000
t.stats <- numeric(n.samples)  # This defines a 10000 dimensional zero vector
                               # t.test <- NULL uses more computing resource
for(i in 1:n.samples) {
  sample.data <- rnorm(n, mu, sigma)
  x.bar <- mean(sample.data)
  s <- sd(sample.data)
  t.stats[i] <- (x.bar - mu) / (s/sqrt(n))
}

# Compare with theoretical t-distribution
x.vals <- seq(-4, 4, length.out = 200)
theoretical.t <- dt(x.vals, df = n-1)    # calling t-density function
theoretical.normal <- dnorm(x.vals)      # standard normal distribution

comparison.df <- data.frame(
  x = rep(x.vals, 2),
  density = c(theoretical.t, theoretical.normal),
  distribution = rep(c("t(9)", "N(0,1)"), each = length(x.vals))
)

t.plt <- ggplot(comparison.df, aes(x = x, y = density, color = distribution)) +
  geom_line(size = 1) +
  labs(title = "t-Distribution vs Normal Distribution",
       x = "Value", y = "Density") +
    theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt")) +
   scale_color_manual(values = c("blue", "orange"))
ggplotly(t.plt)

Why our t-distribution connects with the normal distribution?

Our t-distribution in function behaves similarly to the normal distribution. Our normal standardized formula and normal distribution formula share a numerator accounting for the distance between the mean and the observed value ( shared numerator: \(\bar{X} - \mu\)). Even in shape both the t and normal distributions share a bell curve centered at 0. When the sample size is large enough a t distribution can become a normal distribution. Our t-distribution converging to the normal distribution is valuable because with a large enough sample size, our sample variance because accurate enough to account as the true population variance, allowing our statistics to be more accurate as they are closer to the true population.

Our assumptions of the t-distribution include independent random observations, random sampling, and that our population is normally distributed.

As t distributions tend to converge into normal distributions upon large sample size, often t distributions prior to converging have smaller sample sizes.

The t-distribution considers estimations for the sample mean, we use a chi-squared distribution to assess the variance, also known as spread, of the distribution.

5 Chi-Squared Distrubution

A chi-squared distribution is also a distribution type that can converge into normal distribution. A chi- squared distribution is a special case of a gamma distribution, in which both distributions have skewness.

Below is an example of a chi-square distribution:

set.seed(6)
n <- 5
sigma <- 2

# Generate chi-square statistics
n.samples <- 10000
chisq.stats <- numeric(n.samples)

for(i in 1:n.samples) {
  sample.data <- rnorm(n, 0, sigma)
  chisq.stats[i] <- sum((sample.data/sigma)^2)
}

# Compare with theoretical chi-square
x.vals <- seq(0, 30, length.out = 200)
theoretical.chisq <- dchisq(x.vals, df = n)
theory.df <- data.frame(x = x.vals, density = theoretical.chisq)

chi.plt <- ggplot(data.frame(x = chisq.stats), aes(x = x)) +
  geom_histogram(aes(y = ..density..), bins = 50, alpha = 0.7, fill = "green") +
  geom_line(data = theory.df, aes(x = x, y = density), 
            color = "blue", linewidth = 1.5) +
  #stat_function(fun = dchisq, args = list(df = n), color = "red", size = 1) +
  labs(title = "Chi-Squared Distribution (n=5) ",
       subtitle = "Sum of squared standard normals",
       x = "Value", y = "Density") +
   theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))
ggplotly(chi.plt)

An increase in sample size can lead to a normal distribution, as increase in sample size reduces the skewness.

set.seed(6)
n <- 500
sigma <- 2

# Generate chi-square statistics
n.samples <- 10000
chisq.stats <- numeric(n.samples)

for(i in 1:n.samples) {
  sample.data <- rnorm(n, 0, sigma)
  chisq.stats[i] <- sum((sample.data/sigma)^2)
}

# Compare with theoretical chi-square
x.vals <- seq(0, 1100, length.out = 200)
theoretical.chisq <- dchisq(x.vals, df = n)
theory.df <- data.frame(x = x.vals, density = theoretical.chisq)

chi.plt <- ggplot(data.frame(x = chisq.stats), aes(x = x)) +
  geom_histogram(aes(y = ..density..), bins = 50, alpha = 0.7, fill = "green") +
  geom_line(data = theory.df, aes(x = x, y = density), 
            color = "blue", linewidth =1.5) +
  #stat_function(fun = dchisq, args = list(df = n), color = "red", size = 1) +
  labs(title = "Chi-Squared Distribution (n=500) ",
       subtitle = "Sum of squared standard normals",
       x = "Value", y = "Density") +
   theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))
ggplotly(chi.plt)

A chi-square distribution can derive from an exact normal distribution. It can essentially act as a squared standard normal with one degree of freedom or a sum of squares with more than 1 degree of freedom, adding skewness to a normal distribution. As the chi-square is a squared normal, the distribution can never be negative, exaggerating any right skewness. In other words, a chi-squared distribution can be described as a normal distribution, whose center has moved and now possesses skewness.

In contribution that the variance is a squared parameter, the sampling distribution of the sample variance can be described as a chi-square distribution upon scaling. When our sample size increases,the degree of freedom parameter \((n-1)\) in our numerator increases. The Central Limit Theorem helps our chi-squared distribution take on a normal distribution, smoothing the skewness into a bell-shape, as the sample size increase.

Our chi-square distribution relationship with a normal distribution:

\[ \frac{(n-1)S^2}{\sigma^2} \rightarrow \chi^2_{n-1} \]

Like a t-distribution, our assumptions about a chi-square distribution is that we sample from a normally distributed population as well as individually and independently distributed. The chi-squared and t-distribution have degrees of freedom in their parameters, dictating the shapes of their distributions.

6 F distrubution

With our chi-squared distribution we see the variance of our distribution. Often we have multiple distributions and we need to relate the variances to each other to see quality of the two distributions. Hence we build a F distribution as a ratio of two chi-squared variables of independent sample variances. Like the individual chi-squared, both assume normal distribution. These chi-squared distributions source from independent populations.

\[ {X_1, X_2, ...X_n} ~ ^{i.i.d} N(\mu_2, \sigma^2_1) \\ and \\{Y_1, Y_2, ...Y_n} ~ ^{i.i.d} N(\mu_2, \sigma^2_2) \] \[ S^2_1 = \frac {1}{n_1-1} \sum_{i=1}^{n} ({X_i -\bar{X}})^2 \\and\\ S^2_2 = \frac {1}{n_2-1} \sum_{i=1}^{n} ({Y_i -\bar{Y}})^2 \] Define \[ F= \frac {S^2_1/ \sigma^2} {S^2_2/\sigma^2_2} \rightarrow^d F_{n-1, n_2-1} \]

The 1 degree of freedom each chi-squares hold in the F-distribution give us 2 degrees of freedom (one in the denominator, and one in the numerator) that both contribute to the distribution’s shape.

In the greater the F distribution ratio, the more variance in the numerator’s distribution. The smaller the variance the variance is larger in the denominator distribution. If the F distribution ratio is 1, the two variances in the numerator and denominator are equal.

set.seed(45)
df1 <- 20
df2 <- 25

# Generate F statistics
n.samples <- 10000
f.stats <- numeric(n.samples)

for(i in 1:n.samples) {
  u1 <- rchisq(1, df1)
  u2 <- rchisq(1, df2)
  f.stats[i] <- (u1/df1) / (u2/df2)
}

# Compare with theoretical F-distribution
x.vals <- seq(0, 5, length.out = 200)
theoretical.f <- df(x.vals, df1, df2)
theory.df <- data.frame(x = x.vals, density = theoretical.f)




f.plt <- ggplot(data.frame(x = f.stats), aes(x = x)) +
  geom_histogram(aes(y = ..density..), bins = 50, alpha = 0.7, fill = "blue") +
  geom_line(data = theory.df, aes(x = x, y = density), 
            color = "red", linewidth = 1) +
  coord_cartesian(xlim = c(0, 5)) +
  labs(title = paste("F-Distribution \n F(", df1, ",", df2, ")", sep = ""),
       x = "Value", y = "Density") +
  theme(plot.title = element_text(hjust = 0.5),
        plot.margin = margin(t = 35, r = 20, b = 30, l = 30, unit = "pt"))
ggplotly(f.plt)

7 Conclusion

Assuming a normal distribution allows us to connect a t distribution to a normal distribution. A normal distribution can be used towards a chi- squared distribution to assess model variance and two chi-square tests can be used in an F distribution ratio to assess the overall quality of two distributions.

The normal distribution builds into advanced analyse that allow us to consider the quality of our distribution. Without a standardized distribution shape that the normal distribution gives us, making these comparisons would be challenging, especially through various unit types. Our normal distribution allows us to organize our distribution for analysis, and test the quality of an observed data set either through approximation or theoretical comparison.

LS0tDQp0aXRsZTogIkhvbWV3b3JrIDIiDQphdXRob3I6ICJFemFuYSBSaXZlcnMiDQpkYXRlOiAiMDItMTAtMjAyNiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jX2NvbGxhcHNlZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgdGhlbWU6IGx1bWVuDQogIHBkZl9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBmaWdfd2lkdGg6IDMNCiAgICBmaWdfaGVpZ2h0OiAzDQogIHdvcmRfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIGtlZXBfbWQ6IHllcw0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KYGBge2NzcywgZWNobyA9IEZBTFNFfQ0KI1RPQzo6YmVmb3JlIHsNCiAgY29udGVudDogIlRhYmxlIG9mIENvbnRlbnRzIjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtc2l6ZTogMS4yZW07DQogIGRpc3BsYXk6IGJsb2NrOw0KICBjb2xvcjogbmF2eTsNCiAgbWFyZ2luLWJvdHRvbTogMTBweDsNCn0NCg0KDQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovDQogICAgbGlzdC1zdHlsZTp1cHBlci1yb21hbjsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQp9DQoNCmgxLnRpdGxlIHsgICAgLyogbGV2ZWwgMSBoZWFkZXIgb2YgdGl0bGUgICovDQogIGZvbnQtc2l6ZTogMjJweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCn0NCg0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxNXB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsNCiAgY29sb3I6IG5hdnk7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgxIHsgLyogSGVhZGVyIDEgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDIwcHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMiB7IC8qIEhlYWRlciAyIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE2cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KLyogQWRkIGRvdHMgYWZ0ZXIgbnVtYmVyZWQgaGVhZGVycyAqLw0KLmhlYWRlci1zZWN0aW9uLW51bWJlcjo6YWZ0ZXIgew0KICBjb250ZW50OiAiLiI7DQoNCmJvZHkgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQoNCi5oaWdobGlnaHRtZSB7IGJhY2tncm91bmQtY29sb3I6eWVsbG93OyB9DQoNCnAgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQoNCn0NCmBgYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwYW5kZXIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygicGFuZGVyIikNCiAgIGxpYnJhcnkocGFuZGVyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQogIGxpYnJhcnkoZ2dwbG90MikNCn0NCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiAgbGlicmFyeSh0aWR5dmVyc2UpDQp9DQoNCmlmICghcmVxdWlyZSgicGxvdGx5IikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikNCiAgbGlicmFyeShwbG90bHkpDQp9DQppZiAoIXJlcXVpcmUoIm1peHRvb2xzIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygibWl4dG9vbHMiKQ0KICBsaWJyYXJ5KG1peHRvb2xzKQ0KfQ0KDQppZiAoIXJlcXVpcmUoImdncGxvdDIiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCiAgbGlicmFyeShnZ3Bsb3QyKQ0KfQ0KDQoNCmlmICghcmVxdWlyZSgiZ2dhbmltYXRlIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZ2dhbmltYXRlIikNCiAgbGlicmFyeShnZ2FuaW1hdGUpDQp9DQoNCmlmICghcmVxdWlyZSgiZ2lmc2tpIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZ2lmc2tpIikNCiAgbGlicmFyeShnaWZza2kpDQp9DQoNCg0KIyMgbGlicmFyeShtaXh0b29scykNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgICMgc29tZXRpbWVzLCB5b3UgY29kZSBtYXkgcHJvZHVjZSB3YXJuaW5nIG1lc3NhZ2VzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHlvdSBjYW4gY2hvb3NlIHRvIGluY2x1ZGUgdGhlIHdhcm5pbmcgbWVzc2FnZXMgaW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgICAjIHlvdSBjYW4gYWxzbyBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIHRoZSBvdXRwdXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbiB0aGUgb3V0cHV0IGZpbGUuDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQQ0KICAgICAgICAgICAgICAgICAgICAgICkgIA0KDQojIFlvdSB3aWxsIG5lZWQgdGhlc2UgcGFja2FnZXMgaW5zdGFsbGVkOg0KIyBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCiMgaW5zdGFsbC5wYWNrYWdlcygiZ2dhbmltYXRlIikNCg0KDQoNCmBgYA0KDQpcDQoNCg0KIyBJbnRyb2R1Y3Rpb24NCg0KVGhpcyBub3RlIGNvdmVycyB0aGUgZGVmaW5pdGlvbnMgYW5kIGludGVyLXJlbGF0aW9uc2hpcHMgb2Ygbm9ybWFsLCB0LCBjaGktc3F1YXJlLCBhbmQgRiBkaXN0cmlidXRpb25zLCBhbmQgdGhlaXIgYXNzdW1wdGlvbnMuDQoNCg0KIyBOb3JtYWwgRGlzdHJ1YnRpb25zDQoNCkEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBpcyBhIHBhcmFtZXRyaWMgZGlzdHJpYnV0aW9uLiBBIHBhcmFtZXRyaWMgZGlzdHJpYnV0aW9uIGFzc3VtZXMgdGhlIHNoYXBlIG9mIHRoZSBkaXN0cmlidXRpb24uIEluIG90aGVyIHdvcmRzLCBhIHBhcmFtZXRyaWMgbW9kZWwgYXNzdW1lcyBob3cgdGhlIGRhdGEgaXMgb3JnYW5pemVkIHRvIG1ha2UgYW5hbHlzZXMgZnJvbS4NCg0KQSBub3JtYWwgZGlzdHJpYnV0aW9uIGFzc3VtZXMgYWJvdXQ6DQpcDQogICogNjglIG9mIGRhdGEgaXMgMSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIG1lYW4gDQpcDQogICogOTUlIG9mIHRoZSBkYXRhIGlzIDIgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiB0aGUgbWVhbiANClwNCiAgKiA5OS43JSBvZiB0aGUgZGF0YSBpcyAzIHN0YW5kYXJkIGRldmlhdGlvbnMgb2YgdGhlIG1lYW4gDQpcDQooV2Fja2VyeSwgTWVuZGVuaGFsbCwgU2NoZWFmZmVyLCAxOTQ1LCBwLjEwKS4NCg0KICANCmBgYHtyIEltYWdlLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSIgTm9ybWFsIERpc3RydWJ0aW9uIiwgb3V0LndpZHRoPSc3MCUnLCBmaWcuYWxpZ249J2NlbnRlcid9DQogIA0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIkM6L1VzZXJzLzc1RVI5NjkyODcvT25lRHJpdmUgLSBXZXN0IENoZXN0ZXIgVW5pdmVyc2l0eSBvZiBQQS9TVEEgNTA2IC0gTWF0aGVtYXRpY2FsIFN0YXRpc3RpY3MgSUkvV2Vla2x5IE1vZHVsZXMvV2VlayAzL0hvbWV3b3JrL0ltYWdlIDEgbm9ybWFsIGRpc3RydWJ0aW9uIGZvciBhc3NpZ25lbWVudCAyLnBuZyIpDQoNCiNjZW50ZXIgdGhpcyBpbWFnZQ0KDQpgYGANClRoZSBhc3N1bWVkIG5vcm1hbCBkaXN0cmlidXRpb24gdGFrZXMgb24gYSBiZWxsIGN1cnZlLiBEZW1vbnN0cmF0ZWQgYnkgdGhlIGZvcm11bGE6DQoNCiQkDQpmKHkpID0gXGZyYWN7MX17XHNpZ21hXHNxcnR7MlxwaX19IGVeey1cZnJhY3soeS1cbXUpXjJ9ezJcc2lnbWFeMn19DQokJA0KDQpOb3RlOiBXaGF0IGlzIGEgc3RhbmRhcmQgZGV2aWF0aW9uPyANCiAgLSBBIHN0YW5kYXJkIGRldmlhdGlvbiBtZWFzdXJlcyBob3cgbXVjaCB2YXJpYXRpb24gKG9yIGhvdyBkaXNwZXJzZWQpIGEgc2V0IG9mIHZhbHVlcyBpcyBmcm9tIHRoZSBtZWFuLiBBIGxvd2VyIHN0YW5kYXJkIGRldmlhdGlvbiAoaWcuIDEgc3RhbmRhcmQgZGV2aWF0aW9uIGZyb20gdGhlIG1lYW4pIGlzIGEgdmFsdWUgY2xvc2VyIHRvIHRoZSBtZWFuLiBBIHZhbHVlIGNsb3NlciB0aGUgdGhlIG1lYW4gYXMgd2VsbCBhcyBsb3dlciB2YXJpYW5jZSBtYXkgc3VnZ2VzdCBhIHN0cm9uZ2VyIHZhbHVlIG9yIG1vZGVsLiBBcyBsb3dlciB2YXJpYW5jZSBtYXkgc3VnZ2VzdCBwb2ludHMgYXJlIGNsdXN0ZXJlZCB0aWdodGx5IGFyb3VuZCB0aGUgdGhlIG1lYW4gd2hpbGUgaGlnaGVyIHZhcmlhbmNlIHN1Z2dlc3RzIHRoZSBkYXRhIGlzIHNwcmVhZCBvdXQsIHBvdGVudGlhbGx5IGNvbnRhaW5pbmcgb3V0bGllcnMuDQogIA0KDQoNCiMjIEFzc3VtcHRpb25zIGZvciBOb3JtYWwgRGlzdHJ1YnV0aW9ucw0KICAxLiBEYXRhIGlzIGNvbnRpbnVvdXMNCiAgMi4gU3ltbWV0cmljIHdpdGggb25lIHBlYWsNCiAgMy4gQmVsbCBTaGFwZWQNCiAgNC4gTWVhbiwgbWVkaWFuIGFuZCBtb2RlIGFsbCBhc3N1bWVkIHRvIGJlIGVxdWFsICANCg0KDQoNCiMgVXNpbmcgTm9ybWFsIERpc3RydWJ1dGlvbnMgZm9yIEVzdGltYXRpb24NCg0KDQpBcyB0aGUgbWFqb3JpdHkgb2YgcmFuZG9tIHNhbXBsZXMgdGFrZSBvbiBhIG5vcm1hbCBkaXN0cmlidXRpb24gYXMgdXNpbmcgYSBwYXJhbWV0cmljIG5vcm1hbCBkaXN0cmlidXRpb24gYXMgYSBzb2xlIGVzdGltYXRvciBmb3IgYSB0cnVlIEN1bXVsYXRpdmUgZGVuc2l0eSBmdW5jdGlvbiAoQ0RGKSBzaG91bGQgY29tZSB3aXRoIGNhdXNhdGlvbiBiZWNhdXNlIGFzc3VtaW5nIHRoZSBzaGFwZSBvZiBzYW1wbGUgbWF5IGFkZCBub2lzZSBvciBiaWFzIGludG8gdGhlIGVzdGltYXRvciBhbmQgb3IgYW5hbHlzaXMsIGFzIGFkZGluZyBhIHBhcmFtZXRlciB0ZXN0IG1heSBub3QgYmVzdCBoaXQgdGhlIHNhbXBsZSBhbmQgb3IgcG9wdWxhdGlvbi4NCg0KLU5vdGUgaW4gbW9zdCBjYXNlcyB0aGUgcG9wdWxhdGlvbiBwYXJhbWV0ZXJzIGFuZCBvciBkaXN0cmlidXRpb24gaXMgdW5rbm93bi4NCiAgDQoNCkFsdGhvdWdoIHRoZSBtYWpvcml0eSBvZiByYW5kb20gc2FtcGxlcyB0YWtlIG9uIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBpbmhlcmVudGx5IHRha2luZyBvbiBhIHBhcmFtZXRyaWMgZGlzdHJpYnV0aW9uIGFzIGEgZXN0aW1hdG9yIGZvciBhIHRydWUgQ3VtdWxhdGl2ZSBkZW5zaXR5IGZ1bmN0aW9uIChDREYpLCBhbHdheXMgYXNzdW1pbmcgYSBub3JtYWwgZGlzdHJpYnV0aW9uIHNob3VsZCBjb21lIHdpdGggY2F1dGlvbi4gQXNzdW1pbmcgdGhlIHNoYXBlIG9mIHNhbXBsZSwgd2hlbiB0aGUgc2FtcGxlIGRpc3RyaWJ1dGlvbiBzaGFwZSBtYXkgYmUgdW5rbm93biBtYXkgYWRkIG5vaXNlIG9yIGJpYXMgaW50byB0aGUgZXN0aW1hdG9yIGFuZCBvciBhbmFseXNpcy4gVGhlIGEgcGFyYW1ldGVyIHRlc3QgbWF5IG5vdCBiZXN0IGZpdCB0aGUgc2FtcGxlIGFuZCBvciBwb3B1bGF0aW9uLiBJZiB3ZSBmb3JjZSBhIGJlbGwtY3VydmUgb250byBkYXRhIHRoYXQgaXMgYWN0dWFsbHkgc2tld2VkIChsZWFuaW5nIHRvIG9uZSBzaWRlIGluc3RlYWQgb2Ygc3ltbWV0cmljIGFuZCBub24tbmF0dXJhbGx5IGJlbGwtc2hhcGVkKSBvdXIgY29uY2x1c2lvbnMgd2lsbCBob2xkIGJpYXMuIA0KDQpOb3RlIGluIG1hbnkgY2FzZXMgdGhlIHRydWUgcG9wdWxhdGlvbidzIHBhcmFtZXRlcnMgb3IgZGlzdHJpYnV0aW9ucyBhcmUgdW5rbm93biBzbyBhc3N1bWluZyBzaGFwZSBtYXkgaW5jcmVhc2UgY2hhbmNlIG9mIGVycm9yLg0KDQoNCmBgYHtyIGltYWdlc2tldywgb3V0LndpZHRoPSc3MCUnLCBmaWcuYWxpZ249J2NlbnRlcid9DQoNCiMgaHR0cHM6Ly93d3cuYmlvbG9neWZvcmxpZmUuY29tL3NrZXcuaHRtbA0KDQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiQzovVXNlcnMvNzVFUjk2OTI4Ny9PbmVEcml2ZSAtIFdlc3QgQ2hlc3RlciBVbml2ZXJzaXR5IG9mIFBBL1NUQSA1MDYgLSBNYXRoZW1hdGljYWwgU3RhdGlzdGljcyBJSS9XZWVrbHkgTW9kdWxlcy9XZWVrIDMvSG9tZXdvcmsvc2tld25lc3MgaW1hZ2UgaW1hZ2UgMi5wbmciKQ0KDQpgYGANCiAgDQoNCg0KIyMgTm9ybWFsIERpc3RydWJ1dGlvbiBBZHZhbnRhZ2VzIA0KDQpEZXNwaXRlIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBiZWluZyBhIHBhcmFtZXRyaWMgZGlzdHJpYnV0aW9uIHRoYXQgYXNzdW1lcyBzaGFwZSwgdGhlcmUgYXJlIG1hbnkgYWR2YW50YWdlcyB0byB1c2luZyBhIG5vcm1hbCBkaXN0cmlidXRpb24uKioqKioqKioqKioNCg0KVXNlcyBmb3IgYSBub3JtYWwgZGlzdHJpYnV0aW9uIA0KDQotIEEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBoYXMgYWN0IGFzIGEgY29tcGFyaXNvbiBhbmQgdmFsaWRpdHkgY2hlY2tlciANCiAgICAqICAgQSBub3JtYWwgZGlzdHJpYnV0aW9uICANCiAgICAgICAgT2Z0ZW4gdGhlIGNhc2UgZm9yIGxpbmVhciByZWdyZXNzaW9uLCB0LXRlc3QgYW5kIEFOT1ZBIHJlc2lkdWFsIHRlc3RzDQovDQogICAgKiBXZSB3aWxsIGxhdGVyIGRpc2N1c3MgYW4gbm9ybWFsIGRpc3RyaWJ1dGlvbiBhc3N1bXB0aW9uIHRvIGFzc2VzcyB0aGUgcXVhbGl0eSBvZiB0d28gbW9kZWxzIGJ5IHRoZWlyIHZhcmlhbmNlIHJhdGlvLCBhbHNvIGtub3duIGFzIGFuIEYgZGlzdHJpYnV0aW9uIA0KLw0KICAgICogT3ZlcmFsbCB3ZSBvZnRlbiB1c2Ugbm9ybWFsIGRpc3RyaWJ1dGlvbiBhcyB0aGUgYmFzZXMgdG8gbWFrZSBjb25jbHVzaW9ucyBvciBhcHByb3hpbWF0aW9ucyBhYm91dCBvdXIgZGlzdHJpYnV0aW9ucyBiZWNhdXNlIG9mdGVuIHNhbXBsZXMgb3IgcG9wdWxhdGlvbiBvZnRlbiBhcHByb2FjaCBub3JtYWwgZGlzdHJpYnV0aW9ucyBhbmQgd2UgY2FuIHN0YW5kYXJkaXplIG91ciBkaXN0cmlidXRpb25zIHJlbGF0aXZlbHkgZWFzaWx5IHRvIG1hdGNoIGEgdW5pdmVyc2FsIHNjYWxlIGZvciBzdGFuZGFyZCBkZXZpYXRpb25zLiBSZWdhcmRsZXNzIG9mIHRoZSBkYXRhJ3Mgb3JpZ2luYWwgdW5pdHMsIHdlIGNhbiBzdGFuZGFyZGl6ZSB3aXRoaW4gb3VyIGRhdGEgdG8gZGlnZXN0IGhvdyByYXJlIG9yIGNvbW1vbiBhIGRhdGEgcG9pbnQgaXMgaW4gcmVzcGVjdCB0byB0aGUgb3RoZXIgdmFsdWVzLg0KICAgIA0KDQotIEVzdGltYXRpb24gZm9yIHRoZSBDdW11bGF0aXZlIERpc3RyaWJ1dGlvbiBGdW5jdGlvbg0KICBBIG5vcm1hbCBkaXN0cmlidXRpb24gY2FuIGFjdCBhcyBhbiBlc3RpbWF0b3IgZm9yIHRoZSBjdW11bGF0aXZlIGRpc3RyaWJ1dGlvbiBmdW5jdGlvbi4gIGlmIGFuIGVtcGlyaWNhbCBDREYgaXMgdXNlZCwgdGhlIHRoZW9yZXRpY2FsIG5vcm1hbCBkaXN0cmlidXRpb24gZnVuY3Rpb24gY2FuIGJlIGEgYmFzZSBjb21wYXJpc29uIHRvIHNlZSBpZiB0aGVzZSB0d28gYXJlIHN0YXRpc3RpY2FsbHkgZGlmZmVyZW50LiANCg0KSW4gdGhpcyBjYXNlIHRoZSBlbXBpcmljYWwgQ0RGIGlzIG1vZGVsIGJhc2VkIG9uIHRoZSBkYXRhIG9ic2VydmVkLiBXZSBjYW4gY29tcGFyZSBob3cgd2VsbCBhbiBlbXBpcmljYWwgbW9kZWwgY29tcGFyZXMgdG8gYSB0aGVvcmV0aWNhbCBub3JtYWwgZGlzdHJpYnV0aW9uIG1vZGVsIHRvIGhlbHAgdXMgdW5kZXJzdGFuZCBhbnkgbnVhbmNlIGluIG91ciBvYnNlcnZlZCBkYXRhLiANCg0KYGBge3J9DQoNCnNldC5zZWVkKDQ1KQ0KIyBHZW5lcmF0ZSBzYW1wbGUgZGF0YQ0Kc2FtcGxlX2RhdGEgPC0gcm5vcm0oMTAwLCBtZWFuID0gMCwgc2QgPSAxKQ0KDQojIENyZWF0ZSBlbXBpcmljYWwgQ0RGDQplbXBpcmljYWxfY2RmIDwtIGVjZGYoc2FtcGxlX2RhdGEpDQoNCiMgUGxvdCBlbXBpcmljYWwgdnMgdGhlb3JldGljYWwgQ0RGDQpwbG90X2RmIDwtIGRhdGEuZnJhbWUoDQogIHggPSBzZXEoLTUsIDUsIGxlbmd0aC5vdXQgPSAyNTAwKSwNCiAgRW1waXJpY2FsID0gZW1waXJpY2FsX2NkZihzZXEoLTE1LCAxNSwgbGVuZ3RoLm91dCA9IDI1MDApKSwNCiAgVGhlb3JldGljYWwgPSBwbm9ybShzZXEoLTE1LCAxNSwgbGVuZ3RoLm91dCA9IDI1MDApKQ0KKQ0KDQpwbG90X2RmX2xvbmcgPC0gcGxvdF9kZiAlPiUNCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKEVtcGlyaWNhbCwgVGhlb3JldGljYWwpLCANCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlR5cGUiLCB2YWx1ZXNfdG8gPSAiQ0RGIikNCg0KRm4ucGx0IDwtIGdncGxvdChwbG90X2RmX2xvbmcsIGFlcyh4ID0geCwgeSA9IENERiwgY29sb3IgPSBUeXBlKSkgKw0KICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiRW1waXJpY2FsIiA9ICJncmVlbiIsICJUaGVvcmV0aWNhbCIgPSAicHVycGxlIikpICsNCiAgbGFicyh0aXRsZSA9ICJFbXBpcmljYWwgdnMgVGhlb3JldGljYWwgQ0RGIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJTYW1wbGUgc2l6ZSBuID0gMTAwIGZyb20gU3RhbmRhcmQgTm9ybWFsIiwNCiAgICAgICB4ID0gIngiLCB5ID0gIkNERiIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksDQogICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHQgPSAzNSwgciA9IDIwLCBiID0gMzAsIGwgPSAzMCwgdW5pdCA9ICJwdCIpKQ0KZ2dwbG90bHkoRm4ucGx0KQ0KDQoNCmBgYA0KDQoNCg0KDQpXaGlsZSB0aGUgTm9ybWFsIGRpc3RyaWJ1dGlvbiBpcyB0aGUgZm91bmRhdGlvbiBvZiBwYXJhbWV0cmljIGluZmVyZW5jZSwgaXQgY2FuIGJlIGFwcGxpZWQgdG8gZGVzY3JpYmUgYSBzYW1wbGluZyBkaXN0cmlidXRpb24gaW4gdHdvIGRpc3RpbmN0IGNhcGFjaXRpZXM6DQogIA0KICANCjEuICoqRXhhY3QgRGlzdHJpYnV0aW9uKio6IG91ciBwb3B1bGF0aW9uIGRpc3RyaWJ1dGlvbiBpcyBrbm93biB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZCB3aXRoIHJhbmRvbSB2YXJpYWJsZXMgdGhhdCBhcmUgaWRlbnRpY2FsbHkgYW5kIGluZGVwZW5kZW50bHkgZGlzdHJpYnV0ZWQgd2l0aGluIGEgc21hbGwgc2FtcGxlIHNpemUgb3INCg0KQmVjYXVzZSB3ZSBrbm93IG91ciBwb3B1bGF0aW9uIGRpc3RyaWJ1dGlvbiBpcyBub3JtYWwgd2UgY2FuIHN0YW5kYXJkaXplIG91ciBkaXN0cmlidXRpb24gIHNhbXBsZSB0byBiZSB1bmRlciBvbmUuIA0KDQokJA0KWiA9IFxmcmFje1xiYXJ7WH0gLSBcbXV9e1xzaWdtYSAvIFxzcXJ0e259fSBccmlnaHRhcnJvd15kIE4oMCwxKQ0KJCQNCg0KDQoNCg0KMi4gKipBc3ltcHRvdGljIERpc3RyaWJ1dGlvbioqIG91ciBwb3B1bGF0aW9uIGRpc3RyaWJ1dGlvbiBpcyB1bmtub3duIGJ1dCBvdXIgc2FtcGxlIHNpemUgaXMgbGFyZ2UNCg0KDQojIyBFeHRyYWN0IERpc3RydWJ0aW9uIA0KICBBIGV4YWN0IGRpc3RyaWJ1dGlvbiBhc3N1bWVzIGEgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgcG9wdWxhdGlvbiB3aXRoIHJhbmRvbSB2YXJpYWJsZXMgdGhhdCBhcmUgaWRlbnRpY2FsbHkgYW5kIGluZGVwZW5kZW50bHkgZGlzdHJpYnV0ZWQgd2l0aGluIGEgc21hbGwgc2FtcGxlIHNpemUuIE91ciByYW5kb20gdmFyaWFibGVzIGFyZSBjb2xsZWN0ZWQgYW5kIHRyZWF0ZWQgaW5kZXBlbmRlbnRseSwgYXMgdGhlIHByb2JhYmlsaXR5IG9mIHRoZSBvbmUgdmFsdWUgZG9lcyBub3QgZWZmZWN0IHRoZSBwcm9iYWJpbGl0eSBvZiB0aGUgbmV4dCB2YWx1ZS4NCg0KIyMgQXN5bXB0b3RpYyBEaXN0cmlidXRpb24gUmVsYXRpb24gaW4gTm9ybWFsIERpc3RydWJ1dGlvbg0KQXMgbWVudGlvbmVkIGVhcmxpZXIsIHRoZXJlIGFyZSBzb21lIGFkdmFudGFnZXMgdG8gdXNpbmcgdGhlIG5vcm1hbCBkaXN0cmlidXRpb24gZGVzcGl0ZSBpdHMgc2hhcGUgYXNzdW1wdGlvbi4NCg0KQXMgd2UgdGFrZSBhIHJhbmRvbSBzYW1wbGUgZnJvbSB0aGUgcG9wdWxhdGlvbiBpbiB3aGljaCB3ZSBhcmUgbm90IHN1cmUgb2YgaXRzIGRpc3RyaWJ1dGlvbiwgd2UgdXNlIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uIGFzIGFuIGFwcHJveGltYXRpb24gZm9yIHRoZSB0cnVlIGRpc3RyaWJ1dGlvbi4gDQoNCkR1ZSB0byB0aGUgbGFyZ2Ugc2FtcGxlIHNpemUsIHdlIGNhbiB1c2UgdGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSB0byBhc3N1bWUgb3VyIHNhbXBsZSBzdGF0aXN0aWMgKG9mdGVuIG91ciBzYW1wbGUgbWVhbikgYXBwcm9hY2hlcyBhbmQgcmVhY2hlcyBhIG5vcm1hbCBkaXN0cmlidXRpb24uIEV2ZW4gaWYgaW4gc21hbGxlciBxdWFudGl0aWVzIHRoZSBkaXN0cmlidXRpb24gbWF5IG5vdCBhcHBlYXIgbm9ybWFsLCB3aXRoIGEgbGFyZ2Ugc2FtcGxlIHNpemUgb3VyIGRpc3RyaWJ1dGlvbiBteSBjb252ZXJnZSB0byBhIG5vcm1hbCBkaXN0cmlidXRpb24uIElmIGFuIG9yaWdpbmFsIHBvcHVsYXRpb24gY29udGFpbnMgc2tldyBpbiBpdHMgZGlzdHJpYnV0aW9uLCB3aXRoIGEgbGFyZ2UgZW5vdWdoIHNhbXBsZSB0aGUgZGlzdHJpYnV0aW9uIGNhbiBwbGFjZSBpbnRvIGEgYmVsbCBjdXJ2ZS4NCg0KYGBge3IgfQ0KIyBTZXQgYSBzZWVkIHNvIHRoZSByYW5kb20gcmVzdWx0cyBhcmUgdGhlIHNhbWUgZXZlcnkgdGltZSB5b3UgJ2tuaXQnDQpzZXQuc2VlZCgxMikNCg0KIyBEZWZpbmUgbnVtYmVyIG9mIHNpbXVsYXRpb25zIGFuZCBkaWZmZXJlbnQgc2FtcGxlIHNpemVzIHRvIHRlc3QNCm5fc2ltdWxhdGlvbnMgPC0gMTAwMDANCnNhbXBsZV9zaXplcyA8LSBjKDIsIDUsIDIwLCA1MCkNCg0KIyBTZXQgdXAgYSAyeDIgZ3JpZCBmb3IgdGhlIGdyYXBocw0KcGFyKG1mcm93ID0gYygyLCAyKSkNCg0KZm9yIChuIGluIHNhbXBsZV9zaXplcykgew0KICAjIDEuIFRha2UgMTAsMDAwIHJhbmRvbSBzYW1wbGVzIG9mIHNpemUgJ24nIGZyb20gYSBza2V3ZWQgcG9wdWxhdGlvbg0KICAjIDIuIENhbGN1bGF0ZSB0aGUgbWVhbiBmb3IgZWFjaCBvZiB0aG9zZSAxMCwwMDAgc2FtcGxlcw0KICBzYW1wbGVfbWVhbnMgPC0gcmVwbGljYXRlKG5fc2ltdWxhdGlvbnMsIG1lYW4ocmV4cChuLCByYXRlID0gMSkpKQ0KICANCiAgIyAzLiBDcmVhdGUgdGhlIGhpc3RvZ3JhbQ0KICBoaXN0KHNhbXBsZV9tZWFucywgDQogICAgICAgYnJlYWtzID0gNDAsIA0KICAgICAgIGZyZXEgPSBGQUxTRSwgDQogICAgICAgbWFpbiA9IHBhc3RlKCJTYW1wbGUgU2l6ZSBuID0iLCBuKSwNCiAgICAgICB4bGFiID0gIlZhbHVlIG9mIFNhbXBsZSBNZWFuIiwgDQogICAgICAgY29sID0gInNreWJsdWUiLCANCiAgICAgICBib3JkZXIgPSAid2hpdGUiKQ0KICANCiAgIyA0LiBBZGQgYSB0aGVvcmV0aWNhbCBOb3JtYWwgQ3VydmUgKFJlZCBsaW5lKSB0byBzZWUgdGhlIGZpdA0KICAjIFRoZSBtZWFuIG9mIG91ciBwb3B1bGF0aW9uIGlzIDEsIGFuZCBTRCBpcyAxLg0KICBjdXJ2ZShkbm9ybSh4LCBtZWFuID0gMSwgc2QgPSAxL3NxcnQobikpLCANCiAgICAgICAgYWRkID0gVFJVRSwgY29sID0gInJlZCIsIGx3ZCA9IDIpDQp9DQoNCg0KYGBgDQoNCkluIHRoZXNlIGltYWdlcyB3ZSBzZWUgYXMgdGhlIHNhbXBsZSBzaXplIChuKSBpbmNyZWFzZXMsdGhlIGRpc3RyaWJ1dGlvbiB0byBtb3ZlcyB0byBiZSBsZXNzIHNrZXdlZCBpbnRvIGEgbW9yZSBub3JtYWwgZGlzdHJpYnV0aW9uLiANCg0KDQpBcyB0aGUgb2JzZXJ2ZWQgZGlzdHJpYnV0aW9uLCBtYXkgbm90IGZvbGxvdyBhIG5vcm1hbCBkaXN0cmlidXRpb24gZGlyZWN0bHkgd2Ugc3RhbmRhcmRpemUgb3VyIHZhbHVlcyBpbnRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiwgdXNpbmcgdGhlIGZvbGxvd2luZyBmb3JtdWxhLiBOb3RlIHRoaXMgZm9ybXVsYSBpcyBhbiBhcHByb3hpbWF0aW9uLiBBbiBhcHByb3hpbWF0aW9uIGFjdHMgYXMgYmVzdCBlc3RpbWF0ZSBjb25zaWRlcmluZyB3ZSBkbyBub3Qga25vdyB0aGUgdHJ1ZSBkaXN0cmlidXRpb24sIHVubGlrZSB0aGUgZXhhY3QgZGlzdHJpYnV0aW9uLg0KDQoNCiQkDQpaID0gXGZyYWN7XGJhcntYfSAtIFxtdX17XHNpZ21hIC8gXHNxcnR7bn19IFxyaWdodGFycm93XnthcHJveH0gTigwLDEpDQokJA0KDQpCeSBzdGFuZGFyZGl6aW5nIG91ciB2YWx1ZXMgaW50byBaIHNjb3Jlcywgd2UgY2FuIGFwcHJveGltYXRlIG91ciBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb24gc2FtcGxlIHN0YXRpc3RpY3MsIHdoaWNoIGFyZSB2YWx1ZXMgbGlrZSB0aGUgbWVhbiwgcHJvcG9ydGlvbiwgb3IgcmVncmVzc2lvbiBjb2VmZmljaWVudC4NCg0KDQoNCg0KDQojIHQtZGlzdHVidXRpb24gDQoNCldlIHVzZWQgYSBub3JtYWwgZGlzdHJpYnV0aW9uIHdoZW4gb3VyIHBvcHVsYXRpb24gc3RhbmRhcmQgZGV2aWF0aW9uICRcc2lnbWFeMiQgd2FzIGtub3duLiBXaGVuIHdlIGRvIG5vdCBrbm93IG91ciBwb3B1bGF0aW9uJ3Mgc3RhbmRhcmQgZGV2aWF0aW9uIHdlIHVzZSBhICoqdCBkaXN0cmlidXRpb24qKi4gDQoNCldoZW4gd2UgZG8gbm90IGtub3cgb3VyIHBvcHVsYXRpb24ncyBzdGFuZGFyZCBkZXZpYXRpb24gd2UgZXN0aW1hdGUgdXNpbmcgdGhlIHNhbXBsZSB2YXJpYW5jZSAkU14yJCAuICANCiQkDQogIFQgPSBcZnJhY3tcYmFye1h9IC0gXG11fXtcIFMvIFxzcXJ0e259fSAgXHJpZ2h0YXJyb3cgdF97bi0xfQ0KJCQNCk91ciBmb3JtdWxhIGZvciBvdXQgc2FtcGxlIHZhcmlhbmNlICRTXjIkIGlzIDoNCg0KJCQNClNeMiA9IFxmcmFjIHsxfXtuLTF9IFxzdW1fe2k9MX1ee259ICh7eF9pIC1cYmFye1h9fSleMg0KJCQNCkluIG91ciBUIGRpc3RyaWJ1dGlvbiBzaW5jZSB3ZSBkbyBub3Qga25vdyBvdXIgcG9wdWxhdGlvbiBzdGFuZGFyZCBkZXZpYXRpb24gYW5kIGRpdmlkZSBieSB0aGUgc2FtcGxlIHN0YW5kYXJkIGRldmlhdGlvbiwgd2UgbXVzdCBjb25zaWRlciB0aGUgdmFyaWF0aW9uIHdpdGhpbiB0aGUgc2FtcGxlLCB3aGljaCBpcyB3aHkgd2UgZGl2aWRlICRTJCBieSB0aGUgc3F1YXJlIHJvb3Qgb2YgdGhlIHNhbXBsZSBzaXplLiANCg0KQXMgdGhlIHNoYXBlIG9mIGEgdC1kaXN0cmlidXRpb24gYW5kIG5vcm1hbCBkaXN0cmlidXRpb24gYnkgdGhlIG5ha2VkIGV5ZSBmb2xsb3cgaGlnaGx5IHNpbWlsYXIgc2hhcGVzIHRoZSBmb3JtdWxhaWMgZGlmZmVyZW5jZSBvZiB0aGUgICRTIC9cc3FydHtufSQgLGluIHRoZSB0IGRpc3RyaWJ1dGlvbiBkZW5vbWluYXRvciwgY2F1c2VzIG1vcmUgdW5jZXJ0YWludHkgaW4gdGhlIGRpc3RyaWJ1dGlvbiBsZWFkaW5nIHRvIHdpZGVyICJmYXR0ZXIiIHRhaWxzIGluIHRoZSB0LSBkaXN0cmlidXRpb24gcmF0aGVyIHRoYW4gdGhlIG5vcm1hbCBkaXN0cmlidXRpb24uIFVubGlrZSBpbiB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiB3aGVyZSB3ZSBrbm93IHRoZSB2YXJpYW5jZSwgb3Igc3ByZWFkIG9mIGRhdGEsIHdpdGggdGhlIGdvYWwgb2YgZmluZGluZyB0aGUgc2FtcGxlIG1lYW4sIGluIGEgdC1kaXN0cmlidXRpb24gd2UgbmVpdGhlciBrbm93IHRoZSB2YXJpYW5jZSBub3IgdGhlIHNhbXBsZSBtZWFuLCBsZWFkaW5nIHRvIGEgZ3JlYXRlciBjaGFuY2Ugb2YgdW5jZXJ0YWludHkuIEdyZWF0ZXIgdW5jZXJ0YWludHkgIHVsdGltYXRlbHkgbGVhZHMgdXMgdG8gaGF2ZSBmYXR0ZXIgdGFpbHMgc2hvd2luZyBoaWdoZXIgdmFyaWFuY2UsIGFsdGhvdWdoIGFzIG4gaW5jcmVhc2VzIHRoaXMgdW5jZXJ0YWludHkgaXMgcmVkdWNlZCwgZ2l2aW5nIGEgc21hbGxlciBzdGFuZGFyZCBkZXZpYXRpb24gJFNeMiQgdWx0aW1hdGVseSBkZWNyZWFzaW5nIHRoZSBzcHJlYWQgaW4gdGhlIGRpc3RyaWJ1dGlvbi4gDQoNCg0KDQpOb3RlIGFzIG91ciBzYW1wbGUgc2l6ZSBncm93cywgdGhlIHRhaWxzIG9mIHRoZSB0LWRpc3RyaWJ1dGlvbiBnZXQgbGVzcyBmYXQsIG9mdGVuIGNvbnZlcmdpbmcgY2xvc2VyIHRoZSBhIG5vcm1hbCBkaXN0cmlidXRpb24uIFNpbWlsYXIgdG8gb3VyIENlbnRyYWwgTGltaXQgVGhlcm9uIHdoZXJlIHRoZSBsYXJnZXIgb3VyIHNhbXBsZSBzaXplLCB0aGUgbW9yZSBvdXIgbW9kZWwgY29udmVyZ2VzIHRvIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uLiBUaGUgZm9ybXVsYSBjb21wb25lbnQgb2YgJFxzcXJ0e259JCBhc3Npc3RzIGluIGNoYW5naW5nIHRoZSBkaXN0cmlidXRpb24gc2hhcGUsIGFzIHRoZSBsZXZlbCBvZiBuIGNvbnRyaWJ1dGVzIHRvIHRoZSBkZWdyZWVzIG9mIGZyZWVkb20sIHRoZSBvbmx5IHBhcmFtZXRlciBpbiB0aGUgdC1kaXN0cmlidXRpb24gZm9ybXVsYS4gDQoNCg0KQmVsb3cgd2UgY29tcGFyZSBhIHQtZGlzdHJpYnV0aW9uIHdpdGggYSBub3JtYWwgZGlzdHJpYnV0aW9uLiBOb3RlIHRoZSB0LWRpc3RyaWJ1dGlvbiBoYXMgJ2ZhdHRlcicgdGFpbHMuDQoNCmBgYHtyfQ0KDQpzZXQuc2VlZCgzNTkpDQpuIDwtIDE1DQptdSA8LSA1DQpzaWdtYSA8LSAyDQoNCiMgR2VuZXJhdGUgdC1zdGF0aXN0aWNzDQpuLnNhbXBsZXMgPC0gMTAwMDANCnQuc3RhdHMgPC0gbnVtZXJpYyhuLnNhbXBsZXMpICAjIFRoaXMgZGVmaW5lcyBhIDEwMDAwIGRpbWVuc2lvbmFsIHplcm8gdmVjdG9yDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0LnRlc3QgPC0gTlVMTCB1c2VzIG1vcmUgY29tcHV0aW5nIHJlc291cmNlDQpmb3IoaSBpbiAxOm4uc2FtcGxlcykgew0KICBzYW1wbGUuZGF0YSA8LSBybm9ybShuLCBtdSwgc2lnbWEpDQogIHguYmFyIDwtIG1lYW4oc2FtcGxlLmRhdGEpDQogIHMgPC0gc2Qoc2FtcGxlLmRhdGEpDQogIHQuc3RhdHNbaV0gPC0gKHguYmFyIC0gbXUpIC8gKHMvc3FydChuKSkNCn0NCg0KIyBDb21wYXJlIHdpdGggdGhlb3JldGljYWwgdC1kaXN0cmlidXRpb24NCngudmFscyA8LSBzZXEoLTQsIDQsIGxlbmd0aC5vdXQgPSAyMDApDQp0aGVvcmV0aWNhbC50IDwtIGR0KHgudmFscywgZGYgPSBuLTEpICAgICMgY2FsbGluZyB0LWRlbnNpdHkgZnVuY3Rpb24NCnRoZW9yZXRpY2FsLm5vcm1hbCA8LSBkbm9ybSh4LnZhbHMpICAgICAgIyBzdGFuZGFyZCBub3JtYWwgZGlzdHJpYnV0aW9uDQoNCmNvbXBhcmlzb24uZGYgPC0gZGF0YS5mcmFtZSgNCiAgeCA9IHJlcCh4LnZhbHMsIDIpLA0KICBkZW5zaXR5ID0gYyh0aGVvcmV0aWNhbC50LCB0aGVvcmV0aWNhbC5ub3JtYWwpLA0KICBkaXN0cmlidXRpb24gPSByZXAoYygidCg5KSIsICJOKDAsMSkiKSwgZWFjaCA9IGxlbmd0aCh4LnZhbHMpKQ0KKQ0KDQp0LnBsdCA8LSBnZ3Bsb3QoY29tcGFyaXNvbi5kZiwgYWVzKHggPSB4LCB5ID0gZGVuc2l0eSwgY29sb3IgPSBkaXN0cmlidXRpb24pKSArDQogIGdlb21fbGluZShzaXplID0gMSkgKw0KICBsYWJzKHRpdGxlID0gInQtRGlzdHJpYnV0aW9uIHZzIE5vcm1hbCBEaXN0cmlidXRpb24iLA0KICAgICAgIHggPSAiVmFsdWUiLCB5ID0gIkRlbnNpdHkiKSArDQogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksDQogICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKHQgPSAzNSwgciA9IDIwLCBiID0gMzAsIGwgPSAzMCwgdW5pdCA9ICJwdCIpKSArDQogICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYmx1ZSIsICJvcmFuZ2UiKSkNCmdncGxvdGx5KHQucGx0KQ0KDQpgYGANCg0KDQpXaHkgb3VyIHQtZGlzdHJpYnV0aW9uIGNvbm5lY3RzIHdpdGggdGhlIG5vcm1hbCBkaXN0cmlidXRpb24/IA0KDQpPdXIgdC1kaXN0cmlidXRpb24gaW4gZnVuY3Rpb24gYmVoYXZlcyBzaW1pbGFybHkgdG8gdGhlIG5vcm1hbCBkaXN0cmlidXRpb24uIE91ciBub3JtYWwgc3RhbmRhcmRpemVkIGZvcm11bGEgYW5kIG5vcm1hbCBkaXN0cmlidXRpb24gZm9ybXVsYSAgc2hhcmUgYSBudW1lcmF0b3IgYWNjb3VudGluZyBmb3IgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhlIG1lYW4gYW5kIHRoZSBvYnNlcnZlZCB2YWx1ZSAoIHNoYXJlZCBudW1lcmF0b3I6ICRcYmFye1h9IC0gXG11JCkuIEV2ZW4gaW4gc2hhcGUgYm90aCB0aGUgdCBhbmQgbm9ybWFsIGRpc3RyaWJ1dGlvbnMgc2hhcmUgYSBiZWxsIGN1cnZlIGNlbnRlcmVkIGF0IDAuIFdoZW4gdGhlIHNhbXBsZSBzaXplIGlzIGxhcmdlIGVub3VnaCBhIHQgZGlzdHJpYnV0aW9uIGNhbiBiZWNvbWUgYSBub3JtYWwgZGlzdHJpYnV0aW9uLiBPdXIgdC1kaXN0cmlidXRpb24gY29udmVyZ2luZyB0byB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBpcyB2YWx1YWJsZSBiZWNhdXNlIHdpdGggYSBsYXJnZSBlbm91Z2ggc2FtcGxlIHNpemUsIG91ciBzYW1wbGUgdmFyaWFuY2UgYmVjYXVzZSBhY2N1cmF0ZSBlbm91Z2ggdG8gYWNjb3VudCBhcyB0aGUgdHJ1ZSBwb3B1bGF0aW9uIHZhcmlhbmNlLCBhbGxvd2luZyBvdXIgc3RhdGlzdGljcyB0byBiZSBtb3JlIGFjY3VyYXRlIGFzIHRoZXkgYXJlIGNsb3NlciB0byB0aGUgdHJ1ZSBwb3B1bGF0aW9uLg0KDQoNCk91ciBhc3N1bXB0aW9ucyBvZiB0aGUgdC1kaXN0cmlidXRpb24gaW5jbHVkZSBpbmRlcGVuZGVudCByYW5kb20gb2JzZXJ2YXRpb25zLCByYW5kb20gc2FtcGxpbmcsIGFuZCB0aGF0IG91ciBwb3B1bGF0aW9uIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiAgDQoNCkFzIHQgZGlzdHJpYnV0aW9ucyB0ZW5kIHRvIGNvbnZlcmdlIGludG8gbm9ybWFsIGRpc3RyaWJ1dGlvbnMgdXBvbiBsYXJnZSBzYW1wbGUgc2l6ZSwgb2Z0ZW4gdCBkaXN0cmlidXRpb25zIHByaW9yIHRvIGNvbnZlcmdpbmcgaGF2ZSBzbWFsbGVyIHNhbXBsZSBzaXplcy4NCg0KVGhlIHQtZGlzdHJpYnV0aW9uIGNvbnNpZGVycyBlc3RpbWF0aW9ucyBmb3IgdGhlIHNhbXBsZSBtZWFuLCB3ZSB1c2UgYSBjaGktc3F1YXJlZCBkaXN0cmlidXRpb24gdG8gYXNzZXNzIHRoZSB2YXJpYW5jZSwgYWxzbyBrbm93biBhcyBzcHJlYWQsIG9mIHRoZSBkaXN0cmlidXRpb24uDQoNCiMgQ2hpLVNxdWFyZWQgRGlzdHJ1YnV0aW9uDQoNCkEgY2hpLXNxdWFyZWQgZGlzdHJpYnV0aW9uIGlzIGFsc28gYSBkaXN0cmlidXRpb24gdHlwZSB0aGF0IGNhbiBjb252ZXJnZSBpbnRvIG5vcm1hbCBkaXN0cmlidXRpb24uIEEgY2hpLSBzcXVhcmVkIGRpc3RyaWJ1dGlvbiBpcyBhIHNwZWNpYWwgY2FzZSBvZiBhIGdhbW1hIGRpc3RyaWJ1dGlvbiwgaW4gd2hpY2ggYm90aCBkaXN0cmlidXRpb25zIGhhdmUgc2tld25lc3MuIA0KDQpCZWxvdyBpcyBhbiBleGFtcGxlIG9mIGEgY2hpLXNxdWFyZSBkaXN0cmlidXRpb246DQoNCmBgYHtyIGNoaWV4YW1wbGUxfQ0KDQpzZXQuc2VlZCg2KQ0KbiA8LSA1DQpzaWdtYSA8LSAyDQoNCiMgR2VuZXJhdGUgY2hpLXNxdWFyZSBzdGF0aXN0aWNzDQpuLnNhbXBsZXMgPC0gMTAwMDANCmNoaXNxLnN0YXRzIDwtIG51bWVyaWMobi5zYW1wbGVzKQ0KDQpmb3IoaSBpbiAxOm4uc2FtcGxlcykgew0KICBzYW1wbGUuZGF0YSA8LSBybm9ybShuLCAwLCBzaWdtYSkNCiAgY2hpc3Euc3RhdHNbaV0gPC0gc3VtKChzYW1wbGUuZGF0YS9zaWdtYSleMikNCn0NCg0KIyBDb21wYXJlIHdpdGggdGhlb3JldGljYWwgY2hpLXNxdWFyZQ0KeC52YWxzIDwtIHNlcSgwLCAzMCwgbGVuZ3RoLm91dCA9IDIwMCkNCnRoZW9yZXRpY2FsLmNoaXNxIDwtIGRjaGlzcSh4LnZhbHMsIGRmID0gbikNCnRoZW9yeS5kZiA8LSBkYXRhLmZyYW1lKHggPSB4LnZhbHMsIGRlbnNpdHkgPSB0aGVvcmV0aWNhbC5jaGlzcSkNCg0KY2hpLnBsdCA8LSBnZ3Bsb3QoZGF0YS5mcmFtZSh4ID0gY2hpc3Euc3RhdHMpLCBhZXMoeCA9IHgpKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBiaW5zID0gNTAsIGFscGhhID0gMC43LCBmaWxsID0gImdyZWVuIikgKw0KICBnZW9tX2xpbmUoZGF0YSA9IHRoZW9yeS5kZiwgYWVzKHggPSB4LCB5ID0gZGVuc2l0eSksIA0KICAgICAgICAgICAgY29sb3IgPSAiYmx1ZSIsIGxpbmV3aWR0aCA9IDEuNSkgKw0KICAjc3RhdF9mdW5jdGlvbihmdW4gPSBkY2hpc3EsIGFyZ3MgPSBsaXN0KGRmID0gbiksIGNvbG9yID0gInJlZCIsIHNpemUgPSAxKSArDQogIGxhYnModGl0bGUgPSAiQ2hpLVNxdWFyZWQgRGlzdHJpYnV0aW9uIChuPTUpICIsDQogICAgICAgc3VidGl0bGUgPSAiU3VtIG9mIHNxdWFyZWQgc3RhbmRhcmQgbm9ybWFscyIsDQogICAgICAgeCA9ICJWYWx1ZSIsIHkgPSAiRGVuc2l0eSIpICsNCiAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMzUsIHIgPSAyMCwgYiA9IDMwLCBsID0gMzAsIHVuaXQgPSAicHQiKSkNCmdncGxvdGx5KGNoaS5wbHQpDQoNCg0KYGBgDQoNCkFuIGluY3JlYXNlIGluIHNhbXBsZSBzaXplIGNhbiBsZWFkIHRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiwgYXMgaW5jcmVhc2UgaW4gc2FtcGxlIHNpemUgcmVkdWNlcyB0aGUgc2tld25lc3MuDQpgYGB7ciBjaGlleGFtcGxlM30NCg0Kc2V0LnNlZWQoNikNCm4gPC0gNTAwDQpzaWdtYSA8LSAyDQoNCiMgR2VuZXJhdGUgY2hpLXNxdWFyZSBzdGF0aXN0aWNzDQpuLnNhbXBsZXMgPC0gMTAwMDANCmNoaXNxLnN0YXRzIDwtIG51bWVyaWMobi5zYW1wbGVzKQ0KDQpmb3IoaSBpbiAxOm4uc2FtcGxlcykgew0KICBzYW1wbGUuZGF0YSA8LSBybm9ybShuLCAwLCBzaWdtYSkNCiAgY2hpc3Euc3RhdHNbaV0gPC0gc3VtKChzYW1wbGUuZGF0YS9zaWdtYSleMikNCn0NCg0KIyBDb21wYXJlIHdpdGggdGhlb3JldGljYWwgY2hpLXNxdWFyZQ0KeC52YWxzIDwtIHNlcSgwLCAxMTAwLCBsZW5ndGgub3V0ID0gMjAwKQ0KdGhlb3JldGljYWwuY2hpc3EgPC0gZGNoaXNxKHgudmFscywgZGYgPSBuKQ0KdGhlb3J5LmRmIDwtIGRhdGEuZnJhbWUoeCA9IHgudmFscywgZGVuc2l0eSA9IHRoZW9yZXRpY2FsLmNoaXNxKQ0KDQpjaGkucGx0IDwtIGdncGxvdChkYXRhLmZyYW1lKHggPSBjaGlzcS5zdGF0cyksIGFlcyh4ID0geCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGJpbnMgPSA1MCwgYWxwaGEgPSAwLjcsIGZpbGwgPSAiZ3JlZW4iKSArDQogIGdlb21fbGluZShkYXRhID0gdGhlb3J5LmRmLCBhZXMoeCA9IHgsIHkgPSBkZW5zaXR5KSwgDQogICAgICAgICAgICBjb2xvciA9ICJibHVlIiwgbGluZXdpZHRoID0xLjUpICsNCiAgI3N0YXRfZnVuY3Rpb24oZnVuID0gZGNoaXNxLCBhcmdzID0gbGlzdChkZiA9IG4pLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMSkgKw0KICBsYWJzKHRpdGxlID0gIkNoaS1TcXVhcmVkIERpc3RyaWJ1dGlvbiAobj01MDApICIsDQogICAgICAgc3VidGl0bGUgPSAiU3VtIG9mIHNxdWFyZWQgc3RhbmRhcmQgbm9ybWFscyIsDQogICAgICAgeCA9ICJWYWx1ZSIsIHkgPSAiRGVuc2l0eSIpICsNCiAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLA0KICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMzUsIHIgPSAyMCwgYiA9IDMwLCBsID0gMzAsIHVuaXQgPSAicHQiKSkNCmdncGxvdGx5KGNoaS5wbHQpDQoNCg0KYGBgDQoNCkEgY2hpLXNxdWFyZSBkaXN0cmlidXRpb24gY2FuIGRlcml2ZSBmcm9tIGFuIGV4YWN0IG5vcm1hbCBkaXN0cmlidXRpb24uIEl0IGNhbiBlc3NlbnRpYWxseSBhY3QgYXMgYSBzcXVhcmVkIHN0YW5kYXJkIG5vcm1hbCB3aXRoIG9uZSBkZWdyZWUgb2YgZnJlZWRvbSBvciBhIHN1bSBvZiBzcXVhcmVzIHdpdGggbW9yZSB0aGFuIDEgZGVncmVlIG9mIGZyZWVkb20sIGFkZGluZyBza2V3bmVzcyB0byBhIG5vcm1hbCBkaXN0cmlidXRpb24uIEFzIHRoZSBjaGktc3F1YXJlIGlzIGEgc3F1YXJlZCBub3JtYWwsIHRoZSBkaXN0cmlidXRpb24gY2FuIG5ldmVyIGJlIG5lZ2F0aXZlLCBleGFnZ2VyYXRpbmcgYW55IHJpZ2h0IHNrZXduZXNzLiBJbiBvdGhlciB3b3JkcywgYSBjaGktc3F1YXJlZCBkaXN0cmlidXRpb24gY2FuIGJlIGRlc2NyaWJlZCBhcyBhIG5vcm1hbCBkaXN0cmlidXRpb24sIHdob3NlIGNlbnRlciBoYXMgbW92ZWQgYW5kIG5vdyBwb3NzZXNzZXMgc2tld25lc3MuDQoNCkluIGNvbnRyaWJ1dGlvbiB0aGF0IHRoZSB2YXJpYW5jZSBpcyBhIHNxdWFyZWQgcGFyYW1ldGVyLCB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIG9mIHRoZSBzYW1wbGUgdmFyaWFuY2UgY2FuIGJlIGRlc2NyaWJlZCBhcyBhIGNoaS1zcXVhcmUgZGlzdHJpYnV0aW9uIHVwb24gc2NhbGluZy4gV2hlbiBvdXIgc2FtcGxlIHNpemUgaW5jcmVhc2VzLHRoZSBkZWdyZWUgb2YgZnJlZWRvbSBwYXJhbWV0ZXIgJChuLTEpJCBpbiBvdXIgbnVtZXJhdG9yIGluY3JlYXNlcy4gVGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSBoZWxwcyBvdXIgY2hpLXNxdWFyZWQgZGlzdHJpYnV0aW9uIHRha2Ugb24gYSBub3JtYWwgZGlzdHJpYnV0aW9uLCBzbW9vdGhpbmcgdGhlIHNrZXduZXNzIGludG8gYSBiZWxsLXNoYXBlLCBhcyB0aGUgc2FtcGxlIHNpemUgaW5jcmVhc2UuIA0KDQpPdXIgY2hpLXNxdWFyZSBkaXN0cmlidXRpb24gcmVsYXRpb25zaGlwIHdpdGggYSBub3JtYWwgZGlzdHJpYnV0aW9uOg0KDQokJA0KICBcZnJhY3sobi0xKVNeMn17XHNpZ21hXjJ9IFxyaWdodGFycm93IFxjaGleMl97bi0xfQ0KJCQNCg0KTGlrZSBhIHQtZGlzdHJpYnV0aW9uLCBvdXIgYXNzdW1wdGlvbnMgYWJvdXQgYSBjaGktc3F1YXJlIGRpc3RyaWJ1dGlvbiBpcyB0aGF0IHdlIHNhbXBsZSBmcm9tIGEgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgcG9wdWxhdGlvbiBhcyB3ZWxsIGFzIGluZGl2aWR1YWxseSBhbmQgaW5kZXBlbmRlbnRseSBkaXN0cmlidXRlZC4NClRoZSBjaGktc3F1YXJlZCBhbmQgdC1kaXN0cmlidXRpb24gaGF2ZSBkZWdyZWVzIG9mIGZyZWVkb20gaW4gdGhlaXIgcGFyYW1ldGVycywgZGljdGF0aW5nIHRoZSBzaGFwZXMgb2YgdGhlaXIgZGlzdHJpYnV0aW9ucy4NCg0KDQojIEYgZGlzdHJ1YnV0aW9uDQoNCldpdGggb3VyIGNoaS1zcXVhcmVkIGRpc3RyaWJ1dGlvbiB3ZSBzZWUgdGhlIHZhcmlhbmNlIG9mIG91ciBkaXN0cmlidXRpb24uIE9mdGVuIHdlIGhhdmUgbXVsdGlwbGUgZGlzdHJpYnV0aW9ucyBhbmQgd2UgbmVlZCB0byByZWxhdGUgdGhlIHZhcmlhbmNlcyB0byBlYWNoIG90aGVyIHRvIHNlZSBxdWFsaXR5IG9mIHRoZSB0d28gZGlzdHJpYnV0aW9ucy4gSGVuY2Ugd2UgYnVpbGQgYSBGIGRpc3RyaWJ1dGlvbiBhcyBhIHJhdGlvIG9mIHR3byBjaGktc3F1YXJlZCB2YXJpYWJsZXMgb2YgaW5kZXBlbmRlbnQgc2FtcGxlIHZhcmlhbmNlcy4gTGlrZSB0aGUgaW5kaXZpZHVhbCBjaGktc3F1YXJlZCwgYm90aCBhc3N1bWUgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gVGhlc2UgY2hpLXNxdWFyZWQgZGlzdHJpYnV0aW9ucyBzb3VyY2UgZnJvbSBpbmRlcGVuZGVudCBwb3B1bGF0aW9ucy4gDQoNCiQkDQp7WF8xLCBYXzIsIC4uLlhfbn0gfiBee2kuaS5kfSBOKFxtdV8yLCBcc2lnbWFeMl8xKSBcXCBhbmQgXFx7WV8xLCBZXzIsIC4uLllfbn0gfiBee2kuaS5kfSBOKFxtdV8yLCBcc2lnbWFeMl8yKSANCiQkDQokJA0KU14yXzEgPSBcZnJhYyB7MX17bl8xLTF9IFxzdW1fe2k9MX1ee259ICh7WF9pIC1cYmFye1h9fSleMiAgICBcXGFuZFxcIA0KU14yXzIgPSBcZnJhYyB7MX17bl8yLTF9IFxzdW1fe2k9MX1ee259ICh7WV9pIC1cYmFye1l9fSleMg0KJCQNCkRlZmluZQ0KJCQNCkY9IFxmcmFjIHtTXjJfMS8gXHNpZ21hXjJ9IHtTXjJfMi9cc2lnbWFeMl8yfSBccmlnaHRhcnJvd15kIEZfe24tMSwgbl8yLTF9DQokJCANCg0KDQpUaGUgMSBkZWdyZWUgb2YgZnJlZWRvbSBlYWNoIGNoaS1zcXVhcmVzIGhvbGQgaW4gdGhlIEYtZGlzdHJpYnV0aW9uIGdpdmUgdXMgMiBkZWdyZWVzIG9mIGZyZWVkb20gKG9uZSBpbiB0aGUgZGVub21pbmF0b3IsIGFuZCBvbmUgaW4gdGhlIG51bWVyYXRvcikgdGhhdCBib3RoIGNvbnRyaWJ1dGUgdG8gdGhlIGRpc3RyaWJ1dGlvbidzIHNoYXBlLg0KDQpJbiB0aGUgZ3JlYXRlciB0aGUgRiBkaXN0cmlidXRpb24gcmF0aW8sIHRoZSBtb3JlIHZhcmlhbmNlIGluIHRoZSBudW1lcmF0b3IncyBkaXN0cmlidXRpb24uIFRoZSBzbWFsbGVyIHRoZSB2YXJpYW5jZSB0aGUgdmFyaWFuY2UgaXMgbGFyZ2VyIGluIHRoZSBkZW5vbWluYXRvciBkaXN0cmlidXRpb24uIElmIHRoZSBGIGRpc3RyaWJ1dGlvbiByYXRpbyBpcyAxLCB0aGUgdHdvIHZhcmlhbmNlcyBpbiB0aGUgbnVtZXJhdG9yIGFuZCBkZW5vbWluYXRvciBhcmUgZXF1YWwuDQoNCg0KDQpgYGB7cn0NCg0Kc2V0LnNlZWQoNDUpDQpkZjEgPC0gMjANCmRmMiA8LSAyNQ0KDQojIEdlbmVyYXRlIEYgc3RhdGlzdGljcw0Kbi5zYW1wbGVzIDwtIDEwMDAwDQpmLnN0YXRzIDwtIG51bWVyaWMobi5zYW1wbGVzKQ0KDQpmb3IoaSBpbiAxOm4uc2FtcGxlcykgew0KICB1MSA8LSByY2hpc3EoMSwgZGYxKQ0KICB1MiA8LSByY2hpc3EoMSwgZGYyKQ0KICBmLnN0YXRzW2ldIDwtICh1MS9kZjEpIC8gKHUyL2RmMikNCn0NCg0KIyBDb21wYXJlIHdpdGggdGhlb3JldGljYWwgRi1kaXN0cmlidXRpb24NCngudmFscyA8LSBzZXEoMCwgNSwgbGVuZ3RoLm91dCA9IDIwMCkNCnRoZW9yZXRpY2FsLmYgPC0gZGYoeC52YWxzLCBkZjEsIGRmMikNCnRoZW9yeS5kZiA8LSBkYXRhLmZyYW1lKHggPSB4LnZhbHMsIGRlbnNpdHkgPSB0aGVvcmV0aWNhbC5mKQ0KDQoNCg0KDQpmLnBsdCA8LSBnZ3Bsb3QoZGF0YS5mcmFtZSh4ID0gZi5zdGF0cyksIGFlcyh4ID0geCkpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGJpbnMgPSA1MCwgYWxwaGEgPSAwLjcsIGZpbGwgPSAiYmx1ZSIpICsNCiAgZ2VvbV9saW5lKGRhdGEgPSB0aGVvcnkuZGYsIGFlcyh4ID0geCwgeSA9IGRlbnNpdHkpLCANCiAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIGxpbmV3aWR0aCA9IDEpICsNCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDUpKSArDQogIGxhYnModGl0bGUgPSBwYXN0ZSgiRi1EaXN0cmlidXRpb24gXG4gRigiLCBkZjEsICIsIiwgZGYyLCAiKSIsIHNlcCA9ICIiKSwNCiAgICAgICB4ID0gIlZhbHVlIiwgeSA9ICJEZW5zaXR5IikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwNCiAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4odCA9IDM1LCByID0gMjAsIGIgPSAzMCwgbCA9IDMwLCB1bml0ID0gInB0IikpDQpnZ3Bsb3RseShmLnBsdCkNCg0KDQoNCmBgYA0KDQoNCg0KDQojIENvbmNsdXNpb24NCkFzc3VtaW5nIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBhbGxvd3MgdXMgdG8gY29ubmVjdCBhIHQgZGlzdHJpYnV0aW9uIHRvIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4gQSBub3JtYWwgZGlzdHJpYnV0aW9uIGNhbiBiZSB1c2VkIHRvd2FyZHMgYSBjaGktIHNxdWFyZWQgZGlzdHJpYnV0aW9uIHRvIGFzc2VzcyBtb2RlbCB2YXJpYW5jZSBhbmQgdHdvIGNoaS1zcXVhcmUgdGVzdHMgY2FuIGJlIHVzZWQgaW4gYW4gRiBkaXN0cmlidXRpb24gcmF0aW8gdG8gYXNzZXNzIHRoZSBvdmVyYWxsIHF1YWxpdHkgb2YgdHdvIGRpc3RyaWJ1dGlvbnMuIA0KDQpUaGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBidWlsZHMgaW50byBhZHZhbmNlZCBhbmFseXNlIHRoYXQgYWxsb3cgdXMgdG8gY29uc2lkZXIgdGhlIHF1YWxpdHkgb2Ygb3VyIGRpc3RyaWJ1dGlvbi4gV2l0aG91dCBhIHN0YW5kYXJkaXplZCBkaXN0cmlidXRpb24gc2hhcGUgdGhhdCB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBnaXZlcyB1cywgbWFraW5nIHRoZXNlIGNvbXBhcmlzb25zIHdvdWxkIGJlIGNoYWxsZW5naW5nLCBlc3BlY2lhbGx5IHRocm91Z2ggdmFyaW91cyB1bml0IHR5cGVzLiBPdXIgbm9ybWFsIGRpc3RyaWJ1dGlvbiBhbGxvd3MgdXMgdG8gb3JnYW5pemUgb3VyIGRpc3RyaWJ1dGlvbiBmb3IgYW5hbHlzaXMsIGFuZCB0ZXN0IHRoZSBxdWFsaXR5IG9mIGFuIG9ic2VydmVkIGRhdGEgc2V0IGVpdGhlciB0aHJvdWdoIGFwcHJveGltYXRpb24gb3IgdGhlb3JldGljYWwgY29tcGFyaXNvbi4=