1 load required libraries and global functions

# check, load and install libraries
if ("dWaSSI" %in% installed.packages()) {library(dWaSSI)} else{
  library(devtools)
  install_github("ln1267/dWaSSI") }
librs<-c("raster","rgdal","rgeos","pryr","RColorBrewer","gstat","rasterVis")
f_lib_check(librs)

2 calculate the index

The band order is: Blue, Green, Red, RedEdge, and Near-Infrared.
\(EG= 2*G-R-B\)
\(NDVI = (NIR - Red)/(NIR+Red)\)
\(NDRE = (NIR - Redge)/(NIR+Redge)\)
\(VARI = (G - R)/(G + R - B)\)

f_cal_VIs<-function(dir_data,Sitename,Tifname,shpname,zonal_field,multiple=T){
  da<-brick(paste0(dir_data,Sitename,"/Original_images/",Tifname))
  shp<-readOGR(paste0(dir_data,Sitename,"/shps"),shpname)
  shp<- spTransform(shp, CRS(proj4string(da)))
  
  f_VARI<-function(red,green,blue){
    
    VARI<-(green-red)/(green+red-blue)
    return(VARI)
  }
  
  f_EG<-function(red,green,blue){
    
    EG<-2*green-red-blue
    return(EG)
  }
  
  f_NDVI<- function(red, nir) {
      ndvi <- (nir - red) / (nir + red)
      return(ndvi)
  }
  f_NDRE<- function(redege, nir) {
      ndre <- (nir - redege) / (nir + redege)
      return(ndre)
  }  
  if(!dir.exists(paste0(dir_data,Sitename,"/Results/Tifs/"))){  dir.create(paste0(dir_data,Sitename,"/Results/Tifs/")) }
  
  print(paste0("Calculating vegetation indices"))

  if(multiple) {
    vis<-c("EG","VARI","NDVI","NDRE")
      # NDVI
    EG <- overlay(da[[3]], da[[2]],da[[1]], fun=f_EG)
    VARI <- overlay(da[[3]], da[[2]],da[[1]], fun=f_VARI)
    NDVI <- overlay(da[[3]],da[[5]], fun=f_NDVI)
    NDRE <- overlay(da[[4]],da[[5]], fun=f_NDRE)
    VARI[is.infinite(VARI) | abs(VARI)>1]<-0
    NDVI[is.infinite(NDVI) | abs(NDVI)>1]<-0
    NDVI[is.infinite(NDRE) | abs(NDRE)>1]<-0
    pdf(paste0(dir_data,Sitename,"/Results/",unlist(strsplit(Tifname, ".", fixed = TRUE))[1],"_NDVI.pdf"),width=14*da@ncols/da@nrows,height=14)
    mapTheme <- rasterTheme(region=brewer.pal(8,"RdYlGn"))
   plots<-levelplot(NDVI, margin=F, par.settings=mapTheme,main="NDVI",pretty=TRUE)#+layer(sp.points(shp))
   print(plots)
   dev.off()
    #print(plots)
    VIs<-stack(EG,VARI,NDVI,NDRE)
    
  }else{
    vis<-c("EG","VARI")
    # EG
    EG <- overlay(da[[1]], da[[2]],da[[3]], fun=f_EG)
    # vari
    VARI <- overlay(da[[1]], da[[2]],da[[3]], fun=f_VARI)
    VARI[is.infinite(VARI) | abs(VARI)>1]<-0

    pdf(paste0(dir_data,Sitename,"/Results/",unlist(strsplit(Tifname, ".", fixed = TRUE))[1],"_VARI.pdf"),width=14*da@ncols/da@nrows,height=14)
    mapTheme <- rasterTheme(region=brewer.pal(8,"RdYlGn"))
    plots<-levelplot(VARI, margin=F, par.settings=mapTheme,main="VARI",pretty=TRUE)#+layer(sp.points(shp))
    print(plots)
    dev.off()
    
    VIs<-stack(EG,VARI)
  }

  # zonal data
  print(paste0("Zonaling vegetation index using the field of ",zonal_field))
  ex <- raster::extract(VIs, shp, buffer=0.564,fun=mean,df=T)
  sta_shp <- as.data.frame(ex)
  names(sta_shp)<-c(zonal_field,vis)
  sta_shp[zonal_field] <- shp[[zonal_field]]

  # Export vis
  for( varname in vis){
    print(paste0("exporting ",varname))
    writeRaster(get(varname),paste0(dir_data,Sitename,"/Results/nc/",unlist(strsplit(Tifname, ".", fixed = TRUE))[1],"_",varname,".nc"),varname=varname,xname="lon",yname="lat",format="CDF",overwrite=T)
    writeRaster(get(varname),paste0(dir_data,Sitename,"/Results/Tifs/",unlist(strsplit(Tifname, ".", fixed = TRUE))[1],"_",varname,".tif"),format="GTiff",overwrite=T)
  }
  
  return(sta_shp)
}

f_zonal_VI<-function(dir_data,Sitename,Tifname,shpname,zonal_field,VIname=""){
  da<-raster(paste0(dir_data,Sitename,"/Original_images/",Tifname))
  da[da>1]<-0
  da[da< 0]<-0
  shp<-readOGR(paste0(dir_data,Sitename,"/shps"),shpname)
  shp<- spTransform(shp, CRS(proj4string(da)))
  
  if(!dir.exists(paste0(dir_data,Sitename,"/Results/Tifs/"))){  dir.create(paste0(dir_data,Sitename,"/Results/Tifs/")) }
  
  print(paste0("Zonal vegetation index"))

    pdf(paste0(dir_data,Sitename,"/Results/",unlist(strsplit(Tifname, ".", fixed = TRUE))[1],"_",VIname,".pdf"),width=14*da@ncols/da@nrows,height=14)
    mapTheme <- rasterTheme(region=brewer.pal(8,"RdYlGn"))
    plots<-levelplot(da, margin=F, par.settings=mapTheme,main=VIname,pretty=TRUE)#+layer(sp.points(shp))
    print(plots)
    dev.off()

  # zonal data
  print(paste0("Zonaling vegetation index using the field of ",zonal_field))
  ex <- raster::extract(a, shp, buffer=0.564,fun=mean,df=T)
  sta_shp <- as.data.frame(ex)
  names(sta_shp)<-c(zonal_field,VIname)
  sta_shp[zonal_field] <- shp[[zonal_field]]

  return(sta_shp)
}
#

f_2index_cal<-function(dir_data,filename,daname){
  
  da<-brick(filename)

  # test the input data
  pdf(paste(dir_image,daname,"_RGB.pdf",sep=""))
  #plot(da[[1]])
  plotRGB(da, 1, 2, 3)
  #title(main ="RGB")
  dev.off()
  
  # calculate and write EG
  
  EG <- calc(da, fun=f_EG_raster)
  
  writeRaster(EG,paste(dir_image,daname,"_EG.tif",sep=""),format="GTiff",overwrite=T)
  
  # calculate and write VARI
  VARI<-overlay(da, fun=f_VARI_raster)
  writeRaster(VARI,paste(dir_image,daname,"_VARI.tif",sep=""),format="GTiff",overwrite=T)
  
  # test EG and VARI
  pdf(paste(dir_image,daname,"_index.pdf",sep=""))
  plot(EG)
  title(main ="EG index")
  plot(VARI)
  title(main ="VARI index")
  dev.off()
}


f_2index_array<-function(dir_data,filename,daname,shp=NA){

  da<-brick(filename)
  
  if(!is.na(shp)){
    da<-crop(da,shp)
  }
  
  # test the input data
  pdf(paste(dir_image,daname,"_RGB.pdf",sep=""))
  plotRGB(da, 1, 2, 3,main="RGB image")
  #print(a)
  dev.off()
  
  da_array<-as.array(da)
  # calculate and write EG

  EG <- f_EG_array(da_array)
  EG_raster<-raster(EG,da@extent@xmin,da@extent@xmax,da@extent@ymin,da@extent@ymax,crs=crs(da))
  plot(EG_raster)
  writeRaster(EG_raster,paste(dir_image,daname,"_EG.tif",sep=""),format="GTiff",overwrite=T)

  # calculate and write VARI
  VARI<-f_VARI_array(da_array)
  VARI_raster<-raster(VARI,da@extent@xmin,da@extent@xmax,da@extent@ymin,da@extent@ymax,crs=crs(da))
  writeRaster(VARI_raster,paste(dir_image,daname,"_VARI.tif",sep=""),format="GTiff",overwrite=T)

  # test EG and VARI
  pdf(paste(dir_image,daname,"_index.pdf",sep=""))
  plot(EG_raster)
  title(main ="EG index")
  plot(VARI_raster)
  title(main ="VARI index")
  dev.off()
}

3 Sites

3.1 Meckering

The band order is: Blue, Green, Red, RedEdge, and Near-Infrared.

dir_data<-"/www/Stan/"
# Zonal data for each site
Meckering_VIs_Meckering_trial<-f_cal_VIs(
  dir_data="/www/Stan/",
  Sitename="Meckering",
  Tifname="Meckering_trial_site.tif",
  shpname="Meckering_trial",
  zonal_field<-"id",
  multiple=F
  )
save(VIs_Meckering_trial,file = paste0(dir_data,"Tmp/VIs_Meckering_trial.RData"))

Meckering_VIs_082017<-f_cal_VIs(
  dir_data="/www/Stan/",
  Sitename="Meckering",
  Tifname="August_multi_2017.tif",
  shpname="Meck_Aug_sample_points",
  zonal_field<-"id"
  )
save(Meckering_VIs_082017,file = paste0(dir_data,"Tmp/Meckering_VIs_082017.RData"))

Meckering_VIs_102017<-f_cal_VIs(
  dir_data="/www/Stan/",
  Sitename="Meckering",
  Tifname="October_multi_2017.tif",
  shpname="Meck_Oct_sample_points",
  zonal_field<-"id"
  )
save(Meckering_VIs_102017,file = paste0(dir_data,"Tmp/Meckering_VIs_102017.RData"))

