Pacotes

library("R2WinBUGS")
library("R2jags")
library("rstan")
library("nimble")
library("boa")
library("coda")
library("xtable")
library("kableExtra")
library("tictoc")
library("LaplacesDemon")


Dados

######################################################################################
#                                SIMULAÇÃO DOS DADOS                                 #
######################################################################################
set.seed(123)
#Parâmetros verdadeiros
beta0=-2
beta1=2
beta2=10
sigma2=5
n=100
tau=1/sigma2
#Geração
x1=rnorm(n,0,1)
x2=rnorm(n,2,10)
e=rnorm(n,0, sd = sqrt(sigma2))
y=beta0+beta1*x1+beta2*x2+e


BUGS

Código

######################################################################################
#                                          BUGS                                      #
######################################################################################
sink("mod1.txt")        
cat("
    MODEL LR1 {
    #Verossimilhança 
    for(i in 1:N) {
    y[i] ~ dnorm(mu[i], sigma.theta )
    mu[i] <- beta0 + beta1*x1[i] + beta2*x2[i]
    }
    #Proris
    beta0 ~ dnorm(0,0.1)
    beta1 ~ dnorm(0,0.1)
    beta2 ~ dnorm(0,0.1)
    xi ~ dnorm(0,1)
    eta ~ dgamma(1,0.1)
    # A half-cauchy prior distribution on sigma.theta is induced using
    # a normal prior on xi and an inverse-gamma on tau.eta
    tau.eta <- 1/eta
    sigma.theta <- abs(xi)/sqrt(tau.eta)
    
    # Transformando em desvio
    sd <- 1/sqrt(sigma.theta)
    
     
    } ", fill = TRUE)
sink()
#Obeservação: A dist normal no bugs está definido para a precisão. 
#Tamanho amostral
N = length(y)
#Conjunto de dados observados
data = list("N","y","x1","x2")
#Parâmetros estudados
params = c("beta0", "beta1","beta2","sd")  
#Valores iniciais
inits <- function () {list(beta0 = 0,
                           beta1 = 0,
                           beta2 = 0,
                           sigma.teta = 2)}
tic()
result <- bugs(data = data, inits = inits, parameters.to.save = params,
               model.file = "mod1.txt", n.chains = 3, n.iter = 10000,
               n.burnin = 1000, n.thin=9, bugs.directory = "C:\\Program Files\\WinBUGS14",
               debug = TRUE, save.history = TRUE, DIC = FALSE)
cannot create file 'C:\Program Files\WinBUGS14/System/Rsrc/Registry_Rsave.odc', reason 'Permission denied'cannot open file 'C:\Program Files\WinBUGS14/System/Rsrc/Registry.odc': Permission deniedError in file(con, "wb") : cannot open the connection
toc()
21.9 sec elapsed


Resultados

result$summary %>%
  kable() %>%
  kable_styling()

mean sd 2.5% 25% 50% 75% 97.5% Rhat n.eff
beta0 -1.694912 0.2130390 -2.114025 -1.83325 -1.6965 -1.549 -1.264000 1.000536 3000
beta1 1.690878 0.2363106 1.235925 1.53100 1.6900 1.849 2.150025 1.002342 1100
beta2 10.004714 0.0224442 9.961000 9.98900 10.0000 10.020 10.050000 1.001220 2800
sd 2.119934 0.1512555 1.855000 2.01100 2.1120 2.214 2.438050 1.002110 1200

bugs = result$sims.list
bugs_b0 = bugs$beta0
bugs_b1 = bugs$beta1
bugs_b2 = bugs$beta2
bugs_sd = bugs$sd
plot(bugs_b0,type = "l",main=expression(beta[0]),ylab="",
     xlab="",cex.main=2)
abline(h=-2,col="red")

plot(bugs_b1,type = "l",main=expression(beta[1]),ylab="",
     xlab="",cex.main=2)
abline(h=2,col="red")

plot(bugs_b2,type = "l",main=expression(beta[2]),ylab="",
     xlab="",cex.main=2)
abline(h=10,col="red")

plot(bugs_sd,type = "l",main=expression(sigma),ylab="",
     xlab="",cex.main=2)
abline(h=sqrt(5),col="red")

densplot(as.mcmc(bugs_b0),main=expression(beta[0]),xlab="",ylab="",cex.main=2)

densplot(as.mcmc(bugs_b1),main=expression(beta[1]),xlab="",ylab="",cex.main=2)

densplot(as.mcmc(bugs_b2),main=expression(beta[2]),xlab="",ylab="",cex.main=2)

densplot(as.mcmc(bugs_sd),main=expression(sigma),xlab="",ylab="",cex.main=2)


JAGS

Código

######################################################################################
#                                          JAGS                                      #
######################################################################################
model_code = 'model{
     #Verossimilhança 
    for(i in 1:N) {
    y[i] ~ dnorm(mu[i], sigma.theta )
    mu[i] <- beta0 + beta1*x1[i] + beta2*x2[i]
    }
    #Proris
    beta0 ~ dnorm(0,0.1)
    beta1 ~ dnorm(0,0.1)
    beta2 ~ dnorm(0,0.1)
    xi ~ dnorm(0,1)
    eta ~ dgamma(1,0.1)
    
    tau.eta <- 1/eta
    sigma.theta <- abs(xi)/sqrt(tau.eta)
    
    }'
  
N = length(y)
model_data = list(N = N, y = y, x1 = x1, x2 = x2)
model_parameters =  c("beta0", "beta1","beta2","sigma.theta")
tic()
model_run = jags(data = model_data,
                 parameters.to.save = model_parameters,
                 model.file=textConnection(model_code),
                 n.chains=3, # Number of different starting positions
                 n.iter=10000, # Number of iterations
                 n.burnin=1000, # Number of iterations to remove at start
                 n.thin=9,# Amount of thinning
                 DIC=FALSE) 
Compiling model graph
   Resolving undeclared variables
   Allocating nodes
Graph information:
   Observed stochastic nodes: 100
   Unobserved stochastic nodes: 5
   Total graph size: 613

