1 Quick ggwithinstats function

my_ggwithinstats <- function(data, title, x, y, outlier.label, xlab, ylab) {
  x <- rlang::enquo(x)
  y <- rlang::enquo(y)
  outlier.label <- rlang::enquo(outlier.label)
  
  data %>%
    ggstatsplot::ggwithinstats(
      x = !!x,
      y = !!y,
      title = title,
      xlab = xlab,
      ylab = ylab,
      outlier.tagging = TRUE,            # whether outliers need to be tagged
      outlier.label = !!outlier.label,   # variable to be used for tagging outliers
      outlier.coef = 2,
      pairwise.comparisons = TRUE,
      pairwise.display = "significant",
      results.subtitle = TRUE,
      type = "parametric",
      bf.message = FALSE, 
      p.adjust.method = "none",
      point.path = TRUE,
      ggtheme = ggprism::theme_prism(),
      # package = "RColorBrewer",  # "ggsci",
      # palette = "Dark",         # "default_jco",
      violin.args = list(width = 0.9, alpha = 0.2, size = 1, color = "black"),
      centrality.point.args = list(size = 5, color = "darkred"),
      centrality.label.args = list(size = 3, nudge_x = 0.2, segment.linetype = 5, fill = "#FFF8E7"), 
      ggplot.component = list(
        theme(
          plot.title = element_text(hjust = 0, size = 16),
          plot.subtitle = element_text(hjust = 0, size = 12), 
          plot.caption = element_text(hjust = 0, size = 12), 
          text = element_text(size = 14)
      ))
    ) + scale_colour_grey(start = 0.2, end = 0.2)   # hacky way to change point color
}

# For publication
my_ggwithinstats2 <- function(data, title, x, y, outlier.label, xlab, ylab, 
                              outlier.tagging = FALSE, results.subtitle = TRUE, 
                              centrality.label.args = TRUE, point.path = TRUE,
                              ...) {  # ... for limits and breaks
  x <- rlang::enquo(x)
  y <- rlang::enquo(y)
  outlier.label <- rlang::enquo(outlier.label)
  
  if(centrality.label.args){
    centrality.label.args <- list(size = 3, nudge_x = 0.2, segment.linetype = 5, fill = "#FFF8E7")
  }else{
    centrality.label.args <- list(size = 0, nudge_x = 10, segment.linetype = 0, alpha = 0) # very hacky way of not showing label
  }
  
  if(missing(title)) title <- ""
  if(missing(xlab)) xlab <- rlang::as_name(x)
  if(missing(ylab)) ylab <- rlang::as_name(y)
  
  data %>%
    ggstatsplot::ggwithinstats(
      x = !!x,
      y = !!y,
      title = title,
      xlab = xlab,
      ylab = ylab,
      outlier.tagging = outlier.tagging,                    # whether outlines need to be tagged
      outlier.label = !!outlier.label,                      # variable to be used for tagging outliers
      outlier.coef = 2,
      pairwise.comparisons = TRUE,
      pairwise.display = "all",
      results.subtitle = results.subtitle,
      type = "np",
      bf.message = FALSE, 
      p.adjust.method = "none",
      point.path = point.path,
      ggtheme = ggprism::theme_prism(palette = "black_and_white"),
      # package = "RColorBrewer",  # "ggsci",
      # palette = "Dark",         # "default_jco",
      violin.args = list(width = 0.9, alpha = 0.2, size = 1, color = "black"),
      centrality.plotting = TRUE,
      centrality.type = "parameteric",
      centrality.point.args = list(size = 5, color = "black"),
      centrality.path.args = list(color = "black", size = 1, alpha = 1),
      centrality.label.args = centrality.label.args,
      ggplot.component = list(
        theme(
          plot.title = element_text(hjust = 0, size = 16),
          plot.subtitle = element_text(hjust = 0, size = 12), 
          plot.caption = element_text(hjust = 0, size = 12), 
          text = element_text(family = "Sans", size = 14)
      ))
    ) + scale_colour_grey(start = 0.2, end = 0.2) +  # hacky way to change point color
    scale_y_continuous(...)
}

# Fast ggsave - saves plot with filename of R plot object
fast_ggsave <- function(plot, device = "tiff", path = NULL,
                        units = "in", dpi = 300, width = 5, height = 5, ...){ 
  plot_name <- deparse(substitute(plot))
  ggplot2::ggsave(filename = paste0(plot_name, ".", device), plot = plot,
                  device = device, path = path,
                  units = units, dpi = dpi,
                  width = width, height = height,
                  ...
  )
  
} # use: fast_ggsave(jrad_ox_p, path = savefolder)

# Fast tiff save
fast_tiffsave <- function(plot, path = NULL,
                          units = "in", res = 300, width = 5, height = 5, ...){ 
  plot_name <- deparse(substitute(plot))
  tiff(filename = file.path(path, paste0(plot_name, ".", "tiff")),
       units = units, res = res,
       width = width, height = height,
       ...
  )
  plot(plot)
  dev.off()
}  # use: fast_tiffsave(jrad_ox_p, path = savefolder)

