1 Functions

tpm <- function(counts, lengths) {
  rpk <- counts / lengths
  coef <- sum(rpk) / 1e6
  rpk/coef
}

rpk <- function(counts, lengths) {
  rpk <- counts / lengths
  rpk
}

2 Read data

acc_immune_data_part1 <- read.delim("./Data/raw_data/SN0276364",skip=1,header=T, 
                       sep="\t",stringsAsFactors=F,row.names=1,check.names = F)

acc_immune_data_part2 <- read.delim("./Data/raw_data/SN0276892",skip=1,header=T, 
                       sep="\t",stringsAsFactors=F,row.names=1,check.names = F)

3 Pre-process

#save before omitting
genes_names = acc_immune_data_part1$gene_name
genes_lengths = acc_immune_data_part1[,5]

#omit non relevant cols
acc_immune_data_part1=acc_immune_data_part1[,7:ncol(acc_immune_data_part1)]
acc_immune_data_part2=acc_immune_data_part2[,7:ncol(acc_immune_data_part2)]

#combine datasets
acc_immune_data = cbind(acc_immune_data_part1,acc_immune_data_part2)

#create genes names
genes_names=make.unique(genes_names) %>% replace_na('NA')
rownames(acc_immune_data) = genes_names

#omit non relevant genes
omitgenes= startsWith(rownames(acc_immune_data),"NA")
acc_immune_data=acc_immune_data[!omitgenes,]
genes_lengths = genes_lengths[!omitgenes] #update genes_lengths

#calcualte gene length and MT genes
mt_genes = startsWith(rownames(acc_immune_data),"MT-")| startsWith(rownames(acc_immune_data),"ERCC-")

#get colnames
cell.labels <- gsub(pattern = "/.*$",replacement = "",colnames(acc_immune_data))

#change colnames
colnames(acc_immune_data) <- cell.labels


acc_immune_counts <- CreateSeuratObject(counts = acc_immune_data, project = "acc_immune_counts", min.cells = 3, min.features = 1000)
Warning: Feature names cannot have underscores ('_'), replacing with dashes ('-')

4 QC

acc_immune_counts@meta.data[["percent.mt"]] <- PercentageFeatureSet(acc_immune_counts, pattern = "^MT-")
print_tab(plt = 
            FeatureScatter(acc_immune_counts, feature1 = "nCount_RNA", feature2 = "percent.mt") + 
            theme(legend.position="none", axis.text.x = element_text(size=8)) + 
              geom_point(color='darkblue')
  
            ,title = "MT percentages")

MT percentages

print_tab(plt = 
            VlnPlot(acc_immune_counts, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)
,title = "violin plots")

violin plots

NA

acc_immune_data.rpk=apply(acc_immune_data[!mt_genes,], 2, function(x) rpk(x, genes_lengths[!mt_genes]))
acc_immune <- CreateSeuratObject(counts = acc_immune_data.rpk, project = "acc_immune", min.cells = 3, min.features = 1000)
Warning: Feature names cannot have underscores ('_'), replacing with dashes ('-')
acc_immune = NormalizeData(object = acc_immune,scale.factor = 1e6) #create TPM
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
acc_immune@assays$RNA@data = log2(exp(1)) * acc_immune@assays$RNA@data #convert from e base to 2 base log
# new_genes = rownames(acc_immune_data) %in% rownames(acc_immune)
# acc_immune_data.tpm=apply(acc_immune_data[new_genes,], 2, function(x) tpm(x, genes_lengths[new_genes])) %>%as.data.frame()
# acc_immune_data.tpm = log2(acc_immune_data.tpm+1)

5 Filtering

nFeature_RNA_threshold = 1000
percent.mt_threshold = 40
print ("nFeature_RNA threshold = " %>% paste(nFeature_RNA_threshold))
[1] "nFeature_RNA threshold =  1000"
print ("percent.mt threshold = " %>% paste(percent.mt_threshold))
[1] "percent.mt threshold =  40"
acc_immune <- subset(acc_immune, subset = nFeature_RNA > nFeature_RNA_threshold & percent.mt < percent.mt_threshold)
acc_immune
An object of class Seurat 
22647 features across 621 samples within 1 assay 
Active assay: RNA (22647 features, 0 variable features)

6 PCA

# Identification of highly variable features
acc_immune <- FindVariableFeatures(acc_immune, selection.method = "vst", nfeatures = 15000) 
# Scaling the data
acc_immune <- ScaleData(acc_immune, vars.to.regress = c("percent.mt","nCount_RNA"))
# Perform linear dimensional reduction (PCA)
acc_immune <- RunPCA(acc_immune, features = VariableFeatures(object = acc_immune))
ElbowPlot(acc_immune, ndims = 50) # checking the dimensionality 

pc2use=1:10
clus_res=1
print("PCA dims = " %>% paste(max(pc2use)))
[1] "PCA dims =  10"

7 UMAP and clustering

acc_immune <- FindNeighbors(acc_immune, dims = pc2use,verbose = F)
acc_immune <- FindClusters(acc_immune, resolution = clus_res,verbose = F)

# Run non-linear dimensional reduction (UMAP)
acc_immune <- RunUMAP(acc_immune, dims = pc2use,verbose = F)
DimPlot(object = acc_immune, reduction = "umap", pt.size = 1, label = F)

8 UMAPS




#get metedata
plate = str_extract(colnames(acc_immune), "^.*-P[0-9]*")
patient.ident = str_extract(colnames(acc_immune), "ACC[0-9]*")
origin = str_extract(colnames(acc_immune), "LN")
origin = origin %>% replace_na('Primary')

acc_immune <- AddMetaData(object = acc_immune, metadata = as.factor(patient.ident), col.name = "patient.ident")
acc_immune <- AddMetaData(object = acc_immune, metadata = as.factor(plate), col.name = "plate")
acc_immune <- AddMetaData(object = acc_immune, metadata = as.factor(origin), col.name = "origin")

print_tab(DimPlot(acc_immune, reduction = "umap", label = F, pt.size = 1,group.by = "patient.ident") 
,title = "by patient")

by patient

print_tab(plt = 
            DimPlot(acc_immune, reduction = "umap", label = F, pt.size = 1,group.by = "plate") 
        ,title =  "by plate")

by plate

print_tab(plt =
            FeaturePlot(object = acc_immune, features = "PTPRC")
          ,
          title = "CD45")

CD45

print_tab(plt = 
            DimPlot(acc_immune, reduction = "umap", label = F, pt.size = 1,group.by = "origin") 
        ,title =  "by origin")

by origin

NA

library(SeuratDisk)
SaveH5Seurat(object = acc_immune,filename = "./Data/acc_immune")

9 5K var genes

10 PCA

# Identification of highly variable features
acc_immune <- FindVariableFeatures(acc_immune, selection.method = "vst", nfeatures = 5000) 
# Scaling the data
acc_immune <- ScaleData(acc_immune, vars.to.regress = c("percent.mt","nCount_RNA"))
# Perform linear dimensional reduction (PCA)
acc_immune <- RunPCA(acc_immune, features = VariableFeatures(object = acc_immune))
ElbowPlot(acc_immune, ndims = 50) # checking the dimensionality 

pc2use=1:10
clus_res=1
print("PCA dims = " %>% paste(max(pc2use)))
[1] "PCA dims =  10"

11 UMAP and clustering

acc_immune <- FindNeighbors(acc_immune, dims = pc2use,verbose = F)
acc_immune <- FindClusters(acc_immune, resolution = clus_res,verbose = F)

# Run non-linear dimensional reduction (UMAP)
acc_immune <- RunUMAP(acc_immune, dims = pc2use,verbose = F)
Warning: The default method for RunUMAP has changed from calling Python UMAP via reticulate to the R-native UWOT using the cosine metric
To use Python UMAP via reticulate, set umap.method to 'umap-learn' and metric to 'correlation'
This message will be shown once per session
DimPlot(object = acc_immune, reduction = "umap", pt.size = 1, label = F)

12 UMAPSS




#get metedata
plate = str_extract(colnames(acc_immune), "^.*-P[0-9]*")
patient.ident = str_extract(colnames(acc_immune), "ACC[0-9]*")
origin = str_extract(colnames(acc_immune), "LN")
origin = origin %>% replace_na('Primary')

acc_immune <- AddMetaData(object = acc_immune, metadata = as.factor(patient.ident), col.name = "patient.ident")
acc_immune <- AddMetaData(object = acc_immune, metadata = as.factor(plate), col.name = "plate")
acc_immune <- AddMetaData(object = acc_immune, metadata = as.factor(origin), col.name = "origin")

print_tab(DimPlot(acc_immune, reduction = "umap", label = F, pt.size = 1,group.by = "patient.ident") 
,title = "by patient")

by patient

print_tab(plt = 
            DimPlot(acc_immune, reduction = "umap", label = F, pt.size = 1,group.by = "plate") 
        ,title =  "by plate")

by plate

print_tab(plt =
            FeaturePlot(object = acc_immune, features = "PTPRC")
          ,
          title = "CD45")

CD45

print_tab(plt = 
            DimPlot(acc_immune, reduction = "umap", label = F, pt.size = 1,group.by = "origin") 
        ,title =  "by origin")

by origin

NA

library(SeuratDisk)
SaveH5Seurat(object = acc_immune,filename = "./Data/acc_immune_5KvarGenes")

13 Primary

acc_immune_pri  = subset(acc_immune, subset = origin == "Primary")

13.1 PCA

pc2use=1:10
clus_res=1
print("PCA dims = " %>% paste(max(pc2use)))

13.2 UMAP and clustering

acc_immune_pri <- FindNeighbors(acc_immune_pri, dims = pc2use,verbose = F)
acc_immune_pri <- FindClusters(acc_immune_pri, resolution = clus_res,verbose = F)

# Run non-linear dimensional reduction (UMAP)
acc_immune_pri <- RunUMAP(acc_immune_pri, dims = pc2use,verbose = F,  metric = "euclidean")
DimPlot(object = acc_immune_pri, reduction = "umap", pt.size = 1, label = F)
SeuratDisk::SaveH5Seurat(object = acc_immune_pri,filename = "./Data/acc_immune_pri.h5seurat")

14 LN

acc_immune_ln  = subset(acc_immune, subset = origin == "LN")

14.1 PCA

pc2use=1:10
clus_res=1
print("PCA dims = " %>% paste(max(pc2use)))

14.2 UMAP and clustering

acc_immune_ln <- FindNeighbors(acc_immune_ln, dims = pc2use,verbose = F)
acc_immune_ln <- FindClusters(acc_immune_ln, resolution = clus_res,verbose = F)

# Run non-linear dimensional reduction (UMAP)
acc_immune_ln <- RunUMAP(acc_immune_ln, dims = pc2use,verbose = F,  metric = "euclidean")
DimPlot(object = acc_immune_ln, reduction = "umap", pt.size = 1, label = F)
SeuratDisk::SaveH5Seurat(object = acc_immune_ln,filename = "./Data/acc_immune_ln.h5seurat")

prefix="acc_tpm_nCount_mito_no146_"
acc_caf = readRDS(paste(prefix,"cafs.rds",sep=""))
acc_caf = readRDS("/sci/labs/yotamd/lab_share/ACC/ACC_sc/analysis/acc_tpm_nCount_mito_no146_cafs.rds")

acc_caf <- FindVariableFeatures(acc_caf, selection.method = "vst", nfeatures = 7500)
acc_caf <- ScaleData(acc_caf, vars.to.regress = c("percent.mt","nCount_RNA"))
clus_res=.25
gs=acc_caf@assays$RNA@var.features

myCAF=apply(acc_caf@assays$RNA@scale.data[intersect(c("ADIRF","ACTA2","MYH11","TAGLN","SPARCL1","MCAM","A2M","MYLK","IGFBP7","CRIP1","TINAGL1","TPM2","PTP4A3","PPP1R14A","CRIP2","ADAMTS1","CSRP2","NDUFA4L2","TPM1","MAP1B","FRZB","PRKCDBP","CSRP1","CAV1","ADAMTS4","GJA4","RGS5","MEF2C","CALM2","APOLD1","OAZ2","MGST3","ISYNA1","CPM","PGF","GUCY1B3","UBA2","YIF1A","PHLDA1","NDRG2","ID3","RGS16","CYB5R3","CRYAB","OLFML2A","TIMP3","GUCY1A3","FILIP1","FAM13C","NDUFS4","ITGB1","KCNE4","CPE"),gs),],2,mean)
dCAF=apply(acc_caf@assays$RNA@scale.data[intersect(c("COL1A1","THBS2","CTHRC1","COL3A1","LUM","COL1A2","LGALS1","COL5A1","POSTN","SERPINE1","LOXL2","COL11A1","CTSK","COL12A1","MMP2","INHBA","TNFAIP6","VCAN","ADAM12","THY1","FN1","STEAP1","SPON2","PLAUR","SPHK1","LOX","EMP1","ANGPTL2","RARRES2","SULF1","IGFBP3","COL8A1","GREM1","DCN","ITGA5","ANTXR1","RIN2","TMEM119","TNFRSF12A","P4HA3","CRABP2","TPM4","LOXL1","CPXM1","COL6A1","ASPN","PDLIM4","ITGA11","PRSS23","COL6A2","SFRP2","PLAU","YIF1A","SNAI2","C1S","TMEM176B","CTGF","MORF4L2","UAP1","SERPINF1","ITGB1","TGFBI","HTRA3","C1R","TIMP1","LMNA","CYP1B1","MGP","ANGPTL4"),gs),],2,mean)
iCAF=apply(acc_caf@assays$RNA@scale.data[intersect(c("CFD","GPC3","C3","ADH1B","IGF1","EFEMP1","PODN","SEPP1","CXCL12","ABI3BP","FBLN1","MGST1","MFAP4","PLA2G2A","DPT","WISP2","CCDC80","SFRP2","PTGDS","DCN","MGP","C1S","IGFBP6","GSN","TMEM176A","FIBIN","TMEM176B","SERPINF1","FHL1","GPX3","CTGF","C1R","SFRP4","CYP1B1","CST3","SLC40A1","FHL2","ELN","KLF4","RARRES1","CYR61","IGFBP5"),gs),],2,mean)
iCAF2=apply(acc_caf@assays$RNA@scale.data[intersect(c("IER3","CXCL2","ICAM1","TNFAIP2","NFKBIA","NR4A1","CCL2","SOD2","FOSB","PIM1","ZFP36","CLU","ABL2","GEM","NR4A3","APOD","SAT1","UAP1","OGN","GFPT2","JUNB","THBS1","CDKN1A","C3","CYP1B1","EGR1","ABI3BP","GADD45B","DUSP1","RARRES1","CST3"),gs),],2,mean)
pCAF=apply(acc_caf@assays$RNA@scale.data[intersect(c("NUSAP1","DIAPH3","LOXL2","ADAM12","LOX","POSTN","THY1","CD248","FN1","COL12A1","CTHRC1","COL5A1","LOXL1","COL1A1","COL8A1","COL6A1","COL6A2"),gs),],2,mean)
acc_caf=AddMetaData(acc_caf,myCAF,"pan.myCAF")
acc_caf=AddMetaData(acc_caf,dCAF,"pan.dCAF")
acc_caf=AddMetaData(acc_caf,iCAF,"pan.iCAF")
acc_caf=AddMetaData(acc_caf,iCAF2,"pan.iCAF2")
acc_caf=AddMetaData(acc_caf,pCAF,"pan.pCAF")

pc2use=1:11
acc_caf <- RunPCA(acc_caf, features = VariableFeatures(object = acc_caf))
pcaplot <- PCAPlot(acc_caf, label = FALSE)
elbowplot <- ElbowPlot(acc_caf, ndims = 50) # checking the dimensionality 
acc_caf <- FindNeighbors(acc_caf, dims = pc2use)
acc_caf <- FindClusters(acc_caf, resolution = clus_res)
acc_caf <- RunUMAP(acc_caf, dims = pc2use)
DimPlot(object = acc_caf, reduction = "umap", pt.size = 0.5, label = TRUE)

FeaturePlot(acc_caf, "pan.myCAF", pt.size = 0.5, cols = c("blue","yellow"))
FeaturePlot(acc_caf, "pan.dCAF", pt.size = 0.5, cols = c("blue","yellow"))
FeaturePlot(acc_caf, "pan.iCAF", pt.size = 0.5, cols = c("blue","yellow"))
FeaturePlot(acc_caf, "pan.iCAF2", pt.size = 0.5, cols = c("blue","yellow"))
FeaturePlot(acc_caf, "pan.pCAF", pt.size = 0.5, cols = c("blue","yellow"))
LS0tCnRpdGxlOiAnYHIgcnN0dWRpb2FwaTo6Z2V0U291cmNlRWRpdG9yQ29udGV4dCgpJHBhdGggJT4lIGJhc2VuYW1lKCkgJT4lIGdzdWIocGF0dGVybiA9ICJcXC5SbWQiLHJlcGxhY2VtZW50ID0gIiIpYCcgCmF1dGhvcjogIkF2aXNoYWkgV2l6ZWwiCmRhdGU6ICdgciBTeXMudGltZSgpYCcKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIHRvY19jb2xsYXBzZTogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICBjb2xsYXBzZWQ6IEZBTFNFCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19kZXB0aDogMQotLS0KCgojIEZ1bmN0aW9ucwoKYGBge3Igd2FybmluZz1GQUxTRX0KdHBtIDwtIGZ1bmN0aW9uKGNvdW50cywgbGVuZ3RocykgewogIHJwayA8LSBjb3VudHMgLyBsZW5ndGhzCiAgY29lZiA8LSBzdW0ocnBrKSAvIDFlNgogIHJway9jb2VmCn0KCnJwayA8LSBmdW5jdGlvbihjb3VudHMsIGxlbmd0aHMpIHsKICBycGsgPC0gY291bnRzIC8gbGVuZ3RocwogIHJwawp9CmBgYAoKIyBSZWFkIGRhdGEKYGBge3J9CmFjY19pbW11bmVfZGF0YV9wYXJ0MSA8LSByZWFkLmRlbGltKCIuL0RhdGEvcmF3X2RhdGEvU04wMjc2MzY0Iixza2lwPTEsaGVhZGVyPVQsIAogICAgICAgICAgICAgICAgICAgICAgIHNlcD0iXHQiLHN0cmluZ3NBc0ZhY3RvcnM9Rixyb3cubmFtZXM9MSxjaGVjay5uYW1lcyA9IEYpCgphY2NfaW1tdW5lX2RhdGFfcGFydDIgPC0gcmVhZC5kZWxpbSgiLi9EYXRhL3Jhd19kYXRhL1NOMDI3Njg5MiIsc2tpcD0xLGhlYWRlcj1ULCAKICAgICAgICAgICAgICAgICAgICAgICBzZXA9Ilx0IixzdHJpbmdzQXNGYWN0b3JzPUYscm93Lm5hbWVzPTEsY2hlY2submFtZXMgPSBGKQpgYGAKCiMgUHJlLXByb2Nlc3MKYGBge3J9CiNzYXZlIGJlZm9yZSBvbWl0dGluZwpnZW5lc19uYW1lcyA9IGFjY19pbW11bmVfZGF0YV9wYXJ0MSRnZW5lX25hbWUKZ2VuZXNfbGVuZ3RocyA9IGFjY19pbW11bmVfZGF0YV9wYXJ0MVssNV0KCiNvbWl0IG5vbiByZWxldmFudCBjb2xzCmFjY19pbW11bmVfZGF0YV9wYXJ0MT1hY2NfaW1tdW5lX2RhdGFfcGFydDFbLDc6bmNvbChhY2NfaW1tdW5lX2RhdGFfcGFydDEpXQphY2NfaW1tdW5lX2RhdGFfcGFydDI9YWNjX2ltbXVuZV9kYXRhX3BhcnQyWyw3Om5jb2woYWNjX2ltbXVuZV9kYXRhX3BhcnQyKV0KCiNjb21iaW5lIGRhdGFzZXRzCmFjY19pbW11bmVfZGF0YSA9IGNiaW5kKGFjY19pbW11bmVfZGF0YV9wYXJ0MSxhY2NfaW1tdW5lX2RhdGFfcGFydDIpCgojY3JlYXRlIGdlbmVzIG5hbWVzCmdlbmVzX25hbWVzPW1ha2UudW5pcXVlKGdlbmVzX25hbWVzKSAlPiUgcmVwbGFjZV9uYSgnTkEnKQpyb3duYW1lcyhhY2NfaW1tdW5lX2RhdGEpID0gZ2VuZXNfbmFtZXMKCiNvbWl0IG5vbiByZWxldmFudCBnZW5lcwpvbWl0Z2VuZXM9IHN0YXJ0c1dpdGgocm93bmFtZXMoYWNjX2ltbXVuZV9kYXRhKSwiTkEiKQphY2NfaW1tdW5lX2RhdGE9YWNjX2ltbXVuZV9kYXRhWyFvbWl0Z2VuZXMsXQpnZW5lc19sZW5ndGhzID0gZ2VuZXNfbGVuZ3Roc1shb21pdGdlbmVzXSAjdXBkYXRlIGdlbmVzX2xlbmd0aHMKCiNjYWxjdWFsdGUgZ2VuZSBsZW5ndGggYW5kIE1UIGdlbmVzCm10X2dlbmVzID0gc3RhcnRzV2l0aChyb3duYW1lcyhhY2NfaW1tdW5lX2RhdGEpLCJNVC0iKXwgc3RhcnRzV2l0aChyb3duYW1lcyhhY2NfaW1tdW5lX2RhdGEpLCJFUkNDLSIpCgojZ2V0IGNvbG5hbWVzCmNlbGwubGFiZWxzIDwtIGdzdWIocGF0dGVybiA9ICIvLiokIixyZXBsYWNlbWVudCA9ICIiLGNvbG5hbWVzKGFjY19pbW11bmVfZGF0YSkpCgojY2hhbmdlIGNvbG5hbWVzCmNvbG5hbWVzKGFjY19pbW11bmVfZGF0YSkgPC0gY2VsbC5sYWJlbHMKCgphY2NfaW1tdW5lX2NvdW50cyA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gYWNjX2ltbXVuZV9kYXRhLCBwcm9qZWN0ID0gImFjY19pbW11bmVfY291bnRzIiwgbWluLmNlbGxzID0gMywgbWluLmZlYXR1cmVzID0gMTAwMCkKCmBgYAoKIyBRQyAgey50YWJzZXR9CmBgYHtyIGVjaG89VFJVRSwgcmVzdWx0cz0nYXNpcyd9CmFjY19pbW11bmVfY291bnRzQG1ldGEuZGF0YVtbInBlcmNlbnQubXQiXV0gPC0gUGVyY2VudGFnZUZlYXR1cmVTZXQoYWNjX2ltbXVuZV9jb3VudHMsIHBhdHRlcm4gPSAiXk1ULSIpCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRmVhdHVyZVNjYXR0ZXIoYWNjX2ltbXVuZV9jb3VudHMsIGZlYXR1cmUxID0gIm5Db3VudF9STkEiLCBmZWF0dXJlMiA9ICJwZXJjZW50Lm10IikgKyAKICAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT04KSkgKyAKICAgICAgICAgICAgICBnZW9tX3BvaW50KGNvbG9yPSdkYXJrYmx1ZScpCiAgCiAgICAgICAgICAgICx0aXRsZSA9ICJNVCBwZXJjZW50YWdlcyIpCgpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIFZsblBsb3QoYWNjX2ltbXVuZV9jb3VudHMsIGZlYXR1cmVzID0gYygibkZlYXR1cmVfUk5BIiwgIm5Db3VudF9STkEiLCAicGVyY2VudC5tdCIpLCBuY29sID0gMykKLHRpdGxlID0gInZpb2xpbiBwbG90cyIpCgpgYGAKCgpgYGB7cn0KYWNjX2ltbXVuZV9kYXRhLnJwaz1hcHBseShhY2NfaW1tdW5lX2RhdGFbIW10X2dlbmVzLF0sIDIsIGZ1bmN0aW9uKHgpIHJwayh4LCBnZW5lc19sZW5ndGhzWyFtdF9nZW5lc10pKQphY2NfaW1tdW5lIDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBhY2NfaW1tdW5lX2RhdGEucnBrLCBwcm9qZWN0ID0gImFjY19pbW11bmUiLCBtaW4uY2VsbHMgPSAzLCBtaW4uZmVhdHVyZXMgPSAxMDAwKQpgYGAKYGBge3J9CmFjY19pbW11bmUgPSBOb3JtYWxpemVEYXRhKG9iamVjdCA9IGFjY19pbW11bmUsc2NhbGUuZmFjdG9yID0gMWU2KSAjY3JlYXRlIFRQTQphY2NfaW1tdW5lQGFzc2F5cyRSTkFAZGF0YSA9IGxvZzIoZXhwKDEpKSAqIGFjY19pbW11bmVAYXNzYXlzJFJOQUBkYXRhICNjb252ZXJ0IGZyb20gZSBiYXNlIHRvIDIgYmFzZSBsb2cKYGBgCgoKYGBge3J9CiMgbmV3X2dlbmVzID0gcm93bmFtZXMoYWNjX2ltbXVuZV9kYXRhKSAlaW4lIHJvd25hbWVzKGFjY19pbW11bmUpCiMgYWNjX2ltbXVuZV9kYXRhLnRwbT1hcHBseShhY2NfaW1tdW5lX2RhdGFbbmV3X2dlbmVzLF0sIDIsIGZ1bmN0aW9uKHgpIHRwbSh4LCBnZW5lc19sZW5ndGhzW25ld19nZW5lc10pKSAlPiVhcy5kYXRhLmZyYW1lKCkKIyBhY2NfaW1tdW5lX2RhdGEudHBtID0gbG9nMihhY2NfaW1tdW5lX2RhdGEudHBtKzEpCmBgYAoKIyBGaWx0ZXJpbmcKYGBge3J9Cm5GZWF0dXJlX1JOQV90aHJlc2hvbGQgPSAxMDAwCnBlcmNlbnQubXRfdGhyZXNob2xkID0gNDAKcHJpbnQgKCJuRmVhdHVyZV9STkEgdGhyZXNob2xkID0gIiAlPiUgcGFzdGUobkZlYXR1cmVfUk5BX3RocmVzaG9sZCkpCnByaW50ICgicGVyY2VudC5tdCB0aHJlc2hvbGQgPSAiICU+JSBwYXN0ZShwZXJjZW50Lm10X3RocmVzaG9sZCkpCgphY2NfaW1tdW5lIDwtIHN1YnNldChhY2NfaW1tdW5lLCBzdWJzZXQgPSBuRmVhdHVyZV9STkEgPiBuRmVhdHVyZV9STkFfdGhyZXNob2xkICYgcGVyY2VudC5tdCA8IHBlcmNlbnQubXRfdGhyZXNob2xkKQphY2NfaW1tdW5lCmBgYAoKIyBQQ0EKYGBge3IgcmVzdWx0cz0naGlkZSd9CiMgSWRlbnRpZmljYXRpb24gb2YgaGlnaGx5IHZhcmlhYmxlIGZlYXR1cmVzCmFjY19pbW11bmUgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoYWNjX2ltbXVuZSwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAxNTAwMCkgCgojIFNjYWxpbmcgdGhlIGRhdGEKYWNjX2ltbXVuZSA8LSBTY2FsZURhdGEoYWNjX2ltbXVuZSwgdmFycy50by5yZWdyZXNzID0gYygicGVyY2VudC5tdCIsIm5Db3VudF9STkEiKSkKCiMgUGVyZm9ybSBsaW5lYXIgZGltZW5zaW9uYWwgcmVkdWN0aW9uIChQQ0EpCmFjY19pbW11bmUgPC0gUnVuUENBKGFjY19pbW11bmUsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhvYmplY3QgPSBhY2NfaW1tdW5lKSkKCkVsYm93UGxvdChhY2NfaW1tdW5lLCBuZGltcyA9IDUwKSAjIGNoZWNraW5nIHRoZSBkaW1lbnNpb25hbGl0eSAKCmBgYApgYGB7cn0KcGMydXNlPTE6MTAKY2x1c19yZXM9MQpwcmludCgiUENBIGRpbXMgPSAiICU+JSBwYXN0ZShtYXgocGMydXNlKSkpCmBgYAoKIyBVTUFQIGFuZCBjbHVzdGVyaW5nCmBgYHtyfQphY2NfaW1tdW5lIDwtIEZpbmROZWlnaGJvcnMoYWNjX2ltbXVuZSwgZGltcyA9IHBjMnVzZSx2ZXJib3NlID0gRikKYWNjX2ltbXVuZSA8LSBGaW5kQ2x1c3RlcnMoYWNjX2ltbXVuZSwgcmVzb2x1dGlvbiA9IGNsdXNfcmVzLHZlcmJvc2UgPSBGKQoKIyBSdW4gbm9uLWxpbmVhciBkaW1lbnNpb25hbCByZWR1Y3Rpb24gKFVNQVApCmFjY19pbW11bmUgPC0gUnVuVU1BUChhY2NfaW1tdW5lLCBkaW1zID0gcGMydXNlLHZlcmJvc2UgPSBGKQpEaW1QbG90KG9iamVjdCA9IGFjY19pbW11bmUsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIGxhYmVsID0gRikKYGBgCiMgVU1BUFMgIHsudGFic2V0fQpgYGB7ciBlY2hvPVRSVUUsIHJlc3VsdHM9J2FzaXMnfQoKCgojZ2V0IG1ldGVkYXRhCnBsYXRlID0gc3RyX2V4dHJhY3QoY29sbmFtZXMoYWNjX2ltbXVuZSksICJeLiotUFswLTldKiIpCnBhdGllbnQuaWRlbnQgPSBzdHJfZXh0cmFjdChjb2xuYW1lcyhhY2NfaW1tdW5lKSwgIkFDQ1swLTldKiIpCm9yaWdpbiA9IHN0cl9leHRyYWN0KGNvbG5hbWVzKGFjY19pbW11bmUpLCAiTE4iKQpvcmlnaW4gPSBvcmlnaW4gJT4lIHJlcGxhY2VfbmEoJ1ByaW1hcnknKQoKYWNjX2ltbXVuZSA8LSBBZGRNZXRhRGF0YShvYmplY3QgPSBhY2NfaW1tdW5lLCBtZXRhZGF0YSA9IGFzLmZhY3RvcihwYXRpZW50LmlkZW50KSwgY29sLm5hbWUgPSAicGF0aWVudC5pZGVudCIpCmFjY19pbW11bmUgPC0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjX2ltbXVuZSwgbWV0YWRhdGEgPSBhcy5mYWN0b3IocGxhdGUpLCBjb2wubmFtZSA9ICJwbGF0ZSIpCmFjY19pbW11bmUgPC0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjX2ltbXVuZSwgbWV0YWRhdGEgPSBhcy5mYWN0b3Iob3JpZ2luKSwgY29sLm5hbWUgPSAib3JpZ2luIikKCnByaW50X3RhYihEaW1QbG90KGFjY19pbW11bmUsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBGLCBwdC5zaXplID0gMSxncm91cC5ieSA9ICJwYXRpZW50LmlkZW50IikgCix0aXRsZSA9ICJieSBwYXRpZW50IikKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBEaW1QbG90KGFjY19pbW11bmUsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBGLCBwdC5zaXplID0gMSxncm91cC5ieSA9ICJwbGF0ZSIpIAogICAgICAgICx0aXRsZSA9ICAiYnkgcGxhdGUiKQoKcHJpbnRfdGFiKHBsdCA9CiAgICAgICAgICAgIEZlYXR1cmVQbG90KG9iamVjdCA9IGFjY19pbW11bmUsIGZlYXR1cmVzID0gIlBUUFJDIikKICAgICAgICAgICwKICAgICAgICAgIHRpdGxlID0gIkNENDUiKQpwcmludF90YWIocGx0ID0gCiAgICAgICAgICAgIERpbVBsb3QoYWNjX2ltbXVuZSwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IEYsIHB0LnNpemUgPSAxLGdyb3VwLmJ5ID0gIm9yaWdpbiIpIAogICAgICAgICx0aXRsZSA9ICAiYnkgb3JpZ2luIikKYGBgCgpgYGB7cn0KbGlicmFyeShTZXVyYXREaXNrKQpTYXZlSDVTZXVyYXQob2JqZWN0ID0gYWNjX2ltbXVuZSxmaWxlbmFtZSA9ICIuL0RhdGEvYWNjX2ltbXVuZSIpCmBgYAoKCiMgNUsgdmFyIGdlbmVzCiMgUENBCmBgYHtyIHJlc3VsdHM9J2hpZGUnfQojIElkZW50aWZpY2F0aW9uIG9mIGhpZ2hseSB2YXJpYWJsZSBmZWF0dXJlcwphY2NfaW1tdW5lIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKGFjY19pbW11bmUsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gNTAwMCkgCgojIFNjYWxpbmcgdGhlIGRhdGEKYWNjX2ltbXVuZSA8LSBTY2FsZURhdGEoYWNjX2ltbXVuZSwgdmFycy50by5yZWdyZXNzID0gYygicGVyY2VudC5tdCIsIm5Db3VudF9STkEiKSkKCiMgUGVyZm9ybSBsaW5lYXIgZGltZW5zaW9uYWwgcmVkdWN0aW9uIChQQ0EpCmFjY19pbW11bmUgPC0gUnVuUENBKGFjY19pbW11bmUsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhvYmplY3QgPSBhY2NfaW1tdW5lKSkKCkVsYm93UGxvdChhY2NfaW1tdW5lLCBuZGltcyA9IDUwKSAjIGNoZWNraW5nIHRoZSBkaW1lbnNpb25hbGl0eSAKYGBgCgpgYGB7cn0KcGMydXNlPTE6MTAKY2x1c19yZXM9MQpwcmludCgiUENBIGRpbXMgPSAiICU+JSBwYXN0ZShtYXgocGMydXNlKSkpCmBgYAoKIyBVTUFQIGFuZCBjbHVzdGVyaW5nCmBgYHtyfQphY2NfaW1tdW5lIDwtIEZpbmROZWlnaGJvcnMoYWNjX2ltbXVuZSwgZGltcyA9IHBjMnVzZSx2ZXJib3NlID0gRikKYWNjX2ltbXVuZSA8LSBGaW5kQ2x1c3RlcnMoYWNjX2ltbXVuZSwgcmVzb2x1dGlvbiA9IGNsdXNfcmVzLHZlcmJvc2UgPSBGKQoKIyBSdW4gbm9uLWxpbmVhciBkaW1lbnNpb25hbCByZWR1Y3Rpb24gKFVNQVApCmFjY19pbW11bmUgPC0gUnVuVU1BUChhY2NfaW1tdW5lLCBkaW1zID0gcGMydXNlLHZlcmJvc2UgPSBGKQpEaW1QbG90KG9iamVjdCA9IGFjY19pbW11bmUsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIGxhYmVsID0gRikKYGBgCiMgVU1BUFNTICB7LnRhYnNldH0KYGBge3IgZWNobz1UUlVFLCByZXN1bHRzPSdhc2lzJ30KCgoKI2dldCBtZXRlZGF0YQpwbGF0ZSA9IHN0cl9leHRyYWN0KGNvbG5hbWVzKGFjY19pbW11bmUpLCAiXi4qLVBbMC05XSoiKQpwYXRpZW50LmlkZW50ID0gc3RyX2V4dHJhY3QoY29sbmFtZXMoYWNjX2ltbXVuZSksICJBQ0NbMC05XSoiKQpvcmlnaW4gPSBzdHJfZXh0cmFjdChjb2xuYW1lcyhhY2NfaW1tdW5lKSwgIkxOIikKb3JpZ2luID0gb3JpZ2luICU+JSByZXBsYWNlX25hKCdQcmltYXJ5JykKCmFjY19pbW11bmUgPC0gQWRkTWV0YURhdGEob2JqZWN0ID0gYWNjX2ltbXVuZSwgbWV0YWRhdGEgPSBhcy5mYWN0b3IocGF0aWVudC5pZGVudCksIGNvbC5uYW1lID0gInBhdGllbnQuaWRlbnQiKQphY2NfaW1tdW5lIDwtIEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjY19pbW11bmUsIG1ldGFkYXRhID0gYXMuZmFjdG9yKHBsYXRlKSwgY29sLm5hbWUgPSAicGxhdGUiKQphY2NfaW1tdW5lIDwtIEFkZE1ldGFEYXRhKG9iamVjdCA9IGFjY19pbW11bmUsIG1ldGFkYXRhID0gYXMuZmFjdG9yKG9yaWdpbiksIGNvbC5uYW1lID0gIm9yaWdpbiIpCgpwcmludF90YWIoRGltUGxvdChhY2NfaW1tdW5lLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gRiwgcHQuc2l6ZSA9IDEsZ3JvdXAuYnkgPSAicGF0aWVudC5pZGVudCIpIAosdGl0bGUgPSAiYnkgcGF0aWVudCIpCnByaW50X3RhYihwbHQgPSAKICAgICAgICAgICAgRGltUGxvdChhY2NfaW1tdW5lLCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gRiwgcHQuc2l6ZSA9IDEsZ3JvdXAuYnkgPSAicGxhdGUiKSAKICAgICAgICAsdGl0bGUgPSAgImJ5IHBsYXRlIikKCnByaW50X3RhYihwbHQgPQogICAgICAgICAgICBGZWF0dXJlUGxvdChvYmplY3QgPSBhY2NfaW1tdW5lLCBmZWF0dXJlcyA9ICJQVFBSQyIpCiAgICAgICAgICAsCiAgICAgICAgICB0aXRsZSA9ICJDRDQ1IikKcHJpbnRfdGFiKHBsdCA9IAogICAgICAgICAgICBEaW1QbG90KGFjY19pbW11bmUsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBGLCBwdC5zaXplID0gMSxncm91cC5ieSA9ICJvcmlnaW4iKSAKICAgICAgICAsdGl0bGUgPSAgImJ5IG9yaWdpbiIpCmBgYAoKYGBge3J9CmxpYnJhcnkoU2V1cmF0RGlzaykKU2F2ZUg1U2V1cmF0KG9iamVjdCA9IGFjY19pbW11bmUsZmlsZW5hbWUgPSAiLi9EYXRhL2FjY19pbW11bmVfNUt2YXJHZW5lcyIpCmBgYAoKIyBQcmltYXJ5CmBgYHtyfQphY2NfaW1tdW5lX3ByaSAgPSBzdWJzZXQoYWNjX2ltbXVuZSwgc3Vic2V0ID0gb3JpZ2luID09ICJQcmltYXJ5IikKYGBgCgoKIyMgUENBCmBgYHtyIHJlc3VsdHM9J2hpZGUnfQojIElkZW50aWZpY2F0aW9uIG9mIGhpZ2hseSB2YXJpYWJsZSBmZWF0dXJlcwphY2NfaW1tdW5lX3ByaSA8LSBGaW5kVmFyaWFibGVGZWF0dXJlcyhhY2NfaW1tdW5lX3ByaSwgc2VsZWN0aW9uLm1ldGhvZCA9ICJ2c3QiLCBuZmVhdHVyZXMgPSAxNTAwMCkgCgojIFNjYWxpbmcgdGhlIGRhdGEKYWNjX2ltbXVuZV9wcmkgPC0gU2NhbGVEYXRhKGFjY19pbW11bmVfcHJpLCB2YXJzLnRvLnJlZ3Jlc3MgPSBjKCJwZXJjZW50Lm10IiwibkNvdW50X1JOQSIpKQoKIyBQZXJmb3JtIGxpbmVhciBkaW1lbnNpb25hbCByZWR1Y3Rpb24gKFBDQSkKYWNjX2ltbXVuZV9wcmkgPC0gUnVuUENBKGFjY19pbW11bmVfcHJpLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gYWNjX2ltbXVuZV9wcmkpKQoKRWxib3dQbG90KGFjY19pbW11bmVfcHJpLCBuZGltcyA9IDUwKSAjIGNoZWNraW5nIHRoZSBkaW1lbnNpb25hbGl0eSAKCmBgYAoKYGBge3J9CnBjMnVzZT0xOjEwCmNsdXNfcmVzPTEKcHJpbnQoIlBDQSBkaW1zID0gIiAlPiUgcGFzdGUobWF4KHBjMnVzZSkpKQpgYGAKCiMjIFVNQVAgYW5kIGNsdXN0ZXJpbmcKYGBge3J9CmFjY19pbW11bmVfcHJpIDwtIEZpbmROZWlnaGJvcnMoYWNjX2ltbXVuZV9wcmksIGRpbXMgPSBwYzJ1c2UsdmVyYm9zZSA9IEYpCmFjY19pbW11bmVfcHJpIDwtIEZpbmRDbHVzdGVycyhhY2NfaW1tdW5lX3ByaSwgcmVzb2x1dGlvbiA9IGNsdXNfcmVzLHZlcmJvc2UgPSBGKQoKIyBSdW4gbm9uLWxpbmVhciBkaW1lbnNpb25hbCByZWR1Y3Rpb24gKFVNQVApCmFjY19pbW11bmVfcHJpIDwtIFJ1blVNQVAoYWNjX2ltbXVuZV9wcmksIGRpbXMgPSBwYzJ1c2UsdmVyYm9zZSA9IEYsICBtZXRyaWMgPSAiZXVjbGlkZWFuIikKRGltUGxvdChvYmplY3QgPSBhY2NfaW1tdW5lX3ByaSwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgbGFiZWwgPSBGKQpgYGAKYGBge3J9ClNldXJhdERpc2s6OlNhdmVINVNldXJhdChvYmplY3QgPSBhY2NfaW1tdW5lX3ByaSxmaWxlbmFtZSA9ICIuL0RhdGEvYWNjX2ltbXVuZV9wcmkuaDVzZXVyYXQiKQpgYGAKCgojIExOCmBgYHtyfQphY2NfaW1tdW5lX2xuICA9IHN1YnNldChhY2NfaW1tdW5lLCBzdWJzZXQgPSBvcmlnaW4gPT0gIkxOIikKYGBgCgoKIyMgUENBCmBgYHtyIHJlc3VsdHM9J2hpZGUnfQojIElkZW50aWZpY2F0aW9uIG9mIGhpZ2hseSB2YXJpYWJsZSBmZWF0dXJlcwphY2NfaW1tdW5lX2xuIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKGFjY19pbW11bmVfbG4sIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gMTUwMDApIAoKIyBTY2FsaW5nIHRoZSBkYXRhCmFjY19pbW11bmVfbG4gPC0gU2NhbGVEYXRhKGFjY19pbW11bmVfbG4sIHZhcnMudG8ucmVncmVzcyA9IGMoInBlcmNlbnQubXQiLCJuQ291bnRfUk5BIikpCgojIFBlcmZvcm0gbGluZWFyIGRpbWVuc2lvbmFsIHJlZHVjdGlvbiAoUENBKQphY2NfaW1tdW5lX2xuIDwtIFJ1blBDQShhY2NfaW1tdW5lX2xuLCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMob2JqZWN0ID0gYWNjX2ltbXVuZV9sbikpCgpFbGJvd1Bsb3QoYWNjX2ltbXVuZV9sbiwgbmRpbXMgPSA1MCkgIyBjaGVja2luZyB0aGUgZGltZW5zaW9uYWxpdHkgCgpgYGAKCmBgYHtyfQpwYzJ1c2U9MToxMApjbHVzX3Jlcz0xCnByaW50KCJQQ0EgZGltcyA9ICIgJT4lIHBhc3RlKG1heChwYzJ1c2UpKSkKYGBgCgojIyBVTUFQIGFuZCBjbHVzdGVyaW5nCmBgYHtyfQphY2NfaW1tdW5lX2xuIDwtIEZpbmROZWlnaGJvcnMoYWNjX2ltbXVuZV9sbiwgZGltcyA9IHBjMnVzZSx2ZXJib3NlID0gRikKYWNjX2ltbXVuZV9sbiA8LSBGaW5kQ2x1c3RlcnMoYWNjX2ltbXVuZV9sbiwgcmVzb2x1dGlvbiA9IGNsdXNfcmVzLHZlcmJvc2UgPSBGKQoKIyBSdW4gbm9uLWxpbmVhciBkaW1lbnNpb25hbCByZWR1Y3Rpb24gKFVNQVApCmFjY19pbW11bmVfbG4gPC0gUnVuVU1BUChhY2NfaW1tdW5lX2xuLCBkaW1zID0gcGMydXNlLHZlcmJvc2UgPSBGLCAgbWV0cmljID0gImV1Y2xpZGVhbiIpCkRpbVBsb3Qob2JqZWN0ID0gYWNjX2ltbXVuZV9sbiwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgbGFiZWwgPSBGKQpgYGAKYGBge3J9ClNldXJhdERpc2s6OlNhdmVINVNldXJhdChvYmplY3QgPSBhY2NfaW1tdW5lX2xuLGZpbGVuYW1lID0gIi4vRGF0YS9hY2NfaW1tdW5lX2xuLmg1c2V1cmF0IikKYGBgCmBgYHtyfQoKcHJlZml4PSJhY2NfdHBtX25Db3VudF9taXRvX25vMTQ2XyIKYWNjX2NhZiA9IHJlYWRSRFMocGFzdGUocHJlZml4LCJjYWZzLnJkcyIsc2VwPSIiKSkKYWNjX2NhZiA9IHJlYWRSRFMoIi9zY2kvbGFicy95b3RhbWQvbGFiX3NoYXJlL0FDQy9BQ0Nfc2MvYW5hbHlzaXMvYWNjX3RwbV9uQ291bnRfbWl0b19ubzE0Nl9jYWZzLnJkcyIpCgphY2NfY2FmIDwtIEZpbmRWYXJpYWJsZUZlYXR1cmVzKGFjY19jYWYsIHNlbGVjdGlvbi5tZXRob2QgPSAidnN0IiwgbmZlYXR1cmVzID0gNzUwMCkKYWNjX2NhZiA8LSBTY2FsZURhdGEoYWNjX2NhZiwgdmFycy50by5yZWdyZXNzID0gYygicGVyY2VudC5tdCIsIm5Db3VudF9STkEiKSkKY2x1c19yZXM9LjI1CmdzPWFjY19jYWZAYXNzYXlzJFJOQUB2YXIuZmVhdHVyZXMKCm15Q0FGPWFwcGx5KGFjY19jYWZAYXNzYXlzJFJOQUBzY2FsZS5kYXRhW2ludGVyc2VjdChjKCJBRElSRiIsIkFDVEEyIiwiTVlIMTEiLCJUQUdMTiIsIlNQQVJDTDEiLCJNQ0FNIiwiQTJNIiwiTVlMSyIsIklHRkJQNyIsIkNSSVAxIiwiVElOQUdMMSIsIlRQTTIiLCJQVFA0QTMiLCJQUFAxUjE0QSIsIkNSSVAyIiwiQURBTVRTMSIsIkNTUlAyIiwiTkRVRkE0TDIiLCJUUE0xIiwiTUFQMUIiLCJGUlpCIiwiUFJLQ0RCUCIsIkNTUlAxIiwiQ0FWMSIsIkFEQU1UUzQiLCJHSkE0IiwiUkdTNSIsIk1FRjJDIiwiQ0FMTTIiLCJBUE9MRDEiLCJPQVoyIiwiTUdTVDMiLCJJU1lOQTEiLCJDUE0iLCJQR0YiLCJHVUNZMUIzIiwiVUJBMiIsIllJRjFBIiwiUEhMREExIiwiTkRSRzIiLCJJRDMiLCJSR1MxNiIsIkNZQjVSMyIsIkNSWUFCIiwiT0xGTUwyQSIsIlRJTVAzIiwiR1VDWTFBMyIsIkZJTElQMSIsIkZBTTEzQyIsIk5EVUZTNCIsIklUR0IxIiwiS0NORTQiLCJDUEUiKSxncyksXSwyLG1lYW4pCmRDQUY9YXBwbHkoYWNjX2NhZkBhc3NheXMkUk5BQHNjYWxlLmRhdGFbaW50ZXJzZWN0KGMoIkNPTDFBMSIsIlRIQlMyIiwiQ1RIUkMxIiwiQ09MM0ExIiwiTFVNIiwiQ09MMUEyIiwiTEdBTFMxIiwiQ09MNUExIiwiUE9TVE4iLCJTRVJQSU5FMSIsIkxPWEwyIiwiQ09MMTFBMSIsIkNUU0siLCJDT0wxMkExIiwiTU1QMiIsIklOSEJBIiwiVE5GQUlQNiIsIlZDQU4iLCJBREFNMTIiLCJUSFkxIiwiRk4xIiwiU1RFQVAxIiwiU1BPTjIiLCJQTEFVUiIsIlNQSEsxIiwiTE9YIiwiRU1QMSIsIkFOR1BUTDIiLCJSQVJSRVMyIiwiU1VMRjEiLCJJR0ZCUDMiLCJDT0w4QTEiLCJHUkVNMSIsIkRDTiIsIklUR0E1IiwiQU5UWFIxIiwiUklOMiIsIlRNRU0xMTkiLCJUTkZSU0YxMkEiLCJQNEhBMyIsIkNSQUJQMiIsIlRQTTQiLCJMT1hMMSIsIkNQWE0xIiwiQ09MNkExIiwiQVNQTiIsIlBETElNNCIsIklUR0ExMSIsIlBSU1MyMyIsIkNPTDZBMiIsIlNGUlAyIiwiUExBVSIsIllJRjFBIiwiU05BSTIiLCJDMVMiLCJUTUVNMTc2QiIsIkNUR0YiLCJNT1JGNEwyIiwiVUFQMSIsIlNFUlBJTkYxIiwiSVRHQjEiLCJUR0ZCSSIsIkhUUkEzIiwiQzFSIiwiVElNUDEiLCJMTU5BIiwiQ1lQMUIxIiwiTUdQIiwiQU5HUFRMNCIpLGdzKSxdLDIsbWVhbikKaUNBRj1hcHBseShhY2NfY2FmQGFzc2F5cyRSTkFAc2NhbGUuZGF0YVtpbnRlcnNlY3QoYygiQ0ZEIiwiR1BDMyIsIkMzIiwiQURIMUIiLCJJR0YxIiwiRUZFTVAxIiwiUE9ETiIsIlNFUFAxIiwiQ1hDTDEyIiwiQUJJM0JQIiwiRkJMTjEiLCJNR1NUMSIsIk1GQVA0IiwiUExBMkcyQSIsIkRQVCIsIldJU1AyIiwiQ0NEQzgwIiwiU0ZSUDIiLCJQVEdEUyIsIkRDTiIsIk1HUCIsIkMxUyIsIklHRkJQNiIsIkdTTiIsIlRNRU0xNzZBIiwiRklCSU4iLCJUTUVNMTc2QiIsIlNFUlBJTkYxIiwiRkhMMSIsIkdQWDMiLCJDVEdGIiwiQzFSIiwiU0ZSUDQiLCJDWVAxQjEiLCJDU1QzIiwiU0xDNDBBMSIsIkZITDIiLCJFTE4iLCJLTEY0IiwiUkFSUkVTMSIsIkNZUjYxIiwiSUdGQlA1IiksZ3MpLF0sMixtZWFuKQppQ0FGMj1hcHBseShhY2NfY2FmQGFzc2F5cyRSTkFAc2NhbGUuZGF0YVtpbnRlcnNlY3QoYygiSUVSMyIsIkNYQ0wyIiwiSUNBTTEiLCJUTkZBSVAyIiwiTkZLQklBIiwiTlI0QTEiLCJDQ0wyIiwiU09EMiIsIkZPU0IiLCJQSU0xIiwiWkZQMzYiLCJDTFUiLCJBQkwyIiwiR0VNIiwiTlI0QTMiLCJBUE9EIiwiU0FUMSIsIlVBUDEiLCJPR04iLCJHRlBUMiIsIkpVTkIiLCJUSEJTMSIsIkNES04xQSIsIkMzIiwiQ1lQMUIxIiwiRUdSMSIsIkFCSTNCUCIsIkdBREQ0NUIiLCJEVVNQMSIsIlJBUlJFUzEiLCJDU1QzIiksZ3MpLF0sMixtZWFuKQpwQ0FGPWFwcGx5KGFjY19jYWZAYXNzYXlzJFJOQUBzY2FsZS5kYXRhW2ludGVyc2VjdChjKCJOVVNBUDEiLCJESUFQSDMiLCJMT1hMMiIsIkFEQU0xMiIsIkxPWCIsIlBPU1ROIiwiVEhZMSIsIkNEMjQ4IiwiRk4xIiwiQ09MMTJBMSIsIkNUSFJDMSIsIkNPTDVBMSIsIkxPWEwxIiwiQ09MMUExIiwiQ09MOEExIiwiQ09MNkExIiwiQ09MNkEyIiksZ3MpLF0sMixtZWFuKQphY2NfY2FmPUFkZE1ldGFEYXRhKGFjY19jYWYsbXlDQUYsInBhbi5teUNBRiIpCmFjY19jYWY9QWRkTWV0YURhdGEoYWNjX2NhZixkQ0FGLCJwYW4uZENBRiIpCmFjY19jYWY9QWRkTWV0YURhdGEoYWNjX2NhZixpQ0FGLCJwYW4uaUNBRiIpCmFjY19jYWY9QWRkTWV0YURhdGEoYWNjX2NhZixpQ0FGMiwicGFuLmlDQUYyIikKYWNjX2NhZj1BZGRNZXRhRGF0YShhY2NfY2FmLHBDQUYsInBhbi5wQ0FGIikKCnBjMnVzZT0xOjExCmFjY19jYWYgPC0gUnVuUENBKGFjY19jYWYsIGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhvYmplY3QgPSBhY2NfY2FmKSkKcGNhcGxvdCA8LSBQQ0FQbG90KGFjY19jYWYsIGxhYmVsID0gRkFMU0UpCmVsYm93cGxvdCA8LSBFbGJvd1Bsb3QoYWNjX2NhZiwgbmRpbXMgPSA1MCkgIyBjaGVja2luZyB0aGUgZGltZW5zaW9uYWxpdHkgCmFjY19jYWYgPC0gRmluZE5laWdoYm9ycyhhY2NfY2FmLCBkaW1zID0gcGMydXNlKQphY2NfY2FmIDwtIEZpbmRDbHVzdGVycyhhY2NfY2FmLCByZXNvbHV0aW9uID0gY2x1c19yZXMpCmFjY19jYWYgPC0gUnVuVU1BUChhY2NfY2FmLCBkaW1zID0gcGMydXNlKQpEaW1QbG90KG9iamVjdCA9IGFjY19jYWYsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDAuNSwgbGFiZWwgPSBUUlVFKQoKRmVhdHVyZVBsb3QoYWNjX2NhZiwgInBhbi5teUNBRiIsIHB0LnNpemUgPSAwLjUsIGNvbHMgPSBjKCJibHVlIiwieWVsbG93IikpCkZlYXR1cmVQbG90KGFjY19jYWYsICJwYW4uZENBRiIsIHB0LnNpemUgPSAwLjUsIGNvbHMgPSBjKCJibHVlIiwieWVsbG93IikpCkZlYXR1cmVQbG90KGFjY19jYWYsICJwYW4uaUNBRiIsIHB0LnNpemUgPSAwLjUsIGNvbHMgPSBjKCJibHVlIiwieWVsbG93IikpCkZlYXR1cmVQbG90KGFjY19jYWYsICJwYW4uaUNBRjIiLCBwdC5zaXplID0gMC41LCBjb2xzID0gYygiYmx1ZSIsInllbGxvdyIpKQpGZWF0dXJlUGxvdChhY2NfY2FmLCAicGFuLnBDQUYiLCBwdC5zaXplID0gMC41LCBjb2xzID0gYygiYmx1ZSIsInllbGxvdyIpKQpgYGAK