Initializing model
Deleting model
Error in jags.model(model.file, data = data, inits = init.values, n.chains = n.chains,  : 
  Error in node y[1]
Invalid parent values


Resultados


STAN

Código

######################################################################################
#                                          STAN                                      #
######################################################################################
model = "data {
int<lower=1> N;
vector[N] y;
vector[N] x1;
vector[N] x2;
}
parameters {
real alpha;
real beta1;
real beta2;
real<lower=0> sigma2;
}
transformed parameters{
real<lower=0> sigma;
sigma = fabs(sigma2);
}
model {
alpha ~ normal(0, 10);   
beta1 ~ normal(0, 10); 
beta2 ~ normal(0, 10);
sigma2 ~ cauchy(0,10);
y ~ normal(alpha + beta1 * x1 + beta2*x2, sigma);
}
generated quantities {
vector[N] y_rep;
for(n in 1:N) {
y_rep[n] = normal_rng(alpha + beta1 * x1[n] + beta2*x2[n], sigma);
}
}"
data <- list(y = y, x1 = x1, x2 = x2 , N = 100)
tic()
fit <- stan(model_code = model,
            data = data, iter = 2000, warmup = 1000, chains = 3)

SAMPLING FOR MODEL 'b52d6740126bb2b9be591795cab4219a' NOW (CHAIN 1).
Chain 1: 
Chain 1: Gradient evaluation took 0 seconds
Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
Chain 1: Adjust your expectations accordingly!
Chain 1: 
Chain 1: 
Chain 1: Iteration:    1 / 2000 [  0%]  (Warmup)
Chain 1: Iteration:  200 / 2000 [ 10%]  (Warmup)
Chain 1: Iteration:  400 / 2000 [ 20%]  (Warmup)
Chain 1: Iteration:  600 / 2000 [ 30%]  (Warmup)
Chain 1: Iteration:  800 / 2000 [ 40%]  (Warmup)
Chain 1: Iteration: 1000 / 2000 [ 50%]  (Warmup)
Chain 1: Iteration: 1001 / 2000 [ 50%]  (Sampling)
Chain 1: Iteration: 1200 / 2000 [ 60%]  (Sampling)
Chain 1: Iteration: 1400 / 2000 [ 70%]  (Sampling)
Chain 1: Iteration: 1600 / 2000 [ 80%]  (Sampling)
Chain 1: Iteration: 1800 / 2000 [ 90%]  (Sampling)
Chain 1: Iteration: 2000 / 2000 [100%]  (Sampling)
Chain 1: 
Chain 1:  Elapsed Time: 0.316 seconds (Warm-up)
Chain 1:                0.268 seconds (Sampling)
Chain 1:                0.584 seconds (Total)
Chain 1: 

SAMPLING FOR MODEL 'b52d6740126bb2b9be591795cab4219a' NOW (CHAIN 2).
Chain 2: 
Chain 2: Gradient evaluation took 0 seconds
Chain 2: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
Chain 2: Adjust your expectations accordingly!
Chain 2: 
Chain 2: 
Chain 2: Iteration:    1 / 2000 [  0%]  (Warmup)
Chain 2: Iteration:  200 / 2000 [ 10%]  (Warmup)
Chain 2: Iteration:  400 / 2000 [ 20%]  (Warmup)
Chain 2: Iteration:  600 / 2000 [ 30%]  (Warmup)
Chain 2: Iteration:  800 / 2000 [ 40%]  (Warmup)
Chain 2: Iteration: 1000 / 2000 [ 50%]  (Warmup)
Chain 2: Iteration: 1001 / 2000 [ 50%]  (Sampling)
Chain 2: Iteration: 1200 / 2000 [ 60%]  (Sampling)
Chain 2: Iteration: 1400 / 2000 [ 70%]  (Sampling)
Chain 2: Iteration: 1600 / 2000 [ 80%]  (Sampling)
Chain 2: Iteration: 1800 / 2000 [ 90%]  (Sampling)
Chain 2: Iteration: 2000 / 2000 [100%]  (Sampling)
Chain 2: 
Chain 2:  Elapsed Time: 0.266 seconds (Warm-up)
Chain 2:                0.272 seconds (Sampling)
Chain 2:                0.538 seconds (Total)
Chain 2: 

SAMPLING FOR MODEL 'b52d6740126bb2b9be591795cab4219a' NOW (CHAIN 3).
Chain 3: 
Chain 3: Gradient evaluation took 0 seconds
Chain 3: 1000 transitions using 10 leapfrog steps per transition would take 0 seconds.
Chain 3: Adjust your expectations accordingly!
Chain 3: 
Chain 3: 
Chain 3: Iteration:    1 / 2000 [  0%]  (Warmup)
Chain 3: Iteration:  200 / 2000 [ 10%]  (Warmup)
Chain 3: Iteration:  400 / 2000 [ 20%]  (Warmup)
Chain 3: Iteration:  600 / 2000 [ 30%]  (Warmup)
Chain 3: Iteration:  800 / 2000 [ 40%]  (Warmup)
Chain 3: Iteration: 1000 / 2000 [ 50%]  (Warmup)
Chain 3: Iteration: 1001 / 2000 [ 50%]  (Sampling)
Chain 3: Iteration: 1200 / 2000 [ 60%]  (Sampling)
Chain 3: Iteration: 1400 / 2000 [ 70%]  (Sampling)
Chain 3: Iteration: 1600 / 2000 [ 80%]  (Sampling)
Chain 3: Iteration: 1800 / 2000 [ 90%]  (Sampling)
Chain 3: Iteration: 2000 / 2000 [100%]  (Sampling)
Chain 3: 
Chain 3:  Elapsed Time: 0.499 seconds (Warm-up)
Chain 3:                0.659 seconds (Sampling)
Chain 3:                1.158 seconds (Total)
Chain 3: 
stan = extract(fit)
toc()
62.9 sec elapsed


Resultados

summary(fit,probs = c(0.025, 0.25, 0.50, 0.75, 0.975),pars=c("alpha","beta1","beta2","sigma")) %>%
  kable() %>%
  kable_styling()

