1 Data retrival

library(dplyr)
library(minfi)
cohort <- "GASPARONI"
data.dir <- file.path("DATASETS/",cohort,"/") 
data.dir.table <- "DATASETS/Summary_Table/" 
data.dir.raw <- file.path(data.dir,"/step1_download/") 
data.dir.read <- file.path(data.dir,"/step2_read_minfi/") 
data.dir.bsfilter <- file.path(data.dir,"/step3_bsConvFilter/") 
data.dir.clinical.filter <- file.path(data.dir,"/step4_clinical_available_filtering/") 
data.dir.probes.qc <- file.path(data.dir,"/step5_probesQC_filtering/") 
data.dir.probes.normalization <- file.path(data.dir,"/step6_normalization/") 
data.dir.pca <- file.path(data.dir,"/step7_pca_filtering/") 
data.dir.neuron <- file.path(data.dir,"/step8_neuron_comp/") 
data.dir.single.cpg.pval <- file.path(data.dir,"/step9_single_cpg_pval/") 
data.dir.residuals <- file.path(data.dir,"/step10_residuals/") 
data.dir.median <- file.path(data.dir,"/step11_median/") 
for(p in grep("dir",ls(),value = T)) dir.create(get(p),recursive = TRUE,showWarnings = FALSE)

Required R libraries: GEOquery can be installed as following:

if (!requireNamespace("BiocManager", quietly = TRUE))
  install.packages("BiocManager")

BiocManager::install("GEOquery")

Data from: https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE66351

library(GEOquery)
library(SummarizedExperiment)
test <- getGEO(GEO = "GSE66351",destdir = data.dir.raw)
se <- test$GSE66351_series_matrix.txt.gz %>% makeSummarizedExperimentFromExpressionSet()
se <- se[,se$source_name_ch1  == "Frontal Cortex" &
           se$characteristics_ch1 == "cell type: bulk" &
           se$braak_stage.ch1 != "NA"]

We will download Idat files for all our samples

files <- c(se$supplementary_file %>% as.character(),
           se$supplementary_file.1 %>% as.character())
dir.create(data.dir.raw,showWarnings = FALSE,recursive = TRUE)
plyr::a_ply(files,.margins = 1,.fun = function(url){
  out.file <- file.path(data.dir.raw,basename(url))
  if(!file.exists(out.file)) downloader::download(url,out.file)
  gunzip(out.file)
},.progress = "time")

2 Data Pre-processing

Description:

  • Read in idat files and remove duplicated samples

Input:

  • idat files

Output:

  • RGSet.RDS
  • phenoData
  • BetaMatrixRaw
RGSet <- read.metharray.exp(base = data.dir.raw,
                            recursive = TRUE,
                            verbose = TRUE) #dim: 622399 60
phenoData <- colData(se)
save(RGSet,phenoData, file = paste0(data.dir.read, "Gasparoni.rda")) 

3 Data QC

3.1 Bilsufite conversion filtering

Removing samples with bisulfiteConversion lower than 88.

library(wateRmelon)
library(RPMM)
#library(sesame)
#library(sesameData)
load(file = paste0(data.dir.read, "Gasparoni.rda"))
bs <- data.frame(bisulfiteConversion = bscon(RGSet))
## Loading required package: IlluminaHumanMethylation450kmanifest
bsFilteredOut <- row.names(bs)[bs$bisulfiteConversion < 88]
nb.samples <- ncol(RGSet)
RGSet <- RGSet[,!colnames(RGSet) %in% bsFilteredOut]
nb.samples.bc.filtered <-  ncol(RGSet)
phenoData <- phenoData[match(substr(colnames(RGSet),1,10), phenoData$geo_accession),]
save(RGSet,
     nb.samples,
     bs,
     phenoData,
     nb.samples.bc.filtered, 
     file = paste0(data.dir.bsfilter, "/RGSet_bsfiltered.rda"))

3.2 Clinical data filtering

dim(phenoData)
## [1] 57 49
phenoData$braak_stage.ch1 <- phenoData$braak_stage.ch1 %>% as.numeric()
phenoData$age.ch1 <- phenoData$age.ch1 %>% as.numeric()
### Subset rows and columns
pheno_df <- phenoData  %>% as.data.frame() %>%
  dplyr::filter(
    source_name_ch1 == "Frontal Cortex" &
      !is.na(phenoData$braak_stage.ch1) &
      phenoData$characteristics_ch1 == "cell type: bulk"
  ) %>% dplyr::select(
    c(
      "geo_accession",
      "donor_id.ch1",
      "sentrix_id.ch1",
      "age.ch1",
      "Sex.ch1",
      "braak_stage.ch1"
    )
  )

### Rename vars
colnames(pheno_df) <- c(
  "sample", "subject.id", "slide", "age.brain", "sex", "stage"
)

dim(pheno_df) 
## [1] 57  6
nb.samples.with.clinical <- nrow(pheno_df)
## phenotype dataset
save(RGSet,
     nb.samples.with.clinical,
     pheno_df,
     file = paste0(data.dir.clinical.filter, "/gasparoni_bs_and_clinical_filtered.rda"))

3.3 Probes QC

Input:

  • RGSet.RDS
  • beta_mat.RDS

Output:

  • beta_CG_XY_SNPfiltered.RDS
##### 1. subset to probes with detection P <= 0.01 #############################
### Read in RGSet and beta_mat
load(paste0(data.dir.clinical.filter, "/gasparoni_bs_and_clinical_filtered.rda"))
### subset to probes with detection P <= 0.01
library(minfi)
beta_mat <- getBeta(RGSet) 
nb.probes <- nrow(beta_mat)
detP <- detectionP(RGSet, type = "m+u")
failed.01 <- detP > 0.01
passedProbes <- rownames(failed.01)[rowMeans(failed.01) == 0] 


beta_mat <- beta_mat[passedProbes, ]
nb.probes.detectP <- nrow(beta_mat)

##### 2. keep only probes that start with "cg" #################################
beta_mat <- beta_mat[grep("cg",rownames(beta_mat)),]
dim(beta_mat) 
## [1] 475979     57
nb.probes.detectP.cg <- nrow(beta_mat)

##### 3. drop probes that are on X/Y ###########################################
##### 4. drop probes where SNP with MAF >= 0.01 in the last 5 bp of the probe ##
library(DMRcate)
beta_mat <- rmSNPandCH(
  object = beta_mat,
  dist = 5, 
  mafcut = 0.01, 
  and = TRUE,
  rmcrosshyb = FALSE,
  rmXY = TRUE
) 
nb.probes.cg.dmrcate <- nrow(beta_mat)

##### 5. Output datasets #######################################################
save(
  pheno_df,
  nb.probes.detectP,
  nb.probes.detectP.cg,
  nb.probes.cg.dmrcate,
  beta_mat,
  file = paste0(data.dir.probes.qc, "beta_CG_XY_SNPfiltered_mat.rda")
)

4 Normalization

  • Quantile normalization and BMIQ normalization

Input:

  • beta_CG_XY_SNPfiltered_mat.RDS
  • RGSet.RDS
  • pheno_df.RDS
  • full.annot.RDS

Output:

  • bs.csv
  • pheno_df.RDS
  • QNBMIQ.RDS
load(paste0(data.dir.probes.qc, "beta_CG_XY_SNPfiltered_mat.rda"))

4.1 Quantile normalization

library(lumi)
betaQN <- lumiN(x.lumi = beta_mat, method = "quantile")
## Perform quantile normalization ...
dim(betaQN)
## [1] 446792     57

4.2 BMIQ

library(wateRmelon)
library(RPMM)
library(sesame)
library(sesameData)
### BMIQ
set.seed (946)
doParallel::registerDoParallel(cores = 8)
betaQN_BMIQ <- plyr::aaply(
  betaQN, 2,
  function(x){
    norm_ls <- BMIQ(x, design.v = type12, plots = FALSE)
    return (norm_ls$nbeta)
  },.progress = "time",.parallel = TRUE
) %>% t()
colnames(betaQN_BMIQ) <- substr(colnames(betaQN_BMIQ),1,stringr::str_length(pheno_df$sample) %>% unique)

save(betaQN_BMIQ, pheno_df, file = paste0(data.dir.probes.normalization, "GASPARONI_QNBMIQ.rda"))

5 Outliers detection - PCA analysis

  • Select most variable probes and perform PCA analysis

Input:

  • GASPARONI_QNBMIQ.rds
  • pheno_df.RDS

Output:

  • GASPARONI_PCs_usingBetas.csv,
  • PCA plots
  • GASPARONI_QNBMIQ_PCfiltered.RDS
  • pheno_df.RDS
# plotPCA and OrderDataBySd functions
devtools::source_gist("https://gist.github.com/tiagochst/d3a7b1639acf603916c315d23b1efb3e")
## Sourcing https://gist.githubusercontent.com/tiagochst/d3a7b1639acf603916c315d23b1efb3e/raw/a14424662da343c1301b7b2f03210d28d16ae05c/functions.R
## SHA-1 hash of file is ef6f39dc4e5eddb5ca1c6e5af321e75ff06e9362
### merge in group info
## add center and scale
## compare M values vs. beta values
## with and without center / scale

##### 0.Import datasets ########################################################
load(paste0(data.dir.probes.normalization, "GASPARONI_QNBMIQ.rda"))
identical(colnames(betaQN_BMIQ), pheno_df$sample)
## [1] TRUE
### transform to m values
mvalue_mat <- log2(betaQN_BMIQ / (1 - betaQN_BMIQ)) #dim: 437713 142

pheno_df <- subset(pheno_df, pheno_df$sample %in% colnames(betaQN_BMIQ)) #dim: 142 7

# both_df$stage <- as.numeric(as.character(both_df$stage))

pheno_df$stage3 <- pheno_df$stage
pheno_df$stage3[pheno_df$stage <= 2] <- '0-2'
pheno_df$stage3[pheno_df$stage > 2 & pheno_df$stage < 5] <- '3-4'
pheno_df$stage3[pheno_df$stage >= 5] <- '5-6'


##### 1.Order matrix by most variable probes on top ############################

betaOrd_mat <- OrderDataBySd(betaQN_BMIQ) #dim: 391482 142

mOrd_mat <- OrderDataBySd(mvalue_mat)  #dim: 391482 142

betaOrd_matPlot <- betaOrd_mat[, pheno_df$sample] #dim: 391482 142
mOrd_matPlot <- mOrd_mat[, pheno_df$sample]       #dim: 391482 142
identical(pheno_df$sample, colnames(betaOrd_matPlot))
## [1] TRUE
identical(pheno_df$sample, colnames(mOrd_matPlot))
## [1] TRUE
expSorted_mat = betaOrd_mat #dim: 391482 142

pca <- prcomp(t(expSorted_mat[1:50000, ]),
              center = TRUE,
              scale = TRUE)

d <- data.frame(PC1 = pca$x[, 1], PC2 = pca$x[, 2])

meanPC1 <- mean (d$PC1)
sdPC1   <- sd (d$PC1)

meanPC2 <- mean (d$PC2)
sdPC2   <- sd (d$PC2)

out3sdPC1_1 <- meanPC1 - 3 * sdPC1
out3sdPC1_2 <- meanPC1 + 3 * sdPC1

out3sdPC2_1 <- meanPC2 - 3 * sdPC2
out3sdPC2_2 <- meanPC2 + 3 * sdPC2

d$outlier_PC1[d$PC1 >= out3sdPC1_1 & d$PC1 <= out3sdPC1_2] <- 0
d$outlier_PC1[d$PC1 < out3sdPC1_1 | d$PC1 > out3sdPC1_2] <- 1

d$outlier_PC2[d$PC2 >= out3sdPC2_1 & d$PC2 <= out3sdPC2_2] <- 0
d$outlier_PC2[d$PC2 < out3sdPC2_1 | d$PC2 > out3sdPC2_2] <- 1

readr::write_csv(d, paste0(data.dir.pca, "GASPARONI_PCs_usingBetas.csv"))
##### 2.Filter samples by PCA, save files ######################################

noOutliers <- d[which(d$outlier_PC1 == 0 & d$outlier_PC2 == 0), ]
betaQN_BMIQ_PCfiltered <- betaQN_BMIQ[, rownames(noOutliers)] #dim: 433656 59
saveRDS(betaQN_BMIQ_PCfiltered, paste0(data.dir.pca, "Gasparoni_QNBMIQ_PCfiltered.RDS"))

pheno_df <- pheno_df[pheno_df$sample %in% rownames(noOutliers),] #dim: 59 6
saveRDS(pheno_df, paste0(data.dir.pca, "pheno_df.RDS"))

6 Summary after QC steps

6.1 Data and metadata

nb.samples.with.clinical.after.pca <- ncol(betaQN_BMIQ_PCfiltered)
dim(betaQN_BMIQ_PCfiltered)
## [1] 446792     56
dim(pheno_df)
## [1] 56  7
pheno_df %>% 
  DT::datatable(filter = 'top',
                style = "bootstrap",
                extensions = 'Buttons',
                options = list(scrollX = TRUE, 
                               dom = 'Bfrtip',
                               buttons = I('colvis'),
                               keys = TRUE, 
                               pageLength = 10), 
                rownames = FALSE,
                caption = "Samples metadata")

6.2 Numbers of samples and probes removed in each step

df.samples <- data.frame("Number of samples" =  c(nb.samples, 
                                                  nb.samples.bc.filtered,
                                                  nb.samples.with.clinical, 
                                                  nb.samples.with.clinical.after.pca),
                         "Description" = c("total number of samples",
                                           "samples with bisulfate conversion > 88",
                                           "samples with clinical data",
                                           "Samples after PCA"),
                         "Difference" = c("-",
                                          nb.samples.bc.filtered - nb.samples ,
                                          nb.samples.with.clinical - nb.samples.bc.filtered ,
                                          nb.samples.with.clinical.after.pca - nb.samples.with.clinical)
)    
df.samples           
# Create summary table
df.probes <- data.frame("Number of probes" = c(nb.probes,
                                               nb.probes.detectP, 
                                               nb.probes.detectP.cg,
                                               nb.probes.cg.dmrcate),
                        "Description" = c("total number of probes in raw data",
                                          "detection P < 0.01",
                                          "only probes that start with cg",
                                          "DMRcate"),
                        "Difference" = c("-",
                                         nb.probes.detectP - nb.probes ,
                                         nb.probes.detectP.cg - nb.probes.detectP,
                                         nb.probes.cg.dmrcate - nb.probes.detectP.cg)
)
df.probes
save(df.samples,df.probes,file = file.path(data.dir.table, "GASPARONI_table.rda"))

