library(tidyverse)
library(fastDummies)
library(scales)
library(readxl)
library(here)

# Turn off grouping message
options(dplyr.summarise.inform = FALSE)

# Project-specific functions
source(here("R", "graphics.R"))

# General settings
source(here("analysis", "options.R"))

# Make all the randomness reproducible
set.seed(1234)
sim_raw <- read_excel(here("data", "raw_data", "Market Simulator Version 01.xlsx"),
                      sheet = "Results", range = "O3:AU27")

orgs_raw <- read_excel(here("data", "raw_data", "Market Simulator Version 01.xlsx"),
                       sheet = "Results", range = "N4:O27", 
                       col_names = c("organization", "org_details"))

orgs_clean <- orgs_raw %>% 
  separate(org_details, into = c("org_issue", "org_funding", "org_relationship"), sep = ", ")

personas_raw <- read_excel(here("data", "raw_data", "Market Simulator Version 01.xlsx"),
                           sheet = "Results", range = "P2:AU3") %>% 
  pivot_longer(everything(), names_to = "persona", values_to = "persona_details")

personas_clean <- personas_raw %>% 
  separate(persona_details, into = c("demographics", "actions", "persona_trust"), sep = ", ") %>% 
  separate(demographics, into = c("persona_income", "persona_gender"), sep = " Income ") %>% 
  separate(actions, into = c("persona_ideology", "persona_experience"), sep = " that ") 

sim_long <- sim_raw %>% 
  rename(org_details = `...1`) %>% 
  pivot_longer(cols = -org_details, names_to = "persona_details", values_to = "share")

sim_excel_clean <- sim_long %>% 
  left_join(orgs_raw, by = "org_details") %>% 
  left_join(personas_raw, by = "persona_details") %>% 
  separate(org_details, into = c("org_issue", "org_funding", "org_relationship"), sep = ", ") %>% 
  separate(persona_details, into = c("demographics", "actions", "persona_trust"), sep = ", ") %>% 
  separate(demographics, into = c("persona_income", "persona_gender"), sep = " Income ") %>% 
  separate(actions, into = c("persona_ideology", "persona_experience"), sep = " that ") %>% 
  mutate(org_issue = recode(org_issue, "Refugess Relief" = "Refugee Relief"),
         org_funding = recode(org_funding, "Grants" = "Mostly funded by government grants",
                              "Small Donors" = "Mostly funded by small donors"),
         persona_income = paste(persona_income, "income"),
         persona_income = factor(persona_income, levels = c("Lower income", "Higher income"), ordered = TRUE),
         persona_trust = recode(persona_trust,
                                "Doesn't Trust or Donate" = "Less trusting; donates and volunteers less often",
                                "Trusts and Donates" = "More trusting; donates and volunteers often"),
         persona_experience = recode(persona_experience,
                                     "Doesn't Read or Travel" = "Doesn't follow news; has not travelled abroad",
                                     "Reads and Travels" = "Follows the news; has travelled abroad")) %>% 
  mutate_at(vars(organization, persona), ~fct_inorder(.))
# Gammas of the "everything" model
gammas <- read_rds(
  here('data', 'raw_data', 'posterior_draws', 'public_political_social_charity_demo.rds')
  ) %>% 
  group_by(i, j) %>% 
  summarize(gamma_mean = mean(Gamma)) %>% 
  ungroup() %>% 
  pivot_wider(names_from = j, values_from = gamma_mean) %>% 
  select(-i) %>% 
  t()
organization_columns <- c("organization", "issue.area", "transparency", 
                          "accountability", "funding", "relationship")

organization_possibilities <- expand_grid(
  issue.area = c("Emergency response", "Environment", "Human rights", "Refugee relief"),
  relationship = c("Friendly", "Criticized", "Under crackdown"),
  funding = c("Small private donations", "Government grants")
) %>% 
  mutate(org_id = paste0("org", 1:n()))

organizations <- organization_possibilities %>% 
  mutate(
    organization = "Red Cross",
    transparency = "Yes",
    accountability = "Yes"
  ) %>% 
  select(org_id, all_of(organization_columns)) %>% 
  mutate(organization = factor(organization, 
                               levels = c("Amnesty International", "Greenpeace", 
                                          "Oxfam", "Red Cross")),
         issue.area = factor(issue.area, 
                            levels = c("Emergency response", "Environment", 
                                       "Human rights", "Refugee relief")),
         transparency = factor(transparency, levels = c("No", "Yes")),
         accountability = factor(accountability, levels = c("No", "Yes")),
         funding = factor(funding, levels = c("Small private donations", 
                                              "Handful of wealthy private donors", 
                                              "Government grants")),
         relationship = factor(relationship, levels = c("Friendly", "Criticized", 
                                                        "Under crackdown")))

org_table <- organizations %>% 
  dummy_columns(select_columns = organization_columns,
                remove_selected_columns = TRUE) %>% 
  pivot_longer(cols = -org_id, names_to = "name", ) %>% 
  pivot_wider(names_from = org_id, values_from = value) %>% 
  separate(name, into = c("attribute", "option"), sep = "_") %>% 
  filter(!(option %in% c("Emergency response", "No", "Small private donations", "Friendly")))
persona_columns <- c("national.news", "international.news", "medium.follow.tv", 
                     "medium.follow.print", "medium.follow.online", "medium.follow.social", 
                     "medium.follow.radio", "medium.follow.email", "medium.follow.app", 
                     "follow.govt", "travel", "ideology", "trust.institutions", 
                     "should.be.charitable", "religious.attendance", "religion.importance", 
                     "religion", "trust.charity.importance", "trust.charities", 
                     "donation.frequency", "donated.last.year", "volunteered", 
                     "volunteer.frequency", "history.activism.personal", "history.activism.family",
                     "membership.church", "membership.sport", "membership.art", "membership.union", 
                     "membership.party", "membership.environment", "membership.professional", 
                     "membership.charitable", "membership.consumer", "membership.other", 
                     "gender", "marital", "education", "income", "race", "age")

persona_demographics <- expand_grid(
  income = c("Less than median", "More than median"),
  education = c("High school graduate", "4 year degree"),
  religious.attendance = c("Rarely", "At least once a month")
) %>% 
  mutate(demographics_id = 1:n())

persona_politics <- tribble(
  ~ideology, ~national.news, ~international.news, ~travel,
  "Extremely liberal", "At least once a day",  "Always", "Yes",
  "Extremely conservative", "At least once a day", "Always", "Yes",
  "Extremely liberal", "Rarely", "Never", "No",
  "Extremely conservative", "Rarely", "Never", "No"
) %>% 
  mutate(politics_id = 1:n())

persona_social <- tibble(
  social_id = 1:2,
  trust.institutions = c("Complete trust", "No trust"),
  should.be.charitable = c("Strongly agree", "Strongly disagree"),
  trust.charities = c("Complete trust", "No trust"),
  volunteer.frequency = c("At least once a month", "Rarely"),
  donation.frequency = c("At least once a month", 
                         "More than once a month, less than once a year"),
  history.activism.personal = c("Involved", "Not involved"),
  membership.party = c("Active member", "Don't belong"),
  membership.charitable = c("Active member", "Don't belong")
)

persona_possibilities <- expand_grid(
  demographics_id = persona_demographics$demographics_id,
  politics_id = persona_politics$politics_id,
  social_id = persona_social$social_id
) %>% 
  left_join(persona_demographics, by = "demographics_id") %>% 
  left_join(persona_politics, by = "politics_id") %>% 
  left_join(persona_social, by = "social_id") %>% 
  select(-ends_with("_id")) %>% 
  mutate(persona_id = paste0("persona", 1:n()))

# Columns that should be held constant
# persona_columns %>% .[!(. %in% colnames(persona_possibilities))] %>% cat(sep = "\n")

