Určete aritmetický průměr, medián, rozptyl a směrodatnou odchylku souboru 34 měření úbytku alkalické rezervy u matek prvorodiček.

Určete střední hodnotu 24 stanovení mědi (v ppm) v celozrnné mouce.


library(MASS)
data(chem)
xch = chem


# Cullen Frey plot
library(fitdistrplus)
descdist(xch, discrete=FALSE)
descdist(xch, discrete=FALSE, boot=999)

library(PASWR2)
eda(xch, trim = 0.05, dec = 3)

library(s20x)
normcheck(xch)

library(UsingR)
simple.eda(xch)

library(StatDA)
edaplot(xch,H.freq=FALSE,box=TRUE,H.breaks=30,S.pch=3,S.cex=0.5,D.lwd=1.5,P.log=FALSE,P.main="",P.xlab="Cu [ppm]",P.ylab="Density",B.pch=3,B.cex=0.5)



boxplot.stats(xch, coef = 1.5, do.conf = TRUE, do.out = TRUE)
library(univOutl)
boxB(xch, k=1.5, method="resistant", weights=NULL, id=NULL, exclude=NA, logt=FALSE)
boxB(xch, k=1.5, method='asymmetric', weights=NULL, id=NULL,exclude=NA, logt=FALSE)$outliers
boxB(xch, k=1.5, method='adjbox', weights=NULL, id=NULL, exclude=NA, logt=FALSE)$outliers

library(EnvStats)
rosnerTest(xch, k = 2, alpha = 0.05, warn = TRUE)

library(outliers)
grubbs.test(xch, type=20, opposite=FALSE, two.sided=TRUE)


library(extremevalues)
getOutliers(xch,method="I",distribution="normal")
getOutliers(xch,method="II",distribution="normal")
L <- getOutliers(xch,method="II",distribution="normal")
outlierPlot(xch,L,mode="qq")
outlierPlot(xch,L,mode="residual")

library(OutlierDetection)
UnivariateOutlierDetection(xch, k = 0.05 * length(xch), cutoff = 0.95, dist = FALSE, dens = FALSE, depth = FALSE, Method = "euclidean", rnames = FALSE)


mean(xch)
median(xch)
sd(xch, na.rm=TRUE)


mean(xch,trim=0.1)
mean(xch,trim=0.05)
library(asbio)
mean(trim.me(xch, trim = 0.05))
sd(trim.me(xch, trim = 0.05))

length(xch)
library(asbio)
length(trim.me(xch, trim = 0.05))
length(trim.me(xch, trim = 0.1))

library(WRS2)
winmean(xch, tr = 0.1, na.rm = FALSE)
winmean(xch, tr = 0.05, na.rm = FALSE)
sqrt(winvar(x, tr = 0.2, na.rm = FALSE, STAND = NULL))

### robustni M-odhady (Huber)
library(MASS)
hub = huber(xch, k = 1.5, tol = 1e-06)
hub$mu
hub$s

Průměrná koncentrace z 8 stanovení iontů Na+ v roztoku byla 0.547 mol/l se směrodatnou odchylkou 0.003 mol/l. Určete intervaly spolehlivosti pro průměr, směrodatnou odchylku a rozptyl pro hladinu významnosti 0.05.


m = 0.547
s = 0.003
s2 = s^2; s2
n = 5

m + c(-s,s)*qt(0.95,df=n-1)/sqrt(n)
library(LearningStats)
Mean.CI(m, sigma = NULL, sc = NULL, s = s, n = n, conf.level= 0.95)

s*sqrt((n-1)/qchisq(c(0.975,0.025),df=n-1))
library(LearningStats)
variance.CI(x = NULL, s = s, sc = NULL, smu = NULL, mu = NULL, n = n, conf.level= 0.95)

Byl měřen obsah cínu (v %) ve 100 vzorcích rudy. Výsledky byly zaznamenány formou četnostní tabulky. Určete průměrnou hodnotu a rozptyl.


xx = c(30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80)
fx = c(4, 6, 8, 15, 25, 20, 8, 7, 5, 2)
N = sum(fx)
wt <- fx/N

xx1 = xx[-1]
xx2 = xx[-length(xx)]
xxm = (xx2+xx1)/2

barplot(wt, names.arg = xxm,xlab = "Sn (%)")

density=wt/diff(xx)
plot(xxm,density,type = "h",lwd=8,col=4,xlab = "Sn (%)")
abline(h=0)
xs = seq(xxm[1],xxm[length(xxm)],0.01)
dxs = dnorm(xs,mean=53,sd=10)
points(xs,dxs,type="l",col = "red", lwd = 2)


wm = sum(xxm*fx)/N; wm
weighted.mean(xxm, wt, na.rm = TRUE)
library(Hmisc)
wtd.mean(xxm, weights=wt, normwt=FALSE, na.rm=TRUE)

library(modi)
ws2 = weighted.var(xxm, wt, na.rm = TRUE); ws2
ws = sqrt(ws2); ws
library(Hmisc)
wtd.var(xxm, weights=wt, normwt=FALSE, na.rm=TRUE,method='ML')
# method=c('unbiased', 'ML')
sqrt(wtd.var(xxm, weights=wt, normwt=FALSE, na.rm=TRUE,method='ML'))

wm + c(-s,s)*qt(0.95,df=N-1)/sqrt(N)
library(LearningStats)
Mean.CI(wm, sigma = NULL, sc = NULL, s = s, n = N, conf.level= 0.95)

ws*sqrt((N-1)/qchisq(c(0.975,0.025),df=N-1))
library(LearningStats)
variance.CI(x = NULL, s = ws, sc = NULL, smu = NULL, mu = NULL, n = N, conf.level= 0.95)


library(sn)
fitdistr.grouped(breaks=xx, counts=fx, family="normal", trace = FALSE, wpar = NULL)

