First Step is to load the necessary package, If you dont have them just install them. For jjstatsplot you need to install it remotely. Just remove the dash and press enter. Then Press 3 (none package to be updated). ?group_by()

#remotes::install_github("sbalci/jjstatsplot") #Press 3 !!!!! i.e., installing/Updating none package! 
library(jmv)
library(datasets)
library(plyr)
library(readr)
library(dataframes2xls)
library(data.table)
library(plyr)
library(ggstatsplot)
library(jjstatsplot)
library(lme4)
library(lmerTest)
library(ggplot2)
library(rstatix)
library(coin)
library(ARTool)
library(ggpubr)
library(tidyverse)
library(dplyr)
library("afex")     
library("emmeans")  
library("multcomp") 

Import and merge all the csv files (x.csv where x = ID) of the folder. Note, that the ID is has already been added as column

Discard first X trials per interpenetration feedback condition and then create a summary table for each participant. You need to define nrTrialsPerBlockToRemove.



data$Part <- as.factor(data$Block < 4)
levels(data$Part)

data$Part <- factor(data$Part,levels = c("TRUE","FALSE"),
                  labels = c("Part 1","Part 2"))

nrTrialsPerBlockToRemove <- 1
#trialsToRemove <- seq(from = 1, to = nrTrialsPerBlockToRemove)

  data <-  data %>%
    group_by(ID, Part, InterpenetrationFeedback, FullyShaded) %>% # I have added here the fully shaded 
    slice(nrTrialsPerBlockToRemove+1:n())
  # to double check we are discarding the right rows
  #print(data[[i]]$Trial)

 # This df will be used to create the subsets for 1st part and 2nd part of the experiment. 
  
data$InterpenetrationFeedback  <- as.factor(data$InterpenetrationFeedback)
data$FullyShaded <- as.factor(data$FullyShaded)

Let’s visualize the data per interpenetration feedback and/or part of the experiment (part 1 & part 2).

Warning messages:
1: Unknown or uninitialised column: `Extreme1`. 
2: Unknown or uninitialised column: `Extreme2`. 
ParsiDFplots <- data
ParsiDFplots$ID[ParsiDFplots$ID == 9] <- NA
ParsiDFplots$ID[ParsiDFplots$ID == 17] <- NA
ParsiDFplots$ID[ParsiDFplots$ID == 20] <- NA
ParsiDFplots <- na.omit(ParsiDFplots)
ParsiDFplots <- aggregate(. ~ ID + Age + Gender + InterpenetrationFeedback + Part, ParsiDFplots, mean)
ParsiDFplots$AverageInterpenetration <-100 * ParsiDFplots$AverageInterpenetration
ParsiDFplots$MaxInterpenetration <- 100 * ParsiDFplots$MaxInterpenetration

p1 <- ggstatsplot::ggbetweenstats(
  data = ParsiDFplots,
  x = "InterpenetrationFeedback", #Indepedent Variable
  y = "MaxInterpenetration", # Depedent Variable
  grouping.var = "Part", # 2nd IV 
  type = "p", # parametric test i.e., p values
  pairwise.comparisons = FALSE, #compute pairwise comparisons
  pairwise.display = "significant", # show only the significant ones
  p.adjust.method = "bonferroni", # correction of p-value
  effsize.type = "unbiased", # Calculates the Hedge's g for t tests and the partial Omega for ANOVA
  results.subtitle = FALSE,
  xlab = "Type of Feedback", #label of X axis
  ylab = "Maximum Interpenetration", #label of y axis
  sample.size.label = FALSE,
  var.equal = TRUE, #Assuming Equal variances
  mean.plotting = FALSE,
  mean.ci = TRUE, #display the confidence interval of the mean
  paired = TRUE, #indicating that we have a within subject design
  title.text = "Interpenetration Box-Violin Plots",
  caption.text = "Note: Interpenetration distance is displayed in cm.",
  title.color = "black",
  caption.color = "black"
  ) 

p2 <- ggstatsplot::ggbetweenstats(
  data = ParsiDFplots,
  x = "InterpenetrationFeedback",
  y = "AverageInterpenetration",
  grouping.var = "Part",
  type = "p",
  pairwise.comparisons = FALSE,
  pairwise.display = "significant",
  p.adjust.method = "bonferroni",
  effsize.type = "unbiased",
  results.subtitle = FALSE,
  xlab = "Type of Feedback",
  ylab = "Average Interpenetration",
  sample.size.label = FALSE,
  var.equal = TRUE,
  mean.plotting = FALSE,
  mean.ci = TRUE,
  paired = TRUE,
  title.text = "Interpenetration Box-Violin Plots",
  caption.text = "Note: Interpenetration distance is displayed in cm.",
  title.color = "black",
  caption.color = "black"
)


# Replicating the above but this time we look on the effect of the type of feedback on the DVs in 1st and 2nd Part of the experiment individually
p3 <- ggstatsplot::grouped_ggbetweenstats(
  data = ParsiDFplots,
  x = "InterpenetrationFeedback",
  y = "MaxInterpenetration",
  grouping.var = "Part",
  type = "p",
  pairwise.comparisons = FALSE,
  pairwise.display = "significant",
  p.adjust.method = "bonferroni",
  effsize.type = "unbiased",
  results.subtitle = FALSE,
  xlab = "Type of Feedback",
  ylab = "Maximum Interpenetration",
  sample.size.label = FALSE,
  var.equal = TRUE,
  mean.plotting = FALSE,
  mean.ci = TRUE,
  paired = TRUE,
  title.text = "Interpenetration Box-Violin Plots",
  caption.text = "Note: Interpenetration distance is displayed in cm.",
  title.color = "black",
  caption.color = "black"
  ) 

p4 <- ggstatsplot::grouped_ggbetweenstats(
  data = ParsiDFplots,
  x = "InterpenetrationFeedback",
  y = "AverageInterpenetration",
  grouping.var = "Part",
  type = "p",
  pairwise.comparisons = FALSE,
  pairwise.display = "significant",
  p.adjust.method = "bonferroni",
  effsize.type = "unbiased",
  results.subtitle = FALSE,
  xlab = "Type of Feedback",
  ylab = "Average Interpenetration",
  sample.size.label = FALSE,
  var.equal = TRUE,
  mean.plotting = FALSE,
  mean.ci = TRUE,
  paired = TRUE,
  title.text = "Interpenetration Box-Violin Plots",
  caption.text = "Note: Interpenetration distance is displayed in cm.",
  title.color = "black",
  caption.color = "black"
) 

# Lets check the effect of shaded condition on DVs
p5 <- ggstatsplot:: ggbetweenstats(
  data = ParsiDFplots,
  x = "Part",
  y = "MaxInterpenetration",
  grouping.var = "InterpenetrationFeedback",
  type = "p",
  pairwise.comparisons = FALSE,
  pairwise.display = "significant",
  p.adjust.method = "bonferroni",
  effsize.type = "unbiased",
  results.subtitle = FALSE,
  xlab = "Order",
  ylab = "Maximum Interpenetration",
  sample.size.label = FALSE,
  var.equal = TRUE,
  mean.plotting = FALSE,
  mean.ci = TRUE,
  paired = TRUE,
  title.text = "Interpenetration Box-Violin Plots",
  caption.text = "Note: Interpenetration distance is displayed in cm.",
  title.color = "black",
  caption.color = "black"
  ) 

p6 <- ggstatsplot::ggbetweenstats(
  data = ParsiDFplots,
  x = "Part",
  y = "AverageInterpenetration",
  grouping.var = "InterpenetrationFeedback",
  type = "p",
  pairwise.comparisons = FALSE,
  pairwise.display = "significant",
  p.adjust.method = "bonferroni",
  effsize.type = "unbiased",
  results.subtitle = FALSE,
  xlab = "Order",
  ylab = "Average Interpenetration",
  sample.size.label = FALSE,
  var.equal = TRUE,
  mean.plotting = FALSE,
  mean.ci = TRUE,
  paired = TRUE,
  title.text = "Interpenetration Box-Violin Plots",
  caption.text = "Note: Interpenetration distance is displayed in cm.",
  title.color = "black",
  caption.color = "black"
) 

p7 <- ggstatsplot::grouped_ggbetweenstats(
  data = ParsiDFplots,
  x = "Part",
  y = "MaxInterpenetration",
  grouping.var = "InterpenetrationFeedback",
  type = "p",
  pairwise.comparisons = FALSE,
  pairwise.display = "significant",
  p.adjust.method = "bonferroni",
  effsize.type = "unbiased",
  results.subtitle = FALSE,
  xlab = "Order",
  ylab = "Maximum Interpenetration",
  sample.size.label = FALSE,
  var.equal = TRUE,
  mean.plotting = FALSE,
  mean.ci = TRUE,
  paired = TRUE,
  title.text = "Interpenetration Box-Violin Plots",
  caption.text = "Note: Interpenetration distance is displayed in cm.",
  title.color = "black",
  caption.color = "black") 

p8 <- ggstatsplot::grouped_ggbetweenstats(
  data = ParsiDFplots,
  x = "Part",
  y = "AverageInterpenetration",
  grouping.var = "InterpenetrationFeedback",
  type = "p",
  pairwise.comparisons = FALSE,
  pairwise.display = "significant",
  p.adjust.method = "bonferroni",
  effsize.type = "unbiased",
  results.subtitle = FALSE,
  xlab = "Order",
  ylab = "Average Interpenetration",
  sample.size.label = FALSE,
  var.equal = TRUE,
  mean.plotting = FALSE,
  mean.ci = TRUE,
  paired = TRUE,
  title.text = "Interpenetration Box-Violin Plots",
  caption.text = "Note: Interpenetration distance is displayed in cm.",
  title.color = "black",
  caption.color = "black"
  ) 
p1


p2


p3 


p4


p5 


p6


p7


p8

Let’s check the Two Way Repeated Measures ANOVA

aMax <- aov_ez("ID", "MaxInterpenetration", ParsiDF,
Warning messages:
1: Unknown or uninitialised column: `Extreme1`. 
2: Unknown or uninitialised column: `Extreme2`. 
3: Unknown or uninitialised column: `Extreme1`. 
4: Unknown or uninitialised column: `Extreme2`. 
5: Unknown or uninitialised column: `Extreme1`. 
6: Unknown or uninitialised column: `Extreme2`. 
7: Unknown or uninitialised column: `Extreme1`. 
8: Unknown or uninitialised column: `Extreme2`. 
9: Unknown or uninitialised column: `Extreme1`. 
10: Unknown or uninitialised column: `Extreme2`. 
             within = c("Part", "InterpenetrationFeedback"),
             anova_table = list(es = "pes"))

knitr::kable(nice(aMax$anova_table))
Effect df MSE F pes p.value
Part 1, 20 0.06 31.62 *** .613 <.001
InterpenetrationFeedback 1.91, 38.11 0.12 29.77 *** .598 <.001
Part:InterpenetrationFeedback 2.12, 42.40 0.04 5.80 ** .225 .005
aAv <- aov_ez("ID", "AverageInterpenetration", ParsiDF,
             within = c("Part", "InterpenetrationFeedback"),
             anova_table = list(es = "pes"))

knitr::kable(nice(aAv$anova_table))
Effect df MSE F pes p.value
Part 1, 20 0.07 34.72 *** .634 <.001
InterpenetrationFeedback 1.98, 39.53 0.12 27.65 *** .580 <.001
Part:InterpenetrationFeedback 2.17, 43.30 0.04 6.63 ** .249 .002

effectsize::omega_squared(aMax, partial = TRUE, ci = 0.95)
Parameter                     | Omega2 (partial) |        95% CI
----------------------------------------------------------------
Part                          |             0.58 | [ 0.26, 0.75]
InterpenetrationFeedback      |             0.57 | [ 0.40, 0.69]
Part:InterpenetrationFeedback |             0.18 | [ 0.00, 0.34]
effectsize::omega_squared(aAv, partial = TRUE, ci = 0.95)
Parameter                     | Omega2 (partial) |       95% CI
---------------------------------------------------------------
Part                          |             0.61 | [0.29, 0.77]
InterpenetrationFeedback      |             0.56 | [0.37, 0.67]
Part:InterpenetrationFeedback |             0.21 | [0.01, 0.37]

We can see that every type of feedback as well as the interrelationship with the part of the experiment have a large effect on DVs!!!!!!

Reference for interpreting Omega Squared Small effect: ω2 = 0.01; Medium effect: ω2 = 0.06; Large effect: ω2 = 0.14.

Let’s plot the main effects (Interpenetration Feedback OR Part of the experiment).


aMaxPlots <- aov_ez("ID", "MaxInterpenetration", ParsiDFplots,
             within = c("Part", "InterpenetrationFeedback"),
             anova_table = list(es = "pes"))

aAvPlots <- aov_ez("ID", "AverageInterpenetration", ParsiDFplots,
             within = c("Part", "InterpenetrationFeedback"),
             anova_table = list(es = "pes"))


afex_plot(aMaxPlots, x = "InterpenetrationFeedback", error = "within", 
                mapping = c("linetype", "shape", "fill"),
                data_geom = ggpol::geom_boxjitter, 
                data_arg = list(width = 0.5)) +
            ylim(0, 3)
NOTE: Results may be misleading due to involvement in interactions

afex_plot(aMaxPlots, x = "Part", error = "within", 
                mapping = c("linetype", "shape", "fill"),
                data_geom = ggpol::geom_boxjitter, 
                data_arg = list(width = 0.5))  +
            ylim(0, 3)
NOTE: Results may be misleading due to involvement in interactions

afex_plot(aAvPlots, x = "InterpenetrationFeedback", error = "within", 
                mapping = c("linetype", "shape", "fill"),
                data_geom = ggpol::geom_boxjitter, 
                data_arg = list(width = 0.5)) +
            ylim(0, 2.25)
NOTE: Results may be misleading due to involvement in interactions

afex_plot(aAvPlots, x = "Part", error = "within", 
                mapping = c("linetype", "shape", "fill"),
                data_geom = ggpol::geom_boxjitter, 
                data_arg = list(width = 0.5))  +
            ylim(0, 2.25)
NOTE: Results may be misleading due to involvement in interactions

?afex_plot()

Let’s plot the main interaction effects (Interpenetration Feedback AND Part of the experiment).


afex_plot(aMaxPlots, x = "InterpenetrationFeedback", trace = "Part", error = "within", 
                mapping = c("linetype", "shape", "fill"),
                data_geom = ggpol::geom_boxjitter, 
                data_arg = list(width = 0.5)) +
            ylim(0, 3)


afex_plot(aMaxPlots, x = "Part", trace = "InterpenetrationFeedback", error = "within", 
                mapping = c("linetype", "shape", "fill"),
                data_geom = ggpol::geom_boxjitter, 
                data_arg = list(width = 0.5))  +
            ylim(0, 3)


afex_plot(aAvPlots, x = "InterpenetrationFeedback",  trace = "Part", error = "within", 
                mapping = c("linetype", "shape", "fill"),
                data_geom = ggpol::geom_boxjitter, 
                data_arg = list(width = 0.5)) +
            ylim(0, 2.25)


afex_plot(aAvPlots, x = "Part", trace = "InterpenetrationFeedback", error = "within", 
                mapping = c("linetype", "shape", "fill"),
                data_geom = ggpol:: geom_boxjitter, 
                data_arg = list(width = 0.5))  +
            ylim(0, 2.25)

Post-hoc Tests

# Main Effects
lsmMaxFeedback <- lsmeans(aMax,~ InterpenetrationFeedback)
NOTE: Results may be misleading due to involvement in interactions
contrast(lsmMax, method="pairwise", interaction = TRUE)
 InterpenetrationFeedback_pairwise estimate     SE df t.ratio p.value
 Both - Electrotactile              -0.2308 0.0597 60 -3.865  0.0003 
 Both - NoFeedback                  -0.5275 0.0597 60 -8.835  <.0001 
 Both - Visual                      -0.0921 0.0597 60 -1.543  0.1281 
 Electrotactile - NoFeedback        -0.2967 0.0597 60 -4.969  <.0001 
 Electrotactile - Visual             0.1387 0.0597 60  2.322  0.0236 
 NoFeedback - Visual                 0.4354 0.0597 60  7.292  <.0001 

Results are averaged over the levels of: Part 
lsmMaxPart <- lsmeans(aMax,~ Part)
NOTE: Results may be misleading due to involvement in interactions
contrast(lsmMax, method="pairwise", interaction = TRUE)
 InterpenetrationFeedback_pairwise estimate     SE df t.ratio p.value
 Both - Electrotactile              -0.2308 0.0597 60 -3.865  0.0003 
 Both - NoFeedback                  -0.5275 0.0597 60 -8.835  <.0001 
 Both - Visual                      -0.0921 0.0597 60 -1.543  0.1281 
 Electrotactile - NoFeedback        -0.2967 0.0597 60 -4.969  <.0001 
 Electrotactile - Visual             0.1387 0.0597 60  2.322  0.0236 
 NoFeedback - Visual                 0.4354 0.0597 60  7.292  <.0001 

Results are averaged over the levels of: Part 
lsmMaxIntEff <- lsmeans(aMax,~ InterpenetrationFeedback:Part)
contrast(lsmMax, method="pairwise", interaction = TRUE)
 InterpenetrationFeedback_pairwise estimate     SE df t.ratio p.value
 Both - Electrotactile              -0.2308 0.0597 60 -3.865  0.0003 
 Both - NoFeedback                  -0.5275 0.0597 60 -8.835  <.0001 
 Both - Visual                      -0.0921 0.0597 60 -1.543  0.1281 
 Electrotactile - NoFeedback        -0.2967 0.0597 60 -4.969  <.0001 
 Electrotactile - Visual             0.1387 0.0597 60  2.322  0.0236 
 NoFeedback - Visual                 0.4354 0.0597 60  7.292  <.0001 

Results are averaged over the levels of: Part 
lsmAvFeedback <- lsmeans(aAv,~ InterpenetrationFeedback)
NOTE: Results may be misleading due to involvement in interactions
contrast(lsmAvIntEff, method="pairwise", interaction = TRUE)
 InterpenetrationFeedback_pairwise Part_pairwise   estimate     SE df t.ratio p.value
 Both - Electrotactile             Part.1 - Part.2  -0.0995 0.0702 60 -1.417  0.1617 
 Both - NoFeedback                 Part.1 - Part.2   0.1816 0.0702 60  2.585  0.0122 
 Both - Visual                     Part.1 - Part.2   0.1333 0.0702 60  1.898  0.0625 
 Electrotactile - NoFeedback       Part.1 - Part.2   0.2811 0.0702 60  4.002  0.0002 
 Electrotactile - Visual           Part.1 - Part.2   0.2329 0.0702 60  3.315  0.0016 
 NoFeedback - Visual               Part.1 - Part.2  -0.0483 0.0702 60 -0.687  0.4946 
lsmAvPart <- lsmeans(aAv,~ Part)
NOTE: Results may be misleading due to involvement in interactions
contrast(lsmAvIntEff, method="pairwise", interaction = TRUE)
 InterpenetrationFeedback_pairwise Part_pairwise   estimate     SE df t.ratio p.value
 Both - Electrotactile             Part.1 - Part.2  -0.0995 0.0702 60 -1.417  0.1617 
 Both - NoFeedback                 Part.1 - Part.2   0.1816 0.0702 60  2.585  0.0122 
 Both - Visual                     Part.1 - Part.2   0.1333 0.0702 60  1.898  0.0625 
 Electrotactile - NoFeedback       Part.1 - Part.2   0.2811 0.0702 60  4.002  0.0002 
 Electrotactile - Visual           Part.1 - Part.2   0.2329 0.0702 60  3.315  0.0016 
 NoFeedback - Visual               Part.1 - Part.2  -0.0483 0.0702 60 -0.687  0.4946 
lsmAvIntEff <- lsmeans(aAv,~ InterpenetrationFeedback:Part)
contrast(lsmAvIntEff, method="pairwise", interaction = TRUE)
 InterpenetrationFeedback_pairwise Part_pairwise   estimate     SE df t.ratio p.value
 Both - Electrotactile             Part.1 - Part.2  -0.0928 0.0738 60 -1.258  0.2132 
 Both - NoFeedback                 Part.1 - Part.2   0.1674 0.0738 60  2.268  0.0269 
 Both - Visual                     Part.1 - Part.2   0.1509 0.0738 60  2.046  0.0452 
 Electrotactile - NoFeedback       Part.1 - Part.2   0.2602 0.0738 60  3.527  0.0008 
 Electrotactile - Visual           Part.1 - Part.2   0.2437 0.0738 60  3.304  0.0016 
 NoFeedback - Visual               Part.1 - Part.2  -0.0164 0.0738 60 -0.223  0.8243 
?lsmeans()
# Only Interaction Effects
contrast(emmeans(aMax,~ Part:InterpenetrationFeedback), 
         method="pairwise", interaction=TRUE)
 Part_pairwise   InterpenetrationFeedback_pairwise estimate     SE df t.ratio p.value
 Part.1 - Part.2 Both - Electrotactile              -0.1201 0.0718 60 -1.672  0.0997 
 Part.1 - Part.2 Both - NoFeedback                   0.1262 0.0718 60  1.757  0.0841 
 Part.1 - Part.2 Both - Visual                       0.1153 0.0718 60  1.605  0.1137 
 Part.1 - Part.2 Electrotactile - NoFeedback         0.2463 0.0718 60  3.429  0.0011 
 Part.1 - Part.2 Electrotactile - Visual             0.2354 0.0718 60  3.277  0.0017 
 Part.1 - Part.2 NoFeedback - Visual                -0.0109 0.0718 60 -0.152  0.8800 
contrast(emmeans(aMax,~ InterpenetrationFeedback:Part), 
         method="pairwise", interaction=TRUE)
 InterpenetrationFeedback_pairwise Part_pairwise   estimate     SE df t.ratio p.value
 Both - Electrotactile             Part.1 - Part.2  -0.1201 0.0718 60 -1.672  0.0997 
 Both - NoFeedback                 Part.1 - Part.2   0.1262 0.0718 60  1.757  0.0841 
 Both - Visual                     Part.1 - Part.2   0.1153 0.0718 60  1.605  0.1137 
 Electrotactile - NoFeedback       Part.1 - Part.2   0.2463 0.0718 60  3.429  0.0011 
 Electrotactile - Visual           Part.1 - Part.2   0.2354 0.0718 60  3.277  0.0017 
 NoFeedback - Visual               Part.1 - Part.2  -0.0109 0.0718 60 -0.152  0.8800 
contrast(emmeans(aAv,~ Part:InterpenetrationFeedback), 
         method="pairwise", interaction=TRUE)
 Part_pairwise   InterpenetrationFeedback_pairwise estimate     SE df t.ratio p.value
 Part.1 - Part.2 Both - Electrotactile              -0.0928 0.0738 60 -1.258  0.2132 
 Part.1 - Part.2 Both - NoFeedback                   0.1674 0.0738 60  2.268  0.0269 
 Part.1 - Part.2 Both - Visual                       0.1509 0.0738 60  2.046  0.0452 
 Part.1 - Part.2 Electrotactile - NoFeedback         0.2602 0.0738 60  3.527  0.0008 
 Part.1 - Part.2 Electrotactile - Visual             0.2437 0.0738 60  3.304  0.0016 
 Part.1 - Part.2 NoFeedback - Visual                -0.0164 0.0738 60 -0.223  0.8243 
contrast(emmeans(aAv,~ InterpenetrationFeedback:Part), 
         method="pairwise", interaction=TRUE)
 InterpenetrationFeedback_pairwise Part_pairwise   estimate     SE df t.ratio p.value
 Both - Electrotactile             Part.1 - Part.2  -0.0928 0.0738 60 -1.258  0.2132 
 Both - NoFeedback                 Part.1 - Part.2   0.1674 0.0738 60  2.268  0.0269 
 Both - Visual                     Part.1 - Part.2   0.1509 0.0738 60  2.046  0.0452 
 Electrotactile - NoFeedback       Part.1 - Part.2   0.2602 0.0738 60  3.527  0.0008 
 Electrotactile - Visual           Part.1 - Part.2   0.2437 0.0738 60  3.304  0.0016 
 NoFeedback - Visual               Part.1 - Part.2  -0.0164 0.0738 60 -0.223  0.8243 

Both Part.1 - Electrotactile Part.1 -0.2960 0.0710 95.2 -4.171 0.0017 Both Part.1 - NoFeedback Part.1 -0.4434 0.0710 95.2 -6.248 <.0001 Both Part.1 - Visual Part.1 -0.0531 0.0710 95.2 -0.749 0.9952 Both Part.1 - Both Part.2 0.2904 0.0588 64.1 4.936 0.0002

Part.2 Both - Part.2 Electrotactile -0.1965 0.0710 95.2 -2.769 0.115

LS0tDQp0aXRsZTogIkNvbnRhY3QgRXhwZXJpbWVudCBEYXRhIEFuYWx5c2lzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KRmlyc3QgU3RlcCBpcyB0byBsb2FkIHRoZSBuZWNlc3NhcnkgcGFja2FnZSwgSWYgeW91IGRvbnQgaGF2ZSB0aGVtIGp1c3QgaW5zdGFsbCB0aGVtLiBGb3IgampzdGF0c3Bsb3QgeW91IG5lZWQgdG8gaW5zdGFsbCBpdCByZW1vdGVseS4NCkp1c3QgcmVtb3ZlIHRoZSBkYXNoIGFuZCBwcmVzcyBlbnRlci4gVGhlbiBQcmVzcyAzIChub25lIHBhY2thZ2UgdG8gYmUgdXBkYXRlZCkuIA0KP2dyb3VwX2J5KCkNCg0KYGBge3J9DQojcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoInNiYWxjaS9qanN0YXRzcGxvdCIpICNQcmVzcyAzICEhISEhIGkuZS4sIGluc3RhbGxpbmcvVXBkYXRpbmcgbm9uZSBwYWNrYWdlISANCmxpYnJhcnkoam12KQ0KbGlicmFyeShkYXRhc2V0cykNCmxpYnJhcnkocGx5cikNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGRhdGFmcmFtZXMyeGxzKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShwbHlyKQ0KbGlicmFyeShnZ3N0YXRzcGxvdCkNCmxpYnJhcnkoampzdGF0c3Bsb3QpDQpsaWJyYXJ5KGxtZTQpDQpsaWJyYXJ5KGxtZXJUZXN0KQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShyc3RhdGl4KQ0KbGlicmFyeShjb2luKQ0KbGlicmFyeShBUlRvb2wpDQpsaWJyYXJ5KGdncHVicikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoImFmZXgiKSAgICAgDQpsaWJyYXJ5KCJlbW1lYW5zIikgIA0KbGlicmFyeSgibXVsdGNvbXAiKSANCg0KDQpgYGANCg0KDQoNCkltcG9ydCBhbmQgbWVyZ2UgYWxsIHRoZSBjc3YgZmlsZXMgKHguY3N2IHdoZXJlIHggPSBJRCkgb2YgdGhlIGZvbGRlci4gTm90ZSwgdGhhdCB0aGUgSUQgaXMgaGFzIGFscmVhZHkgYmVlbiBhZGRlZCBhcyBjb2x1bW4gDQpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0naGlkZScsbWVzc2FnZT1GQUxTRSxjYWNoZT1GQUxTRX0NCmRhdGEgPC0gbGlzdC5maWxlcyhwYXRoID0gIkM6L1VzZXJzL3Brb3VydGVzL0Rlc2t0b3AvQ29udGFjdEV4cGVyaW1lbnQvUmVzdWx0cy9QYXJ0aWNpcGFudHMvTWVyZ2luZ0ZvbGRlciIsICAgICAjIElkZW50aWZ5IGFsbCBjc3YgZmlsZXMgaW4gZm9sZGVyDQogICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiKi5jc3YiLCBmdWxsLm5hbWVzID0gVFJVRSkgJT4lIA0KICBsYXBwbHkocmVhZF9jc3YpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBTdG9yZSBhbGwgZmlsZXMgaW4gbGlzdA0KICBiaW5kX3Jvd3MgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBDb21iaW5lIGRhdGEgc2V0cyBpbnRvIGEgc2luZ2xlIGRhdGEgc2V0IA0KZGF0YSANCmBgYA0KDQoNCkRpc2NhcmQgZmlyc3QgWCB0cmlhbHMgcGVyIGludGVycGVuZXRyYXRpb24gZmVlZGJhY2sgY29uZGl0aW9uIGFuZCB0aGVuIGNyZWF0ZSBhIHN1bW1hcnkNCnRhYmxlIGZvciBlYWNoIHBhcnRpY2lwYW50LiBZb3UgbmVlZCB0byBkZWZpbmUgKipuclRyaWFsc1BlckJsb2NrVG9SZW1vdmUqKi4NCmBgYHtyfQ0KDQoNCmRhdGEkUGFydCA8LSBhcy5mYWN0b3IoZGF0YSRCbG9jayA8IDQpDQpsZXZlbHMoZGF0YSRQYXJ0KQ0KDQpkYXRhJFBhcnQgPC0gZmFjdG9yKGRhdGEkUGFydCxsZXZlbHMgPSBjKCJUUlVFIiwiRkFMU0UiKSwNCiAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlBhcnQgMSIsIlBhcnQgMiIpKQ0KDQpuclRyaWFsc1BlckJsb2NrVG9SZW1vdmUgPC0gMQ0KI3RyaWFsc1RvUmVtb3ZlIDwtIHNlcShmcm9tID0gMSwgdG8gPSBuclRyaWFsc1BlckJsb2NrVG9SZW1vdmUpDQoNCiAgZGF0YSA8LSAgZGF0YSAlPiUNCiAgICBncm91cF9ieShJRCwgUGFydCwgSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrLCBGdWxseVNoYWRlZCkgJT4lICMgSSBoYXZlIGFkZGVkIGhlcmUgdGhlIGZ1bGx5IHNoYWRlZCANCiAgICBzbGljZShuclRyaWFsc1BlckJsb2NrVG9SZW1vdmUrMTpuKCkpDQogICMgdG8gZG91YmxlIGNoZWNrIHdlIGFyZSBkaXNjYXJkaW5nIHRoZSByaWdodCByb3dzDQogICNwcmludChkYXRhW1tpXV0kVHJpYWwpDQoNCiAjIFRoaXMgZGYgd2lsbCBiZSB1c2VkIHRvIGNyZWF0ZSB0aGUgc3Vic2V0cyBmb3IgMXN0IHBhcnQgYW5kIDJuZCBwYXJ0IG9mIHRoZSBleHBlcmltZW50LiANCiAgDQpkYXRhJEludGVycGVuZXRyYXRpb25GZWVkYmFjayAgPC0gYXMuZmFjdG9yKGRhdGEkSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrKQ0KZGF0YSRGdWxseVNoYWRlZCA8LSBhcy5mYWN0b3IoZGF0YSRGdWxseVNoYWRlZCkNCmBgYA0KICANCiAgDQpgYGB7cn0NClBhcnNpREYgPC0gZGF0YQ0KDQoNCiMgRXhjbHVkZSB0aGUgSURzIHdoaWNoIHByb2R1Y2VkIHRoZSBleHRyZW1lIHZhbHVlcyAoaS5lLiwgPSBvciA+IDMgY29lZmZpY2llbnRzIGZyb20gdGhlIG1lYW4pDQpQYXJzaURGJElEW1BhcnNpREYkSUQgPT0gOV0gPC0gTkEgDQpQYXJzaURGJElEW1BhcnNpREYkSUQgPT0gMTddIDwtIE5BDQpQYXJzaURGJElEW1BhcnNpREYkSUQgPT0gMjBdIDwtIE5BDQoNClBhcnNpREYgPC0gbmEub21pdChQYXJzaURGKQ0KDQpQYXJzaURGIDwtIGFnZ3JlZ2F0ZSguIH4gSUQgKyBBZ2UgKyBHZW5kZXIgKyBJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2sgKyBQYXJ0LCBQYXJzaURGLCBtZWFuKQ0KDQojQmVmb3JlIENvbnZlcnNpb24gdG8gbG9nYXJpdGhtcyAoc2hvd2luZyB0aGUgYWJub3JtYWwgZGlzdHJpYnV0aW9uKQ0Kc2hhcGlyb190ZXN0KFBhcnNpREYkTWF4SW50ZXJwZW5ldHJhdGlvbikNCnNoYXBpcm9fdGVzdChQYXJzaURGJEF2ZXJhZ2VJbnRlcnBlbmV0cmF0aW9uKQ0KZ2dxcXBsb3QoUGFyc2lERiRNYXhJbnRlcnBlbmV0cmF0aW9uKQ0KZ2dxcXBsb3QoUGFyc2lERiRBdmVyYWdlSW50ZXJwZW5ldHJhdGlvbikNCg0KDQpQYXJzaURGICU+JQ0KICBncm91cF9ieShJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2ssIFBhcnQpICU+JQ0KICBzaGFwaXJvX3Rlc3QoTWF4SW50ZXJwZW5ldHJhdGlvbikgDQoNClBhcnNpREYgJT4lDQogIGdyb3VwX2J5KEludGVycGVuZXRyYXRpb25GZWVkYmFjaywgUGFydCkgJT4lDQogIHNoYXBpcm9fdGVzdChBdmVyYWdlSW50ZXJwZW5ldHJhdGlvbikgIA0KDQoNCiNBZnRlciBDb252ZXJzaW9uIG9mIHRoZSBwZXJmb3JtYW5jZSB2YXJpYWJsZXMgaW50byBsb2dzIChOb3JtYWwgRGlzdHJpYnV0aW9uKQ0KUGFyc2lERiRNYXhJbnRlcnBlbmV0cmF0aW9uIDwtIGxvZyhQYXJzaURGJE1heEludGVycGVuZXRyYXRpb24pDQoNClBhcnNpREYkQXZlcmFnZUludGVycGVuZXRyYXRpb24gPC0gbG9nKFBhcnNpREYkQXZlcmFnZUludGVycGVuZXRyYXRpb24pDQoNCnNoYXBpcm9fdGVzdChQYXJzaURGJE1heEludGVycGVuZXRyYXRpb24pDQpzaGFwaXJvX3Rlc3QoUGFyc2lERiRBdmVyYWdlSW50ZXJwZW5ldHJhdGlvbikNCmdncXFwbG90KFBhcnNpREYkTWF4SW50ZXJwZW5ldHJhdGlvbikNCmdncXFwbG90KFBhcnNpREYkQXZlcmFnZUludGVycGVuZXRyYXRpb24pDQoNCiNMZXQncyBjaGVjayB0aGUgYXNzdW1wdGlvbiBmb3IgZWFjaCBpbnRlcnBlbmV0cmF0aW9uIGZlZWRiYWNrIGFuZCBzaGFkZSBjb25kaXRpb24NClBhcnNpREYgJT4lDQogIGdyb3VwX2J5KEludGVycGVuZXRyYXRpb25GZWVkYmFjaywgUGFydCkgJT4lDQogIHNoYXBpcm9fdGVzdChNYXhJbnRlcnBlbmV0cmF0aW9uKSANCg0KUGFyc2lERiAlPiUNCiAgZ3JvdXBfYnkoSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrLCBQYXJ0KSAlPiUNCiAgc2hhcGlyb190ZXN0KEF2ZXJhZ2VJbnRlcnBlbmV0cmF0aW9uKSANCg0KaGlzdChQYXJzaURGJE1heEludGVycGVuZXRyYXRpb24sbWFpbiA9IHBhc3RlKCJIaXN0b2dyYW0gb2YgTWF4aW11bSBJbnRlcnBlbmV0cmF0aW9uIikgLCB4bGFiID0gIk1heGltdW0gSW50ZXJwZW5ldHJhdGlvbiIpDQoNCmhpc3QoUGFyc2lERiRBdmVyYWdlSW50ZXJwZW5ldHJhdGlvbiwgbWFpbiA9IHBhc3RlKCJIaXN0b2dyYW0gb2YgQXZlcmFnZSBJbnRlcnBlbmV0cmF0aW9uIikgLCB4bGFiID0gIkF2ZXJhZ2UgSW50ZXJwZW5ldHJhdGlvbiIpDQoNCmBgYA0KDQogDQoNCkxldCdzIHZpc3VhbGl6ZSB0aGUgZGF0YSBwZXIgaW50ZXJwZW5ldHJhdGlvbiBmZWVkYmFjayBhbmQvb3IgcGFydCBvZiB0aGUgZXhwZXJpbWVudCAocGFydCAxICYgcGFydCAyKS4NCmBgYHtyfQ0KDQpQYXJzaURGcGxvdHMgPC0gZGF0YSAjIEEgZGF0YWZyYW1lIGp1c3QgZm9yIHRoZSBwbG90cywgc28gd2Ugc2hvdyBldmVyeXRoaW5nIGluIHJlYWwgbnVtYmVycyBhbmQgaW4gY2VudGltZXRlcnMhDQpQYXJzaURGcGxvdHMkSURbUGFyc2lERnBsb3RzJElEID09IDldIDwtIE5BDQpQYXJzaURGcGxvdHMkSURbUGFyc2lERnBsb3RzJElEID09IDE3XSA8LSBOQQ0KUGFyc2lERnBsb3RzJElEW1BhcnNpREZwbG90cyRJRCA9PSAyMF0gPC0gTkENClBhcnNpREZwbG90cyA8LSBuYS5vbWl0KFBhcnNpREZwbG90cykNClBhcnNpREZwbG90cyA8LSBhZ2dyZWdhdGUoLiB+IElEICsgQWdlICsgR2VuZGVyICsgSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrICsgUGFydCwgUGFyc2lERnBsb3RzLCBtZWFuKQ0KDQpQYXJzaURGcGxvdHMkQXZlcmFnZUludGVycGVuZXRyYXRpb24gPC0xMDAgKiBQYXJzaURGcGxvdHMkQXZlcmFnZUludGVycGVuZXRyYXRpb24gI0NvbnZlcnRpbmcgbWV0ZXJzIHRvIGNlbnRpbWV0ZXJzDQpQYXJzaURGcGxvdHMkTWF4SW50ZXJwZW5ldHJhdGlvbiA8LSAxMDAgKiBQYXJzaURGcGxvdHMkTWF4SW50ZXJwZW5ldHJhdGlvbiAjQ29udmVydGluZyBtZXRlcnMgdG8gY2VudGltZXRlcnMNCg0KcDEgPC0gZ2dzdGF0c3Bsb3Q6OmdnYmV0d2VlbnN0YXRzKA0KICBkYXRhID0gUGFyc2lERnBsb3RzLA0KICB4ID0gIkludGVycGVuZXRyYXRpb25GZWVkYmFjayIsICNJbmRlcGVkZW50IFZhcmlhYmxlDQogIHkgPSAiTWF4SW50ZXJwZW5ldHJhdGlvbiIsICMgRGVwZWRlbnQgVmFyaWFibGUNCiAgZ3JvdXBpbmcudmFyID0gIlBhcnQiLCAjIDJuZCBJViANCiAgdHlwZSA9ICJwIiwgIyBwYXJhbWV0cmljIHRlc3QgaS5lLiwgcCB2YWx1ZXMNCiAgcGFpcndpc2UuY29tcGFyaXNvbnMgPSBGQUxTRSwgI2NvbXB1dGUgcGFpcndpc2UgY29tcGFyaXNvbnMNCiAgcGFpcndpc2UuZGlzcGxheSA9ICJzaWduaWZpY2FudCIsICMgc2hvdyBvbmx5IHRoZSBzaWduaWZpY2FudCBvbmVzDQogIHAuYWRqdXN0Lm1ldGhvZCA9ICJib25mZXJyb25pIiwgIyBjb3JyZWN0aW9uIG9mIHAtdmFsdWUNCiAgZWZmc2l6ZS50eXBlID0gInVuYmlhc2VkIiwgIyBDYWxjdWxhdGVzIHRoZSBIZWRnZSdzIGcgZm9yIHQgdGVzdHMgYW5kIHRoZSBwYXJ0aWFsIE9tZWdhIGZvciBBTk9WQQ0KICByZXN1bHRzLnN1YnRpdGxlID0gRkFMU0UsDQogIHhsYWIgPSAiVHlwZSBvZiBGZWVkYmFjayIsICNsYWJlbCBvZiBYIGF4aXMNCiAgeWxhYiA9ICJNYXhpbXVtIEludGVycGVuZXRyYXRpb24iLCAjbGFiZWwgb2YgeSBheGlzDQogIHNhbXBsZS5zaXplLmxhYmVsID0gRkFMU0UsDQogIHZhci5lcXVhbCA9IFRSVUUsICNBc3N1bWluZyBFcXVhbCB2YXJpYW5jZXMNCiAgbWVhbi5wbG90dGluZyA9IEZBTFNFLA0KICBtZWFuLmNpID0gVFJVRSwgI2Rpc3BsYXkgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgdGhlIG1lYW4NCiAgcGFpcmVkID0gVFJVRSwgI2luZGljYXRpbmcgdGhhdCB3ZSBoYXZlIGEgd2l0aGluIHN1YmplY3QgZGVzaWduDQogIHRpdGxlLnRleHQgPSAiSW50ZXJwZW5ldHJhdGlvbiBCb3gtVmlvbGluIFBsb3RzIiwNCiAgY2FwdGlvbi50ZXh0ID0gIk5vdGU6IEludGVycGVuZXRyYXRpb24gZGlzdGFuY2UgaXMgZGlzcGxheWVkIGluIGNtLiIsDQogIHRpdGxlLmNvbG9yID0gImJsYWNrIiwNCiAgY2FwdGlvbi5jb2xvciA9ICJibGFjayINCiAgKSANCg0KcDIgPC0gZ2dzdGF0c3Bsb3Q6OmdnYmV0d2VlbnN0YXRzKA0KICBkYXRhID0gUGFyc2lERnBsb3RzLA0KICB4ID0gIkludGVycGVuZXRyYXRpb25GZWVkYmFjayIsDQogIHkgPSAiQXZlcmFnZUludGVycGVuZXRyYXRpb24iLA0KICBncm91cGluZy52YXIgPSAiUGFydCIsDQogIHR5cGUgPSAicCIsDQogIHBhaXJ3aXNlLmNvbXBhcmlzb25zID0gRkFMU0UsDQogIHBhaXJ3aXNlLmRpc3BsYXkgPSAic2lnbmlmaWNhbnQiLA0KICBwLmFkanVzdC5tZXRob2QgPSAiYm9uZmVycm9uaSIsDQogIGVmZnNpemUudHlwZSA9ICJ1bmJpYXNlZCIsDQogIHJlc3VsdHMuc3VidGl0bGUgPSBGQUxTRSwNCiAgeGxhYiA9ICJUeXBlIG9mIEZlZWRiYWNrIiwNCiAgeWxhYiA9ICJBdmVyYWdlIEludGVycGVuZXRyYXRpb24iLA0KICBzYW1wbGUuc2l6ZS5sYWJlbCA9IEZBTFNFLA0KICB2YXIuZXF1YWwgPSBUUlVFLA0KICBtZWFuLnBsb3R0aW5nID0gRkFMU0UsDQogIG1lYW4uY2kgPSBUUlVFLA0KICBwYWlyZWQgPSBUUlVFLA0KICB0aXRsZS50ZXh0ID0gIkludGVycGVuZXRyYXRpb24gQm94LVZpb2xpbiBQbG90cyIsDQogIGNhcHRpb24udGV4dCA9ICJOb3RlOiBJbnRlcnBlbmV0cmF0aW9uIGRpc3RhbmNlIGlzIGRpc3BsYXllZCBpbiBjbS4iLA0KICB0aXRsZS5jb2xvciA9ICJibGFjayIsDQogIGNhcHRpb24uY29sb3IgPSAiYmxhY2siDQopDQoNCg0KIyBSZXBsaWNhdGluZyB0aGUgYWJvdmUgYnV0IHRoaXMgdGltZSB3ZSBsb29rIG9uIHRoZSBlZmZlY3Qgb2YgdGhlIHR5cGUgb2YgZmVlZGJhY2sgb24gdGhlIERWcyBpbiAxc3QgYW5kIDJuZCBQYXJ0IG9mIHRoZSBleHBlcmltZW50IGluZGl2aWR1YWxseQ0KcDMgPC0gZ2dzdGF0c3Bsb3Q6Omdyb3VwZWRfZ2diZXR3ZWVuc3RhdHMoDQogIGRhdGEgPSBQYXJzaURGcGxvdHMsDQogIHggPSAiSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrIiwNCiAgeSA9ICJNYXhJbnRlcnBlbmV0cmF0aW9uIiwNCiAgZ3JvdXBpbmcudmFyID0gIlBhcnQiLA0KICB0eXBlID0gInAiLA0KICBwYWlyd2lzZS5jb21wYXJpc29ucyA9IEZBTFNFLA0KICBwYWlyd2lzZS5kaXNwbGF5ID0gInNpZ25pZmljYW50IiwNCiAgcC5hZGp1c3QubWV0aG9kID0gImJvbmZlcnJvbmkiLA0KICBlZmZzaXplLnR5cGUgPSAidW5iaWFzZWQiLA0KICByZXN1bHRzLnN1YnRpdGxlID0gRkFMU0UsDQogIHhsYWIgPSAiVHlwZSBvZiBGZWVkYmFjayIsDQogIHlsYWIgPSAiTWF4aW11bSBJbnRlcnBlbmV0cmF0aW9uIiwNCiAgc2FtcGxlLnNpemUubGFiZWwgPSBGQUxTRSwNCiAgdmFyLmVxdWFsID0gVFJVRSwNCiAgbWVhbi5wbG90dGluZyA9IEZBTFNFLA0KICBtZWFuLmNpID0gVFJVRSwNCiAgcGFpcmVkID0gVFJVRSwNCiAgdGl0bGUudGV4dCA9ICJJbnRlcnBlbmV0cmF0aW9uIEJveC1WaW9saW4gUGxvdHMiLA0KICBjYXB0aW9uLnRleHQgPSAiTm90ZTogSW50ZXJwZW5ldHJhdGlvbiBkaXN0YW5jZSBpcyBkaXNwbGF5ZWQgaW4gY20uIiwNCiAgdGl0bGUuY29sb3IgPSAiYmxhY2siLA0KICBjYXB0aW9uLmNvbG9yID0gImJsYWNrIg0KICApIA0KDQpwNCA8LSBnZ3N0YXRzcGxvdDo6Z3JvdXBlZF9nZ2JldHdlZW5zdGF0cygNCiAgZGF0YSA9IFBhcnNpREZwbG90cywNCiAgeCA9ICJJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2siLA0KICB5ID0gIkF2ZXJhZ2VJbnRlcnBlbmV0cmF0aW9uIiwNCiAgZ3JvdXBpbmcudmFyID0gIlBhcnQiLA0KICB0eXBlID0gInAiLA0KICBwYWlyd2lzZS5jb21wYXJpc29ucyA9IEZBTFNFLA0KICBwYWlyd2lzZS5kaXNwbGF5ID0gInNpZ25pZmljYW50IiwNCiAgcC5hZGp1c3QubWV0aG9kID0gImJvbmZlcnJvbmkiLA0KICBlZmZzaXplLnR5cGUgPSAidW5iaWFzZWQiLA0KICByZXN1bHRzLnN1YnRpdGxlID0gRkFMU0UsDQogIHhsYWIgPSAiVHlwZSBvZiBGZWVkYmFjayIsDQogIHlsYWIgPSAiQXZlcmFnZSBJbnRlcnBlbmV0cmF0aW9uIiwNCiAgc2FtcGxlLnNpemUubGFiZWwgPSBGQUxTRSwNCiAgdmFyLmVxdWFsID0gVFJVRSwNCiAgbWVhbi5wbG90dGluZyA9IEZBTFNFLA0KICBtZWFuLmNpID0gVFJVRSwNCiAgcGFpcmVkID0gVFJVRSwNCiAgdGl0bGUudGV4dCA9ICJJbnRlcnBlbmV0cmF0aW9uIEJveC1WaW9saW4gUGxvdHMiLA0KICBjYXB0aW9uLnRleHQgPSAiTm90ZTogSW50ZXJwZW5ldHJhdGlvbiBkaXN0YW5jZSBpcyBkaXNwbGF5ZWQgaW4gY20uIiwNCiAgdGl0bGUuY29sb3IgPSAiYmxhY2siLA0KICBjYXB0aW9uLmNvbG9yID0gImJsYWNrIg0KKSANCg0KIyBMZXRzIGNoZWNrIHRoZSBlZmZlY3Qgb2Ygc2hhZGVkIGNvbmRpdGlvbiBvbiBEVnMNCnA1IDwtIGdnc3RhdHNwbG90OjogZ2diZXR3ZWVuc3RhdHMoDQogIGRhdGEgPSBQYXJzaURGcGxvdHMsDQogIHggPSAiUGFydCIsDQogIHkgPSAiTWF4SW50ZXJwZW5ldHJhdGlvbiIsDQogIGdyb3VwaW5nLnZhciA9ICJJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2siLA0KICB0eXBlID0gInAiLA0KICBwYWlyd2lzZS5jb21wYXJpc29ucyA9IEZBTFNFLA0KICBwYWlyd2lzZS5kaXNwbGF5ID0gInNpZ25pZmljYW50IiwNCiAgcC5hZGp1c3QubWV0aG9kID0gImJvbmZlcnJvbmkiLA0KICBlZmZzaXplLnR5cGUgPSAidW5iaWFzZWQiLA0KICByZXN1bHRzLnN1YnRpdGxlID0gRkFMU0UsDQogIHhsYWIgPSAiT3JkZXIiLA0KICB5bGFiID0gIk1heGltdW0gSW50ZXJwZW5ldHJhdGlvbiIsDQogIHNhbXBsZS5zaXplLmxhYmVsID0gRkFMU0UsDQogIHZhci5lcXVhbCA9IFRSVUUsDQogIG1lYW4ucGxvdHRpbmcgPSBGQUxTRSwNCiAgbWVhbi5jaSA9IFRSVUUsDQogIHBhaXJlZCA9IFRSVUUsDQogIHRpdGxlLnRleHQgPSAiSW50ZXJwZW5ldHJhdGlvbiBCb3gtVmlvbGluIFBsb3RzIiwNCiAgY2FwdGlvbi50ZXh0ID0gIk5vdGU6IEludGVycGVuZXRyYXRpb24gZGlzdGFuY2UgaXMgZGlzcGxheWVkIGluIGNtLiIsDQogIHRpdGxlLmNvbG9yID0gImJsYWNrIiwNCiAgY2FwdGlvbi5jb2xvciA9ICJibGFjayINCiAgKSANCg0KcDYgPC0gZ2dzdGF0c3Bsb3Q6OmdnYmV0d2VlbnN0YXRzKA0KICBkYXRhID0gUGFyc2lERnBsb3RzLA0KICB4ID0gIlBhcnQiLA0KICB5ID0gIkF2ZXJhZ2VJbnRlcnBlbmV0cmF0aW9uIiwNCiAgZ3JvdXBpbmcudmFyID0gIkludGVycGVuZXRyYXRpb25GZWVkYmFjayIsDQogIHR5cGUgPSAicCIsDQogIHBhaXJ3aXNlLmNvbXBhcmlzb25zID0gRkFMU0UsDQogIHBhaXJ3aXNlLmRpc3BsYXkgPSAic2lnbmlmaWNhbnQiLA0KICBwLmFkanVzdC5tZXRob2QgPSAiYm9uZmVycm9uaSIsDQogIGVmZnNpemUudHlwZSA9ICJ1bmJpYXNlZCIsDQogIHJlc3VsdHMuc3VidGl0bGUgPSBGQUxTRSwNCiAgeGxhYiA9ICJPcmRlciIsDQogIHlsYWIgPSAiQXZlcmFnZSBJbnRlcnBlbmV0cmF0aW9uIiwNCiAgc2FtcGxlLnNpemUubGFiZWwgPSBGQUxTRSwNCiAgdmFyLmVxdWFsID0gVFJVRSwNCiAgbWVhbi5wbG90dGluZyA9IEZBTFNFLA0KICBtZWFuLmNpID0gVFJVRSwNCiAgcGFpcmVkID0gVFJVRSwNCiAgdGl0bGUudGV4dCA9ICJJbnRlcnBlbmV0cmF0aW9uIEJveC1WaW9saW4gUGxvdHMiLA0KICBjYXB0aW9uLnRleHQgPSAiTm90ZTogSW50ZXJwZW5ldHJhdGlvbiBkaXN0YW5jZSBpcyBkaXNwbGF5ZWQgaW4gY20uIiwNCiAgdGl0bGUuY29sb3IgPSAiYmxhY2siLA0KICBjYXB0aW9uLmNvbG9yID0gImJsYWNrIg0KKSANCg0KcDcgPC0gZ2dzdGF0c3Bsb3Q6Omdyb3VwZWRfZ2diZXR3ZWVuc3RhdHMoDQogIGRhdGEgPSBQYXJzaURGcGxvdHMsDQogIHggPSAiUGFydCIsDQogIHkgPSAiTWF4SW50ZXJwZW5ldHJhdGlvbiIsDQogIGdyb3VwaW5nLnZhciA9ICJJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2siLA0KICB0eXBlID0gInAiLA0KICBwYWlyd2lzZS5jb21wYXJpc29ucyA9IEZBTFNFLA0KICBwYWlyd2lzZS5kaXNwbGF5ID0gInNpZ25pZmljYW50IiwNCiAgcC5hZGp1c3QubWV0aG9kID0gImJvbmZlcnJvbmkiLA0KICBlZmZzaXplLnR5cGUgPSAidW5iaWFzZWQiLA0KICByZXN1bHRzLnN1YnRpdGxlID0gRkFMU0UsDQogIHhsYWIgPSAiT3JkZXIiLA0KICB5bGFiID0gIk1heGltdW0gSW50ZXJwZW5ldHJhdGlvbiIsDQogIHNhbXBsZS5zaXplLmxhYmVsID0gRkFMU0UsDQogIHZhci5lcXVhbCA9IFRSVUUsDQogIG1lYW4ucGxvdHRpbmcgPSBGQUxTRSwNCiAgbWVhbi5jaSA9IFRSVUUsDQogIHBhaXJlZCA9IFRSVUUsDQogIHRpdGxlLnRleHQgPSAiSW50ZXJwZW5ldHJhdGlvbiBCb3gtVmlvbGluIFBsb3RzIiwNCiAgY2FwdGlvbi50ZXh0ID0gIk5vdGU6IEludGVycGVuZXRyYXRpb24gZGlzdGFuY2UgaXMgZGlzcGxheWVkIGluIGNtLiIsDQogIHRpdGxlLmNvbG9yID0gImJsYWNrIiwNCiAgY2FwdGlvbi5jb2xvciA9ICJibGFjayIpIA0KDQpwOCA8LSBnZ3N0YXRzcGxvdDo6Z3JvdXBlZF9nZ2JldHdlZW5zdGF0cygNCiAgZGF0YSA9IFBhcnNpREZwbG90cywNCiAgeCA9ICJQYXJ0IiwNCiAgeSA9ICJBdmVyYWdlSW50ZXJwZW5ldHJhdGlvbiIsDQogIGdyb3VwaW5nLnZhciA9ICJJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2siLA0KICB0eXBlID0gInAiLA0KICBwYWlyd2lzZS5jb21wYXJpc29ucyA9IEZBTFNFLA0KICBwYWlyd2lzZS5kaXNwbGF5ID0gInNpZ25pZmljYW50IiwNCiAgcC5hZGp1c3QubWV0aG9kID0gImJvbmZlcnJvbmkiLA0KICBlZmZzaXplLnR5cGUgPSAidW5iaWFzZWQiLA0KICByZXN1bHRzLnN1YnRpdGxlID0gRkFMU0UsDQogIHhsYWIgPSAiT3JkZXIiLA0KICB5bGFiID0gIkF2ZXJhZ2UgSW50ZXJwZW5ldHJhdGlvbiIsDQogIHNhbXBsZS5zaXplLmxhYmVsID0gRkFMU0UsDQogIHZhci5lcXVhbCA9IFRSVUUsDQogIG1lYW4ucGxvdHRpbmcgPSBGQUxTRSwNCiAgbWVhbi5jaSA9IFRSVUUsDQogIHBhaXJlZCA9IFRSVUUsDQogIHRpdGxlLnRleHQgPSAiSW50ZXJwZW5ldHJhdGlvbiBCb3gtVmlvbGluIFBsb3RzIiwNCiAgY2FwdGlvbi50ZXh0ID0gIk5vdGU6IEludGVycGVuZXRyYXRpb24gZGlzdGFuY2UgaXMgZGlzcGxheWVkIGluIGNtLiIsDQogIHRpdGxlLmNvbG9yID0gImJsYWNrIiwNCiAgY2FwdGlvbi5jb2xvciA9ICJibGFjayINCiAgKSANCnAxDQoNCnAyDQoNCnAzIA0KDQpwNA0KDQpwNSANCg0KcDYNCg0KcDcNCg0KcDgNCmBgYA0KDQpMZXQncyBjaGVjayB0aGUgVHdvIFdheSBSZXBlYXRlZCBNZWFzdXJlcyBBTk9WQQ0KYGBge3J9DQphTWF4IDwtIGFvdl9leigiSUQiLCAiTWF4SW50ZXJwZW5ldHJhdGlvbiIsIFBhcnNpREYsDQogICAgICAgICAgICAgd2l0aGluID0gYygiUGFydCIsICJJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2siKSwNCiAgICAgICAgICAgICBhbm92YV90YWJsZSA9IGxpc3QoZXMgPSAicGVzIikpDQoNCmtuaXRyOjprYWJsZShuaWNlKGFNYXgkYW5vdmFfdGFibGUpKQ0KYGBgDQoNCmBgYHtyfQ0KYUF2IDwtIGFvdl9leigiSUQiLCAiQXZlcmFnZUludGVycGVuZXRyYXRpb24iLCBQYXJzaURGLA0KICAgICAgICAgICAgIHdpdGhpbiA9IGMoIlBhcnQiLCAiSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrIiksDQogICAgICAgICAgICAgYW5vdmFfdGFibGUgPSBsaXN0KGVzID0gInBlcyIpKQ0KDQprbml0cjo6a2FibGUobmljZShhQXYkYW5vdmFfdGFibGUpKQ0KYGBgDQoNCmBgYHtyfQ0KDQplZmZlY3RzaXplOjpvbWVnYV9zcXVhcmVkKGFNYXgsIHBhcnRpYWwgPSBUUlVFLCBjaSA9IDAuOTUpDQoNCmVmZmVjdHNpemU6Om9tZWdhX3NxdWFyZWQoYUF2LCBwYXJ0aWFsID0gVFJVRSwgY2kgPSAwLjk1KQ0KDQpgYGANCg0KDQpXZSBjYW4gc2VlIHRoYXQgZXZlcnkgdHlwZSBvZiBmZWVkYmFjayBhcyB3ZWxsIGFzIHRoZSBpbnRlcnJlbGF0aW9uc2hpcCB3aXRoIHRoZSBwYXJ0IG9mIHRoZSBleHBlcmltZW50IGhhdmUgYSBsYXJnZSBlZmZlY3Qgb24gRFZzISEhISEhIA0KDQpSZWZlcmVuY2UgZm9yIGludGVycHJldGluZyBPbWVnYSBTcXVhcmVkDQpTbWFsbCBlZmZlY3Q6IM+JMiA9IDAuMDE7DQpNZWRpdW0gZWZmZWN0OiDPiTIgPSAwLjA2Ow0KTGFyZ2UgZWZmZWN0OiDPiTIgPSAwLjE0Lg0KDQoNCkxldCdzIHBsb3QgdGhlIG1haW4gZWZmZWN0cyAoSW50ZXJwZW5ldHJhdGlvbiBGZWVkYmFjayBPUiBQYXJ0IG9mIHRoZSBleHBlcmltZW50KS4NCmBgYHtyfQ0KIyBBTk9WQXMganVzdCBmb3IgdGhlIHBsb3RzDQphTWF4UGxvdHMgPC0gYW92X2V6KCJJRCIsICJNYXhJbnRlcnBlbmV0cmF0aW9uIiwgUGFyc2lERnBsb3RzLA0KICAgICAgICAgICAgIHdpdGhpbiA9IGMoIlBhcnQiLCAiSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrIiksDQogICAgICAgICAgICAgYW5vdmFfdGFibGUgPSBsaXN0KGVzID0gInBlcyIpKQ0KDQphQXZQbG90cyA8LSBhb3ZfZXooIklEIiwgIkF2ZXJhZ2VJbnRlcnBlbmV0cmF0aW9uIiwgUGFyc2lERnBsb3RzLA0KICAgICAgICAgICAgIHdpdGhpbiA9IGMoIlBhcnQiLCAiSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrIiksDQogICAgICAgICAgICAgYW5vdmFfdGFibGUgPSBsaXN0KGVzID0gInBlcyIpKQ0KDQojcGxvdHMNCmFmZXhfcGxvdChhTWF4UGxvdHMsIHggPSAiSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrIiwgZXJyb3IgPSAid2l0aGluIiwgDQogICAgICAgICAgICAgICAgbWFwcGluZyA9IGMoImxpbmV0eXBlIiwgInNoYXBlIiwgImZpbGwiKSwNCiAgICAgICAgICAgICAgICBkYXRhX2dlb20gPSBnZ3BvbDo6Z2VvbV9ib3hqaXR0ZXIsIA0KICAgICAgICAgICAgICAgIGRhdGFfYXJnID0gbGlzdCh3aWR0aCA9IDAuNSkpICsNCiAgICAgICAgICAgIHlsaW0oMCwgMykNCg0KYWZleF9wbG90KGFNYXhQbG90cywgeCA9ICJQYXJ0IiwgZXJyb3IgPSAid2l0aGluIiwgDQogICAgICAgICAgICAgICAgbWFwcGluZyA9IGMoImxpbmV0eXBlIiwgInNoYXBlIiwgImZpbGwiKSwNCiAgICAgICAgICAgICAgICBkYXRhX2dlb20gPSBnZ3BvbDo6Z2VvbV9ib3hqaXR0ZXIsIA0KICAgICAgICAgICAgICAgIGRhdGFfYXJnID0gbGlzdCh3aWR0aCA9IDAuNSkpICArDQogICAgICAgICAgICB5bGltKDAsIDMpDQoNCmFmZXhfcGxvdChhQXZQbG90cywgeCA9ICJJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2siLCBlcnJvciA9ICJ3aXRoaW4iLCANCiAgICAgICAgICAgICAgICBtYXBwaW5nID0gYygibGluZXR5cGUiLCAic2hhcGUiLCAiZmlsbCIpLA0KICAgICAgICAgICAgICAgIGRhdGFfZ2VvbSA9IGdncG9sOjpnZW9tX2JveGppdHRlciwgDQogICAgICAgICAgICAgICAgZGF0YV9hcmcgPSBsaXN0KHdpZHRoID0gMC41KSkgKw0KICAgICAgICAgICAgeWxpbSgwLCAyLjI1KQ0KDQphZmV4X3Bsb3QoYUF2UGxvdHMsIHggPSAiUGFydCIsIGVycm9yID0gIndpdGhpbiIsIA0KICAgICAgICAgICAgICAgIG1hcHBpbmcgPSBjKCJsaW5ldHlwZSIsICJzaGFwZSIsICJmaWxsIiksDQogICAgICAgICAgICAgICAgZGF0YV9nZW9tID0gZ2dwb2w6Omdlb21fYm94aml0dGVyLCANCiAgICAgICAgICAgICAgICBkYXRhX2FyZyA9IGxpc3Qod2lkdGggPSAwLjUpKSAgKw0KICAgICAgICAgICAgeWxpbSgwLCAyLjI1KQ0KYGBgDQoNCkxldCdzIHBsb3QgdGhlIG1haW4gaW50ZXJhY3Rpb24gZWZmZWN0cyAoSW50ZXJwZW5ldHJhdGlvbiBGZWVkYmFjayBBTkQgUGFydCBvZiB0aGUgZXhwZXJpbWVudCkuDQpgYGB7cn0NCg0KYWZleF9wbG90KGFNYXhQbG90cywgeCA9ICJJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2siLCB0cmFjZSA9ICJQYXJ0IiwgZXJyb3IgPSAid2l0aGluIiwgDQogICAgICAgICAgICAgICAgbWFwcGluZyA9IGMoImxpbmV0eXBlIiwgInNoYXBlIiwgImZpbGwiKSwNCiAgICAgICAgICAgICAgICBkYXRhX2dlb20gPSBnZ3BvbDo6Z2VvbV9ib3hqaXR0ZXIsIA0KICAgICAgICAgICAgICAgIGRhdGFfYXJnID0gbGlzdCh3aWR0aCA9IDAuNSkpICsNCiAgICAgICAgICAgIHlsaW0oMCwgMykNCg0KYWZleF9wbG90KGFNYXhQbG90cywgeCA9ICJQYXJ0IiwgdHJhY2UgPSAiSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrIiwgZXJyb3IgPSAid2l0aGluIiwgDQogICAgICAgICAgICAgICAgbWFwcGluZyA9IGMoImxpbmV0eXBlIiwgInNoYXBlIiwgImZpbGwiKSwNCiAgICAgICAgICAgICAgICBkYXRhX2dlb20gPSBnZ3BvbDo6Z2VvbV9ib3hqaXR0ZXIsIA0KICAgICAgICAgICAgICAgIGRhdGFfYXJnID0gbGlzdCh3aWR0aCA9IDAuNSkpICArDQogICAgICAgICAgICB5bGltKDAsIDMpDQoNCmFmZXhfcGxvdChhQXZQbG90cywgeCA9ICJJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2siLCAgdHJhY2UgPSAiUGFydCIsIGVycm9yID0gIndpdGhpbiIsIA0KICAgICAgICAgICAgICAgIG1hcHBpbmcgPSBjKCJsaW5ldHlwZSIsICJzaGFwZSIsICJmaWxsIiksDQogICAgICAgICAgICAgICAgZGF0YV9nZW9tID0gZ2dwb2w6Omdlb21fYm94aml0dGVyLCANCiAgICAgICAgICAgICAgICBkYXRhX2FyZyA9IGxpc3Qod2lkdGggPSAwLjUpKSArDQogICAgICAgICAgICB5bGltKDAsIDIuMjUpDQoNCmFmZXhfcGxvdChhQXZQbG90cywgeCA9ICJQYXJ0IiwgdHJhY2UgPSAiSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrIiwgZXJyb3IgPSAid2l0aGluIiwgDQogICAgICAgICAgICAgICAgbWFwcGluZyA9IGMoImxpbmV0eXBlIiwgInNoYXBlIiwgImZpbGwiKSwNCiAgICAgICAgICAgICAgICBkYXRhX2dlb20gPSBnZ3BvbDo6IGdlb21fYm94aml0dGVyLCANCiAgICAgICAgICAgICAgICBkYXRhX2FyZyA9IGxpc3Qod2lkdGggPSAwLjUpKSAgKw0KICAgICAgICAgICAgeWxpbSgwLCAyLjI1KQ0KDQpgYGANCg0KUG9zdC1ob2MgVGVzdHMNCmBgYHtyfQ0KIg0KIyBNYWluIEVmZmVjdHMNCmxzbU1heEZlZWRiYWNrIDwtIGxzbWVhbnMoYU1heCx+IEludGVycGVuZXRyYXRpb25GZWVkYmFjaykNCmNvbnRyYXN0KGxzbU1heCwgbWV0aG9kPXBhaXJ3aXNlLCBpbnRlcmFjdGlvbiA9IFRSVUUpDQoNCmxzbU1heFBhcnQgPC0gbHNtZWFucyhhTWF4LH4gUGFydCkNCmNvbnRyYXN0KGxzbU1heCwgbWV0aG9kPXBhaXJ3aXNlLCBpbnRlcmFjdGlvbiA9IFRSVUUpDQoNCmxzbU1heEludEVmZiA8LSBsc21lYW5zKGFNYXgsfiBJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2s6UGFydCkNCmNvbnRyYXN0KGxzbU1heCwgbWV0aG9kPXBhaXJ3aXNlLCBpbnRlcmFjdGlvbiA9IFRSVUUpDQoNCmxzbUF2RmVlZGJhY2sgPC0gbHNtZWFucyhhQXYsfiBJbnRlcnBlbmV0cmF0aW9uRmVlZGJhY2spDQpjb250cmFzdChsc21BdkludEVmZiwgbWV0aG9kPXBhaXJ3aXNlLCBpbnRlcmFjdGlvbiA9IFRSVUUpDQoNCmxzbUF2UGFydCA8LSBsc21lYW5zKGFBdix+IFBhcnQpDQpjb250cmFzdChsc21BdkludEVmZiwgbWV0aG9kPXBhaXJ3aXNlLCBpbnRlcmFjdGlvbiA9IFRSVUUpDQoNCmxzbUF2SW50RWZmIDwtIGxzbWVhbnMoYUF2LH4gSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrOlBhcnQpDQpjb250cmFzdChsc21BdkludEVmZiwgbWV0aG9kPXBhaXJ3aXNlLCBpbnRlcmFjdGlvbiA9IFRSVUUpDQoiDQoNCj9sc21lYW5zKCkNCiMgT25seSBJbnRlcmFjdGlvbiBFZmZlY3RzDQpjb250cmFzdChlbW1lYW5zKGFNYXgsfiBQYXJ0OkludGVycGVuZXRyYXRpb25GZWVkYmFjayksIA0KICAgICAgICAgbWV0aG9kPSJwYWlyd2lzZSIsIGludGVyYWN0aW9uPVRSVUUpDQoNCmNvbnRyYXN0KGVtbWVhbnMoYU1heCx+IEludGVycGVuZXRyYXRpb25GZWVkYmFjazpQYXJ0KSwgDQogICAgICAgICBtZXRob2Q9InBhaXJ3aXNlIiwgaW50ZXJhY3Rpb249VFJVRSkNCg0KY29udHJhc3QoZW1tZWFucyhhQXYsfiBQYXJ0OkludGVycGVuZXRyYXRpb25GZWVkYmFjayksIA0KICAgICAgICAgbWV0aG9kPSJwYWlyd2lzZSIsIGludGVyYWN0aW9uPVRSVUUpDQoNCmNvbnRyYXN0KGVtbWVhbnMoYUF2LH4gSW50ZXJwZW5ldHJhdGlvbkZlZWRiYWNrOlBhcnQpLCANCiAgICAgICAgIG1ldGhvZD0icGFpcndpc2UiLCBpbnRlcmFjdGlvbj1UUlVFKQ0KYGBgDQoNCiBCb3RoIFBhcnQuMSAtIEVsZWN0cm90YWN0aWxlIFBhcnQuMSAgICAgICAgICAgIC0wLjI5NjAgMC4wNzEwIDk1LjIgLTQuMTcxICAwLjAwMTcgDQogQm90aCBQYXJ0LjEgLSBOb0ZlZWRiYWNrIFBhcnQuMSAgICAgICAgICAgICAgICAtMC40NDM0IDAuMDcxMCA5NS4yIC02LjI0OCAgPC4wMDAxIA0KIEJvdGggUGFydC4xIC0gVmlzdWFsIFBhcnQuMSAgICAgICAgICAgICAgICAgICAgLTAuMDUzMSAwLjA3MTAgOTUuMiAtMC43NDkgIDAuOTk1MiANCiBCb3RoIFBhcnQuMSAtIEJvdGggUGFydC4yICAgICAgICAgICAgICAgICAgICAgICAwLjI5MDQgMC4wNTg4IDY0LjEgIDQuOTM2ICAwLjAwMDIgDQogDQpQYXJ0LjIgQm90aCAtIFBhcnQuMiBFbGVjdHJvdGFjdGlsZSAgICAgICAgICAgIC0wLjE5NjUgMC4wNzEwIDk1LjIgLTIuNzY5ICAwLjExNQ0KIA0KDQpgYGB7cn0NCg0KDQoNCmBgYA0KDQoNCmBgYHtyfQ0KDQoNCg0KYGBgDQoNCg0KYGBge3J9DQoNCg0KDQpgYGANCg0KDQpgYGB7cn0NCg0KDQoNCmBgYA0KDQoNCg0K