library(ggplot2)
library(patchwork)  
library(mvtnorm)  
set.seed(431)

One Metropolis–Hastings update step

MHstep <- function(theta_current, sig) {
  theta_star <- rnorm(1, mean = theta_current, sd = sig)  # propose candidate θ*
  accprob <- targetdist(theta_star) / targetdist(theta_current)  # acceptance probability
  accprob <- min(1, accprob)
  # accept or reject
  u <- runif(1)
  if (u <= accprob) {
    theta_next <- theta_star
    a <- 1
  } else {
    theta_next <- theta_current
    a <- 0
  }
  return(list(theta1 = theta_next, a = a))
}

Metropolis–Hastings Sampler

MH_sampler <- function(nsamp, sig, burnin, lag, theta_current) {
  theta_samples <- numeric(nsamp)
  acc <- c(accepted = 0, proposed = 0)
  theta <- theta_current   # starting value
  # Burn-in
  for (i in 1:burnin) {
    step <- MHstep(theta, sig)
    theta <- step$theta1
    acc <- acc + c(step$a, 1)
  }
  # Main sampling
  for (i in 1:nsamp) {
    for (j in 1:lag) {
      step <- MHstep(theta, sig)
      theta <- step$theta1
      acc <- acc + c(step$a, 1)
    }
    theta_samples[i] <- theta
  }
  return(list(samples = theta_samples, acc = acc))
}

Visualization function

plot_MH <- function(sig, nsamp = NULL, theta_initial = NULL) {
  
  # Pull global defaults if user does not override
  if (is.null(nsamp)) nsamp <- get("nsamp", envir = .GlobalEnv)
  if (is.null(theta_initial)) theta_initial <- get("theta_initial", envir = .GlobalEnv)
  
  # Run MH sampler
  result <- MH_sampler(
    nsamp = nsamp,
    sig = sig,
    burnin = burnin,
    lag = lag,
    theta_current = theta_initial   # pass renamed argument to MH sampler
  )
  
  theta_vals <- result$samples
  
  # True normalized density
  thetas <- seq(-3, 3, length.out = 500)
  dens <- targetdist(thetas)
  dens <- dens / sum(dens) / (thetas[2] - thetas[1])
  
  df_samples <- data.frame(theta = theta_vals)
  df_true    <- data.frame(theta = thetas, y = dens)
  
  # Histogram + True Density 
 p1 <- ggplot() +
  geom_histogram(data = df_samples,
                 aes(theta, y = ..density.., fill = "Samples"),
                 bins = 30, color = "black") +
  geom_line(data = df_true,
            aes(theta, y, color = "True Density"),
            size = 1.1) +
  scale_color_manual(values = c("True Density" = "red")) +
  scale_fill_manual(values = c("Samples" = "gray80")) +
  labs(
    title = paste0("Metropolis–Hastings Sampling (σ = ", sig, ")"),
    subtitle = paste0(
      "burn-in = ", burnin,
      ",  nsamp = ", nsamp,
      ",  initial θ = ", theta_initial
    ),
    x = expression(theta), y = "density",
    color = "", fill = ""
  ) +
  theme_bw(base_size = 14)

  
  # ---------------- Trace Plot ----------------
  df_trace <- data.frame(iter = 1:length(theta_vals), value = theta_vals)
  
  p2 <- ggplot(df_trace, aes(iter, value)) +
    geom_line(color = "black") +
    labs(
      title = "Trace Plot",
      subtitle = paste0(
        "burn-in = ", burnin,
        ",  kept samples = ", nsamp,
        ",  initial θ = ", theta_initial
      ),
      y = expression(theta~value),
      x = "iteration"
    ) +
    theme_bw(base_size = 14)
  
  # Return stacked plots
  p1 / p2
}

Example

set.seed(431)
#   Target distribution (unnormalized)
targetdist <- function(theta) {
  exp(-theta^4/6 + theta^2/2) * cos(theta^3/4)
}
burnin <- 8000
lag <- 1
nsamp <- 50000
theta_initial <- 0   

# global default
#plot_MH(sig = 0.1)
#plot_MH(sig = 1)
#plot_MH(sig = 10)
# 1. Well-tuned, centered start
plot_MH(sig = 1, nsamp = 3000, theta_initial = 0)

# 2. Same σ, bad initial value 
plot_MH(sig = 1, nsamp = 3000, theta_initial = 6)

# 3. Smaller step size, slower mixing
plot_MH(sig = 0.01, nsamp = 3000, theta_initial = 0)

Gibbs Sampler for Normal Model with Semi-Conjugate Priors

# Data summary
n    <- 24
ybar <- 7.8730           # sample mean
s     <- 0.05353         # sample sd

### Prior parameters
mu0       <- 7.9876      # prior mean for mu
sigma0.2  <- 0.000625    # prior variance of mu
alpha     <- 2.5         # IG(alpha, beta)
beta      <- 0.0043

#  Run Gibbs sampler
Nsim <- 100000               # total draws
mus <- numeric(Nsim)         # store mu draws
sigma2 <- numeric(Nsim)      # store sigma^2 draws

## Initial values
mus[1] <- 8
SSE1   <- (n-1)*s^2 + n*(ybar - mus[1])^2
sigma2[1] <- 1 / rgamma(1, n/2 + alpha, SSE1/2 + beta)

## Gibbs updates
for (k in 2:Nsim) {
  
  ### 1. Sample mu | sigma^2, y
  var_mu  <- 1 / (n / sigma2[k-1] + 1 / sigma0.2)
  mean_mu <- var_mu * (n*ybar / sigma2[k-1] + mu0 / sigma0.2)
  mus[k] <- rnorm(1, mean_mu, sqrt(var_mu))
  
  ### 2. Sample sigma^2 | mu, y
  SSE <- (n-1)*s^2 + n*(ybar - mus[k])^2
  sigma2[k] <- 1 / rgamma(1, n/2 + alpha, SSE/2 + beta)
}


#  Posterior summaries
cat("Posterior mean(mu):", mean(mus), "\n")
Posterior mean(mu): 7.893102 
cat("Posterior sd(mu):",   sd(mus), "\n")
Posterior sd(mu): 0.01170627 
cat("95% CI for mu:\n"); print(quantile(mus, c(0.025, 0.975)))
95% CI for mu:
    2.5%    97.5% 
7.871854 7.917967 
cat("\nPosterior mean(sigma^2):", mean(sigma2), "\n")

Posterior mean(sigma^2): 0.003244212 
cat("95% CI for sigma^2:\n"); print(quantile(sigma2, c(0.025, 0.975)))
95% CI for sigma^2:
       2.5%       97.5% 
0.001803182 0.005834502 
#  Visualize first few Gibbs steps
maxit <- 20
plot(mus[1:maxit], sigma2[1:maxit], type = "n",
     xlab = expression(mu), ylab = expression(sigma^2),
     main = "First 20 Gibbs Iterations")
arrows(mus[1:(maxit-1)], sigma2[1:(maxit-1)],
       mus[2:maxit], sigma2[2:maxit],
       length = 0.1, angle = 30, col = rainbow(maxit-1))
points(mus[1:maxit], sigma2[1:maxit], pch = 20)


#  Trace plots
trace_mu <- ggplot(data.frame(iter = 1:Nsim, mu = mus),
                   aes(iter, mu)) +
  geom_line(color = "steelblue") +
  labs(title = "Trace Plot for μ",
       x = "Iteration", y = expression(mu)) +
  theme_bw(14)
trace_sigma2 <- ggplot(data.frame(iter = 1:Nsim, sigma2 = sigma2),
                       aes(iter, sigma2)) +
  geom_line(color = "firebrick") +
  labs(title = expression("Trace Plot for " * sigma^2),
       x = "Iteration", y = expression(sigma^2)) +
  theme_bw(14)

#  Posterior density plots
dens_mu <- ggplot(data.frame(mu = mus), aes(mu)) +
  geom_density(fill = "steelblue", alpha = 0.4) +
  geom_vline(xintercept = mean(mus), color = "blue", linetype = 2) +
  labs(title = "Posterior Density of μ",
       x = expression(mu), y = "Density") +
  theme_bw(14)
dens_sigma2 <- ggplot(data.frame(sigma2 = sigma2), aes(sigma2)) +
  geom_density(fill = "firebrick", alpha = 0.4) +
  geom_vline(xintercept = mean(sigma2), color = "red", linetype = 2) +
  labs(title = "Posterior Density of σ²",
       x = expression(sigma^2), y = "Density") +
  theme_bw(14)

#  Joint posterior (μ, σ²)
df_post <- data.frame(mu = mus, sigma2 = sigma2)
joint_contour <- ggplot(df_post, aes(mu, sigma2)) +
  stat_density_2d(aes(fill = ..level..), geom = "polygon", alpha = 0.6) +
  scale_fill_viridis_c() +
  labs(title = "Posterior Joint Density of (μ, σ²)",
       x = expression(mu), y = expression(sigma^2)) +
  theme_bw(14)
joint_heatmap <- ggplot(df_post, aes(mu, sigma2)) +
  stat_density_2d_filled(contour_var = "density") +
  labs(title = "Posterior Joint Density Heatmap",
       x = expression(mu), y = expression(sigma^2)) +
  theme_bw(14)


#  Plot combined panels
( trace_mu | trace_sigma2 ) / ( dens_mu | dens_sigma2 )

joint_contour

joint_heatmap

MH Sampler

set.seed(431)
## Log-posterior for (mu, log_sigma2)
log_post <- function(mu, log_sigma2) {
  sigma2 <- exp(log_sigma2)
  
  # SSE(mu) using sufficient stats
  SSE <- (n - 1)*s^2 + n*(ybar - mu)^2
  
  # log-likelihood: N(mu, sigma2) for n observations
  lp_y <- -(n/2) * log(2*pi*sigma2) - SSE/(2*sigma2)
  
  # prior for mu ~ N(mu0, sigma0^2)
  lp_mu <- dnorm(mu, mean = mu0, sd = sqrt(sigma0.2), log = TRUE)
  
  # prior for sigma2 ~ IG(alpha, beta), up to constants:
  # p(sigma2) ∝ (sigma2)^-(alpha+1) exp(-beta/sigma2)
  lp_s2 <- -(alpha + 1)*log(sigma2) - beta/sigma2
  
  # Jacobian for transform sigma2 = exp(log_sigma2)
  lp_jac <- log_sigma2
  return(lp_y + lp_mu + lp_s2 + lp_jac)
} 
  
  
mh_sampler <- function(Nsim, start_mu, start_log_s2,
                       prop_sd_mu, prop_sd_log_s2) {
  mu     <- numeric(Nsim)
  log_s2 <- numeric(Nsim)
  mu[1]     <- start_mu
  log_s2[1] <- start_log_s2
  acc <- 0
  
  for (k in 2:Nsim) {
    # Propose new (mu, log_sigma2) with Gaussian random walk
    mu_prop     <- rnorm(1, mean = mu[k-1],     sd = prop_sd_mu)
    log_s2_prop <- rnorm(1, mean = log_s2[k-1], sd = prop_sd_log_s2)
    
    # Log acceptance ratio (symmetric proposal ⇒ q cancels)
    log_alpha <- log_post(mu_prop, log_s2_prop) -
                 log_post(mu[k-1], log_s2[k-1])
    
    if (log(runif(1)) < log_alpha) {
      # accept
      mu[k]     <- mu_prop
      log_s2[k] <- log_s2_prop
      acc <- acc + 1
    } else {
      # reject (stay at previous)
      mu[k]     <- mu[k-1]
      log_s2[k] <- log_s2[k-1]
    }
  }
  
  list(mu = mu,
       sigma2 = exp(log_s2),
       acc_rate = acc / (Nsim - 1))
}

# Use Gibbs initial sigma2[1] as starting point for MH
mh_out <- mh_sampler(
  Nsim          = Nsim,
  start_mu      = mus[1],
  start_log_s2  = log(sigma2[1]),
  prop_sd_mu    = 0.005,   # tune these
  prop_sd_log_s2 = 0.05
)

mh_out$acc_rate   # check acceptance rate; aim ~ 0.2–0.5
[1] 0.8239982

Comparsion Plots

library(ggplot2)
library(patchwork)

df_comp <- data.frame(
  iter          = 1:Nsim,
  gibbs_mu      = mus,
  mh_mu         = mh_out$mu,
  gibbs_sigma2  = sigma2,
  mh_sigma2     = mh_out$sigma2
)

# Trace Plot
trace_mu_both <- ggplot(df_comp) +
  geom_line(aes(iter, gibbs_mu, colour = "Gibbs")) +
  geom_line(aes(iter, mh_mu,    colour = "MH"), alpha = 0.7) +
  scale_colour_manual(values = c("Gibbs" = "steelblue",
                                 "MH"    = "orange")) +
  labs(title = "Trace Plot for μ: Gibbs vs MH",
       x = "Iteration", y = expression(mu), colour = "") +
  theme_bw(14)
trace_s2_both <- ggplot(df_comp) +
  geom_line(aes(iter, gibbs_sigma2, colour = "Gibbs")) +
  geom_line(aes(iter, mh_sigma2,    colour = "MH"), alpha = 0.7) +
  scale_colour_manual(values = c("Gibbs" = "firebrick",
                                 "MH"    = "darkgreen")) +
  labs(title = expression("Trace Plot for " * sigma^2 * ": Gibbs vs MH"),
       x = "Iteration", y = expression(sigma^2), colour = "") +
  theme_bw(14)
trace_mu_both / trace_s2_both



# Density comparison
dens_mu_both <- ggplot(df_comp) +
  geom_density(aes(gibbs_mu, colour = "Gibbs"), adjust = 1.2) +
  geom_density(aes(mh_mu,    colour = "MH"),    adjust = 1.2, linetype = 2) +
  scale_colour_manual(values = c("Gibbs" = "steelblue",
                                 "MH"    = "orange")) +
  labs(title = "Posterior of μ: Gibbs vs MH",
       x = expression(mu), y = "Density", colour = "") +
  theme_bw(14)
dens_s2_both <- ggplot(df_comp) +
  geom_density(aes(gibbs_sigma2, colour = "Gibbs"), adjust = 1.2) +
  geom_density(aes(mh_sigma2,    colour = "MH"),    adjust = 1.2, linetype = 2) +
  scale_colour_manual(values = c("Gibbs" = "firebrick",
                                 "MH"    = "darkgreen")) +
  labs(title = expression("Posterior of " * sigma^2 * ": Gibbs vs MH"),
       x = expression(sigma^2), y = "Density", colour = "") +
  theme_bw(14)
dens_mu_both | dens_s2_both