mean se_mean sd 2.5% 25% 50% 75% 97.5% n_eff Rhat
alpha -1.705149 0.0039007 0.2203186 -2.128741 -1.851513 -1.706788 -1.558252 -1.266535 3190.227 0.9994377
beta1 1.704664 0.0042980 0.2346550 1.239475 1.547721 1.702359 1.869757 2.162556 2980.765 1.0002684
beta2 10.004990 0.0004031 0.0226243 9.962109 9.990043 10.004909 10.020552 10.048529 3150.105 0.9996364
sigma 2.159418 0.0031805 0.1589902 1.874101 2.049011 2.152554 2.260097 2.490462 2498.909 0.9995500
mean.chain:1 sd.chain:1 2.5%.chain:1 25%.chain:1 50%.chain:1 75%.chain:1 97.5%.chain:1 mean.chain:2 sd.chain:2 2.5%.chain:2 25%.chain:2 50%.chain:2 75%.chain:2 97.5%.chain:2 mean.chain:3 sd.chain:3 2.5%.chain:3 25%.chain:3 50%.chain:3 75%.chain:3 97.5%.chain:3
alpha -1.707477 0.2235333 -2.126845 -1.855703 -1.716247 -1.560096 -1.282388 -1.703702 0.2068422 -2.103886 -1.844171 -1.703053 -1.570987 -1.271763 -1.704267 0.2301279 -2.147936 -1.860284 -1.701615 -1.551234 -1.259488
beta1 1.698001 0.2377841 1.214058 1.535801 1.696142 1.866904 2.154469 1.710654 0.2302538 1.266526 1.553476 1.710989 1.860361 2.178951 1.705337 0.2359243 1.231920 1.544955 1.700726 1.875302 2.155878
beta2 10.004423 0.0237017 9.958859 9.988924 10.003503 10.021196 10.049177 10.005320 0.0216338 9.963577 9.991049 10.005570 10.020792 10.047768 10.005227 0.0225016 9.963601 9.989519 10.005487 10.019398 10.049736
sigma 2.157314 0.1589916 1.861853 2.046991 2.152927 2.264420 2.484893 2.156001 0.1518553 1.880637 2.049673 2.154927 2.245384 2.475617 2.164939 0.1658292 1.876279 2.051884 2.150899 2.269062 2.528738

stan_b0 = stan$alpha
stan_b1 = stan$beta1
stan_b2 = stan$beta2
stan_sd = stan$sigma
plot(stan_b0,type = "l",main=expression(beta[0]),ylab="",
     xlab="",cex.main=2)
abline(h=-2,col="red")

plot(stan_b1,type = "l",main=expression(beta[1]),ylab="",
     xlab="",cex.main=2)
abline(h=2,col="red")

plot(stan_b2,type = "l",main=expression(beta[2]),ylab="",
     xlab="",cex.main=2)
abline(h=10,col="red")

plot(stan_sd,type = "l",main=expression(sigma),ylab="",
     xlab="",cex.main=2)
abline(h=sqrt(5),col="red")

plot(density(stan_b0),main=expression(beta[0]),cex.main=2)

plot(density(stan_b1),main=expression(beta[1]),cex.main=2)

plot(density(stan_b2),main=expression(beta[2]),cex.main=2)

plot(density(stan_sd),main=expression(sigma),cex.main=2)


NIMBLE

Código

######################################################################################
#                                        NIMBLE                                     #
######################################################################################
simpleCode1 <- nimbleCode({
  
beta0 ~ dnorm(0,0.1)
beta1 ~ dnorm(0,0.1)
beta2 ~ dnorm(0,0.1)
xi ~ dt(0,0.01,1)
sigma  <- abs(xi)
sigma2 <- pow(xi,2)
tau <- pow(sigma2,-1)
  
for(i in 1:N) {
Ypred[i] <- beta0 + beta1 * x1[i] + beta2*x2[i]
Y[i] ~ dnorm(Ypred[i], tau)
}
  
  
})
simpleModel1 <- nimbleModel(simpleCode1,
                            data = list(Y = y, x1 = x1,x2=x2),
                            constants = list(N = N),
                            inits = list(beta0 = 0, beta1 = 0,beta2=0, xi = 2 ))
defining model...
building model...
setting data and initial values...
running calculate on model (any error reports that follow may simply reflect missing values in model variables) ... 
checking model sizes and dimensions...
model building finished.
tic()
mcmc.out <- nimbleMCMC(code = simpleModel1, 
                       data = list(Y = y, x1 = x1,x2=x2), 
                       inits = list(beta0 = 0, beta1 = 0,beta2=0, xi = 2),
                       monitors=c("beta0","beta1","beta2","sigma","sigma2"),
                       nchains = 3, 
                       niter = 10000,
                       thin = 9,
                       nburnin = 1000,
                       summary = TRUE, 
                       progressBar = TRUE)
compiling... this may take a minute. Use 'showCompilerOutput = TRUE' to see C++ compiler details.
compilation finished.
runMCMC's handling of nburnin changed in nimble version 0.6-11. Previously, nburnin samples were discarded *post-thinning*.  Now nburnin samples are discarded *pre-thinning*.  The number of samples returned will be floor((niter-nburnin)/thin).
running chain 1...
|-------------|-------------|-------------|-------------|
|-------------------------------------------------------|
running chain 2...
|-------------|-------------|-------------|-------------|
|-------------------------------------------------------|
running chain 3...
|-------------|-------------|-------------|-------------|
|-------------------------------------------------------|
toc()
78.03 sec elapsed


Resultados

mcmc.out$summary %>%
  kable() %>%
  kable_styling()

