# read in data
data = rbind.data.frame(5.2,  7.8,  9.1, 11.3, 12.5, 13.0, 14.2, 15.1, 15.9, 16.7, 17.2, 17.8, 18.4, 18.9, 
  19.3, 19.7, 20.2, 20.6, 21.0, 21.5, 21.9, 22.3, 22.7, 23.1, 23.5, 23.9, 24.3, 24.7, 
  25.1, 25.5, 25.9, 26.3, 26.7, 27.1, 27.5, 27.9, 28.3, 28.7, 29.1, 29.5, 29.9, 30.3, 
  30.7, 31.1, 31.5, 31.9, 32.3, 32.7, 33.1, 33.5, 33.9, 34.3, 34.7, 35.1, 35.5, 35.9, 
  36.3, 36.7, 37.1, 37.5, 37.9, 38.3, 38.7, 39.1, 39.5, 39.9, 40.3, 40.7, 41.1, 41.5,
  41.9, 42.3, 42.7, 43.1, 43.5)
colnames(data) = "time"
  # time is in months

Intro and Setup

The dataset at our disposal for this analyis is made up of 75 recorded failure times (measured in months) for wind turbine gearbox components. Summary statistics as well as a histogram depiction of our sample data can be seen below.

sum_stats_table = function(variable){
  table = cbind(
    round(min(variable),2),
    round(quantile(variable, 0.25),2),
    round(median(variable),2),
    round(mean(variable),2),
    round(quantile(variable, 0.75),2),
    round(max(variable),2)
  )
  colnames(table) = c("Min", "Q1", "Med", "Mean", "Q3", "Max")
  rownames(table) = NULL
  return(table)
}

Summary_Table = sum_stats_table(variable = data$time)
kable(Summary_Table,align = "c",
      caption = "<span style='color:##000000;'>
      Summary Stats of Survival Times (Months)</span>") %>%
  kable_styling(
    bootstrap_options = c("striped", "bordered"),
    full_width = FALSE,
    position = "center")
Summary Stats of Survival Times (Months)
Min Q1 Med Mean Q3 Max
5.2 21.25 28.7 28.19 36.1 43.5
ggplot(data = data) +
  geom_histogram(mapping = aes(x = time, y = after_stat(density)),
                 color = "black",
                  # argument color in geom_histogram is for color of bin lines
                 fill = "lightblue",
                 bins = 10,) +
  labs(title = "Distribution of Survival Times",
       x = "Time (Months)",
       y = "Density") + 
  theme(
    panel.border = element_rect(color = "black", fill = NA, linewidth = 3)
  ) # this is the equivalent of box(lwd = 3) in base R

The engineering team at a wind energy company is unsure whether to label and treat the broader population distribution of fail times as exponentially or Weibull distributed. The probability density of an exponential distribution is simply a more simplified version of the Weibull’s. It is the value of our shape parameter, \(\beta\), that determines which of these distribution’s we will label as the framework for predictive analysis on gearbox fail times moving forward.

For the purposes of today’s analysis, we will treat the null hypothesis that said population is exponentially distributed (AKA \(\beta = 1\)), and the alternative hypothesis that a Weibull distribution more accurately represents the broader population of gearbox fail times (AKA \(\beta \neq 1\)).

\[\begin{align} H_0&: \beta = 1 \quad \text{Takeaway: Exponential} \\ H_a&: \beta \neq 1 \quad \text{Takeaway: Weibull} \end{align}\]

In order to assess the validity of these opposing hypotheses, we must first quantify an estimate for our parameter \(\beta\) under the assumption of each scenario (Weibull distribution vs exponential distribution). In the following sections, I will use maximum likelihood estimation (MLE) to do so.

a.) MLE of Weibull

Operating under the assumption that the population of gearbox fail times is Weibull distributed, we can use MLE to simultaneously generate estimates for the shape parameter, \(\beta\), and the the scale parameter, \(\lambda\). We’ll denote these estimates as \(\hat{\beta}\) and \(\hat{\lambda}\) respectively.

Parameter calculations were performed with R’s built-in optim() function. For mathematical reference, the log-likelihood function for the Weibull distribution as well as the partial derivatives of that very function with respect to both \(\beta\) and \(\lambda\) are below.

\[\Large \ell(\beta,\lambda|t) = [n \times \ln(\beta)] - [n \times \beta \times \ln(\lambda)] + [(\beta - 1) \times \sum\ln(t_i)] - \sum\left(\frac{(t_i)}{\lambda}\right)^\beta \]


\[\Large \frac{\partial f}{\partial \beta} = \frac{n}{\beta} - n \times \ln(\lambda) + \sum\ln(t_i) - \sum\left(\ln\frac{t_i}{\lambda}\right) \times \left(\frac{t_i}{\lambda}\right)^\beta \]


\[\Large \frac{\partial f}{\partial \lambda} = \frac{\beta}{\lambda} \times \sum\left(\frac{t_i}{\lambda}\right)^\beta - n \]

## MLE Weibull Estimation
  # code is largely copied from HW 9 assignment, which took formulas and procedure from following:
    # Week 11, Section 5.2 
    # Week 7, Section 5

#### define likelihood function
## *negative* log likelihood function for Weibull distribution
  # by negative log likelihood, this function....
log_likelihood = function(params, data) {
  beta = params[1]  # shape
  lambda = params[2]  # scale 
  
  # Ensure parameters are positive
  if (beta <= 0 || lambda <= 0) {
    return(1e10)  # Return large value for invalid parameters
  }
  
  n = length(data)
  log_lik = n * log(beta) - n * beta * log(lambda) + 
    (beta - 1) * sum(log(data)) - sum((data / lambda)^beta)
  
  return(log_lik)  # Return log-likelihood! NOT the negative log-likelihood
}

#### define score equations (partial derivatives)
log_likelihood_gradient = function(params, data) {
  beta = params[1]       # shape parameter
  lambda = params[2]  # scale parameter
  
  n = length(data)
  
  partial_deriv_beta = n/beta - n * log(lambda) + sum(log(data)) - 
        sum(log(data/lambda) * (data/lambda)^beta)
  
  partial_deriv_lambda =  (beta/lambda)*(sum((data/lambda)^beta) -n)
  
  return(c(partial_deriv_beta,
           partial_deriv_lambda))  # Gradient of log-likelihood, NOT the negative scores
}

#### use log likelihood and score equations in optim function

# need to have good initial guesses for beta and lambda for the optim function
beta_guess = (sd(data$time)/mean(data$time))^(-1.086)

lambda_guess = mean(data$time)/gamma(1 + 1/beta_guess)


weib_mle_estimates = optim(
  par = c(beta_guess, lambda_guess), # par argument is initial "guesses"
  data = data$time,
  fn = log_likelihood,
  gr = log_likelihood_gradient,
  method = "L-BFGS-B",
  hessian = TRUE,
    # will use the Hessian matrix later on
  control = list(maxit = 1000, 
                 fnscale  = -1,
                 trace = FALSE,
                 abstol = 1e-8)
)
#weib_mle_estimates
  
weib_mle_beta = weib_mle_estimates$par[1] # shape
weib_mle_lambda = weib_mle_estimates$par[2] # scale

Post-MLE, we have estimates of about 3.371 and 31.418 for \(\beta\) and \(\lambda\) respectively. To further ensure these estimates seem reasonable, below I overlaid a Weibull distribution with said parameter values atop our available sample data.

ggplot(data = data) +
  geom_histogram(mapping = aes(x = time, y = after_stat(density)),
                 color = "black",
                  # argument color in geom_histogram is for color of bin lines
                 fill = "lightblue",
                 bins = 10,) +
  # use stat_function in ggplot to show density curves of other distributions
    stat_function(fun = dweibull, 
                args = list(shape = weib_mle_beta, scale = weib_mle_lambda),
                color = "black",
                linewidth = 1.5,
                xlim = range(0:50))+
            # xlim argument so curve doesn't awkardly cut out at edge points of data
  labs(title = "Distribution of Gearbox Survival Times (Weibull)",
       x = "Time (Months)",
       y = "Density") + 
  theme(
    panel.border = element_rect(color = "black", fill = NA, linewidth = 3),
    legend.position = c(0.85, 0.85)
  )

As we can see in our histogram above, there is certainly a respectable amount of overlap between the distributions of our sample data and a theoretical Weibull density curve with parameters of \(\beta \approx 3.371\) and \(\lambda \approx 31.418\). This leads us to believe that if we are to label the broader population of gearbox survival times as Weibull distributed, then the \(\beta\) and \(\lambda\) estimates prescribed via MLE are quality starting population estimators.

Now for comparison’s sake, I will repeat the MLE and visualization procedure, but this time operating under the assumption that the gearbox survival times are generally exponentially distributed.

b.) MLE of Exponential

As alluded to before, the exponential distribution can be simplistically described as a less complicated “version” of the Weibull distribution. Instead of employing two active parameters, the exponential distribution’s only parameter is \(\lambda\), which we will now estimate via MLE. Log-likelihood functions and partial derivatives are written below.

\[\Large \ell(\lambda|t) = -[n \times \ln(\lambda)] - \frac{\sum(t_i)}{\lambda} \]


\[\Large \frac{\partial f}{\partial \lambda} = \frac{n}{\lambda} + \frac{\sum(t_i)}{\lambda^2} \]


## Exponential MLE Distribution
  # once again code largely brought over from HW 9 assignment

# exponential log likelihood follows same pattern as Weibull log likelihood but a MUCH simpler distribution
exp_log_likelihood = function(lambda, data) {
 if (lambda <= 0) return (1e10)
 n = length(data)
 log_lik = -n * log(lambda) - sum(data)/lambda
 return(log_lik)
}

### now define partial derivative w/ respect to lambda (the score function or gradient)
  # performed via quick hand calculation

exp_gradient = function(lambda, data) {
  if (lambda <= 0) return (NA)
  n = length(data)
  partial_deriv_lambda = (n/lambda) + (sum(data)/(lambda^2))
  return(partial_deriv_lambda)
}

exp_mle_estimates = optim(
  par = 1/mean(data$time),
    # the initial guess can simply be 1/(mean of the data) since we are performing this analysis under the theoretical that it is an EXPONENTIAL distribution. The mean of an exponential distribution is 1 divided by the the rate parameter lambda
  data = data$time,
  fn = exp_log_likelihood,
  gr = exp_gradient,
  method = "L-BFGS-B",
  hessian = TRUE,
    # will use the Hessian matrix later on
  control = list(maxit = 1000, 
                 fnscale  = -1,
                 trace = FALSE,
                 abstol = 1e-8)
)
  
#exp_mle_estimates$par

exp_mle_lambda = exp_mle_estimates$par

Per MLE calculations, we can assert that the \(\lambda\) parameter of the distribution of gearbox survival times, if said distribution was truly exponential, is estimated to be roughly 28.377. An exponential distribution with \(\lambda = 28.377\) is overlaid atop the sample data and available below.

ggplot(data = data) +
  geom_histogram(mapping = aes(x = time, y = after_stat(density)),
                 color = "black",
                  # argument color in geom_histogram is for color of bin lines
                 fill = "lightblue",
                 bins = 10,) +
  # use stat_function in ggplot to show density curves of other distributions
    stat_function(fun = dexp, 
                args = list(rate = 1/exp_mle_lambda),
                color = "red",
                linewidth = 1.5,
                xlim = range(0:50)
                )+
            # xlim argument so curve doesn't awkardly cut out at edge points of data
  labs(title = "Distribution of Survival Times (Exp)",
       x = "Time (Months)",
       y = "Density") + 
  theme(
    panel.border = element_rect(color = "black", fill = NA, linewidth = 3),
    legend.position = c(0.85, 0.85)
  )

Comparing this histogram to the one from part a, we see a drastic decline in distribution resemblance between the sample data and the theoretical density curve, when working under the assumption that the population of gearbox survival times is exponentially distributed. We will keep this in mind moving forward, as we run hypothesis tests to quantify the differences between the two distribution assumptions.

c.) Likelihood Ratio Test

To further investigate the difference in each distribution’s fit with regards to our population of interest (gearbox survival times), we will perform a likelihood ratio test (LRT). The LRT takes into account the log-likelihood function evaluated with parameter values estimated from a simpler model (the exponential in this case) and the log-likelihood function evaluated with parameter values estimated from a more complicated model (the Weibull in this scenario). The null hypothesis of such a test is that, per our sample data, there is no significant difference between the two model fits.

# weib_mle_beta and weib_mle_lambda are UNRESTRICTED MLE VALUES, but now we must find

# null hypothesis is that beta = 1
# if null hypothesis is true, then distribution is really just exponential

## the likelihood ratio test is just 2 * 
  # [log likelihood evaluated in unrestricted way] -
  # [log likelihood evaluated in restricted or simple way]

# need to evaluate each distribution's likelihood function at the previously estimated parameters of beta and/or lambda
log_evaluation_weib = log_likelihood(params = c(weib_mle_beta, weib_mle_lambda),
                                     data = data)
log_evaluation_exp = exp_log_likelihood(lambda = exp_mle_lambda,
                                        data = data)

# test stat for likelihood ratio test is uppercase Lambda

Lambda = 2 * abs(log_evaluation_weib - log_evaluation_exp)

p_value_likelihoodratio = 1 - pchisq(Lambda, df = 1)
  # test stat distribution for likelihood ratio test is chi-square distributed
  # df = number of parameters we are estimating in function

Our LRT returned an extremely high test value (\(\Lambda\)) of about 1145.444. Considering \(\Lambda\) follows a chi-square distribution, this test stat coincides with a p value of approximately zero. With these findings, we must reject the null hypothesis as there is very convincing evidence that the Weibull distribution more accurately represents the fit of our population of interest than the exponential distribution does. After examining the histograms in parts a and b, this finding is not surprising.

d.) Bootstrap Likelihood Ratio Test

Lastly, I repeated this same type of procedure, likelihood ratio testing, and applied it to a bootstrapped scenario. Under the guise of the bootstrap LRT, we take repeated samples of a theoretical distribution, in this case an exponential distribution with \(\lambda \approx\) 28.377. Then, for each sample, a test statistic of \(\Lambda\) is found using that particular bootstrap sample’s log-likelihood evaluation along with the log-likelihood evaluation of our original and more complex/unrestricted model (the Weibull in this scenario).

### Bootstrap Likelihood Ratio Test (BLRT) for short
# reference code section 4.3 from Week 12 notes, need to change formulas since we are applying to exponential distribution, not normal

bootstrap_lrt_test = function(data, b, rate_null, obs_lr_stat){
    # obs_lr_stat will = Lambda = likelihood ratio test stat taken from observed data calculations
  n = length(data)
  boot_lr_stat = numeric(b)
    
  # Log-likelihood functions are found in earlier code chunks and will be called to within the optim functions of the for loop process
    
  # START FOR LOOP
    for (i in 1:b){
      
      # Generating artificial data meant to replicate the characteristics of our NULL hypothesis
      # In this case, our null hypothesis is that the data fits an exponential distribution with rate parameter lambda
      boot_exp_sample = rexp(n = n, rate = rate_null) 
  
      ####### Weibull likelihood per boot sample    
      boot_beta_guess = (sd(boot_exp_sample)/mean(boot_exp_sample))^(-1.086)

      boot_lambda_guess = mean(boot_exp_sample)/gamma(1 + 1/boot_beta_guess)
      
      boot_log_weib = optim(
          par = c(boot_beta_guess, boot_lambda_guess), # par argument is initial "guesses"
          data = boot_exp_sample,
          fn = log_likelihood,
          gr = log_likelihood_gradient,
          method = "L-BFGS-B",
          lower = c(1e-8, 1e-8), ## this limiting lower argument is NECESSARY, before I added it I was getting an error line for "non-finite value supplied by optim"
          hessian = TRUE,
          control = list(maxit = 1000, 
                         fnscale  = -1,
                         trace = FALSE,
                         abstol = 1e-8)
          )
      boot_log_weib = boot_log_weib$value # store log likelihood evaluation
      ####### End Weibull likelihood per boot sample 
  

      ####### Exponential likelihood per boot sample    
      boot_log_exp = optim(
          par = 1/mean(boot_exp_sample),
          data = boot_exp_sample,
          fn = exp_log_likelihood,
          gr = exp_gradient,
          method = "L-BFGS-B",
          hessian = TRUE,
          control = list(maxit = 1000, 
                         fnscale  = -1,
                         trace = FALSE,
                         abstol = 1e-8)
          )
      boot_log_exp = boot_log_exp$value  # store log likelihood evaluation
      ####### End Exponential likelihood per boot sample  
      
      
      # the likelihood ratio for EACH instance of the bootstrap is 2 times the difference between the likelihood ratio evaluated under unrestricted (Weibull) circumstances and evaluated under simpler (exponential) circumstances
      boot_lr_stat[i] = 2 * abs(boot_log_weib - boot_log_exp)
      

    } # END FOR LOOP
    
  # calculate and output final p value
  p = (sum(boot_lr_stat >= obs_lr_stat) + 1)/ (b + 1)
  
  ### FINAL p value of bootstrap exercise is equal to.. 
  # number of bootstrap sample LR test stats greater than or equal to the original LR test stat found in section c
  
  return(list(p_value_bootstrap = p,
              bootstrap_lr_stats = boot_lr_stat))
  
} #### END BOOTSTRAP FUNCTION


## now running the function
set.seed(123)
BLRT_test = bootstrap_lrt_test(data = data$time,
                               b = 1000, 
                               rate_null = exp_mle_lambda,
                               obs_lr_stat = Lambda)

# BLRT_test$p_value_bootstrap = 0.000999001

Using a repeated sample size of 1,000, there once again appears to be significant evidence that an assumption of exponential distribution would result in a much less accurate resemblance of our population of gearbox survival times than an assumption of Weibull distribution would. Our bootstrap LRT yielded a p-value of only 0.001.

e.) Summary and Conclusions

To summarize, all of the analysis up to this point supports the notion of moving forward under the assumption that the broader population of gearbox survival times is Weibull distributed with a shape parameter (\(\beta\)) of about 3.371 and scale parameter (\(\lambda\)) of roughly 31.418. Both the standard and bootstrap iterations of the LRT show a significant decline in distribution resemblance when assuming an exponential distribution. Furthermore, we could see in preliminary visual analysis via the histograms in sections a and b, that a Weibull distribution density curve with said paremeters was much more aligned with our sample distribution than that of the exponential curve with \(\beta\) value of approximately 28.377.

