NOTES!!!!!

How to do Hypothesis testing

  1. Read the question carefully. what is known?
  2. Data
    1. one sample, n > 30, sd known = Z test
    2. one sample, n < 30, sd unknown = t test
    3. two sample, n > 30, sd known = Z test
    4. two sample, n < 30, sd unknwon = t test
  3. Compute the Z or t score
  4. Write PDF for z and t distribution
  5. use integration method (trapezoidal/simpson) -> if using t, inside the function add v(df) in function (f,a,b,n=1000)

Things to remember

A. P (P-value)

  • two tail: 2*1- (P(abs(Ztest)))
  • upper tail: 1 - P(Ztest)
  • lower tail: P(Ztest)

B. q (Inverse of P)

  • two tail: q(1-alpha/2)
  • upper tail: q(1-alpha)
  • lower tail: q(alpha)

C. P-value integral

  • two tail: a = |Zscore|, b = 100
  • upper tail: a = Zscore, b = 100
  • lower tail: a = -100, b = Zscore

One Sample Z test

An electrical firm manufactures light bulbs that have a lifetime that is approximately normally distributet with a mean of 800 hours and a standard deviation of 40 hours. Test the hypothesis that µ = 800 hours against the alternative, µ != 800 hours, if a random sample of 30 bulbs has an average life of 788 hours. Use a P-value in your answer.

n = 30
miu = 800
xbar = 788
sd = 40

#HO : µ = 800
#H1 : µ != 800


# ------ Sample Z-Test Function ---
OneSample_Z <- function(xbar, miu, sigma, n, alpha = 0.05, type = "two.tail") {
  
  zscore <- (xbar - miu) / (sigma / sqrt(n))
  
  PDF_Normal <- function(x) {
    1/sqrt(2*pi) * exp(-x^2/2)
  }
  
  # --- Trapezoidal function to find PDF ---
  trap <- function (f, a, b, n = 1000) {
      h = (b - a) / n
      integral = (f(a) + f(b)) / 2
      for (i in 1:(n-1)) {
        integral = integral + f(a + i * h)
      }
      
      integral = integral * h 
      return(integral)
  }
  
  
  # --- Manual integration using Trapezoidal ---
  if (type == "two.tail") {
    p_trap <- 2 * trap(PDF_Normal, abs(zscore), 100)
  } else if (type == "lower") {
    p_trap <- trap(PDF_Normal, -100, zscore)
  } else if (type == "upper") {
    p_trap <- trap(PDF_Normal, zscore, 100)
  }
  
  
  # --- Built-in pnorm comparison ---
  if (type == "two.tail") {
    p_builtin <- 2 * (1 - pnorm(abs(zscore)))
    crit_val <- qnorm(1 - alpha / 2)
  } else if (type == "lower") {
    p_builtin <- pnorm(zscore)
    crit_val <- qnorm(alpha)
  } else if (type == "upper") {
    p_builtin <- 1 - pnorm(zscore)
    crit_val <- qnorm(1 - alpha)
  }
  
  
  # --- Output Results ---
  cat("=== One Sample Z-Test ===\n")
  cat("Sample mean (x̄)    =" ,round(xbar, 4), "\n")
  cat("Population mean μ  =", miu, "\n")
  cat("Z-statistic        =", round(zscore, 4), "\n")
  cat("p-value (Trap)     =", round(p_trap, 5), "\n")
  cat("p-value (pnorm)    =", round(p_builtin, 5), "\n")
  cat("alpha              =", alpha, "\n")
  cat("Critical Z value   =", round(crit_val, 4), "\n\n")
  
  if (p_builtin < alpha) {
    cat(">>> Reject H0 (Significant)\n")
  } else {
    cat(">>> Fail to Reject H0 (Not Significant)\n")
  }
}

OneSample_Z(xbar, miu, sd, n)
=== One Sample Z-Test ===
Sample mean (x̄)    = 788 
Population mean μ  = 800 
Z-statistic        = -1.6432 
p-value (Trap)     = 0.10062 
p-value (pnorm)    = 0.10035 
alpha              = 0.05 
Critical Z value   = 1.96 

>>> Fail to Reject H0 (Not Significant)

One Sample t test

Test the hypothesis that the average content of containers of a particular lubricant is 10 liters if the contents of a random sample of 10 containers are 10.2, 9.7, 10.1, 10.3, 10.1, 9.8, 9.9, 10.4, 10.3, and 9.8 liters. Use a 0.01 level of significance and assume that the distribution of contents is normal.


data <- c(10.2, 9.7, 10.1, 10.3, 10.1, 9.8, 9.9, 10.4, 10.3, 9.8)
miu <- 10



OneSample_t <- function(x, miu, alpha = 0.01, type = "two.tail") {
  
  # --- define the xbar, s, etc ---
  n = length(x)
  x_bar = sum(x)/n
  s = sd(x)
  v = n-1
  
  # --- define the tscore and pdf ---
  
  t_score = (x_bar - miu) / (s/ sqrt(n))
  
  PDF_t <- function(t, v) {
  (gamma((v+1)/2) / (sqrt(v*pi) * gamma(v/2))) * (1 + (t^2)/v)^(-(v+1)/2)
}
  
  # --- Trapezoidal function to find PDF ---
  trap <- function (f, a, b, n = 1000) {
      h = (b - a) / n
      integral = (f(a, v) + f(b, v)) / 2
      for (i in 1:(n-1)) {
        integral = integral + f(a + i * h, v)
      }
      
      integral = integral * h 
      return(integral)
  }
  
  
  # --- Manual integration using Trapezoidal ---
  if (type == "two.tail") {
    p_trap <- 2 * trap(PDF_t, abs(t_score), 100)
  } else if (type == "lower") {
    p_trap <- trap(PDF_t, -100, t_score)
  } else if (type == "upper") {
    p_trap <- trap(PDF_t, t_score, 100)
  }
  
  
  # --- Built-in pnorm comparison ---
  if (type == "two.tail") {
    p_builtin <- 2 * (1 - pt(abs(t_score),v))
    crit_val <- qt(1 - alpha / 2,v)
  } else if (type == "lower") {
    p_builtin <- pt(t_score, v)
    crit_val <- qt(alpha,v)
  } else if (type == "upper") {
    p_builtin <- 1 - pt(t_score,v)
    crit_val <- qt(1 - alpha,v)
  }
  
  
  # --- Output Results ---
  cat("=== One Sample Z-Test ===\n")
  cat("Sample mean (x̄)    =" ,round(x_bar, 4), "\n")
  cat("Population mean μ  =", miu, "\n")
  cat("t-statistic        =", round(t_score, 4), "\n")
  cat("p-value (Trap)     =", round(p_trap, 5), "\n")
  cat("p-value (pnorm)    =", round(p_builtin, 5), "\n")
  cat("alpha              =", alpha, "\n")
  cat("Critical t value   =", round(crit_val, 4), "\n\n")
  
  if (p_builtin < alpha) {
    cat(">>> Reject H0 (Significant)\n")
  } else {
    cat(">>> Fail to Reject H0 (Not Significant)\n")
  }
}

OneSample_t(data, miu)
=== One Sample Z-Test ===
Sample mean (x̄)    = 10.06 
Population mean μ  = 10 
t-statistic        = 0.7717 
p-value (Trap)     = 0.46042 
p-value (pnorm)    = 0.46005 
alpha              = 0.01 
Critical t value   = 3.2498 

>>> Fail to Reject H0 (Not Significant)

Two Sample Z-test

A random sample of size n1 = 25, taken from a normal population with a standard deviation σ1 = 5.2, has a mean xbar1 = 81. A second random sample of size n2 = 36, taken from a different normal population with a standard deviation σ2 = 3.4, has a mean xbar2 = 76. Test the hypothesis that μ1 = μ2 against the alternative, μ1 != μ2. Quote a P-value in your conclusion

n1 = 25
sd1 = 5.2
xbar1 = 81

n2 = 36
sd2 = 3.4
xbar2 = 76

