1 Read and Merge

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Read and Merge
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
wd <- "E:/Cinetic idei noi/EXPERIMENTE OGL Frontiers (O.2 & O.0.3 & O.0.2)"
setwd(wd)
DataTrust <- rio::import(file.path(wd, "O.2 REZULTATE\\O.2 Date PrelucrareSPSS cu NEO si STAI", "O.2 Date pt Trust BUN cu NEO si STAIY.xlsx"))
DataDG <- rio::import(file.path(wd, "O.2 REZULTATE\\O.2 Date PrelucrareSPSS cu NEO si STAI", "O.2 Date pt DG BUN cu NEO si STAIY.xlsx"))
DataVAS <- rio::import(file.path(wd, "O.2 REZULTATE\\O.2 VAS,IOS", "O.2 Date PrelucrareSPSS.xlsx"))
DataBIO <- rio::import(file.path(wd, "O.2 BIO", "O.2 Ox si Cortizol.xlsx"))
  
Data_merge1 <- merge(DataVAS, DataTrust)  
Data_merge2 <- merge(Data_merge1, DataDG) 
Data_merge3 <- merge(Data_merge2, DataBIO)
Data <- Data_merge3
test_names <- unique(unlist(lapply(list(DataTrust, DataDG, DataVAS, DataBIO), names)))
merge_names <- names(Data)
if(identical(merge_names[order(merge_names)], test_names[order(test_names)])){    # the order matters in identical()
  cat("**Merge was succesful**")
  rm("Data_merge1", "Data_merge2", "Data_merge3", "DataBIO", "DataDG", "DataTrust", "DataVAS", "test_names", "merge_names")
}else cat("**Merge unsuccesful**") 

Merge was succesful

2 Derive new variables

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Derive new variables
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Data$D_VasS_Poz <- Data[, "VasS_postPoz"] - Data[, "VasS_prePoz"] 
Data$D_VasS_Neg <- Data[, "VasS_postNeg"] - Data[, "VasS_preNeg"]
Data$D_VasB_Poz <- Data[, "VasB_postPoz"] - Data[, "VasB_prePoz"] 
Data$D_VasB_Neg <- Data[, "VasB_postNeg"] - Data[, "VasB_preNeg"]
Data$D_IOS_Poz <- Data[, "IOS_postPoz"] - Data[, "IOS_prePoz"] 
Data$D_IOS_Neg <- Data[, "IOS_postNeg"] - Data[, "IOS_preNeg"]
Data$D_Sam1_Poz <- Data[, "Sam1_postPoz"] - Data[, "Sam1_prePoz"] 
Data$D_Sam1_Neg <- Data[, "Sam1_postNeg"] - Data[, "Sam1_preNeg"]
Data$D_Sam2_Poz <- Data[, "Sam2_postPoz"] - Data[, "Sam2_prePoz"] 
Data$D_Sam2_Neg <- Data[, "Sam2_postNeg"] - Data[, "Sam2_preNeg"]
Data$D_Sam3_Poz <- Data[, "Sam3_postPoz"] - Data[, "Sam3_prePoz"] 
Data$D_Sam3_Neg <- Data[, "Sam3_postNeg"] - Data[, "Sam3_preNeg"]
Data$D_DG_Poz <- Data[, "DG_postPozTot"] - Data[, "DG_prePozTot"] 
Data$D_DG_Neg <- Data[, "DG_postNegTot"] - Data[, "DG_preNegTot"]
Data$D_TrustMin_Poz <- Data[, "TrustMinPozPost"] - Data[, "TrustMinPozPre"] 
Data$D_TrustMin_Neg <- Data[, "TrustMinNegPost"] - Data[, "TrustMinNegPre"]
Data$D_TrustTot_Poz <- Data[, "TrustTotPozPost"] - Data[, "TrustTotPozPre"] 
Data$D_TrustTot_Neg <- Data[, "TrustTotNegPost"] - Data[, "TrustTotNegPre"]
Data$D_Cort_Poz <- Data[, "Cort_post_Poz"] - Data[, "Cort_pre_Poz"] 
Data$D_Cort_Neg <- Data[, "Cort_post_Neg"] - Data[, "Cort_pre_Neg"]
Data$D_Ox_Poz <- Data[, "Ox_post_Poz"] - Data[, "Ox_pre_Poz"] 
Data$D_Ox_Neg <- Data[, "Ox_post_Neg"] - Data[, "Ox_pre_Neg"]

3 Define Functions

subchunkify <- function(g, fig_height=7, fig_width=5) {
  g_deparsed <- paste0(deparse(
    function() {g}
  ), collapse = '')
  
  sub_chunk <- paste0("
  `","``{r sub_chunk_", floor(runif(1) * 10000), ", fig.height=", fig_height, ", fig.width=", fig_width, ", echo=FALSE}",
  "\n(", 
    g_deparsed
    , ")()",
  "\n`","``
  ")
  
  cat(knitr::knit(text = knitr::knit_expand(text = sub_chunk), quiet = TRUE))
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define Function for mining correlations
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Function for p-value significance -- both for func_ancova_multibox(), Get_Top_Relationships() and Correlations_With_One()
stars_signif <- function(pval) {
  stars = "ns"
  if(pval <= 0.001)
    stars = "***"
  if(pval > 0.001 & pval <= 0.01)
    stars = "**"
  if(pval > 0.01 & pval <= 0.05)
    stars = "*"
  if(pval > 0.05 & pval <= 0.1)
    stars = "."
  stars
}
## Function that returns correlations of all variables in descending order.
# Arg for threshold with default at .3 will keep only correlantions above .3 and below -.3. Also has threshhold for p-value. 
Get_Top_Relationships <- function(data_set, 
                                  correlation_abs_threshold=0.3,
                                  pvalue_threshold=0.05) {
  require(psych)
  require(dplyr)
  feature_names <- names(data_set)
  # strip var names to index for pair-wise identification
  names(data_set) <- seq(1:ncol(data_set))
  # calculate correlation and significance numbers
  cor_data_df <- psych::corr.test(data_set)
  # apply var names to correlation matrix over index
  rownames(cor_data_df$r) <- feature_names
  colnames(cor_data_df$r) <- feature_names
  # top cor and sig
  relationships_set <- cor_data_df$ci[,c('r','p')]
  # apply var names to data over index pairs
  relationships_set$feature_1 <- feature_names[as.numeric(sapply(strsplit(rownames(relationships_set), "-"), `[`, 1))]
  relationships_set$feature_2 <- feature_names[as.numeric(
    sapply(strsplit(rownames(relationships_set), "-"), `[`, 2))]
  relationships_set <- dplyr::select(relationships_set, feature_1, feature_2, r, p) %>% dplyr::rename(correlation = r, p.value = p)
  # return only the most insteresting relationships
  return(filter(relationships_set, abs(correlation) > correlation_abs_threshold &
                  p.value < pvalue_threshold) %>% 
        arrange(p.value) %>%
        mutate(p.signif = sapply(p.value, function(x) stars_signif(x))))
}
## Function that returns all correlation between numeric variables and one specific variable
Correlations_With_One <- function(data_set,
                            variable,
                            correlation_abs_threshold=0.3,
                            pvalue_threshold=0.05) {
  require(psych)
  require(dplyr)
  # use all numeric columns only
  numeric_cols <- unlist(lapply(data_set, is.numeric))
  data_set <- data_set[, numeric_cols]                               
  # calculate correlation and significance numbers
  cor_data_df <- psych::corr.test(data_set[, names(data_set) != variable], data_set[, variable], minlength = 20, adjust="none")
  # top cor and sig
  relationships_set <- as.data.frame(cbind(cor_data_df$r, cor_data_df$p))     # same as  cor_data_df$ci[,c('r','p')]
  relationships_set <- tibble::rownames_to_column(relationships_set, "Variable")   # relationships_set$Variable <- rownames(relationships_set)
  colnames(relationships_set) <- c("Variable", "correlation", "p.value")
  # return only the most insteresting relationships
  cat("#### Correlations with ", variable, "\n")
  return(filter(relationships_set, abs(correlation) > correlation_abs_threshold &
                  p.value < pvalue_threshold) %>% 
           arrange(p.value) %>%
           mutate(p.signif = sapply(p.value, function(x) stars_signif(x)))) %>%
           tibble::as.tibble()
}  
## Function for ploting correlation data frames resulting from Get_Top_Relationships and Correlations_With_One()
func_dotplot_cor <- function(df){                                        # https://www.r-pkg.org/pkg/ggpubr
  dotplotcor_scale_fill <- function(...){                                # Fix colors to signif factor levels even if missing
    ggplot2:::manual_scale(                                   
      'color', 
      values = setNames(
        c("darkgreen", "green3", "lawngreen", "yellow", "red"), 
        c("***", "**", "*", ".", "ns")), 
      ...
    )
  }                                           
  
  dtoplot_theme <- 
    ggpubr::theme_pubr() +
    theme(axis.text.y = element_text(size = 10))
  
  if(!"Variable" %in% colnames(df)){                                             # in oder to work for both Get_Top_Relationships and Correlations_With_One()
  df <- 
    df %>%                                            
      unite(cor_between, c("feature_1", "feature_2"), sep = " X ")               # unite 2 columns to x name from plot
  }else df <- df %>% dplyr::rename(cor_between = Variable)                       # change Variable to x name from plot
  
  df %>%
    ggpubr::ggdotchart(x = "cor_between", y = "correlation",
                       color = "p.signif",                                       # Color by sig
                       #   palette = c("#00AFBB", "#E7B800", "#FC4E07"),         # Custom color palette
                       sorting = "descending",                                   # Sort value in descending order
                       add = "segments",                                         # Add segments from y = 0 to dots
                       add.params = list(color = "lightgray", size = 2),         # Change segment color and size
                       group = "p.signif",                                       # Order by groups
                       dot.size = 8,                                             # Large dot size
                       xlab = "",
                       rotate = TRUE,                                            # Rotate vertically
                       label = round(.$correlation, 1),                          # Add mpg values as dot labels
                       font.label = list(color = "white", size = 9, 
                                         vjust = 0.5),                           # Adjust label parameters
                       ggtheme = dtoplot_theme) +                                # ggplot2 theme
    dotplotcor_scale_fill() +                                            # Fix colors to signif factor levels even if missing
    geom_hline(yintercept = 0, linetype = 2, color = "lightgray")
}
  
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define Function for Pre-Post Plots, t Change and ANCOVA Post
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Func t test si boxplot simplu
func_t_box <- function(df, ind, pre_var, post_var){
  df_modif <-
    df %>%
    select(ind, pre_var, post_var) %>% 
    tidyr::drop_na() %>%
    gather(pre_var, post_var, key = "Cond", value = "value") %>% 
    mutate_at(vars(c(1, 2)), funs(as.factor)) %>% 
    mutate(Cond = factor(Cond, levels = c(pre_var, post_var))) 
  
  stat_comp <- ggpubr::compare_means(value ~ Cond, data = df_modif, method = "t.test", paired = TRUE)
  
  stat_comp2 <-
    df_modif %>% 
    do(tidy(t.test(.$value ~ .$Cond,
                   paired = TRUE,
                   data=.)))
  
  plot <- 
    ggpubr::ggpaired(df_modif, x = "Cond", y = "value", id = ind, 
                     color = "Cond", line.color = "gray", line.size = 0.4,
                     palette = c("#00AFBB", "#FC4E07"), legend = "none") +
      stat_summary(fun.data = mean_se,  colour = "darkred") +
      ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label.x = as.numeric(df_modif$Cond)-0.4, label.y = max(df_modif$value)+0.5) + 
      ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label = "p.signif", comparisons = list(c(pre_var, post_var)))
  
  cat(paste0("#### ", pre_var, " ", post_var, "\n", "\n"))
  print(stat_comp)
  print(stat_comp2)
  print(plot)
}
func_ancova_multibox <- function(df, ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2){
  
  diff_score_c1 <- paste0(post_var_c1, " - ", pre_var_c1)
  diff_score_c2 <- paste0(post_var_c2, " - ", pre_var_c2)
  
  ## Plots and p-values for t tests
  df_modif <-
    df %>%
    select(ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2) %>% 
    tidyr::drop_na() %>%
    gather(pre_var_c1, post_var_c1, pre_var_c2, post_var_c2, key = "Cond", value = "value") %>% 
    mutate_at(vars(c(1, 2)), funs(as.factor)) %>% 
    mutate(Cond = factor(Cond, levels = c(pre_var_c1, post_var_c1, pre_var_c2, post_var_c2))) 
  
  stat_comp <- ggpubr::compare_means(value ~ Cond, data = df_modif, method = "t.test", paired = TRUE, p.adjust.method = "holm")
  
  plot <-
    ggpubr::ggpaired(df_modif, x = "Cond", y = "value", id = ind, 
                     color = "Cond", line.color = "gray", line.size = 0.4,
                     palette = c("#00AFBB", "#FC4E07", "#00AFBB", "#FC4E07"), legend = "none") +
    stat_summary(fun.data = mean_se,  colour = "darkred") +
    ggpubr::stat_compare_means(method = "t.test", paired = TRUE, label = "p.signif", 
                               label.y = c(max(df_modif$value) + 0.1*IQR(df_modif$value),
                                           max(df_modif$value) + 0.1*IQR(df_modif$value),
                                           seq(max(df_modif$value) + 0.3*IQR(df_modif$value), 
                                               max(df_modif$value) + 0.9*IQR(df_modif$value), length.out = 4)),  
                               comparisons = list(c(pre_var_c1, post_var_c1),
                                                  c(pre_var_c2, post_var_c2),
                                                  c(post_var_c1, pre_var_c2),
                                                  c(pre_var_c1, pre_var_c2),
                                                  c(post_var_c1, post_var_c2),
                                                  c(pre_var_c1, post_var_c2)))
  
  ## For ttestChange or ANCOVAChange - we do ttestChange (Post-Pre) here, but it isnt very important
  df_modif2 <-                                 
    df %>%
    select(ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2) %>%
    tidyr::drop_na() 
  df_modif2[diff_score_c1] <- df_modif2[, post_var_c1] - df_modif2[, pre_var_c1]
  df_modif2[diff_score_c2] <- df_modif2[, post_var_c2] - df_modif2[, pre_var_c2]
  
  tChange <- t.test(df_modif2[, diff_score_c1], df_modif2[, diff_score_c2], paired = TRUE)
  
  ## For descriptives by 2 factors (PrePost and PozNeg)
  df_modif3 <-
    df %>%
    select(ind, pre_var_c1, post_var_c1, pre_var_c2, post_var_c2) %>%
    tidyr::drop_na() %>%
    gather(pre_var_c1, post_var_c1, pre_var_c2, post_var_c2, key = "Cond", value = "value") %>%
    mutate(PrePost = case_when(stringr::str_detect(.$"Cond", "pre|Pre") ~ "Pre",
                               stringr::str_detect(.$"Cond", "post|Post") ~ "Post",
                               TRUE ~ NA_character_),
           PozNeg = case_when(stringr::str_detect(.$"Cond", "poz|Poz") ~ "Poz",
                              stringr::str_detect(.$"Cond", "neg|Neg") ~ "Neg",
                              TRUE ~ NA_character_)) %>%
    mutate(PrePost = as.factor(PrePost),
           PozNeg = as.factor(PozNeg))
  
  ## For ANCOVAPost - this is what we use
  df_modif4 <-
    df_modif3 %>%
    select(-"Cond") %>%
    spread("PrePost", "value")
  
  ## Models (here we use ANCOVAPost)    # https://m-clark.github.io/docs/mixedModels/anovamixed.html#introduction
  full_ancovaPost <-                                          # this is better than using lm() and glht()
      jmv::ancova(
        formula = Post ~ Pre + PozNeg,
        data = df_modif4,
        homo = TRUE,
        ss = "3",                                                     
        postHoc = ~ PozNeg,
        postHocCorr = list("tukey"),
        effectSize = list("eta", "partEta")
      )
  
      # mod_ancovaPost <- lm(Post ~ Pre + PozNeg, data = df_modif4)            # this is a Covariate Second model
      # mod_ancovaPost_ss3 <- car::Anova(mod_ancovaPost, type = "III")         # Type III sums of squares; see Andy Fields 2012
      # postHocs <- multcomp::glht(mod_ancovaPost, linfct = multcomp::mcp(PozNeg = "Tukey"))  # differences between the adjusted means,
      # sum_postHocs <- summary(postHocs)                                               # use Tukey or Dunnett’s post hoc tests
      # conf_postHocs <- confint(postHocs)
  scatter <-                                                             # Check for homogeneity of regression slopes
    ggplot(df_modif4, aes(Pre, Post, colour = PozNeg)) +
    geom_point(aes(shape = PozNeg), size = 3) +
    geom_smooth(method = "lm", aes(fill = PozNeg), alpha = 0.1)
    
  
  ## Other Models that work for this date
  # mod_ancovaPost <- lm(post ~ pre + treat)      # exactly the same with aov(post ~ pre + treat)
  # summary(mod_ancovaPost)
  # 
  # mod_anovaRM <- aov(score ~ treat*time + Error(id), dflong)
  # summary(mod_anovaRM)
  # 
  # mod_lme <- lme4::lmer(score ~ treat*time + (1|id), data=dflong)
  # anova(lmeModel)
  
  ## Output
  print(plot)
  cat(paste0("#### ", pre_var_c1, " ", post_var_c1, " ", pre_var_c2, " ", post_var_c2, "\n", "\n"))
  
  cat("#### Descriptives")
  psych::describeBy(df_modif3[, "value"], list(df_modif3[, "PrePost"], df_modif3[, "PozNeg"]), mat = TRUE) %>% 
    as.tibble() %>%
    print()
  cat("\n")
  
  print(stat_comp)
  cat("\n")
  
  cat("#### t Change")
  tidy(tChange) %>% print()
  cat("\n")
  
  cat("#### ANCOVA Post")
  cat("\n")
  cat("##### Homogeneity test")
  print(tibble::as.tibble(full_ancovaPost$assump$homo))
  cat("##### ANCOVA output")
  print(tibble::as.tibble(full_ancovaPost$main))
  # tidy(mod_ancovaPost) %>% 
  #   mutate(p.signif = sapply(p.value, function(x) stars_signif(x))) %>% 
  #   print()
  # cat("\n")
  cat("##### Post Hoc")
  print(tibble::as.tibble(full_ancovaPost$postHoc[[1]]))
  # tidy(sum_postHocs) %>% 
  #   mutate(p.signif = sapply(p.value, function(x) stars_signif(x))) %>% 
  #   print()
  cat("\n")
  cat("##### Homogeneity of regression slopes")
  subchunkify(plot(scatter), 5, 5)
}