LS0tCnRpdGxlOiAiQm9vdHN0cmFwIExpa2VsaWhvb2QgUmF0aW8gVGVzdCIKYXV0aG9yOiAiQ2hyaXMgQmFobSIKZGF0ZTogIkFwcmlsIDE4LCAyMDI2IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfd2lkdGg6IDYKICAgIGZpZ19oZWlnaHQ6IDQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0Ci0tLQoKYGBge2NzcywgZWNobyA9IEZBTFNFfQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOwogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOwogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsKICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsKfQoKaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8KICBmb250LXNpemU6IDI0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IAojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4KCmlmICghcmVxdWlyZSgia25pdHIiKSkgeyAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBjb25kaXRpb25hbCBzdGF0ZW1lbnQgdG8gZGV0ZWN0CiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikgICAgICAgICAgICAgICAgICAjIHdoZXRoZXIgYSBwYWNrYWdlIHdhcyBpbnN0YWxsZWQgaW4KICAgbGlicmFyeShrbml0cikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91ciBtYWNoaW5lLiBJZiBub3QsIGluc3RhbGwgaXQgYW5kCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxvYWQgaXQgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgoKaWYgKCFyZXF1aXJlKHRpZHl2ZXJzZSkpIHtsaWJyYXJ5KHRpZHl2c2Vyc2UpfSAKCmlmICghcmVxdWlyZShHR2FsbHkpKSB7bGlicmFyeShHR2FsbHkpfSAKCmlmICghcmVxdWlyZShrYWJsZUV4dHJhKSkge2xpYnJhcnkoa2FibGVFeHRyYSl9IAoKaWYgKCFyZXF1aXJlKGdncGxvdDIpKSB7bGlicmFyeShnZ3Bsb3QyKX0gCgppZiAoIXJlcXVpcmUoY2FyKSkge2xpYnJhcnkoY2FyKX0gCgppZiAoIXJlcXVpcmUoZHBseXIpKSB7bGlicmFyeShkcGx5cil9IAoKaWYgKCFyZXF1aXJlKHBhbmRlcikpIHtsaWJyYXJ5KHBhbmRlcil9IAoKaWYgKCFyZXF1aXJlKGZvcmVjYXN0KSkge2xpYnJhcnkoZm9yZWNhc3QpfSAKCmlmICghcmVxdWlyZShsdWJyaWRhdGUpKSB7bGlicmFyeShsdWJyaWRhdGUpfSAKCmlmICghcmVxdWlyZSgic2NhbGVzIikpIHsKaW5zdGFsbC5wYWNrYWdlcygic2NhbGVzIikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCmxpYnJhcnkoInNjYWxlcyIpIAp9Cgprbml0cjo6b3B0c19jaHVuayRzZXQoCgllY2hvID0gVFJVRSwKCW1lc3NhZ2UgPSBGQUxTRSwKCXdhcm5pbmcgPSBGQUxTRSwKCWNvbW1lbnQgPSBOQSwKCXJlc3VsdHMgPSBUUlVFLAoJZmlnLmFsaWduID0gImNlbnRlciIKKQpgYGAKCmBgYHtyfQojIHJlYWQgaW4gZGF0YQpkYXRhID0gcmJpbmQuZGF0YS5mcmFtZSg1LjIsICA3LjgsICA5LjEsIDExLjMsIDEyLjUsIDEzLjAsIDE0LjIsIDE1LjEsIDE1LjksIDE2LjcsIDE3LjIsIDE3LjgsIDE4LjQsIDE4LjksIAogIDE5LjMsIDE5LjcsIDIwLjIsIDIwLjYsIDIxLjAsIDIxLjUsIDIxLjksIDIyLjMsIDIyLjcsIDIzLjEsIDIzLjUsIDIzLjksIDI0LjMsIDI0LjcsIAogIDI1LjEsIDI1LjUsIDI1LjksIDI2LjMsIDI2LjcsIDI3LjEsIDI3LjUsIDI3LjksIDI4LjMsIDI4LjcsIDI5LjEsIDI5LjUsIDI5LjksIDMwLjMsIAogIDMwLjcsIDMxLjEsIDMxLjUsIDMxLjksIDMyLjMsIDMyLjcsIDMzLjEsIDMzLjUsIDMzLjksIDM0LjMsIDM0LjcsIDM1LjEsIDM1LjUsIDM1LjksIAogIDM2LjMsIDM2LjcsIDM3LjEsIDM3LjUsIDM3LjksIDM4LjMsIDM4LjcsIDM5LjEsIDM5LjUsIDM5LjksIDQwLjMsIDQwLjcsIDQxLjEsIDQxLjUsCiAgNDEuOSwgNDIuMywgNDIuNywgNDMuMSwgNDMuNSkKY29sbmFtZXMoZGF0YSkgPSAidGltZSIKICAjIHRpbWUgaXMgaW4gbW9udGhzCmBgYAoKIyBJbnRybyBhbmQgU2V0dXAKClRoZSBkYXRhc2V0IGF0IG91ciBkaXNwb3NhbCBmb3IgdGhpcyBhbmFseWlzIGlzIG1hZGUgdXAgb2YgYHIgbnJvdyhkYXRhKWAgcmVjb3JkZWQgZmFpbHVyZSB0aW1lcyAobWVhc3VyZWQgaW4gbW9udGhzKSBmb3Igd2luZCB0dXJiaW5lIGdlYXJib3ggY29tcG9uZW50cy4gU3VtbWFyeSBzdGF0aXN0aWNzIGFzIHdlbGwgYXMgYSBoaXN0b2dyYW0gZGVwaWN0aW9uIG9mIG91ciBzYW1wbGUgZGF0YSBjYW4gYmUgc2VlbiBiZWxvdy4KCmBgYHtyfQpzdW1fc3RhdHNfdGFibGUgPSBmdW5jdGlvbih2YXJpYWJsZSl7CiAgdGFibGUgPSBjYmluZCgKICAgIHJvdW5kKG1pbih2YXJpYWJsZSksMiksCiAgICByb3VuZChxdWFudGlsZSh2YXJpYWJsZSwgMC4yNSksMiksCiAgICByb3VuZChtZWRpYW4odmFyaWFibGUpLDIpLAogICAgcm91bmQobWVhbih2YXJpYWJsZSksMiksCiAgICByb3VuZChxdWFudGlsZSh2YXJpYWJsZSwgMC43NSksMiksCiAgICByb3VuZChtYXgodmFyaWFibGUpLDIpCiAgKQogIGNvbG5hbWVzKHRhYmxlKSA9IGMoIk1pbiIsICJRMSIsICJNZWQiLCAiTWVhbiIsICJRMyIsICJNYXgiKQogIHJvd25hbWVzKHRhYmxlKSA9IE5VTEwKICByZXR1cm4odGFibGUpCn0KClN1bW1hcnlfVGFibGUgPSBzdW1fc3RhdHNfdGFibGUodmFyaWFibGUgPSBkYXRhJHRpbWUpCmthYmxlKFN1bW1hcnlfVGFibGUsYWxpZ24gPSAiYyIsCiAgICAgIGNhcHRpb24gPSAiPHNwYW4gc3R5bGU9J2NvbG9yOiMjMDAwMDAwOyc+CiAgICAgIFN1bW1hcnkgU3RhdHMgb2YgU3Vydml2YWwgVGltZXMgKE1vbnRocyk8L3NwYW4+IikgJT4lCiAga2FibGVfc3R5bGluZygKICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIpLAogICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgcG9zaXRpb24gPSAiY2VudGVyIikKCmdncGxvdChkYXRhID0gZGF0YSkgKwogIGdlb21faGlzdG9ncmFtKG1hcHBpbmcgPSBhZXMoeCA9IHRpbWUsIHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgICMgYXJndW1lbnQgY29sb3IgaW4gZ2VvbV9oaXN0b2dyYW0gaXMgZm9yIGNvbG9yIG9mIGJpbiBsaW5lcwogICAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRibHVlIiwKICAgICAgICAgICAgICAgICBiaW5zID0gMTAsKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgU3Vydml2YWwgVGltZXMiLAogICAgICAgeCA9ICJUaW1lIChNb250aHMpIiwKICAgICAgIHkgPSAiRGVuc2l0eSIpICsgCiAgdGhlbWUoCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEsIGxpbmV3aWR0aCA9IDMpCiAgKSAjIHRoaXMgaXMgdGhlIGVxdWl2YWxlbnQgb2YgYm94KGx3ZCA9IDMpIGluIGJhc2UgUgpgYGAKCgpUaGUgZW5naW5lZXJpbmcgdGVhbSBhdCBhIHdpbmQgZW5lcmd5IGNvbXBhbnkgaXMgdW5zdXJlIHdoZXRoZXIgdG8gbGFiZWwgYW5kIHRyZWF0IHRoZSBicm9hZGVyIHBvcHVsYXRpb24gZGlzdHJpYnV0aW9uIG9mIGZhaWwgdGltZXMgYXMgZXhwb25lbnRpYWxseSBvciBXZWlidWxsIGRpc3RyaWJ1dGVkLiBUaGUgcHJvYmFiaWxpdHkgZGVuc2l0eSBvZiBhbiBleHBvbmVudGlhbCBkaXN0cmlidXRpb24gaXMgc2ltcGx5IGEgbW9yZSBzaW1wbGlmaWVkIHZlcnNpb24gb2YgdGhlIFdlaWJ1bGwncy4gSXQgaXMgdGhlIHZhbHVlIG9mIG91ciBzaGFwZSBwYXJhbWV0ZXIsICRcYmV0YSQsIHRoYXQgZGV0ZXJtaW5lcyB3aGljaCBvZiB0aGVzZSBkaXN0cmlidXRpb24ncyB3ZSB3aWxsIGxhYmVsIGFzIHRoZSBmcmFtZXdvcmsgZm9yIHByZWRpY3RpdmUgYW5hbHlzaXMgb24gZ2VhcmJveCBmYWlsIHRpbWVzIG1vdmluZyBmb3J3YXJkLgoKRm9yIHRoZSBwdXJwb3NlcyBvZiB0b2RheSdzIGFuYWx5c2lzLCB3ZSB3aWxsIHRyZWF0IHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCBzYWlkIHBvcHVsYXRpb24gaXMgZXhwb25lbnRpYWxseSBkaXN0cmlidXRlZCAoQUtBICRcYmV0YSA9IDEkKSwgYW5kIHRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIHRoYXQgYSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBtb3JlIGFjY3VyYXRlbHkgcmVwcmVzZW50cyB0aGUgYnJvYWRlciBwb3B1bGF0aW9uIG9mIGdlYXJib3ggZmFpbCB0aW1lcyAoQUtBICRcYmV0YSBcbmVxIDEkKS4KCgpcYmVnaW57YWxpZ259CkhfMCY6IFxiZXRhID0gMSBccXVhZCBcdGV4dHtUYWtlYXdheTogRXhwb25lbnRpYWx9IFxcCkhfYSY6IFxiZXRhIFxuZXEgMSBccXVhZCBcdGV4dHtUYWtlYXdheTogV2VpYnVsbH0KXGVuZHthbGlnbn0KCkluIG9yZGVyIHRvIGFzc2VzcyB0aGUgdmFsaWRpdHkgb2YgdGhlc2Ugb3Bwb3NpbmcgaHlwb3RoZXNlcywgd2UgbXVzdCBmaXJzdCBxdWFudGlmeSBhbiBlc3RpbWF0ZSBmb3Igb3VyIHBhcmFtZXRlciAkXGJldGEkIHVuZGVyIHRoZSBhc3N1bXB0aW9uIG9mIGVhY2ggc2NlbmFyaW8gKFdlaWJ1bGwgZGlzdHJpYnV0aW9uIHZzIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbikuIEluIHRoZSBmb2xsb3dpbmcgc2VjdGlvbnMsIEkgd2lsbCB1c2UgbWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRpb24gKE1MRSkgdG8gZG8gc28uCgoKIyBhLikgTUxFIG9mIFdlaWJ1bGwKT3BlcmF0aW5nIHVuZGVyIHRoZSBhc3N1bXB0aW9uIHRoYXQgdGhlIHBvcHVsYXRpb24gb2YgZ2VhcmJveCBmYWlsIHRpbWVzIGlzICoqV2VpYnVsbCBkaXN0cmlidXRlZCoqLCB3ZSBjYW4gdXNlIE1MRSB0byBzaW11bHRhbmVvdXNseSBnZW5lcmF0ZSBlc3RpbWF0ZXMgZm9yIHRoZSBzaGFwZSBwYXJhbWV0ZXIsICRcYmV0YSQsIGFuZCB0aGUgdGhlIHNjYWxlIHBhcmFtZXRlciwgJFxsYW1iZGEkLiBXZSdsbCBkZW5vdGUgdGhlc2UgZXN0aW1hdGVzIGFzICRcaGF0e1xiZXRhfSQgYW5kICRcaGF0e1xsYW1iZGF9JCByZXNwZWN0aXZlbHkuCgpQYXJhbWV0ZXIgY2FsY3VsYXRpb25zIHdlcmUgcGVyZm9ybWVkIHdpdGggUidzIGJ1aWx0LWluIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+b3B0aW0oKTwvc3Bhbj4gZnVuY3Rpb24uIEZvciBtYXRoZW1hdGljYWwgcmVmZXJlbmNlLCB0aGUgbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb24gZm9yIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBhcyB3ZWxsIGFzIHRoZSBwYXJ0aWFsIGRlcml2YXRpdmVzIG9mIHRoYXQgdmVyeSBmdW5jdGlvbiB3aXRoIHJlc3BlY3QgdG8gYm90aCAkXGJldGEkIGFuZCAkXGxhbWJkYSQgYXJlIGJlbG93LgoKJCRcTGFyZ2UgXGVsbChcYmV0YSxcbGFtYmRhfHQpID0KW24gXHRpbWVzIFxsbihcYmV0YSldIC0gCltuIFx0aW1lcyBcYmV0YSBcdGltZXMgXGxuKFxsYW1iZGEpXQorIFsoXGJldGEgLSAxKSBcdGltZXMgXHN1bVxsbih0X2kpXQotIFxzdW1cbGVmdChcZnJhY3sodF9pKX17XGxhbWJkYX1ccmlnaHQpXlxiZXRhICQkCgo8YnI+CgokJFxMYXJnZSBcZnJhY3tccGFydGlhbCBmfXtccGFydGlhbCBcYmV0YX0gPQpcZnJhY3tufXtcYmV0YX0gLQpuIFx0aW1lcyBcbG4oXGxhbWJkYSkKKyBcc3VtXGxuKHRfaSkgLQpcc3VtXGxlZnQoXGxuXGZyYWN7dF9pfXtcbGFtYmRhfVxyaWdodCkgXHRpbWVzIFxsZWZ0KFxmcmFje3RfaX17XGxhbWJkYX1ccmlnaHQpXlxiZXRhICAgICQkCgo8YnI+CgokJFxMYXJnZSBcZnJhY3tccGFydGlhbCBmfXtccGFydGlhbCBcbGFtYmRhfSA9ICBcZnJhY3tcYmV0YX17XGxhbWJkYX0gXHRpbWVzIFxzdW1cbGVmdChcZnJhY3t0X2l9e1xsYW1iZGF9XHJpZ2h0KV5cYmV0YSAtIG4gICAgJCQKPGJyPgoKYGBge3J9CiMjIE1MRSBXZWlidWxsIEVzdGltYXRpb24KICAjIGNvZGUgaXMgbGFyZ2VseSBjb3BpZWQgZnJvbSBIVyA5IGFzc2lnbm1lbnQsIHdoaWNoIHRvb2sgZm9ybXVsYXMgYW5kIHByb2NlZHVyZSBmcm9tIGZvbGxvd2luZzoKICAgICMgV2VlayAxMSwgU2VjdGlvbiA1LjIgCiAgICAjIFdlZWsgNywgU2VjdGlvbiA1CgojIyMjIGRlZmluZSBsaWtlbGlob29kIGZ1bmN0aW9uCiMjICpuZWdhdGl2ZSogbG9nIGxpa2VsaWhvb2QgZnVuY3Rpb24gZm9yIFdlaWJ1bGwgZGlzdHJpYnV0aW9uCiAgIyBieSBuZWdhdGl2ZSBsb2cgbGlrZWxpaG9vZCwgdGhpcyBmdW5jdGlvbi4uLi4KbG9nX2xpa2VsaWhvb2QgPSBmdW5jdGlvbihwYXJhbXMsIGRhdGEpIHsKICBiZXRhID0gcGFyYW1zWzFdICAjIHNoYXBlCiAgbGFtYmRhID0gcGFyYW1zWzJdICAjIHNjYWxlIAogIAogICMgRW5zdXJlIHBhcmFtZXRlcnMgYXJlIHBvc2l0aXZlCiAgaWYgKGJldGEgPD0gMCB8fCBsYW1iZGEgPD0gMCkgewogICAgcmV0dXJuKDFlMTApICAjIFJldHVybiBsYXJnZSB2YWx1ZSBmb3IgaW52YWxpZCBwYXJhbWV0ZXJzCiAgfQogIAogIG4gPSBsZW5ndGgoZGF0YSkKICBsb2dfbGlrID0gbiAqIGxvZyhiZXRhKSAtIG4gKiBiZXRhICogbG9nKGxhbWJkYSkgKyAKICAgIChiZXRhIC0gMSkgKiBzdW0obG9nKGRhdGEpKSAtIHN1bSgoZGF0YSAvIGxhbWJkYSleYmV0YSkKICAKICByZXR1cm4obG9nX2xpaykgICMgUmV0dXJuIGxvZy1saWtlbGlob29kISBOT1QgdGhlIG5lZ2F0aXZlIGxvZy1saWtlbGlob29kCn0KCiMjIyMgZGVmaW5lIHNjb3JlIGVxdWF0aW9ucyAocGFydGlhbCBkZXJpdmF0aXZlcykKbG9nX2xpa2VsaWhvb2RfZ3JhZGllbnQgPSBmdW5jdGlvbihwYXJhbXMsIGRhdGEpIHsKICBiZXRhID0gcGFyYW1zWzFdICAgICAgICMgc2hhcGUgcGFyYW1ldGVyCiAgbGFtYmRhID0gcGFyYW1zWzJdICAjIHNjYWxlIHBhcmFtZXRlcgogIAogIG4gPSBsZW5ndGgoZGF0YSkKICAKICBwYXJ0aWFsX2Rlcml2X2JldGEgPSBuL2JldGEgLSBuICogbG9nKGxhbWJkYSkgKyBzdW0obG9nKGRhdGEpKSAtIAogICAgICAgIHN1bShsb2coZGF0YS9sYW1iZGEpICogKGRhdGEvbGFtYmRhKV5iZXRhKQogIAogIHBhcnRpYWxfZGVyaXZfbGFtYmRhID0gIChiZXRhL2xhbWJkYSkqKHN1bSgoZGF0YS9sYW1iZGEpXmJldGEpIC1uKQogIAogIHJldHVybihjKHBhcnRpYWxfZGVyaXZfYmV0YSwKICAgICAgICAgICBwYXJ0aWFsX2Rlcml2X2xhbWJkYSkpICAjIEdyYWRpZW50IG9mIGxvZy1saWtlbGlob29kLCBOT1QgdGhlIG5lZ2F0aXZlIHNjb3Jlcwp9CgojIyMjIHVzZSBsb2cgbGlrZWxpaG9vZCBhbmQgc2NvcmUgZXF1YXRpb25zIGluIG9wdGltIGZ1bmN0aW9uCgojIG5lZWQgdG8gaGF2ZSBnb29kIGluaXRpYWwgZ3Vlc3NlcyBmb3IgYmV0YSBhbmQgbGFtYmRhIGZvciB0aGUgb3B0aW0gZnVuY3Rpb24KYmV0YV9ndWVzcyA9IChzZChkYXRhJHRpbWUpL21lYW4oZGF0YSR0aW1lKSleKC0xLjA4NikKCmxhbWJkYV9ndWVzcyA9IG1lYW4oZGF0YSR0aW1lKS9nYW1tYSgxICsgMS9iZXRhX2d1ZXNzKQoKCndlaWJfbWxlX2VzdGltYXRlcyA9IG9wdGltKAogIHBhciA9IGMoYmV0YV9ndWVzcywgbGFtYmRhX2d1ZXNzKSwgIyBwYXIgYXJndW1lbnQgaXMgaW5pdGlhbCAiZ3Vlc3NlcyIKICBkYXRhID0gZGF0YSR0aW1lLAogIGZuID0gbG9nX2xpa2VsaWhvb2QsCiAgZ3IgPSBsb2dfbGlrZWxpaG9vZF9ncmFkaWVudCwKICBtZXRob2QgPSAiTC1CRkdTLUIiLAogIGhlc3NpYW4gPSBUUlVFLAogICAgIyB3aWxsIHVzZSB0aGUgSGVzc2lhbiBtYXRyaXggbGF0ZXIgb24KICBjb250cm9sID0gbGlzdChtYXhpdCA9IDEwMDAsIAogICAgICAgICAgICAgICAgIGZuc2NhbGUgID0gLTEsCiAgICAgICAgICAgICAgICAgdHJhY2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICBhYnN0b2wgPSAxZS04KQopCiN3ZWliX21sZV9lc3RpbWF0ZXMKICAKd2VpYl9tbGVfYmV0YSA9IHdlaWJfbWxlX2VzdGltYXRlcyRwYXJbMV0gIyBzaGFwZQp3ZWliX21sZV9sYW1iZGEgPSB3ZWliX21sZV9lc3RpbWF0ZXMkcGFyWzJdICMgc2NhbGUKYGBgCgpQb3N0LU1MRSwgd2UgaGF2ZSBlc3RpbWF0ZXMgb2YgYWJvdXQgYHIgcm91bmQod2VpYl9tbGVfYmV0YSwzKWAgYW5kIGByIHJvdW5kKHdlaWJfbWxlX2xhbWJkYSwzKWAgZm9yICRcYmV0YSQgYW5kICRcbGFtYmRhJCByZXNwZWN0aXZlbHkuIFRvIGZ1cnRoZXIgZW5zdXJlIHRoZXNlIGVzdGltYXRlcyBzZWVtIHJlYXNvbmFibGUsIGJlbG93IEkgb3ZlcmxhaWQgYSBXZWlidWxsIGRpc3RyaWJ1dGlvbiB3aXRoIHNhaWQgcGFyYW1ldGVyIHZhbHVlcyBhdG9wIG91ciBhdmFpbGFibGUgc2FtcGxlIGRhdGEuCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBkYXRhKSArCiAgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyh4ID0gdGltZSwgeSA9IGFmdGVyX3N0YXQoZGVuc2l0eSkpLAogICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgICAgICAgICAgICAgIyBhcmd1bWVudCBjb2xvciBpbiBnZW9tX2hpc3RvZ3JhbSBpcyBmb3IgY29sb3Igb2YgYmluIGxpbmVzCiAgICAgICAgICAgICAgICAgZmlsbCA9ICJsaWdodGJsdWUiLAogICAgICAgICAgICAgICAgIGJpbnMgPSAxMCwpICsKICAjIHVzZSBzdGF0X2Z1bmN0aW9uIGluIGdncGxvdCB0byBzaG93IGRlbnNpdHkgY3VydmVzIG9mIG90aGVyIGRpc3RyaWJ1dGlvbnMKICAgIHN0YXRfZnVuY3Rpb24oZnVuID0gZHdlaWJ1bGwsIAogICAgICAgICAgICAgICAgYXJncyA9IGxpc3Qoc2hhcGUgPSB3ZWliX21sZV9iZXRhLCBzY2FsZSA9IHdlaWJfbWxlX2xhbWJkYSksCiAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICBsaW5ld2lkdGggPSAxLjUsCiAgICAgICAgICAgICAgICB4bGltID0gcmFuZ2UoMDo1MCkpKwogICAgICAgICAgICAjIHhsaW0gYXJndW1lbnQgc28gY3VydmUgZG9lc24ndCBhd2thcmRseSBjdXQgb3V0IGF0IGVkZ2UgcG9pbnRzIG9mIGRhdGEKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBHZWFyYm94IFN1cnZpdmFsIFRpbWVzIChXZWlidWxsKSIsCiAgICAgICB4ID0gIlRpbWUgKE1vbnRocykiLAogICAgICAgeSA9ICJEZW5zaXR5IikgKyAKICB0aGVtZSgKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSwgbGluZXdpZHRoID0gMyksCiAgICBsZWdlbmQucG9zaXRpb24gPSBjKDAuODUsIDAuODUpCiAgKQpgYGAKCkFzIHdlIGNhbiBzZWUgaW4gb3VyIGhpc3RvZ3JhbSBhYm92ZSwgdGhlcmUgaXMgY2VydGFpbmx5IGEgcmVzcGVjdGFibGUgYW1vdW50IG9mIG92ZXJsYXAgYmV0d2VlbiB0aGUgZGlzdHJpYnV0aW9ucyBvZiBvdXIgc2FtcGxlIGRhdGEgYW5kIGEgdGhlb3JldGljYWwgV2VpYnVsbCBkZW5zaXR5IGN1cnZlIHdpdGggcGFyYW1ldGVycyBvZiAkXGJldGEgXGFwcHJveCBgciByb3VuZCh3ZWliX21sZV9iZXRhLDMpYCQgYW5kICRcbGFtYmRhIFxhcHByb3ggYHIgcm91bmQod2VpYl9tbGVfbGFtYmRhLDMpYCQuIFRoaXMgbGVhZHMgdXMgdG8gYmVsaWV2ZSB0aGF0ICppZiogd2UgYXJlIHRvIGxhYmVsIHRoZSBicm9hZGVyIHBvcHVsYXRpb24gb2YgZ2VhcmJveCBzdXJ2aXZhbCB0aW1lcyBhcyBXZWlidWxsIGRpc3RyaWJ1dGVkLCB0aGVuIHRoZSAkXGJldGEkIGFuZCAkXGxhbWJkYSQgZXN0aW1hdGVzIHByZXNjcmliZWQgdmlhIE1MRSBhcmUgcXVhbGl0eSBzdGFydGluZyBwb3B1bGF0aW9uIGVzdGltYXRvcnMuCgpOb3cgZm9yIGNvbXBhcmlzb24ncyBzYWtlLCBJIHdpbGwgcmVwZWF0IHRoZSBNTEUgYW5kIHZpc3VhbGl6YXRpb24gcHJvY2VkdXJlLCBidXQgdGhpcyB0aW1lIG9wZXJhdGluZyB1bmRlciB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSBnZWFyYm94IHN1cnZpdmFsIHRpbWVzIGFyZSBnZW5lcmFsbHkgKipleHBvbmVudGlhbGx5KiogZGlzdHJpYnV0ZWQuCgojIGIuKSBNTEUgb2YgRXhwb25lbnRpYWwKQXMgYWxsdWRlZCB0byBiZWZvcmUsIHRoZSBleHBvbmVudGlhbCBkaXN0cmlidXRpb24gY2FuIGJlIHNpbXBsaXN0aWNhbGx5IGRlc2NyaWJlZCBhcyBhIGxlc3MgY29tcGxpY2F0ZWQgInZlcnNpb24iIG9mIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbi4gSW5zdGVhZCBvZiBlbXBsb3lpbmcgdHdvIGFjdGl2ZSBwYXJhbWV0ZXJzLCB0aGUgZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uJ3Mgb25seSBwYXJhbWV0ZXIgaXMgJFxsYW1iZGEkLCB3aGljaCB3ZSB3aWxsIG5vdyBlc3RpbWF0ZSB2aWEgTUxFLiBMb2ctbGlrZWxpaG9vZCBmdW5jdGlvbnMgYW5kIHBhcnRpYWwgZGVyaXZhdGl2ZXMgYXJlIHdyaXR0ZW4gYmVsb3cuCgokJFxMYXJnZSBcZWxsKFxsYW1iZGF8dCkgPSAtW24gXHRpbWVzIFxsbihcbGFtYmRhKV0gLSBcZnJhY3tcc3VtKHRfaSl9e1xsYW1iZGF9ICAkJAoKPGJyPgoKJCRcTGFyZ2UgXGZyYWN7XHBhcnRpYWwgZn17XHBhcnRpYWwgXGxhbWJkYX0gPSBcZnJhY3tufXtcbGFtYmRhfSArIFxmcmFje1xzdW0odF9pKX17XGxhbWJkYV4yfSAgICQkCgo8YnI+CmBgYHtyfQojIyBFeHBvbmVudGlhbCBNTEUgRGlzdHJpYnV0aW9uCiAgIyBvbmNlIGFnYWluIGNvZGUgbGFyZ2VseSBicm91Z2h0IG92ZXIgZnJvbSBIVyA5IGFzc2lnbm1lbnQKCiMgZXhwb25lbnRpYWwgbG9nIGxpa2VsaWhvb2QgZm9sbG93cyBzYW1lIHBhdHRlcm4gYXMgV2VpYnVsbCBsb2cgbGlrZWxpaG9vZCBidXQgYSBNVUNIIHNpbXBsZXIgZGlzdHJpYnV0aW9uCmV4cF9sb2dfbGlrZWxpaG9vZCA9IGZ1bmN0aW9uKGxhbWJkYSwgZGF0YSkgewogaWYgKGxhbWJkYSA8PSAwKSByZXR1cm4gKDFlMTApCiBuID0gbGVuZ3RoKGRhdGEpCiBsb2dfbGlrID0gLW4gKiBsb2cobGFtYmRhKSAtIHN1bShkYXRhKS9sYW1iZGEKIHJldHVybihsb2dfbGlrKQp9CgojIyMgbm93IGRlZmluZSBwYXJ0aWFsIGRlcml2YXRpdmUgdy8gcmVzcGVjdCB0byBsYW1iZGEgKHRoZSBzY29yZSBmdW5jdGlvbiBvciBncmFkaWVudCkKICAjIHBlcmZvcm1lZCB2aWEgcXVpY2sgaGFuZCBjYWxjdWxhdGlvbgoKZXhwX2dyYWRpZW50ID0gZnVuY3Rpb24obGFtYmRhLCBkYXRhKSB7CiAgaWYgKGxhbWJkYSA8PSAwKSByZXR1cm4gKE5BKQogIG4gPSBsZW5ndGgoZGF0YSkKICBwYXJ0aWFsX2Rlcml2X2xhbWJkYSA9IChuL2xhbWJkYSkgKyAoc3VtKGRhdGEpLyhsYW1iZGFeMikpCiAgcmV0dXJuKHBhcnRpYWxfZGVyaXZfbGFtYmRhKQp9CgpleHBfbWxlX2VzdGltYXRlcyA9IG9wdGltKAogIHBhciA9IDEvbWVhbihkYXRhJHRpbWUpLAogICAgIyB0aGUgaW5pdGlhbCBndWVzcyBjYW4gc2ltcGx5IGJlIDEvKG1lYW4gb2YgdGhlIGRhdGEpIHNpbmNlIHdlIGFyZSBwZXJmb3JtaW5nIHRoaXMgYW5hbHlzaXMgdW5kZXIgdGhlIHRoZW9yZXRpY2FsIHRoYXQgaXQgaXMgYW4gRVhQT05FTlRJQUwgZGlzdHJpYnV0aW9uLiBUaGUgbWVhbiBvZiBhbiBleHBvbmVudGlhbCBkaXN0cmlidXRpb24gaXMgMSBkaXZpZGVkIGJ5IHRoZSB0aGUgcmF0ZSBwYXJhbWV0ZXIgbGFtYmRhCiAgZGF0YSA9IGRhdGEkdGltZSwKICBmbiA9IGV4cF9sb2dfbGlrZWxpaG9vZCwKICBnciA9IGV4cF9ncmFkaWVudCwKICBtZXRob2QgPSAiTC1CRkdTLUIiLAogIGhlc3NpYW4gPSBUUlVFLAogICAgIyB3aWxsIHVzZSB0aGUgSGVzc2lhbiBtYXRyaXggbGF0ZXIgb24KICBjb250cm9sID0gbGlzdChtYXhpdCA9IDEwMDAsIAogICAgICAgICAgICAgICAgIGZuc2NhbGUgID0gLTEsCiAgICAgICAgICAgICAgICAgdHJhY2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICBhYnN0b2wgPSAxZS04KQopCiAgCiNleHBfbWxlX2VzdGltYXRlcyRwYXIKCmV4cF9tbGVfbGFtYmRhID0gZXhwX21sZV9lc3RpbWF0ZXMkcGFyCmBgYAoKUGVyIE1MRSBjYWxjdWxhdGlvbnMsIHdlIGNhbiBhc3NlcnQgdGhhdCB0aGUgJFxsYW1iZGEkIHBhcmFtZXRlciBvZiB0aGUgZGlzdHJpYnV0aW9uIG9mIGdlYXJib3ggc3Vydml2YWwgdGltZXMsIGlmIHNhaWQgZGlzdHJpYnV0aW9uIHdhcyB0cnVseSBleHBvbmVudGlhbCwgaXMgZXN0aW1hdGVkIHRvIGJlIHJvdWdobHkgYHIgcm91bmQoZXhwX21sZV9sYW1iZGEsMylgLiBBbiA8c3BhbiBzdHlsZT0iY29sb3I6cmVkOyI+ZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uPC9zcGFuPiB3aXRoICRcbGFtYmRhID0gYHIgcm91bmQoZXhwX21sZV9sYW1iZGEsMylgJCBpcyBvdmVybGFpZCBhdG9wIHRoZSBzYW1wbGUgZGF0YSBhbmQgYXZhaWxhYmxlIGJlbG93LgoKYGBge3J9CmdncGxvdChkYXRhID0gZGF0YSkgKwogIGdlb21faGlzdG9ncmFtKG1hcHBpbmcgPSBhZXMoeCA9IHRpbWUsIHkgPSBhZnRlcl9zdGF0KGRlbnNpdHkpKSwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsCiAgICAgICAgICAgICAgICAgICMgYXJndW1lbnQgY29sb3IgaW4gZ2VvbV9oaXN0b2dyYW0gaXMgZm9yIGNvbG9yIG9mIGJpbiBsaW5lcwogICAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRibHVlIiwKICAgICAgICAgICAgICAgICBiaW5zID0gMTAsKSArCiAgIyB1c2Ugc3RhdF9mdW5jdGlvbiBpbiBnZ3Bsb3QgdG8gc2hvdyBkZW5zaXR5IGN1cnZlcyBvZiBvdGhlciBkaXN0cmlidXRpb25zCiAgICBzdGF0X2Z1bmN0aW9uKGZ1biA9IGRleHAsIAogICAgICAgICAgICAgICAgYXJncyA9IGxpc3QocmF0ZSA9IDEvZXhwX21sZV9sYW1iZGEpLAogICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwKICAgICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEuNSwKICAgICAgICAgICAgICAgIHhsaW0gPSByYW5nZSgwOjUwKQogICAgICAgICAgICAgICAgKSsKICAgICAgICAgICAgIyB4bGltIGFyZ3VtZW50IHNvIGN1cnZlIGRvZXNuJ3QgYXdrYXJkbHkgY3V0IG91dCBhdCBlZGdlIHBvaW50cyBvZiBkYXRhCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgU3Vydml2YWwgVGltZXMgKEV4cCkiLAogICAgICAgeCA9ICJUaW1lIChNb250aHMpIiwKICAgICAgIHkgPSAiRGVuc2l0eSIpICsgCiAgdGhlbWUoCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiYmxhY2siLCBmaWxsID0gTkEsIGxpbmV3aWR0aCA9IDMpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjg1LCAwLjg1KQogICkKCmBgYAoKQ29tcGFyaW5nIHRoaXMgaGlzdG9ncmFtIHRvIHRoZSBvbmUgZnJvbSBwYXJ0IGEsIHdlIHNlZSBhIGRyYXN0aWMgZGVjbGluZSBpbiBkaXN0cmlidXRpb24gcmVzZW1ibGFuY2UgYmV0d2VlbiB0aGUgc2FtcGxlIGRhdGEgYW5kIHRoZSB0aGVvcmV0aWNhbCBkZW5zaXR5IGN1cnZlLCB3aGVuIHdvcmtpbmcgdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgcG9wdWxhdGlvbiBvZiBnZWFyYm94IHN1cnZpdmFsIHRpbWVzIGlzIGV4cG9uZW50aWFsbHkgZGlzdHJpYnV0ZWQuIFdlIHdpbGwga2VlcCB0aGlzIGluIG1pbmQgbW92aW5nIGZvcndhcmQsIGFzIHdlIHJ1biBoeXBvdGhlc2lzIHRlc3RzIHRvIHF1YW50aWZ5IHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSB0d28gZGlzdHJpYnV0aW9uIGFzc3VtcHRpb25zLgoKIyBjLikgTGlrZWxpaG9vZCBSYXRpbyBUZXN0CgpUbyBmdXJ0aGVyIGludmVzdGlnYXRlIHRoZSBkaWZmZXJlbmNlIGluIGVhY2ggZGlzdHJpYnV0aW9uJ3MgZml0IHdpdGggcmVnYXJkcyB0byBvdXIgcG9wdWxhdGlvbiBvZiBpbnRlcmVzdCAoZ2VhcmJveCBzdXJ2aXZhbCB0aW1lcyksIHdlIHdpbGwgcGVyZm9ybSBhIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCAoTFJUKS4gVGhlIExSVCB0YWtlcyBpbnRvIGFjY291bnQgdGhlIGxvZy1saWtlbGlob29kIGZ1bmN0aW9uIGV2YWx1YXRlZCB3aXRoIHBhcmFtZXRlciB2YWx1ZXMgZXN0aW1hdGVkIGZyb20gYSBzaW1wbGVyIG1vZGVsICh0aGUgZXhwb25lbnRpYWwgaW4gdGhpcyBjYXNlKSBhbmQgdGhlIGxvZy1saWtlbGlob29kIGZ1bmN0aW9uIGV2YWx1YXRlZCB3aXRoIHBhcmFtZXRlciB2YWx1ZXMgZXN0aW1hdGVkIGZyb20gYSBtb3JlIGNvbXBsaWNhdGVkIG1vZGVsICh0aGUgV2VpYnVsbCBpbiB0aGlzIHNjZW5hcmlvKS4gVGhlIG51bGwgaHlwb3RoZXNpcyBvZiBzdWNoIGEgdGVzdCBpcyB0aGF0LCBwZXIgb3VyIHNhbXBsZSBkYXRhLCB0aGVyZSBpcyAqKm5vKiogc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28gbW9kZWwgZml0cy4KCmBgYHtyfQojIHdlaWJfbWxlX2JldGEgYW5kIHdlaWJfbWxlX2xhbWJkYSBhcmUgVU5SRVNUUklDVEVEIE1MRSBWQUxVRVMsIGJ1dCBub3cgd2UgbXVzdCBmaW5kCgojIG51bGwgaHlwb3RoZXNpcyBpcyB0aGF0IGJldGEgPSAxCiMgaWYgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUsIHRoZW4gZGlzdHJpYnV0aW9uIGlzIHJlYWxseSBqdXN0IGV4cG9uZW50aWFsCgojIyB0aGUgbGlrZWxpaG9vZCByYXRpbyB0ZXN0IGlzIGp1c3QgMiAqIAogICMgW2xvZyBsaWtlbGlob29kIGV2YWx1YXRlZCBpbiB1bnJlc3RyaWN0ZWQgd2F5XSAtCiAgIyBbbG9nIGxpa2VsaWhvb2QgZXZhbHVhdGVkIGluIHJlc3RyaWN0ZWQgb3Igc2ltcGxlIHdheV0KCiMgbmVlZCB0byBldmFsdWF0ZSBlYWNoIGRpc3RyaWJ1dGlvbidzIGxpa2VsaWhvb2QgZnVuY3Rpb24gYXQgdGhlIHByZXZpb3VzbHkgZXN0aW1hdGVkIHBhcmFtZXRlcnMgb2YgYmV0YSBhbmQvb3IgbGFtYmRhCmxvZ19ldmFsdWF0aW9uX3dlaWIgPSBsb2dfbGlrZWxpaG9vZChwYXJhbXMgPSBjKHdlaWJfbWxlX2JldGEsIHdlaWJfbWxlX2xhbWJkYSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSkKbG9nX2V2YWx1YXRpb25fZXhwID0gZXhwX2xvZ19saWtlbGlob29kKGxhbWJkYSA9IGV4cF9tbGVfbGFtYmRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEpCgojIHRlc3Qgc3RhdCBmb3IgbGlrZWxpaG9vZCByYXRpbyB0ZXN0IGlzIHVwcGVyY2FzZSBMYW1iZGEKCkxhbWJkYSA9IDIgKiBhYnMobG9nX2V2YWx1YXRpb25fd2VpYiAtIGxvZ19ldmFsdWF0aW9uX2V4cCkKCnBfdmFsdWVfbGlrZWxpaG9vZHJhdGlvID0gMSAtIHBjaGlzcShMYW1iZGEsIGRmID0gMSkKICAjIHRlc3Qgc3RhdCBkaXN0cmlidXRpb24gZm9yIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCBpcyBjaGktc3F1YXJlIGRpc3RyaWJ1dGVkCiAgIyBkZiA9IG51bWJlciBvZiBwYXJhbWV0ZXJzIHdlIGFyZSBlc3RpbWF0aW5nIGluIGZ1bmN0aW9uCmBgYAoKT3VyIExSVCByZXR1cm5lZCBhbiBleHRyZW1lbHkgaGlnaCB0ZXN0IHZhbHVlICgkXExhbWJkYSQpIG9mIGFib3V0IGByIHJvdW5kKExhbWJkYSwzKWAuIENvbnNpZGVyaW5nICRcTGFtYmRhJCBmb2xsb3dzIGEgY2hpLXNxdWFyZSBkaXN0cmlidXRpb24sIHRoaXMgdGVzdCBzdGF0IGNvaW5jaWRlcyB3aXRoIGEgcCB2YWx1ZSBvZiBhcHByb3hpbWF0ZWx5IHplcm8uIFdpdGggdGhlc2UgZmluZGluZ3MsIHdlIG11c3QgKipyZWplY3QqKiB0aGUgbnVsbCBoeXBvdGhlc2lzIGFzIHRoZXJlIGlzIHZlcnkgY29udmluY2luZyBldmlkZW5jZSB0aGF0IHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBtb3JlIGFjY3VyYXRlbHkgcmVwcmVzZW50cyB0aGUgZml0IG9mIG91ciBwb3B1bGF0aW9uIG9mIGludGVyZXN0IHRoYW4gdGhlIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiBkb2VzLiBBZnRlciBleGFtaW5pbmcgdGhlIGhpc3RvZ3JhbXMgaW4gcGFydHMgYSBhbmQgYiwgdGhpcyBmaW5kaW5nIGlzIG5vdCBzdXJwcmlzaW5nLgoKIyBkLikgQm9vdHN0cmFwIExpa2VsaWhvb2QgUmF0aW8gVGVzdCAKTGFzdGx5LCBJIHJlcGVhdGVkIHRoaXMgc2FtZSB0eXBlIG9mIHByb2NlZHVyZSwgbGlrZWxpaG9vZCByYXRpbyB0ZXN0aW5nLCBhbmQgYXBwbGllZCBpdCB0byBhIGJvb3RzdHJhcHBlZCBzY2VuYXJpby4gVW5kZXIgdGhlIGd1aXNlIG9mIHRoZSBib290c3RyYXAgTFJULCB3ZSB0YWtlIHJlcGVhdGVkIHNhbXBsZXMgb2YgYSB0aGVvcmV0aWNhbCBkaXN0cmlidXRpb24sIGluIHRoaXMgY2FzZSBhbiBleHBvbmVudGlhbCBkaXN0cmlidXRpb24gd2l0aCAkXGxhbWJkYSBcYXBwcm94JCBgciByb3VuZChleHBfbWxlX2xhbWJkYSwzKWAuIFRoZW4sIGZvciBlYWNoIHNhbXBsZSwgYSB0ZXN0IHN0YXRpc3RpYyBvZiAkXExhbWJkYSQgaXMgZm91bmQgdXNpbmcgdGhhdCBwYXJ0aWN1bGFyIGJvb3RzdHJhcCBzYW1wbGUncyBsb2ctbGlrZWxpaG9vZCBldmFsdWF0aW9uIGFsb25nIHdpdGggdGhlIGxvZy1saWtlbGlob29kIGV2YWx1YXRpb24gb2Ygb3VyIG9yaWdpbmFsIGFuZCBtb3JlIGNvbXBsZXgvdW5yZXN0cmljdGVkIG1vZGVsICh0aGUgV2VpYnVsbCBpbiB0aGlzIHNjZW5hcmlvKS4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQojIyMgQm9vdHN0cmFwIExpa2VsaWhvb2QgUmF0aW8gVGVzdCAoQkxSVCkgZm9yIHNob3J0CiMgcmVmZXJlbmNlIGNvZGUgc2VjdGlvbiA0LjMgZnJvbSBXZWVrIDEyIG5vdGVzLCBuZWVkIHRvIGNoYW5nZSBmb3JtdWxhcyBzaW5jZSB3ZSBhcmUgYXBwbHlpbmcgdG8gZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uLCBub3Qgbm9ybWFsCgpib290c3RyYXBfbHJ0X3Rlc3QgPSBmdW5jdGlvbihkYXRhLCBiLCByYXRlX251bGwsIG9ic19scl9zdGF0KXsKICAgICMgb2JzX2xyX3N0YXQgd2lsbCA9IExhbWJkYSA9IGxpa2VsaWhvb2QgcmF0aW8gdGVzdCBzdGF0IHRha2VuIGZyb20gb2JzZXJ2ZWQgZGF0YSBjYWxjdWxhdGlvbnMKICBuID0gbGVuZ3RoKGRhdGEpCiAgYm9vdF9scl9zdGF0ID0gbnVtZXJpYyhiKQogICAgCiAgIyBMb2ctbGlrZWxpaG9vZCBmdW5jdGlvbnMgYXJlIGZvdW5kIGluIGVhcmxpZXIgY29kZSBjaHVua3MgYW5kIHdpbGwgYmUgY2FsbGVkIHRvIHdpdGhpbiB0aGUgb3B0aW0gZnVuY3Rpb25zIG9mIHRoZSBmb3IgbG9vcCBwcm9jZXNzCiAgICAKICAjIFNUQVJUIEZPUiBMT09QCiAgICBmb3IgKGkgaW4gMTpiKXsKICAgICAgCiAgICAgICMgR2VuZXJhdGluZyBhcnRpZmljaWFsIGRhdGEgbWVhbnQgdG8gcmVwbGljYXRlIHRoZSBjaGFyYWN0ZXJpc3RpY3Mgb2Ygb3VyIE5VTEwgaHlwb3RoZXNpcwogICAgICAjIEluIHRoaXMgY2FzZSwgb3VyIG51bGwgaHlwb3RoZXNpcyBpcyB0aGF0IHRoZSBkYXRhIGZpdHMgYW4gZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uIHdpdGggcmF0ZSBwYXJhbWV0ZXIgbGFtYmRhCiAgICAgIGJvb3RfZXhwX3NhbXBsZSA9IHJleHAobiA9IG4sIHJhdGUgPSByYXRlX251bGwpIAogIAogICAgICAjIyMjIyMjIFdlaWJ1bGwgbGlrZWxpaG9vZCBwZXIgYm9vdCBzYW1wbGUgICAgCiAgICAgIGJvb3RfYmV0YV9ndWVzcyA9IChzZChib290X2V4cF9zYW1wbGUpL21lYW4oYm9vdF9leHBfc2FtcGxlKSleKC0xLjA4NikKCiAgICAgIGJvb3RfbGFtYmRhX2d1ZXNzID0gbWVhbihib290X2V4cF9zYW1wbGUpL2dhbW1hKDEgKyAxL2Jvb3RfYmV0YV9ndWVzcykKICAgICAgCiAgICAgIGJvb3RfbG9nX3dlaWIgPSBvcHRpbSgKICAgICAgICAgIHBhciA9IGMoYm9vdF9iZXRhX2d1ZXNzLCBib290X2xhbWJkYV9ndWVzcyksICMgcGFyIGFyZ3VtZW50IGlzIGluaXRpYWwgImd1ZXNzZXMiCiAgICAgICAgICBkYXRhID0gYm9vdF9leHBfc2FtcGxlLAogICAgICAgICAgZm4gPSBsb2dfbGlrZWxpaG9vZCwKICAgICAgICAgIGdyID0gbG9nX2xpa2VsaWhvb2RfZ3JhZGllbnQsCiAgICAgICAgICBtZXRob2QgPSAiTC1CRkdTLUIiLAogICAgICAgICAgbG93ZXIgPSBjKDFlLTgsIDFlLTgpLCAjIyB0aGlzIGxpbWl0aW5nIGxvd2VyIGFyZ3VtZW50IGlzIE5FQ0VTU0FSWSwgYmVmb3JlIEkgYWRkZWQgaXQgSSB3YXMgZ2V0dGluZyBhbiBlcnJvciBsaW5lIGZvciAibm9uLWZpbml0ZSB2YWx1ZSBzdXBwbGllZCBieSBvcHRpbSIKICAgICAgICAgIGhlc3NpYW4gPSBUUlVFLAogICAgICAgICAgY29udHJvbCA9IGxpc3QobWF4aXQgPSAxMDAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGZuc2NhbGUgID0gLTEsCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgYWJzdG9sID0gMWUtOCkKICAgICAgICAgICkKICAgICAgYm9vdF9sb2dfd2VpYiA9IGJvb3RfbG9nX3dlaWIkdmFsdWUgIyBzdG9yZSBsb2cgbGlrZWxpaG9vZCBldmFsdWF0aW9uCiAgICAgICMjIyMjIyMgRW5kIFdlaWJ1bGwgbGlrZWxpaG9vZCBwZXIgYm9vdCBzYW1wbGUgCiAgCgogICAgICAjIyMjIyMjIEV4cG9uZW50aWFsIGxpa2VsaWhvb2QgcGVyIGJvb3Qgc2FtcGxlICAgIAogICAgICBib290X2xvZ19leHAgPSBvcHRpbSgKICAgICAgICAgIHBhciA9IDEvbWVhbihib290X2V4cF9zYW1wbGUpLAogICAgICAgICAgZGF0YSA9IGJvb3RfZXhwX3NhbXBsZSwKICAgICAgICAgIGZuID0gZXhwX2xvZ19saWtlbGlob29kLAogICAgICAgICAgZ3IgPSBleHBfZ3JhZGllbnQsCiAgICAgICAgICBtZXRob2QgPSAiTC1CRkdTLUIiLAogICAgICAgICAgaGVzc2lhbiA9IFRSVUUsCiAgICAgICAgICBjb250cm9sID0gbGlzdChtYXhpdCA9IDEwMDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgZm5zY2FsZSAgPSAtMSwKICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBhYnN0b2wgPSAxZS04KQogICAgICAgICAgKQogICAgICBib290X2xvZ19leHAgPSBib290X2xvZ19leHAkdmFsdWUgICMgc3RvcmUgbG9nIGxpa2VsaWhvb2QgZXZhbHVhdGlvbgogICAgICAjIyMjIyMjIEVuZCBFeHBvbmVudGlhbCBsaWtlbGlob29kIHBlciBib290IHNhbXBsZSAgCiAgICAgIAogICAgICAKICAgICAgIyB0aGUgbGlrZWxpaG9vZCByYXRpbyBmb3IgRUFDSCBpbnN0YW5jZSBvZiB0aGUgYm9vdHN0cmFwIGlzIDIgdGltZXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbGlrZWxpaG9vZCByYXRpbyBldmFsdWF0ZWQgdW5kZXIgdW5yZXN0cmljdGVkIChXZWlidWxsKSBjaXJjdW1zdGFuY2VzIGFuZCBldmFsdWF0ZWQgdW5kZXIgc2ltcGxlciAoZXhwb25lbnRpYWwpIGNpcmN1bXN0YW5jZXMKICAgICAgYm9vdF9scl9zdGF0W2ldID0gMiAqIGFicyhib290X2xvZ193ZWliIC0gYm9vdF9sb2dfZXhwKQogICAgICAKCiAgICB9ICMgRU5EIEZPUiBMT09QCiAgICAKICAjIGNhbGN1bGF0ZSBhbmQgb3V0cHV0IGZpbmFsIHAgdmFsdWUKICBwID0gKHN1bShib290X2xyX3N0YXQgPj0gb2JzX2xyX3N0YXQpICsgMSkvIChiICsgMSkKICAKICAjIyMgRklOQUwgcCB2YWx1ZSBvZiBib290c3RyYXAgZXhlcmNpc2UgaXMgZXF1YWwgdG8uLiAKICAjIG51bWJlciBvZiBib290c3RyYXAgc2FtcGxlIExSIHRlc3Qgc3RhdHMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHRoZSBvcmlnaW5hbCBMUiB0ZXN0IHN0YXQgZm91bmQgaW4gc2VjdGlvbiBjCiAgCiAgcmV0dXJuKGxpc3QocF92YWx1ZV9ib290c3RyYXAgPSBwLAogICAgICAgICAgICAgIGJvb3RzdHJhcF9scl9zdGF0cyA9IGJvb3RfbHJfc3RhdCkpCiAgCn0gIyMjIyBFTkQgQk9PVFNUUkFQIEZVTkNUSU9OCgoKIyMgbm93IHJ1bm5pbmcgdGhlIGZ1bmN0aW9uCnNldC5zZWVkKDEyMykKQkxSVF90ZXN0ID0gYm9vdHN0cmFwX2xydF90ZXN0KGRhdGEgPSBkYXRhJHRpbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiID0gMTAwMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXRlX251bGwgPSBleHBfbWxlX2xhbWJkYSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic19scl9zdGF0ID0gTGFtYmRhKQoKIyBCTFJUX3Rlc3QkcF92YWx1ZV9ib290c3RyYXAgPSAwLjAwMDk5OTAwMQpgYGAKClVzaW5nIGEgcmVwZWF0ZWQgc2FtcGxlIHNpemUgb2YgMSwwMDAsIHRoZXJlIG9uY2UgYWdhaW4gYXBwZWFycyB0byBiZSBzaWduaWZpY2FudCBldmlkZW5jZSB0aGF0IGFuIGFzc3VtcHRpb24gb2YgZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uIHdvdWxkIHJlc3VsdCBpbiBhIG11Y2ggbGVzcyBhY2N1cmF0ZSByZXNlbWJsYW5jZSBvZiBvdXIgcG9wdWxhdGlvbiBvZiBnZWFyYm94IHN1cnZpdmFsIHRpbWVzIHRoYW4gYW4gYXNzdW1wdGlvbiBvZiBXZWlidWxsIGRpc3RyaWJ1dGlvbiB3b3VsZC4gT3VyIGJvb3RzdHJhcCBMUlQgeWllbGRlZCBhIHAtdmFsdWUgb2Ygb25seSBgciByb3VuZChCTFJUX3Rlc3QkcF92YWx1ZV9ib290c3RyYXAsIDQpYC4KCiMgZS4pIFN1bW1hcnkgYW5kIENvbmNsdXNpb25zClRvIHN1bW1hcml6ZSwgYWxsIG9mIHRoZSBhbmFseXNpcyB1cCB0byB0aGlzIHBvaW50IHN1cHBvcnRzIHRoZSBub3Rpb24gb2YgbW92aW5nIGZvcndhcmQgdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgYnJvYWRlciBwb3B1bGF0aW9uIG9mIGdlYXJib3ggc3Vydml2YWwgdGltZXMgaXMgKipXZWlidWxsIGRpc3RyaWJ1dGVkKiogd2l0aCBhIHNoYXBlIHBhcmFtZXRlciAoJFxiZXRhJCkgb2YgYWJvdXQgYHIgcm91bmQod2VpYl9tbGVfYmV0YSwzKWAgYW5kIHNjYWxlIHBhcmFtZXRlciAoJFxsYW1iZGEkKSBvZiByb3VnaGx5IGByIHJvdW5kKHdlaWJfbWxlX2xhbWJkYSwzKWAuIEJvdGggdGhlIHN0YW5kYXJkIGFuZCBib290c3RyYXAgaXRlcmF0aW9ucyBvZiB0aGUgTFJUIHNob3cgYSBzaWduaWZpY2FudCBkZWNsaW5lIGluIGRpc3RyaWJ1dGlvbiByZXNlbWJsYW5jZSB3aGVuIGFzc3VtaW5nIGFuIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbi4gRnVydGhlcm1vcmUsIHdlIGNvdWxkIHNlZSBpbiBwcmVsaW1pbmFyeSB2aXN1YWwgYW5hbHlzaXMgdmlhIHRoZSBoaXN0b2dyYW1zIGluIHNlY3Rpb25zIGEgYW5kIGIsIHRoYXQgYSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBkZW5zaXR5IGN1cnZlIHdpdGggc2FpZCBwYXJlbWV0ZXJzIHdhcyAqbXVjaCogbW9yZSBhbGlnbmVkIHdpdGggb3VyIHNhbXBsZSBkaXN0cmlidXRpb24gdGhhbiB0aGF0IG9mIHRoZSBleHBvbmVudGlhbCBjdXJ2ZSB3aXRoICRcYmV0YSQgdmFsdWUgb2YgYXBwcm94aW1hdGVseSBgciByb3VuZChleHBfbWxlX2xhbWJkYSwzKWAuCgoK