1 Load data

# Read
file = "DATE O1A Complete.xlsx"
Date <- readxl::read_xlsx(file, sheet = "Date zilnice", skip = 5, col_names = FALSE)
Date_sop <- readRDS("O1a_Processed_SOP.RDS")

1.1 Processing data

# Clean
varnames <- c("Nr_crt", "ID", "Nume_Prenume", "Zi", "Vas_stres_pre", "Vas_bine_pre",
             sprintf("Stais_pre_%01d", seq(1,20)),
             "SOP",
             "IOS_mama", "IOS_tata", "IOS_iubit", "IOS_prieten", "IOS_personalitate",
             "Vas_rel_global", "Vas_rel_arousal",
             "CRQ_1", "CRQ_2", "CRQ_3", "CRQ_4", "CRQ_5", "CRQ_6",
             "Vas_stres_post", "Vas_bine_post",
             sprintf("Stais_post_%01d", seq(1,20))
)
names(Date) <- varnames   # nume noi
Date <- Date[-c(1:2),]    # scoatem randurile cu numele precedente
Date$Nr_crt <- 1:nrow(Date)   # era gol, asa ca numerotam randurile ca sa avem acesta variabila 
# Process NAs
Date <- Date %>% 
    na_if("na") %>%  
    mutate(NA_per_row = rowSums(is.na(.)))     # count NAs by row
Date <- Date %>% 
    filter(NA_per_row < 20)         # arbitrary cutoff for NAs on columns ... it is normal to have 4 NAs for all columns
# Convert to numeric
varsnumeric <- c("Zi", "Vas_stres_pre", "Vas_bine_pre",
                 sprintf("Stais_pre_%01d", seq(1,20)),
                 "IOS_mama", "IOS_tata", "IOS_iubit", "IOS_prieten", "IOS_personalitate",
                 "Vas_rel_global", "Vas_rel_arousal",
                 "CRQ_1", "CRQ_2", "CRQ_3", "CRQ_4", "CRQ_5", "CRQ_6",
                 "Vas_stres_post", "Vas_bine_post",
                  sprintf("Stais_post_%01d", seq(1,20)))
Date <- Date %>% 
  mutate_at(varsnumeric, as.numeric)
# which(Date$Stais_post_11 == 47)    # typo Stais_post_11 value of 47 -> corrected to 4
Date$Stais_post_11[Date$Stais_post_11 == 47] <- 4

1.2 Compute new variables

# Compute new variables 
Conditie <- Date %>% 
    select(Nr_crt, ID, IOS_mama, IOS_tata, IOS_iubit, IOS_prieten, IOS_personalitate) %>% 
    gather(type, value, -c(Nr_crt, ID)) %>% 
    mutate(Conditie = ifelse(!is.na(value), type, NA) ) %>%
    mutate(Conditie = str_replace(Conditie, "IOS_", "")) %>%
    arrange(Nr_crt) %>%
    select(Conditie) %>% na.omit() 
Date$Conditie <- Conditie$Conditie     # tidyverse returns tibble, must do this
IOS <- Date %>% 
  mutate(IOS = coalesce(IOS_mama, IOS_tata, IOS_iubit, IOS_prieten, IOS_personalitate)) %>%
  select(IOS)
Date$IOS <- IOS$IOS   # tidyverse returns tibble, must do this
rm(Conditie, IOS)    # remove 2 tibbles
# Scoring Stai   (convert numeric - VAS)
itemiVAS <- c(5, 6, 41, 42)
itemiStaiS_pre <- 7:26
itemiStaiS_post <- 43:62
ReversedItems <- c(1,2,5,8,10,11,15,16,19,20)
Date <- Date %>%                 
  replace(Date == "na", NA) %>%        # scimbam codarea cu na a Doinei
  mutate_at(vars(itemiStaiS_pre), funs(as.numeric)) %>%        # facem coloanele numerice pt STAI
  mutate_at(vars(itemiStaiS_post), funs(as.numeric)) %>% 
  mutate_at(vars(itemiVAS), funs(as.numeric))
Date[ ,itemiStaiS_pre[ReversedItems]] = 5 - Date[ ,itemiStaiS_pre[ReversedItems]]
Date[ ,itemiStaiS_post[ReversedItems]] = 5 - Date[ ,itemiStaiS_post[ReversedItems]]
Date$StaiS_pre = rowSums(Date[ ,itemiStaiS_pre], na.rm=T ) * NA ^ (rowSums(!is.na(Date[ ,itemiStaiS_pre])) == 0)
Date$StaiS_post = rowSums(Date[ ,itemiStaiS_post], na.rm=T ) * NA ^ (rowSums(!is.na(Date[ ,itemiStaiS_post])) == 0)

1.3 Merge with SOP

# warning + FALSE for joining character vector and factor, coercing into character vector automatically
Date_formerge <-
  Date %>%
  mutate(ID = word(ID, 1))
Date_sop_formerge <-
  Date_sop %>%
  select(FileNames, ID, Conditie, PrePost, 
         Ones:rThrees45) %>%
  gather(variable, value, Ones:rThrees45) %>%
  unite(VarCond, variable, PrePost) %>%
  spread(VarCond, value) %>%
  group_by(ID, Conditie) %>%
  summarise_all(funs(first(.[!is.na(.)])))             # this collapses the rows with NA
  
Date_merged <- left_join(Date_formerge, Date_sop_formerge, by = c("ID", "Conditie"))

1.4 Table of derived variables and SOP

varnottable <- c("Nume_Prenume", "NA_per_row",
                 "IOS_mama", "IOS_tata", "IOS_iubit", "IOS_prieten", "IOS_personalitate",
                 sprintf("Stais_pre_%01d", seq(1,20)), 
                 sprintf("Stais_post_%01d", seq(1,20)))
Date_merged %>%                              
  select(-varnottable) %>%
    DT::datatable(                                  # excel downloadable  DT table
      extensions = 'Buttons',
      options = list(pageLength = 20,
                     scrollX='500px', 
                     dom = 'Bfrtip', 
                     buttons = c('excel', "csv")))



2 SOP

# ## Independent Comparisons (eg for Ones) 
# # Plot indendent 
# ggplot(Date_sop, aes(x = PrePost, y = Ones)) +
#   geom_boxplot() +
#   facet_wrap(~Conditie) +
#   ggpubr::stat_compare_means(method = "t.test", paired = FALSE, comparisons = list(c("Pre","Post")))
# 
# # t test independent
# Date_sop %>% 
#   group_by(Conditie) %>% 
#   do(broom::tidy(t.test(.$Ones ~ .$PrePost, 
#                         mu = 0, 
#                         alt = "two.sided", 
#                         paired = FALSE, 
#                         conf.level = 0.95)))
## Paired Comparisons 
# Filter data for Paired Comparisons 
Date_Paired <- 
  Date_sop %>%
  mutate(PrePost = forcats::fct_relevel(PrePost, 'Pre', 'Post')) %>%               # change level order for plot
  group_by(ID, Conditie) %>%
  filter(n() != 1) %>%                                                             # exclude cases that dont have both Pre and Post data
  ungroup()
