Data getting
tree_of_science <-
tosr::tosR("ethno_education.bib", # Create data from searches
"ethno_education.txt")
[1] 2
Converting your scopus collection into a bibliographic dataframe
Done!
Generating affiliation field tag AU_UN from C1: Done!
Converting your wos collection into a bibliographic dataframe
Done!
Generating affiliation field tag AU_UN from C1: Done!
83 duplicated documents have been removed
Computing TOS SAP
Warning in TOS SAP
Computing TOS subfields
Table 1. Search Criteria
table_1 <-
tibble(wos = length(wos$SR), # Create a dataframe with the values.
scopus = length(scopus$SR),
total = length(wos_scopus_tos$df$SR))
table_1
Figure 1. Languages
main_languages <-
wos_scopus_tos$df |>
select(LA) |>
separate_rows(LA, sep = "; ") |>
count(LA, sort = TRUE) |>
slice(1:5)
other_languages <-
wos_scopus_tos$df |>
separate_rows(LA, sep = "; ") |>
select(LA) |>
count(LA, sort = TRUE) |>
slice(6:n) |>
summarise(n = sum(n)) |>
mutate(LA = "OTHERS") |>
select(LA, n)
Warning in 6:n :
numerical expression has 12 elements: only the first used
languages <-
main_languages |>
bind_rows(other_languages) |>
mutate(percentage = n / sum(n),
percentage = round(percentage,
digits = 2) ) |>
rename(language = LA) |>
select(language, percentage, count = n)
languages
df <- languages |>
rename(value = percentage, group = language) |>
mutate(value = value * 100) |>
select(value, group)
df2 <- df %>%
mutate(csum = rev(cumsum(rev(value))),
pos = value/2 + lead(csum, 1),
pos = if_else(is.na(pos), value/2, pos))
ggplot(df, aes(x = 2 , y = value, fill = fct_inorder(group))) +
geom_col(width = 1, color = 1) +
coord_polar(theta = "y") +
geom_label_repel(data = df2,
aes(y = pos, label = paste0(value, "%")),
size = 4.5, nudge_x = 1, show.legend = FALSE) +
theme(panel.background = element_blank(),
axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
axis.title = element_blank(),
plot.title = element_text(hjust = 0.5, size = 18)) +
labs(title = "Languages") +
guides(fill = guide_legend(title = "")) +
theme_void() +
xlim(0.5, 2.5)

Table 2. Country production
data_biblio_wos <- biblioAnalysis(wos)
wos_country <-
data_biblio_wos$Countries |>
data.frame() |>
mutate(database = "wos") |>
select(country = Tab, papers = Freq, database ) |>
arrange(desc(papers))
data_biblio_scopus <- biblioAnalysis(scopus)
scopus_country <-
data_biblio_scopus$Countries |>
data.frame() |>
mutate(database = "scopus") |>
select(country = Tab, papers = Freq, database ) |>
arrange(desc(papers))
data_biblio_total <- biblioAnalysis(wos_scopus_tos$df)
total_country <-
data_biblio_total$Countries |>
data.frame() |>
mutate(database = "total") |>
select(country = Tab, papers = Freq, database ) |>
arrange(desc(papers))
wos_scopus_total_country <-
wos_country |>
bind_rows(scopus_country,
total_country) |>
mutate(country = as.character(country)) |>
pivot_wider(names_from = database,
values_from = papers) |>
arrange(desc(total)) |>
slice(1:10) |>
mutate(percentage = total / (table_1 |> pull(total)),
percentage = round(percentage, digits = 2))
wos_scopus_total_country
Table 3. Author production
wos_authors <-
data_biblio_wos$Authors |>
data.frame() |>
rename(authors_wos = AU, papers_wos = Freq) |>
arrange(desc(papers_wos)) |>
slice(1:10) |>
mutate(database_wos = "wos")
scopus_authors <-
data_biblio_scopus$Authors |>
data.frame() |>
rename(authors_scopus = AU, papers_scopus = Freq) |>
arrange(desc(papers_scopus)) |>
slice(1:10) |>
mutate(database_scopus = "scopus")
total_authors <-
data_biblio_total$Authors |>
data.frame() |>
rename(authors_total = AU,
papers_total = Freq) |>
arrange(desc(papers_total)) |>
slice(1:10) |>
mutate(database_total = "total")
wos_scopus_authors <-
wos_authors |>
bind_cols(scopus_authors,
total_authors)
wos_scopus_authors
Table 4. Journal production
wos_journal <-
wos |>
filter(str_detect(DT, "ARTICLE")) |>
select(journal = SO) |>
na.omit() |>
count(journal, sort = TRUE) |>
slice(1:20) |>
rename(publications = n) |>
mutate(database = "wos")
scopus_journal <-
scopus |>
filter(str_detect(DT, "ARTICLE")) |>
select(journal = SO) |>
na.omit() |>
count(journal, sort = TRUE) |>
slice(1:20) |>
rename(publications = n) |>
mutate(database = "scopus")
total_journal <-
wos_scopus_tos$df |>
filter(str_detect(DT, "ARTICLE")) |>
select(journal = SO) |>
na.omit() |>
count(journal, sort = TRUE) |>
slice(1:20) |>
rename(publications = n) |>
mutate(database = "total")
wos_scopus_total_journal <-
wos_journal |>
bind_rows(scopus_journal,
total_journal) |>
pivot_wider(names_from = database,
values_from = publications) |>
arrange(desc(total)) |>
slice(1:10) |>
mutate(percentage = total / table_1 |> pull(total),
percentage = round(percentage, digits = 2))
wos_scopus_total_journal
Figure 4. Tree of Science
Tree of Science
tree_of_science
NULL
Clustering analysis
Finding the clusters
nodes <-
tibble(name = V(wos_scopus_tos$graph)$name) |>
left_join(wos_scopus_tos$nodes,
by = c("name" = "ID_TOS"))
wos_scopus_citation_network_1 <-
wos_scopus_tos$graph |>
igraph::set.vertex.attribute(name = "full_name",
index = V(wos_scopus_tos$graph)$name,
value = nodes$CITE)
nodes_1 <-
tibble(name = V(wos_scopus_citation_network_1)$name,
cluster = V(wos_scopus_citation_network_1)$subfield,
full_name = V(wos_scopus_citation_network_1)$full_name)
nodes_2 <-
nodes_1 |>
count(cluster, sort = TRUE) |>
mutate(cluster_1 = row_number()) |>
select(cluster, cluster_1)
nodes_3 <-
nodes_1 |>
left_join(nodes_2) |>
rename(subfield = cluster_1) |>
select(name, full_name, subfield)
Joining, by = "cluster"
edge_list <-
get.edgelist(wos_scopus_citation_network_1) |>
data.frame() |>
rename(Source = X1, Target = X2)
wos_scopus_citation_network <-
graph.data.frame(d = edge_list,
directed = FALSE,
vertices = nodes_3)
wos_scopus_citation_network |>
summary()
IGRAPH e6b120e UN-- 360 586 --
+ attr: name (v/c), full_name (v/c), subfield (v/n)
Choosing clusters
clusters <-
tibble(cluster = V(wos_scopus_citation_network)$subfield) |>
count(cluster, sort = TRUE)
clusters |>
ggplot(aes(x = reorder(cluster, n), y = n)) +
geom_point()

Removing not chosen clusters
wos_scopus_citation_network_clusters <-
wos_scopus_citation_network |>
delete.vertices(which(V(wos_scopus_citation_network)$subfield != 1 & # filter clusters
V(wos_scopus_citation_network)$subfield != 2 &
V(wos_scopus_citation_network)$subfield != 3 &
V(wos_scopus_citation_network)$subfield != 4))
wos_scopus_citation_network_clusters |>
summary()
IGRAPH 29631ff UN-- 170 272 --
+ attr: name (v/c), full_name (v/c), subfield (v/n)
Cluster 1
nodes_full_data |>
filter(cluster == 1) |>
select(full_name) |>
mutate(full_name = str_extract(full_name, SPC %R% # Regular expressions
one_or_more(WRD) %R%
SPC %R%
one_or_more(or(WRD, ANY_CHAR))),
full_name = str_remove(full_name, OPEN_PAREN %R%
repeated(DGT, 4) %R%
CLOSE_PAREN %R%
one_or_more(or(WRD,ANY_CHAR))),
full_name = str_trim(full_name)) |>
unnest_tokens(output = word, input = full_name) |> # Tokenization
anti_join(stop_words) |> # Removing stop words
filter(word != "doi",
!str_detect(word, "[0-9]")) |> # WoS data
filter(word == str_remove(word, pattern = "citation"),
word == str_remove(word, pattern = "research"), # Words removed
word == str_remove(word, pattern = "analysis"),
word == str_remove(word, pattern = "science"),
word == str_remove(word, pattern = "scientometric"),
word == str_remove(word, pattern = "education")) |>
count(word, sort = TRUE) |>
with(wordcloud(word,
n,
random.order = FALSE,
max.words = 50,
colors=pal))
Joining, by = "word"

Cluster 2
nodes_full_data |>
filter(cluster == 2) |>
select(full_name) |>
mutate(full_name = str_extract(full_name, SPC %R% # Regular expressions
one_or_more(WRD) %R%
SPC %R%
one_or_more(or(WRD, ANY_CHAR))),
full_name = str_remove(full_name, OPEN_PAREN %R%
repeated(DGT, 4) %R%
CLOSE_PAREN %R%
one_or_more(or(WRD,ANY_CHAR))),
full_name = str_trim(full_name)) |>
unnest_tokens(output = word, input = full_name) |>
anti_join(stop_words) |>
filter(word != "doi",
!str_detect(word, "[0-9]")) |> # WoS data
filter(word == str_remove(word, pattern = "citation"),
word == str_remove(word, pattern = "research"),
word == str_remove(word, pattern = "analysis"),
word == str_remove(word, pattern = "science"),
word == str_remove(word, pattern = "scientometric"),
word == str_remove(word, pattern = "education")) |>
count(word, sort = TRUE) |>
with(wordcloud(word,
n,
random.order = FALSE,
max.words = 50,
colors=pal))
Joining, by = "word"

Cluster 3
nodes_full_data |>
filter(cluster == 3) |>
select(full_name) |>
mutate(full_name = str_extract(full_name, SPC %R% # Regular expressions
one_or_more(WRD) %R%
SPC %R%
one_or_more(or(WRD, ANY_CHAR))),
full_name = str_remove(full_name, OPEN_PAREN %R%
repeated(DGT, 4) %R%
CLOSE_PAREN %R%
one_or_more(or(WRD,ANY_CHAR))),
full_name = str_trim(full_name)) |>
unnest_tokens(output = word, input = full_name) |>
anti_join(stop_words) |>
filter(word != "doi",
!str_detect(word, "[0-9]")) |> # WoS data
filter(word == str_remove(word, pattern = "citation"),
word == str_remove(word, pattern = "research"),
word == str_remove(word, pattern = "analysis"),
word == str_remove(word, pattern = "science"),
word == str_remove(word, pattern = "scientometric"),
word == str_remove(word, pattern = "education")) |>
count(word, sort = TRUE) |>
with(wordcloud(word,
n,
random.order = FALSE,
max.words = 50,
colors=pal))
Joining, by = "word"

Cluster 4
nodes_full_data |>
filter(cluster == 4) |>
select(full_name) |>
mutate(full_name = str_extract(full_name, SPC %R% # Regular expressions
one_or_more(WRD) %R%
SPC %R%
one_or_more(or(WRD, ANY_CHAR))),
full_name = str_remove(full_name, OPEN_PAREN %R%
repeated(DGT, 4) %R%
CLOSE_PAREN %R%
one_or_more(or(WRD,ANY_CHAR))),
full_name = str_trim(full_name)) |>
unnest_tokens(output = word, input = full_name) |>
anti_join(stop_words) |>
filter(word != "doi",
!str_detect(word, "[0-9]")) |> # WoS data
filter(word == str_remove(word, pattern = "citation"),
word == str_remove(word, pattern = "research"),
word == str_remove(word, pattern = "education"),
word == str_remove(word, pattern = "de"),
word == str_remove(word, pattern = "la"),
word == str_remove(word, pattern = "res")) |>
count(word, sort = TRUE) |>
with(wordcloud(word,
n,
random.order = FALSE,
max.words = 50,
colors=pal))
Joining, by = "word"

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCmVkaXRvcl9vcHRpb25zOiAKICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lCi0tLQoKIyBDcmVhdGluZyB0aGUgZW52aXJvbm1lbnQKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh0b3NyKQpsaWJyYXJ5KGJpYmxpb21ldHJpeCkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoaWdyYXBoKQpsaWJyYXJ5KHRpZHl0ZXh0KQpsaWJyYXJ5KHdvcmRjbG91ZCkKbGlicmFyeShyZWJ1cykKbGlicmFyeShnZ3JlcGVsKSAjIGltcHJvdmUgZG9udXQgdmlzdWFsaXphdGlvbgpgYGAKCiMgRGF0YSBnZXR0aW5nCgpgYGB7cn0Kd29zX3Njb3B1c190b3MgPC0gCiAgdG9zcjo6dG9zcl9sb2FkKCJldGhub19lZHVjYXRpb24uYmliIiwgICMgQ3JlYXRlIGRhdGEgZnJvbSBzZWFyY2hlcyAKICAgICAgICAgICAgICAgICAgImV0aG5vX2VkdWNhdGlvbi50eHQiKQoKdHJlZV9vZl9zY2llbmNlIDwtIAogIHRvc3I6OnRvc1IoImV0aG5vX2VkdWNhdGlvbi5iaWIiLCAgIyBDcmVhdGUgZGF0YSBmcm9tIHNlYXJjaGVzIAogICAgICAgICAgICAgImV0aG5vX2VkdWNhdGlvbi50eHQiKQoKd29zIDwtIAogIGJpYmxpb21ldHJpeDo6Y29udmVydDJkZigiZXRobm9fZWR1Y2F0aW9uLnR4dCIpICMgY3JlYXRlIGRhdGFmcmFtZSBmcm9tIHdvcyBmaWxlCgpzY29wdXMgPC0gCiAgYmlibGlvbWV0cml4Ojpjb252ZXJ0MmRmKCJldGhub19lZHVjYXRpb24uYmliIiwgIyBDcmVhdGUgZGF0YWZyYW1lIGZyb20gc2NvcHVzIGZpbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgZGJzb3VyY2UgPSAic2NvcHVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdCA9ICJiaWJ0ZXgiKQoKCmBgYAoKIyMgVGFibGUgMS4gU2VhcmNoIENyaXRlcmlhCgpgYGB7cn0KdGFibGVfMSA8LSAKICB0aWJibGUod29zID0gbGVuZ3RoKHdvcyRTUiksICMgQ3JlYXRlIGEgZGF0YWZyYW1lIHdpdGggdGhlIHZhbHVlcy4KICAgICAgICAgc2NvcHVzID0gbGVuZ3RoKHNjb3B1cyRTUiksIAogICAgICAgICB0b3RhbCA9IGxlbmd0aCh3b3Nfc2NvcHVzX3RvcyRkZiRTUikpCnRhYmxlXzEKYGBgCgojIyBGaWd1cmUgMS4gTGFuZ3VhZ2VzCgpgYGB7cn0KbWFpbl9sYW5ndWFnZXMgPC0gCiAgd29zX3Njb3B1c190b3MkZGYgfD4gCiAgc2VsZWN0KExBKSB8PiAKICBzZXBhcmF0ZV9yb3dzKExBLCBzZXAgPSAiOyAiKSB8PiAKICBjb3VudChMQSwgc29ydCA9IFRSVUUpIHw+IAogIHNsaWNlKDE6NSkKCm90aGVyX2xhbmd1YWdlcyA8LSAKICB3b3Nfc2NvcHVzX3RvcyRkZiB8PiAKICBzZXBhcmF0ZV9yb3dzKExBLCBzZXAgPSAiOyAiKSB8PiAKICBzZWxlY3QoTEEpIHw+IAogIGNvdW50KExBLCBzb3J0ID0gVFJVRSkgfD4gCiAgc2xpY2UoNjpuKSB8PiAKICBzdW1tYXJpc2UobiA9IHN1bShuKSkgfD4gCiAgbXV0YXRlKExBID0gIk9USEVSUyIpIHw+IAogIHNlbGVjdChMQSwgbikKCmxhbmd1YWdlcyA8LSAKICBtYWluX2xhbmd1YWdlcyB8PiAKICBiaW5kX3Jvd3Mob3RoZXJfbGFuZ3VhZ2VzKSB8PiAKICBtdXRhdGUocGVyY2VudGFnZSA9IG4gLyBzdW0obiksCiAgICAgICAgIHBlcmNlbnRhZ2UgPSByb3VuZChwZXJjZW50YWdlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpICkgfD4gCiAgcmVuYW1lKGxhbmd1YWdlID0gTEEpIHw+CiAgc2VsZWN0KGxhbmd1YWdlLCBwZXJjZW50YWdlLCBjb3VudCA9IG4pCgpsYW5ndWFnZXMKYGBgCgoKYGBge3J9CmRmIDwtIGxhbmd1YWdlcyB8PiAKICByZW5hbWUodmFsdWUgPSBwZXJjZW50YWdlLCBncm91cCA9IGxhbmd1YWdlKSB8PgogIG11dGF0ZSh2YWx1ZSA9IHZhbHVlICogMTAwKSB8PiAKICBzZWxlY3QodmFsdWUsIGdyb3VwKQoKZGYyIDwtIGRmICU+JSAKICBtdXRhdGUoY3N1bSA9IHJldihjdW1zdW0ocmV2KHZhbHVlKSkpLCAKICAgICAgICAgcG9zID0gdmFsdWUvMiArIGxlYWQoY3N1bSwgMSksCiAgICAgICAgIHBvcyA9IGlmX2Vsc2UoaXMubmEocG9zKSwgdmFsdWUvMiwgcG9zKSkKCmdncGxvdChkZiwgYWVzKHggPSAyICwgeSA9IHZhbHVlLCBmaWxsID0gZmN0X2lub3JkZXIoZ3JvdXApKSkgKwogIGdlb21fY29sKHdpZHRoID0gMSwgY29sb3IgPSAxKSArCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsKICBnZW9tX2xhYmVsX3JlcGVsKGRhdGEgPSBkZjIsCiAgICAgICAgICAgICAgICAgICBhZXMoeSA9IHBvcywgbGFiZWwgPSBwYXN0ZTAodmFsdWUsICIlIikpLAogICAgICAgICAgICAgICAgICAgc2l6ZSA9IDQuNSwgbnVkZ2VfeCA9IDEsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IDE4KSkgKwogIGxhYnModGl0bGUgPSAiTGFuZ3VhZ2VzIikgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIiIpKSArCiAgdGhlbWVfdm9pZCgpICsKICB4bGltKDAuNSwgMi41KQpgYGAKCiMjIEZpZ3VyZSAyLiBTY2llbnRpZmljIFByb2R1Y3Rpb24KCmBgYHtyfQp3b3NfYW51YWxfcHJvZHVjdGlvbiA8LSAKICB3b3MgfD4gCiAgc2VsZWN0KFBZKSB8PiAKICBjb3VudChQWSwgc29ydCA9IFRSVUUpIHw+IAogIG5hLm9taXQoKSB8PiAKICBmaWx0ZXIoUFkgPj0gMjAwMCwKICAgICAgICAgUFkgPCB5ZWFyKHRvZGF5KCkpKSB8PiAKICBtdXRhdGUocmVmX3R5cGUgPSAid29zIikKCnNjb3B1c19hbnVhbF9wcm9kdWN0aW9uICA8LSAKICBzY29wdXMgfD4gCiAgc2VsZWN0KFBZKSB8PiAKICBjb3VudChQWSwgc29ydCA9IFRSVUUpIHw+IAogIG5hLm9taXQoKSB8PiAKICBmaWx0ZXIoUFkgPj0gMjAwMCwKICAgICAgICAgUFkgPCB5ZWFyKHRvZGF5KCkpKSB8PgogIG11dGF0ZShyZWZfdHlwZSA9ICJzY29wdXMiKQoKdG90YWxfYW51YWxfcHJvZHVjdGlvbiA8LSAKICB3b3Nfc2NvcHVzX3RvcyRkZiB8PiAKICBzZWxlY3QoUFkpIHw+IAogIGNvdW50KFBZLCBzb3J0ID0gVFJVRSkgfD4gCiAgbmEub21pdCgpIHw+IAogIGZpbHRlcihQWSA+PSAyMDAwLAogICAgICAgICBQWSA8IHllYXIodG9kYXkoKSkpIHw+CiAgbXV0YXRlKHJlZl90eXBlID0gInRvdGFsIikKCndvc19zY29wdXNfdG90YWxfYW5udWFsX3Byb2R1Y3Rpb24gPC0gCiAgd29zX2FudWFsX3Byb2R1Y3Rpb24gfD4gCiAgYmluZF9yb3dzKHNjb3B1c19hbnVhbF9wcm9kdWN0aW9uLAogICAgICAgICAgICB0b3RhbF9hbnVhbF9wcm9kdWN0aW9uKSAKCmZpZ3VyZV8yX2RhdGEgPC0gCiAgd29zX3Njb3B1c190b3RhbF9hbm51YWxfcHJvZHVjdGlvbiB8PiAKICBtdXRhdGUoUFkgPSByZXBsYWNlX25hKFBZLCByZXBsYWNlID0gMCkpIHw+IAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSByZWZfdHlwZSwgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBuKSB8PiAKICBhcnJhbmdlKGRlc2MoUFkpKQoKZmlndXJlXzJfZGF0YSAKYGBgCgpgYGB7cn0Kd29zX3Njb3B1c190b3RhbF9hbm51YWxfcHJvZHVjdGlvbiB8PiAKICBnZ3Bsb3QoYWVzKHggPSBQWSwgeSA9IG4sIGNvbG9yID0gcmVmX3R5cGUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiQW5udWFsIFNjaWVudGlmaWMgUHJvZHVjdGlvbiIsIAogICAgICAgeCA9ICJ5ZWFycyIsCiAgICAgICB5ID0gInBhcGVycyIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgCmBgYAoKIyMgVGFibGUgMi4gQ291bnRyeSBwcm9kdWN0aW9uCgpgYGB7cn0KZGF0YV9iaWJsaW9fd29zIDwtIGJpYmxpb0FuYWx5c2lzKHdvcykKCndvc19jb3VudHJ5IDwtIAogIGRhdGFfYmlibGlvX3dvcyRDb3VudHJpZXMgfD4gCiAgZGF0YS5mcmFtZSgpIHw+IAogIG11dGF0ZShkYXRhYmFzZSA9ICJ3b3MiKSB8PiAKICBzZWxlY3QoY291bnRyeSA9IFRhYiwgcGFwZXJzID0gRnJlcSwgZGF0YWJhc2UgKSB8PiAKICBhcnJhbmdlKGRlc2MocGFwZXJzKSkgCgpkYXRhX2JpYmxpb19zY29wdXMgPC0gYmlibGlvQW5hbHlzaXMoc2NvcHVzKQoKc2NvcHVzX2NvdW50cnkgPC0gCiAgZGF0YV9iaWJsaW9fc2NvcHVzJENvdW50cmllcyB8PiAKICBkYXRhLmZyYW1lKCkgfD4gCiAgbXV0YXRlKGRhdGFiYXNlID0gInNjb3B1cyIpIHw+IAogIHNlbGVjdChjb3VudHJ5ID0gVGFiLCBwYXBlcnMgPSBGcmVxLCBkYXRhYmFzZSApIHw+IAogIGFycmFuZ2UoZGVzYyhwYXBlcnMpKSAKCmRhdGFfYmlibGlvX3RvdGFsIDwtIGJpYmxpb0FuYWx5c2lzKHdvc19zY29wdXNfdG9zJGRmKQogIAp0b3RhbF9jb3VudHJ5IDwtIAogIGRhdGFfYmlibGlvX3RvdGFsJENvdW50cmllcyB8PiAKICBkYXRhLmZyYW1lKCkgfD4gCiAgbXV0YXRlKGRhdGFiYXNlID0gInRvdGFsIikgfD4gCiAgc2VsZWN0KGNvdW50cnkgPSBUYWIsIHBhcGVycyA9IEZyZXEsIGRhdGFiYXNlICkgfD4gCiAgYXJyYW5nZShkZXNjKHBhcGVycykpIAoKd29zX3Njb3B1c190b3RhbF9jb3VudHJ5IDwtIAogIHdvc19jb3VudHJ5IHw+IAogIGJpbmRfcm93cyhzY29wdXNfY291bnRyeSwgCiAgICAgICAgICAgIHRvdGFsX2NvdW50cnkpIHw+IAogIG11dGF0ZShjb3VudHJ5ID0gYXMuY2hhcmFjdGVyKGNvdW50cnkpKSB8PiAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gZGF0YWJhc2UsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gcGFwZXJzKSB8PiAKICBhcnJhbmdlKGRlc2ModG90YWwpKSB8PiAKICBzbGljZSgxOjEwKSB8PiAKICBtdXRhdGUocGVyY2VudGFnZSA9IHRvdGFsIC8gKHRhYmxlXzEgfD4gcHVsbCh0b3RhbCkpLAogICAgICAgICBwZXJjZW50YWdlID0gcm91bmQocGVyY2VudGFnZSwgZGlnaXRzID0gMikpCgp3b3Nfc2NvcHVzX3RvdGFsX2NvdW50cnkKYGBgCgojIyBUYWJsZSAzLiBBdXRob3IgcHJvZHVjdGlvbgoKYGBge3J9Cndvc19hdXRob3JzIDwtIAogIGRhdGFfYmlibGlvX3dvcyRBdXRob3JzIHw+IAogIGRhdGEuZnJhbWUoKSB8PiAKICByZW5hbWUoYXV0aG9yc193b3MgPSBBVSwgcGFwZXJzX3dvcyA9IEZyZXEpIHw+IAogIGFycmFuZ2UoZGVzYyhwYXBlcnNfd29zKSkgfD4gCiAgc2xpY2UoMToxMCkgfD4gCiAgbXV0YXRlKGRhdGFiYXNlX3dvcyA9ICJ3b3MiKQoKCnNjb3B1c19hdXRob3JzIDwtIAogIGRhdGFfYmlibGlvX3Njb3B1cyRBdXRob3JzIHw+IAogIGRhdGEuZnJhbWUoKSB8PiAKICByZW5hbWUoYXV0aG9yc19zY29wdXMgPSBBVSwgcGFwZXJzX3Njb3B1cyA9IEZyZXEpIHw+IAogIGFycmFuZ2UoZGVzYyhwYXBlcnNfc2NvcHVzKSkgfD4gCiAgc2xpY2UoMToxMCkgfD4gCiAgbXV0YXRlKGRhdGFiYXNlX3Njb3B1cyA9ICJzY29wdXMiKQoKdG90YWxfYXV0aG9ycyA8LSAKICBkYXRhX2JpYmxpb190b3RhbCRBdXRob3JzIHw+IAogIGRhdGEuZnJhbWUoKSB8PiAKICByZW5hbWUoYXV0aG9yc190b3RhbCA9IEFVLCAKICAgICAgICAgcGFwZXJzX3RvdGFsID0gRnJlcSkgfD4gCiAgYXJyYW5nZShkZXNjKHBhcGVyc190b3RhbCkpIHw+IAogIHNsaWNlKDE6MTApIHw+IAogIG11dGF0ZShkYXRhYmFzZV90b3RhbCA9ICJ0b3RhbCIpCgp3b3Nfc2NvcHVzX2F1dGhvcnMgPC0gCiAgd29zX2F1dGhvcnMgfD4gCiAgYmluZF9jb2xzKHNjb3B1c19hdXRob3JzLAogICAgICAgICAgICB0b3RhbF9hdXRob3JzKQoKd29zX3Njb3B1c19hdXRob3JzCmBgYAoKIyMgVGFibGUgNC4gSm91cm5hbCBwcm9kdWN0aW9uCgpgYGB7cn0Kd29zX2pvdXJuYWwgPC0gCiAgd29zIHw+IAogIGZpbHRlcihzdHJfZGV0ZWN0KERULCAiQVJUSUNMRSIpKSB8PiAKICBzZWxlY3Qoam91cm5hbCA9IFNPKSB8PiAKICBuYS5vbWl0KCkgfD4gCiAgY291bnQoam91cm5hbCwgc29ydCA9IFRSVUUpIHw+IAogIHNsaWNlKDE6MjApIHw+IAogIHJlbmFtZShwdWJsaWNhdGlvbnMgPSBuKSB8PiAKICBtdXRhdGUoZGF0YWJhc2UgPSAid29zIikKCnNjb3B1c19qb3VybmFsIDwtIAogIHNjb3B1cyB8PiAKICBmaWx0ZXIoc3RyX2RldGVjdChEVCwgIkFSVElDTEUiKSkgfD4gCiAgc2VsZWN0KGpvdXJuYWwgPSBTTykgfD4gCiAgbmEub21pdCgpIHw+IAogIGNvdW50KGpvdXJuYWwsIHNvcnQgPSBUUlVFKSB8PiAKICBzbGljZSgxOjIwKSB8PiAKICByZW5hbWUocHVibGljYXRpb25zID0gbikgfD4gCiAgbXV0YXRlKGRhdGFiYXNlID0gInNjb3B1cyIpCgp0b3RhbF9qb3VybmFsIDwtIAogIHdvc19zY29wdXNfdG9zJGRmIHw+IAogIGZpbHRlcihzdHJfZGV0ZWN0KERULCAiQVJUSUNMRSIpKSB8PiAKICBzZWxlY3Qoam91cm5hbCA9IFNPKSB8PiAKICBuYS5vbWl0KCkgfD4gCiAgY291bnQoam91cm5hbCwgc29ydCA9IFRSVUUpIHw+IAogIHNsaWNlKDE6MjApIHw+IAogIHJlbmFtZShwdWJsaWNhdGlvbnMgPSBuKSB8PiAKICBtdXRhdGUoZGF0YWJhc2UgPSAidG90YWwiKQoKd29zX3Njb3B1c190b3RhbF9qb3VybmFsIDwtIAogIHdvc19qb3VybmFsIHw+IAogIGJpbmRfcm93cyhzY29wdXNfam91cm5hbCwgCiAgICAgICAgICAgIHRvdGFsX2pvdXJuYWwpIHw+IAogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBkYXRhYmFzZSwgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBwdWJsaWNhdGlvbnMpIHw+IAogIGFycmFuZ2UoZGVzYyh0b3RhbCkpIHw+IAogIHNsaWNlKDE6MTApIHw+IAogIG11dGF0ZShwZXJjZW50YWdlID0gdG90YWwgLyB0YWJsZV8xIHw+IHB1bGwodG90YWwpLAogICAgICAgICBwZXJjZW50YWdlID0gcm91bmQocGVyY2VudGFnZSwgZGlnaXRzID0gMikpCgoKd29zX3Njb3B1c190b3RhbF9qb3VybmFsCmBgYAoKIyMgRmlndXJlIDMuIENvLWNpdGF0aW9uIG5ldHdvcmsKCiMjIyBBdXRob3IgY28tY2l0YXRpb24gbmV0d29yawoKYGBge3J9Cndvc19zY29wdXNfYXV0aG9yX21ldGF0YWcgPC0gCiAgbWV0YVRhZ0V4dHJhY3Rpb24od29zX3Njb3B1c190b3MkZGYsIEZpZWxkID0gIkNSX0FVIikKCndvc19zY29wdXNfYXV0aG9yX2NvX2NpdGF0aW9uX21hdHJpeCA8LSAKICBiaWJsaW9OZXR3b3JrKE0gPSB3b3Nfc2NvcHVzX2F1dGhvcl9tZXRhdGFnLCAKICAgICAgICAgICAgICAgIGFuYWx5c2lzID0gImNvLWNpdGF0aW9uIiwgCiAgICAgICAgICAgICAgICBuZXR3b3JrID0gImF1dGhvcnMiKQoKcGxvdF9uZXRfYXV0aG9yX2NvX2NpdGF0aW9uIDwtIAogIG5ldHdvcmtQbG90KHdvc19zY29wdXNfYXV0aG9yX2NvX2NpdGF0aW9uX21hdHJpeCwgCiAgICAgICAgICAgICAgd2VpZ2h0ZWQ9VCwgCiAgICAgICAgICAgICAgbiA9IDMwLCAKICAgICAgICAgICAgICBUaXRsZSA9ICJBdXRob3IgQ28tY2l0YXRpb24gTmV0d29yayIsIAogICAgICAgICAgICAgIHR5cGUgPSAiZnJ1Y2h0ZXJtYW4iLCAKICAgICAgICAgICAgICBzaXplPVQsCiAgICAgICAgICAgICAgZWRnZXNpemUgPSA1LAogICAgICAgICAgICAgIGxhYmVsc2l6ZT0wLjcpCmBgYAoKIyMjIEF1dGhvciBDb2xsYWJvcmF0aW9uIG5ldHdvcmsKCmBgYHtyfQp3b3Nfc2NvcHVzX2F1dGhvcl9jb2xsYWJfbWF0cml4IDwtIAogIGJpYmxpb05ldHdvcmsoTSA9IHdvc19zY29wdXNfdG9zJGRmLCAKICAgICAgICAgICAgICAgIGFuYWx5c2lzID0gImNvbGxhYm9yYXRpb24iLCAKICAgICAgICAgICAgICAgIG5ldHdvcmsgPSAiYXV0aG9ycyIpCgpwbG90X2F1dGhvcl9jb2xsYWIgPC0gCiAgbmV0d29ya1Bsb3QoTmV0TWF0cml4ID0gd29zX3Njb3B1c19hdXRob3JfY29sbGFiX21hdHJpeCwgCiAgICAgICAgICAgICAgd2VpZ2h0ZWQ9VCwgbiA9IDMwLCAKICAgICAgICAgICAgICBUaXRsZSA9ICJBdXRob3IgQ29sbGFib3JhdGlvbiBOZXR3b3JrIiwgCiAgICAgICAgICAgICAgdHlwZSA9ICJmcnVjaHRlcm1hbiIsIAogICAgICAgICAgICAgIHNpemU9VCwKICAgICAgICAgICAgICBlZGdlc2l6ZSA9IDUsCiAgICAgICAgICAgICAgbGFiZWxzaXplPTAuNykKYGBgCgojIyMgQ291bnRyeSBDb2xsYWJvcmF0aW9uIE5ldHdvcmsKCmBgYHtyfQp3b3Nfc2NvcHVzX2NvdW50cnlfY29sbGFiX21hdHJpeCA8LSAKICBiaWJsaW9OZXR3b3JrKE0gPSB3b3Nfc2NvcHVzX3RvcyRkZiwgCiAgICAgICAgICAgICAgICBhbmFseXNpcyA9ICJjb2xsYWJvcmF0aW9uIiwgCiAgICAgICAgICAgICAgICBuZXR3b3JrID0gImNvdW50cmllcyIpCgpwbG90X2NvdW50cnlfY29sbGFiIDwtIAogIG5ldHdvcmtQbG90KHdvc19zY29wdXNfY291bnRyeV9jb2xsYWJfbWF0cml4LCAKICAgICAgICAgICAgICB3ZWlnaHRlZD1ULCBuID0gMzAsIAogICAgICAgICAgICAgIFRpdGxlID0gIkNvdW50cnkgQ29sbGFib3JhdGlvbiBOZXR3b3JrIiwgCiAgICAgICAgICAgICAgdHlwZSA9ICJmcnVjaHRlcm1hbiIsIAogICAgICAgICAgICAgIHNpemU9VCwKICAgICAgICAgICAgICBlZGdlc2l6ZSA9IDUsCiAgICAgICAgICAgICAgbGFiZWxzaXplPTAuNykKYGBgCgojIyMgS2V5d29yZCBjby1jaXRhdGlvbiBuZXR3b3JrCgpgYGB7cn0Kd29zX3Njb3B1c19rZXl3b3JkX2NvX29jY3VycmVuY2VfbWF0cml4IDwtIAogIGJpYmxpb05ldHdvcmsoTSA9IHdvc19zY29wdXNfdG9zJGRmLCAKICAgICAgICAgICAgICAgIGFuYWx5c2lzID0gImNvLW9jY3VycmVuY2VzIiwgCiAgICAgICAgICAgICAgICBuZXR3b3JrID0gImtleXdvcmRzIiwgCiAgICAgICAgICAgICAgICBzZXAgPSAiOyIpCgpwbG90X25ldF9jb19vY2N1cnJlbmNlIDwtIAogIG5ldHdvcmtQbG90KHdvc19zY29wdXNfa2V5d29yZF9jb19vY2N1cnJlbmNlX21hdHJpeCwgCiAgICAgICAgICAgICAgd2VpZ2h0ZWQ9VCwgbiA9IDMwLCAKICAgICAgICAgICAgICBUaXRsZSA9ICJLZXl3b3JkIENvLW9jY3VycmVuY2UgTmV0d29yayIsIAogICAgICAgICAgICAgIHR5cGUgPSAiZnJ1Y2h0ZXJtYW4iLCAKICAgICAgICAgICAgICBzaXplPVQsCiAgICAgICAgICAgICAgZWRnZXNpemUgPSA1LAogICAgICAgICAgICAgIGxhYmVsc2l6ZT0wLjcpCmBgYAoKIyMgRmlndXJlIDQuIFRyZWUgb2YgU2NpZW5jZQoKIyMjIFRyZWUgb2YgU2NpZW5jZQoKYGBge3J9CnRyZWVfb2Zfc2NpZW5jZQpgYGAKCiMjIyBDbHVzdGVyaW5nIGFuYWx5c2lzCgpGaW5kaW5nIHRoZSBjbHVzdGVycwoKYGBge3J9Cm5vZGVzIDwtICAKICB0aWJibGUobmFtZSA9IFYod29zX3Njb3B1c190b3MkZ3JhcGgpJG5hbWUpIHw+IAogIGxlZnRfam9pbih3b3Nfc2NvcHVzX3RvcyRub2RlcywgCiAgICAgICAgICAgIGJ5ID0gYygibmFtZSIgPSAiSURfVE9TIikpCgp3b3Nfc2NvcHVzX2NpdGF0aW9uX25ldHdvcmtfMSA8LSAKICB3b3Nfc2NvcHVzX3RvcyRncmFwaCB8PiAKICBpZ3JhcGg6OnNldC52ZXJ0ZXguYXR0cmlidXRlKG5hbWUgPSAiZnVsbF9uYW1lIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCA9IFYod29zX3Njb3B1c190b3MkZ3JhcGgpJG5hbWUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBub2RlcyRDSVRFKQoKbm9kZXNfMSA8LSAKICB0aWJibGUobmFtZSA9IFYod29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrXzEpJG5hbWUsCiAgICAgICAgIGNsdXN0ZXIgPSBWKHdvc19zY29wdXNfY2l0YXRpb25fbmV0d29ya18xKSRzdWJmaWVsZCwKICAgICAgICAgZnVsbF9uYW1lID0gVih3b3Nfc2NvcHVzX2NpdGF0aW9uX25ldHdvcmtfMSkkZnVsbF9uYW1lKQogIApub2Rlc18yIDwtIAogIG5vZGVzXzEgfD4gCiAgY291bnQoY2x1c3Rlciwgc29ydCA9IFRSVUUpIHw+IAogIG11dGF0ZShjbHVzdGVyXzEgPSByb3dfbnVtYmVyKCkpIHw+IAogIHNlbGVjdChjbHVzdGVyLCBjbHVzdGVyXzEpCgpub2Rlc18zIDwtIAogIG5vZGVzXzEgfD4gCiAgbGVmdF9qb2luKG5vZGVzXzIpIHw+IAogIHJlbmFtZShzdWJmaWVsZCA9IGNsdXN0ZXJfMSkgfD4gCiAgc2VsZWN0KG5hbWUsIGZ1bGxfbmFtZSwgc3ViZmllbGQpCgplZGdlX2xpc3QgPC0gCiAgZ2V0LmVkZ2VsaXN0KHdvc19zY29wdXNfY2l0YXRpb25fbmV0d29ya18xKSB8PiAKICBkYXRhLmZyYW1lKCkgfD4gCiAgcmVuYW1lKFNvdXJjZSA9IFgxLCBUYXJnZXQgPSBYMikKCndvc19zY29wdXNfY2l0YXRpb25fbmV0d29yayA8LSAKICBncmFwaC5kYXRhLmZyYW1lKGQgPSBlZGdlX2xpc3QsIAogICAgICAgICAgICAgICAgICAgZGlyZWN0ZWQgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICB2ZXJ0aWNlcyA9IG5vZGVzXzMpCgp3b3Nfc2NvcHVzX2NpdGF0aW9uX25ldHdvcmsgfD4gCiAgc3VtbWFyeSgpCmBgYAoKQ2hvb3NpbmcgY2x1c3RlcnMKCmBgYHtyfQpjbHVzdGVycyA8LSAKICB0aWJibGUoY2x1c3RlciA9IFYod29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrKSRzdWJmaWVsZCkgfD4gCiAgY291bnQoY2x1c3Rlciwgc29ydCA9IFRSVUUpCgpjbHVzdGVycyB8PiAKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKGNsdXN0ZXIsIG4pLCB5ID0gbikpICsKICBnZW9tX3BvaW50KCkgCmBgYAoKUmVtb3Zpbmcgbm90IGNob3NlbiBjbHVzdGVycwoKYGBge3J9Cndvc19zY29wdXNfY2l0YXRpb25fbmV0d29ya19jbHVzdGVycyA8LSAKICB3b3Nfc2NvcHVzX2NpdGF0aW9uX25ldHdvcmsgfD4gCiAgZGVsZXRlLnZlcnRpY2VzKHdoaWNoKFYod29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrKSRzdWJmaWVsZCAhPSAxICYgIyBmaWx0ZXIgY2x1c3RlcnMgCiAgICAgICAgICAgICAgICAgICAgICAgICAgVih3b3Nfc2NvcHVzX2NpdGF0aW9uX25ldHdvcmspJHN1YmZpZWxkICE9IDIgJgogICAgICAgICAgICAgICAgICAgICAgICAgIFYod29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrKSRzdWJmaWVsZCAhPSAzICAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgVih3b3Nfc2NvcHVzX2NpdGF0aW9uX25ldHdvcmspJHN1YmZpZWxkICE9IDQpKQoKd29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrX2NsdXN0ZXJzIHw+IAogIHN1bW1hcnkoKQpgYGAKCiMjIyBDbHVzdGVyIDEKCmBgYHtyfQpwYWwgPC0gYnJld2VyLnBhbCg4LCJEYXJrMiIpCgpub2Rlc19mdWxsX2RhdGEgPC0gCiAgdGliYmxlKG5hbWUgPSBWKHdvc19zY29wdXNfY2l0YXRpb25fbmV0d29yaykkbmFtZSwKICAgICAgICAgY2x1c3RlciA9IFYod29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrKSRzdWJmaWVsZCwKICAgICAgICAgZnVsbF9uYW1lID0gVih3b3Nfc2NvcHVzX2NpdGF0aW9uX25ldHdvcmspJGZ1bGxfbmFtZSkKCmNsdXN0ZXJfMSA8LSAKICB3b3Nfc2NvcHVzX2NpdGF0aW9uX25ldHdvcmsgfD4gCiAgZGVsZXRlLnZlcnRpY2VzKHdoaWNoKFYod29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrKSRzdWJmaWVsZCAhPSAxKSkKCmNsdXN0ZXJfMV9wYWdlX3JhbmsgPC0gCiAgY2x1c3Rlcl8xIHw+IAogIHNldC52ZXJ0ZXguYXR0cmlidXRlKG5hbWUgPSAicGFnZV9yYW5rIiwgCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBwYWdlX3JhbmsoY2x1c3Rlcl8xKSR2ZWN0b3IpCgpjbHVzdGVyXzFfZGYgPC0gCiAgdGliYmxlKG5hbWUgPSBWKGNsdXN0ZXJfMV9wYWdlX3JhbmspJG5hbWUsCiAgICAgICAgIGZ1bGxfbmFtZSA9IFYoY2x1c3Rlcl8xX3BhZ2VfcmFuaykkZnVsbF9uYW1lLAogICAgICAgICBwYWdlX3JhbmsgPSBWKGNsdXN0ZXJfMV9wYWdlX3JhbmspJHBhZ2VfcmFuaywKICAgICAgICAgY2x1c3RlciA9IFYoY2x1c3Rlcl8xX3BhZ2VfcmFuaykkc3ViZmllbGQsKQoKbm9kZXNfZnVsbF9kYXRhIHw+IAogIGZpbHRlcihjbHVzdGVyID09IDEpIHw+IAogIHNlbGVjdChmdWxsX25hbWUpIHw+IAogIG11dGF0ZShmdWxsX25hbWUgPSBzdHJfZXh0cmFjdChmdWxsX25hbWUsIFNQQyAlUiUgICMgUmVndWxhciBleHByZXNzaW9ucyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVfb3JfbW9yZShXUkQpICVSJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTUEMgJVIlIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uZV9vcl9tb3JlKG9yKFdSRCwgQU5ZX0NIQVIpKSksCiAgICAgICAgIGZ1bGxfbmFtZSA9IHN0cl9yZW1vdmUoZnVsbF9uYW1lLCBPUEVOX1BBUkVOICVSJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGVhdGVkKERHVCwgNCkgJVIlIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0xPU0VfUEFSRU4gJVIlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVfb3JfbW9yZShvcihXUkQsQU5ZX0NIQVIpKSksCiAgICAgICAgIGZ1bGxfbmFtZSA9IHN0cl90cmltKGZ1bGxfbmFtZSkpICB8PiAKICB1bm5lc3RfdG9rZW5zKG91dHB1dCA9IHdvcmQsIGlucHV0ID0gZnVsbF9uYW1lKSB8PiAjIFRva2VuaXphdGlvbgogIGFudGlfam9pbihzdG9wX3dvcmRzKSB8PiAgIyBSZW1vdmluZyBzdG9wIHdvcmRzCiAgIGZpbHRlcih3b3JkICE9ICJkb2kiLAogICAgICAgICAhc3RyX2RldGVjdCh3b3JkLCAiWzAtOV0iKSkgfD4gICMgV29TIGRhdGEKICBmaWx0ZXIod29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAiY2l0YXRpb24iKSwKICAgICAgICAgd29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAicmVzZWFyY2giKSwgICMgV29yZHMgcmVtb3ZlZAogICAgICAgICB3b3JkID09IHN0cl9yZW1vdmUod29yZCwgcGF0dGVybiA9ICJhbmFseXNpcyIpLCAKICAgICAgICAgd29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAic2NpZW5jZSIpLAogICAgICAgICB3b3JkID09IHN0cl9yZW1vdmUod29yZCwgcGF0dGVybiA9ICJzY2llbnRvbWV0cmljIiksCiAgICAgICAgIHdvcmQgPT0gc3RyX3JlbW92ZSh3b3JkLCBwYXR0ZXJuID0gImVkdWNhdGlvbiIpKSB8PgogIGNvdW50KHdvcmQsIHNvcnQgPSBUUlVFKSB8PiAKICB3aXRoKHdvcmRjbG91ZCh3b3JkLCAKICAgICAgICAgICAgICAgICBuLCAKICAgICAgICAgICAgICAgICByYW5kb20ub3JkZXIgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgbWF4LndvcmRzID0gNTAsIAogICAgICAgICAgICAgICAgIGNvbG9ycz1wYWwpKQpgYGAKCiMjIyBDbHVzdGVyIDIKCmBgYHtyfQpjbHVzdGVyXzIgPC0gCiAgd29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrIHw+IAogIGRlbGV0ZS52ZXJ0aWNlcyh3aGljaChWKHdvc19zY29wdXNfY2l0YXRpb25fbmV0d29yaykkc3ViZmllbGQgIT0gMikpCgpjbHVzdGVyXzJfcGFnZV9yYW5rIDwtIAogIGNsdXN0ZXJfMiB8PiAKICBzZXQudmVydGV4LmF0dHJpYnV0ZShuYW1lID0gInBhZ2VfcmFuayIsIAogICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gcGFnZV9yYW5rKGNsdXN0ZXJfMikkdmVjdG9yKQoKY2x1c3Rlcl8yX2RmIDwtIAogIHRpYmJsZShuYW1lID0gVihjbHVzdGVyXzJfcGFnZV9yYW5rKSRuYW1lLAogICAgICAgICBmdWxsX25hbWUgPSBWKGNsdXN0ZXJfMl9wYWdlX3JhbmspJGZ1bGxfbmFtZSwKICAgICAgICAgcGFnZV9yYW5rID0gVihjbHVzdGVyXzJfcGFnZV9yYW5rKSRwYWdlX3JhbmssCiAgICAgICAgIGNsdXN0ZXIgPSBWKGNsdXN0ZXJfMl9wYWdlX3JhbmspJHN1YmZpZWxkLCkKCm5vZGVzX2Z1bGxfZGF0YSB8PiAKICBmaWx0ZXIoY2x1c3RlciA9PSAyKSB8PiAKICBzZWxlY3QoZnVsbF9uYW1lKSB8PiAKICBtdXRhdGUoZnVsbF9uYW1lID0gc3RyX2V4dHJhY3QoZnVsbF9uYW1lLCBTUEMgJVIlICAjIFJlZ3VsYXIgZXhwcmVzc2lvbnMgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25lX29yX21vcmUoV1JEKSAlUiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1BDICVSJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVfb3JfbW9yZShvcihXUkQsIEFOWV9DSEFSKSkpLAogICAgICAgICBmdWxsX25hbWUgPSBzdHJfcmVtb3ZlKGZ1bGxfbmFtZSwgT1BFTl9QQVJFTiAlUiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXBlYXRlZChER1QsIDQpICVSJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENMT1NFX1BBUkVOICVSJQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25lX29yX21vcmUob3IoV1JELEFOWV9DSEFSKSkpLAogICAgICAgICBmdWxsX25hbWUgPSBzdHJfdHJpbShmdWxsX25hbWUpKSAgfD4gCiAgdW5uZXN0X3Rva2VucyhvdXRwdXQgPSB3b3JkLCBpbnB1dCA9IGZ1bGxfbmFtZSkgfD4gCiAgYW50aV9qb2luKHN0b3Bfd29yZHMpIHw+CiAgZmlsdGVyKHdvcmQgIT0gImRvaSIsCiAgICAgICAgICFzdHJfZGV0ZWN0KHdvcmQsICJbMC05XSIpKSB8PiAgIyBXb1MgZGF0YQogIGZpbHRlcih3b3JkID09IHN0cl9yZW1vdmUod29yZCwgcGF0dGVybiA9ICJjaXRhdGlvbiIpLAogICAgICAgICB3b3JkID09IHN0cl9yZW1vdmUod29yZCwgcGF0dGVybiA9ICJyZXNlYXJjaCIpLCAKICAgICAgICAgd29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAiYW5hbHlzaXMiKSwgCiAgICAgICAgIHdvcmQgPT0gc3RyX3JlbW92ZSh3b3JkLCBwYXR0ZXJuID0gInNjaWVuY2UiKSwKICAgICAgICAgd29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAic2NpZW50b21ldHJpYyIpLAogICAgICAgICB3b3JkID09IHN0cl9yZW1vdmUod29yZCwgcGF0dGVybiA9ICJlZHVjYXRpb24iKSkgfD4KICBjb3VudCh3b3JkLCBzb3J0ID0gVFJVRSkgfD4gCiAgd2l0aCh3b3JkY2xvdWQod29yZCwgCiAgICAgICAgICAgICAgICAgbiwgCiAgICAgICAgICAgICAgICAgcmFuZG9tLm9yZGVyID0gRkFMU0UsIAogICAgICAgICAgICAgICAgIG1heC53b3JkcyA9IDUwLCAKICAgICAgICAgICAgICAgICBjb2xvcnM9cGFsKSkKYGBgCgojIyMgQ2x1c3RlciAzCgpgYGB7cn0KCmNsdXN0ZXJfMyA8LSAKICB3b3Nfc2NvcHVzX2NpdGF0aW9uX25ldHdvcmsgfD4gCiAgZGVsZXRlLnZlcnRpY2VzKHdoaWNoKFYod29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrKSRzdWJmaWVsZCAhPSAzKSkKCmNsdXN0ZXJfM19wYWdlX3JhbmsgPC0gCiAgY2x1c3Rlcl8zIHw+IAogIHNldC52ZXJ0ZXguYXR0cmlidXRlKG5hbWUgPSAicGFnZV9yYW5rIiwgCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBwYWdlX3JhbmsoY2x1c3Rlcl8zKSR2ZWN0b3IpCgpjbHVzdGVyXzNfZGYgPC0gCiAgdGliYmxlKG5hbWUgPSBWKGNsdXN0ZXJfM19wYWdlX3JhbmspJG5hbWUsCiAgICAgICAgIGZ1bGxfbmFtZSA9IFYoY2x1c3Rlcl8zX3BhZ2VfcmFuaykkZnVsbF9uYW1lLAogICAgICAgICBwYWdlX3JhbmsgPSBWKGNsdXN0ZXJfM19wYWdlX3JhbmspJHBhZ2VfcmFuaywKICAgICAgICAgY2x1c3RlciA9IFYoY2x1c3Rlcl8zX3BhZ2VfcmFuaykkc3ViZmllbGQsKQoKbm9kZXNfZnVsbF9kYXRhIHw+IAogIGZpbHRlcihjbHVzdGVyID09IDMpIHw+IAogIHNlbGVjdChmdWxsX25hbWUpIHw+IAogIG11dGF0ZShmdWxsX25hbWUgPSBzdHJfZXh0cmFjdChmdWxsX25hbWUsIFNQQyAlUiUgICMgUmVndWxhciBleHByZXNzaW9ucyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVfb3JfbW9yZShXUkQpICVSJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTUEMgJVIlIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uZV9vcl9tb3JlKG9yKFdSRCwgQU5ZX0NIQVIpKSksCiAgICAgICAgIGZ1bGxfbmFtZSA9IHN0cl9yZW1vdmUoZnVsbF9uYW1lLCBPUEVOX1BBUkVOICVSJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGVhdGVkKERHVCwgNCkgJVIlIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0xPU0VfUEFSRU4gJVIlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVfb3JfbW9yZShvcihXUkQsQU5ZX0NIQVIpKSksCiAgICAgICAgIGZ1bGxfbmFtZSA9IHN0cl90cmltKGZ1bGxfbmFtZSkpICB8PiAKICB1bm5lc3RfdG9rZW5zKG91dHB1dCA9IHdvcmQsIGlucHV0ID0gZnVsbF9uYW1lKSB8PiAKICBhbnRpX2pvaW4oc3RvcF93b3JkcykgfD4KICAgZmlsdGVyKHdvcmQgIT0gImRvaSIsCiAgICAgICAgICFzdHJfZGV0ZWN0KHdvcmQsICJbMC05XSIpKSB8PiAgIyBXb1MgZGF0YSAKICBmaWx0ZXIod29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAiY2l0YXRpb24iKSwKICAgICAgICAgd29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAicmVzZWFyY2giKSwgCiAgICAgICAgIHdvcmQgPT0gc3RyX3JlbW92ZSh3b3JkLCBwYXR0ZXJuID0gImFuYWx5c2lzIiksIAogICAgICAgICB3b3JkID09IHN0cl9yZW1vdmUod29yZCwgcGF0dGVybiA9ICJzY2llbmNlIiksCiAgICAgICAgIHdvcmQgPT0gc3RyX3JlbW92ZSh3b3JkLCBwYXR0ZXJuID0gInNjaWVudG9tZXRyaWMiKSwKICAgICAgICAgd29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAiZWR1Y2F0aW9uIikpIHw+CiAgY291bnQod29yZCwgc29ydCA9IFRSVUUpIHw+IAogIHdpdGgod29yZGNsb3VkKHdvcmQsIAogICAgICAgICAgICAgICAgIG4sIAogICAgICAgICAgICAgICAgIHJhbmRvbS5vcmRlciA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICBtYXgud29yZHMgPSA1MCwgCiAgICAgICAgICAgICAgICAgY29sb3JzPXBhbCkpCmBgYAojIyMgQ2x1c3RlciA0CgpgYGB7cn0KCmNsdXN0ZXJfNCA8LSAKICB3b3Nfc2NvcHVzX2NpdGF0aW9uX25ldHdvcmsgfD4gCiAgZGVsZXRlLnZlcnRpY2VzKHdoaWNoKFYod29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrKSRzdWJmaWVsZCAhPSA0KSkKCmNsdXN0ZXJfNF9wYWdlX3JhbmsgPC0gCiAgY2x1c3Rlcl80IHw+IAogIHNldC52ZXJ0ZXguYXR0cmlidXRlKG5hbWUgPSAicGFnZV9yYW5rIiwgCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBwYWdlX3JhbmsoY2x1c3Rlcl80KSR2ZWN0b3IpCgpjbHVzdGVyXzRfZGYgPC0gCiAgdGliYmxlKG5hbWUgPSBWKGNsdXN0ZXJfNF9wYWdlX3JhbmspJG5hbWUsCiAgICAgICAgIGZ1bGxfbmFtZSA9IFYoY2x1c3Rlcl80X3BhZ2VfcmFuaykkZnVsbF9uYW1lLAogICAgICAgICBwYWdlX3JhbmsgPSBWKGNsdXN0ZXJfNF9wYWdlX3JhbmspJHBhZ2VfcmFuaywKICAgICAgICAgY2x1c3RlciA9IFYoY2x1c3Rlcl80X3BhZ2VfcmFuaykkc3ViZmllbGQsKQoKbm9kZXNfZnVsbF9kYXRhIHw+IAogIGZpbHRlcihjbHVzdGVyID09IDQpIHw+IAogIHNlbGVjdChmdWxsX25hbWUpIHw+IAogIG11dGF0ZShmdWxsX25hbWUgPSBzdHJfZXh0cmFjdChmdWxsX25hbWUsIFNQQyAlUiUgICMgUmVndWxhciBleHByZXNzaW9ucyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVfb3JfbW9yZShXUkQpICVSJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTUEMgJVIlIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uZV9vcl9tb3JlKG9yKFdSRCwgQU5ZX0NIQVIpKSksCiAgICAgICAgIGZ1bGxfbmFtZSA9IHN0cl9yZW1vdmUoZnVsbF9uYW1lLCBPUEVOX1BBUkVOICVSJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcGVhdGVkKERHVCwgNCkgJVIlIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ0xPU0VfUEFSRU4gJVIlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbmVfb3JfbW9yZShvcihXUkQsQU5ZX0NIQVIpKSksCiAgICAgICAgIGZ1bGxfbmFtZSA9IHN0cl90cmltKGZ1bGxfbmFtZSkpICB8PiAKICB1bm5lc3RfdG9rZW5zKG91dHB1dCA9IHdvcmQsIGlucHV0ID0gZnVsbF9uYW1lKSB8PiAKICBhbnRpX2pvaW4oc3RvcF93b3JkcykgfD4gCiAgIGZpbHRlcih3b3JkICE9ICJkb2kiLAogICAgICAgICAhc3RyX2RldGVjdCh3b3JkLCAiWzAtOV0iKSkgfD4gICMgV29TIGRhdGEKICBmaWx0ZXIod29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAiY2l0YXRpb24iKSwKICAgICAgICAgd29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAicmVzZWFyY2giKSwgCiAgICAgICAgIHdvcmQgPT0gc3RyX3JlbW92ZSh3b3JkLCBwYXR0ZXJuID0gImVkdWNhdGlvbiIpLCAKICAgICAgICAgd29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAiZGUiKSwKICAgICAgICAgd29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAibGEiKSwKICAgICAgICAgd29yZCA9PSBzdHJfcmVtb3ZlKHdvcmQsIHBhdHRlcm4gPSAicmVzIikpIHw+CiAgY291bnQod29yZCwgc29ydCA9IFRSVUUpIHw+IAogIHdpdGgod29yZGNsb3VkKHdvcmQsIAogICAgICAgICAgICAgICAgIG4sIAogICAgICAgICAgICAgICAgIHJhbmRvbS5vcmRlciA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICBtYXgud29yZHMgPSA1MCwgCiAgICAgICAgICAgICAgICAgY29sb3JzPXBhbCkpCmBgYAoKIyBFeHBvcnRpbmcgZmlsZXMKCmBgYHtyfQoKd3JpdGVfY3N2KHRhYmxlXzEsICJ0YWJsZV8xLmNzdiIpICMgRXhwb3J0aW5nIHRhYmxlIDEKd3JpdGVfY3N2KHdvc19zY29wdXNfdG90YWxfY291bnRyeSwgInRhYmxlXzJfLmNzdiIpICAjIEV4cG9ydGluZyB0YWJsZSAyCndyaXRlX2Nzdih3b3Nfc2NvcHVzX2F1dGhvcnMsICJ0YWJsZV8zLmNzdiIpICMgRXhwb3J0aW5nIHRhYmxlIDMKd3JpdGVfY3N2KHdvc19zY29wdXNfdG90YWxfam91cm5hbCwgInRhYmxlXzQuY3N2IikgIyBFeHBvcnRpbmcgdGFibGUgNAoKCndyaXRlX2NzdihsYW5ndWFnZXMsICJmaWd1cmVfMS5jc3YiKSAjIEV4cG9ydGluZyBkYXRhIGZpZ3VyZSAxIAp3cml0ZV9jc3YoZmlndXJlXzJfZGF0YSwgImZpZ3VyZV8yLmNzdiIpICMgRXhwb3J0aW5nIGRhdGEgZmlndXJlIDIKCndyaXRlLmdyYXBoKHdvc19zY29wdXNfdG9zJGdyYXBoLCAiY2l0YXRpb25fbmV0d29ya19mdWxsLmNzdiIsICJncmFwaG1sIikgIyBFeHBvcnRpbmcgZ3JhcGgKd3JpdGUuZ3JhcGgod29zX3Njb3B1c19jaXRhdGlvbl9uZXR3b3JrX2NsdXN0ZXJzLCAKICAgICAgICAgICAgIndvc19zY29wdXNfY2l0YXRpb25fbmV0d29ya19jbHVzdGVycy5ncmFwaG1sIiwgCiAgICAgICAgICAgICJncmFwaG1sIikKCndyaXRlLmNzdih0cmVlX29mX3NjaWVuY2UsICJ0cmVlX29mX3NjaWVuY2UuY3N2IikgIyBFeHBvcnRpbmcgVHJlZSBvZiBTY2llbmNlCgp3cml0ZS5jc3YoY2x1c3Rlcl8xX2RmLCAiY2x1c3Rlcl8xLmNzdiIpICMgRXhwb3J0aW5nIGNsdXN0ZXIgMQp3cml0ZS5jc3YoY2x1c3Rlcl8yX2RmLCAiY2x1c3Rlcl8yLmNzdiIpICMgRXhwb3J0aW5nIGNsdXN0ZXIgMgp3cml0ZS5jc3YoY2x1c3Rlcl8zX2RmLCAiY2x1c3Rlcl8zLmNzdiIpICMgRXhwb3J0aW5nIGNsdXN0ZXIgMwp3cml0ZS5jc3YoY2x1c3Rlcl80X2RmLCAiY2x1c3Rlcl80LmNzdiIpICMgRXhwb3J0aW5nIGNsdXN0ZXIgNAoKd3JpdGUuY3N2KG5vZGVzX2Z1bGxfZGF0YSwgIm5vZGVzX2Z1bGxfZGF0YS5jc3YiKSAjIEV4cG9ydGluZyBhbGwgbm9kZXMKYGBgCgo=