Introdução

Inferência sob o Modelo Tobit utilizando os pacotes Bugs, Jags, Stan e Nimble

Tamanho amostral = \(100\)

\(x_i \sim unif(1,5;3)\)

Garantindo 5% de censura amostral

A amostra gerada tem a seguinte distribuição:

\(y_i \sim N(\beta_0+\beta_1\times x_i, \tau)\)

Com as seguintes prioris:

\(\beta_0 \sim N(0;0,01)\)

\(\beta_1 \sim N(0;0,01)\)

\(\tau \sim Ga(1;0,1)\)

\(E[\tau] = 10\) e \(V[\tau]=100\)

Para efeito de simulação, foram padronizadas as seguintes definições:

Simulações = 10000

burn = 1000

Tamanho amostral a posteriori = 9000

Cadeias = 1

Espaçamento = 1

Bugs

########################################################################################
#############                          BUGS                                ############# 
########################################################################################
set.seed(20)
x <- runif(100,1.5,3)
y <- rnorm(100,-2+2*x)
y.cens <- ifelse(y>0,y,NA)
table(y.cens<0)

FALSE 
   95 
sink("regression.txt")
cat(" 
model
{
# priors
beta0 ~ dnorm(0,0.01)
beta1 ~ dnorm(0,0.01)
tau ~ dgamma(1,0.1)
# likelihood
for(i in 1:N)
{
mu[i] <- beta0 + beta1*x[i]
y[i] ~ dnorm(mu[i], tau)C(0,)}
}
    ")
sink()
my.data <- list(y=y.cens,N=100,x=x)
params <- c("beta0","beta1","tau")
inits <- function(){list (beta0=1,beta1=1,tau=2)}
res <- bugs(data=my.data, inits=inits, parameters.to.save=params,
            n.iter=10000, n.chains=1, n.burnin=1000,n.thin = 1,
            model.file="regression.txt",DIC=FALSE)
res$summary
           mean        sd       2.5%      25%    50%      75%     97.5%
beta0 -1.924597 0.4815395 -2.8820000 -2.24325 -1.922 -1.60200 -0.991790
beta1  2.056745 0.2125253  1.6469750  1.91300  2.054  2.19800  2.480025
tau    1.265164 0.1818779  0.9342975  1.13775  1.257  1.38025  1.645000
par(mfrow=c(1,3))
plot(res$sims.matrix[,1],type="l",main=expression(beta[0]))
abline(h=-2,col="red")
plot(res$sims.matrix[,2],type="l",main=expression(beta[1]))
abline(h=2,col="red")
plot(res$sims.matrix[,3],type="l",main=expression(tau))
abline(h=1,col="red")
par(mfrow=c(1,3))

plot(density(res$sims.matrix[,1]),main=expression(beta[0]))
abline(v=-2,col="red")
plot(density(res$sims.matrix[,2]),main=expression(beta[1]))
abline(v=2,col="red")
plot(density(res$sims.matrix[,3]),main=expression(tau))
abline(v=1,col="red")

Jags

########################################################################################
#############                          JAGS                                ############# 
########################################################################################
set.seed(20)
x <- runif(100,1.5,3)
y <- rnorm(100,-2+2*x)
y.cens <- ifelse(y>0,y,NA)
y.ind <- as.numeric(y>=0)
N = length(y)
model_code=  'model {
for (i in 1:N){
mu[i] <- beta0 + beta1*x[i]
y.ind[i] ~ dinterval(y.censored[i], 0)
y.censored[i] ~ dnorm(mu[i], tau)}
beta0 ~ dnorm(0,0.01)
beta1 ~ dnorm(0,0.01)
tau ~ dgamma(1,0.1)
}'
tobit.inits <- function() {
  list(beta0=1, beta1=1,tau=2,y.censored=ifelse(y.ind, NA, -abs(rnorm(N, 0, 1))))
}
?jags
m <- jags(model.file=textConnection(model_code),
          parameters.to.save = c("beta0", "beta1","tau"),
          n.iter=10000,n.burnin=1000,n.chains = 1,n.thin = 1,
          data=list(y.censored=y.cens, y.ind=y.ind, N=N,x=x),
          inits=tobit.inits,DIC=FALSE)
module glm loaded
module dic loaded
Compiling model graph
   Resolving undeclared variables
   Allocating nodes
Graph information:
   Observed stochastic nodes: 195
   Unobserved stochastic nodes: 8
   Total graph size: 508

Initializing model


  |                                                        
  |                                                  |   0%
  |                                                        
  |*                                                 |   2%
  |                                                        
  |**                                                |   4%
  |                                                        
  |***                                               |   7%
  |                                                        
  |****                                              |   9%
  |                                                        
  |******                                            |  11%
  |                                                        
  |*******                                           |  13%
  |                                                        
  |********                                          |  16%
  |                                                        
  |*********                                         |  18%
  |                                                        
  |**********                                        |  20%
  |                                                        
  |***********                                       |  22%
  |                                                        
  |************                                      |  24%
  |                                                        
  |*************                                     |  27%
  |                                                        
  |**************                                    |  29%
  |                                                        
  |****************                                  |  31%
  |                                                        
  |*****************                                 |  33%
  |                                                        
  |******************                                |  36%
  |                                                        
  |*******************                               |  38%
  |                                                        
  |********************                              |  40%
  |                                                        
  |*********************                             |  42%
  |                                                        
  |**********************                            |  44%
  |                                                        
  |***********************                           |  47%
  |                                                        
  |************************                          |  49%
  |                                                        
  |**************************                        |  51%
  |                                                        
  |***************************                       |  53%
  |                                                        
  |****************************                      |  56%
  |                                                        
  |*****************************                     |  58%
  |                                                        
  |******************************                    |  60%
  |                                                        
  |*******************************                   |  62%
  |                                                        
  |********************************                  |  64%
  |                                                        
  |*********************************                 |  67%
  |                                                        
  |**********************************                |  69%
  |                                                        
  |************************************              |  71%
  |                                                        
  |*************************************             |  73%
  |                                                        
  |**************************************            |  76%
  |                                                        
  |***************************************           |  78%
  |                                                        
  |****************************************          |  80%
  |                                                        
  |*****************************************         |  82%
  |                                                        
  |******************************************        |  84%
  |                                                        
  |*******************************************       |  87%
  |                                                        
  |********************************************      |  89%
  |                                                        
  |**********************************************    |  91%
  |                                                        
  |***********************************************   |  93%
  |                                                        
  |************************************************  |  96%
  |                                                        
  |************************************************* |  98%
  |                                                        
  |**************************************************| 100%
m$BUGSoutput$summary
           mean        sd       2.5%        25%       50%       75%     97.5%
beta0 -2.688581 0.4871077 -3.6641946 -3.0117060 -2.688885 -2.370395 -1.741422
beta1  2.360142 0.2163471  1.9399078  2.2164496  2.362275  2.503432  2.793005
tau    1.108847 0.1639959  0.8147208  0.9933266  1.101411  1.213167  1.448729
par(mfrow=c(1,3))
plot(m$BUGSoutput$sims.matrix[,1],type="l",main=expression(beta[0]))
abline(h=-2,col="red")
plot(m$BUGSoutput$sims.matrix[,2],type="l",main=expression(beta[1]))
abline(h=2,col="red")
plot(m$BUGSoutput$sims.matrix[,3],type="l",main=expression(tau))
abline(h=1,col="red")
par(mfrow=c(1,3))

