1 Run demoimitMetrics_cleantable script

script_folder <- "C:/Users/Mihai/Desktop/R Notebooks/notebooks/STAD-demoimitMetrics/Scripts" 
script_name <- "demoimitMetrics_to_cleantable_ieeg.R"
source(file.path(script_folder, script_name))
full_data_output_clean <-
  full_data_output_clean %>%
  tidyr::separate(id, into = c("num_id", "code"), "(?<=[0-9])(?=[a-zA-Z])", remove = FALSE) %>%
  dplyr::mutate(id = as.factor(id),
                code = as.factor(code)
  )

2 Data

2.1 Info:

  • Demo scores

    • object response by navigator (individual score) (GameState 9 => newGameState 10)
  • Imitation scores

    • 1st row for start (GameState 14 => newGameState 15)
    • 2nd row for flag (GameState 15 => newGameState 16)
    • 3rd row = first object response by navigator (individual score) (GameState 16 => newGameState 17)
    • 4th row = suggestion marker by observer (observer score) (GameState 17 => newGameState 18)
    • 5th row = 2nd object response by navigator (collaborative score) (GameState 18 => newGameState 19)
  • Variables:

    • id categorical - unique identifier
    • code categorical - IC = pacient / PIC = instructor
    • condition categorical - “social” or “bot”
    • order categorical - 1 or 2 the order of conditions
    • who catergorical - 1 or 2 codes for who’s recording it is (data only for current id is when: who == playerType)
    • newGameState_clean categorical - codes for GameStates (5-11 are Demo, 12-20 are Imit)
    • demoimitState_clean categorical - “Demo” or “Imit” depending on state
    • playerType categorical - 1 or 2 depending on GameState (should be used together with var who)
    • markerType categorical - codes for the object (see documentation), but it actually follows the the above Info (dependes on GameState)
    • score continuous - follows the the above Info (depends on GameState)
full_data_output_clean %>%
  DT::datatable(                                  # excel downloadable  DT table
  extensions = 'Buttons',
  options = list(pageLength = 10,
                 scrollX = '500px', 
                 dom = 'Bfrtip', 
                 buttons = c('excel', "csv"))) %>%
  DT::formatStyle(names(full_data_output_clean),lineHeight = "60%")    # slimmer rows

3 Preliminary Analyses

3.0.1 Functions

plot_growth_state_id <- function(data, cond, gamestate, time_lim = 20) {
  data %>%
  dplyr::filter(condition == cond, newGameState_clean == gamestate) %>%
  group_by(id) %>%
  dplyr::mutate(time = dplyr::row_number()) %>%
  dplyr::filter(time < time_lim) %>%  
    ggplot(aes(x = time, y = score)) +
    geom_line() +
    facet_wrap(~id) +
    ylim(0, 100) +
    scale_x_continuous(breaks = 1:14) +
    ggtitle(paste0("Condition: ", cond, ", ", "Game state: ", gamestate))
}

# e.g.
# full_data_output_clean %>%
#   dplyr::filter(condition == "bot", newGameState_clean == "10") %>%
#   group_by(id) %>%
#   dplyr::mutate(time = dplyr::row_number()) %>%
#   ggplot(aes(x = time, y = score)) +
#   geom_line() +
#   facet_wrap(~id)

plot_growth_state_id_by <- function(data, cond, col_by = c("order", "code"), gamestate, time_lim = 20) {
  data %>%
  dplyr::filter(condition == cond, newGameState_clean == gamestate) %>%
  group_by(id) %>%
  dplyr::mutate(time = dplyr::row_number(),
                order = as.factor(order),
                code = as.factor(code)) %>%
  dplyr::filter(time < time_lim) %>%  
    ggplot(aes(x = time, y = score)) +
    geom_line(aes_string(color = col_by)) +
    geom_point(aes_string(color = col_by)) +
    facet_wrap(~id) +
    ylim(0, 100) +
    scale_x_continuous(breaks = 1:14) +
    ggtitle(paste0("Condition: ", cond, ", ", "Game state: ", gamestate))
}




plot_growth_state_loess <- function(data, cond, gamestate, time_lim = 20) {
  data %>%
  dplyr::filter(condition == cond, newGameState_clean == gamestate) %>%
  group_by(id) %>%
  dplyr::mutate(time = dplyr::row_number()) %>%
  dplyr::filter(time < time_lim) %>%   
    ggplot(aes(x = time, y = score)) +
    geom_line(aes(color = as.factor(id)), alpha = .5) +
    geom_smooth(method = "loess", formula = "y ~ x", color = "red", fill = "red") +
    geom_smooth(method = "lm", formula = y ~ splines::bs(x, knots = seq(2 , 16, by = 2), degree = 1), 
                se = FALSE, color = "black", fill = "gray", alpha = 0.8) +
    ylim(0, 100) +
    scale_x_continuous(breaks = 1:14) +
    ggtitle(paste0("Condition: ", cond, ", ", "Game state: ", gamestate)) +
    labs(color = "id")  
}
  
# e.e.
# full_data_output_clean %>%
# dplyr::filter(condition == "bot", newGameState_clean == "10") %>%
# group_by(id) %>%
# dplyr::mutate(time = dplyr::row_number()) %>%
# ggplot(aes(x = time, y = score)) +
# geom_line(aes(color = as.factor(id)), alpha = .5) +
# geom_smooth(method = "loess", formula = "y ~ x")

plot_growth_state1017_id <- function(data, conds = c("social", "bot"), time_lim = 20) {
  data %>%
  dplyr::filter(condition %in% conds, newGameState_clean %in% c("10", "17")) %>%
  dplyr::mutate(newGameState_clean = as.factor(newGameState_clean)) %>%  
  dplyr::group_by(id, condition) %>%
  dplyr::mutate(time = dplyr::row_number()) %>%
  dplyr::filter(time < time_lim) %>% 
    ggplot(aes(x = time, y = score, color = condition)) +
    geom_line() +
    geom_point(aes(shape = newGameState_clean)) +
    facet_wrap(~id) +
    ylim(0, 100) +
    scale_x_continuous(breaks = 1:14) +
    ggtitle("Alternating GameState 10 and 17") + 
    theme(legend.position = "right")
}



my_ggwithinstats2 <- function(data, title = NULL, x, y, gamestate, time_lim = 20, outlier.label, xlab, ylab, 
                              outlier.tagging = FALSE, results.subtitle = TRUE, 
                              centrality.label.args = TRUE, point.path = TRUE,
                              type = "parametric", 
                              ...) {  # ... for limits and breaks
  x <- rlang::enquo(x)
  y <- rlang::enquo(y)
  outlier.label <- rlang::enquo(outlier.label)
  
  if(is.null(title)) {
    title <- paste0("Game state: ", gamestate)
  }
  
  data <-
    data %>%
    dplyr::select(!!outlier.label, !!x, !!y, newGameState_clean) %>%      # newGameState_clean is hardcoded here
    dplyr::filter(newGameState_clean == gamestate) %>%
    group_by(!!outlier.label, !!x) %>%
    dplyr::mutate(time = dplyr::row_number()) %>%
    dplyr::filter(time < time_lim) %>%   
    dplyr::summarise(mean_score = mean(!!y, na.rm = TRUE))
    
  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
  }
  
  data %>%
    ggstatsplot::ggwithinstats(
      x = !!x,
      y = mean_score,              # here we have the mean score for id, not !!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 = type,
      bf.message = FALSE, 
      p.adjust.method = "none",
      point.path = point.path,
      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.plotting = TRUE,
      centrality.type = "parameteric",
      centrality.point.args = list(size = 5, color = "darkred"),
      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(size = 14)
      ))
    ) + scale_colour_grey(start = 0.2, end = 0.2) +  # hacky way to change point color
    ylim(0, 100) +
    scale_y_continuous(...)
}

# e.g.
# my_ggwithinstats2(full_data_output_clean, x = condition, y = score, outlier.label = id, gamestate = 10,
#                   time_lim = 20, xlab = "Condition", ylab = "score")
                   

3.1 Check balance

3.1.1 All participants

counts_id_condord <-
  full_data_output_clean %>%
  dplyr::count(id, condition, order)

counts_id_condord %>%      
  print(n = Inf)