Metodou EDXRF byly stanoveny prvky v keramické mase a glazuře keramiky z lokalit Longquan a Jingdezhen. Ke zkoumání surovin a technologie výpalu bylo vybráno celkem čtyřicet typických střepů (https://archive.ics.uci.edu/ml/datasets/Chemical+Composition+of+Ceramic+Samples)

data <- read.csv("https://archive.ics.uci.edu/ml/machine-learning-databases/00583/Chemical Composion of Ceramic.csv")
head(data)
ss <- function(X){substr(X, start=1, stop=2)}
snam <- ss(data[,1])
snam

MM = as.data.frame(cbind(snam,data[,"Part"],data["MnO"]))
colnames(MM) = c("Site","Part","MnO")

mno = MM[,"MnO"]
part = as.factor(MM[,"Part"])
site = as.factor(MM[,"Site"])
aggregate(mno,list(site,part), FUN=mean)
aggregate(mno,list(site,part), FUN=median)
aggregate(mno,list(site,part), FUN=length)
aggregate(mno,list(site,part), FUN=function(x){sd(x)/mean(x)})


### Distribuce MnO v keramice jedné z lokalit.

mm = MM[which(MM$Site=="DY"),]
mno = mm[,"MnO"]

## Normalita

# Cullen Frey plot
library(fitdistrplus)
descdist(mno, discrete=FALSE)
descdist(mno, discrete=FALSE, boot=999)
descdist(log(mno), discrete=FALSE, boot=999)

library(PASWR2)
eda(mno, trim = 0, dec = 3)
eda(log(mno), trim = 0, dec = 3)

library(s20x)
normcheck(mno)
normcheck(log(mno))

library(UsingR)
simple.eda(mno)
simple.eda(log(mno))

library(StatDA)
edaplot(mno,H.freq=FALSE,box=TRUE,H.breaks=30,S.pch=3,S.cex=0.5,D.lwd=1.5,P.log=FALSE,P.main="",P.xlab="Zmena alk. rezervy", P.ylab="Density",B.pch=3,B.cex=0.5)

edaplot(mno,H.freq=FALSE,box=TRUE,H.breaks=30,S.pch=3,S.cex=0.5,D.lwd=1.5,P.log=TRUE,P.main="",P.xlab="Zmena alk. rezervy", P.ylab="Density",B.pch=3,B.cex=0.5)


library(cwhmisc)  #  T3 plot (Ghosh)
T3plot(mno,lab=paste("T3 plot of ",deparse(substitute(x))), legend.pos="bottom", cex=0.6)
T3plot(log(mno),lab=paste("T3 plot of ",deparse(substitute(x))), legend.pos="bottom", cex=0.6)


# Box-Cox

library(car)
boxCox(lm(mno~1), lambda = seq(-2, 2, 1/10), plotit = TRUE, interp = TRUE, eps = 1/50, xlab=NULL, ylab=NULL, family="bcPower", param= "lambda", gamma=NULL,grid=TRUE)

library(forecast)
lambda = BoxCox.lambda(mno, method = "loglik", lower = -2, upper = 2)
# method = c("guerrero", "loglik")
xbc = BoxCox(mno, lambda)
xrt = InvBoxCox(xbc, lambda, biasadj = FALSE, fvar = NULL)
par(mfrow=c(1,2))
hist(mno, main="")
hist(xbc, main="",xlab="transf x")
par(mfrow=c(1,1))
er <- qt(0.975,df=length(xbc)-1)*sd(xbc)/sqrt(length(xbc))
left <- mean(xbc)-er; left
right <- mean(xbc)+er; right
InvBoxCox(c(mean(xbc), left, right), lambda, biasadj = FALSE, fvar = NULL)


## Bhattacharya plot s ASH
library(ash) 
nn=30
f <- ash1(bin1(mno,nbin=nn),5) # ash estimate
nk<-length(f$y)-1
yk<-rep(0,nk)
xk<-rep(0,nk)
for(i in 1:nk){
  yk[i]<-log(f$y[i+1]/f$y[i])
  xk[i]<-(f$x[i+1]+f$x[i])/2
}
plot(xk,yk, type="l",col=1,lty=1, main="", xlab="x",ylab="ln( f(i+1) / f(i) )")
rug(mno)


# Hartigan dip test
library(diptest)
dtb = dip(mno, full.result = TRUE, min.is.0 = TRUE, debug = FALSE); dtb
dip.test(mno, simulate.p.value = FALSE, B = 2000)
plot(dtb)


# Silvermanuv test
library(silvermantest) 
# https://www.mathematik.uni-marburg.de/~stochastik/R_packages/
silverman.test(mno, k=1, M = 999, adjust = FALSE, digits = 6)
silverman.test(mno, k=2, M = 999, adjust = FALSE, digits = 6)
silverman.test(mno, k=3, M = 999, adjust = FALSE, digits = 6)
silverman.plot(mno, kmin=1, kmax=3, alpha=0.05, adjust=FALSE)


# Ameijeiras-Alonso excess mass test
library(multimode)
modetest(mno,mod0=1,method="ACR",B=500,lowsup=-Inf,uppsup=Inf,submethod=NULL,n=NULL,tol=NULL,tol2=NULL,gridsize=NULL,alpha=NULL,nMC=NULL,BMC=NULL)


# metoda max verohodnosti
library(mclust)
xs<- sort(mno)
dmc <- Mclust(xs,G=NULL)
dmcBIC <- mclustBIC(x); dmcBIC
nn = 2
dmc <- Mclust(xs,G=nn)
dmcz <-round(dmc$z,nn); as.data.frame(cbind(mm[,2],dmcz))

Byl zjišťován obsah tuku (v %) v mléce od 16 ovcí. Určete vhodnou střední hodnotu tučnosti mléka.


xmo = c(4.08, 3.91, 4.02, 4.26, 4.03, 3.94, 3.82, 3.72, 4.03, 3.87, 4.09, 3.92, 4.18, 3.93, 3.81, 3.71)


### Overeni predpokladu

## Nezavislost

library(s20x)
trendscatter(c(1:length(xmo)), y = xmo, f = 0.5, xlab = "Index", ylab = "Obsah tuku (%)", main = "")

library(DescTools)
VonNeumannTest(xmo, alternative = "two.sided", unbiased = TRUE)
# alternative = c("two.sided", "less", "greater")

library(DescTools)
BartelsRankTest(xmo, alternative = "two.sided", method = "normal")
# alternative = c("two.sided", "trend", "oscillation")
# method = c("normal", "beta", "auto")

library(litteR)
mk = mann_kendall(xmo, type = "both")
# type = c("both", "increasing", "decreasing")
p_value(mk)


## Normalita

# Cullen Frey plot
library(fitdistrplus)
descdist(xmo, discrete=FALSE)
descdist(xmo, discrete=FALSE, boot=999)

library(PASWR2)
eda(xmo, trim = 0, dec = 3)

library(s20x)
normcheck(xmo)

library(UsingR)
simple.eda(xmo)

library(StatDA)
edaplot(xmo,H.freq=FALSE,box=TRUE,H.breaks=30,S.pch=3,S.cex=0.5,D.lwd=1.5,P.log=FALSE,P.main="",P.xlab="Zmena alk. rezervy", P.ylab="Density",B.pch=3,B.cex=0.5)

library(cwhmisc)  #  T3 plot (Ghosh)
T3plot(xmo,lab=paste("T3 plot of ",deparse(substitute(x))), legend.pos="bottom", cex=0.6)


library(moments)
moments::skewness(xmo)
library(e1071)
e1071::skewness(xmo, na.rm = FALSE, type = 3)
library(confintr)
ci_skewness(xmo,probs = c(0.025, 0.975),type = "bootstrap", boot_type = "bca", R = 9999,seed = NULL)
# boot_type = c("bca", "perc", "norm", "basic")

# DAgostinuv test sikmosti
library(moments)
agostino.test(xmo, alternative = "two.sided")
# alternative = c("two.sided", "less", "greater")


library(moments)
kurtosis(xmo)# spicatost
library(confintr)
ci_kurtosis(xmo,probs = c(0.025, 0.975),type = "bootstrap", boot_type = "bca", R = 9999, seed = NULL)
# boot_type = c("bca", "perc", "norm", "basic")

# Anscombe-Glynnuv test spicatosti
library(moments)
anscombe.test(xmo, alternative = "two.sided")
# alternative = c("two.sided", "less", "greater")

# Geary test spicatosti
library(fmsb)
geary.test(xmo)


# Shapiro-Francia test
library(nortest)
sf.test(xmo)

# Shapiro-Wilk test
shapiro.test(xmo)

# Anderson-Darling test
library(nortest)
ad.test(xmo)

# Cramer-von Mises test
cvm.test(xmo)

# Jarque Bera test
library(tseries)
jarque.bera.test(xmo)
library(lawstat)
rjb.test(xmo, option="JB",crit.values="empirical", N = 5000) # klasicky J. B. test
rjb.test(xmo, option="RJB",crit.values="empirical", N = 5000) # robustni J. B. test
# crit.values = c("chisq.approximation", "empirical")

# Lilliefors test (modif. Kolmogorov-Smirnov)
library(nortest)
lillie.test(xmo)

# sj test
library(lawstat)
sj.test(xmo, crit.values = "empirical", N = 1000)
# crit.values = c("t.approximation", "empirical")


## outliers
boxplot.stats(xmo, coef = 1.5, do.conf = TRUE, do.out = TRUE)


## parametry

mean(xmo)
library(confintr)
ci_mean(xmo,  probs = c(0.025, 0.975),type = "t")
ci_mean(xmo,  probs = c(0.025, 0.975),type = "bootstrap",  boot_type = "bca", R = 9999, seed = NULL)
# boot_type = c("stud" (default), "bca", "perc", "norm", "basic")
library(MKinfer)
meanCI(xmo, conf.level = 0.95, boot = FALSE, na.rm = TRUE, alternative = "two.sided")
meanCI(xmo, conf.level = 0.95, boot = TRUE, R = 9999, bootci.type = "all",na.rm = TRUE, alternative = "two.sided")
# alternative = c("two.sided", "less", "greater")

Obsah Ba v kostech (ppm) z lokality Dolní Věstonice - Písky.


xba = c(102.48078, 135.75333, 130.46889, 138.71764, 104.37857,  73.57628,48.91491,67.98234, 101.35093,  60.16596,  90.75023,  47.34744, 49.33503, 76.46496, 175.35793, 130.49675, 148.01476, 114.79635,  65.91149,  83.92482,  71.02072, 34.66255,  96.01142,  78.07690,  54.59542, 158.29052, 119.87277,  69.14092, 78.84901,  41.29317,  72.81092, 554.77243, 259.68719, 149.31984, 107.85497,
82.09231,  26.01403,  98.94641,  56.41384,  86.10823, 118.56925,  94.48836,
65.17541)


# Cullen Frey plot
library(fitdistrplus)
descdist(xba, discrete=FALSE)
descdist(xba, discrete=FALSE, boot=999)
descdist(log(xba), discrete=FALSE, boot=999)

library(PASWR2)
eda(xba, trim = 0.05, dec = 3)
eda(log(xba), trim = 0.05, dec = 3)

library(s20x)
normcheck(xba)
normcheck(log(xba))

library(UsingR)
simple.eda(xba)
simple.eda(log(xba))

library(StatDA)
edaplot(xba,H.freq=FALSE,box=TRUE,H.breaks=30,S.pch=3,S.cex=0.5,D.lwd=1.5,P.log=FALSE,P.main="",P.xlab="Cu [ppm]",P.ylab="Density",B.pch=3,B.cex=0.5)

library(StatDA)
edaplot(xba,H.freq=FALSE,box=TRUE,H.breaks=30,S.pch=3,S.cex=0.5,D.lwd=1.5,P.log=TRUE,P.main="",P.xlab="Cu [ppm]",P.ylab="Density",B.pch=3,B.cex=0.5)



boxplot.stats(xba, coef = 1.5, do.conf = TRUE, do.out = TRUE)
library(univOutl)
boxB(xba, k=1.5, method="resistant", weights=NULL, id=NULL, exclude=NA, logt=FALSE)
boxB(xba, k=1.5, method='asymmetric', weights=NULL, id=NULL,exclude=NA, logt=FALSE)$outliers
boxB(xba, k=1.5, method='adjbox', weights=NULL, id=NULL, exclude=NA, logt=FALSE)$outliers

library(extremevalues)
#getOutliers(xba,method="I",distribution="normal")
#getOutliers(xba,method="II",distribution="normal")
getOutliers(xba,method="I",distribution="lognormal")
getOutliers(xba,method="II",distribution="lognormal")
L <- getOutliers(xch,method="II",distribution="normal")
outlierPlot(xch,L,mode="qq")
outlierPlot(xch,L,mode="residual")

library(OutlierDetection)
UnivariateOutlierDetection(xba, k = 0.05 * length(xch), cutoff = 0.95, dist = FALSE, dens = FALSE, depth = FALSE, Method = "euclidean", rnames = FALSE)


mno = xba[-32]
# mno = xba[-c(32,33)]


# Box-Cox

library(car)
boxCox(lm(mno~1), lambda = seq(-2, 2, 1/10), plotit = TRUE, interp = TRUE, eps = 1/50, xlab=NULL, ylab=NULL, family="bcPower", param= "lambda", gamma=NULL,grid=TRUE)

library(forecast)
lambda = BoxCox.lambda(mno, method = "loglik", lower = -2, upper = 2)
# method = c("guerrero", "loglik")
xbc = BoxCox(mno, lambda)
xrt = InvBoxCox(xbc, lambda, biasadj = FALSE, fvar = NULL)
par(mfrow=c(1,2))
hist(mno, main="")
hist(xbc, main="",xlab="transf x")
par(mfrow=c(1,1))
er <- qt(0.975,df=length(xbc)-1)*sd(xbc)/sqrt(length(xbc))
left <- mean(xbc)-er
right <- mean(xbc)+er
InvBoxCox(c(mean(xbc), left, right), lambda, biasadj = FALSE, fvar = NULL)


mean(xba)
median(xba)
sd(xba, na.rm=TRUE)

mean(mno)
median(mno)
sd(mno, na.rm=TRUE)

library(FSA)
geomean(mno, na.rm = FALSE, zneg.rm = FALSE)
library(DescTools)
Gmean(mno, method = "boot", conf.level = 0.05,sides = "two.sided", na.rm = FALSE)
# method = c("classic", "boot")
# sides = c("two.sided","left","right")
library(fuel)
lognormalmean(mno, estimator="ml", base = exp(1),n = length(mno), m = n - 1, d = 1/n)

library(FSA)
sg = geosd(mno, na.rm = FALSE, zneg.rm = FALSE); 10^sg
library(fuel)
lognormalsd(mno, estimator="ml", base = exp(1),n = length(mno),m = n - 1, d = 1/n)
library(DescTools)
Gsd(mno, na.rm = FALSE)


### Kvantilove odhady

median(xba)

library(confintr)
ci_median(xba,probs = c(0.025, 0.975),type = "bootstrap", boot_type = "bca", R = 9999,seed = NULL)
# type = c("binomial", "bootstrap")
# boot_type = c("bca", "perc", "norm", "basic")
library(MKinfer)
medianCI(xba, conf.level = 0.95, method = "exact",R = 9999, bootci.type = "bca",minLength = FALSE, na.rm = FALSE,alternative = "two.sided")
# method = c("exact", "asymptotic")
# bootci.type = c("norm", "basic", "perc", "bca"),
# alternative = c("two.sided", "less", "greater")


mad(xba, center = median(xba), constant = 1.4826, na.rm = FALSE)
library(rQCC)
mad.unbiased (xba, center = median(xba), constant=1.4826, na.rm = FALSE)

mad2.unbiased(xba, center = median(xba), constant=1.4826, na.rm = FALSE)



library(fitdistrplus)
flm = fitdist(mno,distr="lnorm", method = "mle")
# method = c("mle", "mme", "qme", "mge", "mse")
summary(flm)

fga = fitdist(mno,distr="gamma", method = "mle")
# method = c("mle", "mme", "qme", "mge", "mse")
summary(fga)

Při zjišťování obsahu uhlíku v uhlí byly (za předpokladu normálního rozdělení) z 20 měření vypočteny průměrný obsah 83.050 % a směrodatná odchylka 3.456 %. Určete 95% intervaly spolehlivosti obou parametrů.

Aktivita enzymu podílejícího se na metabolismu karcinogenních látek. Jde o hodnoty močového metabolického poměru 5-acetylamino-6-formylamino-3-methyluracilu k1-methylxantinu (AFMU/1X) po perorálním podání kofeinu.


library(multimode)
data(enzyme)
xea = enzyme

## Normalita

# Cullen Frey plot
library(fitdistrplus)
descdist(xea, discrete=FALSE)
descdist(xea, discrete=FALSE, boot=999)
descdist(log(xea), discrete=FALSE, boot=999)

library(PASWR2)
eda(xea, trim = 0, dec = 3)
eda(log(xea), trim = 0, dec = 3)

library(s20x)
normcheck(xea)
normcheck(log(xea))

library(UsingR)
simple.eda(xea)
simple.eda(log(xea))

library(StatDA)
edaplot(xea,H.freq=FALSE,box=TRUE,H.breaks=30,S.pch=3,S.cex=0.5,D.lwd=1.5,P.log=FALSE,P.main="",P.xlab="Aktivita enzymu", P.ylab="Density",B.pch=3,B.cex=0.5)

edaplot(xea,H.freq=FALSE,box=TRUE,H.breaks=30,S.pch=3,S.cex=0.5,D.lwd=1.5,P.log=TRUE,P.main="",P.xlab="Aktivita enzymu", P.ylab="Density",B.pch=3,B.cex=0.5)






# Box-Cox

library(car)
boxCox(lm(xea~1), lambda = seq(-2, 2, 1/10), plotit = TRUE, interp = TRUE, eps = 1/50, xlab=NULL, ylab=NULL, family="bcPower", param= "lambda", gamma=NULL,grid=TRUE)

library(forecast)
lambda = BoxCox.lambda(xea, method = "loglik", lower = -2, upper = 2)
# method = c("guerrero", "loglik")
xbc = BoxCox(xea, lambda)
xrt = InvBoxCox(xbc, lambda, biasadj = FALSE, fvar = NULL)
par(mfrow=c(1,2))
hist(xea, main="")
hist(xbc, main="",xlab="transf x")
par(mfrow=c(1,1))
er <- qt(0.975,df=length(xbc)-1)*sd(xbc)/sqrt(length(xbc))
left <- mean(xbc)-er; left
right <- mean(xbc)+er; right
InvBoxCox(c(mean(xbc), left, right), lambda, biasadj = FALSE, fvar = NULL)


## Bhattacharya plot s ASH
dat = xea
library(ash) 
nn=30
f <- ash1(bin1(dat,nbin=nn),5) # ash estimate
nk<-length(f$y)-1
yk<-rep(0,nk)
xk<-rep(0,nk)
for(i in 1:nk){
  yk[i]<-log(f$y[i+1]/f$y[i])
  xk[i]<-(f$x[i+1]+f$x[i])/2
}
plot(xk,yk, type="l",col=1,lty=1, main="", xlab="x",ylab="ln( f(i+1) / f(i) )")
rug(dat)


# Hartigan dip test
library(diptest)
dtb = dip(xea, full.result = TRUE, min.is.0 = TRUE, debug = FALSE); dtb
dip.test(xea, simulate.p.value = FALSE, B = 2000)
plot(dtb)


# Silvermanuv test
library(silvermantest) 
# https://www.mathematik.uni-marburg.de/~stochastik/R_packages/
silverman.test(mno, k=1, M = 999, adjust = FALSE, digits = 6)
silverman.test(mno, k=2, M = 999, adjust = FALSE, digits = 6)
silverman.test(mno, k=3, M = 999, adjust = FALSE, digits = 6)
silverman.test(mno, k=4, M = 999, adjust = FALSE, digits = 6)
silverman.plot(mno, kmin=1, kmax=3, alpha=0.05, adjust=FALSE)


# Ameijeiras-Alonso excess mass test
library(multimode)
modetest(mno,mod0=1,method="ACR",B=500,lowsup=-Inf,uppsup=Inf,submethod=NULL,n=NULL,tol=NULL,tol2=NULL,gridsize=NULL,alpha=NULL,nMC=NULL,BMC=NULL)


# metoda max verohodnosti
library(mclust)
xs<- sort(mno)
dmc <- Mclust(xs,G=NULL)
dmcBIC <- mclustBIC(x); dmcBIC
nn = 3
dmc <- Mclust(xs,G=nn)
dmcz <-round(dmc$z,nn); dmcz

Procento oxidu křemičitého (v %) ve 22 chondritových meteoritech.


library(multimode)
data(chondrite)
xcd = chondrite

## Normalita

# Cullen Frey plot
library(fitdistrplus)
descdist(xcd, discrete=FALSE)
descdist(xcd, discrete=FALSE, boot=999)
descdist(log(xcd), discrete=FALSE, boot=999)

library(PASWR2)
eda(xcd, trim = 0, dec = 3)
eda(log(xcd), trim = 0, dec = 3)

library(s20x)
normcheck(xcd)
normcheck(log(xcd))

library(UsingR)
simple.eda(xcd)
simple.eda(log(xcd))

library(StatDA)
edaplot(xcd, H.freq=FALSE,box=TRUE,H.breaks=30,S.pch=3,S.cex=0.5,D.lwd=1.5,P.log=FALSE,P.main="",P.xlab="SiO2", P.ylab="Density",B.pch=3,B.cex=0.5)

edaplot(xcd,H.freq=FALSE,box=TRUE,H.breaks=30,S.pch=3,S.cex=0.5,D.lwd=1.5,P.log=TRUE,P.main="",P.xlab="SiO2", P.ylab="Density",B.pch=3,B.cex=0.5)


# Box-Cox

library(car)
boxCox(lm(xcd~1), lambda = seq(-2, 2, 1/10), plotit = TRUE, interp = TRUE, eps = 1/50, xlab=NULL, ylab=NULL, family="bcPower", param= "lambda", gamma=NULL,grid=TRUE)

library(forecast)
lambda = BoxCox.lambda(xcd, method = "loglik", lower = -2, upper = 2)
# method = c("guerrero", "loglik")
xbc = BoxCox(xcd, lambda)
xrt = InvBoxCox(xbc, lambda, biasadj = FALSE, fvar = NULL)
par(mfrow=c(1,2))
hist(xcd, main="")
hist(xbc, main="",xlab="transf x")
par(mfrow=c(1,1))
er <- qt(0.975,df=length(xbc)-1)*sd(xbc)/sqrt(length(xbc))
left <- mean(xbc)-er; left
right <- mean(xbc)+er; right
InvBoxCox(c(mean(xbc), left, right), lambda, biasadj = FALSE, fvar = NULL)


## Bhattacharya plot s ASH
dat = xcd
library(ash) 
nn=30
f <- ash1(bin1(dat,nbin=nn),5) # ash estimate
nk<-length(f$y)-1
yk<-rep(0,nk)
xk<-rep(0,nk)
for(i in 1:nk){
  yk[i]<-log(f$y[i+1]/f$y[i])
  xk[i]<-(f$x[i+1]+f$x[i])/2
}
plot(xk,yk, type="l",col=1,lty=1, main="", xlab="x",ylab="ln( f(i+1) / f(i) )")
rug(dat)


# Hartigan dip test
library(diptest)
dtb = dip(xcd, full.result = TRUE, min.is.0 = TRUE, debug = FALSE); dtb
dip.test(xcd, simulate.p.value = FALSE, B = 2000)
plot(dtb)


# Silvermanuv test
dat = xcd
library(silvermantest) 
# https://www.mathematik.uni-marburg.de/~stochastik/R_packages/
silverman.test(dat, k=1, M = 999, adjust = FALSE, digits = 6)
silverman.test(dat, k=2, M = 999, adjust = FALSE, digits = 6)
silverman.test(dat, k=3, M = 999, adjust = FALSE, digits = 6)
silverman.plot(dat, kmin=1, kmax=3, alpha=0.05, adjust=FALSE)


# Ameijeiras-Alonso excess mass test
library(multimode)
modetest(xcd,mod0=1,method="ACR",B=500,lowsup=-Inf,uppsup=Inf,submethod=NULL,n=NULL,tol=NULL,tol2=NULL,gridsize=NULL,alpha=NULL,nMC=NULL,BMC=NULL)


# metoda max verohodnosti
library(mclust)
xs<- sort(xcd)
dmc <- Mclust(xs,G=NULL)
dmcBIC <- mclustBIC(x); dmcBIC
nn = 2
dmc <- Mclust(xs,G=nn)
dmcz <-round(dmc$z,nn); dmcz

Určete počet paralelních kolorimetrických stanovení obsahu Fe, aby maximální chyba výsledné hodnoty průměru nepřekročila hodnotu 0.005. Chyba metody (směrodatná odchylka) je 0.0132.


delta = 0.005
sigma = 0.0132

np = (3*sigma/delta)^2; np

nz = ((sigma*qnorm(0.975))/delta)^2; nz

library(samplingbook)
sample.size.mean(e=delta, S=sigma, N = Inf, level = 0.95)

qt = 3
nt = ((sigma*qt)/delta)^2; nt
# iterace
nt = nt-1
nt = ((sigma*qt(0.975,(nt-1)))/delta)^2; nt

Automatický soustruh vyrábí těsnící kroužky o deklarovaném průměru 25 mm. Náhodně vybraných 30 kroužků mělo průměrnou hodnotu 25.43 mm a směrodatnou odchylku 0.145 mm. Je možné při riziku 5 % připustit, že automat dodržuje nominální hodnotu 25 mm?


library(PASWR2)
tsum.test(mean.x = 25.43, s.x = 0.145, n.x = 30, mean.y = NULL, s.y = NULL,n.y = NULL, alternative = "two.sided", mu = 25,var.equal = FALSE,conf.level = 0.95)
# alternative = c("two.sided", "less", "greater")

Při použití dvou odlišných metod měření byly na 10 vzorcích zjištěny rozdíly v naměřených údajích.Rozhodněte, zda existuje systematický rozdíl mezi oběma metodami (na hladině významnosti 0.05).


dx = c(1.2, -3.5, 0.5, 1.4, -0.8, 5.1, 6.8, 1.7, 0.9, -2.3)

library(s20x)
normcheck(dx)



# One sample t-test
t.test(dx,mu=0, alternative = "two.sided") 

# Robustni one sample t-test
library(rt.test)
rt.test(dx, alternative = "two.sided",mu = 0, test.stat = "TA", conf.level = 0.95)
# alternative = c("two.sided", "less", "greater")
# test.stat = c("TA", "TB"), based on the empirical distributions of the TA statistic (based on median and MAD) and the TBstatistic (based on Hodges-Lehmann and Shamos

# Bootstrap t-Test
library(MKinfer)
boot.t.test(dx, y = NULL,alternative = "two.sided", mu = 0, paired = FALSE, var.equal = FALSE,conf.level = 0.95, R = 9999, symmetric = FALSE)
# alternative = c("two.sided", "less", "greater")

library(Bolstad)
bayes.t.test(dx, y = NULL,alternative = "two.sided", mu = 0, paired = FALSE,var.equal = TRUE, conf.level = 0.95,prior = "jeffreys", m = NULL,n0 = NULL,sig.med = NULL, kappa = 1,sigmaPrior = "chisq",nIter = 10000, nBurn = 1000)
# alternative = c("two.sided", "less", "greater")
# prior = c("jeffreys", "joint.conj")

library(BSDA)
SIGN.test(dx, md = 0, alternative = "two.sided",conf.level = 0.95)

library(DescTools)
SignTest(dx,mu = 0, alternative = "two.sided",conf.level = 0.95)


# one sample Wilcoxon (Mann-Whitney) test
wilcox.test(dx, y,alternative = "two.sided", mu = 0, paired = FALSE, exact = FALSE, correct = TRUE,conf.int = FALSE, conf.level = 0.95)
# alternative = c("two.sided", "less", "greater")

library(exactRankTests)
wilcox.exact(dx, y, mu = 0,alternative = "two.sided",paired = FALSE, exact = FALSE,conf.int = TRUE, conf.level = 0.95)
# "two.sided"(default),"greater"or"less"

Výsledky měření téže konstanty dvěma metodami poskytly normálně rozdělené hodnoty výběrů (n1 = 25 a n2 = 31) se směrodatnými odchylkami s1 = 0.523 a s2 = 0.363. Lze na hladině významnosti 0.05 považovat obě metody za stejně přesné?


library(LearningStats)
diffvariance.test(sc1 = 0.523, sc2 = 0.363, n1 = 25, n2 = 31, alternative = "two.sided",alpha = 0.05, plot = TRUE)

diffvariance.CI(sc1 = 0.523, sc2 = 0.363, n1 = 25, n2 = 31, conf.level= 0.05)

Balicí automat zhotovuje balíčky o dané hmotnosti s maximální směrodatnou odchylkou 0.4 g. Ze zkušebního vzorku 10 balíčků byla vypočtena výběrová směrodatná odchylka 0.5 g. Rozhodněte (pro hladinu významnosti 5 %), zda nedošlo k poruše zařízení (nebyla překročena maximální směrodatná odchylka).


n = 10
sig = 0.4
ss = 0.5
library(LearningStats)
variance.test(x = NULL, s = NULL, sc = ss, smu = NULL, mu = NULL,
n = n, sigma02= sig^2, alternative = "greater", alpha = 0.05,
plot = TRUE, lwd = 1)

Hladiny olova v krvi 33 dětí rodičů, kteří pracovali v továrně na výrobu olova, a 33 kontrolních dětí z jejich okolí.


library(PairedData)
data(BloodLead)
xe = BloodLead[,2]
xc = BloodLead[,3]

library(PASWR2)
eda((xe-xc), trim = 0, dec = 3)

library(s20x)
normcheck((xe-xc))


library(PairedData)

boxplot(xc,xe)
plot(xc,xe,xlim=c(0,80),ylim=c(0,80))
abline(0,1)

summary(paired(xe, xc),tr=0.2)

effect.size(paired(xe, xc),tr=0.2)

slidingchart(paired(xe, xc))


# Cohen d (standardized mean difference)
mean(xe-xc)/sd(xe-xc)
library(lsr)
d = cohensD(xe, xc,method = "paired"); d
library(effsize)
cohen.d(xe, xc, paired = TRUE)

cor(xe, xc,method = "pearson")
cor(xe, xc,method = "spearman")


# t-test

t.test(xe, xc, paired = TRUE, alternative = "two.sided")
# t.test(elem ~ lom, data = data, paired = TRUE, alternative = "two.sided")

# Bootstrap t-Test
library(MKinfer)
boot.t.test(xe, xc, alternative = "two.sided",mu = 0, paired = TRUE, var.equal = FALSE, conf.level = 0.95, R = 9999, symmetric = FALSE)
# alternative = c("two.sided", "less", "greater")

library(CarletonStats)
bootPaired(xe, xc, conf.level = 0.95, B = 10000,plot.hist = TRUE, plot.qq = FALSE, legend.loc = "topright",x.name = deparse(substitute(x)), y.name = deparse(substitute(y)))

# Yuen's trimmed mean test
library(PairedData)
yuen.t.test(xe, xc, tr = 0.2, alternative = "two.sided", mu = 0, paired = TRUE, conf.level = 0.95)
# alternative = c("two.sided", "less", "greater")


# Chenuv paired sample t-test pro zesikmenou distribuci
library(EnvStats)
chenTTest(xe, xc , alternative = "greater", mu = 0, paired = TRUE, conf.level = 0.95, ci.method = "z")
# alternative = c("less", "greater")
# ci.method = "z", "t"

library(Bolstad)
bayes.t.test(xe, xc,alternative = "two.sided", mu = 0, paired = TRUE,var.equal = TRUE, conf.level = 0.95,prior = "jeffreys", m = NULL,n0 = NULL,sig.med = NULL, kappa = 1,sigmaPrior = "chisq",nIter = 10000, nBurn = 1000)
# alternative = c("two.sided", "less", "greater")
# prior = c("jeffreys", "joint.conj"),

## Wilcoxonuv parovy test
wilcox.test(xe, xc, paired = TRUE, alternative = "two.sided", conf.int = TRUE)

library(PairedData)
wilcox.test(paired(xe, xc))

## medianovy (znamenkovy) parovy test
library(EnvStats)
signTest(xe, xc, alternative = "two.sided", mu = 0, paired = TRUE, conf.level = 0.95)

# Permutation test for paired data
library(CarletonStats)
permTestPaired(xe, xc, B = 9999,alternative = "two.sided", plot.hist = TRUE,legend.loc = "topright", plot.qq = FALSE,x.name = deparse(substitute(x)), y.name = deparse(substitute(y)))


plot((xe+xc)/2, (xe-xc))

Stanovení koncentrace F3+ (v %) v přípravku “Ferrum citricum ammoniatum viride” se provádí titrací jodu (uvolněného oxidací KI železitými ionty) thiosíranem na škrobový maz. Titrace byla provedna u jedné části vzorků ihned a u druhé 30 minut po přidání KI. Líší se na hladině významnosti 0.05 výsledky obou postupů?


xih = c(13.29, 13.36, 13.32, 13.53, 13.56, 13.43, 13.30, 13.43)
x30 = c(13.86, 13.99, 13.88, 13.91, 13.89, 13.94, 13.80, 13.89)


fe3 = list(xih,x30)
names(fe3) = c("Fe hned", "Fe 30m")
library(reshape2)
fe = setNames(melt(fe3), c('koncentrace','metoda'))


library(lattice)
bwplot(koncentrace~metoda, data=fe)

hist(xih,xlim=c(13,14),col='skyblue',border=T)
hist(x30,add=T,col=scales::alpha('red',.5),border=T)


library(PASWR2)
eda((xih-x30), trim = 0, dec = 3)

library(s20x)
normcheck((xih-x30))


library(PairedData)

boxplot(xih,x30)
plot(xih,x30,xlim=c(13,14),ylim=c(13,14))
abline(0,1)

summary(paired(xih, x30),tr=0.2)

effect.size(paired(xih, x30),tr=0.2)

slidingchart(paired(xih, x30))


# Cohen d (standardized mean difference)
mean(xih-x30)/sd(xih-x30)
library(lsr)
d = cohensD(xih, x30,method = "paired"); d
library(effsize)
cohen.d(xih, x30, paired = TRUE)

cor(xih, x30,method = "pearson")
cor(xih, x30,method = "spearman")


# t-test

t.test(xih, x30, paired = TRUE, alternative = "two.sided")
# t.test(elem ~ lom, data = data, paired = TRUE, alternative = "two.sided")

# Bootstrap t-Test
library(MKinfer)
boot.t.test(xih, x30, alternative = "two.sided",mu = 0, paired = TRUE, var.equal = FALSE, conf.level = 0.95, R = 9999, symmetric = FALSE)
# alternative = c("two.sided", "less", "greater")

library(CarletonStats)
bootPaired(xih, x30, conf.level = 0.95, B = 10000,plot.hist = TRUE, plot.qq = FALSE, legend.loc = "topright",x.name = deparse(substitute(x)), y.name = deparse(substitute(y)))

# Yuen's trimmed mean test
library(PairedData)
yuen.t.test(xih, x30, tr = 0.2, alternative = "two.sided", mu = 0, paired = TRUE, conf.level = 0.95)
# alternative = c("two.sided", "less", "greater")


# Chenuv paired sample t-test pro zesikmenou distribuci
library(EnvStats)
chenTTest(xih, x30 , alternative = "greater", mu = 0, paired = TRUE, conf.level = 0.95, ci.method = "z")
# alternative = c("less", "greater")
# ci.method = "z", "t"

library(Bolstad)
bayes.t.test(xih, x30,alternative = "two.sided", mu = 0, paired = TRUE,var.equal = TRUE, conf.level = 0.95,prior = "jeffreys", m = NULL,n0 = NULL,sig.med = NULL, kappa = 1,sigmaPrior = "chisq",nIter = 10000, nBurn = 1000)
# alternative = c("two.sided", "less", "greater")
# prior = c("jeffreys", "joint.conj"),

## Wilcoxonuv parovy test
wilcox.test(xih, x30, paired = TRUE, alternative = "two.sided", conf.int = TRUE)

library(PairedData)
wilcox.test(paired(xih, x30))

## medianovy (znamenkovy) parovy test
library(EnvStats)
signTest(xih, x30, alternative = "two.sided", mu = 0, paired = TRUE, conf.level = 0.95)

# Permutation test for paired data
library(CarletonStats)
permTestPaired(xih, x30, B = 9999,alternative = "two.sided", plot.hist = TRUE,legend.loc = "topright", plot.qq = FALSE,x.name = deparse(substitute(x)), y.name = deparse(substitute(y)))


plot((xih+x30)/2, (xih-x30))

library(blandr)
bas2 = blandr.statistics (xih,x30, sig.level=0.95)

bas2$bias
bas2$biasUpperCI
bas2$biasLowerCI

bas2$regression.equation
cor(bas2$means,bas2$differences)^2 # R^2

blandr.plot.qq(bas2)

blandr.display.and.draw(method1=xih, method2=x30, plotter = "ggplot",method1name = "Ihned", method2name = "30 min.",plotTitle = "Bland-Altman plot for comparison of 2 methods",sig.level = 0.95, annotate = TRUE, ciDisplay = TRUE,ciShading = TRUE, normalLow = FALSE, normalHigh = FALSE,lowest_y_axis = FALSE, highest_y_axis = FALSE, point_size = 2)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNClVyxI1ldGUgYXJpdG1ldGlja8O9IHByxa9txJtyLCBtZWRpw6FuLCByb3pwdHlsIGEgc23Em3JvZGF0bm91IG9kY2h5bGt1IHNvdWJvcnUgMzQgbcSbxZllbsOtIMO6Ynl0a3UgYWxrYWxpY2vDqSByZXplcnZ5IHUgbWF0ZWsgcHJ2b3JvZGnEjWVrLg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KDQp4cHIgPSBjKDM4LjQsIDQxLjIsIDM5LjcsIDQ0LjEsIDMyLjQsIDQxLjIsIDUyLjEsIDM4LjEsIDQwLjUsIDQwLjksIDQzLjksIDQyLjksIDQxLjUsIDQ0LjgsIDM4LjYsIDQwLjcsIDM5LjYsIDM4LjgsIDM4LjgsIDQyLjUsIDM4LjUsIDM5LjcsIDM4LjgsIDMzLjYsIDQzLjgsIDQ4LjcsIDM5LjAsIDM2LjcsIDQwLjIsIDM4LjUsIDI3LjgsIDQ0LjYsIDM2LjcsIDM5LjkpDQoNCiMjIyBPdmVyZW5pIHByZWRwb2tsYWR1DQoNCiMjIE5lemF2aXNsb3N0DQoNCmxpYnJhcnkoczIweCkNCnRyZW5kc2NhdHRlcihjKDE6bGVuZ3RoKHhwcikpLCB5ID0geHByLCBmID0gMC41LCB4bGFiID0gIkluZGV4IiwgeWxhYiA9ICJabWVuYSBhbGssIHJlemVydnkiLCBtYWluID0gIiIpDQoNCmxpYnJhcnkoRGVzY1Rvb2xzKQ0KVm9uTmV1bWFublRlc3QoeHByLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLCB1bmJpYXNlZCA9IFRSVUUpDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQoNCmxpYnJhcnkoRGVzY1Rvb2xzKQ0KQmFydGVsc1JhbmtUZXN0KHhwciwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIiwgbWV0aG9kID0gIm5vcm1hbCIpDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgInRyZW5kIiwgIm9zY2lsbGF0aW9uIikNCiMgbWV0aG9kID0gYygibm9ybWFsIiwgImJldGEiLCAiYXV0byIpDQoNCmxpYnJhcnkobGl0dGVSKQ0KbWsgPSBtYW5uX2tlbmRhbGwoeHByLCB0eXBlID0gImJvdGgiKQ0KIyB0eXBlID0gYygiYm90aCIsICJpbmNyZWFzaW5nIiwgImRlY3JlYXNpbmciKQ0KcF92YWx1ZShtaykNCg0KbGlicmFyeShsYXdzdGF0KQ0KcnVucy50ZXN0KHhwcixwbG90Lml0ID0gVFJVRSxhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQ0KIyBhbHRlcm5hdGl2ZSA9IGMoInR3by5zaWRlZCIsICJwb3NpdGl2ZS5jb3JyZWxhdGVkIiwgIm5lZ2F0aXZlLmNvcnJlbGF0ZWQiKQ0KDQoNCiMjIE5vcm1hbGl0YQ0KDQojIEN1bGxlbiBGcmV5IHBsb3QNCmxpYnJhcnkoZml0ZGlzdHJwbHVzKQ0KZGVzY2Rpc3QoeHByLCBkaXNjcmV0ZT1GQUxTRSkNCmRlc2NkaXN0KHhwciwgZGlzY3JldGU9RkFMU0UsIGJvb3Q9OTk5KQ0KDQoNCmxpYnJhcnkoUEFTV1IyKQ0KZWRhKHhwciwgdHJpbSA9IDAsIGRlYyA9IDMpDQoNCmxpYnJhcnkoczIweCkNCm5vcm1jaGVjayh4cHIpDQoNCmxpYnJhcnkoVXNpbmdSKQ0Kc2ltcGxlLmVkYSh4cHIpDQoNCmxpYnJhcnkoU3RhdERBKQ0KZWRhcGxvdCh4cHIsSC5mcmVxPUZBTFNFLGJveD1UUlVFLEguYnJlYWtzPTMwLFMucGNoPTMsUy5jZXg9MC41LEQubHdkPTEuNSxQLmxvZz1GQUxTRSxQLm1haW49IiIsUC54bGFiPSJabWVuYSBhbGsuIHJlemVydnkiLCBQLnlsYWI9IkRlbnNpdHkiLEIucGNoPTMsQi5jZXg9MC41KQ0KDQoNCiMgU2hhcGlyby1GcmFuY2lhIHRlc3QNCmxpYnJhcnkobm9ydGVzdCkNCnNmLnRlc3QoeHByKQ0KDQojIFNoYXBpcm8tV2lsayB0ZXN0DQpzaGFwaXJvLnRlc3QoeHByKQ0KDQojIEFuZGVyc29uLURhcmxpbmcgdGVzdA0KbGlicmFyeShub3J0ZXN0KQ0KYWQudGVzdCh4cHIpDQoNCiMgQ3JhbWVyLXZvbiBNaXNlcyB0ZXN0DQpjdm0udGVzdCh4cHIpDQoNCiMgSmFycXVlIEJlcmEgdGVzdA0KbGlicmFyeSh0c2VyaWVzKQ0KamFycXVlLmJlcmEudGVzdCh4cHIpDQpsaWJyYXJ5KGxhd3N0YXQpDQpyamIudGVzdCh4cHIsIG9wdGlvbj0iSkIiLGNyaXQudmFsdWVzPSJlbXBpcmljYWwiLCBOID0gNTAwMCkgIyBrbGFzaWNreSBKLiBCLiB0ZXN0DQpyamIudGVzdCh4cHIsIG9wdGlvbj0iUkpCIixjcml0LnZhbHVlcz0iZW1waXJpY2FsIiwgTiA9IDUwMDApICMgcm9idXN0bmkgSi4gQi4gdGVzdA0KIyBjcml0LnZhbHVlcyA9IGMoImNoaXNxLmFwcHJveGltYXRpb24iLCAiZW1waXJpY2FsIikNCg0KIyBMaWxsaWVmb3JzIHRlc3QgKG1vZGlmLiBLb2xtb2dvcm92LVNtaXJub3YpDQpsaWJyYXJ5KG5vcnRlc3QpDQpsaWxsaWUudGVzdCh4cHIpDQoNCiMgc2ogdGVzdA0KbGlicmFyeShsYXdzdGF0KQ0Kc2oudGVzdCh4cHIsIGNyaXQudmFsdWVzID0gImVtcGlyaWNhbCIsIE4gPSAxMDAwKQ0KIyBjcml0LnZhbHVlcyA9IGMoInQuYXBwcm94aW1hdGlvbiIsICJlbXBpcmljYWwiKQ0KDQoNCiMjIG91dGxpZXJzDQoNCmJveHBsb3Quc3RhdHMoeHByLCBjb2VmID0gMS41LCBkby5jb25mID0gVFJVRSwgZG8ub3V0ID0gVFJVRSkNCmxpYnJhcnkodW5pdk91dGwpDQpib3hCKHhwciwgaz0xLjUsIG1ldGhvZD0icmVzaXN0YW50Iiwgd2VpZ2h0cz1OVUxMLCBpZD1OVUxMLCBleGNsdWRlPU5BLCBsb2d0PUZBTFNFKQ0KYm94Qih4cHIsIGs9MS41LCBtZXRob2Q9J2FzeW1tZXRyaWMnLCB3ZWlnaHRzPU5VTEwsIGlkPU5VTEwsZXhjbHVkZT1OQSwgbG9ndD1GQUxTRSkkb3V0bGllcnMNCmJveEIoeHByLCBrPTEuNSwgbWV0aG9kPSdhZGpib3gnLCB3ZWlnaHRzPU5VTEwsIGlkPU5VTEwsIGV4Y2x1ZGU9TkEsIGxvZ3Q9RkFMU0UpJG91dGxpZXJzDQoNCg0KIyBEQWdvc3RpbnV2IHRlc3Qgc2lrbW9zdGkNCmxpYnJhcnkobW9tZW50cykNCmFnb3N0aW5vLnRlc3QoeHByLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQ0KIyBhbHRlcm5hdGl2ZSA9IGMoInR3by5zaWRlZCIsICJsZXNzIiwgImdyZWF0ZXIiKQ0KDQpsaWJyYXJ5KG1vbWVudHMpDQptb21lbnRzOjpza2V3bmVzcyh4cHIpDQpsaWJyYXJ5KGUxMDcxKQ0KZTEwNzE6OnNrZXduZXNzKHhwciwgbmEucm0gPSBGQUxTRSwgdHlwZSA9IDMpDQpsaWJyYXJ5KGNvbmZpbnRyKQ0KY2lfc2tld25lc3MoeHByLHByb2JzID0gYygwLjAyNSwgMC45NzUpLHR5cGUgPSAiYm9vdHN0cmFwIiwgYm9vdF90eXBlID0gImJjYSIsIFIgPSA5OTk5LHNlZWQgPSBOVUxMKQ0KIyBib290X3R5cGUgPSBjKCJiY2EiLCAicGVyYyIsICJub3JtIiwgImJhc2ljIikNCg0KDQojIEFuc2NvbWJlLUdseW5udXYgdGVzdCBzcGljYXRvc3RpDQpsaWJyYXJ5KG1vbWVudHMpDQphbnNjb21iZS50ZXN0KHhwciwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikNCiMgYWx0ZXJuYXRpdmUgPSBjKCJ0d28uc2lkZWQiLCAibGVzcyIsICJncmVhdGVyIikNCg0KIyBHZWFyeSB0ZXN0IHNwaWNhdG9zdGkNCmxpYnJhcnkoZm1zYikNCmdlYXJ5LnRlc3QoeHByKQ0KDQpsaWJyYXJ5KG1vbWVudHMpDQprdXJ0b3Npcyh4cHIpIyBzcGljYXRvc3QNCmxpYnJhcnkoY29uZmludHIpDQpjaV9rdXJ0b3Npcyh4cHIscHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksdHlwZSA9ICJib290c3RyYXAiLCBib290X3R5cGUgPSAiYmNhIiwgUiA9IDk5OTksIHNlZWQgPSBOVUxMKQ0KIyBib290X3R5cGUgPSBjKCJiY2EiLCAicGVyYyIsICJub3JtIiwgImJhc2ljIikNCg0KDQojIEJveC1Db3gNCg0KbGlicmFyeShjYXIpDQpib3hDb3gobG0oeHByfjEpLCBsYW1iZGEgPSBzZXEoLTIsIDIsIDEvMTApLCBwbG90aXQgPSBUUlVFLCBpbnRlcnAgPSBUUlVFLCBlcHMgPSAxLzUwLCB4bGFiPU5VTEwsIHlsYWI9TlVMTCwgZmFtaWx5PSJiY1Bvd2VyIiwgcGFyYW09ICJsYW1iZGEiLCBnYW1tYT1OVUxMLGdyaWQ9VFJVRSkNCg0KbGlicmFyeShmb3JlY2FzdCkNCmxhbWJkYSA9IEJveENveC5sYW1iZGEoeHByLCBtZXRob2QgPSAibG9nbGlrIiwgbG93ZXIgPSAtMiwgdXBwZXIgPSAyKQ0KIyBtZXRob2QgPSBjKCJndWVycmVybyIsICJsb2dsaWsiKQ0KeGJjID0gQm94Q294KHhwciwgbGFtYmRhKQ0KeHJ0ID0gSW52Qm94Q294KHhiYywgbGFtYmRhLCBiaWFzYWRqID0gRkFMU0UsIGZ2YXIgPSBOVUxMKQ0KcGFyKG1mcm93PWMoMSwyKSkNCmhpc3QoeHByLCBtYWluPSIiKQ0KaGlzdCh4YmMsIG1haW49IiIseGxhYj0idHJhbnNmIHgiKQ0KcGFyKG1mcm93PWMoMSwxKSkNCmVyIDwtIHF0KDAuOTc1LGRmPWxlbmd0aCh4YmMpLTEpKnNkKHhiYykvc3FydChsZW5ndGgoeGJjKSkNCmxlZnQgPC0gbWVhbih4YmMpLWVyOyBsZWZ0DQpyaWdodCA8LSBtZWFuKHhiYykrZXI7IHJpZ2h0DQpJbnZCb3hDb3goYyhtZWFuKHhiYyksIGxlZnQsIHJpZ2h0KSwgbGFtYmRhLCBiaWFzYWRqID0gRkFMU0UsIGZ2YXIgPSBOVUxMKQ0KDQoNCiMjIyBNb21lbnRvdmUgb2RoYWR5DQoNCm1lYW4oeHByKQ0KbGlicmFyeShjb25maW50cikNCmNpX21lYW4oeHByLCAgcHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksdHlwZSA9ICJ0IikNCmNpX21lYW4oeHByLCAgcHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksdHlwZSA9ICJib290c3RyYXAiLCAgYm9vdF90eXBlID0gImJjYSIsIFIgPSA5OTk5LCBzZWVkID0gTlVMTCkNCiMgYm9vdF90eXBlID0gYygic3R1ZCIgKGRlZmF1bHQpLCAiYmNhIiwgInBlcmMiLCAibm9ybSIsICJiYXNpYyIpDQpsaWJyYXJ5KE1LaW5mZXIpDQptZWFuQ0koeHByLCBjb25mLmxldmVsID0gMC45NSwgYm9vdCA9IEZBTFNFLCBuYS5ybSA9IFRSVUUsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQptZWFuQ0koeHByLCBjb25mLmxldmVsID0gMC45NSwgYm9vdCA9IFRSVUUsIFIgPSA5OTk5LCBib290Y2kudHlwZSA9ICJhbGwiLG5hLnJtID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikNCiMgYWx0ZXJuYXRpdmUgPSBjKCJ0d28uc2lkZWQiLCAibGVzcyIsICJncmVhdGVyIikNCg0Kc2QoeCkNCmxpYnJhcnkoY29uZmludHIpDQpjaV9zZCh4cHIscHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksdHlwZSA9ICJjaGktc3F1YXJlZCIpDQpjaV9zZCh4cHIscHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksdHlwZSA9ICJib290c3RyYXAiLCBib290X3R5cGUgPSAiYmNhIixSID0gOTk5OSwgc2VlZCA9IE5VTEwpDQojIHR5cGUgPSBjKCJjaGktc3F1YXJlZCIsICJib290c3RyYXAiKSwNCiMgYm9vdF90eXBlID0gYygiYmNhIiwgInBlcmMiLCAic3R1ZCIsICJub3JtIiwgImJhc2ljIikNCmxpYnJhcnkoTUtpbmZlcikNCnNkQ0koeHByLCBjb25mLmxldmVsID0gMC45NSwgYm9vdCA9IEZBTFNFLG5hLnJtID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikNCnNkQ0koeHByLCBjb25mLmxldmVsID0gMC45NSwgYm9vdCA9IFRSVUUsIFIgPSA5OTk5LCBib290Y2kudHlwZSA9ICJhbGwiLG5hLnJtID0gVFJVRSwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikNCiMgYWx0ZXJuYXRpdmUgPSBjKCJ0d28uc2lkZWQiLCAibGVzcyIsICJncmVhdGVyIikNCg0KDQptZWFuKHhwcix0cmltPTAuMSkNCm1lYW4oeHByLHRyaW09MC4wNykNCmxpYnJhcnkoYXNiaW8pDQptZWFuKHRyaW0ubWUoeHByLCB0cmltID0gMC4wNykpDQpzZCh0cmltLm1lKHhwciwgdHJpbSA9IDAuMDcpKQ0KDQpsaWJyYXJ5KGNvbmZpbnRyKQ0KY2lfbWVhbih0cmltLm1lKHhwciwgdHJpbSA9IDAuMDcpLCAgcHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksdHlwZSA9ICJ0IikNCmNpX21lYW4odHJpbS5tZSh4cHIsIHRyaW0gPSAwLjA3KSwgIHByb2JzID0gYygwLjAyNSwgMC45NzUpLHR5cGUgPSAiYm9vdHN0cmFwIiwgIGJvb3RfdHlwZSA9ICJiY2EiLCBSID0gOTk5OSwgc2VlZCA9IE5VTEwpDQojIGJvb3RfdHlwZSA9IGMoInN0dWQiIChkZWZhdWx0KSwgImJjYSIsICJwZXJjIiwgIm5vcm0iLCAiYmFzaWMiKQ0KDQpsZW5ndGgoeHByKQ0KbGlicmFyeShhc2JpbykNCmxlbmd0aCh0cmltLm1lKHhwciwgdHJpbSA9IDAuMDcpKQ0KbGVuZ3RoKHRyaW0ubWUoeHByLCB0cmltID0gMC4xKSkNCmxlbmd0aCh0cmltLm1lKHhwciwgdHJpbSA9IDAuMikpDQoNCmxpYnJhcnkoYXNiaW8pDQp3aW4oeHByLGxhbWJkYSA9IDAuMDcpDQpsaWJyYXJ5KFdSUzIpDQp3aW5tZWFuKHhwciwgdHIgPSAwLjEsIG5hLnJtID0gRkFMU0UpDQp3aW5tZWFuKHhwciwgdHIgPSAwLjA3LCBuYS5ybSA9IEZBTFNFKQ0Kc3FydCh3aW52YXIoeHByLCB0ciA9IDAuMDcsIG5hLnJtID0gRkFMU0UsIFNUQU5EID0gTlVMTCkpDQoNCmxpYnJhcnkoY29uZmludHIpDQpjaV9tZWFuKHdpbih4cHIsbGFtYmRhID0gMC4wNyksICBwcm9icyA9IGMoMC4wMjUsIDAuOTc1KSx0eXBlID0gInQiKQ0KY2lfbWVhbih3aW4oeHByLGxhbWJkYSA9IDAuMDcpLCAgcHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksdHlwZSA9ICJib290c3RyYXAiLCAgYm9vdF90eXBlID0gImJjYSIsIFIgPSA5OTk5LCBzZWVkID0gTlVMTCkNCiMgYm9vdF90eXBlID0gYygic3R1ZCIgKGRlZmF1bHQpLCAiYmNhIiwgInBlcmMiLCAibm9ybSIsICJiYXNpYyIpDQoNCg0KIyMjIHJvYnVzdG5pIE0tb2RoYWR5IChIdWJlcikNCmxpYnJhcnkoTUFTUykNCmh1YiA9IGh1YmVyKHhwciwgayA9IDEuNSwgdG9sID0gMWUtMDYpDQpodWIkbXUNCmh1YiRzDQoNCg0KIyMjIEt2YW50aWxvdmUgb2RoYWR5DQoNCm1lZGlhbih4cHIpDQoNCmxpYnJhcnkoY29uZmludHIpDQpjaV9tZWRpYW4oeHByLHByb2JzID0gYygwLjAyNSwgMC45NzUpLHR5cGUgPSAiYm9vdHN0cmFwIiwgYm9vdF90eXBlID0gImJjYSIsIFIgPSA5OTk5LHNlZWQgPSBOVUxMKQ0KIyB0eXBlID0gYygiYmlub21pYWwiLCAiYm9vdHN0cmFwIikNCiMgYm9vdF90eXBlID0gYygiYmNhIiwgInBlcmMiLCAibm9ybSIsICJiYXNpYyIpDQpsaWJyYXJ5KE1LaW5mZXIpDQptZWRpYW5DSSh4cHIsIGNvbmYubGV2ZWwgPSAwLjk1LCBtZXRob2QgPSAiZXhhY3QiLFIgPSA5OTk5LCBib290Y2kudHlwZSA9ICJiY2EiLG1pbkxlbmd0aCA9IEZBTFNFLCBuYS5ybSA9IEZBTFNFLGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQojIG1ldGhvZCA9IGMoImV4YWN0IiwgImFzeW1wdG90aWMiKQ0KIyBib290Y2kudHlwZSA9IGMoIm5vcm0iLCAiYmFzaWMiLCAicGVyYyIsICJiY2EiKSwNCiMgYWx0ZXJuYXRpdmUgPSBjKCJ0d28uc2lkZWQiLCAibGVzcyIsICJncmVhdGVyIikNCg0KDQptYWQoeHByLCBjZW50ZXIgPSBtZWRpYW4oeCksIGNvbnN0YW50ID0gMS40ODI2LCBuYS5ybSA9IEZBTFNFKQ0KbGlicmFyeShyUUNDKQ0KbWFkLnVuYmlhc2VkICh4cHIsIGNlbnRlciA9IG1lZGlhbih4KSwgY29uc3RhbnQ9MS40ODI2LCBuYS5ybSA9IEZBTFNFKQ0KDQptYWQyLnVuYmlhc2VkKHhwciwgY2VudGVyID0gbWVkaWFuKHgpLCBjb25zdGFudD0xLjQ4MjYsIG5hLnJtID0gRkFMU0UpDQoNCmxpYnJhcnkoY29uZmludHIpDQpjaV9tYWQoeHByLHByb2JzID0gYygwLjAyNSwgMC45NzUpLGNvbnN0YW50ID0gMS40ODI2LHR5cGUgPSAiYm9vdHN0cmFwIiwgYm9vdF90eXBlID0gImJjYSIsUiA9IDk5OTksIHNlZWQgPSBOVUxMKQ0KIyAgYm9vdF90eXBlID0gYygiYmNhIiwgInBlcmMiLCAibm9ybSIsICJiYXNpYyIpDQpsaWJyYXJ5KE1LaW5mZXIpDQptYWRDSSh4cHIsIGNvbmYubGV2ZWwgPSAwLjk1LCBtZXRob2QgPSAiZXhhY3QiLCBtaW5MZW5ndGggPSBGQUxTRSxSID0gOTk5OSwgYm9vdGNpLnR5cGUgPSAiYmNhIixuYS5ybSA9IEZBTFNFLCBjb25zdGFudCA9IDEuNDgyNixhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQ0KIyBtZXRob2QgPSBjKCJleGFjdCIsICJhc3ltcHRvdGljIikNCiMgYm9vdGNpLnR5cGUgPSBjKCJub3JtIiwgImJhc2ljIiwgInBlcmMiLCAiYmNhIiksDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQoNCg0KDQojIyMgT2RoYWR5IG1ldG9kb3UgbWF4LiB2ZXJvaG9kbm9zdGkNCg0KbGlicmFyeShNQVNTKQ0KZml0ZGlzdHIoeHByLCBkZW5zZnVuPSJub3JtYWwiKQ0KZml0ZGlzdHIoeHByLCBkZW5zZnVuPSJ0IikNCmZpdGRpc3RyKHhwciwgZGVuc2Z1bj0iY2F1Y2h5IikNCg0KbGlicmFyeShicm9vbSkNCmJuID0gYnJvb206OmdsYW5jZShNQVNTOjpmaXRkaXN0cih4cHIsIm5vcm1hbCIpKQ0KYnQgPSBicm9vbTo6Z2xhbmNlKE1BU1M6OmZpdGRpc3RyKHhwciwidCIpKQ0KYmMgPSBicm9vbTo6Z2xhbmNlKE1BU1M6OmZpdGRpc3RyKHhwciwiY2F1Y2h5IikpDQpyYmluZChibixidCxiYykNCg0KbGlicmFyeShmaXRkaXN0cnBsdXMpDQpmaXRkaXN0KHhwcixkaXN0cj0ibm9ybSIsIG1ldGhvZCA9ICJtbGUiKQ0KIyBtZXRob2QgPSBjKCJtbGUiLCAibW1lIiwgInFtZSIsICJtZ2UiLCAibXNlIikNCg0KYGBgDQoNCi0tLQ0KdGl0bGU6ICJSIE5vdGVib29rIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KVXLEjWV0ZSBzdMWZZWRuw60gaG9kbm90dSAyNCBzdGFub3ZlbsOtIG3Em2RpICh2IHBwbSkgdiBjZWxvenJubsOpIG1vdWNlLg0KDQpgYGB7cn0NCg0KbGlicmFyeShNQVNTKQ0KZGF0YShjaGVtKQ0KeGNoID0gY2hlbQ0KDQoNCiMgQ3VsbGVuIEZyZXkgcGxvdA0KbGlicmFyeShmaXRkaXN0cnBsdXMpDQpkZXNjZGlzdCh4Y2gsIGRpc2NyZXRlPUZBTFNFKQ0KZGVzY2Rpc3QoeGNoLCBkaXNjcmV0ZT1GQUxTRSwgYm9vdD05OTkpDQoNCmxpYnJhcnkoUEFTV1IyKQ0KZWRhKHhjaCwgdHJpbSA9IDAuMDUsIGRlYyA9IDMpDQoNCmxpYnJhcnkoczIweCkNCm5vcm1jaGVjayh4Y2gpDQoNCmxpYnJhcnkoVXNpbmdSKQ0Kc2ltcGxlLmVkYSh4Y2gpDQoNCmxpYnJhcnkoU3RhdERBKQ0KZWRhcGxvdCh4Y2gsSC5mcmVxPUZBTFNFLGJveD1UUlVFLEguYnJlYWtzPTMwLFMucGNoPTMsUy5jZXg9MC41LEQubHdkPTEuNSxQLmxvZz1GQUxTRSxQLm1haW49IiIsUC54bGFiPSJDdSBbcHBtXSIsUC55bGFiPSJEZW5zaXR5IixCLnBjaD0zLEIuY2V4PTAuNSkNCg0KDQoNCmJveHBsb3Quc3RhdHMoeGNoLCBjb2VmID0gMS41LCBkby5jb25mID0gVFJVRSwgZG8ub3V0ID0gVFJVRSkNCmxpYnJhcnkodW5pdk91dGwpDQpib3hCKHhjaCwgaz0xLjUsIG1ldGhvZD0icmVzaXN0YW50Iiwgd2VpZ2h0cz1OVUxMLCBpZD1OVUxMLCBleGNsdWRlPU5BLCBsb2d0PUZBTFNFKQ0KYm94Qih4Y2gsIGs9MS41LCBtZXRob2Q9J2FzeW1tZXRyaWMnLCB3ZWlnaHRzPU5VTEwsIGlkPU5VTEwsZXhjbHVkZT1OQSwgbG9ndD1GQUxTRSkkb3V0bGllcnMNCmJveEIoeGNoLCBrPTEuNSwgbWV0aG9kPSdhZGpib3gnLCB3ZWlnaHRzPU5VTEwsIGlkPU5VTEwsIGV4Y2x1ZGU9TkEsIGxvZ3Q9RkFMU0UpJG91dGxpZXJzDQoNCmxpYnJhcnkoRW52U3RhdHMpDQpyb3NuZXJUZXN0KHhjaCwgayA9IDIsIGFscGhhID0gMC4wNSwgd2FybiA9IFRSVUUpDQoNCmxpYnJhcnkob3V0bGllcnMpDQpncnViYnMudGVzdCh4Y2gsIHR5cGU9MjAsIG9wcG9zaXRlPUZBTFNFLCB0d28uc2lkZWQ9VFJVRSkNCg0KDQpsaWJyYXJ5KGV4dHJlbWV2YWx1ZXMpDQpnZXRPdXRsaWVycyh4Y2gsbWV0aG9kPSJJIixkaXN0cmlidXRpb249Im5vcm1hbCIpDQpnZXRPdXRsaWVycyh4Y2gsbWV0aG9kPSJJSSIsZGlzdHJpYnV0aW9uPSJub3JtYWwiKQ0KTCA8LSBnZXRPdXRsaWVycyh4Y2gsbWV0aG9kPSJJSSIsZGlzdHJpYnV0aW9uPSJub3JtYWwiKQ0Kb3V0bGllclBsb3QoeGNoLEwsbW9kZT0icXEiKQ0Kb3V0bGllclBsb3QoeGNoLEwsbW9kZT0icmVzaWR1YWwiKQ0KDQpsaWJyYXJ5KE91dGxpZXJEZXRlY3Rpb24pDQpVbml2YXJpYXRlT3V0bGllckRldGVjdGlvbih4Y2gsIGsgPSAwLjA1ICogbGVuZ3RoKHhjaCksIGN1dG9mZiA9IDAuOTUsIGRpc3QgPSBGQUxTRSwgZGVucyA9IEZBTFNFLCBkZXB0aCA9IEZBTFNFLCBNZXRob2QgPSAiZXVjbGlkZWFuIiwgcm5hbWVzID0gRkFMU0UpDQoNCg0KbWVhbih4Y2gpDQptZWRpYW4oeGNoKQ0Kc2QoeGNoLCBuYS5ybT1UUlVFKQ0KDQoNCm1lYW4oeGNoLHRyaW09MC4xKQ0KbWVhbih4Y2gsdHJpbT0wLjA1KQ0KbGlicmFyeShhc2JpbykNCm1lYW4odHJpbS5tZSh4Y2gsIHRyaW0gPSAwLjA1KSkNCnNkKHRyaW0ubWUoeGNoLCB0cmltID0gMC4wNSkpDQoNCmxlbmd0aCh4Y2gpDQpsaWJyYXJ5KGFzYmlvKQ0KbGVuZ3RoKHRyaW0ubWUoeGNoLCB0cmltID0gMC4wNSkpDQpsZW5ndGgodHJpbS5tZSh4Y2gsIHRyaW0gPSAwLjEpKQ0KDQpsaWJyYXJ5KFdSUzIpDQp3aW5tZWFuKHhjaCwgdHIgPSAwLjEsIG5hLnJtID0gRkFMU0UpDQp3aW5tZWFuKHhjaCwgdHIgPSAwLjA1LCBuYS5ybSA9IEZBTFNFKQ0Kc3FydCh3aW52YXIoeCwgdHIgPSAwLjIsIG5hLnJtID0gRkFMU0UsIFNUQU5EID0gTlVMTCkpDQoNCiMjIyByb2J1c3RuaSBNLW9kaGFkeSAoSHViZXIpDQpsaWJyYXJ5KE1BU1MpDQpodWIgPSBodWJlcih4Y2gsIGsgPSAxLjUsIHRvbCA9IDFlLTA2KQ0KaHViJG11DQpodWIkcw0KDQoNCmBgYA0KDQoNClByxa9txJtybsOhIGtvbmNlbnRyYWNlIHogOCBzdGFub3ZlbsOtIGlvbnTFryBOYSsgdiByb3p0b2t1IGJ5bGEgMC41NDcgbW9sL2wgc2Ugc23Em3JvZGF0bm91IG9kY2h5bGtvdSAwLjAwMyBtb2wvbC4gVXLEjWV0ZSBpbnRlcnZhbHkgc3BvbGVobGl2b3N0aSBwcm8gcHLFr23Em3IsIHNtxJtyb2RhdG5vdSBvZGNoeWxrdSBhIHJvenB0eWwgcHJvIGhsYWRpbnUgdsO9em5hbW5vc3RpIDAuMDUuDQoNCmBgYHtyfQ0KDQptID0gMC41NDcNCnMgPSAwLjAwMw0KczIgPSBzXjI7IHMyDQpuID0gNQ0KDQptICsgYygtcyxzKSpxdCgwLjk1LGRmPW4tMSkvc3FydChuKQ0KbGlicmFyeShMZWFybmluZ1N0YXRzKQ0KTWVhbi5DSShtLCBzaWdtYSA9IE5VTEwsIHNjID0gTlVMTCwgcyA9IHMsIG4gPSBuLCBjb25mLmxldmVsPSAwLjk1KQ0KDQpzKnNxcnQoKG4tMSkvcWNoaXNxKGMoMC45NzUsMC4wMjUpLGRmPW4tMSkpDQpsaWJyYXJ5KExlYXJuaW5nU3RhdHMpDQp2YXJpYW5jZS5DSSh4ID0gTlVMTCwgcyA9IHMsIHNjID0gTlVMTCwgc211ID0gTlVMTCwgbXUgPSBOVUxMLCBuID0gbiwgY29uZi5sZXZlbD0gMC45NSkNCg0KYGBgDQoNCg0KQnlsIG3Em8WZZW4gb2JzYWggY8OtbnUgKHYgJSkgdmUgMTAwIHZ6b3Jjw61jaCBydWR5LiBWw71zbGVka3kgYnlseSB6YXpuYW1lbsOhbnkgZm9ybW91IMSNZXRub3N0bsOtIHRhYnVsa3kuIFVyxI1ldGUgcHLFr23Em3Jub3UgaG9kbm90dSBhIHJvenB0eWwuDQoNCmBgYHtyfQ0KDQp4eCA9IGMoMzAsIDM1LCA0MCwgNDUsIDUwLCA1NSwgNjAsIDY1LCA3MCwgNzUsIDgwKQ0KZnggPSBjKDQsIDYsIDgsIDE1LCAyNSwgMjAsIDgsIDcsIDUsIDIpDQpOID0gc3VtKGZ4KQ0Kd3QgPC0gZngvTg0KDQp4eDEgPSB4eFstMV0NCnh4MiA9IHh4Wy1sZW5ndGgoeHgpXQ0KeHhtID0gKHh4Mit4eDEpLzINCg0KYmFycGxvdCh3dCwgbmFtZXMuYXJnID0geHhtLHhsYWIgPSAiU24gKCUpIikNCg0KZGVuc2l0eT13dC9kaWZmKHh4KQ0KcGxvdCh4eG0sZGVuc2l0eSx0eXBlID0gImgiLGx3ZD04LGNvbD00LHhsYWIgPSAiU24gKCUpIikNCmFibGluZShoPTApDQp4cyA9IHNlcSh4eG1bMV0seHhtW2xlbmd0aCh4eG0pXSwwLjAxKQ0KZHhzID0gZG5vcm0oeHMsbWVhbj01MyxzZD0xMCkNCnBvaW50cyh4cyxkeHMsdHlwZT0ibCIsY29sID0gInJlZCIsIGx3ZCA9IDIpDQoNCg0Kd20gPSBzdW0oeHhtKmZ4KS9OOyB3bQ0Kd2VpZ2h0ZWQubWVhbih4eG0sIHd0LCBuYS5ybSA9IFRSVUUpDQpsaWJyYXJ5KEhtaXNjKQ0Kd3RkLm1lYW4oeHhtLCB3ZWlnaHRzPXd0LCBub3Jtd3Q9RkFMU0UsIG5hLnJtPVRSVUUpDQoNCmxpYnJhcnkobW9kaSkNCndzMiA9IHdlaWdodGVkLnZhcih4eG0sIHd0LCBuYS5ybSA9IFRSVUUpOyB3czINCndzID0gc3FydCh3czIpOyB3cw0KbGlicmFyeShIbWlzYykNCnd0ZC52YXIoeHhtLCB3ZWlnaHRzPXd0LCBub3Jtd3Q9RkFMU0UsIG5hLnJtPVRSVUUsbWV0aG9kPSdNTCcpDQojIG1ldGhvZD1jKCd1bmJpYXNlZCcsICdNTCcpDQpzcXJ0KHd0ZC52YXIoeHhtLCB3ZWlnaHRzPXd0LCBub3Jtd3Q9RkFMU0UsIG5hLnJtPVRSVUUsbWV0aG9kPSdNTCcpKQ0KDQp3bSArIGMoLXMscykqcXQoMC45NSxkZj1OLTEpL3NxcnQoTikNCmxpYnJhcnkoTGVhcm5pbmdTdGF0cykNCk1lYW4uQ0kod20sIHNpZ21hID0gTlVMTCwgc2MgPSBOVUxMLCBzID0gcywgbiA9IE4sIGNvbmYubGV2ZWw9IDAuOTUpDQoNCndzKnNxcnQoKE4tMSkvcWNoaXNxKGMoMC45NzUsMC4wMjUpLGRmPU4tMSkpDQpsaWJyYXJ5KExlYXJuaW5nU3RhdHMpDQp2YXJpYW5jZS5DSSh4ID0gTlVMTCwgcyA9IHdzLCBzYyA9IE5VTEwsIHNtdSA9IE5VTEwsIG11ID0gTlVMTCwgbiA9IE4sIGNvbmYubGV2ZWw9IDAuOTUpDQoNCg0KbGlicmFyeShzbikNCmZpdGRpc3RyLmdyb3VwZWQoYnJlYWtzPXh4LCBjb3VudHM9ZngsIGZhbWlseT0ibm9ybWFsIiwgdHJhY2UgPSBGQUxTRSwgd3BhciA9IE5VTEwpDQoNCmBgYA0KDQoNCk1ldG9kb3UgRURYUkYgYnlseSBzdGFub3ZlbnkgcHJ2a3kgdiBrZXJhbWlja8OpIG1hc2UgYSBnbGF6dcWZZSBrZXJhbWlreSB6IGxva2FsaXQgTG9uZ3F1YW4gYSBKaW5nZGV6aGVuLiBLZSB6a291bcOhbsOtIHN1cm92aW4gYSB0ZWNobm9sb2dpZSB2w71wYWx1IGJ5bG8gdnlicsOhbm8gY2Vsa2VtIMSNdHnFmWljZXQgdHlwaWNrw71jaCBzdMWZZXDFrw0KKGh0dHBzOi8vYXJjaGl2ZS5pY3MudWNpLmVkdS9tbC9kYXRhc2V0cy9DaGVtaWNhbCtDb21wb3NpdGlvbitvZitDZXJhbWljK1NhbXBsZXMpDQoNCmBgYHtyfQ0KZGF0YSA8LSByZWFkLmNzdigiaHR0cHM6Ly9hcmNoaXZlLmljcy51Y2kuZWR1L21sL21hY2hpbmUtbGVhcm5pbmctZGF0YWJhc2VzLzAwNTgzL0NoZW1pY2FsIENvbXBvc2lvbiBvZiBDZXJhbWljLmNzdiIpDQpoZWFkKGRhdGEpDQpzcyA8LSBmdW5jdGlvbihYKXtzdWJzdHIoWCwgc3RhcnQ9MSwgc3RvcD0yKX0NCnNuYW0gPC0gc3MoZGF0YVssMV0pDQpzbmFtDQoNCk1NID0gYXMuZGF0YS5mcmFtZShjYmluZChzbmFtLGRhdGFbLCJQYXJ0Il0sZGF0YVsiTW5PIl0pKQ0KY29sbmFtZXMoTU0pID0gYygiU2l0ZSIsIlBhcnQiLCJNbk8iKQ0KDQptbm8gPSBNTVssIk1uTyJdDQpwYXJ0ID0gYXMuZmFjdG9yKE1NWywiUGFydCJdKQ0Kc2l0ZSA9IGFzLmZhY3RvcihNTVssIlNpdGUiXSkNCmFnZ3JlZ2F0ZShtbm8sbGlzdChzaXRlLHBhcnQpLCBGVU49bWVhbikNCmFnZ3JlZ2F0ZShtbm8sbGlzdChzaXRlLHBhcnQpLCBGVU49bWVkaWFuKQ0KYWdncmVnYXRlKG1ubyxsaXN0KHNpdGUscGFydCksIEZVTj1sZW5ndGgpDQphZ2dyZWdhdGUobW5vLGxpc3Qoc2l0ZSxwYXJ0KSwgRlVOPWZ1bmN0aW9uKHgpe3NkKHgpL21lYW4oeCl9KQ0KDQoNCiMjIyBEaXN0cmlidWNlIE1uTyB2IGtlcmFtaWNlIGplZG7DqSB6IGxva2FsaXQuDQoNCm1tID0gTU1bd2hpY2goTU0kU2l0ZT09IkRZIiksXQ0KbW5vID0gbW1bLCJNbk8iXQ0KDQojIyBOb3JtYWxpdGENCg0KIyBDdWxsZW4gRnJleSBwbG90DQpsaWJyYXJ5KGZpdGRpc3RycGx1cykNCmRlc2NkaXN0KG1ubywgZGlzY3JldGU9RkFMU0UpDQpkZXNjZGlzdChtbm8sIGRpc2NyZXRlPUZBTFNFLCBib290PTk5OSkNCmRlc2NkaXN0KGxvZyhtbm8pLCBkaXNjcmV0ZT1GQUxTRSwgYm9vdD05OTkpDQoNCmxpYnJhcnkoUEFTV1IyKQ0KZWRhKG1ubywgdHJpbSA9IDAsIGRlYyA9IDMpDQplZGEobG9nKG1ubyksIHRyaW0gPSAwLCBkZWMgPSAzKQ0KDQpsaWJyYXJ5KHMyMHgpDQpub3JtY2hlY2sobW5vKQ0Kbm9ybWNoZWNrKGxvZyhtbm8pKQ0KDQpsaWJyYXJ5KFVzaW5nUikNCnNpbXBsZS5lZGEobW5vKQ0Kc2ltcGxlLmVkYShsb2cobW5vKSkNCg0KbGlicmFyeShTdGF0REEpDQplZGFwbG90KG1ubyxILmZyZXE9RkFMU0UsYm94PVRSVUUsSC5icmVha3M9MzAsUy5wY2g9MyxTLmNleD0wLjUsRC5sd2Q9MS41LFAubG9nPUZBTFNFLFAubWFpbj0iIixQLnhsYWI9IlptZW5hIGFsay4gcmV6ZXJ2eSIsIFAueWxhYj0iRGVuc2l0eSIsQi5wY2g9MyxCLmNleD0wLjUpDQoNCmVkYXBsb3QobW5vLEguZnJlcT1GQUxTRSxib3g9VFJVRSxILmJyZWFrcz0zMCxTLnBjaD0zLFMuY2V4PTAuNSxELmx3ZD0xLjUsUC5sb2c9VFJVRSxQLm1haW49IiIsUC54bGFiPSJabWVuYSBhbGsuIHJlemVydnkiLCBQLnlsYWI9IkRlbnNpdHkiLEIucGNoPTMsQi5jZXg9MC41KQ0KDQoNCmxpYnJhcnkoY3dobWlzYykgICMgIFQzIHBsb3QgKEdob3NoKQ0KVDNwbG90KG1ubyxsYWI9cGFzdGUoIlQzIHBsb3Qgb2YgIixkZXBhcnNlKHN1YnN0aXR1dGUoeCkpKSwgbGVnZW5kLnBvcz0iYm90dG9tIiwgY2V4PTAuNikNClQzcGxvdChsb2cobW5vKSxsYWI9cGFzdGUoIlQzIHBsb3Qgb2YgIixkZXBhcnNlKHN1YnN0aXR1dGUoeCkpKSwgbGVnZW5kLnBvcz0iYm90dG9tIiwgY2V4PTAuNikNCg0KDQojIEJveC1Db3gNCg0KbGlicmFyeShjYXIpDQpib3hDb3gobG0obW5vfjEpLCBsYW1iZGEgPSBzZXEoLTIsIDIsIDEvMTApLCBwbG90aXQgPSBUUlVFLCBpbnRlcnAgPSBUUlVFLCBlcHMgPSAxLzUwLCB4bGFiPU5VTEwsIHlsYWI9TlVMTCwgZmFtaWx5PSJiY1Bvd2VyIiwgcGFyYW09ICJsYW1iZGEiLCBnYW1tYT1OVUxMLGdyaWQ9VFJVRSkNCg0KbGlicmFyeShmb3JlY2FzdCkNCmxhbWJkYSA9IEJveENveC5sYW1iZGEobW5vLCBtZXRob2QgPSAibG9nbGlrIiwgbG93ZXIgPSAtMiwgdXBwZXIgPSAyKQ0KIyBtZXRob2QgPSBjKCJndWVycmVybyIsICJsb2dsaWsiKQ0KeGJjID0gQm94Q294KG1ubywgbGFtYmRhKQ0KeHJ0ID0gSW52Qm94Q294KHhiYywgbGFtYmRhLCBiaWFzYWRqID0gRkFMU0UsIGZ2YXIgPSBOVUxMKQ0KcGFyKG1mcm93PWMoMSwyKSkNCmhpc3QobW5vLCBtYWluPSIiKQ0KaGlzdCh4YmMsIG1haW49IiIseGxhYj0idHJhbnNmIHgiKQ0KcGFyKG1mcm93PWMoMSwxKSkNCmVyIDwtIHF0KDAuOTc1LGRmPWxlbmd0aCh4YmMpLTEpKnNkKHhiYykvc3FydChsZW5ndGgoeGJjKSkNCmxlZnQgPC0gbWVhbih4YmMpLWVyOyBsZWZ0DQpyaWdodCA8LSBtZWFuKHhiYykrZXI7IHJpZ2h0DQpJbnZCb3hDb3goYyhtZWFuKHhiYyksIGxlZnQsIHJpZ2h0KSwgbGFtYmRhLCBiaWFzYWRqID0gRkFMU0UsIGZ2YXIgPSBOVUxMKQ0KDQoNCiMjIEJoYXR0YWNoYXJ5YSBwbG90IHMgQVNIDQpsaWJyYXJ5KGFzaCkgDQpubj0zMA0KZiA8LSBhc2gxKGJpbjEobW5vLG5iaW49bm4pLDUpICMgYXNoIGVzdGltYXRlDQpuazwtbGVuZ3RoKGYkeSktMQ0KeWs8LXJlcCgwLG5rKQ0KeGs8LXJlcCgwLG5rKQ0KZm9yKGkgaW4gMTpuayl7DQogIHlrW2ldPC1sb2coZiR5W2krMV0vZiR5W2ldKQ0KICB4a1tpXTwtKGYkeFtpKzFdK2YkeFtpXSkvMg0KfQ0KcGxvdCh4ayx5aywgdHlwZT0ibCIsY29sPTEsbHR5PTEsIG1haW49IiIsIHhsYWI9IngiLHlsYWI9ImxuKCBmKGkrMSkgLyBmKGkpICkiKQ0KcnVnKG1ubykNCg0KDQojIEhhcnRpZ2FuIGRpcCB0ZXN0DQpsaWJyYXJ5KGRpcHRlc3QpDQpkdGIgPSBkaXAobW5vLCBmdWxsLnJlc3VsdCA9IFRSVUUsIG1pbi5pcy4wID0gVFJVRSwgZGVidWcgPSBGQUxTRSk7IGR0Yg0KZGlwLnRlc3QobW5vLCBzaW11bGF0ZS5wLnZhbHVlID0gRkFMU0UsIEIgPSAyMDAwKQ0KcGxvdChkdGIpDQoNCg0KIyBTaWx2ZXJtYW51diB0ZXN0DQpsaWJyYXJ5KHNpbHZlcm1hbnRlc3QpIA0KIyBodHRwczovL3d3dy5tYXRoZW1hdGlrLnVuaS1tYXJidXJnLmRlL35zdG9jaGFzdGlrL1JfcGFja2FnZXMvDQpzaWx2ZXJtYW4udGVzdChtbm8sIGs9MSwgTSA9IDk5OSwgYWRqdXN0ID0gRkFMU0UsIGRpZ2l0cyA9IDYpDQpzaWx2ZXJtYW4udGVzdChtbm8sIGs9MiwgTSA9IDk5OSwgYWRqdXN0ID0gRkFMU0UsIGRpZ2l0cyA9IDYpDQpzaWx2ZXJtYW4udGVzdChtbm8sIGs9MywgTSA9IDk5OSwgYWRqdXN0ID0gRkFMU0UsIGRpZ2l0cyA9IDYpDQpzaWx2ZXJtYW4ucGxvdChtbm8sIGttaW49MSwga21heD0zLCBhbHBoYT0wLjA1LCBhZGp1c3Q9RkFMU0UpDQoNCg0KIyBBbWVpamVpcmFzLUFsb25zbyBleGNlc3MgbWFzcyB0ZXN0DQpsaWJyYXJ5KG11bHRpbW9kZSkNCm1vZGV0ZXN0KG1ubyxtb2QwPTEsbWV0aG9kPSJBQ1IiLEI9NTAwLGxvd3N1cD0tSW5mLHVwcHN1cD1JbmYsc3VibWV0aG9kPU5VTEwsbj1OVUxMLHRvbD1OVUxMLHRvbDI9TlVMTCxncmlkc2l6ZT1OVUxMLGFscGhhPU5VTEwsbk1DPU5VTEwsQk1DPU5VTEwpDQoNCg0KIyBtZXRvZGEgbWF4IHZlcm9ob2Rub3N0aQ0KbGlicmFyeShtY2x1c3QpDQp4czwtIHNvcnQobW5vKQ0KZG1jIDwtIE1jbHVzdCh4cyxHPU5VTEwpDQpkbWNCSUMgPC0gbWNsdXN0QklDKHgpOyBkbWNCSUMNCm5uID0gMg0KZG1jIDwtIE1jbHVzdCh4cyxHPW5uKQ0KZG1jeiA8LXJvdW5kKGRtYyR6LG5uKTsgYXMuZGF0YS5mcmFtZShjYmluZChtbVssMl0sZG1jeikpDQoNCmBgYA0KDQoNCkJ5bCB6amnFocWlb3bDoW4gb2JzYWggdHVrdSAodiAlKSB2IG1sw6ljZSBvZCAxNiBvdmPDrS4gVXLEjWV0ZSB2aG9kbm91IHN0xZllZG7DrSBob2Rub3R1IHR1xI1ub3N0aSBtbMOpa2EuDQoNCmBgYHtyfQ0KDQp4bW8gPSBjKDQuMDgsIDMuOTEsIDQuMDIsIDQuMjYsIDQuMDMsIDMuOTQsIDMuODIsIDMuNzIsIDQuMDMsIDMuODcsIDQuMDksIDMuOTIsIDQuMTgsIDMuOTMsIDMuODEsIDMuNzEpDQoNCg0KIyMjIE92ZXJlbmkgcHJlZHBva2xhZHUNCg0KIyMgTmV6YXZpc2xvc3QNCg0KbGlicmFyeShzMjB4KQ0KdHJlbmRzY2F0dGVyKGMoMTpsZW5ndGgoeG1vKSksIHkgPSB4bW8sIGYgPSAwLjUsIHhsYWIgPSAiSW5kZXgiLCB5bGFiID0gIk9ic2FoIHR1a3UgKCUpIiwgbWFpbiA9ICIiKQ0KDQpsaWJyYXJ5KERlc2NUb29scykNClZvbk5ldW1hbm5UZXN0KHhtbywgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIiwgdW5iaWFzZWQgPSBUUlVFKQ0KIyBhbHRlcm5hdGl2ZSA9IGMoInR3by5zaWRlZCIsICJsZXNzIiwgImdyZWF0ZXIiKQ0KDQpsaWJyYXJ5KERlc2NUb29scykNCkJhcnRlbHNSYW5rVGVzdCh4bW8sIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsIG1ldGhvZCA9ICJub3JtYWwiKQ0KIyBhbHRlcm5hdGl2ZSA9IGMoInR3by5zaWRlZCIsICJ0cmVuZCIsICJvc2NpbGxhdGlvbiIpDQojIG1ldGhvZCA9IGMoIm5vcm1hbCIsICJiZXRhIiwgImF1dG8iKQ0KDQpsaWJyYXJ5KGxpdHRlUikNCm1rID0gbWFubl9rZW5kYWxsKHhtbywgdHlwZSA9ICJib3RoIikNCiMgdHlwZSA9IGMoImJvdGgiLCAiaW5jcmVhc2luZyIsICJkZWNyZWFzaW5nIikNCnBfdmFsdWUobWspDQoNCg0KIyMgTm9ybWFsaXRhDQoNCiMgQ3VsbGVuIEZyZXkgcGxvdA0KbGlicmFyeShmaXRkaXN0cnBsdXMpDQpkZXNjZGlzdCh4bW8sIGRpc2NyZXRlPUZBTFNFKQ0KZGVzY2Rpc3QoeG1vLCBkaXNjcmV0ZT1GQUxTRSwgYm9vdD05OTkpDQoNCmxpYnJhcnkoUEFTV1IyKQ0KZWRhKHhtbywgdHJpbSA9IDAsIGRlYyA9IDMpDQoNCmxpYnJhcnkoczIweCkNCm5vcm1jaGVjayh4bW8pDQoNCmxpYnJhcnkoVXNpbmdSKQ0Kc2ltcGxlLmVkYSh4bW8pDQoNCmxpYnJhcnkoU3RhdERBKQ0KZWRhcGxvdCh4bW8sSC5mcmVxPUZBTFNFLGJveD1UUlVFLEguYnJlYWtzPTMwLFMucGNoPTMsUy5jZXg9MC41LEQubHdkPTEuNSxQLmxvZz1GQUxTRSxQLm1haW49IiIsUC54bGFiPSJabWVuYSBhbGsuIHJlemVydnkiLCBQLnlsYWI9IkRlbnNpdHkiLEIucGNoPTMsQi5jZXg9MC41KQ0KDQpsaWJyYXJ5KGN3aG1pc2MpICAjICBUMyBwbG90IChHaG9zaCkNClQzcGxvdCh4bW8sbGFiPXBhc3RlKCJUMyBwbG90IG9mICIsZGVwYXJzZShzdWJzdGl0dXRlKHgpKSksIGxlZ2VuZC5wb3M9ImJvdHRvbSIsIGNleD0wLjYpDQoNCg0KbGlicmFyeShtb21lbnRzKQ0KbW9tZW50czo6c2tld25lc3MoeG1vKQ0KbGlicmFyeShlMTA3MSkNCmUxMDcxOjpza2V3bmVzcyh4bW8sIG5hLnJtID0gRkFMU0UsIHR5cGUgPSAzKQ0KbGlicmFyeShjb25maW50cikNCmNpX3NrZXduZXNzKHhtbyxwcm9icyA9IGMoMC4wMjUsIDAuOTc1KSx0eXBlID0gImJvb3RzdHJhcCIsIGJvb3RfdHlwZSA9ICJiY2EiLCBSID0gOTk5OSxzZWVkID0gTlVMTCkNCiMgYm9vdF90eXBlID0gYygiYmNhIiwgInBlcmMiLCAibm9ybSIsICJiYXNpYyIpDQoNCiMgREFnb3N0aW51diB0ZXN0IHNpa21vc3RpDQpsaWJyYXJ5KG1vbWVudHMpDQphZ29zdGluby50ZXN0KHhtbywgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikNCiMgYWx0ZXJuYXRpdmUgPSBjKCJ0d28uc2lkZWQiLCAibGVzcyIsICJncmVhdGVyIikNCg0KDQpsaWJyYXJ5KG1vbWVudHMpDQprdXJ0b3Npcyh4bW8pIyBzcGljYXRvc3QNCmxpYnJhcnkoY29uZmludHIpDQpjaV9rdXJ0b3Npcyh4bW8scHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksdHlwZSA9ICJib290c3RyYXAiLCBib290X3R5cGUgPSAiYmNhIiwgUiA9IDk5OTksIHNlZWQgPSBOVUxMKQ0KIyBib290X3R5cGUgPSBjKCJiY2EiLCAicGVyYyIsICJub3JtIiwgImJhc2ljIikNCg0KIyBBbnNjb21iZS1HbHlubnV2IHRlc3Qgc3BpY2F0b3N0aQ0KbGlicmFyeShtb21lbnRzKQ0KYW5zY29tYmUudGVzdCh4bW8sIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQoNCiMgR2VhcnkgdGVzdCBzcGljYXRvc3RpDQpsaWJyYXJ5KGZtc2IpDQpnZWFyeS50ZXN0KHhtbykNCg0KDQojIFNoYXBpcm8tRnJhbmNpYSB0ZXN0DQpsaWJyYXJ5KG5vcnRlc3QpDQpzZi50ZXN0KHhtbykNCg0KIyBTaGFwaXJvLVdpbGsgdGVzdA0Kc2hhcGlyby50ZXN0KHhtbykNCg0KIyBBbmRlcnNvbi1EYXJsaW5nIHRlc3QNCmxpYnJhcnkobm9ydGVzdCkNCmFkLnRlc3QoeG1vKQ0KDQojIENyYW1lci12b24gTWlzZXMgdGVzdA0KY3ZtLnRlc3QoeG1vKQ0KDQojIEphcnF1ZSBCZXJhIHRlc3QNCmxpYnJhcnkodHNlcmllcykNCmphcnF1ZS5iZXJhLnRlc3QoeG1vKQ0KbGlicmFyeShsYXdzdGF0KQ0KcmpiLnRlc3QoeG1vLCBvcHRpb249IkpCIixjcml0LnZhbHVlcz0iZW1waXJpY2FsIiwgTiA9IDUwMDApICMga2xhc2lja3kgSi4gQi4gdGVzdA0KcmpiLnRlc3QoeG1vLCBvcHRpb249IlJKQiIsY3JpdC52YWx1ZXM9ImVtcGlyaWNhbCIsIE4gPSA1MDAwKSAjIHJvYnVzdG5pIEouIEIuIHRlc3QNCiMgY3JpdC52YWx1ZXMgPSBjKCJjaGlzcS5hcHByb3hpbWF0aW9uIiwgImVtcGlyaWNhbCIpDQoNCiMgTGlsbGllZm9ycyB0ZXN0IChtb2RpZi4gS29sbW9nb3Jvdi1TbWlybm92KQ0KbGlicmFyeShub3J0ZXN0KQ0KbGlsbGllLnRlc3QoeG1vKQ0KDQojIHNqIHRlc3QNCmxpYnJhcnkobGF3c3RhdCkNCnNqLnRlc3QoeG1vLCBjcml0LnZhbHVlcyA9ICJlbXBpcmljYWwiLCBOID0gMTAwMCkNCiMgY3JpdC52YWx1ZXMgPSBjKCJ0LmFwcHJveGltYXRpb24iLCAiZW1waXJpY2FsIikNCg0KDQojIyBvdXRsaWVycw0KYm94cGxvdC5zdGF0cyh4bW8sIGNvZWYgPSAxLjUsIGRvLmNvbmYgPSBUUlVFLCBkby5vdXQgPSBUUlVFKQ0KDQoNCiMjIHBhcmFtZXRyeQ0KDQptZWFuKHhtbykNCmxpYnJhcnkoY29uZmludHIpDQpjaV9tZWFuKHhtbywgIHByb2JzID0gYygwLjAyNSwgMC45NzUpLHR5cGUgPSAidCIpDQpjaV9tZWFuKHhtbywgIHByb2JzID0gYygwLjAyNSwgMC45NzUpLHR5cGUgPSAiYm9vdHN0cmFwIiwgIGJvb3RfdHlwZSA9ICJiY2EiLCBSID0gOTk5OSwgc2VlZCA9IE5VTEwpDQojIGJvb3RfdHlwZSA9IGMoInN0dWQiIChkZWZhdWx0KSwgImJjYSIsICJwZXJjIiwgIm5vcm0iLCAiYmFzaWMiKQ0KbGlicmFyeShNS2luZmVyKQ0KbWVhbkNJKHhtbywgY29uZi5sZXZlbCA9IDAuOTUsIGJvb3QgPSBGQUxTRSwgbmEucm0gPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQ0KbWVhbkNJKHhtbywgY29uZi5sZXZlbCA9IDAuOTUsIGJvb3QgPSBUUlVFLCBSID0gOTk5OSwgYm9vdGNpLnR5cGUgPSAiYWxsIixuYS5ybSA9IFRSVUUsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQoNCmBgYA0KDQoNCk9ic2FoIEJhIHYga29zdGVjaCAocHBtKSB6IGxva2FsaXR5IERvbG7DrSBWxJtzdG9uaWNlIC0gUMOtc2t5Lg0KDQpgYGB7cn0NCg0KeGJhID0gYygxMDIuNDgwNzgsIDEzNS43NTMzMywgMTMwLjQ2ODg5LCAxMzguNzE3NjQsIDEwNC4zNzg1NywgIDczLjU3NjI4LDQ4LjkxNDkxLDY3Ljk4MjM0LCAxMDEuMzUwOTMsICA2MC4xNjU5NiwgIDkwLjc1MDIzLCAgNDcuMzQ3NDQsIDQ5LjMzNTAzLCA3Ni40NjQ5NiwgMTc1LjM1NzkzLCAxMzAuNDk2NzUsIDE0OC4wMTQ3NiwgMTE0Ljc5NjM1LCAgNjUuOTExNDksICA4My45MjQ4MiwgIDcxLjAyMDcyLCAzNC42NjI1NSwgIDk2LjAxMTQyLCAgNzguMDc2OTAsICA1NC41OTU0MiwgMTU4LjI5MDUyLCAxMTkuODcyNzcsICA2OS4xNDA5MiwgNzguODQ5MDEsICA0MS4yOTMxNywgIDcyLjgxMDkyLCA1NTQuNzcyNDMsIDI1OS42ODcxOSwgMTQ5LjMxOTg0LCAxMDcuODU0OTcsDQo4Mi4wOTIzMSwgIDI2LjAxNDAzLCAgOTguOTQ2NDEsICA1Ni40MTM4NCwgIDg2LjEwODIzLCAxMTguNTY5MjUsICA5NC40ODgzNiwNCjY1LjE3NTQxKQ0KDQoNCiMgQ3VsbGVuIEZyZXkgcGxvdA0KbGlicmFyeShmaXRkaXN0cnBsdXMpDQpkZXNjZGlzdCh4YmEsIGRpc2NyZXRlPUZBTFNFKQ0KZGVzY2Rpc3QoeGJhLCBkaXNjcmV0ZT1GQUxTRSwgYm9vdD05OTkpDQpkZXNjZGlzdChsb2coeGJhKSwgZGlzY3JldGU9RkFMU0UsIGJvb3Q9OTk5KQ0KDQpsaWJyYXJ5KFBBU1dSMikNCmVkYSh4YmEsIHRyaW0gPSAwLjA1LCBkZWMgPSAzKQ0KZWRhKGxvZyh4YmEpLCB0cmltID0gMC4wNSwgZGVjID0gMykNCg0KbGlicmFyeShzMjB4KQ0Kbm9ybWNoZWNrKHhiYSkNCm5vcm1jaGVjayhsb2coeGJhKSkNCg0KbGlicmFyeShVc2luZ1IpDQpzaW1wbGUuZWRhKHhiYSkNCnNpbXBsZS5lZGEobG9nKHhiYSkpDQoNCmxpYnJhcnkoU3RhdERBKQ0KZWRhcGxvdCh4YmEsSC5mcmVxPUZBTFNFLGJveD1UUlVFLEguYnJlYWtzPTMwLFMucGNoPTMsUy5jZXg9MC41LEQubHdkPTEuNSxQLmxvZz1GQUxTRSxQLm1haW49IiIsUC54bGFiPSJDdSBbcHBtXSIsUC55bGFiPSJEZW5zaXR5IixCLnBjaD0zLEIuY2V4PTAuNSkNCg0KbGlicmFyeShTdGF0REEpDQplZGFwbG90KHhiYSxILmZyZXE9RkFMU0UsYm94PVRSVUUsSC5icmVha3M9MzAsUy5wY2g9MyxTLmNleD0wLjUsRC5sd2Q9MS41LFAubG9nPVRSVUUsUC5tYWluPSIiLFAueGxhYj0iQ3UgW3BwbV0iLFAueWxhYj0iRGVuc2l0eSIsQi5wY2g9MyxCLmNleD0wLjUpDQoNCg0KDQpib3hwbG90LnN0YXRzKHhiYSwgY29lZiA9IDEuNSwgZG8uY29uZiA9IFRSVUUsIGRvLm91dCA9IFRSVUUpDQpsaWJyYXJ5KHVuaXZPdXRsKQ0KYm94Qih4YmEsIGs9MS41LCBtZXRob2Q9InJlc2lzdGFudCIsIHdlaWdodHM9TlVMTCwgaWQ9TlVMTCwgZXhjbHVkZT1OQSwgbG9ndD1GQUxTRSkNCmJveEIoeGJhLCBrPTEuNSwgbWV0aG9kPSdhc3ltbWV0cmljJywgd2VpZ2h0cz1OVUxMLCBpZD1OVUxMLGV4Y2x1ZGU9TkEsIGxvZ3Q9RkFMU0UpJG91dGxpZXJzDQpib3hCKHhiYSwgaz0xLjUsIG1ldGhvZD0nYWRqYm94Jywgd2VpZ2h0cz1OVUxMLCBpZD1OVUxMLCBleGNsdWRlPU5BLCBsb2d0PUZBTFNFKSRvdXRsaWVycw0KDQpsaWJyYXJ5KGV4dHJlbWV2YWx1ZXMpDQojZ2V0T3V0bGllcnMoeGJhLG1ldGhvZD0iSSIsZGlzdHJpYnV0aW9uPSJub3JtYWwiKQ0KI2dldE91dGxpZXJzKHhiYSxtZXRob2Q9IklJIixkaXN0cmlidXRpb249Im5vcm1hbCIpDQpnZXRPdXRsaWVycyh4YmEsbWV0aG9kPSJJIixkaXN0cmlidXRpb249ImxvZ25vcm1hbCIpDQpnZXRPdXRsaWVycyh4YmEsbWV0aG9kPSJJSSIsZGlzdHJpYnV0aW9uPSJsb2dub3JtYWwiKQ0KTCA8LSBnZXRPdXRsaWVycyh4Y2gsbWV0aG9kPSJJSSIsZGlzdHJpYnV0aW9uPSJub3JtYWwiKQ0Kb3V0bGllclBsb3QoeGNoLEwsbW9kZT0icXEiKQ0Kb3V0bGllclBsb3QoeGNoLEwsbW9kZT0icmVzaWR1YWwiKQ0KDQpsaWJyYXJ5KE91dGxpZXJEZXRlY3Rpb24pDQpVbml2YXJpYXRlT3V0bGllckRldGVjdGlvbih4YmEsIGsgPSAwLjA1ICogbGVuZ3RoKHhjaCksIGN1dG9mZiA9IDAuOTUsIGRpc3QgPSBGQUxTRSwgZGVucyA9IEZBTFNFLCBkZXB0aCA9IEZBTFNFLCBNZXRob2QgPSAiZXVjbGlkZWFuIiwgcm5hbWVzID0gRkFMU0UpDQoNCg0KbW5vID0geGJhWy0zMl0NCiMgbW5vID0geGJhWy1jKDMyLDMzKV0NCg0KDQojIEJveC1Db3gNCg0KbGlicmFyeShjYXIpDQpib3hDb3gobG0obW5vfjEpLCBsYW1iZGEgPSBzZXEoLTIsIDIsIDEvMTApLCBwbG90aXQgPSBUUlVFLCBpbnRlcnAgPSBUUlVFLCBlcHMgPSAxLzUwLCB4bGFiPU5VTEwsIHlsYWI9TlVMTCwgZmFtaWx5PSJiY1Bvd2VyIiwgcGFyYW09ICJsYW1iZGEiLCBnYW1tYT1OVUxMLGdyaWQ9VFJVRSkNCg0KbGlicmFyeShmb3JlY2FzdCkNCmxhbWJkYSA9IEJveENveC5sYW1iZGEobW5vLCBtZXRob2QgPSAibG9nbGlrIiwgbG93ZXIgPSAtMiwgdXBwZXIgPSAyKQ0KIyBtZXRob2QgPSBjKCJndWVycmVybyIsICJsb2dsaWsiKQ0KeGJjID0gQm94Q294KG1ubywgbGFtYmRhKQ0KeHJ0ID0gSW52Qm94Q294KHhiYywgbGFtYmRhLCBiaWFzYWRqID0gRkFMU0UsIGZ2YXIgPSBOVUxMKQ0KcGFyKG1mcm93PWMoMSwyKSkNCmhpc3QobW5vLCBtYWluPSIiKQ0KaGlzdCh4YmMsIG1haW49IiIseGxhYj0idHJhbnNmIHgiKQ0KcGFyKG1mcm93PWMoMSwxKSkNCmVyIDwtIHF0KDAuOTc1LGRmPWxlbmd0aCh4YmMpLTEpKnNkKHhiYykvc3FydChsZW5ndGgoeGJjKSkNCmxlZnQgPC0gbWVhbih4YmMpLWVyDQpyaWdodCA8LSBtZWFuKHhiYykrZXINCkludkJveENveChjKG1lYW4oeGJjKSwgbGVmdCwgcmlnaHQpLCBsYW1iZGEsIGJpYXNhZGogPSBGQUxTRSwgZnZhciA9IE5VTEwpDQoNCg0KbWVhbih4YmEpDQptZWRpYW4oeGJhKQ0Kc2QoeGJhLCBuYS5ybT1UUlVFKQ0KDQptZWFuKG1ubykNCm1lZGlhbihtbm8pDQpzZChtbm8sIG5hLnJtPVRSVUUpDQoNCmxpYnJhcnkoRlNBKQ0KZ2VvbWVhbihtbm8sIG5hLnJtID0gRkFMU0UsIHpuZWcucm0gPSBGQUxTRSkNCmxpYnJhcnkoRGVzY1Rvb2xzKQ0KR21lYW4obW5vLCBtZXRob2QgPSAiYm9vdCIsIGNvbmYubGV2ZWwgPSAwLjA1LHNpZGVzID0gInR3by5zaWRlZCIsIG5hLnJtID0gRkFMU0UpDQojIG1ldGhvZCA9IGMoImNsYXNzaWMiLCAiYm9vdCIpDQojIHNpZGVzID0gYygidHdvLnNpZGVkIiwibGVmdCIsInJpZ2h0IikNCmxpYnJhcnkoZnVlbCkNCmxvZ25vcm1hbG1lYW4obW5vLCBlc3RpbWF0b3I9Im1sIiwgYmFzZSA9IGV4cCgxKSxuID0gbGVuZ3RoKG1ubyksIG0gPSBuIC0gMSwgZCA9IDEvbikNCg0KbGlicmFyeShGU0EpDQpzZyA9IGdlb3NkKG1ubywgbmEucm0gPSBGQUxTRSwgem5lZy5ybSA9IEZBTFNFKTsgMTBec2cNCmxpYnJhcnkoZnVlbCkNCmxvZ25vcm1hbHNkKG1ubywgZXN0aW1hdG9yPSJtbCIsIGJhc2UgPSBleHAoMSksbiA9IGxlbmd0aChtbm8pLG0gPSBuIC0gMSwgZCA9IDEvbikNCmxpYnJhcnkoRGVzY1Rvb2xzKQ0KR3NkKG1ubywgbmEucm0gPSBGQUxTRSkNCg0KDQojIyMgS3ZhbnRpbG92ZSBvZGhhZHkNCg0KbWVkaWFuKHhiYSkNCg0KbGlicmFyeShjb25maW50cikNCmNpX21lZGlhbih4YmEscHJvYnMgPSBjKDAuMDI1LCAwLjk3NSksdHlwZSA9ICJib290c3RyYXAiLCBib290X3R5cGUgPSAiYmNhIiwgUiA9IDk5OTksc2VlZCA9IE5VTEwpDQojIHR5cGUgPSBjKCJiaW5vbWlhbCIsICJib290c3RyYXAiKQ0KIyBib290X3R5cGUgPSBjKCJiY2EiLCAicGVyYyIsICJub3JtIiwgImJhc2ljIikNCmxpYnJhcnkoTUtpbmZlcikNCm1lZGlhbkNJKHhiYSwgY29uZi5sZXZlbCA9IDAuOTUsIG1ldGhvZCA9ICJleGFjdCIsUiA9IDk5OTksIGJvb3RjaS50eXBlID0gImJjYSIsbWluTGVuZ3RoID0gRkFMU0UsIG5hLnJtID0gRkFMU0UsYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikNCiMgbWV0aG9kID0gYygiZXhhY3QiLCAiYXN5bXB0b3RpYyIpDQojIGJvb3RjaS50eXBlID0gYygibm9ybSIsICJiYXNpYyIsICJwZXJjIiwgImJjYSIpLA0KIyBhbHRlcm5hdGl2ZSA9IGMoInR3by5zaWRlZCIsICJsZXNzIiwgImdyZWF0ZXIiKQ0KDQoNCm1hZCh4YmEsIGNlbnRlciA9IG1lZGlhbih4YmEpLCBjb25zdGFudCA9IDEuNDgyNiwgbmEucm0gPSBGQUxTRSkNCmxpYnJhcnkoclFDQykNCm1hZC51bmJpYXNlZCAoeGJhLCBjZW50ZXIgPSBtZWRpYW4oeGJhKSwgY29uc3RhbnQ9MS40ODI2LCBuYS5ybSA9IEZBTFNFKQ0KDQptYWQyLnVuYmlhc2VkKHhiYSwgY2VudGVyID0gbWVkaWFuKHhiYSksIGNvbnN0YW50PTEuNDgyNiwgbmEucm0gPSBGQUxTRSkNCg0KDQoNCmxpYnJhcnkoZml0ZGlzdHJwbHVzKQ0KZmxtID0gZml0ZGlzdChtbm8sZGlzdHI9Imxub3JtIiwgbWV0aG9kID0gIm1sZSIpDQojIG1ldGhvZCA9IGMoIm1sZSIsICJtbWUiLCAicW1lIiwgIm1nZSIsICJtc2UiKQ0Kc3VtbWFyeShmbG0pDQoNCmZnYSA9IGZpdGRpc3QobW5vLGRpc3RyPSJnYW1tYSIsIG1ldGhvZCA9ICJtbGUiKQ0KIyBtZXRob2QgPSBjKCJtbGUiLCAibW1lIiwgInFtZSIsICJtZ2UiLCAibXNlIikNCnN1bW1hcnkoZmdhKQ0KDQpgYGANCg0KDQpQxZlpIHpqacWhxaVvdsOhbsOtIG9ic2FodSB1aGzDrWt1IHYgdWhsw60gYnlseSAoemEgcMWZZWRwb2tsYWR1IG5vcm3DoWxuw61obyByb3pkxJtsZW7DrSkgeiAyMCBtxJvFmWVuw60gdnlwb8SNdGVueSBwcsWvbcSbcm7DvSBvYnNhaCA4My4wNTAgJSBhIHNtxJtyb2RhdG7DoSBvZGNoeWxrYSAzLjQ1NiAlLiBVcsSNZXRlIDk1JSBpbnRlcnZhbHkgc3BvbGVobGl2b3N0aSBvYm91IHBhcmFtZXRyxa8uDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQoNCm0gPSA4My4wNTANCnMgPSAzLjQ1Ng0KbiA9IDIwDQoNCm0gKyBjKC1zLCBzKSpxdCgwLjk3NSxkZj1uLTEpL3NxcnQobikNCmxpYnJhcnkoTGVhcm5pbmdTdGF0cykNCk1lYW4uQ0kobSwgc2lnbWEgPSBOVUxMLCBzYyA9IE5VTEwsIHMgPSBzLCBuID0gbiwgY29uZi5sZXZlbD0gMC45NSkkQ0kNCg0KcypzcXJ0KChuLTEpL3FjaGlzcShjKDAuOTc1LCAwLjAyNSksIGRmPW4tMSkpDQpsaWJyYXJ5KExlYXJuaW5nU3RhdHMpDQp2YXJpYW5jZS5DSSh4ID0gTlVMTCwgcyA9IHMsIHNjID0gTlVMTCwgc211ID0gTlVMTCwgbXUgPSBOVUxMLCBuID0gbiwgY29uZi5sZXZlbD0gMC45NSkNCg0KYGBgDQoNCg0KQWt0aXZpdGEgZW56eW11IHBvZMOtbGVqw61jw61obyBzZSBuYSBtZXRhYm9saXNtdSBrYXJjaW5vZ2VubsOtY2ggbMOhdGVrLiBKZGUgbyBob2Rub3R5IG1vxI1vdsOpaG8gbWV0YWJvbGlja8OpaG8gcG9txJtydSA1LWFjZXR5bGFtaW5vLTYtZm9ybXlsYW1pbm8tMy1tZXRoeWx1cmFjaWx1IGsxLW1ldGh5bHhhbnRpbnUgKEFGTVUvMVgpIHBvIHBlcm9yw6FsbsOtbSBwb2TDoW7DrSBrb2ZlaW51Lg0KDQpgYGB7cn0NCg0KbGlicmFyeShtdWx0aW1vZGUpDQpkYXRhKGVuenltZSkNCnhlYSA9IGVuenltZQ0KDQojIyBOb3JtYWxpdGENCg0KIyBDdWxsZW4gRnJleSBwbG90DQpsaWJyYXJ5KGZpdGRpc3RycGx1cykNCmRlc2NkaXN0KHhlYSwgZGlzY3JldGU9RkFMU0UpDQpkZXNjZGlzdCh4ZWEsIGRpc2NyZXRlPUZBTFNFLCBib290PTk5OSkNCmRlc2NkaXN0KGxvZyh4ZWEpLCBkaXNjcmV0ZT1GQUxTRSwgYm9vdD05OTkpDQoNCmxpYnJhcnkoUEFTV1IyKQ0KZWRhKHhlYSwgdHJpbSA9IDAsIGRlYyA9IDMpDQplZGEobG9nKHhlYSksIHRyaW0gPSAwLCBkZWMgPSAzKQ0KDQpsaWJyYXJ5KHMyMHgpDQpub3JtY2hlY2soeGVhKQ0Kbm9ybWNoZWNrKGxvZyh4ZWEpKQ0KDQpsaWJyYXJ5KFVzaW5nUikNCnNpbXBsZS5lZGEoeGVhKQ0Kc2ltcGxlLmVkYShsb2coeGVhKSkNCg0KbGlicmFyeShTdGF0REEpDQplZGFwbG90KHhlYSxILmZyZXE9RkFMU0UsYm94PVRSVUUsSC5icmVha3M9MzAsUy5wY2g9MyxTLmNleD0wLjUsRC5sd2Q9MS41LFAubG9nPUZBTFNFLFAubWFpbj0iIixQLnhsYWI9IkFrdGl2aXRhIGVuenltdSIsIFAueWxhYj0iRGVuc2l0eSIsQi5wY2g9MyxCLmNleD0wLjUpDQoNCmVkYXBsb3QoeGVhLEguZnJlcT1GQUxTRSxib3g9VFJVRSxILmJyZWFrcz0zMCxTLnBjaD0zLFMuY2V4PTAuNSxELmx3ZD0xLjUsUC5sb2c9VFJVRSxQLm1haW49IiIsUC54bGFiPSJBa3Rpdml0YSBlbnp5bXUiLCBQLnlsYWI9IkRlbnNpdHkiLEIucGNoPTMsQi5jZXg9MC41KQ0KDQoNCg0KDQoNCg0KIyBCb3gtQ294DQoNCmxpYnJhcnkoY2FyKQ0KYm94Q294KGxtKHhlYX4xKSwgbGFtYmRhID0gc2VxKC0yLCAyLCAxLzEwKSwgcGxvdGl0ID0gVFJVRSwgaW50ZXJwID0gVFJVRSwgZXBzID0gMS81MCwgeGxhYj1OVUxMLCB5bGFiPU5VTEwsIGZhbWlseT0iYmNQb3dlciIsIHBhcmFtPSAibGFtYmRhIiwgZ2FtbWE9TlVMTCxncmlkPVRSVUUpDQoNCmxpYnJhcnkoZm9yZWNhc3QpDQpsYW1iZGEgPSBCb3hDb3gubGFtYmRhKHhlYSwgbWV0aG9kID0gImxvZ2xpayIsIGxvd2VyID0gLTIsIHVwcGVyID0gMikNCiMgbWV0aG9kID0gYygiZ3VlcnJlcm8iLCAibG9nbGlrIikNCnhiYyA9IEJveENveCh4ZWEsIGxhbWJkYSkNCnhydCA9IEludkJveENveCh4YmMsIGxhbWJkYSwgYmlhc2FkaiA9IEZBTFNFLCBmdmFyID0gTlVMTCkNCnBhcihtZnJvdz1jKDEsMikpDQpoaXN0KHhlYSwgbWFpbj0iIikNCmhpc3QoeGJjLCBtYWluPSIiLHhsYWI9InRyYW5zZiB4IikNCnBhcihtZnJvdz1jKDEsMSkpDQplciA8LSBxdCgwLjk3NSxkZj1sZW5ndGgoeGJjKS0xKSpzZCh4YmMpL3NxcnQobGVuZ3RoKHhiYykpDQpsZWZ0IDwtIG1lYW4oeGJjKS1lcjsgbGVmdA0KcmlnaHQgPC0gbWVhbih4YmMpK2VyOyByaWdodA0KSW52Qm94Q294KGMobWVhbih4YmMpLCBsZWZ0LCByaWdodCksIGxhbWJkYSwgYmlhc2FkaiA9IEZBTFNFLCBmdmFyID0gTlVMTCkNCg0KDQojIyBCaGF0dGFjaGFyeWEgcGxvdCBzIEFTSA0KZGF0ID0geGVhDQpsaWJyYXJ5KGFzaCkgDQpubj0zMA0KZiA8LSBhc2gxKGJpbjEoZGF0LG5iaW49bm4pLDUpICMgYXNoIGVzdGltYXRlDQpuazwtbGVuZ3RoKGYkeSktMQ0KeWs8LXJlcCgwLG5rKQ0KeGs8LXJlcCgwLG5rKQ0KZm9yKGkgaW4gMTpuayl7DQogIHlrW2ldPC1sb2coZiR5W2krMV0vZiR5W2ldKQ0KICB4a1tpXTwtKGYkeFtpKzFdK2YkeFtpXSkvMg0KfQ0KcGxvdCh4ayx5aywgdHlwZT0ibCIsY29sPTEsbHR5PTEsIG1haW49IiIsIHhsYWI9IngiLHlsYWI9ImxuKCBmKGkrMSkgLyBmKGkpICkiKQ0KcnVnKGRhdCkNCg0KDQojIEhhcnRpZ2FuIGRpcCB0ZXN0DQpsaWJyYXJ5KGRpcHRlc3QpDQpkdGIgPSBkaXAoeGVhLCBmdWxsLnJlc3VsdCA9IFRSVUUsIG1pbi5pcy4wID0gVFJVRSwgZGVidWcgPSBGQUxTRSk7IGR0Yg0KZGlwLnRlc3QoeGVhLCBzaW11bGF0ZS5wLnZhbHVlID0gRkFMU0UsIEIgPSAyMDAwKQ0KcGxvdChkdGIpDQoNCg0KIyBTaWx2ZXJtYW51diB0ZXN0DQpsaWJyYXJ5KHNpbHZlcm1hbnRlc3QpIA0KIyBodHRwczovL3d3dy5tYXRoZW1hdGlrLnVuaS1tYXJidXJnLmRlL35zdG9jaGFzdGlrL1JfcGFja2FnZXMvDQpzaWx2ZXJtYW4udGVzdChtbm8sIGs9MSwgTSA9IDk5OSwgYWRqdXN0ID0gRkFMU0UsIGRpZ2l0cyA9IDYpDQpzaWx2ZXJtYW4udGVzdChtbm8sIGs9MiwgTSA9IDk5OSwgYWRqdXN0ID0gRkFMU0UsIGRpZ2l0cyA9IDYpDQpzaWx2ZXJtYW4udGVzdChtbm8sIGs9MywgTSA9IDk5OSwgYWRqdXN0ID0gRkFMU0UsIGRpZ2l0cyA9IDYpDQpzaWx2ZXJtYW4udGVzdChtbm8sIGs9NCwgTSA9IDk5OSwgYWRqdXN0ID0gRkFMU0UsIGRpZ2l0cyA9IDYpDQpzaWx2ZXJtYW4ucGxvdChtbm8sIGttaW49MSwga21heD0zLCBhbHBoYT0wLjA1LCBhZGp1c3Q9RkFMU0UpDQoNCg0KIyBBbWVpamVpcmFzLUFsb25zbyBleGNlc3MgbWFzcyB0ZXN0DQpsaWJyYXJ5KG11bHRpbW9kZSkNCm1vZGV0ZXN0KG1ubyxtb2QwPTEsbWV0aG9kPSJBQ1IiLEI9NTAwLGxvd3N1cD0tSW5mLHVwcHN1cD1JbmYsc3VibWV0aG9kPU5VTEwsbj1OVUxMLHRvbD1OVUxMLHRvbDI9TlVMTCxncmlkc2l6ZT1OVUxMLGFscGhhPU5VTEwsbk1DPU5VTEwsQk1DPU5VTEwpDQoNCg0KIyBtZXRvZGEgbWF4IHZlcm9ob2Rub3N0aQ0KbGlicmFyeShtY2x1c3QpDQp4czwtIHNvcnQobW5vKQ0KZG1jIDwtIE1jbHVzdCh4cyxHPU5VTEwpDQpkbWNCSUMgPC0gbWNsdXN0QklDKHgpOyBkbWNCSUMNCm5uID0gMw0KZG1jIDwtIE1jbHVzdCh4cyxHPW5uKQ0KZG1jeiA8LXJvdW5kKGRtYyR6LG5uKTsgZG1jeg0KDQoNCmBgYA0KDQoNClByb2NlbnRvIG94aWR1IGvFmWVtacSNaXTDqWhvICh2ICUpIHZlIDIyIGNob25kcml0b3bDvWNoIG1ldGVvcml0ZWNoLg0KDQpgYGB7cn0NCg0KbGlicmFyeShtdWx0aW1vZGUpDQpkYXRhKGNob25kcml0ZSkNCnhjZCA9IGNob25kcml0ZQ0KDQojIyBOb3JtYWxpdGENCg0KIyBDdWxsZW4gRnJleSBwbG90DQpsaWJyYXJ5KGZpdGRpc3RycGx1cykNCmRlc2NkaXN0KHhjZCwgZGlzY3JldGU9RkFMU0UpDQpkZXNjZGlzdCh4Y2QsIGRpc2NyZXRlPUZBTFNFLCBib290PTk5OSkNCmRlc2NkaXN0KGxvZyh4Y2QpLCBkaXNjcmV0ZT1GQUxTRSwgYm9vdD05OTkpDQoNCmxpYnJhcnkoUEFTV1IyKQ0KZWRhKHhjZCwgdHJpbSA9IDAsIGRlYyA9IDMpDQplZGEobG9nKHhjZCksIHRyaW0gPSAwLCBkZWMgPSAzKQ0KDQpsaWJyYXJ5KHMyMHgpDQpub3JtY2hlY2soeGNkKQ0Kbm9ybWNoZWNrKGxvZyh4Y2QpKQ0KDQpsaWJyYXJ5KFVzaW5nUikNCnNpbXBsZS5lZGEoeGNkKQ0Kc2ltcGxlLmVkYShsb2coeGNkKSkNCg0KbGlicmFyeShTdGF0REEpDQplZGFwbG90KHhjZCwgSC5mcmVxPUZBTFNFLGJveD1UUlVFLEguYnJlYWtzPTMwLFMucGNoPTMsUy5jZXg9MC41LEQubHdkPTEuNSxQLmxvZz1GQUxTRSxQLm1haW49IiIsUC54bGFiPSJTaU8yIiwgUC55bGFiPSJEZW5zaXR5IixCLnBjaD0zLEIuY2V4PTAuNSkNCg0KZWRhcGxvdCh4Y2QsSC5mcmVxPUZBTFNFLGJveD1UUlVFLEguYnJlYWtzPTMwLFMucGNoPTMsUy5jZXg9MC41LEQubHdkPTEuNSxQLmxvZz1UUlVFLFAubWFpbj0iIixQLnhsYWI9IlNpTzIiLCBQLnlsYWI9IkRlbnNpdHkiLEIucGNoPTMsQi5jZXg9MC41KQ0KDQoNCiMgQm94LUNveA0KDQpsaWJyYXJ5KGNhcikNCmJveENveChsbSh4Y2R+MSksIGxhbWJkYSA9IHNlcSgtMiwgMiwgMS8xMCksIHBsb3RpdCA9IFRSVUUsIGludGVycCA9IFRSVUUsIGVwcyA9IDEvNTAsIHhsYWI9TlVMTCwgeWxhYj1OVUxMLCBmYW1pbHk9ImJjUG93ZXIiLCBwYXJhbT0gImxhbWJkYSIsIGdhbW1hPU5VTEwsZ3JpZD1UUlVFKQ0KDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KbGFtYmRhID0gQm94Q294LmxhbWJkYSh4Y2QsIG1ldGhvZCA9ICJsb2dsaWsiLCBsb3dlciA9IC0yLCB1cHBlciA9IDIpDQojIG1ldGhvZCA9IGMoImd1ZXJyZXJvIiwgImxvZ2xpayIpDQp4YmMgPSBCb3hDb3goeGNkLCBsYW1iZGEpDQp4cnQgPSBJbnZCb3hDb3goeGJjLCBsYW1iZGEsIGJpYXNhZGogPSBGQUxTRSwgZnZhciA9IE5VTEwpDQpwYXIobWZyb3c9YygxLDIpKQ0KaGlzdCh4Y2QsIG1haW49IiIpDQpoaXN0KHhiYywgbWFpbj0iIix4bGFiPSJ0cmFuc2YgeCIpDQpwYXIobWZyb3c9YygxLDEpKQ0KZXIgPC0gcXQoMC45NzUsZGY9bGVuZ3RoKHhiYyktMSkqc2QoeGJjKS9zcXJ0KGxlbmd0aCh4YmMpKQ0KbGVmdCA8LSBtZWFuKHhiYyktZXI7IGxlZnQNCnJpZ2h0IDwtIG1lYW4oeGJjKStlcjsgcmlnaHQNCkludkJveENveChjKG1lYW4oeGJjKSwgbGVmdCwgcmlnaHQpLCBsYW1iZGEsIGJpYXNhZGogPSBGQUxTRSwgZnZhciA9IE5VTEwpDQoNCg0KIyMgQmhhdHRhY2hhcnlhIHBsb3QgcyBBU0gNCmRhdCA9IHhjZA0KbGlicmFyeShhc2gpIA0Kbm49MzANCmYgPC0gYXNoMShiaW4xKGRhdCxuYmluPW5uKSw1KSAjIGFzaCBlc3RpbWF0ZQ0Kbms8LWxlbmd0aChmJHkpLTENCnlrPC1yZXAoMCxuaykNCnhrPC1yZXAoMCxuaykNCmZvcihpIGluIDE6bmspew0KICB5a1tpXTwtbG9nKGYkeVtpKzFdL2YkeVtpXSkNCiAgeGtbaV08LShmJHhbaSsxXStmJHhbaV0pLzINCn0NCnBsb3QoeGsseWssIHR5cGU9ImwiLGNvbD0xLGx0eT0xLCBtYWluPSIiLCB4bGFiPSJ4Iix5bGFiPSJsbiggZihpKzEpIC8gZihpKSApIikNCnJ1ZyhkYXQpDQoNCg0KIyBIYXJ0aWdhbiBkaXAgdGVzdA0KbGlicmFyeShkaXB0ZXN0KQ0KZHRiID0gZGlwKHhjZCwgZnVsbC5yZXN1bHQgPSBUUlVFLCBtaW4uaXMuMCA9IFRSVUUsIGRlYnVnID0gRkFMU0UpOyBkdGINCmRpcC50ZXN0KHhjZCwgc2ltdWxhdGUucC52YWx1ZSA9IEZBTFNFLCBCID0gMjAwMCkNCnBsb3QoZHRiKQ0KDQoNCiMgU2lsdmVybWFudXYgdGVzdA0KZGF0ID0geGNkDQpsaWJyYXJ5KHNpbHZlcm1hbnRlc3QpIA0KIyBodHRwczovL3d3dy5tYXRoZW1hdGlrLnVuaS1tYXJidXJnLmRlL35zdG9jaGFzdGlrL1JfcGFja2FnZXMvDQpzaWx2ZXJtYW4udGVzdChkYXQsIGs9MSwgTSA9IDk5OSwgYWRqdXN0ID0gRkFMU0UsIGRpZ2l0cyA9IDYpDQpzaWx2ZXJtYW4udGVzdChkYXQsIGs9MiwgTSA9IDk5OSwgYWRqdXN0ID0gRkFMU0UsIGRpZ2l0cyA9IDYpDQpzaWx2ZXJtYW4udGVzdChkYXQsIGs9MywgTSA9IDk5OSwgYWRqdXN0ID0gRkFMU0UsIGRpZ2l0cyA9IDYpDQpzaWx2ZXJtYW4ucGxvdChkYXQsIGttaW49MSwga21heD0zLCBhbHBoYT0wLjA1LCBhZGp1c3Q9RkFMU0UpDQoNCg0KIyBBbWVpamVpcmFzLUFsb25zbyBleGNlc3MgbWFzcyB0ZXN0DQpsaWJyYXJ5KG11bHRpbW9kZSkNCm1vZGV0ZXN0KHhjZCxtb2QwPTEsbWV0aG9kPSJBQ1IiLEI9NTAwLGxvd3N1cD0tSW5mLHVwcHN1cD1JbmYsc3VibWV0aG9kPU5VTEwsbj1OVUxMLHRvbD1OVUxMLHRvbDI9TlVMTCxncmlkc2l6ZT1OVUxMLGFscGhhPU5VTEwsbk1DPU5VTEwsQk1DPU5VTEwpDQoNCg0KIyBtZXRvZGEgbWF4IHZlcm9ob2Rub3N0aQ0KbGlicmFyeShtY2x1c3QpDQp4czwtIHNvcnQoeGNkKQ0KZG1jIDwtIE1jbHVzdCh4cyxHPU5VTEwpDQpkbWNCSUMgPC0gbWNsdXN0QklDKHgpOyBkbWNCSUMNCm5uID0gMg0KZG1jIDwtIE1jbHVzdCh4cyxHPW5uKQ0KZG1jeiA8LXJvdW5kKGRtYyR6LG5uKTsgZG1jeg0KYGBgDQoNCg0KDQpVcsSNZXRlIHBvxI1ldCBwYXJhbGVsbsOtY2gga29sb3JpbWV0cmlja8O9Y2ggc3Rhbm92ZW7DrSBvYnNhaHUgRmUsIGFieSBtYXhpbcOhbG7DrSBjaHliYSB2w71zbGVkbsOpIGhvZG5vdHkgcHLFr23Em3J1IG5lcMWZZWtyb8SNaWxhIGhvZG5vdHUgMC4wMDUuIENoeWJhIG1ldG9keSAoc23Em3JvZGF0bsOhIG9kY2h5bGthKSBqZSAwLjAxMzIuIA0KYGBge3J9DQoNCmRlbHRhID0gMC4wMDUNCnNpZ21hID0gMC4wMTMyDQoNCm5wID0gKDMqc2lnbWEvZGVsdGEpXjI7IG5wDQoNCm56ID0gKChzaWdtYSpxbm9ybSgwLjk3NSkpL2RlbHRhKV4yOyBueg0KDQpsaWJyYXJ5KHNhbXBsaW5nYm9vaykNCnNhbXBsZS5zaXplLm1lYW4oZT1kZWx0YSwgUz1zaWdtYSwgTiA9IEluZiwgbGV2ZWwgPSAwLjk1KQ0KDQpxdCA9IDMNCm50ID0gKChzaWdtYSpxdCkvZGVsdGEpXjI7IG50DQojIGl0ZXJhY2UNCm50ID0gbnQtMQ0KbnQgPSAoKHNpZ21hKnF0KDAuOTc1LChudC0xKSkpL2RlbHRhKV4yOyBudA0KDQpgYGANCg0KDQpBdXRvbWF0aWNrw70gc291c3RydWggdnlyw6Fiw60gdMSbc27DrWPDrSBrcm91xb5reSBvIGRla2xhcm92YW7DqW0gcHLFr23Em3J1IDI1IG1tLiBOw6Fob2RuxJsgdnlicmFuw71jaCAzMCBrcm91xb5rxa8gbcSbbG8gcHLFr23Em3Jub3UgaG9kbm90dSAyNS40MyBtbSBhIHNtxJtyb2RhdG5vdSBvZGNoeWxrdSAwLjE0NSBtbS4gSmUgbW/Fvm7DqSBwxZlpIHJpemlrdSA1ICUgcMWZaXB1c3RpdCwgxb5lIGF1dG9tYXQgZG9kcsW+dWplIG5vbWluw6FsbsOtIGhvZG5vdHUgMjUgbW0/DQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KFBBU1dSMikNCnRzdW0udGVzdChtZWFuLnggPSAyNS40Mywgcy54ID0gMC4xNDUsIG4ueCA9IDMwLCBtZWFuLnkgPSBOVUxMLCBzLnkgPSBOVUxMLG4ueSA9IE5VTEwsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsIG11ID0gMjUsdmFyLmVxdWFsID0gRkFMU0UsY29uZi5sZXZlbCA9IDAuOTUpDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQoNCmBgYA0KDQoNClDFmWkgcG91xb5pdMOtIGR2b3Ugb2RsacWhbsO9Y2ggbWV0b2QgbcSbxZllbsOtIGJ5bHkgbmEgMTAgdnpvcmPDrWNoIHpqacWhdMSbbnkgcm96ZMOtbHkgdiBuYW3Em8WZZW7DvWNoIMO6ZGFqw61jaC5Sb3pob2RuxJt0ZSwgemRhIGV4aXN0dWplIHN5c3RlbWF0aWNrw70gcm96ZMOtbCBtZXppIG9ixJttYSBtZXRvZGFtaSAobmEgaGxhZGluxJsgdsO9em5hbW5vc3RpIDAuMDUpLg0KDQpgYGB7cn0NCg0KZHggPSBjKDEuMiwgLTMuNSwgMC41LCAxLjQsIC0wLjgsIDUuMSwgNi44LCAxLjcsIDAuOSwgLTIuMykNCg0KbGlicmFyeShzMjB4KQ0Kbm9ybWNoZWNrKGR4KQ0KDQoNCg0KIyBPbmUgc2FtcGxlIHQtdGVzdA0KdC50ZXN0KGR4LG11PTAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpIA0KDQojIFJvYnVzdG5pIG9uZSBzYW1wbGUgdC10ZXN0DQpsaWJyYXJ5KHJ0LnRlc3QpDQpydC50ZXN0KGR4LCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLG11ID0gMCwgdGVzdC5zdGF0ID0gIlRBIiwgY29uZi5sZXZlbCA9IDAuOTUpDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQojIHRlc3Quc3RhdCA9IGMoIlRBIiwgIlRCIiksIGJhc2VkIG9uIHRoZSBlbXBpcmljYWwgZGlzdHJpYnV0aW9ucyBvZiB0aGUgVEEgc3RhdGlzdGljIChiYXNlZCBvbiBtZWRpYW4gYW5kIE1BRCkgYW5kIHRoZSBUQnN0YXRpc3RpYyAoYmFzZWQgb24gSG9kZ2VzLUxlaG1hbm4gYW5kIFNoYW1vcw0KDQojIEJvb3RzdHJhcCB0LVRlc3QNCmxpYnJhcnkoTUtpbmZlcikNCmJvb3QudC50ZXN0KGR4LCB5ID0gTlVMTCxhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLCBtdSA9IDAsIHBhaXJlZCA9IEZBTFNFLCB2YXIuZXF1YWwgPSBGQUxTRSxjb25mLmxldmVsID0gMC45NSwgUiA9IDk5OTksIHN5bW1ldHJpYyA9IEZBTFNFKQ0KIyBhbHRlcm5hdGl2ZSA9IGMoInR3by5zaWRlZCIsICJsZXNzIiwgImdyZWF0ZXIiKQ0KDQpsaWJyYXJ5KEJvbHN0YWQpDQpiYXllcy50LnRlc3QoZHgsIHkgPSBOVUxMLGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsIG11ID0gMCwgcGFpcmVkID0gRkFMU0UsdmFyLmVxdWFsID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOTUscHJpb3IgPSAiamVmZnJleXMiLCBtID0gTlVMTCxuMCA9IE5VTEwsc2lnLm1lZCA9IE5VTEwsIGthcHBhID0gMSxzaWdtYVByaW9yID0gImNoaXNxIixuSXRlciA9IDEwMDAwLCBuQnVybiA9IDEwMDApDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQojIHByaW9yID0gYygiamVmZnJleXMiLCAiam9pbnQuY29uaiIpDQoNCmxpYnJhcnkoQlNEQSkNClNJR04udGVzdChkeCwgbWQgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLGNvbmYubGV2ZWwgPSAwLjk1KQ0KDQpsaWJyYXJ5KERlc2NUb29scykNClNpZ25UZXN0KGR4LG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIixjb25mLmxldmVsID0gMC45NSkNCg0KDQojIG9uZSBzYW1wbGUgV2lsY294b24gKE1hbm4tV2hpdG5leSkgdGVzdA0Kd2lsY294LnRlc3QoZHgsIHksYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIiwgbXUgPSAwLCBwYWlyZWQgPSBGQUxTRSwgZXhhY3QgPSBGQUxTRSwgY29ycmVjdCA9IFRSVUUsY29uZi5pbnQgPSBGQUxTRSwgY29uZi5sZXZlbCA9IDAuOTUpDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQoNCmxpYnJhcnkoZXhhY3RSYW5rVGVzdHMpDQp3aWxjb3guZXhhY3QoZHgsIHksIG11ID0gMCxhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLHBhaXJlZCA9IEZBTFNFLCBleGFjdCA9IEZBTFNFLGNvbmYuaW50ID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOTUpDQojICJ0d28uc2lkZWQiKGRlZmF1bHQpLCJncmVhdGVyIm9yImxlc3MiDQoNCmBgYA0KDQoNClbDvXNsZWRreSBtxJvFmWVuw60gdMOpxb5lIGtvbnN0YW50eSBkdsSbbWEgbWV0b2RhbWkgcG9za3l0bHkgbm9ybcOhbG7EmyByb3pkxJtsZW7DqSBob2Rub3R5IHbDvWLEm3LFryAobjEgPSAyNSBhIG4yID0gMzEpIHNlIHNtxJtyb2RhdG7DvW1pIG9kY2h5bGthbWkgczEgPSAwLjUyMyBhIHMyID0gMC4zNjMuIEx6ZSBuYSBobGFkaW7EmyB2w716bmFtbm9zdGkgMC4wNSBwb3Zhxb5vdmF0IG9ixJsgbWV0b2R5IHphIHN0ZWpuxJsgcMWZZXNuw6k/DQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KExlYXJuaW5nU3RhdHMpDQpkaWZmdmFyaWFuY2UudGVzdChzYzEgPSAwLjUyMywgc2MyID0gMC4zNjMsIG4xID0gMjUsIG4yID0gMzEsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsYWxwaGEgPSAwLjA1LCBwbG90ID0gVFJVRSkNCg0KZGlmZnZhcmlhbmNlLkNJKHNjMSA9IDAuNTIzLCBzYzIgPSAwLjM2MywgbjEgPSAyNSwgbjIgPSAzMSwgY29uZi5sZXZlbD0gMC4wNSkNCg0KYGBgDQoNCg0KQmFsaWPDrSBhdXRvbWF0IHpob3RvdnVqZSBiYWzDrcSNa3kgbyBkYW7DqSBobW90bm9zdGkgcyBtYXhpbcOhbG7DrSBzbcSbcm9kYXRub3Ugb2RjaHlsa291IDAuNCBnLiBaZSB6a3XFoWVibsOtaG8gdnpvcmt1IDEwIGJhbMOtxI1rxa8gYnlsYSB2eXBvxI10ZW5hIHbDvWLEm3JvdsOhIHNtxJtyb2RhdG7DoSBvZGNoeWxrYSAwLjUgZy4gUm96aG9kbsSbdGUgKHBybyBobGFkaW51IHbDvXpuYW1ub3N0aSA1ICUpLCB6ZGEgbmVkb8WhbG8gayBwb3J1xaFlIHphxZnDrXplbsOtIChuZWJ5bGEgcMWZZWtyb8SNZW5hIG1heGltw6FsbsOtIHNtxJtyb2RhdG7DoSBvZGNoeWxrYSkuDQoNCmBgYHtyfQ0KDQpuID0gMTANCnNpZyA9IDAuNA0Kc3MgPSAwLjUNCmxpYnJhcnkoTGVhcm5pbmdTdGF0cykNCnZhcmlhbmNlLnRlc3QoeCA9IE5VTEwsIHMgPSBOVUxMLCBzYyA9IHNzLCBzbXUgPSBOVUxMLCBtdSA9IE5VTEwsDQpuID0gbiwgc2lnbWEwMj0gc2lnXjIsIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiLCBhbHBoYSA9IDAuMDUsDQpwbG90ID0gVFJVRSwgbHdkID0gMSkNCg0KYGBgDQpIbGFkaW55IG9sb3ZhIHYga3J2aSAzMyBkxJt0w60gcm9kacSNxa8sIGt0ZcWZw60gcHJhY292YWxpIHYgdG92w6FybsSbIG5hIHbDvXJvYnUgb2xvdmEsIGEgMzMga29udHJvbG7DrWNoIGTEm3TDrSB6IGplamljaCBva29sw60uDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KFBhaXJlZERhdGEpDQpkYXRhKEJsb29kTGVhZCkNCnhlID0gQmxvb2RMZWFkWywyXQ0KeGMgPSBCbG9vZExlYWRbLDNdDQoNCmxpYnJhcnkoUEFTV1IyKQ0KZWRhKCh4ZS14YyksIHRyaW0gPSAwLCBkZWMgPSAzKQ0KDQpsaWJyYXJ5KHMyMHgpDQpub3JtY2hlY2soKHhlLXhjKSkNCg0KDQpsaWJyYXJ5KFBhaXJlZERhdGEpDQoNCmJveHBsb3QoeGMseGUpDQpwbG90KHhjLHhlLHhsaW09YygwLDgwKSx5bGltPWMoMCw4MCkpDQphYmxpbmUoMCwxKQ0KDQpzdW1tYXJ5KHBhaXJlZCh4ZSwgeGMpLHRyPTAuMikNCg0KZWZmZWN0LnNpemUocGFpcmVkKHhlLCB4YyksdHI9MC4yKQ0KDQpzbGlkaW5nY2hhcnQocGFpcmVkKHhlLCB4YykpDQoNCg0KIyBDb2hlbiBkIChzdGFuZGFyZGl6ZWQgbWVhbiBkaWZmZXJlbmNlKQ0KbWVhbih4ZS14Yykvc2QoeGUteGMpDQpsaWJyYXJ5KGxzcikNCmQgPSBjb2hlbnNEKHhlLCB4YyxtZXRob2QgPSAicGFpcmVkIik7IGQNCmxpYnJhcnkoZWZmc2l6ZSkNCmNvaGVuLmQoeGUsIHhjLCBwYWlyZWQgPSBUUlVFKQ0KDQpjb3IoeGUsIHhjLG1ldGhvZCA9ICJwZWFyc29uIikNCmNvcih4ZSwgeGMsbWV0aG9kID0gInNwZWFybWFuIikNCg0KDQojIHQtdGVzdA0KDQp0LnRlc3QoeGUsIHhjLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQ0KIyB0LnRlc3QoZWxlbSB+IGxvbSwgZGF0YSA9IGRhdGEsIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQoNCiMgQm9vdHN0cmFwIHQtVGVzdA0KbGlicmFyeShNS2luZmVyKQ0KYm9vdC50LnRlc3QoeGUsIHhjLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLG11ID0gMCwgcGFpcmVkID0gVFJVRSwgdmFyLmVxdWFsID0gRkFMU0UsIGNvbmYubGV2ZWwgPSAwLjk1LCBSID0gOTk5OSwgc3ltbWV0cmljID0gRkFMU0UpDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQoNCmxpYnJhcnkoQ2FybGV0b25TdGF0cykNCmJvb3RQYWlyZWQoeGUsIHhjLCBjb25mLmxldmVsID0gMC45NSwgQiA9IDEwMDAwLHBsb3QuaGlzdCA9IFRSVUUsIHBsb3QucXEgPSBGQUxTRSwgbGVnZW5kLmxvYyA9ICJ0b3ByaWdodCIseC5uYW1lID0gZGVwYXJzZShzdWJzdGl0dXRlKHgpKSwgeS5uYW1lID0gZGVwYXJzZShzdWJzdGl0dXRlKHkpKSkNCg0KIyBZdWVuJ3MgdHJpbW1lZCBtZWFuIHRlc3QNCmxpYnJhcnkoUGFpcmVkRGF0YSkNCnl1ZW4udC50ZXN0KHhlLCB4YywgdHIgPSAwLjIsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsIG11ID0gMCwgcGFpcmVkID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOTUpDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQoNCg0KIyBDaGVudXYgcGFpcmVkIHNhbXBsZSB0LXRlc3QgcHJvIHplc2lrbWVub3UgZGlzdHJpYnVjaQ0KbGlicmFyeShFbnZTdGF0cykNCmNoZW5UVGVzdCh4ZSwgeGMgLCBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIiwgbXUgPSAwLCBwYWlyZWQgPSBUUlVFLCBjb25mLmxldmVsID0gMC45NSwgY2kubWV0aG9kID0gInoiKQ0KIyBhbHRlcm5hdGl2ZSA9IGMoImxlc3MiLCAiZ3JlYXRlciIpDQojIGNpLm1ldGhvZCA9ICJ6IiwgInQiDQoNCmxpYnJhcnkoQm9sc3RhZCkNCmJheWVzLnQudGVzdCh4ZSwgeGMsYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIiwgbXUgPSAwLCBwYWlyZWQgPSBUUlVFLHZhci5lcXVhbCA9IFRSVUUsIGNvbmYubGV2ZWwgPSAwLjk1LHByaW9yID0gImplZmZyZXlzIiwgbSA9IE5VTEwsbjAgPSBOVUxMLHNpZy5tZWQgPSBOVUxMLCBrYXBwYSA9IDEsc2lnbWFQcmlvciA9ICJjaGlzcSIsbkl0ZXIgPSAxMDAwMCwgbkJ1cm4gPSAxMDAwKQ0KIyBhbHRlcm5hdGl2ZSA9IGMoInR3by5zaWRlZCIsICJsZXNzIiwgImdyZWF0ZXIiKQ0KIyBwcmlvciA9IGMoImplZmZyZXlzIiwgImpvaW50LmNvbmoiKSwNCg0KIyMgV2lsY294b251diBwYXJvdnkgdGVzdA0Kd2lsY294LnRlc3QoeGUsIHhjLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLCBjb25mLmludCA9IFRSVUUpDQoNCmxpYnJhcnkoUGFpcmVkRGF0YSkNCndpbGNveC50ZXN0KHBhaXJlZCh4ZSwgeGMpKQ0KDQojIyBtZWRpYW5vdnkgKHpuYW1lbmtvdnkpIHBhcm92eSB0ZXN0DQpsaWJyYXJ5KEVudlN0YXRzKQ0Kc2lnblRlc3QoeGUsIHhjLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLCBtdSA9IDAsIHBhaXJlZCA9IFRSVUUsIGNvbmYubGV2ZWwgPSAwLjk1KQ0KDQojIFBlcm11dGF0aW9uIHRlc3QgZm9yIHBhaXJlZCBkYXRhDQpsaWJyYXJ5KENhcmxldG9uU3RhdHMpDQpwZXJtVGVzdFBhaXJlZCh4ZSwgeGMsIEIgPSA5OTk5LGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsIHBsb3QuaGlzdCA9IFRSVUUsbGVnZW5kLmxvYyA9ICJ0b3ByaWdodCIsIHBsb3QucXEgPSBGQUxTRSx4Lm5hbWUgPSBkZXBhcnNlKHN1YnN0aXR1dGUoeCkpLCB5Lm5hbWUgPSBkZXBhcnNlKHN1YnN0aXR1dGUoeSkpKQ0KDQoNCnBsb3QoKHhlK3hjKS8yLCAoeGUteGMpKQ0KDQpgYGANCg0KDQpTdGFub3ZlbsOtIGtvbmNlbnRyYWNlIEYzKyAodiAlKSB2IHDFmcOtcHJhdmt1ICJGZXJydW0gY2l0cmljdW0gYW1tb25pYXR1bSB2aXJpZGUiIHNlIHByb3bDoWTDrSB0aXRyYWPDrSBqb2R1ICh1dm9sbsSbbsOpaG8gb3hpZGFjw60gS0kgxb5lbGV6aXTDvW1pIGlvbnR5KSB0aGlvc8OtcmFuZW0gbmEgxaFrcm9ib3bDvSBtYXouIFRpdHJhY2UgYnlsYSBwcm92ZWRuYSB1IGplZG7DqSDEjcOhc3RpIHZ6b3Jrxa8gaWhuZWQgYSB1IGRydWjDqSAzMCBtaW51dCBwbyBwxZlpZMOhbsOtIEtJLiBMw63FocOtIHNlIG5hIGhsYWRpbsSbIHbDvXpuYW1ub3N0aSAwLjA1IHbDvXNsZWRreSBvYm91IHBvc3R1cMWvPyAgDQoNCmBgYHtyfQ0KDQp4aWggPSBjKDEzLjI5LCAxMy4zNiwgMTMuMzIsIDEzLjUzLCAxMy41NiwgMTMuNDMsIDEzLjMwLCAxMy40MykNCngzMCA9IGMoMTMuODYsIDEzLjk5LCAxMy44OCwgMTMuOTEsIDEzLjg5LCAxMy45NCwgMTMuODAsIDEzLjg5KQ0KDQoNCmZlMyA9IGxpc3QoeGloLHgzMCkNCm5hbWVzKGZlMykgPSBjKCJGZSBobmVkIiwgIkZlIDMwbSIpDQpsaWJyYXJ5KHJlc2hhcGUyKQ0KZmUgPSBzZXROYW1lcyhtZWx0KGZlMyksIGMoJ2tvbmNlbnRyYWNlJywnbWV0b2RhJykpDQoNCg0KbGlicmFyeShsYXR0aWNlKQ0KYndwbG90KGtvbmNlbnRyYWNlfm1ldG9kYSwgZGF0YT1mZSkNCg0KaGlzdCh4aWgseGxpbT1jKDEzLDE0KSxjb2w9J3NreWJsdWUnLGJvcmRlcj1UKQ0KaGlzdCh4MzAsYWRkPVQsY29sPXNjYWxlczo6YWxwaGEoJ3JlZCcsLjUpLGJvcmRlcj1UKQ0KDQoNCmxpYnJhcnkoUEFTV1IyKQ0KZWRhKCh4aWgteDMwKSwgdHJpbSA9IDAsIGRlYyA9IDMpDQoNCmxpYnJhcnkoczIweCkNCm5vcm1jaGVjaygoeGloLXgzMCkpDQoNCg0KbGlicmFyeShQYWlyZWREYXRhKQ0KDQpib3hwbG90KHhpaCx4MzApDQpwbG90KHhpaCx4MzAseGxpbT1jKDEzLDE0KSx5bGltPWMoMTMsMTQpKQ0KYWJsaW5lKDAsMSkNCg0Kc3VtbWFyeShwYWlyZWQoeGloLCB4MzApLHRyPTAuMikNCg0KZWZmZWN0LnNpemUocGFpcmVkKHhpaCwgeDMwKSx0cj0wLjIpDQoNCnNsaWRpbmdjaGFydChwYWlyZWQoeGloLCB4MzApKQ0KDQoNCiMgQ29oZW4gZCAoc3RhbmRhcmRpemVkIG1lYW4gZGlmZmVyZW5jZSkNCm1lYW4oeGloLXgzMCkvc2QoeGloLXgzMCkNCmxpYnJhcnkobHNyKQ0KZCA9IGNvaGVuc0QoeGloLCB4MzAsbWV0aG9kID0gInBhaXJlZCIpOyBkDQpsaWJyYXJ5KGVmZnNpemUpDQpjb2hlbi5kKHhpaCwgeDMwLCBwYWlyZWQgPSBUUlVFKQ0KDQpjb3IoeGloLCB4MzAsbWV0aG9kID0gInBlYXJzb24iKQ0KY29yKHhpaCwgeDMwLG1ldGhvZCA9ICJzcGVhcm1hbiIpDQoNCg0KIyB0LXRlc3QNCg0KdC50ZXN0KHhpaCwgeDMwLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQ0KIyB0LnRlc3QoZWxlbSB+IGxvbSwgZGF0YSA9IGRhdGEsIHBhaXJlZCA9IFRSVUUsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQoNCiMgQm9vdHN0cmFwIHQtVGVzdA0KbGlicmFyeShNS2luZmVyKQ0KYm9vdC50LnRlc3QoeGloLCB4MzAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsbXUgPSAwLCBwYWlyZWQgPSBUUlVFLCB2YXIuZXF1YWwgPSBGQUxTRSwgY29uZi5sZXZlbCA9IDAuOTUsIFIgPSA5OTk5LCBzeW1tZXRyaWMgPSBGQUxTRSkNCiMgYWx0ZXJuYXRpdmUgPSBjKCJ0d28uc2lkZWQiLCAibGVzcyIsICJncmVhdGVyIikNCg0KbGlicmFyeShDYXJsZXRvblN0YXRzKQ0KYm9vdFBhaXJlZCh4aWgsIHgzMCwgY29uZi5sZXZlbCA9IDAuOTUsIEIgPSAxMDAwMCxwbG90Lmhpc3QgPSBUUlVFLCBwbG90LnFxID0gRkFMU0UsIGxlZ2VuZC5sb2MgPSAidG9wcmlnaHQiLHgubmFtZSA9IGRlcGFyc2Uoc3Vic3RpdHV0ZSh4KSksIHkubmFtZSA9IGRlcGFyc2Uoc3Vic3RpdHV0ZSh5KSkpDQoNCiMgWXVlbidzIHRyaW1tZWQgbWVhbiB0ZXN0DQpsaWJyYXJ5KFBhaXJlZERhdGEpDQp5dWVuLnQudGVzdCh4aWgsIHgzMCwgdHIgPSAwLjIsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsIG11ID0gMCwgcGFpcmVkID0gVFJVRSwgY29uZi5sZXZlbCA9IDAuOTUpDQojIGFsdGVybmF0aXZlID0gYygidHdvLnNpZGVkIiwgImxlc3MiLCAiZ3JlYXRlciIpDQoNCg0KIyBDaGVudXYgcGFpcmVkIHNhbXBsZSB0LXRlc3QgcHJvIHplc2lrbWVub3UgZGlzdHJpYnVjaQ0KbGlicmFyeShFbnZTdGF0cykNCmNoZW5UVGVzdCh4aWgsIHgzMCAsIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiLCBtdSA9IDAsIHBhaXJlZCA9IFRSVUUsIGNvbmYubGV2ZWwgPSAwLjk1LCBjaS5tZXRob2QgPSAieiIpDQojIGFsdGVybmF0aXZlID0gYygibGVzcyIsICJncmVhdGVyIikNCiMgY2kubWV0aG9kID0gInoiLCAidCINCg0KbGlicmFyeShCb2xzdGFkKQ0KYmF5ZXMudC50ZXN0KHhpaCwgeDMwLGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsIG11ID0gMCwgcGFpcmVkID0gVFJVRSx2YXIuZXF1YWwgPSBUUlVFLCBjb25mLmxldmVsID0gMC45NSxwcmlvciA9ICJqZWZmcmV5cyIsIG0gPSBOVUxMLG4wID0gTlVMTCxzaWcubWVkID0gTlVMTCwga2FwcGEgPSAxLHNpZ21hUHJpb3IgPSAiY2hpc3EiLG5JdGVyID0gMTAwMDAsIG5CdXJuID0gMTAwMCkNCiMgYWx0ZXJuYXRpdmUgPSBjKCJ0d28uc2lkZWQiLCAibGVzcyIsICJncmVhdGVyIikNCiMgcHJpb3IgPSBjKCJqZWZmcmV5cyIsICJqb2ludC5jb25qIiksDQoNCiMjIFdpbGNveG9udXYgcGFyb3Z5IHRlc3QNCndpbGNveC50ZXN0KHhpaCwgeDMwLCBwYWlyZWQgPSBUUlVFLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLCBjb25mLmludCA9IFRSVUUpDQoNCmxpYnJhcnkoUGFpcmVkRGF0YSkNCndpbGNveC50ZXN0KHBhaXJlZCh4aWgsIHgzMCkpDQoNCiMjIG1lZGlhbm92eSAoem5hbWVua292eSkgcGFyb3Z5IHRlc3QNCmxpYnJhcnkoRW52U3RhdHMpDQpzaWduVGVzdCh4aWgsIHgzMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIiwgbXUgPSAwLCBwYWlyZWQgPSBUUlVFLCBjb25mLmxldmVsID0gMC45NSkNCg0KIyBQZXJtdXRhdGlvbiB0ZXN0IGZvciBwYWlyZWQgZGF0YQ0KbGlicmFyeShDYXJsZXRvblN0YXRzKQ0KcGVybVRlc3RQYWlyZWQoeGloLCB4MzAsIEIgPSA5OTk5LGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIsIHBsb3QuaGlzdCA9IFRSVUUsbGVnZW5kLmxvYyA9ICJ0b3ByaWdodCIsIHBsb3QucXEgPSBGQUxTRSx4Lm5hbWUgPSBkZXBhcnNlKHN1YnN0aXR1dGUoeCkpLCB5Lm5hbWUgPSBkZXBhcnNlKHN1YnN0aXR1dGUoeSkpKQ0KDQoNCnBsb3QoKHhpaCt4MzApLzIsICh4aWgteDMwKSkNCg0KbGlicmFyeShibGFuZHIpDQpiYXMyID0gYmxhbmRyLnN0YXRpc3RpY3MgKHhpaCx4MzAsIHNpZy5sZXZlbD0wLjk1KQ0KDQpiYXMyJGJpYXMNCmJhczIkYmlhc1VwcGVyQ0kNCmJhczIkYmlhc0xvd2VyQ0kNCg0KYmFzMiRyZWdyZXNzaW9uLmVxdWF0aW9uDQpjb3IoYmFzMiRtZWFucyxiYXMyJGRpZmZlcmVuY2VzKV4yICMgUl4yDQoNCmJsYW5kci5wbG90LnFxKGJhczIpDQoNCmJsYW5kci5kaXNwbGF5LmFuZC5kcmF3KG1ldGhvZDE9eGloLCBtZXRob2QyPXgzMCwgcGxvdHRlciA9ICJnZ3Bsb3QiLG1ldGhvZDFuYW1lID0gIklobmVkIiwgbWV0aG9kMm5hbWUgPSAiMzAgbWluLiIscGxvdFRpdGxlID0gIkJsYW5kLUFsdG1hbiBwbG90IGZvciBjb21wYXJpc29uIG9mIDIgbWV0aG9kcyIsc2lnLmxldmVsID0gMC45NSwgYW5ub3RhdGUgPSBUUlVFLCBjaURpc3BsYXkgPSBUUlVFLGNpU2hhZGluZyA9IFRSVUUsIG5vcm1hbExvdyA9IEZBTFNFLCBub3JtYWxIaWdoID0gRkFMU0UsbG93ZXN0X3lfYXhpcyA9IEZBTFNFLCBoaWdoZXN0X3lfYXhpcyA9IEZBTFNFLCBwb2ludF9zaXplID0gMikNCg0KDQpgYGANCg==