This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

library(radiator)
library(adegenet)
Loading required package: ade4

   /// adegenet 2.1.2 is loaded ////////////

   > overview: '?adegenet'
   > tutorials/doc/questions: 'adegenetWeb()' 
   > bug reports/feature requests: adegenetIssues()
library(PCAviz)

#PCA of all samples uses VCF

##Convert VCF to genind

data <- read_vcf("../data/HCSS_Afilt32m70_01_pp90.vcf",strata = "../../SSHCfiltNreps.strata",parallel.core = 1,vcf.stats = FALSE, filter.monomorphic=FALSE)
Execution date@time: 20200707@1623
Folder created: read_vcf_20200707@1623
Function call and arguments stored in: radiator_read_vcf_args_20200707@1623.tsv
File written: random.seed (299848)

Reading VCF
Data summary: 
    number of samples: 114
    number of markers: 5269
done! timing: 1 sec


File written: radiator_20200707@1624.gds

Analyzing the data...
VCF source: unknown
Data is bi-allelic
Synchronizing data and strata...
    Number of strata: 2
    Number of individuals: 114
Reads assembly: de novo
Filters parameters file generated: filters_parameters_20200707@1623.tsv
Filters parameters file: initiated and updated
################################################################################
####################### radiator::filter_common_markers ########################
################################################################################
Execution date@time: 20200707@1624
Function call and arguments stored in: radiator_filter_common_markers_args_20200707@1624.tsv
Filters parameters file: initiated
Scanning for common markers...
Generating UpSet plot to visualize markers in common
File written: whitelist.common.markers_20200707@1624.tsv
Filters parameters file: updated
################################### RESULTS ####################################

Filter common markers:
Number of individuals / strata / chrom / locus / SNP:
    Before: 114 / 2 / 1 / 3408 / 5269
    Blacklisted: 0 / 0 / 0 / 0 / 0
    After: 114 / 2 / 1 / 3408 / 5269

Computation time, overall: 1 sec
####################### completed filter_common_markers ########################

Preparing output files...
File written: whitelist.markers.tsv
Writing the filtered strata: strata.filtered.tsvstrata.filtered.tsv
################################### SUMMARY ####################################


Number of chromosome/contig/scaffold: 1
Number of locus: 3408
Number of markers: 5269
Number of populations: 2
Number of individuals: 114

Number of ind/pop:
HC = 57
SS = 57

Number of duplicate id: 0
radiator Genomic Data Structure (GDS) file: radiator_20200707@1624.gds

Computation time, overall: 12 sec
############################## completed read_vcf ##############################
gen <- genomic_converter(data,strata = "../../SSHCfiltNreps.strata",output = "genind", filter.monomorphic=F)
################################################################################
######################### radiator::genomic_converter ##########################
################################################################################
Execution date@time: 20200707@1624
Folder created: 13_radiator_genomic_converter_20200707@1624
Function call and arguments stored in: radiator_genomic_converter_args_20200707@1624.tsv
Filters parameters file generated: filters_parameters_20200707@1624.tsv

Importing data

Synchronizing data and strata...
    Number of strata: 2
    Number of individuals: 114

Writing tidy data set:
radiator_data_20200707@1624.rad

Computation time, overall: 9 sec

Preparing data for output

Data is bi-allelic
Generating adegenet genind object
################################### RESULTS ####################################
Data format of input: SeqVarGDSClass
Biallelic data
Number of markers: 5269
Number of chromosome/contig/scaffold: 1
Number of strata: 2
Number of individuals: 114

Computation time, overall: 14 sec
######################### completed genomic_converter ##########################

##Run PCA

HCSSall <- gen$genind
HCSSall
/// GENIND OBJECT /////////

 // 114 individuals; 5,269 loci; 10,538 alleles; size: 7.8 Mb

 // Basic content
   @tab:  114 x 10538 matrix of allele counts
   @loc.n.all: number of alleles per locus (range: 2-2)
   @loc.fac: locus factor for the 10538 columns of @tab
   @all.names: list of allele names for each locus
   @ploidy: ploidy of each individual  (range: 2-2)
   @type:  codom
   @call: radiator::write_genind(data = input, write = TRUE)

 // Optional content
   @pop: population of each individual (group size range: 57-57)
   @strata: a data frame with 2 columns ( POP_ID, INDIVIDUALS )
save(HCSSall,file="../analyses/2bRAD/HCSS_Afilt32m70_01_pp90.genind")
geno <- tab(HCSSall)
geno <- geno[,seq(1,ncol(geno)-1,2)]
head(geno)[,c(1:10)]
          1__Contig0__109103.A1__C 1__Contig0__109119.A1__T 1__Contig0__109120.A1__G
HC1-11                           1                        1                        2
HC1-12                           2                        2                        2
HC1-13                           0                        0                        2
HC1-14-L5                        2                        2                        2
HC1-15                           1                        1                        2
HC1-18                           1                        2                       NA
          1__Contig0__109123.A1__T 1__Contig100040__508.A1__G 1__Contig100040__510.A1__T
HC1-11                           1                          2                          2
HC1-12                           2                          2                          1
HC1-13                           0                          0                          2
HC1-14-L5                        2                          2                          1
HC1-15                           1                          2                          2
HC1-18                           2                          0                          2
          1__Contig100040__516.A1__A 1__Contig100040__524.A1__T 1__Contig100415__3978.A1__C
HC1-11                             2                          2                           0
HC1-12                             2                          1                           2
HC1-13                             2                          2                           1
HC1-14-L5                          2                          2                           1
HC1-15                             2                          2                           0
HC1-18                             2                          2                           1
          1__Contig100504__842.A1__T
HC1-11                             1
HC1-12                             2
HC1-13                             2
HC1-14-L5                          2
HC1-15                             2
HC1-18                             2
write.table(geno,file="../analyses/2bRAD/HCSS_Afilt32m70_01_pp90.geno",quote = F)
NA.afDraw<- function(ind){
  ind.mat <- ind@tab
  new.mat <- ind.mat
  af = colSums(ind.mat[,seq(1,ncol(ind.mat)-1,2)],na.rm = TRUE)/
      (2*apply(ind.mat[,seq(1,ncol(ind.mat)-1,2)],2,function(x) sum(!is.na(x))))
  af.Draw <- function(geno, af){
     new <- function(geno,af){
        if(is.na(geno)){
        newA = rbinom(1,2,af)
        }
        else {newA <- geno}
        return(newA)
   }
  new.row <- mapply(geno,af,FUN = new)
  return(new.row)}
  
  new.mat[,seq(1,ncol(ind.mat)-1,2)] <- t(apply(ind.mat[,seq(1,ncol(ind.mat)-1,2)],1,af.Draw,af))
  new.mat[,seq(2,ncol(ind.mat),2)] <- 2-new.mat[,seq(1,ncol(ind.mat)-1,2)]
  new.ind <- ind
  new.ind@tab <- new.mat
  return(new.ind)
}
u.na <- NA.afDraw(gen$genind)
pca <- dudi.pca(u.na,cent=TRUE,scale=TRUE,scannf = T)
Select the number of axes: 
10

