ALL IMPORTED FILES MUST BE IN THE SAME DIRECTORY AS THIS SCRIPT

Load tidyverse package

setwd("~/OneDrive - The University of Melbourne/R data")
library("tidyverse")

Import raw vcf data from “masterfile” and exclude variants with GnomAD non-cancer AF > 0

masterfile <- read.delim("masterfile.tsv", header=TRUE, row.names=NULL, na.strings = ".", stringsAsFactors=FALSE) %>% 
  dplyr::rename("Sample"="X.Sample") %>% 
  filter(GnomAD_v2.1_non_cancer_AF==0)

Exclude non-epithelial, uterine-only and BRCA +ve samples

ViP_Complete_Cohort <- read.delim("ViP_LoF_Complete_Cohort.txt", stringsAsFactors=FALSE)
ViP_Complete_Cohort_list <- ViP_Complete_Cohort[,1]

masterfile_eoc <- filter(masterfile,Sample%in%c(ViP_Complete_Cohort_list))

Append patient path data and family history info

ViP_OvCa_Path_Data <- read.delim("ViP_OvCa_Path_Data.txt", header=TRUE, row.names=NULL, stringsAsFactors=FALSE) %>% 
  dplyr::rename("Sample"=Exome.ID)
NoFHxCa <- read.delim("NoFHxCa.tsv", header=TRUE, row.names=NULL, stringsAsFactors=FALSE) %>% 
  select(Exome.ID,FHx) %>% 
  dplyr::rename("Sample"=Exome.ID)
masterfile_eoc2 <- left_join(masterfile_eoc,ViP_OvCa_Path_Data,by="Sample",copy=FALSE) %>% 
  left_join(NoFHxCa,by="Sample",copy=FALSE) %>% 
  mutate_at(vars("FHx"),funs(replace(., is.na(.), "YES")))

Exclude other mutation +ve samples (MLH1/MSH2/MSH6/PMS2, TP53, RAD51C/D, BRIP1)

ViP_Discovery_Cohort <- read.delim("ViP_LoF_Discovery_Cohort.txt", stringsAsFactors=FALSE)
ViP_Discovery_Cohort_list <- ViP_Discovery_Cohort[,1]

masterfile_eoc3 <- filter(masterfile_eoc2,Sample%in%c(ViP_Discovery_Cohort_list))

Add Sample AD/DP column to calculate read freq for variants with missing PMCFREQ values

masterfile_eoc4 <- mutate(masterfile_eoc3, AD = as.numeric(sapply(strsplit(Sample.AD,","), function(x) tail(x,1))), DP = as.numeric(Sample.DP), Sample.FREQ = AD/DP)

Total_Sample_Alleles <- (n_distinct(masterfile_eoc4$Sample)*2)

Exclude low-quality variants, GnomAD RF/InbreedingCoeff-flagged variants

masterfile_eoc_lowFreq <- filter(masterfile_eoc4, (QUAL>=30)&
                                 (Identified!="FilteredInAll")&
                                 (Sample.PMCDP>=20)&
                                 (Sample.PMCFREQ<0.25)&
                                 (Sample.FREQ<0.25)) %>% 
  filter(Sample.FREQ>=0.01) %>% 
  filter((!str_detect(GnomAD_v2.1_FILTER_exome,"InbreedingCoeff")&
            !str_detect(GnomAD_v2.1_FILTER_exome,"RF"))|
           is.na(GnomAD_v2.1_FILTER_exome)) %>%
  filter((!str_detect(GnomAD_v2.1_FILTER_genome,"InbreedingCoeff")&
            !str_detect(GnomAD_v2.1_FILTER_genome,"RF"))|
           is.na(GnomAD_v2.1_FILTER_genome))

Remove HAP-only indel variants with PMCFREQ==0

masterfile_eoc_lowFreq_HAP_SNV <- filter(masterfile_eoc_lowFreq,Sample.PMCFREQ==0) %>% 
  filter(Variant_Type=="SNV")
masterfile_eoc_lowFreq2 <- filter(masterfile_eoc_lowFreq,Sample.PMCFREQ!=0) %>% 
  bind_rows(masterfile_eoc_lowFreq_HAP_SNV,.id=NULL)

Exclude MODERATE impact variants

masterfile_eoc_lowFreq_HIGH <- filter(masterfile_eoc_lowFreq2, IMPACT=="HIGH")

Separate Ensembl canonical and RefSeq canonical variants

masterfile_eoc_lowFreq_HIGH_ENSTcanonical <- filter(masterfile_eoc_lowFreq_HIGH,CANONICAL=="YES") %>% 
  write_excel_csv(path="masterfile_eoc_altAF0.25_HIGH_ENSTcanonical.csv",na=".",append=FALSE,col_names=TRUE)

Sample variant counts and AFs

variant_counts_AFs <- function(vcf){
variants_heterozygous <- vcf %>% 
  select(HGVSc,Sample.GT) %>% 
  group_by(HGVSc,Sample.GT) %>% 
  summarise(n()) %>% 
  filter((Sample.GT%in%c("'0/1","'1/0"))) %>% 
  dplyr::rename(alleles = "n()") %>% 
  group_by(HGVSc) %>% 
  summarise(sum(alleles))
variants_homozygous <- vcf %>% 
  select(HGVSc,Sample.GT) %>% 
  group_by(HGVSc,Sample.GT) %>% 
  summarise(n()) %>% 
  filter((Sample.GT!="'0/1")&(Sample.GT!="'1/0")) %>% 
  mutate(alleles = `n()`*2) %>% 
  select(-`n()`) %>% 
  group_by(HGVSc) %>% 
  summarise(sum(alleles))
variants <- full_join(variants_heterozygous,variants_homozygous,by="HGVSc",copy=FALSE,suffix=c(".x",".y")) %>%
  mutate_all(funs(replace(., is.na(.), 0))) %>% 
  mutate(Total_Allele_Count=`sum(alleles).x`+`sum(alleles).y`) %>% 
  mutate(Sample_AF=Total_Allele_Count/Total_Sample_Alleles)
vcf <- left_join(vcf, variants[,c(1,4:5)],by="HGVSc",copy=FALSE)
}

masterfile_eoc_lowFreq_HIGH_ENSTcanonical_2 <- variant_counts_AFs(masterfile_eoc_lowFreq_HIGH_ENSTcanonical)

Sample gene counts and frequencies

gene_counts_AF <- function(vcf){
genes_oneVarAllele <- vcf %>% select(SYMBOL,Sample.GT) %>% 
  select(SYMBOL,Sample.GT) %>% 
  group_by(SYMBOL,Sample.GT) %>% 
  summarise(n()) %>% 
  filter((Sample.GT%in%c("'0/1","'1/0"))) %>% 
  dplyr::rename(gene_Var = "n()") %>% 
  group_by(SYMBOL) %>% 
  summarise(sum(gene_Var))
genes_twoVarAllele <- vcf %>% select(SYMBOL,Sample.GT) %>% 
  select(SYMBOL,Sample.GT) %>% 
  group_by(SYMBOL,Sample.GT) %>% 
  summarise(n()) %>% 
  filter((Sample.GT!="'0/1")&(Sample.GT!="'1/0")) %>% 
  mutate(gene_Var = `n()`*2) %>% 
  select(-`n()`) %>% 
  group_by(SYMBOL) %>% 
  summarise(sum(gene_Var))
genes <- full_join(genes_oneVarAllele,genes_twoVarAllele,by="SYMBOL",copy=FALSE,suffix=c(".x",".y")) %>% 
  mutate_all(funs(replace(., is.na(.), 0))) %>% 
  mutate(Total_Gene_Count=`sum(gene_Var).x`+`sum(gene_Var).y`) %>% 
  mutate(Sample_Gene_Freq=Total_Gene_Count/Total_Sample_Alleles)
vcf <- left_join(vcf, genes[,c(1,4:5)],by="SYMBOL",copy=FALSE)
}

