library(tidyverse)
library(openintro)
library(infer)
Exercise 1
What are the counts within each category for the amount of days these
students have texted while driving within the past 30 days?
Answer:
yrbss %>%
count(text_while_driving_30d) %>%
arrange(desc(n))
## # A tibble: 9 × 2
## text_while_driving_30d n
## <chr> <int>
## 1 0 4792
## 2 did not drive 4646
## 3 1-2 925
## 4 <NA> 918
## 5 30 827
## 6 3-5 493
## 7 10-19 373
## 8 6-9 311
## 9 20-29 298
Exercise 2
What is the proportion of people who have texted while driving every
day in the past 30 days and never wear helmets? Answer:
There are two common interpretations for this question depending on
whether you are looking at the conditional proportion among non-helmet
wearers (the standard method in this lab) or the joint proportion across
the entire dataset. 1. Conditional Proportion (Among non-helmet
wearers)
# Filter for students who never wear helmets
no_helmet <- yrbss %>%
filter(helmet_12m == "never") %>%
mutate(text_ind = ifelse(text_while_driving_30d == "30", "yes", "no"))
# Calculate proportion (excluding NAs)
no_helmet %>%
filter(!is.na(text_ind)) %>%
summarise(
every_day = sum(text_ind == "yes"),
total = n(),
proportion = mean(text_ind == "yes")
)
## # A tibble: 1 × 3
## every_day total proportion
## <int> <int> <dbl>
## 1 463 6503 0.0712
yrbss %>%
summarise(
prop = sum(text_while_driving_30d == "30" & helmet_12m == "never", na.rm = TRUE) / n()
)
## # A tibble: 1 × 1
## prop
## <dbl>
## 1 0.0341
data('yrbss', package='openintro')
no_helmet <- yrbss %>%
filter(helmet_12m == "never")
no_helmet <- no_helmet %>%
mutate(text_ind = ifelse(text_while_driving_30d == "30", "yes", "no"))
Ecercise 3
What is the margin of error for the estimate of the proportion of
non-helmet wearers that have texted while driving each day for the past
30 days based on this survey? Answer: The Margin of Error (\(\text{MoE}\)) for a symmetric confidence
interval is half the width of the interval: \[\text{MoE} = \frac{\text{Upper Limit} -
\text{Lower Limit}}{2}\]From the infer output provided:Lower
Limit (\(\text{Lower CI}\)): \(0.0650\) (\(6.50\%\))Upper Limit (\(\text{Upper CI}\)): \(0.0775\) (\(7.75\%\))Calculation:\[\text{MoE} = \frac{0.0775 - 0.0650}{2} =
\frac{0.0125}{2} = 0.00625 \quad (0.625\%)\]Point Estimate (\(\hat{p}\)): \(\frac{0.0775 + 0.0650}{2} = 0.07125 \quad
(7.125\%)\)Result: The margin of error for this estimate is \(0.00625\) (or \(0.625\%\)).
Exercise 4
Using the infer package, calculate confidence intervals for two other
categorical variables (you’ll need to decide which level to call
“success”, and report the associated margins of error. Interpet the
interval in context of the data. It may be helpful to create new data
sets for each of the two countries first, and then use these data sets
to construct the confidence intervals. Answer:
library(tidyverse)
library(infer)
set.seed(123)
# -------------------------------------------------------------------
# Variable 1: Physical Activity (Success = active 7 days a week)
# -------------------------------------------------------------------
active_data <- yrbss %>%
filter(helmet_12m == "never") %>%
drop_na(physically_active_7d) %>%
mutate(active_ind = ifelse(physically_active_7d == 7, "yes", "no"))
ci_activity <- active_data %>%
specify(response = active_ind, success = "yes") %>%
generate(reps = 1000, type = "bootstrap") %>%
calculate(stat = "prop") %>%
get_ci(level = 0.95)
ci_activity
## # A tibble: 1 × 2
## lower_ci upper_ci
## <dbl> <dbl>
## 1 0.293 0.314
moe_activity <- (ci_activity$upper_ci - ci_activity$lower_ci) / 2
moe_activity
## [1] 0.01054173
# -------------------------------------------------------------------
# Variable 2: Sleep Duration (Success = getting 8+ hours of sleep)
# Note: school_night_hours_sleep is a character variable with levels like "8", "9", "10+"
# -------------------------------------------------------------------
sleep_data <- yrbss %>%
filter(helmet_12m == "never") %>%
drop_na(school_night_hours_sleep) %>%
mutate(sleep_ind = ifelse(school_night_hours_sleep %in% c("8", "9", "10+"), "yes", "no"))
ci_sleep <- sleep_data %>%
specify(response = sleep_ind, success = "yes") %>%
generate(reps = 1000, type = "bootstrap") %>%
calculate(stat = "prop") %>%
get_ci(level = 0.95)
ci_sleep
## # A tibble: 1 × 2
## lower_ci upper_ci
## <dbl> <dbl>
## 1 0.291 0.312
moe_sleep <- (ci_sleep$upper_ci - ci_sleep$lower_ci) / 2
moe_sleep
## [1] 0.01074268
n <- 1000
p <- seq(from = 0, to = 1, by = 0.01)
me <- 2 * sqrt(p * (1 - p)/n)
dd <- data.frame(p = p, me = me)
ggplot(data = dd, aes(x = p, y = me)) +
geom_line() +
labs(x = "Population Proportion", y = "Margin of Error")

Exercise 5
Describe the relationship between p and me. Include the margin of
error vs. population proportion plot you constructed in your answer. For
a given sample size, for which value of p is margin of error maximized?
Answer: 1. Relationship Between \(p\)
and Margin of Error (\(ME\)) The
relationship between the population proportion \(p\) and the margin of error (\(ME\)) is symmetric, non-linear, and forms
an inverted U-shaped parabolic curve.Key Observations:Symmetry around
\(p = 0.5\): The curve is perfectly
symmetrical about \(p = 0.5\). For
instance, \(p = 0.2\) and \(p = 0.8\) produce the exact same margin of
error because \(p(1 - p) = (0.2)(0.8) =
(0.8)(0.2) = 0.16\).Minima at Extrema (\(p = 0\) and \(p =
1\)): At the extreme bounds where \(p =
0\) or \(p = 1\), the
variability is zero (\(SE = 0\)), which
makes the margin of error \(0\). If
every individual in a population either completely possesses or lacks a
trait, there is no sampling variability.Peak at \(p = 0.5\): As \(p\) moves toward \(0.5\) from either direction, the product
\(p(1 - p)\) increases, reaching its
absolute maximum at \(0.25\).
Consequently, the margin of error reaches its maximum when \(p = 0.5\). 2. Margin of Error
vs. Population Proportion Plot Below is the R code used to construct the
dataset and visualization, followed by the resulting plot:
library(ggplot2)
# Set sample size
n <- 1000
# Generate sequence of proportions from 0 to 1
p <- seq(from = 0, to = 1, by = 0.01)
# Calculate margin of error
me <- 2 * sqrt(p * (1 - p) / n)
# Combine into data frame
dd <- data.frame(p = p, me = me)
# Create plot
ggplot(data = dd, aes(x = p, y = me)) +
geom_line(color = "#2b5c8f", size = 1.2) +
geom_point(aes(x = 0.5, y = 2 * sqrt(0.5 * 0.5 / 1000)), color = "red", size = 3) +
annotate("text", x = 0.5, y = 0.033, label = "Maximum ME at p = 0.5 (ME = 0.0316)", color = "red", fontface = "bold") +
labs(
title = "Margin of Error vs. Population Proportion (n = 1000)",
x = "Population Proportion (p)",
y = "Margin of Error (ME)"
) +
theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## Warning in geom_point(aes(x = 0.5, y = 2 * sqrt(0.5 * 0.5/1000)), color = "red", : All aesthetics have length 1, but the data has 101 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
## a single row.

- Value of \(p\) Where Margin of
Error is MaximizedFor a fixed sample size \(n\), the margin of error is maximized at
\(p = 0.50\) (or \(50\%\)).Mathematical Explanation:The
formula for the margin of error is:\[\text{ME} = 2 \times \sqrt{\frac{p(1 -
p)}{n}}\]To find the value of \(p\) that maximizes \(\text{ME}\), we maximize the numerator
function \(f(p) = p(1 - p) = p - p^2\).
Taking the first derivative with respect to \(p\) and setting it to zero:\[\frac{df}{dp} = 1 - 2p = 0 \implies 2p = 1
\implies p = 0.50\]At \(n =
1000\) and \(p = 0.50\), the
maximum margin of error is:\[\text{ME}_{\text{max}} = 2 \times
\sqrt{\frac{0.5(1 - 0.5)}{1000}} = 2 \times \sqrt{\frac{0.25}{1000}}
\approx 0.0316 \quad (3.16\%)\]
Exercise 6
Describe the sampling distribution of sample proportions at n=300 and
p=0.1. Be sure to note the center, spread, and shape.
Answer:
To describe the sampling distribution of sample proportions (\(\hat{p}\)) for a sample size of \(n = 300\) and a population proportion of
\(p = 0.10\), we evaluate the shape,
center, and spread using the Central Limit Theorem for proportions.
Shape To check whether the sampling distribution of \(\hat{p}\) is approximately normal, we
verify the Success-Failure Condition:\[n
\cdot p = 300 \times 0.10 = 30 \ge 10\]\[n \cdot (1 - p) = 300 \times (1 - 0.10) = 300
\times 0.90 = 270 \ge 10\]Since both expected successes (\(30\)) and expected failures (\(270\)) are at least \(10\), the condition is satisfied.Shape: The
sampling distribution of \(\hat{p}\) is
unimodal and approximately symmetric (Normal): \(\hat{p} \sim N(\mu_{\hat{p}},
\sigma_{\hat{p}})\).
Center The mean (expected value) of the sampling distribution of
sample proportions is equal to the true population proportion \(p\):\[\mu_{\hat{p}} = p = 0.10\]Center: The mean
of the sampling distribution is centered at \(0.10\) (or \(10\%\)).
Spread (Standard Error)Assuming the sample of \(n = 300\) observations is selected randomly
and represents less than \(10\%\) of
the population (10% condition), the standard error (\(SE\)) measures the variability between
sample proportions:\[\sigma_{\hat{p}} = SE =
\sqrt{\frac{p(1 - p)}{n}}\]Calculation:\[\sigma_{\hat{p}} = \sqrt{\frac{0.10 \times (1 -
0.10)}{300}} = \sqrt{\frac{0.10 \times 0.90}{300}} =
\sqrt{\frac{0.09}{300}} = \sqrt{0.0003} \approx 0.01732\]Spread:
The standard error of the sampling distribution is approximately \(0.01732\) (or \(1.732\%\)).
# Insert code for Exercise 6 here
Exercise 7
Keep n constant and change p . How does the shape, center, and spread
of the sampling distribution vary as p changes. You might want to adjust
min and max for the x -axis for a better view of the distribution.
Answer: When holding the sample size (\(n\)) constant and varying the population
proportion (\(p\)), the sampling
distribution of sample proportions (\(\hat{p}\)) changes in shape, center, and
spread in the following systematic ways: 1. Center (\(\mu_{\hat{p}}\))Behavior: The center of the
sampling distribution always equals the population proportion:\[\mu_{\hat{p}} = p\]Effect of changing
\(p\): As \(p\) increases, the peak of the distribution
shifts directly to the right along the horizontal axis (\(x\)-axis). As \(p\) decreases, it shifts to the left.
- Spread / Standard Error (\(\sigma_{\hat{p}}\))Behavior:
The variability (standard error) is calculated as:\[\sigma_{\hat{p}} = \sqrt{\frac{p(1 -
p)}{n}}\]Effect of changing \(p\):Maximized at \(p = 0.50\): The standard error reaches its
maximum value when \(p = 0.50\), where
\(p(1 - p) = 0.25\). At \(p = 0.50\), the distribution has its widest
spread.Decreases toward Extrema (\(p \to
0\) or \(p \to 1\)): As \(p\) moves further away from \(0.50\) toward either \(0\) or \(1\), \(p(1 -
p)\) decreases, causing the standard error to shrink and making
the distribution narrower and taller.Symmetry in Spread: Values of \(p\) equidistant from \(0.50\) (such as \(p = 0.20\) and \(p = 0.80\)) produce the exact same standard
error and spread width.
- Shape
Behavior: The shape is governed by the Success-Failure Condition
(\(np \ge 10\) and \(n(1 - p) \ge 10\)).Effect of changing \(p\):Symmetric at \(p = 0.50\): When \(p = 0.50\), the distribution is perfectly
symmetric and bell-shaped, regardless of \(n\) (so long as \(n \ge 20\)).Skewness near Extrema: As \(p\) gets close to \(0\) or \(1\), the distribution becomes skewed:When
\(p\) is small (close to \(0\)), \(np <
10\) makes the distribution right-skewed (bounded by \(0\)).When \(p\) is large (close to \(1\)), \(n(1 - p)
< 10\) makes the distribution left-skewed (bounded by \(1\)).Approximate Normality: As long as
\(p\) stays within a moderate range
such that both \(np \ge 10\) and \(n(1 - p) \ge 10\) hold, the distribution
remains approximately normal.
library(ggplot2)
n <- 300
p_vals <- c(0.10, 0.50, 0.90)
# Generate simulated sampling distributions
set.seed(123)
sim_data <- map_dfr(p_vals, function(p) {
tibble(
p_label = paste0("p = ", p),
phat = rbinom(10000, size = n, prob = p) / n
)
})
# Plot showing shift in center, change in spread, and symmetry
ggplot(sim_data, aes(x = phat, fill = p_label)) +
geom_density(alpha = 0.5) +
scale_x_continuous(limits = c(0, 1), breaks = seq(0, 1, 0.1)) +
labs(
title = "Sampling Distributions of p-hat for n = 300 across varying p",
x = "Sample Proportion (p-hat)",
y = "Density",
fill = "Parameter p"
) +
theme_minimal()

Exercise 8
Now also change n . How does n appear to affect the distribution of
p^ ? Answer: When keeping \(p\)
constant and changing the sample size \(n\), \(n\)
affects the sampling distribution of \(\hat{p}\) across shape, center, and spread
in the following ways:
- Spread (Standard Error \(\sigma_{\hat{p}}\)) — Inversely
Proportional to $
\(Behavior: The standard error formula
is:\)\(\sigma_{\hat{p}} =
\sqrt{\frac{p(1 - p)}{n}}\)$Effect of Increasing \(n\):As \(n\) increases, the denominator gets larger,
which decreases the standard error (\(\sigma_{\hat{p}}\)).The sampling
distribution becomes narrower, taller, and more tightly clustered around
the true population mean \(p\).To cut
the standard error (and the margin of error) in half, you must increase
the sample size \(n\) by a factor of
4.Effect of Decreasing \(n\):As \(n\) decreases, standard error increases,
causing the distribution to spread out and become wider/flatter.
- Shape — Approaches Normality as \(n\) IncreasesBehavior: The Central Limit
Theorem dictates that larger sample sizes force the sampling
distribution of \(\hat{p}\) to become
more bell-shaped and symmetric.Success-Failure Condition (\(np \ge 10\) and \(n(1 - p) \ge 10\)):Small \(n\): If \(n\) is small, the expected counts \(np\) or \(n(1 -
p)\) may fall below \(10\)
(especially when \(p\) is close to
\(0\) or \(1\)). This causes the distribution to be
skewed (right-skewed if \(p < 0.5\),
left-skewed if \(p > 0.5\)).Large
\(n\): As \(n\) grows large enough to satisfy \(np \ge 10\) and \(n(1 - p) \ge 10\), any initial skewness
disappears, and the shape becomes approximately Normal.3. Center (\(\mu_{\hat{p}}\)) — UnchangedBehavior: The
mean (expected value) of the sampling distribution remains equal to the
true population proportion regardless of sample size:\[\mu_{\hat{p}} = p\]Effect of changing
\(n\): \(n\) has no effect on the center. The
distribution will remain centered at \(p\) whether \(n =
30\) or \(n = 3,000\).
library(ggplot2)
library(dplyr)
library(purrr)
set.seed(123)
p <- 0.10
n_vals <- c(30, 100, 300, 1200)
# Generate sampling distributions for different n
sim_n_data <- map_dfr(n_vals, function(n_size) {
tibble(
n_label = factor(paste0("n = ", n_size), levels = paste0("n = ", n_vals)),
phat = rbinom(10000, size = n_size, prob = p) / n_size
)
})
# Overlay density curves
ggplot(sim_n_data, aes(x = phat, fill = n_label)) +
geom_density(alpha = 0.4) +
scale_x_continuous(limits = c(0, 0.3)) +
labs(
title = "Effect of Sample Size (n) on Sampling Distribution of p-hat (p = 0.10)",
x = "Sample Proportion (p-hat)",
y = "Density",
fill = "Sample Size (n)"
) +
theme_minimal()
## Warning: Removed 6 rows containing non-finite outside the scale range
## (`stat_density()`).

Exercise 9
Is there convincing evidence that those who sleep 10+ hours per day
are more likely to strength train every day of the week? As always,
write out the hypotheses for any tests you conduct and outline the
status of the conditions for inference. If you find a significant
difference, also quantify this difference with a confidence interval.
Answer:
set.seed(123)
# 1. Prepare Data
yrbss_strength <- yrbss %>%
drop_na(school_night_hours_sleep, strength_training_7d) %>%
mutate(
sleep_10plus = ifelse(school_night_hours_sleep == "10+", "10+ hours", "<10 hours"),
sleep_10plus = factor(sleep_10plus, levels = c("10+ hours", "<10 hours")),
strength_daily = ifelse(strength_training_7d == 7, "yes", "no"),
strength_daily = factor(strength_daily, levels = c("yes", "no"))
)
# 2. Compute Observed Difference in Proportions
obs_diff <- yrbss_strength %>%
specify(strength_daily ~ sleep_10plus, success = "yes") %>%
calculate(stat = "diff in props", order = c("10+ hours", "<10 hours"))
obs_diff
## Response: strength_daily (factor)
## Explanatory: sleep_10plus (factor)
## # A tibble: 1 × 1
## stat
## <dbl>
## 1 0.105
# 3. Conduct Hypothesis Test via Permutation / Simulation
null_dist <- yrbss_strength %>%
specify(strength_daily ~ sleep_10plus, success = "yes") %>%
hypothesize(null = "independence") %>%
generate(reps = 1000, type = "permute") %>%
calculate(stat = "diff in props", order = c("10+ hours", "<10 hours"))
# Calculate p-value
p_value <- null_dist %>%
get_p_value(obs_stat = obs_diff, direction = "greater")
## Warning: Please be cautious in reporting a p-value of 0. This result is an approximation
## based on the number of `reps` chosen in the `generate()` step.
## ℹ See `get_p_value()` (`?infer::get_p_value()`) for more information.
## # A tibble: 1 × 1
## p_value
## <dbl>
## 1 0
# 4. Quantify Difference with a 95% Confidence Interval (Bootstrap)
boot_dist <- yrbss_strength %>%
specify(strength_daily ~ sleep_10plus, success = "yes") %>%
generate(reps = 1000, type = "bootstrap") %>%
calculate(stat = "diff in props", order = c("10+ hours", "<10 hours"))
ci_diff <- boot_dist %>%
get_ci(level = 0.95)
ci_diff
## # A tibble: 1 × 2
## lower_ci upper_ci
## <dbl> <dbl>
## 1 0.0560 0.155
Exercise 10
Let’s say there has been no difference in likeliness to strength
train every day of the week for those who sleep 10+ hours. What is the
probablity that you could detect a change (at a significance level of
0.05) simply by chance? Hint: Review the definition of the Type 1
error.
Answer:
The probability of detecting a change simply by chance is equal to
the significance level (\(\alpha\)),
which is \(0.05\) (or \(5\%\)).
Explanation & Context:
Definition of Type I Error (\(\alpha\)):\[\text{Type I Error} = P(\text{Reject } H_0 \mid
H_0 \text{ is true}) = \alpha\]The significance level \(\alpha\) represents the threshold set by
the researcher for how much risk of a false positive they are willing to
accept.
In Context:
When conducting a hypothesis test with \(\alpha = 0.05\), you are establishing a
decision rule where \(5\%\) of all
samples drawn from a population with no true difference will randomly
produce a sample statistic extreme enough to fall in the rejection
region, leading to a false conclusion of a difference.
Exercise 11
Suppose you’re hired by the local government to estimate the
proportion of residents that attend a religious service on a weekly
basis. According to the guidelines, the estimate must have a margin of
error no greater than 1% with 95% confidence. You have no idea what to
expect for p . How many people would you have to sample to ensure that
you are within the guidelines? Hint: Refer to your plot of the
relationship between p and margin of error. This question does not
require using a dataset.
Answer:
To determine the required sample size (\(n\)) under the strictest conditions, we use
the worst-case scenario for variability based on the relationship
between population proportion (\(p\))
and margin of error (\(ME\)).
- Determining the Value of \(p\) As
established in the \(ME\) vs. \(p\) curve, the margin of error reaches its
absolute maximum when \(p = 0.50\)
(\(50\%\)).
When you have no prior information or expectation about \(p\), using \(p =
0.50\) provides the most conservative (worst-case) estimate. This
guarantees that your sample size will be large enough to achieve a
margin of error of \(1\%\) or less,
regardless of what the true population proportion turns out to be.
- Given Parameters
Target Margin of Error (\(ME\)):
\(0.01\) (\(1\%\))
Confidence Level: \(95\%\)
Critical Value (\(z^*\)): \(1.96\) (for a \(95\%\) confidence level)
Assumed Proportion (\(p\)): \(0.50\)
- Sample Size Formula & Calculation
The formula for the margin of error of a proportion is:\[ME = z^* \times \sqrt{\frac{p(1 -
p)}{n}}\]Solving for sample size \(n\):\[n = \left(
\frac{z^*}{ME} \right)^2 \times p(1 - p)\]Step-by-Step
Substitution:\[n = \left( \frac{1.96}{0.01}
\right)^2 \times (0.50)(1 - 0.50)\]\[n
= (196)^2 \times 0.25\]\[n = 38,416
\times 0.25 = 9,604\]
Conclusion
It would need to sample at least 9,604 residents to ensure that your
estimate of the proportion of residents attending weekly religious
services has a margin of error no greater than \(1\%\) at a \(95\%\) confidence level.
LS0tDQp0aXRsZTogIkxhYiA2OiBJbmZlcmVuY2UgZm9yIGNhdGVnb3JpY2FsIGRhdGEiDQphdXRob3I6ICJNdWhhbW1hZCBJbWFybiINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDogb3BlbmludHJvOjpsYWJfcmVwb3J0DQotLS0NCg0KYGBge3IgbG9hZC1wYWNrYWdlcywgbWVzc2FnZT1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShvcGVuaW50cm8pDQpsaWJyYXJ5KGluZmVyKQ0KYGBgDQoNCiMjIyBFeGVyY2lzZSAxDQpXaGF0IGFyZSB0aGUgY291bnRzIHdpdGhpbiBlYWNoIGNhdGVnb3J5IGZvciB0aGUgYW1vdW50IG9mIGRheXMgdGhlc2Ugc3R1ZGVudHMgaGF2ZSB0ZXh0ZWQgd2hpbGUgZHJpdmluZyB3aXRoaW4gdGhlIHBhc3QgMzAgZGF5cz8NCg0KQW5zd2VyOg0KDQoNCmBgYHtyIHZDb3VudHMgd2l0aGluIGVhY2ggY2F0ZWdvcnl9DQp5cmJzcyAlPiUgDQogIGNvdW50KHRleHRfd2hpbGVfZHJpdmluZ18zMGQpICU+JSANCiAgYXJyYW5nZShkZXNjKG4pKQ0KYGBgDQoNCg0KIyMjIEV4ZXJjaXNlIDINCldoYXQgaXMgdGhlIHByb3BvcnRpb24gb2YgcGVvcGxlIHdobyBoYXZlIHRleHRlZCB3aGlsZSBkcml2aW5nIGV2ZXJ5IGRheSBpbiB0aGUgcGFzdCAzMCBkYXlzIGFuZCBuZXZlciB3ZWFyIGhlbG1ldHM/DQpBbnN3ZXI6DQoNClRoZXJlIGFyZSB0d28gY29tbW9uIGludGVycHJldGF0aW9ucyBmb3IgdGhpcyBxdWVzdGlvbiBkZXBlbmRpbmcgb24gd2hldGhlciB5b3UgYXJlIGxvb2tpbmcgYXQgdGhlIGNvbmRpdGlvbmFsIHByb3BvcnRpb24gYW1vbmcgbm9uLWhlbG1ldCB3ZWFyZXJzICh0aGUgc3RhbmRhcmQgbWV0aG9kIGluIHRoaXMgbGFiKSBvciB0aGUgam9pbnQgcHJvcG9ydGlvbiBhY3Jvc3MgdGhlIGVudGlyZSBkYXRhc2V0Lg0KMS4gQ29uZGl0aW9uYWwgUHJvcG9ydGlvbiAoQW1vbmcgbm9uLWhlbG1ldCB3ZWFyZXJzKSAgIA0KDQpgYGB7ciBDb25kaXRpb25hbCBQcm9wb3J0aW9uIChBbW9uZyBub24taGVsbWV0IHdlYXJlcnMpfQ0KIyBGaWx0ZXIgZm9yIHN0dWRlbnRzIHdobyBuZXZlciB3ZWFyIGhlbG1ldHMNCm5vX2hlbG1ldCA8LSB5cmJzcyAlPiUgDQogIGZpbHRlcihoZWxtZXRfMTJtID09ICJuZXZlciIpICU+JSANCiAgbXV0YXRlKHRleHRfaW5kID0gaWZlbHNlKHRleHRfd2hpbGVfZHJpdmluZ18zMGQgPT0gIjMwIiwgInllcyIsICJubyIpKQ0KDQojIENhbGN1bGF0ZSBwcm9wb3J0aW9uIChleGNsdWRpbmcgTkFzKQ0Kbm9faGVsbWV0ICU+JSANCiAgZmlsdGVyKCFpcy5uYSh0ZXh0X2luZCkpICU+JSANCiAgc3VtbWFyaXNlKA0KICAgIGV2ZXJ5X2RheSA9IHN1bSh0ZXh0X2luZCA9PSAieWVzIiksDQogICAgdG90YWwgPSBuKCksDQogICAgcHJvcG9ydGlvbiA9IG1lYW4odGV4dF9pbmQgPT0gInllcyIpDQogICkNCmBgYA0KDQoNCg0KDQoNCmBgYHtyIE92ZXJhbGwgSm9pbnQgUHJvcG9ydGlvbiAoT3V0IG9mIHRvdGFsIHNhbXBsZSl9DQp5cmJzcyAlPiUgDQogIHN1bW1hcmlzZSgNCiAgICBwcm9wID0gc3VtKHRleHRfd2hpbGVfZHJpdmluZ18zMGQgPT0gIjMwIiAmIGhlbG1ldF8xMm0gPT0gIm5ldmVyIiwgbmEucm0gPSBUUlVFKSAvIG4oKQ0KICApDQpgYGANCg0KYGBge3J9DQpkYXRhKCd5cmJzcycsIHBhY2thZ2U9J29wZW5pbnRybycpDQpub19oZWxtZXQgPC0geXJic3MgJT4lDQogIGZpbHRlcihoZWxtZXRfMTJtID09ICJuZXZlciIpDQpgYGANCg0KYGBge3J9DQpub19oZWxtZXQgPC0gbm9faGVsbWV0ICU+JQ0KICBtdXRhdGUodGV4dF9pbmQgPSBpZmVsc2UodGV4dF93aGlsZV9kcml2aW5nXzMwZCA9PSAiMzAiLCAieWVzIiwgIm5vIikpDQpgYGANCg0KDQojIyMgRWNlcmNpc2UgMw0KV2hhdCBpcyB0aGUgbWFyZ2luIG9mIGVycm9yIGZvciB0aGUgZXN0aW1hdGUgb2YgdGhlIHByb3BvcnRpb24gb2Ygbm9uLWhlbG1ldCB3ZWFyZXJzIHRoYXQgaGF2ZSB0ZXh0ZWQgd2hpbGUgZHJpdmluZyBlYWNoIGRheSBmb3IgdGhlIHBhc3QgMzAgZGF5cyBiYXNlZCBvbiB0aGlzIHN1cnZleT8NCkFuc3dlcjoNClRoZSBNYXJnaW4gb2YgRXJyb3IgKCRcdGV4dHtNb0V9JCkgZm9yIGEgc3ltbWV0cmljIGNvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgaGFsZiB0aGUgd2lkdGggb2YgdGhlIGludGVydmFsOg0KJCRcdGV4dHtNb0V9ID0gXGZyYWN7XHRleHR7VXBwZXIgTGltaXR9IC0gXHRleHR7TG93ZXIgTGltaXR9fXsyfSQkRnJvbSB0aGUgaW5mZXIgb3V0cHV0IHByb3ZpZGVkOkxvd2VyIExpbWl0ICgkXHRleHR7TG93ZXIgQ0l9JCk6ICQwLjA2NTAkICgkNi41MFwlJClVcHBlciBMaW1pdCAoJFx0ZXh0e1VwcGVyIENJfSQpOiAkMC4wNzc1JCAoJDcuNzVcJSQpQ2FsY3VsYXRpb246JCRcdGV4dHtNb0V9ID0gXGZyYWN7MC4wNzc1IC0gMC4wNjUwfXsyfSA9IFxmcmFjezAuMDEyNX17Mn0gPSAwLjAwNjI1IFxxdWFkICgwLjYyNVwlKSQkUG9pbnQgRXN0aW1hdGUgKCRcaGF0e3B9JCk6ICRcZnJhY3swLjA3NzUgKyAwLjA2NTB9ezJ9ID0gMC4wNzEyNSBccXVhZCAoNy4xMjVcJSkkUmVzdWx0OiBUaGUgbWFyZ2luIG9mIGVycm9yIGZvciB0aGlzIGVzdGltYXRlIGlzICQwLjAwNjI1JCAob3IgJDAuNjI1XCUkKS4NCg0KIyMjIEV4ZXJjaXNlIDQNClVzaW5nIHRoZSBpbmZlciBwYWNrYWdlLCBjYWxjdWxhdGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgZm9yIHR3byBvdGhlciBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgKHlvdeKAmWxsIG5lZWQgdG8gZGVjaWRlIHdoaWNoIGxldmVsIHRvIGNhbGwg4oCcc3VjY2Vzc+KAnSwgYW5kIHJlcG9ydCB0aGUgYXNzb2NpYXRlZCBtYXJnaW5zIG9mIGVycm9yLiBJbnRlcnBldCB0aGUgaW50ZXJ2YWwgaW4gY29udGV4dCBvZiB0aGUgZGF0YS4gSXQgbWF5IGJlIGhlbHBmdWwgdG8gY3JlYXRlIG5ldyBkYXRhIHNldHMgZm9yIGVhY2ggb2YgdGhlIHR3byBjb3VudHJpZXMgZmlyc3QsIGFuZCB0aGVuIHVzZSB0aGVzZSBkYXRhIHNldHMgdG8gY29uc3RydWN0IHRoZSBjb25maWRlbmNlIGludGVydmFscy4NCkFuc3dlcjoNCg0KYGBge3IgZGltLXByZXNlbnR9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoaW5mZXIpDQoNCnNldC5zZWVkKDEyMykNCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIFZhcmlhYmxlIDE6IFBoeXNpY2FsIEFjdGl2aXR5IChTdWNjZXNzID0gYWN0aXZlIDcgZGF5cyBhIHdlZWspDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCmFjdGl2ZV9kYXRhIDwtIHlyYnNzICU+JQ0KICBmaWx0ZXIoaGVsbWV0XzEybSA9PSAibmV2ZXIiKSAlPiUNCiAgZHJvcF9uYShwaHlzaWNhbGx5X2FjdGl2ZV83ZCkgJT4lDQogIG11dGF0ZShhY3RpdmVfaW5kID0gaWZlbHNlKHBoeXNpY2FsbHlfYWN0aXZlXzdkID09IDcsICJ5ZXMiLCAibm8iKSkNCg0KY2lfYWN0aXZpdHkgPC0gYWN0aXZlX2RhdGEgJT4lDQogIHNwZWNpZnkocmVzcG9uc2UgPSBhY3RpdmVfaW5kLCBzdWNjZXNzID0gInllcyIpICU+JQ0KICBnZW5lcmF0ZShyZXBzID0gMTAwMCwgdHlwZSA9ICJib290c3RyYXAiKSAlPiUNCiAgY2FsY3VsYXRlKHN0YXQgPSAicHJvcCIpICU+JQ0KICBnZXRfY2kobGV2ZWwgPSAwLjk1KQ0KDQpjaV9hY3Rpdml0eQ0KbW9lX2FjdGl2aXR5IDwtIChjaV9hY3Rpdml0eSR1cHBlcl9jaSAtIGNpX2FjdGl2aXR5JGxvd2VyX2NpKSAvIDINCm1vZV9hY3Rpdml0eQ0KDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBWYXJpYWJsZSAyOiBTbGVlcCBEdXJhdGlvbiAoU3VjY2VzcyA9IGdldHRpbmcgOCsgaG91cnMgb2Ygc2xlZXApDQojIE5vdGU6IHNjaG9vbF9uaWdodF9ob3Vyc19zbGVlcCBpcyBhIGNoYXJhY3RlciB2YXJpYWJsZSB3aXRoIGxldmVscyBsaWtlICI4IiwgIjkiLCAiMTArIg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQpzbGVlcF9kYXRhIDwtIHlyYnNzICU+JQ0KICBmaWx0ZXIoaGVsbWV0XzEybSA9PSAibmV2ZXIiKSAlPiUNCiAgZHJvcF9uYShzY2hvb2xfbmlnaHRfaG91cnNfc2xlZXApICU+JQ0KICBtdXRhdGUoc2xlZXBfaW5kID0gaWZlbHNlKHNjaG9vbF9uaWdodF9ob3Vyc19zbGVlcCAlaW4lIGMoIjgiLCAiOSIsICIxMCsiKSwgInllcyIsICJubyIpKQ0KDQpjaV9zbGVlcCA8LSBzbGVlcF9kYXRhICU+JQ0KICBzcGVjaWZ5KHJlc3BvbnNlID0gc2xlZXBfaW5kLCBzdWNjZXNzID0gInllcyIpICU+JQ0KICBnZW5lcmF0ZShyZXBzID0gMTAwMCwgdHlwZSA9ICJib290c3RyYXAiKSAlPiUNCiAgY2FsY3VsYXRlKHN0YXQgPSAicHJvcCIpICU+JQ0KICBnZXRfY2kobGV2ZWwgPSAwLjk1KQ0KDQpjaV9zbGVlcA0KbW9lX3NsZWVwIDwtIChjaV9zbGVlcCR1cHBlcl9jaSAtIGNpX3NsZWVwJGxvd2VyX2NpKSAvIDINCm1vZV9zbGVlcA0KYGBgDQoNCmBgYHtyfQ0KbiA8LSAxMDAwDQpwIDwtIHNlcShmcm9tID0gMCwgdG8gPSAxLCBieSA9IDAuMDEpDQptZSA8LSAyICogc3FydChwICogKDEgLSBwKS9uKQ0KZGQgPC0gZGF0YS5mcmFtZShwID0gcCwgbWUgPSBtZSkNCmdncGxvdChkYXRhID0gZGQsIGFlcyh4ID0gcCwgeSA9IG1lKSkgKyANCiAgZ2VvbV9saW5lKCkgKw0KICBsYWJzKHggPSAiUG9wdWxhdGlvbiBQcm9wb3J0aW9uIiwgeSA9ICJNYXJnaW4gb2YgRXJyb3IiKQ0KYGBgDQoNCiMjIyBFeGVyY2lzZSA1DQpEZXNjcmliZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcCBhbmQgbWUuIEluY2x1ZGUgdGhlIG1hcmdpbiBvZiBlcnJvciB2cy4gcG9wdWxhdGlvbiBwcm9wb3J0aW9uIHBsb3QgeW91IGNvbnN0cnVjdGVkIGluIHlvdXIgYW5zd2VyLiBGb3IgYSBnaXZlbiBzYW1wbGUgc2l6ZSwgZm9yIHdoaWNoIHZhbHVlIG9mIHAgaXMgbWFyZ2luIG9mIGVycm9yIG1heGltaXplZD8NCkFuc3dlcjoNCjEuIFJlbGF0aW9uc2hpcCBCZXR3ZWVuICRwJCBhbmQgTWFyZ2luIG9mIEVycm9yICgkTUUkKQ0KVGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBwb3B1bGF0aW9uIHByb3BvcnRpb24gJHAkIGFuZCB0aGUgbWFyZ2luIG9mIGVycm9yICgkTUUkKSBpcyBzeW1tZXRyaWMsIG5vbi1saW5lYXIsIGFuZCBmb3JtcyBhbiBpbnZlcnRlZCBVLXNoYXBlZCBwYXJhYm9saWMgY3VydmUuS2V5IE9ic2VydmF0aW9uczpTeW1tZXRyeSBhcm91bmQgJHAgPSAwLjUkOiBUaGUgY3VydmUgaXMgcGVyZmVjdGx5IHN5bW1ldHJpY2FsIGFib3V0ICRwID0gMC41JC4gRm9yIGluc3RhbmNlLCAkcCA9IDAuMiQgYW5kICRwID0gMC44JCBwcm9kdWNlIHRoZSBleGFjdCBzYW1lIG1hcmdpbiBvZiBlcnJvciBiZWNhdXNlICRwKDEgLSBwKSA9ICgwLjIpKDAuOCkgPSAoMC44KSgwLjIpID0gMC4xNiQuTWluaW1hIGF0IEV4dHJlbWEgKCRwID0gMCQgYW5kICRwID0gMSQpOiBBdCB0aGUgZXh0cmVtZSBib3VuZHMgd2hlcmUgJHAgPSAwJCBvciAkcCA9IDEkLCB0aGUgdmFyaWFiaWxpdHkgaXMgemVybyAoJFNFID0gMCQpLCB3aGljaCBtYWtlcyB0aGUgbWFyZ2luIG9mIGVycm9yICQwJC4gSWYgZXZlcnkgaW5kaXZpZHVhbCBpbiBhIHBvcHVsYXRpb24gZWl0aGVyIGNvbXBsZXRlbHkgcG9zc2Vzc2VzIG9yIGxhY2tzIGEgdHJhaXQsIHRoZXJlIGlzIG5vIHNhbXBsaW5nIHZhcmlhYmlsaXR5LlBlYWsgYXQgJHAgPSAwLjUkOiBBcyAkcCQgbW92ZXMgdG93YXJkICQwLjUkIGZyb20gZWl0aGVyIGRpcmVjdGlvbiwgdGhlIHByb2R1Y3QgJHAoMSAtIHApJCBpbmNyZWFzZXMsIHJlYWNoaW5nIGl0cyBhYnNvbHV0ZSBtYXhpbXVtIGF0ICQwLjI1JC4gQ29uc2VxdWVudGx5LCB0aGUgbWFyZ2luIG9mIGVycm9yIHJlYWNoZXMgaXRzIG1heGltdW0gd2hlbiAkcCA9IDAuNSQuDQoyLiBNYXJnaW4gb2YgRXJyb3IgdnMuIFBvcHVsYXRpb24gUHJvcG9ydGlvbiBQbG90DQpCZWxvdyBpcyB0aGUgUiBjb2RlIHVzZWQgdG8gY29uc3RydWN0IHRoZSBkYXRhc2V0IGFuZCB2aXN1YWxpemF0aW9uLCBmb2xsb3dlZCBieSB0aGUgcmVzdWx0aW5nIHBsb3Q6DQoNCmBgYHtyIE1hcmdpbiBvZiBFcnJvciB2cy4gUG9wdWxhdGlvbiBQcm9wb3J0aW9uIFBsb3R9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgU2V0IHNhbXBsZSBzaXplDQpuIDwtIDEwMDANCg0KIyBHZW5lcmF0ZSBzZXF1ZW5jZSBvZiBwcm9wb3J0aW9ucyBmcm9tIDAgdG8gMQ0KcCA8LSBzZXEoZnJvbSA9IDAsIHRvID0gMSwgYnkgPSAwLjAxKQ0KDQojIENhbGN1bGF0ZSBtYXJnaW4gb2YgZXJyb3INCm1lIDwtIDIgKiBzcXJ0KHAgKiAoMSAtIHApIC8gbikNCg0KIyBDb21iaW5lIGludG8gZGF0YSBmcmFtZQ0KZGQgPC0gZGF0YS5mcmFtZShwID0gcCwgbWUgPSBtZSkNCg0KIyBDcmVhdGUgcGxvdA0KZ2dwbG90KGRhdGEgPSBkZCwgYWVzKHggPSBwLCB5ID0gbWUpKSArDQogIGdlb21fbGluZShjb2xvciA9ICIjMmI1YzhmIiwgc2l6ZSA9IDEuMikgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gMC41LCB5ID0gMiAqIHNxcnQoMC41ICogMC41IC8gMTAwMCkpLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMykgKw0KICBhbm5vdGF0ZSgidGV4dCIsIHggPSAwLjUsIHkgPSAwLjAzMywgbGFiZWwgPSAiTWF4aW11bSBNRSBhdCBwID0gMC41IChNRSA9IDAuMDMxNikiLCBjb2xvciA9ICJyZWQiLCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIk1hcmdpbiBvZiBFcnJvciB2cy4gUG9wdWxhdGlvbiBQcm9wb3J0aW9uIChuID0gMTAwMCkiLA0KICAgIHggPSAiUG9wdWxhdGlvbiBQcm9wb3J0aW9uIChwKSIsDQogICAgeSA9ICJNYXJnaW4gb2YgRXJyb3IgKE1FKSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCjMuIFZhbHVlIG9mICRwJCBXaGVyZSBNYXJnaW4gb2YgRXJyb3IgaXMgTWF4aW1pemVkRm9yIGEgZml4ZWQgc2FtcGxlIHNpemUgJG4kLCB0aGUgbWFyZ2luIG9mIGVycm9yIGlzIG1heGltaXplZCBhdCAkcCA9IDAuNTAkIChvciAkNTBcJSQpLk1hdGhlbWF0aWNhbCBFeHBsYW5hdGlvbjpUaGUgZm9ybXVsYSBmb3IgdGhlIG1hcmdpbiBvZiBlcnJvciBpczokJFx0ZXh0e01FfSA9IDIgXHRpbWVzIFxzcXJ0e1xmcmFje3AoMSAtIHApfXtufX0kJFRvIGZpbmQgdGhlIHZhbHVlIG9mICRwJCB0aGF0IG1heGltaXplcyAkXHRleHR7TUV9JCwgd2UgbWF4aW1pemUgdGhlIG51bWVyYXRvciBmdW5jdGlvbiAkZihwKSA9IHAoMSAtIHApID0gcCAtIHBeMiQuIFRha2luZyB0aGUgZmlyc3QgZGVyaXZhdGl2ZSB3aXRoIHJlc3BlY3QgdG8gJHAkIGFuZCBzZXR0aW5nIGl0IHRvIHplcm86JCRcZnJhY3tkZn17ZHB9ID0gMSAtIDJwID0gMCBcaW1wbGllcyAycCA9IDEgXGltcGxpZXMgcCA9IDAuNTAkJEF0ICRuID0gMTAwMCQgYW5kICRwID0gMC41MCQsIHRoZSBtYXhpbXVtIG1hcmdpbiBvZiBlcnJvciBpczokJFx0ZXh0e01FfV97XHRleHR7bWF4fX0gPSAyIFx0aW1lcyBcc3FydHtcZnJhY3swLjUoMSAtIDAuNSl9ezEwMDB9fSA9IDIgXHRpbWVzIFxzcXJ0e1xmcmFjezAuMjV9ezEwMDB9fSBcYXBwcm94IDAuMDMxNiBccXVhZCAoMy4xNlwlKSQkDQoNCg0KDQoNCg0KIyMjIEV4ZXJjaXNlIDYNCkRlc2NyaWJlIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2Ygc2FtcGxlIHByb3BvcnRpb25zIGF0IG49MzAwDQogYW5kIHA9MC4xLiBCZSBzdXJlIHRvIG5vdGUgdGhlIGNlbnRlciwgc3ByZWFkLCBhbmQgc2hhcGUuDQogDQpBbnN3ZXI6DQoNClRvIGRlc2NyaWJlIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2Ygc2FtcGxlIHByb3BvcnRpb25zICgkXGhhdHtwfSQpIGZvciBhIHNhbXBsZSBzaXplIG9mICRuID0gMzAwJCBhbmQgYSBwb3B1bGF0aW9uIHByb3BvcnRpb24gb2YgJHAgPSAwLjEwJCwgd2UgZXZhbHVhdGUgdGhlIHNoYXBlLCBjZW50ZXIsIGFuZCBzcHJlYWQgdXNpbmcgdGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSBmb3IgcHJvcG9ydGlvbnMuDQoNCjEuIFNoYXBlDQpUbyBjaGVjayB3aGV0aGVyIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgJFxoYXR7cH0kIGlzIGFwcHJveGltYXRlbHkgbm9ybWFsLCB3ZSB2ZXJpZnkgdGhlIFN1Y2Nlc3MtRmFpbHVyZSBDb25kaXRpb246JCRuIFxjZG90IHAgPSAzMDAgXHRpbWVzIDAuMTAgPSAzMCBcZ2UgMTAkJCQkbiBcY2RvdCAoMSAtIHApID0gMzAwIFx0aW1lcyAoMSAtIDAuMTApID0gMzAwIFx0aW1lcyAwLjkwID0gMjcwIFxnZSAxMCQkU2luY2UgYm90aCBleHBlY3RlZCBzdWNjZXNzZXMgKCQzMCQpIGFuZCBleHBlY3RlZCBmYWlsdXJlcyAoJDI3MCQpIGFyZSBhdCBsZWFzdCAkMTAkLCB0aGUgY29uZGl0aW9uIGlzIHNhdGlzZmllZC5TaGFwZTogVGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiAkXGhhdHtwfSQgaXMgdW5pbW9kYWwgYW5kIGFwcHJveGltYXRlbHkgc3ltbWV0cmljIChOb3JtYWwpOiAkXGhhdHtwfSBcc2ltIE4oXG11X3tcaGF0e3B9fSwgXHNpZ21hX3tcaGF0e3B9fSkkLg0KDQoyLiBDZW50ZXINClRoZSBtZWFuIChleHBlY3RlZCB2YWx1ZSkgb2YgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiBzYW1wbGUgcHJvcG9ydGlvbnMgaXMgZXF1YWwgdG8gdGhlIHRydWUgcG9wdWxhdGlvbiBwcm9wb3J0aW9uICRwJDokJFxtdV97XGhhdHtwfX0gPSBwID0gMC4xMCQkQ2VudGVyOiBUaGUgbWVhbiBvZiB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIGlzIGNlbnRlcmVkIGF0ICQwLjEwJCAob3IgJDEwXCUkKS4NCjMuIFNwcmVhZCANCihTdGFuZGFyZCBFcnJvcilBc3N1bWluZyB0aGUgc2FtcGxlIG9mICRuID0gMzAwJCBvYnNlcnZhdGlvbnMgaXMgc2VsZWN0ZWQgcmFuZG9tbHkgYW5kIHJlcHJlc2VudHMgbGVzcyB0aGFuICQxMFwlJCBvZiB0aGUgcG9wdWxhdGlvbiAoMTAlIGNvbmRpdGlvbiksIHRoZSBzdGFuZGFyZCBlcnJvciAoJFNFJCkgbWVhc3VyZXMgdGhlIHZhcmlhYmlsaXR5IGJldHdlZW4gc2FtcGxlIHByb3BvcnRpb25zOiQkXHNpZ21hX3tcaGF0e3B9fSA9IFNFID0gXHNxcnR7XGZyYWN7cCgxIC0gcCl9e259fSQkQ2FsY3VsYXRpb246JCRcc2lnbWFfe1xoYXR7cH19ID0gXHNxcnR7XGZyYWN7MC4xMCBcdGltZXMgKDEgLSAwLjEwKX17MzAwfX0gPSBcc3FydHtcZnJhY3swLjEwIFx0aW1lcyAwLjkwfXszMDB9fSA9IFxzcXJ0e1xmcmFjezAuMDl9ezMwMH19ID0gXHNxcnR7MC4wMDAzfSBcYXBwcm94IDAuMDE3MzIkJFNwcmVhZDogVGhlIHN0YW5kYXJkIGVycm9yIG9mIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gaXMgYXBwcm94aW1hdGVseSAkMC4wMTczMiQgKG9yICQxLjczMlwlJCkuDQoNCg0KYGBge3IgcGxvdC1wcm9wLWJveXMtcHJlc2VudH0NCiMgSW5zZXJ0IGNvZGUgZm9yIEV4ZXJjaXNlIDYgaGVyZQ0KYGBgDQoNCg0KIyMjIEV4ZXJjaXNlIDcNCktlZXAgbg0KIGNvbnN0YW50IGFuZCBjaGFuZ2UgcA0KLiBIb3cgZG9lcyB0aGUgc2hhcGUsIGNlbnRlciwgYW5kIHNwcmVhZCBvZiB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIHZhcnkgYXMgcA0KIGNoYW5nZXMuIFlvdSBtaWdodCB3YW50IHRvIGFkanVzdCBtaW4gYW5kIG1heCBmb3IgdGhlIHgNCi1heGlzIGZvciBhIGJldHRlciB2aWV3IG9mIHRoZSBkaXN0cmlidXRpb24uDQoNCkFuc3dlcjoNCldoZW4gaG9sZGluZyB0aGUgc2FtcGxlIHNpemUgKCRuJCkgY29uc3RhbnQgYW5kIHZhcnlpbmcgdGhlIHBvcHVsYXRpb24gcHJvcG9ydGlvbiAoJHAkKSwgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiBzYW1wbGUgcHJvcG9ydGlvbnMgKCRcaGF0e3B9JCkgY2hhbmdlcyBpbiBzaGFwZSwgY2VudGVyLCBhbmQgc3ByZWFkIGluIHRoZSBmb2xsb3dpbmcgc3lzdGVtYXRpYyB3YXlzOg0KMS4gQ2VudGVyICgkXG11X3tcaGF0e3B9fSQpQmVoYXZpb3I6IFRoZSBjZW50ZXIgb2YgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBhbHdheXMgZXF1YWxzIHRoZSBwb3B1bGF0aW9uIHByb3BvcnRpb246JCRcbXVfe1xoYXR7cH19ID0gcCQkRWZmZWN0IG9mIGNoYW5naW5nICRwJDogQXMgJHAkIGluY3JlYXNlcywgdGhlIHBlYWsgb2YgdGhlIGRpc3RyaWJ1dGlvbiBzaGlmdHMgZGlyZWN0bHkgdG8gdGhlIHJpZ2h0IGFsb25nIHRoZSBob3Jpem9udGFsIGF4aXMgKCR4JC1heGlzKS4gQXMgJHAkIGRlY3JlYXNlcywgaXQgc2hpZnRzIHRvIHRoZSBsZWZ0Lg0KDQoyLiBTcHJlYWQgLyBTdGFuZGFyZCBFcnJvciAoJFxzaWdtYV97XGhhdHtwfX0kKUJlaGF2aW9yOiANCg0KVGhlIHZhcmlhYmlsaXR5IChzdGFuZGFyZCBlcnJvcikgaXMgY2FsY3VsYXRlZCBhczokJFxzaWdtYV97XGhhdHtwfX0gPSBcc3FydHtcZnJhY3twKDEgLSBwKX17bn19JCRFZmZlY3Qgb2YgY2hhbmdpbmcgJHAkOk1heGltaXplZCBhdCAkcCA9IDAuNTAkOiBUaGUgc3RhbmRhcmQgZXJyb3IgcmVhY2hlcyBpdHMgbWF4aW11bSB2YWx1ZSB3aGVuICRwID0gMC41MCQsIHdoZXJlICRwKDEgLSBwKSA9IDAuMjUkLiBBdCAkcCA9IDAuNTAkLCB0aGUgZGlzdHJpYnV0aW9uIGhhcyBpdHMgd2lkZXN0IHNwcmVhZC5EZWNyZWFzZXMgdG93YXJkIEV4dHJlbWEgKCRwIFx0byAwJCBvciAkcCBcdG8gMSQpOiBBcyAkcCQgbW92ZXMgZnVydGhlciBhd2F5IGZyb20gJDAuNTAkIHRvd2FyZCBlaXRoZXIgJDAkIG9yICQxJCwgJHAoMSAtIHApJCBkZWNyZWFzZXMsIGNhdXNpbmcgdGhlIHN0YW5kYXJkIGVycm9yIHRvIHNocmluayBhbmQgbWFraW5nIHRoZSBkaXN0cmlidXRpb24gbmFycm93ZXIgYW5kIHRhbGxlci5TeW1tZXRyeSBpbiBTcHJlYWQ6IFZhbHVlcyBvZiAkcCQgZXF1aWRpc3RhbnQgZnJvbSAkMC41MCQgKHN1Y2ggYXMgJHAgPSAwLjIwJCBhbmQgJHAgPSAwLjgwJCkgcHJvZHVjZSB0aGUgZXhhY3Qgc2FtZSBzdGFuZGFyZCBlcnJvciBhbmQgc3ByZWFkIHdpZHRoLg0KDQozLiBTaGFwZQ0KDQpCZWhhdmlvcjogVGhlIHNoYXBlIGlzIGdvdmVybmVkIGJ5IHRoZSBTdWNjZXNzLUZhaWx1cmUgQ29uZGl0aW9uICgkbnAgXGdlIDEwJCBhbmQgJG4oMSAtIHApIFxnZSAxMCQpLkVmZmVjdCBvZiBjaGFuZ2luZyAkcCQ6U3ltbWV0cmljIGF0ICRwID0gMC41MCQ6IFdoZW4gJHAgPSAwLjUwJCwgdGhlIGRpc3RyaWJ1dGlvbiBpcyBwZXJmZWN0bHkgc3ltbWV0cmljIGFuZCBiZWxsLXNoYXBlZCwgcmVnYXJkbGVzcyBvZiAkbiQgKHNvIGxvbmcgYXMgJG4gXGdlIDIwJCkuU2tld25lc3MgbmVhciBFeHRyZW1hOiBBcyAkcCQgZ2V0cyBjbG9zZSB0byAkMCQgb3IgJDEkLCB0aGUgZGlzdHJpYnV0aW9uIGJlY29tZXMgc2tld2VkOldoZW4gJHAkIGlzIHNtYWxsIChjbG9zZSB0byAkMCQpLCAkbnAgPCAxMCQgbWFrZXMgdGhlIGRpc3RyaWJ1dGlvbiByaWdodC1za2V3ZWQgKGJvdW5kZWQgYnkgJDAkKS5XaGVuICRwJCBpcyBsYXJnZSAoY2xvc2UgdG8gJDEkKSwgJG4oMSAtIHApIDwgMTAkIG1ha2VzIHRoZSBkaXN0cmlidXRpb24gbGVmdC1za2V3ZWQgKGJvdW5kZWQgYnkgJDEkKS5BcHByb3hpbWF0ZSBOb3JtYWxpdHk6IEFzIGxvbmcgYXMgJHAkIHN0YXlzIHdpdGhpbiBhIG1vZGVyYXRlIHJhbmdlIHN1Y2ggdGhhdCBib3RoICRucCBcZ2UgMTAkIGFuZCAkbigxIC0gcCkgXGdlIDEwJCBob2xkLCB0aGUgZGlzdHJpYnV0aW9uIHJlbWFpbnMgYXBwcm94aW1hdGVseSBub3JtYWwuDQoNCmBgYHtyIGZpbmQtbWF4LXRvdGFsfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQpuIDwtIDMwMA0KcF92YWxzIDwtIGMoMC4xMCwgMC41MCwgMC45MCkNCg0KIyBHZW5lcmF0ZSBzaW11bGF0ZWQgc2FtcGxpbmcgZGlzdHJpYnV0aW9ucw0Kc2V0LnNlZWQoMTIzKQ0Kc2ltX2RhdGEgPC0gbWFwX2RmcihwX3ZhbHMsIGZ1bmN0aW9uKHApIHsNCiAgdGliYmxlKA0KICAgIHBfbGFiZWwgPSBwYXN0ZTAoInAgPSAiLCBwKSwNCiAgICBwaGF0ID0gcmJpbm9tKDEwMDAwLCBzaXplID0gbiwgcHJvYiA9IHApIC8gbg0KICApDQp9KQ0KDQojIFBsb3Qgc2hvd2luZyBzaGlmdCBpbiBjZW50ZXIsIGNoYW5nZSBpbiBzcHJlYWQsIGFuZCBzeW1tZXRyeQ0KZ2dwbG90KHNpbV9kYXRhLCBhZXMoeCA9IHBoYXQsIGZpbGwgPSBwX2xhYmVsKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjUpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMSksIGJyZWFrcyA9IHNlcSgwLCAxLCAwLjEpKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiU2FtcGxpbmcgRGlzdHJpYnV0aW9ucyBvZiBwLWhhdCBmb3IgbiA9IDMwMCBhY3Jvc3MgdmFyeWluZyBwIiwNCiAgICB4ID0gIlNhbXBsZSBQcm9wb3J0aW9uIChwLWhhdCkiLA0KICAgIHkgPSAiRGVuc2l0eSIsDQogICAgZmlsbCA9ICJQYXJhbWV0ZXIgcCINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMjIyBFeGVyY2lzZSA4DQpOb3cgYWxzbyBjaGFuZ2Ugbg0KLiBIb3cgZG9lcyBuICBhcHBlYXIgdG8gYWZmZWN0IHRoZSBkaXN0cmlidXRpb24gb2YgcF4NCj8NCkFuc3dlcjoNCldoZW4ga2VlcGluZyAkcCQgY29uc3RhbnQgYW5kIGNoYW5naW5nIHRoZSBzYW1wbGUgc2l6ZSAkbiQsICRuJCBhZmZlY3RzIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgJFxoYXR7cH0kIGFjcm9zcyBzaGFwZSwgY2VudGVyLCBhbmQgc3ByZWFkIGluIHRoZSBmb2xsb3dpbmcgd2F5czoNCg0KMS4gU3ByZWFkIChTdGFuZGFyZCBFcnJvciAkXHNpZ21hX3tcaGF0e3B9fSQpIOKAlCBJbnZlcnNlbHkgUHJvcG9ydGlvbmFsIHRvICRcc3FydHtufQ0KDQokQmVoYXZpb3I6IFRoZSBzdGFuZGFyZCBlcnJvciBmb3JtdWxhIGlzOiQkXHNpZ21hX3tcaGF0e3B9fSA9IFxzcXJ0e1xmcmFje3AoMSAtIHApfXtufX0NCiQkRWZmZWN0IG9mIEluY3JlYXNpbmcgJG4kOkFzICRuJCBpbmNyZWFzZXMsIHRoZSBkZW5vbWluYXRvciBnZXRzIGxhcmdlciwgd2hpY2ggZGVjcmVhc2VzIHRoZSBzdGFuZGFyZCBlcnJvciAoJFxzaWdtYV97XGhhdHtwfX0kKS5UaGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIGJlY29tZXMgbmFycm93ZXIsIHRhbGxlciwgYW5kIG1vcmUgdGlnaHRseSBjbHVzdGVyZWQgYXJvdW5kIHRoZSB0cnVlIHBvcHVsYXRpb24gbWVhbiAkcCQuVG8gY3V0IHRoZSBzdGFuZGFyZCBlcnJvciAoYW5kIHRoZSBtYXJnaW4gb2YgZXJyb3IpIGluIGhhbGYsIHlvdSBtdXN0IGluY3JlYXNlIHRoZSBzYW1wbGUgc2l6ZSAkbiQgYnkgYSBmYWN0b3Igb2YgNC5FZmZlY3Qgb2YgRGVjcmVhc2luZyAkbiQ6QXMgJG4kIGRlY3JlYXNlcywgc3RhbmRhcmQgZXJyb3IgaW5jcmVhc2VzLCBjYXVzaW5nIHRoZSBkaXN0cmlidXRpb24gdG8gc3ByZWFkIG91dCBhbmQgYmVjb21lIHdpZGVyL2ZsYXR0ZXIuDQoNCjIuIFNoYXBlIOKAlCBBcHByb2FjaGVzIE5vcm1hbGl0eSBhcyAkbiQgSW5jcmVhc2VzQmVoYXZpb3I6IFRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gZGljdGF0ZXMgdGhhdCBsYXJnZXIgc2FtcGxlIHNpemVzIGZvcmNlIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgJFxoYXR7cH0kIHRvIGJlY29tZSBtb3JlIGJlbGwtc2hhcGVkIGFuZCBzeW1tZXRyaWMuU3VjY2Vzcy1GYWlsdXJlIENvbmRpdGlvbiAoJG5wIFxnZSAxMCQgYW5kICRuKDEgLSBwKSBcZ2UgMTAkKTpTbWFsbCAkbiQ6IElmICRuJCBpcyBzbWFsbCwgdGhlIGV4cGVjdGVkIGNvdW50cyAkbnAkIG9yICRuKDEgLSBwKSQgbWF5IGZhbGwgYmVsb3cgJDEwJCAoZXNwZWNpYWxseSB3aGVuICRwJCBpcyBjbG9zZSB0byAkMCQgb3IgJDEkKS4gVGhpcyBjYXVzZXMgdGhlIGRpc3RyaWJ1dGlvbiB0byBiZSBza2V3ZWQgKHJpZ2h0LXNrZXdlZCBpZiAkcCA8IDAuNSQsIGxlZnQtc2tld2VkIGlmICRwID4gMC41JCkuTGFyZ2UgJG4kOiBBcyAkbiQgZ3Jvd3MgbGFyZ2UgZW5vdWdoIHRvIHNhdGlzZnkgJG5wIFxnZSAxMCQgYW5kICRuKDEgLSBwKSBcZ2UgMTAkLCBhbnkgaW5pdGlhbCBza2V3bmVzcyBkaXNhcHBlYXJzLCBhbmQgdGhlIHNoYXBlIGJlY29tZXMgYXBwcm94aW1hdGVseSBOb3JtYWwuMy4gQ2VudGVyICgkXG11X3tcaGF0e3B9fSQpIOKAlCBVbmNoYW5nZWRCZWhhdmlvcjogVGhlIG1lYW4gKGV4cGVjdGVkIHZhbHVlKSBvZiB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIHJlbWFpbnMgZXF1YWwgdG8gdGhlIHRydWUgcG9wdWxhdGlvbiBwcm9wb3J0aW9uIHJlZ2FyZGxlc3Mgb2Ygc2FtcGxlIHNpemU6JCRcbXVfe1xoYXR7cH19ID0gcCQkRWZmZWN0IG9mIGNoYW5naW5nICRuJDogJG4kIGhhcyBubyBlZmZlY3Qgb24gdGhlIGNlbnRlci4gVGhlIGRpc3RyaWJ1dGlvbiB3aWxsIHJlbWFpbiBjZW50ZXJlZCBhdCAkcCQgd2hldGhlciAkbiA9IDMwJCBvciAkbiA9IDMsMDAwJC4NCg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHB1cnJyKQ0KDQpzZXQuc2VlZCgxMjMpDQpwIDwtIDAuMTANCm5fdmFscyA8LSBjKDMwLCAxMDAsIDMwMCwgMTIwMCkNCg0KIyBHZW5lcmF0ZSBzYW1wbGluZyBkaXN0cmlidXRpb25zIGZvciBkaWZmZXJlbnQgbg0Kc2ltX25fZGF0YSA8LSBtYXBfZGZyKG5fdmFscywgZnVuY3Rpb24obl9zaXplKSB7DQogIHRpYmJsZSgNCiAgICBuX2xhYmVsID0gZmFjdG9yKHBhc3RlMCgibiA9ICIsIG5fc2l6ZSksIGxldmVscyA9IHBhc3RlMCgibiA9ICIsIG5fdmFscykpLA0KICAgIHBoYXQgPSByYmlub20oMTAwMDAsIHNpemUgPSBuX3NpemUsIHByb2IgPSBwKSAvIG5fc2l6ZQ0KICApDQp9KQ0KDQojIE92ZXJsYXkgZGVuc2l0eSBjdXJ2ZXMNCmdncGxvdChzaW1fbl9kYXRhLCBhZXMoeCA9IHBoYXQsIGZpbGwgPSBuX2xhYmVsKSkgKw0KICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjQpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMC4zKSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkVmZmVjdCBvZiBTYW1wbGUgU2l6ZSAobikgb24gU2FtcGxpbmcgRGlzdHJpYnV0aW9uIG9mIHAtaGF0IChwID0gMC4xMCkiLA0KICAgIHggPSAiU2FtcGxlIFByb3BvcnRpb24gKHAtaGF0KSIsDQogICAgeSA9ICJEZW5zaXR5IiwNCiAgICBmaWxsID0gIlNhbXBsZSBTaXplIChuKSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KIyMjIEV4ZXJjaXNlIDkNCklzIHRoZXJlIGNvbnZpbmNpbmcgZXZpZGVuY2UgdGhhdCB0aG9zZSB3aG8gc2xlZXAgMTArIGhvdXJzIHBlciBkYXkgYXJlIG1vcmUgbGlrZWx5IHRvIHN0cmVuZ3RoIHRyYWluIGV2ZXJ5IGRheSBvZiB0aGUgd2Vlaz8gQXMgYWx3YXlzLCB3cml0ZSBvdXQgdGhlIGh5cG90aGVzZXMgZm9yIGFueSB0ZXN0cyB5b3UgY29uZHVjdCBhbmQgb3V0bGluZSB0aGUgc3RhdHVzIG9mIHRoZSBjb25kaXRpb25zIGZvciBpbmZlcmVuY2UuIElmIHlvdSBmaW5kIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSwgYWxzbyBxdWFudGlmeSB0aGlzIGRpZmZlcmVuY2Ugd2l0aCBhIGNvbmZpZGVuY2UgaW50ZXJ2YWwuDQpBbnN3ZXI6DQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKQ0KDQojIDEuIFByZXBhcmUgRGF0YQ0KeXJic3Nfc3RyZW5ndGggPC0geXJic3MgJT4lDQogIGRyb3BfbmEoc2Nob29sX25pZ2h0X2hvdXJzX3NsZWVwLCBzdHJlbmd0aF90cmFpbmluZ183ZCkgJT4lDQogIG11dGF0ZSgNCiAgICBzbGVlcF8xMHBsdXMgPSBpZmVsc2Uoc2Nob29sX25pZ2h0X2hvdXJzX3NsZWVwID09ICIxMCsiLCAiMTArIGhvdXJzIiwgIjwxMCBob3VycyIpLA0KICAgIHNsZWVwXzEwcGx1cyA9IGZhY3RvcihzbGVlcF8xMHBsdXMsIGxldmVscyA9IGMoIjEwKyBob3VycyIsICI8MTAgaG91cnMiKSksDQogICAgc3RyZW5ndGhfZGFpbHkgPSBpZmVsc2Uoc3RyZW5ndGhfdHJhaW5pbmdfN2QgPT0gNywgInllcyIsICJubyIpLA0KICAgIHN0cmVuZ3RoX2RhaWx5ID0gZmFjdG9yKHN0cmVuZ3RoX2RhaWx5LCBsZXZlbHMgPSBjKCJ5ZXMiLCAibm8iKSkNCiAgKQ0KDQojIDIuIENvbXB1dGUgT2JzZXJ2ZWQgRGlmZmVyZW5jZSBpbiBQcm9wb3J0aW9ucw0Kb2JzX2RpZmYgPC0geXJic3Nfc3RyZW5ndGggJT4lDQogIHNwZWNpZnkoc3RyZW5ndGhfZGFpbHkgfiBzbGVlcF8xMHBsdXMsIHN1Y2Nlc3MgPSAieWVzIikgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gcHJvcHMiLCBvcmRlciA9IGMoIjEwKyBob3VycyIsICI8MTAgaG91cnMiKSkNCg0Kb2JzX2RpZmYNCg0KIyAzLiBDb25kdWN0IEh5cG90aGVzaXMgVGVzdCB2aWEgUGVybXV0YXRpb24gLyBTaW11bGF0aW9uDQpudWxsX2Rpc3QgPC0geXJic3Nfc3RyZW5ndGggJT4lDQogIHNwZWNpZnkoc3RyZW5ndGhfZGFpbHkgfiBzbGVlcF8xMHBsdXMsIHN1Y2Nlc3MgPSAieWVzIikgJT4lDQogIGh5cG90aGVzaXplKG51bGwgPSAiaW5kZXBlbmRlbmNlIikgJT4lDQogIGdlbmVyYXRlKHJlcHMgPSAxMDAwLCB0eXBlID0gInBlcm11dGUiKSAlPiUNCiAgY2FsY3VsYXRlKHN0YXQgPSAiZGlmZiBpbiBwcm9wcyIsIG9yZGVyID0gYygiMTArIGhvdXJzIiwgIjwxMCBob3VycyIpKQ0KDQojIENhbGN1bGF0ZSBwLXZhbHVlDQpwX3ZhbHVlIDwtIG51bGxfZGlzdCAlPiUNCiAgZ2V0X3BfdmFsdWUob2JzX3N0YXQgPSBvYnNfZGlmZiwgZGlyZWN0aW9uID0gImdyZWF0ZXIiKQ0KDQpwX3ZhbHVlDQoNCiMgNC4gUXVhbnRpZnkgRGlmZmVyZW5jZSB3aXRoIGEgOTUlIENvbmZpZGVuY2UgSW50ZXJ2YWwgKEJvb3RzdHJhcCkNCmJvb3RfZGlzdCA8LSB5cmJzc19zdHJlbmd0aCAlPiUNCiAgc3BlY2lmeShzdHJlbmd0aF9kYWlseSB+IHNsZWVwXzEwcGx1cywgc3VjY2VzcyA9ICJ5ZXMiKSAlPiUNCiAgZ2VuZXJhdGUocmVwcyA9IDEwMDAsIHR5cGUgPSAiYm9vdHN0cmFwIikgJT4lDQogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gcHJvcHMiLCBvcmRlciA9IGMoIjEwKyBob3VycyIsICI8MTAgaG91cnMiKSkNCg0KY2lfZGlmZiA8LSBib290X2Rpc3QgJT4lDQogIGdldF9jaShsZXZlbCA9IDAuOTUpDQoNCmNpX2RpZmYNCg0KYGBgDQoNCg0KDQoNCg0KDQojIyMgRXhlcmNpc2UgMTANCkxldOKAmXMgc2F5IHRoZXJlIGhhcyBiZWVuIG5vIGRpZmZlcmVuY2UgaW4gbGlrZWxpbmVzcyB0byBzdHJlbmd0aCB0cmFpbiBldmVyeSBkYXkgb2YgdGhlIHdlZWsgZm9yIHRob3NlIHdobyBzbGVlcCAxMCsgaG91cnMuIFdoYXQgaXMgdGhlIHByb2JhYmxpdHkgdGhhdCB5b3UgY291bGQgZGV0ZWN0IGEgY2hhbmdlIChhdCBhIHNpZ25pZmljYW5jZSBsZXZlbCBvZiAwLjA1KSBzaW1wbHkgYnkgY2hhbmNlPyBIaW50OiBSZXZpZXcgdGhlIGRlZmluaXRpb24gb2YgdGhlIFR5cGUgMSBlcnJvci4NCg0KQW5zd2VyOg0KDQpUaGUgcHJvYmFiaWxpdHkgb2YgZGV0ZWN0aW5nIGEgY2hhbmdlIHNpbXBseSBieSBjaGFuY2UgaXMgZXF1YWwgdG8gdGhlIHNpZ25pZmljYW5jZSBsZXZlbCAoJFxhbHBoYSQpLCB3aGljaCBpcyAkMC4wNSQgKG9yICQ1XCUkKS4NCg0KRXhwbGFuYXRpb24gJiBDb250ZXh0Og0KDQpEZWZpbml0aW9uIG9mIFR5cGUgSSBFcnJvciAoJFxhbHBoYSQpOiQkXHRleHR7VHlwZSBJIEVycm9yfSA9IFAoXHRleHR7UmVqZWN0IH0gSF8wIFxtaWQgSF8wIFx0ZXh0eyBpcyB0cnVlfSkgPSBcYWxwaGEkJFRoZSBzaWduaWZpY2FuY2UgbGV2ZWwgJFxhbHBoYSQgcmVwcmVzZW50cyB0aGUgdGhyZXNob2xkIHNldCBieSB0aGUgcmVzZWFyY2hlciBmb3IgaG93IG11Y2ggcmlzayBvZiBhIGZhbHNlIHBvc2l0aXZlIHRoZXkgYXJlIHdpbGxpbmcgdG8gYWNjZXB0Lg0KDQpJbiBDb250ZXh0Og0KDQpXaGVuIGNvbmR1Y3RpbmcgYSBoeXBvdGhlc2lzIHRlc3Qgd2l0aCAkXGFscGhhID0gMC4wNSQsIHlvdSBhcmUgZXN0YWJsaXNoaW5nIGEgZGVjaXNpb24gcnVsZSB3aGVyZSAkNVwlJCBvZiBhbGwgc2FtcGxlcyBkcmF3biBmcm9tIGEgcG9wdWxhdGlvbiB3aXRoIG5vIHRydWUgZGlmZmVyZW5jZSB3aWxsIHJhbmRvbWx5IHByb2R1Y2UgYSBzYW1wbGUgc3RhdGlzdGljIGV4dHJlbWUgZW5vdWdoIHRvIGZhbGwgaW4gdGhlIHJlamVjdGlvbiByZWdpb24sIGxlYWRpbmcgdG8gYSBmYWxzZSBjb25jbHVzaW9uIG9mIGEgZGlmZmVyZW5jZS4NCg0KDQoNCg0KDQoNCiMjIyBFeGVyY2lzZSAxMQ0KU3VwcG9zZSB5b3XigJlyZSBoaXJlZCBieSB0aGUgbG9jYWwgZ292ZXJubWVudCB0byBlc3RpbWF0ZSB0aGUgcHJvcG9ydGlvbiBvZiByZXNpZGVudHMgdGhhdCBhdHRlbmQgYSByZWxpZ2lvdXMgc2VydmljZSBvbiBhIHdlZWtseSBiYXNpcy4gQWNjb3JkaW5nIHRvIHRoZSBndWlkZWxpbmVzLCB0aGUgZXN0aW1hdGUgbXVzdCBoYXZlIGEgbWFyZ2luIG9mIGVycm9yIG5vIGdyZWF0ZXIgdGhhbiAxJSB3aXRoIDk1JSBjb25maWRlbmNlLiBZb3UgaGF2ZSBubyBpZGVhIHdoYXQgdG8gZXhwZWN0IGZvciBwIC4gSG93IG1hbnkgcGVvcGxlIHdvdWxkIHlvdSBoYXZlIHRvIHNhbXBsZSB0byBlbnN1cmUgdGhhdCB5b3UgYXJlIHdpdGhpbiB0aGUgZ3VpZGVsaW5lcz8NCkhpbnQ6IFJlZmVyIHRvIHlvdXIgcGxvdCBvZiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcA0KIGFuZCBtYXJnaW4gb2YgZXJyb3IuIFRoaXMgcXVlc3Rpb24gZG9lcyBub3QgcmVxdWlyZSB1c2luZyBhIGRhdGFzZXQuDQoNCg0KQW5zd2VyOg0KDQpUbyBkZXRlcm1pbmUgdGhlIHJlcXVpcmVkIHNhbXBsZSBzaXplICgkbiQpIHVuZGVyIHRoZSBzdHJpY3Rlc3QgY29uZGl0aW9ucywgd2UgdXNlIHRoZSB3b3JzdC1jYXNlIHNjZW5hcmlvIGZvciB2YXJpYWJpbGl0eSBiYXNlZCBvbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcG9wdWxhdGlvbiBwcm9wb3J0aW9uICgkcCQpIGFuZCBtYXJnaW4gb2YgZXJyb3IgKCRNRSQpLg0KDQoxLiBEZXRlcm1pbmluZyB0aGUgVmFsdWUgb2YgJHAkDQpBcyBlc3RhYmxpc2hlZCBpbiB0aGUgJE1FJCB2cy4gJHAkIGN1cnZlLCB0aGUgbWFyZ2luIG9mIGVycm9yIHJlYWNoZXMgaXRzIGFic29sdXRlIG1heGltdW0gd2hlbiAkcCA9IDAuNTAkICgkNTBcJSQpLg0KDQpXaGVuIHlvdSBoYXZlIG5vIHByaW9yIGluZm9ybWF0aW9uIG9yIGV4cGVjdGF0aW9uIGFib3V0ICRwJCwgdXNpbmcgJHAgPSAwLjUwJCBwcm92aWRlcyB0aGUgbW9zdCBjb25zZXJ2YXRpdmUgKHdvcnN0LWNhc2UpIGVzdGltYXRlLiBUaGlzIGd1YXJhbnRlZXMgdGhhdCB5b3VyIHNhbXBsZSBzaXplIHdpbGwgYmUgbGFyZ2UgZW5vdWdoIHRvIGFjaGlldmUgYSBtYXJnaW4gb2YgZXJyb3Igb2YgJDFcJSQgb3IgbGVzcywgcmVnYXJkbGVzcyBvZiB3aGF0IHRoZSB0cnVlIHBvcHVsYXRpb24gcHJvcG9ydGlvbiB0dXJucyBvdXQgdG8gYmUuDQoNCjIuIEdpdmVuIFBhcmFtZXRlcnMNCg0KVGFyZ2V0IE1hcmdpbiBvZiBFcnJvciAoJE1FJCk6ICQwLjAxJCAoJDFcJSQpDQoNCkNvbmZpZGVuY2UgTGV2ZWw6ICQ5NVwlJA0KDQpDcml0aWNhbCBWYWx1ZSAoJHpeKiQpOiAkMS45NiQgKGZvciBhICQ5NVwlJCBjb25maWRlbmNlIGxldmVsKQ0KDQpBc3N1bWVkIFByb3BvcnRpb24gKCRwJCk6ICQwLjUwJA0KDQozLiBTYW1wbGUgU2l6ZSBGb3JtdWxhICYgQ2FsY3VsYXRpb24NCg0KVGhlIGZvcm11bGEgZm9yIHRoZSBtYXJnaW4gb2YgZXJyb3Igb2YgYSBwcm9wb3J0aW9uIGlzOiQkTUUgPSB6XiogXHRpbWVzIFxzcXJ0e1xmcmFje3AoMSAtIHApfXtufX0kJFNvbHZpbmcgZm9yIHNhbXBsZSBzaXplICRuJDokJG4gPSBcbGVmdCggXGZyYWN7el4qfXtNRX0gXHJpZ2h0KV4yIFx0aW1lcyBwKDEgLSBwKSQkU3RlcC1ieS1TdGVwIFN1YnN0aXR1dGlvbjokJG4gPSBcbGVmdCggXGZyYWN7MS45Nn17MC4wMX0gXHJpZ2h0KV4yIFx0aW1lcyAoMC41MCkoMSAtIDAuNTApJCQkJG4gPSAoMTk2KV4yIFx0aW1lcyAwLjI1JCQkJG4gPSAzOCw0MTYgXHRpbWVzIDAuMjUgPSA5LDYwNCQkDQoNCg0KQ29uY2x1c2lvbg0KDQpJdCB3b3VsZCBuZWVkIHRvIHNhbXBsZSBhdCBsZWFzdCA5LDYwNCByZXNpZGVudHMgdG8gZW5zdXJlIHRoYXQgeW91ciBlc3RpbWF0ZSBvZiB0aGUgcHJvcG9ydGlvbiBvZiByZXNpZGVudHMgYXR0ZW5kaW5nIHdlZWtseSByZWxpZ2lvdXMgc2VydmljZXMgaGFzIGEgbWFyZ2luIG9mIGVycm9yIG5vIGdyZWF0ZXIgdGhhbiAkMVwlJCBhdCBhICQ5NVwlJCBjb25maWRlbmNlIGxldmVsLg0KDQo=