## Function for paired comparison plot
sop_paired_plot <- function(data, var, cond){
  var <- rlang::enquo(var)
  cond <- rlang::enquo(cond)
  ggplot(data, aes(x = !!cond, y = !!var)) +
    geom_boxplot() +
    stat_summary(fun.data = mean_se,  colour = "darkred") +
    xlab("") +
    facet_wrap(~Conditie) +
    ggpubr::stat_compare_means(method = "t.test", 
                               paired = TRUE, 
                               comparisons = list(c("Pre", "Post")))              # didn't include comparison list in func args
}
# Function t test paired
sop_paired_t <- function(data, var, cond){
  var <- deparse(substitute(var))
  cond <- deparse(substitute(cond))
  formula <- reformulate(cond, response = var)
  data %>%
    group_by(Conditie) %>%
    do(broom::tidy(t.test(data = ., formula,                                      # careful, this is a formula: var ~ PrePost
                          mu = 0,
                          alt = "two.sided",
                          paired = TRUE,
                          conf.level = 0.95)))
}

2.1 Plots with p values and t test

# Plots and t tests
sop_paired_plot(data = Date_Paired, var = Ones, cond = PrePost)                   # plot Ones 

sop_paired_t(data = Date_Paired, var = Ones, cond = PrePost) %>%                  # t test Ones
  knitr::kable(caption = "Ones", digits = 2, format = 'pandoc')                   # need pandoc to print kable caption

Ones
Conditie estimate statistic p.value parameter conf.low conf.high method alternative
iubit -63.24 -0.62 0.54 28 -271.52 145.04 Paired t-test two.sided
mama 48.97 0.57 0.57 34 -125.80 223.74 Paired t-test two.sided
personalitate 47.95 1.13 0.27 37 -38.15 134.04 Paired t-test two.sided
prieten -20.22 -0.21 0.84 35 -217.86 177.42 Paired t-test two.sided
tata -28.03 -0.23 0.82 35 -271.37 215.31 Paired t-test two.sided

sop_paired_plot(data = Date_Paired, var = Twos, cond = PrePost)

sop_paired_t(data = Date_Paired, var = Twos, cond = PrePost) %>%
  knitr::kable(caption = "Twos", digits = 2, format = 'pandoc')                   

Twos
Conditie estimate statistic p.value parameter conf.low conf.high method alternative
iubit 54.86 1.86 0.07 28 -5.47 115.20 Paired t-test two.sided
mama 36.46 2.29 0.03 34 4.06 68.85 Paired t-test two.sided
personalitate 27.45 1.84 0.07 37 -2.81 57.70 Paired t-test two.sided
prieten 4.06 0.29 0.78 35 -24.62 32.73 Paired t-test two.sided
tata 15.25 1.02 0.32 35 -15.21 45.71 Paired t-test two.sided

sop_paired_plot(data = Date_Paired, var = Threes, cond = PrePost)

sop_paired_t(data = Date_Paired, var = Threes, cond = PrePost) %>%
  knitr::kable(caption = "Threes", digits = 2, format = 'pandoc')

Threes
Conditie estimate statistic p.value parameter conf.low conf.high method alternative
iubit -116.90 -1.20 0.24 28 -317.24 83.45 Paired t-test two.sided
mama -188.89 -2.98 0.01 34 -317.67 -60.10 Paired t-test two.sided
personalitate -141.29 -2.62 0.01 37 -250.54 -32.04 Paired t-test two.sided
prieten -151.56 -1.76 0.09 35 -326.85 23.74 Paired t-test two.sided
tata -128.28 -1.18 0.25 35 -348.92 92.37 Paired t-test two.sided

sop_paired_plot(data = Date_Paired, var = Ones45, cond = PrePost)                 # plot Ones before 45s

sop_paired_t(data = Date_Paired, var = Ones45, cond = PrePost) %>%                # t test Ones before 45s
  knitr::kable(caption = "Ones45", digits = 2, format = 'pandoc')

Ones45
Conditie estimate statistic p.value parameter conf.low conf.high method alternative
iubit 7.66 0.38 0.71 28 -33.70 49.01 Paired t-test two.sided
mama 5.14 0.40 0.69 34 -21.15 31.43 Paired t-test two.sided
personalitate 7.61 0.48 0.63 37 -24.43 39.64 Paired t-test two.sided
prieten -12.25 -0.88 0.38 35 -40.50 16.00 Paired t-test two.sided
tata -44.17 -2.46 0.02 35 -80.60 -7.73 Paired t-test two.sided

sop_paired_plot(data = Date_Paired, var = Twos45, cond = PrePost)

sop_paired_t(data = Date_Paired, var = Twos45, cond = PrePost) %>%
  knitr::kable(caption = "Twos45", digits = 2, format = 'pandoc')

Twos45
Conditie estimate statistic p.value parameter conf.low conf.high method alternative
iubit 1.17 0.27 0.79 28 -7.64 9.99 Paired t-test two.sided
mama 2.63 0.86 0.40 34 -3.61 8.87 Paired t-test two.sided
personalitate 1.95 0.61 0.54 37 -4.48 8.37 Paired t-test two.sided
prieten 0.11 0.04 0.97 35 -5.76 5.98 Paired t-test two.sided
tata 3.86 1.83 0.08 35 -0.42 8.14 Paired t-test two.sided

sop_paired_plot(data = Date_Paired, var = Threes45, cond = PrePost)

sop_paired_t(data = Date_Paired, var = Threes45, cond = PrePost) %>%
  knitr::kable(caption = "Threes45", digits = 2, format = 'pandoc')

Threes45
Conditie estimate statistic p.value parameter conf.low conf.high method alternative
iubit -20.03 -1.06 0.30 28 -58.67 18.60 Paired t-test two.sided
mama -12.89 -0.94 0.35 34 -40.60 14.83 Paired t-test two.sided
personalitate -11.89 -0.71 0.48 37 -45.74 21.95 Paired t-test two.sided
prieten -1.94 -0.14 0.89 35 -29.47 25.58 Paired t-test two.sided
tata 16.92 1.10 0.28 35 -14.34 48.17 Paired t-test two.sided

sop_paired_plot(data = Date_Paired, var = rOnes, cond = PrePost)                  # plot ratio Ones to total presses

sop_paired_t(data = Date_Paired, var = rOnes, cond = PrePost) %>%                 # t test ratio Ones to total presses
  knitr::kable(caption = "rOnes", digits = 2, format = 'pandoc')

rOnes
Conditie estimate statistic p.value parameter conf.low conf.high method alternative
iubit 0.00 0.08 0.94 28 -0.07 0.07 Paired t-test two.sided
mama 0.04 1.19 0.24 34 -0.03 0.12 Paired t-test two.sided
personalitate 0.03 1.98 0.05 37 0.00 0.07 Paired t-test two.sided
prieten 0.04 1.18 0.25 35 -0.03 0.10 Paired t-test two.sided
tata 0.03 0.84 0.40 35 -0.05 0.11 Paired t-test two.sided

sop_paired_plot(data = Date_Paired, var = rTwos, cond = PrePost)

sop_paired_t(data = Date_Paired, var = rTwos, cond = PrePost) %>%
  knitr::kable(caption = "rTwos", digits = 2, format = 'pandoc')

rTwos
Conditie estimate statistic p.value parameter conf.low conf.high method alternative
iubit 0.02 1.74 0.09 28 0 0.05 Paired t-test two.sided
mama 0.01 2.49 0.02 34 0 0.03 Paired t-test two.sided
personalitate 0.01 2.15 0.04 37 0 0.02 Paired t-test two.sided
prieten 0.01 1.58 0.12 35 0 0.02 Paired t-test two.sided
tata 0.01 1.49 0.15 35 0 0.02 Paired t-test two.sided

sop_paired_plot(data = Date_Paired, var = rThrees, cond = PrePost)

sop_paired_t(data = Date_Paired, var = rThrees, cond = PrePost) %>%
  knitr::kable(caption = "rThrees", digits = 2, format = 'pandoc')
rThrees
Conditie estimate statistic p.value parameter conf.low conf.high method alternative
iubit -0.02 -0.65 0.52 28 -0.10 0.05 Paired t-test two.sided
mama -0.06 -1.57 0.13 34 -0.13 0.02 Paired t-test two.sided
personalitate -0.05 -2.36 0.02 37 -0.08 -0.01 Paired t-test two.sided
prieten -0.05 -1.37 0.18 35 -0.11 0.02 Paired t-test two.sided
tata -0.04 -1.05 0.30 35 -0.12 0.04 Paired t-test two.sided




3 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] grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] bindrcpp_0.2.2     gridExtra_2.3      plotly_4.8.0       summarytools_0.8.8 DT_0.5             ggpubr_0.2         magrittr_1.5      
 [8] broom_0.5.1        papaja_0.1.0.9842  psych_1.8.10       forcats_0.3.0      stringr_1.3.1      dplyr_0.7.8        purrr_0.2.5       
[15] readr_1.3.0        tidyr_0.8.2        tibble_1.4.2       ggplot2_3.1.0      tidyverse_1.2.1    pacman_0.5.0      

loaded via a namespace (and not attached):
 [1] httr_1.4.0         jsonlite_1.6       viridisLite_0.3.0  modelr_0.1.2       shiny_1.2.0        assertthat_0.2.0   highr_0.7         
 [8] pander_0.6.3       cellranger_1.1.0   yaml_2.2.0         pillar_1.3.1       backports_1.1.3    lattice_0.20-38    glue_1.3.0        
[15] digest_0.6.18      promises_1.0.1     pryr_0.1.4         ggsignif_0.4.0     rvest_0.3.2        colorspace_1.3-2   htmltools_0.3.6   
[22] httpuv_1.4.5       plyr_1.8.4         pkgconfig_2.0.2    haven_2.1.0        xtable_1.8-3       scales_1.0.0       later_0.7.5       
[29] generics_0.0.2     withr_2.1.2        lazyeval_0.2.1     cli_1.0.1          mnormt_1.5-5       crayon_1.3.4       readxl_1.1.0      
[36] mime_0.6           evaluate_0.12      nlme_3.1-137       xml2_1.2.0         foreign_0.8-71     rapportools_1.0    tools_3.5.2       
[43] data.table_1.11.8  hms_0.4.2          matrixStats_0.54.0 munsell_0.5.0      compiler_3.5.2     rlang_0.3.1        RCurl_1.95-4.11   
[50] rstudioapi_0.8     htmlwidgets_1.3    crosstalk_1.0.0    rmarkdown_1.11     bitops_1.0-6       labeling_0.3       gtable_0.2.0      
[57] codetools_0.2-15   R6_2.3.0           lubridate_1.7.4    knitr_1.21         bindr_0.1.1        stringi_1.2.4      parallel_3.5.2    
[64] Rcpp_1.0.0         tidyselect_0.2.5   xfun_0.4          
 

A work by Claudiu Papasteri

claudiu.papasteri@gmail.com

 

LS0tDQp0aXRsZTogIjxicj4gTzFBIFJlcG9ydCIgDQpzdWJ0aXRsZTogIkZpbmFsIFJlcG9ydCINCmF1dGhvcjogIjxicj4gQ2xhdWRpdSBQYXBhc3RlcmkiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlbSAlWScpYCINCm91dHB1dDogDQogICAgaHRtbF9ub3RlYm9vazoNCiAgICAgICAgICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgICAgICAgICAgdG9jOiB0cnVlDQogICAgICAgICAgICB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgICAgICAgICAgdGhlbWU6IHNwYWNlbGFiDQogICAgICAgICAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgICAgICAgICBmb250LWZhbWlseTogQXJpYWwNCiAgICAgICAgICAgIGZpZ193aWR0aDogMTANCiAgICAgICAgICAgIGZpZ19oZWlnaHQ6IDkNCiAgICBwZGZfZG9jdW1lbnQ6IA0KICAgICAgICAgICAgdG9jOiB0cnVlDQogICAgICAgICAgICB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgICAgICAgICAgIyBmb250c2l6ZTogMTFwdA0KICAgICAgICAgICAgIyBnZW9tZXRyeTogbWFyZ2luPTFpbg0KICAgICAgICAgICAgIyBmaWdfd2lkdGg6IDcNCiAgICAgICAgICAgICMgZmlnX2hlaWdodDogNg0KICAgICAgICAgICAgIyBmaWdfY2FwdGlvbjogdHJ1ZQ0KICAgICMgZ2l0aHViX2RvY3VtZW50OiANCiAgICAgICAgICAgICMgdG9jOiB0cnVlDQogICAgICAgICAgICAjIHRvY19kZXB0aDogMg0KICAgICAgICAgICAgIyBodG1sX3ByZXZpZXc6IGZhbHNlDQogICAgICAgICAgICAjIGZpZ193aWR0aDogNQ0KICAgICAgICAgICAgIyBmaWdfaGVpZ2h0OiA1DQogICAgICAgICAgICAjIGRldjoganBlZw0KLS0tDQoNCg0KPCEtLSBTZXR1cCAtLT4NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQ0KIyBraW50ciBvcHRpb25zDQprbml0cjo6b3B0c19jaHVuayRzZXQoDQogIGNvbW1lbnQgPSAiIyIsDQogIGNvbGxhcHNlID0gVFJVRSwNCiAgZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBUUlVFLCBtZXNzYWdlID0gVFJVRSwgY2FjaGUgPSBUUlVFICAgICAgICMgZWNobyA9IEZhbHNlIGZvciBnaXRodWJfZG9jdW1lbnQsIGJ1dCB3aWxsIGJlIGZvbGRlZCBpbiBodG1sX25vdGVib29rDQopDQoNCiMgR2VuZXJhbCBSIG9wdGlvbnMgYW5kIGluZm8NCnNldC5zZWVkKDExMSkgICAgICAgICAgICAgICAjIGluIGNhc2Ugd2UgdXNlIHJhbmRvbWl6ZWQgcHJvY2VkdXJlcyAgICAgICANCm9wdGlvbnMoc2NpcGVuID0gOTk5KSAgICAgICAjIHBvc2l0aXZlIHZhbHVlcyBiaWFzIHRvd2FyZHMgZml4ZWQgYW5kIG5lZ2F0aXZlIHRvd2FyZHMgc2NpZW50aWZpYyBub3RhdGlvbg0KDQojIExvYWQgcGFja2FnZXMNCmlmICghcmVxdWlyZSgicGFjbWFuIikpIGluc3RhbGwucGFja2FnZXMoInBhY21hbiIpDQpwYWNrYWdlcyA8LSBjKA0KICAidGlkeXZlcnNlIiwgICAgICAjIGJlc3QgdGhpbmcgdGhhdCBoYXBwZW5kIHRvIG1lDQogICJwc3ljaCIsICAgICAgICAgICMgZ2VuZXJhbCBwdXJwb3NlIHRvb2xib3ggZm9yIHBlcnNvbmFsaXR5LCBwc3ljaG9tZXRyaWMgdGhlb3J5IGFuZCBleHBlcmltZW50YWwgcHN5Y2hvbG9neQ0KICAicGFwYWphIiwgICAgICAgICAjIGZvciBBUEEgc3R5bGUNCiAgImJyb29tIiwgICAgICAgICAgIyBmb3IgdGlkeSBtb2RlbGxpbmcNCiAgImdncGxvdDIiLCAgICAgICAgIyBiZXN0IHBsb3RzDQogICJnZ3B1YnIiLCAgICAgICAgICMgZ2dwbG90MiB0byBwdWJsaWNhdGlvbiBxdWFsaXR5DQogICJEVCIsICAgICAgICAgICAgICMgbmljZSBzZWFyY2hhYmxlIGFuZCBkb3dubG9hZGFibGUgdGFibGVzDQogICJzdW1tYXJ5dG9vbHMiLA0KICAicGxvdGx5IiwNCiAgImdyaWRFeHRyYSIsDQogICJncmlkIg0KICAjICwgLi4uDQopDQppZiAoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQ0KcGFjbWFuOjpwX2xvYWQoY2hhciA9IHBhY2thZ2VzKQ0KDQojIFRoZW1lcyBmb3IgZ2dwbG90MiBwbG90aW5nIChoZXJlIHVzZWQgQVBBIHN0eWxlKQ0KdGhlbWVfc2V0KHRoZW1lX2FwYSgpKQ0KYGBgDQoNCmBgYHtyIHdvcmtpbmdfZGlyZWN0b3J5LCBpbmNsdWRlID0gRkFMU0V9DQojIGlmIG5lZWRlZA0KIyB3ZCA9ICIuL28xYS1yZXBvcnQiDQojIHNldHdkKHdkKQ0KYGBgDQoNCg0KPCEtLSBSZXBvcnQgLS0+DQoNCg0KIyBMb2FkIGRhdGENCg0KYGBge3IgcmF3X2RhdGEsIHJlc3VsdHMgPSAnaGlkZScsIGNhY2hlLmV4dHJhID0gZmlsZS5pbmZvKCJkaWFtb25kcy5jc3YiKX0NCiMgUmVhZA0KZmlsZSA9ICJEQVRFIE8xQSBDb21wbGV0ZS54bHN4Ig0KDQpEYXRlIDwtIHJlYWR4bDo6cmVhZF94bHN4KGZpbGUsIHNoZWV0ID0gIkRhdGUgemlsbmljZSIsIHNraXAgPSA1LCBjb2xfbmFtZXMgPSBGQUxTRSkNCg0KRGF0ZV9zb3AgPC0gcmVhZFJEUygiTzFhX1Byb2Nlc3NlZF9TT1AuUkRTIikNCmBgYA0KDQoNCiMjIFByb2Nlc3NpbmcgZGF0YQ0KDQpgYGB7ciBwcm9jZXNzZWRfZGF0YSwgY2FjaGUgPSBUUlVFLCBkZXBlbmRzb24gPSAicmF3X2RhdGEifQ0KIyBDbGVhbg0KdmFybmFtZXMgPC0gYygiTnJfY3J0IiwgIklEIiwgIk51bWVfUHJlbnVtZSIsICJaaSIsICJWYXNfc3RyZXNfcHJlIiwgIlZhc19iaW5lX3ByZSIsDQogICAgICAgICAgICAgc3ByaW50ZigiU3RhaXNfcHJlXyUwMWQiLCBzZXEoMSwyMCkpLA0KICAgICAgICAgICAgICJTT1AiLA0KICAgICAgICAgICAgICJJT1NfbWFtYSIsICJJT1NfdGF0YSIsICJJT1NfaXViaXQiLCAiSU9TX3ByaWV0ZW4iLCAiSU9TX3BlcnNvbmFsaXRhdGUiLA0KICAgICAgICAgICAgICJWYXNfcmVsX2dsb2JhbCIsICJWYXNfcmVsX2Fyb3VzYWwiLA0KICAgICAgICAgICAgICJDUlFfMSIsICJDUlFfMiIsICJDUlFfMyIsICJDUlFfNCIsICJDUlFfNSIsICJDUlFfNiIsDQogICAgICAgICAgICAgIlZhc19zdHJlc19wb3N0IiwgIlZhc19iaW5lX3Bvc3QiLA0KICAgICAgICAgICAgIHNwcmludGYoIlN0YWlzX3Bvc3RfJTAxZCIsIHNlcSgxLDIwKSkNCikNCm5hbWVzKERhdGUpIDwtIHZhcm5hbWVzICAgIyBudW1lIG5vaQ0KRGF0ZSA8LSBEYXRlWy1jKDE6MiksXSAgICAjIHNjb2F0ZW0gcmFuZHVyaWxlIGN1IG51bWVsZSBwcmVjZWRlbnRlDQpEYXRlJE5yX2NydCA8LSAxOm5yb3coRGF0ZSkgICAjIGVyYSBnb2wsIGFzYSBjYSBudW1lcm90YW0gcmFuZHVyaWxlIGNhIHNhIGF2ZW0gYWNlc3RhIHZhcmlhYmlsYSANCg0KIyBQcm9jZXNzIE5Bcw0KRGF0ZSA8LSBEYXRlICU+JSANCiAgICBuYV9pZigibmEiKSAlPiUgIA0KICAgIG11dGF0ZShOQV9wZXJfcm93ID0gcm93U3Vtcyhpcy5uYSguKSkpICAgICAjIGNvdW50IE5BcyBieSByb3cNCg0KRGF0ZSA8LSBEYXRlICU+JSANCiAgICBmaWx0ZXIoTkFfcGVyX3JvdyA8IDIwKSAgICAgICAgICMgYXJiaXRyYXJ5IGN1dG9mZiBmb3IgTkFzIG9uIGNvbHVtbnMgLi4uIGl0IGlzIG5vcm1hbCB0byBoYXZlIDQgTkFzIGZvciBhbGwgY29sdW1ucw0KDQojIENvbnZlcnQgdG8gbnVtZXJpYw0KdmFyc251bWVyaWMgPC0gYygiWmkiLCAiVmFzX3N0cmVzX3ByZSIsICJWYXNfYmluZV9wcmUiLA0KICAgICAgICAgICAgICAgICBzcHJpbnRmKCJTdGFpc19wcmVfJTAxZCIsIHNlcSgxLDIwKSksDQogICAgICAgICAgICAgICAgICJJT1NfbWFtYSIsICJJT1NfdGF0YSIsICJJT1NfaXViaXQiLCAiSU9TX3ByaWV0ZW4iLCAiSU9TX3BlcnNvbmFsaXRhdGUiLA0KICAgICAgICAgICAgICAgICAiVmFzX3JlbF9nbG9iYWwiLCAiVmFzX3JlbF9hcm91c2FsIiwNCiAgICAgICAgICAgICAgICAgIkNSUV8xIiwgIkNSUV8yIiwgIkNSUV8zIiwgIkNSUV80IiwgIkNSUV81IiwgIkNSUV82IiwNCiAgICAgICAgICAgICAgICAgIlZhc19zdHJlc19wb3N0IiwgIlZhc19iaW5lX3Bvc3QiLA0KICAgICAgICAgICAgICAgICAgc3ByaW50ZigiU3RhaXNfcG9zdF8lMDFkIiwgc2VxKDEsMjApKSkNCg0KRGF0ZSA8LSBEYXRlICU+JSANCiAgbXV0YXRlX2F0KHZhcnNudW1lcmljLCBhcy5udW1lcmljKQ0KDQojIHdoaWNoKERhdGUkU3RhaXNfcG9zdF8xMSA9PSA0NykgICAgIyB0eXBvIFN0YWlzX3Bvc3RfMTEgdmFsdWUgb2YgNDcgLT4gY29ycmVjdGVkIHRvIDQNCkRhdGUkU3RhaXNfcG9zdF8xMVtEYXRlJFN0YWlzX3Bvc3RfMTEgPT0gNDddIDwtIDQNCmBgYA0KDQo8IS0tIEluc3BlY3QgRGF0YSAtIHN3aXRjaGVkIG9mZiAtLT4NCmBgYHtyIGluc3BlY3RkYXRhLCBlY2hvPUZBTFNFLCByZXN1bHRzPSJoaWRlIn0gDQojIHByaW50KHN1bW1hcnl0b29sczo6ZGZTdW1tYXJ5KERhdGUsIHN0eWxlID0gJ2dyaWQnLCBwbGFpbi5hc2NpaSA9IEZBTFNFLCBncmFwaC5tYWduaWYgPSAwLjg1KSwgICAgIyBzdXBwcmVzcyBvdXRwdXQNCiMgICAgICAgbWV0aG9kID0gJ3JlbmRlcicsIGhlYWRpbmdzID0gRkFMU0UpDQojIHN0cihEYXRlLCBsaXN0Lmxlbj1uY29sKERhdGUpKSAgIyBkYXRhIHR5cGVzIGFyZSBmaW5lDQpgYGANCg0KDQojIyBDb21wdXRlIG5ldyB2YXJpYWJsZXMNCg0KYGBge3IgZGVyaXZlZF9kYXRhLCBjYWNoZSA9IFRSVUUsIGRlcGVuZHNvbiA9ICJwcm9jZXNzZWRfZGF0YSJ9DQojIENvbXB1dGUgbmV3IHZhcmlhYmxlcyANCkNvbmRpdGllIDwtIERhdGUgJT4lIA0KICAgIHNlbGVjdChOcl9jcnQsIElELCBJT1NfbWFtYSwgSU9TX3RhdGEsIElPU19pdWJpdCwgSU9TX3ByaWV0ZW4sIElPU19wZXJzb25hbGl0YXRlKSAlPiUgDQogICAgZ2F0aGVyKHR5cGUsIHZhbHVlLCAtYyhOcl9jcnQsIElEKSkgJT4lIA0KICAgIG11dGF0ZShDb25kaXRpZSA9IGlmZWxzZSghaXMubmEodmFsdWUpLCB0eXBlLCBOQSkgKSAlPiUNCiAgICBtdXRhdGUoQ29uZGl0aWUgPSBzdHJfcmVwbGFjZShDb25kaXRpZSwgIklPU18iLCAiIikpICU+JQ0KICAgIGFycmFuZ2UoTnJfY3J0KSAlPiUNCiAgICBzZWxlY3QoQ29uZGl0aWUpICU+JSBuYS5vbWl0KCkgDQpEYXRlJENvbmRpdGllIDwtIENvbmRpdGllJENvbmRpdGllICAgICAjIHRpZHl2ZXJzZSByZXR1cm5zIHRpYmJsZSwgbXVzdCBkbyB0aGlzDQpJT1MgPC0gRGF0ZSAlPiUgDQogIG11dGF0ZShJT1MgPSBjb2FsZXNjZShJT1NfbWFtYSwgSU9TX3RhdGEsIElPU19pdWJpdCwgSU9TX3ByaWV0ZW4sIElPU19wZXJzb25hbGl0YXRlKSkgJT4lDQogIHNlbGVjdChJT1MpDQpEYXRlJElPUyA8LSBJT1MkSU9TICAgIyB0aWR5dmVyc2UgcmV0dXJucyB0aWJibGUsIG11c3QgZG8gdGhpcw0Kcm0oQ29uZGl0aWUsIElPUykgICAgIyByZW1vdmUgMiB0aWJibGVzDQoNCiMgU2NvcmluZyBTdGFpICAgKGNvbnZlcnQgbnVtZXJpYyAtIFZBUykNCml0ZW1pVkFTIDwtIGMoNSwgNiwgNDEsIDQyKQ0KDQppdGVtaVN0YWlTX3ByZSA8LSA3OjI2DQppdGVtaVN0YWlTX3Bvc3QgPC0gNDM6NjINClJldmVyc2VkSXRlbXMgPC0gYygxLDIsNSw4LDEwLDExLDE1LDE2LDE5LDIwKQ0KDQpEYXRlIDwtIERhdGUgJT4lICAgICAgICAgICAgICAgICANCiAgcmVwbGFjZShEYXRlID09ICJuYSIsIE5BKSAlPiUgICAgICAgICMgc2NpbWJhbSBjb2RhcmVhIGN1IG5hIGEgRG9pbmVpDQogIG11dGF0ZV9hdCh2YXJzKGl0ZW1pU3RhaVNfcHJlKSwgZnVucyhhcy5udW1lcmljKSkgJT4lICAgICAgICAjIGZhY2VtIGNvbG9hbmVsZSBudW1lcmljZSBwdCBTVEFJDQogIG11dGF0ZV9hdCh2YXJzKGl0ZW1pU3RhaVNfcG9zdCksIGZ1bnMoYXMubnVtZXJpYykpICU+JSANCiAgbXV0YXRlX2F0KHZhcnMoaXRlbWlWQVMpLCBmdW5zKGFzLm51bWVyaWMpKQ0KDQpEYXRlWyAsaXRlbWlTdGFpU19wcmVbUmV2ZXJzZWRJdGVtc11dID0gNSAtIERhdGVbICxpdGVtaVN0YWlTX3ByZVtSZXZlcnNlZEl0ZW1zXV0NCkRhdGVbICxpdGVtaVN0YWlTX3Bvc3RbUmV2ZXJzZWRJdGVtc11dID0gNSAtIERhdGVbICxpdGVtaVN0YWlTX3Bvc3RbUmV2ZXJzZWRJdGVtc11dDQoNCkRhdGUkU3RhaVNfcHJlID0gcm93U3VtcyhEYXRlWyAsaXRlbWlTdGFpU19wcmVdLCBuYS5ybT1UICkgKiBOQSBeIChyb3dTdW1zKCFpcy5uYShEYXRlWyAsaXRlbWlTdGFpU19wcmVdKSkgPT0gMCkNCkRhdGUkU3RhaVNfcG9zdCA9IHJvd1N1bXMoRGF0ZVsgLGl0ZW1pU3RhaVNfcG9zdF0sIG5hLnJtPVQgKSAqIE5BIF4gKHJvd1N1bXMoIWlzLm5hKERhdGVbICxpdGVtaVN0YWlTX3Bvc3RdKSkgPT0gMCkNCmBgYA0KDQoNCiMjIE1lcmdlIHdpdGggU09QDQpgYGB7ciBtZXJnZWRfZGF0YSwgY2FjaGUgPSBUUlVFLCBkZXBlbmRzb24gPSAiZGVyaXZlZF9kYXRhIiwgd2FybmluZyA9IEZBTFNFfQ0KIyB3YXJuaW5nICsgRkFMU0UgZm9yIGpvaW5pbmcgY2hhcmFjdGVyIHZlY3RvciBhbmQgZmFjdG9yLCBjb2VyY2luZyBpbnRvIGNoYXJhY3RlciB2ZWN0b3IgYXV0b21hdGljYWxseQ0KRGF0ZV9mb3JtZXJnZSA8LQ0KICBEYXRlICU+JQ0KICBtdXRhdGUoSUQgPSB3b3JkKElELCAxKSkNCg0KRGF0ZV9zb3BfZm9ybWVyZ2UgPC0NCiAgRGF0ZV9zb3AgJT4lDQogIHNlbGVjdChGaWxlTmFtZXMsIElELCBDb25kaXRpZSwgUHJlUG9zdCwgDQogICAgICAgICBPbmVzOnJUaHJlZXM0NSkgJT4lDQogIGdhdGhlcih2YXJpYWJsZSwgdmFsdWUsIE9uZXM6clRocmVlczQ1KSAlPiUNCiAgdW5pdGUoVmFyQ29uZCwgdmFyaWFibGUsIFByZVBvc3QpICU+JQ0KICBzcHJlYWQoVmFyQ29uZCwgdmFsdWUpICU+JQ0KICBncm91cF9ieShJRCwgQ29uZGl0aWUpICU+JQ0KICBzdW1tYXJpc2VfYWxsKGZ1bnMoZmlyc3QoLlshaXMubmEoLildKSkpICAgICAgICAgICAgICMgdGhpcyBjb2xsYXBzZXMgdGhlIHJvd3Mgd2l0aCBOQQ0KICANCkRhdGVfbWVyZ2VkIDwtIGxlZnRfam9pbihEYXRlX2Zvcm1lcmdlLCBEYXRlX3NvcF9mb3JtZXJnZSwgYnkgPSBjKCJJRCIsICJDb25kaXRpZSIpKQ0KDQpgYGANCg0KIyMgVGFibGUgb2YgZGVyaXZlZCB2YXJpYWJsZXMgYW5kIFNPUA0KDQpgYGB7ciB0YWJsZV9kZXJpdmVkX2RhdGF9DQp2YXJub3R0YWJsZSA8LSBjKCJOdW1lX1ByZW51bWUiLCAiTkFfcGVyX3JvdyIsDQogICAgICAgICAgICAgICAgICJJT1NfbWFtYSIsICJJT1NfdGF0YSIsICJJT1NfaXViaXQiLCAiSU9TX3ByaWV0ZW4iLCAiSU9TX3BlcnNvbmFsaXRhdGUiLA0KICAgICAgICAgICAgICAgICBzcHJpbnRmKCJTdGFpc19wcmVfJTAxZCIsIHNlcSgxLDIwKSksIA0KICAgICAgICAgICAgICAgICBzcHJpbnRmKCJTdGFpc19wb3N0XyUwMWQiLCBzZXEoMSwyMCkpKQ0KDQpEYXRlX21lcmdlZCAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgc2VsZWN0KC12YXJub3R0YWJsZSkgJT4lDQogICAgRFQ6OmRhdGF0YWJsZSggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBleGNlbCBkb3dubG9hZGFibGUgIERUIHRhYmxlDQogICAgICBleHRlbnNpb25zID0gJ0J1dHRvbnMnLA0KICAgICAgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDIwLA0KICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsWD0nNTAwcHgnLCANCiAgICAgICAgICAgICAgICAgICAgIGRvbSA9ICdCZnJ0aXAnLCANCiAgICAgICAgICAgICAgICAgICAgIGJ1dHRvbnMgPSBjKCdleGNlbCcsICJjc3YiKSkpDQpgYGANCg0KDQo8YnI+DQo8YnI+DQoNCiMgU09QDQoNCmBgYHtyIHNvcF9mdW5jdGlvbnN9DQojICMjIEluZGVwZW5kZW50IENvbXBhcmlzb25zIChlZyBmb3IgT25lcykgDQojICMgUGxvdCBpbmRlbmRlbnQgDQojIGdncGxvdChEYXRlX3NvcCwgYWVzKHggPSBQcmVQb3N0LCB5ID0gT25lcykpICsNCiMgICBnZW9tX2JveHBsb3QoKSArDQojICAgZmFjZXRfd3JhcCh+Q29uZGl0aWUpICsNCiMgICBnZ3B1YnI6OnN0YXRfY29tcGFyZV9tZWFucyhtZXRob2QgPSAidC50ZXN0IiwgcGFpcmVkID0gRkFMU0UsIGNvbXBhcmlzb25zID0gbGlzdChjKCJQcmUiLCJQb3N0IikpKQ0KIyANCiMgIyB0IHRlc3QgaW5kZXBlbmRlbnQNCiMgRGF0ZV9zb3AgJT4lIA0KIyAgIGdyb3VwX2J5KENvbmRpdGllKSAlPiUgDQojICAgZG8oYnJvb206OnRpZHkodC50ZXN0KC4kT25lcyB+IC4kUHJlUG9zdCwgDQojICAgICAgICAgICAgICAgICAgICAgICAgIG11ID0gMCwgDQojICAgICAgICAgICAgICAgICAgICAgICAgIGFsdCA9ICJ0d28uc2lkZWQiLCANCiMgICAgICAgICAgICAgICAgICAgICAgICAgcGFpcmVkID0gRkFMU0UsIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICBjb25mLmxldmVsID0gMC45NSkpKQ0KDQojIyBQYWlyZWQgQ29tcGFyaXNvbnMgDQojIEZpbHRlciBkYXRhIGZvciBQYWlyZWQgQ29tcGFyaXNvbnMgDQpEYXRlX1BhaXJlZCA8LSANCiAgRGF0ZV9zb3AgJT4lDQogIG11dGF0ZShQcmVQb3N0ID0gZm9yY2F0czo6ZmN0X3JlbGV2ZWwoUHJlUG9zdCwgJ1ByZScsICdQb3N0JykpICU+JSAgICAgICAgICAgICAgICMgY2hhbmdlIGxldmVsIG9yZGVyIGZvciBwbG90DQogIGdyb3VwX2J5KElELCBDb25kaXRpZSkgJT4lDQogIGZpbHRlcihuKCkgIT0gMSkgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgZXhjbHVkZSBjYXNlcyB0aGF0IGRvbnQgaGF2ZSBib3RoIFByZSBhbmQgUG9zdCBkYXRhDQogIHVuZ3JvdXAoKQ0KDQojIyBGdW5jdGlvbiBmb3IgcGFpcmVkIGNvbXBhcmlzb24gcGxvdA0Kc29wX3BhaXJlZF9wbG90IDwtIGZ1bmN0aW9uKGRhdGEsIHZhciwgY29uZCl7DQogIHZhciA8LSBybGFuZzo6ZW5xdW8odmFyKQ0KICBjb25kIDwtIHJsYW5nOjplbnF1byhjb25kKQ0KICBnZ3Bsb3QoZGF0YSwgYWVzKHggPSAhIWNvbmQsIHkgPSAhIXZhcikpICsNCiAgICBnZW9tX2JveHBsb3QoKSArDQogICAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9zZSwgIGNvbG91ciA9ICJkYXJrcmVkIikgKw0KICAgIHhsYWIoIiIpICsNCiAgICBmYWNldF93cmFwKH5Db25kaXRpZSkgKw0KICAgIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ0LnRlc3QiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWlyZWQgPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wYXJpc29ucyA9IGxpc3QoYygiUHJlIiwgIlBvc3QiKSkpICAgICAgICAgICAgICAjIGRpZG4ndCBpbmNsdWRlIGNvbXBhcmlzb24gbGlzdCBpbiBmdW5jIGFyZ3MNCn0NCg0KIyBGdW5jdGlvbiB0IHRlc3QgcGFpcmVkDQpzb3BfcGFpcmVkX3QgPC0gZnVuY3Rpb24oZGF0YSwgdmFyLCBjb25kKXsNCiAgdmFyIDwtIGRlcGFyc2Uoc3Vic3RpdHV0ZSh2YXIpKQ0KICBjb25kIDwtIGRlcGFyc2Uoc3Vic3RpdHV0ZShjb25kKSkNCiAgZm9ybXVsYSA8LSByZWZvcm11bGF0ZShjb25kLCByZXNwb25zZSA9IHZhcikNCiAgZGF0YSAlPiUNCiAgICBncm91cF9ieShDb25kaXRpZSkgJT4lDQogICAgZG8oYnJvb206OnRpZHkodC50ZXN0KGRhdGEgPSAuLCBmb3JtdWxhLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBjYXJlZnVsLCB0aGlzIGlzIGEgZm9ybXVsYTogdmFyIH4gUHJlUG9zdA0KICAgICAgICAgICAgICAgICAgICAgICAgICBtdSA9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGFsdCA9ICJ0d28uc2lkZWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBwYWlyZWQgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBjb25mLmxldmVsID0gMC45NSkpKQ0KfQ0KYGBgDQoNCiMjIFBsb3RzIHdpdGggcCB2YWx1ZXMgYW5kIHQgdGVzdA0KYGBge3Igc29wX3Bsb3RzX3Rlc3RzLCBmaWcud2lkdGggPSAxMCwgZmlnLmFzcCA9IDAuOH0NCiMgUGxvdHMgYW5kIHQgdGVzdHMNCnNvcF9wYWlyZWRfcGxvdChkYXRhID0gRGF0ZV9QYWlyZWQsIHZhciA9IE9uZXMsIGNvbmQgPSBQcmVQb3N0KSAgICAgICAgICAgICAgICAgICAjIHBsb3QgT25lcyANCnNvcF9wYWlyZWRfdChkYXRhID0gRGF0ZV9QYWlyZWQsIHZhciA9IE9uZXMsIGNvbmQgPSBQcmVQb3N0KSAlPiUgICAgICAgICAgICAgICAgICAjIHQgdGVzdCBPbmVzDQogIGtuaXRyOjprYWJsZShjYXB0aW9uID0gIk9uZXMiLCBkaWdpdHMgPSAyLCBmb3JtYXQgPSAncGFuZG9jJykgICAgICAgICAgICAgICAgICAgIyBuZWVkIHBhbmRvYyB0byBwcmludCBrYWJsZSBjYXB0aW9uDQpzb3BfcGFpcmVkX3Bsb3QoZGF0YSA9IERhdGVfUGFpcmVkLCB2YXIgPSBUd29zLCBjb25kID0gUHJlUG9zdCkNCnNvcF9wYWlyZWRfdChkYXRhID0gRGF0ZV9QYWlyZWQsIHZhciA9IFR3b3MsIGNvbmQgPSBQcmVQb3N0KSAlPiUNCiAga25pdHI6OmthYmxlKGNhcHRpb24gPSAiVHdvcyIsIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICdwYW5kb2MnKSAgICAgICAgICAgICAgICAgICANCnNvcF9wYWlyZWRfcGxvdChkYXRhID0gRGF0ZV9QYWlyZWQsIHZhciA9IFRocmVlcywgY29uZCA9IFByZVBvc3QpDQpzb3BfcGFpcmVkX3QoZGF0YSA9IERhdGVfUGFpcmVkLCB2YXIgPSBUaHJlZXMsIGNvbmQgPSBQcmVQb3N0KSAlPiUNCiAga25pdHI6OmthYmxlKGNhcHRpb24gPSAiVGhyZWVzIiwgZGlnaXRzID0gMiwgZm9ybWF0ID0gJ3BhbmRvYycpDQoNCnNvcF9wYWlyZWRfcGxvdChkYXRhID0gRGF0ZV9QYWlyZWQsIHZhciA9IE9uZXM0NSwgY29uZCA9IFByZVBvc3QpICAgICAgICAgICAgICAgICAjIHBsb3QgT25lcyBiZWZvcmUgNDVzDQpzb3BfcGFpcmVkX3QoZGF0YSA9IERhdGVfUGFpcmVkLCB2YXIgPSBPbmVzNDUsIGNvbmQgPSBQcmVQb3N0KSAlPiUgICAgICAgICAgICAgICAgIyB0IHRlc3QgT25lcyBiZWZvcmUgNDVzDQogIGtuaXRyOjprYWJsZShjYXB0aW9uID0gIk9uZXM0NSIsIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICdwYW5kb2MnKQ0Kc29wX3BhaXJlZF9wbG90KGRhdGEgPSBEYXRlX1BhaXJlZCwgdmFyID0gVHdvczQ1LCBjb25kID0gUHJlUG9zdCkNCnNvcF9wYWlyZWRfdChkYXRhID0gRGF0ZV9QYWlyZWQsIHZhciA9IFR3b3M0NSwgY29uZCA9IFByZVBvc3QpICU+JQ0KICBrbml0cjo6a2FibGUoY2FwdGlvbiA9ICJUd29zNDUiLCBkaWdpdHMgPSAyLCBmb3JtYXQgPSAncGFuZG9jJykNCnNvcF9wYWlyZWRfcGxvdChkYXRhID0gRGF0ZV9QYWlyZWQsIHZhciA9IFRocmVlczQ1LCBjb25kID0gUHJlUG9zdCkNCnNvcF9wYWlyZWRfdChkYXRhID0gRGF0ZV9QYWlyZWQsIHZhciA9IFRocmVlczQ1LCBjb25kID0gUHJlUG9zdCkgJT4lDQogIGtuaXRyOjprYWJsZShjYXB0aW9uID0gIlRocmVlczQ1IiwgZGlnaXRzID0gMiwgZm9ybWF0ID0gJ3BhbmRvYycpDQoNCnNvcF9wYWlyZWRfcGxvdChkYXRhID0gRGF0ZV9QYWlyZWQsIHZhciA9IHJPbmVzLCBjb25kID0gUHJlUG9zdCkgICAgICAgICAgICAgICAgICAjIHBsb3QgcmF0aW8gT25lcyB0byB0b3RhbCBwcmVzc2VzDQpzb3BfcGFpcmVkX3QoZGF0YSA9IERhdGVfUGFpcmVkLCB2YXIgPSByT25lcywgY29uZCA9IFByZVBvc3QpICU+JSAgICAgICAgICAgICAgICAgIyB0IHRlc3QgcmF0aW8gT25lcyB0byB0b3RhbCBwcmVzc2VzDQogIGtuaXRyOjprYWJsZShjYXB0aW9uID0gInJPbmVzIiwgZGlnaXRzID0gMiwgZm9ybWF0ID0gJ3BhbmRvYycpDQpzb3BfcGFpcmVkX3Bsb3QoZGF0YSA9IERhdGVfUGFpcmVkLCB2YXIgPSByVHdvcywgY29uZCA9IFByZVBvc3QpDQpzb3BfcGFpcmVkX3QoZGF0YSA9IERhdGVfUGFpcmVkLCB2YXIgPSByVHdvcywgY29uZCA9IFByZVBvc3QpICU+JQ0KICBrbml0cjo6a2FibGUoY2FwdGlvbiA9ICJyVHdvcyIsIGRpZ2l0cyA9IDIsIGZvcm1hdCA9ICdwYW5kb2MnKQ0Kc29wX3BhaXJlZF9wbG90KGRhdGEgPSBEYXRlX1BhaXJlZCwgdmFyID0gclRocmVlcywgY29uZCA9IFByZVBvc3QpDQpzb3BfcGFpcmVkX3QoZGF0YSA9IERhdGVfUGFpcmVkLCB2YXIgPSByVGhyZWVzLCBjb25kID0gUHJlUG9zdCkgJT4lDQogIGtuaXRyOjprYWJsZShjYXB0aW9uID0gInJUaHJlZXMiLCBkaWdpdHMgPSAyLCBmb3JtYXQgPSAncGFuZG9jJykNCmBgYA0KDQoNCjxicj4NCjxicj4NCg0KPCEtLSBTZXNzaW9uIEluZm8gYW5kIExpY2Vuc2UgLS0+DQoNCjxicj4NCg0KIyBTZXNzaW9uIEluZm8NCmBgYHtyIHNlc3Npb25faW5mbywgZWNobyA9IEZBTFNFLCByZXN1bHRzID0gJ21hcmt1cCd9DQpzZXNzaW9uSW5mbygpICAgIA0KYGBgDQoNCjwhLS0gRm9vdGVyIC0tPg0KJm5ic3A7DQo8aHIgLz4NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij5BIHdvcmsgYnkgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL0NsYXVkaXVQYXBhc3RlcmkvIj5DbGF1ZGl1IFBhcGFzdGVyaTwvYT48L3A+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+PHNwYW4gc3R5bGU9ImNvbG9yOiAjODA4MDgwOyI+PGVtPmNsYXVkaXUucGFwYXN0ZXJpQGdtYWlsLmNvbTwvZW0+PC9zcGFuPjwvcD4NCiZuYnNwOw0K