Load and clean data

library(tidyverse)
library(here)
library(csvy)

# Calculate the quantile (and median) of an ordered factor
# Borrowed from @jrnold: https://gist.github.com/jrnold/6759254
#
# In the case of ties, the first in order will win. For instance, 
# bloop <- factor(c("A", "A", "B", "B"), ordered = TRUE)
# median(bloop)  # "A"
quantile.ordered <- function(x, probs = seq(0, 1, 0.25)) {
  tab <- table(x)
  cdf <- cumsum(tab / sum(tab))
  idx <- sapply(probs, function(p) min(which(cdf >= p)))
  levels(x)[idx] 
}

quantile.factor <- quantile.ordered
median.ordered <- function(x) quantile(x, 0.5)
median.factor <- median.ordered


# Load data
# results_file <- file.path(here(), "data", "test_data.csv")
results_file <- here("private", 
                     "NGO Crackdowns and Philanthropy, March 2018 pilot_March 23, 2018_20.01.csv")

# Possible answers
favorability <- c("Very unfavorable", "Unfavorable", "Neutral", 
                  "Favorable", "Very favorable")

likelihood <- c("Extremely unlikely", "Somewhat unlikely", 
                "Neither likely nor unlikely", 
                "Somewhat likely", "Extremely likely")

frequency_charity <- c("Once a week", "Once a month", "Once every three months", 
                       "Once every six months", "Once a year", "Once every few years", 
                       "Never")

frequency_public_affairs <- c("Most of the time", "Some of the time", 
                              "Only now and then", "Hardly at all")

levels_ideology <- c("Strong liberal", "Liberal", "Independent, leaning liberal", 
                     "Independent", "Independent, leaning conservative", 
                     "Conservative", "Very conservative")

levels_education <- c("Less than high school", "High school graduate", 
                      "Some college", "2 year degree", "4 year degree", 
                      "Graduate or professional degree", "Doctorate")

frequency_religion <- c("More than once a week", "Once a week", "Once or twice a month", 
                        "A few times a year", "Seldom", "Never", "Don't know")

levels_gender <- c("Female", "Male", "Transgender", "Other", "Prefer not to say")

levels_income <- c("Less than $10,000", "$10,000 – $19,999", "$20,000 – $29,999", 
                   "$30,000 – $39,999", "$40,000 – $49,999", "$50,000 – $59,999", 
                   "$60,000 – $69,999", "$70,000 – $79,999", "$80,000 – $89,999", 
                   "$90,000 – $99,999", "$100,000 – $149,999", "More than $150,000", 
                   "Prefer not to say")

levels_age <- c("Under 18", "18 – 24", "25 – 34", "35 – 44", "45 – 54", 
                "55 – 64", "65 – 74", "75 – 84", "85 or older")

attention1_answer <- c("Green", "Yellow")
attention2_answer <- "Blue"
levels_attention <- c("Correct", "Incorrect")

# Qualtrics stores question information in the first 3 rows. All we care about
# are the column names in the first row.
results_meta <- read_csv(results_file, n_max = 2)

# The first 10 rows need to be skipped because the consent question has a bunch
# of line breaks and it messes with CSV line counting. The actual responses
# start on row 11. This doesn't entirely make sense, since read_csv can read the
# line break-filled row in just fine. Skipping said lines makes it choke. <shrug>
results_raw <- read_csv(results_file, skip = 16,
                        col_names = colnames(results_meta))

# Confirmation codes to exclude. These are people who failed the attention
# checks or who took the survey outside of MTurk.
#
# The code for determining these is in a script that is excluded from the main
# repository because of privacy issues (it deals directly with MTurk worker
# IDs), called "private/approve_mturkers.R". It outputs this text list of codes.
codes_to_exclude <- read_csv(here("data", "codes_to_exclude.csv"))

# Clean everything
results_check_attention <- results_raw %>%
  # Only select necessary columns
  select(id = ResponseId, confirmation_code = mTurkCode, duration = `Duration (in seconds)`,
         start_date = StartDate, end_date = EndDate,
         crackdown, issue, funding, starts_with("Q")) %>%
  rename(favor_humanitarian = Q2.1_1, favor_human_rights = Q2.1_2, 
         favor_development = Q2.1_3, donate_likely = Q2.3, 
         amount_donate = Q2.4_1, amount_keep = Q2.4_2, amount_why = Q2.5,
         give_charity = Q3.2, volunteer = Q3.3, political_knowledge = Q3.4,
         ideology = Q3.5, education = Q3.6, religiosity = Q3.7,
         gender = Q3.9, gender_other = Q3.9_4_TEXT, income = Q3.10, age = Q3.11) %>%
  # Clean up experimental condition columns
  mutate(issue = recode(issue, `human rights for refugees` = "Human rights",
                        `humanitarian assistance for refugees` = "Humanitarian assistance"),
         funding = recode(funding, `government donors` = "Government",
                          `individual, private donors` = "Private")) %>%
  mutate(crackdown = ifelse(str_detect(crackdown, "harshly restrict"), 
                            "Crackdown", "No crackdown")) %>% 
  mutate(crackdown = factor(crackdown, levels = c("No crackdown", "Crackdown"), 
                            ordered = TRUE),
         issue = factor(issue, levels = c("Human rights", "Humanitarian assistance"), 
                        ordered = TRUE),
         funding = factor(funding, levels = c("Government", "Private"), 
                          ordered = TRUE)) %>% 
  # Attention checks
  mutate(attention1_correct = str_split(Q1.3, ",") %>% 
           map_lgl(~ all(attention1_answer %in% .) & length(.) == length(attention1_answer)),
         attention2_correct = Q3.8 == attention2_answer) %>% 
  # This person contacted me separately to say that they accidentally did the first
  # attention check wrong, but that they did pay attention: 6518634
  mutate(attention1_correct = ifelse(confirmation_code == 6518634,
                                     TRUE, attention1_correct)) 