plot(density(m$BUGSoutput$sims.matrix[,1]),main=expression(beta[0]))
abline(v=-2,col="red")
plot(density(m$BUGSoutput$sims.matrix[,2]),main=expression(beta[1]))
abline(v=2,col="red")
plot(density(m$BUGSoutput$sims.matrix[,3]),main=expression(tau))
abline(v=1,col="red")

Stan modelo normal

########################################################################################
#############                          STAN                                ############# 
########################################################################################
set.seed(20)
y = rnorm(1000,3,2)
y.censored <- ifelse(y>=0, y, 0)
y.ind <- as.numeric(y>=0)
N = length(y)
model = "data {
int<lower=0> N_obs;
int<lower=0> N_cens;
real y_obs[N_obs];
real<lower=min(y_obs)> U;
}
parameters {
real<lower=U> y_cens[N_cens];
real mu;
real<lower=0> sigma2;
}
transformed parameters {
real<lower=0> tau;
tau = 1 / sigma2; 
}
model {
y_obs ~ normal(mu, sqrt(sigma2));
y_cens ~ normal(0, 10);
mu ~ normal(0,10);
sigma2 ~ gamma(1,0.1);
}"
data <- list(y_obs=y.censored, y_cens=y, N_obs = length(y.censored), N_cens = length(y), U = 0)
fit <- stan(model_code = model,data = data, iter = 10000, warmup = 1000, chains = 1)

SAMPLING FOR MODEL 'e14823c6ba9dc00bd93917471a3cce2c' 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 / 10000 [  0%]  (Warmup)
Chain 1: Iteration: 1000 / 10000 [ 10%]  (Warmup)
Chain 1: Iteration: 1001 / 10000 [ 10%]  (Sampling)
Chain 1: Iteration: 2000 / 10000 [ 20%]  (Sampling)
Chain 1: Iteration: 3000 / 10000 [ 30%]  (Sampling)
Chain 1: Iteration: 4000 / 10000 [ 40%]  (Sampling)
Chain 1: Iteration: 5000 / 10000 [ 50%]  (Sampling)
Chain 1: Iteration: 6000 / 10000 [ 60%]  (Sampling)
Chain 1: Iteration: 7000 / 10000 [ 70%]  (Sampling)
Chain 1: Iteration: 8000 / 10000 [ 80%]  (Sampling)
Chain 1: Iteration: 9000 / 10000 [ 90%]  (Sampling)
Chain 1: Iteration: 10000 / 10000 [100%]  (Sampling)
Chain 1: 
Chain 1:  Elapsed Time: 4.77 seconds (Warm-up)
Chain 1:                30.399 seconds (Sampling)
Chain 1:                35.169 seconds (Total)
Chain 1: 
summary(fit,c("mu","tau"))
$summary
         mean      se_mean         sd      2.5%       25%       50%       75%    97.5%    n_eff      Rhat
mu  3.0300011 0.0004999933 0.05991698 2.9136245 2.9892271 3.0303034 3.0703253 3.145489 14360.56 1.0000211
tau 0.2701379 0.0001188452 0.01223221 0.2463536 0.2620211 0.2698582 0.2783503 0.294574 10593.67 0.9999091

$c_summary
, , chains = chain:1

         stats
parameter      mean         sd      2.5%       25%       50%       75%    97.5%
      mu  3.0300011 0.05991698 2.9136245 2.9892271 3.0303034 3.0703253 3.145489
      tau 0.2701379 0.01223221 0.2463536 0.2620211 0.2698582 0.2783503 0.294574
fitd = extract(fit)
par(mfrow=c(1,2))
plot(fitd$mu,type="l",main=expression(mu))
abline(h=3,col="red")
plot(fitd$tau,type="l",main=expression(tau))
abline(h=0.25,col="red")
par(mfrow=c(1,2))

plot(density(fitd$mu,type="l"),main=expression(beta[0]))
abline(v=3,col="red")
plot(density(fitd$tau,type="l"),main=expression(beta[1]))
abline(v=0.25,col="red")

Stan tobit

########################################################################################
#############                          STAN                                ############# 
########################################################################################
set.seed(20)
x <- runif(100,1.5,3)
y <- rnorm(100,-2+2*x)
y.cens <- ifelse(y>0,y,0)
y.ind <- as.numeric(y>=0)
N = length(y)
model = "data {
int<lower=0> N_obs;
int<lower=0> N_cens;
vector[N_obs] y_obs;
vector[N_obs] x;
real<lower=min(y_obs)> U;
}
parameters {
real<lower=U> y_cens[N_cens];
real beta0;
real beta1;
real<lower=0> sigma2;
}
transformed parameters {
real<lower=0> tau;
tau = 1 / sigma2; 
}
model {
y_obs ~ normal(beta0+beta1*x, sqrt(sigma2));
y_cens ~ normal(0, 10);
beta0 ~ normal(0,10);
beta1 ~ normal(0,10);
sigma2 ~ gamma(1,0.1);
}
generated quantities {
vector[N_obs] y_rep;
for(n in 1:N_obs) {
y_rep[n] = normal_rng(beta0 + beta1 * x[n], sqrt(sigma2));
}
}
"
data <- list(y_obs=y.cens, y_cens=y, N_obs = length(y.cens), N_cens = length(y), U = 0,x=x)
fit2 <- stan(model_code = model,data = data, iter = 10000, warmup = 1000, chains = 1)

SAMPLING FOR MODEL 'f7a6ef25f375eddfb9bc1460ee975394' 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 / 10000 [  0%]  (Warmup)
Chain 1: Iteration: 1000 / 10000 [ 10%]  (Warmup)
Chain 1: Iteration: 1001 / 10000 [ 10%]  (Sampling)
Chain 1: Iteration: 2000 / 10000 [ 20%]  (Sampling)
Chain 1: Iteration: 3000 / 10000 [ 30%]  (Sampling)
Chain 1: Iteration: 4000 / 10000 [ 40%]  (Sampling)
Chain 1: Iteration: 5000 / 10000 [ 50%]  (Sampling)
Chain 1: Iteration: 6000 / 10000 [ 60%]  (Sampling)
Chain 1: Iteration: 7000 / 10000 [ 70%]  (Sampling)
Chain 1: Iteration: 8000 / 10000 [ 80%]  (Sampling)
Chain 1: Iteration: 9000 / 10000 [ 90%]  (Sampling)
Chain 1: Iteration: 10000 / 10000 [100%]  (Sampling)
Chain 1: 
Chain 1:  Elapsed Time: 0.815 seconds (Warm-up)
Chain 1:                5.686 seconds (Sampling)
Chain 1:                6.501 seconds (Total)
Chain 1: 
summary(fit2,c("beta0","beta1","sigma2"))
$summary
             mean     se_mean        sd      2.5%        25%        50%       75%     97.5%     n_eff      Rhat
