1 Load data

# Read
filename <- "baza de date rezidential.xlsx"   
Data <- rio::import(filename)  
Data <- Data[, -c(197:202)]    # delete last 6 columns (empty excel columns for excel functions)

1.1 Processing data

# Clean
Data$judet <- as.factor(Data$judet)
Data$gen <- as.factor(Data$gen)  
Data$tip_chestionar <- as.factor(Data$tip_chestionar) # unique(Data$tip_chestionar) # "9-18ani", "5-8ani", "5-8intarziere"
Data$v_mama_nastere <- as.factor(Data$v_mama_nastere)
levels(Data$v_mama_nastere) <- c("<19", "20-25", "26–34", "35>")

1.2 Data Validation

data_validation <- function(x, log_level = futile.logger::WARN,
                             log_appender = "console",
                             log_issues = FALSE) {
  
  Rezidential_col_names <- c("ID", "judet", "oras", "centru", "tip_chestionar", "nume", "data", "varsta", "varsta_inst", "nr_frati", "nr_frati_inst", "v_mama_nastere", "expunere_tox", "boli", "TCC", "asfixie", "abuz_sub", "grad_h", "intarziere", "tras_dez", "tulb_cond", "neglijare", "temperam", "repetenta", "scoala_spec", "inabil_sc", "schimb_dom", "pierd_loc", "comunit", "gen", "cu_cine_loc", "familie", "cyrm_1", "cyrm_2", "cyrm_3", "cyrm_4", "cyrm_5", "cyrm_6", "cyrm_7", "cyrm_8", "cyrm_9", "cyrm_10", "cyrm_11", "cyrm_12", "cyrm_13", "cyrm_14", "cyrm_15", "cyrm_16", "cyrm_17", "cyrm_18", "cyrm_19", "cyrm_20", "cyrm_21", "cyrm_22", "cyrm_23", "cyrm_24", "cyrm_25", "cyrm_26", "cyrm_27", "cyrm_28", "cesd_1", "cesd_2", "cesd_3", "cesd_4", "cesd_5", "cesd_6", "cesd_7", "cesd_8", "cesd_9", "cesd_10", "cesd_11", "cesd_12", "cesd_13", "cesd_14", "cesd_15", "cesd_16", "cesd_17", "cesd_18", "cesd_19", "cesd_20", "gci_1", "gci_2", "gci_3", "gci_4", "gci_5", "gci_6", "gci_7", "gci_8", "gci_9", "gci_10", "gci_11", "gci_12", "gci_13", "gci_14", "sdq_1", "sdq_2", "sdq_3", "sdq_4", "sdq_5", "sdq_6", "sdq_7", "sdq_8", "sdq_9", "sdq_10", "sdq_11", "sdq_12", "sdq_13", "sdq_14", "sdq_15", "sdq_16", "sdq_17", "sdq_18", "sdq_19", "sdq_20", "sdq_21", "sdq_22", "sdq_23", "sdq_24", "sdq_25", "scar_1", "scar_2", "scar_3", "scar_4", "scar_5", "scar_6", "scar_7", "scar_8", "scar_9", "scar_10", "scar_11", "scar_12", "scar_13", "scar_14", "scar_15", "scar_16", "scar_17", "scar_18", "scar_19", "scar_20", "scar_21", "scar_22", "scar_23", "scar_24", "scar_25", "scar_26", "scar_27", "scar_28", "scar_29", "scar_30", "scar_31", "scar_32", "scar_33", "scar_34", "scar_35", "scar_36", "scar_37", "scar_38", "scar_39", "scar_40", "scar_41", "asc_1", "asc_2", "asc_3", "asc_4", "asc_5", "asc_6", "asc_7", "asc_8", "asc_9", "asc_10", "asc_11", "asc_12", "asc_13", "asc_14", "asc_15", "cyw_nr1", "cyw_nr2", "sec1_1", "sec1_2", "sec1_3", "sec1_4", "sec1_5", "sec1_6", "sec1_7", "sec1_8", "sec1_9", "sec1_10", 
"sec2_1", "sec2_2", "sec2_3", "sec2_4", "sec2_5", "sec2_6", "sec2_7", "sec2_8", "sec2_9")
  
  # Set logger severity threshold, defaults to
  # high level use (only flags warnings and errors)
  # Set log_level argument to futile.logger::TRACE for full info
  futile.logger::flog.threshold(log_level)
  
  # Set where to write the log to
  if (log_appender != "console")
  {
    # if not console then to a file called...
    futile.logger::flog.appender(futile.logger::appender.file(log_appender))
  }
  
  # Checks
  futile.logger::flog.info('Initiating Rezidential class.
                           \n\nExpects a data.frame with all Rezidential columns')
  
  # Integrity checks on incoming data ----
  
  # Check the structure of the data is as expected: data.frame containing no
  # missing values and three columns, containing sector, year, and one
  # additional column.
  
  futile.logger::flog.info('\n*** Running integrity checks on input dataframe (x):')
  futile.logger::flog.debug('\nChecking input is properly formatted...')
  
  futile.logger::flog.debug('Checking x is a data.frame...')
  if (!is.data.frame(x))
  {
    futile.logger::flog.error("x must be a data.frame",     # x, capture = TRUE)
                              capture = FALSE)
  }
  
  futile.logger::flog.debug('Checking x has correct number of columns...')
  if (length(colnames(x)) != 196)
  {
    futile.logger::flog.error("x must have 196 columns")
  }
  
  futile.logger::flog.debug('Checking x contains all Rezidential columns...')
  if (!all(Rezidential_col_names %in% colnames(Data))) stop("x must contain all Rezidential columns")
  
  futile.logger::flog.debug('Checking x has gen column with 2 factor levels: f, m...')
  if (!is.factor(x$gen) | !all(levels(x$gen) %in% c("f", "m")))
  {
    futile.logger::flog.error("x must have gen factor with 2 factor levels")
  }
  
  futile.logger::flog.debug('Checking x has tip_chestionar column with 3 factor levels: 9-18ani, 5-8ani, 5-8intarziere...')
  if (!is.factor(x$tip_chestionar) | !all(levels(x$tip_chestionar) %in% c("9-18ani", "5-8ani", "5-8intarziere")))
  {
    futile.logger::flog.error("x must have gen factor with 3 factor levels")
  }
  
 
  futile.logger::flog.info('...passed')
  
  
  futile.logger::flog.info("\n***Running statistical checks on input dataframe (x)")
  
  
  
  futile.logger::flog.debug('Checking that CYRM-26 has only NA in items 27 & 28 for 5-8 year olds ...')
  if(!all(is.na(x[x$tip_chestionar %in% c("5-8ani", "5-8intarziere"), ]$cyrm_27)) |
     !all(is.na(x[x$tip_chestionar %in% c("5-8ani", "5-8intarziere"), ]$cyrm_28))) 
  {
    stop("x has CYRM-26 with non-NA in items 27 & 28 for 5-8 year olds")
  }
  
  ### item 7 for 5-8 is item 8 in 9-18, item 7 & 9 from 9-18 dont exist for 5-8
  futile.logger::flog.debug('Checking that CYW ACE-Q Sect2 has only NA in items 8 & 9 for 5-8 year olds ...')
  if(!all(is.na(x[x$tip_chestionar %in% c("5-8ani", "5-8intarziere"), ]$sec2_8)) |
     !all(is.na(x[x$tip_chestionar %in% c("5-8ani", "5-8intarziere"), ]$sec2_9))) 
  {
    stop("x has CYW ACE-Q Sect2 with non-NA in items 7 & 9 for 5-8 year olds")
  }  
  
  
}
## Run Data Validation
# dput(names(Data), file = "dput_colnames.txt")       # Checks all column names
data_validation(Data, log_level = futile.logger::DEBUG)
INFO [2019-03-25 13:53:21] Initiating Rezidential class.
                           

Expects a data.frame with all Rezidential columns
INFO [2019-03-25 13:53:21] 
*** Running integrity checks on input dataframe (x):
DEBUG [2019-03-25 13:53:21] 
Checking input is properly formatted...
DEBUG [2019-03-25 13:53:21] Checking x is a data.frame...
DEBUG [2019-03-25 13:53:21] Checking x has correct number of columns...
DEBUG [2019-03-25 13:53:21] Checking x contains all Rezidential columns...
DEBUG [2019-03-25 13:53:21] Checking x has gen column with 2 factor levels: f, m...
DEBUG [2019-03-25 13:53:21] Checking x has tip_chestionar column with 3 factor levels: 9-18ani, 5-8ani, 5-8intarziere...
INFO [2019-03-25 13:53:21] ...passed
INFO [2019-03-25 13:53:21] 
***Running statistical checks on input dataframe (x)
DEBUG [2019-03-25 13:53:21] Checking that CYRM-26 has only NA in items 27 & 28 for 5-8 year olds ...
DEBUG [2019-03-25 13:53:21] Checking that CYW ACE-Q Sect2 has only NA in items 8 & 9 for 5-8 year olds ...

1.3 Sample Map

## Get map
# https://gadm.org/download_country.html
# library(raster) # for getData() download map automatically so we dont have to download it by hand
# gadmRO <- getData('GADM', country='RO', level=1)
gadmRO <- readRDS("ROU_adm1.rds")  # load downloaded map 
## Count judet from Rezidential
count_df <- 
  Data %>%
    dplyr::count(judet) %>% 
    dplyr::rename(NAME_1 = judet, count = n) %>%
    dplyr::mutate(NAME_1 = as.character(NAME_1)) %>%
    dplyr::mutate(NAME_1 = stringr::str_replace(NAME_1, "Bucuresti", "Ilfov"))    # replace Bucuresti with Ilfov
    
## Arange dataset for map
gadmRO@data$NAME_1 <- iconv(gadmRO@data$NAME_1, from="UTF-8", to="ASCII//TRANSLIT")   # encoding and diacritics problems
gadmRO@data$NAME_1 <- c("Alba", "Arad", "Arges","Bacau","Bihor","Bistrita-Nasaud", "Botosani", "Brasov", "Braila", "Bucharest", "Buzau","Calarasi", "Caras-Severin",   "Cluj", "Constanta", "Covasna", "Dambovita", "Dolj", "Galati", "Giurgiu", "Gorj", "Harghita",  "Hunedoara", "Iasi", "Ialomita",  "Ilfov", "Maramures", "Mehedinti", "Mures", "Neamt", "Olt", "Prahova","Salaj","Satu Mare", "Sibiu", "Suceava", "Teleorman", "Timis","Tulcea", "Valcea", "Vaslui", "Vrancea")
gadmRO@data$id <- rownames(gadmRO@data)
gadmRO@data$total_sent <- c(30, 25, 101, 65, 30, 20, 0, 30, 10, 0, 30, 20, 35, 0, 55, 0, 20, 0, 45, 25, 50, 20, 20, 300, 0, 125, 20, 10, 0, 20, 120, 80, 80, 20, 30, 150, 0, 30, 11, 0, 20, 16)
gadmRO@data <- left_join(gadmRO@data, count_df, by = "NAME_1")
gadmRO@data <- 
   gadmRO@data %>%
      mutate(category = if_else(is.na(count), NA_integer_, count)) %>%       # dont excplude NA, and use na.value in ggplot
      mutate(category = cut(category, breaks=c(-Inf, 0, 20, 50, 100, 300), 
                            labels=c("0", "1-20", "20-50", "50-100", "100-300"))) 
      
RO_df <- fortify(gadmRO)
RO_df <- left_join(RO_df, gadmRO@data, by = "id")
judete <- 
  RO_df %>%
  plyr::ddply(.(id, HASC_1), summarize, 
                      centrulong = centroid(cbind(long, lat))[1], 
                      centrulat = centroid(cbind(long, lat))[2])
# centroid()[1] is longitudine   --    centroid centroid()[2] is latitudine
judete <- subset(judete, HASC_1!="RO.BI")   # drop Bucuresti bacause we have IF as county
## Output table - unrelated to map data
gadmRO@data  %>%
    dplyr::select(NAME_1, total_sent, count) %>% 
    dplyr::filter(NAME_1 != "Bucharest") %>%
    dplyr::mutate(NAME_1 = stringr::str_replace(NAME_1, "Ilfov", "Ilfov / Bucuresti")) %>%
    dplyr::mutate(count = replace_na(count, 0)) %>% 
    do(bind_rows(., data.frame(NAME_1 = "Total", total_sent = sum(.$total_sent), count = sum(.$count)))) %>%
    dplyr::mutate(perc_return = round(count/total_sent*100, 2)) %>%
    dplyr::mutate(perc_return = replace_na(perc_return, "-")) %>%
  
    knitr::kable(caption = "Sample Information",
                 col.names = c("County", "No. Sent", "No. Returned", "% Returned")) %>% 
    kableExtra::kable_styling(bootstrap_options = "striped", full_width = FALSE, position = "center") %>%
    kableExtra::row_spec(row = 42, bold = TRUE)

Sample Information
County No. Sent No. Returned % Returned
Alba 30 24 80
Arad 25 24 96
Arges 101 61 60.4
Bacau 65 54 83.08
Bihor 30 18 60
Bistrita-Nasaud 20 16 80
Botosani 0 0 -
Brasov 30 24 80
Braila 10 10 100
Buzau 30 30 100
Calarasi 20 19 95
Caras-Severin 35 31 88.57
Cluj 0 0 -
Constanta 55 45 81.82
Covasna 0 0 -
Dambovita 20 10 50
Dolj 0 0 -
Galati 45 44 97.78
Giurgiu 25 25 100
Gorj 50 28 56
Harghita 20 15 75
Hunedoara 20 15 75
Iasi 300 268 89.33
Ialomita 0 0 -
Ilfov / Bucuresti 125 63 50.4
Maramures 20 10 50
Mehedinti 10 10 100
Mures 0 0 -
Neamt 20 15 75
Olt 120 79 65.83
Prahova 80 59 73.75
Salaj 80 60 75
Satu Mare 20 19 95
Sibiu 30 22 73.33
Suceava 150 133 88.67
Teleorman 0 0 -
Timis 30 7 23.33
Tulcea 11 8 72.73
Valcea 0 0 -
Vaslui 20 13 65
Vrancea 16 16 100
Total 1663 1275 76.67

NA
## Set ggplot2 theme for map
theme_opts<-list(theme(panel.grid.minor = element_blank(),
                       panel.grid.major = element_blank(),
                       panel.background = element_blank(),
                       plot.background = element_blank(),
                       axis.line = element_blank(),
                       axis.text.x = element_blank(),
                       axis.text.y = element_blank(),
                       axis.ticks = element_blank(),
                       axis.title.x = element_blank(),
                       axis.title.y = element_blank(),
                       plot.title = element_blank()))
## Plot continuous count -- disabled here 
# ggplot() + 
#   geom_polygon(data = RO_df, aes(long, lat, group = group, fill = count )) +
#   geom_path(data = RO_df, aes(long, lat, group = group), color = "grey", size = 0.1) +
#   scale_fill_distiller(name = "Chestionare", palette = "Greens", trans = "reverse", 
#                        breaks = scales::pretty_breaks(n = 5), na.value = "lightyellow" ) +  
#   labs(title="Nice Map") +
#   geom_text(data = judete, 
#             aes(x = centrulong, y = centrulat, label = gsub("^.*\\.","", HASC_1), 
#             size = 0.2), show.legend = FALSE) +  # extract AB from RO.AB
#   theme_opts
## Plot categories of counts
ggplot() + 
  geom_polygon(data = RO_df, aes(long, lat, group = group, fill = category )) +
  geom_path(data = RO_df, aes(long, lat, group = group), color = "grey", size = 0.1) +
  scale_fill_brewer(name = "Chestionare", type = 'div', palette = 'Greens', direction = 1, na.value = "lightyellow") +
  labs(title="Nice Map") +
  geom_text(data = judete, 
            aes(x = centrulong, y = centrulat, label=gsub("^.*\\.","", HASC_1), 
            size = 0.2), show.legend = FALSE) +  # extract AB from RO.AB
  theme_opts

1.4 Transform & Compute new variables

## Check Scale Items Names
# Data[, 13:29]  # itemi predictori ACE
# Data[, 33:58]  # CYRM-26 doar pt 5-8 ani
# Data[, 33:60]  # CYRM-28 doar pt 9-18 ani
# Data[, 61:80]  # CESDC
# Data[, 81:94]  # GCI
# Data[, 95:119]  # SDQ
# Data[, 120:160]  # Scared
# Data[, 161:175]  # ASCQ
# Data[, 178:187]  # CYW ACE-Q Sect1  -- sum should be equal to "cyw_nr1"
# Data[, 188:196]  # CYW ACE-Q Sect2 -- sum should be equal to "cyw_nr2" -- 7 items for 5-8 (excluds sec2_7 & sec2_9), 9 items for 9-18
## Transform 
  # CYW ACE-Q Sect2 -- 5-8 years has only NA in 8, 9 and 7 corresponds to item 8 in 9-18 years
  # item 7 will be "rautate" for all levels
  # item 8 "politie" only 9-18 years
Data <- 
  Data %>% 
  dplyr::mutate(rautate = if_else(tip_chestionar %in% c("5-8ani", "5-8intarziere"), sec2_7, sec2_8)) %>%
  dplyr::mutate(politie = if_else(tip_chestionar == "9-18ani", sec2_7, as.numeric(NA)))  %>%                  
  dplyr::mutate(sec2_7 = rautate) %>%
  dplyr::mutate(sec2_8 = politie) %>%
  dplyr::select(-c(rautate, politie))
## Define function that calculates RowSums but only for rows with less than 10% NAs; and return NA if all row values are NA 
SpecialRowSums <- function(df, napercent = .1) {
  ifelse(rowSums(is.na(df)) > ncol(df) * napercent,
    NA,
    rowSums(df, na.rm = TRUE) * NA ^ (rowSums(!is.na(df)) == 0)
  )
}
## Compute new variables 
# Scared -- recode 1,2,3 in 0,1,2
  # Total score + cutoff >= 25
  # A score of 7 for items 1, 6, 9, 12, 15, 18, 19, 22, 24, 27, 30, 34, 38 may indicate Panic Disorder
  # A score of 9 for items 5, 7, 14, 21, 23, 28, 33, 35, 37 may indicate Generalized Anxiety Disorder
  # A score of 5 for items 4, 8, 13, 16, 20, 25, 29, 31 may indicate Separation Anxiety
  # A score of 8 for items 3, 10, 26, 32, 39, 40, 41 may indicate Social Anxiety Disorder
  # A score of 3 for items 2, 11, 17, 36 may indicate significant school avoidance
Data[, sprintf("scar_%d", 1:41)] <- Data[, sprintf("scar_%d", 1:41)] - 1     # recode SCARED
Data$PD <- SpecialRowSums(Data[, sprintf("scar_%d", c(1, 6, 9, 12, 15, 18, 19, 22, 24, 27, 30, 34, 38))])
Data$GAD <- SpecialRowSums(Data[, sprintf("scar_%d", c(5, 7, 14, 21, 23, 28, 33, 35, 37))])
Data$SepA <- SpecialRowSums(Data[, sprintf("scar_%d", c(4, 8, 13, 16, 20, 25, 29, 31))])
Data$SAD <- SpecialRowSums(Data[, sprintf("scar_%d", c(3, 10, 26, 32, 39, 40, 41))])
Data$SchA <- SpecialRowSums(Data[, sprintf("scar_%d", c(2, 11, 17, 36))])
Data$SCARED <- SpecialRowSums(Data[, sprintf("scar_%d", 1:41)])
Data$PD_d <- ifelse(Data$PD >= 7, 1, 0)
Data$GAD_d <- ifelse(Data$GAD >= 9, 1, 0)
Data$SepA_d <- ifelse(Data$SepA >= 5, 1, 0)
Data$SAD_d <- ifelse(Data$SAD >= 8, 1, 0)
Data$SchA_d <- ifelse(Data$SchA >= 3, 1, 0)
Data$SCARED_d <- ifelse(Data$PD >= 25, 1, 0)
# CESD -- already coded in 0,1,2,3 
# reversed: 4, 8, 12, 16
# 0-14 = Mild or no depression; 15-60 = significant depression
Data[, sprintf("cesd_%d", c(4, 8, 12, 16))] <- 3 - Data[, sprintf("cesd_%d", c(4, 8, 12, 16))] # recode CESD
Data$CESD <- SpecialRowSums(Data[, sprintf("cesd_%d", 1:20)])
Data$CESD_d <- ifelse(Data$CESD >= 15, 1, 0)
# ASCQ -- already coded in 1,2,3,4,5
  # Secure: 1 3 7 10 15 
  # Anxious: 5 6 9 11 14
  # Avoidant: 2 4 8 12 13
  # Data[, c("ASecur", "AAnxio", "AAvoid", "ASCQ_f", "ASCQ_d")]
Data$ASecur <- SpecialRowSums(Data[, sprintf("asc_%d", c(1, 3, 7, 10, 15))], napercent = .3)   # if more than 2 NA items => NA
Data$AAnxio <- SpecialRowSums(Data[, sprintf("asc_%d", c(5, 6, 9, 11, 14))], napercent = .3)
Data$AAvoid <- SpecialRowSums(Data[, sprintf("asc_%d", c(2, 4, 8, 12, 13))], napercent = .3)
Data <- 
      Data %>%
        dplyr::mutate( 
            ASCQ_f = dplyr::case_when(
              ASecur > AAnxio & ASecur > AAvoid ~ "Secur",
              ASecur == AAnxio & ASecur > AAvoid ~ "Secur&Anxio",
              AAnxio > ASecur & AAnxio > AAvoid ~ "Anxio",
              AAvoid > ASecur & AAvoid > AAnxio ~ "Avoid",
              AAvoid == ASecur & AAvoid > AAnxio ~ "Secur&Avoid",
              AAvoid > ASecur & AAvoid == AAnxio ~ "Anxio&Avoid",
              ASecur == AAnxio & ASecur == AAvoid ~ "Secur&Anxio&Avoid",
              TRUE ~ as.character(NA))) %>%
        dplyr::mutate(ASCQ_f = as.factor(ASCQ_f))
Data <-
      Data %>%                     # insecure = 1, secure = 0
        dplyr::mutate(
          ASCQ_d = ifelse(ASCQ_f %in% c("Secur", "Secur&Anxio", "Secur&Avoid", "Secur&Anxio&Avoid"), 0, 1)) 
# GCIC -- already coded in 1,2,3,4,5
  # Open Climate (Positive wording): first 9 items
  # Closed Climate(Negative wording): last 5 items (10, 11 are reversed positively worder)
  # Total Score ?= Open + rerversed Closed except 10&11  
Data[, sprintf("gci_%d", c(10, 11))] <- 6 - Data[, sprintf("gci_%d", c(10, 11))]
Data$OpenC <- SpecialRowSums(Data[, sprintf("gci_%d", 1:9)], napercent = .3)   # if more than 3 NA items => NA
Data$CloseC <- SpecialRowSums(Data[, sprintf("gci_%d", 10:14)], napercent = .3) # if more than 2 NA items => NA
 
# SDQ
  # diffrent wording for 5-8 and 9-18 but exactly the same items
  # we have just the first part of SDQ; no impact scores
  # recode: 7(obeys), 11 (friend), 14 (popular), 21(reflect), 25(attends)
    # Total = emotion + conduct + hyper + peer  (all subscales exept prosocial)
    # For each of the 5 scales the score can range from 0 to 10 if all items were completed.  http://www.sdqinfo.org/c9.html
    # These scores can be scaled up pro-rata if at least 3 items were completed, 
    # e.g. a score of 4 based on 3 completed items can be scaled up to a score of 7 (6.67 rounded up) for 5 items.
  # Data[, c("Emotion", "Conduct", "Hyper", "Peer", "Prosoc", "External", "Internal", "SDQ")]
# Recode -- first 1,2,3 to 0,1,2 ...then reverse score items
Data[, sprintf("sdq_%d", 1:25)] <- Data[, sprintf("sdq_%d", 1:25)] - 1
Data[, sprintf("sdq_%d", c(7, 11, 14, 21, 25))] <- 2 - Data[, sprintf("sdq_%d", c(7, 11, 14, 21, 25))]
# Define function that scores SDQ subscales and use it
ScoringSDQ <- function(df){
  na_vec <- apply(df, 1, function(x) sum(is.na(x))) 
  scale_score <- ifelse(na_vec < 3, rowMeans(df, na.rm=TRUE), NA)
  scale_score <- as.numeric(scale_score) * 5
  scale_score <- floor(0.5 + scale_score)
}
Data$Emotion <- ScoringSDQ(Data[, sprintf("sdq_%d", c(3, 8, 13, 16, 24))])
Data$Conduct <- ScoringSDQ(Data[, sprintf("sdq_%d", c(5, 7, 12, 18, 22))])
Data$Hyper <- ScoringSDQ(Data[, sprintf("sdq_%d", c(2, 10, 15, 21, 25))])   
Data$Peer <- ScoringSDQ(Data[, sprintf("sdq_%d", c(6, 11, 14, 19, 23))]) 
Data$Prosoc <- ScoringSDQ(Data[, sprintf("sdq_%d", c(1, 4, 9, 17, 20))])   
Data$External <-  rowSums(Data[, c("Conduct", "Hyper")])
Data$Internal <- rowSums(Data[, c("Emotion", "Peer")])
Data$SDQ <- rowSums(Data[, c("Emotion", "Conduct", "Hyper", "Peer")]) 
Data$Emotion_d <- ifelse(Data$Emotion >= 7, 1, 0)   # cutoff scores https://www.leicspart.nhs.uk/Library/poilkj690.pdf
Data$Conduct_d <- ifelse(Data$Conduct >= 6, 1, 0)
Data$Hyper_d <- ifelse(Data$Hyper >= 8, 1, 0)   
Data$Peer_d <- ifelse(Data$Peer >= 5, 1, 0) 
Data$Prosoc_d <- ifelse(Data$Prosoc <= 4, 1, 0)
Data$SDQ_d <- ifelse(Data$SDQ >= 20, 1, 0) 
  
# CYRM
  # Data[, 33:58]  # CYRM-26 doar pt 5-8 ani
  # Data[, 33:60]  # CYRM-28 doar pt 9-18 ani
  # CYRM 26 (5-8 years)
    # CYRMscore = SUM (1:26)
    # CYRM_Individ = SUM (2, 4, 8, 10, 12, 13, 14, 17, 19, 20, 24)
    # CYRM_Caregiver = SUM (5, 6, 7, 11, 16, 23, 25)
    # CYRM_Context = SUM (1, 3, 9, 15, 18, 21, 22, 26)
      # IndPS=SUM (2, 8, 10, 12, 20)
      # IndPeer= SUM (13, 17)
      # IndSS= SUM (4, 14, 19, 24)
      # CrPhys= SUM (5, 7)
      # CrPsyc= SUM (6, 11, 16, 23, 25)
      # CntS= SUM (21, 22)
      # CntEd= SUM (3, 15)
      # CntC= SUM (1, 9, 18, 26)
  # CYRM 28 (9-18 years)
    # CYRMscore = SUM (1:28)
    # CYRM_Individ = SUM (2, 4, 8, 11, 13, 14, 15, 18, 20, 21, 25)
    # CYRM_Caregiver = SUM (5, 6, 7, 12, 17, 24, 26)
    # CYRM_Context = SUM (1, 3, 9, 10, 16, 19, 22, 23, 27, 28)
Data$R_Ind_k <- rep(NA, nrow(Data))
Data[Data$tip_chestionar %in% c("5-8ani", "5-8intarziere"), ]$R_Ind_k <- 
                               SpecialRowSums(Data[Data$tip_chestionar %in% c("5-8ani", "5-8intarziere"), 
                                              sprintf("cyrm_%d", c(2, 4, 8, 10, 12, 13, 14, 17, 19, 20, 24))],
                                              napercent = .29)
Data$R_Care_k <- rep(NA, nrow(Data))
Data[Data$tip_chestionar %in% c("5-8ani", "5-8intarziere"), ]$R_Care_k <- 
                               SpecialRowSums(Data[Data$tip_chestionar %in% c("5-8ani", "5-8intarziere"), 
                                              sprintf("cyrm_%d", c(5, 6, 7, 11, 16, 23, 25))],
                                              napercent = .29)
Data$R_Cont_k <- rep(NA, nrow(Data))
Data[Data$tip_chestionar %in% c("5-8ani", "5-8intarziere"), ]$R_Cont_k <- 
                               SpecialRowSums(Data[Data$tip_chestionar %in% c("5-8ani", "5-8intarziere"), 
                                              sprintf("cyrm_%d", c(1, 3, 9, 15, 18, 21, 22, 26))],
                                              napercent = .29)
Data$CYRM_k <- rep(NA, nrow(Data))
Data$CYRM_k <- rowSums(Data[, c("R_Ind_k", "R_Care_k", "R_Cont_k")])          # _k scores not comparable to _a scores
Data$R_Ind_a <- rep(NA, nrow(Data))
Data[Data$tip_chestionar =="9-18ani", ]$R_Ind_a <- 
                               SpecialRowSums(Data[Data$tip_chestionar == "9-18ani", 
                                              sprintf("cyrm_%d", c(2, 4, 8, 11, 13, 14, 15, 18, 20, 21, 25))],
                                              napercent = .29)
Data$R_Care_a <- rep(NA, nrow(Data))
Data[Data$tip_chestionar =="9-18ani", ]$R_Care_a <- 
                               SpecialRowSums(Data[Data$tip_chestionar == "9-18ani", 
                                              sprintf("cyrm_%d", c(5, 6, 7, 12, 17, 24, 26))],
                                              napercent = .29)
Data$R_Cont_a <- rep(NA, nrow(Data))
Data[Data$tip_chestionar =="9-18ani", ]$R_Cont_a <- 
                               SpecialRowSums(Data[Data$tip_chestionar  == "9-18ani", 
                                              sprintf("cyrm_%d", c(1, 3, 9, 10, 16, 19, 22, 23, 27, 28))],
                                              napercent = .29)
Data$CYRM_a <- rep(NA, nrow(Data))
Data$CYRM_a <- rowSums(Data[, c("R_Ind_a", "R_Care_a", "R_Cont_a")])        # _k scores not comparable to _a scores
# CYW
  # 5-8 years have NA in item 7 and 8, but this doesnt count for cyw_nr1 and cyw_nr2 
Data$CYW <- rowSums(Data[, c("cyw_nr1", "cyw_nr2")], na.rm = TRUE)         

1.5 Export .R for Rezidential2 notebook

1.6 Descriptives for Demographics

apply_if <- function(mat, p, f) {
  # Fill NA with FALSE
  p[is.na(p)] <- FALSE
  mat[p] <- f(mat[p])
  mat
}
apaCorr <- function(mat, corrtype = "pearson") {
  matCorr <- mat
  if (class(matCorr) != "rcorr") {
    matCorr <- rcorr(mat, type = corrtype)
  }
  # Add one star for each p < 0.05, 0.01, 0.001
  stars <- apply_if(round(matCorr$r, 2), matCorr$P < 0.05, function(x) paste0(x, "*"))
  stars <- apply_if(stars, matCorr$P < 0.01, function(x) paste0(x, "*"))
  stars <- apply_if(stars, matCorr$P < 0.001, function(x) paste0(x, "*"))
  # Put - on diagonal and blank on upper diagonal
  stars[upper.tri(stars, diag = T)] <- "-"
  stars[upper.tri(stars, diag = F)] <- ""
  n <- length(stars[1,])
  colnames(stars) <- 1:n
  # Remove _ and convert to title case
  row.names(stars) <- tools::toTitleCase(sapply(row.names(stars), gsub, pattern="_", replacement = " "))
  # Add index number to row names
  row.names(stars) <- paste(paste0(1:n,"."), row.names(stars))
  stars
}
summarytools::dfSummary(Data[, c("gen", "varsta")], 
                        style = "grid", plain.ascii = FALSE, graph.magnif = 0.75)  %>% 
                          print(method = "render", footnote = NA)

Data Frame Summary

Data

N: 1275
No Variable Stats / Values Freqs (% of Valid) Graph Valid Missing
1 gen [factor] 1. f 2. m 666 (52.2%) 609 (47.8%) 1275 (100%) 0 (0%)
2 varsta [numeric] mean (sd) : 13.35 (3.3) min < med < max : 5 < 14 < 18 IQR (CV) : 5 (0.25) 111 distinct values 1275 (100%) 0 (0%)

tadaa_t.test(data = Data, response = varsta, group = gen, print = "markdown") %>% 
                          print(method = "render", footnote = NA)

Table 1: Two Sample t-test with alternative hypothesis: µ1 µ2

Diff µ1 f µ2 m t SE df CI95% p Cohen's d Power
0.3 13.49 13.19 1.6 0.18 1273 (-0.07 - 0.66) .109 0.09 0.36
summarytools::dfSummary(Data[, c("v_mama_nastere", "varsta_inst", "nr_frati", "nr_frati_inst")], 
                        style = "grid", plain.ascii = FALSE, graph.magnif = 0.75)  %>% 
                          print(method = "render", footnote = NA)

Data Frame Summary

Data

N: 1275
No Variable Stats / Values Freqs (% of Valid) Graph Valid Missing
1 v_mama_nastere [factor] 1. <19 2. 20-25 3. 2634 4. 35> 157 (13.8%) 497 (43.7%) 369 (32.4%) 115 (10.1%) 1138 (89.25%) 137 (10.75%)
2 varsta_inst [numeric] mean (sd) : 7.27 (4) min < med < max : 0.08 < 7 < 18 IQR (CV) : 6 (0.55) 86 distinct values 1158 (90.82%) 117 (9.18%)
3 nr_frati [numeric] mean (sd) : 4.04 (2.7) min < med < max : 0 < 3 < 16 IQR (CV) : 3 (0.67) 16 distinct values 1187 (93.1%) 88 (6.9%)
4 nr_frati_inst [numeric] mean (sd) : 2.23 (1.78) min < med < max : 0 < 2 < 11 IQR (CV) : 2 (0.8) 12 distinct values 1070 (83.92%) 205 (16.08%)

GGally::ggpairs(Data, columns = c("nr_frati", "nr_frati_inst"), mapping = aes_string(colour = "gen"),
       upper = list(continuous = "smooth", combo = "box", discrete = "facetbar", na = "na"),
       lower = list(continuous = "smooth_loess", combo = "facethist", discrete = "ratio", na = "na"), # "facetdensity"
       diag = list(continuous = wrap("densityDiag", alpha=0.3), discrete = "barDiag", na = "naDiag"))

GGally::ggpairs(Data, columns = c("v_mama_nastere", "varsta_inst"), mapping = aes_string(colour = "gen"),
       upper = list(continuous = "smooth", combo = "box", discrete = "facetbar", na = "na"),
       lower = list(continuous = "smooth_loess", combo = "facethist", discrete = "ratio", na = "na"), 
       diag = list(continuous = wrap("densityDiag", alpha=0.3), discrete = "barDiag", na = "naDiag"))

Data %>%    # change back factor to numeric in order to compute correlations
  mutate(v_mama_nastere = fct_recode(v_mama_nastere, "1" = "<19" , "2" = "20-25", "3" = "26–34", "4" = "35>")) %>%   
  select(v_mama_nastere, varsta_inst, nr_frati, nr_frati_inst) %>%
  as.matrix(.) %>%
    apaCorr(corrtype = "pearson")  %>% knitr::kable(caption = "Correlations", format = "markdown")

1 2 3 4
1. v Mama Nastere -
2. Varsta Inst 0.01 -
3. Nr Frati 0.19*** -0.08** -
4. Nr Frati Inst 0.06 -0.14*** 0.55*** -

# apaCorr(as.matrix(.[, c("v_mama_nastere", "varsta_inst", "nr_frati", "nr_frati_inst")]), corrtype = "pearson") %>% 
#         knitr::kable(format = "markdown")     # level of significance (p < 0.05, p < 0.01, p < 0.001)

1.7 Descriptives for Risk

Risk_col_names <- c("expunere_tox", "boli", "TCC", "asfixie", "abuz_sub", "grad_h", "intarziere", "tras_dez", "tulb_cond", 
                    "neglijare", "temperam", "repetenta", "scoala_spec", "inabil_sc", "schimb_dom", "pierd_loc", "comunit")
# Plot function and Data function
risk_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("")  
}
risk_data <- function(df, risk_levels, filter_col, filter_level){
  filter_col <- rlang::enquo(filter_col)
  df %>% 
    filter(!!filter_col %in% filter_level) %>% 
    select(Risk_col_names) %>%
    summarise_all(funs(sum(!is.na(.)) / length(.) * 100)) %>% 
    gather(variable, percent) %>%
    arrange(desc(percent)) %>%
    mutate(variable = factor(variable, risk_levels)) 
}
# Rsik data & plots
Data_Risk <- 
  Data %>%    
    select(Risk_col_names) %>%
    summarise_all(funs(sum(!is.na(.)) / length(.) * 100)) %>% 
    gather(variable, percent) %>%
    arrange(desc(percent)) %>%
    mutate(variable = factor(variable, variable))     # this makes levels order match row order!