results <- results_check_attention %>% 
  filter(!(confirmation_code %in% codes_to_exclude$confirmation_code)) %>%
  # Factorize variables
  mutate(donate_likely = factor(donate_likely, levels = likelihood, ordered = TRUE)) %>% 
  mutate_at(vars(favor_humanitarian, favor_human_rights, favor_development),
            funs(factor(., levels = favorability, ordered = TRUE))) %>% 
  mutate(give_charity = factor(give_charity, 
                               levels = frequency_charity, ordered = TRUE),
         volunteer = factor(volunteer, levels = c("No", "Yes"), ordered = TRUE),
         political_knowledge = factor(political_knowledge, 
                                      levels = frequency_public_affairs, ordered = TRUE),
         ideology = factor(ideology, levels = levels_ideology, ordered = TRUE),
         education = factor(education, levels = levels_education, ordered = TRUE),
         religiosity = factor(religiosity, levels = frequency_religion, ordered = TRUE),
         gender = recode(gender, `Other:` = "Other"),
         gender = factor(gender, levels = levels_gender, ordered = TRUE),
         income = factor(income, levels = levels_income, ordered = TRUE),
         age = factor(age, levels = levels_age, ordered = TRUE),
         check1 = factor(attention1_correct, levels = c(TRUE, FALSE),
                         labels = levels_attention, ordered = TRUE),
         check2 = factor(attention2_correct, levels = c(TRUE, FALSE),
                         labels = levels_attention, ordered = TRUE)) %>% 
  # Dichotomize variables
  mutate(donate_likely_bin = fct_recode(donate_likely,
                                        `Not likely` = "Extremely unlikely",
                                        `Not likely` = "Somewhat unlikely",
                                        `Not likely` = "Neither likely nor unlikely",
                                        Likely = "Somewhat likely",
                                        Likely = "Extremely likely")) %>% 
  mutate_at(vars(favor_humanitarian, favor_human_rights, favor_development),
            funs(bin = fct_recode(., 
                                  `Not favorable` = "Very unfavorable",
                                  `Not favorable` = "Unfavorable",
                                  `Not favorable` = "Neutral",
                                  Favorable = "Favorable",
                                  Favorable = "Very favorable"))) %>% 
  mutate(give_charity_3 = fct_recode(give_charity,
                                     `At least once a month` = "Once a week",
                                     `At least once a month` = "Once a month",
                                     `Once a month-once a year` = "Once every three months",
                                     `Once a month-once a year` = "Once every six months",
                                     `Once a month-once a year` = "Once a year",
                                     Rarely = "Once every few years",
                                     Rarely = "Never") %>% fct_rev(),
         give_charity_2 = fct_recode(give_charity,
                                     `At least once a year` = "Once a week",
                                     `At least once a year` = "Once a month",
                                     `At least once a year` = "Once every three months",
                                     `At least once a year` = "Once every six months",
                                     `At least once a year` = "Once a year",
                                     Rarely = "Once every few years",
                                     Rarely = "Never")) %>% 
  mutate(political_knowledge_bin = fct_recode(political_knowledge,
                                              `Often` = "Most of the time",
                                              `Often` = "Some of the time",
                                              `Not often` = "Only now and then",
                                              `Not often` = "Hardly at all") %>% fct_rev()) %>% 
  mutate(ideology_3 = fct_recode(ideology,
                                 `Liberal` = "Strong liberal",
                                 `Liberal` = "Liberal",
                                 `Liberal` = "Independent, leaning liberal",
                                 `Independent` = "Independent",
                                 `Conservative` = "Independent, leaning conservative",
                                 `Conservative` = "Conservative",
                                 `Conservative` = "Very conservative") %>% fct_rev()) %>% 
  mutate(ideology_bin = fct_recode(ideology_3,
                                   `Not liberal` = "Independent",
                                   `Not liberal` = "Conservative")) %>% 
  mutate(education_bin = fct_recode(education,
                                    `No BA` = "Less than high school",
                                    `No BA` = "High school graduate",
                                    `No BA` = "Some college",
                                    `No BA` = "2 year degree",
                                    `BA and above` = "4 year degree",
                                    `BA and above` = "Graduate or professional degree",
                                    `BA and above` = "Doctorate")) %>% 
  mutate(religiosity_bin = fct_recode(religiosity,
                                      `At least once a month` = "More than once a week",
                                      `At least once a month` = "Once a week",
                                      `At least once a month` = "Once or twice a month",
                                      `Rarely` = "A few times a year",
                                      `Rarely` = "Seldom",
                                      `Rarely` = "Never",
                                      NULL = "Don't know") %>% fct_rev()) %>% 
  mutate(income_clean = fct_recode(income, NULL = "Prefer not to say"),
         income_bin = factor(income_clean >= median(.$income), levels = c(FALSE, TRUE),
                             labels = paste(c("Less than", "At least"), median(.$income)))) %>% 
  mutate(age_bin = factor(age >= median(.$age), levels = c(FALSE, TRUE),
                          labels = paste(c("Less than", "At least"), median(.$age))),
         gender_bin = fct_collapse(gender,
                                   Female = "Female",
                                   `Not Female` = c("Male", "Transgender", 
                                                    "Other", "Prefer not to say")))

# Save final clean data
saveRDS(results, here("data", "results_clean.rds"))
write_csvy(results, file = here("data", "results_clean.csv"),
           metadata = here("data", "results_clean.yaml"), na = "NA")

Original computing environment

