Alternative 2 - Calculate the regression based on H
Hypothesis 0: D, t and N matter
delay = c(1,2,3,4)
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.BP.regression.data = data.frame("H" = numeric(100),
"C" = numeric(100),
stringsAsFactors=FALSE)
shapiro.hypothesis.0 = rep(0, 160)
durbinWatson.hypothesis.0 = rep(0, 160)
lm.hypothesis.0 = array(list(), 160)
for(i in 1:160){
elements = c((((i-1)*100)+1):(i*100))
HC.BP.regression.data$H = HC.BP$H[elements]
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.0[[i]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.0[i] = dwtest(lm.hypothesis.0[[i]])$p.value
shapiro.hypothesis.0[i] = shapiro.test(lm.hypothesis.0[[i]]$residuals)$p.value
}
cat("Total: ", 160, " Teste de normalidade: ", length(which(shapiro.hypothesis.0 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.0 > 0.05)), '\n')
Total: 160 Teste de normalidade: 0 Teste de correlação: 152
plot(lm.hypothesis.0[[1]], which = c(1:4), pch = 20)




Hypothesis 1: D matter
#laplace distribution
dimension = c(3, 4, 5, 6)
HC.BP.regression.data = data.frame("H" = numeric(4000),
"C" = numeric(4000),
stringsAsFactors=FALSE)
shapiro.hypothesis.1 = rep(0, 4)
durbinWatson.hypothesis.1 = rep(0, 4)
lm.hypothesis.1 = array(list(), 4)
for(i in 1:length(dimension)){
HC.BP.regression.data$H = HC.BP$H[(((i-1)*4000)+1):(i*4000)]
HC.BP.regression.data$C = HC.BP$C[(((i-1)*4000)+1):(i*4000)]
lm.hypothesis.1[[i]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.1[i] = dwtest(lm.hypothesis.1[[i]])$p.value
shapiro.hypothesis.1[i] = shapiro.test(lm.hypothesis.1[[i]]$residuals)$p.value
}
cat("Total: ", 4, " Teste de normalidade: ", length(which(shapiro.hypothesis.1 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.1 > 0.05)), '\n')
Total: 4 Teste de normalidade: 0 Teste de correlação: 4
plot(lm.hypothesis.1[[1]], which = c(1:4), pch = 20)




Hypothesis 2: t matter
#laplace distribution
delay = c(1, 2, 3, 4)
HC.BP.regression.data = data.frame("H" = numeric(4000),
"C" = numeric(4000),
stringsAsFactors=FALSE)
a = c(1:1000)
shapiro.hypothesis.2 = rep(0, 4)
durbinWatson.hypothesis.2 = rep(0, 4)
lm.hypothesis.2 = array(list(), 4)
for(i in 1:length(delay)){
a = c((((i-1) * 1000) + 1):(i * 1000))
elements = rep(c(a, a + 4000, a + 8000, a + 12000))
HC.BP.regression.data$H = HC.BP$H[elements]
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.2[[i]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.2[i] = dwtest(lm.hypothesis.2[[i]])$p.value
shapiro.hypothesis.2[i] = shapiro.test(lm.hypothesis.2[[i]]$residuals)$p.value
}
cat("Total: ", 4, " Teste de normalidade: ", length(which(shapiro.hypothesis.2 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.2 > 0.05)), '\n')
Total: 4 Teste de normalidade: 0 Teste de correlação: 3
plot(lm.hypothesis.2[[1]], which = c(1:4), pch = 20)




Hypothesis 3: N matter
#laplace distribution
N = c(1e+04, 2e+04, 3e+04, 4e+04, 5e+04, 6e+04, 7e+04, 8e+04, 9e+04, 1e+05)
HC.BP.regression.data = data.frame("H" = numeric(1600),
"C" = numeric(1600),
stringsAsFactors=FALSE)
a = c(1:100)
shapiro.hypothesis.3 = rep(0, 10)
durbinWatson.hypothesis.3 = rep(0, 10)
lm.hypothesis.3 = array(list(), 10)
for(i in 1:length(N)){
a = c((((i-1) * 100) + 1):(i * 100))
elements = rep(c(a, a + 1000, a + 2000, a + 3000, a + 4000, a + 5000, a + 6000, a + 7000, a + 8000, a + 9000, a + 10000, a + 11000, a + 12000, a + 13000, a + 14000, a + 15000))
HC.BP.regression.data$H = HC.BP$H[elements]
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.3[[i]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.3[i] = dwtest(lm.hypothesis.3[[i]])$p.value
shapiro.hypothesis.3[i] = shapiro.test(lm.hypothesis.3[[i]]$residuals)$p.value
}
cat("Total: ", 10, " Teste de normalidade: ", length(which(shapiro.hypothesis.3 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.3 > 0.05)), '\n')
Total: 10 Teste de normalidade: 0 Teste de correlação: 10
plot(lm.hypothesis.3[[1]], which = c(1:4), pch = 20)




Hypothesis 4: D and t matter
#laplace distribution
delay = c(1,2,3,4)
dimension = c(3,4,5,6)
HC.BP.regression.data = data.frame("H" = numeric(1000),
"C" = numeric(1000),
stringsAsFactors=FALSE)
shapiro.hypothesis.4 = rep(0, 16)
durbinWatson.hypothesis.4 = rep(0, 16)
lm.hypothesis.4 = array(list(), 16)
for(i in 1:(length(dimension)*length(delay))){
elements = c((((i-1) * 1000) + 1):(i * 1000))
HC.BP.regression.data$H = HC.BP$H[elements]
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.4[[i]] = lm(data = HC.BP.regression.data, formula = C ~ H)
shapiro.hypothesis.4[i] = shapiro.test(lm.hypothesis.4[[i]]$residuals)$p.value
durbinWatson.hypothesis.4[i] = dwtest(lm.hypothesis.4[[i]])$p.value
}
cat("Total: ", 16, " Teste de normalidade: ", length(which(shapiro.hypothesis.4 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.4 > 0.05)), '\n')
Total: 16 Teste de normalidade: 0 Teste de correlação: 15
plot(lm.hypothesis.4[[1]], which = c(1:4), pch = 20)




Hypothesis 5: D and N matter
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.BP.regression.data = data.frame("H" = numeric(400),
"C" = numeric(400),
stringsAsFactors=FALSE)
shapiro.hypothesis.5 = rep(0, 40)
durbinWatson.hypothesis.5 = rep(0, 40)
lm.hypothesis.5 = array(list(), 40)
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.BP.regression.data$H = HC.BP$H[elements]
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.5[[cc]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.5[cc] = dwtest(lm.hypothesis.5[[cc]])$p.value
shapiro.hypothesis.5[cc] = shapiro.test(lm.hypothesis.5[[cc]]$residuals)$p.value
}
b = b + 4000
}
cat("Total: ", 40, " Teste de normalidade: ", length(which(shapiro.hypothesis.5 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.5 > 0.05)), '\n')
Total: 40 Teste de normalidade: 0 Teste de correlação: 39
plot(lm.hypothesis.5[[1]], which = c(1:4), pch = 20)




Hypothesis 6: t and N matter
delay = c(1,2,3,4)
N = c(1e+04, 2e+04, 3e+04, 4e+04, 5e+04, 6e+04, 7e+04, 8e+04, 9e+04, 1e+05)
HC.BP.regression.data = data.frame("H" = numeric(400),
"C" = numeric(400),
stringsAsFactors=FALSE)
shapiro.hypothesis.6 = rep(0, 40)
lm.hypothesis.6 = array(list(), 40)
durbinWatson.hypothesis.6 = rep(0, 40)
b = cc = 0
for(i in 1:length(delay)){
for(j in 1:length(N)){
cc = cc + 1
a = c((((j - 1) * 100) + 1):(j * 100))
elements = c(a + b, a + b + 4000, a + b + 8000, a + b + 12000)
HC.BP.regression.data$H = HC.BP$H[elements]
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.6[[cc]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.6[cc] = dwtest(lm.hypothesis.6[[cc]])$p.value
shapiro.hypothesis.6[cc] = shapiro.test(lm.hypothesis.6[[cc]]$residuals)$p.value
}
b = b + 1000
}
cat("Total: ", 40, " Teste de normalidade: ", length(which(shapiro.hypothesis.6 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.6 > 0.05)), '\n')
Total: 40 Teste de normalidade: 0 Teste de correlação: 39
plot(lm.hypothesis.6[[1]], which = c(1:4), pch = 20)




The problem
As seen in the normality tests above, the residues obtained do not follow a normal distribution and are therefore not i.i.d (independent and identically distributed). According to the Gauss-Markov theorem, the least squares regression is the best linear estimate of the underlying coefficients, when it is assumed that the errors are not correlated and have the same variance. However, in the presence of non-normal residues or heteroscedasticity, the estimator does not work efficiently (although it remains consistent), producing inaccurate confidence intervals.
One of the major problems with non-normality or heteroscedasticity is that the amount of error in the model generated is not consistent with the entire range of data observed, making the weight’s predictive capacity not the same over the entire dependent variable range. Thus, predictors technically mean different things at different levels of the dependent variable and cannot explain all trends in the data set.
Logarithmic transformation
Hypothesis 0: D, t and N matter
delay = c(1,2,3,4)
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.BP.regression.data = data.frame("H" = numeric(100),
"C" = numeric(100),
stringsAsFactors=FALSE)
shapiro.hypothesis.0 = rep(0, 160)
durbinWatson.hypothesis.0 = rep(0, 160)
lm.hypothesis.0 = array(list(), 160)
plots.hypothesis.0 = array(list(), 160)
for(i in 1:160){
elements = c((((i-1)*100)+1):(i*100))
HC.BP.regression.data$H = log10(HC.BP$H[elements])
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.0[[i]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.0[i] = dwtest(lm.hypothesis.0[[i]])$p.value
shapiro.hypothesis.0[i] = shapiro.test(lm.hypothesis.0[[i]]$residuals)$p.value
HC.BP.regression.data$predicted = predict(lm.hypothesis.0[[i]])
HC.BP.regression.data$residuals = residuals(lm.hypothesis.0[[i]])
plots.hypothesis.0[[i]] = ggplot(HC.BP.regression.data, aes(x = H, y = C)) +
geom_point(colour = "blue") +
geom_smooth(method="lm", formula = y~x) +
geom_segment(aes(xend = H, yend = predicted)) +
geom_point(aes(y = predicted), shape = 1)
}
cat("Total: ", 160, " Teste de normalidade: ", length(which(shapiro.hypothesis.0 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.0 > 0.05)), '\n')
Total: 160 Teste de normalidade: 0 Teste de correlação: 152
plot(lm.hypothesis.0[[1]], which = c(1:4), pch = 20)




Hypothesis 5: D and N matter
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.BP.regression.data = data.frame("H" = numeric(400),
"C" = numeric(400),
stringsAsFactors=FALSE)
shapiro.hypothesis.5 = rep(0, 40)
durbinWatson.hypothesis.5 = rep(0, 40)
lm.hypothesis.5 = array(list(), 40)
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.BP.regression.data$H = log10(HC.BP$H[elements])
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.5[[cc]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.5[cc] = dwtest(lm.hypothesis.5[[cc]])$p.value
shapiro.hypothesis.5[cc] = shapiro.test(lm.hypothesis.5[[cc]]$residuals)$p.value
}
b = b + 4000
}
cat("Total: ", 40, " Teste de normalidade: ", length(which(shapiro.hypothesis.5 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.5 > 0.05)), '\n')
Total: 40 Teste de normalidade: 0 Teste de correlação: 39
plot(lm.hypothesis.5[[1]], which = c(1:4), pch = 20)




log(y/(1 − y)) transformation
Hypothesis 0: D, t and N matter
delay = c(1,2,3,4)
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.BP.regression.data = data.frame("H" = numeric(100),
"C" = numeric(100),
stringsAsFactors=FALSE)
shapiro.hypothesis.0 = rep(0, 160)
durbinWatson.hypothesis.0 = rep(0, 160)
lm.hypothesis.0 = array(list(), 160)
plots.hypothesis.0 = array(list(), 160)
for(i in 1:160){
elements = c((((i-1)*100)+1):(i*100))
x = HC.BP$H[elements]
y = HC.BP$C[elements]
HC.BP.regression.data$H = log(x/(1-x))
HC.BP.regression.data$C = log(y/(1-y))
lm.hypothesis.0[[i]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.0[i] = dwtest(lm.hypothesis.0[[i]])$p.value
shapiro.hypothesis.0[i] = shapiro.test(lm.hypothesis.0[[i]]$residuals)$p.value
HC.BP.regression.data$predicted = predict(lm.hypothesis.0[[i]])
HC.BP.regression.data$residuals = residuals(lm.hypothesis.0[[i]])
plots.hypothesis.0[[i]] = ggplot(HC.BP.regression.data, aes(x = H, y = C)) +
geom_point(colour = "blue") +
geom_smooth(method="lm", formula = y~x) +
geom_segment(aes(xend = H, yend = predicted)) +
geom_point(aes(y = predicted), shape = 1)
}
cat("Total: ", 160, " Teste de normalidade: ", length(which(shapiro.hypothesis.0 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.0 > 0.05)), '\n')
Total: 160 Teste de normalidade: 41 Teste de correlação: 147
plot(lm.hypothesis.0[[1]], which = c(1:4), pch = 20)




Hypothesis 5: D and N matter
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.BP.regression.data = data.frame("H" = numeric(400),
"C" = numeric(400),
stringsAsFactors=FALSE)
shapiro.hypothesis.5 = rep(0, 40)
durbinWatson.hypothesis.5 = rep(0, 40)
lm.hypothesis.5 = array(list(), 40)
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)
x = HC.BP$H[elements]
y = HC.BP$C[elements]
HC.BP.regression.data$H = log(x/(1-x))
HC.BP.regression.data$C = log(y/(1-y))
lm.hypothesis.5[[cc]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.5[cc] = dwtest(lm.hypothesis.5[[cc]])$p.value
shapiro.hypothesis.5[cc] = shapiro.test(lm.hypothesis.5[[cc]]$residuals)$p.value
}
b = b + 4000
}
cat("Total: ", 40, " Teste de normalidade: ", length(which(shapiro.hypothesis.5 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.5 > 0.05)), '\n')
Total: 40 Teste de normalidade: 0 Teste de correlação: 38
plot(lm.hypothesis.5[[1]], which = c(1:4), pch = 20)




Square root transformation
Hypothesis 0: D, t and N matter
delay = c(1,2,3,4)
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.BP.regression.data = data.frame("H" = numeric(100),
"C" = numeric(100),
stringsAsFactors=FALSE)
shapiro.hypothesis.0 = rep(0, 160)
durbinWatson.hypothesis.0 = rep(0, 160)
lm.hypothesis.0 = array(list(), 160)
plots.hypothesis.0 = array(list(), 160)
for(i in 1:160){
elements = c((((i-1)*100)+1):(i*100))
HC.BP.regression.data$H = sqrt(HC.BP$H[elements])
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.0[[i]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.0[i] = dwtest(lm.hypothesis.0[[i]])$p.value
shapiro.hypothesis.0[i] = shapiro.test(lm.hypothesis.0[[i]]$residuals)$p.value
HC.BP.regression.data$predicted = predict(lm.hypothesis.0[[i]])
HC.BP.regression.data$residuals = residuals(lm.hypothesis.0[[i]])
plots.hypothesis.0[[i]] = ggplot(HC.BP.regression.data, aes(x = H, y = C)) +
geom_point(colour = "blue") +
geom_smooth(method="lm", formula = y~x) +
geom_segment(aes(xend = H, yend = predicted)) +
geom_point(aes(y = predicted), shape = 1)
}
cat("Total: ", 160, " Teste de normalidade: ", length(which(shapiro.hypothesis.0 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.0 > 0.05)), '\n')
Total: 160 Teste de normalidade: 0 Teste de correlação: 150
plot(lm.hypothesis.0[[1]], which = c(1:4), pch = 20)




Hypothesis 5: D and N matter
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.BP.regression.data = data.frame("H" = numeric(400),
"C" = numeric(400),
stringsAsFactors=FALSE)
shapiro.hypothesis.5 = rep(0, 40)
durbinWatson.hypothesis.5 = rep(0, 40)
lm.hypothesis.5 = array(list(), 40)
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.BP.regression.data$H = sqrt(HC.BP$H[elements])
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.5[[cc]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.5[cc] = dwtest(lm.hypothesis.5[[cc]])$p.value
shapiro.hypothesis.5[cc] = shapiro.test(lm.hypothesis.5[[cc]]$residuals)$p.value
}
b = b + 4000
}
cat("Total: ", 40, " Teste de normalidade: ", length(which(shapiro.hypothesis.5 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.5 > 0.05)), '\n')
Total: 40 Teste de normalidade: 0 Teste de correlação: 39
plot(lm.hypothesis.5[[1]], which = c(1:4), pch = 20)




Inverse transformation
Hypothesis 0: D, t and N matter
delay = c(1,2,3,4)
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.BP.regression.data = data.frame("H" = numeric(100),
"C" = numeric(100),
stringsAsFactors=FALSE)
shapiro.hypothesis.0 = rep(0, 160)
durbinWatson.hypothesis.0 = rep(0, 160)
lm.hypothesis.0 = array(list(), 160)
plots.hypothesis.0 = array(list(), 160)
for(i in 1:160){
elements = c((((i-1)*100)+1):(i*100))
HC.BP.regression.data$H = 1/(HC.BP$H[elements])
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.0[[i]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.0[i] = dwtest(lm.hypothesis.0[[i]])$p.value
shapiro.hypothesis.0[i] = shapiro.test(lm.hypothesis.0[[i]]$residuals)$p.value
HC.BP.regression.data$predicted = predict(lm.hypothesis.0[[i]])
HC.BP.regression.data$residuals = residuals(lm.hypothesis.0[[i]])
plots.hypothesis.0[[i]] = ggplot(HC.BP.regression.data, aes(x = H, y = C)) +
geom_point(colour = "blue") +
geom_smooth(method="lm", formula = y~x) +
geom_segment(aes(xend = H, yend = predicted)) +
geom_point(aes(y = predicted), shape = 1)
}
cat("Total: ", 160, " Teste de normalidade: ", length(which(shapiro.hypothesis.0 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.0 > 0.05)), '\n')
Total: 160 Teste de normalidade: 0 Teste de correlação: 154
plot(lm.hypothesis.0[[1]], which = c(1:4), pch = 20)




Hypothesis 5: D and N matter
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.BP.regression.data = data.frame("H" = numeric(400),
"C" = numeric(400),
stringsAsFactors=FALSE)
shapiro.hypothesis.5 = rep(0, 40)
durbinWatson.hypothesis.5 = rep(0, 40)
lm.hypothesis.5 = array(list(), 40)
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.BP.regression.data$H = 1/(HC.BP$H[elements])
HC.BP.regression.data$C = HC.BP$C[elements]
lm.hypothesis.5[[cc]] = lm(data = HC.BP.regression.data, formula = C ~ H)
durbinWatson.hypothesis.5[cc] = dwtest(lm.hypothesis.5[[cc]])$p.value
shapiro.hypothesis.5[cc] = shapiro.test(lm.hypothesis.5[[cc]]$residuals)$p.value
}
b = b + 4000
}
cat("Total: ", 40, " Teste de normalidade: ", length(which(shapiro.hypothesis.5 > 0.05)), " Teste de correlação: ", length(which(durbinWatson.hypothesis.5 > 0.05)), '\n')
Total: 40 Teste de normalidade: 0 Teste de correlação: 38
plot(lm.hypothesis.5[[1]], which = c(1:4), pch = 20)




Solution 2: Change the model
Another alternative is to find a model that fully explains the system’s behavior. For that, one option is to use generalized linear models if we want to relax in normality.
MLGs (Generalized Linear Models) are an extension of ordinary least squares regression models. They make it possible to use other distributions for errors and a link function relating the average of the response variable to the linear combination of the explanatory variables.
Solution 3: Alternative residuals distribution
To obtain an estimate of the model parameters, it is necessary to make assumptions about the distribution of its residues. In the traditional implementation of the linear regression algorithm, using the method of ordinary least squares, this assumption is that the residuals are normally distributed.
In this way, it is possible to make other assumptions of the residues, defining an alternative distribution of the residues through:
- Generalized mixed methods;
- Maximum likelihood estimators;
- Bayesian statistics.
Another option is to use the absolute error as a loss function, since it is the maximum likelihood estimator of the Laplace distribution.
LS0tCnRpdGxlOiAiUmVwb3J0IDEgLSBUaGUgc3R1ZHkgb2YgdGhlIGRlbGF5J3MgaW5mbHVlbmNlIGFuZCByZXNpZHVlIGFuYWx5c2lzIgphdXRob3I6ICJFZHVhcmRhIENoYWdhcyIKZGF0ZTogIkFwciAxNywgMjAyMCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCgpgYGB7cn0KcmVxdWlyZShsbXRlc3QpCnJlcXVpcmUoZ2dwbG90MikKcmVxdWlyZShnZ0V4dHJhKQpyZXF1aXJlKGdndGhlbWVzKQpyZXF1aXJlKGdncHVicikKcmVxdWlyZShocmJydGhlbWVzKQpyZXF1aXJlKGV4dHJhZm9udCkKcmVxdWlyZShncmlkRXh0cmEpCnJlcXVpcmUoZ2dyZXBlbCkKcmVxdWlyZShsYXdzdGF0KQpyZXF1aXJlKG5vcnRlc3QpCnJlcXVpcmUoTm9ybWFsTGFwbGFjZSkKCnRoZW1lX3NldCh0aGVtZV9pcHN1bShiYXNlX2ZhbWlseSA9ICJUaW1lcyBOZXcgUm9tYW4iLCAKICAgICAgICAgICAgICBiYXNlX3NpemUgPSAxMCwgYXhpc190aXRsZV9zaXplID0gMTApKQpgYGAKCgojI1RoZSBzdHVkeSBvZiB0aGUgaW5mbHVlbmNlIG9mIHBhcmFtZXRlcnMKClRvIHRoaXMgYW5hbHlzaXMgd2UgdXNlZCB0aGUgZGF0YSBzZXQgd2l0aCAxNi4wMDAgc2FtcGxlcywgYXBwbHlpbmcgYWxsIHBvc3NpYmxlIGNvbmZpZ3VyYXRpb25zIHdpdGggJEQgXGluIFx7MywgNCwgNSwgNlx9JCBhbmQgJFx0YXUgXGluIFx7MSwgMiwgMywgNFx9JCB0byB0aGUgZGVzY3JpcHRvcnMuIAoKYGBge3J9CkhDLkJQID0gZGF0YS5mcmFtZSgiSCIgPSBudW1lcmljKDE2MDAwKSwgCiAgICAgICAgICAgICAgICAgICAiQyIgPSBudW1lcmljKDE2MDAwKSwKICAgICAgICAgICAgICAgICAgICJEaXN0IiA9IG51bWVyaWMoMTYwMDApLAogICAgICAgICAgICAgICAgICAgIkQiID0gbnVtZXJpYygxNjAwMCksCiAgICAgICAgICAgICAgICAgICAidCIgPSBudW1lcmljKDE2MDAwKSwgCiAgICAgICAgICAgICAgICAgICAiTiIgPSBudW1lcmljKDE2MDAwKSwgCiAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQoKSEMuQlAkTiA9IGFzLmZhY3RvcihyZXAoYyhyZXAoMWUrMDQsIDEwMCksIHJlcCgyZSswNCwgMTAwKSwgcmVwKDNlKzA0LCAxMDApLCByZXAoNGUrMDQsIDEwMCksIHJlcCg1ZSswNCwgMTAwKSwgcmVwKDZlKzA0LCAxMDApLCByZXAoN2UrMDQsIDEwMCksIHJlcCg4ZSswNCwgMTAwKSwgcmVwKDllKzA0LCAxMDApLCByZXAoMWUrMDUsIDEwMCkpLCAxNikpCgpIQy5CUCR0ID0gYXMuZmFjdG9yKHJlcChjKHJlcCgxLDEwMDApLCByZXAoMiwxMDAwKSwgcmVwKDMsMTAwMCksIHJlcCg0LDEwMDApKSwgNCkpCgpmaWxlLmNzdiA9IGRhdGEuZnJhbWUocmVhZC5jc3YoIi4uL0RhdGEvSENfc2VyaWVzX2ZrMF8xNjAwMC5jc3YiKSkKCkhDLkJQJEggPSBmaWxlLmNzdlssMV0KSEMuQlAkQyA9IGZpbGUuY3N2WywyXQpIQy5CUCREaXN0ID0gSEMuQlAkQyAvIEhDLkJQJEgKSEMuQlAkRD0gYXMuZmFjdG9yKGZpbGUuY3N2WywzXSkKCnN1bW1hcnkoSEMuQlApCmBgYAoKIyNBbHRlcm5hdGl2ZSAxIC0gQ2FsY3VsYXRlIHRoZSByZWdyZXNzaW9uIGFzIGEgZnVuY3Rpb24gb2YgSCwgRCwgdCBhbmQgTi4KCmBgYHtyfQpsbS5hbHRlcm5hdGl2ZS4xID0gbG0oZGF0YSA9IEhDLkJQLCBmb3JtdWxhID0gQyB+IEggKyBEICsgdCArIE4pCnN1bW1hcnkobG0uYWx0ZXJuYXRpdmUuMSkKYGBgCgpgYGB7cn0KYWQudGVzdChsbS5hbHRlcm5hdGl2ZS4xJHJlc2lkdWFscykKcGxvdChsbS5hbHRlcm5hdGl2ZS4xLCB3aGljaCA9IGMoMTo0KSwgcGNoID0gMjApCmhpc3QobG0uYWx0ZXJuYXRpdmUuMSRyZXNpZHVhbHMsIGJyZWFrcyA9IDUwMCkKYGBgCgojI0FsdGVybmF0aXZlIDIgLSBDYWxjdWxhdGUgdGhlIHJlZ3Jlc3Npb24gYmFzZWQgb24gSCAKCiMjI0h5cG90aGVzaXMgMDogRCwgdCBhbmQgTiBtYXR0ZXIKCmBgYHtyfQpkZWxheSA9IGMoMSwyLDMsNCkKZGltZW5zaW9uID0gYygzLDQsNSw2KQpOID0gYygxZSswNCwgMmUrMDQsIDNlKzA0LCA0ZSswNCwgNWUrMDQsIDZlKzA0LCA3ZSswNCwgOGUrMDQsIDllKzA0LCAxZSswNSkKSEMuQlAucmVncmVzc2lvbi5kYXRhID0gZGF0YS5mcmFtZSgiSCIgPSBudW1lcmljKDEwMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDIiA9IG51bWVyaWMoMTAwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQoKc2hhcGlyby5oeXBvdGhlc2lzLjAgPSByZXAoMCwgMTYwKQpkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4wID0gcmVwKDAsIDE2MCkKbG0uaHlwb3RoZXNpcy4wID0gYXJyYXkobGlzdCgpLCAxNjApCgpmb3IoaSBpbiAxOjE2MCl7CiAgZWxlbWVudHMgPSBjKCgoKGktMSkqMTAwKSsxKTooaSoxMDApKQogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRIID0gSEMuQlAkSFtlbGVtZW50c10KICBIQy5CUC5yZWdyZXNzaW9uLmRhdGEkQyA9IEhDLkJQJENbZWxlbWVudHNdCiAgbG0uaHlwb3RoZXNpcy4wW1tpXV0gPSBsbShkYXRhID0gSEMuQlAucmVncmVzc2lvbi5kYXRhLCBmb3JtdWxhID0gQyB+IEgpCiAgZHVyYmluV2F0c29uLmh5cG90aGVzaXMuMFtpXSA9IGR3dGVzdChsbS5oeXBvdGhlc2lzLjBbW2ldXSkkcC52YWx1ZQogIHNoYXBpcm8uaHlwb3RoZXNpcy4wW2ldID0gc2hhcGlyby50ZXN0KGxtLmh5cG90aGVzaXMuMFtbaV1dJHJlc2lkdWFscykkcC52YWx1ZQp9CmNhdCgiVG90YWw6ICIsIDE2MCwgIiBUZXN0ZSBkZSBub3JtYWxpZGFkZTogIiwgbGVuZ3RoKHdoaWNoKHNoYXBpcm8uaHlwb3RoZXNpcy4wID4gMC4wNSkpLCAiIFRlc3RlIGRlIGNvcnJlbGHDp8OjbzogIiwgbGVuZ3RoKHdoaWNoKGR1cmJpbldhdHNvbi5oeXBvdGhlc2lzLjAgPiAwLjA1KSksICdcbicpCmBgYAoKYGBge3J9CnBsb3QobG0uaHlwb3RoZXNpcy4wW1sxXV0sIHdoaWNoID0gYygxOjQpLCBwY2ggPSAyMCkKYGBgCgojIyNIeXBvdGhlc2lzIDE6IEQgbWF0dGVyCgpgYGB7cn0KI2xhcGxhY2UgZGlzdHJpYnV0aW9uCmRpbWVuc2lvbiA9IGMoMywgNCwgNSwgNikKSEMuQlAucmVncmVzc2lvbi5kYXRhID0gZGF0YS5mcmFtZSgiSCIgPSBudW1lcmljKDQwMDApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQyIgPSBudW1lcmljKDQwMDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCnNoYXBpcm8uaHlwb3RoZXNpcy4xID0gcmVwKDAsIDQpCmR1cmJpbldhdHNvbi5oeXBvdGhlc2lzLjEgPSByZXAoMCwgNCkKbG0uaHlwb3RoZXNpcy4xID0gYXJyYXkobGlzdCgpLCA0KQoKZm9yKGkgaW4gMTpsZW5ndGgoZGltZW5zaW9uKSl7CiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJEggPSBIQy5CUCRIWygoKGktMSkqNDAwMCkrMSk6KGkqNDAwMCldCiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJEMgPSBIQy5CUCRDWygoKGktMSkqNDAwMCkrMSk6KGkqNDAwMCldCiAgbG0uaHlwb3RoZXNpcy4xW1tpXV0gPSBsbShkYXRhID0gSEMuQlAucmVncmVzc2lvbi5kYXRhLCBmb3JtdWxhID0gQyB+IEgpCiAgZHVyYmluV2F0c29uLmh5cG90aGVzaXMuMVtpXSA9IGR3dGVzdChsbS5oeXBvdGhlc2lzLjFbW2ldXSkkcC52YWx1ZQogIHNoYXBpcm8uaHlwb3RoZXNpcy4xW2ldID0gc2hhcGlyby50ZXN0KGxtLmh5cG90aGVzaXMuMVtbaV1dJHJlc2lkdWFscykkcC52YWx1ZQp9CmNhdCgiVG90YWw6ICIsIDQsICIgVGVzdGUgZGUgbm9ybWFsaWRhZGU6ICIsIGxlbmd0aCh3aGljaChzaGFwaXJvLmh5cG90aGVzaXMuMSA+IDAuMDUpKSwgIiBUZXN0ZSBkZSBjb3JyZWxhw6fDo286ICIsIGxlbmd0aCh3aGljaChkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4xID4gMC4wNSkpLCAnXG4nKQpgYGAKCmBgYHtyfQpwbG90KGxtLmh5cG90aGVzaXMuMVtbMV1dLCB3aGljaCA9IGMoMTo0KSwgcGNoID0gMjApCmBgYAoKIyMjSHlwb3RoZXNpcyAyOiB0IG1hdHRlcgoKYGBge3J9CiNsYXBsYWNlIGRpc3RyaWJ1dGlvbgpkZWxheSA9IGMoMSwgMiwgMywgNCkKSEMuQlAucmVncmVzc2lvbi5kYXRhID0gZGF0YS5mcmFtZSgiSCIgPSBudW1lcmljKDQwMDApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQyIgPSBudW1lcmljKDQwMDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCmEgPSBjKDE6MTAwMCkKc2hhcGlyby5oeXBvdGhlc2lzLjIgPSByZXAoMCwgNCkKZHVyYmluV2F0c29uLmh5cG90aGVzaXMuMiA9IHJlcCgwLCA0KQpsbS5oeXBvdGhlc2lzLjIgPSBhcnJheShsaXN0KCksIDQpCgpmb3IoaSBpbiAxOmxlbmd0aChkZWxheSkpewogIGEgPSBjKCgoKGktMSkgKiAxMDAwKSArIDEpOihpICogMTAwMCkpCiAgZWxlbWVudHMgPSByZXAoYyhhLCBhICsgNDAwMCwgYSArIDgwMDAsIGEgKyAxMjAwMCkpCiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJEggPSBIQy5CUCRIW2VsZW1lbnRzXQogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRDID0gSEMuQlAkQ1tlbGVtZW50c10KICBsbS5oeXBvdGhlc2lzLjJbW2ldXSA9IGxtKGRhdGEgPSBIQy5CUC5yZWdyZXNzaW9uLmRhdGEsIGZvcm11bGEgPSBDIH4gSCkKICBkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4yW2ldID0gZHd0ZXN0KGxtLmh5cG90aGVzaXMuMltbaV1dKSRwLnZhbHVlCiAgc2hhcGlyby5oeXBvdGhlc2lzLjJbaV0gPSBzaGFwaXJvLnRlc3QobG0uaHlwb3RoZXNpcy4yW1tpXV0kcmVzaWR1YWxzKSRwLnZhbHVlCn0KY2F0KCJUb3RhbDogIiwgNCwgIiBUZXN0ZSBkZSBub3JtYWxpZGFkZTogIiwgbGVuZ3RoKHdoaWNoKHNoYXBpcm8uaHlwb3RoZXNpcy4yID4gMC4wNSkpLCAiIFRlc3RlIGRlIGNvcnJlbGHDp8OjbzogIiwgbGVuZ3RoKHdoaWNoKGR1cmJpbldhdHNvbi5oeXBvdGhlc2lzLjIgPiAwLjA1KSksICdcbicpCmBgYAoKYGBge3J9CnBsb3QobG0uaHlwb3RoZXNpcy4yW1sxXV0sIHdoaWNoID0gYygxOjQpLCBwY2ggPSAyMCkKYGBgCgojIyNIeXBvdGhlc2lzIDM6IE4gbWF0dGVyCgpgYGB7cn0KI2xhcGxhY2UgZGlzdHJpYnV0aW9uCk4gPSBjKDFlKzA0LCAyZSswNCwgM2UrMDQsIDRlKzA0LCA1ZSswNCwgNmUrMDQsIDdlKzA0LCA4ZSswNCwgOWUrMDQsIDFlKzA1KQpIQy5CUC5yZWdyZXNzaW9uLmRhdGEgPSBkYXRhLmZyYW1lKCJIIiA9IG51bWVyaWMoMTYwMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDIiA9IG51bWVyaWMoMTYwMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKYSA9IGMoMToxMDApCnNoYXBpcm8uaHlwb3RoZXNpcy4zID0gcmVwKDAsIDEwKQpkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4zID0gcmVwKDAsIDEwKQpsbS5oeXBvdGhlc2lzLjMgPSBhcnJheShsaXN0KCksIDEwKQoKZm9yKGkgaW4gMTpsZW5ndGgoTikpewogIGEgPSBjKCgoKGktMSkgKiAxMDApICsgMSk6KGkgKiAxMDApKQogIGVsZW1lbnRzID0gcmVwKGMoYSwgYSArIDEwMDAsIGEgKyAyMDAwLCBhICsgMzAwMCwgYSArIDQwMDAsIGEgKyA1MDAwLCBhICsgNjAwMCwgYSArIDcwMDAsIGEgKyA4MDAwLCBhICsgOTAwMCwgYSArIDEwMDAwLCBhICsgMTEwMDAsIGEgKyAxMjAwMCwgYSArIDEzMDAwLCBhICsgMTQwMDAsIGEgKyAxNTAwMCkpCiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJEggPSBIQy5CUCRIW2VsZW1lbnRzXQogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRDID0gSEMuQlAkQ1tlbGVtZW50c10KICBsbS5oeXBvdGhlc2lzLjNbW2ldXSA9IGxtKGRhdGEgPSBIQy5CUC5yZWdyZXNzaW9uLmRhdGEsIGZvcm11bGEgPSBDIH4gSCkKICBkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4zW2ldID0gZHd0ZXN0KGxtLmh5cG90aGVzaXMuM1tbaV1dKSRwLnZhbHVlCiAgc2hhcGlyby5oeXBvdGhlc2lzLjNbaV0gPSBzaGFwaXJvLnRlc3QobG0uaHlwb3RoZXNpcy4zW1tpXV0kcmVzaWR1YWxzKSRwLnZhbHVlCn0KY2F0KCJUb3RhbDogIiwgMTAsICIgVGVzdGUgZGUgbm9ybWFsaWRhZGU6ICIsIGxlbmd0aCh3aGljaChzaGFwaXJvLmh5cG90aGVzaXMuMyA+IDAuMDUpKSwgIiBUZXN0ZSBkZSBjb3JyZWxhw6fDo286ICIsIGxlbmd0aCh3aGljaChkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4zID4gMC4wNSkpLCAnXG4nKQpgYGAKCmBgYHtyfQpwbG90KGxtLmh5cG90aGVzaXMuM1tbMV1dLCB3aGljaCA9IGMoMTo0KSwgcGNoID0gMjApCmBgYAoKIyMjSHlwb3RoZXNpcyA0OiBEIGFuZCB0IG1hdHRlcgoKYGBge3J9CiNsYXBsYWNlIGRpc3RyaWJ1dGlvbgpkZWxheSA9IGMoMSwyLDMsNCkKZGltZW5zaW9uID0gYygzLDQsNSw2KQpIQy5CUC5yZWdyZXNzaW9uLmRhdGEgPSBkYXRhLmZyYW1lKCJIIiA9IG51bWVyaWMoMTAwMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDIiA9IG51bWVyaWMoMTAwMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKCnNoYXBpcm8uaHlwb3RoZXNpcy40ID0gcmVwKDAsIDE2KQpkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy40ID0gcmVwKDAsIDE2KQpsbS5oeXBvdGhlc2lzLjQgPSBhcnJheShsaXN0KCksIDE2KQoKZm9yKGkgaW4gMToobGVuZ3RoKGRpbWVuc2lvbikqbGVuZ3RoKGRlbGF5KSkpewogIGVsZW1lbnRzID0gYygoKChpLTEpICogMTAwMCkgKyAxKTooaSAqIDEwMDApKQogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRIID0gSEMuQlAkSFtlbGVtZW50c10KICBIQy5CUC5yZWdyZXNzaW9uLmRhdGEkQyA9IEhDLkJQJENbZWxlbWVudHNdCiAgbG0uaHlwb3RoZXNpcy40W1tpXV0gPSBsbShkYXRhID0gSEMuQlAucmVncmVzc2lvbi5kYXRhLCBmb3JtdWxhID0gQyB+IEgpCiAgc2hhcGlyby5oeXBvdGhlc2lzLjRbaV0gPSBzaGFwaXJvLnRlc3QobG0uaHlwb3RoZXNpcy40W1tpXV0kcmVzaWR1YWxzKSRwLnZhbHVlCiAgZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNFtpXSA9IGR3dGVzdChsbS5oeXBvdGhlc2lzLjRbW2ldXSkkcC52YWx1ZQp9CmNhdCgiVG90YWw6ICIsIDE2LCAiIFRlc3RlIGRlIG5vcm1hbGlkYWRlOiAiLCBsZW5ndGgod2hpY2goc2hhcGlyby5oeXBvdGhlc2lzLjQgPiAwLjA1KSksICIgVGVzdGUgZGUgY29ycmVsYcOnw6NvOiAiLCBsZW5ndGgod2hpY2goZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNCA+IDAuMDUpKSwgJ1xuJykKYGBgCgpgYGB7cn0KcGxvdChsbS5oeXBvdGhlc2lzLjRbWzFdXSwgd2hpY2ggPSBjKDE6NCksIHBjaCA9IDIwKQpgYGAKCiMjI0h5cG90aGVzaXMgNTogRCBhbmQgTiBtYXR0ZXIKCmBgYHtyfQpkaW1lbnNpb24gPSBjKDMsNCw1LDYpCk4gPSBjKDFlKzA0LCAyZSswNCwgM2UrMDQsIDRlKzA0LCA1ZSswNCwgNmUrMDQsIDdlKzA0LCA4ZSswNCwgOWUrMDQsIDFlKzA1KQpIQy5CUC5yZWdyZXNzaW9uLmRhdGEgPSBkYXRhLmZyYW1lKCJIIiA9IG51bWVyaWMoNDAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkMiID0gbnVtZXJpYyg0MDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpzaGFwaXJvLmh5cG90aGVzaXMuNSA9IHJlcCgwLCA0MCkKZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNSA9IHJlcCgwLCA0MCkKbG0uaHlwb3RoZXNpcy41ID0gYXJyYXkobGlzdCgpLCA0MCkKCmIgPSBjYyA9IDAKZm9yKGkgaW4gMTpsZW5ndGgoZGltZW5zaW9uKSl7CiAgZm9yKGogaW4gMTpsZW5ndGgoTikpewogICAgY2MgPSBjYyArIDEKICAgIGEgPSBjKCgoKGogLSAxKSAqIDEwMCkgKyAxKTooaiAqIDEwMCkpCiAgICBlbGVtZW50cyA9IGMoYSArIGIsIGEgKyBiICsgMTAwMCwgYSArIGIgKyAyMDAwLCBhICsgYiArIDMwMDApCiAgICBIQy5CUC5yZWdyZXNzaW9uLmRhdGEkSCA9IEhDLkJQJEhbZWxlbWVudHNdCiAgICBIQy5CUC5yZWdyZXNzaW9uLmRhdGEkQyA9IEhDLkJQJENbZWxlbWVudHNdCiAgICBsbS5oeXBvdGhlc2lzLjVbW2NjXV0gPSBsbShkYXRhID0gSEMuQlAucmVncmVzc2lvbi5kYXRhLCBmb3JtdWxhID0gQyB+IEgpCiAgICBkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy41W2NjXSA9IGR3dGVzdChsbS5oeXBvdGhlc2lzLjVbW2NjXV0pJHAudmFsdWUKICAgIHNoYXBpcm8uaHlwb3RoZXNpcy41W2NjXSA9IHNoYXBpcm8udGVzdChsbS5oeXBvdGhlc2lzLjVbW2NjXV0kcmVzaWR1YWxzKSRwLnZhbHVlCiAgfQogIGIgPSBiICsgNDAwMAp9CmNhdCgiVG90YWw6ICIsIDQwLCAiIFRlc3RlIGRlIG5vcm1hbGlkYWRlOiAiLCBsZW5ndGgod2hpY2goc2hhcGlyby5oeXBvdGhlc2lzLjUgPiAwLjA1KSksICIgVGVzdGUgZGUgY29ycmVsYcOnw6NvOiAiLCBsZW5ndGgod2hpY2goZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNSA+IDAuMDUpKSwgJ1xuJykKYGBgCgpgYGB7cn0KcGxvdChsbS5oeXBvdGhlc2lzLjVbWzFdXSwgd2hpY2ggPSBjKDE6NCksIHBjaCA9IDIwKQpgYGAKCiMjI0h5cG90aGVzaXMgNjogdCBhbmQgTiBtYXR0ZXIKCmBgYHtyfQpkZWxheSA9IGMoMSwyLDMsNCkKTiA9IGMoMWUrMDQsIDJlKzA0LCAzZSswNCwgNGUrMDQsIDVlKzA0LCA2ZSswNCwgN2UrMDQsIDhlKzA0LCA5ZSswNCwgMWUrMDUpCkhDLkJQLnJlZ3Jlc3Npb24uZGF0YSA9IGRhdGEuZnJhbWUoIkgiID0gbnVtZXJpYyg0MDApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQyIgPSBudW1lcmljKDQwMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKCnNoYXBpcm8uaHlwb3RoZXNpcy42ID0gcmVwKDAsIDQwKQpsbS5oeXBvdGhlc2lzLjYgPSBhcnJheShsaXN0KCksIDQwKQpkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy42ID0gcmVwKDAsIDQwKQoKYiA9IGNjID0gMApmb3IoaSBpbiAxOmxlbmd0aChkZWxheSkpewogIGZvcihqIGluIDE6bGVuZ3RoKE4pKXsKICAgIGNjID0gY2MgKyAxCiAgICBhID0gYygoKChqIC0gMSkgKiAxMDApICsgMSk6KGogKiAxMDApKQogICAgZWxlbWVudHMgPSBjKGEgKyBiLCBhICsgYiArIDQwMDAsIGEgKyBiICsgODAwMCwgYSArIGIgKyAxMjAwMCkKICAgIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRIID0gSEMuQlAkSFtlbGVtZW50c10KICAgIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRDID0gSEMuQlAkQ1tlbGVtZW50c10KICAgIGxtLmh5cG90aGVzaXMuNltbY2NdXSA9IGxtKGRhdGEgPSBIQy5CUC5yZWdyZXNzaW9uLmRhdGEsIGZvcm11bGEgPSBDIH4gSCkKICAgIGR1cmJpbldhdHNvbi5oeXBvdGhlc2lzLjZbY2NdID0gZHd0ZXN0KGxtLmh5cG90aGVzaXMuNltbY2NdXSkkcC52YWx1ZQogICAgc2hhcGlyby5oeXBvdGhlc2lzLjZbY2NdID0gc2hhcGlyby50ZXN0KGxtLmh5cG90aGVzaXMuNltbY2NdXSRyZXNpZHVhbHMpJHAudmFsdWUKICB9CiAgYiA9IGIgKyAxMDAwCn0KY2F0KCJUb3RhbDogIiwgNDAsICIgVGVzdGUgZGUgbm9ybWFsaWRhZGU6ICIsIGxlbmd0aCh3aGljaChzaGFwaXJvLmh5cG90aGVzaXMuNiA+IDAuMDUpKSwgIiBUZXN0ZSBkZSBjb3JyZWxhw6fDo286ICIsIGxlbmd0aCh3aGljaChkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy42ID4gMC4wNSkpLCAnXG4nKQpgYGAKCmBgYHtyfQpwbG90KGxtLmh5cG90aGVzaXMuNltbMV1dLCB3aGljaCA9IGMoMTo0KSwgcGNoID0gMjApCmBgYAoKIyMjVGhlIHByb2JsZW0KCkFzIHNlZW4gaW4gdGhlIG5vcm1hbGl0eSB0ZXN0cyBhYm92ZSwgdGhlIHJlc2lkdWVzIG9idGFpbmVkIGRvIG5vdCBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGFuZCBhcmUgdGhlcmVmb3JlIG5vdCBpLmkuZCAoaW5kZXBlbmRlbnQgYW5kIGlkZW50aWNhbGx5IGRpc3RyaWJ1dGVkKS4KQWNjb3JkaW5nIHRvIHRoZSBHYXVzcy1NYXJrb3YgdGhlb3JlbSwgdGhlIGxlYXN0IHNxdWFyZXMgcmVncmVzc2lvbiBpcyB0aGUgYmVzdCBsaW5lYXIgZXN0aW1hdGUgb2YgdGhlIHVuZGVybHlpbmcgY29lZmZpY2llbnRzLCB3aGVuIGl0IGlzIGFzc3VtZWQgdGhhdCB0aGUgZXJyb3JzIGFyZSBub3QgY29ycmVsYXRlZCBhbmQgaGF2ZSB0aGUgc2FtZSB2YXJpYW5jZS4KSG93ZXZlciwgaW4gdGhlIHByZXNlbmNlIG9mIG5vbi1ub3JtYWwgcmVzaWR1ZXMgb3IgaGV0ZXJvc2NlZGFzdGljaXR5LCB0aGUgZXN0aW1hdG9yIGRvZXMgbm90IHdvcmsgZWZmaWNpZW50bHkgKGFsdGhvdWdoIGl0IHJlbWFpbnMgY29uc2lzdGVudCksIHByb2R1Y2luZyBpbmFjY3VyYXRlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLgoKT25lIG9mIHRoZSBtYWpvciBwcm9ibGVtcyB3aXRoIG5vbi1ub3JtYWxpdHkgb3IgaGV0ZXJvc2NlZGFzdGljaXR5IGlzIHRoYXQgdGhlIGFtb3VudCBvZiBlcnJvciBpbiB0aGUgbW9kZWwgZ2VuZXJhdGVkIGlzIG5vdCBjb25zaXN0ZW50IHdpdGggdGhlIGVudGlyZSByYW5nZSBvZiBkYXRhIG9ic2VydmVkLCBtYWtpbmcgdGhlIHdlaWdodCdzIHByZWRpY3RpdmUgY2FwYWNpdHkgbm90IHRoZSBzYW1lIG92ZXIgdGhlIGVudGlyZSBkZXBlbmRlbnQgdmFyaWFibGUgcmFuZ2UuClRodXMsIHByZWRpY3RvcnMgdGVjaG5pY2FsbHkgbWVhbiBkaWZmZXJlbnQgdGhpbmdzIGF0IGRpZmZlcmVudCBsZXZlbHMgb2YgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgY2Fubm90IGV4cGxhaW4gYWxsIHRyZW5kcyBpbiB0aGUgZGF0YSBzZXQuCgojIyNQb3NzaWJsZSBzb2x1dGlvbnMKCiMjIyNTb2x1dGlvbiAxOiBUcmFuc2Zvcm1hdGlvbiBvZiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlCgpUaGUgdHJhbnNmb3JtYXRpb24gb2YgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBjYW4gYmUgYW4gb3B0aW9uIHRvIGNvcnJlY3QgdGhlIHByb2JsZW0gZW5jb3VudGVyZWQsIGJ1dCBhdCB0aGUgc2FtZSB0aW1lIGl0IG1ha2VzIHRoZSBpbnRlcnByZXRhdGlvbiBvZiB0aGUgZ2VuZXJhbCBtb2RlbCBhIGxpdHRsZSBtb3JlIG9wYXF1ZS4KClRoZSBzdHJlbmd0aCBvZiB0aGUgdHJhbnNmb3JtYXRpb25zIHRlbmRzIHRvIGZvbGxvdyB0aGUgb3JkZXIgYmVsb3c6CgoxLiBMb2dhcml0aG1pYwoyLiBTcXVhcmUgcm9vdAozLiBSZXZlcnNlCgojIyNMb2dhcml0aG1pYyB0cmFuc2Zvcm1hdGlvbgoKIyMjSHlwb3RoZXNpcyAwOiBELCB0IGFuZCBOIG1hdHRlcgoKYGBge3J9CmRlbGF5ID0gYygxLDIsMyw0KQpkaW1lbnNpb24gPSBjKDMsNCw1LDYpCk4gPSBjKDFlKzA0LCAyZSswNCwgM2UrMDQsIDRlKzA0LCA1ZSswNCwgNmUrMDQsIDdlKzA0LCA4ZSswNCwgOWUrMDQsIDFlKzA1KQpIQy5CUC5yZWdyZXNzaW9uLmRhdGEgPSBkYXRhLmZyYW1lKCJIIiA9IG51bWVyaWMoMTAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkMiID0gbnVtZXJpYygxMDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpzaGFwaXJvLmh5cG90aGVzaXMuMCA9IHJlcCgwLCAxNjApCmR1cmJpbldhdHNvbi5oeXBvdGhlc2lzLjAgPSByZXAoMCwgMTYwKQpsbS5oeXBvdGhlc2lzLjAgPSBhcnJheShsaXN0KCksIDE2MCkKcGxvdHMuaHlwb3RoZXNpcy4wID0gYXJyYXkobGlzdCgpLCAxNjApCgpmb3IoaSBpbiAxOjE2MCl7CiAgZWxlbWVudHMgPSBjKCgoKGktMSkqMTAwKSsxKTooaSoxMDApKQogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRIID0gbG9nMTAoSEMuQlAkSFtlbGVtZW50c10pCiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJEMgPSBIQy5CUCRDW2VsZW1lbnRzXQogIGxtLmh5cG90aGVzaXMuMFtbaV1dID0gbG0oZGF0YSA9IEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSwgZm9ybXVsYSA9IEMgfiBIKQogIGR1cmJpbldhdHNvbi5oeXBvdGhlc2lzLjBbaV0gPSBkd3Rlc3QobG0uaHlwb3RoZXNpcy4wW1tpXV0pJHAudmFsdWUKICBzaGFwaXJvLmh5cG90aGVzaXMuMFtpXSA9IHNoYXBpcm8udGVzdChsbS5oeXBvdGhlc2lzLjBbW2ldXSRyZXNpZHVhbHMpJHAudmFsdWUKICBIQy5CUC5yZWdyZXNzaW9uLmRhdGEkcHJlZGljdGVkID0gcHJlZGljdChsbS5oeXBvdGhlc2lzLjBbW2ldXSkgCiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJHJlc2lkdWFscyA9IHJlc2lkdWFscyhsbS5oeXBvdGhlc2lzLjBbW2ldXSkKICBwbG90cy5oeXBvdGhlc2lzLjBbW2ldXSA9IGdncGxvdChIQy5CUC5yZWdyZXNzaW9uLmRhdGEsIGFlcyh4ID0gSCwgeSA9IEMpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9wb2ludChjb2xvdXIgPSAiYmx1ZSIpICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxtIiwgZm9ybXVsYSA9IHl+eCkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlb21fc2VnbWVudChhZXMoeGVuZCA9IEgsIHllbmQgPSBwcmVkaWN0ZWQpKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9wb2ludChhZXMoeSA9IHByZWRpY3RlZCksIHNoYXBlID0gMSkKfQpjYXQoIlRvdGFsOiAiLCAxNjAsICIgVGVzdGUgZGUgbm9ybWFsaWRhZGU6ICIsIGxlbmd0aCh3aGljaChzaGFwaXJvLmh5cG90aGVzaXMuMCA+IDAuMDUpKSwgIiBUZXN0ZSBkZSBjb3JyZWxhw6fDo286ICIsIGxlbmd0aCh3aGljaChkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4wID4gMC4wNSkpLCAnXG4nKQpgYGAKCmBgYHtyfQpwbG90KGxtLmh5cG90aGVzaXMuMFtbMV1dLCB3aGljaCA9IGMoMTo0KSwgcGNoID0gMjApCmBgYAoKIyMjSHlwb3RoZXNpcyA1OiBEIGFuZCBOIG1hdHRlcgoKYGBge3J9CmRpbWVuc2lvbiA9IGMoMyw0LDUsNikKTiA9IGMoMWUrMDQsIDJlKzA0LCAzZSswNCwgNGUrMDQsIDVlKzA0LCA2ZSswNCwgN2UrMDQsIDhlKzA0LCA5ZSswNCwgMWUrMDUpCkhDLkJQLnJlZ3Jlc3Npb24uZGF0YSA9IGRhdGEuZnJhbWUoIkgiID0gbnVtZXJpYyg0MDApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQyIgPSBudW1lcmljKDQwMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKCnNoYXBpcm8uaHlwb3RoZXNpcy41ID0gcmVwKDAsIDQwKQpkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy41ID0gcmVwKDAsIDQwKQpsbS5oeXBvdGhlc2lzLjUgPSBhcnJheShsaXN0KCksIDQwKQoKYiA9IGNjID0gMApmb3IoaSBpbiAxOmxlbmd0aChkaW1lbnNpb24pKXsKICBmb3IoaiBpbiAxOmxlbmd0aChOKSl7CiAgICBjYyA9IGNjICsgMQogICAgYSA9IGMoKCgoaiAtIDEpICogMTAwKSArIDEpOihqICogMTAwKSkKICAgIGVsZW1lbnRzID0gYyhhICsgYiwgYSArIGIgKyAxMDAwLCBhICsgYiArIDIwMDAsIGEgKyBiICsgMzAwMCkKICAgIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRIID0gbG9nMTAoSEMuQlAkSFtlbGVtZW50c10pCiAgICBIQy5CUC5yZWdyZXNzaW9uLmRhdGEkQyA9IEhDLkJQJENbZWxlbWVudHNdCiAgICBsbS5oeXBvdGhlc2lzLjVbW2NjXV0gPSBsbShkYXRhID0gSEMuQlAucmVncmVzc2lvbi5kYXRhLCBmb3JtdWxhID0gQyB+IEgpCiAgICBkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy41W2NjXSA9IGR3dGVzdChsbS5oeXBvdGhlc2lzLjVbW2NjXV0pJHAudmFsdWUKICAgIHNoYXBpcm8uaHlwb3RoZXNpcy41W2NjXSA9IHNoYXBpcm8udGVzdChsbS5oeXBvdGhlc2lzLjVbW2NjXV0kcmVzaWR1YWxzKSRwLnZhbHVlCiAgfQogIGIgPSBiICsgNDAwMAp9CmNhdCgiVG90YWw6ICIsIDQwLCAiIFRlc3RlIGRlIG5vcm1hbGlkYWRlOiAiLCBsZW5ndGgod2hpY2goc2hhcGlyby5oeXBvdGhlc2lzLjUgPiAwLjA1KSksICIgVGVzdGUgZGUgY29ycmVsYcOnw6NvOiAiLCBsZW5ndGgod2hpY2goZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNSA+IDAuMDUpKSwgJ1xuJykKYGBgCgpgYGB7cn0KcGxvdChsbS5oeXBvdGhlc2lzLjVbWzFdXSwgd2hpY2ggPSBjKDE6NCksIHBjaCA9IDIwKQpgYGAKCgojIyMgbG9nKHkvKDEg4oiSIHkpKSB0cmFuc2Zvcm1hdGlvbgoKIyMjSHlwb3RoZXNpcyAwOiBELCB0IGFuZCBOIG1hdHRlcgoKYGBge3J9CmRlbGF5ID0gYygxLDIsMyw0KQpkaW1lbnNpb24gPSBjKDMsNCw1LDYpCk4gPSBjKDFlKzA0LCAyZSswNCwgM2UrMDQsIDRlKzA0LCA1ZSswNCwgNmUrMDQsIDdlKzA0LCA4ZSswNCwgOWUrMDQsIDFlKzA1KQpIQy5CUC5yZWdyZXNzaW9uLmRhdGEgPSBkYXRhLmZyYW1lKCJIIiA9IG51bWVyaWMoMTAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkMiID0gbnVtZXJpYygxMDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpzaGFwaXJvLmh5cG90aGVzaXMuMCA9IHJlcCgwLCAxNjApCmR1cmJpbldhdHNvbi5oeXBvdGhlc2lzLjAgPSByZXAoMCwgMTYwKQpsbS5oeXBvdGhlc2lzLjAgPSBhcnJheShsaXN0KCksIDE2MCkKcGxvdHMuaHlwb3RoZXNpcy4wID0gYXJyYXkobGlzdCgpLCAxNjApCgpmb3IoaSBpbiAxOjE2MCl7CiAgZWxlbWVudHMgPSBjKCgoKGktMSkqMTAwKSsxKTooaSoxMDApKQogIHggPSBIQy5CUCRIW2VsZW1lbnRzXQogIHkgPSBIQy5CUCRDW2VsZW1lbnRzXQogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRIID0gbG9nKHgvKDEteCkpCiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJEMgPSBsb2coeS8oMS15KSkKICBsbS5oeXBvdGhlc2lzLjBbW2ldXSA9IGxtKGRhdGEgPSBIQy5CUC5yZWdyZXNzaW9uLmRhdGEsIGZvcm11bGEgPSBDIH4gSCkKICBkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4wW2ldID0gZHd0ZXN0KGxtLmh5cG90aGVzaXMuMFtbaV1dKSRwLnZhbHVlCiAgc2hhcGlyby5oeXBvdGhlc2lzLjBbaV0gPSBzaGFwaXJvLnRlc3QobG0uaHlwb3RoZXNpcy4wW1tpXV0kcmVzaWR1YWxzKSRwLnZhbHVlCiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJHByZWRpY3RlZCA9IHByZWRpY3QobG0uaHlwb3RoZXNpcy4wW1tpXV0pIAogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRyZXNpZHVhbHMgPSByZXNpZHVhbHMobG0uaHlwb3RoZXNpcy4wW1tpXV0pCiAgcGxvdHMuaHlwb3RoZXNpcy4wW1tpXV0gPSBnZ3Bsb3QoSEMuQlAucmVncmVzc2lvbi5kYXRhLCBhZXMoeCA9IEgsIHkgPSBDKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoY29sb3VyID0gImJsdWUiKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIGZvcm11bGEgPSB5fngpICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSBILCB5ZW5kID0gcHJlZGljdGVkKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoYWVzKHkgPSBwcmVkaWN0ZWQpLCBzaGFwZSA9IDEpCn0KY2F0KCJUb3RhbDogIiwgMTYwLCAiIFRlc3RlIGRlIG5vcm1hbGlkYWRlOiAiLCBsZW5ndGgod2hpY2goc2hhcGlyby5oeXBvdGhlc2lzLjAgPiAwLjA1KSksICIgVGVzdGUgZGUgY29ycmVsYcOnw6NvOiAiLCBsZW5ndGgod2hpY2goZHVyYmluV2F0c29uLmh5cG90aGVzaXMuMCA+IDAuMDUpKSwgJ1xuJykKYGBgCgpgYGB7cn0KcGxvdChsbS5oeXBvdGhlc2lzLjBbWzFdXSwgd2hpY2ggPSBjKDE6NCksIHBjaCA9IDIwKQpgYGAKCiMjI0h5cG90aGVzaXMgNTogRCBhbmQgTiBtYXR0ZXIKCmBgYHtyfQpkaW1lbnNpb24gPSBjKDMsNCw1LDYpCk4gPSBjKDFlKzA0LCAyZSswNCwgM2UrMDQsIDRlKzA0LCA1ZSswNCwgNmUrMDQsIDdlKzA0LCA4ZSswNCwgOWUrMDQsIDFlKzA1KQpIQy5CUC5yZWdyZXNzaW9uLmRhdGEgPSBkYXRhLmZyYW1lKCJIIiA9IG51bWVyaWMoNDAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkMiID0gbnVtZXJpYyg0MDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpzaGFwaXJvLmh5cG90aGVzaXMuNSA9IHJlcCgwLCA0MCkKZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNSA9IHJlcCgwLCA0MCkKbG0uaHlwb3RoZXNpcy41ID0gYXJyYXkobGlzdCgpLCA0MCkKCmIgPSBjYyA9IDAKZm9yKGkgaW4gMTpsZW5ndGgoZGltZW5zaW9uKSl7CiAgZm9yKGogaW4gMTpsZW5ndGgoTikpewogICAgY2MgPSBjYyArIDEKICAgIGEgPSBjKCgoKGogLSAxKSAqIDEwMCkgKyAxKTooaiAqIDEwMCkpCiAgICBlbGVtZW50cyA9IGMoYSArIGIsIGEgKyBiICsgMTAwMCwgYSArIGIgKyAyMDAwLCBhICsgYiArIDMwMDApCiAgICB4ID0gSEMuQlAkSFtlbGVtZW50c10KICAgIHkgPSBIQy5CUCRDW2VsZW1lbnRzXQogICAgSEMuQlAucmVncmVzc2lvbi5kYXRhJEggPSBsb2coeC8oMS14KSkKICAgIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRDID0gbG9nKHkvKDEteSkpCiAgICBsbS5oeXBvdGhlc2lzLjVbW2NjXV0gPSBsbShkYXRhID0gSEMuQlAucmVncmVzc2lvbi5kYXRhLCBmb3JtdWxhID0gQyB+IEgpCiAgICBkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy41W2NjXSA9IGR3dGVzdChsbS5oeXBvdGhlc2lzLjVbW2NjXV0pJHAudmFsdWUKICAgIHNoYXBpcm8uaHlwb3RoZXNpcy41W2NjXSA9IHNoYXBpcm8udGVzdChsbS5oeXBvdGhlc2lzLjVbW2NjXV0kcmVzaWR1YWxzKSRwLnZhbHVlCiAgfQogIGIgPSBiICsgNDAwMAp9CmNhdCgiVG90YWw6ICIsIDQwLCAiIFRlc3RlIGRlIG5vcm1hbGlkYWRlOiAiLCBsZW5ndGgod2hpY2goc2hhcGlyby5oeXBvdGhlc2lzLjUgPiAwLjA1KSksICIgVGVzdGUgZGUgY29ycmVsYcOnw6NvOiAiLCBsZW5ndGgod2hpY2goZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNSA+IDAuMDUpKSwgJ1xuJykKYGBgCgpgYGB7cn0KcGxvdChsbS5oeXBvdGhlc2lzLjVbWzFdXSwgd2hpY2ggPSBjKDE6NCksIHBjaCA9IDIwKQpgYGAKCiMjI1NxdWFyZSByb290IHRyYW5zZm9ybWF0aW9uCgojIyNIeXBvdGhlc2lzIDA6IEQsIHQgYW5kIE4gbWF0dGVyCgpgYGB7cn0KZGVsYXkgPSBjKDEsMiwzLDQpCmRpbWVuc2lvbiA9IGMoMyw0LDUsNikKTiA9IGMoMWUrMDQsIDJlKzA0LCAzZSswNCwgNGUrMDQsIDVlKzA0LCA2ZSswNCwgN2UrMDQsIDhlKzA0LCA5ZSswNCwgMWUrMDUpCkhDLkJQLnJlZ3Jlc3Npb24uZGF0YSA9IGRhdGEuZnJhbWUoIkgiID0gbnVtZXJpYygxMDApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQyIgPSBudW1lcmljKDEwMCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKCnNoYXBpcm8uaHlwb3RoZXNpcy4wID0gcmVwKDAsIDE2MCkKZHVyYmluV2F0c29uLmh5cG90aGVzaXMuMCA9IHJlcCgwLCAxNjApCmxtLmh5cG90aGVzaXMuMCA9IGFycmF5KGxpc3QoKSwgMTYwKQpwbG90cy5oeXBvdGhlc2lzLjAgPSBhcnJheShsaXN0KCksIDE2MCkKCmZvcihpIGluIDE6MTYwKXsKICBlbGVtZW50cyA9IGMoKCgoaS0xKSoxMDApKzEpOihpKjEwMCkpCiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJEggPSBzcXJ0KEhDLkJQJEhbZWxlbWVudHNdKQogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRDID0gSEMuQlAkQ1tlbGVtZW50c10KICBsbS5oeXBvdGhlc2lzLjBbW2ldXSA9IGxtKGRhdGEgPSBIQy5CUC5yZWdyZXNzaW9uLmRhdGEsIGZvcm11bGEgPSBDIH4gSCkKICBkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4wW2ldID0gZHd0ZXN0KGxtLmh5cG90aGVzaXMuMFtbaV1dKSRwLnZhbHVlCiAgc2hhcGlyby5oeXBvdGhlc2lzLjBbaV0gPSBzaGFwaXJvLnRlc3QobG0uaHlwb3RoZXNpcy4wW1tpXV0kcmVzaWR1YWxzKSRwLnZhbHVlCiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJHByZWRpY3RlZCA9IHByZWRpY3QobG0uaHlwb3RoZXNpcy4wW1tpXV0pIAogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRyZXNpZHVhbHMgPSByZXNpZHVhbHMobG0uaHlwb3RoZXNpcy4wW1tpXV0pCiAgcGxvdHMuaHlwb3RoZXNpcy4wW1tpXV0gPSBnZ3Bsb3QoSEMuQlAucmVncmVzc2lvbi5kYXRhLCBhZXMoeCA9IEgsIHkgPSBDKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoY29sb3VyID0gImJsdWUiKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIGZvcm11bGEgPSB5fngpICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSBILCB5ZW5kID0gcHJlZGljdGVkKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoYWVzKHkgPSBwcmVkaWN0ZWQpLCBzaGFwZSA9IDEpCn0KY2F0KCJUb3RhbDogIiwgMTYwLCAiIFRlc3RlIGRlIG5vcm1hbGlkYWRlOiAiLCBsZW5ndGgod2hpY2goc2hhcGlyby5oeXBvdGhlc2lzLjAgPiAwLjA1KSksICIgVGVzdGUgZGUgY29ycmVsYcOnw6NvOiAiLCBsZW5ndGgod2hpY2goZHVyYmluV2F0c29uLmh5cG90aGVzaXMuMCA+IDAuMDUpKSwgJ1xuJykKYGBgCgpgYGB7cn0KcGxvdChsbS5oeXBvdGhlc2lzLjBbWzFdXSwgd2hpY2ggPSBjKDE6NCksIHBjaCA9IDIwKQpgYGAKCiMjI0h5cG90aGVzaXMgNTogRCBhbmQgTiBtYXR0ZXIKCmBgYHtyfQpkaW1lbnNpb24gPSBjKDMsNCw1LDYpCk4gPSBjKDFlKzA0LCAyZSswNCwgM2UrMDQsIDRlKzA0LCA1ZSswNCwgNmUrMDQsIDdlKzA0LCA4ZSswNCwgOWUrMDQsIDFlKzA1KQpIQy5CUC5yZWdyZXNzaW9uLmRhdGEgPSBkYXRhLmZyYW1lKCJIIiA9IG51bWVyaWMoNDAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkMiID0gbnVtZXJpYyg0MDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpzaGFwaXJvLmh5cG90aGVzaXMuNSA9IHJlcCgwLCA0MCkKZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNSA9IHJlcCgwLCA0MCkKbG0uaHlwb3RoZXNpcy41ID0gYXJyYXkobGlzdCgpLCA0MCkKCmIgPSBjYyA9IDAKZm9yKGkgaW4gMTpsZW5ndGgoZGltZW5zaW9uKSl7CiAgZm9yKGogaW4gMTpsZW5ndGgoTikpewogICAgY2MgPSBjYyArIDEKICAgIGEgPSBjKCgoKGogLSAxKSAqIDEwMCkgKyAxKTooaiAqIDEwMCkpCiAgICBlbGVtZW50cyA9IGMoYSArIGIsIGEgKyBiICsgMTAwMCwgYSArIGIgKyAyMDAwLCBhICsgYiArIDMwMDApCiAgICBIQy5CUC5yZWdyZXNzaW9uLmRhdGEkSCA9IHNxcnQoSEMuQlAkSFtlbGVtZW50c10pCiAgICBIQy5CUC5yZWdyZXNzaW9uLmRhdGEkQyA9IEhDLkJQJENbZWxlbWVudHNdCiAgICBsbS5oeXBvdGhlc2lzLjVbW2NjXV0gPSBsbShkYXRhID0gSEMuQlAucmVncmVzc2lvbi5kYXRhLCBmb3JtdWxhID0gQyB+IEgpCiAgICBkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy41W2NjXSA9IGR3dGVzdChsbS5oeXBvdGhlc2lzLjVbW2NjXV0pJHAudmFsdWUKICAgIHNoYXBpcm8uaHlwb3RoZXNpcy41W2NjXSA9IHNoYXBpcm8udGVzdChsbS5oeXBvdGhlc2lzLjVbW2NjXV0kcmVzaWR1YWxzKSRwLnZhbHVlCiAgfQogIGIgPSBiICsgNDAwMAp9CmNhdCgiVG90YWw6ICIsIDQwLCAiIFRlc3RlIGRlIG5vcm1hbGlkYWRlOiAiLCBsZW5ndGgod2hpY2goc2hhcGlyby5oeXBvdGhlc2lzLjUgPiAwLjA1KSksICIgVGVzdGUgZGUgY29ycmVsYcOnw6NvOiAiLCBsZW5ndGgod2hpY2goZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNSA+IDAuMDUpKSwgJ1xuJykKYGBgCgpgYGB7cn0KcGxvdChsbS5oeXBvdGhlc2lzLjVbWzFdXSwgd2hpY2ggPSBjKDE6NCksIHBjaCA9IDIwKQpgYGAKCiMjI0ludmVyc2UgdHJhbnNmb3JtYXRpb24KCiMjI0h5cG90aGVzaXMgMDogRCwgdCBhbmQgTiBtYXR0ZXIKCmBgYHtyfQpkZWxheSA9IGMoMSwyLDMsNCkKZGltZW5zaW9uID0gYygzLDQsNSw2KQpOID0gYygxZSswNCwgMmUrMDQsIDNlKzA0LCA0ZSswNCwgNWUrMDQsIDZlKzA0LCA3ZSswNCwgOGUrMDQsIDllKzA0LCAxZSswNSkKSEMuQlAucmVncmVzc2lvbi5kYXRhID0gZGF0YS5mcmFtZSgiSCIgPSBudW1lcmljKDEwMCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDIiA9IG51bWVyaWMoMTAwKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQoKc2hhcGlyby5oeXBvdGhlc2lzLjAgPSByZXAoMCwgMTYwKQpkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4wID0gcmVwKDAsIDE2MCkKbG0uaHlwb3RoZXNpcy4wID0gYXJyYXkobGlzdCgpLCAxNjApCnBsb3RzLmh5cG90aGVzaXMuMCA9IGFycmF5KGxpc3QoKSwgMTYwKQoKZm9yKGkgaW4gMToxNjApewogIGVsZW1lbnRzID0gYygoKChpLTEpKjEwMCkrMSk6KGkqMTAwKSkKICBIQy5CUC5yZWdyZXNzaW9uLmRhdGEkSCA9IDEvKEhDLkJQJEhbZWxlbWVudHNdKQogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRDID0gSEMuQlAkQ1tlbGVtZW50c10KICBsbS5oeXBvdGhlc2lzLjBbW2ldXSA9IGxtKGRhdGEgPSBIQy5CUC5yZWdyZXNzaW9uLmRhdGEsIGZvcm11bGEgPSBDIH4gSCkKICBkdXJiaW5XYXRzb24uaHlwb3RoZXNpcy4wW2ldID0gZHd0ZXN0KGxtLmh5cG90aGVzaXMuMFtbaV1dKSRwLnZhbHVlCiAgc2hhcGlyby5oeXBvdGhlc2lzLjBbaV0gPSBzaGFwaXJvLnRlc3QobG0uaHlwb3RoZXNpcy4wW1tpXV0kcmVzaWR1YWxzKSRwLnZhbHVlCiAgSEMuQlAucmVncmVzc2lvbi5kYXRhJHByZWRpY3RlZCA9IHByZWRpY3QobG0uaHlwb3RoZXNpcy4wW1tpXV0pIAogIEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSRyZXNpZHVhbHMgPSByZXNpZHVhbHMobG0uaHlwb3RoZXNpcy4wW1tpXV0pCiAgcGxvdHMuaHlwb3RoZXNpcy4wW1tpXV0gPSBnZ3Bsb3QoSEMuQlAucmVncmVzc2lvbi5kYXRhLCBhZXMoeCA9IEgsIHkgPSBDKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoY29sb3VyID0gImJsdWUiKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsIGZvcm11bGEgPSB5fngpICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9tX3NlZ21lbnQoYWVzKHhlbmQgPSBILCB5ZW5kID0gcHJlZGljdGVkKSkgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlb21fcG9pbnQoYWVzKHkgPSBwcmVkaWN0ZWQpLCBzaGFwZSA9IDEpCn0KY2F0KCJUb3RhbDogIiwgMTYwLCAiIFRlc3RlIGRlIG5vcm1hbGlkYWRlOiAiLCBsZW5ndGgod2hpY2goc2hhcGlyby5oeXBvdGhlc2lzLjAgPiAwLjA1KSksICIgVGVzdGUgZGUgY29ycmVsYcOnw6NvOiAiLCBsZW5ndGgod2hpY2goZHVyYmluV2F0c29uLmh5cG90aGVzaXMuMCA+IDAuMDUpKSwgJ1xuJykKYGBgCgpgYGB7cn0KcGxvdChsbS5oeXBvdGhlc2lzLjBbWzFdXSwgd2hpY2ggPSBjKDE6NCksIHBjaCA9IDIwKQpgYGAKCiMjI0h5cG90aGVzaXMgNTogRCBhbmQgTiBtYXR0ZXIKCmBgYHtyfQpkaW1lbnNpb24gPSBjKDMsNCw1LDYpCk4gPSBjKDFlKzA0LCAyZSswNCwgM2UrMDQsIDRlKzA0LCA1ZSswNCwgNmUrMDQsIDdlKzA0LCA4ZSswNCwgOWUrMDQsIDFlKzA1KQpIQy5CUC5yZWdyZXNzaW9uLmRhdGEgPSBkYXRhLmZyYW1lKCJIIiA9IG51bWVyaWMoNDAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkMiID0gbnVtZXJpYyg0MDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpzaGFwaXJvLmh5cG90aGVzaXMuNSA9IHJlcCgwLCA0MCkKZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNSA9IHJlcCgwLCA0MCkKbG0uaHlwb3RoZXNpcy41ID0gYXJyYXkobGlzdCgpLCA0MCkKCmIgPSBjYyA9IDAKZm9yKGkgaW4gMTpsZW5ndGgoZGltZW5zaW9uKSl7CiAgZm9yKGogaW4gMTpsZW5ndGgoTikpewogICAgY2MgPSBjYyArIDEKICAgIGEgPSBjKCgoKGogLSAxKSAqIDEwMCkgKyAxKTooaiAqIDEwMCkpCiAgICBlbGVtZW50cyA9IGMoYSArIGIsIGEgKyBiICsgMTAwMCwgYSArIGIgKyAyMDAwLCBhICsgYiArIDMwMDApCiAgICBIQy5CUC5yZWdyZXNzaW9uLmRhdGEkSCA9IDEvKEhDLkJQJEhbZWxlbWVudHNdKQogICAgSEMuQlAucmVncmVzc2lvbi5kYXRhJEMgPSBIQy5CUCRDW2VsZW1lbnRzXQogICAgbG0uaHlwb3RoZXNpcy41W1tjY11dID0gbG0oZGF0YSA9IEhDLkJQLnJlZ3Jlc3Npb24uZGF0YSwgZm9ybXVsYSA9IEMgfiBIKQogICAgZHVyYmluV2F0c29uLmh5cG90aGVzaXMuNVtjY10gPSBkd3Rlc3QobG0uaHlwb3RoZXNpcy41W1tjY11dKSRwLnZhbHVlCiAgICBzaGFwaXJvLmh5cG90aGVzaXMuNVtjY10gPSBzaGFwaXJvLnRlc3QobG0uaHlwb3RoZXNpcy41W1tjY11dJHJlc2lkdWFscykkcC52YWx1ZQogIH0KICBiID0gYiArIDQwMDAKfQpjYXQoIlRvdGFsOiAiLCA0MCwgIiBUZXN0ZSBkZSBub3JtYWxpZGFkZTogIiwgbGVuZ3RoKHdoaWNoKHNoYXBpcm8uaHlwb3RoZXNpcy41ID4gMC4wNSkpLCAiIFRlc3RlIGRlIGNvcnJlbGHDp8OjbzogIiwgbGVuZ3RoKHdoaWNoKGR1cmJpbldhdHNvbi5oeXBvdGhlc2lzLjUgPiAwLjA1KSksICdcbicpCmBgYAoKYGBge3J9CnBsb3QobG0uaHlwb3RoZXNpcy41W1sxXV0sIHdoaWNoID0gYygxOjQpLCBwY2ggPSAyMCkKYGBgCgojIyMjU29sdXRpb24gMjogQ2hhbmdlIHRoZSBtb2RlbAoKQW5vdGhlciBhbHRlcm5hdGl2ZSBpcyB0byBmaW5kIGEgbW9kZWwgdGhhdCBmdWxseSBleHBsYWlucyB0aGUgc3lzdGVtJ3MgYmVoYXZpb3IuCkZvciB0aGF0LCBvbmUgb3B0aW9uIGlzIHRvIHVzZSBnZW5lcmFsaXplZCBsaW5lYXIgbW9kZWxzIGlmIHdlIHdhbnQgdG8gcmVsYXggaW4gbm9ybWFsaXR5LgoKTUxHcyAoR2VuZXJhbGl6ZWQgTGluZWFyIE1vZGVscykgYXJlIGFuIGV4dGVuc2lvbiBvZiBvcmRpbmFyeSBsZWFzdCBzcXVhcmVzIHJlZ3Jlc3Npb24gbW9kZWxzLgpUaGV5IG1ha2UgaXQgcG9zc2libGUgdG8gdXNlIG90aGVyIGRpc3RyaWJ1dGlvbnMgZm9yIGVycm9ycyBhbmQgYSBsaW5rIGZ1bmN0aW9uIHJlbGF0aW5nIHRoZSBhdmVyYWdlIG9mIHRoZSByZXNwb25zZSB2YXJpYWJsZSB0byB0aGUgbGluZWFyIGNvbWJpbmF0aW9uIG9mIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMuCgojIyMjU29sdXRpb24gMzogQWx0ZXJuYXRpdmUgcmVzaWR1YWxzIGRpc3RyaWJ1dGlvbgoKVG8gb2J0YWluIGFuIGVzdGltYXRlIG9mIHRoZSBtb2RlbCBwYXJhbWV0ZXJzLCBpdCBpcyBuZWNlc3NhcnkgdG8gbWFrZSBhc3N1bXB0aW9ucyBhYm91dCB0aGUgZGlzdHJpYnV0aW9uIG9mIGl0cyByZXNpZHVlcy4KSW4gdGhlIHRyYWRpdGlvbmFsIGltcGxlbWVudGF0aW9uIG9mIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBhbGdvcml0aG0sIHVzaW5nIHRoZSBtZXRob2Qgb2Ygb3JkaW5hcnkgbGVhc3Qgc3F1YXJlcywgdGhpcyBhc3N1bXB0aW9uIGlzIHRoYXQgdGhlIHJlc2lkdWFscyBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuCgpJbiB0aGlzIHdheSwgaXQgaXMgcG9zc2libGUgdG8gbWFrZSBvdGhlciBhc3N1bXB0aW9ucyBvZiB0aGUgcmVzaWR1ZXMsIGRlZmluaW5nIGFuIGFsdGVybmF0aXZlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1ZXMgdGhyb3VnaDoKCjEuIEdlbmVyYWxpemVkIG1peGVkIG1ldGhvZHM7CjIuIE1heGltdW0gbGlrZWxpaG9vZCBlc3RpbWF0b3JzOwozLiBCYXllc2lhbiBzdGF0aXN0aWNzLgoKQW5vdGhlciBvcHRpb24gaXMgdG8gdXNlIHRoZSBhYnNvbHV0ZSBlcnJvciBhcyBhIGxvc3MgZnVuY3Rpb24sIHNpbmNlIGl0IGlzIHRoZSBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdG9yIG9mIHRoZSBMYXBsYWNlIGRpc3RyaWJ1dGlvbi4K