Mean Median St.Dev. 95%CI_low 95%CI_upp
beta0 -1.701853 -1.700324 0.2247996 -2.134344 -1.269477
beta1 1.694019 1.699318 0.2317892 1.237297 2.166930
beta2 10.006603 10.006732 0.0223889 9.962705 10.051267
sigma 2.151196 2.139595 0.1634963 1.852558 2.511840
sigma2 4.654348 4.577867 0.7162964 3.431973 6.309339
Mean Median St.Dev. 95%CI_low 95%CI_upp
beta0 -1.690154 -1.683048 0.2156525 -2.118917 -1.284972
beta1 1.686202 1.683455 0.2413500 1.218901 2.165015
beta2 10.004045 10.004224 0.0220070 9.959289 10.049076
sigma 2.149450 2.140115 0.1534882 1.879498 2.459997
sigma2 4.643669 4.580092 0.6692461 3.532516 6.051586
Mean Median St.Dev. 95%CI_low 95%CI_upp
beta0 -1.703272 -1.700163 0.2156711 -2.120387 -1.287375
beta1 1.691633 1.686491 0.2365682 1.233774 2.149293
beta2 10.004938 10.005058 0.0229612 9.959744 10.047435
sigma 2.153613 2.146234 0.1546927 1.847456 2.494988
sigma2 4.661956 4.606319 0.6731883 3.413092 6.224967
Mean Median St.Dev. 95%CI_low 95%CI_upp
beta0 -1.698426 -1.692678 0.2187562 -2.123892 -1.284737
beta1 1.690618 1.690694 0.2365450 1.232427 2.158214
beta2 10.005195 10.005548 0.0224733 9.959804 10.049202
sigma 2.151420 2.142408 0.1572459 1.856467 2.484581
sigma2 4.653324 4.589912 0.6863865 3.446468 6.173146

nimble_b0  =  c(mcmc.out$samples$chain1[,1],mcmc.out$samples$chain2[,1],mcmc.out$samples$chain3[,1])
nimble_b1  =  c(mcmc.out$samples$chain1[,2],mcmc.out$samples$chain2[,2],mcmc.out$samples$chain3[,2])
nimble_b2  =  c(mcmc.out$samples$chain1[,3],mcmc.out$samples$chain2[,3],mcmc.out$samples$chain3[,3])
nimble_sigma  =  c(mcmc.out$samples$chain1[,4],mcmc.out$samples$chain2[,4],mcmc.out$samples$chain3[,4])
plot(nimble_b0,type = "l",main=expression(beta[0]),ylab="",
     xlab="",cex.main=2)
abline(h=-2,col="red")

plot(nimble_b1,type = "l",main=expression(beta[1]),ylab="",
     xlab="",cex.main=2)
abline(h=2,col="red")

plot(nimble_b2,type = "l",main=expression(beta[2]),ylab="",
     xlab="",cex.main=2)
abline(h=10,col="red")

plot(nimble_sigma,type = "l",main=expression(sigma),ylab="",
     xlab="",cex.main=2)
abline(h=sqrt(5),col="red")

plot(density(nimble_b0),main=expression(beta[0]),cex.main=2)

plot(density(nimble_b1),main=expression(beta[1]),cex.main=2)

plot(density(nimble_b2),main=expression(beta[2]),cex.main=2)

plot(density(nimble_sigma),main=expression(sigma),cex.main=2)

