Demografice
## Pie chart
Data %>%
mutate(Gen = as.factor(as.character(gen))) %>%
mutate(Gen = forcats::fct_recode(Gen, "femin" = "f", "masculin" = "m")) %>%
group_by(Gen) %>%
dplyr::summarise(counts = n()) %>%
mutate(prop = round(counts*100/sum(counts), 1),
lab.ypos = cumsum(prop) - .5*prop,
Percent = paste0(prop, " %")) %>%
ggpubr::ggpie(x = "prop", label = "Percent",
fill = "Gen", color = "white",
lab.pos = "in", lab.font = list(color = "white"),
palette = "grey")
## Dodged Bar plot of Age and Gender
Data %>%
mutate(Varta_categ = cut(varsta,
breaks = c(-Inf, 6, 8, 10, 12, 14, 16, Inf),
labels=c("5-6", "6-8", "8-10", "10-12", "12-14", "14-16", "16-18"),
right = FALSE)) %>%
mutate(Varta_categ = as.factor(Varta_categ),
Gen = as.factor(as.character(gen))) %>%
mutate(Gen = forcats::fct_recode(Gen, "femin" = "f", "masculin" = "m")) %>%
dplyr::count(Varta_categ, Gen) %>% # Group by, then count number in each group
mutate(pct = prop.table(n)) %>% # Calculate percent within each var
ggplot(aes(x = Varta_categ, y = pct, fill = Gen, label = scales::percent(pct))) +
geom_col(position = 'dodge') +
geom_text(position = position_dodge(width = .9), # move to center of bars
vjust = -0.5, # nudge above top of bar
size = 3) +
scale_y_continuous(labels = scales::percent) +
ggtitle("") +
xlab("Varsta") + ylab("Percentage %") +
guides(fill = guide_legend(title = "Gen", ncol = 1)) +
scale_fill_grey(start = 0.8, end = 0.2, na.value = "red", aesthetics = "fill") +
theme(legend.position = "right", legend.direction = "vertical",
legend.justification = c(0, 1), panel.border = element_rect(fill = NA, colour = "black"))
GCIC
# Data[str_detect(colnames(Data), fixed("gci", ignore_case=TRUE))] # items
Data_gci <- Data[, c(sprintf("gci_%d", 1:14), "OpenC", "CloseC", "centru")]
labels_gci <-
c("Foarte neadevărat",
"Neadevărat",
"Un pic neadevărat / Un pic adevărat",
"Adevărat",
"Foarte adevărat")
itemtext_gci <-
c("1. Oamenii de la centru se poartă frumos cu mine.",
"2. Am încredere în oamenii din centru.",
"3. Oamenii de la centru mă înţeleg.",
"4. Atunci când mă plâng de ceva, oamenii din centru mă iau în serios.",
"5. Oamenii de la centru sunt corecți.",
"6. Simt că aici, la centru, lucrez la îndeplinirea scopurilor mele.",
"7. În acest centru sunt întotdeauna destui oameni care să mă ajute.",
"8. Oamenii din centru se țin de cuvânt.",
"9. Pot să cer ajutor de la oamenii din centru atunci când am nevoie.",
"10. În acest centru, copiii au încredere unii în alții.",
"11. Aici, poți să ai încredere în toată lumea.",
"12. Haosul și gălăgia din centru mă înnebunesc.",
"13. Sunt prea mulți copii aici.",
"14. Oamenii de la centru sunt adesea prea ocupați ca să mă ajute.")
Data_gci <-
Data_gci %>%
mutate_at(vars(sprintf("gci_%d", 1:14)), ~as.factor(as.character(.))) %>%
rename_at(vars(sprintf("gci_%d", 1:14)), ~itemtext_gci) %>%
rename_at(vars("OpenC", "CloseC"), ~c("Climat deschis", "Climat închis")) %>%
dplyr::rename(Centru = centru)
# Plots # library(likert)
Likertobj_gci <- likert::likert(Data_gci[, 1:14], nlevels = 5) # here are percentages
plot(Likertobj_gci, type = "bar",
centered = TRUE, center = 3, include.center = TRUE, # "3" is neutral
wrap = 30, low.color = 'burlywood', high.color = 'maroon',
group.order = names(Data_gci[, 1:14])) +
ylab("Procent") +
guides(fill = guide_legend(nrow = 1, title = "Răspuns")) +
geom_vline(xintercept = 5.51)
Data_gci %>%
select("Climat deschis", "Climat închis") %>%
gather() %>%
rename_at(vars("key", "value"), ~c("Var", "Scor")) %>%
ggpubr::ggviolin("Var", "Scor", fill = "Var",
palette = c("#00AFBB", "#FC4E07"),
add = "boxplot", add.params = list(fill = "white"),
xlab = "", legend = "none") +
stat_summary(fun.data = mean_se, colour = "darkred")
Data_gci %>%
select("Climat deschis", "Climat închis", "Centru") %>%
gather(key ="Var", value = "Scor", -Centru) %>%
mutate(Centru = as.factor(Centru)) %>%
ggpubr::ggviolin("Var", "Scor", fill = "Var",
palette = c("#00AFBB", "#FC4E07"),
add = "boxplot", add.params = list(fill = "white"),
xlab = "", legend = "none",
facet.by = "Centru") +
stat_summary(fun.data = mean_se, colour = "darkred")
ASCQ
Data_ascq <-
Data %>%
dplyr::select(sprintf("asc_%d", 1:15), c("ASecur", "AAnxio", "AAvoid", "ASCQ_f", "centru")) %>%
dplyr::rename(Centru = centru) %>%
mutate(
ASCQ_f = forcats::fct_recode(ASCQ_f,
"Sec" = "Secur",
"Sec și Anx" = "Secur&Anxio",
"Anx" = "Anxio",
"Evit" = "Avoid",
"Sec și Evit" = "Secur&Avoid",
"Anx și Evit" = "Anxio&Avoid",
"Sec, Anx, Evit" = "Secur&Anxio&Avoid"),
ASCQ_f = fct_explicit_na(ASCQ_f, "lipsă"))
# Create a custom color scale for all ASCQ graphs
library(RColorBrewer)
myColors <- brewer.pal(9,"Set1")
names(myColors) <- levels(Data_ascq$ASCQ_f)
colScale <- scale_colour_manual(name = "ASCQ_f", values = myColors)
# Plot
ggplot(Data_ascq, aes(x = forcats::fct_infreq(ASCQ_f), fill = ASCQ_f)) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
geom_text(aes(y = ((..count..)/sum(..count..)),
label = scales::percent((..count..)/sum(..count..))),
stat = "count", vjust = -0.25) +
scale_y_continuous(labels = percent) +
labs(title = "", y = "Procent", x = "Tip Atașament") +
guides(fill = FALSE) + colScale # color scale here keep consistency of color with factor level
ggplot(Data_ascq, aes(x = forcats::fct_infreq(ASCQ_f), fill = ASCQ_f)) +
facet_wrap(~Centru, scales = "free", ncol = 2) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
geom_text(aes(y = ((..count..)/sum(..count..)),
label = scales::percent((..count..)/sum(..count..))),
stat = "count", vjust = -0.25) +
scale_y_continuous(labels = percent) +
labs(title = "", y = "Procent", x = "") +
guides(fill = FALSE) + colScale + # color scale here keep consistency of color with factor level
theme(axis.text.x = element_text(angle = 90, hjust = 1))
ACE
# Data$sec2_1 is redundant because all should be 1, even tough there are 403 NA and 872 of 1
Ace_col_names <- c(sprintf("sec1_%d", 1:10), sprintf("sec2_%d", 2:9))
Ace_new_names <- c("divort", "incarcerare", "boala mintala", "amenintare", "umilire",
"abuz sexual", "lipsuri", "abuz fizic", "adictie", "nesiguranta",
"bullying", "deces", "emigrare", "boala", "violenta",
"rautate", "politie", "abuz partener")
# Plot function and Data function
ace_plot <- function(df){
ggplot(df, aes(x = variable, y = percent, fill = variable)) +
geom_bar(stat = "identity") +
geom_text(aes(label = paste0(round(percent), "%")), vjust = -0.25) +
guides(fill=FALSE) +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
ylab("Percentage") + xlab("")
}
ace_data <- function(df, ace_levels, filter_col, filter_level){
filter_col <- rlang::enquo(filter_col)
df %>%
filter(!!filter_col %in% filter_level) %>%
select(Ace_col_names) %>%
summarise_all(funs(sum(!is.na(.)) / length(.) * 100)) %>%
gather(variable, percent) %>%
mutate(variable = stringr::str_replace(variable, Ace_col_names, Ace_new_names)) %>%
arrange(desc(percent)) %>%
mutate(variable = factor(variable, ace_levels))
}
# ACEs data & plots
Data_ACE <-
Data %>% # barplot(colSums(Data[, Ace_col_names], na.rm = TRUE))
select(Ace_col_names) %>%
summarise_all(funs(sum(!is.na(.)) / length(.) * 100)) %>%
gather(variable, percent) %>%
mutate(variable = stringr::str_replace(variable, Ace_col_names, Ace_new_names)) %>%
arrange(desc(percent)) %>%
mutate(variable = factor(variable, variable)) # this makes levels order match row order!
ace_levels <- levels(Data_ACE$variable)
ace_plot1 <-
Data_ACE %>%
ace_plot() +
ggtitle("ACE")
ace_plot2 <-
ace_data(Data, ace_levels, gen, filter_level = "f") %>%
ace_plot() +
ggtitle("ACE - fete")
ace_plot3 <-
ace_data(Data, ace_levels, gen, filter_level = "m") %>%
ace_plot() +
ggtitle("ACE - băieți")
ace_plot4 <-
ace_data(Data, ace_levels, tip_chestionar, filter_level = c("5-8ani", "5-8intarziere")) %>%
ace_plot() +
ggtitle("ACE - 5-8 ani")
ace_plot5 <-
ace_data(Data, ace_levels, tip_chestionar, filter_level = "9-18ani") %>%
ace_plot() +
ggtitle("ACE - 9-18 ani")
ggpubr::ggarrange(ace_plot1,
ggarrange(ace_plot2, ace_plot3, ncol = 2, labels = c("B", "C")),
ggarrange(ace_plot4, ace_plot5, ncol = 2, labels = c("C", "D")),
nrow = 3,
labels = "A")
Session Info
R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 8.1 x64 (build 9600)
Matrix products: default
locale:
[1] LC_COLLATE=Romanian_Romania.1250 LC_CTYPE=Romanian_Romania.1250 LC_MONETARY=Romanian_Romania.1250 LC_NUMERIC=C
[5] LC_TIME=Romanian_Romania.1250
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] RColorBrewer_1.1-2 GGally_1.4.0 Hmisc_4.1-1 Formula_1.2-3 survival_2.44-1.1
[6] lattice_0.20-38 rio_0.5.16 scales_1.0.0 ggpubr_0.2 magrittr_1.5
[11] PerformanceAnalytics_1.5.2 xts_0.11-2 zoo_1.8-4 tadaatoolbox_0.16.1 summarytools_0.8.8
[16] broom_0.5.2 psych_1.8.12 forcats_0.4.0 stringr_1.4.0 dplyr_0.8.3
[21] purrr_0.3.2 readr_1.3.1 tidyr_1.0.0 tibble_2.1.3 ggplot2_3.2.1
[26] tidyverse_1.2.1 papaja_0.1.0.9842 kableExtra_0.9.0 knitr_1.25 pacman_0.5.1
loaded via a namespace (and not attached):
[1] colorspace_1.4-1 pryr_0.1.4 ellipsis_0.3.0 htmlTable_1.12 base64enc_0.1-3 rstudioapi_0.8 mvtnorm_1.0-11
[8] lubridate_1.7.4 xml2_1.2.0 codetools_0.2-16 splines_3.6.1 mnormt_1.5-5 zeallot_0.1.0 pixiedust_0.8.6
[15] jsonlite_1.6 cluster_2.1.0 compiler_3.6.1 httr_1.4.0 backports_1.1.4 assertthat_0.2.1 Matrix_1.2-17
[22] lazyeval_0.2.2 cli_1.1.0 acepack_1.4.1 htmltools_0.3.6 tools_3.6.1 gtable_0.3.0 glue_1.3.1
[29] reshape2_1.4.3 Rcpp_1.0.2 carData_3.0-2 cellranger_1.1.0 vctrs_0.2.0 nlme_3.1-140 xfun_0.9
[36] openxlsx_4.1.0 rvest_0.3.2 lifecycle_0.1.0 MASS_7.3-51.4 hms_0.5.1 parallel_3.6.1 expm_0.999-3
[43] pwr_1.2-2 curl_3.2 gridExtra_2.3 pander_0.6.3 likert_1.3.5 rpart_4.1-15 reshape_0.8.8
[50] latticeExtra_0.6-28 stringi_1.4.3 nortest_1.0-4 checkmate_1.8.5 boot_1.3-22 zip_1.0.0 rlang_0.4.0
[57] pkgconfig_2.0.3 matrixStats_0.54.0 bitops_1.0-6 evaluate_0.14 labeling_0.3 rapportools_1.0 htmlwidgets_1.3
[64] cowplot_0.9.3 tidyselect_0.2.5 plyr_1.8.4 R6_2.4.0 DescTools_0.99.29 generics_0.0.2 pillar_1.4.2
[71] haven_2.1.1 foreign_0.8-71 withr_2.1.2 abind_1.4-5 RCurl_1.95-4.11 nnet_7.3-12 modelr_0.1.5
[78] crayon_1.3.4 car_3.0-2 rmarkdown_1.15 viridis_0.5.1 grid_3.6.1 readxl_1.1.0 data.table_1.11.8
[85] digest_0.6.21 xtable_1.8-4 munsell_0.5.0 viridisLite_0.3.0 quadprog_1.5-5
A work by Claudiu Papasteri
claudiu.papasteri@gmail.com
LS0tDQp0aXRsZTogIjxicj4gUmV6aWRlbnRpYWwiIA0Kc3VidGl0bGU6ICJJYXNpICINCmF1dGhvcjogIjxicj4gQ2xhdWRpdSBQYXBhc3RlcmkiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlbSAlWScpYCINCm91dHB1dDogDQogICAgaHRtbF9ub3RlYm9vazoNCiAgICAgICAgICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgICAgICAgICAgdG9jOiB0cnVlDQogICAgICAgICAgICB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgICAgICAgICAgdGhlbWU6IHNwYWNlbGFiDQogICAgICAgICAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgICAgICAgICBmb250LWZhbWlseTogQXJpYWwNCiAgICAgICAgICAgIGZpZ193aWR0aDogMTANCiAgICAgICAgICAgIGZpZ19oZWlnaHQ6IDkNCiAgICAjIHBkZl9kb2N1bWVudDogDQogICAgICAgICAgICAjIHRvYzogdHJ1ZQ0KICAgICAgICAgICAgIyB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgICMgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgICAgICAgICAjIGZvbnRzaXplOiAxMXB0DQogICAgICAgICAgICAjIGdlb21ldHJ5OiBtYXJnaW49MWluDQogICAgICAgICAgICAjIGZpZ193aWR0aDogNw0KICAgICAgICAgICAgIyBmaWdfaGVpZ2h0OiA2DQogICAgICAgICAgICAjIGZpZ19jYXB0aW9uOiB0cnVlDQogICAgIyBnaXRodWJfZG9jdW1lbnQ6IA0KICAgICAgICAgICAgIyB0b2M6IHRydWUNCiAgICAgICAgICAgICMgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICAjIGh0bWxfcHJldmlldzogZmFsc2UNCiAgICAgICAgICAgICMgZmlnX3dpZHRoOiA1DQogICAgICAgICAgICAjIGZpZ19oZWlnaHQ6IDUNCiAgICAgICAgICAgICMgZGV2OiBqcGVnDQotLS0NCg0KDQo8IS0tIFNldHVwIC0tPg0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRkFMU0V9DQojIGtpbnRyIG9wdGlvbnMNCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgY29tbWVudCA9ICIjIiwNCiAgY29sbGFwc2UgPSBUUlVFLA0KICBlY2hvID0gVFJVRSwgDQogIGNhY2hlID0gVFJVRSwgDQogIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFICAgIyBXSEVOIE5PVEVCT09LIElTIEZJTklTSEVEIC4uLiB1bnRpbCB0aGVuIGxlYXZlOiB3YXJuaW5nID0gVFJVRSwgbWVzc2FnZSA9IFRSVUUgICAgICAgIA0KKQ0KDQojIEdlbmVyYWwgUiBvcHRpb25zIGFuZCBpbmZvDQpzZXQuc2VlZCgxMTEpICAgICAgICAgICAgICAgIyBpbiBjYXNlIHdlIHVzZSByYW5kb21pemVkIHByb2NlZHVyZXMgICAgICAgDQpvcHRpb25zKHNjaXBlbiA9IDk5OSkgICAgICAgIyBwb3NpdGl2ZSB2YWx1ZXMgYmlhcyB0b3dhcmRzIGZpeGVkIGFuZCBuZWdhdGl2ZSB0b3dhcmRzIHNjaWVudGlmaWMgbm90YXRpb24NCg0KIyBMb2FkIHBhY2thZ2VzDQppZiAoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQ0KcGFja2FnZXMgPC0gYygNCiAgImtuaXRyIiwgImthYmxlRXh0cmEiLCAicGFwYWphIiwgIA0KICAidGlkeXZlcnNlIiwgICAgICAgDQogICJwc3ljaCIsICAgICAgICAgICANCiAgImJyb29tIiwgInN1bW1hcnl0b29scyIsICJ0YWRhYXRvb2xib3giLCAiUGVyZm9ybWFuY2VBbmFseXRpY3MiLCAgICAgICAgICANCiAgImdncGxvdDIiLCAiZ2dwdWJyIiwgInNjYWxlcyIsICAgICAgICANCiAgInJpbyIsDQogICJIbWlzYyIsIA0KICAiR0dhbGx5IiwgIlJDb2xvckJyZXdlciINCiAgIyAsIC4uLg0KKQ0KcGFjbWFuOjpwX2xvYWQoY2hhciA9IHBhY2thZ2VzKQ0KDQojIFRoZW1lcyBmb3IgZ2dwbG90MiBwbG90aW5nIChoZXJlIHVzZWQgQVBBIHN0eWxlKQ0KdGhlbWVfc2V0KHRoZW1lX2FwYSgpKQ0KDQojIFRhYmxlcyBrbml0dGluZyB0byBXb3JkDQpkb2MudHlwZSA8LSBrbml0cjo6b3B0c19rbml0JGdldCgncm1hcmtkb3duLnBhbmRvYy50bycpICAjIHRoZW4gZm9ybWF0IHRhYmxlcyB1c2luZyBhbiBpZiBzdGF0ZW1lbnQgbGlrZToNCiMgaWYgKGRvYy50eXBlID09ICJkb2N4IikgeyBwYW5kZXI6OnBhbmRlcihkZikgfSBlbHNlIHsga25pdHI6OmthYmxlKGRmKSB9DQoNCiMgU2V0IHdkIGZvciBOb3RlYm9vaw0KZm9sZGVyIDwtICJDOi9Vc2Vycy9NaWhhaS9EZXNrdG9wL1IgTm90ZWJvb2tzL25vdGVib29rcy9SZXppZGVudGlhbF9JYXNpIg0KIyBrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9IG5vcm1hbGl6ZVBhdGgoZm9sZGVyKSkNCmBgYA0KDQoNCg0KPCEtLSBSRVBPUlQgLS0+DQoNCiMgTG9hZCBkYXRhDQoNCmBgYHtyIHJkc19kYXRhLCByZXN1bHRzID0gJ2hpZGUnLCBjYWNoZS5leHRyYSA9IGZpbGUuaW5mbygiRGF0YV9SZXppZGVudGlhbC5SRFMiKX0NCiMjIFJlYWQNCmZpbGVuYW1lIDwtICJEYXRhX1JlemlkZW50aWFsLlJEUyIgICANCg0KRGF0YSA8LSByZWFkUkRTKGZpbGUucGF0aChmb2xkZXIsIGZpbGVuYW1lKSkgIA0KYGBgDQoNCg0KIyMgRG9hciBkaW4gSWFzaQ0KDQpgYGB7ciBkZXJpdmVkX2RhdGEsIGRlcGVuZHNvbiA9ICJyZHNfZGF0YSJ9DQpEYXRhIDwtDQogIERhdGEgJT4lDQogIGZpbHRlcihqdWRldCA9PSAiSWFzaSIpDQpgYGANCg0KDQojIERlbW9ncmFmaWNlDQoNCmBgYHtyIGdlbiwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9NiwgcmVzdWx0cz0nYXNpcyd9DQojIyBQaWUgY2hhcnQNCkRhdGEgICU+JQ0KICBtdXRhdGUoR2VuID0gYXMuZmFjdG9yKGFzLmNoYXJhY3RlcihnZW4pKSkgJT4lDQogIG11dGF0ZShHZW4gPSBmb3JjYXRzOjpmY3RfcmVjb2RlKEdlbiwgImZlbWluIiA9ICJmIiwgIm1hc2N1bGluIiA9ICJtIikpICU+JQ0KICBncm91cF9ieShHZW4pICU+JQ0KICBkcGx5cjo6c3VtbWFyaXNlKGNvdW50cyA9IG4oKSkgJT4lDQogIG11dGF0ZShwcm9wID0gcm91bmQoY291bnRzKjEwMC9zdW0oY291bnRzKSwgMSksDQogICAgICAgICBsYWIueXBvcyA9IGN1bXN1bShwcm9wKSAtIC41KnByb3AsDQogICAgICAgICBQZXJjZW50ID0gcGFzdGUwKHByb3AsICIgJSIpKSAlPiUgDQogIGdncHVicjo6Z2dwaWUoeCA9ICJwcm9wIiwgbGFiZWwgPSAiUGVyY2VudCIsDQogICAgICAgICAgICAgICAgZmlsbCA9ICJHZW4iLCBjb2xvciA9ICJ3aGl0ZSIsIA0KICAgICAgICAgICAgICAgIGxhYi5wb3MgPSAiaW4iLCBsYWIuZm9udCA9IGxpc3QoY29sb3IgPSAid2hpdGUiKSwNCiAgICAgICAgICAgICAgICBwYWxldHRlID0gImdyZXkiKQ0KYGBgDQoNCg0KYGBge3IgdmFyc3RlX2dlbiwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NiwgcmVzdWx0cz0nYXNpcyd9DQojIyBEb2RnZWQgQmFyIHBsb3Qgb2YgQWdlIGFuZCBHZW5kZXINCkRhdGEgICU+JQ0KICBtdXRhdGUoVmFydGFfY2F0ZWcgPSBjdXQodmFyc3RhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLUluZiwgNiwgOCwgMTAsIDEyLCAxNCwgMTYsIEluZiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzPWMoIjUtNiIsICI2LTgiLCAiOC0xMCIsICIxMC0xMiIsICIxMi0xNCIsICIxNC0xNiIsICIxNi0xOCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gRkFMU0UpKSAlPiUgIA0KICBtdXRhdGUoVmFydGFfY2F0ZWcgPSBhcy5mYWN0b3IoVmFydGFfY2F0ZWcpLA0KICAgICAgICAgR2VuID0gYXMuZmFjdG9yKGFzLmNoYXJhY3RlcihnZW4pKSkgJT4lDQogIG11dGF0ZShHZW4gPSBmb3JjYXRzOjpmY3RfcmVjb2RlKEdlbiwgImZlbWluIiA9ICJmIiwgIm1hc2N1bGluIiA9ICJtIikpICU+JQ0KICBkcGx5cjo6Y291bnQoVmFydGFfY2F0ZWcsIEdlbikgJT4lICAgICAgICAgICAgICAgICAgICAjIEdyb3VwIGJ5LCB0aGVuIGNvdW50IG51bWJlciBpbiBlYWNoIGdyb3VwDQogIG11dGF0ZShwY3QgPSBwcm9wLnRhYmxlKG4pKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICMgQ2FsY3VsYXRlIHBlcmNlbnQgd2l0aGluIGVhY2ggdmFyDQogIGdncGxvdChhZXMoeCA9IFZhcnRhX2NhdGVnLCB5ID0gcGN0LCBmaWxsID0gR2VuLCBsYWJlbCA9IHNjYWxlczo6cGVyY2VudChwY3QpKSkgKyANCiAgICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZScpICsgDQogICAgZ2VvbV90ZXh0KHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAuOSksICAgICMgbW92ZSB0byBjZW50ZXIgb2YgYmFycw0KICAgICAgICAgICAgICB2anVzdCA9IC0wLjUsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG51ZGdlIGFib3ZlIHRvcCBvZiBiYXINCiAgICAgICAgICAgICAgc2l6ZSA9IDMpICsgDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkgKw0KICAgIGdndGl0bGUoIiIpICsNCiAgICB4bGFiKCJWYXJzdGEiKSArIHlsYWIoIlBlcmNlbnRhZ2UgJSIpICsgDQogICAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiR2VuIiwgbmNvbCA9IDEpKSArIA0KICAgIHNjYWxlX2ZpbGxfZ3JleShzdGFydCA9IDAuOCwgZW5kID0gMC4yLCBuYS52YWx1ZSA9ICJyZWQiLCBhZXN0aGV0aWNzID0gImZpbGwiKSArDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwgbGVnZW5kLmRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsIA0KICAgICAgICAgIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSwgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSwgY29sb3VyID0gImJsYWNrIikpDQpgYGANCg0KDQoNCiMgR0NJQw0KDQpgYGB7ciBnY2ljXzEsIHJlc3VsdHM9J2FzaXMnLCBmaWcuaGVpZ2h0PTEwLCBmaWcud2lkdGg9MTIsIGZpZy5hbGlnbj0nY2VudGVyJ30NCiMgRGF0YVtzdHJfZGV0ZWN0KGNvbG5hbWVzKERhdGEpLCBmaXhlZCgiZ2NpIiwgaWdub3JlX2Nhc2U9VFJVRSkpXSAjIGl0ZW1zDQpEYXRhX2djaSA8LSBEYXRhWywgYyhzcHJpbnRmKCJnY2lfJWQiLCAxOjE0KSwgIk9wZW5DIiwgIkNsb3NlQyIsICJjZW50cnUiKV0NCg0KbGFiZWxzX2djaSA8LSANCiAgYygiRm9hcnRlIG5lYWRldsSDcmF0IiwNCiAgIk5lYWRldsSDcmF0IiwNCiAgIlVuIHBpYyBuZWFkZXbEg3JhdCAvIFVuIHBpYyBhZGV2xINyYXQiLA0KICAiQWRldsSDcmF0IiwNCiAgIkZvYXJ0ZSBhZGV2xINyYXQiKQ0KDQppdGVtdGV4dF9nY2kgPC0NCiAgYygiMS4gT2FtZW5paSBkZSBsYSBjZW50cnUgc2UgcG9hcnTEgyBmcnVtb3MgY3UgbWluZS4iLA0KICAiMi4gQW0gw65uY3JlZGVyZSDDrm4gb2FtZW5paSBkaW4gY2VudHJ1LiIsDQogICIzLiBPYW1lbmlpIGRlIGxhIGNlbnRydSBtxIMgw65uxaNlbGVnLiIsDQogICI0LiBBdHVuY2kgY8OibmQgbcSDIHBsw6JuZyBkZSBjZXZhLCBvYW1lbmlpIGRpbiBjZW50cnUgbcSDIGlhdSDDrm4gc2VyaW9zLiIsDQogICI1LiBPYW1lbmlpIGRlIGxhIGNlbnRydSBzdW50IGNvcmVjyJtpLiIsDQogICI2LiBTaW10IGPEgyBhaWNpLCBsYSBjZW50cnUsIGx1Y3JleiBsYSDDrm5kZXBsaW5pcmVhIHNjb3B1cmlsb3IgbWVsZS4iLA0KICAiNy4gw45uIGFjZXN0IGNlbnRydSBzdW50IMOubnRvdGRlYXVuYSBkZXN0dWkgb2FtZW5pIGNhcmUgc8SDIG3EgyBhanV0ZS4iLA0KICAiOC4gT2FtZW5paSBkaW4gY2VudHJ1IHNlIMibaW4gZGUgY3V2w6JudC4iLA0KICAiOS4gUG90IHPEgyBjZXIgYWp1dG9yIGRlIGxhIG9hbWVuaWkgZGluIGNlbnRydSBhdHVuY2kgY8OibmQgYW0gbmV2b2llLiIsDQogICIxMC4gw45uIGFjZXN0IGNlbnRydSwgY29waWlpIGF1IMOubmNyZWRlcmUgdW5paSDDrm4gYWzIm2lpLiIsDQogICIxMS4gQWljaSwgcG/Im2kgc8SDIGFpIMOubmNyZWRlcmUgw65uIHRvYXTEgyBsdW1lYS4iLA0KICAiMTIuIEhhb3N1bCDImWkgZ8SDbMSDZ2lhIGRpbiBjZW50cnUgbcSDIMOubm5lYnVuZXNjLiIsDQogICIxMy4gU3VudCBwcmVhIG11bMibaSBjb3BpaSBhaWNpLiIsDQogICIxNC4gT2FtZW5paSBkZSBsYSBjZW50cnUgc3VudCBhZGVzZWEgcHJlYSBvY3VwYcibaSBjYSBzxIMgbcSDIGFqdXRlLiIpDQoNCkRhdGFfZ2NpIDwtDQogIERhdGFfZ2NpICU+JQ0KICBtdXRhdGVfYXQodmFycyhzcHJpbnRmKCJnY2lfJWQiLCAxOjE0KSksIH5hcy5mYWN0b3IoYXMuY2hhcmFjdGVyKC4pKSkgJT4lDQogIHJlbmFtZV9hdCh2YXJzKHNwcmludGYoImdjaV8lZCIsIDE6MTQpKSwgfml0ZW10ZXh0X2djaSkgJT4lDQogIHJlbmFtZV9hdCh2YXJzKCJPcGVuQyIsICJDbG9zZUMiKSwgfmMoIkNsaW1hdCBkZXNjaGlzIiwgIkNsaW1hdCDDrm5jaGlzIikpICU+JQ0KICBkcGx5cjo6cmVuYW1lKENlbnRydSA9IGNlbnRydSkNCg0KIyBQbG90cyAgIyBsaWJyYXJ5KGxpa2VydCkNCkxpa2VydG9ial9nY2kgPC0gbGlrZXJ0OjpsaWtlcnQoRGF0YV9nY2lbLCAxOjE0XSwgbmxldmVscyA9IDUpICAgIyBoZXJlIGFyZSBwZXJjZW50YWdlcw0KDQpwbG90KExpa2VydG9ial9nY2ksIHR5cGUgPSAiYmFyIiwgDQogICAgIGNlbnRlcmVkID0gVFJVRSwgY2VudGVyID0gMywgaW5jbHVkZS5jZW50ZXIgPSBUUlVFLCAgICAgICAgICAgICAgIyAiMyIgaXMgbmV1dHJhbA0KICAgICB3cmFwID0gMzAsIGxvdy5jb2xvciA9ICdidXJseXdvb2QnLCBoaWdoLmNvbG9yID0gJ21hcm9vbicsDQogICAgIGdyb3VwLm9yZGVyID0gbmFtZXMoRGF0YV9nY2lbLCAxOjE0XSkpICsNCiAgeWxhYigiUHJvY2VudCIpICsgDQogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKG5yb3cgPSAxLCB0aXRsZSA9ICJSxINzcHVucyIpKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDUuNTEpDQpgYGANCg0KDQpgYGB7ciBnY2ljXzIsIHJlc3VsdHM9J2FzaXMnLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04LCBmaWcuYWxpZ249J2NlbnRlcid9DQpEYXRhX2djaSAlPiUNCiAgc2VsZWN0KCJDbGltYXQgZGVzY2hpcyIsICJDbGltYXQgw65uY2hpcyIpICU+JQ0KICBnYXRoZXIoKSAlPiUNCiAgcmVuYW1lX2F0KHZhcnMoImtleSIsICJ2YWx1ZSIpLCB+YygiVmFyIiwgIlNjb3IiKSkgJT4lDQogICAgZ2dwdWJyOjpnZ3Zpb2xpbigiVmFyIiwgIlNjb3IiLCBmaWxsID0gIlZhciIsDQogICAgICBwYWxldHRlID0gYygiIzAwQUZCQiIsICIjRkM0RTA3IiksDQogICAgICBhZGQgPSAiYm94cGxvdCIsIGFkZC5wYXJhbXMgPSBsaXN0KGZpbGwgPSAid2hpdGUiKSwNCiAgICAgIHhsYWIgPSAiIiwgbGVnZW5kID0gIm5vbmUiKSArDQogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fc2UsICBjb2xvdXIgPSAiZGFya3JlZCIpDQpgYGANCg0KDQpgYGB7ciBnY2ljXzMsIHJlc3VsdHM9J2FzaXMnLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04LCBmaWcuYWxpZ249J2NlbnRlcid9DQpEYXRhX2djaSAlPiUNCiAgc2VsZWN0KCJDbGltYXQgZGVzY2hpcyIsICJDbGltYXQgw65uY2hpcyIsICJDZW50cnUiKSAlPiUNCiAgZ2F0aGVyKGtleSA9IlZhciIsIHZhbHVlID0gIlNjb3IiLCAtQ2VudHJ1KSAlPiUNCiAgbXV0YXRlKENlbnRydSA9IGFzLmZhY3RvcihDZW50cnUpKSAlPiUNCiAgICBnZ3B1YnI6OmdndmlvbGluKCJWYXIiLCAiU2NvciIsIGZpbGwgPSAiVmFyIiwNCiAgICAgIHBhbGV0dGUgPSBjKCIjMDBBRkJCIiwgIiNGQzRFMDciKSwNCiAgICAgIGFkZCA9ICJib3hwbG90IiwgYWRkLnBhcmFtcyA9IGxpc3QoZmlsbCA9ICJ3aGl0ZSIpLA0KICAgICAgeGxhYiA9ICIiLCBsZWdlbmQgPSAibm9uZSIsDQogICAgICBmYWNldC5ieSA9ICJDZW50cnUiKSArDQogIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fc2UsICBjb2xvdXIgPSAiZGFya3JlZCIpDQoNCmNhdCgiIyMjIENsaW1hdCBkZXNjaGlzIikNCkRhdGFfZ2NpICU+JQ0KICBzZWxlY3QoIkNsaW1hdCBkZXNjaGlzIiwgIkNlbnRydSIpICU+JSANCiAgZ3JvdXBfYnkoQ2VudHJ1KSAlPiUgIA0KICBkcGx5cjo6c3VtbWFyaXNlKG1lZGllID0gbWVhbihgQ2xpbWF0IGRlc2NoaXNgLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgICAgICAgIHNkID0gc2QoYENsaW1hdCBkZXNjaGlzYCwgbmEucm0gPSBUUlVFKSkNCg0KY2F0KCIjIyMgQ2xpbWF0IMOubmNoaXMiKQ0KRGF0YV9nY2kgJT4lDQogIHNlbGVjdCgiQ2xpbWF0IMOubmNoaXMiLCAiQ2VudHJ1IikgJT4lIA0KICBncm91cF9ieShDZW50cnUpICU+JSAgDQogIGRwbHlyOjpzdW1tYXJpc2UobWVkaWUgPSBtZWFuKGBDbGltYXQgw65uY2hpc2AsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICAgICAgICAgc2QgPSBzZChgQ2xpbWF0IMOubmNoaXNgLCBuYS5ybSA9IFRSVUUpKQ0KYGBgDQoNCg0KIyBBU0NRDQoNCmBgYHtyIGFzY3FfMSwgcmVzdWx0cz0nYXNpcycsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTksIGZpZy5hbGlnbj0nY2VudGVyJ30NCkRhdGFfYXNjcSA8LQ0KICBEYXRhICU+JQ0KICBkcGx5cjo6c2VsZWN0KHNwcmludGYoImFzY18lZCIsIDE6MTUpLCBjKCJBU2VjdXIiLCAiQUFueGlvIiwgIkFBdm9pZCIsICJBU0NRX2YiLCAiY2VudHJ1IikpICU+JQ0KICBkcGx5cjo6cmVuYW1lKENlbnRydSA9IGNlbnRydSkgJT4lDQogIG11dGF0ZSgNCiAgICBBU0NRX2YgPSBmb3JjYXRzOjpmY3RfcmVjb2RlKEFTQ1FfZiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNlYyIgPSAiU2VjdXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2VjIMiZaSBBbngiID0gIlNlY3VyJkFueGlvIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFueCIgPSAiQW54aW8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRXZpdCIgPSAiQXZvaWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2VjIMiZaSBFdml0IiA9ICJTZWN1ciZBdm9pZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBbnggyJlpIEV2aXQiID0gIkFueGlvJkF2b2lkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNlYywgQW54LCBFdml0IiA9ICJTZWN1ciZBbnhpbyZBdm9pZCIpLA0KICAgIEFTQ1FfZiA9IGZjdF9leHBsaWNpdF9uYShBU0NRX2YsICJsaXBzxIMiKSkNCg0KIyBDcmVhdGUgYSBjdXN0b20gY29sb3Igc2NhbGUgZm9yIGFsbCBBU0NRIGdyYXBocw0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpteUNvbG9ycyA8LSBicmV3ZXIucGFsKDksIlNldDEiKQ0KbmFtZXMobXlDb2xvcnMpIDwtIGxldmVscyhEYXRhX2FzY3EkQVNDUV9mKQ0KY29sU2NhbGUgPC0gc2NhbGVfY29sb3VyX21hbnVhbChuYW1lID0gIkFTQ1FfZiIsIHZhbHVlcyA9IG15Q29sb3JzKQ0KDQojIFBsb3QNCmdncGxvdChEYXRhX2FzY3EsIGFlcyh4ID0gZm9yY2F0czo6ZmN0X2luZnJlcShBU0NRX2YpLCBmaWxsID0gQVNDUV9mKSkgKw0KICBnZW9tX2JhcihhZXMoeSA9ICguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSkgKw0KICBnZW9tX3RleHQoYWVzKHkgPSAoKC4uY291bnQuLikvc3VtKC4uY291bnQuLikpLCANCiAgICAgICAgICAgICAgICBsYWJlbCA9IHNjYWxlczo6cGVyY2VudCgoLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSkpLCANCiAgICAgICAgICAgIHN0YXQgPSAiY291bnQiLCB2anVzdCA9IC0wLjI1KSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50KSArDQogIGxhYnModGl0bGUgPSAiIiwgeSA9ICJQcm9jZW50IiwgeCA9ICJUaXAgQXRhyJlhbWVudCIpICsNCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKyBjb2xTY2FsZSAgICAgICAjIGNvbG9yIHNjYWxlIGhlcmUga2VlcCBjb25zaXN0ZW5jeSBvZiBjb2xvciB3aXRoIGZhY3RvciBsZXZlbA0KYGBgDQoNCg0KYGBge3IgYXNjcV8yLCByZXN1bHRzPSdhc2lzJywgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTEwLCBmaWcuYWxpZ249J2NlbnRlcid9DQpnZ3Bsb3QoRGF0YV9hc2NxLCBhZXMoeCA9IGZvcmNhdHM6OmZjdF9pbmZyZXEoQVNDUV9mKSwgZmlsbCA9IEFTQ1FfZikpICsNCiAgZmFjZXRfd3JhcCh+Q2VudHJ1LCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAyKSArDQogIGdlb21fYmFyKGFlcyh5ID0gKC4uY291bnQuLikvc3VtKC4uY291bnQuLikpKSArDQogIGdlb21fdGV4dChhZXMoeSA9ICgoLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSksIA0KICAgICAgICAgICAgICAgIGxhYmVsID0gc2NhbGVzOjpwZXJjZW50KCguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSksIA0KICAgICAgICAgICAgc3RhdCA9ICJjb3VudCIsIHZqdXN0ID0gLTAuMjUpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnQpICsNCiAgbGFicyh0aXRsZSA9ICIiLCB5ID0gIlByb2NlbnQiLCB4ID0gIiIpICsNCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkgKyBjb2xTY2FsZSArICAgICAgICAgICAgICAgICAgICAgICAgICMgY29sb3Igc2NhbGUgaGVyZSBrZWVwIGNvbnNpc3RlbmN5IG9mIGNvbG9yIHdpdGggZmFjdG9yIGxldmVsDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpIA0KYGBgDQoNCg0KIyBBQ0UNCg0KYGBge3IgZGVzY3JfYWNlLCBmaWcud2lkdGggPSAxMiwgZmlnLmFzcCA9IDEuNn0NCiMgRGF0YSRzZWMyXzEgICAgaXMgcmVkdW5kYW50IGJlY2F1c2UgYWxsIHNob3VsZCBiZSAxLCBldmVuIHRvdWdoIHRoZXJlIGFyZSA0MDMgTkEgYW5kIDg3MiBvZiAxDQpBY2VfY29sX25hbWVzIDwtIGMoc3ByaW50Zigic2VjMV8lZCIsIDE6MTApLCBzcHJpbnRmKCJzZWMyXyVkIiwgMjo5KSkNCg0KQWNlX25ld19uYW1lcyA8LSBjKCJkaXZvcnQiLCAiaW5jYXJjZXJhcmUiLCAiYm9hbGEgbWludGFsYSIsICJhbWVuaW50YXJlIiwgInVtaWxpcmUiLCANCiAgICAgICAgICAgICAgICAgICAiYWJ1eiBzZXh1YWwiLCAibGlwc3VyaSIsICJhYnV6IGZpemljIiwgImFkaWN0aWUiLCAibmVzaWd1cmFudGEiLCANCiAgICAgICAgICAgICAgICAgICAiYnVsbHlpbmciLCAiZGVjZXMiLCAiZW1pZ3JhcmUiLCAiYm9hbGEiLCAidmlvbGVudGEiLCANCiAgICAgICAgICAgICAgICAgICAicmF1dGF0ZSIsICJwb2xpdGllIiwgImFidXogcGFydGVuZXIiKQ0KDQojIFBsb3QgZnVuY3Rpb24gYW5kIERhdGEgZnVuY3Rpb24NCmFjZV9wbG90IDwtIGZ1bmN0aW9uKGRmKXsgDQogIGdncGxvdChkZiwgYWVzKHggPSB2YXJpYWJsZSwgeSA9IHBlcmNlbnQsIGZpbGwgPSB2YXJpYWJsZSkpICsgDQogICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAocm91bmQocGVyY2VudCksICIlIikpLCB2anVzdCA9IC0wLjI1KSArDQogICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIA0KICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBoanVzdCA9IDEpKSArDQogICAgIHlsYWIoIlBlcmNlbnRhZ2UiKSArICB4bGFiKCIiKSAgDQp9DQoNCmFjZV9kYXRhIDwtIGZ1bmN0aW9uKGRmLCBhY2VfbGV2ZWxzLCBmaWx0ZXJfY29sLCBmaWx0ZXJfbGV2ZWwpew0KICBmaWx0ZXJfY29sIDwtIHJsYW5nOjplbnF1byhmaWx0ZXJfY29sKQ0KICBkZiAlPiUgDQogICAgZmlsdGVyKCEhZmlsdGVyX2NvbCAlaW4lIGZpbHRlcl9sZXZlbCkgJT4lIA0KICAgIHNlbGVjdChBY2VfY29sX25hbWVzKSAlPiUNCiAgICBzdW1tYXJpc2VfYWxsKGZ1bnMoc3VtKCFpcy5uYSguKSkgLyBsZW5ndGgoLikgKiAxMDApKSAlPiUgDQogICAgZ2F0aGVyKHZhcmlhYmxlLCBwZXJjZW50KSAlPiUNCiAgICBtdXRhdGUodmFyaWFibGUgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZSh2YXJpYWJsZSwgQWNlX2NvbF9uYW1lcywgQWNlX25ld19uYW1lcykpICU+JQ0KICAgIGFycmFuZ2UoZGVzYyhwZXJjZW50KSkgJT4lDQogICAgbXV0YXRlKHZhcmlhYmxlID0gZmFjdG9yKHZhcmlhYmxlLCBhY2VfbGV2ZWxzKSkgDQp9ICANCiAgDQojIEFDRXMgZGF0YSAmIHBsb3RzDQpEYXRhX0FDRSA8LSANCiAgRGF0YSAlPiUgICAgIyBiYXJwbG90KGNvbFN1bXMoRGF0YVssIEFjZV9jb2xfbmFtZXNdLCBuYS5ybSA9IFRSVUUpKQ0KICAgIHNlbGVjdChBY2VfY29sX25hbWVzKSAlPiUNCiAgICBzdW1tYXJpc2VfYWxsKGZ1bnMoc3VtKCFpcy5uYSguKSkgLyBsZW5ndGgoLikgKiAxMDApKSAlPiUgDQogICAgZ2F0aGVyKHZhcmlhYmxlLCBwZXJjZW50KSAlPiUNCiAgICBtdXRhdGUodmFyaWFibGUgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZSh2YXJpYWJsZSwgQWNlX2NvbF9uYW1lcywgQWNlX25ld19uYW1lcykpICU+JQ0KICAgIGFycmFuZ2UoZGVzYyhwZXJjZW50KSkgJT4lDQogICAgbXV0YXRlKHZhcmlhYmxlID0gZmFjdG9yKHZhcmlhYmxlLCB2YXJpYWJsZSkpICAgICAjIHRoaXMgbWFrZXMgbGV2ZWxzIG9yZGVyIG1hdGNoIHJvdyBvcmRlciENCmFjZV9sZXZlbHMgPC0gbGV2ZWxzKERhdGFfQUNFJHZhcmlhYmxlKSAgDQoNCmFjZV9wbG90MSA8LSANCiAgRGF0YV9BQ0UgJT4lDQogICAgYWNlX3Bsb3QoKSArDQogICAgICBnZ3RpdGxlKCJBQ0UiKSANCg0KYWNlX3Bsb3QyIDwtICANCiAgYWNlX2RhdGEoRGF0YSwgYWNlX2xldmVscywgZ2VuLCBmaWx0ZXJfbGV2ZWwgPSAiZiIpICU+JQ0KICAgIGFjZV9wbG90KCkgKw0KICAgICAgZ2d0aXRsZSgiQUNFIC0gZmV0ZSIpIA0KDQphY2VfcGxvdDMgPC0NCiAgYWNlX2RhdGEoRGF0YSwgYWNlX2xldmVscywgZ2VuLCBmaWx0ZXJfbGV2ZWwgPSAibSIpICU+JQ0KICAgIGFjZV9wbG90KCkgKw0KICAgICAgZ2d0aXRsZSgiQUNFIC0gYsSDaWXIm2kiKSANCg0KYWNlX3Bsb3Q0IDwtDQogIGFjZV9kYXRhKERhdGEsIGFjZV9sZXZlbHMsIHRpcF9jaGVzdGlvbmFyLCBmaWx0ZXJfbGV2ZWwgPSBjKCI1LThhbmkiLCAiNS04aW50YXJ6aWVyZSIpKSAlPiUNCiAgICBhY2VfcGxvdCgpICsNCiAgICAgIGdndGl0bGUoIkFDRSAtIDUtOCBhbmkiKSANCg0KYWNlX3Bsb3Q1IDwtDQogIGFjZV9kYXRhKERhdGEsIGFjZV9sZXZlbHMsIHRpcF9jaGVzdGlvbmFyLCBmaWx0ZXJfbGV2ZWwgPSAiOS0xOGFuaSIpICU+JQ0KICAgIGFjZV9wbG90KCkgKw0KICAgICAgZ2d0aXRsZSgiQUNFIC0gOS0xOCBhbmkiKQ0KDQoNCmdncHVicjo6Z2dhcnJhbmdlKGFjZV9wbG90MSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgZ2dhcnJhbmdlKGFjZV9wbG90MiwgYWNlX3Bsb3QzLCBuY29sID0gMiwgbGFiZWxzID0gYygiQiIsICJDIikpLCANCiAgICAgICAgICBnZ2FycmFuZ2UoYWNlX3Bsb3Q0LCBhY2VfcGxvdDUsIG5jb2wgPSAyLCBsYWJlbHMgPSBjKCJDIiwgIkQiKSksDQogICAgICAgICAgbnJvdyA9IDMsIA0KICAgICAgICAgIGxhYmVscyA9ICJBIikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQpgYGANCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCjwhLS0gU2Vzc2lvbiBJbmZvIGFuZCBMaWNlbnNlIC0tPg0KDQo8YnI+DQoNCjxicj4NCg0KIyBTZXNzaW9uIEluZm8NCmBgYHtyIHNlc3Npb25faW5mbywgZWNobyA9IEZBTFNFLCByZXN1bHRzID0gJ21hcmt1cCd9DQpzZXNzaW9uSW5mbygpICAgIA0KYGBgDQoNCjwhLS0gRm9vdGVyIC0tPg0KJm5ic3A7DQo8aHIgLz4NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij5BIHdvcmsgYnkgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL0NsYXVkaXVQYXBhc3RlcmkvIj5DbGF1ZGl1IFBhcGFzdGVyaTwvYT48L3A+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+PHNwYW4gc3R5bGU9ImNvbG9yOiAjODA4MDgwOyI+PGVtPmNsYXVkaXUucGFwYXN0ZXJpQGdtYWlsLmNvbTwvZW0+PC9zcGFuPjwvcD4NCiZuYnNwOw0K