Data and Setup

# stored as data vector
data = rbind.data.frame(3.2, 5.8, 7.1, 4.5, 10.3, 6.2, 8.7, 5.1, 12.5, 6.9,
9.4, 5.7, 11.8, 4.9, 9.1, 6.5, 13.2, 7.8, 10.6, 6.1,
8.9, 5.4, 12.1, 7.3, 9.8, 5.9, 11.4, 6.8, 10.9, 7.5,
4.2, 8.3, 6.4, 14.1, 5.6, 9.7, 7.9, 11.1, 6.7, 10.2,
5.3, 8.6, 7.2, 12.9, 6.3, 9.3, 8.1, 13.7, 7.6, 10.8)
colnames(data) = "time"

# stored as raw values
times = c(3.2, 5.8, 7.1, 4.5, 10.3, 6.2, 8.7, 5.1, 12.5, 6.9,
9.4, 5.7, 11.8, 4.9, 9.1, 6.5, 13.2, 7.8, 10.6, 6.1,
8.9, 5.4, 12.1, 7.3, 9.8, 5.9, 11.4, 6.8, 10.9, 7.5,
4.2, 8.3, 6.4, 14.1, 5.6, 9.7, 7.9, 11.1, 6.7, 10.2,
5.3, 8.6, 7.2, 12.9, 6.3, 9.3, 8.1, 13.7, 7.6, 10.8)

For this analysis, we will be examining a dataset composed of 50 observed customer service call duration times, provided by a major North American phone provider. A summary and histogram of the available data is 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 = times)
kable(Summary_Table,align = "c",
      caption = "<span style='color:##000000;'>
      Summary Stats of Call Times </span>") %>%
  kable_styling(
    bootstrap_options = c("striped", "bordered"),
    full_width = FALSE,
    position = "center")
Summary Stats of Call Times
Min Q1 Med Mean Q3 Max
3.2 6.23 7.85 8.31 10.28 14.1
hist(data$time, 
     main = "Distribution of Call Times",
     xlab = "Call Time",
     prob = TRUE,
)
box(lwd=3)

Moving forward, we will use this available sample data to create confidence intervals to estimate the population parameter \(\theta\) from the broader population of service call duration times for this phone provider. Each of these confidence intervals will have a coverage (or confidence level) of 95%. This means that, in a theoretical world with endless random sampling from the population, the true value of \(\theta\) would be included in our interval 95% of the time.

We will operate under the assumption that our data follows a Lindley distribution. That distribution’s density function, MLE for estimating \(\theta\) (the distribution’s shape parameter), and Fisher information function are below.

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Week 8 - Confidence Intervals/PDF.png")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Week 8 - Confidence Intervals/MLE.png")

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Week 8 - Confidence Intervals/info.png")


a.) Asymptotic Confidence Interval

The first confidence interval I constructed to estimate \(\theta\) was an asymptotic interval, predicated on the properties of the central limit theorem (CLT). Per the CLT, a sample composed of independent and identically distributed data approaches a normal distribution as sample size increases. Conventional wisdom states that generally the CLT can be applied if the sample size is at least 30, which is the case in this scenario.

sample_var = var(data$time) # = 7.305241

n = nrow(data)

### per provided MLE formula
mle_numerator = 1 - mean(data$time) + 
  sqrt(mean(data$time)^2 + 6*mean(data$time)+1)

mle_denominator = 2 * mean(data$time)

theta_hat = mle_numerator/mle_denominator

# referencing code from Section 4 of Week 8 notes

# Find SE next
  # we are finding standard error of theta hat, so use theta hat in expression
  
  # calculations are extracted from Fisher's Information of theta expression that is provided in instructions

se_numerator = 1

se_denominator = sqrt(n * 
                        ((2/theta_hat^2) - 
                           1/(1+theta_hat)^2))

se = se_numerator/se_denominator

crit_value_low = qnorm(0.025)
crit_value_high = qnorm(0.025, lower.tail = FALSE)

  # 0.025 + 0.025 = 0.05 = 95% confidence

# confidence interval formula is estimate +- (critical value)(standard error)

ci_low = theta_hat - abs(crit_value_low * se)
  # = 0.1758057

ci_high = theta_hat + abs(crit_value_high * se)
  # = 0.2623931

The first step I took in constructing this asymptotic interval was calculating a point estimate of our parameter of interest, \(\theta\). I did so by using the closed form MLE equation pictured earlier in this report. Doing so provided me a \(\hat\theta\) value of approximately 0.219.

Since the formula for creating a confidence interval is estimate +- [(critical value) X (standard error)], I then focused on quantifying the error of the interval. As for the critical value, I simply used R’s qnorm() function (which is mathematically sound due to the CLT), and got critical values of roughly +- 1.96.

Regarding standard error, I performed algebraic manipulation on the Fisher information function referenced in opening section. Since the Fisher function tells us how much one instance of a random variable indicates about \(\theta\), I multiplied the given function by our sample size (n = 50). According to principles of MLE, the variance of \(\theta\) is simply 1 divided by \(\theta\)’s Fisher function. Because standard error (or standard deviation) is the square root of variance, I was ultimately able to calculate a standard error of roughly 0.022.

Putting these components together - the point estimate, critical value, and standard error - our final asymptotic confidence interval for \(\theta\) is the following (rounded):

\[\Large 0.176< \theta < 0.262\]

For greater certainty that no errors were made, I went forward and plotted, over top the sample data, a Lindley distribution with \(\theta\) values respectively representing the low and high points of the asymptotic interval as well as our original point estimate for \(\hat\theta\).

# install.packages("VGAM") needed to do so for dlind function
library(VGAM)

hist(data$time, 
     main = "Distribution of Call Times",
     xlab = "Call Time",
     prob = TRUE,
)

# lower limit
curve(dlind(x , theta = ci_low), 
      col = "blue",
      lwd = 3,
      add = TRUE)

# point estimation
curve(dlind(x , theta = theta_hat), 
      col = "red",
      lwd = 3,
      add = TRUE)

# upper limit
curve(dlind(x , theta = ci_high), 
      col = "green",
      lwd = 3,
      add = TRUE)

legend("topright",
       legend = c(paste0("Lower Limit (", round(ci_low,3), ")"),
                  paste0("Point Estimate (", round(theta_hat,3), ")" ),
                  paste0("Upper Limit (", round(ci_high,3), ")")),
       col = c("blue", "red", "green"),
       lwd = 3,
       box.lwd=3)

box(lwd=3)

