if(!require(geoR)) install.packages("geoR")
if(!require(stats)) install.packages("stats")
if(!require(ggplot2)) install.packages("ggplot2")
if(!require(nortest)) install.packages("nortest")
if(!require(betareg)) install.packages("betareg")
if(!require(glmmTMB)) install.packages("glmmTMB")
if(!require(graphics)) install.packages("graphics")
if(!require(EnvStats)) install.packages("EnvStats")
if(!require(rcompanion)) install.packages("rcompanion")

Para realizar este estudo, utilizamos um dataset com 16.000 valores de entropia de permutação de Shannon e complexidade estatística referentes a ruídos brancos gerados artificialmente com amostras de tamanhos \(N \in \{10.000, 20.000, 30.000, 40.000, 50.000, 60.000, 70.000, 80.000, 90.000, 100.000\}\), aplicando todas as possíveis configurações de \(D \in \{3, 4, 5, 6\}\) e \(\tau \in \{1, 2, 3, 4\}\) aos descritores.

A disposição dos dados no plano \(HC\) pode ser observada abaixo:

HC.BP = data.frame("H" = numeric(16000), 
                   "C" = numeric(16000),
                   "Dist" = numeric(16000),
                   "D" = numeric(16000),
                   "t" = numeric(16000), 
                   "N" = numeric(16000), 
                   stringsAsFactors=FALSE)
HC.BP$N = as.factor(rep(c(rep(1e+04, 100), rep(2e+04, 100), rep(3e+04, 100), rep(4e+04, 100), rep(5e+04, 100), rep(6e+04, 100), rep(7e+04, 100), rep(8e+04, 100), rep(9e+04, 100), rep(1e+05, 100)), 16))
HC.BP$t = as.factor(rep(c(rep(1,1000), rep(2,1000), rep(3,1000), rep(4,1000)), 4))
file.csv = data.frame(read.csv("../Data/HC_series_fk0_16000.csv"))
HC.BP$H = file.csv[,1]
HC.BP$C = file.csv[,2]
HC.BP$Dist = HC.BP$C / HC.BP$H
HC.BP$D= as.factor(file.csv[,3])

Transformação de Box-Cox

Logo, aplicamos a transformação sobre a variável resposta do nosso problema, ou seja, nos valores de complexidade estatística do dataset de ruídos branco. Após aplicar a transformação nossos dados passam a se apresentar dispostos do seguinte modo:

parameters = boxcoxfit(HC.BP$C, lambda2 = F)
lambda = parameters$lambda[1]
if(lambda==0){T.norm = log(HC.BP$C)}
if(lambda!=0){T.norm = ((HC.BP$C)^lambda - 1)/lambda}
T.norm = (T.norm - min(T.norm))/(max(T.norm) - min(T.norm))
n.obs = sum(!is.na(T.norm))
T.norm = (T.norm * (n.obs - 1) + 0.5)/n.obs
plot(x = HC.BP$H, y = T.norm)

Regressão beta

Na geração dos modelos de regressão, consideramos três hipóteses de análise:

  1. Os fatores \(D\) e \(N\) influenciam na construção de uma região de intervalo de confiança, logo são considerados na equação de regressão utilizando o operador (\(*\)).

  2. Os fatores \(D\) e \(N\) influenciam na construção de uma região de intervalo de confiança e são considerados na equação de regressão usando o operador (\(+\)).

  3. Consideraremos na equação de regressão apenas a variável \(H\), gerando diferentes modelos para as diferentes configurações de \(D\) e \(N\).

Hipótese 1 - Calculando a regressão como uma função de H, D e N (usando o operador *)

HC.BP.regression.data = data.frame("H" = numeric(16000), 
                                   "C" = numeric(16000),
                                   "D" = numeric(16000),
                                   "N" = numeric(16000), 
                                   stringsAsFactors=FALSE)
HC.BP.regression.data$H = HC.BP$H
HC.BP.regression.data$C = T.norm
HC.BP.regression.data$D = HC.BP$D
HC.BP.regression.data$N = HC.BP$N
r.squared.1 = data.frame("logit" = numeric(1), "probit" = numeric(1), "cauchy" = numeric(1), "cloglog" = numeric(1),"loglog" = numeric(1),    
                         stringsAsFactors=FALSE)
lm.fit.logit.1 = betareg(data = HC.BP.regression.data, formula = C ~ H * D * N, link = "logit")
r.squared.1$logit = lm.fit.logit.1$pseudo.r.squared
  
lm.fit.probit.1 = betareg(data = HC.BP.regression.data, formula = C ~ H * D * N, link = "probit")
r.squared.1$probit = lm.fit.probit.1$pseudo.r.squared
lm.fit.cauchit.1 = betareg(data = HC.BP.regression.data, formula = C ~ H * D * N, link = "cauchit")
r.squared.1$cauchy = lm.fit.cauchit.1$pseudo.r.squared
  
