ALL IMPORTED FILES MUST BE IN THE SAME DIRECTORY AS THIS SCRIPT
Load tidyverse package
library("tidyverse")
Import raw vcf data from “masterfile” and exclude variants with GnomAD non-cancer AF > 0.005
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.005)
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_eoc_withPath_FHx <- 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")))
rm(ViP_OvCa_Path_Data,NoFHxCa)
Exclude low-grade tumour samples
masterfile_eoc2 <- filter(masterfile_eoc_withPath_FHx,(!Histopath.Type%in%c("Borderline tumour",
"Mucinous",
"Clear cell",
"Low-grade serous",
"Low-grade endometrioid",
"Serous (?low-grade/borderline)",
"Mixed Mullerian",
"Mixed EAOC")))
Exclude samples with/without family history of BrOvCa in 1st and/or 2nd degree relatives
masterfile_eoc_FHx <- filter(masterfile_eoc2,FHx%in%c("YES"))
masterfile_eoc_noFHx <- filter(masterfile_eoc2,!FHx%in%c("YES"))
Exclude low-quality variants and GnomAD RF/InbreedingCoeff-flagged variants
masterfile_eoc_FHx_goodQ <- filter(masterfile_eoc_FHx, (QUAL>=30)&
(Identified!="FilteredInAll")&
(Sample.PMCDP>=10)&
(Sample.PMCFREQ>=0.25)) %>%
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))
masterfile_eoc_noFHx_goodQ <- filter(masterfile_eoc_noFHx, (QUAL>=30)&
(Identified!="FilteredInAll")&
(Sample.PMCDP>=10)&
(Sample.PMCFREQ>=0.25)) %>%
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))
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_eoc_FHx_goodQ2 <- filter(masterfile_eoc_FHx_goodQ,Sample%in%c(ViP_Discovery_Cohort_list))
Total_Sample_Alleles_FHx <- (n_distinct(masterfile_eoc_FHx_goodQ2$Sample)*2)
masterfile_eoc_noFHx_goodQ2 <- filter(masterfile_eoc_noFHx_goodQ,Sample%in%c(ViP_Discovery_Cohort_list))
Total_Sample_Alleles_noFHx <- (n_distinct(masterfile_eoc_noFHx_goodQ2$Sample)*2)
Exclude MODERATE impact variants
masterfile_eoc_FHx_goodQ_HIGH <- filter(masterfile_eoc_FHx_goodQ, IMPACT=="HIGH")
masterfile_eoc_FHx_goodQ2_HIGH <- filter(masterfile_eoc_FHx_goodQ2, IMPACT=="HIGH")
masterfile_eoc_noFHx_goodQ_HIGH <- filter(masterfile_eoc_noFHx_goodQ, IMPACT=="HIGH")
masterfile_eoc_noFHx_goodQ2_HIGH <- filter(masterfile_eoc_noFHx_goodQ2, IMPACT=="HIGH")
Separate Ensembl canonical and RefSeq canonical variants
masterfile_eoc_FHx_goodQ_HIGH_ENSTcanonical <- filter(masterfile_eoc_FHx_goodQ_HIGH,CANONICAL=="YES")
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical <- filter(masterfile_eoc_FHx_goodQ2_HIGH,CANONICAL=="YES")
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical <- filter(masterfile_eoc_FHx_goodQ2_HIGH,Ensembl94_refseq_mrna!="is.na") %>%
filter(!Ensembl94_refseq_mrna_STATUS%in%c(".|.",
".|.|.",
"MODEL",
"INFERRED",
"PREDICTED",
"PROVISIONAL",
"WGS"))
masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical <- filter(masterfile_eoc_noFHx_goodQ_HIGH,CANONICAL=="YES")
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical <- filter(masterfile_eoc_noFHx_goodQ2_HIGH,CANONICAL=="YES")
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical <- filter(masterfile_eoc_noFHx_goodQ2_HIGH,Ensembl94_refseq_mrna!="is.na") %>%
filter(!Ensembl94_refseq_mrna_STATUS%in%c(".|.",
".|.|.",
"MODEL",
"INFERRED",
"PREDICTED",
"PROVISIONAL",
"WGS"))
Sample variant counts and AFs
variant_counts_AFs <- function(vcf,Total_Sample_Alleles){
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_FHx_goodQ_HIGH_ENSTcanonical_2 <- variant_counts_AFs(masterfile_eoc_FHx_goodQ_HIGH_ENSTcanonical,Total_Sample_Alleles_FHx)
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_2 <- variant_counts_AFs(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical,Total_Sample_Alleles_FHx)
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_2 <- variant_counts_AFs(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical,Total_Sample_Alleles_FHx)
masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical_2 <- variant_counts_AFs(masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical,Total_Sample_Alleles_noFHx)
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_2 <- variant_counts_AFs(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical,Total_Sample_Alleles_noFHx)
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_2 <- variant_counts_AFs(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical,Total_Sample_Alleles_noFHx)
Exclude variants with sample AF >0.01̛
masterfile_eoc_FHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01 <- filter(masterfile_eoc_FHx_goodQ_HIGH_ENSTcanonical_2,Sample_AF < 0.01)
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01 <- filter(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_2,Sample_AF < 0.01)
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01 <- filter(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_2,Sample_AF < 0.01)
masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01 <- filter(masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical_2,Sample_AF < 0.01)
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01 <- filter(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_2,Sample_AF < 0.01)
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01 <- filter(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_2,Sample_AF < 0.01)
Output list of genes and variants with sample AF >0.01
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_genesandvariants0.01 <- filter(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_2,Sample_AF > 0.01)
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_genesandvariants0.01[,c(2:6,25:54)] %>%
distinct(.keep_all = FALSE) %>%
write_excel_csv(path="masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_genesandvariants0.01.csv",na=".",append=FALSE,col_names=TRUE)
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_genesandvariants0.01 <- filter(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_2,Sample_AF > 0.01)
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_genesandvariants0.01[,c(2:6,25:54)] %>%
distinct(.keep_all = FALSE) %>%
write_excel_csv(path="masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_genesandvariants0.01.csv",na=".",append=FALSE,col_names=TRUE)
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_genesandvariants0.01 <- filter(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_2,Sample_AF > 0.01)
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_genesandvariants0.01[,c(2:6,25:54)] %>%
distinct(.keep_all = FALSE) %>%
write_excel_csv(path="masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_genesandvariants0.01.csv",na=".",append=FALSE,col_names=TRUE)
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_genesandvariants0.01 <- filter(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_2,Sample_AF > 0.01)
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_genesandvariants0.01[,c(2:6,25:54)] %>%
distinct(.keep_all = FALSE) %>%
write_excel_csv(path="masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_genesandvariants0.01.csv",na=".",append=FALSE,col_names=TRUE)
Sample gene counts and frequencies
gene_counts_AFs <- function(vcf,Total_Sample_Alleles){
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_FHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01_2 <- gene_counts_AFs(masterfile_eoc_FHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01,Total_Sample_Alleles_FHx)
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_2 <- gene_counts_AFs(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01,Total_Sample_Alleles_FHx)
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_2 <- gene_counts_AFs(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01,Total_Sample_Alleles_FHx)
masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01_2 <- gene_counts_AFs(masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01,Total_Sample_Alleles_noFHx)
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_2 <- gene_counts_AFs(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01,Total_Sample_Alleles_noFHx)
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_2 <- gene_counts_AFs(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01,Total_Sample_Alleles_noFHx)
Add GnomAD gene-level data
GnomAD_stats_LOF_VEP <- read.delim("GnomAD_stats_LOF_VEP.tsv", header=TRUE, row.names=NULL, stringsAsFactors=FALSE)
GnomADD <- function(vcf,GnomAD){
vcf <- left_join(vcf, GnomAD[,c(2,30:41)],by="Feature",copy=FALSE)
vcf <- mutate_at(vcf,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)))
}
masterfile_eoc_FHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats <- GnomADD(masterfile_eoc_FHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01_2,GnomAD_stats_LOF_VEP)
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats <- GnomADD(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_2,GnomAD_stats_LOF_VEP)
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats <- GnomADD(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_2,GnomAD_stats_LOF_VEP)
masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats <- GnomADD(masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01_2,GnomAD_stats_LOF_VEP)
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats <- GnomADD(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_2,GnomAD_stats_LOF_VEP)
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats <- GnomADD(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_2,GnomAD_stats_LOF_VEP)
Calculate Sample/GnomAD gene freq ratios for total and NFE GnomAD figures (including and excluding variants with AF > 0.005), as well as allele freq ratios
ratios <- function(vcf){
mutate(vcf,
"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,
"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)
}
masterfile_eoc_FHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios <-
ratios(masterfile_eoc_FHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats)
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios <-
ratios(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats)
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios <-
ratios(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats)
masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios <-
ratios(masterfile_eoc_noFHx_goodQ_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats)
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios <-
ratios(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats)
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios <-
ratios(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats)
Create data frames with Agilent SureSelect whole exome genes (all ENST, protein-coding only and non-protein-coding) for volcano plot
ensembl_biotypes <- read.delim("ensembl_biotypes.tsv", stringsAsFactors=FALSE) %>%
select(ensembl_transcript_id,transcript_biotype) %>%
dplyr::rename("Feature"="ensembl_transcript_id","BIOTYPE"="transcript_biotype")
GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_all <- read.delim("GnomAD.gene.stats.v2.RF.only.agilent.v6.only.tsv", header=TRUE, row.names=NULL, stringsAsFactors=FALSE) %>%
filter(CANONICAL=="YES") %>%
dplyr::rename("SYMBOL"="X.Symbol") %>%
dplyr::rename("Gene"="ENSG") %>%
left_join(ensembl_biotypes,by="Feature",copy=FALSE)
GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_protein_coding <- read.delim("GnomAD.gene.stats.v2.RF.only.agilent.v6.only.tsv", header=TRUE, row.names=NULL, stringsAsFactors=FALSE) %>%
filter(CANONICAL=="YES") %>%
dplyr::rename("SYMBOL"="X.Symbol") %>%
dplyr::rename("Gene"="ENSG") %>%
left_join(ensembl_biotypes,by="Feature",copy=FALSE) %>%
filter(BIOTYPE%in%c("protein_coding"))
GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_non_protein_coding <- read.delim("GnomAD.gene.stats.v2.RF.only.agilent.v6.only.tsv", header=TRUE, row.names=NULL, stringsAsFactors=FALSE) %>%
filter(CANONICAL=="YES") %>%
dplyr::rename("SYMBOL"="X.Symbol") %>%
dplyr::rename("Gene"="ENSG") %>%
left_join(ensembl_biotypes,by="Feature",copy=FALSE) %>%
filter(!BIOTYPE%in%c("protein_coding"))
allGenes_AgilentSSv6_list <- tibble("SYMBOL"=GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_all$SYMBOL,"Gene"=GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_all$Gene,"Feature"=GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_all$Feature) %>%
distinct(.keep_all=TRUE) %>%
arrange(SYMBOL)
allGenes_AgilentSSv6_list_protein_coding_only <- tibble("SYMBOL"=GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_protein_coding$SYMBOL,"Gene"=GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_protein_coding$Gene,"Feature"=GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_protein_coding$Feature) %>%
distinct(.keep_all=TRUE) %>%
arrange(SYMBOL)
allGenes_AgilentSSv6_list_non_protein_coding_only <- tibble("SYMBOL"=GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_non_protein_coding$SYMBOL,"Gene"=GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_non_protein_coding$Gene,"Feature"=GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_non_protein_coding$Feature) %>%
distinct(.keep_all=TRUE) %>%
arrange(SYMBOL)
allGenes_masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_list <- tibble("SYMBOL"=masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios$SYMBOL,"Gene"=masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios$Gene,"BIOTYPE"=masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios$BIOTYPE) %>%
distinct(.keep_all=TRUE) %>%
arrange(SYMBOL)
allGenes_masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_list <- tibble("SYMBOL"=masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios$SYMBOL,"Gene"=masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios$Gene,"BIOTYPE"=masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios$BIOTYPE) %>%
distinct(.keep_all=TRUE) %>%
filter(BIOTYPE%in%c("protein_coding")) %>%
arrange(SYMBOL)
allGenes_masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype2_list <- tibble("SYMBOL"=masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios$SYMBOL,"Gene"=masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios$Gene,"BIOTYPE"=masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios$BIOTYPE) %>%
distinct(.keep_all=TRUE) %>%
filter(!BIOTYPE%in%c("protein_coding")) %>%
arrange(SYMBOL)
volcano <- function(vcf,gene_list,GnomAD,Total_Sample_Alleles){
water <- vcf %>%
mutate(Total_Case_Alleles=Total_Sample_Alleles) %>%
select(SYMBOL,Gene,Total_Gene_Count,Total_Case_Alleles) %>%
distinct(SYMBOL,Gene,Total_Gene_Count,Total_Case_Alleles)
water2 <- bind_rows(water, anti_join(gene_list,water,by="Gene")) %>%
mutate_at(vars("Total_Gene_Count"),funs(replace(., is.na(.), 0))) %>%
mutate_at(vars("Total_Case_Alleles"),funs(replace(., is.na(.), Total_Sample_Alleles)))
water3 <- right_join(water2,GnomAD,by="Gene",copy=FALSE) %>%
select("SYMBOL.x","Gene","Total_Gene_Count","Total_Case_Alleles","FILTER_RF_LOF_HIGHIMPACT_AC_0.005","FILTER_RF_LOF_HIGHIMPACT_AC_0.005_NFE","MAX_AN","MAX_AN_NFE","FILTER_RF_LOF_HIGHIMPACT_AF_0.005_ADJ","FILTER_RF_LOF_HIGHIMPACT_AF_0.005_NFE_ADJ") %>%
dplyr::rename("SYMBOL"="SYMBOL.x") %>%
mutate(FILTER_RF_LOF_HIGHIMPACT_AC_0.005_ADJ=round((MAX_AN*FILTER_RF_LOF_HIGHIMPACT_AF_0.005_ADJ))) %>%
mutate(FILTER_RF_LOF_HIGHIMPACT_AC_0.005_NFE_ADJ=round((MAX_AN_NFE*FILTER_RF_LOF_HIGHIMPACT_AF_0.005_NFE_ADJ))) %>%
distinct(.keep_all=TRUE)
return(water3)
}
volcano_FHx_sampleAF0.01_allGenes <- volcano(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios,allGenes_AgilentSSv6_list,GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_all,Total_Sample_Alleles_FHx)
volcano_FHx_sampleAF0.01_biotype_allGenes <- volcano(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios,allGenes_AgilentSSv6_list_protein_coding_only,GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_protein_coding,Total_Sample_Alleles_FHx)
volcano_FHx_sampleAF0.01_biotype2_allGenes <- volcano(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios,allGenes_AgilentSSv6_list_non_protein_coding_only,GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_non_protein_coding,Total_Sample_Alleles_FHx)
volcano_noFHx_sampleAF0.01_allGenes <- volcano(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios,allGenes_AgilentSSv6_list,GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_all,Total_Sample_Alleles_noFHx)
volcano_noFHx_sampleAF0.01_biotype_allGenes <- volcano(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios,allGenes_AgilentSSv6_list_protein_coding_only,GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_protein_coding,Total_Sample_Alleles_noFHx)
volcano_noFHx_sampleAF0.01_biotype2_allGenes <- volcano(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios,allGenes_AgilentSSv6_list_non_protein_coding_only,GnomAD_stats_AgilentSSv6_LOF_VEP_ENSTcanonical_non_protein_coding,Total_Sample_Alleles_noFHx)
Calculate Fisher’s test values (Ensembl Canonical)
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults <- mutate(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios,Total_Case_Alleles=Total_Sample_Alleles_FHx) %>%
left_join(GnomAD_stats_LOF_VEP[,c(2,6,10,14:29)],by="Feature",copy=FALSE)
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2 <- mutate(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults, MAX_AN=replace(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN, is.na(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN), max(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN, na.rm=TRUE))) %>%
mutate(MAX_AN_NFE=replace(.$MAX_AN_NFE, is.na(.$MAX_AN_NFE), max(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN_NFE, na.rm=TRUE)))
fisherresults_ENST <- apply(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2[,c(222,230,244,245)],1,function(x) {fisher.test(rbind(x[1:2],c(x[3]-x[1],x[4]-x[2])))})
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005 = sapply(fisherresults_ENST,function(x) round(x$p.value,12))
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$OR_0.005 = sapply(fisherresults_ENST,function(x) round(x$estimate,4))
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$`95%CI_0.005` = sapply(fisherresults_ENST,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$BH_0.005 = p.adjust(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005,method = "BH")
fisherresults2_ENST <- apply(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2[,c(222,233,244,246)],1,function(x) {fisher.test(rbind(x[1:2],c(x[3]-x[1],x[4]-x[2])))})
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005_NFE = sapply(fisherresults2_ENST,function(x) round(x$p.value,12))
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$OR_0.005_NFE = sapply(fisherresults2_ENST,function(x) round(x$estimate,4))
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$`95%CI_0.005_NFE` = sapply(fisherresults2_ENST,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$BH_0.005_NFE = p.adjust(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005_NFE,method = "BH")
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults <- mutate(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios,Total_Case_Alleles=Total_Sample_Alleles_noFHx) %>%
left_join(GnomAD_stats_LOF_VEP[,c(2,6,10,14:29)],by="Feature",copy=FALSE)
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2 <- mutate(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults, MAX_AN=replace(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN, is.na(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN), max(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN, na.rm=TRUE))) %>%
mutate(MAX_AN_NFE=replace(.$MAX_AN_NFE, is.na(.$MAX_AN_NFE), max(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN_NFE, na.rm=TRUE)))
fisherresults_ENST <- apply(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2[,c(222,230,244,245)],1,function(x) {fisher.test(rbind(x[1:2],c(x[3]-x[1],x[4]-x[2])))})
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005 = sapply(fisherresults_ENST,function(x) round(x$p.value,12))
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$OR_0.005 = sapply(fisherresults_ENST,function(x) round(x$estimate,4))
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$`95%CI_0.005` = sapply(fisherresults_ENST,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$BH_0.005 = p.adjust(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005,method = "BH")
fisherresults2_ENST <- apply(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2[,c(222,233,244,246)],1,function(x) {fisher.test(rbind(x[1:2],c(x[3]-x[1],x[4]-x[2])))})
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005_NFE = sapply(fisherresults2_ENST,function(x) round(x$p.value,12))
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$OR_0.005_NFE = sapply(fisherresults2_ENST,function(x) round(x$estimate,4))
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$`95%CI_0.005_NFE` = sapply(fisherresults2_ENST,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$BH_0.005_NFE = p.adjust(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005_NFE,method = "BH")
Calculate Fisher’s test values (RefSeq Canonical)
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults <- mutate(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios,Total_Case_Alleles=Total_Sample_Alleles_FHx) %>%
left_join(GnomAD_stats_LOF_VEP[,c(2,6,10,14:29)],by="Feature",copy=FALSE)
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2 <- mutate(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults, MAX_AN=replace(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN, is.na(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN), max(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN, na.rm=TRUE))) %>%
mutate(MAX_AN_NFE=replace(.$MAX_AN_NFE, is.na(.$MAX_AN_NFE), max(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN_NFE, na.rm=TRUE)))
fisherresults_NM <- apply(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2[,c(222,230,244,245)],1,function(x) {fisher.test(rbind(x[1:2],c(x[3]-x[1],x[4]-x[2])))})
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005 = sapply(fisherresults_NM,function(x) round(x$p.value,12))
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$OR_0.005 = sapply(fisherresults_NM,function(x) round(x$estimate,4))
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$`95%CI_0.005` = sapply(fisherresults_NM,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$BH_0.005 = p.adjust(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005,method = "BH")
fisherresults2_NM <- apply(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2[,c(222,233,244,246)],1,function(x) {fisher.test(rbind(x[1:2],c(x[3]-x[1],x[4]-x[2])))})
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005_NFE = sapply(fisherresults2_NM,function(x) round(x$p.value,12))
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$OR_0.005_NFE = sapply(fisherresults2_NM,function(x) round(x$estimate,4))
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$`95%CI_0.005_NFE` = sapply(fisherresults2_NM,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$BH_0.005_NFE = p.adjust(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005_NFE,method = "BH")
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults <- mutate(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios,Total_Case_Alleles=Total_Sample_Alleles_noFHx) %>%
left_join(GnomAD_stats_LOF_VEP[,c(2,6,10,14:29)],by="Feature",copy=FALSE)
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2 <- mutate(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults, MAX_AN=replace(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN, is.na(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN), max(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN, na.rm=TRUE))) %>%
mutate(MAX_AN_NFE=replace(.$MAX_AN_NFE, is.na(.$MAX_AN_NFE), max(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults$MAX_AN_NFE, na.rm=TRUE)))
fisherresults_NM <- apply(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2[,c(222,230,244,245)],1,function(x) {fisher.test(rbind(x[1:2],c(x[3]-x[1],x[4]-x[2])))})
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005 = sapply(fisherresults_NM,function(x) round(x$p.value,12))
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$OR_0.005 = sapply(fisherresults_NM,function(x) round(x$estimate,4))
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$`95%CI_0.005` = sapply(fisherresults_NM,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$BH_0.005 = p.adjust(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005,method = "BH")
fisherresults2_NM <- apply(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2[,c(222,233,244,246)],1,function(x) {fisher.test(rbind(x[1:2],c(x[3]-x[1],x[4]-x[2])))})
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005_NFE = sapply(fisherresults2_NM,function(x) round(x$p.value,12))
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$OR_0.005_NFE = sapply(fisherresults2_NM,function(x) round(x$estimate,4))
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$`95%CI_0.005_NFE` = sapply(fisherresults2_NM,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$BH_0.005_NFE = p.adjust(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2$P_value_Fisher_0.005_NFE,method = "BH")
Calculate Fisher’s test values (volcano plot)
fisherresults_allGenes_volcano <- apply(volcano_FHx_sampleAF0.01_allGenes[,c(3,5,4,7)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_FHx_sampleAF0.01_allGenes$P_value_Fisher_0.005 = sapply(fisherresults_allGenes_volcano,function(x) round(x$p.value,15))
volcano_FHx_sampleAF0.01_allGenes$OR_0.005 = sapply(fisherresults_allGenes_volcano,function(x) round(x$estimate,15))
volcano_FHx_sampleAF0.01_allGenes$`95%CI_0.005` = sapply(fisherresults_allGenes_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_FHx_sampleAF0.01_allGenes$BH_0.005 = p.adjust(volcano_FHx_sampleAF0.01_allGenes$P_value_Fisher_0.005,method = "BH")
fisherresults_NFE_volcano <- apply(volcano_FHx_sampleAF0.01_allGenes[,c(3,6,4,8)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_FHx_sampleAF0.01_allGenes$P_value_Fisher_0.005_NFE = sapply(fisherresults_NFE_volcano,function(x) round(x$p.value,15))
volcano_FHx_sampleAF0.01_allGenes$OR_0.005_NFE = sapply(fisherresults_NFE_volcano,function(x) round(x$estimate,15))
volcano_FHx_sampleAF0.01_allGenes$`95%CI_0.005_NFE` = sapply(fisherresults_NFE_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_FHx_sampleAF0.01_allGenes$BH_0.005_NFE = p.adjust(volcano_FHx_sampleAF0.01_allGenes$P_value_Fisher_0.005_NFE,method = "BH")
fisherresults_biotype_allGenes_volcano <- apply(volcano_FHx_sampleAF0.01_biotype_allGenes[,c(3,5,4,7)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_FHx_sampleAF0.01_biotype_allGenes$P_value_Fisher_0.005 = sapply(fisherresults_biotype_allGenes_volcano,function(x) round(x$p.value,15))
volcano_FHx_sampleAF0.01_biotype_allGenes$OR_0.005 = sapply(fisherresults_biotype_allGenes_volcano,function(x) round(x$estimate,15))
volcano_FHx_sampleAF0.01_biotype_allGenes$`95%CI_0.005` = sapply(fisherresults_biotype_allGenes_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_FHx_sampleAF0.01_biotype_allGenes$BH_0.005 = p.adjust(volcano_FHx_sampleAF0.01_biotype_allGenes$P_value_Fisher_0.005,method = "BH")
fisherresults_biotype_NFE_volcano <- apply(volcano_FHx_sampleAF0.01_biotype_allGenes[,c(3,6,4,8)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_FHx_sampleAF0.01_biotype_allGenes$P_value_Fisher_0.005_NFE = sapply(fisherresults_biotype_NFE_volcano,function(x) round(x$p.value,15))
volcano_FHx_sampleAF0.01_biotype_allGenes$OR_0.005_NFE = sapply(fisherresults_biotype_NFE_volcano,function(x) round(x$estimate,15))
volcano_FHx_sampleAF0.01_biotype_allGenes$`95%CI_0.005_NFE` = sapply(fisherresults_biotype_NFE_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_FHx_sampleAF0.01_biotype_allGenes$BH_0.005_NFE = p.adjust(volcano_FHx_sampleAF0.01_biotype_allGenes$P_value_Fisher_0.005_NFE,method = "BH")
fisherresults_biotype2_allGenes_volcano <- apply(volcano_FHx_sampleAF0.01_biotype2_allGenes[,c(3,5,4,7)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_FHx_sampleAF0.01_biotype2_allGenes$P_value_Fisher_0.005 = sapply(fisherresults_biotype2_allGenes_volcano,function(x) round(x$p.value,15))
volcano_FHx_sampleAF0.01_biotype2_allGenes$OR_0.005 = sapply(fisherresults_biotype2_allGenes_volcano,function(x) round(x$estimate,15))
volcano_FHx_sampleAF0.01_biotype2_allGenes$`95%CI_0.005` = sapply(fisherresults_biotype2_allGenes_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_FHx_sampleAF0.01_biotype2_allGenes$BH_0.005 = p.adjust(volcano_FHx_sampleAF0.01_biotype2_allGenes$P_value_Fisher_0.005,method = "BH")
fisherresults_biotype2_NFE_volcano <- apply(volcano_FHx_sampleAF0.01_biotype2_allGenes[,c(3,6,4,8)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_FHx_sampleAF0.01_biotype2_allGenes$P_value_Fisher_0.005_NFE = sapply(fisherresults_biotype2_NFE_volcano,function(x) round(x$p.value,15))
volcano_FHx_sampleAF0.01_biotype2_allGenes$OR_0.005_NFE = sapply(fisherresults_biotype2_NFE_volcano,function(x) round(x$estimate,15))
volcano_FHx_sampleAF0.01_biotype2_allGenes$`95%CI_0.005_NFE` = sapply(fisherresults_biotype2_NFE_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_FHx_sampleAF0.01_biotype2_allGenes$BH_0.005_NFE = p.adjust(volcano_FHx_sampleAF0.01_biotype2_allGenes$P_value_Fisher_0.005_NFE,method = "BH")
fisherresults_allGenes_volcano <- apply(volcano_noFHx_sampleAF0.01_allGenes[,c(3,5,4,7)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_noFHx_sampleAF0.01_allGenes$P_value_Fisher_0.005 = sapply(fisherresults_allGenes_volcano,function(x) round(x$p.value,15))
volcano_noFHx_sampleAF0.01_allGenes$OR_0.005 = sapply(fisherresults_allGenes_volcano,function(x) round(x$estimate,15))
volcano_noFHx_sampleAF0.01_allGenes$`95%CI_0.005` = sapply(fisherresults_allGenes_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_noFHx_sampleAF0.01_allGenes$BH_0.005 = p.adjust(volcano_noFHx_sampleAF0.01_allGenes$P_value_Fisher_0.005,method = "BH")
fisherresults_NFE_volcano <- apply(volcano_noFHx_sampleAF0.01_allGenes[,c(3,6,4,8)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_noFHx_sampleAF0.01_allGenes$P_value_Fisher_0.005_NFE = sapply(fisherresults_NFE_volcano,function(x) round(x$p.value,15))
volcano_noFHx_sampleAF0.01_allGenes$OR_0.005_NFE = sapply(fisherresults_NFE_volcano,function(x) round(x$estimate,15))
volcano_noFHx_sampleAF0.01_allGenes$`95%CI_0.005_NFE` = sapply(fisherresults_NFE_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_noFHx_sampleAF0.01_allGenes$BH_0.005_NFE = p.adjust(volcano_noFHx_sampleAF0.01_allGenes$P_value_Fisher_0.005_NFE,method = "BH")
fisherresults_biotype_allGenes_volcano <- apply(volcano_noFHx_sampleAF0.01_biotype_allGenes[,c(3,5,4,7)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_noFHx_sampleAF0.01_biotype_allGenes$P_value_Fisher_0.005 = sapply(fisherresults_biotype_allGenes_volcano,function(x) round(x$p.value,15))
volcano_noFHx_sampleAF0.01_biotype_allGenes$OR_0.005 = sapply(fisherresults_biotype_allGenes_volcano,function(x) round(x$estimate,15))
volcano_noFHx_sampleAF0.01_biotype_allGenes$`95%CI_0.005` = sapply(fisherresults_biotype_allGenes_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_noFHx_sampleAF0.01_biotype_allGenes$BH_0.005 = p.adjust(volcano_noFHx_sampleAF0.01_biotype_allGenes$P_value_Fisher_0.005,method = "BH")
fisherresults_biotype_NFE_volcano <- apply(volcano_noFHx_sampleAF0.01_biotype_allGenes[,c(3,6,4,8)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_noFHx_sampleAF0.01_biotype_allGenes$P_value_Fisher_0.005_NFE = sapply(fisherresults_biotype_NFE_volcano,function(x) round(x$p.value,15))
volcano_noFHx_sampleAF0.01_biotype_allGenes$OR_0.005_NFE = sapply(fisherresults_biotype_NFE_volcano,function(x) round(x$estimate,15))
volcano_noFHx_sampleAF0.01_biotype_allGenes$`95%CI_0.005_NFE` = sapply(fisherresults_biotype_NFE_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_noFHx_sampleAF0.01_biotype_allGenes$BH_0.005_NFE = p.adjust(volcano_noFHx_sampleAF0.01_biotype_allGenes$P_value_Fisher_0.005_NFE,method = "BH")
fisherresults_biotype2_allGenes_volcano <- apply(volcano_noFHx_sampleAF0.01_biotype2_allGenes[,c(3,5,4,7)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_noFHx_sampleAF0.01_biotype2_allGenes$P_value_Fisher_0.005 = sapply(fisherresults_biotype2_allGenes_volcano,function(x) round(x$p.value,15))
volcano_noFHx_sampleAF0.01_biotype2_allGenes$OR_0.005 = sapply(fisherresults_biotype2_allGenes_volcano,function(x) round(x$estimate,15))
volcano_noFHx_sampleAF0.01_biotype2_allGenes$`95%CI_0.005` = sapply(fisherresults_biotype2_allGenes_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_noFHx_sampleAF0.01_biotype2_allGenes$BH_0.005 = p.adjust(volcano_noFHx_sampleAF0.01_biotype2_allGenes$P_value_Fisher_0.005,method = "BH")
fisherresults_biotype2_NFE_volcano <- apply(volcano_noFHx_sampleAF0.01_biotype2_allGenes[,c(3,6,4,8)],1,function(x) {fisher.test(rbind(x[1:2],c(abs(x[3]-x[1]),abs(x[4]-x[2]))))})
volcano_noFHx_sampleAF0.01_biotype2_allGenes$P_value_Fisher_0.005_NFE = sapply(fisherresults_biotype2_NFE_volcano,function(x) round(x$p.value,15))
volcano_noFHx_sampleAF0.01_biotype2_allGenes$OR_0.005_NFE = sapply(fisherresults_biotype2_NFE_volcano,function(x) round(x$estimate,15))
volcano_noFHx_sampleAF0.01_biotype2_allGenes$`95%CI_0.005_NFE` = sapply(fisherresults_biotype2_NFE_volcano,function(x) paste(round(x$conf.int[1:2],2),collapse="~"))
volcano_noFHx_sampleAF0.01_biotype2_allGenes$BH_0.005_NFE = p.adjust(volcano_noFHx_sampleAF0.01_biotype2_allGenes$P_value_Fisher_0.005_NFE,method = "BH")
Identify variants with filtering AF > maximum credible population AF in GnomAD for hereditary EOC (0.000181)
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults3 <- mutate(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2, FilteringAF_95_Exceeds_MaxCredPopAF=((GnomAD_v2.1_non_cancer_Filtering_AF_95)>0.000181)) %>%
mutate(FilteringAF_95_NFE_Exceeds_MaxCredPopAF=((GnomAD_v2.1_non_cancer_Filtering_AF_95_nfe)>0.000181))
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults3 <- mutate(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2, FilteringAF_95_Exceeds_MaxCredPopAF=((GnomAD_v2.1_non_cancer_Filtering_AF_95)>0.000181)) %>%
mutate(FilteringAF_95_NFE_Exceeds_MaxCredPopAF=((GnomAD_v2.1_non_cancer_Filtering_AF_95_nfe)>0.000181))
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults3 <- mutate(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2, FilteringAF_95_Exceeds_MaxCredPopAF=((GnomAD_v2.1_non_cancer_Filtering_AF_95)>0.000181)) %>%
mutate(FilteringAF_95_NFE_Exceeds_MaxCredPopAF=((GnomAD_v2.1_non_cancer_Filtering_AF_95_nfe)>0.000181))
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults3 <- mutate(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults2, FilteringAF_95_Exceeds_MaxCredPopAF=((GnomAD_v2.1_non_cancer_Filtering_AF_95)>0.000181)) %>%
mutate(FilteringAF_95_NFE_Exceeds_MaxCredPopAF=((GnomAD_v2.1_non_cancer_Filtering_AF_95_nfe)>0.000181))
Identify variants that PASS/FAIL the LOFTEE 50bp rule
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults4 <- mutate(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults3,LoF_50_BP_RULE = ifelse(grepl("50_BP_RULE:PASS", LoF_info), TRUE, ifelse(grepl("50_BP_RULE:FAIL", LoF_info), FALSE, NA)))
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults4 <- mutate(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults3,LoF_50_BP_RULE = ifelse(grepl("50_BP_RULE:PASS", LoF_info), TRUE, ifelse(grepl("50_BP_RULE:FAIL", LoF_info), FALSE, NA)))
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults4 <- mutate(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults3,LoF_50_BP_RULE = ifelse(grepl("50_BP_RULE:PASS", LoF_info), TRUE, ifelse(grepl("50_BP_RULE:FAIL", LoF_info), FALSE, NA)))
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults4 <- mutate(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults3,LoF_50_BP_RULE = ifelse(grepl("50_BP_RULE:PASS", LoF_info), TRUE, ifelse(grepl("50_BP_RULE:FAIL", LoF_info), FALSE, NA)))
Import NMD depleted gene list and annotate variants accordingly
NMD_depleted_gene_list <- read.csv("NMD_depleted_gene_list.csv", stringsAsFactors=FALSE) %>%
dplyr::rename("SYMBOL" = gene) %>%
dplyr::rename("Feature" = txnames) %>%
dplyr::rename("NMD_predictor_rank" = min.rank)
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5 <- left_join(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults4, NMD_depleted_gene_list[,c(2:3)],by="Feature",copy=FALSE)
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5 <- left_join(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults4, NMD_depleted_gene_list[,c(1:3)],by="SYMBOL",copy=FALSE)
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5 <- left_join(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults4, NMD_depleted_gene_list[,c(2:3)],by="Feature",copy=FALSE)
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5 <- left_join(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults4, NMD_depleted_gene_list[,c(1:3)],by="SYMBOL",copy=FALSE)
Remove redundant objects and output data
rm(list=(ls(pattern="^genes")))
rm(list=(ls(pattern="^variants")))
rm(list=(ls(pattern="^fisherresults")))
write_excel_csv(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,path="masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01.csv",na=".",append=FALSE,col_names=TRUE)
select(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,SYMBOL,Gene,P_value_Fisher_0.005_NFE) %>%
arrange(P_value_Fisher_0.005_NFE) %>%
unique() %>%
write_tsv(path="FHx_HIGH_ENSTcanonical_BH_p_values.tsv")
write_excel_csv(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,path="masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01.csv",na=".",append=FALSE,col_names=TRUE)
select(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,SYMBOL,Gene,P_value_Fisher_0.005_NFE) %>%
arrange(P_value_Fisher_0.005_NFE) %>%
unique() %>%
write_tsv(path="FHx_HIGH_NMcanonical_BH_p_values.tsv")
write_excel_csv(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,path="masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01.csv",na=".",append=FALSE,col_names=TRUE)
select(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,SYMBOL,Gene,P_value_Fisher_0.005_NFE) %>%
arrange(P_value_Fisher_0.005_NFE) %>%
unique() %>%
write_tsv(path="FHx_HIGH_ENSTcanonical_BH_p_values.tsv")
write_excel_csv(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,path="masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01.csv",na=".",append=FALSE,col_names=TRUE)
select(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,SYMBOL,Gene,P_value_Fisher_0.005_NFE) %>%
arrange(P_value_Fisher_0.005_NFE) %>%
unique() %>%
write_tsv(path="FHx_HIGH_NMcanonical_BH_p_values.tsv")
Calculate total LoF variants in sample vs total LoF variants in GnomAD non-cancer NFE and use for chi-squared test
oddsratio <- function (a, b = NULL, c = NULL, d = NULL, conf.level = 0.95,
p.calc.by.independence = TRUE)
{
if (is.matrix(a)) {
if ((dim(a)[1] != 2L) | (dim(a)[2] != 2L)) {
stop("Input matrix must be a 2x2 table.")
}
.a <- a[1, 1]
.b <- a[1, 2]
.c <- a[2, 1]
.d <- a[2, 2]
.data.name <- deparse(substitute(a))
}
else {
.a <- a
.b <- b
.c <- c
.d <- d
.data.name <- paste(deparse(substitute(a)), deparse(substitute(b)),
deparse(substitute(c)), deparse(substitute(d)))
}
.MAT <- matrix(c(.a, .b, M1 <- .a + .b, .c, .d, M0 <- .c +
.d, N1 <- .a + .c, N0 <- .b + .d, Total <- .a + .b +
.c + .d), 3, 3)
colnames(.MAT) <- c("Sample", "GnomAD", "Total") #("Disease", "Nondisease", "Total")
rownames(.MAT) <- c("LoF", "No LoF", "Total") #("Exposed", "Nonexposed", "Total")
class(.MAT) <- "table"
print(.MAT)
ESTIMATE <- (.a /.b)/(.c/.d)
norm.pp <- qnorm(1 - (1 - conf.level)/2)
if (p.calc.by.independence) {
p.v <- 2 * (1 - pnorm(abs((.a - N1 * M1/Total)/sqrt(N1 *
N0 * M1 * M0/Total/Total/(Total - 1)))))
}
else {
p.v <- 2 * (1 - pnorm(log(ifelse(ESTIMATE > 1, ESTIMATE,
1/ESTIMATE))/sqrt(1/.a + 1/.b + 1/.c + 1/.d)))
}
ORL <- ESTIMATE * exp(-norm.pp * sqrt(1/.a + 1/.b + 1/.c +
1/.d))
ORU <- ESTIMATE * exp(norm.pp * sqrt(1/.a + 1/.b + 1/.c +
1/.d)) %>% signif(digits=7)
CINT <- paste(signif(ORL,digits = 7),signif(ORU,digits = 7),sep="~")
attr(CINT, "conf.level") <- conf.level
RVAL <- list(p.value = p.v, conf.int = CINT, estimate = ESTIMATE,
method = "Odds ratio estimate and its significance probability",
data.name = .data.name)
class(RVAL) <- "htest"
return(RVAL)
}
a <- sum(volcano_FHx_sampleAF0.01_allGenes$Total_Gene_Count) %>% as.numeric()
b <- Total_Sample_Alleles_FHx*(nrow(allGenes_AgilentSSv6_list)) %>% as.numeric()
b1 <- b-a %>% as.numeric()
c <- sum(volcano_FHx_sampleAF0.01_allGenes$FILTER_RF_LOF_HIGHIMPACT_AC_0.005) %>% as.numeric()
d <- (max(volcano_FHx_sampleAF0.01_allGenes$MAX_AN))*nrow(allGenes_AgilentSSv6_list) %>% as.numeric()
d1 <- d-c %>% as.numeric()
e <- sum(volcano_FHx_sampleAF0.01_allGenes$FILTER_RF_LOF_HIGHIMPACT_AC_0.005_NFE) %>% as.numeric()
f <- (max(volcano_FHx_sampleAF0.01_allGenes$MAX_AN_NFE))*nrow(allGenes_AgilentSSv6_list) %>% as.numeric()
f1 <- f-e %>% as.numeric()
g <- sum(volcano_FHx_sampleAF0.01_biotype_allGenes$Total_Gene_Count) %>% as.numeric()
h <- Total_Sample_Alleles_FHx*(nrow(allGenes_AgilentSSv6_list_protein_coding_only)) %>% as.numeric()
h1 <- h-g %>% as.numeric()
i <- sum(volcano_FHx_sampleAF0.01_biotype_allGenes$FILTER_RF_LOF_HIGHIMPACT_AC_0.005) %>% as.numeric()
j <- (max(volcano_FHx_sampleAF0.01_biotype_allGenes$MAX_AN))*nrow(allGenes_AgilentSSv6_list_protein_coding_only) %>% as.numeric()
j1 <- j-i %>% as.numeric()
k <- sum(volcano_FHx_sampleAF0.01_biotype_allGenes$FILTER_RF_LOF_HIGHIMPACT_AC_0.005_NFE) %>% as.numeric()
l <- (max(volcano_FHx_sampleAF0.01_biotype_allGenes$MAX_AN_NFE))*nrow(allGenes_AgilentSSv6_list_protein_coding_only) %>% as.numeric()
l1 <- l-k %>% as.numeric()
chiX2_0.005_FHx <- matrix(c(a,b1,c,d1),nrow=2,byrow=TRUE)
chiX2_0.005_NFE_FHx <- matrix(c(a,b1,e,f1),nrow=2,byrow=TRUE)
chiX2_0.005_biotype_FHx <- matrix(c(g,h1,i,j1),nrow=2,byrow=TRUE)
chiX2_0.005_NFE_biotype_FHx <- matrix(c(g,h1,k,l1),nrow=2,byrow=TRUE)
m <- sum(volcano_noFHx_sampleAF0.01_allGenes$Total_Gene_Count) %>% as.numeric()
n <- Total_Sample_Alleles_noFHx*(nrow(allGenes_AgilentSSv6_list)) %>% as.numeric()
n1 <- n-m %>% as.numeric()
o <- sum(volcano_noFHx_sampleAF0.01_allGenes$FILTER_RF_LOF_HIGHIMPACT_AC_0.005) %>% as.numeric()
p <- (max(volcano_noFHx_sampleAF0.01_allGenes$MAX_AN))*nrow(allGenes_AgilentSSv6_list) %>% as.numeric()
p1 <- p-o %>% as.numeric()
q <- sum(volcano_noFHx_sampleAF0.01_allGenes$FILTER_RF_LOF_HIGHIMPACT_AC_0.005_NFE) %>% as.numeric()
r <- (max(volcano_noFHx_sampleAF0.01_allGenes$MAX_AN_NFE))*nrow(allGenes_AgilentSSv6_list) %>% as.numeric()
r1 <- r-q %>% as.numeric()
s <- sum(volcano_noFHx_sampleAF0.01_biotype_allGenes$Total_Gene_Count) %>% as.numeric()
t <- Total_Sample_Alleles_noFHx*(nrow(allGenes_AgilentSSv6_list_protein_coding_only)) %>% as.numeric()
t1 <- t-s %>% as.numeric()
u <- sum(volcano_noFHx_sampleAF0.01_biotype_allGenes$FILTER_RF_LOF_HIGHIMPACT_AC_0.005) %>% as.numeric()
v <- (max(volcano_noFHx_sampleAF0.01_biotype_allGenes$MAX_AN))*nrow(allGenes_AgilentSSv6_list_protein_coding_only) %>% as.numeric()
v1 <- v-u %>% as.numeric()
w <- sum(volcano_noFHx_sampleAF0.01_biotype_allGenes$FILTER_RF_LOF_HIGHIMPACT_AC_0.005_NFE) %>% as.numeric()
x <- (max(volcano_noFHx_sampleAF0.01_biotype_allGenes$MAX_AN_NFE))*nrow(allGenes_AgilentSSv6_list_protein_coding_only) %>% as.numeric()
x1 <- x-w %>% as.numeric()
chiX2_0.005_noFHx <- matrix(c(m,n1,o,p1),nrow=2,byrow=TRUE)
chiX2_0.005_NFE_noFHx <- matrix(c(m,n1,q,r1),nrow=2,byrow=TRUE)
chiX2_0.005_biotype_noFHx <- matrix(c(s,t1,u,v1),nrow=2,byrow=TRUE)
chiX2_0.005_NFE_biotype_noFHx <- matrix(c(s,t1,w,x1),nrow=2,byrow=TRUE)
chiX2_0.005_NFE_FHx_noFHx <- matrix(c(chiX2_0.005_NFE_FHx[1,],chiX2_0.005_NFE_noFHx[1,]),nrow=2,byrow=TRUE)
chiX2_0.005_NFE_biotype_FHx_noFHx <- matrix(c(chiX2_0.005_NFE_biotype_FHx[1,],chiX2_0.005_NFE_biotype_noFHx[1,]),nrow=2,byrow=TRUE)
setwd("~/OneDrive - The University of Melbourne/R data")
sink(file="masterfile_eoc_LOF_volcano_chiX2_results.txt",append=TRUE)
chisq.test(chiX2_0.005_FHx,correct=FALSE)
oddsratio(chiX2_0.005_FHx)
chisq.test(chiX2_0.005_NFE_FHx,correct=FALSE)
oddsratio(chiX2_0.005_NFE_FHx)
chisq.test(chiX2_0.005_biotype_FHx,correct=FALSE)
oddsratio(chiX2_0.005_biotype_FHx)
chisq.test(chiX2_0.005_NFE_biotype_FHx,correct=FALSE)
oddsratio(chiX2_0.005_NFE_biotype_FHx)
chisq.test(chiX2_0.005_noFHx,correct=FALSE)
oddsratio(chiX2_0.005_noFHx)
chisq.test(chiX2_0.005_NFE_noFHx,correct=FALSE)
oddsratio(chiX2_0.005_NFE_noFHx)
chisq.test(chiX2_0.005_biotype_noFHx,correct=FALSE)
oddsratio(chiX2_0.005_biotype_noFHx)
chisq.test(chiX2_0.005_NFE_biotype_noFHx,correct=FALSE)
oddsratio(chiX2_0.005_NFE_biotype_noFHx)
chisq.test(chiX2_0.005_NFE_FHx_noFHx,correct=FALSE)
chisq.test(chiX2_0.005_NFE_biotype_FHx_noFHx,correct=FALSE)
sink()
Remove variants with non-protein-coding biotypes
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype <- filter(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,BIOTYPE%in%c("protein_coding"))
masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_biotype <- filter(masterfile_eoc_FHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,BIOTYPE%in%c("protein_coding"))
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype <- filter(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,BIOTYPE%in%c("protein_coding"))
masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_biotype <- filter(masterfile_eoc_noFHx_goodQ2_HIGH_NMcanonical_sampleAF0.01_withGnomADstats_ratios_fisherresults5,BIOTYPE%in%c("protein_coding"))
Calculate number of retained protein-coding LoF variants per individual in FHx/noFHx cohorts, and output results.
masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson <- select(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype,Sample,CHROM,POS,REF,ALT,Sample.GT,SYMBOL,Gene,Feature,HGVSc)
samples_FHx <- masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson[,1] %>% unique()
samples_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson <- data.frame(Sample=factor(),No_of_Variants=double())
for(sample in samples_FHx){
sample_data <- filter(masterfile_eoc_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson,Sample%in%c(sample))
sample_variants <- variant_counts_AFs(sample_data,Total_Sample_Alleles_FHx)
no_of_variants <- sum(sample_variants$Total_Allele_Count)
samples_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson <- add_row(samples_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson,Sample=sample,No_of_Variants=no_of_variants)
}
write_tsv(samples_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson,path="samples_FHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson.tsv")
masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson <- select(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype,Sample,CHROM,POS,REF,ALT,Sample.GT,SYMBOL,Gene,Feature,HGVSc)
samples_noFHx <- masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson[,1] %>% unique()
samples_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson <- data.frame(Sample=factor(),No_of_Variants=double())
for(sample in samples_noFHx){
sample_data <- filter(masterfile_eoc_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson,Sample%in%c(sample))
sample_variants <- variant_counts_AFs(sample_data,Total_Sample_Alleles_noFHx)
no_of_variants <- sum(sample_variants$Total_Allele_Count)
samples_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson <- add_row(samples_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson,Sample=sample,No_of_Variants=no_of_variants)
}
write_tsv(samples_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson,path="samples_noFHx_goodQ2_HIGH_ENSTcanonical_sampleAF0.01_biotype_variantsPerPerson.tsv")
Output data for log p-value volcano plots
volcano_FHx_sampleAF0.01_allGenes2 <- mutate(volcano_FHx_sampleAF0.01_allGenes,"Log10_P-value_Fisher_0.05_NFE" = log10(P_value_Fisher_0.005_NFE)) %>%
arrange(desc(OR_0.005_NFE)) %>%
mutate("Plotted_Log10_P-value_Fisher_0.05_NFE"=
if_else (OR_0.005_NFE>=1, `Log10_P-value_Fisher_0.05_NFE`*-1, `Log10_P-value_Fisher_0.05_NFE`, missing=NULL)) %>%
arrange(desc(`Plotted_Log10_P-value_Fisher_0.05_NFE`),desc(OR_0.005_NFE)) %>%
write_excel_csv(path="volcano_FHx_sampleAF0.01_allGenes_v6.csv",na=".",append=FALSE,col_names=TRUE)
volcano_FHx_sampleAF0.01_biotype_allGenes2 <- mutate(volcano_FHx_sampleAF0.01_biotype_allGenes,"Log10_P-value_Fisher_0.05_NFE" = log10(P_value_Fisher_0.005_NFE)) %>%
arrange(desc(OR_0.005_NFE)) %>%
mutate("Plotted_Log10_P-value_Fisher_0.05_NFE"=
if_else (OR_0.005_NFE>=1, `Log10_P-value_Fisher_0.05_NFE`*-1, `Log10_P-value_Fisher_0.05_NFE`, missing=NULL)) %>%
arrange(desc(`Plotted_Log10_P-value_Fisher_0.05_NFE`),desc(OR_0.005_NFE)) %>%
write_excel_csv(path="volcano_FHx_sampleAF0.01_biotype_allGenes_v6.csv",na=".",append=FALSE,col_names=TRUE)
volcano_FHx_sampleAF0.01_biotype2_allGenes2 <- mutate(volcano_FHx_sampleAF0.01_biotype2_allGenes,"Log10_P-value_Fisher_0.05_NFE" = log10(P_value_Fisher_0.005_NFE)) %>%
arrange(desc(OR_0.005_NFE)) %>%
mutate("Plotted_Log10_P-value_Fisher_0.05_NFE"=
if_else (OR_0.005_NFE>=1, `Log10_P-value_Fisher_0.05_NFE`*-1, `Log10_P-value_Fisher_0.05_NFE`, missing=NULL)) %>%
arrange(desc(`Plotted_Log10_P-value_Fisher_0.05_NFE`),desc(OR_0.005_NFE)) %>%
write_excel_csv(path="volcano_FHx_sampleAF0.01_biotype2_allGenes_v6.csv",na=".",append=FALSE,col_names=TRUE)
volcano_noFHx_sampleAF0.01_allGenes2 <- mutate(volcano_noFHx_sampleAF0.01_allGenes,"Log10_P-value_Fisher_0.05_NFE" = log10(P_value_Fisher_0.005_NFE)) %>%
arrange(desc(OR_0.005_NFE)) %>%
mutate("Plotted_Log10_P-value_Fisher_0.05_NFE"=
if_else (OR_0.005_NFE>=1, `Log10_P-value_Fisher_0.05_NFE`*-1, `Log10_P-value_Fisher_0.05_NFE`, missing=NULL)) %>%
arrange(desc(`Plotted_Log10_P-value_Fisher_0.05_NFE`),desc(OR_0.005_NFE)) %>%
write_excel_csv(path="volcano_noFHx_sampleAF0.01_allGenes_v6.csv",na=".",append=FALSE,col_names=TRUE)
volcano_noFHx_sampleAF0.01_biotype_allGenes2 <- mutate(volcano_noFHx_sampleAF0.01_biotype_allGenes,"Log10_P-value_Fisher_0.05_NFE" = log10(P_value_Fisher_0.005_NFE)) %>%
arrange(desc(OR_0.005_NFE)) %>%
mutate("Plotted_Log10_P-value_Fisher_0.05_NFE"=
if_else (OR_0.005_NFE>=1, `Log10_P-value_Fisher_0.05_NFE`*-1, `Log10_P-value_Fisher_0.05_NFE`, missing=NULL)) %>%
arrange(desc(`Plotted_Log10_P-value_Fisher_0.05_NFE`),desc(OR_0.005_NFE)) %>%
write_excel_csv(path="volcano_noFHx_sampleAF0.01_biotype_allGenes_v6.csv",na=".",append=FALSE,col_names=TRUE)
volcano_noFHx_sampleAF0.01_biotype2_allGenes2 <- mutate(volcano_noFHx_sampleAF0.01_biotype2_allGenes,"Log10_P-value_Fisher_0.05_NFE" = log10(P_value_Fisher_0.005_NFE)) %>%
arrange(desc(OR_0.005_NFE)) %>%
mutate("Plotted_Log10_P-value_Fisher_0.05_NFE"=
if_else (OR_0.005_NFE>=1, `Log10_P-value_Fisher_0.05_NFE`*-1, `Log10_P-value_Fisher_0.05_NFE`, missing=NULL)) %>%
arrange(desc(`Plotted_Log10_P-value_Fisher_0.05_NFE`),desc(OR_0.005_NFE)) %>%
write_excel_csv(path="volcano_noFHx_sampleAF0.01_biotype2_allGenes_v6.csv",na=".",append=FALSE,col_names=TRUE)
LS0tCnRpdGxlOiAiVGhlc2lzIExvRiBWYXJpYW50cyBGaWx0ZXJpbmcgYW5kIEFuYWx5c2lzIGJ5IEZhbWlseSBIaXN0b3J5IFNjcmlwdCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKQUxMIElNUE9SVEVEIEZJTEVTIE1VU1QgQkUgSU4gVEhFIFNBTUUgRElSRUNUT1JZIEFTIFRISVMgU0NSSVBUCgpMb2FkIHRpZHl2ZXJzZSBwYWNrYWdlCmBgYHtyfQpsaWJyYXJ5KCJ0aWR5dmVyc2UiKQpgYGAKCkltcG9ydCByYXcgdmNmIGRhdGEgZnJvbSAibWFzdGVyZmlsZSIgYW5kIGV4Y2x1ZGUgdmFyaWFudHMgd2l0aCBHbm9tQUQgbm9uLWNhbmNlciBBRiA+IDAuMDA1CmBgYHtyfQptYXN0ZXJmaWxlIDwtIHJlYWQuZGVsaW0oIm1hc3RlcmZpbGUudHN2IiwgaGVhZGVyPVRSVUUsIHJvdy5uYW1lcz1OVUxMLCBuYS5zdHJpbmdzID0gIi4iLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKSAlPiUgCiAgZHBseXI6OnJlbmFtZSgiU2FtcGxlIj0iWC5TYW1wbGUiKSAlPiUgCiAgZmlsdGVyKEdub21BRF92Mi4xX25vbl9jYW5jZXJfQUY8PTAuMDA1KQpgYGAKCkV4Y2x1ZGUgbm9uLWVwaXRoZWxpYWwsIHV0ZXJpbmUtb25seSBhbmQgQlJDQSArdmUgc2FtcGxlcwpgYGB7cn0KVmlQX0NvbXBsZXRlX0NvaG9ydCA8LSByZWFkLmRlbGltKCJWaVBfTG9GX0NvbXBsZXRlX0NvaG9ydC50eHQiLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQpWaVBfQ29tcGxldGVfQ29ob3J0X2xpc3QgPC0gVmlQX0NvbXBsZXRlX0NvaG9ydFssMV0KCm1hc3RlcmZpbGVfZW9jIDwtIGZpbHRlcihtYXN0ZXJmaWxlLFNhbXBsZSVpbiVjKFZpUF9Db21wbGV0ZV9Db2hvcnRfbGlzdCkpCmBgYAoKQXBwZW5kIHBhdGllbnQgcGF0aCBkYXRhIGFuZCBmYW1pbHkgaGlzdG9yeSBpbmZvCmBgYHtyfQpWaVBfT3ZDYV9QYXRoX0RhdGEgPC0gcmVhZC5kZWxpbSgiVmlQX092Q2FfUGF0aF9EYXRhLnR4dCIsIGhlYWRlcj1UUlVFLCByb3cubmFtZXM9TlVMTCwgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoIlNhbXBsZSI9RXhvbWUuSUQpCk5vRkh4Q2EgPC0gcmVhZC5kZWxpbSgiTm9GSHhDYS50c3YiLCBoZWFkZXI9VFJVRSwgcm93Lm5hbWVzPU5VTEwsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpICU+JSAKICBzZWxlY3QoRXhvbWUuSUQsRkh4KSAlPiUgCiAgZHBseXI6OnJlbmFtZSgiU2FtcGxlIj1FeG9tZS5JRCkKbWFzdGVyZmlsZV9lb2Nfd2l0aFBhdGhfRkh4IDwtIGxlZnRfam9pbihtYXN0ZXJmaWxlX2VvYyxWaVBfT3ZDYV9QYXRoX0RhdGEsYnk9IlNhbXBsZSIsY29weT1GQUxTRSkgJT4lIAogIGxlZnRfam9pbihOb0ZIeENhLGJ5PSJTYW1wbGUiLGNvcHk9RkFMU0UpICU+JSAKICBtdXRhdGVfYXQodmFycygiRkh4IiksZnVucyhyZXBsYWNlKC4sIGlzLm5hKC4pLCAiWUVTIikpKQpybShWaVBfT3ZDYV9QYXRoX0RhdGEsTm9GSHhDYSkKYGBgCgpFeGNsdWRlIGxvdy1ncmFkZSB0dW1vdXIgc2FtcGxlcwpgYGB7cn0KbWFzdGVyZmlsZV9lb2MyIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY193aXRoUGF0aF9GSHgsKCFIaXN0b3BhdGguVHlwZSVpbiVjKCJCb3JkZXJsaW5lIHR1bW91ciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTXVjaW5vdXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNsZWFyIGNlbGwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxvdy1ncmFkZSBzZXJvdXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxvdy1ncmFkZSBlbmRvbWV0cmlvaWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNlcm91cyAoP2xvdy1ncmFkZS9ib3JkZXJsaW5lKSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWl4ZWQgTXVsbGVyaWFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNaXhlZCBFQU9DIikpKQpgYGAKCkV4Y2x1ZGUgc2FtcGxlcyB3aXRoL3dpdGhvdXQgZmFtaWx5IGhpc3Rvcnkgb2YgQnJPdkNhIGluIDFzdCBhbmQvb3IgMm5kIGRlZ3JlZSByZWxhdGl2ZXMKYGBge3J9Cm1hc3RlcmZpbGVfZW9jX0ZIeCA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2MyLEZIeCVpbiVjKCJZRVMiKSkKCm1hc3RlcmZpbGVfZW9jX25vRkh4IDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvYzIsIUZIeCVpbiVjKCJZRVMiKSkKYGBgCgpFeGNsdWRlIGxvdy1xdWFsaXR5IHZhcmlhbnRzIGFuZCBHbm9tQUQgUkYvSW5icmVlZGluZ0NvZWZmLWZsYWdnZWQgdmFyaWFudHMKYGBge3J9Cm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUSA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2NfRkh4LCAoUVVBTD49MzApJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoSWRlbnRpZmllZCE9IkZpbHRlcmVkSW5BbGwiKSYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFNhbXBsZS5QTUNEUD49MTApJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoU2FtcGxlLlBNQ0ZSRVE+PTAuMjUpKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcigoIXN0cl9kZXRlY3QoR25vbUFEX3YyLjFfRklMVEVSX2V4b21lLCJJbmJyZWVkaW5nQ29lZmYiKSYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFzdHJfZGV0ZWN0KEdub21BRF92Mi4xX0ZJTFRFUl9leG9tZSwiUkYiKSl8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEdub21BRF92Mi4xX0ZJTFRFUl9leG9tZSkpICU+JSAKICBmaWx0ZXIoKCFzdHJfZGV0ZWN0KEdub21BRF92Mi4xX0ZJTFRFUl9nZW5vbWUsIkluYnJlZWRpbmdDb2VmZiIpJgogICAgICAgICAgICAhc3RyX2RldGVjdChHbm9tQURfdjIuMV9GSUxURVJfZ2Vub21lLCJSRiIpKXwKICAgICAgICAgICBpcy5uYShHbm9tQURfdjIuMV9GSUxURVJfZ2Vub21lKSkKCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19ub0ZIeCwgKFFVQUw+PTMwKSYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKElkZW50aWZpZWQhPSJGaWx0ZXJlZEluQWxsIikmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChTYW1wbGUuUE1DRFA+PTEwKSYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKFNhbXBsZS5QTUNGUkVRPj0wLjI1KSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoKCFzdHJfZGV0ZWN0KEdub21BRF92Mi4xX0ZJTFRFUl9leG9tZSwiSW5icmVlZGluZ0NvZWZmIikmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhc3RyX2RldGVjdChHbm9tQURfdjIuMV9GSUxURVJfZXhvbWUsIlJGIikpfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShHbm9tQURfdjIuMV9GSUxURVJfZXhvbWUpKSAlPiUgCiAgZmlsdGVyKCghc3RyX2RldGVjdChHbm9tQURfdjIuMV9GSUxURVJfZ2Vub21lLCJJbmJyZWVkaW5nQ29lZmYiKSYKICAgICAgICAgICAgIXN0cl9kZXRlY3QoR25vbUFEX3YyLjFfRklMVEVSX2dlbm9tZSwiUkYiKSl8CiAgICAgICAgICAgaXMubmEoR25vbUFEX3YyLjFfRklMVEVSX2dlbm9tZSkpCmBgYAoKRXhjbHVkZSBvdGhlciBtdXRhdGlvbiArdmUgc2FtcGxlcyAoTUxIMS9NU0gyL01TSDYvUE1TMiwgVFA1MywgUkFENTFDL0QsIEJSSVAxKQpgYGB7cn0KVmlQX0Rpc2NvdmVyeV9Db2hvcnQgPC0gcmVhZC5kZWxpbSgiVmlQX0xvRl9EaXNjb3ZlcnlfQ29ob3J0LnR4dCIsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpClZpUF9EaXNjb3ZlcnlfQ29ob3J0X2xpc3QgPC0gVmlQX0Rpc2NvdmVyeV9Db2hvcnRbLDFdCgptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEsU2FtcGxlJWluJWMoVmlQX0Rpc2NvdmVyeV9Db2hvcnRfbGlzdCkpClRvdGFsX1NhbXBsZV9BbGxlbGVzX0ZIeCA8LSAobl9kaXN0aW5jdChtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyJFNhbXBsZSkqMikKCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMiA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEsU2FtcGxlJWluJWMoVmlQX0Rpc2NvdmVyeV9Db2hvcnRfbGlzdCkpClRvdGFsX1NhbXBsZV9BbGxlbGVzX25vRkh4IDwtIChuX2Rpc3RpbmN0KG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMiRTYW1wbGUpKjIpCmBgYAoKRXhjbHVkZSBNT0RFUkFURSBpbXBhY3QgdmFyaWFudHMKYGBge3J9Cm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUV9ISUdIIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEsIElNUEFDVD09IkhJR0giKQoKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyLCBJTVBBQ1Q9PSJISUdIIikKCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRX0hJR0ggPC0gZmlsdGVyKG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRLCBJTVBBQ1Q9PSJISUdIIikKCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTIsIElNUEFDVD09IkhJR0giKQpgYGAKClNlcGFyYXRlIEVuc2VtYmwgY2Fub25pY2FsIGFuZCBSZWZTZXEgY2Fub25pY2FsIHZhcmlhbnRzCmBgYHtyfQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFFfSElHSF9FTlNUY2Fub25pY2FsIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFFfSElHSCxDQU5PTklDQUw9PSJZRVMiKSAKCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0gsQ0FOT05JQ0FMPT0iWUVTIikgCgptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWwgPC0gZmlsdGVyKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSCxFbnNlbWJsOTRfcmVmc2VxX21ybmEhPSJpcy5uYSIpICU+JSAKICBmaWx0ZXIoIUVuc2VtYmw5NF9yZWZzZXFfbXJuYV9TVEFUVVMlaW4lYygiLnwuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLnwufC4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNT0RFTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIklORkVSUkVEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUFJFRElDVEVEIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUFJPVklTSU9OQUwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXR1MiKSkKCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRX0hJR0hfRU5TVGNhbm9uaWNhbCA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFFfSElHSCxDQU5PTklDQUw9PSJZRVMiKSAKCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWwgPC0gZmlsdGVyKG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdILENBTk9OSUNBTD09IllFUyIpIAoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWwgPC0gZmlsdGVyKG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdILEVuc2VtYmw5NF9yZWZzZXFfbXJuYSE9ImlzLm5hIikgJT4lIAogIGZpbHRlcighRW5zZW1ibDk0X3JlZnNlcV9tcm5hX1NUQVRVUyVpbiVjKCIufC4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIufC58LiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1PREVMIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSU5GRVJSRUQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQUkVESUNURUQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQUk9WSVNJT05BTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldHUyIpKQpgYGAKClNhbXBsZSB2YXJpYW50IGNvdW50cyBhbmQgQUZzCmBgYHtyfQp2YXJpYW50X2NvdW50c19BRnMgPC0gZnVuY3Rpb24odmNmLFRvdGFsX1NhbXBsZV9BbGxlbGVzKXsKdmFyaWFudHNfaGV0ZXJvenlnb3VzIDwtIHZjZiAlPiUgCiAgc2VsZWN0KEhHVlNjLFNhbXBsZS5HVCkgJT4lIAogIGdyb3VwX2J5KEhHVlNjLFNhbXBsZS5HVCkgJT4lIAogIHN1bW1hcmlzZShuKCkpICU+JSAKICBmaWx0ZXIoKFNhbXBsZS5HVCVpbiVjKCInMC8xIiwiJzEvMCIpKSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoYWxsZWxlcyA9ICJuKCkiKSAlPiUgCiAgZ3JvdXBfYnkoSEdWU2MpICU+JSAKICBzdW1tYXJpc2Uoc3VtKGFsbGVsZXMpKQp2YXJpYW50c19ob21venlnb3VzIDwtIHZjZiAlPiUgCiAgc2VsZWN0KEhHVlNjLFNhbXBsZS5HVCkgJT4lIAogIGdyb3VwX2J5KEhHVlNjLFNhbXBsZS5HVCkgJT4lIAogIHN1bW1hcmlzZShuKCkpICU+JSAKICBmaWx0ZXIoKFNhbXBsZS5HVCE9IicwLzEiKSYoU2FtcGxlLkdUIT0iJzEvMCIpKSAlPiUgCiAgbXV0YXRlKGFsbGVsZXMgPSBgbigpYCoyKSAlPiUgCiAgc2VsZWN0KC1gbigpYCkgJT4lIAogIGdyb3VwX2J5KEhHVlNjKSAlPiUgCiAgc3VtbWFyaXNlKHN1bShhbGxlbGVzKSkKdmFyaWFudHMgPC0gZnVsbF9qb2luKHZhcmlhbnRzX2hldGVyb3p5Z291cyx2YXJpYW50c19ob21venlnb3VzLGJ5PSJIR1ZTYyIsY29weT1GQUxTRSxzdWZmaXg9YygiLngiLCIueSIpKSAlPiUKICBtdXRhdGVfYWxsKGZ1bnMocmVwbGFjZSguLCBpcy5uYSguKSwgMCkpKSAlPiUgCiAgbXV0YXRlKFRvdGFsX0FsbGVsZV9Db3VudD1gc3VtKGFsbGVsZXMpLnhgK2BzdW0oYWxsZWxlcykueWApICU+JSAKICBtdXRhdGUoU2FtcGxlX0FGPVRvdGFsX0FsbGVsZV9Db3VudC9Ub3RhbF9TYW1wbGVfQWxsZWxlcykKdmNmIDwtIGxlZnRfam9pbih2Y2YsIHZhcmlhbnRzWyxjKDEsNDo1KV0sYnk9IkhHVlNjIixjb3B5PUZBTFNFKQp9CgptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFFfSElHSF9FTlNUY2Fub25pY2FsXzIgPC0gdmFyaWFudF9jb3VudHNfQUZzKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUV9ISUdIX0VOU1RjYW5vbmljYWwsVG90YWxfU2FtcGxlX0FsbGVsZXNfRkh4KQoKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfMiA8LSB2YXJpYW50X2NvdW50c19BRnMobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWwsVG90YWxfU2FtcGxlX0FsbGVsZXNfRkh4KQoKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsXzIgPC0gdmFyaWFudF9jb3VudHNfQUZzKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbCxUb3RhbF9TYW1wbGVfQWxsZWxlc19GSHgpCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUV9ISUdIX0VOU1RjYW5vbmljYWxfMiA8LSB2YXJpYW50X2NvdW50c19BRnMobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFFfSElHSF9FTlNUY2Fub25pY2FsLFRvdGFsX1NhbXBsZV9BbGxlbGVzX25vRkh4KQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF8yIDwtIHZhcmlhbnRfY291bnRzX0FGcyhtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsLFRvdGFsX1NhbXBsZV9BbGxlbGVzX25vRkh4KQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfMiA8LSB2YXJpYW50X2NvdW50c19BRnMobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWwsVG90YWxfU2FtcGxlX0FsbGVsZXNfbm9GSHgpCmBgYAoKRXhjbHVkZSB2YXJpYW50cyB3aXRoIHNhbXBsZSBBRiA+MC4wMcybCmBgYHtyfQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFFfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMSA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRX0hJR0hfRU5TVGNhbm9uaWNhbF8yLFNhbXBsZV9BRiA8IDAuMDEpCgptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDEgPC0gZmlsdGVyKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsXzIsU2FtcGxlX0FGIDwgMC4wMSkKCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDEgPC0gZmlsdGVyKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF8yLFNhbXBsZV9BRiA8IDAuMDEpCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUV9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUV9ISUdIX0VOU1RjYW5vbmljYWxfMixTYW1wbGVfQUYgPCAwLjAxKQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDEgPC0gZmlsdGVyKG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfMixTYW1wbGVfQUYgPCAwLjAxKQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF8yLFNhbXBsZV9BRiA8IDAuMDEpCmBgYAoKT3V0cHV0IGxpc3Qgb2YgZ2VuZXMgYW5kIHZhcmlhbnRzIHdpdGggc2FtcGxlIEFGID4wLjAxCmBgYHtyfQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9nZW5lc2FuZHZhcmlhbnRzMC4wMSA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfMixTYW1wbGVfQUYgPiAwLjAxKQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9nZW5lc2FuZHZhcmlhbnRzMC4wMVssYygyOjYsMjU6NTQpXSAlPiUgCiAgZGlzdGluY3QoLmtlZXBfYWxsID0gRkFMU0UpICU+JSAKICB3cml0ZV9leGNlbF9jc3YocGF0aD0ibWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfZ2VuZXNhbmR2YXJpYW50czAuMDEuY3N2IixuYT0iLiIsYXBwZW5kPUZBTFNFLGNvbF9uYW1lcz1UUlVFKQoKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX2dlbmVzYW5kdmFyaWFudHMwLjAxIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfMixTYW1wbGVfQUYgPiAwLjAxKQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfZ2VuZXNhbmR2YXJpYW50czAuMDFbLGMoMjo2LDI1OjU0KV0gJT4lIAogIGRpc3RpbmN0KC5rZWVwX2FsbCA9IEZBTFNFKSAlPiUgCiAgd3JpdGVfZXhjZWxfY3N2KHBhdGg9Im1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9nZW5lc2FuZHZhcmlhbnRzMC4wMS5jc3YiLG5hPSIuIixhcHBlbmQ9RkFMU0UsY29sX25hbWVzPVRSVUUpCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX2dlbmVzYW5kdmFyaWFudHMwLjAxIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsXzIsU2FtcGxlX0FGID4gMC4wMSkKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9nZW5lc2FuZHZhcmlhbnRzMC4wMVssYygyOjYsMjU6NTQpXSAlPiUgCiAgZGlzdGluY3QoLmtlZXBfYWxsID0gRkFMU0UpICU+JSAKICB3cml0ZV9leGNlbF9jc3YocGF0aD0ibWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9nZW5lc2FuZHZhcmlhbnRzMC4wMS5jc3YiLG5hPSIuIixhcHBlbmQ9RkFMU0UsY29sX25hbWVzPVRSVUUpCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9nZW5lc2FuZHZhcmlhbnRzMC4wMSA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfMixTYW1wbGVfQUYgPiAwLjAxKQptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9nZW5lc2FuZHZhcmlhbnRzMC4wMVssYygyOjYsMjU6NTQpXSAlPiUgCiAgZGlzdGluY3QoLmtlZXBfYWxsID0gRkFMU0UpICU+JSAKICB3cml0ZV9leGNlbF9jc3YocGF0aD0ibWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfZ2VuZXNhbmR2YXJpYW50czAuMDEuY3N2IixuYT0iLiIsYXBwZW5kPUZBTFNFLGNvbF9uYW1lcz1UUlVFKQpgYGAKClNhbXBsZSBnZW5lIGNvdW50cyBhbmQgZnJlcXVlbmNpZXMKYGBge3J9CmdlbmVfY291bnRzX0FGcyA8LSBmdW5jdGlvbih2Y2YsVG90YWxfU2FtcGxlX0FsbGVsZXMpewpnZW5lc19vbmVWYXJBbGxlbGUgPC0gdmNmICU+JSBzZWxlY3QoU1lNQk9MLFNhbXBsZS5HVCkgJT4lIAogIHNlbGVjdChTWU1CT0wsU2FtcGxlLkdUKSAlPiUgCiAgZ3JvdXBfYnkoU1lNQk9MLFNhbXBsZS5HVCkgJT4lIAogIHN1bW1hcmlzZShuKCkpICU+JSAKICBmaWx0ZXIoKFNhbXBsZS5HVCVpbiVjKCInMC8xIiwiJzEvMCIpKSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoZ2VuZV9WYXIgPSAibigpIikgJT4lIAogIGdyb3VwX2J5KFNZTUJPTCkgJT4lIAogIHN1bW1hcmlzZShzdW0oZ2VuZV9WYXIpKQpnZW5lc190d29WYXJBbGxlbGUgPC0gdmNmICU+JSBzZWxlY3QoU1lNQk9MLFNhbXBsZS5HVCkgJT4lIAogIHNlbGVjdChTWU1CT0wsU2FtcGxlLkdUKSAlPiUgCiAgZ3JvdXBfYnkoU1lNQk9MLFNhbXBsZS5HVCkgJT4lIAogIHN1bW1hcmlzZShuKCkpICU+JSAKICBmaWx0ZXIoKFNhbXBsZS5HVCE9IicwLzEiKSYoU2FtcGxlLkdUIT0iJzEvMCIpKSAlPiUgCiAgbXV0YXRlKGdlbmVfVmFyID0gYG4oKWAqMikgJT4lIAogIHNlbGVjdCgtYG4oKWApICU+JSAKICBncm91cF9ieShTWU1CT0wpICU+JSAKICBzdW1tYXJpc2Uoc3VtKGdlbmVfVmFyKSkKZ2VuZXMgPC0gZnVsbF9qb2luKGdlbmVzX29uZVZhckFsbGVsZSxnZW5lc190d29WYXJBbGxlbGUsYnk9IlNZTUJPTCIsY29weT1GQUxTRSxzdWZmaXg9YygiLngiLCIueSIpKSAlPiUgCiAgbXV0YXRlX2FsbChmdW5zKHJlcGxhY2UoLiwgaXMubmEoLiksIDApKSkgJT4lIAogIG11dGF0ZShUb3RhbF9HZW5lX0NvdW50PWBzdW0oZ2VuZV9WYXIpLnhgK2BzdW0oZ2VuZV9WYXIpLnlgKSAlPiUgCiAgbXV0YXRlKFNhbXBsZV9HZW5lX0ZyZXE9VG90YWxfR2VuZV9Db3VudC9Ub3RhbF9TYW1wbGVfQWxsZWxlcykKdmNmIDwtIGxlZnRfam9pbih2Y2YsIGdlbmVzWyxjKDEsNDo1KV0sYnk9IlNZTUJPTCIsY29weT1GQUxTRSkKfQoKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfMiA8LSBnZW5lX2NvdW50c19BRnMobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDEsVG90YWxfU2FtcGxlX0FsbGVsZXNfRkh4KQoKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxXzIgPC0gZ2VuZV9jb3VudHNfQUZzKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMSxUb3RhbF9TYW1wbGVfQWxsZWxlc19GSHgpCgptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxXzIgPC0gZ2VuZV9jb3VudHNfQUZzKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDEsVG90YWxfU2FtcGxlX0FsbGVsZXNfRkh4KQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFFfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV8yIDwtIGdlbmVfY291bnRzX0FGcyhtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUV9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxLFRvdGFsX1NhbXBsZV9BbGxlbGVzX25vRkh4KQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfMiA8LSBnZW5lX2NvdW50c19BRnMobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDEsVG90YWxfU2FtcGxlX0FsbGVsZXNfbm9GSHgpCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfMiA8LSBnZW5lX2NvdW50c19BRnMobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxLFRvdGFsX1NhbXBsZV9BbGxlbGVzX25vRkh4KQpgYGAKCkFkZCBHbm9tQUQgZ2VuZS1sZXZlbCBkYXRhCmBgYHtyfQpHbm9tQURfc3RhdHNfTE9GX1ZFUCA8LSByZWFkLmRlbGltKCJHbm9tQURfc3RhdHNfTE9GX1ZFUC50c3YiLCBoZWFkZXI9VFJVRSwgcm93Lm5hbWVzPU5VTEwsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpHbm9tQUREIDwtIGZ1bmN0aW9uKHZjZixHbm9tQUQpewogIHZjZiA8LSBsZWZ0X2pvaW4odmNmLCBHbm9tQURbLGMoMiwzMDo0MSldLGJ5PSJGZWF0dXJlIixjb3B5PUZBTFNFKSAKICB2Y2YgPC0gbXV0YXRlX2F0KHZjZix2YXJzKHN0YXJ0c193aXRoKCJGSUxURVJfIikpLGZ1bnMocmVwbGFjZSguLCBpcy5uYSguKSwgMCkpKSAlPiUKICBtdXRhdGVfaWYoZ3JlcGwoInBvcG1heCQiLCBuYW1lcyguKSksZnVucyhpZmVsc2UoLiA9PSAiTkEiLCAwLCBhcy5udW1lcmljKC4pKSkpICU+JSAKICBtdXRhdGVfYXQodmFycyhlbmRzX3dpdGgoInBvcG1heCIpKSxmdW5zKHJlcGxhY2UoLiwgaXMubmEoLiksIDApKSkKfQoKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzIDwtIEdub21BREQobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfMixHbm9tQURfc3RhdHNfTE9GX1ZFUCkKCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHMgPC0gR25vbUFERChtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfMixHbm9tQURfc3RhdHNfTE9GX1ZFUCkKCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzIDwtIEdub21BREQobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV8yLEdub21BRF9zdGF0c19MT0ZfVkVQKQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFFfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHMgPC0gR25vbUFERChtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUV9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxXzIsR25vbUFEX3N0YXRzX0xPRl9WRVApCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHMgPC0gR25vbUFERChtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV8yLEdub21BRF9zdGF0c19MT0ZfVkVQKQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0cyA8LSBHbm9tQUREKG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV8yLEdub21BRF9zdGF0c19MT0ZfVkVQKQpgYGAKCkNhbGN1bGF0ZSBTYW1wbGUvR25vbUFEIGdlbmUgZnJlcSByYXRpb3MgZm9yIHRvdGFsIGFuZCBORkUgR25vbUFEIGZpZ3VyZXMgKGluY2x1ZGluZyBhbmQgZXhjbHVkaW5nIHZhcmlhbnRzIHdpdGggQUYgPiAwLjAwNSksIGFzIHdlbGwgYXMgYWxsZWxlIGZyZXEgcmF0aW9zCmBgYHtyfQpyYXRpb3MgPC0gZnVuY3Rpb24odmNmKXsKICBtdXRhdGUodmNmLCAKICAgICAgICAgIlNhbXBsZV9HZW5lX0xPRl9GcmVxX1JhdGlvX0dub21BRCI9U2FtcGxlX0dlbmVfRnJlcS9GSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUZfMS4wX0FESiwKICAgICAgICAgIlNhbXBsZV9HZW5lX0xPRl9GcmVxX1JhdGlvX0dub21BRF8wLjAwNSI9U2FtcGxlX0dlbmVfRnJlcS9GSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUZfMC4wMDVfQURKLAogICAgICAgICAiUmF0aW9fRGlmZmVyZW5jZSI9U2FtcGxlX0dlbmVfTE9GX0ZyZXFfUmF0aW9fR25vbUFEXzAuMDA1LVNhbXBsZV9HZW5lX0xPRl9GcmVxX1JhdGlvX0dub21BRCwgCiAgICAgICAgICJTYW1wbGVfR2VuZV9MT0ZfRnJlcV9SYXRpb19Hbm9tQURfTkZFIj1TYW1wbGVfR2VuZV9GcmVxL0ZJTFRFUl9SRl9MT0ZfSElHSElNUEFDVF9BRl8xLjBfTkZFX0FESiwKICAgICAgICAgIlNhbXBsZV9HZW5lX0xPRl9GcmVxX1JhdGlvX0dub21BRF9ORkVfMC4wMDUiPVNhbXBsZV9HZW5lX0ZyZXEvRklMVEVSX1JGX0xPRl9ISUdISU1QQUNUX0FGXzAuMDA1X05GRV9BREosCiAgICAgICAgICJSYXRpb19EaWZmZXJlbmNlX05GRSI9U2FtcGxlX0dlbmVfTE9GX0ZyZXFfUmF0aW9fR25vbUFEX05GRV8wLjAwNS1TYW1wbGVfR2VuZV9MT0ZfRnJlcV9SYXRpb19Hbm9tQURfTkZFLAogICAgICAgICAiU2FtcGxlX0dlbmVfTE9GX0FGX1JhdGlvIj1TYW1wbGVfQUYvR25vbUFEX3YyLjFfbm9uX2NhbmNlcl9BRiwgCiAgICAgICAgICJTYW1wbGVfR2VuZV9MT0ZfQUZfUmF0aW9fTkZFIj1TYW1wbGVfQUYvR25vbUFEX3YyLjFfbm9uX2NhbmNlcl9BRl9uZmUpCn0KCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUV9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3MgPC0gCiAgcmF0aW9zKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUV9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0cykKCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zIDwtIAogIHJhdGlvcyhtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzKQoKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zIDwtIAogIHJhdGlvcyhtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0cykKCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvcyA8LSAKICByYXRpb3MobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFFfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHMpCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zIDwtIAogIHJhdGlvcyhtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHMpCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvcyA8LSAKICByYXRpb3MobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0cykKYGBgCgpDcmVhdGUgZGF0YSBmcmFtZXMgd2l0aCBBZ2lsZW50IFN1cmVTZWxlY3Qgd2hvbGUgZXhvbWUgZ2VuZXMgKGFsbCBFTlNULCBwcm90ZWluLWNvZGluZyBvbmx5IGFuZCBub24tcHJvdGVpbi1jb2RpbmcpIGZvciB2b2xjYW5vIHBsb3QKYGBge3J9CmVuc2VtYmxfYmlvdHlwZXMgPC0gcmVhZC5kZWxpbSgiZW5zZW1ibF9iaW90eXBlcy50c3YiLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKSAlPiUgCiAgc2VsZWN0KGVuc2VtYmxfdHJhbnNjcmlwdF9pZCx0cmFuc2NyaXB0X2Jpb3R5cGUpICU+JSAKICBkcGx5cjo6cmVuYW1lKCJGZWF0dXJlIj0iZW5zZW1ibF90cmFuc2NyaXB0X2lkIiwiQklPVFlQRSI9InRyYW5zY3JpcHRfYmlvdHlwZSIpCkdub21BRF9zdGF0c19BZ2lsZW50U1N2Nl9MT0ZfVkVQX0VOU1RjYW5vbmljYWxfYWxsIDwtIHJlYWQuZGVsaW0oIkdub21BRC5nZW5lLnN0YXRzLnYyLlJGLm9ubHkuYWdpbGVudC52Ni5vbmx5LnRzdiIsIGhlYWRlcj1UUlVFLCByb3cubmFtZXM9TlVMTCwgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkgJT4lIAogIGZpbHRlcihDQU5PTklDQUw9PSJZRVMiKSAlPiUgCiAgZHBseXI6OnJlbmFtZSgiU1lNQk9MIj0iWC5TeW1ib2wiKSAlPiUgCiAgZHBseXI6OnJlbmFtZSgiR2VuZSI9IkVOU0ciKSAlPiUgCiAgbGVmdF9qb2luKGVuc2VtYmxfYmlvdHlwZXMsYnk9IkZlYXR1cmUiLGNvcHk9RkFMU0UpCkdub21BRF9zdGF0c19BZ2lsZW50U1N2Nl9MT0ZfVkVQX0VOU1RjYW5vbmljYWxfcHJvdGVpbl9jb2RpbmcgPC0gcmVhZC5kZWxpbSgiR25vbUFELmdlbmUuc3RhdHMudjIuUkYub25seS5hZ2lsZW50LnY2Lm9ubHkudHN2IiwgaGVhZGVyPVRSVUUsIHJvdy5uYW1lcz1OVUxMLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKSAlPiUgCiAgZmlsdGVyKENBTk9OSUNBTD09IllFUyIpICU+JSAKICBkcGx5cjo6cmVuYW1lKCJTWU1CT0wiPSJYLlN5bWJvbCIpICU+JSAKICBkcGx5cjo6cmVuYW1lKCJHZW5lIj0iRU5TRyIpICU+JSAKICBsZWZ0X2pvaW4oZW5zZW1ibF9iaW90eXBlcyxieT0iRmVhdHVyZSIsY29weT1GQUxTRSkgJT4lIAogIGZpbHRlcihCSU9UWVBFJWluJWMoInByb3RlaW5fY29kaW5nIikpCkdub21BRF9zdGF0c19BZ2lsZW50U1N2Nl9MT0ZfVkVQX0VOU1RjYW5vbmljYWxfbm9uX3Byb3RlaW5fY29kaW5nIDwtIHJlYWQuZGVsaW0oIkdub21BRC5nZW5lLnN0YXRzLnYyLlJGLm9ubHkuYWdpbGVudC52Ni5vbmx5LnRzdiIsIGhlYWRlcj1UUlVFLCByb3cubmFtZXM9TlVMTCwgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkgJT4lIAogIGZpbHRlcihDQU5PTklDQUw9PSJZRVMiKSAlPiUgCiAgZHBseXI6OnJlbmFtZSgiU1lNQk9MIj0iWC5TeW1ib2wiKSAlPiUgCiAgZHBseXI6OnJlbmFtZSgiR2VuZSI9IkVOU0ciKSAlPiUgCiAgbGVmdF9qb2luKGVuc2VtYmxfYmlvdHlwZXMsYnk9IkZlYXR1cmUiLGNvcHk9RkFMU0UpICU+JSAKICBmaWx0ZXIoIUJJT1RZUEUlaW4lYygicHJvdGVpbl9jb2RpbmciKSkKCmFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3QgPC0gdGliYmxlKCJTWU1CT0wiPUdub21BRF9zdGF0c19BZ2lsZW50U1N2Nl9MT0ZfVkVQX0VOU1RjYW5vbmljYWxfYWxsJFNZTUJPTCwiR2VuZSI9R25vbUFEX3N0YXRzX0FnaWxlbnRTU3Y2X0xPRl9WRVBfRU5TVGNhbm9uaWNhbF9hbGwkR2VuZSwiRmVhdHVyZSI9R25vbUFEX3N0YXRzX0FnaWxlbnRTU3Y2X0xPRl9WRVBfRU5TVGNhbm9uaWNhbF9hbGwkRmVhdHVyZSkgJT4lIAogIGRpc3RpbmN0KC5rZWVwX2FsbD1UUlVFKSAlPiUgCiAgYXJyYW5nZShTWU1CT0wpCmFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3RfcHJvdGVpbl9jb2Rpbmdfb25seSA8LSB0aWJibGUoIlNZTUJPTCI9R25vbUFEX3N0YXRzX0FnaWxlbnRTU3Y2X0xPRl9WRVBfRU5TVGNhbm9uaWNhbF9wcm90ZWluX2NvZGluZyRTWU1CT0wsIkdlbmUiPUdub21BRF9zdGF0c19BZ2lsZW50U1N2Nl9MT0ZfVkVQX0VOU1RjYW5vbmljYWxfcHJvdGVpbl9jb2RpbmckR2VuZSwiRmVhdHVyZSI9R25vbUFEX3N0YXRzX0FnaWxlbnRTU3Y2X0xPRl9WRVBfRU5TVGNhbm9uaWNhbF9wcm90ZWluX2NvZGluZyRGZWF0dXJlKSAlPiUgCiAgZGlzdGluY3QoLmtlZXBfYWxsPVRSVUUpICU+JSAKICBhcnJhbmdlKFNZTUJPTCkKYWxsR2VuZXNfQWdpbGVudFNTdjZfbGlzdF9ub25fcHJvdGVpbl9jb2Rpbmdfb25seSA8LSB0aWJibGUoIlNZTUJPTCI9R25vbUFEX3N0YXRzX0FnaWxlbnRTU3Y2X0xPRl9WRVBfRU5TVGNhbm9uaWNhbF9ub25fcHJvdGVpbl9jb2RpbmckU1lNQk9MLCJHZW5lIj1Hbm9tQURfc3RhdHNfQWdpbGVudFNTdjZfTE9GX1ZFUF9FTlNUY2Fub25pY2FsX25vbl9wcm90ZWluX2NvZGluZyRHZW5lLCJGZWF0dXJlIj1Hbm9tQURfc3RhdHNfQWdpbGVudFNTdjZfTE9GX1ZFUF9FTlNUY2Fub25pY2FsX25vbl9wcm90ZWluX2NvZGluZyRGZWF0dXJlKSAlPiUgCiAgZGlzdGluY3QoLmtlZXBfYWxsPVRSVUUpICU+JSAKICBhcnJhbmdlKFNZTUJPTCkKCmFsbEdlbmVzX21hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV9saXN0IDwtIHRpYmJsZSgiU1lNQk9MIj1tYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvcyRTWU1CT0wsIkdlbmUiPW1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zJEdlbmUsIkJJT1RZUEUiPW1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zJEJJT1RZUEUpICU+JSAKICBkaXN0aW5jdCgua2VlcF9hbGw9VFJVRSkgJT4lIAogIGFycmFuZ2UoU1lNQk9MKQphbGxHZW5lc19tYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9saXN0IDwtIHRpYmJsZSgiU1lNQk9MIj1tYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvcyRTWU1CT0wsIkdlbmUiPW1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zJEdlbmUsIkJJT1RZUEUiPW1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zJEJJT1RZUEUpICU+JSAKICBkaXN0aW5jdCgua2VlcF9hbGw9VFJVRSkgJT4lIAogIGZpbHRlcihCSU9UWVBFJWluJWMoInByb3RlaW5fY29kaW5nIikpICU+JSAKICBhcnJhbmdlKFNZTUJPTCkKYWxsR2VuZXNfbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2xpc3QgPC0gdGliYmxlKCJTWU1CT0wiPW1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zJFNZTUJPTCwiR2VuZSI9bWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3MkR2VuZSwiQklPVFlQRSI9bWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3MkQklPVFlQRSkgJT4lIAogIGRpc3RpbmN0KC5rZWVwX2FsbD1UUlVFKSAlPiUgCiAgZmlsdGVyKCFCSU9UWVBFJWluJWMoInByb3RlaW5fY29kaW5nIikpICU+JSAKICBhcnJhbmdlKFNZTUJPTCkKCnZvbGNhbm8gPC0gZnVuY3Rpb24odmNmLGdlbmVfbGlzdCxHbm9tQUQsVG90YWxfU2FtcGxlX0FsbGVsZXMpewogIHdhdGVyIDwtIHZjZiAlPiUgCiAgbXV0YXRlKFRvdGFsX0Nhc2VfQWxsZWxlcz1Ub3RhbF9TYW1wbGVfQWxsZWxlcykgJT4lIAogIHNlbGVjdChTWU1CT0wsR2VuZSxUb3RhbF9HZW5lX0NvdW50LFRvdGFsX0Nhc2VfQWxsZWxlcykgJT4lIAogIGRpc3RpbmN0KFNZTUJPTCxHZW5lLFRvdGFsX0dlbmVfQ291bnQsVG90YWxfQ2FzZV9BbGxlbGVzKSAKICB3YXRlcjIgPC0gYmluZF9yb3dzKHdhdGVyLCBhbnRpX2pvaW4oZ2VuZV9saXN0LHdhdGVyLGJ5PSJHZW5lIikpICU+JSAKICBtdXRhdGVfYXQodmFycygiVG90YWxfR2VuZV9Db3VudCIpLGZ1bnMocmVwbGFjZSguLCBpcy5uYSguKSwgMCkpKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoIlRvdGFsX0Nhc2VfQWxsZWxlcyIpLGZ1bnMocmVwbGFjZSguLCBpcy5uYSguKSwgVG90YWxfU2FtcGxlX0FsbGVsZXMpKSkKICB3YXRlcjMgPC0gcmlnaHRfam9pbih3YXRlcjIsR25vbUFELGJ5PSJHZW5lIixjb3B5PUZBTFNFKSAlPiUgCiAgc2VsZWN0KCJTWU1CT0wueCIsIkdlbmUiLCJUb3RhbF9HZW5lX0NvdW50IiwiVG90YWxfQ2FzZV9BbGxlbGVzIiwiRklMVEVSX1JGX0xPRl9ISUdISU1QQUNUX0FDXzAuMDA1IiwiRklMVEVSX1JGX0xPRl9ISUdISU1QQUNUX0FDXzAuMDA1X05GRSIsIk1BWF9BTiIsIk1BWF9BTl9ORkUiLCJGSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUZfMC4wMDVfQURKIiwiRklMVEVSX1JGX0xPRl9ISUdISU1QQUNUX0FGXzAuMDA1X05GRV9BREoiKSAlPiUgCiAgZHBseXI6OnJlbmFtZSgiU1lNQk9MIj0iU1lNQk9MLngiKSAlPiUKICBtdXRhdGUoRklMVEVSX1JGX0xPRl9ISUdISU1QQUNUX0FDXzAuMDA1X0FESj1yb3VuZCgoTUFYX0FOKkZJTFRFUl9SRl9MT0ZfSElHSElNUEFDVF9BRl8wLjAwNV9BREopKSkgJT4lIAogIG11dGF0ZShGSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUNfMC4wMDVfTkZFX0FESj1yb3VuZCgoTUFYX0FOX05GRSpGSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUZfMC4wMDVfTkZFX0FESikpKSAlPiUgCiAgZGlzdGluY3QoLmtlZXBfYWxsPVRSVUUpCiAgcmV0dXJuKHdhdGVyMykKfQoKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzIDwtIHZvbGNhbm8obWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3MsYWxsR2VuZXNfQWdpbGVudFNTdjZfbGlzdCxHbm9tQURfc3RhdHNfQWdpbGVudFNTdjZfTE9GX1ZFUF9FTlNUY2Fub25pY2FsX2FsbCxUb3RhbF9TYW1wbGVfQWxsZWxlc19GSHgpCgp2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyA8LSB2b2xjYW5vKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zLGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3RfcHJvdGVpbl9jb2Rpbmdfb25seSxHbm9tQURfc3RhdHNfQWdpbGVudFNTdjZfTE9GX1ZFUF9FTlNUY2Fub25pY2FsX3Byb3RlaW5fY29kaW5nLFRvdGFsX1NhbXBsZV9BbGxlbGVzX0ZIeCkKCnZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lcyA8LSB2b2xjYW5vKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zLGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3Rfbm9uX3Byb3RlaW5fY29kaW5nX29ubHksR25vbUFEX3N0YXRzX0FnaWxlbnRTU3Y2X0xPRl9WRVBfRU5TVGNhbm9uaWNhbF9ub25fcHJvdGVpbl9jb2RpbmcsVG90YWxfU2FtcGxlX0FsbGVsZXNfRkh4KQoKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMgPC0gdm9sY2FubyhtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zLGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3QsR25vbUFEX3N0YXRzX0FnaWxlbnRTU3Y2X0xPRl9WRVBfRU5TVGNhbm9uaWNhbF9hbGwsVG90YWxfU2FtcGxlX0FsbGVsZXNfbm9GSHgpCgp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzIDwtIHZvbGNhbm8obWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvcyxhbGxHZW5lc19BZ2lsZW50U1N2Nl9saXN0X3Byb3RlaW5fY29kaW5nX29ubHksR25vbUFEX3N0YXRzX0FnaWxlbnRTU3Y2X0xPRl9WRVBfRU5TVGNhbm9uaWNhbF9wcm90ZWluX2NvZGluZyxUb3RhbF9TYW1wbGVfQWxsZWxlc19ub0ZIeCkKCnZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzIDwtIHZvbGNhbm8obWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvcyxhbGxHZW5lc19BZ2lsZW50U1N2Nl9saXN0X25vbl9wcm90ZWluX2NvZGluZ19vbmx5LEdub21BRF9zdGF0c19BZ2lsZW50U1N2Nl9MT0ZfVkVQX0VOU1RjYW5vbmljYWxfbm9uX3Byb3RlaW5fY29kaW5nLFRvdGFsX1NhbXBsZV9BbGxlbGVzX25vRkh4KQpgYGAKCkNhbGN1bGF0ZSBGaXNoZXIncyB0ZXN0IHZhbHVlcyAoRW5zZW1ibCBDYW5vbmljYWwpCmBgYHtyfQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzIDwtIG11dGF0ZShtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvcyxUb3RhbF9DYXNlX0FsbGVsZXM9VG90YWxfU2FtcGxlX0FsbGVsZXNfRkh4KSAlPiUgCiAgbGVmdF9qb2luKEdub21BRF9zdGF0c19MT0ZfVkVQWyxjKDIsNiwxMCwxNDoyOSldLGJ5PSJGZWF0dXJlIixjb3B5PUZBTFNFKSAKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czIgPC0gbXV0YXRlKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMsIE1BWF9BTj1yZXBsYWNlKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMkTUFYX0FOLCBpcy5uYShtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzJE1BWF9BTiksIG1heChtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzJE1BWF9BTiwgbmEucm09VFJVRSkpKSAlPiUgCiAgbXV0YXRlKE1BWF9BTl9ORkU9cmVwbGFjZSguJE1BWF9BTl9ORkUsIGlzLm5hKC4kTUFYX0FOX05GRSksIG1heChtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzJE1BWF9BTl9ORkUsIG5hLnJtPVRSVUUpKSkKCmZpc2hlcnJlc3VsdHNfRU5TVCA8LSBhcHBseShtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMlssYygyMjIsMjMwLDI0NCwyNDUpXSwxLGZ1bmN0aW9uKHgpIHtmaXNoZXIudGVzdChyYmluZCh4WzE6Ml0sYyh4WzNdLXhbMV0seFs0XS14WzJdKSkpfSkKCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJFBfdmFsdWVfRmlzaGVyXzAuMDA1ID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfRU5TVCxmdW5jdGlvbih4KSByb3VuZCh4JHAudmFsdWUsMTIpKQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRPUl8wLjAwNSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX0VOU1QsZnVuY3Rpb24oeCkgcm91bmQoeCRlc3RpbWF0ZSw0KSkKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czIkYDk1JUNJXzAuMDA1YCA9IHNhcHBseShmaXNoZXJyZXN1bHRzX0VOU1QsZnVuY3Rpb24oeCkgcGFzdGUocm91bmQoeCRjb25mLmludFsxOjJdLDIpLGNvbGxhcHNlPSJ+IikpCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJEJIXzAuMDA1ID0gcC5hZGp1c3QobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czIkUF92YWx1ZV9GaXNoZXJfMC4wMDUsbWV0aG9kID0gIkJIIikKCmZpc2hlcnJlc3VsdHMyX0VOU1QgPC0gYXBwbHkobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czJbLGMoMjIyLDIzMywyNDQsMjQ2KV0sMSxmdW5jdGlvbih4KSB7ZmlzaGVyLnRlc3QocmJpbmQoeFsxOjJdLGMoeFszXS14WzFdLHhbNF0teFsyXSkpKX0pCgptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUgPSBzYXBwbHkoZmlzaGVycmVzdWx0czJfRU5TVCxmdW5jdGlvbih4KSByb3VuZCh4JHAudmFsdWUsMTIpKQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRPUl8wLjAwNV9ORkUgPSBzYXBwbHkoZmlzaGVycmVzdWx0czJfRU5TVCxmdW5jdGlvbih4KSByb3VuZCh4JGVzdGltYXRlLDQpKQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRgOTUlQ0lfMC4wMDVfTkZFYCA9IHNhcHBseShmaXNoZXJyZXN1bHRzMl9FTlNULGZ1bmN0aW9uKHgpIHBhc3RlKHJvdW5kKHgkY29uZi5pbnRbMToyXSwyKSxjb2xsYXBzZT0ifiIpKQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRCSF8wLjAwNV9ORkUgPSBwLmFkanVzdChtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUsbWV0aG9kID0gIkJIIikKCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0cyA8LSBtdXRhdGUobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvcyxUb3RhbF9DYXNlX0FsbGVsZXM9VG90YWxfU2FtcGxlX0FsbGVsZXNfbm9GSHgpICU+JSAKICBsZWZ0X2pvaW4oR25vbUFEX3N0YXRzX0xPRl9WRVBbLGMoMiw2LDEwLDE0OjI5KV0sYnk9IkZlYXR1cmUiLGNvcHk9RkFMU0UpIAptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyIDwtIG11dGF0ZShtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMsIE1BWF9BTj1yZXBsYWNlKG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0cyRNQVhfQU4sIGlzLm5hKG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0cyRNQVhfQU4pLCBtYXgobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzJE1BWF9BTiwgbmEucm09VFJVRSkpKSAlPiUgCiAgbXV0YXRlKE1BWF9BTl9ORkU9cmVwbGFjZSguJE1BWF9BTl9ORkUsIGlzLm5hKC4kTUFYX0FOX05GRSksIG1heChtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMkTUFYX0FOX05GRSwgbmEucm09VFJVRSkpKQoKZmlzaGVycmVzdWx0c19FTlNUIDwtIGFwcGx5KG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czJbLGMoMjIyLDIzMCwyNDQsMjQ1KV0sMSxmdW5jdGlvbih4KSB7ZmlzaGVyLnRlc3QocmJpbmQoeFsxOjJdLGMoeFszXS14WzFdLHhbNF0teFsyXSkpKX0pCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJFBfdmFsdWVfRmlzaGVyXzAuMDA1ID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfRU5TVCxmdW5jdGlvbih4KSByb3VuZCh4JHAudmFsdWUsMTIpKQptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJE9SXzAuMDA1ID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfRU5TVCxmdW5jdGlvbih4KSByb3VuZCh4JGVzdGltYXRlLDQpKQptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJGA5NSVDSV8wLjAwNWAgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19FTlNULGZ1bmN0aW9uKHgpIHBhc3RlKHJvdW5kKHgkY29uZi5pbnRbMToyXSwyKSxjb2xsYXBzZT0ifiIpKQptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJEJIXzAuMDA1ID0gcC5hZGp1c3QobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRQX3ZhbHVlX0Zpc2hlcl8wLjAwNSxtZXRob2QgPSAiQkgiKQoKZmlzaGVycmVzdWx0czJfRU5TVCA8LSBhcHBseShtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyWyxjKDIyMiwyMzMsMjQ0LDI0NildLDEsZnVuY3Rpb24oeCkge2Zpc2hlci50ZXN0KHJiaW5kKHhbMToyXSxjKHhbM10teFsxXSx4WzRdLXhbMl0pKSl9KQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUgPSBzYXBwbHkoZmlzaGVycmVzdWx0czJfRU5TVCxmdW5jdGlvbih4KSByb3VuZCh4JHAudmFsdWUsMTIpKQptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJE9SXzAuMDA1X05GRSA9IHNhcHBseShmaXNoZXJyZXN1bHRzMl9FTlNULGZ1bmN0aW9uKHgpIHJvdW5kKHgkZXN0aW1hdGUsNCkpCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czIkYDk1JUNJXzAuMDA1X05GRWAgPSBzYXBwbHkoZmlzaGVycmVzdWx0czJfRU5TVCxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRCSF8wLjAwNV9ORkUgPSBwLmFkanVzdChtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJFBfdmFsdWVfRmlzaGVyXzAuMDA1X05GRSxtZXRob2QgPSAiQkgiKQpgYGAKCkNhbGN1bGF0ZSBGaXNoZXIncyB0ZXN0IHZhbHVlcyAoUmVmU2VxIENhbm9uaWNhbCkKYGBge3J9Cm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzIDwtIG11dGF0ZShtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3MsVG90YWxfQ2FzZV9BbGxlbGVzPVRvdGFsX1NhbXBsZV9BbGxlbGVzX0ZIeCkgJT4lIAogIGxlZnRfam9pbihHbm9tQURfc3RhdHNfTE9GX1ZFUFssYygyLDYsMTAsMTQ6MjkpXSxieT0iRmVhdHVyZSIsY29weT1GQUxTRSkgCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiA8LSBtdXRhdGUobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMsIE1BWF9BTj1yZXBsYWNlKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzJE1BWF9BTiwgaXMubmEobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMkTUFYX0FOKSwgbWF4KG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzJE1BWF9BTiwgbmEucm09VFJVRSkpKSAlPiUgCiAgbXV0YXRlKE1BWF9BTl9ORkU9cmVwbGFjZSguJE1BWF9BTl9ORkUsIGlzLm5hKC4kTUFYX0FOX05GRSksIG1heChtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0cyRNQVhfQU5fTkZFLCBuYS5ybT1UUlVFKSkpCgpmaXNoZXJyZXN1bHRzX05NIDwtIGFwcGx5KG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMlssYygyMjIsMjMwLDI0NCwyNDUpXSwxLGZ1bmN0aW9uKHgpIHtmaXNoZXIudGVzdChyYmluZCh4WzE6Ml0sYyh4WzNdLXhbMV0seFs0XS14WzJdKSkpfSkKCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRQX3ZhbHVlX0Zpc2hlcl8wLjAwNSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX05NLGZ1bmN0aW9uKHgpIHJvdW5kKHgkcC52YWx1ZSwxMikpCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRPUl8wLjAwNSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX05NLGZ1bmN0aW9uKHgpIHJvdW5kKHgkZXN0aW1hdGUsNCkpCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRgOTUlQ0lfMC4wMDVgID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfTk0sZnVuY3Rpb24oeCkgcGFzdGUocm91bmQoeCRjb25mLmludFsxOjJdLDIpLGNvbGxhcHNlPSJ+IikpCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRCSF8wLjAwNSA9IHAuYWRqdXN0KG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRQX3ZhbHVlX0Zpc2hlcl8wLjAwNSxtZXRob2QgPSAiQkgiKQoKZmlzaGVycmVzdWx0czJfTk0gPC0gYXBwbHkobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyWyxjKDIyMiwyMzMsMjQ0LDI0NildLDEsZnVuY3Rpb24oeCkge2Zpc2hlci50ZXN0KHJiaW5kKHhbMToyXSxjKHhbM10teFsxXSx4WzRdLXhbMl0pKSl9KQoKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJFBfdmFsdWVfRmlzaGVyXzAuMDA1X05GRSA9IHNhcHBseShmaXNoZXJyZXN1bHRzMl9OTSxmdW5jdGlvbih4KSByb3VuZCh4JHAudmFsdWUsMTIpKQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czIkT1JfMC4wMDVfTkZFID0gc2FwcGx5KGZpc2hlcnJlc3VsdHMyX05NLGZ1bmN0aW9uKHgpIHJvdW5kKHgkZXN0aW1hdGUsNCkpCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRgOTUlQ0lfMC4wMDVfTkZFYCA9IHNhcHBseShmaXNoZXJyZXN1bHRzMl9OTSxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJEJIXzAuMDA1X05GRSA9IHAuYWRqdXN0KG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUsbWV0aG9kID0gIkJIIikKCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMgPC0gbXV0YXRlKG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zLFRvdGFsX0Nhc2VfQWxsZWxlcz1Ub3RhbF9TYW1wbGVfQWxsZWxlc19ub0ZIeCkgJT4lIAogIGxlZnRfam9pbihHbm9tQURfc3RhdHNfTE9GX1ZFUFssYygyLDYsMTAsMTQ6MjkpXSxieT0iRmVhdHVyZSIsY29weT1GQUxTRSkgCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyIDwtIG11dGF0ZShtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzLCBNQVhfQU49cmVwbGFjZShtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzJE1BWF9BTiwgaXMubmEobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0cyRNQVhfQU4pLCBtYXgobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0cyRNQVhfQU4sIG5hLnJtPVRSVUUpKSkgJT4lIAogIG11dGF0ZShNQVhfQU5fTkZFPXJlcGxhY2UoLiRNQVhfQU5fTkZFLCBpcy5uYSguJE1BWF9BTl9ORkUpLCBtYXgobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0cyRNQVhfQU5fTkZFLCBuYS5ybT1UUlVFKSkpCgpmaXNoZXJyZXN1bHRzX05NIDwtIGFwcGx5KG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyWyxjKDIyMiwyMzAsMjQ0LDI0NSldLDEsZnVuY3Rpb24oeCkge2Zpc2hlci50ZXN0KHJiaW5kKHhbMToyXSxjKHhbM10teFsxXSx4WzRdLXhbMl0pKSl9KQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czIkUF92YWx1ZV9GaXNoZXJfMC4wMDUgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19OTSxmdW5jdGlvbih4KSByb3VuZCh4JHAudmFsdWUsMTIpKQptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRPUl8wLjAwNSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX05NLGZ1bmN0aW9uKHgpIHJvdW5kKHgkZXN0aW1hdGUsNCkpCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJGA5NSVDSV8wLjAwNWAgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19OTSxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czIkQkhfMC4wMDUgPSBwLmFkanVzdChtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRQX3ZhbHVlX0Zpc2hlcl8wLjAwNSxtZXRob2QgPSAiQkgiKQoKZmlzaGVycmVzdWx0czJfTk0gPC0gYXBwbHkobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czJbLGMoMjIyLDIzMywyNDQsMjQ2KV0sMSxmdW5jdGlvbih4KSB7ZmlzaGVyLnRlc3QocmJpbmQoeFsxOjJdLGMoeFszXS14WzFdLHhbNF0teFsyXSkpKX0pCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUgPSBzYXBwbHkoZmlzaGVycmVzdWx0czJfTk0sZnVuY3Rpb24oeCkgcm91bmQoeCRwLnZhbHVlLDEyKSkKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czIkT1JfMC4wMDVfTkZFID0gc2FwcGx5KGZpc2hlcnJlc3VsdHMyX05NLGZ1bmN0aW9uKHgpIHJvdW5kKHgkZXN0aW1hdGUsNCkpCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyJGA5NSVDSV8wLjAwNV9ORkVgID0gc2FwcGx5KGZpc2hlcnJlc3VsdHMyX05NLGZ1bmN0aW9uKHgpIHBhc3RlKHJvdW5kKHgkY29uZi5pbnRbMToyXSwyKSxjb2xsYXBzZT0ifiIpKQptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRCSF8wLjAwNV9ORkUgPSBwLmFkanVzdChtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiRQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUsbWV0aG9kID0gIkJIIikKYGBgCgpDYWxjdWxhdGUgRmlzaGVyJ3MgdGVzdCB2YWx1ZXMgKHZvbGNhbm8gcGxvdCkKYGBge3J9CmZpc2hlcnJlc3VsdHNfYWxsR2VuZXNfdm9sY2FubyA8LSBhcHBseSh2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXNbLGMoMyw1LDQsNyldLDEsZnVuY3Rpb24oeCkge2Zpc2hlci50ZXN0KHJiaW5kKHhbMToyXSxjKGFicyh4WzNdLXhbMV0pLGFicyh4WzRdLXhbMl0pKSkpfSkKCnZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcyRQX3ZhbHVlX0Zpc2hlcl8wLjAwNSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2FsbEdlbmVzX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcm91bmQoeCRwLnZhbHVlLDE1KSkKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJE9SXzAuMDA1ID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYWxsR2VuZXNfdm9sY2FubyxmdW5jdGlvbih4KSByb3VuZCh4JGVzdGltYXRlLDE1KSkKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJGA5NSVDSV8wLjAwNWAgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19hbGxHZW5lc192b2xjYW5vLGZ1bmN0aW9uKHgpIHBhc3RlKHJvdW5kKHgkY29uZi5pbnRbMToyXSwyKSxjb2xsYXBzZT0ifiIpKQp2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMkQkhfMC4wMDUgPSBwLmFkanVzdCh2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMkUF92YWx1ZV9GaXNoZXJfMC4wMDUsbWV0aG9kID0gIkJIIikKCmZpc2hlcnJlc3VsdHNfTkZFX3ZvbGNhbm8gPC0gYXBwbHkodm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzWyxjKDMsNiw0LDgpXSwxLGZ1bmN0aW9uKHgpIHtmaXNoZXIudGVzdChyYmluZCh4WzE6Ml0sYyhhYnMoeFszXS14WzFdKSxhYnMoeFs0XS14WzJdKSkpKX0pCgp2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMkUF92YWx1ZV9GaXNoZXJfMC4wMDVfTkZFID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfTkZFX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcm91bmQoeCRwLnZhbHVlLDE1KSkKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJE9SXzAuMDA1X05GRSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX05GRV92b2xjYW5vLGZ1bmN0aW9uKHgpIHJvdW5kKHgkZXN0aW1hdGUsMTUpKQp2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMkYDk1JUNJXzAuMDA1X05GRWAgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19ORkVfdm9sY2FubyxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJEJIXzAuMDA1X05GRSA9IHAuYWRqdXN0KHZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcyRQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUsbWV0aG9kID0gIkJIIikKCmZpc2hlcnJlc3VsdHNfYmlvdHlwZV9hbGxHZW5lc192b2xjYW5vIDwtIGFwcGx5KHZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzWyxjKDMsNSw0LDcpXSwxLGZ1bmN0aW9uKHgpIHtmaXNoZXIudGVzdChyYmluZCh4WzE6Ml0sYyhhYnMoeFszXS14WzFdKSxhYnMoeFs0XS14WzJdKSkpKX0pCgp2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRQX3ZhbHVlX0Zpc2hlcl8wLjAwNSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2Jpb3R5cGVfYWxsR2VuZXNfdm9sY2FubyxmdW5jdGlvbih4KSByb3VuZCh4JHAudmFsdWUsMTUpKQp2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRPUl8wLjAwNSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2Jpb3R5cGVfYWxsR2VuZXNfdm9sY2FubyxmdW5jdGlvbih4KSByb3VuZCh4JGVzdGltYXRlLDE1KSkKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMkYDk1JUNJXzAuMDA1YCA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2Jpb3R5cGVfYWxsR2VuZXNfdm9sY2FubyxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMkQkhfMC4wMDUgPSBwLmFkanVzdCh2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRQX3ZhbHVlX0Zpc2hlcl8wLjAwNSxtZXRob2QgPSAiQkgiKQoKZmlzaGVycmVzdWx0c19iaW90eXBlX05GRV92b2xjYW5vIDwtIGFwcGx5KHZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzWyxjKDMsNiw0LDgpXSwxLGZ1bmN0aW9uKHgpIHtmaXNoZXIudGVzdChyYmluZCh4WzE6Ml0sYyhhYnMoeFszXS14WzFdKSxhYnMoeFs0XS14WzJdKSkpKX0pCgp2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19iaW90eXBlX05GRV92b2xjYW5vLGZ1bmN0aW9uKHgpIHJvdW5kKHgkcC52YWx1ZSwxNSkpCnZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzJE9SXzAuMDA1X05GRSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2Jpb3R5cGVfTkZFX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcm91bmQoeCRlc3RpbWF0ZSwxNSkpCnZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzJGA5NSVDSV8wLjAwNV9ORkVgID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYmlvdHlwZV9ORkVfdm9sY2FubyxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMkQkhfMC4wMDVfTkZFID0gcC5hZGp1c3Qodm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMkUF92YWx1ZV9GaXNoZXJfMC4wMDVfTkZFLG1ldGhvZCA9ICJCSCIpCgpmaXNoZXJyZXN1bHRzX2Jpb3R5cGUyX2FsbEdlbmVzX3ZvbGNhbm8gPC0gYXBwbHkodm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzWyxjKDMsNSw0LDcpXSwxLGZ1bmN0aW9uKHgpIHtmaXNoZXIudGVzdChyYmluZCh4WzE6Ml0sYyhhYnMoeFszXS14WzFdKSxhYnMoeFs0XS14WzJdKSkpKX0pCgp2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZTJfYWxsR2VuZXMkUF92YWx1ZV9GaXNoZXJfMC4wMDUgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19iaW90eXBlMl9hbGxHZW5lc192b2xjYW5vLGZ1bmN0aW9uKHgpIHJvdW5kKHgkcC52YWx1ZSwxNSkpCnZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lcyRPUl8wLjAwNSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2Jpb3R5cGUyX2FsbEdlbmVzX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcm91bmQoeCRlc3RpbWF0ZSwxNSkpCnZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lcyRgOTUlQ0lfMC4wMDVgID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYmlvdHlwZTJfYWxsR2VuZXNfdm9sY2FubyxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzJEJIXzAuMDA1ID0gcC5hZGp1c3Qodm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzJFBfdmFsdWVfRmlzaGVyXzAuMDA1LG1ldGhvZCA9ICJCSCIpCgpmaXNoZXJyZXN1bHRzX2Jpb3R5cGUyX05GRV92b2xjYW5vIDwtIGFwcGx5KHZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lc1ssYygzLDYsNCw4KV0sMSxmdW5jdGlvbih4KSB7ZmlzaGVyLnRlc3QocmJpbmQoeFsxOjJdLGMoYWJzKHhbM10teFsxXSksYWJzKHhbNF0teFsyXSkpKSl9KQoKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzJFBfdmFsdWVfRmlzaGVyXzAuMDA1X05GRSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2Jpb3R5cGUyX05GRV92b2xjYW5vLGZ1bmN0aW9uKHgpIHJvdW5kKHgkcC52YWx1ZSwxNSkpCnZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lcyRPUl8wLjAwNV9ORkUgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19iaW90eXBlMl9ORkVfdm9sY2FubyxmdW5jdGlvbih4KSByb3VuZCh4JGVzdGltYXRlLDE1KSkKdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzJGA5NSVDSV8wLjAwNV9ORkVgID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYmlvdHlwZTJfTkZFX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcGFzdGUocm91bmQoeCRjb25mLmludFsxOjJdLDIpLGNvbGxhcHNlPSJ+IikpCnZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lcyRCSF8wLjAwNV9ORkUgPSBwLmFkanVzdCh2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZTJfYWxsR2VuZXMkUF92YWx1ZV9GaXNoZXJfMC4wMDVfTkZFLG1ldGhvZCA9ICJCSCIpCgpmaXNoZXJyZXN1bHRzX2FsbEdlbmVzX3ZvbGNhbm8gPC0gYXBwbHkodm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXNbLGMoMyw1LDQsNyldLDEsZnVuY3Rpb24oeCkge2Zpc2hlci50ZXN0KHJiaW5kKHhbMToyXSxjKGFicyh4WzNdLXhbMV0pLGFicyh4WzRdLXhbMl0pKSkpfSkKCnZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJFBfdmFsdWVfRmlzaGVyXzAuMDA1ID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYWxsR2VuZXNfdm9sY2FubyxmdW5jdGlvbih4KSByb3VuZCh4JHAudmFsdWUsMTUpKQp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcyRPUl8wLjAwNSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2FsbEdlbmVzX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcm91bmQoeCRlc3RpbWF0ZSwxNSkpCnZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJGA5NSVDSV8wLjAwNWAgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19hbGxHZW5lc192b2xjYW5vLGZ1bmN0aW9uKHgpIHBhc3RlKHJvdW5kKHgkY29uZi5pbnRbMToyXSwyKSxjb2xsYXBzZT0ifiIpKQp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcyRCSF8wLjAwNSA9IHAuYWRqdXN0KHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJFBfdmFsdWVfRmlzaGVyXzAuMDA1LG1ldGhvZCA9ICJCSCIpCgpmaXNoZXJyZXN1bHRzX05GRV92b2xjYW5vIDwtIGFwcGx5KHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzWyxjKDMsNiw0LDgpXSwxLGZ1bmN0aW9uKHgpIHtmaXNoZXIudGVzdChyYmluZCh4WzE6Ml0sYyhhYnMoeFszXS14WzFdKSxhYnMoeFs0XS14WzJdKSkpKX0pCgp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcyRQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19ORkVfdm9sY2FubyxmdW5jdGlvbih4KSByb3VuZCh4JHAudmFsdWUsMTUpKQp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcyRPUl8wLjAwNV9ORkUgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19ORkVfdm9sY2FubyxmdW5jdGlvbih4KSByb3VuZCh4JGVzdGltYXRlLDE1KSkKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMkYDk1JUNJXzAuMDA1X05GRWAgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19ORkVfdm9sY2FubyxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMkQkhfMC4wMDVfTkZFID0gcC5hZGp1c3Qodm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMkUF92YWx1ZV9GaXNoZXJfMC4wMDVfTkZFLG1ldGhvZCA9ICJCSCIpCgpmaXNoZXJyZXN1bHRzX2Jpb3R5cGVfYWxsR2VuZXNfdm9sY2FubyA8LSBhcHBseSh2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzWyxjKDMsNSw0LDcpXSwxLGZ1bmN0aW9uKHgpIHtmaXNoZXIudGVzdChyYmluZCh4WzE6Ml0sYyhhYnMoeFszXS14WzFdKSxhYnMoeFs0XS14WzJdKSkpKX0pCgp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzJFBfdmFsdWVfRmlzaGVyXzAuMDA1ID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYmlvdHlwZV9hbGxHZW5lc192b2xjYW5vLGZ1bmN0aW9uKHgpIHJvdW5kKHgkcC52YWx1ZSwxNSkpCnZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMkT1JfMC4wMDUgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19iaW90eXBlX2FsbEdlbmVzX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcm91bmQoeCRlc3RpbWF0ZSwxNSkpCnZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMkYDk1JUNJXzAuMDA1YCA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2Jpb3R5cGVfYWxsR2VuZXNfdm9sY2FubyxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRCSF8wLjAwNSA9IHAuYWRqdXN0KHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMkUF92YWx1ZV9GaXNoZXJfMC4wMDUsbWV0aG9kID0gIkJIIikKCmZpc2hlcnJlc3VsdHNfYmlvdHlwZV9ORkVfdm9sY2FubyA8LSBhcHBseSh2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzWyxjKDMsNiw0LDgpXSwxLGZ1bmN0aW9uKHgpIHtmaXNoZXIudGVzdChyYmluZCh4WzE6Ml0sYyhhYnMoeFszXS14WzFdKSxhYnMoeFs0XS14WzJdKSkpKX0pCgp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzJFBfdmFsdWVfRmlzaGVyXzAuMDA1X05GRSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2Jpb3R5cGVfTkZFX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcm91bmQoeCRwLnZhbHVlLDE1KSkKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRPUl8wLjAwNV9ORkUgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19iaW90eXBlX05GRV92b2xjYW5vLGZ1bmN0aW9uKHgpIHJvdW5kKHgkZXN0aW1hdGUsMTUpKQp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzJGA5NSVDSV8wLjAwNV9ORkVgID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYmlvdHlwZV9ORkVfdm9sY2FubyxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRCSF8wLjAwNV9ORkUgPSBwLmFkanVzdCh2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzJFBfdmFsdWVfRmlzaGVyXzAuMDA1X05GRSxtZXRob2QgPSAiQkgiKQoKZmlzaGVycmVzdWx0c19iaW90eXBlMl9hbGxHZW5lc192b2xjYW5vIDwtIGFwcGx5KHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzWyxjKDMsNSw0LDcpXSwxLGZ1bmN0aW9uKHgpIHtmaXNoZXIudGVzdChyYmluZCh4WzE6Ml0sYyhhYnMoeFszXS14WzFdKSxhYnMoeFs0XS14WzJdKSkpKX0pCgp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lcyRQX3ZhbHVlX0Zpc2hlcl8wLjAwNSA9IHNhcHBseShmaXNoZXJyZXN1bHRzX2Jpb3R5cGUyX2FsbEdlbmVzX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcm91bmQoeCRwLnZhbHVlLDE1KSkKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZTJfYWxsR2VuZXMkT1JfMC4wMDUgPSBzYXBwbHkoZmlzaGVycmVzdWx0c19iaW90eXBlMl9hbGxHZW5lc192b2xjYW5vLGZ1bmN0aW9uKHgpIHJvdW5kKHgkZXN0aW1hdGUsMTUpKQp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lcyRgOTUlQ0lfMC4wMDVgID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYmlvdHlwZTJfYWxsR2VuZXNfdm9sY2FubyxmdW5jdGlvbih4KSBwYXN0ZShyb3VuZCh4JGNvbmYuaW50WzE6Ml0sMiksY29sbGFwc2U9In4iKSkKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZTJfYWxsR2VuZXMkQkhfMC4wMDUgPSBwLmFkanVzdCh2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lcyRQX3ZhbHVlX0Zpc2hlcl8wLjAwNSxtZXRob2QgPSAiQkgiKQoKZmlzaGVycmVzdWx0c19iaW90eXBlMl9ORkVfdm9sY2FubyA8LSBhcHBseSh2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lc1ssYygzLDYsNCw4KV0sMSxmdW5jdGlvbih4KSB7ZmlzaGVyLnRlc3QocmJpbmQoeFsxOjJdLGMoYWJzKHhbM10teFsxXSksYWJzKHhbNF0teFsyXSkpKSl9KQoKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZTJfYWxsR2VuZXMkUF92YWx1ZV9GaXNoZXJfMC4wMDVfTkZFID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYmlvdHlwZTJfTkZFX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcm91bmQoeCRwLnZhbHVlLDE1KSkKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZTJfYWxsR2VuZXMkT1JfMC4wMDVfTkZFID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYmlvdHlwZTJfTkZFX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcm91bmQoeCRlc3RpbWF0ZSwxNSkpCnZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzJGA5NSVDSV8wLjAwNV9ORkVgID0gc2FwcGx5KGZpc2hlcnJlc3VsdHNfYmlvdHlwZTJfTkZFX3ZvbGNhbm8sZnVuY3Rpb24oeCkgcGFzdGUocm91bmQoeCRjb25mLmludFsxOjJdLDIpLGNvbGxhcHNlPSJ+IikpCnZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzJEJIXzAuMDA1X05GRSA9IHAuYWRqdXN0KHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzJFBfdmFsdWVfRmlzaGVyXzAuMDA1X05GRSxtZXRob2QgPSAiQkgiKQpgYGAKCklkZW50aWZ5IHZhcmlhbnRzIHdpdGggZmlsdGVyaW5nIEFGID4gbWF4aW11bSBjcmVkaWJsZSBwb3B1bGF0aW9uIEFGIGluIEdub21BRCBmb3IgaGVyZWRpdGFyeSBFT0MgKDAuMDAwMTgxKQpgYGB7cn0KbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czMgPC0gbXV0YXRlKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyLCBGaWx0ZXJpbmdBRl85NV9FeGNlZWRzX01heENyZWRQb3BBRj0oKEdub21BRF92Mi4xX25vbl9jYW5jZXJfRmlsdGVyaW5nX0FGXzk1KT4wLjAwMDE4MSkpICU+JSAKICBtdXRhdGUoRmlsdGVyaW5nQUZfOTVfTkZFX0V4Y2VlZHNfTWF4Q3JlZFBvcEFGPSgoR25vbUFEX3YyLjFfbm9uX2NhbmNlcl9GaWx0ZXJpbmdfQUZfOTVfbmZlKT4wLjAwMDE4MSkpCgptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czMgPC0gbXV0YXRlKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiwgRmlsdGVyaW5nQUZfOTVfRXhjZWVkc19NYXhDcmVkUG9wQUY9KChHbm9tQURfdjIuMV9ub25fY2FuY2VyX0ZpbHRlcmluZ19BRl85NSk+MC4wMDAxODEpKSAlPiUgCiAgbXV0YXRlKEZpbHRlcmluZ0FGXzk1X05GRV9FeGNlZWRzX01heENyZWRQb3BBRj0oKEdub21BRF92Mi4xX25vbl9jYW5jZXJfRmlsdGVyaW5nX0FGXzk1X25mZSk+MC4wMDAxODEpKQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMyA8LSBtdXRhdGUobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMiwgRmlsdGVyaW5nQUZfOTVfRXhjZWVkc19NYXhDcmVkUG9wQUY9KChHbm9tQURfdjIuMV9ub25fY2FuY2VyX0ZpbHRlcmluZ19BRl85NSk+MC4wMDAxODEpKSAlPiUgCiAgbXV0YXRlKEZpbHRlcmluZ0FGXzk1X05GRV9FeGNlZWRzX01heENyZWRQb3BBRj0oKEdub21BRF92Mi4xX25vbl9jYW5jZXJfRmlsdGVyaW5nX0FGXzk1X25mZSk+MC4wMDAxODEpKQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czMgPC0gbXV0YXRlKG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMyLCBGaWx0ZXJpbmdBRl85NV9FeGNlZWRzX01heENyZWRQb3BBRj0oKEdub21BRF92Mi4xX25vbl9jYW5jZXJfRmlsdGVyaW5nX0FGXzk1KT4wLjAwMDE4MSkpICU+JSAKICBtdXRhdGUoRmlsdGVyaW5nQUZfOTVfTkZFX0V4Y2VlZHNfTWF4Q3JlZFBvcEFGPSgoR25vbUFEX3YyLjFfbm9uX2NhbmNlcl9GaWx0ZXJpbmdfQUZfOTVfbmZlKT4wLjAwMDE4MSkpCmBgYAoKSWRlbnRpZnkgdmFyaWFudHMgdGhhdCBQQVNTL0ZBSUwgdGhlIExPRlRFRSA1MGJwIHJ1bGUKYGBge3J9Cm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHM0IDwtIG11dGF0ZShtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMyxMb0ZfNTBfQlBfUlVMRSA9IGlmZWxzZShncmVwbCgiNTBfQlBfUlVMRTpQQVNTIiwgTG9GX2luZm8pLCBUUlVFLCBpZmVsc2UoZ3JlcGwoIjUwX0JQX1JVTEU6RkFJTCIsIExvRl9pbmZvKSwgRkFMU0UsIE5BKSkpCgptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czQgPC0gbXV0YXRlKG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMyxMb0ZfNTBfQlBfUlVMRSA9IGlmZWxzZShncmVwbCgiNTBfQlBfUlVMRTpQQVNTIiwgTG9GX2luZm8pLCBUUlVFLCBpZmVsc2UoZ3JlcGwoIjUwX0JQX1JVTEU6RkFJTCIsIExvRl9pbmZvKSwgRkFMU0UsIE5BKSkpCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHM0IDwtIG11dGF0ZShtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHMzLExvRl81MF9CUF9SVUxFID0gaWZlbHNlKGdyZXBsKCI1MF9CUF9SVUxFOlBBU1MiLCBMb0ZfaW5mbyksIFRSVUUsIGlmZWxzZShncmVwbCgiNTBfQlBfUlVMRTpGQUlMIiwgTG9GX2luZm8pLCBGQUxTRSwgTkEpKSkKCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHM0IDwtIG11dGF0ZShtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzMyxMb0ZfNTBfQlBfUlVMRSA9IGlmZWxzZShncmVwbCgiNTBfQlBfUlVMRTpQQVNTIiwgTG9GX2luZm8pLCBUUlVFLCBpZmVsc2UoZ3JlcGwoIjUwX0JQX1JVTEU6RkFJTCIsIExvRl9pbmZvKSwgRkFMU0UsIE5BKSkpCmBgYAoKSW1wb3J0IE5NRCBkZXBsZXRlZCBnZW5lIGxpc3QgYW5kIGFubm90YXRlIHZhcmlhbnRzIGFjY29yZGluZ2x5CmBgYHtyfQpOTURfZGVwbGV0ZWRfZ2VuZV9saXN0IDwtIHJlYWQuY3N2KCJOTURfZGVwbGV0ZWRfZ2VuZV9saXN0LmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpICU+JSAKICBkcGx5cjo6cmVuYW1lKCJTWU1CT0wiID0gZ2VuZSkgJT4lIAogIGRwbHlyOjpyZW5hbWUoIkZlYXR1cmUiID0gdHhuYW1lcykgJT4lIAogIGRwbHlyOjpyZW5hbWUoIk5NRF9wcmVkaWN0b3JfcmFuayIgPSBtaW4ucmFuaykKCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHM1IDwtIGxlZnRfam9pbihtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzNCwgTk1EX2RlcGxldGVkX2dlbmVfbGlzdFssYygyOjMpXSxieT0iRmVhdHVyZSIsY29weT1GQUxTRSkgCm1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzNSA8LSBsZWZ0X2pvaW4obWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHM0LCBOTURfZGVwbGV0ZWRfZ2VuZV9saXN0WyxjKDE6MyldLGJ5PSJTWU1CT0wiLGNvcHk9RkFMU0UpIAoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzNSA8LSBsZWZ0X2pvaW4obWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzNCwgTk1EX2RlcGxldGVkX2dlbmVfbGlzdFssYygyOjMpXSxieT0iRmVhdHVyZSIsY29weT1GQUxTRSkgCm1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHM1IDwtIGxlZnRfam9pbihtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzNCwgTk1EX2RlcGxldGVkX2dlbmVfbGlzdFssYygxOjMpXSxieT0iU1lNQk9MIixjb3B5PUZBTFNFKSAKYGBgCgpSZW1vdmUgcmVkdW5kYW50IG9iamVjdHMgYW5kIG91dHB1dCBkYXRhCmBgYHtyfQpybShsaXN0PShscyhwYXR0ZXJuPSJeZ2VuZXMiKSkpCnJtKGxpc3Q9KGxzKHBhdHRlcm49Il52YXJpYW50cyIpKSkKcm0obGlzdD0obHMocGF0dGVybj0iXmZpc2hlcnJlc3VsdHMiKSkpCgp3cml0ZV9leGNlbF9jc3YobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czUscGF0aD0ibWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxLmNzdiIsbmE9Ii4iLGFwcGVuZD1GQUxTRSxjb2xfbmFtZXM9VFJVRSkKCnNlbGVjdChtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzNSxTWU1CT0wsR2VuZSxQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUpICU+JSAKICBhcnJhbmdlKFBfdmFsdWVfRmlzaGVyXzAuMDA1X05GRSkgJT4lIAogIHVuaXF1ZSgpICU+JSAKICB3cml0ZV90c3YocGF0aD0iRkh4X0hJR0hfRU5TVGNhbm9uaWNhbF9CSF9wX3ZhbHVlcy50c3YiKQoKd3JpdGVfZXhjZWxfY3N2KG1hc3RlcmZpbGVfZW9jX0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzNSxwYXRoPSJtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxLmNzdiIsbmE9Ii4iLGFwcGVuZD1GQUxTRSxjb2xfbmFtZXM9VFJVRSkKCnNlbGVjdChtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czUsU1lNQk9MLEdlbmUsUF92YWx1ZV9GaXNoZXJfMC4wMDVfTkZFKSAlPiUgCiAgYXJyYW5nZShQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUpICU+JSAKICB1bmlxdWUoKSAlPiUgCiAgd3JpdGVfdHN2KHBhdGg9IkZIeF9ISUdIX05NY2Fub25pY2FsX0JIX3BfdmFsdWVzLnRzdiIpCgp3cml0ZV9leGNlbF9jc3YobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzNSxwYXRoPSJtYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMS5jc3YiLG5hPSIuIixhcHBlbmQ9RkFMU0UsY29sX25hbWVzPVRSVUUpCgpzZWxlY3QobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzNSxTWU1CT0wsR2VuZSxQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUpICU+JSAKICBhcnJhbmdlKFBfdmFsdWVfRmlzaGVyXzAuMDA1X05GRSkgJT4lIAogIHVuaXF1ZSgpICU+JSAKICB3cml0ZV90c3YocGF0aD0iRkh4X0hJR0hfRU5TVGNhbm9uaWNhbF9CSF9wX3ZhbHVlcy50c3YiKQoKd3JpdGVfZXhjZWxfY3N2KG1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV93aXRoR25vbUFEc3RhdHNfcmF0aW9zX2Zpc2hlcnJlc3VsdHM1LHBhdGg9Im1hc3RlcmZpbGVfZW9jX25vRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMS5jc3YiLG5hPSIuIixhcHBlbmQ9RkFMU0UsY29sX25hbWVzPVRSVUUpCgpzZWxlY3QobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czUsU1lNQk9MLEdlbmUsUF92YWx1ZV9GaXNoZXJfMC4wMDVfTkZFKSAlPiUgCiAgYXJyYW5nZShQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUpICU+JSAKICB1bmlxdWUoKSAlPiUgCiAgd3JpdGVfdHN2KHBhdGg9IkZIeF9ISUdIX05NY2Fub25pY2FsX0JIX3BfdmFsdWVzLnRzdiIpCmBgYAoKQ2FsY3VsYXRlIHRvdGFsIExvRiB2YXJpYW50cyBpbiBzYW1wbGUgdnMgdG90YWwgTG9GIHZhcmlhbnRzIGluIEdub21BRCBub24tY2FuY2VyIE5GRSBhbmQgdXNlIGZvciBjaGktc3F1YXJlZCB0ZXN0CmBgYHtyfQpvZGRzcmF0aW8gPC0gZnVuY3Rpb24gKGEsIGIgPSBOVUxMLCBjID0gTlVMTCwgZCA9IE5VTEwsIGNvbmYubGV2ZWwgPSAwLjk1LCAKICAgIHAuY2FsYy5ieS5pbmRlcGVuZGVuY2UgPSBUUlVFKSAKewogICAgaWYgKGlzLm1hdHJpeChhKSkgewogICAgICAgIGlmICgoZGltKGEpWzFdICE9IDJMKSB8IChkaW0oYSlbMl0gIT0gMkwpKSB7CiAgICAgICAgICAgIHN0b3AoIklucHV0IG1hdHJpeCBtdXN0IGJlIGEgMngyIHRhYmxlLiIpCiAgICAgICAgfQogICAgICAgIC5hIDwtIGFbMSwgMV0KICAgICAgICAuYiA8LSBhWzEsIDJdCiAgICAgICAgLmMgPC0gYVsyLCAxXQogICAgICAgIC5kIDwtIGFbMiwgMl0KICAgICAgICAuZGF0YS5uYW1lIDwtIGRlcGFyc2Uoc3Vic3RpdHV0ZShhKSkKICAgIH0KICAgIGVsc2UgewogICAgICAgIC5hIDwtIGEKICAgICAgICAuYiA8LSBiCiAgICAgICAgLmMgPC0gYwogICAgICAgIC5kIDwtIGQKICAgICAgICAuZGF0YS5uYW1lIDwtIHBhc3RlKGRlcGFyc2Uoc3Vic3RpdHV0ZShhKSksIGRlcGFyc2Uoc3Vic3RpdHV0ZShiKSksIAogICAgICAgICAgICBkZXBhcnNlKHN1YnN0aXR1dGUoYykpLCBkZXBhcnNlKHN1YnN0aXR1dGUoZCkpKQogICAgfQogICAgLk1BVCA8LSBtYXRyaXgoYyguYSwgLmIsIE0xIDwtIC5hICsgLmIsIC5jLCAuZCwgTTAgPC0gLmMgKyAKICAgICAgICAuZCwgTjEgPC0gLmEgKyAuYywgTjAgPC0gLmIgKyAuZCwgVG90YWwgPC0gLmEgKyAuYiArIAogICAgICAgIC5jICsgLmQpLCAzLCAzKQogICAgY29sbmFtZXMoLk1BVCkgPC0gYygiU2FtcGxlIiwgIkdub21BRCIsICJUb3RhbCIpICMoIkRpc2Vhc2UiLCAiTm9uZGlzZWFzZSIsICJUb3RhbCIpCiAgICByb3duYW1lcyguTUFUKSA8LSBjKCJMb0YiLCAiTm8gTG9GIiwgIlRvdGFsIikgIygiRXhwb3NlZCIsICJOb25leHBvc2VkIiwgIlRvdGFsIikKICAgIGNsYXNzKC5NQVQpIDwtICJ0YWJsZSIKICAgIHByaW50KC5NQVQpCiAgICBFU1RJTUFURSA8LSAoLmEgLy5iKS8oLmMvLmQpCiAgICBub3JtLnBwIDwtIHFub3JtKDEgLSAoMSAtIGNvbmYubGV2ZWwpLzIpCiAgICBpZiAocC5jYWxjLmJ5LmluZGVwZW5kZW5jZSkgewogICAgICAgIHAudiA8LSAyICogKDEgLSBwbm9ybShhYnMoKC5hIC0gTjEgKiBNMS9Ub3RhbCkvc3FydChOMSAqIAogICAgICAgICAgICBOMCAqIE0xICogTTAvVG90YWwvVG90YWwvKFRvdGFsIC0gMSkpKSkpCiAgICB9CiAgICBlbHNlIHsKICAgICAgICBwLnYgPC0gMiAqICgxIC0gcG5vcm0obG9nKGlmZWxzZShFU1RJTUFURSA+IDEsIEVTVElNQVRFLCAKICAgICAgICAgICAgMS9FU1RJTUFURSkpL3NxcnQoMS8uYSArIDEvLmIgKyAxLy5jICsgMS8uZCkpKQogICAgfQogICAgT1JMIDwtIEVTVElNQVRFICogZXhwKC1ub3JtLnBwICogc3FydCgxLy5hICsgMS8uYiArIDEvLmMgKyAKICAgICAgICAxLy5kKSkKICAgIE9SVSA8LSBFU1RJTUFURSAqIGV4cChub3JtLnBwICogc3FydCgxLy5hICsgMS8uYiArIDEvLmMgKyAKICAgICAgICAxLy5kKSkgJT4lIHNpZ25pZihkaWdpdHM9NykKICAgIENJTlQgPC0gcGFzdGUoc2lnbmlmKE9STCxkaWdpdHMgPSA3KSxzaWduaWYoT1JVLGRpZ2l0cyA9IDcpLHNlcD0ifiIpCiAgICBhdHRyKENJTlQsICJjb25mLmxldmVsIikgPC0gY29uZi5sZXZlbAogICAgUlZBTCA8LSBsaXN0KHAudmFsdWUgPSBwLnYsIGNvbmYuaW50ID0gQ0lOVCwgZXN0aW1hdGUgPSBFU1RJTUFURSwgCiAgICAgICAgbWV0aG9kID0gIk9kZHMgcmF0aW8gZXN0aW1hdGUgYW5kIGl0cyBzaWduaWZpY2FuY2UgcHJvYmFiaWxpdHkiLCAKICAgICAgICBkYXRhLm5hbWUgPSAuZGF0YS5uYW1lKQogICAgY2xhc3MoUlZBTCkgPC0gImh0ZXN0IgogICAgcmV0dXJuKFJWQUwpCn0KCmEgPC0gc3VtKHZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcyRUb3RhbF9HZW5lX0NvdW50KSAlPiUgYXMubnVtZXJpYygpCmIgPC0gVG90YWxfU2FtcGxlX0FsbGVsZXNfRkh4Kihucm93KGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3QpKSAlPiUgYXMubnVtZXJpYygpCmIxIDwtIGItYSAlPiUgYXMubnVtZXJpYygpCmMgPC0gc3VtKHZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcyRGSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUNfMC4wMDUpICU+JSBhcy5udW1lcmljKCkKZCA8LSAobWF4KHZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcyRNQVhfQU4pKSpucm93KGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3QpICU+JSBhcy5udW1lcmljKCkKZDEgPC0gZC1jICU+JSBhcy5udW1lcmljKCkKZSA8LSBzdW0odm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJEZJTFRFUl9SRl9MT0ZfSElHSElNUEFDVF9BQ18wLjAwNV9ORkUpICU+JSBhcy5udW1lcmljKCkKZiA8LSAobWF4KHZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcyRNQVhfQU5fTkZFKSkqbnJvdyhhbGxHZW5lc19BZ2lsZW50U1N2Nl9saXN0KSAlPiUgYXMubnVtZXJpYygpCmYxIDwtIGYtZSAlPiUgYXMubnVtZXJpYygpCgpnIDwtIHN1bSh2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRUb3RhbF9HZW5lX0NvdW50KSAlPiUgYXMubnVtZXJpYygpCmggPC0gVG90YWxfU2FtcGxlX0FsbGVsZXNfRkh4Kihucm93KGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3RfcHJvdGVpbl9jb2Rpbmdfb25seSkpICU+JSBhcy5udW1lcmljKCkKaDEgPC0gaC1nICU+JSBhcy5udW1lcmljKCkKaSA8LSBzdW0odm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMkRklMVEVSX1JGX0xPRl9ISUdISU1QQUNUX0FDXzAuMDA1KSAlPiUgYXMubnVtZXJpYygpCmogPC0gKG1heCh2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRNQVhfQU4pKSpucm93KGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3RfcHJvdGVpbl9jb2Rpbmdfb25seSkgJT4lIGFzLm51bWVyaWMoKQpqMSA8LSBqLWkgJT4lIGFzLm51bWVyaWMoKQprIDwtIHN1bSh2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRGSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUNfMC4wMDVfTkZFKSAlPiUgYXMubnVtZXJpYygpCmwgPC0gKG1heCh2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRNQVhfQU5fTkZFKSkqbnJvdyhhbGxHZW5lc19BZ2lsZW50U1N2Nl9saXN0X3Byb3RlaW5fY29kaW5nX29ubHkpICU+JSBhcy5udW1lcmljKCkKbDEgPC0gbC1rICU+JSBhcy5udW1lcmljKCkKCmNoaVgyXzAuMDA1X0ZIeCA8LSBtYXRyaXgoYyhhLGIxLGMsZDEpLG5yb3c9MixieXJvdz1UUlVFKQpjaGlYMl8wLjAwNV9ORkVfRkh4IDwtIG1hdHJpeChjKGEsYjEsZSxmMSksbnJvdz0yLGJ5cm93PVRSVUUpCmNoaVgyXzAuMDA1X2Jpb3R5cGVfRkh4IDwtIG1hdHJpeChjKGcsaDEsaSxqMSksbnJvdz0yLGJ5cm93PVRSVUUpCmNoaVgyXzAuMDA1X05GRV9iaW90eXBlX0ZIeCA8LSBtYXRyaXgoYyhnLGgxLGssbDEpLG5yb3c9MixieXJvdz1UUlVFKQoKbSA8LSBzdW0odm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMkVG90YWxfR2VuZV9Db3VudCkgJT4lIGFzLm51bWVyaWMoKQpuIDwtIFRvdGFsX1NhbXBsZV9BbGxlbGVzX25vRkh4Kihucm93KGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3QpKSAlPiUgYXMubnVtZXJpYygpCm4xIDwtIG4tbSAlPiUgYXMubnVtZXJpYygpCm8gPC0gc3VtKHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJEZJTFRFUl9SRl9MT0ZfSElHSElNUEFDVF9BQ18wLjAwNSkgJT4lIGFzLm51bWVyaWMoKQpwIDwtIChtYXgodm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMkTUFYX0FOKSkqbnJvdyhhbGxHZW5lc19BZ2lsZW50U1N2Nl9saXN0KSAlPiUgYXMubnVtZXJpYygpCnAxIDwtIHAtbyAlPiUgYXMubnVtZXJpYygpCnEgPC0gc3VtKHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJEZJTFRFUl9SRl9MT0ZfSElHSElNUEFDVF9BQ18wLjAwNV9ORkUpICU+JSBhcy5udW1lcmljKCkKciA8LSAobWF4KHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzJE1BWF9BTl9ORkUpKSpucm93KGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3QpICU+JSBhcy5udW1lcmljKCkKcjEgPC0gci1xICU+JSBhcy5udW1lcmljKCkKCnMgPC0gc3VtKHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMkVG90YWxfR2VuZV9Db3VudCkgJT4lIGFzLm51bWVyaWMoKQp0IDwtIFRvdGFsX1NhbXBsZV9BbGxlbGVzX25vRkh4Kihucm93KGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3RfcHJvdGVpbl9jb2Rpbmdfb25seSkpICU+JSBhcy5udW1lcmljKCkKdDEgPC0gdC1zICU+JSBhcy5udW1lcmljKCkKdSA8LSBzdW0odm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRGSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUNfMC4wMDUpICU+JSBhcy5udW1lcmljKCkKdiA8LSAobWF4KHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMkTUFYX0FOKSkqbnJvdyhhbGxHZW5lc19BZ2lsZW50U1N2Nl9saXN0X3Byb3RlaW5fY29kaW5nX29ubHkpICU+JSBhcy5udW1lcmljKCkKdjEgPC0gdi11ICU+JSBhcy5udW1lcmljKCkKdyA8LSBzdW0odm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lcyRGSUxURVJfUkZfTE9GX0hJR0hJTVBBQ1RfQUNfMC4wMDVfTkZFKSAlPiUgYXMubnVtZXJpYygpCnggPC0gKG1heCh2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzJE1BWF9BTl9ORkUpKSpucm93KGFsbEdlbmVzX0FnaWxlbnRTU3Y2X2xpc3RfcHJvdGVpbl9jb2Rpbmdfb25seSkgJT4lIGFzLm51bWVyaWMoKQp4MSA8LSB4LXcgJT4lIGFzLm51bWVyaWMoKQoKY2hpWDJfMC4wMDVfbm9GSHggPC0gbWF0cml4KGMobSxuMSxvLHAxKSxucm93PTIsYnlyb3c9VFJVRSkKY2hpWDJfMC4wMDVfTkZFX25vRkh4IDwtIG1hdHJpeChjKG0sbjEscSxyMSksbnJvdz0yLGJ5cm93PVRSVUUpCmNoaVgyXzAuMDA1X2Jpb3R5cGVfbm9GSHggPC0gbWF0cml4KGMocyx0MSx1LHYxKSxucm93PTIsYnlyb3c9VFJVRSkKY2hpWDJfMC4wMDVfTkZFX2Jpb3R5cGVfbm9GSHggPC0gbWF0cml4KGMocyx0MSx3LHgxKSxucm93PTIsYnlyb3c9VFJVRSkKCmNoaVgyXzAuMDA1X05GRV9GSHhfbm9GSHggPC0gbWF0cml4KGMoY2hpWDJfMC4wMDVfTkZFX0ZIeFsxLF0sY2hpWDJfMC4wMDVfTkZFX25vRkh4WzEsXSksbnJvdz0yLGJ5cm93PVRSVUUpCmNoaVgyXzAuMDA1X05GRV9iaW90eXBlX0ZIeF9ub0ZIeCA8LSBtYXRyaXgoYyhjaGlYMl8wLjAwNV9ORkVfYmlvdHlwZV9GSHhbMSxdLGNoaVgyXzAuMDA1X05GRV9iaW90eXBlX25vRkh4WzEsXSksbnJvdz0yLGJ5cm93PVRSVUUpCgpzZXR3ZCgifi9PbmVEcml2ZSAtIFRoZSBVbml2ZXJzaXR5IG9mIE1lbGJvdXJuZS9SIGRhdGEiKQpzaW5rKGZpbGU9Im1hc3RlcmZpbGVfZW9jX0xPRl92b2xjYW5vX2NoaVgyX3Jlc3VsdHMudHh0IixhcHBlbmQ9VFJVRSkKCmNoaXNxLnRlc3QoY2hpWDJfMC4wMDVfRkh4LGNvcnJlY3Q9RkFMU0UpCm9kZHNyYXRpbyhjaGlYMl8wLjAwNV9GSHgpCmNoaXNxLnRlc3QoY2hpWDJfMC4wMDVfTkZFX0ZIeCxjb3JyZWN0PUZBTFNFKQpvZGRzcmF0aW8oY2hpWDJfMC4wMDVfTkZFX0ZIeCkKY2hpc3EudGVzdChjaGlYMl8wLjAwNV9iaW90eXBlX0ZIeCxjb3JyZWN0PUZBTFNFKQpvZGRzcmF0aW8oY2hpWDJfMC4wMDVfYmlvdHlwZV9GSHgpCmNoaXNxLnRlc3QoY2hpWDJfMC4wMDVfTkZFX2Jpb3R5cGVfRkh4LGNvcnJlY3Q9RkFMU0UpCm9kZHNyYXRpbyhjaGlYMl8wLjAwNV9ORkVfYmlvdHlwZV9GSHgpCgpjaGlzcS50ZXN0KGNoaVgyXzAuMDA1X25vRkh4LGNvcnJlY3Q9RkFMU0UpCm9kZHNyYXRpbyhjaGlYMl8wLjAwNV9ub0ZIeCkKY2hpc3EudGVzdChjaGlYMl8wLjAwNV9ORkVfbm9GSHgsY29ycmVjdD1GQUxTRSkKb2Rkc3JhdGlvKGNoaVgyXzAuMDA1X05GRV9ub0ZIeCkKY2hpc3EudGVzdChjaGlYMl8wLjAwNV9iaW90eXBlX25vRkh4LGNvcnJlY3Q9RkFMU0UpCm9kZHNyYXRpbyhjaGlYMl8wLjAwNV9iaW90eXBlX25vRkh4KQpjaGlzcS50ZXN0KGNoaVgyXzAuMDA1X05GRV9iaW90eXBlX25vRkh4LGNvcnJlY3Q9RkFMU0UpCm9kZHNyYXRpbyhjaGlYMl8wLjAwNV9ORkVfYmlvdHlwZV9ub0ZIeCkKCmNoaXNxLnRlc3QoY2hpWDJfMC4wMDVfTkZFX0ZIeF9ub0ZIeCxjb3JyZWN0PUZBTFNFKQpjaGlzcS50ZXN0KGNoaVgyXzAuMDA1X05GRV9iaW90eXBlX0ZIeF9ub0ZIeCxjb3JyZWN0PUZBTFNFKQoKc2luaygpCmBgYAoKUmVtb3ZlIHZhcmlhbnRzIHdpdGggbm9uLXByb3RlaW4tY29kaW5nIGJpb3R5cGVzCmBgYHtyfQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZSA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czUsQklPVFlQRSVpbiVjKCJwcm90ZWluX2NvZGluZyIpKQoKbWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX05NY2Fub25pY2FsX3NhbXBsZUFGMC4wMV9iaW90eXBlIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czUsQklPVFlQRSVpbiVjKCJwcm90ZWluX2NvZGluZyIpKQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZSA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfd2l0aEdub21BRHN0YXRzX3JhdGlvc19maXNoZXJyZXN1bHRzNSxCSU9UWVBFJWluJWMoInByb3RlaW5fY29kaW5nIikpCgptYXN0ZXJmaWxlX2VvY19ub0ZIeF9nb29kUTJfSElHSF9OTWNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZSA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfTk1jYW5vbmljYWxfc2FtcGxlQUYwLjAxX3dpdGhHbm9tQURzdGF0c19yYXRpb3NfZmlzaGVycmVzdWx0czUsQklPVFlQRSVpbiVjKCJwcm90ZWluX2NvZGluZyIpKQpgYGAKCkNhbGN1bGF0ZSBudW1iZXIgb2YgcmV0YWluZWQgcHJvdGVpbi1jb2RpbmcgTG9GIHZhcmlhbnRzIHBlciBpbmRpdmlkdWFsIGluIEZIeC9ub0ZIeCBjb2hvcnRzLCBhbmQgb3V0cHV0IHJlc3VsdHMuCmBgYHtyfQptYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZV92YXJpYW50c1BlclBlcnNvbiA8LSBzZWxlY3QobWFzdGVyZmlsZV9lb2NfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX2Jpb3R5cGUsU2FtcGxlLENIUk9NLFBPUyxSRUYsQUxULFNhbXBsZS5HVCxTWU1CT0wsR2VuZSxGZWF0dXJlLEhHVlNjKQpzYW1wbGVzX0ZIeCA8LSBtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZV92YXJpYW50c1BlclBlcnNvblssMV0gJT4lIHVuaXF1ZSgpCnNhbXBsZXNfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfdmFyaWFudHNQZXJQZXJzb24gPC0gZGF0YS5mcmFtZShTYW1wbGU9ZmFjdG9yKCksTm9fb2ZfVmFyaWFudHM9ZG91YmxlKCkpCmZvcihzYW1wbGUgaW4gc2FtcGxlc19GSHgpewogIHNhbXBsZV9kYXRhIDwtIGZpbHRlcihtYXN0ZXJmaWxlX2VvY19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZV92YXJpYW50c1BlclBlcnNvbixTYW1wbGUlaW4lYyhzYW1wbGUpKQogIHNhbXBsZV92YXJpYW50cyA8LSB2YXJpYW50X2NvdW50c19BRnMoc2FtcGxlX2RhdGEsVG90YWxfU2FtcGxlX0FsbGVsZXNfRkh4KQogIG5vX29mX3ZhcmlhbnRzIDwtIHN1bShzYW1wbGVfdmFyaWFudHMkVG90YWxfQWxsZWxlX0NvdW50KQogIHNhbXBsZXNfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfdmFyaWFudHNQZXJQZXJzb24gPC0gYWRkX3JvdyhzYW1wbGVzX0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV9iaW90eXBlX3ZhcmlhbnRzUGVyUGVyc29uLFNhbXBsZT1zYW1wbGUsTm9fb2ZfVmFyaWFudHM9bm9fb2ZfdmFyaWFudHMpCn0Kd3JpdGVfdHN2KHNhbXBsZXNfRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfdmFyaWFudHNQZXJQZXJzb24scGF0aD0ic2FtcGxlc19GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZV92YXJpYW50c1BlclBlcnNvbi50c3YiKQoKbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZV92YXJpYW50c1BlclBlcnNvbiA8LSBzZWxlY3QobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZSxTYW1wbGUsQ0hST00sUE9TLFJFRixBTFQsU2FtcGxlLkdULFNZTUJPTCxHZW5lLEZlYXR1cmUsSEdWU2MpCnNhbXBsZXNfbm9GSHggPC0gbWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZV92YXJpYW50c1BlclBlcnNvblssMV0gJT4lIHVuaXF1ZSgpCnNhbXBsZXNfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZV92YXJpYW50c1BlclBlcnNvbiA8LSBkYXRhLmZyYW1lKFNhbXBsZT1mYWN0b3IoKSxOb19vZl9WYXJpYW50cz1kb3VibGUoKSkKZm9yKHNhbXBsZSBpbiBzYW1wbGVzX25vRkh4KXsKICBzYW1wbGVfZGF0YSA8LSBmaWx0ZXIobWFzdGVyZmlsZV9lb2Nfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZV92YXJpYW50c1BlclBlcnNvbixTYW1wbGUlaW4lYyhzYW1wbGUpKQogIHNhbXBsZV92YXJpYW50cyA8LSB2YXJpYW50X2NvdW50c19BRnMoc2FtcGxlX2RhdGEsVG90YWxfU2FtcGxlX0FsbGVsZXNfbm9GSHgpCiAgbm9fb2ZfdmFyaWFudHMgPC0gc3VtKHNhbXBsZV92YXJpYW50cyRUb3RhbF9BbGxlbGVfQ291bnQpCiAgc2FtcGxlc19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV9iaW90eXBlX3ZhcmlhbnRzUGVyUGVyc29uIDwtIGFkZF9yb3coc2FtcGxlc19ub0ZIeF9nb29kUTJfSElHSF9FTlNUY2Fub25pY2FsX3NhbXBsZUFGMC4wMV9iaW90eXBlX3ZhcmlhbnRzUGVyUGVyc29uLFNhbXBsZT1zYW1wbGUsTm9fb2ZfVmFyaWFudHM9bm9fb2ZfdmFyaWFudHMpCn0Kd3JpdGVfdHN2KHNhbXBsZXNfbm9GSHhfZ29vZFEyX0hJR0hfRU5TVGNhbm9uaWNhbF9zYW1wbGVBRjAuMDFfYmlvdHlwZV92YXJpYW50c1BlclBlcnNvbixwYXRoPSJzYW1wbGVzX25vRkh4X2dvb2RRMl9ISUdIX0VOU1RjYW5vbmljYWxfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfdmFyaWFudHNQZXJQZXJzb24udHN2IikKYGBgCgpPdXRwdXQgZGF0YSBmb3IgbG9nIHAtdmFsdWUgdm9sY2FubyBwbG90cwpgYGB7cn0Kdm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzMiA8LSBtdXRhdGUodm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzLCJMb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRSIgPSBsb2cxMChQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUpKSAlPiUgCiAgYXJyYW5nZShkZXNjKE9SXzAuMDA1X05GRSkpICU+JSAKICBtdXRhdGUoIlBsb3R0ZWRfTG9nMTBfUC12YWx1ZV9GaXNoZXJfMC4wNV9ORkUiPSAKICBpZl9lbHNlIChPUl8wLjAwNV9ORkU+PTEsIGBMb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRWAqLTEsIGBMb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRWAsIG1pc3Npbmc9TlVMTCkpICU+JSAKICBhcnJhbmdlKGRlc2MoYFBsb3R0ZWRfTG9nMTBfUC12YWx1ZV9GaXNoZXJfMC4wNV9ORkVgKSxkZXNjKE9SXzAuMDA1X05GRSkpICU+JSAKICB3cml0ZV9leGNlbF9jc3YocGF0aD0idm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzX3Y2LmNzdiIsbmE9Ii4iLGFwcGVuZD1GQUxTRSxjb2xfbmFtZXM9VFJVRSkKCnZvbGNhbm9fRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzMiA8LSBtdXRhdGUodm9sY2Fub19GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMsIkxvZzEwX1AtdmFsdWVfRmlzaGVyXzAuMDVfTkZFIiA9IGxvZzEwKFBfdmFsdWVfRmlzaGVyXzAuMDA1X05GRSkpICU+JSAKICBhcnJhbmdlKGRlc2MoT1JfMC4wMDVfTkZFKSkgJT4lIAogIG11dGF0ZSgiUGxvdHRlZF9Mb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRSI9IAogIGlmX2Vsc2UgKE9SXzAuMDA1X05GRT49MSwgYExvZzEwX1AtdmFsdWVfRmlzaGVyXzAuMDVfTkZFYCotMSwgYExvZzEwX1AtdmFsdWVfRmlzaGVyXzAuMDVfTkZFYCwgbWlzc2luZz1OVUxMKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhgUGxvdHRlZF9Mb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRWApLGRlc2MoT1JfMC4wMDVfTkZFKSkgJT4lIAogIHdyaXRlX2V4Y2VsX2NzdihwYXRoPSJ2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lc192Ni5jc3YiLG5hPSIuIixhcHBlbmQ9RkFMU0UsY29sX25hbWVzPVRSVUUpCgp2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZTJfYWxsR2VuZXMyIDwtIG11dGF0ZSh2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZTJfYWxsR2VuZXMsIkxvZzEwX1AtdmFsdWVfRmlzaGVyXzAuMDVfTkZFIiA9IGxvZzEwKFBfdmFsdWVfRmlzaGVyXzAuMDA1X05GRSkpICU+JSAKICBhcnJhbmdlKGRlc2MoT1JfMC4wMDVfTkZFKSkgJT4lIAogIG11dGF0ZSgiUGxvdHRlZF9Mb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRSI9IAogIGlmX2Vsc2UgKE9SXzAuMDA1X05GRT49MSwgYExvZzEwX1AtdmFsdWVfRmlzaGVyXzAuMDVfTkZFYCotMSwgYExvZzEwX1AtdmFsdWVfRmlzaGVyXzAuMDVfTkZFYCwgbWlzc2luZz1OVUxMKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhgUGxvdHRlZF9Mb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRWApLGRlc2MoT1JfMC4wMDVfTkZFKSkgJT4lIAogIHdyaXRlX2V4Y2VsX2NzdihwYXRoPSJ2b2xjYW5vX0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZTJfYWxsR2VuZXNfdjYuY3N2IixuYT0iLiIsYXBwZW5kPUZBTFNFLGNvbF9uYW1lcz1UUlVFKQoKdm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYWxsR2VuZXMyIDwtIG11dGF0ZSh2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9hbGxHZW5lcywiTG9nMTBfUC12YWx1ZV9GaXNoZXJfMC4wNV9ORkUiID0gbG9nMTAoUF92YWx1ZV9GaXNoZXJfMC4wMDVfTkZFKSkgJT4lIAogIGFycmFuZ2UoZGVzYyhPUl8wLjAwNV9ORkUpKSAlPiUgCiAgbXV0YXRlKCJQbG90dGVkX0xvZzEwX1AtdmFsdWVfRmlzaGVyXzAuMDVfTkZFIj0gCiAgaWZfZWxzZSAoT1JfMC4wMDVfTkZFPj0xLCBgTG9nMTBfUC12YWx1ZV9GaXNoZXJfMC4wNV9ORkVgKi0xLCBgTG9nMTBfUC12YWx1ZV9GaXNoZXJfMC4wNV9ORkVgLCBtaXNzaW5nPU5VTEwpKSAlPiUgCiAgYXJyYW5nZShkZXNjKGBQbG90dGVkX0xvZzEwX1AtdmFsdWVfRmlzaGVyXzAuMDVfTkZFYCksZGVzYyhPUl8wLjAwNV9ORkUpKSAlPiUgCiAgd3JpdGVfZXhjZWxfY3N2KHBhdGg9InZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2FsbEdlbmVzX3Y2LmNzdiIsbmE9Ii4iLGFwcGVuZD1GQUxTRSxjb2xfbmFtZXM9VFJVRSkKCnZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGVfYWxsR2VuZXMyIDwtIG11dGF0ZSh2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlX2FsbEdlbmVzLCJMb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRSIgPSBsb2cxMChQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUpKSAlPiUgCiAgYXJyYW5nZShkZXNjKE9SXzAuMDA1X05GRSkpICU+JSAKICBtdXRhdGUoIlBsb3R0ZWRfTG9nMTBfUC12YWx1ZV9GaXNoZXJfMC4wNV9ORkUiPSAKICBpZl9lbHNlIChPUl8wLjAwNV9ORkU+PTEsIGBMb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRWAqLTEsIGBMb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRWAsIG1pc3Npbmc9TlVMTCkpICU+JSAKICBhcnJhbmdlKGRlc2MoYFBsb3R0ZWRfTG9nMTBfUC12YWx1ZV9GaXNoZXJfMC4wNV9ORkVgKSxkZXNjKE9SXzAuMDA1X05GRSkpICU+JSAKICB3cml0ZV9leGNlbF9jc3YocGF0aD0idm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZV9hbGxHZW5lc192Ni5jc3YiLG5hPSIuIixhcHBlbmQ9RkFMU0UsY29sX25hbWVzPVRSVUUpCgp2b2xjYW5vX25vRkh4X3NhbXBsZUFGMC4wMV9iaW90eXBlMl9hbGxHZW5lczIgPC0gbXV0YXRlKHZvbGNhbm9fbm9GSHhfc2FtcGxlQUYwLjAxX2Jpb3R5cGUyX2FsbEdlbmVzLCJMb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRSIgPSBsb2cxMChQX3ZhbHVlX0Zpc2hlcl8wLjAwNV9ORkUpKSAlPiUgCiAgYXJyYW5nZShkZXNjKE9SXzAuMDA1X05GRSkpICU+JSAKICBtdXRhdGUoIlBsb3R0ZWRfTG9nMTBfUC12YWx1ZV9GaXNoZXJfMC4wNV9ORkUiPSAKICBpZl9lbHNlIChPUl8wLjAwNV9ORkU+PTEsIGBMb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRWAqLTEsIGBMb2cxMF9QLXZhbHVlX0Zpc2hlcl8wLjA1X05GRWAsIG1pc3Npbmc9TlVMTCkpICU+JSAKICBhcnJhbmdlKGRlc2MoYFBsb3R0ZWRfTG9nMTBfUC12YWx1ZV9GaXNoZXJfMC4wNV9ORkVgKSxkZXNjKE9SXzAuMDA1X05GRSkpICU+JSAKICB3cml0ZV9leGNlbF9jc3YocGF0aD0idm9sY2Fub19ub0ZIeF9zYW1wbGVBRjAuMDFfYmlvdHlwZTJfYWxsR2VuZXNfdjYuY3N2IixuYT0iLiIsYXBwZW5kPUZBTFNFLGNvbF9uYW1lcz1UUlVFKQpgYGA=