# H0 : μ1 = μ2
# H1 : μ1 != μ2

TwoSample_Z <- function(xbar1, xbar2, sigma1, sigma2, n1, n2, alpha = 0.05, d0 = 0, type = "two.tail") {
  
  zscore <- (xbar1 - xbar2 - d0) / sqrt((sigma1^2/n1) + (sigma2^2/n2))
  
  PDF_Normal <- function(x) {
    1/sqrt(2*pi) * exp(-x^2/2)
  }
  
  # --- Trapezoidal function to find PDF ---
  trap <- function (f, a, b, n = 1000) {
      h = (b - a) / n
      integral = (f(a) + f(b)) / 2
      for (i in 1:(n-1)) {
        integral = integral + f(a + i * h)
      }
      
      integral = integral * h 
      return(integral)
  }
  
  
  # --- Manual integration using Trapezoidal ---
  if (type == "two.tail") {
    p_trap <- 2 * trap(PDF_Normal, abs(zscore), 100)
  } else if (type == "lower") {
    p_trap <- trap(PDF_Normal, -100, zscore)
  } else if (type == "upper") {
    p_trap <- trap(PDF_Normal, zscore, 100)
  }
  
  
  # --- Built-in pnorm comparison ---
  if (type == "two.tail") {
    p_builtin <- 2 * (1 - pnorm(abs(zscore)))
    crit_val <- qnorm(1 - alpha / 2)
  } else if (type == "lower") {
    p_builtin <- pnorm(zscore)
    crit_val <- qnorm(alpha)
  } else if (type == "upper") {
    p_builtin <- 1 - pnorm(zscore)
    crit_val <- qnorm(1 - alpha)
  }
  
  
  # --- Output Results ---
  cat("=== Two Sample Z-Test ===\n")
  cat("Sample mean (x̄1)   =" ,round(xbar1, 4), "\n")
  cat("Sample mean (x̄2)   =" ,round(xbar2, 4), "\n")
  cat("Z-statistic        =", round(zscore, 4), "\n")
  cat("p-value (Trap)     =", round(p_trap, 5), "\n")
  cat("p-value (pnorm)    =", round(p_builtin, 5), "\n")
  cat("alpha              =", alpha, "\n")
  cat("Critical Z value   =", round(crit_val, 4), "\n\n")
  
  if (p_builtin < alpha) {
    cat(">>> Reject H0 (Significant)\n")
  } else {
    cat(">>> Fail to Reject H0 (Not Significant)\n")
  }
}

TwoSample_Z(xbar1, xbar2, sd1, sd2, n1, n2)
=== Two Sample Z-Test ===
Sample mean (x̄1)   = 81 
Sample mean (x̄2)   = 76 
Z-statistic        = 4.2217 
p-value (Trap)     = 2e-05 
p-value (pnorm)    = 2e-05 
alpha              = 0.05 
Critical Z value   = 1.96 

>>> Reject H0 (Significant)

Two sample t-test, variance is equal

To find out whether a new serum will arrest leukemia, 9 mice, all with an advanced stage of the disease, are selected. Five mice receive the treatment and 4 do not. Survival times, in years, from the time the experiment commenced are as follows:

Treatment = 2.1, 5.3, 1.4, 4.6, 0.9 No Treatment = 1.9, 0.5, 2.8, 3.1

At the 0.05 level of significance, can the serum be said to be effective? Assume the two population to be normally distributed with equal variances.

data1 <- c(2.1, 5.3, 1.4, 4.6, 0.9)
data2 <- c(1.9, 0.5, 2.8, 3.1)

# H0 : The serum is effective (μ1 = μ2)
# H1 : The serum is not effective

TwoSample_t_same <- function(x1, x2, alpha = 0.05, type = "two.tail", d0 = 0) {
  
  # --- define the xbar, s, etc ---
  n1 = length(x1)
  n2 = length (x2)
  x_bar1 = sum(x1)/n1
  x_bar2 = sum(x2)/n2
  s1 = sd(x1)
  s2 = sd(x2)
  v = (n1 + n2) - 2
  sp_2 = (((n1 - 1)*s1^2) + ((n2 - 1)*s2^2)) / v
  sp = sqrt(sp_2)
  
  # --- define the tscore and pdf ---
  
  t_score = (x_bar1 - x_bar2 - d0) / (sp*sqrt((1/n1)+(1/n2)))
  
  PDF_t <- function(t, v) {
  (gamma((v+1)/2) / (sqrt(v*pi) * gamma(v/2))) * (1 + (t^2)/v)^(-(v+1)/2)
}
  
  # --- Trapezoidal function to find PDF ---
  trap <- function (f, a, b, n = 1000) {
      h = (b - a) / n
      integral = (f(a, v) + f(b, v)) / 2
      for (i in 1:(n-1)) {
        integral = integral + f(a + i * h, v)
      }
      
      integral = integral * h 
      return(integral)
  }
  
  
  # --- Manual integration using Trapezoidal ---
  if (type == "two.tail") {
    p_trap <- 2 * trap(PDF_t, abs(t_score), 100)
  } else if (type == "lower") {
    p_trap <- trap(PDF_t, -100, t_score)
  } else if (type == "upper") {
    p_trap <- trap(PDF_t, t_score, 100)
  }
  
  
  # --- Built-in pnorm comparison ---
  if (type == "two.tail") {
    p_builtin <- 2 * (1 - pt(abs(t_score),v))
    crit_val <- qt(1 - alpha / 2,v)
  } else if (type == "lower") {
    p_builtin <- pt(t_score, v)
    crit_val <- qt(alpha,v)
  } else if (type == "upper") {
    p_builtin <- 1 - pt(t_score,v)
    crit_val <- qt(1 - alpha,v)
  }
  
  
  # --- Output Results ---
  cat("=== One Sample Z-Test ===\n")
  cat("Sample mean (x̄1)    =" ,round(x_bar1, 4), "\n")
  cat("Sample mean (x2)    =" ,round(x_bar2, 4), "\n")
  cat("Population mean μ  =", miu, "\n")
  cat("t-statistic        =", round(t_score, 4), "\n")
  cat("p-value (Trap)     =", round(p_trap, 5), "\n")
  cat("p-value (pnorm)    =", round(p_builtin, 5), "\n")
  cat("alpha              =", alpha, "\n")
  cat("Critical t value   =", round(crit_val, 4), "\n\n")
  
  if (p_builtin < alpha) {
    cat(">>> Reject H0 (Significant)\n")
  } else {
    cat(">>> Fail to Reject H0 (Not Significant)\n")
  }
}

TwoSample_t_same(data1, data2)
=== One Sample Z-Test ===
Sample mean (x̄1)    = 2.86 
Sample mean (x2)    = 2.075 
Population mean μ  = 10 
t-statistic        = 0.699 
p-value (Trap)     = 0.50747 
p-value (pnorm)    = 0.50711 
alpha              = 0.05 
Critical t value   = 2.3646 

>>> Fail to Reject H0 (Not Significant)

Two sample t-test, variance is not equal

A study was conducted by the Department of Zoology at Virginia Tech to determine if there is a significant difference in the density of organisms at two different stations located on Cedar Run, a secondary stream in the Roanoke River drainage basin. Sewage from a sewage treatment plant and overflow from the Federal Mogul Corporation settling pond enter the stream near its headwaters. The following data give the density measurements, in number of organisms per square meter, at the two collecting stations

Station 1 = 5030, 13700, 10730, 11400, 860, 2200, 4250, 15040, 4980, 11910, 8130, 26850, 17660, 22800, 1130, 1690 Station 2 = 2800, 4670, 6890, 7720, 7030, 7330, 2810, 1330, 3320, 1230, 2130, 2190

Can we conclude, at the 0.05 level of significance, that the average densities at the two stations are equal? Assume that the observations come from normal populations with different variances.