personas <- persona_possibilities %>% 
  mutate(
    medium.follow.tv = "Follow",
    medium.follow.print = "Follow",
    medium.follow.online = "Don't follow",
    medium.follow.social = "Follow",
    medium.follow.radio = "Don't follow",
    medium.follow.email = "Don't follow",
    medium.follow.app = "Don't follow",
    follow.govt = "Often",
    religion.importance = "Important",
    religion = "Protestant",
    trust.charity.importance = "Somewhat important",
    donated.last.year = "$100-$499",
    volunteered = "No",
    history.activism.family = "Not involved",
    membership.church = "Don't belong",
    membership.sport = "Don't belong",
    membership.art = "Don't belong",
    membership.union = "Don't belong",
    membership.environment = "Don't belong",
    membership.professional = "Don't belong",
    membership.consumer = "Don't belong",
    membership.other = "Don't belong",
    gender = "Male",
    marital = "Married",
    race = "White",
    age = "Less than median"
  ) %>% 
  select(persona_id, all_of(persona_columns)) %>% 
  mutate(
    national.news = factor(national.news, levels = c("Rarely", "Once a week", "At least once a day")),
    international.news = factor(international.news, levels = c("Never", "Sometimes", "Always")),
    medium.follow.tv = factor(medium.follow.tv, levels = c("Don't follow", "Follow")),
    medium.follow.print = factor(medium.follow.print, levels = c("Don't follow", "Follow")),
    medium.follow.online = factor(medium.follow.online, levels = c("Don't follow", "Follow")),
    medium.follow.social = factor(medium.follow.social, levels = c("Don't follow", "Follow")),
    medium.follow.radio = factor(medium.follow.radio, levels = c("Don't follow", "Follow")),
    medium.follow.email = factor(medium.follow.email, levels = c("Don't follow", "Follow")),
    medium.follow.app = factor(medium.follow.app, levels = c("Don't follow", "Follow")),
    follow.govt = factor(follow.govt, levels = c("Not often", "Often")),
    travel = factor(travel, levels = c("No", "Yes")),
    ideology = factor(ideology, 
                      levels = c("Extremely liberal", "Somewhat liberal", 
                                 "Slightly liberal", "Moderate", "Slightly conservative", 
                                 "Somewhat conservative", "Extremely conservative")),
    trust.institutions = factor(trust.institutions,
                                levels = c("No trust", "Very little trust", "Little trust", 
                                           "Neutral", "Some trust", "A lot of trust", "Complete trust")),
    should.be.charitable = factor(should.be.charitable,
                                  levels = c("Strongly disagree", "Disagree", "Somewhat disagree", 
                                             "Neutral", "Somewhat agree", "Agree", "Strongly agree")),
    religious.attendance = factor(religious.attendance,
                                  levels = c("Not sure", "Rarely", "At least once a month")),
    religion.importance = factor(religion.importance,
                                 levels = c("Not important", "Important")),
    religion = factor(religion, 
                      levels = c("Catholic", "Protestant", "Christian Orthodox", "Jewish", 
                                 "Muslim", "Sikh", "Hindu", "Buddhist", "Atheist", "Other")),
    trust.charity.importance = factor(trust.charity.importance,
                                      levels = c("Not important", "Very unimportant", 
                                                 "Somewhat unimportant", "Neutral", 
                                                 "Somewhat important", "Very important", "Essential")),
    trust.charities = factor(trust.charities,
                             levels = c("No trust", "Very little trust", "Little trust", 
                                        "Neutral", "Some trust", "A lot of trust", "Complete trust")),
    donation.frequency = factor(donation.frequency,
                                levels = c("More than once a month, less than once a year", "At least once a month")),
    donated.last.year = factor(donated.last.year,
                               levels = c("$1-$49", "$50-$99", "$100-$499", "$500-$999", 
                                          "$1000-$4,999", "$5000-$9,999", "$10,000+")),
    volunteered = factor(volunteered, levels = c("No", "Yes")),
    volunteer.frequency = factor(volunteer.frequency,
                                 levels = c("Haven't volunteered in past 12 months", "Rarely", 
                                            "More than once a month, less than once a year", 
                                            "At least once a month")),
    history.activism.personal = factor(history.activism.personal,
                                       levels = c("Not involved", "Involved")),
    history.activism.family = factor(history.activism.family,
                                     levels = c("Not involved", "Involved")),
    membership.church = factor(membership.church,
                               levels  = c("Don't belong", "Inactive member", "Active member")),
    membership.sport = factor(membership.sport,
                              levels = c("Don't belong", "Inactive member", "Active member")),
    membership.art = factor(membership.art,
                            levels = c("Don't belong", "Inactive member", "Active member")),
    membership.union = factor(membership.union,
                              levels = c("Don't belong", "Inactive member", "Active member")),
    membership.party = factor(membership.party,
                              levels = c("Don't belong", "Inactive member", "Active member")),
    membership.environment = factor(membership.environment,
                                    levels = c("Don't belong", "Inactive member", "Active member")),
    membership.professional = factor(membership.professional,
                                     levels  = c("Don't belong", "Inactive member", "Active member")),
    membership.charitable = factor(membership.charitable,
                                   levels  = c("Don't belong", "Inactive member", "Active member")),
    membership.consumer = factor(membership.consumer,
                                 levels  = c("Don't belong", "Inactive member", "Active member")),
    membership.other = factor(membership.other,
                              levels = c("Don't belong", "Inactive member", "Active member")),
    gender = factor(gender,
                    levels = c("Male", "Female", "Transgender", "Prefer not to say", "Other")),
    marital = factor(marital,
                     levels = c("Married", "Widowed", "Divorced", "Separated", "Never married")),
    education = factor(education,
                       levels = c("Less than high school", "High school graduate", "Some college", 
                                  "2 year degree", "4 year degree", "Graduate or professional degree", "Doctorate")),
    income = factor(income,
                    levels = c("Less than median", "More than median")),
    race = factor(race,
                  levels = c("White", "Black or African American", "American Indian or Alaska Native", 
                             "Asian", "Native Hawaiian or Pacific Islander", "Other")),
    age = factor(age,
                 levels = c("Less than median", "More than median"))
  )

persona_base_cases <- c(
  "national.news_Rarely",
  "international.news_Never",
  "follow.govt_Not often",
  "travel_No",
  "ideology_Extremely liberal",
  "trust.institutions_No trust",
  "should.be.charitable_Strongly disagree",
  "religious.attendance_Not sure",
  "religion.importance_Not important",
  "religion_Catholic",
  "trust.charity.importance_Not important",
  "trust.charities_No trust",
  "donation.frequency_More than once a month, less than once a year",
  "donated.last.year_$1-$49",
  "volunteered_No",
  "volunteer.frequency_Haven't volunteered in past 12 months",
  "history.activism.personal_Not involved",
  "history.activism.family_Not involved",
  "gender_Male",
  "marital_Married",
  "education_Less than high school",
  "income_Less than median",
  "age_Less than median"
)

persona_table <- personas %>% 
  dummy_columns(select_columns = persona_columns,
                remove_selected_columns = TRUE) %>% 
  pivot_longer(cols = -persona_id, names_to = "name", ) %>% 
  pivot_wider(names_from = persona_id, values_from = value) %>% 
  # Get rid of base cases
  filter(!(name %in% persona_base_cases)) %>% 
  filter(!str_detect(name, "Don't follow"),
         !str_detect(name, "Don't belong")) %>% 
  separate(name, into = c("attribute", "option"), sep = "_") %>% 
  # Add intercept
  add_row(attribute = "Intercept", option = "Intercept", .before = 1) %>% 
  mutate(across(everything(), ~replace_na(., 1)))
predicted_betas <- persona_table %>% 
  summarize(across(starts_with("persona"), ~as.matrix(gammas) %*% as.matrix(.)))

expected_utilities <- exp(t(org_table[,3:ncol(org_table)]) %*% 
                            as.matrix(predicted_betas[,1:ncol(predicted_betas)])) %>% 
  as_tibble(rownames = "org")

prop_expected_utilities <- expected_utilities %>% 
  mutate(across(starts_with("persona"), ~. / sum(.)))
org_details <- organizations %>% 
  mutate(organization = str_replace(org_id, "org", "Org "),
         funding = fct_recode(funding, 
                              "Mostly funded by small donors" = "Small private donations",
                              "Mostly funded by government grants" = "Government grants"),
         relationship = fct_rev(relationship)) %>%
  select(org_id, organization, org_issue = issue.area, 
         org_funding = funding, org_relationship = relationship)

persona_details <- personas %>% 
  mutate(persona_income = fct_recode(income, 
                                     "Lower income" = "Less than median", 
                                     "Higher income" = "More than median"),
         persona_education = fct_recode(education, "College graduate" = "4 year degree"),
         persona_religion = fct_recode(religious.attendance, 
                                       "Rarely attends religious services" = "Rarely",
                                       "Attends at least monthly" = "At least once a month"),
         persona_ideology = fct_recode(ideology, 
                                       "Conservative" = "Extremely conservative",
                                       "Liberal" = "Extremely liberal"),
         persona_experience = ifelse(travel == "Yes", 
                                     "Follows the news; has travelled abroad", 
                                     "Doesn't follow news; has not travelled abroad"),
         persona_trust = ifelse(trust.charities == "Complete trust", 
                                "More trusting; donates and volunteers often", 
                                "Less trusting; donates and volunteers less often")) %>% 
  mutate(persona = str_replace(persona_id, "persona", "Persona ")) %>% 
  select(persona, starts_with("persona"))

sim_clean <- prop_expected_utilities %>% 
  pivot_longer(cols = -org, names_to = "persona_id", values_to = "share") %>% 
  left_join(org_details, by = c("org" = "org_id")) %>% 
  left_join(persona_details, by = "persona_id")
write_rds(sim_excel_clean, here("data", "derived_data", "sim_excel_final.rds"))
write_rds(sim_clean, here("data", "derived_data", "sim_final.rds"))


Original computing environment

