1. load libraries
2. Data PREPERATION
# Read the inferCNV HMM .dat file
infercnv_data <- read.delim("../L7_PBMC_uphyloplot/HMM_CNV_predictions.HMMi6.leiden.hmm_mode-subclusters.Pnorm_0.5.pred_cnv_genes.dat", sep="\t", header=TRUE)
# Remove any rows with NA or infinite values
infercnv_data <- infercnv_data[complete.cases(infercnv_data), ]
infercnv_data <- infercnv_data[is.finite(infercnv_data$start) & is.finite(infercnv_data$end), ]
# Remove 'chr' prefix from chromosome names if present
infercnv_data$chr <- gsub("^chr", "", infercnv_data$chr)
# Display the first few rows and structure of the data
print(head(infercnv_data))
str(infercnv_data)
# Filter out rows with PBMC from the cell_group_name column
infercnv_data <- infercnv_data[!grepl("PBMC", infercnv_data$cell_group_name), ]
# Replace 'all_observations' with 'L7', keeping only the part after the last underscore
infercnv_data$cell_group_name <- gsub("all_observations\\.all_observations_", "L7_", infercnv_data$cell_group_name)
# Check the first few rows after filtering and renaming
print(head(infercnv_data))
3. Query Cytogenetic Bands-Script2
# Load required libraries
library(dplyr)
library(readr)
# Function to download and process cytogenetic band data from UCSC
get_cyto_bands <- function() {
url <- "http://hgdownload.cse.ucsc.edu/goldenpath/hg38/database/cytoBand.txt.gz"
cyto_bands <- read_tsv(url, col_names = c("chr", "start", "end", "band", "stain"))
cyto_bands$chr <- gsub("chr", "", cyto_bands$chr) # Remove 'chr' prefix from chromosome names
return(cyto_bands)
}
# Function to find the cytogenetic band for a given position
find_band <- function(chr, pos_start, pos_end, cyto_bands) {
bands <- cyto_bands %>%
filter(chr == !!chr,
(start >= pos_start & start <= pos_end) |
(end >= pos_start & end <= pos_end) |
(start <= pos_start & end >= pos_end))
if (nrow(bands) > 0) {
return(paste(unique(bands$band), collapse = ","))
} else {
return(NA)
}
}
# Download cytogenetic band data
cyto_bands <- get_cyto_bands()
# Apply the function to each row in infercnv_data
result <- infercnv_data %>%
rowwise() %>%
mutate(band = find_band(chr, start, end, cyto_bands)) %>%
ungroup()
# View the first few rows of the result
print(head(result))
# Save the result to a new CSV file
write.csv(result, "L7_cytogenetics/L7_infercnv_with_bands.csv", row.names = FALSE)
# Display summary of the final result
summary(result)
4. Checking Cytogenetic Data
# Load necessary libraries
library(dplyr)
library(readr)
# Load the inferCNV data (L7_infercnv_with_bands2.csv) containing chromosome and band information
infercnv_data <- read_csv("L7_cytogenetics/L7_infercnv_with_bands.csv")
# Create a new column combining chromosome number and band information (e.g., "1p36.33")
infercnv_data <- infercnv_data %>%
mutate(chr_band = paste(chr, band, sep=""))
# Define cytogenetic bands for patient3
patient3_bands <- c(
"1p36.1",
"2p21", "2p13.6",
"3q24", "3q25.1", "3q25.31", "3q25.33",
"3q26.1", "3q26.31", "3q26.33", "3q27.2", "3q29",
"4", "5",
"6p21.31", "6p21.2",
"8",
"9p21.3",
"10p14",
"12p13.2", "12p13.1", "12q21.33", "12q22",
"14q12", "14q21.1", "14q22.1",
"15q24.2",
"16q24.2", "16q24.3",
"17p13.3", "17p11.2", "17p12",
"17q22", "17q24.3", "17q25.3"
)
# Define cytogenetic bands for L7
L7_bands <- c(
"1p36.1",
"2p21", "2p13.6",
"2q33.1", "2q33.3",
"3q24", "3q25.1", "3q25.31", "3q25.33",
"3q26.1", "3q26.31", "3q26.33", "3q27.2", "3q29",
"4q25", "4qter",
"5",
"6p21.31", "6p21.2",
"8",
"9p21.3",
"10p14",
"12p13.2", "12p13.1", "12q21.33", "12q22",
"14q12", "14q21.1", "14q22.1",
"15q24.2", "15q26.3",
"16q24.2", "16q24.3",
"17p13.3", "17p11.2", "17p12",
"17q22", "17q24.3", "17q25.3"
)
# Function to compare bands
compare_bands <- function(bands_list, infercnv_bands) {
comparison <- data.frame(
Band = bands_list,
Present_in_infercnv = ifelse(bands_list %in% infercnv_bands, "Present", "Not Present")
)
return(comparison)
}
# Compare patient3 bands to L7_infercnv bands
patient3_comparison <- compare_bands(patient3_bands, infercnv_data$chr_band)
# Compare L7 bands to L7_infercnv bands
L7_comparison <- compare_bands(L7_bands, infercnv_data$chr_band)
# View the comparison results
print("patient3 Comparison:")
print(patient3_comparison)
print("L7 Comparison:")
print(L7_comparison)
# Save the comparison results to CSV files
write.csv(patient3_comparison, "L7_cytogenetics/patient3_vs_L7_infercnv_comparison.csv", row.names = FALSE)
write.csv(L7_comparison, "L7_cytogenetics/L7_vs_L7_infercnv_comparison.csv", row.names = FALSE)
5. Cytogenetic Data Present and percentage of cells having that
CNVs
# Load required libraries
library(dplyr)
library(ggplot2)
library(tidyr)
library(readr)
# Read the inferCNV results
infercnv_file <- "L7_cytogenetics/L7_infercnv_with_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Create chr_band column in infercnv_data
infercnv_data$chr_band <- paste0(infercnv_data$chr, infercnv_data$band)
# Save the updated data frame with the new chr_band column
write.csv(infercnv_data, "L7_cytogenetics/L7_infercnv_with_chr_bands.csv", row.names = FALSE)
# Print the first few rows to confirm the new column
print(head(infercnv_data))
cat("Updated data frame with chr_band column has been saved as 'L7_infercnv_with_chr_bands.csv'\n")
Updated data frame with chr_band column has been saved as 'L7_infercnv_with_chr_bands.csv'
6. Cytogenetic Data Present and percentage of cells having that
CNVs
# Load required libraries
library(dplyr)
library(ggplot2)
library(readr)
# Read the updated inferCNV results with chr_band column
infercnv_file <- "L1_cytogenetics/L1_infercnv_with_chr_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Total number of unique cell groups
total_cells <- length(unique(infercnv_data$cell_group_name))
# Analyze CNV for all bands, focusing on chr_band and state
cnv_summary <- infercnv_data %>%
group_by(chr_band, state) %>%
summarize(unique_cells = n_distinct(cell_group_name), .groups = 'drop') %>%
mutate(
percentage = (unique_cells / total_cells) * 100,
cnv_type = case_when(
state == 1 ~ "Complete Loss (0x)",
state == 2 ~ "Loss of One Copy (0.5x)",
state == 3 ~ "Neutral (1x)",
state == 4 ~ "Addition of One Copy (1.5x)",
state == 5 ~ "Addition of Two Copies (2x)",
state == 6 ~ "Placeholder for >2 Copies (3x)",
TRUE ~ "Unknown" # Fallback for unexpected states
)
)
# Filter for CNVs affecting more than 10% of cells (for all states)
significant_cnv_summary <- cnv_summary %>%
filter(percentage > 90) %>%
select(chr_band, state, unique_cells, percentage, cnv_type)
# Print the summary for significant CNV analysis
print(significant_cnv_summary)
# Save the significant CNV summary to a CSV file
output_file <- "L1_cytogenetics/significant_cnv_summary.csv"
write.csv(significant_cnv_summary, output_file, row.names = FALSE)
# Print confirmation message
cat("Significant CNV summary saved to", output_file, "\n")
Significant CNV summary saved to L1_cytogenetics/significant_cnv_summary.csv
# Visualization of the percentage of cells affected by CNVs in different chromosome bands
ggplot(significant_cnv_summary, aes(x = reorder(chr_band, -percentage), y = percentage, fill = cnv_type)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Percentage of Cells Affected by CNVs in Chromosome Bands",
x = "Chromosome Band",
y = "Percentage of Cells Affected (%)") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.title = element_blank())

# Save the plot
ggsave("L1_cytogenetics/cnv_percentage_by_chrbands.png", width = 10, height = 6)
# Load required libraries
library(dplyr)
library(readr)
# Read the updated inferCNV results with chr_band column
infercnv_file <- "L1_cytogenetics/L1_infercnv_with_chr_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Total number of unique cell groups
total_cells <- length(unique(infercnv_data$cell_group_name))
# Analyze CNV for all bands
cnv_summary <- infercnv_data %>%
group_by(chr_band, state) %>%
summarize(unique_cells = n_distinct(cell_group_name), .groups = 'drop') %>%
mutate(
percentage = (unique_cells / total_cells) * 100,
cnv_type = case_when(
state == 1 ~ "Complete Loss (0x)",
state == 2 ~ "Loss of One Copy (0.5x)",
state == 3 ~ "Neutral (1x)",
state == 4 ~ "Addition of One Copy (1.5x)",
state == 5 ~ "Addition of Two Copies (2x)",
state == 6 ~ "Placeholder for >2x Copies (3x)",
TRUE ~ "Unknown" # Added a fallback for unexpected state values
)
)
# Filter for CNVs affecting more than 10% of cells (for all states)
significant_cnv_summary <- cnv_summary %>%
filter(percentage > 90) %>%
select(chr_band, state, unique_cells, percentage, cnv_type)
# Save the filtered gain/loss summary to a CSV file
output_file <- "L1_cytogenetics/significant_gain_loss_summary_90.csv"
write.csv(significant_cnv_summary, output_file, row.names = FALSE)
# Print confirmation message
cat("Significant Gain/Loss summary with >90% affected cells saved to", output_file, "\n")
Significant Gain/Loss summary with >90% affected cells saved to L1_cytogenetics/significant_gain_loss_summary_90.csv
# Create a bar plot with percentage on X-axis and chromosomal bands on Y-axis
ggplot(significant_cnv_summary, aes(x = percentage, y = chr_band, fill = cnv_type)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Significant CNVs Affecting >90% of Cells",
x = "Percentage of Cells",
y = "Chromosomal Band",
fill = "CNV Type") +
theme_minimal() +
theme(axis.text.y = element_text(angle = 0, hjust = 1))

NA
NA
L1.
# Load required libraries
library(dplyr)
library(ggplot2)
library(readr)
# Read the updated inferCNV results with chr_band column
infercnv_file <- "L1_cytogenetics/L1_infercnv_with_chr_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Total number of unique cell groups
total_cells <- length(unique(infercnv_data$cell_group_name))
# Analyze CNV for all bands
cnv_summary <- infercnv_data %>%
group_by(chr_band, state) %>%
summarize(unique_cells = n_distinct(cell_group_name), .groups = 'drop') %>%
mutate(
percentage = (unique_cells / total_cells) * 100,
cnv_type = case_when(
state == 1 ~ "Complete Loss (0x)",
state == 2 ~ "Loss of One Copy (0.5x)",
state == 3 ~ "Neutral (1x)",
state == 4 ~ "Addition of One Copy (1.5x)",
state == 5 ~ "Addition of Two Copies (2x)",
state == 6 ~ "Placeholder for >2x Copies (3x)",
TRUE ~ "Unknown"
)
)
# Filter for CNVs affecting more than 10% of cells (for all states)
significant_cnv_summary <- cnv_summary %>%
filter(percentage > 90) %>%
select(chr_band, state, unique_cells, percentage, cnv_type)
# Save the filtered gain/loss summary to a CSV file
output_file <- "L1_cytogenetics/significant_gain_loss_summary_90.csv"
write.csv(significant_cnv_summary, output_file, row.names = FALSE)
# Print confirmation message
cat("Significant Gain/Loss summary with >90% affected cells saved to", output_file, "\n")
Significant Gain/Loss summary with >90% affected cells saved to L1_cytogenetics/significant_gain_loss_summary_90.csv
# Publication-quality plot with percentage of cells on X-axis and chromosomal bands on Y-axis
ggplot(significant_cnv_summary, aes(x = percentage, y = reorder(chr_band, percentage), fill = cnv_type)) +
geom_bar(stat = "identity", position = "dodge", width = 0.8) + # Adjusted bar width
scale_fill_manual(values = c("Complete Loss (0x)" = "#fdae61", # Red for loss
"Loss of One Copy (0.5x)" = "#313695", # Orange for partial loss
"Addition of One Copy (1.5x)" = "red", # Blue for gain
"Addition of Two Copies (2x)" = "darkgreen")) + # Dark blue for higher gain
labs(title = "Significant CNVs Affecting >90% of Cells",
subtitle = "Chromosomal Bands with CNVs in >90% of Cells",
x = "Percentage of Cells (%)",
y = "Chromosomal Band",
fill = "CNV Type") +
theme_minimal(base_size = 14) + # Adjust text size for readability
theme(
axis.title.x = element_text(size = 14, face = "bold"),
axis.title.y = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
plot.title = element_text(hjust = 0.5, size = 18, face = "bold"), # Center the title
plot.subtitle = element_text(hjust = 0.5, size = 14),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11),
panel.grid.major.x = element_line(color = "gray90"), # Add gridlines
panel.grid.minor.x = element_blank(), # Remove minor gridlines
legend.position = "top", # Position legend at the top
legend.key.size = unit(0.8, "cm")
)

L2.
# Load required libraries
library(dplyr)
library(ggplot2)
library(readr)
# Read the updated inferCNV results with chr_band column
infercnv_file <- "L2_cytogenetics/L2_infercnv_with_chr_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Total number of unique cell groups
total_cells <- length(unique(infercnv_data$cell_group_name))
# Analyze CNV for all bands
cnv_summary <- infercnv_data %>%
group_by(chr_band, state) %>%
summarize(unique_cells = n_distinct(cell_group_name), .groups = 'drop') %>%
mutate(
percentage = (unique_cells / total_cells) * 100,
cnv_type = case_when(
state == 1 ~ "Complete Loss (0x)",
state == 2 ~ "Loss of One Copy (0.5x)",
state == 3 ~ "Neutral (1x)",
state == 4 ~ "Addition of One Copy (1.5x)",
state == 5 ~ "Addition of Two Copies (2x)",
state == 6 ~ "Placeholder for >2x Copies (3x)",
TRUE ~ "Unknown"
)
)
# Filter for CNVs affecting more than 10% of cells (for all states)
significant_cnv_summary <- cnv_summary %>%
filter(percentage > 97) %>%
select(chr_band, state, unique_cells, percentage, cnv_type)
# Save the filtered gain/loss summary to a CSV file
output_file <- "L2_cytogenetics/significant_gain_loss_summary_90.csv"
write.csv(significant_cnv_summary, output_file, row.names = FALSE)
# Print confirmation message
cat("Significant Gain/Loss summary with >90% affected cells saved to", output_file, "\n")
Significant Gain/Loss summary with >90% affected cells saved to L2_cytogenetics/significant_gain_loss_summary_90.csv
# Publication-quality plot with percentage of cells on X-axis and chromosomal bands on Y-axis
ggplot(significant_cnv_summary, aes(x = percentage, y = reorder(chr_band, percentage), fill = cnv_type)) +
geom_bar(stat = "identity", position = "dodge", width = 0.8) + # Adjusted bar width
scale_fill_manual(values = c("Complete Loss (0x)" = "#fdae61", # Red for loss
"Loss of One Copy (0.5x)" = "#313695", # Orange for partial loss
"Addition of One Copy (1.5x)" = "red", # Blue for gain
"Addition of Two Copies (2x)" = "darkgreen")) + # Dark blue for higher gain
labs(title = "Significant CNVs Affecting >90% of Cells",
subtitle = "Chromosomal Bands with CNVs in >90% of Cells",
x = "Percentage of Cells (%)",
y = "Chromosomal Band",
fill = "CNV Type") +
theme_minimal(base_size = 14) + # Adjust text size for readability
theme(
axis.title.x = element_text(size = 14, face = "bold"),
axis.title.y = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
plot.title = element_text(hjust = 0.5, size = 18, face = "bold"), # Center the title
plot.subtitle = element_text(hjust = 0.5, size = 14),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11),
panel.grid.major.x = element_line(color = "gray90"), # Add gridlines
panel.grid.minor.x = element_blank(), # Remove minor gridlines
legend.position = "top", # Position legend at the top
legend.key.size = unit(0.8, "cm")
)

L3.
# Load required libraries
library(dplyr)
library(ggplot2)
library(readr)
# Read the updated inferCNV results with chr_band column
infercnv_file <- "L3_cytogenetics/L3_infercnv_with_chr_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Total number of unique cell groups
total_cells <- length(unique(infercnv_data$cell_group_name))
# Analyze CNV for all bands
cnv_summary <- infercnv_data %>%
group_by(chr_band, state) %>%
summarize(unique_cells = n_distinct(cell_group_name), .groups = 'drop') %>%
mutate(
percentage = (unique_cells / total_cells) * 100,
cnv_type = case_when(
state == 1 ~ "Complete Loss (0x)",
state == 2 ~ "Loss of One Copy (0.5x)",
state == 3 ~ "Neutral (1x)",
state == 4 ~ "Addition of One Copy (1.5x)",
state == 5 ~ "Addition of Two Copies (2x)",
state == 6 ~ "Placeholder for >2x Copies (3x)",
TRUE ~ "Unknown"
)
)
# Filter for CNVs affecting more than 10% of cells (for all states)
significant_cnv_summary <- cnv_summary %>%
filter(percentage > 98) %>%
select(chr_band, state, unique_cells, percentage, cnv_type)
# Save the filtered gain/loss summary to a CSV file
output_file <- "L3_cytogenetics/significant_gain_loss_summary_90.csv"
write.csv(significant_cnv_summary, output_file, row.names = FALSE)
# Print confirmation message
cat("Significant Gain/Loss summary with >90% affected cells saved to", output_file, "\n")
Significant Gain/Loss summary with >90% affected cells saved to L3_cytogenetics/significant_gain_loss_summary_90.csv
# Publication-quality plot with percentage of cells on X-axis and chromosomal bands on Y-axis
ggplot(significant_cnv_summary, aes(x = percentage, y = reorder(chr_band, percentage), fill = cnv_type)) +
geom_bar(stat = "identity", position = "dodge", width = 0.8) + # Adjusted bar width
scale_fill_manual(values = c("Complete Loss (0x)" = "#fdae61", # Red for loss
"Loss of One Copy (0.5x)" = "#313695", # Orange for partial loss
"Addition of One Copy (1.5x)" = "red", # Blue for gain
"Addition of Two Copies (2x)" = "darkgreen")) + # Dark blue for higher gain
labs(title = "Significant CNVs Affecting >90% of Cells",
subtitle = "Chromosomal Bands with CNVs in >90% of Cells",
x = "Percentage of Cells (%)",
y = "Chromosomal Band",
fill = "CNV Type") +
theme_minimal(base_size = 14) + # Adjust text size for readability
theme(
axis.title.x = element_text(size = 14, face = "bold"),
axis.title.y = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
plot.title = element_text(hjust = 0.5, size = 18, face = "bold"), # Center the title
plot.subtitle = element_text(hjust = 0.5, size = 14),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11),
panel.grid.major.x = element_line(color = "gray90"), # Add gridlines
panel.grid.minor.x = element_blank(), # Remove minor gridlines
legend.position = "top", # Position legend at the top
legend.key.size = unit(0.8, "cm")
)

L4.
# Load required libraries
library(dplyr)
library(ggplot2)
library(readr)
# Read the updated inferCNV results with chr_band column
infercnv_file <- "L4_cytogenetics/L4_infercnv_with_chr_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Total number of unique cell groups
total_cells <- length(unique(infercnv_data$cell_group_name))
# Analyze CNV for all bands
cnv_summary <- infercnv_data %>%
group_by(chr_band, state) %>%
summarize(unique_cells = n_distinct(cell_group_name), .groups = 'drop') %>%
mutate(
percentage = (unique_cells / total_cells) * 100,
cnv_type = case_when(
state == 1 ~ "Complete Loss (0x)",
state == 2 ~ "Loss of One Copy (0.5x)",
state == 3 ~ "Neutral (1x)",
state == 4 ~ "Addition of One Copy (1.5x)",
state == 5 ~ "Addition of Two Copies (2x)",
state == 6 ~ "Placeholder for >2x Copies (3x)",
TRUE ~ "Unknown"
)
)
# Filter for CNVs affecting more than 10% of cells (for all states)
significant_cnv_summary <- cnv_summary %>%
filter(percentage > 93) %>%
select(chr_band, state, unique_cells, percentage, cnv_type)
# Save the filtered gain/loss summary to a CSV file
output_file <- "L4_cytogenetics/significant_gain_loss_summary_90.csv"
write.csv(significant_cnv_summary, output_file, row.names = FALSE)
# Print confirmation message
cat("Significant Gain/Loss summary with >90% affected cells saved to", output_file, "\n")
Significant Gain/Loss summary with >90% affected cells saved to L4_cytogenetics/significant_gain_loss_summary_90.csv
# Publication-quality plot with percentage of cells on X-axis and chromosomal bands on Y-axis
ggplot(significant_cnv_summary, aes(x = percentage, y = reorder(chr_band, percentage), fill = cnv_type)) +
geom_bar(stat = "identity", position = "dodge", width = 0.8) + # Adjusted bar width
scale_fill_manual(values = c("Complete Loss (0x)" = "#fdae61", # Red for loss
"Loss of One Copy (0.5x)" = "#313695", # Orange for partial loss
"Addition of One Copy (1.5x)" = "red", # Blue for gain
"Addition of Two Copies (2x)" = "darkgreen")) + # Dark blue for higher gain
labs(title = "Significant CNVs Affecting >90% of Cells",
subtitle = "Chromosomal Bands with CNVs in >90% of Cells",
x = "Percentage of Cells (%)",
y = "Chromosomal Band",
fill = "CNV Type") +
theme_minimal(base_size = 14) + # Adjust text size for readability
theme(
axis.title.x = element_text(size = 14, face = "bold"),
axis.title.y = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
plot.title = element_text(hjust = 0.5, size = 18, face = "bold"), # Center the title
plot.subtitle = element_text(hjust = 0.5, size = 14),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11),
panel.grid.major.x = element_line(color = "gray90"), # Add gridlines
panel.grid.minor.x = element_blank(), # Remove minor gridlines
legend.position = "top", # Position legend at the top
legend.key.size = unit(0.8, "cm")
)

L5.
# Load required libraries
library(dplyr)
library(ggplot2)
library(readr)
# Read the updated inferCNV results with chr_band column
infercnv_file <- "L5_cytogenetics/L5_infercnv_with_chr_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Total number of unique cell groups
total_cells <- length(unique(infercnv_data$cell_group_name))
# Analyze CNV for all bands
cnv_summary <- infercnv_data %>%
group_by(chr_band, state) %>%
summarize(unique_cells = n_distinct(cell_group_name), .groups = 'drop') %>%
mutate(
percentage = (unique_cells / total_cells) * 100,
cnv_type = case_when(
state == 1 ~ "Complete Loss (0x)",
state == 2 ~ "Loss of One Copy (0.5x)",
state == 3 ~ "Neutral (1x)",
state == 4 ~ "Addition of One Copy (1.5x)",
state == 5 ~ "Addition of Two Copies (2x)",
state == 6 ~ "Placeholder for >2x Copies (3x)",
TRUE ~ "Unknown"
)
)
# Filter for CNVs affecting more than 10% of cells (for all states)
significant_cnv_summary <- cnv_summary %>%
filter(percentage > 90) %>%
select(chr_band, state, unique_cells, percentage, cnv_type)
# Save the filtered gain/loss summary to a CSV file
output_file <- "L5_cytogenetics/significant_gain_loss_summary_90.csv"
write.csv(significant_cnv_summary, output_file, row.names = FALSE)
# Print confirmation message
cat("Significant Gain/Loss summary with >90% affected cells saved to", output_file, "\n")
# Publication-quality plot with percentage of cells on X-axis and chromosomal bands on Y-axis
ggplot(significant_cnv_summary, aes(x = percentage, y = reorder(chr_band, percentage), fill = cnv_type)) +
geom_bar(stat = "identity", position = "dodge", width = 0.8) + # Adjusted bar width
scale_fill_manual(values = c("Complete Loss (0x)" = "#fdae61", # Red for loss
"Loss of One Copy (0.5x)" = "#313695", # Orange for partial loss
"Addition of One Copy (1.5x)" = "red", # Blue for gain
"Addition of Two Copies (2x)" = "darkgreen")) + # Dark blue for higher gain
labs(title = "Significant CNVs Affecting >90% of Cells",
subtitle = "Chromosomal Bands with CNVs in >90% of Cells",
x = "Percentage of Cells (%)",
y = "Chromosomal Band",
fill = "CNV Type") +
theme_minimal(base_size = 14) + # Adjust text size for readability
theme(
axis.title.x = element_text(size = 14, face = "bold"),
axis.title.y = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
plot.title = element_text(hjust = 0.5, size = 18, face = "bold"), # Center the title
plot.subtitle = element_text(hjust = 0.5, size = 14),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11),
panel.grid.major.x = element_line(color = "gray90"), # Add gridlines
panel.grid.minor.x = element_blank(), # Remove minor gridlines
legend.position = "top", # Position legend at the top
legend.key.size = unit(0.8, "cm")
)
L6.
# Load required libraries
library(dplyr)
library(ggplot2)
library(readr)
# Read the updated inferCNV results with chr_band column
infercnv_file <- "L6_cytogenetics/L6_infercnv_with_chr_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Total number of unique cell groups
total_cells <- length(unique(infercnv_data$cell_group_name))
# Analyze CNV for all bands
cnv_summary <- infercnv_data %>%
group_by(chr_band, state) %>%
summarize(unique_cells = n_distinct(cell_group_name), .groups = 'drop') %>%
mutate(
percentage = (unique_cells / total_cells) * 100,
cnv_type = case_when(
state == 1 ~ "Complete Loss (0x)",
state == 2 ~ "Loss of One Copy (0.5x)",
state == 3 ~ "Neutral (1x)",
state == 4 ~ "Addition of One Copy (1.5x)",
state == 5 ~ "Addition of Two Copies (2x)",
state == 6 ~ "Placeholder for >2x Copies (3x)",
TRUE ~ "Unknown"
)
)
# Filter for CNVs affecting more than 10% of cells (for all states)
significant_cnv_summary <- cnv_summary %>%
filter(percentage > 90) %>%
select(chr_band, state, unique_cells, percentage, cnv_type)
# Save the filtered gain/loss summary to a CSV file
output_file <- "L6_cytogenetics/significant_gain_loss_summary_90.csv"
write.csv(significant_cnv_summary, output_file, row.names = FALSE)
# Print confirmation message
cat("Significant Gain/Loss summary with >90% affected cells saved to", output_file, "\n")
# Publication-quality plot with percentage of cells on X-axis and chromosomal bands on Y-axis
ggplot(significant_cnv_summary, aes(x = percentage, y = reorder(chr_band, percentage), fill = cnv_type)) +
geom_bar(stat = "identity", position = "dodge", width = 0.8) + # Adjusted bar width
scale_fill_manual(values = c("Complete Loss (0x)" = "#fdae61", # Red for loss
"Loss of One Copy (0.5x)" = "#313695", # Orange for partial loss
"Addition of One Copy (1.5x)" = "red", # Blue for gain
"Addition of Two Copies (2x)" = "darkgreen")) + # Dark blue for higher gain
labs(title = "Significant CNVs Affecting >90% of Cells",
subtitle = "Chromosomal Bands with CNVs in >90% of Cells",
x = "Percentage of Cells (%)",
y = "Chromosomal Band",
fill = "CNV Type") +
theme_minimal(base_size = 14) + # Adjust text size for readability
theme(
axis.title.x = element_text(size = 14, face = "bold"),
axis.title.y = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
plot.title = element_text(hjust = 0.5, size = 18, face = "bold"), # Center the title
plot.subtitle = element_text(hjust = 0.5, size = 14),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11),
panel.grid.major.x = element_line(color = "gray90"), # Add gridlines
panel.grid.minor.x = element_blank(), # Remove minor gridlines
legend.position = "top", # Position legend at the top
legend.key.size = unit(0.8, "cm")
)
L7.
# Load required libraries
library(dplyr)
library(ggplot2)
library(readr)
# Read the updated inferCNV results with chr_band column
infercnv_file <- "L7_cytogenetics/L7_infercnv_with_chr_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Total number of unique cell groups
total_cells <- length(unique(infercnv_data$cell_group_name))
# Analyze CNV for all bands
cnv_summary <- infercnv_data %>%
group_by(chr_band, state) %>%
summarize(unique_cells = n_distinct(cell_group_name), .groups = 'drop') %>%
mutate(
percentage = (unique_cells / total_cells) * 100,
cnv_type = case_when(
state == 1 ~ "Complete Loss (0x)",
state == 2 ~ "Loss of One Copy (0.5x)",
state == 3 ~ "Neutral (1x)",
state == 4 ~ "Addition of One Copy (1.5x)",
state == 5 ~ "Addition of Two Copies (2x)",
state == 6 ~ "Placeholder for >2x Copies (3x)",
TRUE ~ "Unknown"
)
)
# Filter for CNVs affecting more than 10% of cells (for all states)
significant_cnv_summary <- cnv_summary %>%
filter(percentage > 90) %>%
select(chr_band, state, unique_cells, percentage, cnv_type)
# Save the filtered gain/loss summary to a CSV file
output_file <- "L7_cytogenetics/significant_gain_loss_summary_90.csv"
write.csv(significant_cnv_summary, output_file, row.names = FALSE)
# Print confirmation message
cat("Significant Gain/Loss summary with >90% affected cells saved to", output_file, "\n")
Significant Gain/Loss summary with >90% affected cells saved to L7_cytogenetics/significant_gain_loss_summary_90.csv
# Publication-quality plot with percentage of cells on X-axis and chromosomal bands on Y-axis
ggplot(significant_cnv_summary, aes(x = percentage, y = reorder(chr_band, percentage), fill = cnv_type)) +
geom_bar(stat = "identity", position = "dodge", width = 0.8) + # Adjusted bar width
scale_fill_manual(values = c("Complete Loss (0x)" = "#fdae61", # Red for loss
"Loss of One Copy (0.5x)" = "#313695", # Orange for partial loss
"Addition of One Copy (1.5x)" = "red", # Blue for gain
"Addition of Two Copies (2x)" = "darkgreen")) + # Dark blue for higher gain
labs(title = "Significant CNVs Affecting >90% of Cells",
subtitle = "Chromosomal Bands with CNVs in >90% of Cells",
x = "Percentage of Cells (%)",
y = "Chromosomal Band",
fill = "CNV Type") +
theme_minimal(base_size = 14) + # Adjust text size for readability
theme(
axis.title.x = element_text(size = 14, face = "bold"),
axis.title.y = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
plot.title = element_text(hjust = 0.5, size = 18, face = "bold"), # Center the title
plot.subtitle = element_text(hjust = 0.5, size = 14),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11),
panel.grid.major.x = element_line(color = "gray90"), # Add gridlines
panel.grid.minor.x = element_blank(), # Remove minor gridlines
legend.position = "top", # Position legend at the top
legend.key.size = unit(0.8, "cm")
)

L1<8%&>10.
# Load required libraries
library(dplyr)
library(ggplot2)
library(readr)
# Read the updated inferCNV results with chr_band column
infercnv_file <- "L1_cytogenetics/L1_infercnv_with_chr_bands.csv"
infercnv_data <- read.csv(infercnv_file, stringsAsFactors = FALSE)
# Total number of unique cell groups
total_cells <- length(unique(infercnv_data$cell_group_name))
# Analyze CNV for all bands
cnv_summary <- infercnv_data %>%
group_by(chr_band, state) %>%
summarize(unique_cells = n_distinct(cell_group_name), .groups = 'drop') %>%
mutate(
percentage = (unique_cells / total_cells) * 100,
cnv_type = case_when(
state == 1 ~ "Complete Loss (0x)",
state == 2 ~ "Loss of One Copy (0.5x)",
state == 3 ~ "Neutral (1x)",
state == 4 ~ "Addition of One Copy (1.5x)",
state == 5 ~ "Addition of Two Copies (2x)",
state == 6 ~ "Placeholder for >2x Copies (3x)",
TRUE ~ "Unknown"
)
)
# Filter for CNVs affecting more than 10% of cells (for all states)
significant_cnv_summary <- cnv_summary %>%
filter(percentage >8 & percentage <10) %>%
select(chr_band, state, unique_cells, percentage, cnv_type)
# Save the filtered gain/loss summary to a CSV file
output_file <- "L1_cytogenetics/significant_gain_loss_summary_less_than_5%.csv"
write.csv(significant_cnv_summary, output_file, row.names = FALSE)
# Print confirmation message
cat("Significant Gain/Loss summary with <5% affected cells saved to", output_file, "\n")
Significant Gain/Loss summary with <5% affected cells saved to L1_cytogenetics/significant_gain_loss_summary_less_than_5%.csv
# Publication-quality plot with percentage of cells on X-axis and chromosomal bands on Y-axis
ggplot(significant_cnv_summary, aes(x = percentage, y = reorder(chr_band, percentage), fill = cnv_type)) +
geom_bar(stat = "identity", position = "dodge", width = 0.8) + # Adjusted bar width
scale_fill_manual(values = c("Complete Loss (0x)" = "#fdae61", # Red for loss
"Loss of One Copy (0.5x)" = "#313695", # Orange for partial loss
"Addition of One Copy (1.5x)" = "red", # Blue for gain
"Addition of Two Copies (2x)" = "darkgreen")) + # Dark blue for higher gain
labs(title = "Significant CNVs Affecting <5% of Cells",
subtitle = "Chromosomal Bands with CNVs in <5% of Cells",
x = "Percentage of Cells (%)",
y = "Chromosomal Band",
fill = "CNV Type") +
theme_minimal(base_size = 14) + # Adjust text size for readability
theme(
axis.title.x = element_text(size = 14, face = "bold"),
axis.title.y = element_text(size = 14, face = "bold"),
axis.text = element_text(size = 12),
plot.title = element_text(hjust = 0.5, size = 18, face = "bold"), # Center the title
plot.subtitle = element_text(hjust = 0.5, size = 14),
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11),
panel.grid.major.x = element_line(color = "gray90"), # Add gridlines
panel.grid.minor.x = element_blank(), # Remove minor gridlines
legend.position = "top", # Position legend at the top
legend.key.size = unit(0.8, "cm")
)

LS0tCnRpdGxlOiAiQ3l0b2dlbmV0aWMgQW5hbHlzaXMiCmF1dGhvcjogTmFzaXIgTWFobW9vZCBBYmJhc2kKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBJbnN0YWxsIGFuZCBsb2FkIHJlcXVpcmVkIHBhY2thZ2VzCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiYmlvbWFSdCIsIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcygiYmlvbWFSdCIpCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZHBseXIiLCBxdWlldGx5ID0gVFJVRSkpIGluc3RhbGwucGFja2FnZXMoImRwbHlyIikKbGlicmFyeShiaW9tYVJ0KQpsaWJyYXJ5KGRwbHlyKQoKCmBgYAoKIyAyLiBEYXRhIFBSRVBFUkFUSU9OICAKYGBge3IgZGF0YTEsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEyfQoKCiMgUmVhZCB0aGUgaW5mZXJDTlYgSE1NIC5kYXQgZmlsZQppbmZlcmNudl9kYXRhIDwtIHJlYWQuZGVsaW0oIi4uL0w3X1BCTUNfdXBoeWxvcGxvdC9ITU1fQ05WX3ByZWRpY3Rpb25zLkhNTWk2LmxlaWRlbi5obW1fbW9kZS1zdWJjbHVzdGVycy5Qbm9ybV8wLjUucHJlZF9jbnZfZ2VuZXMuZGF0Iiwgc2VwPSJcdCIsIGhlYWRlcj1UUlVFKQoKIyBSZW1vdmUgYW55IHJvd3Mgd2l0aCBOQSBvciBpbmZpbml0ZSB2YWx1ZXMKaW5mZXJjbnZfZGF0YSA8LSBpbmZlcmNudl9kYXRhW2NvbXBsZXRlLmNhc2VzKGluZmVyY252X2RhdGEpLCBdCmluZmVyY252X2RhdGEgPC0gaW5mZXJjbnZfZGF0YVtpcy5maW5pdGUoaW5mZXJjbnZfZGF0YSRzdGFydCkgJiBpcy5maW5pdGUoaW5mZXJjbnZfZGF0YSRlbmQpLCBdCgojIFJlbW92ZSAnY2hyJyBwcmVmaXggZnJvbSBjaHJvbW9zb21lIG5hbWVzIGlmIHByZXNlbnQKaW5mZXJjbnZfZGF0YSRjaHIgPC0gZ3N1YigiXmNociIsICIiLCBpbmZlcmNudl9kYXRhJGNocikKCiMgRGlzcGxheSB0aGUgZmlyc3QgZmV3IHJvd3MgYW5kIHN0cnVjdHVyZSBvZiB0aGUgZGF0YQpwcmludChoZWFkKGluZmVyY252X2RhdGEpKQpzdHIoaW5mZXJjbnZfZGF0YSkKCgoKIyBGaWx0ZXIgb3V0IHJvd3Mgd2l0aCBQQk1DIGZyb20gdGhlIGNlbGxfZ3JvdXBfbmFtZSBjb2x1bW4KaW5mZXJjbnZfZGF0YSA8LSBpbmZlcmNudl9kYXRhWyFncmVwbCgiUEJNQyIsIGluZmVyY252X2RhdGEkY2VsbF9ncm91cF9uYW1lKSwgXQoKIyBSZXBsYWNlICdhbGxfb2JzZXJ2YXRpb25zJyB3aXRoICdMNycsIGtlZXBpbmcgb25seSB0aGUgcGFydCBhZnRlciB0aGUgbGFzdCB1bmRlcnNjb3JlCmluZmVyY252X2RhdGEkY2VsbF9ncm91cF9uYW1lIDwtIGdzdWIoImFsbF9vYnNlcnZhdGlvbnNcXC5hbGxfb2JzZXJ2YXRpb25zXyIsICJMN18iLCBpbmZlcmNudl9kYXRhJGNlbGxfZ3JvdXBfbmFtZSkKCiMgQ2hlY2sgdGhlIGZpcnN0IGZldyByb3dzIGFmdGVyIGZpbHRlcmluZyBhbmQgcmVuYW1pbmcKcHJpbnQoaGVhZChpbmZlcmNudl9kYXRhKSkKCgoKYGBgCgoKIyAzLiBRdWVyeSBDeXRvZ2VuZXRpYyBCYW5kcy1TY3JpcHQyCmBgYHtyIGRhdGEzLCBmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD0xMH0KCiMgTG9hZCByZXF1aXJlZCBsaWJyYXJpZXMKbGlicmFyeShkcGx5cikKbGlicmFyeShyZWFkcikKCiMgRnVuY3Rpb24gdG8gZG93bmxvYWQgYW5kIHByb2Nlc3MgY3l0b2dlbmV0aWMgYmFuZCBkYXRhIGZyb20gVUNTQwpnZXRfY3l0b19iYW5kcyA8LSBmdW5jdGlvbigpIHsKICB1cmwgPC0gImh0dHA6Ly9oZ2Rvd25sb2FkLmNzZS51Y3NjLmVkdS9nb2xkZW5wYXRoL2hnMzgvZGF0YWJhc2UvY3l0b0JhbmQudHh0Lmd6IgogIGN5dG9fYmFuZHMgPC0gcmVhZF90c3YodXJsLCBjb2xfbmFtZXMgPSBjKCJjaHIiLCAic3RhcnQiLCAiZW5kIiwgImJhbmQiLCAic3RhaW4iKSkKICBjeXRvX2JhbmRzJGNociA8LSBnc3ViKCJjaHIiLCAiIiwgY3l0b19iYW5kcyRjaHIpICAjIFJlbW92ZSAnY2hyJyBwcmVmaXggZnJvbSBjaHJvbW9zb21lIG5hbWVzCiAgcmV0dXJuKGN5dG9fYmFuZHMpCn0KCiMgRnVuY3Rpb24gdG8gZmluZCB0aGUgY3l0b2dlbmV0aWMgYmFuZCBmb3IgYSBnaXZlbiBwb3NpdGlvbgpmaW5kX2JhbmQgPC0gZnVuY3Rpb24oY2hyLCBwb3Nfc3RhcnQsIHBvc19lbmQsIGN5dG9fYmFuZHMpIHsKICBiYW5kcyA8LSBjeXRvX2JhbmRzICU+JQogICAgZmlsdGVyKGNociA9PSAhIWNociwgCiAgICAgICAgICAgKHN0YXJ0ID49IHBvc19zdGFydCAmIHN0YXJ0IDw9IHBvc19lbmQpIHwgCiAgICAgICAgICAgKGVuZCA+PSBwb3Nfc3RhcnQgJiBlbmQgPD0gcG9zX2VuZCkgfAogICAgICAgICAgIChzdGFydCA8PSBwb3Nfc3RhcnQgJiBlbmQgPj0gcG9zX2VuZCkpCiAgCiAgaWYgKG5yb3coYmFuZHMpID4gMCkgewogICAgcmV0dXJuKHBhc3RlKHVuaXF1ZShiYW5kcyRiYW5kKSwgY29sbGFwc2UgPSAiLCIpKQogIH0gZWxzZSB7CiAgICByZXR1cm4oTkEpCiAgfQp9CgojIERvd25sb2FkIGN5dG9nZW5ldGljIGJhbmQgZGF0YQpjeXRvX2JhbmRzIDwtIGdldF9jeXRvX2JhbmRzKCkKCiMgQXBwbHkgdGhlIGZ1bmN0aW9uIHRvIGVhY2ggcm93IGluIGluZmVyY252X2RhdGEKcmVzdWx0IDwtIGluZmVyY252X2RhdGEgJT4lCiAgcm93d2lzZSgpICU+JQogIG11dGF0ZShiYW5kID0gZmluZF9iYW5kKGNociwgc3RhcnQsIGVuZCwgY3l0b19iYW5kcykpICU+JQogIHVuZ3JvdXAoKQoKIyBWaWV3IHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgcmVzdWx0CnByaW50KGhlYWQocmVzdWx0KSkKCiMgU2F2ZSB0aGUgcmVzdWx0IHRvIGEgbmV3IENTViBmaWxlCndyaXRlLmNzdihyZXN1bHQsICJMN19jeXRvZ2VuZXRpY3MvTDdfaW5mZXJjbnZfd2l0aF9iYW5kcy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCiMgRGlzcGxheSBzdW1tYXJ5IG9mIHRoZSBmaW5hbCByZXN1bHQKc3VtbWFyeShyZXN1bHQpCgpgYGAKCgojIDQuIENoZWNraW5nIEN5dG9nZW5ldGljIERhdGEKYGBge3IgZGF0YTQsIGZpZy5oZWlnaHQ9NiwgZmlnLndpZHRoPTEwfQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKQoKIyBMb2FkIHRoZSBpbmZlckNOViBkYXRhIChMN19pbmZlcmNudl93aXRoX2JhbmRzMi5jc3YpIGNvbnRhaW5pbmcgY2hyb21vc29tZSBhbmQgYmFuZCBpbmZvcm1hdGlvbgppbmZlcmNudl9kYXRhIDwtIHJlYWRfY3N2KCJMN19jeXRvZ2VuZXRpY3MvTDdfaW5mZXJjbnZfd2l0aF9iYW5kcy5jc3YiKQoKIyBDcmVhdGUgYSBuZXcgY29sdW1uIGNvbWJpbmluZyBjaHJvbW9zb21lIG51bWJlciBhbmQgYmFuZCBpbmZvcm1hdGlvbiAoZS5nLiwgIjFwMzYuMzMiKQppbmZlcmNudl9kYXRhIDwtIGluZmVyY252X2RhdGEgJT4lCiAgbXV0YXRlKGNocl9iYW5kID0gcGFzdGUoY2hyLCBiYW5kLCBzZXA9IiIpKQoKIyBEZWZpbmUgY3l0b2dlbmV0aWMgYmFuZHMgZm9yIHBhdGllbnQzCnBhdGllbnQzX2JhbmRzIDwtIGMoCiAiMXAzNi4xIiwgCiAgIjJwMjEiLCAiMnAxMy42IiwgCiAgIjNxMjQiLCAiM3EyNS4xIiwgIjNxMjUuMzEiLCAiM3EyNS4zMyIsIAogICIzcTI2LjEiLCAiM3EyNi4zMSIsICIzcTI2LjMzIiwgIjNxMjcuMiIsICIzcTI5IiwgCiAgIjQiLCAiNSIsIAogICI2cDIxLjMxIiwgIjZwMjEuMiIsIAogICI4IiwgCiAgIjlwMjEuMyIsIAogICIxMHAxNCIsIAogICIxMnAxMy4yIiwgIjEycDEzLjEiLCAiMTJxMjEuMzMiLCAiMTJxMjIiLCAKICAiMTRxMTIiLCAiMTRxMjEuMSIsICIxNHEyMi4xIiwgCiAgIjE1cTI0LjIiLCAKICAiMTZxMjQuMiIsICIxNnEyNC4zIiwgCiAgIjE3cDEzLjMiLCAiMTdwMTEuMiIsICIxN3AxMiIsIAogICIxN3EyMiIsICIxN3EyNC4zIiwgIjE3cTI1LjMiCikKCiMgRGVmaW5lIGN5dG9nZW5ldGljIGJhbmRzIGZvciBMNwpMN19iYW5kcyA8LSBjKAogICIxcDM2LjEiLCAKICAiMnAyMSIsICIycDEzLjYiLCAKICAiMnEzMy4xIiwgIjJxMzMuMyIsIAogICIzcTI0IiwgIjNxMjUuMSIsICIzcTI1LjMxIiwgIjNxMjUuMzMiLCAKICAiM3EyNi4xIiwgIjNxMjYuMzEiLCAiM3EyNi4zMyIsICIzcTI3LjIiLCAiM3EyOSIsIAogICI0cTI1IiwgIjRxdGVyIiwgCiAgIjUiLCAKICAiNnAyMS4zMSIsICI2cDIxLjIiLCAKICAiOCIsIAogICI5cDIxLjMiLCAKICAiMTBwMTQiLCAKICAiMTJwMTMuMiIsICIxMnAxMy4xIiwgIjEycTIxLjMzIiwgIjEycTIyIiwgCiAgIjE0cTEyIiwgIjE0cTIxLjEiLCAiMTRxMjIuMSIsIAogICIxNXEyNC4yIiwgIjE1cTI2LjMiLCAKICAiMTZxMjQuMiIsICIxNnEyNC4zIiwgCiAgIjE3cDEzLjMiLCAiMTdwMTEuMiIsICIxN3AxMiIsIAogICIxN3EyMiIsICIxN3EyNC4zIiwgIjE3cTI1LjMiCikKCiMgRnVuY3Rpb24gdG8gY29tcGFyZSBiYW5kcwpjb21wYXJlX2JhbmRzIDwtIGZ1bmN0aW9uKGJhbmRzX2xpc3QsIGluZmVyY252X2JhbmRzKSB7CiAgY29tcGFyaXNvbiA8LSBkYXRhLmZyYW1lKAogICAgQmFuZCA9IGJhbmRzX2xpc3QsCiAgICBQcmVzZW50X2luX2luZmVyY252ID0gaWZlbHNlKGJhbmRzX2xpc3QgJWluJSBpbmZlcmNudl9iYW5kcywgIlByZXNlbnQiLCAiTm90IFByZXNlbnQiKQogICkKICByZXR1cm4oY29tcGFyaXNvbikKfQoKIyBDb21wYXJlIHBhdGllbnQzIGJhbmRzIHRvIEw3X2luZmVyY252IGJhbmRzCnBhdGllbnQzX2NvbXBhcmlzb24gPC0gY29tcGFyZV9iYW5kcyhwYXRpZW50M19iYW5kcywgaW5mZXJjbnZfZGF0YSRjaHJfYmFuZCkKCiMgQ29tcGFyZSBMNyBiYW5kcyB0byBMN19pbmZlcmNudiBiYW5kcwpMN19jb21wYXJpc29uIDwtIGNvbXBhcmVfYmFuZHMoTDdfYmFuZHMsIGluZmVyY252X2RhdGEkY2hyX2JhbmQpCgojIFZpZXcgdGhlIGNvbXBhcmlzb24gcmVzdWx0cwpwcmludCgicGF0aWVudDMgQ29tcGFyaXNvbjoiKQpwcmludChwYXRpZW50M19jb21wYXJpc29uKQoKcHJpbnQoIkw3IENvbXBhcmlzb246IikKcHJpbnQoTDdfY29tcGFyaXNvbikKCiMgU2F2ZSB0aGUgY29tcGFyaXNvbiByZXN1bHRzIHRvIENTViBmaWxlcwp3cml0ZS5jc3YocGF0aWVudDNfY29tcGFyaXNvbiwgIkw3X2N5dG9nZW5ldGljcy9wYXRpZW50M192c19MN19pbmZlcmNudl9jb21wYXJpc29uLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQp3cml0ZS5jc3YoTDdfY29tcGFyaXNvbiwgIkw3X2N5dG9nZW5ldGljcy9MN192c19MN19pbmZlcmNudl9jb21wYXJpc29uLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKCmBgYAoKIyA1LiBDeXRvZ2VuZXRpYyBEYXRhIFByZXNlbnQgYW5kIHBlcmNlbnRhZ2Ugb2YgY2VsbHMgaGF2aW5nIHRoYXQgQ05WcwpgYGB7ciBkYXRhNSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojIExvYWQgcmVxdWlyZWQgbGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0aWR5cikKbGlicmFyeShyZWFkcikKCiMgUmVhZCB0aGUgaW5mZXJDTlYgcmVzdWx0cwppbmZlcmNudl9maWxlIDwtICJMN19jeXRvZ2VuZXRpY3MvTDdfaW5mZXJjbnZfd2l0aF9iYW5kcy5jc3YiCmluZmVyY252X2RhdGEgPC0gcmVhZC5jc3YoaW5mZXJjbnZfZmlsZSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBDcmVhdGUgY2hyX2JhbmQgY29sdW1uIGluIGluZmVyY252X2RhdGEKaW5mZXJjbnZfZGF0YSRjaHJfYmFuZCA8LSBwYXN0ZTAoaW5mZXJjbnZfZGF0YSRjaHIsIGluZmVyY252X2RhdGEkYmFuZCkKCiMgU2F2ZSB0aGUgdXBkYXRlZCBkYXRhIGZyYW1lIHdpdGggdGhlIG5ldyBjaHJfYmFuZCBjb2x1bW4Kd3JpdGUuY3N2KGluZmVyY252X2RhdGEsICJMN19jeXRvZ2VuZXRpY3MvTDdfaW5mZXJjbnZfd2l0aF9jaHJfYmFuZHMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgojIFByaW50IHRoZSBmaXJzdCBmZXcgcm93cyB0byBjb25maXJtIHRoZSBuZXcgY29sdW1uCnByaW50KGhlYWQoaW5mZXJjbnZfZGF0YSkpCgpjYXQoIlVwZGF0ZWQgZGF0YSBmcmFtZSB3aXRoIGNocl9iYW5kIGNvbHVtbiBoYXMgYmVlbiBzYXZlZCBhcyAnTDdfaW5mZXJjbnZfd2l0aF9jaHJfYmFuZHMuY3N2J1xuIikKCgpgYGAKCgojIDYuIEN5dG9nZW5ldGljIERhdGEgUHJlc2VudCBhbmQgcGVyY2VudGFnZSBvZiBjZWxscyBoYXZpbmcgdGhhdCBDTlZzCmBgYHtyIGRhdGE2LCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgTG9hZCByZXF1aXJlZCBsaWJyYXJpZXMKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlYWRyKQoKIyBSZWFkIHRoZSB1cGRhdGVkIGluZmVyQ05WIHJlc3VsdHMgd2l0aCBjaHJfYmFuZCBjb2x1bW4KaW5mZXJjbnZfZmlsZSA8LSAiTDFfY3l0b2dlbmV0aWNzL0wxX2luZmVyY252X3dpdGhfY2hyX2JhbmRzLmNzdiIKaW5mZXJjbnZfZGF0YSA8LSByZWFkLmNzdihpbmZlcmNudl9maWxlLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojIFRvdGFsIG51bWJlciBvZiB1bmlxdWUgY2VsbCBncm91cHMKdG90YWxfY2VsbHMgPC0gbGVuZ3RoKHVuaXF1ZShpbmZlcmNudl9kYXRhJGNlbGxfZ3JvdXBfbmFtZSkpCgojIEFuYWx5emUgQ05WIGZvciBhbGwgYmFuZHMsIGZvY3VzaW5nIG9uIGNocl9iYW5kIGFuZCBzdGF0ZQpjbnZfc3VtbWFyeSA8LSBpbmZlcmNudl9kYXRhICU+JQogIGdyb3VwX2J5KGNocl9iYW5kLCBzdGF0ZSkgJT4lCiAgc3VtbWFyaXplKHVuaXF1ZV9jZWxscyA9IG5fZGlzdGluY3QoY2VsbF9ncm91cF9uYW1lKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgbXV0YXRlKAogICAgcGVyY2VudGFnZSA9ICh1bmlxdWVfY2VsbHMgLyB0b3RhbF9jZWxscykgKiAxMDAsCiAgICBjbnZfdHlwZSA9IGNhc2Vfd2hlbigKICAgICAgc3RhdGUgPT0gMSB+ICJDb21wbGV0ZSBMb3NzICgweCkiLAogICAgICBzdGF0ZSA9PSAyIH4gIkxvc3Mgb2YgT25lIENvcHkgKDAuNXgpIiwKICAgICAgc3RhdGUgPT0gMyB+ICJOZXV0cmFsICgxeCkiLAogICAgICBzdGF0ZSA9PSA0IH4gIkFkZGl0aW9uIG9mIE9uZSBDb3B5ICgxLjV4KSIsCiAgICAgIHN0YXRlID09IDUgfiAiQWRkaXRpb24gb2YgVHdvIENvcGllcyAoMngpIiwKICAgICAgc3RhdGUgPT0gNiB+ICJQbGFjZWhvbGRlciBmb3IgPjIgQ29waWVzICgzeCkiLAogICAgICBUUlVFIH4gIlVua25vd24iICAjIEZhbGxiYWNrIGZvciB1bmV4cGVjdGVkIHN0YXRlcwogICAgKQogICkKCiMgRmlsdGVyIGZvciBDTlZzIGFmZmVjdGluZyBtb3JlIHRoYW4gMTAlIG9mIGNlbGxzIChmb3IgYWxsIHN0YXRlcykKc2lnbmlmaWNhbnRfY252X3N1bW1hcnkgPC0gY252X3N1bW1hcnkgJT4lCiAgZmlsdGVyKHBlcmNlbnRhZ2UgPiA5MCkgJT4lCiAgc2VsZWN0KGNocl9iYW5kLCBzdGF0ZSwgdW5pcXVlX2NlbGxzLCBwZXJjZW50YWdlLCBjbnZfdHlwZSkKCiMgUHJpbnQgdGhlIHN1bW1hcnkgZm9yIHNpZ25pZmljYW50IENOViBhbmFseXNpcwpwcmludChzaWduaWZpY2FudF9jbnZfc3VtbWFyeSkKCiMgU2F2ZSB0aGUgc2lnbmlmaWNhbnQgQ05WIHN1bW1hcnkgdG8gYSBDU1YgZmlsZQpvdXRwdXRfZmlsZSA8LSAiTDFfY3l0b2dlbmV0aWNzL3NpZ25pZmljYW50X2Nudl9zdW1tYXJ5LmNzdiIKd3JpdGUuY3N2KHNpZ25pZmljYW50X2Nudl9zdW1tYXJ5LCBvdXRwdXRfZmlsZSwgcm93Lm5hbWVzID0gRkFMU0UpCgojIFByaW50IGNvbmZpcm1hdGlvbiBtZXNzYWdlCmNhdCgiU2lnbmlmaWNhbnQgQ05WIHN1bW1hcnkgc2F2ZWQgdG8iLCBvdXRwdXRfZmlsZSwgIlxuIikKCiMgVmlzdWFsaXphdGlvbiBvZiB0aGUgcGVyY2VudGFnZSBvZiBjZWxscyBhZmZlY3RlZCBieSBDTlZzIGluIGRpZmZlcmVudCBjaHJvbW9zb21lIGJhbmRzCmdncGxvdChzaWduaWZpY2FudF9jbnZfc3VtbWFyeSwgYWVzKHggPSByZW9yZGVyKGNocl9iYW5kLCAtcGVyY2VudGFnZSksIHkgPSBwZXJjZW50YWdlLCBmaWxsID0gY252X3R5cGUpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIikgKwogIGxhYnModGl0bGUgPSAiUGVyY2VudGFnZSBvZiBDZWxscyBBZmZlY3RlZCBieSBDTlZzIGluIENocm9tb3NvbWUgQmFuZHMiLAogICAgICAgeCA9ICJDaHJvbW9zb21lIEJhbmQiLAogICAgICAgeSA9ICJQZXJjZW50YWdlIG9mIENlbGxzIEFmZmVjdGVkICglKSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQoKIyBTYXZlIHRoZSBwbG90Cmdnc2F2ZSgiTDFfY3l0b2dlbmV0aWNzL2Nudl9wZXJjZW50YWdlX2J5X2NocmJhbmRzLnBuZyIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDYpCgpgYGAKCmBgYHtyIGRhdGE3LCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KIyBMb2FkIHJlcXVpcmVkIGxpYnJhcmllcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKQoKIyBSZWFkIHRoZSB1cGRhdGVkIGluZmVyQ05WIHJlc3VsdHMgd2l0aCBjaHJfYmFuZCBjb2x1bW4KaW5mZXJjbnZfZmlsZSA8LSAiTDFfY3l0b2dlbmV0aWNzL0wxX2luZmVyY252X3dpdGhfY2hyX2JhbmRzLmNzdiIKaW5mZXJjbnZfZGF0YSA8LSByZWFkLmNzdihpbmZlcmNudl9maWxlLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojIFRvdGFsIG51bWJlciBvZiB1bmlxdWUgY2VsbCBncm91cHMKdG90YWxfY2VsbHMgPC0gbGVuZ3RoKHVuaXF1ZShpbmZlcmNudl9kYXRhJGNlbGxfZ3JvdXBfbmFtZSkpCgojIEFuYWx5emUgQ05WIGZvciBhbGwgYmFuZHMKY252X3N1bW1hcnkgPC0gaW5mZXJjbnZfZGF0YSAlPiUKICBncm91cF9ieShjaHJfYmFuZCwgc3RhdGUpICU+JQogIHN1bW1hcml6ZSh1bmlxdWVfY2VsbHMgPSBuX2Rpc3RpbmN0KGNlbGxfZ3JvdXBfbmFtZSksIC5ncm91cHMgPSAnZHJvcCcpICU+JQogIG11dGF0ZSgKICAgIHBlcmNlbnRhZ2UgPSAodW5pcXVlX2NlbGxzIC8gdG90YWxfY2VsbHMpICogMTAwLAogICAgY252X3R5cGUgPSBjYXNlX3doZW4oCiAgICAgIHN0YXRlID09IDEgfiAiQ29tcGxldGUgTG9zcyAoMHgpIiwKICAgICAgc3RhdGUgPT0gMiB+ICJMb3NzIG9mIE9uZSBDb3B5ICgwLjV4KSIsCiAgICAgIHN0YXRlID09IDMgfiAiTmV1dHJhbCAoMXgpIiwKICAgICAgc3RhdGUgPT0gNCB+ICJBZGRpdGlvbiBvZiBPbmUgQ29weSAoMS41eCkiLAogICAgICBzdGF0ZSA9PSA1IH4gIkFkZGl0aW9uIG9mIFR3byBDb3BpZXMgKDJ4KSIsCiAgICAgIHN0YXRlID09IDYgfiAiUGxhY2Vob2xkZXIgZm9yID4yeCBDb3BpZXMgKDN4KSIsCiAgICAgIFRSVUUgfiAiVW5rbm93biIgICMgQWRkZWQgYSBmYWxsYmFjayBmb3IgdW5leHBlY3RlZCBzdGF0ZSB2YWx1ZXMKICAgICkKICApCgojIEZpbHRlciBmb3IgQ05WcyBhZmZlY3RpbmcgbW9yZSB0aGFuIDEwJSBvZiBjZWxscyAoZm9yIGFsbCBzdGF0ZXMpCnNpZ25pZmljYW50X2Nudl9zdW1tYXJ5IDwtIGNudl9zdW1tYXJ5ICU+JQogIGZpbHRlcihwZXJjZW50YWdlID4gOTApICU+JQogIHNlbGVjdChjaHJfYmFuZCwgc3RhdGUsIHVuaXF1ZV9jZWxscywgcGVyY2VudGFnZSwgY252X3R5cGUpCgoKIyBTYXZlIHRoZSBmaWx0ZXJlZCBnYWluL2xvc3Mgc3VtbWFyeSB0byBhIENTViBmaWxlCm91dHB1dF9maWxlIDwtICJMMV9jeXRvZ2VuZXRpY3Mvc2lnbmlmaWNhbnRfZ2Fpbl9sb3NzX3N1bW1hcnlfOTAuY3N2Igp3cml0ZS5jc3Yoc2lnbmlmaWNhbnRfY252X3N1bW1hcnksIG91dHB1dF9maWxlLCByb3cubmFtZXMgPSBGQUxTRSkKCiMgUHJpbnQgY29uZmlybWF0aW9uIG1lc3NhZ2UKY2F0KCJTaWduaWZpY2FudCBHYWluL0xvc3Mgc3VtbWFyeSB3aXRoID45MCUgYWZmZWN0ZWQgY2VsbHMgc2F2ZWQgdG8iLCBvdXRwdXRfZmlsZSwgIlxuIikKCiMgQ3JlYXRlIGEgYmFyIHBsb3Qgd2l0aCBwZXJjZW50YWdlIG9uIFgtYXhpcyBhbmQgY2hyb21vc29tYWwgYmFuZHMgb24gWS1heGlzCmdncGxvdChzaWduaWZpY2FudF9jbnZfc3VtbWFyeSwgYWVzKHggPSBwZXJjZW50YWdlLCB5ID0gY2hyX2JhbmQsIGZpbGwgPSBjbnZfdHlwZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgbGFicyh0aXRsZSA9ICJTaWduaWZpY2FudCBDTlZzIEFmZmVjdGluZyA+OTAlIG9mIENlbGxzIiwKICAgICAgIHggPSAiUGVyY2VudGFnZSBvZiBDZWxscyIsCiAgICAgICB5ID0gIkNocm9tb3NvbWFsIEJhbmQiLAogICAgICAgZmlsbCA9ICJDTlYgVHlwZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCwgaGp1c3QgPSAxKSkKCgpgYGAKCiMgTDEuCmBgYHtyIGRhdGE4LCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KIyBMb2FkIHJlcXVpcmVkIGxpYnJhcmllcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocmVhZHIpCgojIFJlYWQgdGhlIHVwZGF0ZWQgaW5mZXJDTlYgcmVzdWx0cyB3aXRoIGNocl9iYW5kIGNvbHVtbgppbmZlcmNudl9maWxlIDwtICJMMV9jeXRvZ2VuZXRpY3MvTDFfaW5mZXJjbnZfd2l0aF9jaHJfYmFuZHMuY3N2IgppbmZlcmNudl9kYXRhIDwtIHJlYWQuY3N2KGluZmVyY252X2ZpbGUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCiMgVG90YWwgbnVtYmVyIG9mIHVuaXF1ZSBjZWxsIGdyb3Vwcwp0b3RhbF9jZWxscyA8LSBsZW5ndGgodW5pcXVlKGluZmVyY252X2RhdGEkY2VsbF9ncm91cF9uYW1lKSkKCiMgQW5hbHl6ZSBDTlYgZm9yIGFsbCBiYW5kcwpjbnZfc3VtbWFyeSA8LSBpbmZlcmNudl9kYXRhICU+JQogIGdyb3VwX2J5KGNocl9iYW5kLCBzdGF0ZSkgJT4lCiAgc3VtbWFyaXplKHVuaXF1ZV9jZWxscyA9IG5fZGlzdGluY3QoY2VsbF9ncm91cF9uYW1lKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgbXV0YXRlKAogICAgcGVyY2VudGFnZSA9ICh1bmlxdWVfY2VsbHMgLyB0b3RhbF9jZWxscykgKiAxMDAsCiAgICBjbnZfdHlwZSA9IGNhc2Vfd2hlbigKICAgICAgc3RhdGUgPT0gMSB+ICJDb21wbGV0ZSBMb3NzICgweCkiLAogICAgICBzdGF0ZSA9PSAyIH4gIkxvc3Mgb2YgT25lIENvcHkgKDAuNXgpIiwKICAgICAgc3RhdGUgPT0gMyB+ICJOZXV0cmFsICgxeCkiLAogICAgICBzdGF0ZSA9PSA0IH4gIkFkZGl0aW9uIG9mIE9uZSBDb3B5ICgxLjV4KSIsCiAgICAgIHN0YXRlID09IDUgfiAiQWRkaXRpb24gb2YgVHdvIENvcGllcyAoMngpIiwKICAgICAgc3RhdGUgPT0gNiB+ICJQbGFjZWhvbGRlciBmb3IgPjJ4IENvcGllcyAoM3gpIiwKICAgICAgVFJVRSB+ICJVbmtub3duIgogICAgKQogICkKCiMgRmlsdGVyIGZvciBDTlZzIGFmZmVjdGluZyBtb3JlIHRoYW4gMTAlIG9mIGNlbGxzIChmb3IgYWxsIHN0YXRlcykKc2lnbmlmaWNhbnRfY252X3N1bW1hcnkgPC0gY252X3N1bW1hcnkgJT4lCiAgZmlsdGVyKHBlcmNlbnRhZ2UgPiA5MCkgJT4lCiAgc2VsZWN0KGNocl9iYW5kLCBzdGF0ZSwgdW5pcXVlX2NlbGxzLCBwZXJjZW50YWdlLCBjbnZfdHlwZSkKCiMgU2F2ZSB0aGUgZmlsdGVyZWQgZ2Fpbi9sb3NzIHN1bW1hcnkgdG8gYSBDU1YgZmlsZQpvdXRwdXRfZmlsZSA8LSAiTDFfY3l0b2dlbmV0aWNzL3NpZ25pZmljYW50X2dhaW5fbG9zc19zdW1tYXJ5XzkwLmNzdiIKd3JpdGUuY3N2KHNpZ25pZmljYW50X2Nudl9zdW1tYXJ5LCBvdXRwdXRfZmlsZSwgcm93Lm5hbWVzID0gRkFMU0UpCgojIFByaW50IGNvbmZpcm1hdGlvbiBtZXNzYWdlCmNhdCgiU2lnbmlmaWNhbnQgR2Fpbi9Mb3NzIHN1bW1hcnkgd2l0aCA+OTAlIGFmZmVjdGVkIGNlbGxzIHNhdmVkIHRvIiwgb3V0cHV0X2ZpbGUsICJcbiIpCgojIFB1YmxpY2F0aW9uLXF1YWxpdHkgcGxvdCB3aXRoIHBlcmNlbnRhZ2Ugb2YgY2VsbHMgb24gWC1heGlzIGFuZCBjaHJvbW9zb21hbCBiYW5kcyBvbiBZLWF4aXMKZ2dwbG90KHNpZ25pZmljYW50X2Nudl9zdW1tYXJ5LCBhZXMoeCA9IHBlcmNlbnRhZ2UsIHkgPSByZW9yZGVyKGNocl9iYW5kLCBwZXJjZW50YWdlKSwgZmlsbCA9IGNudl90eXBlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHdpZHRoID0gMC44KSArICAjIEFkanVzdGVkIGJhciB3aWR0aAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkNvbXBsZXRlIExvc3MgKDB4KSIgPSAiI2ZkYWU2MSIsICAjIFJlZCBmb3IgbG9zcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxvc3Mgb2YgT25lIENvcHkgKDAuNXgpIiA9ICIjMzEzNjk1IiwgICMgT3JhbmdlIGZvciBwYXJ0aWFsIGxvc3MKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBZGRpdGlvbiBvZiBPbmUgQ29weSAoMS41eCkiID0gInJlZCIsICAjIEJsdWUgZm9yIGdhaW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBZGRpdGlvbiBvZiBUd28gQ29waWVzICgyeCkiID0gImRhcmtncmVlbiIpKSArICAjIERhcmsgYmx1ZSBmb3IgaGlnaGVyIGdhaW4KICBsYWJzKHRpdGxlID0gIlNpZ25pZmljYW50IENOVnMgQWZmZWN0aW5nID45MCUgb2YgQ2VsbHMiLAogICAgICAgc3VidGl0bGUgPSAiQ2hyb21vc29tYWwgQmFuZHMgd2l0aCBDTlZzIGluID45MCUgb2YgQ2VsbHMiLAogICAgICAgeCA9ICJQZXJjZW50YWdlIG9mIENlbGxzICglKSIsCiAgICAgICB5ID0gIkNocm9tb3NvbWFsIEJhbmQiLAogICAgICAgZmlsbCA9ICJDTlYgVHlwZSIpICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArICAjIEFkanVzdCB0ZXh0IHNpemUgZm9yIHJlYWRhYmlsaXR5CiAgdGhlbWUoCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTgsIGZhY2UgPSAiYm9sZCIpLCAgIyBDZW50ZXIgdGhlIHRpdGxlCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTQpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyYXk5MCIpLCAgIyBBZGQgZ3JpZGxpbmVzCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksICAjIFJlbW92ZSBtaW5vciBncmlkbGluZXMKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLCAgIyBQb3NpdGlvbiBsZWdlbmQgYXQgdGhlIHRvcAogICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjgsICJjbSIpCiAgKSAKCmBgYAojIEwyLgpgYGB7ciBkYXRhOSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgTG9hZCByZXF1aXJlZCBsaWJyYXJpZXMKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlYWRyKQoKIyBSZWFkIHRoZSB1cGRhdGVkIGluZmVyQ05WIHJlc3VsdHMgd2l0aCBjaHJfYmFuZCBjb2x1bW4KaW5mZXJjbnZfZmlsZSA8LSAiTDJfY3l0b2dlbmV0aWNzL0wyX2luZmVyY252X3dpdGhfY2hyX2JhbmRzLmNzdiIKaW5mZXJjbnZfZGF0YSA8LSByZWFkLmNzdihpbmZlcmNudl9maWxlLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojIFRvdGFsIG51bWJlciBvZiB1bmlxdWUgY2VsbCBncm91cHMKdG90YWxfY2VsbHMgPC0gbGVuZ3RoKHVuaXF1ZShpbmZlcmNudl9kYXRhJGNlbGxfZ3JvdXBfbmFtZSkpCgojIEFuYWx5emUgQ05WIGZvciBhbGwgYmFuZHMKY252X3N1bW1hcnkgPC0gaW5mZXJjbnZfZGF0YSAlPiUKICBncm91cF9ieShjaHJfYmFuZCwgc3RhdGUpICU+JQogIHN1bW1hcml6ZSh1bmlxdWVfY2VsbHMgPSBuX2Rpc3RpbmN0KGNlbGxfZ3JvdXBfbmFtZSksIC5ncm91cHMgPSAnZHJvcCcpICU+JQogIG11dGF0ZSgKICAgIHBlcmNlbnRhZ2UgPSAodW5pcXVlX2NlbGxzIC8gdG90YWxfY2VsbHMpICogMTAwLAogICAgY252X3R5cGUgPSBjYXNlX3doZW4oCiAgICAgIHN0YXRlID09IDEgfiAiQ29tcGxldGUgTG9zcyAoMHgpIiwKICAgICAgc3RhdGUgPT0gMiB+ICJMb3NzIG9mIE9uZSBDb3B5ICgwLjV4KSIsCiAgICAgIHN0YXRlID09IDMgfiAiTmV1dHJhbCAoMXgpIiwKICAgICAgc3RhdGUgPT0gNCB+ICJBZGRpdGlvbiBvZiBPbmUgQ29weSAoMS41eCkiLAogICAgICBzdGF0ZSA9PSA1IH4gIkFkZGl0aW9uIG9mIFR3byBDb3BpZXMgKDJ4KSIsCiAgICAgIHN0YXRlID09IDYgfiAiUGxhY2Vob2xkZXIgZm9yID4yeCBDb3BpZXMgKDN4KSIsCiAgICAgIFRSVUUgfiAiVW5rbm93biIKICAgICkKICApCgojIEZpbHRlciBmb3IgQ05WcyBhZmZlY3RpbmcgbW9yZSB0aGFuIDEwJSBvZiBjZWxscyAoZm9yIGFsbCBzdGF0ZXMpCnNpZ25pZmljYW50X2Nudl9zdW1tYXJ5IDwtIGNudl9zdW1tYXJ5ICU+JQogIGZpbHRlcihwZXJjZW50YWdlID4gOTcpICU+JQogIHNlbGVjdChjaHJfYmFuZCwgc3RhdGUsIHVuaXF1ZV9jZWxscywgcGVyY2VudGFnZSwgY252X3R5cGUpCgojIFNhdmUgdGhlIGZpbHRlcmVkIGdhaW4vbG9zcyBzdW1tYXJ5IHRvIGEgQ1NWIGZpbGUKb3V0cHV0X2ZpbGUgPC0gIkwyX2N5dG9nZW5ldGljcy9zaWduaWZpY2FudF9nYWluX2xvc3Nfc3VtbWFyeV85MC5jc3YiCndyaXRlLmNzdihzaWduaWZpY2FudF9jbnZfc3VtbWFyeSwgb3V0cHV0X2ZpbGUsIHJvdy5uYW1lcyA9IEZBTFNFKQoKIyBQcmludCBjb25maXJtYXRpb24gbWVzc2FnZQpjYXQoIlNpZ25pZmljYW50IEdhaW4vTG9zcyBzdW1tYXJ5IHdpdGggPjkwJSBhZmZlY3RlZCBjZWxscyBzYXZlZCB0byIsIG91dHB1dF9maWxlLCAiXG4iKQoKIyBQdWJsaWNhdGlvbi1xdWFsaXR5IHBsb3Qgd2l0aCBwZXJjZW50YWdlIG9mIGNlbGxzIG9uIFgtYXhpcyBhbmQgY2hyb21vc29tYWwgYmFuZHMgb24gWS1heGlzCmdncGxvdChzaWduaWZpY2FudF9jbnZfc3VtbWFyeSwgYWVzKHggPSBwZXJjZW50YWdlLCB5ID0gcmVvcmRlcihjaHJfYmFuZCwgcGVyY2VudGFnZSksIGZpbGwgPSBjbnZfdHlwZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCB3aWR0aCA9IDAuOCkgKyAgIyBBZGp1c3RlZCBiYXIgd2lkdGgKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJDb21wbGV0ZSBMb3NzICgweCkiID0gIiNmZGFlNjEiLCAgIyBSZWQgZm9yIGxvc3MKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMb3NzIG9mIE9uZSBDb3B5ICgwLjV4KSIgPSAiIzMxMzY5NSIsICAjIE9yYW5nZSBmb3IgcGFydGlhbCBsb3NzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWRkaXRpb24gb2YgT25lIENvcHkgKDEuNXgpIiA9ICJyZWQiLCAgIyBCbHVlIGZvciBnYWluCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWRkaXRpb24gb2YgVHdvIENvcGllcyAoMngpIiA9ICJkYXJrZ3JlZW4iKSkgKyAgIyBEYXJrIGJsdWUgZm9yIGhpZ2hlciBnYWluCiAgbGFicyh0aXRsZSA9ICJTaWduaWZpY2FudCBDTlZzIEFmZmVjdGluZyA+OTAlIG9mIENlbGxzIiwKICAgICAgIHN1YnRpdGxlID0gIkNocm9tb3NvbWFsIEJhbmRzIHdpdGggQ05WcyBpbiA+OTAlIG9mIENlbGxzIiwKICAgICAgIHggPSAiUGVyY2VudGFnZSBvZiBDZWxscyAoJSkiLAogICAgICAgeSA9ICJDaHJvbW9zb21hbCBCYW5kIiwKICAgICAgIGZpbGwgPSAiQ05WIFR5cGUiKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKyAgIyBBZGp1c3QgdGV4dCBzaXplIGZvciByZWFkYWJpbGl0eQogIHRoZW1lKAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE4LCBmYWNlID0gImJvbGQiKSwgICMgQ2VudGVyIHRoZSB0aXRsZQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE0KSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5OTAiKSwgICMgQWRkIGdyaWRsaW5lcwogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLCAgIyBSZW1vdmUgbWlub3IgZ3JpZGxpbmVzCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgICMgUG9zaXRpb24gbGVnZW5kIGF0IHRoZSB0b3AKICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC44LCAiY20iKQogICkgCgpgYGAKIyBMMy4KYGBge3IgZGF0YTEwLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KIyBMb2FkIHJlcXVpcmVkIGxpYnJhcmllcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocmVhZHIpCgojIFJlYWQgdGhlIHVwZGF0ZWQgaW5mZXJDTlYgcmVzdWx0cyB3aXRoIGNocl9iYW5kIGNvbHVtbgppbmZlcmNudl9maWxlIDwtICJMM19jeXRvZ2VuZXRpY3MvTDNfaW5mZXJjbnZfd2l0aF9jaHJfYmFuZHMuY3N2IgppbmZlcmNudl9kYXRhIDwtIHJlYWQuY3N2KGluZmVyY252X2ZpbGUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCiMgVG90YWwgbnVtYmVyIG9mIHVuaXF1ZSBjZWxsIGdyb3Vwcwp0b3RhbF9jZWxscyA8LSBsZW5ndGgodW5pcXVlKGluZmVyY252X2RhdGEkY2VsbF9ncm91cF9uYW1lKSkKCiMgQW5hbHl6ZSBDTlYgZm9yIGFsbCBiYW5kcwpjbnZfc3VtbWFyeSA8LSBpbmZlcmNudl9kYXRhICU+JQogIGdyb3VwX2J5KGNocl9iYW5kLCBzdGF0ZSkgJT4lCiAgc3VtbWFyaXplKHVuaXF1ZV9jZWxscyA9IG5fZGlzdGluY3QoY2VsbF9ncm91cF9uYW1lKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgbXV0YXRlKAogICAgcGVyY2VudGFnZSA9ICh1bmlxdWVfY2VsbHMgLyB0b3RhbF9jZWxscykgKiAxMDAsCiAgICBjbnZfdHlwZSA9IGNhc2Vfd2hlbigKICAgICAgc3RhdGUgPT0gMSB+ICJDb21wbGV0ZSBMb3NzICgweCkiLAogICAgICBzdGF0ZSA9PSAyIH4gIkxvc3Mgb2YgT25lIENvcHkgKDAuNXgpIiwKICAgICAgc3RhdGUgPT0gMyB+ICJOZXV0cmFsICgxeCkiLAogICAgICBzdGF0ZSA9PSA0IH4gIkFkZGl0aW9uIG9mIE9uZSBDb3B5ICgxLjV4KSIsCiAgICAgIHN0YXRlID09IDUgfiAiQWRkaXRpb24gb2YgVHdvIENvcGllcyAoMngpIiwKICAgICAgc3RhdGUgPT0gNiB+ICJQbGFjZWhvbGRlciBmb3IgPjJ4IENvcGllcyAoM3gpIiwKICAgICAgVFJVRSB+ICJVbmtub3duIgogICAgKQogICkKCiMgRmlsdGVyIGZvciBDTlZzIGFmZmVjdGluZyBtb3JlIHRoYW4gMTAlIG9mIGNlbGxzIChmb3IgYWxsIHN0YXRlcykKc2lnbmlmaWNhbnRfY252X3N1bW1hcnkgPC0gY252X3N1bW1hcnkgJT4lCiAgZmlsdGVyKHBlcmNlbnRhZ2UgPiA5OCkgJT4lCiAgc2VsZWN0KGNocl9iYW5kLCBzdGF0ZSwgdW5pcXVlX2NlbGxzLCBwZXJjZW50YWdlLCBjbnZfdHlwZSkKCiMgU2F2ZSB0aGUgZmlsdGVyZWQgZ2Fpbi9sb3NzIHN1bW1hcnkgdG8gYSBDU1YgZmlsZQpvdXRwdXRfZmlsZSA8LSAiTDNfY3l0b2dlbmV0aWNzL3NpZ25pZmljYW50X2dhaW5fbG9zc19zdW1tYXJ5XzkwLmNzdiIKd3JpdGUuY3N2KHNpZ25pZmljYW50X2Nudl9zdW1tYXJ5LCBvdXRwdXRfZmlsZSwgcm93Lm5hbWVzID0gRkFMU0UpCgojIFByaW50IGNvbmZpcm1hdGlvbiBtZXNzYWdlCmNhdCgiU2lnbmlmaWNhbnQgR2Fpbi9Mb3NzIHN1bW1hcnkgd2l0aCA+OTAlIGFmZmVjdGVkIGNlbGxzIHNhdmVkIHRvIiwgb3V0cHV0X2ZpbGUsICJcbiIpCgojIFB1YmxpY2F0aW9uLXF1YWxpdHkgcGxvdCB3aXRoIHBlcmNlbnRhZ2Ugb2YgY2VsbHMgb24gWC1heGlzIGFuZCBjaHJvbW9zb21hbCBiYW5kcyBvbiBZLWF4aXMKZ2dwbG90KHNpZ25pZmljYW50X2Nudl9zdW1tYXJ5LCBhZXMoeCA9IHBlcmNlbnRhZ2UsIHkgPSByZW9yZGVyKGNocl9iYW5kLCBwZXJjZW50YWdlKSwgZmlsbCA9IGNudl90eXBlKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHdpZHRoID0gMC44KSArICAjIEFkanVzdGVkIGJhciB3aWR0aAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkNvbXBsZXRlIExvc3MgKDB4KSIgPSAiI2ZkYWU2MSIsICAjIFJlZCBmb3IgbG9zcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkxvc3Mgb2YgT25lIENvcHkgKDAuNXgpIiA9ICIjMzEzNjk1IiwgICMgT3JhbmdlIGZvciBwYXJ0aWFsIGxvc3MKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBZGRpdGlvbiBvZiBPbmUgQ29weSAoMS41eCkiID0gInJlZCIsICAjIEJsdWUgZm9yIGdhaW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBZGRpdGlvbiBvZiBUd28gQ29waWVzICgyeCkiID0gImRhcmtncmVlbiIpKSArICAjIERhcmsgYmx1ZSBmb3IgaGlnaGVyIGdhaW4KICBsYWJzKHRpdGxlID0gIlNpZ25pZmljYW50IENOVnMgQWZmZWN0aW5nID45MCUgb2YgQ2VsbHMiLAogICAgICAgc3VidGl0bGUgPSAiQ2hyb21vc29tYWwgQmFuZHMgd2l0aCBDTlZzIGluID45MCUgb2YgQ2VsbHMiLAogICAgICAgeCA9ICJQZXJjZW50YWdlIG9mIENlbGxzICglKSIsCiAgICAgICB5ID0gIkNocm9tb3NvbWFsIEJhbmQiLAogICAgICAgZmlsbCA9ICJDTlYgVHlwZSIpICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArICAjIEFkanVzdCB0ZXh0IHNpemUgZm9yIHJlYWRhYmlsaXR5CiAgdGhlbWUoCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTgsIGZhY2UgPSAiYm9sZCIpLCAgIyBDZW50ZXIgdGhlIHRpdGxlCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBzaXplID0gMTQpLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyYXk5MCIpLCAgIyBBZGQgZ3JpZGxpbmVzCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksICAjIFJlbW92ZSBtaW5vciBncmlkbGluZXMKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLCAgIyBQb3NpdGlvbiBsZWdlbmQgYXQgdGhlIHRvcAogICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjgsICJjbSIpCiAgKSAKCmBgYAojIEw0LgpgYGB7ciBkYXRhMTEsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQojIExvYWQgcmVxdWlyZWQgbGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShyZWFkcikKCiMgUmVhZCB0aGUgdXBkYXRlZCBpbmZlckNOViByZXN1bHRzIHdpdGggY2hyX2JhbmQgY29sdW1uCmluZmVyY252X2ZpbGUgPC0gIkw0X2N5dG9nZW5ldGljcy9MNF9pbmZlcmNudl93aXRoX2Nocl9iYW5kcy5jc3YiCmluZmVyY252X2RhdGEgPC0gcmVhZC5jc3YoaW5mZXJjbnZfZmlsZSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBUb3RhbCBudW1iZXIgb2YgdW5pcXVlIGNlbGwgZ3JvdXBzCnRvdGFsX2NlbGxzIDwtIGxlbmd0aCh1bmlxdWUoaW5mZXJjbnZfZGF0YSRjZWxsX2dyb3VwX25hbWUpKQoKIyBBbmFseXplIENOViBmb3IgYWxsIGJhbmRzCmNudl9zdW1tYXJ5IDwtIGluZmVyY252X2RhdGEgJT4lCiAgZ3JvdXBfYnkoY2hyX2JhbmQsIHN0YXRlKSAlPiUKICBzdW1tYXJpemUodW5pcXVlX2NlbGxzID0gbl9kaXN0aW5jdChjZWxsX2dyb3VwX25hbWUpLCAuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUKICBtdXRhdGUoCiAgICBwZXJjZW50YWdlID0gKHVuaXF1ZV9jZWxscyAvIHRvdGFsX2NlbGxzKSAqIDEwMCwKICAgIGNudl90eXBlID0gY2FzZV93aGVuKAogICAgICBzdGF0ZSA9PSAxIH4gIkNvbXBsZXRlIExvc3MgKDB4KSIsCiAgICAgIHN0YXRlID09IDIgfiAiTG9zcyBvZiBPbmUgQ29weSAoMC41eCkiLAogICAgICBzdGF0ZSA9PSAzIH4gIk5ldXRyYWwgKDF4KSIsCiAgICAgIHN0YXRlID09IDQgfiAiQWRkaXRpb24gb2YgT25lIENvcHkgKDEuNXgpIiwKICAgICAgc3RhdGUgPT0gNSB+ICJBZGRpdGlvbiBvZiBUd28gQ29waWVzICgyeCkiLAogICAgICBzdGF0ZSA9PSA2IH4gIlBsYWNlaG9sZGVyIGZvciA+MnggQ29waWVzICgzeCkiLAogICAgICBUUlVFIH4gIlVua25vd24iCiAgICApCiAgKQoKIyBGaWx0ZXIgZm9yIENOVnMgYWZmZWN0aW5nIG1vcmUgdGhhbiAxMCUgb2YgY2VsbHMgKGZvciBhbGwgc3RhdGVzKQpzaWduaWZpY2FudF9jbnZfc3VtbWFyeSA8LSBjbnZfc3VtbWFyeSAlPiUKICBmaWx0ZXIocGVyY2VudGFnZSA+IDkzKSAlPiUKICBzZWxlY3QoY2hyX2JhbmQsIHN0YXRlLCB1bmlxdWVfY2VsbHMsIHBlcmNlbnRhZ2UsIGNudl90eXBlKQoKIyBTYXZlIHRoZSBmaWx0ZXJlZCBnYWluL2xvc3Mgc3VtbWFyeSB0byBhIENTViBmaWxlCm91dHB1dF9maWxlIDwtICJMNF9jeXRvZ2VuZXRpY3Mvc2lnbmlmaWNhbnRfZ2Fpbl9sb3NzX3N1bW1hcnlfOTAuY3N2Igp3cml0ZS5jc3Yoc2lnbmlmaWNhbnRfY252X3N1bW1hcnksIG91dHB1dF9maWxlLCByb3cubmFtZXMgPSBGQUxTRSkKCiMgUHJpbnQgY29uZmlybWF0aW9uIG1lc3NhZ2UKY2F0KCJTaWduaWZpY2FudCBHYWluL0xvc3Mgc3VtbWFyeSB3aXRoID45MCUgYWZmZWN0ZWQgY2VsbHMgc2F2ZWQgdG8iLCBvdXRwdXRfZmlsZSwgIlxuIikKCiMgUHVibGljYXRpb24tcXVhbGl0eSBwbG90IHdpdGggcGVyY2VudGFnZSBvZiBjZWxscyBvbiBYLWF4aXMgYW5kIGNocm9tb3NvbWFsIGJhbmRzIG9uIFktYXhpcwpnZ3Bsb3Qoc2lnbmlmaWNhbnRfY252X3N1bW1hcnksIGFlcyh4ID0gcGVyY2VudGFnZSwgeSA9IHJlb3JkZXIoY2hyX2JhbmQsIHBlcmNlbnRhZ2UpLCBmaWxsID0gY252X3R5cGUpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgd2lkdGggPSAwLjgpICsgICMgQWRqdXN0ZWQgYmFyIHdpZHRoCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiQ29tcGxldGUgTG9zcyAoMHgpIiA9ICIjZmRhZTYxIiwgICMgUmVkIGZvciBsb3NzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTG9zcyBvZiBPbmUgQ29weSAoMC41eCkiID0gIiMzMTM2OTUiLCAgIyBPcmFuZ2UgZm9yIHBhcnRpYWwgbG9zcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFkZGl0aW9uIG9mIE9uZSBDb3B5ICgxLjV4KSIgPSAicmVkIiwgICMgQmx1ZSBmb3IgZ2FpbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFkZGl0aW9uIG9mIFR3byBDb3BpZXMgKDJ4KSIgPSAiZGFya2dyZWVuIikpICsgICMgRGFyayBibHVlIGZvciBoaWdoZXIgZ2FpbgogIGxhYnModGl0bGUgPSAiU2lnbmlmaWNhbnQgQ05WcyBBZmZlY3RpbmcgPjkwJSBvZiBDZWxscyIsCiAgICAgICBzdWJ0aXRsZSA9ICJDaHJvbW9zb21hbCBCYW5kcyB3aXRoIENOVnMgaW4gPjkwJSBvZiBDZWxscyIsCiAgICAgICB4ID0gIlBlcmNlbnRhZ2Ugb2YgQ2VsbHMgKCUpIiwKICAgICAgIHkgPSAiQ2hyb21vc29tYWwgQmFuZCIsCiAgICAgICBmaWxsID0gIkNOViBUeXBlIikgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsgICMgQWRqdXN0IHRleHQgc2l6ZSBmb3IgcmVhZGFiaWxpdHkKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxOCwgZmFjZSA9ICJib2xkIiksICAjIENlbnRlciB0aGUgdGl0bGUKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTkwIiksICAjIEFkZCBncmlkbGluZXMKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUmVtb3ZlIG1pbm9yIGdyaWRsaW5lcwogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsICAjIFBvc2l0aW9uIGxlZ2VuZCBhdCB0aGUgdG9wCiAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuOCwgImNtIikKICApIAoKYGBgCiMgTDUuCmBgYHtyIGRhdGExMiwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgTG9hZCByZXF1aXJlZCBsaWJyYXJpZXMKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlYWRyKQoKIyBSZWFkIHRoZSB1cGRhdGVkIGluZmVyQ05WIHJlc3VsdHMgd2l0aCBjaHJfYmFuZCBjb2x1bW4KaW5mZXJjbnZfZmlsZSA8LSAiTDVfY3l0b2dlbmV0aWNzL0w1X2luZmVyY252X3dpdGhfY2hyX2JhbmRzLmNzdiIKaW5mZXJjbnZfZGF0YSA8LSByZWFkLmNzdihpbmZlcmNudl9maWxlLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojIFRvdGFsIG51bWJlciBvZiB1bmlxdWUgY2VsbCBncm91cHMKdG90YWxfY2VsbHMgPC0gbGVuZ3RoKHVuaXF1ZShpbmZlcmNudl9kYXRhJGNlbGxfZ3JvdXBfbmFtZSkpCgojIEFuYWx5emUgQ05WIGZvciBhbGwgYmFuZHMKY252X3N1bW1hcnkgPC0gaW5mZXJjbnZfZGF0YSAlPiUKICBncm91cF9ieShjaHJfYmFuZCwgc3RhdGUpICU+JQogIHN1bW1hcml6ZSh1bmlxdWVfY2VsbHMgPSBuX2Rpc3RpbmN0KGNlbGxfZ3JvdXBfbmFtZSksIC5ncm91cHMgPSAnZHJvcCcpICU+JQogIG11dGF0ZSgKICAgIHBlcmNlbnRhZ2UgPSAodW5pcXVlX2NlbGxzIC8gdG90YWxfY2VsbHMpICogMTAwLAogICAgY252X3R5cGUgPSBjYXNlX3doZW4oCiAgICAgIHN0YXRlID09IDEgfiAiQ29tcGxldGUgTG9zcyAoMHgpIiwKICAgICAgc3RhdGUgPT0gMiB+ICJMb3NzIG9mIE9uZSBDb3B5ICgwLjV4KSIsCiAgICAgIHN0YXRlID09IDMgfiAiTmV1dHJhbCAoMXgpIiwKICAgICAgc3RhdGUgPT0gNCB+ICJBZGRpdGlvbiBvZiBPbmUgQ29weSAoMS41eCkiLAogICAgICBzdGF0ZSA9PSA1IH4gIkFkZGl0aW9uIG9mIFR3byBDb3BpZXMgKDJ4KSIsCiAgICAgIHN0YXRlID09IDYgfiAiUGxhY2Vob2xkZXIgZm9yID4yeCBDb3BpZXMgKDN4KSIsCiAgICAgIFRSVUUgfiAiVW5rbm93biIKICAgICkKICApCgojIEZpbHRlciBmb3IgQ05WcyBhZmZlY3RpbmcgbW9yZSB0aGFuIDEwJSBvZiBjZWxscyAoZm9yIGFsbCBzdGF0ZXMpCnNpZ25pZmljYW50X2Nudl9zdW1tYXJ5IDwtIGNudl9zdW1tYXJ5ICU+JQogIGZpbHRlcihwZXJjZW50YWdlID4gOTApICU+JQogIHNlbGVjdChjaHJfYmFuZCwgc3RhdGUsIHVuaXF1ZV9jZWxscywgcGVyY2VudGFnZSwgY252X3R5cGUpCgojIFNhdmUgdGhlIGZpbHRlcmVkIGdhaW4vbG9zcyBzdW1tYXJ5IHRvIGEgQ1NWIGZpbGUKb3V0cHV0X2ZpbGUgPC0gIkw1X2N5dG9nZW5ldGljcy9zaWduaWZpY2FudF9nYWluX2xvc3Nfc3VtbWFyeV85MC5jc3YiCndyaXRlLmNzdihzaWduaWZpY2FudF9jbnZfc3VtbWFyeSwgb3V0cHV0X2ZpbGUsIHJvdy5uYW1lcyA9IEZBTFNFKQoKIyBQcmludCBjb25maXJtYXRpb24gbWVzc2FnZQpjYXQoIlNpZ25pZmljYW50IEdhaW4vTG9zcyBzdW1tYXJ5IHdpdGggPjkwJSBhZmZlY3RlZCBjZWxscyBzYXZlZCB0byIsIG91dHB1dF9maWxlLCAiXG4iKQoKIyBQdWJsaWNhdGlvbi1xdWFsaXR5IHBsb3Qgd2l0aCBwZXJjZW50YWdlIG9mIGNlbGxzIG9uIFgtYXhpcyBhbmQgY2hyb21vc29tYWwgYmFuZHMgb24gWS1heGlzCmdncGxvdChzaWduaWZpY2FudF9jbnZfc3VtbWFyeSwgYWVzKHggPSBwZXJjZW50YWdlLCB5ID0gcmVvcmRlcihjaHJfYmFuZCwgcGVyY2VudGFnZSksIGZpbGwgPSBjbnZfdHlwZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCB3aWR0aCA9IDAuOCkgKyAgIyBBZGp1c3RlZCBiYXIgd2lkdGgKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJDb21wbGV0ZSBMb3NzICgweCkiID0gIiNmZGFlNjEiLCAgIyBSZWQgZm9yIGxvc3MKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMb3NzIG9mIE9uZSBDb3B5ICgwLjV4KSIgPSAiIzMxMzY5NSIsICAjIE9yYW5nZSBmb3IgcGFydGlhbCBsb3NzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWRkaXRpb24gb2YgT25lIENvcHkgKDEuNXgpIiA9ICJyZWQiLCAgIyBCbHVlIGZvciBnYWluCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWRkaXRpb24gb2YgVHdvIENvcGllcyAoMngpIiA9ICJkYXJrZ3JlZW4iKSkgKyAgIyBEYXJrIGJsdWUgZm9yIGhpZ2hlciBnYWluCiAgbGFicyh0aXRsZSA9ICJTaWduaWZpY2FudCBDTlZzIEFmZmVjdGluZyA+OTAlIG9mIENlbGxzIiwKICAgICAgIHN1YnRpdGxlID0gIkNocm9tb3NvbWFsIEJhbmRzIHdpdGggQ05WcyBpbiA+OTAlIG9mIENlbGxzIiwKICAgICAgIHggPSAiUGVyY2VudGFnZSBvZiBDZWxscyAoJSkiLAogICAgICAgeSA9ICJDaHJvbW9zb21hbCBCYW5kIiwKICAgICAgIGZpbGwgPSAiQ05WIFR5cGUiKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKyAgIyBBZGp1c3QgdGV4dCBzaXplIGZvciByZWFkYWJpbGl0eQogIHRoZW1lKAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE4LCBmYWNlID0gImJvbGQiKSwgICMgQ2VudGVyIHRoZSB0aXRsZQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE0KSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5OTAiKSwgICMgQWRkIGdyaWRsaW5lcwogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLCAgIyBSZW1vdmUgbWlub3IgZ3JpZGxpbmVzCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgICMgUG9zaXRpb24gbGVnZW5kIGF0IHRoZSB0b3AKICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC44LCAiY20iKQogICkgCgpgYGAKCgojIEw2LgpgYGB7ciBkYXRhMTMsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQojIExvYWQgcmVxdWlyZWQgbGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShyZWFkcikKCiMgUmVhZCB0aGUgdXBkYXRlZCBpbmZlckNOViByZXN1bHRzIHdpdGggY2hyX2JhbmQgY29sdW1uCmluZmVyY252X2ZpbGUgPC0gIkw2X2N5dG9nZW5ldGljcy9MNl9pbmZlcmNudl93aXRoX2Nocl9iYW5kcy5jc3YiCmluZmVyY252X2RhdGEgPC0gcmVhZC5jc3YoaW5mZXJjbnZfZmlsZSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBUb3RhbCBudW1iZXIgb2YgdW5pcXVlIGNlbGwgZ3JvdXBzCnRvdGFsX2NlbGxzIDwtIGxlbmd0aCh1bmlxdWUoaW5mZXJjbnZfZGF0YSRjZWxsX2dyb3VwX25hbWUpKQoKIyBBbmFseXplIENOViBmb3IgYWxsIGJhbmRzCmNudl9zdW1tYXJ5IDwtIGluZmVyY252X2RhdGEgJT4lCiAgZ3JvdXBfYnkoY2hyX2JhbmQsIHN0YXRlKSAlPiUKICBzdW1tYXJpemUodW5pcXVlX2NlbGxzID0gbl9kaXN0aW5jdChjZWxsX2dyb3VwX25hbWUpLCAuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUKICBtdXRhdGUoCiAgICBwZXJjZW50YWdlID0gKHVuaXF1ZV9jZWxscyAvIHRvdGFsX2NlbGxzKSAqIDEwMCwKICAgIGNudl90eXBlID0gY2FzZV93aGVuKAogICAgICBzdGF0ZSA9PSAxIH4gIkNvbXBsZXRlIExvc3MgKDB4KSIsCiAgICAgIHN0YXRlID09IDIgfiAiTG9zcyBvZiBPbmUgQ29weSAoMC41eCkiLAogICAgICBzdGF0ZSA9PSAzIH4gIk5ldXRyYWwgKDF4KSIsCiAgICAgIHN0YXRlID09IDQgfiAiQWRkaXRpb24gb2YgT25lIENvcHkgKDEuNXgpIiwKICAgICAgc3RhdGUgPT0gNSB+ICJBZGRpdGlvbiBvZiBUd28gQ29waWVzICgyeCkiLAogICAgICBzdGF0ZSA9PSA2IH4gIlBsYWNlaG9sZGVyIGZvciA+MnggQ29waWVzICgzeCkiLAogICAgICBUUlVFIH4gIlVua25vd24iCiAgICApCiAgKQoKIyBGaWx0ZXIgZm9yIENOVnMgYWZmZWN0aW5nIG1vcmUgdGhhbiAxMCUgb2YgY2VsbHMgKGZvciBhbGwgc3RhdGVzKQpzaWduaWZpY2FudF9jbnZfc3VtbWFyeSA8LSBjbnZfc3VtbWFyeSAlPiUKICBmaWx0ZXIocGVyY2VudGFnZSA+IDkwKSAlPiUKICBzZWxlY3QoY2hyX2JhbmQsIHN0YXRlLCB1bmlxdWVfY2VsbHMsIHBlcmNlbnRhZ2UsIGNudl90eXBlKQoKIyBTYXZlIHRoZSBmaWx0ZXJlZCBnYWluL2xvc3Mgc3VtbWFyeSB0byBhIENTViBmaWxlCm91dHB1dF9maWxlIDwtICJMNl9jeXRvZ2VuZXRpY3Mvc2lnbmlmaWNhbnRfZ2Fpbl9sb3NzX3N1bW1hcnlfOTAuY3N2Igp3cml0ZS5jc3Yoc2lnbmlmaWNhbnRfY252X3N1bW1hcnksIG91dHB1dF9maWxlLCByb3cubmFtZXMgPSBGQUxTRSkKCiMgUHJpbnQgY29uZmlybWF0aW9uIG1lc3NhZ2UKY2F0KCJTaWduaWZpY2FudCBHYWluL0xvc3Mgc3VtbWFyeSB3aXRoID45MCUgYWZmZWN0ZWQgY2VsbHMgc2F2ZWQgdG8iLCBvdXRwdXRfZmlsZSwgIlxuIikKCiMgUHVibGljYXRpb24tcXVhbGl0eSBwbG90IHdpdGggcGVyY2VudGFnZSBvZiBjZWxscyBvbiBYLWF4aXMgYW5kIGNocm9tb3NvbWFsIGJhbmRzIG9uIFktYXhpcwpnZ3Bsb3Qoc2lnbmlmaWNhbnRfY252X3N1bW1hcnksIGFlcyh4ID0gcGVyY2VudGFnZSwgeSA9IHJlb3JkZXIoY2hyX2JhbmQsIHBlcmNlbnRhZ2UpLCBmaWxsID0gY252X3R5cGUpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgd2lkdGggPSAwLjgpICsgICMgQWRqdXN0ZWQgYmFyIHdpZHRoCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiQ29tcGxldGUgTG9zcyAoMHgpIiA9ICIjZmRhZTYxIiwgICMgUmVkIGZvciBsb3NzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTG9zcyBvZiBPbmUgQ29weSAoMC41eCkiID0gIiMzMTM2OTUiLCAgIyBPcmFuZ2UgZm9yIHBhcnRpYWwgbG9zcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFkZGl0aW9uIG9mIE9uZSBDb3B5ICgxLjV4KSIgPSAicmVkIiwgICMgQmx1ZSBmb3IgZ2FpbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFkZGl0aW9uIG9mIFR3byBDb3BpZXMgKDJ4KSIgPSAiZGFya2dyZWVuIikpICsgICMgRGFyayBibHVlIGZvciBoaWdoZXIgZ2FpbgogIGxhYnModGl0bGUgPSAiU2lnbmlmaWNhbnQgQ05WcyBBZmZlY3RpbmcgPjkwJSBvZiBDZWxscyIsCiAgICAgICBzdWJ0aXRsZSA9ICJDaHJvbW9zb21hbCBCYW5kcyB3aXRoIENOVnMgaW4gPjkwJSBvZiBDZWxscyIsCiAgICAgICB4ID0gIlBlcmNlbnRhZ2Ugb2YgQ2VsbHMgKCUpIiwKICAgICAgIHkgPSAiQ2hyb21vc29tYWwgQmFuZCIsCiAgICAgICBmaWxsID0gIkNOViBUeXBlIikgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsgICMgQWRqdXN0IHRleHQgc2l6ZSBmb3IgcmVhZGFiaWxpdHkKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxOCwgZmFjZSA9ICJib2xkIiksICAjIENlbnRlciB0aGUgdGl0bGUKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTkwIiksICAjIEFkZCBncmlkbGluZXMKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUmVtb3ZlIG1pbm9yIGdyaWRsaW5lcwogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsICAjIFBvc2l0aW9uIGxlZ2VuZCBhdCB0aGUgdG9wCiAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuOCwgImNtIikKICApIAoKYGBgCgojIEw3LgpgYGB7ciBkYXRhMTQsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQojIExvYWQgcmVxdWlyZWQgbGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShyZWFkcikKCiMgUmVhZCB0aGUgdXBkYXRlZCBpbmZlckNOViByZXN1bHRzIHdpdGggY2hyX2JhbmQgY29sdW1uCmluZmVyY252X2ZpbGUgPC0gIkw3X2N5dG9nZW5ldGljcy9MN19pbmZlcmNudl93aXRoX2Nocl9iYW5kcy5jc3YiCmluZmVyY252X2RhdGEgPC0gcmVhZC5jc3YoaW5mZXJjbnZfZmlsZSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBUb3RhbCBudW1iZXIgb2YgdW5pcXVlIGNlbGwgZ3JvdXBzCnRvdGFsX2NlbGxzIDwtIGxlbmd0aCh1bmlxdWUoaW5mZXJjbnZfZGF0YSRjZWxsX2dyb3VwX25hbWUpKQoKIyBBbmFseXplIENOViBmb3IgYWxsIGJhbmRzCmNudl9zdW1tYXJ5IDwtIGluZmVyY252X2RhdGEgJT4lCiAgZ3JvdXBfYnkoY2hyX2JhbmQsIHN0YXRlKSAlPiUKICBzdW1tYXJpemUodW5pcXVlX2NlbGxzID0gbl9kaXN0aW5jdChjZWxsX2dyb3VwX25hbWUpLCAuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUKICBtdXRhdGUoCiAgICBwZXJjZW50YWdlID0gKHVuaXF1ZV9jZWxscyAvIHRvdGFsX2NlbGxzKSAqIDEwMCwKICAgIGNudl90eXBlID0gY2FzZV93aGVuKAogICAgICBzdGF0ZSA9PSAxIH4gIkNvbXBsZXRlIExvc3MgKDB4KSIsCiAgICAgIHN0YXRlID09IDIgfiAiTG9zcyBvZiBPbmUgQ29weSAoMC41eCkiLAogICAgICBzdGF0ZSA9PSAzIH4gIk5ldXRyYWwgKDF4KSIsCiAgICAgIHN0YXRlID09IDQgfiAiQWRkaXRpb24gb2YgT25lIENvcHkgKDEuNXgpIiwKICAgICAgc3RhdGUgPT0gNSB+ICJBZGRpdGlvbiBvZiBUd28gQ29waWVzICgyeCkiLAogICAgICBzdGF0ZSA9PSA2IH4gIlBsYWNlaG9sZGVyIGZvciA+MnggQ29waWVzICgzeCkiLAogICAgICBUUlVFIH4gIlVua25vd24iCiAgICApCiAgKQoKIyBGaWx0ZXIgZm9yIENOVnMgYWZmZWN0aW5nIG1vcmUgdGhhbiAxMCUgb2YgY2VsbHMgKGZvciBhbGwgc3RhdGVzKQpzaWduaWZpY2FudF9jbnZfc3VtbWFyeSA8LSBjbnZfc3VtbWFyeSAlPiUKICBmaWx0ZXIocGVyY2VudGFnZSA+IDkwKSAlPiUKICBzZWxlY3QoY2hyX2JhbmQsIHN0YXRlLCB1bmlxdWVfY2VsbHMsIHBlcmNlbnRhZ2UsIGNudl90eXBlKQoKIyBTYXZlIHRoZSBmaWx0ZXJlZCBnYWluL2xvc3Mgc3VtbWFyeSB0byBhIENTViBmaWxlCm91dHB1dF9maWxlIDwtICJMN19jeXRvZ2VuZXRpY3Mvc2lnbmlmaWNhbnRfZ2Fpbl9sb3NzX3N1bW1hcnlfOTAuY3N2Igp3cml0ZS5jc3Yoc2lnbmlmaWNhbnRfY252X3N1bW1hcnksIG91dHB1dF9maWxlLCByb3cubmFtZXMgPSBGQUxTRSkKCiMgUHJpbnQgY29uZmlybWF0aW9uIG1lc3NhZ2UKY2F0KCJTaWduaWZpY2FudCBHYWluL0xvc3Mgc3VtbWFyeSB3aXRoID45MCUgYWZmZWN0ZWQgY2VsbHMgc2F2ZWQgdG8iLCBvdXRwdXRfZmlsZSwgIlxuIikKCiMgUHVibGljYXRpb24tcXVhbGl0eSBwbG90IHdpdGggcGVyY2VudGFnZSBvZiBjZWxscyBvbiBYLWF4aXMgYW5kIGNocm9tb3NvbWFsIGJhbmRzIG9uIFktYXhpcwpnZ3Bsb3Qoc2lnbmlmaWNhbnRfY252X3N1bW1hcnksIGFlcyh4ID0gcGVyY2VudGFnZSwgeSA9IHJlb3JkZXIoY2hyX2JhbmQsIHBlcmNlbnRhZ2UpLCBmaWxsID0gY252X3R5cGUpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgd2lkdGggPSAwLjgpICsgICMgQWRqdXN0ZWQgYmFyIHdpZHRoCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiQ29tcGxldGUgTG9zcyAoMHgpIiA9ICIjZmRhZTYxIiwgICMgUmVkIGZvciBsb3NzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTG9zcyBvZiBPbmUgQ29weSAoMC41eCkiID0gIiMzMTM2OTUiLCAgIyBPcmFuZ2UgZm9yIHBhcnRpYWwgbG9zcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFkZGl0aW9uIG9mIE9uZSBDb3B5ICgxLjV4KSIgPSAicmVkIiwgICMgQmx1ZSBmb3IgZ2FpbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFkZGl0aW9uIG9mIFR3byBDb3BpZXMgKDJ4KSIgPSAiZGFya2dyZWVuIikpICsgICMgRGFyayBibHVlIGZvciBoaWdoZXIgZ2FpbgogIGxhYnModGl0bGUgPSAiU2lnbmlmaWNhbnQgQ05WcyBBZmZlY3RpbmcgPjkwJSBvZiBDZWxscyIsCiAgICAgICBzdWJ0aXRsZSA9ICJDaHJvbW9zb21hbCBCYW5kcyB3aXRoIENOVnMgaW4gPjkwJSBvZiBDZWxscyIsCiAgICAgICB4ID0gIlBlcmNlbnRhZ2Ugb2YgQ2VsbHMgKCUpIiwKICAgICAgIHkgPSAiQ2hyb21vc29tYWwgQmFuZCIsCiAgICAgICBmaWxsID0gIkNOViBUeXBlIikgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsgICMgQWRqdXN0IHRleHQgc2l6ZSBmb3IgcmVhZGFiaWxpdHkKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxOCwgZmFjZSA9ICJib2xkIiksICAjIENlbnRlciB0aGUgdGl0bGUKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTkwIiksICAjIEFkZCBncmlkbGluZXMKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUmVtb3ZlIG1pbm9yIGdyaWRsaW5lcwogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsICAjIFBvc2l0aW9uIGxlZ2VuZCBhdCB0aGUgdG9wCiAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuOCwgImNtIikKICApIAoKYGBgCgojIEwxPDglJj4xMC4KYGBge3IgZGF0YTE1LCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KIyBMb2FkIHJlcXVpcmVkIGxpYnJhcmllcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocmVhZHIpCgojIFJlYWQgdGhlIHVwZGF0ZWQgaW5mZXJDTlYgcmVzdWx0cyB3aXRoIGNocl9iYW5kIGNvbHVtbgppbmZlcmNudl9maWxlIDwtICJMMV9jeXRvZ2VuZXRpY3MvTDFfaW5mZXJjbnZfd2l0aF9jaHJfYmFuZHMuY3N2IgppbmZlcmNudl9kYXRhIDwtIHJlYWQuY3N2KGluZmVyY252X2ZpbGUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCiMgVG90YWwgbnVtYmVyIG9mIHVuaXF1ZSBjZWxsIGdyb3Vwcwp0b3RhbF9jZWxscyA8LSBsZW5ndGgodW5pcXVlKGluZmVyY252X2RhdGEkY2VsbF9ncm91cF9uYW1lKSkKCiMgQW5hbHl6ZSBDTlYgZm9yIGFsbCBiYW5kcwpjbnZfc3VtbWFyeSA8LSBpbmZlcmNudl9kYXRhICU+JQogIGdyb3VwX2J5KGNocl9iYW5kLCBzdGF0ZSkgJT4lCiAgc3VtbWFyaXplKHVuaXF1ZV9jZWxscyA9IG5fZGlzdGluY3QoY2VsbF9ncm91cF9uYW1lKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lCiAgbXV0YXRlKAogICAgcGVyY2VudGFnZSA9ICh1bmlxdWVfY2VsbHMgLyB0b3RhbF9jZWxscykgKiAxMDAsCiAgICBjbnZfdHlwZSA9IGNhc2Vfd2hlbigKICAgICAgc3RhdGUgPT0gMSB+ICJDb21wbGV0ZSBMb3NzICgweCkiLAogICAgICBzdGF0ZSA9PSAyIH4gIkxvc3Mgb2YgT25lIENvcHkgKDAuNXgpIiwKICAgICAgc3RhdGUgPT0gMyB+ICJOZXV0cmFsICgxeCkiLAogICAgICBzdGF0ZSA9PSA0IH4gIkFkZGl0aW9uIG9mIE9uZSBDb3B5ICgxLjV4KSIsCiAgICAgIHN0YXRlID09IDUgfiAiQWRkaXRpb24gb2YgVHdvIENvcGllcyAoMngpIiwKICAgICAgc3RhdGUgPT0gNiB+ICJQbGFjZWhvbGRlciBmb3IgPjJ4IENvcGllcyAoM3gpIiwKICAgICAgVFJVRSB+ICJVbmtub3duIgogICAgKQogICkKCiMgRmlsdGVyIGZvciBDTlZzIGFmZmVjdGluZyBtb3JlIHRoYW4gMTAlIG9mIGNlbGxzIChmb3IgYWxsIHN0YXRlcykKc2lnbmlmaWNhbnRfY252X3N1bW1hcnkgPC0gY252X3N1bW1hcnkgJT4lCiAgZmlsdGVyKHBlcmNlbnRhZ2UgPjggICYgcGVyY2VudGFnZSA8MTApICU+JQogIHNlbGVjdChjaHJfYmFuZCwgc3RhdGUsIHVuaXF1ZV9jZWxscywgcGVyY2VudGFnZSwgY252X3R5cGUpCgojIFNhdmUgdGhlIGZpbHRlcmVkIGdhaW4vbG9zcyBzdW1tYXJ5IHRvIGEgQ1NWIGZpbGUKb3V0cHV0X2ZpbGUgPC0gIkwxX2N5dG9nZW5ldGljcy9zaWduaWZpY2FudF9nYWluX2xvc3Nfc3VtbWFyeV9sZXNzX3RoYW5fNSUuY3N2Igp3cml0ZS5jc3Yoc2lnbmlmaWNhbnRfY252X3N1bW1hcnksIG91dHB1dF9maWxlLCByb3cubmFtZXMgPSBGQUxTRSkKCiMgUHJpbnQgY29uZmlybWF0aW9uIG1lc3NhZ2UKY2F0KCJTaWduaWZpY2FudCBHYWluL0xvc3Mgc3VtbWFyeSB3aXRoIDw1JSBhZmZlY3RlZCBjZWxscyBzYXZlZCB0byIsIG91dHB1dF9maWxlLCAiXG4iKQoKIyBQdWJsaWNhdGlvbi1xdWFsaXR5IHBsb3Qgd2l0aCBwZXJjZW50YWdlIG9mIGNlbGxzIG9uIFgtYXhpcyBhbmQgY2hyb21vc29tYWwgYmFuZHMgb24gWS1heGlzCmdncGxvdChzaWduaWZpY2FudF9jbnZfc3VtbWFyeSwgYWVzKHggPSBwZXJjZW50YWdlLCB5ID0gcmVvcmRlcihjaHJfYmFuZCwgcGVyY2VudGFnZSksIGZpbGwgPSBjbnZfdHlwZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCB3aWR0aCA9IDAuOCkgKyAgIyBBZGp1c3RlZCBiYXIgd2lkdGgKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJDb21wbGV0ZSBMb3NzICgweCkiID0gIiNmZGFlNjEiLCAgIyBSZWQgZm9yIGxvc3MKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMb3NzIG9mIE9uZSBDb3B5ICgwLjV4KSIgPSAiIzMxMzY5NSIsICAjIE9yYW5nZSBmb3IgcGFydGlhbCBsb3NzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWRkaXRpb24gb2YgT25lIENvcHkgKDEuNXgpIiA9ICJyZWQiLCAgIyBCbHVlIGZvciBnYWluCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWRkaXRpb24gb2YgVHdvIENvcGllcyAoMngpIiA9ICJkYXJrZ3JlZW4iKSkgKyAgIyBEYXJrIGJsdWUgZm9yIGhpZ2hlciBnYWluCiAgbGFicyh0aXRsZSA9ICJTaWduaWZpY2FudCBDTlZzIEFmZmVjdGluZyA8NSUgb2YgQ2VsbHMiLAogICAgICAgc3VidGl0bGUgPSAiQ2hyb21vc29tYWwgQmFuZHMgd2l0aCBDTlZzIGluIDw1JSBvZiBDZWxscyIsCiAgICAgICB4ID0gIlBlcmNlbnRhZ2Ugb2YgQ2VsbHMgKCUpIiwKICAgICAgIHkgPSAiQ2hyb21vc29tYWwgQmFuZCIsCiAgICAgICBmaWxsID0gIkNOViBUeXBlIikgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsgICMgQWRqdXN0IHRleHQgc2l6ZSBmb3IgcmVhZGFiaWxpdHkKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxOCwgZmFjZSA9ICJib2xkIiksICAjIENlbnRlciB0aGUgdGl0bGUKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSAxNCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTkwIiksICAjIEFkZCBncmlkbGluZXMKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwgICMgUmVtb3ZlIG1pbm9yIGdyaWRsaW5lcwogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsICAjIFBvc2l0aW9uIGxlZ2VuZCBhdCB0aGUgdG9wCiAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuOCwgImNtIikKICApIAoKYGBg