station1 <- c(5030, 13700, 10730, 11400, 860, 2200, 4250, 15040, 4980, 11910, 8130, 26850, 17660, 22800, 1130, 1690)
station2 <- c(2800, 4670, 6890, 7720, 7030, 7330, 2810, 1330, 3320, 1230, 2130, 2190)

TwoSample_t_diff <- function(x1, x2, alpha = 0.05, type = "two.tail", d0 = 0) {
  
  # --- define the xbar, s, etc ---
  n1 = length(x1)
  n2 = length (x2)
  x_bar1 = sum(x1)/n1
  x_bar2 = sum(x2)/n2
  s1 = sd(x1)
  s2 = sd(x2)
  a = ((s1^2/n1) + (s2^2/n2))^2
  b = (((s1^2/n1)^2)/(n1-1)) + (((s2^2/n2)^2)/(n2-1))
  v = a/b
  
  
  # --- define the tscore and pdf ---
  
  t_score = ((x_bar1 - x_bar2) - d0) / (sqrt((s1^2/n1) + (s2^2/n2)))
  
  PDF_t <- function(t, v) {
  (gamma((v+1)/2) / (sqrt(v*pi) * gamma(v/2))) * (1 + (t^2)/v)^(-(v+1)/2)
}
  
  # --- Trapezoidal function to find PDF ---
  trap <- function (f, a, b, n = 1000) {
      h = (b - a) / n
      integral = (f(a, v) + f(b, v)) / 2
      for (i in 1:(n-1)) {
        integral = integral + f(a + i * h, v)
      }
      
      integral = integral * h 
      return(integral)
  }
  
  
  # --- Manual integration using Trapezoidal ---
  if (type == "two.tail") {
    p_trap <- 2 * trap(PDF_t, abs(t_score), 100)
  } else if (type == "lower") {
    p_trap <- trap(PDF_t, -100, t_score)
  } else if (type == "upper") {
    p_trap <- trap(PDF_t, t_score, 100)
  }
  
  
  # --- Built-in pnorm comparison ---
  if (type == "two.tail") {
    p_builtin <- 2 * (1 - pt(abs(t_score),v))
    crit_val <- qt(1 - alpha / 2,v)
  } else if (type == "lower") {
    p_builtin <- pt(t_score, v)
    crit_val <- qt(alpha,v)
  } else if (type == "upper") {
    p_builtin <- 1 - pt(t_score,v)
    crit_val <- qt(1 - alpha,v)
  }
  
  
  # --- Output Results ---
  cat("=== One Sample Z-Test ===\n")
  cat("Sample mean (x̄1)    =" ,round(x_bar1, 4), "\n")
  cat("Sample mean (x2)    =" ,round(x_bar2, 4), "\n")
  cat("Population mean μ  =", miu, "\n")
  cat("t-statistic        =", round(t_score, 4), "\n")
  cat("p-value (Trap)     =", round(p_trap, 5), "\n")
  cat("p-value (pnorm)    =", round(p_builtin, 5), "\n")
  cat("alpha              =", alpha, "\n")
  cat("Critical t value   =", round(crit_val, 4), "\n\n")
  
  if (p_builtin < alpha) {
    cat(">>> Reject H0 (Significant)\n")
  } else {
    cat(">>> Fail to Reject H0 (Not Significant)\n")
  }
}

TwoSample_t_diff(station1, station2)
=== One Sample Z-Test ===
Sample mean (x̄1)    = 9897.5 
Sample mean (x2)    = 4120.833 
Population mean μ  = 10 
t-statistic        = 2.7578 
p-value (Trap)     = 0.01266 
p-value (pnorm)    = 0.01261 
alpha              = 0.05 
Critical t value   = 2.0947 