As we can see, the overall trend of each plotted Lindley distribution does roughly mirror the trend of our sample data, with the upper limit of our confidence interval having the greatest resemblance. The plot does not provide overwhelming evidence for or against the accuracy of our interval estimations. We will keep this in mind, and compare the asymptotic interval results to the likelihood ratio results found in the next section.


b.) Likelihood Ratio Confidence Interval

The second confidence interval I created was a likelihood ratio one. Likelihood ratio intervals are not reliant on the theory of asymptotic normality, and are generally seen as more effective when working with small or moderate sample sizes.

While the likelihood ratio function works by default with standard likelihood functions, I chose to utilize the log likelihood for greater calculative ease. The provided log likelihood is below.

knitr::include_graphics("/Users/chrisbahm/Library/Mobile Documents/com~apple~CloudDocs/West Chester/Spring 2026/STA 506 - Grad Math Stat 2 /STA 506 R Folder/Week 8 - Confidence Intervals/Log.png")

# reference sections 5.1 through 5.3 from class notes

### The likelihood ratio works THE SAME using the log likelihood so will proceed using that function

# define log likelihood function
log_likelihood = function(theta, data){
  n = nrow(data)
  
  C = sum(log(1 + data))
  S = sum(data)
  
  return(n * log(theta^2/(1+theta)) + C - (theta * S))
}

## now evaluate log likelihood at MLE value of theta hat found in part a

log_likelihood_at_mle = log_likelihood(theta = theta_hat, data = data)
# = -143.3101
  # denominator of ratio function
  # remember, natural log of any number between 0 and 1 is negative, so do not be alarmed at value

Evaluating the log likelihood function with the value of \(\hat\theta\) = 0.219 originally found through the MLE function, we get a log likelihood of about -143.31.

I then utilize Wilks’ Theorem, which states that the likelihood ratio stat of \(\theta\) is equal to 2 times the difference between the log likelihood evaluated at \(\hat\theta\) and the log likelihood evaluated at the different data points of our sample.

## Wilks' Theorem
LR_stat = function(theta, data){
  2 * (log_likelihood_at_mle - log_likelihood(theta, data))
}

  # Wilks' theorem states that a likelihood ratio confidence interval with X parameters will have a critical value of a chi-square distribution with 1 - alpha, and a df = X
ratio_crit_value = qchisq(0.95, df = 1) # = 3.841459

root_function = function(theta, data, theta_hat){
  LR_stat(theta, data) - ratio_crit_value
}

lambda_lower = uniroot(root_function, 
                  interval = c(0.0001, theta_hat),
                  data = data,
                  theta_hat = theta_hat)$root

lambda_higher = uniroot(root_function, 
                  interval = c(theta_hat, 2),
                  data = data,
                  theta_hat = theta_hat)$root

#lambda_lower = 0.1786415
#lambda_higher = 0.2653312

Finally, R’s uniroot() function works to find the root of the equations set up by subtracting the critical value (3.841) from the likelihood ratio stat equation.

The critical value was quantified as the 95th percentile of a chi-square distribution with 1 degree of freedom. Wilks’ theorem states that a likelihood ratio confidence interval with X parameters will have a critical value of a chi-square distribution with 1 - \(\alpha\), and a df = X.

The ending results for the likelihood ratio confidence interval were the following:

\[\Large 0.179< \theta < 0.265\]


c.) Interval Comparison

As we can see, both methods of parameter interval estimation yielded extraordinarily similar results. If forced to make a choice, I would likely recommend moving forward with the likelihood confidence interval. I say this for two reasons.

First, as mentioned above, likelihood ratios are generally seen as a more effective tool when working with small to moderate sample sizes. In this scenario with a sample size of only 50, it is probably safer to use a method such as the likelihood ratio technique which is not reliant on the principle of asymptotic normality. Beyond that, if we recall back to our plot above, we saw that the larger values of \(\theta\) yielded a greater resemblance to our sample data. As we see in the comparison table below, both the lower and higher interval estimates from the likelihood ratio method are of greater value than their counterparts from the asymptotic method.

asymp_results = cbind(ci_low, ci_high)
ratio_results = cbind(lambda_lower, lambda_higher)
results = rbind(asymp_results, ratio_results)
colnames(results) = c("Lower Estimate", "Higher Estimate")
rownames(results) = c("Asymptotic", "Likelihood Ratio")

