# Set general settings for markdown file
knitr::opts_chunk$set(
  message = FALSE,
  warning = FALSE,
  comment = "",
  results = "hold")


# Clear environment
rm(list = ls())


# Load packages
library(dplyr)      # for data wrangling
library(knitr)      # for integrating computing and reporting in markdown
library(pastecs)    # for descriptive statistics
library(kableExtra) # for customizing appearance of tables
library(MASS)       # for boxcox function and contrast definition
library(lme4)       # for (G)LMMs
library(lmerTest)   # for LMM p values (Satterthwaite's method for approximating dfs for t and F tests)
library(sjPlot)     # for tab_model function to display (G)LMM results


# Load functions
source("./functions/summarySEwithinO.R")  # Function provided by R-cookbook: http://www.cookbook-r.com/Graphs/Plotting_means_and_error_bars_(ggplot2)/
source("./functions/my_table_template.R") # Function to create table template


# Turn off scientific notation
options(scipen = 999)


# Prepare labels for (G)LMM tables
labels <- c(
  "(Intercept)"                   = "Intercept",
  "gng_response_type2-1"          = "FH – SH",
  "gng_response_type3-2"          = "FA – FH",
  "group2-1"                      = "Group (OCD – HC)",
  "gng_response_type2-1:group2-1" = "FH – SH x Group",
  "gng_response_type3-2:group2-1" = "FA – FH x Group")


Data Cleaning


# Load data
load(file = "./data/Single_Trial_Data.rda")


# Create numeric accuracy variable (0 = FA; 1 = SH, FH, IR)
single_trial_data <- single_trial_data %>%
  dplyr::mutate(gng_accuracy_numeric = ifelse(gng_response_type == "FH" | gng_response_type == "SH" |
      gng_response_type == "IR", 1, ifelse(gng_response_type == "FA", 0, NA)))


# For RT analysis, exclude inhibited gng responses, missing gng responses, gng responses with
# wrong key, gng RT outliers, and trials with ERP artifacts
single_trial_data_gng_rt <- single_trial_data %>%
  dplyr::filter(
    gng_response_type != "IR" &
    gng_response_type != "miss" &
    gng_response_type != "wrong_key" &
    (is.na(gng_rt_invalid) | gng_rt_invalid == FALSE) &
    stimulation == "sham" &
    MFN_artifact == FALSE)


# For accuracy analysis, exclude missing gng responses, gng responses with wrong key, gng RT outliers,
# and trials with ERP artifacts
single_trial_data_gng_acc <- single_trial_data %>%
  dplyr::filter(
    gng_response_type != "miss" &
    gng_response_type != "wrong_key" &
    (is.na(gng_rt_invalid) | gng_rt_invalid == FALSE) &
    stimulation == "sham" &
    MFN_artifact == FALSE)


# Make categorical variables factors
single_trial_data_gng_rt$gng_response_type <- factor(single_trial_data_gng_rt$gng_response_type,
  levels = c("SH", "FH", "FA"))
single_trial_data_gng_rt$participant_id    <- factor(single_trial_data_gng_rt$participant_id)
single_trial_data_gng_rt$group             <- factor(single_trial_data_gng_rt$group)
single_trial_data_gng_acc$participant_id   <- factor(single_trial_data_gng_acc$participant_id)
single_trial_data_gng_acc$group            <- factor(single_trial_data_gng_acc$group)

In the analysis of RT and accuracy in the go/no-go task, trials were discarded if RT in the go/no-go task was below 100 ms or above 800 ms, response was missing, or the response was made with a key not assigned to the go/no-go task. We further discarded trials containing artifacts in the EEG, i.e., a voltage difference exceeding 200 μV within an epoch or 50 μV between sample points.


Descriptive Statistics


This table corresponds to Table S2 in the supplemental material.

# Calculate descriptive statistics for RT
descriptive_statistics_rt <- summarySEwithinO(
  data          = single_trial_data_gng_rt,
  measurevar    = "gng_rt",
  withinvars    = "gng_response_type",
  betweenvars   = "group",
  idvar         = "participant_id",
  conf.interval = .95) %>%
  # Rename variable and select variables for subsequent merging
  dplyr::rename(mean = gng_rt) %>%
  dplyr::select("group", "gng_response_type", "mean", "ci")


# Prepare calculation of descriptive statistics for proportion of response types (based on all trials)
descriptive_statistics_proportion <- single_trial_data %>%
  dplyr::filter(stimulation == "sham") %>%
  dplyr::group_by(participant_id, group) %>%
  dplyr::summarize(
    SH         = sum(gng_response_type == "SH")        / length(participant_id) * 100,
    FH         = sum(gng_response_type == "FH")        / length(participant_id) * 100,
    FA         = sum(gng_response_type == "FA")        / length(participant_id) * 100,
    IR         = sum(gng_response_type == "IR")        / length(participant_id) * 100,
    misses     = sum(gng_response_type == "miss")      / length(participant_id) * 100,
    wrong_key  = sum(gng_response_type == "wrong_key") / length(participant_id) * 100) %>%
  dplyr::ungroup()


# Calculate descriptive statistics for proportion (exclude first column containing participant ID)
descriptive_statistics_proportion <- descriptive_statistics_proportion[, -c(1)] %>%
  dplyr::group_by(group) %>%
  do(data.frame(t(stat.desc(.)))) %>%
  na.omit() %>%
  dplyr::ungroup() %>%
  # Create response type column, rename variable, and select variables for subsequent merging
  dplyr::mutate(gng_response_type = rep(c("SH ","FH ","FA ","IR", "Missing response", "Wrong key response"),2)) %>%
  dplyr::rename(ci = CI.mean) %>%
  dplyr::select("group", "gng_response_type", "mean", "ci")


# Combine measures
descriptive_statistics <- as.data.frame(rbind(descriptive_statistics_rt, descriptive_statistics_proportion))


# Create column with format "M [CI]" for RT (round to 0 decimals)
descriptive_statistics$M_CI <- paste0(round(descriptive_statistics$mean, 0), " [",
  round(descriptive_statistics$mean - descriptive_statistics$ci, 0), ", ",
  round(descriptive_statistics$mean + descriptive_statistics$ci, 0), "]")


# Create column with format "M [CI]" for accuracy (round to 2 decimals)
descriptive_statistics[c(7:18), ]$M_CI <- paste0(
  format(round(descriptive_statistics[c(7:18), ]$mean, 2), nsmall = 2), " [",
  format(round(descriptive_statistics[c(7:18), ]$mean -
               descriptive_statistics[c(7:18), ]$ci,   2), nsmall = 2), ", ",
  format(round(descriptive_statistics[c(7:18), ]$mean +
               descriptive_statistics[c(7:18), ]$ci,   2), nsmall = 2), "]")


# Split and re-merge table to display both groups next to each other
descriptive_statistics <- split(descriptive_statistics, descriptive_statistics$group)
descriptive_statistics_display <- cbind(descriptive_statistics$OCD[, c("gng_response_type", "M_CI")],
                                        descriptive_statistics$HC[, "M_CI"])


