library("R2OpenBUGS")
library("R2jags")
library("R2stan")
library("dplyr")
library("rstan")
library("nimble")
library("HDInterval")
library("tictoc")
library("mvtnorm")


########################################################################################
#############                          DADOS                               ############# 
########################################################################################

set.seed(6)

y  = list()
y.censt = list()
y.obs = list()
y.ind = list()
censura = vector()

for (i in 1:100){
  n=100
  y[[i]] <- rnorm(100,3,2)
  y.censt[[i]] <- ifelse(y[[i]]>0,y[[i]],NA)}

for (i in 1:100){y.ind[[i]] <- as.numeric(y[[i]]>=0)}

for (i in 1:100){censura[i] = as.vector(table(y.censt[[i]]>0)/100)};mean(censura)


N = length(y)


########################################################################################
#############                          BUGS                                ############# 
########################################################################################

amostra_bugs = list()
final_bugs = list()
mu_bugs  = list()
tau_bugs = list()
media_mu_bugs = vector()
media_tau_bugs = vector()
sd_mu_bugs = vector()
sd_tau_bugs = vector()
eqm_mu_bugs  = vector()
eqm_tau_bugs  = vector()
hdi_bugs = list()


tic()
for (i in 1:100){
  
y.cens = y.censt[[i]]

sink("regression.txt")
cat(" 
  model
  {
  # priors
  a ~ dnorm(0,0.01)
  b ~ dgamma(1,10)
  
  # likelihood
  for(i in 1:N)
  {
  y[i] ~ dnorm(a, b)C(0,1)}
  }
  ")
sink()

my.data <- list(y=y.cens, N=100)

params <- c("a", "b")

inits <- function(){list(beta0=1,beta1=1)}

amostra_bugs[[i]] <- bugs(data=my.data, inits=inits, parameters.to.save=params,
            n.iter=10000, n.chains=1, n.burnin=1000,
              model.file="regression.txt",DIC=FALSE)  
  

final_bugs[[i]] = amostra_bugs[[i]]$sims.matrix

mu_bugs[[i]]  = final_bugs[[i]][,1]
tau_bugs[[i]]  = final_bugs[[i]][,2]

media_mu_bugs[i]  = mean(mu_bugs[[i]]) 
media_tau_bugs[i]  = mean(tau_bugs[[i]]) 

sd_mu_bugs[i]  = sd(mu_bugs[[i]])
sd_tau_bugs[i]  = sd(tau_bugs[[i]])

eqm_mu_bugs[i]  = mean((mu_bugs[[i]]-3)^2)
eqm_tau_bugs[i]  = mean((tau_bugs[[i]]-0.25)^2)

hdi_bugs[[i]] = hdi(final_bugs[[i]])

}
toc()

t_bugs = 162 

media_bugs=c(mean(media_mu_bugs),mean(media_tau_bugs))
sd_bugs=c(mean(sd_mu_bugs),mean(sd_tau_bugs))
eqm_bugs=c(mean(eqm_mu_bugs),mean(eqm_tau_bugs))
medidas_bugs=cbind(media_bugs,sd_bugs,eqm_bugs)
rownames(medidas_bugs) = c("mu","tau")

hdp_bugs=t(as.data.frame(hdi(final_bugs)))
aux = as.character(rownames(hdp_bugs))
real=rep(c(3,0.25),10)
hdp_bugs=as.data.frame(cbind(aux,hdp_bugs,real))

hdp_bugs$lower = as.numeric(as.character(hdp_bugs$lower))
hdp_bugs$upper = as.numeric(as.character(hdp_bugs$upper))
hdp_bugs$real = as.numeric(as.character(hdp_bugs$real))

hdp_bugs = arrange(hdp_bugs,aux)

prop_bugs=ifelse(hdp_bugs$lower<hdp_bugs$real&hdp_bugs$real<hdp_bugs$upper,1,0)

hdp_bugs=as.data.frame(cbind(hdp_bugs,prop_bugs))

mu_prop_bugs=sum(hdp_bugs$prop_bugs[1:100])/100;tau_prop_bugs=sum(hdp_bugs$prop_bugs[101:200])/100
cred_bugs = rbind(mu_prop_bugs,tau_prop_bugs);colnames(cred_bugs)=c("cred_bugs")

tabela_bugs = cbind(medidas_bugs,cred_bugs,t_bugs)

########################################################################################
#############                          jags                                ############# 
########################################################################################

amostra_jags = list()
final_jags = list()
mu_jags  = list()
tau_jags = list()
media_mu_jags = vector()
media_tau_jags = vector()
sd_mu_jags = vector()
sd_tau_jags = vector()
eqm_mu_jags  = vector()
eqm_tau_jags  = vector()
hdi_jags = list()

tic()
for (i in 1:100){
  
  y.cens = y.censt[[i]]
  y.indx  = y.ind[[i]]

  model_code=  'model {
  for (j in 1:N){
  y.indx[j] ~ dinterval(y.cens[j], 0)
  y.cens[j] ~ dnorm(a,b)
  }
  a ~ dnorm(0,0.01)
  b ~ dgamma(1,10)
}'

tobit.inits <- function(){list(a=0, b=1,y.cens=ifelse(y.indx, NA, -abs(rnorm(N, 0, 1))))}
  
amostra_jags[[i]] <- jags(model.file=textConnection(model_code),
            parameters.to.save = c("a", "b"),
            data=list(y.cens=y.cens, y.indx=y.indx, N=N),
            inits=tobit.inits,DIC = FALSE,n.iter = 10000,n.burnin = 1000)

final_jags[[i]] = amostra_jags[[i]][["BUGSoutput"]][["sims.matrix"]]

mu_jags[[i]]  = final_jags[[i]][,1]
tau_jags[[i]]  = final_jags[[i]][,2]

media_mu_jags[i]  = mean(mu_jags[[i]]) 
media_tau_jags[i]  = mean(tau_jags[[i]]) 

sd_mu_jags[i]  = sd(mu_jags[[i]])
sd_tau_jags[i]  = sd(tau_jags[[i]])

eqm_mu_jags[i]  = mean((mu_jags[[i]]-3)^2)
eqm_tau_jags[i]  = mean((tau_jags[[i]]-0.25)^2)

hdi_jags[[i]] = hdi(final_jags[[i]])

}
toc()

t_jags = 13

media_jags=c(mean(media_mu_jags),mean(media_tau_jags))
sd_jags=c(mean(sd_mu_jags),mean(sd_tau_jags))
eqm_jags=c(mean(eqm_mu_jags),mean(eqm_tau_jags))
medidas_jags=cbind(media_jags,sd_jags,eqm_jags)
rownames(medidas_jags) = c("mu","tau")

hdp_jags=t(as.data.frame(hdi(final_jags)))
aux = as.character(rownames(hdp_jags))
real=rep(c(3,0.25),10)
hdp_jags=as.data.frame(cbind(aux,hdp_jags,real))

hdp_jags$lower = as.numeric(as.character(hdp_jags$lower))
hdp_jags$upper = as.numeric(as.character(hdp_jags$upper))
hdp_jags$real = as.numeric(as.character(hdp_jags$real))

hdp_jags = arrange(hdp_jags,aux)

prop_jags=ifelse(hdp_jags$lower<hdp_jags$real&hdp_jags$real<hdp_jags$upper,1,0)

hdp_jags=as.data.frame(cbind(hdp_jags,prop_jags))

