index.html

1 (Re) generate a set of shared gene IDs among species

The following is copied from xref.rmd from previous work.

Yeah I have no idea what I am doing with this, but here are the things Najib wants to cross reference: (In order of inclusion)

  • Orthology information from the 2005 Science paper
  • Signalp/GPI/Transmembrane data
  • Similarity/Orthology information to Homo at >=45% similarity
  • Secretome data from a paper provided by Saloe
  • (Future)L.major exosome data
  • Characterized Potential Host/Parasite Interactors (Peter Kima paper)
  • T.brucei essentiality data
  • L.major metabolic pathway daat

1.1 The orthology information from the TritrypDB

The tritrypdb maintains this type of data, found in the text downloadable data files. I have a perl script which parses these and dumps the resulting curated orthologies into tab delimited files.

I am going to use the tritrypdb master table as my starting point.

refdir = "/cbcb/lab/nelsayed/ref_data"
tritryp_master = read.csv(paste0(refdir, "/TriTrypDB_text/lmajor/lmajor_master.tab.xz"), sep="\t", header=TRUE)
tritryp_ortho = read.csv(paste0(refdir, "/TriTrypDB_text/lmajor/lmajor_ortho.txt.xz"), sep="\t", header=FALSE)
colnames(tritryp_ortho) = c("lmajor","num","ortho","strain","annotation","syntenic","comments")
tritryp_xrefs = tritryp_master[,c("ID","Product_Description","Gene_Name","X._TM_Domains","Ortholog_count","Paralog_count","Ortholog_Group","SignalP_Scores","SignalP_Peptide","UniProt_ID","Entrez_Gene_ID","Gene_Name_or_Symbol")]
dim(tritryp_xrefs)
## [1] 9378   12
tritryp_ortho_tb = subset(tritryp_ortho, strain == 'Trypanosoma brucei TREU927')
tritryp_ortho_tc = subset(tritryp_ortho, strain == 'Trypanosoma cruzi CL Brener Esmeraldo-like'| strain == 'Trypanosoma cruzi CL Brener Non-Esmeraldo-like')
tritryp_ortho_tb_combined = aggregate(ortho~lmajor, paste, collapse=",", data=tritryp_ortho_tb)
colnames(tritryp_ortho_tb_combined) = c("lmajor","tbrucei")
tritryp_ortho_tc_combined = aggregate(ortho~lmajor, paste, collapse=",", data=tritryp_ortho_tc)
colnames(tritryp_ortho_tc_combined) = c("lmajor","tcruzi")
tritryp_xrefs = merge(tritryp_xrefs, tritryp_ortho_tb_combined, by.x="ID", by.y="lmajor", all.x=TRUE)
tritryp_xrefs = merge(tritryp_xrefs, tritryp_ortho_tc_combined, by.x="ID", by.y="lmajor", all.x=TRUE)
dim(tritryp_xrefs)
## [1] 9378   14

2 Now add orthology from Science 2005

This data is found in supplemental table S1, which I copied to /cbcb/lab/nelsayed/ref_data/Science_2005/ This file looks like it will be difficult to work with, the first column is a gene identifier from each of the three main species – easy enough. The second column is a ‘secondary gene identifier’ and appears to me to be inconsistent. The third is a cluster identifier, unfortunately it too is inconsistent. The next column ‘COG type’, appears to be the best. Finally there is a predicted protein type which of course contains primarily the text ‘hypothetical’ or ‘amastin.’

science_2005 = read.csv("/cbcb/lab/nelsayed/ref_data/science_2005/1112181s_tableS1.txt", sep="\t", comment="#", header=TRUE)
colnames(science_2005) = c("primary_gene","secondary_gene","jaccard","cog_type","cog_id","gene_product")
science_agg = science_2005
science_agg = as.data.frame(lapply(science_agg, function(x) if(is.character(x)|is.factor(x)) gsub("\\*new gene in LmjF.v5.0\\*","lmundef",x) else x))
science_agg = as.data.frame(lapply(science_agg, function(x) if(is.character(x)|is.factor(x)) gsub("\\* new gene in LmjF.v5.0\\*","lmundef",x) else x))
science_agg = as.data.frame(lapply(science_agg, function(x) if(is.character(x)|is.factor(x)) gsub("\\*new gene in TcBr.v4.0\\*","tcundef",x) else x))
science_agg = as.data.frame(lapply(science_agg, function(x) if(is.character(x)|is.factor(x)) gsub("\\*new gene in Tb927.v4.0\\*","tbundef",x) else x))
science_agg$cog = science_agg$cog_id
science_agg$cog = ifelse(science_agg$cog == "lmundef", as.character(paste0('nocog', science_agg$primary_gene)), as.character(science_agg$cog_id))
science_agg$cog = ifelse(science_agg$cog == '', as.character(paste0('nocog', science_agg$primary_gene)), as.character(science_agg$cog_id))
science_agg$cog = ifelse(science_agg$cog == "", as.character(paste0('nocog', science_agg$primary_gene)), as.character(science_agg$cog_id))
length(levels(as.factor(science_agg$cog)))
## [1] 7176
science_agg$cog = ifelse(science_agg$cog == "", as.character(paste0('nocog', science_agg$primary_gene)), as.character(science_agg$cog_id))
length(levels(as.factor(science_agg$cog)))
## [1] 16802
science_lmcogs = science_agg[grep("^Lm", science_agg$primary_gene, perl=TRUE),]
science_lmcogs = science_lmcogs[,c("primary_gene","cog")]
science_aggregated = aggregate(primary_gene~cog, paste, collapse=",", data=science_agg)
science_merged = merge(science_lmcogs, science_aggregated, by.x="cog", by.y="cog", all.x=TRUE)
science_merged = merge(science_merged, science_agg, by.x="primary_gene.x", by.y="primary_gene")
colnames(science_merged) = c("ID","cog","genes","secondary_gene","jaccard","cog_type","cog_id","gene_product","cog_again")
science_merged = science_merged[-9]  ## Drop the duplicate column
science_merged$ID = gsub("LmjF", "LmjF\\.", science_merged$ID)
science_merged$genes = gsub("LmjF", "LmjF\\.", science_merged$genes)
science_merged$genes = gsub("Tb", "Tb927\\.", science_merged$genes)

2.1 Bring together the tritrypdb and science 2005 tables

This stanza marks the place where the first two tables are joined.

head(science_merged)
##             ID              cog
## 1 LmjF.01.0010 nocogLmjF01.0010
## 2 LmjF.01.0020    20332099_cogs
## 3 LmjF.01.0030    19584616_cogs
## 4 LmjF.01.0040 nocogLmjF01.0040
## 5 LmjF.01.0050 nocogLmjF01.0050
## 6 LmjF.01.0060    21566042_cogs
##                                                                         genes
## 1                                                                LmjF.01.0010
## 2 Tc00.1047053506895.50,Tc00.1047053508501.300,LmjF.01.0020,Tb927.09.160.2280
## 3 Tc00.1047053506895.40,Tc00.1047053508501.290,LmjF.01.0030,Tb927.09.160.2260
## 4                                                                LmjF.01.0040
## 5                                                                LmjF.01.0050
## 6 Tc00.1047053506895.30,Tc00.1047053508501.280,LmjF.01.0060,Tb927.09.160.2250
##   secondary_gene jaccard             cog_type        cog_id
## 1                                   singleton
## 2                        3-way COG [Lm+Tb+Tc] 20332099_cogs
## 3                        3-way COG [Lm+Tb+Tc] 19584616_cogs
## 4                                   singleton
## 5                                   singleton
## 6                        3-way COG [Lm+Tb+Tc] 21566042_cogs
##                             gene_product
## 1 hypothetical protein, unknown function
## 2        hypothetical protein, conserved
## 3            MCAK-like kinesin, putative
## 4 hypothetical protein, unknown function
## 5                  carboxylase, putative
## 6        hypothetical protein, conserved
dim(science_merged)
## [1] 8299    8
head(tritryp_xrefs)
##             ID                    Product_Description Gene_Name X._TM_Domains
## 1 LmjF.01.0010 hypothetical protein, unknown function      null             2
## 2 LmjF.01.0020        hypothetical protein, conserved      null             0
## 3 LmjF.01.0030            MCAK-like kinesin, putative      null             0
## 4 LmjF.01.0040 hypothetical protein, unknown function      null             0
## 5 LmjF.01.0050                  carboxylase, putative      null             0
## 6 LmjF.01.0060        hypothetical protein, conserved      null             0
##   Ortholog_count Paralog_count Ortholog_Group SignalP_Scores SignalP_Peptide UniProt_ID
## 1              9             0     OG5_183100         NN Sum             HMM       null
## 2             21             0     OG5_148223           null            null       null
## 3             43             1     OG5_127200           null            null       null
## 4              7             0     OG5_183101         NN Sum             HMM       null
## 5             32             1     OG5_126626           null            null       null
## 6             17             0     OG5_148224         NN Sum             HMM       null
##   Entrez_Gene_ID Gene_Name_or_Symbol                    tbrucei
## 1           null                null                       <NA>
## 2           null                null               Tb927.9.3670
## 3           null                null Tb927.11.3280,Tb927.9.3650
## 4           null                null                       <NA>
## 5           null                null  Tb927.4.5350,Tb927.8.6970
## 6           null                null               Tb927.9.3640
##                                                             tcruzi
## 1                                                             <NA>
## 2                                 TcCLB.506895.50,TcCLB.508501.300
## 3 TcCLB.506895.40,TcCLB.509589.30,TcCLB.503999.20,TcCLB.508501.290
## 4                                                             <NA>
## 5                                  TcCLB.504835.20,TcCLB.509913.10
## 6                                 TcCLB.506895.30,TcCLB.508501.280
dim(tritryp_xrefs)
## [1] 9378   14
tri_sci = merge(science_merged, tritryp_xrefs, by.x="ID", by.y="ID", all.y=TRUE)

original_columns = c("ID","science_cog","science_genes","science_sec_gene","science_jaccard","science_cog_type","science_cog_id","science_gene_product")
new_columns = c("tritryp_description","tritryp_gene_name","tritryp_tm_domains","tritryp_ortholog_count","tritryp_paralog_count","tritryp_ortholog_group","tritryp_signalp_score","tritryp_signalp_peptide","tritryp_uniprot","tritryp_entrez_geneid","tritryp_gene_symbol","tritryp_brucei_homologs","tritryp_cruzi_homologs")
all_columns = c(original_columns, new_columns)
colnames(tri_sci) = all_columns
dim(tri_sci)
## [1] 9378   21

2.2 Read in my run of signalp 4.1

signalp_data = read.csv(file="reference/lmajor_signalp_cleavage.gff", sep="\t", header=TRUE, comment="#")
signalp_data = signalp_data[,c("sequence.name","end","score","source")]
colnames(signalp_data) = c("ID","end","score","source")
dim(tri_sci)
## [1] 9378   21
dim(signalp_data)
## [1] 840   4
tri_sci_sig = merge(tri_sci, signalp_data, by.x="ID", by.y="ID", all.x=TRUE)
dim(tri_sci_sig)
## [1] 9378   24
koh_data = read.csv(file="reference/koh.txt", sep=" ", header=FALSE)
colnames(koh_data) = c("ID","koh_score")
tri_sci_sig = merge(tri_sci_sig, koh_data, by.x="ID", by.y="ID", all.x=TRUE)

new_columns = c("signalp_end","signalp_score","signalp_version", "koh_score")
all_columns = c(all_columns, new_columns)
colnames(tri_sci_sig) = all_columns

2.3 Read in ggsearch36 using lmajor query and human library.

I specify query/library because I have a reciprocal search. Also, I am using the UCSC known peptides, which have a separate file to cross reference them to the ENSG identifiers, so I will need to merge across both files.

pepnames = read.csv("reference/knownGene.txt.gz", sep="\t", header=FALSE)
colnames(pepnames) = c("ID","chr","strand","start","end","start2","start3","num","exons","exons2","q","UCSC")
fasta_search = read.csv("reference/lmajor_vs_hsapiens.out.table", sep="\t", header=TRUE)
fasta_pepnames = merge(pepnames, fasta_search, by.x="ID", by.y="Hit.ID")
fasta_pepnames = fasta_pepnames[,c("UCSC","Query.Name","Query.length","Hit.Length","Score","E","Identity","Hit.length","Hit.Matches")]
fasta_pepnames$Query.Name = make.names(fasta_pepnames$Query.Name, unique=TRUE)
tri_sci_sig_fas = merge(tri_sci_sig, fasta_pepnames, by.x="ID", by.y="Query.Name", all.x=TRUE)

new_columns = c("fasta_ucsc_id","fasta_query_length","fasta_libhit_length","fasta_score","fasta_e","fasta_identity","fasta_hit_length","fasta_hit_matches")
all_columns = c(all_columns, new_columns)
colnames(tri_sci_sig_fas) = all_columns
##write_xls(data=tri_sci_sig_fas, file="merged_tables")

2.4 Merge in secretome data and the communication paper data

## This is from Table S3 of:
## "An exosome-based secretion pathway is responsible for protein export from Leishmania and communication with macrophages."
## http://jcs.biologists.org/content/123/6/842.short
secretome = read.csv("reference/secretome.csv", header=TRUE)
colnames(secretome) = c("ID","name","exosome","secretome")
secretome$ID = gsub(pattern="LmjF", replacement="LmjF\\.", x=secretome$ID)
tri_sci_sig_fas_sec = merge(tri_sci_sig_fas, secretome, by.x="ID", by.y="ID", all.x=TRUE)

## This comma separated file was extracted from table S4 from:
## http://www.genomebiology.com/2008/9/2/R35/additional
## "Proteomic analysis of the secretome of Leishmania donovani"
communication = read.csv("reference/communication.csv", header=TRUE)
colnames(communication) = c("ID","communication_name", "ms_gpi")
tri_sci_sig_fas_sec = merge(tri_sci_sig_fas_sec, communication, by.x="ID", by.y="ID", all.x=TRUE)

## The following table came from Supplementary 5 in
## http://www.genomebiology.com/2008/9/2/R35
## "Proteomic analysis of the secretome of Leishmania donovani"
donovani_cmca_ratio = read.csv("reference/proteomic_analysis_secretome_donovani_s5.csv", header=TRUE)
## The following comes from table S2 from the same paper
donovani_s2 = read.csv("reference/gb-2008-9-2-r35-s2.csv", header=TRUE)
colnames(donovani_s2) = c("accession","id","meanlmmcmca1","rel_pep_ratio1","meanlmmcmca2","rel_pep_ratio2","meanlmmcmca3","rel_pep_ratio3","meanlmmcmca4","rel_pep_ratio4","meanlmmcmca_all")

##write_xls(data=donovani_s2, file="donovani_s2_table")

##dim(subset(donovani_s2, meanlmcmca_all > 1.7))
head(donovani_s2)
##     accession                                                    id meanlmmcmca1
## 1 LmjF14.1360                     myo-inositol-1-phosphate synthase       3.0297
## 2 LmjF23.0200                endoribonuclease L-PSP (pb5), putative       1.2585
## 3 LmjF15.1203                       60S acidic ribosomal protein P2           NA
## 4 LmjF35.2420            phosphoinositide-binding protein, putative           NA
## 5 LmjF16.0140 eukaryotic translation initiation factor 1A, putative           NA
## 6 LmjF32.2180                       hypothetical protein, conserved       0.7839
##   rel_pep_ratio1 meanlmmcmca2 rel_pep_ratio2 meanlmmcmca3 rel_pep_ratio3 meanlmmcmca4
## 1         454.31        3.077          101.2        6.500         319.11       3.1091
## 2           0.00           NA            0.0        7.122         308.26       3.3414
## 3           0.00        2.695          163.5        6.020          91.37       2.4791
## 4           0.00        4.264          798.9        5.273           0.00       0.9933
## 5           0.00        3.257          138.9        5.509          96.61       1.0225
## 6          91.71        2.749          419.4        5.710           0.00           NA
##   rel_pep_ratio4 meanlmmcmca_all
## 1         183.26           3.929
## 2         328.36           3.907
## 3         156.92           3.731
## 4          12.14           3.510
## 5           0.00           3.263
## 6          23.26           3.081
donovani_s2$accession = gsub(pattern="LmjF", replacement="LmjF\\.", x=donovani_s2$accession)
tri_sci_sig_fas_sec = merge(tri_sci_sig_fas_sec, donovani_s2, by.x="ID", by.y="accession", all.x=TRUE)

## The following table comes from 10.1371/journal.pntd.0000842
## PLoS Negl Trop Dis. 2010 Oct; 4(10): e842
## It is table 1 from: Leishmania effector molecules identified by CMAT.
## It required a small amount of manual playing to make into a usable csv
kima = read.csv("reference/kima_table.csv")
tri_sci_sig_fas_sec = merge(tri_sci_sig_fas_sec, kima, by.x="ID", by.y="name", all.x=TRUE)

new_columns = c("secretome_name","secretome_exosome_boolean","secretome_boolean","communication_name","communication_hit_type","lds2_id","lds2_lmmcma1","lds2_relpepratio1","lds2_lmmcma2","lds2_relpepratio2","lds2_lmmcma3","lds2_relpepratio3","lds2_lmmcma4","lds2_relpepratio4","lds2_meanlmmcma","kima_clone","kima_homolog","kima_chromosome","kima_signal","kima_comment")
all_columns = c(all_columns, new_columns)
colnames(tri_sci_sig_fas_sec) = all_columns

2.5 Merge in RNASeq data

rnaseq_human_mouse = read.csv("csv/geneID_Lmajor_human_mouse_DEbothup_metac_amast4.txt", header=FALSE)
rnaseq_human_mouse$rnaseq_hsmmup = 1
rnaseq_fourhpi = read.csv("csv/TableS7-4hpi.csv", header=TRUE)

tri_sci_sig_fas_sec_rna = merge(tri_sci_sig_fas_sec, rnaseq_human_mouse, by.x="ID", by.y="V1", all.x=TRUE)
tri_sci_sig_fas_sec_rna = merge(tri_sci_sig_fas_sec_rna, rnaseq_fourhpi, by.x="ID", by.y="ID", all.x=TRUE)

new_columns = c("rnaseq_hsmmup","rnaseq_4hpidesc","rnaseq_4hpifc","rnaseq_4hpipval","rnaseq_4hpipregofun","rnaseq_4hpipredgoproc")
all_columns = c(all_columns, new_columns)
colnames(tri_sci_sig_fas_sec_rna) = all_columns
tri_sci_sig_fas_sec_rna$rnaseq_hsmmup[is.na(tri_sci_sig_fas_sec_rna$rnaseq_hsmmup)] = 0

##write_xls(data=merged_de, file="merged")

2.6 Merge in re-analyzed RNASeq data

Since I do not have the number of genes alone for brucei/cruzi, I will cheat and subtract the number observed from the size of the two genomes and assume that is correct (it probably is not).

library(TxDb.Lmajor.friedlin.TriTrypDB27)
library(org.Lmajor.friedlin.eg.db)
library(Leishmania.major.Friedlin)
summary(genes(Leishmania.major.Friedlin))
## [1] "GRanges object with 9377 ranges and 1 metadata column"
## 9377

library(TxDb.Tbrucei.TREU927.TriTrypDB27)
library(org.Tbrucei.TREU927.eg.db)
library(Trypanosoma.brucei.treu927)
summary(genes(Trypanosoma.brucei.treu927))
## [1] "GRanges object with 12093 ranges and 1 metadata column"
## 12093

library(TxDb.Tcruzi.CLBrenerEsmeraldo.TriTrypDB27)
library(org.Tcruzi.CLBrenerEsmeraldo.eg.db)
library(Trypanosoma.cruzi.CLBrener.Esmeraldo)
## 10597
summary(genes(Trypanosoma.cruzi.CLBrener.Esmeraldo))
## [1] "GRanges object with 10597 ranges and 1 metadata column"
rnaseq <- read.csv("csv/lmajor_metac_vs_amast4.csv")
head(rnaseq)
##                X  logFC AveExpr      t   P.Value adj.P.Val     B fold_change
## 1 LmjF.19.1530-1  1.480   8.453  14.50 8.359e-14 3.599e-10 21.44      2.7899
## 2 LmjF.26.0640-1  1.822   7.266  14.49 8.488e-14 3.599e-10 21.31      3.5367
## 3 LmjF.36.2030-1  1.387   8.786  11.68 1.026e-11 1.822e-08 16.86      2.6156
## 4 LmjF.26.0620-1  1.472   7.271  11.69 1.007e-11 1.822e-08 16.83      2.7732
## 5 LmjF.17.0890-1 -1.745   6.556 -11.65 1.074e-11 1.822e-08 16.75      0.2984
## 6 LmjF.17.0020-1  2.154   8.166  11.51 1.414e-11 1.998e-08 16.53      4.4518
head(tri_sci_sig_fas_sec)
##             ID      science_cog
## 1 LmjF.01.0010 nocogLmjF01.0010
## 2 LmjF.01.0020    20332099_cogs
## 3 LmjF.01.0030    19584616_cogs
## 4 LmjF.01.0040 nocogLmjF01.0040
## 5 LmjF.01.0050 nocogLmjF01.0050
## 6 LmjF.01.0060    21566042_cogs
##                                                                 science_genes
## 1                                                                LmjF.01.0010
## 2 Tc00.1047053506895.50,Tc00.1047053508501.300,LmjF.01.0020,Tb927.09.160.2280
## 3 Tc00.1047053506895.40,Tc00.1047053508501.290,LmjF.01.0030,Tb927.09.160.2260
## 4                                                                LmjF.01.0040
## 5                                                                LmjF.01.0050
## 6 Tc00.1047053506895.30,Tc00.1047053508501.280,LmjF.01.0060,Tb927.09.160.2250
##   science_sec_gene science_jaccard     science_cog_type science_cog_id
## 1                                             singleton
## 2                                  3-way COG [Lm+Tb+Tc]  20332099_cogs
## 3                                  3-way COG [Lm+Tb+Tc]  19584616_cogs
## 4                                             singleton
## 5                                             singleton
## 6                                  3-way COG [Lm+Tb+Tc]  21566042_cogs
##                     science_gene_product                    tritryp_description
## 1 hypothetical protein, unknown function hypothetical protein, unknown function
## 2        hypothetical protein, conserved        hypothetical protein, conserved
## 3            MCAK-like kinesin, putative            MCAK-like kinesin, putative
## 4 hypothetical protein, unknown function hypothetical protein, unknown function
## 5                  carboxylase, putative                  carboxylase, putative
## 6        hypothetical protein, conserved        hypothetical protein, conserved
##   tritryp_gene_name tritryp_tm_domains tritryp_ortholog_count tritryp_paralog_count
## 1              null                  2                      9                     0
## 2              null                  0                     21                     0
## 3              null                  0                     43                     1
## 4              null                  0                      7                     0
## 5              null                  0                     32                     1
## 6              null                  0                     17                     0
##   tritryp_ortholog_group tritryp_signalp_score tritryp_signalp_peptide tritryp_uniprot
## 1             OG5_183100                NN Sum                     HMM            null
## 2             OG5_148223                  null                    null            null
## 3             OG5_127200                  null                    null            null
## 4             OG5_183101                NN Sum                     HMM            null
## 5             OG5_126626                  null                    null            null
## 6             OG5_148224                NN Sum                     HMM            null
##   tritryp_entrez_geneid tritryp_gene_symbol    tritryp_brucei_homologs
## 1                  null                null                       <NA>
## 2                  null                null               Tb927.9.3670
## 3                  null                null Tb927.11.3280,Tb927.9.3650
## 4                  null                null                       <NA>
## 5                  null                null  Tb927.4.5350,Tb927.8.6970
## 6                  null                null               Tb927.9.3640
##                                             tritryp_cruzi_homologs signalp_end
## 1                                                             <NA>          24
## 2                                 TcCLB.506895.50,TcCLB.508501.300          NA
## 3 TcCLB.506895.40,TcCLB.509589.30,TcCLB.503999.20,TcCLB.508501.290          NA
## 4                                                             <NA>          NA
## 5                                  TcCLB.504835.20,TcCLB.509913.10          NA
## 6                                 TcCLB.506895.30,TcCLB.508501.280          NA
##   signalp_score signalp_version koh_score     fasta_ucsc_id fasta_query_length
## 1         0.863     SignalP-4.1        NA              <NA>                 NA
## 2            NA            <NA>        NA              <NA>                 NA
## 3            NA            <NA>        NA ENST00000372224.7                668
## 4            NA            <NA>        NA              <NA>                 NA
## 5            NA            <NA>        NA ENST00000376285.4                665
## 6            NA            <NA>        NA              <NA>                 NA
##   fasta_libhit_length fasta_score fasta_e fasta_identity fasta_hit_length
## 1                  NA          NA      NA             NA               NA
## 2                  NA          NA      NA             NA               NA
## 3                 725        50.0 3.2e-56          0.373              807
## 4                  NA          NA      NA             NA               NA
## 5                 728       100.7 0.0e+00          0.526              733
## 6                  NA          NA      NA             NA               NA
##   fasta_hit_matches secretome_name secretome_exosome_boolean secretome_boolean
## 1                NA           <NA>                        NA                NA
## 2                NA           <NA>                        NA                NA
## 3               428           <NA>                        NA                NA
## 4                NA           <NA>                        NA                NA
## 5               534           <NA>                        NA                NA
## 6                NA           <NA>                        NA                NA
##   communication_name communication_hit_type lds2_id lds2_lmmcma1 lds2_relpepratio1
## 1               <NA>                   <NA>    <NA>           NA                NA
## 2               <NA>                   <NA>    <NA>           NA                NA
## 3               <NA>                   <NA>    <NA>           NA                NA
## 4               <NA>                   <NA>    <NA>           NA                NA
## 5               <NA>                   <NA>    <NA>           NA                NA
## 6               <NA>                   <NA>    <NA>           NA                NA
##   lds2_lmmcma2 lds2_relpepratio2 lds2_lmmcma3 lds2_relpepratio3 lds2_lmmcma4
## 1           NA                NA           NA                NA           NA
## 2           NA                NA           NA                NA           NA
## 3           NA                NA           NA                NA           NA
## 4           NA                NA           NA                NA           NA
## 5           NA                NA           NA                NA           NA
## 6           NA                NA           NA                NA           NA
##   lds2_relpepratio4 lds2_meanlmmcma kima_clone kima_homolog kima_chromosome kima_signal
## 1                NA              NA       <NA>         <NA>              NA        <NA>
## 2                NA              NA       <NA>         <NA>              NA        <NA>
## 3                NA              NA       <NA>         <NA>              NA        <NA>
## 4                NA              NA       <NA>         <NA>              NA        <NA>
## 5                NA              NA       <NA>         <NA>              NA        <NA>
## 6                NA              NA       <NA>         <NA>              NA        <NA>
##   kima_comment
## 1         <NA>
## 2         <NA>
## 3         <NA>
## 4         <NA>
## 5         <NA>
## 6         <NA>
rownames(rnaseq) <- gsub(pattern="\\-1$", replacement="", x=rnaseq[["X"]])
rnaseq_orthologs <- merge(rnaseq, tri_sci_sig_fas_sec, by.x="row.names", by.y="ID", all.x=TRUE)
write.csv(file="csv/rnaseq_orthologs.csv", x=rnaseq_orthologs)

## Lm/Tc:  The set of genes where tritryp_cruzi_homologs is not NA
lmtc_orthology <- !is.na(rnaseq_orthologs[["tritryp_cruzi_homologs"]])
sum(lmtc_orthology)
## [1] 6451
lmtc_orthologs <- rnaseq_orthologs[lmtc_orthology,]
lmtc_orthologs_sig <- lmtc_orthologs[["adj.P.Val"]] <= 0.05
sum(lmtc_orthologs_sig)
## [1] 2416
lmtc_orthologs_sig <- lmtc_orthologs[lmtc_orthologs_sig, ]
lmtc_orthologs_sigup <- lmtc_orthologs_sig[["logFC"]] > 0.0
sum(lmtc_orthologs_sigup)
## [1] 1398
lmtc_orthologs_sigup <- lmtc_orthologs[lmtc_orthologs_sigup, ]
write.csv(file="csv/lmtc_orthologs_sigup.csv", x=lmtc_orthologs_sigup)
lmtc_orthologs_sigdown <- lmtc_orthologs_sig[["logFC"]] < 0.0
sum(lmtc_orthologs_sigdown)
## [1] 1018
lmtc_orthologs_sigdown <- lmtc_orthologs[lmtc_orthologs_sigdown, ]
write.csv(file="csv/lmtc_orthologs_sigdown.csv", x=lmtc_orthologs_sigdown)
lmtc_orthologs_sig2up <- lmtc_orthologs_sig[["logFC"]] >= 1.0
sum(lmtc_orthologs_sig2up)
## [1] 86
lmtc_orthologs_sig2up <- lmtc_orthologs[lmtc_orthologs_sig2up, ]
write.csv(file="csv/lmtc_orthologs_sig2up.csv", x=lmtc_orthologs_sig2up)
lmtc_orthologs_sig2down <- lmtc_orthologs_sig[["logFC"]] <= -1.0
sum(lmtc_orthologs_sig2down)
## [1] 115
lmtc_orthologs_sig2down <- lmtc_orthologs[lmtc_orthologs_sig2down, ]
write.csv(file="csv/lmtc_orthologs_sig2down.csv", x=lmtc_orthologs_sig2down)

## Lm/Tb:  The set of genes where tritryp_cruzi_homologs is not NA
lmtb_orthology <- !is.na(rnaseq_orthologs[["tritryp_brucei_homologs"]])
sum(lmtb_orthology)
## [1] 6103
lmtb_orthologs <- rnaseq_orthologs[lmtb_orthology,]
lmtb_orthologs_sig <- lmtb_orthologs[["adj.P.Val"]] <= 0.05
sum(lmtb_orthologs_sig)
## [1] 2308
lmtb_orthologs_sig <-lmtb_orthologs[lmtb_orthologs_sig, ]
lmtb_orthologs_sigup <- lmtb_orthologs_sig[["logFC"]] > 0.0
sum(lmtb_orthologs_sigup)
## [1] 1337
lmtb_orthologs_sigup <-lmtb_orthologs[lmtb_orthologs_sigup, ]
write.csv(file="csv/lmtb_orthologs_sigup.csv", x=lmtb_orthologs_sigup)
lmtb_orthologs_sigdown <- lmtb_orthologs_sig[["logFC"]] < 0.0
sum(lmtb_orthologs_sigdown)
## [1] 971
lmtb_orthologs_sigdown <-lmtb_orthologs[lmtb_orthologs_sigdown, ]
write.csv(file="csv/lmtb_orthologs_sigdown.csv", x=lmtb_orthologs_sigdown)
lmtb_orthologs_sig2up <- lmtb_orthologs_sig[["logFC"]] >= 1.0
sum(lmtb_orthologs_sig2up)
## [1] 84
lmtb_orthologs_sig2up <- lmtb_orthologs[lmtb_orthologs_sig2up, ]
write.csv(file="csv/lmtb_orthologs_sig2up.csv", x=lmtb_orthologs_sig2up)
lmtb_orthologs_sig2down <- lmtb_orthologs_sig[["logFC"]] <= -1.0
sum(lmtb_orthologs_sig2down)
## [1] 111
lmtb_orthologs_sig2down <- lmtb_orthologs[lmtb_orthologs_sig2down, ]
write.csv(file="csv/lmtb_orthologs_sig2down.csv", x=lmtb_orthologs_sig2down)

