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.

———————- 1. Transform .vcf to genlight

Import clean .vcf:

library(vcfR)
package <U+393C><U+3E31>vcfR<U+393C><U+3E32> was built under R version 3.5.3
   *****       ***   vcfR   ***       *****
   This is vcfR 1.8.0 
     browseVignettes('vcfR') # Documentation
     citation('vcfR') # Citation
   *****       *****      *****       *****
vcf_clean <- read.vcfR(file = "C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/0_2020.02.11_SNPcalling_rawDArTs/3.sex-linked/p1r9_ld_50kb_1kb_removed_missing_0.61_no_sexlinked_HW.recode.vcf")
Scanning file to determine attributes.
File attributes:
  meta lines: 395
  header_line: 396
  variant count: 33168
  column count: 542

Meta line 395 read in.
All meta lines processed.
gt matrix initialized.
Character matrix gt created.
  Character matrix gt rows: 33168
  Character matrix gt cols: 542
  skip: 0
  nrows: 33168
  row_num: 0

Processed variant 1000
Processed variant 2000
Processed variant 3000
Processed variant 4000
Processed variant 5000
Processed variant 6000
Processed variant 7000
Processed variant 8000
Processed variant 9000
Processed variant 10000
Processed variant 11000
Processed variant 12000
Processed variant 13000
Processed variant 14000
Processed variant 15000
Processed variant 16000
Processed variant 17000
Processed variant 18000
Processed variant 19000
Processed variant 20000
Processed variant 21000
Processed variant 22000
Processed variant 23000
Processed variant 24000
Processed variant 25000
Processed variant 26000
Processed variant 27000
Processed variant 28000
Processed variant 29000
Processed variant 30000
Processed variant 31000
Processed variant 32000
Processed variant 33000
Processed variant: 33168
All variants processed

Transform .vcf to genlight:

gl <- vcfR2genlight(vcf_clean)
Loading required namespace: adegenet

Let’s inspect the gl object:

gl
 /// GENLIGHT OBJECT /////////

 // 533 genotypes,  33,168 binary SNPs, size: 9.2 Mb
 436558 (2.47 %) missing data

 // Basic content
   @gen: list of 533 SNPbin

 // Optional content
   @ind.names:  533 individual labels
   @loc.names:  33168 locus labels
   @chromosome: factor storing chromosomes of the SNPs
   @position: integer storing positions of the SNPs
   @other: a list containing: elements without names 

Change names (genotyping ID) for BandID

# Check that order is correct
sum(gl@ind.names == new$gl.ind.names)
[1] 533

———————– 2. Subset census per season

This census was modified manually to have each individual per season only once, and if they were present in more than one neighbourhood, I fused the neighbourhood label

census <- read.csv("C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/11_2020.04.21_PCA/Census_all_seasons_neighbourhood.csv",
                  colClasses = c("factor",
                                 "factor",
                                 "NULL",
                                 "character",
                                 "factor",
                                 rep("NULL", 3)))
                   
censi <- list()
for (i in 1:length(levels(census$Season)))
  censi[[i]] <- droplevels(census[census$Season == levels(census$Season)[i], ])

———————- 3. Make recode table per season

seasons <- c("2011.2012",
             "2012.2013",
             "2013.2014",
             "2014.2015",
             "2015.2016",
             "2016.2017",
             "2017.2018")
for (i in 1:length(recodes))
  write.csv(recodes[[i]], file = paste("C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/11_2020.04.21_PCA/recode_",
                                       seasons[i],
                                       ".csv",
                                       sep = ""), 
            row.names = FALSE,
            col.names = FALSE)
attempt to set 'col.names' ignoredattempt to set 'col.names' ignoredattempt to set 'col.names' ignoredattempt to set 'col.names' ignoredattempt to set 'col.names' ignoredattempt to set 'col.names' ignoredattempt to set 'col.names' ignored

———————- 4. Subset gl per season

gl_season <- list()
for (i in 1:length(recodes))
  gl_season[[i]] <- gl.recode.ind(gl, 
                                  ind.recode = paste("C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/11_2020.04.21_PCA/recode_",
                                       seasons[i],
                                       ".csv",
                                       sep = ""))
Processing genlight object
  Relabelling individuals (=specimens) as per  C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/11_2020.04.21_PCA/recode_2011.2012.csv 
Deleting individuals or samples flagged for deletion
Starting gl.filter.monomorphs: Deleting monomorphic loci
Completed gl.filter.monomorphs

Starting utils.recalc.avgpic: Recalculating OneRatioRef, OneRatioSnp, PICRef, PICSnp and AvgPIC
Completed utils.recalc.avgpic

Starting utils.recalc.callrate: Recalculating CallRate
Completed utils.recalc.callrate

Starting utils.recalc.freqhets: Recalculating frequency of heterozygotes
Completed utils.recalc.freqhets

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, reference allele
Completed utils.recalc.freqhomref

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, alternate allele
Completed utils.recalc.freqhomsnp

Processing genlight object
  Relabelling individuals (=specimens) as per  C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/11_2020.04.21_PCA/recode_2012.2013.csv 
Deleting individuals or samples flagged for deletion
Starting gl.filter.monomorphs: Deleting monomorphic loci
Completed gl.filter.monomorphs

Starting utils.recalc.avgpic: Recalculating OneRatioRef, OneRatioSnp, PICRef, PICSnp and AvgPIC
Completed utils.recalc.avgpic

Starting utils.recalc.callrate: Recalculating CallRate
Completed utils.recalc.callrate

Starting utils.recalc.freqhets: Recalculating frequency of heterozygotes
Completed utils.recalc.freqhets

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, reference allele
Completed utils.recalc.freqhomref

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, alternate allele
Completed utils.recalc.freqhomsnp

Processing genlight object
  Relabelling individuals (=specimens) as per  C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/11_2020.04.21_PCA/recode_2013.2014.csv 
Deleting individuals or samples flagged for deletion
Starting gl.filter.monomorphs: Deleting monomorphic loci
Completed gl.filter.monomorphs

Starting utils.recalc.avgpic: Recalculating OneRatioRef, OneRatioSnp, PICRef, PICSnp and AvgPIC
Completed utils.recalc.avgpic

Starting utils.recalc.callrate: Recalculating CallRate
Completed utils.recalc.callrate

Starting utils.recalc.freqhets: Recalculating frequency of heterozygotes
Completed utils.recalc.freqhets

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, reference allele
Completed utils.recalc.freqhomref

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, alternate allele
Completed utils.recalc.freqhomsnp

Processing genlight object
  Relabelling individuals (=specimens) as per  C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/11_2020.04.21_PCA/recode_2014.2015.csv 
Deleting individuals or samples flagged for deletion
Starting gl.filter.monomorphs: Deleting monomorphic loci
Completed gl.filter.monomorphs

Starting utils.recalc.avgpic: Recalculating OneRatioRef, OneRatioSnp, PICRef, PICSnp and AvgPIC
Completed utils.recalc.avgpic

Starting utils.recalc.callrate: Recalculating CallRate
Completed utils.recalc.callrate

Starting utils.recalc.freqhets: Recalculating frequency of heterozygotes
Completed utils.recalc.freqhets

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, reference allele
Completed utils.recalc.freqhomref

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, alternate allele
Completed utils.recalc.freqhomsnp

Processing genlight object
  Relabelling individuals (=specimens) as per  C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/11_2020.04.21_PCA/recode_2015.2016.csv 
Deleting individuals or samples flagged for deletion
Starting gl.filter.monomorphs: Deleting monomorphic loci
Completed gl.filter.monomorphs

Starting utils.recalc.avgpic: Recalculating OneRatioRef, OneRatioSnp, PICRef, PICSnp and AvgPIC
Completed utils.recalc.avgpic

Starting utils.recalc.callrate: Recalculating CallRate
Completed utils.recalc.callrate

Starting utils.recalc.freqhets: Recalculating frequency of heterozygotes
Completed utils.recalc.freqhets

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, reference allele
Completed utils.recalc.freqhomref

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, alternate allele
Completed utils.recalc.freqhomsnp

Processing genlight object
  Relabelling individuals (=specimens) as per  C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/11_2020.04.21_PCA/recode_2016.2017.csv 
Deleting individuals or samples flagged for deletion
Starting gl.filter.monomorphs: Deleting monomorphic loci
Completed gl.filter.monomorphs

Starting utils.recalc.avgpic: Recalculating OneRatioRef, OneRatioSnp, PICRef, PICSnp and AvgPIC
Completed utils.recalc.avgpic

Starting utils.recalc.callrate: Recalculating CallRate
Completed utils.recalc.callrate

Starting utils.recalc.freqhets: Recalculating frequency of heterozygotes
Completed utils.recalc.freqhets

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, reference allele
Completed utils.recalc.freqhomref

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, alternate allele
Completed utils.recalc.freqhomsnp

Processing genlight object
  Relabelling individuals (=specimens) as per  C:/Users/drob0006/Google Drive/Projects/1.MateChoice_BreedingManagement/Analyses2020/11_2020.04.21_PCA/recode_2017.2018.csv 
Deleting individuals or samples flagged for deletion
Starting gl.filter.monomorphs: Deleting monomorphic loci
Completed gl.filter.monomorphs

Starting utils.recalc.avgpic: Recalculating OneRatioRef, OneRatioSnp, PICRef, PICSnp and AvgPIC
Completed utils.recalc.avgpic

Starting utils.recalc.callrate: Recalculating CallRate
Completed utils.recalc.callrate

Starting utils.recalc.freqhets: Recalculating frequency of heterozygotes
Completed utils.recalc.freqhets

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, reference allele
Completed utils.recalc.freqhomref

Starting utils.recalc.freqhomref: Recalculating frequency of homozygotes, alternate allele
Completed utils.recalc.freqhomsnp

————- 5. Add individual metadata file with id, pop, sex

ind.metadata_season <- list()
for (i in 1:length(recodes)) {
  ind.metadata_season[[i]] <- merge(recodes[[i]],
                                    censi[[i]][, -1],
                                    by.x = "V1",
                                    by.y = "Band",
                                    sort = FALSE)
  ind.metadata_season[[i]] <- ind.metadata_season[[i]][, -2]
  names(ind.metadata_season[[i]]) <- c("id", "pop", "sex")
  # Check if they have same number of individuals
  print(nrow(ind.metadata_season[[i]]))
  print(length(gl_season[[i]]@ind.names))
  # Check if the order matches
  print(sum(ind.metadata_season[[i]]$id == gl_season[[i]]@ind.names))
}
[1] 36
[1] 36
[1] 36
[1] 27
[1] 27
[1] 27
[1] 49
[1] 49
[1] 49
[1] 64
[1] 64
[1] 64
[1] 79
[1] 79
[1] 79
[1] 94
[1] 94
[1] 94
[1] 118
[1] 118
[1] 118

Now we assign the ind.metadata as the @other$ind.metrics section of the genlight objects:

for (i in 1:length(gl_season)) {
  # Assign as individual metafile
  gl_season[[i]]@other$ind.metrics <- ind.metadata_season[[i]]
  # And as pop
  gl_season[[i]]@pop <- ind.metadata_season[[i]]$pop
  # Check if everything is correct
  print(sum(gl_season[[i]]@ind.names == gl_season[[i]]@other$ind.metrics$id))
}
[1] 36
[1] 27
[1] 49
[1] 64
[1] 79
[1] 94
[1] 118
pop(gl_season[[1]])
 [1] Blue       Blue       Blue       Blue       Blue       Blue       Blue       Green      Blue      
[10] Blue       Green      Green      Green      Blue/Green Blue       Blue/Green Red        Green     
[19] Green      Blue/Green Green      Blue       Blue       Blue       Blue/Green Green      Green     
[28] Blue       Green      Blue       Blue       Blue       Blue       Blue       Blue       Green     
Levels: Blue Blue/Green Green Red
gl_season[[1]]
 /// GENLIGHT OBJECT /////////

 // 36 genotypes,  23,570 binary SNPs, size: 5.4 Mb
 15287 (1.8 %) missing data

 // Basic content
   @gen: list of 36 SNPbin

 // Optional content
   @ind.names:  36 individual labels
   @loc.names:  23570 locus labels
   @chromosome: factor storing chromosomes of the SNPs
   @position: integer storing positions of the SNPs
   @pop: population of each individual (group size range: 1-20)
   @other: a list containing: loc.metrics  ind.metrics 

———————————– 6. PCA

Modifying dartR function for generating PCA biplot

#install.packages("directlabels")
#library(directlabels)
biplot.pop <- function(glPca, data, scale = FALSE, ellipse = FALSE, p = 0.95, 
                       labels = "pop", hadjust = 1.5, vadjust = 1, xaxis = 1, 
                       yaxis = 2) {
  # Sanity checks
  if (class(glPca) != "glPca" | class(data) != "genlight") {
    cat("Fatal Error: glPca and genlight objects required for glPca and data parameters respectively!\n")
    stop()
  }
  if (labels != "pop") {
    cat("Fatal Error: This function is only for plotting populations!\n")
    stop()
  }
  library(ggplot2)
  #library(directlabels)
  # Parameters
  m <- cbind(glPca$scores[, xaxis], glPca$scores[, yaxis])
  df <- data.frame(m)
  s <- sum(glPca$eig)
  e <- round(glPca$eig * 100/s, 1)
  xlab <- paste("PCoA  axis  ", xaxis, "  (", e[xaxis], "%)", sep = "")
  ylab <- paste("PCoA  axis  ", yaxis, "  (", e[yaxis], "%)", sep = "")
  
  # Plotting
  if (labels == "pop") {
    cat("Plotting populations\n")
    ind <- indNames(data)
    Neighbourhood <- factor(pop(data))
    df <- cbind(df, ind, factor(pop(data)))
    colnames(df) <- c("PCoAx", "PCoAy", "ind", "pop")
    
    p <- ggplot(df, 
                aes(x = df$PCoAx, y = df$PCoAy, group = Neighbourhood, colour = Neighbourhood)) + 
      geom_point(size = 3, aes(colour = Neighbourhood)) +
      scale_color_manual(values = c("Blue"           = "deepskyblue",
                                    "Blue/Green"     = "turquoise",
                                    "Blue/Green/Red" = "blueviolet",
                                    "Blue/Red"       = "magenta",
                                    "Blue/Woori1"    = "mediumblue",
                                    "Blue/Woori3"    = "lawngreen",
                                    "Green"          = "forestgreen",
                                    "Green/Red"      = "goldenrod",
                                    "JESWA"          = "gray",
                                    "Red"            = "red",
                                    "Woori1"         = "black",
                                    "Woori1/Woori2"  = "sienna",
                                    "Woori2"         = "darkorange",
                                    "Woori3"         = "yellow",
                                    "WY&CCC"         = "pink")) + 
      #geom_dl(aes(label = pop), method = "smart.grid") + 
      theme(axis.title   = element_text(face = "bold", size = "16", 
                                          color = "black"), 
            axis.text.x  = element_text(face = "bold", angle = 0, vjust = 0.5, 
                                          size = 59), 
            axis.text.y  = element_text(face = "bold", angle = 0, vjust = 0.5, 
                                          size = 14), 
            legend.title = element_text(colour = "black", size = 18, face = "bold"), 
            legend.text  = element_text(colour = "black", size = 18, face = "bold")) + 
      labs(x = xlab, y = ylab) + 
      geom_hline(yintercept = 0) + 
      geom_vline(xintercept = 0) + 
      theme(legend.position = "none") + 
      theme_bw()
    if (scale == TRUE) {
      p <- p + coord_fixed(ratio = e[yaxis]/e[xaxis])
    }
    if (ellipse == TRUE) {
      p <- p + stat_ellipse(aes(colour = "black"), type = "norm", 
        level = 0.95)
    }
  }
  p
  return(p)
}

2011.2012

#pc1 <- gl.pcoa(gl_season[[1]], nfactors=5)
barplot(pc1$eig/sum(pc1$eig)*100, 
        xlab = "PC",
        ylab = "Percentage of represented variation")

      
biplot.pop(pc1, gl_season[[1]], labels = "pop", xaxis = 1, yaxis = 2)
Plotting populations

2012.2013

#pc2 <- gl.pcoa(gl_season[[2]], nfactors=5)
barplot(pc2$eig/sum(pc2$eig)*100, 
        xlab = "PC",
        ylab = "Percentage of represented variation")

      
biplot.pop(pc2, gl_season[[2]], labels = "pop", xaxis = 1, yaxis = 2)
Plotting populations

2013.2014

#pc3 <- gl.pcoa(gl_season[[3]], nfactors = 5)
barplot(pc3$eig/sum(pc3$eig)*100, 
        xlab = "PC",
        ylab = "Percentage of represented variation")

      
biplot.pop(pc3, gl_season[[3]], labels = "pop", xaxis = 1, yaxis = 2)
Plotting populations

2014.2015

#pc4 <- gl.pcoa(gl_season[[4]], nfactors = 5)
barplot(pc4$eig/sum(pc4$eig)*100, 
        xlab = "PC",
        ylab = "Percentage of represented variation")

      
biplot.pop(pc4, gl_season[[4]], labels = "pop", xaxis = 1, yaxis = 2)
Plotting populations

2015.2016

#pc5 <- gl.pcoa(gl_season[[5]], nfactors = 5)
barplot(pc5$eig/sum(pc5$eig)*100, 
        xlab = "PC",
        ylab = "Percentage of represented variation")

      
biplot.pop(pc5, gl_season[[5]], labels = "pop", xaxis = 1, yaxis = 2)
Plotting populations

2016.2017

pc6 <- gl.pcoa(gl_season[[6]], nfactors = 5)
Performing a PCoA, individuals as entities, SNP loci as attributes
Ordination yielded 26 informative dimensions from 93 original dimensions
  PCoA Axis 1 explains 6.9 % of the total variance
  PCoA Axis 1 and 2 combined explain 13.2 % of the total variance
  PCoA Axis 1-3 combined explain 18 % of the total variance
barplot(pc6$eig/sum(pc6$eig)*100, 
        xlab = "PC",
        ylab = "Percentage of represented variation")

      
biplot.pop(pc6, gl_season[[6]], labels = "pop", xaxis = 1, yaxis = 2)
Plotting populations