## # http://dirk.eddelbuettel.com/blog/2017/11/27/#011_faster_package_installation_one
## VER=
## CCACHE=ccache
## CC=$(CCACHE) gcc$(VER)
## CXX=$(CCACHE) g++$(VER)
## CXXFLAGS=-Wno-unused-variable -Wno-unused-function -Wno-unused-local-typedefs
## CXX11=$(CCACHE) g++$(VER)
## CXX14=$(CCACHE) g++$(VER)
## FLIBS = -L`gfortran -print-file-name=libgfortran.dylib | xargs dirname`
## FC=$(CCACHE) gfortran$(VER)
## F77=$(CCACHE) gfortran$(VER)
## Session info -------------------------------------------------------------
##  setting  value                       
##  version  R version 3.5.1 (2018-07-02)
##  system   x86_64, darwin15.6.0        
##  ui       X11                         
##  language (EN)                        
##  collate  en_US.UTF-8                 
##  tz       America/Denver              
##  date     2018-07-19
## Packages -----------------------------------------------------------------
##  package    * version    date       source                          
##  assertthat   0.2.0      2017-04-11 CRAN (R 3.5.0)                  
##  backports    1.1.2      2017-12-13 CRAN (R 3.5.0)                  
##  base       * 3.5.1      2018-07-05 local                           
##  base64enc    0.1-3      2015-07-28 CRAN (R 3.5.0)                  
##  bindr        0.1.1      2018-03-13 CRAN (R 3.5.0)                  
##  bindrcpp   * 0.2.2      2018-03-29 CRAN (R 3.5.0)                  
##  broom        0.4.5      2018-07-03 CRAN (R 3.5.0)                  
##  cellranger   1.1.0      2016-07-27 CRAN (R 3.5.0)                  
##  cli          1.0.0      2017-11-05 CRAN (R 3.5.0)                  
##  colorspace   1.3-2      2016-12-14 CRAN (R 3.5.0)                  
##  compiler     3.5.1      2018-07-05 local                           
##  crayon       1.3.4      2017-09-16 CRAN (R 3.5.0)                  
##  csvy       * 0.2.1      2018-04-30 Github (leeper/csvy@01a2f9d)    
##  data.table   1.10.4-3   2017-10-27 CRAN (R 3.5.0)                  
##  datasets   * 3.5.1      2018-07-05 local                           
##  devtools     1.13.5     2018-02-18 CRAN (R 3.5.0)                  
##  digest       0.6.15     2018-01-28 CRAN (R 3.5.0)                  
##  dplyr      * 0.7.6      2018-06-29 CRAN (R 3.5.1)                  
##  evaluate     0.10.1     2017-06-24 CRAN (R 3.5.0)                  
##  forcats    * 0.3.0      2018-02-19 CRAN (R 3.5.0)                  
##  foreign      0.8-70     2017-11-28 CRAN (R 3.5.1)                  
##  ggplot2    * 3.0.0      2018-07-03 CRAN (R 3.5.0)                  
##  glue         1.2.0.9000 2018-04-30 Github (tidyverse/glue@b538962) 
##  graphics   * 3.5.1      2018-07-05 local                           
##  grDevices  * 3.5.1      2018-07-05 local                           
##  grid         3.5.1      2018-07-05 local                           
##  gtable       0.2.0      2016-02-26 CRAN (R 3.5.0)                  
##  haven        1.1.2      2018-06-27 CRAN (R 3.5.0)                  
##  here       * 0.1        2017-05-28 CRAN (R 3.5.0)                  
##  hms          0.4.2      2018-03-10 CRAN (R 3.5.0)                  
##  htmltools    0.3.6      2017-04-28 CRAN (R 3.5.0)                  
##  httr         1.3.1      2017-08-20 CRAN (R 3.5.0)                  
##  jsonlite     1.5        2017-06-01 CRAN (R 3.5.0)                  
##  knitr        1.20       2018-02-20 CRAN (R 3.5.0)                  
##  lattice      0.20-35    2017-03-25 CRAN (R 3.5.1)                  
##  lazyeval     0.2.1      2017-10-29 CRAN (R 3.5.0)                  
##  lubridate    1.7.4      2018-04-11 CRAN (R 3.5.0)                  
##  magrittr     1.5        2014-11-22 CRAN (R 3.5.0)                  
##  memoise      1.1.0      2017-04-21 CRAN (R 3.5.0)                  
##  methods    * 3.5.1      2018-07-05 local                           
##  mnormt       1.5-5      2016-10-15 CRAN (R 3.5.0)                  
##  modelr       0.1.2      2018-05-11 CRAN (R 3.5.0)                  
##  munsell      0.5.0      2018-06-12 cran (@0.5.0)                   
##  nlme         3.1-137    2018-04-07 CRAN (R 3.5.1)                  
##  parallel     3.5.1      2018-07-05 local                           
##  pillar       1.2.3      2018-05-25 CRAN (R 3.5.0)                  
##  pkgconfig    2.0.1      2017-03-21 CRAN (R 3.5.0)                  
##  plyr         1.8.4      2016-06-08 CRAN (R 3.5.0)                  
##  psych        1.8.4      2018-05-06 cran (@1.8.4)                   
##  purrr      * 0.2.5      2018-05-29 cran (@0.2.5)                   
##  R6           2.2.2      2017-06-17 CRAN (R 3.5.0)                  
##  Rcpp         0.12.17    2018-05-18 cran (@0.12.17)                 
##  readr      * 1.1.1      2017-05-16 CRAN (R 3.5.0)                  
##  readxl       1.1.0      2018-04-20 CRAN (R 3.5.0)                  
##  reshape2     1.4.3      2017-12-11 CRAN (R 3.5.0)                  
##  rlang        0.2.1      2018-05-30 CRAN (R 3.5.0)                  
##  rmarkdown    1.10       2018-06-11 CRAN (R 3.5.0)                  
##  rprojroot    1.3-2      2018-01-03 CRAN (R 3.5.0)                  
##  rstudioapi   0.7        2017-09-07 CRAN (R 3.5.0)                  
##  rvest        0.3.2      2016-06-17 CRAN (R 3.5.0)                  
##  scales       0.5.0.9000 2018-07-16 Github (hadley/scales@419236a)  
##  stats      * 3.5.1      2018-07-05 local                           
##  stringi      1.2.3      2018-06-12 CRAN (R 3.5.0)                  
##  stringr    * 1.3.1      2018-05-10 CRAN (R 3.5.0)                  
##  tibble     * 1.4.2      2018-01-22 CRAN (R 3.5.0)                  
##  tidyr      * 0.8.1      2018-05-18 CRAN (R 3.5.0)                  
##  tidyselect   0.2.4      2018-02-26 CRAN (R 3.5.0)                  
##  tidyverse  * 1.2.1      2017-11-14 CRAN (R 3.5.0)                  
##  tools        3.5.1      2018-07-05 local                           
##  utils      * 3.5.1      2018-07-05 local                           
##  withr        2.1.2      2018-07-16 Github (jimhester/withr@fe56f20)
##  xml2         1.2.0      2018-01-24 CRAN (R 3.5.0)                  
##  yaml         2.1.19     2018-05-01 CRAN (R 3.5.0)
LS0tCnRpdGxlOiAiQ2xlYW4gZGF0YSIKYXV0aG9yOiAiQW5kcmV3IEhlaXNzIGFuZCBTdXBhcm5hIENoYXVkaHJ5IgpkYXRlOiAiTGFzdCBydW46IGByIGZvcm1hdChTeXMudGltZSgpLCAnJUIgJWUsICVZJylgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKIyBMb2FkIGFuZCBjbGVhbiBkYXRhCgpgYGB7ciBjbGVhbi1kYXRhLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShoZXJlKQpsaWJyYXJ5KGNzdnkpCgojIENhbGN1bGF0ZSB0aGUgcXVhbnRpbGUgKGFuZCBtZWRpYW4pIG9mIGFuIG9yZGVyZWQgZmFjdG9yCiMgQm9ycm93ZWQgZnJvbSBAanJub2xkOiBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9qcm5vbGQvNjc1OTI1NAojCiMgSW4gdGhlIGNhc2Ugb2YgdGllcywgdGhlIGZpcnN0IGluIG9yZGVyIHdpbGwgd2luLiBGb3IgaW5zdGFuY2UsIAojIGJsb29wIDwtIGZhY3RvcihjKCJBIiwgIkEiLCAiQiIsICJCIiksIG9yZGVyZWQgPSBUUlVFKQojIG1lZGlhbihibG9vcCkgICMgIkEiCnF1YW50aWxlLm9yZGVyZWQgPC0gZnVuY3Rpb24oeCwgcHJvYnMgPSBzZXEoMCwgMSwgMC4yNSkpIHsKICB0YWIgPC0gdGFibGUoeCkKICBjZGYgPC0gY3Vtc3VtKHRhYiAvIHN1bSh0YWIpKQogIGlkeCA8LSBzYXBwbHkocHJvYnMsIGZ1bmN0aW9uKHApIG1pbih3aGljaChjZGYgPj0gcCkpKQogIGxldmVscyh4KVtpZHhdIAp9CgpxdWFudGlsZS5mYWN0b3IgPC0gcXVhbnRpbGUub3JkZXJlZAptZWRpYW4ub3JkZXJlZCA8LSBmdW5jdGlvbih4KSBxdWFudGlsZSh4LCAwLjUpCm1lZGlhbi5mYWN0b3IgPC0gbWVkaWFuLm9yZGVyZWQKCgojIExvYWQgZGF0YQojIHJlc3VsdHNfZmlsZSA8LSBmaWxlLnBhdGgoaGVyZSgpLCAiZGF0YSIsICJ0ZXN0X2RhdGEuY3N2IikKcmVzdWx0c19maWxlIDwtIGhlcmUoInByaXZhdGUiLCAKICAgICAgICAgICAgICAgICAgICAgIk5HTyBDcmFja2Rvd25zIGFuZCBQaGlsYW50aHJvcHksIE1hcmNoIDIwMTggcGlsb3RfTWFyY2ggMjMsIDIwMThfMjAuMDEuY3N2IikKCiMgUG9zc2libGUgYW5zd2VycwpmYXZvcmFiaWxpdHkgPC0gYygiVmVyeSB1bmZhdm9yYWJsZSIsICJVbmZhdm9yYWJsZSIsICJOZXV0cmFsIiwgCiAgICAgICAgICAgICAgICAgICJGYXZvcmFibGUiLCAiVmVyeSBmYXZvcmFibGUiKQoKbGlrZWxpaG9vZCA8LSBjKCJFeHRyZW1lbHkgdW5saWtlbHkiLCAiU29tZXdoYXQgdW5saWtlbHkiLCAKICAgICAgICAgICAgICAgICJOZWl0aGVyIGxpa2VseSBub3IgdW5saWtlbHkiLCAKICAgICAgICAgICAgICAgICJTb21ld2hhdCBsaWtlbHkiLCAiRXh0cmVtZWx5IGxpa2VseSIpCgpmcmVxdWVuY3lfY2hhcml0eSA8LSBjKCJPbmNlIGEgd2VlayIsICJPbmNlIGEgbW9udGgiLCAiT25jZSBldmVyeSB0aHJlZSBtb250aHMiLCAKICAgICAgICAgICAgICAgICAgICAgICAiT25jZSBldmVyeSBzaXggbW9udGhzIiwgIk9uY2UgYSB5ZWFyIiwgIk9uY2UgZXZlcnkgZmV3IHllYXJzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIk5ldmVyIikKCmZyZXF1ZW5jeV9wdWJsaWNfYWZmYWlycyA8LSBjKCJNb3N0IG9mIHRoZSB0aW1lIiwgIlNvbWUgb2YgdGhlIHRpbWUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9ubHkgbm93IGFuZCB0aGVuIiwgIkhhcmRseSBhdCBhbGwiKQoKbGV2ZWxzX2lkZW9sb2d5IDwtIGMoIlN0cm9uZyBsaWJlcmFsIiwgIkxpYmVyYWwiLCAiSW5kZXBlbmRlbnQsIGxlYW5pbmcgbGliZXJhbCIsIAogICAgICAgICAgICAgICAgICAgICAiSW5kZXBlbmRlbnQiLCAiSW5kZXBlbmRlbnQsIGxlYW5pbmcgY29uc2VydmF0aXZlIiwgCiAgICAgICAgICAgICAgICAgICAgICJDb25zZXJ2YXRpdmUiLCAiVmVyeSBjb25zZXJ2YXRpdmUiKQoKbGV2ZWxzX2VkdWNhdGlvbiA8LSBjKCJMZXNzIHRoYW4gaGlnaCBzY2hvb2wiLCAiSGlnaCBzY2hvb2wgZ3JhZHVhdGUiLCAKICAgICAgICAgICAgICAgICAgICAgICJTb21lIGNvbGxlZ2UiLCAiMiB5ZWFyIGRlZ3JlZSIsICI0IHllYXIgZGVncmVlIiwgCiAgICAgICAgICAgICAgICAgICAgICAiR3JhZHVhdGUgb3IgcHJvZmVzc2lvbmFsIGRlZ3JlZSIsICJEb2N0b3JhdGUiKQoKZnJlcXVlbmN5X3JlbGlnaW9uIDwtIGMoIk1vcmUgdGhhbiBvbmNlIGEgd2VlayIsICJPbmNlIGEgd2VlayIsICJPbmNlIG9yIHR3aWNlIGEgbW9udGgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIkEgZmV3IHRpbWVzIGEgeWVhciIsICJTZWxkb20iLCAiTmV2ZXIiLCAiRG9uJ3Qga25vdyIpCgpsZXZlbHNfZ2VuZGVyIDwtIGMoIkZlbWFsZSIsICJNYWxlIiwgIlRyYW5zZ2VuZGVyIiwgIk90aGVyIiwgIlByZWZlciBub3QgdG8gc2F5IikKCmxldmVsc19pbmNvbWUgPC0gYygiTGVzcyB0aGFuICQxMCwwMDAiLCAiJDEwLDAwMCDigJMgJDE5LDk5OSIsICIkMjAsMDAwIOKAkyAkMjksOTk5IiwgCiAgICAgICAgICAgICAgICAgICAiJDMwLDAwMCDigJMgJDM5LDk5OSIsICIkNDAsMDAwIOKAkyAkNDksOTk5IiwgIiQ1MCwwMDAg4oCTICQ1OSw5OTkiLCAKICAgICAgICAgICAgICAgICAgICIkNjAsMDAwIOKAkyAkNjksOTk5IiwgIiQ3MCwwMDAg4oCTICQ3OSw5OTkiLCAiJDgwLDAwMCDigJMgJDg5LDk5OSIsIAogICAgICAgICAgICAgICAgICAgIiQ5MCwwMDAg4oCTICQ5OSw5OTkiLCAiJDEwMCwwMDAg4oCTICQxNDksOTk5IiwgIk1vcmUgdGhhbiAkMTUwLDAwMCIsIAogICAgICAgICAgICAgICAgICAgIlByZWZlciBub3QgdG8gc2F5IikKCmxldmVsc19hZ2UgPC0gYygiVW5kZXIgMTgiLCAiMTgg4oCTIDI0IiwgIjI1IOKAkyAzNCIsICIzNSDigJMgNDQiLCAiNDUg4oCTIDU0IiwgCiAgICAgICAgICAgICAgICAiNTUg4oCTIDY0IiwgIjY1IOKAkyA3NCIsICI3NSDigJMgODQiLCAiODUgb3Igb2xkZXIiKQoKYXR0ZW50aW9uMV9hbnN3ZXIgPC0gYygiR3JlZW4iLCAiWWVsbG93IikKYXR0ZW50aW9uMl9hbnN3ZXIgPC0gIkJsdWUiCmxldmVsc19hdHRlbnRpb24gPC0gYygiQ29ycmVjdCIsICJJbmNvcnJlY3QiKQoKIyBRdWFsdHJpY3Mgc3RvcmVzIHF1ZXN0aW9uIGluZm9ybWF0aW9uIGluIHRoZSBmaXJzdCAzIHJvd3MuIEFsbCB3ZSBjYXJlIGFib3V0CiMgYXJlIHRoZSBjb2x1bW4gbmFtZXMgaW4gdGhlIGZpcnN0IHJvdy4KcmVzdWx0c19tZXRhIDwtIHJlYWRfY3N2KHJlc3VsdHNfZmlsZSwgbl9tYXggPSAyKQoKIyBUaGUgZmlyc3QgMTAgcm93cyBuZWVkIHRvIGJlIHNraXBwZWQgYmVjYXVzZSB0aGUgY29uc2VudCBxdWVzdGlvbiBoYXMgYSBidW5jaAojIG9mIGxpbmUgYnJlYWtzIGFuZCBpdCBtZXNzZXMgd2l0aCBDU1YgbGluZSBjb3VudGluZy4gVGhlIGFjdHVhbCByZXNwb25zZXMKIyBzdGFydCBvbiByb3cgMTEuIFRoaXMgZG9lc24ndCBlbnRpcmVseSBtYWtlIHNlbnNlLCBzaW5jZSByZWFkX2NzdiBjYW4gcmVhZCB0aGUKIyBsaW5lIGJyZWFrLWZpbGxlZCByb3cgaW4ganVzdCBmaW5lLiBTa2lwcGluZyBzYWlkIGxpbmVzIG1ha2VzIGl0IGNob2tlLiA8c2hydWc+CnJlc3VsdHNfcmF3IDwtIHJlYWRfY3N2KHJlc3VsdHNfZmlsZSwgc2tpcCA9IDE2LAogICAgICAgICAgICAgICAgICAgICAgICBjb2xfbmFtZXMgPSBjb2xuYW1lcyhyZXN1bHRzX21ldGEpKQoKIyBDb25maXJtYXRpb24gY29kZXMgdG8gZXhjbHVkZS4gVGhlc2UgYXJlIHBlb3BsZSB3aG8gZmFpbGVkIHRoZSBhdHRlbnRpb24KIyBjaGVja3Mgb3Igd2hvIHRvb2sgdGhlIHN1cnZleSBvdXRzaWRlIG9mIE1UdXJrLgojCiMgVGhlIGNvZGUgZm9yIGRldGVybWluaW5nIHRoZXNlIGlzIGluIGEgc2NyaXB0IHRoYXQgaXMgZXhjbHVkZWQgZnJvbSB0aGUgbWFpbgojIHJlcG9zaXRvcnkgYmVjYXVzZSBvZiBwcml2YWN5IGlzc3VlcyAoaXQgZGVhbHMgZGlyZWN0bHkgd2l0aCBNVHVyayB3b3JrZXIKIyBJRHMpLCBjYWxsZWQgInByaXZhdGUvYXBwcm92ZV9tdHVya2Vycy5SIi4gSXQgb3V0cHV0cyB0aGlzIHRleHQgbGlzdCBvZiBjb2Rlcy4KY29kZXNfdG9fZXhjbHVkZSA8LSByZWFkX2NzdihoZXJlKCJkYXRhIiwgImNvZGVzX3RvX2V4Y2x1ZGUuY3N2IikpCgojIENsZWFuIGV2ZXJ5dGhpbmcKcmVzdWx0c19jaGVja19hdHRlbnRpb24gPC0gcmVzdWx0c19yYXcgJT4lCiAgIyBPbmx5IHNlbGVjdCBuZWNlc3NhcnkgY29sdW1ucwogIHNlbGVjdChpZCA9IFJlc3BvbnNlSWQsIGNvbmZpcm1hdGlvbl9jb2RlID0gbVR1cmtDb2RlLCBkdXJhdGlvbiA9IGBEdXJhdGlvbiAoaW4gc2Vjb25kcylgLAogICAgICAgICBzdGFydF9kYXRlID0gU3RhcnREYXRlLCBlbmRfZGF0ZSA9IEVuZERhdGUsCiAgICAgICAgIGNyYWNrZG93biwgaXNzdWUsIGZ1bmRpbmcsIHN0YXJ0c193aXRoKCJRIikpICU+JQogIHJlbmFtZShmYXZvcl9odW1hbml0YXJpYW4gPSBRMi4xXzEsIGZhdm9yX2h1bWFuX3JpZ2h0cyA9IFEyLjFfMiwgCiAgICAgICAgIGZhdm9yX2RldmVsb3BtZW50ID0gUTIuMV8zLCBkb25hdGVfbGlrZWx5ID0gUTIuMywgCiAgICAgICAgIGFtb3VudF9kb25hdGUgPSBRMi40XzEsIGFtb3VudF9rZWVwID0gUTIuNF8yLCBhbW91bnRfd2h5ID0gUTIuNSwKICAgICAgICAgZ2l2ZV9jaGFyaXR5ID0gUTMuMiwgdm9sdW50ZWVyID0gUTMuMywgcG9saXRpY2FsX2tub3dsZWRnZSA9IFEzLjQsCiAgICAgICAgIGlkZW9sb2d5ID0gUTMuNSwgZWR1Y2F0aW9uID0gUTMuNiwgcmVsaWdpb3NpdHkgPSBRMy43LAogICAgICAgICBnZW5kZXIgPSBRMy45LCBnZW5kZXJfb3RoZXIgPSBRMy45XzRfVEVYVCwgaW5jb21lID0gUTMuMTAsIGFnZSA9IFEzLjExKSAlPiUKICAjIENsZWFuIHVwIGV4cGVyaW1lbnRhbCBjb25kaXRpb24gY29sdW1ucwogIG11dGF0ZShpc3N1ZSA9IHJlY29kZShpc3N1ZSwgYGh1bWFuIHJpZ2h0cyBmb3IgcmVmdWdlZXNgID0gIkh1bWFuIHJpZ2h0cyIsCiAgICAgICAgICAgICAgICAgICAgICAgIGBodW1hbml0YXJpYW4gYXNzaXN0YW5jZSBmb3IgcmVmdWdlZXNgID0gIkh1bWFuaXRhcmlhbiBhc3Npc3RhbmNlIiksCiAgICAgICAgIGZ1bmRpbmcgPSByZWNvZGUoZnVuZGluZywgYGdvdmVybm1lbnQgZG9ub3JzYCA9ICJHb3Zlcm5tZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBgaW5kaXZpZHVhbCwgcHJpdmF0ZSBkb25vcnNgID0gIlByaXZhdGUiKSkgJT4lCiAgbXV0YXRlKGNyYWNrZG93biA9IGlmZWxzZShzdHJfZGV0ZWN0KGNyYWNrZG93biwgImhhcnNobHkgcmVzdHJpY3QiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ3JhY2tkb3duIiwgIk5vIGNyYWNrZG93biIpKSAlPiUgCiAgbXV0YXRlKGNyYWNrZG93biA9IGZhY3RvcihjcmFja2Rvd24sIGxldmVscyA9IGMoIk5vIGNyYWNrZG93biIsICJDcmFja2Rvd24iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSksCiAgICAgICAgIGlzc3VlID0gZmFjdG9yKGlzc3VlLCBsZXZlbHMgPSBjKCJIdW1hbiByaWdodHMiLCAiSHVtYW5pdGFyaWFuIGFzc2lzdGFuY2UiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSwKICAgICAgICAgZnVuZGluZyA9IGZhY3RvcihmdW5kaW5nLCBsZXZlbHMgPSBjKCJHb3Zlcm5tZW50IiwgIlByaXZhdGUiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKSAlPiUgCiAgIyBBdHRlbnRpb24gY2hlY2tzCiAgbXV0YXRlKGF0dGVudGlvbjFfY29ycmVjdCA9IHN0cl9zcGxpdChRMS4zLCAiLCIpICU+JSAKICAgICAgICAgICBtYXBfbGdsKH4gYWxsKGF0dGVudGlvbjFfYW5zd2VyICVpbiUgLikgJiBsZW5ndGgoLikgPT0gbGVuZ3RoKGF0dGVudGlvbjFfYW5zd2VyKSksCiAgICAgICAgIGF0dGVudGlvbjJfY29ycmVjdCA9IFEzLjggPT0gYXR0ZW50aW9uMl9hbnN3ZXIpICU+JSAKICAjIFRoaXMgcGVyc29uIGNvbnRhY3RlZCBtZSBzZXBhcmF0ZWx5IHRvIHNheSB0aGF0IHRoZXkgYWNjaWRlbnRhbGx5IGRpZCB0aGUgZmlyc3QKICAjIGF0dGVudGlvbiBjaGVjayB3cm9uZywgYnV0IHRoYXQgdGhleSBkaWQgcGF5IGF0dGVudGlvbjogNjUxODYzNAogIG11dGF0ZShhdHRlbnRpb24xX2NvcnJlY3QgPSBpZmVsc2UoY29uZmlybWF0aW9uX2NvZGUgPT0gNjUxODYzNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUsIGF0dGVudGlvbjFfY29ycmVjdCkpIAoKcmVzdWx0cyA8LSByZXN1bHRzX2NoZWNrX2F0dGVudGlvbiAlPiUgCiAgZmlsdGVyKCEoY29uZmlybWF0aW9uX2NvZGUgJWluJSBjb2Rlc190b19leGNsdWRlJGNvbmZpcm1hdGlvbl9jb2RlKSkgJT4lCiAgIyBGYWN0b3JpemUgdmFyaWFibGVzCiAgbXV0YXRlKGRvbmF0ZV9saWtlbHkgPSBmYWN0b3IoZG9uYXRlX2xpa2VseSwgbGV2ZWxzID0gbGlrZWxpaG9vZCwgb3JkZXJlZCA9IFRSVUUpKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoZmF2b3JfaHVtYW5pdGFyaWFuLCBmYXZvcl9odW1hbl9yaWdodHMsIGZhdm9yX2RldmVsb3BtZW50KSwKICAgICAgICAgICAgZnVucyhmYWN0b3IoLiwgbGV2ZWxzID0gZmF2b3JhYmlsaXR5LCBvcmRlcmVkID0gVFJVRSkpKSAlPiUgCiAgbXV0YXRlKGdpdmVfY2hhcml0eSA9IGZhY3RvcihnaXZlX2NoYXJpdHksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gZnJlcXVlbmN5X2NoYXJpdHksIG9yZGVyZWQgPSBUUlVFKSwKICAgICAgICAgdm9sdW50ZWVyID0gZmFjdG9yKHZvbHVudGVlciwgbGV2ZWxzID0gYygiTm8iLCAiWWVzIiksIG9yZGVyZWQgPSBUUlVFKSwKICAgICAgICAgcG9saXRpY2FsX2tub3dsZWRnZSA9IGZhY3Rvcihwb2xpdGljYWxfa25vd2xlZGdlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBmcmVxdWVuY3lfcHVibGljX2FmZmFpcnMsIG9yZGVyZWQgPSBUUlVFKSwKICAgICAgICAgaWRlb2xvZ3kgPSBmYWN0b3IoaWRlb2xvZ3ksIGxldmVscyA9IGxldmVsc19pZGVvbG9neSwgb3JkZXJlZCA9IFRSVUUpLAogICAgICAgICBlZHVjYXRpb24gPSBmYWN0b3IoZWR1Y2F0aW9uLCBsZXZlbHMgPSBsZXZlbHNfZWR1Y2F0aW9uLCBvcmRlcmVkID0gVFJVRSksCiAgICAgICAgIHJlbGlnaW9zaXR5ID0gZmFjdG9yKHJlbGlnaW9zaXR5LCBsZXZlbHMgPSBmcmVxdWVuY3lfcmVsaWdpb24sIG9yZGVyZWQgPSBUUlVFKSwKICAgICAgICAgZ2VuZGVyID0gcmVjb2RlKGdlbmRlciwgYE90aGVyOmAgPSAiT3RoZXIiKSwKICAgICAgICAgZ2VuZGVyID0gZmFjdG9yKGdlbmRlciwgbGV2ZWxzID0gbGV2ZWxzX2dlbmRlciwgb3JkZXJlZCA9IFRSVUUpLAogICAgICAgICBpbmNvbWUgPSBmYWN0b3IoaW5jb21lLCBsZXZlbHMgPSBsZXZlbHNfaW5jb21lLCBvcmRlcmVkID0gVFJVRSksCiAgICAgICAgIGFnZSA9IGZhY3RvcihhZ2UsIGxldmVscyA9IGxldmVsc19hZ2UsIG9yZGVyZWQgPSBUUlVFKSwKICAgICAgICAgY2hlY2sxID0gZmFjdG9yKGF0dGVudGlvbjFfY29ycmVjdCwgbGV2ZWxzID0gYyhUUlVFLCBGQUxTRSksCiAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBsZXZlbHNfYXR0ZW50aW9uLCBvcmRlcmVkID0gVFJVRSksCiAgICAgICAgIGNoZWNrMiA9IGZhY3RvcihhdHRlbnRpb24yX2NvcnJlY3QsIGxldmVscyA9IGMoVFJVRSwgRkFMU0UpLAogICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gbGV2ZWxzX2F0dGVudGlvbiwgb3JkZXJlZCA9IFRSVUUpKSAlPiUgCiAgIyBEaWNob3RvbWl6ZSB2YXJpYWJsZXMKICBtdXRhdGUoZG9uYXRlX2xpa2VseV9iaW4gPSBmY3RfcmVjb2RlKGRvbmF0ZV9saWtlbHksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTm90IGxpa2VseWAgPSAiRXh0cmVtZWx5IHVubGlrZWx5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBOb3QgbGlrZWx5YCA9ICJTb21ld2hhdCB1bmxpa2VseSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTm90IGxpa2VseWAgPSAiTmVpdGhlciBsaWtlbHkgbm9yIHVubGlrZWx5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExpa2VseSA9ICJTb21ld2hhdCBsaWtlbHkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTGlrZWx5ID0gIkV4dHJlbWVseSBsaWtlbHkiKSkgJT4lIAogIG11dGF0ZV9hdCh2YXJzKGZhdm9yX2h1bWFuaXRhcmlhbiwgZmF2b3JfaHVtYW5fcmlnaHRzLCBmYXZvcl9kZXZlbG9wbWVudCksCiAgICAgICAgICAgIGZ1bnMoYmluID0gZmN0X3JlY29kZSguLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBOb3QgZmF2b3JhYmxlYCA9ICJWZXJ5IHVuZmF2b3JhYmxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBOb3QgZmF2b3JhYmxlYCA9ICJVbmZhdm9yYWJsZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTm90IGZhdm9yYWJsZWAgPSAiTmV1dHJhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGYXZvcmFibGUgPSAiRmF2b3JhYmxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZhdm9yYWJsZSA9ICJWZXJ5IGZhdm9yYWJsZSIpKSkgJT4lIAogIG11dGF0ZShnaXZlX2NoYXJpdHlfMyA9IGZjdF9yZWNvZGUoZ2l2ZV9jaGFyaXR5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEF0IGxlYXN0IG9uY2UgYSBtb250aGAgPSAiT25jZSBhIHdlZWsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEF0IGxlYXN0IG9uY2UgYSBtb250aGAgPSAiT25jZSBhIG1vbnRoIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBPbmNlIGEgbW9udGgtb25jZSBhIHllYXJgID0gIk9uY2UgZXZlcnkgdGhyZWUgbW9udGhzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBPbmNlIGEgbW9udGgtb25jZSBhIHllYXJgID0gIk9uY2UgZXZlcnkgc2l4IG1vbnRocyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgT25jZSBhIG1vbnRoLW9uY2UgYSB5ZWFyYCA9ICJPbmNlIGEgeWVhciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSYXJlbHkgPSAiT25jZSBldmVyeSBmZXcgeWVhcnMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUmFyZWx5ID0gIk5ldmVyIikgJT4lIGZjdF9yZXYoKSwKICAgICAgICAgZ2l2ZV9jaGFyaXR5XzIgPSBmY3RfcmVjb2RlKGdpdmVfY2hhcml0eSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBBdCBsZWFzdCBvbmNlIGEgeWVhcmAgPSAiT25jZSBhIHdlZWsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEF0IGxlYXN0IG9uY2UgYSB5ZWFyYCA9ICJPbmNlIGEgbW9udGgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEF0IGxlYXN0IG9uY2UgYSB5ZWFyYCA9ICJPbmNlIGV2ZXJ5IHRocmVlIG1vbnRocyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQXQgbGVhc3Qgb25jZSBhIHllYXJgID0gIk9uY2UgZXZlcnkgc2l4IG1vbnRocyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQXQgbGVhc3Qgb25jZSBhIHllYXJgID0gIk9uY2UgYSB5ZWFyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJhcmVseSA9ICJPbmNlIGV2ZXJ5IGZldyB5ZWFycyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBSYXJlbHkgPSAiTmV2ZXIiKSkgJT4lIAogIG11dGF0ZShwb2xpdGljYWxfa25vd2xlZGdlX2JpbiA9IGZjdF9yZWNvZGUocG9saXRpY2FsX2tub3dsZWRnZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBPZnRlbmAgPSAiTW9zdCBvZiB0aGUgdGltZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgT2Z0ZW5gID0gIlNvbWUgb2YgdGhlIHRpbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYE5vdCBvZnRlbmAgPSAiT25seSBub3cgYW5kIHRoZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYE5vdCBvZnRlbmAgPSAiSGFyZGx5IGF0IGFsbCIpICU+JSBmY3RfcmV2KCkpICU+JSAKICBtdXRhdGUoaWRlb2xvZ3lfMyA9IGZjdF9yZWNvZGUoaWRlb2xvZ3ksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBMaWJlcmFsYCA9ICJTdHJvbmcgbGliZXJhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBMaWJlcmFsYCA9ICJMaWJlcmFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYExpYmVyYWxgID0gIkluZGVwZW5kZW50LCBsZWFuaW5nIGxpYmVyYWwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgSW5kZXBlbmRlbnRgID0gIkluZGVwZW5kZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYENvbnNlcnZhdGl2ZWAgPSAiSW5kZXBlbmRlbnQsIGxlYW5pbmcgY29uc2VydmF0aXZlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYENvbnNlcnZhdGl2ZWAgPSAiQ29uc2VydmF0aXZlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYENvbnNlcnZhdGl2ZWAgPSAiVmVyeSBjb25zZXJ2YXRpdmUiKSAlPiUgZmN0X3JldigpKSAlPiUgCiAgbXV0YXRlKGlkZW9sb2d5X2JpbiA9IGZjdF9yZWNvZGUoaWRlb2xvZ3lfMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTm90IGxpYmVyYWxgID0gIkluZGVwZW5kZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTm90IGxpYmVyYWxgID0gIkNvbnNlcnZhdGl2ZSIpKSAlPiUgCiAgbXV0YXRlKGVkdWNhdGlvbl9iaW4gPSBmY3RfcmVjb2RlKGVkdWNhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYE5vIEJBYCA9ICJMZXNzIHRoYW4gaGlnaCBzY2hvb2wiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTm8gQkFgID0gIkhpZ2ggc2Nob29sIGdyYWR1YXRlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYE5vIEJBYCA9ICJTb21lIGNvbGxlZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTm8gQkFgID0gIjIgeWVhciBkZWdyZWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQkEgYW5kIGFib3ZlYCA9ICI0IHllYXIgZGVncmVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEJBIGFuZCBhYm92ZWAgPSAiR3JhZHVhdGUgb3IgcHJvZmVzc2lvbmFsIGRlZ3JlZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBCQSBhbmQgYWJvdmVgID0gIkRvY3RvcmF0ZSIpKSAlPiUgCiAgbXV0YXRlKHJlbGlnaW9zaXR5X2JpbiA9IGZjdF9yZWNvZGUocmVsaWdpb3NpdHksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEF0IGxlYXN0IG9uY2UgYSBtb250aGAgPSAiTW9yZSB0aGFuIG9uY2UgYSB3ZWVrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgQXQgbGVhc3Qgb25jZSBhIG1vbnRoYCA9ICJPbmNlIGEgd2VlayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEF0IGxlYXN0IG9uY2UgYSBtb250aGAgPSAiT25jZSBvciB0d2ljZSBhIG1vbnRoIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgUmFyZWx5YCA9ICJBIGZldyB0aW1lcyBhIHllYXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBSYXJlbHlgID0gIlNlbGRvbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFJhcmVseWAgPSAiTmV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5VTEwgPSAiRG9uJ3Qga25vdyIpICU+JSBmY3RfcmV2KCkpICU+JSAKICBtdXRhdGUoaW5jb21lX2NsZWFuID0gZmN0X3JlY29kZShpbmNvbWUsIE5VTEwgPSAiUHJlZmVyIG5vdCB0byBzYXkiKSwKICAgICAgICAgaW5jb21lX2JpbiA9IGZhY3RvcihpbmNvbWVfY2xlYW4gPj0gbWVkaWFuKC4kaW5jb21lKSwgbGV2ZWxzID0gYyhGQUxTRSwgVFJVRSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gcGFzdGUoYygiTGVzcyB0aGFuIiwgIkF0IGxlYXN0IiksIG1lZGlhbiguJGluY29tZSkpKSkgJT4lIAogIG11dGF0ZShhZ2VfYmluID0gZmFjdG9yKGFnZSA+PSBtZWRpYW4oLiRhZ2UpLCBsZXZlbHMgPSBjKEZBTFNFLCBUUlVFKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBwYXN0ZShjKCJMZXNzIHRoYW4iLCAiQXQgbGVhc3QiKSwgbWVkaWFuKC4kYWdlKSkpLAogICAgICAgICBnZW5kZXJfYmluID0gZmN0X2NvbGxhcHNlKGdlbmRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGZW1hbGUgPSAiRmVtYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTm90IEZlbWFsZWAgPSBjKCJNYWxlIiwgIlRyYW5zZ2VuZGVyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT3RoZXIiLCAiUHJlZmVyIG5vdCB0byBzYXkiKSkpCgojIFNhdmUgZmluYWwgY2xlYW4gZGF0YQpzYXZlUkRTKHJlc3VsdHMsIGhlcmUoImRhdGEiLCAicmVzdWx0c19jbGVhbi5yZHMiKSkKd3JpdGVfY3N2eShyZXN1bHRzLCBmaWxlID0gaGVyZSgiZGF0YSIsICJyZXN1bHRzX2NsZWFuLmNzdiIpLAogICAgICAgICAgIG1ldGFkYXRhID0gaGVyZSgiZGF0YSIsICJyZXN1bHRzX2NsZWFuLnlhbWwiKSwgbmEgPSAiTkEiKQpgYGAKCmBgYHtyIGNvbXBsZXRlZC1zdW1tYXJ5fQojIFNhdmUgaW5mb3JtYXRpb24gYWJvdXQgY29tcGxldGlvbiByYXRlcwpjb21wbGV0ZWRfc2tlbGV0b24gPC0gcmVzdWx0c19jaGVja19hdHRlbnRpb24gJT4lIAogIGxlZnRfam9pbihjb2Rlc190b19leGNsdWRlLCBieSA9ICJjb25maXJtYXRpb25fY29kZSIpICU+JSAKICByZXBsYWNlX25hKGxpc3QocmVhc29uID0gIkFwcHJvdmVkIikpICU+JSAKICBleHBhbmQocmVhc29uLCBjcmFja2Rvd24sIGlzc3VlLCBmdW5kaW5nKQoKY29tcGxldGVkX3N1bW1hcnkgPC0gcmVzdWx0c19jaGVja19hdHRlbnRpb24gJT4lIAogIGxlZnRfam9pbihjb2Rlc190b19leGNsdWRlLCBieSA9ICJjb25maXJtYXRpb25fY29kZSIpICU+JSAKICByZXBsYWNlX25hKGxpc3QocmVhc29uID0gIkFwcHJvdmVkIikpICU+JSAKICBjb3VudChyZWFzb24sIGNyYWNrZG93biwgaXNzdWUsIGZ1bmRpbmcpICU+JSAKICByaWdodF9qb2luKGNvbXBsZXRlZF9za2VsZXRvbiwgYnkgPSBjKCJyZWFzb24iLCAiY3JhY2tkb3duIiwgImlzc3VlIiwgImZ1bmRpbmciKSkgJT4lIAogIHJlcGxhY2VfbmEobGlzdChuID0gMCkpCgpzYXZlUkRTKGNvbXBsZXRlZF9zdW1tYXJ5LCBoZXJlKCJkYXRhIiwgImNvbXBsZXRpb25fc3VtbWFyeS5yZHMiKSkKd3JpdGVfY3N2KGNvbXBsZXRlZF9zdW1tYXJ5LCBoZXJlKCJkYXRhIiwgImNvbXBsZXRpb25fc3VtbWFyeS5jc3YiKSkKYGBgCgoKIyBPcmlnaW5hbCBjb21wdXRpbmcgZW52aXJvbm1lbnQKCjxidXR0b24gZGF0YS10b2dnbGU9ImNvbGxhcHNlIiBkYXRhLXRhcmdldD0iI3Nlc3Npb25pbmZvIiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IGJ0bi1tZCBidG4taW5mbyI+SGVyZSdzIHdoYXQgd2UgdXNlZCB0aGUgbGFzdCB0aW1lIHdlIGJ1aWx0IHRoaXMgcGFnZTwvYnV0dG9uPgoKPGRpdiBpZD0ic2Vzc2lvbmluZm8iIGNsYXNzPSJjb2xsYXBzZSI+CgpgYGB7ciBzaG93LXNlc3Npb24taW5mbywgZWNobz1UUlVFfQp3cml0ZUxpbmVzKHJlYWRMaW5lcyhmaWxlLnBhdGgoU3lzLmdldGVudigiSE9NRSIpLCAiLlIvTWFrZXZhcnMiKSkpCgpkZXZ0b29sczo6c2Vzc2lvbl9pbmZvKCkKYGBgCgo8L2Rpdj4gIAo=