counts_id_condord %>%
  dplyr::select(condition, order) %>%
  table() %>%
  knitr::kable(caption = "Order")
Order
1 2
bot 3 3
social 16 0

3.1.2 Participants with both conditions

ids_full_subj <-
  full_data_output_clean %>%
  group_by(id, condition) %>%
  summarise(count = n()) %>%
  dplyr::filter(n() > 1) %>%
  dplyr::pull(id) %>%
  unique()

full_data_output_clean %>%
  dplyr::filter(id %in% ids_full_subj) %>%
  dplyr::count(id, condition, order) %>%
  dplyr::select(condition, order) %>%
  table() %>%
  knitr::kable(caption = "Order")
Order
1 2
bot 0 3
social 3 0

3.2 Individual growth (object not considered)

plot_growth_state_id_by(full_data_output_clean, "bot", "order", "10")  

plot_growth_state_id_by(full_data_output_clean, "social", "code", "10") %>% print() %>% suppressMessages()


plot_growth_state_id_by(full_data_output_clean, "bot", "order", "15")  

plot_growth_state_id_by(full_data_output_clean, "social", "code", "15") %>% print() %>% suppressMessages()


plot_growth_state_id_by(full_data_output_clean, "bot", "order", "16")  

plot_growth_state_id_by(full_data_output_clean, "social", "code", "16") %>% print() %>% suppressMessages()


plot_growth_state_id_by(full_data_output_clean, "bot", "order", "17")  

plot_growth_state_id_by(full_data_output_clean, "social", "code", "17") %>% print() %>% suppressMessages()


plot_growth_state_id_by(full_data_output_clean, "bot", "order", "18")  

plot_growth_state_id_by(full_data_output_clean, "social", "code", "18") %>% print() %>% suppressMessages()


plot_growth_state_id_by(full_data_output_clean, "bot", "order", "19")  

plot_growth_state_id_by(full_data_output_clean, "social", "code", "19") %>% print() %>% suppressMessages()


# plot_growth_state_id(full_data_output_clean, "bot", "19")
# plot_growth_state_id(full_data_output_clean, "social", "19")

3.3 Individual growth (object not considered) - instructors excluded

Red = Loess

Black = Spline regression (1st degree polynomial), knots = every second time point

full_data_output_clean_ic <-
  full_data_output_clean %>%
  dplyr::filter(code == "IC")

cowplot::plot_grid(
  plot_growth_state_loess(full_data_output_clean_ic, "bot", "10") + theme(legend.position="none"),
  plot_growth_state_loess(full_data_output_clean_ic, "social", "10") + theme(legend.position="none"),
  nrow = 2
)


cowplot::plot_grid(
  plot_growth_state_loess(full_data_output_clean_ic, "bot", "15") + theme(legend.position="none"),
  plot_growth_state_loess(full_data_output_clean_ic, "social", "15") + theme(legend.position="none"),  
  nrow = 2
)


cowplot::plot_grid(
  plot_growth_state_loess(full_data_output_clean_ic, "bot", "16") + theme(legend.position="none"),
  plot_growth_state_loess(full_data_output_clean_ic, "social", "16") + theme(legend.position="none"),  
  nrow = 2
)


cowplot::plot_grid(
  plot_growth_state_loess(full_data_output_clean_ic, "bot", "17") + theme(legend.position="none"),
  plot_growth_state_loess(full_data_output_clean_ic, "social", "17") + theme(legend.position="none"),  
  nrow = 2
)


cowplot::plot_grid(
  plot_growth_state_loess(full_data_output_clean_ic, "bot", "18") + theme(legend.position="none"),
  plot_growth_state_loess(full_data_output_clean_ic, "social", "18") + theme(legend.position="none"), 
  nrow = 2
)

  
cowplot::plot_grid(
  plot_growth_state_loess(full_data_output_clean_ic, "bot", "19") + theme(legend.position="none"),
  plot_growth_state_loess(full_data_output_clean_ic, "social", "19") + theme(legend.position="none"), 
  nrow = 2
)

3.4 Alternating GameStates 10 and 17 for each participant by condition

3.4.1 All participans

plot_growth_state1017_id(full_data_output_clean)

3.4.2 Partcipants with both conditions

full_data_output_clean %>%
  dplyr::filter(id %in% ids_full_subj) %>%
  plot_growth_state1017_id()

3.4.3 GameState 19, only first object, individual level average

Order is not accounted for

plot_gs19_first <- 
  full_data_output_clean %>%
  dplyr::select(id, condition, score, newGameState_clean, markerType) %>%      
  dplyr::filter(newGameState_clean == "19") %>%
  dplyr::group_by(id, condition) %>%  
  dplyr::mutate(first_marker = dplyr::if_else(markerType == dplyr::first(markerType), "yes", "no")) %>%  
  dplyr::filter(first_marker == "yes") %>%
  dplyr::mutate(time = dplyr::row_number()) %>%
    ggplot(aes(x = time, y = score)) +
    geom_line() +
    geom_point() +
    # facet_wrap(score ~ condition, strip.position = "top") +
    # facet_grid(condition ~ id) +    
    facet_grid(rows = vars(id), cols = vars(condition)) + 
    ylim(0, 100) +
    scale_x_continuous(breaks = 1:16) +
    ggtitle(paste0("Game state: ", "19")) +
    theme_bw() 

suppressMessages(print(plot_gs19_first))

full_data_output_clean %>%
dplyr::select(id, condition, score, newGameState_clean, markerType) %>%      
dplyr::filter(newGameState_clean == "19") %>%
dplyr::group_by(id, condition) %>%  
dplyr::mutate(first_marker = dplyr::if_else(markerType == dplyr::first(markerType), "yes", "no")) %>%  
dplyr::filter(first_marker == "yes") %>%
dplyr::summarise(mean_score = mean(score, na.rm = TRUE)) %>%
  ggstatsplot::ggwithinstats(
    x = condition,
    y = mean_score,
    outlier.tagging = TRUE,                   
    outlier.label = id, 
    title = "GameState: 19"
  )


4 Session Info

R version 4.1.0 (2021-05-18)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 8.1 x64 (build 9600)

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    
system code page: 1252

attached base packages:
[1] splines   stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] rio_0.5.29         ggstatsplot_0.8.0  cowplot_1.1.1      scales_1.2.0       ggpubr_0.4.0       summarytools_1.0.0 rstatix_0.7.0     
 [8] broom_0.7.11       psych_2.1.9        forcats_0.5.1      stringr_1.4.0      dplyr_1.0.9        purrr_0.3.4        readr_2.0.1       
[15] tidyr_1.1.3        tibble_3.1.7       ggplot2_3.3.5      tidyverse_1.3.1    papaja_0.1.0.9997  pacman_0.5.1      

loaded via a namespace (and not attached):
  [1] readxl_1.3.1              pairwiseComparisons_3.1.6 backports_1.2.1           plyr_1.8.6                gmp_0.6-2                
  [6] crosstalk_1.1.1           kSamples_1.2-9            ipmisc_6.0.2              TH.data_1.0-10            pryr_0.1.5               
 [11] digest_0.6.28             SuppDists_1.1-9.7         htmltools_0.5.2           magick_2.7.3              fansi_0.5.0              
 [16] magrittr_2.0.1            checkmate_2.0.0           memoise_2.0.0             paletteer_1.4.0           tzdb_0.1.2               
 [21] openxlsx_4.2.4            modelr_0.1.8              matrixStats_0.60.1        sandwich_3.0-1            colorspace_2.0-3         
 [26] rvest_1.0.2               ggrepel_0.9.1             haven_2.4.3               xfun_0.30                 prismatic_1.0.0          
 [31] tcltk_4.1.0               crayon_1.5.1              jsonlite_1.8.0            zeallot_0.1.0             survival_3.2-13          
 [36] zoo_1.8-9                 glue_1.6.2                gtable_0.3.0              emmeans_1.6.3             MatrixModels_0.5-0       
 [41] statsExpressions_1.1.0    car_3.0-11                Rmpfr_0.8-4               abind_1.4-5               rapportools_1.0          
 [46] mvtnorm_1.1-2             DBI_1.1.1                 PMCMRplus_1.9.0           Rcpp_1.0.7                xtable_1.8-4             
 [51] performance_0.7.3         tmvnsim_1.0-2             foreign_0.8-81            DT_0.19                   htmlwidgets_1.5.3        
 [56] datawizard_0.2.0.1        httr_1.4.3                ellipsis_0.3.2            farver_2.1.0              pkgconfig_2.0.3          
 [61] reshape_0.8.8             sass_0.4.1                multcompView_0.1-8        dbplyr_2.1.1              utf8_1.2.2               
 [66] labeling_0.4.2            effectsize_0.4.5          tidyselect_1.1.2          rlang_1.0.2               munsell_0.5.0            
 [71] cellranger_1.1.0          tools_4.1.0               cachem_1.0.6              cli_3.0.1                 generics_0.1.2           
 [76] evaluate_0.15             fastmap_1.1.0             yaml_2.3.5                BWStest_0.2.2             rematch2_2.1.2           
 [81] knitr_1.39                fs_1.5.2                  zip_2.2.0                 pander_0.6.5              WRS2_1.1-3               
 [86] pbapply_1.4-3             nlme_3.1-152              xml2_1.3.3                correlation_0.7.0         compiler_4.1.0           
 [91] rstudioapi_0.13           curl_4.3.2                ggsignif_0.6.2            reprex_2.0.1              bslib_0.3.1              
 [96] stringi_1.7.4             highr_0.9                 parameters_0.14.0         lattice_0.20-44           Matrix_1.3-4             