2017.2018

pc7 <- gl.pcoa(gl_season[[7]], nfactors = 5)
Performing a PCoA, individuals as entities, SNP loci as attributes
Ordination yielded 31 informative dimensions from 117 original dimensions
  PCoA Axis 1 explains 6.5 % of the total variance
  PCoA Axis 1 and 2 combined explain 12.1 % of the total variance
  PCoA Axis 1-3 combined explain 16.7 % of the total variance
barplot(pc7$eig/sum(pc7$eig)*100, 
        xlab = "PC",
        ylab = "Percentage of represented variation")

      
biplot.pop(pc7, gl_season[[7]], labels = "pop", xaxis = 1, yaxis = 2)
Plotting populations

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiANCg0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAxLiBUcmFuc2Zvcm0gLnZjZiB0byBnZW5saWdodA0KDQojIEltcG9ydCBjbGVhbiAudmNmOg0KYGBge3J9DQpsaWJyYXJ5KHZjZlIpDQp2Y2ZfY2xlYW4gPC0gcmVhZC52Y2ZSKGZpbGUgPSAiQzovVXNlcnMvZHJvYjAwMDYvR29vZ2xlIERyaXZlL1Byb2plY3RzLzEuTWF0ZUNob2ljZV9CcmVlZGluZ01hbmFnZW1lbnQvQW5hbHlzZXMyMDIwLzBfMjAyMC4wMi4xMV9TTlBjYWxsaW5nX3Jhd0RBclRzLzMuc2V4LWxpbmtlZC9wMXI5X2xkXzUwa2JfMWtiX3JlbW92ZWRfbWlzc2luZ18wLjYxX25vX3NleGxpbmtlZF9IVy5yZWNvZGUudmNmIikNCmBgYA0KDQoNCiMgVHJhbnNmb3JtIC52Y2YgdG8gZ2VubGlnaHQ6DQpgYGB7cn0NCmdsIDwtIHZjZlIyZ2VubGlnaHQodmNmX2NsZWFuKQ0KYGBgDQoNCiMgTGV0J3MgaW5zcGVjdCB0aGUgZ2wgb2JqZWN0Og0KYGBge3J9DQpnbA0KYGBgDQoNCiMgQ2hhbmdlIG5hbWVzIChnZW5vdHlwaW5nIElEKSBmb3IgQmFuZElEDQpgYGB7cn0NCiMgSW1wb3J0IElEIG1hc3RlciBkYXRhYmFzZQ0KYmFuZHMgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL2Ryb2IwMDA2L0dvb2dsZSBEcml2ZS9Qcm9qZWN0cy8xLk1hdGVDaG9pY2VfQnJlZWRpbmdNYW5hZ2VtZW50L0FuYWx5c2VzMjAyMC8zXzIwMjAuMDIuMjFfS2luc2hpcF9JbmJyZWVkaW5nX0NPQU5DRVNUUlkvMjAyMC4wMi4xMF9JRF9NQVNURVJfZGF0YWJhc2UuY3N2IiwNCiAgICAgICAgICAgICAgICAgIGNvbENsYXNzZXMgPSBjKCJOVUxMIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjaGFyYWN0ZXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImNoYXJhY3RlciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXAoIk5VTEwiLCAzKSkpDQoNCiMgTWVyZ2UgdGhlIGdsIG5hbWVzIHdpdGggdGhlIEJhbmRJRHMNCm5ldyA8LSBtZXJnZShkYXRhLmZyYW1lKGdsQGluZC5uYW1lcyksIA0KICAgICAgICAgICAgIGJhbmRzLA0KICAgICAgICAgICAgIGJ5LnggPSAiZ2wuaW5kLm5hbWVzIiwNCiAgICAgICAgICAgICBieS55ID0gIkdlbm90eXBpbmdfY2xlYW5JRCIsDQogICAgICAgICAgICAgYWxsLnggPSBUUlVFLCAgIyBhbGwgZ29vZCwgbm8gTkFzDQogICAgICAgICAgICAgc29ydCA9IEZBTFNFKQ0KDQojIFN1YnN0aXR1dGUgd2VpcmQgbmFtZSAiMDQzLTAwNTQxIChvciA1NDI/KSINCm5ld1sxMjQsICJCYW5kSUQiXSA8LSAiMDQzLTAwNTQxIg0KDQojIENoZWNrIHRoYXQgb3JkZXIgaXMgY29ycmVjdA0Kc3VtKGdsQGluZC5uYW1lcyA9PSBuZXckZ2wuaW5kLm5hbWVzKSAgIyA1MzMgbWVhbnMgYWxsIHJvd3MgYXJlIFRSVUUNCg0KIyBTdWJzdGl0dXRlIGdsIG5hbWVzIChnZW5vdHlwaW5nIElEKSBmb3IgQmFuZElEDQpnbEBpbmQubmFtZXMgPC0gbmV3JEJhbmRJRA0KYGBgDQoNCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAyLiBTdWJzZXQgY2Vuc3VzIHBlciBzZWFzb24NClRoaXMgY2Vuc3VzIHdhcyBtb2RpZmllZCBtYW51YWxseSB0byBoYXZlIGVhY2ggaW5kaXZpZHVhbCBwZXIgc2Vhc29uIG9ubHkgb25jZSwNCmFuZCBpZiB0aGV5IHdlcmUgcHJlc2VudCBpbiBtb3JlIHRoYW4gb25lIG5laWdoYm91cmhvb2QsIEkgZnVzZWQgdGhlIG5laWdoYm91cmhvb2QNCmxhYmVsDQpgYGB7cn0NCmNlbnN1cyA8LSByZWFkLmNzdigiQzovVXNlcnMvZHJvYjAwMDYvR29vZ2xlIERyaXZlL1Byb2plY3RzLzEuTWF0ZUNob2ljZV9CcmVlZGluZ01hbmFnZW1lbnQvQW5hbHlzZXMyMDIwLzExXzIwMjAuMDQuMjFfUENBL0NlbnN1c19hbGxfc2Vhc29uc19uZWlnaGJvdXJob29kLmNzdiIsDQogICAgICAgICAgICAgICAgICBjb2xDbGFzc2VzID0gYygiZmFjdG9yIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmYWN0b3IiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5VTEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImNoYXJhY3RlciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmFjdG9yIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcCgiTlVMTCIsIDMpKSkNCiAgICAgICAgICAgICAgICAgICANCmNlbnNpIDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6bGVuZ3RoKGxldmVscyhjZW5zdXMkU2Vhc29uKSkpDQogIGNlbnNpW1tpXV0gPC0gZHJvcGxldmVscyhjZW5zdXNbY2Vuc3VzJFNlYXNvbiA9PSBsZXZlbHMoY2Vuc3VzJFNlYXNvbilbaV0sIF0pDQpgYGANCg0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gMy4gTWFrZSByZWNvZGUgdGFibGUgcGVyIHNlYXNvbg0KYGBge3J9DQojIE1ha2UgcmVjb2RlIHRhYmxlDQpsaWJyYXJ5KGRhcnRSKQ0KZ2wubWFrZS5yZWNvZGUuaW5kKGdsLCBvdXRmaWxlID0gInJlY29kZS5jc3YiLCBvdXRwYXRoID0gIkM6L1VzZXJzL2Ryb2IwMDA2L0dvb2dsZSBEcml2ZS9Qcm9qZWN0cy8xLk1hdGVDaG9pY2VfQnJlZWRpbmdNYW5hZ2VtZW50L0FuYWx5c2VzMjAyMC8xMV8yMDIwLjA0LjIxX1BDQS8iKQ0KDQoNCg0KIyBJbXBvcnQgaXQgYmFjaw0KcmVjb2RlX2RmIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9kcm9iMDAwNi9Hb29nbGUgRHJpdmUvUHJvamVjdHMvMS5NYXRlQ2hvaWNlX0JyZWVkaW5nTWFuYWdlbWVudC9BbmFseXNlczIwMjAvMTFfMjAyMC4wNC4yMV9QQ0EvcmVjb2RlLmNzdiIsDQogICAgICAgICAgICAgICAgICAgICAgaGVhZGVyID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgY29sQ2xhc3NlcyA9IGMoImNoYXJhY3RlciIsICJjaGFyYWN0ZXIiKSkNCg0KIyBNZXJnZSBwZXIgc2Vhc29uIG1ha2luZyAiTlVMTCIgYXMgIkRlbGV0ZSINCnJlY29kZXMgPC0gbGlzdCgpDQpmb3IgKGkgaW4gMTpsZW5ndGgoY2Vuc2kpKQ0KICByZWNvZGVzW1tpXV0gPC0gbWVyZ2UocmVjb2RlX2RmLA0KICAgICAgICAgICAgICAgICAgICAgICAgY2Vuc2lbW2ldXVssIDM6NF0sDQogICAgICAgICAgICAgICAgICAgICAgICBieS54ID0gIlYxIiwNCiAgICAgICAgICAgICAgICAgICAgICAgIGJ5LnkgPSAiQmFuZCIsDQogICAgICAgICAgICAgICAgICAgICAgICBhbGwueCA9IFRSVUUpICAjIENhbm5vdCBiZSBzb3J0ZWQ6IGl0IGxlYXZlcyBOQSBhdCB0aGUgZW5kDQoNCmZvciAoaSBpbiAxOmxlbmd0aChyZWNvZGVzKSkgew0KICBmb3IgKGogaW4gMTpucm93KHJlY29kZXNbW2ldXSkpIHsNCiAgICBpZiAoaXMubmEocmVjb2Rlc1tbaV1dW2osICJTZXgiXSkpDQogICAgICByZWNvZGVzW1tpXV1baiwgIlYyIl0gPC0gIkRlbGV0ZSINCiAgICB9DQogIHJlY29kZXNbW2ldXSA8LSByZWNvZGVzW1tpXV1bLCAtM10NCn0NCg0KIyBDaGVjayBhbGwgaGF2ZSB0aGUgc2FtZSBudW1iZXIgb2YgaW5kaXZpZHVhbHMNCmZvciAoaSBpbiAxOmxlbmd0aChyZWNvZGVzKSkNCiAgcHJpbnQobnJvdyhyZWNvZGVzW1tpXV0pKQ0KDQojIE9yZGVyIGJ5IHRoZSBuYW1lcyBpbiB0aGUgZ2wgb2JqZWN0DQpmb3IgKGkgaW4gMTpsZW5ndGgocmVjb2RlcykpDQogIHJlY29kZXNbW2ldXSA8LSByZWNvZGVzW1tpXV1bbWF0Y2goZ2xAaW5kLm5hbWVzLCByZWNvZGVzW1tpXV0kVjEpLCBdDQoNCiMgU2VlIGlmIHRoZXkgbWF0Y2gNCmZvciAoaSBpbiAxOmxlbmd0aChyZWNvZGVzKSkNCiAgcHJpbnQoc3VtKHJlY29kZXNbW2ldXSRWMSA9PSBnbEBpbmQubmFtZXMpKSAgIyBBbGwgNTMzIG1lYW5zIHRoZXkgYWxsIG1hdGNoDQoNCiMgU2F2ZSB0aGVtIGFzIC5jc3YNCnNlYXNvbnMgPC0gYygiMjAxMS4yMDEyIiwNCiAgICAgICAgICAgICAiMjAxMi4yMDEzIiwNCiAgICAgICAgICAgICAiMjAxMy4yMDE0IiwNCiAgICAgICAgICAgICAiMjAxNC4yMDE1IiwNCiAgICAgICAgICAgICAiMjAxNS4yMDE2IiwNCiAgICAgICAgICAgICAiMjAxNi4yMDE3IiwNCiAgICAgICAgICAgICAiMjAxNy4yMDE4IikNCg0KZm9yIChpIGluIDE6bGVuZ3RoKHJlY29kZXMpKQ0KICB3cml0ZS50YWJsZShyZWNvZGVzW1tpXV0sIGZpbGUgPSBwYXN0ZSgiQzovVXNlcnMvZHJvYjAwMDYvR29vZ2xlIERyaXZlL1Byb2plY3RzLzEuTWF0ZUNob2ljZV9CcmVlZGluZ01hbmFnZW1lbnQvQW5hbHlzZXMyMDIwLzExXzIwMjAuMDQuMjFfUENBL3JlY29kZV8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Vhc29uc1tpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIuY3N2IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICIiKSwgDQogICAgICAgICAgICByb3cubmFtZXMgPSBGQUxTRSwNCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IEZBTFNFLA0KICAgICAgICAgICAgc2VwID0gIiwiKQ0KYGBgDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSA0LiBTdWJzZXQgZ2wgcGVyIHNlYXNvbg0KYGBge3J9DQojIFVzaW5nIGZ1bmN0aW9uIHRoYXQgc3Vic2V0cyBhbmQgcmVjYWxjdWxhdGVzIGFsbGVsZSBmcmVxdWVuY2llcywgZGVsZXRpbmcNCiMgbW9ub21vcnBoaWMgbG9jaQ0KZ2xfc2Vhc29uIDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6bGVuZ3RoKHNlYXNvbnMpKQ0KICBnbF9zZWFzb25bW2ldXSA8LSBnbC5yZWNvZGUuaW5kKGdsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmQucmVjb2RlID0gcGFzdGUoIkM6L1VzZXJzL2Ryb2IwMDA2L0dvb2dsZSBEcml2ZS9Qcm9qZWN0cy8xLk1hdGVDaG9pY2VfQnJlZWRpbmdNYW5hZ2VtZW50L0FuYWx5c2VzMjAyMC8xMV8yMDIwLjA0LjIxX1BDQS9yZWNvZGVfIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlYXNvbnNbaV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLmNzdiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiIikpDQpgYGANCg0KDQojIC0tLS0tLS0tLS0tLS0gNS4gQWRkIGluZGl2aWR1YWwgbWV0YWRhdGEgZmlsZSB3aXRoIGlkLCBwb3AsIHNleA0KYGBge3J9DQppbmQubWV0YWRhdGFfc2Vhc29uIDwtIGxpc3QoKQ0KZm9yIChpIGluIDE6bGVuZ3RoKHJlY29kZXMpKSB7DQogIGluZC5tZXRhZGF0YV9zZWFzb25bW2ldXSA8LSBtZXJnZShyZWNvZGVzW1tpXV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZW5zaVtbaV1dWywgLTFdLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkueCA9ICJWMSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieS55ID0gIkJhbmQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc29ydCA9IEZBTFNFKQ0KICBpbmQubWV0YWRhdGFfc2Vhc29uW1tpXV0gPC0gaW5kLm1ldGFkYXRhX3NlYXNvbltbaV1dWywgLTJdDQogIG5hbWVzKGluZC5tZXRhZGF0YV9zZWFzb25bW2ldXSkgPC0gYygiaWQiLCAicG9wIiwgInNleCIpDQogICMgQ2hlY2sgaWYgdGhleSBoYXZlIHNhbWUgbnVtYmVyIG9mIGluZGl2aWR1YWxzDQogIHByaW50KG5yb3coaW5kLm1ldGFkYXRhX3NlYXNvbltbaV1dKSkNCiAgcHJpbnQobGVuZ3RoKGdsX3NlYXNvbltbaV1dQGluZC5uYW1lcykpDQogICMgQ2hlY2sgaWYgYWxsIG9mIHRoZW0gbWF0Y2ggaW4gb3JkZXINCiAgcHJpbnQoc3VtKGluZC5tZXRhZGF0YV9zZWFzb25bW2ldXSRpZCA9PSBnbF9zZWFzb25bW2ldXUBpbmQubmFtZXMpKQ0KfQ0KYGBgDQoNCiMgTm93IHdlIGFzc2lnbiB0aGUgaW5kLm1ldGFkYXRhIGFzIHRoZSBAb3RoZXIkaW5kLm1ldHJpY3Mgc2VjdGlvbiBvZiB0aGUgZ2VubGlnaHQgb2JqZWN0czoNCmBgYHtyfQ0KZm9yIChpIGluIDE6bGVuZ3RoKGdsX3NlYXNvbikpIHsNCiAgIyBBc3NpZ24gYXMgaW5kaXZpZHVhbCBtZXRhZmlsZQ0KICBnbF9zZWFzb25bW2ldXUBvdGhlciRpbmQubWV0cmljcyA8LSBpbmQubWV0YWRhdGFfc2Vhc29uW1tpXV0NCiAgIyBBbmQgYXMgcG9wDQogIGdsX3NlYXNvbltbaV1dQHBvcCA8LSBpbmQubWV0YWRhdGFfc2Vhc29uW1tpXV0kcG9wDQogICMgQ2hlY2sgaWYgZXZlcnl0aGluZyBpcyBjb3JyZWN0DQogIHByaW50KHN1bShnbF9zZWFzb25bW2ldXUBpbmQubmFtZXMgPT0gZ2xfc2Vhc29uW1tpXV1Ab3RoZXIkaW5kLm1ldHJpY3MkaWQpKQ0KfQ0KDQojcG9wKGdsX3NlYXNvbltbMV1dKQ0KI2dsX3NlYXNvbltbMV1dDQpgYGANCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSA2LiBQQ0ENCiMgTW9kaWZ5aW5nIGRhcnRSIGZ1bmN0aW9uIGZvciBnZW5lcmF0aW5nIFBDQSBiaXBsb3QNCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoImRpcmVjdGxhYmVscyIpDQojbGlicmFyeShkaXJlY3RsYWJlbHMpDQoNCmJpcGxvdC5wb3AgPC0gZnVuY3Rpb24oZ2xQY2EsIGRhdGEsIHNjYWxlID0gRkFMU0UsIGVsbGlwc2UgPSBGQUxTRSwgcCA9IDAuOTUsIA0KICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSAicG9wIiwgaGFkanVzdCA9IDEuNSwgdmFkanVzdCA9IDEsIHhheGlzID0gMSwgDQogICAgICAgICAgICAgICAgICAgICAgIHlheGlzID0gMikgew0KICAjIFNhbml0eSBjaGVja3MNCiAgaWYgKGNsYXNzKGdsUGNhKSAhPSAiZ2xQY2EiIHwgY2xhc3MoZGF0YSkgIT0gImdlbmxpZ2h0Iikgew0KICAgIGNhdCgiRmF0YWwgRXJyb3I6IGdsUGNhIGFuZCBnZW5saWdodCBvYmplY3RzIHJlcXVpcmVkIGZvciBnbFBjYSBhbmQgZGF0YSBwYXJhbWV0ZXJzIHJlc3BlY3RpdmVseSFcbiIpDQogICAgc3RvcCgpDQogIH0NCiAgaWYgKGxhYmVscyAhPSAicG9wIikgew0KICAgIGNhdCgiRmF0YWwgRXJyb3I6IFRoaXMgZnVuY3Rpb24gaXMgb25seSBmb3IgcGxvdHRpbmcgcG9wdWxhdGlvbnMhXG4iKQ0KICAgIHN0b3AoKQ0KICB9DQogIGxpYnJhcnkoZ2dwbG90MikNCiAgI2xpYnJhcnkoZGlyZWN0bGFiZWxzKQ0KICAjIFBhcmFtZXRlcnMNCiAgbSA8LSBjYmluZChnbFBjYSRzY29yZXNbLCB4YXhpc10sIGdsUGNhJHNjb3Jlc1ssIHlheGlzXSkNCiAgZGYgPC0gZGF0YS5mcmFtZShtKQ0KICBzIDwtIHN1bShnbFBjYSRlaWcpDQogIGUgPC0gcm91bmQoZ2xQY2EkZWlnICogMTAwL3MsIDEpDQogIHhsYWIgPC0gcGFzdGUoIlBDb0EgIGF4aXMgICIsIHhheGlzLCAiICAoIiwgZVt4YXhpc10sICIlKSIsIHNlcCA9ICIiKQ0KICB5bGFiIDwtIHBhc3RlKCJQQ29BICBheGlzICAiLCB5YXhpcywgIiAgKCIsIGVbeWF4aXNdLCAiJSkiLCBzZXAgPSAiIikNCiAgDQogICMgUGxvdHRpbmcNCiAgaWYgKGxhYmVscyA9PSAicG9wIikgew0KICAgIGNhdCgiUGxvdHRpbmcgcG9wdWxhdGlvbnNcbiIpDQogICAgaW5kIDwtIGluZE5hbWVzKGRhdGEpDQogICAgTmVpZ2hib3VyaG9vZCA8LSBmYWN0b3IocG9wKGRhdGEpKQ0KICAgIGRmIDwtIGNiaW5kKGRmLCBpbmQsIGZhY3Rvcihwb3AoZGF0YSkpKQ0KICAgIGNvbG5hbWVzKGRmKSA8LSBjKCJQQ29BeCIsICJQQ29BeSIsICJpbmQiLCAicG9wIikNCiAgICANCiAgICBwIDwtIGdncGxvdChkZiwgDQogICAgICAgICAgICAgICAgYWVzKHggPSBkZiRQQ29BeCwgeSA9IGRmJFBDb0F5LCBncm91cCA9IE5laWdoYm91cmhvb2QsIGNvbG91ciA9IE5laWdoYm91cmhvb2QpKSArIA0KICAgICAgZ2VvbV9wb2ludChzaXplID0gMywgYWVzKGNvbG91ciA9IE5laWdoYm91cmhvb2QpKSArDQogICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiQmx1ZSIgICAgICAgICAgID0gImRlZXBza3libHVlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCbHVlL0dyZWVuIiAgICAgPSAidHVycXVvaXNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCbHVlL0dyZWVuL1JlZCIgPSAiYmx1ZXZpb2xldCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmx1ZS9SZWQiICAgICAgID0gIm1hZ2VudGEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJsdWUvV29vcmkxIiAgICA9ICJtZWRpdW1ibHVlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCbHVlL1dvb3JpMyIgICAgPSAibGF3bmdyZWVuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcmVlbiIgICAgICAgICAgPSAiZm9yZXN0Z3JlZW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdyZWVuL1JlZCIgICAgICA9ICJnb2xkZW5yb2QiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkpFU1dBIiAgICAgICAgICA9ICJncmF5IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWQiICAgICAgICAgICAgPSAicmVkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXb29yaTEiICAgICAgICAgPSAiYmxhY2siLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldvb3JpMS9Xb29yaTIiICA9ICJzaWVubmEiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldvb3JpMiIgICAgICAgICA9ICJkYXJrb3JhbmdlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXb29yaTMiICAgICAgICAgPSAieWVsbG93IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXWSZDQ0MiICAgICAgICAgPSAicGluayIpKSArIA0KICAgICAgI2dlb21fZGwoYWVzKGxhYmVsID0gcG9wKSwgbWV0aG9kID0gInNtYXJ0LmdyaWQiKSArIA0KICAgICAgdGhlbWUoYXhpcy50aXRsZSAgID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAiMTYiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiksIA0KICAgICAgICAgICAgYXhpcy50ZXh0LnggID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIGFuZ2xlID0gMCwgdmp1c3QgPSAwLjUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDU5KSwgDQogICAgICAgICAgICBheGlzLnRleHQueSAgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgYW5nbGUgPSAwLCB2anVzdCA9IDAuNSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMTQpLCANCiAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMTgsIGZhY2UgPSAiYm9sZCIpLCANCiAgICAgICAgICAgIGxlZ2VuZC50ZXh0ICA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMTgsIGZhY2UgPSAiYm9sZCIpKSArIA0KICAgICAgbGFicyh4ID0geGxhYiwgeSA9IHlsYWIpICsgDQogICAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIA0KICAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCkgKyANCiAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCiAgICAgIHRoZW1lX2J3KCkNCiAgICBpZiAoc2NhbGUgPT0gVFJVRSkgew0KICAgICAgcCA8LSBwICsgY29vcmRfZml4ZWQocmF0aW8gPSBlW3lheGlzXS9lW3hheGlzXSkNCiAgICB9DQogICAgaWYgKGVsbGlwc2UgPT0gVFJVRSkgew0KICAgICAgcCA8LSBwICsgc3RhdF9lbGxpcHNlKGFlcyhjb2xvdXIgPSAiYmxhY2siKSwgdHlwZSA9ICJub3JtIiwgDQogICAgICAgIGxldmVsID0gMC45NSkNCiAgICB9DQogIH0NCiAgcA0KICByZXR1cm4ocCkNCn0NCmBgYA0KDQojIDIwMTEuMjAxMg0KYGBge3J9DQojcGMxIDwtIGdsLnBjb2EoZ2xfc2Vhc29uW1sxXV0sIG5mYWN0b3JzPTUpDQpiYXJwbG90KHBjMSRlaWcvc3VtKHBjMSRlaWcpKjEwMCwgDQogICAgICAgIHhsYWIgPSAiUEMiLA0KICAgICAgICB5bGFiID0gIlBlcmNlbnRhZ2Ugb2YgcmVwcmVzZW50ZWQgdmFyaWF0aW9uIikNCiAgICAgIA0KYmlwbG90LnBvcChwYzEsIGdsX3NlYXNvbltbMV1dLCBsYWJlbHMgPSAicG9wIiwgeGF4aXMgPSAxLCB5YXhpcyA9IDIpDQpgYGANCg0KDQojIDIwMTIuMjAxMw0KYGBge3J9DQojcGMyIDwtIGdsLnBjb2EoZ2xfc2Vhc29uW1syXV0sIG5mYWN0b3JzPTUpDQpiYXJwbG90KHBjMiRlaWcvc3VtKHBjMiRlaWcpKjEwMCwgDQogICAgICAgIHhsYWIgPSAiUEMiLA0KICAgICAgICB5bGFiID0gIlBlcmNlbnRhZ2Ugb2YgcmVwcmVzZW50ZWQgdmFyaWF0aW9uIikNCiAgICAgIA0KYmlwbG90LnBvcChwYzIsIGdsX3NlYXNvbltbMl1dLCBsYWJlbHMgPSAicG9wIiwgeGF4aXMgPSAxLCB5YXhpcyA9IDIpDQpgYGANCg0KDQojIDIwMTMuMjAxNA0KYGBge3J9DQojcGMzIDwtIGdsLnBjb2EoZ2xfc2Vhc29uW1szXV0sIG5mYWN0b3JzID0gNSkNCmJhcnBsb3QocGMzJGVpZy9zdW0ocGMzJGVpZykqMTAwLCANCiAgICAgICAgeGxhYiA9ICJQQyIsDQogICAgICAgIHlsYWIgPSAiUGVyY2VudGFnZSBvZiByZXByZXNlbnRlZCB2YXJpYXRpb24iKQ0KICAgICAgDQpiaXBsb3QucG9wKHBjMywgZ2xfc2Vhc29uW1szXV0sIGxhYmVscyA9ICJwb3AiLCB4YXhpcyA9IDEsIHlheGlzID0gMikNCmBgYA0KDQoNCiMgMjAxNC4yMDE1DQpgYGB7cn0NCiNwYzQgPC0gZ2wucGNvYShnbF9zZWFzb25bWzRdXSwgbmZhY3RvcnMgPSA1KQ0KYmFycGxvdChwYzQkZWlnL3N1bShwYzQkZWlnKSoxMDAsIA0KICAgICAgICB4bGFiID0gIlBDIiwNCiAgICAgICAgeWxhYiA9ICJQZXJjZW50YWdlIG9mIHJlcHJlc2VudGVkIHZhcmlhdGlvbiIpDQogICAgICANCmJpcGxvdC5wb3AocGM0LCBnbF9zZWFzb25bWzRdXSwgbGFiZWxzID0gInBvcCIsIHhheGlzID0gMSwgeWF4aXMgPSAyKQ0KYGBgDQoNCg0KDQojIDIwMTUuMjAxNg0KYGBge3J9DQojcGM1IDwtIGdsLnBjb2EoZ2xfc2Vhc29uW1s1XV0sIG5mYWN0b3JzID0gNSkNCmJhcnBsb3QocGM1JGVpZy9zdW0ocGM1JGVpZykqMTAwLCANCiAgICAgICAgeGxhYiA9ICJQQyIsDQogICAgICAgIHlsYWIgPSAiUGVyY2VudGFnZSBvZiByZXByZXNlbnRlZCB2YXJpYXRpb24iKQ0KICAgICAgDQpiaXBsb3QucG9wKHBjNSwgZ2xfc2Vhc29uW1s1XV0sIGxhYmVscyA9ICJwb3AiLCB4YXhpcyA9IDEsIHlheGlzID0gMikNCmBgYA0KDQoNCiMgMjAxNi4yMDE3DQpgYGB7cn0NCnBjNiA8LSBnbC5wY29hKGdsX3NlYXNvbltbNl1dLCBuZmFjdG9ycyA9IDUpDQpiYXJwbG90KHBjNiRlaWcvc3VtKHBjNiRlaWcpKjEwMCwgDQogICAgICAgIHhsYWIgPSAiUEMiLA0KICAgICAgICB5bGFiID0gIlBlcmNlbnRhZ2Ugb2YgcmVwcmVzZW50ZWQgdmFyaWF0aW9uIikNCiAgICAgIA0KYmlwbG90LnBvcChwYzYsIGdsX3NlYXNvbltbNl1dLCBsYWJlbHMgPSAicG9wIiwgeGF4aXMgPSAxLCB5YXhpcyA9IDIpDQpgYGANCg0KDQojIDIwMTcuMjAxOA0KYGBge3J9DQpwYzcgPC0gZ2wucGNvYShnbF9zZWFzb25bWzddXSwgbmZhY3RvcnMgPSA1KQ0KYmFycGxvdChwYzckZWlnL3N1bShwYzckZWlnKSoxMDAsIA0KICAgICAgICB4bGFiID0gIlBDIiwNCiAgICAgICAgeWxhYiA9ICJQZXJjZW50YWdlIG9mIHJlcHJlc2VudGVkIHZhcmlhdGlvbiIpDQogICAgICANCmJpcGxvdC5wb3AocGM3LCBnbF9zZWFzb25bWzddXSwgbGFiZWxzID0gInBvcCIsIHhheGlzID0gMSwgeWF4aXMgPSAyKQ0KYGBgDQoNCg0KDQoNCg0KDQoNCg==