risk_levels <- levels(Data_Risk$variable)  
risk_plot1 <- 
  Data_Risk %>%
    risk_plot() +
      ggtitle("Risk") 
risk_plot2 <-  
  risk_data(Data, risk_levels, gen, filter_level = "f") %>%
    risk_plot() +
      ggtitle("Risk - girls") 
risk_plot3 <-
  risk_data(Data, risk_levels, gen, filter_level = "m") %>%
    risk_plot() +
      ggtitle("Risk - boys") 
risk_plot4 <-
  risk_data(Data, risk_levels, tip_chestionar, filter_level = c("5-8ani", "5-8intarziere")) %>%
    risk_plot() +
      ggtitle("Risk - 5-8 years") 
risk_plot5 <-
  risk_data(Data, risk_levels, tip_chestionar, filter_level = "9-18ani") %>%
    risk_plot() +
      ggtitle("Risk - 9-18 years")
ggpubr::ggarrange(risk_plot1,                                                 
          ggarrange(risk_plot2, risk_plot3, ncol = 2, labels = c("B", "C")), 
          ggarrange(risk_plot4, risk_plot5, ncol = 2, labels = c("C", "D")),
          nrow = 3, 
          labels = "A")

1.8 Descriptives for ACEs

# 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 - girls") 
ace_plot3 <-
  ace_data(Data, ace_levels, gen, filter_level = "m") %>%
    ace_plot() +
      ggtitle("ACE - boys") 