mu_prop_jags=sum(hdp_jags$prop_jags[1:100])/100;tau_prop_jags=sum(hdp_jags$prop_jags[101:200])/100
cred_jags = rbind(mu_prop_jags,tau_prop_jags);colnames(cred_jags)=c("cred_jags")

tabela_jags = cbind(medidas_jags,cred_jags,t_jags)


########################################################################################
#############                          STAN                                ############# 
########################################################################################

fit = list()
amostra_stan = list()
final_stan = list()
mu_stan  = list()
tau_stan = list()
media_mu_stan = vector()
media_tau_stan = vector()
sd_mu_stan = vector()
sd_tau_stan = vector()
eqm_mu_stan  = vector()
eqm_tau_stan  = vector()
hdi_stan = list()

tic()
for (i in 1:100){
  y = rnorm(1000,3,2)
  y.censored <- ifelse(y>=0, y, NA)
  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,10);
}"


data <- list(y_obs=y, y_cens=y.censored, N_obs = N, N_cens = N, U = 0)

fit[[i]] <- stan(model_code = model,data = data, iter = 10000, warmup = 1000, chains = 1)

amostra_stan[[i]] <- extract(fit[[i]])

mu_stan[[i]]  = amostra_stan[[i]][["mu"]]
tau_stan[[i]]  = amostra_stan[[i]][["tau"]]

final_stan[[i]] = cbind(amostra_stan[[i]][["mu"]],amostra_stan[[i]][["tau"]])

mu_stan[[i]]  = final_stan[[i]][,1]
tau_stan[[i]]  = final_stan[[i]][,2]

media_mu_stan[i]  = mean(mu_stan[[i]]) 
media_tau_stan[i]  = mean(tau_stan[[i]]) 

sd_mu_stan[i]  = sd(mu_stan[[i]])
sd_tau_stan[i]  = sd(tau_stan[[i]])

eqm_mu_stan[i]  = mean((mu_stan[[i]]-3)^2)
eqm_tau_stan[i]  = mean((tau_stan[[i]]-0.25)^2)

hdi_stan[[i]] = hdi(final_stan[[i]])}
toc()

t_stan = 3803 

media_stan=c(mean(media_mu_stan),mean(media_tau_stan))
sd_stan=c(mean(sd_mu_stan),mean(sd_tau_stan))
eqm_stan=c(mean(eqm_mu_stan),mean(eqm_tau_stan))
medidas_stan=cbind(media_stan,sd_stan,eqm_stan)
rownames(medidas_stan) = c("mu","tau")

hdp_stan=t(as.data.frame(hdi(final_stan)))
aux = as.character(rownames(hdp_stan))
real=rep(c(3,0.25),10)
hdp_stan=as.data.frame(cbind(aux,hdp_stan,real))


hdp_stan$lower = as.numeric(as.character(hdp_stan$lower))
hdp_stan$upper = as.numeric(as.character(hdp_stan$upper))
hdp_stan$real = as.numeric(as.character(hdp_stan$real))

hdp_stan = arrange(hdp_stan,aux)

prop_stan=ifelse(hdp_stan$lower<hdp_stan$real&hdp_stan$real<hdp_stan$upper,1,0)

hdp_stan=as.data.frame(cbind(hdp_stan,prop_stan))

mu_prop_stan=sum(hdp_stan$prop_stan[1:43])/44;tau_prop_stan=sum(hdp_stan$prop_stan[44:88])/44
cred_stan = rbind(mu_prop_stan,tau_prop_stan);colnames(cred_stan)=c("cred_stan")

tabela_stan = cbind(medidas_stan,cred_stan,t_stan)

rm(fit)

########################################################################################
#############                          NIMBLE                              ############# 
########################################################################################

amostra_nimble = list()
final_nimble = list()
mu_nimble  = list()
tau_nimble = list()
media_mu_nimble = vector()
media_tau_nimble = vector()
sd_mu_nimble = vector()
sd_tau_nimble = vector()
eqm_mu_nimble  = vector()
eqm_tau_nimble  = vector()
hdi_nimble = list()

tic()
for (i in 1:100){
y = rnorm(1000,3,2)
y.censored <- ifelse(y>=0, y, NA)
y.ind <- as.numeric(y>=0)
N = length(y)

simpleCode1 <- nimbleCode({
  for (j in 1:N){
    y.ind[j] ~ dinterval(y.censored[j], 0)
    y.censored[j] ~ dnorm(a,b)
  }
  a ~ dnorm(0, .01)
  b ~ dgamma(1,10)
  sigma2 <- 1/b})

tobit.inits <- function() {
  list(a=0, b=1, 
       y.censored=ifelse(y.ind, NA, -abs(rnorm(N, 0, 1))))
}

simpleModel1 <- nimbleModel(simpleCode1,
                            data=list(y.censored=y.censored, y.ind=y.ind, N=N),
                            constants = list(N = N),
                            inits = list(a=0, b=1,y.censored=ifelse(y.ind, NA, -abs(rnorm(N, 0, 1)))))

amostra_nimble[[i]] <- nimbleMCMC(code = simpleModel1, 
                       monitors=c("a", "b"),
                       nchains = 1, 
                       niter = 1000,
                       summary = TRUE, 
                       progressBar = TRUE)

final_nimble[[i]] = amostra_nimble[[i]][["samples"]]

mu_nimble[[i]]  = final_nimble[[i]][,1]
tau_nimble[[i]]  = final_nimble[[i]][,2]

media_mu_nimble[i]  = mean(mu_nimble[[i]]) 
media_tau_nimble[i]  = mean(tau_nimble[[i]]) 

sd_mu_nimble[i]  = sd(mu_nimble[[i]])
sd_tau_nimble[i]  = sd(tau_nimble[[i]])

eqm_mu_nimble[i]  = mean((mu_nimble[[i]]-3)^2)
eqm_tau_nimble[i]  = mean((tau_nimble[[i]]-0.25)^2)

hdi_nimble[[i]] = hdi(final_nimble[[i]])

}
toc()

t_nimble = 5787

media_nimble=c(mean(media_mu_nimble),mean(media_tau_nimble))
sd_nimble=c(mean(sd_mu_nimble),mean(sd_tau_nimble))
eqm_nimble=c(mean(eqm_mu_nimble),mean(eqm_tau_nimble))
medidas_nimble=cbind(media_nimble,sd_nimble,eqm_nimble)
rownames(medidas_nimble) = c("mu","tau")

hdp_nimble=t(as.data.frame(hdi(final_nimble)))
aux = as.character(rownames(hdp_nimble))
real=rep(c(3,0.25),10)
hdp_nimble=as.data.frame(cbind(aux,hdp_nimble,real))

hdp_nimble$lower = as.numeric(as.character(hdp_nimble$lower))
hdp_nimble$upper = as.numeric(as.character(hdp_nimble$upper))
hdp_nimble$real = as.numeric(as.character(hdp_nimble$real))

hdp_nimble = arrange(hdp_nimble,aux)

prop_nimble=ifelse(hdp_nimble$lower<hdp_nimble$real&hdp_nimble$real<hdp_nimble$upper,1,0)

hdp_nimble=as.data.frame(cbind(hdp_nimble,prop_nimble))

mu_prop_nimble=sum(hdp_nimble$prop_nimble[1:100])/100;tau_prop_nimble=sum(hdp_nimble$prop_nimble[101:200])/100
cred_nimble = rbind(mu_prop_nimble,tau_prop_nimble);colnames(cred_nimble)=c("cred_nimble")