7 Compute neuron proportion

Data from https://www.tandfonline.com/doi/full/10.4161/epi.23924

  • Input: Gasparoni_QNBMIQ_PCfiltered.RDS, pheno_df.RDS

  • Output: pheno_withNeuronProp_df.RDS

objects <- load("../../CET/CETS_Image.RData")
objects
##  [1] "a"             "a1"            "b"             "b1"           
##  [5] "brain"         "c"             "dat"           "deconvolute"  
##  [9] "dilution"      "estProportion" "f"             "g2"           
## [13] "getF"          "getReference"  "i"             "idx"          
## [17] "modelIdx"      "p"             "pdBrain"       "prop"         
## [21] "r2"            "refProfile"    "res"           "rowttests"    
## [25] "variables"

7.1 Get reference profile from Caucasions + controls

idx <- list(
  controlNeuron = pdBrain$celltype == "N" & pdBrain$diag == "Control" & pdBrain$ethnicity == "Caucasian",
  controlGlia   = pdBrain$celltype == "G" & pdBrain$diag == "Control" & pdBrain$ethnicity == "Caucasian"
)

refProfile <- getReference(brain, idx)


##### 2. Estimate proportions of neurons in PFC samples ########################

### Limit to 10,000 cpgs in the refProfile dataset
pfc <- readRDS(paste0(data.dir.pca, "Gasparoni_QNBMIQ_PCfiltered.RDS")) #dim: 433656 59

selected <- rownames(pfc) %in% rownames(refProfile)

pfc.refcpgs <- pfc[selected, ] 

### Estimate proportion of neurons
prop <- data.frame(estProportion(pfc.refcpgs, profile = refProfile))
colnames(prop) <- "prop.neuron"

##### 3. Merge pfc.refcpgs with phenotype file #################################
pheno <- readRDS(paste0(data.dir.pca, "pheno_df.RDS"))

pheno_final <- merge(
  pheno,
  prop,
  by.x = "sample",
  by.y = "row.names"
)

saveRDS(pheno_final, paste0(data.dir.neuron, "pheno_withNeuronProp_df.RDS"))

8 Linear regression by cpgs Methylation

Input:

  • Gasparoni_QNBMIQ_PCfiltered.RDS,
  • pheno59_withNeuronProp_df.RDS

Output:

  • Gasparoni_single_cpg_pVal_df.csv

8.1 Import datasets

beta_mat <- readRDS(paste0(data.dir.pca, "Gasparoni_QNBMIQ_PCfiltered.RDS")) 
pheno_df <- readRDS(paste0(data.dir.neuron, "pheno_withNeuronProp_df.RDS")) 

8.2 Test all cpgs

### Compute M values
mval_mat <- log2(beta_mat / (1 - beta_mat))

pheno_df$Sample <- pheno_df$sample

identical(pheno_df$Sample, colnames(mval_mat))
## [1] TRUE
pheno_df$sex <- as.factor(pheno_df$sex)
pheno_df$slide <- as.factor(pheno_df$slide)
# If rosmap cohort, don't forget batch effect

str(pheno_df)
## 'data.frame':    56 obs. of  9 variables:
##  $ sample     : chr  "GSM2808939" "GSM2808940" "GSM2808941" "GSM2808942" ...
##  $ subject.id : chr  "RZ052" "RZ055" "RZ057" "RZ058" ...
##  $ slide      : Factor w/ 6 levels "5854945010","5854945021",..: 3 3 3 3 3 3 3 3 4 4 ...
##  $ age.brain  : num  82 80 88 77 75 73 67 74 53 18 ...
##  $ sex        : Factor w/ 2 levels "F","M": 1 2 1 1 2 2 1 2 2 2 ...
##  $ stage      : num  5 5 2 2 2 6 6 6 0 0 ...
##  $ stage3     : chr  "5-6" "5-6" "0-2" "0-2" ...
##  $ prop.neuron: num  0.374 0.403 0.431 0.24 0.343 ...
##  $ Sample     : chr  "GSM2808939" "GSM2808940" "GSM2808941" "GSM2808942" ...
is(pheno_df$stage,"numeric")
## [1] TRUE
is(pheno_df$age.brain,"numeric")
## [1] TRUE
is(pheno_df$prop.neuron,"numeric")
## [1] TRUE
predictors_char <- "stage"
covariates_char <- c("age.brain", "sex", "prop.neuron", "slide")


doParallel::registerDoParallel(cores = parallel::detectCores()/2)
devtools::source_gist("https://gist.github.com/tiagochst/d3a7b1639acf603916c315d23b1efb3e")

results_ordered_df <- plyr::adply(mval_mat,1, function(row){
  
  sumOneRegion_df <- data.frame(t(row))
  
  result <- TestSingleRegion(
    predictors_char = predictors_char,
    covariates_char = covariates_char,
    pheno_df = pheno_df,
    sumOneRegion_df = sumOneRegion_df
  )
  result
}, .progress = "time",.parallel = TRUE,.id = "cpg")
colnames(results_ordered_df)[1] <- "cpg"

identical(row.names(mval_mat), results_ordered_df$cpg %>% as.character())

results_ordered_df$fdr <- p.adjust(
    results_ordered_df$pValue,
    method = "fdr"
)

write.csv(
  results_ordered_df,
  paste0(data.dir.single.cpg.pval, "Gasparoni_single_cpg_pVal_df.csv"),
  row.names = FALSE
)
results_ordered_df <- readr::read_csv(
  paste0(data.dir.single.cpg.pval, "Gasparoni_single_cpg_pVal_df.csv"),
  col_types = readr::cols())
results_ordered_df

9 Linear regression by regions median Methylation

9.1 Residuals control and coMethylated Regions

  1. Take residuals
  2. Find co-methylated regions

Input:

  • QNBMIQ_PCfiltered
  • pheno_withNeuronProp_df

Output:

  • QNBMIQ_PCfiltered_mvalResiduals
  • residuals_cometh_ls

9.1.1 Residuals

##### 1. Import datasets #######################################################
beta_mat <- readRDS(paste0(data.dir.pca, "Gasparoni_QNBMIQ_PCfiltered.RDS")) #dim:433656 59
pheno_df <- readRDS(paste0(data.dir.neuron, "pheno_withNeuronProp_df.RDS")) #dim:59 7

### Compute M values
mvalue_mat <- log2(beta_mat / (1 - beta_mat))

### Reorder samples based on pheno_df
mvalue_mat <- mvalue_mat[, pheno_df$sample]

identical(colnames(mvalue_mat),  pheno_df$sample)

### Take residuals
lmF <- function(mval){
  fitE <- lm(
    as.numeric(mval) ~ age.brain + sex + prop.neuron + as.character(slide), #add batch if rosmap
    data = pheno_df,
    na.action = na.exclude
  )
  residuals (fitE)
}
doParallel::registerDoParallel(cores = 4)
resid <- plyr::adply(mvalue_mat,1,.fun = lmF,.progress = "time",.parallel = TRUE)
rownames(resid) <- resid[,1]
resid[,1] <- NULL
colnames(resid) <- colnames(mvalue_mat)
dim(resid)
dim(mvalue_mat)

### Save dataset
saveRDS(
  resid,
  paste0(data.dir.residuals, "Gasparoni_QNBMIQ_PCfiltered_mvalResiduals.RDS")
)

9.1.2 Find co-methylated regions

### Import datasets
mvalue_residuals_mat <- readRDS(
  paste0(data.dir.residuals, "Gasparoni_QNBMIQ_PCfiltered_mvalResiduals.RDS")
)

### Call in functions
library(coMethDMR)
library(BiocParallel)

probes.cluster.all <- coMethDMR::getPredefinedCluster(arrayType = "450k",
                                                      clusterType = "regions")

ncores <- parallel::detectCores()/2
### Find co-methylated clusters
coMeth_ls <- CoMethAllRegions(
  dnam = mvalue_residuals_mat,      
  betaToM = FALSE,                   
  CpGs_ls = probes.cluster.all,
  arrayType = "450k",
  rDropThresh_num = 0.4,
  minPairwiseCorr = NULL,
  method = "spearman",             
  returnAllCpGs = TRUE,              
  output = "all",
  nCores_int = ncores,
  progressbar = FALSE
)

saveRDS(
  coMeth_ls,
  paste0(data.dir.residuals,"Gasparoni_residuals_cometh_input_ls.RDS")
)

9.2 Linear regression by regions median Methylation

  1. Calculate medians by cluster and sample
  2. linear regression

Input:

  • QNBMIQ_PCfiltered,
  • pheno_withNeuronProp_df
  • residuals_cometh_input_ls

Output:

  • info_df
  • mediansMval_df
  • linear_df_aging

9.2.1 Calculate medians by cluster and sample

### Import datasets
beta_mat <- readRDS(paste0(data.dir.pca,
                           "Gasparoni_QNBMIQ_PCfiltered.RDS"))
pheno_df <- readRDS(paste0(data.dir.neuron, "pheno_withNeuronProp_df.RDS"))
mval_mat <- log2(beta_mat / (1 - beta_mat)) %>% as.matrix()
coMeth_ls <- readRDS(
  paste0(data.dir.residuals, "Gasparoni_residuals_cometh_input_ls.RDS")
)

### Create info dataset
input_cometh <- data.frame(
  inputRegion = coMeth_ls$inputRegion_chr,
  nCoMethRegion = coMeth_ls$nCoMethRegions_num,
  coMethRegion = names(coMeth_ls$coMeth_ls),
  nCpGs = unlist(lapply(coMeth_ls$coMeth_ls, length), use.names = FALSE),
  stringsAsFactors = FALSE
)

input_cometh_nodup <- input_cometh[
  !duplicated(input_cometh$coMethRegion),
  ]
colnames(input_cometh_nodup) <- c(
  paste0(cohort, "_inputRegion"),
  paste0(cohort, "_nCoMethRegion"),
  paste0(cohort, "_coMethRegion"),
  paste0(cohort, "_nCpGs")
)

saveRDS(
  input_cometh_nodup,
  paste0(data.dir.median, cohort,"_info_df.rds")
)

### Take median of probes in each cluster for each sample
filename <-  paste0(paste0(data.dir.median, cohort, "_mediansMval_df.rds"))
library(robustbase)
mval_mat <- mval_mat[rownames(mval_mat) %in% unlist(coMeth_ls$coMeth_ls),]
if(!file.exists(filename)){
  medianMval.df <- plyr::ldply(
    coMeth_ls$coMeth_ls[!duplicated(names(coMeth_ls$coMeth_ls))],
    function(probes){
      colMedians(mval_mat[as.character(probes),], na.rm = TRUE)
    },
    .progress = "time"
  )
  medianMval.df$.id <- NULL
  colnames(medianMval.df) <- colnames(mval_mat)
  saveRDS(medianMval.df, file = filename)
} else {
  medianMval.df <- readRDS(filename)
}

9.2.2 Test all regions – linear regressions

### Import datasets
cohort <- "Gasparoni"
info_df <- readRDS(dir(data.dir.median, pattern = "info", full.names = TRUE))
mediansMval_df <- readRDS(dir(data.dir.median, pattern = "mediansMval", full.names = TRUE))
pheno_df <- readRDS(paste0(data.dir.neuron, "pheno_withNeuronProp_df.RDS")) 

### Check variables before fitting model
pheno_df$Sample <- pheno_df$sample
identical(pheno_df$Sample, colnames(mediansMval_df))
## [1] TRUE
pheno_df$sex <- as.factor(pheno_df$sex)
pheno_df$slide <- as.factor(pheno_df$slide)
# If rosmap cohort, don't forget batch effect

str(pheno_df)
## 'data.frame':    56 obs. of  9 variables:
##  $ sample     : chr  "GSM2808939" "GSM2808940" "GSM2808941" "GSM2808942" ...
##  $ subject.id : chr  "RZ052" "RZ055" "RZ057" "RZ058" ...
##  $ slide      : Factor w/ 6 levels "5854945010","5854945021",..: 3 3 3 3 3 3 3 3 4 4 ...
##  $ age.brain  : num  82 80 88 77 75 73 67 74 53 18 ...
##  $ sex        : Factor w/ 2 levels "F","M": 1 2 1 1 2 2 1 2 2 2 ...
##  $ stage      : num  5 5 2 2 2 6 6 6 0 0 ...
##  $ stage3     : chr  "5-6" "5-6" "0-2" "0-2" ...
##  $ prop.neuron: num  0.374 0.403 0.431 0.24 0.343 ...
##  $ Sample     : chr  "GSM2808939" "GSM2808940" "GSM2808941" "GSM2808942" ...
devtools::source_gist("https://gist.github.com/tiagochst/d3a7b1639acf603916c315d23b1efb3e")

predictors_char <- "stage"
covariates_char <- c("age.brain", "sex", "prop.neuron", "slide")

res_df <- TestAllRegions_noInfo(
  predictors_char = predictors_char,
  covariates_char = covariates_char,
  pheno_df = pheno_df,
  summarizedRegions_df = mediansMval_df
)

colnames(res_df) <- c(
  paste0(cohort, "_estimate"),
  paste0(cohort, "_se"),
  paste0(cohort, "_pVal"),
  paste0(cohort, "_fdr")
)

res_withInfo_df <- cbind(info_df, res_df)

saveRDS(
  res_withInfo_df,
  paste0(data.dir.median,  cohort, "_linear_df.rds")
)
file <- dir(data.dir.median,pattern = paste0(".*linear_df"),
            recursive = T,
            full.names = TRUE,
            ignore.case = T)
file
## [1] "DATASETS//GASPARONI////step11_median//Gasparoni_linear_df.rds"
res_withInfo_df <- readRDS(file)
dim(res_withInfo_df)
## [1] 39865     8
res_withInfo_df

10 Data final

dir(path = data.dir,recursive = T, pattern = ".rda|.csv|.RDS")
##  [1] "step10_residuals/Gasparoni_QNBMIQ_PCfiltered_mvalResiduals.RDS"           
##  [2] "step10_residuals/Gasparoni_residuals_cometh_input_ls.RDS"                 
##  [3] "step2_read_minfi/Gasparoni.rda"                                           
##  [4] "step2_read_minfi/GSE66351_pheno.csv"                                      
##  [5] "step3_bsConvFilter/RGSet_bsfiltered.rda"                                  
##  [6] "step4_clinical_available_filtering/gasparoni_bs_and_clinical_filtered.rda"
##  [7] "step5_probesQC_filtering/beta_CG_XY_SNPfiltered_mat.rda"                  
##  [8] "step6_normalization/GASPARONI_QNBMIQ.rda"                                 
##  [9] "step6_normalization/GASPARONI_QNBMIQ.RDS"                                 
## [10] "step7_pca_filtering/GASPARONI_PCs_usingBetas.csv"                         
## [11] "step7_pca_filtering/Gasparoni_QNBMIQ_PCfiltered.RDS"                      
## [12] "step7_pca_filtering/pheno_df.RDS"                                         
## [13] "step8_neuron_comp/pheno_withNeuronProp_df.RDS"                            
## [14] "step9_single_cpg_pval/Gasparoni_single_cpg_pVal_df.csv"

11 Session information

devtools::session_info()
## ─ Session info ───────────────────────────────────────────────────────────────
##  setting  value                                             
##  version  R Under development (unstable) (2020-02-25 r77857)
##  os       macOS Catalina 10.15.3                            
##  system   x86_64, darwin15.6.0                              
##  ui       X11                                               
##  language (EN)                                              
##  collate  en_US.UTF-8                                       
##  ctype    en_US.UTF-8                                       
##  tz       America/New_York                                  
##  date     2020-04-30                                        
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package                                       * version     date       lib
##  acepack                                         1.4.1       2016-10-29 [1]
##  affy                                            1.65.1      2019-11-06 [1]
##  affyio                                          1.57.0      2019-11-06 [1]
##  annotate                                        1.65.1      2020-01-27 [1]
##  AnnotationDbi                                 * 1.49.1      2020-01-25 [1]
##  AnnotationFilter                                1.11.0      2019-11-06 [1]
##  AnnotationHub                                 * 2.19.12     2020-04-21 [1]
##  askpass                                         1.1         2019-01-13 [1]
##  assertthat                                      0.2.1       2019-03-21 [1]
##  backports                                       1.1.6       2020-04-05 [1]
##  base64                                          2.0         2016-05-10 [1]
##  base64enc                                       0.1-3       2015-07-28 [1]
##  beanplot                                        1.2         2014-09-19 [1]
##  Biobase                                       * 2.47.3      2020-03-16 [1]
##  BiocFileCache                                 * 1.11.6      2020-04-16 [1]
##  BiocGenerics                                  * 0.33.3      2020-03-23 [1]
##  BiocManager                                     1.30.10     2019-11-16 [1]
##  BiocParallel                                    1.21.3      2020-04-21 [1]
##  BiocVersion                                     3.11.1      2019-11-13 [1]
##  biomaRt                                         2.43.6      2020-04-21 [1]
##  Biostrings                                    * 2.55.7      2020-03-24 [1]
##  biovizBase                                      1.35.1      2019-12-03 [1]
##  bit                                             1.1-15.2    2020-02-10 [1]
##  bit64                                           0.9-7       2017-05-08 [1]
##  bitops                                          1.0-6       2013-08-17 [1]
##  blob                                            1.2.1       2020-01-20 [1]
##  BSgenome                                        1.55.4      2020-03-19 [1]
##  bsseq                                           1.23.2      2020-04-06 [1]
##  bumphunter                                    * 1.29.0      2019-11-07 [1]
##  callr                                           3.4.3       2020-03-28 [1]
##  cellranger                                      1.1.0       2016-07-27 [1]
##  checkmate                                       2.0.0       2020-02-06 [1]
##  cli                                             2.0.2       2020-02-28 [1]
##  cluster                                       * 2.1.0       2019-06-19 [1]
##  codetools                                       0.2-16      2018-12-24 [1]
##  colorspace                                      1.4-1       2019-03-18 [1]
##  crayon                                          1.3.4       2017-09-16 [1]
##  crosstalk                                       1.1.0.1     2020-03-13 [1]
##  curl                                            4.3         2019-12-02 [1]
##  data.table                                      1.12.9      2020-02-26 [1]
##  DBI                                             1.1.0       2019-12-15 [1]
##  dbplyr                                        * 1.4.3       2020-04-19 [1]
##  DelayedArray                                  * 0.13.12     2020-04-10 [1]
##  DelayedMatrixStats                              1.9.1       2020-03-30 [1]
##  desc                                            1.2.0       2018-05-01 [1]
##  devtools                                        2.3.0       2020-04-10 [1]
##  dichromat                                       2.0-0       2013-01-24 [1]
##  digest                                          0.6.25      2020-02-23 [1]
##  DMRcate                                       * 2.1.9       2020-03-28 [1]
##  DMRcatedata                                   * 2.5.0       2019-10-31 [1]
##  DNAcopy                                         1.61.0      2019-11-06 [1]
##  doRNG                                           1.8.2       2020-01-27 [1]
##  dplyr                                         * 0.8.99.9002 2020-04-02 [1]
##  DSS                                             2.35.1      2020-04-14 [1]
##  DT                                              0.13        2020-03-23 [1]
##  edgeR                                           3.29.1      2020-02-26 [1]
##  ellipsis                                        0.3.0       2019-09-20 [1]
##  ensembldb                                       2.11.4      2020-04-17 [1]
##  evaluate                                        0.14        2019-05-28 [1]
##  ExperimentHub                                 * 1.13.8      2020-04-21 [1]
##  fansi                                           0.4.1       2020-01-08 [1]
##  fastmap                                         1.0.1       2019-10-08 [1]
##  FDb.InfiniumMethylation.hg19                  * 2.2.0       2020-04-09 [1]
##  foreach                                       * 1.5.0       2020-03-30 [1]
##  foreign                                         0.8-79      2020-04-26 [1]
##  Formula                                         1.2-3       2018-05-03 [1]
##  fs                                              1.4.1       2020-04-04 [1]
##  genefilter                                      1.69.0      2019-11-06 [1]
##  generics                                        0.0.2       2018-11-29 [1]
##  GenomeInfoDb                                  * 1.23.17     2020-04-13 [1]
##  GenomeInfoDbData                                1.2.3       2020-04-20 [1]
##  GenomicAlignments                               1.23.2      2020-03-24 [1]
##  GenomicFeatures                               * 1.39.7      2020-03-19 [1]
##  GenomicRanges                                 * 1.39.3      2020-04-08 [1]
##  GEOquery                                        2.55.2      2020-04-23 [1]
##  ggplot2                                       * 3.3.0       2020-03-05 [1]
##  glue                                            1.4.0       2020-04-03 [1]
##  gridExtra                                       2.3         2017-09-09 [1]
##  gtable                                          0.3.0       2019-03-25 [1]
##  gtools                                          3.8.2       2020-03-31 [1]
##  Gviz                                            1.31.13     2020-04-21 [1]
##  HDF5Array                                       1.15.18     2020-04-10 [1]
##  Hmisc                                           4.4-0       2020-03-23 [1]
##  hms                                             0.5.3       2020-01-08 [1]
##  htmlTable                                       1.13.3      2019-12-04 [1]
##  htmltools                                       0.4.0       2019-10-04 [1]
##  htmlwidgets                                     1.5.1       2019-10-08 [1]
##  httpuv                                          1.5.2       2019-09-11 [1]
##  httr                                            1.4.1       2019-08-05 [1]
##  IlluminaHumanMethylation450kanno.ilmn12.hg19  * 0.6.0       2020-03-24 [1]
##  IlluminaHumanMethylation450kmanifest          * 0.4.0       2020-04-09 [1]
##  IlluminaHumanMethylationEPICanno.ilm10b4.hg19   0.6.0       2020-04-09 [1]
##  illuminaio                                    * 0.29.0      2019-11-06 [1]
##  interactiveDisplayBase                          1.25.0      2019-11-06 [1]
##  IRanges                                       * 2.21.8      2020-03-25 [1]
##  iterators                                     * 1.0.12      2019-07-26 [1]
##  jpeg                                            0.1-8.1     2019-10-24 [1]
##  jsonlite                                        1.6.1       2020-02-02 [1]
##  KernSmooth                                      2.23-17     2020-04-26 [1]
##  knitr                                           1.28        2020-02-06 [1]
##  later                                           1.0.0       2019-10-04 [1]
##  lattice                                         0.20-41     2020-04-02 [1]
##  latticeExtra                                    0.6-29      2019-12-19 [1]
##  lazyeval                                        0.2.2       2019-03-15 [1]
##  lifecycle                                       0.2.0       2020-03-06 [1]
##  limma                                         * 3.43.8      2020-04-14 [1]
##  locfit                                        * 1.5-9.4     2020-03-25 [1]
##  lumi                                          * 2.39.3      2020-03-27 [1]
##  magrittr                                        1.5         2014-11-22 [1]
##  MASS                                            7.3-51.6    2020-04-26 [1]
##  Matrix                                          1.2-18      2019-11-27 [1]
##  matrixStats                                   * 0.56.0      2020-03-13 [1]
##  mclust                                          5.4.6       2020-04-11 [1]
##  memoise                                         1.1.0       2017-04-21 [1]
##  methylumi                                     * 2.33.0      2019-11-06 [1]
##  mgcv                                            1.8-31      2019-11-09 [1]
##  mime                                            0.9         2020-02-04 [1]
##  minfi                                         * 1.33.1      2020-03-05 [1]
##  missMethyl                                      1.21.4      2020-01-28 [1]
##  multtest                                        2.43.1      2020-03-12 [1]
##  munsell                                         0.5.0       2018-06-12 [1]
##  nleqslv                                         3.3.2       2018-05-17 [1]
##  nlme                                            3.1-147     2020-04-13 [1]
##  nnet                                            7.3-14      2020-04-26 [1]
##  nor1mix                                         1.3-0       2019-06-13 [1]
##  openssl                                         1.4.1       2019-07-18 [1]
##  org.Hs.eg.db                                  * 3.10.0      2020-03-30 [1]
##  permute                                         0.9-5       2019-03-12 [1]
##  pillar                                          1.4.3       2019-12-20 [1]
##  pkgbuild                                        1.0.7       2020-04-25 [1]
##  pkgconfig                                       2.0.3       2019-09-22 [1]
##  pkgload                                         1.0.2       2018-10-29 [1]
##  plyr                                            1.8.6       2020-03-03 [1]
##  png                                             0.1-7       2013-12-03 [1]
##  preprocessCore                                  1.49.2      2020-02-01 [1]
##  prettyunits                                     1.1.1       2020-01-24 [1]
##  processx                                        3.4.2       2020-02-09 [1]
##  progress                                        1.2.2       2019-05-16 [1]
##  promises                                        1.1.0       2019-10-04 [1]
##  ProtGenerics                                    1.19.3      2019-12-25 [1]
##  ps                                              1.3.2       2020-02-13 [1]
##  purrr                                           0.3.4       2020-04-17 [1]
##  quadprog                                        1.5-8       2019-11-20 [1]
##  R.methodsS3                                     1.8.0       2020-02-14 [1]
##  R.oo                                            1.23.0      2019-11-03 [1]
##  R.utils                                         2.9.2       2019-12-08 [1]
##  R6                                              2.4.1       2019-11-12 [1]
##  randomForest                                    4.6-14      2018-03-25 [1]
##  rappdirs                                        0.3.1       2016-03-28 [1]
##  RColorBrewer                                    1.1-2       2014-12-07 [1]
##  Rcpp                                            1.0.4.6     2020-04-09 [1]
##  RCurl                                           1.98-1.2    2020-04-18 [1]
##  readr                                           1.3.1       2018-12-21 [1]
##  readxl                                          1.3.1       2019-03-13 [1]
##  remotes                                         2.1.1       2020-02-15 [1]
##  reshape                                         0.8.8       2018-10-23 [1]
##  reshape2                                      * 1.4.4       2020-04-09 [1]
##  rhdf5                                           2.31.10     2020-04-02 [1]
##  Rhdf5lib                                        1.9.3       2020-04-15 [1]
##  rlang                                           0.4.5.9000  2020-03-20 [1]
##  rmarkdown                                       2.1         2020-01-20 [1]
##  rngtools                                        1.5         2020-01-23 [1]
##  ROC                                           * 1.63.0      2019-11-06 [1]
##  rpart                                           4.1-15      2019-04-12 [1]
##  RPMM                                          * 1.25        2017-02-28 [1]
##  rprojroot                                       1.3-2       2018-01-03 [1]
##  Rsamtools                                       2.3.7       2020-03-18 [1]
##  RSQLite                                         2.2.0       2020-01-07 [1]
##  rstudioapi                                      0.11        2020-02-07 [1]
##  rtracklayer                                     1.47.0      2019-11-06 [1]
##  S4Vectors                                     * 0.25.15     2020-04-04 [1]
##  scales                                        * 1.1.0       2019-11-18 [1]
##  scrime                                          1.3.5       2018-12-01 [1]
##  sesame                                        * 1.5.3       2020-03-03 [1]
##  sesameData                                    * 1.5.0       2019-10-31 [1]
##  sessioninfo                                     1.1.1       2018-11-05 [1]
##  shiny                                           1.4.0.2     2020-03-13 [1]
##  siggenes                                        1.61.0      2019-11-06 [1]
##  statmod                                         1.4.34      2020-02-17 [1]
##  stringi                                         1.4.6       2020-02-17 [1]
##  stringr                                         1.4.0       2019-02-10 [1]
##  SummarizedExperiment                          * 1.17.5      2020-03-27 [1]
##  survival                                        3.1-12      2020-04-10 [1]
##  testthat                                        2.3.2       2020-03-02 [1]
##  tibble                                          3.0.1       2020-04-20 [1]
##  tidyr                                           1.0.2       2020-01-24 [1]
##  tidyselect                                      1.0.0       2020-01-27 [1]
##  TxDb.Hsapiens.UCSC.hg19.knownGene             * 3.2.2       2020-04-02 [1]
##  usethis                                         1.6.0       2020-04-09 [1]
##  VariantAnnotation                               1.33.5      2020-04-23 [1]
##  vctrs                                           0.2.99.9010 2020-04-02 [1]
##  wateRmelon                                    * 1.31.0      2019-11-06 [1]
##  wheatmap                                        0.1.0       2018-03-15 [1]
##  withr                                           2.2.0       2020-04-20 [1]
##  xfun                                            0.13        2020-04-13 [1]
##  XML                                             3.99-0.3    2020-01-20 [1]
##  xml2                                            1.3.2       2020-04-23 [1]
##  xtable                                          1.8-4       2019-04-21 [1]
##  XVector                                       * 0.27.2      2020-03-24 [1]
##  yaml                                            2.2.1       2020-02-01 [1]
##  zlibbioc                                        1.33.1      2020-01-24 [1]
##  source                                     
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  local                                      
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  Github (tidyverse/dplyr@affb977)           
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  Github (Bioconductor/GenomicRanges@70e6e69)
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  Github (r-lib/rlang@a90b04b)               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  Github (r-lib/vctrs@fd24927)               
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
##  CRAN (R 4.0.0)                             
##  Bioconductor                               
## 
## [1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library
LS0tCnRpdGxlOiAiR0FTUEFST05JIGRhdGFzZXQiCmF1dGhvcjogIkxhbnl1IFpoYW5nLCBUaWFnbyBDLiBTaWx2YSwgTGlseSBXYW5nIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBybWFya2Rvd246Omh0bWxfZG9jdW1lbnQ6CiAgICB0aGVtZTogbHVtZW4KICAgIGhpZ2hsaWdodDogbnVsbAogICAgdG9jOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHllcwogICAgdG9jX2RlcHRoOiAzCmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUgICAgCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgojIERhdGEgcmV0cml2YWwKCmBgYHtSLCBtZXNzYWdlID0gRkFMU0UsIHJlc3VsdHMgPSAnaGlkZSd9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobWluZmkpCmBgYAoKYGBge1J9CmNvaG9ydCA8LSAiR0FTUEFST05JIgpkYXRhLmRpciA8LSBmaWxlLnBhdGgoIkRBVEFTRVRTLyIsY29ob3J0LCIvIikgCmRhdGEuZGlyLnRhYmxlIDwtICJEQVRBU0VUUy9TdW1tYXJ5X1RhYmxlLyIgCmRhdGEuZGlyLnJhdyA8LSBmaWxlLnBhdGgoZGF0YS5kaXIsIi9zdGVwMV9kb3dubG9hZC8iKSAKZGF0YS5kaXIucmVhZCA8LSBmaWxlLnBhdGgoZGF0YS5kaXIsIi9zdGVwMl9yZWFkX21pbmZpLyIpIApkYXRhLmRpci5ic2ZpbHRlciA8LSBmaWxlLnBhdGgoZGF0YS5kaXIsIi9zdGVwM19ic0NvbnZGaWx0ZXIvIikgCmRhdGEuZGlyLmNsaW5pY2FsLmZpbHRlciA8LSBmaWxlLnBhdGgoZGF0YS5kaXIsIi9zdGVwNF9jbGluaWNhbF9hdmFpbGFibGVfZmlsdGVyaW5nLyIpIApkYXRhLmRpci5wcm9iZXMucWMgPC0gZmlsZS5wYXRoKGRhdGEuZGlyLCIvc3RlcDVfcHJvYmVzUUNfZmlsdGVyaW5nLyIpIApkYXRhLmRpci5wcm9iZXMubm9ybWFsaXphdGlvbiA8LSBmaWxlLnBhdGgoZGF0YS5kaXIsIi9zdGVwNl9ub3JtYWxpemF0aW9uLyIpIApkYXRhLmRpci5wY2EgPC0gZmlsZS5wYXRoKGRhdGEuZGlyLCIvc3RlcDdfcGNhX2ZpbHRlcmluZy8iKSAKZGF0YS5kaXIubmV1cm9uIDwtIGZpbGUucGF0aChkYXRhLmRpciwiL3N0ZXA4X25ldXJvbl9jb21wLyIpIApkYXRhLmRpci5zaW5nbGUuY3BnLnB2YWwgPC0gZmlsZS5wYXRoKGRhdGEuZGlyLCIvc3RlcDlfc2luZ2xlX2NwZ19wdmFsLyIpIApkYXRhLmRpci5yZXNpZHVhbHMgPC0gZmlsZS5wYXRoKGRhdGEuZGlyLCIvc3RlcDEwX3Jlc2lkdWFscy8iKSAKZGF0YS5kaXIubWVkaWFuIDwtIGZpbGUucGF0aChkYXRhLmRpciwiL3N0ZXAxMV9tZWRpYW4vIikgCmZvcihwIGluIGdyZXAoImRpciIsbHMoKSx2YWx1ZSA9IFQpKSBkaXIuY3JlYXRlKGdldChwKSxyZWN1cnNpdmUgPSBUUlVFLHNob3dXYXJuaW5ncyA9IEZBTFNFKQpgYGAKClJlcXVpcmVkIFIgbGlicmFyaWVzOiBgR0VPcXVlcnlgIGNhbiBiZSBpbnN0YWxsZWQgYXMgZm9sbG93aW5nOgoKYGBge1IsIGV2YWwgPSBGQUxTRX0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJCaW9jTWFuYWdlciIsIHF1aWV0bHkgPSBUUlVFKSkKICBpbnN0YWxsLnBhY2thZ2VzKCJCaW9jTWFuYWdlciIpCgpCaW9jTWFuYWdlcjo6aW5zdGFsbCgiR0VPcXVlcnkiKQpgYGAKCkRhdGEgZnJvbTogaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9nZW8vcXVlcnkvYWNjLmNnaT9hY2M9R1NFNjYzNTEKCmBgYHtyIHN5bmFwc2UsIGV2YWwgPSBGQUxTRX0KbGlicmFyeShHRU9xdWVyeSkKbGlicmFyeShTdW1tYXJpemVkRXhwZXJpbWVudCkKdGVzdCA8LSBnZXRHRU8oR0VPID0gIkdTRTY2MzUxIixkZXN0ZGlyID0gZGF0YS5kaXIucmF3KQpzZSA8LSB0ZXN0JEdTRTY2MzUxX3Nlcmllc19tYXRyaXgudHh0Lmd6ICU+JSBtYWtlU3VtbWFyaXplZEV4cGVyaW1lbnRGcm9tRXhwcmVzc2lvblNldCgpCmBgYAoKYGBge1IsIGV2YWwgPSBGQUxTRX0Kc2UgPC0gc2VbLHNlJHNvdXJjZV9uYW1lX2NoMSAgPT0gIkZyb250YWwgQ29ydGV4IiAmCiAgICAgICAgICAgc2UkY2hhcmFjdGVyaXN0aWNzX2NoMSA9PSAiY2VsbCB0eXBlOiBidWxrIiAmCiAgICAgICAgICAgc2UkYnJhYWtfc3RhZ2UuY2gxICE9ICJOQSJdCmBgYAoKV2UgIHdpbGwgZG93bmxvYWQgSWRhdCBmaWxlcyBmb3IgYWxsIG91ciBzYW1wbGVzCgpgYGB7UiwgZXZhbCA9ICBGQUxTRX0KZmlsZXMgPC0gYyhzZSRzdXBwbGVtZW50YXJ5X2ZpbGUgJT4lIGFzLmNoYXJhY3RlcigpLAogICAgICAgICAgIHNlJHN1cHBsZW1lbnRhcnlfZmlsZS4xICU+JSBhcy5jaGFyYWN0ZXIoKSkKZGlyLmNyZWF0ZShkYXRhLmRpci5yYXcsc2hvd1dhcm5pbmdzID0gRkFMU0UscmVjdXJzaXZlID0gVFJVRSkKcGx5cjo6YV9wbHkoZmlsZXMsLm1hcmdpbnMgPSAxLC5mdW4gPSBmdW5jdGlvbih1cmwpewogIG91dC5maWxlIDwtIGZpbGUucGF0aChkYXRhLmRpci5yYXcsYmFzZW5hbWUodXJsKSkKICBpZighZmlsZS5leGlzdHMob3V0LmZpbGUpKSBkb3dubG9hZGVyOjpkb3dubG9hZCh1cmwsb3V0LmZpbGUpCiAgZ3VuemlwKG91dC5maWxlKQp9LC5wcm9ncmVzcyA9ICJ0aW1lIikKYGBgCgoKIyBEYXRhIFByZS1wcm9jZXNzaW5nCgpEZXNjcmlwdGlvbjogCgotIFJlYWQgaW4gaWRhdCBmaWxlcyBhbmQgcmVtb3ZlIGR1cGxpY2F0ZWQgc2FtcGxlcwoKSW5wdXQ6IAoKLSBpZGF0IGZpbGVzCgpPdXRwdXQ6IAoKLSBSR1NldC5SRFMKLSBwaGVub0RhdGEKLSBCZXRhTWF0cml4UmF3CgpgYGB7UiwgZXZhbCA9IEZBTFNFfQpSR1NldCA8LSByZWFkLm1ldGhhcnJheS5leHAoYmFzZSA9IGRhdGEuZGlyLnJhdywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2l2ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlID0gVFJVRSkgI2RpbTogNjIyMzk5IDYwCnBoZW5vRGF0YSA8LSBjb2xEYXRhKHNlKQpzYXZlKFJHU2V0LHBoZW5vRGF0YSwgZmlsZSA9IHBhc3RlMChkYXRhLmRpci5yZWFkLCAiR2FzcGFyb25pLnJkYSIpKSAKYGBgCgoKIyBEYXRhIFFDIAoKIyMgQmlsc3VmaXRlIGNvbnZlcnNpb24gZmlsdGVyaW5nCgpSZW1vdmluZyBzYW1wbGVzIHdpdGggYmlzdWxmaXRlQ29udmVyc2lvbiBsb3dlciB0aGFuIDg4LgoKYGBge1IgcWNfc2FtcGxlc19wYWNrYWdlcywgbWVzc2FnZSA9IEZBTFNFLCByZXN1bHRzID0gImhpZGUifQpsaWJyYXJ5KHdhdGVSbWVsb24pCmxpYnJhcnkoUlBNTSkKI2xpYnJhcnkoc2VzYW1lKQojbGlicmFyeShzZXNhbWVEYXRhKQpgYGAKCgpgYGB7Un0KbG9hZChmaWxlID0gcGFzdGUwKGRhdGEuZGlyLnJlYWQsICJHYXNwYXJvbmkucmRhIikpCmJzIDwtIGRhdGEuZnJhbWUoYmlzdWxmaXRlQ29udmVyc2lvbiA9IGJzY29uKFJHU2V0KSkKYnNGaWx0ZXJlZE91dCA8LSByb3cubmFtZXMoYnMpW2JzJGJpc3VsZml0ZUNvbnZlcnNpb24gPCA4OF0KbmIuc2FtcGxlcyA8LSBuY29sKFJHU2V0KQpSR1NldCA8LSBSR1NldFssIWNvbG5hbWVzKFJHU2V0KSAlaW4lIGJzRmlsdGVyZWRPdXRdCm5iLnNhbXBsZXMuYmMuZmlsdGVyZWQgPC0gIG5jb2woUkdTZXQpCnBoZW5vRGF0YSA8LSBwaGVub0RhdGFbbWF0Y2goc3Vic3RyKGNvbG5hbWVzKFJHU2V0KSwxLDEwKSwgcGhlbm9EYXRhJGdlb19hY2Nlc3Npb24pLF0KYGBgCgpgYGB7UiwgZXZhbCA9IEZBTFNFfQpzYXZlKFJHU2V0LAogICAgIG5iLnNhbXBsZXMsCiAgICAgYnMsCiAgICAgcGhlbm9EYXRhLAogICAgIG5iLnNhbXBsZXMuYmMuZmlsdGVyZWQsIAogICAgIGZpbGUgPSBwYXN0ZTAoZGF0YS5kaXIuYnNmaWx0ZXIsICIvUkdTZXRfYnNmaWx0ZXJlZC5yZGEiKSkKYGBgCgpgYGB7UiwgaW5jbHVkZSA9IEZBTFNFLCBldmFsID0gVFJVRX0KbG9hZChmaWxlID0gcGFzdGUwKGRhdGEuZGlyLmJzZmlsdGVyLCAiL1JHU2V0X2JzZmlsdGVyZWQucmRhIikpCmBgYAoKYGBge1IsIGluY2x1ZGUgPSBGQUxTRSwgZXZhbD1GQUxTRX0KZ2dwdWJyOjpnZ2hpc3RvZ3JhbShicyRiaXN1bGZpdGVDb252ZXJzaW9uLHhsYWIgPSAiYmlzdWxmaXRlIENvbnZlcnNpb24iICkKYGBgCgojIyBDbGluaWNhbCBkYXRhIGZpbHRlcmluZwoKYGBge1J9CmRpbShwaGVub0RhdGEpCgpwaGVub0RhdGEkYnJhYWtfc3RhZ2UuY2gxIDwtIHBoZW5vRGF0YSRicmFha19zdGFnZS5jaDEgJT4lIGFzLm51bWVyaWMoKQpwaGVub0RhdGEkYWdlLmNoMSA8LSBwaGVub0RhdGEkYWdlLmNoMSAlPiUgYXMubnVtZXJpYygpCiMjIyBTdWJzZXQgcm93cyBhbmQgY29sdW1ucwpwaGVub19kZiA8LSBwaGVub0RhdGEgICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lCiAgZHBseXI6OmZpbHRlcigKICAgIHNvdXJjZV9uYW1lX2NoMSA9PSAiRnJvbnRhbCBDb3J0ZXgiICYKICAgICAgIWlzLm5hKHBoZW5vRGF0YSRicmFha19zdGFnZS5jaDEpICYKICAgICAgcGhlbm9EYXRhJGNoYXJhY3RlcmlzdGljc19jaDEgPT0gImNlbGwgdHlwZTogYnVsayIKICApICU+JSBkcGx5cjo6c2VsZWN0KAogICAgYygKICAgICAgImdlb19hY2Nlc3Npb24iLAogICAgICAiZG9ub3JfaWQuY2gxIiwKICAgICAgInNlbnRyaXhfaWQuY2gxIiwKICAgICAgImFnZS5jaDEiLAogICAgICAiU2V4LmNoMSIsCiAgICAgICJicmFha19zdGFnZS5jaDEiCiAgICApCiAgKQoKIyMjIFJlbmFtZSB2YXJzCmNvbG5hbWVzKHBoZW5vX2RmKSA8LSBjKAogICJzYW1wbGUiLCAic3ViamVjdC5pZCIsICJzbGlkZSIsICJhZ2UuYnJhaW4iLCAic2V4IiwgInN0YWdlIgopCgpkaW0ocGhlbm9fZGYpIApuYi5zYW1wbGVzLndpdGguY2xpbmljYWwgPC0gbnJvdyhwaGVub19kZikKIyMgcGhlbm90eXBlIGRhdGFzZXQKc2F2ZShSR1NldCwKICAgICBuYi5zYW1wbGVzLndpdGguY2xpbmljYWwsCiAgICAgcGhlbm9fZGYsCiAgICAgZmlsZSA9IHBhc3RlMChkYXRhLmRpci5jbGluaWNhbC5maWx0ZXIsICIvZ2FzcGFyb25pX2JzX2FuZF9jbGluaWNhbF9maWx0ZXJlZC5yZGEiKSkKYGBgCgojIyBQcm9iZXMgUUMKCklucHV0OiAKCi0gUkdTZXQuUkRTCi0gYmV0YV9tYXQuUkRTCgpPdXRwdXQ6IAoKLSBiZXRhX0NHX1hZX1NOUGZpbHRlcmVkLlJEUwoKCmBgYHtSfQojIyMjIyAxLiBzdWJzZXQgdG8gcHJvYmVzIHdpdGggZGV0ZWN0aW9uIFAgPD0gMC4wMSAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMgUmVhZCBpbiBSR1NldCBhbmQgYmV0YV9tYXQKbG9hZChwYXN0ZTAoZGF0YS5kaXIuY2xpbmljYWwuZmlsdGVyLCAiL2dhc3Bhcm9uaV9ic19hbmRfY2xpbmljYWxfZmlsdGVyZWQucmRhIikpCmBgYAoKYGBge1IsIG1lc3NhZ2UgPSBGQUxTRSwgcmVzdWx0cyA9ICdoaWRlJ30KIyMjIHN1YnNldCB0byBwcm9iZXMgd2l0aCBkZXRlY3Rpb24gUCA8PSAwLjAxCmxpYnJhcnkobWluZmkpCmBgYAoKYGBge1J9CmJldGFfbWF0IDwtIGdldEJldGEoUkdTZXQpIApuYi5wcm9iZXMgPC0gbnJvdyhiZXRhX21hdCkKZGV0UCA8LSBkZXRlY3Rpb25QKFJHU2V0LCB0eXBlID0gIm0rdSIpCmZhaWxlZC4wMSA8LSBkZXRQID4gMC4wMQpwYXNzZWRQcm9iZXMgPC0gcm93bmFtZXMoZmFpbGVkLjAxKVtyb3dNZWFucyhmYWlsZWQuMDEpID09IDBdIAoKCmJldGFfbWF0IDwtIGJldGFfbWF0W3Bhc3NlZFByb2JlcywgXQpuYi5wcm9iZXMuZGV0ZWN0UCA8LSBucm93KGJldGFfbWF0KQoKIyMjIyMgMi4ga2VlcCBvbmx5IHByb2JlcyB0aGF0IHN0YXJ0IHdpdGggImNnIiAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKYmV0YV9tYXQgPC0gYmV0YV9tYXRbZ3JlcCgiY2ciLHJvd25hbWVzKGJldGFfbWF0KSksXQpkaW0oYmV0YV9tYXQpIApuYi5wcm9iZXMuZGV0ZWN0UC5jZyA8LSBucm93KGJldGFfbWF0KQoKIyMjIyMgMy4gZHJvcCBwcm9iZXMgdGhhdCBhcmUgb24gWC9ZICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyMgNC4gZHJvcCBwcm9iZXMgd2hlcmUgU05QIHdpdGggTUFGID49IDAuMDEgaW4gdGhlIGxhc3QgNSBicCBvZiB0aGUgcHJvYmUgIyMKYGBgCgpgYGB7UiwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0V9CmxpYnJhcnkoRE1SY2F0ZSkKYmV0YV9tYXQgPC0gcm1TTlBhbmRDSCgKICBvYmplY3QgPSBiZXRhX21hdCwKICBkaXN0ID0gNSwgCiAgbWFmY3V0ID0gMC4wMSwgCiAgYW5kID0gVFJVRSwKICBybWNyb3NzaHliID0gRkFMU0UsCiAgcm1YWSA9IFRSVUUKKSAKbmIucHJvYmVzLmNnLmRtcmNhdGUgPC0gbnJvdyhiZXRhX21hdCkKCiMjIyMjIDUuIE91dHB1dCBkYXRhc2V0cyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCnNhdmUoCiAgcGhlbm9fZGYsCiAgbmIucHJvYmVzLmRldGVjdFAsCiAgbmIucHJvYmVzLmRldGVjdFAuY2csCiAgbmIucHJvYmVzLmNnLmRtcmNhdGUsCiAgYmV0YV9tYXQsCiAgZmlsZSA9IHBhc3RlMChkYXRhLmRpci5wcm9iZXMucWMsICJiZXRhX0NHX1hZX1NOUGZpbHRlcmVkX21hdC5yZGEiKQopCmBgYAoKIyBOb3JtYWxpemF0aW9uCgotIFF1YW50aWxlIG5vcm1hbGl6YXRpb24gYW5kIEJNSVEgbm9ybWFsaXphdGlvbgoKSW5wdXQ6IAoKLSBiZXRhX0NHX1hZX1NOUGZpbHRlcmVkX21hdC5SRFMKLSBSR1NldC5SRFMKLSBwaGVub19kZi5SRFMKLSBmdWxsLmFubm90LlJEUwoKT3V0cHV0OiAKCi0gYnMuY3N2Ci0gcGhlbm9fZGYuUkRTCi0gUU5CTUlRLlJEUwoKYGBge1IgcWNTYW1wbGVzRGF0YX0KbG9hZChwYXN0ZTAoZGF0YS5kaXIucHJvYmVzLnFjLCAiYmV0YV9DR19YWV9TTlBmaWx0ZXJlZF9tYXQucmRhIikpCmBgYAoKCiMjIFF1YW50aWxlIG5vcm1hbGl6YXRpb24KCmBgYHtSLCBtZXNzYWdlID0gRkFMU0UsIHJlc3VsdHMgPSAnaGlkZSd9CmxpYnJhcnkobHVtaSkKYGBgCgoKYGBge1J9CmJldGFRTiA8LSBsdW1pTih4Lmx1bWkgPSBiZXRhX21hdCwgbWV0aG9kID0gInF1YW50aWxlIikKZGltKGJldGFRTikKYGBgCgojIyBCTUlRCgpgYGB7UiwgbWVzc2FnZSA9IEZBTFNFLCByZXN1bHRzID0gImhpZGUifQpsaWJyYXJ5KHdhdGVSbWVsb24pCmxpYnJhcnkoUlBNTSkKbGlicmFyeShzZXNhbWUpCmxpYnJhcnkoc2VzYW1lRGF0YSkKYGBgCgpgYGB7UiwgZXZhbCA9IEZBTFNFLCBpbmNsdWRlID0gRkFMU0V9CiMjIyBPcmRlciBhbm5vdGF0aW9uIGluIHRoZSBzYW1lIG9yZGVyIGFzIGJldGEgbWF0cml4CmFubm90VHlwZSA8LSBzZXNhbWVEYXRhR2V0KCJITTQ1MC5oZzE5Lm1hbmlmZXN0IikKYW5ub3RUeXBlJGRlc2lnblR5cGVOdW1lcmljIDwtIGlmZWxzZShhbm5vdFR5cGUkZGVzaWduVHlwZSA9PSAiSSIsMSwyKQoKIyMjIERlbnNpdHkgcGxvdCBmb3IgdHlwZSBJIGFuZCB0eXBlIElJIHByb2JlcwpsaWJyYXJ5KHNtKQoKYmV0YVFOQ29tcGxldGVDb2wxIDwtIGJldGFRTltjb21wbGV0ZS5jYXNlcyhiZXRhUU5bLDFdKSwgXQphbm5vdFR5cGVDb21wbGV0ZUNvbDEgPC0gYW5ub3RUeXBlW3Jvdy5uYW1lcyhiZXRhUU5Db21wbGV0ZUNvbDEpLCBdCgpzbS5kZW5zaXR5LmNvbXBhcmUoCiAgYmV0YVFOQ29tcGxldGVDb2wxWywxXSwKICBhbm5vdFR5cGVDb21wbGV0ZUNvbDEkZGVzaWduVHlwZU51bWVyaWMKKQoKdHlwZTEyIDwtIGFubm90VHlwZSRkZXNpZ25UeXBlTnVtZXJpY1ttYXRjaChyb3duYW1lcyhiZXRhUU4pLG5hbWVzKGFubm90VHlwZSkpXQpgYGAKYGBge1IsIGV2YWwgPSBGQUxTRX0KIyMjIEJNSVEKc2V0LnNlZWQgKDk0NikKZG9QYXJhbGxlbDo6cmVnaXN0ZXJEb1BhcmFsbGVsKGNvcmVzID0gOCkKYmV0YVFOX0JNSVEgPC0gcGx5cjo6YWFwbHkoCiAgYmV0YVFOLCAyLAogIGZ1bmN0aW9uKHgpewogICAgbm9ybV9scyA8LSBCTUlRKHgsIGRlc2lnbi52ID0gdHlwZTEyLCBwbG90cyA9IEZBTFNFKQogICAgcmV0dXJuIChub3JtX2xzJG5iZXRhKQogIH0sLnByb2dyZXNzID0gInRpbWUiLC5wYXJhbGxlbCA9IFRSVUUKKSAlPiUgdCgpCmNvbG5hbWVzKGJldGFRTl9CTUlRKSA8LSBzdWJzdHIoY29sbmFtZXMoYmV0YVFOX0JNSVEpLDEsc3RyaW5ncjo6c3RyX2xlbmd0aChwaGVub19kZiRzYW1wbGUpICU+JSB1bmlxdWUpCgpzYXZlKGJldGFRTl9CTUlRLCBwaGVub19kZiwgZmlsZSA9IHBhc3RlMChkYXRhLmRpci5wcm9iZXMubm9ybWFsaXphdGlvbiwgIkdBU1BBUk9OSV9RTkJNSVEucmRhIikpCmBgYAoKYGBge1IsIGluY2x1ZGUgPSBGQUxTRX0KbG9hZChwYXN0ZTAoZGF0YS5kaXIucHJvYmVzLm5vcm1hbGl6YXRpb24sICJHQVNQQVJPTklfUU5CTUlRLnJkYSIpKQpgYGAKCmBgYHtSLCBldmFsID0gRkFMU0UsIGluY2x1ZGUgPSBGQUxTRX0KIyMjIyMgNi4gRGVuc2l0eSBwbG90IGFmdGVyIG5vcm1hbGl6YXRpb24gYW5kIEJNSVEgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKbWF0ZGVuc2l0eShvYmplY3QgPSBiZXRhUU5fQk1JUSwKICAgICAgICAgICBncm91cEZhY3RvciA9ICBwaGVub19kZiRzdGFnZSAlPiUgIGFzLmZhY3RvcigpLAogICAgICAgICAgIHhsYWIgPSAiICIsIAogICAgICAgICAgIHlsYWIgPSAiZGVuc2l0eSIsCiAgICAgICAgICAgbWFpbiA9ICJCZXRhIFZhbHVlcyIsIAogICAgICAgICAgIGJyZXdlci5uID0gOCwgCiAgICAgICAgICAgYnJld2VyLm5hbWUgPSAiRGFyazIiKQoKbGVnZW5kKCd0b3AnLAogICAgICAgcGFzdGUwKCJzdGFnZSAiLCBsZXZlbHMoIHBoZW5vX2RmJHN0YWdlICU+JSAgYXMuZmFjdG9yKCkpKSwKICAgICAgIGNvbCA9IGMoMTo3KSwgbHR5ID0gMSwgbHdkID0gMykKYGBgCgojIE91dGxpZXJzIGRldGVjdGlvbiAtIFBDQSBhbmFseXNpcwoKLSBTZWxlY3QgbW9zdCB2YXJpYWJsZSBwcm9iZXMgYW5kIHBlcmZvcm0gUENBIGFuYWx5c2lzCgpJbnB1dDogCgotIEdBU1BBUk9OSV9RTkJNSVEucmRzCi0gcGhlbm9fZGYuUkRTCgpPdXRwdXQ6IAoKLSBHQVNQQVJPTklfUENzX3VzaW5nQmV0YXMuY3N2LCAKLSBQQ0EgcGxvdHMKLSBHQVNQQVJPTklfUU5CTUlRX1BDZmlsdGVyZWQuUkRTCi0gcGhlbm9fZGYuUkRTCgoKYGBge1J9CiMgcGxvdFBDQSBhbmQgT3JkZXJEYXRhQnlTZCBmdW5jdGlvbnMKZGV2dG9vbHM6OnNvdXJjZV9naXN0KCJodHRwczovL2dpc3QuZ2l0aHViLmNvbS90aWFnb2Noc3QvZDNhN2IxNjM5YWNmNjAzOTE2YzMxNWQyM2IxZWZiM2UiKQpgYGAKCmBgYHtSfQojIyMgbWVyZ2UgaW4gZ3JvdXAgaW5mbwojIyBhZGQgY2VudGVyIGFuZCBzY2FsZQojIyBjb21wYXJlIE0gdmFsdWVzIHZzLiBiZXRhIHZhbHVlcwojIyB3aXRoIGFuZCB3aXRob3V0IGNlbnRlciAvIHNjYWxlCgojIyMjIyAwLkltcG9ydCBkYXRhc2V0cyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwpsb2FkKHBhc3RlMChkYXRhLmRpci5wcm9iZXMubm9ybWFsaXphdGlvbiwgIkdBU1BBUk9OSV9RTkJNSVEucmRhIikpCmlkZW50aWNhbChjb2xuYW1lcyhiZXRhUU5fQk1JUSksIHBoZW5vX2RmJHNhbXBsZSkKCiMjIyB0cmFuc2Zvcm0gdG8gbSB2YWx1ZXMKbXZhbHVlX21hdCA8LSBsb2cyKGJldGFRTl9CTUlRIC8gKDEgLSBiZXRhUU5fQk1JUSkpICNkaW06IDQzNzcxMyAxNDIKCnBoZW5vX2RmIDwtIHN1YnNldChwaGVub19kZiwgcGhlbm9fZGYkc2FtcGxlICVpbiUgY29sbmFtZXMoYmV0YVFOX0JNSVEpKSAjZGltOiAxNDIgNwoKIyBib3RoX2RmJHN0YWdlIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGJvdGhfZGYkc3RhZ2UpKQoKcGhlbm9fZGYkc3RhZ2UzIDwtIHBoZW5vX2RmJHN0YWdlCnBoZW5vX2RmJHN0YWdlM1twaGVub19kZiRzdGFnZSA8PSAyXSA8LSAnMC0yJwpwaGVub19kZiRzdGFnZTNbcGhlbm9fZGYkc3RhZ2UgPiAyICYgcGhlbm9fZGYkc3RhZ2UgPCA1XSA8LSAnMy00JwpwaGVub19kZiRzdGFnZTNbcGhlbm9fZGYkc3RhZ2UgPj0gNV0gPC0gJzUtNicKCgojIyMjIyAxLk9yZGVyIG1hdHJpeCBieSBtb3N0IHZhcmlhYmxlIHByb2JlcyBvbiB0b3AgIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKYmV0YU9yZF9tYXQgPC0gT3JkZXJEYXRhQnlTZChiZXRhUU5fQk1JUSkgI2RpbTogMzkxNDgyIDE0MgoKbU9yZF9tYXQgPC0gT3JkZXJEYXRhQnlTZChtdmFsdWVfbWF0KSAgI2RpbTogMzkxNDgyIDE0MgoKYmV0YU9yZF9tYXRQbG90IDwtIGJldGFPcmRfbWF0WywgcGhlbm9fZGYkc2FtcGxlXSAjZGltOiAzOTE0ODIgMTQyCm1PcmRfbWF0UGxvdCA8LSBtT3JkX21hdFssIHBoZW5vX2RmJHNhbXBsZV0gICAgICAgI2RpbTogMzkxNDgyIDE0MgppZGVudGljYWwocGhlbm9fZGYkc2FtcGxlLCBjb2xuYW1lcyhiZXRhT3JkX21hdFBsb3QpKQppZGVudGljYWwocGhlbm9fZGYkc2FtcGxlLCBjb2xuYW1lcyhtT3JkX21hdFBsb3QpKQoKZXhwU29ydGVkX21hdCA9IGJldGFPcmRfbWF0ICNkaW06IDM5MTQ4MiAxNDIKCnBjYSA8LSBwcmNvbXAodChleHBTb3J0ZWRfbWF0WzE6NTAwMDAsIF0pLAogICAgICAgICAgICAgIGNlbnRlciA9IFRSVUUsCiAgICAgICAgICAgICAgc2NhbGUgPSBUUlVFKQoKZCA8LSBkYXRhLmZyYW1lKFBDMSA9IHBjYSR4WywgMV0sIFBDMiA9IHBjYSR4WywgMl0pCgptZWFuUEMxIDwtIG1lYW4gKGQkUEMxKQpzZFBDMSAgIDwtIHNkIChkJFBDMSkKCm1lYW5QQzIgPC0gbWVhbiAoZCRQQzIpCnNkUEMyICAgPC0gc2QgKGQkUEMyKQoKb3V0M3NkUEMxXzEgPC0gbWVhblBDMSAtIDMgKiBzZFBDMQpvdXQzc2RQQzFfMiA8LSBtZWFuUEMxICsgMyAqIHNkUEMxCgpvdXQzc2RQQzJfMSA8LSBtZWFuUEMyIC0gMyAqIHNkUEMyCm91dDNzZFBDMl8yIDwtIG1lYW5QQzIgKyAzICogc2RQQzIKCmQkb3V0bGllcl9QQzFbZCRQQzEgPj0gb3V0M3NkUEMxXzEgJiBkJFBDMSA8PSBvdXQzc2RQQzFfMl0gPC0gMApkJG91dGxpZXJfUEMxW2QkUEMxIDwgb3V0M3NkUEMxXzEgfCBkJFBDMSA+IG91dDNzZFBDMV8yXSA8LSAxCgpkJG91dGxpZXJfUEMyW2QkUEMyID49IG91dDNzZFBDMl8xICYgZCRQQzIgPD0gb3V0M3NkUEMyXzJdIDwtIDAKZCRvdXRsaWVyX1BDMltkJFBDMiA8IG91dDNzZFBDMl8xIHwgZCRQQzIgPiBvdXQzc2RQQzJfMl0gPC0gMQoKcmVhZHI6OndyaXRlX2NzdihkLCBwYXN0ZTAoZGF0YS5kaXIucGNhLCAiR0FTUEFST05JX1BDc191c2luZ0JldGFzLmNzdiIpKQpgYGAKCmBgYHtSLCBldmFsID0gRkFMU0UsIGluY2x1ZGUgPSBGQUxTRX0KIyMjIyMgMi5QQ0EgcGxvdCAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdncmVwZWwpCgojIyMgYmV0YSB2YWx1ZXMKYnlTdGFnZSA8LSBwbG90UENBKAogIGRhdGFzZXQgPSAiR2FzcGFyb25pOiBiZXRhIHZhbHVlcyIsCiAgZXhwU29ydGVkX21hdCA9IGJldGFPcmRfbWF0LAogIHBoZW5vID0gcGhlbm9fZGYsCiAgZ3JvdXBfY2hhciA9ICJzdGFnZTMiLAogIG50b3AgPSA1MDAwMCwKICBjZW50ZXIgPSBUUlVFLAogIHNjYWxlID0gVFJVRQopCgpieVNleCA8LSBwbG90UENBKAogIGRhdGFzZXQgPSAiR2FzcGFyb25pOiBiZXRhIHZhbHVlcyIsCiAgZXhwU29ydGVkX21hdCA9IGJldGFPcmRfbWF0LAogIHBoZW5vID0gcGhlbm9fZGYsCiAgZ3JvdXBfY2hhciA9ICJzZXgiLAogIG50b3AgPSA1MDAwMCwKICBjZW50ZXIgPSBUUlVFLAogIHNjYWxlID0gVFJVRQopCgoKIyMjIyBNIHZhbHVlcwpieVN0YWdlIDwtIHBsb3RQQ0EoCiAgZGF0YXNldCA9ICJHYXNwYXJvbmk6IE0gdmFsdWVzIiwKICBleHBTb3J0ZWRfbWF0ID0gbU9yZF9tYXQsCiAgcGhlbm8gPSBwaGVub19kZiwKICBncm91cF9jaGFyID0gInN0YWdlMyIsCiAgbnRvcCA9IDUwMDAwLAogIGNlbnRlciA9IFRSVUUsCiAgc2NhbGUgPSBUUlVFCikKCmJ5U2V4IDwtIHBsb3RQQ0EoCiAgZGF0YXNldCA9ICJHYXNwYXJvbmk6IE0gdmFsdWVzIiwKICBleHBTb3J0ZWRfbWF0ID0gbU9yZF9tYXQsCiAgcGhlbm8gPSBwaGVub19kZiwKICBncm91cF9jaGFyID0gInNleCIsCiAgbnRvcCA9IDUwMDAwLAogIGNlbnRlciA9IFRSVUUsCiAgc2NhbGUgPSBUUlVFCikKYGBgCgoKYGBge1J9CiMjIyMjIDIuRmlsdGVyIHNhbXBsZXMgYnkgUENBLCBzYXZlIGZpbGVzICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpub091dGxpZXJzIDwtIGRbd2hpY2goZCRvdXRsaWVyX1BDMSA9PSAwICYgZCRvdXRsaWVyX1BDMiA9PSAwKSwgXQpiZXRhUU5fQk1JUV9QQ2ZpbHRlcmVkIDwtIGJldGFRTl9CTUlRWywgcm93bmFtZXMobm9PdXRsaWVycyldICNkaW06IDQzMzY1NiA1OQpzYXZlUkRTKGJldGFRTl9CTUlRX1BDZmlsdGVyZWQsIHBhc3RlMChkYXRhLmRpci5wY2EsICJHYXNwYXJvbmlfUU5CTUlRX1BDZmlsdGVyZWQuUkRTIikpCgpwaGVub19kZiA8LSBwaGVub19kZltwaGVub19kZiRzYW1wbGUgJWluJSByb3duYW1lcyhub091dGxpZXJzKSxdICNkaW06IDU5IDYKc2F2ZVJEUyhwaGVub19kZiwgcGFzdGUwKGRhdGEuZGlyLnBjYSwgInBoZW5vX2RmLlJEUyIpKQpgYGAKCiMgU3VtbWFyeSBhZnRlciBRQyBzdGVwcwoKIyMgRGF0YSBhbmQgbWV0YWRhdGEKYGBge1J9Cm5iLnNhbXBsZXMud2l0aC5jbGluaWNhbC5hZnRlci5wY2EgPC0gbmNvbChiZXRhUU5fQk1JUV9QQ2ZpbHRlcmVkKQpkaW0oYmV0YVFOX0JNSVFfUENmaWx0ZXJlZCkKZGltKHBoZW5vX2RmKQpwaGVub19kZiAlPiUgCiAgRFQ6OmRhdGF0YWJsZShmaWx0ZXIgPSAndG9wJywKICAgICAgICAgICAgICAgIHN0eWxlID0gImJvb3RzdHJhcCIsCiAgICAgICAgICAgICAgICBleHRlbnNpb25zID0gJ0J1dHRvbnMnLAogICAgICAgICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2Nyb2xsWCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tID0gJ0JmcnRpcCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zID0gSSgnY29sdmlzJyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlzID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gMTApLCAKICAgICAgICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgICBjYXB0aW9uID0gIlNhbXBsZXMgbWV0YWRhdGEiKQpgYGAKCmBgYHtSLCBldmFsID0gRkFMU0UsIGluY2x1ZGUgPSBGQUxTRX0KZ2dwdWJyOjpnZ2hpc3RvZ3JhbShkYXRhID0gcGhlbm9fZGYsIHggPSAic3RhZ2UiLGJpbnMgPSA4KQpnZ3B1YnI6OmdnaGlzdG9ncmFtKGRhdGEgPSBwaGVub19kZiwgeCA9ICJzdGFnZSIsYmlucyA9IDgsZmFjZXQuYnkgPSAic2V4IixmaWxsID0gInNleCIpCmdncHVicjo6Z2doaXN0b2dyYW0oZGF0YSA9IHBoZW5vX2RmLCB4ID0gImFnZS5icmFpbiIsYmlucyA9IDIwKQpnZ3B1YnI6OmdnaGlzdG9ncmFtKGRhdGEgPSBwaGVub19kZiwgeCA9ICJhZ2UuYnJhaW4iLGJpbnMgPSAyMCxmaWxsID0gInNleCIsZmFjZXQuYnkgPSAic2V4IikKYGBgCgoKIyMgTnVtYmVycyBvZiBzYW1wbGVzIGFuZCBwcm9iZXMgcmVtb3ZlZCBpbiBlYWNoIHN0ZXAKCmBgYHtSfQpkZi5zYW1wbGVzIDwtIGRhdGEuZnJhbWUoIk51bWJlciBvZiBzYW1wbGVzIiA9ICBjKG5iLnNhbXBsZXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5iLnNhbXBsZXMuYmMuZmlsdGVyZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmIuc2FtcGxlcy53aXRoLmNsaW5pY2FsLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYi5zYW1wbGVzLndpdGguY2xpbmljYWwuYWZ0ZXIucGNhKSwKICAgICAgICAgICAgICAgICAgICAgICAgICJEZXNjcmlwdGlvbiIgPSBjKCJ0b3RhbCBudW1iZXIgb2Ygc2FtcGxlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic2FtcGxlcyB3aXRoIGJpc3VsZmF0ZSBjb252ZXJzaW9uID4gODgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInNhbXBsZXMgd2l0aCBjbGluaWNhbCBkYXRhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTYW1wbGVzIGFmdGVyIFBDQSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIkRpZmZlcmVuY2UiID0gYygiLSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5iLnNhbXBsZXMuYmMuZmlsdGVyZWQgLSBuYi5zYW1wbGVzICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmIuc2FtcGxlcy53aXRoLmNsaW5pY2FsIC0gbmIuc2FtcGxlcy5iYy5maWx0ZXJlZCAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5iLnNhbXBsZXMud2l0aC5jbGluaWNhbC5hZnRlci5wY2EgLSBuYi5zYW1wbGVzLndpdGguY2xpbmljYWwpCikgICAgCmRmLnNhbXBsZXMgICAgICAgICAgIAoKIyBDcmVhdGUgc3VtbWFyeSB0YWJsZQpkZi5wcm9iZXMgPC0gZGF0YS5mcmFtZSgiTnVtYmVyIG9mIHByb2JlcyIgPSBjKG5iLnByb2JlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYi5wcm9iZXMuZGV0ZWN0UCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmIucHJvYmVzLmRldGVjdFAuY2csCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmIucHJvYmVzLmNnLmRtcmNhdGUpLAogICAgICAgICAgICAgICAgICAgICAgICAiRGVzY3JpcHRpb24iID0gYygidG90YWwgbnVtYmVyIG9mIHByb2JlcyBpbiByYXcgZGF0YSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJkZXRlY3Rpb24gUCA8IDAuMDEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAib25seSBwcm9iZXMgdGhhdCBzdGFydCB3aXRoIGNnIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRNUmNhdGUiKSwKICAgICAgICAgICAgICAgICAgICAgICAgIkRpZmZlcmVuY2UiID0gYygiLSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmIucHJvYmVzLmRldGVjdFAgLSBuYi5wcm9iZXMgLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5iLnByb2Jlcy5kZXRlY3RQLmNnIC0gbmIucHJvYmVzLmRldGVjdFAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmIucHJvYmVzLmNnLmRtcmNhdGUgLSBuYi5wcm9iZXMuZGV0ZWN0UC5jZykKKQpkZi5wcm9iZXMKCnNhdmUoZGYuc2FtcGxlcyxkZi5wcm9iZXMsZmlsZSA9IGZpbGUucGF0aChkYXRhLmRpci50YWJsZSwgIkdBU1BBUk9OSV90YWJsZS5yZGEiKSkKYGBgCgojIENvbXB1dGUgbmV1cm9uIHByb3BvcnRpb24KCkRhdGEgZnJvbSAgaHR0cHM6Ly93d3cudGFuZGZvbmxpbmUuY29tL2RvaS9mdWxsLzEwLjQxNjEvZXBpLjIzOTI0CgotIElucHV0OiBHYXNwYXJvbmlfUU5CTUlRX1BDZmlsdGVyZWQuUkRTLCBwaGVub19kZi5SRFMKCi0gT3V0cHV0OiBwaGVub193aXRoTmV1cm9uUHJvcF9kZi5SRFMKCmBgYHtSfQpvYmplY3RzIDwtIGxvYWQoIi4uLy4uL0NFVC9DRVRTX0ltYWdlLlJEYXRhIikKb2JqZWN0cwpgYGAKCiMjIEdldCByZWZlcmVuY2UgcHJvZmlsZSBmcm9tIENhdWNhc2lvbnMgKyBjb250cm9scyAKYGBge1J9CmlkeCA8LSBsaXN0KAogIGNvbnRyb2xOZXVyb24gPSBwZEJyYWluJGNlbGx0eXBlID09ICJOIiAmIHBkQnJhaW4kZGlhZyA9PSAiQ29udHJvbCIgJiBwZEJyYWluJGV0aG5pY2l0eSA9PSAiQ2F1Y2FzaWFuIiwKICBjb250cm9sR2xpYSAgID0gcGRCcmFpbiRjZWxsdHlwZSA9PSAiRyIgJiBwZEJyYWluJGRpYWcgPT0gIkNvbnRyb2wiICYgcGRCcmFpbiRldGhuaWNpdHkgPT0gIkNhdWNhc2lhbiIKKQoKcmVmUHJvZmlsZSA8LSBnZXRSZWZlcmVuY2UoYnJhaW4sIGlkeCkKCgojIyMjIyAyLiBFc3RpbWF0ZSBwcm9wb3J0aW9ucyBvZiBuZXVyb25zIGluIFBGQyBzYW1wbGVzICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyMjIExpbWl0IHRvIDEwLDAwMCBjcGdzIGluIHRoZSByZWZQcm9maWxlIGRhdGFzZXQKcGZjIDwtIHJlYWRSRFMocGFzdGUwKGRhdGEuZGlyLnBjYSwgIkdhc3Bhcm9uaV9RTkJNSVFfUENmaWx0ZXJlZC5SRFMiKSkgI2RpbTogNDMzNjU2IDU5CgpzZWxlY3RlZCA8LSByb3duYW1lcyhwZmMpICVpbiUgcm93bmFtZXMocmVmUHJvZmlsZSkKCnBmYy5yZWZjcGdzIDwtIHBmY1tzZWxlY3RlZCwgXSAKCiMjIyBFc3RpbWF0ZSBwcm9wb3J0aW9uIG9mIG5ldXJvbnMKcHJvcCA8LSBkYXRhLmZyYW1lKGVzdFByb3BvcnRpb24ocGZjLnJlZmNwZ3MsIHByb2ZpbGUgPSByZWZQcm9maWxlKSkKY29sbmFtZXMocHJvcCkgPC0gInByb3AubmV1cm9uIgoKIyMjIyMgMy4gTWVyZ2UgcGZjLnJlZmNwZ3Mgd2l0aCBwaGVub3R5cGUgZmlsZSAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKcGhlbm8gPC0gcmVhZFJEUyhwYXN0ZTAoZGF0YS5kaXIucGNhLCAicGhlbm9fZGYuUkRTIikpCgpwaGVub19maW5hbCA8LSBtZXJnZSgKICBwaGVubywKICBwcm9wLAogIGJ5LnggPSAic2FtcGxlIiwKICBieS55ID0gInJvdy5uYW1lcyIKKQoKc2F2ZVJEUyhwaGVub19maW5hbCwgcGFzdGUwKGRhdGEuZGlyLm5ldXJvbiwgInBoZW5vX3dpdGhOZXVyb25Qcm9wX2RmLlJEUyIpKQpgYGAKCiMgTGluZWFyIHJlZ3Jlc3Npb24gYnkgY3BncyBNZXRoeWxhdGlvbiAKCklucHV0OiAKCi0gR2FzcGFyb25pX1FOQk1JUV9QQ2ZpbHRlcmVkLlJEUywKLSBwaGVubzU5X3dpdGhOZXVyb25Qcm9wX2RmLlJEUwoKT3V0cHV0OgoKLSBHYXNwYXJvbmlfc2luZ2xlX2NwZ19wVmFsX2RmLmNzdgoKIyMgSW1wb3J0IGRhdGFzZXRzCgpgYGB7Un0KYmV0YV9tYXQgPC0gcmVhZFJEUyhwYXN0ZTAoZGF0YS5kaXIucGNhLCAiR2FzcGFyb25pX1FOQk1JUV9QQ2ZpbHRlcmVkLlJEUyIpKSAKcGhlbm9fZGYgPC0gcmVhZFJEUyhwYXN0ZTAoZGF0YS5kaXIubmV1cm9uLCAicGhlbm9fd2l0aE5ldXJvblByb3BfZGYuUkRTIikpIApgYGAKCiMjIFRlc3QgYWxsIGNwZ3MKCmBgYHtSLCBldmFsID0gVFJVRX0KIyMjIENvbXB1dGUgTSB2YWx1ZXMKbXZhbF9tYXQgPC0gbG9nMihiZXRhX21hdCAvICgxIC0gYmV0YV9tYXQpKQoKcGhlbm9fZGYkU2FtcGxlIDwtIHBoZW5vX2RmJHNhbXBsZQoKaWRlbnRpY2FsKHBoZW5vX2RmJFNhbXBsZSwgY29sbmFtZXMobXZhbF9tYXQpKQoKcGhlbm9fZGYkc2V4IDwtIGFzLmZhY3RvcihwaGVub19kZiRzZXgpCnBoZW5vX2RmJHNsaWRlIDwtIGFzLmZhY3RvcihwaGVub19kZiRzbGlkZSkKIyBJZiByb3NtYXAgY29ob3J0LCBkb24ndCBmb3JnZXQgYmF0Y2ggZWZmZWN0CgpzdHIocGhlbm9fZGYpCgppcyhwaGVub19kZiRzdGFnZSwibnVtZXJpYyIpCmlzKHBoZW5vX2RmJGFnZS5icmFpbiwibnVtZXJpYyIpCmlzKHBoZW5vX2RmJHByb3AubmV1cm9uLCJudW1lcmljIikKYGBgCgoKYGBge1IsIGV2YWwgPSBGQUxTRX0KcHJlZGljdG9yc19jaGFyIDwtICJzdGFnZSIKY292YXJpYXRlc19jaGFyIDwtIGMoImFnZS5icmFpbiIsICJzZXgiLCAicHJvcC5uZXVyb24iLCAic2xpZGUiKQoKCmRvUGFyYWxsZWw6OnJlZ2lzdGVyRG9QYXJhbGxlbChjb3JlcyA9IHBhcmFsbGVsOjpkZXRlY3RDb3JlcygpLzIpCmRldnRvb2xzOjpzb3VyY2VfZ2lzdCgiaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vdGlhZ29jaHN0L2QzYTdiMTYzOWFjZjYwMzkxNmMzMTVkMjNiMWVmYjNlIikKCnJlc3VsdHNfb3JkZXJlZF9kZiA8LSBwbHlyOjphZHBseShtdmFsX21hdCwxLCBmdW5jdGlvbihyb3cpewogIAogIHN1bU9uZVJlZ2lvbl9kZiA8LSBkYXRhLmZyYW1lKHQocm93KSkKICAKICByZXN1bHQgPC0gVGVzdFNpbmdsZVJlZ2lvbigKICAgIHByZWRpY3RvcnNfY2hhciA9IHByZWRpY3RvcnNfY2hhciwKICAgIGNvdmFyaWF0ZXNfY2hhciA9IGNvdmFyaWF0ZXNfY2hhciwKICAgIHBoZW5vX2RmID0gcGhlbm9fZGYsCiAgICBzdW1PbmVSZWdpb25fZGYgPSBzdW1PbmVSZWdpb25fZGYKICApCiAgcmVzdWx0Cn0sIC5wcm9ncmVzcyA9ICJ0aW1lIiwucGFyYWxsZWwgPSBUUlVFLC5pZCA9ICJjcGciKQpjb2xuYW1lcyhyZXN1bHRzX29yZGVyZWRfZGYpWzFdIDwtICJjcGciCgppZGVudGljYWwocm93Lm5hbWVzKG12YWxfbWF0KSwgcmVzdWx0c19vcmRlcmVkX2RmJGNwZyAlPiUgYXMuY2hhcmFjdGVyKCkpCgpyZXN1bHRzX29yZGVyZWRfZGYkZmRyIDwtIHAuYWRqdXN0KAogICAgcmVzdWx0c19vcmRlcmVkX2RmJHBWYWx1ZSwKICAgIG1ldGhvZCA9ICJmZHIiCikKCndyaXRlLmNzdigKICByZXN1bHRzX29yZGVyZWRfZGYsCiAgcGFzdGUwKGRhdGEuZGlyLnNpbmdsZS5jcGcucHZhbCwgIkdhc3Bhcm9uaV9zaW5nbGVfY3BnX3BWYWxfZGYuY3N2IiksCiAgcm93Lm5hbWVzID0gRkFMU0UKKQpgYGAKCmBgYHtSfQpyZXN1bHRzX29yZGVyZWRfZGYgPC0gcmVhZHI6OnJlYWRfY3N2KAogIHBhc3RlMChkYXRhLmRpci5zaW5nbGUuY3BnLnB2YWwsICJHYXNwYXJvbmlfc2luZ2xlX2NwZ19wVmFsX2RmLmNzdiIpLAogIGNvbF90eXBlcyA9IHJlYWRyOjpjb2xzKCkpCnJlc3VsdHNfb3JkZXJlZF9kZgpgYGAKCgojIExpbmVhciByZWdyZXNzaW9uIGJ5IHJlZ2lvbnMgbWVkaWFuIE1ldGh5bGF0aW9uIAoKIyMgUmVzaWR1YWxzIGNvbnRyb2wgYW5kIGNvTWV0aHlsYXRlZCBSZWdpb25zCgoxLiBUYWtlIHJlc2lkdWFscwoyLiBGaW5kIGNvLW1ldGh5bGF0ZWQgcmVnaW9ucwoKSW5wdXQ6IAoKLSBRTkJNSVFfUENmaWx0ZXJlZAotIHBoZW5vX3dpdGhOZXVyb25Qcm9wX2RmCgpPdXRwdXQ6IAoKLSBRTkJNSVFfUENmaWx0ZXJlZF9tdmFsUmVzaWR1YWxzCi0gcmVzaWR1YWxzX2NvbWV0aF9scwoKIyMjIFJlc2lkdWFscwoKYGBge1IsIGV2YWwgPSBGQUxTRX0KIyMjIyMgMS4gSW1wb3J0IGRhdGFzZXRzICMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKYmV0YV9tYXQgPC0gcmVhZFJEUyhwYXN0ZTAoZGF0YS5kaXIucGNhLCAiR2FzcGFyb25pX1FOQk1JUV9QQ2ZpbHRlcmVkLlJEUyIpKSAjZGltOjQzMzY1NiA1OQpwaGVub19kZiA8LSByZWFkUkRTKHBhc3RlMChkYXRhLmRpci5uZXVyb24sICJwaGVub193aXRoTmV1cm9uUHJvcF9kZi5SRFMiKSkgI2RpbTo1OSA3CgojIyMgQ29tcHV0ZSBNIHZhbHVlcwptdmFsdWVfbWF0IDwtIGxvZzIoYmV0YV9tYXQgLyAoMSAtIGJldGFfbWF0KSkKCiMjIyBSZW9yZGVyIHNhbXBsZXMgYmFzZWQgb24gcGhlbm9fZGYKbXZhbHVlX21hdCA8LSBtdmFsdWVfbWF0WywgcGhlbm9fZGYkc2FtcGxlXQoKaWRlbnRpY2FsKGNvbG5hbWVzKG12YWx1ZV9tYXQpLCAgcGhlbm9fZGYkc2FtcGxlKQoKIyMjIFRha2UgcmVzaWR1YWxzCmxtRiA8LSBmdW5jdGlvbihtdmFsKXsKICBmaXRFIDwtIGxtKAogICAgYXMubnVtZXJpYyhtdmFsKSB+IGFnZS5icmFpbiArIHNleCArIHByb3AubmV1cm9uICsgYXMuY2hhcmFjdGVyKHNsaWRlKSwgI2FkZCBiYXRjaCBpZiByb3NtYXAKICAgIGRhdGEgPSBwaGVub19kZiwKICAgIG5hLmFjdGlvbiA9IG5hLmV4Y2x1ZGUKICApCiAgcmVzaWR1YWxzIChmaXRFKQp9CmRvUGFyYWxsZWw6OnJlZ2lzdGVyRG9QYXJhbGxlbChjb3JlcyA9IDQpCnJlc2lkIDwtIHBseXI6OmFkcGx5KG12YWx1ZV9tYXQsMSwuZnVuID0gbG1GLC5wcm9ncmVzcyA9ICJ0aW1lIiwucGFyYWxsZWwgPSBUUlVFKQpyb3duYW1lcyhyZXNpZCkgPC0gcmVzaWRbLDFdCnJlc2lkWywxXSA8LSBOVUxMCmNvbG5hbWVzKHJlc2lkKSA8LSBjb2xuYW1lcyhtdmFsdWVfbWF0KQpkaW0ocmVzaWQpCmRpbShtdmFsdWVfbWF0KQoKIyMjIFNhdmUgZGF0YXNldApzYXZlUkRTKAogIHJlc2lkLAogIHBhc3RlMChkYXRhLmRpci5yZXNpZHVhbHMsICJHYXNwYXJvbmlfUU5CTUlRX1BDZmlsdGVyZWRfbXZhbFJlc2lkdWFscy5SRFMiKQopCmBgYAoKIyMjIEZpbmQgY28tbWV0aHlsYXRlZCByZWdpb25zCgpgYGB7UiwgZXZhbCA9IEZBTFNFfQojIyMgSW1wb3J0IGRhdGFzZXRzCm12YWx1ZV9yZXNpZHVhbHNfbWF0IDwtIHJlYWRSRFMoCiAgcGFzdGUwKGRhdGEuZGlyLnJlc2lkdWFscywgIkdhc3Bhcm9uaV9RTkJNSVFfUENmaWx0ZXJlZF9tdmFsUmVzaWR1YWxzLlJEUyIpCikKCiMjIyBDYWxsIGluIGZ1bmN0aW9ucwpsaWJyYXJ5KGNvTWV0aERNUikKbGlicmFyeShCaW9jUGFyYWxsZWwpCgpwcm9iZXMuY2x1c3Rlci5hbGwgPC0gY29NZXRoRE1SOjpnZXRQcmVkZWZpbmVkQ2x1c3RlcihhcnJheVR5cGUgPSAiNDUwayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJUeXBlID0gInJlZ2lvbnMiKQoKbmNvcmVzIDwtIHBhcmFsbGVsOjpkZXRlY3RDb3JlcygpLzIKIyMjIEZpbmQgY28tbWV0aHlsYXRlZCBjbHVzdGVycwpjb01ldGhfbHMgPC0gQ29NZXRoQWxsUmVnaW9ucygKICBkbmFtID0gbXZhbHVlX3Jlc2lkdWFsc19tYXQsICAgICAgCiAgYmV0YVRvTSA9IEZBTFNFLCAgICAgICAgICAgICAgICAgICAKICBDcEdzX2xzID0gcHJvYmVzLmNsdXN0ZXIuYWxsLAogIGFycmF5VHlwZSA9ICI0NTBrIiwKICByRHJvcFRocmVzaF9udW0gPSAwLjQsCiAgbWluUGFpcndpc2VDb3JyID0gTlVMTCwKICBtZXRob2QgPSAic3BlYXJtYW4iLCAgICAgICAgICAgICAKICByZXR1cm5BbGxDcEdzID0gVFJVRSwgICAgICAgICAgICAgIAogIG91dHB1dCA9ICJhbGwiLAogIG5Db3Jlc19pbnQgPSBuY29yZXMsCiAgcHJvZ3Jlc3NiYXIgPSBGQUxTRQopCgpzYXZlUkRTKAogIGNvTWV0aF9scywKICBwYXN0ZTAoZGF0YS5kaXIucmVzaWR1YWxzLCJHYXNwYXJvbmlfcmVzaWR1YWxzX2NvbWV0aF9pbnB1dF9scy5SRFMiKQopCmBgYAoKIyMgTGluZWFyIHJlZ3Jlc3Npb24gYnkgcmVnaW9ucyBtZWRpYW4gTWV0aHlsYXRpb24gCgoxLiBDYWxjdWxhdGUgbWVkaWFucyBieSBjbHVzdGVyIGFuZCBzYW1wbGUKMi4gbGluZWFyIHJlZ3Jlc3Npb24KCklucHV0OiAKCi0gUU5CTUlRX1BDZmlsdGVyZWQsCi0gcGhlbm9fd2l0aE5ldXJvblByb3BfZGYKLSByZXNpZHVhbHNfY29tZXRoX2lucHV0X2xzCgpPdXRwdXQ6IAoKLSBpbmZvX2RmCi0gbWVkaWFuc012YWxfZGYKLSBsaW5lYXJfZGZfYWdpbmcKCiMjIyBDYWxjdWxhdGUgbWVkaWFucyBieSBjbHVzdGVyIGFuZCBzYW1wbGUKCmBgYHtSLCBldmFsID0gRkFMU0V9CiMjIyBJbXBvcnQgZGF0YXNldHMKYmV0YV9tYXQgPC0gcmVhZFJEUyhwYXN0ZTAoZGF0YS5kaXIucGNhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiR2FzcGFyb25pX1FOQk1JUV9QQ2ZpbHRlcmVkLlJEUyIpKQpwaGVub19kZiA8LSByZWFkUkRTKHBhc3RlMChkYXRhLmRpci5uZXVyb24sICJwaGVub193aXRoTmV1cm9uUHJvcF9kZi5SRFMiKSkKbXZhbF9tYXQgPC0gbG9nMihiZXRhX21hdCAvICgxIC0gYmV0YV9tYXQpKSAlPiUgYXMubWF0cml4KCkKY29NZXRoX2xzIDwtIHJlYWRSRFMoCiAgcGFzdGUwKGRhdGEuZGlyLnJlc2lkdWFscywgIkdhc3Bhcm9uaV9yZXNpZHVhbHNfY29tZXRoX2lucHV0X2xzLlJEUyIpCikKCiMjIyBDcmVhdGUgaW5mbyBkYXRhc2V0CmlucHV0X2NvbWV0aCA8LSBkYXRhLmZyYW1lKAogIGlucHV0UmVnaW9uID0gY29NZXRoX2xzJGlucHV0UmVnaW9uX2NociwKICBuQ29NZXRoUmVnaW9uID0gY29NZXRoX2xzJG5Db01ldGhSZWdpb25zX251bSwKICBjb01ldGhSZWdpb24gPSBuYW1lcyhjb01ldGhfbHMkY29NZXRoX2xzKSwKICBuQ3BHcyA9IHVubGlzdChsYXBwbHkoY29NZXRoX2xzJGNvTWV0aF9scywgbGVuZ3RoKSwgdXNlLm5hbWVzID0gRkFMU0UpLAogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQopCgppbnB1dF9jb21ldGhfbm9kdXAgPC0gaW5wdXRfY29tZXRoWwogICFkdXBsaWNhdGVkKGlucHV0X2NvbWV0aCRjb01ldGhSZWdpb24pLAogIF0KY29sbmFtZXMoaW5wdXRfY29tZXRoX25vZHVwKSA8LSBjKAogIHBhc3RlMChjb2hvcnQsICJfaW5wdXRSZWdpb24iKSwKICBwYXN0ZTAoY29ob3J0LCAiX25Db01ldGhSZWdpb24iKSwKICBwYXN0ZTAoY29ob3J0LCAiX2NvTWV0aFJlZ2lvbiIpLAogIHBhc3RlMChjb2hvcnQsICJfbkNwR3MiKQopCgpzYXZlUkRTKAogIGlucHV0X2NvbWV0aF9ub2R1cCwKICBwYXN0ZTAoZGF0YS5kaXIubWVkaWFuLCBjb2hvcnQsIl9pbmZvX2RmLnJkcyIpCikKCiMjIyBUYWtlIG1lZGlhbiBvZiBwcm9iZXMgaW4gZWFjaCBjbHVzdGVyIGZvciBlYWNoIHNhbXBsZQpmaWxlbmFtZSA8LSAgcGFzdGUwKHBhc3RlMChkYXRhLmRpci5tZWRpYW4sIGNvaG9ydCwgIl9tZWRpYW5zTXZhbF9kZi5yZHMiKSkKbGlicmFyeShyb2J1c3RiYXNlKQptdmFsX21hdCA8LSBtdmFsX21hdFtyb3duYW1lcyhtdmFsX21hdCkgJWluJSB1bmxpc3QoY29NZXRoX2xzJGNvTWV0aF9scyksXQppZighZmlsZS5leGlzdHMoZmlsZW5hbWUpKXsKICBtZWRpYW5NdmFsLmRmIDwtIHBseXI6OmxkcGx5KAogICAgY29NZXRoX2xzJGNvTWV0aF9sc1shZHVwbGljYXRlZChuYW1lcyhjb01ldGhfbHMkY29NZXRoX2xzKSldLAogICAgZnVuY3Rpb24ocHJvYmVzKXsKICAgICAgY29sTWVkaWFucyhtdmFsX21hdFthcy5jaGFyYWN0ZXIocHJvYmVzKSxdLCBuYS5ybSA9IFRSVUUpCiAgICB9LAogICAgLnByb2dyZXNzID0gInRpbWUiCiAgKQogIG1lZGlhbk12YWwuZGYkLmlkIDwtIE5VTEwKICBjb2xuYW1lcyhtZWRpYW5NdmFsLmRmKSA8LSBjb2xuYW1lcyhtdmFsX21hdCkKICBzYXZlUkRTKG1lZGlhbk12YWwuZGYsIGZpbGUgPSBmaWxlbmFtZSkKfSBlbHNlIHsKICBtZWRpYW5NdmFsLmRmIDwtIHJlYWRSRFMoZmlsZW5hbWUpCn0KYGBgCgojIyMgVGVzdCBhbGwgcmVnaW9ucyAtLSBsaW5lYXIgcmVncmVzc2lvbnMKCmBgYHtSLCBldmFsID0gVFJVRX0KIyMjIEltcG9ydCBkYXRhc2V0cwpjb2hvcnQgPC0gIkdhc3Bhcm9uaSIKaW5mb19kZiA8LSByZWFkUkRTKGRpcihkYXRhLmRpci5tZWRpYW4sIHBhdHRlcm4gPSAiaW5mbyIsIGZ1bGwubmFtZXMgPSBUUlVFKSkKbWVkaWFuc012YWxfZGYgPC0gcmVhZFJEUyhkaXIoZGF0YS5kaXIubWVkaWFuLCBwYXR0ZXJuID0gIm1lZGlhbnNNdmFsIiwgZnVsbC5uYW1lcyA9IFRSVUUpKQpwaGVub19kZiA8LSByZWFkUkRTKHBhc3RlMChkYXRhLmRpci5uZXVyb24sICJwaGVub193aXRoTmV1cm9uUHJvcF9kZi5SRFMiKSkgCgojIyMgQ2hlY2sgdmFyaWFibGVzIGJlZm9yZSBmaXR0aW5nIG1vZGVsCnBoZW5vX2RmJFNhbXBsZSA8LSBwaGVub19kZiRzYW1wbGUKaWRlbnRpY2FsKHBoZW5vX2RmJFNhbXBsZSwgY29sbmFtZXMobWVkaWFuc012YWxfZGYpKQoKcGhlbm9fZGYkc2V4IDwtIGFzLmZhY3RvcihwaGVub19kZiRzZXgpCnBoZW5vX2RmJHNsaWRlIDwtIGFzLmZhY3RvcihwaGVub19kZiRzbGlkZSkKIyBJZiByb3NtYXAgY29ob3J0LCBkb24ndCBmb3JnZXQgYmF0Y2ggZWZmZWN0CgpzdHIocGhlbm9fZGYpCmBgYAoKYGBge1IsIGV2YWwgPSBGQUxTRX0KZGV2dG9vbHM6OnNvdXJjZV9naXN0KCJodHRwczovL2dpc3QuZ2l0aHViLmNvbS90aWFnb2Noc3QvZDNhN2IxNjM5YWNmNjAzOTE2YzMxNWQyM2IxZWZiM2UiKQoKcHJlZGljdG9yc19jaGFyIDwtICJzdGFnZSIKY292YXJpYXRlc19jaGFyIDwtIGMoImFnZS5icmFpbiIsICJzZXgiLCAicHJvcC5uZXVyb24iLCAic2xpZGUiKQoKcmVzX2RmIDwtIFRlc3RBbGxSZWdpb25zX25vSW5mbygKICBwcmVkaWN0b3JzX2NoYXIgPSBwcmVkaWN0b3JzX2NoYXIsCiAgY292YXJpYXRlc19jaGFyID0gY292YXJpYXRlc19jaGFyLAogIHBoZW5vX2RmID0gcGhlbm9fZGYsCiAgc3VtbWFyaXplZFJlZ2lvbnNfZGYgPSBtZWRpYW5zTXZhbF9kZgopCgpjb2xuYW1lcyhyZXNfZGYpIDwtIGMoCiAgcGFzdGUwKGNvaG9ydCwgIl9lc3RpbWF0ZSIpLAogIHBhc3RlMChjb2hvcnQsICJfc2UiKSwKICBwYXN0ZTAoY29ob3J0LCAiX3BWYWwiKSwKICBwYXN0ZTAoY29ob3J0LCAiX2ZkciIpCikKCnJlc193aXRoSW5mb19kZiA8LSBjYmluZChpbmZvX2RmLCByZXNfZGYpCgpzYXZlUkRTKAogIHJlc193aXRoSW5mb19kZiwKICBwYXN0ZTAoZGF0YS5kaXIubWVkaWFuLCAgY29ob3J0LCAiX2xpbmVhcl9kZi5yZHMiKQopCmBgYAoKYGBge1J9CmZpbGUgPC0gZGlyKGRhdGEuZGlyLm1lZGlhbixwYXR0ZXJuID0gcGFzdGUwKCIuKmxpbmVhcl9kZiIpLAogICAgICAgICAgICByZWN1cnNpdmUgPSBULAogICAgICAgICAgICBmdWxsLm5hbWVzID0gVFJVRSwKICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBUKQpmaWxlCnJlc193aXRoSW5mb19kZiA8LSByZWFkUkRTKGZpbGUpCmRpbShyZXNfd2l0aEluZm9fZGYpCnJlc193aXRoSW5mb19kZgpgYGAKCiMgRGF0YSBmaW5hbAoKYGBge1J9CmRpcihwYXRoID0gZGF0YS5kaXIscmVjdXJzaXZlID0gVCwgcGF0dGVybiA9ICIucmRhfC5jc3Z8LlJEUyIpCmBgYAoKIyBTZXNzaW9uIGluZm9ybWF0aW9uCmBgYHtSfQpkZXZ0b29sczo6c2Vzc2lvbl9pbmZvKCkKYGBgCg==