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

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

setwd('R://JDBG2022-A6322/Results/Sequencing/First and Second Batch combined analysis')

library(fgsea)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
library(stats)
library(cowplot)
library(DESeq2)
Loading required package: S4Vectors
Loading required package: stats4
Loading required package: BiocGenerics

Attaching package: ‘BiocGenerics’

The following objects are masked from ‘package:stats’:

    IQR, mad, sd, var, xtabs

The following objects are masked from ‘package:base’:

    anyDuplicated, aperm, append, as.data.frame, basename, cbind, colnames, dirname, do.call, duplicated, eval, evalq, Filter, Find, get, grep,
    grepl, intersect, is.unsorted, lapply, Map, mapply, match, mget, order, paste, pmax, pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce,
    rownames, sapply, setdiff, sort, table, tapply, union, unique, unsplit, which.max, which.min


Attaching package: ‘S4Vectors’

The following object is masked from ‘package:utils’:

    findMatches

The following objects are masked from ‘package:base’:

    expand.grid, I, unname

Loading required package: IRanges

Attaching package: ‘IRanges’

The following object is masked from ‘package:grDevices’:

    windows

Loading required package: GenomicRanges
Loading required package: GenomeInfoDb
Loading required package: SummarizedExperiment
Loading required package: MatrixGenerics
Loading required package: matrixStats

Attaching package: ‘MatrixGenerics’

The following objects are masked from ‘package:matrixStats’:

    colAlls, colAnyNAs, colAnys, colAvgsPerRowSet, colCollapse, colCounts, colCummaxs, colCummins, colCumprods, colCumsums, colDiffs, colIQRDiffs,
    colIQRs, colLogSumExps, colMadDiffs, colMads, colMaxs, colMeans2, colMedians, colMins, colOrderStats, colProds, colQuantiles, colRanges,
    colRanks, colSdDiffs, colSds, colSums2, colTabulates, colVarDiffs, colVars, colWeightedMads, colWeightedMeans, colWeightedMedians,
    colWeightedSds, colWeightedVars, rowAlls, rowAnyNAs, rowAnys, rowAvgsPerColSet, rowCollapse, rowCounts, rowCummaxs, rowCummins, rowCumprods,
    rowCumsums, rowDiffs, rowIQRDiffs, rowIQRs, rowLogSumExps, rowMadDiffs, rowMads, rowMaxs, rowMeans2, rowMedians, rowMins, rowOrderStats,
    rowProds, rowQuantiles, rowRanges, rowRanks, rowSdDiffs, rowSds, rowSums2, rowTabulates, rowVarDiffs, rowVars, rowWeightedMads, rowWeightedMeans,
    rowWeightedMedians, rowWeightedSds, rowWeightedVars

Loading required package: Biobase
Welcome to Bioconductor

    Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor, see 'citation("Biobase")', and for packages
    'citation("pkgname")'.


Attaching package: ‘Biobase’

The following object is masked from ‘package:MatrixGenerics’:

    rowMedians

The following objects are masked from ‘package:matrixStats’:

    anyMissing, rowMedians
library(ggplot2)
library(EnhancedVolcano)
Loading required package: ggrepel
library(genefilter)

Attaching package: ‘genefilter’

The following objects are masked from ‘package:MatrixGenerics’:

    rowSds, rowVars

The following objects are masked from ‘package:matrixStats’:

    rowSds, rowVars
library(calibrate)
Loading required package: MASS

Attaching package: ‘MASS’

The following object is masked from ‘package:genefilter’:

    area
library(RColorBrewer)
library(ComplexHeatmap)
Loading required package: grid
========================================
ComplexHeatmap version 2.16.0
Bioconductor page: http://bioconductor.org/packages/ComplexHeatmap/
Github page: https://github.com/jokergoo/ComplexHeatmap
Documentation: http://jokergoo.github.io/ComplexHeatmap-reference

If you use it in published research, please cite either one:
- Gu, Z. Complex Heatmap Visualization. iMeta 2022.
- Gu, Z. Complex heatmaps reveal patterns and correlations in multidimensional 
    genomic data. Bioinformatics 2016.


The new InteractiveComplexHeatmap package can directly export static 
complex heatmaps into an interactive Shiny app with zero effort. Have a try!

This message can be suppressed by:
  suppressPackageStartupMessages(library(ComplexHeatmap))
========================================


Attaching package: ‘ComplexHeatmap’

The following object is masked from ‘package:genefilter’:

    dist2
library(goseq)
Loading required package: BiasedUrn
Loading required package: geneLenDataBase
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      

Attaching package: ‘geneLenDataBase’

The following object is masked from ‘package:S4Vectors’:

    unfactor
library(geneLenDataBase)
library(gage)
library(AnnotationDbi)

Attaching package: ‘AnnotationDbi’

The following object is masked from ‘package:MASS’:

    select
library(org.Mm.eg.db)
library(reshape2)
library(pathview)

##############################################################################
Pathview is an open source software package distributed under GNU General
Public License version 3 (GPLv3). Details of GPLv3 is available at
http://www.gnu.org/licenses/gpl-3.0.html. Particullary, users are required to
formally cite the original Pathview paper (not just mention it) in publications
or products. For details, do citation("pathview") within R.