## Lm/Tc/Tb:  The set of genes where tritryp_cruzi_homologs is not NA
lmtctb_orthology <- !is.na(rnaseq_orthologs[["tritryp_brucei_homologs"]]) & !is.na(rnaseq_orthologs[["tritryp_cruzi_homologs"]])
sum(lmtctb_orthology)
## [1] 5989
lmtctb_orthologs <- rnaseq_orthologs[lmtctb_orthology,]
lmtctb_orthologs_sig <- lmtctb_orthologs[["adj.P.Val"]] <= 0.05
sum(lmtctb_orthologs_sig)
## [1] 2260
lmtctb_orthologs_sig <-lmtctb_orthologs[lmtctb_orthologs_sig, ]
lmtctb_orthologs_sigup <- lmtctb_orthologs_sig[["logFC"]] > 0.0
sum(lmtctb_orthologs_sigup)
## [1] 1313
lmtctb_orthologs_sigup <-lmtctb_orthologs[lmtctb_orthologs_sigup, ]
write.csv(file="csv/lmtctb_orthologs_sigup.csv", x=lmtctb_orthologs_sigup)
lmtctb_orthologs_sigdown <- lmtctb_orthologs_sig[["logFC"]] < 0.0
sum(lmtctb_orthologs_sigdown)
## [1] 947
lmtctb_orthologs_sigdown <-lmtctb_orthologs[lmtctb_orthologs_sigdown, ]
write.csv(file="csv/lmtctb_orthologs_sigdown.csv", x=lmtctb_orthologs_sigdown)
lmtctb_orthologs_sig2up <- lmtctb_orthologs_sig[["logFC"]] >= 1.0
sum(lmtctb_orthologs_sig2up)
## [1] 84
lmtctb_orthologs_sig2up <- lmtctb_orthologs[lmtctb_orthologs_sig2up, ]
write.csv(file="csv/lmtctb_orthologs_sig2up.csv", x=lmtctb_orthologs_sig2up)
lmtctb_orthologs_sig2down <- lmtctb_orthologs_sig[["logFC"]] <= -1.0
sum(lmtctb_orthologs_sig2down)
## [1] 109
lmtctb_orthologs_sig2down <- lmtctb_orthologs[lmtctb_orthologs_sig2down, ]
write.csv(file="csv/lmtctb_orthologs_sig2down.csv", x=lmtctb_orthologs_sig2down)

## Lm/Tc/NOTTb:  The set of genes where tritryp_cruzi_homologs is not NA but brucei is Na
lmtc_notb_orthology <- !is.na(rnaseq_orthologs[["tritryp_cruzi_homologs"]]) & is.na(rnaseq_orthologs[["tritryp_brucei_homologs"]])
sum(lmtc_notb_orthology)
## [1] 462
lmtc_notb_orthologs <- rnaseq_orthologs[lmtc_notb_orthology,]
lmtc_notb_orthologs_sig <- lmtc_notb_orthologs[["adj.P.Val"]] <= 0.05
sum(lmtc_notb_orthologs_sig)
## [1] 156
lmtc_notb_orthologs_sig <-lmtc_notb_orthologs[lmtc_notb_orthologs_sig, ]
lmtc_notb_orthologs_sigup <- lmtc_notb_orthologs_sig[["logFC"]] > 0.0
sum(lmtc_notb_orthologs_sigup)
## [1] 85
lmtc_notb_orthologs_sigup <-lmtc_notb_orthologs[lmtc_notb_orthologs_sigup, ]
write.csv(file="csv/lmtc_notb_orthologs_sigup.csv", x=lmtc_notb_orthologs_sigup)
lmtc_notb_orthologs_sigdown <- lmtc_notb_orthologs_sig[["logFC"]] < 0.0
sum(lmtc_notb_orthologs_sigdown)
## [1] 71
lmtc_notb_orthologs_sigdown <-lmtc_notb_orthologs[lmtc_notb_orthologs_sigdown, ]
write.csv(file="csv/lmtc_notb_orthologs_sigdown.csv", x=lmtc_notb_orthologs_sigdown)
lmtc_notb_orthologs_sig2up <- lmtc_notb_orthologs_sig[["logFC"]] >= 1.0
sum(lmtc_notb_orthologs_sig2up)
## [1] 2
lmtc_notb_orthologs_sig2up <- lmtc_notb_orthologs[lmtc_notb_orthologs_sig2up, ]
write.csv(file="csv/lmtc_notb_orthologs_sig2up.csv", x=lmtc_notb_orthologs_sig2up)
lmtc_notb_orthologs_sig2down <- lmtc_notb_orthologs_sig[["logFC"]] <= -1.0
sum(lmtc_notb_orthologs_sig2down)
## [1] 6
lmtc_notb_orthologs_sig2down <- lmtc_notb_orthologs[lmtc_notb_orthologs_sig2down, ]
write.csv(file="csv/lmtc_notb_orthologs_sig2down.csv", x=lmtc_notb_orthologs_sig2down)

## Lm/Tb/NOTTc:  The set of genes where tritryp_brucei_homologs is not NA but cruzi is NA
lmtb_notc_orthology <- !is.na(rnaseq_orthologs[["tritryp_brucei_homologs"]]) & is.na(rnaseq_orthologs[["tritryp_cruzi_homologs"]])
sum(lmtb_notc_orthology)
## [1] 114
lmtb_notc_orthologs <- rnaseq_orthologs[lmtb_notc_orthology,]
lmtb_notc_orthologs_sig <- lmtb_notc_orthologs[["adj.P.Val"]] <= 0.05
sum(lmtb_notc_orthologs_sig)
## [1] 48
lmtb_notc_orthologs_sig <-lmtb_notc_orthologs[lmtb_notc_orthologs_sig, ]
lmtb_notc_orthologs_sigup <- lmtb_notc_orthologs_sig[["logFC"]] > 0.0
sum(lmtb_notc_orthologs_sigup)
## [1] 24
lmtb_notc_orthologs_sigup <-lmtb_notc_orthologs[lmtb_notc_orthologs_sigup, ]
write.csv(file="csv/lmtb_notc_orthologs_sigup.csv", x=lmtb_notc_orthologs_sigup)
lmtb_notc_orthologs_sigdown <- lmtb_notc_orthologs_sig[["logFC"]] < 0.0
sum(lmtb_notc_orthologs_sigdown)
## [1] 24
lmtb_notc_orthologs_sigdown <-lmtb_notc_orthologs[lmtb_notc_orthologs_sigdown, ]
write.csv(file="csv/lmtb_notc_orthologs_sigdown.csv", x=lmtb_notc_orthologs_sigdown)
lmtb_notc_orthologs_sig2up <- lmtb_notc_orthologs_sig[["logFC"]] >= 1.0
sum(lmtb_notc_orthologs_sig2up)
## [1] 0
lmtb_notc_orthologs_sig2up <- lmtb_notc_orthologs[lmtb_notc_orthologs_sig2up, ]
write.csv(file="csv/lmtb_notc_orthologs_sig2up.csv", x=lmtb_notc_orthologs_sig2up)
lmtb_notc_orthologs_sig2down <- lmtb_notc_orthologs_sig[["logFC"]] <= -1.0
sum(lmtb_notc_orthologs_sig2down)
## [1] 2
lmtb_notc_orthologs_sig2down <- lmtb_notc_orthologs[lmtb_notc_orthologs_sig2down, ]
write.csv(file="csv/lmtb_notc_orthologs_sig2down.csv", x=lmtb_notc_orthologs_sig2down)

## Lm/NOTb/NOTTc:  The set of genes where tritryp_brucei_homologs is NA and cruzi is NA
lm_notbnotc_orthology <- is.na(rnaseq_orthologs[["tritryp_brucei_homologs"]]) & is.na(rnaseq_orthologs[["tritryp_cruzi_homologs"]])
sum(lm_notbnotc_orthology)
## [1] 1915
lm_notbnotc_orthologs <- rnaseq_orthologs[lm_notbnotc_orthology,]
lm_notbnotc_orthologs_sig <- lm_notbnotc_orthologs[["adj.P.Val"]] <= 0.05
sum(lm_notbnotc_orthologs_sig)
## [1] 760
lm_notbnotc_orthologs_sig <-lm_notbnotc_orthologs[lm_notbnotc_orthologs_sig, ]
lm_notbnotc_orthologs_sigup <- lm_notbnotc_orthologs_sig[["logFC"]] > 0.0
sum(lm_notbnotc_orthologs_sigup)
## [1] 310
lm_notbnotc_orthologs_sigup <-lm_notbnotc_orthologs[lm_notbnotc_orthologs_sigup, ]
write.csv(file="csv/lm_notbnotc_orthologs_sigup.csv", x=lm_notbnotc_orthologs_sigup)
lm_notbnotc_orthologs_sigdown <- lm_notbnotc_orthologs_sig[["logFC"]] < 0.0
sum(lm_notbnotc_orthologs_sigdown)
## [1] 450
lm_notbnotc_orthologs_sigdown <-lm_notbnotc_orthologs[lm_notbnotc_orthologs_sigdown, ]
write.csv(file="csv/lm_notbnotc_orthologs_sigdown.csv", x=lm_notbnotc_orthologs_sigdown)
lm_notbnotc_orthologs_sig2up <- lm_notbnotc_orthologs_sig[["logFC"]] >= 1.0
sum(lm_notbnotc_orthologs_sig2up)
## [1] 27
lm_notbnotc_orthologs_sig2up <- lm_notbnotc_orthologs[lm_notbnotc_orthologs_sig2up, ]
write.csv(file="csv/lm_notbnotc_orthologs_sig2up.csv", x=lm_notbnotc_orthologs_sig2up)
lm_notbnotc_orthologs_sig2down <- lm_notbnotc_orthologs_sig[["logFC"]] <= -1.0
sum(lm_notbnotc_orthologs_sig2down)
## [1] 74
lm_notbnotc_orthologs_sig2down <- lm_notbnotc_orthologs[lm_notbnotc_orthologs_sig2down, ]
write.csv(file="csv/lm_notbnotc_orthologs_sig2down.csv", x=lm_notbnotc_orthologs_sig2down)

library(venneuler)
library(hpgltools)

## This plots the set of p-value ups not log2 limited
ones <- c("Lm"=310, "Tc"=306, "Tb"=358)
twos <- c("Lm&Tc"=85, "Lm&Tb"=24)
threes <- c("Lm&Tb&Tc"=1313)
fun_venn_plot(ones=ones, twos=twos, threes=threes)
## Error: object 'centers' not found

## Repeat for the p-value downs not log2 limited
threes <- c("Lm&Tb&Tc" = 947)
twos <- c("Lm&Tc" = 71, "Lm&Tb" = 24)
ones <- c("Lm" = 450, "Tc" = 326, "Tb" = 380)
fun_venn_plot(ones=ones, twos=twos, threes=threes)
## Error: object 'centers' not found

## Repeat for the p-value ups with log2 limit
threes <- c("Lm&Tb&Tc" = 84)
twos <- c("Lm&Tc" = 2, "Lm&Tb" = 0)
ones <- c("Lm" = 27, "Tc" = 20, "Tb" = 24)
fun_venn_plot(ones=ones, twos=twos, threes=threes)
## Error: object 'centers' not found

## Repeat for the p-value downs with log2 limit
threes <- c("Lm&Tb&Tc" = 109)
twos <- c("Lm&Tc" = 6, "Lm&Tb" = 2)
ones <- c("Lm" = 74, "Tc" = 60, "Tb" = 66)
fun_venn_plot(ones=ones, twos=twos, threes=threes)
## Error: object 'centers' not found

2.7 An query example

##save(list=c('merged_de'), file="merged_table.RData")
load('merged_table.RData')
library(sqldf)
head(merged_de)
colnames(merged_de)
all_fasta_low_e = sqldf("SELECT * from merged_de WHERE fasta_e < '0.001'")
head(all_fasta_low_e)

de_up = sqldf("SELECT * FROM merged_de_four WHERE fourhpi_fc > '1'")
de_up_sec = sqldf("SELECT * FROM de_up WHERE secretome_name is not NULL and fourhpi_fc > '2'")

de_upup = sqldf("SELECT * FROM merged_de_four WHERE fourhpi_fc > '2'")
de_up_nohuman = sqldf("SELECT * FROM de_up WHERE fasta_e is NULL")
de_up_nohuman_ranked = de_up_nohuman[ order(de_up_nohuman$fourhpi_fc, decreasing=TRUE),]
de_up_nohuman_ranked_200 = head(de_up_nohuman_ranked, n=200)
de_up_nohuman_ranked_notb = sqldf("SELECT * FROM de_up_nohuman_ranked_200 WHERE tritryp_brucei_homologs is NULL")

a = de_up_nohuman_ranked_notb

dim(de_up_nohuman)
de_up_nohuman_signalp = sqldf("SELECT * FROM de_up_nohuman WHERE signalp_score is not NULL")
dim(de_up_nohuman_signalp)

fc_filter2 = sqldf("SELECT * FROM de_up_nohuman_signalp WHERE fourhpi_fc > '2'")
fc_filter = sqldf("SELECT * FROM de_up_nohuman_signalp WHERE fourhpi_fc > '1.5'")
fc_filter_nobrucei = sqldf("SELECT * FROM fc_filter WHERE tritryp_brucei_homologs is NULL")
fc_filter_nohomolog = sqldf("SELECT * FROM fc_filter WHERE tritryp_brucei_homologs is NULL AND tritryp_cruzi_homologs is NULL")
dim(fc_filter_nohomolog)

fc_filter2$secretome_name
fc_filter_nohomolog$secretome_name

secretome_hits = sqldf("SELECT * FROM merged_de_four WHERE secretome_name is not NULL")

3 What Najib, Saloe, Cecilia want from this:

Before printing the tables below, perform the following operations.

  1. I think add a column including the debothup mouse data as a boolean
  2. I think add the Kima et al. data.

Once complete, do the following:

3.1 For Saloe

Provide a table which is: a. Rank order all by fold change (highest->lowest)

This table includes only columns describing the following: a. ID, FC, tbrucei boolean, mean_cmca > 1.7 boolean, mouse boolean, kima boolean, sum of columns (3,4,5,6)

## Requisite #1: The set of genes which are not in the fasta search between lmajor and homo sapiens.
saloe_start = tri_sci_sig_fas_sec_rna
library("sqldf")
saloe = sqldf("SELECT * FROM saloe_start WHERE fasta_e is NULL")
saloe = saloe[ order(saloe$rnaseq_4hpifc, decreasing=TRUE),]
saloe = saloe[,c("ID","rnaseq_4hpifc","rnaseq_4hpipval","tritryp_brucei_homologs","lds2_meanlmmcma","rnaseq_hsmmup","kima_clone")]
saloe$tritryp_brucei_homologs[is.na(saloe$tritryp_brucei_homologs)] = 0
saloe$tritryp_brucei_homologs[saloe$tritryp_brucei_homologs != 0] = 1
saloe$tritryp_brucei_homologs = as.numeric(saloe$tritryp_brucei_homologs)
saloe$kima_clone[is.na(saloe$kima_clone)] = 0
saloe$lds2_meanlmmcma = as.numeric(saloe$lds2_meanlmmcma)
saloe$lds2_meanlmmcma[is.na(saloe$lds2_meanlmmcma)] = 0
saloe$lds2_meanlmmcma[saloe$lds2_meanlmmcma < 1.7 ] = 0
saloe$lds2_meanlmmcma[saloe$lds2_meanlmmcma >= 1.7 ] = 1

write_xls(data=saloe, file="saloe_v1")

4 Save me!