# --- Gibbs heatmap 
mh_mu_q  <- quantile(df_comp$mh_mu,     probs = c(0.005, 0.995))
mh_s2_q  <- quantile(df_comp$mh_sigma2, probs = c(0.005, 0.995))
zoom_x <- c(mh_mu_q[1], mh_mu_q[2])
zoom_y <- c(mh_s2_q[1], mh_s2_q[2])
heat_gibbs_zoom <- ggplot(df_comp, aes(gibbs_mu, gibbs_sigma2)) +
  stat_density_2d_filled(contour_var = "density", alpha = 0.9) +
  stat_density_2d(color = "white", linewidth = 0.4) +
  scale_fill_viridis_d(option = "C") +
  coord_cartesian(xlim = zoom_x, ylim = zoom_y, expand = FALSE) +
  labs(
    title = "Joint Posterior Heatmap (Gibbs)",
    x = expression(mu),
    y = expression(sigma^2),
    fill = "Density Level"
  ) +
  theme_bw(base_size = 16) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18),
    axis.text  = element_text(size = 14),
    legend.title = element_text(size = 14),
    legend.text  = element_text(size = 12),
    panel.border = element_rect(linewidth = 0.8, color = "black"),
    panel.grid = element_blank()
  )
heat_gibbs_zoom



# MH heatmap 

heat_mh_zoom <- ggplot(df_comp, aes(mh_mu, mh_sigma2)) +
  stat_density_2d_filled(contour_var = "density", alpha = 0.9) +
  stat_density_2d(color = "white", linewidth = 0.4) +
  scale_fill_viridis_d(option = "C") +
  coord_cartesian(xlim = zoom_x, ylim = zoom_y, expand = FALSE) +
  labs(
    title = "Joint Posterior Heatmap (MH)",
    x = expression(mu),
    y = expression(sigma^2),
    fill = "Density Level"
  ) +
  theme_bw(base_size = 16) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5),
    axis.title = element_text(size = 18),
    axis.text  = element_text(size = 14),
    legend.title = element_text(size = 14),
    legend.text  = element_text(size = 12),
    panel.border = element_rect(linewidth = 0.8, color = "black"),
    panel.grid = element_blank()
  )
heat_mh_zoom

# Set layout: 1 row, 2 columns
par(mfrow = c(1, 2), mar = c(5, 5, 4, 2))

# ------------------------------
# Panel 1: Posterior of μ
# ------------------------------
dens_gibbs_mu <- density(df_comp$gibbs_mu)
dens_mh_mu    <- density(df_comp$mh_mu)

plot(dens_gibbs_mu,
     main = "Posterior of μ: Gibbs vs MH",
     xlab = expression(mu),
     ylab = "Density",
     col  = "steelblue",
     lwd  = 2,
     lty  = 1,          # solid
     cex.lab = 1.3,
     cex.main = 1.4)

lines(dens_mh_mu,
      col = "orange",
      lwd = 2,
      lty = 2)          # dashed

legend("topright",
       legend = c("Gibbs (solid)", "MH (dashed)"),
       col = c("steelblue", "orange"),
       lwd = 2,
       lty = c(1, 2),
       bty = "n",
       cex = 1.1)

# ------------------------------
# Panel 2: Posterior of σ²
# ------------------------------
dens_gibbs_s2 <- density(df_comp$gibbs_sigma2)
dens_mh_s2    <- density(df_comp$mh_sigma2)

plot(dens_gibbs_s2,
     main = expression("Posterior of " * sigma^2 * ": Gibbs vs MH"),
     xlab = expression(sigma^2),
     ylab = "Density",
     col  = "firebrick",
     lwd  = 2,
     lty  = 1,          # solid
     cex.lab = 1.3,
     cex.main = 1.4)

lines(dens_mh_s2,
      col = "darkgreen",
      lwd = 2,
      lty = 2)          # dashed

legend("topright",
       legend = c("Gibbs (solid)", "MH (dashed)"),
       col = c("firebrick", "darkgreen"),
       lwd = 2,
       lty = c(1, 2),
       bty = "n",
       cex = 1.1)

# Restore default layout
par(mfrow = c(1, 1))