beta0  -2.5029309 0.005461745 0.4608263 -3.402576 -2.8167268 -2.5013279 -2.189749 -1.583587  7118.880 0.9999093
beta1   2.2875233 0.002451611 0.2052878  1.886756  2.1474523  2.2848043  2.428126  2.691587  7011.696 0.9999060
sigma2  0.8801829 0.001066457 0.1311793  0.665012  0.7881697  0.8669909  0.957052  1.175921 15130.167 1.0001735

$c_summary
, , chains = chain:1

         stats
parameter       mean        sd      2.5%        25%        50%       75%     97.5%
   beta0  -2.5029309 0.4608263 -3.402576 -2.8167268 -2.5013279 -2.189749 -1.583587
   beta1   2.2875233 0.2052878  1.886756  2.1474523  2.2848043  2.428126  2.691587
   sigma2  0.8801829 0.1311793  0.665012  0.7881697  0.8669909  0.957052  1.175921
fitd = extract(fit2)
par(mfrow=c(1,3))
plot(fitd$beta0,type="l",main=expression(beta[0]))
abline(h=-2,col="red")
plot(fitd$beta1,type="l",main=expression(beta[1]))
abline(h=2,col="red")
plot(fitd$sigma2,type="l",main=expression(sigma^2))
abline(h=1,col="red")
par(mfrow=c(1,3))

plot(density(fitd$beta0,type="l"),main=expression(beta[0]))
abline(v=-2,col="red")
plot(density(fitd$beta1,type="l"),main=expression(beta[1]))
abline(v=2,col="red")
plot(density(fitd$sigma2,type="l"),main=expression(sigma^2))
abline(v=1,col="red")

Nimble 1

########################################################################################
#############                          NIMBLE                              ############# 
########################################################################################
set.seed(20)
x <- runif(100,1.5,3)
y <- rnorm(100,-2+2*x)
y.cens <- ifelse(y>0,y,NA)
y.ind <- as.numeric(y>=0)
N = length(y)
simpleCode1 <- nimbleCode({
for (i in 1:N){
mu[i] <- beta0 + beta1*x[i]
y.ind[i] ~ dinterval(y.censored[i], 0)
y.censored[i] ~ dnorm(mu[i], tau)}
beta0 ~ dnorm(0,0.01)
beta1 ~ dnorm(0,0.01)
tau ~ dgamma(1,0.1)
})
 
tobit.inits <- function() {
  list(beta0=1, beta1=1,tau=2,y.censored=ifelse(y.ind, NA, -abs(rnorm(N, 0, 1))))
}
simpleModel1 <- nimbleModel(simpleCode1,data=list(y.censored=y.cens, y.ind=y.ind, N=N,x=x),constants = list(N = N))
defining model...
BUGSmodel: found the same variable(s) in both 'data' and 'constants'; using variable(s) from 'data'.
building model...
setting data and initial values...
data not used in model: Nrunning calculate on model (any error reports that follow may simply reflect missing values in model variables) ... 
checking model sizes and dimensions... This model is not fully initialized. This is not an error. To see which variables are not initialized, use model$initializeInfo(). For more information on model initialization, see help(modelInitialization).
model building finished.
mcmc.out <- nimbleMCMC(code = simpleModel1, 
                       monitors=c("beta0", "beta1","tau"),
                       nchains = 1, 
                       niter = 10000,
                       nburnin = 1000,
                       summary = TRUE, 
                       progressBar = TRUE)
compiling... this may take a minute. Use 'showCompilerOutput = TRUE' to see C++ compiler details.
compilation finished.
running chain 1...
|-------------|-------------|-------------|-------------|
|-------------------------------------------------------|
mcmc.out$summary
           Mean    Median   St.Dev.  95%CI_low 95%CI_upp
beta0 -2.680071 -2.663973 0.4857003 -3.6917210 -1.775284
beta1  2.356633  2.348672 0.2151124  1.9515371  2.801466
tau    1.111285  1.101014 0.1627670  0.8139987  1.446730
par(mfrow=c(1,3))
plot(mcmc.out$samples[,1],type="l",main=expression(beta[0]))
abline(h=-2,col="red")
plot(mcmc.out$samples[,2],type="l",main=expression(beta[1]))
abline(h=2,col="red")
plot(mcmc.out$samples[,3],type="l",main=expression(tau))
abline(h=1,col="red")
par(mfrow=c(1,3))

plot(density(mcmc.out$samples[,1]),main=expression(beta[0]))
abline(v=-2,col="red")
plot(density(mcmc.out$samples[,2]),main=expression(beta[1]))
abline(v=2,col="red")
plot(density(mcmc.out$samples[,3]),main=expression(tau))
abline(v=1,col="red")

geweke.diag(mcmc.out$samples)

Fraction in 1st window = 0.1
Fraction in 2nd window = 0.5 

  beta0   beta1     tau 
 0.1693 -0.1391  0.4951 
raftery.diag(mcmc.out$samples)

Quantile (q) = 0.025
Accuracy (r) = +/- 0.005
Probability (s) = 0.95 
                                             
       Burn-in  Total Lower bound  Dependence
       (M)      (N)   (Nmin)       factor (I)
 beta0 44       46372 3746         12.40     
 beta1 48       51728 3746         13.80     
 tau   2        3973  3746          1.06     

Nimble 2

########################################################################################
#############                          NIMBLE                              ############# 
########################################################################################
set.seed(20)
x <- runif(100,1.5,3)
y <- rnorm(100,-2+2*x)
y.cens <- ifelse(y>0,y,NA)
y.ind <- as.numeric(y>=0)
N = length(y)
simpleCode1 <- nimbleCode({
for (i in 1:N){
mu[i] <- beta0 + beta1*x[i]
y.ind[i] ~ dinterval(y.censored[i], 0)
y.censored[i] ~ dnorm(mu[i], tau)}
beta0 ~ dnorm(0,0.01)
beta1 ~ dnorm(0,0.01)
tau ~ dgamma(1,0.1)
})
 
tobit.inits <- function() {
  list(beta0=1, beta1=1,tau=2,y.censored=ifelse(y.ind, NA, -abs(rnorm(N, 0, 1))))
}
simpleModel1 <- nimbleModel(simpleCode1,data=list(y.censored=y.cens, y.ind=y.ind, N=N,x=x),constants = list(N = N))
defining model...
BUGSmodel: found the same variable(s) in both 'data' and 'constants'; using variable(s) from 'data'.
building model...
setting data and initial values...
data not used in model: Nrunning calculate on model (any error reports that follow may simply reflect missing values in model variables) ... 
checking model sizes and dimensions... This model is not fully initialized. This is not an error. To see which variables are not initialized, use model$initializeInfo(). For more information on model initialization, see help(modelInitialization).
model building finished.
mcmc.out <- nimbleMCMC(code = simpleModel1, 
                       monitors=c("beta0", "beta1","tau"),
                       nchains = 1, 
                       niter = 100000,
                       nburnin = 1000,
                       summary = TRUE, 
                       progressBar = TRUE)
compiling... this may take a minute. Use 'showCompilerOutput = TRUE' to see C++ compiler details.
compilation finished.
running chain 1...
|-------------|-------------|-------------|-------------|
|-------------------------------------------------------|
mcmc.out$summary
           Mean    Median   St.Dev.  95%CI_low 95%CI_upp