masterfile_eoc_lowFreq_HIGH_ENSTcanonical_3 <- gene_counts_AF(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_2)

Add GnomAD gene-level data

GnomAD_stats_LOF_VEP <- read.delim("GnomAD_stats_LOF_VEP.tsv", header=TRUE, row.names=NULL, stringsAsFactors=FALSE)

masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats <- left_join(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_3, GnomAD_stats_LOF_VEP[,c(2,30:41)],by="Feature",copy=FALSE) 
masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats2 <- mutate_at(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats,vars(starts_with("FILTER_")),funs(replace(., is.na(.), 0))) %>% 
  mutate_if(grepl("popmax$", names(.)),funs(ifelse(. == "NA", 0, as.numeric(.)))) %>% 
  mutate_at(vars(ends_with("popmax")),funs(replace(., is.na(.), 0)))

Calculate Sample/GnomAD gene freq ratios for total and NFE GnomAD figures, including and excluding variants with AF > 0.005

masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios <- 
  mutate(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats2, "Sample_Gene_LOF_Freq_Ratio_GnomAD"=Sample_Gene_Freq/FILTER_RF_LOF_HIGHIMPACT_AF_1.0_ADJ,
"Sample_Gene_LOF_Freq_Ratio_GnomAD_0.005"=Sample_Gene_Freq/FILTER_RF_LOF_HIGHIMPACT_AF_0.005_ADJ,
"Ratio_Difference"=Sample_Gene_LOF_Freq_Ratio_GnomAD_0.005-Sample_Gene_LOF_Freq_Ratio_GnomAD, 
"Sample_Gene_LOF_Freq_Ratio_GnomAD_NFE"=Sample_Gene_Freq/FILTER_RF_LOF_HIGHIMPACT_AF_1.0_NFE_ADJ,
"Sample_Gene_LOF_Freq_Ratio_GnomAD_NFE_0.005"=Sample_Gene_Freq/FILTER_RF_LOF_HIGHIMPACT_AF_0.005_NFE_ADJ,
"Ratio_Difference_NFE"=Sample_Gene_LOF_Freq_Ratio_GnomAD_NFE_0.005-Sample_Gene_LOF_Freq_Ratio_GnomAD_NFE)

Calculate Sample/GnomAD allele freq ratios

masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios2 <- mutate(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios, "Sample_Gene_LOF_AF_Ratio"=Sample_AF/GnomAD_v2.1_non_cancer_AF, 
"Sample_Gene_LOF_AF_Ratio_NFE"=Sample_AF/GnomAD_v2.1_non_cancer_AF_nfe)

Attach other GnomAD data for DNA repair genes analysis

masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3 <- mutate(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios2,Total_Case_Alleles=Total_Sample_Alleles) %>% 
  left_join(GnomAD_stats_LOF_VEP[,c(2,6,10,14:29)],by="Feature",copy=FALSE) 
masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios4 <- mutate(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3, MAX_AN=replace(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3$MAX_AN, is.na(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3$MAX_AN), max(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3$MAX_AN, na.rm=TRUE))) %>% 
  mutate(MAX_AN_NFE=replace(.$MAX_AN_NFE, is.na(.$MAX_AN_NFE), max(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3$MAX_AN_NFE, na.rm=TRUE)))

Post-filtering figures (ENST, excl. mutation +ve samples)

n_distinct(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3$Sample)
[1] 150
n_distinct(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3$Gene)
[1] 102
n_distinct(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3$HGVSc)
[1] 117

Divide into groups stratified by age (<60/>=60) and presence/absence of FHx, and output files.

masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios_ageUnder60 <- filter(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3,Reported.Age.Dx<60) %>%
  write_excel_csv(path="masterfile_eoc_altAF0.25_HIGH_ENSTcanonical_ageUnder60.csv",na=".",append=FALSE,col_names=TRUE)
  
masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios_ageOver60 <- filter(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3,Reported.Age.Dx>=60) %>% 
  write_excel_csv(path="masterfile_eoc_altAF0.25_HIGH_ENSTcanonical_ageOver60.csv",na=".",append=FALSE,col_names=TRUE)
  
masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios_FHx <- filter(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3,FHx%in%c("YES")) %>% 
  write_excel_csv(path="masterfile_eoc_altAF0.25_HIGH_ENSTcanonical_FHx.csv",na=".",append=FALSE,col_names=TRUE)
  
masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios_noFHx <- 
filter(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3,!FHx%in%c("YES")) %>% 
  write_excel_csv(path="masterfile_eoc_altAF0.25_HIGH_ENSTcanonical_noFHx.csv",na=".",append=FALSE,col_names=TRUE)

Identify ViP samples with and without low-frequency variants post-filtering (incl age/FHx distribution), and perform simple linear regression comparison for age vs presence of low-frequency variants

ViP_LowFreqVar_Samples <- select(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3,Sample) %>% distinct(.keep_all=FALSE)
ViP_noLowFreqVar_Samples <- filter(ViP_Discovery_Cohort,!Exome.ID%in%ViP_LowFreqVar_Samples$Sample)
ViP_noLowFreqVar_Path <- filter(ViP_OvCa_Path_Data,Sample%in%ViP_noLowFreqVar_Samples$Exome.ID)
ViP_LowFreqVar_Path <- filter(ViP_OvCa_Path_Data,Sample%in%ViP_LowFreqVar_Samples$Sample)
ViP_FHx <- select(masterfile_eoc4,Sample,FHx) %>% 
  distinct(.keep_all=FALSE)
FHx <- filter(ViP_FHx,FHx=="YES")
NoFHx <- filter(ViP_FHx,FHx=="NO")

FHx_LowFreqVar <- filter(FHx,Sample%in%ViP_LowFreqVar_Samples$Sample)
NoFHx_LowFreqVar <- filter(NoFHx,Sample%in%ViP_LowFreqVar_Samples$Sample)
FHx_noLowFreqVar <- filter(FHx,Sample%in%ViP_noLowFreqVar_Samples$Exome.ID)
NoFHxCa_noLowFreqVar <- filter(NoFHx,Sample%in%ViP_noLowFreqVar_Samples$Exome.ID) 

ViP_noLowFreqVar_Path %>% mutate(age_group = ifelse(Reported.Age.Dx <30,"<30",
                                               ifelse(Reported.Age.Dx < 40,"30-39",
                                                      ifelse(Reported.Age.Dx < 50,"40-49",
                                                             ifelse(Reported.Age.Dx < 60,"50-59",
                                                                    ifelse(Reported.Age.Dx < 70,"60-69",
                                                                           ifelse(Reported.Age.Dx < 80,"70-79",">80")))))))%>%
  group_by(age_group)%>%
  count()
ViP_LowFreqVar_Path %>% mutate(age_group = ifelse(Reported.Age.Dx <30,"<30",
                                               ifelse(Reported.Age.Dx < 40,"30-39",
                                                      ifelse(Reported.Age.Dx < 50,"40-49",
                                                             ifelse(Reported.Age.Dx < 60,"50-59",
                                                                    ifelse(Reported.Age.Dx < 70,"60-69",
                                                                           ifelse(Reported.Age.Dx < 80,"70-79",">80")))))))%>%
  group_by(age_group)%>%
  count()
Low_vs_noLowFreqVar <- bind_rows(ViP_LowFreqVar_Path,ViP_noLowFreqVar_Path,.id = "LowFreq_status")
Low_vs_noLowFreqVar$LowFreq_status <- as.factor(Low_vs_noLowFreqVar$LowFreq_status)
Age_lm <- lm(Reported.Age.Dx~LowFreq_status,Low_vs_noLowFreqVar)
summary(Age_lm)

Call:
lm(formula = Reported.Age.Dx ~ LowFreq_status, data = Low_vs_noLowFreqVar)

Residuals:
    Min      1Q  Median      3Q     Max 
-36.640  -7.386   0.614   7.614  28.614 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)      61.6400     0.9157  67.312   <2e-16 ***
LowFreq_status2  -2.2539     1.0899  -2.068   0.0392 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 11.22 on 508 degrees of freedom
Multiple R-squared:  0.008347,  Adjusted R-squared:  0.006395 
F-statistic: 4.276 on 1 and 508 DF,  p-value: 0.03916

Extract DNA repair gene variants from sample data by repair pathway, and combine into one table

DNArepair_other_list <- tibble("SYMBOL"=c("XRCC1","PARP1","PARP2","APEX1","FEN1","OGG1","UNG","SMUG1","MBD4","TDG","MUTYH","NTHL1","MPG","NEIL1","NEIL2","NEIL3","APEX2","PNKP","APLF","PARP3","MSH3","MSH4","MSH5","MLH3","PMS1","PMS2P3","EXO1","RFC1","RFC2","RFC3","RFC4","RFC5","PCNA","ERCC4","ERCC2","ERCC5","XPC","ERCC6","GTF2H2","ERCC3","XPA","RAD23B","POLE","POLD1","RAD23A","LIG3","CETN2","DDB1","DDB2","GTF2H1","GTF2H3","GTF2H4","GTF2H5","CDK7","CCNH","MNAT1","LIG1","ERCC8","UVSSA","XAB2","MMS19","ATM","RPA1","RPA2","RPA3","RPA4","RAD51","NBN","RAD50","CHEK2","MRE11A","RAD52","RAD51B","DMC1","XRCC2","XRCC3","RAD54L","RAD54B","SHFM1","RBBP8","SLX1A","SLX1B","GEN1","ATR","ERCC1","FANCA","FANCB","FANCC","FANCD2","FANCE","FANCF","FANCG","FANCI","FANCL","FANCM","PALB2","CHEK1","SLX4","FAN1","C1orf86","C19orf40","MUS81","EME1","XRCC6","XRCC5","PRKDC","LIG4","XRCC4","DCLRE1C","NHEJ1","MGMT","ALKBH2","ALKBH3","PAXIP1","BLM","KMT2C","CRIP1","CDK12","BAP1","BARD1","WRN","BUB1","CENPE","ZW10","TTK","KNTC1","AURKB","POLB","POLH","POLQ","TDP1","TDP2","NUDT1","DUT","RRM2B","POLG","REV3L","MAD2L2","REV1","POLI","POLK","POLL","POLM","POLN","TREX1","TREX2","APTX","SPO11","ENDOV","UBE2A","UBE2B","RAD18","SHPRH","HLTF","RNF168","SPRTN","RNF8","RNF4","UBE2V2","UBE2N","H2AFX","CHAF1A","SETMAR","RECQL4","MPLKIP","DCLRE1A","DCLRE1B","PRPF19","RECQL","RECQL5","HELQ","RDM1","NABP2","ATRIP","MDC1","RAD1","RAD9A","HUS1","RAD17","TP53","TP53BP1","TOPBP1","CLK2","PER1","MLH1","MSH2","MSH6","PMS2","TP53","RAD51C","RAD51D","BRIP1","BRCA1","BRCA2"))
                                                                                                           masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios_DNArepair_other <-                                  filter(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios3,SYMBOL%in%DNArepair_other_list$SYMBOL) %>% write_excel_csv(path="masterfile_eoc_altAF0.25_HIGH_ENSTcanonical_DNArepair_other.csv",na=".",append=FALSE,col_names=TRUE)

DNA repair gene filtering figures