tt <- sm(saveme(filename="xrefs.rda.xz"))
LS0tCnRpdGxlOiAiUk5Bc2VxIG9mIEwubWFqb3IvYW1hem9uZW5zaXM6ICBHZW5lIElEIGNyb3NzIHJlZmVyZW5jaW5nLiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogaHRtbF9kb2N1bWVudDoKICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgY29kZV9mb2xkaW5nOiBzaG93CiAgZmlnX2NhcHRpb246IHRydWUKICBmaWdfaGVpZ2h0OiA3CiAgZmlnX3dpZHRoOiA3CiAgaGlnaGxpZ2h0OiB0YW5nbwogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IGNvc21vCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICBjb2xsYXBzZWQ6IGZhbHNlCiAgIHNtb290aF9zY3JvbGw6IGZhbHNlCi0tLQoKPHN0eWxlPgpib2R5IC5tYWluLWNvbnRhaW5lciB7Cm1heC13aWR0aDogMTYwMHB4Owp9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlPUZBTFNFfQojIyBUaGVzZSBhcmUgdGhlIG9wdGlvbnMgSSB0ZW5kIHRvIGZhdm9yCmxpYnJhcnkoImhwZ2x0b29scyIpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KAogICAgcHJvZ3Jlc3MgPSBUUlVFLAogICAgdmVyYm9zZSA9IFRSVUUsCiAgICB3aWR0aCA9IDkwLAogICAgZWNobyA9IFRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICAgIGVycm9yID0gVFJVRSwKICAgIGZpZy53aWR0aCA9IDgsCiAgICBmaWcuaGVpZ2h0ID0gOCwKICAgIGRwaSA9IDk2KQpvcHRpb25zKAogICAgZGlnaXRzID0gNCwKICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwKICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbCA9ICJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQpzZXQuc2VlZCgxKQpybWRfZmlsZSA8LSAiY3Jvc3NyZWZfcGFyYXNpdGVfZ2VuZXMuUm1kIgpgYGAKCltpbmRleC5odG1sXShpbmRleC5odG1sKQoKYGBge3IgcmVuZGVyaW5nLCBpbmNsdWRlPUZBTFNFLCBldmFsPUZBTFNFfQojIyBUaGlzIGJsb2NrIGlzIHVzZWQgdG8gcmVuZGVyIGEgZG9jdW1lbnQgZnJvbSB3aXRoaW4gaXQuCnJtYXJrZG93bjo6cmVuZGVyKHJtZF9maWxlKQoKIyMgQW4gZXh0cmEgcmVuZGVyZXIgZm9yIHBkZiBvdXRwdXQKcm1hcmtkb3duOjpyZW5kZXIocm1kX2ZpbGUsIG91dHB1dF9mb3JtYXQ9InBkZl9kb2N1bWVudCIsIG91dHB1dF9vcHRpb25zPWMoInNraXBfaHRtbCIpKQojIyBPciB0byBzYXZlL2xvYWQgbGFyZ2UgUmRhdGEgZmlsZXMuCmhwZ2x0b29sczo6OnNhdmVtZSgpCmhwZ2x0b29sczo6OmxvYWRtZSgpCnJtKGxpc3Q9bHMoKSkKYGBgCgojIChSZSkgZ2VuZXJhdGUgYSBzZXQgb2Ygc2hhcmVkIGdlbmUgSURzIGFtb25nIHNwZWNpZXMKClRoZSBmb2xsb3dpbmcgaXMgY29waWVkIGZyb20geHJlZi5ybWQgZnJvbSBwcmV2aW91cyB3b3JrLgoKWWVhaCBJIGhhdmUgbm8gaWRlYSB3aGF0IEkgYW0gZG9pbmcgd2l0aCB0aGlzLCBidXQgaGVyZSBhcmUgdGhlIHRoaW5ncwpOYWppYiB3YW50cyB0byBjcm9zcyByZWZlcmVuY2U6IChJbiBvcmRlciBvZiBpbmNsdXNpb24pCgogKyBPcnRob2xvZ3kgaW5mb3JtYXRpb24gZnJvbSB0aGUgMjAwNSBTY2llbmNlIHBhcGVyCiArIFNpZ25hbHAvR1BJL1RyYW5zbWVtYnJhbmUgZGF0YQogKyBTaW1pbGFyaXR5L09ydGhvbG9neSBpbmZvcm1hdGlvbiB0byBIb21vIGF0ID49NDUlIHNpbWlsYXJpdHkKICsgU2VjcmV0b21lIGRhdGEgZnJvbSBhIHBhcGVyIHByb3ZpZGVkIGJ5IFNhbG9lCiArIChGdXR1cmUpTC5tYWpvciBleG9zb21lIGRhdGEKICsgQ2hhcmFjdGVyaXplZCBQb3RlbnRpYWwgSG9zdC9QYXJhc2l0ZSBJbnRlcmFjdG9ycyAoUGV0ZXIgS2ltYSBwYXBlcikKICsgVC5icnVjZWkgZXNzZW50aWFsaXR5IGRhdGEKICsgTC5tYWpvciBtZXRhYm9saWMgcGF0aHdheSBkYWF0CgojIyBUaGUgb3J0aG9sb2d5IGluZm9ybWF0aW9uIGZyb20gdGhlIFRyaXRyeXBEQgoKVGhlIHRyaXRyeXBkYiBtYWludGFpbnMgdGhpcyB0eXBlIG9mIGRhdGEsIGZvdW5kIGluIHRoZSB0ZXh0CmRvd25sb2FkYWJsZSBkYXRhIGZpbGVzLiAgSSBoYXZlIGEgcGVybCBzY3JpcHQgd2hpY2ggcGFyc2VzIHRoZXNlIGFuZApkdW1wcyB0aGUgcmVzdWx0aW5nIGN1cmF0ZWQgb3J0aG9sb2dpZXMgaW50byB0YWIgZGVsaW1pdGVkIGZpbGVzLgoKSSBhbSBnb2luZyB0byB1c2UgdGhlIHRyaXRyeXBkYiBtYXN0ZXIgdGFibGUgYXMgbXkgc3RhcnRpbmcgcG9pbnQuCgpgYGB7ciBjdXJhdGVkX29ydGhvbG9nc30KcmVmZGlyID0gIi9jYmNiL2xhYi9uZWxzYXllZC9yZWZfZGF0YSIKdHJpdHJ5cF9tYXN0ZXIgPSByZWFkLmNzdihwYXN0ZTAocmVmZGlyLCAiL1RyaVRyeXBEQl90ZXh0L2xtYWpvci9sbWFqb3JfbWFzdGVyLnRhYi54eiIpLCBzZXA9Ilx0IiwgaGVhZGVyPVRSVUUpCnRyaXRyeXBfb3J0aG8gPSByZWFkLmNzdihwYXN0ZTAocmVmZGlyLCAiL1RyaVRyeXBEQl90ZXh0L2xtYWpvci9sbWFqb3Jfb3J0aG8udHh0Lnh6IiksIHNlcD0iXHQiLCBoZWFkZXI9RkFMU0UpCmNvbG5hbWVzKHRyaXRyeXBfb3J0aG8pID0gYygibG1ham9yIiwibnVtIiwib3J0aG8iLCJzdHJhaW4iLCJhbm5vdGF0aW9uIiwic3ludGVuaWMiLCJjb21tZW50cyIpCnRyaXRyeXBfeHJlZnMgPSB0cml0cnlwX21hc3RlclssYygiSUQiLCJQcm9kdWN0X0Rlc2NyaXB0aW9uIiwiR2VuZV9OYW1lIiwiWC5fVE1fRG9tYWlucyIsIk9ydGhvbG9nX2NvdW50IiwiUGFyYWxvZ19jb3VudCIsIk9ydGhvbG9nX0dyb3VwIiwiU2lnbmFsUF9TY29yZXMiLCJTaWduYWxQX1BlcHRpZGUiLCJVbmlQcm90X0lEIiwiRW50cmV6X0dlbmVfSUQiLCJHZW5lX05hbWVfb3JfU3ltYm9sIildCmRpbSh0cml0cnlwX3hyZWZzKQp0cml0cnlwX29ydGhvX3RiID0gc3Vic2V0KHRyaXRyeXBfb3J0aG8sIHN0cmFpbiA9PSAnVHJ5cGFub3NvbWEgYnJ1Y2VpIFRSRVU5MjcnKQp0cml0cnlwX29ydGhvX3RjID0gc3Vic2V0KHRyaXRyeXBfb3J0aG8sIHN0cmFpbiA9PSAnVHJ5cGFub3NvbWEgY3J1emkgQ0wgQnJlbmVyIEVzbWVyYWxkby1saWtlJ3wgc3RyYWluID09ICdUcnlwYW5vc29tYSBjcnV6aSBDTCBCcmVuZXIgTm9uLUVzbWVyYWxkby1saWtlJykKdHJpdHJ5cF9vcnRob190Yl9jb21iaW5lZCA9IGFnZ3JlZ2F0ZShvcnRob35sbWFqb3IsIHBhc3RlLCBjb2xsYXBzZT0iLCIsIGRhdGE9dHJpdHJ5cF9vcnRob190YikKY29sbmFtZXModHJpdHJ5cF9vcnRob190Yl9jb21iaW5lZCkgPSBjKCJsbWFqb3IiLCJ0YnJ1Y2VpIikKdHJpdHJ5cF9vcnRob190Y19jb21iaW5lZCA9IGFnZ3JlZ2F0ZShvcnRob35sbWFqb3IsIHBhc3RlLCBjb2xsYXBzZT0iLCIsIGRhdGE9dHJpdHJ5cF9vcnRob190YykKY29sbmFtZXModHJpdHJ5cF9vcnRob190Y19jb21iaW5lZCkgPSBjKCJsbWFqb3IiLCJ0Y3J1emkiKQp0cml0cnlwX3hyZWZzID0gbWVyZ2UodHJpdHJ5cF94cmVmcywgdHJpdHJ5cF9vcnRob190Yl9jb21iaW5lZCwgYnkueD0iSUQiLCBieS55PSJsbWFqb3IiLCBhbGwueD1UUlVFKQp0cml0cnlwX3hyZWZzID0gbWVyZ2UodHJpdHJ5cF94cmVmcywgdHJpdHJ5cF9vcnRob190Y19jb21iaW5lZCwgYnkueD0iSUQiLCBieS55PSJsbWFqb3IiLCBhbGwueD1UUlVFKQpkaW0odHJpdHJ5cF94cmVmcykKYGBgCgojIE5vdyBhZGQgb3J0aG9sb2d5IGZyb20gU2NpZW5jZSAyMDA1CgpUaGlzIGRhdGEgaXMgZm91bmQgaW4gc3VwcGxlbWVudGFsIHRhYmxlIFMxLCB3aGljaCBJIGNvcGllZCB0bwovY2JjYi9sYWIvbmVsc2F5ZWQvcmVmX2RhdGEvU2NpZW5jZV8yMDA1LwpUaGlzIGZpbGUgbG9va3MgbGlrZSBpdCB3aWxsIGJlIGRpZmZpY3VsdCB0byB3b3JrIHdpdGgsIHRoZSBmaXJzdApjb2x1bW4gaXMgYSBnZW5lIGlkZW50aWZpZXIgZnJvbSBlYWNoIG9mIHRoZSB0aHJlZSBtYWluIHNwZWNpZXMgLS0KZWFzeSBlbm91Z2guICBUaGUgc2Vjb25kIGNvbHVtbiBpcyBhICdzZWNvbmRhcnkgZ2VuZSBpZGVudGlmaWVyJyBhbmQKYXBwZWFycyB0byBtZSB0byBiZSBpbmNvbnNpc3RlbnQuICBUaGUgdGhpcmQgaXMgYSBjbHVzdGVyIGlkZW50aWZpZXIsCnVuZm9ydHVuYXRlbHkgaXQgdG9vIGlzIGluY29uc2lzdGVudC4gIFRoZSBuZXh0IGNvbHVtbiAnQ09HIHR5cGUnLAphcHBlYXJzIHRvIGJlIHRoZSBiZXN0LiAgRmluYWxseSB0aGVyZSBpcyBhIHByZWRpY3RlZCBwcm90ZWluIHR5cGUKd2hpY2ggb2YgY291cnNlIGNvbnRhaW5zIHByaW1hcmlseSB0aGUgdGV4dCAnaHlwb3RoZXRpY2FsJyBvcgonYW1hc3Rpbi4nCgpgYGB7ciBzY2llbmNlX29ydGhvbG9nc30Kc2NpZW5jZV8yMDA1ID0gcmVhZC5jc3YoIi9jYmNiL2xhYi9uZWxzYXllZC9yZWZfZGF0YS9zY2llbmNlXzIwMDUvMTExMjE4MXNfdGFibGVTMS50eHQiLCBzZXA9Ilx0IiwgY29tbWVudD0iIyIsIGhlYWRlcj1UUlVFKQpjb2xuYW1lcyhzY2llbmNlXzIwMDUpID0gYygicHJpbWFyeV9nZW5lIiwic2Vjb25kYXJ5X2dlbmUiLCJqYWNjYXJkIiwiY29nX3R5cGUiLCJjb2dfaWQiLCJnZW5lX3Byb2R1Y3QiKQpzY2llbmNlX2FnZyA9IHNjaWVuY2VfMjAwNQpzY2llbmNlX2FnZyA9IGFzLmRhdGEuZnJhbWUobGFwcGx5KHNjaWVuY2VfYWdnLCBmdW5jdGlvbih4KSBpZihpcy5jaGFyYWN0ZXIoeCl8aXMuZmFjdG9yKHgpKSBnc3ViKCJcXCpuZXcgZ2VuZSBpbiBMbWpGLnY1LjBcXCoiLCJsbXVuZGVmIix4KSBlbHNlIHgpKQpzY2llbmNlX2FnZyA9IGFzLmRhdGEuZnJhbWUobGFwcGx5KHNjaWVuY2VfYWdnLCBmdW5jdGlvbih4KSBpZihpcy5jaGFyYWN0ZXIoeCl8aXMuZmFjdG9yKHgpKSBnc3ViKCJcXCogbmV3IGdlbmUgaW4gTG1qRi52NS4wXFwqIiwibG11bmRlZiIseCkgZWxzZSB4KSkKc2NpZW5jZV9hZ2cgPSBhcy5kYXRhLmZyYW1lKGxhcHBseShzY2llbmNlX2FnZywgZnVuY3Rpb24oeCkgaWYoaXMuY2hhcmFjdGVyKHgpfGlzLmZhY3Rvcih4KSkgZ3N1YigiXFwqbmV3IGdlbmUgaW4gVGNCci52NC4wXFwqIiwidGN1bmRlZiIseCkgZWxzZSB4KSkKc2NpZW5jZV9hZ2cgPSBhcy5kYXRhLmZyYW1lKGxhcHBseShzY2llbmNlX2FnZywgZnVuY3Rpb24oeCkgaWYoaXMuY2hhcmFjdGVyKHgpfGlzLmZhY3Rvcih4KSkgZ3N1YigiXFwqbmV3IGdlbmUgaW4gVGI5MjcudjQuMFxcKiIsInRidW5kZWYiLHgpIGVsc2UgeCkpCnNjaWVuY2VfYWdnJGNvZyA9IHNjaWVuY2VfYWdnJGNvZ19pZApzY2llbmNlX2FnZyRjb2cgPSBpZmVsc2Uoc2NpZW5jZV9hZ2ckY29nID09ICJsbXVuZGVmIiwgYXMuY2hhcmFjdGVyKHBhc3RlMCgnbm9jb2cnLCBzY2llbmNlX2FnZyRwcmltYXJ5X2dlbmUpKSwgYXMuY2hhcmFjdGVyKHNjaWVuY2VfYWdnJGNvZ19pZCkpCnNjaWVuY2VfYWdnJGNvZyA9IGlmZWxzZShzY2llbmNlX2FnZyRjb2cgPT0gJycsIGFzLmNoYXJhY3RlcihwYXN0ZTAoJ25vY29nJywgc2NpZW5jZV9hZ2ckcHJpbWFyeV9nZW5lKSksIGFzLmNoYXJhY3RlcihzY2llbmNlX2FnZyRjb2dfaWQpKQpzY2llbmNlX2FnZyRjb2cgPSBpZmVsc2Uoc2NpZW5jZV9hZ2ckY29nID09ICIiLCBhcy5jaGFyYWN0ZXIocGFzdGUwKCdub2NvZycsIHNjaWVuY2VfYWdnJHByaW1hcnlfZ2VuZSkpLCBhcy5jaGFyYWN0ZXIoc2NpZW5jZV9hZ2ckY29nX2lkKSkKbGVuZ3RoKGxldmVscyhhcy5mYWN0b3Ioc2NpZW5jZV9hZ2ckY29nKSkpCnNjaWVuY2VfYWdnJGNvZyA9IGlmZWxzZShzY2llbmNlX2FnZyRjb2cgPT0gIiIsIGFzLmNoYXJhY3RlcihwYXN0ZTAoJ25vY29nJywgc2NpZW5jZV9hZ2ckcHJpbWFyeV9nZW5lKSksIGFzLmNoYXJhY3RlcihzY2llbmNlX2FnZyRjb2dfaWQpKQpsZW5ndGgobGV2ZWxzKGFzLmZhY3RvcihzY2llbmNlX2FnZyRjb2cpKSkKc2NpZW5jZV9sbWNvZ3MgPSBzY2llbmNlX2FnZ1tncmVwKCJeTG0iLCBzY2llbmNlX2FnZyRwcmltYXJ5X2dlbmUsIHBlcmw9VFJVRSksXQpzY2llbmNlX2xtY29ncyA9IHNjaWVuY2VfbG1jb2dzWyxjKCJwcmltYXJ5X2dlbmUiLCJjb2ciKV0Kc2NpZW5jZV9hZ2dyZWdhdGVkID0gYWdncmVnYXRlKHByaW1hcnlfZ2VuZX5jb2csIHBhc3RlLCBjb2xsYXBzZT0iLCIsIGRhdGE9c2NpZW5jZV9hZ2cpCnNjaWVuY2VfbWVyZ2VkID0gbWVyZ2Uoc2NpZW5jZV9sbWNvZ3MsIHNjaWVuY2VfYWdncmVnYXRlZCwgYnkueD0iY29nIiwgYnkueT0iY29nIiwgYWxsLng9VFJVRSkKc2NpZW5jZV9tZXJnZWQgPSBtZXJnZShzY2llbmNlX21lcmdlZCwgc2NpZW5jZV9hZ2csIGJ5Lng9InByaW1hcnlfZ2VuZS54IiwgYnkueT0icHJpbWFyeV9nZW5lIikKY29sbmFtZXMoc2NpZW5jZV9tZXJnZWQpID0gYygiSUQiLCJjb2ciLCJnZW5lcyIsInNlY29uZGFyeV9nZW5lIiwiamFjY2FyZCIsImNvZ190eXBlIiwiY29nX2lkIiwiZ2VuZV9wcm9kdWN0IiwiY29nX2FnYWluIikKc2NpZW5jZV9tZXJnZWQgPSBzY2llbmNlX21lcmdlZFstOV0gICMjIERyb3AgdGhlIGR1cGxpY2F0ZSBjb2x1bW4Kc2NpZW5jZV9tZXJnZWQkSUQgPSBnc3ViKCJMbWpGIiwgIkxtakZcXC4iLCBzY2llbmNlX21lcmdlZCRJRCkKc2NpZW5jZV9tZXJnZWQkZ2VuZXMgPSBnc3ViKCJMbWpGIiwgIkxtakZcXC4iLCBzY2llbmNlX21lcmdlZCRnZW5lcykKc2NpZW5jZV9tZXJnZWQkZ2VuZXMgPSBnc3ViKCJUYiIsICJUYjkyN1xcLiIsIHNjaWVuY2VfbWVyZ2VkJGdlbmVzKQpgYGAKCiMjIEJyaW5nIHRvZ2V0aGVyIHRoZSB0cml0cnlwZGIgYW5kIHNjaWVuY2UgMjAwNSB0YWJsZXMKClRoaXMgc3RhbnphIG1hcmtzIHRoZSBwbGFjZSB3aGVyZSB0aGUgZmlyc3QgdHdvIHRhYmxlcyBhcmUgam9pbmVkLgoKYGBge3IgbWVyZ2VfdHJpdHJ5cF9zY2llbmNlfQpoZWFkKHNjaWVuY2VfbWVyZ2VkKQpkaW0oc2NpZW5jZV9tZXJnZWQpCmhlYWQodHJpdHJ5cF94cmVmcykKZGltKHRyaXRyeXBfeHJlZnMpCnRyaV9zY2kgPSBtZXJnZShzY2llbmNlX21lcmdlZCwgdHJpdHJ5cF94cmVmcywgYnkueD0iSUQiLCBieS55PSJJRCIsIGFsbC55PVRSVUUpCgpvcmlnaW5hbF9jb2x1bW5zID0gYygiSUQiLCJzY2llbmNlX2NvZyIsInNjaWVuY2VfZ2VuZXMiLCJzY2llbmNlX3NlY19nZW5lIiwic2NpZW5jZV9qYWNjYXJkIiwic2NpZW5jZV9jb2dfdHlwZSIsInNjaWVuY2VfY29nX2lkIiwic2NpZW5jZV9nZW5lX3Byb2R1Y3QiKQpuZXdfY29sdW1ucyA9IGMoInRyaXRyeXBfZGVzY3JpcHRpb24iLCJ0cml0cnlwX2dlbmVfbmFtZSIsInRyaXRyeXBfdG1fZG9tYWlucyIsInRyaXRyeXBfb3J0aG9sb2dfY291bnQiLCJ0cml0cnlwX3BhcmFsb2dfY291bnQiLCJ0cml0cnlwX29ydGhvbG9nX2dyb3VwIiwidHJpdHJ5cF9zaWduYWxwX3Njb3JlIiwidHJpdHJ5cF9zaWduYWxwX3BlcHRpZGUiLCJ0cml0cnlwX3VuaXByb3QiLCJ0cml0cnlwX2VudHJlel9nZW5laWQiLCJ0cml0cnlwX2dlbmVfc3ltYm9sIiwidHJpdHJ5cF9icnVjZWlfaG9tb2xvZ3MiLCJ0cml0cnlwX2NydXppX2hvbW9sb2dzIikKYWxsX2NvbHVtbnMgPSBjKG9yaWdpbmFsX2NvbHVtbnMsIG5ld19jb2x1bW5zKQpjb2xuYW1lcyh0cmlfc2NpKSA9IGFsbF9jb2x1bW5zCmRpbSh0cmlfc2NpKQpgYGAKCiMjIFJlYWQgaW4gbXkgcnVuIG9mIHNpZ25hbHAgNC4xCgpgYGB7ciBtZXJnZV9zaWduYWxwfQpzaWduYWxwX2RhdGEgPSByZWFkLmNzdihmaWxlPSJyZWZlcmVuY2UvbG1ham9yX3NpZ25hbHBfY2xlYXZhZ2UuZ2ZmIiwgc2VwPSJcdCIsIGhlYWRlcj1UUlVFLCBjb21tZW50PSIjIikKc2lnbmFscF9kYXRhID0gc2lnbmFscF9kYXRhWyxjKCJzZXF1ZW5jZS5uYW1lIiwiZW5kIiwic2NvcmUiLCJzb3VyY2UiKV0KY29sbmFtZXMoc2lnbmFscF9kYXRhKSA9IGMoIklEIiwiZW5kIiwic2NvcmUiLCJzb3VyY2UiKQpkaW0odHJpX3NjaSkKZGltKHNpZ25hbHBfZGF0YSkKCnRyaV9zY2lfc2lnID0gbWVyZ2UodHJpX3NjaSwgc2lnbmFscF9kYXRhLCBieS54PSJJRCIsIGJ5Lnk9IklEIiwgYWxsLng9VFJVRSkKZGltKHRyaV9zY2lfc2lnKQoKa29oX2RhdGEgPSByZWFkLmNzdihmaWxlPSJyZWZlcmVuY2Uva29oLnR4dCIsIHNlcD0iICIsIGhlYWRlcj1GQUxTRSkKY29sbmFtZXMoa29oX2RhdGEpID0gYygiSUQiLCJrb2hfc2NvcmUiKQp0cmlfc2NpX3NpZyA9IG1lcmdlKHRyaV9zY2lfc2lnLCBrb2hfZGF0YSwgYnkueD0iSUQiLCBieS55PSJJRCIsIGFsbC54PVRSVUUpCgpuZXdfY29sdW1ucyA9IGMoInNpZ25hbHBfZW5kIiwic2lnbmFscF9zY29yZSIsInNpZ25hbHBfdmVyc2lvbiIsICJrb2hfc2NvcmUiKQphbGxfY29sdW1ucyA9IGMoYWxsX2NvbHVtbnMsIG5ld19jb2x1bW5zKQpjb2xuYW1lcyh0cmlfc2NpX3NpZykgPSBhbGxfY29sdW1ucwpgYGAKCiMjIFJlYWQgaW4gZ2dzZWFyY2gzNiB1c2luZyBsbWFqb3IgcXVlcnkgYW5kIGh1bWFuIGxpYnJhcnkuCgpJIHNwZWNpZnkgcXVlcnkvbGlicmFyeSBiZWNhdXNlIEkgaGF2ZSBhIHJlY2lwcm9jYWwgc2VhcmNoLgpBbHNvLCBJIGFtIHVzaW5nIHRoZSBVQ1NDIGtub3duIHBlcHRpZGVzLCB3aGljaCBoYXZlIGEgc2VwYXJhdGUgZmlsZQp0byBjcm9zcyByZWZlcmVuY2UgdGhlbSB0byB0aGUgRU5TRyBpZGVudGlmaWVycywgc28gSSB3aWxsIG5lZWQgdG8KbWVyZ2UgYWNyb3NzIGJvdGggZmlsZXMuCgpgYGB7ciBnZ3NlYXJjaF9sbWFqb3JfaHNhcGllbnN9CnBlcG5hbWVzID0gcmVhZC5jc3YoInJlZmVyZW5jZS9rbm93bkdlbmUudHh0Lmd6Iiwgc2VwPSJcdCIsIGhlYWRlcj1GQUxTRSkKY29sbmFtZXMocGVwbmFtZXMpID0gYygiSUQiLCJjaHIiLCJzdHJhbmQiLCJzdGFydCIsImVuZCIsInN0YXJ0MiIsInN0YXJ0MyIsIm51bSIsImV4b25zIiwiZXhvbnMyIiwicSIsIlVDU0MiKQpmYXN0YV9zZWFyY2ggPSByZWFkLmNzdigicmVmZXJlbmNlL2xtYWpvcl92c19oc2FwaWVucy5vdXQudGFibGUiLCBzZXA9Ilx0IiwgaGVhZGVyPVRSVUUpCmZhc3RhX3BlcG5hbWVzID0gbWVyZ2UocGVwbmFtZXMsIGZhc3RhX3NlYXJjaCwgYnkueD0iSUQiLCBieS55PSJIaXQuSUQiKQpmYXN0YV9wZXBuYW1lcyA9IGZhc3RhX3BlcG5hbWVzWyxjKCJVQ1NDIiwiUXVlcnkuTmFtZSIsIlF1ZXJ5Lmxlbmd0aCIsIkhpdC5MZW5ndGgiLCJTY29yZSIsIkUiLCJJZGVudGl0eSIsIkhpdC5sZW5ndGgiLCJIaXQuTWF0Y2hlcyIpXQpmYXN0YV9wZXBuYW1lcyRRdWVyeS5OYW1lID0gbWFrZS5uYW1lcyhmYXN0YV9wZXBuYW1lcyRRdWVyeS5OYW1lLCB1bmlxdWU9VFJVRSkKdHJpX3NjaV9zaWdfZmFzID0gbWVyZ2UodHJpX3NjaV9zaWcsIGZhc3RhX3BlcG5hbWVzLCBieS54PSJJRCIsIGJ5Lnk9IlF1ZXJ5Lk5hbWUiLCBhbGwueD1UUlVFKQoKbmV3X2NvbHVtbnMgPSBjKCJmYXN0YV91Y3NjX2lkIiwiZmFzdGFfcXVlcnlfbGVuZ3RoIiwiZmFzdGFfbGliaGl0X2xlbmd0aCIsImZhc3RhX3Njb3JlIiwiZmFzdGFfZSIsImZhc3RhX2lkZW50aXR5IiwiZmFzdGFfaGl0X2xlbmd0aCIsImZhc3RhX2hpdF9tYXRjaGVzIikKYWxsX2NvbHVtbnMgPSBjKGFsbF9jb2x1bW5zLCBuZXdfY29sdW1ucykKY29sbmFtZXModHJpX3NjaV9zaWdfZmFzKSA9IGFsbF9jb2x1bW5zCiMjd3JpdGVfeGxzKGRhdGE9dHJpX3NjaV9zaWdfZmFzLCBmaWxlPSJtZXJnZWRfdGFibGVzIikKYGBgCgojIyBNZXJnZSBpbiBzZWNyZXRvbWUgZGF0YSBhbmQgdGhlIGNvbW11bmljYXRpb24gcGFwZXIgZGF0YQoKYGBge3Igc2VjcmV0b21lfQojIyBUaGlzIGlzIGZyb20gVGFibGUgUzMgb2Y6CiMjICJBbiBleG9zb21lLWJhc2VkIHNlY3JldGlvbiBwYXRod2F5IGlzIHJlc3BvbnNpYmxlIGZvciBwcm90ZWluIGV4cG9ydCBmcm9tIExlaXNobWFuaWEgYW5kIGNvbW11bmljYXRpb24gd2l0aCBtYWNyb3BoYWdlcy4iCiMjIGh0dHA6Ly9qY3MuYmlvbG9naXN0cy5vcmcvY29udGVudC8xMjMvNi84NDIuc2hvcnQKc2VjcmV0b21lID0gcmVhZC5jc3YoInJlZmVyZW5jZS9zZWNyZXRvbWUuY3N2IiwgaGVhZGVyPVRSVUUpCmNvbG5hbWVzKHNlY3JldG9tZSkgPSBjKCJJRCIsIm5hbWUiLCJleG9zb21lIiwic2VjcmV0b21lIikKc2VjcmV0b21lJElEID0gZ3N1YihwYXR0ZXJuPSJMbWpGIiwgcmVwbGFjZW1lbnQ9IkxtakZcXC4iLCB4PXNlY3JldG9tZSRJRCkKdHJpX3NjaV9zaWdfZmFzX3NlYyA9IG1lcmdlKHRyaV9zY2lfc2lnX2Zhcywgc2VjcmV0b21lLCBieS54PSJJRCIsIGJ5Lnk9IklEIiwgYWxsLng9VFJVRSkKCiMjIFRoaXMgY29tbWEgc2VwYXJhdGVkIGZpbGUgd2FzIGV4dHJhY3RlZCBmcm9tIHRhYmxlIFM0IGZyb206CiMjIGh0dHA6Ly93d3cuZ2Vub21lYmlvbG9neS5jb20vMjAwOC85LzIvUjM1L2FkZGl0aW9uYWwKIyMgIlByb3Rlb21pYyBhbmFseXNpcyBvZiB0aGUgc2VjcmV0b21lIG9mIExlaXNobWFuaWEgZG9ub3ZhbmkiCmNvbW11bmljYXRpb24gPSByZWFkLmNzdigicmVmZXJlbmNlL2NvbW11bmljYXRpb24uY3N2IiwgaGVhZGVyPVRSVUUpCmNvbG5hbWVzKGNvbW11bmljYXRpb24pID0gYygiSUQiLCJjb21tdW5pY2F0aW9uX25hbWUiLCAibXNfZ3BpIikKdHJpX3NjaV9zaWdfZmFzX3NlYyA9IG1lcmdlKHRyaV9zY2lfc2lnX2Zhc19zZWMsIGNvbW11bmljYXRpb24sIGJ5Lng9IklEIiwgYnkueT0iSUQiLCBhbGwueD1UUlVFKQoKIyMgVGhlIGZvbGxvd2luZyB0YWJsZSBjYW1lIGZyb20gU3VwcGxlbWVudGFyeSA1IGluCiMjIGh0dHA6Ly93d3cuZ2Vub21lYmlvbG9neS5jb20vMjAwOC85LzIvUjM1CiMjICJQcm90ZW9taWMgYW5hbHlzaXMgb2YgdGhlIHNlY3JldG9tZSBvZiBMZWlzaG1hbmlhIGRvbm92YW5pIgpkb25vdmFuaV9jbWNhX3JhdGlvID0gcmVhZC5jc3YoInJlZmVyZW5jZS9wcm90ZW9taWNfYW5hbHlzaXNfc2VjcmV0b21lX2Rvbm92YW5pX3M1LmNzdiIsIGhlYWRlcj1UUlVFKQojIyBUaGUgZm9sbG93aW5nIGNvbWVzIGZyb20gdGFibGUgUzIgZnJvbSB0aGUgc2FtZSBwYXBlcgpkb25vdmFuaV9zMiA9IHJlYWQuY3N2KCJyZWZlcmVuY2UvZ2ItMjAwOC05LTItcjM1LXMyLmNzdiIsIGhlYWRlcj1UUlVFKQpjb2xuYW1lcyhkb25vdmFuaV9zMikgPSBjKCJhY2Nlc3Npb24iLCJpZCIsIm1lYW5sbW1jbWNhMSIsInJlbF9wZXBfcmF0aW8xIiwibWVhbmxtbWNtY2EyIiwicmVsX3BlcF9yYXRpbzIiLCJtZWFubG1tY21jYTMiLCJyZWxfcGVwX3JhdGlvMyIsIm1lYW5sbW1jbWNhNCIsInJlbF9wZXBfcmF0aW80IiwibWVhbmxtbWNtY2FfYWxsIikKCiMjd3JpdGVfeGxzKGRhdGE9ZG9ub3ZhbmlfczIsIGZpbGU9ImRvbm92YW5pX3MyX3RhYmxlIikKCiMjZGltKHN1YnNldChkb25vdmFuaV9zMiwgbWVhbmxtY21jYV9hbGwgPiAxLjcpKQpoZWFkKGRvbm92YW5pX3MyKQpkb25vdmFuaV9zMiRhY2Nlc3Npb24gPSBnc3ViKHBhdHRlcm49IkxtakYiLCByZXBsYWNlbWVudD0iTG1qRlxcLiIsIHg9ZG9ub3ZhbmlfczIkYWNjZXNzaW9uKQp0cmlfc2NpX3NpZ19mYXNfc2VjID0gbWVyZ2UodHJpX3NjaV9zaWdfZmFzX3NlYywgZG9ub3ZhbmlfczIsIGJ5Lng9IklEIiwgYnkueT0iYWNjZXNzaW9uIiwgYWxsLng9VFJVRSkKCiMjIFRoZSBmb2xsb3dpbmcgdGFibGUgY29tZXMgZnJvbSAxMC4xMzcxL2pvdXJuYWwucG50ZC4wMDAwODQyCiMjIFBMb1MgTmVnbCBUcm9wIERpcy4gMjAxMCBPY3Q7IDQoMTApOiBlODQyCiMjIEl0IGlzIHRhYmxlIDEgZnJvbTogTGVpc2htYW5pYSBlZmZlY3RvciBtb2xlY3VsZXMgaWRlbnRpZmllZCBieSBDTUFULgojIyBJdCByZXF1aXJlZCBhIHNtYWxsIGFtb3VudCBvZiBtYW51YWwgcGxheWluZyB0byBtYWtlIGludG8gYSB1c2FibGUgY3N2CmtpbWEgPSByZWFkLmNzdigicmVmZXJlbmNlL2tpbWFfdGFibGUuY3N2IikKdHJpX3NjaV9zaWdfZmFzX3NlYyA9IG1lcmdlKHRyaV9zY2lfc2lnX2Zhc19zZWMsIGtpbWEsIGJ5Lng9IklEIiwgYnkueT0ibmFtZSIsIGFsbC54PVRSVUUpCgpuZXdfY29sdW1ucyA9IGMoInNlY3JldG9tZV9uYW1lIiwic2VjcmV0b21lX2V4b3NvbWVfYm9vbGVhbiIsInNlY3JldG9tZV9ib29sZWFuIiwiY29tbXVuaWNhdGlvbl9uYW1lIiwiY29tbXVuaWNhdGlvbl9oaXRfdHlwZSIsImxkczJfaWQiLCJsZHMyX2xtbWNtYTEiLCJsZHMyX3JlbHBlcHJhdGlvMSIsImxkczJfbG1tY21hMiIsImxkczJfcmVscGVwcmF0aW8yIiwibGRzMl9sbW1jbWEzIiwibGRzMl9yZWxwZXByYXRpbzMiLCJsZHMyX2xtbWNtYTQiLCJsZHMyX3JlbHBlcHJhdGlvNCIsImxkczJfbWVhbmxtbWNtYSIsImtpbWFfY2xvbmUiLCJraW1hX2hvbW9sb2ciLCJraW1hX2Nocm9tb3NvbWUiLCJraW1hX3NpZ25hbCIsImtpbWFfY29tbWVudCIpCmFsbF9jb2x1bW5zID0gYyhhbGxfY29sdW1ucywgbmV3X2NvbHVtbnMpCmNvbG5hbWVzKHRyaV9zY2lfc2lnX2Zhc19zZWMpID0gYWxsX2NvbHVtbnMKYGBgCgojIyBNZXJnZSBpbiBSTkFTZXEgZGF0YQoKYGBge3IgZGVib3RodXB9CnJuYXNlcV9odW1hbl9tb3VzZSA9IHJlYWQuY3N2KCJjc3YvZ2VuZUlEX0xtYWpvcl9odW1hbl9tb3VzZV9ERWJvdGh1cF9tZXRhY19hbWFzdDQudHh0IiwgaGVhZGVyPUZBTFNFKQpybmFzZXFfaHVtYW5fbW91c2Ukcm5hc2VxX2hzbW11cCA9IDEKcm5hc2VxX2ZvdXJocGkgPSByZWFkLmNzdigiY3N2L1RhYmxlUzctNGhwaS5jc3YiLCBoZWFkZXI9VFJVRSkKCnRyaV9zY2lfc2lnX2Zhc19zZWNfcm5hID0gbWVyZ2UodHJpX3NjaV9zaWdfZmFzX3NlYywgcm5hc2VxX2h1bWFuX21vdXNlLCBieS54PSJJRCIsIGJ5Lnk9IlYxIiwgYWxsLng9VFJVRSkKdHJpX3NjaV9zaWdfZmFzX3NlY19ybmEgPSBtZXJnZSh0cmlfc2NpX3NpZ19mYXNfc2VjX3JuYSwgcm5hc2VxX2ZvdXJocGksIGJ5Lng9IklEIiwgYnkueT0iSUQiLCBhbGwueD1UUlVFKQoKbmV3X2NvbHVtbnMgPSBjKCJybmFzZXFfaHNtbXVwIiwicm5hc2VxXzRocGlkZXNjIiwicm5hc2VxXzRocGlmYyIsInJuYXNlcV80aHBpcHZhbCIsInJuYXNlcV80aHBpcHJlZ29mdW4iLCJybmFzZXFfNGhwaXByZWRnb3Byb2MiKQphbGxfY29sdW1ucyA9IGMoYWxsX2NvbHVtbnMsIG5ld19jb2x1bW5zKQpjb2xuYW1lcyh0cmlfc2NpX3NpZ19mYXNfc2VjX3JuYSkgPSBhbGxfY29sdW1ucwp0cmlfc2NpX3NpZ19mYXNfc2VjX3JuYSRybmFzZXFfaHNtbXVwW2lzLm5hKHRyaV9zY2lfc2lnX2Zhc19zZWNfcm5hJHJuYXNlcV9oc21tdXApXSA9IDAKCiMjd3JpdGVfeGxzKGRhdGE9bWVyZ2VkX2RlLCBmaWxlPSJtZXJnZWQiKQpgYGAKCiMjIE1lcmdlIGluIHJlLWFuYWx5emVkIFJOQVNlcSBkYXRhCgpTaW5jZSBJIGRvIG5vdCBoYXZlIHRoZSBudW1iZXIgb2YgZ2VuZXMgYWxvbmUgZm9yIGJydWNlaS9jcnV6aSwgSSB3aWxsIGNoZWF0IGFuZCBzdWJ0cmFjdCB0aGUgbnVtYmVyCm9ic2VydmVkIGZyb20gdGhlIHNpemUgb2YgdGhlIHR3byBnZW5vbWVzIGFuZCBhc3N1bWUgdGhhdCBpcyBjb3JyZWN0IChpdCBwcm9iYWJseSBpcyBub3QpLgoKCgpgYGB7ciBtZXJnZV9ybmFzZXF9CmxpYnJhcnkoVHhEYi5MbWFqb3IuZnJpZWRsaW4uVHJpVHJ5cERCMjcpCmxpYnJhcnkob3JnLkxtYWpvci5mcmllZGxpbi5lZy5kYikKbGlicmFyeShMZWlzaG1hbmlhLm1ham9yLkZyaWVkbGluKQpzdW1tYXJ5KGdlbmVzKExlaXNobWFuaWEubWFqb3IuRnJpZWRsaW4pKQojIyA5Mzc3CgpsaWJyYXJ5KFR4RGIuVGJydWNlaS5UUkVVOTI3LlRyaVRyeXBEQjI3KQpsaWJyYXJ5KG9yZy5UYnJ1Y2VpLlRSRVU5MjcuZWcuZGIpCmxpYnJhcnkoVHJ5cGFub3NvbWEuYnJ1Y2VpLnRyZXU5MjcpCnN1bW1hcnkoZ2VuZXMoVHJ5cGFub3NvbWEuYnJ1Y2VpLnRyZXU5MjcpKQojIyAxMjA5MwoKbGlicmFyeShUeERiLlRjcnV6aS5DTEJyZW5lckVzbWVyYWxkby5UcmlUcnlwREIyNykKbGlicmFyeShvcmcuVGNydXppLkNMQnJlbmVyRXNtZXJhbGRvLmVnLmRiKQpsaWJyYXJ5KFRyeXBhbm9zb21hLmNydXppLkNMQnJlbmVyLkVzbWVyYWxkbykKIyMgMTA1OTcKc3VtbWFyeShnZW5lcyhUcnlwYW5vc29tYS5jcnV6aS5DTEJyZW5lci5Fc21lcmFsZG8pKQoKcm5hc2VxIDwtIHJlYWQuY3N2KCJjc3YvbG1ham9yX21ldGFjX3ZzX2FtYXN0NC5jc3YiKQpoZWFkKHJuYXNlcSkKaGVhZCh0cmlfc2NpX3NpZ19mYXNfc2VjKQpyb3duYW1lcyhybmFzZXEpIDwtIGdzdWIocGF0dGVybj0iXFwtMSQiLCByZXBsYWNlbWVudD0iIiwgeD1ybmFzZXFbWyJYIl1dKQpybmFzZXFfb3J0aG9sb2dzIDwtIG1lcmdlKHJuYXNlcSwgdHJpX3NjaV9zaWdfZmFzX3NlYywgYnkueD0icm93Lm5hbWVzIiwgYnkueT0iSUQiLCBhbGwueD1UUlVFKQp3cml0ZS5jc3YoZmlsZT0iY3N2L3JuYXNlcV9vcnRob2xvZ3MuY3N2IiwgeD1ybmFzZXFfb3J0aG9sb2dzKQoKIyMgTG0vVGM6ICBUaGUgc2V0IG9mIGdlbmVzIHdoZXJlIHRyaXRyeXBfY3J1emlfaG9tb2xvZ3MgaXMgbm90IE5BCmxtdGNfb3J0aG9sb2d5IDwtICFpcy5uYShybmFzZXFfb3J0aG9sb2dzW1sidHJpdHJ5cF9jcnV6aV9ob21vbG9ncyJdXSkKc3VtKGxtdGNfb3J0aG9sb2d5KQpsbXRjX29ydGhvbG9ncyA8LSBybmFzZXFfb3J0aG9sb2dzW2xtdGNfb3J0aG9sb2d5LF0KbG10Y19vcnRob2xvZ3Nfc2lnIDwtIGxtdGNfb3J0aG9sb2dzW1siYWRqLlAuVmFsIl1dIDw9IDAuMDUKc3VtKGxtdGNfb3J0aG9sb2dzX3NpZykKbG10Y19vcnRob2xvZ3Nfc2lnIDwtIGxtdGNfb3J0aG9sb2dzW2xtdGNfb3J0aG9sb2dzX3NpZywgXQpsbXRjX29ydGhvbG9nc19zaWd1cCA8LSBsbXRjX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA+IDAuMApzdW0obG10Y19vcnRob2xvZ3Nfc2lndXApCmxtdGNfb3J0aG9sb2dzX3NpZ3VwIDwtIGxtdGNfb3J0aG9sb2dzW2xtdGNfb3J0aG9sb2dzX3NpZ3VwLCBdCndyaXRlLmNzdihmaWxlPSJjc3YvbG10Y19vcnRob2xvZ3Nfc2lndXAuY3N2IiwgeD1sbXRjX29ydGhvbG9nc19zaWd1cCkKbG10Y19vcnRob2xvZ3Nfc2lnZG93biA8LSBsbXRjX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA8IDAuMApzdW0obG10Y19vcnRob2xvZ3Nfc2lnZG93bikKbG10Y19vcnRob2xvZ3Nfc2lnZG93biA8LSBsbXRjX29ydGhvbG9nc1tsbXRjX29ydGhvbG9nc19zaWdkb3duLCBdCndyaXRlLmNzdihmaWxlPSJjc3YvbG10Y19vcnRob2xvZ3Nfc2lnZG93bi5jc3YiLCB4PWxtdGNfb3J0aG9sb2dzX3NpZ2Rvd24pCmxtdGNfb3J0aG9sb2dzX3NpZzJ1cCA8LSBsbXRjX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA+PSAxLjAKc3VtKGxtdGNfb3J0aG9sb2dzX3NpZzJ1cCkKbG10Y19vcnRob2xvZ3Nfc2lnMnVwIDwtIGxtdGNfb3J0aG9sb2dzW2xtdGNfb3J0aG9sb2dzX3NpZzJ1cCwgXQp3cml0ZS5jc3YoZmlsZT0iY3N2L2xtdGNfb3J0aG9sb2dzX3NpZzJ1cC5jc3YiLCB4PWxtdGNfb3J0aG9sb2dzX3NpZzJ1cCkKbG10Y19vcnRob2xvZ3Nfc2lnMmRvd24gPC0gbG10Y19vcnRob2xvZ3Nfc2lnW1sibG9nRkMiXV0gPD0gLTEuMApzdW0obG10Y19vcnRob2xvZ3Nfc2lnMmRvd24pCmxtdGNfb3J0aG9sb2dzX3NpZzJkb3duIDwtIGxtdGNfb3J0aG9sb2dzW2xtdGNfb3J0aG9sb2dzX3NpZzJkb3duLCBdCndyaXRlLmNzdihmaWxlPSJjc3YvbG10Y19vcnRob2xvZ3Nfc2lnMmRvd24uY3N2IiwgeD1sbXRjX29ydGhvbG9nc19zaWcyZG93bikKCiMjIExtL1RiOiAgVGhlIHNldCBvZiBnZW5lcyB3aGVyZSB0cml0cnlwX2NydXppX2hvbW9sb2dzIGlzIG5vdCBOQQpsbXRiX29ydGhvbG9neSA8LSAhaXMubmEocm5hc2VxX29ydGhvbG9nc1tbInRyaXRyeXBfYnJ1Y2VpX2hvbW9sb2dzIl1dKQpzdW0obG10Yl9vcnRob2xvZ3kpCmxtdGJfb3J0aG9sb2dzIDwtIHJuYXNlcV9vcnRob2xvZ3NbbG10Yl9vcnRob2xvZ3ksXQpsbXRiX29ydGhvbG9nc19zaWcgPC0gbG10Yl9vcnRob2xvZ3NbWyJhZGouUC5WYWwiXV0gPD0gMC4wNQpzdW0obG10Yl9vcnRob2xvZ3Nfc2lnKQpsbXRiX29ydGhvbG9nc19zaWcgPC1sbXRiX29ydGhvbG9nc1tsbXRiX29ydGhvbG9nc19zaWcsIF0KbG10Yl9vcnRob2xvZ3Nfc2lndXAgPC0gbG10Yl9vcnRob2xvZ3Nfc2lnW1sibG9nRkMiXV0gPiAwLjAKc3VtKGxtdGJfb3J0aG9sb2dzX3NpZ3VwKQpsbXRiX29ydGhvbG9nc19zaWd1cCA8LWxtdGJfb3J0aG9sb2dzW2xtdGJfb3J0aG9sb2dzX3NpZ3VwLCBdCndyaXRlLmNzdihmaWxlPSJjc3YvbG10Yl9vcnRob2xvZ3Nfc2lndXAuY3N2IiwgeD1sbXRiX29ydGhvbG9nc19zaWd1cCkKbG10Yl9vcnRob2xvZ3Nfc2lnZG93biA8LSBsbXRiX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA8IDAuMApzdW0obG10Yl9vcnRob2xvZ3Nfc2lnZG93bikKbG10Yl9vcnRob2xvZ3Nfc2lnZG93biA8LWxtdGJfb3J0aG9sb2dzW2xtdGJfb3J0aG9sb2dzX3NpZ2Rvd24sIF0Kd3JpdGUuY3N2KGZpbGU9ImNzdi9sbXRiX29ydGhvbG9nc19zaWdkb3duLmNzdiIsIHg9bG10Yl9vcnRob2xvZ3Nfc2lnZG93bikKbG10Yl9vcnRob2xvZ3Nfc2lnMnVwIDwtIGxtdGJfb3J0aG9sb2dzX3NpZ1tbImxvZ0ZDIl1dID49IDEuMApzdW0obG10Yl9vcnRob2xvZ3Nfc2lnMnVwKQpsbXRiX29ydGhvbG9nc19zaWcydXAgPC0gbG10Yl9vcnRob2xvZ3NbbG10Yl9vcnRob2xvZ3Nfc2lnMnVwLCBdCndyaXRlLmNzdihmaWxlPSJjc3YvbG10Yl9vcnRob2xvZ3Nfc2lnMnVwLmNzdiIsIHg9bG10Yl9vcnRob2xvZ3Nfc2lnMnVwKQpsbXRiX29ydGhvbG9nc19zaWcyZG93biA8LSBsbXRiX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA8PSAtMS4wCnN1bShsbXRiX29ydGhvbG9nc19zaWcyZG93bikKbG10Yl9vcnRob2xvZ3Nfc2lnMmRvd24gPC0gbG10Yl9vcnRob2xvZ3NbbG10Yl9vcnRob2xvZ3Nfc2lnMmRvd24sIF0Kd3JpdGUuY3N2KGZpbGU9ImNzdi9sbXRiX29ydGhvbG9nc19zaWcyZG93bi5jc3YiLCB4PWxtdGJfb3J0aG9sb2dzX3NpZzJkb3duKQoKIyMgTG0vVGMvVGI6ICBUaGUgc2V0IG9mIGdlbmVzIHdoZXJlIHRyaXRyeXBfY3J1emlfaG9tb2xvZ3MgaXMgbm90IE5BCmxtdGN0Yl9vcnRob2xvZ3kgPC0gIWlzLm5hKHJuYXNlcV9vcnRob2xvZ3NbWyJ0cml0cnlwX2JydWNlaV9ob21vbG9ncyJdXSkgJiAhaXMubmEocm5hc2VxX29ydGhvbG9nc1tbInRyaXRyeXBfY3J1emlfaG9tb2xvZ3MiXV0pCnN1bShsbXRjdGJfb3J0aG9sb2d5KQpsbXRjdGJfb3J0aG9sb2dzIDwtIHJuYXNlcV9vcnRob2xvZ3NbbG10Y3RiX29ydGhvbG9neSxdCmxtdGN0Yl9vcnRob2xvZ3Nfc2lnIDwtIGxtdGN0Yl9vcnRob2xvZ3NbWyJhZGouUC5WYWwiXV0gPD0gMC4wNQpzdW0obG10Y3RiX29ydGhvbG9nc19zaWcpCmxtdGN0Yl9vcnRob2xvZ3Nfc2lnIDwtbG10Y3RiX29ydGhvbG9nc1tsbXRjdGJfb3J0aG9sb2dzX3NpZywgXQpsbXRjdGJfb3J0aG9sb2dzX3NpZ3VwIDwtIGxtdGN0Yl9vcnRob2xvZ3Nfc2lnW1sibG9nRkMiXV0gPiAwLjAKc3VtKGxtdGN0Yl9vcnRob2xvZ3Nfc2lndXApCmxtdGN0Yl9vcnRob2xvZ3Nfc2lndXAgPC1sbXRjdGJfb3J0aG9sb2dzW2xtdGN0Yl9vcnRob2xvZ3Nfc2lndXAsIF0Kd3JpdGUuY3N2KGZpbGU9ImNzdi9sbXRjdGJfb3J0aG9sb2dzX3NpZ3VwLmNzdiIsIHg9bG10Y3RiX29ydGhvbG9nc19zaWd1cCkKbG10Y3RiX29ydGhvbG9nc19zaWdkb3duIDwtIGxtdGN0Yl9vcnRob2xvZ3Nfc2lnW1sibG9nRkMiXV0gPCAwLjAKc3VtKGxtdGN0Yl9vcnRob2xvZ3Nfc2lnZG93bikKbG10Y3RiX29ydGhvbG9nc19zaWdkb3duIDwtbG10Y3RiX29ydGhvbG9nc1tsbXRjdGJfb3J0aG9sb2dzX3NpZ2Rvd24sIF0Kd3JpdGUuY3N2KGZpbGU9ImNzdi9sbXRjdGJfb3J0aG9sb2dzX3NpZ2Rvd24uY3N2IiwgeD1sbXRjdGJfb3J0aG9sb2dzX3NpZ2Rvd24pCmxtdGN0Yl9vcnRob2xvZ3Nfc2lnMnVwIDwtIGxtdGN0Yl9vcnRob2xvZ3Nfc2lnW1sibG9nRkMiXV0gPj0gMS4wCnN1bShsbXRjdGJfb3J0aG9sb2dzX3NpZzJ1cCkKbG10Y3RiX29ydGhvbG9nc19zaWcydXAgPC0gbG10Y3RiX29ydGhvbG9nc1tsbXRjdGJfb3J0aG9sb2dzX3NpZzJ1cCwgXQp3cml0ZS5jc3YoZmlsZT0iY3N2L2xtdGN0Yl9vcnRob2xvZ3Nfc2lnMnVwLmNzdiIsIHg9bG10Y3RiX29ydGhvbG9nc19zaWcydXApCmxtdGN0Yl9vcnRob2xvZ3Nfc2lnMmRvd24gPC0gbG10Y3RiX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA8PSAtMS4wCnN1bShsbXRjdGJfb3J0aG9sb2dzX3NpZzJkb3duKQpsbXRjdGJfb3J0aG9sb2dzX3NpZzJkb3duIDwtIGxtdGN0Yl9vcnRob2xvZ3NbbG10Y3RiX29ydGhvbG9nc19zaWcyZG93biwgXQp3cml0ZS5jc3YoZmlsZT0iY3N2L2xtdGN0Yl9vcnRob2xvZ3Nfc2lnMmRvd24uY3N2IiwgeD1sbXRjdGJfb3J0aG9sb2dzX3NpZzJkb3duKQoKIyMgTG0vVGMvTk9UVGI6ICBUaGUgc2V0IG9mIGdlbmVzIHdoZXJlIHRyaXRyeXBfY3J1emlfaG9tb2xvZ3MgaXMgbm90IE5BIGJ1dCBicnVjZWkgaXMgTmEKbG10Y19ub3RiX29ydGhvbG9neSA8LSAhaXMubmEocm5hc2VxX29ydGhvbG9nc1tbInRyaXRyeXBfY3J1emlfaG9tb2xvZ3MiXV0pICYgaXMubmEocm5hc2VxX29ydGhvbG9nc1tbInRyaXRyeXBfYnJ1Y2VpX2hvbW9sb2dzIl1dKQpzdW0obG10Y19ub3RiX29ydGhvbG9neSkKbG10Y19ub3RiX29ydGhvbG9ncyA8LSBybmFzZXFfb3J0aG9sb2dzW2xtdGNfbm90Yl9vcnRob2xvZ3ksXQpsbXRjX25vdGJfb3J0aG9sb2dzX3NpZyA8LSBsbXRjX25vdGJfb3J0aG9sb2dzW1siYWRqLlAuVmFsIl1dIDw9IDAuMDUKc3VtKGxtdGNfbm90Yl9vcnRob2xvZ3Nfc2lnKQpsbXRjX25vdGJfb3J0aG9sb2dzX3NpZyA8LWxtdGNfbm90Yl9vcnRob2xvZ3NbbG10Y19ub3RiX29ydGhvbG9nc19zaWcsIF0KbG10Y19ub3RiX29ydGhvbG9nc19zaWd1cCA8LSBsbXRjX25vdGJfb3J0aG9sb2dzX3NpZ1tbImxvZ0ZDIl1dID4gMC4wCnN1bShsbXRjX25vdGJfb3J0aG9sb2dzX3NpZ3VwKQpsbXRjX25vdGJfb3J0aG9sb2dzX3NpZ3VwIDwtbG10Y19ub3RiX29ydGhvbG9nc1tsbXRjX25vdGJfb3J0aG9sb2dzX3NpZ3VwLCBdCndyaXRlLmNzdihmaWxlPSJjc3YvbG10Y19ub3RiX29ydGhvbG9nc19zaWd1cC5jc3YiLCB4PWxtdGNfbm90Yl9vcnRob2xvZ3Nfc2lndXApCmxtdGNfbm90Yl9vcnRob2xvZ3Nfc2lnZG93biA8LSBsbXRjX25vdGJfb3J0aG9sb2dzX3NpZ1tbImxvZ0ZDIl1dIDwgMC4wCnN1bShsbXRjX25vdGJfb3J0aG9sb2dzX3NpZ2Rvd24pCmxtdGNfbm90Yl9vcnRob2xvZ3Nfc2lnZG93biA8LWxtdGNfbm90Yl9vcnRob2xvZ3NbbG10Y19ub3RiX29ydGhvbG9nc19zaWdkb3duLCBdCndyaXRlLmNzdihmaWxlPSJjc3YvbG10Y19ub3RiX29ydGhvbG9nc19zaWdkb3duLmNzdiIsIHg9bG10Y19ub3RiX29ydGhvbG9nc19zaWdkb3duKQpsbXRjX25vdGJfb3J0aG9sb2dzX3NpZzJ1cCA8LSBsbXRjX25vdGJfb3J0aG9sb2dzX3NpZ1tbImxvZ0ZDIl1dID49IDEuMApzdW0obG10Y19ub3RiX29ydGhvbG9nc19zaWcydXApCmxtdGNfbm90Yl9vcnRob2xvZ3Nfc2lnMnVwIDwtIGxtdGNfbm90Yl9vcnRob2xvZ3NbbG10Y19ub3RiX29ydGhvbG9nc19zaWcydXAsIF0Kd3JpdGUuY3N2KGZpbGU9ImNzdi9sbXRjX25vdGJfb3J0aG9sb2dzX3NpZzJ1cC5jc3YiLCB4PWxtdGNfbm90Yl9vcnRob2xvZ3Nfc2lnMnVwKQpsbXRjX25vdGJfb3J0aG9sb2dzX3NpZzJkb3duIDwtIGxtdGNfbm90Yl9vcnRob2xvZ3Nfc2lnW1sibG9nRkMiXV0gPD0gLTEuMApzdW0obG10Y19ub3RiX29ydGhvbG9nc19zaWcyZG93bikKbG10Y19ub3RiX29ydGhvbG9nc19zaWcyZG93biA8LSBsbXRjX25vdGJfb3J0aG9sb2dzW2xtdGNfbm90Yl9vcnRob2xvZ3Nfc2lnMmRvd24sIF0Kd3JpdGUuY3N2KGZpbGU9ImNzdi9sbXRjX25vdGJfb3J0aG9sb2dzX3NpZzJkb3duLmNzdiIsIHg9bG10Y19ub3RiX29ydGhvbG9nc19zaWcyZG93bikKCiMjIExtL1RiL05PVFRjOiAgVGhlIHNldCBvZiBnZW5lcyB3aGVyZSB0cml0cnlwX2JydWNlaV9ob21vbG9ncyBpcyBub3QgTkEgYnV0IGNydXppIGlzIE5BCmxtdGJfbm90Y19vcnRob2xvZ3kgPC0gIWlzLm5hKHJuYXNlcV9vcnRob2xvZ3NbWyJ0cml0cnlwX2JydWNlaV9ob21vbG9ncyJdXSkgJiBpcy5uYShybmFzZXFfb3J0aG9sb2dzW1sidHJpdHJ5cF9jcnV6aV9ob21vbG9ncyJdXSkKc3VtKGxtdGJfbm90Y19vcnRob2xvZ3kpCmxtdGJfbm90Y19vcnRob2xvZ3MgPC0gcm5hc2VxX29ydGhvbG9nc1tsbXRiX25vdGNfb3J0aG9sb2d5LF0KbG10Yl9ub3RjX29ydGhvbG9nc19zaWcgPC0gbG10Yl9ub3RjX29ydGhvbG9nc1tbImFkai5QLlZhbCJdXSA8PSAwLjA1CnN1bShsbXRiX25vdGNfb3J0aG9sb2dzX3NpZykKbG10Yl9ub3RjX29ydGhvbG9nc19zaWcgPC1sbXRiX25vdGNfb3J0aG9sb2dzW2xtdGJfbm90Y19vcnRob2xvZ3Nfc2lnLCBdCmxtdGJfbm90Y19vcnRob2xvZ3Nfc2lndXAgPC0gbG10Yl9ub3RjX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA+IDAuMApzdW0obG10Yl9ub3RjX29ydGhvbG9nc19zaWd1cCkKbG10Yl9ub3RjX29ydGhvbG9nc19zaWd1cCA8LWxtdGJfbm90Y19vcnRob2xvZ3NbbG10Yl9ub3RjX29ydGhvbG9nc19zaWd1cCwgXQp3cml0ZS5jc3YoZmlsZT0iY3N2L2xtdGJfbm90Y19vcnRob2xvZ3Nfc2lndXAuY3N2IiwgeD1sbXRiX25vdGNfb3J0aG9sb2dzX3NpZ3VwKQpsbXRiX25vdGNfb3J0aG9sb2dzX3NpZ2Rvd24gPC0gbG10Yl9ub3RjX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA8IDAuMApzdW0obG10Yl9ub3RjX29ydGhvbG9nc19zaWdkb3duKQpsbXRiX25vdGNfb3J0aG9sb2dzX3NpZ2Rvd24gPC1sbXRiX25vdGNfb3J0aG9sb2dzW2xtdGJfbm90Y19vcnRob2xvZ3Nfc2lnZG93biwgXQp3cml0ZS5jc3YoZmlsZT0iY3N2L2xtdGJfbm90Y19vcnRob2xvZ3Nfc2lnZG93bi5jc3YiLCB4PWxtdGJfbm90Y19vcnRob2xvZ3Nfc2lnZG93bikKbG10Yl9ub3RjX29ydGhvbG9nc19zaWcydXAgPC0gbG10Yl9ub3RjX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA+PSAxLjAKc3VtKGxtdGJfbm90Y19vcnRob2xvZ3Nfc2lnMnVwKQpsbXRiX25vdGNfb3J0aG9sb2dzX3NpZzJ1cCA8LSBsbXRiX25vdGNfb3J0aG9sb2dzW2xtdGJfbm90Y19vcnRob2xvZ3Nfc2lnMnVwLCBdCndyaXRlLmNzdihmaWxlPSJjc3YvbG10Yl9ub3RjX29ydGhvbG9nc19zaWcydXAuY3N2IiwgeD1sbXRiX25vdGNfb3J0aG9sb2dzX3NpZzJ1cCkKbG10Yl9ub3RjX29ydGhvbG9nc19zaWcyZG93biA8LSBsbXRiX25vdGNfb3J0aG9sb2dzX3NpZ1tbImxvZ0ZDIl1dIDw9IC0xLjAKc3VtKGxtdGJfbm90Y19vcnRob2xvZ3Nfc2lnMmRvd24pCmxtdGJfbm90Y19vcnRob2xvZ3Nfc2lnMmRvd24gPC0gbG10Yl9ub3RjX29ydGhvbG9nc1tsbXRiX25vdGNfb3J0aG9sb2dzX3NpZzJkb3duLCBdCndyaXRlLmNzdihmaWxlPSJjc3YvbG10Yl9ub3RjX29ydGhvbG9nc19zaWcyZG93bi5jc3YiLCB4PWxtdGJfbm90Y19vcnRob2xvZ3Nfc2lnMmRvd24pCgojIyBMbS9OT1RiL05PVFRjOiAgVGhlIHNldCBvZiBnZW5lcyB3aGVyZSB0cml0cnlwX2JydWNlaV9ob21vbG9ncyBpcyBOQSBhbmQgY3J1emkgaXMgTkEKbG1fbm90Ym5vdGNfb3J0aG9sb2d5IDwtIGlzLm5hKHJuYXNlcV9vcnRob2xvZ3NbWyJ0cml0cnlwX2JydWNlaV9ob21vbG9ncyJdXSkgJiBpcy5uYShybmFzZXFfb3J0aG9sb2dzW1sidHJpdHJ5cF9jcnV6aV9ob21vbG9ncyJdXSkKc3VtKGxtX25vdGJub3RjX29ydGhvbG9neSkKbG1fbm90Ym5vdGNfb3J0aG9sb2dzIDwtIHJuYXNlcV9vcnRob2xvZ3NbbG1fbm90Ym5vdGNfb3J0aG9sb2d5LF0KbG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZyA8LSBsbV9ub3Ribm90Y19vcnRob2xvZ3NbWyJhZGouUC5WYWwiXV0gPD0gMC4wNQpzdW0obG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZykKbG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZyA8LWxtX25vdGJub3RjX29ydGhvbG9nc1tsbV9ub3Ribm90Y19vcnRob2xvZ3Nfc2lnLCBdCmxtX25vdGJub3RjX29ydGhvbG9nc19zaWd1cCA8LSBsbV9ub3Ribm90Y19vcnRob2xvZ3Nfc2lnW1sibG9nRkMiXV0gPiAwLjAKc3VtKGxtX25vdGJub3RjX29ydGhvbG9nc19zaWd1cCkKbG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZ3VwIDwtbG1fbm90Ym5vdGNfb3J0aG9sb2dzW2xtX25vdGJub3RjX29ydGhvbG9nc19zaWd1cCwgXQp3cml0ZS5jc3YoZmlsZT0iY3N2L2xtX25vdGJub3RjX29ydGhvbG9nc19zaWd1cC5jc3YiLCB4PWxtX25vdGJub3RjX29ydGhvbG9nc19zaWd1cCkKbG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZ2Rvd24gPC0gbG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZ1tbImxvZ0ZDIl1dIDwgMC4wCnN1bShsbV9ub3Ribm90Y19vcnRob2xvZ3Nfc2lnZG93bikKbG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZ2Rvd24gPC1sbV9ub3Ribm90Y19vcnRob2xvZ3NbbG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZ2Rvd24sIF0Kd3JpdGUuY3N2KGZpbGU9ImNzdi9sbV9ub3Ribm90Y19vcnRob2xvZ3Nfc2lnZG93bi5jc3YiLCB4PWxtX25vdGJub3RjX29ydGhvbG9nc19zaWdkb3duKQpsbV9ub3Ribm90Y19vcnRob2xvZ3Nfc2lnMnVwIDwtIGxtX25vdGJub3RjX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA+PSAxLjAKc3VtKGxtX25vdGJub3RjX29ydGhvbG9nc19zaWcydXApCmxtX25vdGJub3RjX29ydGhvbG9nc19zaWcydXAgPC0gbG1fbm90Ym5vdGNfb3J0aG9sb2dzW2xtX25vdGJub3RjX29ydGhvbG9nc19zaWcydXAsIF0Kd3JpdGUuY3N2KGZpbGU9ImNzdi9sbV9ub3Ribm90Y19vcnRob2xvZ3Nfc2lnMnVwLmNzdiIsIHg9bG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZzJ1cCkKbG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZzJkb3duIDwtIGxtX25vdGJub3RjX29ydGhvbG9nc19zaWdbWyJsb2dGQyJdXSA8PSAtMS4wCnN1bShsbV9ub3Ribm90Y19vcnRob2xvZ3Nfc2lnMmRvd24pCmxtX25vdGJub3RjX29ydGhvbG9nc19zaWcyZG93biA8LSBsbV9ub3Ribm90Y19vcnRob2xvZ3NbbG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZzJkb3duLCBdCndyaXRlLmNzdihmaWxlPSJjc3YvbG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZzJkb3duLmNzdiIsIHg9bG1fbm90Ym5vdGNfb3J0aG9sb2dzX3NpZzJkb3duKQoKbGlicmFyeSh2ZW5uZXVsZXIpCmxpYnJhcnkoaHBnbHRvb2xzKQoKIyMgVGhpcyBwbG90cyB0aGUgc2V0IG9mIHAtdmFsdWUgdXBzIG5vdCBsb2cyIGxpbWl0ZWQKb25lcyA8LSBjKCJMbSI9MzEwLCAiVGMiPTMwNiwgIlRiIj0zNTgpCnR3b3MgPC0gYygiTG0mVGMiPTg1LCAiTG0mVGIiPTI0KQp0aHJlZXMgPC0gYygiTG0mVGImVGMiPTEzMTMpCmZ1bl92ZW5uX3Bsb3Qob25lcz1vbmVzLCB0d29zPXR3b3MsIHRocmVlcz10aHJlZXMpCgojIyBSZXBlYXQgZm9yIHRoZSBwLXZhbHVlIGRvd25zIG5vdCBsb2cyIGxpbWl0ZWQKdGhyZWVzIDwtIGMoIkxtJlRiJlRjIiA9IDk0NykKdHdvcyA8LSBjKCJMbSZUYyIgPSA3MSwgIkxtJlRiIiA9IDI0KQpvbmVzIDwtIGMoIkxtIiA9IDQ1MCwgIlRjIiA9IDMyNiwgIlRiIiA9IDM4MCkKZnVuX3Zlbm5fcGxvdChvbmVzPW9uZXMsIHR3b3M9dHdvcywgdGhyZWVzPXRocmVlcykKCiMjIFJlcGVhdCBmb3IgdGhlIHAtdmFsdWUgdXBzIHdpdGggbG9nMiBsaW1pdAp0aHJlZXMgPC0gYygiTG0mVGImVGMiID0gODQpCnR3b3MgPC0gYygiTG0mVGMiID0gMiwgIkxtJlRiIiA9IDApCm9uZXMgPC0gYygiTG0iID0gMjcsICJUYyIgPSAyMCwgIlRiIiA9IDI0KQpmdW5fdmVubl9wbG90KG9uZXM9b25lcywgdHdvcz10d29zLCB0aHJlZXM9dGhyZWVzKQoKIyMgUmVwZWF0IGZvciB0aGUgcC12YWx1ZSBkb3ducyB3aXRoIGxvZzIgbGltaXQKdGhyZWVzIDwtIGMoIkxtJlRiJlRjIiA9IDEwOSkKdHdvcyA8LSBjKCJMbSZUYyIgPSA2LCAiTG0mVGIiID0gMikKb25lcyA8LSBjKCJMbSIgPSA3NCwgIlRjIiA9IDYwLCAiVGIiID0gNjYpCmZ1bl92ZW5uX3Bsb3Qob25lcz1vbmVzLCB0d29zPXR3b3MsIHRocmVlcz10aHJlZXMpCmBgYAoKIyMgQW4gcXVlcnkgZXhhbXBsZQpgYGB7ciBybmFkb21fcXVlcmllcywgZXZhbD1GQUxTRX0KIyNzYXZlKGxpc3Q9YygnbWVyZ2VkX2RlJyksIGZpbGU9Im1lcmdlZF90YWJsZS5SRGF0YSIpCmxvYWQoJ21lcmdlZF90YWJsZS5SRGF0YScpCmxpYnJhcnkoc3FsZGYpCmhlYWQobWVyZ2VkX2RlKQpjb2xuYW1lcyhtZXJnZWRfZGUpCmFsbF9mYXN0YV9sb3dfZSA9IHNxbGRmKCJTRUxFQ1QgKiBmcm9tIG1lcmdlZF9kZSBXSEVSRSBmYXN0YV9lIDwgJzAuMDAxJyIpCmhlYWQoYWxsX2Zhc3RhX2xvd19lKQoKZGVfdXAgPSBzcWxkZigiU0VMRUNUICogRlJPTSBtZXJnZWRfZGVfZm91ciBXSEVSRSBmb3VyaHBpX2ZjID4gJzEnIikKZGVfdXBfc2VjID0gc3FsZGYoIlNFTEVDVCAqIEZST00gZGVfdXAgV0hFUkUgc2VjcmV0b21lX25hbWUgaXMgbm90IE5VTEwgYW5kIGZvdXJocGlfZmMgPiAnMiciKQoKZGVfdXB1cCA9IHNxbGRmKCJTRUxFQ1QgKiBGUk9NIG1lcmdlZF9kZV9mb3VyIFdIRVJFIGZvdXJocGlfZmMgPiAnMiciKQpkZV91cF9ub2h1bWFuID0gc3FsZGYoIlNFTEVDVCAqIEZST00gZGVfdXAgV0hFUkUgZmFzdGFfZSBpcyBOVUxMIikKZGVfdXBfbm9odW1hbl9yYW5rZWQgPSBkZV91cF9ub2h1bWFuWyBvcmRlcihkZV91cF9ub2h1bWFuJGZvdXJocGlfZmMsIGRlY3JlYXNpbmc9VFJVRSksXQpkZV91cF9ub2h1bWFuX3JhbmtlZF8yMDAgPSBoZWFkKGRlX3VwX25vaHVtYW5fcmFua2VkLCBuPTIwMCkKZGVfdXBfbm9odW1hbl9yYW5rZWRfbm90YiA9IHNxbGRmKCJTRUxFQ1QgKiBGUk9NIGRlX3VwX25vaHVtYW5fcmFua2VkXzIwMCBXSEVSRSB0cml0cnlwX2JydWNlaV9ob21vbG9ncyBpcyBOVUxMIikKCmEgPSBkZV91cF9ub2h1bWFuX3JhbmtlZF9ub3RiCgpkaW0oZGVfdXBfbm9odW1hbikKZGVfdXBfbm9odW1hbl9zaWduYWxwID0gc3FsZGYoIlNFTEVDVCAqIEZST00gZGVfdXBfbm9odW1hbiBXSEVSRSBzaWduYWxwX3Njb3JlIGlzIG5vdCBOVUxMIikKZGltKGRlX3VwX25vaHVtYW5fc2lnbmFscCkKCmZjX2ZpbHRlcjIgPSBzcWxkZigiU0VMRUNUICogRlJPTSBkZV91cF9ub2h1bWFuX3NpZ25hbHAgV0hFUkUgZm91cmhwaV9mYyA+ICcyJyIpCmZjX2ZpbHRlciA9IHNxbGRmKCJTRUxFQ1QgKiBGUk9NIGRlX3VwX25vaHVtYW5fc2lnbmFscCBXSEVSRSBmb3VyaHBpX2ZjID4gJzEuNSciKQpmY19maWx0ZXJfbm9icnVjZWkgPSBzcWxkZigiU0VMRUNUICogRlJPTSBmY19maWx0ZXIgV0hFUkUgdHJpdHJ5cF9icnVjZWlfaG9tb2xvZ3MgaXMgTlVMTCIpCmZjX2ZpbHRlcl9ub2hvbW9sb2cgPSBzcWxkZigiU0VMRUNUICogRlJPTSBmY19maWx0ZXIgV0hFUkUgdHJpdHJ5cF9icnVjZWlfaG9tb2xvZ3MgaXMgTlVMTCBBTkQgdHJpdHJ5cF9jcnV6aV9ob21vbG9ncyBpcyBOVUxMIikKZGltKGZjX2ZpbHRlcl9ub2hvbW9sb2cpCgpmY19maWx0ZXIyJHNlY3JldG9tZV9uYW1lCmZjX2ZpbHRlcl9ub2hvbW9sb2ckc2VjcmV0b21lX25hbWUKCnNlY3JldG9tZV9oaXRzID0gc3FsZGYoIlNFTEVDVCAqIEZST00gbWVyZ2VkX2RlX2ZvdXIgV0hFUkUgc2VjcmV0b21lX25hbWUgaXMgbm90IE5VTEwiKQpgYGAKCiMgV2hhdCBOYWppYiwgU2Fsb2UsIENlY2lsaWEgd2FudCBmcm9tIHRoaXM6CgogQmVmb3JlIHByaW50aW5nIHRoZSB0YWJsZXMgYmVsb3csIHBlcmZvcm0gdGhlIGZvbGxvd2luZyBvcGVyYXRpb25zLgoKMS4gIEkgdGhpbmsgYWRkIGEgY29sdW1uIGluY2x1ZGluZyB0aGUgZGVib3RodXAgbW91c2UgZGF0YSBhcyBhIGJvb2xlYW4KMi4gIEkgdGhpbmsgYWRkIHRoZSBLaW1hIGV0IGFsLiBkYXRhLgoKIE9uY2UgY29tcGxldGUsIGRvIHRoZSBmb2xsb3dpbmc6CgojIyBGb3IgU2Fsb2UKClByb3ZpZGUgYSB0YWJsZSB3aGljaCBpczoKYS4gIFJhbmsgb3JkZXIgYWxsIGJ5IGZvbGQgY2hhbmdlIChoaWdoZXN0LT5sb3dlc3QpCgpUaGlzIHRhYmxlIGluY2x1ZGVzIG9ubHkgY29sdW1ucyBkZXNjcmliaW5nIHRoZSBmb2xsb3dpbmc6CmEuIElELCBGQywgdGJydWNlaSBib29sZWFuLCBtZWFuX2NtY2EgPiAxLjcgYm9vbGVhbiwgbW91c2UgYm9vbGVhbiwga2ltYSBib29sZWFuLCBzdW0gb2YgY29sdW1ucyAoMyw0LDUsNikKCmBgYHtyIGZvcl9zYWxvZSwgZXZhbD1GQUxTRX0KIyMgUmVxdWlzaXRlICMxOiBUaGUgc2V0IG9mIGdlbmVzIHdoaWNoIGFyZSBub3QgaW4gdGhlIGZhc3RhIHNlYXJjaCBiZXR3ZWVuIGxtYWpvciBhbmQgaG9tbyBzYXBpZW5zLgpzYWxvZV9zdGFydCA9IHRyaV9zY2lfc2lnX2Zhc19zZWNfcm5hCmxpYnJhcnkoInNxbGRmIikKc2Fsb2UgPSBzcWxkZigiU0VMRUNUICogRlJPTSBzYWxvZV9zdGFydCBXSEVSRSBmYXN0YV9lIGlzIE5VTEwiKQpzYWxvZSA9IHNhbG9lWyBvcmRlcihzYWxvZSRybmFzZXFfNGhwaWZjLCBkZWNyZWFzaW5nPVRSVUUpLF0Kc2Fsb2UgPSBzYWxvZVssYygiSUQiLCJybmFzZXFfNGhwaWZjIiwicm5hc2VxXzRocGlwdmFsIiwidHJpdHJ5cF9icnVjZWlfaG9tb2xvZ3MiLCJsZHMyX21lYW5sbW1jbWEiLCJybmFzZXFfaHNtbXVwIiwia2ltYV9jbG9uZSIpXQpzYWxvZSR0cml0cnlwX2JydWNlaV9ob21vbG9nc1tpcy5uYShzYWxvZSR0cml0cnlwX2JydWNlaV9ob21vbG9ncyldID0gMApzYWxvZSR0cml0cnlwX2JydWNlaV9ob21vbG9nc1tzYWxvZSR0cml0cnlwX2JydWNlaV9ob21vbG9ncyAhPSAwXSA9IDEKc2Fsb2UkdHJpdHJ5cF9icnVjZWlfaG9tb2xvZ3MgPSBhcy5udW1lcmljKHNhbG9lJHRyaXRyeXBfYnJ1Y2VpX2hvbW9sb2dzKQpzYWxvZSRraW1hX2Nsb25lW2lzLm5hKHNhbG9lJGtpbWFfY2xvbmUpXSA9IDAKc2Fsb2UkbGRzMl9tZWFubG1tY21hID0gYXMubnVtZXJpYyhzYWxvZSRsZHMyX21lYW5sbW1jbWEpCnNhbG9lJGxkczJfbWVhbmxtbWNtYVtpcy5uYShzYWxvZSRsZHMyX21lYW5sbW1jbWEpXSA9IDAKc2Fsb2UkbGRzMl9tZWFubG1tY21hW3NhbG9lJGxkczJfbWVhbmxtbWNtYSA8IDEuNyBdID0gMApzYWxvZSRsZHMyX21lYW5sbW1jbWFbc2Fsb2UkbGRzMl9tZWFubG1tY21hID49IDEuNyBdID0gMQoKd3JpdGVfeGxzKGRhdGE9c2Fsb2UsIGZpbGU9InNhbG9lX3YxIikKYGBgCgojIFNhdmUgbWUhCgpgYGB7ciBzYXZlbWV9CnR0IDwtIHNtKHNhdmVtZShmaWxlbmFtZT0ieHJlZnMucmRhLnh6IikpCmBgYAo=