kable(results,align = "c",
      caption = "<span style='color:##000000;'>
      Estimates of Shape Parameter </span>") %>%
  kable_styling(
    bootstrap_options = c("striped", "bordered"),
    full_width = FALSE,
    position = "center")
Estimates of Shape Parameter
Lower Estimate Higher Estimate
Asymptotic 0.1758057 0.2623931
Likelihood Ratio 0.1786415 0.2653312
LS0tCnRpdGxlOiAiTGlrZWxpaG9vZCBDb25maWRlbmNlIEludGVydmFscyIKYXV0aG9yOiAiQ2hyaXMgQmFobSIKZGF0ZTogIk1hcmNoIDIxLCAyMDI2IgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfd2lkdGg6IDYKICAgIGZpZ19oZWlnaHQ6IDQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0Ci0tLQoKYGBge2NzcywgZWNobyA9IEZBTFNFfQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOwogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOwogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsKICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsKfQoKaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8KICBmb250LXNpemU6IDI0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IAojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4KCmlmICghcmVxdWlyZSgia25pdHIiKSkgeyAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBjb25kaXRpb25hbCBzdGF0ZW1lbnQgdG8gZGV0ZWN0CiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikgICAgICAgICAgICAgICAgICAjIHdoZXRoZXIgYSBwYWNrYWdlIHdhcyBpbnN0YWxsZWQgaW4KICAgbGlicmFyeShrbml0cikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91ciBtYWNoaW5lLiBJZiBub3QsIGluc3RhbGwgaXQgYW5kCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxvYWQgaXQgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgoKaWYgKCFyZXF1aXJlKHRpZHl2ZXJzZSkpIHtsaWJyYXJ5KHRpZHl2c2Vyc2UpfSAKCmlmICghcmVxdWlyZShHR2FsbHkpKSB7bGlicmFyeShHR2FsbHkpfSAKCmlmICghcmVxdWlyZShrYWJsZUV4dHJhKSkge2xpYnJhcnkoa2FibGVFeHRyYSl9IAoKaWYgKCFyZXF1aXJlKGdncGxvdDIpKSB7bGlicmFyeShnZ3Bsb3QyKX0gCgppZiAoIXJlcXVpcmUoY2FyKSkge2xpYnJhcnkoY2FyKX0gCgppZiAoIXJlcXVpcmUoZHBseXIpKSB7bGlicmFyeShkcGx5cil9IAoKaWYgKCFyZXF1aXJlKHBhbmRlcikpIHtsaWJyYXJ5KHBhbmRlcil9IAoKaWYgKCFyZXF1aXJlKGZvcmVjYXN0KSkge2xpYnJhcnkoZm9yZWNhc3QpfSAKCmlmICghcmVxdWlyZShsdWJyaWRhdGUpKSB7bGlicmFyeShsdWJyaWRhdGUpfSAKCmlmICghcmVxdWlyZSgic2NhbGVzIikpIHsKaW5zdGFsbC5wYWNrYWdlcygic2NhbGVzIikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCmxpYnJhcnkoInNjYWxlcyIpIAp9Cgprbml0cjo6b3B0c19jaHVuayRzZXQoCgllY2hvID0gVFJVRSwKCW1lc3NhZ2UgPSBGQUxTRSwKCXdhcm5pbmcgPSBGQUxTRSwKCWNvbW1lbnQgPSBOQSwKCXJlc3VsdHMgPSBUUlVFLAoJZmlnLmFsaWduID0gImNlbnRlciIKKQpgYGAKCiMgRGF0YSBhbmQgU2V0dXAKCmBgYHtyfQojIHN0b3JlZCBhcyBkYXRhIHZlY3RvcgpkYXRhID0gcmJpbmQuZGF0YS5mcmFtZSgzLjIsIDUuOCwgNy4xLCA0LjUsIDEwLjMsIDYuMiwgOC43LCA1LjEsIDEyLjUsIDYuOSwKOS40LCA1LjcsIDExLjgsIDQuOSwgOS4xLCA2LjUsIDEzLjIsIDcuOCwgMTAuNiwgNi4xLAo4LjksIDUuNCwgMTIuMSwgNy4zLCA5LjgsIDUuOSwgMTEuNCwgNi44LCAxMC45LCA3LjUsCjQuMiwgOC4zLCA2LjQsIDE0LjEsIDUuNiwgOS43LCA3LjksIDExLjEsIDYuNywgMTAuMiwKNS4zLCA4LjYsIDcuMiwgMTIuOSwgNi4zLCA5LjMsIDguMSwgMTMuNywgNy42LCAxMC44KQpjb2xuYW1lcyhkYXRhKSA9ICJ0aW1lIgoKIyBzdG9yZWQgYXMgcmF3IHZhbHVlcwp0aW1lcyA9IGMoMy4yLCA1LjgsIDcuMSwgNC41LCAxMC4zLCA2LjIsIDguNywgNS4xLCAxMi41LCA2LjksCjkuNCwgNS43LCAxMS44LCA0LjksIDkuMSwgNi41LCAxMy4yLCA3LjgsIDEwLjYsIDYuMSwKOC45LCA1LjQsIDEyLjEsIDcuMywgOS44LCA1LjksIDExLjQsIDYuOCwgMTAuOSwgNy41LAo0LjIsIDguMywgNi40LCAxNC4xLCA1LjYsIDkuNywgNy45LCAxMS4xLCA2LjcsIDEwLjIsCjUuMywgOC42LCA3LjIsIDEyLjksIDYuMywgOS4zLCA4LjEsIDEzLjcsIDcuNiwgMTAuOCkKCmBgYApGb3IgdGhpcyBhbmFseXNpcywgd2Ugd2lsbCBiZSBleGFtaW5pbmcgYSBkYXRhc2V0IGNvbXBvc2VkIG9mIGByIG5yb3coZGF0YSlgIG9ic2VydmVkIGN1c3RvbWVyIHNlcnZpY2UgY2FsbCBkdXJhdGlvbiB0aW1lcywgcHJvdmlkZWQgYnkgYSBtYWpvciBOb3J0aCBBbWVyaWNhbiBwaG9uZSBwcm92aWRlci4gQSBzdW1tYXJ5IGFuZCBoaXN0b2dyYW0gb2YgdGhlIGF2YWlsYWJsZSBkYXRhIGlzIGJlbG93LgoKYGBge3IsIGZpZy5oZWlnaHQ9NS41LCBmaWcud2lkdGg9Ni41fQpzdW1fc3RhdHNfdGFibGUgPSBmdW5jdGlvbih2YXJpYWJsZSl7CiAgdGFibGUgPSBjYmluZCgKICAgIHJvdW5kKG1pbih2YXJpYWJsZSksMiksCiAgICByb3VuZChxdWFudGlsZSh2YXJpYWJsZSwgMC4yNSksMiksCiAgICByb3VuZChtZWRpYW4odmFyaWFibGUpLDIpLAogICAgcm91bmQobWVhbih2YXJpYWJsZSksMiksCiAgICByb3VuZChxdWFudGlsZSh2YXJpYWJsZSwgMC43NSksMiksCiAgICByb3VuZChtYXgodmFyaWFibGUpLDIpCiAgKQogIGNvbG5hbWVzKHRhYmxlKSA9IGMoIk1pbiIsICJRMSIsICJNZWQiLCAiTWVhbiIsICJRMyIsICJNYXgiKQogIHJvd25hbWVzKHRhYmxlKSA9IE5VTEwKICByZXR1cm4odGFibGUpCn0KClN1bW1hcnlfVGFibGUgPSBzdW1fc3RhdHNfdGFibGUodmFyaWFibGUgPSB0aW1lcykKa2FibGUoU3VtbWFyeV9UYWJsZSxhbGlnbiA9ICJjIiwKICAgICAgY2FwdGlvbiA9ICI8c3BhbiBzdHlsZT0nY29sb3I6IyMwMDAwMDA7Jz4KICAgICAgU3VtbWFyeSBTdGF0cyBvZiBDYWxsIFRpbWVzIDwvc3Bhbj4iKSAlPiUKICBrYWJsZV9zdHlsaW5nKAogICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImJvcmRlcmVkIiksCiAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICBwb3NpdGlvbiA9ICJjZW50ZXIiKQoKCmhpc3QoZGF0YSR0aW1lLCAKICAgICBtYWluID0gIkRpc3RyaWJ1dGlvbiBvZiBDYWxsIFRpbWVzIiwKICAgICB4bGFiID0gIkNhbGwgVGltZSIsCiAgICAgcHJvYiA9IFRSVUUsCikKYm94KGx3ZD0zKQoKYGBgCgpNb3ZpbmcgZm9yd2FyZCwgd2Ugd2lsbCB1c2UgdGhpcyBhdmFpbGFibGUgc2FtcGxlIGRhdGEgdG8gY3JlYXRlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHRvIGVzdGltYXRlIHRoZSBwb3B1bGF0aW9uIHBhcmFtZXRlciAkXHRoZXRhJCBmcm9tIHRoZSBicm9hZGVyIHBvcHVsYXRpb24gb2Ygc2VydmljZSBjYWxsIGR1cmF0aW9uIHRpbWVzIGZvciB0aGlzIHBob25lIHByb3ZpZGVyLiBFYWNoIG9mIHRoZXNlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIHdpbGwgaGF2ZSBhIGNvdmVyYWdlIChvciBjb25maWRlbmNlIGxldmVsKSBvZiA5NSUuIFRoaXMgbWVhbnMgdGhhdCwgaW4gYSB0aGVvcmV0aWNhbCB3b3JsZCB3aXRoIGVuZGxlc3MgcmFuZG9tIHNhbXBsaW5nIGZyb20gdGhlIHBvcHVsYXRpb24sIHRoZSB0cnVlIHZhbHVlIG9mICRcdGhldGEkIHdvdWxkIGJlIGluY2x1ZGVkIGluIG91ciBpbnRlcnZhbCA5NSUgb2YgdGhlIHRpbWUuCgpXZSB3aWxsIG9wZXJhdGUgdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCBvdXIgZGF0YSBmb2xsb3dzIGEgTGluZGxleSBkaXN0cmlidXRpb24uIFRoYXQgZGlzdHJpYnV0aW9uJ3MgZGVuc2l0eSBmdW5jdGlvbiwgTUxFIGZvciBlc3RpbWF0aW5nICRcdGhldGEkICh0aGUgZGlzdHJpYnV0aW9uJ3Mgc2hhcGUgcGFyYW1ldGVyKSwgYW5kIEZpc2hlciBpbmZvcm1hdGlvbiBmdW5jdGlvbiBhcmUgYmVsb3cuCgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9jaHJpc2JhaG0vTGlicmFyeS9Nb2JpbGUgRG9jdW1lbnRzL2NvbX5hcHBsZX5DbG91ZERvY3MvV2VzdCBDaGVzdGVyL1NwcmluZyAyMDI2L1NUQSA1MDYgLSBHcmFkIE1hdGggU3RhdCAyIC9TVEEgNTA2IFIgRm9sZGVyL1dlZWsgOCAtIENvbmZpZGVuY2UgSW50ZXJ2YWxzL1BERi5wbmciKQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9jaHJpc2JhaG0vTGlicmFyeS9Nb2JpbGUgRG9jdW1lbnRzL2NvbX5hcHBsZX5DbG91ZERvY3MvV2VzdCBDaGVzdGVyL1NwcmluZyAyMDI2L1NUQSA1MDYgLSBHcmFkIE1hdGggU3RhdCAyIC9TVEEgNTA2IFIgRm9sZGVyL1dlZWsgOCAtIENvbmZpZGVuY2UgSW50ZXJ2YWxzL01MRS5wbmciKQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIi9Vc2Vycy9jaHJpc2JhaG0vTGlicmFyeS9Nb2JpbGUgRG9jdW1lbnRzL2NvbX5hcHBsZX5DbG91ZERvY3MvV2VzdCBDaGVzdGVyL1NwcmluZyAyMDI2L1NUQSA1MDYgLSBHcmFkIE1hdGggU3RhdCAyIC9TVEEgNTA2IFIgRm9sZGVyL1dlZWsgOCAtIENvbmZpZGVuY2UgSW50ZXJ2YWxzL2luZm8ucG5nIikKYGBgCgo8YnI+CgojIGEuKSBBc3ltcHRvdGljIENvbmZpZGVuY2UgSW50ZXJ2YWwKVGhlIGZpcnN0IGNvbmZpZGVuY2UgaW50ZXJ2YWwgSSBjb25zdHJ1Y3RlZCB0byBlc3RpbWF0ZSAkXHRoZXRhJCB3YXMgYW4gYXN5bXB0b3RpYyBpbnRlcnZhbCwgcHJlZGljYXRlZCBvbiB0aGUgcHJvcGVydGllcyBvZiB0aGUgY2VudHJhbCBsaW1pdCB0aGVvcmVtIChDTFQpLiBQZXIgdGhlIENMVCwgYSBzYW1wbGUgY29tcG9zZWQgb2YgaW5kZXBlbmRlbnQgYW5kIGlkZW50aWNhbGx5IGRpc3RyaWJ1dGVkIGRhdGEgYXBwcm9hY2hlcyBhIG5vcm1hbCBkaXN0cmlidXRpb24gYXMgc2FtcGxlIHNpemUgaW5jcmVhc2VzLiBDb252ZW50aW9uYWwgd2lzZG9tIHN0YXRlcyB0aGF0IGdlbmVyYWxseSB0aGUgQ0xUIGNhbiBiZSBhcHBsaWVkIGlmIHRoZSBzYW1wbGUgc2l6ZSBpcyBhdCBsZWFzdCAzMCwgd2hpY2ggaXMgdGhlIGNhc2UgaW4gdGhpcyBzY2VuYXJpby4KCmBgYHtyfQpzYW1wbGVfdmFyID0gdmFyKGRhdGEkdGltZSkgIyA9IDcuMzA1MjQxCgpuID0gbnJvdyhkYXRhKQoKIyMjIHBlciBwcm92aWRlZCBNTEUgZm9ybXVsYQptbGVfbnVtZXJhdG9yID0gMSAtIG1lYW4oZGF0YSR0aW1lKSArIAogIHNxcnQobWVhbihkYXRhJHRpbWUpXjIgKyA2Km1lYW4oZGF0YSR0aW1lKSsxKQoKbWxlX2Rlbm9taW5hdG9yID0gMiAqIG1lYW4oZGF0YSR0aW1lKQoKdGhldGFfaGF0ID0gbWxlX251bWVyYXRvci9tbGVfZGVub21pbmF0b3IKCiMgcmVmZXJlbmNpbmcgY29kZSBmcm9tIFNlY3Rpb24gNCBvZiBXZWVrIDggbm90ZXMKCiMgRmluZCBTRSBuZXh0CiAgIyB3ZSBhcmUgZmluZGluZyBzdGFuZGFyZCBlcnJvciBvZiB0aGV0YSBoYXQsIHNvIHVzZSB0aGV0YSBoYXQgaW4gZXhwcmVzc2lvbgogIAogICMgY2FsY3VsYXRpb25zIGFyZSBleHRyYWN0ZWQgZnJvbSBGaXNoZXIncyBJbmZvcm1hdGlvbiBvZiB0aGV0YSBleHByZXNzaW9uIHRoYXQgaXMgcHJvdmlkZWQgaW4gaW5zdHJ1Y3Rpb25zCgpzZV9udW1lcmF0b3IgPSAxCgpzZV9kZW5vbWluYXRvciA9IHNxcnQobiAqIAogICAgICAgICAgICAgICAgICAgICAgICAoKDIvdGhldGFfaGF0XjIpIC0gCiAgICAgICAgICAgICAgICAgICAgICAgICAgIDEvKDErdGhldGFfaGF0KV4yKSkKCnNlID0gc2VfbnVtZXJhdG9yL3NlX2Rlbm9taW5hdG9yCgpjcml0X3ZhbHVlX2xvdyA9IHFub3JtKDAuMDI1KQpjcml0X3ZhbHVlX2hpZ2ggPSBxbm9ybSgwLjAyNSwgbG93ZXIudGFpbCA9IEZBTFNFKQoKICAjIDAuMDI1ICsgMC4wMjUgPSAwLjA1ID0gOTUlIGNvbmZpZGVuY2UKCiMgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3JtdWxhIGlzIGVzdGltYXRlICstIChjcml0aWNhbCB2YWx1ZSkoc3RhbmRhcmQgZXJyb3IpCgpjaV9sb3cgPSB0aGV0YV9oYXQgLSBhYnMoY3JpdF92YWx1ZV9sb3cgKiBzZSkKICAjID0gMC4xNzU4MDU3CgpjaV9oaWdoID0gdGhldGFfaGF0ICsgYWJzKGNyaXRfdmFsdWVfaGlnaCAqIHNlKQogICMgPSAwLjI2MjM5MzEKCmBgYApUaGUgZmlyc3Qgc3RlcCBJIHRvb2sgaW4gY29uc3RydWN0aW5nIHRoaXMgYXN5bXB0b3RpYyBpbnRlcnZhbCB3YXMgY2FsY3VsYXRpbmcgYSBwb2ludCBlc3RpbWF0ZSBvZiBvdXIgcGFyYW1ldGVyIG9mIGludGVyZXN0LCAkXHRoZXRhJC4gSSBkaWQgc28gYnkgdXNpbmcgdGhlIGNsb3NlZCBmb3JtIE1MRSBlcXVhdGlvbiBwaWN0dXJlZCBlYXJsaWVyIGluIHRoaXMgcmVwb3J0LiBEb2luZyBzbyBwcm92aWRlZCBtZSBhICRcaGF0XHRoZXRhJCB2YWx1ZSBvZiBhcHByb3hpbWF0ZWx5ICoqYHIgcm91bmQodGhldGFfaGF0LDMpYCoqLgoKU2luY2UgdGhlIGZvcm11bGEgZm9yIGNyZWF0aW5nIGEgY29uZmlkZW5jZSBpbnRlcnZhbCBpcyAqKmVzdGltYXRlICstIFsoY3JpdGljYWwgdmFsdWUpIFggKHN0YW5kYXJkIGVycm9yKV0qKiwgSSB0aGVuIGZvY3VzZWQgb24gcXVhbnRpZnlpbmcgdGhlIGVycm9yIG9mIHRoZSBpbnRlcnZhbC4gQXMgZm9yIHRoZSBjcml0aWNhbCB2YWx1ZSwgSSBzaW1wbHkgdXNlZCBSJ3MgPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij5xbm9ybSgpPC9zcGFuPiBmdW5jdGlvbiAod2hpY2ggaXMgbWF0aGVtYXRpY2FsbHkgc291bmQgZHVlIHRvIHRoZSBDTFQpLCBhbmQgZ290IGNyaXRpY2FsIHZhbHVlcyBvZiByb3VnaGx5ICstIGByIHJvdW5kKGNyaXRfdmFsdWVfaGlnaCwzKWAuCgpSZWdhcmRpbmcgc3RhbmRhcmQgZXJyb3IsIEkgcGVyZm9ybWVkIGFsZ2VicmFpYyBtYW5pcHVsYXRpb24gb24gdGhlIEZpc2hlciBpbmZvcm1hdGlvbiBmdW5jdGlvbiByZWZlcmVuY2VkIGluIG9wZW5pbmcgc2VjdGlvbi4gU2luY2UgdGhlIEZpc2hlciBmdW5jdGlvbiB0ZWxscyB1cyBob3cgbXVjaCAqb25lIGluc3RhbmNlKiBvZiBhIHJhbmRvbSB2YXJpYWJsZSBpbmRpY2F0ZXMgYWJvdXQgJFx0aGV0YSQsIEkgbXVsdGlwbGllZCB0aGUgZ2l2ZW4gZnVuY3Rpb24gYnkgb3VyIHNhbXBsZSBzaXplIChuID0gNTApLiBBY2NvcmRpbmcgdG8gcHJpbmNpcGxlcyBvZiBNTEUsIHRoZSB2YXJpYW5jZSBvZiAkXHRoZXRhJCBpcyBzaW1wbHkgMSBkaXZpZGVkIGJ5ICRcdGhldGEkJ3MgRmlzaGVyIGZ1bmN0aW9uLiBCZWNhdXNlIHN0YW5kYXJkIGVycm9yIChvciBzdGFuZGFyZCBkZXZpYXRpb24pIGlzIHRoZSBzcXVhcmUgcm9vdCBvZiB2YXJpYW5jZSwgSSB3YXMgdWx0aW1hdGVseSBhYmxlIHRvIGNhbGN1bGF0ZSBhIHN0YW5kYXJkIGVycm9yIG9mIHJvdWdobHkgYHIgcm91bmQoc2UsIDMpYC4KClB1dHRpbmcgdGhlc2UgY29tcG9uZW50cyB0b2dldGhlciAtIHRoZSBwb2ludCBlc3RpbWF0ZSwgY3JpdGljYWwgdmFsdWUsIGFuZCBzdGFuZGFyZCBlcnJvciAtIG91ciBmaW5hbCBhc3ltcHRvdGljIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yICRcdGhldGEkIGlzIHRoZSBmb2xsb3dpbmcgKHJvdW5kZWQpOgoKJCRcTGFyZ2UgYHIgcm91bmQoY2lfbG93LDMpYDwgXHRoZXRhIDwgYHIgcm91bmQoY2lfaGlnaCwzKWAkJAoKRm9yIGdyZWF0ZXIgY2VydGFpbnR5IHRoYXQgbm8gZXJyb3JzIHdlcmUgbWFkZSwgSSB3ZW50IGZvcndhcmQgYW5kIHBsb3R0ZWQsIG92ZXIgdG9wIHRoZSBzYW1wbGUgZGF0YSwgYSBMaW5kbGV5IGRpc3RyaWJ1dGlvbiB3aXRoICRcdGhldGEkIHZhbHVlcyByZXNwZWN0aXZlbHkgcmVwcmVzZW50aW5nIHRoZSBsb3cgYW5kIGhpZ2ggcG9pbnRzIG9mIHRoZSBhc3ltcHRvdGljIGludGVydmFsIGFzIHdlbGwgYXMgb3VyIG9yaWdpbmFsIHBvaW50IGVzdGltYXRlIGZvciAkXGhhdFx0aGV0YSQuIApgYGB7ciwgZmlnLmhlaWdodD01LjUsIGZpZy53aWR0aD02LjV9CiMgaW5zdGFsbC5wYWNrYWdlcygiVkdBTSIpIG5lZWRlZCB0byBkbyBzbyBmb3IgZGxpbmQgZnVuY3Rpb24KbGlicmFyeShWR0FNKQoKaGlzdChkYXRhJHRpbWUsIAogICAgIG1haW4gPSAiRGlzdHJpYnV0aW9uIG9mIENhbGwgVGltZXMiLAogICAgIHhsYWIgPSAiQ2FsbCBUaW1lIiwKICAgICBwcm9iID0gVFJVRSwKKQoKIyBsb3dlciBsaW1pdApjdXJ2ZShkbGluZCh4ICwgdGhldGEgPSBjaV9sb3cpLCAKICAgICAgY29sID0gImJsdWUiLAogICAgICBsd2QgPSAzLAogICAgICBhZGQgPSBUUlVFKQoKIyBwb2ludCBlc3RpbWF0aW9uCmN1cnZlKGRsaW5kKHggLCB0aGV0YSA9IHRoZXRhX2hhdCksIAogICAgICBjb2wgPSAicmVkIiwKICAgICAgbHdkID0gMywKICAgICAgYWRkID0gVFJVRSkKCiMgdXBwZXIgbGltaXQKY3VydmUoZGxpbmQoeCAsIHRoZXRhID0gY2lfaGlnaCksIAogICAgICBjb2wgPSAiZ3JlZW4iLAogICAgICBsd2QgPSAzLAogICAgICBhZGQgPSBUUlVFKQoKbGVnZW5kKCJ0b3ByaWdodCIsCiAgICAgICBsZWdlbmQgPSBjKHBhc3RlMCgiTG93ZXIgTGltaXQgKCIsIHJvdW5kKGNpX2xvdywzKSwgIikiKSwKICAgICAgICAgICAgICAgICAgcGFzdGUwKCJQb2ludCBFc3RpbWF0ZSAoIiwgcm91bmQodGhldGFfaGF0LDMpLCAiKSIgKSwKICAgICAgICAgICAgICAgICAgcGFzdGUwKCJVcHBlciBMaW1pdCAoIiwgcm91bmQoY2lfaGlnaCwzKSwgIikiKSksCiAgICAgICBjb2wgPSBjKCJibHVlIiwgInJlZCIsICJncmVlbiIpLAogICAgICAgbHdkID0gMywKICAgICAgIGJveC5sd2Q9MykKCmJveChsd2Q9MykKYGBgCgpBcyB3ZSBjYW4gc2VlLCB0aGUgb3ZlcmFsbCB0cmVuZCBvZiBlYWNoIHBsb3R0ZWQgTGluZGxleSBkaXN0cmlidXRpb24gZG9lcyByb3VnaGx5IG1pcnJvciB0aGUgdHJlbmQgb2Ygb3VyIHNhbXBsZSBkYXRhLCB3aXRoIHRoZSB1cHBlciBsaW1pdCBvZiBvdXIgY29uZmlkZW5jZSBpbnRlcnZhbCBoYXZpbmcgdGhlIGdyZWF0ZXN0IHJlc2VtYmxhbmNlLiBUaGUgcGxvdCBkb2VzIG5vdCBwcm92aWRlIG92ZXJ3aGVsbWluZyBldmlkZW5jZSBmb3Igb3IgYWdhaW5zdCB0aGUgYWNjdXJhY3kgb2Ygb3VyIGludGVydmFsIGVzdGltYXRpb25zLiBXZSB3aWxsIGtlZXAgdGhpcyBpbiBtaW5kLCBhbmQgY29tcGFyZSB0aGUgYXN5bXB0b3RpYyBpbnRlcnZhbCByZXN1bHRzIHRvIHRoZSBsaWtlbGlob29kIHJhdGlvIHJlc3VsdHMgZm91bmQgaW4gdGhlIG5leHQgc2VjdGlvbi4KCjxicj4KCiMgYi4pIExpa2VsaWhvb2QgUmF0aW8gQ29uZmlkZW5jZSBJbnRlcnZhbApUaGUgc2Vjb25kIGNvbmZpZGVuY2UgaW50ZXJ2YWwgSSBjcmVhdGVkIHdhcyBhIGxpa2VsaWhvb2QgcmF0aW8gb25lLiBMaWtlbGlob29kIHJhdGlvIGludGVydmFscyBhcmUgbm90IHJlbGlhbnQgb24gdGhlIHRoZW9yeSBvZiBhc3ltcHRvdGljIG5vcm1hbGl0eSwgYW5kIGFyZSBnZW5lcmFsbHkgc2VlbiBhcyBtb3JlIGVmZmVjdGl2ZSB3aGVuIHdvcmtpbmcgd2l0aCBzbWFsbCBvciBtb2RlcmF0ZSBzYW1wbGUgc2l6ZXMuIAoKV2hpbGUgdGhlIGxpa2VsaWhvb2QgcmF0aW8gZnVuY3Rpb24gd29ya3MgYnkgZGVmYXVsdCB3aXRoIHN0YW5kYXJkIGxpa2VsaWhvb2QgZnVuY3Rpb25zLCBJIGNob3NlIHRvIHV0aWxpemUgdGhlIGxvZyBsaWtlbGlob29kIGZvciBncmVhdGVyIGNhbGN1bGF0aXZlIGVhc2UuIFRoZSBwcm92aWRlZCBsb2cgbGlrZWxpaG9vZCBpcyBiZWxvdy4KCmBgYHtyfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiL1VzZXJzL2NocmlzYmFobS9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9XZXN0IENoZXN0ZXIvU3ByaW5nIDIwMjYvU1RBIDUwNiAtIEdyYWQgTWF0aCBTdGF0IDIgL1NUQSA1MDYgUiBGb2xkZXIvV2VlayA4IC0gQ29uZmlkZW5jZSBJbnRlcnZhbHMvTG9nLnBuZyIpCmBgYAoKYGBge3J9CiMgcmVmZXJlbmNlIHNlY3Rpb25zIDUuMSB0aHJvdWdoIDUuMyBmcm9tIGNsYXNzIG5vdGVzCgojIyMgVGhlIGxpa2VsaWhvb2QgcmF0aW8gd29ya3MgVEhFIFNBTUUgdXNpbmcgdGhlIGxvZyBsaWtlbGlob29kIHNvIHdpbGwgcHJvY2VlZCB1c2luZyB0aGF0IGZ1bmN0aW9uCgojIGRlZmluZSBsb2cgbGlrZWxpaG9vZCBmdW5jdGlvbgpsb2dfbGlrZWxpaG9vZCA9IGZ1bmN0aW9uKHRoZXRhLCBkYXRhKXsKICBuID0gbnJvdyhkYXRhKQogIAogIEMgPSBzdW0obG9nKDEgKyBkYXRhKSkKICBTID0gc3VtKGRhdGEpCiAgCiAgcmV0dXJuKG4gKiBsb2codGhldGFeMi8oMSt0aGV0YSkpICsgQyAtICh0aGV0YSAqIFMpKQp9CgojIyBub3cgZXZhbHVhdGUgbG9nIGxpa2VsaWhvb2QgYXQgTUxFIHZhbHVlIG9mIHRoZXRhIGhhdCBmb3VuZCBpbiBwYXJ0IGEKCmxvZ19saWtlbGlob29kX2F0X21sZSA9IGxvZ19saWtlbGlob29kKHRoZXRhID0gdGhldGFfaGF0LCBkYXRhID0gZGF0YSkKIyA9IC0xNDMuMzEwMQogICMgZGVub21pbmF0b3Igb2YgcmF0aW8gZnVuY3Rpb24KICAjIHJlbWVtYmVyLCBuYXR1cmFsIGxvZyBvZiBhbnkgbnVtYmVyIGJldHdlZW4gMCBhbmQgMSBpcyBuZWdhdGl2ZSwgc28gZG8gbm90IGJlIGFsYXJtZWQgYXQgdmFsdWUKYGBgCgpFdmFsdWF0aW5nIHRoZSBsb2cgbGlrZWxpaG9vZCBmdW5jdGlvbiB3aXRoIHRoZSB2YWx1ZSBvZiAkXGhhdFx0aGV0YSQgPSBgciByb3VuZCh0aGV0YV9oYXQsMylgIG9yaWdpbmFsbHkgZm91bmQgdGhyb3VnaCB0aGUgTUxFIGZ1bmN0aW9uLCB3ZSBnZXQgYSBsb2cgbGlrZWxpaG9vZCBvZiBhYm91dCBgciByb3VuZChsb2dfbGlrZWxpaG9vZF9hdF9tbGUsMylgLiAKCkkgdGhlbiB1dGlsaXplICpXaWxrcycgVGhlb3JlbSosIHdoaWNoIHN0YXRlcyB0aGF0IHRoZSBsaWtlbGlob29kIHJhdGlvIHN0YXQgb2YgJFx0aGV0YSQgaXMgZXF1YWwgdG8gMiB0aW1lcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBsb2cgbGlrZWxpaG9vZCBldmFsdWF0ZWQgYXQgJFxoYXRcdGhldGEkIGFuZCB0aGUgbG9nIGxpa2VsaWhvb2QgZXZhbHVhdGVkIGF0IHRoZSBkaWZmZXJlbnQgZGF0YSBwb2ludHMgb2Ygb3VyIHNhbXBsZS4KCmBgYHtyfQojIyBXaWxrcycgVGhlb3JlbQpMUl9zdGF0ID0gZnVuY3Rpb24odGhldGEsIGRhdGEpewogIDIgKiAobG9nX2xpa2VsaWhvb2RfYXRfbWxlIC0gbG9nX2xpa2VsaWhvb2QodGhldGEsIGRhdGEpKQp9CgogICMgV2lsa3MnIHRoZW9yZW0gc3RhdGVzIHRoYXQgYSBsaWtlbGlob29kIHJhdGlvIGNvbmZpZGVuY2UgaW50ZXJ2YWwgd2l0aCBYIHBhcmFtZXRlcnMgd2lsbCBoYXZlIGEgY3JpdGljYWwgdmFsdWUgb2YgYSBjaGktc3F1YXJlIGRpc3RyaWJ1dGlvbiB3aXRoIDEgLSBhbHBoYSwgYW5kIGEgZGYgPSBYCnJhdGlvX2NyaXRfdmFsdWUgPSBxY2hpc3EoMC45NSwgZGYgPSAxKSAjID0gMy44NDE0NTkKCnJvb3RfZnVuY3Rpb24gPSBmdW5jdGlvbih0aGV0YSwgZGF0YSwgdGhldGFfaGF0KXsKICBMUl9zdGF0KHRoZXRhLCBkYXRhKSAtIHJhdGlvX2NyaXRfdmFsdWUKfQoKbGFtYmRhX2xvd2VyID0gdW5pcm9vdChyb290X2Z1bmN0aW9uLCAKICAgICAgICAgICAgICAgICAgaW50ZXJ2YWwgPSBjKDAuMDAwMSwgdGhldGFfaGF0KSwKICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsCiAgICAgICAgICAgICAgICAgIHRoZXRhX2hhdCA9IHRoZXRhX2hhdCkkcm9vdAoKbGFtYmRhX2hpZ2hlciA9IHVuaXJvb3Qocm9vdF9mdW5jdGlvbiwgCiAgICAgICAgICAgICAgICAgIGludGVydmFsID0gYyh0aGV0YV9oYXQsIDIpLAogICAgICAgICAgICAgICAgICBkYXRhID0gZGF0YSwKICAgICAgICAgICAgICAgICAgdGhldGFfaGF0ID0gdGhldGFfaGF0KSRyb290CgojbGFtYmRhX2xvd2VyID0gMC4xNzg2NDE1CiNsYW1iZGFfaGlnaGVyID0gMC4yNjUzMzEyCmBgYAoKRmluYWxseSwgUidzIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+dW5pcm9vdCgpPC9zcGFuPiBmdW5jdGlvbiB3b3JrcyB0byBmaW5kIHRoZSByb290IG9mIHRoZSBlcXVhdGlvbnMgc2V0IHVwIGJ5IHN1YnRyYWN0aW5nIHRoZSBjcml0aWNhbCB2YWx1ZSAoYHIgcm91bmQocmF0aW9fY3JpdF92YWx1ZSwzKWApIGZyb20gdGhlIGxpa2VsaWhvb2QgcmF0aW8gc3RhdCBlcXVhdGlvbi4gCgpUaGUgY3JpdGljYWwgdmFsdWUgd2FzIHF1YW50aWZpZWQgYXMgdGhlIDk1dGggcGVyY2VudGlsZSBvZiBhIGNoaS1zcXVhcmUgZGlzdHJpYnV0aW9uIHdpdGggMSBkZWdyZWUgb2YgZnJlZWRvbS4gV2lsa3MnIHRoZW9yZW0gc3RhdGVzIHRoYXQgYSBsaWtlbGlob29kIHJhdGlvIGNvbmZpZGVuY2UgaW50ZXJ2YWwgd2l0aCBYIHBhcmFtZXRlcnMgd2lsbCBoYXZlIGEgY3JpdGljYWwgdmFsdWUgb2YgYSBjaGktc3F1YXJlIGRpc3RyaWJ1dGlvbiB3aXRoIDEgLSAkXGFscGhhJCwgYW5kIGEgZGYgPSBYLgoKVGhlIGVuZGluZyByZXN1bHRzIGZvciB0aGUgbGlrZWxpaG9vZCByYXRpbyBjb25maWRlbmNlIGludGVydmFsIHdlcmUgdGhlIGZvbGxvd2luZzoKCiQkXExhcmdlIGByIHJvdW5kKGxhbWJkYV9sb3dlciwzKWA8IFx0aGV0YSA8IGByIHJvdW5kKGxhbWJkYV9oaWdoZXIsMylgJCQKCjxicj4KCiMgYy4pIEludGVydmFsIENvbXBhcmlzb24KQXMgd2UgY2FuIHNlZSwgYm90aCBtZXRob2RzIG9mIHBhcmFtZXRlciBpbnRlcnZhbCBlc3RpbWF0aW9uIHlpZWxkZWQgZXh0cmFvcmRpbmFyaWx5IHNpbWlsYXIgcmVzdWx0cy4gSWYgZm9yY2VkIHRvIG1ha2UgYSBjaG9pY2UsIEkgd291bGQgbGlrZWx5IHJlY29tbWVuZCBtb3ZpbmcgZm9yd2FyZCB3aXRoIHRoZSBsaWtlbGlob29kIGNvbmZpZGVuY2UgaW50ZXJ2YWwuIEkgc2F5IHRoaXMgZm9yIHR3byByZWFzb25zLiAKCkZpcnN0LCBhcyBtZW50aW9uZWQgYWJvdmUsIGxpa2VsaWhvb2QgcmF0aW9zIGFyZSBnZW5lcmFsbHkgc2VlbiBhcyBhIG1vcmUgZWZmZWN0aXZlIHRvb2wgd2hlbiB3b3JraW5nIHdpdGggc21hbGwgdG8gbW9kZXJhdGUgc2FtcGxlIHNpemVzLiBJbiB0aGlzIHNjZW5hcmlvIHdpdGggYSBzYW1wbGUgc2l6ZSBvZiBvbmx5IGByIG5yb3coZGF0YSlgLCBpdCBpcyBwcm9iYWJseSBzYWZlciB0byB1c2UgYSBtZXRob2Qgc3VjaCBhcyB0aGUgbGlrZWxpaG9vZCByYXRpbyB0ZWNobmlxdWUgd2hpY2ggaXMgbm90IHJlbGlhbnQgb24gdGhlIHByaW5jaXBsZSBvZiBhc3ltcHRvdGljIG5vcm1hbGl0eS4gQmV5b25kIHRoYXQsIGlmIHdlIHJlY2FsbCBiYWNrIHRvIG91ciBwbG90IGFib3ZlLCB3ZSBzYXcgdGhhdCB0aGUgbGFyZ2VyIHZhbHVlcyBvZiAkXHRoZXRhJCB5aWVsZGVkIGEgZ3JlYXRlciByZXNlbWJsYW5jZSB0byBvdXIgc2FtcGxlIGRhdGEuIEFzIHdlIHNlZSBpbiB0aGUgY29tcGFyaXNvbiB0YWJsZSBiZWxvdywgYm90aCB0aGUgbG93ZXIgYW5kIGhpZ2hlciBpbnRlcnZhbCBlc3RpbWF0ZXMgZnJvbSB0aGUgbGlrZWxpaG9vZCByYXRpbyBtZXRob2QgYXJlIG9mIGdyZWF0ZXIgdmFsdWUgdGhhbiB0aGVpciBjb3VudGVycGFydHMgZnJvbSB0aGUgYXN5bXB0b3RpYyBtZXRob2QuCgpgYGB7cn0KYXN5bXBfcmVzdWx0cyA9IGNiaW5kKGNpX2xvdywgY2lfaGlnaCkKcmF0aW9fcmVzdWx0cyA9IGNiaW5kKGxhbWJkYV9sb3dlciwgbGFtYmRhX2hpZ2hlcikKcmVzdWx0cyA9IHJiaW5kKGFzeW1wX3Jlc3VsdHMsIHJhdGlvX3Jlc3VsdHMpCmNvbG5hbWVzKHJlc3VsdHMpID0gYygiTG93ZXIgRXN0aW1hdGUiLCAiSGlnaGVyIEVzdGltYXRlIikKcm93bmFtZXMocmVzdWx0cykgPSBjKCJBc3ltcHRvdGljIiwgIkxpa2VsaWhvb2QgUmF0aW8iKQoKa2FibGUocmVzdWx0cyxhbGlnbiA9ICJjIiwKICAgICAgY2FwdGlvbiA9ICI8c3BhbiBzdHlsZT0nY29sb3I6IyMwMDAwMDA7Jz4KICAgICAgRXN0aW1hdGVzIG9mIFNoYXBlIFBhcmFtZXRlciA8L3NwYW4+IikgJT4lCiAga2FibGVfc3R5bGluZygKICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIpLAogICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgcG9zaXRpb24gPSAiY2VudGVyIikKCmBgYAoK