LS0tDQp0aXRsZTogIkNvbXBhcmHn428gZW50cmUgb3MgcGFjb3RlcyBkZSBNQ01DIg0KYXV0aG9yOiAiUmFmYWVsIENhYnJhbCBGZXJuYW5kZXoiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KPGJyPg0KDQoNCiNQYWNvdGVzDQoNCmBgYHtyfQ0KbGlicmFyeSgiUjJXaW5CVUdTIikNCmxpYnJhcnkoIlIyamFncyIpDQpsaWJyYXJ5KCJyc3RhbiIpDQpsaWJyYXJ5KCJuaW1ibGUiKQ0KbGlicmFyeSgiYm9hIikNCmxpYnJhcnkoImNvZGEiKQ0KbGlicmFyeSgieHRhYmxlIikNCmxpYnJhcnkoImthYmxlRXh0cmEiKQ0KbGlicmFyeSgidGljdG9jIikNCmxpYnJhcnkoIkxhcGxhY2VzRGVtb24iKQ0KYGBgDQo8YnI+DQoNCiNEYWRvcw0KYGBge3J9DQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU0lNVUxBx8NPIERPUyBEQURPUyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCnNldC5zZWVkKDEyMykNCg0KI1BhcuJtZXRyb3MgdmVyZGFkZWlyb3MNCmJldGEwPS0yDQpiZXRhMT0yDQpiZXRhMj0xMA0Kc2lnbWEyPTUNCm49MTAwDQp0YXU9MS9zaWdtYTINCg0KI0dlcmHn428NCngxPXJub3JtKG4sMCwxKQ0KeDI9cm5vcm0obiwyLDEwKQ0KZT1ybm9ybShuLDAsIHNkID0gc3FydChzaWdtYTIpKQ0KeT1iZXRhMCtiZXRhMSp4MStiZXRhMip4MitlDQoNCg0KYGBgDQo8YnI+DQoNCiNCVUdTDQoNCiMjQ/NkaWdvDQpgYGB7cn0NCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCVUdTICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCnNpbmsoIm1vZDEudHh0IikgICAgICAgIA0KY2F0KCINCiAgICBNT0RFTCBMUjEgew0KICAgICNWZXJvc3NpbWlsaGFu52EgDQogICAgZm9yKGkgaW4gMTpOKSB7DQogICAgeVtpXSB+IGRub3JtKG11W2ldLCBzaWdtYS50aGV0YSApDQogICAgbXVbaV0gPC0gYmV0YTAgKyBiZXRhMSp4MVtpXSArIGJldGEyKngyW2ldDQogICAgfQ0KICAgICNQcm9yaXMNCiAgICBiZXRhMCB+IGRub3JtKDAsMC4xKQ0KICAgIGJldGExIH4gZG5vcm0oMCwwLjEpDQogICAgYmV0YTIgfiBkbm9ybSgwLDAuMSkNCiAgICB4aSB+IGRub3JtKDAsMSkNCiAgICBldGEgfiBkZ2FtbWEoMSwwLjEpDQoNCiAgICAjIEEgaGFsZi1jYXVjaHkgcHJpb3IgZGlzdHJpYnV0aW9uIG9uIHNpZ21hLnRoZXRhIGlzIGluZHVjZWQgdXNpbmcNCiAgICAjIGEgbm9ybWFsIHByaW9yIG9uIHhpIGFuZCBhbiBpbnZlcnNlLWdhbW1hIG9uIHRhdS5ldGENCiAgICB0YXUuZXRhIDwtIDEvZXRhDQogICAgc2lnbWEudGhldGEgPC0gYWJzKHhpKS9zcXJ0KHRhdS5ldGEpDQogICAgDQogICAgIyBUcmFuc2Zvcm1hbmRvIGVtIGRlc3Zpbw0KICAgIHNkIDwtIDEvc3FydChzaWdtYS50aGV0YSkNCiAgICANCiAgICAgDQogICAgfSAiLCBmaWxsID0gVFJVRSkNCnNpbmsoKQ0KI09iZXNlcnZh5+NvOiBBIGRpc3Qgbm9ybWFsIG5vIGJ1Z3MgZXN04SBkZWZpbmlkbyBwYXJhIGEgcHJlY2lz428uIA0KI1RhbWFuaG8gYW1vc3RyYWwNCk4gPSBsZW5ndGgoeSkNCiNDb25qdW50byBkZSBkYWRvcyBvYnNlcnZhZG9zDQpkYXRhID0gbGlzdCgiTiIsInkiLCJ4MSIsIngyIikNCiNQYXLibWV0cm9zIGVzdHVkYWRvcw0KcGFyYW1zID0gYygiYmV0YTAiLCAiYmV0YTEiLCJiZXRhMiIsInNkIikgIA0KI1ZhbG9yZXMgaW5pY2lhaXMNCmluaXRzIDwtIGZ1bmN0aW9uICgpIHtsaXN0KGJldGEwID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJldGExID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJldGEyID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpZ21hLnRldGEgPSAyKX0NCnRpYygpDQpyZXN1bHQgPC0gYnVncyhkYXRhID0gZGF0YSwgaW5pdHMgPSBpbml0cywgcGFyYW1ldGVycy50by5zYXZlID0gcGFyYW1zLA0KICAgICAgICAgICAgICAgbW9kZWwuZmlsZSA9ICJtb2QxLnR4dCIsIG4uY2hhaW5zID0gMywgbi5pdGVyID0gMTAwMDAsDQogICAgICAgICAgICAgICBuLmJ1cm5pbiA9IDEwMDAsIG4udGhpbj05LCBidWdzLmRpcmVjdG9yeSA9ICJDOlxcUHJvZ3JhbSBGaWxlc1xcV2luQlVHUzE0IiwNCiAgICAgICAgICAgICAgIGRlYnVnID0gVFJVRSwgc2F2ZS5oaXN0b3J5ID0gVFJVRSwgRElDID0gRkFMU0UpDQp0b2MoKQ0KYGBgDQo8YnI+DQoNCiMjUmVzdWx0YWRvcw0KYGBge3J9DQpyZXN1bHQkc3VtbWFyeSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZygpDQoNCmJ1Z3MgPSByZXN1bHQkc2ltcy5saXN0DQpidWdzX2IwID0gYnVncyRiZXRhMA0KYnVnc19iMSA9IGJ1Z3MkYmV0YTENCmJ1Z3NfYjIgPSBidWdzJGJldGEyDQpidWdzX3NkID0gYnVncyRzZA0KDQpwbG90KGJ1Z3NfYjAsdHlwZSA9ICJsIixtYWluPWV4cHJlc3Npb24oYmV0YVswXSkseWxhYj0iIiwNCiAgICAgeGxhYj0iIixjZXgubWFpbj0yKQ0KYWJsaW5lKGg9LTIsY29sPSJyZWQiKQ0KcGxvdChidWdzX2IxLHR5cGUgPSAibCIsbWFpbj1leHByZXNzaW9uKGJldGFbMV0pLHlsYWI9IiIsDQogICAgIHhsYWI9IiIsY2V4Lm1haW49MikNCmFibGluZShoPTIsY29sPSJyZWQiKQ0KcGxvdChidWdzX2IyLHR5cGUgPSAibCIsbWFpbj1leHByZXNzaW9uKGJldGFbMl0pLHlsYWI9IiIsDQogICAgIHhsYWI9IiIsY2V4Lm1haW49MikNCmFibGluZShoPTEwLGNvbD0icmVkIikNCg0KcGxvdChidWdzX3NkLHR5cGUgPSAibCIsbWFpbj1leHByZXNzaW9uKHNpZ21hKSx5bGFiPSIiLA0KICAgICB4bGFiPSIiLGNleC5tYWluPTIpDQphYmxpbmUoaD1zcXJ0KDUpLGNvbD0icmVkIikNCg0KZGVuc3Bsb3QoYXMubWNtYyhidWdzX2IwKSxtYWluPWV4cHJlc3Npb24oYmV0YVswXSkseGxhYj0iIix5bGFiPSIiLGNleC5tYWluPTIpDQpkZW5zcGxvdChhcy5tY21jKGJ1Z3NfYjEpLG1haW49ZXhwcmVzc2lvbihiZXRhWzFdKSx4bGFiPSIiLHlsYWI9IiIsY2V4Lm1haW49MikNCmRlbnNwbG90KGFzLm1jbWMoYnVnc19iMiksbWFpbj1leHByZXNzaW9uKGJldGFbMl0pLHhsYWI9IiIseWxhYj0iIixjZXgubWFpbj0yKQ0KZGVuc3Bsb3QoYXMubWNtYyhidWdzX3NkKSxtYWluPWV4cHJlc3Npb24oc2lnbWEpLHhsYWI9IiIseWxhYj0iIixjZXgubWFpbj0yKQ0KDQoNCg0KYGBgDQo8YnI+DQoNCiNKQUdTDQoNCiMjQ/NkaWdvDQpgYGB7cn0NCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBKQUdTICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KbW9kZWxfY29kZSA9ICdtb2RlbHsNCiAgICAgI1Zlcm9zc2ltaWxoYW7nYSANCiAgICBmb3IoaSBpbiAxOk4pIHsNCiAgICB5W2ldIH4gZG5vcm0obXVbaV0sIHNpZ21hLnRoZXRhICkNCiAgICBtdVtpXSA8LSBiZXRhMCArIGJldGExKngxW2ldICsgYmV0YTIqeDJbaV0NCiAgICB9DQogICAgI1Byb3Jpcw0KICAgIGJldGEwIH4gZG5vcm0oMCwwLjEpDQogICAgYmV0YTEgfiBkbm9ybSgwLDAuMSkNCiAgICBiZXRhMiB+IGRub3JtKDAsMC4xKQ0KICAgIHhpIH4gZG5vcm0oMCwxKQ0KICAgIGV0YSB+IGRnYW1tYSgxLDAuMSkNCg0KICAgICMgQSBoYWxmLWNhdWNoeSBwcmlvciBkaXN0cmlidXRpb24gb24gc2lnbWEudGhldGEgaXMgaW5kdWNlZCB1c2luZw0KICAgICMgYSBub3JtYWwgcHJpb3Igb24geGkgYW5kIGFuIGludmVyc2UtZ2FtbWEgb24gdGF1LmV0YQ0KICAgIHRhdS5ldGEgPC0gMS9ldGENCiAgICBzaWdtYS50aGV0YSA8LSBhYnMoeGkpL3NxcnQodGF1LmV0YSl9Jw0KDQogIA0KTiA9IGxlbmd0aCh5KQ0KDQptb2RlbF9kYXRhID0gbGlzdChOID0gTiwgeSA9IHksIHgxID0geDEsIHgyID0geDIpDQoNCm1vZGVsX3BhcmFtZXRlcnMgPSAgYygiYmV0YTAiLCAiYmV0YTEiLCJiZXRhMiIsICJzaWdtYS50aGV0YSIpDQoNCnRpYygpDQptb2RlbF9ydW4gPSBqYWdzKGRhdGEgPSBtb2RlbF9kYXRhLA0KICAgICAgICAgICAgICAgICBwYXJhbWV0ZXJzLnRvLnNhdmUgPSBtb2RlbF9wYXJhbWV0ZXJzLA0KICAgICAgICAgICAgICAgICBtb2RlbC5maWxlPXRleHRDb25uZWN0aW9uKG1vZGVsX2NvZGUpLA0KICAgICAgICAgICAgICAgICBuLmNoYWlucz0zLCAjIE51bWJlciBvZiBkaWZmZXJlbnQgc3RhcnRpbmcgcG9zaXRpb25zDQogICAgICAgICAgICAgICAgIG4uaXRlcj0xMDAwMCwgIyBOdW1iZXIgb2YgaXRlcmF0aW9ucw0KICAgICAgICAgICAgICAgICBuLmJ1cm5pbj0xMDAwLCAjIE51bWJlciBvZiBpdGVyYXRpb25zIHRvIHJlbW92ZSBhdCBzdGFydA0KICAgICAgICAgICAgICAgICBuLnRoaW49OSwjIEFtb3VudCBvZiB0aGlubmluZw0KICAgICAgICAgICAgICAgICBESUM9RkFMU0UpIA0KdG9jKCkNCg0KDQoNCmBgYA0KPGJyPg0KDQojI1Jlc3VsdGFkb3MNCmBgYHtyLGV2YWw9RkFMU0UsZWNobz1GQUxTRX0NCm1vZGVsX3J1biRCVUdTb3V0cHV0JHN1bW1hcnkgJT4lDQogIGthYmxlKCkgJT4lDQogIGthYmxlX3N0eWxpbmcoKQ0KDQpqYWdzID0gbW9kZWxfcnVuW1siQlVHU291dHB1dCJdXVtbInNpbXMubWF0cml4Il1dDQpqYWdzX2IwID0gamFnc1ssMV0NCmphZ3NfYjEgPSBqYWdzWywyXQ0KamFnc19iMiA9IGphZ3NbLDNdDQpqYWdzX3MyID0gamFnc1ssNF0NCmphZ3NfdGF1ID0gamFnc1ssNV0NCg0KDQpwbG90KGphZ3NfYjAsdHlwZSA9ICJsIixtYWluPWV4cHJlc3Npb24oYmV0YVswXSkseWxhYj0iIiwNCiAgICAgeGxhYj0iIixjZXgubWFpbj0yKQ0KYWJsaW5lKGg9YmV0YTAsY29sPSJyZWQiKQ0KcGxvdChqYWdzX2IxLHR5cGUgPSAibCIsbWFpbj1leHByZXNzaW9uKGJldGFbMV0pLHlsYWI9IiIsDQogICAgIHhsYWI9IiIsY2V4Lm1haW49MikNCmFibGluZShoPWJldGExLGNvbD0icmVkIikNCnBsb3QoYnVnc19iMix0eXBlID0gImwiLG1haW49ZXhwcmVzc2lvbihiZXRhWzJdKSx5bGFiPSIiLA0KICAgICB4bGFiPSIiLGNleC5tYWluPTIpDQphYmxpbmUoaD0xMCxjb2w9InJlZCIpDQpwbG90KGphZ3NfczIsdHlwZSA9ICJsIixtYWluPWV4cHJlc3Npb24oc2lnbWFeMikseWxhYj0iIiwNCiAgICAgeGxhYj0iIixjZXgubWFpbj0yKQ0KYWJsaW5lKGg9c2lnbWEyLGNvbD0icmVkIikNCnBsb3QoamFnc190YXUsdHlwZSA9ICJsIixtYWluPWV4cHJlc3Npb24odGF1KSx5bGFiPSIiLA0KICAgICB4bGFiPSIiLGNleC5tYWluPTIpDQphYmxpbmUoaD10YXUsY29sPSJyZWQiKQ0KDQoNCg0KZGVuc3Bsb3QoYXMubWNtYyhqYWdzX2IwKSxtYWluPWV4cHJlc3Npb24oYmV0YVswXSkseGxhYj0iIix5bGFiPSIiLGNleC5tYWluPTIpDQpkZW5zcGxvdChhcy5tY21jKGphZ3NfYjEpLG1haW49ZXhwcmVzc2lvbihiZXRhWzFdKSx4bGFiPSIiLHlsYWI9IiIsY2V4Lm1haW49MikNCmRlbnNwbG90KGFzLm1jbWMoYnVnc19iMiksbWFpbj1leHByZXNzaW9uKGJldGFbMl0pLHhsYWI9IiIseWxhYj0iIixjZXgubWFpbj0yKQ0KZGVuc3Bsb3QoYXMubWNtYyhqYWdzX3MyKSxtYWluPWV4cHJlc3Npb24oc2lnbWFeMikseGxhYj0iIix5bGFiPSIiLGNleC5tYWluPTIpDQpkZW5zcGxvdChhcy5tY21jKGphZ3NfdGF1KSxtYWluPWV4cHJlc3Npb24odGF1KSx4bGFiPSIiLHlsYWI9IiIsY2V4Lm1haW49MikNCg0KYGBgDQo8YnI+DQoNCiNTVEFODQoNCiMjQ/NkaWdvDQpgYGB7cn0NCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNUQU4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCm1vZGVsID0gImRhdGEgew0KaW50PGxvd2VyPTE+IE47DQp2ZWN0b3JbTl0geTsNCnZlY3RvcltOXSB4MTsNCnZlY3RvcltOXSB4MjsNCn0NCnBhcmFtZXRlcnMgew0KcmVhbCBhbHBoYTsNCnJlYWwgYmV0YTE7DQpyZWFsIGJldGEyOw0KcmVhbDxsb3dlcj0wPiBzaWdtYTI7DQp9DQp0cmFuc2Zvcm1lZCBwYXJhbWV0ZXJzew0KcmVhbDxsb3dlcj0wPiBzaWdtYTsNCnNpZ21hID0gZmFicyhzaWdtYTIpOw0KfQ0KbW9kZWwgew0KYWxwaGEgfiBub3JtYWwoMCwgMTApOyAgIA0KYmV0YTEgfiBub3JtYWwoMCwgMTApOyANCmJldGEyIH4gbm9ybWFsKDAsIDEwKTsNCnNpZ21hMiB+IGNhdWNoeSgwLDEwKTsNCnkgfiBub3JtYWwoYWxwaGEgKyBiZXRhMSAqIHgxICsgYmV0YTIqeDIsIHNpZ21hKTsNCn0NCg0KZ2VuZXJhdGVkIHF1YW50aXRpZXMgew0KdmVjdG9yW05dIHlfcmVwOw0KZm9yKG4gaW4gMTpOKSB7DQp5X3JlcFtuXSA9IG5vcm1hbF9ybmcoYWxwaGEgKyBiZXRhMSAqIHgxW25dICsgYmV0YTIqeDJbbl0sIHNpZ21hKTsNCn0NCn0iDQoNCg0KZGF0YSA8LSBsaXN0KHkgPSB5LCB4MSA9IHgxLCB4MiA9IHgyICwgTiA9IDEwMCkNCg0KdGljKCkNCmZpdCA8LSBzdGFuKG1vZGVsX2NvZGUgPSBtb2RlbCwNCiAgICAgICAgICAgIGRhdGEgPSBkYXRhLCBpdGVyID0gMjAwMCwgd2FybXVwID0gMTAwMCwgY2hhaW5zID0gMykNCg0KDQpzdGFuID0gZXh0cmFjdChmaXQpDQp0b2MoKQ0KDQoNCmBgYA0KPGJyPg0KDQojI1Jlc3VsdGFkb3MNCmBgYHtyfQ0Kc3VtbWFyeShmaXQscHJvYnMgPSBjKDAuMDI1LCAwLjI1LCAwLjUwLCAwLjc1LCAwLjk3NSkscGFycz1jKCJhbHBoYSIsImJldGExIiwiYmV0YTIiLCJzaWdtYSIpKSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZygpDQoNCnN0YW5fYjAgPSBzdGFuJGFscGhhDQpzdGFuX2IxID0gc3RhbiRiZXRhMQ0Kc3Rhbl9iMiA9IHN0YW4kYmV0YTINCnN0YW5fc2QgPSBzdGFuJHNpZ21hDQoNCg0KcGxvdChzdGFuX2IwLHR5cGUgPSAibCIsbWFpbj1leHByZXNzaW9uKGJldGFbMF0pLHlsYWI9IiIsDQogICAgIHhsYWI9IiIsY2V4Lm1haW49MikNCmFibGluZShoPS0yLGNvbD0icmVkIikNCnBsb3Qoc3Rhbl9iMSx0eXBlID0gImwiLG1haW49ZXhwcmVzc2lvbihiZXRhWzFdKSx5bGFiPSIiLA0KICAgICB4bGFiPSIiLGNleC5tYWluPTIpDQphYmxpbmUoaD0yLGNvbD0icmVkIikNCnBsb3Qoc3Rhbl9iMix0eXBlID0gImwiLG1haW49ZXhwcmVzc2lvbihiZXRhWzJdKSx5bGFiPSIiLA0KICAgICB4bGFiPSIiLGNleC5tYWluPTIpDQphYmxpbmUoaD0xMCxjb2w9InJlZCIpDQpwbG90KHN0YW5fc2QsdHlwZSA9ICJsIixtYWluPWV4cHJlc3Npb24oc2lnbWEpLHlsYWI9IiIsDQogICAgIHhsYWI9IiIsY2V4Lm1haW49MikNCmFibGluZShoPXNxcnQoNSksY29sPSJyZWQiKQ0KDQpwbG90KGRlbnNpdHkoc3Rhbl9iMCksbWFpbj1leHByZXNzaW9uKGJldGFbMF0pLGNleC5tYWluPTIpDQpwbG90KGRlbnNpdHkoc3Rhbl9iMSksbWFpbj1leHByZXNzaW9uKGJldGFbMV0pLGNleC5tYWluPTIpDQpwbG90KGRlbnNpdHkoc3Rhbl9iMiksbWFpbj1leHByZXNzaW9uKGJldGFbMl0pLGNleC5tYWluPTIpDQpwbG90KGRlbnNpdHkoc3Rhbl9zZCksbWFpbj1leHByZXNzaW9uKHNpZ21hKSxjZXgubWFpbj0yKQ0KYGBgDQoNCjxicj4NCg0KI05JTUJMRQ0KDQojI0PzZGlnbw0KYGBge3J9DQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTklNQkxFICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCnNpbXBsZUNvZGUxIDwtIG5pbWJsZUNvZGUoew0KICANCmJldGEwIH4gZG5vcm0oMCwwLjEpDQpiZXRhMSB+IGRub3JtKDAsMC4xKQ0KYmV0YTIgfiBkbm9ybSgwLDAuMSkNCnhpIH4gZHQoMCwwLjAxLDEpDQpzaWdtYSAgPC0gYWJzKHhpKQ0Kc2lnbWEyIDwtIHBvdyh4aSwyKQ0KdGF1IDwtIHBvdyhzaWdtYTIsLTEpDQogIA0KZm9yKGkgaW4gMTpOKSB7DQpZcHJlZFtpXSA8LSBiZXRhMCArIGJldGExICogeDFbaV0gKyBiZXRhMip4MltpXQ0KWVtpXSB+IGRub3JtKFlwcmVkW2ldLCB0YXUpDQp9DQogIA0KICANCn0pDQoNCg0KDQoNCnNpbXBsZU1vZGVsMSA8LSBuaW1ibGVNb2RlbChzaW1wbGVDb2RlMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gbGlzdChZID0geSwgeDEgPSB4MSx4Mj14MiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RhbnRzID0gbGlzdChOID0gTiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdHMgPSBsaXN0KGJldGEwID0gMCwgYmV0YTEgPSAwLGJldGEyPTAsIHhpID0gMiApKQ0KDQp0aWMoKQ0KbWNtYy5vdXQgPC0gbmltYmxlTUNNQyhjb2RlID0gc2ltcGxlTW9kZWwxLCANCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGxpc3QoWSA9IHksIHgxID0geDEseDI9eDIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgaW5pdHMgPSBsaXN0KGJldGEwID0gMCwgYmV0YTEgPSAwLGJldGEyPTAsIHhpID0gMiksDQogICAgICAgICAgICAgICAgICAgICAgIG1vbml0b3JzPWMoImJldGEwIiwiYmV0YTEiLCJiZXRhMiIsInNpZ21hIiwic2lnbWEyIiksDQogICAgICAgICAgICAgICAgICAgICAgIG5jaGFpbnMgPSAzLCANCiAgICAgICAgICAgICAgICAgICAgICAgbml0ZXIgPSAxMDAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgdGhpbiA9IDksDQogICAgICAgICAgICAgICAgICAgICAgIG5idXJuaW4gPSAxMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5ID0gVFJVRSwgDQogICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzQmFyID0gVFJVRSkNCnRvYygpDQoNCmBgYA0KPGJyPg0KDQojI1Jlc3VsdGFkb3MNCmBgYHtyfQ0KbWNtYy5vdXQkc3VtbWFyeSAlPiUNCiAga2FibGUoKSAlPiUNCiAga2FibGVfc3R5bGluZygpDQoNCg0KbmltYmxlX2IwICA9ICBjKG1jbWMub3V0JHNhbXBsZXMkY2hhaW4xWywxXSxtY21jLm91dCRzYW1wbGVzJGNoYWluMlssMV0sbWNtYy5vdXQkc2FtcGxlcyRjaGFpbjNbLDFdKQ0KbmltYmxlX2IxICA9ICBjKG1jbWMub3V0JHNhbXBsZXMkY2hhaW4xWywyXSxtY21jLm91dCRzYW1wbGVzJGNoYWluMlssMl0sbWNtYy5vdXQkc2FtcGxlcyRjaGFpbjNbLDJdKQ0KbmltYmxlX2IyICA9ICBjKG1jbWMub3V0JHNhbXBsZXMkY2hhaW4xWywzXSxtY21jLm91dCRzYW1wbGVzJGNoYWluMlssM10sbWNtYy5vdXQkc2FtcGxlcyRjaGFpbjNbLDNdKQ0KbmltYmxlX3NpZ21hICA9ICBjKG1jbWMub3V0JHNhbXBsZXMkY2hhaW4xWyw0XSxtY21jLm91dCRzYW1wbGVzJGNoYWluMlssNF0sbWNtYy5vdXQkc2FtcGxlcyRjaGFpbjNbLDRdKQ0KDQoNCnBsb3QobmltYmxlX2IwLHR5cGUgPSAibCIsbWFpbj1leHByZXNzaW9uKGJldGFbMF0pLHlsYWI9IiIsDQogICAgIHhsYWI9IiIsY2V4Lm1haW49MikNCmFibGluZShoPS0yLGNvbD0icmVkIikNCnBsb3QobmltYmxlX2IxLHR5cGUgPSAibCIsbWFpbj1leHByZXNzaW9uKGJldGFbMV0pLHlsYWI9IiIsDQogICAgIHhsYWI9IiIsY2V4Lm1haW49MikNCmFibGluZShoPTIsY29sPSJyZWQiKQ0KcGxvdChuaW1ibGVfYjIsdHlwZSA9ICJsIixtYWluPWV4cHJlc3Npb24oYmV0YVsyXSkseWxhYj0iIiwNCiAgICAgeGxhYj0iIixjZXgubWFpbj0yKQ0KYWJsaW5lKGg9MTAsY29sPSJyZWQiKQ0KcGxvdChuaW1ibGVfc2lnbWEsdHlwZSA9ICJsIixtYWluPWV4cHJlc3Npb24oc2lnbWEpLHlsYWI9IiIsDQogICAgIHhsYWI9IiIsY2V4Lm1haW49MikNCmFibGluZShoPXNxcnQoNSksY29sPSJyZWQiKQ0KDQoNCnBsb3QoZGVuc2l0eShuaW1ibGVfYjApLG1haW49ZXhwcmVzc2lvbihiZXRhWzBdKSxjZXgubWFpbj0yKQ0KcGxvdChkZW5zaXR5KG5pbWJsZV9iMSksbWFpbj1leHByZXNzaW9uKGJldGFbMV0pLGNleC5tYWluPTIpDQpwbG90KGRlbnNpdHkobmltYmxlX2IyKSxtYWluPWV4cHJlc3Npb24oYmV0YVsyXSksY2V4Lm1haW49MikNCnBsb3QoZGVuc2l0eShuaW1ibGVfc2lnbWEpLG1haW49ZXhwcmVzc2lvbihzaWdtYSksY2V4Lm1haW49MikNCg0KYGBgDQoNCg0KDQo=