The pathview downloads and uses KEGG data. Non-academic uses may require a KEGG
license agreement (details at http://www.kegg.jp/kegg/legal.html).
##############################################################################
library(dplyr)

Attaching package: ‘dplyr’

The following object is masked from ‘package:AnnotationDbi’:

    select

The following object is masked from ‘package:MASS’:

    select

The following object is masked from ‘package:Biobase’:

    combine

The following object is masked from ‘package:matrixStats’:

    count

The following objects are masked from ‘package:GenomicRanges’:

    intersect, setdiff, union

The following object is masked from ‘package:GenomeInfoDb’:

    intersect

The following objects are masked from ‘package:IRanges’:

    collapse, desc, intersect, setdiff, slice, union

The following objects are masked from ‘package:S4Vectors’:

    first, intersect, rename, setdiff, setequal, union

The following objects are masked from ‘package:BiocGenerics’:

    combine, intersect, setdiff, union

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(VennDiagram)
Loading required package: futile.logger
library(magrittr)

Attaching package: ‘magrittr’

The following object is masked from ‘package:GenomicRanges’:

    subtract
library(clusterProfiler)
clusterProfiler v4.8.1  For help: https://yulab-smu.top/biomedical-knowledge-mining-book/

If you use clusterProfiler in published research, please cite:
T Wu, E Hu, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, X Fu, S Liu, X Bo, and G Yu. clusterProfiler 4.0: A universal enrichment tool for interpreting omics data. The Innovation. 2021, 2(3):100141

Attaching package: ‘clusterProfiler’

The following object is masked from ‘package:AnnotationDbi’:

    select

The following object is masked from ‘package:MASS’:

    select

The following object is masked from ‘package:IRanges’:

    slice

The following object is masked from ‘package:S4Vectors’:

    rename

The following object is masked from ‘package:stats’:

    filter
library(AnnotationDbi)
library(PoiClaClu)
library(tidyr)

Attaching package: ‘tidyr’

The following object is masked from ‘package:magrittr’:

    extract

The following object is masked from ‘package:reshape2’:

    smiths

The following object is masked from ‘package:S4Vectors’:

    expand
library(tibble)
library(msigdbr)
library(ggpubr)

Attaching package: ‘ggpubr’

The following object is masked from ‘package:VennDiagram’:

    rotate

The following object is masked from ‘package:cowplot’:

    get_legend
library(GO.db)
library(GOstats)
Loading required package: Category
Loading required package: Matrix

Attaching package: ‘Matrix’

The following objects are masked from ‘package:tidyr’:

    expand, pack, unpack

The following object is masked from ‘package:S4Vectors’:

    expand

Loading required package: graph
Warning: replacing previous import ‘utils::findMatches’ by ‘S4Vectors::findMatches’ when loading ‘AnnotationForge’
Attaching package: ‘GOstats’

The following object is masked from ‘package:AnnotationDbi’:

    makeGOGraph
library(gageData)
countDataNK <- read.csv('R://JDBG2022-A6322/Results/Sequencing/First and Second Batch combined analysis/JD.count.csv', header = TRUE, sep = ",")
metaDataNK <- read.csv('R://JDBG2022-A6322/Results/Sequencing/First and Second Batch combined analysis/JD.metadata.csv', header = TRUE, sep = ",")

#First attempting to look at the data without subsetting based on condition
dds <- DESeqDataSetFromMatrix(countData=countDataNK, DataFrame(metaDataNK), design=~genotype, tidy = TRUE)
Warning: some variables in design formula are characters, converting to factors
dds <- DESeq(dds)
estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
-- replacing outliers and refitting for 495 genes
-- DESeq argument 'minReplicatesForReplace' = 7 
-- original counts are preserved in counts(dds)
estimating dispersions
fitting model and testing
vsd <- vst(dds, blind=FALSE)

# plotPCA(vsd, intgroup="condition")
# plotPCA(vsd, intgroup="genotype")
# plotPCA(vsd, intgroup= c("genotype", "condition"))


pcaData <- plotPCA(vsd, intgroup=c("condition", "genotype"), returnData=TRUE)
percentVar <- round(100 * attr(pcaData, "percentVar"))

pcaplot<-ggplot(pcaData, aes(PC1, PC2, color=genotype, shape=condition)) +
  geom_point(size=5) +
  xlab(paste0("PC1: ",percentVar[1],"% variance")) +
  ylab(paste0("PC2: ",percentVar[2],"% variance")) +
  theme_light()

ggsave(filename = "PCA-plot.tiff",
  plot = pcaplot, device = "tiff", path = NULL, scale = 1, width = 5, height = 5, units = c("in"), dpi = 600)
pcaplot

#Trying to make a VENN diagram indiscriminate of subsets - just all subsets and genotype as the main comparitor

resA_DKO <- results(dds, contrast=c("genotype","DKO","NCR"))
resB_FOXO1 <- results(dds, contrast=c("genotype","FOXO1KO","NCR"))
resC_GFI1 <- results(dds, contrast=c("genotype","GFI1KO","NCR"))

  get_lfc_sign <- function(df, thr = 1.1){
  df$lfc_thr <- 0
  df$lfc_thr[which(df$log2FoldChange >= thr)] <- 1
  df$lfc_thr[which(df$log2FoldChange <= (-1.1 * thr))] <- -1
  return(df)
}

resA_DKO <- get_lfc_sign(resA_DKO, thr=1.1)
resB_FOXO1 <- get_lfc_sign(resB_FOXO1, thr=1.1)
resC_GFI1 <- get_lfc_sign(resC_GFI1, thr=1.1)

resA_DKO <- resA_DKO[order(resA_DKO$pvalue, decreasing=FALSE), ]
resB_FOXO1 <- resB_FOXO1[order(resB_FOXO1$pvalue, decreasing=FALSE), ]
resC_GFI1 <- resC_GFI1[order(resC_GFI1$pvalue, decreasing=FALSE), ]

table(resA_DKO$padj < 0.05, resA_DKO$lfc_thr)
       
           -1     0     1
  FALSE   634 19662   674
  TRUE    475  3108   575
table(resB_FOXO1$padj < 0.05, resB_FOXO1$lfc_thr)
       
           -1     0     1
  FALSE    87 17197    95
  TRUE    222  1967   140
table(resC_GFI1$padj < 0.05, resC_GFI1$lfc_thr)
       
           -1     0     1
  FALSE    46 19414   184
  TRUE     52  1087   280
resA_DKO$symbol <- mapIds(org.Mm.eg.db, keys=row.names(resA_DKO), column="SYMBOL", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resA_DKO$entrez <- mapIds(org.Mm.eg.db, keys=row.names(resA_DKO), column="ENTREZID", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resA_DKO$name <- mapIds(org.Mm.eg.db, keys=row.names(resA_DKO), column="GENENAME", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
#Add Entrez, Symbol and gene name to resB_FOXO1 files
resB_FOXO1$symbol <- mapIds(org.Mm.eg.db, keys=row.names(resB_FOXO1), column="SYMBOL", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resB_FOXO1$entrez <- mapIds(org.Mm.eg.db, keys=row.names(resB_FOXO1), column="ENTREZID", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resB_FOXO1$name <- mapIds(org.Mm.eg.db, keys=row.names(resB_FOXO1), column="GENENAME", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
#Add Entrez, Symbol and gene name to resC_GFI1 files
resC_GFI1$symbol <- mapIds(org.Mm.eg.db, keys=row.names(resC_GFI1), column="SYMBOL", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resC_GFI1$entrez <- mapIds(org.Mm.eg.db, keys=row.names(resC_GFI1), column="ENTREZID", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resC_GFI1$name <- mapIds(org.Mm.eg.db, keys=row.names(resC_GFI1), column="GENENAME", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resASig_NK <- resA_DKO[which(resA_DKO$padj < 0.05 & abs(resA_DKO$log2FoldChange) >= 1.1 & resA_DKO$baseMean >= 20), ]
resBSig_NK <- resB_FOXO1[which(resB_FOXO1$padj < 0.05 & abs(resB_FOXO1$log2FoldChange) >= 1.1 & resB_FOXO1$baseMean >= 20), ]
resCSig_NK <- resC_GFI1[which(resC_GFI1$padj < 0.05 & abs(resC_GFI1$log2FoldChange) >= 1.1 & resC_GFI1$baseMean >= 20), ]

write.csv(resASig_NK, "NK_NCR_vs_DKO_0.05pAdj1.1L2FC20BaseMean.csv")
write.csv(resBSig_NK, "NK_NCR_vs_FOXO1KO_0.05pAdj1.1L2FC20BaseMean.csv")
write.csv(resCSig_NK, "NK_NCR_vs_GFI1KO_0.05pAdj1.1L2FC20BaseMean.csv")


##VENN diagram DEG of ALL NK indiscriminate of Subset

set1NK <- resASig_NK$symbol
set2NK <- resBSig_NK$symbol
set3NK <- resCSig_NK$symbol
colors <- c("slateblue1", "goldenrod1", "indianred1")

set1NK<-na.omit(set1NK)
set2NK<-na.omit(set2NK)
set3NK<-na.omit(set3NK)

venn.diagram(
  x = list(set1NK, set2NK, set3NK),
  category.names = c("DKO", "FOXO1KO", "GFI1KO"),
  filename = 'DEG ALL NK VennDiagram.png',
  output = TRUE,
  imagetype = "png",
  scaled = FALSE,
  col = "black",
  fill = colors,
  cat.col = colors,
  cat.cex = 1.5,   # Adjust the font size to make the labels smaller
  cat.pos = 0,     # Move the labels outside the circles
  cat.dist = c(0.05, 0.05, -0.45),  # Adjust the distance for each category label individually
  margin = 0.15
)
[1] 1
countData <- read.csv('R://JDBG2022-A6322/Results/Sequencing/First and Second Batch combined analysis/JD.count.csv', header = TRUE, sep = ",", row.names = 1)
metaData <- read.csv('R://JDBG2022-A6322/Results/Sequencing/First and Second Batch combined analysis/JD.metadata.csv', header = TRUE, sep = ",")

metaData$genotype <- factor(metaData$genotype, levels = c("NCR", "FOXO1KO", "GFI1KO", "DKO"))
metaData$condition <- factor(metaData$condition, levels = c("Imm", "M1", "M2"))

######################### within each condition, how does KO compare to WT########################################

dds_meta1 <- metaData %>% filter(condition == "M1")
dds_1 <- DESeqDataSetFromMatrix(countData=countData[,which(colnames(countData) %in% dds_meta1$Geneid)], dds_meta1, design=~genotype)
#dds_1 <- dds_1[rowSums(counts(dds_1)) > 8, ]
dds_1 <- DESeq(dds_1)
estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
resA <- results(dds_1, contrast=c("genotype","DKO","NCR"))
resB <- results(dds_1, contrast=c("genotype","FOXO1KO","NCR"))
resC <- results(dds_1, contrast=c("genotype","GFI1KO","NCR"))
# change the last variable in the sequence to be the control and the second to be the comparitor - this resA here, NCR (control) vs DKO 

  get_lfc_sign <- function(df, thr = 1.1){
  df$lfc_thr <- 0
  df$lfc_thr[which(df$log2FoldChange >= thr)] <- 1
  df$lfc_thr[which(df$log2FoldChange <= (-1.1 * thr))] <- -1
  return(df)
}

resA <- get_lfc_sign(resA, thr=1.1)
resB <- get_lfc_sign(resB, thr=1.1)
resC <- get_lfc_sign(resC, thr=1.1)

resA <- resA[order(resA$pvalue, decreasing=FALSE), ]
resB <- resB[order(resB$pvalue, decreasing=FALSE), ]
resC <- resC[order(resC$pvalue, decreasing=FALSE), ]

table(resA$padj < 0.05, resA$lfc_thr)
       
           -1     0     1
  FALSE   910 19202  1251
  TRUE    416  1526   484
table(resB$padj < 0.05, resB$lfc_thr)
       
           -1     0     1
  FALSE   668 18836   692
  TRUE    250   818   152
table(resC$padj < 0.05, resC$lfc_thr)
       
           -1     0     1
  FALSE   543 20370   889
  TRUE     43   504   262
 

#MA plot

plotMA(
  resA,
  #padj = 0.05,
  #log2Foldchange = 1.5,
  alpha = 0.5,
  #select.top.method = c("padj", "log2FoldChange"),
  #top = 20,
  #select.top.method = c("padj", "log2FoldChange"),
  main = "M1 NK cells - NCR Vs DKO",
  xlab = "Average log2 counts per million",
  ylab = "Log2 Fold Change",
  ylim = c(-15, 15),
  colNonSig = "black",
  #palette = c("#B31B21", "#1465AC", "darkgray"),
  #colSig = "firebrick1",
  colSig = "dodgerblue",
  returnData = FALSE,
  MLE = FALSE,
  #ggtheme = theme_classic(),
)

resA$symbol <- mapIds(org.Mm.eg.db, keys=row.names(resA), column="SYMBOL", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resA$entrez <- mapIds(org.Mm.eg.db, keys=row.names(resA), column="ENTREZID", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resA$name <- mapIds(org.Mm.eg.db, keys=row.names(resA), column="GENENAME", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
#Add Entrez, Symbol and gene name to resB files
resB$symbol <- mapIds(org.Mm.eg.db, keys=row.names(resB), column="SYMBOL", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resB$entrez <- mapIds(org.Mm.eg.db, keys=row.names(resB), column="ENTREZID", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resB$name <- mapIds(org.Mm.eg.db, keys=row.names(resB), column="GENENAME", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
#Add Entrez, Symbol and gene name to resC files
resC$symbol <- mapIds(org.Mm.eg.db, keys=row.names(resC), column="SYMBOL", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resC$entrez <- mapIds(org.Mm.eg.db, keys=row.names(resC), column="ENTREZID", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resC$name <- mapIds(org.Mm.eg.db, keys=row.names(resC), column="GENENAME", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
# Add normalized count to the result Table
resAanno<- merge(as.data.frame(resA), as.data.frame(counts(dds_1, normalized=TRUE)), by="row.names", sort=FALSE)
resBanno<- merge(as.data.frame(resB), as.data.frame(counts(dds_1, normalized=TRUE)), by="row.names", sort=FALSE)
resCanno<- merge(as.data.frame(resC), as.data.frame(counts(dds_1, normalized=TRUE)), by="row.names", sort=FALSE)

write.csv(resAanno, "M1_NCR_vs_DKO.csv")
write.csv(resBanno, "M1_NCR_vs_FOXO1KO.csv")
write.csv(resCanno, "M1_NCR_vs_GFI1KO.csv")
## This is just me playing around with a volcano plot first to see lots of genes and then a second one where I've handpicked some genes to map on 

#volcano plot resA
volplot_resA_discovery <- EnhancedVolcano(resA, 
                           lab = resA$symbol, 
                           x = "log2FoldChange", 
                           y = "padj", 
                           border = "full", 
                           borderColour = "black", 
                           gridlines.major = F, 
                           gridlines.minor = F,
                           title = 'M1 - DKO vs NCR',
                           subtitle = bquote(italic('FDR <= 0.05 and absolute FC >= 1.1')),
                              #selectLab = c('Eomes','FOXO1','Gfi1','Id3','Pdcd1','Gzma','Gzmb', 'Tbx21'),
                           pCutoff = 0.00005,
                           FCcutoff = 1.1,
                           pointSize = 3.0,
                           labSize = 3.5,
                           legendPosition = 'none',
                           xlim = c(-10, 15),
                              #legendLabels = c("NS", expression(Log[2] ~ FC), "p-value", expression(p - value ~ and ~ log[2] ~ FC)),
                           #drawConnectors = TRUE, 
                           max.overlaps = 100,
                           lengthConnectors = unit(0.001, "npc"),
                           typeConnectors = 'closed',
                           endsConnectors = "last",
                           widthConnectors = 0.1,
                              #col=c("grey", "green4", "blue", "red3"),
                           colAlpha = 0.5
)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...
volplot_resA_discovery

lab_italics <- paste0("italic('", resA$symbol, "')")
selectLab_italics = paste0(
  "italic('",
  c('Dusp7','Ptpn5','Fcgr3', 'Tcf7','Icos','Vegfc','Gmfg','Cphx1','Gpr15', 'Thy1', 'Nek10', 'Hopx', 'FOXO1', 'Gfi1'),
  "')")

Volplot_M1resA <- EnhancedVolcano(resA,
                lab = lab_italics,
                x = 'log2FoldChange',
                y = 'pvalue',
                selectLab = selectLab_italics,
                xlab = bquote(~Log[2]~ 'fold change'),
                pCutoff = 0.00005,
                FCcutoff = 1.1,
                pointSize = 3.0,
                labSize = 6.0,
                labCol = 'black',
                title = 'M1 - DKO vs NCR',
                subtitle = bquote(italic('FDR <= 0.05 and absolute FC >= 1.1')),
                #border = "full",
                labFace = 'bold',
                boxedLabels = TRUE,
                gridlines.major = F, 
                gridlines.minor = F,
                parseLabels = TRUE,
                col = c('grey30', 'green4', 'blue1', 'red3'),
                colAlpha = 4/5,
                legendPosition = 'bottom',
                legendLabSize = 14,
                legendIconSize = 4.0,
                drawConnectors = TRUE,
                widthConnectors = 1.0,
                colConnectors = 'black') + coord_flip()
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...Coordinate system already present. Adding new coordinate system, which will replace the existing one.
Volplot_M1resA

countDataTOTAL <- read.csv('R://JDBG2022-A6322/Results/Sequencing/First and Second Batch combined analysis/JD.count.csv', header = TRUE, sep = ",", row.names = 1) 
metaDataTOTAL <- read.csv('R://JDBG2022-A6322/Results/Sequencing/First and Second Batch combined analysis/JD.metadata.csv', header = TRUE, sep = ",")

metaDataTOTAL$genotype <- factor(metaDataTOTAL$genotype, levels = c("NCR", "FOXO1KO", "GFI1KO", "DKO"))
metaDataTOTAL$condition <- factor(metaDataTOTAL$condition, levels = c("Imm", "M1", "M2"))

 
######################### within each condition, how does KO compare to WT########################################

dds_meta1 <- metaDataTOTAL %>% filter(condition == "M1")
dds_1 <- DESeqDataSetFromMatrix(countData=countDataTOTAL[,which(colnames(countDataTOTAL) %in% dds_meta1$Geneid)], dds_meta1, design=~genotype)
#dds_1 <- dds_1[rowSums(counts(dds_1)) > 8, ]
dds_1 <- DESeq(dds_1)
estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
resA <- results(dds_1, contrast=c("genotype","DKO","NCR"))
resB <- results(dds_1, contrast=c("genotype","FOXO1KO","NCR"))
resC <- results(dds_1, contrast=c("genotype","GFI1KO","NCR"))
# change the last variable in the sequence to be the control and the second to be the comparitor - this resA here, NCR (control) vs DKO 

  get_lfc_sign <- function(df, thr = 1.1){
  df$lfc_thr <- 0
  df$lfc_thr[which(df$log2FoldChange >= thr)] <- 1
  df$lfc_thr[which(df$log2FoldChange <= (-1.1 * thr))] <- -1
  return(df)
}

resA <- get_lfc_sign(resA, thr=1.1)
resB <- get_lfc_sign(resB, thr=1.1)
resC <- get_lfc_sign(resC, thr=1.1)

resA <- resA[order(resA$pvalue, decreasing=FALSE), ]
resB <- resB[order(resB$pvalue, decreasing=FALSE), ]
resC <- resC[order(resC$pvalue, decreasing=FALSE), ]

table(resA$padj < 0.05, resA$lfc_thr)
       
           -1     0     1
  FALSE   910 19202  1251
  TRUE    416  1526   484
table(resB$padj < 0.05, resB$lfc_thr)
       
           -1     0     1
  FALSE   668 18836   692
  TRUE    250   818   152
table(resC$padj < 0.05, resC$lfc_thr)
       
           -1     0     1
  FALSE   543 20370   889
  TRUE     43   504   262
#Add Entrez, Symbol and gene name to resA files
resA$symbol <- mapIds(org.Mm.eg.db, keys=row.names(resA), column="SYMBOL", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resA$entrez <- mapIds(org.Mm.eg.db, keys=row.names(resA), column="ENTREZID", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resA$name <- mapIds(org.Mm.eg.db, keys=row.names(resA), column="GENENAME", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
#Add Entrez, Symbol and gene name to resB files
resB$symbol <- mapIds(org.Mm.eg.db, keys=row.names(resB), column="SYMBOL", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resB$entrez <- mapIds(org.Mm.eg.db, keys=row.names(resB), column="ENTREZID", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resB$name <- mapIds(org.Mm.eg.db, keys=row.names(resB), column="GENENAME", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
#Add Entrez, Symbol and gene name to resC files
resC$symbol <- mapIds(org.Mm.eg.db, keys=row.names(resC), column="SYMBOL", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resC$entrez <- mapIds(org.Mm.eg.db, keys=row.names(resC), column="ENTREZID", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
resC$name <- mapIds(org.Mm.eg.db, keys=row.names(resC), column="GENENAME", keytype="ENSEMBL", multiVals="first")
'select()' returned 1:many mapping between keys and columns
# Add normalized count to the result Table
resA<- merge(as.data.frame(resA), as.data.frame(counts(dds_1, normalized=TRUE)), by="row.names", sort=FALSE)
resB<- merge(as.data.frame(resB), as.data.frame(counts(dds_1, normalized=TRUE)), by="row.names", sort=FALSE)
resC<- merge(as.data.frame(resC), as.data.frame(counts(dds_1, normalized=TRUE)), by="row.names", sort=FALSE)


#PCA plot
rld <- rlog(dds_1)
# plotPCA(rld, intgroup = c("genotype"))
# plotPCA(rld, intgroup = c("genotype", "condition"))
my_theme <- theme(panel.grid.major = element_blank(),
                  panel.grid.minor = element_blank(),
                  panel.background = element_rect(fill = "white", color = "black"),
                  panel.border = element_rect(color = "black", fill = NA, linewidth = 0.1))
plotPCA(rld, intgroup = "genotype", ntop = 500, returnData = FALSE) + my_theme + geom_point(size=5) + labs(title = "PCA Plot - M1 Gene Expression Data")


resASig <- resA[which(resA$padj < 0.05 & abs(resA$log2FoldChange) >= 1.1 & resA$baseMean >= 20), ]
resBSig <- resB[which(resB$padj < 0.05 & abs(resB$log2FoldChange) >= 1.1 & resB$baseMean >= 20), ]
resCSig <- resC[which(resC$padj < 0.05 & abs(resC$log2FoldChange) >= 1.1 & resC$baseMean >= 20), ]

mat <- assay(rld)
idA <- resASig$Row.names
DEgenes <- mat[idA,]
colData(rld)
DataFrame with 20 rows and 5 columns
           Geneid condition genotype     batch sizeFactor
      <character>  <factor> <factor> <integer>  <numeric>
JD.5         JD.5        M1   NCR            1   0.930689
JD.8         JD.8        M1   NCR            1   1.011171
JD.11       JD.11        M1   NCR            1   0.994989
JD.14       JD.14        M1   NCR            1   0.788172
JD.17       JD.17        M1   GFI1KO         1   0.740554
...           ...       ...      ...       ...        ...
D11           D11        M1  DKO             2    1.31403
E2             E2        M1  NCR             2    1.42852
E5             E5        M1  GFI1KO          2    1.19067
E8             E8        M1  FOXO1KO         2    1.56719
E11           E11        M1  DKO             2    1.03036
annotation <- data.frame(genotype=colData(rld)$genotype)
genotype_colors <- list("genotype"=c("NCR" = "grey65", "FOXO1KO" = "goldenrod1", "GFI1KO" = "indianred1", "DKO" = "slateblue1"))

bwr_99 <- colorRampPalette(c("cyan", "black", "yellow"))(n = 99)

#Dendrogram
pheatmap(DEgenes, 
         scale = "row", 
         show_rownames = F,
         show_colnames = F,
         color = bwr_99,
         clustering_distance_rows = "correlation", 
         annotation_col = annotation, 
         annotation_colors = genotype_colors,
         treeheight_row = 30,
         treeheight_col = 15,
         main="M1 DEG")

# Candidate gene heatmaps

genesEff <- c("Lag3", "Batf3", "Tnfsf8", "Gzmm", "Il21r", "Itk", "Tnfsf10", "Tlr3", "Foxo1", "Socs1", "Cd2ap", "Gzmk", "Il18r1", "Il12rb2", "Zeb2", "Prf1", "Gmzb", "Ifng", "Ccl4", "Sh2d1b1")
genesDevDiff <- c("Lef1", "Gata6", "Hhat", "Eomes", "Runx2", "Sox4", "Id3", "Tox", "Il4ra", "Dtx1", "Cd27", "Tcf7", "Klrg1", "Tbx21", "Spi1", "Id2")
genesCellSurface <- c("Kit", "Thy1", "Klra1", "Klra3", "Klra4", "Klra8", "Klra9", "Klra17", "Klrb1a", "Klrc1", "Klrc3", "Klrd1", "Ncr1", "Cd244a", "Klrg1", "Cd226", "Il2rb", "Klrb1c", "Fcgr3", "Sell", "Cd27", "H2-Ab1", "Cd86", "Cd69", "Klrd1", "Lair1", "Lag3", "Nkrp1", "Ccr5", "Ccr7", "Cxcr1", "Cxcr2", "Cxcr3", "Cxcr4", "Cx3cr1", "S1pr5", "Ccr2", "Il2ra", "Il12rb1", "Il15ra", "Il18r1", "Fcgr1", "Fcgr2a", "Fcgr2b", "Fcgr2c", "Fcgr3")
genesMetabolism <- c("Ppargc1a", "Ppara", "Ppard", "Pparg", "Sirt1", "Foxo1", "Foxo3", "Foxo4", "Acox1", "Acadm", "Acads", "Acsl1", "Acsl3", "Acsl4", "Acsl5", "Acsl6", "Akr1b8", "Akr1b3", "Aldh1a1", "Aldh2", "Aldh3a1", "Aldh4a1", "Aldh5a1", "Cpt1a", "Cpt1b", "Cpt2", "Fasn", "Fabp1", "Fabp2", "Fabp3", "Fabp4", "Fabp5", "Glut1", "Glut2", "Glut3", "Glut4", "G6pd", "Pck1", "Pck2", "Hk1", "Hk2", "Gck", "Pdk1", "Pdk2", "Pdk3")
genesProliferationCellSurvival <- c("Klf2", "Bbc3", "Klf4", "Il7r", "Bcl2a1b", "Bag3", "Bcl2", "Bcl2l1",  "Bcl2l11", "Mcl1", "Bax", "Bad", "Bid", "Bak1", "Casp3", "Casp8", "Casp9", "Xiap", "Survivin", "Pten", "Akt1", "Akt2", "Akt3", "Mtor", "Rb1", "E2f1", "E2f", "E2f3", "Tp53", "Cdkn1a", "Cdkn1b", "Cdkn2a", "Cdkn2b", "Nfkb1", "Nfkb2", "Rela", "Relb", "Tnf", "Tnfrsf1a", "Tnfrsf1b", "Mapk1", "Mapk3",  "Mapk8", "Mapk9", "Mapk14", "Mapk12", "Mapk13", "Map3k1", "Map3k5", "Map3k7")
genesTranscriptionFactors <- c("Gfi1", "Gfi1b", "Eomes", "Tbx21", "Nfil3", "Id2", "Nfkbia", "Nfkbid", "Nfkbiz", "Spi1", "Nr4a1", "Ncr1", "Tcf7", "Hobit", "Blimp1", "Gata3", "Il7r", "Tox", "Tox2", "Zbtb16", "Rora", "Ets1", "Eomes", "Tox2", "Tbx21", "Zeb2", "Runx3", "Id2", "Nfil3", "Tox", "Gata3", "Prdm1", "Batf", "Batf3", "Irf4", "Irf8", "Stat4", "Stat5", "c-Myc", "Notch1", "Ttf1", "Nkx3-1", "Gfi1", "Gfi1b", "Foxo1", "Foxo3", "Foxo4", "Spi1", "Spib", "Spic", "Ets1", "Ets2", "Pax5", "Pax8")
genesMigration <- c("Cxcr3", "Ccr5", "Ccr2", "Gpr183", "Ccr7", "Itgb3", "Cd63", "Itgad", "Gpr155", "Itgb5", "Ccr10", "Cxcr4", "Sell", "Itga4", "Itga6", "Itga1", "S1pr5", "Cxcr3", "Cx3cr1", "Ccr7", "S1pr5", "Cxcr4", "Cxcr6", "Ccr5", "Ccr9", "Ccr2", "Ccr6", "Itga4", "Itgb1", "Itgb2", "ItgaL", "ItgaM", "Itga1", "ItgaE", "ItgaD", "Itgb7", "ItgaE", "Selp", "Sele", "Sell", "Cldn1", "Cldn2", "Cldn3", "Cldn4", "Cldn5", "Cldn7", "Cldn8", "Cldn9", "Cldn10", "Cldn11", "Cldn12", "Cldn15", "Cldn16", "Cldn17", "Cldn18", "Cldn19", "Cldn20")
genesActivationInhibition <- c("Klra8", "Klra7", "Klra4", "Klra3", "Klra1", "Klrd1", "Cd94", "Lair-1", "Ptpn6", "Shp1", "Cish", "Cd244a", "Cd38", "Il6st", "Klrc1", "Cd101", "Hmbox1", "Klra3", "Klra1", "Cd226", "Cd96", "Cd200r1", "Ahr", "Cd72", "Tigit", "Cd69", "Ncr", "Klrb1c", "Klrb1b", "Cd244", "Ly49h", "Klrk1", "Cd226", "Cd25", "Il2rb", "Ifngr1", "Ifnar1", "Stat4", "Stat5", "Stat1", "Prf1", "Gzma", "Gzmb", "Gzmk", "Gzmm", "Tnfsf10", "Fasl", "Fas", "Ifng")
genesCytokineChemokine <- c("Ifng", "Tnf", "Csf2", "Il10", "Il2", "Il12", "Il15", "Il18", "Il22", "Il27", "Il33", "Cxcl1", "Cxcl2", "Cxcl3", "Cxcl4", "Cxcl5", "Cxcl9", "Cxcl10", "Cxcl11", "Cxcl12", "Cxcl13", "Cxcl16", "Ccl1", "Ccl2", "Ccl3", "Ccl4", "Ccl5", "Ccl6", "Ccl7", "Ccl8", "Ccl9", "Ccl10", "Ccl11", "Ccl12", "Ccl17", "Ccl19", "Ccl20", "Ccl21", "Ccl22", "Ccl25", "Ccl27", "Ccl28")
genesProteinValidation <- c("Itga2", "Itgam", "Thy1", "Thy1.2", "Klrb1c", "Nkrp1c", "Kit", "Tbx21", "Eomes", "Foxo1", "Ncr1", "Ncr", "Cxcr3", "Cx3cr1", "Tox", "Klrg1", "Sell", "Havcr2", "Il7r", "Icos", "Tcf7", "Il18r1", "Cd226", "Cd38", "Lag3")


plot_genes_heatmap <- function(resA, expression_mat, dds_meta1, keep_genes, keep_groups = c("NCR", "FOXO1KO", "DKO", "GFI1KO"), padj_cutoff = 0.05, log2FoldChange_cutoff = 1.1, baseMean_cutoff = 20, ...) {
  resA$significant <- ifelse(resA$padj < padj_cutoff & abs(resA$log2FoldChange) >= log2FoldChange_cutoff & resA$baseMean >= baseMean_cutoff & !is.na(resA$symbol), "yes", "no")
  df1 <- data.frame(expression_mat, "Row.names" = row.names(expression_mat))
  df2 <- data.frame("Row.names" = resA$Row.names, "significant" = resA$significant, "genes" = resA$symbol)
  mat <- dplyr::full_join(df1, df2, by = "Row.names")  #df3, df4,
  mat <- mat[, -which(colnames(mat) == "Row.names")]
  mat <- mat %>% filter(genes %in% keep_genes)
  row.names(mat) <- mat[, ncol(mat)]
  mat <- mat[, -ncol(mat)]
  mat <- mat[rowSums(mat[, -ncol(mat)]) > 0, ]
  row_anno <- mat[, "significant", drop = F]
  mat <- mat[, dds_meta1 %>% filter(genotype %in% keep_groups) %>% dplyr::select(Geneid) %>% unlist() %>% as.character()]
  col_anno <- dds_meta1 %>%
    filter(genotype %in% keep_groups) %>%
    dplyr::select(genotype)
  row.names(col_anno) <- dds_meta1 %>%
    filter(genotype %in% keep_groups) %>%
    dplyr::select(Geneid) %>%
    unlist() %>%
    as.character()
  
  genotype_colors <- list("genotype" = c("NCR" = "grey65", "FOXO1KO" = "goldenrod1", "GFI1KO" = "indianred1", "DKO" = "slateblue1"))
  sig_col <- list("significant" = c("yes" = "#e15179", "no" = "#e7e7e7"))
  pheatmap(mat,
           annotation_colors = c(genotype_colors, sig_col),
           annotation_col = col_anno,
           annotation_row = row_anno,
           ...
  )
}

plot_genes_heatmap(resA, assay(rld), dds_meta1, genesProteinValidation, keep_groups = c("NCR", "FOXO1KO", "DKO", "GFI1KO"),
                   show_rownames = T,
                   cluster_cols = T,
                   show_colnames = F,
                   cluster_rows = T,
                   scale="row",
                   #border_color = NA,
                   treeheight_row = 10,
                   clustering_distance_rows = "correlation",
                   color = bwr_99)
Warning: The input is a data frame, convert it to the matrix.

##VENN diagram DEG

set1 <- resASig$symbol
set2 <- resBSig$symbol
set3 <- resCSig$symbol
colors <- c("slateblue1", "goldenrod1", "indianred1")

set1<-na.omit(set1)
set2<-na.omit(set2)
set3<-na.omit(set3)

venn.diagram(
  x = list(set1, set2, set3),
  category.names = c("DKO", "FOXO1KO", "GFI1KO"),
  filename = 'DEG M1 VennDiagram.png',
  output = TRUE,
  imagetype = "png",
  scaled = FALSE,
  col = "black",
  fill = colors,
  cat.col = colors,
  cat.cex = 1.5,   # Adjust the font size to make the labels smaller
  cat.pos = 0,     # Move the labels outside the circles
  cat.dist = c(0.05, 0.05, -0.45),  # Adjust the distance for each category label individually
  margin = 0.15
)
[1] 1
#GO BP analysis 

#BP
orderSigresA_GO_UP <- resASig %>% filter(padj < 0.05 & (log2FoldChange) >= 1.1 & baseMean >= 20 & !is.na(symbol))
orderSigresA_GO_DOWN <- resASig %>% filter(padj < 0.05 & (log2FoldChange) <= -1.1 & baseMean >= 20 & !is.na(symbol))


egoBP_UPresA <- enrichGO(gene         = orderSigresA_GO_UP$entrez,
                 OrgDb         = org.Mm.eg.db,
                 keyType       = 'ENTREZID',
                 ont           = "BP",
                 pAdjustMethod = "BH",
                 pvalueCutoff  = 0.05,
                 )
head(egoBP_UPresA)

dotplot(egoBP_UPresA, showCategory = 15)


egoBP_DOWNresA <- enrichGO(gene         = orderSigresA_GO_DOWN$entrez,
                     OrgDb         = org.Mm.eg.db,
                     keyType       = 'ENTREZID',
                     ont           = "BP",
                     pAdjustMethod = "BH",
                     pvalueCutoff  = 0.05,
)
head(egoBP_DOWNresA)
dotplot(egoBP_DOWNresA, showCategory = 15)


write.csv(egoBP_UPresA, "M1_NCR_vs_DKO_GOBPup.csv")
write.csv(egoBP_DOWNresA, "M1_NCR_vs_DKO_GOBPdown.csv")
#KEGG pathway analysis

orderSigresA_GO_UP <- resASig %>% filter(padj < 0.05 & (log2FoldChange) >= 1.1 & baseMean >= 20 & !is.na(symbol))

KEGGup <- enrichKEGG(gene         = orderSigresA_GO_UP$entrez,
                 organism     = 'mmu',
                 keyType = "ncbi-geneid",
                 pvalueCutoff = 1,
                 qvalueCutoff = 1)
Reading KEGG annotation online: "https://rest.kegg.jp/link/mmu/pathway"...
Warning: the 'wininet' method is deprecated for http:// and https:// URLsReading KEGG annotation online: "https://rest.kegg.jp/list/pathway/mmu"...
Warning: the 'wininet' method is deprecated for http:// and https:// URLsReading KEGG annotation online: "https://rest.kegg.jp/conv/ncbi-geneid/mmu"...
Warning: the 'wininet' method is deprecated for http:// and https:// URLs
dotplot(KEGGup, showCategory = 10)




orderSigresA_GO_DOWN <- resASig %>% filter(padj < 0.05 & (log2FoldChange) <= -1.1 & baseMean >= 20 & !is.na(symbol))

KEGGdown <- enrichKEGG(gene         = orderSigresA_GO_DOWN$entrez,
                 organism     = 'mmu',
                 keyType = "ncbi-geneid",
                 pvalueCutoff = 1,
                 qvalueCutoff = 1)
dotplot(KEGGdown, showCategory = 10)


write.csv(KEGGup, "M1_NCR_vs_DKO_KEGGup.csv")
write.csv(KEGGdown, "M1_NCR_vs_DKO_KEGGdown.csv")
#GSEA

#change log2foldchange to negative values to see underexpression?
#DKO
tmp <- resA[!is.na(resA$symbol), ]
tmp <- tmp[order(tmp$stat, decreasing = T), ]
testgenes <- tmp$stat
names(testgenes) <- tmp$symbol
testgenes <- testgenes[!is.na(testgenes)]

gene_sets <- msigdbr(species = "mouse", category = "H")

gene_sets <- gene_sets %>%
  dplyr::select(gs_name, gene_symbol)

gsearesA <- GSEA(geneList = testgenes,
                TERM2GENE = gene_sets)
preparing geneSet collections...
GSEA analysis...
Warning: There are ties in the preranked stats (4.56% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Warning: There are duplicate gene names, fgsea may produce unexpected results.Warning: 'package:stats' may not be available when loadingWarning: 'package:stats' may not be available when loadingleading edge analysis...
done...
dotplot(gsearesA)


View(gsearesA)
dfgsearesA <- as.data.frame(gsearesA)



#attempting to overlap dfgsearesA/B/C

# str(dfgsearesA)
# str(dfgsearesB)
# str(dfgsearesC)
# 
# celltypes = c('Imm', 'M1', 'M2')
# groups = c("NCR", "FOXO1KO", "GFI1KO", "DKO")



#adding a score for GSEA
resdf2 <- resA %>%
  arrange(padj) %>%
  mutate(gsea_metric = -log10(padj) * sign(log2FoldChange))

resdf2 <- resdf2 %>%
  mutate(padj = case_when(padj == 0 ~ .Machine$double.xmin,
                          TRUE ~ padj)) %>%
  mutate(gsea_metric = -log10(padj) * sign(log2FoldChange))
resdf2

resdf2 <- resdf2 %>%
  filter(! is.na(gsea_metric)) %>%
  arrange(desc(gsea_metric))
View(resdf2)

hist(resdf2$gsea_metric, breaks = 100)


ranks <- resdf2 %>%
  select(symbol, gsea_metric) %>%
  distinct(symbol, .keep_all = TRUE) %>%
  deframe()

head(ranks)
   Ptpn5 Cdc42bpb    Grhl3    Bend5   Rhbdf2      Dsp 
307.6527 307.6527 228.2902 188.3544 172.5150 147.6078 
gseares <- GSEA(geneList = ranks,
                TERM2GENE = gene_sets)
preparing geneSet collections...
GSEA analysis...
Warning: There are ties in the preranked stats (44.04% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Warning: 'package:stats' may not be available when loadingno term enriched under specific pvalueCutoff...
gsearesdf <- as.data.frame(gseares)

dotplot(gseares)
Error in `$<-.data.frame`(`*tmp*`, ".sign", value = "activated") : 
  replacement has 1 row, data has 0
# # compared to Wt, how does KO change in condition
# ############################################################################################################
# You helped write this initial code 2 months ago - I haven't fully thought through how I would present data that look at IMM vs M1 vs M2 in each KO - maybe this comparison could be useful for looking at how pathways or key transcription factors change as the cells develop from IMM into M1 into M2

# # FOXO1KO vs WT and Imm vs M1
# dds_meta1 <- metaDataTOTAL %>% filter((genotype %in% c("NCR", "FOXO1KO")) & (condition %in% c("Imm", "M1")))
# dds_1 <- DESeqDataSetFromMatrix(countData=countDataTOTAL[,which(colnames(countDataTOTAL) %in% dds_meta1$Geneid)], dds_meta1, design= ~ 0 + condition + genotype + genotype:condition)
# dds_1 <- dds_1[rowSums(counts(dds_1)) > 5, ]
# dds_1 <- DESeq(dds_1)
# 
# resultsNames(dds_1)
# resA <- results(dds_1, name = 'conditionM1.genotypeFOXO1KO')
# 
# get_lfc_sign <- function(df, thr = 1){
#   df$lfc_thr <- 0
#   df$lfc_thr[which(df$log2FoldChange >= thr)] <- 1
#   df$lfc_thr[which(df$log2FoldChange <= (-1 * thr))] <- -1
#   return(df)
# }
# 
# resA <- get_lfc_sign(resA, thr=1)
# 
# resA <- resA[order(resA$pvalue, decreasing=FALSE), ]
# 
# table(resA$padj < 0.05, resA$lfc_thr)
# 
# write.csv(resA, "filenames.csv")

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

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

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tDQp0aXRsZTogIkJlbHogTGFiIE5LIGNlbGwgUk5BIHNlcSB2MC4xIDExLjguMjMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkN0cmwrU2hpZnQrRW50ZXIqLiANCg0KYGBge3J9DQpzZXR3ZCgnUjovL0pEQkcyMDIyLUE2MzIyL1Jlc3VsdHMvU2VxdWVuY2luZy9GaXJzdCBhbmQgU2Vjb25kIEJhdGNoIGNvbWJpbmVkIGFuYWx5c2lzJykNCg0KbGlicmFyeShmZ3NlYSkNCmxpYnJhcnkoc3RhdHMpDQpsaWJyYXJ5KGNvd3Bsb3QpDQpsaWJyYXJ5KERFU2VxMikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQ0KbGlicmFyeShnZW5lZmlsdGVyKQ0KbGlicmFyeShjYWxpYnJhdGUpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkoQ29tcGxleEhlYXRtYXApDQpsaWJyYXJ5KGdvc2VxKQ0KbGlicmFyeShnZW5lTGVuRGF0YUJhc2UpDQpsaWJyYXJ5KGdhZ2UpDQpsaWJyYXJ5KEFubm90YXRpb25EYmkpDQpsaWJyYXJ5KG9yZy5NbS5lZy5kYikNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KHBhdGh2aWV3KQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoVmVubkRpYWdyYW0pDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KbGlicmFyeShjbHVzdGVyUHJvZmlsZXIpDQpsaWJyYXJ5KEFubm90YXRpb25EYmkpDQpsaWJyYXJ5KFBvaUNsYUNsdSkNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KHRpYmJsZSkNCmxpYnJhcnkobXNpZ2RicikNCmxpYnJhcnkoZ2dwdWJyKQ0KbGlicmFyeShHTy5kYikNCmxpYnJhcnkoR09zdGF0cykNCmxpYnJhcnkoZ2FnZURhdGEpDQpgYGANCg0KYGBge3J9DQojTG9va2luZyBhdCB0aGUgZGF0YSB3aXRob3V0IGNvbnNpZGVyYXRpb24gb2YgY29uZGl0aW9uLCBvbmx5IGdlbm90eXBlDQoNCmNvdW50RGF0YU5LIDwtIHJlYWQuY3N2KCdSOi8vSkRCRzIwMjItQTYzMjIvUmVzdWx0cy9TZXF1ZW5jaW5nL0ZpcnN0IGFuZCBTZWNvbmQgQmF0Y2ggY29tYmluZWQgYW5hbHlzaXMvSkQuY291bnQuY3N2JywgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiKQ0KbWV0YURhdGFOSyA8LSByZWFkLmNzdignUjovL0pEQkcyMDIyLUE2MzIyL1Jlc3VsdHMvU2VxdWVuY2luZy9GaXJzdCBhbmQgU2Vjb25kIEJhdGNoIGNvbWJpbmVkIGFuYWx5c2lzL0pELm1ldGFkYXRhLmNzdicsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIikNCg0KI0ZpcnN0IGF0dGVtcHRpbmcgdG8gbG9vayBhdCB0aGUgZGF0YSB3aXRob3V0IHN1YnNldHRpbmcgYmFzZWQgb24gY29uZGl0aW9uDQpkZHMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGE9Y291bnREYXRhTkssIERhdGFGcmFtZShtZXRhRGF0YU5LKSwgZGVzaWduPX5nZW5vdHlwZSwgdGlkeSA9IFRSVUUpDQpkZHMgPC0gREVTZXEoZGRzKQ0KDQp2c2QgPC0gdnN0KGRkcywgYmxpbmQ9RkFMU0UpDQoNCiMgcGxvdFBDQSh2c2QsIGludGdyb3VwPSJjb25kaXRpb24iKQ0KIyBwbG90UENBKHZzZCwgaW50Z3JvdXA9Imdlbm90eXBlIikNCiMgcGxvdFBDQSh2c2QsIGludGdyb3VwPSBjKCJnZW5vdHlwZSIsICJjb25kaXRpb24iKSkNCg0KDQpwY2FEYXRhIDwtIHBsb3RQQ0EodnNkLCBpbnRncm91cD1jKCJjb25kaXRpb24iLCAiZ2Vub3R5cGUiKSwgcmV0dXJuRGF0YT1UUlVFKQ0KcGVyY2VudFZhciA8LSByb3VuZCgxMDAgKiBhdHRyKHBjYURhdGEsICJwZXJjZW50VmFyIikpDQoNCnBjYXBsb3Q8LWdncGxvdChwY2FEYXRhLCBhZXMoUEMxLCBQQzIsIGNvbG9yPWdlbm90eXBlLCBzaGFwZT1jb25kaXRpb24pKSArDQogIGdlb21fcG9pbnQoc2l6ZT01KSArDQogIHhsYWIocGFzdGUwKCJQQzE6ICIscGVyY2VudFZhclsxXSwiJSB2YXJpYW5jZSIpKSArDQogIHlsYWIocGFzdGUwKCJQQzI6ICIscGVyY2VudFZhclsyXSwiJSB2YXJpYW5jZSIpKSArDQogIHRoZW1lX2xpZ2h0KCkNCg0KZ2dzYXZlKGZpbGVuYW1lID0gIlBDQS1wbG90LnRpZmYiLA0KICBwbG90ID0gcGNhcGxvdCwgZGV2aWNlID0gInRpZmYiLCBwYXRoID0gTlVMTCwgc2NhbGUgPSAxLCB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIHVuaXRzID0gYygiaW4iKSwgZHBpID0gNjAwKQ0KcGNhcGxvdA0KYGBgDQoNCmBgYHtyfQ0KI1RyeWluZyB0byBtYWtlIGEgVkVOTiBkaWFncmFtIGluZGlzY3JpbWluYXRlIG9mIHN1YnNldHMgLSBqdXN0IGFsbCBzdWJzZXRzIGFuZCBnZW5vdHlwZSBhcyB0aGUgbWFpbiBjb21wYXJpdG9yDQoNCnJlc0FfREtPIDwtIHJlc3VsdHMoZGRzLCBjb250cmFzdD1jKCJnZW5vdHlwZSIsIkRLTyIsIk5DUiIpKQ0KcmVzQl9GT1hPMSA8LSByZXN1bHRzKGRkcywgY29udHJhc3Q9YygiZ2Vub3R5cGUiLCJGT1hPMUtPIiwiTkNSIikpDQpyZXNDX0dGSTEgPC0gcmVzdWx0cyhkZHMsIGNvbnRyYXN0PWMoImdlbm90eXBlIiwiR0ZJMUtPIiwiTkNSIikpDQoNCiAgZ2V0X2xmY19zaWduIDwtIGZ1bmN0aW9uKGRmLCB0aHIgPSAxLjEpew0KICBkZiRsZmNfdGhyIDwtIDANCiAgZGYkbGZjX3Roclt3aGljaChkZiRsb2cyRm9sZENoYW5nZSA+PSB0aHIpXSA8LSAxDQogIGRmJGxmY190aHJbd2hpY2goZGYkbG9nMkZvbGRDaGFuZ2UgPD0gKC0xLjEgKiB0aHIpKV0gPC0gLTENCiAgcmV0dXJuKGRmKQ0KfQ0KDQpyZXNBX0RLTyA8LSBnZXRfbGZjX3NpZ24ocmVzQV9ES08sIHRocj0xLjEpDQpyZXNCX0ZPWE8xIDwtIGdldF9sZmNfc2lnbihyZXNCX0ZPWE8xLCB0aHI9MS4xKQ0KcmVzQ19HRkkxIDwtIGdldF9sZmNfc2lnbihyZXNDX0dGSTEsIHRocj0xLjEpDQoNCnJlc0FfREtPIDwtIHJlc0FfREtPW29yZGVyKHJlc0FfREtPJHB2YWx1ZSwgZGVjcmVhc2luZz1GQUxTRSksIF0NCnJlc0JfRk9YTzEgPC0gcmVzQl9GT1hPMVtvcmRlcihyZXNCX0ZPWE8xJHB2YWx1ZSwgZGVjcmVhc2luZz1GQUxTRSksIF0NCnJlc0NfR0ZJMSA8LSByZXNDX0dGSTFbb3JkZXIocmVzQ19HRkkxJHB2YWx1ZSwgZGVjcmVhc2luZz1GQUxTRSksIF0NCg0KdGFibGUocmVzQV9ES08kcGFkaiA8IDAuMDUsIHJlc0FfREtPJGxmY190aHIpDQp0YWJsZShyZXNCX0ZPWE8xJHBhZGogPCAwLjA1LCByZXNCX0ZPWE8xJGxmY190aHIpDQp0YWJsZShyZXNDX0dGSTEkcGFkaiA8IDAuMDUsIHJlc0NfR0ZJMSRsZmNfdGhyKQ0KDQpyZXNBX0RLTyRzeW1ib2wgPC0gbWFwSWRzKG9yZy5NbS5lZy5kYiwga2V5cz1yb3cubmFtZXMocmVzQV9ES08pLCBjb2x1bW49IlNZTUJPTCIsIGtleXR5cGU9IkVOU0VNQkwiLCBtdWx0aVZhbHM9ImZpcnN0IikNCnJlc0FfREtPJGVudHJleiA8LSBtYXBJZHMob3JnLk1tLmVnLmRiLCBrZXlzPXJvdy5uYW1lcyhyZXNBX0RLTyksIGNvbHVtbj0iRU5UUkVaSUQiLCBrZXl0eXBlPSJFTlNFTUJMIiwgbXVsdGlWYWxzPSJmaXJzdCIpDQpyZXNBX0RLTyRuYW1lIDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0FfREtPKSwgY29sdW1uPSJHRU5FTkFNRSIsIGtleXR5cGU9IkVOU0VNQkwiLCBtdWx0aVZhbHM9ImZpcnN0IikNCg0KI0FkZCBFbnRyZXosIFN5bWJvbCBhbmQgZ2VuZSBuYW1lIHRvIHJlc0JfRk9YTzEgZmlsZXMNCnJlc0JfRk9YTzEkc3ltYm9sIDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0JfRk9YTzEpLCBjb2x1bW49IlNZTUJPTCIsIGtleXR5cGU9IkVOU0VNQkwiLCBtdWx0aVZhbHM9ImZpcnN0IikNCnJlc0JfRk9YTzEkZW50cmV6IDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0JfRk9YTzEpLCBjb2x1bW49IkVOVFJFWklEIiwga2V5dHlwZT0iRU5TRU1CTCIsIG11bHRpVmFscz0iZmlyc3QiKQ0KcmVzQl9GT1hPMSRuYW1lIDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0JfRk9YTzEpLCBjb2x1bW49IkdFTkVOQU1FIiwga2V5dHlwZT0iRU5TRU1CTCIsIG11bHRpVmFscz0iZmlyc3QiKQ0KDQojQWRkIEVudHJleiwgU3ltYm9sIGFuZCBnZW5lIG5hbWUgdG8gcmVzQ19HRkkxIGZpbGVzDQpyZXNDX0dGSTEkc3ltYm9sIDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0NfR0ZJMSksIGNvbHVtbj0iU1lNQk9MIiwga2V5dHlwZT0iRU5TRU1CTCIsIG11bHRpVmFscz0iZmlyc3QiKQ0KcmVzQ19HRkkxJGVudHJleiA8LSBtYXBJZHMob3JnLk1tLmVnLmRiLCBrZXlzPXJvdy5uYW1lcyhyZXNDX0dGSTEpLCBjb2x1bW49IkVOVFJFWklEIiwga2V5dHlwZT0iRU5TRU1CTCIsIG11bHRpVmFscz0iZmlyc3QiKQ0KcmVzQ19HRkkxJG5hbWUgPC0gbWFwSWRzKG9yZy5NbS5lZy5kYiwga2V5cz1yb3cubmFtZXMocmVzQ19HRkkxKSwgY29sdW1uPSJHRU5FTkFNRSIsIGtleXR5cGU9IkVOU0VNQkwiLCBtdWx0aVZhbHM9ImZpcnN0IikNCg0KcmVzQVNpZ19OSyA8LSByZXNBX0RLT1t3aGljaChyZXNBX0RLTyRwYWRqIDwgMC4wNSAmIGFicyhyZXNBX0RLTyRsb2cyRm9sZENoYW5nZSkgPj0gMS4xICYgcmVzQV9ES08kYmFzZU1lYW4gPj0gMjApLCBdDQpyZXNCU2lnX05LIDwtIHJlc0JfRk9YTzFbd2hpY2gocmVzQl9GT1hPMSRwYWRqIDwgMC4wNSAmIGFicyhyZXNCX0ZPWE8xJGxvZzJGb2xkQ2hhbmdlKSA+PSAxLjEgJiByZXNCX0ZPWE8xJGJhc2VNZWFuID49IDIwKSwgXQ0KcmVzQ1NpZ19OSyA8LSByZXNDX0dGSTFbd2hpY2gocmVzQ19HRkkxJHBhZGogPCAwLjA1ICYgYWJzKHJlc0NfR0ZJMSRsb2cyRm9sZENoYW5nZSkgPj0gMS4xICYgcmVzQ19HRkkxJGJhc2VNZWFuID49IDIwKSwgXQ0KDQp3cml0ZS5jc3YocmVzQVNpZ19OSywgIk5LX05DUl92c19ES09fMC4wNXBBZGoxLjFMMkZDMjBCYXNlTWVhbi5jc3YiKQ0Kd3JpdGUuY3N2KHJlc0JTaWdfTkssICJOS19OQ1JfdnNfRk9YTzFLT18wLjA1cEFkajEuMUwyRkMyMEJhc2VNZWFuLmNzdiIpDQp3cml0ZS5jc3YocmVzQ1NpZ19OSywgIk5LX05DUl92c19HRkkxS09fMC4wNXBBZGoxLjFMMkZDMjBCYXNlTWVhbi5jc3YiKQ0KDQoNCiMjVkVOTiBkaWFncmFtIERFRyBvZiBBTEwgTksgaW5kaXNjcmltaW5hdGUgb2YgU3Vic2V0DQoNCnNldDFOSyA8LSByZXNBU2lnX05LJHN5bWJvbA0Kc2V0Mk5LIDwtIHJlc0JTaWdfTkskc3ltYm9sDQpzZXQzTksgPC0gcmVzQ1NpZ19OSyRzeW1ib2wNCmNvbG9ycyA8LSBjKCJzbGF0ZWJsdWUxIiwgImdvbGRlbnJvZDEiLCAiaW5kaWFucmVkMSIpDQoNCnNldDFOSzwtbmEub21pdChzZXQxTkspDQpzZXQyTks8LW5hLm9taXQoc2V0Mk5LKQ0Kc2V0M05LPC1uYS5vbWl0KHNldDNOSykNCg0KdmVubi5kaWFncmFtKA0KICB4ID0gbGlzdChzZXQxTkssIHNldDJOSywgc2V0M05LKSwNCiAgY2F0ZWdvcnkubmFtZXMgPSBjKCJES08iLCAiRk9YTzFLTyIsICJHRkkxS08iKSwNCiAgZmlsZW5hbWUgPSAnREVHIEFMTCBOSyBWZW5uRGlhZ3JhbS5wbmcnLA0KICBvdXRwdXQgPSBUUlVFLA0KICBpbWFnZXR5cGUgPSAicG5nIiwNCiAgc2NhbGVkID0gRkFMU0UsDQogIGNvbCA9ICJibGFjayIsDQogIGZpbGwgPSBjb2xvcnMsDQogIGNhdC5jb2wgPSBjb2xvcnMsDQogIGNhdC5jZXggPSAxLjUsICAgIyBBZGp1c3QgdGhlIGZvbnQgc2l6ZSB0byBtYWtlIHRoZSBsYWJlbHMgc21hbGxlcg0KICBjYXQucG9zID0gMCwgICAgICMgTW92ZSB0aGUgbGFiZWxzIG91dHNpZGUgdGhlIGNpcmNsZXMNCiAgY2F0LmRpc3QgPSBjKDAuMDUsIDAuMDUsIC0wLjQ1KSwgICMgQWRqdXN0IHRoZSBkaXN0YW5jZSBmb3IgZWFjaCBjYXRlZ29yeSBsYWJlbCBpbmRpdmlkdWFsbHkNCiAgbWFyZ2luID0gMC4xNQ0KKQ0KYGBgDQoNCmBgYHtyfQ0KI25vdGUgdGhpcyBpcyBub3cganVzdCBtZXRhRGF0YSBhbmQgY291bnREYXRhIC0gbm90IHRvdGFsIGFzIHdlJ3JlIHN1YnNldHRpbmcgcG9wdWxhdGlvbnMNCg0KY291bnREYXRhIDwtIHJlYWQuY3N2KCdSOi8vSkRCRzIwMjItQTYzMjIvUmVzdWx0cy9TZXF1ZW5jaW5nL0ZpcnN0IGFuZCBTZWNvbmQgQmF0Y2ggY29tYmluZWQgYW5hbHlzaXMvSkQuY291bnQuY3N2JywgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiLCByb3cubmFtZXMgPSAxKQ0KbWV0YURhdGEgPC0gcmVhZC5jc3YoJ1I6Ly9KREJHMjAyMi1BNjMyMi9SZXN1bHRzL1NlcXVlbmNpbmcvRmlyc3QgYW5kIFNlY29uZCBCYXRjaCBjb21iaW5lZCBhbmFseXNpcy9KRC5tZXRhZGF0YS5jc3YnLCBoZWFkZXIgPSBUUlVFLCBzZXAgPSAiLCIpDQoNCm1ldGFEYXRhJGdlbm90eXBlIDwtIGZhY3RvcihtZXRhRGF0YSRnZW5vdHlwZSwgbGV2ZWxzID0gYygiTkNSIiwgIkZPWE8xS08iLCAiR0ZJMUtPIiwgIkRLTyIpKQ0KbWV0YURhdGEkY29uZGl0aW9uIDwtIGZhY3RvcihtZXRhRGF0YSRjb25kaXRpb24sIGxldmVscyA9IGMoIkltbSIsICJNMSIsICJNMiIpKQ0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHdpdGhpbiBlYWNoIGNvbmRpdGlvbiwgaG93IGRvZXMgS08gY29tcGFyZSB0byBXVCMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KZGRzX21ldGExIDwtIG1ldGFEYXRhICU+JSBmaWx0ZXIoY29uZGl0aW9uID09ICJNMSIpDQpkZHNfMSA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YT1jb3VudERhdGFbLHdoaWNoKGNvbG5hbWVzKGNvdW50RGF0YSkgJWluJSBkZHNfbWV0YTEkR2VuZWlkKV0sIGRkc19tZXRhMSwgZGVzaWduPX5nZW5vdHlwZSkNCiNkZHNfMSA8LSBkZHNfMVtyb3dTdW1zKGNvdW50cyhkZHNfMSkpID4gOCwgXQ0KZGRzXzEgPC0gREVTZXEoZGRzXzEpDQoNCnJlc0EgPC0gcmVzdWx0cyhkZHNfMSwgY29udHJhc3Q9YygiZ2Vub3R5cGUiLCJES08iLCJOQ1IiKSkNCnJlc0IgPC0gcmVzdWx0cyhkZHNfMSwgY29udHJhc3Q9YygiZ2Vub3R5cGUiLCJGT1hPMUtPIiwiTkNSIikpDQpyZXNDIDwtIHJlc3VsdHMoZGRzXzEsIGNvbnRyYXN0PWMoImdlbm90eXBlIiwiR0ZJMUtPIiwiTkNSIikpDQojIGNoYW5nZSB0aGUgbGFzdCB2YXJpYWJsZSBpbiB0aGUgc2VxdWVuY2UgdG8gYmUgdGhlIGNvbnRyb2wgYW5kIHRoZSBzZWNvbmQgdG8gYmUgdGhlIGNvbXBhcml0b3IgLSB0aGlzIHJlc0EgaGVyZSwgTkNSIChjb250cm9sKSB2cyBES08gDQoNCiAgZ2V0X2xmY19zaWduIDwtIGZ1bmN0aW9uKGRmLCB0aHIgPSAxLjEpew0KICBkZiRsZmNfdGhyIDwtIDANCiAgZGYkbGZjX3Roclt3aGljaChkZiRsb2cyRm9sZENoYW5nZSA+PSB0aHIpXSA8LSAxDQogIGRmJGxmY190aHJbd2hpY2goZGYkbG9nMkZvbGRDaGFuZ2UgPD0gKC0xLjEgKiB0aHIpKV0gPC0gLTENCiAgcmV0dXJuKGRmKQ0KfQ0KDQpyZXNBIDwtIGdldF9sZmNfc2lnbihyZXNBLCB0aHI9MS4xKQ0KcmVzQiA8LSBnZXRfbGZjX3NpZ24ocmVzQiwgdGhyPTEuMSkNCnJlc0MgPC0gZ2V0X2xmY19zaWduKHJlc0MsIHRocj0xLjEpDQoNCnJlc0EgPC0gcmVzQVtvcmRlcihyZXNBJHB2YWx1ZSwgZGVjcmVhc2luZz1GQUxTRSksIF0NCnJlc0IgPC0gcmVzQltvcmRlcihyZXNCJHB2YWx1ZSwgZGVjcmVhc2luZz1GQUxTRSksIF0NCnJlc0MgPC0gcmVzQ1tvcmRlcihyZXNDJHB2YWx1ZSwgZGVjcmVhc2luZz1GQUxTRSksIF0NCg0KdGFibGUocmVzQSRwYWRqIDwgMC4wNSwgcmVzQSRsZmNfdGhyKQ0KdGFibGUocmVzQiRwYWRqIDwgMC4wNSwgcmVzQiRsZmNfdGhyKQ0KdGFibGUocmVzQyRwYWRqIDwgMC4wNSwgcmVzQyRsZmNfdGhyKQ0KIA0KDQojTUEgcGxvdA0KDQpwbG90TUEoDQogIHJlc0EsDQogICNwYWRqID0gMC4wNSwNCiAgI2xvZzJGb2xkY2hhbmdlID0gMS41LA0KICBhbHBoYSA9IDAuNSwNCiAgI3NlbGVjdC50b3AubWV0aG9kID0gYygicGFkaiIsICJsb2cyRm9sZENoYW5nZSIpLA0KICAjdG9wID0gMjAsDQogICNzZWxlY3QudG9wLm1ldGhvZCA9IGMoInBhZGoiLCAibG9nMkZvbGRDaGFuZ2UiKSwNCiAgbWFpbiA9ICJNMSBOSyBjZWxscyAtIE5DUiBWcyBES08iLA0KICB4bGFiID0gIkF2ZXJhZ2UgbG9nMiBjb3VudHMgcGVyIG1pbGxpb24iLA0KICB5bGFiID0gIkxvZzIgRm9sZCBDaGFuZ2UiLA0KICB5bGltID0gYygtMTUsIDE1KSwNCiAgY29sTm9uU2lnID0gImJsYWNrIiwNCiAgI3BhbGV0dGUgPSBjKCIjQjMxQjIxIiwgIiMxNDY1QUMiLCAiZGFya2dyYXkiKSwNCiAgI2NvbFNpZyA9ICJmaXJlYnJpY2sxIiwNCiAgY29sU2lnID0gImRvZGdlcmJsdWUiLA0KICByZXR1cm5EYXRhID0gRkFMU0UsDQogIE1MRSA9IEZBTFNFLA0KICAjZ2d0aGVtZSA9IHRoZW1lX2NsYXNzaWMoKSwNCikNCmBgYA0KDQoNCmBgYHtyfQ0KI1BDQSBwbG90DQoNCnJsZCA8LSBybG9nKGRkc18xKQ0KIyBwbG90UENBKHJsZCwgaW50Z3JvdXAgPSBjKCJnZW5vdHlwZSIpKQ0KIyBwbG90UENBKHJsZCwgaW50Z3JvdXAgPSBjKCJnZW5vdHlwZSIsICJjb25kaXRpb24iKSkNCm15X3RoZW1lIDwtIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgICAgICAgICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJibGFjayIsIGZpbGwgPSBOQSwgbGluZXdpZHRoID0gMC4xKSkNCnBsb3RQQ0EocmxkLCBpbnRncm91cCA9ICJnZW5vdHlwZSIsIG50b3AgPSA1MDAsIHJldHVybkRhdGEgPSBGQUxTRSkgKyBteV90aGVtZSArIGdlb21fcG9pbnQoc2l6ZT01KSArIGxhYnModGl0bGUgPSAiUENBIFBsb3QgLSBNMSBHZW5lIEV4cHJlc3Npb24gRGF0YSIpDQpgYGANCg0KDQpgYGB7cn0NCnJlc0Ekc3ltYm9sIDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0EpLCBjb2x1bW49IlNZTUJPTCIsIGtleXR5cGU9IkVOU0VNQkwiLCBtdWx0aVZhbHM9ImZpcnN0IikNCnJlc0EkZW50cmV6IDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0EpLCBjb2x1bW49IkVOVFJFWklEIiwga2V5dHlwZT0iRU5TRU1CTCIsIG11bHRpVmFscz0iZmlyc3QiKQ0KcmVzQSRuYW1lIDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0EpLCBjb2x1bW49IkdFTkVOQU1FIiwga2V5dHlwZT0iRU5TRU1CTCIsIG11bHRpVmFscz0iZmlyc3QiKQ0KDQojQWRkIEVudHJleiwgU3ltYm9sIGFuZCBnZW5lIG5hbWUgdG8gcmVzQiBmaWxlcw0KcmVzQiRzeW1ib2wgPC0gbWFwSWRzKG9yZy5NbS5lZy5kYiwga2V5cz1yb3cubmFtZXMocmVzQiksIGNvbHVtbj0iU1lNQk9MIiwga2V5dHlwZT0iRU5TRU1CTCIsIG11bHRpVmFscz0iZmlyc3QiKQ0KcmVzQiRlbnRyZXogPC0gbWFwSWRzKG9yZy5NbS5lZy5kYiwga2V5cz1yb3cubmFtZXMocmVzQiksIGNvbHVtbj0iRU5UUkVaSUQiLCBrZXl0eXBlPSJFTlNFTUJMIiwgbXVsdGlWYWxzPSJmaXJzdCIpDQpyZXNCJG5hbWUgPC0gbWFwSWRzKG9yZy5NbS5lZy5kYiwga2V5cz1yb3cubmFtZXMocmVzQiksIGNvbHVtbj0iR0VORU5BTUUiLCBrZXl0eXBlPSJFTlNFTUJMIiwgbXVsdGlWYWxzPSJmaXJzdCIpDQoNCiNBZGQgRW50cmV6LCBTeW1ib2wgYW5kIGdlbmUgbmFtZSB0byByZXNDIGZpbGVzDQpyZXNDJHN5bWJvbCA8LSBtYXBJZHMob3JnLk1tLmVnLmRiLCBrZXlzPXJvdy5uYW1lcyhyZXNDKSwgY29sdW1uPSJTWU1CT0wiLCBrZXl0eXBlPSJFTlNFTUJMIiwgbXVsdGlWYWxzPSJmaXJzdCIpDQpyZXNDJGVudHJleiA8LSBtYXBJZHMob3JnLk1tLmVnLmRiLCBrZXlzPXJvdy5uYW1lcyhyZXNDKSwgY29sdW1uPSJFTlRSRVpJRCIsIGtleXR5cGU9IkVOU0VNQkwiLCBtdWx0aVZhbHM9ImZpcnN0IikNCnJlc0MkbmFtZSA8LSBtYXBJZHMob3JnLk1tLmVnLmRiLCBrZXlzPXJvdy5uYW1lcyhyZXNDKSwgY29sdW1uPSJHRU5FTkFNRSIsIGtleXR5cGU9IkVOU0VNQkwiLCBtdWx0aVZhbHM9ImZpcnN0IikNCg0KDQojIEFkZCBub3JtYWxpemVkIGNvdW50IHRvIHRoZSByZXN1bHQgVGFibGUNCnJlc0Fhbm5vPC0gbWVyZ2UoYXMuZGF0YS5mcmFtZShyZXNBKSwgYXMuZGF0YS5mcmFtZShjb3VudHMoZGRzXzEsIG5vcm1hbGl6ZWQ9VFJVRSkpLCBieT0icm93Lm5hbWVzIiwgc29ydD1GQUxTRSkNCnJlc0Jhbm5vPC0gbWVyZ2UoYXMuZGF0YS5mcmFtZShyZXNCKSwgYXMuZGF0YS5mcmFtZShjb3VudHMoZGRzXzEsIG5vcm1hbGl6ZWQ9VFJVRSkpLCBieT0icm93Lm5hbWVzIiwgc29ydD1GQUxTRSkNCnJlc0Nhbm5vPC0gbWVyZ2UoYXMuZGF0YS5mcmFtZShyZXNDKSwgYXMuZGF0YS5mcmFtZShjb3VudHMoZGRzXzEsIG5vcm1hbGl6ZWQ9VFJVRSkpLCBieT0icm93Lm5hbWVzIiwgc29ydD1GQUxTRSkNCg0Kd3JpdGUuY3N2KHJlc0Fhbm5vLCAiTTFfTkNSX3ZzX0RLTy5jc3YiKQ0Kd3JpdGUuY3N2KHJlc0Jhbm5vLCAiTTFfTkNSX3ZzX0ZPWE8xS08uY3N2IikNCndyaXRlLmNzdihyZXNDYW5ubywgIk0xX05DUl92c19HRkkxS08uY3N2IikNCmBgYA0KDQpgYGB7cn0NCiMjIFRoaXMgaXMganVzdCBtZSBwbGF5aW5nIGFyb3VuZCB3aXRoIGEgdm9sY2FubyBwbG90IGZpcnN0IHRvIHNlZSBsb3RzIG9mIGdlbmVzIGFuZCB0aGVuIGEgc2Vjb25kIG9uZSB3aGVyZSBJJ3ZlIGhhbmRwaWNrZWQgc29tZSBnZW5lcyB0byBtYXAgb24gDQoNCiN2b2xjYW5vIHBsb3QgcmVzQQ0Kdm9scGxvdF9yZXNBX2Rpc2NvdmVyeSA8LSBFbmhhbmNlZFZvbGNhbm8ocmVzQSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWIgPSByZXNBJHN5bWJvbCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gImxvZzJGb2xkQ2hhbmdlIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gInBhZGoiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvcmRlciA9ICJmdWxsIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJDb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyaWRsaW5lcy5tYWpvciA9IEYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZGxpbmVzLm1pbm9yID0gRiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gJ00xIC0gREtPIHZzIE5DUicsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJ0aXRsZSA9IGJxdW90ZShpdGFsaWMoJ0ZEUiA8PSAwLjA1IGFuZCBhYnNvbHV0ZSBGQyA+PSAxLjEnKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjc2VsZWN0TGFiID0gYygnRW9tZXMnLCdGT1hPMScsJ0dmaTEnLCdJZDMnLCdQZGNkMScsJ0d6bWEnLCdHem1iJywgJ1RieDIxJyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wMDAwNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIEZDY3V0b2ZmID0gMS4xLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRTaXplID0gMy4wLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiU2l6ZSA9IDMuNSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uID0gJ25vbmUnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgeGxpbSA9IGMoLTEwLCAxNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjbGVnZW5kTGFiZWxzID0gYygiTlMiLCBleHByZXNzaW9uKExvZ1syXSB+IEZDKSwgInAtdmFsdWUiLCBleHByZXNzaW9uKHAgLSB2YWx1ZSB+IGFuZCB+IGxvZ1syXSB+IEZDKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAjZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5vdmVybGFwcyA9IDEwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aENvbm5lY3RvcnMgPSB1bml0KDAuMDAxLCAibnBjIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlQ29ubmVjdG9ycyA9ICdjbG9zZWQnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kc0Nvbm5lY3RvcnMgPSAibGFzdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjY29sPWMoImdyZXkiLCAiZ3JlZW40IiwgImJsdWUiLCAicmVkMyIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sQWxwaGEgPSAwLjUNCikNCnZvbHBsb3RfcmVzQV9kaXNjb3ZlcnkNCmdnc2F2ZShmaWxlbmFtZSA9ICJWb2xwbG90IE0xIERLTyBOSyBjZWxsc19zZWFyY2gudGlmZiIsDQogICAgICAgcGxvdCA9IHZvbHBsb3RfcmVzQV9kaXNjb3ZlcnksIGRldmljZSA9ICJ0aWZmIiwgcGF0aCA9IE5VTEwsIHNjYWxlID0gMSwgd2lkdGggPSA4LCBoZWlnaHQgPSA4LCB1bml0cyA9IGMoImluIiksIGRwaSA9IDYwMCkNCmBgYA0KDQoNCmBgYHtyfQ0KIyMjIyMjIyMgc2Vjb25kIHZvbGNhbm8gcGxvdCANCg0KDQpsYWJfaXRhbGljcyA8LSBwYXN0ZTAoIml0YWxpYygnIiwgcmVzQSRzeW1ib2wsICInKSIpDQpzZWxlY3RMYWJfaXRhbGljcyA9IHBhc3RlMCgNCiAgIml0YWxpYygnIiwNCiAgYygnRHVzcDcnLCdQdHBuNScsJ0ZjZ3IzJywgJ1RjZjcnLCdJY29zJywnVmVnZmMnLCdHbWZnJywnQ3BoeDEnLCdHcHIxNScsICdUaHkxJywgJ05lazEwJywgJ0hvcHgnLCAnRk9YTzEnLCAnR2ZpMScpLA0KICAiJykiKQ0KDQpWb2xwbG90X00xcmVzQSA8LSBFbmhhbmNlZFZvbGNhbm8ocmVzQSwNCiAgICAgICAgICAgICAgICBsYWIgPSBsYWJfaXRhbGljcywNCiAgICAgICAgICAgICAgICB4ID0gJ2xvZzJGb2xkQ2hhbmdlJywNCiAgICAgICAgICAgICAgICB5ID0gJ3B2YWx1ZScsDQogICAgICAgICAgICAgICAgc2VsZWN0TGFiID0gc2VsZWN0TGFiX2l0YWxpY3MsDQogICAgICAgICAgICAgICAgeGxhYiA9IGJxdW90ZSh+TG9nWzJdfiAnZm9sZCBjaGFuZ2UnKSwNCiAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wMDAwNSwNCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDEuMSwNCiAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAzLjAsDQogICAgICAgICAgICAgICAgbGFiU2l6ZSA9IDYuMCwNCiAgICAgICAgICAgICAgICBsYWJDb2wgPSAnYmxhY2snLA0KICAgICAgICAgICAgICAgIHRpdGxlID0gJ00xIC0gREtPIHZzIE5DUicsDQogICAgICAgICAgICAgICAgc3VidGl0bGUgPSBicXVvdGUoaXRhbGljKCdGRFIgPD0gMC4wNSBhbmQgYWJzb2x1dGUgRkMgPj0gMS4xJykpLA0KICAgICAgICAgICAgICAgICNib3JkZXIgPSAiZnVsbCIsDQogICAgICAgICAgICAgICAgbGFiRmFjZSA9ICdib2xkJywNCiAgICAgICAgICAgICAgICBib3hlZExhYmVscyA9IFRSVUUsDQogICAgICAgICAgICAgICAgZ3JpZGxpbmVzLm1ham9yID0gRiwgDQogICAgICAgICAgICAgICAgZ3JpZGxpbmVzLm1pbm9yID0gRiwNCiAgICAgICAgICAgICAgICBwYXJzZUxhYmVscyA9IFRSVUUsDQogICAgICAgICAgICAgICAgY29sID0gYygnZ3JleTMwJywgJ2dyZWVuNCcsICdibHVlMScsICdyZWQzJyksDQogICAgICAgICAgICAgICAgY29sQWxwaGEgPSA0LzUsDQogICAgICAgICAgICAgICAgbGVnZW5kUG9zaXRpb24gPSAnYm90dG9tJywNCiAgICAgICAgICAgICAgICBsZWdlbmRMYWJTaXplID0gMTQsDQogICAgICAgICAgICAgICAgbGVnZW5kSWNvblNpemUgPSA0LjAsDQogICAgICAgICAgICAgICAgZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLA0KICAgICAgICAgICAgICAgIHdpZHRoQ29ubmVjdG9ycyA9IDEuMCwNCiAgICAgICAgICAgICAgICBjb2xDb25uZWN0b3JzID0gJ2JsYWNrJykgKyBjb29yZF9mbGlwKCkNClZvbHBsb3RfTTFyZXNBDQpgYGANCg0KYGBge3J9DQpjb3VudERhdGFUT1RBTCA8LSByZWFkLmNzdignUjovL0pEQkcyMDIyLUE2MzIyL1Jlc3VsdHMvU2VxdWVuY2luZy9GaXJzdCBhbmQgU2Vjb25kIEJhdGNoIGNvbWJpbmVkIGFuYWx5c2lzL0pELmNvdW50LmNzdicsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIiwgcm93Lm5hbWVzID0gMSkgDQptZXRhRGF0YVRPVEFMIDwtIHJlYWQuY3N2KCdSOi8vSkRCRzIwMjItQTYzMjIvUmVzdWx0cy9TZXF1ZW5jaW5nL0ZpcnN0IGFuZCBTZWNvbmQgQmF0Y2ggY29tYmluZWQgYW5hbHlzaXMvSkQubWV0YWRhdGEuY3N2JywgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiKQ0KDQptZXRhRGF0YVRPVEFMJGdlbm90eXBlIDwtIGZhY3RvcihtZXRhRGF0YVRPVEFMJGdlbm90eXBlLCBsZXZlbHMgPSBjKCJOQ1IiLCAiRk9YTzFLTyIsICJHRkkxS08iLCAiREtPIikpDQptZXRhRGF0YVRPVEFMJGNvbmRpdGlvbiA8LSBmYWN0b3IobWV0YURhdGFUT1RBTCRjb25kaXRpb24sIGxldmVscyA9IGMoIkltbSIsICJNMSIsICJNMiIpKQ0KDQogDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIHdpdGhpbiBlYWNoIGNvbmRpdGlvbiwgaG93IGRvZXMgS08gY29tcGFyZSB0byBXVCMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCg0KZGRzX21ldGExIDwtIG1ldGFEYXRhVE9UQUwgJT4lIGZpbHRlcihjb25kaXRpb24gPT0gIk0xIikNCmRkc18xIDwtIERFU2VxRGF0YVNldEZyb21NYXRyaXgoY291bnREYXRhPWNvdW50RGF0YVRPVEFMWyx3aGljaChjb2xuYW1lcyhjb3VudERhdGFUT1RBTCkgJWluJSBkZHNfbWV0YTEkR2VuZWlkKV0sIGRkc19tZXRhMSwgZGVzaWduPX5nZW5vdHlwZSkNCiNkZHNfMSA8LSBkZHNfMVtyb3dTdW1zKGNvdW50cyhkZHNfMSkpID4gOCwgXQ0KZGRzXzEgPC0gREVTZXEoZGRzXzEpDQoNCnJlc0EgPC0gcmVzdWx0cyhkZHNfMSwgY29udHJhc3Q9YygiZ2Vub3R5cGUiLCJES08iLCJOQ1IiKSkNCnJlc0IgPC0gcmVzdWx0cyhkZHNfMSwgY29udHJhc3Q9YygiZ2Vub3R5cGUiLCJGT1hPMUtPIiwiTkNSIikpDQpyZXNDIDwtIHJlc3VsdHMoZGRzXzEsIGNvbnRyYXN0PWMoImdlbm90eXBlIiwiR0ZJMUtPIiwiTkNSIikpDQojIGNoYW5nZSB0aGUgbGFzdCB2YXJpYWJsZSBpbiB0aGUgc2VxdWVuY2UgdG8gYmUgdGhlIGNvbnRyb2wgYW5kIHRoZSBzZWNvbmQgdG8gYmUgdGhlIGNvbXBhcml0b3IgLSB0aGlzIHJlc0EgaGVyZSwgTkNSIChjb250cm9sKSB2cyBES08gDQoNCiAgZ2V0X2xmY19zaWduIDwtIGZ1bmN0aW9uKGRmLCB0aHIgPSAxLjEpew0KICBkZiRsZmNfdGhyIDwtIDANCiAgZGYkbGZjX3Roclt3aGljaChkZiRsb2cyRm9sZENoYW5nZSA+PSB0aHIpXSA8LSAxDQogIGRmJGxmY190aHJbd2hpY2goZGYkbG9nMkZvbGRDaGFuZ2UgPD0gKC0xLjEgKiB0aHIpKV0gPC0gLTENCiAgcmV0dXJuKGRmKQ0KfQ0KDQpyZXNBIDwtIGdldF9sZmNfc2lnbihyZXNBLCB0aHI9MS4xKQ0KcmVzQiA8LSBnZXRfbGZjX3NpZ24ocmVzQiwgdGhyPTEuMSkNCnJlc0MgPC0gZ2V0X2xmY19zaWduKHJlc0MsIHRocj0xLjEpDQoNCnJlc0EgPC0gcmVzQVtvcmRlcihyZXNBJHB2YWx1ZSwgZGVjcmVhc2luZz1GQUxTRSksIF0NCnJlc0IgPC0gcmVzQltvcmRlcihyZXNCJHB2YWx1ZSwgZGVjcmVhc2luZz1GQUxTRSksIF0NCnJlc0MgPC0gcmVzQ1tvcmRlcihyZXNDJHB2YWx1ZSwgZGVjcmVhc2luZz1GQUxTRSksIF0NCg0KdGFibGUocmVzQSRwYWRqIDwgMC4wNSwgcmVzQSRsZmNfdGhyKQ0KdGFibGUocmVzQiRwYWRqIDwgMC4wNSwgcmVzQiRsZmNfdGhyKQ0KdGFibGUocmVzQyRwYWRqIDwgMC4wNSwgcmVzQyRsZmNfdGhyKQ0KDQojQWRkIEVudHJleiwgU3ltYm9sIGFuZCBnZW5lIG5hbWUgdG8gcmVzQSBmaWxlcw0KcmVzQSRzeW1ib2wgPC0gbWFwSWRzKG9yZy5NbS5lZy5kYiwga2V5cz1yb3cubmFtZXMocmVzQSksIGNvbHVtbj0iU1lNQk9MIiwga2V5dHlwZT0iRU5TRU1CTCIsIG11bHRpVmFscz0iZmlyc3QiKQ0KcmVzQSRlbnRyZXogPC0gbWFwSWRzKG9yZy5NbS5lZy5kYiwga2V5cz1yb3cubmFtZXMocmVzQSksIGNvbHVtbj0iRU5UUkVaSUQiLCBrZXl0eXBlPSJFTlNFTUJMIiwgbXVsdGlWYWxzPSJmaXJzdCIpDQpyZXNBJG5hbWUgPC0gbWFwSWRzKG9yZy5NbS5lZy5kYiwga2V5cz1yb3cubmFtZXMocmVzQSksIGNvbHVtbj0iR0VORU5BTUUiLCBrZXl0eXBlPSJFTlNFTUJMIiwgbXVsdGlWYWxzPSJmaXJzdCIpDQoNCiNBZGQgRW50cmV6LCBTeW1ib2wgYW5kIGdlbmUgbmFtZSB0byByZXNCIGZpbGVzDQpyZXNCJHN5bWJvbCA8LSBtYXBJZHMob3JnLk1tLmVnLmRiLCBrZXlzPXJvdy5uYW1lcyhyZXNCKSwgY29sdW1uPSJTWU1CT0wiLCBrZXl0eXBlPSJFTlNFTUJMIiwgbXVsdGlWYWxzPSJmaXJzdCIpDQpyZXNCJGVudHJleiA8LSBtYXBJZHMob3JnLk1tLmVnLmRiLCBrZXlzPXJvdy5uYW1lcyhyZXNCKSwgY29sdW1uPSJFTlRSRVpJRCIsIGtleXR5cGU9IkVOU0VNQkwiLCBtdWx0aVZhbHM9ImZpcnN0IikNCnJlc0IkbmFtZSA8LSBtYXBJZHMob3JnLk1tLmVnLmRiLCBrZXlzPXJvdy5uYW1lcyhyZXNCKSwgY29sdW1uPSJHRU5FTkFNRSIsIGtleXR5cGU9IkVOU0VNQkwiLCBtdWx0aVZhbHM9ImZpcnN0IikNCg0KI0FkZCBFbnRyZXosIFN5bWJvbCBhbmQgZ2VuZSBuYW1lIHRvIHJlc0MgZmlsZXMNCnJlc0Mkc3ltYm9sIDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0MpLCBjb2x1bW49IlNZTUJPTCIsIGtleXR5cGU9IkVOU0VNQkwiLCBtdWx0aVZhbHM9ImZpcnN0IikNCnJlc0MkZW50cmV6IDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0MpLCBjb2x1bW49IkVOVFJFWklEIiwga2V5dHlwZT0iRU5TRU1CTCIsIG11bHRpVmFscz0iZmlyc3QiKQ0KcmVzQyRuYW1lIDwtIG1hcElkcyhvcmcuTW0uZWcuZGIsIGtleXM9cm93Lm5hbWVzKHJlc0MpLCBjb2x1bW49IkdFTkVOQU1FIiwga2V5dHlwZT0iRU5TRU1CTCIsIG11bHRpVmFscz0iZmlyc3QiKQ0KDQoNCiMgQWRkIG5vcm1hbGl6ZWQgY291bnQgdG8gdGhlIHJlc3VsdCBUYWJsZQ0KcmVzQTwtIG1lcmdlKGFzLmRhdGEuZnJhbWUocmVzQSksIGFzLmRhdGEuZnJhbWUoY291bnRzKGRkc18xLCBub3JtYWxpemVkPVRSVUUpKSwgYnk9InJvdy5uYW1lcyIsIHNvcnQ9RkFMU0UpDQpyZXNCPC0gbWVyZ2UoYXMuZGF0YS5mcmFtZShyZXNCKSwgYXMuZGF0YS5mcmFtZShjb3VudHMoZGRzXzEsIG5vcm1hbGl6ZWQ9VFJVRSkpLCBieT0icm93Lm5hbWVzIiwgc29ydD1GQUxTRSkNCnJlc0M8LSBtZXJnZShhcy5kYXRhLmZyYW1lKHJlc0MpLCBhcy5kYXRhLmZyYW1lKGNvdW50cyhkZHNfMSwgbm9ybWFsaXplZD1UUlVFKSksIGJ5PSJyb3cubmFtZXMiLCBzb3J0PUZBTFNFKQ0KDQoNCiNQQ0EgcGxvdA0KcmxkIDwtIHJsb2coZGRzXzEpDQojIHBsb3RQQ0EocmxkLCBpbnRncm91cCA9IGMoImdlbm90eXBlIikpDQojIHBsb3RQQ0EocmxkLCBpbnRncm91cCA9IGMoImdlbm90eXBlIiwgImNvbmRpdGlvbiIpKQ0KbXlfdGhlbWUgPC0gdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgICAgICAgICAgICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gImJsYWNrIiwgZmlsbCA9IE5BLCBsaW5ld2lkdGggPSAwLjEpKQ0KcGxvdFBDQShybGQsIGludGdyb3VwID0gImdlbm90eXBlIiwgbnRvcCA9IDUwMCwgcmV0dXJuRGF0YSA9IEZBTFNFKSArIG15X3RoZW1lICsgZ2VvbV9wb2ludChzaXplPTUpICsgbGFicyh0aXRsZSA9ICJQQ0EgUGxvdCAtIE0xIEdlbmUgRXhwcmVzc2lvbiBEYXRhIikNCg0KcmVzQVNpZyA8LSByZXNBW3doaWNoKHJlc0EkcGFkaiA8IDAuMDUgJiBhYnMocmVzQSRsb2cyRm9sZENoYW5nZSkgPj0gMS4xICYgcmVzQSRiYXNlTWVhbiA+PSAyMCksIF0NCnJlc0JTaWcgPC0gcmVzQlt3aGljaChyZXNCJHBhZGogPCAwLjA1ICYgYWJzKHJlc0IkbG9nMkZvbGRDaGFuZ2UpID49IDEuMSAmIHJlc0IkYmFzZU1lYW4gPj0gMjApLCBdDQpyZXNDU2lnIDwtIHJlc0Nbd2hpY2gocmVzQyRwYWRqIDwgMC4wNSAmIGFicyhyZXNDJGxvZzJGb2xkQ2hhbmdlKSA+PSAxLjEgJiByZXNDJGJhc2VNZWFuID49IDIwKSwgXQ0KDQptYXQgPC0gYXNzYXkocmxkKQ0KaWRBIDwtIHJlc0FTaWckUm93Lm5hbWVzDQpERWdlbmVzIDwtIG1hdFtpZEEsXQ0KY29sRGF0YShybGQpDQoNCmFubm90YXRpb24gPC0gZGF0YS5mcmFtZShnZW5vdHlwZT1jb2xEYXRhKHJsZCkkZ2Vub3R5cGUpDQpnZW5vdHlwZV9jb2xvcnMgPC0gbGlzdCgiZ2Vub3R5cGUiPWMoIk5DUiIgPSAiZ3JleTY1IiwgIkZPWE8xS08iID0gImdvbGRlbnJvZDEiLCAiR0ZJMUtPIiA9ICJpbmRpYW5yZWQxIiwgIkRLTyIgPSAic2xhdGVibHVlMSIpKQ0KDQpid3JfOTkgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJjeWFuIiwgImJsYWNrIiwgInllbGxvdyIpKShuID0gOTkpDQoNCiNEZW5kcm9ncmFtDQpwaGVhdG1hcChERWdlbmVzLCANCiAgICAgICAgIHNjYWxlID0gInJvdyIsIA0KICAgICAgICAgc2hvd19yb3duYW1lcyA9IEYsDQogICAgICAgICBzaG93X2NvbG5hbWVzID0gRiwNCiAgICAgICAgIGNvbG9yID0gYndyXzk5LA0KICAgICAgICAgY2x1c3RlcmluZ19kaXN0YW5jZV9yb3dzID0gImNvcnJlbGF0aW9uIiwgDQogICAgICAgICBhbm5vdGF0aW9uX2NvbCA9IGFubm90YXRpb24sIA0KICAgICAgICAgYW5ub3RhdGlvbl9jb2xvcnMgPSBnZW5vdHlwZV9jb2xvcnMsDQogICAgICAgICB0cmVlaGVpZ2h0X3JvdyA9IDMwLA0KICAgICAgICAgdHJlZWhlaWdodF9jb2wgPSAxNSwNCiAgICAgICAgIG1haW49Ik0xIERFRyIpDQpgYGANCg0KYGBge3J9DQojVE9QIDQwIERFRw0KDQpvcmRlclNpZ3Jlc0EgPC0gcmVzQVNpZyAlPiUgZmlsdGVyKHBhZGogPCAwLjA1ICYgYWJzKGxvZzJGb2xkQ2hhbmdlKSA+PSAxLjEgJiBiYXNlTWVhbiA+PSAyMCAmICFpcy5uYShzeW1ib2wpKQ0Kb3JkZXJTaWdyZXNCIDwtIHJlc0JTaWcgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSAmIGFicyhsb2cyRm9sZENoYW5nZSkgPj0gMS4xICYgYmFzZU1lYW4gPj0gMjAgJiAhaXMubmEoc3ltYm9sKSkNCm9yZGVyU2lncmVzQyA8LSByZXNDU2lnICU+JSBmaWx0ZXIocGFkaiA8IDAuMDUgJiBhYnMobG9nMkZvbGRDaGFuZ2UpID49IDEuMSAmIGJhc2VNZWFuID49IDIwICYgIWlzLm5hKHN5bWJvbCkpDQoNCndyaXRlLmNzdihvcmRlclNpZ3Jlc0EsICJNMV9OQ1JfdnNfREtPMC4wNXBBZGoxLjFMMkZDMjBCYXNlTWVhbi5jc3YiKQ0Kd3JpdGUuY3N2KG9yZGVyU2lncmVzQiwgIk0xX05DUl92c19GT1hPMUtPMC4wNXBBZGoxLjFMMkZDMjBCYXNlTWVhbi5jc3YiKQ0Kd3JpdGUuY3N2KG9yZGVyU2lncmVzQywgIk0xX05DUl92c19HRkkxS08wLjA1cEFkajEuMUwyRkMyMEJhc2VNZWFuLmNzdiIpDQoNCg0KaWQxIDwtIG9yZGVyU2lncmVzQSRSb3cubmFtZXMNCmlkMiA8LSBvcmRlclNpZ3Jlc0Ekc3ltYm9sDQp0b3BERSA8LSBtYXRbaWQxLCBkZHNfbWV0YTEgJT4lIGZpbHRlcihnZW5vdHlwZSAlaW4lIGMoIkRLTyIsICJOQ1IiKSkgJT4lIHNlbGVjdChHZW5laWQpICU+JSB1bmxpc3QgJT4lIGFzLmNoYXJhY3Rlcl0NCnJvd25hbWVzKHRvcERFKSA8LSBpZDINCnRvcDQwREUgPC0gaGVhZCh0b3BERSwgbj00MCkNCiNid3JfOTAgPC0gY29sb3JSYW1wUGFsZXR0ZShjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKShuID0gOTkpDQoNCg0KI1RvcCA0MCBERSBnZW5lcyBmcm9tIGRkc18xDQpwaGVhdG1hcCh0b3A0MERFLCANCiAgICAgICAgIHNjYWxlID0gInJvdyIsIA0KICAgICAgICAgc2hvd19yb3duYW1lcyA9IFQsDQogICAgICAgICBzaG93X2NvbG5hbWVzID0gRiwNCiAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9ICJjb3JyZWxhdGlvbiIsDQogICAgICAgICBhbm5vdGF0aW9uX2NvbG9ycyA9IGdlbm90eXBlX2NvbG9ycywNCiAgICAgICAgIGJvcmRlcl9jb2xvciA9IE5BLA0KICAgICAgICAgY2VsbGhlaWdodCA9IDEyLA0KICAgICAgICAgbGVnZW5kID0gVCwNCiAgICAgICAgI2FuZ2xlX2NvbCA9IGMoIjI3MCIsICIwIiwgIjQ1IiwgIjkwIiwgIjMxNSIpDQogICAgICAgICBjZWxsd2lkdGggPSAxMiwNCiAgICAgICAgIHRyZWVoZWlnaHRfY29sID0gNSwNCiAgICAgICAgIHRyZWVoZWlnaHRfcm93ID0gNSwNCiAgICAgICAgIGFubm90YXRpb25fY29sID0gZGRzX21ldGExICU+JSBmaWx0ZXIoZ2Vub3R5cGUgJWluJSBjKCJES08iLCAiTkNSIikpICU+JSBzZWxlY3QoZ2Vub3R5cGUpLCANCiAgICAgICAgICNtYWluPSJES08gLSBUb3AgNDAgTTEgREVHcyIsIA0KICAgICAgICAgY29sb3IgPSBid3JfOTkpDQpgYGANCg0KYGBge3J9DQojIENhbmRpZGF0ZSBnZW5lIGhlYXRtYXBzDQoNCmdlbmVzRWZmIDwtIGMoIkxhZzMiLCAiQmF0ZjMiLCAiVG5mc2Y4IiwgIkd6bW0iLCAiSWwyMXIiLCAiSXRrIiwgIlRuZnNmMTAiLCAiVGxyMyIsICJGb3hvMSIsICJTb2NzMSIsICJDZDJhcCIsICJHem1rIiwgIklsMThyMSIsICJJbDEycmIyIiwgIlplYjIiLCAiUHJmMSIsICJHbXpiIiwgIklmbmciLCAiQ2NsNCIsICJTaDJkMWIxIikNCmdlbmVzRGV2RGlmZiA8LSBjKCJMZWYxIiwgIkdhdGE2IiwgIkhoYXQiLCAiRW9tZXMiLCAiUnVueDIiLCAiU294NCIsICJJZDMiLCAiVG94IiwgIklsNHJhIiwgIkR0eDEiLCAiQ2QyNyIsICJUY2Y3IiwgIktscmcxIiwgIlRieDIxIiwgIlNwaTEiLCAiSWQyIikNCmdlbmVzQ2VsbFN1cmZhY2UgPC0gYygiS2l0IiwgIlRoeTEiLCAiS2xyYTEiLCAiS2xyYTMiLCAiS2xyYTQiLCAiS2xyYTgiLCAiS2xyYTkiLCAiS2xyYTE3IiwgIktscmIxYSIsICJLbHJjMSIsICJLbHJjMyIsICJLbHJkMSIsICJOY3IxIiwgIkNkMjQ0YSIsICJLbHJnMSIsICJDZDIyNiIsICJJbDJyYiIsICJLbHJiMWMiLCAiRmNncjMiLCAiU2VsbCIsICJDZDI3IiwgIkgyLUFiMSIsICJDZDg2IiwgIkNkNjkiLCAiS2xyZDEiLCAiTGFpcjEiLCAiTGFnMyIsICJOa3JwMSIsICJDY3I1IiwgIkNjcjciLCAiQ3hjcjEiLCAiQ3hjcjIiLCAiQ3hjcjMiLCAiQ3hjcjQiLCAiQ3gzY3IxIiwgIlMxcHI1IiwgIkNjcjIiLCAiSWwycmEiLCAiSWwxMnJiMSIsICJJbDE1cmEiLCAiSWwxOHIxIiwgIkZjZ3IxIiwgIkZjZ3IyYSIsICJGY2dyMmIiLCAiRmNncjJjIiwgIkZjZ3IzIikNCmdlbmVzTWV0YWJvbGlzbSA8LSBjKCJQcGFyZ2MxYSIsICJQcGFyYSIsICJQcGFyZCIsICJQcGFyZyIsICJTaXJ0MSIsICJGb3hvMSIsICJGb3hvMyIsICJGb3hvNCIsICJBY294MSIsICJBY2FkbSIsICJBY2FkcyIsICJBY3NsMSIsICJBY3NsMyIsICJBY3NsNCIsICJBY3NsNSIsICJBY3NsNiIsICJBa3IxYjgiLCAiQWtyMWIzIiwgIkFsZGgxYTEiLCAiQWxkaDIiLCAiQWxkaDNhMSIsICJBbGRoNGExIiwgIkFsZGg1YTEiLCAiQ3B0MWEiLCAiQ3B0MWIiLCAiQ3B0MiIsICJGYXNuIiwgIkZhYnAxIiwgIkZhYnAyIiwgIkZhYnAzIiwgIkZhYnA0IiwgIkZhYnA1IiwgIkdsdXQxIiwgIkdsdXQyIiwgIkdsdXQzIiwgIkdsdXQ0IiwgIkc2cGQiLCAiUGNrMSIsICJQY2syIiwgIkhrMSIsICJIazIiLCAiR2NrIiwgIlBkazEiLCAiUGRrMiIsICJQZGszIikNCmdlbmVzUHJvbGlmZXJhdGlvbkNlbGxTdXJ2aXZhbCA8LSBjKCJLbGYyIiwgIkJiYzMiLCAiS2xmNCIsICJJbDdyIiwgIkJjbDJhMWIiLCAiQmFnMyIsICJCY2wyIiwgIkJjbDJsMSIsICAiQmNsMmwxMSIsICJNY2wxIiwgIkJheCIsICJCYWQiLCAiQmlkIiwgIkJhazEiLCAiQ2FzcDMiLCAiQ2FzcDgiLCAiQ2FzcDkiLCAiWGlhcCIsICJTdXJ2aXZpbiIsICJQdGVuIiwgIkFrdDEiLCAiQWt0MiIsICJBa3QzIiwgIk10b3IiLCAiUmIxIiwgIkUyZjEiLCAiRTJmIiwgIkUyZjMiLCAiVHA1MyIsICJDZGtuMWEiLCAiQ2RrbjFiIiwgIkNka24yYSIsICJDZGtuMmIiLCAiTmZrYjEiLCAiTmZrYjIiLCAiUmVsYSIsICJSZWxiIiwgIlRuZiIsICJUbmZyc2YxYSIsICJUbmZyc2YxYiIsICJNYXBrMSIsICJNYXBrMyIsICAiTWFwazgiLCAiTWFwazkiLCAiTWFwazE0IiwgIk1hcGsxMiIsICJNYXBrMTMiLCAiTWFwM2sxIiwgIk1hcDNrNSIsICJNYXAzazciKQ0KZ2VuZXNUcmFuc2NyaXB0aW9uRmFjdG9ycyA8LSBjKCJHZmkxIiwgIkdmaTFiIiwgIkVvbWVzIiwgIlRieDIxIiwgIk5maWwzIiwgIklkMiIsICJOZmtiaWEiLCAiTmZrYmlkIiwgIk5ma2JpeiIsICJTcGkxIiwgIk5yNGExIiwgIk5jcjEiLCAiVGNmNyIsICJIb2JpdCIsICJCbGltcDEiLCAiR2F0YTMiLCAiSWw3ciIsICJUb3giLCAiVG94MiIsICJaYnRiMTYiLCAiUm9yYSIsICJFdHMxIiwgIkVvbWVzIiwgIlRveDIiLCAiVGJ4MjEiLCAiWmViMiIsICJSdW54MyIsICJJZDIiLCAiTmZpbDMiLCAiVG94IiwgIkdhdGEzIiwgIlByZG0xIiwgIkJhdGYiLCAiQmF0ZjMiLCAiSXJmNCIsICJJcmY4IiwgIlN0YXQ0IiwgIlN0YXQ1IiwgImMtTXljIiwgIk5vdGNoMSIsICJUdGYxIiwgIk5reDMtMSIsICJHZmkxIiwgIkdmaTFiIiwgIkZveG8xIiwgIkZveG8zIiwgIkZveG80IiwgIlNwaTEiLCAiU3BpYiIsICJTcGljIiwgIkV0czEiLCAiRXRzMiIsICJQYXg1IiwgIlBheDgiKQ0KZ2VuZXNNaWdyYXRpb24gPC0gYygiQ3hjcjMiLCAiQ2NyNSIsICJDY3IyIiwgIkdwcjE4MyIsICJDY3I3IiwgIkl0Z2IzIiwgIkNkNjMiLCAiSXRnYWQiLCAiR3ByMTU1IiwgIkl0Z2I1IiwgIkNjcjEwIiwgIkN4Y3I0IiwgIlNlbGwiLCAiSXRnYTQiLCAiSXRnYTYiLCAiSXRnYTEiLCAiUzFwcjUiLCAiQ3hjcjMiLCAiQ3gzY3IxIiwgIkNjcjciLCAiUzFwcjUiLCAiQ3hjcjQiLCAiQ3hjcjYiLCAiQ2NyNSIsICJDY3I5IiwgIkNjcjIiLCAiQ2NyNiIsICJJdGdhNCIsICJJdGdiMSIsICJJdGdiMiIsICJJdGdhTCIsICJJdGdhTSIsICJJdGdhMSIsICJJdGdhRSIsICJJdGdhRCIsICJJdGdiNyIsICJJdGdhRSIsICJTZWxwIiwgIlNlbGUiLCAiU2VsbCIsICJDbGRuMSIsICJDbGRuMiIsICJDbGRuMyIsICJDbGRuNCIsICJDbGRuNSIsICJDbGRuNyIsICJDbGRuOCIsICJDbGRuOSIsICJDbGRuMTAiLCAiQ2xkbjExIiwgIkNsZG4xMiIsICJDbGRuMTUiLCAiQ2xkbjE2IiwgIkNsZG4xNyIsICJDbGRuMTgiLCAiQ2xkbjE5IiwgIkNsZG4yMCIpDQpnZW5lc0FjdGl2YXRpb25JbmhpYml0aW9uIDwtIGMoIktscmE4IiwgIktscmE3IiwgIktscmE0IiwgIktscmEzIiwgIktscmExIiwgIktscmQxIiwgIkNkOTQiLCAiTGFpci0xIiwgIlB0cG42IiwgIlNocDEiLCAiQ2lzaCIsICJDZDI0NGEiLCAiQ2QzOCIsICJJbDZzdCIsICJLbHJjMSIsICJDZDEwMSIsICJIbWJveDEiLCAiS2xyYTMiLCAiS2xyYTEiLCAiQ2QyMjYiLCAiQ2Q5NiIsICJDZDIwMHIxIiwgIkFociIsICJDZDcyIiwgIlRpZ2l0IiwgIkNkNjkiLCAiTmNyIiwgIktscmIxYyIsICJLbHJiMWIiLCAiQ2QyNDQiLCAiTHk0OWgiLCAiS2xyazEiLCAiQ2QyMjYiLCAiQ2QyNSIsICJJbDJyYiIsICJJZm5ncjEiLCAiSWZuYXIxIiwgIlN0YXQ0IiwgIlN0YXQ1IiwgIlN0YXQxIiwgIlByZjEiLCAiR3ptYSIsICJHem1iIiwgIkd6bWsiLCAiR3ptbSIsICJUbmZzZjEwIiwgIkZhc2wiLCAiRmFzIiwgIklmbmciKQ0KZ2VuZXNDeXRva2luZUNoZW1va2luZSA8LSBjKCJJZm5nIiwgIlRuZiIsICJDc2YyIiwgIklsMTAiLCAiSWwyIiwgIklsMTIiLCAiSWwxNSIsICJJbDE4IiwgIklsMjIiLCAiSWwyNyIsICJJbDMzIiwgIkN4Y2wxIiwgIkN4Y2wyIiwgIkN4Y2wzIiwgIkN4Y2w0IiwgIkN4Y2w1IiwgIkN4Y2w5IiwgIkN4Y2wxMCIsICJDeGNsMTEiLCAiQ3hjbDEyIiwgIkN4Y2wxMyIsICJDeGNsMTYiLCAiQ2NsMSIsICJDY2wyIiwgIkNjbDMiLCAiQ2NsNCIsICJDY2w1IiwgIkNjbDYiLCAiQ2NsNyIsICJDY2w4IiwgIkNjbDkiLCAiQ2NsMTAiLCAiQ2NsMTEiLCAiQ2NsMTIiLCAiQ2NsMTciLCAiQ2NsMTkiLCAiQ2NsMjAiLCAiQ2NsMjEiLCAiQ2NsMjIiLCAiQ2NsMjUiLCAiQ2NsMjciLCAiQ2NsMjgiKQ0KZ2VuZXNQcm90ZWluVmFsaWRhdGlvbiA8LSBjKCJJdGdhMiIsICJJdGdhbSIsICJUaHkxIiwgIlRoeTEuMiIsICJLbHJiMWMiLCAiTmtycDFjIiwgIktpdCIsICJUYngyMSIsICJFb21lcyIsICJGb3hvMSIsICJOY3IxIiwgIk5jciIsICJDeGNyMyIsICJDeDNjcjEiLCAiVG94IiwgIktscmcxIiwgIlNlbGwiLCAiSGF2Y3IyIiwgIklsN3IiLCAiSWNvcyIsICJUY2Y3IiwgIklsMThyMSIsICJDZDIyNiIsICJDZDM4IiwgIkxhZzMiKQ0KDQoNCnBsb3RfZ2VuZXNfaGVhdG1hcCA8LSBmdW5jdGlvbihyZXNBLCBleHByZXNzaW9uX21hdCwgZGRzX21ldGExLCBrZWVwX2dlbmVzLCBrZWVwX2dyb3VwcyA9IGMoIk5DUiIsICJGT1hPMUtPIiwgIkRLTyIsICJHRkkxS08iKSwgcGFkal9jdXRvZmYgPSAwLjA1LCBsb2cyRm9sZENoYW5nZV9jdXRvZmYgPSAxLjEsIGJhc2VNZWFuX2N1dG9mZiA9IDIwLCAuLi4pIHsNCiAgcmVzQSRzaWduaWZpY2FudCA8LSBpZmVsc2UocmVzQSRwYWRqIDwgcGFkal9jdXRvZmYgJiBhYnMocmVzQSRsb2cyRm9sZENoYW5nZSkgPj0gbG9nMkZvbGRDaGFuZ2VfY3V0b2ZmICYgcmVzQSRiYXNlTWVhbiA+PSBiYXNlTWVhbl9jdXRvZmYgJiAhaXMubmEocmVzQSRzeW1ib2wpLCAieWVzIiwgIm5vIikNCiAgZGYxIDwtIGRhdGEuZnJhbWUoZXhwcmVzc2lvbl9tYXQsICJSb3cubmFtZXMiID0gcm93Lm5hbWVzKGV4cHJlc3Npb25fbWF0KSkNCiAgZGYyIDwtIGRhdGEuZnJhbWUoIlJvdy5uYW1lcyIgPSByZXNBJFJvdy5uYW1lcywgInNpZ25pZmljYW50IiA9IHJlc0Ekc2lnbmlmaWNhbnQsICJnZW5lcyIgPSByZXNBJHN5bWJvbCkNCiAgbWF0IDwtIGRwbHlyOjpmdWxsX2pvaW4oZGYxLCBkZjIsIGJ5ID0gIlJvdy5uYW1lcyIpICAjZGYzLCBkZjQsDQogIG1hdCA8LSBtYXRbLCAtd2hpY2goY29sbmFtZXMobWF0KSA9PSAiUm93Lm5hbWVzIildDQogIG1hdCA8LSBtYXQgJT4lIGZpbHRlcihnZW5lcyAlaW4lIGtlZXBfZ2VuZXMpDQogIHJvdy5uYW1lcyhtYXQpIDwtIG1hdFssIG5jb2wobWF0KV0NCiAgbWF0IDwtIG1hdFssIC1uY29sKG1hdCldDQogIG1hdCA8LSBtYXRbcm93U3VtcyhtYXRbLCAtbmNvbChtYXQpXSkgPiAwLCBdDQogIHJvd19hbm5vIDwtIG1hdFssICJzaWduaWZpY2FudCIsIGRyb3AgPSBGXQ0KICBtYXQgPC0gbWF0WywgZGRzX21ldGExICU+JSBmaWx0ZXIoZ2Vub3R5cGUgJWluJSBrZWVwX2dyb3VwcykgJT4lIGRwbHlyOjpzZWxlY3QoR2VuZWlkKSAlPiUgdW5saXN0KCkgJT4lIGFzLmNoYXJhY3RlcigpXQ0KICBjb2xfYW5ubyA8LSBkZHNfbWV0YTEgJT4lDQogICAgZmlsdGVyKGdlbm90eXBlICVpbiUga2VlcF9ncm91cHMpICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoZ2Vub3R5cGUpDQogIHJvdy5uYW1lcyhjb2xfYW5ubykgPC0gZGRzX21ldGExICU+JQ0KICAgIGZpbHRlcihnZW5vdHlwZSAlaW4lIGtlZXBfZ3JvdXBzKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KEdlbmVpZCkgJT4lDQogICAgdW5saXN0KCkgJT4lDQogICAgYXMuY2hhcmFjdGVyKCkNCiAgDQogIGdlbm90eXBlX2NvbG9ycyA8LSBsaXN0KCJnZW5vdHlwZSIgPSBjKCJOQ1IiID0gImdyZXk2NSIsICJGT1hPMUtPIiA9ICJnb2xkZW5yb2QxIiwgIkdGSTFLTyIgPSAiaW5kaWFucmVkMSIsICJES08iID0gInNsYXRlYmx1ZTEiKSkNCiAgc2lnX2NvbCA8LSBsaXN0KCJzaWduaWZpY2FudCIgPSBjKCJ5ZXMiID0gIiNlMTUxNzkiLCAibm8iID0gIiNlN2U3ZTciKSkNCiAgcGhlYXRtYXAobWF0LA0KICAgICAgICAgICBhbm5vdGF0aW9uX2NvbG9ycyA9IGMoZ2Vub3R5cGVfY29sb3JzLCBzaWdfY29sKSwNCiAgICAgICAgICAgYW5ub3RhdGlvbl9jb2wgPSBjb2xfYW5ubywNCiAgICAgICAgICAgYW5ub3RhdGlvbl9yb3cgPSByb3dfYW5ubywNCiAgICAgICAgICAgLi4uDQogICkNCn0NCg0KcGxvdF9nZW5lc19oZWF0bWFwKHJlc0EsIGFzc2F5KHJsZCksIGRkc19tZXRhMSwgZ2VuZXNQcm90ZWluVmFsaWRhdGlvbiwga2VlcF9ncm91cHMgPSBjKCJOQ1IiLCAiRk9YTzFLTyIsICJES08iLCAiR0ZJMUtPIiksDQogICAgICAgICAgICAgICAgICAgc2hvd19yb3duYW1lcyA9IFQsDQogICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2xzID0gVCwNCiAgICAgICAgICAgICAgICAgICBzaG93X2NvbG5hbWVzID0gRiwNCiAgICAgICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3MgPSBULA0KICAgICAgICAgICAgICAgICAgIHNjYWxlPSJyb3ciLA0KICAgICAgICAgICAgICAgICAgICNib3JkZXJfY29sb3IgPSBOQSwNCiAgICAgICAgICAgICAgICAgICB0cmVlaGVpZ2h0X3JvdyA9IDEwLA0KICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJpbmdfZGlzdGFuY2Vfcm93cyA9ICJjb3JyZWxhdGlvbiIsDQogICAgICAgICAgICAgICAgICAgY29sb3IgPSBid3JfOTkpDQogDQpgYGANCg0KYGBge3J9DQojI1ZFTk4gZGlhZ3JhbSBERUcNCg0Kc2V0MSA8LSByZXNBU2lnJHN5bWJvbA0Kc2V0MiA8LSByZXNCU2lnJHN5bWJvbA0Kc2V0MyA8LSByZXNDU2lnJHN5bWJvbA0KY29sb3JzIDwtIGMoInNsYXRlYmx1ZTEiLCAiZ29sZGVucm9kMSIsICJpbmRpYW5yZWQxIikNCg0Kc2V0MTwtbmEub21pdChzZXQxKQ0Kc2V0MjwtbmEub21pdChzZXQyKQ0Kc2V0MzwtbmEub21pdChzZXQzKQ0KDQp2ZW5uLmRpYWdyYW0oDQogIHggPSBsaXN0KHNldDEsIHNldDIsIHNldDMpLA0KICBjYXRlZ29yeS5uYW1lcyA9IGMoIkRLTyIsICJGT1hPMUtPIiwgIkdGSTFLTyIpLA0KICBmaWxlbmFtZSA9ICdERUcgTTEgVmVubkRpYWdyYW0ucG5nJywNCiAgb3V0cHV0ID0gVFJVRSwNCiAgaW1hZ2V0eXBlID0gInBuZyIsDQogIHNjYWxlZCA9IEZBTFNFLA0KICBjb2wgPSAiYmxhY2siLA0KICBmaWxsID0gY29sb3JzLA0KICBjYXQuY29sID0gY29sb3JzLA0KICBjYXQuY2V4ID0gMS41LCAgICMgQWRqdXN0IHRoZSBmb250IHNpemUgdG8gbWFrZSB0aGUgbGFiZWxzIHNtYWxsZXINCiAgY2F0LnBvcyA9IDAsICAgICAjIE1vdmUgdGhlIGxhYmVscyBvdXRzaWRlIHRoZSBjaXJjbGVzDQogIGNhdC5kaXN0ID0gYygwLjA1LCAwLjA1LCAtMC40NSksICAjIEFkanVzdCB0aGUgZGlzdGFuY2UgZm9yIGVhY2ggY2F0ZWdvcnkgbGFiZWwgaW5kaXZpZHVhbGx5DQogIG1hcmdpbiA9IDAuMTUNCikNCmBgYA0KDQpgYGB7cn0NCiNHTyBCUCBhbmFseXNpcyANCg0KI0JQDQpvcmRlclNpZ3Jlc0FfR09fVVAgPC0gcmVzQVNpZyAlPiUgZmlsdGVyKHBhZGogPCAwLjA1ICYgKGxvZzJGb2xkQ2hhbmdlKSA+PSAxLjEgJiBiYXNlTWVhbiA+PSAyMCAmICFpcy5uYShzeW1ib2wpKQ0Kb3JkZXJTaWdyZXNBX0dPX0RPV04gPC0gcmVzQVNpZyAlPiUgZmlsdGVyKHBhZGogPCAwLjA1ICYgKGxvZzJGb2xkQ2hhbmdlKSA8PSAtMS4xICYgYmFzZU1lYW4gPj0gMjAgJiAhaXMubmEoc3ltYm9sKSkNCg0KDQplZ29CUF9VUHJlc0EgPC0gZW5yaWNoR08oZ2VuZSAgICAgICAgID0gb3JkZXJTaWdyZXNBX0dPX1VQJGVudHJleiwNCiAgICAgICAgICAgICAgICAgT3JnRGIgICAgICAgICA9IG9yZy5NbS5lZy5kYiwNCiAgICAgICAgICAgICAgICAga2V5VHlwZSAgICAgICA9ICdFTlRSRVpJRCcsDQogICAgICAgICAgICAgICAgIG9udCAgICAgICAgICAgPSAiQlAiLA0KICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwNCiAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmICA9IDAuMDUsDQogICAgICAgICAgICAgICAgICkNCmhlYWQoZWdvQlBfVVByZXNBKQ0KZG90cGxvdChlZ29CUF9VUHJlc0EsIHNob3dDYXRlZ29yeSA9IDE1KQ0KDQplZ29CUF9ET1dOcmVzQSA8LSBlbnJpY2hHTyhnZW5lICAgICAgICAgPSBvcmRlclNpZ3Jlc0FfR09fRE9XTiRlbnRyZXosDQogICAgICAgICAgICAgICAgICAgICBPcmdEYiAgICAgICAgID0gb3JnLk1tLmVnLmRiLA0KICAgICAgICAgICAgICAgICAgICAga2V5VHlwZSAgICAgICA9ICdFTlRSRVpJRCcsDQogICAgICAgICAgICAgICAgICAgICBvbnQgICAgICAgICAgID0gIkJQIiwNCiAgICAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLA0KICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmICA9IDAuMDUsDQopDQpoZWFkKGVnb0JQX0RPV05yZXNBKQ0KZG90cGxvdChlZ29CUF9ET1dOcmVzQSwgc2hvd0NhdGVnb3J5ID0gMTUpDQoNCndyaXRlLmNzdihlZ29CUF9VUHJlc0EsICJNMV9OQ1JfdnNfREtPX0dPQlB1cC5jc3YiKQ0Kd3JpdGUuY3N2KGVnb0JQX0RPV05yZXNBLCAiTTFfTkNSX3ZzX0RLT19HT0JQZG93bi5jc3YiKQ0KYGBgDQoNCg0KYGBge3J9DQojS0VHRyBwYXRod2F5IGFuYWx5c2lzDQoNCm9yZGVyU2lncmVzQV9HT19VUCA8LSByZXNBU2lnICU+JSBmaWx0ZXIocGFkaiA8IDAuMDUgJiAobG9nMkZvbGRDaGFuZ2UpID49IDEuMSAmIGJhc2VNZWFuID49IDIwICYgIWlzLm5hKHN5bWJvbCkpDQoNCktFR0d1cCA8LSBlbnJpY2hLRUdHKGdlbmUgICAgICAgICA9IG9yZGVyU2lncmVzQV9HT19VUCRlbnRyZXosDQogICAgICAgICAgICAgICAgIG9yZ2FuaXNtICAgICA9ICdtbXUnLA0KICAgICAgICAgICAgICAgICBrZXlUeXBlID0gIm5jYmktZ2VuZWlkIiwNCiAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMSwNCiAgICAgICAgICAgICAgICAgcXZhbHVlQ3V0b2ZmID0gMSkNCmRvdHBsb3QoS0VHR3VwLCBzaG93Q2F0ZWdvcnkgPSAxMCkNCg0KDQoNCm9yZGVyU2lncmVzQV9HT19ET1dOIDwtIHJlc0FTaWcgJT4lIGZpbHRlcihwYWRqIDwgMC4wNSAmIChsb2cyRm9sZENoYW5nZSkgPD0gLTEuMSAmIGJhc2VNZWFuID49IDIwICYgIWlzLm5hKHN5bWJvbCkpDQoNCktFR0dkb3duIDwtIGVucmljaEtFR0coZ2VuZSAgICAgICAgID0gb3JkZXJTaWdyZXNBX0dPX0RPV04kZW50cmV6LA0KICAgICAgICAgICAgICAgICBvcmdhbmlzbSAgICAgPSAnbW11JywNCiAgICAgICAgICAgICAgICAga2V5VHlwZSA9ICJuY2JpLWdlbmVpZCIsDQogICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDEsDQogICAgICAgICAgICAgICAgIHF2YWx1ZUN1dG9mZiA9IDEpDQpkb3RwbG90KEtFR0dkb3duLCBzaG93Q2F0ZWdvcnkgPSAxMCkNCg0Kd3JpdGUuY3N2KEtFR0d1cCwgIk0xX05DUl92c19ES09fS0VHR3VwLmNzdiIpDQp3cml0ZS5jc3YoS0VHR2Rvd24sICJNMV9OQ1JfdnNfREtPX0tFR0dkb3duLmNzdiIpDQpgYGANCg0KYGBge3J9DQojR1NFQQ0KDQojY2hhbmdlIGxvZzJmb2xkY2hhbmdlIHRvIG5lZ2F0aXZlIHZhbHVlcyB0byBzZWUgdW5kZXJleHByZXNzaW9uPw0KI0RLTw0KdG1wIDwtIHJlc0FbIWlzLm5hKHJlc0Ekc3ltYm9sKSwgXQ0KdG1wIDwtIHRtcFtvcmRlcih0bXAkc3RhdCwgZGVjcmVhc2luZyA9IFQpLCBdDQp0ZXN0Z2VuZXMgPC0gdG1wJHN0YXQNCm5hbWVzKHRlc3RnZW5lcykgPC0gdG1wJHN5bWJvbA0KdGVzdGdlbmVzIDwtIHRlc3RnZW5lc1shaXMubmEodGVzdGdlbmVzKV0NCg0KZ2VuZV9zZXRzIDwtIG1zaWdkYnIoc3BlY2llcyA9ICJtb3VzZSIsIGNhdGVnb3J5ID0gIkgiKQ0KDQpnZW5lX3NldHMgPC0gZ2VuZV9zZXRzICU+JQ0KICBkcGx5cjo6c2VsZWN0KGdzX25hbWUsIGdlbmVfc3ltYm9sKQ0KDQpnc2VhcmVzQSA8LSBHU0VBKGdlbmVMaXN0ID0gdGVzdGdlbmVzLA0KICAgICAgICAgICAgICAgIFRFUk0yR0VORSA9IGdlbmVfc2V0cykNCg0KZG90cGxvdChnc2VhcmVzQSkNCg0KVmlldyhnc2VhcmVzQSkNCmRmZ3NlYXJlc0EgPC0gYXMuZGF0YS5mcmFtZShnc2VhcmVzQSkNCg0KDQoNCiNhdHRlbXB0aW5nIHRvIG92ZXJsYXAgZGZnc2VhcmVzQS9CL0MNCg0KIyBzdHIoZGZnc2VhcmVzQSkNCiMgc3RyKGRmZ3NlYXJlc0IpDQojIHN0cihkZmdzZWFyZXNDKQ0KIyANCiMgY2VsbHR5cGVzID0gYygnSW1tJywgJ00xJywgJ00yJykNCiMgZ3JvdXBzID0gYygiTkNSIiwgIkZPWE8xS08iLCAiR0ZJMUtPIiwgIkRLTyIpDQoNCg0KDQojYWRkaW5nIGEgc2NvcmUgZm9yIEdTRUENCnJlc2RmMiA8LSByZXNBICU+JQ0KICBhcnJhbmdlKHBhZGopICU+JQ0KICBtdXRhdGUoZ3NlYV9tZXRyaWMgPSAtbG9nMTAocGFkaikgKiBzaWduKGxvZzJGb2xkQ2hhbmdlKSkNCg0KcmVzZGYyIDwtIHJlc2RmMiAlPiUNCiAgbXV0YXRlKHBhZGogPSBjYXNlX3doZW4ocGFkaiA9PSAwIH4gLk1hY2hpbmUkZG91YmxlLnhtaW4sDQogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBwYWRqKSkgJT4lDQogIG11dGF0ZShnc2VhX21ldHJpYyA9IC1sb2cxMChwYWRqKSAqIHNpZ24obG9nMkZvbGRDaGFuZ2UpKQ0KcmVzZGYyDQoNCnJlc2RmMiA8LSByZXNkZjIgJT4lDQogIGZpbHRlcighIGlzLm5hKGdzZWFfbWV0cmljKSkgJT4lDQogIGFycmFuZ2UoZGVzYyhnc2VhX21ldHJpYykpDQpWaWV3KHJlc2RmMikNCg0KaGlzdChyZXNkZjIkZ3NlYV9tZXRyaWMsIGJyZWFrcyA9IDEwMCkNCg0KcmFua3MgPC0gcmVzZGYyICU+JQ0KICBzZWxlY3Qoc3ltYm9sLCBnc2VhX21ldHJpYykgJT4lDQogIGRpc3RpbmN0KHN5bWJvbCwgLmtlZXBfYWxsID0gVFJVRSkgJT4lDQogIGRlZnJhbWUoKQ0KDQpoZWFkKHJhbmtzKQ0KDQpnc2VhcmVzIDwtIEdTRUEoZ2VuZUxpc3QgPSByYW5rcywNCiAgICAgICAgICAgICAgICBURVJNMkdFTkUgPSBnZW5lX3NldHMpDQpnc2VhcmVzZGYgPC0gYXMuZGF0YS5mcmFtZShnc2VhcmVzKQ0KDQpkb3RwbG90KGdzZWFyZXMpDQoNClZpZXcoZ3NlYXJlc2RmKQ0KIA0KYGBgDQpgYGB7cn0NCiMgIyBjb21wYXJlZCB0byBXdCwgaG93IGRvZXMgS08gY2hhbmdlIGluIGNvbmRpdGlvbg0KIyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMgWW91IGhlbHBlZCB3cml0ZSB0aGlzIGluaXRpYWwgY29kZSAyIG1vbnRocyBhZ28gLSBJIGhhdmVuJ3QgZnVsbHkgdGhvdWdodCB0aHJvdWdoIGhvdyBJIHdvdWxkIHByZXNlbnQgZGF0YSB0aGF0IGxvb2sgYXQgSU1NIHZzIE0xIHZzIE0yIGluIGVhY2ggS08gLSBtYXliZSB0aGlzIGNvbXBhcmlzb24gY291bGQgYmUgdXNlZnVsIGZvciBsb29raW5nIGF0IGhvdyBwYXRod2F5cyBvciBrZXkgdHJhbnNjcmlwdGlvbiBmYWN0b3JzIGNoYW5nZSBhcyB0aGUgY2VsbHMgZGV2ZWxvcCBmcm9tIElNTSBpbnRvIE0xIGludG8gTTINCg0KIyAjIEZPWE8xS08gdnMgV1QgYW5kIEltbSB2cyBNMQ0KIyBkZHNfbWV0YTEgPC0gbWV0YURhdGFUT1RBTCAlPiUgZmlsdGVyKChnZW5vdHlwZSAlaW4lIGMoIk5DUiIsICJGT1hPMUtPIikpICYgKGNvbmRpdGlvbiAlaW4lIGMoIkltbSIsICJNMSIpKSkNCiMgZGRzXzEgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGE9Y291bnREYXRhVE9UQUxbLHdoaWNoKGNvbG5hbWVzKGNvdW50RGF0YVRPVEFMKSAlaW4lIGRkc19tZXRhMSRHZW5laWQpXSwgZGRzX21ldGExLCBkZXNpZ249IH4gMCArIGNvbmRpdGlvbiArIGdlbm90eXBlICsgZ2Vub3R5cGU6Y29uZGl0aW9uKQ0KIyBkZHNfMSA8LSBkZHNfMVtyb3dTdW1zKGNvdW50cyhkZHNfMSkpID4gNSwgXQ0KIyBkZHNfMSA8LSBERVNlcShkZHNfMSkNCiMgDQojIHJlc3VsdHNOYW1lcyhkZHNfMSkNCiMgcmVzQSA8LSByZXN1bHRzKGRkc18xLCBuYW1lID0gJ2NvbmRpdGlvbk0xLmdlbm90eXBlRk9YTzFLTycpDQojIA0KIyBnZXRfbGZjX3NpZ24gPC0gZnVuY3Rpb24oZGYsIHRociA9IDEpew0KIyAgIGRmJGxmY190aHIgPC0gMA0KIyAgIGRmJGxmY190aHJbd2hpY2goZGYkbG9nMkZvbGRDaGFuZ2UgPj0gdGhyKV0gPC0gMQ0KIyAgIGRmJGxmY190aHJbd2hpY2goZGYkbG9nMkZvbGRDaGFuZ2UgPD0gKC0xICogdGhyKSldIDwtIC0xDQojICAgcmV0dXJuKGRmKQ0KIyB9DQojIA0KIyByZXNBIDwtIGdldF9sZmNfc2lnbihyZXNBLCB0aHI9MSkNCiMgDQojIHJlc0EgPC0gcmVzQVtvcmRlcihyZXNBJHB2YWx1ZSwgZGVjcmVhc2luZz1GQUxTRSksIF0NCiMgDQojIHRhYmxlKHJlc0EkcGFkaiA8IDAuMDUsIHJlc0EkbGZjX3RocikNCiMgDQojIHdyaXRlLmNzdihyZXNBLCAiZmlsZW5hbWVzLmNzdiIpDQpgYGANCg0KDQpBZGQgYSBuZXcgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpJbnNlcnQgQ2h1bmsqIGJ1dHRvbiBvbiB0aGUgdG9vbGJhciBvciBieSBwcmVzc2luZyAqQ3RybCtBbHQrSSouDQoNCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLg0KDQpUaGUgcHJldmlldyBzaG93cyB5b3UgYSByZW5kZXJlZCBIVE1MIGNvcHkgb2YgdGhlIGNvbnRlbnRzIG9mIHRoZSBlZGl0b3IuIENvbnNlcXVlbnRseSwgdW5saWtlICpLbml0KiwgKlByZXZpZXcqIGRvZXMgbm90IHJ1biBhbnkgUiBjb2RlIGNodW5rcy4gSW5zdGVhZCwgdGhlIG91dHB1dCBvZiB0aGUgY2h1bmsgd2hlbiBpdCB3YXMgbGFzdCBydW4gaW4gdGhlIGVkaXRvciBpcyBkaXNwbGF5ZWQuDQo=