# Errors with ggplot2  --- can use this to save:
# Cairo::Cairo(
#   width = 5, 
#   height = 5, 
#   file = file.path(savefolder, paste0("jrad_ox_p", ".", "tiff")),
#   type = "png", 
#   bg =  "white",    # "transparent" 
#   dpi = 300,
#   units = "in"
# )
# plot(jrad_ox_p) 
# dev.off()

2 Read data

folder <- "C:/Users/Mihai/Desktop/R Notebooks/notebooks/M2-report"
file <- "Date M2.1mirosuri.xlsx"

# savefolder <- "C:/Users/Mihai/Desktop/R Notebooks/notebooks/o1b-report-behavior/Art"

data <- rio::import(file.path(folder, file), which = 1)

data <- 
  data %>%
  dplyr::mutate(timp = factor(timp, levels = c("Pre", "Post"))) %>%
  dplyr::mutate(ID = as.factor(ID))

3 Data

data %>%
  DT::datatable(                                  # excel downloadable  DT table
    extensions = 'Buttons',
    options = list(pageLength = 6,
                   scrollX = '500px', 
                   dom = 'Bfrtip', 
                   buttons = c('excel', "csv"))
  )
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

4 Descriptives and Plots

# Descriptives
var_names <- colnames(data)[-c(1:2)]

data %>%
  dplyr::group_by(timp) %>%
  dplyr::select(-ID) %>%
  rstatix::get_summary_stats(type = "common") %>%
  dplyr::arrange(match(variable, var_names)) %>%
  print(n = Inf)
# Plots
# data %>%
#   group_by(ID) %>%
#   my_ggwithinstats2(
#     x = timp,
#     y = val_cafea,
#     outlier.label = ID, 
#     centrality.label.args = FALSE,
#     breaks = seq(from = 1, to = 7, by = 1),
#     limits = c(4, 7)
#   ) # %>%fast_tiffsave(., path = savefolder)


# Run in loop
var_names <- colnames(data)[-c(1:2)]
graph_list <- list()

for (var in var_names) {
  graph_list[[var]] <-
    data %>%
      group_by(ID) %>%
      my_ggwithinstats2(
        x = timp,
        y = !! rlang::sym(var),
        outlier.label = ID,
        centrality.label.args = FALSE,
        breaks = seq(from = 1, to = 7, by = 1),
        limits = c(4, 7)
  )
}

library(gridExtra)
do.call("grid.arrange", c(graph_list[1:3], ncol = 1))

do.call("grid.arrange", c(graph_list[4:6], ncol = 1))

do.call("grid.arrange", c(graph_list[7:9], ncol = 1))

do.call("grid.arrange", c(graph_list[10:12], ncol = 1))

do.call("grid.arrange", c(graph_list[13:15], ncol = 1))

do.call("grid.arrange", c(graph_list[16:18], ncol = 1))

do.call("grid.arrange", c(graph_list[19:21], ncol = 1))

do.call("grid.arrange", c(graph_list[22:24], ncol = 1))

5 Permutation test of symmetry

library(coin) # https://rcompanion.org/handbook/K_01.html

# coin::symmetry_test(val_cafea ~ timp | ID, data = data)

# Run in loop
var_names <- colnames(data)[-c(1:2, 22:24)]

for (var in var_names) {
  # data_perm <-
  #   data %>%
  #   dplyr::group_by(ID) %>%
  #   dplyr::select(ID, timp, dplyr::any_of(var)) %>%
  #   tidyr::drop_na(dplyr::any_of(var)) %>%
  #   dplyr::filter(n() == 2)
  
  formula <- as.formula(paste0(var, " ~ timp | ID"))
  tryCatch({
    coin::symmetry_test(formula, data = data) %>% print()
  }, error=function(e){}) 
}

    Asymptotic General Symmetry Test

data:  val_cafea by timp (Pre, Post) 
     stratified by ID
Z = -1.4142, p-value = 0.1573
alternative hypothesis: two.sided


    Asymptotic General Symmetry Test

data:  viv_cafea by timp (Pre, Post) 
     stratified by ID
Z = -1.3868, p-value = 0.1655
alternative hypothesis: two.sided


    Asymptotic General Symmetry Test

data:  rel_cafea by timp (Pre, Post) 
     stratified by ID
Z = -2.1974, p-value = 0.02799
alternative hypothesis: two.sided


    Asymptotic General Symmetry Test

data:  val_vanilie by timp (Pre, Post) 
     stratified by ID
Z = NaN, p-value = NA
alternative hypothesis: two.sided


    Asymptotic General Symmetry Test

data:  viv_vanilie by timp (Pre, Post) 
     stratified by ID
Z = -0.65465, p-value = 0.5127
alternative hypothesis: two.sided


    Asymptotic General Symmetry Test

data:  rel_vanilie by timp (Pre, Post) 
     stratified by ID
