rm(list = ls())
#install.packages("sna")
library(openalexR)
library(tidyverse)
require(igraph)
g <- make_graph("Zachary")
plot(g)

gmat <- as_adjacency_matrix(g, type = "both", sparse = FALSE)
gmat
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17]
## [1,] 0 1 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0
## [2,] 1 0 1 1 0 0 0 1 0 0 0 0 0 1 0 0 0
## [3,] 1 1 0 1 0 0 0 1 1 1 0 0 0 1 0 0 0
## [4,] 1 1 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0
## [5,] 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0
## [6,] 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 1
## [7,] 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1
## [8,] 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
## [9,] 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [10,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [11,] 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0
## [12,] 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [13,] 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
## [14,] 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0
## [15,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [16,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [17,] 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0
## [18,] 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [19,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [20,] 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [21,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [22,] 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [23,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [24,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [25,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [26,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [27,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [28,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [29,] 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [30,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [31,] 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
## [32,] 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [33,] 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 1 0
## [34,] 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 1 0
## [,18] [,19] [,20] [,21] [,22] [,23] [,24] [,25] [,26] [,27] [,28] [,29] [,30] [,31] [,32]
## [1,] 1 0 1 0 1 0 0 0 0 0 0 0 0 0 1
## [2,] 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0
## [3,] 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0
## [4,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [5,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [6,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [7,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [8,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [9,] 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
## [10,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [11,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [12,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [13,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [14,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [15,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [16,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [17,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [18,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [19,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [20,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [21,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [22,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [23,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [24,] 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0
## [25,] 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1
## [26,] 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1
## [27,] 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
## [28,] 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
## [29,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
## [30,] 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0
## [31,] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## [32,] 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0
## [33,] 0 1 0 1 0 1 1 0 0 0 0 0 1 1 1
## [34,] 0 1 1 1 0 1 1 0 0 1 1 1 1 1 1
## [,33] [,34]
## [1,] 0 0
## [2,] 0 0
## [3,] 1 0
## [4,] 0 0
## [5,] 0 0
## [6,] 0 0
## [7,] 0 0
## [8,] 0 0
## [9,] 1 1
## [10,] 0 1
## [11,] 0 0
## [12,] 0 0
## [13,] 0 0
## [14,] 0 1
## [15,] 1 1
## [16,] 1 1
## [17,] 0 0
## [18,] 0 0
## [19,] 1 1
## [20,] 0 1
## [21,] 1 1
## [22,] 0 0
## [23,] 1 1
## [24,] 1 1
## [25,] 0 0
## [26,] 0 0
## [27,] 0 1
## [28,] 0 1
## [29,] 0 1
## [30,] 1 1
## [31,] 1 1
## [32,] 1 1
## [33,] 0 1
## [34,] 1 0
# changing V
V(g)$size = betweenness(g, normalized = T, directed = FALSE) * 60 + 15 #after some trial and error
plot(g, mode = "undirected")

set.seed(2345)
l <- layout_with_mds(g) #https://igraph.org/r/doc/layout_with_mds.html
plot(g, layout = l)

l #let us take a look at the coordinates
## [,1] [,2]
## [1,] 1.070931935 -0.172458113
## [2,] 0.732844464 0.754023309
## [3,] 0.100582299 0.397693607
## [4,] 0.708246655 0.570205545
## [5,] 1.816293170 -0.120778206
## [6,] 1.881329566 -0.135518854
## [7,] 1.881329566 -0.135518854
## [8,] 0.812606714 0.472619437
## [9,] -0.003769996 0.615513628
## [10,] -0.685680315 0.621065149
## [11,] 1.816293170 -0.120778206
## [12,] 1.621247830 -0.065820692
## [13,] 1.637845123 0.001789972
## [14,] 0.067317230 0.681421148
## [15,] -1.796316404 0.351417630
## [16,] -1.796316404 0.351417630
## [17,] 2.775260452 -0.124317652
## [18,] 1.616210024 0.182510197
## [19,] -1.796316404 0.351417630
## [20,] 0.048362858 0.566654982
## [21,] -1.796316404 0.351417630
## [22,] 1.616210024 0.182510197
## [23,] -1.796316404 0.351417630
## [24,] -1.891240567 -0.799574907
## [25,] -0.258345165 -2.006346563
## [26,] -0.360530857 -2.131642875
## [27,] -1.865177401 0.128596564
## [28,] -0.760226022 -0.529392331
## [29,] -0.710979936 -0.299960128
## [30,] -1.898426916 -0.149398746
## [31,] -0.568691923 0.804189411
## [32,] -0.048136037 -0.870967614
## [33,] -1.023681000 -0.035802363
## [34,] -1.146442924 -0.037605192
l[1, 1] <- 4
l[34, 1] <- -3.5
plot(g, layout = l)

## making network collaberations data, from JT's tutorial
fload <- function(filename) {
load(filename)
get(ls()[ls() != "filename"])
}
scholars <- fload("C:/Users/kalle/OneDrive/Documenten/REMA/Jaar 2/Social Networks/KS_labjournal/data/processed/scholars_20240924.rda")
#functie maken
fcolnet <- function(data = scholars, university = "RU", discipline = "sociology", waves = list(c(2015,
2018), c(2019, 2023)), type = c("first")) {
# step 1
demographics <- do.call(rbind.data.frame, data$demographics)
demographics <- demographics %>%
mutate(Universiteit1.22 = replace(Universiteit1.22, is.na(Universiteit1.22), ""), Universiteit2.22 = replace(Universiteit2.22,
is.na(Universiteit2.22), ""), Universiteit1.24 = replace(Universiteit1.24, is.na(Universiteit1.24),
""), Universiteit2.24 = replace(Universiteit2.24, is.na(Universiteit2.24), ""), discipline.22 = replace(discipline.22,
is.na(discipline.22), ""), discipline.24 = replace(discipline.24, is.na(discipline.24), ""))
sample <- which((demographics$Universiteit1.22 %in% university | demographics$Universiteit2.22 %in%
university | demographics$Universiteit1.24 %in% university | demographics$Universiteit2.24 %in%
university) & (demographics$discipline.22 %in% discipline | demographics$discipline.24 %in% discipline))
demographics_soc <- demographics[sample, ]
scholars_sel <- lapply(scholars, "[", sample)
# step 2
ids <- demographics_soc$au_id
nwaves <- length(waves)
nets <- array(0, dim = c(nwaves, length(ids), length(ids)), dimnames = list(wave = 1:nwaves, ids,
ids))
dimnames(nets)
# step 3
df_works <- tibble(works_id = unlist(lapply(scholars_sel$work, function(l) l$id)), works_author = unlist(lapply(scholars_sel$work,
function(l) l$author), recursive = FALSE), works_year = unlist(lapply(scholars_sel$work, function(l) l$publication_year),
recursive = FALSE))
df_works <- df_works[!duplicated(df_works), ]
# step 4
if (type == "first") {
for (j in 1:nwaves) {
df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
]
for (i in 1:nrow(df_works_w)) {
ego <- df_works_w$works_author[i][[1]]$au_id[1]
alters <- df_works_w$works_author[i][[1]]$au_id[-1]
if (sum(ids %in% ego) > 0 & sum(ids %in% alters) > 0) {
nets[j, which(ids %in% ego), which(ids %in% alters)] <- 1
}
}
}
}
if (type == "last") {
for (j in 1:nwaves) {
df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
]
for (i in 1:nrow(df_works_w)) {
ego <- rev(df_works_w$works_author[i][[1]]$au_id)[1]
alters <- rev(df_works_w$works_author[i][[1]]$au_id)[-1]
if (sum(ids %in% ego) > 0 & sum(ids %in% alters) > 0) {
nets[j, which(ids %in% ego), which(ids %in% alters)] <- 1
}
}
}
}
if (type == "all") {
for (j in 1:nwaves) {
df_works_w <- df_works[df_works$works_year >= waves[[j]][1] & df_works$works_year <= waves[[j]][2],
]
for (i in 1:nrow(df_works_w)) {
egos <- df_works_w$works_author[i][[1]]$au_id
if (sum(ids %in% egos) > 0) {
nets[j, which(ids %in% egos), which(ids %in% egos)] <- 1
}
}
}
}
output <- list()
output$data <- scholars_sel
output$nets <- nets
return(output)
}
Descriptive statistics
for the network
#functie gebruiken
data <- fcolnet(data = scholars,
university = "RU",
discipline = "sociology",
waves = list(c(2015, 2018), c(2019, 2023)),
type = c("all"))
#first wave
net_w1 <- data$nets[1,,]
diag(net_w1) <- 0
g <- graph_from_adjacency_matrix(net_w1, mode = "undirected", diag = FALSE)
#density
density <- edge_density(g)
density
## [1] 0.04326531
#degree centrality
#ego level
degree(g)
## https://openalex.org/A5011326378 https://openalex.org/A5014129369 https://openalex.org/A5023395007
## 0 3 0
## https://openalex.org/A5068642001 https://openalex.org/A5074062335 https://openalex.org/A5018242597
## 1 0 0
## https://openalex.org/A5030977100 https://openalex.org/A5007673492 https://openalex.org/A5016107698
## 3 7 1
## https://openalex.org/A5062608377 https://openalex.org/A5002388922 https://openalex.org/A5023494442
## 2 2 1
## https://openalex.org/A5046746723 https://openalex.org/A5017382943 https://openalex.org/A5035350135
## 0 0 16
## https://openalex.org/A5079372810 https://openalex.org/A5048988743 https://openalex.org/A5027461314
## 3 5 13
## https://openalex.org/A5035502020 https://openalex.org/A5087380803 https://openalex.org/A5066699568
## 6 4 4
## https://openalex.org/A5060015711 https://openalex.org/A5017017044 https://openalex.org/A5050987926
## 4 8 2
## https://openalex.org/A5019030264 https://openalex.org/A5009655338 https://openalex.org/A5026217132
## 0 0 0
## https://openalex.org/A5001803910 https://openalex.org/A5030092568 https://openalex.org/A5050683616
## 0 0 1
## https://openalex.org/A5031371982 https://openalex.org/A5023362052 https://openalex.org/A5071959536
## 0 0 1
## https://openalex.org/A5093927073 https://openalex.org/A5055096981 https://openalex.org/A5031002485
## 0 0 0
## https://openalex.org/A5020765315 https://openalex.org/A5065130106 https://openalex.org/A5080235042
## 1 0 0
## https://openalex.org/A5038009917 https://openalex.org/A5047687982 https://openalex.org/A5057934803
## 1 2 2
## https://openalex.org/A5063338887 https://openalex.org/A5045572082 https://openalex.org/A5085493990
## 2 2 0
## https://openalex.org/A5003892082 https://openalex.org/A5047911137 https://openalex.org/A5017637321
## 7 0 2
## https://openalex.org/A5068000059 https://openalex.org/A5013258554
## 0 0
#network level
mean(degree(g, mode = "all"))
## [1] 2.12
#transitivity
transitivity(g, type = "undirected")
## [1] 0.2743902
#plot
test_w1 <- igraph::graph_from_adjacency_matrix(
data$nets[1,,], #for this example I take the first wave of data. (thus I select the array of networks and take the first matrix)
mode = c("undirected"),
weighted = NULL,
diag = FALSE,
add.colnames = NULL,
add.rownames = NULL
)
## Warning: Same attribute for columns and rows, row names are ignored
plot(test_w1,
vertex.label = NA,
edge.width = 0.2,
edge.arrow.size =0.2)