[101] vctrs_0.4.1               pillar_1.7.0              lifecycle_1.0.1           mc2d_0.1-21               jquerylib_0.1.4          
[106] estimability_1.3          data.table_1.14.0         insight_0.14.4            patchwork_1.1.1           R6_2.5.1                 
[111] BayesFactor_0.9.12-4.2    codetools_0.2-18          boot_1.3-28               MASS_7.3-54               gtools_3.9.2             
[116] assertthat_0.2.1          withr_2.5.0               mnormt_2.0.2              multcomp_1.4-17           mgcv_1.8-36              
[121] bayestestR_0.11.0         parallel_4.1.0            hms_1.1.1                 grid_4.1.0                coda_0.19-4              
[126] rmarkdown_2.14            carData_3.0-4             lubridate_1.7.10          base64enc_0.1-3          

 


A work by Claudiu Papasteri

 

LS0tDQp0aXRsZTogIjxicj4gU1RBRCAtIERlbW8gYW5kIEltaXRhdGlvbiBNZXRyaWNzIGZvciBpRUVHIiANCnN1YnRpdGxlOiAiUHJlbGltaW5hcnkgQW5hbHlzaXMiDQphdXRob3I6ICI8YnI+IENsYXVkaXUgUGFwYXN0ZXJpIg0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJW0gJVknKWAiDQpvdXRwdXQ6IA0KICAgIGh0bWxfbm90ZWJvb2s6DQogICAgICAgICAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICAgICAgICAgIHRvYzogdHJ1ZQ0KICAgICAgICAgICAgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICAgICAgICAgIHRoZW1lOiBzcGFjZWxhYg0KICAgICAgICAgICAgaGlnaGxpZ2h0OiB0YW5nbw0KICAgICAgICAgICAgZm9udC1mYW1pbHk6IEFyaWFsDQogICAgICAgICAgICBmaWdfd2lkdGg6IDEwDQogICAgICAgICAgICBmaWdfaGVpZ2h0OiA5DQogICAgIyBwZGZfZG9jdW1lbnQ6IA0KICAgICAgICAgICAgIyB0b2M6IHRydWUNCiAgICAgICAgICAgICMgIHRvY19kZXB0aDogMg0KICAgICAgICAgICAgIyAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgICAgICAgICAjIGZvbnRzaXplOiAxMXB0DQogICAgICAgICAgICAjIGdlb21ldHJ5OiBtYXJnaW49MWluDQogICAgICAgICAgICAjIGZpZ193aWR0aDogNw0KICAgICAgICAgICAgIyBmaWdfaGVpZ2h0OiA2DQogICAgICAgICAgICAjIGZpZ19jYXB0aW9uOiB0cnVlDQogICAgIyBnaXRodWJfZG9jdW1lbnQ6IA0KICAgICAgICAgICAgIyB0b2M6IHRydWUNCiAgICAgICAgICAgICMgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICAjIGh0bWxfcHJldmlldzogZmFsc2UNCiAgICAgICAgICAgICMgZmlnX3dpZHRoOiA1DQogICAgICAgICAgICAjIGZpZ19oZWlnaHQ6IDUNCiAgICAgICAgICAgICMgZGV2OiBqcGVnDQotLS0NCg0KPCEtLSBTZXR1cCAtLT4NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGtpbnRyIG9wdGlvbnMNCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgY29tbWVudCA9ICIjIiwNCiAgY29sbGFwc2UgPSBUUlVFLA0KICBlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gVFJVRSwgY2FjaGUgPSBUUlVFICAgICAgICMgZWNobyA9IEZhbHNlIGZvciBnaXRodWJfZG9jdW1lbnQsIGJ1dCB3aWxsIGJlIGZvbGRlZCBpbiBodG1sX25vdGVib29rDQopDQoNCm9wdGlvbnMoZHBseXIuc3VtbWFyaXNlLmluZm9ybSA9IEZBTFNFKSAgICMgYW5ub3lpbmcgc3VtbWFyaXplIG1lc3NhZ2VzIHBhc3MgdGhyb3VnaHQgbWVzc2FnZT1GQUxTRQ0KDQojIEdlbmVyYWwgUiBvcHRpb25zIGFuZCBpbmZvDQpTeXMuc2V0ZW52KGBfUl9TM19NRVRIT0RfUkVHSVNUUkFUSU9OX05PVEVfT1ZFUldSSVRFU19gID0gImZhbHNlIikgIyBzdXBwcmVzcyAiUzMgbWV0aG9kIG92ZXJ3cml0dGVuIiBiZWZvcmUgbG9hZGluZyBwYWNrYWdlcw0Kc2V0LnNlZWQoMTExKSAgICAgICAgICAgICAgICMgaW4gY2FzZSB3ZSB1c2UgcmFuZG9taXplZCBwcm9jZWR1cmVzICAgICAgIA0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICAgICAgICMgcG9zaXRpdmUgdmFsdWVzIGJpYXMgdG93YXJkcyBmaXhlZCBhbmQgbmVnYXRpdmUgdG93YXJkcyBzY2llbnRpZmljIG5vdGF0aW9uDQoNCiMgTG9hZCBwYWNrYWdlcw0KaWYgKCFyZXF1aXJlKCJwYWNtYW4iKSkgaW5zdGFsbC5wYWNrYWdlcygicGFjbWFuIikNCnBhY2thZ2VzIDwtIGMoDQogICJwYXBhamEiLA0KICAidGlkeXZlcnNlIiwgICAgICANCiAgInBzeWNoIiwgICAgICAgICAgDQogICJicm9vbSIsICJyc3RhdGl4IiwNCiAgInN1bW1hcnl0b29scyIsICAgICAgICAgICAgDQogICJnZ3Bsb3QyIiwgImdncHViciIsICJzY2FsZXMiLCAic3BsaW5lcyIsICJjb3dwbG90IiwgImdnc3RhdHNwbG90IiwgICAgICAgIA0KICAicmlvIg0KICAjICwgLi4uDQopDQppZiAoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQ0KcGFjbWFuOjpwX2xvYWQoY2hhciA9IHBhY2thZ2VzKQ0KDQojIFRoZW1lcyBmb3IgZ2dwbG90MiBwbG90aW5nIChoZXJlIHVzZWQgQVBBIHN0eWxlKQ0KdGhlbWVfc2V0KHRoZW1lX2FwYSgpKQ0KYGBgDQoNCjwhLS0gUmVwb3J0IC0tPg0KDQojIFJ1biBkZW1vaW1pdE1ldHJpY3NfY2xlYW50YWJsZSBzY3JpcHQNCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpzY3JpcHRfZm9sZGVyIDwtICJDOi9Vc2Vycy9NaWhhaS9EZXNrdG9wL1IgTm90ZWJvb2tzL25vdGVib29rcy9TVEFELWRlbW9pbWl0TWV0cmljcy9TY3JpcHRzIiANCnNjcmlwdF9uYW1lIDwtICJkZW1vaW1pdE1ldHJpY3NfdG9fY2xlYW50YWJsZV9pZWVnLlIiDQpzb3VyY2UoZmlsZS5wYXRoKHNjcmlwdF9mb2xkZXIsIHNjcmlwdF9uYW1lKSkNCmBgYA0KDQpgYGB7cn0NCmZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4gPC0NCiAgZnVsbF9kYXRhX291dHB1dF9jbGVhbiAlPiUNCiAgdGlkeXI6OnNlcGFyYXRlKGlkLCBpbnRvID0gYygibnVtX2lkIiwgImNvZGUiKSwgIig/PD1bMC05XSkoPz1bYS16QS1aXSkiLCByZW1vdmUgPSBGQUxTRSkgJT4lDQogIGRwbHlyOjptdXRhdGUoaWQgPSBhcy5mYWN0b3IoaWQpLA0KICAgICAgICAgICAgICAgIGNvZGUgPSBhcy5mYWN0b3IoY29kZSkNCiAgKQ0KYGBgDQoNCg0KIyBEYXRhDQoNCiMjIEluZm86DQoNCi0gICBEZW1vIHNjb3Jlcw0KDQogICAgLSAgIG9iamVjdCByZXNwb25zZSBieSBuYXZpZ2F0b3IgKGluZGl2aWR1YWwgc2NvcmUpIChHYW1lU3RhdGUgOSA9XD4gbmV3R2FtZVN0YXRlIDEwKQ0KDQotICAgSW1pdGF0aW9uIHNjb3Jlcw0KDQogICAgLSAgIDFzdCByb3cgZm9yIHN0YXJ0IChHYW1lU3RhdGUgMTQgPVw+IG5ld0dhbWVTdGF0ZSAxNSkNCiAgICAtICAgMm5kIHJvdyBmb3IgZmxhZyAoR2FtZVN0YXRlIDE1ID1cPiBuZXdHYW1lU3RhdGUgMTYpDQogICAgLSAgIDNyZCByb3cgPSBmaXJzdCBvYmplY3QgcmVzcG9uc2UgYnkgbmF2aWdhdG9yIChpbmRpdmlkdWFsIHNjb3JlKSAoR2FtZVN0YXRlIDE2ID1cPiBuZXdHYW1lU3RhdGUgMTcpDQogICAgLSAgIDR0aCByb3cgPSBzdWdnZXN0aW9uIG1hcmtlciBieSBvYnNlcnZlciAob2JzZXJ2ZXIgc2NvcmUpIChHYW1lU3RhdGUgMTcgPVw+IG5ld0dhbWVTdGF0ZSAxOCkNCiAgICAtICAgNXRoIHJvdyA9IDJuZCBvYmplY3QgcmVzcG9uc2UgYnkgbmF2aWdhdG9yIChjb2xsYWJvcmF0aXZlIHNjb3JlKSAoR2FtZVN0YXRlIDE4ID1cPiBuZXdHYW1lU3RhdGUgMTkpDQoNCi0gICBWYXJpYWJsZXM6DQoNCiAgICAtICAgaWQgY2F0ZWdvcmljYWwgLSB1bmlxdWUgaWRlbnRpZmllcg0KICAgIC0gICBjb2RlIGNhdGVnb3JpY2FsIC0gSUMgPSBwYWNpZW50IC8gUElDID0gaW5zdHJ1Y3Rvcg0KICAgIC0gICBjb25kaXRpb24gY2F0ZWdvcmljYWwgLSAic29jaWFsIiBvciAiYm90Ig0KICAgIC0gICBvcmRlciBjYXRlZ29yaWNhbCAtIDEgb3IgMiB0aGUgb3JkZXIgb2YgY29uZGl0aW9ucw0KICAgIC0gICB3aG8gY2F0ZXJnb3JpY2FsIC0gMSBvciAyIGNvZGVzIGZvciB3aG8ncyByZWNvcmRpbmcgaXQgaXMgKGRhdGEgb25seSBmb3IgY3VycmVudCBpZCBpcyB3aGVuOiAqd2hvID09IHBsYXllclR5cGUqKQ0KDQogICAgPCEtLSArIG5ld0dhbWVTdGF0ZV9mIGNhdGVnb3JpY2FsIC0gY29kZXMgZm9yIEdhbWVTdGF0ZXMgKDUtMTEgYXJlIERlbW8sIDEyLTIwIGFyZSBJbWl0KSAtLT4NCg0KICAgIDwhLS0gKyBkZW1vaW1pdFN0YXRlIGNhdGVnb3JpY2FsIC0gIkRlbW8iIG9yICJJbWl0IiBkZXBlbmRpbmcgb24gc3RhdGUgLS0+DQoNCiAgICAtICAgbmV3R2FtZVN0YXRlX2NsZWFuIGNhdGVnb3JpY2FsIC0gY29kZXMgZm9yIEdhbWVTdGF0ZXMgKDUtMTEgYXJlIERlbW8sIDEyLTIwIGFyZSBJbWl0KQ0KICAgIC0gICBkZW1vaW1pdFN0YXRlX2NsZWFuIGNhdGVnb3JpY2FsIC0gIkRlbW8iIG9yICJJbWl0IiBkZXBlbmRpbmcgb24gc3RhdGUNCiAgICAtICAgcGxheWVyVHlwZSBjYXRlZ29yaWNhbCAtIDEgb3IgMiBkZXBlbmRpbmcgb24gR2FtZVN0YXRlIChzaG91bGQgYmUgdXNlZCB0b2dldGhlciB3aXRoIHZhciAqd2hvKikNCiAgICAtICAgbWFya2VyVHlwZSBjYXRlZ29yaWNhbCAtIGNvZGVzIGZvciB0aGUgb2JqZWN0IChzZWUgZG9jdW1lbnRhdGlvbiksIGJ1dCBpdCBhY3R1YWxseSBmb2xsb3dzIHRoZSB0aGUgYWJvdmUgSW5mbyAoZGVwZW5kZXMgb24gR2FtZVN0YXRlKQ0KICAgIC0gICBzY29yZSBjb250aW51b3VzIC0gZm9sbG93cyB0aGUgdGhlIGFib3ZlIEluZm8gKGRlcGVuZHMgb24gR2FtZVN0YXRlKQ0KDQpgYGB7cn0NCmZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4gJT4lDQogIERUOjpkYXRhdGFibGUoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgZXhjZWwgZG93bmxvYWRhYmxlICBEVCB0YWJsZQ0KICBleHRlbnNpb25zID0gJ0J1dHRvbnMnLA0KICBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsDQogICAgICAgICAgICAgICAgIHNjcm9sbFggPSAnNTAwcHgnLCANCiAgICAgICAgICAgICAgICAgZG9tID0gJ0JmcnRpcCcsIA0KICAgICAgICAgICAgICAgICBidXR0b25zID0gYygnZXhjZWwnLCAiY3N2IikpKSAlPiUNCiAgRFQ6OmZvcm1hdFN0eWxlKG5hbWVzKGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4pLGxpbmVIZWlnaHQgPSAiNjAlIikgICAgIyBzbGltbWVyIHJvd3MNCmBgYA0KDQojIFByZWxpbWluYXJ5IEFuYWx5c2VzDQoNCiMjIyBGdW5jdGlvbnMNCg0KYGBge3J9DQpwbG90X2dyb3d0aF9zdGF0ZV9pZCA8LSBmdW5jdGlvbihkYXRhLCBjb25kLCBnYW1lc3RhdGUsIHRpbWVfbGltID0gMjApIHsNCiAgZGF0YSAlPiUNCiAgZHBseXI6OmZpbHRlcihjb25kaXRpb24gPT0gY29uZCwgbmV3R2FtZVN0YXRlX2NsZWFuID09IGdhbWVzdGF0ZSkgJT4lDQogIGdyb3VwX2J5KGlkKSAlPiUNCiAgZHBseXI6Om11dGF0ZSh0aW1lID0gZHBseXI6OnJvd19udW1iZXIoKSkgJT4lDQogIGRwbHlyOjpmaWx0ZXIodGltZSA8IHRpbWVfbGltKSAlPiUgIA0KICAgIGdncGxvdChhZXMoeCA9IHRpbWUsIHkgPSBzY29yZSkpICsNCiAgICBnZW9tX2xpbmUoKSArDQogICAgZmFjZXRfd3JhcCh+aWQpICsNCiAgICB5bGltKDAsIDEwMCkgKw0KICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjE0KSArDQogICAgZ2d0aXRsZShwYXN0ZTAoIkNvbmRpdGlvbjogIiwgY29uZCwgIiwgIiwgIkdhbWUgc3RhdGU6ICIsIGdhbWVzdGF0ZSkpDQp9DQoNCiMgZS5nLg0KIyBmdWxsX2RhdGFfb3V0cHV0X2NsZWFuICU+JQ0KIyAgIGRwbHlyOjpmaWx0ZXIoY29uZGl0aW9uID09ICJib3QiLCBuZXdHYW1lU3RhdGVfY2xlYW4gPT0gIjEwIikgJT4lDQojICAgZ3JvdXBfYnkoaWQpICU+JQ0KIyAgIGRwbHlyOjptdXRhdGUodGltZSA9IGRwbHlyOjpyb3dfbnVtYmVyKCkpICU+JQ0KIyAgIGdncGxvdChhZXMoeCA9IHRpbWUsIHkgPSBzY29yZSkpICsNCiMgICBnZW9tX2xpbmUoKSArDQojICAgZmFjZXRfd3JhcCh+aWQpDQoNCnBsb3RfZ3Jvd3RoX3N0YXRlX2lkX2J5IDwtIGZ1bmN0aW9uKGRhdGEsIGNvbmQsIGNvbF9ieSA9IGMoIm9yZGVyIiwgImNvZGUiKSwgZ2FtZXN0YXRlLCB0aW1lX2xpbSA9IDIwKSB7DQogIGRhdGEgJT4lDQogIGRwbHlyOjpmaWx0ZXIoY29uZGl0aW9uID09IGNvbmQsIG5ld0dhbWVTdGF0ZV9jbGVhbiA9PSBnYW1lc3RhdGUpICU+JQ0KICBncm91cF9ieShpZCkgJT4lDQogIGRwbHlyOjptdXRhdGUodGltZSA9IGRwbHlyOjpyb3dfbnVtYmVyKCksDQogICAgICAgICAgICAgICAgb3JkZXIgPSBhcy5mYWN0b3Iob3JkZXIpLA0KICAgICAgICAgICAgICAgIGNvZGUgPSBhcy5mYWN0b3IoY29kZSkpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKHRpbWUgPCB0aW1lX2xpbSkgJT4lICANCiAgICBnZ3Bsb3QoYWVzKHggPSB0aW1lLCB5ID0gc2NvcmUpKSArDQogICAgZ2VvbV9saW5lKGFlc19zdHJpbmcoY29sb3IgPSBjb2xfYnkpKSArDQogICAgZ2VvbV9wb2ludChhZXNfc3RyaW5nKGNvbG9yID0gY29sX2J5KSkgKw0KICAgIGZhY2V0X3dyYXAofmlkKSArDQogICAgeWxpbSgwLCAxMDApICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMToxNCkgKw0KICAgIGdndGl0bGUocGFzdGUwKCJDb25kaXRpb246ICIsIGNvbmQsICIsICIsICJHYW1lIHN0YXRlOiAiLCBnYW1lc3RhdGUpKQ0KfQ0KDQoNCg0KDQpwbG90X2dyb3d0aF9zdGF0ZV9sb2VzcyA8LSBmdW5jdGlvbihkYXRhLCBjb25kLCBnYW1lc3RhdGUsIHRpbWVfbGltID0gMjApIHsNCiAgZGF0YSAlPiUNCiAgZHBseXI6OmZpbHRlcihjb25kaXRpb24gPT0gY29uZCwgbmV3R2FtZVN0YXRlX2NsZWFuID09IGdhbWVzdGF0ZSkgJT4lDQogIGdyb3VwX2J5KGlkKSAlPiUNCiAgZHBseXI6Om11dGF0ZSh0aW1lID0gZHBseXI6OnJvd19udW1iZXIoKSkgJT4lDQogIGRwbHlyOjpmaWx0ZXIodGltZSA8IHRpbWVfbGltKSAlPiUgICANCiAgICBnZ3Bsb3QoYWVzKHggPSB0aW1lLCB5ID0gc2NvcmUpKSArDQogICAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IGFzLmZhY3RvcihpZCkpLCBhbHBoYSA9IC41KSArDQogICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgZm9ybXVsYSA9ICJ5IH4geCIsIGNvbG9yID0gInJlZCIsIGZpbGwgPSAicmVkIikgKw0KICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGZvcm11bGEgPSB5IH4gc3BsaW5lczo6YnMoeCwga25vdHMgPSBzZXEoMiAsIDE2LCBieSA9IDIpLCBkZWdyZWUgPSAxKSwgDQogICAgICAgICAgICAgICAgc2UgPSBGQUxTRSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImdyYXkiLCBhbHBoYSA9IDAuOCkgKw0KICAgIHlsaW0oMCwgMTAwKSArDQogICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IDE6MTQpICsNCiAgICBnZ3RpdGxlKHBhc3RlMCgiQ29uZGl0aW9uOiAiLCBjb25kLCAiLCAiLCAiR2FtZSBzdGF0ZTogIiwgZ2FtZXN0YXRlKSkgKw0KICAgIGxhYnMoY29sb3IgPSAiaWQiKSAgDQp9DQogIA0KIyBlLmUuDQojIGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4gJT4lDQojIGRwbHlyOjpmaWx0ZXIoY29uZGl0aW9uID09ICJib3QiLCBuZXdHYW1lU3RhdGVfY2xlYW4gPT0gIjEwIikgJT4lDQojIGdyb3VwX2J5KGlkKSAlPiUNCiMgZHBseXI6Om11dGF0ZSh0aW1lID0gZHBseXI6OnJvd19udW1iZXIoKSkgJT4lDQojIGdncGxvdChhZXMoeCA9IHRpbWUsIHkgPSBzY29yZSkpICsNCiMgZ2VvbV9saW5lKGFlcyhjb2xvciA9IGFzLmZhY3RvcihpZCkpLCBhbHBoYSA9IC41KSArDQojIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIGZvcm11bGEgPSAieSB+IHgiKQ0KDQpwbG90X2dyb3d0aF9zdGF0ZTEwMTdfaWQgPC0gZnVuY3Rpb24oZGF0YSwgY29uZHMgPSBjKCJzb2NpYWwiLCAiYm90IiksIHRpbWVfbGltID0gMjApIHsNCiAgZGF0YSAlPiUNCiAgZHBseXI6OmZpbHRlcihjb25kaXRpb24gJWluJSBjb25kcywgbmV3R2FtZVN0YXRlX2NsZWFuICVpbiUgYygiMTAiLCAiMTciKSkgJT4lDQogIGRwbHlyOjptdXRhdGUobmV3R2FtZVN0YXRlX2NsZWFuID0gYXMuZmFjdG9yKG5ld0dhbWVTdGF0ZV9jbGVhbikpICU+JSAgDQogIGRwbHlyOjpncm91cF9ieShpZCwgY29uZGl0aW9uKSAlPiUNCiAgZHBseXI6Om11dGF0ZSh0aW1lID0gZHBseXI6OnJvd19udW1iZXIoKSkgJT4lDQogIGRwbHlyOjpmaWx0ZXIodGltZSA8IHRpbWVfbGltKSAlPiUgDQogICAgZ2dwbG90KGFlcyh4ID0gdGltZSwgeSA9IHNjb3JlLCBjb2xvciA9IGNvbmRpdGlvbikpICsNCiAgICBnZW9tX2xpbmUoKSArDQogICAgZ2VvbV9wb2ludChhZXMoc2hhcGUgPSBuZXdHYW1lU3RhdGVfY2xlYW4pKSArDQogICAgZmFjZXRfd3JhcCh+aWQpICsNCiAgICB5bGltKDAsIDEwMCkgKw0KICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjE0KSArDQogICAgZ2d0aXRsZSgiQWx0ZXJuYXRpbmcgR2FtZVN0YXRlIDEwIGFuZCAxNyIpICsgDQogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikNCn0NCg0KDQoNCm15X2dnd2l0aGluc3RhdHMyIDwtIGZ1bmN0aW9uKGRhdGEsIHRpdGxlID0gTlVMTCwgeCwgeSwgZ2FtZXN0YXRlLCB0aW1lX2xpbSA9IDIwLCBvdXRsaWVyLmxhYmVsLCB4bGFiLCB5bGFiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dGxpZXIudGFnZ2luZyA9IEZBTFNFLCByZXN1bHRzLnN1YnRpdGxlID0gVFJVRSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZW50cmFsaXR5LmxhYmVsLmFyZ3MgPSBUUlVFLCBwb2ludC5wYXRoID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAicGFyYW1ldHJpYyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uKSB7ICAjIC4uLiBmb3IgbGltaXRzIGFuZCBicmVha3MNCiAgeCA8LSBybGFuZzo6ZW5xdW8oeCkNCiAgeSA8LSBybGFuZzo6ZW5xdW8oeSkNCiAgb3V0bGllci5sYWJlbCA8LSBybGFuZzo6ZW5xdW8ob3V0bGllci5sYWJlbCkNCiAgDQogIGlmKGlzLm51bGwodGl0bGUpKSB7DQogICAgdGl0bGUgPC0gcGFzdGUwKCJHYW1lIHN0YXRlOiAiLCBnYW1lc3RhdGUpDQogIH0NCiAgDQogIGRhdGEgPC0NCiAgICBkYXRhICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoISFvdXRsaWVyLmxhYmVsLCAhIXgsICEheSwgbmV3R2FtZVN0YXRlX2NsZWFuKSAlPiUgICAgICAjIG5ld0dhbWVTdGF0ZV9jbGVhbiBpcyBoYXJkY29kZWQgaGVyZQ0KICAgIGRwbHlyOjpmaWx0ZXIobmV3R2FtZVN0YXRlX2NsZWFuID09IGdhbWVzdGF0ZSkgJT4lDQogICAgZ3JvdXBfYnkoISFvdXRsaWVyLmxhYmVsLCAhIXgpICU+JQ0KICAgIGRwbHlyOjptdXRhdGUodGltZSA9IGRwbHlyOjpyb3dfbnVtYmVyKCkpICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIodGltZSA8IHRpbWVfbGltKSAlPiUgICANCiAgICBkcGx5cjo6c3VtbWFyaXNlKG1lYW5fc2NvcmUgPSBtZWFuKCEheSwgbmEucm0gPSBUUlVFKSkNCiAgICANCiAgaWYoY2VudHJhbGl0eS5sYWJlbC5hcmdzKXsNCiAgICBjZW50cmFsaXR5LmxhYmVsLmFyZ3MgPC0gbGlzdChzaXplID0gMywgbnVkZ2VfeCA9IDAuMiwgc2VnbWVudC5saW5ldHlwZSA9IDUsIGZpbGwgPSAiI0ZGRjhFNyIpDQogIH1lbHNlew0KICAgIGNlbnRyYWxpdHkubGFiZWwuYXJncyA8LSBsaXN0KHNpemUgPSAwLCBudWRnZV94ID0gMTAsIHNlZ21lbnQubGluZXR5cGUgPSAwLCBhbHBoYSA9IDApICMgdmVyeSBoYWNreSB3YXkgb2Ygbm90IHNob3dpbmcgbGFiZWwNCiAgfQ0KICANCiAgZGF0YSAlPiUNCiAgICBnZ3N0YXRzcGxvdDo6Z2d3aXRoaW5zdGF0cygNCiAgICAgIHggPSAhIXgsDQogICAgICB5ID0gbWVhbl9zY29yZSwgICAgICAgICAgICAgICMgaGVyZSB3ZSBoYXZlIHRoZSBtZWFuIHNjb3JlIGZvciBpZCwgbm90ICEheQ0KICAgICAgdGl0bGUgPSB0aXRsZSwNCiAgICAgIHhsYWIgPSB4bGFiLA0KICAgICAgeWxhYiA9IHlsYWIsDQogICAgICBvdXRsaWVyLnRhZ2dpbmcgPSBvdXRsaWVyLnRhZ2dpbmcsICAgICAgICAgICAgICAgICAgICAjIHdoZXRoZXIgb3V0bGluZXMgbmVlZCB0byBiZSB0YWdnZWQNCiAgICAgIG91dGxpZXIubGFiZWwgPSAhIW91dGxpZXIubGFiZWwsICAgICAgICAgICAgICAgICAgICAgICMgdmFyaWFibGUgdG8gYmUgdXNlZCBmb3IgdGFnZ2luZyBvdXRsaWVycw0KICAgICAgb3V0bGllci5jb2VmID0gMiwNCiAgICAgIHBhaXJ3aXNlLmNvbXBhcmlzb25zID0gVFJVRSwNCiAgICAgIHBhaXJ3aXNlLmRpc3BsYXkgPSAiYWxsIiwNCiAgICAgIHJlc3VsdHMuc3VidGl0bGUgPSByZXN1bHRzLnN1YnRpdGxlLA0KICAgICAgdHlwZSA9IHR5cGUsDQogICAgICBiZi5tZXNzYWdlID0gRkFMU0UsIA0KICAgICAgcC5hZGp1c3QubWV0aG9kID0gIm5vbmUiLA0KICAgICAgcG9pbnQucGF0aCA9IHBvaW50LnBhdGgsDQogICAgICBnZ3RoZW1lID0gZ2dwcmlzbTo6dGhlbWVfcHJpc20oKSwNCiAgICAgICMgcGFja2FnZSA9ICJSQ29sb3JCcmV3ZXIiLCAgIyAiZ2dzY2kiLA0KICAgICAgIyBwYWxldHRlID0gIkRhcmsiLCAgICAgICAgICMgImRlZmF1bHRfamNvIiwNCiAgICAgIHZpb2xpbi5hcmdzID0gbGlzdCh3aWR0aCA9IDAuOSwgYWxwaGEgPSAwLjIsIHNpemUgPSAxLCBjb2xvciA9ICJibGFjayIpLA0KICAgICAgY2VudHJhbGl0eS5wbG90dGluZyA9IFRSVUUsDQogICAgICBjZW50cmFsaXR5LnR5cGUgPSAicGFyYW1ldGVyaWMiLA0KICAgICAgY2VudHJhbGl0eS5wb2ludC5hcmdzID0gbGlzdChzaXplID0gNSwgY29sb3IgPSAiZGFya3JlZCIpLA0KICAgICAgY2VudHJhbGl0eS5sYWJlbC5hcmdzID0gY2VudHJhbGl0eS5sYWJlbC5hcmdzLA0KICAgICAgZ2dwbG90LmNvbXBvbmVudCA9IGxpc3QoDQogICAgICAgIHRoZW1lKA0KICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLCBzaXplID0gMTYpLA0KICAgICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLCBzaXplID0gMTIpLCANCiAgICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLCBzaXplID0gMTIpLCANCiAgICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkNCiAgICAgICkpDQogICAgKSArIHNjYWxlX2NvbG91cl9ncmV5KHN0YXJ0ID0gMC4yLCBlbmQgPSAwLjIpICsgICMgaGFja3kgd2F5IHRvIGNoYW5nZSBwb2ludCBjb2xvcg0KICAgIHlsaW0oMCwgMTAwKSArDQogICAgc2NhbGVfeV9jb250aW51b3VzKC4uLikNCn0NCg0KIyBlLmcuDQojIG15X2dnd2l0aGluc3RhdHMyKGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4sIHggPSBjb25kaXRpb24sIHkgPSBzY29yZSwgb3V0bGllci5sYWJlbCA9IGlkLCBnYW1lc3RhdGUgPSAxMCwNCiMgICAgICAgICAgICAgICAgICAgdGltZV9saW0gPSAyMCwgeGxhYiA9ICJDb25kaXRpb24iLCB5bGFiID0gInNjb3JlIikNCiAgICAgICAgICAgICAgICAgICANCmBgYA0KDQojIyBDaGVjayBiYWxhbmNlDQoNCiMjIyBBbGwgcGFydGljaXBhbnRzDQoNCmBgYHtyfQ0KY291bnRzX2lkX2NvbmRvcmQgPC0NCiAgZnVsbF9kYXRhX291dHB1dF9jbGVhbiAlPiUNCiAgZHBseXI6OmNvdW50KGlkLCBjb25kaXRpb24sIG9yZGVyKQ0KDQpjb3VudHNfaWRfY29uZG9yZCAlPiUgICAgICANCiAgcHJpbnQobiA9IEluZikNCg0KY291bnRzX2lkX2NvbmRvcmQgJT4lDQogIGRwbHlyOjpzZWxlY3QoY29uZGl0aW9uLCBvcmRlcikgJT4lDQogIHRhYmxlKCkgJT4lDQogIGtuaXRyOjprYWJsZShjYXB0aW9uID0gIk9yZGVyIikNCmBgYA0KDQojIyMgUGFydGljaXBhbnRzIHdpdGggYm90aCBjb25kaXRpb25zDQoNCmBgYHtyfQ0KaWRzX2Z1bGxfc3ViaiA8LQ0KICBmdWxsX2RhdGFfb3V0cHV0X2NsZWFuICU+JQ0KICBncm91cF9ieShpZCwgY29uZGl0aW9uKSAlPiUNCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUNCiAgZHBseXI6OmZpbHRlcihuKCkgPiAxKSAlPiUNCiAgZHBseXI6OnB1bGwoaWQpICU+JQ0KICB1bmlxdWUoKQ0KDQpmdWxsX2RhdGFfb3V0cHV0X2NsZWFuICU+JQ0KICBkcGx5cjo6ZmlsdGVyKGlkICVpbiUgaWRzX2Z1bGxfc3ViaikgJT4lDQogIGRwbHlyOjpjb3VudChpZCwgY29uZGl0aW9uLCBvcmRlcikgJT4lDQogIGRwbHlyOjpzZWxlY3QoY29uZGl0aW9uLCBvcmRlcikgJT4lDQogIHRhYmxlKCkgJT4lDQogIGtuaXRyOjprYWJsZShjYXB0aW9uID0gIk9yZGVyIikNCmBgYA0KDQoNCiMjIEluZGl2aWR1YWwgZ3Jvd3RoIChvYmplY3Qgbm90IGNvbnNpZGVyZWQpDQoNCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMH0NCnBsb3RfZ3Jvd3RoX3N0YXRlX2lkX2J5KGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4sICJib3QiLCAib3JkZXIiLCAiMTAiKSAgDQpwbG90X2dyb3d0aF9zdGF0ZV9pZF9ieShmdWxsX2RhdGFfb3V0cHV0X2NsZWFuLCAic29jaWFsIiwgImNvZGUiLCAiMTAiKSAlPiUgcHJpbnQoKSAlPiUgc3VwcHJlc3NNZXNzYWdlcygpDQoNCnBsb3RfZ3Jvd3RoX3N0YXRlX2lkX2J5KGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4sICJib3QiLCAib3JkZXIiLCAiMTUiKSAgDQpwbG90X2dyb3d0aF9zdGF0ZV9pZF9ieShmdWxsX2RhdGFfb3V0cHV0X2NsZWFuLCAic29jaWFsIiwgImNvZGUiLCAiMTUiKSAlPiUgcHJpbnQoKSAlPiUgc3VwcHJlc3NNZXNzYWdlcygpDQoNCnBsb3RfZ3Jvd3RoX3N0YXRlX2lkX2J5KGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4sICJib3QiLCAib3JkZXIiLCAiMTYiKSAgDQpwbG90X2dyb3d0aF9zdGF0ZV9pZF9ieShmdWxsX2RhdGFfb3V0cHV0X2NsZWFuLCAic29jaWFsIiwgImNvZGUiLCAiMTYiKSAlPiUgcHJpbnQoKSAlPiUgc3VwcHJlc3NNZXNzYWdlcygpDQoNCnBsb3RfZ3Jvd3RoX3N0YXRlX2lkX2J5KGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4sICJib3QiLCAib3JkZXIiLCAiMTciKSAgDQpwbG90X2dyb3d0aF9zdGF0ZV9pZF9ieShmdWxsX2RhdGFfb3V0cHV0X2NsZWFuLCAic29jaWFsIiwgImNvZGUiLCAiMTciKSAlPiUgcHJpbnQoKSAlPiUgc3VwcHJlc3NNZXNzYWdlcygpDQoNCnBsb3RfZ3Jvd3RoX3N0YXRlX2lkX2J5KGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4sICJib3QiLCAib3JkZXIiLCAiMTgiKSAgDQpwbG90X2dyb3d0aF9zdGF0ZV9pZF9ieShmdWxsX2RhdGFfb3V0cHV0X2NsZWFuLCAic29jaWFsIiwgImNvZGUiLCAiMTgiKSAlPiUgcHJpbnQoKSAlPiUgc3VwcHJlc3NNZXNzYWdlcygpDQoNCnBsb3RfZ3Jvd3RoX3N0YXRlX2lkX2J5KGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4sICJib3QiLCAib3JkZXIiLCAiMTkiKSAgDQpwbG90X2dyb3d0aF9zdGF0ZV9pZF9ieShmdWxsX2RhdGFfb3V0cHV0X2NsZWFuLCAic29jaWFsIiwgImNvZGUiLCAiMTkiKSAlPiUgcHJpbnQoKSAlPiUgc3VwcHJlc3NNZXNzYWdlcygpDQoNCiMgcGxvdF9ncm93dGhfc3RhdGVfaWQoZnVsbF9kYXRhX291dHB1dF9jbGVhbiwgImJvdCIsICIxOSIpDQojIHBsb3RfZ3Jvd3RoX3N0YXRlX2lkKGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW4sICJzb2NpYWwiLCAiMTkiKQ0KYGBgDQoNCiMjIEluZGl2aWR1YWwgZ3Jvd3RoIChvYmplY3Qgbm90IGNvbnNpZGVyZWQpIC0gaW5zdHJ1Y3RvcnMgZXhjbHVkZWQNCg0KUmVkID0gTG9lc3MNCg0KQmxhY2sgPSBTcGxpbmUgcmVncmVzc2lvbiAoMXN0IGRlZ3JlZSBwb2x5bm9taWFsKSwga25vdHMgPSBldmVyeSBzZWNvbmQgdGltZSBwb2ludA0KDQpgYGB7ciwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OH0NCmZ1bGxfZGF0YV9vdXRwdXRfY2xlYW5faWMgPC0NCiAgZnVsbF9kYXRhX291dHB1dF9jbGVhbiAlPiUNCiAgZHBseXI6OmZpbHRlcihjb2RlID09ICJJQyIpDQoNCmNvd3Bsb3Q6OnBsb3RfZ3JpZCgNCiAgcGxvdF9ncm93dGhfc3RhdGVfbG9lc3MoZnVsbF9kYXRhX291dHB1dF9jbGVhbl9pYywgImJvdCIsICIxMCIpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksDQogIHBsb3RfZ3Jvd3RoX3N0YXRlX2xvZXNzKGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW5faWMsICJzb2NpYWwiLCAiMTAiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLA0KICBucm93ID0gMg0KKQ0KDQpjb3dwbG90OjpwbG90X2dyaWQoDQogIHBsb3RfZ3Jvd3RoX3N0YXRlX2xvZXNzKGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW5faWMsICJib3QiLCAiMTUiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLA0KICBwbG90X2dyb3d0aF9zdGF0ZV9sb2VzcyhmdWxsX2RhdGFfb3V0cHV0X2NsZWFuX2ljLCAic29jaWFsIiwgIjE1IikgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSwgIA0KICBucm93ID0gMg0KKQ0KDQpjb3dwbG90OjpwbG90X2dyaWQoDQogIHBsb3RfZ3Jvd3RoX3N0YXRlX2xvZXNzKGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW5faWMsICJib3QiLCAiMTYiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLA0KICBwbG90X2dyb3d0aF9zdGF0ZV9sb2VzcyhmdWxsX2RhdGFfb3V0cHV0X2NsZWFuX2ljLCAic29jaWFsIiwgIjE2IikgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSwgIA0KICBucm93ID0gMg0KKQ0KDQpjb3dwbG90OjpwbG90X2dyaWQoDQogIHBsb3RfZ3Jvd3RoX3N0YXRlX2xvZXNzKGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW5faWMsICJib3QiLCAiMTciKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLA0KICBwbG90X2dyb3d0aF9zdGF0ZV9sb2VzcyhmdWxsX2RhdGFfb3V0cHV0X2NsZWFuX2ljLCAic29jaWFsIiwgIjE3IikgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSwgIA0KICBucm93ID0gMg0KKQ0KDQpjb3dwbG90OjpwbG90X2dyaWQoDQogIHBsb3RfZ3Jvd3RoX3N0YXRlX2xvZXNzKGZ1bGxfZGF0YV9vdXRwdXRfY2xlYW5faWMsICJib3QiLCAiMTgiKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLA0KICBwbG90X2dyb3d0aF9zdGF0ZV9sb2VzcyhmdWxsX2RhdGFfb3V0cHV0X2NsZWFuX2ljLCAic29jaWFsIiwgIjE4IikgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSwgDQogIG5yb3cgPSAyDQopDQogIA0KY293cGxvdDo6cGxvdF9ncmlkKA0KICBwbG90X2dyb3d0aF9zdGF0ZV9sb2VzcyhmdWxsX2RhdGFfb3V0cHV0X2NsZWFuX2ljLCAiYm90IiwgIjE5IikgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSwNCiAgcGxvdF9ncm93dGhfc3RhdGVfbG9lc3MoZnVsbF9kYXRhX291dHB1dF9jbGVhbl9pYywgInNvY2lhbCIsICIxOSIpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksIA0KICBucm93ID0gMg0KKQ0KYGBgDQoNCg0KIyMgQWx0ZXJuYXRpbmcgR2FtZVN0YXRlcyAxMCBhbmQgMTcgZm9yIGVhY2ggcGFydGljaXBhbnQgYnkgY29uZGl0aW9uDQoNCiMjIyBBbGwgcGFydGljaXBhbnMNCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xMn0NCnBsb3RfZ3Jvd3RoX3N0YXRlMTAxN19pZChmdWxsX2RhdGFfb3V0cHV0X2NsZWFuKQ0KYGBgDQoNCiMjIyBQYXJ0Y2lwYW50cyB3aXRoIGJvdGggY29uZGl0aW9ucw0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9MTF9DQpmdWxsX2RhdGFfb3V0cHV0X2NsZWFuICU+JQ0KICBkcGx5cjo6ZmlsdGVyKGlkICVpbiUgaWRzX2Z1bGxfc3ViaikgJT4lDQogIHBsb3RfZ3Jvd3RoX3N0YXRlMTAxN19pZCgpDQpgYGANCg0KDQojIyMgR2FtZVN0YXRlIDE5LCBvbmx5IGZpcnN0IG9iamVjdCwgaW5kaXZpZHVhbCBsZXZlbCBhdmVyYWdlDQoNCk9yZGVyIGlzIG5vdCBhY2NvdW50ZWQgZm9yDQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTE3LCBmaWcud2lkdGg9NywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnBsb3RfZ3MxOV9maXJzdCA8LSANCiAgZnVsbF9kYXRhX291dHB1dF9jbGVhbiAlPiUNCiAgZHBseXI6OnNlbGVjdChpZCwgY29uZGl0aW9uLCBzY29yZSwgbmV3R2FtZVN0YXRlX2NsZWFuLCBtYXJrZXJUeXBlKSAlPiUgICAgICANCiAgZHBseXI6OmZpbHRlcihuZXdHYW1lU3RhdGVfY2xlYW4gPT0gIjE5IikgJT4lDQogIGRwbHlyOjpncm91cF9ieShpZCwgY29uZGl0aW9uKSAlPiUgIA0KICBkcGx5cjo6bXV0YXRlKGZpcnN0X21hcmtlciA9IGRwbHlyOjppZl9lbHNlKG1hcmtlclR5cGUgPT0gZHBseXI6OmZpcnN0KG1hcmtlclR5cGUpLCAieWVzIiwgIm5vIikpICU+JSAgDQogIGRwbHlyOjpmaWx0ZXIoZmlyc3RfbWFya2VyID09ICJ5ZXMiKSAlPiUNCiAgZHBseXI6Om11dGF0ZSh0aW1lID0gZHBseXI6OnJvd19udW1iZXIoKSkgJT4lDQogICAgZ2dwbG90KGFlcyh4ID0gdGltZSwgeSA9IHNjb3JlKSkgKw0KICAgIGdlb21fbGluZSgpICsNCiAgICBnZW9tX3BvaW50KCkgKw0KICAgICMgZmFjZXRfd3JhcChzY29yZSB+IGNvbmRpdGlvbiwgc3RyaXAucG9zaXRpb24gPSAidG9wIikgKw0KICAgICMgZmFjZXRfZ3JpZChjb25kaXRpb24gfiBpZCkgKyAgICANCiAgICBmYWNldF9ncmlkKHJvd3MgPSB2YXJzKGlkKSwgY29scyA9IHZhcnMoY29uZGl0aW9uKSkgKyANCiAgICB5bGltKDAsIDEwMCkgKw0KICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjE2KSArDQogICAgZ2d0aXRsZShwYXN0ZTAoIkdhbWUgc3RhdGU6ICIsICIxOSIpKSArDQogICAgdGhlbWVfYncoKSANCg0Kc3VwcHJlc3NNZXNzYWdlcyhwcmludChwbG90X2dzMTlfZmlyc3QpKQ0KYGBgDQoNCmBgYHtyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD03fQ0KZnVsbF9kYXRhX291dHB1dF9jbGVhbiAlPiUNCmRwbHlyOjpzZWxlY3QoaWQsIGNvbmRpdGlvbiwgc2NvcmUsIG5ld0dhbWVTdGF0ZV9jbGVhbiwgbWFya2VyVHlwZSkgJT4lICAgICAgDQpkcGx5cjo6ZmlsdGVyKG5ld0dhbWVTdGF0ZV9jbGVhbiA9PSAiMTkiKSAlPiUNCmRwbHlyOjpncm91cF9ieShpZCwgY29uZGl0aW9uKSAlPiUgIA0KZHBseXI6Om11dGF0ZShmaXJzdF9tYXJrZXIgPSBkcGx5cjo6aWZfZWxzZShtYXJrZXJUeXBlID09IGRwbHlyOjpmaXJzdChtYXJrZXJUeXBlKSwgInllcyIsICJubyIpKSAlPiUgIA0KZHBseXI6OmZpbHRlcihmaXJzdF9tYXJrZXIgPT0gInllcyIpICU+JQ0KZHBseXI6OnN1bW1hcmlzZShtZWFuX3Njb3JlID0gbWVhbihzY29yZSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGdnc3RhdHNwbG90OjpnZ3dpdGhpbnN0YXRzKA0KICAgIHggPSBjb25kaXRpb24sDQogICAgeSA9IG1lYW5fc2NvcmUsDQogICAgb3V0bGllci50YWdnaW5nID0gVFJVRSwgICAgICAgICAgICAgICAgICAgDQogICAgb3V0bGllci5sYWJlbCA9IGlkLCANCiAgICB0aXRsZSA9ICJHYW1lU3RhdGU6IDE5Ig0KICApDQpgYGANCg0KDQoNCg0KPCEtLSBTZXNzaW9uIEluZm8gYW5kIExpY2Vuc2UgLS0+DQoNCjxicj4NCg0KIyBTZXNzaW9uIEluZm8NCg0KYGBge3Igc2Vzc2lvbl9pbmZvLCBlY2hvID0gRkFMU0UsIHJlc3VsdHMgPSAnbWFya3VwJ30NCnNlc3Npb25JbmZvKCkgICAgDQpgYGANCg0KPCEtLSBGb290ZXIgLS0+DQoNCsKgDQoNCjxociAvPg0KDQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+DQoNCkEgd29yayBieSA8YSBocmVmPSJodHRwczovL2dpdGh1Yi5jb20vQ2xhdWRpdVBhcGFzdGVyaS8iPkNsYXVkaXUgUGFwYXN0ZXJpPC9hPg0KDQo8L3A+DQoNCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij4NCg0KPGVtPltjbGF1ZGl1LnBhcGFzdGVyaVxAZ21haWwuY29tXShtYWlsdG86Y2xhdWRpdS5wYXBhc3RlcmlAZ21haWwuY29tKXsuZW1haWx9PC9lbT4NCg0KPC9wPg0KDQrCoA0K