4 Analyses

4.1 Correlations between Diffrence Scores with other variables

## Correlations between Diffrence Scores with other variables
Correlations_With_One(Data[,-c(1:7)], variable = "D_Ox_Poz", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # D_DG_Poz, Neo_C4, Neo_E3

4.1.0.1 Correlations with D_Ox_Poz

Correlations_With_One(Data[,-c(1:7)], variable = "D_Ox_Neg", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # nimic

4.1.0.2 Correlations with D_Ox_Neg

Correlations_With_One(Data[,-c(1:7)], variable = "D_Cort_Poz", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05) # D_Sam1_Poz, D_TrustTot_Poz, StaiS

4.1.0.3 Correlations with D_Cort_Poz

Correlations_With_One(Data[,-c(1:7)], variable = "D_Cort_Neg", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # nimic

4.1.0.4 Correlations with D_Cort_Neg

Correlations_With_One(Data[,-c(1:7)], variable = "D_VasS_Poz", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # nimic

4.1.0.5 Correlations with D_VasS_Poz

Correlations_With_One(Data[,-c(1:7)], variable = "D_VasS_Neg", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # D_TrustTot_Neg

4.1.0.6 Correlations with D_VasS_Neg

Correlations_With_One(Data[,-c(1:7)], variable = "D_VasB_Poz", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # D_Sam1_Poz

4.1.0.7 Correlations with D_VasB_Poz

Correlations_With_One(Data[,-c(1:7)], variable = "D_VasB_Neg", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # D_Sam1_Neg

4.1.0.8 Correlations with D_VasB_Neg

Correlations_With_One(Data[,-c(1:7)], variable = "D_IOS_Poz", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # nimic

4.1.0.9 Correlations with D_IOS_Poz

Correlations_With_One(Data[,-c(1:7)], variable = "D_IOS_Neg", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # nimic

4.1.0.10 Correlations with D_IOS_Neg

Correlations_With_One(Data[,-c(1:7)], variable = "D_DG_Poz", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # nimic

4.1.0.11 Correlations with D_DG_Poz

Correlations_With_One(Data[,-c(1:7)], variable = "D_DG_Neg", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # nimic

4.1.0.12 Correlations with D_DG_Neg

Correlations_With_One(Data[,-c(1:7)], variable = "D_TrustMin_Poz", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # nimic

4.1.0.13 Correlations with D_TrustMin_Poz

Correlations_With_One(Data[,-c(1:7)], variable = "D_TrustMin_Neg", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # nimic

4.1.0.14 Correlations with D_TrustMin_Neg

Correlations_With_One(Data[,-c(1:7)], variable = "D_TrustTot_Poz", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # nimic

4.1.0.15 Correlations with D_TrustTot_Poz

Correlations_With_One(Data[,-c(1:7)], variable = "D_TrustTot_Neg", correlation_abs_threshold = 0.2, pvalue_threshold = 0.05)  # D_VasS_Neg

4.1.0.16 Correlations with D_TrustTot_Neg

4.2 Simple before-after analyses with t test

## Simple before-after analyses with t test
func_t_box(Data, "Indicativ", "Ox_pre_Poz", "Ox_post_Poz")  # sig  

4.2.0.1 Ox_pre_Poz Ox_post_Poz

func_t_box(Data, "Indicativ", "Ox_pre_Neg", "Ox_post_Neg")  # sig

4.2.0.2 Ox_pre_Neg Ox_post_Neg

func_t_box(Data, "Indicativ", "Cort_pre_Poz", "Cort_post_Poz")  # nu  

4.2.0.3 Cort_pre_Poz Cort_post_Poz

func_t_box(Data, "Indicativ", "Cort_pre_Neg", "Cort_post_Neg")  # sig

4.2.0.4 Cort_pre_Neg Cort_post_Neg

func_t_box(Data, "Indicativ", "VasS_prePoz", "VasS_postPoz")  # sig  

4.2.0.5 VasS_prePoz VasS_postPoz

func_t_box(Data, "Indicativ", "VasS_preNeg", "VasS_postNeg")  # nu

4.2.0.6 VasS_preNeg VasS_postNeg

func_t_box(Data, "Indicativ", "VasB_prePoz", "VasB_postPoz")  # sig  

4.2.0.7 VasB_prePoz VasB_postPoz

func_t_box(Data, "Indicativ", "VasB_preNeg", "VasB_postNeg")  # nu

4.2.0.8 VasB_preNeg VasB_postNeg

func_t_box(Data, "Indicativ", "Sam1_prePoz", "Sam1_postPoz")  # sig  

4.2.0.9 Sam1_prePoz Sam1_postPoz

func_t_box(Data, "Indicativ", "Sam1_preNeg", "Sam1_postNeg")  # nu

4.2.0.10 Sam1_preNeg Sam1_postNeg

func_t_box(Data, "Indicativ", "Sam2_prePoz", "Sam2_postPoz")  # nu  

4.2.0.11 Sam2_prePoz Sam2_postPoz

func_t_box(Data, "Indicativ", "Sam2_preNeg", "Sam2_postNeg")  # nu

4.2.0.12 Sam2_preNeg Sam2_postNeg

func_t_box(Data, "Indicativ", "IOS_prePoz", "IOS_postPoz")  # sig  

4.2.0.13 IOS_prePoz IOS_postPoz

func_t_box(Data, "Indicativ", "IOS_preNeg", "IOS_postNeg")  # nu

4.2.0.14 IOS_preNeg IOS_postNeg

func_t_box(Data, "Indicativ", "DG_prePozTot", "DG_postPozTot")  # nu  

4.2.0.15 DG_prePozTot DG_postPozTot

func_t_box(Data, "Indicativ", "DG_preNegTot", "DG_postNegTot")  # sig

4.2.0.16 DG_preNegTot DG_postNegTot

func_t_box(Data, "Indicativ", "TrustMinPozPre", "TrustMinPozPost")  # nu  

4.2.0.17 TrustMinPozPre TrustMinPozPost

func_t_box(Data, "Indicativ", "TrustMinNegPre", "TrustMinNegPost")  # nu

4.2.0.18 TrustMinNegPre TrustMinNegPost

func_t_box(Data, "Indicativ", "TrustTotPozPre", "TrustTotPozPost")  # nu  

4.2.0.19 TrustTotPozPre TrustTotPozPost

func_t_box(Data, "Indicativ", "TrustTotNegPre", "TrustTotNegPost")  # nu

4.2.0.20 TrustTotNegPre TrustTotNegPost

4.3 tChance and ANCOVAPost

## tChance and ANCOVAPost 
func_ancova_multibox(Data, "Indicativ", "Ox_pre_Poz", "Ox_post_Poz", "Ox_pre_Neg", "Ox_post_Neg")

4.3.0.1 Ox_pre_Poz Ox_post_Poz Ox_pre_Neg Ox_post_Neg

4.3.0.2 Descriptives

NA

4.3.0.3 t Change

4.3.0.4 ANCOVA Post

4.3.0.4.1 Homogeneity test
4.3.0.4.2 ANCOVA output
4.3.0.4.3 Post Hoc
4.3.0.4.4 Homogeneity of regression slopes
plot of chunk sub_chunk_5929

plot of chunk sub_chunk_5929

func_ancova_multibox(Data, "Indicativ", "Cort_pre_Poz", "Cort_post_Poz", "Cort_pre_Neg", "Cort_post_Neg")

4.3.0.5 Cort_pre_Poz Cort_post_Poz Cort_pre_Neg Cort_post_Neg

4.3.0.6 Descriptives

NA

4.3.0.7 t Change

4.3.0.8 ANCOVA Post

4.3.0.8.1 Homogeneity test
4.3.0.8.2 ANCOVA output
4.3.0.8.3 Post Hoc
4.3.0.8.4 Homogeneity of regression slopes
plot of chunk sub_chunk_7264

plot of chunk sub_chunk_7264

func_ancova_multibox(Data, "Indicativ", "VasS_prePoz", "VasS_postPoz", "VasS_preNeg", "VasS_postNeg")

4.3.0.9 VasS_prePoz VasS_postPoz VasS_preNeg VasS_postNeg

4.3.0.10 Descriptives

NA

4.3.0.11 t Change

4.3.0.12 ANCOVA Post

4.3.0.12.1 Homogeneity test
4.3.0.12.2 ANCOVA output
4.3.0.12.3 Post Hoc
4.3.0.12.4 Homogeneity of regression slopes
plot of chunk sub_chunk_3704

plot of chunk sub_chunk_3704

func_ancova_multibox(Data, "Indicativ", "VasB_prePoz", "VasB_postPoz", "VasB_preNeg", "VasB_postNeg")

4.3.0.13 VasB_prePoz VasB_postPoz VasB_preNeg VasB_postNeg

4.3.0.14 Descriptives

NA

4.3.0.15 t Change

4.3.0.16 ANCOVA Post

4.3.0.16.1 Homogeneity test
4.3.0.16.2 ANCOVA output
4.3.0.16.3 Post Hoc
4.3.0.16.4 Homogeneity of regression slopes
plot of chunk sub_chunk_5149

plot of chunk sub_chunk_5149

func_ancova_multibox(Data, "Indicativ", "Sam1_prePoz", "Sam1_postPoz", "Sam1_preNeg", "Sam1_postNeg")

4.3.0.17 Sam1_prePoz Sam1_postPoz Sam1_preNeg Sam1_postNeg

4.3.0.18 Descriptives

NA

4.3.0.19 t Change

4.3.0.20 ANCOVA Post

4.3.0.20.1 Homogeneity test
4.3.0.20.2 ANCOVA output
4.3.0.20.3 Post Hoc
4.3.0.20.4 Homogeneity of regression slopes
plot of chunk sub_chunk_3776

plot of chunk sub_chunk_3776

func_ancova_multibox(Data, "Indicativ", "Sam2_prePoz", "Sam2_postPoz", "Sam2_preNeg", "Sam2_postNeg")

4.3.0.21 Sam2_prePoz Sam2_postPoz Sam2_preNeg Sam2_postNeg

4.3.0.22 Descriptives

NA

4.3.0.23 t Change

4.3.0.24 ANCOVA Post

4.3.0.24.1 Homogeneity test
4.3.0.24.2 ANCOVA output
4.3.0.24.3 Post Hoc
4.3.0.24.4 Homogeneity of regression slopes
plot of chunk sub_chunk_4183

plot of chunk sub_chunk_4183

func_ancova_multibox(Data, "Indicativ", "IOS_prePoz", "IOS_postPoz", "IOS_preNeg", "IOS_postNeg") 

4.3.0.25 IOS_prePoz IOS_postPoz IOS_preNeg IOS_postNeg

4.3.0.26 Descriptives

NA

4.3.0.27 t Change

4.3.0.28 ANCOVA Post

4.3.0.28.1 Homogeneity test
4.3.0.28.2 ANCOVA output
4.3.0.28.3 Post Hoc
4.3.0.28.4 Homogeneity of regression slopes
plot of chunk sub_chunk_106

plot of chunk sub_chunk_106

func_ancova_multibox(Data, "Indicativ", "DG_prePozTot", "DG_postPozTot", "DG_preNegTot", "DG_postNegTot") 

4.3.0.29 DG_prePozTot DG_postPozTot DG_preNegTot DG_postNegTot

4.3.0.30 Descriptives

NA

4.3.0.31 t Change

4.3.0.32 ANCOVA Post

4.3.0.32.1 Homogeneity test
4.3.0.32.2 ANCOVA output
4.3.0.32.3 Post Hoc
4.3.0.32.4 Homogeneity of regression slopes
plot of chunk sub_chunk_5322

plot of chunk sub_chunk_5322

func_ancova_multibox(Data, "Indicativ", "TrustMinPozPre", "TrustMinPozPost", "TrustMinNegPre", "TrustMinNegPost") 

4.3.0.33 TrustMinPozPre TrustMinPozPost TrustMinNegPre TrustMinNegPost

4.3.0.34 Descriptives

NA

4.3.0.35 t Change

4.3.0.36 ANCOVA Post

4.3.0.36.1 Homogeneity test
4.3.0.36.2 ANCOVA output
4.3.0.36.3 Post Hoc
4.3.0.36.4 Homogeneity of regression slopes
plot of chunk sub_chunk_4321

plot of chunk sub_chunk_4321

func_ancova_multibox(Data, "Indicativ", "TrustTotPozPre", "TrustTotPozPost", "TrustTotNegPre", "TrustTotNegPost") 

4.3.0.37 TrustTotPozPre TrustTotPozPost TrustTotNegPre TrustTotNegPost

4.3.0.38 Descriptives

NA

4.3.0.39 t Change

4.3.0.40 ANCOVA Post

4.3.0.40.1 Homogeneity test
4.3.0.40.2 ANCOVA output
4.3.0.40.3 Post Hoc
4.3.0.40.4 Homogeneity of regression slopes
plot of chunk sub_chunk_936

plot of chunk sub_chunk_936

4.4 Correlations with Oxy

## Mining Correlations with Oxy
df_OxyAll_cor <-
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.05) %>%
    dplyr::as_tibble() %>%
    dplyr::filter_all(any_vars(grepl("Ox", .)))                           # only Oxy, but both Pre and Post Oxy
df_OxyAll_cor %>%              
    print(n = Inf)                                     
df_OxyAll_cor %>%
  func_dotplot_cor()

 
# Correlations only on Pre measures with Oxy -- nothing
df_OxyPre_cor <- 
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.1) %>%
    dplyr::as_tibble() %>%
    filter_at(vars(feature_1, feature_2), all_vars(grepl("pre|Pre", .))) %>%
    dplyr::filter_all(any_vars(grepl("Ox", .))) 
df_OxyPre_cor %>%
  print(n = Inf)
# Correlations only on Post measures with Oxy
df_OxyPost_cor <-
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.1) %>%
    dplyr::as_tibble() %>%
    filter_at(vars(feature_1, feature_2), all_vars(grepl("post|Post", .))) %>%
    dplyr::filter_all(any_vars(grepl("Ox", .))) 
df_OxyPost_cor %>%
    print(n = Inf)
df_OxyPost_cor %>% 
  func_dotplot_cor()

4.5 Correlations with Stess

## Mining Correlations with VasS
df_VasSAll_cor <-
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.05) %>%
    dplyr::as_tibble() %>%
    dplyr::filter_all(any_vars(grepl("VasS", .)))                           # only VasS, but both Pre and Post VasS
df_VasSAll_cor %>%              
    print(n = Inf)                                     
# Correlations only on Pre measures with VasS
df_VasSPre_cor <- 
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.1) %>%
    dplyr::as_tibble() %>%
    filter_at(vars(feature_1, feature_2), all_vars(grepl("pre|Pre", .))) %>%
    dplyr::filter_all(any_vars(grepl("VasS", .))) 
df_VasSPre_cor %>%
  print(n = Inf)
df_VasSPre_cor %>% 
  func_dotplot_cor()

# Correlations only on Post measures with VasS
df_VasSPost_cor <-
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.1) %>%
    dplyr::as_tibble() %>%
    filter_at(vars(feature_1, feature_2), all_vars(grepl("post|Post", .))) %>%
    dplyr::filter_all(any_vars(grepl("VasS", .))) 
df_VasSPost_cor %>%
    print(n = Inf)
df_VasSPost_cor %>% 
  func_dotplot_cor()

4.6 Correlations with Well Being

## Mining Correlations with VasB
df_VasBAll_cor <-
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.05) %>%
  dplyr::as_tibble() %>%
  dplyr::filter_all(any_vars(grepl("VasB", .)))                           # only VasB, but both Pre and Post VasB
df_VasBAll_cor %>%              
  print(n = Inf)                                     
# Correlations only on Pre measures with VasB
df_VasBPre_cor <- 
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.1) %>%
  dplyr::as_tibble() %>%
  filter_at(vars(feature_1, feature_2), all_vars(grepl("pre|Pre", .))) %>%
  dplyr::filter_all(any_vars(grepl("VasB", .))) 
df_VasBPre_cor %>%
  print(n = Inf)
df_VasBPre_cor %>%
  func_dotplot_cor()

# Correlations only on Post measures with VasB
df_VasBPost_cor <-
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.1) %>%
  dplyr::as_tibble() %>%
  filter_at(vars(feature_1, feature_2), all_vars(grepl("post|Post", .))) %>%
  dplyr::filter_all(any_vars(grepl("VasB", .))) 
df_VasBPost_cor %>%
  print(n = Inf)
df_VasBPost_cor %>% 
  func_dotplot_cor()

4.7 Correlations with IOS

## Mining Correlations with IOS
df_IOSAll_cor <-
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.05) %>%
  dplyr::as_tibble() %>%
  dplyr::filter_all(any_vars(grepl("IOS", .)))                           # only IOS, but both Pre and Post IOS
df_IOSAll_cor %>%              
  print(n = Inf)                                     
# Correlations only on Pre measures with IOS
df_IOSPre_cor <- 
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.1) %>%
  dplyr::as_tibble() %>%
  filter_at(vars(feature_1, feature_2), all_vars(grepl("pre|Pre", .))) %>%
  dplyr::filter_all(any_vars(grepl("IOS", .))) 
df_IOSPre_cor %>%
  print(n = Inf)
df_IOSPre_cor %>%
  func_dotplot_cor()

# Correlations only on Post measures with IOS
df_IOSPost_cor <-
  Get_Top_Relationships(Data[,-c(1:7)], correlation_abs_threshold = 0.2, pvalue_threshold = 0.1) %>%
  dplyr::as_tibble() %>%
  filter_at(vars(feature_1, feature_2), all_vars(grepl("post|Post", .))) %>%
  dplyr::filter_all(any_vars(grepl("IOS", .))) 
df_IOSPost_cor %>%
  print(n = Inf)
df_IOSPost_cor %>% 
  func_dotplot_cor()



5 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     rio_0.5.16         plyr_1.8.4         summarytools_0.9.3 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] nlme_3.1-137       bitops_1.0-6       matrixStats_0.54.0 lubridate_1.7.4    httr_1.4.0         tools_3.5.2        backports_1.1.3   
 [8] R6_2.4.0           lazyeval_0.2.1     colorspace_1.3-2   withr_2.1.2        tidyselect_0.2.5   mnormt_1.5-5       emmeans_1.3.1     
[15] curl_3.3           compiler_3.5.2     cli_1.0.1          rvest_0.3.2        xml2_1.2.0         sandwich_2.5-1     labeling_0.3      
[22] scales_1.0.0       checkmate_1.8.5    mvtnorm_1.0-10     digest_0.6.18      foreign_0.8-71     base64enc_0.1-3    pkgconfig_2.0.2   
[29] htmltools_0.3.6    highr_0.7          htmlwidgets_1.3    rlang_0.3.0.1      readxl_1.1.0       rstudioapi_0.8     pryr_0.1.4        
[36] jmvcore_0.9.5.2    bindr_0.1.1        generics_0.0.2     zoo_1.8-4          jsonlite_1.6       zip_1.0.0          car_3.0-2         
[43] RCurl_1.95-4.11    rapportools_1.0    Matrix_1.2-15      Rcpp_1.0.1         munsell_0.5.0      abind_1.4-5        stringi_1.2.4     
[50] multcomp_1.4-10    yaml_2.2.0         carData_3.0-2      MASS_7.3-51.1      grid_3.5.2         parallel_3.5.2     crayon_1.3.4      
[57] lattice_0.20-38    splines_3.5.2      haven_2.1.0        pander_0.6.3       hms_0.4.2          magick_2.0         knitr_1.21        
[64] pillar_1.3.1       tcltk_3.5.2        rjson_0.2.20       estimability_1.3   ggsignif_0.4.0     codetools_0.2-15   glue_1.3.1        
[71] evaluate_0.12      data.table_1.12.2  modelr_0.1.2       cellranger_1.1.0   gtable_0.2.0       assertthat_0.2.1   xfun_0.4          
[78] openxlsx_4.1.0     xtable_1.8-3       coda_0.19-2        survival_2.43-3    jmv_0.9.6.1        TH.data_1.0-9     
 

A work by Claudiu Papasteri

claudiu.papasteri@gmail.com

 

LS0tDQp0aXRsZTogIjxicj4gTy4yIFJlcG9ydCIgDQpzdWJ0aXRsZTogIkZvY3VzIG9uIE94eSINCmF1dGhvcjogIjxicj4gQ2xhdWRpdSBQYXBhc3RlcmkiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlbSAlWScpYCINCm91dHB1dDogDQogICAgaHRtbF9ub3RlYm9vazoNCiAgICAgICAgICAjIHNlbGZfY29udGFpbmVkOiBubw0KICAgICAgICAgICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgICAgICAgICB0b2M6IHRydWUNCiAgICAgICAgICAgIHRvY19kZXB0aDogMg0KICAgICAgICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgICAgICAgICB0aGVtZTogc3BhY2VsYWINCiAgICAgICAgICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiBBcmlhbA0KICAgICAgICAgICAgZmlnX3dpZHRoOiAxMA0KICAgICAgICAgICAgZmlnX2hlaWdodDogOQ0KICAgICAjIHBkZl9kb2N1bWVudDogDQogICAgICAgICAgICAjIHRvYzogdHJ1ZQ0KICAgICAgICAgICAgIyB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgICMgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgICAgICAgICAjIGZvbnRzaXplOiAxMXB0DQogICAgICAgICAgICAjIGdlb21ldHJ5OiBtYXJnaW49MWluDQogICAgICAgICAgICAjIGZpZ193aWR0aDogNw0KICAgICAgICAgICAgIyBmaWdfaGVpZ2h0OiA2DQogICAgICAgICAgICAjIGZpZ19jYXB0aW9uOiB0cnVlDQogICAgIyBnaXRodWJfZG9jdW1lbnQ6IA0KICAgICAgICAgICAgIyB0b2M6IHRydWUNCiAgICAgICAgICAgICMgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICAjIGh0bWxfcHJldmlldzogZmFsc2UNCiAgICAgICAgICAgICMgZmlnX3dpZHRoOiA1DQogICAgICAgICAgICAjIGZpZ19oZWlnaHQ6IDUNCiAgICAgICAgICAgICMgZGV2OiBqcGVnDQotLS0NCg0KDQo8IS0tIFNldHVwIC0tPg0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBraW50ciBvcHRpb25zDQprbml0cjo6b3B0c19jaHVuayRzZXQoDQogIGNvbW1lbnQgPSAiIyIsDQogIGNvbGxhcHNlID0gVFJVRSwNCiAgZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBUUlVFLCBtZXNzYWdlID0gVFJVRSwgY2FjaGUgPSBUUlVFICAgICAgICMgZWNobyA9IEZhbHNlIGZvciBnaXRodWJfZG9jdW1lbnQsIGJ1dCB3aWxsIGJlIGZvbGRlZCBpbiBodG1sX25vdGVib29rDQopDQoNCiMgR2VuZXJhbCBSIG9wdGlvbnMgYW5kIGluZm8NCnNldC5zZWVkKDExMSkgICAgICAgICAgICAgICAjIGluIGNhc2Ugd2UgdXNlIHJhbmRvbWl6ZWQgcHJvY2VkdXJlcyAgICAgICANCm9wdGlvbnMoc2NpcGVuID0gOTk5KSAgICAgICAjIHBvc2l0aXZlIHZhbHVlcyBiaWFzIHRvd2FyZHMgZml4ZWQgYW5kIG5lZ2F0aXZlIHRvd2FyZHMgc2NpZW50aWZpYyBub3RhdGlvbg0KDQojIExvYWQgcGFja2FnZXMNCmlmICghcmVxdWlyZSgicGFjbWFuIikpIGluc3RhbGwucGFja2FnZXMoInBhY21hbiIpDQpwYWNrYWdlcyA8LSBjKA0KICAidGlkeXZlcnNlIiwgICAgICAjIGJlc3QgdGhpbmcgdGhhdCBoYXBwZW5kIHRvIG1lDQogICJwc3ljaCIsICAgICAgICAgICMgZ2VuZXJhbCBwdXJwb3NlIHRvb2xib3ggZm9yIHBlcnNvbmFsaXR5LCBwc3ljaG9tZXRyaWMgdGhlb3J5IGFuZCBleHBlcmltZW50YWwgcHN5Y2hvbG9neQ0KICAicGFwYWphIiwgICAgICAgICAjIGZvciBBUEEgc3R5bGUNCiAgImJyb29tIiwgICAgICAgICAgIyBmb3IgdGlkeSBtb2RlbGxpbmcNCiAgImdncGxvdDIiLCAgICAgICAgIyBiZXN0IHBsb3RzDQogICJnZ3B1YnIiLCAgICAgICAgICMgZ2dwbG90MiB0byBwdWJsaWNhdGlvbiBxdWFsaXR5DQogICJEVCIsICAgICAgICAgICAgICMgbmljZSBzZWFyY2hhYmxlIGFuZCBkb3dubG9hZGFibGUgdGFibGVzDQogICJzdW1tYXJ5dG9vbHMiLA0KICAicGx5ciIsIA0KICAicmlvIg0KICAjICwgLi4uDQopDQppZiAoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQ0KcGFjbWFuOjpwX2xvYWQoY2hhciA9IHBhY2thZ2VzKQ0KDQojIFRoZW1lcyBmb3IgZ2dwbG90MiBwbG90aW5nIChoZXJlIHVzZWQgQVBBIHN0eWxlKQ0KdGhlbWVfc2V0KHRoZW1lX2FwYSgpKQ0KYGBgDQoNCg0KDQo8IS0tIFJlcG9ydCAtLT4NCg0KDQojIFJlYWQgYW5kIE1lcmdlDQoNCg0KYGBge3IgcmVhZF9tZXJnZSwgcmVzdWx0cz0nYXNpcyd9DQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIFJlYWQgYW5kIE1lcmdlDQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQp3ZCA8LSAiRTovQ2luZXRpYyBpZGVpIG5vaS9FWFBFUklNRU5URSBPR0wgRnJvbnRpZXJzIChPLjIgJiBPLjAuMyAmIE8uMC4yKSINCnNldHdkKHdkKQ0KDQpEYXRhVHJ1c3QgPC0gcmlvOjppbXBvcnQoZmlsZS5wYXRoKHdkLCAiTy4yIFJFWlVMVEFURVxcTy4yIERhdGUgUHJlbHVjcmFyZVNQU1MgY3UgTkVPIHNpIFNUQUkiLCAiTy4yIERhdGUgcHQgVHJ1c3QgQlVOIGN1IE5FTyBzaSBTVEFJWS54bHN4IikpDQpEYXRhREcgPC0gcmlvOjppbXBvcnQoZmlsZS5wYXRoKHdkLCAiTy4yIFJFWlVMVEFURVxcTy4yIERhdGUgUHJlbHVjcmFyZVNQU1MgY3UgTkVPIHNpIFNUQUkiLCAiTy4yIERhdGUgcHQgREcgQlVOIGN1IE5FTyBzaSBTVEFJWS54bHN4IikpDQpEYXRhVkFTIDwtIHJpbzo6aW1wb3J0KGZpbGUucGF0aCh3ZCwgIk8uMiBSRVpVTFRBVEVcXE8uMiBWQVMsSU9TIiwgIk8uMiBEYXRlIFByZWx1Y3JhcmVTUFNTLnhsc3giKSkNCkRhdGFCSU8gPC0gcmlvOjppbXBvcnQoZmlsZS5wYXRoKHdkLCAiTy4yIEJJTyIsICJPLjIgT3ggc2kgQ29ydGl6b2wueGxzeCIpKQ0KICANCkRhdGFfbWVyZ2UxIDwtIG1lcmdlKERhdGFWQVMsIERhdGFUcnVzdCkgIA0KRGF0YV9tZXJnZTIgPC0gbWVyZ2UoRGF0YV9tZXJnZTEsIERhdGFERykgDQpEYXRhX21lcmdlMyA8LSBtZXJnZShEYXRhX21lcmdlMiwgRGF0YUJJTykNCg0KRGF0YSA8LSBEYXRhX21lcmdlMw0KDQp0ZXN0X25hbWVzIDwtIHVuaXF1ZSh1bmxpc3QobGFwcGx5KGxpc3QoRGF0YVRydXN0LCBEYXRhREcsIERhdGFWQVMsIERhdGFCSU8pLCBuYW1lcykpKQ0KbWVyZ2VfbmFtZXMgPC0gbmFtZXMoRGF0YSkNCg0KaWYoaWRlbnRpY2FsKG1lcmdlX25hbWVzW29yZGVyKG1lcmdlX25hbWVzKV0sIHRlc3RfbmFtZXNbb3JkZXIodGVzdF9uYW1lcyldKSl7ICAgICMgdGhlIG9yZGVyIG1hdHRlcnMgaW4gaWRlbnRpY2FsKCkNCiAgY2F0KCIqKk1lcmdlIHdhcyBzdWNjZXNmdWwqKiIpDQogIHJtKCJEYXRhX21lcmdlMSIsICJEYXRhX21lcmdlMiIsICJEYXRhX21lcmdlMyIsICJEYXRhQklPIiwgIkRhdGFERyIsICJEYXRhVHJ1c3QiLCAiRGF0YVZBUyIsICJ0ZXN0X25hbWVzIiwgIm1lcmdlX25hbWVzIikNCn1lbHNlIGNhdCgiKipNZXJnZSB1bnN1Y2Nlc2Z1bCoqIikgDQpgYGANCg0KDQojIERlcml2ZSBuZXcgdmFyaWFibGVzDQoNCmBgYHtyIGRlcml2ZV92YXIsIGhpZGU9VFJVRX0NCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMgRGVyaXZlIG5ldyB2YXJpYWJsZXMNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCkRhdGEkRF9WYXNTX1BveiA8LSBEYXRhWywgIlZhc1NfcG9zdFBveiJdIC0gRGF0YVssICJWYXNTX3ByZVBveiJdIA0KRGF0YSREX1Zhc1NfTmVnIDwtIERhdGFbLCAiVmFzU19wb3N0TmVnIl0gLSBEYXRhWywgIlZhc1NfcHJlTmVnIl0NCkRhdGEkRF9WYXNCX1BveiA8LSBEYXRhWywgIlZhc0JfcG9zdFBveiJdIC0gRGF0YVssICJWYXNCX3ByZVBveiJdIA0KRGF0YSREX1Zhc0JfTmVnIDwtIERhdGFbLCAiVmFzQl9wb3N0TmVnIl0gLSBEYXRhWywgIlZhc0JfcHJlTmVnIl0NCkRhdGEkRF9JT1NfUG96IDwtIERhdGFbLCAiSU9TX3Bvc3RQb3oiXSAtIERhdGFbLCAiSU9TX3ByZVBveiJdIA0KRGF0YSREX0lPU19OZWcgPC0gRGF0YVssICJJT1NfcG9zdE5lZyJdIC0gRGF0YVssICJJT1NfcHJlTmVnIl0NCg0KRGF0YSREX1NhbTFfUG96IDwtIERhdGFbLCAiU2FtMV9wb3N0UG96Il0gLSBEYXRhWywgIlNhbTFfcHJlUG96Il0gDQpEYXRhJERfU2FtMV9OZWcgPC0gRGF0YVssICJTYW0xX3Bvc3ROZWciXSAtIERhdGFbLCAiU2FtMV9wcmVOZWciXQ0KRGF0YSREX1NhbTJfUG96IDwtIERhdGFbLCAiU2FtMl9wb3N0UG96Il0gLSBEYXRhWywgIlNhbTJfcHJlUG96Il0gDQpEYXRhJERfU2FtMl9OZWcgPC0gRGF0YVssICJTYW0yX3Bvc3ROZWciXSAtIERhdGFbLCAiU2FtMl9wcmVOZWciXQ0KRGF0YSREX1NhbTNfUG96IDwtIERhdGFbLCAiU2FtM19wb3N0UG96Il0gLSBEYXRhWywgIlNhbTNfcHJlUG96Il0gDQpEYXRhJERfU2FtM19OZWcgPC0gRGF0YVssICJTYW0zX3Bvc3ROZWciXSAtIERhdGFbLCAiU2FtM19wcmVOZWciXQ0KDQpEYXRhJERfREdfUG96IDwtIERhdGFbLCAiREdfcG9zdFBvelRvdCJdIC0gRGF0YVssICJER19wcmVQb3pUb3QiXSANCkRhdGEkRF9ER19OZWcgPC0gRGF0YVssICJER19wb3N0TmVnVG90Il0gLSBEYXRhWywgIkRHX3ByZU5lZ1RvdCJdDQoNCkRhdGEkRF9UcnVzdE1pbl9Qb3ogPC0gRGF0YVssICJUcnVzdE1pblBvelBvc3QiXSAtIERhdGFbLCAiVHJ1c3RNaW5Qb3pQcmUiXSANCkRhdGEkRF9UcnVzdE1pbl9OZWcgPC0gRGF0YVssICJUcnVzdE1pbk5lZ1Bvc3QiXSAtIERhdGFbLCAiVHJ1c3RNaW5OZWdQcmUiXQ0KRGF0YSREX1RydXN0VG90X1BveiA8LSBEYXRhWywgIlRydXN0VG90UG96UG9zdCJdIC0gRGF0YVssICJUcnVzdFRvdFBvelByZSJdIA0KRGF0YSREX1RydXN0VG90X05lZyA8LSBEYXRhWywgIlRydXN0VG90TmVnUG9zdCJdIC0gRGF0YVssICJUcnVzdFRvdE5lZ1ByZSJdDQoNCkRhdGEkRF9Db3J0X1BveiA8LSBEYXRhWywgIkNvcnRfcG9zdF9Qb3oiXSAtIERhdGFbLCAiQ29ydF9wcmVfUG96Il0gDQpEYXRhJERfQ29ydF9OZWcgPC0gRGF0YVssICJDb3J0X3Bvc3RfTmVnIl0gLSBEYXRhWywgIkNvcnRfcHJlX05lZyJdDQpEYXRhJERfT3hfUG96IDwtIERhdGFbLCAiT3hfcG9zdF9Qb3oiXSAtIERhdGFbLCAiT3hfcHJlX1BveiJdIA0KRGF0YSREX094X05lZyA8LSBEYXRhWywgIk94X3Bvc3RfTmVnIl0gLSBEYXRhWywgIk94X3ByZV9OZWciXQ0KYGBgDQoNCg0KIyBEZWZpbmUgRnVuY3Rpb25zIA0KDQpgYGB7ciBkZWZfZnVuY19zdWJjaHVua3Bsb3QsIGhpZGU9VFJVRX0NCnN1YmNodW5raWZ5IDwtIGZ1bmN0aW9uKGcsIGZpZ19oZWlnaHQ9NywgZmlnX3dpZHRoPTUpIHsNCiAgZ19kZXBhcnNlZCA8LSBwYXN0ZTAoZGVwYXJzZSgNCiAgICBmdW5jdGlvbigpIHtnfQ0KICApLCBjb2xsYXBzZSA9ICcnKQ0KICANCiAgc3ViX2NodW5rIDwtIHBhc3RlMCgiDQogIGAiLCJgYHtyIHN1Yl9jaHVua18iLCBmbG9vcihydW5pZigxKSAqIDEwMDAwKSwgIiwgZmlnLmhlaWdodD0iLCBmaWdfaGVpZ2h0LCAiLCBmaWcud2lkdGg9IiwgZmlnX3dpZHRoLCAiLCBlY2hvPUZBTFNFfSIsDQogICJcbigiLCANCiAgICBnX2RlcGFyc2VkDQogICAgLCAiKSgpIiwNCiAgIlxuYCIsImBgDQogICIpDQogIA0KICBjYXQoa25pdHI6OmtuaXQodGV4dCA9IGtuaXRyOjprbml0X2V4cGFuZCh0ZXh0ID0gc3ViX2NodW5rKSwgcXVpZXQgPSBUUlVFKSkNCn0NCmBgYA0KDQpgYGB7ciBkZWZfZnVuYywgaGlkZT1UUlVFfQ0KI35+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KIyBEZWZpbmUgRnVuY3Rpb24gZm9yIG1pbmluZyBjb3JyZWxhdGlvbnMNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMjIEZ1bmN0aW9uIGZvciBwLXZhbHVlIHNpZ25pZmljYW5jZSAtLSBib3RoIGZvciBmdW5jX2FuY292YV9tdWx0aWJveCgpLCBHZXRfVG9wX1JlbGF0aW9uc2hpcHMoKSBhbmQgQ29ycmVsYXRpb25zX1dpdGhfT25lKCkNCnN0YXJzX3NpZ25pZiA8LSBmdW5jdGlvbihwdmFsKSB7DQogIHN0YXJzID0gIm5zIg0KICBpZihwdmFsIDw9IDAuMDAxKQ0KICAgIHN0YXJzID0gIioqKiINCiAgaWYocHZhbCA+IDAuMDAxICYgcHZhbCA8PSAwLjAxKQ0KICAgIHN0YXJzID0gIioqIg0KICBpZihwdmFsID4gMC4wMSAmIHB2YWwgPD0gMC4wNSkNCiAgICBzdGFycyA9ICIqIg0KICBpZihwdmFsID4gMC4wNSAmIHB2YWwgPD0gMC4xKQ0KICAgIHN0YXJzID0gIi4iDQogIHN0YXJzDQp9DQoNCiMjIEZ1bmN0aW9uIHRoYXQgcmV0dXJucyBjb3JyZWxhdGlvbnMgb2YgYWxsIHZhcmlhYmxlcyBpbiBkZXNjZW5kaW5nIG9yZGVyLg0KIyBBcmcgZm9yIHRocmVzaG9sZCB3aXRoIGRlZmF1bHQgYXQgLjMgd2lsbCBrZWVwIG9ubHkgY29ycmVsYW50aW9ucyBhYm92ZSAuMyBhbmQgYmVsb3cgLS4zLiBBbHNvIGhhcyB0aHJlc2hob2xkIGZvciBwLXZhbHVlLiANCkdldF9Ub3BfUmVsYXRpb25zaGlwcyA8LSBmdW5jdGlvbihkYXRhX3NldCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZD0wLjMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlX3RocmVzaG9sZD0wLjA1KSB7DQogIHJlcXVpcmUocHN5Y2gpDQogIHJlcXVpcmUoZHBseXIpDQogIGZlYXR1cmVfbmFtZXMgPC0gbmFtZXMoZGF0YV9zZXQpDQogICMgc3RyaXAgdmFyIG5hbWVzIHRvIGluZGV4IGZvciBwYWlyLXdpc2UgaWRlbnRpZmljYXRpb24NCiAgbmFtZXMoZGF0YV9zZXQpIDwtIHNlcSgxOm5jb2woZGF0YV9zZXQpKQ0KICAjIGNhbGN1bGF0ZSBjb3JyZWxhdGlvbiBhbmQgc2lnbmlmaWNhbmNlIG51bWJlcnMNCiAgY29yX2RhdGFfZGYgPC0gcHN5Y2g6OmNvcnIudGVzdChkYXRhX3NldCkNCiAgIyBhcHBseSB2YXIgbmFtZXMgdG8gY29ycmVsYXRpb24gbWF0cml4IG92ZXIgaW5kZXgNCiAgcm93bmFtZXMoY29yX2RhdGFfZGYkcikgPC0gZmVhdHVyZV9uYW1lcw0KICBjb2xuYW1lcyhjb3JfZGF0YV9kZiRyKSA8LSBmZWF0dXJlX25hbWVzDQogICMgdG9wIGNvciBhbmQgc2lnDQogIHJlbGF0aW9uc2hpcHNfc2V0IDwtIGNvcl9kYXRhX2RmJGNpWyxjKCdyJywncCcpXQ0KICAjIGFwcGx5IHZhciBuYW1lcyB0byBkYXRhIG92ZXIgaW5kZXggcGFpcnMNCiAgcmVsYXRpb25zaGlwc19zZXQkZmVhdHVyZV8xIDwtIGZlYXR1cmVfbmFtZXNbYXMubnVtZXJpYyhzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMocmVsYXRpb25zaGlwc19zZXQpLCAiLSIpLCBgW2AsIDEpKV0NCiAgcmVsYXRpb25zaGlwc19zZXQkZmVhdHVyZV8yIDwtIGZlYXR1cmVfbmFtZXNbYXMubnVtZXJpYygNCiAgICBzYXBwbHkoc3Ryc3BsaXQocm93bmFtZXMocmVsYXRpb25zaGlwc19zZXQpLCAiLSIpLCBgW2AsIDIpKV0NCiAgcmVsYXRpb25zaGlwc19zZXQgPC0gZHBseXI6OnNlbGVjdChyZWxhdGlvbnNoaXBzX3NldCwgZmVhdHVyZV8xLCBmZWF0dXJlXzIsIHIsIHApICU+JSBkcGx5cjo6cmVuYW1lKGNvcnJlbGF0aW9uID0gciwgcC52YWx1ZSA9IHApDQogICMgcmV0dXJuIG9ubHkgdGhlIG1vc3QgaW5zdGVyZXN0aW5nIHJlbGF0aW9uc2hpcHMNCiAgcmV0dXJuKGZpbHRlcihyZWxhdGlvbnNoaXBzX3NldCwgYWJzKGNvcnJlbGF0aW9uKSA+IGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgJg0KICAgICAgICAgICAgICAgICAgcC52YWx1ZSA8IHB2YWx1ZV90aHJlc2hvbGQpICU+JSANCiAgICAgICAgYXJyYW5nZShwLnZhbHVlKSAlPiUNCiAgICAgICAgbXV0YXRlKHAuc2lnbmlmID0gc2FwcGx5KHAudmFsdWUsIGZ1bmN0aW9uKHgpIHN0YXJzX3NpZ25pZih4KSkpKQ0KfQ0KDQojIyBGdW5jdGlvbiB0aGF0IHJldHVybnMgYWxsIGNvcnJlbGF0aW9uIGJldHdlZW4gbnVtZXJpYyB2YXJpYWJsZXMgYW5kIG9uZSBzcGVjaWZpYyB2YXJpYWJsZQ0KQ29ycmVsYXRpb25zX1dpdGhfT25lIDwtIGZ1bmN0aW9uKGRhdGFfc2V0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQ9MC4zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZV90aHJlc2hvbGQ9MC4wNSkgew0KICByZXF1aXJlKHBzeWNoKQ0KICByZXF1aXJlKGRwbHlyKQ0KICAjIHVzZSBhbGwgbnVtZXJpYyBjb2x1bW5zIG9ubHkNCiAgbnVtZXJpY19jb2xzIDwtIHVubGlzdChsYXBwbHkoZGF0YV9zZXQsIGlzLm51bWVyaWMpKQ0KICBkYXRhX3NldCA8LSBkYXRhX3NldFssIG51bWVyaWNfY29sc10gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICMgY2FsY3VsYXRlIGNvcnJlbGF0aW9uIGFuZCBzaWduaWZpY2FuY2UgbnVtYmVycw0KICBjb3JfZGF0YV9kZiA8LSBwc3ljaDo6Y29yci50ZXN0KGRhdGFfc2V0WywgbmFtZXMoZGF0YV9zZXQpICE9IHZhcmlhYmxlXSwgZGF0YV9zZXRbLCB2YXJpYWJsZV0sIG1pbmxlbmd0aCA9IDIwLCBhZGp1c3Q9Im5vbmUiKQ0KICAjIHRvcCBjb3IgYW5kIHNpZw0KICByZWxhdGlvbnNoaXBzX3NldCA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKGNvcl9kYXRhX2RmJHIsIGNvcl9kYXRhX2RmJHApKSAgICAgIyBzYW1lIGFzICBjb3JfZGF0YV9kZiRjaVssYygncicsJ3AnKV0NCiAgcmVsYXRpb25zaGlwc19zZXQgPC0gdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4ocmVsYXRpb25zaGlwc19zZXQsICJWYXJpYWJsZSIpICAgIyByZWxhdGlvbnNoaXBzX3NldCRWYXJpYWJsZSA8LSByb3duYW1lcyhyZWxhdGlvbnNoaXBzX3NldCkNCiAgY29sbmFtZXMocmVsYXRpb25zaGlwc19zZXQpIDwtIGMoIlZhcmlhYmxlIiwgImNvcnJlbGF0aW9uIiwgInAudmFsdWUiKQ0KICAjIHJldHVybiBvbmx5IHRoZSBtb3N0IGluc3RlcmVzdGluZyByZWxhdGlvbnNoaXBzDQogIGNhdCgiIyMjIyBDb3JyZWxhdGlvbnMgd2l0aCAiLCB2YXJpYWJsZSwgIlxuIikNCiAgcmV0dXJuKGZpbHRlcihyZWxhdGlvbnNoaXBzX3NldCwgYWJzKGNvcnJlbGF0aW9uKSA+IGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgJg0KICAgICAgICAgICAgICAgICAgcC52YWx1ZSA8IHB2YWx1ZV90aHJlc2hvbGQpICU+JSANCiAgICAgICAgICAgYXJyYW5nZShwLnZhbHVlKSAlPiUNCiAgICAgICAgICAgbXV0YXRlKHAuc2lnbmlmID0gc2FwcGx5KHAudmFsdWUsIGZ1bmN0aW9uKHgpIHN0YXJzX3NpZ25pZih4KSkpKSAlPiUNCiAgICAgICAgICAgdGliYmxlOjphcy50aWJibGUoKQ0KfSAgDQoNCg0KIyMgRnVuY3Rpb24gZm9yIHBsb3RpbmcgY29ycmVsYXRpb24gZGF0YSBmcmFtZXMgcmVzdWx0aW5nIGZyb20gR2V0X1RvcF9SZWxhdGlvbnNoaXBzIGFuZCBDb3JyZWxhdGlvbnNfV2l0aF9PbmUoKQ0KZnVuY19kb3RwbG90X2NvciA8LSBmdW5jdGlvbihkZil7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaHR0cHM6Ly93d3cuci1wa2cub3JnL3BrZy9nZ3B1YnINCiAgZG90cGxvdGNvcl9zY2FsZV9maWxsIDwtIGZ1bmN0aW9uKC4uLil7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEZpeCBjb2xvcnMgdG8gc2lnbmlmIGZhY3RvciBsZXZlbHMgZXZlbiBpZiBtaXNzaW5nDQogICAgZ2dwbG90Mjo6Om1hbnVhbF9zY2FsZSggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgJ2NvbG9yJywgDQogICAgICB2YWx1ZXMgPSBzZXROYW1lcygNCiAgICAgICAgYygiZGFya2dyZWVuIiwgImdyZWVuMyIsICJsYXduZ3JlZW4iLCAieWVsbG93IiwgInJlZCIpLCANCiAgICAgICAgYygiKioqIiwgIioqIiwgIioiLCAiLiIsICJucyIpKSwgDQogICAgICAuLi4NCiAgICApDQogIH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIA0KICBkdG9wbG90X3RoZW1lIDwtIA0KICAgIGdncHVicjo6dGhlbWVfcHVicigpICsNCiAgICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQ0KICANCiAgaWYoISJWYXJpYWJsZSIgJWluJSBjb2xuYW1lcyhkZikpeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW4gb2RlciB0byB3b3JrIGZvciBib3RoIEdldF9Ub3BfUmVsYXRpb25zaGlwcyBhbmQgQ29ycmVsYXRpb25zX1dpdGhfT25lKCkNCiAgZGYgPC0gDQogICAgZGYgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgIHVuaXRlKGNvcl9iZXR3ZWVuLCBjKCJmZWF0dXJlXzEiLCAiZmVhdHVyZV8yIiksIHNlcCA9ICIgWCAiKSAgICAgICAgICAgICAgICMgdW5pdGUgMiBjb2x1bW5zIHRvIHggbmFtZSBmcm9tIHBsb3QNCiAgfWVsc2UgZGYgPC0gZGYgJT4lIGRwbHlyOjpyZW5hbWUoY29yX2JldHdlZW4gPSBWYXJpYWJsZSkgICAgICAgICAgICAgICAgICAgICAgICMgY2hhbmdlIFZhcmlhYmxlIHRvIHggbmFtZSBmcm9tIHBsb3QNCiAgDQogIGRmICU+JQ0KICAgIGdncHVicjo6Z2dkb3RjaGFydCh4ID0gImNvcl9iZXR3ZWVuIiwgeSA9ICJjb3JyZWxhdGlvbiIsDQogICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gInAuc2lnbmlmIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIENvbG9yIGJ5IHNpZw0KICAgICAgICAgICAgICAgICAgICAgICAjICAgcGFsZXR0ZSA9IGMoIiMwMEFGQkIiLCAiI0U3QjgwMCIsICIjRkM0RTA3IiksICAgICAgICAgIyBDdXN0b20gY29sb3IgcGFsZXR0ZQ0KICAgICAgICAgICAgICAgICAgICAgICBzb3J0aW5nID0gImRlc2NlbmRpbmciLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBTb3J0IHZhbHVlIGluIGRlc2NlbmRpbmcgb3JkZXINCiAgICAgICAgICAgICAgICAgICAgICAgYWRkID0gInNlZ21lbnRzIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQWRkIHNlZ21lbnRzIGZyb20geSA9IDAgdG8gZG90cw0KICAgICAgICAgICAgICAgICAgICAgICBhZGQucGFyYW1zID0gbGlzdChjb2xvciA9ICJsaWdodGdyYXkiLCBzaXplID0gMiksICAgICAgICAgIyBDaGFuZ2Ugc2VnbWVudCBjb2xvciBhbmQgc2l6ZQ0KICAgICAgICAgICAgICAgICAgICAgICBncm91cCA9ICJwLnNpZ25pZiIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBPcmRlciBieSBncm91cHMNCiAgICAgICAgICAgICAgICAgICAgICAgZG90LnNpemUgPSA4LCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgTGFyZ2UgZG90IHNpemUNCiAgICAgICAgICAgICAgICAgICAgICAgeGxhYiA9ICIiLA0KICAgICAgICAgICAgICAgICAgICAgICByb3RhdGUgPSBUUlVFLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSb3RhdGUgdmVydGljYWxseQ0KICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IHJvdW5kKC4kY29ycmVsYXRpb24sIDEpLCAgICAgICAgICAgICAgICAgICAgICAgICAgIyBBZGQgbXBnIHZhbHVlcyBhcyBkb3QgbGFiZWxzDQogICAgICAgICAgICAgICAgICAgICAgIGZvbnQubGFiZWwgPSBsaXN0KGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IDAuNSksICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBBZGp1c3QgbGFiZWwgcGFyYW1ldGVycw0KICAgICAgICAgICAgICAgICAgICAgICBnZ3RoZW1lID0gZHRvcGxvdF90aGVtZSkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBnZ3Bsb3QyIHRoZW1lDQogICAgZG90cGxvdGNvcl9zY2FsZV9maWxsKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBGaXggY29sb3JzIHRvIHNpZ25pZiBmYWN0b3IgbGV2ZWxzIGV2ZW4gaWYgbWlzc2luZw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3IgPSAibGlnaHRncmF5IikNCn0NCg0KICANCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMgRGVmaW5lIEZ1bmN0aW9uIGZvciBQcmUtUG9zdCBQbG90cywgdCBDaGFuZ2UgYW5kIEFOQ09WQSBQb3N0DQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIyBGdW5jIHQgdGVzdCBzaSBib3hwbG90IHNpbXBsdQ0KZnVuY190X2JveCA8LSBmdW5jdGlvbihkZiwgaW5kLCBwcmVfdmFyLCBwb3N0X3Zhcil7DQogIGRmX21vZGlmIDwtDQogICAgZGYgJT4lDQogICAgc2VsZWN0KGluZCwgcHJlX3ZhciwgcG9zdF92YXIpICU+JSANCiAgICB0aWR5cjo6ZHJvcF9uYSgpICU+JQ0KICAgIGdhdGhlcihwcmVfdmFyLCBwb3N0X3Zhciwga2V5ID0gIkNvbmQiLCB2YWx1ZSA9ICJ2YWx1ZSIpICU+JSANCiAgICBtdXRhdGVfYXQodmFycyhjKDEsIDIpKSwgZnVucyhhcy5mYWN0b3IpKSAlPiUgDQogICAgbXV0YXRlKENvbmQgPSBmYWN0b3IoQ29uZCwgbGV2ZWxzID0gYyhwcmVfdmFyLCBwb3N0X3ZhcikpKSANCiAgDQogIHN0YXRfY29tcCA8LSBnZ3B1YnI6OmNvbXBhcmVfbWVhbnModmFsdWUgfiBDb25kLCBkYXRhID0gZGZfbW9kaWYsIG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFKQ0KICANCiAgc3RhdF9jb21wMiA8LQ0KICAgIGRmX21vZGlmICU+JSANCiAgICBkbyh0aWR5KHQudGVzdCguJHZhbHVlIH4gLiRDb25kLA0KICAgICAgICAgICAgICAgICAgIHBhaXJlZCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgZGF0YT0uKSkpDQogIA0KICBwbG90IDwtIA0KICAgIGdncHVicjo6Z2dwYWlyZWQoZGZfbW9kaWYsIHggPSAiQ29uZCIsIHkgPSAidmFsdWUiLCBpZCA9IGluZCwgDQogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJDb25kIiwgbGluZS5jb2xvciA9ICJncmF5IiwgbGluZS5zaXplID0gMC40LA0KICAgICAgICAgICAgICAgICAgICAgcGFsZXR0ZSA9IGMoIiMwMEFGQkIiLCAiI0ZDNEUwNyIpLCBsZWdlbmQgPSAibm9uZSIpICsNCiAgICAgIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fc2UsICBjb2xvdXIgPSAiZGFya3JlZCIpICsNCiAgICAgIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFLCBsYWJlbC54ID0gYXMubnVtZXJpYyhkZl9tb2RpZiRDb25kKS0wLjQsIGxhYmVsLnkgPSBtYXgoZGZfbW9kaWYkdmFsdWUpKzAuNSkgKyANCiAgICAgIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFLCBsYWJlbCA9ICJwLnNpZ25pZiIsIGNvbXBhcmlzb25zID0gbGlzdChjKHByZV92YXIsIHBvc3RfdmFyKSkpDQogIA0KICBjYXQocGFzdGUwKCIjIyMjICIsIHByZV92YXIsICIgIiwgcG9zdF92YXIsICJcbiIsICJcbiIpKQ0KICBwcmludChzdGF0X2NvbXApDQogIHByaW50KHN0YXRfY29tcDIpDQogIHByaW50KHBsb3QpDQp9DQoNCg0KZnVuY19hbmNvdmFfbXVsdGlib3ggPC0gZnVuY3Rpb24oZGYsIGluZCwgcHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEsIHByZV92YXJfYzIsIHBvc3RfdmFyX2MyKXsNCiAgDQogIGRpZmZfc2NvcmVfYzEgPC0gcGFzdGUwKHBvc3RfdmFyX2MxLCAiIC0gIiwgcHJlX3Zhcl9jMSkNCiAgZGlmZl9zY29yZV9jMiA8LSBwYXN0ZTAocG9zdF92YXJfYzIsICIgLSAiLCBwcmVfdmFyX2MyKQ0KICANCiAgIyMgUGxvdHMgYW5kIHAtdmFsdWVzIGZvciB0IHRlc3RzDQogIGRmX21vZGlmIDwtDQogICAgZGYgJT4lDQogICAgc2VsZWN0KGluZCwgcHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEsIHByZV92YXJfYzIsIHBvc3RfdmFyX2MyKSAlPiUgDQogICAgdGlkeXI6OmRyb3BfbmEoKSAlPiUNCiAgICBnYXRoZXIocHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEsIHByZV92YXJfYzIsIHBvc3RfdmFyX2MyLCBrZXkgPSAiQ29uZCIsIHZhbHVlID0gInZhbHVlIikgJT4lIA0KICAgIG11dGF0ZV9hdCh2YXJzKGMoMSwgMikpLCBmdW5zKGFzLmZhY3RvcikpICU+JSANCiAgICBtdXRhdGUoQ29uZCA9IGZhY3RvcihDb25kLCBsZXZlbHMgPSBjKHByZV92YXJfYzEsIHBvc3RfdmFyX2MxLCBwcmVfdmFyX2MyLCBwb3N0X3Zhcl9jMikpKSANCiAgDQogIHN0YXRfY29tcCA8LSBnZ3B1YnI6OmNvbXBhcmVfbWVhbnModmFsdWUgfiBDb25kLCBkYXRhID0gZGZfbW9kaWYsIG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFLCBwLmFkanVzdC5tZXRob2QgPSAiaG9sbSIpDQogIA0KICBwbG90IDwtDQogICAgZ2dwdWJyOjpnZ3BhaXJlZChkZl9tb2RpZiwgeCA9ICJDb25kIiwgeSA9ICJ2YWx1ZSIsIGlkID0gaW5kLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIkNvbmQiLCBsaW5lLmNvbG9yID0gImdyYXkiLCBsaW5lLnNpemUgPSAwLjQsDQogICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gYygiIzAwQUZCQiIsICIjRkM0RTA3IiwgIiMwMEFGQkIiLCAiI0ZDNEUwNyIpLCBsZWdlbmQgPSAibm9uZSIpICsNCiAgICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX3NlLCAgY29sb3VyID0gImRhcmtyZWQiKSArDQogICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9IFRSVUUsIGxhYmVsID0gInAuc2lnbmlmIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwueSA9IGMobWF4KGRmX21vZGlmJHZhbHVlKSArIDAuMSpJUVIoZGZfbW9kaWYkdmFsdWUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChkZl9tb2RpZiR2YWx1ZSkgKyAwLjEqSVFSKGRmX21vZGlmJHZhbHVlKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXEobWF4KGRmX21vZGlmJHZhbHVlKSArIDAuMypJUVIoZGZfbW9kaWYkdmFsdWUpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGRmX21vZGlmJHZhbHVlKSArIDAuOSpJUVIoZGZfbW9kaWYkdmFsdWUpLCBsZW5ndGgub3V0ID0gNCkpLCAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcGFyaXNvbnMgPSBsaXN0KGMocHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKHByZV92YXJfYzIsIHBvc3RfdmFyX2MyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYyhwb3N0X3Zhcl9jMSwgcHJlX3Zhcl9jMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMocHJlX3Zhcl9jMSwgcHJlX3Zhcl9jMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMocG9zdF92YXJfYzEsIHBvc3RfdmFyX2MyKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYyhwcmVfdmFyX2MxLCBwb3N0X3Zhcl9jMikpKQ0KICANCiAgIyMgRm9yIHR0ZXN0Q2hhbmdlIG9yIEFOQ09WQUNoYW5nZSAtIHdlIGRvIHR0ZXN0Q2hhbmdlIChQb3N0LVByZSkgaGVyZSwgYnV0IGl0IGlzbnQgdmVyeSBpbXBvcnRhbnQNCiAgZGZfbW9kaWYyIDwtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgZGYgJT4lDQogICAgc2VsZWN0KGluZCwgcHJlX3Zhcl9jMSwgcG9zdF92YXJfYzEsIHByZV92YXJfYzIsIHBvc3RfdmFyX2MyKSAlPiUNCiAgICB0aWR5cjo6ZHJvcF9uYSgpIA0KICBkZl9tb2RpZjJbZGlmZl9zY29yZV9jMV0gPC0gZGZfbW9kaWYyWywgcG9zdF92YXJfYzFdIC0gZGZfbW9kaWYyWywgcHJlX3Zhcl9jMV0NCiAgZGZfbW9kaWYyW2RpZmZfc2NvcmVfYzJdIDwtIGRmX21vZGlmMlssIHBvc3RfdmFyX2MyXSAtIGRmX21vZGlmMlssIHByZV92YXJfYzJdDQogIA0KICB0Q2hhbmdlIDwtIHQudGVzdChkZl9tb2RpZjJbLCBkaWZmX3Njb3JlX2MxXSwgZGZfbW9kaWYyWywgZGlmZl9zY29yZV9jMl0sIHBhaXJlZCA9IFRSVUUpDQogIA0KICAjIyBGb3IgZGVzY3JpcHRpdmVzIGJ5IDIgZmFjdG9ycyAoUHJlUG9zdCBhbmQgUG96TmVnKQ0KICBkZl9tb2RpZjMgPC0NCiAgICBkZiAlPiUNCiAgICBzZWxlY3QoaW5kLCBwcmVfdmFyX2MxLCBwb3N0X3Zhcl9jMSwgcHJlX3Zhcl9jMiwgcG9zdF92YXJfYzIpICU+JQ0KICAgIHRpZHlyOjpkcm9wX25hKCkgJT4lDQogICAgZ2F0aGVyKHByZV92YXJfYzEsIHBvc3RfdmFyX2MxLCBwcmVfdmFyX2MyLCBwb3N0X3Zhcl9jMiwga2V5ID0gIkNvbmQiLCB2YWx1ZSA9ICJ2YWx1ZSIpICU+JQ0KICAgIG11dGF0ZShQcmVQb3N0ID0gY2FzZV93aGVuKHN0cmluZ3I6OnN0cl9kZXRlY3QoLiQiQ29uZCIsICJwcmV8UHJlIikgfiAiUHJlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfZGV0ZWN0KC4kIkNvbmQiLCAicG9zdHxQb3N0IikgfiAiUG9zdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgICBQb3pOZWcgPSBjYXNlX3doZW4oc3RyaW5ncjo6c3RyX2RldGVjdCguJCJDb25kIiwgInBvenxQb3oiKSB+ICJQb3oiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5ncjo6c3RyX2RldGVjdCguJCJDb25kIiwgIm5lZ3xOZWciKSB+ICJOZWciLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8pKSAlPiUNCiAgICBtdXRhdGUoUHJlUG9zdCA9IGFzLmZhY3RvcihQcmVQb3N0KSwNCiAgICAgICAgICAgUG96TmVnID0gYXMuZmFjdG9yKFBvek5lZykpDQogIA0KICAjIyBGb3IgQU5DT1ZBUG9zdCAtIHRoaXMgaXMgd2hhdCB3ZSB1c2UNCiAgZGZfbW9kaWY0IDwtDQogICAgZGZfbW9kaWYzICU+JQ0KICAgIHNlbGVjdCgtIkNvbmQiKSAlPiUNCiAgICBzcHJlYWQoIlByZVBvc3QiLCAidmFsdWUiKQ0KICANCiAgIyMgTW9kZWxzIChoZXJlIHdlIHVzZSBBTkNPVkFQb3N0KSAgICAjIGh0dHBzOi8vbS1jbGFyay5naXRodWIuaW8vZG9jcy9taXhlZE1vZGVscy9hbm92YW1peGVkLmh0bWwjaW50cm9kdWN0aW9uDQogIGZ1bGxfYW5jb3ZhUG9zdCA8LSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhpcyBpcyBiZXR0ZXIgdGhhbiB1c2luZyBsbSgpIGFuZCBnbGh0KCkNCiAgICAgIGptdjo6YW5jb3ZhKA0KICAgICAgICBmb3JtdWxhID0gUG9zdCB+IFByZSArIFBvek5lZywNCiAgICAgICAgZGF0YSA9IGRmX21vZGlmNCwNCiAgICAgICAgaG9tbyA9IFRSVUUsDQogICAgICAgIHNzID0gIjMiLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgIHBvc3RIb2MgPSB+IFBvek5lZywNCiAgICAgICAgcG9zdEhvY0NvcnIgPSBsaXN0KCJ0dWtleSIpLA0KICAgICAgICBlZmZlY3RTaXplID0gbGlzdCgiZXRhIiwgInBhcnRFdGEiKQ0KICAgICAgKQ0KICANCiAgICAgICMgbW9kX2FuY292YVBvc3QgPC0gbG0oUG9zdCB+IFByZSArIFBvek5lZywgZGF0YSA9IGRmX21vZGlmNCkgICAgICAgICAgICAjIHRoaXMgaXMgYSBDb3ZhcmlhdGUgU2Vjb25kIG1vZGVsDQogICAgICAjIG1vZF9hbmNvdmFQb3N0X3NzMyA8LSBjYXI6OkFub3ZhKG1vZF9hbmNvdmFQb3N0LCB0eXBlID0gIklJSSIpICAgICAgICAgIyBUeXBlIElJSSBzdW1zIG9mIHNxdWFyZXM7IHNlZSBBbmR5IEZpZWxkcyAyMDEyDQogICAgICAjIHBvc3RIb2NzIDwtIG11bHRjb21wOjpnbGh0KG1vZF9hbmNvdmFQb3N0LCBsaW5mY3QgPSBtdWx0Y29tcDo6bWNwKFBvek5lZyA9ICJUdWtleSIpKSAgIyBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSBhZGp1c3RlZCBtZWFucywNCiAgICAgICMgc3VtX3Bvc3RIb2NzIDwtIHN1bW1hcnkocG9zdEhvY3MpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBUdWtleSBvciBEdW5uZXR0knMgcG9zdCBob2MgdGVzdHMNCiAgICAgICMgY29uZl9wb3N0SG9jcyA8LSBjb25maW50KHBvc3RIb2NzKQ0KICBzY2F0dGVyIDwtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQ2hlY2sgZm9yIGhvbW9nZW5laXR5IG9mIHJlZ3Jlc3Npb24gc2xvcGVzDQogICAgZ2dwbG90KGRmX21vZGlmNCwgYWVzKFByZSwgUG9zdCwgY29sb3VyID0gUG96TmVnKSkgKw0KICAgIGdlb21fcG9pbnQoYWVzKHNoYXBlID0gUG96TmVnKSwgc2l6ZSA9IDMpICsNCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBhZXMoZmlsbCA9IFBvek5lZyksIGFscGhhID0gMC4xKQ0KICAgIA0KICANCiAgIyMgT3RoZXIgTW9kZWxzIHRoYXQgd29yayBmb3IgdGhpcyBkYXRlDQogICMgbW9kX2FuY292YVBvc3QgPC0gbG0ocG9zdCB+IHByZSArIHRyZWF0KSAgICAgICMgZXhhY3RseSB0aGUgc2FtZSB3aXRoIGFvdihwb3N0IH4gcHJlICsgdHJlYXQpDQogICMgc3VtbWFyeShtb2RfYW5jb3ZhUG9zdCkNCiAgIyANCiAgIyBtb2RfYW5vdmFSTSA8LSBhb3Yoc2NvcmUgfiB0cmVhdCp0aW1lICsgRXJyb3IoaWQpLCBkZmxvbmcpDQogICMgc3VtbWFyeShtb2RfYW5vdmFSTSkNCiAgIyANCiAgIyBtb2RfbG1lIDwtIGxtZTQ6OmxtZXIoc2NvcmUgfiB0cmVhdCp0aW1lICsgKDF8aWQpLCBkYXRhPWRmbG9uZykNCiAgIyBhbm92YShsbWVNb2RlbCkNCiAgDQogICMjIE91dHB1dA0KICBwcmludChwbG90KQ0KICBjYXQocGFzdGUwKCIjIyMjICIsIHByZV92YXJfYzEsICIgIiwgcG9zdF92YXJfYzEsICIgIiwgcHJlX3Zhcl9jMiwgIiAiLCBwb3N0X3Zhcl9jMiwgIlxuIiwgIlxuIikpDQogIA0KICBjYXQoIiMjIyMgRGVzY3JpcHRpdmVzIikNCiAgcHN5Y2g6OmRlc2NyaWJlQnkoZGZfbW9kaWYzWywgInZhbHVlIl0sIGxpc3QoZGZfbW9kaWYzWywgIlByZVBvc3QiXSwgZGZfbW9kaWYzWywgIlBvek5lZyJdKSwgbWF0ID0gVFJVRSkgJT4lIA0KICAgIGFzLnRpYmJsZSgpICU+JQ0KICAgIHByaW50KCkNCiAgY2F0KCJcbiIpDQogIA0KICBwcmludChzdGF0X2NvbXApDQogIGNhdCgiXG4iKQ0KICANCiAgY2F0KCIjIyMjIHQgQ2hhbmdlIikNCiAgdGlkeSh0Q2hhbmdlKSAlPiUgcHJpbnQoKQ0KICBjYXQoIlxuIikNCiAgDQogIGNhdCgiIyMjIyBBTkNPVkEgUG9zdCIpDQogIGNhdCgiXG4iKQ0KICBjYXQoIiMjIyMjIEhvbW9nZW5laXR5IHRlc3QiKQ0KICBwcmludCh0aWJibGU6OmFzLnRpYmJsZShmdWxsX2FuY292YVBvc3QkYXNzdW1wJGhvbW8pKQ0KICBjYXQoIiMjIyMjIEFOQ09WQSBvdXRwdXQiKQ0KICBwcmludCh0aWJibGU6OmFzLnRpYmJsZShmdWxsX2FuY292YVBvc3QkbWFpbikpDQogICMgdGlkeShtb2RfYW5jb3ZhUG9zdCkgJT4lIA0KICAjICAgbXV0YXRlKHAuc2lnbmlmID0gc2FwcGx5KHAudmFsdWUsIGZ1bmN0aW9uKHgpIHN0YXJzX3NpZ25pZih4KSkpICU+JSANCiAgIyAgIHByaW50KCkNCiAgIyBjYXQoIlxuIikNCiAgY2F0KCIjIyMjIyBQb3N0IEhvYyIpDQogIHByaW50KHRpYmJsZTo6YXMudGliYmxlKGZ1bGxfYW5jb3ZhUG9zdCRwb3N0SG9jW1sxXV0pKQ0KICAjIHRpZHkoc3VtX3Bvc3RIb2NzKSAlPiUgDQogICMgICBtdXRhdGUocC5zaWduaWYgPSBzYXBwbHkocC52YWx1ZSwgZnVuY3Rpb24oeCkgc3RhcnNfc2lnbmlmKHgpKSkgJT4lIA0KICAjICAgcHJpbnQoKQ0KICBjYXQoIlxuIikNCiAgY2F0KCIjIyMjIyBIb21vZ2VuZWl0eSBvZiByZWdyZXNzaW9uIHNsb3BlcyIpDQogIHN1YmNodW5raWZ5KHBsb3Qoc2NhdHRlciksIDUsIDUpDQp9DQpgYGANCg0KDQojIEFuYWx5c2VzDQoNCiMjIENvcnJlbGF0aW9ucyBiZXR3ZWVuIERpZmZyZW5jZSBTY29yZXMgd2l0aCBvdGhlciB2YXJpYWJsZXMNCg0KYGBge3IgRF9jb3Jfb3RoZXIsIHJlc3VsdHM9J2FzaXMnfQ0KIyMgQ29ycmVsYXRpb25zIGJldHdlZW4gRGlmZnJlbmNlIFNjb3JlcyB3aXRoIG90aGVyIHZhcmlhYmxlcw0KQ29ycmVsYXRpb25zX1dpdGhfT25lKERhdGFbLC1jKDE6NyldLCB2YXJpYWJsZSA9ICJEX094X1BveiIsIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAgIyBEX0RHX1BveiwgTmVvX0M0LCBOZW9fRTMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9PeF9OZWciLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgbmltaWMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9Db3J0X1BveiIsIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAjIERfU2FtMV9Qb3osIERfVHJ1c3RUb3RfUG96LCBTdGFpUw0KQ29ycmVsYXRpb25zX1dpdGhfT25lKERhdGFbLC1jKDE6NyldLCB2YXJpYWJsZSA9ICJEX0NvcnRfTmVnIiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIG5pbWljDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfVmFzU19Qb3oiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgbmltaWMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9WYXNTX05lZyIsIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAgIyBEX1RydXN0VG90X05lZw0KQ29ycmVsYXRpb25zX1dpdGhfT25lKERhdGFbLC1jKDE6NyldLCB2YXJpYWJsZSA9ICJEX1Zhc0JfUG96IiwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMDUpICAjIERfU2FtMV9Qb3oNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9WYXNCX05lZyIsIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAgIyBEX1NhbTFfTmVnDQpDb3JyZWxhdGlvbnNfV2l0aF9PbmUoRGF0YVssLWMoMTo3KV0sIHZhcmlhYmxlID0gIkRfSU9TX1BveiIsIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAgIyBuaW1pYw0KQ29ycmVsYXRpb25zX1dpdGhfT25lKERhdGFbLC1jKDE6NyldLCB2YXJpYWJsZSA9ICJEX0lPU19OZWciLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgbmltaWMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9ER19Qb3oiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgbmltaWMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9ER19OZWciLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgbmltaWMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9UcnVzdE1pbl9Qb3oiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgbmltaWMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9UcnVzdE1pbl9OZWciLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgbmltaWMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9UcnVzdFRvdF9Qb3oiLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgbmltaWMNCkNvcnJlbGF0aW9uc19XaXRoX09uZShEYXRhWywtYygxOjcpXSwgdmFyaWFibGUgPSAiRF9UcnVzdFRvdF9OZWciLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgICMgRF9WYXNTX05lZw0KYGBgDQoNCg0KIyMgU2ltcGxlIGJlZm9yZS1hZnRlciBhbmFseXNlcyB3aXRoIHQgdGVzdA0KDQpgYGB7ciB0X3Rlc3QsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTcsIHJlc3VsdHM9J2FzaXMnfQ0KIyMgU2ltcGxlIGJlZm9yZS1hZnRlciBhbmFseXNlcyB3aXRoIHQgdGVzdA0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIk94X3ByZV9Qb3oiLCAiT3hfcG9zdF9Qb3oiKSAgIyBzaWcgIA0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIk94X3ByZV9OZWciLCAiT3hfcG9zdF9OZWciKSAgIyBzaWcNCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJDb3J0X3ByZV9Qb3oiLCAiQ29ydF9wb3N0X1BveiIpICAjIG51ICANCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJDb3J0X3ByZV9OZWciLCAiQ29ydF9wb3N0X05lZyIpICAjIHNpZw0KDQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiVmFzU19wcmVQb3oiLCAiVmFzU19wb3N0UG96IikgICMgc2lnICANCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJWYXNTX3ByZU5lZyIsICJWYXNTX3Bvc3ROZWciKSAgIyBudQ0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIlZhc0JfcHJlUG96IiwgIlZhc0JfcG9zdFBveiIpICAjIHNpZyAgDQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiVmFzQl9wcmVOZWciLCAiVmFzQl9wb3N0TmVnIikgICMgbnUNCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJTYW0xX3ByZVBveiIsICJTYW0xX3Bvc3RQb3oiKSAgIyBzaWcgIA0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIlNhbTFfcHJlTmVnIiwgIlNhbTFfcG9zdE5lZyIpICAjIG51DQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiU2FtMl9wcmVQb3oiLCAiU2FtMl9wb3N0UG96IikgICMgbnUgIA0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIlNhbTJfcHJlTmVnIiwgIlNhbTJfcG9zdE5lZyIpICAjIG51DQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiSU9TX3ByZVBveiIsICJJT1NfcG9zdFBveiIpICAjIHNpZyAgDQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiSU9TX3ByZU5lZyIsICJJT1NfcG9zdE5lZyIpICAjIG51DQoNCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJER19wcmVQb3pUb3QiLCAiREdfcG9zdFBvelRvdCIpICAjIG51ICANCmZ1bmNfdF9ib3goRGF0YSwgIkluZGljYXRpdiIsICJER19wcmVOZWdUb3QiLCAiREdfcG9zdE5lZ1RvdCIpICAjIHNpZw0KDQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiVHJ1c3RNaW5Qb3pQcmUiLCAiVHJ1c3RNaW5Qb3pQb3N0IikgICMgbnUgIA0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIlRydXN0TWluTmVnUHJlIiwgIlRydXN0TWluTmVnUG9zdCIpICAjIG51DQpmdW5jX3RfYm94KERhdGEsICJJbmRpY2F0aXYiLCAiVHJ1c3RUb3RQb3pQcmUiLCAiVHJ1c3RUb3RQb3pQb3N0IikgICMgbnUgIA0KZnVuY190X2JveChEYXRhLCAiSW5kaWNhdGl2IiwgIlRydXN0VG90TmVnUHJlIiwgIlRydXN0VG90TmVnUG9zdCIpICAjIG51DQpgYGANCg0KDQojIyB0Q2hhbmNlIGFuZCBBTkNPVkFQb3N0DQoNCmBgYHtyIHRfQ2hhbmdlX0FOQ09WQV9Qb3N0cywgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTEyLCByZXN1bHRzPSdhc2lzJ30NCiMjIHRDaGFuY2UgYW5kIEFOQ09WQVBvc3QgDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIk94X3ByZV9Qb3oiLCAiT3hfcG9zdF9Qb3oiLCAiT3hfcHJlX05lZyIsICJPeF9wb3N0X05lZyIpDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIkNvcnRfcHJlX1BveiIsICJDb3J0X3Bvc3RfUG96IiwgIkNvcnRfcHJlX05lZyIsICJDb3J0X3Bvc3RfTmVnIikNCg0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YSwgIkluZGljYXRpdiIsICJWYXNTX3ByZVBveiIsICJWYXNTX3Bvc3RQb3oiLCAiVmFzU19wcmVOZWciLCAiVmFzU19wb3N0TmVnIikNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGEsICJJbmRpY2F0aXYiLCAiVmFzQl9wcmVQb3oiLCAiVmFzQl9wb3N0UG96IiwgIlZhc0JfcHJlTmVnIiwgIlZhc0JfcG9zdE5lZyIpDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIlNhbTFfcHJlUG96IiwgIlNhbTFfcG9zdFBveiIsICJTYW0xX3ByZU5lZyIsICJTYW0xX3Bvc3ROZWciKQ0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YSwgIkluZGljYXRpdiIsICJTYW0yX3ByZVBveiIsICJTYW0yX3Bvc3RQb3oiLCAiU2FtMl9wcmVOZWciLCAiU2FtMl9wb3N0TmVnIikNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGEsICJJbmRpY2F0aXYiLCAiSU9TX3ByZVBveiIsICJJT1NfcG9zdFBveiIsICJJT1NfcHJlTmVnIiwgIklPU19wb3N0TmVnIikgDQoNCmZ1bmNfYW5jb3ZhX211bHRpYm94KERhdGEsICJJbmRpY2F0aXYiLCAiREdfcHJlUG96VG90IiwgIkRHX3Bvc3RQb3pUb3QiLCAiREdfcHJlTmVnVG90IiwgIkRHX3Bvc3ROZWdUb3QiKSANCg0KZnVuY19hbmNvdmFfbXVsdGlib3goRGF0YSwgIkluZGljYXRpdiIsICJUcnVzdE1pblBvelByZSIsICJUcnVzdE1pblBvelBvc3QiLCAiVHJ1c3RNaW5OZWdQcmUiLCAiVHJ1c3RNaW5OZWdQb3N0IikgDQpmdW5jX2FuY292YV9tdWx0aWJveChEYXRhLCAiSW5kaWNhdGl2IiwgIlRydXN0VG90UG96UHJlIiwgIlRydXN0VG90UG96UG9zdCIsICJUcnVzdFRvdE5lZ1ByZSIsICJUcnVzdFRvdE5lZ1Bvc3QiKSANCmBgYA0KDQoNCiMjIENvcnJlbGF0aW9ucyB3aXRoIE94eQ0KDQpgYGB7ciBjb3JfT3gsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTcsIHJlc3VsdHM9J2FzaXMnfQ0KIyMgTWluaW5nIENvcnJlbGF0aW9ucyB3aXRoIE94eQ0KZGZfT3h5QWxsX2NvciA8LQ0KICBHZXRfVG9wX1JlbGF0aW9uc2hpcHMoRGF0YVssLWMoMTo3KV0sIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjA1KSAlPiUNCiAgICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lDQogICAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIk94IiwgLikpKSAgICAgICAgICAgICAgICAgICAgICAgICAgICMgb25seSBPeHksIGJ1dCBib3RoIFByZSBhbmQgUG9zdCBPeHkNCg0KZGZfT3h5QWxsX2NvciAlPiUgICAgICAgICAgICAgIA0KICAgIHByaW50KG4gPSBJbmYpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KZGZfT3h5QWxsX2NvciAlPiUNCiAgZnVuY19kb3RwbG90X2NvcigpDQogDQojIENvcnJlbGF0aW9ucyBvbmx5IG9uIFByZSBtZWFzdXJlcyB3aXRoIE94eSAtLSBub3RoaW5nDQpkZl9PeHlQcmVfY29yIDwtIA0KICBHZXRfVG9wX1JlbGF0aW9uc2hpcHMoRGF0YVssLWMoMTo3KV0sIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjEpICU+JQ0KICAgIGRwbHlyOjphc190aWJibGUoKSAlPiUNCiAgICBmaWx0ZXJfYXQodmFycyhmZWF0dXJlXzEsIGZlYXR1cmVfMiksIGFsbF92YXJzKGdyZXBsKCJwcmV8UHJlIiwgLikpKSAlPiUNCiAgICBkcGx5cjo6ZmlsdGVyX2FsbChhbnlfdmFycyhncmVwbCgiT3giLCAuKSkpIA0KDQpkZl9PeHlQcmVfY29yICU+JQ0KICBwcmludChuID0gSW5mKQ0KDQojIENvcnJlbGF0aW9ucyBvbmx5IG9uIFBvc3QgbWVhc3VyZXMgd2l0aCBPeHkNCmRmX094eVBvc3RfY29yIDwtDQogIEdldF9Ub3BfUmVsYXRpb25zaGlwcyhEYXRhWywtYygxOjcpXSwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMSkgJT4lDQogICAgZHBseXI6OmFzX3RpYmJsZSgpICU+JQ0KICAgIGZpbHRlcl9hdCh2YXJzKGZlYXR1cmVfMSwgZmVhdHVyZV8yKSwgYWxsX3ZhcnMoZ3JlcGwoInBvc3R8UG9zdCIsIC4pKSkgJT4lDQogICAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIk94IiwgLikpKSANCg0KZGZfT3h5UG9zdF9jb3IgJT4lDQogICAgcHJpbnQobiA9IEluZikNCmRmX094eVBvc3RfY29yICU+JSANCiAgZnVuY19kb3RwbG90X2NvcigpDQpgYGANCg0KDQojIyBDb3JyZWxhdGlvbnMgd2l0aCBTdGVzcw0KDQpgYGB7ciBjb3JfVmFzUywgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NywgcmVzdWx0cz0nYXNpcyd9DQojIyBNaW5pbmcgQ29ycmVsYXRpb25zIHdpdGggVmFzUw0KZGZfVmFzU0FsbF9jb3IgPC0NCiAgR2V0X1RvcF9SZWxhdGlvbnNoaXBzKERhdGFbLC1jKDE6NyldLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgJT4lDQogICAgZHBseXI6OmFzX3RpYmJsZSgpICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXJfYWxsKGFueV92YXJzKGdyZXBsKCJWYXNTIiwgLikpKSAgICAgICAgICAgICAgICAgICAgICAgICAgICMgb25seSBWYXNTLCBidXQgYm90aCBQcmUgYW5kIFBvc3QgVmFzUw0KDQpkZl9WYXNTQWxsX2NvciAlPiUgICAgICAgICAgICAgIA0KICAgIHByaW50KG4gPSBJbmYpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQojIENvcnJlbGF0aW9ucyBvbmx5IG9uIFByZSBtZWFzdXJlcyB3aXRoIFZhc1MNCmRmX1Zhc1NQcmVfY29yIDwtIA0KICBHZXRfVG9wX1JlbGF0aW9uc2hpcHMoRGF0YVssLWMoMTo3KV0sIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjEpICU+JQ0KICAgIGRwbHlyOjphc190aWJibGUoKSAlPiUNCiAgICBmaWx0ZXJfYXQodmFycyhmZWF0dXJlXzEsIGZlYXR1cmVfMiksIGFsbF92YXJzKGdyZXBsKCJwcmV8UHJlIiwgLikpKSAlPiUNCiAgICBkcGx5cjo6ZmlsdGVyX2FsbChhbnlfdmFycyhncmVwbCgiVmFzUyIsIC4pKSkgDQoNCmRmX1Zhc1NQcmVfY29yICU+JQ0KICBwcmludChuID0gSW5mKQ0KZGZfVmFzU1ByZV9jb3IgJT4lIA0KICBmdW5jX2RvdHBsb3RfY29yKCkNCg0KIyBDb3JyZWxhdGlvbnMgb25seSBvbiBQb3N0IG1lYXN1cmVzIHdpdGggVmFzUw0KZGZfVmFzU1Bvc3RfY29yIDwtDQogIEdldF9Ub3BfUmVsYXRpb25zaGlwcyhEYXRhWywtYygxOjcpXSwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMSkgJT4lDQogICAgZHBseXI6OmFzX3RpYmJsZSgpICU+JQ0KICAgIGZpbHRlcl9hdCh2YXJzKGZlYXR1cmVfMSwgZmVhdHVyZV8yKSwgYWxsX3ZhcnMoZ3JlcGwoInBvc3R8UG9zdCIsIC4pKSkgJT4lDQogICAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIlZhc1MiLCAuKSkpIA0KDQpkZl9WYXNTUG9zdF9jb3IgJT4lDQogICAgcHJpbnQobiA9IEluZikNCmRmX1Zhc1NQb3N0X2NvciAlPiUgDQogIGZ1bmNfZG90cGxvdF9jb3IoKQ0KYGBgDQoNCg0KIyMgQ29ycmVsYXRpb25zIHdpdGggV2VsbCBCZWluZw0KDQpgYGB7ciBjb3JfVmFzQiwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NywgcmVzdWx0cz0nYXNpcyd9DQojIyBNaW5pbmcgQ29ycmVsYXRpb25zIHdpdGggVmFzQg0KZGZfVmFzQkFsbF9jb3IgPC0NCiAgR2V0X1RvcF9SZWxhdGlvbnNoaXBzKERhdGFbLC1jKDE6NyldLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgJT4lDQogIGRwbHlyOjphc190aWJibGUoKSAlPiUNCiAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIlZhc0IiLCAuKSkpICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBvbmx5IFZhc0IsIGJ1dCBib3RoIFByZSBhbmQgUG9zdCBWYXNCDQoNCmRmX1Zhc0JBbGxfY29yICU+JSAgICAgICAgICAgICAgDQogIHByaW50KG4gPSBJbmYpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KDQojIENvcnJlbGF0aW9ucyBvbmx5IG9uIFByZSBtZWFzdXJlcyB3aXRoIFZhc0INCmRmX1Zhc0JQcmVfY29yIDwtIA0KICBHZXRfVG9wX1JlbGF0aW9uc2hpcHMoRGF0YVssLWMoMTo3KV0sIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjEpICU+JQ0KICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lDQogIGZpbHRlcl9hdCh2YXJzKGZlYXR1cmVfMSwgZmVhdHVyZV8yKSwgYWxsX3ZhcnMoZ3JlcGwoInByZXxQcmUiLCAuKSkpICU+JQ0KICBkcGx5cjo6ZmlsdGVyX2FsbChhbnlfdmFycyhncmVwbCgiVmFzQiIsIC4pKSkgDQoNCmRmX1Zhc0JQcmVfY29yICU+JQ0KICBwcmludChuID0gSW5mKQ0KZGZfVmFzQlByZV9jb3IgJT4lDQogIGZ1bmNfZG90cGxvdF9jb3IoKQ0KDQojIENvcnJlbGF0aW9ucyBvbmx5IG9uIFBvc3QgbWVhc3VyZXMgd2l0aCBWYXNCDQpkZl9WYXNCUG9zdF9jb3IgPC0NCiAgR2V0X1RvcF9SZWxhdGlvbnNoaXBzKERhdGFbLC1jKDE6NyldLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4xKSAlPiUNCiAgZHBseXI6OmFzX3RpYmJsZSgpICU+JQ0KICBmaWx0ZXJfYXQodmFycyhmZWF0dXJlXzEsIGZlYXR1cmVfMiksIGFsbF92YXJzKGdyZXBsKCJwb3N0fFBvc3QiLCAuKSkpICU+JQ0KICBkcGx5cjo6ZmlsdGVyX2FsbChhbnlfdmFycyhncmVwbCgiVmFzQiIsIC4pKSkgDQoNCmRmX1Zhc0JQb3N0X2NvciAlPiUNCiAgcHJpbnQobiA9IEluZikNCmRmX1Zhc0JQb3N0X2NvciAlPiUgDQogIGZ1bmNfZG90cGxvdF9jb3IoKQ0KYGBgDQoNCg0KIyMgQ29ycmVsYXRpb25zIHdpdGggSU9TIA0KDQpgYGB7ciBjb3JfSU9TLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD03LCByZXN1bHRzPSdhc2lzJ30NCiMjIE1pbmluZyBDb3JyZWxhdGlvbnMgd2l0aCBJT1MNCmRmX0lPU0FsbF9jb3IgPC0NCiAgR2V0X1RvcF9SZWxhdGlvbnNoaXBzKERhdGFbLC1jKDE6NyldLCBjb3JyZWxhdGlvbl9hYnNfdGhyZXNob2xkID0gMC4yLCBwdmFsdWVfdGhyZXNob2xkID0gMC4wNSkgJT4lDQogIGRwbHlyOjphc190aWJibGUoKSAlPiUNCiAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIklPUyIsIC4pKSkgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG9ubHkgSU9TLCBidXQgYm90aCBQcmUgYW5kIFBvc3QgSU9TDQoNCmRmX0lPU0FsbF9jb3IgJT4lICAgICAgICAgICAgICANCiAgcHJpbnQobiA9IEluZikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgDQoNCiMgQ29ycmVsYXRpb25zIG9ubHkgb24gUHJlIG1lYXN1cmVzIHdpdGggSU9TDQpkZl9JT1NQcmVfY29yIDwtIA0KICBHZXRfVG9wX1JlbGF0aW9uc2hpcHMoRGF0YVssLWMoMTo3KV0sIGNvcnJlbGF0aW9uX2Fic190aHJlc2hvbGQgPSAwLjIsIHB2YWx1ZV90aHJlc2hvbGQgPSAwLjEpICU+JQ0KICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lDQogIGZpbHRlcl9hdCh2YXJzKGZlYXR1cmVfMSwgZmVhdHVyZV8yKSwgYWxsX3ZhcnMoZ3JlcGwoInByZXxQcmUiLCAuKSkpICU+JQ0KICBkcGx5cjo6ZmlsdGVyX2FsbChhbnlfdmFycyhncmVwbCgiSU9TIiwgLikpKSANCg0KZGZfSU9TUHJlX2NvciAlPiUNCiAgcHJpbnQobiA9IEluZikNCmRmX0lPU1ByZV9jb3IgJT4lDQogIGZ1bmNfZG90cGxvdF9jb3IoKQ0KDQojIENvcnJlbGF0aW9ucyBvbmx5IG9uIFBvc3QgbWVhc3VyZXMgd2l0aCBJT1MNCmRmX0lPU1Bvc3RfY29yIDwtDQogIEdldF9Ub3BfUmVsYXRpb25zaGlwcyhEYXRhWywtYygxOjcpXSwgY29ycmVsYXRpb25fYWJzX3RocmVzaG9sZCA9IDAuMiwgcHZhbHVlX3RocmVzaG9sZCA9IDAuMSkgJT4lDQogIGRwbHlyOjphc190aWJibGUoKSAlPiUNCiAgZmlsdGVyX2F0KHZhcnMoZmVhdHVyZV8xLCBmZWF0dXJlXzIpLCBhbGxfdmFycyhncmVwbCgicG9zdHxQb3N0IiwgLikpKSAlPiUNCiAgZHBseXI6OmZpbHRlcl9hbGwoYW55X3ZhcnMoZ3JlcGwoIklPUyIsIC4pKSkgDQoNCmRmX0lPU1Bvc3RfY29yICU+JQ0KICBwcmludChuID0gSW5mKQ0KZGZfSU9TUG9zdF9jb3IgJT4lIA0KICBmdW5jX2RvdHBsb3RfY29yKCkNCmBgYA0KDQoNCjxicj4NCg0KDQoNCjwhLS0gU2Vzc2lvbiBJbmZvIGFuZCBMaWNlbnNlIC0tPg0KDQo8YnI+DQoNCiMgU2Vzc2lvbiBJbmZvDQpgYGB7ciBzZXNzaW9uX2luZm8sIGVjaG8gPSBGQUxTRSwgcmVzdWx0cyA9ICdtYXJrdXAnfQ0Kc2Vzc2lvbkluZm8oKSAgICANCmBgYA0KDQo8IS0tIEZvb3RlciAtLT4NCiZuYnNwOw0KPGhyIC8+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+QSB3b3JrIGJ5IDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9DbGF1ZGl1UGFwYXN0ZXJpLyI+Q2xhdWRpdSBQYXBhc3Rlcmk8L2E+PC9wPg0KPHAgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPjxzcGFuIHN0eWxlPSJjb2xvcjogIzgwODA4MDsiPjxlbT5jbGF1ZGl1LnBhcGFzdGVyaUBnbWFpbC5jb208L2VtPjwvc3Bhbj48L3A+DQombmJzcDsNCg==