ace_plot4 <-
  ace_data(Data, ace_levels, tip_chestionar, filter_level = c("5-8ani", "5-8intarziere")) %>%
    ace_plot() +
      ggtitle("ACE - 5-8 years") 
ace_plot5 <-
  ace_data(Data, ace_levels, tip_chestionar, filter_level = "9-18ani") %>%
    ace_plot() +
      ggtitle("ACE - 9-18 years")
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")                                        

           
#Data %>%
  #select(ID, tip_chestionar, gen, sprintf("sec1_%d", 1:10), sprintf("sec2_%d", 1:9)) %>%
  #gather(variable, value, sec1_1:sec2_9, -c(tip_chestionar, gen), na.rm = FALSE, convert = FALSE) %>%
  #mutate(value = replace_na(value, 0)) %>%
  

1.9 Descriptives for ACE Score

summarytools::dfSummary(Data[, "CYW"], 
                        style = "grid", plain.ascii = FALSE, graph.magnif = 0.75)  %>% 
                          print(method = "render", footnote = NA)

Data Frame Summary

CYW

N: 1275
No Variable Stats / Values Freqs (% of Valid) Graph Valid Missing
1 x [numeric] mean (sd) : 5.56 (3.23) min < med < max : 0 < 5 < 19 IQR (CV) : 5 (0.58) 19 distinct values 1275 (100%) 0 (0%)

tadaa_t.test(data = Data, response = CYW, group = gen, print = "markdown") %>% 
                          print(method = "render", footnote = NA)

Table 2: Two Sample t-test with alternative hypothesis: µ1 µ2

Diff µ1 f µ2 m t SE df CI95% p Cohen's d Power
0.1 5.6 5.51 0.54 0.18 1273 (-0.26 - 0.45) .589 0.03 0.08

GGally::ggpairs(Data, columns = c("CYW", "gen"), mapping = aes_string(colour = "gen"),
       upper = list(continuous = "smooth", combo = "box", discrete = "facetbar", na = "na"),
       lower = list(continuous = "smooth_loess", combo = "facethist", discrete = "ratio", na = "na"), 
       diag = list(continuous = wrap("densityDiag", alpha=0.3), discrete = "barDiag", na = "naDiag"))

1.10 Correlations: ACE Score, Risk, ACEs

# Data %>%
#   rename_at(vars(Ace_col_names), ~ Ace_new_names) %>%
#   select(CYW, Ace_new_names, Risk_col_names) %>%
#   replace(is.na(.), 0) %>%
#   as.matrix(.) %>%
#     apaCorr(corrtype = "pearson")  %>% knitr::kable(caption = "Correlations", format = "markdown")
Data %>%
    rename_at(vars(Ace_col_names), ~ Ace_new_names) %>%
    select(CYW, Ace_new_names, Risk_col_names) %>%
    replace(is.na(.), 0) %>%
    as.matrix(.) %>%
      Hmisc::rcorr(., type = "pearson") %>% 
      with(                                      # piping with multi-argument functions
      corrplot::corrplot(.$r, method = "number", type = "upper", p.mat = .$P, sig.level = 0.05, 
               insig = "blank", tl.col = "black", tl.cex = .9, tl.srt = 45, number.cex = 0.5) 
      )


2 Session Info

R version 3.5.2 (2018-12-20)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

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] bindrcpp_0.2.2             geosphere_1.5-7            plyr_1.8.4                 PerformanceAnalytics_1.5.2 xts_0.11-2                
 [6] zoo_1.8-4                  tadaatoolbox_0.16.1        summarytools_0.8.8         car_3.0-2                  carData_3.0-2             
[11] scales_1.0.0               RColorBrewer_1.1-2         corrplot_0.84              GGally_1.4.0               psycho_0.4.0              
[16] Hmisc_4.1-1                Formula_1.2-3              survival_2.43-3            lattice_0.20-38            rio_0.5.16                
[21] ggpubr_0.2                 magrittr_1.5               broom_0.5.1                papaja_0.1.0.9842          psych_1.8.10              
[26] forcats_0.3.0              stringr_1.3.1              dplyr_0.7.8                purrr_0.2.5                readr_1.3.0               
[31] tidyr_0.8.2                tibble_1.4.2               ggplot2_3.1.0              tidyverse_1.2.1            kableExtra_1.0.1          
[36] knitr_1.21                 pacman_0.5.0              

loaded via a namespace (and not attached):
  [1] estimability_1.3       SparseM_1.77           lavaan_0.6-3           coda_0.19-2            nonnest2_0.5-2        
  [6] acepack_1.4.1          dygraphs_1.1.1.6       multcomp_1.4-8         data.table_1.11.8      rpart_4.1-13          
 [11] inline_0.3.15          RCurl_1.95-4.11        generics_0.0.2         cowplot_0.9.3          lambda.r_1.2.3        
 [16] callr_3.1.1            TH.data_1.0-9          webshot_0.5.1          xml2_1.2.0             lubridate_1.7.4       
 [21] httpuv_1.4.5           StanHeaders_2.18.0-1   assertthat_0.2.0       d3Network_0.5.2.1      viridis_0.5.1         
 [26] xfun_0.4               hms_0.4.2              bayesplot_1.6.0        evaluate_0.12          promises_1.0.1        
 [31] readxl_1.1.0           igraph_1.2.2           htmlwidgets_1.3        futile.logger_1.4.3    mcmc_0.9-5            
 [36] reshape_0.8.8          stats4_3.5.2           crosstalk_1.0.0        backports_1.1.3        pbivnorm_0.6.0        
 [41] markdown_0.9           ggcorrplot_0.1.2       MCMCpack_1.4-4         rapportools_1.0        pwr_1.2-2             
 [46] quantreg_5.38          abind_1.4-5            withr_2.1.2            pryr_0.1.4             checkmate_1.8.5       
 [51] emmeans_1.3.1          sna_2.4                fdrtool_1.2.15         prettyunits_1.0.2      mnormt_1.5-5          
 [56] cluster_2.0.7-1        mi_1.0                 lazyeval_0.2.1         crayon_1.3.4           ellipse_0.4.1         
 [61] labeling_0.3           pkgconfig_2.0.2        nlme_3.1-137           ggm_2.3                nnet_7.3-12           
 [66] bindr_0.1.1            rlang_0.3.1            miniUI_0.1.1.1         colourpicker_1.0       MatrixModels_0.4-1    
 [71] sandwich_2.5-0         modelr_0.1.2           cellranger_1.1.0       matrixStats_0.54.0     Matrix_1.2-15         
 [76] loo_2.0.0              boot_1.3-20            base64enc_0.1-3        whisker_0.3-2          ggridges_0.5.1        
 [81] processx_3.2.1         png_0.1-7              viridisLite_0.3.0      rjson_0.2.20           bitops_1.0-6          
 [86] pander_0.6.3           arm_1.10-1             jpeg_0.1-8             shinystan_2.5.0        threejs_0.3.1         
 [91] compiler_3.5.2         rstantools_1.5.1       lme4_1.1-19            cli_1.0.1              lmerTest_3.0-1        
 [96] pbapply_1.3-4          ps_1.2.1               formatR_1.5            htmlTable_1.12         MASS_7.3-51.1         
[101] tidyselect_0.2.5       stringi_1.2.4          pixiedust_0.8.6        sem_3.1-9              highr_0.7             
[106] yaml_2.2.0             latticeExtra_0.6-28    grid_3.5.2             manipulate_1.0.1       tools_3.5.2           
[111] parallel_3.5.2         matrixcalc_1.0-3       rstudioapi_0.8         foreign_0.8-71         gridExtra_2.3         
[116] BDgraph_2.53           digest_0.6.18          shiny_1.2.0            quadprog_1.5-5         nortest_1.0-4         
[121] ppcor_1.1              Rcpp_1.0.0             BayesFactor_0.9.12-4.2 later_0.7.5            httr_1.4.0            
[126] rsconnect_0.8.13       colorspace_1.3-2       blavaan_0.3-4          rvest_0.3.2            splines_3.5.2         
[131] expm_0.999-3           sp_1.3-1               shinythemes_1.1.2      MuMIn_1.42.1           xtable_1.8-3          
[136] rstanarm_2.18.2        futile.options_1.0.1   jsonlite_1.6           nloptr_1.2.1           corpcor_1.6.9         
[141] rstan_2.18.2           glasso_1.10            nFactors_2.3.3         R6_2.3.0               pillar_1.3.1          
[146] htmltools_0.3.6        mime_0.6               glue_1.3.0             minqa_1.2.4            DT_0.5                
[151] codetools_0.2-15       pkgbuild_1.0.2         mvtnorm_1.0-8          network_1.13.0.1       numDeriv_2016.8-1     
[156] huge_1.2.7             curl_3.2               DescTools_0.99.27      gtools_3.8.1           zip_1.0.0             
[161] shinyjs_1.0            openxlsx_4.1.0         CompQuadForm_1.4.3     rmarkdown_1.11         qgraph_1.5            
[166] statnet.common_4.1.4   munsell_0.5.0          haven_2.1.0            reshape2_1.4.3         gtable_0.2.0          
 

A work by Claudiu Papasteri

claudiu.papasteri@gmail.com

 

LS0tDQp0aXRsZTogIjxicj4gUmV6aWRlbnRpYWwiIA0Kc3VidGl0bGU6ICJQcmVsaW1pbmFyeSBBbmFseXNpcyINCmF1dGhvcjogIjxicj4gQ2xhdWRpdSBQYXBhc3RlcmkiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlbSAlWScpYCINCm91dHB1dDogDQogICAgaHRtbF9ub3RlYm9vazoNCiAgICAgICAgICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgICAgICAgICAgdG9jOiB0cnVlDQogICAgICAgICAgICB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgICAgICAgICAgdGhlbWU6IHNwYWNlbGFiDQogICAgICAgICAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgICAgICAgICBmb250LWZhbWlseTogQXJpYWwNCiAgICAgICAgICAgIGZpZ193aWR0aDogMTANCiAgICAgICAgICAgIGZpZ19oZWlnaHQ6IDkNCiAgICBwZGZfZG9jdW1lbnQ6IA0KICAgICAgICAgICAgdG9jOiB0cnVlDQogICAgICAgICAgICB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgICAgICAgICAgIyBmb250c2l6ZTogMTFwdA0KICAgICAgICAgICAgIyBnZW9tZXRyeTogbWFyZ2luPTFpbg0KICAgICAgICAgICAgIyBmaWdfd2lkdGg6IDcNCiAgICAgICAgICAgICMgZmlnX2hlaWdodDogNg0KICAgICAgICAgICAgIyBmaWdfY2FwdGlvbjogdHJ1ZQ0KICAgICMgZ2l0aHViX2RvY3VtZW50OiANCiAgICAgICAgICAgICMgdG9jOiB0cnVlDQogICAgICAgICAgICAjIHRvY19kZXB0aDogMg0KICAgICAgICAgICAgIyBodG1sX3ByZXZpZXc6IGZhbHNlDQogICAgICAgICAgICAjIGZpZ193aWR0aDogNQ0KICAgICAgICAgICAgIyBmaWdfaGVpZ2h0OiA1DQogICAgICAgICAgICAjIGRldjoganBlZw0KLS0tDQoNCg0KPCEtLSBTZXR1cCAtLT4NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0KIyBraW50ciBvcHRpb25zDQprbml0cjo6b3B0c19jaHVuayRzZXQoDQogIGNvbW1lbnQgPSAiIyIsDQogIGNvbGxhcHNlID0gVFJVRSwNCiAgZWNobyA9IFRSVUUsIA0KICBjYWNoZSA9IFRSVUUsIA0KICB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSAgICMgV0hFTiBOT1RFQk9PSyBJUyBGSU5JU0hFRCAuLi4gdW50aWwgdGhlbiBsZWF2ZTogd2FybmluZyA9IFRSVUUsIG1lc3NhZ2UgPSBUUlVFICAgICAgICANCikNCg0KIyBHZW5lcmFsIFIgb3B0aW9ucyBhbmQgaW5mbw0Kc2V0LnNlZWQoMTExKSAgICAgICAgICAgICAgICMgaW4gY2FzZSB3ZSB1c2UgcmFuZG9taXplZCBwcm9jZWR1cmVzICAgICAgIA0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICAgICAgICMgcG9zaXRpdmUgdmFsdWVzIGJpYXMgdG93YXJkcyBmaXhlZCBhbmQgbmVnYXRpdmUgdG93YXJkcyBzY2llbnRpZmljIG5vdGF0aW9uDQoNCiMgTG9hZCBwYWNrYWdlcw0KaWYgKCFyZXF1aXJlKCJwYWNtYW4iKSkgaW5zdGFsbC5wYWNrYWdlcygicGFjbWFuIikNCnBhY2thZ2VzIDwtIGMoDQogICJrbml0ciIsICJrYWJsZUV4dHJhIiwgICMgZm9yIGZvcm1hdHRpbmcgbm90ZWJvb2sgDQogICJ0aWR5dmVyc2UiLCAgICAgICMgYmVzdCB0aGluZyB0aGF0IGhhcHBlbmQgdG8gbWUNCiAgInBzeWNoIiwgICAgICAgICAgIyBnZW5lcmFsIHB1cnBvc2UgdG9vbGJveCBmb3IgcGVyc29uYWxpdHksIHBzeWNob21ldHJpYyB0aGVvcnkgYW5kIGV4cGVyaW1lbnRhbCBwc3ljaG9sb2d5DQogICJwYXBhamEiLCAgICAgICAgICMgZm9yIEFQQSBzdHlsZQ0KICAiYnJvb20iLCAgICAgICAgICAjIGZvciB0aWR5IG1vZGVsbGluZw0KICAiZ2dwbG90MiIsICAgICAgICAjIGJlc3QgcGxvdHMNCiAgImdncHViciIsICAgICAgICAgICMgZ2dwbG90MiB0byBwdWJsaWNhdGlvbiBxdWFsaXR5DQogICJyaW8iLA0KICAiSG1pc2MiLCAicHN5Y2hvIiwgDQogICJHR2FsbHkiLCAiY29ycnBsb3QiLCAiUkNvbG9yQnJld2VyIiwgDQogICJzY2FsZXMiLCAgICAgICAgICAjIGZvciBwcmV0dHlfYnJlYWtzDQogICJjYXIiLCAic3VtbWFyeXRvb2xzIiwgInRhZGFhdG9vbGJveCIsICJQZXJmb3JtYW5jZUFuYWx5dGljcyIsDQogICJwbHlyIiwgICAgICAgICAgICAjIGZvciBkZHBseQ0KICAiZ2Vvc3BoZXJlIiAgICAgICAgIyBmb3IgY2VudHJvaWQNCiAgIyAsIC4uLg0KKQ0KaWYgKCFyZXF1aXJlKCJwYWNtYW4iKSkgaW5zdGFsbC5wYWNrYWdlcygicGFjbWFuIikNCnBhY21hbjo6cF9sb2FkKGNoYXIgPSBwYWNrYWdlcykNCg0KIyBUaGVtZXMgZm9yIGdncGxvdDIgcGxvdGluZyAoaGVyZSB1c2VkIEFQQSBzdHlsZSkNCnRoZW1lX3NldCh0aGVtZV9hcGEoKSkNCmBgYA0KDQpgYGB7ciB3b3JraW5nX2RpcmVjdG9yeSwgaW5jbHVkZSA9IEZBTFNFfQ0KIyBpZiBuZWVkZWQNCiMgd2QgPSAiLi9SZXppZGVudGlhbCINCiMgc2V0d2Qod2QpDQpgYGANCg0KDQo8IS0tIFJFUE9SVCAtLT4NCg0KDQojIExvYWQgZGF0YQ0KDQpgYGB7ciByYXdfZGF0YSwgcmVzdWx0cyA9ICdoaWRlJywgY2FjaGUuZXh0cmEgPSBmaWxlLmluZm8oImRpYW1vbmRzLmNzdiIpfQ0KIyBSZWFkDQpmaWxlbmFtZSA8LSAiYmF6YSBkZSBkYXRlIHJlemlkZW50aWFsLnhsc3giICAgDQoNCkRhdGEgPC0gcmlvOjppbXBvcnQoZmlsZW5hbWUpICANCkRhdGEgPC0gRGF0YVssIC1jKDE5NzoyMDIpXSAgICAjIGRlbGV0ZSBsYXN0IDYgY29sdW1ucyAoZW1wdHkgZXhjZWwgY29sdW1ucyBmb3IgZXhjZWwgZnVuY3Rpb25zKQ0KYGBgDQoNCg0KIyMgUHJvY2Vzc2luZyBkYXRhDQoNCmBgYHtyIHByb2Nlc3NlZF9kYXRhLCBjYWNoZSA9IFRSVUUsIGRlcGVuZHNvbiA9ICJyYXdfZGF0YSJ9DQojIENsZWFuDQpEYXRhJGp1ZGV0IDwtIGFzLmZhY3RvcihEYXRhJGp1ZGV0KQ0KRGF0YSRnZW4gPC0gYXMuZmFjdG9yKERhdGEkZ2VuKSAgDQpEYXRhJHRpcF9jaGVzdGlvbmFyIDwtIGFzLmZhY3RvcihEYXRhJHRpcF9jaGVzdGlvbmFyKSAjIHVuaXF1ZShEYXRhJHRpcF9jaGVzdGlvbmFyKSAjICI5LTE4YW5pIiwgIjUtOGFuaSIsICI1LThpbnRhcnppZXJlIg0KRGF0YSR2X21hbWFfbmFzdGVyZSA8LSBhcy5mYWN0b3IoRGF0YSR2X21hbWFfbmFzdGVyZSkNCmxldmVscyhEYXRhJHZfbWFtYV9uYXN0ZXJlKSA8LSBjKCI8MTkiLCAiMjAtMjUiLCAiMjaWMzQiLCAiMzU+IikNCmBgYA0KDQo8IS0tIEluc3BlY3QgRGF0YSAtIHN3aXRjaGVkIG9mZiAtLT4NCmBgYHtyIGluc3BlY3RkYXRhLCBlY2hvPUZBTFNFLCByZXN1bHRzPSJoaWRlIn0NCiMgcHJpbnQoc3VtbWFyeXRvb2xzOjpkZlN1bW1hcnkoRGF0YSwgc3R5bGUgPSAnZ3JpZCcsIHBsYWluLmFzY2lpID0gRkFMU0UsIGdyYXBoLm1hZ25pZiA9IDAuODUpLCAgICAjIHN1cHByZXNzIG91dHB1dA0KIyAgICAgICBtZXRob2QgPSAncmVuZGVyJywgaGVhZGluZ3MgPSBGQUxTRSkNCiMgc3RyKERhdGEsIGxpc3QubGVuPW5jb2woRGF0YSkpICAjIGRhdGEgdHlwZXMgYXJlIGZpbmUNCmBgYA0KDQoNCiMjIERhdGEgVmFsaWRhdGlvbg0KDQpgYGB7ciBkYXRhX3ZhbGlkYXRpb24sIGRlcGVuZHNvbiA9ICJwcm9jZXNzZWRfZGF0YSJ9DQpkYXRhX3ZhbGlkYXRpb24gPC0gZnVuY3Rpb24oeCwgbG9nX2xldmVsID0gZnV0aWxlLmxvZ2dlcjo6V0FSTiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nX2FwcGVuZGVyID0gImNvbnNvbGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dfaXNzdWVzID0gRkFMU0UpIHsNCiAgDQogIFJlemlkZW50aWFsX2NvbF9uYW1lcyA8LSBjKCJJRCIsICJqdWRldCIsICJvcmFzIiwgImNlbnRydSIsICJ0aXBfY2hlc3Rpb25hciIsICJudW1lIiwgImRhdGEiLCAidmFyc3RhIiwgInZhcnN0YV9pbnN0IiwgIm5yX2ZyYXRpIiwgIm5yX2ZyYXRpX2luc3QiLCAidl9tYW1hX25hc3RlcmUiLCAiZXhwdW5lcmVfdG94IiwgImJvbGkiLCAiVENDIiwgImFzZml4aWUiLCAiYWJ1el9zdWIiLCAiZ3JhZF9oIiwgImludGFyemllcmUiLCAidHJhc19kZXoiLCAidHVsYl9jb25kIiwgIm5lZ2xpamFyZSIsICJ0ZW1wZXJhbSIsICJyZXBldGVudGEiLCAic2NvYWxhX3NwZWMiLCAiaW5hYmlsX3NjIiwgInNjaGltYl9kb20iLCAicGllcmRfbG9jIiwgImNvbXVuaXQiLCAiZ2VuIiwgImN1X2NpbmVfbG9jIiwgImZhbWlsaWUiLCAiY3lybV8xIiwgImN5cm1fMiIsICJjeXJtXzMiLCAiY3lybV80IiwgImN5cm1fNSIsICJjeXJtXzYiLCAiY3lybV83IiwgImN5cm1fOCIsICJjeXJtXzkiLCAiY3lybV8xMCIsICJjeXJtXzExIiwgImN5cm1fMTIiLCAiY3lybV8xMyIsICJjeXJtXzE0IiwgImN5cm1fMTUiLCAiY3lybV8xNiIsICJjeXJtXzE3IiwgImN5cm1fMTgiLCAiY3lybV8xOSIsICJjeXJtXzIwIiwgImN5cm1fMjEiLCAiY3lybV8yMiIsICJjeXJtXzIzIiwgImN5cm1fMjQiLCAiY3lybV8yNSIsICJjeXJtXzI2IiwgImN5cm1fMjciLCAiY3lybV8yOCIsICJjZXNkXzEiLCAiY2VzZF8yIiwgImNlc2RfMyIsICJjZXNkXzQiLCAiY2VzZF81IiwgImNlc2RfNiIsICJjZXNkXzciLCAiY2VzZF84IiwgImNlc2RfOSIsICJjZXNkXzEwIiwgImNlc2RfMTEiLCAiY2VzZF8xMiIsICJjZXNkXzEzIiwgImNlc2RfMTQiLCAiY2VzZF8xNSIsICJjZXNkXzE2IiwgImNlc2RfMTciLCAiY2VzZF8xOCIsICJjZXNkXzE5IiwgImNlc2RfMjAiLCAiZ2NpXzEiLCAiZ2NpXzIiLCAiZ2NpXzMiLCAiZ2NpXzQiLCAiZ2NpXzUiLCAiZ2NpXzYiLCAiZ2NpXzciLCAiZ2NpXzgiLCAiZ2NpXzkiLCAiZ2NpXzEwIiwgImdjaV8xMSIsICJnY2lfMTIiLCAiZ2NpXzEzIiwgImdjaV8xNCIsICJzZHFfMSIsICJzZHFfMiIsICJzZHFfMyIsICJzZHFfNCIsICJzZHFfNSIsICJzZHFfNiIsICJzZHFfNyIsICJzZHFfOCIsICJzZHFfOSIsICJzZHFfMTAiLCAic2RxXzExIiwgInNkcV8xMiIsICJzZHFfMTMiLCAic2RxXzE0IiwgInNkcV8xNSIsICJzZHFfMTYiLCAic2RxXzE3IiwgInNkcV8xOCIsICJzZHFfMTkiLCAic2RxXzIwIiwgInNkcV8yMSIsICJzZHFfMjIiLCAic2RxXzIzIiwgInNkcV8yNCIsICJzZHFfMjUiLCAic2Nhcl8xIiwgInNjYXJfMiIsICJzY2FyXzMiLCAic2Nhcl80IiwgInNjYXJfNSIsICJzY2FyXzYiLCAic2Nhcl83IiwgInNjYXJfOCIsICJzY2FyXzkiLCAic2Nhcl8xMCIsICJzY2FyXzExIiwgInNjYXJfMTIiLCAic2Nhcl8xMyIsICJzY2FyXzE0IiwgInNjYXJfMTUiLCAic2Nhcl8xNiIsICJzY2FyXzE3IiwgInNjYXJfMTgiLCAic2Nhcl8xOSIsICJzY2FyXzIwIiwgInNjYXJfMjEiLCAic2Nhcl8yMiIsICJzY2FyXzIzIiwgInNjYXJfMjQiLCAic2Nhcl8yNSIsICJzY2FyXzI2IiwgInNjYXJfMjciLCAic2Nhcl8yOCIsICJzY2FyXzI5IiwgInNjYXJfMzAiLCAic2Nhcl8zMSIsICJzY2FyXzMyIiwgInNjYXJfMzMiLCAic2Nhcl8zNCIsICJzY2FyXzM1IiwgInNjYXJfMzYiLCAic2Nhcl8zNyIsICJzY2FyXzM4IiwgInNjYXJfMzkiLCAic2Nhcl80MCIsICJzY2FyXzQxIiwgImFzY18xIiwgImFzY18yIiwgImFzY18zIiwgImFzY180IiwgImFzY181IiwgImFzY182IiwgImFzY183IiwgImFzY184IiwgImFzY185IiwgImFzY18xMCIsICJhc2NfMTEiLCAiYXNjXzEyIiwgImFzY18xMyIsICJhc2NfMTQiLCAiYXNjXzE1IiwgImN5d19ucjEiLCAiY3l3X25yMiIsICJzZWMxXzEiLCAic2VjMV8yIiwgInNlYzFfMyIsICJzZWMxXzQiLCAic2VjMV81IiwgInNlYzFfNiIsICJzZWMxXzciLCAic2VjMV84IiwgInNlYzFfOSIsICJzZWMxXzEwIiwgDQoic2VjMl8xIiwgInNlYzJfMiIsICJzZWMyXzMiLCAic2VjMl80IiwgInNlYzJfNSIsICJzZWMyXzYiLCAic2VjMl83IiwgInNlYzJfOCIsICJzZWMyXzkiKQ0KICANCiAgIyBTZXQgbG9nZ2VyIHNldmVyaXR5IHRocmVzaG9sZCwgZGVmYXVsdHMgdG8NCiAgIyBoaWdoIGxldmVsIHVzZSAob25seSBmbGFncyB3YXJuaW5ncyBhbmQgZXJyb3JzKQ0KICAjIFNldCBsb2dfbGV2ZWwgYXJndW1lbnQgdG8gZnV0aWxlLmxvZ2dlcjo6VFJBQ0UgZm9yIGZ1bGwgaW5mbw0KICBmdXRpbGUubG9nZ2VyOjpmbG9nLnRocmVzaG9sZChsb2dfbGV2ZWwpDQogIA0KICAjIFNldCB3aGVyZSB0byB3cml0ZSB0aGUgbG9nIHRvDQogIGlmIChsb2dfYXBwZW5kZXIgIT0gImNvbnNvbGUiKQ0KICB7DQogICAgIyBpZiBub3QgY29uc29sZSB0aGVuIHRvIGEgZmlsZSBjYWxsZWQuLi4NCiAgICBmdXRpbGUubG9nZ2VyOjpmbG9nLmFwcGVuZGVyKGZ1dGlsZS5sb2dnZXI6OmFwcGVuZGVyLmZpbGUobG9nX2FwcGVuZGVyKSkNCiAgfQ0KICANCiAgIyBDaGVja3MNCiAgZnV0aWxlLmxvZ2dlcjo6ZmxvZy5pbmZvKCdJbml0aWF0aW5nIFJlemlkZW50aWFsIGNsYXNzLg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5cbkV4cGVjdHMgYSBkYXRhLmZyYW1lIHdpdGggYWxsIFJlemlkZW50aWFsIGNvbHVtbnMnKQ0KICANCiAgIyBJbnRlZ3JpdHkgY2hlY2tzIG9uIGluY29taW5nIGRhdGEgLS0tLQ0KICANCiAgIyBDaGVjayB0aGUgc3RydWN0dXJlIG9mIHRoZSBkYXRhIGlzIGFzIGV4cGVjdGVkOiBkYXRhLmZyYW1lIGNvbnRhaW5pbmcgbm8NCiAgIyBtaXNzaW5nIHZhbHVlcyBhbmQgdGhyZWUgY29sdW1ucywgY29udGFpbmluZyBzZWN0b3IsIHllYXIsIGFuZCBvbmUNCiAgIyBhZGRpdGlvbmFsIGNvbHVtbi4NCiAgDQogIGZ1dGlsZS5sb2dnZXI6OmZsb2cuaW5mbygnXG4qKiogUnVubmluZyBpbnRlZ3JpdHkgY2hlY2tzIG9uIGlucHV0IGRhdGFmcmFtZSAoeCk6JykNCiAgZnV0aWxlLmxvZ2dlcjo6ZmxvZy5kZWJ1ZygnXG5DaGVja2luZyBpbnB1dCBpcyBwcm9wZXJseSBmb3JtYXR0ZWQuLi4nKQ0KICANCiAgZnV0aWxlLmxvZ2dlcjo6ZmxvZy5kZWJ1ZygnQ2hlY2tpbmcgeCBpcyBhIGRhdGEuZnJhbWUuLi4nKQ0KICBpZiAoIWlzLmRhdGEuZnJhbWUoeCkpDQogIHsNCiAgICBmdXRpbGUubG9nZ2VyOjpmbG9nLmVycm9yKCJ4IG11c3QgYmUgYSBkYXRhLmZyYW1lIiwgICAgICMgeCwgY2FwdHVyZSA9IFRSVUUpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0dXJlID0gRkFMU0UpDQogIH0NCiAgDQogIGZ1dGlsZS5sb2dnZXI6OmZsb2cuZGVidWcoJ0NoZWNraW5nIHggaGFzIGNvcnJlY3QgbnVtYmVyIG9mIGNvbHVtbnMuLi4nKQ0KICBpZiAobGVuZ3RoKGNvbG5hbWVzKHgpKSAhPSAxOTYpDQogIHsNCiAgICBmdXRpbGUubG9nZ2VyOjpmbG9nLmVycm9yKCJ4IG11c3QgaGF2ZSAxOTYgY29sdW1ucyIpDQogIH0NCiAgDQogIGZ1dGlsZS5sb2dnZXI6OmZsb2cuZGVidWcoJ0NoZWNraW5nIHggY29udGFpbnMgYWxsIFJlemlkZW50aWFsIGNvbHVtbnMuLi4nKQ0KICBpZiAoIWFsbChSZXppZGVudGlhbF9jb2xfbmFtZXMgJWluJSBjb2xuYW1lcyhEYXRhKSkpIHN0b3AoInggbXVzdCBjb250YWluIGFsbCBSZXppZGVudGlhbCBjb2x1bW5zIikNCiAgDQogIGZ1dGlsZS5sb2dnZXI6OmZsb2cuZGVidWcoJ0NoZWNraW5nIHggaGFzIGdlbiBjb2x1bW4gd2l0aCAyIGZhY3RvciBsZXZlbHM6IGYsIG0uLi4nKQ0KICBpZiAoIWlzLmZhY3Rvcih4JGdlbikgfCAhYWxsKGxldmVscyh4JGdlbikgJWluJSBjKCJmIiwgIm0iKSkpDQogIHsNCiAgICBmdXRpbGUubG9nZ2VyOjpmbG9nLmVycm9yKCJ4IG11c3QgaGF2ZSBnZW4gZmFjdG9yIHdpdGggMiBmYWN0b3IgbGV2ZWxzIikNCiAgfQ0KICANCiAgZnV0aWxlLmxvZ2dlcjo6ZmxvZy5kZWJ1ZygnQ2hlY2tpbmcgeCBoYXMgdGlwX2NoZXN0aW9uYXIgY29sdW1uIHdpdGggMyBmYWN0b3IgbGV2ZWxzOiA5LTE4YW5pLCA1LThhbmksIDUtOGludGFyemllcmUuLi4nKQ0KICBpZiAoIWlzLmZhY3Rvcih4JHRpcF9jaGVzdGlvbmFyKSB8ICFhbGwobGV2ZWxzKHgkdGlwX2NoZXN0aW9uYXIpICVpbiUgYygiOS0xOGFuaSIsICI1LThhbmkiLCAiNS04aW50YXJ6aWVyZSIpKSkNCiAgew0KICAgIGZ1dGlsZS5sb2dnZXI6OmZsb2cuZXJyb3IoInggbXVzdCBoYXZlIGdlbiBmYWN0b3Igd2l0aCAzIGZhY3RvciBsZXZlbHMiKQ0KICB9DQogIA0KIA0KICBmdXRpbGUubG9nZ2VyOjpmbG9nLmluZm8oJy4uLnBhc3NlZCcpDQoNCiAgDQogIA0KICBmdXRpbGUubG9nZ2VyOjpmbG9nLmluZm8oIlxuKioqUnVubmluZyBzdGF0aXN0aWNhbCBjaGVja3Mgb24gaW5wdXQgZGF0YWZyYW1lICh4KSIpDQogIA0KICANCiAgDQogIGZ1dGlsZS5sb2dnZXI6OmZsb2cuZGVidWcoJ0NoZWNraW5nIHRoYXQgQ1lSTS0yNiBoYXMgb25seSBOQSBpbiBpdGVtcyAyNyAmIDI4IGZvciA1LTggeWVhciBvbGRzIC4uLicpDQogIGlmKCFhbGwoaXMubmEoeFt4JHRpcF9jaGVzdGlvbmFyICVpbiUgYygiNS04YW5pIiwgIjUtOGludGFyemllcmUiKSwgXSRjeXJtXzI3KSkgfA0KICAgICAhYWxsKGlzLm5hKHhbeCR0aXBfY2hlc3Rpb25hciAlaW4lIGMoIjUtOGFuaSIsICI1LThpbnRhcnppZXJlIiksIF0kY3lybV8yOCkpKSANCiAgew0KICAgIHN0b3AoInggaGFzIENZUk0tMjYgd2l0aCBub24tTkEgaW4gaXRlbXMgMjcgJiAyOCBmb3IgNS04IHllYXIgb2xkcyIpDQogIH0NCiAgDQogICMjIyBpdGVtIDcgZm9yIDUtOCBpcyBpdGVtIDggaW4gOS0xOCwgaXRlbSA3ICYgOSBmcm9tIDktMTggZG9udCBleGlzdCBmb3IgNS04DQogIGZ1dGlsZS5sb2dnZXI6OmZsb2cuZGVidWcoJ0NoZWNraW5nIHRoYXQgQ1lXIEFDRS1RIFNlY3QyIGhhcyBvbmx5IE5BIGluIGl0ZW1zIDggJiA5IGZvciA1LTggeWVhciBvbGRzIC4uLicpDQogIGlmKCFhbGwoaXMubmEoeFt4JHRpcF9jaGVzdGlvbmFyICVpbiUgYygiNS04YW5pIiwgIjUtOGludGFyemllcmUiKSwgXSRzZWMyXzgpKSB8DQogICAgICFhbGwoaXMubmEoeFt4JHRpcF9jaGVzdGlvbmFyICVpbiUgYygiNS04YW5pIiwgIjUtOGludGFyemllcmUiKSwgXSRzZWMyXzkpKSkgDQogIHsNCiAgICBzdG9wKCJ4IGhhcyBDWVcgQUNFLVEgU2VjdDIgd2l0aCBub24tTkEgaW4gaXRlbXMgNyAmIDkgZm9yIDUtOCB5ZWFyIG9sZHMiKQ0KICB9ICANCiAgDQogIA0KDQp9DQoNCiMjIFJ1biBEYXRhIFZhbGlkYXRpb24NCiMgZHB1dChuYW1lcyhEYXRhKSwgZmlsZSA9ICJkcHV0X2NvbG5hbWVzLnR4dCIpICAgICAgICMgQ2hlY2tzIGFsbCBjb2x1bW4gbmFtZXMNCmRhdGFfdmFsaWRhdGlvbihEYXRhLCBsb2dfbGV2ZWwgPSBmdXRpbGUubG9nZ2VyOjpERUJVRykNCg0KYGBgDQoNCiMjIFNhbXBsZSBNYXANCg0KYGBge3IgbWFwX2RhdGF9DQojIyBHZXQgbWFwDQojIGh0dHBzOi8vZ2FkbS5vcmcvZG93bmxvYWRfY291bnRyeS5odG1sDQojIGxpYnJhcnkocmFzdGVyKSAjIGZvciBnZXREYXRhKCkgZG93bmxvYWQgbWFwIGF1dG9tYXRpY2FsbHkgc28gd2UgZG9udCBoYXZlIHRvIGRvd25sb2FkIGl0IGJ5IGhhbmQNCiMgZ2FkbVJPIDwtIGdldERhdGEoJ0dBRE0nLCBjb3VudHJ5PSdSTycsIGxldmVsPTEpDQpnYWRtUk8gPC0gcmVhZFJEUygiUk9VX2FkbTEucmRzIikgICMgbG9hZCBkb3dubG9hZGVkIG1hcCANCg0KIyMgQ291bnQganVkZXQgZnJvbSBSZXppZGVudGlhbA0KY291bnRfZGYgPC0gDQogIERhdGEgJT4lDQogICAgZHBseXI6OmNvdW50KGp1ZGV0KSAlPiUgDQogICAgZHBseXI6OnJlbmFtZShOQU1FXzEgPSBqdWRldCwgY291bnQgPSBuKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKE5BTUVfMSA9IGFzLmNoYXJhY3RlcihOQU1FXzEpKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKE5BTUVfMSA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlKE5BTUVfMSwgIkJ1Y3VyZXN0aSIsICJJbGZvdiIpKSAgICAjIHJlcGxhY2UgQnVjdXJlc3RpIHdpdGggSWxmb3YNCg0KICAgIA0KIyMgQXJhbmdlIGRhdGFzZXQgZm9yIG1hcA0KZ2FkbVJPQGRhdGEkTkFNRV8xIDwtIGljb252KGdhZG1ST0BkYXRhJE5BTUVfMSwgZnJvbT0iVVRGLTgiLCB0bz0iQVNDSUkvL1RSQU5TTElUIikgICAjIGVuY29kaW5nIGFuZCBkaWFjcml0aWNzIHByb2JsZW1zDQpnYWRtUk9AZGF0YSROQU1FXzEgPC0gYygiQWxiYSIsICJBcmFkIiwgIkFyZ2VzIiwiQmFjYXUiLCJCaWhvciIsIkJpc3RyaXRhLU5hc2F1ZCIsICJCb3Rvc2FuaSIsICJCcmFzb3YiLCAiQnJhaWxhIiwgIkJ1Y2hhcmVzdCIsICJCdXphdSIsIkNhbGFyYXNpIiwgIkNhcmFzLVNldmVyaW4iLCAgICJDbHVqIiwgIkNvbnN0YW50YSIsICJDb3Zhc25hIiwgIkRhbWJvdml0YSIsICJEb2xqIiwgIkdhbGF0aSIsICJHaXVyZ2l1IiwgIkdvcmoiLCAiSGFyZ2hpdGEiLCAgIkh1bmVkb2FyYSIsICJJYXNpIiwgIklhbG9taXRhIiwgICJJbGZvdiIsICJNYXJhbXVyZXMiLCAiTWVoZWRpbnRpIiwgIk11cmVzIiwgIk5lYW10IiwgIk9sdCIsICJQcmFob3ZhIiwiU2FsYWoiLCJTYXR1IE1hcmUiLCAiU2liaXUiLCAiU3VjZWF2YSIsICJUZWxlb3JtYW4iLCAiVGltaXMiLCJUdWxjZWEiLCAiVmFsY2VhIiwgIlZhc2x1aSIsICJWcmFuY2VhIikNCg0KZ2FkbVJPQGRhdGEkaWQgPC0gcm93bmFtZXMoZ2FkbVJPQGRhdGEpDQpnYWRtUk9AZGF0YSR0b3RhbF9zZW50IDwtIGMoMzAsIDI1LCAxMDEsIDY1LCAzMCwgMjAsIDAsIDMwLCAxMCwgMCwgMzAsIDIwLCAzNSwgMCwgNTUsIDAsIDIwLCAwLCA0NSwgMjUsIDUwLCAyMCwgMjAsIDMwMCwgMCwgMTI1LCAyMCwgMTAsIDAsIDIwLCAxMjAsIDgwLCA4MCwgMjAsIDMwLCAxNTAsIDAsIDMwLCAxMSwgMCwgMjAsIDE2KQ0KDQpnYWRtUk9AZGF0YSA8LSBsZWZ0X2pvaW4oZ2FkbVJPQGRhdGEsIGNvdW50X2RmLCBieSA9ICJOQU1FXzEiKQ0KDQpnYWRtUk9AZGF0YSA8LSANCiAgIGdhZG1ST0BkYXRhICU+JQ0KICAgICAgbXV0YXRlKGNhdGVnb3J5ID0gaWZfZWxzZShpcy5uYShjb3VudCksIE5BX2ludGVnZXJfLCBjb3VudCkpICU+JSAgICAgICAjIGRvbnQgZXhjcGx1ZGUgTkEsIGFuZCB1c2UgbmEudmFsdWUgaW4gZ2dwbG90DQogICAgICBtdXRhdGUoY2F0ZWdvcnkgPSBjdXQoY2F0ZWdvcnksIGJyZWFrcz1jKC1JbmYsIDAsIDIwLCA1MCwgMTAwLCAzMDApLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHM9YygiMCIsICIxLTIwIiwgIjIwLTUwIiwgIjUwLTEwMCIsICIxMDAtMzAwIikpKSANCiAgICAgIA0KDQpST19kZiA8LSBmb3J0aWZ5KGdhZG1STykNClJPX2RmIDwtIGxlZnRfam9pbihST19kZiwgZ2FkbVJPQGRhdGEsIGJ5ID0gImlkIikNCg0KanVkZXRlIDwtIA0KICBST19kZiAlPiUNCiAgcGx5cjo6ZGRwbHkoLihpZCwgSEFTQ18xKSwgc3VtbWFyaXplLCANCiAgICAgICAgICAgICAgICAgICAgICBjZW50cnVsb25nID0gY2VudHJvaWQoY2JpbmQobG9uZywgbGF0KSlbMV0sIA0KICAgICAgICAgICAgICAgICAgICAgIGNlbnRydWxhdCA9IGNlbnRyb2lkKGNiaW5kKGxvbmcsIGxhdCkpWzJdKQ0KIyBjZW50cm9pZCgpWzFdIGlzIGxvbmdpdHVkaW5lICAgLS0gICAgY2VudHJvaWQgY2VudHJvaWQoKVsyXSBpcyBsYXRpdHVkaW5lDQpqdWRldGUgPC0gc3Vic2V0KGp1ZGV0ZSwgSEFTQ18xIT0iUk8uQkkiKSAgICMgZHJvcCBCdWN1cmVzdGkgYmFjYXVzZSB3ZSBoYXZlIElGIGFzIGNvdW50eQ0KDQojIyBPdXRwdXQgdGFibGUgLSB1bnJlbGF0ZWQgdG8gbWFwIGRhdGENCmdhZG1ST0BkYXRhICAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KE5BTUVfMSwgdG90YWxfc2VudCwgY291bnQpICU+JSANCiAgICBkcGx5cjo6ZmlsdGVyKE5BTUVfMSAhPSAiQnVjaGFyZXN0IikgJT4lDQogICAgZHBseXI6Om11dGF0ZShOQU1FXzEgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZShOQU1FXzEsICJJbGZvdiIsICJJbGZvdiAvIEJ1Y3VyZXN0aSIpKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKGNvdW50ID0gcmVwbGFjZV9uYShjb3VudCwgMCkpICU+JSANCiAgICBkbyhiaW5kX3Jvd3MoLiwgZGF0YS5mcmFtZShOQU1FXzEgPSAiVG90YWwiLCB0b3RhbF9zZW50ID0gc3VtKC4kdG90YWxfc2VudCksIGNvdW50ID0gc3VtKC4kY291bnQpKSkpICU+JQ0KICAgIGRwbHlyOjptdXRhdGUocGVyY19yZXR1cm4gPSByb3VuZChjb3VudC90b3RhbF9zZW50KjEwMCwgMikpICU+JQ0KICAgIGRwbHlyOjptdXRhdGUocGVyY19yZXR1cm4gPSByZXBsYWNlX25hKHBlcmNfcmV0dXJuLCAiLSIpKSAlPiUNCiAgDQogICAga25pdHI6OmthYmxlKGNhcHRpb24gPSAiU2FtcGxlIEluZm9ybWF0aW9uIiwNCiAgICAgICAgICAgICAgICAgY29sLm5hbWVzID0gYygiQ291bnR5IiwgIk5vLiBTZW50IiwgIk5vLiBSZXR1cm5lZCIsICIlIFJldHVybmVkIikpICU+JSANCiAgICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gInN0cmlwZWQiLCBmdWxsX3dpZHRoID0gRkFMU0UsIHBvc2l0aW9uID0gImNlbnRlciIpICU+JQ0KICAgIGthYmxlRXh0cmE6OnJvd19zcGVjKHJvdyA9IDQyLCBib2xkID0gVFJVRSkNCg0KICANCmBgYA0KDQpgYGB7ciBtYXBfcGxvdCwgZmlnLndpZHRoID0gMTAsIGZpZy5hc3AgPSAwLjh9DQojIyBTZXQgZ2dwbG90MiB0aGVtZSBmb3IgbWFwDQp0aGVtZV9vcHRzPC1saXN0KHRoZW1lKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICAgICAgICAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSkNCg0KIyMgUGxvdCBjb250aW51b3VzIGNvdW50IC0tIGRpc2FibGVkIGhlcmUgDQojIGdncGxvdCgpICsgDQojICAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBST19kZiwgYWVzKGxvbmcsIGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IGNvdW50ICkpICsNCiMgICBnZW9tX3BhdGgoZGF0YSA9IFJPX2RmLCBhZXMobG9uZywgbGF0LCBncm91cCA9IGdyb3VwKSwgY29sb3IgPSAiZ3JleSIsIHNpemUgPSAwLjEpICsNCiMgICBzY2FsZV9maWxsX2Rpc3RpbGxlcihuYW1lID0gIkNoZXN0aW9uYXJlIiwgcGFsZXR0ZSA9ICJHcmVlbnMiLCB0cmFucyA9ICJyZXZlcnNlIiwgDQojICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2NhbGVzOjpwcmV0dHlfYnJlYWtzKG4gPSA1KSwgbmEudmFsdWUgPSAibGlnaHR5ZWxsb3ciICkgKyAgDQojICAgbGFicyh0aXRsZT0iTmljZSBNYXAiKSArDQojICAgZ2VvbV90ZXh0KGRhdGEgPSBqdWRldGUsIA0KIyAgICAgICAgICAgICBhZXMoeCA9IGNlbnRydWxvbmcsIHkgPSBjZW50cnVsYXQsIGxhYmVsID0gZ3N1YigiXi4qXFwuIiwiIiwgSEFTQ18xKSwgDQojICAgICAgICAgICAgIHNpemUgPSAwLjIpLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArICAjIGV4dHJhY3QgQUIgZnJvbSBSTy5BQg0KIyAgIHRoZW1lX29wdHMNCg0KIyMgUGxvdCBjYXRlZ29yaWVzIG9mIGNvdW50cw0KZ2dwbG90KCkgKyANCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBST19kZiwgYWVzKGxvbmcsIGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IGNhdGVnb3J5ICkpICsNCiAgZ2VvbV9wYXRoKGRhdGEgPSBST19kZiwgYWVzKGxvbmcsIGxhdCwgZ3JvdXAgPSBncm91cCksIGNvbG9yID0gImdyZXkiLCBzaXplID0gMC4xKSArDQogIHNjYWxlX2ZpbGxfYnJld2VyKG5hbWUgPSAiQ2hlc3Rpb25hcmUiLCB0eXBlID0gJ2RpdicsIHBhbGV0dGUgPSAnR3JlZW5zJywgZGlyZWN0aW9uID0gMSwgbmEudmFsdWUgPSAibGlnaHR5ZWxsb3ciKSArDQogIGxhYnModGl0bGU9Ik5pY2UgTWFwIikgKw0KICBnZW9tX3RleHQoZGF0YSA9IGp1ZGV0ZSwgDQogICAgICAgICAgICBhZXMoeCA9IGNlbnRydWxvbmcsIHkgPSBjZW50cnVsYXQsIGxhYmVsPWdzdWIoIl4uKlxcLiIsIiIsIEhBU0NfMSksIA0KICAgICAgICAgICAgc2l6ZSA9IDAuMiksIHNob3cubGVnZW5kID0gRkFMU0UpICsgICMgZXh0cmFjdCBBQiBmcm9tIFJPLkFCDQogIHRoZW1lX29wdHMNCg0KYGBgDQoNCg0KIyMgVHJhbnNmb3JtICYgQ29tcHV0ZSBuZXcgdmFyaWFibGVzDQoNCmBgYHtyIGRlcml2ZWRfZGF0YSwgY2FjaGUgPSBUUlVFLCBkZXBlbmRzb24gPSAicHJvY2Vzc2VkX2RhdGEifQ0KIyMgQ2hlY2sgU2NhbGUgSXRlbXMgTmFtZXMNCiMgRGF0YVssIDEzOjI5XSAgIyBpdGVtaSBwcmVkaWN0b3JpIEFDRQ0KIyBEYXRhWywgMzM6NThdICAjIENZUk0tMjYgZG9hciBwdCA1LTggYW5pDQojIERhdGFbLCAzMzo2MF0gICMgQ1lSTS0yOCBkb2FyIHB0IDktMTggYW5pDQojIERhdGFbLCA2MTo4MF0gICMgQ0VTREMNCiMgRGF0YVssIDgxOjk0XSAgIyBHQ0kNCiMgRGF0YVssIDk1OjExOV0gICMgU0RRDQojIERhdGFbLCAxMjA6MTYwXSAgIyBTY2FyZWQNCiMgRGF0YVssIDE2MToxNzVdICAjIEFTQ1ENCiMgRGF0YVssIDE3ODoxODddICAjIENZVyBBQ0UtUSBTZWN0MSAgLS0gc3VtIHNob3VsZCBiZSBlcXVhbCB0byAiY3l3X25yMSINCiMgRGF0YVssIDE4ODoxOTZdICAjIENZVyBBQ0UtUSBTZWN0MiAtLSBzdW0gc2hvdWxkIGJlIGVxdWFsIHRvICJjeXdfbnIyIiAtLSA3IGl0ZW1zIGZvciA1LTggKGV4Y2x1ZHMgc2VjMl83ICYgc2VjMl85KSwgOSBpdGVtcyBmb3IgOS0xOA0KDQojIyBUcmFuc2Zvcm0gDQogICMgQ1lXIEFDRS1RIFNlY3QyIC0tIDUtOCB5ZWFycyBoYXMgb25seSBOQSBpbiA4LCA5IGFuZCA3IGNvcnJlc3BvbmRzIHRvIGl0ZW0gOCBpbiA5LTE4IHllYXJzDQogICMgaXRlbSA3IHdpbGwgYmUgInJhdXRhdGUiIGZvciBhbGwgbGV2ZWxzDQogICMgaXRlbSA4ICJwb2xpdGllIiBvbmx5IDktMTggeWVhcnMNCkRhdGEgPC0gDQogIERhdGEgJT4lIA0KICBkcGx5cjo6bXV0YXRlKHJhdXRhdGUgPSBpZl9lbHNlKHRpcF9jaGVzdGlvbmFyICVpbiUgYygiNS04YW5pIiwgIjUtOGludGFyemllcmUiKSwgc2VjMl83LCBzZWMyXzgpKSAlPiUNCiAgZHBseXI6Om11dGF0ZShwb2xpdGllID0gaWZfZWxzZSh0aXBfY2hlc3Rpb25hciA9PSAiOS0xOGFuaSIsIHNlYzJfNywgYXMubnVtZXJpYyhOQSkpKSAgJT4lICAgICAgICAgICAgICAgICAgDQogIGRwbHlyOjptdXRhdGUoc2VjMl83ID0gcmF1dGF0ZSkgJT4lDQogIGRwbHlyOjptdXRhdGUoc2VjMl84ID0gcG9saXRpZSkgJT4lDQogIGRwbHlyOjpzZWxlY3QoLWMocmF1dGF0ZSwgcG9saXRpZSkpDQoNCg0KIyMgRGVmaW5lIGZ1bmN0aW9uIHRoYXQgY2FsY3VsYXRlcyBSb3dTdW1zIGJ1dCBvbmx5IGZvciByb3dzIHdpdGggbGVzcyB0aGFuIDEwJSBOQXM7IGFuZCByZXR1cm4gTkEgaWYgYWxsIHJvdyB2YWx1ZXMgYXJlIE5BIA0KU3BlY2lhbFJvd1N1bXMgPC0gZnVuY3Rpb24oZGYsIG5hcGVyY2VudCA9IC4xKSB7DQogIGlmZWxzZShyb3dTdW1zKGlzLm5hKGRmKSkgPiBuY29sKGRmKSAqIG5hcGVyY2VudCwNCiAgICBOQSwNCiAgICByb3dTdW1zKGRmLCBuYS5ybSA9IFRSVUUpICogTkEgXiAocm93U3VtcyghaXMubmEoZGYpKSA9PSAwKQ0KICApDQp9DQoNCiMjIENvbXB1dGUgbmV3IHZhcmlhYmxlcyANCg0KIyBTY2FyZWQgLS0gcmVjb2RlIDEsMiwzIGluIDAsMSwyDQogICMgVG90YWwgc2NvcmUgKyBjdXRvZmYgPj0gMjUNCiAgIyBBIHNjb3JlIG9mIDcgZm9yIGl0ZW1zIDEsIDYsIDksIDEyLCAxNSwgMTgsIDE5LCAyMiwgMjQsIDI3LCAzMCwgMzQsIDM4IG1heSBpbmRpY2F0ZSBQYW5pYyBEaXNvcmRlcg0KICAjIEEgc2NvcmUgb2YgOSBmb3IgaXRlbXMgNSwgNywgMTQsIDIxLCAyMywgMjgsIDMzLCAzNSwgMzcgbWF5IGluZGljYXRlIEdlbmVyYWxpemVkIEFueGlldHkgRGlzb3JkZXINCiAgIyBBIHNjb3JlIG9mIDUgZm9yIGl0ZW1zIDQsIDgsIDEzLCAxNiwgMjAsIDI1LCAyOSwgMzEgbWF5IGluZGljYXRlIFNlcGFyYXRpb24gQW54aWV0eQ0KICAjIEEgc2NvcmUgb2YgOCBmb3IgaXRlbXMgMywgMTAsIDI2LCAzMiwgMzksIDQwLCA0MSBtYXkgaW5kaWNhdGUgU29jaWFsIEFueGlldHkgRGlzb3JkZXINCiAgIyBBIHNjb3JlIG9mIDMgZm9yIGl0ZW1zIDIsIDExLCAxNywgMzYgbWF5IGluZGljYXRlIHNpZ25pZmljYW50IHNjaG9vbCBhdm9pZGFuY2UNCg0KRGF0YVssIHNwcmludGYoInNjYXJfJWQiLCAxOjQxKV0gPC0gRGF0YVssIHNwcmludGYoInNjYXJfJWQiLCAxOjQxKV0gLSAxICAgICAjIHJlY29kZSBTQ0FSRUQNCg0KRGF0YSRQRCA8LSBTcGVjaWFsUm93U3VtcyhEYXRhWywgc3ByaW50Zigic2Nhcl8lZCIsIGMoMSwgNiwgOSwgMTIsIDE1LCAxOCwgMTksIDIyLCAyNCwgMjcsIDMwLCAzNCwgMzgpKV0pDQpEYXRhJEdBRCA8LSBTcGVjaWFsUm93U3VtcyhEYXRhWywgc3ByaW50Zigic2Nhcl8lZCIsIGMoNSwgNywgMTQsIDIxLCAyMywgMjgsIDMzLCAzNSwgMzcpKV0pDQpEYXRhJFNlcEEgPC0gU3BlY2lhbFJvd1N1bXMoRGF0YVssIHNwcmludGYoInNjYXJfJWQiLCBjKDQsIDgsIDEzLCAxNiwgMjAsIDI1LCAyOSwgMzEpKV0pDQpEYXRhJFNBRCA8LSBTcGVjaWFsUm93U3VtcyhEYXRhWywgc3ByaW50Zigic2Nhcl8lZCIsIGMoMywgMTAsIDI2LCAzMiwgMzksIDQwLCA0MSkpXSkNCkRhdGEkU2NoQSA8LSBTcGVjaWFsUm93U3VtcyhEYXRhWywgc3ByaW50Zigic2Nhcl8lZCIsIGMoMiwgMTEsIDE3LCAzNikpXSkNCkRhdGEkU0NBUkVEIDwtIFNwZWNpYWxSb3dTdW1zKERhdGFbLCBzcHJpbnRmKCJzY2FyXyVkIiwgMTo0MSldKQ0KDQpEYXRhJFBEX2QgPC0gaWZlbHNlKERhdGEkUEQgPj0gNywgMSwgMCkNCkRhdGEkR0FEX2QgPC0gaWZlbHNlKERhdGEkR0FEID49IDksIDEsIDApDQpEYXRhJFNlcEFfZCA8LSBpZmVsc2UoRGF0YSRTZXBBID49IDUsIDEsIDApDQpEYXRhJFNBRF9kIDwtIGlmZWxzZShEYXRhJFNBRCA+PSA4LCAxLCAwKQ0KRGF0YSRTY2hBX2QgPC0gaWZlbHNlKERhdGEkU2NoQSA+PSAzLCAxLCAwKQ0KRGF0YSRTQ0FSRURfZCA8LSBpZmVsc2UoRGF0YSRQRCA+PSAyNSwgMSwgMCkNCg0KIyBDRVNEIC0tIGFscmVhZHkgY29kZWQgaW4gMCwxLDIsMyANCiMgcmV2ZXJzZWQ6IDQsIDgsIDEyLCAxNg0KIyAwLTE0ID0gTWlsZCBvciBubyBkZXByZXNzaW9uOyAxNS02MCA9IHNpZ25pZmljYW50IGRlcHJlc3Npb24NCkRhdGFbLCBzcHJpbnRmKCJjZXNkXyVkIiwgYyg0LCA4LCAxMiwgMTYpKV0gPC0gMyAtIERhdGFbLCBzcHJpbnRmKCJjZXNkXyVkIiwgYyg0LCA4LCAxMiwgMTYpKV0gIyByZWNvZGUgQ0VTRA0KDQpEYXRhJENFU0QgPC0gU3BlY2lhbFJvd1N1bXMoRGF0YVssIHNwcmludGYoImNlc2RfJWQiLCAxOjIwKV0pDQpEYXRhJENFU0RfZCA8LSBpZmVsc2UoRGF0YSRDRVNEID49IDE1LCAxLCAwKQ0KDQoNCiMgQVNDUSAtLSBhbHJlYWR5IGNvZGVkIGluIDEsMiwzLDQsNQ0KICAjIFNlY3VyZTogMSAzIDcgMTAgMTUgDQogICMgQW54aW91czogNSA2IDkgMTEgMTQNCiAgIyBBdm9pZGFudDogMiA0IDggMTIgMTMNCiAgIyBEYXRhWywgYygiQVNlY3VyIiwgIkFBbnhpbyIsICJBQXZvaWQiLCAiQVNDUV9mIiwgIkFTQ1FfZCIpXQ0KDQpEYXRhJEFTZWN1ciA8LSBTcGVjaWFsUm93U3VtcyhEYXRhWywgc3ByaW50ZigiYXNjXyVkIiwgYygxLCAzLCA3LCAxMCwgMTUpKV0sIG5hcGVyY2VudCA9IC4zKSAgICMgaWYgbW9yZSB0aGFuIDIgTkEgaXRlbXMgPT4gTkENCkRhdGEkQUFueGlvIDwtIFNwZWNpYWxSb3dTdW1zKERhdGFbLCBzcHJpbnRmKCJhc2NfJWQiLCBjKDUsIDYsIDksIDExLCAxNCkpXSwgbmFwZXJjZW50ID0gLjMpDQpEYXRhJEFBdm9pZCA8LSBTcGVjaWFsUm93U3VtcyhEYXRhWywgc3ByaW50ZigiYXNjXyVkIiwgYygyLCA0LCA4LCAxMiwgMTMpKV0sIG5hcGVyY2VudCA9IC4zKQ0KDQpEYXRhIDwtIA0KICAgICAgRGF0YSAlPiUNCiAgICAgICAgZHBseXI6Om11dGF0ZSggDQogICAgICAgICAgICBBU0NRX2YgPSBkcGx5cjo6Y2FzZV93aGVuKA0KICAgICAgICAgICAgICBBU2VjdXIgPiBBQW54aW8gJiBBU2VjdXIgPiBBQXZvaWQgfiAiU2VjdXIiLA0KICAgICAgICAgICAgICBBU2VjdXIgPT0gQUFueGlvICYgQVNlY3VyID4gQUF2b2lkIH4gIlNlY3VyJkFueGlvIiwNCiAgICAgICAgICAgICAgQUFueGlvID4gQVNlY3VyICYgQUFueGlvID4gQUF2b2lkIH4gIkFueGlvIiwNCiAgICAgICAgICAgICAgQUF2b2lkID4gQVNlY3VyICYgQUF2b2lkID4gQUFueGlvIH4gIkF2b2lkIiwNCiAgICAgICAgICAgICAgQUF2b2lkID09IEFTZWN1ciAmIEFBdm9pZCA+IEFBbnhpbyB+ICJTZWN1ciZBdm9pZCIsDQogICAgICAgICAgICAgIEFBdm9pZCA+IEFTZWN1ciAmIEFBdm9pZCA9PSBBQW54aW8gfiAiQW54aW8mQXZvaWQiLA0KICAgICAgICAgICAgICBBU2VjdXIgPT0gQUFueGlvICYgQVNlY3VyID09IEFBdm9pZCB+ICJTZWN1ciZBbnhpbyZBdm9pZCIsDQogICAgICAgICAgICAgIFRSVUUgfiBhcy5jaGFyYWN0ZXIoTkEpKSkgJT4lDQogICAgICAgIGRwbHlyOjptdXRhdGUoQVNDUV9mID0gYXMuZmFjdG9yKEFTQ1FfZikpDQpEYXRhIDwtDQogICAgICBEYXRhICU+JSAgICAgICAgICAgICAgICAgICAgICMgaW5zZWN1cmUgPSAxLCBzZWN1cmUgPSAwDQogICAgICAgIGRwbHlyOjptdXRhdGUoDQogICAgICAgICAgQVNDUV9kID0gaWZlbHNlKEFTQ1FfZiAlaW4lIGMoIlNlY3VyIiwgIlNlY3VyJkFueGlvIiwgIlNlY3VyJkF2b2lkIiwgIlNlY3VyJkFueGlvJkF2b2lkIiksIDAsIDEpKSANCg0KDQojIEdDSUMgLS0gYWxyZWFkeSBjb2RlZCBpbiAxLDIsMyw0LDUNCiAgIyBPcGVuIENsaW1hdGUgKFBvc2l0aXZlIHdvcmRpbmcpOiBmaXJzdCA5IGl0ZW1zDQogICMgQ2xvc2VkIENsaW1hdGUoTmVnYXRpdmUgd29yZGluZyk6IGxhc3QgNSBpdGVtcyAoMTAsIDExIGFyZSByZXZlcnNlZCBwb3NpdGl2ZWx5IHdvcmRlcikNCiAgIyBUb3RhbCBTY29yZSA/PSBPcGVuICsgcmVydmVyc2VkIENsb3NlZCBleGNlcHQgMTAmMTEgIA0KDQpEYXRhWywgc3ByaW50ZigiZ2NpXyVkIiwgYygxMCwgMTEpKV0gPC0gNiAtIERhdGFbLCBzcHJpbnRmKCJnY2lfJWQiLCBjKDEwLCAxMSkpXQ0KDQpEYXRhJE9wZW5DIDwtIFNwZWNpYWxSb3dTdW1zKERhdGFbLCBzcHJpbnRmKCJnY2lfJWQiLCAxOjkpXSwgbmFwZXJjZW50ID0gLjMpICAgIyBpZiBtb3JlIHRoYW4gMyBOQSBpdGVtcyA9PiBOQQ0KRGF0YSRDbG9zZUMgPC0gU3BlY2lhbFJvd1N1bXMoRGF0YVssIHNwcmludGYoImdjaV8lZCIsIDEwOjE0KV0sIG5hcGVyY2VudCA9IC4zKSAjIGlmIG1vcmUgdGhhbiAyIE5BIGl0ZW1zID0+IE5BDQogDQoNCg0KIyBTRFENCiAgIyBkaWZmcmVudCB3b3JkaW5nIGZvciA1LTggYW5kIDktMTggYnV0IGV4YWN0bHkgdGhlIHNhbWUgaXRlbXMNCiAgIyB3ZSBoYXZlIGp1c3QgdGhlIGZpcnN0IHBhcnQgb2YgU0RROyBubyBpbXBhY3Qgc2NvcmVzDQogICMgcmVjb2RlOiA3KG9iZXlzKSwgMTEgKGZyaWVuZCksIDE0IChwb3B1bGFyKSwgMjEocmVmbGVjdCksIDI1KGF0dGVuZHMpDQogICAgIyBUb3RhbCA9IGVtb3Rpb24gKyBjb25kdWN0ICsgaHlwZXIgKyBwZWVyICAoYWxsIHN1YnNjYWxlcyBleGVwdCBwcm9zb2NpYWwpDQogICAgIyBGb3IgZWFjaCBvZiB0aGUgNSBzY2FsZXMgdGhlIHNjb3JlIGNhbiByYW5nZSBmcm9tIDAgdG8gMTAgaWYgYWxsIGl0ZW1zIHdlcmUgY29tcGxldGVkLiAgaHR0cDovL3d3dy5zZHFpbmZvLm9yZy9jOS5odG1sDQogICAgIyBUaGVzZSBzY29yZXMgY2FuIGJlIHNjYWxlZCB1cCBwcm8tcmF0YSBpZiBhdCBsZWFzdCAzIGl0ZW1zIHdlcmUgY29tcGxldGVkLCANCiAgICAjIGUuZy4gYSBzY29yZSBvZiA0IGJhc2VkIG9uIDMgY29tcGxldGVkIGl0ZW1zIGNhbiBiZSBzY2FsZWQgdXAgdG8gYSBzY29yZSBvZiA3ICg2LjY3IHJvdW5kZWQgdXApIGZvciA1IGl0ZW1zLg0KICAjIERhdGFbLCBjKCJFbW90aW9uIiwgIkNvbmR1Y3QiLCAiSHlwZXIiLCAiUGVlciIsICJQcm9zb2MiLCAiRXh0ZXJuYWwiLCAiSW50ZXJuYWwiLCAiU0RRIildDQoNCiMgUmVjb2RlIC0tIGZpcnN0IDEsMiwzIHRvIDAsMSwyIC4uLnRoZW4gcmV2ZXJzZSBzY29yZSBpdGVtcw0KRGF0YVssIHNwcmludGYoInNkcV8lZCIsIDE6MjUpXSA8LSBEYXRhWywgc3ByaW50Zigic2RxXyVkIiwgMToyNSldIC0gMQ0KRGF0YVssIHNwcmludGYoInNkcV8lZCIsIGMoNywgMTEsIDE0LCAyMSwgMjUpKV0gPC0gMiAtIERhdGFbLCBzcHJpbnRmKCJzZHFfJWQiLCBjKDcsIDExLCAxNCwgMjEsIDI1KSldDQoNCiMgRGVmaW5lIGZ1bmN0aW9uIHRoYXQgc2NvcmVzIFNEUSBzdWJzY2FsZXMgYW5kIHVzZSBpdA0KU2NvcmluZ1NEUSA8LSBmdW5jdGlvbihkZil7DQogIG5hX3ZlYyA8LSBhcHBseShkZiwgMSwgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkgDQogIHNjYWxlX3Njb3JlIDwtIGlmZWxzZShuYV92ZWMgPCAzLCByb3dNZWFucyhkZiwgbmEucm09VFJVRSksIE5BKQ0KICBzY2FsZV9zY29yZSA8LSBhcy5udW1lcmljKHNjYWxlX3Njb3JlKSAqIDUNCiAgc2NhbGVfc2NvcmUgPC0gZmxvb3IoMC41ICsgc2NhbGVfc2NvcmUpDQp9DQoNCkRhdGEkRW1vdGlvbiA8LSBTY29yaW5nU0RRKERhdGFbLCBzcHJpbnRmKCJzZHFfJWQiLCBjKDMsIDgsIDEzLCAxNiwgMjQpKV0pDQpEYXRhJENvbmR1Y3QgPC0gU2NvcmluZ1NEUShEYXRhWywgc3ByaW50Zigic2RxXyVkIiwgYyg1LCA3LCAxMiwgMTgsIDIyKSldKQ0KRGF0YSRIeXBlciA8LSBTY29yaW5nU0RRKERhdGFbLCBzcHJpbnRmKCJzZHFfJWQiLCBjKDIsIDEwLCAxNSwgMjEsIDI1KSldKSAgIA0KRGF0YSRQZWVyIDwtIFNjb3JpbmdTRFEoRGF0YVssIHNwcmludGYoInNkcV8lZCIsIGMoNiwgMTEsIDE0LCAxOSwgMjMpKV0pIA0KRGF0YSRQcm9zb2MgPC0gU2NvcmluZ1NEUShEYXRhWywgc3ByaW50Zigic2RxXyVkIiwgYygxLCA0LCA5LCAxNywgMjApKV0pICAgDQoNCkRhdGEkRXh0ZXJuYWwgPC0gIHJvd1N1bXMoRGF0YVssIGMoIkNvbmR1Y3QiLCAiSHlwZXIiKV0pDQpEYXRhJEludGVybmFsIDwtIHJvd1N1bXMoRGF0YVssIGMoIkVtb3Rpb24iLCAiUGVlciIpXSkNCkRhdGEkU0RRIDwtIHJvd1N1bXMoRGF0YVssIGMoIkVtb3Rpb24iLCAiQ29uZHVjdCIsICJIeXBlciIsICJQZWVyIildKSANCg0KRGF0YSRFbW90aW9uX2QgPC0gaWZlbHNlKERhdGEkRW1vdGlvbiA+PSA3LCAxLCAwKSAgICMgY3V0b2ZmIHNjb3JlcyBodHRwczovL3d3dy5sZWljc3BhcnQubmhzLnVrL0xpYnJhcnkvcG9pbGtqNjkwLnBkZg0KRGF0YSRDb25kdWN0X2QgPC0gaWZlbHNlKERhdGEkQ29uZHVjdCA+PSA2LCAxLCAwKQ0KRGF0YSRIeXBlcl9kIDwtIGlmZWxzZShEYXRhJEh5cGVyID49IDgsIDEsIDApICAgDQpEYXRhJFBlZXJfZCA8LSBpZmVsc2UoRGF0YSRQZWVyID49IDUsIDEsIDApIA0KRGF0YSRQcm9zb2NfZCA8LSBpZmVsc2UoRGF0YSRQcm9zb2MgPD0gNCwgMSwgMCkNCkRhdGEkU0RRX2QgPC0gaWZlbHNlKERhdGEkU0RRID49IDIwLCAxLCAwKSANCiAgDQojIENZUk0NCiAgIyBEYXRhWywgMzM6NThdICAjIENZUk0tMjYgZG9hciBwdCA1LTggYW5pDQogICMgRGF0YVssIDMzOjYwXSAgIyBDWVJNLTI4IGRvYXIgcHQgOS0xOCBhbmkNCiAgIyBDWVJNIDI2ICg1LTggeWVhcnMpDQogICAgIyBDWVJNc2NvcmUgPSBTVU0gKDE6MjYpDQogICAgIyBDWVJNX0luZGl2aWQgPSBTVU0gKDIsIDQsIDgsIDEwLCAxMiwgMTMsIDE0LCAxNywgMTksIDIwLCAyNCkNCiAgICAjIENZUk1fQ2FyZWdpdmVyID0gU1VNICg1LCA2LCA3LCAxMSwgMTYsIDIzLCAyNSkNCiAgICAjIENZUk1fQ29udGV4dCA9IFNVTSAoMSwgMywgOSwgMTUsIDE4LCAyMSwgMjIsIDI2KQ0KICAgICAgIyBJbmRQUz1TVU0gKDIsIDgsIDEwLCAxMiwgMjApDQogICAgICAjIEluZFBlZXI9IFNVTSAoMTMsIDE3KQ0KICAgICAgIyBJbmRTUz0gU1VNICg0LCAxNCwgMTksIDI0KQ0KICAgICAgIyBDclBoeXM9IFNVTSAoNSwgNykNCiAgICAgICMgQ3JQc3ljPSBTVU0gKDYsIDExLCAxNiwgMjMsIDI1KQ0KICAgICAgIyBDbnRTPSBTVU0gKDIxLCAyMikNCiAgICAgICMgQ250RWQ9IFNVTSAoMywgMTUpDQogICAgICAjIENudEM9IFNVTSAoMSwgOSwgMTgsIDI2KQ0KICAjIENZUk0gMjggKDktMTggeWVhcnMpDQogICAgIyBDWVJNc2NvcmUgPSBTVU0gKDE6MjgpDQogICAgIyBDWVJNX0luZGl2aWQgPSBTVU0gKDIsIDQsIDgsIDExLCAxMywgMTQsIDE1LCAxOCwgMjAsIDIxLCAyNSkNCiAgICAjIENZUk1fQ2FyZWdpdmVyID0gU1VNICg1LCA2LCA3LCAxMiwgMTcsIDI0LCAyNikNCiAgICAjIENZUk1fQ29udGV4dCA9IFNVTSAoMSwgMywgOSwgMTAsIDE2LCAxOSwgMjIsIDIzLCAyNywgMjgpDQoNCg0KRGF0YSRSX0luZF9rIDwtIHJlcChOQSwgbnJvdyhEYXRhKSkNCkRhdGFbRGF0YSR0aXBfY2hlc3Rpb25hciAlaW4lIGMoIjUtOGFuaSIsICI1LThpbnRhcnppZXJlIiksIF0kUl9JbmRfayA8LSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTcGVjaWFsUm93U3VtcyhEYXRhW0RhdGEkdGlwX2NoZXN0aW9uYXIgJWluJSBjKCI1LThhbmkiLCAiNS04aW50YXJ6aWVyZSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpbnRmKCJjeXJtXyVkIiwgYygyLCA0LCA4LCAxMCwgMTIsIDEzLCAxNCwgMTcsIDE5LCAyMCwgMjQpKV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFwZXJjZW50ID0gLjI5KQ0KRGF0YSRSX0NhcmVfayA8LSByZXAoTkEsIG5yb3coRGF0YSkpDQpEYXRhW0RhdGEkdGlwX2NoZXN0aW9uYXIgJWluJSBjKCI1LThhbmkiLCAiNS04aW50YXJ6aWVyZSIpLCBdJFJfQ2FyZV9rIDwtIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNwZWNpYWxSb3dTdW1zKERhdGFbRGF0YSR0aXBfY2hlc3Rpb25hciAlaW4lIGMoIjUtOGFuaSIsICI1LThpbnRhcnppZXJlIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcmludGYoImN5cm1fJWQiLCBjKDUsIDYsIDcsIDExLCAxNiwgMjMsIDI1KSldLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hcGVyY2VudCA9IC4yOSkNCkRhdGEkUl9Db250X2sgPC0gcmVwKE5BLCBucm93KERhdGEpKQ0KRGF0YVtEYXRhJHRpcF9jaGVzdGlvbmFyICVpbiUgYygiNS04YW5pIiwgIjUtOGludGFyemllcmUiKSwgXSRSX0NvbnRfayA8LSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTcGVjaWFsUm93U3VtcyhEYXRhW0RhdGEkdGlwX2NoZXN0aW9uYXIgJWluJSBjKCI1LThhbmkiLCAiNS04aW50YXJ6aWVyZSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpbnRmKCJjeXJtXyVkIiwgYygxLCAzLCA5LCAxNSwgMTgsIDIxLCAyMiwgMjYpKV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFwZXJjZW50ID0gLjI5KQ0KRGF0YSRDWVJNX2sgPC0gcmVwKE5BLCBucm93KERhdGEpKQ0KRGF0YSRDWVJNX2sgPC0gcm93U3VtcyhEYXRhWywgYygiUl9JbmRfayIsICJSX0NhcmVfayIsICJSX0NvbnRfayIpXSkgICAgICAgICAgIyBfayBzY29yZXMgbm90IGNvbXBhcmFibGUgdG8gX2Egc2NvcmVzDQoNCkRhdGEkUl9JbmRfYSA8LSByZXAoTkEsIG5yb3coRGF0YSkpDQpEYXRhW0RhdGEkdGlwX2NoZXN0aW9uYXIgPT0iOS0xOGFuaSIsIF0kUl9JbmRfYSA8LSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTcGVjaWFsUm93U3VtcyhEYXRhW0RhdGEkdGlwX2NoZXN0aW9uYXIgPT0gIjktMThhbmkiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpbnRmKCJjeXJtXyVkIiwgYygyLCA0LCA4LCAxMSwgMTMsIDE0LCAxNSwgMTgsIDIwLCAyMSwgMjUpKV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFwZXJjZW50ID0gLjI5KQ0KRGF0YSRSX0NhcmVfYSA8LSByZXAoTkEsIG5yb3coRGF0YSkpDQpEYXRhW0RhdGEkdGlwX2NoZXN0aW9uYXIgPT0iOS0xOGFuaSIsIF0kUl9DYXJlX2EgPC0gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3BlY2lhbFJvd1N1bXMoRGF0YVtEYXRhJHRpcF9jaGVzdGlvbmFyID09ICI5LTE4YW5pIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaW50ZigiY3lybV8lZCIsIGMoNSwgNiwgNywgMTIsIDE3LCAyNCwgMjYpKV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFwZXJjZW50ID0gLjI5KQ0KRGF0YSRSX0NvbnRfYSA8LSByZXAoTkEsIG5yb3coRGF0YSkpDQpEYXRhW0RhdGEkdGlwX2NoZXN0aW9uYXIgPT0iOS0xOGFuaSIsIF0kUl9Db250X2EgPC0gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3BlY2lhbFJvd1N1bXMoRGF0YVtEYXRhJHRpcF9jaGVzdGlvbmFyICA9PSAiOS0xOGFuaSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcmludGYoImN5cm1fJWQiLCBjKDEsIDMsIDksIDEwLCAxNiwgMTksIDIyLCAyMywgMjcsIDI4KSldLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hcGVyY2VudCA9IC4yOSkNCkRhdGEkQ1lSTV9hIDwtIHJlcChOQSwgbnJvdyhEYXRhKSkNCkRhdGEkQ1lSTV9hIDwtIHJvd1N1bXMoRGF0YVssIGMoIlJfSW5kX2EiLCAiUl9DYXJlX2EiLCAiUl9Db250X2EiKV0pICAgICAgICAjIF9rIHNjb3JlcyBub3QgY29tcGFyYWJsZSB0byBfYSBzY29yZXMNCg0KDQojIENZVw0KICAjIDUtOCB5ZWFycyBoYXZlIE5BIGluIGl0ZW0gNyBhbmQgOCwgYnV0IHRoaXMgZG9lc250IGNvdW50IGZvciBjeXdfbnIxIGFuZCBjeXdfbnIyIA0KRGF0YSRDWVcgPC0gcm93U3VtcyhEYXRhWywgYygiY3l3X25yMSIsICJjeXdfbnIyIildLCBuYS5ybSA9IFRSVUUpICAgICAgICAgDQoNCmBgYA0KDQoNCiMjIEV4cG9ydCAuUiBmb3IgUmV6aWRlbnRpYWwyIG5vdGVib29rDQoNCmBgYHtyIGV4cG9ydCwgZWNobz1GQUxTRSwgcmVzdWx0cz0iaGlkZSJ9DQpzYXZlUkRTKERhdGEsIGZpbGUgPSAiRGF0YV9SZXppZGVudGlhbC5SRFMiKQ0KYGBgDQoNCg0KIyMgRGVzY3JpcHRpdmVzIGZvciBEZW1vZ3JhcGhpY3MNCg0KYGBge3IgZGVzY3JfZnVuY3Rpb25zfQ0KYXBwbHlfaWYgPC0gZnVuY3Rpb24obWF0LCBwLCBmKSB7DQogICMgRmlsbCBOQSB3aXRoIEZBTFNFDQogIHBbaXMubmEocCldIDwtIEZBTFNFDQogIG1hdFtwXSA8LSBmKG1hdFtwXSkNCiAgbWF0DQp9DQoNCmFwYUNvcnIgPC0gZnVuY3Rpb24obWF0LCBjb3JydHlwZSA9ICJwZWFyc29uIikgew0KICBtYXRDb3JyIDwtIG1hdA0KICBpZiAoY2xhc3MobWF0Q29ycikgIT0gInJjb3JyIikgew0KICAgIG1hdENvcnIgPC0gcmNvcnIobWF0LCB0eXBlID0gY29ycnR5cGUpDQogIH0NCg0KICAjIEFkZCBvbmUgc3RhciBmb3IgZWFjaCBwIDwgMC4wNSwgMC4wMSwgMC4wMDENCiAgc3RhcnMgPC0gYXBwbHlfaWYocm91bmQobWF0Q29yciRyLCAyKSwgbWF0Q29yciRQIDwgMC4wNSwgZnVuY3Rpb24oeCkgcGFzdGUwKHgsICIqIikpDQogIHN0YXJzIDwtIGFwcGx5X2lmKHN0YXJzLCBtYXRDb3JyJFAgPCAwLjAxLCBmdW5jdGlvbih4KSBwYXN0ZTAoeCwgIioiKSkNCiAgc3RhcnMgPC0gYXBwbHlfaWYoc3RhcnMsIG1hdENvcnIkUCA8IDAuMDAxLCBmdW5jdGlvbih4KSBwYXN0ZTAoeCwgIioiKSkNCiAgIyBQdXQgLSBvbiBkaWFnb25hbCBhbmQgYmxhbmsgb24gdXBwZXIgZGlhZ29uYWwNCiAgc3RhcnNbdXBwZXIudHJpKHN0YXJzLCBkaWFnID0gVCldIDwtICItIg0KICBzdGFyc1t1cHBlci50cmkoc3RhcnMsIGRpYWcgPSBGKV0gPC0gIiINCiAgbiA8LSBsZW5ndGgoc3RhcnNbMSxdKQ0KICBjb2xuYW1lcyhzdGFycykgPC0gMTpuDQogICMgUmVtb3ZlIF8gYW5kIGNvbnZlcnQgdG8gdGl0bGUgY2FzZQ0KICByb3cubmFtZXMoc3RhcnMpIDwtIHRvb2xzOjp0b1RpdGxlQ2FzZShzYXBwbHkocm93Lm5hbWVzKHN0YXJzKSwgZ3N1YiwgcGF0dGVybj0iXyIsIHJlcGxhY2VtZW50ID0gIiAiKSkNCiAgIyBBZGQgaW5kZXggbnVtYmVyIHRvIHJvdyBuYW1lcw0KICByb3cubmFtZXMoc3RhcnMpIDwtIHBhc3RlKHBhc3RlMCgxOm4sIi4iKSwgcm93Lm5hbWVzKHN0YXJzKSkNCiAgc3RhcnMNCn0NCmBgYA0KDQpgYGB7ciBkZXNjcl9kZW1vZ3IxfQ0Kc3VtbWFyeXRvb2xzOjpkZlN1bW1hcnkoRGF0YVssIGMoImdlbiIsICJ2YXJzdGEiKV0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUgPSAiZ3JpZCIsIHBsYWluLmFzY2lpID0gRkFMU0UsIGdyYXBoLm1hZ25pZiA9IDAuNzUpICAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHByaW50KG1ldGhvZCA9ICJyZW5kZXIiLCBmb290bm90ZSA9IE5BKQ0KDQp0YWRhYV90LnRlc3QoZGF0YSA9IERhdGEsIHJlc3BvbnNlID0gdmFyc3RhLCBncm91cCA9IGdlbiwgcHJpbnQgPSAibWFya2Rvd24iKSAlPiUgDQogICAgICAgICAgICAgICAgICAgICAgICAgIHByaW50KG1ldGhvZCA9ICJyZW5kZXIiLCBmb290bm90ZSA9IE5BKQ0KYGBgDQoNCmBgYHtyIGRlc2NyX2RlbW9ncjJ9DQpzdW1tYXJ5dG9vbHM6OmRmU3VtbWFyeShEYXRhWywgYygidl9tYW1hX25hc3RlcmUiLCAidmFyc3RhX2luc3QiLCAibnJfZnJhdGkiLCAibnJfZnJhdGlfaW5zdCIpXSwgDQogICAgICAgICAgICAgICAgICAgICAgICBzdHlsZSA9ICJncmlkIiwgcGxhaW4uYXNjaWkgPSBGQUxTRSwgZ3JhcGgubWFnbmlmID0gMC43NSkgICU+JSANCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpbnQobWV0aG9kID0gInJlbmRlciIsIGZvb3Rub3RlID0gTkEpDQoNCkdHYWxseTo6Z2dwYWlycyhEYXRhLCBjb2x1bW5zID0gYygibnJfZnJhdGkiLCAibnJfZnJhdGlfaW5zdCIpLCBtYXBwaW5nID0gYWVzX3N0cmluZyhjb2xvdXIgPSAiZ2VuIiksDQogICAgICAgdXBwZXIgPSBsaXN0KGNvbnRpbnVvdXMgPSAic21vb3RoIiwgY29tYm8gPSAiYm94IiwgZGlzY3JldGUgPSAiZmFjZXRiYXIiLCBuYSA9ICJuYSIpLA0KICAgICAgIGxvd2VyID0gbGlzdChjb250aW51b3VzID0gInNtb290aF9sb2VzcyIsIGNvbWJvID0gImZhY2V0aGlzdCIsIGRpc2NyZXRlID0gInJhdGlvIiwgbmEgPSAibmEiKSwgIyAiZmFjZXRkZW5zaXR5Ig0KICAgICAgIGRpYWcgPSBsaXN0KGNvbnRpbnVvdXMgPSB3cmFwKCJkZW5zaXR5RGlhZyIsIGFscGhhPTAuMyksIGRpc2NyZXRlID0gImJhckRpYWciLCBuYSA9ICJuYURpYWciKSkNCg0KR0dhbGx5OjpnZ3BhaXJzKERhdGEsIGNvbHVtbnMgPSBjKCJ2X21hbWFfbmFzdGVyZSIsICJ2YXJzdGFfaW5zdCIpLCBtYXBwaW5nID0gYWVzX3N0cmluZyhjb2xvdXIgPSAiZ2VuIiksDQogICAgICAgdXBwZXIgPSBsaXN0KGNvbnRpbnVvdXMgPSAic21vb3RoIiwgY29tYm8gPSAiYm94IiwgZGlzY3JldGUgPSAiZmFjZXRiYXIiLCBuYSA9ICJuYSIpLA0KICAgICAgIGxvd2VyID0gbGlzdChjb250aW51b3VzID0gInNtb290aF9sb2VzcyIsIGNvbWJvID0gImZhY2V0aGlzdCIsIGRpc2NyZXRlID0gInJhdGlvIiwgbmEgPSAibmEiKSwgDQogICAgICAgZGlhZyA9IGxpc3QoY29udGludW91cyA9IHdyYXAoImRlbnNpdHlEaWFnIiwgYWxwaGE9MC4zKSwgZGlzY3JldGUgPSAiYmFyRGlhZyIsIG5hID0gIm5hRGlhZyIpKQ0KDQoNCkRhdGEgJT4lICAgICMgY2hhbmdlIGJhY2sgZmFjdG9yIHRvIG51bWVyaWMgaW4gb3JkZXIgdG8gY29tcHV0ZSBjb3JyZWxhdGlvbnMNCiAgbXV0YXRlKHZfbWFtYV9uYXN0ZXJlID0gZmN0X3JlY29kZSh2X21hbWFfbmFzdGVyZSwgIjEiID0gIjwxOSIgLCAiMiIgPSAiMjAtMjUiLCAiMyIgPSAiMjaWMzQiLCAiNCIgPSAiMzU+IikpICU+JSAgIA0KICBzZWxlY3Qodl9tYW1hX25hc3RlcmUsIHZhcnN0YV9pbnN0LCBucl9mcmF0aSwgbnJfZnJhdGlfaW5zdCkgJT4lDQogIGFzLm1hdHJpeCguKSAlPiUNCiAgICBhcGFDb3JyKGNvcnJ0eXBlID0gInBlYXJzb24iKSAgJT4lIGtuaXRyOjprYWJsZShjYXB0aW9uID0gIkNvcnJlbGF0aW9ucyIsIGZvcm1hdCA9ICJtYXJrZG93biIpDQoNCiMgYXBhQ29ycihhcy5tYXRyaXgoLlssIGMoInZfbWFtYV9uYXN0ZXJlIiwgInZhcnN0YV9pbnN0IiwgIm5yX2ZyYXRpIiwgIm5yX2ZyYXRpX2luc3QiKV0pLCBjb3JydHlwZSA9ICJwZWFyc29uIikgJT4lIA0KIyAgICAgICAgIGtuaXRyOjprYWJsZShmb3JtYXQgPSAibWFya2Rvd24iKSAgICAgIyBsZXZlbCBvZiBzaWduaWZpY2FuY2UgKHAgPCAwLjA1LCBwIDwgMC4wMSwgcCA8IDAuMDAxKQ0KDQpgYGANCg0KDQojIyBEZXNjcmlwdGl2ZXMgZm9yIFJpc2sNCg0KYGBge3IgZGVzY3JfcmlzaywgZmlnLndpZHRoID0gMTIsIGZpZy5hc3AgPSAxLjZ9DQpSaXNrX2NvbF9uYW1lcyA8LSBjKCJleHB1bmVyZV90b3giLCAiYm9saSIsICJUQ0MiLCAiYXNmaXhpZSIsICJhYnV6X3N1YiIsICJncmFkX2giLCAiaW50YXJ6aWVyZSIsICJ0cmFzX2RleiIsICJ0dWxiX2NvbmQiLCANCiAgICAgICAgICAgICAgICAgICAgIm5lZ2xpamFyZSIsICJ0ZW1wZXJhbSIsICJyZXBldGVudGEiLCAic2NvYWxhX3NwZWMiLCAiaW5hYmlsX3NjIiwgInNjaGltYl9kb20iLCAicGllcmRfbG9jIiwgImNvbXVuaXQiKQ0KDQojIFBsb3QgZnVuY3Rpb24gYW5kIERhdGEgZnVuY3Rpb24NCnJpc2tfcGxvdCA8LSBmdW5jdGlvbihkZil7IA0KICBnZ3Bsb3QoZGYsIGFlcyh4ID0gdmFyaWFibGUsIHkgPSBwZXJjZW50LCBmaWxsID0gdmFyaWFibGUpKSArIA0KICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHJvdW5kKHBlcmNlbnQpLCAiJSIpKSwgdmp1c3QgPSAtMC4yNSkgKw0KICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyANCiAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkgKw0KICAgICB5bGFiKCJQZXJjZW50YWdlIikgKyAgeGxhYigiIikgIA0KfQ0KDQpyaXNrX2RhdGEgPC0gZnVuY3Rpb24oZGYsIHJpc2tfbGV2ZWxzLCBmaWx0ZXJfY29sLCBmaWx0ZXJfbGV2ZWwpew0KICBmaWx0ZXJfY29sIDwtIHJsYW5nOjplbnF1byhmaWx0ZXJfY29sKQ0KICBkZiAlPiUgDQogICAgZmlsdGVyKCEhZmlsdGVyX2NvbCAlaW4lIGZpbHRlcl9sZXZlbCkgJT4lIA0KICAgIHNlbGVjdChSaXNrX2NvbF9uYW1lcykgJT4lDQogICAgc3VtbWFyaXNlX2FsbChmdW5zKHN1bSghaXMubmEoLikpIC8gbGVuZ3RoKC4pICogMTAwKSkgJT4lIA0KICAgIGdhdGhlcih2YXJpYWJsZSwgcGVyY2VudCkgJT4lDQogICAgYXJyYW5nZShkZXNjKHBlcmNlbnQpKSAlPiUNCiAgICBtdXRhdGUodmFyaWFibGUgPSBmYWN0b3IodmFyaWFibGUsIHJpc2tfbGV2ZWxzKSkgDQp9DQoNCiMgUnNpayBkYXRhICYgcGxvdHMNCkRhdGFfUmlzayA8LSANCiAgRGF0YSAlPiUgICAgDQogICAgc2VsZWN0KFJpc2tfY29sX25hbWVzKSAlPiUNCiAgICBzdW1tYXJpc2VfYWxsKGZ1bnMoc3VtKCFpcy5uYSguKSkgLyBsZW5ndGgoLikgKiAxMDApKSAlPiUgDQogICAgZ2F0aGVyKHZhcmlhYmxlLCBwZXJjZW50KSAlPiUNCiAgICBhcnJhbmdlKGRlc2MocGVyY2VudCkpICU+JQ0KICAgIG11dGF0ZSh2YXJpYWJsZSA9IGZhY3Rvcih2YXJpYWJsZSwgdmFyaWFibGUpKSAgICAgIyB0aGlzIG1ha2VzIGxldmVscyBvcmRlciBtYXRjaCByb3cgb3JkZXIhDQpyaXNrX2xldmVscyA8LSBsZXZlbHMoRGF0YV9SaXNrJHZhcmlhYmxlKSAgDQoNCnJpc2tfcGxvdDEgPC0gDQogIERhdGFfUmlzayAlPiUNCiAgICByaXNrX3Bsb3QoKSArDQogICAgICBnZ3RpdGxlKCJSaXNrIikgDQoNCnJpc2tfcGxvdDIgPC0gIA0KICByaXNrX2RhdGEoRGF0YSwgcmlza19sZXZlbHMsIGdlbiwgZmlsdGVyX2xldmVsID0gImYiKSAlPiUNCiAgICByaXNrX3Bsb3QoKSArDQogICAgICBnZ3RpdGxlKCJSaXNrIC0gZ2lybHMiKSANCg0Kcmlza19wbG90MyA8LQ0KICByaXNrX2RhdGEoRGF0YSwgcmlza19sZXZlbHMsIGdlbiwgZmlsdGVyX2xldmVsID0gIm0iKSAlPiUNCiAgICByaXNrX3Bsb3QoKSArDQogICAgICBnZ3RpdGxlKCJSaXNrIC0gYm95cyIpIA0KDQpyaXNrX3Bsb3Q0IDwtDQogIHJpc2tfZGF0YShEYXRhLCByaXNrX2xldmVscywgdGlwX2NoZXN0aW9uYXIsIGZpbHRlcl9sZXZlbCA9IGMoIjUtOGFuaSIsICI1LThpbnRhcnppZXJlIikpICU+JQ0KICAgIHJpc2tfcGxvdCgpICsNCiAgICAgIGdndGl0bGUoIlJpc2sgLSA1LTggeWVhcnMiKSANCg0Kcmlza19wbG90NSA8LQ0KICByaXNrX2RhdGEoRGF0YSwgcmlza19sZXZlbHMsIHRpcF9jaGVzdGlvbmFyLCBmaWx0ZXJfbGV2ZWwgPSAiOS0xOGFuaSIpICU+JQ0KICAgIHJpc2tfcGxvdCgpICsNCiAgICAgIGdndGl0bGUoIlJpc2sgLSA5LTE4IHllYXJzIikNCg0KDQpnZ3B1YnI6OmdnYXJyYW5nZShyaXNrX3Bsb3QxLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICBnZ2FycmFuZ2Uocmlza19wbG90Miwgcmlza19wbG90MywgbmNvbCA9IDIsIGxhYmVscyA9IGMoIkIiLCAiQyIpKSwgDQogICAgICAgICAgZ2dhcnJhbmdlKHJpc2tfcGxvdDQsIHJpc2tfcGxvdDUsIG5jb2wgPSAyLCBsYWJlbHMgPSBjKCJDIiwgIkQiKSksDQogICAgICAgICAgbnJvdyA9IDMsIA0KICAgICAgICAgIGxhYmVscyA9ICJBIikNCg0KYGBgDQoNCg0KIyMgRGVzY3JpcHRpdmVzIGZvciBBQ0VzDQoNCmBgYHtyIGRlc2NyX2FjZSwgZmlnLndpZHRoID0gMTIsIGZpZy5hc3AgPSAxLjZ9DQojIERhdGEkc2VjMl8xICAgIGlzIHJlZHVuZGFudCBiZWNhdXNlIGFsbCBzaG91bGQgYmUgMSwgZXZlbiB0b3VnaCB0aGVyZSBhcmUgNDAzIE5BIGFuZCA4NzIgb2YgMQ0KQWNlX2NvbF9uYW1lcyA8LSBjKHNwcmludGYoInNlYzFfJWQiLCAxOjEwKSwgc3ByaW50Zigic2VjMl8lZCIsIDI6OSkpDQoNCkFjZV9uZXdfbmFtZXMgPC0gYygiZGl2b3J0IiwgImluY2FyY2VyYXJlIiwgImJvYWxhIG1pbnRhbGEiLCAiYW1lbmludGFyZSIsICJ1bWlsaXJlIiwgDQogICAgICAgICAgICAgICAgICAgImFidXogc2V4dWFsIiwgImxpcHN1cmkiLCAiYWJ1eiBmaXppYyIsICJhZGljdGllIiwgIm5lc2lndXJhbnRhIiwgDQogICAgICAgICAgICAgICAgICAgImJ1bGx5aW5nIiwgImRlY2VzIiwgImVtaWdyYXJlIiwgImJvYWxhIiwgInZpb2xlbnRhIiwgDQogICAgICAgICAgICAgICAgICAgInJhdXRhdGUiLCAicG9saXRpZSIsICJhYnV6IHBhcnRlbmVyIikNCg0KIyBQbG90IGZ1bmN0aW9uIGFuZCBEYXRhIGZ1bmN0aW9uDQphY2VfcGxvdCA8LSBmdW5jdGlvbihkZil7IA0KICBnZ3Bsb3QoZGYsIGFlcyh4ID0gdmFyaWFibGUsIHkgPSBwZXJjZW50LCBmaWxsID0gdmFyaWFibGUpKSArIA0KICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHJvdW5kKHBlcmNlbnQpLCAiJSIpKSwgdmp1c3QgPSAtMC4yNSkgKw0KICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyANCiAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxKSkgKw0KICAgICB5bGFiKCJQZXJjZW50YWdlIikgKyAgeGxhYigiIikgIA0KfQ0KDQphY2VfZGF0YSA8LSBmdW5jdGlvbihkZiwgYWNlX2xldmVscywgZmlsdGVyX2NvbCwgZmlsdGVyX2xldmVsKXsNCiAgZmlsdGVyX2NvbCA8LSBybGFuZzo6ZW5xdW8oZmlsdGVyX2NvbCkNCiAgZGYgJT4lIA0KICAgIGZpbHRlcighIWZpbHRlcl9jb2wgJWluJSBmaWx0ZXJfbGV2ZWwpICU+JSANCiAgICBzZWxlY3QoQWNlX2NvbF9uYW1lcykgJT4lDQogICAgc3VtbWFyaXNlX2FsbChmdW5zKHN1bSghaXMubmEoLikpIC8gbGVuZ3RoKC4pICogMTAwKSkgJT4lIA0KICAgIGdhdGhlcih2YXJpYWJsZSwgcGVyY2VudCkgJT4lDQogICAgbXV0YXRlKHZhcmlhYmxlID0gc3RyaW5ncjo6c3RyX3JlcGxhY2UodmFyaWFibGUsIEFjZV9jb2xfbmFtZXMsIEFjZV9uZXdfbmFtZXMpKSAlPiUNCiAgICBhcnJhbmdlKGRlc2MocGVyY2VudCkpICU+JQ0KICAgIG11dGF0ZSh2YXJpYWJsZSA9IGZhY3Rvcih2YXJpYWJsZSwgYWNlX2xldmVscykpIA0KfSAgDQogIA0KIyBBQ0VzIGRhdGEgJiBwbG90cw0KRGF0YV9BQ0UgPC0gDQogIERhdGEgJT4lICAgICMgYmFycGxvdChjb2xTdW1zKERhdGFbLCBBY2VfY29sX25hbWVzXSwgbmEucm0gPSBUUlVFKSkNCiAgICBzZWxlY3QoQWNlX2NvbF9uYW1lcykgJT4lDQogICAgc3VtbWFyaXNlX2FsbChmdW5zKHN1bSghaXMubmEoLikpIC8gbGVuZ3RoKC4pICogMTAwKSkgJT4lIA0KICAgIGdhdGhlcih2YXJpYWJsZSwgcGVyY2VudCkgJT4lDQogICAgbXV0YXRlKHZhcmlhYmxlID0gc3RyaW5ncjo6c3RyX3JlcGxhY2UodmFyaWFibGUsIEFjZV9jb2xfbmFtZXMsIEFjZV9uZXdfbmFtZXMpKSAlPiUNCiAgICBhcnJhbmdlKGRlc2MocGVyY2VudCkpICU+JQ0KICAgIG11dGF0ZSh2YXJpYWJsZSA9IGZhY3Rvcih2YXJpYWJsZSwgdmFyaWFibGUpKSAgICAgIyB0aGlzIG1ha2VzIGxldmVscyBvcmRlciBtYXRjaCByb3cgb3JkZXIhDQphY2VfbGV2ZWxzIDwtIGxldmVscyhEYXRhX0FDRSR2YXJpYWJsZSkgIA0KDQphY2VfcGxvdDEgPC0gDQogIERhdGFfQUNFICU+JQ0KICAgIGFjZV9wbG90KCkgKw0KICAgICAgZ2d0aXRsZSgiQUNFIikgDQoNCmFjZV9wbG90MiA8LSAgDQogIGFjZV9kYXRhKERhdGEsIGFjZV9sZXZlbHMsIGdlbiwgZmlsdGVyX2xldmVsID0gImYiKSAlPiUNCiAgICBhY2VfcGxvdCgpICsNCiAgICAgIGdndGl0bGUoIkFDRSAtIGdpcmxzIikgDQoNCmFjZV9wbG90MyA8LQ0KICBhY2VfZGF0YShEYXRhLCBhY2VfbGV2ZWxzLCBnZW4sIGZpbHRlcl9sZXZlbCA9ICJtIikgJT4lDQogICAgYWNlX3Bsb3QoKSArDQogICAgICBnZ3RpdGxlKCJBQ0UgLSBib3lzIikgDQoNCmFjZV9wbG90NCA8LQ0KICBhY2VfZGF0YShEYXRhLCBhY2VfbGV2ZWxzLCB0aXBfY2hlc3Rpb25hciwgZmlsdGVyX2xldmVsID0gYygiNS04YW5pIiwgIjUtOGludGFyemllcmUiKSkgJT4lDQogICAgYWNlX3Bsb3QoKSArDQogICAgICBnZ3RpdGxlKCJBQ0UgLSA1LTggeWVhcnMiKSANCg0KYWNlX3Bsb3Q1IDwtDQogIGFjZV9kYXRhKERhdGEsIGFjZV9sZXZlbHMsIHRpcF9jaGVzdGlvbmFyLCBmaWx0ZXJfbGV2ZWwgPSAiOS0xOGFuaSIpICU+JQ0KICAgIGFjZV9wbG90KCkgKw0KICAgICAgZ2d0aXRsZSgiQUNFIC0gOS0xOCB5ZWFycyIpDQoNCg0KZ2dwdWJyOjpnZ2FycmFuZ2UoYWNlX3Bsb3QxLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICBnZ2FycmFuZ2UoYWNlX3Bsb3QyLCBhY2VfcGxvdDMsIG5jb2wgPSAyLCBsYWJlbHMgPSBjKCJCIiwgIkMiKSksIA0KICAgICAgICAgIGdnYXJyYW5nZShhY2VfcGxvdDQsIGFjZV9wbG90NSwgbmNvbCA9IDIsIGxhYmVscyA9IGMoIkMiLCAiRCIpKSwNCiAgICAgICAgICBucm93ID0gMywgDQogICAgICAgICAgbGFiZWxzID0gIkEiKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgDQojRGF0YSAlPiUNCiAgI3NlbGVjdChJRCwgdGlwX2NoZXN0aW9uYXIsIGdlbiwgc3ByaW50Zigic2VjMV8lZCIsIDE6MTApLCBzcHJpbnRmKCJzZWMyXyVkIiwgMTo5KSkgJT4lDQogICNnYXRoZXIodmFyaWFibGUsIHZhbHVlLCBzZWMxXzE6c2VjMl85LCAtYyh0aXBfY2hlc3Rpb25hciwgZ2VuKSwgbmEucm0gPSBGQUxTRSwgY29udmVydCA9IEZBTFNFKSAlPiUNCiAgI211dGF0ZSh2YWx1ZSA9IHJlcGxhY2VfbmEodmFsdWUsIDApKSAlPiUNCiAgDQpgYGANCg0KDQojIyBEZXNjcmlwdGl2ZXMgZm9yIEFDRSBTY29yZQ0KDQpgYGB7ciBkZXNjcl9hY2Vfc2NvcmV9DQpzdW1tYXJ5dG9vbHM6OmRmU3VtbWFyeShEYXRhWywgIkNZVyJdLCANCiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlID0gImdyaWQiLCBwbGFpbi5hc2NpaSA9IEZBTFNFLCBncmFwaC5tYWduaWYgPSAwLjc1KSAgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludChtZXRob2QgPSAicmVuZGVyIiwgZm9vdG5vdGUgPSBOQSkNCg0KdGFkYWFfdC50ZXN0KGRhdGEgPSBEYXRhLCByZXNwb25zZSA9IENZVywgZ3JvdXAgPSBnZW4sIHByaW50ID0gIm1hcmtkb3duIikgJT4lIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludChtZXRob2QgPSAicmVuZGVyIiwgZm9vdG5vdGUgPSBOQSkNCg0KR0dhbGx5OjpnZ3BhaXJzKERhdGEsIGNvbHVtbnMgPSBjKCJDWVciLCAiZ2VuIiksIG1hcHBpbmcgPSBhZXNfc3RyaW5nKGNvbG91ciA9ICJnZW4iKSwNCiAgICAgICB1cHBlciA9IGxpc3QoY29udGludW91cyA9ICJzbW9vdGgiLCBjb21ibyA9ICJib3giLCBkaXNjcmV0ZSA9ICJmYWNldGJhciIsIG5hID0gIm5hIiksDQogICAgICAgbG93ZXIgPSBsaXN0KGNvbnRpbnVvdXMgPSAic21vb3RoX2xvZXNzIiwgY29tYm8gPSAiZmFjZXRoaXN0IiwgZGlzY3JldGUgPSAicmF0aW8iLCBuYSA9ICJuYSIpLCANCiAgICAgICBkaWFnID0gbGlzdChjb250aW51b3VzID0gd3JhcCgiZGVuc2l0eURpYWciLCBhbHBoYT0wLjMpLCBkaXNjcmV0ZSA9ICJiYXJEaWFnIiwgbmEgPSAibmFEaWFnIikpDQoNCmBgYA0KDQoNCiMjIENvcnJlbGF0aW9uczogQUNFIFNjb3JlLCBSaXNrLCBBQ0VzDQoNCmBgYHtyIGFuYWx5c19jb3IsIGZpZy53aWR0aCA9IDE0LCBmaWcuYXNwID0gMX0NCiMgRGF0YSAlPiUNCiMgICByZW5hbWVfYXQodmFycyhBY2VfY29sX25hbWVzKSwgfiBBY2VfbmV3X25hbWVzKSAlPiUNCiMgICBzZWxlY3QoQ1lXLCBBY2VfbmV3X25hbWVzLCBSaXNrX2NvbF9uYW1lcykgJT4lDQojICAgcmVwbGFjZShpcy5uYSguKSwgMCkgJT4lDQojICAgYXMubWF0cml4KC4pICU+JQ0KIyAgICAgYXBhQ29ycihjb3JydHlwZSA9ICJwZWFyc29uIikgICU+JSBrbml0cjo6a2FibGUoY2FwdGlvbiA9ICJDb3JyZWxhdGlvbnMiLCBmb3JtYXQgPSAibWFya2Rvd24iKQ0KDQpEYXRhICU+JQ0KICAgIHJlbmFtZV9hdCh2YXJzKEFjZV9jb2xfbmFtZXMpLCB+IEFjZV9uZXdfbmFtZXMpICU+JQ0KICAgIHNlbGVjdChDWVcsIEFjZV9uZXdfbmFtZXMsIFJpc2tfY29sX25hbWVzKSAlPiUNCiAgICByZXBsYWNlKGlzLm5hKC4pLCAwKSAlPiUNCiAgICBhcy5tYXRyaXgoLikgJT4lDQogICAgICBIbWlzYzo6cmNvcnIoLiwgdHlwZSA9ICJwZWFyc29uIikgJT4lIA0KICAgICAgd2l0aCggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcGlwaW5nIHdpdGggbXVsdGktYXJndW1lbnQgZnVuY3Rpb25zDQogICAgICBjb3JycGxvdDo6Y29ycnBsb3QoLiRyLCBtZXRob2QgPSAibnVtYmVyIiwgdHlwZSA9ICJ1cHBlciIsIHAubWF0ID0gLiRQLCBzaWcubGV2ZWwgPSAwLjA1LCANCiAgICAgICAgICAgICAgIGluc2lnID0gImJsYW5rIiwgdGwuY29sID0gImJsYWNrIiwgdGwuY2V4ID0gLjksIHRsLnNydCA9IDQ1LCBudW1iZXIuY2V4ID0gMC41KSANCiAgICAgICkNCmBgYA0KDQoNCjwhLS0gU2Vzc2lvbiBJbmZvIGFuZCBMaWNlbnNlIC0tPg0KDQo8YnI+DQoNCiMgU2Vzc2lvbiBJbmZvDQpgYGB7ciBzZXNzaW9uX2luZm8sIGVjaG8gPSBGQUxTRSwgcmVzdWx0cyA9ICdtYXJrdXAnfQ0Kc2Vzc2lvbkluZm8oKSAgICANCmBgYA0KDQo8IS0tIEZvb3RlciAtLT4NCiZuYnNwOw0KPGhyIC8+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+QSB3b3JrIGJ5IDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9DbGF1ZGl1UGFwYXN0ZXJpLyI+Q2xhdWRpdSBQYXBhc3Rlcmk8L2E+PC9wPg0KPHAgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPjxzcGFuIHN0eWxlPSJjb2xvcjogIzgwODA4MDsiPjxlbT5jbGF1ZGl1LnBhcGFzdGVyaUBnbWFpbC5jb208L2VtPjwvc3Bhbj48L3A+DQombmJzcDsNCg==