lm.fit.cloglog.1 = betareg(data = HC.BP.regression.data, formula = C ~ H * D * N, link = "cloglog")
r.squared.1$cloglog = lm.fit.cloglog.1$pseudo.r.squared
  
lm.fit.loglog.1 = betareg(data = HC.BP.regression.data, formula = C ~ H * D * N, link = "loglog")
r.squared.1$loglog = lm.fit.loglog.1$pseudo.r.squared
summary(r.squared.1)
     logit            probit           cauchy            cloglog           loglog      
 Min.   :0.5379   Min.   :0.6963   Min.   :0.007184   Min.   :0.3925   Min.   :0.8519  
 1st Qu.:0.5379   1st Qu.:0.6963   1st Qu.:0.007184   1st Qu.:0.3925   1st Qu.:0.8519  
 Median :0.5379   Median :0.6963   Median :0.007184   Median :0.3925   Median :0.8519  
 Mean   :0.5379   Mean   :0.6963   Mean   :0.007184   Mean   :0.3925   Mean   :0.8519  
 3rd Qu.:0.5379   3rd Qu.:0.6963   3rd Qu.:0.007184   3rd Qu.:0.3925   3rd Qu.:0.8519  
 Max.   :0.5379   Max.   :0.6963   Max.   :0.007184   Max.   :0.3925   Max.   :0.8519  

Hipótese 2 - Calculando a regressão como uma função de H, D e N (usando o operador +)

r.squared.2 = data.frame("logit" = numeric(1), "probit" = numeric(1), "cauchy" = numeric(1), "loglog" = numeric(1),    
                         stringsAsFactors=FALSE)
lm.fit.logit.2 = betareg(data = HC.BP.regression.data, formula = C ~ H + D + N, link = "logit")
r.squared.2$logit = lm.fit.logit.2$pseudo.r.squared
lm.fit.cauchit.2 = betareg(data = HC.BP.regression.data, formula = C ~ H + D + N, link = "cauchit")
r.squared.2$cauchy = lm.fit.cauchit.2$pseudo.r.squared
  
lm.fit.probit.2 = betareg(data = HC.BP.regression.data, formula = C ~ H + D + N, link = "probit")
r.squared.2$probit = lm.fit.probit.2$pseudo.r.squared
  
lm.fit.loglog.2 = betareg(data = HC.BP.regression.data, formula = C ~ H + D + N, link = "loglog")
r.squared.2$loglog = lm.fit.loglog.2$pseudo.r.squared
summary(r.squared.2) 
     logit            probit           cauchy             loglog      
 Min.   :0.5351   Min.   :0.6941   Min.   :0.006429   Min.   :0.8531  
 1st Qu.:0.5351   1st Qu.:0.6941   1st Qu.:0.006429   1st Qu.:0.8531  
 Median :0.5351   Median :0.6941   Median :0.006429   Median :0.8531  
 Mean   :0.5351   Mean   :0.6941   Mean   :0.006429   Mean   :0.8531  
 3rd Qu.:0.5351   3rd Qu.:0.6941   3rd Qu.:0.006429   3rd Qu.:0.8531  
 Max.   :0.5351   Max.   :0.6941   Max.   :0.006429   Max.   :0.8531  

Hipótese 3 - Calculando a regressão como uma função apenas de H

dimension = c(3,4,5,6)
N = c(1e+04, 2e+04, 3e+04, 4e+04, 5e+04, 6e+04, 7e+04, 8e+04, 9e+04, 1e+05)
HC.test.3 = data.frame("H" = numeric(400), 
                       "C" = numeric(400),
                       stringsAsFactors=FALSE)