devtools::session_info()
## ─ Session info ───────────────────────────────────────────────────────────────
##  setting  value                       
##  version  R version 4.0.2 (2020-06-22)
##  os       macOS Catalina 10.15.6      
##  system   x86_64, darwin17.0          
##  ui       X11                         
##  language (EN)                        
##  collate  en_US.UTF-8                 
##  ctype    en_US.UTF-8                 
##  tz       America/New_York            
##  date     2020-10-01                  
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package     * version date       lib source        
##  assertthat    0.2.1   2019-03-21 [1] CRAN (R 4.0.0)
##  backports     1.1.9   2020-08-24 [1] CRAN (R 4.0.2)
##  base64enc     0.1-3   2015-07-28 [1] CRAN (R 4.0.0)
##  blob          1.2.1   2020-01-20 [1] CRAN (R 4.0.0)
##  broom         0.7.0   2020-07-09 [1] CRAN (R 4.0.2)
##  callr         3.4.3   2020-03-28 [1] CRAN (R 4.0.0)
##  cellranger    1.1.0   2016-07-27 [1] CRAN (R 4.0.0)
##  cli           2.0.2   2020-02-28 [1] CRAN (R 4.0.0)
##  colorspace    1.4-1   2019-03-18 [1] CRAN (R 4.0.0)
##  crayon        1.3.4   2017-09-16 [1] CRAN (R 4.0.0)
##  data.table    1.13.0  2020-07-24 [1] CRAN (R 4.0.2)
##  DBI           1.1.0   2019-12-15 [1] CRAN (R 4.0.0)
##  dbplyr        1.4.4   2020-05-27 [1] CRAN (R 4.0.2)
##  desc          1.2.0   2018-05-01 [1] CRAN (R 4.0.0)
##  devtools      2.3.1   2020-07-21 [1] CRAN (R 4.0.2)
##  digest        0.6.25  2020-02-23 [1] CRAN (R 4.0.0)
##  dplyr       * 1.0.2   2020-08-18 [1] CRAN (R 4.0.2)
##  ellipsis      0.3.1   2020-05-15 [1] CRAN (R 4.0.0)
##  evaluate      0.14    2019-05-28 [1] CRAN (R 4.0.0)
##  fansi         0.4.1   2020-01-08 [1] CRAN (R 4.0.0)
##  fastDummies * 1.6.2   2020-09-16 [1] CRAN (R 4.0.2)
##  forcats     * 0.5.0   2020-03-01 [1] CRAN (R 4.0.0)
##  fs            1.5.0   2020-07-31 [1] CRAN (R 4.0.2)
##  generics      0.0.2   2018-11-29 [1] CRAN (R 4.0.0)
##  ggplot2     * 3.3.2   2020-06-19 [1] CRAN (R 4.0.2)
##  glue          1.4.2   2020-08-27 [1] CRAN (R 4.0.2)
##  gtable        0.3.0   2019-03-25 [1] CRAN (R 4.0.0)
##  haven         2.3.1   2020-06-01 [1] CRAN (R 4.0.2)
##  here        * 0.1     2017-05-28 [1] CRAN (R 4.0.0)
##  hms           0.5.3   2020-01-08 [1] CRAN (R 4.0.0)
##  htmltools     0.5.0   2020-06-16 [1] CRAN (R 4.0.0)
##  httr          1.4.2   2020-07-20 [1] CRAN (R 4.0.2)
##  jsonlite      1.7.0   2020-06-25 [1] CRAN (R 4.0.2)
##  knitr         1.29    2020-06-23 [1] CRAN (R 4.0.2)
##  lifecycle     0.2.0   2020-03-06 [1] CRAN (R 4.0.0)
##  lubridate     1.7.9   2020-06-08 [1] CRAN (R 4.0.2)
##  magrittr      1.5     2014-11-22 [1] CRAN (R 4.0.0)
##  memoise       1.1.0   2017-04-21 [1] CRAN (R 4.0.0)
##  modelr        0.1.8   2020-05-19 [1] CRAN (R 4.0.2)
##  munsell       0.5.0   2018-06-12 [1] CRAN (R 4.0.0)
##  pander        0.6.3   2018-11-06 [1] CRAN (R 4.0.0)
##  pillar        1.4.6   2020-07-10 [1] CRAN (R 4.0.2)
##  pkgbuild      1.1.0   2020-07-13 [1] CRAN (R 4.0.2)
##  pkgconfig     2.0.3   2019-09-22 [1] CRAN (R 4.0.0)
##  pkgload       1.1.0   2020-05-29 [1] CRAN (R 4.0.2)
##  prettyunits   1.1.1   2020-01-24 [1] CRAN (R 4.0.0)
##  processx      3.4.3   2020-07-05 [1] CRAN (R 4.0.0)
##  ps            1.3.4   2020-08-11 [1] CRAN (R 4.0.2)
##  purrr       * 0.3.4   2020-04-17 [1] CRAN (R 4.0.0)
##  R6            2.4.1   2019-11-12 [1] CRAN (R 4.0.0)
##  Rcpp          1.0.5   2020-07-06 [1] CRAN (R 4.0.2)
##  readr       * 1.3.1   2018-12-21 [1] CRAN (R 4.0.0)
##  readxl      * 1.3.1   2019-03-13 [1] CRAN (R 4.0.0)
##  rematch       1.0.1   2016-04-21 [1] CRAN (R 4.0.0)
##  remotes       2.2.0   2020-07-21 [1] CRAN (R 4.0.2)
##  reprex        0.3.0   2019-05-16 [1] CRAN (R 4.0.0)
##  rlang         0.4.7   2020-07-09 [1] CRAN (R 4.0.2)
##  rmarkdown     2.3     2020-06-18 [1] CRAN (R 4.0.2)
##  rprojroot     1.3-2   2018-01-03 [1] CRAN (R 4.0.0)
##  rstudioapi    0.11    2020-02-07 [1] CRAN (R 4.0.0)
##  rvest         0.3.6   2020-07-25 [1] CRAN (R 4.0.2)
##  scales      * 1.1.1   2020-05-11 [1] CRAN (R 4.0.0)
##  sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 4.0.0)
##  stringi       1.4.6   2020-02-17 [1] CRAN (R 4.0.0)
##  stringr     * 1.4.0   2019-02-10 [1] CRAN (R 4.0.0)
##  testthat      2.3.2   2020-03-02 [1] CRAN (R 4.0.0)
##  tibble      * 3.0.3   2020-07-10 [1] CRAN (R 4.0.2)
##  tidyr       * 1.1.2   2020-08-27 [1] CRAN (R 4.0.2)
##  tidyselect    1.1.0   2020-05-11 [1] CRAN (R 4.0.0)
##  tidyverse   * 1.3.0   2019-11-21 [1] CRAN (R 4.0.0)
##  usethis       1.6.1   2020-04-29 [1] CRAN (R 4.0.0)
##  vctrs         0.3.4   2020-08-29 [1] CRAN (R 4.0.2)
##  viridisLite   0.3.0   2018-02-01 [1] CRAN (R 4.0.0)
##  withr         2.2.0   2020-04-20 [1] CRAN (R 4.0.0)
##  xfun          0.16    2020-07-24 [1] CRAN (R 4.0.2)
##  xml2          1.3.2   2020-04-23 [1] CRAN (R 4.0.0)
##  yaml          2.2.1   2020-02-01 [1] CRAN (R 4.0.0)
## 
## [1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library
writeLines(readLines(file.path(Sys.getenv("HOME"), ".R/Makevars")))
## # http://dirk.eddelbuettel.com/blog/2017/11/27/#011_faster_package_installation_one
## VER=
## CCACHE=ccache
## CC=$(CCACHE) gcc$(VER)
## CXX=$(CCACHE) g++$(VER)
## CXX11=$(CCACHE) g++$(VER)
## CXX14=$(CCACHE) g++$(VER)
## FC=$(CCACHE) gfortran$(VER)
## F77=$(CCACHE) gfortran$(VER)
## 
## CXX14FLAGS=-O3 -march=native -mtune=native -fPIC
LS0tCnRpdGxlOiAiR2VuZXJhdGUgYW5kIGNsZWFuIHNpbXVsYXRlZCBkYXRhIgphdXRob3I6ICJTdXBhcm5hIENoYXVkaHJ5LCBNYXJjIERvdHNvbiwgYW5kIEFuZHJldyBIZWlzcyIKZGF0ZTogIkxhc3QgcnVuOiBgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVGJylgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIHBhbmRvY19hcmdzOgogICAgICAtICItLWRlZmF1bHQtaW1hZ2UtZXh0ZW5zaW9uPXBuZyIKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlCi0tLQoKYGBge3IgbG9hZC1wYWNrYWdlcywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZmFzdER1bW1pZXMpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShoZXJlKQoKIyBUdXJuIG9mZiBncm91cGluZyBtZXNzYWdlCm9wdGlvbnMoZHBseXIuc3VtbWFyaXNlLmluZm9ybSA9IEZBTFNFKQoKIyBQcm9qZWN0LXNwZWNpZmljIGZ1bmN0aW9ucwpzb3VyY2UoaGVyZSgiUiIsICJncmFwaGljcy5SIikpCgojIEdlbmVyYWwgc2V0dGluZ3MKc291cmNlKGhlcmUoImFuYWx5c2lzIiwgIm9wdGlvbnMuUiIpKQoKIyBNYWtlIGFsbCB0aGUgcmFuZG9tbmVzcyByZXByb2R1Y2libGUKc2V0LnNlZWQoMTIzNCkKYGBgCgpgYGB7ciBzaW1wbGVyLWV4Y2VsLWJhc2VkLW1vZGVsLCBtZXNzYWdlPUZBTFNFfQpzaW1fcmF3IDwtIHJlYWRfZXhjZWwoaGVyZSgiZGF0YSIsICJyYXdfZGF0YSIsICJNYXJrZXQgU2ltdWxhdG9yIFZlcnNpb24gMDEueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAiUmVzdWx0cyIsIHJhbmdlID0gIk8zOkFVMjciKQoKb3Jnc19yYXcgPC0gcmVhZF9leGNlbChoZXJlKCJkYXRhIiwgInJhd19kYXRhIiwgIk1hcmtldCBTaW11bGF0b3IgVmVyc2lvbiAwMS54bHN4IiksCiAgICAgICAgICAgICAgICAgICAgICAgc2hlZXQgPSAiUmVzdWx0cyIsIHJhbmdlID0gIk40Ok8yNyIsIAogICAgICAgICAgICAgICAgICAgICAgIGNvbF9uYW1lcyA9IGMoIm9yZ2FuaXphdGlvbiIsICJvcmdfZGV0YWlscyIpKQoKb3Jnc19jbGVhbiA8LSBvcmdzX3JhdyAlPiUgCiAgc2VwYXJhdGUob3JnX2RldGFpbHMsIGludG8gPSBjKCJvcmdfaXNzdWUiLCAib3JnX2Z1bmRpbmciLCAib3JnX3JlbGF0aW9uc2hpcCIpLCBzZXAgPSAiLCAiKQoKcGVyc29uYXNfcmF3IDwtIHJlYWRfZXhjZWwoaGVyZSgiZGF0YSIsICJyYXdfZGF0YSIsICJNYXJrZXQgU2ltdWxhdG9yIFZlcnNpb24gMDEueGxzeCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICJSZXN1bHRzIiwgcmFuZ2UgPSAiUDI6QVUzIikgJT4lIAogIHBpdm90X2xvbmdlcihldmVyeXRoaW5nKCksIG5hbWVzX3RvID0gInBlcnNvbmEiLCB2YWx1ZXNfdG8gPSAicGVyc29uYV9kZXRhaWxzIikKCnBlcnNvbmFzX2NsZWFuIDwtIHBlcnNvbmFzX3JhdyAlPiUgCiAgc2VwYXJhdGUocGVyc29uYV9kZXRhaWxzLCBpbnRvID0gYygiZGVtb2dyYXBoaWNzIiwgImFjdGlvbnMiLCAicGVyc29uYV90cnVzdCIpLCBzZXAgPSAiLCAiKSAlPiUgCiAgc2VwYXJhdGUoZGVtb2dyYXBoaWNzLCBpbnRvID0gYygicGVyc29uYV9pbmNvbWUiLCAicGVyc29uYV9nZW5kZXIiKSwgc2VwID0gIiBJbmNvbWUgIikgJT4lIAogIHNlcGFyYXRlKGFjdGlvbnMsIGludG8gPSBjKCJwZXJzb25hX2lkZW9sb2d5IiwgInBlcnNvbmFfZXhwZXJpZW5jZSIpLCBzZXAgPSAiIHRoYXQgIikgCgpzaW1fbG9uZyA8LSBzaW1fcmF3ICU+JSAKICByZW5hbWUob3JnX2RldGFpbHMgPSBgLi4uMWApICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IC1vcmdfZGV0YWlscywgbmFtZXNfdG8gPSAicGVyc29uYV9kZXRhaWxzIiwgdmFsdWVzX3RvID0gInNoYXJlIikKCnNpbV9leGNlbF9jbGVhbiA8LSBzaW1fbG9uZyAlPiUgCiAgbGVmdF9qb2luKG9yZ3NfcmF3LCBieSA9ICJvcmdfZGV0YWlscyIpICU+JSAKICBsZWZ0X2pvaW4ocGVyc29uYXNfcmF3LCBieSA9ICJwZXJzb25hX2RldGFpbHMiKSAlPiUgCiAgc2VwYXJhdGUob3JnX2RldGFpbHMsIGludG8gPSBjKCJvcmdfaXNzdWUiLCAib3JnX2Z1bmRpbmciLCAib3JnX3JlbGF0aW9uc2hpcCIpLCBzZXAgPSAiLCAiKSAlPiUgCiAgc2VwYXJhdGUocGVyc29uYV9kZXRhaWxzLCBpbnRvID0gYygiZGVtb2dyYXBoaWNzIiwgImFjdGlvbnMiLCAicGVyc29uYV90cnVzdCIpLCBzZXAgPSAiLCAiKSAlPiUgCiAgc2VwYXJhdGUoZGVtb2dyYXBoaWNzLCBpbnRvID0gYygicGVyc29uYV9pbmNvbWUiLCAicGVyc29uYV9nZW5kZXIiKSwgc2VwID0gIiBJbmNvbWUgIikgJT4lIAogIHNlcGFyYXRlKGFjdGlvbnMsIGludG8gPSBjKCJwZXJzb25hX2lkZW9sb2d5IiwgInBlcnNvbmFfZXhwZXJpZW5jZSIpLCBzZXAgPSAiIHRoYXQgIikgJT4lIAogIG11dGF0ZShvcmdfaXNzdWUgPSByZWNvZGUob3JnX2lzc3VlLCAiUmVmdWdlc3MgUmVsaWVmIiA9ICJSZWZ1Z2VlIFJlbGllZiIpLAogICAgICAgICBvcmdfZnVuZGluZyA9IHJlY29kZShvcmdfZnVuZGluZywgIkdyYW50cyIgPSAiTW9zdGx5IGZ1bmRlZCBieSBnb3Zlcm5tZW50IGdyYW50cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTbWFsbCBEb25vcnMiID0gIk1vc3RseSBmdW5kZWQgYnkgc21hbGwgZG9ub3JzIiksCiAgICAgICAgIHBlcnNvbmFfaW5jb21lID0gcGFzdGUocGVyc29uYV9pbmNvbWUsICJpbmNvbWUiKSwKICAgICAgICAgcGVyc29uYV9pbmNvbWUgPSBmYWN0b3IocGVyc29uYV9pbmNvbWUsIGxldmVscyA9IGMoIkxvd2VyIGluY29tZSIsICJIaWdoZXIgaW5jb21lIiksIG9yZGVyZWQgPSBUUlVFKSwKICAgICAgICAgcGVyc29uYV90cnVzdCA9IHJlY29kZShwZXJzb25hX3RydXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEb2Vzbid0IFRydXN0IG9yIERvbmF0ZSIgPSAiTGVzcyB0cnVzdGluZzsgZG9uYXRlcyBhbmQgdm9sdW50ZWVycyBsZXNzIG9mdGVuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVHJ1c3RzIGFuZCBEb25hdGVzIiA9ICJNb3JlIHRydXN0aW5nOyBkb25hdGVzIGFuZCB2b2x1bnRlZXJzIG9mdGVuIiksCiAgICAgICAgIHBlcnNvbmFfZXhwZXJpZW5jZSA9IHJlY29kZShwZXJzb25hX2V4cGVyaWVuY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRG9lc24ndCBSZWFkIG9yIFRyYXZlbCIgPSAiRG9lc24ndCBmb2xsb3cgbmV3czsgaGFzIG5vdCB0cmF2ZWxsZWQgYWJyb2FkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWFkcyBhbmQgVHJhdmVscyIgPSAiRm9sbG93cyB0aGUgbmV3czsgaGFzIHRyYXZlbGxlZCBhYnJvYWQiKSkgJT4lIAogIG11dGF0ZV9hdCh2YXJzKG9yZ2FuaXphdGlvbiwgcGVyc29uYSksIH5mY3RfaW5vcmRlciguKSkKYGBgCgpgYGB7ciBsb2FkLWRhdGEsIG1lc3NhZ2U9RkFMU0V9CiMgR2FtbWFzIG9mIHRoZSAiZXZlcnl0aGluZyIgbW9kZWwKZ2FtbWFzIDwtIHJlYWRfcmRzKAogIGhlcmUoJ2RhdGEnLCAncmF3X2RhdGEnLCAncG9zdGVyaW9yX2RyYXdzJywgJ3B1YmxpY19wb2xpdGljYWxfc29jaWFsX2NoYXJpdHlfZGVtby5yZHMnKQogICkgJT4lIAogIGdyb3VwX2J5KGksIGopICU+JSAKICBzdW1tYXJpemUoZ2FtbWFfbWVhbiA9IG1lYW4oR2FtbWEpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gaiwgdmFsdWVzX2Zyb20gPSBnYW1tYV9tZWFuKSAlPiUgCiAgc2VsZWN0KC1pKSAlPiUgCiAgdCgpCmBgYAoKYGBge3IgcG9zc2libGUtb3JnYW5pemF0aW9uc30Kb3JnYW5pemF0aW9uX2NvbHVtbnMgPC0gYygib3JnYW5pemF0aW9uIiwgImlzc3VlLmFyZWEiLCAidHJhbnNwYXJlbmN5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgImFjY291bnRhYmlsaXR5IiwgImZ1bmRpbmciLCAicmVsYXRpb25zaGlwIikKCm9yZ2FuaXphdGlvbl9wb3NzaWJpbGl0aWVzIDwtIGV4cGFuZF9ncmlkKAogIGlzc3VlLmFyZWEgPSBjKCJFbWVyZ2VuY3kgcmVzcG9uc2UiLCAiRW52aXJvbm1lbnQiLCAiSHVtYW4gcmlnaHRzIiwgIlJlZnVnZWUgcmVsaWVmIiksCiAgcmVsYXRpb25zaGlwID0gYygiRnJpZW5kbHkiLCAiQ3JpdGljaXplZCIsICJVbmRlciBjcmFja2Rvd24iKSwKICBmdW5kaW5nID0gYygiU21hbGwgcHJpdmF0ZSBkb25hdGlvbnMiLCAiR292ZXJubWVudCBncmFudHMiKQopICU+JSAKICBtdXRhdGUob3JnX2lkID0gcGFzdGUwKCJvcmciLCAxOm4oKSkpCgpvcmdhbml6YXRpb25zIDwtIG9yZ2FuaXphdGlvbl9wb3NzaWJpbGl0aWVzICU+JSAKICBtdXRhdGUoCiAgICBvcmdhbml6YXRpb24gPSAiUmVkIENyb3NzIiwKICAgIHRyYW5zcGFyZW5jeSA9ICJZZXMiLAogICAgYWNjb3VudGFiaWxpdHkgPSAiWWVzIgogICkgJT4lIAogIHNlbGVjdChvcmdfaWQsIGFsbF9vZihvcmdhbml6YXRpb25fY29sdW1ucykpICU+JSAKICBtdXRhdGUob3JnYW5pemF0aW9uID0gZmFjdG9yKG9yZ2FuaXphdGlvbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJBbW5lc3R5IEludGVybmF0aW9uYWwiLCAiR3JlZW5wZWFjZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT3hmYW0iLCAiUmVkIENyb3NzIikpLAogICAgICAgICBpc3N1ZS5hcmVhID0gZmFjdG9yKGlzc3VlLmFyZWEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiRW1lcmdlbmN5IHJlc3BvbnNlIiwgIkVudmlyb25tZW50IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIdW1hbiByaWdodHMiLCAiUmVmdWdlZSByZWxpZWYiKSksCiAgICAgICAgIHRyYW5zcGFyZW5jeSA9IGZhY3Rvcih0cmFuc3BhcmVuY3ksIGxldmVscyA9IGMoIk5vIiwgIlllcyIpKSwKICAgICAgICAgYWNjb3VudGFiaWxpdHkgPSBmYWN0b3IoYWNjb3VudGFiaWxpdHksIGxldmVscyA9IGMoIk5vIiwgIlllcyIpKSwKICAgICAgICAgZnVuZGluZyA9IGZhY3RvcihmdW5kaW5nLCBsZXZlbHMgPSBjKCJTbWFsbCBwcml2YXRlIGRvbmF0aW9ucyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkhhbmRmdWwgb2Ygd2VhbHRoeSBwcml2YXRlIGRvbm9ycyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdvdmVybm1lbnQgZ3JhbnRzIikpLAogICAgICAgICByZWxhdGlvbnNoaXAgPSBmYWN0b3IocmVsYXRpb25zaGlwLCBsZXZlbHMgPSBjKCJGcmllbmRseSIsICJDcml0aWNpemVkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVuZGVyIGNyYWNrZG93biIpKSkKCm9yZ190YWJsZSA8LSBvcmdhbml6YXRpb25zICU+JSAKICBkdW1teV9jb2x1bW5zKHNlbGVjdF9jb2x1bW5zID0gb3JnYW5pemF0aW9uX2NvbHVtbnMsCiAgICAgICAgICAgICAgICByZW1vdmVfc2VsZWN0ZWRfY29sdW1ucyA9IFRSVUUpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IC1vcmdfaWQsIG5hbWVzX3RvID0gIm5hbWUiLCApICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gb3JnX2lkLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKSAlPiUgCiAgc2VwYXJhdGUobmFtZSwgaW50byA9IGMoImF0dHJpYnV0ZSIsICJvcHRpb24iKSwgc2VwID0gIl8iKSAlPiUgCiAgZmlsdGVyKCEob3B0aW9uICVpbiUgYygiRW1lcmdlbmN5IHJlc3BvbnNlIiwgIk5vIiwgIlNtYWxsIHByaXZhdGUgZG9uYXRpb25zIiwgIkZyaWVuZGx5IikpKQpgYGAKCmBgYHtyIHBvc3NpYmxlLXBlcnNvbmFzfQpwZXJzb25hX2NvbHVtbnMgPC0gYygibmF0aW9uYWwubmV3cyIsICJpbnRlcm5hdGlvbmFsLm5ld3MiLCAibWVkaXVtLmZvbGxvdy50diIsIAogICAgICAgICAgICAgICAgICAgICAibWVkaXVtLmZvbGxvdy5wcmludCIsICJtZWRpdW0uZm9sbG93Lm9ubGluZSIsICJtZWRpdW0uZm9sbG93LnNvY2lhbCIsIAogICAgICAgICAgICAgICAgICAgICAibWVkaXVtLmZvbGxvdy5yYWRpbyIsICJtZWRpdW0uZm9sbG93LmVtYWlsIiwgIm1lZGl1bS5mb2xsb3cuYXBwIiwgCiAgICAgICAgICAgICAgICAgICAgICJmb2xsb3cuZ292dCIsICJ0cmF2ZWwiLCAiaWRlb2xvZ3kiLCAidHJ1c3QuaW5zdGl0dXRpb25zIiwgCiAgICAgICAgICAgICAgICAgICAgICJzaG91bGQuYmUuY2hhcml0YWJsZSIsICJyZWxpZ2lvdXMuYXR0ZW5kYW5jZSIsICJyZWxpZ2lvbi5pbXBvcnRhbmNlIiwgCiAgICAgICAgICAgICAgICAgICAgICJyZWxpZ2lvbiIsICJ0cnVzdC5jaGFyaXR5LmltcG9ydGFuY2UiLCAidHJ1c3QuY2hhcml0aWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICJkb25hdGlvbi5mcmVxdWVuY3kiLCAiZG9uYXRlZC5sYXN0LnllYXIiLCAidm9sdW50ZWVyZWQiLCAKICAgICAgICAgICAgICAgICAgICAgInZvbHVudGVlci5mcmVxdWVuY3kiLCAiaGlzdG9yeS5hY3RpdmlzbS5wZXJzb25hbCIsICJoaXN0b3J5LmFjdGl2aXNtLmZhbWlseSIsCiAgICAgICAgICAgICAgICAgICAgICJtZW1iZXJzaGlwLmNodXJjaCIsICJtZW1iZXJzaGlwLnNwb3J0IiwgIm1lbWJlcnNoaXAuYXJ0IiwgIm1lbWJlcnNoaXAudW5pb24iLCAKICAgICAgICAgICAgICAgICAgICAgIm1lbWJlcnNoaXAucGFydHkiLCAibWVtYmVyc2hpcC5lbnZpcm9ubWVudCIsICJtZW1iZXJzaGlwLnByb2Zlc3Npb25hbCIsIAogICAgICAgICAgICAgICAgICAgICAibWVtYmVyc2hpcC5jaGFyaXRhYmxlIiwgIm1lbWJlcnNoaXAuY29uc3VtZXIiLCAibWVtYmVyc2hpcC5vdGhlciIsIAogICAgICAgICAgICAgICAgICAgICAiZ2VuZGVyIiwgIm1hcml0YWwiLCAiZWR1Y2F0aW9uIiwgImluY29tZSIsICJyYWNlIiwgImFnZSIpCgpwZXJzb25hX2RlbW9ncmFwaGljcyA8LSBleHBhbmRfZ3JpZCgKICBpbmNvbWUgPSBjKCJMZXNzIHRoYW4gbWVkaWFuIiwgIk1vcmUgdGhhbiBtZWRpYW4iKSwKICBlZHVjYXRpb24gPSBjKCJIaWdoIHNjaG9vbCBncmFkdWF0ZSIsICI0IHllYXIgZGVncmVlIiksCiAgcmVsaWdpb3VzLmF0dGVuZGFuY2UgPSBjKCJSYXJlbHkiLCAiQXQgbGVhc3Qgb25jZSBhIG1vbnRoIikKKSAlPiUgCiAgbXV0YXRlKGRlbW9ncmFwaGljc19pZCA9IDE6bigpKQoKcGVyc29uYV9wb2xpdGljcyA8LSB0cmliYmxlKAogIH5pZGVvbG9neSwgfm5hdGlvbmFsLm5ld3MsIH5pbnRlcm5hdGlvbmFsLm5ld3MsIH50cmF2ZWwsCiAgIkV4dHJlbWVseSBsaWJlcmFsIiwgIkF0IGxlYXN0IG9uY2UgYSBkYXkiLCAgIkFsd2F5cyIsICJZZXMiLAogICJFeHRyZW1lbHkgY29uc2VydmF0aXZlIiwgIkF0IGxlYXN0IG9uY2UgYSBkYXkiLCAiQWx3YXlzIiwgIlllcyIsCiAgIkV4dHJlbWVseSBsaWJlcmFsIiwgIlJhcmVseSIsICJOZXZlciIsICJObyIsCiAgIkV4dHJlbWVseSBjb25zZXJ2YXRpdmUiLCAiUmFyZWx5IiwgIk5ldmVyIiwgIk5vIgopICU+JSAKICBtdXRhdGUocG9saXRpY3NfaWQgPSAxOm4oKSkKCnBlcnNvbmFfc29jaWFsIDwtIHRpYmJsZSgKICBzb2NpYWxfaWQgPSAxOjIsCiAgdHJ1c3QuaW5zdGl0dXRpb25zID0gYygiQ29tcGxldGUgdHJ1c3QiLCAiTm8gdHJ1c3QiKSwKICBzaG91bGQuYmUuY2hhcml0YWJsZSA9IGMoIlN0cm9uZ2x5IGFncmVlIiwgIlN0cm9uZ2x5IGRpc2FncmVlIiksCiAgdHJ1c3QuY2hhcml0aWVzID0gYygiQ29tcGxldGUgdHJ1c3QiLCAiTm8gdHJ1c3QiKSwKICB2b2x1bnRlZXIuZnJlcXVlbmN5ID0gYygiQXQgbGVhc3Qgb25jZSBhIG1vbnRoIiwgIlJhcmVseSIpLAogIGRvbmF0aW9uLmZyZXF1ZW5jeSA9IGMoIkF0IGxlYXN0IG9uY2UgYSBtb250aCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIk1vcmUgdGhhbiBvbmNlIGEgbW9udGgsIGxlc3MgdGhhbiBvbmNlIGEgeWVhciIpLAogIGhpc3RvcnkuYWN0aXZpc20ucGVyc29uYWwgPSBjKCJJbnZvbHZlZCIsICJOb3QgaW52b2x2ZWQiKSwKICBtZW1iZXJzaGlwLnBhcnR5ID0gYygiQWN0aXZlIG1lbWJlciIsICJEb24ndCBiZWxvbmciKSwKICBtZW1iZXJzaGlwLmNoYXJpdGFibGUgPSBjKCJBY3RpdmUgbWVtYmVyIiwgIkRvbid0IGJlbG9uZyIpCikKCnBlcnNvbmFfcG9zc2liaWxpdGllcyA8LSBleHBhbmRfZ3JpZCgKICBkZW1vZ3JhcGhpY3NfaWQgPSBwZXJzb25hX2RlbW9ncmFwaGljcyRkZW1vZ3JhcGhpY3NfaWQsCiAgcG9saXRpY3NfaWQgPSBwZXJzb25hX3BvbGl0aWNzJHBvbGl0aWNzX2lkLAogIHNvY2lhbF9pZCA9IHBlcnNvbmFfc29jaWFsJHNvY2lhbF9pZAopICU+JSAKICBsZWZ0X2pvaW4ocGVyc29uYV9kZW1vZ3JhcGhpY3MsIGJ5ID0gImRlbW9ncmFwaGljc19pZCIpICU+JSAKICBsZWZ0X2pvaW4ocGVyc29uYV9wb2xpdGljcywgYnkgPSAicG9saXRpY3NfaWQiKSAlPiUgCiAgbGVmdF9qb2luKHBlcnNvbmFfc29jaWFsLCBieSA9ICJzb2NpYWxfaWQiKSAlPiUgCiAgc2VsZWN0KC1lbmRzX3dpdGgoIl9pZCIpKSAlPiUgCiAgbXV0YXRlKHBlcnNvbmFfaWQgPSBwYXN0ZTAoInBlcnNvbmEiLCAxOm4oKSkpCgojIENvbHVtbnMgdGhhdCBzaG91bGQgYmUgaGVsZCBjb25zdGFudAojIHBlcnNvbmFfY29sdW1ucyAlPiUgLlshKC4gJWluJSBjb2xuYW1lcyhwZXJzb25hX3Bvc3NpYmlsaXRpZXMpKV0gJT4lIGNhdChzZXAgPSAiXG4iKQoKcGVyc29uYXMgPC0gcGVyc29uYV9wb3NzaWJpbGl0aWVzICU+JSAKICBtdXRhdGUoCiAgICBtZWRpdW0uZm9sbG93LnR2ID0gIkZvbGxvdyIsCiAgICBtZWRpdW0uZm9sbG93LnByaW50ID0gIkZvbGxvdyIsCiAgICBtZWRpdW0uZm9sbG93Lm9ubGluZSA9ICJEb24ndCBmb2xsb3ciLAogICAgbWVkaXVtLmZvbGxvdy5zb2NpYWwgPSAiRm9sbG93IiwKICAgIG1lZGl1bS5mb2xsb3cucmFkaW8gPSAiRG9uJ3QgZm9sbG93IiwKICAgIG1lZGl1bS5mb2xsb3cuZW1haWwgPSAiRG9uJ3QgZm9sbG93IiwKICAgIG1lZGl1bS5mb2xsb3cuYXBwID0gIkRvbid0IGZvbGxvdyIsCiAgICBmb2xsb3cuZ292dCA9ICJPZnRlbiIsCiAgICByZWxpZ2lvbi5pbXBvcnRhbmNlID0gIkltcG9ydGFudCIsCiAgICByZWxpZ2lvbiA9ICJQcm90ZXN0YW50IiwKICAgIHRydXN0LmNoYXJpdHkuaW1wb3J0YW5jZSA9ICJTb21ld2hhdCBpbXBvcnRhbnQiLAogICAgZG9uYXRlZC5sYXN0LnllYXIgPSAiJDEwMC0kNDk5IiwKICAgIHZvbHVudGVlcmVkID0gIk5vIiwKICAgIGhpc3RvcnkuYWN0aXZpc20uZmFtaWx5ID0gIk5vdCBpbnZvbHZlZCIsCiAgICBtZW1iZXJzaGlwLmNodXJjaCA9ICJEb24ndCBiZWxvbmciLAogICAgbWVtYmVyc2hpcC5zcG9ydCA9ICJEb24ndCBiZWxvbmciLAogICAgbWVtYmVyc2hpcC5hcnQgPSAiRG9uJ3QgYmVsb25nIiwKICAgIG1lbWJlcnNoaXAudW5pb24gPSAiRG9uJ3QgYmVsb25nIiwKICAgIG1lbWJlcnNoaXAuZW52aXJvbm1lbnQgPSAiRG9uJ3QgYmVsb25nIiwKICAgIG1lbWJlcnNoaXAucHJvZmVzc2lvbmFsID0gIkRvbid0IGJlbG9uZyIsCiAgICBtZW1iZXJzaGlwLmNvbnN1bWVyID0gIkRvbid0IGJlbG9uZyIsCiAgICBtZW1iZXJzaGlwLm90aGVyID0gIkRvbid0IGJlbG9uZyIsCiAgICBnZW5kZXIgPSAiTWFsZSIsCiAgICBtYXJpdGFsID0gIk1hcnJpZWQiLAogICAgcmFjZSA9ICJXaGl0ZSIsCiAgICBhZ2UgPSAiTGVzcyB0aGFuIG1lZGlhbiIKICApICU+JSAKICBzZWxlY3QocGVyc29uYV9pZCwgYWxsX29mKHBlcnNvbmFfY29sdW1ucykpICU+JSAKICBtdXRhdGUoCiAgICBuYXRpb25hbC5uZXdzID0gZmFjdG9yKG5hdGlvbmFsLm5ld3MsIGxldmVscyA9IGMoIlJhcmVseSIsICJPbmNlIGEgd2VlayIsICJBdCBsZWFzdCBvbmNlIGEgZGF5IikpLAogICAgaW50ZXJuYXRpb25hbC5uZXdzID0gZmFjdG9yKGludGVybmF0aW9uYWwubmV3cywgbGV2ZWxzID0gYygiTmV2ZXIiLCAiU29tZXRpbWVzIiwgIkFsd2F5cyIpKSwKICAgIG1lZGl1bS5mb2xsb3cudHYgPSBmYWN0b3IobWVkaXVtLmZvbGxvdy50diwgbGV2ZWxzID0gYygiRG9uJ3QgZm9sbG93IiwgIkZvbGxvdyIpKSwKICAgIG1lZGl1bS5mb2xsb3cucHJpbnQgPSBmYWN0b3IobWVkaXVtLmZvbGxvdy5wcmludCwgbGV2ZWxzID0gYygiRG9uJ3QgZm9sbG93IiwgIkZvbGxvdyIpKSwKICAgIG1lZGl1bS5mb2xsb3cub25saW5lID0gZmFjdG9yKG1lZGl1bS5mb2xsb3cub25saW5lLCBsZXZlbHMgPSBjKCJEb24ndCBmb2xsb3ciLCAiRm9sbG93IikpLAogICAgbWVkaXVtLmZvbGxvdy5zb2NpYWwgPSBmYWN0b3IobWVkaXVtLmZvbGxvdy5zb2NpYWwsIGxldmVscyA9IGMoIkRvbid0IGZvbGxvdyIsICJGb2xsb3ciKSksCiAgICBtZWRpdW0uZm9sbG93LnJhZGlvID0gZmFjdG9yKG1lZGl1bS5mb2xsb3cucmFkaW8sIGxldmVscyA9IGMoIkRvbid0IGZvbGxvdyIsICJGb2xsb3ciKSksCiAgICBtZWRpdW0uZm9sbG93LmVtYWlsID0gZmFjdG9yKG1lZGl1bS5mb2xsb3cuZW1haWwsIGxldmVscyA9IGMoIkRvbid0IGZvbGxvdyIsICJGb2xsb3ciKSksCiAgICBtZWRpdW0uZm9sbG93LmFwcCA9IGZhY3RvcihtZWRpdW0uZm9sbG93LmFwcCwgbGV2ZWxzID0gYygiRG9uJ3QgZm9sbG93IiwgIkZvbGxvdyIpKSwKICAgIGZvbGxvdy5nb3Z0ID0gZmFjdG9yKGZvbGxvdy5nb3Z0LCBsZXZlbHMgPSBjKCJOb3Qgb2Z0ZW4iLCAiT2Z0ZW4iKSksCiAgICB0cmF2ZWwgPSBmYWN0b3IodHJhdmVsLCBsZXZlbHMgPSBjKCJObyIsICJZZXMiKSksCiAgICBpZGVvbG9neSA9IGZhY3RvcihpZGVvbG9neSwgCiAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJFeHRyZW1lbHkgbGliZXJhbCIsICJTb21ld2hhdCBsaWJlcmFsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTbGlnaHRseSBsaWJlcmFsIiwgIk1vZGVyYXRlIiwgIlNsaWdodGx5IGNvbnNlcnZhdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU29tZXdoYXQgY29uc2VydmF0aXZlIiwgIkV4dHJlbWVseSBjb25zZXJ2YXRpdmUiKSksCiAgICB0cnVzdC5pbnN0aXR1dGlvbnMgPSBmYWN0b3IodHJ1c3QuaW5zdGl0dXRpb25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIk5vIHRydXN0IiwgIlZlcnkgbGl0dGxlIHRydXN0IiwgIkxpdHRsZSB0cnVzdCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXRyYWwiLCAiU29tZSB0cnVzdCIsICJBIGxvdCBvZiB0cnVzdCIsICJDb21wbGV0ZSB0cnVzdCIpKSwKICAgIHNob3VsZC5iZS5jaGFyaXRhYmxlID0gZmFjdG9yKHNob3VsZC5iZS5jaGFyaXRhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiU3Ryb25nbHkgZGlzYWdyZWUiLCAiRGlzYWdyZWUiLCAiU29tZXdoYXQgZGlzYWdyZWUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXRyYWwiLCAiU29tZXdoYXQgYWdyZWUiLCAiQWdyZWUiLCAiU3Ryb25nbHkgYWdyZWUiKSksCiAgICByZWxpZ2lvdXMuYXR0ZW5kYW5jZSA9IGZhY3RvcihyZWxpZ2lvdXMuYXR0ZW5kYW5jZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIk5vdCBzdXJlIiwgIlJhcmVseSIsICJBdCBsZWFzdCBvbmNlIGEgbW9udGgiKSksCiAgICByZWxpZ2lvbi5pbXBvcnRhbmNlID0gZmFjdG9yKHJlbGlnaW9uLmltcG9ydGFuY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIk5vdCBpbXBvcnRhbnQiLCAiSW1wb3J0YW50IikpLAogICAgcmVsaWdpb24gPSBmYWN0b3IocmVsaWdpb24sIAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiQ2F0aG9saWMiLCAiUHJvdGVzdGFudCIsICJDaHJpc3RpYW4gT3J0aG9kb3giLCAiSmV3aXNoIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNdXNsaW0iLCAiU2lraCIsICJIaW5kdSIsICJCdWRkaGlzdCIsICJBdGhlaXN0IiwgIk90aGVyIikpLAogICAgdHJ1c3QuY2hhcml0eS5pbXBvcnRhbmNlID0gZmFjdG9yKHRydXN0LmNoYXJpdHkuaW1wb3J0YW5jZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJOb3QgaW1wb3J0YW50IiwgIlZlcnkgdW5pbXBvcnRhbnQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTb21ld2hhdCB1bmltcG9ydGFudCIsICJOZXV0cmFsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU29tZXdoYXQgaW1wb3J0YW50IiwgIlZlcnkgaW1wb3J0YW50IiwgIkVzc2VudGlhbCIpKSwKICAgIHRydXN0LmNoYXJpdGllcyA9IGZhY3Rvcih0cnVzdC5jaGFyaXRpZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiTm8gdHJ1c3QiLCAiVmVyeSBsaXR0bGUgdHJ1c3QiLCAiTGl0dGxlIHRydXN0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmV1dHJhbCIsICJTb21lIHRydXN0IiwgIkEgbG90IG9mIHRydXN0IiwgIkNvbXBsZXRlIHRydXN0IikpLAogICAgZG9uYXRpb24uZnJlcXVlbmN5ID0gZmFjdG9yKGRvbmF0aW9uLmZyZXF1ZW5jeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJNb3JlIHRoYW4gb25jZSBhIG1vbnRoLCBsZXNzIHRoYW4gb25jZSBhIHllYXIiLCAiQXQgbGVhc3Qgb25jZSBhIG1vbnRoIikpLAogICAgZG9uYXRlZC5sYXN0LnllYXIgPSBmYWN0b3IoZG9uYXRlZC5sYXN0LnllYXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCIkMS0kNDkiLCAiJDUwLSQ5OSIsICIkMTAwLSQ0OTkiLCAiJDUwMC0kOTk5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIkMTAwMC0kNCw5OTkiLCAiJDUwMDAtJDksOTk5IiwgIiQxMCwwMDArIikpLAogICAgdm9sdW50ZWVyZWQgPSBmYWN0b3Iodm9sdW50ZWVyZWQsIGxldmVscyA9IGMoIk5vIiwgIlllcyIpKSwKICAgIHZvbHVudGVlci5mcmVxdWVuY3kgPSBmYWN0b3Iodm9sdW50ZWVyLmZyZXF1ZW5jeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiSGF2ZW4ndCB2b2x1bnRlZXJlZCBpbiBwYXN0IDEyIG1vbnRocyIsICJSYXJlbHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTW9yZSB0aGFuIG9uY2UgYSBtb250aCwgbGVzcyB0aGFuIG9uY2UgYSB5ZWFyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkF0IGxlYXN0IG9uY2UgYSBtb250aCIpKSwKICAgIGhpc3RvcnkuYWN0aXZpc20ucGVyc29uYWwgPSBmYWN0b3IoaGlzdG9yeS5hY3RpdmlzbS5wZXJzb25hbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiTm90IGludm9sdmVkIiwgIkludm9sdmVkIikpLAogICAgaGlzdG9yeS5hY3RpdmlzbS5mYW1pbHkgPSBmYWN0b3IoaGlzdG9yeS5hY3RpdmlzbS5mYW1pbHksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJOb3QgaW52b2x2ZWQiLCAiSW52b2x2ZWQiKSksCiAgICBtZW1iZXJzaGlwLmNodXJjaCA9IGZhY3RvcihtZW1iZXJzaGlwLmNodXJjaCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyAgPSBjKCJEb24ndCBiZWxvbmciLCAiSW5hY3RpdmUgbWVtYmVyIiwgIkFjdGl2ZSBtZW1iZXIiKSksCiAgICBtZW1iZXJzaGlwLnNwb3J0ID0gZmFjdG9yKG1lbWJlcnNoaXAuc3BvcnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkRvbid0IGJlbG9uZyIsICJJbmFjdGl2ZSBtZW1iZXIiLCAiQWN0aXZlIG1lbWJlciIpKSwKICAgIG1lbWJlcnNoaXAuYXJ0ID0gZmFjdG9yKG1lbWJlcnNoaXAuYXJ0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiRG9uJ3QgYmVsb25nIiwgIkluYWN0aXZlIG1lbWJlciIsICJBY3RpdmUgbWVtYmVyIikpLAogICAgbWVtYmVyc2hpcC51bmlvbiA9IGZhY3RvcihtZW1iZXJzaGlwLnVuaW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJEb24ndCBiZWxvbmciLCAiSW5hY3RpdmUgbWVtYmVyIiwgIkFjdGl2ZSBtZW1iZXIiKSksCiAgICBtZW1iZXJzaGlwLnBhcnR5ID0gZmFjdG9yKG1lbWJlcnNoaXAucGFydHksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkRvbid0IGJlbG9uZyIsICJJbmFjdGl2ZSBtZW1iZXIiLCAiQWN0aXZlIG1lbWJlciIpKSwKICAgIG1lbWJlcnNoaXAuZW52aXJvbm1lbnQgPSBmYWN0b3IobWVtYmVyc2hpcC5lbnZpcm9ubWVudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiRG9uJ3QgYmVsb25nIiwgIkluYWN0aXZlIG1lbWJlciIsICJBY3RpdmUgbWVtYmVyIikpLAogICAgbWVtYmVyc2hpcC5wcm9mZXNzaW9uYWwgPSBmYWN0b3IobWVtYmVyc2hpcC5wcm9mZXNzaW9uYWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgID0gYygiRG9uJ3QgYmVsb25nIiwgIkluYWN0aXZlIG1lbWJlciIsICJBY3RpdmUgbWVtYmVyIikpLAogICAgbWVtYmVyc2hpcC5jaGFyaXRhYmxlID0gZmFjdG9yKG1lbWJlcnNoaXAuY2hhcml0YWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgID0gYygiRG9uJ3QgYmVsb25nIiwgIkluYWN0aXZlIG1lbWJlciIsICJBY3RpdmUgbWVtYmVyIikpLAogICAgbWVtYmVyc2hpcC5jb25zdW1lciA9IGZhY3RvcihtZW1iZXJzaGlwLmNvbnN1bWVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgID0gYygiRG9uJ3QgYmVsb25nIiwgIkluYWN0aXZlIG1lbWJlciIsICJBY3RpdmUgbWVtYmVyIikpLAogICAgbWVtYmVyc2hpcC5vdGhlciA9IGZhY3RvcihtZW1iZXJzaGlwLm90aGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJEb24ndCBiZWxvbmciLCAiSW5hY3RpdmUgbWVtYmVyIiwgIkFjdGl2ZSBtZW1iZXIiKSksCiAgICBnZW5kZXIgPSBmYWN0b3IoZ2VuZGVyLAogICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIk1hbGUiLCAiRmVtYWxlIiwgIlRyYW5zZ2VuZGVyIiwgIlByZWZlciBub3QgdG8gc2F5IiwgIk90aGVyIikpLAogICAgbWFyaXRhbCA9IGZhY3RvcihtYXJpdGFsLAogICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJNYXJyaWVkIiwgIldpZG93ZWQiLCAiRGl2b3JjZWQiLCAiU2VwYXJhdGVkIiwgIk5ldmVyIG1hcnJpZWQiKSksCiAgICBlZHVjYXRpb24gPSBmYWN0b3IoZWR1Y2F0aW9uLAogICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkxlc3MgdGhhbiBoaWdoIHNjaG9vbCIsICJIaWdoIHNjaG9vbCBncmFkdWF0ZSIsICJTb21lIGNvbGxlZ2UiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyIHllYXIgZGVncmVlIiwgIjQgeWVhciBkZWdyZWUiLCAiR3JhZHVhdGUgb3IgcHJvZmVzc2lvbmFsIGRlZ3JlZSIsICJEb2N0b3JhdGUiKSksCiAgICBpbmNvbWUgPSBmYWN0b3IoaW5jb21lLAogICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkxlc3MgdGhhbiBtZWRpYW4iLCAiTW9yZSB0aGFuIG1lZGlhbiIpKSwKICAgIHJhY2UgPSBmYWN0b3IocmFjZSwKICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiV2hpdGUiLCAiQmxhY2sgb3IgQWZyaWNhbiBBbWVyaWNhbiIsICJBbWVyaWNhbiBJbmRpYW4gb3IgQWxhc2thIE5hdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBc2lhbiIsICJOYXRpdmUgSGF3YWlpYW4gb3IgUGFjaWZpYyBJc2xhbmRlciIsICJPdGhlciIpKSwKICAgIGFnZSA9IGZhY3RvcihhZ2UsCiAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiTGVzcyB0aGFuIG1lZGlhbiIsICJNb3JlIHRoYW4gbWVkaWFuIikpCiAgKQoKcGVyc29uYV9iYXNlX2Nhc2VzIDwtIGMoCiAgIm5hdGlvbmFsLm5ld3NfUmFyZWx5IiwKICAiaW50ZXJuYXRpb25hbC5uZXdzX05ldmVyIiwKICAiZm9sbG93LmdvdnRfTm90IG9mdGVuIiwKICAidHJhdmVsX05vIiwKICAiaWRlb2xvZ3lfRXh0cmVtZWx5IGxpYmVyYWwiLAogICJ0cnVzdC5pbnN0aXR1dGlvbnNfTm8gdHJ1c3QiLAogICJzaG91bGQuYmUuY2hhcml0YWJsZV9TdHJvbmdseSBkaXNhZ3JlZSIsCiAgInJlbGlnaW91cy5hdHRlbmRhbmNlX05vdCBzdXJlIiwKICAicmVsaWdpb24uaW1wb3J0YW5jZV9Ob3QgaW1wb3J0YW50IiwKICAicmVsaWdpb25fQ2F0aG9saWMiLAogICJ0cnVzdC5jaGFyaXR5LmltcG9ydGFuY2VfTm90IGltcG9ydGFudCIsCiAgInRydXN0LmNoYXJpdGllc19ObyB0cnVzdCIsCiAgImRvbmF0aW9uLmZyZXF1ZW5jeV9Nb3JlIHRoYW4gb25jZSBhIG1vbnRoLCBsZXNzIHRoYW4gb25jZSBhIHllYXIiLAogICJkb25hdGVkLmxhc3QueWVhcl8kMS0kNDkiLAogICJ2b2x1bnRlZXJlZF9ObyIsCiAgInZvbHVudGVlci5mcmVxdWVuY3lfSGF2ZW4ndCB2b2x1bnRlZXJlZCBpbiBwYXN0IDEyIG1vbnRocyIsCiAgImhpc3RvcnkuYWN0aXZpc20ucGVyc29uYWxfTm90IGludm9sdmVkIiwKICAiaGlzdG9yeS5hY3RpdmlzbS5mYW1pbHlfTm90IGludm9sdmVkIiwKICAiZ2VuZGVyX01hbGUiLAogICJtYXJpdGFsX01hcnJpZWQiLAogICJlZHVjYXRpb25fTGVzcyB0aGFuIGhpZ2ggc2Nob29sIiwKICAiaW5jb21lX0xlc3MgdGhhbiBtZWRpYW4iLAogICJhZ2VfTGVzcyB0aGFuIG1lZGlhbiIKKQoKcGVyc29uYV90YWJsZSA8LSBwZXJzb25hcyAlPiUgCiAgZHVtbXlfY29sdW1ucyhzZWxlY3RfY29sdW1ucyA9IHBlcnNvbmFfY29sdW1ucywKICAgICAgICAgICAgICAgIHJlbW92ZV9zZWxlY3RlZF9jb2x1bW5zID0gVFJVRSkgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gLXBlcnNvbmFfaWQsIG5hbWVzX3RvID0gIm5hbWUiLCApICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcGVyc29uYV9pZCwgdmFsdWVzX2Zyb20gPSB2YWx1ZSkgJT4lIAogICMgR2V0IHJpZCBvZiBiYXNlIGNhc2VzCiAgZmlsdGVyKCEobmFtZSAlaW4lIHBlcnNvbmFfYmFzZV9jYXNlcykpICU+JSAKICBmaWx0ZXIoIXN0cl9kZXRlY3QobmFtZSwgIkRvbid0IGZvbGxvdyIpLAogICAgICAgICAhc3RyX2RldGVjdChuYW1lLCAiRG9uJ3QgYmVsb25nIikpICU+JSAKICBzZXBhcmF0ZShuYW1lLCBpbnRvID0gYygiYXR0cmlidXRlIiwgIm9wdGlvbiIpLCBzZXAgPSAiXyIpICU+JSAKICAjIEFkZCBpbnRlcmNlcHQKICBhZGRfcm93KGF0dHJpYnV0ZSA9ICJJbnRlcmNlcHQiLCBvcHRpb24gPSAiSW50ZXJjZXB0IiwgLmJlZm9yZSA9IDEpICU+JSAKICBtdXRhdGUoYWNyb3NzKGV2ZXJ5dGhpbmcoKSwgfnJlcGxhY2VfbmEoLiwgMSkpKQpgYGAKCmBgYHtyIHByZWRpY3RlZC1tYXJrZXQtc2hhcmVzfQpwcmVkaWN0ZWRfYmV0YXMgPC0gcGVyc29uYV90YWJsZSAlPiUgCiAgc3VtbWFyaXplKGFjcm9zcyhzdGFydHNfd2l0aCgicGVyc29uYSIpLCB+YXMubWF0cml4KGdhbW1hcykgJSolIGFzLm1hdHJpeCguKSkpCgpleHBlY3RlZF91dGlsaXRpZXMgPC0gZXhwKHQob3JnX3RhYmxlWywzOm5jb2wob3JnX3RhYmxlKV0pICUqJSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLm1hdHJpeChwcmVkaWN0ZWRfYmV0YXNbLDE6bmNvbChwcmVkaWN0ZWRfYmV0YXMpXSkpICU+JSAKICBhc190aWJibGUocm93bmFtZXMgPSAib3JnIikKCnByb3BfZXhwZWN0ZWRfdXRpbGl0aWVzIDwtIGV4cGVjdGVkX3V0aWxpdGllcyAlPiUgCiAgbXV0YXRlKGFjcm9zcyhzdGFydHNfd2l0aCgicGVyc29uYSIpLCB+LiAvIHN1bSguKSkpCmBgYAoKYGBge3IgZmluYWxpemUtZGF0YX0Kb3JnX2RldGFpbHMgPC0gb3JnYW5pemF0aW9ucyAlPiUgCiAgbXV0YXRlKG9yZ2FuaXphdGlvbiA9IHN0cl9yZXBsYWNlKG9yZ19pZCwgIm9yZyIsICJPcmcgIiksCiAgICAgICAgIGZ1bmRpbmcgPSBmY3RfcmVjb2RlKGZ1bmRpbmcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTW9zdGx5IGZ1bmRlZCBieSBzbWFsbCBkb25vcnMiID0gIlNtYWxsIHByaXZhdGUgZG9uYXRpb25zIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1vc3RseSBmdW5kZWQgYnkgZ292ZXJubWVudCBncmFudHMiID0gIkdvdmVybm1lbnQgZ3JhbnRzIiksCiAgICAgICAgIHJlbGF0aW9uc2hpcCA9IGZjdF9yZXYocmVsYXRpb25zaGlwKSkgJT4lCiAgc2VsZWN0KG9yZ19pZCwgb3JnYW5pemF0aW9uLCBvcmdfaXNzdWUgPSBpc3N1ZS5hcmVhLCAKICAgICAgICAgb3JnX2Z1bmRpbmcgPSBmdW5kaW5nLCBvcmdfcmVsYXRpb25zaGlwID0gcmVsYXRpb25zaGlwKQoKcGVyc29uYV9kZXRhaWxzIDwtIHBlcnNvbmFzICU+JSAKICBtdXRhdGUocGVyc29uYV9pbmNvbWUgPSBmY3RfcmVjb2RlKGluY29tZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTG93ZXIgaW5jb21lIiA9ICJMZXNzIHRoYW4gbWVkaWFuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSGlnaGVyIGluY29tZSIgPSAiTW9yZSB0aGFuIG1lZGlhbiIpLAogICAgICAgICBwZXJzb25hX2VkdWNhdGlvbiA9IGZjdF9yZWNvZGUoZWR1Y2F0aW9uLCAiQ29sbGVnZSBncmFkdWF0ZSIgPSAiNCB5ZWFyIGRlZ3JlZSIpLAogICAgICAgICBwZXJzb25hX3JlbGlnaW9uID0gZmN0X3JlY29kZShyZWxpZ2lvdXMuYXR0ZW5kYW5jZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSYXJlbHkgYXR0ZW5kcyByZWxpZ2lvdXMgc2VydmljZXMiID0gIlJhcmVseSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBdHRlbmRzIGF0IGxlYXN0IG1vbnRobHkiID0gIkF0IGxlYXN0IG9uY2UgYSBtb250aCIpLAogICAgICAgICBwZXJzb25hX2lkZW9sb2d5ID0gZmN0X3JlY29kZShpZGVvbG9neSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDb25zZXJ2YXRpdmUiID0gIkV4dHJlbWVseSBjb25zZXJ2YXRpdmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGliZXJhbCIgPSAiRXh0cmVtZWx5IGxpYmVyYWwiKSwKICAgICAgICAgcGVyc29uYV9leHBlcmllbmNlID0gaWZlbHNlKHRyYXZlbCA9PSAiWWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRm9sbG93cyB0aGUgbmV3czsgaGFzIHRyYXZlbGxlZCBhYnJvYWQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEb2Vzbid0IGZvbGxvdyBuZXdzOyBoYXMgbm90IHRyYXZlbGxlZCBhYnJvYWQiKSwKICAgICAgICAgcGVyc29uYV90cnVzdCA9IGlmZWxzZSh0cnVzdC5jaGFyaXRpZXMgPT0gIkNvbXBsZXRlIHRydXN0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1vcmUgdHJ1c3Rpbmc7IGRvbmF0ZXMgYW5kIHZvbHVudGVlcnMgb2Z0ZW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTGVzcyB0cnVzdGluZzsgZG9uYXRlcyBhbmQgdm9sdW50ZWVycyBsZXNzIG9mdGVuIikpICU+JSAKICBtdXRhdGUocGVyc29uYSA9IHN0cl9yZXBsYWNlKHBlcnNvbmFfaWQsICJwZXJzb25hIiwgIlBlcnNvbmEgIikpICU+JSAKICBzZWxlY3QocGVyc29uYSwgc3RhcnRzX3dpdGgoInBlcnNvbmEiKSkKCnNpbV9jbGVhbiA8LSBwcm9wX2V4cGVjdGVkX3V0aWxpdGllcyAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtb3JnLCBuYW1lc190byA9ICJwZXJzb25hX2lkIiwgdmFsdWVzX3RvID0gInNoYXJlIikgJT4lIAogIGxlZnRfam9pbihvcmdfZGV0YWlscywgYnkgPSBjKCJvcmciID0gIm9yZ19pZCIpKSAlPiUgCiAgbGVmdF9qb2luKHBlcnNvbmFfZGV0YWlscywgYnkgPSAicGVyc29uYV9pZCIpCmBgYAoKYGBge3Igc2F2ZS1jbGVhbi1kYXRhfQp3cml0ZV9yZHMoc2ltX2V4Y2VsX2NsZWFuLCBoZXJlKCJkYXRhIiwgImRlcml2ZWRfZGF0YSIsICJzaW1fZXhjZWxfZmluYWwucmRzIikpCndyaXRlX3JkcyhzaW1fY2xlYW4sIGhlcmUoImRhdGEiLCAiZGVyaXZlZF9kYXRhIiwgInNpbV9maW5hbC5yZHMiKSkKYGBgCgoKXAoKIyBPcmlnaW5hbCBjb21wdXRpbmcgZW52aXJvbm1lbnQKCjxidXR0b24gZGF0YS10b2dnbGU9ImNvbGxhcHNlIiBkYXRhLXRhcmdldD0iI3Nlc3Npb25pbmZvIiBjbGFzcz0iYnRuIGJ0bi1wcmltYXJ5IGJ0bi1tZCBidG4taW5mbyI+SGVyZSdzIHdoYXQgd2UgdXNlZCB0aGUgbGFzdCB0aW1lIHdlIGJ1aWx0IHRoaXMgcGFnZTwvYnV0dG9uPgoKPGRpdiBpZD0ic2Vzc2lvbmluZm8iIGNsYXNzPSJjb2xsYXBzZSI+CgpgYGB7ciBzaG93LXNlc3Npb24taW5mbywgZWNobz1UUlVFLCB3aWR0aD0xMDB9CmRldnRvb2xzOjpzZXNzaW9uX2luZm8oKQoKd3JpdGVMaW5lcyhyZWFkTGluZXMoZmlsZS5wYXRoKFN5cy5nZXRlbnYoIkhPTUUiKSwgIi5SL01ha2V2YXJzIikpKQpgYGAKCjwvZGl2Pgo=