n_distinct(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios_DNArepair_other$Sample)
[1] 5
n_distinct(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios_DNArepair_other$Gene)
[1] 4
n_distinct(masterfile_eoc_lowFreq_HIGH_ENSTcanonical_withGnomADstats_ratios_DNArepair_other$HGVSc)
[1] 5
LS0tCnRpdGxlOiAiVGhlc2lzIExvdy1GcmVxdWVuY3kgRE5BIFJlcGFpciBHZW5lcyBTb21hdGljIExvRiBWYXJpYW50cyBGaWx0ZXJpbmcgU2NyaXB0IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpBTEwgSU1QT1JURUQgRklMRVMgTVVTVCBCRSBJTiBUSEUgU0FNRSBESVJFQ1RPUlkgQVMgVEhJUyBTQ1JJUFQKCkxvYWQgdGlkeXZlcnNlIHBhY2thZ2UKYGBge3J9CnNldHdkKCJ+L09uZURyaXZlIC0gVGhlIFVuaXZlcnNpdHkgb2YgTWVsYm91cm5lL1IgZGF0YSIpCmxpYnJhcnkoInRpZHl2ZXJzZSIpCmBgYAoKSW1wb3J0IHJhdyB2Y2YgZGF0YSBmcm9tICJtYXN0ZXJmaWxlIiBhbmQgZXhjbHVkZSB2YXJpYW50cyB3aXRoIEdub21BRCBub24tY2FuY2VyIEFGID4gMApgYGB7cn0KbWFzdGVyZmlsZSA8LSByZWFkLmRlbGltKCJtYXN0ZXJmaWxlLnRzdiIsIGhlYWRlcj1UUlVFLCByb3cubmFtZXM9TlVMTCwgbmEuc3RyaW5ncyA9ICIuIiwgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoIlNhbXBsZSI9IlguU2FtcGxlIikgJT4lIAogIGZpbHRlcihHbm9tQURfdjIuMV9ub25fY2FuY2VyX0FGPT0wKQpgYGAKCkV4Y2x1ZGUgbm9uLWVwaXRoZWxpYWwsIHV0ZXJpbmUtb25seSBhbmQgQlJDQSArdmUgc2FtcGxlcwpgYGB7cn0KVmlQX0NvbXBsZXRlX0NvaG9ydCA8LSByZWFkLmRlbGltKCJWaVBfTG9GX0NvbXBsZXRlX0NvaG9ydC50eHQiLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpWaVBfQ29tcGxldGVfQ29ob3J0X2xpc3QgPC0gVmlQX0NvbXBsZXRlX0NvaG9ydFssMV0KCm1hc3RlcmZpbGVfZW9jIDwtIGZpbHRlcihtYXN0ZXJmaWxlLFNhbXBsZSVpbiVjKFZpUF9Db21wbGV0ZV9Db2hvcnRfbGlzdCkpCmBgYAoKQXBwZW5kIHBhdGllbnQgcGF0aCBkYXRhIGFuZCBmYW1pbHkgaGlzdG9yeSBpbmZvCmBgYHtyfQpWaVBfT3ZDYV9QYXRoX0RhdGEgPC0gcmVhZC5kZWxpbSgiVmlQX092Q2FfUGF0aF9EYXRhLnR4dCIsIGhlYWRlcj1UUlVFLCByb3cubmFtZXM9TlVMTCwgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoIlNhbXBsZSI9RXhvbWUuSUQpCk5vRkh4Q2EgPC0gcmVhZC5kZWxpbSgiTm9GSHhDYS50c3YiLCBoZWFkZXI9VFJVRSwgcm93Lm5hbWVzPU5VTEwsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpICU+JSAKICBzZWxlY3QoRXhvbWUuSUQsRkh4KSAlPiUgCiAgZHBseXI6OnJlbmFtZSgiU2FtcGxlIj1FeG9tZS5JRCkKbWFzdGVyZmlsZV9lb2MyIDwtIGxlZnRfam9pbihtYXN0ZXJmaWxlX2VvYyxWaVBfT3ZDYV9QYXRoX0RhdGEsYnk9IlNhbXBsZSIsY29weT1GQUxTRSkgJT4lIAogIGxlZnRfam9pbihOb0ZIeENhLGJ5PSJTYW1wbGUiLGNvcHk9RkFMU0UpICU+JSAKICBtdXRhdGVfYXQodmFycygiRkh4IiksZnVucyhyZXBsYWNlKC4sIGlzLm5hKC4pLCAiWUVTIikpKQpgYGAKCkV4Y2x1ZGUgb3RoZXIgbXV0YXRpb24gK3ZlIHNhbXBsZXMgKE1MSDEvTVNIMi9NU0g2L1BNUzIsIFRQNTMsIFJBRDUxQy9ELCBCUklQMSkKYGBge3J9ClZpUF9EaXNjb3ZlcnlfQ29ob3J0IDwtIHJlYWQuZGVsaW0oIlZpUF9Mb0ZfRGlzY292ZXJ5X0NvaG9ydC50eHQiLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpWaVBfRGlzY292ZXJ5X0NvaG9ydF9saXN0IDwtIFZpUF9EaXNjb3ZlcnlfQ29ob3J0WywxXQoKbWFzdGVyZmlsZV9lb2MzIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvYzIsU2FtcGxlJWluJWMoVmlQX0Rpc2NvdmVyeV9Db2hvcnRfbGlzdCkpCmBgYAoKQWRkIFNhbXBsZSBBRC9EUCBjb2x1bW4gdG8gY2FsY3VsYXRlIHJlYWQgZnJlcSBmb3IgdmFyaWFudHMgd2l0aCBtaXNzaW5nIFBNQ0ZSRVEgdmFsdWVzCmBgYHtyfQptYXN0ZXJmaWxlX2VvYzQgPC0gbXV0YXRlKG1hc3RlcmZpbGVfZW9jMywgQUQgPSBhcy5udW1lcmljKHNhcHBseShzdHJzcGxpdChTYW1wbGUuQUQsIiwiKSwgZnVuY3Rpb24oeCkgdGFpbCh4LDEpKSksIERQID0gYXMubnVtZXJpYyhTYW1wbGUuRFApLCBTYW1wbGUuRlJFUSA9IEFEL0RQKQoKVG90YWxfU2FtcGxlX0FsbGVsZXMgPC0gKG5fZGlzdGluY3QobWFzdGVyZmlsZV9lb2M0JFNhbXBsZSkqMikKYGBgCgpFeGNsdWRlIGxvdy1xdWFsaXR5IHZhcmlhbnRzLCBHbm9tQUQgUkYvSW5icmVlZGluZ0NvZWZmLWZsYWdnZWQgdmFyaWFudHMKYGBge3J9Cm1hc3RlcmZpbGVfZW9jX2xvd0ZyZXEgPC0gZmlsdGVyKG1hc3RlcmZpbGVfZW9jNCwgKFFVQUw+PTMwKSYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKElkZW50aWZpZWQhPSJGaWx0ZXJlZEluQWxsIikmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChTYW1wbGUuUE1DRFA+PTIwKSYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFNhbXBsZS5QTUNGUkVRPDAuMjUpJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoU2FtcGxlLkZSRVE8MC4yNSkpICU+JSAKICBmaWx0ZXIoU2FtcGxlLkZSRVE+PTAuMDEpICU+JSAKICBmaWx0ZXIoKCFzdHJfZGV0ZWN0KEdub21BRF92Mi4xX0ZJTFRFUl9leG9tZSwiSW5icmVlZGluZ0NvZWZmIikmCiAgICAgICAgICAgICFzdHJfZGV0ZWN0KEdub21BRF92Mi4xX0ZJTFRFUl9leG9tZSwiUkYiKSl8CiAgICAgICAgICAgaXMubmEoR25vbUFEX3YyLjFfRklMVEVSX2V4b21lKSkgJT4lCiAgZmlsdGVyKCghc3RyX2RldGVjdChHbm9tQURfdjIuMV9GSUxURVJfZ2Vub21lLCJJbmJyZWVkaW5nQ29lZmYiKSYKICAgICAgICAgICAgIXN0cl9kZXRlY3QoR25vbUFEX3YyLjFfRklMVEVSX2dlbm9tZSwiUkYiKSl8CiAgICAgICAgICAgaXMubmEoR25vbUFEX3YyLjFfRklMVEVSX2dlbm9tZSkpCmBgYAoKUmVtb3ZlIEhBUC1vbmx5IGluZGVsIHZhcmlhbnRzIHdpdGggUE1DRlJFUT09MApgYGB7cn0KbWFzdGVyZmlsZV9lb2NfbG93RnJlcV9IQVBfU05WIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19sb3dGcmVxLFNhbXBsZS5QTUNGUkVRPT0wKSAlPiUgCiAgZmlsdGVyKFZhcmlhbnRfVHlwZT09IlNOViIpCm1hc3RlcmZpbGVfZW9jX2xvd0ZyZXEyIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19sb3dGcmVxLFNhbXBsZS5QTUNGUkVRIT0wKSAlPiUgCiAgYmluZF9yb3dzKG1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSEFQX1NOViwuaWQ9TlVMTCkKYGBgCgpFeGNsdWRlIE1PREVSQVRFIGltcGFjdCB2YXJpYW50cwpgYGB7cn0KbWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19sb3dGcmVxMiwgSU1QQUNUPT0iSElHSCIpCmBgYAoKU2VwYXJhdGUgRW5zZW1ibCBjYW5vbmljYWwgYW5kIFJlZlNlcSBjYW5vbmljYWwgdmFyaWFudHMKYGBge3J9Cm1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0gsQ0FOT05JQ0FMPT0iWUVTIikgJT4lIAogIHdyaXRlX2V4Y2VsX2NzdihwYXRoPSJtYXN0ZXJmaWxlX2VvY19hbHRBRjAuMjVfSElHSF9FTlNUY2Fub25pY2FsLmNzdiIsbmE9Ii4iLGFwcGVuZD1GQUxTRSxjb2xfbmFtZXM9VFJVRSkKYGBgCgpTYW1wbGUgdmFyaWFudCBjb3VudHMgYW5kIEFGcwpgYGB7cn0KdmFyaWFudF9jb3VudHNfQUZzIDwtIGZ1bmN0aW9uKHZjZil7CnZhcmlhbnRzX2hldGVyb3p5Z291cyA8LSB2Y2YgJT4lIAogIHNlbGVjdChIR1ZTYyxTYW1wbGUuR1QpICU+JSAKICBncm91cF9ieShIR1ZTYyxTYW1wbGUuR1QpICU+JSAKICBzdW1tYXJpc2UobigpKSAlPiUgCiAgZmlsdGVyKChTYW1wbGUuR1QlaW4lYygiJzAvMSIsIicxLzAiKSkpICU+JSAKICBkcGx5cjo6cmVuYW1lKGFsbGVsZXMgPSAibigpIikgJT4lIAogIGdyb3VwX2J5KEhHVlNjKSAlPiUgCiAgc3VtbWFyaXNlKHN1bShhbGxlbGVzKSkKdmFyaWFudHNfaG9tb3p5Z291cyA8LSB2Y2YgJT4lIAogIHNlbGVjdChIR1ZTYyxTYW1wbGUuR1QpICU+JSAKICBncm91cF9ieShIR1ZTYyxTYW1wbGUuR1QpICU+JSAKICBzdW1tYXJpc2UobigpKSAlPiUgCiAgZmlsdGVyKChTYW1wbGUuR1QhPSInMC8xIikmKFNhbXBsZS5HVCE9IicxLzAiKSkgJT4lIAogIG11dGF0ZShhbGxlbGVzID0gYG4oKWAqMikgJT4lIAogIHNlbGVjdCgtYG4oKWApICU+JSAKICBncm91cF9ieShIR1ZTYykgJT4lIAogIHN1bW1hcmlzZShzdW0oYWxsZWxlcykpCnZhcmlhbnRzIDwtIGZ1bGxfam9pbih2YXJpYW50c19oZXRlcm96eWdvdXMsdmFyaWFudHNfaG9tb3p5Z291cyxieT0iSEdWU2MiLGNvcHk9RkFMU0Usc3VmZml4PWMoIi54IiwiLnkiKSkgJT4lCiAgbXV0YXRlX2FsbChmdW5zKHJlcGxhY2UoLiwgaXMubmEoLiksIDApKSkgJT4lIAogIG11dGF0ZShUb3RhbF9BbGxlbGVfQ291bnQ9YHN1bShhbGxlbGVzKS54YCtgc3VtKGFsbGVsZXMpLnlgKSAlPiUgCiAgbXV0YXRlKFNhbXBsZV9BRj1Ub3RhbF9BbGxlbGVfQ291bnQvVG90YWxfU2FtcGxlX0FsbGVsZXMpCnZjZiA8LSBsZWZ0X2pvaW4odmNmLCB2YXJpYW50c1ssYygxLDQ6NSldLGJ5PSJIR1ZTYyIsY29weT1GQUxTRSkKfQoKbWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfMiA8LSB2YXJpYW50X2NvdW50c19BRnMobWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWwpCmBgYAoKU2FtcGxlIGdlbmUgY291bnRzIGFuZCBmcmVxdWVuY2llcwpgYGB7cn0KZ2VuZV9jb3VudHNfQUYgPC0gZnVuY3Rpb24odmNmKXsKZ2VuZXNfb25lVmFyQWxsZWxlIDwtIHZjZiAlPiUgc2VsZWN0KFNZTUJPTCxTYW1wbGUuR1QpICU+JSAKICBzZWxlY3QoU1lNQk9MLFNhbXBsZS5HVCkgJT4lIAogIGdyb3VwX2J5KFNZTUJPTCxTYW1wbGUuR1QpICU+JSAKICBzdW1tYXJpc2UobigpKSAlPiUgCiAgZmlsdGVyKChTYW1wbGUuR1QlaW4lYygiJzAvMSIsIicxLzAiKSkpICU+JSAKICBkcGx5cjo6cmVuYW1lKGdlbmVfVmFyID0gIm4oKSIpICU+JSAKICBncm91cF9ieShTWU1CT0wpICU+JSAKICBzdW1tYXJpc2Uoc3VtKGdlbmVfVmFyKSkKZ2VuZXNfdHdvVmFyQWxsZWxlIDwtIHZjZiAlPiUgc2VsZWN0KFNZTUJPTCxTYW1wbGUuR1QpICU+JSAKICBzZWxlY3QoU1lNQk9MLFNhbXBsZS5HVCkgJT4lIAogIGdyb3VwX2J5KFNZTUJPTCxTYW1wbGUuR1QpICU+JSAKICBzdW1tYXJpc2UobigpKSAlPiUgCiAgZmlsdGVyKChTYW1wbGUuR1QhPSInMC8xIikmKFNhbXBsZS5HVCE9IicxLzAiKSkgJT4lIAogIG11dGF0ZShnZW5lX1ZhciA9IGBuKClgKjIpICU+JSAKICBzZWxlY3QoLWBuKClgKSAlPiUgCiAgZ3JvdXBfYnkoU1lNQk9MKSAlPiUgCiAgc3VtbWFyaXNlKHN1bShnZW5lX1ZhcikpCmdlbmVzIDwtIGZ1bGxfam9pbihnZW5lc19vbmVWYXJBbGxlbGUsZ2VuZXNfdHdvVmFyQWxsZWxlLGJ5PSJTWU1CT0wiLGNvcHk9RkFMU0Usc3VmZml4PWMoIi54IiwiLnkiKSkgJT4lIAogIG11dGF0ZV9hbGwoZnVucyhyZXBsYWNlKC4sIGlzLm5hKC4pLCAwKSkpICU+JSAKICBtdXRhdGUoVG90YWxfR2VuZV9Db3VudD1gc3VtKGdlbmVfVmFyKS54YCtgc3VtKGdlbmVfVmFyKS55YCkgJT4lIAogIG11dGF0ZShTYW1wbGVfR2VuZV9GcmVxPVRvdGFsX0dlbmVfQ291bnQvVG90YWxfU2FtcGxlX0FsbGVsZXMpCnZjZiA8LSBsZWZ0X2pvaW4odmNmLCBnZW5lc1ssYygxLDQ6NSldLGJ5PSJTWU1CT0wiLGNvcHk9RkFMU0UpCn0KCm1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsXzMgPC0gZ2VuZV9jb3VudHNfQUYobWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfMikKYGBgCgpBZGQgR25vbUFEIGdlbmUtbGV2ZWwgZGF0YQpgYGB7cn0KR25vbUFEX3N0YXRzX0xPRl9WRVAgPC0gcmVhZC5kZWxpbSgiR25vbUFEX3N0YXRzX0xPRl9WRVAudHN2IiwgaGVhZGVyPVRSVUUsIHJvdy5uYW1lcz1OVUxMLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQoKbWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfd2l0aEdub21BRHN0YXRzIDwtIGxlZnRfam9pbihtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF8zLCBHbm9tQURfc3RhdHNfTE9GX1ZFUFssYygyLDMwOjQxKV0sYnk9IkZlYXR1cmUiLGNvcHk9RkFMU0UpIAptYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHMyIDwtIG11dGF0ZV9hdChtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHMsdmFycyhzdGFydHNfd2l0aCgiRklMVEVSXyIpKSxmdW5zKHJlcGxhY2UoLiwgaXMubmEoLiksIDApKSkgJT4lIAogIG11dGF0ZV9pZihncmVwbCgicG9wbWF4JCIsIG5hbWVzKC4pKSxmdW5zKGlmZWxzZSguID09ICJOQSIsIDAsIGFzLm51bWVyaWMoLikpKSkgJT4lIAogIG11dGF0ZV9hdCh2YXJzKGVuZHNfd2l0aCgicG9wbWF4IikpLGZ1bnMocmVwbGFjZSguLCBpcy5uYSguKSwgMCkpKQpgYGAKCkNhbGN1bGF0ZSBTYW1wbGUvR25vbUFEIGdlbmUgZnJlcSByYXRpb3MgZm9yIHRvdGFsIGFuZCBORkUgR25vbUFEIGZpZ3VyZXMsIGluY2x1ZGluZyBhbmQgZXhjbHVkaW5nIHZhcmlhbnRzIHdpdGggQUYgPiAwLjAwNQpgYGB7cn0KbWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfd2l0aEdub21BRHN0YXRzX3JhdGlvcyA8LSAKICBtdXRhdGUobWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfd2l0aEdub21BRHN0YXRzMiwgIlNhbXBsZV9HZW5lX0xPRl9GcmVxX1JhdGlvX0dub21BRCI9U2FtcGxlX0dlbmVfRnJlcS9GSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUZfMS4wX0FESiwKIlNhbXBsZV9HZW5lX0xPRl9GcmVxX1JhdGlvX0dub21BRF8wLjAwNSI9U2FtcGxlX0dlbmVfRnJlcS9GSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUZfMC4wMDVfQURKLAoiUmF0aW9fRGlmZmVyZW5jZSI9U2FtcGxlX0dlbmVfTE9GX0ZyZXFfUmF0aW9fR25vbUFEXzAuMDA1LVNhbXBsZV9HZW5lX0xPRl9GcmVxX1JhdGlvX0dub21BRCwgCiJTYW1wbGVfR2VuZV9MT0ZfRnJlcV9SYXRpb19Hbm9tQURfTkZFIj1TYW1wbGVfR2VuZV9GcmVxL0ZJTFRFUl9SRl9MT0ZfSElHSElNUEFDVF9BRl8xLjBfTkZFX0FESiwKIlNhbXBsZV9HZW5lX0xPRl9GcmVxX1JhdGlvX0dub21BRF9ORkVfMC4wMDUiPVNhbXBsZV9HZW5lX0ZyZXEvRklMVEVSX1JGX0xPRl9ISUdISU1QQUNUX0FGXzAuMDA1X05GRV9BREosCiJSYXRpb19EaWZmZXJlbmNlX05GRSI9U2FtcGxlX0dlbmVfTE9GX0ZyZXFfUmF0aW9fR25vbUFEX05GRV8wLjAwNS1TYW1wbGVfR2VuZV9MT0ZfRnJlcV9SYXRpb19Hbm9tQURfTkZFKQpgYGAKCkNhbGN1bGF0ZSBTYW1wbGUvR25vbUFEIGFsbGVsZSBmcmVxIHJhdGlvcyAKYGBge3J9Cm1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsX3dpdGhHbm9tQURzdGF0c19yYXRpb3MyIDwtIG11dGF0ZShtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zLCAiU2FtcGxlX0dlbmVfTE9GX0FGX1JhdGlvIj1TYW1wbGVfQUYvR25vbUFEX3YyLjFfbm9uX2NhbmNlcl9BRiwgCiJTYW1wbGVfR2VuZV9MT0ZfQUZfUmF0aW9fTkZFIj1TYW1wbGVfQUYvR25vbUFEX3YyLjFfbm9uX2NhbmNlcl9BRl9uZmUpCmBgYAoKQXR0YWNoIG90aGVyIEdub21BRCBkYXRhIGZvciBETkEgcmVwYWlyIGdlbmVzIGFuYWx5c2lzCmBgYHtyfQptYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zMyA8LSBtdXRhdGUobWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfd2l0aEdub21BRHN0YXRzX3JhdGlvczIsVG90YWxfQ2FzZV9BbGxlbGVzPVRvdGFsX1NhbXBsZV9BbGxlbGVzKSAlPiUgCiAgbGVmdF9qb2luKEdub21BRF9zdGF0c19MT0ZfVkVQWyxjKDIsNiwxMCwxNDoyOSldLGJ5PSJGZWF0dXJlIixjb3B5PUZBTFNFKSAKbWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfd2l0aEdub21BRHN0YXRzX3JhdGlvczQgPC0gbXV0YXRlKG1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsX3dpdGhHbm9tQURzdGF0c19yYXRpb3MzLCBNQVhfQU49cmVwbGFjZShtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zMyRNQVhfQU4sIGlzLm5hKG1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsX3dpdGhHbm9tQURzdGF0c19yYXRpb3MzJE1BWF9BTiksIG1heChtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zMyRNQVhfQU4sIG5hLnJtPVRSVUUpKSkgJT4lIAogIG11dGF0ZShNQVhfQU5fTkZFPXJlcGxhY2UoLiRNQVhfQU5fTkZFLCBpcy5uYSguJE1BWF9BTl9ORkUpLCBtYXgobWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfd2l0aEdub21BRHN0YXRzX3JhdGlvczMkTUFYX0FOX05GRSwgbmEucm09VFJVRSkpKQpgYGAKClBvc3QtZmlsdGVyaW5nIGZpZ3VyZXMgKEVOU1QsIGV4Y2wuIG11dGF0aW9uICt2ZSBzYW1wbGVzKQpgYGB7cn0Kbl9kaXN0aW5jdChtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zMyRTYW1wbGUpCm5fZGlzdGluY3QobWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfd2l0aEdub21BRHN0YXRzX3JhdGlvczMkR2VuZSkKbl9kaXN0aW5jdChtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zMyRIR1ZTYykKYGBgCgpEaXZpZGUgaW50byBncm91cHMgc3RyYXRpZmllZCBieSBhZ2UgKDw2MC8+PTYwKSBhbmQgcHJlc2VuY2UvYWJzZW5jZSBvZiBGSHgsIGFuZCBvdXRwdXQgZmlsZXMuCmBgYHtyfQptYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2FnZVVuZGVyNjAgPC0gZmlsdGVyKG1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsX3dpdGhHbm9tQURzdGF0c19yYXRpb3MzLFJlcG9ydGVkLkFnZS5EeDw2MCkgJT4lCiAgd3JpdGVfZXhjZWxfY3N2KHBhdGg9Im1hc3RlcmZpbGVfZW9jX2FsdEFGMC4yNV9ISUdIX0VOU1RjYW5vbmljYWxfYWdlVW5kZXI2MC5jc3YiLG5hPSIuIixhcHBlbmQ9RkFMU0UsY29sX25hbWVzPVRSVUUpCiAgCm1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfYWdlT3ZlcjYwIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zMyxSZXBvcnRlZC5BZ2UuRHg+PTYwKSAlPiUgCiAgd3JpdGVfZXhjZWxfY3N2KHBhdGg9Im1hc3RlcmZpbGVfZW9jX2FsdEFGMC4yNV9ISUdIX0VOU1RjYW5vbmljYWxfYWdlT3ZlcjYwLmNzdiIsbmE9Ii4iLGFwcGVuZD1GQUxTRSxjb2xfbmFtZXM9VFJVRSkKICAKbWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfd2l0aEdub21BRHN0YXRzX3JhdGlvc19GSHggPC0gZmlsdGVyKG1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsX3dpdGhHbm9tQURzdGF0c19yYXRpb3MzLEZIeCVpbiVjKCJZRVMiKSkgJT4lIAogIHdyaXRlX2V4Y2VsX2NzdihwYXRoPSJtYXN0ZXJmaWxlX2VvY19hbHRBRjAuMjVfSElHSF9FTlNUY2Fub25pY2FsX0ZIeC5jc3YiLG5hPSIuIixhcHBlbmQ9RkFMU0UsY29sX25hbWVzPVRSVUUpCiAgCm1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsX3dpdGhHbm9tQURzdGF0c19yYXRpb3Nfbm9GSHggPC0gCmZpbHRlcihtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zMywhRkh4JWluJWMoIllFUyIpKSAlPiUgCiAgd3JpdGVfZXhjZWxfY3N2KHBhdGg9Im1hc3RlcmZpbGVfZW9jX2FsdEFGMC4yNV9ISUdIX0VOU1RjYW5vbmljYWxfbm9GSHguY3N2IixuYT0iLiIsYXBwZW5kPUZBTFNFLGNvbF9uYW1lcz1UUlVFKQpgYGAKCklkZW50aWZ5IFZpUCBzYW1wbGVzIHdpdGggYW5kIHdpdGhvdXQgbG93LWZyZXF1ZW5jeSB2YXJpYW50cyBwb3N0LWZpbHRlcmluZyAoaW5jbCBhZ2UvRkh4IGRpc3RyaWJ1dGlvbiksIGFuZCBwZXJmb3JtIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbiBjb21wYXJpc29uIGZvciBhZ2UgdnMgcHJlc2VuY2Ugb2YgbG93LWZyZXF1ZW5jeSB2YXJpYW50cwpgYGB7cn0KVmlQX0xvd0ZyZXFWYXJfU2FtcGxlcyA8LSBzZWxlY3QobWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfd2l0aEdub21BRHN0YXRzX3JhdGlvczMsU2FtcGxlKSAlPiUgZGlzdGluY3QoLmtlZXBfYWxsPUZBTFNFKQpWaVBfbm9Mb3dGcmVxVmFyX1NhbXBsZXMgPC0gZmlsdGVyKFZpUF9EaXNjb3ZlcnlfQ29ob3J0LCFFeG9tZS5JRCVpbiVWaVBfTG93RnJlcVZhcl9TYW1wbGVzJFNhbXBsZSkKVmlQX25vTG93RnJlcVZhcl9QYXRoIDwtIGZpbHRlcihWaVBfT3ZDYV9QYXRoX0RhdGEsU2FtcGxlJWluJVZpUF9ub0xvd0ZyZXFWYXJfU2FtcGxlcyRFeG9tZS5JRCkKVmlQX0xvd0ZyZXFWYXJfUGF0aCA8LSBmaWx0ZXIoVmlQX092Q2FfUGF0aF9EYXRhLFNhbXBsZSVpbiVWaVBfTG93RnJlcVZhcl9TYW1wbGVzJFNhbXBsZSkKVmlQX0ZIeCA8LSBzZWxlY3QobWFzdGVyZmlsZV9lb2M0LFNhbXBsZSxGSHgpICU+JSAKICBkaXN0aW5jdCgua2VlcF9hbGw9RkFMU0UpCkZIeCA8LSBmaWx0ZXIoVmlQX0ZIeCxGSHg9PSJZRVMiKQpOb0ZIeCA8LSBmaWx0ZXIoVmlQX0ZIeCxGSHg9PSJOTyIpCgpGSHhfTG93RnJlcVZhciA8LSBmaWx0ZXIoRkh4LFNhbXBsZSVpbiVWaVBfTG93RnJlcVZhcl9TYW1wbGVzJFNhbXBsZSkKTm9GSHhfTG93RnJlcVZhciA8LSBmaWx0ZXIoTm9GSHgsU2FtcGxlJWluJVZpUF9Mb3dGcmVxVmFyX1NhbXBsZXMkU2FtcGxlKQpGSHhfbm9Mb3dGcmVxVmFyIDwtIGZpbHRlcihGSHgsU2FtcGxlJWluJVZpUF9ub0xvd0ZyZXFWYXJfU2FtcGxlcyRFeG9tZS5JRCkKTm9GSHhDYV9ub0xvd0ZyZXFWYXIgPC0gZmlsdGVyKE5vRkh4LFNhbXBsZSVpbiVWaVBfbm9Mb3dGcmVxVmFyX1NhbXBsZXMkRXhvbWUuSUQpIAoKVmlQX25vTG93RnJlcVZhcl9QYXRoICU+JSBtdXRhdGUoYWdlX2dyb3VwID0gaWZlbHNlKFJlcG9ydGVkLkFnZS5EeCA8MzAsIjwzMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKFJlcG9ydGVkLkFnZS5EeCA8IDQwLCIzMC0zOSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShSZXBvcnRlZC5BZ2UuRHggPCA1MCwiNDAtNDkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKFJlcG9ydGVkLkFnZS5EeCA8IDYwLCI1MC01OSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKFJlcG9ydGVkLkFnZS5EeCA8IDcwLCI2MC02OSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShSZXBvcnRlZC5BZ2UuRHggPCA4MCwiNzAtNzkiLCI+ODAiKSkpKSkpKSU+JQogIGdyb3VwX2J5KGFnZV9ncm91cCklPiUKICBjb3VudCgpClZpUF9Mb3dGcmVxVmFyX1BhdGggJT4lIG11dGF0ZShhZ2VfZ3JvdXAgPSBpZmVsc2UoUmVwb3J0ZWQuQWdlLkR4IDwzMCwiPDMwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoUmVwb3J0ZWQuQWdlLkR4IDwgNDAsIjMwLTM5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKFJlcG9ydGVkLkFnZS5EeCA8IDUwLCI0MC00OSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoUmVwb3J0ZWQuQWdlLkR4IDwgNjAsIjUwLTU5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoUmVwb3J0ZWQuQWdlLkR4IDwgNzAsIjYwLTY5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKFJlcG9ydGVkLkFnZS5EeCA8IDgwLCI3MC03OSIsIj44MCIpKSkpKSkpJT4lCiAgZ3JvdXBfYnkoYWdlX2dyb3VwKSU+JQogIGNvdW50KCkKTG93X3ZzX25vTG93RnJlcVZhciA8LSBiaW5kX3Jvd3MoVmlQX0xvd0ZyZXFWYXJfUGF0aCxWaVBfbm9Mb3dGcmVxVmFyX1BhdGgsLmlkID0gIkxvd0ZyZXFfc3RhdHVzIikKTG93X3ZzX25vTG93RnJlcVZhciRMb3dGcmVxX3N0YXR1cyA8LSBhcy5mYWN0b3IoTG93X3ZzX25vTG93RnJlcVZhciRMb3dGcmVxX3N0YXR1cykKQWdlX2xtIDwtIGxtKFJlcG9ydGVkLkFnZS5EeH5Mb3dGcmVxX3N0YXR1cyxMb3dfdnNfbm9Mb3dGcmVxVmFyKQpzdW1tYXJ5KEFnZV9sbSkKYGBgCgpFeHRyYWN0IEROQSByZXBhaXIgZ2VuZSB2YXJpYW50cyBmcm9tIHNhbXBsZSBkYXRhIGJ5IHJlcGFpciBwYXRod2F5LCBhbmQgY29tYmluZSBpbnRvIG9uZSB0YWJsZQpgYGB7cn0KRE5BcmVwYWlyX290aGVyX2xpc3QgPC0gdGliYmxlKCJTWU1CT0wiPWMoIlhSQ0MxIiwiUEFSUDEiLCJQQVJQMiIsIkFQRVgxIiwiRkVOMSIsIk9HRzEiLCJVTkciLCJTTVVHMSIsIk1CRDQiLCJUREciLCJNVVRZSCIsIk5USEwxIiwiTVBHIiwiTkVJTDEiLCJORUlMMiIsIk5FSUwzIiwiQVBFWDIiLCJQTktQIiwiQVBMRiIsIlBBUlAzIiwiTVNIMyIsIk1TSDQiLCJNU0g1IiwiTUxIMyIsIlBNUzEiLCJQTVMyUDMiLCJFWE8xIiwiUkZDMSIsIlJGQzIiLCJSRkMzIiwiUkZDNCIsIlJGQzUiLCJQQ05BIiwiRVJDQzQiLCJFUkNDMiIsIkVSQ0M1IiwiWFBDIiwiRVJDQzYiLCJHVEYySDIiLCJFUkNDMyIsIlhQQSIsIlJBRDIzQiIsIlBPTEUiLCJQT0xEMSIsIlJBRDIzQSIsIkxJRzMiLCJDRVROMiIsIkREQjEiLCJEREIyIiwiR1RGMkgxIiwiR1RGMkgzIiwiR1RGMkg0IiwiR1RGMkg1IiwiQ0RLNyIsIkNDTkgiLCJNTkFUMSIsIkxJRzEiLCJFUkNDOCIsIlVWU1NBIiwiWEFCMiIsIk1NUzE5IiwiQVRNIiwiUlBBMSIsIlJQQTIiLCJSUEEzIiwiUlBBNCIsIlJBRDUxIiwiTkJOIiwiUkFENTAiLCJDSEVLMiIsIk1SRTExQSIsIlJBRDUyIiwiUkFENTFCIiwiRE1DMSIsIlhSQ0MyIiwiWFJDQzMiLCJSQUQ1NEwiLCJSQUQ1NEIiLCJTSEZNMSIsIlJCQlA4IiwiU0xYMUEiLCJTTFgxQiIsIkdFTjEiLCJBVFIiLCJFUkNDMSIsIkZBTkNBIiwiRkFOQ0IiLCJGQU5DQyIsIkZBTkNEMiIsIkZBTkNFIiwiRkFOQ0YiLCJGQU5DRyIsIkZBTkNJIiwiRkFOQ0wiLCJGQU5DTSIsIlBBTEIyIiwiQ0hFSzEiLCJTTFg0IiwiRkFOMSIsIkMxb3JmODYiLCJDMTlvcmY0MCIsIk1VUzgxIiwiRU1FMSIsIlhSQ0M2IiwiWFJDQzUiLCJQUktEQyIsIkxJRzQiLCJYUkNDNCIsIkRDTFJFMUMiLCJOSEVKMSIsIk1HTVQiLCJBTEtCSDIiLCJBTEtCSDMiLCJQQVhJUDEiLCJCTE0iLCJLTVQyQyIsIkNSSVAxIiwiQ0RLMTIiLCJCQVAxIiwiQkFSRDEiLCJXUk4iLCJCVUIxIiwiQ0VOUEUiLCJaVzEwIiwiVFRLIiwiS05UQzEiLCJBVVJLQiIsIlBPTEIiLCJQT0xIIiwiUE9MUSIsIlREUDEiLCJURFAyIiwiTlVEVDEiLCJEVVQiLCJSUk0yQiIsIlBPTEciLCJSRVYzTCIsIk1BRDJMMiIsIlJFVjEiLCJQT0xJIiwiUE9MSyIsIlBPTEwiLCJQT0xNIiwiUE9MTiIsIlRSRVgxIiwiVFJFWDIiLCJBUFRYIiwiU1BPMTEiLCJFTkRPViIsIlVCRTJBIiwiVUJFMkIiLCJSQUQxOCIsIlNIUFJIIiwiSExURiIsIlJORjE2OCIsIlNQUlROIiwiUk5GOCIsIlJORjQiLCJVQkUyVjIiLCJVQkUyTiIsIkgyQUZYIiwiQ0hBRjFBIiwiU0VUTUFSIiwiUkVDUUw0IiwiTVBMS0lQIiwiRENMUkUxQSIsIkRDTFJFMUIiLCJQUlBGMTkiLCJSRUNRTCIsIlJFQ1FMNSIsIkhFTFEiLCJSRE0xIiwiTkFCUDIiLCJBVFJJUCIsIk1EQzEiLCJSQUQxIiwiUkFEOUEiLCJIVVMxIiwiUkFEMTciLCJUUDUzIiwiVFA1M0JQMSIsIlRPUEJQMSIsIkNMSzIiLCJQRVIxIiwiTUxIMSIsIk1TSDIiLCJNU0g2IiwiUE1TMiIsIlRQNTMiLCJSQUQ1MUMiLCJSQUQ1MUQiLCJCUklQMSIsIkJSQ0ExIiwiQlJDQTIiKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zX0ROQXJlcGFpcl9vdGhlciA8LSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIobWFzdGVyZmlsZV9lb2NfbG93RnJlcV9ISUdIX0VOU1RjYW5vbmljYWxfd2l0aEdub21BRHN0YXRzX3JhdGlvczMsU1lNQk9MJWluJUROQXJlcGFpcl9vdGhlcl9saXN0JFNZTUJPTCkgJT4lIHdyaXRlX2V4Y2VsX2NzdihwYXRoPSJtYXN0ZXJmaWxlX2VvY19hbHRBRjAuMjVfSElHSF9FTlNUY2Fub25pY2FsX0ROQXJlcGFpcl9vdGhlci5jc3YiLG5hPSIuIixhcHBlbmQ9RkFMU0UsY29sX25hbWVzPVRSVUUpCmBgYAoKRE5BIHJlcGFpciBnZW5lIGZpbHRlcmluZyBmaWd1cmVzCmBgYHtyfQpuX2Rpc3RpbmN0KG1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfRE5BcmVwYWlyX290aGVyJFNhbXBsZSkKbl9kaXN0aW5jdChtYXN0ZXJmaWxlX2VvY19sb3dGcmVxX0hJR0hfRU5TVGNhbm9uaWNhbF93aXRoR25vbUFEc3RhdHNfcmF0aW9zX0ROQXJlcGFpcl9vdGhlciRHZW5lKQpuX2Rpc3RpbmN0KG1hc3RlcmZpbGVfZW9jX2xvd0ZyZXFfSElHSF9FTlNUY2Fub25pY2FsX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfRE5BcmVwYWlyX290aGVyJEhHVlNjKQpgYGAK