# 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(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
library(splithalf)  # for permutation-based split-half reliability


# 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 LMM tables
labels <- c(
  "(Intercept)" = "Intercept",
  "group2-1"    = "Group (OCD – HC)")


Data Cleaning


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


# For ERP analysis, exclude inhibited gng responses, missing gng responses, gng responses with
# wrong key, gng RT outliers, and trials with ERP artifacts
single_trial_data_erp <- 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)


# Create accuracy variable ("incorrect" = FA; "correct" = SH, FH)
single_trial_data_erp <- single_trial_data_erp %>%
  dplyr::mutate(gng_accuracy = ifelse(gng_response_type == "FA", "incorrect", "correct"))


# Calculate % of excluded trials per participant
excluded_trials_per_participant <- single_trial_data %>%
  dplyr::filter(stimulation == "sham") %>%
  dplyr::group_by(participant_id) %>%
  dplyr::summarize(EEG_artifact = sum(is.nan(MFN_0_100_FCz)) / length(participant_id) * 100) %>%
  dplyr::ungroup() %>%
  dplyr::summarize(across(-c(participant_id), list(mean, sd)))


# Calculate number of remaining trials per participant
remaining_trials_per_participant <- single_trial_data_erp %>%
  dplyr::group_by(participant_id, gng_accuracy) %>%
  dplyr::summarize(n = n()) %>%
  dplyr::group_by(gng_accuracy) %>% 
  dplyr::summarize(mean = mean(n), sd = sd(n)) %>%
  dplyr::ungroup() 


# Make categorical variables factors
single_trial_data_erp$participant_id <- factor(single_trial_data_erp$participant_id)
single_trial_data_erp$group          <- factor(single_trial_data_erp$group)

In the analysis of ERPs 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, resulting in rejection of 0.58% (SD = 1.21) of epochs on average (remaining trials per participant for ERN analysis: M = 44.71, SD = 23.65; for CRN analysis: M = 333.21, SD = 17.67).


Descriptive Statistics


This table corresponds to Table S2 in the supplemental material.

# Calculate descriptive statistics for ERN/CRN
descriptive_statistics <- summarySEwithinO(
  data          = single_trial_data_erp,
  measurevar    = "MFN_0_100_FCz",
  withinvars    = "gng_accuracy",
  betweenvars   = "group",
  idvar         = "participant_id",
  conf.interval = .95) %>%
  # Rename variable and create measure variable
  dplyr::rename(mean = MFN_0_100_FCz) %>%
  dplyr::mutate(measure = rep(c("CRN (µV)", "ERN (µV)"), 2))


