Prepare Data:

rm(list = ls())
library("rugarch")
library("fGarch")
library("MASS")
library("ismev")
# library("lmom")
# library("QRM")
library("skewt")
library("zoo")
library("plotrix")
source("~/OneDrive - INSEAD/SkewEllipt/Code_Update/Rfns.R")
setwd("~/OneDrive - INSEAD/SkewEllipt/Code_Update/Natalia/out500/")
##=========================================================
## Backtesting CoVaR
##=========================================================
dat = fread("~/OneDrive - INSEAD/SkewEllipt/Code_Update/Natalia/Ret_data.csv") # raw data file (1962/07/02 - 2017/07/31)
dat = dat[,`:=`(RET=as.numeric(as.character(RET)), SP500 = as.numeric(as.character(SP500)))]
dat = dat[!is.na(RET)]
dat = unique(dat, by = c("TICKER", "date") )
setnames(dat, "RET", "r")
r.KO = dat[TICKER == 'KO', list(date, TICKER, r, SP500)]
r.GE = dat[TICKER == 'GE', list(date, TICKER, r, SP500)]
r.BA = dat[TICKER == 'BA', list(date, TICKER, r, SP500)]
r.DIS = dat[TICKER == 'DIS', list(date, TICKER, r, SP500)]
dat.indices <- unique(data.frame(dat$date,dat$Ret_M,dat$SP500))
colnames(dat.indices)<-c("date","retM","sp500")
rM <- zoo(x=dat.indices$retM,order.by = strptime(dat.indices$date,"%Y%m%d"))
rSP<- zoo(x=dat.indices$sp500,order.by = strptime(dat.indices$date,"%Y%m%d"))
load("CoVaR.RDATA")
# attributes(out)
##columns are 95% CoVaR by EVT method, 99% CoVaR by EVT method and 95% CoVaR by empirical method
covar.KO <- out$CoVaR.KO
covar.BA <- out$CoVaR.BA
covar.DIS <- out$CoVaR.DIS
covar.GE <- out$CoVaR.GE

Out-of-sample Test

We calcualte one-day ahead predicted VaR and CoVaR using past 500 days (rolloing window) and then match with loss series. Specifically, we use data from day 1 to 500 to fit Garch model and get residual series and predicted mu and sigmal. Then we calculate one-day ahead predicted VaR and CoVaR, that is day 501 VaR and CoVaR.

## identify subsample where L[t+1]^j > VaR[t+1]^j
n=dim(covar.KO)[1]
end = nrow(r.KO) + 1
setwd("~/OneDrive - INSEAD/SkewEllipt/Code_Update/Natalia/out500/")
load("outKO.RDATA")
var.KO <- out.p$stEVT[,2:3]
loss.KO <- -r.KO$r[(end-n):(end-1)]
load("outBA.RDATA")
var.BA <- out.p$stEVT[,2:3]
loss.BA <- -r.BA$r[(end-n):(end-1)]
load("outDIS.RDATA")
var.DIS <- out.p$stEVT[,2:3]
loss.DIS <- -r.DIS$r[(end-n):(end-1)]
load("outGE.RDATA")
var.GE <- out.p$stEVT[,2:3]
loss.GE <- -r.GE$r[(end-n):(end-1)]
y <- loss.DIS
rmat <- var.DIS
covar <- covar.DIS
yI <- as.vector(-rSP[(end-n):(end-1)])

We check the performance of predicted VaR:

k=dim(rmat)[2] # number of methods/cases
ymat = matrix(rep(y, k), ncol = k, byrow=FALSE)
hmat = (ymat > rmat)
apply(hmat,2,"sum",na.rm=T)/n*100
[1] 5.162738 1.234568

We check the performance of predicted CoVaR:

r.evt.sub95 <- subset(covar[,1],hmat[,1])
r.evt.sub99 <- subset(covar[,2],hmat[,2])
r.emp.sub95 <- subset(covar[,3],hmat[,1])
r.emp.sub99 <- subset(covar[,4],hmat[,2])
r.fp.sub95 <-  subset(covar[,5],hmat[,1])
r.fp.sub99 <-  subset(covar[,6],hmat[,2])
## Checking % violations of CoVaR by the index losses
yI.sub95 <- as.numeric(subset(yI, hmat[,1]))
yI.sub99 <- as.numeric(subset(yI, hmat[,2]))
# Remove NA values
r.sub95 = rbind(r.evt.sub95,r.emp.sub95, r.fp.sub95)
ind.na95 = which( (is.na(apply(r.sub95,2,sum))) )
r.sub99 = rbind(r.evt.sub99,r.emp.sub99, r.fp.sub99)
ind.na99 = which((is.na(apply(r.sub99,2,sum))) )
if (length(ind.na95)>0){
  r.evt.sub95 <- r.evt.sub95[-ind.na95]
  r.emp.sub95 <- r.emp.sub95[-ind.na95]
  r.fp.sub95 <- r.fp.sub95[-ind.na95]
  yI.sub95 <- yI.sub95[-ind.na95]
}
if (length(ind.na99)>0){
  r.evt.sub99 <- r.evt.sub99[-ind.na99]
  r.emp.sub99 <- r.emp.sub99[-ind.na99]
  r.fp.sub99 <- r.fp.sub99[-ind.na99]
  yI.sub99 <- yI.sub99[-ind.na99]
}
m95 <- length(yI.sub95) #sub-sample size for q=0.95
m99 <- length(yI.sub99) #sub-sample size for q=0.99
round(c(sum(yI.sub95>r.evt.sub95)/m95*100,sum(yI.sub95>r.emp.sub95)/m95*100, sum(yI.sub95>r.fp.sub95)/m95*100, sum(yI.sub99>r.evt.sub99)/m99*100, sum(yI.sub99>r.emp.sub99)/m99*100, sum(yI.sub99>r.fp.sub99)/m99*100),2)
[1] 13.69  9.38  7.74  4.35 24.22  3.11
The EVT method does not perform well for 95% CoVaR estimation but relatively good for 99% CoVaR estimation. Simple CCT is consistent with this result, but comparative backtesting and TLM suggests that FP is slightly better than EVT. In summary, EVT and FP is significantly better than empirical method at 10% level for estimation 99% CoVaR, but EVT and FP are quite similar.
cct <- matrix(nrow=3, ncol=2) # simple & general CCT
tmp <- cct.2s.VaR(x=yI.sub95, r=r.evt.sub95,lev=0.95); cct[1,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.2s.VaR(x=yI.sub95, r=r.emp.sub95,lev=0.95); cct[2,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.2s.VaR(x=yI.sub95, r=r.fp.sub95,lev=0.95); cct[3,]<-c(tmp$pv.avg,tmp$pv.cond)
round(cct,3)
      [,1]  [,2]
[1,] 0.000 0.000
[2,] 0.000 0.001
[3,] 0.008 0.013
# tmp <- cct.2s.VaR(x=yI.sub99, r=r.evt.sub99,lev=0.99); cct[1,]<-c(tmp$pv.avg,tmp$pv.cond)
# tmp <- cct.2s.VaR(x=yI.sub99, r=r.emp.sub99,lev=0.99); cct[2,]<-c(tmp$pv.avg,tmp$pv.cond)
# tmp <- cct.2s.VaR(x=yI.sub99, r=r.fp.sub99,lev=0.99); cct[3,]<-c(tmp$pv.avg,tmp$pv.cond)
# round(cct,3)
## ONE-SIDED TEST of super-calibration as in Basel Accord
cct.1s <- matrix(nrow=3, ncol=2) # simple & general one-sided CCT of super-calibration
tmp <- cct.1s.VaR(x=yI.sub95, r=r.evt.sub95,lev=0.95); cct.1s[1,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.1s.VaR(x=yI.sub95, r=r.emp.sub95,lev=0.95); cct.1s[2,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.1s.VaR(x=yI.sub95, r=r.fp.sub95,lev=0.95); cct.1s[3,]<-c(tmp$pv.avg,tmp$pv.cond)
round(cct.1s,3)
      [,1]  [,2]
[1,] 0.000 0.000
[2,] 0.000 0.000
[3,] 0.004 0.012
cct.1s <- matrix(nrow=3, ncol=2) # simple & general one-sided CCT of super-calibration
tmp <- cct.1s.VaR(x=yI.sub99, r=r.evt.sub99,lev=0.99); cct.1s[1,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.1s.VaR(x=yI.sub99, r=r.emp.sub99,lev=0.99); cct.1s[2,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.1s.VaR(x=yI.sub99, r=r.fp.sub99,lev=0.99); cct.1s[3,]<-c(tmp$pv.avg,tmp$pv.cond)
round(cct.1s,3)
      [,1]  [,2]
[1,] 0.020 0.060
[2,] 0.000 0.000
[3,] 0.063 0.149
## Comparative backtesting
## q=.95
smat <- matrix(nrow=3, ncol=1)
smat[1,1] <- mean(sfVaR(r=r.evt.sub95,x=yI.sub95,a=0.95,h=1))
smat[2,1] <- mean(sfVaR(r=r.emp.sub95,x=yI.sub95,a=0.95,h=1))
smat[3,1] <- mean(sfVaR(r=r.fp.sub95,x=yI.sub95,a=0.95,h=1))
apply(smat,2,"rank")
     [,1]
[1,]    3
[2,]    1
[3,]    2
## q=.99
smat <- matrix(nrow=3, ncol=1)
smat[1,1] <- mean(sfVaR(r=r.evt.sub99,x=yI.sub99,a=0.99,h=1))
smat[2,1] <- mean(sfVaR(r=r.emp.sub99,x=yI.sub99,a=0.99,h=1))
smat[3,1] <- mean(sfVaR(r=r.fp.sub99,x=yI.sub99,a=0.99,h=1))
apply(smat,2,"rank")
     [,1]
[1,]    1
[2,]    3
[3,]    2
## TLM
rm=1
tlm95 <- TLMfn(r=rbind(r.evt.sub95,r.emp.sub95,r.fp.sub95), y=yI.sub95, rm=rm, lev=0.95,h=1)
plotTLM(tlm95$TLM10, rm=1, lev=0.95,method=c("evt","emp","st"))

tlm99 <- TLMfn(r=rbind(r.evt.sub99,r.emp.sub99,r.fp.sub99), y=yI.sub99, rm=rm, lev=0.99,h=1)
plotTLM(tlm99$TLM10, rm=1, lev=0.99,method=c("evt","emp","st"))

In-Sample Test

However, we can show that movement in CoVaR is driven by the predict sigmal from Garch model, and the predicted sigmal shares the similar pattern of lagged loss series. The figure blow plots subsample with 100 days for SP500 loss series. As shown in the figure, the peaks of sigma_SP500 are in line with CoVaR from EVT and FP, but are one-period head of loss series (see x-axis 80-100). This result comes from the fact that predicted sigma is heavily affected by the most recent data. When there is a high reutrn (or loss) today, the predicted volatility will be very high tomorrow.

plot(covar[5800:5900,1], type = "l", col = "blue", ylim =  c(-0.1,0.2), lty = 3, ylab = "Return")
points(covar[5800:5900,5], type = "l", col = "black", lty = 1)
points(yI[5800:5900], type = "l", col = "red", lty = 2)
setwd("~/OneDrive - INSEAD/SkewEllipt/Code_Update/Natalia/out500/")
load("outSP500.RDATA")
points(out.p$sigt.st[5800:5900], type = "l", col = 'green', lty = 4)
legend("topright", legend = c("EVT", "FP", "SP500","sigma_SP500"), col = c("blue", "black", "red","green"), lty = c(3,1,2,4))

Similarly, if we plot subsample in which DIS loss is beyond 99% VaR, the peaks of SP00 and CoVaR from different methods are not aligned.

plot(r.fp.sub99, type = "l", col = "blue", ylim =  c(-0.03,0.3), lty = 3, ylab = "Return")
points(yI.sub99, type = "l", col = "black", lty = 1)
points(r.evt.sub99, type = "l", col = "red", lty = 2)
legend("topright", legend = c("FP", "EVT", "Loss"), col = c("blue", "red", "black"), lty = c(3,2,1))

If we shift Loss series one-day ahead (or shift CoVaR one day one-day backward), then the peaks are aligned. Essentially, this is in-sample analysis. We compare CoVaR estiamted using day 1 to day 500 data with day 500 loss.

## identify subsample where L[t+1]^j > VaR[t+1]^j
n=dim(covar.KO)[1]
end = nrow(r.KO)
loss.DIS <- -r.DIS$r[(end-n):(end-1)]
y <- loss.DIS
yI <- as.vector(-rSP[(end-n):(end-1)])
plot(covar[5800:5900,1], type = "l", col = "blue", ylim =  c(-0.1,0.2), lty = 3, ylab = "Return")
points(covar[5800:5900,5], type = "l", col = "black", lty = 1)
points(yI[5800:5900], type = "l", col = "red", lty = 2)
setwd("~/OneDrive - INSEAD/SkewEllipt/Code_Update/Natalia/out500/")
load("outSP500.RDATA")
points(out.p$sigt.st[5800:5900], type = "l", col = 'green', lty = 4)
legend("topright", legend = c("EVT", "FP", "SP500","sigma_SP500"), col = c("blue", "black", "red","green"), lty = c(3,1,2,4))

Now, we repeat all the analysis for in-sample CoVaR.

k=dim(rmat)[2] # number of methods/cases
ymat = matrix(rep(y, k), ncol = k, byrow=FALSE)
hmat = (ymat > rmat)
apply(hmat,2,"sum",na.rm=T)/n*100
[1] 3.7186682 0.4489338
r.evt.sub95 <- subset(covar[,1],hmat[,1])
r.evt.sub99 <- subset(covar[,2],hmat[,2])
r.emp.sub95 <- subset(covar[,3],hmat[,1])
r.emp.sub99 <- subset(covar[,4],hmat[,2])
r.fp.sub95 <-  subset(covar[,5],hmat[,1])
r.fp.sub99 <-  subset(covar[,6],hmat[,2])
## Checking % violations of CoVaR by the index losses
yI.sub95 <- as.numeric(subset(yI, hmat[,1]))
yI.sub99 <- as.numeric(subset(yI, hmat[,2]))
# Remove NA values
r.sub95 = rbind(r.evt.sub95,r.emp.sub95, r.fp.sub95)
ind.na95 = which( (is.na(apply(r.sub95,2,sum))) )
r.sub99 = rbind(r.evt.sub99,r.emp.sub99, r.fp.sub99)
ind.na99 = which((is.na(apply(r.sub99,2,sum))) )
if (length(ind.na95)>0){
  r.evt.sub95 <- r.evt.sub95[-ind.na95]
  r.emp.sub95 <- r.emp.sub95[-ind.na95]
  r.fp.sub95 <- r.fp.sub95[-ind.na95]
  yI.sub95 <- yI.sub95[-ind.na95]
}
if (length(ind.na99)>0){
  r.evt.sub99 <- r.evt.sub99[-ind.na99]
  r.emp.sub99 <- r.emp.sub99[-ind.na99]
  r.fp.sub99 <- r.fp.sub99[-ind.na99]
  yI.sub99 <- yI.sub99[-ind.na99]
}
m95 <- length(yI.sub95) #sub-sample size for q=0.95
m99 <- length(yI.sub99) #sub-sample size for q=0.99
round(c(sum(yI.sub95>r.evt.sub95)/m95*100,sum(yI.sub95>r.emp.sub95)/m95*100, sum(yI.sub95>r.fp.sub95)/m95*100, sum(yI.sub99>r.evt.sub99)/m99*100, sum(yI.sub99>r.emp.sub99)/m99*100, sum(yI.sub99>r.fp.sub99)/m99*100),2)
[1] 4.99 2.08 3.12 0.00 0.00 0.00

From above numbers, EVT looks work quite well for in-sample analysis. However, comparative backtesting and TLM seem to suggest that EVT is worse than empirical method. I do not understand why we get different resutls from different tests.

cct <- matrix(nrow=3, ncol=2) # simple & general CCT
tmp <- cct.2s.VaR(x=yI.sub95, r=r.evt.sub95,lev=0.95); cct[1,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.2s.VaR(x=yI.sub95, r=r.emp.sub95,lev=0.95); cct[2,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.2s.VaR(x=yI.sub95, r=r.fp.sub95,lev=0.95); cct[3,]<-c(tmp$pv.avg,tmp$pv.cond)
round(cct,3)
      [,1]  [,2]
[1,] 0.992 0.513
[2,] 0.000 0.000
[3,] 0.018 0.011
# tmp <- cct.2s.VaR(x=yI.sub99, r=r.evt.sub99,lev=0.99); cct[1,]<-c(tmp$pv.avg,tmp$pv.cond)
# tmp <- cct.2s.VaR(x=yI.sub99, r=r.emp.sub99,lev=0.99); cct[2,]<-c(tmp$pv.avg,tmp$pv.cond)
# tmp <- cct.2s.VaR(x=yI.sub99, r=r.fp.sub99,lev=0.99); cct[3,]<-c(tmp$pv.avg,tmp$pv.cond)
# round(cct,3)
## ONE-SIDED TEST of super-calibration as in Basel Accord
cct.1s <- matrix(nrow=3, ncol=2) # simple & general one-sided CCT of super-calibration
tmp <- cct.1s.VaR(x=yI.sub95, r=r.evt.sub95,lev=0.95); cct.1s[1,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.1s.VaR(x=yI.sub95, r=r.emp.sub95,lev=0.95); cct.1s[2,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.1s.VaR(x=yI.sub95, r=r.fp.sub95,lev=0.95); cct.1s[3,]<-c(tmp$pv.avg,tmp$pv.cond)
round(cct.1s,3)
      [,1] [,2]
[1,] 0.504    1
[2,] 1.000    1
[3,] 0.991    1
cct.1s <- matrix(nrow=3, ncol=2) # simple & general one-sided CCT of super-calibration
tmp <- cct.1s.VaR(x=yI.sub99, r=r.evt.sub99,lev=0.99); cct.1s[1,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.1s.VaR(x=yI.sub99, r=r.emp.sub99,lev=0.99); cct.1s[2,]<-c(tmp$pv.avg,tmp$pv.cond)
tmp <- cct.1s.VaR(x=yI.sub99, r=r.fp.sub99,lev=0.99); cct.1s[3,]<-c(tmp$pv.avg,tmp$pv.cond)
round(cct.1s,3)
     [,1] [,2]
[1,]    1    1
[2,]    1    1
[3,]    1    1
## Comparative backtesting
## q=.95
smat <- matrix(nrow=3, ncol=1)
smat[1,1] <- mean(sfVaR(r=r.evt.sub95,x=yI.sub95,a=0.95,h=1))
smat[2,1] <- mean(sfVaR(r=r.emp.sub95,x=yI.sub95,a=0.95,h=1))
smat[3,1] <- mean(sfVaR(r=r.fp.sub95,x=yI.sub95,a=0.95,h=1))
apply(smat,2,"rank")
     [,1]
[1,]    2
[2,]    1
[3,]    3
## q=.99
smat <- matrix(nrow=3, ncol=1)
smat[1,1] <- mean(sfVaR(r=r.evt.sub99,x=yI.sub99,a=0.99,h=1))
smat[2,1] <- mean(sfVaR(r=r.emp.sub99,x=yI.sub99,a=0.99,h=1))
smat[3,1] <- mean(sfVaR(r=r.fp.sub99,x=yI.sub99,a=0.99,h=1))
apply(smat,2,"rank")
     [,1]
[1,]    3
[2,]    1
[3,]    2
## TLM
rm=1
tlm95 <- TLMfn(r=rbind(r.evt.sub95,r.emp.sub95,r.fp.sub95), y=yI.sub95, rm=rm, lev=0.95,h=1)
plotTLM(tlm95$TLM10, rm=1, lev=0.95,method=c("evt","emp","st"))

tlm99 <- TLMfn(r=rbind(r.evt.sub99,r.emp.sub99,r.fp.sub99), y=yI.sub99, rm=rm, lev=0.99,h=1)
plotTLM(tlm99$TLM10, rm=1, lev=0.99,method=c("evt","emp","st"))

plot(r.fp.sub99, type = "l", col = "blue", ylim =  c(-0.03,0.4), lty = 3, ylab = "Return")
points(yI.sub99, type = "l", col = "black", lty = 1)
points(r.evt.sub99, type = "l", col = "red", lty = 2)
legend("topright", legend = c("FP", "EVT", "Loss"), col = c("blue", "red", "black"), lty = c(3,2,1))

plot(yI, ylab="", ylim=c(-.12,0.4), col="gray",xlab="", main="DIS", cex.main=0.8, lty = 1)
lines(time(yI),covar.DIS[,1], col="red", lty = 2)
lines(time(yI),covar.DIS[,5], col="black", lty = 3)
lines(time(yI),covar.DIS[,3], col="green", lty = 4)
legend("topleft", legend = c("SP500", "EVT", "FP", "HS"), col = c("grey", "red", "black", "green"), lty = c(1,2,3,4))

LS0tCnRpdGxlOiAiQ29WYVIgLS0gRElTIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIyMgUHJlcGFyZSBEYXRhOgoKYGBge3IgaW5jbHVkZT1UUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmc9RkFMU0V9CnJtKGxpc3QgPSBscygpKQpsaWJyYXJ5KCJydWdhcmNoIikKbGlicmFyeSgiZkdhcmNoIikKbGlicmFyeSgiTUFTUyIpCmxpYnJhcnkoImlzbWV2IikKIyBsaWJyYXJ5KCJsbW9tIikKIyBsaWJyYXJ5KCJRUk0iKQpsaWJyYXJ5KCJza2V3dCIpCmxpYnJhcnkoInpvbyIpCmxpYnJhcnkoInBsb3RyaXgiKQoKc291cmNlKCJ+L09uZURyaXZlIC0gSU5TRUFEL1NrZXdFbGxpcHQvQ29kZV9VcGRhdGUvUmZucy5SIikKc2V0d2QoIn4vT25lRHJpdmUgLSBJTlNFQUQvU2tld0VsbGlwdC9Db2RlX1VwZGF0ZS9OYXRhbGlhL291dDUwMC8iKQojIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIyBCYWNrdGVzdGluZyBDb1ZhUgojIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKZGF0ID0gZnJlYWQoIn4vT25lRHJpdmUgLSBJTlNFQUQvU2tld0VsbGlwdC9Db2RlX1VwZGF0ZS9OYXRhbGlhL1JldF9kYXRhLmNzdiIpICMgcmF3IGRhdGEgZmlsZSAoMTk2Mi8wNy8wMiAtIDIwMTcvMDcvMzEpCmRhdCA9IGRhdFssYDo9YChSRVQ9YXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoUkVUKSksIFNQNTAwID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoU1A1MDApKSldCmRhdCA9IGRhdFshaXMubmEoUkVUKV0KZGF0ID0gdW5pcXVlKGRhdCwgYnkgPSBjKCJUSUNLRVIiLCAiZGF0ZSIpICkKc2V0bmFtZXMoZGF0LCAiUkVUIiwgInIiKQpyLktPID0gZGF0W1RJQ0tFUiA9PSAnS08nLCBsaXN0KGRhdGUsIFRJQ0tFUiwgciwgU1A1MDApXQpyLkdFID0gZGF0W1RJQ0tFUiA9PSAnR0UnLCBsaXN0KGRhdGUsIFRJQ0tFUiwgciwgU1A1MDApXQpyLkJBID0gZGF0W1RJQ0tFUiA9PSAnQkEnLCBsaXN0KGRhdGUsIFRJQ0tFUiwgciwgU1A1MDApXQpyLkRJUyA9IGRhdFtUSUNLRVIgPT0gJ0RJUycsIGxpc3QoZGF0ZSwgVElDS0VSLCByLCBTUDUwMCldCgpkYXQuaW5kaWNlcyA8LSB1bmlxdWUoZGF0YS5mcmFtZShkYXQkZGF0ZSxkYXQkUmV0X00sZGF0JFNQNTAwKSkKY29sbmFtZXMoZGF0LmluZGljZXMpPC1jKCJkYXRlIiwicmV0TSIsInNwNTAwIikKck0gPC0gem9vKHg9ZGF0LmluZGljZXMkcmV0TSxvcmRlci5ieSA9IHN0cnB0aW1lKGRhdC5pbmRpY2VzJGRhdGUsIiVZJW0lZCIpKQpyU1A8LSB6b28oeD1kYXQuaW5kaWNlcyRzcDUwMCxvcmRlci5ieSA9IHN0cnB0aW1lKGRhdC5pbmRpY2VzJGRhdGUsIiVZJW0lZCIpKQoKbG9hZCgiQ29WYVIuUkRBVEEiKQojIGF0dHJpYnV0ZXMob3V0KQoKIyNjb2x1bW5zIGFyZSA5NSUgQ29WYVIgYnkgRVZUIG1ldGhvZCwgOTklIENvVmFSIGJ5IEVWVCBtZXRob2QgYW5kIDk1JSBDb1ZhUiBieSBlbXBpcmljYWwgbWV0aG9kCgpjb3Zhci5LTyA8LSBvdXQkQ29WYVIuS08KY292YXIuQkEgPC0gb3V0JENvVmFSLkJBCmNvdmFyLkRJUyA8LSBvdXQkQ29WYVIuRElTCmNvdmFyLkdFIDwtIG91dCRDb1ZhUi5HRQpgYGAKCgojIyMgT3V0LW9mLXNhbXBsZSBUZXN0CldlIGNhbGN1YWx0ZSBvbmUtZGF5IGFoZWFkIHByZWRpY3RlZCBWYVIgYW5kIENvVmFSIHVzaW5nIHBhc3QgNTAwIGRheXMgKHJvbGxvaW5nIHdpbmRvdykgYW5kIHRoZW4gbWF0Y2ggd2l0aCBsb3NzIHNlcmllcy4gU3BlY2lmaWNhbGx5LCB3ZSB1c2UgZGF0YSBmcm9tIGRheSAxIHRvIDUwMCB0byBmaXQgR2FyY2ggbW9kZWwgYW5kIGdldCByZXNpZHVhbCBzZXJpZXMgYW5kIHByZWRpY3RlZCBtdSBhbmQgc2lnbWFsLiBUaGVuIHdlIGNhbGN1bGF0ZSBvbmUtZGF5IGFoZWFkIHByZWRpY3RlZCBWYVIgYW5kIENvVmFSLCB0aGF0IGlzIGRheSA1MDEgVmFSIGFuZCBDb1ZhUi4KCgpgYGB7cixtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMjIGlkZW50aWZ5IHN1YnNhbXBsZSB3aGVyZSBMW3QrMV1eaiA+IFZhUlt0KzFdXmoKbj1kaW0oY292YXIuS08pWzFdCmVuZCA9IG5yb3coci5LTykgKyAxCnNldHdkKCJ+L09uZURyaXZlIC0gSU5TRUFEL1NrZXdFbGxpcHQvQ29kZV9VcGRhdGUvTmF0YWxpYS9vdXQ1MDAvIikKbG9hZCgib3V0S08uUkRBVEEiKQp2YXIuS08gPC0gb3V0LnAkc3RFVlRbLDI6M10KbG9zcy5LTyA8LSAtci5LTyRyWyhlbmQtbik6KGVuZC0xKV0KCmxvYWQoIm91dEJBLlJEQVRBIikKdmFyLkJBIDwtIG91dC5wJHN0RVZUWywyOjNdCmxvc3MuQkEgPC0gLXIuQkEkclsoZW5kLW4pOihlbmQtMSldCgpsb2FkKCJvdXRESVMuUkRBVEEiKQp2YXIuRElTIDwtIG91dC5wJHN0RVZUWywyOjNdCmxvc3MuRElTIDwtIC1yLkRJUyRyWyhlbmQtbik6KGVuZC0xKV0KCmxvYWQoIm91dEdFLlJEQVRBIikKdmFyLkdFIDwtIG91dC5wJHN0RVZUWywyOjNdCmxvc3MuR0UgPC0gLXIuR0UkclsoZW5kLW4pOihlbmQtMSldCmBgYAoKYGBge3J9CnkgPC0gbG9zcy5ESVMKcm1hdCA8LSB2YXIuRElTCmNvdmFyIDwtIGNvdmFyLkRJUwp5SSA8LSBhcy52ZWN0b3IoLXJTUFsoZW5kLW4pOihlbmQtMSldKQpgYGAKCldlIGNoZWNrIHRoZSBwZXJmb3JtYW5jZSBvZiBwcmVkaWN0ZWQgVmFSOgpgYGB7cn0Kaz1kaW0ocm1hdClbMl0gIyBudW1iZXIgb2YgbWV0aG9kcy9jYXNlcwp5bWF0ID0gbWF0cml4KHJlcCh5LCBrKSwgbmNvbCA9IGssIGJ5cm93PUZBTFNFKQpobWF0ID0gKHltYXQgPiBybWF0KQoKYXBwbHkoaG1hdCwyLCJzdW0iLG5hLnJtPVQpL24qMTAwCmBgYAoKV2UgY2hlY2sgdGhlIHBlcmZvcm1hbmNlIG9mIHByZWRpY3RlZCBDb1ZhUjoKYGBge3J9CnIuZXZ0LnN1Yjk1IDwtIHN1YnNldChjb3ZhclssMV0saG1hdFssMV0pCnIuZXZ0LnN1Yjk5IDwtIHN1YnNldChjb3ZhclssMl0saG1hdFssMl0pCnIuZW1wLnN1Yjk1IDwtIHN1YnNldChjb3ZhclssM10saG1hdFssMV0pCnIuZW1wLnN1Yjk5IDwtIHN1YnNldChjb3ZhclssNF0saG1hdFssMl0pCnIuZnAuc3ViOTUgPC0gIHN1YnNldChjb3ZhclssNV0saG1hdFssMV0pCnIuZnAuc3ViOTkgPC0gIHN1YnNldChjb3ZhclssNl0saG1hdFssMl0pCgojIyBDaGVja2luZyAlIHZpb2xhdGlvbnMgb2YgQ29WYVIgYnkgdGhlIGluZGV4IGxvc3Nlcwp5SS5zdWI5NSA8LSBhcy5udW1lcmljKHN1YnNldCh5SSwgaG1hdFssMV0pKQp5SS5zdWI5OSA8LSBhcy5udW1lcmljKHN1YnNldCh5SSwgaG1hdFssMl0pKQoKIyBSZW1vdmUgTkEgdmFsdWVzCnIuc3ViOTUgPSByYmluZChyLmV2dC5zdWI5NSxyLmVtcC5zdWI5NSwgci5mcC5zdWI5NSkKaW5kLm5hOTUgPSB3aGljaCggKGlzLm5hKGFwcGx5KHIuc3ViOTUsMixzdW0pKSkgKQoKci5zdWI5OSA9IHJiaW5kKHIuZXZ0LnN1Yjk5LHIuZW1wLnN1Yjk5LCByLmZwLnN1Yjk5KQppbmQubmE5OSA9IHdoaWNoKChpcy5uYShhcHBseShyLnN1Yjk5LDIsc3VtKSkpICkKCmlmIChsZW5ndGgoaW5kLm5hOTUpPjApewogIHIuZXZ0LnN1Yjk1IDwtIHIuZXZ0LnN1Yjk1Wy1pbmQubmE5NV0KICByLmVtcC5zdWI5NSA8LSByLmVtcC5zdWI5NVstaW5kLm5hOTVdCiAgci5mcC5zdWI5NSA8LSByLmZwLnN1Yjk1Wy1pbmQubmE5NV0KICB5SS5zdWI5NSA8LSB5SS5zdWI5NVstaW5kLm5hOTVdCn0KaWYgKGxlbmd0aChpbmQubmE5OSk+MCl7CiAgci5ldnQuc3ViOTkgPC0gci5ldnQuc3ViOTlbLWluZC5uYTk5XQogIHIuZW1wLnN1Yjk5IDwtIHIuZW1wLnN1Yjk5Wy1pbmQubmE5OV0KICByLmZwLnN1Yjk5IDwtIHIuZnAuc3ViOTlbLWluZC5uYTk5XQogIHlJLnN1Yjk5IDwtIHlJLnN1Yjk5Wy1pbmQubmE5OV0KfQoKCm05NSA8LSBsZW5ndGgoeUkuc3ViOTUpICNzdWItc2FtcGxlIHNpemUgZm9yIHE9MC45NQptOTkgPC0gbGVuZ3RoKHlJLnN1Yjk5KSAjc3ViLXNhbXBsZSBzaXplIGZvciBxPTAuOTkKCnJvdW5kKGMoc3VtKHlJLnN1Yjk1PnIuZXZ0LnN1Yjk1KS9tOTUqMTAwLHN1bSh5SS5zdWI5NT5yLmVtcC5zdWI5NSkvbTk1KjEwMCwgc3VtKHlJLnN1Yjk1PnIuZnAuc3ViOTUpL205NSoxMDAsIHN1bSh5SS5zdWI5OT5yLmV2dC5zdWI5OSkvbTk5KjEwMCwgc3VtKHlJLnN1Yjk5PnIuZW1wLnN1Yjk5KS9tOTkqMTAwLCBzdW0oeUkuc3ViOTk+ci5mcC5zdWI5OSkvbTk5KjEwMCksMikKYGBgCgojIyMjIyBUaGUgRVZUIG1ldGhvZCBkb2VzIG5vdCBwZXJmb3JtIHdlbGwgZm9yIDk1JSBDb1ZhUiBlc3RpbWF0aW9uIGJ1dCByZWxhdGl2ZWx5IGdvb2QgZm9yIDk5JSBDb1ZhUiBlc3RpbWF0aW9uLiBTaW1wbGUgQ0NUIGlzIGNvbnNpc3RlbnQgd2l0aCB0aGlzIHJlc3VsdCwgYnV0IGNvbXBhcmF0aXZlIGJhY2t0ZXN0aW5nICBhbmQgVExNIHN1Z2dlc3RzIHRoYXQgRlAgaXMgc2xpZ2h0bHkgYmV0dGVyIHRoYW4gRVZULiAgSW4gc3VtbWFyeSwgRVZUIGFuZCBGUCBpcyBzaWduaWZpY2FudGx5IGJldHRlciB0aGFuIGVtcGlyaWNhbCBtZXRob2QgYXQgMTAlIGxldmVsIGZvciBlc3RpbWF0aW9uIDk5JSBDb1ZhUiwgYnV0IEVWVCBhbmQgRlAgYXJlIHF1aXRlIHNpbWlsYXIuCgoKYGBge3J9CmNjdCA8LSBtYXRyaXgobnJvdz0zLCBuY29sPTIpICMgc2ltcGxlICYgZ2VuZXJhbCBDQ1QKCnRtcCA8LSBjY3QuMnMuVmFSKHg9eUkuc3ViOTUsIHI9ci5ldnQuc3ViOTUsbGV2PTAuOTUpOyBjY3RbMSxdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCnRtcCA8LSBjY3QuMnMuVmFSKHg9eUkuc3ViOTUsIHI9ci5lbXAuc3ViOTUsbGV2PTAuOTUpOyBjY3RbMixdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCnRtcCA8LSBjY3QuMnMuVmFSKHg9eUkuc3ViOTUsIHI9ci5mcC5zdWI5NSxsZXY9MC45NSk7IGNjdFszLF08LWModG1wJHB2LmF2Zyx0bXAkcHYuY29uZCkKcm91bmQoY2N0LDMpCgojIHRtcCA8LSBjY3QuMnMuVmFSKHg9eUkuc3ViOTksIHI9ci5ldnQuc3ViOTksbGV2PTAuOTkpOyBjY3RbMSxdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCiMgdG1wIDwtIGNjdC4ycy5WYVIoeD15SS5zdWI5OSwgcj1yLmVtcC5zdWI5OSxsZXY9MC45OSk7IGNjdFsyLF08LWModG1wJHB2LmF2Zyx0bXAkcHYuY29uZCkKIyB0bXAgPC0gY2N0LjJzLlZhUih4PXlJLnN1Yjk5LCByPXIuZnAuc3ViOTksbGV2PTAuOTkpOyBjY3RbMyxdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCiMgcm91bmQoY2N0LDMpCgoKIyMgT05FLVNJREVEIFRFU1Qgb2Ygc3VwZXItY2FsaWJyYXRpb24gYXMgaW4gQmFzZWwgQWNjb3JkCmNjdC4xcyA8LSBtYXRyaXgobnJvdz0zLCBuY29sPTIpICMgc2ltcGxlICYgZ2VuZXJhbCBvbmUtc2lkZWQgQ0NUIG9mIHN1cGVyLWNhbGlicmF0aW9uCnRtcCA8LSBjY3QuMXMuVmFSKHg9eUkuc3ViOTUsIHI9ci5ldnQuc3ViOTUsbGV2PTAuOTUpOyBjY3QuMXNbMSxdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCnRtcCA8LSBjY3QuMXMuVmFSKHg9eUkuc3ViOTUsIHI9ci5lbXAuc3ViOTUsbGV2PTAuOTUpOyBjY3QuMXNbMixdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCnRtcCA8LSBjY3QuMXMuVmFSKHg9eUkuc3ViOTUsIHI9ci5mcC5zdWI5NSxsZXY9MC45NSk7IGNjdC4xc1szLF08LWModG1wJHB2LmF2Zyx0bXAkcHYuY29uZCkKcm91bmQoY2N0LjFzLDMpCgpjY3QuMXMgPC0gbWF0cml4KG5yb3c9MywgbmNvbD0yKSAjIHNpbXBsZSAmIGdlbmVyYWwgb25lLXNpZGVkIENDVCBvZiBzdXBlci1jYWxpYnJhdGlvbgp0bXAgPC0gY2N0LjFzLlZhUih4PXlJLnN1Yjk5LCByPXIuZXZ0LnN1Yjk5LGxldj0wLjk5KTsgY2N0LjFzWzEsXTwtYyh0bXAkcHYuYXZnLHRtcCRwdi5jb25kKQp0bXAgPC0gY2N0LjFzLlZhUih4PXlJLnN1Yjk5LCByPXIuZW1wLnN1Yjk5LGxldj0wLjk5KTsgY2N0LjFzWzIsXTwtYyh0bXAkcHYuYXZnLHRtcCRwdi5jb25kKQp0bXAgPC0gY2N0LjFzLlZhUih4PXlJLnN1Yjk5LCByPXIuZnAuc3ViOTksbGV2PTAuOTkpOyBjY3QuMXNbMyxdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCnJvdW5kKGNjdC4xcywzKQoKIyMgQ29tcGFyYXRpdmUgYmFja3Rlc3RpbmcKIyMgcT0uOTUKc21hdCA8LSBtYXRyaXgobnJvdz0zLCBuY29sPTEpCnNtYXRbMSwxXSA8LSBtZWFuKHNmVmFSKHI9ci5ldnQuc3ViOTUseD15SS5zdWI5NSxhPTAuOTUsaD0xKSkKc21hdFsyLDFdIDwtIG1lYW4oc2ZWYVIocj1yLmVtcC5zdWI5NSx4PXlJLnN1Yjk1LGE9MC45NSxoPTEpKQpzbWF0WzMsMV0gPC0gbWVhbihzZlZhUihyPXIuZnAuc3ViOTUseD15SS5zdWI5NSxhPTAuOTUsaD0xKSkKYXBwbHkoc21hdCwyLCJyYW5rIikKCiMjIHE9Ljk5CnNtYXQgPC0gbWF0cml4KG5yb3c9MywgbmNvbD0xKQpzbWF0WzEsMV0gPC0gbWVhbihzZlZhUihyPXIuZXZ0LnN1Yjk5LHg9eUkuc3ViOTksYT0wLjk5LGg9MSkpCnNtYXRbMiwxXSA8LSBtZWFuKHNmVmFSKHI9ci5lbXAuc3ViOTkseD15SS5zdWI5OSxhPTAuOTksaD0xKSkKc21hdFszLDFdIDwtIG1lYW4oc2ZWYVIocj1yLmZwLnN1Yjk5LHg9eUkuc3ViOTksYT0wLjk5LGg9MSkpCmFwcGx5KHNtYXQsMiwicmFuayIpCgojIyBUTE0Kcm09MQp0bG05NSA8LSBUTE1mbihyPXJiaW5kKHIuZXZ0LnN1Yjk1LHIuZW1wLnN1Yjk1LHIuZnAuc3ViOTUpLCB5PXlJLnN1Yjk1LCBybT1ybSwgbGV2PTAuOTUsaD0xKQpwbG90VExNKHRsbTk1JFRMTTEwLCBybT0xLCBsZXY9MC45NSxtZXRob2Q9YygiZXZ0IiwiZW1wIiwic3QiKSkKCnRsbTk5IDwtIFRMTWZuKHI9cmJpbmQoci5ldnQuc3ViOTksci5lbXAuc3ViOTksci5mcC5zdWI5OSksIHk9eUkuc3ViOTksIHJtPXJtLCBsZXY9MC45OSxoPTEpCnBsb3RUTE0odGxtOTkkVExNMTAsIHJtPTEsIGxldj0wLjk5LG1ldGhvZD1jKCJldnQiLCJlbXAiLCJzdCIpKQpgYGAKCgoKIyMjIEluLVNhbXBsZSBUZXN0Ckhvd2V2ZXIsIHdlIGNhbiBzaG93IHRoYXQgbW92ZW1lbnQgaW4gQ29WYVIgaXMgZHJpdmVuIGJ5IHRoZSBwcmVkaWN0IHNpZ21hbCBmcm9tIEdhcmNoIG1vZGVsLCBhbmQgdGhlIHByZWRpY3RlZCBzaWdtYWwgc2hhcmVzIHRoZSBzaW1pbGFyIHBhdHRlcm4gb2YgbGFnZ2VkIGxvc3Mgc2VyaWVzLiBUaGUgZmlndXJlIGJsb3cgcGxvdHMgc3Vic2FtcGxlIHdpdGggMTAwIGRheXMgZm9yIFNQNTAwIGxvc3Mgc2VyaWVzLiBBcyBzaG93biBpbiB0aGUgZmlndXJlLCB0aGUgcGVha3Mgb2Ygc2lnbWFfU1A1MDAgYXJlIGluIGxpbmUgd2l0aCBDb1ZhUiBmcm9tIEVWVCBhbmQgRlAsIGJ1dCBhcmUgb25lLXBlcmlvZCBoZWFkIG9mIGxvc3Mgc2VyaWVzIChzZWUgeC1heGlzIDgwLTEwMCkuIFRoaXMgcmVzdWx0IGNvbWVzIGZyb20gdGhlIGZhY3QgdGhhdCBwcmVkaWN0ZWQgc2lnbWEgaXMgaGVhdmlseSBhZmZlY3RlZCBieSB0aGUgbW9zdCByZWNlbnQgZGF0YS4gV2hlbiB0aGVyZSBpcyBhIGhpZ2ggcmV1dHJuIChvciBsb3NzKSB0b2RheSwgdGhlIHByZWRpY3RlZCB2b2xhdGlsaXR5IHdpbGwgYmUgdmVyeSBoaWdoIHRvbW9ycm93LgoKYGBge3IgaW5jbHVkZT1UUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBsb3QoY292YXJbNTgwMDo1OTAwLDFdLCB0eXBlID0gImwiLCBjb2wgPSAiYmx1ZSIsIHlsaW0gPSAgYygtMC4xLDAuMiksIGx0eSA9IDMsIHlsYWIgPSAiUmV0dXJuIikKcG9pbnRzKGNvdmFyWzU4MDA6NTkwMCw1XSwgdHlwZSA9ICJsIiwgY29sID0gImJsYWNrIiwgbHR5ID0gMSkKcG9pbnRzKHlJWzU4MDA6NTkwMF0sIHR5cGUgPSAibCIsIGNvbCA9ICJyZWQiLCBsdHkgPSAyKQpzZXR3ZCgifi9PbmVEcml2ZSAtIElOU0VBRC9Ta2V3RWxsaXB0L0NvZGVfVXBkYXRlL05hdGFsaWEvb3V0NTAwLyIpCmxvYWQoIm91dFNQNTAwLlJEQVRBIikKcG9pbnRzKG91dC5wJHNpZ3Quc3RbNTgwMDo1OTAwXSwgdHlwZSA9ICJsIiwgY29sID0gJ2dyZWVuJywgbHR5ID0gNCkKbGVnZW5kKCJ0b3ByaWdodCIsIGxlZ2VuZCA9IGMoIkVWVCIsICJGUCIsICJTUDUwMCIsInNpZ21hX1NQNTAwIiksIGNvbCA9IGMoImJsdWUiLCAiYmxhY2siLCAicmVkIiwiZ3JlZW4iKSwgbHR5ID0gYygzLDEsMiw0KSkKYGBgCgpTaW1pbGFybHksIGlmIHdlIHBsb3Qgc3Vic2FtcGxlIGluIHdoaWNoIERJUyBsb3NzIGlzIGJleW9uZCA5OSUgVmFSLCB0aGUgcGVha3Mgb2YgU1AwMCBhbmQgQ29WYVIgZnJvbSBkaWZmZXJlbnQgbWV0aG9kcyBhcmUgbm90IGFsaWduZWQuCmBgYHtyfQpwbG90KHIuZnAuc3ViOTksIHR5cGUgPSAibCIsIGNvbCA9ICJibHVlIiwgeWxpbSA9ICBjKC0wLjAzLDAuMyksIGx0eSA9IDMsIHlsYWIgPSAiUmV0dXJuIikKcG9pbnRzKHlJLnN1Yjk5LCB0eXBlID0gImwiLCBjb2wgPSAiYmxhY2siLCBsdHkgPSAxKQpwb2ludHMoci5ldnQuc3ViOTksIHR5cGUgPSAibCIsIGNvbCA9ICJyZWQiLCBsdHkgPSAyKQpsZWdlbmQoInRvcHJpZ2h0IiwgbGVnZW5kID0gYygiRlAiLCAiRVZUIiwgIkxvc3MiKSwgY29sID0gYygiYmx1ZSIsICJyZWQiLCAiYmxhY2siKSwgbHR5ID0gYygzLDIsMSkpCmBgYAoKCklmIHdlIHNoaWZ0IExvc3Mgc2VyaWVzIG9uZS1kYXkgYWhlYWQgKG9yIHNoaWZ0IENvVmFSIG9uZSBkYXkgb25lLWRheSBiYWNrd2FyZCksIHRoZW4gdGhlIHBlYWtzIGFyZSBhbGlnbmVkLiBFc3NlbnRpYWxseSwgdGhpcyBpcyBpbi1zYW1wbGUgYW5hbHlzaXMuIFdlIGNvbXBhcmUgQ29WYVIgZXN0aWFtdGVkIHVzaW5nIGRheSAxIHRvIGRheSA1MDAgZGF0YSB3aXRoIGRheSA1MDAgbG9zcy4KCmBgYHtyLG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz1GQUxTRX0KIyMgaWRlbnRpZnkgc3Vic2FtcGxlIHdoZXJlIExbdCsxXV5qID4gVmFSW3QrMV1eagpuPWRpbShjb3Zhci5LTylbMV0KZW5kID0gbnJvdyhyLktPKQoKbG9zcy5ESVMgPC0gLXIuRElTJHJbKGVuZC1uKTooZW5kLTEpXQp5IDwtIGxvc3MuRElTCnlJIDwtIGFzLnZlY3RvcigtclNQWyhlbmQtbik6KGVuZC0xKV0pCgpwbG90KGNvdmFyWzU4MDA6NTkwMCwxXSwgdHlwZSA9ICJsIiwgY29sID0gImJsdWUiLCB5bGltID0gIGMoLTAuMSwwLjIpLCBsdHkgPSAzLCB5bGFiID0gIlJldHVybiIpCnBvaW50cyhjb3Zhcls1ODAwOjU5MDAsNV0sIHR5cGUgPSAibCIsIGNvbCA9ICJibGFjayIsIGx0eSA9IDEpCnBvaW50cyh5SVs1ODAwOjU5MDBdLCB0eXBlID0gImwiLCBjb2wgPSAicmVkIiwgbHR5ID0gMikKc2V0d2QoIn4vT25lRHJpdmUgLSBJTlNFQUQvU2tld0VsbGlwdC9Db2RlX1VwZGF0ZS9OYXRhbGlhL291dDUwMC8iKQpsb2FkKCJvdXRTUDUwMC5SREFUQSIpCnBvaW50cyhvdXQucCRzaWd0LnN0WzU4MDA6NTkwMF0sIHR5cGUgPSAibCIsIGNvbCA9ICdncmVlbicsIGx0eSA9IDQpCmxlZ2VuZCgidG9wcmlnaHQiLCBsZWdlbmQgPSBjKCJFVlQiLCAiRlAiLCAiU1A1MDAiLCJzaWdtYV9TUDUwMCIpLCBjb2wgPSBjKCJibHVlIiwgImJsYWNrIiwgInJlZCIsImdyZWVuIiksIGx0eSA9IGMoMywxLDIsNCkpCmBgYAoKCk5vdywgd2UgcmVwZWF0IGFsbCB0aGUgYW5hbHlzaXMgZm9yIGluLXNhbXBsZSBDb1ZhUi4KCgpgYGB7cn0Kaz1kaW0ocm1hdClbMl0gIyBudW1iZXIgb2YgbWV0aG9kcy9jYXNlcwp5bWF0ID0gbWF0cml4KHJlcCh5LCBrKSwgbmNvbCA9IGssIGJ5cm93PUZBTFNFKQpobWF0ID0gKHltYXQgPiBybWF0KQoKYXBwbHkoaG1hdCwyLCJzdW0iLG5hLnJtPVQpL24qMTAwCmBgYAoKCmBgYHtyfQpyLmV2dC5zdWI5NSA8LSBzdWJzZXQoY292YXJbLDFdLGhtYXRbLDFdKQpyLmV2dC5zdWI5OSA8LSBzdWJzZXQoY292YXJbLDJdLGhtYXRbLDJdKQpyLmVtcC5zdWI5NSA8LSBzdWJzZXQoY292YXJbLDNdLGhtYXRbLDFdKQpyLmVtcC5zdWI5OSA8LSBzdWJzZXQoY292YXJbLDRdLGhtYXRbLDJdKQpyLmZwLnN1Yjk1IDwtICBzdWJzZXQoY292YXJbLDVdLGhtYXRbLDFdKQpyLmZwLnN1Yjk5IDwtICBzdWJzZXQoY292YXJbLDZdLGhtYXRbLDJdKQoKIyMgQ2hlY2tpbmcgJSB2aW9sYXRpb25zIG9mIENvVmFSIGJ5IHRoZSBpbmRleCBsb3NzZXMKeUkuc3ViOTUgPC0gYXMubnVtZXJpYyhzdWJzZXQoeUksIGhtYXRbLDFdKSkKeUkuc3ViOTkgPC0gYXMubnVtZXJpYyhzdWJzZXQoeUksIGhtYXRbLDJdKSkKCiMgUmVtb3ZlIE5BIHZhbHVlcwpyLnN1Yjk1ID0gcmJpbmQoci5ldnQuc3ViOTUsci5lbXAuc3ViOTUsIHIuZnAuc3ViOTUpCmluZC5uYTk1ID0gd2hpY2goIChpcy5uYShhcHBseShyLnN1Yjk1LDIsc3VtKSkpICkKCnIuc3ViOTkgPSByYmluZChyLmV2dC5zdWI5OSxyLmVtcC5zdWI5OSwgci5mcC5zdWI5OSkKaW5kLm5hOTkgPSB3aGljaCgoaXMubmEoYXBwbHkoci5zdWI5OSwyLHN1bSkpKSApCgppZiAobGVuZ3RoKGluZC5uYTk1KT4wKXsKICByLmV2dC5zdWI5NSA8LSByLmV2dC5zdWI5NVstaW5kLm5hOTVdCiAgci5lbXAuc3ViOTUgPC0gci5lbXAuc3ViOTVbLWluZC5uYTk1XQogIHIuZnAuc3ViOTUgPC0gci5mcC5zdWI5NVstaW5kLm5hOTVdCiAgeUkuc3ViOTUgPC0geUkuc3ViOTVbLWluZC5uYTk1XQp9CmlmIChsZW5ndGgoaW5kLm5hOTkpPjApewogIHIuZXZ0LnN1Yjk5IDwtIHIuZXZ0LnN1Yjk5Wy1pbmQubmE5OV0KICByLmVtcC5zdWI5OSA8LSByLmVtcC5zdWI5OVstaW5kLm5hOTldCiAgci5mcC5zdWI5OSA8LSByLmZwLnN1Yjk5Wy1pbmQubmE5OV0KICB5SS5zdWI5OSA8LSB5SS5zdWI5OVstaW5kLm5hOTldCn0KCgptOTUgPC0gbGVuZ3RoKHlJLnN1Yjk1KSAjc3ViLXNhbXBsZSBzaXplIGZvciBxPTAuOTUKbTk5IDwtIGxlbmd0aCh5SS5zdWI5OSkgI3N1Yi1zYW1wbGUgc2l6ZSBmb3IgcT0wLjk5Cgpyb3VuZChjKHN1bSh5SS5zdWI5NT5yLmV2dC5zdWI5NSkvbTk1KjEwMCxzdW0oeUkuc3ViOTU+ci5lbXAuc3ViOTUpL205NSoxMDAsIHN1bSh5SS5zdWI5NT5yLmZwLnN1Yjk1KS9tOTUqMTAwLCBzdW0oeUkuc3ViOTk+ci5ldnQuc3ViOTkpL205OSoxMDAsIHN1bSh5SS5zdWI5OT5yLmVtcC5zdWI5OSkvbTk5KjEwMCwgc3VtKHlJLnN1Yjk5PnIuZnAuc3ViOTkpL205OSoxMDApLDIpCmBgYAoKIyMjIyBGcm9tIGFib3ZlIG51bWJlcnMsIEVWVCBsb29rcyB3b3JrIHF1aXRlIHdlbGwgZm9yIGluLXNhbXBsZSBhbmFseXNpcy4gSG93ZXZlciwgY29tcGFyYXRpdmUgYmFja3Rlc3RpbmcgYW5kIFRMTSBzZWVtIHRvIHN1Z2dlc3QgdGhhdCBFVlQgaXMgd29yc2UgdGhhbiBlbXBpcmljYWwgbWV0aG9kLiBJIGRvIG5vdCB1bmRlcnN0YW5kIHdoeSB3ZSBnZXQgZGlmZmVyZW50IHJlc3V0bHMgZnJvbSBkaWZmZXJlbnQgdGVzdHMuIAoKYGBge3J9CmNjdCA8LSBtYXRyaXgobnJvdz0zLCBuY29sPTIpICMgc2ltcGxlICYgZ2VuZXJhbCBDQ1QKCnRtcCA8LSBjY3QuMnMuVmFSKHg9eUkuc3ViOTUsIHI9ci5ldnQuc3ViOTUsbGV2PTAuOTUpOyBjY3RbMSxdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCnRtcCA8LSBjY3QuMnMuVmFSKHg9eUkuc3ViOTUsIHI9ci5lbXAuc3ViOTUsbGV2PTAuOTUpOyBjY3RbMixdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCnRtcCA8LSBjY3QuMnMuVmFSKHg9eUkuc3ViOTUsIHI9ci5mcC5zdWI5NSxsZXY9MC45NSk7IGNjdFszLF08LWModG1wJHB2LmF2Zyx0bXAkcHYuY29uZCkKcm91bmQoY2N0LDMpCgojIHRtcCA8LSBjY3QuMnMuVmFSKHg9eUkuc3ViOTksIHI9ci5ldnQuc3ViOTksbGV2PTAuOTkpOyBjY3RbMSxdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCiMgdG1wIDwtIGNjdC4ycy5WYVIoeD15SS5zdWI5OSwgcj1yLmVtcC5zdWI5OSxsZXY9MC45OSk7IGNjdFsyLF08LWModG1wJHB2LmF2Zyx0bXAkcHYuY29uZCkKIyB0bXAgPC0gY2N0LjJzLlZhUih4PXlJLnN1Yjk5LCByPXIuZnAuc3ViOTksbGV2PTAuOTkpOyBjY3RbMyxdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCiMgcm91bmQoY2N0LDMpCgoKIyMgT05FLVNJREVEIFRFU1Qgb2Ygc3VwZXItY2FsaWJyYXRpb24gYXMgaW4gQmFzZWwgQWNjb3JkCmNjdC4xcyA8LSBtYXRyaXgobnJvdz0zLCBuY29sPTIpICMgc2ltcGxlICYgZ2VuZXJhbCBvbmUtc2lkZWQgQ0NUIG9mIHN1cGVyLWNhbGlicmF0aW9uCnRtcCA8LSBjY3QuMXMuVmFSKHg9eUkuc3ViOTUsIHI9ci5ldnQuc3ViOTUsbGV2PTAuOTUpOyBjY3QuMXNbMSxdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCnRtcCA8LSBjY3QuMXMuVmFSKHg9eUkuc3ViOTUsIHI9ci5lbXAuc3ViOTUsbGV2PTAuOTUpOyBjY3QuMXNbMixdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCnRtcCA8LSBjY3QuMXMuVmFSKHg9eUkuc3ViOTUsIHI9ci5mcC5zdWI5NSxsZXY9MC45NSk7IGNjdC4xc1szLF08LWModG1wJHB2LmF2Zyx0bXAkcHYuY29uZCkKcm91bmQoY2N0LjFzLDMpCgpjY3QuMXMgPC0gbWF0cml4KG5yb3c9MywgbmNvbD0yKSAjIHNpbXBsZSAmIGdlbmVyYWwgb25lLXNpZGVkIENDVCBvZiBzdXBlci1jYWxpYnJhdGlvbgp0bXAgPC0gY2N0LjFzLlZhUih4PXlJLnN1Yjk5LCByPXIuZXZ0LnN1Yjk5LGxldj0wLjk5KTsgY2N0LjFzWzEsXTwtYyh0bXAkcHYuYXZnLHRtcCRwdi5jb25kKQp0bXAgPC0gY2N0LjFzLlZhUih4PXlJLnN1Yjk5LCByPXIuZW1wLnN1Yjk5LGxldj0wLjk5KTsgY2N0LjFzWzIsXTwtYyh0bXAkcHYuYXZnLHRtcCRwdi5jb25kKQp0bXAgPC0gY2N0LjFzLlZhUih4PXlJLnN1Yjk5LCByPXIuZnAuc3ViOTksbGV2PTAuOTkpOyBjY3QuMXNbMyxdPC1jKHRtcCRwdi5hdmcsdG1wJHB2LmNvbmQpCnJvdW5kKGNjdC4xcywzKQoKIyMgQ29tcGFyYXRpdmUgYmFja3Rlc3RpbmcKIyMgcT0uOTUKc21hdCA8LSBtYXRyaXgobnJvdz0zLCBuY29sPTEpCnNtYXRbMSwxXSA8LSBtZWFuKHNmVmFSKHI9ci5ldnQuc3ViOTUseD15SS5zdWI5NSxhPTAuOTUsaD0xKSkKc21hdFsyLDFdIDwtIG1lYW4oc2ZWYVIocj1yLmVtcC5zdWI5NSx4PXlJLnN1Yjk1LGE9MC45NSxoPTEpKQpzbWF0WzMsMV0gPC0gbWVhbihzZlZhUihyPXIuZnAuc3ViOTUseD15SS5zdWI5NSxhPTAuOTUsaD0xKSkKYXBwbHkoc21hdCwyLCJyYW5rIikKCiMjIHE9Ljk5CnNtYXQgPC0gbWF0cml4KG5yb3c9MywgbmNvbD0xKQpzbWF0WzEsMV0gPC0gbWVhbihzZlZhUihyPXIuZXZ0LnN1Yjk5LHg9eUkuc3ViOTksYT0wLjk5LGg9MSkpCnNtYXRbMiwxXSA8LSBtZWFuKHNmVmFSKHI9ci5lbXAuc3ViOTkseD15SS5zdWI5OSxhPTAuOTksaD0xKSkKc21hdFszLDFdIDwtIG1lYW4oc2ZWYVIocj1yLmZwLnN1Yjk5LHg9eUkuc3ViOTksYT0wLjk5LGg9MSkpCmFwcGx5KHNtYXQsMiwicmFuayIpCgojIyBUTE0Kcm09MQp0bG05NSA8LSBUTE1mbihyPXJiaW5kKHIuZXZ0LnN1Yjk1LHIuZW1wLnN1Yjk1LHIuZnAuc3ViOTUpLCB5PXlJLnN1Yjk1LCBybT1ybSwgbGV2PTAuOTUsaD0xKQpwbG90VExNKHRsbTk1JFRMTTEwLCBybT0xLCBsZXY9MC45NSxtZXRob2Q9YygiZXZ0IiwiZW1wIiwic3QiKSkKCnRsbTk5IDwtIFRMTWZuKHI9cmJpbmQoci5ldnQuc3ViOTksci5lbXAuc3ViOTksci5mcC5zdWI5OSksIHk9eUkuc3ViOTksIHJtPXJtLCBsZXY9MC45OSxoPTEpCnBsb3RUTE0odGxtOTkkVExNMTAsIHJtPTEsIGxldj0wLjk5LG1ldGhvZD1jKCJldnQiLCJlbXAiLCJzdCIpKQpgYGAKCmBgYHtyfQpwbG90KHIuZnAuc3ViOTksIHR5cGUgPSAibCIsIGNvbCA9ICJibHVlIiwgeWxpbSA9ICBjKC0wLjAzLDAuNCksIGx0eSA9IDMsIHlsYWIgPSAiUmV0dXJuIikKcG9pbnRzKHlJLnN1Yjk5LCB0eXBlID0gImwiLCBjb2wgPSAiYmxhY2siLCBsdHkgPSAxKQpwb2ludHMoci5ldnQuc3ViOTksIHR5cGUgPSAibCIsIGNvbCA9ICJyZWQiLCBsdHkgPSAyKQpsZWdlbmQoInRvcHJpZ2h0IiwgbGVnZW5kID0gYygiRlAiLCAiRVZUIiwgIkxvc3MiKSwgY29sID0gYygiYmx1ZSIsICJyZWQiLCAiYmxhY2siKSwgbHR5ID0gYygzLDIsMSkpCmBgYAoKYGBge3J9CnBsb3QoeUksIHlsYWI9IiIsIHlsaW09YygtLjEyLDAuNCksIGNvbD0iZ3JheSIseGxhYj0iIiwgbWFpbj0iRElTIiwgY2V4Lm1haW49MC44LCBsdHkgPSAxKQpsaW5lcyh0aW1lKHlJKSxjb3Zhci5ESVNbLDFdLCBjb2w9InJlZCIsIGx0eSA9IDIpCmxpbmVzKHRpbWUoeUkpLGNvdmFyLkRJU1ssNV0sIGNvbD0iYmxhY2siLCBsdHkgPSAzKQpsaW5lcyh0aW1lKHlJKSxjb3Zhci5ESVNbLDNdLCBjb2w9ImdyZWVuIiwgbHR5ID0gNCkKbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kID0gYygiU1A1MDAiLCAiRVZUIiwgIkZQIiwgIkhTIiksIGNvbCA9IGMoImdyZXkiLCAicmVkIiwgImJsYWNrIiwgImdyZWVuIiksIGx0eSA9IGMoMSwyLDMsNCkpCmBgYAoK