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.

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

  1. 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}})\).

  2. 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\%\)).

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

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

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

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

  1. 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.
p_value
## # 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\)).

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

  1. 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\)

  1. 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=