tabela_nimble = cbind(medidas_nimble,cred_nimble,t_nimble)



########################################################################################
#############                          LAPLACE                             ############# 
########################################################################################

amostra_laplace = list()
final_laplace = list()
mu_laplace  = list()
tau_laplace = list()
media_mu_laplace = vector()
media_tau_laplace = vector()
sd_mu_laplace = vector()
sd_tau_laplace = vector()
eqm_mu_laplace  = vector()
eqm_tau_laplace  = vector()
hdi_laplace = list()


for (i in 1:100){
y <- rnorm(100,3,2)
y.cens <- ifelse(y>0,y,NA)
d = ifelse(y < 0, 0, 1)

model <- function(p,y,d) {
  log_lik <- pnorm(0, p["mu"], 1/sqrt(p["tau"]), log = T)*sum(1-d) + sum(d * dnorm(y, p["mu"], 1/sqrt(p["tau"]), log = T))
  log_post <- log_lik + dnorm(p["mu"], 0, 10, log = T) + dgamma(p["tau"], 1, 10, log = T)
  log_post
}

inits <- c(mu = 0, tau = 1)
fit <- optim(inits, model, control = list(fnscale = -1), hessian = TRUE, y = y, d = d)
param_mean <- fit$par
param_cov_mat <- solve(-fit$hessian)
round(param_mean, 2)

final_laplace[[i]] <- rmvnorm(10000, param_mean, param_cov_mat)

mu_laplace[[i]]  = final_laplace[[i]][,1]
tau_laplace[[i]]  = final_laplace[[i]][,2]

media_mu_laplace[i]  = mean(mu_laplace[[i]]) 
media_tau_laplace[i]  = mean(tau_laplace[[i]]) 

sd_mu_laplace[i]  = sd(mu_laplace[[i]])
sd_tau_laplace[i]  = sd(tau_laplace[[i]])

eqm_mu_laplace[i]  = mean((mu_laplace[[i]]-3)^2)
eqm_tau_laplace[i]  = mean((tau_laplace[[i]]-0.25)^2)

hdi_laplace[[i]] = hdi(final_laplace[[i]])
}


t_laplace = 1

media_laplace=c(mean(media_mu_laplace),mean(media_tau_laplace))
sd_laplace=c(mean(sd_mu_laplace),mean(sd_tau_laplace))
eqm_laplace=c(mean(eqm_mu_laplace),mean(eqm_tau_laplace))
medidas_laplace=cbind(media_laplace,sd_laplace,eqm_laplace)
rownames(medidas_laplace) = c("mu","tau")

hdp_laplace=t(as.data.frame(hdi(final_laplace)))
aux = as.character(rownames(hdp_laplace))
real=rep(c(3,0.25),10)
hdp_laplace=as.data.frame(cbind(aux,hdp_laplace,real))

hdp_laplace$lower = as.numeric(as.character(hdp_laplace$lower))
hdp_laplace$upper = as.numeric(as.character(hdp_laplace$upper))
hdp_laplace$real = as.numeric(as.character(hdp_laplace$real))

hdp_laplace = arrange(hdp_laplace,aux)

prop_laplace=ifelse(hdp_laplace$lower<hdp_laplace$real&hdp_laplace$real<hdp_laplace$upper,1,0)

hdp_laplace=as.data.frame(cbind(hdp_laplace,prop_laplace))

mu_prop_laplace=sum(hdp_laplace$prop_laplace[1:100])/100;tau_prop_laplace=sum(hdp_laplace$prop_laplace[101:200])/100
cred_laplace = rbind(mu_prop_laplace,tau_prop_laplace);colnames(cred_laplace)=c("cred_laplace")