pca <- dudi.pca(u.na,cent=TRUE,scale=TRUE,scannf = F, nf = 10)
col6 <-  c("red","blue")
par(mfrow=c(2,2))
s.class(pca$li, strata(u.na)$POP_ID,xax=1,yax=2, 
        sub = "HCSS_Afilt32m70_01_pp90, PC1-2, 114 inds, 5269 SNPs ",
        possub = "topleft",col=transp(col6,.6),axesell=FALSE,
        cstar=0, cpoint=3, grid=FALSE, cellipse = 0)
s.class(pca$li, strata(u.na)$POP_ID,xax=1,yax=3, 
        sub = "HCSS_Afilt32m70_01_pp90, PC1-3, 114 inds, 5269 SNPs ",
        possub = "topleft",col=transp(col6,.6),axesell=FALSE,
        cstar=0, cpoint=3, grid=FALSE, cellipse = 0)
s.class(pca$li, strata(u.na)$POP_ID,xax=1,yax=4, 
        sub = "HCSS_Afilt32m70_01_pp90, PC1-4, 114 inds, 5269 SNPs ",
        possub = "topleft",col=transp(col6,.6),axesell=FALSE,
        cstar=0, cpoint=3, grid=FALSE, cellipse = 0)
s.class(pca$li, strata(u.na)$POP_ID,xax=1,yax=5, 
        sub = "HCSS_Afilt32m70_01_pp90, PC1-5, 114 inds, 5269 SNPs ",
        possub = "topleft",col=transp(col6,.6),axesell=FALSE,
        cstar=0, cpoint=3, grid=FALSE, cellipse = 0)

eig.perc <- 100*pca$eig/sum(pca$eig)
head(eig.perc)
[1] 6.651406 5.064544 4.572244 4.176433 3.049277 2.982483

Saving PCA

write.table(pca$li,file = "../analyses/2bRAD/PCA_allHCSS.tab",sep="\t",quote = F)
save(pca,  file = "../analyses/2bRAD/PCA_allHCSS.Robj")

##Get top loading SNPs

library(factoextra)
PCA.var.loadings <- get_pca_var(pca)
#data.frame(PCA.var.loadings$contrib) # % that each variable (locus) contributes to PCA dimensions. We're interested in Dim1 and Dim2. 
# Subset variable loadings for those that contribute >5% to PC axes 
loci <- rownames(subset(data.frame(PCA.var.loadings$contrib), Dim.1>0.05)) #axis 1 
loci = sapply(strsplit(loci,"\\."), '[',1)
loci <- unique(loci)
length(loci)
[1] 110
contig <- sapply(strsplit(loci,"__"), '[',2)
pos <- sapply(strsplit(loci,"__"), '[',3)
positions <- cbind(contig,pos)
head(positions)
     contig         pos    
[1,] "Contig101655" "12681"
[2,] "Contig104078" "683"  
[3,] "Contig107120" "3263" 
[4,] "Contig109783" "670"  
[5,] "Contig120378" "211"  
[6,] "Contig121049" "2908" 
# read in fst per site
fst= read.csv("../analyses/2bRAD/HCSS_sfsm70_PerSiteFst.csv")
head(fst)
   contig    pos     a     b        fst
1 Contig0  74432 0.000 0.009 0.00000000
2 Contig0 109103 0.034 0.457 0.07423581
3 Contig0 109119 0.003 0.052 0.05660377
4 Contig0 109123 0.002 0.067 0.02941176
5 Contig1  40362 0.000 0.009 0.00000000
6 Contig1  42880 0.003 0.078 0.03797468
# get fst for the top 5% of PC1 loadings, and save
pc1fst <- merge(positions,fst, all.x=T)[,c('contig','pos','fst')]
invalid factor level, NA generated
head(pc1fst)
        contig   pos       fst
1 Contig101655 12681 0.1790393
2 Contig104078   683 0.2639138
3 Contig107120  3263 0.5111441
4 Contig109783   670 0.7590206
5 Contig120378   211 0.3101695
6 Contig121049  2908 0.3650255
write.table(pc1fst,"../analyses/2bRAD/Fst_PCA_allHCSS_95.tab",sep="\t",quote = F,row.names = F)

##old way

li <-pca$li
c1 <- pca$c1
colnames(c1) <- colnames(li)
#create pcaviz object
pviz <- pcaviz(x=li,rotation=c1,dat=u.na$strata)
pcaviz_loadingsplot(pviz,min.rank = 0.95)

PC1snps = rownames(pca$c1[which(abs(pca$c1$CS1) > quantile(abs(pca$c1$CS1),0.95)),])
length(PC1snps)
[1] 527
head(PC1snps)
[1] "1__Contig101655__12681.A1__A" "1__Contig101655__12681.A2__T" "1__Contig101935__6468.A1__G" 
[4] "1__Contig101935__6468.A2__A"  "1__Contig103053__1134.A1__C"  "1__Contig103053__1134.A2__T" 
loci = sapply(strsplit(PC1snps,"\\."), '[',1)
loci <- unique(loci)
contig <- sapply(strsplit(loci,"__"), '[',2)
pos <- sapply(strsplit(loci,"__"), '[',3)
positions <- cbind(contig,pos)
head(positions)
     contig         pos    
[1,] "Contig101655" "12681"
[2,] "Contig101935" "6468" 
[3,] "Contig103053" "1134" 
[4,] "Contig103053" "1136" 
[5,] "Contig103346" "16201"
[6,] "Contig104078" "683"  
fst= read.csv("../analyses/2bRAD/HCSS_sfsm70_PerSiteFst.csv")
head(fst)
   contig    pos     a     b        fst
1 Contig0  74432 0.000 0.009 0.00000000
2 Contig0 109103 0.034 0.457 0.07423581
3 Contig0 109119 0.003 0.052 0.05660377
4 Contig0 109123 0.002 0.067 0.02941176
5 Contig1  40362 0.000 0.009 0.00000000
6 Contig1  42880 0.003 0.078 0.03797468
# get fst for the top 5% of PC1 loadings, and save
pc1fst <- merge(positions,fst, all.x=T)[,c('contig','pos','fst')]
invalid factor level, NA generated
head(pc1fst)
        contig   pos       fst
1 Contig101655 12681 0.1790393
2 Contig101935  6468 0.3543046
3 Contig103053  1134 0.2765957
4 Contig103053  1136 0.2765957
5 Contig103346 16201 0.1146667
6 Contig104078   683 0.2639138
write.table(pc1fst,"../analyses/2bRAD/Fst_PCA_allHCSS_95.tab",sep="\t",quote = F,row.names = F)

#PCA of just MBD samples

mbd = c("HC1-2B-L5","HC1-4","HC2-15A-L5","HC2-17B","HC3-1","HC3-5-L5B","HC3-7","HC3-10","HC3-11",
        "SS2-9-L5","SS2-14-L5","SS2-18-L5","SS3-3","SS3-14","SS3-15","SS3-16","SS3-20","SS5-18")
genmdb <- u.na[i=mbd,drop=TRUE]
genmdb <- genmdb[loc=isPoly(genmdb)]
@tab does not contain integers; as of adegenet_2.0-0, numeric values are no longer used
genmdb
/// GENIND OBJECT /////////

 // 18 individuals; 4,373 loci; 8,746 alleles; size: 3.9 Mb

 // Basic content
   @tab:  18 x 8746 matrix of allele counts
   @loc.n.all: number of alleles per locus (range: 2-2)
   @loc.fac: locus factor for the 8746 columns of @tab
   @all.names: list of allele names for each locus
   @ploidy: ploidy of each individual  (range: 2-2)
   @type:  codom
   @call: .local(x = x, i = i, j = j, loc = ..1, drop = drop)

 // Optional content
   @pop: population of each individual (group size range: 9-9)
   @strata: a data frame with 2 columns ( POP_ID, INDIVIDUALS )
mbd = c("HC1-2B-L5","HC1-4","HC2-15A-L5","HC2-17B","HC3-1","HC3-5-L5B","HC3-7","HC3-10","HC3-11",
        "SS2-9-L5","SS2-14-L5","SS2-18-L5","SS3-3","SS3-14","SS3-15","SS3-16","SS3-20","SS5-18")
HCSS <- HCSSall[i=mbd, drop=TRUE]
HCSS <- HCSS[loc=isPoly(HCSS)]
HCSS
/// GENIND OBJECT /////////

 // 18 individuals; 4,342 loci; 8,684 alleles; size: 3.2 Mb

 // Basic content
   @tab:  18 x 8684 matrix of allele counts
   @loc.n.all: number of alleles per locus (range: 2-2)
   @loc.fac: locus factor for the 8684 columns of @tab
   @all.names: list of allele names for each locus
   @ploidy: ploidy of each individual  (range: 2-2)
   @type:  codom
   @call: .local(x = x, i = i, j = j, loc = ..1, drop = drop)

 // Optional content
   @pop: population of each individual (group size range: 9-9)
   @strata: a data frame with 2 columns ( POP_ID, INDIVIDUALS )
genoM <- tab(HCSS)
genoM <- genoM[,seq(1,ncol(genoM)-1,2)]
head(genoM)[,c(1:10)]
           1__Contig0__109103.A1__C 1__Contig0__109119.A1__T 1__Contig0__109123.A1__T
HC1-2B-L5                         1                        2                        2
HC1-4                             1                        2                        2
HC2-15A-L5                        2                        2                        2
HC2-17B                           1                        2                        2
HC3-1                             0                        0                        0
HC3-5-L5B                        NA                        2                        2
           1__Contig100040__508.A1__G 1__Contig100040__516.A1__A 1__Contig100040__524.A1__T
HC1-2B-L5                          NA                         NA                         NA
HC1-4                               1                          1                          2
HC2-15A-L5                          1                          2                          1
HC2-17B                             1                          2                          2
HC3-1                               0                          2                          2
HC3-5-L5B                           2                          2                          0
           1__Contig100415__3978.A1__C 1__Contig100504__842.A1__T 1__Contig100504__863.A1__A
HC1-2B-L5                            2                          2                          2
HC1-4                                1                          2                          2
HC2-15A-L5                           2                          2                          2
HC2-17B                              1                          2                          2
HC3-1                                2                          2                          2
HC3-5-L5B                            2                          2                          2
           1__Contig100572__10193.A1__G
HC1-2B-L5                            NA
HC1-4                                NA
HC2-15A-L5                            1
HC2-17B                               2
HC3-1                                 1
HC3-5-L5B                             1
write.table(genoM,file="../analyses/2bRAD/MBD_HCSS_Afilt32m70_01_pp90.geno",quote = F)
# get geno with maf > 0.05 ( excludes singletons)
x <- HCSS[loc=which(minorAllele(HCSS)> 0.05)]
x
/// GENIND OBJECT /////////

 // 18 individuals; 3,547 loci; 7,094 alleles; size: 2.7 Mb

 // Basic content
   @tab:  18 x 7094 matrix of allele counts
   @loc.n.all: number of alleles per locus (range: 2-2)
   @loc.fac: locus factor for the 7094 columns of @tab
   @all.names: list of allele names for each locus
   @ploidy: ploidy of each individual  (range: 2-2)
   @type:  codom
   @call: .local(x = x, i = i, j = j, loc = ..1, drop = drop)

 // Optional content
   @pop: population of each individual (group size range: 9-9)
   @strata: a data frame with 2 columns ( POP_ID, INDIVIDUALS )
xM <- tab(x)
xM <- xM[,seq(1,ncol(xM)-1,2)]
write.table(xM,file="../analyses/2bRAD/MBD_HCSS_Afilt32m70_01_pp90_maf05.geno",quote = F)
#pca <- dudi.pca(genmdb,cent=TRUE,scale=TRUE,scannf = T)
pcaM <- dudi.pca(genmdb,cent=TRUE,scale=TRUE,scannf = F, nf = 10)
col6 <-  c("red","blue")
par(mfrow=c(2,2))
s.class(pcaM$li, strata(genmdb)$POP_ID,xax=1,yax=2, 
        sub = "HCSS_Afilt32m70_01_pp90 MBD, PC1-2, 18 inds, 4373 SNPs ",
        possub = "topleft",col=transp(col6,.6),axesell=FALSE,
        cstar=0, cpoint=3, grid=FALSE, cellipse = 0)
s.class(pcaM$li, strata(genmdb)$POP_ID,xax=1,yax=3, 
        sub = "HCSS_Afilt32m70_01_pp90 MBD, PC1-3, 18 inds, 4373 SNPs ",
        possub = "topleft",col=transp(col6,.6),axesell=FALSE,
        cstar=0, cpoint=3, grid=FALSE, cellipse = 0)
