1. Load Libraries

2. load seurat object

#Load Seurat Object L7
load("../0-robj/5-Harmony_Integrated_All_samples_Merged_CD4Tcells_final_Resolution_Selected_0.8_ADT_Normalized_cleaned_mt.robj")


All_samples_Merged
An object of class Seurat 
62900 features across 49305 samples within 6 assays 
Active assay: SCT (26176 features, 3000 variable features)
 3 layers present: counts, data, scale.data
 5 other assays present: RNA, ADT, prediction.score.celltype.l1, prediction.score.celltype.l2, prediction.score.celltype.l3
 5 dimensional reductions calculated: integrated_dr, ref.umap, pca, umap, harmony

3. Set Up Identifiers for Clustering

# Assign cluster identities to the Seurat object
Idents(All_samples_Merged) <- "seurat_clusters"

DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line",label = T, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters",label = T, label.box = T)

4. Differential Expression Analysis

4.1 Using MAST with SCT and Latent Variables (Batch Correction)

# Set the default assay to SCT
DefaultAssay(All_samples_Merged) <- "SCT"

markers_mast_SCT <- FindMarkers(
  All_samples_Merged,
  ident.1 = c("5", "9", "1", "2", "6", "8", "4", "0", "7", "11", "12", "13"), # Cell lines-Malignant
  ident.2 = c("3", "10"), # Normal CD4 T cells
  assay = "SCT",
  test.use = "MAST",
  latent.vars = c("cell_line") # Adjust for batch effects
  )
Warning in asMethod(object): sparse->dense coercion: allocating vector of size
5.3 GiB
Warning in new_with_repaired_slots(classname = method, design = colData(sca), : Dropping illegal slot(s) norm.method for class BayesGLMlike.  
                    This likely indicates a bug in an upstream package.

Done!
Combining coefficients and standard errors
Calculating log-fold changes
Calculating likelihood ratio tests
Refitting on reduced model...

Done!
write.csv(markers_mast_SCT, file = "../0-robj/RNA_SCT_test_default_pct_fc_parameters/1-MAST_with_SCT_batch_cellline_as_Covariate.csv", row.names = TRUE)

4.2 Using MAST with RNA and Latent Variables (Batch Correction)

library(magrittr)

Attaching package: 'magrittr'
The following object is masked from 'package:GenomicRanges':

    subtract
# Set the default assay to RNA
DefaultAssay(All_samples_Merged) <- "RNA"

# Normalize the RNA assay but DO NOT scale the data
All_samples_Merged <- All_samples_Merged %>%
  NormalizeData(normalization.method = "LogNormalize", scale.factor = 10000)
Normalizing layer: counts
markers_mast_RNA <- FindMarkers(
  All_samples_Merged,
 ident.1 = c("5", "9", "1", "2", "6", "8", "4", "0", "7", "11", "12", "13"), # Cell lines-Malignant
  ident.2 = c("3", "10"), # Normal CD4 T cells
  assay = "RNA",
  test.use = "MAST",
  latent.vars = c("cell_line") # Adjust for batch effects
  )
Warning in asMethod(object): sparse->dense coercion: allocating vector of size
5.1 GiB

Done!
Combining coefficients and standard errors
Calculating log-fold changes
Calculating likelihood ratio tests
Refitting on reduced model...

Done!
write.csv(markers_mast_RNA, file = "../0-robj/RNA_SCT_test_default_pct_fc_parameters/2-MAST_with_RNA_batch_cellline_as_Covariate.csv", row.names = TRUE)

5. Compute Mean Expression for Groups

library(Seurat)
library(dplyr)

# Define cell groups
group1_cells <- WhichCells(All_samples_Merged, idents = c("5", "9", "1", "2", "6", "8", "4", "0", "7", "11", "12", "13"))  # Malignant CD4+ T cells
group2_cells <- WhichCells(All_samples_Merged, idents = c("3", "10"))  # Normal CD4+ T cells

# Extract normalized expression values for both assays
expression_data_RNA <- GetAssayData(All_samples_Merged, assay = "RNA", layer = "data")  # Log-normalized counts
expression_data_SCT <- GetAssayData(All_samples_Merged, assay = "SCT", layer = "data")  # SCT-normalized counts (not Pearson residuals)

# Function to calculate mean expression for each group
calculate_mean_expression <- function(markers, group1_cells, group2_cells, expression_data) {
  group1_mean <- rowMeans(expression_data[, group1_cells, drop = FALSE], na.rm = TRUE)
  group2_mean <- rowMeans(expression_data[, group2_cells, drop = FALSE], na.rm = TRUE)
  
  markers <- markers %>%
    rownames_to_column("gene") %>%
    mutate(mean_expr_group1 = group1_mean[gene],
           mean_expr_group2 = group2_mean[gene])
  
  return(markers)
}

# Compute mean expression for RNA and SCT assays
markers_mast_RNA <- calculate_mean_expression(markers_mast_RNA, group1_cells, group2_cells, expression_data_RNA)
markers_mast_SCT <- calculate_mean_expression(markers_mast_SCT, group1_cells, group2_cells, expression_data_SCT)

# Save updated results with mean expression

write.csv(markers_mast_SCT, file = "../0-robj/RNA_SCT_test_default_pct_fc_parameters/1-MAST_with_SCT_batch_cellline_as_Covariate_with_meanExpression.csv", row.names = TRUE)

write.csv(markers_mast_RNA, file = "../0-robj/RNA_SCT_test_default_pct_fc_parameters/2-MAST_with_RNA_batch_cellline_as_Covariate_with_meanExpression.csv", row.names = TRUE)

6. Summarize Results

6.1 Summary Function

summarize_markers <- function(markers) {
  num_pval0 <- sum(markers$p_val_adj == 0)
  num_pval1 <- sum(markers$p_val_adj == 1)
  num_significant <- sum(markers$p_val_adj < 0.05)
  num_upregulated <- sum(markers$avg_log2FC > 1)
  num_downregulated <- sum(markers$avg_log2FC < -1)
  
  cat("Number of genes with p_val_adj = 0:", num_pval0, "\n")
  cat("Number of genes with p_val_adj = 1:", num_pval1, "\n")
  cat("Number of significant genes (p_val_adj < 0.05):", num_significant, "\n")
  cat("Number of upregulated genes (avg_log2FC > 1):", num_upregulated, "\n")
  cat("Number of downregulated genes (avg_log2FC < -1):", num_downregulated, "\n")
}

6.2 Summarize Markers1 (MAST with SCT Assay)

cat("Markers1 Summary (MAST with SCT Assay):\n")
Markers1 Summary (MAST with SCT Assay):
summarize_markers(markers_mast_SCT)
Number of genes with p_val_adj = 0: 72 
Number of genes with p_val_adj = 1: 8299 
Number of significant genes (p_val_adj < 0.05): 5084 
Number of upregulated genes (avg_log2FC > 1): 9917 
Number of downregulated genes (avg_log2FC < -1): 789 

6.3 Summary for Markers2 (MAST with RNA Assay)

cat("Markers2 Summary (MAST with RNA Assay):\n")
Markers2 Summary (MAST with RNA Assay):
summarize_markers(markers_mast_RNA)
Number of genes with p_val_adj = 0: 78 
Number of genes with p_val_adj = 1: 4853 
Number of significant genes (p_val_adj < 0.05): 8198 
Number of upregulated genes (avg_log2FC > 1): 4183 
Number of downregulated genes (avg_log2FC < -1): 2606 

Compare Results Between SCT and RNA Assays

### Compare Results Between RNA and SCT Assays

# Load gene sets
genes_mast_sct <- markers_mast_SCT$gene
genes_mast_rna <- markers_mast_RNA$gene
common_genes_mast <- intersect(genes_mast_sct, genes_mast_rna)

cat("MAST: Common Genes Between SCT and RNA:", length(common_genes_mast), "\n")
MAST: Common Genes Between SCT and RNA: 13478 

7. Visualization

7.1 Volcano Plot for MAST-SCT with Batch Correction

EnhancedVolcano(markers_mast_SCT,
                lab = markers_mast_SCT$gene,
                x = "avg_log2FC",
                y = "p_val_adj",
                title = "Malignant_vs_Normal_MAST_SCT",
                pCutoff = 0.05,
                FCcutoff = 1.0)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest
non-zero p-value...

7.2 Volcano Plot MAST-RNA with Batch Correction

EnhancedVolcano(markers_mast_RNA,
                lab = markers_mast_RNA$gene,
                x = "avg_log2FC",
                y = "p_val_adj",
                title = "Malignant_vs_Normal_MAST_RNA",
                pCutoff = 0.05,
                FCcutoff = 1.0)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest
non-zero p-value...

7.3 Volcano Plot MAST-RNA with Batch Correction

### 1. Load Data and Prepare for Comparison

library(ggplot2)

df_sct <- read.csv("../0-robj/RNA_SCT_test_default_pct_fc_parameters/1-MAST_with_SCT_batch_cellline_as_Covariate.csv", row.names = 1)
df_rna <- read.csv("../0-robj/RNA_SCT_test_default_pct_fc_parameters/2-MAST_with_RNA_batch_cellline_as_Covariate.csv", row.names = 1)

df_sct$assay <- "SCT"
df_rna$assay <- "RNA"

df_combined <- rbind(df_sct, df_rna)

### 2. Volcano Plot for SCT vs RNA Comparison

ggplot(df_combined, aes(x = avg_log2FC, y = -log10(p_val_adj), color = assay)) +
  geom_point(alpha = 0.7) +
  theme_minimal() +
  labs(title = "Volcano Plot: RNA vs SCT", x = "Log2 Fold Change", y = "-Log10 Adjusted P-value") +
  scale_color_manual(values = c("SCT" = "blue", "RNA" = "red"))

7.4 Correlation of Log2 Fold Change Between RNA and SCT

# Correlation of Log2 Fold Change Between RNA and SCT
# Goal: See if genes have consistent fold changes between RNA and SCT normalization.


library(dplyr)  # Load dplyr to use rownames_to_column


# Convert row names to a "gene" column
df_sct <- df_sct %>% rownames_to_column(var = "gene")
df_rna <- df_rna %>% rownames_to_column(var = "gene")

# Merge datasets by gene
df_merged <- merge(df_sct, df_rna, by = "gene", suffixes = c("_SCT", "_RNA"))

# Scatter plot of log2FC values
ggplot(df_merged, aes(x = avg_log2FC_SCT, y = avg_log2FC_RNA)) +
  geom_point(alpha = 0.7, color = "blue") +
  geom_smooth(method = "lm", color = "red", linetype = "dashed") +
  theme_minimal() +
  labs(title = "Log2 Fold Change Comparison: SCT vs RNA",
       x = "SCT Log2 Fold Change",
       y = "RNA Log2 Fold Change") +
  geom_abline(slope = 1, intercept = 0, linetype = "dotted", color = "black")
`geom_smooth()` using formula = 'y ~ x'

7.5 Find overlap between the top 100 most significant genes:

cor(df_merged$avg_log2FC_SCT, df_merged$avg_log2FC_RNA, use = "complete.obs")
[1] 0.9923688
# Higher correlation (~0.8-1.0) suggests consistency between methods.
# Lower correlation (<0.6) may indicate different normalization effects.


library(ggplot2)
library(dplyr)

# Define a broader list of known Sezary genes
sezary_genes <- c("KIR3DL2", "TOX", "TWIST1", "CD52", "CCR4", "IL2RA", "CD7", "DPP4", "CCR7", "GATA3", "FOXP3", "CCR7", "CD70", "PLS3", "PDCD1")

# Filter the merged data to include only the known Sezary genes
df_filtered <- df_merged %>%
  filter(gene %in% sezary_genes)

# Volcano plot showing only the known Sezary genes with gene names
ggplot(df_filtered, aes(x = avg_log2FC_SCT, y = -log10(p_val_adj_SCT), color = gene)) +
  geom_point(alpha = 0.7) +
  geom_text(aes(label = gene), vjust = 1.5, hjust = 0.5, size = 3, color = "black") +  # Adding gene names
  theme_minimal() +
  labs(title = "Volcano Plot: Known Sezary Genes (SCT Assay)", 
       x = "Log2 Fold Change (SCT)", 
       y = "-Log10 Adjusted P-value") +
  scale_color_manual(values = c(
                      "KIR3DL2" = "#1f77b4",  # blue
                      "TOX" = "#ff7f0e",  # orange
                      "TWIST1" = "#2ca02c",  # green
                      "CD52" = "#9467bd",  # purple
                      "CCR4" = "#8c564b",  # brown
                      "IL2RA" = "#e377c2",  # pink
                      "CD7" = "#7f7f7f",  # gray
                      "DPP4" = "#bcbd22",  # yellow-green
                      "CCR7" = "#17becf",  # cyan
                      "GATA3" = "#d62728",  # red
                      "FOXP3" = "#8a2be2",  # blue-violet
                      "DNM3" = "#ff6347",  # tomato
                      "NCR1" = "#3cb371",  # medium sea green
                      "CD70" = "#ff1493",  # deep pink
                      "AIRE" = "#00bfff",  # deep sky blue
                      "PDCD1 (PD-1)" = "#4c72b0",  # steel blue
                      "CD274 (PD-L1)" = "#c5b0d5"  # light purple
)) + 
theme(legend.position = "top")

library(ggplot2)
library(dplyr)

# Define the list of known Sezary genes
sezary_genes <- c("KIR3DL2", "TOX", "TWIST1", "CD52", "CCR4", "IL2RA", "CD7", "DPP4", "CCR7", "GATA3", "FOXP3", "CCR7", "CD70", "PLS3", "PDCD1")

# Filter the merged data to include only the known Sezary genes for RNA data
df_filtered_rna <- df_merged %>%
  filter(gene %in% sezary_genes)

# Volcano plot showing only the known Sezary genes for RNA assay with gene names
ggplot(df_filtered_rna, aes(x = avg_log2FC_RNA, y = -log10(p_val_adj_RNA), color = gene)) +
  geom_point(alpha = 0.7) +
  geom_text(aes(label = gene), vjust = 1.5, hjust = 0.5, size = 3, color = "black") +  # Adding gene names
  theme_minimal() +
  labs(title = "Volcano Plot: Known Sezary Genes (RNA Assay)", 
       x = "Log2 Fold Change (RNA)", 
       y = "-Log10 Adjusted P-value") +
  scale_color_manual(values = c(
                      "KIR3DL2" = "#1f77b4",  # blue
                      "TOX" = "#ff7f0e",  # orange
                      "TWIST1" = "#2ca02c",  # green
                      "CD52" = "#9467bd",  # purple
                      "CCR4" = "#8c564b",  # brown
                      "IL2RA" = "#e377c2",  # pink
                      "CD7" = "#7f7f7f",  # gray
                      "DPP4" = "#bcbd22",  # yellow-green
                      "CCR7" = "#17becf",  # cyan
                      "GATA3" = "#d62728",  # red
                      "FOXP3" = "#8a2be2",  # blue-violet
                      "DNM3" = "#ff6347",  # tomato
                      "NCR1" = "#3cb371",  # medium sea green
                      "CD70" = "#ff1493",  # deep pink
                      "AIRE" = "#00bfff",  # deep sky blue
                      "PDCD1 (PD-1)" = "#4c72b0",  # steel blue
                      "CD274 (PD-L1)" = "#c5b0d5"  # light purple
)) + 
theme(legend.position = "top")

LS0tCnRpdGxlOiAiTUFTVCBvbiBTQ1QgYW5kIFJOQSBhc3NheSBhbmQgaXRzIGNvbXBhcmlzb24gdG8gc2VlIHdoaWNoIGlzIGJldHRlciB3aXRoIGRlZmF1bHQgc2V0dGluZ3MiCmF1dGhvcjogIk5hc2lyIE1haG1vb2QgQWJiYXNpIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwotLS0KCiMgMS4gTG9hZCBMaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KE1BU1QpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGhlYXRtYXApCmxpYnJhcnkodGliYmxlKQpgYGAKCgojIDIuIGxvYWQgc2V1cmF0IG9iamVjdApgYGB7ciBsb2FkX3NldXJhdH0KI0xvYWQgU2V1cmF0IE9iamVjdCBMNwpsb2FkKCIuLi8wLXJvYmovNS1IYXJtb255X0ludGVncmF0ZWRfQWxsX3NhbXBsZXNfTWVyZ2VkX0NENFRjZWxsc19maW5hbF9SZXNvbHV0aW9uX1NlbGVjdGVkXzAuOF9BRFRfTm9ybWFsaXplZF9jbGVhbmVkX210LnJvYmoiKQoKCkFsbF9zYW1wbGVzX01lcmdlZAoKCgpgYGAKCiMgMy4gU2V0IFVwIElkZW50aWZpZXJzIGZvciBDbHVzdGVyaW5nCmBgYHtyfQojIEFzc2lnbiBjbHVzdGVyIGlkZW50aXRpZXMgdG8gdGhlIFNldXJhdCBvYmplY3QKSWRlbnRzKEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gInNldXJhdF9jbHVzdGVycyIKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKCmBgYAoKIyA0LiAgRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gQW5hbHlzaXMKCiMjIDQuMSBVc2luZyBNQVNUIHdpdGggU0NUIGFuZCBMYXRlbnQgVmFyaWFibGVzIChCYXRjaCBDb3JyZWN0aW9uKQpgYGB7cn0KCiMgU2V0IHRoZSBkZWZhdWx0IGFzc2F5IHRvIFNDVApEZWZhdWx0QXNzYXkoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAiU0NUIgoKbWFya2Vyc19tYXN0X1NDVCA8LSBGaW5kTWFya2VycygKICBBbGxfc2FtcGxlc19NZXJnZWQsCiAgaWRlbnQuMSA9IGMoIjUiLCAiOSIsICIxIiwgIjIiLCAiNiIsICI4IiwgIjQiLCAiMCIsICI3IiwgIjExIiwgIjEyIiwgIjEzIiksICMgQ2VsbCBsaW5lcy1NYWxpZ25hbnQKICBpZGVudC4yID0gYygiMyIsICIxMCIpLCAjIE5vcm1hbCBDRDQgVCBjZWxscwogIGFzc2F5ID0gIlNDVCIsCiAgdGVzdC51c2UgPSAiTUFTVCIsCiAgbGF0ZW50LnZhcnMgPSBjKCJjZWxsX2xpbmUiKSAjIEFkanVzdCBmb3IgYmF0Y2ggZWZmZWN0cwogICkKCndyaXRlLmNzdihtYXJrZXJzX21hc3RfU0NULCBmaWxlID0gIi4uLzAtcm9iai9STkFfU0NUX3Rlc3RfZGVmYXVsdF9wY3RfZmNfcGFyYW1ldGVycy8xLU1BU1Rfd2l0aF9TQ1RfYmF0Y2hfY2VsbGxpbmVfYXNfQ292YXJpYXRlLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKIyMgNC4yIFVzaW5nIE1BU1Qgd2l0aCBSTkEgYW5kIExhdGVudCBWYXJpYWJsZXMgKEJhdGNoIENvcnJlY3Rpb24pCmBgYHtyfQoKCmxpYnJhcnkobWFncml0dHIpCgojIFNldCB0aGUgZGVmYXVsdCBhc3NheSB0byBSTkEKRGVmYXVsdEFzc2F5KEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gIlJOQSIKCiMgTm9ybWFsaXplIHRoZSBSTkEgYXNzYXkgYnV0IERPIE5PVCBzY2FsZSB0aGUgZGF0YQpBbGxfc2FtcGxlc19NZXJnZWQgPC0gQWxsX3NhbXBsZXNfTWVyZ2VkICU+JQogIE5vcm1hbGl6ZURhdGEobm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwgc2NhbGUuZmFjdG9yID0gMTAwMDApCgoKbWFya2Vyc19tYXN0X1JOQSA8LSBGaW5kTWFya2VycygKICBBbGxfc2FtcGxlc19NZXJnZWQsCiBpZGVudC4xID0gYygiNSIsICI5IiwgIjEiLCAiMiIsICI2IiwgIjgiLCAiNCIsICIwIiwgIjciLCAiMTEiLCAiMTIiLCAiMTMiKSwgIyBDZWxsIGxpbmVzLU1hbGlnbmFudAogIGlkZW50LjIgPSBjKCIzIiwgIjEwIiksICMgTm9ybWFsIENENCBUIGNlbGxzCiAgYXNzYXkgPSAiUk5BIiwKICB0ZXN0LnVzZSA9ICJNQVNUIiwKICBsYXRlbnQudmFycyA9IGMoImNlbGxfbGluZSIpICMgQWRqdXN0IGZvciBiYXRjaCBlZmZlY3RzCiAgKQoKd3JpdGUuY3N2KG1hcmtlcnNfbWFzdF9STkEsIGZpbGUgPSAiLi4vMC1yb2JqL1JOQV9TQ1RfdGVzdF9kZWZhdWx0X3BjdF9mY19wYXJhbWV0ZXJzLzItTUFTVF93aXRoX1JOQV9iYXRjaF9jZWxsbGluZV9hc19Db3ZhcmlhdGUuY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkKYGBgCgoKCiMgNS4gQ29tcHV0ZSBNZWFuIEV4cHJlc3Npb24gZm9yIEdyb3VwcwpgYGB7cn0KbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoZHBseXIpCgojIERlZmluZSBjZWxsIGdyb3Vwcwpncm91cDFfY2VsbHMgPC0gV2hpY2hDZWxscyhBbGxfc2FtcGxlc19NZXJnZWQsIGlkZW50cyA9IGMoIjUiLCAiOSIsICIxIiwgIjIiLCAiNiIsICI4IiwgIjQiLCAiMCIsICI3IiwgIjExIiwgIjEyIiwgIjEzIikpICAjIE1hbGlnbmFudCBDRDQrIFQgY2VsbHMKZ3JvdXAyX2NlbGxzIDwtIFdoaWNoQ2VsbHMoQWxsX3NhbXBsZXNfTWVyZ2VkLCBpZGVudHMgPSBjKCIzIiwgIjEwIikpICAjIE5vcm1hbCBDRDQrIFQgY2VsbHMKCiMgRXh0cmFjdCBub3JtYWxpemVkIGV4cHJlc3Npb24gdmFsdWVzIGZvciBib3RoIGFzc2F5cwpleHByZXNzaW9uX2RhdGFfUk5BIDwtIEdldEFzc2F5RGF0YShBbGxfc2FtcGxlc19NZXJnZWQsIGFzc2F5ID0gIlJOQSIsIGxheWVyID0gImRhdGEiKSAgIyBMb2ctbm9ybWFsaXplZCBjb3VudHMKZXhwcmVzc2lvbl9kYXRhX1NDVCA8LSBHZXRBc3NheURhdGEoQWxsX3NhbXBsZXNfTWVyZ2VkLCBhc3NheSA9ICJTQ1QiLCBsYXllciA9ICJkYXRhIikgICMgU0NULW5vcm1hbGl6ZWQgY291bnRzIChub3QgUGVhcnNvbiByZXNpZHVhbHMpCgojIEZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBtZWFuIGV4cHJlc3Npb24gZm9yIGVhY2ggZ3JvdXAKY2FsY3VsYXRlX21lYW5fZXhwcmVzc2lvbiA8LSBmdW5jdGlvbihtYXJrZXJzLCBncm91cDFfY2VsbHMsIGdyb3VwMl9jZWxscywgZXhwcmVzc2lvbl9kYXRhKSB7CiAgZ3JvdXAxX21lYW4gPC0gcm93TWVhbnMoZXhwcmVzc2lvbl9kYXRhWywgZ3JvdXAxX2NlbGxzLCBkcm9wID0gRkFMU0VdLCBuYS5ybSA9IFRSVUUpCiAgZ3JvdXAyX21lYW4gPC0gcm93TWVhbnMoZXhwcmVzc2lvbl9kYXRhWywgZ3JvdXAyX2NlbGxzLCBkcm9wID0gRkFMU0VdLCBuYS5ybSA9IFRSVUUpCiAgCiAgbWFya2VycyA8LSBtYXJrZXJzICU+JQogICAgcm93bmFtZXNfdG9fY29sdW1uKCJnZW5lIikgJT4lCiAgICBtdXRhdGUobWVhbl9leHByX2dyb3VwMSA9IGdyb3VwMV9tZWFuW2dlbmVdLAogICAgICAgICAgIG1lYW5fZXhwcl9ncm91cDIgPSBncm91cDJfbWVhbltnZW5lXSkKICAKICByZXR1cm4obWFya2VycykKfQoKIyBDb21wdXRlIG1lYW4gZXhwcmVzc2lvbiBmb3IgUk5BIGFuZCBTQ1QgYXNzYXlzCm1hcmtlcnNfbWFzdF9STkEgPC0gY2FsY3VsYXRlX21lYW5fZXhwcmVzc2lvbihtYXJrZXJzX21hc3RfUk5BLCBncm91cDFfY2VsbHMsIGdyb3VwMl9jZWxscywgZXhwcmVzc2lvbl9kYXRhX1JOQSkKbWFya2Vyc19tYXN0X1NDVCA8LSBjYWxjdWxhdGVfbWVhbl9leHByZXNzaW9uKG1hcmtlcnNfbWFzdF9TQ1QsIGdyb3VwMV9jZWxscywgZ3JvdXAyX2NlbGxzLCBleHByZXNzaW9uX2RhdGFfU0NUKQoKIyBTYXZlIHVwZGF0ZWQgcmVzdWx0cyB3aXRoIG1lYW4gZXhwcmVzc2lvbgoKd3JpdGUuY3N2KG1hcmtlcnNfbWFzdF9TQ1QsIGZpbGUgPSAiLi4vMC1yb2JqL1JOQV9TQ1RfdGVzdF9kZWZhdWx0X3BjdF9mY19wYXJhbWV0ZXJzLzEtTUFTVF93aXRoX1NDVF9iYXRjaF9jZWxsbGluZV9hc19Db3ZhcmlhdGVfd2l0aF9tZWFuRXhwcmVzc2lvbi5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQoKd3JpdGUuY3N2KG1hcmtlcnNfbWFzdF9STkEsIGZpbGUgPSAiLi4vMC1yb2JqL1JOQV9TQ1RfdGVzdF9kZWZhdWx0X3BjdF9mY19wYXJhbWV0ZXJzLzItTUFTVF93aXRoX1JOQV9iYXRjaF9jZWxsbGluZV9hc19Db3ZhcmlhdGVfd2l0aF9tZWFuRXhwcmVzc2lvbi5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQoKYGBgCgojIDYuIFN1bW1hcml6ZSBSZXN1bHRzCgojIyA2LjEgU3VtbWFyeSBGdW5jdGlvbgpgYGB7cn0Kc3VtbWFyaXplX21hcmtlcnMgPC0gZnVuY3Rpb24obWFya2VycykgewogIG51bV9wdmFsMCA8LSBzdW0obWFya2VycyRwX3ZhbF9hZGogPT0gMCkKICBudW1fcHZhbDEgPC0gc3VtKG1hcmtlcnMkcF92YWxfYWRqID09IDEpCiAgbnVtX3NpZ25pZmljYW50IDwtIHN1bShtYXJrZXJzJHBfdmFsX2FkaiA8IDAuMDUpCiAgbnVtX3VwcmVndWxhdGVkIDwtIHN1bShtYXJrZXJzJGF2Z19sb2cyRkMgPiAxKQogIG51bV9kb3ducmVndWxhdGVkIDwtIHN1bShtYXJrZXJzJGF2Z19sb2cyRkMgPCAtMSkKICAKICBjYXQoIk51bWJlciBvZiBnZW5lcyB3aXRoIHBfdmFsX2FkaiA9IDA6IiwgbnVtX3B2YWwwLCAiXG4iKQogIGNhdCgiTnVtYmVyIG9mIGdlbmVzIHdpdGggcF92YWxfYWRqID0gMToiLCBudW1fcHZhbDEsICJcbiIpCiAgY2F0KCJOdW1iZXIgb2Ygc2lnbmlmaWNhbnQgZ2VuZXMgKHBfdmFsX2FkaiA8IDAuMDUpOiIsIG51bV9zaWduaWZpY2FudCwgIlxuIikKICBjYXQoIk51bWJlciBvZiB1cHJlZ3VsYXRlZCBnZW5lcyAoYXZnX2xvZzJGQyA+IDEpOiIsIG51bV91cHJlZ3VsYXRlZCwgIlxuIikKICBjYXQoIk51bWJlciBvZiBkb3ducmVndWxhdGVkIGdlbmVzIChhdmdfbG9nMkZDIDwgLTEpOiIsIG51bV9kb3ducmVndWxhdGVkLCAiXG4iKQp9CgpgYGAKCiMjIDYuMiBTdW1tYXJpemUgTWFya2VyczEgKE1BU1Qgd2l0aCBTQ1QgQXNzYXkpCmBgYHtyfQpjYXQoIk1hcmtlcnMxIFN1bW1hcnkgKE1BU1Qgd2l0aCBTQ1QgQXNzYXkpOlxuIikKc3VtbWFyaXplX21hcmtlcnMobWFya2Vyc19tYXN0X1NDVCkKCmBgYAoKIyMgNi4zIFN1bW1hcnkgZm9yIE1hcmtlcnMyIChNQVNUIHdpdGggUk5BIEFzc2F5KQpgYGB7cn0KY2F0KCJNYXJrZXJzMiBTdW1tYXJ5IChNQVNUIHdpdGggUk5BIEFzc2F5KTpcbiIpCnN1bW1hcml6ZV9tYXJrZXJzKG1hcmtlcnNfbWFzdF9STkEpCmBgYAoKIyMgQ29tcGFyZSBSZXN1bHRzIEJldHdlZW4gU0NUIGFuZCBSTkEgQXNzYXlzCmBgYHtyfQojIyMgQ29tcGFyZSBSZXN1bHRzIEJldHdlZW4gUk5BIGFuZCBTQ1QgQXNzYXlzCgojIExvYWQgZ2VuZSBzZXRzCmdlbmVzX21hc3Rfc2N0IDwtIG1hcmtlcnNfbWFzdF9TQ1QkZ2VuZQpnZW5lc19tYXN0X3JuYSA8LSBtYXJrZXJzX21hc3RfUk5BJGdlbmUKY29tbW9uX2dlbmVzX21hc3QgPC0gaW50ZXJzZWN0KGdlbmVzX21hc3Rfc2N0LCBnZW5lc19tYXN0X3JuYSkKCmNhdCgiTUFTVDogQ29tbW9uIEdlbmVzIEJldHdlZW4gU0NUIGFuZCBSTkE6IiwgbGVuZ3RoKGNvbW1vbl9nZW5lc19tYXN0KSwgIlxuIikKCmBgYAoKCiMgNy4gVmlzdWFsaXphdGlvbgoKIyMgNy4xIFZvbGNhbm8gUGxvdCBmb3IgTUFTVC1TQ1Qgd2l0aCBCYXRjaCBDb3JyZWN0aW9uCmBgYHtyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9CgpFbmhhbmNlZFZvbGNhbm8obWFya2Vyc19tYXN0X1NDVCwKICAgICAgICAgICAgICAgIGxhYiA9IG1hcmtlcnNfbWFzdF9TQ1QkZ2VuZSwKICAgICAgICAgICAgICAgIHggPSAiYXZnX2xvZzJGQyIsCiAgICAgICAgICAgICAgICB5ID0gInBfdmFsX2FkaiIsCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJNYWxpZ25hbnRfdnNfTm9ybWFsX01BU1RfU0NUIiwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLjApCgpgYGAKCiMjIDcuMiBWb2xjYW5vIFBsb3QgTUFTVC1STkEgd2l0aCBCYXRjaCBDb3JyZWN0aW9uCmBgYHtyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9CgpFbmhhbmNlZFZvbGNhbm8obWFya2Vyc19tYXN0X1JOQSwKICAgICAgICAgICAgICAgIGxhYiA9IG1hcmtlcnNfbWFzdF9STkEkZ2VuZSwKICAgICAgICAgICAgICAgIHggPSAiYXZnX2xvZzJGQyIsCiAgICAgICAgICAgICAgICB5ID0gInBfdmFsX2FkaiIsCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJNYWxpZ25hbnRfdnNfTm9ybWFsX01BU1RfUk5BIiwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLjApCgpgYGAKCiMjIDcuMyBWb2xjYW5vIFBsb3QgTUFTVC1STkEgd2l0aCBCYXRjaCBDb3JyZWN0aW9uCmBgYHtyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9CgojIyMgMS4gTG9hZCBEYXRhIGFuZCBQcmVwYXJlIGZvciBDb21wYXJpc29uCgpsaWJyYXJ5KGdncGxvdDIpCgpkZl9zY3QgPC0gcmVhZC5jc3YoIi4uLzAtcm9iai9STkFfU0NUX3Rlc3RfZGVmYXVsdF9wY3RfZmNfcGFyYW1ldGVycy8xLU1BU1Rfd2l0aF9TQ1RfYmF0Y2hfY2VsbGxpbmVfYXNfQ292YXJpYXRlLmNzdiIsIHJvdy5uYW1lcyA9IDEpCmRmX3JuYSA8LSByZWFkLmNzdigiLi4vMC1yb2JqL1JOQV9TQ1RfdGVzdF9kZWZhdWx0X3BjdF9mY19wYXJhbWV0ZXJzLzItTUFTVF93aXRoX1JOQV9iYXRjaF9jZWxsbGluZV9hc19Db3ZhcmlhdGUuY3N2Iiwgcm93Lm5hbWVzID0gMSkKCmRmX3NjdCRhc3NheSA8LSAiU0NUIgpkZl9ybmEkYXNzYXkgPC0gIlJOQSIKCmRmX2NvbWJpbmVkIDwtIHJiaW5kKGRmX3NjdCwgZGZfcm5hKQoKIyMjIDIuIFZvbGNhbm8gUGxvdCBmb3IgU0NUIHZzIFJOQSBDb21wYXJpc29uCgpnZ3Bsb3QoZGZfY29tYmluZWQsIGFlcyh4ID0gYXZnX2xvZzJGQywgeSA9IC1sb2cxMChwX3ZhbF9hZGopLCBjb2xvciA9IGFzc2F5KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjcpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90OiBSTkEgdnMgU0NUIiwgeCA9ICJMb2cyIEZvbGQgQ2hhbmdlIiwgeSA9ICItTG9nMTAgQWRqdXN0ZWQgUC12YWx1ZSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiU0NUIiA9ICJibHVlIiwgIlJOQSIgPSAicmVkIikpCgpgYGAKCgojIyA3LjQgQ29ycmVsYXRpb24gb2YgTG9nMiBGb2xkIENoYW5nZSBCZXR3ZWVuIFJOQSBhbmQgU0NUCmBgYHtyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9CgojIENvcnJlbGF0aW9uIG9mIExvZzIgRm9sZCBDaGFuZ2UgQmV0d2VlbiBSTkEgYW5kIFNDVAojIEdvYWw6IFNlZSBpZiBnZW5lcyBoYXZlIGNvbnNpc3RlbnQgZm9sZCBjaGFuZ2VzIGJldHdlZW4gUk5BIGFuZCBTQ1Qgbm9ybWFsaXphdGlvbi4KCgpsaWJyYXJ5KGRwbHlyKSAgIyBMb2FkIGRwbHlyIHRvIHVzZSByb3duYW1lc190b19jb2x1bW4KCgojIENvbnZlcnQgcm93IG5hbWVzIHRvIGEgImdlbmUiIGNvbHVtbgpkZl9zY3QgPC0gZGZfc2N0ICU+JSByb3duYW1lc190b19jb2x1bW4odmFyID0gImdlbmUiKQpkZl9ybmEgPC0gZGZfcm5hICU+JSByb3duYW1lc190b19jb2x1bW4odmFyID0gImdlbmUiKQoKIyBNZXJnZSBkYXRhc2V0cyBieSBnZW5lCmRmX21lcmdlZCA8LSBtZXJnZShkZl9zY3QsIGRmX3JuYSwgYnkgPSAiZ2VuZSIsIHN1ZmZpeGVzID0gYygiX1NDVCIsICJfUk5BIikpCgojIFNjYXR0ZXIgcGxvdCBvZiBsb2cyRkMgdmFsdWVzCmdncGxvdChkZl9tZXJnZWQsIGFlcyh4ID0gYXZnX2xvZzJGQ19TQ1QsIHkgPSBhdmdfbG9nMkZDX1JOQSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC43LCBjb2xvciA9ICJibHVlIikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiTG9nMiBGb2xkIENoYW5nZSBDb21wYXJpc29uOiBTQ1QgdnMgUk5BIiwKICAgICAgIHggPSAiU0NUIExvZzIgRm9sZCBDaGFuZ2UiLAogICAgICAgeSA9ICJSTkEgTG9nMiBGb2xkIENoYW5nZSIpICsKICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRvdHRlZCIsIGNvbG9yID0gImJsYWNrIikKYGBgCgoKIyMgNy41IEZpbmQgb3ZlcmxhcCBiZXR3ZWVuIHRoZSB0b3AgMTAwIG1vc3Qgc2lnbmlmaWNhbnQgZ2VuZXM6CmBgYHtyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9Cgpjb3IoZGZfbWVyZ2VkJGF2Z19sb2cyRkNfU0NULCBkZl9tZXJnZWQkYXZnX2xvZzJGQ19STkEsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQoKIyBIaWdoZXIgY29ycmVsYXRpb24gKH4wLjgtMS4wKSBzdWdnZXN0cyBjb25zaXN0ZW5jeSBiZXR3ZWVuIG1ldGhvZHMuCiMgTG93ZXIgY29ycmVsYXRpb24gKDwwLjYpIG1heSBpbmRpY2F0ZSBkaWZmZXJlbnQgbm9ybWFsaXphdGlvbiBlZmZlY3RzLgoKCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKCiMgRGVmaW5lIGEgYnJvYWRlciBsaXN0IG9mIGtub3duIFNlemFyeSBnZW5lcwpzZXphcnlfZ2VuZXMgPC0gYygiS0lSM0RMMiIsICJUT1giLCAiVFdJU1QxIiwgIkNENTIiLCAiQ0NSNCIsICJJTDJSQSIsICJDRDciLCAiRFBQNCIsICJDQ1I3IiwgIkdBVEEzIiwgIkZPWFAzIiwgIkNDUjciLCAiQ0Q3MCIsICJQTFMzIiwgIlBEQ0QxIikKCiMgRmlsdGVyIHRoZSBtZXJnZWQgZGF0YSB0byBpbmNsdWRlIG9ubHkgdGhlIGtub3duIFNlemFyeSBnZW5lcwpkZl9maWx0ZXJlZCA8LSBkZl9tZXJnZWQgJT4lCiAgZmlsdGVyKGdlbmUgJWluJSBzZXphcnlfZ2VuZXMpCgojIFZvbGNhbm8gcGxvdCBzaG93aW5nIG9ubHkgdGhlIGtub3duIFNlemFyeSBnZW5lcyB3aXRoIGdlbmUgbmFtZXMKZ2dwbG90KGRmX2ZpbHRlcmVkLCBhZXMoeCA9IGF2Z19sb2cyRkNfU0NULCB5ID0gLWxvZzEwKHBfdmFsX2Fkal9TQ1QpLCBjb2xvciA9IGdlbmUpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNykgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBnZW5lKSwgdmp1c3QgPSAxLjUsIGhqdXN0ID0gMC41LCBzaXplID0gMywgY29sb3IgPSAiYmxhY2siKSArICAjIEFkZGluZyBnZW5lIG5hbWVzCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIlZvbGNhbm8gUGxvdDogS25vd24gU2V6YXJ5IEdlbmVzIChTQ1QgQXNzYXkpIiwgCiAgICAgICB4ID0gIkxvZzIgRm9sZCBDaGFuZ2UgKFNDVCkiLCAKICAgICAgIHkgPSAiLUxvZzEwIEFkanVzdGVkIFAtdmFsdWUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAgICAgICAgICAgICAgICAgICAiS0lSM0RMMiIgPSAiIzFmNzdiNCIsICAjIGJsdWUKICAgICAgICAgICAgICAgICAgICAgICJUT1giID0gIiNmZjdmMGUiLCAgIyBvcmFuZ2UKICAgICAgICAgICAgICAgICAgICAgICJUV0lTVDEiID0gIiMyY2EwMmMiLCAgIyBncmVlbgogICAgICAgICAgICAgICAgICAgICAgIkNENTIiID0gIiM5NDY3YmQiLCAgIyBwdXJwbGUKICAgICAgICAgICAgICAgICAgICAgICJDQ1I0IiA9ICIjOGM1NjRiIiwgICMgYnJvd24KICAgICAgICAgICAgICAgICAgICAgICJJTDJSQSIgPSAiI2UzNzdjMiIsICAjIHBpbmsKICAgICAgICAgICAgICAgICAgICAgICJDRDciID0gIiM3ZjdmN2YiLCAgIyBncmF5CiAgICAgICAgICAgICAgICAgICAgICAiRFBQNCIgPSAiI2JjYmQyMiIsICAjIHllbGxvdy1ncmVlbgogICAgICAgICAgICAgICAgICAgICAgIkNDUjciID0gIiMxN2JlY2YiLCAgIyBjeWFuCiAgICAgICAgICAgICAgICAgICAgICAiR0FUQTMiID0gIiNkNjI3MjgiLCAgIyByZWQKICAgICAgICAgICAgICAgICAgICAgICJGT1hQMyIgPSAiIzhhMmJlMiIsICAjIGJsdWUtdmlvbGV0CiAgICAgICAgICAgICAgICAgICAgICAiRE5NMyIgPSAiI2ZmNjM0NyIsICAjIHRvbWF0bwogICAgICAgICAgICAgICAgICAgICAgIk5DUjEiID0gIiMzY2IzNzEiLCAgIyBtZWRpdW0gc2VhIGdyZWVuCiAgICAgICAgICAgICAgICAgICAgICAiQ0Q3MCIgPSAiI2ZmMTQ5MyIsICAjIGRlZXAgcGluawogICAgICAgICAgICAgICAgICAgICAgIkFJUkUiID0gIiMwMGJmZmYiLCAgIyBkZWVwIHNreSBibHVlCiAgICAgICAgICAgICAgICAgICAgICAiUERDRDEgKFBELTEpIiA9ICIjNGM3MmIwIiwgICMgc3RlZWwgYmx1ZQogICAgICAgICAgICAgICAgICAgICAgIkNEMjc0IChQRC1MMSkiID0gIiNjNWIwZDUiICAjIGxpZ2h0IHB1cnBsZQopKSArIAp0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCgoKCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKCiMgRGVmaW5lIHRoZSBsaXN0IG9mIGtub3duIFNlemFyeSBnZW5lcwpzZXphcnlfZ2VuZXMgPC0gYygiS0lSM0RMMiIsICJUT1giLCAiVFdJU1QxIiwgIkNENTIiLCAiQ0NSNCIsICJJTDJSQSIsICJDRDciLCAiRFBQNCIsICJDQ1I3IiwgIkdBVEEzIiwgIkZPWFAzIiwgIkNDUjciLCAiQ0Q3MCIsICJQTFMzIiwgIlBEQ0QxIikKCiMgRmlsdGVyIHRoZSBtZXJnZWQgZGF0YSB0byBpbmNsdWRlIG9ubHkgdGhlIGtub3duIFNlemFyeSBnZW5lcyBmb3IgUk5BIGRhdGEKZGZfZmlsdGVyZWRfcm5hIDwtIGRmX21lcmdlZCAlPiUKICBmaWx0ZXIoZ2VuZSAlaW4lIHNlemFyeV9nZW5lcykKCiMgVm9sY2FubyBwbG90IHNob3dpbmcgb25seSB0aGUga25vd24gU2V6YXJ5IGdlbmVzIGZvciBSTkEgYXNzYXkgd2l0aCBnZW5lIG5hbWVzCmdncGxvdChkZl9maWx0ZXJlZF9ybmEsIGFlcyh4ID0gYXZnX2xvZzJGQ19STkEsIHkgPSAtbG9nMTAocF92YWxfYWRqX1JOQSksIGNvbG9yID0gZ2VuZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC43KSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGdlbmUpLCB2anVzdCA9IDEuNSwgaGp1c3QgPSAwLjUsIHNpemUgPSAzLCBjb2xvciA9ICJibGFjayIpICsgICMgQWRkaW5nIGdlbmUgbmFtZXMKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90OiBLbm93biBTZXphcnkgR2VuZXMgKFJOQSBBc3NheSkiLCAKICAgICAgIHggPSAiTG9nMiBGb2xkIENoYW5nZSAoUk5BKSIsIAogICAgICAgeSA9ICItTG9nMTAgQWRqdXN0ZWQgUC12YWx1ZSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygKICAgICAgICAgICAgICAgICAgICAgICJLSVIzREwyIiA9ICIjMWY3N2I0IiwgICMgYmx1ZQogICAgICAgICAgICAgICAgICAgICAgIlRPWCIgPSAiI2ZmN2YwZSIsICAjIG9yYW5nZQogICAgICAgICAgICAgICAgICAgICAgIlRXSVNUMSIgPSAiIzJjYTAyYyIsICAjIGdyZWVuCiAgICAgICAgICAgICAgICAgICAgICAiQ0Q1MiIgPSAiIzk0NjdiZCIsICAjIHB1cnBsZQogICAgICAgICAgICAgICAgICAgICAgIkNDUjQiID0gIiM4YzU2NGIiLCAgIyBicm93bgogICAgICAgICAgICAgICAgICAgICAgIklMMlJBIiA9ICIjZTM3N2MyIiwgICMgcGluawogICAgICAgICAgICAgICAgICAgICAgIkNENyIgPSAiIzdmN2Y3ZiIsICAjIGdyYXkKICAgICAgICAgICAgICAgICAgICAgICJEUFA0IiA9ICIjYmNiZDIyIiwgICMgeWVsbG93LWdyZWVuCiAgICAgICAgICAgICAgICAgICAgICAiQ0NSNyIgPSAiIzE3YmVjZiIsICAjIGN5YW4KICAgICAgICAgICAgICAgICAgICAgICJHQVRBMyIgPSAiI2Q2MjcyOCIsICAjIHJlZAogICAgICAgICAgICAgICAgICAgICAgIkZPWFAzIiA9ICIjOGEyYmUyIiwgICMgYmx1ZS12aW9sZXQKICAgICAgICAgICAgICAgICAgICAgICJETk0zIiA9ICIjZmY2MzQ3IiwgICMgdG9tYXRvCiAgICAgICAgICAgICAgICAgICAgICAiTkNSMSIgPSAiIzNjYjM3MSIsICAjIG1lZGl1bSBzZWEgZ3JlZW4KICAgICAgICAgICAgICAgICAgICAgICJDRDcwIiA9ICIjZmYxNDkzIiwgICMgZGVlcCBwaW5rCiAgICAgICAgICAgICAgICAgICAgICAiQUlSRSIgPSAiIzAwYmZmZiIsICAjIGRlZXAgc2t5IGJsdWUKICAgICAgICAgICAgICAgICAgICAgICJQRENEMSAoUEQtMSkiID0gIiM0YzcyYjAiLCAgIyBzdGVlbCBibHVlCiAgICAgICAgICAgICAgICAgICAgICAiQ0QyNzQgKFBELUwxKSIgPSAiI2M1YjBkNSIgICMgbGlnaHQgcHVycGxlCikpICsgCnRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKYGBg