1 Define functions

## Define function that recodes to numeric, but watches out to coercion to not introduce NAs
colstonumeric <- function(df){
  tryCatch({
    df_num <- as.data.frame(
      lapply(df,
             function(x) { as.numeric(as.character(x))})) 
  },warning = function(stop_on_warning) {
    message("Stoped the execution of numeric conversion: ", conditionMessage(stop_on_warning))
  }) 
}
##
## Define function that reverse codes items
ReverseCode <- function(df, tonumeric = FALSE, min = NULL, max = NULL) {
  if(tonumeric) df <- colstonumeric(df)
  df <- (max + min) - df
}
##
## Define function that scores only rows with less than 10% NAs (returns NA if all or above threshold percentage of rows are NA); can reverse code if vector of column indexes and min, max are provided.
ScoreLikert <- function(df, napercent = .1, tonumeric = FALSE, reversecols = NULL, min = NULL, max = NULL) {
  reverse_list <- list(reversecols = reversecols, min = min, max = max)
  reverse_check <- !sapply(reverse_list, is.null)
  
  # Recode to numeric, but watch out to coercion to not introduce NAs
  colstonumeric <- function(df){
    tryCatch({
      df_num <- as.data.frame(
        lapply(df,
               function(x) { as.numeric(as.character(x))})) 
    },warning = function(stop_on_warning) {
      message("Stoped the execution of numeric conversion: ", conditionMessage(stop_on_warning))
    }) 
  }
  
  if(tonumeric) df <- colstonumeric(df)
  
  if(all(reverse_check)){
    df[ ,reversecols] <- (max + min) - df[ ,reversecols]
  }else if(any(reverse_check)){
    stop("Insuficient info for reversing. Please provide: ", paste(names(reverse_list)[!reverse_check], collapse = ", "))
  }
  
  ifelse(rowSums(is.na(df)) > ncol(df) * napercent,
         NA,
         rowSums(df, na.rm = TRUE) * NA ^ (rowSums(!is.na(df)) == 0)
  )
}
##
# library(tidyverse)
# library(ggpubr)
# library(rstatix)
# library(broom)
# library(emmeans)
# library(rlang)


# Function ANCOVAPost
# Takes Long Data
ANCOVAPost_func <- 
  function(data, id_var, 
           time_var, pre_label, post_label,
           value_var = scores, cond_var, 
           assum_check = TRUE, posthoc = TRUE, 
           p_adjust_method = "bonferroni"){
  
  id_var_enq <- rlang::enquo(id_var)
  id_var_name <- rlang::as_name(id_var_enq)    
  time_var_enq <- rlang::enquo(time_var)
  time_var_name <- rlang::as_name(time_var_enq)
  pre_var_enq <- rlang::enquo(pre_label)
  pre_var_name <- rlang::as_name(pre_var_enq)  
  post_var_enq <- rlang::enquo(post_label)
  post_var_name <- rlang::as_name(post_var_enq)
  cond_var_enq <- rlang::enquo(cond_var)
  cond_var_name <- rlang::as_name(cond_var_enq)
  value_var_enq <- rlang::enquo(value_var)
  value_var_name <- rlang::as_name(value_var_enq) 
  
  data_wider <-
    data %>%
    dplyr::select(!!id_var_enq, !!time_var_enq, !!cond_var_enq, !!value_var_enq) %>%
    spread(key = time_var_name, value = value_var_name) # %>%     # if need to compute change score statistics go from here
    # mutate(difference = !!post_var_enq - !!pre_var_enq)  
    
  # Assumptions
  if(assum_check){
  cat("\n Linearity assumptionLinearity assumption (linear relationship between pre-test and post-test for each group) \n")
  # Create a scatter plot between the covariate (i.e., pretest) and the outcome variable (i.e., posttest)
  scatter_lin <-  
    ggscatter(data_wider, x = pre_var_name, y = post_var_name, color = cond_var_name, 
              add = "reg.line", title = "Linearity assumption") +
      stat_regline_equation(aes(label =  paste(..eq.label.., ..rr.label.., sep = "~~~~"), color = !!cond_var_enq))
  
  cat("\n Homogeneity of regression slopes (interaction term is n.s.) \n")
  data_wider %>% 
    anova_test(as.formula(paste0(post_var_name, " ~ ", cond_var_name, " * ", pre_var_name))) %>% 
    print()   
  
  cat("\n Normality of residuals (Model diagnostics & Shapiro Wilk) \n")
  # Fit the model, the covariate goes first
  model <- 
    lm(as.formula(paste0(post_var_name, " ~ ", cond_var_name, " + ", pre_var_name)),
       data = data_wider)
  cat("\n Inspect the model diagnostic metrics \n")
  model.metrics <- 
    augment(model) %>%
    dplyr::select(-.hat, -.sigma, -.fitted, -.se.fit)  %>%    # Remove details
    print()
  cat("\n Normality of residuals (Shapiro Wilk p>.05) \n")
  shapiro_test(model.metrics$.resid) %>% 
    print()
  
  cat("\n Homogeneity of variances (Levene’s test p>.05) \n")
  model.metrics %>% 
    levene_test(as.formula(paste0(".resid", " ~ ", cond_var_name)) ) %>%     
    print()
  
  cat("\n Outliers (needs to be 0) \n")
  model.metrics %>% 
    filter(abs(.std.resid) > 3) %>%
    as.data.frame() %>% 
    print()
  
  }
  
  cat("\n ANCOVAPost \n")
  res_ancova <- 
    data_wider %>% 
    anova_test(as.formula(paste0(post_var_name, " ~ ",  pre_var_name, " + ", cond_var_name)))       # the covariate needs to be first term 
  get_anova_table(res_ancova) %>% print()
  
  cat("\n Pairwise comparisons \n")
  pwc <- 
    data_wider %>% 
    emmeans_test(as.formula(paste0(post_var_name, " ~ ", cond_var_name)),       
                 covariate = !!pre_var_enq,
                 p.adjust.method = p_adjust_method)
  pwc %>% print()
  cat("\n Display the adjusted means of each group, also called as the estimated marginal means (emmeans) \n")
  get_emmeans(pwc) %>% print()
  
  # Visualization: line plots with p-values
  pwc <- 
    pwc %>% 
    add_xy_position(x = cond_var_name, fun = "mean_se")
  
  line_plot <- 
    ggline(get_emmeans(pwc), x = cond_var_name, y = "emmean") +
      geom_errorbar(aes(ymin = conf.low, ymax = conf.high), width = 0.2) + 
      stat_pvalue_manual(pwc, hide.ns = TRUE, tip.length = FALSE) +
      labs(subtitle = get_test_label(res_ancova, detailed = TRUE),
           caption = get_pwc_label(pwc))
  
  if(assum_check){
    list(scatter_lin, line_plot)
  }else{
    line_plot
  }
  
}

# ex.
# ANCOVAPost_func(new_anxiety, time_var = time, pre_label = pretest, post_label = posttest,
#           value_var = scores, cond_var = group, assum_check = TRUE, p_adjust_method = "bonferroni")
# library(tidyverse)
# library(ggpubr)
# library(rstatix)
# library(rlang)

# Define Function for Mixed Anova
tw_mixedANOVA_func <- 
  function(data, id_var, cond_var, time_var, value_var, 
           assum_check = TRUE, posthoc_sig_interac = FALSE, posthoc_ns_interac = FALSE,
           p_adjust_method = "bonferroni"){
    
    # input dataframe needs to have columns names diffrent from "variable" and "value" because it collides with rstatix::shapiro_test
    
    id_var_enq <- rlang::enquo(id_var)  
    cond_var_enq <- rlang::enquo(cond_var)
    cond_var_name <- rlang::as_name(cond_var_enq)
    time_var_enq <- rlang::enquo(time_var)
    time_var_name <- rlang::as_name(time_var_enq)
    value_var_enq <- rlang::enquo(value_var)
    value_var_name <- rlang::as_name(value_var_enq)
    
    data <-                  # need to subset becuase of strange contrasts error in anova_test()
      data %>%
      dplyr::select(!!id_var_enq, !!time_var_enq, !!cond_var_enq, !!value_var_enq) 
    
    # Assumptions
    if(assum_check){
      cat("\n Outliers \n")
      data %>%
        dplyr::group_by(!!time_var_enq, !!cond_var_enq) %>%
        rstatix::identify_outliers(!!value_var_enq) %>%                                  # outliers (needs to be 0)
        print()
      
      cat("\n Normality assumption (p>.05) \n")
      data %>%
        dplyr::group_by(!!time_var_enq, !!cond_var_enq) %>%
        rstatix::shapiro_test(!!value_var_enq) %>%                                        # normality assumption (p>.05)
        print()
      
      qq_plot <- 
        ggpubr::ggqqplot(data = data, value_var_name, ggtheme = theme_bw(), title = "QQ Plot") +
        ggplot2::facet_grid(vars(!!time_var_enq), vars(!!cond_var_enq), labeller = "label_both")    # QQ plot
      
      cat("\n Homogneity of variance assumption - Levene’s test (p>.05) \n")
      data %>%
        group_by(!!time_var_enq ) %>%
        levene_test(as.formula(paste0(value_var_name, " ~ ", cond_var_name))) %>%
        print()
      
      cat("\n Homogeneity of covariances assumption - Box’s test of equality of covariance matrices (p>.001) \n")
      box_m(data = data[, value_var_name, drop = FALSE], group = data[, cond_var_name, drop = TRUE]) %>%
        print
    }
    
    # Two-way rmANOVA - check for interaction (ex. F(2, 22) = 30.4, p < 0.0001)
    cat("\n Two-way rmANOVA \n")
    res_aov <- 
      anova_test(data = data, dv = !!value_var_enq, wid = !!id_var_enq,               # automatically does sphericity Mauchly’s test
                 within = !!time_var_enq, between = !!cond_var_enq)
    get_anova_table(res_aov) %>%  # ges: Greenhouse-Geisser sphericity correction is automatically applied to factors violating the sphericity assumption  
      print()
    
    
    # ------------------------------------------------------------------------
    
    #- Procedure for a significant two-way interaction -
    if(posthoc_sig_interac){
      cat("\n Effect of group at each time point - One-way ANOVA\n")
      one_way <- 
        data %>%
        group_by(!!time_var_enq) %>%
        anova_test(dv = !!value_var_enq, wid = !!id_var_enq, between = !!cond_var_enq) %>%
        get_anova_table() %>%
        adjust_pvalue(method = p_adjust_method)
      one_way %>% print()
      
      cat("\n Pairwise comparisons between group levels \n")
      pwc <- 
        data %>%
        group_by(!!time_var_enq) %>%
        pairwise_t_test(as.formula(paste0(value_var_name, " ~ ", cond_var_name)), 
                        p.adjust.method = p_adjust_method)
      pwc %>% print()
      cat("\n Effect of time at each level of exercises group  - One-way ANOVA \n")
      one_way2 <- 
        data %>%
        group_by(!!cond_var_enq) %>%
        anova_test(dv = !!value_var_enq, wid = !!id_var_enq, within = !!time_var_enq) %>%
        get_anova_table() %>%
        adjust_pvalue(method = p_adjust_method)
      one_way2 %>% print()
      
      cat("\n Pairwise comparisons between time points at each group levels (we have repeated measures by time) \n")
      pwc2 <-
        data %>%
        group_by(!!cond_var_enq) %>%
        pairwise_t_test(
          as.formula(paste0(value_var_name, " ~ ", time_var_name)),     # paste formula, not quosure
          paired = TRUE,
          p.adjust.method = p_adjust_method
        )
      pwc2  %>% print()
    }
    
    #- Procedure for non-significant two-way interaction- 
    # If the interaction is not significant, you need to interpret the main effects for each of the two variables: treatment and time.
    if(posthoc_ns_interac){
      cat("\n Comparisons for treatment variable \n")
      pwc_cond <-
        data %>%
        pairwise_t_test(
          as.formula(paste0(value_var_name, " ~ ", cond_var_name)),     # paste formula, not quosure             
          paired = FALSE,
          p.adjust.method = p_adjust_method
        )
      pwc_cond %>% print()
      cat("\n Comparisons for time variable \n")
      pwc_time <-
        data %>% 
        pairwise_t_test(
          as.formula(paste0(value_var_name, " ~ ", time_var_name)),     # paste formula, not quosure
          paired = TRUE,
          p.adjust.method = p_adjust_method
        )
      pwc_time %>% print()
    }
    
    # Visualization
    bx_plot <- 
      ggboxplot(data, x = time_var_name, y = value_var_name,
                color = cond_var_name, palette = "jco")
    pwc <- 
      pwc %>% 
      add_xy_position(x = time_var_name)
    bx_plot <- 
      bx_plot + 
      stat_pvalue_manual(pwc, tip.length = 0, hide.ns = TRUE) +
      labs(
        subtitle = get_test_label(res_aov, detailed = TRUE),
        caption = get_pwc_label(pwc)
      )
    
    if(assum_check){ 
      list(qq_plot, bx_plot)
    }else{
      bx_plot
    } 
    
  }

# ex. - run on long format
# tw_mixedANOVA_func(data = anxiety, id_var = id, cond_var = group, time_var = time, value_var = score,
#                 posthoc_sig_interac = TRUE, posthoc_ns_interac = TRUE)

2 Read, Clean, Recode

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Read, Clean, Recode, Unite
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

## Read files
folder <- "C:/Users/Mihai/Desktop/R Notebooks/notebooks/PA4-report"
old_file <- "Date_pt_analiza_PA4online.xlsx"
file <- "Date_pt_analiza_PA4online - Final2.xlsx"

setwd(folder)

# ID df
id_df <- rio::import(file.path(folder, file),
                               skip = 1, which = "ID-uri atribuite")   
id_df <- 
  id_df %>%
  dplyr::mutate(ID = stringr::str_replace_all(ID, fixed(" "), ""))     # remove white spaces
all(id_df$ID == toupper(id_df$ID))                                     # check if all are upper case
id_df[, "e-mail"] <- tolower(id_df[, "e-mail"])
id_df <- id_df[!duplicated(id_df),]                   # 36 duplicated, 115 unique

firstform_df <- rio::import(file.path(folder, file),
                               skip = 0, which = "Formular de înscriere și consim")
firstform_df <- firstform_df[, -length(firstform_df)]                  # a column "work" was added to the end 
old_file_firstform_df <- rio::import(file.path(folder, old_file),
                               skip = 0, which = "Formular de înscriere și consim") 
if(all.equal(colnames(firstform_df), colnames(old_file_firstform_df))) {rm(old_file_firstform_df)}


colnames(firstform_df)[7] <- "e-mail"
firstform_df[, "e-mail"] <- tolower(firstform_df[, "e-mail"])

baseline_df <- dplyr::left_join(id_df, firstform_df, by = "e-mail")
baseline_df <- 
  baseline_df %>%
  dplyr::select(colnames(firstform_df), everything())     # move cols from id_df to back so we have matching cols index for baseline_df & firstform_df
all.equal(colnames(baseline_df)[1:172], colnames(firstform_df)[1:172])             # check if colnames match, except ID and name that where added
table(baseline_df$ID) # some IDs are doubled
## Settings
cutoffPCL <- 32   # literature: 31-33 or 38 
algPCL <- data.frame(B = 1, C = 1, D = 2, E = 2)
algPCL_subclin <- data.frame(B = 1, C = 1, D = 1, E = 1)

cutoffMBI_Ex <- 2.20  
cutoffMBI_Cy <- 2
##

## Data
Data <- baseline_df
##

# Define column index:  index = col index; itemindex = index of item in questionnaire
indexSIG <- 60:67 - 10    # modified in new table by 10
indexMBI <- 68:83 - 10
indexPCL <- 159:178 - 10
itemindexMBI_Ex <- c(1, 3, 5, 11, 14)
itemindexMBI_Cy <- c(2, 7, 8, 13, 15)
itemindexMBI_Pe <- c(4, 6, 9, 10, 12, 16)

# Rename columns
# names(Data)[1:12] <- stringr::str_replace_all(names(Data)[1:12], "[[:blank:]]", "_")
# names(Data)[17] <- "Real_Email"
# names(Data)[18] <- "Real_Tel"
# names(Data)[19] <- "Real_Name"
# names(Data)[50] <- "Real_Age_categ"

names(Data)[9] <- "nume"
names(Data)[40] <- "Age_categ"
names(Data)[41] <- "Sex"

names(Data)[names(Data) %in% names(Data[, indexSIG])]  <- c(sprintf("SIG_%01d", seq(1, 8)))
names(Data)[names(Data) %in% names(Data[, indexMBI])]  <- c(sprintf("MBI_%01d", seq(1, 16)))
names(Data)[names(Data) %in% names(Data[, indexPCL])]  <- c(sprintf("PCL_%01d", seq(1, 20)))


# Data <-
#   Data %>%
#   dplyr::filter(Response_Status == "completed")                          # select only complete cases
 

# Recode 
## Define function that recodes to numeric, but watches out to coercion to not introduce NAs
colstonumeric <- function(df){
  tryCatch({
    df_num <- as.data.frame(
      lapply(df,
             function(x) { as.numeric(as.character(x))})) 
  },warning = function(stop_on_warning) {
    message("Stoped the execution of numeric conversion: ", conditionMessage(stop_on_warning))
  }) 
}
##
## Define function that reverse codes items
ReverseCode <- function(df, tonumeric = FALSE, min = NULL, max = NULL) {
  if(tonumeric) df <- colstonumeric(df)
  df <- (max + min) - df
}
##

# lapply(Data[,indexPCL], unique)
Data[ ,indexPCL][ Data[ ,indexPCL] == "deloc"] <- "0"
Data[ ,indexPCL][ Data[ ,indexPCL] == "puțin"] <- "1"
Data[ ,indexPCL][ Data[ ,indexPCL] == "moderat"] <- "2"
Data[ ,indexPCL][ Data[ ,indexPCL] == "mult"] <- "3"
Data[ ,indexPCL][ Data[ ,indexPCL] == "foarte mult"] <- "4"
Data[ ,indexPCL][ Data[ ,indexPCL] == "Not Answered"] <- NA

Data[ ,indexSIG][ Data[ ,indexSIG] == "NU"] <- "0"
Data[ ,indexSIG][ Data[ ,indexSIG] == "?"] <- "1.5"
Data[ ,indexSIG][ Data[ ,indexSIG] == "DA"] <- "3"
Data[ ,indexSIG][ Data[ ,indexSIG] == "Not Answered"] <- NA

Data[ ,indexMBI] <- data.frame(lapply(Data[ ,indexMBI], 
                                      function(x) {gsub(".*Niciodat.*", "0", x)}), stringsAsFactors = FALSE)
Data[ ,indexMBI] <- data.frame(lapply(Data[ ,indexMBI], 
                                      function(x) {gsub(".*Zilnic.*", "6", x)}), stringsAsFactors = FALSE)
Data[ ,indexMBI][ Data[ ,indexMBI] == "Not Answered"] <- NA


Data[, indexSIG] <- colstonumeric(Data[, indexSIG])
Data[, indexMBI] <- colstonumeric(Data[, indexMBI])
Data[, indexPCL] <- colstonumeric(Data[, indexPCL])



# Scores
## Define function that scores only rows with less than 10% NAs (returns NA if all or above threshold percentage of rows are NA); can reverse code if vector of column indexes and min, max are provided.
ScoreLikert <- function(df, stat = "sum", natozero = FALSE, napercent = .1, tonumeric = FALSE, reversecols = NULL, min = NULL, max = NULL) {
  reverse_list <- list(reversecols = reversecols, min = min, max = max)
  reverse_check <- !sapply(reverse_list, is.null)
  
  # Recode to numeric, but watch out to coercion to not introduce NAs
  colstonumeric <- function(df){
    tryCatch({
      df_num <- as.data.frame(
        lapply(df,
               function(x) { as.numeric(as.character(x))})) 
    },warning = function(stop_on_warning) {
      message("Stoped the execution of numeric conversion: ", conditionMessage(stop_on_warning))
    }) 
  }
  
  if(tonumeric) df <- colstonumeric(df)
  
  if(all(reverse_check)){
    df[ ,reversecols] <- (max + min) - df[ ,reversecols]
  }else if(any(reverse_check)){
    stop("Insuficient info for reversing. Please provide: ", paste(names(reverse_list)[!reverse_check], collapse = ", "))
  }
  
  if(tonumeric) df <- colstonumeric(df)                           
  
  if(natozero) df[is.na(df)] <- 0                                    # NAs to 0 can help when stat = "mean" with na.rm = T because it keeps denominator constant
  
  if(stat == "sum"){
  df_res <- ifelse(rowSums(is.na(df)) > ncol(df) * napercent,
                   NA,
                   rowSums(df, na.rm = TRUE) * NA ^ (rowSums(!is.na(df)) == 0))
  }
  if(stat == "mean"){
    df_res <- ifelse(rowSums(is.na(df)) > ncol(df) * napercent,
                     NA,
                     rowMeans(df, na.rm = TRUE) * NA ^ (rowSums(!is.na(df)) == 0))
  }
  return(df_res)
}
##


# Score PCL
Data$PCL_Total <- ScoreLikert(Data[, indexPCL], napercent = .3)               # NA if NA threshold is exceeded 
Data$PCL_B <- ScoreLikert(Data[, c(sprintf("PCL_%01d", 1:5))], napercent = 1)    # do nothing if NA threshold is exceeded
Data$PCL_C <- ScoreLikert(Data[, c(sprintf("PCL_%01d", 6:7))], napercent = 1) 
Data$PCL_D <- ScoreLikert(Data[, c(sprintf("PCL_%01d", 8:14))], napercent = 1)  
Data$PCL_E <- ScoreLikert(Data[, c(sprintf("PCL_%01d", 15:20))], napercent = 1)

# Score SIG
Data$SIG_Total <- ScoreLikert(Data[, indexSIG], napercent = .3)

# Score MBI
Data$MBI_Total <- ScoreLikert(Data[, indexMBI], napercent = .3, stat = "mean", natozero = TRUE)
Data$MBI_Ex <- ScoreLikert(Data[, c(sprintf("MBI_%01d", itemindexMBI_Ex))], napercent = 1, stat = "mean", natozero = TRUE)
Data$MBI_Cy <- ScoreLikert(Data[, c(sprintf("MBI_%01d", itemindexMBI_Cy))], napercent = 1, stat = "mean", natozero = TRUE)
Data$MBI_Pe <- ScoreLikert(Data[, c(sprintf("MBI_%01d", itemindexMBI_Pe))], napercent = 1, stat = "mean", natozero = TRUE)


# PCL Diagnostic Algorithm
itemsPCL_B <- c(sprintf("PCL_%01d", 1:5))
itemsPCL_C <- c(sprintf("PCL_%01d", 6:7))
itemsPCL_D <- c(sprintf("PCL_%01d", 8:14))
itemsPCL_E <- c(sprintf("PCL_%01d", 15:20))

DataPCLAlg <-  
  Data %>% 
  dplyr::select(tidyselect::all_of(indexPCL)) %>% 
  dplyr::mutate_all(
    funs(case_when(
      . >=2 ~ 1,
      # . <2 ~ 0,
      is.na(.) ~ 0,
      TRUE  ~  0))) %>% 
  
  mutate(PCL_CritB = case_when(rowSums(.[,itemsPCL_B], na.rm = TRUE) >= algPCL$B ~ 1,      # algPCL <- data.frame(B = 1, C = 1, D = 2, E = 2)
                               # rowSums(.[,itemsPCL_B], na.rm = TRUE) <1 ~ 0,
                               TRUE  ~  0)) %>% 
  mutate(PCL_CritC = case_when(rowSums(.[,itemsPCL_C], na.rm = TRUE) >= algPCL$C ~ 1,    
                               # rowSums(.[,itemsPCL_C], na.rm = TRUE) <1 ~ 0,
                               TRUE  ~  0)) %>% 
  mutate(PCL_CritD = case_when(rowSums(.[,itemsPCL_D], na.rm = TRUE) >= algPCL$D ~ 1,   
                               # rowSums(.[,itemsPCL_D], na.rm = TRUE) <1 ~ 0,
                               TRUE  ~  0)) %>% 
  mutate(PCL_CritE = case_when(rowSums(.[,itemsPCL_E], na.rm = TRUE) >= algPCL$E ~ 1,    
                               # rowSums(.[,itemsPCL_E], na.rm = TRUE) <1 ~ 0,
                               TRUE  ~  0)) %>% 
  mutate(PCL_Alg = case_when(PCL_CritB == 1 & PCL_CritC == 1 & PCL_CritD == 1 & PCL_CritE == 1 ~ 1,
                             TRUE  ~  0)) 

Data$PCLAlg <- DataPCLAlg$PCL_Alg

DataPCLAlg_subclin <-  
  Data %>% 
  dplyr::select(tidyselect::all_of(indexPCL)) %>% 
  dplyr::mutate_all(
    funs(case_when(
      . >=2 ~ 1,
      # . <2 ~ 0,
      is.na(.) ~ 0,
      TRUE  ~  0))) %>% 
  
  mutate(PCL_CritB = case_when(rowSums(.[,itemsPCL_B], na.rm = TRUE) >= algPCL_subclin$B ~ 1,  
                               # rowSums(.[,itemsPCL_B], na.rm = TRUE) <1 ~ 0,
                               TRUE  ~  0)) %>% 
  mutate(PCL_CritC = case_when(rowSums(.[,itemsPCL_C], na.rm = TRUE) >= algPCL_subclin$C ~ 1,    
                               # rowSums(.[,itemsPCL_C], na.rm = TRUE) <1 ~ 0,
                               TRUE  ~  0)) %>% 
  mutate(PCL_CritD = case_when(rowSums(.[,itemsPCL_D], na.rm = TRUE) >= algPCL_subclin$D ~ 1,   
                               # rowSums(.[,itemsPCL_D], na.rm = TRUE) <1 ~ 0,
                               TRUE  ~  0)) %>% 
  mutate(PCL_CritE = case_when(rowSums(.[,itemsPCL_E], na.rm = TRUE) >= algPCL_subclin$E ~ 1,    
                               # rowSums(.[,itemsPCL_E], na.rm = TRUE) <1 ~ 0,
                               TRUE  ~  0)) %>% 
  mutate(PCL_Alg_subclin = case_when(PCL_CritB == 1 & PCL_CritC == 1 & PCL_CritD == 1 & PCL_CritE == 1 ~ 1,
                                     TRUE  ~  0)) 

Data$PCLAlg_subclin <- DataPCLAlg_subclin$PCL_Alg_subclin

Data$MBI_Ex_cut <- ifelse(Data$MBI_Ex >= cutoffMBI_Ex, 1, 0)
Data$MBI_Cy_cut <- ifelse(Data$MBI_Cy >= cutoffMBI_Cy, 1, 0)


# Global Screening & Groups
df_screening <- Data[,c("ID", "nume", "e-mail", "Age_categ", "Sex",
                        "SIG_Total", "MBI_Ex", "MBI_Cy", "MBI_Ex_cut", "MBI_Cy_cut",
                        "PCL_Total", "PCL_B", "PCL_C", "PCL_D", "PCL_E", "PCLAlg", "PCLAlg_subclin")]



# Check same result with screening done on Google Colab 
# check_g <- rio::import(file.path(folder, "check_screening", "PA4_Screening 2021-01-18 18_03_40CHECK.xlsx")) 
# check_l <- df_screening
# 
# check_merge <- full_join(check_l, check_g, by = c("e-mail" = "Real_Email"))
# 
# names_l <- paste0(c("SIG_Total", "MBI_Ex_cut", "MBI_Cy_cut", "PCL_Total", "PCL_B", "PCL_C", "PCL_D", "PCL_E", "PCLAlg", "PCLAlg_subclin"), ".x")
# names_g <- paste0(c("SIG_Total", "MBI_Ex_cut", "MBI_Cy_cut", "PCL_Total", "PCL_B", "PCL_C", "PCL_D", "PCL_E", "PCLAlg", "PCLAlg_subclin"), ".y")
# 
# all.equal(check_merge[, names_l], check_merge[, names_l])
############
[1] "6A" "9C"
[1] 22
[1] TRUE
[1] 25
[1] TRUE
[1] 8
[1] TRUE
[1] 52
[1] TRUE
character(0)
[1] 47
 [1] "5A"  "6A"  "2X"  "6X"  "13X" "17X" "19X" "9R"  "11R" "2B"  "6B"  "3C"  "10C" "13C" "14C" "15C" "16C" "3D"  "8D"  "10D" "6E"  "18R"
 [1] "3X"  "5X"  "8X"  "9X"  "12X" "15X" "25X" "28X" "8R"  "12R" "1B"  "8B"  "9B"  "10B" "12B" "13B" "14B" "2C"  "5C"  "6C"  "7C"  "8C"  "4D"  "5D"  "17R"
character(0)
character(0)
[1] TRUE

3 Outcome Measures

4 Dictator Game

# DG df
dg_df_pre <- rio::import(file.path(folder, file),
                                   skip = 0, which = "DictatorGame pre")
dg_df_pre <- 
  dg_df_pre %>%
  janitor::remove_empty("rows") 
  
colnames(dg_df_pre)[4] <- "ID"
dg_df_pre <- 
  dg_df_pre %>%
  dplyr::mutate(ID = stringr::str_replace_all(ID, fixed(" "), "")) %>%    # remove white spaces
  dplyr::mutate(ID = toupper(ID))                                         # to upper
all(dg_df_pre$ID == toupper(dg_df_pre$ID)) 
dg_df_post <- rio::import(file.path(folder, file),
                                   skip = 0, which = "DictatorGame post")
dg_df_post <- 
  dg_df_post %>%
  janitor::remove_empty("rows")

colnames(dg_df_post)[4] <- "ID"
dg_df_post <- 
  dg_df_post %>%
  dplyr::mutate(ID = stringr::str_replace_all(ID, fixed(" "), "")) %>%    # remove white spaces
  dplyr::mutate(ID = toupper(ID))                                         # to upper
all(dg_df_post$ID == toupper(dg_df_post$ID)) 
colnames(dg_df_pre)[5:8] <- sprintf("DG_%d", 1:4)
colnames(dg_df_pre)[2] <- "Response_Status"
colnames(dg_df_post)[5:8] <- sprintf("DG_%d", 1:4)
colnames(dg_df_post)[3] <- "Response_Status"

dg_df_pre <-
  dg_df_pre %>%
  dplyr::mutate(`Date Modified` = lubridate::ymd_hms(format(`Date Modified`, "%Y-%m-%d %H:%M:%S", tz = "UTC"))) %>%
  mutate_if(is.character, ~na_if(., "Not Answered")) %>%
  dplyr::filter(Response_Status == "completed") %>%
  dplyr::filter(!stringr::str_detect(ID, "PA4OXT")) %>%
  dplyr::filter(!stringr::str_detect(ID, "PA4RMN"))

dg_df_post <-
  dg_df_post %>%
  dplyr::mutate(`Date Modified` = lubridate::ymd_hms(format(`Date Modified`, "%Y-%m-%d %H:%M:%S", tz = "UTC"))) %>%
  mutate_if(is.character, ~dplyr::na_if(., "Not Answered")) %>%
  dplyr::filter(Response_Status == "completed") %>%
  dplyr::filter(!stringr::str_detect(ID, "PA4OXT")) %>%
  dplyr::filter(!stringr::str_detect(ID, "PA4RMN"))

dg_df_pre <-
  dg_df_pre %>%
  dplyr::mutate_at(vars(starts_with("DG_")), ~stringr::str_extract(., "[0-9]+")) %>%   # extracts first number (all games start with Player A, so always first number)
  dplyr::mutate_at(vars(starts_with("DG_")), as.numeric) %>%
  dplyr::mutate(Time = rep("Pre", nrow(.))) %>%
  dplyr::mutate(Cond = ifelse(stringr::str_detect(ID, "X"), "CTRL", "TR")) %>%
  select(`Date Modified`, ID, starts_with("DG_"), Time, Cond)

dg_df_post <-
  dg_df_post %>%
  dplyr::mutate_at(vars(starts_with("DG_")), ~stringr::str_extract(., "[0-9]+")) %>%   # extracts first number (all games start with Player A, so always first number)
  dplyr::mutate_at(vars(starts_with("DG_")), as.numeric) %>%
  dplyr::mutate(Time = rep("Post", nrow(.))) %>%
  dplyr::mutate(Cond = ifelse(stringr::str_detect(ID, "X"), "CTRL", "TR")) %>%
  select(`Date Modified`, ID, starts_with("DG_"), Time, Cond)

# Transform DG 0-900 egoism to 0-9 altruism
dg_trans_func <- function(x){trans <- 9 - x / 100}

dg_df_pre <-
  dg_df_pre %>%
  dplyr::mutate_at(vars(starts_with("DG_")), dg_trans_func) 

dg_df_post <-
  dg_df_post %>%
  dplyr::mutate_at(vars(starts_with("DG_")), dg_trans_func) 

# Unite DG data - Long Format
dg_united_long <- rbind(dg_df_pre, dg_df_post)
which(table(dg_united_long$ID)> 2 )     # IDs "3B" & "31X" have more than 2 trials
dg_united_long[dg_united_long$ID == "3B",]  # two Pres -- keep the first

–>

5 T test Dicatator Game

## DG - PTSD TR
#### DG_Total_Pre DG_Total_Post

## DG - PTSD CTRL
#### DG_Total_Pre DG_Total_Post

## DG - Burnout TR
#### DG_Total_Pre DG_Total_Post

## DG - Burnout CTRL
#### DG_Total_Pre DG_Total_Post

## DG - Old TR
## DG - Old CTRL
## DG - General Population TR
#### DG_Total_Pre DG_Total_Post

## DG - General Population CTRL
#### DG_Total_Pre DG_Total_Post

–>

# Scales df
scale_df_pre <- rio::import(file.path(folder, file),
                           skip = 0, which = "Set teste zi 1 pre")
scale_df_pre <- 
  scale_df_pre %>%
  janitor::remove_empty("rows") 

scale_df_pre <- scale_df_pre[,-2]
colnames(scale_df_pre)[1] <- "Date"
colnames(scale_df_pre)[2] <- "ID"
scale_df_pre <- 
  scale_df_pre %>%
  dplyr::mutate(ID = stringr::str_replace_all(ID, fixed(" "), "")) %>%    # remove white spaces
  dplyr::mutate(ID = toupper(ID))                                    # to upper
all(scale_df_pre$ID == toupper(scale_df_pre$ID)) 
scale_df_post <- rio::import(file.path(folder, file),
                            skip = 0, which = "Set teste zi 5 post")
scale_df_post <- 
  scale_df_post %>%
  janitor::remove_empty("rows") 

scale_df_post <- scale_df_post[,-2]
colnames(scale_df_post)[1] <- "Date"
colnames(scale_df_post)[2] <- "ID"
scale_df_post <- 
  scale_df_post %>%
  dplyr::mutate(ID = stringr::str_replace_all(ID, fixed(" "), "")) %>%    # remove white spaces
  dplyr::mutate(ID = toupper(ID))                                     # to upper
all(scale_df_post$ID == toupper(scale_df_post$ID))
all.equal(colnames(scale_df_post), colnames(scale_df_pre))   # setdiff(colnames(scale_df_post), colnames(scale_df_pre))
# Deal with Not Answer
scale_df_pre <-
  scale_df_pre %>%
  mutate_if(is.character, ~dplyr::na_if(., "Not Answered"))

scale_df_post <-
  scale_df_post %>%
  mutate_if(is.character, ~dplyr::na_if(., "Not Answered"))

# Exclude subjects
scale_df_pre <-
  scale_df_pre %>%
  dplyr::filter(!stringr::str_detect(ID, "PA4OXT")) %>%
  dplyr::filter(!stringr::str_detect(ID, "RMN")) 

scale_df_post <-
  scale_df_post %>%
  dplyr::filter(!stringr::str_detect(ID, "PA4OXT")) %>%
  dplyr::filter(!stringr::str_detect(ID, "RMN")) 

# Add Condition
scale_df_pre <-
  scale_df_pre %>%
  dplyr::mutate(Time = rep("Pre", nrow(.))) %>%
  dplyr::mutate(Cond = ifelse(stringr::str_detect(ID, "X"), "CTRL", "TR"))

scale_df_post <-
  scale_df_post %>%
  dplyr::mutate(Time = rep("Post", nrow(.))) %>%
    dplyr::mutate(Cond = ifelse(stringr::str_detect(ID, "X"), "CTRL", "TR"))


## PANAS: Positive Affect Score = sum items 1, 3, 5, 9, 10, 12, 14, 16, 17, 19. Negative Affect Score = sum items 2, 4, 6, 7, 8, 11, 13, 15, 18, 20.  
index_item_panas <- 3:22
colnames(scale_df_pre)[index_item_panas] <- sprintf("PANAS_%d", 1:20)
colnames(scale_df_post)[index_item_panas] <- sprintf("PANAS_%d", 1:20)

scale_df_pre[, index_item_panas] <- data.frame(lapply(scale_df_pre[, index_item_panas], 
                                      function(x) {gsub(".*în foarte mică măsură.*", "1", x)}), stringsAsFactors = FALSE)
scale_df_pre[, index_item_panas] <- data.frame(lapply(scale_df_pre[, index_item_panas], 
                                      function(x) {gsub(".*în mică măsură.*", "2", x)}), stringsAsFactors = FALSE)
scale_df_pre[, index_item_panas] <- data.frame(lapply(scale_df_pre[, index_item_panas], 
                                      function(x) {gsub(".*într-o oarecare măsură.*", "3", x)}), stringsAsFactors = FALSE)
scale_df_pre[, index_item_panas] <- data.frame(lapply(scale_df_pre[, index_item_panas], 
                                      function(x) {gsub(".*în mare măsură.*", "4", x)}), stringsAsFactors = FALSE)
scale_df_pre[, index_item_panas] <- data.frame(lapply(scale_df_pre[, index_item_panas], 
                                      function(x) {gsub(".*în foarte mare măsură.*", "5", x)}), stringsAsFactors = FALSE)

scale_df_post[, index_item_panas] <- data.frame(lapply(scale_df_post[, index_item_panas], 
                                                      function(x) {gsub(".*în foarte mică măsură.*", "1", x)}), stringsAsFactors = FALSE)
scale_df_post[, index_item_panas] <- data.frame(lapply(scale_df_post[, index_item_panas], 
                                                      function(x) {gsub(".*în mică măsură.*", "2", x)}), stringsAsFactors = FALSE)
scale_df_post[, index_item_panas] <- data.frame(lapply(scale_df_post[, index_item_panas], 
                                                      function(x) {gsub(".*într-o oarecare măsură.*", "3", x)}), stringsAsFactors = FALSE)
scale_df_post[, index_item_panas] <- data.frame(lapply(scale_df_post[, index_item_panas], 
                                                      function(x) {gsub(".*în mare măsură.*", "4", x)}), stringsAsFactors = FALSE)
scale_df_post[, index_item_panas] <- data.frame(lapply(scale_df_post[, index_item_panas], 
                                                      function(x) {gsub(".*în foarte mare măsură.*", "5", x)}), stringsAsFactors = FALSE)
# Scoring
scale_df_pre$PA_Total <- ScoreLikert(scale_df_pre[, index_item_panas][c(1, 3, 5, 9, 10, 12, 14, 16, 17, 19)], 
                                    tonumeric = TRUE, napercent = .11)                              # not more than 1 NAs for 10 items
scale_df_pre$NA_Total <- ScoreLikert(scale_df_pre[, index_item_panas][c(2, 4, 6, 7, 8, 11, 13, 15, 18, 20)],
                                    tonumeric = TRUE, napercent = .11)                              # not more than 1 NAs for 10 items

scale_df_post$PA_Total <- ScoreLikert(scale_df_post[, index_item_panas][c(1, 3, 5, 9, 10, 12, 14, 16, 17, 19)], 
                                     tonumeric = TRUE, napercent = .11)                              # not more than 1 NAs for 10 items
scale_df_post$NA_Total <- ScoreLikert(scale_df_post[, index_item_panas][c(2, 4, 6, 7, 8, 11, 13, 15, 18, 20)],
                                     tonumeric = TRUE, napercent = .11)                              # not more than 1 NAs for 10 items


## PSS-SF 14 (likert 0-4). Items 4, 5, 6, 7, 9, 10, and 13 are scored in reverse direction.
index_item_pss <- 23:36
index_item_revPSS <- c(4, 5, 6, 7, 9, 10, 13)
colnames(scale_df_pre)[index_item_pss] <- sprintf("PSS_%d", 1:14)
colnames(scale_df_post)[index_item_pss] <- sprintf("PSS_%d", 1:14)

scale_df_pre[, index_item_pss] <- data.frame(lapply(scale_df_pre[, index_item_pss], 
                                      function(x) {gsub(".*niciodată.*", "0", x)}), stringsAsFactors = FALSE)
scale_df_pre[, index_item_pss] <- data.frame(lapply(scale_df_pre[, index_item_pss], 
                                      function(x) {gsub(".*aproape niciodată.*", "1", x)}), stringsAsFactors = FALSE)
scale_df_pre[, index_item_pss] <- data.frame(lapply(scale_df_pre[, index_item_pss], 
                                      function(x) {gsub(".*uneori.*", "2", x)}), stringsAsFactors = FALSE)
scale_df_pre[, index_item_pss] <- data.frame(lapply(scale_df_pre[, index_item_pss], 
                                      function(x) {gsub(".*destul de des.*", "3", x)}), stringsAsFactors = FALSE)
scale_df_pre[, index_item_pss] <- data.frame(lapply(scale_df_pre[, index_item_pss], 
                                      function(x) {gsub(".*foarte des.*", "4", x)}), stringsAsFactors = FALSE)

scale_df_post[, index_item_pss] <- data.frame(lapply(scale_df_post[, index_item_pss], 
                                                    function(x) {gsub(".*niciodată.*", "0", x)}), stringsAsFactors = FALSE)
scale_df_post[, index_item_pss] <- data.frame(lapply(scale_df_post[, index_item_pss], 
                                                    function(x) {gsub(".*aproape niciodată.*", "1", x)}), stringsAsFactors = FALSE)
scale_df_post[, index_item_pss] <- data.frame(lapply(scale_df_post[, index_item_pss], 
                                                    function(x) {gsub(".*uneori.*", "2", x)}), stringsAsFactors = FALSE)
scale_df_post[, index_item_pss] <- data.frame(lapply(scale_df_post[, index_item_pss], 
                                                    function(x) {gsub(".*destul de des.*", "3", x)}), stringsAsFactors = FALSE)
scale_df_post[, index_item_pss] <- data.frame(lapply(scale_df_post[, index_item_pss], 
                                                    function(x) {gsub(".*foarte des.*", "4", x)}), stringsAsFactors = FALSE)

# Score
scale_df_pre[, index_item_pss] <- colstonumeric(scale_df_pre[, index_item_pss])
scale_df_post[, index_item_pss] <- colstonumeric(scale_df_post[, index_item_pss])

scale_df_pre[, index_item_pss][index_item_revPSS] <- ReverseCode(scale_df_pre[, index_item_pss][index_item_revPSS], tonumeric = FALSE, min = 0, max = 4)
scale_df_post[, index_item_pss][index_item_revPSS] <- ReverseCode(scale_df_post[, index_item_pss][index_item_revPSS], tonumeric = FALSE, min = 0, max = 4)

scale_df_pre$PSS_Total <- ScoreLikert(scale_df_pre[, index_item_pss], napercent = .11)
scale_df_post$PSS_Total <- ScoreLikert(scale_df_post[, index_item_pss], napercent = .11)


# Unite scale df - Long Format
scale_united_long <- rbind(scale_df_pre, scale_df_post)

# scale_united_long %>%
#   count(ID) %>%
#   print(n = Inf)  # ID "2B", "5E" have double record 

# scale_united_long[scale_united_long$ID == "2B",]
scale_united_long <- scale_united_long[-26,]
# scale_united_long[scale_united_long$ID == "5E",]
scale_united_long <- scale_united_long[-109,]

# Exclude subj wiht only one observation, exclude ID NOTANSWERED
scale_united_long <-
  scale_united_long %>%
  group_by(ID) %>%
  dplyr::filter(n() > 1) %>%
  ungroup() %>%
  dplyr::filter(ID != "NOTANSWERED")

# Unite DG data - Wide Format
scale_united_wide <-
  scale_united_long %>%
  dplyr::select(ID, Date, Time, Cond, PA_Total, NA_Total, PSS_Total) %>%
  tidyr::pivot_wider(id_cols = c(ID, Cond), names_from = Time, values_from = c("Date", "PA_Total", "NA_Total", "PSS_Total"))

–>

6 T test PSS

## PSS - PTSD TR
#### PSS_Total_Pre PSS_Total_Post

## PSS - PTSD CTRL
#### PSS_Total_Pre PSS_Total_Post

## PSS - Burnout TR
#### PSS_Total_Pre PSS_Total_Post

## PSS - Burnout CTRL
#### PSS_Total_Pre PSS_Total_Post

## PSS - General Population TR
#### PSS_Total_Pre PSS_Total_Post

## PSS - General Population CTRL
#### PSS_Total_Pre PSS_Total_Post

–>

7 T test PA

## PA - PTSD TR
#### PA_Total_Pre PA_Total_Post

## PA - PTSD CTRL
#### PA_Total_Pre PA_Total_Post

## PA - Burnout TR
#### PA_Total_Pre PA_Total_Post

## PA - Burnout CTRL
#### PA_Total_Pre PA_Total_Post

## PA - General Population TR
#### PA_Total_Pre PA_Total_Post

## PA - General Population CTRL
#### PA_Total_Pre PA_Total_Post

–>

8 T test NA

## NA - PTSD TR
#### NA_Total_Pre NA_Total_Post

## NA - PTSD CTRL
#### NA_Total_Pre NA_Total_Post

## NA - Burnout TR
#### NA_Total_Pre NA_Total_Post

## NA - Burnout CTRL
#### NA_Total_Pre NA_Total_Post

## NA - General Population TR
#### NA_Total_Pre NA_Total_Post

## NA - General Population CTRL
#### NA_Total_Pre NA_Total_Post

–>


9 Session Info

R version 3.6.1 (2019-07-05)
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    

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

other attached packages:
 [1] pwr_1.2-2                  rlang_0.4.6                emmeans_1.4.5              rio_0.5.16                 scales_1.1.0               ggpubr_0.2.5              
 [7] magrittr_1.5               tadaatoolbox_0.16.1        summarytools_0.8.8         rstatix_0.5.0              broom_0.5.6                PerformanceAnalytics_1.5.2
[13] xts_0.11-2                 zoo_1.8-4                  psych_1.9.12.31            forcats_0.5.0              stringr_1.4.0              dplyr_0.8.5               
[19] purrr_0.3.3                readr_1.3.1                tidyr_1.0.2                tibble_3.0.0               ggplot2_3.3.0              tidyverse_1.3.0           
[25] papaja_0.1.0.9997          pacman_0.5.1              

loaded via a namespace (and not attached):
 [1] TH.data_1.0-9      colorspace_1.4-1   ggsignif_0.4.0     pryr_0.1.4         ellipsis_0.3.0     estimability_1.3   snakecase_0.9.2    fs_1.4.1          
 [9] rstudioapi_0.11    farver_2.0.3       fansi_0.4.1        mvtnorm_1.1-0      lubridate_1.7.4    xml2_1.3.1         codetools_0.2-16   splines_3.6.1     
[17] mnormt_1.5-6       knitr_1.28         pixiedust_0.8.6    jsonlite_1.6.1     dbplyr_1.4.3       compiler_3.6.1     httr_1.4.1         backports_1.1.6   
[25] assertthat_0.2.1   Matrix_1.2-17      cli_2.0.2          htmltools_0.4.0    tools_3.6.1        coda_0.19-2        gtable_0.3.0       glue_1.4.0        
[33] Rcpp_1.0.4.6       carData_3.0-2      cellranger_1.1.0   vctrs_0.2.4        nlme_3.1-140       xfun_0.13          openxlsx_4.1.0     rvest_0.3.5       
[41] lifecycle_0.2.0    MASS_7.3-51.4      hms_0.5.3          parallel_3.6.1     sandwich_2.5-0     expm_0.999-3       curl_4.3           gridExtra_2.3     
[49] pander_0.6.3       stringi_1.4.6      nortest_1.0-4      boot_1.3-22        zip_1.0.0          pkgconfig_2.0.3    matrixStats_0.54.0 bitops_1.0-6      
[57] lattice_0.20-38    rapportools_1.0    labeling_0.3       tidyselect_1.0.0   plyr_1.8.6         R6_2.4.1           DescTools_0.99.34  generics_0.0.2    
[65] multcomp_1.4-8     DBI_1.0.0          pillar_1.4.3       haven_2.2.0        foreign_0.8-71     withr_2.1.2        survival_2.44-1.1  abind_1.4-5       
[73] RCurl_1.95-4.11    janitor_2.0.1      modelr_0.1.6       crayon_1.3.4       car_3.0-7          viridis_0.5.1      grid_3.6.1         readxl_1.3.1      
[81] data.table_1.12.8  reprex_0.3.0       digest_0.6.25      xtable_1.8-4       munsell_0.5.0      viridisLite_0.3.0  quadprog_1.5-5    
 

A work by Claudiu Papasteri

 

LS0tDQp0aXRsZTogIjxicj4gUEE0IiANCnN1YnRpdGxlOiAiUmVwb3J0Ig0KYXV0aG9yOiAiPGJyPiBDbGF1ZGl1IFBhcGFzdGVyaSINCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVkICVtICVZJylgIg0Kb3V0cHV0OiANCiAgICBodG1sX25vdGVib29rOg0KICAgICAgICAgICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgICAgICAgICB0b2M6IHRydWUNCiAgICAgICAgICAgIHRvY19kZXB0aDogMg0KICAgICAgICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgICAgICAgICB0aGVtZTogc3BhY2VsYWINCiAgICAgICAgICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiBBcmlhbA0KICAgICAgICAgICAgZmlnX3dpZHRoOiAxMA0KICAgICAgICAgICAgZmlnX2hlaWdodDogOQ0KICAgICMgcGRmX2RvY3VtZW50OiANCiAgICAgICAgICAgICMgdG9jOiB0cnVlDQogICAgICAgICAgICAjICB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgICMgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgICAgICAgICAgIyBmb250c2l6ZTogMTFwdA0KICAgICAgICAgICAgIyBnZW9tZXRyeTogbWFyZ2luPTFpbg0KICAgICAgICAgICAgIyBmaWdfd2lkdGg6IDcNCiAgICAgICAgICAgICMgZmlnX2hlaWdodDogNg0KICAgICAgICAgICAgIyBmaWdfY2FwdGlvbjogdHJ1ZQ0KICAgICMgZ2l0aHViX2RvY3VtZW50OiANCiAgICAgICAgICAgICMgdG9jOiB0cnVlDQogICAgICAgICAgICAjIHRvY19kZXB0aDogMg0KICAgICAgICAgICAgIyBodG1sX3ByZXZpZXc6IGZhbHNlDQogICAgICAgICAgICAjIGZpZ193aWR0aDogNQ0KICAgICAgICAgICAgIyBmaWdfaGVpZ2h0OiA1DQogICAgICAgICAgICAjIGRldjoganBlZw0KLS0tDQoNCg0KPCEtLSBTZXR1cCAtLT4NCg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMga2ludHIgb3B0aW9ucw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBjb21tZW50ID0gIiMiLA0KICBjb2xsYXBzZSA9IFRSVUUsDQogIGVycm9yID0gVFJVRSwNCiAgZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBjYWNoZSA9IFRSVUUgICAgICAgIyBlY2hvID0gRmFsc2UgZm9yIGdpdGh1Yl9kb2N1bWVudCwgYnV0IHdpbGwgYmUgZm9sZGVkIGluIGh0bWxfbm90ZWJvb2sNCikNCg0KIyBHZW5lcmFsIFIgb3B0aW9ucyBhbmQgaW5mbw0Kc2V0LnNlZWQoMTExKSAgICAgICAgICAgICAgICMgaW4gY2FzZSB3ZSB1c2UgcmFuZG9taXplZCBwcm9jZWR1cmVzICAgICAgIA0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpICAgICAgICMgcG9zaXRpdmUgdmFsdWVzIGJpYXMgdG93YXJkcyBmaXhlZCBhbmQgbmVnYXRpdmUgdG93YXJkcyBzY2llbnRpZmljIG5vdGF0aW9uDQoNCiMgTG9hZCBwYWNrYWdlcw0KaWYgKCFyZXF1aXJlKCJwYWNtYW4iKSkgaW5zdGFsbC5wYWNrYWdlcygicGFjbWFuIikNCnBhY2thZ2VzIDwtIGMoDQogICJwYXBhamEiLA0KICAidGlkeXZlcnNlIiwgICAgICAgDQogICJwc3ljaCIsICJQZXJmb3JtYW5jZUFuYWx5dGljcyIsICAgICAgICAgIA0KICAiYnJvb20iLCAicnN0YXRpeCIsDQogICJzdW1tYXJ5dG9vbHMiLCAidGFkYWF0b29sYm94IiwgICAgICAgICAgIA0KICAiZ2dwbG90MiIsICJnZ3B1YnIiLCAic2NhbGVzIiwgICAgICAgIA0KICAicmlvIiwNCiAgImdncHViciIsICJyc3RhdGl4IiwgImJyb29tIiwgImVtbWVhbnMiLCAicmxhbmciLA0KICAicHdyIg0KICAjICwgLi4uDQopDQppZiAoIXJlcXVpcmUoInBhY21hbiIpKSBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKQ0KcGFjbWFuOjpwX2xvYWQoY2hhciA9IHBhY2thZ2VzKQ0KDQojIFRoZW1lcyBmb3IgZ2dwbG90MiBwbG90aW5nIChoZXJlIHVzZWQgQVBBIHN0eWxlKQ0KdGhlbWVfc2V0KHRoZW1lX2FwYSgpKQ0KYGBgDQoNCg0KDQoNCg0KPCEtLSBSZXBvcnQgLS0+DQoNCiMgRGVmaW5lIGZ1bmN0aW9ucw0KDQpgYGB7ciBkZWZfZnVuY30NCiMjIERlZmluZSBmdW5jdGlvbiB0aGF0IHJlY29kZXMgdG8gbnVtZXJpYywgYnV0IHdhdGNoZXMgb3V0IHRvIGNvZXJjaW9uIHRvIG5vdCBpbnRyb2R1Y2UgTkFzDQpjb2xzdG9udW1lcmljIDwtIGZ1bmN0aW9uKGRmKXsNCiAgdHJ5Q2F0Y2goew0KICAgIGRmX251bSA8LSBhcy5kYXRhLmZyYW1lKA0KICAgICAgbGFwcGx5KGRmLA0KICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHsgYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeCkpfSkpIA0KICB9LHdhcm5pbmcgPSBmdW5jdGlvbihzdG9wX29uX3dhcm5pbmcpIHsNCiAgICBtZXNzYWdlKCJTdG9wZWQgdGhlIGV4ZWN1dGlvbiBvZiBudW1lcmljIGNvbnZlcnNpb246ICIsIGNvbmRpdGlvbk1lc3NhZ2Uoc3RvcF9vbl93YXJuaW5nKSkNCiAgfSkgDQp9DQojIw0KIyMgRGVmaW5lIGZ1bmN0aW9uIHRoYXQgcmV2ZXJzZSBjb2RlcyBpdGVtcw0KUmV2ZXJzZUNvZGUgPC0gZnVuY3Rpb24oZGYsIHRvbnVtZXJpYyA9IEZBTFNFLCBtaW4gPSBOVUxMLCBtYXggPSBOVUxMKSB7DQogIGlmKHRvbnVtZXJpYykgZGYgPC0gY29sc3RvbnVtZXJpYyhkZikNCiAgZGYgPC0gKG1heCArIG1pbikgLSBkZg0KfQ0KIyMNCiMjIERlZmluZSBmdW5jdGlvbiB0aGF0IHNjb3JlcyBvbmx5IHJvd3Mgd2l0aCBsZXNzIHRoYW4gMTAlIE5BcyAocmV0dXJucyBOQSBpZiBhbGwgb3IgYWJvdmUgdGhyZXNob2xkIHBlcmNlbnRhZ2Ugb2Ygcm93cyBhcmUgTkEpOyBjYW4gcmV2ZXJzZSBjb2RlIGlmIHZlY3RvciBvZiBjb2x1bW4gaW5kZXhlcyBhbmQgbWluLCBtYXggYXJlIHByb3ZpZGVkLg0KU2NvcmVMaWtlcnQgPC0gZnVuY3Rpb24oZGYsIG5hcGVyY2VudCA9IC4xLCB0b251bWVyaWMgPSBGQUxTRSwgcmV2ZXJzZWNvbHMgPSBOVUxMLCBtaW4gPSBOVUxMLCBtYXggPSBOVUxMKSB7DQogIHJldmVyc2VfbGlzdCA8LSBsaXN0KHJldmVyc2Vjb2xzID0gcmV2ZXJzZWNvbHMsIG1pbiA9IG1pbiwgbWF4ID0gbWF4KQ0KICByZXZlcnNlX2NoZWNrIDwtICFzYXBwbHkocmV2ZXJzZV9saXN0LCBpcy5udWxsKQ0KICANCiAgIyBSZWNvZGUgdG8gbnVtZXJpYywgYnV0IHdhdGNoIG91dCB0byBjb2VyY2lvbiB0byBub3QgaW50cm9kdWNlIE5Bcw0KICBjb2xzdG9udW1lcmljIDwtIGZ1bmN0aW9uKGRmKXsNCiAgICB0cnlDYXRjaCh7DQogICAgICBkZl9udW0gPC0gYXMuZGF0YS5mcmFtZSgNCiAgICAgICAgbGFwcGx5KGRmLA0KICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkgeyBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih4KSl9KSkgDQogICAgfSx3YXJuaW5nID0gZnVuY3Rpb24oc3RvcF9vbl93YXJuaW5nKSB7DQogICAgICBtZXNzYWdlKCJTdG9wZWQgdGhlIGV4ZWN1dGlvbiBvZiBudW1lcmljIGNvbnZlcnNpb246ICIsIGNvbmRpdGlvbk1lc3NhZ2Uoc3RvcF9vbl93YXJuaW5nKSkNCiAgICB9KSANCiAgfQ0KICANCiAgaWYodG9udW1lcmljKSBkZiA8LSBjb2xzdG9udW1lcmljKGRmKQ0KICANCiAgaWYoYWxsKHJldmVyc2VfY2hlY2spKXsNCiAgICBkZlsgLHJldmVyc2Vjb2xzXSA8LSAobWF4ICsgbWluKSAtIGRmWyAscmV2ZXJzZWNvbHNdDQogIH1lbHNlIGlmKGFueShyZXZlcnNlX2NoZWNrKSl7DQogICAgc3RvcCgiSW5zdWZpY2llbnQgaW5mbyBmb3IgcmV2ZXJzaW5nLiBQbGVhc2UgcHJvdmlkZTogIiwgcGFzdGUobmFtZXMocmV2ZXJzZV9saXN0KVshcmV2ZXJzZV9jaGVja10sIGNvbGxhcHNlID0gIiwgIikpDQogIH0NCiAgDQogIGlmZWxzZShyb3dTdW1zKGlzLm5hKGRmKSkgPiBuY29sKGRmKSAqIG5hcGVyY2VudCwNCiAgICAgICAgIE5BLA0KICAgICAgICAgcm93U3VtcyhkZiwgbmEucm0gPSBUUlVFKSAqIE5BIF4gKHJvd1N1bXMoIWlzLm5hKGRmKSkgPT0gMCkNCiAgKQ0KfQ0KIyMNCmBgYA0KDQoNCmBgYHtyIGRlZl9mdW5jX3R0ZXN0LCBoaWRlPVRSVUV9DQojIyBGdW5jIHQgdGVzdCBzaSBib3hwbG90IHNpbXBsdQ0KZnVuY190X2JveCA8LSBmdW5jdGlvbihkZiwgaW5kLCBwcmVfdmFyLCBwb3N0X3Zhcil7DQogIHZhcnMgPC0gYyhpbmQsIHByZV92YXIsIHBvc3RfdmFyKSAgICAgICAgICAgICAgICAjIHRvIGF2b2lkIG5ldyB0aWR5dmVyc2UgZXJyb3Igb2YgYW1iaWd1aXR5IGR1ZSB0byBleHRlcm5hbCB2ZWN0b3MNCiAgZGZfbW9kaWYgPC0NCiAgICBkZiAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KHRpZHlzZWxlY3Q6OmFsbF9vZih2YXJzKSkgJT4lIA0KICAgIHRpZHlyOjpkcm9wX25hKCkgJT4lDQogICAgZ2F0aGVyKHRpZHlzZWxlY3Q6OmFsbF9vZihwcmVfdmFyKSwgdGlkeXNlbGVjdDo6YWxsX29mKHBvc3RfdmFyKSwga2V5ID0gIkNvbmQiLCB2YWx1ZSA9ICJ2YWx1ZSIpICU+JSANCiAgICBtdXRhdGVfYXQodmFycyhjKDEsIDIpKSwgYXMuZmFjdG9yKSAlPiUgDQogICAgbXV0YXRlKENvbmQgPSBmYWN0b3IoQ29uZCwgbGV2ZWxzID0gYyhwcmVfdmFyLCBwb3N0X3ZhcikpKSANCiAgDQogIHN0YXRfY29tcCA8LSBnZ3B1YnI6OmNvbXBhcmVfbWVhbnModmFsdWUgfiBDb25kLCBkYXRhID0gZGZfbW9kaWYsIG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFKQ0KICANCiAgc3RhdF9jb21wMiA8LQ0KICAgIGRmX21vZGlmICU+JSANCiAgICBkbyh0aWR5KHQudGVzdCguJHZhbHVlIH4gLiRDb25kLA0KICAgICAgICAgICAgICAgICAgIHBhaXJlZCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgZGF0YT0uKSkpDQogIA0KICBwbG90IDwtIA0KICAgIGdncHVicjo6Z2dwYWlyZWQoZGZfbW9kaWYsIHggPSAiQ29uZCIsIHkgPSAidmFsdWUiLCBpZCA9IGluZCwgDQogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJDb25kIiwgbGluZS5jb2xvciA9ICJncmF5IiwgbGluZS5zaXplID0gMC40LA0KICAgICAgICAgICAgICAgICAgICAgcGFsZXR0ZSA9IGMoIiMwMEFGQkIiLCAiI0ZDNEUwNyIpLCBsZWdlbmQgPSAibm9uZSIpICsNCiAgICAgIHN0YXRfc3VtbWFyeShmdW4uZGF0YSA9IG1lYW5fc2UsICBjb2xvdXIgPSAiZGFya3JlZCIpICsNCiAgICAgIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFLCBsYWJlbC54ID0gYXMubnVtZXJpYyhkZl9tb2RpZiRDb25kKS0wLjQsIGxhYmVsLnkgPSBtYXgoZGZfbW9kaWYkdmFsdWUpKzAuNSkgKyANCiAgICAgIGdncHVicjo6c3RhdF9jb21wYXJlX21lYW5zKG1ldGhvZCA9ICJ0LnRlc3QiLCBwYWlyZWQgPSBUUlVFLCBsYWJlbCA9ICJwLnNpZ25pZiIsIGNvbXBhcmlzb25zID0gbGlzdChjKHByZV92YXIsIHBvc3RfdmFyKSkpDQogIA0KICBjYXQocGFzdGUwKCIjIyMjICIsIHByZV92YXIsICIgIiwgcG9zdF92YXIsICJcbiIsICJcbiIpKQ0KICBwcmludChzdGF0X2NvbXApDQogIHByaW50KHN0YXRfY29tcDIpDQogIHByaW50KHBsb3QpDQp9DQpgYGANCg0KDQpgYGB7ciBzYW1wbGVzaXplX2lkZXB0dGVzdH0NCnNhbXBsZXNpemVfcGFpcmVkdHRlc3QgPC0gZnVuY3Rpb24oZGYsIHByZV92YXIsIHBvc3RfdmFyKXsNCiAgdmFycyA8LSBjKHByZV92YXIsIHBvc3RfdmFyKSAgICAgICAgICAgICAgICAjIHRvIGF2b2lkIG5ldyB0aWR5dmVyc2UgZXJyb3Igb2YgYW1iaWd1aXR5IGR1ZSB0byBleHRlcm5hbCB2ZWN0b3JzDQogIGRmX21vZGlmIDwtDQogICAgZGYgJT4lDQogICAgZHBseXI6OnNlbGVjdCh0aWR5c2VsZWN0OjphbGxfb2YodmFycykpICU+JSANCiAgICB0aWR5cjo6ZHJvcF9uYSgpICU+JQ0KICAgIGdhdGhlcih0aWR5c2VsZWN0OjphbGxfb2YocHJlX3ZhciksIHRpZHlzZWxlY3Q6OmFsbF9vZihwb3N0X3ZhciksIGtleSA9ICJDb25kIiwgdmFsdWUgPSAidmFsdWUiKSAlPiUgDQogICAgbXV0YXRlKENvbmQgPSBmYWN0b3IoQ29uZCwgbGV2ZWxzID0gYyhwcmVfdmFyLCBwb3N0X3ZhcikpKSANCiAgDQogIGNhdCgiIyMgQ29oZW4ncyBkIFxuIikNCiAgZWZmX3NpemVfdGFibGUgPC0NCiAgICBkZl9tb2RpZiAlPiUNCiAgICBjb2hlbnNfZCh2YWx1ZSB+IENvbmQsIHBhaXJlZCA9IFRSVUUpICU+JQ0KICAgIHByaW50KCkNCiAgZWZmX3NpemUgPC0gYXMubnVtZXJpYyhlZmZfc2l6ZV90YWJsZSRlZmZzaXplKQ0KDQogIGNhdCgiIyMgU2FtcGxlIFNpemUgZXN0aW1hdGlvbiBcbiIpDQogIHNhbXBsZV9zaXplX3RhYmxlIDwtDQogICAgcHdyOjpwd3IudC50ZXN0KGQgPSBlZmZfc2l6ZSwgc2lnLmxldmVsID0gLjA1LCBwb3dlciA9IC44LCB0eXBlID0gInBhaXJlZCIsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpIA0KICBzYW1wbGVfc2l6ZV90YWJsZSAlPiUgYnJvb206OnRpZHkoKSAlPiUgcHJpbnQoKQ0KDQogIHBsb3Qoc2FtcGxlX3NpemVfdGFibGUpDQp9ICANCmBgYA0KDQoNCmBgYHtyIGRlZl9mdW5jX0FOQ09WQVBvc3R9DQojIGxpYnJhcnkodGlkeXZlcnNlKQ0KIyBsaWJyYXJ5KGdncHVicikNCiMgbGlicmFyeShyc3RhdGl4KQ0KIyBsaWJyYXJ5KGJyb29tKQ0KIyBsaWJyYXJ5KGVtbWVhbnMpDQojIGxpYnJhcnkocmxhbmcpDQoNCg0KIyBGdW5jdGlvbiBBTkNPVkFQb3N0DQojIFRha2VzIExvbmcgRGF0YQ0KQU5DT1ZBUG9zdF9mdW5jIDwtIA0KICBmdW5jdGlvbihkYXRhLCBpZF92YXIsIA0KICAgICAgICAgICB0aW1lX3ZhciwgcHJlX2xhYmVsLCBwb3N0X2xhYmVsLA0KICAgICAgICAgICB2YWx1ZV92YXIgPSBzY29yZXMsIGNvbmRfdmFyLCANCiAgICAgICAgICAgYXNzdW1fY2hlY2sgPSBUUlVFLCBwb3N0aG9jID0gVFJVRSwgDQogICAgICAgICAgIHBfYWRqdXN0X21ldGhvZCA9ICJib25mZXJyb25pIil7DQogIA0KICBpZF92YXJfZW5xIDwtIHJsYW5nOjplbnF1byhpZF92YXIpDQogIGlkX3Zhcl9uYW1lIDwtIHJsYW5nOjphc19uYW1lKGlkX3Zhcl9lbnEpICAgIA0KICB0aW1lX3Zhcl9lbnEgPC0gcmxhbmc6OmVucXVvKHRpbWVfdmFyKQ0KICB0aW1lX3Zhcl9uYW1lIDwtIHJsYW5nOjphc19uYW1lKHRpbWVfdmFyX2VucSkNCiAgcHJlX3Zhcl9lbnEgPC0gcmxhbmc6OmVucXVvKHByZV9sYWJlbCkNCiAgcHJlX3Zhcl9uYW1lIDwtIHJsYW5nOjphc19uYW1lKHByZV92YXJfZW5xKSAgDQogIHBvc3RfdmFyX2VucSA8LSBybGFuZzo6ZW5xdW8ocG9zdF9sYWJlbCkNCiAgcG9zdF92YXJfbmFtZSA8LSBybGFuZzo6YXNfbmFtZShwb3N0X3Zhcl9lbnEpDQogIGNvbmRfdmFyX2VucSA8LSBybGFuZzo6ZW5xdW8oY29uZF92YXIpDQogIGNvbmRfdmFyX25hbWUgPC0gcmxhbmc6OmFzX25hbWUoY29uZF92YXJfZW5xKQ0KICB2YWx1ZV92YXJfZW5xIDwtIHJsYW5nOjplbnF1byh2YWx1ZV92YXIpDQogIHZhbHVlX3Zhcl9uYW1lIDwtIHJsYW5nOjphc19uYW1lKHZhbHVlX3Zhcl9lbnEpIA0KICANCiAgZGF0YV93aWRlciA8LQ0KICAgIGRhdGEgJT4lDQogICAgZHBseXI6OnNlbGVjdCghIWlkX3Zhcl9lbnEsICEhdGltZV92YXJfZW5xLCAhIWNvbmRfdmFyX2VucSwgISF2YWx1ZV92YXJfZW5xKSAlPiUNCiAgICBzcHJlYWQoa2V5ID0gdGltZV92YXJfbmFtZSwgdmFsdWUgPSB2YWx1ZV92YXJfbmFtZSkgIyAlPiUgICAgICMgaWYgbmVlZCB0byBjb21wdXRlIGNoYW5nZSBzY29yZSBzdGF0aXN0aWNzIGdvIGZyb20gaGVyZQ0KICAgICMgbXV0YXRlKGRpZmZlcmVuY2UgPSAhIXBvc3RfdmFyX2VucSAtICEhcHJlX3Zhcl9lbnEpICANCiAgICANCiAgIyBBc3N1bXB0aW9ucw0KICBpZihhc3N1bV9jaGVjayl7DQogIGNhdCgiXG4gTGluZWFyaXR5IGFzc3VtcHRpb25MaW5lYXJpdHkgYXNzdW1wdGlvbiAobGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHByZS10ZXN0IGFuZCBwb3N0LXRlc3QgZm9yIGVhY2ggZ3JvdXApIFxuIikNCiAgIyBDcmVhdGUgYSBzY2F0dGVyIHBsb3QgYmV0d2VlbiB0aGUgY292YXJpYXRlIChpLmUuLCBwcmV0ZXN0KSBhbmQgdGhlIG91dGNvbWUgdmFyaWFibGUgKGkuZS4sIHBvc3R0ZXN0KQ0KICBzY2F0dGVyX2xpbiA8LSAgDQogICAgZ2dzY2F0dGVyKGRhdGFfd2lkZXIsIHggPSBwcmVfdmFyX25hbWUsIHkgPSBwb3N0X3Zhcl9uYW1lLCBjb2xvciA9IGNvbmRfdmFyX25hbWUsIA0KICAgICAgICAgICAgICBhZGQgPSAicmVnLmxpbmUiLCB0aXRsZSA9ICJMaW5lYXJpdHkgYXNzdW1wdGlvbiIpICsNCiAgICAgIHN0YXRfcmVnbGluZV9lcXVhdGlvbihhZXMobGFiZWwgPSAgcGFzdGUoLi5lcS5sYWJlbC4uLCAuLnJyLmxhYmVsLi4sIHNlcCA9ICJ+fn5+IiksIGNvbG9yID0gISFjb25kX3Zhcl9lbnEpKQ0KICANCiAgY2F0KCJcbiBIb21vZ2VuZWl0eSBvZiByZWdyZXNzaW9uIHNsb3BlcyAoaW50ZXJhY3Rpb24gdGVybSBpcyBuLnMuKSBcbiIpDQogIGRhdGFfd2lkZXIgJT4lIA0KICAgIGFub3ZhX3Rlc3QoYXMuZm9ybXVsYShwYXN0ZTAocG9zdF92YXJfbmFtZSwgIiB+ICIsIGNvbmRfdmFyX25hbWUsICIgKiAiLCBwcmVfdmFyX25hbWUpKSkgJT4lIA0KICAgIHByaW50KCkgICANCiAgDQogIGNhdCgiXG4gTm9ybWFsaXR5IG9mIHJlc2lkdWFscyAoTW9kZWwgZGlhZ25vc3RpY3MgJiBTaGFwaXJvIFdpbGspIFxuIikNCiAgIyBGaXQgdGhlIG1vZGVsLCB0aGUgY292YXJpYXRlIGdvZXMgZmlyc3QNCiAgbW9kZWwgPC0gDQogICAgbG0oYXMuZm9ybXVsYShwYXN0ZTAocG9zdF92YXJfbmFtZSwgIiB+ICIsIGNvbmRfdmFyX25hbWUsICIgKyAiLCBwcmVfdmFyX25hbWUpKSwNCiAgICAgICBkYXRhID0gZGF0YV93aWRlcikNCiAgY2F0KCJcbiBJbnNwZWN0IHRoZSBtb2RlbCBkaWFnbm9zdGljIG1ldHJpY3MgXG4iKQ0KICBtb2RlbC5tZXRyaWNzIDwtIA0KICAgIGF1Z21lbnQobW9kZWwpICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoLS5oYXQsIC0uc2lnbWEsIC0uZml0dGVkLCAtLnNlLmZpdCkgICU+JSAgICAjIFJlbW92ZSBkZXRhaWxzDQogICAgcHJpbnQoKQ0KICBjYXQoIlxuIE5vcm1hbGl0eSBvZiByZXNpZHVhbHMgKFNoYXBpcm8gV2lsayBwPi4wNSkgXG4iKQ0KICBzaGFwaXJvX3Rlc3QobW9kZWwubWV0cmljcyQucmVzaWQpICU+JSANCiAgICBwcmludCgpDQogIA0KICBjYXQoIlxuIEhvbW9nZW5laXR5IG9mIHZhcmlhbmNlcyAoTGV2ZW5l4oCZcyB0ZXN0IHA+LjA1KSBcbiIpDQogIG1vZGVsLm1ldHJpY3MgJT4lIA0KICAgIGxldmVuZV90ZXN0KGFzLmZvcm11bGEocGFzdGUwKCIucmVzaWQiLCAiIH4gIiwgY29uZF92YXJfbmFtZSkpICkgJT4lICAgICANCiAgICBwcmludCgpDQogIA0KICBjYXQoIlxuIE91dGxpZXJzIChuZWVkcyB0byBiZSAwKSBcbiIpDQogIG1vZGVsLm1ldHJpY3MgJT4lIA0KICAgIGZpbHRlcihhYnMoLnN0ZC5yZXNpZCkgPiAzKSAlPiUNCiAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICAgIHByaW50KCkNCiAgDQogIH0NCiAgDQogIGNhdCgiXG4gQU5DT1ZBUG9zdCBcbiIpDQogIHJlc19hbmNvdmEgPC0gDQogICAgZGF0YV93aWRlciAlPiUgDQogICAgYW5vdmFfdGVzdChhcy5mb3JtdWxhKHBhc3RlMChwb3N0X3Zhcl9uYW1lLCAiIH4gIiwgIHByZV92YXJfbmFtZSwgIiArICIsIGNvbmRfdmFyX25hbWUpKSkgICAgICAgIyB0aGUgY292YXJpYXRlIG5lZWRzIHRvIGJlIGZpcnN0IHRlcm0gDQogIGdldF9hbm92YV90YWJsZShyZXNfYW5jb3ZhKSAlPiUgcHJpbnQoKQ0KICANCiAgY2F0KCJcbiBQYWlyd2lzZSBjb21wYXJpc29ucyBcbiIpDQogIHB3YyA8LSANCiAgICBkYXRhX3dpZGVyICU+JSANCiAgICBlbW1lYW5zX3Rlc3QoYXMuZm9ybXVsYShwYXN0ZTAocG9zdF92YXJfbmFtZSwgIiB+ICIsIGNvbmRfdmFyX25hbWUpKSwgICAgICAgDQogICAgICAgICAgICAgICAgIGNvdmFyaWF0ZSA9ICEhcHJlX3Zhcl9lbnEsDQogICAgICAgICAgICAgICAgIHAuYWRqdXN0Lm1ldGhvZCA9IHBfYWRqdXN0X21ldGhvZCkNCiAgcHdjICU+JSBwcmludCgpDQogIGNhdCgiXG4gRGlzcGxheSB0aGUgYWRqdXN0ZWQgbWVhbnMgb2YgZWFjaCBncm91cCwgYWxzbyBjYWxsZWQgYXMgdGhlIGVzdGltYXRlZCBtYXJnaW5hbCBtZWFucyAoZW1tZWFucykgXG4iKQ0KICBnZXRfZW1tZWFucyhwd2MpICU+JSBwcmludCgpDQogIA0KICAjIFZpc3VhbGl6YXRpb246IGxpbmUgcGxvdHMgd2l0aCBwLXZhbHVlcw0KICBwd2MgPC0gDQogICAgcHdjICU+JSANCiAgICBhZGRfeHlfcG9zaXRpb24oeCA9IGNvbmRfdmFyX25hbWUsIGZ1biA9ICJtZWFuX3NlIikNCiAgDQogIGxpbmVfcGxvdCA8LSANCiAgICBnZ2xpbmUoZ2V0X2VtbWVhbnMocHdjKSwgeCA9IGNvbmRfdmFyX25hbWUsIHkgPSAiZW1tZWFuIikgKw0KICAgICAgZ2VvbV9lcnJvcmJhcihhZXMoeW1pbiA9IGNvbmYubG93LCB5bWF4ID0gY29uZi5oaWdoKSwgd2lkdGggPSAwLjIpICsgDQogICAgICBzdGF0X3B2YWx1ZV9tYW51YWwocHdjLCBoaWRlLm5zID0gVFJVRSwgdGlwLmxlbmd0aCA9IEZBTFNFKSArDQogICAgICBsYWJzKHN1YnRpdGxlID0gZ2V0X3Rlc3RfbGFiZWwocmVzX2FuY292YSwgZGV0YWlsZWQgPSBUUlVFKSwNCiAgICAgICAgICAgY2FwdGlvbiA9IGdldF9wd2NfbGFiZWwocHdjKSkNCiAgDQogIGlmKGFzc3VtX2NoZWNrKXsNCiAgICBsaXN0KHNjYXR0ZXJfbGluLCBsaW5lX3Bsb3QpDQogIH1lbHNlew0KICAgIGxpbmVfcGxvdA0KICB9DQogIA0KfQ0KDQojIGV4Lg0KIyBBTkNPVkFQb3N0X2Z1bmMobmV3X2FueGlldHksIHRpbWVfdmFyID0gdGltZSwgcHJlX2xhYmVsID0gcHJldGVzdCwgcG9zdF9sYWJlbCA9IHBvc3R0ZXN0LA0KIyAgICAgICAgICAgdmFsdWVfdmFyID0gc2NvcmVzLCBjb25kX3ZhciA9IGdyb3VwLCBhc3N1bV9jaGVjayA9IFRSVUUsIHBfYWRqdXN0X21ldGhvZCA9ICJib25mZXJyb25pIikNCmBgYA0KDQoNCmBgYHtyIGRlZl9mdW5jX21peGVkQU5PVkF9DQojIGxpYnJhcnkodGlkeXZlcnNlKQ0KIyBsaWJyYXJ5KGdncHVicikNCiMgbGlicmFyeShyc3RhdGl4KQ0KIyBsaWJyYXJ5KHJsYW5nKQ0KDQojIERlZmluZSBGdW5jdGlvbiBmb3IgTWl4ZWQgQW5vdmENCnR3X21peGVkQU5PVkFfZnVuYyA8LSANCiAgZnVuY3Rpb24oZGF0YSwgaWRfdmFyLCBjb25kX3ZhciwgdGltZV92YXIsIHZhbHVlX3ZhciwgDQogICAgICAgICAgIGFzc3VtX2NoZWNrID0gVFJVRSwgcG9zdGhvY19zaWdfaW50ZXJhYyA9IEZBTFNFLCBwb3N0aG9jX25zX2ludGVyYWMgPSBGQUxTRSwNCiAgICAgICAgICAgcF9hZGp1c3RfbWV0aG9kID0gImJvbmZlcnJvbmkiKXsNCiAgICANCiAgICAjIGlucHV0IGRhdGFmcmFtZSBuZWVkcyB0byBoYXZlIGNvbHVtbnMgbmFtZXMgZGlmZnJlbnQgZnJvbSAidmFyaWFibGUiIGFuZCAidmFsdWUiIGJlY2F1c2UgaXQgY29sbGlkZXMgd2l0aCByc3RhdGl4OjpzaGFwaXJvX3Rlc3QNCiAgICANCiAgICBpZF92YXJfZW5xIDwtIHJsYW5nOjplbnF1byhpZF92YXIpICANCiAgICBjb25kX3Zhcl9lbnEgPC0gcmxhbmc6OmVucXVvKGNvbmRfdmFyKQ0KICAgIGNvbmRfdmFyX25hbWUgPC0gcmxhbmc6OmFzX25hbWUoY29uZF92YXJfZW5xKQ0KICAgIHRpbWVfdmFyX2VucSA8LSBybGFuZzo6ZW5xdW8odGltZV92YXIpDQogICAgdGltZV92YXJfbmFtZSA8LSBybGFuZzo6YXNfbmFtZSh0aW1lX3Zhcl9lbnEpDQogICAgdmFsdWVfdmFyX2VucSA8LSBybGFuZzo6ZW5xdW8odmFsdWVfdmFyKQ0KICAgIHZhbHVlX3Zhcl9uYW1lIDwtIHJsYW5nOjphc19uYW1lKHZhbHVlX3Zhcl9lbnEpDQogICAgDQogICAgZGF0YSA8LSAgICAgICAgICAgICAgICAgICMgbmVlZCB0byBzdWJzZXQgYmVjdWFzZSBvZiBzdHJhbmdlIGNvbnRyYXN0cyBlcnJvciBpbiBhbm92YV90ZXN0KCkNCiAgICAgIGRhdGEgJT4lDQogICAgICBkcGx5cjo6c2VsZWN0KCEhaWRfdmFyX2VucSwgISF0aW1lX3Zhcl9lbnEsICEhY29uZF92YXJfZW5xLCAhIXZhbHVlX3Zhcl9lbnEpIA0KICAgIA0KICAgICMgQXNzdW1wdGlvbnMNCiAgICBpZihhc3N1bV9jaGVjayl7DQogICAgICBjYXQoIlxuIE91dGxpZXJzIFxuIikNCiAgICAgIGRhdGEgJT4lDQogICAgICAgIGRwbHlyOjpncm91cF9ieSghIXRpbWVfdmFyX2VucSwgISFjb25kX3Zhcl9lbnEpICU+JQ0KICAgICAgICByc3RhdGl4OjppZGVudGlmeV9vdXRsaWVycyghIXZhbHVlX3Zhcl9lbnEpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG91dGxpZXJzIChuZWVkcyB0byBiZSAwKQ0KICAgICAgICBwcmludCgpDQogICAgICANCiAgICAgIGNhdCgiXG4gTm9ybWFsaXR5IGFzc3VtcHRpb24gKHA+LjA1KSBcbiIpDQogICAgICBkYXRhICU+JQ0KICAgICAgICBkcGx5cjo6Z3JvdXBfYnkoISF0aW1lX3Zhcl9lbnEsICEhY29uZF92YXJfZW5xKSAlPiUNCiAgICAgICAgcnN0YXRpeDo6c2hhcGlyb190ZXN0KCEhdmFsdWVfdmFyX2VucSkgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbm9ybWFsaXR5IGFzc3VtcHRpb24gKHA+LjA1KQ0KICAgICAgICBwcmludCgpDQogICAgICANCiAgICAgIHFxX3Bsb3QgPC0gDQogICAgICAgIGdncHVicjo6Z2dxcXBsb3QoZGF0YSA9IGRhdGEsIHZhbHVlX3Zhcl9uYW1lLCBnZ3RoZW1lID0gdGhlbWVfYncoKSwgdGl0bGUgPSAiUVEgUGxvdCIpICsNCiAgICAgICAgZ2dwbG90Mjo6ZmFjZXRfZ3JpZCh2YXJzKCEhdGltZV92YXJfZW5xKSwgdmFycyghIWNvbmRfdmFyX2VucSksIGxhYmVsbGVyID0gImxhYmVsX2JvdGgiKSAgICAjIFFRIHBsb3QNCiAgICAgIA0KICAgICAgY2F0KCJcbiBIb21vZ25laXR5IG9mIHZhcmlhbmNlIGFzc3VtcHRpb24gLSBMZXZlbmXigJlzIHRlc3QgKHA+LjA1KSBcbiIpDQogICAgICBkYXRhICU+JQ0KICAgICAgICBncm91cF9ieSghIXRpbWVfdmFyX2VucSApICU+JQ0KICAgICAgICBsZXZlbmVfdGVzdChhcy5mb3JtdWxhKHBhc3RlMCh2YWx1ZV92YXJfbmFtZSwgIiB+ICIsIGNvbmRfdmFyX25hbWUpKSkgJT4lDQogICAgICAgIHByaW50KCkNCiAgICAgIA0KICAgICAgY2F0KCJcbiBIb21vZ2VuZWl0eSBvZiBjb3ZhcmlhbmNlcyBhc3N1bXB0aW9uIC0gQm944oCZcyB0ZXN0IG9mIGVxdWFsaXR5IG9mIGNvdmFyaWFuY2UgbWF0cmljZXMgKHA+LjAwMSkgXG4iKQ0KICAgICAgYm94X20oZGF0YSA9IGRhdGFbLCB2YWx1ZV92YXJfbmFtZSwgZHJvcCA9IEZBTFNFXSwgZ3JvdXAgPSBkYXRhWywgY29uZF92YXJfbmFtZSwgZHJvcCA9IFRSVUVdKSAlPiUNCiAgICAgICAgcHJpbnQNCiAgICB9DQogICAgDQogICAgIyBUd28td2F5IHJtQU5PVkEgLSBjaGVjayBmb3IgaW50ZXJhY3Rpb24gKGV4LiBGKDIsIDIyKSA9IDMwLjQsIHAgPCAwLjAwMDEpDQogICAgY2F0KCJcbiBUd28td2F5IHJtQU5PVkEgXG4iKQ0KICAgIHJlc19hb3YgPC0gDQogICAgICBhbm92YV90ZXN0KGRhdGEgPSBkYXRhLCBkdiA9ICEhdmFsdWVfdmFyX2VucSwgd2lkID0gISFpZF92YXJfZW5xLCAgICAgICAgICAgICAgICMgYXV0b21hdGljYWxseSBkb2VzIHNwaGVyaWNpdHkgTWF1Y2hseeKAmXMgdGVzdA0KICAgICAgICAgICAgICAgICB3aXRoaW4gPSAhIXRpbWVfdmFyX2VucSwgYmV0d2VlbiA9ICEhY29uZF92YXJfZW5xKQ0KICAgIGdldF9hbm92YV90YWJsZShyZXNfYW92KSAlPiUgICMgZ2VzOiBHcmVlbmhvdXNlLUdlaXNzZXIgc3BoZXJpY2l0eSBjb3JyZWN0aW9uIGlzIGF1dG9tYXRpY2FsbHkgYXBwbGllZCB0byBmYWN0b3JzIHZpb2xhdGluZyB0aGUgc3BoZXJpY2l0eSBhc3N1bXB0aW9uICANCiAgICAgIHByaW50KCkNCiAgICANCiAgICANCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KICAgIA0KICAgICMtIFByb2NlZHVyZSBmb3IgYSBzaWduaWZpY2FudCB0d28td2F5IGludGVyYWN0aW9uIC0NCiAgICBpZihwb3N0aG9jX3NpZ19pbnRlcmFjKXsNCiAgICAgIGNhdCgiXG4gRWZmZWN0IG9mIGdyb3VwIGF0IGVhY2ggdGltZSBwb2ludCAtIE9uZS13YXkgQU5PVkFcbiIpDQogICAgICBvbmVfd2F5IDwtIA0KICAgICAgICBkYXRhICU+JQ0KICAgICAgICBncm91cF9ieSghIXRpbWVfdmFyX2VucSkgJT4lDQogICAgICAgIGFub3ZhX3Rlc3QoZHYgPSAhIXZhbHVlX3Zhcl9lbnEsIHdpZCA9ICEhaWRfdmFyX2VucSwgYmV0d2VlbiA9ICEhY29uZF92YXJfZW5xKSAlPiUNCiAgICAgICAgZ2V0X2Fub3ZhX3RhYmxlKCkgJT4lDQogICAgICAgIGFkanVzdF9wdmFsdWUobWV0aG9kID0gcF9hZGp1c3RfbWV0aG9kKQ0KICAgICAgb25lX3dheSAlPiUgcHJpbnQoKQ0KICAgICAgDQogICAgICBjYXQoIlxuIFBhaXJ3aXNlIGNvbXBhcmlzb25zIGJldHdlZW4gZ3JvdXAgbGV2ZWxzIFxuIikNCiAgICAgIHB3YyA8LSANCiAgICAgICAgZGF0YSAlPiUNCiAgICAgICAgZ3JvdXBfYnkoISF0aW1lX3Zhcl9lbnEpICU+JQ0KICAgICAgICBwYWlyd2lzZV90X3Rlc3QoYXMuZm9ybXVsYShwYXN0ZTAodmFsdWVfdmFyX25hbWUsICIgfiAiLCBjb25kX3Zhcl9uYW1lKSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgcC5hZGp1c3QubWV0aG9kID0gcF9hZGp1c3RfbWV0aG9kKQ0KICAgICAgcHdjICU+JSBwcmludCgpDQogICAgICBjYXQoIlxuIEVmZmVjdCBvZiB0aW1lIGF0IGVhY2ggbGV2ZWwgb2YgZXhlcmNpc2VzIGdyb3VwICAtIE9uZS13YXkgQU5PVkEgXG4iKQ0KICAgICAgb25lX3dheTIgPC0gDQogICAgICAgIGRhdGEgJT4lDQogICAgICAgIGdyb3VwX2J5KCEhY29uZF92YXJfZW5xKSAlPiUNCiAgICAgICAgYW5vdmFfdGVzdChkdiA9ICEhdmFsdWVfdmFyX2VucSwgd2lkID0gISFpZF92YXJfZW5xLCB3aXRoaW4gPSAhIXRpbWVfdmFyX2VucSkgJT4lDQogICAgICAgIGdldF9hbm92YV90YWJsZSgpICU+JQ0KICAgICAgICBhZGp1c3RfcHZhbHVlKG1ldGhvZCA9IHBfYWRqdXN0X21ldGhvZCkNCiAgICAgIG9uZV93YXkyICU+JSBwcmludCgpDQogICAgICANCiAgICAgIGNhdCgiXG4gUGFpcndpc2UgY29tcGFyaXNvbnMgYmV0d2VlbiB0aW1lIHBvaW50cyBhdCBlYWNoIGdyb3VwIGxldmVscyAod2UgaGF2ZSByZXBlYXRlZCBtZWFzdXJlcyBieSB0aW1lKSBcbiIpDQogICAgICBwd2MyIDwtDQogICAgICAgIGRhdGEgJT4lDQogICAgICAgIGdyb3VwX2J5KCEhY29uZF92YXJfZW5xKSAlPiUNCiAgICAgICAgcGFpcndpc2VfdF90ZXN0KA0KICAgICAgICAgIGFzLmZvcm11bGEocGFzdGUwKHZhbHVlX3Zhcl9uYW1lLCAiIH4gIiwgdGltZV92YXJfbmFtZSkpLCAgICAgIyBwYXN0ZSBmb3JtdWxhLCBub3QgcXVvc3VyZQ0KICAgICAgICAgIHBhaXJlZCA9IFRSVUUsDQogICAgICAgICAgcC5hZGp1c3QubWV0aG9kID0gcF9hZGp1c3RfbWV0aG9kDQogICAgICAgICkNCiAgICAgIHB3YzIgICU+JSBwcmludCgpDQogICAgfQ0KICAgIA0KICAgICMtIFByb2NlZHVyZSBmb3Igbm9uLXNpZ25pZmljYW50IHR3by13YXkgaW50ZXJhY3Rpb24tIA0KICAgICMgSWYgdGhlIGludGVyYWN0aW9uIGlzIG5vdCBzaWduaWZpY2FudCwgeW91IG5lZWQgdG8gaW50ZXJwcmV0IHRoZSBtYWluIGVmZmVjdHMgZm9yIGVhY2ggb2YgdGhlIHR3byB2YXJpYWJsZXM6IHRyZWF0bWVudCBhbmQgdGltZS4NCiAgICBpZihwb3N0aG9jX25zX2ludGVyYWMpew0KICAgICAgY2F0KCJcbiBDb21wYXJpc29ucyBmb3IgdHJlYXRtZW50IHZhcmlhYmxlIFxuIikNCiAgICAgIHB3Y19jb25kIDwtDQogICAgICAgIGRhdGEgJT4lDQogICAgICAgIHBhaXJ3aXNlX3RfdGVzdCgNCiAgICAgICAgICBhcy5mb3JtdWxhKHBhc3RlMCh2YWx1ZV92YXJfbmFtZSwgIiB+ICIsIGNvbmRfdmFyX25hbWUpKSwgICAgICMgcGFzdGUgZm9ybXVsYSwgbm90IHF1b3N1cmUgICAgICAgICAgICAgDQogICAgICAgICAgcGFpcmVkID0gRkFMU0UsDQogICAgICAgICAgcC5hZGp1c3QubWV0aG9kID0gcF9hZGp1c3RfbWV0aG9kDQogICAgICAgICkNCiAgICAgIHB3Y19jb25kICU+JSBwcmludCgpDQogICAgICBjYXQoIlxuIENvbXBhcmlzb25zIGZvciB0aW1lIHZhcmlhYmxlIFxuIikNCiAgICAgIHB3Y190aW1lIDwtDQogICAgICAgIGRhdGEgJT4lIA0KICAgICAgICBwYWlyd2lzZV90X3Rlc3QoDQogICAgICAgICAgYXMuZm9ybXVsYShwYXN0ZTAodmFsdWVfdmFyX25hbWUsICIgfiAiLCB0aW1lX3Zhcl9uYW1lKSksICAgICAjIHBhc3RlIGZvcm11bGEsIG5vdCBxdW9zdXJlDQogICAgICAgICAgcGFpcmVkID0gVFJVRSwNCiAgICAgICAgICBwLmFkanVzdC5tZXRob2QgPSBwX2FkanVzdF9tZXRob2QNCiAgICAgICAgKQ0KICAgICAgcHdjX3RpbWUgJT4lIHByaW50KCkNCiAgICB9DQogICAgDQogICAgIyBWaXN1YWxpemF0aW9uDQogICAgYnhfcGxvdCA8LSANCiAgICAgIGdnYm94cGxvdChkYXRhLCB4ID0gdGltZV92YXJfbmFtZSwgeSA9IHZhbHVlX3Zhcl9uYW1lLA0KICAgICAgICAgICAgICAgIGNvbG9yID0gY29uZF92YXJfbmFtZSwgcGFsZXR0ZSA9ICJqY28iKQ0KICAgIHB3YyA8LSANCiAgICAgIHB3YyAlPiUgDQogICAgICBhZGRfeHlfcG9zaXRpb24oeCA9IHRpbWVfdmFyX25hbWUpDQogICAgYnhfcGxvdCA8LSANCiAgICAgIGJ4X3Bsb3QgKyANCiAgICAgIHN0YXRfcHZhbHVlX21hbnVhbChwd2MsIHRpcC5sZW5ndGggPSAwLCBoaWRlLm5zID0gVFJVRSkgKw0KICAgICAgbGFicygNCiAgICAgICAgc3VidGl0bGUgPSBnZXRfdGVzdF9sYWJlbChyZXNfYW92LCBkZXRhaWxlZCA9IFRSVUUpLA0KICAgICAgICBjYXB0aW9uID0gZ2V0X3B3Y19sYWJlbChwd2MpDQogICAgICApDQogICAgDQogICAgaWYoYXNzdW1fY2hlY2speyANCiAgICAgIGxpc3QocXFfcGxvdCwgYnhfcGxvdCkNCiAgICB9ZWxzZXsNCiAgICAgIGJ4X3Bsb3QNCiAgICB9IA0KICAgIA0KICB9DQoNCiMgZXguIC0gcnVuIG9uIGxvbmcgZm9ybWF0DQojIHR3X21peGVkQU5PVkFfZnVuYyhkYXRhID0gYW54aWV0eSwgaWRfdmFyID0gaWQsIGNvbmRfdmFyID0gZ3JvdXAsIHRpbWVfdmFyID0gdGltZSwgdmFsdWVfdmFyID0gc2NvcmUsDQojICAgICAgICAgICAgICAgICBwb3N0aG9jX3NpZ19pbnRlcmFjID0gVFJVRSwgcG9zdGhvY19uc19pbnRlcmFjID0gVFJVRSkNCg0KYGBgDQoNCg0KDQojIFJlYWQsIENsZWFuLCBSZWNvZGUNCg0KYGBge3IgcmVkX2NsZWFuX3JlY29kZV9tZXJnZSwgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9RkFMU0V9DQojfn5+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+fg0KIyBSZWFkLCBDbGVhbiwgUmVjb2RlLCBVbml0ZQ0KI35+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+fn4NCg0KIyMgUmVhZCBmaWxlcw0KZm9sZGVyIDwtICJDOi9Vc2Vycy9NaWhhaS9EZXNrdG9wL1IgTm90ZWJvb2tzL25vdGVib29rcy9QQTQtcmVwb3J0Ig0Kb2xkX2ZpbGUgPC0gIkRhdGVfcHRfYW5hbGl6YV9QQTRvbmxpbmUueGxzeCINCmZpbGUgPC0gIkRhdGVfcHRfYW5hbGl6YV9QQTRvbmxpbmUgLSBGaW5hbDIueGxzeCINCg0Kc2V0d2QoZm9sZGVyKQ0KDQojIElEIGRmDQppZF9kZiA8LSByaW86OmltcG9ydChmaWxlLnBhdGgoZm9sZGVyLCBmaWxlKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBza2lwID0gMSwgd2hpY2ggPSAiSUQtdXJpIGF0cmlidWl0ZSIpICAgDQppZF9kZiA8LSANCiAgaWRfZGYgJT4lDQogIGRwbHlyOjptdXRhdGUoSUQgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoSUQsIGZpeGVkKCIgIiksICIiKSkgICAgICMgcmVtb3ZlIHdoaXRlIHNwYWNlcw0KYWxsKGlkX2RmJElEID09IHRvdXBwZXIoaWRfZGYkSUQpKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGNoZWNrIGlmIGFsbCBhcmUgdXBwZXIgY2FzZQ0KaWRfZGZbLCAiZS1tYWlsIl0gPC0gdG9sb3dlcihpZF9kZlssICJlLW1haWwiXSkNCmlkX2RmIDwtIGlkX2RmWyFkdXBsaWNhdGVkKGlkX2RmKSxdICAgICAgICAgICAgICAgICAgICMgMzYgZHVwbGljYXRlZCwgMTE1IHVuaXF1ZQ0KDQpmaXJzdGZvcm1fZGYgPC0gcmlvOjppbXBvcnQoZmlsZS5wYXRoKGZvbGRlciwgZmlsZSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2tpcCA9IDAsIHdoaWNoID0gIkZvcm11bGFyIGRlIMOubnNjcmllcmUgyJlpIGNvbnNpbSIpDQpmaXJzdGZvcm1fZGYgPC0gZmlyc3Rmb3JtX2RmWywgLWxlbmd0aChmaXJzdGZvcm1fZGYpXSAgICAgICAgICAgICAgICAgICMgYSBjb2x1bW4gIndvcmsiIHdhcyBhZGRlZCB0byB0aGUgZW5kIA0Kb2xkX2ZpbGVfZmlyc3Rmb3JtX2RmIDwtIHJpbzo6aW1wb3J0KGZpbGUucGF0aChmb2xkZXIsIG9sZF9maWxlKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBza2lwID0gMCwgd2hpY2ggPSAiRm9ybXVsYXIgZGUgw65uc2NyaWVyZSDImWkgY29uc2ltIikgDQppZihhbGwuZXF1YWwoY29sbmFtZXMoZmlyc3Rmb3JtX2RmKSwgY29sbmFtZXMob2xkX2ZpbGVfZmlyc3Rmb3JtX2RmKSkpIHtybShvbGRfZmlsZV9maXJzdGZvcm1fZGYpfQ0KDQoNCmNvbG5hbWVzKGZpcnN0Zm9ybV9kZilbN10gPC0gImUtbWFpbCINCmZpcnN0Zm9ybV9kZlssICJlLW1haWwiXSA8LSB0b2xvd2VyKGZpcnN0Zm9ybV9kZlssICJlLW1haWwiXSkNCg0KYmFzZWxpbmVfZGYgPC0gZHBseXI6OmxlZnRfam9pbihpZF9kZiwgZmlyc3Rmb3JtX2RmLCBieSA9ICJlLW1haWwiKQ0KYmFzZWxpbmVfZGYgPC0gDQogIGJhc2VsaW5lX2RmICU+JQ0KICBkcGx5cjo6c2VsZWN0KGNvbG5hbWVzKGZpcnN0Zm9ybV9kZiksIGV2ZXJ5dGhpbmcoKSkgICAgICMgbW92ZSBjb2xzIGZyb20gaWRfZGYgdG8gYmFjayBzbyB3ZSBoYXZlIG1hdGNoaW5nIGNvbHMgaW5kZXggZm9yIGJhc2VsaW5lX2RmICYgZmlyc3Rmb3JtX2RmDQphbGwuZXF1YWwoY29sbmFtZXMoYmFzZWxpbmVfZGYpWzE6MTcyXSwgY29sbmFtZXMoZmlyc3Rmb3JtX2RmKVsxOjE3Ml0pICAgICAgICAgICAgICMgY2hlY2sgaWYgY29sbmFtZXMgbWF0Y2gsIGV4Y2VwdCBJRCBhbmQgbmFtZSB0aGF0IHdoZXJlIGFkZGVkDQoNCnRhYmxlKGJhc2VsaW5lX2RmJElEKSAjIHNvbWUgSURzIGFyZSBkb3VibGVkDQpgYGANCg0KDQpgYGB7ciBkYXNkfQ0KIyMgU2V0dGluZ3MNCmN1dG9mZlBDTCA8LSAzMiAgICMgbGl0ZXJhdHVyZTogMzEtMzMgb3IgMzggDQphbGdQQ0wgPC0gZGF0YS5mcmFtZShCID0gMSwgQyA9IDEsIEQgPSAyLCBFID0gMikNCmFsZ1BDTF9zdWJjbGluIDwtIGRhdGEuZnJhbWUoQiA9IDEsIEMgPSAxLCBEID0gMSwgRSA9IDEpDQoNCmN1dG9mZk1CSV9FeCA8LSAyLjIwICANCmN1dG9mZk1CSV9DeSA8LSAyDQojIw0KDQojIyBEYXRhDQpEYXRhIDwtIGJhc2VsaW5lX2RmDQojIw0KDQojIERlZmluZSBjb2x1bW4gaW5kZXg6ICBpbmRleCA9IGNvbCBpbmRleDsgaXRlbWluZGV4ID0gaW5kZXggb2YgaXRlbSBpbiBxdWVzdGlvbm5haXJlDQppbmRleFNJRyA8LSA2MDo2NyAtIDEwICAgICMgbW9kaWZpZWQgaW4gbmV3IHRhYmxlIGJ5IDEwDQppbmRleE1CSSA8LSA2ODo4MyAtIDEwDQppbmRleFBDTCA8LSAxNTk6MTc4IC0gMTANCml0ZW1pbmRleE1CSV9FeCA8LSBjKDEsIDMsIDUsIDExLCAxNCkNCml0ZW1pbmRleE1CSV9DeSA8LSBjKDIsIDcsIDgsIDEzLCAxNSkNCml0ZW1pbmRleE1CSV9QZSA8LSBjKDQsIDYsIDksIDEwLCAxMiwgMTYpDQoNCiMgUmVuYW1lIGNvbHVtbnMNCiMgbmFtZXMoRGF0YSlbMToxMl0gPC0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKG5hbWVzKERhdGEpWzE6MTJdLCAiW1s6Ymxhbms6XV0iLCAiXyIpDQojIG5hbWVzKERhdGEpWzE3XSA8LSAiUmVhbF9FbWFpbCINCiMgbmFtZXMoRGF0YSlbMThdIDwtICJSZWFsX1RlbCINCiMgbmFtZXMoRGF0YSlbMTldIDwtICJSZWFsX05hbWUiDQojIG5hbWVzKERhdGEpWzUwXSA8LSAiUmVhbF9BZ2VfY2F0ZWciDQoNCm5hbWVzKERhdGEpWzldIDwtICJudW1lIg0KbmFtZXMoRGF0YSlbNDBdIDwtICJBZ2VfY2F0ZWciDQpuYW1lcyhEYXRhKVs0MV0gPC0gIlNleCINCg0KbmFtZXMoRGF0YSlbbmFtZXMoRGF0YSkgJWluJSBuYW1lcyhEYXRhWywgaW5kZXhTSUddKV0gIDwtIGMoc3ByaW50ZigiU0lHXyUwMWQiLCBzZXEoMSwgOCkpKQ0KbmFtZXMoRGF0YSlbbmFtZXMoRGF0YSkgJWluJSBuYW1lcyhEYXRhWywgaW5kZXhNQkldKV0gIDwtIGMoc3ByaW50ZigiTUJJXyUwMWQiLCBzZXEoMSwgMTYpKSkNCm5hbWVzKERhdGEpW25hbWVzKERhdGEpICVpbiUgbmFtZXMoRGF0YVssIGluZGV4UENMXSldICA8LSBjKHNwcmludGYoIlBDTF8lMDFkIiwgc2VxKDEsIDIwKSkpDQoNCg0KIyBEYXRhIDwtDQojICAgRGF0YSAlPiUNCiMgICBkcGx5cjo6ZmlsdGVyKFJlc3BvbnNlX1N0YXR1cyA9PSAiY29tcGxldGVkIikgICAgICAgICAgICAgICAgICAgICAgICAgICMgc2VsZWN0IG9ubHkgY29tcGxldGUgY2FzZXMNCiANCg0KIyBSZWNvZGUgDQojIyBEZWZpbmUgZnVuY3Rpb24gdGhhdCByZWNvZGVzIHRvIG51bWVyaWMsIGJ1dCB3YXRjaGVzIG91dCB0byBjb2VyY2lvbiB0byBub3QgaW50cm9kdWNlIE5Bcw0KY29sc3RvbnVtZXJpYyA8LSBmdW5jdGlvbihkZil7DQogIHRyeUNhdGNoKHsNCiAgICBkZl9udW0gPC0gYXMuZGF0YS5mcmFtZSgNCiAgICAgIGxhcHBseShkZiwNCiAgICAgICAgICAgICBmdW5jdGlvbih4KSB7IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHgpKX0pKSANCiAgfSx3YXJuaW5nID0gZnVuY3Rpb24oc3RvcF9vbl93YXJuaW5nKSB7DQogICAgbWVzc2FnZSgiU3RvcGVkIHRoZSBleGVjdXRpb24gb2YgbnVtZXJpYyBjb252ZXJzaW9uOiAiLCBjb25kaXRpb25NZXNzYWdlKHN0b3Bfb25fd2FybmluZykpDQogIH0pIA0KfQ0KIyMNCiMjIERlZmluZSBmdW5jdGlvbiB0aGF0IHJldmVyc2UgY29kZXMgaXRlbXMNClJldmVyc2VDb2RlIDwtIGZ1bmN0aW9uKGRmLCB0b251bWVyaWMgPSBGQUxTRSwgbWluID0gTlVMTCwgbWF4ID0gTlVMTCkgew0KICBpZih0b251bWVyaWMpIGRmIDwtIGNvbHN0b251bWVyaWMoZGYpDQogIGRmIDwtIChtYXggKyBtaW4pIC0gZGYNCn0NCiMjDQoNCiMgbGFwcGx5KERhdGFbLGluZGV4UENMXSwgdW5pcXVlKQ0KRGF0YVsgLGluZGV4UENMXVsgRGF0YVsgLGluZGV4UENMXSA9PSAiZGVsb2MiXSA8LSAiMCINCkRhdGFbICxpbmRleFBDTF1bIERhdGFbICxpbmRleFBDTF0gPT0gInB1yJtpbiJdIDwtICIxIg0KRGF0YVsgLGluZGV4UENMXVsgRGF0YVsgLGluZGV4UENMXSA9PSAibW9kZXJhdCJdIDwtICIyIg0KRGF0YVsgLGluZGV4UENMXVsgRGF0YVsgLGluZGV4UENMXSA9PSAibXVsdCJdIDwtICIzIg0KRGF0YVsgLGluZGV4UENMXVsgRGF0YVsgLGluZGV4UENMXSA9PSAiZm9hcnRlIG11bHQiXSA8LSAiNCINCkRhdGFbICxpbmRleFBDTF1bIERhdGFbICxpbmRleFBDTF0gPT0gIk5vdCBBbnN3ZXJlZCJdIDwtIE5BDQoNCkRhdGFbICxpbmRleFNJR11bIERhdGFbICxpbmRleFNJR10gPT0gIk5VIl0gPC0gIjAiDQpEYXRhWyAsaW5kZXhTSUddWyBEYXRhWyAsaW5kZXhTSUddID09ICI/Il0gPC0gIjEuNSINCkRhdGFbICxpbmRleFNJR11bIERhdGFbICxpbmRleFNJR10gPT0gIkRBIl0gPC0gIjMiDQpEYXRhWyAsaW5kZXhTSUddWyBEYXRhWyAsaW5kZXhTSUddID09ICJOb3QgQW5zd2VyZWQiXSA8LSBOQQ0KDQpEYXRhWyAsaW5kZXhNQkldIDwtIGRhdGEuZnJhbWUobGFwcGx5KERhdGFbICxpbmRleE1CSV0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KSB7Z3N1YigiLipOaWNpb2RhdC4qIiwgIjAiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpEYXRhWyAsaW5kZXhNQkldIDwtIGRhdGEuZnJhbWUobGFwcGx5KERhdGFbICxpbmRleE1CSV0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KSB7Z3N1YigiLipaaWxuaWMuKiIsICI2IiwgeCl9KSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KRGF0YVsgLGluZGV4TUJJXVsgRGF0YVsgLGluZGV4TUJJXSA9PSAiTm90IEFuc3dlcmVkIl0gPC0gTkENCg0KDQpEYXRhWywgaW5kZXhTSUddIDwtIGNvbHN0b251bWVyaWMoRGF0YVssIGluZGV4U0lHXSkNCkRhdGFbLCBpbmRleE1CSV0gPC0gY29sc3RvbnVtZXJpYyhEYXRhWywgaW5kZXhNQkldKQ0KRGF0YVssIGluZGV4UENMXSA8LSBjb2xzdG9udW1lcmljKERhdGFbLCBpbmRleFBDTF0pDQoNCg0KDQojIFNjb3Jlcw0KIyMgRGVmaW5lIGZ1bmN0aW9uIHRoYXQgc2NvcmVzIG9ubHkgcm93cyB3aXRoIGxlc3MgdGhhbiAxMCUgTkFzIChyZXR1cm5zIE5BIGlmIGFsbCBvciBhYm92ZSB0aHJlc2hvbGQgcGVyY2VudGFnZSBvZiByb3dzIGFyZSBOQSk7IGNhbiByZXZlcnNlIGNvZGUgaWYgdmVjdG9yIG9mIGNvbHVtbiBpbmRleGVzIGFuZCBtaW4sIG1heCBhcmUgcHJvdmlkZWQuDQpTY29yZUxpa2VydCA8LSBmdW5jdGlvbihkZiwgc3RhdCA9ICJzdW0iLCBuYXRvemVybyA9IEZBTFNFLCBuYXBlcmNlbnQgPSAuMSwgdG9udW1lcmljID0gRkFMU0UsIHJldmVyc2Vjb2xzID0gTlVMTCwgbWluID0gTlVMTCwgbWF4ID0gTlVMTCkgew0KICByZXZlcnNlX2xpc3QgPC0gbGlzdChyZXZlcnNlY29scyA9IHJldmVyc2Vjb2xzLCBtaW4gPSBtaW4sIG1heCA9IG1heCkNCiAgcmV2ZXJzZV9jaGVjayA8LSAhc2FwcGx5KHJldmVyc2VfbGlzdCwgaXMubnVsbCkNCiAgDQogICMgUmVjb2RlIHRvIG51bWVyaWMsIGJ1dCB3YXRjaCBvdXQgdG8gY29lcmNpb24gdG8gbm90IGludHJvZHVjZSBOQXMNCiAgY29sc3RvbnVtZXJpYyA8LSBmdW5jdGlvbihkZil7DQogICAgdHJ5Q2F0Y2goew0KICAgICAgZGZfbnVtIDwtIGFzLmRhdGEuZnJhbWUoDQogICAgICAgIGxhcHBseShkZiwNCiAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHsgYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoeCkpfSkpIA0KICAgIH0sd2FybmluZyA9IGZ1bmN0aW9uKHN0b3Bfb25fd2FybmluZykgew0KICAgICAgbWVzc2FnZSgiU3RvcGVkIHRoZSBleGVjdXRpb24gb2YgbnVtZXJpYyBjb252ZXJzaW9uOiAiLCBjb25kaXRpb25NZXNzYWdlKHN0b3Bfb25fd2FybmluZykpDQogICAgfSkgDQogIH0NCiAgDQogIGlmKHRvbnVtZXJpYykgZGYgPC0gY29sc3RvbnVtZXJpYyhkZikNCiAgDQogIGlmKGFsbChyZXZlcnNlX2NoZWNrKSl7DQogICAgZGZbICxyZXZlcnNlY29sc10gPC0gKG1heCArIG1pbikgLSBkZlsgLHJldmVyc2Vjb2xzXQ0KICB9ZWxzZSBpZihhbnkocmV2ZXJzZV9jaGVjaykpew0KICAgIHN0b3AoIkluc3VmaWNpZW50IGluZm8gZm9yIHJldmVyc2luZy4gUGxlYXNlIHByb3ZpZGU6ICIsIHBhc3RlKG5hbWVzKHJldmVyc2VfbGlzdClbIXJldmVyc2VfY2hlY2tdLCBjb2xsYXBzZSA9ICIsICIpKQ0KICB9DQogIA0KICBpZih0b251bWVyaWMpIGRmIDwtIGNvbHN0b251bWVyaWMoZGYpICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogIA0KICBpZihuYXRvemVybykgZGZbaXMubmEoZGYpXSA8LSAwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBOQXMgdG8gMCBjYW4gaGVscCB3aGVuIHN0YXQgPSAibWVhbiIgd2l0aCBuYS5ybSA9IFQgYmVjYXVzZSBpdCBrZWVwcyBkZW5vbWluYXRvciBjb25zdGFudA0KICANCiAgaWYoc3RhdCA9PSAic3VtIil7DQogIGRmX3JlcyA8LSBpZmVsc2Uocm93U3Vtcyhpcy5uYShkZikpID4gbmNvbChkZikgKiBuYXBlcmNlbnQsDQogICAgICAgICAgICAgICAgICAgTkEsDQogICAgICAgICAgICAgICAgICAgcm93U3VtcyhkZiwgbmEucm0gPSBUUlVFKSAqIE5BIF4gKHJvd1N1bXMoIWlzLm5hKGRmKSkgPT0gMCkpDQogIH0NCiAgaWYoc3RhdCA9PSAibWVhbiIpew0KICAgIGRmX3JlcyA8LSBpZmVsc2Uocm93U3Vtcyhpcy5uYShkZikpID4gbmNvbChkZikgKiBuYXBlcmNlbnQsDQogICAgICAgICAgICAgICAgICAgICBOQSwNCiAgICAgICAgICAgICAgICAgICAgIHJvd01lYW5zKGRmLCBuYS5ybSA9IFRSVUUpICogTkEgXiAocm93U3VtcyghaXMubmEoZGYpKSA9PSAwKSkNCiAgfQ0KICByZXR1cm4oZGZfcmVzKQ0KfQ0KIyMNCg0KDQojIFNjb3JlIFBDTA0KRGF0YSRQQ0xfVG90YWwgPC0gU2NvcmVMaWtlcnQoRGF0YVssIGluZGV4UENMXSwgbmFwZXJjZW50ID0gLjMpICAgICAgICAgICAgICAgIyBOQSBpZiBOQSB0aHJlc2hvbGQgaXMgZXhjZWVkZWQgDQpEYXRhJFBDTF9CIDwtIFNjb3JlTGlrZXJ0KERhdGFbLCBjKHNwcmludGYoIlBDTF8lMDFkIiwgMTo1KSldLCBuYXBlcmNlbnQgPSAxKSAgICAjIGRvIG5vdGhpbmcgaWYgTkEgdGhyZXNob2xkIGlzIGV4Y2VlZGVkDQpEYXRhJFBDTF9DIDwtIFNjb3JlTGlrZXJ0KERhdGFbLCBjKHNwcmludGYoIlBDTF8lMDFkIiwgNjo3KSldLCBuYXBlcmNlbnQgPSAxKSANCkRhdGEkUENMX0QgPC0gU2NvcmVMaWtlcnQoRGF0YVssIGMoc3ByaW50ZigiUENMXyUwMWQiLCA4OjE0KSldLCBuYXBlcmNlbnQgPSAxKSAgDQpEYXRhJFBDTF9FIDwtIFNjb3JlTGlrZXJ0KERhdGFbLCBjKHNwcmludGYoIlBDTF8lMDFkIiwgMTU6MjApKV0sIG5hcGVyY2VudCA9IDEpDQoNCiMgU2NvcmUgU0lHDQpEYXRhJFNJR19Ub3RhbCA8LSBTY29yZUxpa2VydChEYXRhWywgaW5kZXhTSUddLCBuYXBlcmNlbnQgPSAuMykNCg0KIyBTY29yZSBNQkkNCkRhdGEkTUJJX1RvdGFsIDwtIFNjb3JlTGlrZXJ0KERhdGFbLCBpbmRleE1CSV0sIG5hcGVyY2VudCA9IC4zLCBzdGF0ID0gIm1lYW4iLCBuYXRvemVybyA9IFRSVUUpDQpEYXRhJE1CSV9FeCA8LSBTY29yZUxpa2VydChEYXRhWywgYyhzcHJpbnRmKCJNQklfJTAxZCIsIGl0ZW1pbmRleE1CSV9FeCkpXSwgbmFwZXJjZW50ID0gMSwgc3RhdCA9ICJtZWFuIiwgbmF0b3plcm8gPSBUUlVFKQ0KRGF0YSRNQklfQ3kgPC0gU2NvcmVMaWtlcnQoRGF0YVssIGMoc3ByaW50ZigiTUJJXyUwMWQiLCBpdGVtaW5kZXhNQklfQ3kpKV0sIG5hcGVyY2VudCA9IDEsIHN0YXQgPSAibWVhbiIsIG5hdG96ZXJvID0gVFJVRSkNCkRhdGEkTUJJX1BlIDwtIFNjb3JlTGlrZXJ0KERhdGFbLCBjKHNwcmludGYoIk1CSV8lMDFkIiwgaXRlbWluZGV4TUJJX1BlKSldLCBuYXBlcmNlbnQgPSAxLCBzdGF0ID0gIm1lYW4iLCBuYXRvemVybyA9IFRSVUUpDQoNCg0KIyBQQ0wgRGlhZ25vc3RpYyBBbGdvcml0aG0NCml0ZW1zUENMX0IgPC0gYyhzcHJpbnRmKCJQQ0xfJTAxZCIsIDE6NSkpDQppdGVtc1BDTF9DIDwtIGMoc3ByaW50ZigiUENMXyUwMWQiLCA2OjcpKQ0KaXRlbXNQQ0xfRCA8LSBjKHNwcmludGYoIlBDTF8lMDFkIiwgODoxNCkpDQppdGVtc1BDTF9FIDwtIGMoc3ByaW50ZigiUENMXyUwMWQiLCAxNToyMCkpDQoNCkRhdGFQQ0xBbGcgPC0gIA0KICBEYXRhICU+JSANCiAgZHBseXI6OnNlbGVjdCh0aWR5c2VsZWN0OjphbGxfb2YoaW5kZXhQQ0wpKSAlPiUgDQogIGRwbHlyOjptdXRhdGVfYWxsKA0KICAgIGZ1bnMoY2FzZV93aGVuKA0KICAgICAgLiA+PTIgfiAxLA0KICAgICAgIyAuIDwyIH4gMCwNCiAgICAgIGlzLm5hKC4pIH4gMCwNCiAgICAgIFRSVUUgIH4gIDApKSkgJT4lIA0KICANCiAgbXV0YXRlKFBDTF9Dcml0QiA9IGNhc2Vfd2hlbihyb3dTdW1zKC5bLGl0ZW1zUENMX0JdLCBuYS5ybSA9IFRSVUUpID49IGFsZ1BDTCRCIH4gMSwgICAgICAjIGFsZ1BDTCA8LSBkYXRhLmZyYW1lKEIgPSAxLCBDID0gMSwgRCA9IDIsIEUgPSAyKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcm93U3VtcyguWyxpdGVtc1BDTF9CXSwgbmEucm0gPSBUUlVFKSA8MSB+IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSAgfiAgMCkpICU+JSANCiAgbXV0YXRlKFBDTF9Dcml0QyA9IGNhc2Vfd2hlbihyb3dTdW1zKC5bLGl0ZW1zUENMX0NdLCBuYS5ybSA9IFRSVUUpID49IGFsZ1BDTCRDIH4gMSwgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyByb3dTdW1zKC5bLGl0ZW1zUENMX0NdLCBuYS5ybSA9IFRSVUUpIDwxIH4gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFICB+ICAwKSkgJT4lIA0KICBtdXRhdGUoUENMX0NyaXREID0gY2FzZV93aGVuKHJvd1N1bXMoLlssaXRlbXNQQ0xfRF0sIG5hLnJtID0gVFJVRSkgPj0gYWxnUENMJEQgfiAxLCAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcm93U3VtcyguWyxpdGVtc1BDTF9EXSwgbmEucm0gPSBUUlVFKSA8MSB+IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSAgfiAgMCkpICU+JSANCiAgbXV0YXRlKFBDTF9Dcml0RSA9IGNhc2Vfd2hlbihyb3dTdW1zKC5bLGl0ZW1zUENMX0VdLCBuYS5ybSA9IFRSVUUpID49IGFsZ1BDTCRFIH4gMSwgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyByb3dTdW1zKC5bLGl0ZW1zUENMX0VdLCBuYS5ybSA9IFRSVUUpIDwxIH4gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFICB+ICAwKSkgJT4lIA0KICBtdXRhdGUoUENMX0FsZyA9IGNhc2Vfd2hlbihQQ0xfQ3JpdEIgPT0gMSAmIFBDTF9Dcml0QyA9PSAxICYgUENMX0NyaXREID09IDEgJiBQQ0xfQ3JpdEUgPT0gMSB+IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgIH4gIDApKSANCg0KRGF0YSRQQ0xBbGcgPC0gRGF0YVBDTEFsZyRQQ0xfQWxnDQoNCkRhdGFQQ0xBbGdfc3ViY2xpbiA8LSAgDQogIERhdGEgJT4lIA0KICBkcGx5cjo6c2VsZWN0KHRpZHlzZWxlY3Q6OmFsbF9vZihpbmRleFBDTCkpICU+JSANCiAgZHBseXI6Om11dGF0ZV9hbGwoDQogICAgZnVucyhjYXNlX3doZW4oDQogICAgICAuID49MiB+IDEsDQogICAgICAjIC4gPDIgfiAwLA0KICAgICAgaXMubmEoLikgfiAwLA0KICAgICAgVFJVRSAgfiAgMCkpKSAlPiUgDQogIA0KICBtdXRhdGUoUENMX0NyaXRCID0gY2FzZV93aGVuKHJvd1N1bXMoLlssaXRlbXNQQ0xfQl0sIG5hLnJtID0gVFJVRSkgPj0gYWxnUENMX3N1YmNsaW4kQiB+IDEsICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJvd1N1bXMoLlssaXRlbXNQQ0xfQl0sIG5hLnJtID0gVFJVRSkgPDEgfiAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgIH4gIDApKSAlPiUgDQogIG11dGF0ZShQQ0xfQ3JpdEMgPSBjYXNlX3doZW4ocm93U3VtcyguWyxpdGVtc1BDTF9DXSwgbmEucm0gPSBUUlVFKSA+PSBhbGdQQ0xfc3ViY2xpbiRDIH4gMSwgICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyByb3dTdW1zKC5bLGl0ZW1zUENMX0NdLCBuYS5ybSA9IFRSVUUpIDwxIH4gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFICB+ICAwKSkgJT4lIA0KICBtdXRhdGUoUENMX0NyaXREID0gY2FzZV93aGVuKHJvd1N1bXMoLlssaXRlbXNQQ0xfRF0sIG5hLnJtID0gVFJVRSkgPj0gYWxnUENMX3N1YmNsaW4kRCB+IDEsICAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyByb3dTdW1zKC5bLGl0ZW1zUENMX0RdLCBuYS5ybSA9IFRSVUUpIDwxIH4gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFICB+ICAwKSkgJT4lIA0KICBtdXRhdGUoUENMX0NyaXRFID0gY2FzZV93aGVuKHJvd1N1bXMoLlssaXRlbXNQQ0xfRV0sIG5hLnJtID0gVFJVRSkgPj0gYWxnUENMX3N1YmNsaW4kRSB+IDEsICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcm93U3VtcyguWyxpdGVtc1BDTF9FXSwgbmEucm0gPSBUUlVFKSA8MSB+IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSAgfiAgMCkpICU+JSANCiAgbXV0YXRlKFBDTF9BbGdfc3ViY2xpbiA9IGNhc2Vfd2hlbihQQ0xfQ3JpdEIgPT0gMSAmIFBDTF9Dcml0QyA9PSAxICYgUENMX0NyaXREID09IDEgJiBQQ0xfQ3JpdEUgPT0gMSB+IDEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSAgfiAgMCkpIA0KDQpEYXRhJFBDTEFsZ19zdWJjbGluIDwtIERhdGFQQ0xBbGdfc3ViY2xpbiRQQ0xfQWxnX3N1YmNsaW4NCg0KRGF0YSRNQklfRXhfY3V0IDwtIGlmZWxzZShEYXRhJE1CSV9FeCA+PSBjdXRvZmZNQklfRXgsIDEsIDApDQpEYXRhJE1CSV9DeV9jdXQgPC0gaWZlbHNlKERhdGEkTUJJX0N5ID49IGN1dG9mZk1CSV9DeSwgMSwgMCkNCg0KDQojIEdsb2JhbCBTY3JlZW5pbmcgJiBHcm91cHMNCmRmX3NjcmVlbmluZyA8LSBEYXRhWyxjKCJJRCIsICJudW1lIiwgImUtbWFpbCIsICJBZ2VfY2F0ZWciLCAiU2V4IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICJTSUdfVG90YWwiLCAiTUJJX0V4IiwgIk1CSV9DeSIsICJNQklfRXhfY3V0IiwgIk1CSV9DeV9jdXQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIlBDTF9Ub3RhbCIsICJQQ0xfQiIsICJQQ0xfQyIsICJQQ0xfRCIsICJQQ0xfRSIsICJQQ0xBbGciLCAiUENMQWxnX3N1YmNsaW4iKV0NCg0KDQoNCiMgQ2hlY2sgc2FtZSByZXN1bHQgd2l0aCBzY3JlZW5pbmcgZG9uZSBvbiBHb29nbGUgQ29sYWIgDQojIGNoZWNrX2cgPC0gcmlvOjppbXBvcnQoZmlsZS5wYXRoKGZvbGRlciwgImNoZWNrX3NjcmVlbmluZyIsICJQQTRfU2NyZWVuaW5nIDIwMjEtMDEtMTggMThfMDNfNDBDSEVDSy54bHN4IikpIA0KIyBjaGVja19sIDwtIGRmX3NjcmVlbmluZw0KIyANCiMgY2hlY2tfbWVyZ2UgPC0gZnVsbF9qb2luKGNoZWNrX2wsIGNoZWNrX2csIGJ5ID0gYygiZS1tYWlsIiA9ICJSZWFsX0VtYWlsIikpDQojIA0KIyBuYW1lc19sIDwtIHBhc3RlMChjKCJTSUdfVG90YWwiLCAiTUJJX0V4X2N1dCIsICJNQklfQ3lfY3V0IiwgIlBDTF9Ub3RhbCIsICJQQ0xfQiIsICJQQ0xfQyIsICJQQ0xfRCIsICJQQ0xfRSIsICJQQ0xBbGciLCAiUENMQWxnX3N1YmNsaW4iKSwgIi54IikNCiMgbmFtZXNfZyA8LSBwYXN0ZTAoYygiU0lHX1RvdGFsIiwgIk1CSV9FeF9jdXQiLCAiTUJJX0N5X2N1dCIsICJQQ0xfVG90YWwiLCAiUENMX0IiLCAiUENMX0MiLCAiUENMX0QiLCAiUENMX0UiLCAiUENMQWxnIiwgIlBDTEFsZ19zdWJjbGluIiksICIueSIpDQojIA0KIyBhbGwuZXF1YWwoY2hlY2tfbWVyZ2VbLCBuYW1lc19sXSwgY2hlY2tfbWVyZ2VbLCBuYW1lc19sXSkNCiMjIyMjIyMjIyMjIw0KDQpgYGANCg0KDQpgYGB7ciBjbGVhbl9jb3JyZWN0aW5nX2lkc30NCmRmX3NjcmVlbmluZyA8LSANCiAgZGZfc2NyZWVuaW5nICU+JQ0KICBkcGx5cjo6bmFfaWYoIk5vdCBBbnN3ZXJlZCIpICAgICMgc29tZSBtb3JlIE5Bcw0KDQpkZl9zY3JlZW5pbmcgPC0gDQogIGRmX3NjcmVlbmluZyAlPiUNCiAgZHBseXI6OmZpbHRlcighc3RyaW5ncjo6c3RyX2RldGVjdChJRCwgIlBBNE9YVCIpKSAgICMgZXhjbHVkZSB0aGVzZQ0KDQojIElEICI4QSIgbmVlZHMgdG8gYmUgbmFtZSAiUyBBIiwgQWdlX2NhdGVnICJwZXN0ZSA2NSBhbmkiDQojIElEICIyNlgiIG5lZWRzIHRvIGJlIG5hbWUgImJvbGRhc3UgbGlsaWFuYSIsIEFnZV9jYXRlZyAiNDEtNjUgYW5pIiAgICANCmRmX3NjcmVlbmluZyA8LSANCiAgZGZfc2NyZWVuaW5nICU+JQ0KICBkcGx5cjo6ZmlsdGVyKCEoSUQgPT0gIjhBIiAmIEFnZV9jYXRlZyA9PSAiNDEtNjUgYW5pIikpICU+JSANCiAgZHBseXI6OmZpbHRlcighKElEID09ICIyNlgiICYgQWdlX2NhdGVnID09ICJwZXN0ZSA2NSBhbmkiKSkgDQoNCg0KIyBkdXBsaWNhdGVkDQpkZl9zY3JlZW5pbmckSURbZHVwbGljYXRlZChkZl9zY3JlZW5pbmckSUQpXSAgICAgICAgICAgICAjIGR1cGxpY2F0ZWQgSURzOiAiNkEiICI5QyINCmRmX3NjcmVlbmluZyA8LSANCiAgZGZfc2NyZWVuaW5nICU+JQ0KICBkcGx5cjo6ZmlsdGVyKCEoSUQgPT0gIjZBIiAmIGlzLm5hKEFnZV9jYXRlZykpKSAlPiUgDQogIGRwbHlyOjpmaWx0ZXIoIShJRCA9PSAiOUMiICYgaXMubmEoQWdlX2NhdGVnKSkpIA0KYGBgDQoNCg0KYGBge3IgZXh0cmFjdF9pZHN9DQoNCiMjIyMjDQpvdmVsYXBfdG9fcHRzZCA8LSBjKCI2WCIsICIxOVgiLCAiMTFSIiwgIjEwQyIsICIxNEMiLCAiM0QiKQ0Kb3ZlbGFwX3RvX2J1cm4gPC0gYygiOVgiLCAiMTJYIiwgIjhSIiwgIjEyQiIsICIxM0IiLCAiNUMiLCAiMTdSIikNCiANCiAgDQppZHNfcHRzZCA8LQ0KICBkZl9zY3JlZW5pbmcgJT4lDQogICAgZHBseXI6OmZpbHRlcihQQ0xBbGcgPT0gMSkgJT4lDQogICAgZHBseXI6OnNlbGVjdChJRCkgJT4lDQogICAgZHBseXI6OmZpbHRlcighKElEICVpbiUgb3ZlbGFwX3RvX2J1cm4pKSAlPiUNCiAgICBkcGx5cjo6cHVsbCgpDQoNCmlkc19idXJuIDwtDQogIGRmX3NjcmVlbmluZyAlPiUNCiAgICBkcGx5cjo6ZmlsdGVyKE1CSV9FeF9jdXQgPT0gMSwgTUJJX0N5X2N1dCA9PSAxKSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KElEKSAlPiUNCiAgICBkcGx5cjo6ZmlsdGVyKCEoSUQgJWluJSBvdmVsYXBfdG9fcHRzZCkpICU+JQ0KICAgIGRwbHlyOjpwdWxsKCkNCg0KaWRzX29sZCA8LQ0KICBkZl9zY3JlZW5pbmcgJT4lDQogICAgZHBseXI6OmZpbHRlcihBZ2VfY2F0ZWcgPT0gInBlc3RlIDY1IGFuaSIpICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoSUQpICU+JQ0KICAgIGRwbHlyOjpwdWxsKCkNCg0KaWRzX25vcm1hbCA8LQ0KICAgZGZfc2NyZWVuaW5nICU+JQ0KICAgIGRwbHlyOjpmaWx0ZXIoIShJRCAlaW4lIGMoaWRzX3B0c2QsIGlkc19idXJuLCBpZHNfb2xkKSkpICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QoSUQpICU+JQ0KICAgIGRwbHlyOjpwdWxsKCkNCg0KDQojIENIRUNLUw0KbGVuZ3RoKHVuaXF1ZShpZHNfcHRzZCkpOyBsZW5ndGgodW5pcXVlKGlkc19wdHNkKSkgPT0gbGVuZ3RoKGlkc19wdHNkKSAgICAgICAgICAgICAgIyBubyBkdXBsaWNhdGUgSURzDQpsZW5ndGgodW5pcXVlKGlkc19idXJuKSk7IGxlbmd0aCh1bmlxdWUoaWRzX2J1cm4pKSA9PSBsZW5ndGgoaWRzX2J1cm4pICAgICAgICAgICAgICAjIG5vIGR1cGxpY2F0ZSBJRHMNCmxlbmd0aCh1bmlxdWUoaWRzX29sZCkpOyBsZW5ndGgodW5pcXVlKGlkc19vbGQpKSA9PSBsZW5ndGgoaWRzX29sZCkgICAgICAgICAgICAgICAgICMgbm8gZHVwbGljYXRlIElEcw0KbGVuZ3RoKHVuaXF1ZShpZHNfbm9ybWFsKSk7IGxlbmd0aCh1bmlxdWUoaWRzX25vcm1hbCkpID09IGxlbmd0aChpZHNfbm9ybWFsKSAgICAgICAgIyBubyBkdXBsaWNhdGUgSURzDQoNCmludGVyc2VjdCh1bmlxdWUoaWRzX3B0c2QpLCB1bmlxdWUoaWRzX2J1cm4pKSAgICMgYmVmb3JlOiAxMyBjb21tb24gLS0gbm93OiAwIA0KbGVuZ3RoKHVuaXF1ZShjKGlkc19wdHNkLCBpZHNfYnVybikpKSAgICAgICMgNDcgdG90YWwNCnNldGRpZmYoaWRzX3B0c2QsIGlkc19idXJuKSAgICAgICAgICAjIGJlZm9yZTogb25seSBwdHNkICAgMTYgLS0gbm93OiAyMg0Kc2V0ZGlmZihpZHNfYnVybiwgaWRzX3B0c2QpICAgICAgICAgICMgYmVmb3JlOiBvbmx5IGJ1cm4gICAxOCAtLSBub3c6IDI1DQppbnRlcnNlY3QoaWRzX3B0c2QsIGlkc19vbGQpICAgICMgbm8gb2xkIHdpdGggUFRTRA0KaW50ZXJzZWN0KGlkc19wdHNkLCBpZHNfb2xkKSAgICAjIG5vIG9sZCB3aXRoIEJ1cm4gT3V0DQpsZW5ndGgodW5pcXVlKGMoaWRzX3B0c2QsIGlkc19idXJuLCBpZHNfb2xkLCBpZHNfbm9ybWFsKSkpID09IDEwNiAgIyBhbGwgZ29vZCANCg0KDQoNCiMjIyMNCnNjcmVlbmluZ19pZHNfZ3JvdXBzIDwtIGxpc3QoDQogIHB0c2QgPSBpZHNfcHRzZCwNCiAgYnVybiA9IGlkc19idXJuLA0KICBwdHNkX29yX2J1cm4gPSBpbnRlcnNlY3QodW5pcXVlKGlkc19wdHNkKSwgdW5pcXVlKGlkc19idXJuKSksDQogIG9sZCA9IGlkc19vbGQsDQogIG5vcm1hbCA9IGlkc19ub3JtYWwNCikNCg0KDQojIGlkc19ncm91cHNfZGY8LSANCiMgICBEYXRhICU+JQ0KIyAgIGRwbHlyOjpzZWxlY3QoMTczLCAxNzU6MTg4KQ0KYGBgDQoNCg0KYGBge3IgaXpvbGF0aX0NCiMgY29sbmFtZXMoRGF0YSlbMjZdIDwtICJTb2NfRGlzY29uZiINCiMgDQojIERhdGEgJT4lDQojICAgZHBseXI6OmZpbHRlcihJRCAlaW4lIGlkc19ub3JtYWwpICU+JQ0KIyAgIGRwbHlyOjpzZWxlY3QoU29jX0Rpc2NvbmYpICU+JSANCiMgICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLCB+ZHBseXI6Om5hX2lmKC4sICJOb3QgQW5zd2VyZWQiKSkgJT4lDQojICAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgYXMubG9naWNhbCkgJT4lDQojICAgZHBseXI6OnB1bGwoKSAlPiUgc3VtKC4sIG5hLnJtID0gVFJVRSkNCg0KIyBpem9sYXRpaSBhciBmaTogY2VpIDkgYmF0cmFuaSBzaSAxNiBub3JtYWxpDQogIA0KYGBgDQoNCiMgT3V0Y29tZSBNZWFzdXJlcw0KDQojIERpY3RhdG9yIEdhbWUNCg0KYGBge3IgZGdfc2NvcmluZywgcmVzdWx0cz0naGlkZSd9DQojIERHIGRmDQpkZ19kZl9wcmUgPC0gcmlvOjppbXBvcnQoZmlsZS5wYXRoKGZvbGRlciwgZmlsZSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNraXAgPSAwLCB3aGljaCA9ICJEaWN0YXRvckdhbWUgcHJlIikNCmRnX2RmX3ByZSA8LSANCiAgZGdfZGZfcHJlICU+JQ0KICBqYW5pdG9yOjpyZW1vdmVfZW1wdHkoInJvd3MiKSANCiAgDQpjb2xuYW1lcyhkZ19kZl9wcmUpWzRdIDwtICJJRCINCmRnX2RmX3ByZSA8LSANCiAgZGdfZGZfcHJlICU+JQ0KICBkcGx5cjo6bXV0YXRlKElEID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKElELCBmaXhlZCgiICIpLCAiIikpICU+JSAgICAjIHJlbW92ZSB3aGl0ZSBzcGFjZXMNCiAgZHBseXI6Om11dGF0ZShJRCA9IHRvdXBwZXIoSUQpKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0byB1cHBlcg0KYWxsKGRnX2RmX3ByZSRJRCA9PSB0b3VwcGVyKGRnX2RmX3ByZSRJRCkpIA0KDQpkZ19kZl9wb3N0IDwtIHJpbzo6aW1wb3J0KGZpbGUucGF0aChmb2xkZXIsIGZpbGUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBza2lwID0gMCwgd2hpY2ggPSAiRGljdGF0b3JHYW1lIHBvc3QiKQ0KZGdfZGZfcG9zdCA8LSANCiAgZGdfZGZfcG9zdCAlPiUNCiAgamFuaXRvcjo6cmVtb3ZlX2VtcHR5KCJyb3dzIikNCg0KY29sbmFtZXMoZGdfZGZfcG9zdClbNF0gPC0gIklEIg0KZGdfZGZfcG9zdCA8LSANCiAgZGdfZGZfcG9zdCAlPiUNCiAgZHBseXI6Om11dGF0ZShJRCA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbChJRCwgZml4ZWQoIiAiKSwgIiIpKSAlPiUgICAgIyByZW1vdmUgd2hpdGUgc3BhY2VzDQogIGRwbHlyOjptdXRhdGUoSUQgPSB0b3VwcGVyKElEKSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdG8gdXBwZXINCmFsbChkZ19kZl9wb3N0JElEID09IHRvdXBwZXIoZGdfZGZfcG9zdCRJRCkpIA0KDQpjb2xuYW1lcyhkZ19kZl9wcmUpWzU6OF0gPC0gc3ByaW50ZigiREdfJWQiLCAxOjQpDQpjb2xuYW1lcyhkZ19kZl9wcmUpWzJdIDwtICJSZXNwb25zZV9TdGF0dXMiDQpjb2xuYW1lcyhkZ19kZl9wb3N0KVs1OjhdIDwtIHNwcmludGYoIkRHXyVkIiwgMTo0KQ0KY29sbmFtZXMoZGdfZGZfcG9zdClbM10gPC0gIlJlc3BvbnNlX1N0YXR1cyINCg0KZGdfZGZfcHJlIDwtDQogIGRnX2RmX3ByZSAlPiUNCiAgZHBseXI6Om11dGF0ZShgRGF0ZSBNb2RpZmllZGAgPSBsdWJyaWRhdGU6OnltZF9obXMoZm9ybWF0KGBEYXRlIE1vZGlmaWVkYCwgIiVZLSVtLSVkICVIOiVNOiVTIiwgdHogPSAiVVRDIikpKSAlPiUNCiAgbXV0YXRlX2lmKGlzLmNoYXJhY3Rlciwgfm5hX2lmKC4sICJOb3QgQW5zd2VyZWQiKSkgJT4lDQogIGRwbHlyOjpmaWx0ZXIoUmVzcG9uc2VfU3RhdHVzID09ICJjb21wbGV0ZWQiKSAlPiUNCiAgZHBseXI6OmZpbHRlcighc3RyaW5ncjo6c3RyX2RldGVjdChJRCwgIlBBNE9YVCIpKSAlPiUNCiAgZHBseXI6OmZpbHRlcighc3RyaW5ncjo6c3RyX2RldGVjdChJRCwgIlBBNFJNTiIpKQ0KDQpkZ19kZl9wb3N0IDwtDQogIGRnX2RmX3Bvc3QgJT4lDQogIGRwbHlyOjptdXRhdGUoYERhdGUgTW9kaWZpZWRgID0gbHVicmlkYXRlOjp5bWRfaG1zKGZvcm1hdChgRGF0ZSBNb2RpZmllZGAsICIlWS0lbS0lZCAlSDolTTolUyIsIHR6ID0gIlVUQyIpKSkgJT4lDQogIG11dGF0ZV9pZihpcy5jaGFyYWN0ZXIsIH5kcGx5cjo6bmFfaWYoLiwgIk5vdCBBbnN3ZXJlZCIpKSAlPiUNCiAgZHBseXI6OmZpbHRlcihSZXNwb25zZV9TdGF0dXMgPT0gImNvbXBsZXRlZCIpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKCFzdHJpbmdyOjpzdHJfZGV0ZWN0KElELCAiUEE0T1hUIikpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKCFzdHJpbmdyOjpzdHJfZGV0ZWN0KElELCAiUEE0Uk1OIikpDQoNCmRnX2RmX3ByZSA8LQ0KICBkZ19kZl9wcmUgJT4lDQogIGRwbHlyOjptdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiREdfIikpLCB+c3RyaW5ncjo6c3RyX2V4dHJhY3QoLiwgIlswLTldKyIpKSAlPiUgICAjIGV4dHJhY3RzIGZpcnN0IG51bWJlciAoYWxsIGdhbWVzIHN0YXJ0IHdpdGggUGxheWVyIEEsIHNvIGFsd2F5cyBmaXJzdCBudW1iZXIpDQogIGRwbHlyOjptdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiREdfIikpLCBhcy5udW1lcmljKSAlPiUNCiAgZHBseXI6Om11dGF0ZShUaW1lID0gcmVwKCJQcmUiLCBucm93KC4pKSkgJT4lDQogIGRwbHlyOjptdXRhdGUoQ29uZCA9IGlmZWxzZShzdHJpbmdyOjpzdHJfZGV0ZWN0KElELCAiWCIpLCAiQ1RSTCIsICJUUiIpKSAlPiUNCiAgc2VsZWN0KGBEYXRlIE1vZGlmaWVkYCwgSUQsIHN0YXJ0c193aXRoKCJER18iKSwgVGltZSwgQ29uZCkNCg0KZGdfZGZfcG9zdCA8LQ0KICBkZ19kZl9wb3N0ICU+JQ0KICBkcGx5cjo6bXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkRHXyIpKSwgfnN0cmluZ3I6OnN0cl9leHRyYWN0KC4sICJbMC05XSsiKSkgJT4lICAgIyBleHRyYWN0cyBmaXJzdCBudW1iZXIgKGFsbCBnYW1lcyBzdGFydCB3aXRoIFBsYXllciBBLCBzbyBhbHdheXMgZmlyc3QgbnVtYmVyKQ0KICBkcGx5cjo6bXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkRHXyIpKSwgYXMubnVtZXJpYykgJT4lDQogIGRwbHlyOjptdXRhdGUoVGltZSA9IHJlcCgiUG9zdCIsIG5yb3coLikpKSAlPiUNCiAgZHBseXI6Om11dGF0ZShDb25kID0gaWZlbHNlKHN0cmluZ3I6OnN0cl9kZXRlY3QoSUQsICJYIiksICJDVFJMIiwgIlRSIikpICU+JQ0KICBzZWxlY3QoYERhdGUgTW9kaWZpZWRgLCBJRCwgc3RhcnRzX3dpdGgoIkRHXyIpLCBUaW1lLCBDb25kKQ0KDQojIFRyYW5zZm9ybSBERyAwLTkwMCBlZ29pc20gdG8gMC05IGFsdHJ1aXNtDQpkZ190cmFuc19mdW5jIDwtIGZ1bmN0aW9uKHgpe3RyYW5zIDwtIDkgLSB4IC8gMTAwfQ0KDQpkZ19kZl9wcmUgPC0NCiAgZGdfZGZfcHJlICU+JQ0KICBkcGx5cjo6bXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkRHXyIpKSwgZGdfdHJhbnNfZnVuYykgDQoNCmRnX2RmX3Bvc3QgPC0NCiAgZGdfZGZfcG9zdCAlPiUNCiAgZHBseXI6Om11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJER18iKSksIGRnX3RyYW5zX2Z1bmMpIA0KDQojIFVuaXRlIERHIGRhdGEgLSBMb25nIEZvcm1hdA0KZGdfdW5pdGVkX2xvbmcgPC0gcmJpbmQoZGdfZGZfcHJlLCBkZ19kZl9wb3N0KQ0Kd2hpY2godGFibGUoZGdfdW5pdGVkX2xvbmckSUQpPiAyICkgICAgICMgSURzICIzQiIgJiAiMzFYIiBoYXZlIG1vcmUgdGhhbiAyIHRyaWFscw0KZGdfdW5pdGVkX2xvbmdbZGdfdW5pdGVkX2xvbmckSUQgPT0gIjNCIixdICAjIHR3byBQcmVzIC0tIGtlZXAgdGhlIGZpcnN0DQpkZ191bml0ZWRfbG9uZyA8LSBkZ191bml0ZWRfbG9uZ1stNTUsIF0NCmRnX3VuaXRlZF9sb25nW2RnX3VuaXRlZF9sb25nJElEID09ICIzMVgiLF0gIyB0d28gUHJlcyAtLSBrZWVwIHRoZSBmaXJzdA0KZGdfdW5pdGVkX2xvbmcgPC0gZGdfdW5pdGVkX2xvbmdbLTczLCBdDQpkZ191bml0ZWRfbG9uZ1tkZ191bml0ZWRfbG9uZyRJRCA9PSAiNUUiLF0gIyB0d28gUHJlcyAtLSBrZWVwIHRoZSBmaXJzdA0KZGdfdW5pdGVkX2xvbmcgPC0gZGdfdW5pdGVkX2xvbmdbLTEwNiwgXQ0KDQpkZ191bml0ZWRfbG9uZyRER19Ub3RhbCA8LSByb3dTdW1zKGRnX3VuaXRlZF9sb25nWywgc3ByaW50ZigiREdfJWQiLCAxOjQpXSwgbmEucm0gPSBUUlVFKSANCg0KIyBVbml0ZSBERyBkYXRhIC0gV2lkZSBGb3JtYXQNCmRnX3VuaXRlZF93aWRlIDwtDQogIGRnX3VuaXRlZF9sb25nICU+JQ0KICB0aWR5cjo6cGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoSUQsIENvbmQpLCBuYW1lc19mcm9tID0gVGltZSwgdmFsdWVzX2Zyb20gPSBjKCJEYXRlIE1vZGlmaWVkIiwgc3ByaW50ZigiREdfJWQiLCAxOjQpLCAiREdfVG90YWwiKSkNCiMgZGdfdW5pdGVkX3dpZGUyIDwtIGRwbHlyOjpsZWZ0X2pvaW4oZGdfdW5pdGVkX3dpZGUsIGlkc19ncm91cHNfZGYsIGJ5ID0gIklEIikgICAgICMgbm8gbmVlZCB0byBtZXJnZSwgYWxyZWFkeSBoYXZlIGlkcyBmb3IgZ3JvdXBzIHN0b3JlZA0KDQpgYGANCg0KPCEtLQ0KYGBge3IgbWl4ZWRhbm92YV9kZ30NCmNhdCgiTWl4ZWQgQU5PVkEgLSBERyB3aG9sZSBzYW1wbGUgKG5vdCBieSBncm91cHMpIikNCiMgTWl4ZWQgQU5PVkENCmRnX3VuaXRlZF9sb25nICU+JQ0KICBncm91cF9ieShJRCkgJT4lDQogIGZpbHRlcihuKCkgPiAxKSAlPiUgICAgICMga2VlcCBvbmx5IGNvbXBsZXRlIGNhc2VzDQogIHVuZ3JvdXAoKSAlPiUgDQogIHR3X21peGVkQU5PVkFfZnVuYyhkYXRhID0gLiwgaWRfdmFyID0gSUQsIGNvbmRfdmFyID0gQ29uZCwgdGltZV92YXIgPSBUaW1lLCB2YWx1ZV92YXIgPSBER19Ub3RhbCwNCiAgICAgICAgICAgICAgICAgIHBvc3Rob2Nfc2lnX2ludGVyYWMgPSBUUlVFLCBwb3N0aG9jX25zX2ludGVyYWMgPSBUUlVFKQ0KYGBgDQotLT4NCg0KIyBUIHRlc3QgRGljYXRhdG9yIEdhbWUNCg0KYGBge3IgdHRlc3RfYnlncm91cF9kZ30NCiMgZHBseXI6OmZpbHRlcihJRCAlaW4lIGMoaWRzX3B0c2QsIGlkc19idXJuLCBpZHNfb2xkLCBpZHNfbm9ybWFsKSkgJT4lDQoNCmNhdCgiIyMgREcgLSBQVFNEIFRSIikNCmRnX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX3B0c2QpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIlRSIikgJT4lDQogIGZ1bmNfdF9ib3goLiwgaW5kID0gIklEIiwgcHJlX3ZhciA9ICJER19Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJER19Ub3RhbF9Qb3N0IikNCmNhdCgiIyMgREcgLSBQVFNEIENUUkwiKQ0KZGdfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfcHRzZCkgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiQ1RSTCIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiREdfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiREdfVG90YWxfUG9zdCIpDQoNCg0KY2F0KCIjIyBERyAtIEJ1cm5vdXQgVFIiKQ0KZGdfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfYnVybikgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiVFIiKSAlPiUNCiAgZnVuY190X2JveCguLCBpbmQgPSAiSUQiLCBwcmVfdmFyID0gIkRHX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIkRHX1RvdGFsX1Bvc3QiKQ0KY2F0KCIjIyBERyAtIEJ1cm5vdXQgQ1RSTCIpDQpkZ191bml0ZWRfd2lkZSAlPiUNCiAgZHBseXI6OmZpbHRlcihJRCAlaW4lIGlkc19idXJuKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJDVFJMIikgJT4lDQogIGZ1bmNfdF9ib3goLiwgaW5kID0gIklEIiwgcHJlX3ZhciA9ICJER19Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJER19Ub3RhbF9Qb3N0IikNCg0KDQpjYXQoIiMjIERHIC0gT2xkIFRSIikNCiMgZGdfdW5pdGVkX3dpZGUgJT4lDQojICAgZHBseXI6OmZpbHRlcihJRCAlaW4lIGlkc19vbGQpICU+JQ0KIyAgIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiVFIiKSAlPiUNCiMgICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiREdfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiREdfVG90YWxfUG9zdCIpDQpjYXQoIiMjIERHIC0gT2xkIENUUkwiKQ0KIyBkZ191bml0ZWRfd2lkZSAlPiUNCiMgICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX29sZCkgJT4lDQojICAgZHBseXI6OmZpbHRlcihDb25kID09ICJDVFJMIikgJT4lDQojICAgZnVuY190X2JveCguLCBpbmQgPSAiSUQiLCBwcmVfdmFyID0gIkRHX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIkRHX1RvdGFsX1Bvc3QiKQ0KDQpjYXQoIiMjIERHIC0gR2VuZXJhbCBQb3B1bGF0aW9uIFRSIikNCmRnX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX25vcm1hbCkgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiVFIiKSAlPiUNCiAgZnVuY190X2JveCguLCBpbmQgPSAiSUQiLCBwcmVfdmFyID0gIkRHX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIkRHX1RvdGFsX1Bvc3QiKQ0KY2F0KCIjIyBERyAtIEdlbmVyYWwgUG9wdWxhdGlvbiBDVFJMIikNCmRnX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX25vcm1hbCkgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiQ1RSTCIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiREdfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiREdfVG90YWxfUG9zdCIpDQpgYGANCg0KPCEtLQ0KIyMgREcgTm9ybWFsIFNhbXBsZSBTaXplIGVzdGltYXRpb24NCg0KYGBge3IgZGdfc2FtcGxlc2l6ZX0NCmNhdCgiIyMgREcgLSBHZW5lcmFsIFBvcHVsYXRpb24gVFIiKQ0KZGdfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfbm9ybWFsKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJUUiIpICU+JQ0KICBzYW1wbGVzaXplX3BhaXJlZHR0ZXN0KC4sIHByZV92YXIgPSAiREdfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiREdfVG90YWxfUG9zdCIpDQpjYXQoIiMjIERHIC0gR2VuZXJhbCBQb3B1bGF0aW9uIENUUkwiKQ0KZGdfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfbm9ybWFsKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJDVFJMIikgJT4lDQogIHNhbXBsZXNpemVfcGFpcmVkdHRlc3QoLiwgaW5kID0gIklEIiwgcHJlX3ZhciA9ICJER19Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJER19Ub3RhbF9Qb3N0IikNCmBgYA0KLS0+DQoNCg0KYGBge3Igc2NhbGVfc2NvcmluZywgcmVzdWx0cz0naGlkZSd9DQojIFNjYWxlcyBkZg0Kc2NhbGVfZGZfcHJlIDwtIHJpbzo6aW1wb3J0KGZpbGUucGF0aChmb2xkZXIsIGZpbGUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgc2tpcCA9IDAsIHdoaWNoID0gIlNldCB0ZXN0ZSB6aSAxIHByZSIpDQpzY2FsZV9kZl9wcmUgPC0gDQogIHNjYWxlX2RmX3ByZSAlPiUNCiAgamFuaXRvcjo6cmVtb3ZlX2VtcHR5KCJyb3dzIikgDQoNCnNjYWxlX2RmX3ByZSA8LSBzY2FsZV9kZl9wcmVbLC0yXQ0KY29sbmFtZXMoc2NhbGVfZGZfcHJlKVsxXSA8LSAiRGF0ZSINCmNvbG5hbWVzKHNjYWxlX2RmX3ByZSlbMl0gPC0gIklEIg0Kc2NhbGVfZGZfcHJlIDwtIA0KICBzY2FsZV9kZl9wcmUgJT4lDQogIGRwbHlyOjptdXRhdGUoSUQgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoSUQsIGZpeGVkKCIgIiksICIiKSkgJT4lICAgICMgcmVtb3ZlIHdoaXRlIHNwYWNlcw0KICBkcGx5cjo6bXV0YXRlKElEID0gdG91cHBlcihJRCkpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0byB1cHBlcg0KYWxsKHNjYWxlX2RmX3ByZSRJRCA9PSB0b3VwcGVyKHNjYWxlX2RmX3ByZSRJRCkpIA0KDQpzY2FsZV9kZl9wb3N0IDwtIHJpbzo6aW1wb3J0KGZpbGUucGF0aChmb2xkZXIsIGZpbGUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNraXAgPSAwLCB3aGljaCA9ICJTZXQgdGVzdGUgemkgNSBwb3N0IikNCnNjYWxlX2RmX3Bvc3QgPC0gDQogIHNjYWxlX2RmX3Bvc3QgJT4lDQogIGphbml0b3I6OnJlbW92ZV9lbXB0eSgicm93cyIpIA0KDQpzY2FsZV9kZl9wb3N0IDwtIHNjYWxlX2RmX3Bvc3RbLC0yXQ0KY29sbmFtZXMoc2NhbGVfZGZfcG9zdClbMV0gPC0gIkRhdGUiDQpjb2xuYW1lcyhzY2FsZV9kZl9wb3N0KVsyXSA8LSAiSUQiDQpzY2FsZV9kZl9wb3N0IDwtIA0KICBzY2FsZV9kZl9wb3N0ICU+JQ0KICBkcGx5cjo6bXV0YXRlKElEID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKElELCBmaXhlZCgiICIpLCAiIikpICU+JSAgICAjIHJlbW92ZSB3aGl0ZSBzcGFjZXMNCiAgZHBseXI6Om11dGF0ZShJRCA9IHRvdXBwZXIoSUQpKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRvIHVwcGVyDQphbGwoc2NhbGVfZGZfcG9zdCRJRCA9PSB0b3VwcGVyKHNjYWxlX2RmX3Bvc3QkSUQpKQ0KDQphbGwuZXF1YWwoY29sbmFtZXMoc2NhbGVfZGZfcG9zdCksIGNvbG5hbWVzKHNjYWxlX2RmX3ByZSkpICAgIyBzZXRkaWZmKGNvbG5hbWVzKHNjYWxlX2RmX3Bvc3QpLCBjb2xuYW1lcyhzY2FsZV9kZl9wcmUpKQ0KDQojIERlYWwgd2l0aCBOb3QgQW5zd2VyDQpzY2FsZV9kZl9wcmUgPC0NCiAgc2NhbGVfZGZfcHJlICU+JQ0KICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLCB+ZHBseXI6Om5hX2lmKC4sICJOb3QgQW5zd2VyZWQiKSkNCg0Kc2NhbGVfZGZfcG9zdCA8LQ0KICBzY2FsZV9kZl9wb3N0ICU+JQ0KICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLCB+ZHBseXI6Om5hX2lmKC4sICJOb3QgQW5zd2VyZWQiKSkNCg0KIyBFeGNsdWRlIHN1YmplY3RzDQpzY2FsZV9kZl9wcmUgPC0NCiAgc2NhbGVfZGZfcHJlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKCFzdHJpbmdyOjpzdHJfZGV0ZWN0KElELCAiUEE0T1hUIikpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKCFzdHJpbmdyOjpzdHJfZGV0ZWN0KElELCAiUk1OIikpIA0KDQpzY2FsZV9kZl9wb3N0IDwtDQogIHNjYWxlX2RmX3Bvc3QgJT4lDQogIGRwbHlyOjpmaWx0ZXIoIXN0cmluZ3I6OnN0cl9kZXRlY3QoSUQsICJQQTRPWFQiKSkgJT4lDQogIGRwbHlyOjpmaWx0ZXIoIXN0cmluZ3I6OnN0cl9kZXRlY3QoSUQsICJSTU4iKSkgDQoNCiMgQWRkIENvbmRpdGlvbg0Kc2NhbGVfZGZfcHJlIDwtDQogIHNjYWxlX2RmX3ByZSAlPiUNCiAgZHBseXI6Om11dGF0ZShUaW1lID0gcmVwKCJQcmUiLCBucm93KC4pKSkgJT4lDQogIGRwbHlyOjptdXRhdGUoQ29uZCA9IGlmZWxzZShzdHJpbmdyOjpzdHJfZGV0ZWN0KElELCAiWCIpLCAiQ1RSTCIsICJUUiIpKQ0KDQpzY2FsZV9kZl9wb3N0IDwtDQogIHNjYWxlX2RmX3Bvc3QgJT4lDQogIGRwbHlyOjptdXRhdGUoVGltZSA9IHJlcCgiUG9zdCIsIG5yb3coLikpKSAlPiUNCiAgICBkcGx5cjo6bXV0YXRlKENvbmQgPSBpZmVsc2Uoc3RyaW5ncjo6c3RyX2RldGVjdChJRCwgIlgiKSwgIkNUUkwiLCAiVFIiKSkNCg0KDQojIyBQQU5BUzogUG9zaXRpdmUgQWZmZWN0IFNjb3JlID0gc3VtIGl0ZW1zIDEsIDMsIDUsIDksIDEwLCAxMiwgMTQsIDE2LCAxNywgMTkuIE5lZ2F0aXZlIEFmZmVjdCBTY29yZSA9IHN1bSBpdGVtcyAyLCA0LCA2LCA3LCA4LCAxMSwgMTMsIDE1LCAxOCwgMjAuICANCmluZGV4X2l0ZW1fcGFuYXMgPC0gMzoyMg0KY29sbmFtZXMoc2NhbGVfZGZfcHJlKVtpbmRleF9pdGVtX3BhbmFzXSA8LSBzcHJpbnRmKCJQQU5BU18lZCIsIDE6MjApDQpjb2xuYW1lcyhzY2FsZV9kZl9wb3N0KVtpbmRleF9pdGVtX3BhbmFzXSA8LSBzcHJpbnRmKCJQQU5BU18lZCIsIDE6MjApDQoNCnNjYWxlX2RmX3ByZVssIGluZGV4X2l0ZW1fcGFuYXNdIDwtIGRhdGEuZnJhbWUobGFwcGx5KHNjYWxlX2RmX3ByZVssIGluZGV4X2l0ZW1fcGFuYXNdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkge2dzdWIoIi4qw65uIGZvYXJ0ZSBtaWPEgyBtxINzdXLEgy4qIiwgIjEiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3BhbmFzXSA8LSBkYXRhLmZyYW1lKGxhcHBseShzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3BhbmFzXSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHtnc3ViKCIuKsOubiBtaWPEgyBtxINzdXLEgy4qIiwgIjIiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3BhbmFzXSA8LSBkYXRhLmZyYW1lKGxhcHBseShzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3BhbmFzXSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHtnc3ViKCIuKsOubnRyLW8gb2FyZWNhcmUgbcSDc3VyxIMuKiIsICIzIiwgeCl9KSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0Kc2NhbGVfZGZfcHJlWywgaW5kZXhfaXRlbV9wYW5hc10gPC0gZGF0YS5mcmFtZShsYXBwbHkoc2NhbGVfZGZfcHJlWywgaW5kZXhfaXRlbV9wYW5hc10sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KSB7Z3N1YigiLirDrm4gbWFyZSBtxINzdXLEgy4qIiwgIjQiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3BhbmFzXSA8LSBkYXRhLmZyYW1lKGxhcHBseShzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3BhbmFzXSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHtnc3ViKCIuKsOubiBmb2FydGUgbWFyZSBtxINzdXLEgy4qIiwgIjUiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQoNCnNjYWxlX2RmX3Bvc3RbLCBpbmRleF9pdGVtX3BhbmFzXSA8LSBkYXRhLmZyYW1lKGxhcHBseShzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wYW5hc10sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkge2dzdWIoIi4qw65uIGZvYXJ0ZSBtaWPEgyBtxINzdXLEgy4qIiwgIjEiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wYW5hc10gPC0gZGF0YS5mcmFtZShsYXBwbHkoc2NhbGVfZGZfcG9zdFssIGluZGV4X2l0ZW1fcGFuYXNdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHtnc3ViKCIuKsOubiBtaWPEgyBtxINzdXLEgy4qIiwgIjIiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wYW5hc10gPC0gZGF0YS5mcmFtZShsYXBwbHkoc2NhbGVfZGZfcG9zdFssIGluZGV4X2l0ZW1fcGFuYXNdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHtnc3ViKCIuKsOubnRyLW8gb2FyZWNhcmUgbcSDc3VyxIMuKiIsICIzIiwgeCl9KSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0Kc2NhbGVfZGZfcG9zdFssIGluZGV4X2l0ZW1fcGFuYXNdIDwtIGRhdGEuZnJhbWUobGFwcGx5KHNjYWxlX2RmX3Bvc3RbLCBpbmRleF9pdGVtX3BhbmFzXSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KSB7Z3N1YigiLirDrm4gbWFyZSBtxINzdXLEgy4qIiwgIjQiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wYW5hc10gPC0gZGF0YS5mcmFtZShsYXBwbHkoc2NhbGVfZGZfcG9zdFssIGluZGV4X2l0ZW1fcGFuYXNdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHtnc3ViKCIuKsOubiBmb2FydGUgbWFyZSBtxINzdXLEgy4qIiwgIjUiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQojIFNjb3JpbmcNCnNjYWxlX2RmX3ByZSRQQV9Ub3RhbCA8LSBTY29yZUxpa2VydChzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3BhbmFzXVtjKDEsIDMsIDUsIDksIDEwLCAxMiwgMTQsIDE2LCAxNywgMTkpXSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b251bWVyaWMgPSBUUlVFLCBuYXBlcmNlbnQgPSAuMTEpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBub3QgbW9yZSB0aGFuIDEgTkFzIGZvciAxMCBpdGVtcw0Kc2NhbGVfZGZfcHJlJE5BX1RvdGFsIDwtIFNjb3JlTGlrZXJ0KHNjYWxlX2RmX3ByZVssIGluZGV4X2l0ZW1fcGFuYXNdW2MoMiwgNCwgNiwgNywgOCwgMTEsIDEzLCAxNSwgMTgsIDIwKV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b251bWVyaWMgPSBUUlVFLCBuYXBlcmNlbnQgPSAuMTEpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBub3QgbW9yZSB0aGFuIDEgTkFzIGZvciAxMCBpdGVtcw0KDQpzY2FsZV9kZl9wb3N0JFBBX1RvdGFsIDwtIFNjb3JlTGlrZXJ0KHNjYWxlX2RmX3Bvc3RbLCBpbmRleF9pdGVtX3BhbmFzXVtjKDEsIDMsIDUsIDksIDEwLCAxMiwgMTQsIDE2LCAxNywgMTkpXSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9udW1lcmljID0gVFJVRSwgbmFwZXJjZW50ID0gLjExKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbm90IG1vcmUgdGhhbiAxIE5BcyBmb3IgMTAgaXRlbXMNCnNjYWxlX2RmX3Bvc3QkTkFfVG90YWwgPC0gU2NvcmVMaWtlcnQoc2NhbGVfZGZfcG9zdFssIGluZGV4X2l0ZW1fcGFuYXNdW2MoMiwgNCwgNiwgNywgOCwgMTEsIDEzLCAxNSwgMTgsIDIwKV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9udW1lcmljID0gVFJVRSwgbmFwZXJjZW50ID0gLjExKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbm90IG1vcmUgdGhhbiAxIE5BcyBmb3IgMTAgaXRlbXMNCg0KDQojIyBQU1MtU0YgMTQgKGxpa2VydCAwLTQpLiBJdGVtcyA0LCA1LCA2LCA3LCA5LCAxMCwgYW5kIDEzIGFyZSBzY29yZWQgaW4gcmV2ZXJzZSBkaXJlY3Rpb24uDQppbmRleF9pdGVtX3BzcyA8LSAyMzozNg0KaW5kZXhfaXRlbV9yZXZQU1MgPC0gYyg0LCA1LCA2LCA3LCA5LCAxMCwgMTMpDQpjb2xuYW1lcyhzY2FsZV9kZl9wcmUpW2luZGV4X2l0ZW1fcHNzXSA8LSBzcHJpbnRmKCJQU1NfJWQiLCAxOjE0KQ0KY29sbmFtZXMoc2NhbGVfZGZfcG9zdClbaW5kZXhfaXRlbV9wc3NdIDwtIHNwcmludGYoIlBTU18lZCIsIDE6MTQpDQoNCnNjYWxlX2RmX3ByZVssIGluZGV4X2l0ZW1fcHNzXSA8LSBkYXRhLmZyYW1lKGxhcHBseShzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3Bzc10sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KSB7Z3N1YigiLipuaWNpb2RhdMSDLioiLCAiMCIsIHgpfSksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCnNjYWxlX2RmX3ByZVssIGluZGV4X2l0ZW1fcHNzXSA8LSBkYXRhLmZyYW1lKGxhcHBseShzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3Bzc10sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KSB7Z3N1YigiLiphcHJvYXBlIG5pY2lvZGF0xIMuKiIsICIxIiwgeCl9KSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0Kc2NhbGVfZGZfcHJlWywgaW5kZXhfaXRlbV9wc3NdIDwtIGRhdGEuZnJhbWUobGFwcGx5KHNjYWxlX2RmX3ByZVssIGluZGV4X2l0ZW1fcHNzXSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHtnc3ViKCIuKnVuZW9yaS4qIiwgIjIiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3Bzc10gPC0gZGF0YS5mcmFtZShsYXBwbHkoc2NhbGVfZGZfcHJlWywgaW5kZXhfaXRlbV9wc3NdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkge2dzdWIoIi4qZGVzdHVsIGRlIGRlcy4qIiwgIjMiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wcmVbLCBpbmRleF9pdGVtX3Bzc10gPC0gZGF0YS5mcmFtZShsYXBwbHkoc2NhbGVfZGZfcHJlWywgaW5kZXhfaXRlbV9wc3NdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkge2dzdWIoIi4qZm9hcnRlIGRlcy4qIiwgIjQiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQoNCnNjYWxlX2RmX3Bvc3RbLCBpbmRleF9pdGVtX3Bzc10gPC0gZGF0YS5mcmFtZShsYXBwbHkoc2NhbGVfZGZfcG9zdFssIGluZGV4X2l0ZW1fcHNzXSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24oeCkge2dzdWIoIi4qbmljaW9kYXTEgy4qIiwgIjAiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wc3NdIDwtIGRhdGEuZnJhbWUobGFwcGx5KHNjYWxlX2RmX3Bvc3RbLCBpbmRleF9pdGVtX3Bzc10sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHtnc3ViKCIuKmFwcm9hcGUgbmljaW9kYXTEgy4qIiwgIjEiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wc3NdIDwtIGRhdGEuZnJhbWUobGFwcGx5KHNjYWxlX2RmX3Bvc3RbLCBpbmRleF9pdGVtX3Bzc10sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHtnc3ViKCIuKnVuZW9yaS4qIiwgIjIiLCB4KX0pLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpDQpzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wc3NdIDwtIGRhdGEuZnJhbWUobGFwcGx5KHNjYWxlX2RmX3Bvc3RbLCBpbmRleF9pdGVtX3Bzc10sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKHgpIHtnc3ViKCIuKmRlc3R1bCBkZSBkZXMuKiIsICIzIiwgeCl9KSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0Kc2NhbGVfZGZfcG9zdFssIGluZGV4X2l0ZW1fcHNzXSA8LSBkYXRhLmZyYW1lKGxhcHBseShzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wc3NdLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbih4KSB7Z3N1YigiLipmb2FydGUgZGVzLioiLCAiNCIsIHgpfSksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCg0KIyBTY29yZQ0Kc2NhbGVfZGZfcHJlWywgaW5kZXhfaXRlbV9wc3NdIDwtIGNvbHN0b251bWVyaWMoc2NhbGVfZGZfcHJlWywgaW5kZXhfaXRlbV9wc3NdKQ0Kc2NhbGVfZGZfcG9zdFssIGluZGV4X2l0ZW1fcHNzXSA8LSBjb2xzdG9udW1lcmljKHNjYWxlX2RmX3Bvc3RbLCBpbmRleF9pdGVtX3Bzc10pDQoNCnNjYWxlX2RmX3ByZVssIGluZGV4X2l0ZW1fcHNzXVtpbmRleF9pdGVtX3JldlBTU10gPC0gUmV2ZXJzZUNvZGUoc2NhbGVfZGZfcHJlWywgaW5kZXhfaXRlbV9wc3NdW2luZGV4X2l0ZW1fcmV2UFNTXSwgdG9udW1lcmljID0gRkFMU0UsIG1pbiA9IDAsIG1heCA9IDQpDQpzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wc3NdW2luZGV4X2l0ZW1fcmV2UFNTXSA8LSBSZXZlcnNlQ29kZShzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wc3NdW2luZGV4X2l0ZW1fcmV2UFNTXSwgdG9udW1lcmljID0gRkFMU0UsIG1pbiA9IDAsIG1heCA9IDQpDQoNCnNjYWxlX2RmX3ByZSRQU1NfVG90YWwgPC0gU2NvcmVMaWtlcnQoc2NhbGVfZGZfcHJlWywgaW5kZXhfaXRlbV9wc3NdLCBuYXBlcmNlbnQgPSAuMTEpDQpzY2FsZV9kZl9wb3N0JFBTU19Ub3RhbCA8LSBTY29yZUxpa2VydChzY2FsZV9kZl9wb3N0WywgaW5kZXhfaXRlbV9wc3NdLCBuYXBlcmNlbnQgPSAuMTEpDQoNCg0KIyBVbml0ZSBzY2FsZSBkZiAtIExvbmcgRm9ybWF0DQpzY2FsZV91bml0ZWRfbG9uZyA8LSByYmluZChzY2FsZV9kZl9wcmUsIHNjYWxlX2RmX3Bvc3QpDQoNCiMgc2NhbGVfdW5pdGVkX2xvbmcgJT4lDQojICAgY291bnQoSUQpICU+JQ0KIyAgIHByaW50KG4gPSBJbmYpICAjIElEICIyQiIsICI1RSIgaGF2ZSBkb3VibGUgcmVjb3JkIA0KDQojIHNjYWxlX3VuaXRlZF9sb25nW3NjYWxlX3VuaXRlZF9sb25nJElEID09ICIyQiIsXQ0Kc2NhbGVfdW5pdGVkX2xvbmcgPC0gc2NhbGVfdW5pdGVkX2xvbmdbLTI2LF0NCiMgc2NhbGVfdW5pdGVkX2xvbmdbc2NhbGVfdW5pdGVkX2xvbmckSUQgPT0gIjVFIixdDQpzY2FsZV91bml0ZWRfbG9uZyA8LSBzY2FsZV91bml0ZWRfbG9uZ1stMTA5LF0NCg0KIyBFeGNsdWRlIHN1Ymogd2lodCBvbmx5IG9uZSBvYnNlcnZhdGlvbiwgZXhjbHVkZSBJRCBOT1RBTlNXRVJFRA0Kc2NhbGVfdW5pdGVkX2xvbmcgPC0NCiAgc2NhbGVfdW5pdGVkX2xvbmcgJT4lDQogIGdyb3VwX2J5KElEKSAlPiUNCiAgZHBseXI6OmZpbHRlcihuKCkgPiAxKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICE9ICJOT1RBTlNXRVJFRCIpDQoNCiMgVW5pdGUgREcgZGF0YSAtIFdpZGUgRm9ybWF0DQpzY2FsZV91bml0ZWRfd2lkZSA8LQ0KICBzY2FsZV91bml0ZWRfbG9uZyAlPiUNCiAgZHBseXI6OnNlbGVjdChJRCwgRGF0ZSwgVGltZSwgQ29uZCwgUEFfVG90YWwsIE5BX1RvdGFsLCBQU1NfVG90YWwpICU+JQ0KICB0aWR5cjo6cGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoSUQsIENvbmQpLCBuYW1lc19mcm9tID0gVGltZSwgdmFsdWVzX2Zyb20gPSBjKCJEYXRlIiwgIlBBX1RvdGFsIiwgIk5BX1RvdGFsIiwgIlBTU19Ub3RhbCIpKQ0KDQpgYGANCg0KDQo8IS0tDQpgYGB7ciBtaXhlZGFub3ZhX3NjYWxlc30NCmNhdCgiTWl4ZWQgQU5PVkEgLSBQU1Mgd2hvbGUgc2FtcGxlIChub3QgYnkgZ3JvdXBzKSIpDQojIE1peGVkIEFOT1ZBDQpzY2FsZV91bml0ZWRfbG9uZyAlPiUNCiAgZ3JvdXBfYnkoSUQpICU+JQ0KICBmaWx0ZXIobigpID4gMSkgJT4lICAgICAjIGtlZXAgb25seSBjb21wbGV0ZSBjYXNlcyAtLSBoZXJlIGFyZSBvbmx5IGNvbXBsZXRlDQogIHVuZ3JvdXAoKSAlPiUgDQogIHR3X21peGVkQU5PVkFfZnVuYyhkYXRhID0gLiwgaWRfdmFyID0gSUQsIGNvbmRfdmFyID0gQ29uZCwgdGltZV92YXIgPSBUaW1lLCB2YWx1ZV92YXIgPSBQU1NfVG90YWwsDQogICAgICAgICAgICAgICAgICBwb3N0aG9jX3NpZ19pbnRlcmFjID0gVFJVRSwgcG9zdGhvY19uc19pbnRlcmFjID0gVFJVRSkNCg0KY2F0KCJNaXhlZCBBTk9WQSAtIFBBIHdob2xlIHNhbXBsZSAobm90IGJ5IGdyb3VwcykiKQ0Kc2NhbGVfdW5pdGVkX2xvbmcgJT4lDQogIGdyb3VwX2J5KElEKSAlPiUNCiAgZmlsdGVyKG4oKSA+IDEpICU+JSAgICAgIyBrZWVwIG9ubHkgY29tcGxldGUgY2FzZXMgLS0gaGVyZSBhcmUgb25seSBjb21wbGV0ZQ0KICB1bmdyb3VwKCkgJT4lIA0KICB0d19taXhlZEFOT1ZBX2Z1bmMoZGF0YSA9IC4sIGlkX3ZhciA9IElELCBjb25kX3ZhciA9IENvbmQsIHRpbWVfdmFyID0gVGltZSwgdmFsdWVfdmFyID0gUEFfVG90YWwsDQogICAgICAgICAgICAgICAgICBwb3N0aG9jX3NpZ19pbnRlcmFjID0gVFJVRSwgcG9zdGhvY19uc19pbnRlcmFjID0gVFJVRSkNCg0KY2F0KCJNaXhlZCBBTk9WQSAtIE5BIHdob2xlIHNhbXBsZSAobm90IGJ5IGdyb3VwcykiKQ0Kc2NhbGVfdW5pdGVkX2xvbmcgJT4lDQogIGdyb3VwX2J5KElEKSAlPiUNCiAgZmlsdGVyKG4oKSA+IDEpICU+JSAgICAgIyBrZWVwIG9ubHkgY29tcGxldGUgY2FzZXMgLS0gaGVyZSBhcmUgb25seSBjb21wbGV0ZQ0KICB1bmdyb3VwKCkgJT4lIA0KICB0d19taXhlZEFOT1ZBX2Z1bmMoZGF0YSA9IC4sIGlkX3ZhciA9IElELCBjb25kX3ZhciA9IENvbmQsIHRpbWVfdmFyID0gVGltZSwgdmFsdWVfdmFyID0gTkFfVG90YWwsDQogICAgICAgICAgICAgICAgICBwb3N0aG9jX3NpZ19pbnRlcmFjID0gVFJVRSwgcG9zdGhvY19uc19pbnRlcmFjID0gVFJVRSkNCmBgYA0KLS0+DQoNCiMgVCB0ZXN0IFBTUw0KDQpgYGB7ciB0dGVzdF9ieWdyb3VwX3Bzc30NCiMgZHBseXI6OmZpbHRlcihJRCAlaW4lIGMoaWRzX3B0c2QsIGlkc19idXJuLCBpZHNfb2xkLCBpZHNfbm9ybWFsKSkgJT4lDQoNCmNhdCgiIyMgUFNTIC0gUFRTRCBUUiIpDQpzY2FsZV91bml0ZWRfd2lkZSAlPiUNCiAgZHBseXI6OmZpbHRlcihJRCAlaW4lIGlkc19wdHNkKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJUUiIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiUFNTX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIlBTU19Ub3RhbF9Qb3N0IikNCmNhdCgiIyMgUFNTIC0gUFRTRCBDVFJMIikNCnNjYWxlX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX3B0c2QpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIkNUUkwiKSAlPiUNCiAgZnVuY190X2JveCguLCBpbmQgPSAiSUQiLCBwcmVfdmFyID0gIlBTU19Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJQU1NfVG90YWxfUG9zdCIpDQoNCg0KY2F0KCIjIyBQU1MgLSBCdXJub3V0IFRSIikNCnNjYWxlX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX2J1cm4pICU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIlRSIikgJT4lDQogIGZ1bmNfdF9ib3goLiwgaW5kID0gIklEIiwgcHJlX3ZhciA9ICJQU1NfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiUFNTX1RvdGFsX1Bvc3QiKQ0KY2F0KCIjIyBQU1MgLSBCdXJub3V0IENUUkwiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfYnVybikgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiQ1RSTCIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiUFNTX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIlBTU19Ub3RhbF9Qb3N0IikNCg0KDQojIGNhdCgiIyMgUFNTIC0gT2xkIFRSIikNCiMgc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQojICAgZHBseXI6OmZpbHRlcihJRCAlaW4lIGlkc19vbGQpICU+JQ0KIyAgIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiVFIiKSAlPiUNCiMgICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiUFNTX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIlBTU19Ub3RhbF9Qb3N0IikNCiMgY2F0KCIjIyBQU1MgLSBPbGQgQ1RSTCIpDQojIHNjYWxlX3VuaXRlZF93aWRlICU+JQ0KIyAgIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfb2xkKSAlPiUNCiMgICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIkNUUkwiKSAlPiUNCiMgICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiUFNTX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIlBTU19Ub3RhbF9Qb3N0IikNCg0KY2F0KCIjIyBQU1MgLSBHZW5lcmFsIFBvcHVsYXRpb24gVFIiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfbm9ybWFsKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJUUiIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiUFNTX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIlBTU19Ub3RhbF9Qb3N0IikNCmNhdCgiIyMgUFNTIC0gR2VuZXJhbCBQb3B1bGF0aW9uIENUUkwiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfbm9ybWFsKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJDVFJMIikgJT4lDQogIGZ1bmNfdF9ib3goLiwgaW5kID0gIklEIiwgcHJlX3ZhciA9ICJQU1NfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiUFNTX1RvdGFsX1Bvc3QiKQ0KYGBgDQoNCjwhLS0NCiMjIFBTUyBOb3JtYWwgU2FtcGxlIFNpemUgZXN0aW1hdGlvbg0KDQpgYGB7ciBzYW1wbGVzaXplX3Bzc30NCmNhdCgiIyMgUFNTIC0gR2VuZXJhbCBQb3B1bGF0aW9uIFRSIikNCnNjYWxlX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX25vcm1hbCkgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiVFIiKSAlPiUNCiAgc2FtcGxlc2l6ZV9wYWlyZWR0dGVzdCguLCBwcmVfdmFyID0gIlBTU19Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJQU1NfVG90YWxfUG9zdCIpDQpjYXQoIiMjIFBTUyAtIEdlbmVyYWwgUG9wdWxhdGlvbiBDVFJMIikNCnNjYWxlX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX25vcm1hbCkgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiQ1RSTCIpICU+JQ0KICBzYW1wbGVzaXplX3BhaXJlZHR0ZXN0KC4sIHByZV92YXIgPSAiUFNTX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIlBTU19Ub3RhbF9Qb3N0IikNCmBgYA0KLS0+DQoNCiMgVCB0ZXN0IFBBDQoNCmBgYHtyIHR0ZXN0X2J5Z3JvdXBfcGF9DQpjYXQoIiMjIFBBIC0gUFRTRCBUUiIpDQpzY2FsZV91bml0ZWRfd2lkZSAlPiUNCiAgZHBseXI6OmZpbHRlcihJRCAlaW4lIGlkc19wdHNkKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJUUiIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiUEFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiUEFfVG90YWxfUG9zdCIpDQpjYXQoIiMjIFBBIC0gUFRTRCBDVFJMIikNCnNjYWxlX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX3B0c2QpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIkNUUkwiKSAlPiUNCiAgZnVuY190X2JveCguLCBpbmQgPSAiSUQiLCBwcmVfdmFyID0gIlBBX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIlBBX1RvdGFsX1Bvc3QiKQ0KDQoNCmNhdCgiIyMgUEEgLSBCdXJub3V0IFRSIikNCnNjYWxlX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX2J1cm4pICU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIlRSIikgJT4lDQogIGZ1bmNfdF9ib3goLiwgaW5kID0gIklEIiwgcHJlX3ZhciA9ICJQQV9Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJQQV9Ub3RhbF9Qb3N0IikNCmNhdCgiIyMgUEEgLSBCdXJub3V0IENUUkwiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfYnVybikgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiQ1RSTCIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiUEFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiUEFfVG90YWxfUG9zdCIpDQoNCg0KIyBjYXQoIiMjIFBBIC0gT2xkIFRSIikNCiMgc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQojICAgZHBseXI6OmZpbHRlcihJRCAlaW4lIGlkc19vbGQpICU+JQ0KIyAgIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiVFIiKSAlPiUNCiMgICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiUEFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiUEFfVG90YWxfUG9zdCIpDQojIGNhdCgiIyMgUEEgLSBPbGQgQ1RSTCIpDQojIHNjYWxlX3VuaXRlZF93aWRlICU+JQ0KIyAgIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfb2xkKSAlPiUNCiMgICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIkNUUkwiKSAlPiUNCiMgICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiUEFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiUEFfVG90YWxfUG9zdCIpDQoNCmNhdCgiIyMgUEEgLSBHZW5lcmFsIFBvcHVsYXRpb24gVFIiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfbm9ybWFsKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJUUiIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiUEFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiUEFfVG90YWxfUG9zdCIpDQpjYXQoIiMjIFBBIC0gR2VuZXJhbCBQb3B1bGF0aW9uIENUUkwiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfbm9ybWFsKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJDVFJMIikgJT4lDQogIGZ1bmNfdF9ib3goLiwgaW5kID0gIklEIiwgcHJlX3ZhciA9ICJQQV9Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJQQV9Ub3RhbF9Qb3N0IikNCg0KYGBgDQoNCjwhLS0NCiMjIFBBIE5vcm1hbCBTYW1wbGUgU2l6ZSBlc3RpbWF0aW9uDQoNCmBgYHtyIHNhbXBsZXNpemVfcGF9DQpjYXQoIiMjIFBTUyAtIEdlbmVyYWwgUG9wdWxhdGlvbiBUUiIpDQpzY2FsZV91bml0ZWRfd2lkZSAlPiUNCiAgZHBseXI6OmZpbHRlcihJRCAlaW4lIGlkc19ub3JtYWwpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIlRSIikgJT4lDQogIHNhbXBsZXNpemVfcGFpcmVkdHRlc3QoLiwgcHJlX3ZhciA9ICJQQV9Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJQQV9Ub3RhbF9Qb3N0IikNCmNhdCgiIyMgUFNTIC0gR2VuZXJhbCBQb3B1bGF0aW9uIENUUkwiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfbm9ybWFsKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJDVFJMIikgJT4lDQogIHNhbXBsZXNpemVfcGFpcmVkdHRlc3QoLiwgcHJlX3ZhciA9ICJQQV9Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJQQV9Ub3RhbF9Qb3N0IikNCmBgYA0KLS0+DQoNCiMgVCB0ZXN0IE5BDQoNCmBgYHtyIHR0ZXN0X2J5Z3JvdXBfbmF9DQpjYXQoIiMjIE5BIC0gUFRTRCBUUiIpDQpzY2FsZV91bml0ZWRfd2lkZSAlPiUNCiAgZHBseXI6OmZpbHRlcihJRCAlaW4lIGlkc19wdHNkKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJUUiIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiTkFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiTkFfVG90YWxfUG9zdCIpDQpjYXQoIiMjIE5BIC0gUFRTRCBDVFJMIikNCnNjYWxlX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX3B0c2QpICU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIkNUUkwiKSAlPiUNCiAgZnVuY190X2JveCguLCBpbmQgPSAiSUQiLCBwcmVfdmFyID0gIk5BX1RvdGFsX1ByZSIsIHBvc3RfdmFyID0gIk5BX1RvdGFsX1Bvc3QiKQ0KDQoNCmNhdCgiIyMgTkEgLSBCdXJub3V0IFRSIikNCnNjYWxlX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX2J1cm4pICU+JQ0KICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIlRSIikgJT4lDQogIGZ1bmNfdF9ib3goLiwgaW5kID0gIklEIiwgcHJlX3ZhciA9ICJOQV9Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJOQV9Ub3RhbF9Qb3N0IikNCmNhdCgiIyMgTkEgLSBCdXJub3V0IENUUkwiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfYnVybikgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiQ1RSTCIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiTkFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiTkFfVG90YWxfUG9zdCIpDQoNCg0KIyBjYXQoIiMjIE5BIC0gT2xkIFRSIikNCiMgc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQojICAgZHBseXI6OmZpbHRlcihJRCAlaW4lIGlkc19vbGQpICU+JQ0KIyAgIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiVFIiKSAlPiUNCiMgICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiTkFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiTkFfVG90YWxfUG9zdCIpDQojIGNhdCgiIyMgTkEgLSBPbGQgQ1RSTCIpDQojIHNjYWxlX3VuaXRlZF93aWRlICU+JQ0KIyAgIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfb2xkKSAlPiUNCiMgICBkcGx5cjo6ZmlsdGVyKENvbmQgPT0gIkNUUkwiKSAlPiUNCiMgICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiTkFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiTkFfVG90YWxfUG9zdCIpDQoNCmNhdCgiIyMgTkEgLSBHZW5lcmFsIFBvcHVsYXRpb24gVFIiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfbm9ybWFsKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJUUiIpICU+JQ0KICBmdW5jX3RfYm94KC4sIGluZCA9ICJJRCIsIHByZV92YXIgPSAiTkFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiTkFfVG90YWxfUG9zdCIpDQpjYXQoIiMjIE5BIC0gR2VuZXJhbCBQb3B1bGF0aW9uIENUUkwiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfbm9ybWFsKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJDVFJMIikgJT4lDQogIGZ1bmNfdF9ib3goLiwgaW5kID0gIklEIiwgcHJlX3ZhciA9ICJOQV9Ub3RhbF9QcmUiLCBwb3N0X3ZhciA9ICJOQV9Ub3RhbF9Qb3N0IikNCmBgYA0KDQo8IS0tDQojIyBOQSBOb3JtYWwgU2FtcGxlIFNpemUgZXN0aW1hdGlvbg0KDQpgYGB7ciBzYW1wbGVzaXplX25hfQ0KY2F0KCIjIyBQU1MgLSBHZW5lcmFsIFBvcHVsYXRpb24gVFIiKQ0Kc2NhbGVfdW5pdGVkX3dpZGUgJT4lDQogIGRwbHlyOjpmaWx0ZXIoSUQgJWluJSBpZHNfbm9ybWFsKSAlPiUNCiAgZHBseXI6OmZpbHRlcihDb25kID09ICJUUiIpICU+JQ0KICBzYW1wbGVzaXplX3BhaXJlZHR0ZXN0KC4sIHByZV92YXIgPSAiTkFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiTkFfVG90YWxfUG9zdCIpDQpjYXQoIiMjIFBTUyAtIEdlbmVyYWwgUG9wdWxhdGlvbiBDVFJMIikNCnNjYWxlX3VuaXRlZF93aWRlICU+JQ0KICBkcGx5cjo6ZmlsdGVyKElEICVpbiUgaWRzX25vcm1hbCkgJT4lDQogIGRwbHlyOjpmaWx0ZXIoQ29uZCA9PSAiQ1RSTCIpICU+JQ0KICBzYW1wbGVzaXplX3BhaXJlZHR0ZXN0KC4sIHByZV92YXIgPSAiTkFfVG90YWxfUHJlIiwgcG9zdF92YXIgPSAiTkFfVG90YWxfUG9zdCIpDQpgYGANCi0tPg0KDQoNCg0KPCEtLSBTZXNzaW9uIEluZm8gYW5kIExpY2Vuc2UgLS0+DQoNCjxicj4NCg0KIyBTZXNzaW9uIEluZm8NCmBgYHtyIHNlc3Npb25faW5mbywgZWNobyA9IEZBTFNFLCByZXN1bHRzID0gJ21hcmt1cCd9DQpzZXNzaW9uSW5mbygpICAgIA0KYGBgDQoNCjwhLS0gRm9vdGVyIC0tPg0KJm5ic3A7DQo8aHIgLz4NCjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij5BIHdvcmsgYnkgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL0NsYXVkaXVQYXBhc3RlcmkvIj5DbGF1ZGl1IFBhcGFzdGVyaTwvYT48L3A+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+PHNwYW4gc3R5bGU9ImNvbG9yOiAjODA4MDgwOyI+PGVtPmNsYXVkaXUucGFwYXN0ZXJpQGdtYWlsLmNvbTwvZW0+PC9zcGFuPjwvcD4NCiZuYnNwOw0K