s.class(pcaM$li, strata(genmdb)$POP_ID,xax=1,yax=4, 
        sub = "HCSS_Afilt32m70_01_pp90 MBD, PC1-4, 18 inds, 4373 SNPs ",
        possub = "topleft",col=transp(col6,.6),axesell=FALSE,
        cstar=0, cpoint=3, grid=FALSE, cellipse = 0)
s.class(pcaM$li, strata(genmdb)$POP_ID,xax=1,yax=5, 
        sub = "HCSS_Afilt32m70_01_pp90 MBD, PC1-5, 18 inds, 4373 SNPs ",
        possub = "topleft",col=transp(col6,.6),axesell=FALSE,
        cstar=0, cpoint=3, grid=FALSE, cellipse = 0)

eig.perc <- 100*pcaM$eig/sum(pcaM$eig)
head(eig.perc)
[1] 12.317614  8.988271  7.696656  7.301543  6.422120  6.262430

Saving PCA

write.table(pcaM$li,file = "../analyses/2bRAD/PCA_MBD.tab",sep="\t",quote = F)
save(pcaM,  file = "../analyses/2bRAD/PCA_MBD.Robj")

##Get top loading SNPs

library(factoextra)
PCA.var.loadings <- get_pca_var(pcaM)
#data.frame(PCA.var.loadings$contrib) # % that each variable (locus) contributes to PCA dimensions. We're interested in Dim1 and Dim2. 
# Subset variable loadings for those that contribute >5% to PC axes 
loci <- rownames(subset(data.frame(PCA.var.loadings$contrib), Dim.1>0.05)) #axis 1 
loci = sapply(strsplit(loci,"\\."), '[',1)
loci <- unique(loci)
length(loci)
[1] 105
contig <- sapply(strsplit(loci,"__"), '[',2)
pos <- sapply(strsplit(loci,"__"), '[',3)
positions <- cbind(contig,pos)
head(positions)
     contig         pos   
[1,] "Contig107120" "3263"
[2,] "Contig109783" "670" 
[3,] "Contig109827" "6152"
[4,] "Contig112828" "139" 
[5,] "Contig117256" "646" 
[6,] "Contig117622" "6364"
# get fst for the top 5% of PC1 loadings, and save
pc1fstM <- merge(positions,fst, all.x=T)[,c('contig','pos','fst')]
invalid factor level, NA generated
head(pc1fstM)
        contig  pos       fst
1 Contig107120 3263 0.5111441
2 Contig109783  670 0.7590206
3 Contig109827 6152 0.1503132
4 Contig112828  139 0.2288288
5 Contig117256  646 0.1486989
6 Contig117622 6364 0.2860963
write.table(pc1fstM,"../analyses/2bRAD/Fst_PCA_MBD_95.tab",sep="\t",quote = F,row.names = F)

###Old, gets top 5% quantile

li <-pcaM$li
c1 <- pcaM$c1
colnames(c1) <- colnames(li)
#create pcaviz object
pvizM <- pcaviz(x=li,rotation=c1,dat=genmdb$strata)
pcaviz_loadingsplot(pvizM,min.rank = 0.95)

PC1snpsM = rownames(pcaM$c1[which(abs(pcaM$c1$CS1) > quantile(abs(pcaM$c1$CS1),0.95)),])
length(PC1snpsM)
[1] 438
head(PC1snpsM)
[1] "1__Contig101335__1205.A1__C" "1__Contig101335__1205.A2__T" "1__Contig101935__6468.A1__G"
[4] "1__Contig101935__6468.A2__A" "1__Contig102417__2171.A1__G" "1__Contig102417__2171.A2__T"
lociM = sapply(strsplit(PC1snpsM,"\\."), '[',1)
lociM <- unique(lociM)
contig <- sapply(strsplit(lociM,"__"), '[',2)
pos <- sapply(strsplit(lociM,"__"), '[',3)
positionsM <- cbind(contig,pos)
head(positionsM)
     contig         pos   
[1,] "Contig101335" "1205"
[2,] "Contig101935" "6468"
[3,] "Contig102417" "2171"
[4,] "Contig103298" "7435"
[5,] "Contig106125" "3829"
[6,] "Contig107120" "3263"
# get fst for the top 5% of PC1 loadings, and save
pc1fstM <- merge(positionsM,fst, all.x=T)[,c('contig','pos','fst')]
invalid factor level, NA generated
head(pc1fstM)
        contig  pos        fst
1 Contig101335 1205         NA
2 Contig101935 6468 0.35430464
3 Contig102417 2171 0.07792208
4 Contig103298 7435 0.06282723
5 Contig106125 3829 0.27296588
6 Contig107120 3263 0.51114413
write.table(pc1fstM,"../analyses/2bRAD/Fst_PCA_MBD_95.tab",sep="\t",quote = F,row.names = F)

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