# Display table (and rearrange rows)
my_table_template(descriptive_statistics_display[c(3:1, 4:9), ],
  caption = "Descriptive Statistics for Behavioral Performance in the Go/No-Go Task",
  col_names = c("Measure", rep("M [95% CI]", 2)),
  header_above_config = c("", "Patients with OCD", "Healthy control participants")) %>%
  add_footnote("\n Note. CIs are adjusted for within-participant comparisons using the method described 
  by Morey (2008).", notation = "none") %>%
  pack_rows("Response time (ms)", 1, 3) %>%
  pack_rows("Proportion of responses (%)", 4, 9)
Descriptive Statistics for Behavioral Performance in the Go/No-Go Task
Patients with OCD
Healthy control participants
Measure M [95% CI] M [95% CI]
Response time (ms)
SH 363 [360, 365] 362 [360, 365]
FH 297 [295, 298] 283 [281, 285]
FA 285 [279, 290] 296 [290, 302]
Proportion of responses (%)
SH 44.77 [41.70, 47.85] 46.37 [42.86, 49.88]
FH 21.23 [18.23, 24.24] 19.69 [16.47, 22.91]
FA 9.14 [ 6.97, 11.30] 8.76 [ 7.33, 10.19]
IR 23.34 [21.19, 25.49] 23.74 [22.33, 25.15]
Missing response 1.03 [ 0.52, 1.54] 1.17 [ 0.45, 1.89]
Wrong key response 0.49 [ 0.26, 0.71] 0.27 [ 0.16, 0.38]

Note. CIs are adjusted for within-participant comparisons using the method described
by Morey (2008).
# Define data basis (all go trials, equivalent to calculation in task program) 
single_trial_data_rt_limit <- single_trial_data %>%
  dplyr::filter(
    gng_response_type != "FA" & 
    gng_response_type != "IR" &
    gng_response_type != "miss" &
    gng_response_type != "wrong_key" & 
    stimulation == "sham")


# Add block variable
single_trial_data_rt_limit <- single_trial_data_rt_limit %>%
  dplyr::mutate(block = ifelse(trial < 29, 1, 
                           ifelse((trial > 28 & trial < 101), 2,
                              ifelse((trial > 100 & trial < 173), 3, 
                                 ifelse((trial > 172 & trial < 201), 4,
                                    ifelse((trial > 200 & trial < 273), 5,
                                       ifelse((trial > 272 & trial < 345), 6,
                                          ifelse((trial > 344 & trial < 373), 7,
                                             ifelse((trial > 372 & trial < 445), 8, 9)))))))))


# Get mean RT per block
mean_rt_per_block <- single_trial_data_rt_limit %>%
  dplyr::group_by(participant_id, block) %>%
  dplyr::summarize(mean_rt = mean(gng_rt)) %>%
  dplyr::ungroup()


# Calculate fast hit response time limit in calibration blocks 1, 4, and 7
mean_rt_per_block <- mean_rt_per_block %>% 
  dplyr::filter(block == 1 | block == 4 | block == 7) %>% 
  dplyr::mutate(fh_time = ifelse(block == 1, mean_rt * 0.8, mean_rt * 0.9),
                group   = as.factor(ifelse(substr(participant_id, 1, 1) == "C", "HC", "OCD"))) 


# Calculate mean, sd, min, and max of fast hit response time limit per group
fh_time <- mean_rt_per_block %>%
  dplyr::group_by(group) %>% 
  dplyr::summarize(M = mean(fh_time), SD = sd(fh_time), min = min(fh_time), max = max(fh_time)) %>%
  dplyr::ungroup() 


# Round values
fh_time[, c(2:5)] <- round(fh_time[, c(2:5)], digits = 0)


# Display table 
my_table_template(fh_time, caption = "Fast Hit Response Time Limit",
  col_names = c("Group", "M", "SD", "min", "max"))
Fast Hit Response Time Limit
Group M SD min max
HC 294 46 195 442
OCD 300 57 218 434



Analysis of Response Time


We performed a linear mixed model (LMM) on single-trial data. Analysis of RT in the go/no-go task included group and response type (slow hit, fast hit, false alarm) as fixed effects.

We used sliding difference contrasts for categorical fixed effects and started with the maximal random-effects structure for each model. In case of non-convergence, random effects were specified as uncorrelated. Using principal component analysis, we identified random effects explaining zero variance and removed these, as recommended by Bates, Kliegl, et al. (2015).

Determine Data Transformation

RT was log-transformed to normalize residuals. This was determined using the Box–Cox procedure (Box & Cox, 1964).

# Arrange plots
par(mfrow = c(1, 5))


# Determine transformation by estimating optimal lambda using Box–Cox procedure
bc_rt <- boxcox(gng_rt ~ 1, data = single_trial_data_gng_rt)
optlambda_rt <- bc_rt$x[which.max(bc_rt$y)]


# Density plot for raw RT
plot(density(single_trial_data_gng_rt$gng_rt), main = "Raw RT: Density Plot")


# Q-q plot for raw RT
qqnorm(single_trial_data_gng_rt$gng_rt, main = "Raw RT: Q-Q Plot", pch = 1)


# Density plot for log RT
plot(density(single_trial_data_gng_rt$gng_rt_log), main = "Log RT: Density Plot")


# Q-q plot for log RT
qqnorm(single_trial_data_gng_rt$gng_rt_log, main = "Log RT: Q-Q Plot", pch = 1)

# Reset plot layout
par(mfrow = c(1, 1))

The optimal lambda is -0.55, suggesting that log transformation is appropriate.


LMM

This table corresponds to Table 2 in the manuscript.

# Define contrasts (sliding difference contrasts = effect coding for factors with 2 levels)
contrasts(single_trial_data_gng_rt$gng_response_type) <- contr.sdif(3)
contrasts(single_trial_data_gng_rt$group)             <- contr.sdif(2)


# Run model with maximal random-effects structure
LMM_gng_rt <- lmer(gng_rt_log ~ gng_response_type * group +
  (1 + gng_response_type | participant_id),
  data = single_trial_data_gng_rt,
  REML = TRUE,
  control = lmerControl(optimizer = "bobyqa"))


# Check model output and PCA of random-effects variance-covariance estimates
# summary(LMM_gng_rt)        # Model does converge
# isSingular(LMM_gng_rt)     # No singular fit
# summary(rePCA(LMM_gng_rt)) # All terms explain variance


# Display results (fixed effects)
tab_model(LMM_gng_rt,
  dv.labels = "RT", pred.labels = labels, show.stat = TRUE, show.icc = FALSE, show.r2 = FALSE,
  show.re.var = FALSE, show.ngroups = FALSE, minus.sign = "-", string.pred = "Fixed effects",
  string.est = "b", string.stat = "t", string.ci = "95 % CI", p.val = "satterthwaite",
  title = "LMM Results for RT in the Go/No-Go Task")


# Display random effects
print("Random effects:")
print(VarCorr(LMM_gng_rt), digits = 1, comp = "Std.Dev.")
LMM Results for RT in the Go/No-Go Task
  RT
Fixed effects b 95 % CI t p
Intercept 5.73 5.69 – 5.76 300.78 <0.001
FH – SH -0.26 -0.28 – -0.24 -24.82 <0.001
FA – FH 0.04 0.02 – 0.07 3.41 0.001
Group (OCD – HC) 0.01 -0.07 – 0.09 0.26 0.797
FH – SH x Group 0.01 -0.03 – 0.05 0.37 0.710
FA – FH x Group -0.02 -0.07 – 0.03 -0.93 0.359
Observations 21164
[1] "Random effects:"
 Groups         Name                 Std.Dev. Corr       
 participant_id (Intercept)          0.14                
                gng_response_type2-1 0.07     -0.20      
                gng_response_type3-2 0.08      0.14 -0.20
 Residual                            0.18                


RTs were shorter for fast hits than for slow hits and false alarms. There was no significant group difference in RT.


Analysis of Accuracy


We performed a binomial generalized linear mixed model (GLMM) on single-trial data. Analysis of accuracy in the go/no-go task included group as fixed effect.

We used sliding difference contrasts for categorical fixed effects and started with the maximal random-effects structure for each model. In case of non-convergence, random effects were specified as uncorrelated. Using principal component analysis, we identified random effects explaining zero variance and removed these, as recommended by Bates, Kliegl, et al. (2015).

GLMM

This table corresponds to Table 2 in the manuscript.

# Define contrasts (sliding difference contrasts = effect coding for factors with 2 levels)
contrasts(single_trial_data_gng_acc$group) <- contr.sdif(2)


# Run model with maximal random-effects structure
GLMM_gng_acc <- glmer(gng_accuracy_numeric ~ group + (1 | participant_id),
  data = single_trial_data_gng_acc,
  family = binomial,
  control = glmerControl(optimizer = "bobyqa"))


# Check model output and PCA of random-effects variance-covariance estimates
# summary(GLMM_gng_acc)        # Model does converge
# isSingular(GLMM_gng_acc)     # No singular fit
# summary(rePCA(GLMM_gng_acc)) # All terms explain variance


# Display results (fixed effects)
tab_model(GLMM_gng_acc,
  dv.labels = "Accuracy", pred.labels = labels, show.stat = TRUE, show.icc = FALSE, show.r2 = FALSE,
  show.re.var = FALSE, show.ngroups = FALSE, minus.sign = "-", string.pred = "Fixed effects",
  string.est = "Odds ratio", string.stat = "z", string.ci = "95 % CI", 
  title = "GLMM Results for Accuracy in the Go/No-Go Task")


# Display random effects
print("Random effects:")
print(VarCorr(GLMM_gng_acc), digits = 2, comp = "Std.Dev.")
GLMM Results for Accuracy in the Go/No-Go Task
  Accuracy
Fixed effects Odds ratio 95 % CI z p
Intercept 11.57 9.88 – 13.54 30.45 <0.001
Group (OCD – HC) 1.03 0.75 – 1.41 0.19 0.848
Observations 27892
[1] "Random effects:"
 Groups         Name        Std.Dev.
 participant_id (Intercept) 0.58    


There was no significant group difference in accuracy.


References


Bates, D., Kliegl, R., Vasishth, S., & Baayen, H. (2015). Parsimonious mixed models. arXiv. https://arxiv.org/abs/1506.04967v2

Box, G. E., & Cox, D. R. (1964). An analysis of transformations. Journal of the Royal Statistical Society: Series B (Methodological), 26(2), 211–243. https://doi.org/10.1111/j.2517-6161.1964.tb00553.x

Morey, R. (2008). Confidence intervals from normalized data: A correction to Cousineau (2005). Tutorials in Quantitative Methods for Psychology, 4(2), 61–64. https://doi.org/10.20982/tqmp.04.2.p061


Session Info


sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19044)

Matrix products: default

locale:
[1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252   
[3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C                   
[5] LC_TIME=German_Germany.1252    

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

other attached packages:
 [1] plyr_1.8.7       sjPlot_2.8.11    lmerTest_3.1-3   lme4_1.1-25     
 [5] Matrix_1.5-1     MASS_7.3-51.4    kableExtra_1.3.4 pastecs_1.3.21  
 [9] knitr_1.40       dplyr_1.0.10    

loaded via a namespace (and not attached):
 [1] httr_1.4.4          sass_0.4.0          tidyr_1.2.1        
 [4] jsonlite_1.8.3      viridisLite_0.4.1   splines_3.6.1      
 [7] modelr_0.1.9        bslib_0.4.0         datawizard_0.6.2   
[10] assertthat_0.2.1    statmod_1.4.37      highr_0.9          
[13] renv_0.12.0         yaml_2.2.1          bayestestR_0.13.0  
[16] numDeriv_2016.8-1.1 pillar_1.8.1        backports_1.4.1    
[19] lattice_0.20-45     glue_1.6.2          digest_0.6.30      
[22] rvest_1.0.3         minqa_1.2.4         colorspace_2.0-3   
[25] htmltools_0.5.3     pkgconfig_2.0.3     broom_1.0.1        
[28] purrr_0.3.5         xtable_1.8-4        mvtnorm_1.1-3      
[31] scales_1.2.1        webshot_0.5.4       svglite_2.1.0      
[34] emmeans_1.6.0       tibble_3.1.8        generics_0.1.3     
[37] ggplot2_3.3.6       sjlabelled_1.2.0    cachem_1.0.4       
[40] withr_2.5.0         cli_3.4.1           magrittr_2.0.3     
[43] effectsize_0.7.0.5  estimability_1.4.1  evaluate_0.16      
[46] fansi_1.0.3         nlme_3.1-140        xml2_1.3.3         
[49] tools_3.6.1         lifecycle_1.0.3     stringr_1.4.1      
[52] munsell_0.5.0       ggeffects_1.1.3     compiler_3.6.1     
[55] jquerylib_0.1.4     systemfonts_1.0.4   rlang_1.0.6        
[58] grid_3.6.1          nloptr_1.2.2.2      parameters_0.19.0  
[61] rstudioapi_0.14     rmarkdown_2.16      boot_1.3-22        
[64] gtable_0.3.1        sjstats_0.18.1      DBI_1.1.3          
[67] sjmisc_2.8.9        R6_2.5.1            performance_0.10.0 
[70] fastmap_1.1.0       utf8_1.2.2          insight_0.18.4     
[73] stringi_1.6.1       Rcpp_1.0.9          vctrs_0.5.0        
[76] tidyselect_1.2.0    xfun_0.33          
LS0tDQp0aXRsZTogIkdvL05vLUdvIERhdGEiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50DQotLS0NCg0KPCEtLSBTZXQgZ2VuZXJhbCBzZXR0aW5ncyAtLT4NCg0KYGBge3Igc2V0dXAsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFfQ0KDQojIFNldCBnZW5lcmFsIHNldHRpbmdzIGZvciBtYXJrZG93biBmaWxlDQprbml0cjo6b3B0c19jaHVuayRzZXQoDQogIG1lc3NhZ2UgPSBGQUxTRSwNCiAgd2FybmluZyA9IEZBTFNFLA0KICBjb21tZW50ID0gIiIsDQogIHJlc3VsdHMgPSAiaG9sZCIpDQoNCg0KIyBDbGVhciBlbnZpcm9ubWVudA0Kcm0obGlzdCA9IGxzKCkpDQoNCg0KIyBMb2FkIHBhY2thZ2VzDQpsaWJyYXJ5KGRwbHlyKSAgICAgICMgZm9yIGRhdGEgd3JhbmdsaW5nDQpsaWJyYXJ5KGtuaXRyKSAgICAgICMgZm9yIGludGVncmF0aW5nIGNvbXB1dGluZyBhbmQgcmVwb3J0aW5nIGluIG1hcmtkb3duDQpsaWJyYXJ5KHBhc3RlY3MpICAgICMgZm9yIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MNCmxpYnJhcnkoa2FibGVFeHRyYSkgIyBmb3IgY3VzdG9taXppbmcgYXBwZWFyYW5jZSBvZiB0YWJsZXMNCmxpYnJhcnkoTUFTUykgICAgICAgIyBmb3IgYm94Y294IGZ1bmN0aW9uIGFuZCBjb250cmFzdCBkZWZpbml0aW9uDQpsaWJyYXJ5KGxtZTQpICAgICAgICMgZm9yIChHKUxNTXMNCmxpYnJhcnkobG1lclRlc3QpICAgIyBmb3IgTE1NIHAgdmFsdWVzIChTYXR0ZXJ0aHdhaXRlJ3MgbWV0aG9kIGZvciBhcHByb3hpbWF0aW5nIGRmcyBmb3IgdCBhbmQgRiB0ZXN0cykNCmxpYnJhcnkoc2pQbG90KSAgICAgIyBmb3IgdGFiX21vZGVsIGZ1bmN0aW9uIHRvIGRpc3BsYXkgKEcpTE1NIHJlc3VsdHMNCg0KDQojIExvYWQgZnVuY3Rpb25zDQpzb3VyY2UoIi4vZnVuY3Rpb25zL3N1bW1hcnlTRXdpdGhpbk8uUiIpICAjIEZ1bmN0aW9uIHByb3ZpZGVkIGJ5IFItY29va2Jvb2s6IGh0dHA6Ly93d3cuY29va2Jvb2stci5jb20vR3JhcGhzL1Bsb3R0aW5nX21lYW5zX2FuZF9lcnJvcl9iYXJzXyhnZ3Bsb3QyKS8NCnNvdXJjZSgiLi9mdW5jdGlvbnMvbXlfdGFibGVfdGVtcGxhdGUuUiIpICMgRnVuY3Rpb24gdG8gY3JlYXRlIHRhYmxlIHRlbXBsYXRlDQoNCg0KIyBUdXJuIG9mZiBzY2llbnRpZmljIG5vdGF0aW9uDQpvcHRpb25zKHNjaXBlbiA9IDk5OSkNCg0KDQojIFByZXBhcmUgbGFiZWxzIGZvciAoRylMTU0gdGFibGVzDQpsYWJlbHMgPC0gYygNCiAgIihJbnRlcmNlcHQpIiAgICAgICAgICAgICAgICAgICA9ICJJbnRlcmNlcHQiLA0KICAiZ25nX3Jlc3BvbnNlX3R5cGUyLTEiICAgICAgICAgID0gIkZIIOKAkyBTSCIsDQogICJnbmdfcmVzcG9uc2VfdHlwZTMtMiIgICAgICAgICAgPSAiRkEg4oCTIEZIIiwNCiAgImdyb3VwMi0xIiAgICAgICAgICAgICAgICAgICAgICA9ICJHcm91cCAoT0NEIOKAkyBIQykiLA0KICAiZ25nX3Jlc3BvbnNlX3R5cGUyLTE6Z3JvdXAyLTEiID0gIkZIIOKAkyBTSCB4IEdyb3VwIiwNCiAgImduZ19yZXNwb25zZV90eXBlMy0yOmdyb3VwMi0xIiA9ICJGQSDigJMgRkggeCBHcm91cCIpDQpgYGANCjxicj4NCg0KIyMgRGF0YSBDbGVhbmluZw0KKioqDQoNCmBgYHtyIGxvYWQtYW5kLWNsZWFuLWRhdGF9DQoNCiMgTG9hZCBkYXRhDQpsb2FkKGZpbGUgPSAiLi9kYXRhL1NpbmdsZV9UcmlhbF9EYXRhLnJkYSIpDQoNCg0KIyBDcmVhdGUgbnVtZXJpYyBhY2N1cmFjeSB2YXJpYWJsZSAoMCA9IEZBOyAxID0gU0gsIEZILCBJUikNCnNpbmdsZV90cmlhbF9kYXRhIDwtIHNpbmdsZV90cmlhbF9kYXRhICU+JQ0KICBkcGx5cjo6bXV0YXRlKGduZ19hY2N1cmFjeV9udW1lcmljID0gaWZlbHNlKGduZ19yZXNwb25zZV90eXBlID09ICJGSCIgfCBnbmdfcmVzcG9uc2VfdHlwZSA9PSAiU0giIHwNCiAgICAgIGduZ19yZXNwb25zZV90eXBlID09ICJJUiIsIDEsIGlmZWxzZShnbmdfcmVzcG9uc2VfdHlwZSA9PSAiRkEiLCAwLCBOQSkpKQ0KDQoNCiMgRm9yIFJUIGFuYWx5c2lzLCBleGNsdWRlIGluaGliaXRlZCBnbmcgcmVzcG9uc2VzLCBtaXNzaW5nIGduZyByZXNwb25zZXMsIGduZyByZXNwb25zZXMgd2l0aA0KIyB3cm9uZyBrZXksIGduZyBSVCBvdXRsaWVycywgYW5kIHRyaWFscyB3aXRoIEVSUCBhcnRpZmFjdHMNCnNpbmdsZV90cmlhbF9kYXRhX2duZ19ydCA8LSBzaW5nbGVfdHJpYWxfZGF0YSAlPiUNCiAgZHBseXI6OmZpbHRlcigNCiAgICBnbmdfcmVzcG9uc2VfdHlwZSAhPSAiSVIiICYNCiAgICBnbmdfcmVzcG9uc2VfdHlwZSAhPSAibWlzcyIgJg0KICAgIGduZ19yZXNwb25zZV90eXBlICE9ICJ3cm9uZ19rZXkiICYNCiAgICAoaXMubmEoZ25nX3J0X2ludmFsaWQpIHwgZ25nX3J0X2ludmFsaWQgPT0gRkFMU0UpICYNCiAgICBzdGltdWxhdGlvbiA9PSAic2hhbSIgJg0KICAgIE1GTl9hcnRpZmFjdCA9PSBGQUxTRSkNCg0KDQojIEZvciBhY2N1cmFjeSBhbmFseXNpcywgZXhjbHVkZSBtaXNzaW5nIGduZyByZXNwb25zZXMsIGduZyByZXNwb25zZXMgd2l0aCB3cm9uZyBrZXksIGduZyBSVCBvdXRsaWVycywNCiMgYW5kIHRyaWFscyB3aXRoIEVSUCBhcnRpZmFjdHMNCnNpbmdsZV90cmlhbF9kYXRhX2duZ19hY2MgPC0gc2luZ2xlX3RyaWFsX2RhdGEgJT4lDQogIGRwbHlyOjpmaWx0ZXIoDQogICAgZ25nX3Jlc3BvbnNlX3R5cGUgIT0gIm1pc3MiICYNCiAgICBnbmdfcmVzcG9uc2VfdHlwZSAhPSAid3Jvbmdfa2V5IiAmDQogICAgKGlzLm5hKGduZ19ydF9pbnZhbGlkKSB8IGduZ19ydF9pbnZhbGlkID09IEZBTFNFKSAmDQogICAgc3RpbXVsYXRpb24gPT0gInNoYW0iICYNCiAgICBNRk5fYXJ0aWZhY3QgPT0gRkFMU0UpDQoNCg0KIyBNYWtlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBmYWN0b3JzDQpzaW5nbGVfdHJpYWxfZGF0YV9nbmdfcnQkZ25nX3Jlc3BvbnNlX3R5cGUgPC0gZmFjdG9yKHNpbmdsZV90cmlhbF9kYXRhX2duZ19ydCRnbmdfcmVzcG9uc2VfdHlwZSwNCiAgbGV2ZWxzID0gYygiU0giLCAiRkgiLCAiRkEiKSkNCnNpbmdsZV90cmlhbF9kYXRhX2duZ19ydCRwYXJ0aWNpcGFudF9pZCAgICA8LSBmYWN0b3Ioc2luZ2xlX3RyaWFsX2RhdGFfZ25nX3J0JHBhcnRpY2lwYW50X2lkKQ0Kc2luZ2xlX3RyaWFsX2RhdGFfZ25nX3J0JGdyb3VwICAgICAgICAgICAgIDwtIGZhY3RvcihzaW5nbGVfdHJpYWxfZGF0YV9nbmdfcnQkZ3JvdXApDQpzaW5nbGVfdHJpYWxfZGF0YV9nbmdfYWNjJHBhcnRpY2lwYW50X2lkICAgPC0gZmFjdG9yKHNpbmdsZV90cmlhbF9kYXRhX2duZ19hY2MkcGFydGljaXBhbnRfaWQpDQpzaW5nbGVfdHJpYWxfZGF0YV9nbmdfYWNjJGdyb3VwICAgICAgICAgICAgPC0gZmFjdG9yKHNpbmdsZV90cmlhbF9kYXRhX2duZ19hY2MkZ3JvdXApDQpgYGANCg0KSW4gdGhlIGFuYWx5c2lzIG9mIFJUIGFuZCBhY2N1cmFjeSBpbiB0aGUgZ28vbm8tZ28gdGFzaywgdHJpYWxzIHdlcmUgZGlzY2FyZGVkIGlmIFJUIGluIHRoZSBnby9uby1nbyB0YXNrIHdhcyBiZWxvdyAxMDAgbXMgb3IgYWJvdmUgODAwIG1zLCByZXNwb25zZSB3YXMgbWlzc2luZywgb3IgdGhlIHJlc3BvbnNlIHdhcyBtYWRlIHdpdGggYSBrZXkgbm90IGFzc2lnbmVkIHRvIHRoZSBnby9uby1nbyB0YXNrLiBXZSBmdXJ0aGVyIGRpc2NhcmRlZCB0cmlhbHMgY29udGFpbmluZyBhcnRpZmFjdHMgaW4gdGhlIEVFRywgaS5lLiwgYSB2b2x0YWdlIGRpZmZlcmVuY2UgZXhjZWVkaW5nIDIwMCDOvFYgd2l0aGluIGFuIGVwb2NoIG9yIDUwIM68ViBiZXR3ZWVuIHNhbXBsZSBwb2ludHMuIA0KPGJyPjxicj48YnI+DQoNCiMjIERlc2NyaXB0aXZlIFN0YXRpc3RpY3MNCioqKg0KDQpUaGlzIHRhYmxlIGNvcnJlc3BvbmRzIHRvIFRhYmxlIFMyIGluIHRoZSBzdXBwbGVtZW50YWwgbWF0ZXJpYWwuICANCg0KYGBge3IgZGVzY3JpcHRpdmUtc3RhdGlzdGljcy10YWJsZX0NCg0KIyBDYWxjdWxhdGUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBmb3IgUlQNCmRlc2NyaXB0aXZlX3N0YXRpc3RpY3NfcnQgPC0gc3VtbWFyeVNFd2l0aGluTygNCiAgZGF0YSAgICAgICAgICA9IHNpbmdsZV90cmlhbF9kYXRhX2duZ19ydCwNCiAgbWVhc3VyZXZhciAgICA9ICJnbmdfcnQiLA0KICB3aXRoaW52YXJzICAgID0gImduZ19yZXNwb25zZV90eXBlIiwNCiAgYmV0d2VlbnZhcnMgICA9ICJncm91cCIsDQogIGlkdmFyICAgICAgICAgPSAicGFydGljaXBhbnRfaWQiLA0KICBjb25mLmludGVydmFsID0gLjk1KSAlPiUNCiAgIyBSZW5hbWUgdmFyaWFibGUgYW5kIHNlbGVjdCB2YXJpYWJsZXMgZm9yIHN1YnNlcXVlbnQgbWVyZ2luZw0KICBkcGx5cjo6cmVuYW1lKG1lYW4gPSBnbmdfcnQpICU+JQ0KICBkcGx5cjo6c2VsZWN0KCJncm91cCIsICJnbmdfcmVzcG9uc2VfdHlwZSIsICJtZWFuIiwgImNpIikNCg0KDQojIFByZXBhcmUgY2FsY3VsYXRpb24gb2YgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBmb3IgcHJvcG9ydGlvbiBvZiByZXNwb25zZSB0eXBlcyAoYmFzZWQgb24gYWxsIHRyaWFscykNCmRlc2NyaXB0aXZlX3N0YXRpc3RpY3NfcHJvcG9ydGlvbiA8LSBzaW5nbGVfdHJpYWxfZGF0YSAlPiUNCiAgZHBseXI6OmZpbHRlcihzdGltdWxhdGlvbiA9PSAic2hhbSIpICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnkocGFydGljaXBhbnRfaWQsIGdyb3VwKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZSgNCiAgICBTSCAgICAgICAgID0gc3VtKGduZ19yZXNwb25zZV90eXBlID09ICJTSCIpICAgICAgICAvIGxlbmd0aChwYXJ0aWNpcGFudF9pZCkgKiAxMDAsDQogICAgRkggICAgICAgICA9IHN1bShnbmdfcmVzcG9uc2VfdHlwZSA9PSAiRkgiKSAgICAgICAgLyBsZW5ndGgocGFydGljaXBhbnRfaWQpICogMTAwLA0KICAgIEZBICAgICAgICAgPSBzdW0oZ25nX3Jlc3BvbnNlX3R5cGUgPT0gIkZBIikgICAgICAgIC8gbGVuZ3RoKHBhcnRpY2lwYW50X2lkKSAqIDEwMCwNCiAgICBJUiAgICAgICAgID0gc3VtKGduZ19yZXNwb25zZV90eXBlID09ICJJUiIpICAgICAgICAvIGxlbmd0aChwYXJ0aWNpcGFudF9pZCkgKiAxMDAsDQogICAgbWlzc2VzICAgICA9IHN1bShnbmdfcmVzcG9uc2VfdHlwZSA9PSAibWlzcyIpICAgICAgLyBsZW5ndGgocGFydGljaXBhbnRfaWQpICogMTAwLA0KICAgIHdyb25nX2tleSAgPSBzdW0oZ25nX3Jlc3BvbnNlX3R5cGUgPT0gIndyb25nX2tleSIpIC8gbGVuZ3RoKHBhcnRpY2lwYW50X2lkKSAqIDEwMCkgJT4lDQogIGRwbHlyOjp1bmdyb3VwKCkNCg0KDQojIENhbGN1bGF0ZSBkZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGZvciBwcm9wb3J0aW9uIChleGNsdWRlIGZpcnN0IGNvbHVtbiBjb250YWluaW5nIHBhcnRpY2lwYW50IElEKQ0KZGVzY3JpcHRpdmVfc3RhdGlzdGljc19wcm9wb3J0aW9uIDwtIGRlc2NyaXB0aXZlX3N0YXRpc3RpY3NfcHJvcG9ydGlvblssIC1jKDEpXSAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KGdyb3VwKSAlPiUNCiAgZG8oZGF0YS5mcmFtZSh0KHN0YXQuZGVzYyguKSkpKSAlPiUNCiAgbmEub21pdCgpICU+JQ0KICBkcGx5cjo6dW5ncm91cCgpICU+JQ0KICAjIENyZWF0ZSByZXNwb25zZSB0eXBlIGNvbHVtbiwgcmVuYW1lIHZhcmlhYmxlLCBhbmQgc2VsZWN0IHZhcmlhYmxlcyBmb3Igc3Vic2VxdWVudCBtZXJnaW5nDQogIGRwbHlyOjptdXRhdGUoZ25nX3Jlc3BvbnNlX3R5cGUgPSByZXAoYygiU0ggIiwiRkggIiwiRkEgIiwiSVIiLCAiTWlzc2luZyByZXNwb25zZSIsICJXcm9uZyBrZXkgcmVzcG9uc2UiKSwyKSkgJT4lDQogIGRwbHlyOjpyZW5hbWUoY2kgPSBDSS5tZWFuKSAlPiUNCiAgZHBseXI6OnNlbGVjdCgiZ3JvdXAiLCAiZ25nX3Jlc3BvbnNlX3R5cGUiLCAibWVhbiIsICJjaSIpDQoNCg0KIyBDb21iaW5lIG1lYXN1cmVzDQpkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzIDwtIGFzLmRhdGEuZnJhbWUocmJpbmQoZGVzY3JpcHRpdmVfc3RhdGlzdGljc19ydCwgZGVzY3JpcHRpdmVfc3RhdGlzdGljc19wcm9wb3J0aW9uKSkNCg0KDQojIENyZWF0ZSBjb2x1bW4gd2l0aCBmb3JtYXQgIk0gW0NJXSIgZm9yIFJUIChyb3VuZCB0byAwIGRlY2ltYWxzKQ0KZGVzY3JpcHRpdmVfc3RhdGlzdGljcyRNX0NJIDwtIHBhc3RlMChyb3VuZChkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzJG1lYW4sIDApLCAiIFsiLA0KICByb3VuZChkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzJG1lYW4gLSBkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzJGNpLCAwKSwgIiwgIiwNCiAgcm91bmQoZGVzY3JpcHRpdmVfc3RhdGlzdGljcyRtZWFuICsgZGVzY3JpcHRpdmVfc3RhdGlzdGljcyRjaSwgMCksICJdIikNCg0KDQojIENyZWF0ZSBjb2x1bW4gd2l0aCBmb3JtYXQgIk0gW0NJXSIgZm9yIGFjY3VyYWN5IChyb3VuZCB0byAyIGRlY2ltYWxzKQ0KZGVzY3JpcHRpdmVfc3RhdGlzdGljc1tjKDc6MTgpLCBdJE1fQ0kgPC0gcGFzdGUwKA0KICBmb3JtYXQocm91bmQoZGVzY3JpcHRpdmVfc3RhdGlzdGljc1tjKDc6MTgpLCBdJG1lYW4sIDIpLCBuc21hbGwgPSAyKSwgIiBbIiwNCiAgZm9ybWF0KHJvdW5kKGRlc2NyaXB0aXZlX3N0YXRpc3RpY3NbYyg3OjE4KSwgXSRtZWFuIC0NCiAgICAgICAgICAgICAgIGRlc2NyaXB0aXZlX3N0YXRpc3RpY3NbYyg3OjE4KSwgXSRjaSwgICAyKSwgbnNtYWxsID0gMiksICIsICIsDQogIGZvcm1hdChyb3VuZChkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzW2MoNzoxOCksIF0kbWVhbiArDQogICAgICAgICAgICAgICBkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzW2MoNzoxOCksIF0kY2ksICAgMiksIG5zbWFsbCA9IDIpLCAiXSIpDQoNCg0KIyBTcGxpdCBhbmQgcmUtbWVyZ2UgdGFibGUgdG8gZGlzcGxheSBib3RoIGdyb3VwcyBuZXh0IHRvIGVhY2ggb3RoZXINCmRlc2NyaXB0aXZlX3N0YXRpc3RpY3MgPC0gc3BsaXQoZGVzY3JpcHRpdmVfc3RhdGlzdGljcywgZGVzY3JpcHRpdmVfc3RhdGlzdGljcyRncm91cCkNCmRlc2NyaXB0aXZlX3N0YXRpc3RpY3NfZGlzcGxheSA8LSBjYmluZChkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzJE9DRFssIGMoImduZ19yZXNwb25zZV90eXBlIiwgIk1fQ0kiKV0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpdmVfc3RhdGlzdGljcyRIQ1ssICJNX0NJIl0pDQoNCg0KIyBEaXNwbGF5IHRhYmxlIChhbmQgcmVhcnJhbmdlIHJvd3MpDQpteV90YWJsZV90ZW1wbGF0ZShkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzX2Rpc3BsYXlbYygzOjEsIDQ6OSksIF0sDQogIGNhcHRpb24gPSAiRGVzY3JpcHRpdmUgU3RhdGlzdGljcyBmb3IgQmVoYXZpb3JhbCBQZXJmb3JtYW5jZSBpbiB0aGUgR28vTm8tR28gVGFzayIsDQogIGNvbF9uYW1lcyA9IGMoIk1lYXN1cmUiLCByZXAoIk0gWzk1JSBDSV0iLCAyKSksDQogIGhlYWRlcl9hYm92ZV9jb25maWcgPSBjKCIiLCAiUGF0aWVudHMgd2l0aCBPQ0QiLCAiSGVhbHRoeSBjb250cm9sIHBhcnRpY2lwYW50cyIpKSAlPiUNCiAgYWRkX2Zvb3Rub3RlKCJcbiBOb3RlLiBDSXMgYXJlIGFkanVzdGVkIGZvciB3aXRoaW4tcGFydGljaXBhbnQgY29tcGFyaXNvbnMgdXNpbmcgdGhlIG1ldGhvZCBkZXNjcmliZWQgDQogIGJ5IE1vcmV5ICgyMDA4KS4iLCBub3RhdGlvbiA9ICJub25lIikgJT4lDQogIHBhY2tfcm93cygiUmVzcG9uc2UgdGltZSAobXMpIiwgMSwgMykgJT4lDQogIHBhY2tfcm93cygiUHJvcG9ydGlvbiBvZiByZXNwb25zZXMgKCUpIiwgNCwgOSkNCmBgYA0KDQpgYGB7ciBmYXN0LWhpdC1yZXNwb25zZS10aW1lLWxpbWl0fQ0KDQojIERlZmluZSBkYXRhIGJhc2lzIChhbGwgZ28gdHJpYWxzLCBlcXVpdmFsZW50IHRvIGNhbGN1bGF0aW9uIGluIHRhc2sgcHJvZ3JhbSkgDQpzaW5nbGVfdHJpYWxfZGF0YV9ydF9saW1pdCA8LSBzaW5nbGVfdHJpYWxfZGF0YSAlPiUNCiAgZHBseXI6OmZpbHRlcigNCiAgICBnbmdfcmVzcG9uc2VfdHlwZSAhPSAiRkEiICYgDQogICAgZ25nX3Jlc3BvbnNlX3R5cGUgIT0gIklSIiAmDQogICAgZ25nX3Jlc3BvbnNlX3R5cGUgIT0gIm1pc3MiICYNCiAgICBnbmdfcmVzcG9uc2VfdHlwZSAhPSAid3Jvbmdfa2V5IiAmIA0KICAgIHN0aW11bGF0aW9uID09ICJzaGFtIikNCg0KDQojIEFkZCBibG9jayB2YXJpYWJsZQ0Kc2luZ2xlX3RyaWFsX2RhdGFfcnRfbGltaXQgPC0gc2luZ2xlX3RyaWFsX2RhdGFfcnRfbGltaXQgJT4lDQogIGRwbHlyOjptdXRhdGUoYmxvY2sgPSBpZmVsc2UodHJpYWwgPCAyOSwgMSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoKHRyaWFsID4gMjggJiB0cmlhbCA8IDEwMSksIDIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoKHRyaWFsID4gMTAwICYgdHJpYWwgPCAxNzMpLCAzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSgodHJpYWwgPiAxNzIgJiB0cmlhbCA8IDIwMSksIDQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoKHRyaWFsID4gMjAwICYgdHJpYWwgPCAyNzMpLCA1LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKCh0cmlhbCA+IDI3MiAmIHRyaWFsIDwgMzQ1KSwgNiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZSgodHJpYWwgPiAzNDQgJiB0cmlhbCA8IDM3MyksIDcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoKHRyaWFsID4gMzcyICYgdHJpYWwgPCA0NDUpLCA4LCA5KSkpKSkpKSkpDQoNCg0KIyBHZXQgbWVhbiBSVCBwZXIgYmxvY2sNCm1lYW5fcnRfcGVyX2Jsb2NrIDwtIHNpbmdsZV90cmlhbF9kYXRhX3J0X2xpbWl0ICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnkocGFydGljaXBhbnRfaWQsIGJsb2NrKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShtZWFuX3J0ID0gbWVhbihnbmdfcnQpKSAlPiUNCiAgZHBseXI6OnVuZ3JvdXAoKQ0KDQoNCiMgQ2FsY3VsYXRlIGZhc3QgaGl0IHJlc3BvbnNlIHRpbWUgbGltaXQgaW4gY2FsaWJyYXRpb24gYmxvY2tzIDEsIDQsIGFuZCA3DQptZWFuX3J0X3Blcl9ibG9jayA8LSBtZWFuX3J0X3Blcl9ibG9jayAlPiUgDQogIGRwbHlyOjpmaWx0ZXIoYmxvY2sgPT0gMSB8IGJsb2NrID09IDQgfCBibG9jayA9PSA3KSAlPiUgDQogIGRwbHlyOjptdXRhdGUoZmhfdGltZSA9IGlmZWxzZShibG9jayA9PSAxLCBtZWFuX3J0ICogMC44LCBtZWFuX3J0ICogMC45KSwNCiAgICAgICAgICAgICAgICBncm91cCAgID0gYXMuZmFjdG9yKGlmZWxzZShzdWJzdHIocGFydGljaXBhbnRfaWQsIDEsIDEpID09ICJDIiwgIkhDIiwgIk9DRCIpKSkgDQoNCg0KIyBDYWxjdWxhdGUgbWVhbiwgc2QsIG1pbiwgYW5kIG1heCBvZiBmYXN0IGhpdCByZXNwb25zZSB0aW1lIGxpbWl0IHBlciBncm91cA0KZmhfdGltZSA8LSBtZWFuX3J0X3Blcl9ibG9jayAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KGdyb3VwKSAlPiUgDQogIGRwbHlyOjpzdW1tYXJpemUoTSA9IG1lYW4oZmhfdGltZSksIFNEID0gc2QoZmhfdGltZSksIG1pbiA9IG1pbihmaF90aW1lKSwgbWF4ID0gbWF4KGZoX3RpbWUpKSAlPiUNCiAgZHBseXI6OnVuZ3JvdXAoKSANCg0KDQojIFJvdW5kIHZhbHVlcw0KZmhfdGltZVssIGMoMjo1KV0gPC0gcm91bmQoZmhfdGltZVssIGMoMjo1KV0sIGRpZ2l0cyA9IDApDQoNCg0KIyBEaXNwbGF5IHRhYmxlIA0KbXlfdGFibGVfdGVtcGxhdGUoZmhfdGltZSwgY2FwdGlvbiA9ICJGYXN0IEhpdCBSZXNwb25zZSBUaW1lIExpbWl0IiwNCiAgY29sX25hbWVzID0gYygiR3JvdXAiLCAiTSIsICJTRCIsICJtaW4iLCAibWF4IikpDQpgYGANCjxicj48YnI+DQoNCiMjIEFuYWx5c2lzIG9mIFJlc3BvbnNlIFRpbWUgey50YWJzZXR9DQoqKioNCg0KV2UgcGVyZm9ybWVkIGEgbGluZWFyIG1peGVkIG1vZGVsIChMTU0pIG9uIHNpbmdsZS10cmlhbCBkYXRhLiBBbmFseXNpcyBvZiBSVCBpbiB0aGUgZ28vbm8tZ28gdGFzayBpbmNsdWRlZCBncm91cCBhbmQgcmVzcG9uc2UgdHlwZSAoc2xvdyBoaXQsIGZhc3QgaGl0LCBmYWxzZSBhbGFybSkgYXMgZml4ZWQgZWZmZWN0cy4gDQoNCldlIHVzZWQgc2xpZGluZyBkaWZmZXJlbmNlIGNvbnRyYXN0cyBmb3IgY2F0ZWdvcmljYWwgZml4ZWQgZWZmZWN0cyBhbmQgc3RhcnRlZCB3aXRoIHRoZSBtYXhpbWFsIHJhbmRvbS1lZmZlY3RzIHN0cnVjdHVyZSBmb3IgZWFjaCBtb2RlbC4gSW4gY2FzZSBvZiBub24tY29udmVyZ2VuY2UsIHJhbmRvbSBlZmZlY3RzIHdlcmUgc3BlY2lmaWVkIGFzIHVuY29ycmVsYXRlZC4gVXNpbmcgcHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcywgd2UgaWRlbnRpZmllZCByYW5kb20gZWZmZWN0cyBleHBsYWluaW5nIHplcm8gdmFyaWFuY2UgYW5kIHJlbW92ZWQgdGhlc2UsIGFzIHJlY29tbWVuZGVkIGJ5IEJhdGVzLCBLbGllZ2wsIGV0IGFsLiAoMjAxNSkuIA0KPGJyPjxicj4NCg0KIyMjIERldGVybWluZSBEYXRhIFRyYW5zZm9ybWF0aW9uDQoNClJUIHdhcyBsb2ctdHJhbnNmb3JtZWQgdG8gbm9ybWFsaXplIHJlc2lkdWFscy4gVGhpcyB3YXMgZGV0ZXJtaW5lZCB1c2luZyB0aGUgQm944oCTQ294IHByb2NlZHVyZSAoQm94ICYgQ294LCAxOTY0KS4NCg0KYGBge3IgcnQtZGV0ZXJtaW5lLXRyYW5zZm9ybWF0aW9uLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodCA9IDN9DQoNCiMgQXJyYW5nZSBwbG90cw0KcGFyKG1mcm93ID0gYygxLCA1KSkNCg0KDQojIERldGVybWluZSB0cmFuc2Zvcm1hdGlvbiBieSBlc3RpbWF0aW5nIG9wdGltYWwgbGFtYmRhIHVzaW5nIEJveOKAk0NveCBwcm9jZWR1cmUNCmJjX3J0IDwtIGJveGNveChnbmdfcnQgfiAxLCBkYXRhID0gc2luZ2xlX3RyaWFsX2RhdGFfZ25nX3J0KQ0Kb3B0bGFtYmRhX3J0IDwtIGJjX3J0JHhbd2hpY2gubWF4KGJjX3J0JHkpXQ0KDQoNCiMgRGVuc2l0eSBwbG90IGZvciByYXcgUlQNCnBsb3QoZGVuc2l0eShzaW5nbGVfdHJpYWxfZGF0YV9nbmdfcnQkZ25nX3J0KSwgbWFpbiA9ICJSYXcgUlQ6IERlbnNpdHkgUGxvdCIpDQoNCg0KIyBRLXEgcGxvdCBmb3IgcmF3IFJUDQpxcW5vcm0oc2luZ2xlX3RyaWFsX2RhdGFfZ25nX3J0JGduZ19ydCwgbWFpbiA9ICJSYXcgUlQ6IFEtUSBQbG90IiwgcGNoID0gMSkNCg0KDQojIERlbnNpdHkgcGxvdCBmb3IgbG9nIFJUDQpwbG90KGRlbnNpdHkoc2luZ2xlX3RyaWFsX2RhdGFfZ25nX3J0JGduZ19ydF9sb2cpLCBtYWluID0gIkxvZyBSVDogRGVuc2l0eSBQbG90IikNCg0KDQojIFEtcSBwbG90IGZvciBsb2cgUlQNCnFxbm9ybShzaW5nbGVfdHJpYWxfZGF0YV9nbmdfcnQkZ25nX3J0X2xvZywgbWFpbiA9ICJMb2cgUlQ6IFEtUSBQbG90IiwgcGNoID0gMSkNCg0KDQojIFJlc2V0IHBsb3QgbGF5b3V0DQpwYXIobWZyb3cgPSBjKDEsIDEpKQ0KYGBgDQpUaGUgb3B0aW1hbCBsYW1iZGEgaXMgYHIgcm91bmQob3B0bGFtYmRhX3J0LCBkaWdpdHMgPSAyKWAsIHN1Z2dlc3RpbmcgdGhhdCBsb2cgdHJhbnNmb3JtYXRpb24gaXMgYXBwcm9wcmlhdGUuIA0KPGJyPjxicj48YnI+DQoNCiMjIyBMTU0gey5hY3RpdmV9DQoNClRoaXMgdGFibGUgY29ycmVzcG9uZHMgdG8gVGFibGUgMiBpbiB0aGUgbWFudXNjcmlwdC4gDQoNCmBgYHtyIGxtbS1ydH0NCg0KIyBEZWZpbmUgY29udHJhc3RzIChzbGlkaW5nIGRpZmZlcmVuY2UgY29udHJhc3RzID0gZWZmZWN0IGNvZGluZyBmb3IgZmFjdG9ycyB3aXRoIDIgbGV2ZWxzKQ0KY29udHJhc3RzKHNpbmdsZV90cmlhbF9kYXRhX2duZ19ydCRnbmdfcmVzcG9uc2VfdHlwZSkgPC0gY29udHIuc2RpZigzKQ0KY29udHJhc3RzKHNpbmdsZV90cmlhbF9kYXRhX2duZ19ydCRncm91cCkgICAgICAgICAgICAgPC0gY29udHIuc2RpZigyKQ0KDQoNCiMgUnVuIG1vZGVsIHdpdGggbWF4aW1hbCByYW5kb20tZWZmZWN0cyBzdHJ1Y3R1cmUNCkxNTV9nbmdfcnQgPC0gbG1lcihnbmdfcnRfbG9nIH4gZ25nX3Jlc3BvbnNlX3R5cGUgKiBncm91cCArDQogICgxICsgZ25nX3Jlc3BvbnNlX3R5cGUgfCBwYXJ0aWNpcGFudF9pZCksDQogIGRhdGEgPSBzaW5nbGVfdHJpYWxfZGF0YV9nbmdfcnQsDQogIFJFTUwgPSBUUlVFLA0KICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIpKQ0KDQoNCiMgQ2hlY2sgbW9kZWwgb3V0cHV0IGFuZCBQQ0Egb2YgcmFuZG9tLWVmZmVjdHMgdmFyaWFuY2UtY292YXJpYW5jZSBlc3RpbWF0ZXMNCiMgc3VtbWFyeShMTU1fZ25nX3J0KSAgICAgICAgIyBNb2RlbCBkb2VzIGNvbnZlcmdlDQojIGlzU2luZ3VsYXIoTE1NX2duZ19ydCkgICAgICMgTm8gc2luZ3VsYXIgZml0DQojIHN1bW1hcnkocmVQQ0EoTE1NX2duZ19ydCkpICMgQWxsIHRlcm1zIGV4cGxhaW4gdmFyaWFuY2UNCg0KDQojIERpc3BsYXkgcmVzdWx0cyAoZml4ZWQgZWZmZWN0cykNCnRhYl9tb2RlbChMTU1fZ25nX3J0LA0KICBkdi5sYWJlbHMgPSAiUlQiLCBwcmVkLmxhYmVscyA9IGxhYmVscywgc2hvdy5zdGF0ID0gVFJVRSwgc2hvdy5pY2MgPSBGQUxTRSwgc2hvdy5yMiA9IEZBTFNFLA0KICBzaG93LnJlLnZhciA9IEZBTFNFLCBzaG93Lm5ncm91cHMgPSBGQUxTRSwgbWludXMuc2lnbiA9ICItIiwgc3RyaW5nLnByZWQgPSAiRml4ZWQgZWZmZWN0cyIsDQogIHN0cmluZy5lc3QgPSAiYiIsIHN0cmluZy5zdGF0ID0gInQiLCBzdHJpbmcuY2kgPSAiOTUgJSBDSSIsIHAudmFsID0gInNhdHRlcnRod2FpdGUiLA0KICB0aXRsZSA9ICJMTU0gUmVzdWx0cyBmb3IgUlQgaW4gdGhlIEdvL05vLUdvIFRhc2siKQ0KDQoNCiMgRGlzcGxheSByYW5kb20gZWZmZWN0cw0KcHJpbnQoIlJhbmRvbSBlZmZlY3RzOiIpDQpwcmludChWYXJDb3JyKExNTV9nbmdfcnQpLCBkaWdpdHMgPSAxLCBjb21wID0gIlN0ZC5EZXYuIikNCmBgYA0KPGJyPg0KUlRzIHdlcmUgc2hvcnRlciBmb3IgZmFzdCBoaXRzIHRoYW4gZm9yIHNsb3cgaGl0cyBhbmQgZmFsc2UgYWxhcm1zLiBUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgZ3JvdXAgZGlmZmVyZW5jZSBpbiBSVC4gDQo8YnI+PGJyPjxicj4NCg0KIyMgQW5hbHlzaXMgb2YgQWNjdXJhY3kgey50YWJzZXR9DQoqKioNCg0KV2UgcGVyZm9ybWVkIGEgYmlub21pYWwgZ2VuZXJhbGl6ZWQgbGluZWFyIG1peGVkIG1vZGVsIChHTE1NKSBvbiBzaW5nbGUtdHJpYWwgZGF0YS4gQW5hbHlzaXMgb2YgYWNjdXJhY3kgaW4gdGhlIGdvL25vLWdvIHRhc2sgaW5jbHVkZWQgZ3JvdXAgYXMgZml4ZWQgZWZmZWN0LiANCg0KV2UgdXNlZCBzbGlkaW5nIGRpZmZlcmVuY2UgY29udHJhc3RzIGZvciBjYXRlZ29yaWNhbCBmaXhlZCBlZmZlY3RzIGFuZCBzdGFydGVkIHdpdGggdGhlIG1heGltYWwgcmFuZG9tLWVmZmVjdHMgc3RydWN0dXJlIGZvciBlYWNoIG1vZGVsLiBJbiBjYXNlIG9mIG5vbi1jb252ZXJnZW5jZSwgcmFuZG9tIGVmZmVjdHMgd2VyZSBzcGVjaWZpZWQgYXMgdW5jb3JyZWxhdGVkLiBVc2luZyBwcmluY2lwYWwgY29tcG9uZW50IGFuYWx5c2lzLCB3ZSBpZGVudGlmaWVkIHJhbmRvbSBlZmZlY3RzIGV4cGxhaW5pbmcgemVybyB2YXJpYW5jZSBhbmQgcmVtb3ZlZCB0aGVzZSwgYXMgcmVjb21tZW5kZWQgYnkgQmF0ZXMsIEtsaWVnbCwgZXQgYWwuICgyMDE1KS4gDQo8YnI+PGJyPg0KDQojIyMgR0xNTQ0KDQpUaGlzIHRhYmxlIGNvcnJlc3BvbmRzIHRvIFRhYmxlIDIgaW4gdGhlIG1hbnVzY3JpcHQuICANCg0KYGBge3IgZ2xtbS1hY2N1cmFjeX0NCg0KIyBEZWZpbmUgY29udHJhc3RzIChzbGlkaW5nIGRpZmZlcmVuY2UgY29udHJhc3RzID0gZWZmZWN0IGNvZGluZyBmb3IgZmFjdG9ycyB3aXRoIDIgbGV2ZWxzKQ0KY29udHJhc3RzKHNpbmdsZV90cmlhbF9kYXRhX2duZ19hY2MkZ3JvdXApIDwtIGNvbnRyLnNkaWYoMikNCg0KDQojIFJ1biBtb2RlbCB3aXRoIG1heGltYWwgcmFuZG9tLWVmZmVjdHMgc3RydWN0dXJlDQpHTE1NX2duZ19hY2MgPC0gZ2xtZXIoZ25nX2FjY3VyYWN5X251bWVyaWMgfiBncm91cCArICgxIHwgcGFydGljaXBhbnRfaWQpLA0KICBkYXRhID0gc2luZ2xlX3RyaWFsX2RhdGFfZ25nX2FjYywNCiAgZmFtaWx5ID0gYmlub21pYWwsDQogIGNvbnRyb2wgPSBnbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIpKQ0KDQoNCiMgQ2hlY2sgbW9kZWwgb3V0cHV0IGFuZCBQQ0Egb2YgcmFuZG9tLWVmZmVjdHMgdmFyaWFuY2UtY292YXJpYW5jZSBlc3RpbWF0ZXMNCiMgc3VtbWFyeShHTE1NX2duZ19hY2MpICAgICAgICAjIE1vZGVsIGRvZXMgY29udmVyZ2UNCiMgaXNTaW5ndWxhcihHTE1NX2duZ19hY2MpICAgICAjIE5vIHNpbmd1bGFyIGZpdA0KIyBzdW1tYXJ5KHJlUENBKEdMTU1fZ25nX2FjYykpICMgQWxsIHRlcm1zIGV4cGxhaW4gdmFyaWFuY2UNCg0KDQojIERpc3BsYXkgcmVzdWx0cyAoZml4ZWQgZWZmZWN0cykNCnRhYl9tb2RlbChHTE1NX2duZ19hY2MsDQogIGR2LmxhYmVscyA9ICJBY2N1cmFjeSIsIHByZWQubGFiZWxzID0gbGFiZWxzLCBzaG93LnN0YXQgPSBUUlVFLCBzaG93LmljYyA9IEZBTFNFLCBzaG93LnIyID0gRkFMU0UsDQogIHNob3cucmUudmFyID0gRkFMU0UsIHNob3cubmdyb3VwcyA9IEZBTFNFLCBtaW51cy5zaWduID0gIi0iLCBzdHJpbmcucHJlZCA9ICJGaXhlZCBlZmZlY3RzIiwNCiAgc3RyaW5nLmVzdCA9ICJPZGRzIHJhdGlvIiwgc3RyaW5nLnN0YXQgPSAieiIsIHN0cmluZy5jaSA9ICI5NSAlIENJIiwgDQogIHRpdGxlID0gIkdMTU0gUmVzdWx0cyBmb3IgQWNjdXJhY3kgaW4gdGhlIEdvL05vLUdvIFRhc2siKQ0KDQoNCiMgRGlzcGxheSByYW5kb20gZWZmZWN0cw0KcHJpbnQoIlJhbmRvbSBlZmZlY3RzOiIpDQpwcmludChWYXJDb3JyKEdMTU1fZ25nX2FjYyksIGRpZ2l0cyA9IDIsIGNvbXAgPSAiU3RkLkRldi4iKQ0KYGBgDQo8YnI+DQpUaGVyZSB3YXMgbm8gc2lnbmlmaWNhbnQgZ3JvdXAgZGlmZmVyZW5jZSBpbiBhY2N1cmFjeS4gDQo8YnI+PGJyPjxicj4NCg0KIyMgUmVmZXJlbmNlcw0KKioqDQpCYXRlcywgRC4sIEtsaWVnbCwgUi4sIFZhc2lzaHRoLCBTLiwgJiBCYWF5ZW4sIEguICgyMDE1KS4gKlBhcnNpbW9uaW91cyBtaXhlZCBtb2RlbHMuKiBhclhpdi4gaHR0cHM6Ly9hcnhpdi5vcmcvYWJzLzE1MDYuMDQ5Njd2MiA8YnI+PGJyPg0KQm94LCBHLiBFLiwgJiBDb3gsIEQuIFIuICgxOTY0KS4gQW4gYW5hbHlzaXMgb2YgdHJhbnNmb3JtYXRpb25zLiAqSm91cm5hbCBvZiB0aGUgUm95YWwgU3RhdGlzdGljYWwgU29jaWV0eTogU2VyaWVzIEIgKE1ldGhvZG9sb2dpY2FsKSwgMjYqKDIpLCAyMTHigJMyNDMuIGh0dHBzOi8vZG9pLm9yZy8xMC4xMTExL2ouMjUxNy02MTYxLjE5NjQudGIwMDU1My54IDxicj48YnI+DQpNb3JleSwgUi4gKDIwMDgpLiBDb25maWRlbmNlIGludGVydmFscyBmcm9tIG5vcm1hbGl6ZWQgZGF0YTogQSBjb3JyZWN0aW9uIHRvIENvdXNpbmVhdSAoMjAwNSkuICpUdXRvcmlhbHMgaW4gUXVhbnRpdGF0aXZlIE1ldGhvZHMgZm9yIFBzeWNob2xvZ3ksIDQqKDIpLCA2MeKAkzY0LiBodHRwczovL2RvaS5vcmcvMTAuMjA5ODIvdHFtcC4wNC4yLnAwNjEgDQo8YnI+PGJyPjxicj4NCg0KIyMgU2Vzc2lvbiBJbmZvDQoqKioNCmBgYHtyIHNlc3Npb24taW5mb30NCg0Kc2Vzc2lvbkluZm8oKQ0KYGBgDQo=