### second wave
#duidelijk meer density, centrality en minder isolates.
net_w2 <- data$nets[2,,]
diag(net_w2) <- 0
g2 <- graph_from_adjacency_matrix(net_w2, mode = "undirected", diag = FALSE)
#density
density2 <- edge_density(g2)
density2
## [1] 0.07428571
#degree centrality
#ego level
degree (g2)
## https://openalex.org/A5011326378 https://openalex.org/A5014129369 https://openalex.org/A5023395007
## 0 2 1
## https://openalex.org/A5068642001 https://openalex.org/A5074062335 https://openalex.org/A5018242597
## 1 1 8
## https://openalex.org/A5030977100 https://openalex.org/A5007673492 https://openalex.org/A5016107698
## 3 9 5
## https://openalex.org/A5062608377 https://openalex.org/A5002388922 https://openalex.org/A5023494442
## 5 2 3
## https://openalex.org/A5046746723 https://openalex.org/A5017382943 https://openalex.org/A5035350135
## 3 0 15
## https://openalex.org/A5079372810 https://openalex.org/A5048988743 https://openalex.org/A5027461314
## 4 7 14
## https://openalex.org/A5035502020 https://openalex.org/A5087380803 https://openalex.org/A5066699568
## 13 8 6
## https://openalex.org/A5060015711 https://openalex.org/A5017017044 https://openalex.org/A5050987926
## 7 3 2
## https://openalex.org/A5019030264 https://openalex.org/A5009655338 https://openalex.org/A5026217132
## 0 2 2
## https://openalex.org/A5001803910 https://openalex.org/A5030092568 https://openalex.org/A5050683616
## 3 2 1
## https://openalex.org/A5031371982 https://openalex.org/A5023362052 https://openalex.org/A5071959536
## 2 2 2
## https://openalex.org/A5093927073 https://openalex.org/A5055096981 https://openalex.org/A5031002485
## 0 4 3
## https://openalex.org/A5020765315 https://openalex.org/A5065130106 https://openalex.org/A5080235042
## 4 3 3
## https://openalex.org/A5038009917 https://openalex.org/A5047687982 https://openalex.org/A5057934803
## 1 1 1
## https://openalex.org/A5063338887 https://openalex.org/A5045572082 https://openalex.org/A5085493990
## 2 4 3
## https://openalex.org/A5003892082 https://openalex.org/A5047911137 https://openalex.org/A5017637321
## 14 0 0
## https://openalex.org/A5068000059 https://openalex.org/A5013258554
## 1 0
#network level
mean(degree(g2, mode = "all"))
## [1] 3.64
#transitivity
transitivity(g2, type = "undirected")
## [1] 0.3226891
test_w2 <- igraph::graph_from_adjacency_matrix(
data$nets[2,,],
mode = c("undirected"),
weighted = NULL,
diag = FALSE,
add.colnames = NULL,
add.rownames = NULL
)
## Warning: Same attribute for columns and rows, row names are ignored
plot(test_w2,
vertex.label = NA,
edge.width = 0.2,
edge.arrow.size =0.2)

Ego
characteristics
# Scraping the # of citations of all papers published during per wave
df_scholars <- do.call(rbind, scholars$demographics)
mail = "kalle.stoffers@ru.nl"
#empty list
citations_per_wave <- list()
for (author in df_scholars$au_id[1:675]) {
#fetch papers per authors
papers <- oa_fetch(
entity = "works",
author.id = author,
mailto = mail)
# check if papers is NULL or has 0 rows
if (is.null(papers) || nrow(papers) == 0) {
# fill with 0 citations for both waves
citations <- tibble(
au_id = author,
citations_w1 = 0,
citations_w2 = 0
)
} else {
# wave 1 citations
citations_w1 <- papers |>
filter(publication_year >= 2015 & publication_year <= 2018) |>
summarise(citations_w1 = sum(cited_by_count, na.rm = TRUE))
# wave 2 citations
citations_w2 <- papers |>
filter(publication_year >= 2019 & publication_year <= 2023) |>
summarise(citations_w2 = sum(cited_by_count, na.rm = TRUE))
# handle case where one of the summaries might return 0 rows
if (nrow(citations_w1) == 0) citations_w1 <- tibble(citations_w1 = 0)
if (nrow(citations_w2) == 0) citations_w2 <- tibble(citations_w2 = 0)
#join the two
citations <- merge(citations_w1, citations_w2)
citations <- citations|>
mutate(au_id = author) |>
relocate(au_id)
}
citations_per_wave[[author]] <- citations
}
#merge met originele dataset
citations_df <- bind_rows(citations_per_wave)
df <- left_join(df_scholars, citations_df, by = "au_id")
fsave <- function(x, file = NULL, location = "./data/processed/") {
ifelse(!dir.exists("data"), dir.create("data"), FALSE)
ifelse(!dir.exists("data/processed"), dir.create("data/processed"), FALSE)
if (is.null(file))
file = deparse(substitute(x))
datename <- substr(gsub("[:-]", "", Sys.time()), 1, 8)
totalname <- paste(location, file, "_", datename, ".rda", sep = "")
save(x, file = totalname) #need to fix if file is reloaded as input name, not as x.
}
fsave(df)
#descriptives citations
df<- fload("~/REMA/Jaar 2/Social Networks/KS_labjournal/data/processed/df_20250929.rda")
summary(df$citations_w1)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0 0.0 45.0 256.8 264.0 17808.0
summary (df$citations_w2)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0 12.0 64.0 174.5 181.0 5030.0
#remove outlier
df<- df |> filter(citations_w1 <= 6000)
summary (df$citations_w2)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0 12.0 64.0 167.3 180.8 4836.0
df_long <- df|>
pivot_longer(cols = c(citations_w1, citations_w2),
names_to = "wave",
names_prefix = "citations_w",
values_to = "citations") |>
mutate(wave = as.factor(wave))
ggplot(df_long, aes(x = citations, color = wave)) + geom_density()