LS0tCnRpdGxlOiAnUENBIG9mIDJiIFJBRCBkYXRhJwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiAKClRyeSBleGVjdXRpbmcgdGhpcyBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biogYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgcGxhY2luZyB5b3VyIGN1cnNvciBpbnNpZGUgaXQgYW5kIHByZXNzaW5nICpDdHJsK1NoaWZ0K0VudGVyKi4gCgpgYGB7cn0KbGlicmFyeShyYWRpYXRvcikKbGlicmFyeShhZGVnZW5ldCkKbGlicmFyeShQQ0F2aXopCmBgYAojUENBIG9mIGFsbCBzYW1wbGVzIHVzZXMgVkNGICAKCiMjQ29udmVydCBWQ0YgdG8gZ2VuaW5kICAKCmBgYHtyfQpkYXRhIDwtIHJlYWRfdmNmKCIuLi9kYXRhL0hDU1NfQWZpbHQzMm03MF8wMV9wcDkwLnZjZiIsc3RyYXRhID0gIi4uLy4uL1NTSENmaWx0TnJlcHMuc3RyYXRhIixwYXJhbGxlbC5jb3JlID0gMSx2Y2Yuc3RhdHMgPSBGQUxTRSwgZmlsdGVyLm1vbm9tb3JwaGljPUZBTFNFKQpgYGAKYGBge3J9CmdlbiA8LSBnZW5vbWljX2NvbnZlcnRlcihkYXRhLHN0cmF0YSA9ICIuLi8uLi9TU0hDZmlsdE5yZXBzLnN0cmF0YSIsb3V0cHV0ID0gImdlbmluZCIsIGZpbHRlci5tb25vbW9ycGhpYz1GKQpgYGAKIyNSdW4gUENBCmBgYHtyfQpIQ1NTYWxsIDwtIGdlbiRnZW5pbmQKSENTU2FsbApzYXZlKEhDU1NhbGwsZmlsZT0iLi4vYW5hbHlzZXMvMmJSQUQvSENTU19BZmlsdDMybTcwXzAxX3BwOTAuZ2VuaW5kIikKYGBgCmBgYHtyfQpnZW5vIDwtIHRhYihIQ1NTYWxsKQpnZW5vIDwtIGdlbm9bLHNlcSgxLG5jb2woZ2VubyktMSwyKV0KaGVhZChnZW5vKVssYygxOjEwKV0Kd3JpdGUudGFibGUoZ2VubyxmaWxlPSIuLi9hbmFseXNlcy8yYlJBRC9IQ1NTX0FmaWx0MzJtNzBfMDFfcHA5MC5nZW5vIixxdW90ZSA9IEYpCmBgYAoKYGBge3J9Ck5BLmFmRHJhdzwtIGZ1bmN0aW9uKGluZCl7CiAgaW5kLm1hdCA8LSBpbmRAdGFiCiAgbmV3Lm1hdCA8LSBpbmQubWF0CiAgYWYgPSBjb2xTdW1zKGluZC5tYXRbLHNlcSgxLG5jb2woaW5kLm1hdCktMSwyKV0sbmEucm0gPSBUUlVFKS8KICAgICAgKDIqYXBwbHkoaW5kLm1hdFssc2VxKDEsbmNvbChpbmQubWF0KS0xLDIpXSwyLGZ1bmN0aW9uKHgpIHN1bSghaXMubmEoeCkpKSkKICBhZi5EcmF3IDwtIGZ1bmN0aW9uKGdlbm8sIGFmKXsKICAgICBuZXcgPC0gZnVuY3Rpb24oZ2VubyxhZil7CiAgICAgICAgaWYoaXMubmEoZ2VubykpewogICAgICAgIG5ld0EgPSByYmlub20oMSwyLGFmKQogICAgICAgIH0KICAgICAgICBlbHNlIHtuZXdBIDwtIGdlbm99CiAgICAgICAgcmV0dXJuKG5ld0EpCiAgIH0KICBuZXcucm93IDwtIG1hcHBseShnZW5vLGFmLEZVTiA9IG5ldykKICByZXR1cm4obmV3LnJvdyl9CiAgCiAgbmV3Lm1hdFssc2VxKDEsbmNvbChpbmQubWF0KS0xLDIpXSA8LSB0KGFwcGx5KGluZC5tYXRbLHNlcSgxLG5jb2woaW5kLm1hdCktMSwyKV0sMSxhZi5EcmF3LGFmKSkKICBuZXcubWF0WyxzZXEoMixuY29sKGluZC5tYXQpLDIpXSA8LSAyLW5ldy5tYXRbLHNlcSgxLG5jb2woaW5kLm1hdCktMSwyKV0KICBuZXcuaW5kIDwtIGluZAogIG5ldy5pbmRAdGFiIDwtIG5ldy5tYXQKICByZXR1cm4obmV3LmluZCkKfQpgYGAKCmBgYHtyfQp1Lm5hIDwtIE5BLmFmRHJhdyhnZW4kZ2VuaW5kKQpgYGAKYGBge3J9CiNwY2EgPC0gZHVkaS5wY2EodS5uYSxjZW50PVRSVUUsc2NhbGU9VFJVRSxzY2FubmYgPSBUKQpgYGAKYGBge3J9CnBjYSA8LSBkdWRpLnBjYSh1Lm5hLGNlbnQ9VFJVRSxzY2FsZT1UUlVFLHNjYW5uZiA9IEYsIG5mID0gMTApCmBgYAoKCmBgYHtyfQpjb2w2IDwtICBjKCJyZWQiLCJibHVlIikKcGFyKG1mcm93PWMoMiwyKSkKcy5jbGFzcyhwY2EkbGksIHN0cmF0YSh1Lm5hKSRQT1BfSUQseGF4PTEseWF4PTIsIAogICAgICAgIHN1YiA9ICJIQ1NTX0FmaWx0MzJtNzBfMDFfcHA5MCwgUEMxLTIsIDExNCBpbmRzLCA1MjY5IFNOUHMgIiwKICAgICAgICBwb3NzdWIgPSAidG9wbGVmdCIsY29sPXRyYW5zcChjb2w2LC42KSxheGVzZWxsPUZBTFNFLAogICAgICAgIGNzdGFyPTAsIGNwb2ludD0zLCBncmlkPUZBTFNFLCBjZWxsaXBzZSA9IDApCnMuY2xhc3MocGNhJGxpLCBzdHJhdGEodS5uYSkkUE9QX0lELHhheD0xLHlheD0zLCAKICAgICAgICBzdWIgPSAiSENTU19BZmlsdDMybTcwXzAxX3BwOTAsIFBDMS0zLCAxMTQgaW5kcywgNTI2OSBTTlBzICIsCiAgICAgICAgcG9zc3ViID0gInRvcGxlZnQiLGNvbD10cmFuc3AoY29sNiwuNiksYXhlc2VsbD1GQUxTRSwKICAgICAgICBjc3Rhcj0wLCBjcG9pbnQ9MywgZ3JpZD1GQUxTRSwgY2VsbGlwc2UgPSAwKQpzLmNsYXNzKHBjYSRsaSwgc3RyYXRhKHUubmEpJFBPUF9JRCx4YXg9MSx5YXg9NCwgCiAgICAgICAgc3ViID0gIkhDU1NfQWZpbHQzMm03MF8wMV9wcDkwLCBQQzEtNCwgMTE0IGluZHMsIDUyNjkgU05QcyAiLAogICAgICAgIHBvc3N1YiA9ICJ0b3BsZWZ0Iixjb2w9dHJhbnNwKGNvbDYsLjYpLGF4ZXNlbGw9RkFMU0UsCiAgICAgICAgY3N0YXI9MCwgY3BvaW50PTMsIGdyaWQ9RkFMU0UsIGNlbGxpcHNlID0gMCkKcy5jbGFzcyhwY2EkbGksIHN0cmF0YSh1Lm5hKSRQT1BfSUQseGF4PTEseWF4PTUsIAogICAgICAgIHN1YiA9ICJIQ1NTX0FmaWx0MzJtNzBfMDFfcHA5MCwgUEMxLTUsIDExNCBpbmRzLCA1MjY5IFNOUHMgIiwKICAgICAgICBwb3NzdWIgPSAidG9wbGVmdCIsY29sPXRyYW5zcChjb2w2LC42KSxheGVzZWxsPUZBTFNFLAogICAgICAgIGNzdGFyPTAsIGNwb2ludD0zLCBncmlkPUZBTFNFLCBjZWxsaXBzZSA9IDApCmBgYAoKYGBge3J9CmVpZy5wZXJjIDwtIDEwMCpwY2EkZWlnL3N1bShwY2EkZWlnKQpoZWFkKGVpZy5wZXJjKQpgYGAKU2F2aW5nIFBDQQpgYGB7cn0Kd3JpdGUudGFibGUocGNhJGxpLGZpbGUgPSAiLi4vYW5hbHlzZXMvMmJSQUQvUENBX2FsbEhDU1MudGFiIixzZXA9Ilx0IixxdW90ZSA9IEYpCnNhdmUocGNhLCAgZmlsZSA9ICIuLi9hbmFseXNlcy8yYlJBRC9QQ0FfYWxsSENTUy5Sb2JqIikKYGBgCiMjR2V0IHRvcCBsb2FkaW5nIFNOUHMgIApgYGB7cn0KbGlicmFyeShmYWN0b2V4dHJhKQpQQ0EudmFyLmxvYWRpbmdzIDwtIGdldF9wY2FfdmFyKHBjYSkKCiNkYXRhLmZyYW1lKFBDQS52YXIubG9hZGluZ3MkY29udHJpYikgIyAlIHRoYXQgZWFjaCB2YXJpYWJsZSAobG9jdXMpIGNvbnRyaWJ1dGVzIHRvIFBDQSBkaW1lbnNpb25zLiBXZSdyZSBpbnRlcmVzdGVkIGluIERpbTEgYW5kIERpbTIuIAojIFN1YnNldCB2YXJpYWJsZSBsb2FkaW5ncyBmb3IgdGhvc2UgdGhhdCBjb250cmlidXRlID41JSB0byBQQyBheGVzIApsb2NpIDwtIHJvd25hbWVzKHN1YnNldChkYXRhLmZyYW1lKFBDQS52YXIubG9hZGluZ3MkY29udHJpYiksIERpbS4xPjAuMDUpKSAjYXhpcyAxIApsb2NpID0gc2FwcGx5KHN0cnNwbGl0KGxvY2ksIlxcLiIpLCAnWycsMSkKbG9jaSA8LSB1bmlxdWUobG9jaSkKbGVuZ3RoKGxvY2kpCmNvbnRpZyA8LSBzYXBwbHkoc3Ryc3BsaXQobG9jaSwiX18iKSwgJ1snLDIpCnBvcyA8LSBzYXBwbHkoc3Ryc3BsaXQobG9jaSwiX18iKSwgJ1snLDMpCgpwb3NpdGlvbnMgPC0gY2JpbmQoY29udGlnLHBvcykKaGVhZChwb3NpdGlvbnMpCgpgYGAKYGBge3J9CiMgcmVhZCBpbiBmc3QgcGVyIHNpdGUKZnN0PSByZWFkLmNzdigiLi4vYW5hbHlzZXMvMmJSQUQvSENTU19zZnNtNzBfUGVyU2l0ZUZzdC5jc3YiKQpoZWFkKGZzdCkKYGBgCmBgYHtyfQojIGdldCBmc3QgZm9yIHRoZSB0b3AgNSUgb2YgUEMxIGxvYWRpbmdzLCBhbmQgc2F2ZQpwYzFmc3QgPC0gbWVyZ2UocG9zaXRpb25zLGZzdCwgYWxsLng9VClbLGMoJ2NvbnRpZycsJ3BvcycsJ2ZzdCcpXQpoZWFkKHBjMWZzdCkKYGBgCmBgYHtyfQp3cml0ZS50YWJsZShwYzFmc3QsIi4uL2FuYWx5c2VzLzJiUkFEL0ZzdF9QQ0FfYWxsSENTU185NS50YWIiLHNlcD0iXHQiLHF1b3RlID0gRixyb3cubmFtZXMgPSBGKQpgYGAKCiMjb2xkIHdheQpgYGB7cn0KbGkgPC1wY2EkbGkKYzEgPC0gcGNhJGMxCmNvbG5hbWVzKGMxKSA8LSBjb2xuYW1lcyhsaSkKI2NyZWF0ZSBwY2F2aXogb2JqZWN0CnB2aXogPC0gcGNhdml6KHg9bGkscm90YXRpb249YzEsZGF0PXUubmEkc3RyYXRhKQpgYGAKYGBge3J9CnBjYXZpel9sb2FkaW5nc3Bsb3QocHZpeixtaW4ucmFuayA9IDAuOTUpCmBgYApgYGB7cn0KUEMxc25wcyA9IHJvd25hbWVzKHBjYSRjMVt3aGljaChhYnMocGNhJGMxJENTMSkgPiBxdWFudGlsZShhYnMocGNhJGMxJENTMSksMC45NSkpLF0pCmxlbmd0aChQQzFzbnBzKQpoZWFkKFBDMXNucHMpCmBgYApgYGB7cn0KbG9jaSA9IHNhcHBseShzdHJzcGxpdChQQzFzbnBzLCJcXC4iKSwgJ1snLDEpCmxvY2kgPC0gdW5pcXVlKGxvY2kpCmNvbnRpZyA8LSBzYXBwbHkoc3Ryc3BsaXQobG9jaSwiX18iKSwgJ1snLDIpCnBvcyA8LSBzYXBwbHkoc3Ryc3BsaXQobG9jaSwiX18iKSwgJ1snLDMpCgpwb3NpdGlvbnMgPC0gY2JpbmQoY29udGlnLHBvcykKaGVhZChwb3NpdGlvbnMpCmBgYApgYGB7cn0KIyByZWFkIGluIGZzdCBwZXIgc2l0ZQpmc3Q9IHJlYWQuY3N2KCIuLi9hbmFseXNlcy8yYlJBRC9IQ1NTX3Nmc203MF9QZXJTaXRlRnN0LmNzdiIpCmhlYWQoZnN0KQpgYGAKYGBge3J9CiMgZ2V0IGZzdCBmb3IgdGhlIHRvcCA1JSBvZiBQQzEgbG9hZGluZ3MsIGFuZCBzYXZlCnBjMWZzdCA8LSBtZXJnZShwb3NpdGlvbnMsZnN0LCBhbGwueD1UKVssYygnY29udGlnJywncG9zJywnZnN0JyldCmhlYWQocGMxZnN0KQpgYGAKYGBge3J9CndyaXRlLnRhYmxlKHBjMWZzdCwiLi4vYW5hbHlzZXMvMmJSQUQvRnN0X1BDQV9hbGxIQ1NTXzk1LnRhYiIsc2VwPSJcdCIscXVvdGUgPSBGLHJvdy5uYW1lcyA9IEYpCmBgYAoKI1BDQSBvZiBqdXN0IE1CRCBzYW1wbGVzCmBgYHtyfQptYmQgPSBjKCJIQzEtMkItTDUiLCJIQzEtNCIsIkhDMi0xNUEtTDUiLCJIQzItMTdCIiwiSEMzLTEiLCJIQzMtNS1MNUIiLCJIQzMtNyIsIkhDMy0xMCIsIkhDMy0xMSIsCiAgICAgICAgIlNTMi05LUw1IiwiU1MyLTE0LUw1IiwiU1MyLTE4LUw1IiwiU1MzLTMiLCJTUzMtMTQiLCJTUzMtMTUiLCJTUzMtMTYiLCJTUzMtMjAiLCJTUzUtMTgiKQpnZW5tZGIgPC0gdS5uYVtpPW1iZCxkcm9wPVRSVUVdCmdlbm1kYiA8LSBnZW5tZGJbbG9jPWlzUG9seShnZW5tZGIpXQpnZW5tZGIKYGBgCmBgYHtyfQptYmQgPSBjKCJIQzEtMkItTDUiLCJIQzEtNCIsIkhDMi0xNUEtTDUiLCJIQzItMTdCIiwiSEMzLTEiLCJIQzMtNS1MNUIiLCJIQzMtNyIsIkhDMy0xMCIsIkhDMy0xMSIsCiAgICAgICAgIlNTMi05LUw1IiwiU1MyLTE0LUw1IiwiU1MyLTE4LUw1IiwiU1MzLTMiLCJTUzMtMTQiLCJTUzMtMTUiLCJTUzMtMTYiLCJTUzMtMjAiLCJTUzUtMTgiKQpIQ1NTIDwtIEhDU1NhbGxbaT1tYmQsIGRyb3A9VFJVRV0KSENTUyA8LSBIQ1NTW2xvYz1pc1BvbHkoSENTUyldCkhDU1MKZ2Vub00gPC0gdGFiKEhDU1MpCmdlbm9NIDwtIGdlbm9NWyxzZXEoMSxuY29sKGdlbm9NKS0xLDIpXQpoZWFkKGdlbm9NKVssYygxOjEwKV0Kd3JpdGUudGFibGUoZ2Vub00sZmlsZT0iLi4vYW5hbHlzZXMvMmJSQUQvTUJEX0hDU1NfQWZpbHQzMm03MF8wMV9wcDkwLmdlbm8iLHF1b3RlID0gRikKYGBgCmBgYHtyfQojIGdldCBnZW5vIHdpdGggbWFmID4gMC4wNSAoIGV4Y2x1ZGVzIHNpbmdsZXRvbnMpCnggPC0gSENTU1tsb2M9d2hpY2gobWlub3JBbGxlbGUoSENTUyk+IDAuMDUpXQp4CnhNIDwtIHRhYih4KQp4TSA8LSB4TVssc2VxKDEsbmNvbCh4TSktMSwyKV0Kd3JpdGUudGFibGUoeE0sZmlsZT0iLi4vYW5hbHlzZXMvMmJSQUQvTUJEX0hDU1NfQWZpbHQzMm03MF8wMV9wcDkwX21hZjA1Lmdlbm8iLHF1b3RlID0gRikKYGBgCgpgYGB7cn0KI3BjYSA8LSBkdWRpLnBjYShnZW5tZGIsY2VudD1UUlVFLHNjYWxlPVRSVUUsc2Nhbm5mID0gVCkKYGBgCmBgYHtyfQpwY2FNIDwtIGR1ZGkucGNhKGdlbm1kYixjZW50PVRSVUUsc2NhbGU9VFJVRSxzY2FubmYgPSBGLCBuZiA9IDEwKQpgYGAKCgpgYGB7cn0KY29sNiA8LSAgYygicmVkIiwiYmx1ZSIpCnBhcihtZnJvdz1jKDIsMikpCnMuY2xhc3MocGNhTSRsaSwgc3RyYXRhKGdlbm1kYikkUE9QX0lELHhheD0xLHlheD0yLCAKICAgICAgICBzdWIgPSAiSENTU19BZmlsdDMybTcwXzAxX3BwOTAgTUJELCBQQzEtMiwgMTggaW5kcywgNDM3MyBTTlBzICIsCiAgICAgICAgcG9zc3ViID0gInRvcGxlZnQiLGNvbD10cmFuc3AoY29sNiwuNiksYXhlc2VsbD1GQUxTRSwKICAgICAgICBjc3Rhcj0wLCBjcG9pbnQ9MywgZ3JpZD1GQUxTRSwgY2VsbGlwc2UgPSAwKQpzLmNsYXNzKHBjYU0kbGksIHN0cmF0YShnZW5tZGIpJFBPUF9JRCx4YXg9MSx5YXg9MywgCiAgICAgICAgc3ViID0gIkhDU1NfQWZpbHQzMm03MF8wMV9wcDkwIE1CRCwgUEMxLTMsIDE4IGluZHMsIDQzNzMgU05QcyAiLAogICAgICAgIHBvc3N1YiA9ICJ0b3BsZWZ0Iixjb2w9dHJhbnNwKGNvbDYsLjYpLGF4ZXNlbGw9RkFMU0UsCiAgICAgICAgY3N0YXI9MCwgY3BvaW50PTMsIGdyaWQ9RkFMU0UsIGNlbGxpcHNlID0gMCkKcy5jbGFzcyhwY2FNJGxpLCBzdHJhdGEoZ2VubWRiKSRQT1BfSUQseGF4PTEseWF4PTQsIAogICAgICAgIHN1YiA9ICJIQ1NTX0FmaWx0MzJtNzBfMDFfcHA5MCBNQkQsIFBDMS00LCAxOCBpbmRzLCA0MzczIFNOUHMgIiwKICAgICAgICBwb3NzdWIgPSAidG9wbGVmdCIsY29sPXRyYW5zcChjb2w2LC42KSxheGVzZWxsPUZBTFNFLAogICAgICAgIGNzdGFyPTAsIGNwb2ludD0zLCBncmlkPUZBTFNFLCBjZWxsaXBzZSA9IDApCnMuY2xhc3MocGNhTSRsaSwgc3RyYXRhKGdlbm1kYikkUE9QX0lELHhheD0xLHlheD01LCAKICAgICAgICBzdWIgPSAiSENTU19BZmlsdDMybTcwXzAxX3BwOTAgTUJELCBQQzEtNSwgMTggaW5kcywgNDM3MyBTTlBzICIsCiAgICAgICAgcG9zc3ViID0gInRvcGxlZnQiLGNvbD10cmFuc3AoY29sNiwuNiksYXhlc2VsbD1GQUxTRSwKICAgICAgICBjc3Rhcj0wLCBjcG9pbnQ9MywgZ3JpZD1GQUxTRSwgY2VsbGlwc2UgPSAwKQpgYGAKCmBgYHtyfQplaWcucGVyYyA8LSAxMDAqcGNhTSRlaWcvc3VtKHBjYU0kZWlnKQpoZWFkKGVpZy5wZXJjKQpgYGAKU2F2aW5nIFBDQQpgYGB7cn0Kd3JpdGUudGFibGUocGNhTSRsaSxmaWxlID0gIi4uL2FuYWx5c2VzLzJiUkFEL1BDQV9NQkQudGFiIixzZXA9Ilx0IixxdW90ZSA9IEYpCnNhdmUocGNhTSwgIGZpbGUgPSAiLi4vYW5hbHlzZXMvMmJSQUQvUENBX01CRC5Sb2JqIikKYGBgCiMjR2V0IHRvcCBsb2FkaW5nIFNOUHMgIApgYGB7cn0KbGlicmFyeShmYWN0b2V4dHJhKQpQQ0EudmFyLmxvYWRpbmdzIDwtIGdldF9wY2FfdmFyKHBjYU0pCgojZGF0YS5mcmFtZShQQ0EudmFyLmxvYWRpbmdzJGNvbnRyaWIpICMgJSB0aGF0IGVhY2ggdmFyaWFibGUgKGxvY3VzKSBjb250cmlidXRlcyB0byBQQ0EgZGltZW5zaW9ucy4gV2UncmUgaW50ZXJlc3RlZCBpbiBEaW0xIGFuZCBEaW0yLiAKIyBTdWJzZXQgdmFyaWFibGUgbG9hZGluZ3MgZm9yIHRob3NlIHRoYXQgY29udHJpYnV0ZSA+NSUgdG8gUEMgYXhlcyAKbG9jaSA8LSByb3duYW1lcyhzdWJzZXQoZGF0YS5mcmFtZShQQ0EudmFyLmxvYWRpbmdzJGNvbnRyaWIpLCBEaW0uMT4wLjA1KSkgI2F4aXMgMSAKbG9jaSA9IHNhcHBseShzdHJzcGxpdChsb2NpLCJcXC4iKSwgJ1snLDEpCmxvY2kgPC0gdW5pcXVlKGxvY2kpCmxlbmd0aChsb2NpKQpjb250aWcgPC0gc2FwcGx5KHN0cnNwbGl0KGxvY2ksIl9fIiksICdbJywyKQpwb3MgPC0gc2FwcGx5KHN0cnNwbGl0KGxvY2ksIl9fIiksICdbJywzKQoKcG9zaXRpb25zIDwtIGNiaW5kKGNvbnRpZyxwb3MpCmhlYWQocG9zaXRpb25zKQoKYGBgCgpgYGB7cn0KIyBnZXQgZnN0IGZvciB0aGUgdG9wIDUlIG9mIFBDMSBsb2FkaW5ncywgYW5kIHNhdmUKcGMxZnN0TSA8LSBtZXJnZShwb3NpdGlvbnMsZnN0LCBhbGwueD1UKVssYygnY29udGlnJywncG9zJywnZnN0JyldCmhlYWQocGMxZnN0TSkKYGBgCmBgYHtyfQp3cml0ZS50YWJsZShwYzFmc3RNLCIuLi9hbmFseXNlcy8yYlJBRC9Gc3RfUENBX01CRF85NS50YWIiLHNlcD0iXHQiLHF1b3RlID0gRixyb3cubmFtZXMgPSBGKQpgYGAKCgojIyNPbGQsIGdldHMgdG9wIDUlIHF1YW50aWxlCmBgYHtyfQpsaSA8LXBjYU0kbGkKYzEgPC0gcGNhTSRjMQpjb2xuYW1lcyhjMSkgPC0gY29sbmFtZXMobGkpCiNjcmVhdGUgcGNhdml6IG9iamVjdApwdml6TSA8LSBwY2F2aXooeD1saSxyb3RhdGlvbj1jMSxkYXQ9Z2VubWRiJHN0cmF0YSkKYGBgCmBgYHtyfQpwY2F2aXpfbG9hZGluZ3NwbG90KHB2aXpNLG1pbi5yYW5rID0gMC45NSkKYGBgCmBgYHtyfQpQQzFzbnBzTSA9IHJvd25hbWVzKHBjYU0kYzFbd2hpY2goYWJzKHBjYU0kYzEkQ1MxKSA+IHF1YW50aWxlKGFicyhwY2FNJGMxJENTMSksMC45NSkpLF0pCmxlbmd0aChQQzFzbnBzTSkKaGVhZChQQzFzbnBzTSkKYGBgCmBgYHtyfQpsb2NpTSA9IHNhcHBseShzdHJzcGxpdChQQzFzbnBzTSwiXFwuIiksICdbJywxKQpsb2NpTSA8LSB1bmlxdWUobG9jaU0pCmNvbnRpZyA8LSBzYXBwbHkoc3Ryc3BsaXQobG9jaU0sIl9fIiksICdbJywyKQpwb3MgPC0gc2FwcGx5KHN0cnNwbGl0KGxvY2lNLCJfXyIpLCAnWycsMykKCnBvc2l0aW9uc00gPC0gY2JpbmQoY29udGlnLHBvcykKaGVhZChwb3NpdGlvbnNNKQpgYGAKCmBgYHtyfQojIGdldCBmc3QgZm9yIHRoZSB0b3AgNSUgb2YgUEMxIGxvYWRpbmdzLCBhbmQgc2F2ZQpwYzFmc3RNIDwtIG1lcmdlKHBvc2l0aW9uc00sZnN0LCBhbGwueD1UKVssYygnY29udGlnJywncG9zJywnZnN0JyldCmhlYWQocGMxZnN0TSkKYGBgCmBgYHtyfQp3cml0ZS50YWJsZShwYzFmc3RNLCIuLi9hbmFseXNlcy8yYlJBRC9Gc3RfUENBX01CRF85NS50YWIiLHNlcD0iXHQiLHF1b3RlID0gRixyb3cubmFtZXMgPSBGKQpgYGAKCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDdHJsK0FsdCtJKi4KCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLgo=