untill here all the analysis done on the server according to Tzippy pipeline based on “Moving Pictures” tutorial from QIIME2 site. The pipeline run with run-analysys.sh at 172.35.15.214/pita/users/rotem/firsttry. The data copied and unzipped to the data directory.

#' extract qiime files by a specific file extension
#'
#' @param filepath Path of the qza/v file to be extract
#' @param extension File extension to unzipped from filepath. format \code{'*csv'}.
#' @return Extracted files with \code{extension} in the qiime \code{filepath} file.
#' @examples
#' extract.qiime("path\to\qiime\file\qzv", extension = "*csv")
extract.qiime = function (filepath, extension) {
  library(tools)
  library(filesstrings)
  shortname = file_path_sans_ext(filepath)
  tozip = unzip(filepath, exdir = "data", list = T)[,1]
  unzip(  filepath
        , exdir = "data/"
        , files = tozip[grepl(pattern = extension, tozip)]
        , overwrite = T)
  
  dir.create(shortname)
  unzipped = list.files(  pattern = extension
                        , full.names = T
                        , recursive = T
                        , include.dirs = T)
  
  
  file.move(files = unzipped, destinations = shortname, overwrite = TRUE)
  system("find . -type d -empty -delete")
}

#' Return last taxa names for specific SV
#'
#' @param SV The requested SV.
#' @param taxonomy_table taxonomy table with KPCOFGS order, with confidence level at last column and SV at the first, taxa levels unknown should be empty.
#' @param depth Optional, the depth of the taxonomical level to be returned.
#' @return The last [depth=2] non empty taxonomical values for specific SV expect of specie level.
#' @examples
#' get.last.name(SV = "AAAAAAAAAA", taxonomy_table, depth =2)
get.last.name = function(SV, taxonomy_table, depth = 2) {
  taxonomy_levels = c("kingdom", "phylum","class","order"
                      ,"family", "genus", "specie")
  taxonomy_table = taxonomy_table[,c("feature", taxonomy_levels)]
  specific = taxonomy_table[taxonomy_table[,1] == SV,]
  specific = specific[specific != ""]
  specific = specific[specific != " "]
  specific = specific[!is.na(specific)]
  specific = specific[nchar(specific) > 4]
  rev(specific)[1:depth]
  
  paste(rev(rev(specific)[1:depth]), collapse = " ")
}
library(tidyverse)
extract.qiime(filepath = "data/taxa-bar-plots.qzv", extension = "*csv")
'data/taxa-bar-plots' already exists7 files moved. 7 failed.
extract.qiime("data/taxa-bar-plots.qzv", "*tsv")
'data/taxa-bar-plots' already exists4 files moved. 0 failed.
source("../scripts/add_sig_asterix_boxplot_funcs.R")

level2 = read.csv("data/taxa-bar-plots/level-2.csv")

datm = level2 %>% 
  select(index, Type, Diet, Antibiotics, contains("k__"))# %>% 
  #gather(Group, value = number,-index,  -Type, -Diet, -Antibiotics) %>% 
  #group_by(index, Group) %>% summarize(RA = number / sum(number))
  #group_by(Type, Group) %>% summarise(median = median(value)) %>% 
  
  RAtable = datm %>% select(index, Type, Diet, Antibiotics) %>% 
    bind_cols(prop.table(datm %>%
                           select(contains("k__")) %>% 
                           as.matrix(), 1)  %>%
                as.data.frame()) %>% 
    gather(Group, value = frequency, -index,  -Type, -Diet, -Antibiotics)
#RAtable$Type = factor(medianRA$Type, levels =c("Control", "Fructose", "Control_AB",  "Fructose_AB") )
  

    medianRA = RAtable %>% 
             group_by(Type, Group) %>% 
             summarise(median = median(frequency))
  medianRA$Type = factor(medianRA$Type, levels =c("Control", "Fructose", "Control_AB",  "Fructose_AB") )
  ggplot() + 
    geom_bar(data = medianRA
           , aes(y = median, x = Type, fill = Group)
           , stat = "identity", position="fill") + 
  theme_classic()

levels(RAtable$Antibiotics) = c("No Antibiotics", "Antibiotics")
proteo = RAtable %>% filter(Group ==  "k__Bacteria.p__Proteobacteria")
source("../scripts/asteriks.R")

pp = ggplot() + 
geom_boxplot(data = proteo, aes(x = Antibiotics, fill = Diet, y = frequency)) 
boxplot_2_vars_grouped_add_asterix(pp, proteo, "Antibiotics", "frequency", "Diet"
                                   , test = "wilcox", fdr = 1) +
  theme_classic() + 
  ylab("Proteobacteria RA") + 
  xlab("")


proteo_noAB = proteo %>% filter(Antibiotics == "No Antibiotics")
pp = ggplot() + 
geom_boxplot(data = proteo_noAB, aes(x = Diet, fill = Diet, y = frequency)) 
pp = add_significant_asterix_to_plot_bothType(pp
                                              , proteo_noAB$Diet
                                              , proteo_noAB$frequency
                                              , test_type = "wilcox")
pp[[1]] +   
  theme_classic() + 
  ylab("Proteobacteria RA") + 
  xlab("")

Bacteroidetes = RAtable %>% filter(Group ==  "k__Bacteria.p__Bacteroidetes")
pp = ggplot() + 
geom_boxplot(data = Bacteroidetes, aes(  x = Antibiotics 
                                       , fill = Diet
                                       , y = frequency)) 
boxplot_2_vars_grouped_add_asterix(pp, Bacteroidetes, "Antibiotics"
                                   , "frequency", "Diet" , test = "wilcox", fdr = 1) +
  theme_classic() + 
  ylab("Bacteroidetes RA") + 
  xlab("")


Bacteroidetes_noAB = Bacteroidetes %>% filter(Antibiotics == "No Antibiotics")
pp = ggplot() + 
geom_boxplot(data = Bacteroidetes_noAB, aes(x = Diet, fill = Diet, y = frequency)) 
pp = add_significant_asterix_to_plot_bothType(pp
                                              , Bacteroidetes_noAB$Diet
                                              , Bacteroidetes_noAB$frequency
                                              , test_type = "wilcox")
pp[[1]] +   
  theme_classic() + 
  ylab("Bacteroidetes RA") + 
  xlab("")

Firmicutes = RAtable %>% filter(Group ==  "k__Bacteria.p__Firmicutes")
pp = ggplot() + 
geom_boxplot(data = Firmicutes, aes(x = Antibiotics, fill = Diet, y = frequency)) 
boxplot_2_vars_grouped_add_asterix(pp, Firmicutes, "Antibiotics", "frequency", "Diet"
                                   , test = "wilcox", fdr = 1) +
  theme_classic() + 
  ylab("Firmicutes RA") + 
  xlab("")


Firmicutes_noAB = Firmicutes %>% filter(Antibiotics == "No Antibiotics")
pp = ggplot() + 
geom_boxplot(data = Firmicutes_noAB, aes(x = Diet, fill = Diet, y = frequency)) 
pp = add_significant_asterix_to_plot_bothType(pp
                                              , Firmicutes_noAB$Diet
                                              , Firmicutes_noAB$frequency
                                              , test_type = "wilcox")
pp[[1]] +   
  theme_classic() + 
  ylab("Firmicutes RA") + 
  xlab("")

FirVsBac =  RAtable %>% filter(Group ==  "k__Bacteria.p__Firmicutes" |
                                 Group ==  "k__Bacteria.p__Bacteroidetes") %>% 
  spread(Group, frequency) %>% mutate(ratio = k__Bacteria.p__Firmicutes / k__Bacteria.p__Bacteroidetes)
pp = ggplot() + 
geom_boxplot(data = FirVsBac, aes(x = Antibiotics, fill = Diet, y = ratio)) 
boxplot_2_vars_grouped_add_asterix(pp, FirVsBac, "Antibiotics", "ratio", "Diet"
                                   , test = "wilcox", fdr = 1) +
  theme_classic() + 
  ylab("Firmicutes/Bacteroidetes RA") + 
  xlab("")


FirVsBac_noAB = FirVsBac %>% filter(Antibiotics == "No Antibiotics")
pp = ggplot() + 
geom_boxplot(data = FirVsBac_noAB, aes(x = Diet, fill = Diet, y = ratio)) 
pp = add_significant_asterix_to_plot_bothType(pp
                                              , FirVsBac_noAB$Diet
                                              , FirVsBac_noAB$ratio
                                              , test_type = "wilcox"
                                              )
pp[[1]] +   
  theme_classic() + 
  ylab("Firmicutes/Bacteroidetes RA") + 
  xlab("")

level6 = read.csv("data/taxa-bar-plots/level-6.csv")
maaslin2_input_noAB = level6 %>% 
    filter(Antibiotics == "No") %>%
    select(index, contains("k__"))
# names(level5)[60:70]
maaslin2_metadata_noAB = level6 %>%
    filter(Antibiotics == "No") %>%
    select(  index
           , Diet
           # , Weight
           )

names(maaslin2_input_noAB)[1] = "#"
names(maaslin2_metadata_noAB)[1] = "#"

write.table(  maaslin2_input_noAB
            , "data/maaslin2_input_noAB"
            , sep = "\t"
            , quote = T
            , row.names = F)
write.table(  maaslin2_metadata_noAB
            , "data/maaslin2_metadata_noAB"
            , sep = "\t"
            , quote = T
            , row.names = F)

Maaslin2::Maaslin2("data/maaslin2_input_noAB"
    , "data/maaslin2_metadata_noAB"
    , "output_maaslin_noAB_weight"
    # , random_effects = "Weight"
)
maaslin_results = read.table("output_maaslin_noAB_weight/significant_results.tsv"
                             , header = T)
# View(maaslin_results)
file.remove("data/maaslin2_input_noAB", "data/maaslin2_metadata_noAB")

Read biom table and make relative abundances table from it.

source("../scripts/extract.biom.table.R")
library(funrar)

extract.biom.table("/pita/users/rotem/firsttry/res/table.qza")

biom = read.table("/pita/users/rotem/firsttry/res/table.tsv"
                  , skip = 1, sep = "\t", comment.char = "",
                  header = T, stringsAsFactors=FALSE)