# Create column with format "M [CI]" (round to 2 decimals)
descriptive_statistics$M_CI <- paste0(
  format(round(descriptive_statistics$mean, 2), nsmall = 2), " [",
  format(round(descriptive_statistics$mean -
               descriptive_statistics$ci,   2), nsmall = 2), ", ",
  format(round(descriptive_statistics$mean +
               descriptive_statistics$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("measure", "M_CI")],
                                        descriptive_statistics$HC[, "M_CI"])


# Display table (and rearrange rows)
my_table_template(descriptive_statistics_display[c(2, 1), ],
  caption = "Descriptive Statistics for ERP Measures",
  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). ERN and CRN were measured as mean amplitude 
  from 0 to 100 ms at electrode FCz after false alarms and hits, respectively.", notation = "none") 
Descriptive Statistics for ERP Measures
Patients with OCD
Healthy control participants
Measure M [95% CI] M [95% CI]
ERN (µV) -2.21 [-2.89, -1.53] -2.15 [-2.90, -1.41]
CRN (µV) 2.38 [ 2.15, 2.61] 2.33 [ 2.10, 2.55]

Note. CIs are adjusted for within-participant comparisons using the method
described by Morey (2008). ERN and CRN were measured as mean amplitude
from 0 to 100 ms at electrode FCz after false alarms and hits, respectively.



Split-Half Reliability


# Calculate permutation-based split-half internal consistency for ERN/CRN
invisible(capture.output(split_half_reliability <- splithalf(
  data = single_trial_data_erp,
  outcome = "RT",
  score = "average",
  permutations = 5000,
  halftype = "random",
  var.RT = "MFN_0_100_FCz",
  var.participant = "participant_id",
  var.condition = "gng_accuracy",
  conditionlist = c("correct", "incorrect"),
  average = "mean")))


# Make nice table for display
split_half_reliability <- cbind(ERP = c("CRN", "ERN"), split_half_reliability$final_estimates) %>%
  dplyr::select(ERP, spearmanbrown, SB_low, SB_high) %>%
  dplyr::rename(r = spearmanbrown, CI_low = SB_low, CI_up = SB_high)


# Display permutation-based split-half internal consistency
my_table_template(split_half_reliability[c(2, 1), ],
  caption = "Permutation-based split-half reliability")
Permutation-based split-half reliability
ERP r CI_low CI_up
ERN 0.89 0.82 0.94
CRN 0.98 0.98 0.99

Internal consistency was good for ERN (r = 0.89, 95% CI [0.82, 0.94]) and excellent for CRN (r = 0.98, 95% CI [0.98, 0.99]), as assessed with a permutation-based split-half method using 5,000 random splits and Spearman–Brown correction.


Analysis of ERN & CRN


We performed linear mixed models (LMMs) on single-trial data. Analysis of ERP amplitudes in the go/no-go task included group as fixed effect. Models on ERN and CRN were based on false alarm and hit trials, respectively.

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

No data transformation was required to meet the assumption of normally distributed residuals. This was determined using the Box–Cox procedure (Box & Cox, 1964).

# Arrange plots
par(mfrow = c(2, 3))


# Determine transformation of ERN by estimating optimal lambda using Box–Cox procedure
bc_ern <- boxcox(MFN_0_100_FCz + 50 ~ 1,
  data = single_trial_data_erp[single_trial_data_erp$gng_accuracy == "incorrect", ])
optlambda_ern <- bc_ern$x[which.max(bc_ern$y)]


# Density plot for ERN values
plot(density(single_trial_data_erp[single_trial_data_erp$gng_accuracy == "incorrect", ]$MFN_0_100_FCz),
  main = "ERN: Density Plot")


# Q-q plot for ERN values
qqnorm(single_trial_data_erp[single_trial_data_erp$gng_accuracy == "incorrect", ]$MFN_0_100_FCz,
  main = "ERN: Q-Q Plot", pch = 1)


# Determine transformation of CRN by estimating optimal lambda using Box–Cox procedure
bc_crn <- boxcox(MFN_0_100_FCz + 50 ~ 1,
  data = single_trial_data_erp[single_trial_data_erp$gng_accuracy == "correct", ])
optlambda_crn <- bc_crn$x[which.max(bc_crn$y)]


# Density plot for CRN values
plot(density(single_trial_data_erp[single_trial_data_erp$gng_accuracy == "correct", ]$MFN_0_100_FCz),
  main = "CRN: Density Plot")


# Q-q plot for CRN values
qqnorm(single_trial_data_erp[single_trial_data_erp$gng_accuracy == "correct", ]$MFN_0_100_FCz,
  main = "CRN: Q-Q Plot", pch = 1)

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

For the ERN, the optimal lambda is 1.03 (upper left plot), suggesting that no transformation is needed. For the CRN, the optimal lambda is 0.99 (lower left plot), suggesting that no transformation is needed.


LMM on ERN & CRN

This table corresponds to Table 5 in the manuscript.

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


# Run model on ERN with maximal random-effects structure
LMM_ern <- lmer(MFN_0_100_FCz ~ group + (1 | participant_id),
  data = single_trial_data_erp[single_trial_data_erp$gng_accuracy == "incorrect", ],
  REML = TRUE,
  control = lmerControl(optimizer = "bobyqa"))


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


# Run model on CRN with maximal random-effects structure
LMM_crn <- lmer(MFN_0_100_FCz ~ group + (1 | participant_id),
  data = single_trial_data_erp[single_trial_data_erp$gng_accuracy == "correct", ],
  REML = TRUE,
  control = lmerControl(optimizer = "bobyqa"))


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


# Display results (fixed effects)
tab_model(LMM_ern, LMM_crn,
  dv.labels = c("ERN", "CRN"), 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 ERN and CRN in the Go/No-Go Task")


# Display random effects
print("Random effects ERN:")
print(VarCorr(LMM_ern), digits = 3, comp = "Std.Dev.")


# Display random effects
print("Random effects CRN:")
print(VarCorr(LMM_crn), digits = 3, comp = "Std.Dev.")
LMM Results for ERN and CRN in the Go/No-Go Task
  ERN CRN
Fixed effects b 95 % CI t p b 95 % CI t p
Intercept -2.65 -3.93 – -1.37 -4.15 <0.001 2.33 1.41 – 3.25 5.07 <0.001
Group (OCD – HC) 0.52 -2.04 – 3.09 0.41 0.684 0.05 -1.79 – 1.89 0.05 0.956
Observations 2504 18660
[1] "Random effects ERN:"
 Groups         Name        Std.Dev.
 participant_id (Intercept) 4.55    
 Residual                   8.50    
[1] "Random effects CRN:"
 Groups         Name        Std.Dev.
 participant_id (Intercept) 3.41    
 Residual                   7.98    


ERN and CRN amplitudes did not differ significantly between groups.


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       splithalf_0.8.2  sjPlot_2.8.11    lmerTest_3.1-3  
 [5] lme4_1.1-25      Matrix_1.5-1     MASS_7.3-51.4    kableExtra_1.3.4
 [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         robustbase_0.95-0   yaml_2.2.1         
[16] bayestestR_0.13.0   numDeriv_2016.8-1.1 pillar_1.8.1       
[19] backports_1.4.1     lattice_0.20-45     glue_1.6.2         
[22] digest_0.6.30       rvest_1.0.3         minqa_1.2.4        
[25] colorspace_2.0-3    psych_2.2.9         htmltools_0.5.3    
[28] pkgconfig_2.0.3     broom_1.0.1         purrr_0.3.5        
[31] xtable_1.8-4        mvtnorm_1.1-3       patchwork_1.1.2    
[34] scales_1.2.1        webshot_0.5.4       svglite_2.1.0      
[37] emmeans_1.6.0       tibble_3.1.8        generics_0.1.3     
[40] ggplot2_3.3.6       ellipsis_0.3.2      sjlabelled_1.2.0   
[43] withr_2.5.0         cachem_1.0.4        mnormt_2.1.1       
[46] cli_3.4.1           magrittr_2.0.3      effectsize_0.7.0.5 
[49] estimability_1.4.1  evaluate_0.16       fansi_1.0.3        
[52] nlme_3.1-140        xml2_1.3.3          tools_3.6.1        
[55] lifecycle_1.0.3     stringr_1.4.1       munsell_0.5.0      
[58] ggeffects_1.1.3     compiler_3.6.1      jquerylib_0.1.4    
[61] systemfonts_1.0.4   rlang_1.0.6         grid_3.6.1         
[64] nloptr_1.2.2.2      parameters_0.19.0   rstudioapi_0.14    
[67] rmarkdown_2.16      boot_1.3-22         gtable_0.3.1       
[70] sjstats_0.18.1      DBI_1.1.3           sjmisc_2.8.9       
[73] R6_2.5.1            performance_0.10.0  fastmap_1.1.0      
[76] utf8_1.2.2          insight_0.18.4      stringi_1.6.1      
[79] parallel_3.6.1      Rcpp_1.0.9          vctrs_0.5.0        
[82] DEoptimR_1.0-11     tidyselect_1.2.0    xfun_0.33          
LS0tDQp0aXRsZTogIkVSUCBEYXRhIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudA0KLS0tDQoNCjwhLS0gU2V0IGdlbmVyYWwgc2V0dGluZ3MgLS0+DQoNCmBgYHtyIHNldHVwLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KIyBTZXQgZ2VuZXJhbCBzZXR0aW5ncyBmb3IgbWFya2Rvd24gZmlsZQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBtZXNzYWdlID0gRkFMU0UsDQogIHdhcm5pbmcgPSBGQUxTRSwNCiAgY29tbWVudCA9ICIiLA0KICByZXN1bHRzID0gImhvbGQiKQ0KDQoNCiMgQ2xlYXIgZW52aXJvbm1lbnQNCnJtKGxpc3QgPSBscygpKQ0KDQoNCiMgTG9hZCBwYWNrYWdlcw0KbGlicmFyeShkcGx5cikgICAgICAjIGZvciBkYXRhIHdyYW5nbGluZw0KbGlicmFyeShrbml0cikgICAgICAjIGZvciBpbnRlZ3JhdGluZyBjb21wdXRpbmcgYW5kIHJlcG9ydGluZyBpbiBtYXJrZG93bg0KbGlicmFyeShrYWJsZUV4dHJhKSAjIGZvciBjdXN0b21pemluZyBhcHBlYXJhbmNlIG9mIHRhYmxlcw0KbGlicmFyeShNQVNTKSAgICAgICAjIGZvciBib3hjb3ggZnVuY3Rpb24gYW5kIGNvbnRyYXN0IGRlZmluaXRpb24NCmxpYnJhcnkobG1lNCkgICAgICAgIyBmb3IgKEcpTE1Ncw0KbGlicmFyeShsbWVyVGVzdCkgICAjIGZvciBMTU0gcCB2YWx1ZXMgKFNhdHRlcnRod2FpdGUncyBtZXRob2QgZm9yIGFwcHJveGltYXRpbmcgZGZzIGZvciB0IGFuZCBGIHRlc3RzKQ0KbGlicmFyeShzalBsb3QpICAgICAjIGZvciB0YWJfbW9kZWwgZnVuY3Rpb24gdG8gZGlzcGxheSAoRylMTU0gcmVzdWx0cw0KbGlicmFyeShzcGxpdGhhbGYpICAjIGZvciBwZXJtdXRhdGlvbi1iYXNlZCBzcGxpdC1oYWxmIHJlbGlhYmlsaXR5DQoNCg0KIyBMb2FkIGZ1bmN0aW9ucw0Kc291cmNlKCIuL2Z1bmN0aW9ucy9zdW1tYXJ5U0V3aXRoaW5PLlIiKSAgIyBGdW5jdGlvbiBwcm92aWRlZCBieSBSLWNvb2tib29rOiBodHRwOi8vd3d3LmNvb2tib29rLXIuY29tL0dyYXBocy9QbG90dGluZ19tZWFuc19hbmRfZXJyb3JfYmFyc18oZ2dwbG90MikvDQpzb3VyY2UoIi4vZnVuY3Rpb25zL215X3RhYmxlX3RlbXBsYXRlLlIiKSAjIEZ1bmN0aW9uIHRvIGNyZWF0ZSB0YWJsZSB0ZW1wbGF0ZQ0KDQoNCiMgVHVybiBvZmYgc2NpZW50aWZpYyBub3RhdGlvbg0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpDQoNCg0KIyBQcmVwYXJlIGxhYmVscyBmb3IgTE1NIHRhYmxlcw0KbGFiZWxzIDwtIGMoDQogICIoSW50ZXJjZXB0KSIgPSAiSW50ZXJjZXB0IiwNCiAgImdyb3VwMi0xIiAgICA9ICJHcm91cCAoT0NEIOKAkyBIQykiKQ0KYGBgDQo8YnI+DQoNCiMjIERhdGEgQ2xlYW5pbmcNCioqKg0KDQpgYGB7ciBsb2FkLWFuZC1jbGVhbi1kYXRhfQ0KDQojIExvYWQgZGF0YQ0KbG9hZChmaWxlID0gIi4vZGF0YS9TaW5nbGVfVHJpYWxfRGF0YS5yZGEiKQ0KDQoNCiMgRm9yIEVSUCBhbmFseXNpcywgZXhjbHVkZSBpbmhpYml0ZWQgZ25nIHJlc3BvbnNlcywgbWlzc2luZyBnbmcgcmVzcG9uc2VzLCBnbmcgcmVzcG9uc2VzIHdpdGgNCiMgd3Jvbmcga2V5LCBnbmcgUlQgb3V0bGllcnMsIGFuZCB0cmlhbHMgd2l0aCBFUlAgYXJ0aWZhY3RzDQpzaW5nbGVfdHJpYWxfZGF0YV9lcnAgPC0gc2luZ2xlX3RyaWFsX2RhdGEgJT4lDQogIGRwbHlyOjpmaWx0ZXIoDQogICAgZ25nX3Jlc3BvbnNlX3R5cGUgIT0gIklSIiAmDQogICAgZ25nX3Jlc3BvbnNlX3R5cGUgIT0gIm1pc3MiICYNCiAgICBnbmdfcmVzcG9uc2VfdHlwZSAhPSAid3Jvbmdfa2V5IiAmDQogICAgKGlzLm5hKGduZ19ydF9pbnZhbGlkKSB8IGduZ19ydF9pbnZhbGlkICA9PSBGQUxTRSkgJg0KICAgIHN0aW11bGF0aW9uID09ICJzaGFtIiAmDQogICAgTUZOX2FydGlmYWN0ID09IEZBTFNFKQ0KDQoNCiMgQ3JlYXRlIGFjY3VyYWN5IHZhcmlhYmxlICgiaW5jb3JyZWN0IiA9IEZBOyAiY29ycmVjdCIgPSBTSCwgRkgpDQpzaW5nbGVfdHJpYWxfZGF0YV9lcnAgPC0gc2luZ2xlX3RyaWFsX2RhdGFfZXJwICU+JQ0KICBkcGx5cjo6bXV0YXRlKGduZ19hY2N1cmFjeSA9IGlmZWxzZShnbmdfcmVzcG9uc2VfdHlwZSA9PSAiRkEiLCAiaW5jb3JyZWN0IiwgImNvcnJlY3QiKSkNCg0KDQojIENhbGN1bGF0ZSAlIG9mIGV4Y2x1ZGVkIHRyaWFscyBwZXIgcGFydGljaXBhbnQNCmV4Y2x1ZGVkX3RyaWFsc19wZXJfcGFydGljaXBhbnQgPC0gc2luZ2xlX3RyaWFsX2RhdGEgJT4lDQogIGRwbHlyOjpmaWx0ZXIoc3RpbXVsYXRpb24gPT0gInNoYW0iKSAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KHBhcnRpY2lwYW50X2lkKSAlPiUNCiAgZHBseXI6OnN1bW1hcml6ZShFRUdfYXJ0aWZhY3QgPSBzdW0oaXMubmFuKE1GTl8wXzEwMF9GQ3opKSAvIGxlbmd0aChwYXJ0aWNpcGFudF9pZCkgKiAxMDApICU+JQ0KICBkcGx5cjo6dW5ncm91cCgpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKGFjcm9zcygtYyhwYXJ0aWNpcGFudF9pZCksIGxpc3QobWVhbiwgc2QpKSkNCg0KDQojIENhbGN1bGF0ZSBudW1iZXIgb2YgcmVtYWluaW5nIHRyaWFscyBwZXIgcGFydGljaXBhbnQNCnJlbWFpbmluZ190cmlhbHNfcGVyX3BhcnRpY2lwYW50IDwtIHNpbmdsZV90cmlhbF9kYXRhX2VycCAlPiUNCiAgZHBseXI6Omdyb3VwX2J5KHBhcnRpY2lwYW50X2lkLCBnbmdfYWNjdXJhY3kpICU+JQ0KICBkcGx5cjo6c3VtbWFyaXplKG4gPSBuKCkpICU+JQ0KICBkcGx5cjo6Z3JvdXBfYnkoZ25nX2FjY3VyYWN5KSAlPiUgDQogIGRwbHlyOjpzdW1tYXJpemUobWVhbiA9IG1lYW4obiksIHNkID0gc2QobikpICU+JQ0KICBkcGx5cjo6dW5ncm91cCgpIA0KDQoNCiMgTWFrZSBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgZmFjdG9ycw0Kc2luZ2xlX3RyaWFsX2RhdGFfZXJwJHBhcnRpY2lwYW50X2lkIDwtIGZhY3RvcihzaW5nbGVfdHJpYWxfZGF0YV9lcnAkcGFydGljaXBhbnRfaWQpDQpzaW5nbGVfdHJpYWxfZGF0YV9lcnAkZ3JvdXAgICAgICAgICAgPC0gZmFjdG9yKHNpbmdsZV90cmlhbF9kYXRhX2VycCRncm91cCkNCmBgYA0KDQpJbiB0aGUgYW5hbHlzaXMgb2YgRVJQcyBpbiB0aGUgZ28vbm8tZ28gdGFzaywgdHJpYWxzIHdlcmUgZGlzY2FyZGVkIGlmIFJUIGluIHRoZSBnby9uby1nbyB0YXNrIHdhcyBiZWxvdyAxMDAgbXMgb3IgYWJvdmUgODAwIG1zLCByZXNwb25zZSB3YXMgbWlzc2luZywgb3IgdGhlIHJlc3BvbnNlIHdhcyBtYWRlIHdpdGggYSBrZXkgbm90IGFzc2lnbmVkIHRvIHRoZSBnby9uby1nbyB0YXNrLiBXZSBmdXJ0aGVyIGRpc2NhcmRlZCB0cmlhbHMgY29udGFpbmluZyBhcnRpZmFjdHMgaW4gdGhlIEVFRywgaS5lLiwgYSB2b2x0YWdlIGRpZmZlcmVuY2UgZXhjZWVkaW5nIDIwMCDOvFYgd2l0aGluIGFuIGVwb2NoIG9yIDUwIM68ViBiZXR3ZWVuIHNhbXBsZSBwb2ludHMsIHJlc3VsdGluZyBpbiByZWplY3Rpb24gb2YgYHIgcm91bmQoZXhjbHVkZWRfdHJpYWxzX3Blcl9wYXJ0aWNpcGFudCRFRUdfYXJ0aWZhY3RfMSwgZGlnaXRzID0gMilgJSAoKlNEKiA9IGByIHJvdW5kKGV4Y2x1ZGVkX3RyaWFsc19wZXJfcGFydGljaXBhbnQkRUVHX2FydGlmYWN0XzIsIGRpZ2l0cyA9IDIpYCkgb2YgZXBvY2hzIG9uIGF2ZXJhZ2UgKHJlbWFpbmluZyB0cmlhbHMgcGVyIHBhcnRpY2lwYW50IGZvciBFUk4gYW5hbHlzaXM6ICpNKiA9IGByIHJvdW5kKHJlbWFpbmluZ190cmlhbHNfcGVyX3BhcnRpY2lwYW50JG1lYW5bMl0sIGRpZ2l0cyA9IDIpYCwgKlNEKiA9IGByIHJvdW5kKHJlbWFpbmluZ190cmlhbHNfcGVyX3BhcnRpY2lwYW50JHNkWzJdLCBkaWdpdHMgPSAyKWA7IGZvciBDUk4gYW5hbHlzaXM6ICpNKiA9IGByIHJvdW5kKHJlbWFpbmluZ190cmlhbHNfcGVyX3BhcnRpY2lwYW50JG1lYW5bMV0sIGRpZ2l0cyA9IDIpYCwgKlNEKiA9IGByIHJvdW5kKHJlbWFpbmluZ190cmlhbHNfcGVyX3BhcnRpY2lwYW50JHNkWzFdLCBkaWdpdHMgPSAyKWApLiANCjxicj48YnI+PGJyPg0KDQojIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzIA0KKioqDQoNClRoaXMgdGFibGUgY29ycmVzcG9uZHMgdG8gVGFibGUgUzIgaW4gdGhlIHN1cHBsZW1lbnRhbCBtYXRlcmlhbC4NCg0KYGBge3IgZGVzY3JpcHRpdmUtc3RhdGlzdGljcy10YWJsZX0NCg0KIyBDYWxjdWxhdGUgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBmb3IgRVJOL0NSTg0KZGVzY3JpcHRpdmVfc3RhdGlzdGljcyA8LSBzdW1tYXJ5U0V3aXRoaW5PKA0KICBkYXRhICAgICAgICAgID0gc2luZ2xlX3RyaWFsX2RhdGFfZXJwLA0KICBtZWFzdXJldmFyICAgID0gIk1GTl8wXzEwMF9GQ3oiLA0KICB3aXRoaW52YXJzICAgID0gImduZ19hY2N1cmFjeSIsDQogIGJldHdlZW52YXJzICAgPSAiZ3JvdXAiLA0KICBpZHZhciAgICAgICAgID0gInBhcnRpY2lwYW50X2lkIiwNCiAgY29uZi5pbnRlcnZhbCA9IC45NSkgJT4lDQogICMgUmVuYW1lIHZhcmlhYmxlIGFuZCBjcmVhdGUgbWVhc3VyZSB2YXJpYWJsZQ0KICBkcGx5cjo6cmVuYW1lKG1lYW4gPSBNRk5fMF8xMDBfRkN6KSAlPiUNCiAgZHBseXI6Om11dGF0ZShtZWFzdXJlID0gcmVwKGMoIkNSTiAowrVWKSIsICJFUk4gKMK1VikiKSwgMikpDQoNCg0KIyBDcmVhdGUgY29sdW1uIHdpdGggZm9ybWF0ICJNIFtDSV0iIChyb3VuZCB0byAyIGRlY2ltYWxzKQ0KZGVzY3JpcHRpdmVfc3RhdGlzdGljcyRNX0NJIDwtIHBhc3RlMCgNCiAgZm9ybWF0KHJvdW5kKGRlc2NyaXB0aXZlX3N0YXRpc3RpY3MkbWVhbiwgMiksIG5zbWFsbCA9IDIpLCAiIFsiLA0KICBmb3JtYXQocm91bmQoZGVzY3JpcHRpdmVfc3RhdGlzdGljcyRtZWFuIC0NCiAgICAgICAgICAgICAgIGRlc2NyaXB0aXZlX3N0YXRpc3RpY3MkY2ksICAgMiksIG5zbWFsbCA9IDIpLCAiLCAiLA0KICBmb3JtYXQocm91bmQoZGVzY3JpcHRpdmVfc3RhdGlzdGljcyRtZWFuICsNCiAgICAgICAgICAgICAgIGRlc2NyaXB0aXZlX3N0YXRpc3RpY3MkY2ksICAgMiksIG5zbWFsbCA9IDIpLCAiXSIpDQoNCg0KIyBTcGxpdCBhbmQgcmUtbWVyZ2UgdGFibGUgdG8gZGlzcGxheSBib3RoIGdyb3VwcyBuZXh0IHRvIGVhY2ggb3RoZXINCmRlc2NyaXB0aXZlX3N0YXRpc3RpY3MgPC0gc3BsaXQoZGVzY3JpcHRpdmVfc3RhdGlzdGljcywgZGVzY3JpcHRpdmVfc3RhdGlzdGljcyRncm91cCkNCmRlc2NyaXB0aXZlX3N0YXRpc3RpY3NfZGlzcGxheSA8LSBjYmluZChkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzJE9DRFssIGMoIm1lYXN1cmUiLCAiTV9DSSIpXSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzJEhDWywgIk1fQ0kiXSkNCg0KDQojIERpc3BsYXkgdGFibGUgKGFuZCByZWFycmFuZ2Ugcm93cykNCm15X3RhYmxlX3RlbXBsYXRlKGRlc2NyaXB0aXZlX3N0YXRpc3RpY3NfZGlzcGxheVtjKDIsIDEpLCBdLA0KICBjYXB0aW9uID0gIkRlc2NyaXB0aXZlIFN0YXRpc3RpY3MgZm9yIEVSUCBNZWFzdXJlcyIsDQogIGNvbF9uYW1lcyA9IGMoIk1lYXN1cmUiLCByZXAoIk0gWzk1JSBDSV0iLCAyKSksDQogIGhlYWRlcl9hYm92ZV9jb25maWcgPSBjKCIiLCAiUGF0aWVudHMgd2l0aCBPQ0QiLCAiSGVhbHRoeSBjb250cm9sIHBhcnRpY2lwYW50cyIpKSAlPiUNCiAgYWRkX2Zvb3Rub3RlKCJcbiBOb3RlLiBDSXMgYXJlIGFkanVzdGVkIGZvciB3aXRoaW4tcGFydGljaXBhbnQgY29tcGFyaXNvbnMgdXNpbmcgdGhlIG1ldGhvZCANCiAgZGVzY3JpYmVkIGJ5IE1vcmV5ICgyMDA4KS4gRVJOIGFuZCBDUk4gd2VyZSBtZWFzdXJlZCBhcyBtZWFuIGFtcGxpdHVkZSANCiAgZnJvbSAwIHRvIDEwMCBtcyBhdCBlbGVjdHJvZGUgRkN6IGFmdGVyIGZhbHNlIGFsYXJtcyBhbmQgaGl0cywgcmVzcGVjdGl2ZWx5LiIsIG5vdGF0aW9uID0gIm5vbmUiKSANCmBgYA0KPGJyPjxicj4NCg0KIyMgU3BsaXQtSGFsZiBSZWxpYWJpbGl0eQ0KKioqDQoNCmBgYHtyIHBlcm11dGF0aW9uLXNwbGl0LWhhbGYtcmVsaWFiaWxpdHl9DQoNCiMgQ2FsY3VsYXRlIHBlcm11dGF0aW9uLWJhc2VkIHNwbGl0LWhhbGYgaW50ZXJuYWwgY29uc2lzdGVuY3kgZm9yIEVSTi9DUk4NCmludmlzaWJsZShjYXB0dXJlLm91dHB1dChzcGxpdF9oYWxmX3JlbGlhYmlsaXR5IDwtIHNwbGl0aGFsZigNCiAgZGF0YSA9IHNpbmdsZV90cmlhbF9kYXRhX2VycCwNCiAgb3V0Y29tZSA9ICJSVCIsDQogIHNjb3JlID0gImF2ZXJhZ2UiLA0KICBwZXJtdXRhdGlvbnMgPSA1MDAwLA0KICBoYWxmdHlwZSA9ICJyYW5kb20iLA0KICB2YXIuUlQgPSAiTUZOXzBfMTAwX0ZDeiIsDQogIHZhci5wYXJ0aWNpcGFudCA9ICJwYXJ0aWNpcGFudF9pZCIsDQogIHZhci5jb25kaXRpb24gPSAiZ25nX2FjY3VyYWN5IiwNCiAgY29uZGl0aW9ubGlzdCA9IGMoImNvcnJlY3QiLCAiaW5jb3JyZWN0IiksDQogIGF2ZXJhZ2UgPSAibWVhbiIpKSkNCg0KDQojIE1ha2UgbmljZSB0YWJsZSBmb3IgZGlzcGxheQ0Kc3BsaXRfaGFsZl9yZWxpYWJpbGl0eSA8LSBjYmluZChFUlAgPSBjKCJDUk4iLCAiRVJOIiksIHNwbGl0X2hhbGZfcmVsaWFiaWxpdHkkZmluYWxfZXN0aW1hdGVzKSAlPiUNCiAgZHBseXI6OnNlbGVjdChFUlAsIHNwZWFybWFuYnJvd24sIFNCX2xvdywgU0JfaGlnaCkgJT4lDQogIGRwbHlyOjpyZW5hbWUociA9IHNwZWFybWFuYnJvd24sIENJX2xvdyA9IFNCX2xvdywgQ0lfdXAgPSBTQl9oaWdoKQ0KDQoNCiMgRGlzcGxheSBwZXJtdXRhdGlvbi1iYXNlZCBzcGxpdC1oYWxmIGludGVybmFsIGNvbnNpc3RlbmN5DQpteV90YWJsZV90ZW1wbGF0ZShzcGxpdF9oYWxmX3JlbGlhYmlsaXR5W2MoMiwgMSksIF0sDQogIGNhcHRpb24gPSAiUGVybXV0YXRpb24tYmFzZWQgc3BsaXQtaGFsZiByZWxpYWJpbGl0eSIpDQpgYGANCkludGVybmFsIGNvbnNpc3RlbmN5IHdhcyBnb29kIGZvciBFUk4gKCpyKiA9IGByIHJvdW5kKHNwbGl0X2hhbGZfcmVsaWFiaWxpdHlbMixdJHIsIGRpZ2l0cyA9IDIpYCwgOTUlIENJIFtgciByb3VuZChzcGxpdF9oYWxmX3JlbGlhYmlsaXR5WzIsXSRDSV9sb3csIGRpZ2l0cyA9IDIpYCwgYHIgcm91bmQoc3BsaXRfaGFsZl9yZWxpYWJpbGl0eVsyLF0kQ0lfdXAsIGRpZ2l0cyA9IDIpYF0pIGFuZCBleGNlbGxlbnQgZm9yIENSTiAoKnIqID0gYHIgcm91bmQoc3BsaXRfaGFsZl9yZWxpYWJpbGl0eVsxLF0kciwgZGlnaXRzID0gMilgLCA5NSUgQ0kgW2ByIHJvdW5kKHNwbGl0X2hhbGZfcmVsaWFiaWxpdHlbMSxdJENJX2xvdywgZGlnaXRzID0gMilgLCBgciByb3VuZChzcGxpdF9oYWxmX3JlbGlhYmlsaXR5WzEsXSRDSV91cCwgZGlnaXRzID0gMilgXSksIGFzIGFzc2Vzc2VkIHdpdGggYSBwZXJtdXRhdGlvbi1iYXNlZCBzcGxpdC1oYWxmIG1ldGhvZCB1c2luZyA1LDAwMCByYW5kb20gc3BsaXRzIGFuZCBTcGVhcm1hbuKAk0Jyb3duIGNvcnJlY3Rpb24uDQo8YnI+PGJyPjxicj4NCg0KIyMgQW5hbHlzaXMgb2YgRVJOICYgQ1JOIHsudGFic2V0fQ0KKioqDQoNCldlIHBlcmZvcm1lZCBsaW5lYXIgbWl4ZWQgbW9kZWxzIChMTU1zKSBvbiBzaW5nbGUtdHJpYWwgZGF0YS4gQW5hbHlzaXMgb2YgRVJQIGFtcGxpdHVkZXMgaW4gdGhlIGdvL25vLWdvIHRhc2sgaW5jbHVkZWQgZ3JvdXAgYXMgZml4ZWQgZWZmZWN0LiBNb2RlbHMgb24gRVJOIGFuZCBDUk4gd2VyZSBiYXNlZCBvbiBmYWxzZSBhbGFybSBhbmQgaGl0IHRyaWFscywgcmVzcGVjdGl2ZWx5LiANCg0KV2UgdXNlZCBzbGlkaW5nIGRpZmZlcmVuY2UgY29udHJhc3RzIGZvciBjYXRlZ29yaWNhbCBmaXhlZCBlZmZlY3RzIGFuZCBzdGFydGVkIHdpdGggdGhlIG1heGltYWwgcmFuZG9tLWVmZmVjdHMgc3RydWN0dXJlIGZvciBlYWNoIG1vZGVsLiBJbiBjYXNlIG9mIG5vbi1jb252ZXJnZW5jZSwgcmFuZG9tIGVmZmVjdHMgd2VyZSBzcGVjaWZpZWQgYXMgdW5jb3JyZWxhdGVkLiBVc2luZyBwcmluY2lwYWwgY29tcG9uZW50IGFuYWx5c2lzLCB3ZSBpZGVudGlmaWVkIHJhbmRvbSBlZmZlY3RzIGV4cGxhaW5pbmcgemVybyB2YXJpYW5jZSBhbmQgcmVtb3ZlZCB0aGVzZSwgYXMgcmVjb21tZW5kZWQgYnkgQmF0ZXMsIEtsaWVnbCwgZXQgYWwuICgyMDE1KS4gDQo8YnI+PGJyPg0KDQojIyMgRGV0ZXJtaW5lIERhdGEgVHJhbnNmb3JtYXRpb24NCg0KTm8gZGF0YSB0cmFuc2Zvcm1hdGlvbiB3YXMgcmVxdWlyZWQgdG8gbWVldCB0aGUgYXNzdW1wdGlvbiBvZiBub3JtYWxseSBkaXN0cmlidXRlZCByZXNpZHVhbHMuIFRoaXMgd2FzIGRldGVybWluZWQgdXNpbmcgdGhlIEJveOKAk0NveCBwcm9jZWR1cmUgKEJveCAmIENveCwgMTk2NCkuDQoNCmBgYHtyIGVycC1kZXRlcm1pbmUtdHJhbnNmb3JtYXRpb24sIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA2fQ0KDQojIEFycmFuZ2UgcGxvdHMNCnBhcihtZnJvdyA9IGMoMiwgMykpDQoNCg0KIyBEZXRlcm1pbmUgdHJhbnNmb3JtYXRpb24gb2YgRVJOIGJ5IGVzdGltYXRpbmcgb3B0aW1hbCBsYW1iZGEgdXNpbmcgQm944oCTQ294IHByb2NlZHVyZQ0KYmNfZXJuIDwtIGJveGNveChNRk5fMF8xMDBfRkN6ICsgNTAgfiAxLA0KICBkYXRhID0gc2luZ2xlX3RyaWFsX2RhdGFfZXJwW3NpbmdsZV90cmlhbF9kYXRhX2VycCRnbmdfYWNjdXJhY3kgPT0gImluY29ycmVjdCIsIF0pDQpvcHRsYW1iZGFfZXJuIDwtIGJjX2VybiR4W3doaWNoLm1heChiY19lcm4keSldDQoNCg0KIyBEZW5zaXR5IHBsb3QgZm9yIEVSTiB2YWx1ZXMNCnBsb3QoZGVuc2l0eShzaW5nbGVfdHJpYWxfZGF0YV9lcnBbc2luZ2xlX3RyaWFsX2RhdGFfZXJwJGduZ19hY2N1cmFjeSA9PSAiaW5jb3JyZWN0IiwgXSRNRk5fMF8xMDBfRkN6KSwNCiAgbWFpbiA9ICJFUk46IERlbnNpdHkgUGxvdCIpDQoNCg0KIyBRLXEgcGxvdCBmb3IgRVJOIHZhbHVlcw0KcXFub3JtKHNpbmdsZV90cmlhbF9kYXRhX2VycFtzaW5nbGVfdHJpYWxfZGF0YV9lcnAkZ25nX2FjY3VyYWN5ID09ICJpbmNvcnJlY3QiLCBdJE1GTl8wXzEwMF9GQ3osDQogIG1haW4gPSAiRVJOOiBRLVEgUGxvdCIsIHBjaCA9IDEpDQoNCg0KIyBEZXRlcm1pbmUgdHJhbnNmb3JtYXRpb24gb2YgQ1JOIGJ5IGVzdGltYXRpbmcgb3B0aW1hbCBsYW1iZGEgdXNpbmcgQm944oCTQ294IHByb2NlZHVyZQ0KYmNfY3JuIDwtIGJveGNveChNRk5fMF8xMDBfRkN6ICsgNTAgfiAxLA0KICBkYXRhID0gc2luZ2xlX3RyaWFsX2RhdGFfZXJwW3NpbmdsZV90cmlhbF9kYXRhX2VycCRnbmdfYWNjdXJhY3kgPT0gImNvcnJlY3QiLCBdKQ0Kb3B0bGFtYmRhX2NybiA8LSBiY19jcm4keFt3aGljaC5tYXgoYmNfY3JuJHkpXQ0KDQoNCiMgRGVuc2l0eSBwbG90IGZvciBDUk4gdmFsdWVzDQpwbG90KGRlbnNpdHkoc2luZ2xlX3RyaWFsX2RhdGFfZXJwW3NpbmdsZV90cmlhbF9kYXRhX2VycCRnbmdfYWNjdXJhY3kgPT0gImNvcnJlY3QiLCBdJE1GTl8wXzEwMF9GQ3opLA0KICBtYWluID0gIkNSTjogRGVuc2l0eSBQbG90IikNCg0KDQojIFEtcSBwbG90IGZvciBDUk4gdmFsdWVzDQpxcW5vcm0oc2luZ2xlX3RyaWFsX2RhdGFfZXJwW3NpbmdsZV90cmlhbF9kYXRhX2VycCRnbmdfYWNjdXJhY3kgPT0gImNvcnJlY3QiLCBdJE1GTl8wXzEwMF9GQ3osDQogIG1haW4gPSAiQ1JOOiBRLVEgUGxvdCIsIHBjaCA9IDEpDQoNCg0KIyBSZXNldCBwbG90IGxheW91dA0KcGFyKG1mcm93ID0gYygxLCAxKSkNCmBgYA0KRm9yIHRoZSBFUk4sIHRoZSBvcHRpbWFsIGxhbWJkYSBpcyBgciByb3VuZChvcHRsYW1iZGFfZXJuLCBkaWdpdHMgPSAyKWAgKHVwcGVyIGxlZnQgcGxvdCksIHN1Z2dlc3RpbmcgdGhhdCBubyB0cmFuc2Zvcm1hdGlvbiBpcyBuZWVkZWQuDQpGb3IgdGhlIENSTiwgdGhlIG9wdGltYWwgbGFtYmRhIGlzIGByIHJvdW5kKG9wdGxhbWJkYV9jcm4sIGRpZ2l0cyA9IDIpYCAobG93ZXIgbGVmdCBwbG90KSwgc3VnZ2VzdGluZyB0aGF0IG5vIHRyYW5zZm9ybWF0aW9uIGlzIG5lZWRlZC4NCjxicj48YnI+PGJyPg0KDQojIyMgTE1NIG9uIEVSTiAmIENSTiB7LmFjdGl2ZX0NCg0KVGhpcyB0YWJsZSBjb3JyZXNwb25kcyB0byBUYWJsZSA1IGluIHRoZSBtYW51c2NyaXB0LiANCg0KYGBge3IgbG1tLWVycH0NCg0KIyBEZWZpbmUgY29udHJhc3RzIChzbGlkaW5nIGRpZmZlcmVuY2UgY29udHJhc3RzID0gZWZmZWN0IGNvZGluZyBmb3IgZmFjdG9ycyB3aXRoIDIgbGV2ZWxzKQ0KY29udHJhc3RzKHNpbmdsZV90cmlhbF9kYXRhX2VycCRncm91cCkgPC0gY29udHIuc2RpZigyKQ0KDQoNCiMgUnVuIG1vZGVsIG9uIEVSTiB3aXRoIG1heGltYWwgcmFuZG9tLWVmZmVjdHMgc3RydWN0dXJlDQpMTU1fZXJuIDwtIGxtZXIoTUZOXzBfMTAwX0ZDeiB+IGdyb3VwICsgKDEgfCBwYXJ0aWNpcGFudF9pZCksDQogIGRhdGEgPSBzaW5nbGVfdHJpYWxfZGF0YV9lcnBbc2luZ2xlX3RyaWFsX2RhdGFfZXJwJGduZ19hY2N1cmFjeSA9PSAiaW5jb3JyZWN0IiwgXSwNCiAgUkVNTCA9IFRSVUUsDQogIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIikpDQoNCg0KIyBDaGVjayBtb2RlbCBvdXRwdXQgYW5kIFBDQSBvZiByYW5kb20tZWZmZWN0cyB2YXJpYW5jZS1jb3ZhcmlhbmNlIGVzdGltYXRlcw0KIyBzdW1tYXJ5KExNTV9lcm4pICAgICAgICAjIE1vZGVsIGRvZXMgY29udmVyZ2UNCiMgaXNTaW5ndWxhcihMTU1fZXJuKSAgICAgIyBObyBzaW5ndWxhciBmaXQNCiMgc3VtbWFyeShyZVBDQShMTU1fZXJuKSkgIyBBbGwgdGVybXMgZXhwbGFpbiB2YXJpYW5jZQ0KDQoNCiMgUnVuIG1vZGVsIG9uIENSTiB3aXRoIG1heGltYWwgcmFuZG9tLWVmZmVjdHMgc3RydWN0dXJlDQpMTU1fY3JuIDwtIGxtZXIoTUZOXzBfMTAwX0ZDeiB+IGdyb3VwICsgKDEgfCBwYXJ0aWNpcGFudF9pZCksDQogIGRhdGEgPSBzaW5nbGVfdHJpYWxfZGF0YV9lcnBbc2luZ2xlX3RyaWFsX2RhdGFfZXJwJGduZ19hY2N1cmFjeSA9PSAiY29ycmVjdCIsIF0sDQogIFJFTUwgPSBUUlVFLA0KICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIpKQ0KDQoNCiMgQ2hlY2sgbW9kZWwgb3V0cHV0IGFuZCBQQ0Egb2YgcmFuZG9tLWVmZmVjdHMgdmFyaWFuY2UtY292YXJpYW5jZSBlc3RpbWF0ZXMNCiMgc3VtbWFyeShMTU1fY3JuKSAgICAgICAgIyBNb2RlbCBkb2VzIGNvbnZlcmdlDQojIGlzU2luZ3VsYXIoTE1NX2NybikgICAgICMgTm8gc2luZ3VsYXIgZml0DQojIHN1bW1hcnkocmVQQ0EoTE1NX2NybikpICMgQWxsIHRlcm1zIGV4cGxhaW4gdmFyaWFuY2UNCg0KDQojIERpc3BsYXkgcmVzdWx0cyAoZml4ZWQgZWZmZWN0cykNCnRhYl9tb2RlbChMTU1fZXJuLCBMTU1fY3JuLA0KICBkdi5sYWJlbHMgPSBjKCJFUk4iLCAiQ1JOIiksIHByZWQubGFiZWxzID0gbGFiZWxzLCBzaG93LnN0YXQgPSBUUlVFLCBzaG93LmljYyA9IEZBTFNFLA0KICBzaG93LnIyID0gRkFMU0UsIHNob3cucmUudmFyID0gRkFMU0UsIHNob3cubmdyb3VwcyA9IEZBTFNFLCBtaW51cy5zaWduID0gIi0iLA0KICBzdHJpbmcucHJlZCA9ICJGaXhlZCBlZmZlY3RzIiwgc3RyaW5nLmVzdCA9ICJiIiwgc3RyaW5nLnN0YXQgPSAidCIsIHN0cmluZy5jaSA9ICI5NSAlIENJIiwNCiAgcC52YWwgPSAic2F0dGVydGh3YWl0ZSIsIHRpdGxlID0gIkxNTSBSZXN1bHRzIGZvciBFUk4gYW5kIENSTiBpbiB0aGUgR28vTm8tR28gVGFzayIpDQoNCg0KIyBEaXNwbGF5IHJhbmRvbSBlZmZlY3RzDQpwcmludCgiUmFuZG9tIGVmZmVjdHMgRVJOOiIpDQpwcmludChWYXJDb3JyKExNTV9lcm4pLCBkaWdpdHMgPSAzLCBjb21wID0gIlN0ZC5EZXYuIikNCg0KDQojIERpc3BsYXkgcmFuZG9tIGVmZmVjdHMNCnByaW50KCJSYW5kb20gZWZmZWN0cyBDUk46IikNCnByaW50KFZhckNvcnIoTE1NX2NybiksIGRpZ2l0cyA9IDMsIGNvbXAgPSAiU3RkLkRldi4iKQ0KYGBgDQo8YnI+DQpFUk4gYW5kIENSTiBhbXBsaXR1ZGVzIGRpZCBub3QgZGlmZmVyIHNpZ25pZmljYW50bHkgYmV0d2VlbiBncm91cHMuDQo8YnI+PGJyPjxicj4NCg0KIyMgUmVmZXJlbmNlcw0KKioqDQpCYXRlcywgRC4sIEtsaWVnbCwgUi4sIFZhc2lzaHRoLCBTLiwgJiBCYWF5ZW4sIEguICgyMDE1KS4gKlBhcnNpbW9uaW91cyBtaXhlZCBtb2RlbHMuKiBhclhpdi4gaHR0cHM6Ly9hcnhpdi5vcmcvYWJzLzE1MDYuMDQ5Njd2MiA8YnI+PGJyPg0KQm94LCBHLiBFLiwgJiBDb3gsIEQuIFIuICgxOTY0KS4gQW4gYW5hbHlzaXMgb2YgdHJhbnNmb3JtYXRpb25zLiAqSm91cm5hbCBvZiB0aGUgUm95YWwgU3RhdGlzdGljYWwgU29jaWV0eTogU2VyaWVzIEIgKE1ldGhvZG9sb2dpY2FsKSwgMjYqKDIpLCAyMTHigJMyNDMuIGh0dHBzOi8vZG9pLm9yZy8xMC4xMTExL2ouMjUxNy02MTYxLjE5NjQudGIwMDU1My54IDxicj48YnI+DQpNb3JleSwgUi4gKDIwMDgpLiBDb25maWRlbmNlIGludGVydmFscyBmcm9tIG5vcm1hbGl6ZWQgZGF0YTogQSBjb3JyZWN0aW9uIHRvIENvdXNpbmVhdSAoMjAwNSkuICpUdXRvcmlhbHMgaW4gUXVhbnRpdGF0aXZlIE1ldGhvZHMgZm9yIFBzeWNob2xvZ3ksIDQqKDIpLCA2MeKAkzY0LiBodHRwczovL2RvaS5vcmcvMTAuMjA5ODIvdHFtcC4wNC4yLnAwNjEgDQo8YnI+PGJyPjxicj4NCg0KIyMgU2Vzc2lvbiBJbmZvDQoqKioNCmBgYHtyIHNlc3Npb24taW5mb30NCg0Kc2Vzc2lvbkluZm8oKQ0KYGBgDQo=