beta0 -2.692343 -2.693460 0.4915015 -3.6561635 -1.705984
beta1  2.361458  2.362215 0.2180700  1.9235208  2.790032
tau    1.110457  1.102130 0.1630927  0.8148995  1.454054
par(mfrow=c(1,3))
plot(mcmc.out$samples[,1],type="l",main=expression(beta[0]))
abline(h=-2,col="red")
plot(mcmc.out$samples[,2],type="l",main=expression(beta[1]))
abline(h=2,col="red")
plot(mcmc.out$samples[,3],type="l",main=expression(tau))
abline(h=1,col="red")
par(mfrow=c(1,3))

plot(density(mcmc.out$samples[,1]),main=expression(beta[0]))
abline(v=-2,col="red")
plot(density(mcmc.out$samples[,2]),main=expression(beta[1]))
abline(v=2,col="red")
plot(density(mcmc.out$samples[,3]),main=expression(tau))
abline(v=1,col="red")

geweke.diag(mcmc.out$samples)

Fraction in 1st window = 0.1
Fraction in 2nd window = 0.5 

  beta0   beta1     tau 
 0.4908 -0.4564  0.3993 
raftery.diag(mcmc.out$samples)

Quantile (q) = 0.025
Accuracy (r) = +/- 0.005
Probability (s) = 0.95 
                                             
       Burn-in  Total Lower bound  Dependence
       (M)      (N)   (Nmin)       factor (I)
 beta0 54       65151 3746         17.40     
 beta1 77       83050 3746         22.20     
 tau   2        3927  3746          1.05     

Laplace