tabela_laplace = cbind(medidas_laplace,cred_laplace,t_laplace)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCmBgYHtyfQ0KbGlicmFyeSgiUjJPcGVuQlVHUyIpDQpsaWJyYXJ5KCJSMmphZ3MiKQ0KbGlicmFyeSgiUjJzdGFuIikNCmxpYnJhcnkoImRwbHlyIikNCmxpYnJhcnkoInJzdGFuIikNCmxpYnJhcnkoIm5pbWJsZSIpDQpsaWJyYXJ5KCJIREludGVydmFsIikNCmxpYnJhcnkoInRpY3RvYyIpDQpsaWJyYXJ5KCJtdnRub3JtIikNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjICAgICAgICAgICAgICAgICAgICAgICAgICBEQURPUyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIyMjIyMjIyMjIyMjIA0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQpzZXQuc2VlZCg2KQ0KDQp5ICA9IGxpc3QoKQ0KeS5jZW5zdCA9IGxpc3QoKQ0KeS5vYnMgPSBsaXN0KCkNCnkuaW5kID0gbGlzdCgpDQpjZW5zdXJhID0gdmVjdG9yKCkNCg0KZm9yIChpIGluIDE6MTAwKXsNCiAgbj0xMDANCiAgeVtbaV1dIDwtIHJub3JtKDEwMCwzLDIpDQogIHkuY2Vuc3RbW2ldXSA8LSBpZmVsc2UoeVtbaV1dPjAseVtbaV1dLE5BKX0NCg0KZm9yIChpIGluIDE6MTAwKXt5LmluZFtbaV1dIDwtIGFzLm51bWVyaWMoeVtbaV1dPj0wKX0NCg0KZm9yIChpIGluIDE6MTAwKXtjZW5zdXJhW2ldID0gYXMudmVjdG9yKHRhYmxlKHkuY2Vuc3RbW2ldXT4wKS8xMDApfTttZWFuKGNlbnN1cmEpDQoNCg0KTiA9IGxlbmd0aCh5KQ0KDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMgICAgICAgICAgICAgICAgICAgICAgICAgIEJVR1MgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIyMjIyMjIyMjIyMgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCmFtb3N0cmFfYnVncyA9IGxpc3QoKQ0KZmluYWxfYnVncyA9IGxpc3QoKQ0KbXVfYnVncyAgPSBsaXN0KCkNCnRhdV9idWdzID0gbGlzdCgpDQptZWRpYV9tdV9idWdzID0gdmVjdG9yKCkNCm1lZGlhX3RhdV9idWdzID0gdmVjdG9yKCkNCnNkX211X2J1Z3MgPSB2ZWN0b3IoKQ0Kc2RfdGF1X2J1Z3MgPSB2ZWN0b3IoKQ0KZXFtX211X2J1Z3MgID0gdmVjdG9yKCkNCmVxbV90YXVfYnVncyAgPSB2ZWN0b3IoKQ0KaGRpX2J1Z3MgPSBsaXN0KCkNCg0KDQp0aWMoKQ0KZm9yIChpIGluIDE6MTAwKXsNCiAgDQp5LmNlbnMgPSB5LmNlbnN0W1tpXV0NCg0Kc2luaygicmVncmVzc2lvbi50eHQiKQ0KY2F0KCIgDQogIG1vZGVsDQogIHsNCiAgIyBwcmlvcnMNCiAgYSB+IGRub3JtKDAsMC4wMSkNCiAgYiB+IGRnYW1tYSgxLDEwKQ0KICANCiAgIyBsaWtlbGlob29kDQogIGZvcihpIGluIDE6TikNCiAgew0KICB5W2ldIH4gZG5vcm0oYSwgYilDKDAsMSl9DQogIH0NCiAgIikNCnNpbmsoKQ0KDQpteS5kYXRhIDwtIGxpc3QoeT15LmNlbnMsIE49MTAwKQ0KDQpwYXJhbXMgPC0gYygiYSIsICJiIikNCg0KaW5pdHMgPC0gZnVuY3Rpb24oKXtsaXN0KGJldGEwPTEsYmV0YTE9MSl9DQoNCmFtb3N0cmFfYnVnc1tbaV1dIDwtIGJ1Z3MoZGF0YT1teS5kYXRhLCBpbml0cz1pbml0cywgcGFyYW1ldGVycy50by5zYXZlPXBhcmFtcywNCiAgICAgICAgICAgIG4uaXRlcj0xMDAwMCwgbi5jaGFpbnM9MSwgbi5idXJuaW49MTAwMCwNCiAgICAgICAgICAgICAgbW9kZWwuZmlsZT0icmVncmVzc2lvbi50eHQiLERJQz1GQUxTRSkgIA0KICANCg0KZmluYWxfYnVnc1tbaV1dID0gYW1vc3RyYV9idWdzW1tpXV0kc2ltcy5tYXRyaXgNCg0KbXVfYnVnc1tbaV1dICA9IGZpbmFsX2J1Z3NbW2ldXVssMV0NCnRhdV9idWdzW1tpXV0gID0gZmluYWxfYnVnc1tbaV1dWywyXQ0KDQptZWRpYV9tdV9idWdzW2ldICA9IG1lYW4obXVfYnVnc1tbaV1dKSANCm1lZGlhX3RhdV9idWdzW2ldICA9IG1lYW4odGF1X2J1Z3NbW2ldXSkgDQoNCnNkX211X2J1Z3NbaV0gID0gc2QobXVfYnVnc1tbaV1dKQ0Kc2RfdGF1X2J1Z3NbaV0gID0gc2QodGF1X2J1Z3NbW2ldXSkNCg0KZXFtX211X2J1Z3NbaV0gID0gbWVhbigobXVfYnVnc1tbaV1dLTMpXjIpDQplcW1fdGF1X2J1Z3NbaV0gID0gbWVhbigodGF1X2J1Z3NbW2ldXS0wLjI1KV4yKQ0KDQpoZGlfYnVnc1tbaV1dID0gaGRpKGZpbmFsX2J1Z3NbW2ldXSkNCg0KfQ0KdG9jKCkNCg0KdF9idWdzID0gMTYyIA0KDQptZWRpYV9idWdzPWMobWVhbihtZWRpYV9tdV9idWdzKSxtZWFuKG1lZGlhX3RhdV9idWdzKSkNCnNkX2J1Z3M9YyhtZWFuKHNkX211X2J1Z3MpLG1lYW4oc2RfdGF1X2J1Z3MpKQ0KZXFtX2J1Z3M9YyhtZWFuKGVxbV9tdV9idWdzKSxtZWFuKGVxbV90YXVfYnVncykpDQptZWRpZGFzX2J1Z3M9Y2JpbmQobWVkaWFfYnVncyxzZF9idWdzLGVxbV9idWdzKQ0Kcm93bmFtZXMobWVkaWRhc19idWdzKSA9IGMoIm11IiwidGF1IikNCg0KaGRwX2J1Z3M9dChhcy5kYXRhLmZyYW1lKGhkaShmaW5hbF9idWdzKSkpDQphdXggPSBhcy5jaGFyYWN0ZXIocm93bmFtZXMoaGRwX2J1Z3MpKQ0KcmVhbD1yZXAoYygzLDAuMjUpLDEwKQ0KaGRwX2J1Z3M9YXMuZGF0YS5mcmFtZShjYmluZChhdXgsaGRwX2J1Z3MscmVhbCkpDQoNCmhkcF9idWdzJGxvd2VyID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoaGRwX2J1Z3MkbG93ZXIpKQ0KaGRwX2J1Z3MkdXBwZXIgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihoZHBfYnVncyR1cHBlcikpDQpoZHBfYnVncyRyZWFsID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoaGRwX2J1Z3MkcmVhbCkpDQoNCmhkcF9idWdzID0gYXJyYW5nZShoZHBfYnVncyxhdXgpDQoNCnByb3BfYnVncz1pZmVsc2UoaGRwX2J1Z3MkbG93ZXI8aGRwX2J1Z3MkcmVhbCZoZHBfYnVncyRyZWFsPGhkcF9idWdzJHVwcGVyLDEsMCkNCg0KaGRwX2J1Z3M9YXMuZGF0YS5mcmFtZShjYmluZChoZHBfYnVncyxwcm9wX2J1Z3MpKQ0KDQptdV9wcm9wX2J1Z3M9c3VtKGhkcF9idWdzJHByb3BfYnVnc1sxOjEwMF0pLzEwMDt0YXVfcHJvcF9idWdzPXN1bShoZHBfYnVncyRwcm9wX2J1Z3NbMTAxOjIwMF0pLzEwMA0KY3JlZF9idWdzID0gcmJpbmQobXVfcHJvcF9idWdzLHRhdV9wcm9wX2J1Z3MpO2NvbG5hbWVzKGNyZWRfYnVncyk9YygiY3JlZF9idWdzIikNCg0KdGFiZWxhX2J1Z3MgPSBjYmluZChtZWRpZGFzX2J1Z3MsY3JlZF9idWdzLHRfYnVncykNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyAgICAgICAgICAgICAgICAgICAgICAgICAgamFncyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMjIyMjIyMjIyMjIyANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KYW1vc3RyYV9qYWdzID0gbGlzdCgpDQpmaW5hbF9qYWdzID0gbGlzdCgpDQptdV9qYWdzICA9IGxpc3QoKQ0KdGF1X2phZ3MgPSBsaXN0KCkNCm1lZGlhX211X2phZ3MgPSB2ZWN0b3IoKQ0KbWVkaWFfdGF1X2phZ3MgPSB2ZWN0b3IoKQ0Kc2RfbXVfamFncyA9IHZlY3RvcigpDQpzZF90YXVfamFncyA9IHZlY3RvcigpDQplcW1fbXVfamFncyAgPSB2ZWN0b3IoKQ0KZXFtX3RhdV9qYWdzICA9IHZlY3RvcigpDQpoZGlfamFncyA9IGxpc3QoKQ0KDQp0aWMoKQ0KZm9yIChpIGluIDE6MTAwKXsNCiAgDQogIHkuY2VucyA9IHkuY2Vuc3RbW2ldXQ0KICB5LmluZHggID0geS5pbmRbW2ldXQ0KDQogIG1vZGVsX2NvZGU9ICAnbW9kZWwgew0KICBmb3IgKGogaW4gMTpOKXsNCiAgeS5pbmR4W2pdIH4gZGludGVydmFsKHkuY2Vuc1tqXSwgMCkNCiAgeS5jZW5zW2pdIH4gZG5vcm0oYSxiKQ0KICB9DQogIGEgfiBkbm9ybSgwLDAuMDEpDQogIGIgfiBkZ2FtbWEoMSwxMCkNCn0nDQoNCnRvYml0LmluaXRzIDwtIGZ1bmN0aW9uKCl7bGlzdChhPTAsIGI9MSx5LmNlbnM9aWZlbHNlKHkuaW5keCwgTkEsIC1hYnMocm5vcm0oTiwgMCwgMSkpKSl9DQogIA0KYW1vc3RyYV9qYWdzW1tpXV0gPC0gamFncyhtb2RlbC5maWxlPXRleHRDb25uZWN0aW9uKG1vZGVsX2NvZGUpLA0KICAgICAgICAgICAgcGFyYW1ldGVycy50by5zYXZlID0gYygiYSIsICJiIiksDQogICAgICAgICAgICBkYXRhPWxpc3QoeS5jZW5zPXkuY2VucywgeS5pbmR4PXkuaW5keCwgTj1OKSwNCiAgICAgICAgICAgIGluaXRzPXRvYml0LmluaXRzLERJQyA9IEZBTFNFLG4uaXRlciA9IDEwMDAwLG4uYnVybmluID0gMTAwMCkNCg0KZmluYWxfamFnc1tbaV1dID0gYW1vc3RyYV9qYWdzW1tpXV1bWyJCVUdTb3V0cHV0Il1dW1sic2ltcy5tYXRyaXgiXV0NCg0KbXVfamFnc1tbaV1dICA9IGZpbmFsX2phZ3NbW2ldXVssMV0NCnRhdV9qYWdzW1tpXV0gID0gZmluYWxfamFnc1tbaV1dWywyXQ0KDQptZWRpYV9tdV9qYWdzW2ldICA9IG1lYW4obXVfamFnc1tbaV1dKSANCm1lZGlhX3RhdV9qYWdzW2ldICA9IG1lYW4odGF1X2phZ3NbW2ldXSkgDQoNCnNkX211X2phZ3NbaV0gID0gc2QobXVfamFnc1tbaV1dKQ0Kc2RfdGF1X2phZ3NbaV0gID0gc2QodGF1X2phZ3NbW2ldXSkNCg0KZXFtX211X2phZ3NbaV0gID0gbWVhbigobXVfamFnc1tbaV1dLTMpXjIpDQplcW1fdGF1X2phZ3NbaV0gID0gbWVhbigodGF1X2phZ3NbW2ldXS0wLjI1KV4yKQ0KDQpoZGlfamFnc1tbaV1dID0gaGRpKGZpbmFsX2phZ3NbW2ldXSkNCg0KfQ0KdG9jKCkNCg0KdF9qYWdzID0gMTMNCg0KbWVkaWFfamFncz1jKG1lYW4obWVkaWFfbXVfamFncyksbWVhbihtZWRpYV90YXVfamFncykpDQpzZF9qYWdzPWMobWVhbihzZF9tdV9qYWdzKSxtZWFuKHNkX3RhdV9qYWdzKSkNCmVxbV9qYWdzPWMobWVhbihlcW1fbXVfamFncyksbWVhbihlcW1fdGF1X2phZ3MpKQ0KbWVkaWRhc19qYWdzPWNiaW5kKG1lZGlhX2phZ3Msc2RfamFncyxlcW1famFncykNCnJvd25hbWVzKG1lZGlkYXNfamFncykgPSBjKCJtdSIsInRhdSIpDQoNCmhkcF9qYWdzPXQoYXMuZGF0YS5mcmFtZShoZGkoZmluYWxfamFncykpKQ0KYXV4ID0gYXMuY2hhcmFjdGVyKHJvd25hbWVzKGhkcF9qYWdzKSkNCnJlYWw9cmVwKGMoMywwLjI1KSwxMCkNCmhkcF9qYWdzPWFzLmRhdGEuZnJhbWUoY2JpbmQoYXV4LGhkcF9qYWdzLHJlYWwpKQ0KDQpoZHBfamFncyRsb3dlciA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGhkcF9qYWdzJGxvd2VyKSkNCmhkcF9qYWdzJHVwcGVyID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoaGRwX2phZ3MkdXBwZXIpKQ0KaGRwX2phZ3MkcmVhbCA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGhkcF9qYWdzJHJlYWwpKQ0KDQpoZHBfamFncyA9IGFycmFuZ2UoaGRwX2phZ3MsYXV4KQ0KDQpwcm9wX2phZ3M9aWZlbHNlKGhkcF9qYWdzJGxvd2VyPGhkcF9qYWdzJHJlYWwmaGRwX2phZ3MkcmVhbDxoZHBfamFncyR1cHBlciwxLDApDQoNCmhkcF9qYWdzPWFzLmRhdGEuZnJhbWUoY2JpbmQoaGRwX2phZ3MscHJvcF9qYWdzKSkNCg0KbXVfcHJvcF9qYWdzPXN1bShoZHBfamFncyRwcm9wX2phZ3NbMToxMDBdKS8xMDA7dGF1X3Byb3BfamFncz1zdW0oaGRwX2phZ3MkcHJvcF9qYWdzWzEwMToyMDBdKS8xMDANCmNyZWRfamFncyA9IHJiaW5kKG11X3Byb3BfamFncyx0YXVfcHJvcF9qYWdzKTtjb2xuYW1lcyhjcmVkX2phZ3MpPWMoImNyZWRfamFncyIpDQoNCnRhYmVsYV9qYWdzID0gY2JpbmQobWVkaWRhc19qYWdzLGNyZWRfamFncyx0X2phZ3MpDQoNCg0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyAgICAgICAgICAgICAgICAgICAgICAgICAgU1RBTiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyMjIyMjIyMjIyMjIyANCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KZml0ID0gbGlzdCgpDQphbW9zdHJhX3N0YW4gPSBsaXN0KCkNCmZpbmFsX3N0YW4gPSBsaXN0KCkNCm11X3N0YW4gID0gbGlzdCgpDQp0YXVfc3RhbiA9IGxpc3QoKQ0KbWVkaWFfbXVfc3RhbiA9IHZlY3RvcigpDQptZWRpYV90YXVfc3RhbiA9IHZlY3RvcigpDQpzZF9tdV9zdGFuID0gdmVjdG9yKCkNCnNkX3RhdV9zdGFuID0gdmVjdG9yKCkNCmVxbV9tdV9zdGFuICA9IHZlY3RvcigpDQplcW1fdGF1X3N0YW4gID0gdmVjdG9yKCkNCmhkaV9zdGFuID0gbGlzdCgpDQoNCnRpYygpDQpmb3IgKGkgaW4gMToxMDApew0KICB5ID0gcm5vcm0oMTAwMCwzLDIpDQogIHkuY2Vuc29yZWQgPC0gaWZlbHNlKHk+PTAsIHksIE5BKQ0KICB5LmluZCA8LSBhcy5udW1lcmljKHk+PTApDQogIE4gPSBsZW5ndGgoeSkNCiAgDQogIG1vZGVsID0gImRhdGEgew0KaW50PGxvd2VyPTA+IE5fb2JzOw0KaW50PGxvd2VyPTA+IE5fY2VuczsNCnJlYWwgeV9vYnNbTl9vYnNdOw0KcmVhbDxsb3dlcj1taW4oeV9vYnMpPiBVOw0KfQ0KcGFyYW1ldGVycyB7DQpyZWFsPGxvd2VyPVU+IHlfY2Vuc1tOX2NlbnNdOw0KcmVhbCBtdTsNCnJlYWw8bG93ZXI9MD4gc2lnbWEyOw0KfQ0KdHJhbnNmb3JtZWQgcGFyYW1ldGVycyB7DQpyZWFsPGxvd2VyPTA+IHRhdTsNCnRhdSA9IDEgLyBzaWdtYTI7IA0KfQ0KbW9kZWwgew0KeV9vYnMgfiBub3JtYWwobXUsIHNxcnQoc2lnbWEyKSk7DQp5X2NlbnMgfiBub3JtYWwoMCwgMTApOw0KbXUgfiBub3JtYWwoMCwxMCk7DQpzaWdtYTIgfiBnYW1tYSgxLDEwKTsNCn0iDQoNCg0KZGF0YSA8LSBsaXN0KHlfb2JzPXksIHlfY2Vucz15LmNlbnNvcmVkLCBOX29icyA9IE4sIE5fY2VucyA9IE4sIFUgPSAwKQ0KDQpmaXRbW2ldXSA8LSBzdGFuKG1vZGVsX2NvZGUgPSBtb2RlbCxkYXRhID0gZGF0YSwgaXRlciA9IDEwMDAwLCB3YXJtdXAgPSAxMDAwLCBjaGFpbnMgPSAxKQ0KDQphbW9zdHJhX3N0YW5bW2ldXSA8LSBleHRyYWN0KGZpdFtbaV1dKQ0KDQptdV9zdGFuW1tpXV0gID0gYW1vc3RyYV9zdGFuW1tpXV1bWyJtdSJdXQ0KdGF1X3N0YW5bW2ldXSAgPSBhbW9zdHJhX3N0YW5bW2ldXVtbInRhdSJdXQ0KDQpmaW5hbF9zdGFuW1tpXV0gPSBjYmluZChhbW9zdHJhX3N0YW5bW2ldXVtbIm11Il1dLGFtb3N0cmFfc3RhbltbaV1dW1sidGF1Il1dKQ0KDQptdV9zdGFuW1tpXV0gID0gZmluYWxfc3RhbltbaV1dWywxXQ0KdGF1X3N0YW5bW2ldXSAgPSBmaW5hbF9zdGFuW1tpXV1bLDJdDQoNCm1lZGlhX211X3N0YW5baV0gID0gbWVhbihtdV9zdGFuW1tpXV0pIA0KbWVkaWFfdGF1X3N0YW5baV0gID0gbWVhbih0YXVfc3RhbltbaV1dKSANCg0Kc2RfbXVfc3RhbltpXSAgPSBzZChtdV9zdGFuW1tpXV0pDQpzZF90YXVfc3RhbltpXSAgPSBzZCh0YXVfc3RhbltbaV1dKQ0KDQplcW1fbXVfc3RhbltpXSAgPSBtZWFuKChtdV9zdGFuW1tpXV0tMyleMikNCmVxbV90YXVfc3RhbltpXSAgPSBtZWFuKCh0YXVfc3RhbltbaV1dLTAuMjUpXjIpDQoNCmhkaV9zdGFuW1tpXV0gPSBoZGkoZmluYWxfc3RhbltbaV1dKX0NCnRvYygpDQoNCnRfc3RhbiA9IDM4MDMgDQoNCm1lZGlhX3N0YW49YyhtZWFuKG1lZGlhX211X3N0YW4pLG1lYW4obWVkaWFfdGF1X3N0YW4pKQ0Kc2Rfc3Rhbj1jKG1lYW4oc2RfbXVfc3RhbiksbWVhbihzZF90YXVfc3RhbikpDQplcW1fc3Rhbj1jKG1lYW4oZXFtX211X3N0YW4pLG1lYW4oZXFtX3RhdV9zdGFuKSkNCm1lZGlkYXNfc3Rhbj1jYmluZChtZWRpYV9zdGFuLHNkX3N0YW4sZXFtX3N0YW4pDQpyb3duYW1lcyhtZWRpZGFzX3N0YW4pID0gYygibXUiLCJ0YXUiKQ0KDQpoZHBfc3Rhbj10KGFzLmRhdGEuZnJhbWUoaGRpKGZpbmFsX3N0YW4pKSkNCmF1eCA9IGFzLmNoYXJhY3Rlcihyb3duYW1lcyhoZHBfc3RhbikpDQpyZWFsPXJlcChjKDMsMC4yNSksMTApDQpoZHBfc3Rhbj1hcy5kYXRhLmZyYW1lKGNiaW5kKGF1eCxoZHBfc3RhbixyZWFsKSkNCg0KDQpoZHBfc3RhbiRsb3dlciA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGhkcF9zdGFuJGxvd2VyKSkNCmhkcF9zdGFuJHVwcGVyID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoaGRwX3N0YW4kdXBwZXIpKQ0KaGRwX3N0YW4kcmVhbCA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGhkcF9zdGFuJHJlYWwpKQ0KDQpoZHBfc3RhbiA9IGFycmFuZ2UoaGRwX3N0YW4sYXV4KQ0KDQpwcm9wX3N0YW49aWZlbHNlKGhkcF9zdGFuJGxvd2VyPGhkcF9zdGFuJHJlYWwmaGRwX3N0YW4kcmVhbDxoZHBfc3RhbiR1cHBlciwxLDApDQoNCmhkcF9zdGFuPWFzLmRhdGEuZnJhbWUoY2JpbmQoaGRwX3N0YW4scHJvcF9zdGFuKSkNCg0KbXVfcHJvcF9zdGFuPXN1bShoZHBfc3RhbiRwcm9wX3N0YW5bMTo0M10pLzQ0O3RhdV9wcm9wX3N0YW49c3VtKGhkcF9zdGFuJHByb3Bfc3Rhbls0NDo4OF0pLzQ0DQpjcmVkX3N0YW4gPSByYmluZChtdV9wcm9wX3N0YW4sdGF1X3Byb3Bfc3Rhbik7Y29sbmFtZXMoY3JlZF9zdGFuKT1jKCJjcmVkX3N0YW4iKQ0KDQp0YWJlbGFfc3RhbiA9IGNiaW5kKG1lZGlkYXNfc3RhbixjcmVkX3N0YW4sdF9zdGFuKQ0KDQpybShmaXQpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMjIyMjIyMjIyMjIyMgICAgICAgICAgICAgICAgICAgICAgICAgIE5JTUJMRSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMjIyMjIyMjIyMjIyMgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCmFtb3N0cmFfbmltYmxlID0gbGlzdCgpDQpmaW5hbF9uaW1ibGUgPSBsaXN0KCkNCm11X25pbWJsZSAgPSBsaXN0KCkNCnRhdV9uaW1ibGUgPSBsaXN0KCkNCm1lZGlhX211X25pbWJsZSA9IHZlY3RvcigpDQptZWRpYV90YXVfbmltYmxlID0gdmVjdG9yKCkNCnNkX211X25pbWJsZSA9IHZlY3RvcigpDQpzZF90YXVfbmltYmxlID0gdmVjdG9yKCkNCmVxbV9tdV9uaW1ibGUgID0gdmVjdG9yKCkNCmVxbV90YXVfbmltYmxlICA9IHZlY3RvcigpDQpoZGlfbmltYmxlID0gbGlzdCgpDQoNCnRpYygpDQpmb3IgKGkgaW4gMToxMDApew0KeSA9IHJub3JtKDEwMDAsMywyKQ0KeS5jZW5zb3JlZCA8LSBpZmVsc2UoeT49MCwgeSwgTkEpDQp5LmluZCA8LSBhcy5udW1lcmljKHk+PTApDQpOID0gbGVuZ3RoKHkpDQoNCnNpbXBsZUNvZGUxIDwtIG5pbWJsZUNvZGUoew0KICBmb3IgKGogaW4gMTpOKXsNCiAgICB5LmluZFtqXSB+IGRpbnRlcnZhbCh5LmNlbnNvcmVkW2pdLCAwKQ0KICAgIHkuY2Vuc29yZWRbal0gfiBkbm9ybShhLGIpDQogIH0NCiAgYSB+IGRub3JtKDAsIC4wMSkNCiAgYiB+IGRnYW1tYSgxLDEwKQ0KICBzaWdtYTIgPC0gMS9ifSkNCg0KdG9iaXQuaW5pdHMgPC0gZnVuY3Rpb24oKSB7DQogIGxpc3QoYT0wLCBiPTEsIA0KICAgICAgIHkuY2Vuc29yZWQ9aWZlbHNlKHkuaW5kLCBOQSwgLWFicyhybm9ybShOLCAwLCAxKSkpKQ0KfQ0KDQpzaW1wbGVNb2RlbDEgPC0gbmltYmxlTW9kZWwoc2ltcGxlQ29kZTEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1saXN0KHkuY2Vuc29yZWQ9eS5jZW5zb3JlZCwgeS5pbmQ9eS5pbmQsIE49TiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RhbnRzID0gbGlzdChOID0gTiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdHMgPSBsaXN0KGE9MCwgYj0xLHkuY2Vuc29yZWQ9aWZlbHNlKHkuaW5kLCBOQSwgLWFicyhybm9ybShOLCAwLCAxKSkpKSkNCg0KYW1vc3RyYV9uaW1ibGVbW2ldXSA8LSBuaW1ibGVNQ01DKGNvZGUgPSBzaW1wbGVNb2RlbDEsIA0KICAgICAgICAgICAgICAgICAgICAgICBtb25pdG9ycz1jKCJhIiwgImIiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgbmNoYWlucyA9IDEsIA0KICAgICAgICAgICAgICAgICAgICAgICBuaXRlciA9IDEwMDAsDQogICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcnkgPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3NCYXIgPSBUUlVFKQ0KDQpmaW5hbF9uaW1ibGVbW2ldXSA9IGFtb3N0cmFfbmltYmxlW1tpXV1bWyJzYW1wbGVzIl1dDQoNCm11X25pbWJsZVtbaV1dICA9IGZpbmFsX25pbWJsZVtbaV1dWywxXQ0KdGF1X25pbWJsZVtbaV1dICA9IGZpbmFsX25pbWJsZVtbaV1dWywyXQ0KDQptZWRpYV9tdV9uaW1ibGVbaV0gID0gbWVhbihtdV9uaW1ibGVbW2ldXSkgDQptZWRpYV90YXVfbmltYmxlW2ldICA9IG1lYW4odGF1X25pbWJsZVtbaV1dKSANCg0Kc2RfbXVfbmltYmxlW2ldICA9IHNkKG11X25pbWJsZVtbaV1dKQ0Kc2RfdGF1X25pbWJsZVtpXSAgPSBzZCh0YXVfbmltYmxlW1tpXV0pDQoNCmVxbV9tdV9uaW1ibGVbaV0gID0gbWVhbigobXVfbmltYmxlW1tpXV0tMyleMikNCmVxbV90YXVfbmltYmxlW2ldICA9IG1lYW4oKHRhdV9uaW1ibGVbW2ldXS0wLjI1KV4yKQ0KDQpoZGlfbmltYmxlW1tpXV0gPSBoZGkoZmluYWxfbmltYmxlW1tpXV0pDQoNCn0NCnRvYygpDQoNCnRfbmltYmxlID0gNTc4Nw0KDQptZWRpYV9uaW1ibGU9YyhtZWFuKG1lZGlhX211X25pbWJsZSksbWVhbihtZWRpYV90YXVfbmltYmxlKSkNCnNkX25pbWJsZT1jKG1lYW4oc2RfbXVfbmltYmxlKSxtZWFuKHNkX3RhdV9uaW1ibGUpKQ0KZXFtX25pbWJsZT1jKG1lYW4oZXFtX211X25pbWJsZSksbWVhbihlcW1fdGF1X25pbWJsZSkpDQptZWRpZGFzX25pbWJsZT1jYmluZChtZWRpYV9uaW1ibGUsc2RfbmltYmxlLGVxbV9uaW1ibGUpDQpyb3duYW1lcyhtZWRpZGFzX25pbWJsZSkgPSBjKCJtdSIsInRhdSIpDQoNCmhkcF9uaW1ibGU9dChhcy5kYXRhLmZyYW1lKGhkaShmaW5hbF9uaW1ibGUpKSkNCmF1eCA9IGFzLmNoYXJhY3Rlcihyb3duYW1lcyhoZHBfbmltYmxlKSkNCnJlYWw9cmVwKGMoMywwLjI1KSwxMCkNCmhkcF9uaW1ibGU9YXMuZGF0YS5mcmFtZShjYmluZChhdXgsaGRwX25pbWJsZSxyZWFsKSkNCg0KaGRwX25pbWJsZSRsb3dlciA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGhkcF9uaW1ibGUkbG93ZXIpKQ0KaGRwX25pbWJsZSR1cHBlciA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGhkcF9uaW1ibGUkdXBwZXIpKQ0KaGRwX25pbWJsZSRyZWFsID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoaGRwX25pbWJsZSRyZWFsKSkNCg0KaGRwX25pbWJsZSA9IGFycmFuZ2UoaGRwX25pbWJsZSxhdXgpDQoNCnByb3BfbmltYmxlPWlmZWxzZShoZHBfbmltYmxlJGxvd2VyPGhkcF9uaW1ibGUkcmVhbCZoZHBfbmltYmxlJHJlYWw8aGRwX25pbWJsZSR1cHBlciwxLDApDQoNCmhkcF9uaW1ibGU9YXMuZGF0YS5mcmFtZShjYmluZChoZHBfbmltYmxlLHByb3BfbmltYmxlKSkNCg0KbXVfcHJvcF9uaW1ibGU9c3VtKGhkcF9uaW1ibGUkcHJvcF9uaW1ibGVbMToxMDBdKS8xMDA7dGF1X3Byb3BfbmltYmxlPXN1bShoZHBfbmltYmxlJHByb3BfbmltYmxlWzEwMToyMDBdKS8xMDANCmNyZWRfbmltYmxlID0gcmJpbmQobXVfcHJvcF9uaW1ibGUsdGF1X3Byb3BfbmltYmxlKTtjb2xuYW1lcyhjcmVkX25pbWJsZSk9YygiY3JlZF9uaW1ibGUiKQ0KDQp0YWJlbGFfbmltYmxlID0gY2JpbmQobWVkaWRhc19uaW1ibGUsY3JlZF9uaW1ibGUsdF9uaW1ibGUpDQoNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIyMjIyMjICAgICAgICAgICAgICAgICAgICAgICAgICBMQVBMQUNFICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIyMjIyMjIyMjIyMjIA0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQphbW9zdHJhX2xhcGxhY2UgPSBsaXN0KCkNCmZpbmFsX2xhcGxhY2UgPSBsaXN0KCkNCm11X2xhcGxhY2UgID0gbGlzdCgpDQp0YXVfbGFwbGFjZSA9IGxpc3QoKQ0KbWVkaWFfbXVfbGFwbGFjZSA9IHZlY3RvcigpDQptZWRpYV90YXVfbGFwbGFjZSA9IHZlY3RvcigpDQpzZF9tdV9sYXBsYWNlID0gdmVjdG9yKCkNCnNkX3RhdV9sYXBsYWNlID0gdmVjdG9yKCkNCmVxbV9tdV9sYXBsYWNlICA9IHZlY3RvcigpDQplcW1fdGF1X2xhcGxhY2UgID0gdmVjdG9yKCkNCmhkaV9sYXBsYWNlID0gbGlzdCgpDQoNCg0KZm9yIChpIGluIDE6MTAwKXsNCnkgPC0gcm5vcm0oMTAwLDMsMikNCnkuY2VucyA8LSBpZmVsc2UoeT4wLHksTkEpDQpkID0gaWZlbHNlKHkgPCAwLCAwLCAxKQ0KDQptb2RlbCA8LSBmdW5jdGlvbihwLHksZCkgew0KICBsb2dfbGlrIDwtIHBub3JtKDAsIHBbIm11Il0sIDEvc3FydChwWyJ0YXUiXSksIGxvZyA9IFQpKnN1bSgxLWQpICsgc3VtKGQgKiBkbm9ybSh5LCBwWyJtdSJdLCAxL3NxcnQocFsidGF1Il0pLCBsb2cgPSBUKSkNCiAgbG9nX3Bvc3QgPC0gbG9nX2xpayArIGRub3JtKHBbIm11Il0sIDAsIDEwLCBsb2cgPSBUKSArIGRnYW1tYShwWyJ0YXUiXSwgMSwgMTAsIGxvZyA9IFQpDQogIGxvZ19wb3N0DQp9DQoNCmluaXRzIDwtIGMobXUgPSAwLCB0YXUgPSAxKQ0KZml0IDwtIG9wdGltKGluaXRzLCBtb2RlbCwgY29udHJvbCA9IGxpc3QoZm5zY2FsZSA9IC0xKSwgaGVzc2lhbiA9IFRSVUUsIHkgPSB5LCBkID0gZCkNCnBhcmFtX21lYW4gPC0gZml0JHBhcg0KcGFyYW1fY292X21hdCA8LSBzb2x2ZSgtZml0JGhlc3NpYW4pDQpyb3VuZChwYXJhbV9tZWFuLCAyKQ0KDQpmaW5hbF9sYXBsYWNlW1tpXV0gPC0gcm12bm9ybSgxMDAwMCwgcGFyYW1fbWVhbiwgcGFyYW1fY292X21hdCkNCg0KbXVfbGFwbGFjZVtbaV1dICA9IGZpbmFsX2xhcGxhY2VbW2ldXVssMV0NCnRhdV9sYXBsYWNlW1tpXV0gID0gZmluYWxfbGFwbGFjZVtbaV1dWywyXQ0KDQptZWRpYV9tdV9sYXBsYWNlW2ldICA9IG1lYW4obXVfbGFwbGFjZVtbaV1dKSANCm1lZGlhX3RhdV9sYXBsYWNlW2ldICA9IG1lYW4odGF1X2xhcGxhY2VbW2ldXSkgDQoNCnNkX211X2xhcGxhY2VbaV0gID0gc2QobXVfbGFwbGFjZVtbaV1dKQ0Kc2RfdGF1X2xhcGxhY2VbaV0gID0gc2QodGF1X2xhcGxhY2VbW2ldXSkNCg0KZXFtX211X2xhcGxhY2VbaV0gID0gbWVhbigobXVfbGFwbGFjZVtbaV1dLTMpXjIpDQplcW1fdGF1X2xhcGxhY2VbaV0gID0gbWVhbigodGF1X2xhcGxhY2VbW2ldXS0wLjI1KV4yKQ0KDQpoZGlfbGFwbGFjZVtbaV1dID0gaGRpKGZpbmFsX2xhcGxhY2VbW2ldXSkNCn0NCg0KDQp0X2xhcGxhY2UgPSAxDQoNCm1lZGlhX2xhcGxhY2U9YyhtZWFuKG1lZGlhX211X2xhcGxhY2UpLG1lYW4obWVkaWFfdGF1X2xhcGxhY2UpKQ0Kc2RfbGFwbGFjZT1jKG1lYW4oc2RfbXVfbGFwbGFjZSksbWVhbihzZF90YXVfbGFwbGFjZSkpDQplcW1fbGFwbGFjZT1jKG1lYW4oZXFtX211X2xhcGxhY2UpLG1lYW4oZXFtX3RhdV9sYXBsYWNlKSkNCm1lZGlkYXNfbGFwbGFjZT1jYmluZChtZWRpYV9sYXBsYWNlLHNkX2xhcGxhY2UsZXFtX2xhcGxhY2UpDQpyb3duYW1lcyhtZWRpZGFzX2xhcGxhY2UpID0gYygibXUiLCJ0YXUiKQ0KDQpoZHBfbGFwbGFjZT10KGFzLmRhdGEuZnJhbWUoaGRpKGZpbmFsX2xhcGxhY2UpKSkNCmF1eCA9IGFzLmNoYXJhY3Rlcihyb3duYW1lcyhoZHBfbGFwbGFjZSkpDQpyZWFsPXJlcChjKDMsMC4yNSksMTApDQpoZHBfbGFwbGFjZT1hcy5kYXRhLmZyYW1lKGNiaW5kKGF1eCxoZHBfbGFwbGFjZSxyZWFsKSkNCg0KaGRwX2xhcGxhY2UkbG93ZXIgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihoZHBfbGFwbGFjZSRsb3dlcikpDQpoZHBfbGFwbGFjZSR1cHBlciA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGhkcF9sYXBsYWNlJHVwcGVyKSkNCmhkcF9sYXBsYWNlJHJlYWwgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihoZHBfbGFwbGFjZSRyZWFsKSkNCg0KaGRwX2xhcGxhY2UgPSBhcnJhbmdlKGhkcF9sYXBsYWNlLGF1eCkNCg0KcHJvcF9sYXBsYWNlPWlmZWxzZShoZHBfbGFwbGFjZSRsb3dlcjxoZHBfbGFwbGFjZSRyZWFsJmhkcF9sYXBsYWNlJHJlYWw8aGRwX2xhcGxhY2UkdXBwZXIsMSwwKQ0KDQpoZHBfbGFwbGFjZT1hcy5kYXRhLmZyYW1lKGNiaW5kKGhkcF9sYXBsYWNlLHByb3BfbGFwbGFjZSkpDQoNCm11X3Byb3BfbGFwbGFjZT1zdW0oaGRwX2xhcGxhY2UkcHJvcF9sYXBsYWNlWzE6MTAwXSkvMTAwO3RhdV9wcm9wX2xhcGxhY2U9c3VtKGhkcF9sYXBsYWNlJHByb3BfbGFwbGFjZVsxMDE6MjAwXSkvMTAwDQpjcmVkX2xhcGxhY2UgPSByYmluZChtdV9wcm9wX2xhcGxhY2UsdGF1X3Byb3BfbGFwbGFjZSk7Y29sbmFtZXMoY3JlZF9sYXBsYWNlKT1jKCJjcmVkX2xhcGxhY2UiKQ0KDQp0YWJlbGFfbGFwbGFjZSA9IGNiaW5kKG1lZGlkYXNfbGFwbGFjZSxjcmVkX2xhcGxhY2UsdF9sYXBsYWNlKQ0KDQoNCg0KYGBgDQoNCg==