Z = -1.4142, p-value = 0.1573
alternative hypothesis: two.sided


    Asymptotic General Symmetry Test

data:  val_vin by timp (Pre, Post) 
     stratified by ID
Z = -1.4142, p-value = 0.1573
alternative hypothesis: two.sided


    Asymptotic General Symmetry Test

data:  viv_vin by timp (Pre, Post) 
     stratified by ID
Z = -1.4, p-value = 0.1615
alternative hypothesis: two.sided


    Asymptotic General Symmetry Test

data:  rel_vin by timp (Pre, Post) 
     stratified by ID
Z = -2.2678, p-value = 0.02334
alternative hypothesis: two.sided


6 Session Info

 

A work by Claudiu Papasteri

 

LS0tDQp0aXRsZTogIjxicj4gTTIuMSBTbWVsbHMiIA0Kc3VidGl0bGU6ICIxMCBTdWJqZWN0IGRhdGFzZXQiDQphdXRob3I6ICI8YnI+IENsYXVkaXUgUGFwYXN0ZXJpIg0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJW0gJVknKWAiDQpvdXRwdXQ6IA0KICAgIGh0bWxfbm90ZWJvb2s6DQogICAgICAgICAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICAgICAgICAgIHRvYzogdHJ1ZQ0KICAgICAgICAgICAgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICAgICAgICAgIHRoZW1lOiBzcGFjZWxhYg0KICAgICAgICAgICAgaGlnaGxpZ2h0OiB0YW5nbw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6IEFyaWFsDQogICAgICAgICAgICBmaWdfd2lkdGg6IDEwDQogICAgICAgICAgICBmaWdfaGVpZ2h0OiA5DQogICAgIyBwZGZfZG9jdW1lbnQ6IA0KICAgICAgICAgICAgIyB0b2M6IHRydWUNCiAgICAgICAgICAgICMgIHRvY19kZXB0aDogMg0KICAgICAgICAgICAgIyAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgICAgICAgICAjIGZvbnRzaXplOiAxMXB0DQogICAgICAgICAgICAjIGdlb21ldHJ5OiBtYXJnaW49MWluDQogICAgICAgICAgICAjIGZpZ193aWR0aDogNw0KICAgICAgICAgICAgIyBmaWdfaGVpZ2h0OiA2DQogICAgICAgICAgICAjIGZpZ19jYXB0aW9uOiB0cnVlDQogICAgIyBnaXRodWJfZG9jdW1lbnQ6IA0KICAgICAgICAgICAgIyB0b2M6IHRydWUNCiAgICAgICAgICAgICMgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICAjIGh0bWxfcHJldmlldzogZmFsc2UNCiAgICAgICAgICAgICMgZmlnX3dpZHRoOiA1DQogICAgICAgICAgICAjIGZpZ19oZWlnaHQ6IDUNCiAgICAgICAgICAgICMgZGV2OiBqcGVnDQotLS0NCg0KDQo8IS0tIFNldHVwIC0tPg0KDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBraW50ciBvcHRpb25zDQprbml0cjo6b3B0c19jaHVuayRzZXQoDQogIGNvbW1lbnQgPSAiIyIsDQogIGNvbGxhcHNlID0gVFJVRSwNCiAgZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IFRSVUUsIGNhY2hlID0gVFJVRSAgICAgICAjIGVjaG8gPSBGYWxzZSBmb3IgZ2l0aHViX2RvY3VtZW50LCBidXQgd2lsbCBiZSBmb2xkZWQgaW4gaHRtbF9ub3RlYm9vaw0KKQ0KDQojIEdlbmVyYWwgUiBvcHRpb25zIGFuZCBpbmZvDQpzZXQuc2VlZCgxMTEpICAgICAgICAgICAgICAgIyBpbiBjYXNlIHdlIHVzZSByYW5kb21pemVkIHByb2NlZHVyZXMgICAgICAgDQpvcHRpb25zKHNjaXBlbiA9IDk5OSkgICAgICAgIyBwb3NpdGl2ZSB2YWx1ZXMgYmlhcyB0b3dhcmRzIGZpeGVkIGFuZCBuZWdhdGl2ZSB0b3dhcmRzIHNjaWVudGlmaWMgbm90YXRpb24NCg0KIyBMb2FkIHBhY2thZ2VzDQppZiAoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQ0KcGFja2FnZXMgPC0gYygNCiAgInBhcGFqYSIsDQogICJ0aWR5dmVyc2UiLCAicGx5ciIsICAgICAgDQogICJwc3ljaCIsICJQZXJmb3JtYW5jZUFuYWx5dGljcyIsICAgICAgICAgIA0KICAiYnJvb20iLCAicnN0YXRpeCIsDQogICJzdW1tYXJ5dG9vbHMiLCAgICAgICAgICAgIA0KICAiZ2dwbG90MiIsICJnZ3B1YnIiLCAic2NhbGVzIiwgICAgICAgIA0KICAicmlvIg0KICAjICwgLi4uDQopDQppZiAoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQ0KcGFjbWFuOjpwX2xvYWQoY2hhciA9IHBhY2thZ2VzKQ0KDQojIFRoZW1lcyBmb3IgZ2dwbG90MiBwbG90aW5nIChoZXJlIHVzZWQgQVBBIHN0eWxlKQ0KdGhlbWVfc2V0KHRoZW1lX2FwYSgpKQ0KYGBgDQoNCg0KDQoNCg0KPCEtLSBSZXBvcnQgLS0+DQoNCiMgUXVpY2sgZ2d3aXRoaW5zdGF0cyBmdW5jdGlvbg0KDQpgYGB7cn0NCm15X2dnd2l0aGluc3RhdHMgPC0gZnVuY3Rpb24oZGF0YSwgdGl0bGUsIHgsIHksIG91dGxpZXIubGFiZWwsIHhsYWIsIHlsYWIpIHsNCiAgeCA8LSBybGFuZzo6ZW5xdW8oeCkNCiAgeSA8LSBybGFuZzo6ZW5xdW8oeSkNCiAgb3V0bGllci5sYWJlbCA8LSBybGFuZzo6ZW5xdW8ob3V0bGllci5sYWJlbCkNCiAgDQogIGRhdGEgJT4lDQogICAgZ2dzdGF0c3Bsb3Q6Omdnd2l0aGluc3RhdHMoDQogICAgICB4ID0gISF4LA0KICAgICAgeSA9ICEheSwNCiAgICAgIHRpdGxlID0gdGl0bGUsDQogICAgICB4bGFiID0geGxhYiwNCiAgICAgIHlsYWIgPSB5bGFiLA0KICAgICAgb3V0bGllci50YWdnaW5nID0gVFJVRSwgICAgICAgICAgICAjIHdoZXRoZXIgb3V0bGllcnMgbmVlZCB0byBiZSB0YWdnZWQNCiAgICAgIG91dGxpZXIubGFiZWwgPSAhIW91dGxpZXIubGFiZWwsICAgIyB2YXJpYWJsZSB0byBiZSB1c2VkIGZvciB0YWdnaW5nIG91dGxpZXJzDQogICAgICBvdXRsaWVyLmNvZWYgPSAyLA0KICAgICAgcGFpcndpc2UuY29tcGFyaXNvbnMgPSBUUlVFLA0KICAgICAgcGFpcndpc2UuZGlzcGxheSA9ICJzaWduaWZpY2FudCIsDQogICAgICByZXN1bHRzLnN1YnRpdGxlID0gVFJVRSwNCiAgICAgIHR5cGUgPSAicGFyYW1ldHJpYyIsDQogICAgICBiZi5tZXNzYWdlID0gRkFMU0UsIA0KICAgICAgcC5hZGp1c3QubWV0aG9kID0gIm5vbmUiLA0KICAgICAgcG9pbnQucGF0aCA9IFRSVUUsDQogICAgICBnZ3RoZW1lID0gZ2dwcmlzbTo6dGhlbWVfcHJpc20oKSwNCiAgICAgICMgcGFja2FnZSA9ICJSQ29sb3JCcmV3ZXIiLCAgIyAiZ2dzY2kiLA0KICAgICAgIyBwYWxldHRlID0gIkRhcmsiLCAgICAgICAgICMgImRlZmF1bHRfamNvIiwNCiAgICAgIHZpb2xpbi5hcmdzID0gbGlzdCh3aWR0aCA9IDAuOSwgYWxwaGEgPSAwLjIsIHNpemUgPSAxLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgY2VudHJhbGl0eS5wb2ludC5hcmdzID0gbGlzdChzaXplID0gNSwgY29sb3IgPSAiZGFya3JlZCIpLA0KICAgICAgY2VudHJhbGl0eS5sYWJlbC5hcmdzID0gbGlzdChzaXplID0gMywgbnVkZ2VfeCA9IDAuMiwgc2VnbWVudC5saW5ldHlwZSA9IDUsIGZpbGwgPSAiI0ZGRjhFNyIpLCANCiAgICAgIGdncGxvdC5jb21wb25lbnQgPSBsaXN0KA0KICAgICAgICB0aGVtZSgNCiAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDE2KSwNCiAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDEyKSwgDQogICAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDEyKSwgDQogICAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpDQogICAgICApKQ0KICAgICkgKyBzY2FsZV9jb2xvdXJfZ3JleShzdGFydCA9IDAuMiwgZW5kID0gMC4yKSAgICMgaGFja3kgd2F5IHRvIGNoYW5nZSBwb2ludCBjb2xvcg0KfQ0KDQojIEZvciBwdWJsaWNhdGlvbg0KbXlfZ2d3aXRoaW5zdGF0czIgPC0gZnVuY3Rpb24oZGF0YSwgdGl0bGUsIHgsIHksIG91dGxpZXIubGFiZWwsIHhsYWIsIHlsYWIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0bGllci50YWdnaW5nID0gRkFMU0UsIHJlc3VsdHMuc3VidGl0bGUgPSBUUlVFLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNlbnRyYWxpdHkubGFiZWwuYXJncyA9IFRSVUUsIHBvaW50LnBhdGggPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uKSB7ICAjIC4uLiBmb3IgbGltaXRzIGFuZCBicmVha3MNCiAgeCA8LSBybGFuZzo6ZW5xdW8oeCkNCiAgeSA8LSBybGFuZzo6ZW5xdW8oeSkNCiAgb3V0bGllci5sYWJlbCA8LSBybGFuZzo6ZW5xdW8ob3V0bGllci5sYWJlbCkNCiAgDQogIGlmKGNlbnRyYWxpdHkubGFiZWwuYXJncyl7DQogICAgY2VudHJhbGl0eS5sYWJlbC5hcmdzIDwtIGxpc3Qoc2l6ZSA9IDMsIG51ZGdlX3ggPSAwLjIsIHNlZ21lbnQubGluZXR5cGUgPSA1LCBmaWxsID0gIiNGRkY4RTciKQ0KICB9ZWxzZXsNCiAgICBjZW50cmFsaXR5LmxhYmVsLmFyZ3MgPC0gbGlzdChzaXplID0gMCwgbnVkZ2VfeCA9IDEwLCBzZWdtZW50LmxpbmV0eXBlID0gMCwgYWxwaGEgPSAwKSAjIHZlcnkgaGFja3kgd2F5IG9mIG5vdCBzaG93aW5nIGxhYmVsDQogIH0NCiAgDQogIGlmKG1pc3NpbmcodGl0bGUpKSB0aXRsZSA8LSAiIg0KICBpZihtaXNzaW5nKHhsYWIpKSB4bGFiIDwtIHJsYW5nOjphc19uYW1lKHgpDQogIGlmKG1pc3NpbmcoeWxhYikpIHlsYWIgPC0gcmxhbmc6OmFzX25hbWUoeSkNCiAgDQogIGRhdGEgJT4lDQogICAgZ2dzdGF0c3Bsb3Q6Omdnd2l0aGluc3RhdHMoDQogICAgICB4ID0gISF4LA0KICAgICAgeSA9ICEheSwNCiAgICAgIHRpdGxlID0gdGl0bGUsDQogICAgICB4bGFiID0geGxhYiwNCiAgICAgIHlsYWIgPSB5bGFiLA0KICAgICAgb3V0bGllci50YWdnaW5nID0gb3V0bGllci50YWdnaW5nLCAgICAgICAgICAgICAgICAgICAgIyB3aGV0aGVyIG91dGxpbmVzIG5lZWQgdG8gYmUgdGFnZ2VkDQogICAgICBvdXRsaWVyLmxhYmVsID0gISFvdXRsaWVyLmxhYmVsLCAgICAgICAgICAgICAgICAgICAgICAjIHZhcmlhYmxlIHRvIGJlIHVzZWQgZm9yIHRhZ2dpbmcgb3V0bGllcnMNCiAgICAgIG91dGxpZXIuY29lZiA9IDIsDQogICAgICBwYWlyd2lzZS5jb21wYXJpc29ucyA9IFRSVUUsDQogICAgICBwYWlyd2lzZS5kaXNwbGF5ID0gImFsbCIsDQogICAgICByZXN1bHRzLnN1YnRpdGxlID0gcmVzdWx0cy5zdWJ0aXRsZSwNCiAgICAgIHR5cGUgPSAibnAiLA0KICAgICAgYmYubWVzc2FnZSA9IEZBTFNFLCANCiAgICAgIHAuYWRqdXN0Lm1ldGhvZCA9ICJub25lIiwNCiAgICAgIHBvaW50LnBhdGggPSBwb2ludC5wYXRoLA0KICAgICAgZ2d0aGVtZSA9IGdncHJpc206OnRoZW1lX3ByaXNtKHBhbGV0dGUgPSAiYmxhY2tfYW5kX3doaXRlIiksDQogICAgICAjIHBhY2thZ2UgPSAiUkNvbG9yQnJld2VyIiwgICMgImdnc2NpIiwNCiAgICAgICMgcGFsZXR0ZSA9ICJEYXJrIiwgICAgICAgICAjICJkZWZhdWx0X2pjbyIsDQogICAgICB2aW9saW4uYXJncyA9IGxpc3Qod2lkdGggPSAwLjksIGFscGhhID0gMC4yLCBzaXplID0gMSwgY29sb3IgPSAiYmxhY2siKSwNCiAgICAgIGNlbnRyYWxpdHkucGxvdHRpbmcgPSBUUlVFLA0KICAgICAgY2VudHJhbGl0eS50eXBlID0gInBhcmFtZXRlcmljIiwNCiAgICAgIGNlbnRyYWxpdHkucG9pbnQuYXJncyA9IGxpc3Qoc2l6ZSA9IDUsIGNvbG9yID0gImJsYWNrIiksDQogICAgICBjZW50cmFsaXR5LnBhdGguYXJncyA9IGxpc3QoY29sb3IgPSAiYmxhY2siLCBzaXplID0gMSwgYWxwaGEgPSAxKSwNCiAgICAgIGNlbnRyYWxpdHkubGFiZWwuYXJncyA9IGNlbnRyYWxpdHkubGFiZWwuYXJncywNCiAgICAgIGdncGxvdC5jb21wb25lbnQgPSBsaXN0KA0KICAgICAgICB0aGVtZSgNCiAgICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDE2KSwNCiAgICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDEyKSwgDQogICAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDEyKSwgDQogICAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiU2FucyIsIHNpemUgPSAxNCkNCiAgICAgICkpDQogICAgKSArIHNjYWxlX2NvbG91cl9ncmV5KHN0YXJ0ID0gMC4yLCBlbmQgPSAwLjIpICsgICMgaGFja3kgd2F5IHRvIGNoYW5nZSBwb2ludCBjb2xvcg0KICAgIHNjYWxlX3lfY29udGludW91cyguLi4pDQp9DQoNCiMgRmFzdCBnZ3NhdmUgLSBzYXZlcyBwbG90IHdpdGggZmlsZW5hbWUgb2YgUiBwbG90IG9iamVjdA0KZmFzdF9nZ3NhdmUgPC0gZnVuY3Rpb24ocGxvdCwgZGV2aWNlID0gInRpZmYiLCBwYXRoID0gTlVMTCwNCiAgICAgICAgICAgICAgICAgICAgICAgIHVuaXRzID0gImluIiwgZHBpID0gMzAwLCB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIC4uLil7IA0KICBwbG90X25hbWUgPC0gZGVwYXJzZShzdWJzdGl0dXRlKHBsb3QpKQ0KICBnZ3Bsb3QyOjpnZ3NhdmUoZmlsZW5hbWUgPSBwYXN0ZTAocGxvdF9uYW1lLCAiLiIsIGRldmljZSksIHBsb3QgPSBwbG90LA0KICAgICAgICAgICAgICAgICAgZGV2aWNlID0gZGV2aWNlLCBwYXRoID0gcGF0aCwNCiAgICAgICAgICAgICAgICAgIHVuaXRzID0gdW5pdHMsIGRwaSA9IGRwaSwNCiAgICAgICAgICAgICAgICAgIHdpZHRoID0gd2lkdGgsIGhlaWdodCA9IGhlaWdodCwNCiAgICAgICAgICAgICAgICAgIC4uLg0KICApDQogIA0KfSAjIHVzZTogZmFzdF9nZ3NhdmUoanJhZF9veF9wLCBwYXRoID0gc2F2ZWZvbGRlcikNCg0KIyBGYXN0IHRpZmYgc2F2ZQ0KZmFzdF90aWZmc2F2ZSA8LSBmdW5jdGlvbihwbG90LCBwYXRoID0gTlVMTCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdW5pdHMgPSAiaW4iLCByZXMgPSAzMDAsIHdpZHRoID0gNSwgaGVpZ2h0ID0gNSwgLi4uKXsgDQogIHBsb3RfbmFtZSA8LSBkZXBhcnNlKHN1YnN0aXR1dGUocGxvdCkpDQogIHRpZmYoZmlsZW5hbWUgPSBmaWxlLnBhdGgocGF0aCwgcGFzdGUwKHBsb3RfbmFtZSwgIi4iLCAidGlmZiIpKSwNCiAgICAgICB1bml0cyA9IHVuaXRzLCByZXMgPSByZXMsDQogICAgICAgd2lkdGggPSB3aWR0aCwgaGVpZ2h0ID0gaGVpZ2h0LA0KICAgICAgIC4uLg0KICApDQogIHBsb3QocGxvdCkNCiAgZGV2Lm9mZigpDQp9ICAjIHVzZTogZmFzdF90aWZmc2F2ZShqcmFkX294X3AsIHBhdGggPSBzYXZlZm9sZGVyKQ0KDQojIEVycm9ycyB3aXRoIGdncGxvdDIgIC0tLSBjYW4gdXNlIHRoaXMgdG8gc2F2ZToNCiMgQ2Fpcm86OkNhaXJvKA0KIyAgIHdpZHRoID0gNSwgDQojICAgaGVpZ2h0ID0gNSwgDQojICAgZmlsZSA9IGZpbGUucGF0aChzYXZlZm9sZGVyLCBwYXN0ZTAoImpyYWRfb3hfcCIsICIuIiwgInRpZmYiKSksDQojICAgdHlwZSA9ICJwbmciLCANCiMgICBiZyA9ICAid2hpdGUiLCAgICAjICJ0cmFuc3BhcmVudCIgDQojICAgZHBpID0gMzAwLA0KIyAgIHVuaXRzID0gImluIg0KIyApDQojIHBsb3QoanJhZF9veF9wKSANCiMgZGV2Lm9mZigpDQpgYGANCg0KDQoNCg0KIyBSZWFkIGRhdGENCg0KYGBge3IgcmVhZF9jbGVhbl9yZWNvZGVfbWVyZ2Vfb3h0LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30NCmZvbGRlciA8LSAiQzovVXNlcnMvTWloYWkvRGVza3RvcC9SIE5vdGVib29rcy9ub3RlYm9va3MvTTItcmVwb3J0Ig0KZmlsZSA8LSAiRGF0ZSBNMi4xbWlyb3N1cmkueGxzeCINCg0KIyBzYXZlZm9sZGVyIDwtICJDOi9Vc2Vycy9NaWhhaS9EZXNrdG9wL1IgTm90ZWJvb2tzL25vdGVib29rcy9vMWItcmVwb3J0LWJlaGF2aW9yL0FydCINCg0KZGF0YSA8LSByaW86OmltcG9ydChmaWxlLnBhdGgoZm9sZGVyLCBmaWxlKSwgd2hpY2ggPSAxKQ0KDQpkYXRhIDwtIA0KICBkYXRhICU+JQ0KICBkcGx5cjo6bXV0YXRlKHRpbXAgPSBmYWN0b3IodGltcCwgbGV2ZWxzID0gYygiUHJlIiwgIlBvc3QiKSkpICU+JQ0KICBkcGx5cjo6bXV0YXRlKElEID0gYXMuZmFjdG9yKElEKSkNCmBgYA0KDQoNCiMgRGF0YQ0KDQpgYGB7cn0NCmRhdGEgJT4lDQogIERUOjpkYXRhdGFibGUoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgZXhjZWwgZG93bmxvYWRhYmxlICBEVCB0YWJsZQ0KICAgIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycsDQogICAgb3B0aW9ucyA9IGxpc3QocGFnZUxlbmd0aCA9IDYsDQogICAgICAgICAgICAgICAgICAgc2Nyb2xsWCA9ICc1MDBweCcsIA0KICAgICAgICAgICAgICAgICAgIGRvbSA9ICdCZnJ0aXAnLCANCiAgICAgICAgICAgICAgICAgICBidXR0b25zID0gYygnZXhjZWwnLCAiY3N2IikpDQogICkNCmBgYA0KDQoNCiMgRGVzY3JpcHRpdmVzIGFuZCBQbG90cyANCg0KYGBge3J9DQojIERlc2NyaXB0aXZlcw0KdmFyX25hbWVzIDwtIGNvbG5hbWVzKGRhdGEpWy1jKDE6MildDQoNCmRhdGEgJT4lDQogIGRwbHlyOjpncm91cF9ieSh0aW1wKSAlPiUNCiAgZHBseXI6OnNlbGVjdCgtSUQpICU+JQ0KICByc3RhdGl4OjpnZXRfc3VtbWFyeV9zdGF0cyh0eXBlID0gImNvbW1vbiIpICU+JQ0KICBkcGx5cjo6YXJyYW5nZShtYXRjaCh2YXJpYWJsZSwgdmFyX25hbWVzKSkgJT4lDQogIHByaW50KG4gPSBJbmYpDQpgYGANCg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTEwfQ0KIyBQbG90cw0KIyBkYXRhICU+JQ0KIyAgIGdyb3VwX2J5KElEKSAlPiUNCiMgICBteV9nZ3dpdGhpbnN0YXRzMigNCiMgICAgIHggPSB0aW1wLA0KIyAgICAgeSA9IHZhbF9jYWZlYSwNCiMgICAgIG91dGxpZXIubGFiZWwgPSBJRCwgDQojICAgICBjZW50cmFsaXR5LmxhYmVsLmFyZ3MgPSBGQUxTRSwNCiMgICAgIGJyZWFrcyA9IHNlcShmcm9tID0gMSwgdG8gPSA3LCBieSA9IDEpLA0KIyAgICAgbGltaXRzID0gYyg0LCA3KQ0KIyAgICkgIyAlPiVmYXN0X3RpZmZzYXZlKC4sIHBhdGggPSBzYXZlZm9sZGVyKQ0KDQoNCiMgUnVuIGluIGxvb3ANCnZhcl9uYW1lcyA8LSBjb2xuYW1lcyhkYXRhKVstYygxOjIpXQ0KZ3JhcGhfbGlzdCA8LSBsaXN0KCkNCg0KZm9yICh2YXIgaW4gdmFyX25hbWVzKSB7DQogIGdyYXBoX2xpc3RbW3Zhcl1dIDwtDQogICAgZGF0YSAlPiUNCiAgICAgIGdyb3VwX2J5KElEKSAlPiUNCiAgICAgIG15X2dnd2l0aGluc3RhdHMyKA0KICAgICAgICB4ID0gdGltcCwNCiAgICAgICAgeSA9ICEhIHJsYW5nOjpzeW0odmFyKSwNCiAgICAgICAgb3V0bGllci5sYWJlbCA9IElELA0KICAgICAgICBjZW50cmFsaXR5LmxhYmVsLmFyZ3MgPSBGQUxTRSwNCiAgICAgICAgYnJlYWtzID0gc2VxKGZyb20gPSAxLCB0byA9IDcsIGJ5ID0gMSksDQogICAgICAgIGxpbWl0cyA9IGMoNCwgNykNCiAgKQ0KfQ0KDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmRvLmNhbGwoImdyaWQuYXJyYW5nZSIsIGMoZ3JhcGhfbGlzdFsxOjNdLCBuY29sID0gMSkpDQpkby5jYWxsKCJncmlkLmFycmFuZ2UiLCBjKGdyYXBoX2xpc3RbNDo2XSwgbmNvbCA9IDEpKQ0KZG8uY2FsbCgiZ3JpZC5hcnJhbmdlIiwgYyhncmFwaF9saXN0Wzc6OV0sIG5jb2wgPSAxKSkNCmRvLmNhbGwoImdyaWQuYXJyYW5nZSIsIGMoZ3JhcGhfbGlzdFsxMDoxMl0sIG5jb2wgPSAxKSkNCmRvLmNhbGwoImdyaWQuYXJyYW5nZSIsIGMoZ3JhcGhfbGlzdFsxMzoxNV0sIG5jb2wgPSAxKSkNCmRvLmNhbGwoImdyaWQuYXJyYW5nZSIsIGMoZ3JhcGhfbGlzdFsxNjoxOF0sIG5jb2wgPSAxKSkNCmRvLmNhbGwoImdyaWQuYXJyYW5nZSIsIGMoZ3JhcGhfbGlzdFsxOToyMV0sIG5jb2wgPSAxKSkNCmRvLmNhbGwoImdyaWQuYXJyYW5nZSIsIGMoZ3JhcGhfbGlzdFsyMjoyNF0sIG5jb2wgPSAxKSkNCmBgYA0KDQojIFBlcm11dGF0aW9uIHRlc3Qgb2Ygc3ltbWV0cnkNCg0KYGBge3J9DQpsaWJyYXJ5KGNvaW4pICMgaHR0cHM6Ly9yY29tcGFuaW9uLm9yZy9oYW5kYm9vay9LXzAxLmh0bWwNCg0KIyBjb2luOjpzeW1tZXRyeV90ZXN0KHZhbF9jYWZlYSB+IHRpbXAgfCBJRCwgZGF0YSA9IGRhdGEpDQoNCiMgUnVuIGluIGxvb3ANCnZhcl9uYW1lcyA8LSBjb2xuYW1lcyhkYXRhKVstYygxOjIsIDIyOjI0KV0NCg0KZm9yICh2YXIgaW4gdmFyX25hbWVzKSB7DQogICMgZGF0YV9wZXJtIDwtDQogICMgICBkYXRhICU+JQ0KICAjICAgZHBseXI6Omdyb3VwX2J5KElEKSAlPiUNCiAgIyAgIGRwbHlyOjpzZWxlY3QoSUQsIHRpbXAsIGRwbHlyOjphbnlfb2YodmFyKSkgJT4lDQogICMgICB0aWR5cjo6ZHJvcF9uYShkcGx5cjo6YW55X29mKHZhcikpICU+JQ0KICAjICAgZHBseXI6OmZpbHRlcihuKCkgPT0gMikNCiAgDQogIGZvcm11bGEgPC0gYXMuZm9ybXVsYShwYXN0ZTAodmFyLCAiIH4gdGltcCB8IElEIikpDQogIHRyeUNhdGNoKHsNCiAgICBjb2luOjpzeW1tZXRyeV90ZXN0KGZvcm11bGEsIGRhdGEgPSBkYXRhKSAlPiUgcHJpbnQoKQ0KICB9LCBlcnJvcj1mdW5jdGlvbihlKXt9KSANCn0NCg0KYGBgDQoNCg0KDQoNCg0KPCEtLSBTZXNzaW9uIEluZm8gYW5kIExpY2Vuc2UgLS0+DQoNCjxicj4NCg0KIyBTZXNzaW9uIEluZm8NCmBgYHtyIHNlc3Npb25faW5mbywgZWNobyA9IEZBTFNFLCByZXN1bHRzID0gJ21hcmt1cCd9DQpzZXNzaW9uSW5mbygpICAgIA0KYGBgDQoNCjwhLS0gRm9vdGVyIC0tPg0KJm5ic3A7DQo8aHIgLz4NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij5BIHdvcmsgYnkgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL0NsYXVkaXVQYXBhc3RlcmkvIj5DbGF1ZGl1IFBhcGFzdGVyaTwvYT48L3A+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+PHNwYW4gc3R5bGU9ImNvbG9yOiAjODA4MDgwOyI+PGVtPmNsYXVkaXUucGFwYXN0ZXJpQGdtYWlsLmNvbTwvZW0+PC9zcGFuPjwvcD4NCiZuYnNwOw0K