>>> Reject H0 (Significant)
LS0tDQp0aXRsZTogIkxhdGloYW4gRVRTIChXNikiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIF8qKk5PVEVTISEhISEqKl8NCiMjIEhvdyB0byBkbyBIeXBvdGhlc2lzIHRlc3RpbmcNCjEuIFJlYWQgdGhlIHF1ZXN0aW9uIGNhcmVmdWxseS4gd2hhdCBpcyBrbm93bj8NCjIuIERhdGEgDQogICAgYSkgb25lIHNhbXBsZSwgbiA+IDMwLCBzZCBrbm93biA9IFogdGVzdA0KICAgIGIpIG9uZSBzYW1wbGUsIG4gPCAzMCwgc2QgdW5rbm93biA9IHQgdGVzdA0KICAgIGMpIHR3byBzYW1wbGUsIG4gPiAzMCwgc2Qga25vd24gPSBaIHRlc3QNCiAgICBkKSB0d28gc2FtcGxlLCBuIDwgMzAsIHNkIHVua253b24gPSB0IHRlc3QNCjMuIENvbXB1dGUgdGhlIFogb3IgdCBzY29yZQ0KNC4gV3JpdGUgUERGIGZvciB6IGFuZCB0IGRpc3RyaWJ1dGlvbg0KNS4gdXNlIGludGVncmF0aW9uIG1ldGhvZCAodHJhcGV6b2lkYWwvc2ltcHNvbikNCiAgIC0+IGlmIHVzaW5nIHQsIGluc2lkZSB0aGUgZnVuY3Rpb24gYWRkIHYoZGYpIGluIGZ1bmN0aW9uIChmLGEsYixuPTEwMDApDQogIA0KIyMgVGhpbmdzIHRvIHJlbWVtYmVyDQpBLiBQIChQLXZhbHVlKQ0KDQogICAtIHR3byB0YWlsOiAyKjEtIChQKGFicyhadGVzdCkpKQ0KICAgLSB1cHBlciB0YWlsOiAxIC0gUChadGVzdCkNCiAgIC0gbG93ZXIgdGFpbDogUChadGVzdCkNCiAgIA0KQi4gcSAoSW52ZXJzZSBvZiBQKQ0KDQogICAtIHR3byB0YWlsOiBxKDEtYWxwaGEvMikNCiAgIC0gdXBwZXIgdGFpbDogcSgxLWFscGhhKQ0KICAgLSBsb3dlciB0YWlsOiBxKGFscGhhKQ0KICANCkMuIFAtdmFsdWUgaW50ZWdyYWwNCg0KICAtIHR3byB0YWlsOiBhID0gfFpzY29yZXwsIGIgPSAxMDANCiAgLSB1cHBlciB0YWlsOiBhID0gWnNjb3JlLCBiID0gMTAwDQogIC0gbG93ZXIgdGFpbDogYSA9IC0xMDAsIGIgPSBac2NvcmUNCg0KDQoNCg0KDQojIyAqKk9uZSBTYW1wbGUgWiB0ZXN0KioNCg0KDQpBbiBlbGVjdHJpY2FsIGZpcm0gbWFudWZhY3R1cmVzIGxpZ2h0IGJ1bGJzIHRoYXQgaGF2ZSBhIGxpZmV0aW1lIHRoYXQgaXMgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRldCB3aXRoIGEgbWVhbiBvZiA4MDAgaG91cnMgYW5kIGEgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIDQwIGhvdXJzLiBUZXN0IHRoZSBoeXBvdGhlc2lzIHRoYXQgwrUgPSA4MDAgaG91cnMgYWdhaW5zdCB0aGUgYWx0ZXJuYXRpdmUsIMK1ICE9IDgwMCBob3VycywgaWYgYSByYW5kb20gc2FtcGxlIG9mIDMwIGJ1bGJzIGhhcyBhbiBhdmVyYWdlIGxpZmUgb2YgNzg4IGhvdXJzLiBVc2UgYSBQLXZhbHVlIGluIHlvdXIgYW5zd2VyLg0KDQpgYGB7cn0NCm4gPSAzMA0KbWl1ID0gODAwDQp4YmFyID0gNzg4DQpzZCA9IDQwDQoNCiNITyA6IMK1ID0gODAwDQojSDEgOiDCtSAhPSA4MDANCg0KDQojIC0tLS0tLSBTYW1wbGUgWi1UZXN0IEZ1bmN0aW9uIC0tLQ0KT25lU2FtcGxlX1ogPC0gZnVuY3Rpb24oeGJhciwgbWl1LCBzaWdtYSwgbiwgYWxwaGEgPSAwLjA1LCB0eXBlID0gInR3by50YWlsIikgew0KICANCiAgenNjb3JlIDwtICh4YmFyIC0gbWl1KSAvIChzaWdtYSAvIHNxcnQobikpDQogIA0KICBQREZfTm9ybWFsIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICAxL3NxcnQoMipwaSkgKiBleHAoLXheMi8yKQ0KICB9DQogIA0KICAjIC0tLSBUcmFwZXpvaWRhbCBmdW5jdGlvbiB0byBmaW5kIFBERiAtLS0NCiAgdHJhcCA8LSBmdW5jdGlvbiAoZiwgYSwgYiwgbiA9IDEwMDApIHsNCiAgICAgIGggPSAoYiAtIGEpIC8gbg0KICAgICAgaW50ZWdyYWwgPSAoZihhKSArIGYoYikpIC8gMg0KICAgICAgZm9yIChpIGluIDE6KG4tMSkpIHsNCiAgICAgICAgaW50ZWdyYWwgPSBpbnRlZ3JhbCArIGYoYSArIGkgKiBoKQ0KICAgICAgfQ0KICAgICAgDQogICAgICBpbnRlZ3JhbCA9IGludGVncmFsICogaCANCiAgICAgIHJldHVybihpbnRlZ3JhbCkNCiAgfQ0KICANCiAgDQogICMgLS0tIE1hbnVhbCBpbnRlZ3JhdGlvbiB1c2luZyBUcmFwZXpvaWRhbCAtLS0NCiAgaWYgKHR5cGUgPT0gInR3by50YWlsIikgew0KICAgIHBfdHJhcCA8LSAyICogdHJhcChQREZfTm9ybWFsLCBhYnMoenNjb3JlKSwgMTAwKQ0KICB9IGVsc2UgaWYgKHR5cGUgPT0gImxvd2VyIikgew0KICAgIHBfdHJhcCA8LSB0cmFwKFBERl9Ob3JtYWwsIC0xMDAsIHpzY29yZSkNCiAgfSBlbHNlIGlmICh0eXBlID09ICJ1cHBlciIpIHsNCiAgICBwX3RyYXAgPC0gdHJhcChQREZfTm9ybWFsLCB6c2NvcmUsIDEwMCkNCiAgfQ0KICANCiAgDQogICMgLS0tIEJ1aWx0LWluIHBub3JtIGNvbXBhcmlzb24gLS0tDQogIGlmICh0eXBlID09ICJ0d28udGFpbCIpIHsNCiAgICBwX2J1aWx0aW4gPC0gMiAqICgxIC0gcG5vcm0oYWJzKHpzY29yZSkpKQ0KICAgIGNyaXRfdmFsIDwtIHFub3JtKDEgLSBhbHBoYSAvIDIpDQogIH0gZWxzZSBpZiAodHlwZSA9PSAibG93ZXIiKSB7DQogICAgcF9idWlsdGluIDwtIHBub3JtKHpzY29yZSkNCiAgICBjcml0X3ZhbCA8LSBxbm9ybShhbHBoYSkNCiAgfSBlbHNlIGlmICh0eXBlID09ICJ1cHBlciIpIHsNCiAgICBwX2J1aWx0aW4gPC0gMSAtIHBub3JtKHpzY29yZSkNCiAgICBjcml0X3ZhbCA8LSBxbm9ybSgxIC0gYWxwaGEpDQogIH0NCiAgDQogIA0KICAjIC0tLSBPdXRwdXQgUmVzdWx0cyAtLS0NCiAgY2F0KCI9PT0gT25lIFNhbXBsZSBaLVRlc3QgPT09XG4iKQ0KICBjYXQoIlNhbXBsZSBtZWFuICh4zIQpICAgID0iICxyb3VuZCh4YmFyLCA0KSwgIlxuIikNCiAgY2F0KCJQb3B1bGF0aW9uIG1lYW4gzrwgID0iLCBtaXUsICJcbiIpDQogIGNhdCgiWi1zdGF0aXN0aWMgICAgICAgID0iLCByb3VuZCh6c2NvcmUsIDQpLCAiXG4iKQ0KICBjYXQoInAtdmFsdWUgKFRyYXApICAgICA9Iiwgcm91bmQocF90cmFwLCA1KSwgIlxuIikNCiAgY2F0KCJwLXZhbHVlIChwbm9ybSkgICAgPSIsIHJvdW5kKHBfYnVpbHRpbiwgNSksICJcbiIpDQogIGNhdCgiYWxwaGEgICAgICAgICAgICAgID0iLCBhbHBoYSwgIlxuIikNCiAgY2F0KCJDcml0aWNhbCBaIHZhbHVlICAgPSIsIHJvdW5kKGNyaXRfdmFsLCA0KSwgIlxuXG4iKQ0KICANCiAgaWYgKHBfYnVpbHRpbiA8IGFscGhhKSB7DQogICAgY2F0KCI+Pj4gUmVqZWN0IEgwIChTaWduaWZpY2FudClcbiIpDQogIH0gZWxzZSB7DQogICAgY2F0KCI+Pj4gRmFpbCB0byBSZWplY3QgSDAgKE5vdCBTaWduaWZpY2FudClcbiIpDQogIH0NCn0NCg0KT25lU2FtcGxlX1ooeGJhciwgbWl1LCBzZCwgbikNCmBgYA0KIyMgKipPbmUgU2FtcGxlIHQgdGVzdCoqIA0KDQpUZXN0IHRoZSBoeXBvdGhlc2lzIHRoYXQgdGhlIGF2ZXJhZ2UgY29udGVudCBvZiBjb250YWluZXJzIG9mIGEgcGFydGljdWxhciBsdWJyaWNhbnQgaXMgMTAgbGl0ZXJzIGlmIHRoZSBjb250ZW50cyBvZiBhIHJhbmRvbSBzYW1wbGUgb2YgMTAgY29udGFpbmVycyBhcmUgMTAuMiwgOS43LCAxMC4xLCAxMC4zLCAxMC4xLCA5LjgsIDkuOSwgMTAuNCwgMTAuMywgYW5kIDkuOCBsaXRlcnMuIFVzZSBhIDAuMDEgbGV2ZWwgb2Ygc2lnbmlmaWNhbmNlIGFuZCBhc3N1bWUgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGNvbnRlbnRzIGlzIG5vcm1hbC4NCg0KYGBge3J9DQoNCmRhdGEgPC0gYygxMC4yLCA5LjcsIDEwLjEsIDEwLjMsIDEwLjEsIDkuOCwgOS45LCAxMC40LCAxMC4zLCA5LjgpDQptaXUgPC0gMTANCg0KDQoNCk9uZVNhbXBsZV90IDwtIGZ1bmN0aW9uKHgsIG1pdSwgYWxwaGEgPSAwLjAxLCB0eXBlID0gInR3by50YWlsIikgew0KICANCiAgIyAtLS0gZGVmaW5lIHRoZSB4YmFyLCBzLCBldGMgLS0tDQogIG4gPSBsZW5ndGgoeCkNCiAgeF9iYXIgPSBzdW0oeCkvbg0KICBzID0gc2QoeCkNCiAgdiA9IG4tMQ0KICANCiAgIyAtLS0gZGVmaW5lIHRoZSB0c2NvcmUgYW5kIHBkZiAtLS0NCiAgDQogIHRfc2NvcmUgPSAoeF9iYXIgLSBtaXUpIC8gKHMvIHNxcnQobikpDQogIA0KICBQREZfdCA8LSBmdW5jdGlvbih0LCB2KSB7DQogIChnYW1tYSgodisxKS8yKSAvIChzcXJ0KHYqcGkpICogZ2FtbWEodi8yKSkpICogKDEgKyAodF4yKS92KV4oLSh2KzEpLzIpDQp9DQogIA0KICAjIC0tLSBUcmFwZXpvaWRhbCBmdW5jdGlvbiB0byBmaW5kIFBERiAtLS0NCiAgdHJhcCA8LSBmdW5jdGlvbiAoZiwgYSwgYiwgbiA9IDEwMDApIHsNCiAgICAgIGggPSAoYiAtIGEpIC8gbg0KICAgICAgaW50ZWdyYWwgPSAoZihhLCB2KSArIGYoYiwgdikpIC8gMg0KICAgICAgZm9yIChpIGluIDE6KG4tMSkpIHsNCiAgICAgICAgaW50ZWdyYWwgPSBpbnRlZ3JhbCArIGYoYSArIGkgKiBoLCB2KQ0KICAgICAgfQ0KICAgICAgDQogICAgICBpbnRlZ3JhbCA9IGludGVncmFsICogaCANCiAgICAgIHJldHVybihpbnRlZ3JhbCkNCiAgfQ0KICANCiAgDQogICMgLS0tIE1hbnVhbCBpbnRlZ3JhdGlvbiB1c2luZyBUcmFwZXpvaWRhbCAtLS0NCiAgaWYgKHR5cGUgPT0gInR3by50YWlsIikgew0KICAgIHBfdHJhcCA8LSAyICogdHJhcChQREZfdCwgYWJzKHRfc2NvcmUpLCAxMDApDQogIH0gZWxzZSBpZiAodHlwZSA9PSAibG93ZXIiKSB7DQogICAgcF90cmFwIDwtIHRyYXAoUERGX3QsIC0xMDAsIHRfc2NvcmUpDQogIH0gZWxzZSBpZiAodHlwZSA9PSAidXBwZXIiKSB7DQogICAgcF90cmFwIDwtIHRyYXAoUERGX3QsIHRfc2NvcmUsIDEwMCkNCiAgfQ0KICANCiAgDQogICMgLS0tIEJ1aWx0LWluIHBub3JtIGNvbXBhcmlzb24gLS0tDQogIGlmICh0eXBlID09ICJ0d28udGFpbCIpIHsNCiAgICBwX2J1aWx0aW4gPC0gMiAqICgxIC0gcHQoYWJzKHRfc2NvcmUpLHYpKQ0KICAgIGNyaXRfdmFsIDwtIHF0KDEgLSBhbHBoYSAvIDIsdikNCiAgfSBlbHNlIGlmICh0eXBlID09ICJsb3dlciIpIHsNCiAgICBwX2J1aWx0aW4gPC0gcHQodF9zY29yZSwgdikNCiAgICBjcml0X3ZhbCA8LSBxdChhbHBoYSx2KQ0KICB9IGVsc2UgaWYgKHR5cGUgPT0gInVwcGVyIikgew0KICAgIHBfYnVpbHRpbiA8LSAxIC0gcHQodF9zY29yZSx2KQ0KICAgIGNyaXRfdmFsIDwtIHF0KDEgLSBhbHBoYSx2KQ0KICB9DQogIA0KICANCiAgIyAtLS0gT3V0cHV0IFJlc3VsdHMgLS0tDQogIGNhdCgiPT09IE9uZSBTYW1wbGUgWi1UZXN0ID09PVxuIikNCiAgY2F0KCJTYW1wbGUgbWVhbiAoeMyEKSAgICA9IiAscm91bmQoeF9iYXIsIDQpLCAiXG4iKQ0KICBjYXQoIlBvcHVsYXRpb24gbWVhbiDOvCAgPSIsIG1pdSwgIlxuIikNCiAgY2F0KCJ0LXN0YXRpc3RpYyAgICAgICAgPSIsIHJvdW5kKHRfc2NvcmUsIDQpLCAiXG4iKQ0KICBjYXQoInAtdmFsdWUgKFRyYXApICAgICA9Iiwgcm91bmQocF90cmFwLCA1KSwgIlxuIikNCiAgY2F0KCJwLXZhbHVlIChwbm9ybSkgICAgPSIsIHJvdW5kKHBfYnVpbHRpbiwgNSksICJcbiIpDQogIGNhdCgiYWxwaGEgICAgICAgICAgICAgID0iLCBhbHBoYSwgIlxuIikNCiAgY2F0KCJDcml0aWNhbCB0IHZhbHVlICAgPSIsIHJvdW5kKGNyaXRfdmFsLCA0KSwgIlxuXG4iKQ0KICANCiAgaWYgKHBfYnVpbHRpbiA8IGFscGhhKSB7DQogICAgY2F0KCI+Pj4gUmVqZWN0IEgwIChTaWduaWZpY2FudClcbiIpDQogIH0gZWxzZSB7DQogICAgY2F0KCI+Pj4gRmFpbCB0byBSZWplY3QgSDAgKE5vdCBTaWduaWZpY2FudClcbiIpDQogIH0NCn0NCg0KT25lU2FtcGxlX3QoZGF0YSwgbWl1KQ0KDQpgYGANCiMjICoqVHdvIFNhbXBsZSBaLXRlc3QqKg0KDQpBIHJhbmRvbSBzYW1wbGUgb2Ygc2l6ZSBuMSA9IDI1LCB0YWtlbiBmcm9tIGEgbm9ybWFsIHBvcHVsYXRpb24gd2l0aCBhIHN0YW5kYXJkIGRldmlhdGlvbiDPgzEgPSA1LjIsIGhhcyBhIG1lYW4geGJhcjEgPSA4MS4gQSBzZWNvbmQgcmFuZG9tIHNhbXBsZSBvZiBzaXplIG4yID0gMzYsIHRha2VuIGZyb20gYSBkaWZmZXJlbnQgbm9ybWFsIHBvcHVsYXRpb24gd2l0aCBhIHN0YW5kYXJkIGRldmlhdGlvbiDPgzIgPSAzLjQsIGhhcyBhIG1lYW4geGJhcjIgPSA3Ni4gVGVzdCB0aGUgaHlwb3RoZXNpcyB0aGF0IM68MSA9IM68MiBhZ2FpbnN0IHRoZSBhbHRlcm5hdGl2ZSwgzrwxICE9IM68Mi4gUXVvdGUgYSBQLXZhbHVlIGluIHlvdXIgY29uY2x1c2lvbg0KDQpgYGB7cn0NCm4xID0gMjUNCnNkMSA9IDUuMg0KeGJhcjEgPSA4MQ0KDQpuMiA9IDM2DQpzZDIgPSAzLjQNCnhiYXIyID0gNzYNCg0KIyBIMCA6IM68MSA9IM68Mg0KIyBIMSA6IM68MSAhPSDOvDINCg0KVHdvU2FtcGxlX1ogPC0gZnVuY3Rpb24oeGJhcjEsIHhiYXIyLCBzaWdtYTEsIHNpZ21hMiwgbjEsIG4yLCBhbHBoYSA9IDAuMDUsIGQwID0gMCwgdHlwZSA9ICJ0d28udGFpbCIpIHsNCiAgDQogIHpzY29yZSA8LSAoeGJhcjEgLSB4YmFyMiAtIGQwKSAvIHNxcnQoKHNpZ21hMV4yL24xKSArIChzaWdtYTJeMi9uMikpDQogIA0KICBQREZfTm9ybWFsIDwtIGZ1bmN0aW9uKHgpIHsNCiAgICAxL3NxcnQoMipwaSkgKiBleHAoLXheMi8yKQ0KICB9DQogIA0KICAjIC0tLSBUcmFwZXpvaWRhbCBmdW5jdGlvbiB0byBmaW5kIFBERiAtLS0NCiAgdHJhcCA8LSBmdW5jdGlvbiAoZiwgYSwgYiwgbiA9IDEwMDApIHsNCiAgICAgIGggPSAoYiAtIGEpIC8gbg0KICAgICAgaW50ZWdyYWwgPSAoZihhKSArIGYoYikpIC8gMg0KICAgICAgZm9yIChpIGluIDE6KG4tMSkpIHsNCiAgICAgICAgaW50ZWdyYWwgPSBpbnRlZ3JhbCArIGYoYSArIGkgKiBoKQ0KICAgICAgfQ0KICAgICAgDQogICAgICBpbnRlZ3JhbCA9IGludGVncmFsICogaCANCiAgICAgIHJldHVybihpbnRlZ3JhbCkNCiAgfQ0KICANCiAgDQogICMgLS0tIE1hbnVhbCBpbnRlZ3JhdGlvbiB1c2luZyBUcmFwZXpvaWRhbCAtLS0NCiAgaWYgKHR5cGUgPT0gInR3by50YWlsIikgew0KICAgIHBfdHJhcCA8LSAyICogdHJhcChQREZfTm9ybWFsLCBhYnMoenNjb3JlKSwgMTAwKQ0KICB9IGVsc2UgaWYgKHR5cGUgPT0gImxvd2VyIikgew0KICAgIHBfdHJhcCA8LSB0cmFwKFBERl9Ob3JtYWwsIC0xMDAsIHpzY29yZSkNCiAgfSBlbHNlIGlmICh0eXBlID09ICJ1cHBlciIpIHsNCiAgICBwX3RyYXAgPC0gdHJhcChQREZfTm9ybWFsLCB6c2NvcmUsIDEwMCkNCiAgfQ0KICANCiAgDQogICMgLS0tIEJ1aWx0LWluIHBub3JtIGNvbXBhcmlzb24gLS0tDQogIGlmICh0eXBlID09ICJ0d28udGFpbCIpIHsNCiAgICBwX2J1aWx0aW4gPC0gMiAqICgxIC0gcG5vcm0oYWJzKHpzY29yZSkpKQ0KICAgIGNyaXRfdmFsIDwtIHFub3JtKDEgLSBhbHBoYSAvIDIpDQogIH0gZWxzZSBpZiAodHlwZSA9PSAibG93ZXIiKSB7DQogICAgcF9idWlsdGluIDwtIHBub3JtKHpzY29yZSkNCiAgICBjcml0X3ZhbCA8LSBxbm9ybShhbHBoYSkNCiAgfSBlbHNlIGlmICh0eXBlID09ICJ1cHBlciIpIHsNCiAgICBwX2J1aWx0aW4gPC0gMSAtIHBub3JtKHpzY29yZSkNCiAgICBjcml0X3ZhbCA8LSBxbm9ybSgxIC0gYWxwaGEpDQogIH0NCiAgDQogIA0KICAjIC0tLSBPdXRwdXQgUmVzdWx0cyAtLS0NCiAgY2F0KCI9PT0gVHdvIFNhbXBsZSBaLVRlc3QgPT09XG4iKQ0KICBjYXQoIlNhbXBsZSBtZWFuICh4zIQxKSAgID0iICxyb3VuZCh4YmFyMSwgNCksICJcbiIpDQogIGNhdCgiU2FtcGxlIG1lYW4gKHjMhDIpICAgPSIgLHJvdW5kKHhiYXIyLCA0KSwgIlxuIikNCiAgY2F0KCJaLXN0YXRpc3RpYyAgICAgICAgPSIsIHJvdW5kKHpzY29yZSwgNCksICJcbiIpDQogIGNhdCgicC12YWx1ZSAoVHJhcCkgICAgID0iLCByb3VuZChwX3RyYXAsIDUpLCAiXG4iKQ0KICBjYXQoInAtdmFsdWUgKHBub3JtKSAgICA9Iiwgcm91bmQocF9idWlsdGluLCA1KSwgIlxuIikNCiAgY2F0KCJhbHBoYSAgICAgICAgICAgICAgPSIsIGFscGhhLCAiXG4iKQ0KICBjYXQoIkNyaXRpY2FsIFogdmFsdWUgICA9Iiwgcm91bmQoY3JpdF92YWwsIDQpLCAiXG5cbiIpDQogIA0KICBpZiAocF9idWlsdGluIDwgYWxwaGEpIHsNCiAgICBjYXQoIj4+PiBSZWplY3QgSDAgKFNpZ25pZmljYW50KVxuIikNCiAgfSBlbHNlIHsNCiAgICBjYXQoIj4+PiBGYWlsIHRvIFJlamVjdCBIMCAoTm90IFNpZ25pZmljYW50KVxuIikNCiAgfQ0KfQ0KDQpUd29TYW1wbGVfWih4YmFyMSwgeGJhcjIsIHNkMSwgc2QyLCBuMSwgbjIpDQoNCmBgYA0KDQojIyAqKlR3byBzYW1wbGUgdC10ZXN0LCB2YXJpYW5jZSBpcyBlcXVhbCoqDQoNClRvIGZpbmQgb3V0IHdoZXRoZXIgYSBuZXcgc2VydW0gd2lsbCBhcnJlc3QgbGV1a2VtaWEsIDkgbWljZSwgYWxsIHdpdGggYW4gYWR2YW5jZWQgc3RhZ2Ugb2YgdGhlIGRpc2Vhc2UsIGFyZSBzZWxlY3RlZC4gRml2ZSBtaWNlIHJlY2VpdmUgdGhlIHRyZWF0bWVudCBhbmQgNCBkbyBub3QuIFN1cnZpdmFsIHRpbWVzLCBpbiB5ZWFycywgZnJvbSB0aGUgdGltZSB0aGUgZXhwZXJpbWVudCBjb21tZW5jZWQgYXJlIGFzIGZvbGxvd3M6IA0KDQpUcmVhdG1lbnQgPSAyLjEsIDUuMywgMS40LCA0LjYsIDAuOQ0KTm8gVHJlYXRtZW50ID0gMS45LCAwLjUsIDIuOCwgMy4xDQoNCkF0IHRoZSAwLjA1IGxldmVsIG9mIHNpZ25pZmljYW5jZSwgY2FuIHRoZSBzZXJ1bSBiZSBzYWlkIHRvIGJlIGVmZmVjdGl2ZT8gQXNzdW1lIHRoZSB0d28gcG9wdWxhdGlvbiB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZCB3aXRoIGVxdWFsIHZhcmlhbmNlcy4gDQpgYGB7cn0NCmRhdGExIDwtIGMoMi4xLCA1LjMsIDEuNCwgNC42LCAwLjkpDQpkYXRhMiA8LSBjKDEuOSwgMC41LCAyLjgsIDMuMSkNCg0KIyBIMCA6IFRoZSBzZXJ1bSBpcyBlZmZlY3RpdmUgKM68MSA9IM68MikNCiMgSDEgOiBUaGUgc2VydW0gaXMgbm90IGVmZmVjdGl2ZQ0KDQpUd29TYW1wbGVfdF9zYW1lIDwtIGZ1bmN0aW9uKHgxLCB4MiwgYWxwaGEgPSAwLjA1LCB0eXBlID0gInR3by50YWlsIiwgZDAgPSAwKSB7DQogIA0KICAjIC0tLSBkZWZpbmUgdGhlIHhiYXIsIHMsIGV0YyAtLS0NCiAgbjEgPSBsZW5ndGgoeDEpDQogIG4yID0gbGVuZ3RoICh4MikNCiAgeF9iYXIxID0gc3VtKHgxKS9uMQ0KICB4X2JhcjIgPSBzdW0oeDIpL24yDQogIHMxID0gc2QoeDEpDQogIHMyID0gc2QoeDIpDQogIHYgPSAobjEgKyBuMikgLSAyDQogIHNwXzIgPSAoKChuMSAtIDEpKnMxXjIpICsgKChuMiAtIDEpKnMyXjIpKSAvIHYNCiAgc3AgPSBzcXJ0KHNwXzIpDQogIA0KICAjIC0tLSBkZWZpbmUgdGhlIHRzY29yZSBhbmQgcGRmIC0tLQ0KICANCiAgdF9zY29yZSA9ICh4X2JhcjEgLSB4X2JhcjIgLSBkMCkgLyAoc3Aqc3FydCgoMS9uMSkrKDEvbjIpKSkNCiAgDQogIFBERl90IDwtIGZ1bmN0aW9uKHQsIHYpIHsNCiAgKGdhbW1hKCh2KzEpLzIpIC8gKHNxcnQodipwaSkgKiBnYW1tYSh2LzIpKSkgKiAoMSArICh0XjIpL3YpXigtKHYrMSkvMikNCn0NCiAgDQogICMgLS0tIFRyYXBlem9pZGFsIGZ1bmN0aW9uIHRvIGZpbmQgUERGIC0tLQ0KICB0cmFwIDwtIGZ1bmN0aW9uIChmLCBhLCBiLCBuID0gMTAwMCkgew0KICAgICAgaCA9IChiIC0gYSkgLyBuDQogICAgICBpbnRlZ3JhbCA9IChmKGEsIHYpICsgZihiLCB2KSkgLyAyDQogICAgICBmb3IgKGkgaW4gMToobi0xKSkgew0KICAgICAgICBpbnRlZ3JhbCA9IGludGVncmFsICsgZihhICsgaSAqIGgsIHYpDQogICAgICB9DQogICAgICANCiAgICAgIGludGVncmFsID0gaW50ZWdyYWwgKiBoIA0KICAgICAgcmV0dXJuKGludGVncmFsKQ0KICB9DQogIA0KICANCiAgIyAtLS0gTWFudWFsIGludGVncmF0aW9uIHVzaW5nIFRyYXBlem9pZGFsIC0tLQ0KICBpZiAodHlwZSA9PSAidHdvLnRhaWwiKSB7DQogICAgcF90cmFwIDwtIDIgKiB0cmFwKFBERl90LCBhYnModF9zY29yZSksIDEwMCkNCiAgfSBlbHNlIGlmICh0eXBlID09ICJsb3dlciIpIHsNCiAgICBwX3RyYXAgPC0gdHJhcChQREZfdCwgLTEwMCwgdF9zY29yZSkNCiAgfSBlbHNlIGlmICh0eXBlID09ICJ1cHBlciIpIHsNCiAgICBwX3RyYXAgPC0gdHJhcChQREZfdCwgdF9zY29yZSwgMTAwKQ0KICB9DQogIA0KICANCiAgIyAtLS0gQnVpbHQtaW4gcG5vcm0gY29tcGFyaXNvbiAtLS0NCiAgaWYgKHR5cGUgPT0gInR3by50YWlsIikgew0KICAgIHBfYnVpbHRpbiA8LSAyICogKDEgLSBwdChhYnModF9zY29yZSksdikpDQogICAgY3JpdF92YWwgPC0gcXQoMSAtIGFscGhhIC8gMix2KQ0KICB9IGVsc2UgaWYgKHR5cGUgPT0gImxvd2VyIikgew0KICAgIHBfYnVpbHRpbiA8LSBwdCh0X3Njb3JlLCB2KQ0KICAgIGNyaXRfdmFsIDwtIHF0KGFscGhhLHYpDQogIH0gZWxzZSBpZiAodHlwZSA9PSAidXBwZXIiKSB7DQogICAgcF9idWlsdGluIDwtIDEgLSBwdCh0X3Njb3JlLHYpDQogICAgY3JpdF92YWwgPC0gcXQoMSAtIGFscGhhLHYpDQogIH0NCiAgDQogIA0KICAjIC0tLSBPdXRwdXQgUmVzdWx0cyAtLS0NCiAgY2F0KCI9PT0gT25lIFNhbXBsZSBaLVRlc3QgPT09XG4iKQ0KICBjYXQoIlNhbXBsZSBtZWFuICh4zIQxKSAgICA9IiAscm91bmQoeF9iYXIxLCA0KSwgIlxuIikNCiAgY2F0KCJTYW1wbGUgbWVhbiAoeDIpICAgID0iICxyb3VuZCh4X2JhcjIsIDQpLCAiXG4iKQ0KICBjYXQoIlBvcHVsYXRpb24gbWVhbiDOvCAgPSIsIG1pdSwgIlxuIikNCiAgY2F0KCJ0LXN0YXRpc3RpYyAgICAgICAgPSIsIHJvdW5kKHRfc2NvcmUsIDQpLCAiXG4iKQ0KICBjYXQoInAtdmFsdWUgKFRyYXApICAgICA9Iiwgcm91bmQocF90cmFwLCA1KSwgIlxuIikNCiAgY2F0KCJwLXZhbHVlIChwbm9ybSkgICAgPSIsIHJvdW5kKHBfYnVpbHRpbiwgNSksICJcbiIpDQogIGNhdCgiYWxwaGEgICAgICAgICAgICAgID0iLCBhbHBoYSwgIlxuIikNCiAgY2F0KCJDcml0aWNhbCB0IHZhbHVlICAgPSIsIHJvdW5kKGNyaXRfdmFsLCA0KSwgIlxuXG4iKQ0KICANCiAgaWYgKHBfYnVpbHRpbiA8IGFscGhhKSB7DQogICAgY2F0KCI+Pj4gUmVqZWN0IEgwIChTaWduaWZpY2FudClcbiIpDQogIH0gZWxzZSB7DQogICAgY2F0KCI+Pj4gRmFpbCB0byBSZWplY3QgSDAgKE5vdCBTaWduaWZpY2FudClcbiIpDQogIH0NCn0NCg0KVHdvU2FtcGxlX3Rfc2FtZShkYXRhMSwgZGF0YTIpDQpgYGANCg0KIyMgKipUd28gc2FtcGxlIHQtdGVzdCwgdmFyaWFuY2UgaXMgbm90IGVxdWFsKioNCg0KQSBzdHVkeSB3YXMgY29uZHVjdGVkIGJ5IHRoZSBEZXBhcnRtZW50IG9mIFpvb2xvZ3kgYXQgVmlyZ2luaWEgVGVjaCB0byBkZXRlcm1pbmUgaWYgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHRoZSBkZW5zaXR5IG9mIG9yZ2FuaXNtcyBhdCB0d28gZGlmZmVyZW50IHN0YXRpb25zIGxvY2F0ZWQgb24gQ2VkYXIgUnVuLCBhIHNlY29uZGFyeSBzdHJlYW0gaW4gdGhlIFJvYW5va2UgUml2ZXIgZHJhaW5hZ2UgYmFzaW4uIFNld2FnZSBmcm9tIGEgc2V3YWdlIHRyZWF0bWVudCBwbGFudCBhbmQgb3ZlcmZsb3cgZnJvbSB0aGUgRmVkZXJhbCBNb2d1bCBDb3Jwb3JhdGlvbiBzZXR0bGluZyBwb25kIGVudGVyIHRoZSBzdHJlYW0gbmVhciBpdHMgaGVhZHdhdGVycy4gVGhlIGZvbGxvd2luZyBkYXRhIGdpdmUgdGhlIGRlbnNpdHkgbWVhc3VyZW1lbnRzLCBpbiBudW1iZXIgb2Ygb3JnYW5pc21zIHBlciBzcXVhcmUgbWV0ZXIsIGF0IHRoZSB0d28gY29sbGVjdGluZyBzdGF0aW9ucw0KDQpTdGF0aW9uIDEgPSA1MDMwLCAxMzcwMCwgMTA3MzAsIDExNDAwLCA4NjAsIDIyMDAsIDQyNTAsIDE1MDQwLCA0OTgwLCAxMTkxMCwgODEzMCwgMjY4NTAsIDE3NjYwLCAyMjgwMCwgMTEzMCwgMTY5MA0KU3RhdGlvbiAyID0gMjgwMCwgNDY3MCwgNjg5MCwgNzcyMCwgNzAzMCwgNzMzMCwgMjgxMCwgMTMzMCwgMzMyMCwgMTIzMCwgMjEzMCwgMjE5MA0KDQpDYW4gd2UgY29uY2x1ZGUsIGF0IHRoZSAwLjA1IGxldmVsIG9mIHNpZ25pZmljYW5jZSwgdGhhdCB0aGUgYXZlcmFnZSBkZW5zaXRpZXMgYXQgdGhlIHR3byBzdGF0aW9ucyBhcmUgZXF1YWw/IEFzc3VtZSB0aGF0IHRoZSBvYnNlcnZhdGlvbnMgY29tZSBmcm9tIG5vcm1hbCBwb3B1bGF0aW9ucyB3aXRoIGRpZmZlcmVudCB2YXJpYW5jZXMuDQoNCmBgYHtyfQ0Kc3RhdGlvbjEgPC0gYyg1MDMwLCAxMzcwMCwgMTA3MzAsIDExNDAwLCA4NjAsIDIyMDAsIDQyNTAsIDE1MDQwLCA0OTgwLCAxMTkxMCwgODEzMCwgMjY4NTAsIDE3NjYwLCAyMjgwMCwgMTEzMCwgMTY5MCkNCnN0YXRpb24yIDwtIGMoMjgwMCwgNDY3MCwgNjg5MCwgNzcyMCwgNzAzMCwgNzMzMCwgMjgxMCwgMTMzMCwgMzMyMCwgMTIzMCwgMjEzMCwgMjE5MCkNCg0KVHdvU2FtcGxlX3RfZGlmZiA8LSBmdW5jdGlvbih4MSwgeDIsIGFscGhhID0gMC4wNSwgdHlwZSA9ICJ0d28udGFpbCIsIGQwID0gMCkgew0KICANCiAgIyAtLS0gZGVmaW5lIHRoZSB4YmFyLCBzLCBldGMgLS0tDQogIG4xID0gbGVuZ3RoKHgxKQ0KICBuMiA9IGxlbmd0aCAoeDIpDQogIHhfYmFyMSA9IHN1bSh4MSkvbjENCiAgeF9iYXIyID0gc3VtKHgyKS9uMg0KICBzMSA9IHNkKHgxKQ0KICBzMiA9IHNkKHgyKQ0KICBhID0gKChzMV4yL24xKSArIChzMl4yL24yKSleMg0KICBiID0gKCgoczFeMi9uMSleMikvKG4xLTEpKSArICgoKHMyXjIvbjIpXjIpLyhuMi0xKSkNCiAgdiA9IGEvYg0KICANCiAgDQogICMgLS0tIGRlZmluZSB0aGUgdHNjb3JlIGFuZCBwZGYgLS0tDQogIA0KICB0X3Njb3JlID0gKCh4X2JhcjEgLSB4X2JhcjIpIC0gZDApIC8gKHNxcnQoKHMxXjIvbjEpICsgKHMyXjIvbjIpKSkNCiAgDQogIFBERl90IDwtIGZ1bmN0aW9uKHQsIHYpIHsNCiAgKGdhbW1hKCh2KzEpLzIpIC8gKHNxcnQodipwaSkgKiBnYW1tYSh2LzIpKSkgKiAoMSArICh0XjIpL3YpXigtKHYrMSkvMikNCn0NCiAgDQogICMgLS0tIFRyYXBlem9pZGFsIGZ1bmN0aW9uIHRvIGZpbmQgUERGIC0tLQ0KICB0cmFwIDwtIGZ1bmN0aW9uIChmLCBhLCBiLCBuID0gMTAwMCkgew0KICAgICAgaCA9IChiIC0gYSkgLyBuDQogICAgICBpbnRlZ3JhbCA9IChmKGEsIHYpICsgZihiLCB2KSkgLyAyDQogICAgICBmb3IgKGkgaW4gMToobi0xKSkgew0KICAgICAgICBpbnRlZ3JhbCA9IGludGVncmFsICsgZihhICsgaSAqIGgsIHYpDQogICAgICB9DQogICAgICANCiAgICAgIGludGVncmFsID0gaW50ZWdyYWwgKiBoIA0KICAgICAgcmV0dXJuKGludGVncmFsKQ0KICB9DQogIA0KICANCiAgIyAtLS0gTWFudWFsIGludGVncmF0aW9uIHVzaW5nIFRyYXBlem9pZGFsIC0tLQ0KICBpZiAodHlwZSA9PSAidHdvLnRhaWwiKSB7DQogICAgcF90cmFwIDwtIDIgKiB0cmFwKFBERl90LCBhYnModF9zY29yZSksIDEwMCkNCiAgfSBlbHNlIGlmICh0eXBlID09ICJsb3dlciIpIHsNCiAgICBwX3RyYXAgPC0gdHJhcChQREZfdCwgLTEwMCwgdF9zY29yZSkNCiAgfSBlbHNlIGlmICh0eXBlID09ICJ1cHBlciIpIHsNCiAgICBwX3RyYXAgPC0gdHJhcChQREZfdCwgdF9zY29yZSwgMTAwKQ0KICB9DQogIA0KICANCiAgIyAtLS0gQnVpbHQtaW4gcG5vcm0gY29tcGFyaXNvbiAtLS0NCiAgaWYgKHR5cGUgPT0gInR3by50YWlsIikgew0KICAgIHBfYnVpbHRpbiA8LSAyICogKDEgLSBwdChhYnModF9zY29yZSksdikpDQogICAgY3JpdF92YWwgPC0gcXQoMSAtIGFscGhhIC8gMix2KQ0KICB9IGVsc2UgaWYgKHR5cGUgPT0gImxvd2VyIikgew0KICAgIHBfYnVpbHRpbiA8LSBwdCh0X3Njb3JlLCB2KQ0KICAgIGNyaXRfdmFsIDwtIHF0KGFscGhhLHYpDQogIH0gZWxzZSBpZiAodHlwZSA9PSAidXBwZXIiKSB7DQogICAgcF9idWlsdGluIDwtIDEgLSBwdCh0X3Njb3JlLHYpDQogICAgY3JpdF92YWwgPC0gcXQoMSAtIGFscGhhLHYpDQogIH0NCiAgDQogIA0KICAjIC0tLSBPdXRwdXQgUmVzdWx0cyAtLS0NCiAgY2F0KCI9PT0gT25lIFNhbXBsZSBaLVRlc3QgPT09XG4iKQ0KICBjYXQoIlNhbXBsZSBtZWFuICh4zIQxKSAgICA9IiAscm91bmQoeF9iYXIxLCA0KSwgIlxuIikNCiAgY2F0KCJTYW1wbGUgbWVhbiAoeDIpICAgID0iICxyb3VuZCh4X2JhcjIsIDQpLCAiXG4iKQ0KICBjYXQoIlBvcHVsYXRpb24gbWVhbiDOvCAgPSIsIG1pdSwgIlxuIikNCiAgY2F0KCJ0LXN0YXRpc3RpYyAgICAgICAgPSIsIHJvdW5kKHRfc2NvcmUsIDQpLCAiXG4iKQ0KICBjYXQoInAtdmFsdWUgKFRyYXApICAgICA9Iiwgcm91bmQocF90cmFwLCA1KSwgIlxuIikNCiAgY2F0KCJwLXZhbHVlIChwbm9ybSkgICAgPSIsIHJvdW5kKHBfYnVpbHRpbiwgNSksICJcbiIpDQogIGNhdCgiYWxwaGEgICAgICAgICAgICAgID0iLCBhbHBoYSwgIlxuIikNCiAgY2F0KCJDcml0aWNhbCB0IHZhbHVlICAgPSIsIHJvdW5kKGNyaXRfdmFsLCA0KSwgIlxuXG4iKQ0KICANCiAgaWYgKHBfYnVpbHRpbiA8IGFscGhhKSB7DQogICAgY2F0KCI+Pj4gUmVqZWN0IEgwIChTaWduaWZpY2FudClcbiIpDQogIH0gZWxzZSB7DQogICAgY2F0KCI+Pj4gRmFpbCB0byBSZWplY3QgSDAgKE5vdCBTaWduaWZpY2FudClcbiIpDQogIH0NCn0NCg0KVHdvU2FtcGxlX3RfZGlmZihzdGF0aW9uMSwgc3RhdGlvbjIpDQpgYGANCg0K