LS0tDQp0aXRsZTogIldlZWsgNCINCmF1dGhvcjogIkthbGxlIFN0b2ZmZXJzIg0KZGF0ZTogIjIwMjUtMDktMjYiDQpvdXRwdXQ6IGh0bWxfZG9jdW1lbnQNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQpgYGB7cn0NCnJtKGxpc3QgPSBscygpKQ0KDQojaW5zdGFsbC5wYWNrYWdlcygic25hIikNCmxpYnJhcnkob3BlbmFsZXhSKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpyZXF1aXJlKGlncmFwaCkNCg0KZyA8LSBtYWtlX2dyYXBoKCJaYWNoYXJ5IikNCnBsb3QoZykNCg0KZ21hdCA8LSBhc19hZGphY2VuY3lfbWF0cml4KGcsIHR5cGUgPSAiYm90aCIsIHNwYXJzZSA9IEZBTFNFKQ0KZ21hdA0KDQojIGNoYW5naW5nIFYNClYoZykkc2l6ZSA9IGJldHdlZW5uZXNzKGcsIG5vcm1hbGl6ZWQgPSBULCBkaXJlY3RlZCA9IEZBTFNFKSAqIDYwICsgMTUgICNhZnRlciBzb21lIHRyaWFsIGFuZCBlcnJvcg0KcGxvdChnLCBtb2RlID0gInVuZGlyZWN0ZWQiKQ0KDQpzZXQuc2VlZCgyMzQ1KQ0KbCA8LSBsYXlvdXRfd2l0aF9tZHMoZykgICNodHRwczovL2lncmFwaC5vcmcvci9kb2MvbGF5b3V0X3dpdGhfbWRzLmh0bWwNCnBsb3QoZywgbGF5b3V0ID0gbCkNCg0KbCAgI2xldCB1cyB0YWtlIGEgbG9vayBhdCB0aGUgY29vcmRpbmF0ZXMNCmxbMSwgMV0gPC0gNA0KbFszNCwgMV0gPC0gLTMuNQ0KcGxvdChnLCBsYXlvdXQgPSBsKQ0KDQoNCmBgYA0KDQpgYGB7cn0NCiMjIG1ha2luZyBuZXR3b3JrIGNvbGxhYmVyYXRpb25zIGRhdGEsIGZyb20gSlQncyB0dXRvcmlhbA0KDQoNCmZsb2FkIDwtIGZ1bmN0aW9uKGZpbGVuYW1lKSB7DQogICAgbG9hZChmaWxlbmFtZSkNCiAgICBnZXQobHMoKVtscygpICE9ICJmaWxlbmFtZSJdKQ0KfQ0KDQpzY2hvbGFycyA8LSBmbG9hZCgiQzovVXNlcnMva2FsbGUvT25lRHJpdmUvRG9jdW1lbnRlbi9SRU1BL0phYXIgMi9Tb2NpYWwgTmV0d29ya3MvS1NfbGFiam91cm5hbC9kYXRhL3Byb2Nlc3NlZC9zY2hvbGFyc18yMDI0MDkyNC5yZGEiKQ0KDQojZnVuY3RpZSBtYWtlbg0KZmNvbG5ldCA8LSBmdW5jdGlvbihkYXRhID0gc2Nob2xhcnMsIHVuaXZlcnNpdHkgPSAiUlUiLCBkaXNjaXBsaW5lID0gInNvY2lvbG9neSIsIHdhdmVzID0gbGlzdChjKDIwMTUsDQogICAgMjAxOCksIGMoMjAxOSwgMjAyMykpLCB0eXBlID0gYygiZmlyc3QiKSkgew0KDQogICAgIyBzdGVwIDENCiAgICBkZW1vZ3JhcGhpY3MgPC0gZG8uY2FsbChyYmluZC5kYXRhLmZyYW1lLCBkYXRhJGRlbW9ncmFwaGljcykNCiAgICBkZW1vZ3JhcGhpY3MgPC0gZGVtb2dyYXBoaWNzICU+JQ0KICAgICAgICBtdXRhdGUoVW5pdmVyc2l0ZWl0MS4yMiA9IHJlcGxhY2UoVW5pdmVyc2l0ZWl0MS4yMiwgaXMubmEoVW5pdmVyc2l0ZWl0MS4yMiksICIiKSwgVW5pdmVyc2l0ZWl0Mi4yMiA9IHJlcGxhY2UoVW5pdmVyc2l0ZWl0Mi4yMiwNCiAgICAgICAgICAgIGlzLm5hKFVuaXZlcnNpdGVpdDIuMjIpLCAiIiksIFVuaXZlcnNpdGVpdDEuMjQgPSByZXBsYWNlKFVuaXZlcnNpdGVpdDEuMjQsIGlzLm5hKFVuaXZlcnNpdGVpdDEuMjQpLA0KICAgICAgICAgICAgIiIpLCBVbml2ZXJzaXRlaXQyLjI0ID0gcmVwbGFjZShVbml2ZXJzaXRlaXQyLjI0LCBpcy5uYShVbml2ZXJzaXRlaXQyLjI0KSwgIiIpLCBkaXNjaXBsaW5lLjIyID0gcmVwbGFjZShkaXNjaXBsaW5lLjIyLA0KICAgICAgICAgICAgaXMubmEoZGlzY2lwbGluZS4yMiksICIiKSwgZGlzY2lwbGluZS4yNCA9IHJlcGxhY2UoZGlzY2lwbGluZS4yNCwgaXMubmEoZGlzY2lwbGluZS4yNCksICIiKSkNCg0KICAgIHNhbXBsZSA8LSB3aGljaCgoZGVtb2dyYXBoaWNzJFVuaXZlcnNpdGVpdDEuMjIgJWluJSB1bml2ZXJzaXR5IHwgZGVtb2dyYXBoaWNzJFVuaXZlcnNpdGVpdDIuMjIgJWluJQ0KICAgICAgICB1bml2ZXJzaXR5IHwgZGVtb2dyYXBoaWNzJFVuaXZlcnNpdGVpdDEuMjQgJWluJSB1bml2ZXJzaXR5IHwgZGVtb2dyYXBoaWNzJFVuaXZlcnNpdGVpdDIuMjQgJWluJQ0KICAgICAgICB1bml2ZXJzaXR5KSAmIChkZW1vZ3JhcGhpY3MkZGlzY2lwbGluZS4yMiAlaW4lIGRpc2NpcGxpbmUgfCBkZW1vZ3JhcGhpY3MkZGlzY2lwbGluZS4yNCAlaW4lIGRpc2NpcGxpbmUpKQ0KDQogICAgZGVtb2dyYXBoaWNzX3NvYyA8LSBkZW1vZ3JhcGhpY3Nbc2FtcGxlLCBdDQogICAgc2Nob2xhcnNfc2VsIDwtIGxhcHBseShzY2hvbGFycywgIlsiLCBzYW1wbGUpDQoNCiAgICAjIHN0ZXAgMg0KICAgIGlkcyA8LSBkZW1vZ3JhcGhpY3Nfc29jJGF1X2lkDQogICAgbndhdmVzIDwtIGxlbmd0aCh3YXZlcykNCiAgICBuZXRzIDwtIGFycmF5KDAsIGRpbSA9IGMobndhdmVzLCBsZW5ndGgoaWRzKSwgbGVuZ3RoKGlkcykpLCBkaW1uYW1lcyA9IGxpc3Qod2F2ZSA9IDE6bndhdmVzLCBpZHMsDQogICAgICAgIGlkcykpDQogICAgZGltbmFtZXMobmV0cykNCg0KICAgICMgc3RlcCAzDQogICAgZGZfd29ya3MgPC0gdGliYmxlKHdvcmtzX2lkID0gdW5saXN0KGxhcHBseShzY2hvbGFyc19zZWwkd29yaywgZnVuY3Rpb24obCkgbCRpZCkpLCB3b3Jrc19hdXRob3IgPSB1bmxpc3QobGFwcGx5KHNjaG9sYXJzX3NlbCR3b3JrLA0KICAgICAgICBmdW5jdGlvbihsKSBsJGF1dGhvciksIHJlY3Vyc2l2ZSA9IEZBTFNFKSwgd29ya3NfeWVhciA9IHVubGlzdChsYXBwbHkoc2Nob2xhcnNfc2VsJHdvcmssIGZ1bmN0aW9uKGwpIGwkcHVibGljYXRpb25feWVhciksDQogICAgICAgIHJlY3Vyc2l2ZSA9IEZBTFNFKSkNCg0KICAgIGRmX3dvcmtzIDwtIGRmX3dvcmtzWyFkdXBsaWNhdGVkKGRmX3dvcmtzKSwgXQ0KDQogICAgIyBzdGVwIDQNCiAgICBpZiAodHlwZSA9PSAiZmlyc3QiKSB7DQogICAgICAgIGZvciAoaiBpbiAxOm53YXZlcykgew0KICAgICAgICAgICAgZGZfd29ya3NfdyA8LSBkZl93b3Jrc1tkZl93b3JrcyR3b3Jrc195ZWFyID49IHdhdmVzW1tqXV1bMV0gJiBkZl93b3JrcyR3b3Jrc195ZWFyIDw9IHdhdmVzW1tqXV1bMl0sDQogICAgICAgICAgICAgICAgXQ0KICAgICAgICAgICAgZm9yIChpIGluIDE6bnJvdyhkZl93b3Jrc193KSkgew0KICAgICAgICAgICAgICAgIGVnbyA8LSBkZl93b3Jrc193JHdvcmtzX2F1dGhvcltpXVtbMV1dJGF1X2lkWzFdDQogICAgICAgICAgICAgICAgYWx0ZXJzIDwtIGRmX3dvcmtzX3ckd29ya3NfYXV0aG9yW2ldW1sxXV0kYXVfaWRbLTFdDQogICAgICAgICAgICAgICAgaWYgKHN1bShpZHMgJWluJSBlZ28pID4gMCAmIHN1bShpZHMgJWluJSBhbHRlcnMpID4gMCkgew0KICAgICAgICAgICAgICAgICAgbmV0c1tqLCB3aGljaChpZHMgJWluJSBlZ28pLCB3aGljaChpZHMgJWluJSBhbHRlcnMpXSA8LSAxDQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfQ0KDQogICAgaWYgKHR5cGUgPT0gImxhc3QiKSB7DQogICAgICAgIGZvciAoaiBpbiAxOm53YXZlcykgew0KICAgICAgICAgICAgZGZfd29ya3NfdyA8LSBkZl93b3Jrc1tkZl93b3JrcyR3b3Jrc195ZWFyID49IHdhdmVzW1tqXV1bMV0gJiBkZl93b3JrcyR3b3Jrc195ZWFyIDw9IHdhdmVzW1tqXV1bMl0sDQogICAgICAgICAgICAgICAgXQ0KICAgICAgICAgICAgZm9yIChpIGluIDE6bnJvdyhkZl93b3Jrc193KSkgew0KICAgICAgICAgICAgICAgIGVnbyA8LSByZXYoZGZfd29ya3NfdyR3b3Jrc19hdXRob3JbaV1bWzFdXSRhdV9pZClbMV0NCiAgICAgICAgICAgICAgICBhbHRlcnMgPC0gcmV2KGRmX3dvcmtzX3ckd29ya3NfYXV0aG9yW2ldW1sxXV0kYXVfaWQpWy0xXQ0KICAgICAgICAgICAgICAgIGlmIChzdW0oaWRzICVpbiUgZWdvKSA+IDAgJiBzdW0oaWRzICVpbiUgYWx0ZXJzKSA+IDApIHsNCiAgICAgICAgICAgICAgICAgIG5ldHNbaiwgd2hpY2goaWRzICVpbiUgZWdvKSwgd2hpY2goaWRzICVpbiUgYWx0ZXJzKV0gPC0gMQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH0NCg0KICAgIGlmICh0eXBlID09ICJhbGwiKSB7DQogICAgICAgIGZvciAoaiBpbiAxOm53YXZlcykgew0KICAgICAgICAgICAgZGZfd29ya3NfdyA8LSBkZl93b3Jrc1tkZl93b3JrcyR3b3Jrc195ZWFyID49IHdhdmVzW1tqXV1bMV0gJiBkZl93b3JrcyR3b3Jrc195ZWFyIDw9IHdhdmVzW1tqXV1bMl0sDQogICAgICAgICAgICAgICAgXQ0KICAgICAgICAgICAgZm9yIChpIGluIDE6bnJvdyhkZl93b3Jrc193KSkgew0KICAgICAgICAgICAgICAgIGVnb3MgPC0gZGZfd29ya3NfdyR3b3Jrc19hdXRob3JbaV1bWzFdXSRhdV9pZA0KICAgICAgICAgICAgICAgIGlmIChzdW0oaWRzICVpbiUgZWdvcykgPiAwKSB7DQogICAgICAgICAgICAgICAgICBuZXRzW2osIHdoaWNoKGlkcyAlaW4lIGVnb3MpLCB3aGljaChpZHMgJWluJSBlZ29zKV0gPC0gMQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgIH0NCiAgICBvdXRwdXQgPC0gbGlzdCgpDQogICAgb3V0cHV0JGRhdGEgPC0gc2Nob2xhcnNfc2VsDQogICAgb3V0cHV0JG5ldHMgPC0gbmV0cw0KICAgIHJldHVybihvdXRwdXQpDQp9DQoNCmBgYA0KDQojIERlc2NyaXB0aXZlIHN0YXRpc3RpY3MgZm9yIHRoZSBuZXR3b3JrDQoNCmBgYHtyfQ0KI2Z1bmN0aWUgZ2VicnVpa2VuDQoNCmRhdGEgPC0gZmNvbG5ldChkYXRhID0gc2Nob2xhcnMsIA0KICAgICAgICAgICAgICAgIHVuaXZlcnNpdHkgPSAiUlUiLCANCiAgICAgICAgICAgICAgICBkaXNjaXBsaW5lID0gInNvY2lvbG9neSIsIA0KICAgICAgICAgICAgICAgIHdhdmVzID0gbGlzdChjKDIwMTUsIDIwMTgpLCBjKDIwMTksIDIwMjMpKSwgDQogICAgICAgICAgICAgICAgdHlwZSA9IGMoImFsbCIpKQ0KDQojZmlyc3Qgd2F2ZQ0KbmV0X3cxIDwtIGRhdGEkbmV0c1sxLCxdDQpkaWFnKG5ldF93MSkgPC0gMA0KZyA8LSBncmFwaF9mcm9tX2FkamFjZW5jeV9tYXRyaXgobmV0X3cxLCBtb2RlID0gInVuZGlyZWN0ZWQiLCBkaWFnID0gRkFMU0UpDQoNCiNkZW5zaXR5DQpkZW5zaXR5IDwtIGVkZ2VfZGVuc2l0eShnKQ0KZGVuc2l0eQ0KDQoNCiNkZWdyZWUgY2VudHJhbGl0eQ0KI2VnbyBsZXZlbA0KZGVncmVlKGcpDQoNCiNuZXR3b3JrIGxldmVsDQptZWFuKGRlZ3JlZShnLCBtb2RlID0gImFsbCIpKQ0KDQoNCiN0cmFuc2l0aXZpdHkNCnRyYW5zaXRpdml0eShnLCB0eXBlID0gInVuZGlyZWN0ZWQiKQ0KDQoNCiNwbG90DQp0ZXN0X3cxIDwtIGlncmFwaDo6Z3JhcGhfZnJvbV9hZGphY2VuY3lfbWF0cml4KA0KICBkYXRhJG5ldHNbMSwsXSwgI2ZvciB0aGlzIGV4YW1wbGUgSSB0YWtlIHRoZSBmaXJzdCB3YXZlIG9mIGRhdGEuICh0aHVzIEkgc2VsZWN0IHRoZSBhcnJheSBvZiBuZXR3b3JrcyBhbmQgdGFrZSB0aGUgZmlyc3QgbWF0cml4KQ0KICBtb2RlID0gYygidW5kaXJlY3RlZCIpLA0KICB3ZWlnaHRlZCA9IE5VTEwsDQogIGRpYWcgPSBGQUxTRSwNCiAgYWRkLmNvbG5hbWVzID0gTlVMTCwNCiAgYWRkLnJvd25hbWVzID0gTlVMTA0KKQ0KDQpwbG90KHRlc3RfdzEsDQogIHZlcnRleC5sYWJlbCA9IE5BLA0KICBlZGdlLndpZHRoID0gMC4yLA0KICBlZGdlLmFycm93LnNpemUgPTAuMikNCg0KDQojIyMgc2Vjb25kIHdhdmUNCg0KI2R1aWRlbGlqayBtZWVyIGRlbnNpdHksIGNlbnRyYWxpdHkgZW4gbWluZGVyIGlzb2xhdGVzLg0KDQpuZXRfdzIgPC0gZGF0YSRuZXRzWzIsLF0NCmRpYWcobmV0X3cyKSA8LSAwDQpnMiA8LSBncmFwaF9mcm9tX2FkamFjZW5jeV9tYXRyaXgobmV0X3cyLCBtb2RlID0gInVuZGlyZWN0ZWQiLCBkaWFnID0gRkFMU0UpDQoNCiNkZW5zaXR5DQpkZW5zaXR5MiA8LSBlZGdlX2RlbnNpdHkoZzIpDQpkZW5zaXR5Mg0KDQoNCiNkZWdyZWUgY2VudHJhbGl0eQ0KI2VnbyBsZXZlbA0KZGVncmVlIChnMikNCg0KI25ldHdvcmsgbGV2ZWwNCm1lYW4oZGVncmVlKGcyLCBtb2RlID0gImFsbCIpKQ0KDQoNCiN0cmFuc2l0aXZpdHkNCnRyYW5zaXRpdml0eShnMiwgdHlwZSA9ICJ1bmRpcmVjdGVkIikNCg0KDQoNCg0KdGVzdF93MiA8LSBpZ3JhcGg6OmdyYXBoX2Zyb21fYWRqYWNlbmN5X21hdHJpeCgNCiAgZGF0YSRuZXRzWzIsLF0sDQogIG1vZGUgPSBjKCJ1bmRpcmVjdGVkIiksDQogIHdlaWdodGVkID0gTlVMTCwNCiAgZGlhZyA9IEZBTFNFLA0KICBhZGQuY29sbmFtZXMgPSBOVUxMLA0KICBhZGQucm93bmFtZXMgPSBOVUxMDQopDQoNCnBsb3QodGVzdF93MiwNCiAgdmVydGV4LmxhYmVsID0gTkEsDQogIGVkZ2Uud2lkdGggPSAwLjIsDQogIGVkZ2UuYXJyb3cuc2l6ZSA9MC4yKQ0KDQoNCmBgYA0KDQojIEVnbyBjaGFyYWN0ZXJpc3RpY3MNCg0KYGBge3IsIGV2YWw9RkFMU0UsIGVjaG89VFJVRX0NCiMgU2NyYXBpbmcgdGhlICMgb2YgY2l0YXRpb25zIG9mIGFsbCBwYXBlcnMgcHVibGlzaGVkIGR1cmluZyBwZXIgd2F2ZSANCg0KDQpkZl9zY2hvbGFycyA8LSBkby5jYWxsKHJiaW5kLCBzY2hvbGFycyRkZW1vZ3JhcGhpY3MpDQoNCm1haWwgPSAia2FsbGUuc3RvZmZlcnNAcnUubmwiDQoNCg0KI2VtcHR5IGxpc3QNCmNpdGF0aW9uc19wZXJfd2F2ZSA8LSBsaXN0KCkNCg0KDQpmb3IgKGF1dGhvciBpbiBkZl9zY2hvbGFycyRhdV9pZFsxOjY3NV0pIHsNCg0KI2ZldGNoIHBhcGVycyBwZXIgYXV0aG9ycw0KcGFwZXJzIDwtIG9hX2ZldGNoKA0KICBlbnRpdHkgPSAid29ya3MiLA0KICBhdXRob3IuaWQgPSBhdXRob3IsDQogIG1haWx0byA9IG1haWwpDQoNCiMgY2hlY2sgaWYgcGFwZXJzIGlzIE5VTEwgb3IgaGFzIDAgcm93cw0KICBpZiAoaXMubnVsbChwYXBlcnMpIHx8IG5yb3cocGFwZXJzKSA9PSAwKSB7DQogICAgIyBmaWxsIHdpdGggMCBjaXRhdGlvbnMgZm9yIGJvdGggd2F2ZXMNCiAgICBjaXRhdGlvbnMgPC0gdGliYmxlKA0KICAgICAgYXVfaWQgPSBhdXRob3IsDQogICAgICBjaXRhdGlvbnNfdzEgPSAwLA0KICAgICAgY2l0YXRpb25zX3cyID0gMA0KICAgICkNCiAgfSBlbHNlIHsNCiAgICAjIHdhdmUgMSBjaXRhdGlvbnMNCiAgICBjaXRhdGlvbnNfdzEgPC0gcGFwZXJzIHw+DQogICAgICBmaWx0ZXIocHVibGljYXRpb25feWVhciA+PSAyMDE1ICYgcHVibGljYXRpb25feWVhciA8PSAyMDE4KSB8Pg0KICAgICAgc3VtbWFyaXNlKGNpdGF0aW9uc193MSA9IHN1bShjaXRlZF9ieV9jb3VudCwgbmEucm0gPSBUUlVFKSkNCg0KICAgICMgd2F2ZSAyIGNpdGF0aW9ucw0KICAgIGNpdGF0aW9uc193MiA8LSBwYXBlcnMgfD4NCiAgICAgIGZpbHRlcihwdWJsaWNhdGlvbl95ZWFyID49IDIwMTkgJiBwdWJsaWNhdGlvbl95ZWFyIDw9IDIwMjMpIHw+DQogICAgICBzdW1tYXJpc2UoY2l0YXRpb25zX3cyID0gc3VtKGNpdGVkX2J5X2NvdW50LCBuYS5ybSA9IFRSVUUpKQ0KDQogICAgIyBoYW5kbGUgY2FzZSB3aGVyZSBvbmUgb2YgdGhlIHN1bW1hcmllcyBtaWdodCByZXR1cm4gMCByb3dzDQogICAgaWYgKG5yb3coY2l0YXRpb25zX3cxKSA9PSAwKSBjaXRhdGlvbnNfdzEgPC0gdGliYmxlKGNpdGF0aW9uc193MSA9IDApDQogICAgaWYgKG5yb3coY2l0YXRpb25zX3cyKSA9PSAwKSBjaXRhdGlvbnNfdzIgPC0gdGliYmxlKGNpdGF0aW9uc193MiA9IDApDQoNCiNqb2luIHRoZSB0d28NCmNpdGF0aW9ucyA8LSBtZXJnZShjaXRhdGlvbnNfdzEsIGNpdGF0aW9uc193MikNCg0KY2l0YXRpb25zIDwtIGNpdGF0aW9uc3w+DQogIG11dGF0ZShhdV9pZCA9IGF1dGhvcikgfD4NCiAgcmVsb2NhdGUoYXVfaWQpDQp9DQogIA0KY2l0YXRpb25zX3Blcl93YXZlW1thdXRob3JdXSA8LSBjaXRhdGlvbnMNCg0KfQ0KICANCg0KI21lcmdlIG1ldCBvcmlnaW5lbGUgZGF0YXNldA0KY2l0YXRpb25zX2RmIDwtIGJpbmRfcm93cyhjaXRhdGlvbnNfcGVyX3dhdmUpDQoNCmRmIDwtIGxlZnRfam9pbihkZl9zY2hvbGFycywgY2l0YXRpb25zX2RmLCBieSA9ICJhdV9pZCIpDQoNCg0KZnNhdmUgPC0gZnVuY3Rpb24oeCwgZmlsZSA9IE5VTEwsIGxvY2F0aW9uID0gIi4vZGF0YS9wcm9jZXNzZWQvIikgew0KICAgIGlmZWxzZSghZGlyLmV4aXN0cygiZGF0YSIpLCBkaXIuY3JlYXRlKCJkYXRhIiksIEZBTFNFKQ0KICAgIGlmZWxzZSghZGlyLmV4aXN0cygiZGF0YS9wcm9jZXNzZWQiKSwgZGlyLmNyZWF0ZSgiZGF0YS9wcm9jZXNzZWQiKSwgRkFMU0UpDQogICAgaWYgKGlzLm51bGwoZmlsZSkpDQogICAgICAgIGZpbGUgPSBkZXBhcnNlKHN1YnN0aXR1dGUoeCkpDQogICAgZGF0ZW5hbWUgPC0gc3Vic3RyKGdzdWIoIls6LV0iLCAiIiwgU3lzLnRpbWUoKSksIDEsIDgpDQogICAgdG90YWxuYW1lIDwtIHBhc3RlKGxvY2F0aW9uLCBmaWxlLCAiXyIsIGRhdGVuYW1lLCAiLnJkYSIsIHNlcCA9ICIiKQ0KICAgIHNhdmUoeCwgZmlsZSA9IHRvdGFsbmFtZSkgICNuZWVkIHRvIGZpeCBpZiBmaWxlIGlzIHJlbG9hZGVkIGFzIGlucHV0IG5hbWUsIG5vdCBhcyB4LiANCn0NCg0KZnNhdmUoZGYpDQoNCmBgYA0KDQpgYGB7cn0NCiNkZXNjcmlwdGl2ZXMgY2l0YXRpb25zDQoNCmRmPC0gZmxvYWQoIn4vUkVNQS9KYWFyIDIvU29jaWFsIE5ldHdvcmtzL0tTX2xhYmpvdXJuYWwvZGF0YS9wcm9jZXNzZWQvZGZfMjAyNTA5MjkucmRhIikNCg0KDQpzdW1tYXJ5KGRmJGNpdGF0aW9uc193MSkNCnN1bW1hcnkgKGRmJGNpdGF0aW9uc193MikNCg0KI3JlbW92ZSBvdXRsaWVyDQpkZjwtIGRmIHw+IGZpbHRlcihjaXRhdGlvbnNfdzEgPD0gNjAwMCkNCnN1bW1hcnkgKGRmJGNpdGF0aW9uc193MikNCg0KZGZfbG9uZyA8LSBkZnw+DQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhjaXRhdGlvbnNfdzEsIGNpdGF0aW9uc193MiksDQogICAgICAgICAgICAgICBuYW1lc190byA9ICJ3YXZlIiwNCiAgICAgICAgICAgICAgIG5hbWVzX3ByZWZpeCA9ICJjaXRhdGlvbnNfdyIsDQogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiY2l0YXRpb25zIikgfD4NCiAgbXV0YXRlKHdhdmUgPSBhcy5mYWN0b3Iod2F2ZSkpDQoNCmdncGxvdChkZl9sb25nLCBhZXMoeCA9IGNpdGF0aW9ucywgY29sb3IgPSB3YXZlKSkgKyBnZW9tX2RlbnNpdHkoKQ0KDQpgYGANCg==