names(biom)[1] = "SampleID"
SVs = biom$SampleID

biom = data.frame(t(biom))
biom = biom[-1,]
colnames(biom) = SVs
biom = cbind("SampleID" = row.names(biom), biom)
biom[2:length(biom)] = lapply(biom[2:length(biom)]
                              , function(x) as.numeric(as.character(x)))

RAbiom = biom %>% select(-1) %>% 
  as.matrix() %>% make_relative() %>% 
  as.data.frame()

RAbiom = cbind("SampleID" = biom$SampleID, RAbiom)
source("../scripts/extract.biom.table.R")
library(funrar)

extract.biom.table("/pita/users/rotem/firsttry/res/table.qza")
error in running commandsh: 1: qiime: not found
sh: 1: biom: not found
error in running command
biom = read.table("/pita/users/rotem/firsttry/res/table.tsv"
                  , skip = 1, sep = "\t", comment.char = "",
                  header = T, stringsAsFactors=FALSE)

names(biom)[1] = "SampleID"
SVs = biom$SampleID

biom = data.frame(t(biom))
biom = biom[-1,]
colnames(biom) = SVs
biom = cbind("SampleID" = row.names(biom), biom)
biom[2:length(biom)] = lapply(biom[2:length(biom)]
                              , function(x) as.numeric(as.character(x)))

RAbiom = biom %>% select(-1) %>% 
  as.matrix() %>% make_relative() %>% 
  as.data.frame()

RAbiom = cbind("SampleID" = biom$SampleID, RAbiom)
write.table(  biom_table
            , "data/biom_table"
            , sep = "\t"
            , quote = T
            , row.names = F)


write.table(  mapping
            , "data/mapping"
            , sep = "\t"
            , quote = T
            , row.names = F)

Maaslin2::Maaslin2("data/biom_table"
    , "data/mapping"
    , "output_maaslin_SV_noAB"
    )
maaslin_results = read.table("output_maaslin_SV_noAB/all_results.tsv"
                            , header = T)
# mapping_file = read.table("../firsttry/res/map.csv", header = T)
mapping_file = read.table("/pita/users/rotem/firsttry/res/map.csv"
                          , header = T)
levels(mapping_file$Type) = c("Ctrl", "Ctrl+AB", "Fructose", "Fructose+AB")


biom_meta = left_join(RAbiom, mapping_file, by = "SampleID")

biom_table = 
  biom_meta %>% 
    filter(Antibiotics == "No") %>% 
    select(SampleID, matches("[ATGC]{10,}"))

mapping = mapping_file %>% 
  filter(Antibiotics == "No") %>% 
  select(SampleID, Diet)
taxonomy_levels = c("kingdom", "phylum","class","order"
                    ,"family", "genus", "specie")
pattern = "[kpcofgs]__"
extract.qiime("/pita/users/rotem/firsttry/res/taxonomy.qzv", "*tsv")
'/pita/users/rotem/firsttry/res/taxonomy' already exists11 files moved. 0 failed.
taxonomy = read.csv("/pita/users/rotem/firsttry/res/taxonomy/input.tsv"
                    , sep = "\t") %>% 
              separate(Taxon, sep =";", into = taxonomy_levels)
Expected 7 pieces. Missing pieces filled with `NA` in 120 rows [1, 6, 11, 29, 50, 53, 61, 79, 81, 93, 96, 98, 99, 108, 119, 121, 126, 136, 138, 142, ...].
# taxonomy = read.csv("../firsttry/res/taxonomy/input.tsv"
#                     , sep = "\t") %>% 
#               separate(Taxon, sep =";", into = taxonomy_levels)

taxonomy = taxonomy[-1,]


taxonomy = sapply(taxonomy, as.character)
taxonomy[is.na(taxonomy)] = ""
taxonomy = data.frame(taxonomy)

# taxonomy[,taxonomy_levels] = 
# as.data.frame(lapply(taxonomy %>% select(taxonomy_levels)
#                      , str_remove, pattern))
high_maaslin = 
  maaslin_results %>% 
    filter(qval < 0.05) %>%
    select(feature)

RAbiom_high_maaslin = 
  biom_meta %>% filter(Antibiotics == "No") %>% 
                select( high_maaslin %>%
                        unlist() %>%
                        as.character(), SampleID)

RAbiom_high_maaslin = 
  RAbiom_high_maaslin %>% 
  left_join(mapping_file %>% 
              select(SampleID, Diet, Antibiotics, Rat_Number)
                , by = "SampleID") %>% 
  filter(Antibiotics == "No")
  
melted_maaslin = 
  reshape2::melt(  RAbiom_high_maaslin
                 , id = c("SampleID", "Diet", "Antibiotics", "Rat_Number")
                 , variable.name = "feature"
                 , value.name = "RA")
# get taxa names
source("../scripts/get.last.name.R")
names(taxonomy)[1] = "feature"
taxa_names = 
  data.frame(  taxa = unlist(lapply(high_maaslin$feature
                                  , get.last.name, taxonomy))
             , feature = high_maaslin$feature)

melted_maaslin = left_join(melted_maaslin, taxa_names, by = "feature")
# Nice samples names
melted_maaslin = melted_maaslin %>% 
      mutate(code = paste(Diet, paste0("#",Rat_Number)))
# Normalize RA values (just in case)
melted_maaslin = 
  melted_maaslin %>% group_by(feature) %>% mutate(norm_RA = scale(RA))

melted_maaslin$feature = factor(melted_maaslin$feature)
biom_tableAB = 
  biom_meta %>% 
    filter(Antibiotics == "Yes") %>% 
    select(SampleID, matches("[ATGC]{10,}"))

mappingAB = mapping_file %>% 
  filter(Antibiotics == "Yes") %>% 
  select(SampleID, Diet)
write.table(  biom_tableAB
            , "data/biom_tableAB"
            , sep = "\t"
            , quote = T
            , row.names = F)

write.table(  mappingAB
            , "data/mappingAB"
            , sep = "\t"
            , quote = T
            , row.names = F)

Maaslin2::Maaslin2("data/biom_tableAB"
    , "data/mappingAB"
    , "output_maaslin_SV_AB"
    )
maaslin_resultsAB = read.table("output_maaslin_SV_AB/all_results.tsv"
                               , header = T)

names(maaslin_resultsAB)[9]
temp = maaslin_resultsAB[maaslin_resultsAB$qval < .1 & ! is.na(maaslin_resultsAB$qval),]$feature

# tempb = maaslin_resultsAB %>% filter(qval < .05) %>% select(feature) %>% unlist()
high_maaslinAB = 
maaslin_resultsAB %>% 
  filter(qval < 0.05) %>%
  select(feature) # %>%
  # unlist()

RAbiom_high_maaslinAB = 
  biom_meta %>% filter(Antibiotics == "Yes") %>% 
                select( high_maaslinAB %>%
                        unlist() %>%
                        as.character(), SampleID)

RAbiom_high_maaslinAB = 
  RAbiom_high_maaslinAB %>% 
  # rownames_to_column("SampleID") %>% 
  left_join(mapping_file %>% 
              select(SampleID, Diet, Antibiotics, Rat_Number)
                , by = "SampleID") 
  
melted_maaslinAB = 
  reshape2::melt(  RAbiom_high_maaslinAB
                 , id = c("SampleID", "Diet", "Antibiotics", "Rat_Number")
                 , variable.name = "feature"
                 , value.name = "RA")
# get taxa names
source("../scripts/get.last.name.R")
names(taxonomy)[1] = "feature"
taxa_namesAB = 
  data.frame(  taxa = unlist(lapply(high_maaslinAB$feature
                                  , get.last.name, taxonomy))
             , feature = high_maaslinAB$feature)
melted_maaslinAB = left_join(melted_maaslinAB, taxa_namesAB)
Joining, by = "feature"
# Nice samples names
melted_maaslinAB = melted_maaslinAB %>% 
      mutate(code = paste(Diet, paste0("#",Rat_Number)))
# Normalize RA values (just in case)
melted_maaslinAB = 
  melted_maaslinAB %>% group_by(feature) %>% mutate(norm_RA = scale(RA))

melted_maaslinAB$feature = factor(melted_maaslinAB$feature)

ggplot(melted_maaslinAB, aes(  x = code
                           , y = feature
                           , fill = log(RA+1e-11)
                           # , group = taxa
                           , group = Diet)) +
  geom_tile() +
  scale_fill_continuous(type = "viridis", name = "log(RA)") + 
  scale_y_discrete(labels = factor(melted_maaslinAB$taxa)[order(melted_maaslinAB$code)]) + 
  # scale_x_discrete(labels = factor(melted_maaslin$Diet)[order(melted_maaslin$code)]) +
  ggtitle("With Antibiotics") + 
  theme(  
    # axis.text.y = element_blank()
         axis.text.x = element_blank()
        , axis.title.x = element_blank()
       )

ggsave(filename = "maaslin_noAB.svg", height = 7, width = 5)  

unweighted_path = "/pita/users/rotem/firsttry/res/core-metrics-results/unweighted_unifrac_pcoa_results.qza"
extract.qiime(unweighted_path, "*txt")
1 file moved. 0 failed.
pcoa = read.table("/pita/users/rotem/firsttry/res/core-metrics-results/unweighted_unifrac_pcoa_results/ordination.txt"
                  , skip = 9, nrows = length(mapping_file$SampleID), row.names = 1)


var_explained = read.table("/pita/users/rotem/firsttry/res/core-metrics-results/unweighted_unifrac_pcoa_results/ordination.txt", skip = 4, nrows = 1)

pco1 = paste0("PCoA 1 (", round(var_explained[1,1]*100), "%)")
pco2 = paste0("PCoA 2 (", round(var_explained[1,2]*100), "%)")
pco3 = paste0("PCoA 3 (", round(var_explained[1,3]*100), "%)")
ggplot(melted_maaslin, aes(  x = code
                           , y = feature
                           , fill = log(RA+1e-11)
                           # , group = taxa
                           , group = Diet)) +
  geom_tile() +
  scale_fill_continuous(type = "viridis", name = "log(RA)") + 
  scale_y_discrete(labels = factor(melted_maaslin$taxa)[order(melted_maaslin$code)]) + 
  # scale_x_discrete(labels = factor(melted_maaslin$Diet)[order(melted_maaslin$code)]) +
  ggtitle("No Antibiotics") + 
  theme(  
    # axis.text.y = element_blank()
         axis.text.x = element_blank()
        , axis.title.x = element_blank()
       )