lm.fit.logit.3 = lm.fit.probit.3 = lm.fit.cloglog.3 = lm.fit.loglog.3 = array(list(), 40)
r.squared.3 = data.frame("logit" = numeric(40), "probit" = numeric(40), "cloglog" = numeric(40),"loglog" = numeric(40), stringsAsFactors=FALSE)
b = cc = 0
for(i in 1:length(dimension)){
  for(j in 1:length(N)){
      cc = cc + 1
      a = c((((j - 1) * 100) + 1):(j * 100))
      elements = c(a + b, a + b + 1000, a + b + 2000, a + b + 3000)
    
      HC.test.3$H = HC.BP.regression.data$H[elements]
      HC.test.3$C = HC.BP.regression.data$C[elements]
      
      lm.fit.logit.3[[cc]] = betareg(data = HC.test.3, formula = C ~ H, link = "logit")
      r.squared.3$logit[cc] = lm.fit.logit.3[[cc]]$pseudo.r.squared
      
      lm.fit.probit.3[[cc]] = betareg(data = HC.test.3, formula = C ~ H, link = "probit")
      r.squared.3$probit[cc] = lm.fit.probit.3[[cc]]$pseudo.r.squared
      
      lm.fit.cloglog.3[[cc]] = betareg(data = HC.test.3, formula = C ~ H, link = "cloglog")
      r.squared.3$cloglog[cc] = lm.fit.cloglog.3[[cc]]$pseudo.r.squared
      
      lm.fit.loglog.3[[cc]] = betareg(data = HC.test.3, formula = C ~ H, link = "loglog")
      r.squared.3$loglog[cc] = lm.fit.loglog.3[[cc]]$pseudo.r.squared
  } 
  b = b + 4000
}
summary(r.squared.3)
     logit            probit          cloglog           loglog      
 Min.   :0.3506   Min.   :0.5413   Min.   :0.2428   Min.   :0.7712  
 1st Qu.:0.4743   1st Qu.:0.6551   1st Qu.:0.3450   1st Qu.:0.8328  
 Median :0.5841   Median :0.7184   Median :0.4362   Median :0.8669  
 Mean   :0.5935   Mean   :0.7144   Mean   :0.4688   Mean   :0.8596  
 3rd Qu.:0.6948   3rd Qu.:0.7777   3rd Qu.:0.5271   3rd Qu.:0.8841  
 Max.   :0.8642   Max.   :0.8684   Max.   :0.7993   Max.   :0.9279  

Análise dos plots dos modelos obtidos

Como visto acima, os melhores ajustes são obtidos ao aplicar a função de link loglog sobre o modelo de regressão. Logo, analisaremos os gráficos de diagnótico para tais regressões.

Hipótese 1 - Calculando a regressão como uma função de H, D e N (usando o operador *)

plot(lm.fit.loglog.1) 

Hipótese 2 - Calculando a regressão como uma função de H, D e N (usando o operador +)

plot(lm.fit.loglog.2) 

Hipótese 3 - Calculando a regressão como uma função apenas de H

plot(lm.fit.loglog.3[[1]]) 

Ajuste R-quadrado de cada hipótese analisada

adj.rsq1 = lm.fit.loglog.1$pseudo.r.squared
adj.rsq2 = lm.fit.loglog.2$pseudo.r.squared
adj.rsq3 = lm.fit.loglog.3[[1]]$pseudo.r.squared
cat(" Adjusted R-Square (hypothesis 1):", adj.rsq1, "\n", 
    "Adjusted R-Square (hypothesis 2):", adj.rsq2, "\n", 
    "Adjusted R-Square (hypothesis 3):", adj.rsq3, "\n")
 Adjusted R-Square (hypothesis 1): 0.8519265 
 Adjusted R-Square (hypothesis 2): 0.8530805 
 Adjusted R-Square (hypothesis 3): 0.8407004 
LS0tCnRpdGxlOiAiUmVwb3J0IDQgLSBCZXRhIHJlZ3Jlc3Npb24gdXNpbmcgQm94LUNveCBUcmFuc2Zvcm1hdGlvbiIKYXV0aG9yOiAiRWR1YXJkYSBDaGFnYXMiCmRhdGU6ICJNYXkgMDQsIDIwMjAiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKYGBge3J9CmlmKCFyZXF1aXJlKGdlb1IpKSBpbnN0YWxsLnBhY2thZ2VzKCJnZW9SIikKaWYoIXJlcXVpcmUoc3RhdHMpKSBpbnN0YWxsLnBhY2thZ2VzKCJzdGF0cyIpCmlmKCFyZXF1aXJlKGdncGxvdDIpKSBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikKaWYoIXJlcXVpcmUobm9ydGVzdCkpIGluc3RhbGwucGFja2FnZXMoIm5vcnRlc3QiKQppZighcmVxdWlyZShiZXRhcmVnKSkgaW5zdGFsbC5wYWNrYWdlcygiYmV0YXJlZyIpCmlmKCFyZXF1aXJlKGdsbW1UTUIpKSBpbnN0YWxsLnBhY2thZ2VzKCJnbG1tVE1CIikKaWYoIXJlcXVpcmUoZ3JhcGhpY3MpKSBpbnN0YWxsLnBhY2thZ2VzKCJncmFwaGljcyIpCmlmKCFyZXF1aXJlKEVudlN0YXRzKSkgaW5zdGFsbC5wYWNrYWdlcygiRW52U3RhdHMiKQppZighcmVxdWlyZShyY29tcGFuaW9uKSkgaW5zdGFsbC5wYWNrYWdlcygicmNvbXBhbmlvbiIpCmBgYAoKUGFyYSByZWFsaXphciBlc3RlIGVzdHVkbywgdXRpbGl6YW1vcyB1bSBkYXRhc2V0IGNvbSAxNi4wMDAgdmFsb3JlcyBkZSBlbnRyb3BpYSBkZSBwZXJtdXRhw6fDo28gZGUgU2hhbm5vbiBlIGNvbXBsZXhpZGFkZSBlc3RhdMOtc3RpY2EgcmVmZXJlbnRlcyBhIHJ1w61kb3MgYnJhbmNvcyBnZXJhZG9zIGFydGlmaWNpYWxtZW50ZSBjb20gYW1vc3RyYXMgZGUgdGFtYW5ob3MgJE4gXGluIFx7MTAuMDAwLCAyMC4wMDAsIDMwLjAwMCwgNDAuMDAwLCA1MC4wMDAsIDYwLjAwMCwgNzAuMDAwLCA4MC4wMDAsIDkwLjAwMCwgMTAwLjAwMFx9JCwgYXBsaWNhbmRvIHRvZGFzIGFzIHBvc3PDrXZlaXMgY29uZmlndXJhw6fDtWVzIGRlICREIFxpbiBcezMsIDQsIDUsIDZcfSQgZSAgJFx0YXUgXGluIFx7MSwgMiwgMywgNFx9JCBhb3MgZGVzY3JpdG9yZXMuCgpBIGRpc3Bvc2nDp8OjbyBkb3MgZGFkb3Mgbm8gcGxhbm8gJEhDJCBwb2RlIHNlciBvYnNlcnZhZGEgYWJhaXhvOiAKCmBgYHtyfQpIQy5CUCA9IGRhdGEuZnJhbWUoIkgiID0gbnVtZXJpYygxNjAwMCksIAogICAgICAgICAgICAgICAgICAgIkMiID0gbnVtZXJpYygxNjAwMCksCiAgICAgICAgICAgICAgICAgICAiRGlzdCIgPSBudW1lcmljKDE2MDAwKSwKICAgICAgICAgICAgICAgICAgICJEIiA9IG51bWVyaWMoMTYwMDApLAogICAgICAgICAgICAgICAgICAgInQiID0gbnVtZXJpYygxNjAwMCksIAogICAgICAgICAgICAgICAgICAgIk4iID0gbnVtZXJpYygxNjAwMCksIAogICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKCkhDLkJQJE4gPSBhcy5mYWN0b3IocmVwKGMocmVwKDFlKzA0LCAxMDApLCByZXAoMmUrMDQsIDEwMCksIHJlcCgzZSswNCwgMTAwKSwgcmVwKDRlKzA0LCAxMDApLCByZXAoNWUrMDQsIDEwMCksIHJlcCg2ZSswNCwgMTAwKSwgcmVwKDdlKzA0LCAxMDApLCByZXAoOGUrMDQsIDEwMCksIHJlcCg5ZSswNCwgMTAwKSwgcmVwKDFlKzA1LCAxMDApKSwgMTYpKQoKSEMuQlAkdCA9IGFzLmZhY3RvcihyZXAoYyhyZXAoMSwxMDAwKSwgcmVwKDIsMTAwMCksIHJlcCgzLDEwMDApLCByZXAoNCwxMDAwKSksIDQpKQoKZmlsZS5jc3YgPSBkYXRhLmZyYW1lKHJlYWQuY3N2KCIuLi9EYXRhL0hDX3Nlcmllc19mazBfMTYwMDAuY3N2IikpCgpIQy5CUCRIID0gZmlsZS5jc3ZbLDFdCkhDLkJQJEMgPSBmaWxlLmNzdlssMl0KSEMuQlAkRGlzdCA9IEhDLkJQJEMgLyBIQy5CUCRICkhDLkJQJEQ9IGFzLmZhY3RvcihmaWxlLmNzdlssM10pCmBgYAoKIyNUcmFuc2Zvcm1hw6fDo28gZGUgQm94LUNveAoKTG9nbywgYXBsaWNhbW9zIGEgdHJhbnNmb3JtYcOnw6NvIHNvYnJlIGEgdmFyacOhdmVsIHJlc3Bvc3RhIGRvIG5vc3NvIHByb2JsZW1hLCBvdSBzZWphLCBub3MgdmFsb3JlcyBkZSBjb21wbGV4aWRhZGUgZXN0YXTDrXN0aWNhIGRvIGRhdGFzZXQgZGUgcnXDrWRvcyBicmFuY28uIEFww7NzIGFwbGljYXIgYSB0cmFuc2Zvcm1hw6fDo28gbm9zc29zIGRhZG9zIHBhc3NhbSBhIHNlIGFwcmVzZW50YXIgZGlzcG9zdG9zIGRvIHNlZ3VpbnRlIG1vZG86CgpgYGB7cn0KcGFyYW1ldGVycyA9IGJveGNveGZpdChIQy5CUCRDLCBsYW1iZGEyID0gRikKbGFtYmRhID0gcGFyYW1ldGVycyRsYW1iZGFbMV0KaWYobGFtYmRhPT0wKXtULm5vcm0gPSBsb2coSEMuQlAkQyl9CmlmKGxhbWJkYSE9MCl7VC5ub3JtID0gKChIQy5CUCRDKV5sYW1iZGEgLSAxKS9sYW1iZGF9ClQubm9ybSA9IChULm5vcm0gLSBtaW4oVC5ub3JtKSkvKG1heChULm5vcm0pIC0gbWluKFQubm9ybSkpCm4ub2JzID0gc3VtKCFpcy5uYShULm5vcm0pKQpULm5vcm0gPSAoVC5ub3JtICogKG4ub2JzIC0gMSkgKyAwLjUpL24ub2JzCnBsb3QoeCA9IEhDLkJQJEgsIHkgPSBULm5vcm0pCmBgYAoKI1JlZ3Jlc3PDo28gYmV0YQoKTmEgZ2VyYcOnw6NvIGRvcyBtb2RlbG9zIGRlIHJlZ3Jlc3PDo28sIGNvbnNpZGVyYW1vcyB0csOqcyBoaXDDs3Rlc2VzIGRlIGFuw6FsaXNlOiAKCjEuIE9zIGZhdG9yZXMgJEQkIGUgJE4kIGluZmx1ZW5jaWFtIG5hIGNvbnN0cnXDp8OjbyBkZSB1bWEgcmVnacOjbyBkZSBpbnRlcnZhbG8gZGUgY29uZmlhbsOnYSwgbG9nbyBzw6NvIGNvbnNpZGVyYWRvcyBuYSBlcXVhw6fDo28gZGUgcmVncmVzc8OjbyB1dGlsaXphbmRvIG8gb3BlcmFkb3IgKCQqJCkuCgoyLiBPcyBmYXRvcmVzICREJCBlICROJCBpbmZsdWVuY2lhbSBuYSBjb25zdHJ1w6fDo28gZGUgdW1hIHJlZ2nDo28gZGUgaW50ZXJ2YWxvIGRlIGNvbmZpYW7Dp2EgZSBzw6NvIGNvbnNpZGVyYWRvcyBuYSBlcXVhw6fDo28gZGUgcmVncmVzc8OjbyB1c2FuZG8gbyBvcGVyYWRvciAoJCskKS4KCjMuIENvbnNpZGVyYXJlbW9zIG5hIGVxdWHDp8OjbyBkZSByZWdyZXNzw6NvIGFwZW5hcyBhIHZhcmnDoXZlbCAkSCQsIGdlcmFuZG8gZGlmZXJlbnRlcyBtb2RlbG9zIHBhcmEgYXMgZGlmZXJlbnRlcyBjb25maWd1cmHDp8O1ZXMgZGUgJEQkIGUgJE4kLgoKCiMjI0hpcMOzdGVzZSAxIC0gQ2FsY3VsYW5kbyBhIHJlZ3Jlc3PDo28gY29tbyB1bWEgZnVuw6fDo28gZGUgSCwgRCBlIE4gKHVzYW5kbyBvIG9wZXJhZG9yICopCgpgYGB7cn0KSEMuQlAucmVncmVzc2lvbi5kYXRhID0gZGF0YS5mcmFtZSgiSCIgPSBudW1lcmljKDE2MDAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkMiID0gbnVtZXJpYygxNjAwMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkQiID0gbnVtZXJpYygxNjAwMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk4iID0gbnVtZXJpYygxNjAwMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgoKSEMuQlAucmVncmVzc2lvbi5kYXRhJEggPSBIQy5CUCRICkhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRDID0gVC5ub3JtCkhDLkJQLnJlZ3Jlc3Npb24uZGF0YSREID0gSEMuQlAkRApIQy5CUC5yZWdyZXNzaW9uLmRhdGEkTiA9IEhDLkJQJE4KCnIuc3F1YXJlZC4xID0gZGF0YS5mcmFtZSgibG9naXQiID0gbnVtZXJpYygxKSwgInByb2JpdCIgPSBudW1lcmljKDEpLCAiY2F1Y2h5IiA9IG51bWVyaWMoMSksICJjbG9nbG9nIiA9IG51bWVyaWMoMSksImxvZ2xvZyIgPSBudW1lcmljKDEpLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpsbS5maXQubG9naXQuMSA9IGJldGFyZWcoZGF0YSA9IEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSwgZm9ybXVsYSA9IEMgfiBIICogRCAqIE4sIGxpbmsgPSAibG9naXQiKQpyLnNxdWFyZWQuMSRsb2dpdCA9IGxtLmZpdC5sb2dpdC4xJHBzZXVkby5yLnNxdWFyZWQKICAKbG0uZml0LnByb2JpdC4xID0gYmV0YXJlZyhkYXRhID0gSEMuQlAucmVncmVzc2lvbi5kYXRhLCBmb3JtdWxhID0gQyB+IEggKiBEICogTiwgbGluayA9ICJwcm9iaXQiKQpyLnNxdWFyZWQuMSRwcm9iaXQgPSBsbS5maXQucHJvYml0LjEkcHNldWRvLnIuc3F1YXJlZAoKbG0uZml0LmNhdWNoaXQuMSA9IGJldGFyZWcoZGF0YSA9IEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSwgZm9ybXVsYSA9IEMgfiBIICogRCAqIE4sIGxpbmsgPSAiY2F1Y2hpdCIpCnIuc3F1YXJlZC4xJGNhdWNoeSA9IGxtLmZpdC5jYXVjaGl0LjEkcHNldWRvLnIuc3F1YXJlZAogIApsbS5maXQuY2xvZ2xvZy4xID0gYmV0YXJlZyhkYXRhID0gSEMuQlAucmVncmVzc2lvbi5kYXRhLCBmb3JtdWxhID0gQyB+IEggKiBEICogTiwgbGluayA9ICJjbG9nbG9nIikKci5zcXVhcmVkLjEkY2xvZ2xvZyA9IGxtLmZpdC5jbG9nbG9nLjEkcHNldWRvLnIuc3F1YXJlZAogIApsbS5maXQubG9nbG9nLjEgPSBiZXRhcmVnKGRhdGEgPSBIQy5CUC5yZWdyZXNzaW9uLmRhdGEsIGZvcm11bGEgPSBDIH4gSCAqIEQgKiBOLCBsaW5rID0gImxvZ2xvZyIpCnIuc3F1YXJlZC4xJGxvZ2xvZyA9IGxtLmZpdC5sb2dsb2cuMSRwc2V1ZG8uci5zcXVhcmVkCgpzdW1tYXJ5KHIuc3F1YXJlZC4xKQpgYGAKCiMjI0hpcMOzdGVzZSAyIC0gQ2FsY3VsYW5kbyBhIHJlZ3Jlc3PDo28gY29tbyB1bWEgZnVuw6fDo28gZGUgSCwgRCBlIE4gKHVzYW5kbyBvIG9wZXJhZG9yICspCgpgYGB7cn0Kci5zcXVhcmVkLjIgPSBkYXRhLmZyYW1lKCJsb2dpdCIgPSBudW1lcmljKDEpLCAicHJvYml0IiA9IG51bWVyaWMoMSksICJjYXVjaHkiID0gbnVtZXJpYygxKSwgImxvZ2xvZyIgPSBudW1lcmljKDEpLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpsbS5maXQubG9naXQuMiA9IGJldGFyZWcoZGF0YSA9IEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSwgZm9ybXVsYSA9IEMgfiBIICsgRCArIE4sIGxpbmsgPSAibG9naXQiKQpyLnNxdWFyZWQuMiRsb2dpdCA9IGxtLmZpdC5sb2dpdC4yJHBzZXVkby5yLnNxdWFyZWQKCmxtLmZpdC5jYXVjaGl0LjIgPSBiZXRhcmVnKGRhdGEgPSBIQy5CUC5yZWdyZXNzaW9uLmRhdGEsIGZvcm11bGEgPSBDIH4gSCArIEQgKyBOLCBsaW5rID0gImNhdWNoaXQiKQpyLnNxdWFyZWQuMiRjYXVjaHkgPSBsbS5maXQuY2F1Y2hpdC4yJHBzZXVkby5yLnNxdWFyZWQKICAKbG0uZml0LnByb2JpdC4yID0gYmV0YXJlZyhkYXRhID0gSEMuQlAucmVncmVzc2lvbi5kYXRhLCBmb3JtdWxhID0gQyB+IEggKyBEICsgTiwgbGluayA9ICJwcm9iaXQiKQpyLnNxdWFyZWQuMiRwcm9iaXQgPSBsbS5maXQucHJvYml0LjIkcHNldWRvLnIuc3F1YXJlZAogIApsbS5maXQubG9nbG9nLjIgPSBiZXRhcmVnKGRhdGEgPSBIQy5CUC5yZWdyZXNzaW9uLmRhdGEsIGZvcm11bGEgPSBDIH4gSCArIEQgKyBOLCBsaW5rID0gImxvZ2xvZyIpCnIuc3F1YXJlZC4yJGxvZ2xvZyA9IGxtLmZpdC5sb2dsb2cuMiRwc2V1ZG8uci5zcXVhcmVkCgpzdW1tYXJ5KHIuc3F1YXJlZC4yKSAKYGBgCgojIyNIaXDDs3Rlc2UgMyAtIENhbGN1bGFuZG8gYSByZWdyZXNzw6NvIGNvbW8gdW1hIGZ1bsOnw6NvIGFwZW5hcyBkZSBICgpgYGB7cn0KZGltZW5zaW9uID0gYygzLDQsNSw2KQpOID0gYygxZSswNCwgMmUrMDQsIDNlKzA0LCA0ZSswNCwgNWUrMDQsIDZlKzA0LCA3ZSswNCwgOGUrMDQsIDllKzA0LCAxZSswNSkKSEMudGVzdC4zID0gZGF0YS5mcmFtZSgiSCIgPSBudW1lcmljKDQwMCksIAogICAgICAgICAgICAgICAgICAgICAgICJDIiA9IG51bWVyaWMoNDAwKSwKICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpsbS5maXQubG9naXQuMyA9IGxtLmZpdC5wcm9iaXQuMyA9IGxtLmZpdC5jbG9nbG9nLjMgPSBsbS5maXQubG9nbG9nLjMgPSBhcnJheShsaXN0KCksIDQwKQpyLnNxdWFyZWQuMyA9IGRhdGEuZnJhbWUoImxvZ2l0IiA9IG51bWVyaWMoNDApLCAicHJvYml0IiA9IG51bWVyaWMoNDApLCAiY2xvZ2xvZyIgPSBudW1lcmljKDQwKSwibG9nbG9nIiA9IG51bWVyaWMoNDApLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQoKYiA9IGNjID0gMApmb3IoaSBpbiAxOmxlbmd0aChkaW1lbnNpb24pKXsKICBmb3IoaiBpbiAxOmxlbmd0aChOKSl7CiAgICAgIGNjID0gY2MgKyAxCiAgICAgIGEgPSBjKCgoKGogLSAxKSAqIDEwMCkgKyAxKTooaiAqIDEwMCkpCiAgICAgIGVsZW1lbnRzID0gYyhhICsgYiwgYSArIGIgKyAxMDAwLCBhICsgYiArIDIwMDAsIGEgKyBiICsgMzAwMCkKICAgIAogICAgICBIQy50ZXN0LjMkSCA9IEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRIW2VsZW1lbnRzXQogICAgICBIQy50ZXN0LjMkQyA9IEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRDW2VsZW1lbnRzXQogICAgICAKICAgICAgbG0uZml0LmxvZ2l0LjNbW2NjXV0gPSBiZXRhcmVnKGRhdGEgPSBIQy50ZXN0LjMsIGZvcm11bGEgPSBDIH4gSCwgbGluayA9ICJsb2dpdCIpCiAgICAgIHIuc3F1YXJlZC4zJGxvZ2l0W2NjXSA9IGxtLmZpdC5sb2dpdC4zW1tjY11dJHBzZXVkby5yLnNxdWFyZWQKICAgICAgCiAgICAgIGxtLmZpdC5wcm9iaXQuM1tbY2NdXSA9IGJldGFyZWcoZGF0YSA9IEhDLnRlc3QuMywgZm9ybXVsYSA9IEMgfiBILCBsaW5rID0gInByb2JpdCIpCiAgICAgIHIuc3F1YXJlZC4zJHByb2JpdFtjY10gPSBsbS5maXQucHJvYml0LjNbW2NjXV0kcHNldWRvLnIuc3F1YXJlZAogICAgICAKICAgICAgbG0uZml0LmNsb2dsb2cuM1tbY2NdXSA9IGJldGFyZWcoZGF0YSA9IEhDLnRlc3QuMywgZm9ybXVsYSA9IEMgfiBILCBsaW5rID0gImNsb2dsb2ciKQogICAgICByLnNxdWFyZWQuMyRjbG9nbG9nW2NjXSA9IGxtLmZpdC5jbG9nbG9nLjNbW2NjXV0kcHNldWRvLnIuc3F1YXJlZAogICAgICAKICAgICAgbG0uZml0LmxvZ2xvZy4zW1tjY11dID0gYmV0YXJlZyhkYXRhID0gSEMudGVzdC4zLCBmb3JtdWxhID0gQyB+IEgsIGxpbmsgPSAibG9nbG9nIikKICAgICAgci5zcXVhcmVkLjMkbG9nbG9nW2NjXSA9IGxtLmZpdC5sb2dsb2cuM1tbY2NdXSRwc2V1ZG8uci5zcXVhcmVkCiAgfSAKICBiID0gYiArIDQwMDAKfQoKc3VtbWFyeShyLnNxdWFyZWQuMykKYGBgCgojIyNBbsOhbGlzZSBkb3MgcGxvdHMgZG9zIG1vZGVsb3Mgb2J0aWRvcwoKQ29tbyB2aXN0byBhY2ltYSwgb3MgbWVsaG9yZXMgYWp1c3RlcyBzw6NvIG9idGlkb3MgYW8gYXBsaWNhciBhIGZ1bsOnw6NvIGRlIGxpbmsgbG9nbG9nIHNvYnJlIG8gbW9kZWxvIGRlIHJlZ3Jlc3PDo28uIApMb2dvLCBhbmFsaXNhcmVtb3Mgb3MgZ3LDoWZpY29zIGRlIGRpYWduw7N0aWNvIHBhcmEgdGFpcyByZWdyZXNzw7Vlcy4KCiMjI0hpcMOzdGVzZSAxIC0gQ2FsY3VsYW5kbyBhIHJlZ3Jlc3PDo28gY29tbyB1bWEgZnVuw6fDo28gZGUgSCwgRCBlIE4gKHVzYW5kbyBvIG9wZXJhZG9yICopCgpgYGB7cn0KcGxvdChsbS5maXQubG9nbG9nLjEpIApgYGAKCiMjI0hpcMOzdGVzZSAyIC0gQ2FsY3VsYW5kbyBhIHJlZ3Jlc3PDo28gY29tbyB1bWEgZnVuw6fDo28gZGUgSCwgRCBlIE4gKHVzYW5kbyBvIG9wZXJhZG9yICspCgpgYGB7cn0KcGxvdChsbS5maXQubG9nbG9nLjIpIApgYGAKCiMjI0hpcMOzdGVzZSAzIC0gQ2FsY3VsYW5kbyBhIHJlZ3Jlc3PDo28gY29tbyB1bWEgZnVuw6fDo28gYXBlbmFzIGRlIEgKCmBgYHtyfQpwbG90KGxtLmZpdC5sb2dsb2cuM1tbMV1dKSAKYGBgCgoKIyMjVmlzdWFsaXphbmRvIG9zIGFqdXN0ZXMgb2J0aWRvcyBwZWxhIGZ1bsOnw6NvIGRlIGxpbmsgbG9nbG9nCgpgYGB7cn0KZ2dwbG90KEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSwgYWVzKHggPSBILCB5ID0gQykpICsKICBnZW9tX3BvaW50KCkgKwogIHNjYWxlX2ZpbGxfZ3JleSgpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBwcmVkaWN0KGxtLmZpdC5sb2dsb2cuMSwgSEMuQlAucmVncmVzc2lvbi5kYXRhLCB0eXBlID0gJ3Jlc3BvbnNlJykpKSAKYGBgCgpgYGB7cn0KZ2dwbG90KEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSwgYWVzKHggPSBILCB5ID0gQykpICsKICBnZW9tX3BvaW50KCkgKwogIHNjYWxlX2ZpbGxfZ3JleSgpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBwcmVkaWN0KGxtLmZpdC5sb2dsb2cuMiwgSEMuQlAucmVncmVzc2lvbi5kYXRhLCB0eXBlID0gJ3Jlc3BvbnNlJykpKSAKYGBgCgpgYGB7cn0KYSA9IGMoMToxMDApCmVsZW1lbnRzID0gYyhhLCBhICsgMTAwMCwgYSArIDIwMDAsIGEgKyAzMDAwKQpIQy50ZXN0LjMkSCA9IEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRIW2VsZW1lbnRzXQpIQy50ZXN0LjMkQyA9IEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRDW2VsZW1lbnRzXQogICAgICAKZ2dwbG90KEhDLnRlc3QuMywgYWVzKHggPSBILCB5ID0gQykpICsKICBnZW9tX3BvaW50KCkgKwogIHNjYWxlX2ZpbGxfZ3JleSgpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBwcmVkaWN0KGxtLmZpdC5jbG9nbG9nLjNbWzFdXSwgSEMudGVzdC4zLCB0eXBlID0gJ3Jlc3BvbnNlJykpKSAKYGBgCgoKIyMjQWp1c3RlIFItcXVhZHJhZG8gZGUgY2FkYSBoaXDDs3Rlc2UgYW5hbGlzYWRhCgpgYGB7cn0KYWRqLnJzcTEgPSBsbS5maXQubG9nbG9nLjEkcHNldWRvLnIuc3F1YXJlZAphZGoucnNxMiA9IGxtLmZpdC5sb2dsb2cuMiRwc2V1ZG8uci5zcXVhcmVkCmFkai5yc3EzID0gbG0uZml0LmxvZ2xvZy4zW1sxXV0kcHNldWRvLnIuc3F1YXJlZAoKY2F0KCIgQWRqdXN0ZWQgUi1TcXVhcmUgKGh5cG90aGVzaXMgMSk6IiwgYWRqLnJzcTEsICJcbiIsIAogICAgIkFkanVzdGVkIFItU3F1YXJlIChoeXBvdGhlc2lzIDIpOiIsIGFkai5yc3EyLCAiXG4iLCAKICAgICJBZGp1c3RlZCBSLVNxdWFyZSAoaHlwb3RoZXNpcyAzKToiLCBhZGoucnNxMywgIlxuIikKYGBg