LS0tCnRpdGxlOiAiTUggQWxnbyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwYXRjaHdvcmspICAKbGlicmFyeShtdnRub3JtKSAgCnNldC5zZWVkKDQzMSkKYGBgCgojIyMgICBPbmUgTWV0cm9wb2xpc+KAk0hhc3RpbmdzIHVwZGF0ZSBzdGVwCmBgYHtyfQpNSHN0ZXAgPC0gZnVuY3Rpb24odGhldGFfY3VycmVudCwgc2lnKSB7CiAgdGhldGFfc3RhciA8LSBybm9ybSgxLCBtZWFuID0gdGhldGFfY3VycmVudCwgc2QgPSBzaWcpICAjIHByb3Bvc2UgY2FuZGlkYXRlIM64KgogIGFjY3Byb2IgPC0gdGFyZ2V0ZGlzdCh0aGV0YV9zdGFyKSAvIHRhcmdldGRpc3QodGhldGFfY3VycmVudCkgICMgYWNjZXB0YW5jZSBwcm9iYWJpbGl0eQogIGFjY3Byb2IgPC0gbWluKDEsIGFjY3Byb2IpCiAgIyBhY2NlcHQgb3IgcmVqZWN0CiAgdSA8LSBydW5pZigxKQogIGlmICh1IDw9IGFjY3Byb2IpIHsKICAgIHRoZXRhX25leHQgPC0gdGhldGFfc3RhcgogICAgYSA8LSAxCiAgfSBlbHNlIHsKICAgIHRoZXRhX25leHQgPC0gdGhldGFfY3VycmVudAogICAgYSA8LSAwCiAgfQogIHJldHVybihsaXN0KHRoZXRhMSA9IHRoZXRhX25leHQsIGEgPSBhKSkKfQpgYGAKCgojIyMgIE1ldHJvcG9saXPigJNIYXN0aW5ncyBTYW1wbGVyCmBgYHtyfQpNSF9zYW1wbGVyIDwtIGZ1bmN0aW9uKG5zYW1wLCBzaWcsIGJ1cm5pbiwgbGFnLCB0aGV0YV9jdXJyZW50KSB7CiAgdGhldGFfc2FtcGxlcyA8LSBudW1lcmljKG5zYW1wKQogIGFjYyA8LSBjKGFjY2VwdGVkID0gMCwgcHJvcG9zZWQgPSAwKQogIHRoZXRhIDwtIHRoZXRhX2N1cnJlbnQgICAjIHN0YXJ0aW5nIHZhbHVlCiAgIyBCdXJuLWluCiAgZm9yIChpIGluIDE6YnVybmluKSB7CiAgICBzdGVwIDwtIE1Ic3RlcCh0aGV0YSwgc2lnKQogICAgdGhldGEgPC0gc3RlcCR0aGV0YTEKICAgIGFjYyA8LSBhY2MgKyBjKHN0ZXAkYSwgMSkKICB9CiAgIyBNYWluIHNhbXBsaW5nCiAgZm9yIChpIGluIDE6bnNhbXApIHsKICAgIGZvciAoaiBpbiAxOmxhZykgewogICAgICBzdGVwIDwtIE1Ic3RlcCh0aGV0YSwgc2lnKQogICAgICB0aGV0YSA8LSBzdGVwJHRoZXRhMQogICAgICBhY2MgPC0gYWNjICsgYyhzdGVwJGEsIDEpCiAgICB9CiAgICB0aGV0YV9zYW1wbGVzW2ldIDwtIHRoZXRhCiAgfQogIHJldHVybihsaXN0KHNhbXBsZXMgPSB0aGV0YV9zYW1wbGVzLCBhY2MgPSBhY2MpKQp9CmBgYAoKCiMjIyAgVmlzdWFsaXphdGlvbiBmdW5jdGlvbgoKCmBgYHtyfQpwbG90X01IIDwtIGZ1bmN0aW9uKHNpZywgbnNhbXAgPSBOVUxMLCB0aGV0YV9pbml0aWFsID0gTlVMTCkgewogIAogICMgUHVsbCBnbG9iYWwgZGVmYXVsdHMgaWYgdXNlciBkb2VzIG5vdCBvdmVycmlkZQogIGlmIChpcy5udWxsKG5zYW1wKSkgbnNhbXAgPC0gZ2V0KCJuc2FtcCIsIGVudmlyID0gLkdsb2JhbEVudikKICBpZiAoaXMubnVsbCh0aGV0YV9pbml0aWFsKSkgdGhldGFfaW5pdGlhbCA8LSBnZXQoInRoZXRhX2luaXRpYWwiLCBlbnZpciA9IC5HbG9iYWxFbnYpCiAgCiAgIyBSdW4gTUggc2FtcGxlcgogIHJlc3VsdCA8LSBNSF9zYW1wbGVyKAogICAgbnNhbXAgPSBuc2FtcCwKICAgIHNpZyA9IHNpZywKICAgIGJ1cm5pbiA9IGJ1cm5pbiwKICAgIGxhZyA9IGxhZywKICAgIHRoZXRhX2N1cnJlbnQgPSB0aGV0YV9pbml0aWFsICAgIyBwYXNzIHJlbmFtZWQgYXJndW1lbnQgdG8gTUggc2FtcGxlcgogICkKICAKICB0aGV0YV92YWxzIDwtIHJlc3VsdCRzYW1wbGVzCiAgCiAgIyBUcnVlIG5vcm1hbGl6ZWQgZGVuc2l0eQogIHRoZXRhcyA8LSBzZXEoLTMsIDMsIGxlbmd0aC5vdXQgPSA1MDApCiAgZGVucyA8LSB0YXJnZXRkaXN0KHRoZXRhcykKICBkZW5zIDwtIGRlbnMgLyBzdW0oZGVucykgLyAodGhldGFzWzJdIC0gdGhldGFzWzFdKQogIAogIGRmX3NhbXBsZXMgPC0gZGF0YS5mcmFtZSh0aGV0YSA9IHRoZXRhX3ZhbHMpCiAgZGZfdHJ1ZSAgICA8LSBkYXRhLmZyYW1lKHRoZXRhID0gdGhldGFzLCB5ID0gZGVucykKICAKICAjIEhpc3RvZ3JhbSArIFRydWUgRGVuc2l0eSAKIHAxIDwtIGdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gZGZfc2FtcGxlcywKICAgICAgICAgICAgICAgICBhZXModGhldGEsIHkgPSAuLmRlbnNpdHkuLiwgZmlsbCA9ICJTYW1wbGVzIiksCiAgICAgICAgICAgICAgICAgYmlucyA9IDMwLCBjb2xvciA9ICJibGFjayIpICsKICBnZW9tX2xpbmUoZGF0YSA9IGRmX3RydWUsCiAgICAgICAgICAgIGFlcyh0aGV0YSwgeSwgY29sb3IgPSAiVHJ1ZSBEZW5zaXR5IiksCiAgICAgICAgICAgIHNpemUgPSAxLjEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiVHJ1ZSBEZW5zaXR5IiA9ICJyZWQiKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIlNhbXBsZXMiID0gImdyYXk4MCIpKSArCiAgbGFicygKICAgIHRpdGxlID0gcGFzdGUwKCJNZXRyb3BvbGlz4oCTSGFzdGluZ3MgU2FtcGxpbmcgKM+DID0gIiwgc2lnLCAiKSIpLAogICAgc3VidGl0bGUgPSBwYXN0ZTAoCiAgICAgICJidXJuLWluID0gIiwgYnVybmluLAogICAgICAiLCAgbnNhbXAgPSAiLCBuc2FtcCwKICAgICAgIiwgIGluaXRpYWwgzrggPSAiLCB0aGV0YV9pbml0aWFsCiAgICApLAogICAgeCA9IGV4cHJlc3Npb24odGhldGEpLCB5ID0gImRlbnNpdHkiLAogICAgY29sb3IgPSAiIiwgZmlsbCA9ICIiCiAgKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTQpCgogIAogICMgLS0tLS0tLS0tLS0tLS0tLSBUcmFjZSBQbG90IC0tLS0tLS0tLS0tLS0tLS0KICBkZl90cmFjZSA8LSBkYXRhLmZyYW1lKGl0ZXIgPSAxOmxlbmd0aCh0aGV0YV92YWxzKSwgdmFsdWUgPSB0aGV0YV92YWxzKQogIAogIHAyIDwtIGdncGxvdChkZl90cmFjZSwgYWVzKGl0ZXIsIHZhbHVlKSkgKwogICAgZ2VvbV9saW5lKGNvbG9yID0gImJsYWNrIikgKwogICAgbGFicygKICAgICAgdGl0bGUgPSAiVHJhY2UgUGxvdCIsCiAgICAgIHN1YnRpdGxlID0gcGFzdGUwKAogICAgICAgICJidXJuLWluID0gIiwgYnVybmluLAogICAgICAgICIsICBrZXB0IHNhbXBsZXMgPSAiLCBuc2FtcCwKICAgICAgICAiLCAgaW5pdGlhbCDOuCA9ICIsIHRoZXRhX2luaXRpYWwKICAgICAgKSwKICAgICAgeSA9IGV4cHJlc3Npb24odGhldGF+dmFsdWUpLAogICAgICB4ID0gIml0ZXJhdGlvbiIKICAgICkgKwogICAgdGhlbWVfYncoYmFzZV9zaXplID0gMTQpCiAgCiAgIyBSZXR1cm4gc3RhY2tlZCBwbG90cwogIHAxIC8gcDIKfQpgYGAKCiMjIEV4YW1wbGUKYGBge3J9CnNldC5zZWVkKDQzMSkKIyAgIFRhcmdldCBkaXN0cmlidXRpb24gKHVubm9ybWFsaXplZCkKdGFyZ2V0ZGlzdCA8LSBmdW5jdGlvbih0aGV0YSkgewogIGV4cCgtdGhldGFeNC82ICsgdGhldGFeMi8yKSAqIGNvcyh0aGV0YV4zLzQpCn0KYnVybmluIDwtIDgwMDAKbGFnIDwtIDEKbnNhbXAgPC0gNTAwMDAKdGhldGFfaW5pdGlhbCA8LSAwICAgCgojIGdsb2JhbCBkZWZhdWx0CiNwbG90X01IKHNpZyA9IDAuMSkKI3Bsb3RfTUgoc2lnID0gMSkKI3Bsb3RfTUgoc2lnID0gMTApCmBgYAoKCmBgYHtyfQojIDEuIFdlbGwtdHVuZWQsIGNlbnRlcmVkIHN0YXJ0CnBsb3RfTUgoc2lnID0gMSwgbnNhbXAgPSAzMDAwLCB0aGV0YV9pbml0aWFsID0gMCkKIyAyLiBTYW1lIM+DLCBiYWQgaW5pdGlhbCB2YWx1ZSAKcGxvdF9NSChzaWcgPSAxLCBuc2FtcCA9IDMwMDAsIHRoZXRhX2luaXRpYWwgPSA2KQojIDMuIFNtYWxsZXIgc3RlcCBzaXplLCBzbG93ZXIgbWl4aW5nCnBsb3RfTUgoc2lnID0gMC4wMSwgbnNhbXAgPSAzMDAwLCB0aGV0YV9pbml0aWFsID0gMCkKYGBgCgojICBHaWJicyBTYW1wbGVyIGZvciBOb3JtYWwgTW9kZWwgd2l0aCBTZW1pLUNvbmp1Z2F0ZSBQcmlvcnMKYGBge3J9CiMgRGF0YSBzdW1tYXJ5Cm4gICAgPC0gMjQKeWJhciA8LSA3Ljg3MzAgICAgICAgICAgICMgc2FtcGxlIG1lYW4KcyAgICAgPC0gMC4wNTM1MyAgICAgICAgICMgc2FtcGxlIHNkCgojIyMgUHJpb3IgcGFyYW1ldGVycwptdTAgICAgICAgPC0gNy45ODc2ICAgICAgIyBwcmlvciBtZWFuIGZvciBtdQpzaWdtYTAuMiAgPC0gMC4wMDA2MjUgICAgIyBwcmlvciB2YXJpYW5jZSBvZiBtdQphbHBoYSAgICAgPC0gMi41ICAgICAgICAgIyBJRyhhbHBoYSwgYmV0YSkKYmV0YSAgICAgIDwtIDAuMDA0MwoKIyAgUnVuIEdpYmJzIHNhbXBsZXIKTnNpbSA8LSAxMDAwMDAgICAgICAgICAgICAgICAjIHRvdGFsIGRyYXdzCm11cyA8LSBudW1lcmljKE5zaW0pICAgICAgICAgIyBzdG9yZSBtdSBkcmF3cwpzaWdtYTIgPC0gbnVtZXJpYyhOc2ltKSAgICAgICMgc3RvcmUgc2lnbWFeMiBkcmF3cwoKIyMgSW5pdGlhbCB2YWx1ZXMKbXVzWzFdIDwtIDgKU1NFMSAgIDwtIChuLTEpKnNeMiArIG4qKHliYXIgLSBtdXNbMV0pXjIKc2lnbWEyWzFdIDwtIDEgLyByZ2FtbWEoMSwgbi8yICsgYWxwaGEsIFNTRTEvMiArIGJldGEpCgojIyBHaWJicyB1cGRhdGVzCmZvciAoayBpbiAyOk5zaW0pIHsKICAKICAjIyMgMS4gU2FtcGxlIG11IHwgc2lnbWFeMiwgeQogIHZhcl9tdSAgPC0gMSAvIChuIC8gc2lnbWEyW2stMV0gKyAxIC8gc2lnbWEwLjIpCiAgbWVhbl9tdSA8LSB2YXJfbXUgKiAobip5YmFyIC8gc2lnbWEyW2stMV0gKyBtdTAgLyBzaWdtYTAuMikKICBtdXNba10gPC0gcm5vcm0oMSwgbWVhbl9tdSwgc3FydCh2YXJfbXUpKQogIAogICMjIyAyLiBTYW1wbGUgc2lnbWFeMiB8IG11LCB5CiAgU1NFIDwtIChuLTEpKnNeMiArIG4qKHliYXIgLSBtdXNba10pXjIKICBzaWdtYTJba10gPC0gMSAvIHJnYW1tYSgxLCBuLzIgKyBhbHBoYSwgU1NFLzIgKyBiZXRhKQp9CgoKIyAgUG9zdGVyaW9yIHN1bW1hcmllcwpjYXQoIlBvc3RlcmlvciBtZWFuKG11KToiLCBtZWFuKG11cyksICJcbiIpCmNhdCgiUG9zdGVyaW9yIHNkKG11KToiLCAgIHNkKG11cyksICJcbiIpCmNhdCgiOTUlIENJIGZvciBtdTpcbiIpOyBwcmludChxdWFudGlsZShtdXMsIGMoMC4wMjUsIDAuOTc1KSkpCmNhdCgiXG5Qb3N0ZXJpb3IgbWVhbihzaWdtYV4yKToiLCBtZWFuKHNpZ21hMiksICJcbiIpCmNhdCgiOTUlIENJIGZvciBzaWdtYV4yOlxuIik7IHByaW50KHF1YW50aWxlKHNpZ21hMiwgYygwLjAyNSwgMC45NzUpKSkKCgojICBWaXN1YWxpemUgZmlyc3QgZmV3IEdpYmJzIHN0ZXBzCm1heGl0IDwtIDIwCnBsb3QobXVzWzE6bWF4aXRdLCBzaWdtYTJbMTptYXhpdF0sIHR5cGUgPSAibiIsCiAgICAgeGxhYiA9IGV4cHJlc3Npb24obXUpLCB5bGFiID0gZXhwcmVzc2lvbihzaWdtYV4yKSwKICAgICBtYWluID0gIkZpcnN0IDIwIEdpYmJzIEl0ZXJhdGlvbnMiKQphcnJvd3MobXVzWzE6KG1heGl0LTEpXSwgc2lnbWEyWzE6KG1heGl0LTEpXSwKICAgICAgIG11c1syOm1heGl0XSwgc2lnbWEyWzI6bWF4aXRdLAogICAgICAgbGVuZ3RoID0gMC4xLCBhbmdsZSA9IDMwLCBjb2wgPSByYWluYm93KG1heGl0LTEpKQpwb2ludHMobXVzWzE6bWF4aXRdLCBzaWdtYTJbMTptYXhpdF0sIHBjaCA9IDIwKQoKIyAgVHJhY2UgcGxvdHMKdHJhY2VfbXUgPC0gZ2dwbG90KGRhdGEuZnJhbWUoaXRlciA9IDE6TnNpbSwgbXUgPSBtdXMpLAogICAgICAgICAgICAgICAgICAgYWVzKGl0ZXIsIG11KSkgKwogIGdlb21fbGluZShjb2xvciA9ICJzdGVlbGJsdWUiKSArCiAgbGFicyh0aXRsZSA9ICJUcmFjZSBQbG90IGZvciDOvCIsCiAgICAgICB4ID0gIkl0ZXJhdGlvbiIsIHkgPSBleHByZXNzaW9uKG11KSkgKwogIHRoZW1lX2J3KDE0KQp0cmFjZV9zaWdtYTIgPC0gZ2dwbG90KGRhdGEuZnJhbWUoaXRlciA9IDE6TnNpbSwgc2lnbWEyID0gc2lnbWEyKSwKICAgICAgICAgICAgICAgICAgICAgICBhZXMoaXRlciwgc2lnbWEyKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJmaXJlYnJpY2siKSArCiAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oIlRyYWNlIFBsb3QgZm9yICIgKiBzaWdtYV4yKSwKICAgICAgIHggPSAiSXRlcmF0aW9uIiwgeSA9IGV4cHJlc3Npb24oc2lnbWFeMikpICsKICB0aGVtZV9idygxNCkKCiMgIFBvc3RlcmlvciBkZW5zaXR5IHBsb3RzCmRlbnNfbXUgPC0gZ2dwbG90KGRhdGEuZnJhbWUobXUgPSBtdXMpLCBhZXMobXUpKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAic3RlZWxibHVlIiwgYWxwaGEgPSAwLjQpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuKG11cyksIGNvbG9yID0gImJsdWUiLCBsaW5ldHlwZSA9IDIpICsKICBsYWJzKHRpdGxlID0gIlBvc3RlcmlvciBEZW5zaXR5IG9mIM68IiwKICAgICAgIHggPSBleHByZXNzaW9uKG11KSwgeSA9ICJEZW5zaXR5IikgKwogIHRoZW1lX2J3KDE0KQpkZW5zX3NpZ21hMiA8LSBnZ3Bsb3QoZGF0YS5mcmFtZShzaWdtYTIgPSBzaWdtYTIpLCBhZXMoc2lnbWEyKSkgKwogIGdlb21fZGVuc2l0eShmaWxsID0gImZpcmVicmljayIsIGFscGhhID0gMC40KSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbihzaWdtYTIpLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9IDIpICsKICBsYWJzKHRpdGxlID0gIlBvc3RlcmlvciBEZW5zaXR5IG9mIM+DwrIiLAogICAgICAgeCA9IGV4cHJlc3Npb24oc2lnbWFeMiksIHkgPSAiRGVuc2l0eSIpICsKICB0aGVtZV9idygxNCkKCiMgIEpvaW50IHBvc3RlcmlvciAozrwsIM+DwrIpCmRmX3Bvc3QgPC0gZGF0YS5mcmFtZShtdSA9IG11cywgc2lnbWEyID0gc2lnbWEyKQpqb2ludF9jb250b3VyIDwtIGdncGxvdChkZl9wb3N0LCBhZXMobXUsIHNpZ21hMikpICsKICBzdGF0X2RlbnNpdHlfMmQoYWVzKGZpbGwgPSAuLmxldmVsLi4pLCBnZW9tID0gInBvbHlnb24iLCBhbHBoYSA9IDAuNikgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKwogIGxhYnModGl0bGUgPSAiUG9zdGVyaW9yIEpvaW50IERlbnNpdHkgb2YgKM68LCDPg8KyKSIsCiAgICAgICB4ID0gZXhwcmVzc2lvbihtdSksIHkgPSBleHByZXNzaW9uKHNpZ21hXjIpKSArCiAgdGhlbWVfYncoMTQpCmpvaW50X2hlYXRtYXAgPC0gZ2dwbG90KGRmX3Bvc3QsIGFlcyhtdSwgc2lnbWEyKSkgKwogIHN0YXRfZGVuc2l0eV8yZF9maWxsZWQoY29udG91cl92YXIgPSAiZGVuc2l0eSIpICsKICBsYWJzKHRpdGxlID0gIlBvc3RlcmlvciBKb2ludCBEZW5zaXR5IEhlYXRtYXAiLAogICAgICAgeCA9IGV4cHJlc3Npb24obXUpLCB5ID0gZXhwcmVzc2lvbihzaWdtYV4yKSkgKwogIHRoZW1lX2J3KDE0KQoKCiMgIFBsb3QgY29tYmluZWQgcGFuZWxzCiggdHJhY2VfbXUgfCB0cmFjZV9zaWdtYTIgKSAvICggZGVuc19tdSB8IGRlbnNfc2lnbWEyICkKam9pbnRfY29udG91cgpqb2ludF9oZWF0bWFwCmBgYAoKCgojICBNSCBTYW1wbGVyIApgYGB7cn0Kc2V0LnNlZWQoNDMxKQojIyBMb2ctcG9zdGVyaW9yIGZvciAobXUsIGxvZ19zaWdtYTIpCmxvZ19wb3N0IDwtIGZ1bmN0aW9uKG11LCBsb2dfc2lnbWEyKSB7CiAgc2lnbWEyIDwtIGV4cChsb2dfc2lnbWEyKQogIAogICMgU1NFKG11KSB1c2luZyBzdWZmaWNpZW50IHN0YXRzCiAgU1NFIDwtIChuIC0gMSkqc14yICsgbiooeWJhciAtIG11KV4yCiAgCiAgIyBsb2ctbGlrZWxpaG9vZDogTihtdSwgc2lnbWEyKSBmb3IgbiBvYnNlcnZhdGlvbnMKICBscF95IDwtIC0obi8yKSAqIGxvZygyKnBpKnNpZ21hMikgLSBTU0UvKDIqc2lnbWEyKQogIAogICMgcHJpb3IgZm9yIG11IH4gTihtdTAsIHNpZ21hMF4yKQogIGxwX211IDwtIGRub3JtKG11LCBtZWFuID0gbXUwLCBzZCA9IHNxcnQoc2lnbWEwLjIpLCBsb2cgPSBUUlVFKQogIAogICMgcHJpb3IgZm9yIHNpZ21hMiB+IElHKGFscGhhLCBiZXRhKSwgdXAgdG8gY29uc3RhbnRzOgogICMgcChzaWdtYTIpIOKInSAoc2lnbWEyKV4tKGFscGhhKzEpIGV4cCgtYmV0YS9zaWdtYTIpCiAgbHBfczIgPC0gLShhbHBoYSArIDEpKmxvZyhzaWdtYTIpIC0gYmV0YS9zaWdtYTIKICAKICAjIEphY29iaWFuIGZvciB0cmFuc2Zvcm0gc2lnbWEyID0gZXhwKGxvZ19zaWdtYTIpCiAgbHBfamFjIDwtIGxvZ19zaWdtYTIKICByZXR1cm4obHBfeSArIGxwX211ICsgbHBfczIgKyBscF9qYWMpCn0gCiAgCiAgCm1oX3NhbXBsZXIgPC0gZnVuY3Rpb24oTnNpbSwgc3RhcnRfbXUsIHN0YXJ0X2xvZ19zMiwKICAgICAgICAgICAgICAgICAgICAgICBwcm9wX3NkX211LCBwcm9wX3NkX2xvZ19zMikgewogIG11ICAgICA8LSBudW1lcmljKE5zaW0pCiAgbG9nX3MyIDwtIG51bWVyaWMoTnNpbSkKICBtdVsxXSAgICAgPC0gc3RhcnRfbXUKICBsb2dfczJbMV0gPC0gc3RhcnRfbG9nX3MyCiAgYWNjIDwtIDAKICAKICBmb3IgKGsgaW4gMjpOc2ltKSB7CiAgICAjIFByb3Bvc2UgbmV3IChtdSwgbG9nX3NpZ21hMikgd2l0aCBHYXVzc2lhbiByYW5kb20gd2FsawogICAgbXVfcHJvcCAgICAgPC0gcm5vcm0oMSwgbWVhbiA9IG11W2stMV0sICAgICBzZCA9IHByb3Bfc2RfbXUpCiAgICBsb2dfczJfcHJvcCA8LSBybm9ybSgxLCBtZWFuID0gbG9nX3MyW2stMV0sIHNkID0gcHJvcF9zZF9sb2dfczIpCiAgICAKICAgICMgTG9nIGFjY2VwdGFuY2UgcmF0aW8gKHN5bW1ldHJpYyBwcm9wb3NhbCDih5IgcSBjYW5jZWxzKQogICAgbG9nX2FscGhhIDwtIGxvZ19wb3N0KG11X3Byb3AsIGxvZ19zMl9wcm9wKSAtCiAgICAgICAgICAgICAgICAgbG9nX3Bvc3QobXVbay0xXSwgbG9nX3MyW2stMV0pCiAgICAKICAgIGlmIChsb2cocnVuaWYoMSkpIDwgbG9nX2FscGhhKSB7CiAgICAgICMgYWNjZXB0CiAgICAgIG11W2tdICAgICA8LSBtdV9wcm9wCiAgICAgIGxvZ19zMltrXSA8LSBsb2dfczJfcHJvcAogICAgICBhY2MgPC0gYWNjICsgMQogICAgfSBlbHNlIHsKICAgICAgIyByZWplY3QgKHN0YXkgYXQgcHJldmlvdXMpCiAgICAgIG11W2tdICAgICA8LSBtdVtrLTFdCiAgICAgIGxvZ19zMltrXSA8LSBsb2dfczJbay0xXQogICAgfQogIH0KICAKICBsaXN0KG11ID0gbXUsCiAgICAgICBzaWdtYTIgPSBleHAobG9nX3MyKSwKICAgICAgIGFjY19yYXRlID0gYWNjIC8gKE5zaW0gLSAxKSkKfQoKIyBVc2UgR2liYnMgaW5pdGlhbCBzaWdtYTJbMV0gYXMgc3RhcnRpbmcgcG9pbnQgZm9yIE1ICm1oX291dCA8LSBtaF9zYW1wbGVyKAogIE5zaW0gICAgICAgICAgPSBOc2ltLAogIHN0YXJ0X211ICAgICAgPSBtdXNbMV0sCiAgc3RhcnRfbG9nX3MyICA9IGxvZyhzaWdtYTJbMV0pLAogIHByb3Bfc2RfbXUgICAgPSAwLjAwNSwgICAjIHR1bmUgdGhlc2UKICBwcm9wX3NkX2xvZ19zMiA9IDAuMDUKKQoKbWhfb3V0JGFjY19yYXRlICAgIyBjaGVjayBhY2NlcHRhbmNlIHJhdGU7IGFpbSB+IDAuMuKAkzAuNQpgYGAKCgoKIyBDb21wYXJzaW9uIFBsb3RzCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGF0Y2h3b3JrKQoKZGZfY29tcCA8LSBkYXRhLmZyYW1lKAogIGl0ZXIgICAgICAgICAgPSAxOk5zaW0sCiAgZ2liYnNfbXUgICAgICA9IG11cywKICBtaF9tdSAgICAgICAgID0gbWhfb3V0JG11LAogIGdpYmJzX3NpZ21hMiAgPSBzaWdtYTIsCiAgbWhfc2lnbWEyICAgICA9IG1oX291dCRzaWdtYTIKKQoKIyBUcmFjZSBQbG90CnRyYWNlX211X2JvdGggPC0gZ2dwbG90KGRmX2NvbXApICsKICBnZW9tX2xpbmUoYWVzKGl0ZXIsIGdpYmJzX211LCBjb2xvdXIgPSAiR2liYnMiKSkgKwogIGdlb21fbGluZShhZXMoaXRlciwgbWhfbXUsICAgIGNvbG91ciA9ICJNSCIpLCBhbHBoYSA9IDAuNykgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiR2liYnMiID0gInN0ZWVsYmx1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNSCIgICAgPSAib3JhbmdlIikpICsKICBsYWJzKHRpdGxlID0gIlRyYWNlIFBsb3QgZm9yIM68OiBHaWJicyB2cyBNSCIsCiAgICAgICB4ID0gIkl0ZXJhdGlvbiIsIHkgPSBleHByZXNzaW9uKG11KSwgY29sb3VyID0gIiIpICsKICB0aGVtZV9idygxNCkKdHJhY2VfczJfYm90aCA8LSBnZ3Bsb3QoZGZfY29tcCkgKwogIGdlb21fbGluZShhZXMoaXRlciwgZ2liYnNfc2lnbWEyLCBjb2xvdXIgPSAiR2liYnMiKSkgKwogIGdlb21fbGluZShhZXMoaXRlciwgbWhfc2lnbWEyLCAgICBjb2xvdXIgPSAiTUgiKSwgYWxwaGEgPSAwLjcpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIkdpYmJzIiA9ICJmaXJlYnJpY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTUgiICAgID0gImRhcmtncmVlbiIpKSArCiAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oIlRyYWNlIFBsb3QgZm9yICIgKiBzaWdtYV4yICogIjogR2liYnMgdnMgTUgiKSwKICAgICAgIHggPSAiSXRlcmF0aW9uIiwgeSA9IGV4cHJlc3Npb24oc2lnbWFeMiksIGNvbG91ciA9ICIiKSArCiAgdGhlbWVfYncoMTQpCnRyYWNlX211X2JvdGggLyB0cmFjZV9zMl9ib3RoCgoKIyBEZW5zaXR5IGNvbXBhcmlzb24KZGVuc19tdV9ib3RoIDwtIGdncGxvdChkZl9jb21wKSArCiAgZ2VvbV9kZW5zaXR5KGFlcyhnaWJic19tdSwgY29sb3VyID0gIkdpYmJzIiksIGFkanVzdCA9IDEuMikgKwogIGdlb21fZGVuc2l0eShhZXMobWhfbXUsICAgIGNvbG91ciA9ICJNSCIpLCAgICBhZGp1c3QgPSAxLjIsIGxpbmV0eXBlID0gMikgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygiR2liYnMiID0gInN0ZWVsYmx1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNSCIgICAgPSAib3JhbmdlIikpICsKICBsYWJzKHRpdGxlID0gIlBvc3RlcmlvciBvZiDOvDogR2liYnMgdnMgTUgiLAogICAgICAgeCA9IGV4cHJlc3Npb24obXUpLCB5ID0gIkRlbnNpdHkiLCBjb2xvdXIgPSAiIikgKwogIHRoZW1lX2J3KDE0KQpkZW5zX3MyX2JvdGggPC0gZ2dwbG90KGRmX2NvbXApICsKICBnZW9tX2RlbnNpdHkoYWVzKGdpYmJzX3NpZ21hMiwgY29sb3VyID0gIkdpYmJzIiksIGFkanVzdCA9IDEuMikgKwogIGdlb21fZGVuc2l0eShhZXMobWhfc2lnbWEyLCAgICBjb2xvdXIgPSAiTUgiKSwgICAgYWRqdXN0ID0gMS4yLCBsaW5ldHlwZSA9IDIpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIkdpYmJzIiA9ICJmaXJlYnJpY2siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTUgiICAgID0gImRhcmtncmVlbiIpKSArCiAgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oIlBvc3RlcmlvciBvZiAiICogc2lnbWFeMiAqICI6IEdpYmJzIHZzIE1IIiksCiAgICAgICB4ID0gZXhwcmVzc2lvbihzaWdtYV4yKSwgeSA9ICJEZW5zaXR5IiwgY29sb3VyID0gIiIpICsKICB0aGVtZV9idygxNCkKZGVuc19tdV9ib3RoIHwgZGVuc19zMl9ib3RoCgoKCiMgLS0tIEdpYmJzIGhlYXRtYXAgCm1oX211X3EgIDwtIHF1YW50aWxlKGRmX2NvbXAkbWhfbXUsICAgICBwcm9icyA9IGMoMC4wMDUsIDAuOTk1KSkKbWhfczJfcSAgPC0gcXVhbnRpbGUoZGZfY29tcCRtaF9zaWdtYTIsIHByb2JzID0gYygwLjAwNSwgMC45OTUpKQp6b29tX3ggPC0gYyhtaF9tdV9xWzFdLCBtaF9tdV9xWzJdKQp6b29tX3kgPC0gYyhtaF9zMl9xWzFdLCBtaF9zMl9xWzJdKQpoZWF0X2dpYmJzX3pvb20gPC0gZ2dwbG90KGRmX2NvbXAsIGFlcyhnaWJic19tdSwgZ2liYnNfc2lnbWEyKSkgKwogIHN0YXRfZGVuc2l0eV8yZF9maWxsZWQoY29udG91cl92YXIgPSAiZGVuc2l0eSIsIGFscGhhID0gMC45KSArCiAgc3RhdF9kZW5zaXR5XzJkKGNvbG9yID0gIndoaXRlIiwgbGluZXdpZHRoID0gMC40KSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Qob3B0aW9uID0gIkMiKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSB6b29tX3gsIHlsaW0gPSB6b29tX3ksIGV4cGFuZCA9IEZBTFNFKSArCiAgbGFicygKICAgIHRpdGxlID0gIkpvaW50IFBvc3RlcmlvciBIZWF0bWFwIChHaWJicykiLAogICAgeCA9IGV4cHJlc3Npb24obXUpLAogICAgeSA9IGV4cHJlc3Npb24oc2lnbWFeMiksCiAgICBmaWxsID0gIkRlbnNpdHkgTGV2ZWwiCiAgKSArCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMTYpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwLCBmYWNlID0gImJvbGQiLCBoanVzdCA9IDAuNSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCksCiAgICBheGlzLnRleHQgID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIGxlZ2VuZC50ZXh0ICA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGxpbmV3aWR0aCA9IDAuOCwgY29sb3IgPSAiYmxhY2siKSwKICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkKICApCmhlYXRfZ2liYnNfem9vbQoKCiMgTUggaGVhdG1hcCAKCmhlYXRfbWhfem9vbSA8LSBnZ3Bsb3QoZGZfY29tcCwgYWVzKG1oX211LCBtaF9zaWdtYTIpKSArCiAgc3RhdF9kZW5zaXR5XzJkX2ZpbGxlZChjb250b3VyX3ZhciA9ICJkZW5zaXR5IiwgYWxwaGEgPSAwLjkpICsKICBzdGF0X2RlbnNpdHlfMmQoY29sb3IgPSAid2hpdGUiLCBsaW5ld2lkdGggPSAwLjQpICsKICBzY2FsZV9maWxsX3ZpcmlkaXNfZChvcHRpb24gPSAiQyIpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IHpvb21feCwgeWxpbSA9IHpvb21feSwgZXhwYW5kID0gRkFMU0UpICsKICBsYWJzKAogICAgdGl0bGUgPSAiSm9pbnQgUG9zdGVyaW9yIEhlYXRtYXAgKE1IKSIsCiAgICB4ID0gZXhwcmVzc2lvbihtdSksCiAgICB5ID0gZXhwcmVzc2lvbihzaWdtYV4yKSwKICAgIGZpbGwgPSAiRGVuc2l0eSBMZXZlbCIKICApICsKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxNikgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSwKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwKICAgIGF4aXMudGV4dCAgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgbGVnZW5kLnRleHQgID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QobGluZXdpZHRoID0gMC44LCBjb2xvciA9ICJibGFjayIpLAogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKQogICkKaGVhdF9taF96b29tCgpgYGAKYGBge3J9CiMgU2V0IGxheW91dDogMSByb3csIDIgY29sdW1ucwpwYXIobWZyb3cgPSBjKDEsIDIpLCBtYXIgPSBjKDUsIDUsIDQsIDIpKQoKIyBQYW5lbCAxOiBQb3N0ZXJpb3Igb2YgzrwKZGVuc19naWJic19tdSA8LSBkZW5zaXR5KGRmX2NvbXAkZ2liYnNfbXUpCmRlbnNfbWhfbXUgICAgPC0gZGVuc2l0eShkZl9jb21wJG1oX211KQoKcGxvdChkZW5zX2dpYmJzX211LAogICAgIG1haW4gPSAiUG9zdGVyaW9yIG9mIM68OiBHaWJicyB2cyBNSCIsCiAgICAgeGxhYiA9IGV4cHJlc3Npb24obXUpLAogICAgIHlsYWIgPSAiRGVuc2l0eSIsCiAgICAgY29sICA9ICJzdGVlbGJsdWUiLAogICAgIGx3ZCAgPSAyLAogICAgIGx0eSAgPSAxLCAgICAgICAgICAjIHNvbGlkCiAgICAgY2V4LmxhYiA9IDEuMywKICAgICBjZXgubWFpbiA9IDEuNCkKCmxpbmVzKGRlbnNfbWhfbXUsCiAgICAgIGNvbCA9ICJvcmFuZ2UiLAogICAgICBsd2QgPSAyLAogICAgICBsdHkgPSAyKSAgICAgICAgICAjIGRhc2hlZAoKbGVnZW5kKCJ0b3ByaWdodCIsCiAgICAgICBsZWdlbmQgPSBjKCJHaWJicyAoc29saWQpIiwgIk1IIChkYXNoZWQpIiksCiAgICAgICBjb2wgPSBjKCJzdGVlbGJsdWUiLCAib3JhbmdlIiksCiAgICAgICBsd2QgPSAyLAogICAgICAgbHR5ID0gYygxLCAyKSwKICAgICAgIGJ0eSA9ICJuIiwKICAgICAgIGNleCA9IDEuMSkKCiMgUGFuZWwgMjogUG9zdGVyaW9yIG9mIM+DwrIKZGVuc19naWJic19zMiA8LSBkZW5zaXR5KGRmX2NvbXAkZ2liYnNfc2lnbWEyKQpkZW5zX21oX3MyICAgIDwtIGRlbnNpdHkoZGZfY29tcCRtaF9zaWdtYTIpCgpwbG90KGRlbnNfZ2liYnNfczIsCiAgICAgbWFpbiA9IGV4cHJlc3Npb24oIlBvc3RlcmlvciBvZiAiICogc2lnbWFeMiAqICI6IEdpYmJzIHZzIE1IIiksCiAgICAgeGxhYiA9IGV4cHJlc3Npb24oc2lnbWFeMiksCiAgICAgeWxhYiA9ICJEZW5zaXR5IiwKICAgICBjb2wgID0gImZpcmVicmljayIsCiAgICAgbHdkICA9IDIsCiAgICAgbHR5ICA9IDEsICAgICAgICAgICMgc29saWQKICAgICBjZXgubGFiID0gMS4zLAogICAgIGNleC5tYWluID0gMS40KQoKbGluZXMoZGVuc19taF9zMiwKICAgICAgY29sID0gImRhcmtncmVlbiIsCiAgICAgIGx3ZCA9IDIsCiAgICAgIGx0eSA9IDIpICAgICAgICAgICMgZGFzaGVkCgpsZWdlbmQoInRvcHJpZ2h0IiwKICAgICAgIGxlZ2VuZCA9IGMoIkdpYmJzIChzb2xpZCkiLCAiTUggKGRhc2hlZCkiKSwKICAgICAgIGNvbCA9IGMoImZpcmVicmljayIsICJkYXJrZ3JlZW4iKSwKICAgICAgIGx3ZCA9IDIsCiAgICAgICBsdHkgPSBjKDEsIDIpLAogICAgICAgYnR5ID0gIm4iLAogICAgICAgY2V4ID0gMS4xKQoKIyBSZXN0b3JlIGRlZmF1bHQgbGF5b3V0CnBhcihtZnJvdyA9IGMoMSwgMSkpCgpgYGAKCgoKCgoKCg==