# ggsave(filename = "maaslin_noAB.svg", height = 7, width = 6)  
pcoa %>% 
  rownames_to_column("SampleID") %>%
  left_join(mapping_file, by = "SampleID") %>% 
  ggplot(aes(color = Type, x = V2, y = V3)) + 
  geom_point(size = 4) + 
  xlab(pco1) + 
  ylab(pco2) + 
  theme_classic()

pcoa %>% 
  rownames_to_column("SampleID") %>%
  left_join(mapping_file, by = "SampleID") %>% 
  ggplot(aes(color = Type, x = V2, y = V4)) + 
  geom_point(size = 4) + 
  xlab(pco1) + 
  ylab(pco3) + 
  theme_classic()

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQp1bnRpbGwgaGVyZSBhbGwgdGhlIGFuYWx5c2lzIGRvbmUgb24gdGhlIHNlcnZlciBhY2NvcmRpbmcgdG8gVHppcHB5IHBpcGVsaW5lIGJhc2VkIG9uICJNb3ZpbmcgUGljdHVyZXMiIHR1dG9yaWFsIGZyb20gW1FJSU1FMiBzaXRlXShodHRwczovL2RvY3MucWlpbWUyLm9yZy8yMDE5LjQvdHV0b3JpYWxzL21vdmluZy1waWN0dXJlcy8pLiBUaGUgcGlwZWxpbmUgcnVuIHdpdGggYHJ1bi1hbmFseXN5cy5zaGAgYXQgYDE3Mi4zNS4xNS4yMTQvcGl0YS91c2Vycy9yb3RlbS9maXJzdHRyeWAuClRoZSBkYXRhIGNvcGllZCBhbmQgdW56aXBwZWQgdG8gdGhlIGBkYXRhYCBkaXJlY3RvcnkuCmBgYHtiYXNoLCBpbmNsdWRlID0gRkFMU0V9CiMuLi9taW5pY29uZGEzL2Jpbi9jb25kYSBpbml0CgojLi4vbWluaWNvbmRhMy9iaW4vY29uZGEgYWN0aXZhdGUgcWlpbWUyLTIwMTkuNAoKYGBgCgpgYGB7ciBmdW5jdGlvbnN9CiMnIGV4dHJhY3QgcWlpbWUgZmlsZXMgYnkgYSBzcGVjaWZpYyBmaWxlIGV4dGVuc2lvbgojJwojJyBAcGFyYW0gZmlsZXBhdGggUGF0aCBvZiB0aGUgcXphL3YgZmlsZSB0byBiZSBleHRyYWN0CiMnIEBwYXJhbSBleHRlbnNpb24gRmlsZSBleHRlbnNpb24gdG8gdW56aXBwZWQgZnJvbSBmaWxlcGF0aC4gZm9ybWF0IFxjb2RleycqY3N2J30uCiMnIEByZXR1cm4gRXh0cmFjdGVkIGZpbGVzIHdpdGggXGNvZGV7ZXh0ZW5zaW9ufSBpbiB0aGUgcWlpbWUgXGNvZGV7ZmlsZXBhdGh9IGZpbGUuCiMnIEBleGFtcGxlcwojJyBleHRyYWN0LnFpaW1lKCJwYXRoXHRvXHFpaW1lXGZpbGVccXp2IiwgZXh0ZW5zaW9uID0gIipjc3YiKQpleHRyYWN0LnFpaW1lID0gZnVuY3Rpb24gKGZpbGVwYXRoLCBleHRlbnNpb24pIHsKICBsaWJyYXJ5KHRvb2xzKQogIGxpYnJhcnkoZmlsZXNzdHJpbmdzKQogIHNob3J0bmFtZSA9IGZpbGVfcGF0aF9zYW5zX2V4dChmaWxlcGF0aCkKICB0b3ppcCA9IHVuemlwKGZpbGVwYXRoLCBleGRpciA9ICJkYXRhIiwgbGlzdCA9IFQpWywxXQogIHVuemlwKCAgZmlsZXBhdGgKICAgICAgICAsIGV4ZGlyID0gImRhdGEvIgogICAgICAgICwgZmlsZXMgPSB0b3ppcFtncmVwbChwYXR0ZXJuID0gZXh0ZW5zaW9uLCB0b3ppcCldCiAgICAgICAgLCBvdmVyd3JpdGUgPSBUKQogIAogIGRpci5jcmVhdGUoc2hvcnRuYW1lKQogIHVuemlwcGVkID0gbGlzdC5maWxlcyggIHBhdHRlcm4gPSBleHRlbnNpb24KICAgICAgICAgICAgICAgICAgICAgICAgLCBmdWxsLm5hbWVzID0gVAogICAgICAgICAgICAgICAgICAgICAgICAsIHJlY3Vyc2l2ZSA9IFQKICAgICAgICAgICAgICAgICAgICAgICAgLCBpbmNsdWRlLmRpcnMgPSBUKQogIAogIAogIGZpbGUubW92ZShmaWxlcyA9IHVuemlwcGVkLCBkZXN0aW5hdGlvbnMgPSBzaG9ydG5hbWUsIG92ZXJ3cml0ZSA9IFRSVUUpCiAgc3lzdGVtKCJmaW5kIC4gLXR5cGUgZCAtZW1wdHkgLWRlbGV0ZSIpCn0KCiMnIFJldHVybiBsYXN0IHRheGEgbmFtZXMgZm9yIHNwZWNpZmljIFNWCiMnCiMnIEBwYXJhbSBTViBUaGUgcmVxdWVzdGVkIFNWLgojJyBAcGFyYW0gdGF4b25vbXlfdGFibGUgdGF4b25vbXkgdGFibGUgd2l0aCBLUENPRkdTIG9yZGVyLCB3aXRoIGNvbmZpZGVuY2UgbGV2ZWwgYXQgbGFzdCBjb2x1bW4gYW5kIFNWIGF0IHRoZSBmaXJzdCwgdGF4YSBsZXZlbHMgdW5rbm93biBzaG91bGQgYmUgZW1wdHkuCiMnIEBwYXJhbSBkZXB0aCBPcHRpb25hbCwgdGhlIGRlcHRoIG9mIHRoZSB0YXhvbm9taWNhbCBsZXZlbCB0byBiZSByZXR1cm5lZC4KIycgQHJldHVybiBUaGUgbGFzdCBbZGVwdGg9Ml0gbm9uIGVtcHR5IHRheG9ub21pY2FsIHZhbHVlcyBmb3Igc3BlY2lmaWMgU1YgZXhwZWN0IG9mIHNwZWNpZSBsZXZlbC4KIycgQGV4YW1wbGVzCiMnIGdldC5sYXN0Lm5hbWUoU1YgPSAiQUFBQUFBQUFBQSIsIHRheG9ub215X3RhYmxlLCBkZXB0aCA9MikKZ2V0Lmxhc3QubmFtZSA9IGZ1bmN0aW9uKFNWLCB0YXhvbm9teV90YWJsZSwgZGVwdGggPSAyKSB7CiAgdGF4b25vbXlfbGV2ZWxzID0gYygia2luZ2RvbSIsICJwaHlsdW0iLCJjbGFzcyIsIm9yZGVyIgogICAgICAgICAgICAgICAgICAgICAgLCJmYW1pbHkiLCAiZ2VudXMiLCAic3BlY2llIikKICB0YXhvbm9teV90YWJsZSA9IHRheG9ub215X3RhYmxlWyxjKCJmZWF0dXJlIiwgdGF4b25vbXlfbGV2ZWxzKV0KICBzcGVjaWZpYyA9IHRheG9ub215X3RhYmxlW3RheG9ub215X3RhYmxlWywxXSA9PSBTVixdCiAgc3BlY2lmaWMgPSBzcGVjaWZpY1tzcGVjaWZpYyAhPSAiIl0KICBzcGVjaWZpYyA9IHNwZWNpZmljW3NwZWNpZmljICE9ICIgIl0KICBzcGVjaWZpYyA9IHNwZWNpZmljWyFpcy5uYShzcGVjaWZpYyldCiAgc3BlY2lmaWMgPSBzcGVjaWZpY1tuY2hhcihzcGVjaWZpYykgPiA0XQogIHJldihzcGVjaWZpYylbMTpkZXB0aF0KICAKICBwYXN0ZShyZXYocmV2KHNwZWNpZmljKVsxOmRlcHRoXSksIGNvbGxhcHNlID0gIiAiKQp9CgpgYGAKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKZXh0cmFjdC5xaWltZShmaWxlcGF0aCA9ICJkYXRhL3RheGEtYmFyLXBsb3RzLnF6diIsIGV4dGVuc2lvbiA9ICIqY3N2IikKZXh0cmFjdC5xaWltZSgiZGF0YS90YXhhLWJhci1wbG90cy5xenYiLCAiKnRzdiIpCgpgYGAKCmBgYHtyLCBpbmNsdWRlID0gRkFMU0V9CmxldmVsMyA9IHJlYWQuY3N2KCJkYXRhL3RheGEtYmFyLXBsb3RzL2xldmVsLTMuY3N2IikKCmRhdG0gPSBsZXZlbDMgJT4lIAogIHNlbGVjdChUeXBlLCBjb250YWlucygia19fIikpICU+JSAKICBnYXRoZXIoR3JvdXAsICJ2YWx1ZSIsIC1UeXBlKSAlPiUgCiAgZ3JvdXBfYnkoVHlwZSwgR3JvdXApICU+JSBzdW1tYXJpc2UobWVkaWFuID0gbWVkaWFuKHZhbHVlKSkKCmdncGxvdChkYXRtLCBhZXMoeCA9IFR5cGUsIHkgPSBtZWRpYW4sIGZpbGwgPSBHcm91cCkpICsgCiAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIixzdGF0ID0gImlkZW50aXR5IikgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSkgKwogICAgdGhlbWVfY2xhc3NpYygpCiAgCmBgYAoKYGBge3J9CnNvdXJjZSgiLi4vc2NyaXB0cy9hZGRfc2lnX2FzdGVyaXhfYm94cGxvdF9mdW5jcy5SIikKCmxldmVsMiA9IHJlYWQuY3N2KCJkYXRhL3RheGEtYmFyLXBsb3RzL2xldmVsLTIuY3N2IikKCmRhdG0gPSBsZXZlbDIgJT4lIAogIHNlbGVjdChpbmRleCwgVHlwZSwgRGlldCwgQW50aWJpb3RpY3MsIGNvbnRhaW5zKCJrX18iKSkjICU+JSAKICAjZ2F0aGVyKEdyb3VwLCB2YWx1ZSA9IG51bWJlciwtaW5kZXgsICAtVHlwZSwgLURpZXQsIC1BbnRpYmlvdGljcykgJT4lIAogICNncm91cF9ieShpbmRleCwgR3JvdXApICU+JSBzdW1tYXJpemUoUkEgPSBudW1iZXIgLyBzdW0obnVtYmVyKSkKICAjZ3JvdXBfYnkoVHlwZSwgR3JvdXApICU+JSBzdW1tYXJpc2UobWVkaWFuID0gbWVkaWFuKHZhbHVlKSkgJT4lIAogIAogIFJBdGFibGUgPSBkYXRtICU+JSBzZWxlY3QoaW5kZXgsIFR5cGUsIERpZXQsIEFudGliaW90aWNzKSAlPiUgCiAgICBiaW5kX2NvbHMocHJvcC50YWJsZShkYXRtICU+JQogICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3QoY29udGFpbnMoImtfXyIpKSAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm1hdHJpeCgpLCAxKSAgJT4lCiAgICAgICAgICAgICAgICBhcy5kYXRhLmZyYW1lKCkpICU+JSAKICAgIGdhdGhlcihHcm91cCwgdmFsdWUgPSBmcmVxdWVuY3ksIC1pbmRleCwgIC1UeXBlLCAtRGlldCwgLUFudGliaW90aWNzKQojUkF0YWJsZSRUeXBlID0gZmFjdG9yKG1lZGlhblJBJFR5cGUsIGxldmVscyA9YygiQ29udHJvbCIsICJGcnVjdG9zZSIsICJDb250cm9sX0FCIiwgICJGcnVjdG9zZV9BQiIpICkKICAKCiAgICBtZWRpYW5SQSA9IFJBdGFibGUgJT4lIAogICAgICAgICAgICAgZ3JvdXBfYnkoVHlwZSwgR3JvdXApICU+JSAKICAgICAgICAgICAgIHN1bW1hcmlzZShtZWRpYW4gPSBtZWRpYW4oZnJlcXVlbmN5KSkKICBtZWRpYW5SQSRUeXBlID0gZmFjdG9yKG1lZGlhblJBJFR5cGUsIGxldmVscyA9YygiQ29udHJvbCIsICJGcnVjdG9zZSIsICJDb250cm9sX0FCIiwgICJGcnVjdG9zZV9BQiIpICkKICBnZ3Bsb3QoKSArIAogICAgZ2VvbV9iYXIoZGF0YSA9IG1lZGlhblJBCiAgICAgICAgICAgLCBhZXMoeSA9IG1lZGlhbiwgeCA9IFR5cGUsIGZpbGwgPSBHcm91cCkKICAgICAgICAgICAsIHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbj0iZmlsbCIpICsgCiAgdGhlbWVfY2xhc3NpYygpCmBgYApgYGB7cn0KbGV2ZWxzKFJBdGFibGUkQW50aWJpb3RpY3MpID0gYygiTm8gQW50aWJpb3RpY3MiLCAiQW50aWJpb3RpY3MiKQpwcm90ZW8gPSBSQXRhYmxlICU+JSBmaWx0ZXIoR3JvdXAgPT0gICJrX19CYWN0ZXJpYS5wX19Qcm90ZW9iYWN0ZXJpYSIpCmBgYAoKYGBge3IsIGluY2x1ZGUgPSBGQUxTRX0KbGV2ZWxzKFJBdGFibGUkQW50aWJpb3RpY3MpID0gYygiTm8gQW50aWJpb3RpY3MiLCAiQW50aWJpb3RpY3MiKQpwcm90ZW8gPSBSQXRhYmxlICU+JSBmaWx0ZXIoR3JvdXAgPT0gICJrX19CYWN0ZXJpYS5wX19Qcm90ZW9iYWN0ZXJpYSIpCnAgPSBnZ3Bsb3QoKSArIAogIGdlb21fYm94cGxvdChkYXRhID0gcHJvdGVvLCBhZXMoZmlsbCA9IERpZXQsIHkgPSBmcmVxdWVuY3kpKSArIAogIHlsYWIoImFscGhhIGRpdmVyc2l0eSBmcmVxdWVuY3kiKSArCiAgZmFjZXRfd3JhcCggfiBBbnRpYmlvdGljcyArIERpZXQsIHN0cmlwLnBvc2l0aW9uPSJib3R0b20iLCBucm93ID0gMSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueCA9IGVsZW1lbnRfbGluZShzaXplID0gMCkpCgogIGFkZF9zaWduaWZpY2FudF9hc3Rlcml4X3RvX3Bsb3RfdjIocCwgUkF0YWJsZSREaWV0LCBSQXRhYmxlJGZyZXF1ZW5jeSkKCiMgICBnZ3Bsb3QoZGF0bSwgYWVzKHggPSBUeXBlLCB5ID0gUkEsIGZpbGwgPSBHcm91cCkpICsgCiMgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLHN0YXQgPSAiaWRlbnRpdHkiKSArCiMgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpICsgCiMgICAgIGdndGl0bGUoIlRheGEgTDIgYnkgVHlwZSBNZWRpYW4iKSsKIyAgICAgdGhlbWVfY2xhc3NpYygpCiMgCiMgCiMgCiMgZ2dwbG90KCkgKwojICAgZ2VvbV9ib3hwbG90KGRhdGEgPSBwcm90ZW8sIGFlcyh5ID0gUkEsIHggPSBUeXBlLCBmaWxsID0gVHlwZSkpCiMgCiMgcHJvdGVvID0gZGF0bSAlPiUgZmlsdGVyKEdyb3VwID09ICAia19fQmFjdGVyaWEucF9fUHJvdGVvYmFjdGVyaWEiKQojIGdncGxvdCgpICsKIyAgIGdlb21fYm94cGxvdChkYXRhID0gcHJvdGVvLCBhZXMoeSA9IFJBLCB4ID0gVHlwZSwgZmlsbCA9IFR5cGUpKQoKYGBgCgpgYGB7cn0Kc291cmNlKCIuLi9zY3JpcHRzL2FzdGVyaWtzLlIiKQoKcHAgPSBnZ3Bsb3QoKSArIApnZW9tX2JveHBsb3QoZGF0YSA9IHByb3RlbywgYWVzKHggPSBBbnRpYmlvdGljcywgZmlsbCA9IERpZXQsIHkgPSBmcmVxdWVuY3kpKSAKYm94cGxvdF8yX3ZhcnNfZ3JvdXBlZF9hZGRfYXN0ZXJpeChwcCwgcHJvdGVvLCAiQW50aWJpb3RpY3MiLCAiZnJlcXVlbmN5IiwgIkRpZXQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCB0ZXN0ID0gIndpbGNveCIsIGZkciA9IDEpICsKICB0aGVtZV9jbGFzc2ljKCkgKyAKICB5bGFiKCJQcm90ZW9iYWN0ZXJpYSBSQSIpICsgCiAgeGxhYigiIikKCnByb3Rlb19ub0FCID0gcHJvdGVvICU+JSBmaWx0ZXIoQW50aWJpb3RpY3MgPT0gIk5vIEFudGliaW90aWNzIikKcHAgPSBnZ3Bsb3QoKSArIApnZW9tX2JveHBsb3QoZGF0YSA9IHByb3Rlb19ub0FCLCBhZXMoeCA9IERpZXQsIGZpbGwgPSBEaWV0LCB5ID0gZnJlcXVlbmN5KSkgCnBwID0gYWRkX3NpZ25pZmljYW50X2FzdGVyaXhfdG9fcGxvdF9ib3RoVHlwZShwcAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBwcm90ZW9fbm9BQiREaWV0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIHByb3Rlb19ub0FCJGZyZXF1ZW5jeQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCB0ZXN0X3R5cGUgPSAid2lsY294IikKcHBbWzFdXSArICAgCiAgdGhlbWVfY2xhc3NpYygpICsgCiAgeWxhYigiUHJvdGVvYmFjdGVyaWEgUkEiKSArIAogIHhsYWIoIiIpCgpgYGAKCmBgYHtyfQpCYWN0ZXJvaWRldGVzID0gUkF0YWJsZSAlPiUgZmlsdGVyKEdyb3VwID09ICAia19fQmFjdGVyaWEucF9fQmFjdGVyb2lkZXRlcyIpCnBwID0gZ2dwbG90KCkgKyAKZ2VvbV9ib3hwbG90KGRhdGEgPSBCYWN0ZXJvaWRldGVzLCBhZXMoICB4ID0gQW50aWJpb3RpY3MgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgZmlsbCA9IERpZXQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCB5ID0gZnJlcXVlbmN5KSkgCmJveHBsb3RfMl92YXJzX2dyb3VwZWRfYWRkX2FzdGVyaXgocHAsIEJhY3Rlcm9pZGV0ZXMsICJBbnRpYmlvdGljcyIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsICJmcmVxdWVuY3kiLCAiRGlldCIgLCB0ZXN0ID0gIndpbGNveCIsIGZkciA9IDEpICsKICB0aGVtZV9jbGFzc2ljKCkgKyAKICB5bGFiKCJCYWN0ZXJvaWRldGVzIFJBIikgKyAKICB4bGFiKCIiKQoKQmFjdGVyb2lkZXRlc19ub0FCID0gQmFjdGVyb2lkZXRlcyAlPiUgZmlsdGVyKEFudGliaW90aWNzID09ICJObyBBbnRpYmlvdGljcyIpCnBwID0gZ2dwbG90KCkgKyAKZ2VvbV9ib3hwbG90KGRhdGEgPSBCYWN0ZXJvaWRldGVzX25vQUIsIGFlcyh4ID0gRGlldCwgZmlsbCA9IERpZXQsIHkgPSBmcmVxdWVuY3kpKSAKcHAgPSBhZGRfc2lnbmlmaWNhbnRfYXN0ZXJpeF90b19wbG90X2JvdGhUeXBlKHBwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEJhY3Rlcm9pZGV0ZXNfbm9BQiREaWV0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEJhY3Rlcm9pZGV0ZXNfbm9BQiRmcmVxdWVuY3kKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgdGVzdF90eXBlID0gIndpbGNveCIpCnBwW1sxXV0gKyAgIAogIHRoZW1lX2NsYXNzaWMoKSArIAogIHlsYWIoIkJhY3Rlcm9pZGV0ZXMgUkEiKSArIAogIHhsYWIoIiIpCgpgYGAKCmBgYHtyfQpGaXJtaWN1dGVzID0gUkF0YWJsZSAlPiUgZmlsdGVyKEdyb3VwID09ICAia19fQmFjdGVyaWEucF9fRmlybWljdXRlcyIpCnBwID0gZ2dwbG90KCkgKyAKZ2VvbV9ib3hwbG90KGRhdGEgPSBGaXJtaWN1dGVzLCBhZXMoeCA9IEFudGliaW90aWNzLCBmaWxsID0gRGlldCwgeSA9IGZyZXF1ZW5jeSkpIApib3hwbG90XzJfdmFyc19ncm91cGVkX2FkZF9hc3Rlcml4KHBwLCBGaXJtaWN1dGVzLCAiQW50aWJpb3RpY3MiLCAiZnJlcXVlbmN5IiwgIkRpZXQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCB0ZXN0ID0gIndpbGNveCIsIGZkciA9IDEpICsKICB0aGVtZV9jbGFzc2ljKCkgKyAKICB5bGFiKCJGaXJtaWN1dGVzIFJBIikgKyAKICB4bGFiKCIiKQoKRmlybWljdXRlc19ub0FCID0gRmlybWljdXRlcyAlPiUgZmlsdGVyKEFudGliaW90aWNzID09ICJObyBBbnRpYmlvdGljcyIpCnBwID0gZ2dwbG90KCkgKyAKZ2VvbV9ib3hwbG90KGRhdGEgPSBGaXJtaWN1dGVzX25vQUIsIGFlcyh4ID0gRGlldCwgZmlsbCA9IERpZXQsIHkgPSBmcmVxdWVuY3kpKSAKcHAgPSBhZGRfc2lnbmlmaWNhbnRfYXN0ZXJpeF90b19wbG90X2JvdGhUeXBlKHBwCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEZpcm1pY3V0ZXNfbm9BQiREaWV0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIEZpcm1pY3V0ZXNfbm9BQiRmcmVxdWVuY3kKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgdGVzdF90eXBlID0gIndpbGNveCIpCnBwW1sxXV0gKyAgIAogIHRoZW1lX2NsYXNzaWMoKSArIAogIHlsYWIoIkZpcm1pY3V0ZXMgUkEiKSArIAogIHhsYWIoIiIpCgpgYGAKYGBge3J9CkZpclZzQmFjID0gIFJBdGFibGUgJT4lIGZpbHRlcihHcm91cCA9PSAgImtfX0JhY3RlcmlhLnBfX0Zpcm1pY3V0ZXMiIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR3JvdXAgPT0gICJrX19CYWN0ZXJpYS5wX19CYWN0ZXJvaWRldGVzIikgJT4lIAogIHNwcmVhZChHcm91cCwgZnJlcXVlbmN5KSAlPiUgbXV0YXRlKHJhdGlvID0ga19fQmFjdGVyaWEucF9fRmlybWljdXRlcyAvIGtfX0JhY3RlcmlhLnBfX0JhY3Rlcm9pZGV0ZXMpCnBwID0gZ2dwbG90KCkgKyAKZ2VvbV9ib3hwbG90KGRhdGEgPSBGaXJWc0JhYywgYWVzKHggPSBBbnRpYmlvdGljcywgZmlsbCA9IERpZXQsIHkgPSByYXRpbykpIApib3hwbG90XzJfdmFyc19ncm91cGVkX2FkZF9hc3Rlcml4KHBwLCBGaXJWc0JhYywgIkFudGliaW90aWNzIiwgInJhdGlvIiwgIkRpZXQiCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCB0ZXN0ID0gIndpbGNveCIsIGZkciA9IDEpICsKICB0aGVtZV9jbGFzc2ljKCkgKyAKICB5bGFiKCJGaXJtaWN1dGVzL0JhY3Rlcm9pZGV0ZXMgUkEiKSArIAogIHhsYWIoIiIpCgpGaXJWc0JhY19ub0FCID0gRmlyVnNCYWMgJT4lIGZpbHRlcihBbnRpYmlvdGljcyA9PSAiTm8gQW50aWJpb3RpY3MiKQpwcCA9IGdncGxvdCgpICsgCmdlb21fYm94cGxvdChkYXRhID0gRmlyVnNCYWNfbm9BQiwgYWVzKHggPSBEaWV0LCBmaWxsID0gRGlldCwgeSA9IHJhdGlvKSkgCnBwID0gYWRkX3NpZ25pZmljYW50X2FzdGVyaXhfdG9fcGxvdF9ib3RoVHlwZShwcAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBGaXJWc0JhY19ub0FCJERpZXQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgRmlyVnNCYWNfbm9BQiRyYXRpbwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCB0ZXN0X3R5cGUgPSAid2lsY294IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQpwcFtbMV1dICsgICAKICB0aGVtZV9jbGFzc2ljKCkgKyAKICB5bGFiKCJGaXJtaWN1dGVzL0JhY3Rlcm9pZGV0ZXMgUkEiKSArIAogIHhsYWIoIiIpCgpgYGAKCmBgYHtyLCBpbmNsdWRlID0gRkFMU0V9CmxldmVsNyA9IHJlYWQuY3N2KCJkYXRhL3RheGEtYmFyLXBsb3RzL2xldmVsLTcuY3N2IikKZGF0bSA9IGxldmVsNyAlPiUgCiAgc2VsZWN0KFR5cGUsIGNvbnRhaW5zKCJrX18iKSkgJT4lIAogIGdhdGhlcihHcm91cCwgInZhbHVlIiwgLVR5cGUpICU+JSAKICBncm91cF9ieShUeXBlLCBHcm91cCkgJT4lIHN1bW1hcmlzZShtZWRpYW4gPSBtZWRpYW4odmFsdWUpKQoKZGF0bSAlPiUgZmlsdGVyKEdyb3VwID09ICJrX19CYWN0ZXJpYS5wX19Qcm90ZW9iYWN0ZXJpYSIpCgpkYXRtJEdyb3VwID0gbGV2ZWxzKGZhY3RvcihkYXRtJEdyb3VwKSkKZ2dwbG90KCkgKyBnZW9tX2JveHBsb3QoZGF0YSA9IGRhdG0sIGFlcyh4ID0gVHlwZSwgeSA9IG1lZGlhbiwgZmlsbCA9IFR5cGUpKSArIAogIHhsYWIoIiIpCiAKYGBgCgpgYGB7ciwgcmVzdWx0cyA9ICJoaWRlIn0KbGV2ZWw2ID0gcmVhZC5jc3YoImRhdGEvdGF4YS1iYXItcGxvdHMvbGV2ZWwtNi5jc3YiKQptYWFzbGluMl9pbnB1dF9ub0FCID0gbGV2ZWw2ICU+JSAKICAgIGZpbHRlcihBbnRpYmlvdGljcyA9PSAiTm8iKSAlPiUKICAgIHNlbGVjdChpbmRleCwgY29udGFpbnMoImtfXyIpKQojIG5hbWVzKGxldmVsNSlbNjA6NzBdCm1hYXNsaW4yX21ldGFkYXRhX25vQUIgPSBsZXZlbDYgJT4lCiAgICBmaWx0ZXIoQW50aWJpb3RpY3MgPT0gIk5vIikgJT4lCiAgICBzZWxlY3QoICBpbmRleAogICAgICAgICAgICwgRGlldAogICAgICAgICAgICMgLCBXZWlnaHQKICAgICAgICAgICApCgpuYW1lcyhtYWFzbGluMl9pbnB1dF9ub0FCKVsxXSA9ICIjIgpuYW1lcyhtYWFzbGluMl9tZXRhZGF0YV9ub0FCKVsxXSA9ICIjIgoKd3JpdGUudGFibGUoICBtYWFzbGluMl9pbnB1dF9ub0FCCiAgICAgICAgICAgICwgImRhdGEvbWFhc2xpbjJfaW5wdXRfbm9BQiIKICAgICAgICAgICAgLCBzZXAgPSAiXHQiCiAgICAgICAgICAgICwgcXVvdGUgPSBUCiAgICAgICAgICAgICwgcm93Lm5hbWVzID0gRikKd3JpdGUudGFibGUoICBtYWFzbGluMl9tZXRhZGF0YV9ub0FCCiAgICAgICAgICAgICwgImRhdGEvbWFhc2xpbjJfbWV0YWRhdGFfbm9BQiIKICAgICAgICAgICAgLCBzZXAgPSAiXHQiCiAgICAgICAgICAgICwgcXVvdGUgPSBUCiAgICAgICAgICAgICwgcm93Lm5hbWVzID0gRikKCk1hYXNsaW4yOjpNYWFzbGluMigiZGF0YS9tYWFzbGluMl9pbnB1dF9ub0FCIgogICAgLCAiZGF0YS9tYWFzbGluMl9tZXRhZGF0YV9ub0FCIgogICAgLCAib3V0cHV0X21hYXNsaW5fbm9BQl93ZWlnaHQiCiAgICAjICwgcmFuZG9tX2VmZmVjdHMgPSAiV2VpZ2h0IgopCgptYWFzbGluX3Jlc3VsdHMgPSByZWFkLnRhYmxlKCJvdXRwdXRfbWFhc2xpbl9ub0FCX3dlaWdodC9zaWduaWZpY2FudF9yZXN1bHRzLnRzdiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIGhlYWRlciA9IFQpCiMgVmlldyhtYWFzbGluX3Jlc3VsdHMpCmZpbGUucmVtb3ZlKCJkYXRhL21hYXNsaW4yX2lucHV0X25vQUIiLCAiZGF0YS9tYWFzbGluMl9tZXRhZGF0YV9ub0FCIikKYGBgClJlYWQgYmlvbSB0YWJsZSBhbmQgbWFrZSByZWxhdGl2ZSBhYnVuZGFuY2VzIHRhYmxlIGZyb20gaXQuCmBgYHtyLCBiaW9tLXRhYmxlfQpzb3VyY2UoIi4uL3NjcmlwdHMvZXh0cmFjdC5iaW9tLnRhYmxlLlIiKQpsaWJyYXJ5KGZ1bnJhcikKCmV4dHJhY3QuYmlvbS50YWJsZSgiL3BpdGEvdXNlcnMvcm90ZW0vZmlyc3R0cnkvcmVzL3RhYmxlLnF6YSIpCgpiaW9tID0gcmVhZC50YWJsZSgiL3BpdGEvdXNlcnMvcm90ZW0vZmlyc3R0cnkvcmVzL3RhYmxlLnRzdiIKICAgICAgICAgICAgICAgICAgLCBza2lwID0gMSwgc2VwID0gIlx0IiwgY29tbWVudC5jaGFyID0gIiIsCiAgICAgICAgICAgICAgICAgIGhlYWRlciA9IFQsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpuYW1lcyhiaW9tKVsxXSA9ICJTYW1wbGVJRCIKU1ZzID0gYmlvbSRTYW1wbGVJRAoKYmlvbSA9IGRhdGEuZnJhbWUodChiaW9tKSkKYmlvbSA9IGJpb21bLTEsXQpjb2xuYW1lcyhiaW9tKSA9IFNWcwpiaW9tID0gY2JpbmQoIlNhbXBsZUlEIiA9IHJvdy5uYW1lcyhiaW9tKSwgYmlvbSkKYmlvbVsyOmxlbmd0aChiaW9tKV0gPSBsYXBwbHkoYmlvbVsyOmxlbmd0aChiaW9tKV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBmdW5jdGlvbih4KSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih4KSkpCgpSQWJpb20gPSBiaW9tICU+JSBzZWxlY3QoLTEpICU+JSAKICBhcy5tYXRyaXgoKSAlPiUgbWFrZV9yZWxhdGl2ZSgpICU+JSAKICBhcy5kYXRhLmZyYW1lKCkKClJBYmlvbSA9IGNiaW5kKCJTYW1wbGVJRCIgPSBiaW9tJFNhbXBsZUlELCBSQWJpb20pCgoKYGBgCgpgYGB7cn0KIyBtYXBwaW5nX2ZpbGUgPSByZWFkLnRhYmxlKCIuLi9maXJzdHRyeS9yZXMvbWFwLmNzdiIsIGhlYWRlciA9IFQpCm1hcHBpbmdfZmlsZSA9IHJlYWQudGFibGUoIi9waXRhL3VzZXJzL3JvdGVtL2ZpcnN0dHJ5L3Jlcy9tYXAuY3N2IgogICAgICAgICAgICAgICAgICAgICAgICAgICwgaGVhZGVyID0gVCkKbGV2ZWxzKG1hcHBpbmdfZmlsZSRUeXBlKSA9IGMoIkN0cmwiLCAiQ3RybCtBQiIsICJGcnVjdG9zZSIsICJGcnVjdG9zZStBQiIpCgoKYmlvbV9tZXRhID0gbGVmdF9qb2luKFJBYmlvbSwgbWFwcGluZ19maWxlLCBieSA9ICJTYW1wbGVJRCIpCgpiaW9tX3RhYmxlID0gCiAgYmlvbV9tZXRhICU+JSAKICAgIGZpbHRlcihBbnRpYmlvdGljcyA9PSAiTm8iKSAlPiUgCiAgICBzZWxlY3QoU2FtcGxlSUQsIG1hdGNoZXMoIltBVEdDXXsxMCx9IikpCgptYXBwaW5nID0gbWFwcGluZ19maWxlICU+JSAKICBmaWx0ZXIoQW50aWJpb3RpY3MgPT0gIk5vIikgJT4lIAogIHNlbGVjdChTYW1wbGVJRCwgRGlldCkKYGBgCgpgYGB7ciBydW4tbWFhc2xpbiwgcmVzdWx0cyA9ICJoaWRlIiwgbWVzc2FnZSA9IEZ9CndyaXRlLnRhYmxlKCAgYmlvbV90YWJsZQogICAgICAgICAgICAsICJkYXRhL2Jpb21fdGFibGUiCiAgICAgICAgICAgICwgc2VwID0gIlx0IgogICAgICAgICAgICAsIHF1b3RlID0gVAogICAgICAgICAgICAsIHJvdy5uYW1lcyA9IEYpCgoKd3JpdGUudGFibGUoICBtYXBwaW5nCiAgICAgICAgICAgICwgImRhdGEvbWFwcGluZyIKICAgICAgICAgICAgLCBzZXAgPSAiXHQiCiAgICAgICAgICAgICwgcXVvdGUgPSBUCiAgICAgICAgICAgICwgcm93Lm5hbWVzID0gRikKCk1hYXNsaW4yOjpNYWFzbGluMigiZGF0YS9iaW9tX3RhYmxlIgogICAgLCAiZGF0YS9tYXBwaW5nIgogICAgLCAib3V0cHV0X21hYXNsaW5fU1Zfbm9BQiIKICAgICkKCm1hYXNsaW5fcmVzdWx0cyA9IHJlYWQudGFibGUoIm91dHB1dF9tYWFzbGluX1NWX25vQUIvYWxsX3Jlc3VsdHMudHN2IgogICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBoZWFkZXIgPSBUKQoKYGBgCgpgYGB7cn0KdGF4b25vbXlfbGV2ZWxzID0gYygia2luZ2RvbSIsICJwaHlsdW0iLCJjbGFzcyIsIm9yZGVyIgogICAgICAgICAgICAgICAgICAgICwiZmFtaWx5IiwgImdlbnVzIiwgInNwZWNpZSIpCnBhdHRlcm4gPSAiW2twY29mZ3NdX18iCmV4dHJhY3QucWlpbWUoIi9waXRhL3VzZXJzL3JvdGVtL2ZpcnN0dHJ5L3Jlcy90YXhvbm9teS5xenYiLCAiKnRzdiIpCnRheG9ub215ID0gcmVhZC5jc3YoIi9waXRhL3VzZXJzL3JvdGVtL2ZpcnN0dHJ5L3Jlcy90YXhvbm9teS9pbnB1dC50c3YiCiAgICAgICAgICAgICAgICAgICAgLCBzZXAgPSAiXHQiKSAlPiUgCiAgICAgICAgICAgICAgc2VwYXJhdGUoVGF4b24sIHNlcCA9IjsiLCBpbnRvID0gdGF4b25vbXlfbGV2ZWxzKQoKIyB0YXhvbm9teSA9IHJlYWQuY3N2KCIuLi9maXJzdHRyeS9yZXMvdGF4b25vbXkvaW5wdXQudHN2IgojICAgICAgICAgICAgICAgICAgICAgLCBzZXAgPSAiXHQiKSAlPiUgCiMgICAgICAgICAgICAgICBzZXBhcmF0ZShUYXhvbiwgc2VwID0iOyIsIGludG8gPSB0YXhvbm9teV9sZXZlbHMpCgp0YXhvbm9teSA9IHRheG9ub215Wy0xLF0KCgp0YXhvbm9teSA9IHNhcHBseSh0YXhvbm9teSwgYXMuY2hhcmFjdGVyKQp0YXhvbm9teVtpcy5uYSh0YXhvbm9teSldID0gIiIKdGF4b25vbXkgPSBkYXRhLmZyYW1lKHRheG9ub215KQoKIyB0YXhvbm9teVssdGF4b25vbXlfbGV2ZWxzXSA9IAojIGFzLmRhdGEuZnJhbWUobGFwcGx5KHRheG9ub215ICU+JSBzZWxlY3QodGF4b25vbXlfbGV2ZWxzKQojICAgICAgICAgICAgICAgICAgICAgICwgc3RyX3JlbW92ZSwgcGF0dGVybikpCgpgYGAKCmBgYHtyLCB3YXJuaW5nID0gRn0KaGlnaF9tYWFzbGluID0gCiAgbWFhc2xpbl9yZXN1bHRzICU+JSAKICAgIGZpbHRlcihxdmFsIDwgMC4wNSkgJT4lCiAgICBzZWxlY3QoZmVhdHVyZSkKClJBYmlvbV9oaWdoX21hYXNsaW4gPSAKICBiaW9tX21ldGEgJT4lIGZpbHRlcihBbnRpYmlvdGljcyA9PSAiTm8iKSAlPiUgCiAgICAgICAgICAgICAgICBzZWxlY3QoIGhpZ2hfbWFhc2xpbiAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgdW5saXN0KCkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIGFzLmNoYXJhY3RlcigpLCBTYW1wbGVJRCkKClJBYmlvbV9oaWdoX21hYXNsaW4gPSAKICBSQWJpb21faGlnaF9tYWFzbGluICU+JSAKICBsZWZ0X2pvaW4obWFwcGluZ19maWxlICU+JSAKICAgICAgICAgICAgICBzZWxlY3QoU2FtcGxlSUQsIERpZXQsIEFudGliaW90aWNzLCBSYXRfTnVtYmVyKQogICAgICAgICAgICAgICAgLCBieSA9ICJTYW1wbGVJRCIpICU+JSAKICBmaWx0ZXIoQW50aWJpb3RpY3MgPT0gIk5vIikKICAKbWVsdGVkX21hYXNsaW4gPSAKICByZXNoYXBlMjo6bWVsdCggIFJBYmlvbV9oaWdoX21hYXNsaW4KICAgICAgICAgICAgICAgICAsIGlkID0gYygiU2FtcGxlSUQiLCAiRGlldCIsICJBbnRpYmlvdGljcyIsICJSYXRfTnVtYmVyIikKICAgICAgICAgICAgICAgICAsIHZhcmlhYmxlLm5hbWUgPSAiZmVhdHVyZSIKICAgICAgICAgICAgICAgICAsIHZhbHVlLm5hbWUgPSAiUkEiKQojIGdldCB0YXhhIG5hbWVzCnNvdXJjZSgiLi4vc2NyaXB0cy9nZXQubGFzdC5uYW1lLlIiKQpuYW1lcyh0YXhvbm9teSlbMV0gPSAiZmVhdHVyZSIKdGF4YV9uYW1lcyA9IAogIGRhdGEuZnJhbWUoICB0YXhhID0gdW5saXN0KGxhcHBseShoaWdoX21hYXNsaW4kZmVhdHVyZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBnZXQubGFzdC5uYW1lLCB0YXhvbm9teSkpCiAgICAgICAgICAgICAsIGZlYXR1cmUgPSBoaWdoX21hYXNsaW4kZmVhdHVyZSkKCm1lbHRlZF9tYWFzbGluID0gbGVmdF9qb2luKG1lbHRlZF9tYWFzbGluLCB0YXhhX25hbWVzLCBieSA9ICJmZWF0dXJlIikKIyBOaWNlIHNhbXBsZXMgbmFtZXMKbWVsdGVkX21hYXNsaW4gPSBtZWx0ZWRfbWFhc2xpbiAlPiUgCiAgICAgIG11dGF0ZShjb2RlID0gcGFzdGUoRGlldCwgcGFzdGUwKCIjIixSYXRfTnVtYmVyKSkpCiMgTm9ybWFsaXplIFJBIHZhbHVlcyAoanVzdCBpbiBjYXNlKQptZWx0ZWRfbWFhc2xpbiA9IAogIG1lbHRlZF9tYWFzbGluICU+JSBncm91cF9ieShmZWF0dXJlKSAlPiUgbXV0YXRlKG5vcm1fUkEgPSBzY2FsZShSQSkpCgptZWx0ZWRfbWFhc2xpbiRmZWF0dXJlID0gZmFjdG9yKG1lbHRlZF9tYWFzbGluJGZlYXR1cmUpCmBgYApgYGB7ciwgd2FybmluZyA9IEZ9CmdncGxvdChtZWx0ZWRfbWFhc2xpbiwgYWVzKCAgeCA9IGNvZGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgLCB5ID0gZmVhdHVyZQogICAgICAgICAgICAgICAgICAgICAgICAgICAsIGZpbGwgPSBsb2coUkErMWUtMTEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICMgLCBncm91cCA9IHRheGEKICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBncm91cCA9IERpZXQpKSArCiAgZ2VvbV90aWxlKCkgKwogIHNjYWxlX2ZpbGxfY29udGludW91cyh0eXBlID0gInZpcmlkaXMiLCBuYW1lID0gImxvZyhSQSkiKSArIAogIHNjYWxlX3lfZGlzY3JldGUobGFiZWxzID0gZmFjdG9yKG1lbHRlZF9tYWFzbGluJHRheGEpW29yZGVyKG1lbHRlZF9tYWFzbGluJGNvZGUpXSkgKyAKICAjIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZmFjdG9yKG1lbHRlZF9tYWFzbGluJERpZXQpW29yZGVyKG1lbHRlZF9tYWFzbGluJGNvZGUpXSkgKwogIGdndGl0bGUoIk5vIEFudGliaW90aWNzIikgKyAKICB0aGVtZSggIAogICAgIyBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKQogICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKQogICAgICAgICwgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpCiAgICAgICApCgojIGdnc2F2ZShmaWxlbmFtZSA9ICJtYWFzbGluX25vQUIuc3ZnIiwgaGVpZ2h0ID0gNywgd2lkdGggPSA2KSAgCgpgYGAKYGBge3IgbWFrZS1iaW9tLXRhYmxlLWZvci1BQn0KYmlvbV90YWJsZUFCID0gCiAgYmlvbV9tZXRhICU+JSAKICAgIGZpbHRlcihBbnRpYmlvdGljcyA9PSAiWWVzIikgJT4lIAogICAgc2VsZWN0KFNhbXBsZUlELCBtYXRjaGVzKCJbQVRHQ117MTAsfSIpKQoKbWFwcGluZ0FCID0gbWFwcGluZ19maWxlICU+JSAKICBmaWx0ZXIoQW50aWJpb3RpY3MgPT0gIlllcyIpICU+JSAKICBzZWxlY3QoU2FtcGxlSUQsIERpZXQpCmBgYAoKYGBge3IgcnVuLW1hYXNsaW4tQUIsIHJlc3VsdHMgPSAiaGlkZSIsIG1lc3NhZ2UgPSBGfQp3cml0ZS50YWJsZSggIGJpb21fdGFibGVBQgogICAgICAgICAgICAsICJkYXRhL2Jpb21fdGFibGVBQiIKICAgICAgICAgICAgLCBzZXAgPSAiXHQiCiAgICAgICAgICAgICwgcXVvdGUgPSBUCiAgICAgICAgICAgICwgcm93Lm5hbWVzID0gRikKCndyaXRlLnRhYmxlKCAgbWFwcGluZ0FCCiAgICAgICAgICAgICwgImRhdGEvbWFwcGluZ0FCIgogICAgICAgICAgICAsIHNlcCA9ICJcdCIKICAgICAgICAgICAgLCBxdW90ZSA9IFQKICAgICAgICAgICAgLCByb3cubmFtZXMgPSBGKQoKTWFhc2xpbjI6Ok1hYXNsaW4yKCJkYXRhL2Jpb21fdGFibGVBQiIKICAgICwgImRhdGEvbWFwcGluZ0FCIgogICAgLCAib3V0cHV0X21hYXNsaW5fU1ZfQUIiCiAgICApCgptYWFzbGluX3Jlc3VsdHNBQiA9IHJlYWQudGFibGUoIm91dHB1dF9tYWFzbGluX1NWX0FCL2FsbF9yZXN1bHRzLnRzdiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgaGVhZGVyID0gVCkKCm5hbWVzKG1hYXNsaW5fcmVzdWx0c0FCKVs5XQp0ZW1wID0gbWFhc2xpbl9yZXN1bHRzQUJbbWFhc2xpbl9yZXN1bHRzQUIkcXZhbCA8IC4xICYgISBpcy5uYShtYWFzbGluX3Jlc3VsdHNBQiRxdmFsKSxdJGZlYXR1cmUKCiMgdGVtcGIgPSBtYWFzbGluX3Jlc3VsdHNBQiAlPiUgZmlsdGVyKHF2YWwgPCAuMDUpICU+JSBzZWxlY3QoZmVhdHVyZSkgJT4lIHVubGlzdCgpCgoKYGBgCgpgYGB7ciBtbWFzbGluLWhlYXRtYXAtQUIsIHdhcm5pbmcgPSBGfQpoaWdoX21hYXNsaW5BQiA9IAptYWFzbGluX3Jlc3VsdHNBQiAlPiUgCiAgZmlsdGVyKHF2YWwgPCAwLjA1KSAlPiUKICBzZWxlY3QoZmVhdHVyZSkgIyAlPiUKICAjIHVubGlzdCgpCgpSQWJpb21faGlnaF9tYWFzbGluQUIgPSAKICBiaW9tX21ldGEgJT4lIGZpbHRlcihBbnRpYmlvdGljcyA9PSAiWWVzIikgJT4lIAogICAgICAgICAgICAgICAgc2VsZWN0KCBoaWdoX21hYXNsaW5BQiAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgdW5saXN0KCkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIGFzLmNoYXJhY3RlcigpLCBTYW1wbGVJRCkKClJBYmlvbV9oaWdoX21hYXNsaW5BQiA9IAogIFJBYmlvbV9oaWdoX21hYXNsaW5BQiAlPiUgCiAgIyByb3duYW1lc190b19jb2x1bW4oIlNhbXBsZUlEIikgJT4lIAogIGxlZnRfam9pbihtYXBwaW5nX2ZpbGUgJT4lIAogICAgICAgICAgICAgIHNlbGVjdChTYW1wbGVJRCwgRGlldCwgQW50aWJpb3RpY3MsIFJhdF9OdW1iZXIpCiAgICAgICAgICAgICAgICAsIGJ5ID0gIlNhbXBsZUlEIikgCiAgCm1lbHRlZF9tYWFzbGluQUIgPSAKICByZXNoYXBlMjo6bWVsdCggIFJBYmlvbV9oaWdoX21hYXNsaW5BQgogICAgICAgICAgICAgICAgICwgaWQgPSBjKCJTYW1wbGVJRCIsICJEaWV0IiwgIkFudGliaW90aWNzIiwgIlJhdF9OdW1iZXIiKQogICAgICAgICAgICAgICAgICwgdmFyaWFibGUubmFtZSA9ICJmZWF0dXJlIgogICAgICAgICAgICAgICAgICwgdmFsdWUubmFtZSA9ICJSQSIpCiMgZ2V0IHRheGEgbmFtZXMKc291cmNlKCIuLi9zY3JpcHRzL2dldC5sYXN0Lm5hbWUuUiIpCm5hbWVzKHRheG9ub215KVsxXSA9ICJmZWF0dXJlIgp0YXhhX25hbWVzQUIgPSAKICBkYXRhLmZyYW1lKCAgdGF4YSA9IHVubGlzdChsYXBwbHkoaGlnaF9tYWFzbGluQUIkZmVhdHVyZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBnZXQubGFzdC5uYW1lLCB0YXhvbm9teSkpCiAgICAgICAgICAgICAsIGZlYXR1cmUgPSBoaWdoX21hYXNsaW5BQiRmZWF0dXJlKQptZWx0ZWRfbWFhc2xpbkFCID0gbGVmdF9qb2luKG1lbHRlZF9tYWFzbGluQUIsIHRheGFfbmFtZXNBQikKIyBOaWNlIHNhbXBsZXMgbmFtZXMKbWVsdGVkX21hYXNsaW5BQiA9IG1lbHRlZF9tYWFzbGluQUIgJT4lIAogICAgICBtdXRhdGUoY29kZSA9IHBhc3RlKERpZXQsIHBhc3RlMCgiIyIsUmF0X051bWJlcikpKQojIE5vcm1hbGl6ZSBSQSB2YWx1ZXMgKGp1c3QgaW4gY2FzZSkKbWVsdGVkX21hYXNsaW5BQiA9IAogIG1lbHRlZF9tYWFzbGluQUIgJT4lIGdyb3VwX2J5KGZlYXR1cmUpICU+JSBtdXRhdGUobm9ybV9SQSA9IHNjYWxlKFJBKSkKCm1lbHRlZF9tYWFzbGluQUIkZmVhdHVyZSA9IGZhY3RvcihtZWx0ZWRfbWFhc2xpbkFCJGZlYXR1cmUpCgpnZ3Bsb3QobWVsdGVkX21hYXNsaW5BQiwgYWVzKCAgeCA9IGNvZGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgLCB5ID0gZmVhdHVyZQogICAgICAgICAgICAgICAgICAgICAgICAgICAsIGZpbGwgPSBsb2coUkErMWUtMTEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICMgLCBncm91cCA9IHRheGEKICAgICAgICAgICAgICAgICAgICAgICAgICAgLCBncm91cCA9IERpZXQpKSArCiAgZ2VvbV90aWxlKCkgKwogIHNjYWxlX2ZpbGxfY29udGludW91cyh0eXBlID0gInZpcmlkaXMiLCBuYW1lID0gImxvZyhSQSkiKSArIAogIHNjYWxlX3lfZGlzY3JldGUobGFiZWxzID0gZmFjdG9yKG1lbHRlZF9tYWFzbGluQUIkdGF4YSlbb3JkZXIobWVsdGVkX21hYXNsaW5BQiRjb2RlKV0pICsgCiAgIyBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZhY3RvcihtZWx0ZWRfbWFhc2xpbiREaWV0KVtvcmRlcihtZWx0ZWRfbWFhc2xpbiRjb2RlKV0pICsKICBnZ3RpdGxlKCJXaXRoIEFudGliaW90aWNzIikgKyAKICB0aGVtZSggIAogICAgIyBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKQogICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKQogICAgICAgICwgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpCiAgICAgICApCgpnZ3NhdmUoZmlsZW5hbWUgPSAibWFhc2xpbl9ub0FCLnN2ZyIsIGhlaWdodCA9IDcsIHdpZHRoID0gNSkgIAoKYGBgCgoKYGBge3IgdW53ZWlnaHRlZC11bmlmcmFjLCB3YXJuaW5nID0gRn0KdW53ZWlnaHRlZF9wYXRoID0gIi9waXRhL3VzZXJzL3JvdGVtL2ZpcnN0dHJ5L3Jlcy9jb3JlLW1ldHJpY3MtcmVzdWx0cy91bndlaWdodGVkX3VuaWZyYWNfcGNvYV9yZXN1bHRzLnF6YSIKZXh0cmFjdC5xaWltZSh1bndlaWdodGVkX3BhdGgsICIqdHh0IikKCnBjb2EgPSByZWFkLnRhYmxlKCIvcGl0YS91c2Vycy9yb3RlbS9maXJzdHRyeS9yZXMvY29yZS1tZXRyaWNzLXJlc3VsdHMvdW53ZWlnaHRlZF91bmlmcmFjX3Bjb2FfcmVzdWx0cy9vcmRpbmF0aW9uLnR4dCIKICAgICAgICAgICAgICAgICAgLCBza2lwID0gOSwgbnJvd3MgPSBsZW5ndGgobWFwcGluZ19maWxlJFNhbXBsZUlEKSwgcm93Lm5hbWVzID0gMSkKCgp2YXJfZXhwbGFpbmVkID0gcmVhZC50YWJsZSgiL3BpdGEvdXNlcnMvcm90ZW0vZmlyc3R0cnkvcmVzL2NvcmUtbWV0cmljcy1yZXN1bHRzL3Vud2VpZ2h0ZWRfdW5pZnJhY19wY29hX3Jlc3VsdHMvb3JkaW5hdGlvbi50eHQiLCBza2lwID0gNCwgbnJvd3MgPSAxKQoKcGNvMSA9IHBhc3RlMCgiUENvQSAxICgiLCByb3VuZCh2YXJfZXhwbGFpbmVkWzEsMV0qMTAwKSwgIiUpIikKcGNvMiA9IHBhc3RlMCgiUENvQSAyICgiLCByb3VuZCh2YXJfZXhwbGFpbmVkWzEsMl0qMTAwKSwgIiUpIikKcGNvMyA9IHBhc3RlMCgiUENvQSAzICgiLCByb3VuZCh2YXJfZXhwbGFpbmVkWzEsM10qMTAwKSwgIiUpIikKYGBgCgpgYGB7ciwgd2FybmluZyA9IEZ9CnBjb2EgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigiU2FtcGxlSUQiKSAlPiUKICBsZWZ0X2pvaW4obWFwcGluZ19maWxlLCBieSA9ICJTYW1wbGVJRCIpICU+JSAKICBnZ3Bsb3QoYWVzKGNvbG9yID0gVHlwZSwgeCA9IFYyLCB5ID0gVjMpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDQpICsgCiAgeGxhYihwY28xKSArIAogIHlsYWIocGNvMikgKyAKICB0aGVtZV9jbGFzc2ljKCkKYGBgCgpgYGB7ciwgd2FybmluZyA9IEZ9CnBjb2EgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigiU2FtcGxlSUQiKSAlPiUKICBsZWZ0X2pvaW4obWFwcGluZ19maWxlLCBieSA9ICJTYW1wbGVJRCIpICU+JSAKICBnZ3Bsb3QoYWVzKGNvbG9yID0gVHlwZSwgeCA9IFYyLCB5ID0gVjQpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDQpICsgCiAgeGxhYihwY28xKSArIAogIHlsYWIocGNvMykgKyAKICB0aGVtZV9jbGFzc2ljKCkKYGBgCgpgYGB7ciwgd2FybmluZyA9IEZ9CnBjb2EgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigiU2FtcGxlSUQiKSAlPiUKICBsZWZ0X2pvaW4obWFwcGluZ19maWxlLCBieSA9ICJTYW1wbGVJRCIpICU+JSAKICBnZ3Bsb3QoYWVzKGNvbG9yID0gVHlwZSwgeCA9IFYzLCB5ID0gVjQpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDQpICsgCiAgeGxhYihwY28yKSArIAogIHlsYWIocGNvMykgKyAKICB0aGVtZV9jbGFzc2ljKCkKYGBgCgpgYGB7ciwgaW5jbHVkZSA9IEZBTFNFfQpSQWJpb21faGlnaF9tYWFzbGluX3QgPSBSQWJpb21faGlnaF9tYWFzbGluICU+JSB0KCkgJT4lIGRhdGEuZnJhbWUoKQpuYW1lcyhSQWJpb21faGlnaF9tYWFzbGluX3QpID0gZmFjdG9yKHVubGlzdChSQWJpb21faGlnaF9tYWFzbGluX3RbMSxdKSkKClJBYmlvbV9oaWdoX21hYXNsaW5fdCA9IFJBYmlvbV9oaWdoX21hYXNsaW5fdFstMSxdCgpobSA9IApSQWJpb21faGlnaF9tYWFzbGluX3QgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbigiU1YiKSAlPiUKICBnYXRoZXIoc2FtcGxlID0gLVNWLCB2YWx1ZSA9ICJSQSIpCgpnZ3Bsb3QoaG0sIGFlcyhmaWxsID0gUkEsIHkgPSBTViwgeCA9IGtleSkpICsgCiAgZ2VvbV90aWxlKCkgKyAKICBzY2FsZV9maWxsX2dyYWRpZW50KCkgKyAKICB0aGVtZSggIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogICAgICAgICwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKCmBgYHtyIGxldmVsLTUtQUIsIGluY2x1ZGUgPSBGQUxTRX0KbGV2ZWw1ID0gcmVhZC5jc3YoImRhdGEvdGF4YS1iYXItcGxvdHMvbGV2ZWwtNS5jc3YiKQptYWFzbGluMl9pbnB1dF9BQiA9IGxldmVsNSAlPiUgCiAgICBmaWx0ZXIoQW50aWJpb3RpY3MgPT0gIlllcyIpICU+JQogICAgc2VsZWN0KGluZGV4LCBjb250YWlucygia19fIikpCiMgbmFtZXMobGV2ZWw1KQptYWFzbGluMl9tZXRhZGF0YV9BQiA9IGxldmVsNSAlPiUKICAgIGZpbHRlcihBbnRpYmlvdGljcyA9PSAiWWVzIikgJT4lCiAgICBzZWxlY3QoaW5kZXgsIERpZXQsIFdlaWdodCkKCm5hbWVzKG1hYXNsaW4yX2lucHV0X0FCKVsxXSA9ICIjIgpuYW1lcyhtYWFzbGluMl9tZXRhZGF0YV9BQilbMV0gPSAiIyIKCndyaXRlLnRhYmxlKCAgbWFhc2xpbjJfaW5wdXRfQUIKICAgICAgICAgICAgLCAiZGF0YS9tYWFzbGluMl9pbnB1dF9BQiIKICAgICAgICAgICAgLCBzZXAgPSAiXHQiCiAgICAgICAgICAgICwgcXVvdGUgPSBUCiAgICAgICAgICAgICwgcm93Lm5hbWVzID0gRikKd3JpdGUudGFibGUoICBtYWFzbGluMl9tZXRhZGF0YV9BQgogICAgICAgICAgICAsICJkYXRhL21hYXNsaW4yX21ldGFkYXRhX0FCIgogICAgICAgICAgICAsIHNlcCA9ICJcdCIKICAgICAgICAgICAgLCBxdW90ZSA9IFQKICAgICAgICAgICAgLCByb3cubmFtZXMgPSBGKQoKTWFhc2xpbjI6Ok1hYXNsaW4yKCJkYXRhL21hYXNsaW4yX2lucHV0X0FCIgogICAgLCAiZGF0YS9tYWFzbGluMl9tZXRhZGF0YV9BQiIKICAgICwgIm91dHB1dF9tYWFzbGluX0FCIgogICAgKQoKIyBmaWxlLnJlbW92ZSgiZGF0YS9tYWFzbGluMl9pbnB1dF9BQiIsICJkYXRhL21hYXNsaW4yX21ldGFkYXRhX0FCIikKCmBgYAoKYGBge2Jhc2h9CmBgYCAKCg==