Meckering_VIs_092017<-f_cal_VIs(
  dir_data="/www/Stan/",
  Sitename="Meckering",
  Tifname="September_multi_2017.tif",
  shpname="Meck_Sept_sample_points",
  zonal_field<-"id"
  )
save(Meckering_VIs_092017,file = paste0(dir_data,"Tmp/Meckering_VIs_092017.RData"))

3.2 Merge with MED and other data

MED<-read.csv(paste0(dir_data,"Meckering/data/Meckering_med_moist.csv"))
MED<-MED[-10]

load(paste0(dir_data,"Tmp/Meckering_VIs_092017.RData"))
load(paste0(dir_data,"Tmp/Meckering_VIs_082017.RData"))
load(paste0(dir_data,"Tmp/Meckering_VIs_102017.RData"))

Meckering_VIs_092017$Date<-"092017"
Meckering_VIs_082017$Date<-"082017"
Meckering_VIs_102017$Date<-"102017"

VIs<-rbind(Meckering_VIs_092017,Meckering_VIs_082017,Meckering_VIs_102017)
names(VIs)[1]<-"samples"
library(reshape2)
a<-melt(VIs,id=c("samples","Date"))
VIs<-dcast(a,samples~variable+Date)

Merge_data<-merge(MED,VIs,all.x = T,by="samples")

write.csv(Merge_data,paste0(dir_data,Sitename,"/Results/",Sitename,"_Merge_MED_VIs.csv"),row.names = F)

library(ggplot2)
ggplot(data =Merge_data,aes(x=NDVI_092017,y=med_0807,col=Position))+geom_point()+facet_wrap(~Position)

library(dplyr)

cor.test(Merge_data$NDVI,Merge_data$med_0807)

3.3 Kojonup

shpfile<-"Kojonup_2017_sample_points"
# Zonal data for each site
VIs_Kojonup_trial<-f_cal_VIs(
  dir_data="/www/Stan/",
  Sitename="Kojonup",
  Tifname="Sept_2017_multi_modified.tif",
  shpname=shpfile,
  zonal_field<-"id",
  multiple=F
  )

shpfile<-"Kojonup_2017_sample_points"
# Zonal data for each site
VIs_Kojonup_trial<-f_cal_VIs(
  dir_data="/www/Stan/",
  Sitename="Kojonup",
  Tifname="Kojonup-Tot-Pot-Ura-Tho.tif",
  shpname=shpfile,
  zonal_field<-"id",
  multiple=F
  )

save(VIs_Kojonup_trial,file = "/Dataset/www/Stan/Tmp/VIs_Kojonup_trial.RData")


Kojonup_VIs_092017<-f_cal_VIs(
  dir_data="/www/Stan/",
  Sitename="Kojonup",
  Tifname="Sept_2017_multi_modified.tif",
  shpname=shpfile,
  zonal_field<-"id"
  )
save(Kojonup_VIs_092017,file = "/www/Stan/Tmp/Kojonup_VIs_092017.RData")

Kojonup_VIs_102017<-f_cal_VIs(
  dir_data="/www/Stan/",
  Sitename="Kojonup",
  Tifname="Oct_2017_multi_modified.tif",
  shpname=shpfile,
  zonal_field<-"id"
  )
save(Kojonup_VIs_102017,file = "/www/Stan/Tmp/Kojonup_VIs_102017.RData")


Kojonup_Flight2<-f_zonal_VI(
  dir_data="/www/Stan/",
  Sitename="Kojonup",
  Tifname="North_Kojonup_Flight_2_NDVI_poly1_lanczos.tif",
  shpname=shpfile,
  zonal_field<-"id",
  VIname = "NDVI"
  )
save(Kojonup_Flight2,file = "/www/Stan/Tmp/Kojonup_Flight2.RData")

plot(a)
plot(shp,add=T)



Kojonup_Flight4<-f_cal_VIs(
  dir_data="/www/Stan/",
  Sitename="Kojonup",
  Tifname="North_Kojonup_Flight_4_NDVI_poly1_lanczos.tif",
  shpname=shpfile,
  zonal_field<-"id"
  )
save(Kojonup_Flight4,file = "/www/Stan/Tmp/Kojonup_Flight4.RData")

Kojonup_Flight5<-f_cal_VIs(
  dir_data="/www/Stan/",
  Sitename="Kojonup",
  Tifname="North_Kojonup_Flight_5_NDVI_poly1_lanczos.tif",
  shpname=shpfile,
  zonal_field<-"id"
  )
save(Kojonup_Flight5,file = "/www/Stan/Tmp/Kojonup_Flight5.RData")

3.4 Merge MED

MED<-read.csv("/www/Stan/Kojonup/data/Kojonup_med_moist.csv")

load("/www/Stan/Tmp/Kojonup_VIs_092017.RData")
load("/www/Stan/Tmp/Kojonup_VIs_102017.RData")

Kojonup_VIs_092017$Date<-"092017"
Kojonup_VIs_102017$Date<-"102017"

VIs<-rbind(Kojonup_VIs_092017,Kojonup_VIs_102017)
names(VIs)[1]<-"Samples"
library(reshape2)
a<-melt(VIs,id=c("Samples","Date"))
VIs<-dcast(a,Samples~variable+Date)

Merge_data<-merge(MED,VIs,all.x = T,by="Samples")

write.csv(Merge_data,"/www/Stan/Kojonup/Results/Merge_MED_VIs.csv",row.names = F)

4 Process Radimatrix data

4.1 Sites

# interplate points using IDW 
f_plotrad<-function(da,df,varname){
  library(gstat)
  r<-raster(matrix(1,nrow=as.integer(da@nrows/10),ncol=as.integer(da@ncols/10)),xmn=da@extent@xmin,xmx=da@extent@xmax,ymn=da@extent@ymin,ymx=da@extent@ymax,crs=CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"))
  # interpolate
  mg <- gstat(id = varname, formula = get(varname)~1, locations = ~x+y, data=df, 
              nmax=7, set=list(idp = .5))
  z <- interpolate(r, mg)
  z <- mask(z, r)
  names(z)<-varname
  mapTheme <- rasterTheme(region=brewer.pal(8,"Blues"))
  plt <- levelplot(z, margin=F, par.settings=mapTheme,main=varname,pretty=TRUE)
  plt
  return(z)
}


da<-raster("/www/Stan/2018/Badgingarra/McAlpinepaddock217072017_VIS.nc")
shp<-readOGR("/www/Stan/2018/Badgingarra","boundary")
print(da)

# read rad EM data and select useful columns
rad<-read.csv("/www/Stan/2018/EM_and_Gamma/EM_and_gamma/EM/Badgingarra EM.csv",header = F,stringsAsFactors=F)


## Load TOTl data
rad<-read.csv("/www/Stan/2018/EM_and_Gamma/EM_and_gamma/Gamma/Badgingarra gamma.csv",header =T,stringsAsFactors=F)
rad<-rad[c(4,3,5:9)]
names(rad)<-c("y","x","Ele","TotCount","Potassium","Uranium","Thorium")

rad<-subset(rad,x>0)
a<-f_plotrad(resolution = 0.00001,df = rad,varname = "TotCount")
b<-f_plotrad(resolution = 0.00001,df = rad,varname = "Potassium")
c<-f_plotrad(resolution = 0.00001,df = rad,varname = "Uranium")
d<-f_plotrad(resolution = 0.00001,df = rad,varname = "Thorium")
cc <- brick(a,b,c,d)

writeRaster(cc,filename = "/www/Stan/2018/EM_and_Gamma/result/Badgingarra-Tot-Pot-Ura-Tho.tif",format="GTiff",overwrite=T)


rad<-read.csv("/www/Stan/2018/EM_and_Gamma/EM_and_gamma/EM/Kojonup EM.csv",header = F,stringsAsFactors=F)

rad<-rad[c(5,6,10,17,18,19,20)]
names(rad)<-c("y","x","Ele","EMd","MG1","EMs","MG2")

rad<-read.csv("/www/Stan/2018/EM_and_Gamma/EM_and_gamma/Gamma/Badgingarra gamma.csv")
rad<-read.csv("/www/Stan/2018/EM_and_Gamma/EM_and_gamma/Gamma/Kojonup gamma.csv")
rad<-rad[3:9]
names(rad)<-c("x","y","Ele","Totalcount","Potassium","Uranium","Thorium")


# transfer csv to spatil points
xy <- rad[,c("x","y")] # long + lat
spdf <- SpatialPointsDataFrame(coords = xy, data = rad,
                               proj4string = CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"))

# clip points data based on the outlint polygon
spdf.clip <- spdf[shp, ]

pdf("/www/Stan/gamma.pdf")
for (var in names(rad)[-c(1:3)]){
  
  print(f_plotrad(a,spdf@data,var))

}

dev.off()
for (var in names(rad)[-c(1:3)]){
  
  zz<-f_plotrad(a,spdf@data,var)
  f_plot_sp(zz,filename = paste0("/www/Stan/",var,".pdf"),varnames = var,cuts = 10)
}

r<-f_plotrad(a,spdf@data,"Potassium")
b<-f_plotrad(a,spdf@data,"Uranium")
g<-f_plotrad(a,spdf@data,"Thorium")

c <- brick(r,g,b)
writeRaster(c,"/www/Stan/Kojonup/Results/Kojnup_gamma.tif",format="GTiff",overwrite=T)
pdf("/www/Stan/rad_plot.pdf")
mapTheme <- rasterTheme(region=brewer.pal(8,"Reds"))
levelplot(r, margin=F, par.settings=mapTheme,main="Potassium",pretty=TRUE)
mapTheme <- rasterTheme(region=brewer.pal(8,"Greens"))
levelplot(g, margin=F, par.settings=mapTheme,main="Thorium",pretty=TRUE)
mapTheme <- rasterTheme(region=brewer.pal(8,"Blues"))
levelplot(b, margin=F, par.settings=mapTheme,main="Uranium",pretty=TRUE)

plotRGB(c, 1, 2,3, stretch="hist")

dev.off()
# }

plot(r)
plot(shp,add=T)

4.2 Sites_function

f_gamma(input = "/www/Stan/2018/EM_and_Gamma/Moora_large_scale/DEX_20180212_050745.csv",
       plotname="/www/Stan/2018/EM_and_Gamma/result/DEX-Tot-Pot-Ura-Tho.pdf",
       output="/www/Stan/2018/EM_and_Gamma/result/DEX-Tot-Pot-Ura-Tho.tif",
       plot=T)
[1] "/www/Stan/2018/EM_and_Gamma/Moora_large_scale/DEX_20180212_050745.csv"
Loading required package: lattice
Loading required package: latticeExtra
Loading required package: RColorBrewer
[inverse distance weighted interpolation]
[inverse distance weighted interpolation]
[inverse distance weighted interpolation]
[inverse distance weighted interpolation]
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayBmb3IgV2F0ZXIgUmVwZWxsZW5jeSBkYXRhIHByb2Nlc3MiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazogCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdG9jOiB5ZXMKLS0tCiMgbG9hZCByZXF1aXJlZCBsaWJyYXJpZXMgYW5kIGdsb2JhbCBmdW5jdGlvbnMKYGBge3IgbGlicywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0V9CiMgY2hlY2ssIGxvYWQgYW5kIGluc3RhbGwgbGlicmFyaWVzCmlmICgiZFdhU1NJIiAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpKSB7bGlicmFyeShkV2FTU0kpfSBlbHNlewogIGxpYnJhcnkoZGV2dG9vbHMpCiAgaW5zdGFsbF9naXRodWIoImxuMTI2Ny9kV2FTU0kiKSB9CmxpYnJzPC1jKCJyYXN0ZXIiLCJyZ2RhbCIsInJnZW9zIiwicHJ5ciIsIlJDb2xvckJyZXdlciIsImdzdGF0IiwicmFzdGVyVmlzIikKZl9saWJfY2hlY2sobGlicnMpCmBgYAojIGNhbGN1bGF0ZSB0aGUgaW5kZXgKVGhlIGJhbmQgb3JkZXIgaXM6IEJsdWUsIEdyZWVuLCBSZWQsIFJlZEVkZ2UsIGFuZCBOZWFyLUluZnJhcmVkLiAgCiRFRz0gMipHLVItQiQgIAokTkRWSSA9IChOSVIgLSBSZWQpLyhOSVIrUmVkKSQgIAokTkRSRSA9IChOSVIgLSBSZWRnZSkvKE5JUitSZWRnZSkkICAKJFZBUkkgPSAoRyAtIFIpLyhHICsgUiAtIEIpJCAgCmBgYHtyIGluZGV4fQpmX2NhbF9WSXM8LWZ1bmN0aW9uKGRpcl9kYXRhLFNpdGVuYW1lLFRpZm5hbWUsc2hwbmFtZSx6b25hbF9maWVsZCxtdWx0aXBsZT1UKXsKICBkYTwtYnJpY2socGFzdGUwKGRpcl9kYXRhLFNpdGVuYW1lLCIvT3JpZ2luYWxfaW1hZ2VzLyIsVGlmbmFtZSkpCiAgc2hwPC1yZWFkT0dSKHBhc3RlMChkaXJfZGF0YSxTaXRlbmFtZSwiL3NocHMiKSxzaHBuYW1lKQogIHNocDwtIHNwVHJhbnNmb3JtKHNocCwgQ1JTKHByb2o0c3RyaW5nKGRhKSkpCiAgCiAgZl9WQVJJPC1mdW5jdGlvbihyZWQsZ3JlZW4sYmx1ZSl7CiAgICAKICAgIFZBUkk8LShncmVlbi1yZWQpLyhncmVlbityZWQtYmx1ZSkKICAgIHJldHVybihWQVJJKQogIH0KICAKICBmX0VHPC1mdW5jdGlvbihyZWQsZ3JlZW4sYmx1ZSl7CiAgICAKICAgIEVHPC0yKmdyZWVuLXJlZC1ibHVlCiAgICByZXR1cm4oRUcpCiAgfQogIAogIGZfTkRWSTwtIGZ1bmN0aW9uKHJlZCwgbmlyKSB7CiAgICAgIG5kdmkgPC0gKG5pciAtIHJlZCkgLyAobmlyICsgcmVkKQogICAgICByZXR1cm4obmR2aSkKICB9CiAgZl9ORFJFPC0gZnVuY3Rpb24ocmVkZWdlLCBuaXIpIHsKICAgICAgbmRyZSA8LSAobmlyIC0gcmVkZWdlKSAvIChuaXIgKyByZWRlZ2UpCiAgICAgIHJldHVybihuZHJlKQogIH0gIAogIGlmKCFkaXIuZXhpc3RzKHBhc3RlMChkaXJfZGF0YSxTaXRlbmFtZSwiL1Jlc3VsdHMvVGlmcy8iKSkpeyAgZGlyLmNyZWF0ZShwYXN0ZTAoZGlyX2RhdGEsU2l0ZW5hbWUsIi9SZXN1bHRzL1RpZnMvIikpIH0KICAKICBwcmludChwYXN0ZTAoIkNhbGN1bGF0aW5nIHZlZ2V0YXRpb24gaW5kaWNlcyIpKQoKICBpZihtdWx0aXBsZSkgewogICAgdmlzPC1jKCJFRyIsIlZBUkkiLCJORFZJIiwiTkRSRSIpCiAgICAgICMgTkRWSQogICAgRUcgPC0gb3ZlcmxheShkYVtbM11dLCBkYVtbMl1dLGRhW1sxXV0sIGZ1bj1mX0VHKQogICAgVkFSSSA8LSBvdmVybGF5KGRhW1szXV0sIGRhW1syXV0sZGFbWzFdXSwgZnVuPWZfVkFSSSkKICAgIE5EVkkgPC0gb3ZlcmxheShkYVtbM11dLGRhW1s1XV0sIGZ1bj1mX05EVkkpCiAgICBORFJFIDwtIG92ZXJsYXkoZGFbWzRdXSxkYVtbNV1dLCBmdW49Zl9ORFJFKQogICAgVkFSSVtpcy5pbmZpbml0ZShWQVJJKSB8IGFicyhWQVJJKT4xXTwtMAogICAgTkRWSVtpcy5pbmZpbml0ZShORFZJKSB8IGFicyhORFZJKT4xXTwtMAogICAgTkRWSVtpcy5pbmZpbml0ZShORFJFKSB8IGFicyhORFJFKT4xXTwtMAogICAgcGRmKHBhc3RlMChkaXJfZGF0YSxTaXRlbmFtZSwiL1Jlc3VsdHMvIix1bmxpc3Qoc3Ryc3BsaXQoVGlmbmFtZSwgIi4iLCBmaXhlZCA9IFRSVUUpKVsxXSwiX05EVkkucGRmIiksd2lkdGg9MTQqZGFAbmNvbHMvZGFAbnJvd3MsaGVpZ2h0PTE0KQogICAgbWFwVGhlbWUgPC0gcmFzdGVyVGhlbWUocmVnaW9uPWJyZXdlci5wYWwoOCwiUmRZbEduIikpCiAgIHBsb3RzPC1sZXZlbHBsb3QoTkRWSSwgbWFyZ2luPUYsIHBhci5zZXR0aW5ncz1tYXBUaGVtZSxtYWluPSJORFZJIixwcmV0dHk9VFJVRSkjK2xheWVyKHNwLnBvaW50cyhzaHApKQogICBwcmludChwbG90cykKICAgZGV2Lm9mZigpCiAgICAjcHJpbnQocGxvdHMpCiAgICBWSXM8LXN0YWNrKEVHLFZBUkksTkRWSSxORFJFKQogICAgCiAgfWVsc2V7CiAgICB2aXM8LWMoIkVHIiwiVkFSSSIpCiAgICAjIEVHCiAgICBFRyA8LSBvdmVybGF5KGRhW1sxXV0sIGRhW1syXV0sZGFbWzNdXSwgZnVuPWZfRUcpCiAgICAjIHZhcmkKICAgIFZBUkkgPC0gb3ZlcmxheShkYVtbMV1dLCBkYVtbMl1dLGRhW1szXV0sIGZ1bj1mX1ZBUkkpCiAgICBWQVJJW2lzLmluZmluaXRlKFZBUkkpIHwgYWJzKFZBUkkpPjFdPC0wCgogICAgcGRmKHBhc3RlMChkaXJfZGF0YSxTaXRlbmFtZSwiL1Jlc3VsdHMvIix1bmxpc3Qoc3Ryc3BsaXQoVGlmbmFtZSwgIi4iLCBmaXhlZCA9IFRSVUUpKVsxXSwiX1ZBUkkucGRmIiksd2lkdGg9MTQqZGFAbmNvbHMvZGFAbnJvd3MsaGVpZ2h0PTE0KQogICAgbWFwVGhlbWUgPC0gcmFzdGVyVGhlbWUocmVnaW9uPWJyZXdlci5wYWwoOCwiUmRZbEduIikpCiAgICBwbG90czwtbGV2ZWxwbG90KFZBUkksIG1hcmdpbj1GLCBwYXIuc2V0dGluZ3M9bWFwVGhlbWUsbWFpbj0iVkFSSSIscHJldHR5PVRSVUUpIytsYXllcihzcC5wb2ludHMoc2hwKSkKICAgIHByaW50KHBsb3RzKQogICAgZGV2Lm9mZigpCiAgICAKICAgIFZJczwtc3RhY2soRUcsVkFSSSkKICB9CgogICMgem9uYWwgZGF0YQogIHByaW50KHBhc3RlMCgiWm9uYWxpbmcgdmVnZXRhdGlvbiBpbmRleCB1c2luZyB0aGUgZmllbGQgb2YgIix6b25hbF9maWVsZCkpCiAgZXggPC0gcmFzdGVyOjpleHRyYWN0KFZJcywgc2hwLCBidWZmZXI9MC41NjQsZnVuPW1lYW4sZGY9VCkKICBzdGFfc2hwIDwtIGFzLmRhdGEuZnJhbWUoZXgpCiAgbmFtZXMoc3RhX3NocCk8LWMoem9uYWxfZmllbGQsdmlzKQogIHN0YV9zaHBbem9uYWxfZmllbGRdIDwtIHNocFtbem9uYWxfZmllbGRdXQoKICAjIEV4cG9ydCB2aXMKICBmb3IoIHZhcm5hbWUgaW4gdmlzKXsKICAgIHByaW50KHBhc3RlMCgiZXhwb3J0aW5nICIsdmFybmFtZSkpCiAgICB3cml0ZVJhc3RlcihnZXQodmFybmFtZSkscGFzdGUwKGRpcl9kYXRhLFNpdGVuYW1lLCIvUmVzdWx0cy9uYy8iLHVubGlzdChzdHJzcGxpdChUaWZuYW1lLCAiLiIsIGZpeGVkID0gVFJVRSkpWzFdLCJfIix2YXJuYW1lLCIubmMiKSx2YXJuYW1lPXZhcm5hbWUseG5hbWU9ImxvbiIseW5hbWU9ImxhdCIsZm9ybWF0PSJDREYiLG92ZXJ3cml0ZT1UKQogICAgd3JpdGVSYXN0ZXIoZ2V0KHZhcm5hbWUpLHBhc3RlMChkaXJfZGF0YSxTaXRlbmFtZSwiL1Jlc3VsdHMvVGlmcy8iLHVubGlzdChzdHJzcGxpdChUaWZuYW1lLCAiLiIsIGZpeGVkID0gVFJVRSkpWzFdLCJfIix2YXJuYW1lLCIudGlmIiksZm9ybWF0PSJHVGlmZiIsb3ZlcndyaXRlPVQpCiAgfQogIAogIHJldHVybihzdGFfc2hwKQp9CgpmX3pvbmFsX1ZJPC1mdW5jdGlvbihkaXJfZGF0YSxTaXRlbmFtZSxUaWZuYW1lLHNocG5hbWUsem9uYWxfZmllbGQsVkluYW1lPSIiKXsKICBkYTwtcmFzdGVyKHBhc3RlMChkaXJfZGF0YSxTaXRlbmFtZSwiL09yaWdpbmFsX2ltYWdlcy8iLFRpZm5hbWUpKQogIGRhW2RhPjFdPC0wCiAgZGFbZGE8IDBdPC0wCiAgc2hwPC1yZWFkT0dSKHBhc3RlMChkaXJfZGF0YSxTaXRlbmFtZSwiL3NocHMiKSxzaHBuYW1lKQogIHNocDwtIHNwVHJhbnNmb3JtKHNocCwgQ1JTKHByb2o0c3RyaW5nKGRhKSkpCiAgCiAgaWYoIWRpci5leGlzdHMocGFzdGUwKGRpcl9kYXRhLFNpdGVuYW1lLCIvUmVzdWx0cy9UaWZzLyIpKSl7ICBkaXIuY3JlYXRlKHBhc3RlMChkaXJfZGF0YSxTaXRlbmFtZSwiL1Jlc3VsdHMvVGlmcy8iKSkgfQogIAogIHByaW50KHBhc3RlMCgiWm9uYWwgdmVnZXRhdGlvbiBpbmRleCIpKQoKICAgIHBkZihwYXN0ZTAoZGlyX2RhdGEsU2l0ZW5hbWUsIi9SZXN1bHRzLyIsdW5saXN0KHN0cnNwbGl0KFRpZm5hbWUsICIuIiwgZml4ZWQgPSBUUlVFKSlbMV0sIl8iLFZJbmFtZSwiLnBkZiIpLHdpZHRoPTE0KmRhQG5jb2xzL2RhQG5yb3dzLGhlaWdodD0xNCkKICAgIG1hcFRoZW1lIDwtIHJhc3RlclRoZW1lKHJlZ2lvbj1icmV3ZXIucGFsKDgsIlJkWWxHbiIpKQogICAgcGxvdHM8LWxldmVscGxvdChkYSwgbWFyZ2luPUYsIHBhci5zZXR0aW5ncz1tYXBUaGVtZSxtYWluPVZJbmFtZSxwcmV0dHk9VFJVRSkjK2xheWVyKHNwLnBvaW50cyhzaHApKQogICAgcHJpbnQocGxvdHMpCiAgICBkZXYub2ZmKCkKCiAgIyB6b25hbCBkYXRhCiAgcHJpbnQocGFzdGUwKCJab25hbGluZyB2ZWdldGF0aW9uIGluZGV4IHVzaW5nIHRoZSBmaWVsZCBvZiAiLHpvbmFsX2ZpZWxkKSkKICBleCA8LSByYXN0ZXI6OmV4dHJhY3QoYSwgc2hwLCBidWZmZXI9MC41NjQsZnVuPW1lYW4sZGY9VCkKICBzdGFfc2hwIDwtIGFzLmRhdGEuZnJhbWUoZXgpCiAgbmFtZXMoc3RhX3NocCk8LWMoem9uYWxfZmllbGQsVkluYW1lKQogIHN0YV9zaHBbem9uYWxfZmllbGRdIDwtIHNocFtbem9uYWxfZmllbGRdXQoKICByZXR1cm4oc3RhX3NocCkKfQojCgpmXzJpbmRleF9jYWw8LWZ1bmN0aW9uKGRpcl9kYXRhLGZpbGVuYW1lLGRhbmFtZSl7CiAgCiAgZGE8LWJyaWNrKGZpbGVuYW1lKQoKICAjIHRlc3QgdGhlIGlucHV0IGRhdGEKICBwZGYocGFzdGUoZGlyX2ltYWdlLGRhbmFtZSwiX1JHQi5wZGYiLHNlcD0iIikpCiAgI3Bsb3QoZGFbWzFdXSkKICBwbG90UkdCKGRhLCAxLCAyLCAzKQogICN0aXRsZShtYWluID0iUkdCIikKICBkZXYub2ZmKCkKICAKICAjIGNhbGN1bGF0ZSBhbmQgd3JpdGUgRUcKICAKICBFRyA8LSBjYWxjKGRhLCBmdW49Zl9FR19yYXN0ZXIpCiAgCiAgd3JpdGVSYXN0ZXIoRUcscGFzdGUoZGlyX2ltYWdlLGRhbmFtZSwiX0VHLnRpZiIsc2VwPSIiKSxmb3JtYXQ9IkdUaWZmIixvdmVyd3JpdGU9VCkKICAKICAjIGNhbGN1bGF0ZSBhbmQgd3JpdGUgVkFSSQogIFZBUkk8LW92ZXJsYXkoZGEsIGZ1bj1mX1ZBUklfcmFzdGVyKQogIHdyaXRlUmFzdGVyKFZBUkkscGFzdGUoZGlyX2ltYWdlLGRhbmFtZSwiX1ZBUkkudGlmIixzZXA9IiIpLGZvcm1hdD0iR1RpZmYiLG92ZXJ3cml0ZT1UKQogIAogICMgdGVzdCBFRyBhbmQgVkFSSQogIHBkZihwYXN0ZShkaXJfaW1hZ2UsZGFuYW1lLCJfaW5kZXgucGRmIixzZXA9IiIpKQogIHBsb3QoRUcpCiAgdGl0bGUobWFpbiA9IkVHIGluZGV4IikKICBwbG90KFZBUkkpCiAgdGl0bGUobWFpbiA9IlZBUkkgaW5kZXgiKQogIGRldi5vZmYoKQp9CgoKZl8yaW5kZXhfYXJyYXk8LWZ1bmN0aW9uKGRpcl9kYXRhLGZpbGVuYW1lLGRhbmFtZSxzaHA9TkEpewoKICBkYTwtYnJpY2soZmlsZW5hbWUpCiAgCiAgaWYoIWlzLm5hKHNocCkpewogICAgZGE8LWNyb3AoZGEsc2hwKQogIH0KICAKICAjIHRlc3QgdGhlIGlucHV0IGRhdGEKICBwZGYocGFzdGUoZGlyX2ltYWdlLGRhbmFtZSwiX1JHQi5wZGYiLHNlcD0iIikpCiAgcGxvdFJHQihkYSwgMSwgMiwgMyxtYWluPSJSR0IgaW1hZ2UiKQogICNwcmludChhKQogIGRldi5vZmYoKQogIAogIGRhX2FycmF5PC1hcy5hcnJheShkYSkKICAjIGNhbGN1bGF0ZSBhbmQgd3JpdGUgRUcKCiAgRUcgPC0gZl9FR19hcnJheShkYV9hcnJheSkKICBFR19yYXN0ZXI8LXJhc3RlcihFRyxkYUBleHRlbnRAeG1pbixkYUBleHRlbnRAeG1heCxkYUBleHRlbnRAeW1pbixkYUBleHRlbnRAeW1heCxjcnM9Y3JzKGRhKSkKICBwbG90KEVHX3Jhc3RlcikKICB3cml0ZVJhc3RlcihFR19yYXN0ZXIscGFzdGUoZGlyX2ltYWdlLGRhbmFtZSwiX0VHLnRpZiIsc2VwPSIiKSxmb3JtYXQ9IkdUaWZmIixvdmVyd3JpdGU9VCkKCiAgIyBjYWxjdWxhdGUgYW5kIHdyaXRlIFZBUkkKICBWQVJJPC1mX1ZBUklfYXJyYXkoZGFfYXJyYXkpCiAgVkFSSV9yYXN0ZXI8LXJhc3RlcihWQVJJLGRhQGV4dGVudEB4bWluLGRhQGV4dGVudEB4bWF4LGRhQGV4dGVudEB5bWluLGRhQGV4dGVudEB5bWF4LGNycz1jcnMoZGEpKQogIHdyaXRlUmFzdGVyKFZBUklfcmFzdGVyLHBhc3RlKGRpcl9pbWFnZSxkYW5hbWUsIl9WQVJJLnRpZiIsc2VwPSIiKSxmb3JtYXQ9IkdUaWZmIixvdmVyd3JpdGU9VCkKCiAgIyB0ZXN0IEVHIGFuZCBWQVJJCiAgcGRmKHBhc3RlKGRpcl9pbWFnZSxkYW5hbWUsIl9pbmRleC5wZGYiLHNlcD0iIikpCiAgcGxvdChFR19yYXN0ZXIpCiAgdGl0bGUobWFpbiA9IkVHIGluZGV4IikKICBwbG90KFZBUklfcmFzdGVyKQogIHRpdGxlKG1haW4gPSJWQVJJIGluZGV4IikKICBkZXYub2ZmKCkKfQoKYGBgCgojIFNpdGVzCgojIyBNZWNrZXJpbmcKVGhlIGJhbmQgb3JkZXIgaXM6IEJsdWUsIEdyZWVuLCBSZWQsIFJlZEVkZ2UsIGFuZCBOZWFyLUluZnJhcmVkLgpgYGB7cn0KZGlyX2RhdGE8LSIvd3d3L1N0YW4vIgojIFpvbmFsIGRhdGEgZm9yIGVhY2ggc2l0ZQpNZWNrZXJpbmdfVklzX01lY2tlcmluZ190cmlhbDwtZl9jYWxfVklzKAogIGRpcl9kYXRhPSIvd3d3L1N0YW4vIiwKICBTaXRlbmFtZT0iTWVja2VyaW5nIiwKICBUaWZuYW1lPSJNZWNrZXJpbmdfdHJpYWxfc2l0ZS50aWYiLAogIHNocG5hbWU9Ik1lY2tlcmluZ190cmlhbCIsCiAgem9uYWxfZmllbGQ8LSJpZCIsCiAgbXVsdGlwbGU9RgogICkKc2F2ZShWSXNfTWVja2VyaW5nX3RyaWFsLGZpbGUgPSBwYXN0ZTAoZGlyX2RhdGEsIlRtcC9WSXNfTWVja2VyaW5nX3RyaWFsLlJEYXRhIikpCgpNZWNrZXJpbmdfVklzXzA4MjAxNzwtZl9jYWxfVklzKAogIGRpcl9kYXRhPSIvd3d3L1N0YW4vIiwKICBTaXRlbmFtZT0iTWVja2VyaW5nIiwKICBUaWZuYW1lPSJBdWd1c3RfbXVsdGlfMjAxNy50aWYiLAogIHNocG5hbWU9Ik1lY2tfQXVnX3NhbXBsZV9wb2ludHMiLAogIHpvbmFsX2ZpZWxkPC0iaWQiCiAgKQpzYXZlKE1lY2tlcmluZ19WSXNfMDgyMDE3LGZpbGUgPSBwYXN0ZTAoZGlyX2RhdGEsIlRtcC9NZWNrZXJpbmdfVklzXzA4MjAxNy5SRGF0YSIpKQoKTWVja2VyaW5nX1ZJc18xMDIwMTc8LWZfY2FsX1ZJcygKICBkaXJfZGF0YT0iL3d3dy9TdGFuLyIsCiAgU2l0ZW5hbWU9Ik1lY2tlcmluZyIsCiAgVGlmbmFtZT0iT2N0b2Jlcl9tdWx0aV8yMDE3LnRpZiIsCiAgc2hwbmFtZT0iTWVja19PY3Rfc2FtcGxlX3BvaW50cyIsCiAgem9uYWxfZmllbGQ8LSJpZCIKICApCnNhdmUoTWVja2VyaW5nX1ZJc18xMDIwMTcsZmlsZSA9IHBhc3RlMChkaXJfZGF0YSwiVG1wL01lY2tlcmluZ19WSXNfMTAyMDE3LlJEYXRhIikpCgpNZWNrZXJpbmdfVklzXzA5MjAxNzwtZl9jYWxfVklzKAogIGRpcl9kYXRhPSIvd3d3L1N0YW4vIiwKICBTaXRlbmFtZT0iTWVja2VyaW5nIiwKICBUaWZuYW1lPSJTZXB0ZW1iZXJfbXVsdGlfMjAxNy50aWYiLAogIHNocG5hbWU9Ik1lY2tfU2VwdF9zYW1wbGVfcG9pbnRzIiwKICB6b25hbF9maWVsZDwtImlkIgogICkKc2F2ZShNZWNrZXJpbmdfVklzXzA5MjAxNyxmaWxlID0gcGFzdGUwKGRpcl9kYXRhLCJUbXAvTWVja2VyaW5nX1ZJc18wOTIwMTcuUkRhdGEiKSkKYGBgCiMjIE1lcmdlIHdpdGggTUVEIGFuZCBvdGhlciBkYXRhCmBgYHtyfQpNRUQ8LXJlYWQuY3N2KHBhc3RlMChkaXJfZGF0YSwiTWVja2VyaW5nL2RhdGEvTWVja2VyaW5nX21lZF9tb2lzdC5jc3YiKSkKTUVEPC1NRURbLTEwXQoKbG9hZChwYXN0ZTAoZGlyX2RhdGEsIlRtcC9NZWNrZXJpbmdfVklzXzA5MjAxNy5SRGF0YSIpKQpsb2FkKHBhc3RlMChkaXJfZGF0YSwiVG1wL01lY2tlcmluZ19WSXNfMDgyMDE3LlJEYXRhIikpCmxvYWQocGFzdGUwKGRpcl9kYXRhLCJUbXAvTWVja2VyaW5nX1ZJc18xMDIwMTcuUkRhdGEiKSkKCk1lY2tlcmluZ19WSXNfMDkyMDE3JERhdGU8LSIwOTIwMTciCk1lY2tlcmluZ19WSXNfMDgyMDE3JERhdGU8LSIwODIwMTciCk1lY2tlcmluZ19WSXNfMTAyMDE3JERhdGU8LSIxMDIwMTciCgpWSXM8LXJiaW5kKE1lY2tlcmluZ19WSXNfMDkyMDE3LE1lY2tlcmluZ19WSXNfMDgyMDE3LE1lY2tlcmluZ19WSXNfMTAyMDE3KQpuYW1lcyhWSXMpWzFdPC0ic2FtcGxlcyIKbGlicmFyeShyZXNoYXBlMikKYTwtbWVsdChWSXMsaWQ9Yygic2FtcGxlcyIsIkRhdGUiKSkKVklzPC1kY2FzdChhLHNhbXBsZXN+dmFyaWFibGUrRGF0ZSkKCk1lcmdlX2RhdGE8LW1lcmdlKE1FRCxWSXMsYWxsLnggPSBULGJ5PSJzYW1wbGVzIikKCndyaXRlLmNzdihNZXJnZV9kYXRhLHBhc3RlMChkaXJfZGF0YSxTaXRlbmFtZSwiL1Jlc3VsdHMvIixTaXRlbmFtZSwiX01lcmdlX01FRF9WSXMuY3N2Iikscm93Lm5hbWVzID0gRikKCmxpYnJhcnkoZ2dwbG90MikKZ2dwbG90KGRhdGEgPU1lcmdlX2RhdGEsYWVzKHg9TkRWSV8wOTIwMTcseT1tZWRfMDgwNyxjb2w9UG9zaXRpb24pKStnZW9tX3BvaW50KCkrZmFjZXRfd3JhcCh+UG9zaXRpb24pCgpsaWJyYXJ5KGRwbHlyKQoKY29yLnRlc3QoTWVyZ2VfZGF0YSRORFZJLE1lcmdlX2RhdGEkbWVkXzA4MDcpCgpgYGAKCiMjIEtvam9udXAKYGBge3IgS29qb251cH0Kc2hwZmlsZTwtIktvam9udXBfMjAxN19zYW1wbGVfcG9pbnRzIgojIFpvbmFsIGRhdGEgZm9yIGVhY2ggc2l0ZQpWSXNfS29qb251cF90cmlhbDwtZl9jYWxfVklzKAogIGRpcl9kYXRhPSIvd3d3L1N0YW4vIiwKICBTaXRlbmFtZT0iS29qb251cCIsCiAgVGlmbmFtZT0iU2VwdF8yMDE3X211bHRpX21vZGlmaWVkLnRpZiIsCiAgc2hwbmFtZT1zaHBmaWxlLAogIHpvbmFsX2ZpZWxkPC0iaWQiLAogIG11bHRpcGxlPUYKICApCgpzaHBmaWxlPC0iS29qb251cF8yMDE3X3NhbXBsZV9wb2ludHMiCiMgWm9uYWwgZGF0YSBmb3IgZWFjaCBzaXRlClZJc19Lb2pvbnVwX3RyaWFsPC1mX2NhbF9WSXMoCiAgZGlyX2RhdGE9Ii93d3cvU3Rhbi8iLAogIFNpdGVuYW1lPSJLb2pvbnVwIiwKICBUaWZuYW1lPSJLb2pvbnVwLVRvdC1Qb3QtVXJhLVRoby50aWYiLAogIHNocG5hbWU9c2hwZmlsZSwKICB6b25hbF9maWVsZDwtImlkIiwKICBtdWx0aXBsZT1GCiAgKQoKc2F2ZShWSXNfS29qb251cF90cmlhbCxmaWxlID0gIi9EYXRhc2V0L3d3dy9TdGFuL1RtcC9WSXNfS29qb251cF90cmlhbC5SRGF0YSIpCgoKS29qb251cF9WSXNfMDkyMDE3PC1mX2NhbF9WSXMoCiAgZGlyX2RhdGE9Ii93d3cvU3Rhbi8iLAogIFNpdGVuYW1lPSJLb2pvbnVwIiwKICBUaWZuYW1lPSJTZXB0XzIwMTdfbXVsdGlfbW9kaWZpZWQudGlmIiwKICBzaHBuYW1lPXNocGZpbGUsCiAgem9uYWxfZmllbGQ8LSJpZCIKICApCnNhdmUoS29qb251cF9WSXNfMDkyMDE3LGZpbGUgPSAiL3d3dy9TdGFuL1RtcC9Lb2pvbnVwX1ZJc18wOTIwMTcuUkRhdGEiKQoKS29qb251cF9WSXNfMTAyMDE3PC1mX2NhbF9WSXMoCiAgZGlyX2RhdGE9Ii93d3cvU3Rhbi8iLAogIFNpdGVuYW1lPSJLb2pvbnVwIiwKICBUaWZuYW1lPSJPY3RfMjAxN19tdWx0aV9tb2RpZmllZC50aWYiLAogIHNocG5hbWU9c2hwZmlsZSwKICB6b25hbF9maWVsZDwtImlkIgogICkKc2F2ZShLb2pvbnVwX1ZJc18xMDIwMTcsZmlsZSA9ICIvd3d3L1N0YW4vVG1wL0tvam9udXBfVklzXzEwMjAxNy5SRGF0YSIpCgoKS29qb251cF9GbGlnaHQyPC1mX3pvbmFsX1ZJKAogIGRpcl9kYXRhPSIvd3d3L1N0YW4vIiwKICBTaXRlbmFtZT0iS29qb251cCIsCiAgVGlmbmFtZT0iTm9ydGhfS29qb251cF9GbGlnaHRfMl9ORFZJX3BvbHkxX2xhbmN6b3MudGlmIiwKICBzaHBuYW1lPXNocGZpbGUsCiAgem9uYWxfZmllbGQ8LSJpZCIsCiAgVkluYW1lID0gIk5EVkkiCiAgKQpzYXZlKEtvam9udXBfRmxpZ2h0MixmaWxlID0gIi93d3cvU3Rhbi9UbXAvS29qb251cF9GbGlnaHQyLlJEYXRhIikKCnBsb3QoYSkKcGxvdChzaHAsYWRkPVQpCgoKCktvam9udXBfRmxpZ2h0NDwtZl9jYWxfVklzKAogIGRpcl9kYXRhPSIvd3d3L1N0YW4vIiwKICBTaXRlbmFtZT0iS29qb251cCIsCiAgVGlmbmFtZT0iTm9ydGhfS29qb251cF9GbGlnaHRfNF9ORFZJX3BvbHkxX2xhbmN6b3MudGlmIiwKICBzaHBuYW1lPXNocGZpbGUsCiAgem9uYWxfZmllbGQ8LSJpZCIKICApCnNhdmUoS29qb251cF9GbGlnaHQ0LGZpbGUgPSAiL3d3dy9TdGFuL1RtcC9Lb2pvbnVwX0ZsaWdodDQuUkRhdGEiKQoKS29qb251cF9GbGlnaHQ1PC1mX2NhbF9WSXMoCiAgZGlyX2RhdGE9Ii93d3cvU3Rhbi8iLAogIFNpdGVuYW1lPSJLb2pvbnVwIiwKICBUaWZuYW1lPSJOb3J0aF9Lb2pvbnVwX0ZsaWdodF81X05EVklfcG9seTFfbGFuY3pvcy50aWYiLAogIHNocG5hbWU9c2hwZmlsZSwKICB6b25hbF9maWVsZDwtImlkIgogICkKc2F2ZShLb2pvbnVwX0ZsaWdodDUsZmlsZSA9ICIvd3d3L1N0YW4vVG1wL0tvam9udXBfRmxpZ2h0NS5SRGF0YSIpCgpgYGAKCgojIyBNZXJnZSBNRUQKYGBge3J9Ck1FRDwtcmVhZC5jc3YoIi93d3cvU3Rhbi9Lb2pvbnVwL2RhdGEvS29qb251cF9tZWRfbW9pc3QuY3N2IikKCmxvYWQoIi93d3cvU3Rhbi9UbXAvS29qb251cF9WSXNfMDkyMDE3LlJEYXRhIikKbG9hZCgiL3d3dy9TdGFuL1RtcC9Lb2pvbnVwX1ZJc18xMDIwMTcuUkRhdGEiKQoKS29qb251cF9WSXNfMDkyMDE3JERhdGU8LSIwOTIwMTciCktvam9udXBfVklzXzEwMjAxNyREYXRlPC0iMTAyMDE3IgoKVklzPC1yYmluZChLb2pvbnVwX1ZJc18wOTIwMTcsS29qb251cF9WSXNfMTAyMDE3KQpuYW1lcyhWSXMpWzFdPC0iU2FtcGxlcyIKbGlicmFyeShyZXNoYXBlMikKYTwtbWVsdChWSXMsaWQ9YygiU2FtcGxlcyIsIkRhdGUiKSkKVklzPC1kY2FzdChhLFNhbXBsZXN+dmFyaWFibGUrRGF0ZSkKCk1lcmdlX2RhdGE8LW1lcmdlKE1FRCxWSXMsYWxsLnggPSBULGJ5PSJTYW1wbGVzIikKCndyaXRlLmNzdihNZXJnZV9kYXRhLCIvd3d3L1N0YW4vS29qb251cC9SZXN1bHRzL01lcmdlX01FRF9WSXMuY3N2Iixyb3cubmFtZXMgPSBGKQoKCmBgYAoKIyBQcm9jZXNzIFJhZGltYXRyaXggZGF0YQoKIyMgU2l0ZXMKYGBge3J9CiMgaW50ZXJwbGF0ZSBwb2ludHMgdXNpbmcgSURXIApmX3Bsb3RyYWQ8LWZ1bmN0aW9uKGRhLGRmLHZhcm5hbWUpewogIGxpYnJhcnkoZ3N0YXQpCiAgcjwtcmFzdGVyKG1hdHJpeCgxLG5yb3c9YXMuaW50ZWdlcihkYUBucm93cy8xMCksbmNvbD1hcy5pbnRlZ2VyKGRhQG5jb2xzLzEwKSkseG1uPWRhQGV4dGVudEB4bWluLHhteD1kYUBleHRlbnRAeG1heCx5bW49ZGFAZXh0ZW50QHltaW4seW14PWRhQGV4dGVudEB5bWF4LGNycz1DUlMoIitwcm9qPWxvbmdsYXQgK2RhdHVtPVdHUzg0ICtub19kZWZzICtlbGxwcz1XR1M4NCArdG93Z3M4ND0wLDAsMCIpKQogICMgaW50ZXJwb2xhdGUKICBtZyA8LSBnc3RhdChpZCA9IHZhcm5hbWUsIGZvcm11bGEgPSBnZXQodmFybmFtZSl+MSwgbG9jYXRpb25zID0gfngreSwgZGF0YT1kZiwgCiAgICAgICAgICAgICAgbm1heD03LCBzZXQ9bGlzdChpZHAgPSAuNSkpCiAgeiA8LSBpbnRlcnBvbGF0ZShyLCBtZykKICB6IDwtIG1hc2soeiwgcikKICBuYW1lcyh6KTwtdmFybmFtZQogIG1hcFRoZW1lIDwtIHJhc3RlclRoZW1lKHJlZ2lvbj1icmV3ZXIucGFsKDgsIkJsdWVzIikpCiAgcGx0IDwtIGxldmVscGxvdCh6LCBtYXJnaW49RiwgcGFyLnNldHRpbmdzPW1hcFRoZW1lLG1haW49dmFybmFtZSxwcmV0dHk9VFJVRSkKICBwbHQKICByZXR1cm4oeikKfQoKCmRhPC1yYXN0ZXIoIi93d3cvU3Rhbi8yMDE4L0JhZGdpbmdhcnJhL01jQWxwaW5lcGFkZG9jazIxNzA3MjAxN19WSVMubmMiKQpzaHA8LXJlYWRPR1IoIi93d3cvU3Rhbi8yMDE4L0JhZGdpbmdhcnJhIiwiYm91bmRhcnkiKQpwcmludChkYSkKCiMgcmVhZCByYWQgRU0gZGF0YSBhbmQgc2VsZWN0IHVzZWZ1bCBjb2x1bW5zCnJhZDwtcmVhZC5jc3YoIi93d3cvU3Rhbi8yMDE4L0VNX2FuZF9HYW1tYS9FTV9hbmRfZ2FtbWEvRU0vQmFkZ2luZ2FycmEgRU0uY3N2IixoZWFkZXIgPSBGLHN0cmluZ3NBc0ZhY3RvcnM9RikKCgojIyBMb2FkIFRPVGwgZGF0YQpyYWQ8LXJlYWQuY3N2KCIvd3d3L1N0YW4vMjAxOC9FTV9hbmRfR2FtbWEvRU1fYW5kX2dhbW1hL0dhbW1hL0JhZGdpbmdhcnJhIGdhbW1hLmNzdiIsaGVhZGVyID1ULHN0cmluZ3NBc0ZhY3RvcnM9RikKcmFkPC1yYWRbYyg0LDMsNTo5KV0KbmFtZXMocmFkKTwtYygieSIsIngiLCJFbGUiLCJUb3RDb3VudCIsIlBvdGFzc2l1bSIsIlVyYW5pdW0iLCJUaG9yaXVtIikKCnJhZDwtc3Vic2V0KHJhZCx4PjApCmE8LWZfcGxvdHJhZChyZXNvbHV0aW9uID0gMC4wMDAwMSxkZiA9IHJhZCx2YXJuYW1lID0gIlRvdENvdW50IikKYjwtZl9wbG90cmFkKHJlc29sdXRpb24gPSAwLjAwMDAxLGRmID0gcmFkLHZhcm5hbWUgPSAiUG90YXNzaXVtIikKYzwtZl9wbG90cmFkKHJlc29sdXRpb24gPSAwLjAwMDAxLGRmID0gcmFkLHZhcm5hbWUgPSAiVXJhbml1bSIpCmQ8LWZfcGxvdHJhZChyZXNvbHV0aW9uID0gMC4wMDAwMSxkZiA9IHJhZCx2YXJuYW1lID0gIlRob3JpdW0iKQpjYyA8LSBicmljayhhLGIsYyxkKQoKd3JpdGVSYXN0ZXIoY2MsZmlsZW5hbWUgPSAiL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL3Jlc3VsdC9CYWRnaW5nYXJyYS1Ub3QtUG90LVVyYS1UaG8udGlmIixmb3JtYXQ9IkdUaWZmIixvdmVyd3JpdGU9VCkKCgpyYWQ8LXJlYWQuY3N2KCIvd3d3L1N0YW4vMjAxOC9FTV9hbmRfR2FtbWEvRU1fYW5kX2dhbW1hL0VNL0tvam9udXAgRU0uY3N2IixoZWFkZXIgPSBGLHN0cmluZ3NBc0ZhY3RvcnM9RikKCnJhZDwtcmFkW2MoNSw2LDEwLDE3LDE4LDE5LDIwKV0KbmFtZXMocmFkKTwtYygieSIsIngiLCJFbGUiLCJFTWQiLCJNRzEiLCJFTXMiLCJNRzIiKQoKcmFkPC1yZWFkLmNzdigiL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL0VNX2FuZF9nYW1tYS9HYW1tYS9CYWRnaW5nYXJyYSBnYW1tYS5jc3YiKQpyYWQ8LXJlYWQuY3N2KCIvd3d3L1N0YW4vMjAxOC9FTV9hbmRfR2FtbWEvRU1fYW5kX2dhbW1hL0dhbW1hL0tvam9udXAgZ2FtbWEuY3N2IikKcmFkPC1yYWRbMzo5XQpuYW1lcyhyYWQpPC1jKCJ4IiwieSIsIkVsZSIsIlRvdGFsY291bnQiLCJQb3Rhc3NpdW0iLCJVcmFuaXVtIiwiVGhvcml1bSIpCgoKIyB0cmFuc2ZlciBjc3YgdG8gc3BhdGlsIHBvaW50cwp4eSA8LSByYWRbLGMoIngiLCJ5IildICMgbG9uZyArIGxhdApzcGRmIDwtIFNwYXRpYWxQb2ludHNEYXRhRnJhbWUoY29vcmRzID0geHksIGRhdGEgPSByYWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9qNHN0cmluZyA9IENSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQgK25vX2RlZnMgK2VsbHBzPVdHUzg0ICt0b3dnczg0PTAsMCwwIikpCgojIGNsaXAgcG9pbnRzIGRhdGEgYmFzZWQgb24gdGhlIG91dGxpbnQgcG9seWdvbgpzcGRmLmNsaXAgPC0gc3BkZltzaHAsIF0KCnBkZigiL3d3dy9TdGFuL2dhbW1hLnBkZiIpCmZvciAodmFyIGluIG5hbWVzKHJhZClbLWMoMTozKV0pewogIAogIHByaW50KGZfcGxvdHJhZChhLHNwZGZAZGF0YSx2YXIpKQoKfQoKZGV2Lm9mZigpCmZvciAodmFyIGluIG5hbWVzKHJhZClbLWMoMTozKV0pewogIAogIHp6PC1mX3Bsb3RyYWQoYSxzcGRmQGRhdGEsdmFyKQogIGZfcGxvdF9zcCh6eixmaWxlbmFtZSA9IHBhc3RlMCgiL3d3dy9TdGFuLyIsdmFyLCIucGRmIiksdmFybmFtZXMgPSB2YXIsY3V0cyA9IDEwKQp9CgpyPC1mX3Bsb3RyYWQoYSxzcGRmQGRhdGEsIlBvdGFzc2l1bSIpCmI8LWZfcGxvdHJhZChhLHNwZGZAZGF0YSwiVXJhbml1bSIpCmc8LWZfcGxvdHJhZChhLHNwZGZAZGF0YSwiVGhvcml1bSIpCgpjIDwtIGJyaWNrKHIsZyxiKQp3cml0ZVJhc3RlcihjLCIvd3d3L1N0YW4vS29qb251cC9SZXN1bHRzL0tvam51cF9nYW1tYS50aWYiLGZvcm1hdD0iR1RpZmYiLG92ZXJ3cml0ZT1UKQpwZGYoIi93d3cvU3Rhbi9yYWRfcGxvdC5wZGYiKQptYXBUaGVtZSA8LSByYXN0ZXJUaGVtZShyZWdpb249YnJld2VyLnBhbCg4LCJSZWRzIikpCmxldmVscGxvdChyLCBtYXJnaW49RiwgcGFyLnNldHRpbmdzPW1hcFRoZW1lLG1haW49IlBvdGFzc2l1bSIscHJldHR5PVRSVUUpCm1hcFRoZW1lIDwtIHJhc3RlclRoZW1lKHJlZ2lvbj1icmV3ZXIucGFsKDgsIkdyZWVucyIpKQpsZXZlbHBsb3QoZywgbWFyZ2luPUYsIHBhci5zZXR0aW5ncz1tYXBUaGVtZSxtYWluPSJUaG9yaXVtIixwcmV0dHk9VFJVRSkKbWFwVGhlbWUgPC0gcmFzdGVyVGhlbWUocmVnaW9uPWJyZXdlci5wYWwoOCwiQmx1ZXMiKSkKbGV2ZWxwbG90KGIsIG1hcmdpbj1GLCBwYXIuc2V0dGluZ3M9bWFwVGhlbWUsbWFpbj0iVXJhbml1bSIscHJldHR5PVRSVUUpCgpwbG90UkdCKGMsIDEsIDIsMywgc3RyZXRjaD0iaGlzdCIpCgpkZXYub2ZmKCkKIyB9CgpwbG90KHIpCnBsb3Qoc2hwLGFkZD1UKQoKCmBgYAoKIyMgU2l0ZXNfZnVuY3Rpb24KYGBge3J9CiMgaW50ZXJwbGF0ZSBwb2ludHMgdXNpbmcgSURXIApmX3Bsb3RyYWQ8LWZ1bmN0aW9uKHJlc29sdXRpb24sZGYsdmFybmFtZSl7CiAgbGlicmFyeShnc3RhdCkKICBsaWJyYXJ5KHJhc3RlclZpcykKICAjIGludGVycG9sYXRlCiAgbGF0czwtcmFuZ2UoZGYkeSkKICBsb25nczwtcmFuZ2UoZGYkeCkKICByb3dzPC1yb3VuZCgobGF0c1syXS1sYXRzWzFdKS9yZXNvbHV0aW9uLDApCiAgY29sczwtcm91bmQoKGxvbmdzWzJdLWxvbmdzWzFdKS9yZXNvbHV0aW9uLDApCiAgICAKICByPC1yYXN0ZXIobWF0cml4KDEsbnJvdz1yb3dzLG5jb2w9Y29scykseG1uPWxvbmdzWzFdLHhteD1sb25nc1syXSx5bW49bGF0c1sxXSx5bXg9bGF0c1syXSxjcnM9Q1JTKCIrcHJvaj1sb25nbGF0ICtkYXR1bT1XR1M4NCArbm9fZGVmcyArZWxscHM9V0dTODQgK3Rvd2dzODQ9MCwwLDAiKSkKICBtZyA8LSBnc3RhdChpZCA9IHZhcm5hbWUsIGZvcm11bGEgPSBnZXQodmFybmFtZSl+MSwgbG9jYXRpb25zID0gfngreSwgZGF0YT1kZiwgCiAgICAgICAgICAgICAgbm1heD03LCBzZXQ9bGlzdChpZHAgPSAuNSkpCiAgeiA8LSBpbnRlcnBvbGF0ZShyLCBtZykKICB6IDwtIG1hc2soeiwgcikKICBuYW1lcyh6KTwtdmFybmFtZQogICMgbWFwVGhlbWUgPC0gcmFzdGVyVGhlbWUocmVnaW9uPWJyZXdlci5wYWwoOCwiQmx1ZXMiKSkKICAjIHBsdCA8LSBsZXZlbHBsb3QoeiwgbWFyZ2luPUYsIHBhci5zZXR0aW5ncz1tYXBUaGVtZSxtYWluPXZhcm5hbWUscHJldHR5PVRSVUUpCiAgIyBwbHQKICByZXR1cm4oeikKfQoKCiMjIExvYWQgVE9UbCBkYXRhCmZfZ2FtbWE8LWZ1bmN0aW9uKGlucHV0LHJlc29sdXRpb249MC4wMDAwMSxwbG90bmFtZT0iL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL3Jlc3VsdC9XZXN0LUNoZXN0ZXItMi1Ub3QtUG90LVVyYS1UaG8ucGRmIixvdXRwdXQ9Ii93d3cvU3Rhbi8yMDE4L0VNX2FuZF9HYW1tYS9yZXN1bHQvV2VzdC1DaGVzdGVyLTItVG90LVBvdC1VcmEtVGhvLnRpZiIscGxvdD1GKXsKcHJpbnQoaW5wdXQpCnJhZDwtcmVhZC5jc3YoaW5wdXQsaGVhZGVyID1ULHN0cmluZ3NBc0ZhY3RvcnM9RikKcmFkPC1yYWRbYyg0LDMsNTo5KV0KbmFtZXMocmFkKTwtYygieSIsIngiLCJFbGUiLCJUb3RDb3VudCIsIlBvdGFzc2l1bSIsIlVyYW5pdW0iLCJUaG9yaXVtIikKCnJhZDwtc3Vic2V0KHJhZCx4PjApCmE8LWZfcGxvdHJhZChyZXNvbHV0aW9uID0gcmVzb2x1dGlvbixkZiA9IHJhZCx2YXJuYW1lID0gIlRvdENvdW50IikKYjwtZl9wbG90cmFkKHJlc29sdXRpb24gPSByZXNvbHV0aW9uLGRmID0gcmFkLHZhcm5hbWUgPSAiUG90YXNzaXVtIikKYzwtZl9wbG90cmFkKHJlc29sdXRpb24gPSByZXNvbHV0aW9uLGRmID0gcmFkLHZhcm5hbWUgPSAiVXJhbml1bSIpCmQ8LWZfcGxvdHJhZChyZXNvbHV0aW9uID0gcmVzb2x1dGlvbixkZiA9IHJhZCx2YXJuYW1lID0gIlRob3JpdW0iKQpjYyA8LSBicmljayhhLGIsYyxkKQppZihwbG90KSB7CiAgcGRmKHBsb3RuYW1lKQogIG1hcFRoZW1lIDwtIHJhc3RlclRoZW1lKHJlZ2lvbj1icmV3ZXIucGFsKDgsIlJlZHMiKSkKICBwcmludChsZXZlbHBsb3QoYiwgbWFyZ2luPUYsIHBhci5zZXR0aW5ncz1tYXBUaGVtZSxtYWluPSJQb3Rhc3NpdW0iLHByZXR0eT1UUlVFKSkKICBtYXBUaGVtZSA8LSByYXN0ZXJUaGVtZShyZWdpb249YnJld2VyLnBhbCg4LCJHcmVlbnMiKSkKICBwcmludChsZXZlbHBsb3QoZCwgbWFyZ2luPUYsIHBhci5zZXR0aW5ncz1tYXBUaGVtZSxtYWluPSJUaG9yaXVtIixwcmV0dHk9VFJVRSkpCiAgbWFwVGhlbWUgPC0gcmFzdGVyVGhlbWUocmVnaW9uPWJyZXdlci5wYWwoOCwiQmx1ZXMiKSkKIHByaW50KCBsZXZlbHBsb3QoYywgbWFyZ2luPUYsIHBhci5zZXR0aW5ncz1tYXBUaGVtZSxtYWluPSJVcmFuaXVtIixwcmV0dHk9VFJVRSkpCiAgZGV2Lm9mZigpCn0KCndyaXRlUmFzdGVyKGNjLGZpbGVuYW1lID0gb3V0cHV0LGZvcm1hdD0iR1RpZmYiLG92ZXJ3cml0ZT1UKQp9CgojIEtvam9udXAgc2l0ZSAtLS0tLS0tLQpmX2dhbW1hKGlucHV0ID0gIi93d3cvU3Rhbi8yMDE4L0VNX2FuZF9HYW1tYS9FTV9hbmRfZ2FtbWEvR2FtbWEvS29qb251cCBnYW1tYS5jc3YiLAogICAgICAgcGxvdG5hbWU9Ii93d3cvU3Rhbi8yMDE4L0VNX2FuZF9HYW1tYS9yZXN1bHQvS29qb251cC1Ub3QtUG90LVVyYS1UaG8ucGRmIiwKICAgICAgIG91dHB1dD0iL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL3Jlc3VsdC9Lb2pvbnVwLVRvdC1Qb3QtVXJhLVRoby50aWYiLAogICAgICAgcGxvdD1UKQojIEJhZGdpbmdhcnJhIHNpdGUgLS0tLS0tLS0KZl9nYW1tYShpbnB1dCA9ICIvd3d3L1N0YW4vMjAxOC9FTV9hbmRfR2FtbWEvRU1fYW5kX2dhbW1hL0dhbW1hL0JhZGdpbmdhcnJhIGdhbW1hLmNzdiIsCiAgICAgICBwbG90bmFtZT0iL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL3Jlc3VsdC9CYWRnaW5nYXJyYS1Ub3QtUG90LVVyYS1UaG8ucGRmIiwKICAgICAgIG91dHB1dD0iL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL3Jlc3VsdC9CYWRnaW5nYXJyYS1Ub3QtUG90LVVyYS1UaG8udGlmIiwKICAgICAgIHBsb3Q9VCkKIyBNb29yYSBzaXRlIC0tLS0tLS0tCmZfZ2FtbWEoaW5wdXQgPSAiL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL0VNX2FuZF9nYW1tYS9HYW1tYS9Nb29yYS9Nb29yYSBQbG90IDMgZ2FtbWEuY3N2IiwKICAgICAgIHBsb3RuYW1lPSIvd3d3L1N0YW4vMjAxOC9FTV9hbmRfR2FtbWEvcmVzdWx0L01vb3JhX1Bsb3RfMy1Ub3QtUG90LVVyYS1UaG8ucGRmIiwKICAgICAgIG91dHB1dD0iL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL3Jlc3VsdC9Nb29yYV9QbG90XzMtVG90LVBvdC1VcmEtVGhvLnRpZiIsCiAgICAgICBwbG90PVQpCmZfZ2FtbWEoaW5wdXQgPSAiL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL01vb3JhX2xhcmdlX3NjYWxlL0RFWF8yMDE4MDIxMl8wNTA3NDUuY3N2IiwKICAgICAgIHBsb3RuYW1lPSIvd3d3L1N0YW4vMjAxOC9FTV9hbmRfR2FtbWEvcmVzdWx0L0RFWC1Ub3QtUG90LVVyYS1UaG8ucGRmIiwKICAgICAgIG91dHB1dD0iL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL3Jlc3VsdC9ERVgtVG90LVBvdC1VcmEtVGhvLnRpZiIsCiAgICAgICBwbG90PVQpCgoKZl9FTTwtZnVuY3Rpb24oaW5wdXQscmVzb2x1dGlvbj0wLjAwMDAxLHBsb3RuYW1lPSIvd3d3L1N0YW4vMjAxOC9FTV9hbmRfR2FtbWEvcmVzdWx0L1dlc3QtQ2hlc3Rlci0yLVRvdC1Qb3QtVXJhLVRoby5wZGYiLG91dHB1dD0iL3d3dy9TdGFuLzIwMTgvRU1fYW5kX0dhbW1hL3Jlc3VsdC9XZXN0LUNoZXN0ZXItMi1Ub3QtUG90LVVyYS1UaG8udGlmIixwbG90PUYpewpwcmludChpbnB1dCkKcmFkPC1yZWFkLmNzdihpbnB1dCxzdHJpbmdzQXNGYWN0b3JzPUYsaGVhZGVyID1GKQpyYWQ8LXJhZFtjKDUsNiwxMCwxNywxOCwxOSwyMCldCm5hbWVzKHJhZCk8LWMoInkiLCJ4IiwiRWxlIiwiRU1kIiwiTUcxIiwiRU1zIiwiTUcyIikKcmFkPC1zdWJzZXQocmFkLHg+MCkKYTwtZl9wbG90cmFkKHJlc29sdXRpb24gPSByZXNvbHV0aW9uLGRmID0gcmFkLHZhcm5hbWUgPSAiRU1kIikKYjwtZl9wbG90cmFkKHJlc29sdXRpb24gPSByZXNvbHV0aW9uLGRmID0gcmFkLHZhcm5hbWUgPSAiTUcxIikKYzwtZl9wbG90cmFkKHJlc29sdXRpb24gPSByZXNvbHV0aW9uLGRmID0gcmFkLHZhcm5hbWUgPSAiRU1zIikKZDwtZl9wbG90cmFkKHJlc29sdXRpb24gPSByZXNvbHV0aW9uLGRmID0gcmFkLHZhcm5hbWUgPSAiTUcyIikKY2MgPC0gYnJpY2soYSxiLGMsZCkKaWYocGxvdCkgewogIHBkZihwbG90bmFtZSkKICBtYXBUaGVtZSA8LSByYXN0ZXJUaGVtZShyZWdpb249YnJld2VyLnBhbCg4LCJSZWRzIikpCiAgcHJpbnQobGV2ZWxwbG90KGIsIG1hcmdpbj1GLCBwYXIuc2V0dGluZ3M9bWFwVGhlbWUsbWFpbj0iUG90YXNzaXVtIixwcmV0dHk9VFJVRSkpCiAgbWFwVGhlbWUgPC0gcmFzdGVyVGhlbWUocmVnaW9uPWJyZXdlci5wYWwoOCwiR3JlZW5zIikpCiAgcHJpbnQobGV2ZWxwbG90KGQsIG1hcmdpbj1GLCBwYXIuc2V0dGluZ3M9bWFwVGhlbWUsbWFpbj0iVGhvcml1bSIscHJldHR5PVRSVUUpKQogIG1hcFRoZW1lIDwtIHJhc3RlclRoZW1lKHJlZ2lvbj1icmV3ZXIucGFsKDgsIkJsdWVzIikpCiBwcmludCggbGV2ZWxwbG90KGMsIG1hcmdpbj1GLCBwYXIuc2V0dGluZ3M9bWFwVGhlbWUsbWFpbj0iVXJhbml1bSIscHJldHR5PVRSVUUpKQogIGRldi5vZmYoKQp9CndyaXRlUmFzdGVyKGNjLGZpbGVuYW1lID0gIi93d3cvU3Rhbi8yMDE4L0VNX2FuZF9HYW1tYS9yZXN1bHQvRWxzZXdoZXJlU291dGgtRU1kLU1HMS1FTXMtTUcyLnRpZiIsZm9ybWF0PSJHVGlmZiIsb3ZlcndyaXRlPVQpCn0KCgojIFBMb3QgdGhlIGRhdGEKcGRmKCIvd3d3L1N0YW4vcmFkX3Bsb3QucGRmIikKbWFwVGhlbWUgPC0gcmFzdGVyVGhlbWUocmVnaW9uPWJyZXdlci5wYWwoOCwiUmVkcyIpKQpsZXZlbHBsb3QoYSwgbWFyZ2luPUYsIHBhci5zZXR0aW5ncz1tYXBUaGVtZSxtYWluPSJQb3Rhc3NpdW0iLHByZXR0eT1UUlVFKQptYXBUaGVtZSA8LSByYXN0ZXJUaGVtZShyZWdpb249YnJld2VyLnBhbCg4LCJHcmVlbnMiKSkKbGV2ZWxwbG90KGIsIG1hcmdpbj1GLCBwYXIuc2V0dGluZ3M9bWFwVGhlbWUsbWFpbj0iVGhvcml1bSIscHJldHR5PVRSVUUpCm1hcFRoZW1lIDwtIHJhc3RlclRoZW1lKHJlZ2lvbj1icmV3ZXIucGFsKDgsIkJsdWVzIikpCmxldmVscGxvdChjLCBtYXJnaW49RiwgcGFyLnNldHRpbmdzPW1hcFRoZW1lLG1haW49IlVyYW5pdW0iLHByZXR0eT1UUlVFKQoKcGxvdFJHQihjLCAxLCAyLDMsIHN0cmV0Y2g9Imhpc3QiKQoKZGV2Lm9mZigpCgoKYGBg