########################################################################################
#############                          LAPLACE                             ############# 
########################################################################################
set.seed(20)
x <- runif(100,1.5,3)
y <- rnorm(100,-2+2*x)
y.cens <- ifelse(y>0,y,NA)
y.ind <- as.numeric(y>=0)
N = length(y)
d = ifelse(y < 0, 0, 1)
model <- function(p,y,d,x) {
  log_lik <- sum(pnorm(0, p["beta0"] + p["beta1"]*x, 1/sqrt(p["tau"]), log = T)*(1-d)) + sum(d * dnorm(y, p["beta0"] + p["beta1"]*x, 1/sqrt(p["tau"]), log = T))
  log_post <- log_lik + dnorm(p["beta0"], 0, 10, log = T) + dnorm(p["beta1"], 0, 10, log = T) + dgamma(p["tau"], 1, 0.1, log = T)
  log_post
}
inits <- c(beta0 = 1,beta1 = 1, tau = 2)
fit <- optim(inits, model, control = list(fnscale = -1), hessian = TRUE,y = y,d = d,x=x,method = "SANN")
param_mean <- fit$par
param_cov_mat <- solve(-fit$hessian)
round(param_mean, 2)
beta0 beta1   tau 
-2.65  2.34  1.12 
qnorm(c(0.025,0.975),param_mean[1],sqrt(param_cov_mat[1,1]))
[1] -3.579736 -1.712075
qnorm(c(0.025,0.975),param_mean[2],sqrt(param_cov_mat[2,2]))
[1] 1.926429 2.755371
qnorm(c(0.025,0.975),param_mean[3],sqrt(param_cov_mat[3,3]))
[1] 0.7986063 1.4431002
LS0tDQp0aXRsZTogIlRvYml0Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmxpYnJhcnkoIlIyT3BlbkJVR1MiKQ0KbGlicmFyeSgiUjJqYWdzIikNCmxpYnJhcnkoImRwbHlyIikNCmxpYnJhcnkoInJzdGFuIikNCmxpYnJhcnkoIm5pbWJsZSIpDQpsaWJyYXJ5KCJIREludGVydmFsIikNCmxpYnJhcnkoIm12dG5vcm0iKQ0KbGlicmFyeSgiTGFwbGFjZXNEZW1vbiIpDQpgYGANCg0KI0ludHJvZHXDp8Ojbw0KDQpJbmZlcsOqbmNpYSBzb2IgbyBNb2RlbG8gVG9iaXQgdXRpbGl6YW5kbyBvcyBwYWNvdGVzIEJ1Z3MsIEphZ3MsIFN0YW4gZSBOaW1ibGUNCg0KVGFtYW5obyBhbW9zdHJhbCA9ICQxMDAkDQoNCiR4X2kgXHNpbSB1bmlmKDEsNTszKSQNCg0KR2FyYW50aW5kbyA1JSBkZSBjZW5zdXJhIGFtb3N0cmFsDQoNCg0KQSBhbW9zdHJhIGdlcmFkYSB0ZW0gYSBzZWd1aW50ZSBkaXN0cmlidWnDp8OjbzoNCg0KJHlfaSBcc2ltIE4oXGJldGFfMCtcYmV0YV8xXHRpbWVzIHhfaSwgXHRhdSkkDQoNCg0KQ29tIGFzIHNlZ3VpbnRlcyBwcmlvcmlzOg0KDQokXGJldGFfMCBcc2ltIE4oMDswLDAxKSQNCg0KJFxiZXRhXzEgXHNpbSBOKDA7MCwwMSkkDQoNCiRcdGF1IFxzaW0gR2EoMTswLDEpJA0KDQokRVtcdGF1XSA9IDEwJCBlICRWW1x0YXVdPTEwMCQNCg0KDQpQYXJhIGVmZWl0byBkZSBzaW11bGHDp8OjbywgZm9yYW0gcGFkcm9uaXphZGFzIGFzIHNlZ3VpbnRlcyBkZWZpbmnDp8O1ZXM6DQoNClNpbXVsYcOnw7VlcyA9IDEwMDAwDQoNCl9idXJuXyA9IDEwMDANCg0KVGFtYW5obyBhbW9zdHJhbCBhIHBvc3RlcmlvcmkgPSA5MDAwDQoNCkNhZGVpYXMgPSAxDQoNCkVzcGHDp2FtZW50byA9IDENCiANCg0KI0J1Z3MNCg0KYGBge3J9DQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMgICAgICAgICAgICAgICAgICAgICAgICAgIEJVR1MgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIyMjIyMjIyMjIyMgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCnNldC5zZWVkKDIwKQ0KDQp4IDwtIHJ1bmlmKDEwMCwxLjUsMykNCnkgPC0gcm5vcm0oMTAwLC0yKzIqeCkNCnkuY2VucyA8LSBpZmVsc2UoeT4wLHksTkEpDQp0YWJsZSh5LmNlbnM8MCkNCg0Kc2luaygicmVncmVzc2lvbi50eHQiKQ0KY2F0KCIgDQptb2RlbA0Kew0KIyBwcmlvcnMNCmJldGEwIH4gZG5vcm0oMCwwLjAxKQ0KYmV0YTEgfiBkbm9ybSgwLDAuMDEpDQp0YXUgfiBkZ2FtbWEoMSwwLjEpDQoNCiMgbGlrZWxpaG9vZA0KZm9yKGkgaW4gMTpOKQ0Kew0KbXVbaV0gPC0gYmV0YTAgKyBiZXRhMSp4W2ldDQp5W2ldIH4gZG5vcm0obXVbaV0sIHRhdSlDKDAsKX0NCn0NCiAgICAiKQ0Kc2luaygpDQoNCm15LmRhdGEgPC0gbGlzdCh5PXkuY2VucyxOPTEwMCx4PXgpDQoNCnBhcmFtcyA8LSBjKCJiZXRhMCIsImJldGExIiwidGF1IikNCg0KaW5pdHMgPC0gZnVuY3Rpb24oKXtsaXN0IChiZXRhMD0xLGJldGExPTEsdGF1PTIpfQ0KDQpyZXMgPC0gYnVncyhkYXRhPW15LmRhdGEsIGluaXRzPWluaXRzLCBwYXJhbWV0ZXJzLnRvLnNhdmU9cGFyYW1zLA0KICAgICAgICAgICAgbi5pdGVyPTEwMDAwLCBuLmNoYWlucz0xLCBuLmJ1cm5pbj0xMDAwLG4udGhpbiA9IDEsDQogICAgICAgICAgICBtb2RlbC5maWxlPSJyZWdyZXNzaW9uLnR4dCIsRElDPUZBTFNFKQ0KcmVzJHN1bW1hcnkNCg0KcGFyKG1mcm93PWMoMSwzKSkNCnBsb3QocmVzJHNpbXMubWF0cml4WywxXSx0eXBlPSJsIixtYWluPWV4cHJlc3Npb24oYmV0YVswXSkpDQphYmxpbmUoaD0tMixjb2w9InJlZCIpDQpwbG90KHJlcyRzaW1zLm1hdHJpeFssMl0sdHlwZT0ibCIsbWFpbj1leHByZXNzaW9uKGJldGFbMV0pKQ0KYWJsaW5lKGg9Mixjb2w9InJlZCIpDQpwbG90KHJlcyRzaW1zLm1hdHJpeFssM10sdHlwZT0ibCIsbWFpbj1leHByZXNzaW9uKHRhdSkpDQphYmxpbmUoaD0xLGNvbD0icmVkIikNCg0KDQpwYXIobWZyb3c9YygxLDMpKQ0KcGxvdChkZW5zaXR5KHJlcyRzaW1zLm1hdHJpeFssMV0pLG1haW49ZXhwcmVzc2lvbihiZXRhWzBdKSkNCmFibGluZSh2PS0yLGNvbD0icmVkIikNCnBsb3QoZGVuc2l0eShyZXMkc2ltcy5tYXRyaXhbLDJdKSxtYWluPWV4cHJlc3Npb24oYmV0YVsxXSkpDQphYmxpbmUodj0yLGNvbD0icmVkIikNCnBsb3QoZGVuc2l0eShyZXMkc2ltcy5tYXRyaXhbLDNdKSxtYWluPWV4cHJlc3Npb24odGF1KSkNCmFibGluZSh2PTEsY29sPSJyZWQiKQ0KDQpgYGANCg0KDQoNCiNKYWdzDQpgYGB7cn0NCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyAgICAgICAgICAgICAgICAgICAgICAgICAgSkFHUyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMjIyMjIyMjIyMjIyANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0Kc2V0LnNlZWQoMjApDQoNCnggPC0gcnVuaWYoMTAwLDEuNSwzKQ0KeSA8LSBybm9ybSgxMDAsLTIrMip4KQ0KeS5jZW5zIDwtIGlmZWxzZSh5PjAseSxOQSkNCnkuaW5kIDwtIGFzLm51bWVyaWMoeT49MCkNCk4gPSBsZW5ndGgoeSkNCg0KDQptb2RlbF9jb2RlPSAgJ21vZGVsIHsNCmZvciAoaSBpbiAxOk4pew0KDQptdVtpXSA8LSBiZXRhMCArIGJldGExKnhbaV0NCnkuaW5kW2ldIH4gZGludGVydmFsKHkuY2Vuc29yZWRbaV0sIDApDQp5LmNlbnNvcmVkW2ldIH4gZG5vcm0obXVbaV0sIHRhdSl9DQoNCmJldGEwIH4gZG5vcm0oMCwwLjAxKQ0KYmV0YTEgfiBkbm9ybSgwLDAuMDEpDQp0YXUgfiBkZ2FtbWEoMSwwLjEpDQoNCn0nDQoNCnRvYml0LmluaXRzIDwtIGZ1bmN0aW9uKCkgew0KICBsaXN0KGJldGEwPTEsIGJldGExPTEsdGF1PTIseS5jZW5zb3JlZD1pZmVsc2UoeS5pbmQsIE5BLCAtYWJzKHJub3JtKE4sIDAsIDEpKSkpDQp9DQoNCj9qYWdzDQoNCm0gPC0gamFncyhtb2RlbC5maWxlPXRleHRDb25uZWN0aW9uKG1vZGVsX2NvZGUpLA0KICAgICAgICAgIHBhcmFtZXRlcnMudG8uc2F2ZSA9IGMoImJldGEwIiwgImJldGExIiwidGF1IiksDQogICAgICAgICAgbi5pdGVyPTEwMDAwLG4uYnVybmluPTEwMDAsbi5jaGFpbnMgPSAxLG4udGhpbiA9IDEsDQogICAgICAgICAgZGF0YT1saXN0KHkuY2Vuc29yZWQ9eS5jZW5zLCB5LmluZD15LmluZCwgTj1OLHg9eCksDQogICAgICAgICAgaW5pdHM9dG9iaXQuaW5pdHMsRElDPUZBTFNFKQ0KDQptJEJVR1NvdXRwdXQkc3VtbWFyeQ0KDQpwYXIobWZyb3c9YygxLDMpKQ0KcGxvdChtJEJVR1NvdXRwdXQkc2ltcy5tYXRyaXhbLDFdLHR5cGU9ImwiLG1haW49ZXhwcmVzc2lvbihiZXRhWzBdKSkNCmFibGluZShoPS0yLGNvbD0icmVkIikNCnBsb3QobSRCVUdTb3V0cHV0JHNpbXMubWF0cml4WywyXSx0eXBlPSJsIixtYWluPWV4cHJlc3Npb24oYmV0YVsxXSkpDQphYmxpbmUoaD0yLGNvbD0icmVkIikNCnBsb3QobSRCVUdTb3V0cHV0JHNpbXMubWF0cml4WywzXSx0eXBlPSJsIixtYWluPWV4cHJlc3Npb24odGF1KSkNCmFibGluZShoPTEsY29sPSJyZWQiKQ0KDQpwYXIobWZyb3c9YygxLDMpKQ0KcGxvdChkZW5zaXR5KG0kQlVHU291dHB1dCRzaW1zLm1hdHJpeFssMV0pLG1haW49ZXhwcmVzc2lvbihiZXRhWzBdKSkNCmFibGluZSh2PS0yLGNvbD0icmVkIikNCnBsb3QoZGVuc2l0eShtJEJVR1NvdXRwdXQkc2ltcy5tYXRyaXhbLDJdKSxtYWluPWV4cHJlc3Npb24oYmV0YVsxXSkpDQphYmxpbmUodj0yLGNvbD0icmVkIikNCnBsb3QoZGVuc2l0eShtJEJVR1NvdXRwdXQkc2ltcy5tYXRyaXhbLDNdKSxtYWluPWV4cHJlc3Npb24odGF1KSkNCmFibGluZSh2PTEsY29sPSJyZWQiKQ0KDQoNCmBgYA0KDQoNCiNTdGFuIG1vZGVsbyBub3JtYWwNCg0KYGBge3Isd2FybmluZz1GQUxTRX0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMgICAgICAgICAgICAgICAgICAgICAgICAgIFNUQU4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIyMjIyMjIyMjIyMgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCnNldC5zZWVkKDIwKQ0KeSA9IHJub3JtKDEwMDAsMywyKQ0KeS5jZW5zb3JlZCA8LSBpZmVsc2UoeT49MCwgeSwgMCkNCnkuaW5kIDwtIGFzLm51bWVyaWMoeT49MCkNCk4gPSBsZW5ndGgoeSkNCg0KDQptb2RlbCA9ICJkYXRhIHsNCmludDxsb3dlcj0wPiBOX29iczsNCmludDxsb3dlcj0wPiBOX2NlbnM7DQpyZWFsIHlfb2JzW05fb2JzXTsNCnJlYWw8bG93ZXI9bWluKHlfb2JzKT4gVTsNCn0NCnBhcmFtZXRlcnMgew0KcmVhbDxsb3dlcj1VPiB5X2NlbnNbTl9jZW5zXTsNCnJlYWwgbXU7DQpyZWFsPGxvd2VyPTA+IHNpZ21hMjsNCn0NCnRyYW5zZm9ybWVkIHBhcmFtZXRlcnMgew0KcmVhbDxsb3dlcj0wPiB0YXU7DQp0YXUgPSAxIC8gc2lnbWEyOyANCn0NCm1vZGVsIHsNCnlfb2JzIH4gbm9ybWFsKG11LCBzcXJ0KHNpZ21hMikpOw0KeV9jZW5zIH4gbm9ybWFsKDAsIDEwKTsNCm11IH4gbm9ybWFsKDAsMTApOw0Kc2lnbWEyIH4gZ2FtbWEoMSwwLjEpOw0KfSINCg0KZGF0YSA8LSBsaXN0KHlfb2JzPXkuY2Vuc29yZWQsIHlfY2Vucz15LCBOX29icyA9IGxlbmd0aCh5LmNlbnNvcmVkKSwgTl9jZW5zID0gbGVuZ3RoKHkpLCBVID0gMCkNCmZpdCA8LSBzdGFuKG1vZGVsX2NvZGUgPSBtb2RlbCxkYXRhID0gZGF0YSwgaXRlciA9IDEwMDAwLCB3YXJtdXAgPSAxMDAwLCBjaGFpbnMgPSAxKQ0Kc3VtbWFyeShmaXQsYygibXUiLCJ0YXUiKSkNCg0KZml0ZCA9IGV4dHJhY3QoZml0KQ0KDQpwYXIobWZyb3c9YygxLDIpKQ0KcGxvdChmaXRkJG11LHR5cGU9ImwiLG1haW49ZXhwcmVzc2lvbihtdSkpDQphYmxpbmUoaD0zLGNvbD0icmVkIikNCnBsb3QoZml0ZCR0YXUsdHlwZT0ibCIsbWFpbj1leHByZXNzaW9uKHRhdSkpDQphYmxpbmUoaD0wLjI1LGNvbD0icmVkIikNCg0KcGFyKG1mcm93PWMoMSwyKSkNCnBsb3QoZGVuc2l0eShmaXRkJG11LHR5cGU9ImwiKSxtYWluPWV4cHJlc3Npb24oYmV0YVswXSkpDQphYmxpbmUodj0zLGNvbD0icmVkIikNCnBsb3QoZGVuc2l0eShmaXRkJHRhdSx0eXBlPSJsIiksbWFpbj1leHByZXNzaW9uKGJldGFbMV0pKQ0KYWJsaW5lKHY9MC4yNSxjb2w9InJlZCIpDQoNCmBgYA0KDQoNCg0KDQojU3RhbiB0b2JpdA0KDQpgYGB7cix3YXJuaW5nPUZBTFNFfQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyAgICAgICAgICAgICAgICAgICAgICAgICAgU1RBTiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMjIyMjIyMjIyMjIyANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0Kc2V0LnNlZWQoMjApDQoNCnggPC0gcnVuaWYoMTAwLDEuNSwzKQ0KeSA8LSBybm9ybSgxMDAsLTIrMip4KQ0KeS5jZW5zIDwtIGlmZWxzZSh5PjAseSwwKQ0KeS5pbmQgPC0gYXMubnVtZXJpYyh5Pj0wKQ0KTiA9IGxlbmd0aCh5KQ0KDQoNCm1vZGVsID0gImRhdGEgew0KaW50PGxvd2VyPTA+IE5fb2JzOw0KaW50PGxvd2VyPTA+IE5fY2VuczsNCnZlY3RvcltOX29ic10geV9vYnM7DQp2ZWN0b3JbTl9vYnNdIHg7DQpyZWFsPGxvd2VyPW1pbih5X29icyk+IFU7DQp9DQpwYXJhbWV0ZXJzIHsNCnJlYWw8bG93ZXI9VT4geV9jZW5zW05fY2Vuc107DQpyZWFsIGJldGEwOw0KcmVhbCBiZXRhMTsNCnJlYWw8bG93ZXI9MD4gc2lnbWEyOw0KfQ0KdHJhbnNmb3JtZWQgcGFyYW1ldGVycyB7DQpyZWFsPGxvd2VyPTA+IHRhdTsNCnRhdSA9IDEgLyBzaWdtYTI7IA0KfQ0KbW9kZWwgew0KeV9vYnMgfiBub3JtYWwoYmV0YTArYmV0YTEqeCwgc3FydChzaWdtYTIpKTsNCnlfY2VucyB+IG5vcm1hbCgwLCAxMCk7DQpiZXRhMCB+IG5vcm1hbCgwLDEwKTsNCmJldGExIH4gbm9ybWFsKDAsMTApOw0Kc2lnbWEyIH4gZ2FtbWEoMSwwLjEpOw0KfQ0KZ2VuZXJhdGVkIHF1YW50aXRpZXMgew0KdmVjdG9yW05fb2JzXSB5X3JlcDsNCmZvcihuIGluIDE6Tl9vYnMpIHsNCnlfcmVwW25dID0gbm9ybWFsX3JuZyhiZXRhMCArIGJldGExICogeFtuXSwgc3FydChzaWdtYTIpKTsNCn0NCn0NCiINCg0KZGF0YSA8LSBsaXN0KHlfb2JzPXkuY2VucywgeV9jZW5zPXksIE5fb2JzID0gbGVuZ3RoKHkuY2VucyksIE5fY2VucyA9IGxlbmd0aCh5KSwgVSA9IDAseD14KQ0KZml0MiA8LSBzdGFuKG1vZGVsX2NvZGUgPSBtb2RlbCxkYXRhID0gZGF0YSwgaXRlciA9IDEwMDAwLCB3YXJtdXAgPSAxMDAwLCBjaGFpbnMgPSAxKQ0Kc3VtbWFyeShmaXQyLGMoImJldGEwIiwiYmV0YTEiLCJzaWdtYTIiKSkNCg0KZml0ZCA9IGV4dHJhY3QoZml0MikNCg0KcGFyKG1mcm93PWMoMSwzKSkNCnBsb3QoZml0ZCRiZXRhMCx0eXBlPSJsIixtYWluPWV4cHJlc3Npb24oYmV0YVswXSkpDQphYmxpbmUoaD0tMixjb2w9InJlZCIpDQpwbG90KGZpdGQkYmV0YTEsdHlwZT0ibCIsbWFpbj1leHByZXNzaW9uKGJldGFbMV0pKQ0KYWJsaW5lKGg9Mixjb2w9InJlZCIpDQpwbG90KGZpdGQkc2lnbWEyLHR5cGU9ImwiLG1haW49ZXhwcmVzc2lvbihzaWdtYV4yKSkNCmFibGluZShoPTEsY29sPSJyZWQiKQ0KDQpwYXIobWZyb3c9YygxLDMpKQ0KcGxvdChkZW5zaXR5KGZpdGQkYmV0YTAsdHlwZT0ibCIpLG1haW49ZXhwcmVzc2lvbihiZXRhWzBdKSkNCmFibGluZSh2PS0yLGNvbD0icmVkIikNCnBsb3QoZGVuc2l0eShmaXRkJGJldGExLHR5cGU9ImwiKSxtYWluPWV4cHJlc3Npb24oYmV0YVsxXSkpDQphYmxpbmUodj0yLGNvbD0icmVkIikNCnBsb3QoZGVuc2l0eShmaXRkJHNpZ21hMix0eXBlPSJsIiksbWFpbj1leHByZXNzaW9uKHNpZ21hXjIpKQ0KYWJsaW5lKHY9MSxjb2w9InJlZCIpDQpgYGANCg0KDQojTmltYmxlIDENCmBgYHtyfQ0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyAgICAgICAgICAgICAgICAgICAgICAgICAgTklNQkxFICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMjIyMjIyMjIyMjIyANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0Kc2V0LnNlZWQoMjApDQoNCnggPC0gcnVuaWYoMTAwLDEuNSwzKQ0KeSA8LSBybm9ybSgxMDAsLTIrMip4KQ0KeS5jZW5zIDwtIGlmZWxzZSh5PjAseSxOQSkNCnkuaW5kIDwtIGFzLm51bWVyaWMoeT49MCkNCk4gPSBsZW5ndGgoeSkNCg0Kc2ltcGxlQ29kZTEgPC0gbmltYmxlQ29kZSh7DQpmb3IgKGkgaW4gMTpOKXsNCg0KbXVbaV0gPC0gYmV0YTAgKyBiZXRhMSp4W2ldDQp5LmluZFtpXSB+IGRpbnRlcnZhbCh5LmNlbnNvcmVkW2ldLCAwKQ0KeS5jZW5zb3JlZFtpXSB+IGRub3JtKG11W2ldLCB0YXUpfQ0KDQpiZXRhMCB+IGRub3JtKDAsMC4wMSkNCmJldGExIH4gZG5vcm0oMCwwLjAxKQ0KdGF1IH4gZGdhbW1hKDEsMC4xKQ0KDQp9KQ0KIA0KdG9iaXQuaW5pdHMgPC0gZnVuY3Rpb24oKSB7DQogIGxpc3QoYmV0YTA9MSwgYmV0YTE9MSx0YXU9Mix5LmNlbnNvcmVkPWlmZWxzZSh5LmluZCwgTkEsIC1hYnMocm5vcm0oTiwgMCwgMSkpKSkNCn0NCg0Kc2ltcGxlTW9kZWwxIDwtIG5pbWJsZU1vZGVsKHNpbXBsZUNvZGUxLGRhdGE9bGlzdCh5LmNlbnNvcmVkPXkuY2VucywgeS5pbmQ9eS5pbmQsIE49Tix4PXgpLGNvbnN0YW50cyA9IGxpc3QoTiA9IE4pKQ0KDQptY21jLm91dCA8LSBuaW1ibGVNQ01DKGNvZGUgPSBzaW1wbGVNb2RlbDEsIA0KICAgICAgICAgICAgICAgICAgICAgICBtb25pdG9ycz1jKCJiZXRhMCIsICJiZXRhMSIsInRhdSIpLA0KICAgICAgICAgICAgICAgICAgICAgICBuY2hhaW5zID0gMSwgDQogICAgICAgICAgICAgICAgICAgICAgIG5pdGVyID0gMTAwMDAsDQogICAgICAgICAgICAgICAgICAgICAgIG5idXJuaW4gPSAxMDAwLA0KICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5ID0gVFJVRSwgDQogICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzQmFyID0gVFJVRSkNCg0KbWNtYy5vdXQkc3VtbWFyeQ0KDQpwYXIobWZyb3c9YygxLDMpKQ0KcGxvdChtY21jLm91dCRzYW1wbGVzWywxXSx0eXBlPSJsIixtYWluPWV4cHJlc3Npb24oYmV0YVswXSkpDQphYmxpbmUoaD0tMixjb2w9InJlZCIpDQpwbG90KG1jbWMub3V0JHNhbXBsZXNbLDJdLHR5cGU9ImwiLG1haW49ZXhwcmVzc2lvbihiZXRhWzFdKSkNCmFibGluZShoPTIsY29sPSJyZWQiKQ0KcGxvdChtY21jLm91dCRzYW1wbGVzWywzXSx0eXBlPSJsIixtYWluPWV4cHJlc3Npb24odGF1KSkNCmFibGluZShoPTEsY29sPSJyZWQiKQ0KDQpwYXIobWZyb3c9YygxLDMpKQ0KcGxvdChkZW5zaXR5KG1jbWMub3V0JHNhbXBsZXNbLDFdKSxtYWluPWV4cHJlc3Npb24oYmV0YVswXSkpDQphYmxpbmUodj0tMixjb2w9InJlZCIpDQpwbG90KGRlbnNpdHkobWNtYy5vdXQkc2FtcGxlc1ssMl0pLG1haW49ZXhwcmVzc2lvbihiZXRhWzFdKSkNCmFibGluZSh2PTIsY29sPSJyZWQiKQ0KcGxvdChkZW5zaXR5KG1jbWMub3V0JHNhbXBsZXNbLDNdKSxtYWluPWV4cHJlc3Npb24odGF1KSkNCmFibGluZSh2PTEsY29sPSJyZWQiKQ0KDQpnZXdla2UuZGlhZyhtY21jLm91dCRzYW1wbGVzKQ0KcmFmdGVyeS5kaWFnKG1jbWMub3V0JHNhbXBsZXMpDQoNCmBgYA0KDQoNCiNOaW1ibGUgMg0KDQpgYGB7cn0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMgICAgICAgICAgICAgICAgICAgICAgICAgIE5JTUJMRSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIyMjIyMjIyMjIyMgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCnNldC5zZWVkKDIwKQ0KDQp4IDwtIHJ1bmlmKDEwMCwxLjUsMykNCnkgPC0gcm5vcm0oMTAwLC0yKzIqeCkNCnkuY2VucyA8LSBpZmVsc2UoeT4wLHksTkEpDQp5LmluZCA8LSBhcy5udW1lcmljKHk+PTApDQpOID0gbGVuZ3RoKHkpDQoNCnNpbXBsZUNvZGUxIDwtIG5pbWJsZUNvZGUoew0KZm9yIChpIGluIDE6Til7DQoNCm11W2ldIDwtIGJldGEwICsgYmV0YTEqeFtpXQ0KeS5pbmRbaV0gfiBkaW50ZXJ2YWwoeS5jZW5zb3JlZFtpXSwgMCkNCnkuY2Vuc29yZWRbaV0gfiBkbm9ybShtdVtpXSwgdGF1KX0NCg0KYmV0YTAgfiBkbm9ybSgwLDAuMDEpDQpiZXRhMSB+IGRub3JtKDAsMC4wMSkNCnRhdSB+IGRnYW1tYSgxLDAuMSkNCg0KfSkNCiANCnRvYml0LmluaXRzIDwtIGZ1bmN0aW9uKCkgew0KICBsaXN0KGJldGEwPTEsIGJldGExPTEsdGF1PTIseS5jZW5zb3JlZD1pZmVsc2UoeS5pbmQsIE5BLCAtYWJzKHJub3JtKE4sIDAsIDEpKSkpDQp9DQoNCnNpbXBsZU1vZGVsMSA8LSBuaW1ibGVNb2RlbChzaW1wbGVDb2RlMSxkYXRhPWxpc3QoeS5jZW5zb3JlZD15LmNlbnMsIHkuaW5kPXkuaW5kLCBOPU4seD14KSxjb25zdGFudHMgPSBsaXN0KE4gPSBOKSkNCg0KbWNtYy5vdXQgPC0gbmltYmxlTUNNQyhjb2RlID0gc2ltcGxlTW9kZWwxLCANCiAgICAgICAgICAgICAgICAgICAgICAgbW9uaXRvcnM9YygiYmV0YTAiLCAiYmV0YTEiLCJ0YXUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgbmNoYWlucyA9IDEsIA0KICAgICAgICAgICAgICAgICAgICAgICBuaXRlciA9IDEwMDAwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgbmJ1cm5pbiA9IDEwMDAsDQogICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcnkgPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3NCYXIgPSBUUlVFKQ0KDQptY21jLm91dCRzdW1tYXJ5DQoNCnBhcihtZnJvdz1jKDEsMykpDQpwbG90KG1jbWMub3V0JHNhbXBsZXNbLDFdLHR5cGU9ImwiLG1haW49ZXhwcmVzc2lvbihiZXRhWzBdKSkNCmFibGluZShoPS0yLGNvbD0icmVkIikNCnBsb3QobWNtYy5vdXQkc2FtcGxlc1ssMl0sdHlwZT0ibCIsbWFpbj1leHByZXNzaW9uKGJldGFbMV0pKQ0KYWJsaW5lKGg9Mixjb2w9InJlZCIpDQpwbG90KG1jbWMub3V0JHNhbXBsZXNbLDNdLHR5cGU9ImwiLG1haW49ZXhwcmVzc2lvbih0YXUpKQ0KYWJsaW5lKGg9MSxjb2w9InJlZCIpDQoNCnBhcihtZnJvdz1jKDEsMykpDQpwbG90KGRlbnNpdHkobWNtYy5vdXQkc2FtcGxlc1ssMV0pLG1haW49ZXhwcmVzc2lvbihiZXRhWzBdKSkNCmFibGluZSh2PS0yLGNvbD0icmVkIikNCnBsb3QoZGVuc2l0eShtY21jLm91dCRzYW1wbGVzWywyXSksbWFpbj1leHByZXNzaW9uKGJldGFbMV0pKQ0KYWJsaW5lKHY9Mixjb2w9InJlZCIpDQpwbG90KGRlbnNpdHkobWNtYy5vdXQkc2FtcGxlc1ssM10pLG1haW49ZXhwcmVzc2lvbih0YXUpKQ0KYWJsaW5lKHY9MSxjb2w9InJlZCIpDQoNCmdld2VrZS5kaWFnKG1jbWMub3V0JHNhbXBsZXMpDQpyYWZ0ZXJ5LmRpYWcobWNtYy5vdXQkc2FtcGxlcykNCg0KYGBgDQoNCg0KDQojTGFwbGFjZQ0KYGBge3J9DQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjICAgICAgICAgICAgICAgICAgICAgICAgICBMQVBMQUNFICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIyMjIyMjIyMjIyMjIA0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQoNCnNldC5zZWVkKDIwKQ0KDQp4IDwtIHJ1bmlmKDEwMCwxLjUsMykNCnkgPC0gcm5vcm0oMTAwLC0yKzIqeCkNCnkuY2VucyA8LSBpZmVsc2UoeT4wLHksTkEpDQp5LmluZCA8LSBhcy5udW1lcmljKHk+PTApDQpOID0gbGVuZ3RoKHkpDQoNCmQgPSBpZmVsc2UoeSA8IDAsIDAsIDEpDQoNCm1vZGVsIDwtIGZ1bmN0aW9uKHAseSxkLHgpIHsNCiAgbG9nX2xpayA8LSBzdW0ocG5vcm0oMCwgcFsiYmV0YTAiXSArIHBbImJldGExIl0qeCwgMS9zcXJ0KHBbInRhdSJdKSwgbG9nID0gVCkqKDEtZCkpICsgc3VtKGQgKiBkbm9ybSh5LCBwWyJiZXRhMCJdICsgcFsiYmV0YTEiXSp4LCAxL3NxcnQocFsidGF1Il0pLCBsb2cgPSBUKSkNCiAgbG9nX3Bvc3QgPC0gbG9nX2xpayArIGRub3JtKHBbImJldGEwIl0sIDAsIDEwLCBsb2cgPSBUKSArIGRub3JtKHBbImJldGExIl0sIDAsIDEwLCBsb2cgPSBUKSArIGRnYW1tYShwWyJ0YXUiXSwgMSwgMC4xLCBsb2cgPSBUKQ0KICBsb2dfcG9zdA0KfQ0KDQppbml0cyA8LSBjKGJldGEwID0gMSxiZXRhMSA9IDEsIHRhdSA9IDIpDQpmaXQgPC0gb3B0aW0oaW5pdHMsIG1vZGVsLCBjb250cm9sID0gbGlzdChmbnNjYWxlID0gLTEpLCBoZXNzaWFuID0gVFJVRSx5ID0geSxkID0gZCx4PXgsbWV0aG9kID0gIlNBTk4iKQ0KcGFyYW1fbWVhbiA8LSBmaXQkcGFyDQpwYXJhbV9jb3ZfbWF0IDwtIHNvbHZlKC1maXQkaGVzc2lhbikNCnJvdW5kKHBhcmFtX21lYW4sIDIpDQoNCg0KcW5vcm0oYygwLjAyNSwwLjk3NSkscGFyYW1fbWVhblsxXSxzcXJ0KHBhcmFtX2Nvdl9tYXRbMSwxXSkpDQpxbm9ybShjKDAuMDI1LDAuOTc1KSxwYXJhbV9tZWFuWzJdLHNxcnQocGFyYW1fY292X21hdFsyLDJdKSkNCnFub3JtKGMoMC4wMjUsMC45NzUpLHBhcmFtX21lYW5bM10sc3FydChwYXJhbV9jb3ZfbWF0WzMsM10pKQ0KDQpgYGANCg0KDQo=