Setup

R notebook for analysis of saccade latency quantiles in the sacc-tDCS dataset.

kable(head(groupData))
subject stimulation leg block trial type direction deviation.start deviation.end.x deviation.end.y amplitude latency drift.x drift.y
S01 anodal baseline 1 1 lateral right 0.462897 0.170455 -0.0080638 8.02463 433 0.0953736 0.102814
S01 anodal baseline 1 1 center left 0.459092 1.032850 0.0665268 7.16262 439 0.0953736 0.102814
S01 anodal baseline 1 2 lateral right 0.344561 -0.344967 0.2197400 7.74873 291 0.0953736 0.102814
S01 anodal baseline 1 2 center left 0.550230 0.361201 0.3507760 7.43233 198 0.0953736 0.102814
S01 anodal baseline 1 3 lateral right 0.514736 -0.588470 0.1673250 7.61080 281 0.0953736 0.102814
S01 anodal baseline 1 3 center left 0.620728 1.576610 0.4031910 6.35043 376 0.0953736 0.102814
  • subject: subject ID
  • stimulation: Whether data are from the anodal or cathodal session
  • leg: Whether data are before (pre), during (tDCS), or after (post.1, post.2) tDCS
  • block: After each block participant had a brief break and tracker was recalibrated
  • trial: trial number within a block
  • type:
    • lateral - fixation in center of display, saccade made towards the periphery
    • center - fixation in periphery, saccade made back towards the center of the display
  • direction: left for saccades towards the left of current fixation position; right for saccades to the right
  • deviation.start : distance (in visual angle) from saccade start point to fixation
  • deviation.end.x: distance (in visual angle) from x-coordinate of saccade end point to x-coordinate of target location
  • deviation.end.y: same for y-coordinate
  • amplitude: distance (in visual angle) between saccade start and end point
  • latency: time (in ms) from target onset to start of saccade
  • drift.x: distance (in visual angle) between x-coordinate of average fixation position during the break to x-coordinate of fixation stimulus. This stimulus was displayed at each break in the task, so this data can be used as an estimate of offsets to do drift correction.
  • drift.y: same for y-coordinate

Shift function analysis

This analysis is based on Rand Wilcox’s shift function (for dependent groups), as published in Wilcox, R. R., & Erceg-Hurn, D. M. (2012). Comparing two dependent groups via quantiles. Journal of Applied Statistics, 39(12), 2655-2664. It uses the implementation in the rogme package. See the accompanying paper and code for much more info.

Estimate quantiles and compute shift function

Briefly, the code below performs the following steps:

  • Compute the deciles (10% quantiles) for each individual subject’s distribution of saccade latencies, for each condition, using the Harrell-Davis quantile estimator. This procedure uses a weighted average of order statistics (based on the data points) to estimate each quantile, so it tends to be more precise than simple methods, and it is said to perform well in a wide variety of cases.
  • Take two of these distributions (in this case, the anodal and cathodal sessions) and subtract the deciles to look at the difference. A plot of the decile differences vs. the deciles in one condition is called a shift function.
  • Compute 95% confidence intervals with a percentile bootstrap of the decile differences. If the confidence interval of a particular decile difference does not include zero, the difference is significant. The confidence intervals are not corrected for multiple comparisons, but the p-values are (using Hochberg’s method).
qData <- groupData %>%
  filter(!is.na(latency)) %>% # discard missing saccades
  group_by(subject,leg,type,direction) %>% # for each condition
  nest(stimulation,latency) %>% # make a list_column "data" out of the stimulation and latency columns. Now, each group has its own data frame consisting of the stimulation and latency columns for that group
  mutate(shift = purrr::map(data, ~ shiftdhd_pbci(., formula = latency ~ stimulation, nboot = 2000))) # for each group, estimate quantiles and compute shift function, and store as a list column in "shift"

qData <- unnest(qData,shift) # unpack the list column to get the model results for each group in the original data frame

# Alternatively, instead of "nest ...", "mutate ..." and "unnest ...", you can call shiftdhd through dplyr::do (but this is basically depreated in favor of purrr:map)
# do(shiftdhd(.[,c("stimulation","latency")], formula = latency ~ stimulation, nboot = 100)) # estimate quantiles and compute shift function

This takes quite a while to compute with a large number of bootstrap samples, so write the data file to disk. The current and next code chunk are not evaluated by default! (eval=FALSE)

write_csv(qData, here("data", "sacc-tDCS_quantiles.csv"))

Summary plots

Add decile codes and anodal medians to data frame, for plotting:

For each quantile, count which subjects show significant effects, and in which direction:

Lateral saccades

Shift functions:

ggplot(filter(qStats, type == "lateral"), aes(anodal, difference)) +
   facet_grid(leg ~ direction) +
   geom_hline(yintercept = 0, linetype = "dashed", alpha = 0.5) +
   geom_vline(aes(xintercept = anodal_median), linetype = "dashed", alpha = 0.5) +
   stat_summary(fun.data = mean_cl_normal, geom = "linerange", colour = "black", size = 0.5) +
   stat_summary(fun.y = mean, geom = "line", size = 1, colour = "grey50", alpha = 0.5) +
   stat_summary(fun.y = mean, geom = "point", aes(fill = deco), size = 2, colour = "black", shape = 21) +
   scale_fill_gradient(low = "white", high = "grey30", guide = FALSE) +
   scale_x_continuous("anodal deciles (ms)", limits = c(80,200), breaks = seq(100,200,25)) +
   scale_y_continuous("anodal - cathodal deciles (ms)")

It looks like the slowest saccades show the biggest difference for most conditions. Curiously, cathodal tDCS there leads to faster latencies. However, this pattern already seems to be present in the baseline.

Let’s examine the number of subjects with a signifcant difference per quantile:

ggplot(filter(qSig, type == "lateral", !is.na(significance)), aes(q, fill = significance)) +
  facet_grid(leg ~ direction) +
  geom_bar(position = "stack") +
  stat_bin(binwidth = .1, geom = "text", size = 2, aes(label = ..count..), position = position_stack(vjust = 0.5)) +
  scale_fill_manual(values = c("#F25F5C", "#4B93B1")) +
  scale_x_continuous("decile", breaks = seq(0.1,0.9,0.1), labels = seq(1,9,1)) +
  scale_y_continuous("number of participants with significant difference", limits = c(0, length(unique(qSig$subject))), breaks = c(0,10,20,length(unique(qSig$subject))))

This effect in the right tail seems to be driven by a relatively small number of participants, and a sizable number of participants also shows an anodal effect there… Further, if anyhting, the most significant differences are in the baseline block…

Center saccades

ggplot(filter(qStats, type == "center"), aes(anodal, difference)) +
   facet_grid(leg ~ direction) +
   geom_hline(yintercept = 0, linetype = "dashed", alpha = 0.5) +
   geom_vline(aes(xintercept = anodal_median), linetype = "dashed", alpha = 0.5) +
   stat_summary(fun.data = mean_cl_normal, geom = "linerange", colour = "black", size = 0.5) +
   stat_summary(fun.y = mean, geom = "line", size = 1, colour = "grey50", alpha = 0.5) +
   stat_summary(fun.y = mean, geom = "point", aes(fill = deco), size = 2, colour = "black", shape = 21) +
   scale_fill_gradient(low = "white", high = "grey30", guide = FALSE) +
   scale_x_continuous("anodal deciles (ms)", limits = c(80,200), breaks = seq(100,200,25)) +
   scale_y_continuous("anodal - cathodal deciles (ms)")

There the pattern appears opposite: the greatest difference is in the fastest saccades. It makes sense that these would be most impacted for center saccades. They could be impulsive errors that are increased with stimulation (though again, cathodal leads to faster latencies, which is unexpected). But again, this pattern is present across the board.

ggplot(filter(qSig, type == "center", !is.na(significance)), aes(q, fill = significance)) +
  facet_grid(leg ~ direction) +
  geom_bar(position = "stack") +
  stat_bin(binwidth = .1, geom = "text", size = 2, aes(label = ..count..), position = position_stack(vjust = 0.5)) +
  scale_fill_manual(values = c("#F25F5C", "#4B93B1")) +
  scale_x_continuous("decile", breaks = seq(0.1,0.9,0.1), labels = seq(1,9,1)) +
  scale_y_continuous("number of participants with significant difference", limits = c(0, length(unique(qSig$subject))), breaks = c(0,10,20,length(unique(qSig$subject))))

The strongest effects are again significant in fewer subjects, and on the whole there is never an effect in one direction which is significant in more than half the sample.

Individual shift functions

Let’s plot the shift functions for each subject for the left-lateral condition (of main interest as Kanai et al. (2012) found effects of anodal tDCS there).

Baseline

ggplot(filter(qStats, leg == "baseline", type  == "lateral", direction == "left"), aes(anodal, difference)) +
  facet_wrap(~subject, ncol = 5, scales = "free") +
  geom_hline(yintercept = 0, linetype = "dashed", alpha = 0.5) +
  geom_vline(aes(xintercept = anodal_median), linetype = "dashed", alpha = 0.5) +
  geom_linerange(aes(ymin=ci_lower, ymax=ci_upper), colour = "black", size = 0.5) +
  geom_line(size = 1, colour = "grey50", alpha = 0.5) +
  geom_point(aes(fill = deco), size = 2, colour = "black", shape = 21) +
  scale_fill_gradient(low = "white", high = "grey30", guide = FALSE) +
  xlab("anodal deciles") +
  ylab("anodal - cathodal deciles (ms)") +
  ggtitle("Left lateral saccades during baseline")

During tDCS

ggplot(filter(qStats, leg == "tDCS", type  == "lateral", direction == "left"), aes(anodal, difference)) +
  facet_wrap(~subject, ncol = 5, scales = "free") +
  geom_hline(yintercept = 0, linetype = "dashed", alpha = 0.5) +
  geom_vline(aes(xintercept = anodal_median), linetype = "dashed", alpha = 0.5) +
  geom_linerange(aes(ymin=ci_lower, ymax=ci_upper), colour = "black", size = 0.5) +
  geom_line(size = 1, colour = "grey50", alpha = 0.5) +
  geom_point(aes(fill = deco), size = 2, colour = "black", shape = 21) +
  scale_fill_gradient(low = "white", high = "grey30", guide = FALSE) +
  xlab("anodal deciles") +
  ylab("anodal - cathodal deciles (ms)") +
  ggtitle("Left lateral saccades during tDCS")

After tDCS (0-15 min)

ggplot(filter(qStats, leg == "post-1", type  == "lateral", direction == "left"), aes(anodal, difference)) +
  facet_wrap(~subject, ncol = 5, scales = "free") +
  geom_hline(yintercept = 0, linetype = "dashed", alpha = 0.5) +
  geom_vline(aes(xintercept = anodal_median), linetype = "dashed", alpha = 0.5) +
  geom_linerange(aes(ymin=ci_lower, ymax=ci_upper), colour = "black", size = 0.5) +
  geom_line(size = 1, colour = "grey50", alpha = 0.5) +
  geom_point(aes(fill = deco), size = 2, colour = "black", shape = 21) +
  scale_fill_gradient(low = "white", high = "grey30", guide = FALSE) +
  xlab("anodal deciles") +
  ylab("anodal - cathodal deciles (ms)") +
  ggtitle("Left lateral saccades post-tDCS (0-15 min)")

After tDCS (15-30 min)

ggplot(filter(qStats, leg == "post-2", type  == "lateral", direction == "left"), aes(anodal, difference)) +
  facet_wrap(~subject, ncol = 5, scales = "free") +
  geom_hline(yintercept = 0, linetype = "dashed", alpha = 0.5) +
  geom_vline(aes(xintercept = anodal_median), linetype = "dashed", alpha = 0.5) +
  geom_linerange(aes(ymin=ci_lower, ymax=ci_upper), colour = "black", size = 0.5) +
  geom_line(size = 1, colour = "grey50", alpha = 0.5) +
  geom_point(aes(fill = deco), size = 2, colour = "black", shape = 21) +
  scale_fill_gradient(low = "white", high = "grey30", guide = FALSE) +
  xlab("anodal deciles") +
  ylab("anodal - cathodal deciles (ms)") +
  ggtitle("Left lateral saccades post-tDCS (15-30 min)")

LS0tCnRpdGxlOiAic2FjYy10RENTOiBTYWNjYWRlIGxhdGVuY3kgcXVhbnRpbGUgYW5hbHlzaXMiCmF1dGhvcjogIkxlb24gUmV0ZWlnIgpvdXRwdXQ6CiAgZ2l0aHViX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDIKICBodG1sX25vdGVib29rOgogICAgaGlnaGxpZ2h0OiBweWdtZW50cwogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgojIFNldHVwCgpSIG5vdGVib29rIGZvciBhbmFseXNpcyBvZiBzYWNjYWRlIGxhdGVuY3kgcXVhbnRpbGVzIGluIHRoZSBgc2FjYy10RENTYCBkYXRhc2V0LgoKYGBge3Igc2V0dXB9CiMgTG9hZCBzb21lIGxpYnJhcmllcwpsaWJyYXJ5KGhlcmUpICMgZmlsZSBwYXRocwpsaWJyYXJ5KHRpZHl2ZXJzZSkgIyBnZ3Bsb3QyLCB0aWJibGUsIHRpZHlyLCByZWFkciwgcHVycnIsIGFuZCBkcGx5cgpsaWJyYXJ5KHJvZ21lKSAjIHJvYnVzdCBncmFwaGljYWwgbWV0aG9kcyAocXVhbnRpbGUgZXN0aW1hdGlvbiwgc2hpZnQgZnVuY3Rpb24pCmxpYnJhcnkoa25pdHIpICMgUiBtYXJrZG93biBvdXRwdXQgKGh0bWwsIHBkZiwgZXRjLikKIyBzZXQgZGVmYXVsdCBvdXRwdXQgYW5kIGZpZ3VyZSBvcHRpb25zCmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgZmlnLndpZHRoID0gNywgZmlnLmFzcCA9IDAuNjE4LCBvdXQud2lkdGggPSAiNzUlIiwgZmlnLmFsaWduID0gImNlbnRlciIpCgpzZXNzaW9uSW5mbygpCmBgYAoKYGBge3IgTG9hZCB0aGUgZGF0YSBmcmFtZX0KIyBMb2FkIHRoZSBkYXRhIGZyYW1lCmRhdGFGaWxlIDwtIGhlcmUoImRhdGEiLCAic2FjYy10RENTX2RhdGEuY3N2IikKZ3JvdXBEYXRhIDwtIHJlYWRfY3N2KGRhdGFGaWxlLCBjb2xfbmFtZXMgPSBUUlVFLCBuYSA9ICJOYU4iLCBwcm9ncmVzcyA9IEZBTFNFLCBjb2xfdHlwZXMgPSBjb2xzKAogIHN0aW11bGF0aW9uID0gY29sX2ZhY3RvcihjKCJhbm9kYWwiLCJjYXRob2RhbCIpKSwKICBsZWcgPSBjb2xfZmFjdG9yKGMoInByZSIsInREQ1MiLCJwb3N0IikpLAogIHR5cGUgPSBjb2xfZmFjdG9yKGMoImxhdGVyYWwiLCJjZW50ZXIiKSksCiAgZGlyZWN0aW9uID0gY29sX2ZhY3RvcihjKCJsZWZ0IiwicmlnaHQiKSkgCikpCmBgYAoKYGBge3IgTWFrZSBzZXBhcmF0ZSBsZWcgb3V0IG9mIGZpbmFsIDMgcG9zdCBibG9ja3N9CiMgTG9hZCB0aGUgZGF0YSBmcmFtZQpncm91cERhdGEgPC0gbXV0YXRlKGdyb3VwRGF0YSwKICAgICAgICAgICAgICAgICAgICBsZWcgPSBhcy5jaGFyYWN0ZXIobGVnKSwgIyBjYW5ub3QgZWRpdCBsZWcgaWYgaXQncyBzdGlsbCBhIGZhY3RvcgogICAgICAgICAgICAgICAgICAgIGxlZyA9IHJlcGxhY2UobGVnLCBsZWcgPT0gInByZSIsICJiYXNlbGluZSIpLAogICAgICAgICAgICAgICAgICAgIGxlZyA9IHJlcGxhY2UobGVnLCBsZWcgPT0gInBvc3QiLCAicG9zdC0xIiksCiAgICAgICAgICAgICAgICAgICAgbGVnID0gcmVwbGFjZShsZWcsIGJsb2NrID4gMywgInBvc3QtMiIpLAogICAgICAgICAgICAgICAgICAgIGxlZyA9IGZhY3RvcihsZWcsIGxldmVscyA9IGMoImJhc2VsaW5lIiwgInREQ1MiLCAicG9zdC0xIiwgInBvc3QtMiIpKSAjIHJlZmFjdG9yIGFuZCBvcmRlciBsZXZlbHMKICAgICAgICAgICAgICAgICAgICApCmBgYAoKYGBge3IgU2hvdyBkYXRhIGZyYW1lfQprYWJsZShoZWFkKGdyb3VwRGF0YSkpCmBgYAoKKiBfX3N1YmplY3RfXzogc3ViamVjdCBJRAoqIF9fc3RpbXVsYXRpb25fXzogV2hldGhlciBkYXRhIGFyZSBmcm9tIHRoZSBhbm9kYWwgb3IgY2F0aG9kYWwgc2Vzc2lvbgoqIF9fbGVnX186IFdoZXRoZXIgZGF0YSBhcmUgYmVmb3JlIChgcHJlYCksIGR1cmluZyAoYHREQ1NgKSwgb3IgYWZ0ZXIgKGBwb3N0LjFgLCBgcG9zdC4yYCkgdERDUwoqIF9fYmxvY2tfXzogQWZ0ZXIgZWFjaCBibG9jayBwYXJ0aWNpcGFudCBoYWQgYSBicmllZiBicmVhayBhbmQgdHJhY2tlciB3YXMgcmVjYWxpYnJhdGVkCiogX190cmlhbF9fOiB0cmlhbCBudW1iZXIgd2l0aGluIGEgYmxvY2sKKiBfX3R5cGVfXzoKICAgICogYGxhdGVyYWxgIC0gZml4YXRpb24gaW4gY2VudGVyIG9mIGRpc3BsYXksIHNhY2NhZGUgbWFkZSB0b3dhcmRzIHRoZSBwZXJpcGhlcnkKICAgICogYGNlbnRlcmAgLSBmaXhhdGlvbiBpbiBwZXJpcGhlcnksIHNhY2NhZGUgbWFkZSBiYWNrIHRvd2FyZHMgdGhlIGNlbnRlciBvZiB0aGUgZGlzcGxheQoqIF9fZGlyZWN0aW9uX186IGBsZWZ0YCBmb3Igc2FjY2FkZXMgdG93YXJkcyB0aGUgbGVmdCBvZiBjdXJyZW50IGZpeGF0aW9uIHBvc2l0aW9uOyBgcmlnaHRgIGZvciBzYWNjYWRlcyB0byB0aGUgcmlnaHQKKiBfX2RldmlhdGlvbi5zdGFydF9fIDogZGlzdGFuY2UgKGluIHZpc3VhbCBhbmdsZSkgZnJvbSBzYWNjYWRlIHN0YXJ0IHBvaW50IHRvIGZpeGF0aW9uCiogX19kZXZpYXRpb24uZW5kLnhfXzogZGlzdGFuY2UgKGluIHZpc3VhbCBhbmdsZSkgZnJvbSB4LWNvb3JkaW5hdGUgb2Ygc2FjY2FkZSBlbmQgcG9pbnQgdG8geC1jb29yZGluYXRlIG9mIHRhcmdldCBsb2NhdGlvbgoqIF9fZGV2aWF0aW9uLmVuZC55X186IHNhbWUgZm9yIHktY29vcmRpbmF0ZQoqIF9fYW1wbGl0dWRlX186IGRpc3RhbmNlIChpbiB2aXN1YWwgYW5nbGUpIGJldHdlZW4gc2FjY2FkZSBzdGFydCBhbmQgZW5kIHBvaW50CiogX19sYXRlbmN5X186IHRpbWUgKGluIG1zKSBmcm9tIHRhcmdldCBvbnNldCB0byBzdGFydCBvZiBzYWNjYWRlCiogX19kcmlmdC54X186IGRpc3RhbmNlIChpbiB2aXN1YWwgYW5nbGUpIGJldHdlZW4geC1jb29yZGluYXRlIG9mIGF2ZXJhZ2UgZml4YXRpb24gcG9zaXRpb24gZHVyaW5nIHRoZSBicmVhayB0byB4LWNvb3JkaW5hdGUgb2YgZml4YXRpb24gc3RpbXVsdXMuIFRoaXMgc3RpbXVsdXMgd2FzIGRpc3BsYXllZCBhdCBlYWNoIGJyZWFrIGluIHRoZSB0YXNrLCBzbyB0aGlzIGRhdGEgY2FuIGJlIHVzZWQgYXMgYW4gZXN0aW1hdGUgb2Ygb2Zmc2V0cyB0byBkbyBkcmlmdCBjb3JyZWN0aW9uLgoqIF9fZHJpZnQueV9fOiBzYW1lIGZvciB5LWNvb3JkaW5hdGUKCiMgU2hpZnQgZnVuY3Rpb24gYW5hbHlzaXMKClRoaXMgYW5hbHlzaXMgaXMgYmFzZWQgb24gUmFuZCBXaWxjb3gncyBzaGlmdCBmdW5jdGlvbiAoZm9yIGRlcGVuZGVudCBncm91cHMpLCBhcyBwdWJsaXNoZWQgaW4gW1dpbGNveCwgUi4gUi4sICYgRXJjZWctSHVybiwgRC4gTS4gKDIwMTIpLiBDb21wYXJpbmcgdHdvIGRlcGVuZGVudCBncm91cHMgdmlhIHF1YW50aWxlcy4gSm91cm5hbCBvZiBBcHBsaWVkIFN0YXRpc3RpY3MsIDM5KDEyKSwgMjY1NS0yNjY0XShodHRwOi8vZHguZG9pLm9yZy8xMC4xMDgwLzAyNjY0NzYzLjIwMTIuNzI0NjY1KS4gSXQgdXNlcyB0aGUgaW1wbGVtZW50YXRpb24gaW4gdGhlIFtgcm9nbWVgIHBhY2thZ2VdKGh0dHBzOi8vZ2l0aHViLmNvbS9HUm91c3NlbGV0L3JvZ21lKS4gU2VlIHRoZSBbYWNjb21wYW55aW5nIHBhcGVyIGFuZCBjb2RlXShodHRwczovL2ZpZ3NoYXJlLmNvbS9hcnRpY2xlcy9Nb2Rlcm5fZ3JhcGhpY2FsX21ldGhvZHNfdG9fY29tcGFyZV90d29fZ3JvdXBzX29mX29ic2VydmF0aW9ucy80MDU1OTcwKSBmb3IgbXVjaCBtb3JlIGluZm8uCgojIyBFc3RpbWF0ZSBxdWFudGlsZXMgYW5kIGNvbXB1dGUgc2hpZnQgZnVuY3Rpb24KCkJyaWVmbHksIHRoZSBjb2RlIGJlbG93IHBlcmZvcm1zIHRoZSBmb2xsb3dpbmcgc3RlcHM6CgoqIENvbXB1dGUgdGhlIGRlY2lsZXMgKDEwJSBxdWFudGlsZXMpIGZvciBlYWNoIGluZGl2aWR1YWwgc3ViamVjdCdzIGRpc3RyaWJ1dGlvbiBvZiBzYWNjYWRlIGxhdGVuY2llcywgZm9yIGVhY2ggY29uZGl0aW9uLCB1c2luZyB0aGUgIFtIYXJyZWxsLURhdmlzIHF1YW50aWxlIGVzdGltYXRvcl0oaHR0cHM6Ly9nYXJzdGF0cy53b3JkcHJlc3MuY29tLzIwMTYvMDYvMDkvdGhlLWhhcnJlbGwtZGF2aXMtcXVhbnRpbGUtZXN0aW1hdG9yLykuIFRoaXMgcHJvY2VkdXJlIHVzZXMgYSB3ZWlnaHRlZCBhdmVyYWdlIG9mIG9yZGVyIHN0YXRpc3RpY3MgKGJhc2VkIG9uIHRoZSBkYXRhIHBvaW50cykgdG8gZXN0aW1hdGUgZWFjaCBxdWFudGlsZSwgc28gaXQgdGVuZHMgdG8gYmUgbW9yZSBwcmVjaXNlIHRoYW4gc2ltcGxlIG1ldGhvZHMsIGFuZCBpdCBpcyBzYWlkIHRvIHBlcmZvcm0gd2VsbCBpbiBhIHdpZGUgdmFyaWV0eSBvZiBjYXNlcy4KKiBUYWtlIHR3byBvZiB0aGVzZSBkaXN0cmlidXRpb25zIChpbiB0aGlzIGNhc2UsIHRoZSBfYW5vZGFsXyBhbmQgX2NhdGhvZGFsXyBzZXNzaW9ucykgYW5kIHN1YnRyYWN0IHRoZSBkZWNpbGVzIHRvIGxvb2sgYXQgdGhlIGRpZmZlcmVuY2UuIEEgcGxvdCBvZiB0aGUgZGVjaWxlIGRpZmZlcmVuY2VzIHZzLiB0aGUgZGVjaWxlcyBpbiBvbmUgY29uZGl0aW9uIGlzIGNhbGxlZCBhIFtzaGlmdCBmdW5jdGlvbl0oaHR0cHM6Ly9nYXJzdGF0cy53b3JkcHJlc3MuY29tLzIwMTYvMDcvMTIvc2hpZnQtZnVuY3Rpb24vKS4KKiBDb21wdXRlIDk1JSBjb25maWRlbmNlIGludGVydmFscyB3aXRoIGEgcGVyY2VudGlsZSBib290c3RyYXAgb2YgdGhlIGRlY2lsZSBkaWZmZXJlbmNlcy4gSWYgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgb2YgYSBwYXJ0aWN1bGFyIGRlY2lsZSBkaWZmZXJlbmNlIGRvZXMgbm90IGluY2x1ZGUgemVybywgdGhlIGRpZmZlcmVuY2UgaXMgc2lnbmlmaWNhbnQuIFRoZSBjb25maWRlbmNlIGludGVydmFscyBhcmUgKipub3QqKiBjb3JyZWN0ZWQgZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zLCBidXQgdGhlIHAtdmFsdWVzIGFyZSAodXNpbmcgSG9jaGJlcmcncyBtZXRob2QpLgoKYGBge3IgUXVhbnRpbGVzIGFuZCBzaGlmdCBmdW5jdGlvbiwgZXZhbD1GQUxTRX0KcURhdGEgPC0gZ3JvdXBEYXRhICU+JQogIGZpbHRlcighaXMubmEobGF0ZW5jeSkpICU+JSAjIGRpc2NhcmQgbWlzc2luZyBzYWNjYWRlcwogIGdyb3VwX2J5KHN1YmplY3QsbGVnLHR5cGUsZGlyZWN0aW9uKSAlPiUgIyBmb3IgZWFjaCBjb25kaXRpb24KICBuZXN0KHN0aW11bGF0aW9uLGxhdGVuY3kpICU+JSAjIG1ha2UgYSBsaXN0X2NvbHVtbiAiZGF0YSIgb3V0IG9mIHRoZSBzdGltdWxhdGlvbiBhbmQgbGF0ZW5jeSBjb2x1bW5zLiBOb3csIGVhY2ggZ3JvdXAgaGFzIGl0cyBvd24gZGF0YSBmcmFtZSBjb25zaXN0aW5nIG9mIHRoZSBzdGltdWxhdGlvbiBhbmQgbGF0ZW5jeSBjb2x1bW5zIGZvciB0aGF0IGdyb3VwCiAgbXV0YXRlKHNoaWZ0ID0gcHVycnI6Om1hcChkYXRhLCB+IHNoaWZ0ZGhkX3BiY2koLiwgZm9ybXVsYSA9IGxhdGVuY3kgfiBzdGltdWxhdGlvbiwgbmJvb3QgPSAyMDAwKSkpICMgZm9yIGVhY2ggZ3JvdXAsIGVzdGltYXRlIHF1YW50aWxlcyBhbmQgY29tcHV0ZSBzaGlmdCBmdW5jdGlvbiwgYW5kIHN0b3JlIGFzIGEgbGlzdCBjb2x1bW4gaW4gInNoaWZ0IgoKcURhdGEgPC0gdW5uZXN0KHFEYXRhLHNoaWZ0KSAjIHVucGFjayB0aGUgbGlzdCBjb2x1bW4gdG8gZ2V0IHRoZSBtb2RlbCByZXN1bHRzIGZvciBlYWNoIGdyb3VwIGluIHRoZSBvcmlnaW5hbCBkYXRhIGZyYW1lCgojIEFsdGVybmF0aXZlbHksIGluc3RlYWQgb2YgIm5lc3QgLi4uIiwgIm11dGF0ZSAuLi4iIGFuZCAidW5uZXN0IC4uLiIsIHlvdSBjYW4gY2FsbCBzaGlmdGRoZCB0aHJvdWdoIGRwbHlyOjpkbyAoYnV0IHRoaXMgaXMgYmFzaWNhbGx5IGRlcHJlYXRlZCBpbiBmYXZvciBvZiBwdXJycjptYXApCiMgZG8oc2hpZnRkaGQoLlssYygic3RpbXVsYXRpb24iLCJsYXRlbmN5IildLCBmb3JtdWxhID0gbGF0ZW5jeSB+IHN0aW11bGF0aW9uLCBuYm9vdCA9IDEwMCkpICMgZXN0aW1hdGUgcXVhbnRpbGVzIGFuZCBjb21wdXRlIHNoaWZ0IGZ1bmN0aW9uCmBgYAoKVGhpcyB0YWtlcyBxdWl0ZSBhIHdoaWxlIHRvIGNvbXB1dGUgd2l0aCBhIGxhcmdlIG51bWJlciBvZiBib290c3RyYXAgc2FtcGxlcywgc28gd3JpdGUgdGhlIGRhdGEgZmlsZSB0byBkaXNrLiBUaGUgY3VycmVudCBhbmQgbmV4dCBjb2RlIGNodW5rIGFyZSBub3QgZXZhbHVhdGVkIGJ5IGRlZmF1bHQhIChgZXZhbD1GQUxTRWApCgpgYGB7ciBXcml0ZSBxdWFudGlsZSBkYXRhLCBldmFsPUZBTFNFfQoKd3JpdGVfY3N2KHFEYXRhLCBoZXJlKCJkYXRhIiwgInNhY2MtdERDU19xdWFudGlsZXMuY3N2IikpCgpgYGAKCmBgYHtyIExvYWQgcXVhbnRpbGUgZGF0YX0Kc3ViczJleGNsdWRlIDwtIHN1YnMyZXhjbHVkZSA8LSBjKCJTMjEiLCJTMjUiLCJTMTYiLCJTMjIiLCJTMjgiKSAKcURhdGEgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YSIsICJzYWNjLXREQ1NfcXVhbnRpbGVzLmNzdiIpKSAlPiUKICBmaWx0ZXIoIShzdWJqZWN0ICVpbiUgc3ViczJleGNsdWRlKSkgJT4lICMgZXhjbHVkZSBzdWJqZWN0cwogICAgbXV0YXRlKGxlZyA9IHJlcGxhY2UobGVnLCBsZWcgPT0gInByZSIsICJiYXNlbGluZSIpLCAjIHJlbmFtZSBhbmQgcmVvZGVyIGxldmVscwogICAgICAgICBsZWcgPSByZXBsYWNlKGxlZywgbGVnID09ICJwb3N0LjEiLCAicG9zdC0xIiksCiAgICAgICAgIGxlZyA9IHJlcGxhY2UobGVnLCBsZWcgPT0gInBvc3QuMiIsICJwb3N0LTIiKSwKICAgICAgICAgbGVnID0gZmFjdG9yKGxlZywgbGV2ZWxzID0gYygiYmFzZWxpbmUiLCAidERDUyIsICJwb3N0LTEiLCAicG9zdC0yIikpKQpgYGAKCiMjIFN1bW1hcnkgcGxvdHMKCkFkZCBkZWNpbGUgY29kZXMgYW5kIGFub2RhbCBtZWRpYW5zIHRvIGRhdGEgZnJhbWUsIGZvciBwbG90dGluZzoKCmBgYHtyIEF2ZXJhZ2UgYW5vZGFsIGRlY2lsZXN9CnFTdGF0cyA8LSBxRGF0YSAlPiUKICBncm91cF9ieShzdWJqZWN0LGxlZyx0eXBlLGRpcmVjdGlvbikgJT4lCiAgbXV0YXRlKGRlY28gPSBjKHNlcSgxLDUpLHNlcSg0LDEpKSkgJT4lICMgYWRkIGNvZGUgb2YgZGVjaWxlcyB0byBkYXRhIGZyYW1lCiAgZ3JvdXBfYnkobGVnLHR5cGUsZGlyZWN0aW9uLHEpICU+JSAKICBtdXRhdGUoYW5vZGFsID0gbWVhbihhbm9kYWwpKSAlPiUgIyBtZWFuIG9mICJhbm9kYWwiIHF1YW50aWxlcyBPVkVSIHN1YmplY3RzCiAgZ3JvdXBfYnkobGVnLHR5cGUsZGlyZWN0aW9uKSAlPiUgCiAgbXV0YXRlKGFub2RhbF9tZWRpYW4gPSBtZWRpYW4oYW5vZGFsKSkgIyBtZWRpYW4gZm9yIHBsb3R0aW5nCmBgYAoKRm9yIGVhY2ggcXVhbnRpbGUsIGNvdW50IHdoaWNoIHN1YmplY3RzIHNob3cgc2lnbmlmaWNhbnQgZWZmZWN0cywgYW5kIGluIHdoaWNoIGRpcmVjdGlvbjoKCmBgYHtyIENvdW50IHNpZ25pZmljYW5jZSBvZiBkZWNpbGVzfQpxU2lnIDwtIHFEYXRhICU+JQogIGdyb3VwX2J5KHN1YmplY3QsbGVnLHR5cGUsZGlyZWN0aW9uLHEpICU+JQogIG11dGF0ZShzaWduaWZpY2FuY2UgPSBOQSwKICAgICAgICAgIyBJZiAoYW5vZGFsIC0gY2F0aG9kYWwpIHF1YW50aWxlIGRpZmZlcmVuY2UgaXMgcG9zaXRpdmUsIGxhdGVuY3kgZm9yIGFub2RhbCA+IGxhdGVuY3kgZm9yIGNhdGhvZGFsCiAgICAgICAgIHNpZ25pZmljYW5jZSA9IHJlcGxhY2Uoc2lnbmlmaWNhbmNlLCBwX3ZhbHVlIDwgcF9jcml0ICYgZGlmZmVyZW5jZSA+IDAsICJjYXRob2RhbC5mYXN0ZXIiKSwKICAgICAgICAgIyBJZiAoYW5vZGFsIC0gY2F0aG9kYWwpIHF1YW50aWxlIGRpZmZlcmVuY2UgaXMgbmVnYXRpdmUsIGxhdGVuY3kgZm9yIGFub2RhbCA8IGxhdGVuY3kgZm9yIGNhdGhvZGFsCiAgICAgICAgIHNpZ25pZmljYW5jZSA9IHJlcGxhY2Uoc2lnbmlmaWNhbmNlLCBwX3ZhbHVlIDwgcF9jcml0ICYgZGlmZmVyZW5jZSA8IDAsICJhbm9kYWwuZmFzdGVyIikKICApCmBgYAoKIyMjIExhdGVyYWwgc2FjY2FkZXMKClNoaWZ0IGZ1bmN0aW9uczoKCmBgYHtyIFNoaWZ0IGZ1bmN0aW9uIGxhdGVyYWx9CmdncGxvdChmaWx0ZXIocVN0YXRzLCB0eXBlID09ICJsYXRlcmFsIiksIGFlcyhhbm9kYWwsIGRpZmZlcmVuY2UpKSArCiAgIGZhY2V0X2dyaWQobGVnIH4gZGlyZWN0aW9uKSArCiAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGFscGhhID0gMC41KSArCiAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBhbm9kYWxfbWVkaWFuKSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgYWxwaGEgPSAwLjUpICsKICAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9jbF9ub3JtYWwsIGdlb20gPSAibGluZXJhbmdlIiwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKwogICBzdGF0X3N1bW1hcnkoZnVuLnkgPSBtZWFuLCBnZW9tID0gImxpbmUiLCBzaXplID0gMSwgY29sb3VyID0gImdyZXk1MCIsIGFscGhhID0gMC41KSArCiAgIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAicG9pbnQiLCBhZXMoZmlsbCA9IGRlY28pLCBzaXplID0gMiwgY29sb3VyID0gImJsYWNrIiwgc2hhcGUgPSAyMSkgKwogICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJ3aGl0ZSIsIGhpZ2ggPSAiZ3JleTMwIiwgZ3VpZGUgPSBGQUxTRSkgKwogICBzY2FsZV94X2NvbnRpbnVvdXMoImFub2RhbCBkZWNpbGVzIChtcykiLCBsaW1pdHMgPSBjKDgwLDIwMCksIGJyZWFrcyA9IHNlcSgxMDAsMjAwLDI1KSkgKwogICBzY2FsZV95X2NvbnRpbnVvdXMoImFub2RhbCAtIGNhdGhvZGFsIGRlY2lsZXMgKG1zKSIpCmBgYAoKSXQgbG9va3MgbGlrZSB0aGUgc2xvd2VzdCBzYWNjYWRlcyBzaG93IHRoZSBiaWdnZXN0IGRpZmZlcmVuY2UgZm9yIG1vc3QgY29uZGl0aW9ucy4gQ3VyaW91c2x5LCBjYXRob2RhbCB0RENTIHRoZXJlIGxlYWRzIHRvIGZhc3RlciBsYXRlbmNpZXMuIEhvd2V2ZXIsIHRoaXMgcGF0dGVybiBhbHJlYWR5IHNlZW1zIHRvIGJlIHByZXNlbnQgaW4gdGhlIGJhc2VsaW5lLgoKTGV0J3MgZXhhbWluZSB0aGUgbnVtYmVyIG9mIHN1YmplY3RzIHdpdGggYSBzaWduaWZjYW50IGRpZmZlcmVuY2UgcGVyIHF1YW50aWxlOgoKYGBge3IgU2lnbmlmaWNhbmNlIHNoaWZ0IGZ1bmN0aW9uIGxhdGVyYWx9CmdncGxvdChmaWx0ZXIocVNpZywgdHlwZSA9PSAibGF0ZXJhbCIsICFpcy5uYShzaWduaWZpY2FuY2UpKSwgYWVzKHEsIGZpbGwgPSBzaWduaWZpY2FuY2UpKSArCiAgZmFjZXRfZ3JpZChsZWcgfiBkaXJlY3Rpb24pICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIpICsKICBzdGF0X2JpbihiaW53aWR0aCA9IC4xLCBnZW9tID0gInRleHQiLCBzaXplID0gMiwgYWVzKGxhYmVsID0gLi5jb3VudC4uKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjRjI1RjVDIiwgIiM0QjkzQjEiKSkgKwogIHNjYWxlX3hfY29udGludW91cygiZGVjaWxlIiwgYnJlYWtzID0gc2VxKDAuMSwwLjksMC4xKSwgbGFiZWxzID0gc2VxKDEsOSwxKSkgKwogIHNjYWxlX3lfY29udGludW91cygibnVtYmVyIG9mIHBhcnRpY2lwYW50cyB3aXRoIHNpZ25pZmljYW50IGRpZmZlcmVuY2UiLCBsaW1pdHMgPSBjKDAsIGxlbmd0aCh1bmlxdWUocVNpZyRzdWJqZWN0KSkpLCBicmVha3MgPSBjKDAsMTAsMjAsbGVuZ3RoKHVuaXF1ZShxU2lnJHN1YmplY3QpKSkpCmBgYAoKVGhpcyBlZmZlY3QgaW4gdGhlIHJpZ2h0IHRhaWwgc2VlbXMgdG8gYmUgZHJpdmVuIGJ5IGEgcmVsYXRpdmVseSBzbWFsbCBudW1iZXIgb2YgcGFydGljaXBhbnRzLCBhbmQgYSBzaXphYmxlIG51bWJlciBvZiBwYXJ0aWNpcGFudHMgYWxzbyBzaG93cyBhbiBhbm9kYWwgZWZmZWN0IHRoZXJlLi4uIEZ1cnRoZXIsIGlmIGFueWh0aW5nLCB0aGUgbW9zdCBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBhcmUgaW4gdGhlIGJhc2VsaW5lIGJsb2NrLi4uCgojIyMgQ2VudGVyIHNhY2NhZGVzCgpgYGB7ciBTaGlmdCBmdW5jdGlvbiBjZW50ZXJ9CmdncGxvdChmaWx0ZXIocVN0YXRzLCB0eXBlID09ICJjZW50ZXIiKSwgYWVzKGFub2RhbCwgZGlmZmVyZW5jZSkpICsKICAgZmFjZXRfZ3JpZChsZWcgfiBkaXJlY3Rpb24pICsKICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgYWxwaGEgPSAwLjUpICsKICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IGFub2RhbF9tZWRpYW4pLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBhbHBoYSA9IDAuNSkgKwogICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX2NsX25vcm1hbCwgZ2VvbSA9ICJsaW5lcmFuZ2UiLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gMC41KSArCiAgIHN0YXRfc3VtbWFyeShmdW4ueSA9IG1lYW4sIGdlb20gPSAibGluZSIsIHNpemUgPSAxLCBjb2xvdXIgPSAiZ3JleTUwIiwgYWxwaGEgPSAwLjUpICsKICAgc3RhdF9zdW1tYXJ5KGZ1bi55ID0gbWVhbiwgZ2VvbSA9ICJwb2ludCIsIGFlcyhmaWxsID0gZGVjbyksIHNpemUgPSAyLCBjb2xvdXIgPSAiYmxhY2siLCBzaGFwZSA9IDIxKSArCiAgIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIndoaXRlIiwgaGlnaCA9ICJncmV5MzAiLCBndWlkZSA9IEZBTFNFKSArCiAgIHNjYWxlX3hfY29udGludW91cygiYW5vZGFsIGRlY2lsZXMgKG1zKSIsIGxpbWl0cyA9IGMoODAsMjAwKSwgYnJlYWtzID0gc2VxKDEwMCwyMDAsMjUpKSArCiAgIHNjYWxlX3lfY29udGludW91cygiYW5vZGFsIC0gY2F0aG9kYWwgZGVjaWxlcyAobXMpIikKYGBgCgpUaGVyZSB0aGUgcGF0dGVybiBhcHBlYXJzIG9wcG9zaXRlOiB0aGUgZ3JlYXRlc3QgZGlmZmVyZW5jZSBpcyBpbiB0aGUgZmFzdGVzdCBzYWNjYWRlcy4gSXQgbWFrZXMgc2Vuc2UgdGhhdCB0aGVzZSB3b3VsZCBiZSBtb3N0IGltcGFjdGVkIGZvciBjZW50ZXIgc2FjY2FkZXMuIFRoZXkgY291bGQgYmUgaW1wdWxzaXZlIGVycm9ycyB0aGF0IGFyZSBpbmNyZWFzZWQgd2l0aCBzdGltdWxhdGlvbiAodGhvdWdoIGFnYWluLCBjYXRob2RhbCBsZWFkcyB0byBmYXN0ZXIgbGF0ZW5jaWVzLCB3aGljaCBpcyB1bmV4cGVjdGVkKS4gQnV0IGFnYWluLCB0aGlzIHBhdHRlcm4gaXMgcHJlc2VudCBhY3Jvc3MgdGhlIGJvYXJkLgoKYGBge3IgU2lnbmlmaWNhbmNlIHNoaWZ0IGZ1bmN0aW9uIGNlbnRlcn0KZ2dwbG90KGZpbHRlcihxU2lnLCB0eXBlID09ICJjZW50ZXIiLCAhaXMubmEoc2lnbmlmaWNhbmNlKSksIGFlcyhxLCBmaWxsID0gc2lnbmlmaWNhbmNlKSkgKwogIGZhY2V0X2dyaWQobGVnIH4gZGlyZWN0aW9uKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAic3RhY2siKSArCiAgc3RhdF9iaW4oYmlud2lkdGggPSAuMSwgZ2VvbSA9ICJ0ZXh0Iiwgc2l6ZSA9IDIsIGFlcyhsYWJlbCA9IC4uY291bnQuLiksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0YyNUY1QyIsICIjNEI5M0IxIikpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoImRlY2lsZSIsIGJyZWFrcyA9IHNlcSgwLjEsMC45LDAuMSksIGxhYmVscyA9IHNlcSgxLDksMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIm51bWJlciBvZiBwYXJ0aWNpcGFudHMgd2l0aCBzaWduaWZpY2FudCBkaWZmZXJlbmNlIiwgbGltaXRzID0gYygwLCBsZW5ndGgodW5pcXVlKHFTaWckc3ViamVjdCkpKSwgYnJlYWtzID0gYygwLDEwLDIwLGxlbmd0aCh1bmlxdWUocVNpZyRzdWJqZWN0KSkpKQpgYGAKClRoZSBzdHJvbmdlc3QgZWZmZWN0cyBhcmUgYWdhaW4gc2lnbmlmaWNhbnQgaW4gZmV3ZXIgc3ViamVjdHMsIGFuZCBvbiB0aGUgd2hvbGUgdGhlcmUgaXMgbmV2ZXIgYW4gZWZmZWN0IGluIG9uZSBkaXJlY3Rpb24gd2hpY2ggaXMgc2lnbmlmaWNhbnQgaW4gbW9yZSB0aGFuIGhhbGYgdGhlIHNhbXBsZS4KCiMjIEluZGl2aWR1YWwgc2hpZnQgZnVuY3Rpb25zCgpMZXQncyBwbG90IHRoZSBzaGlmdCBmdW5jdGlvbnMgZm9yIGVhY2ggc3ViamVjdCBmb3IgdGhlIGxlZnQtbGF0ZXJhbCBjb25kaXRpb24gKG9mIG1haW4gaW50ZXJlc3QgYXMgW0thbmFpIGV0IGFsLiAoMjAxMildKGh0dHA6Ly9keC5kb2kub3JnLzEwLjMzODkvZnBzeXQuMjAxMi4wMDA0NSkgZm91bmQgZWZmZWN0cyBvZiBhbm9kYWwgdERDUyB0aGVyZSkuCgojIyMgQmFzZWxpbmUKCmBgYHtyIFNoaWZ0IGxhdGVyYWwgbGVmdCBiYXNlbGluZSwgZmlnLndpZHRoPTEwfQpnZ3Bsb3QoZmlsdGVyKHFTdGF0cywgbGVnID09ICJiYXNlbGluZSIsIHR5cGUgID09ICJsYXRlcmFsIiwgZGlyZWN0aW9uID09ICJsZWZ0IiksIGFlcyhhbm9kYWwsIGRpZmZlcmVuY2UpKSArCiAgZmFjZXRfd3JhcCh+c3ViamVjdCwgbmNvbCA9IDUsIHNjYWxlcyA9ICJmcmVlIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGFscGhhID0gMC41KSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IGFub2RhbF9tZWRpYW4pLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBhbHBoYSA9IDAuNSkgKwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluPWNpX2xvd2VyLCB5bWF4PWNpX3VwcGVyKSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fbGluZShzaXplID0gMSwgY29sb3VyID0gImdyZXk1MCIsIGFscGhhID0gMC41KSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGRlY28pLCBzaXplID0gMiwgY29sb3VyID0gImJsYWNrIiwgc2hhcGUgPSAyMSkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIndoaXRlIiwgaGlnaCA9ICJncmV5MzAiLCBndWlkZSA9IEZBTFNFKSArCiAgeGxhYigiYW5vZGFsIGRlY2lsZXMiKSArCiAgeWxhYigiYW5vZGFsIC0gY2F0aG9kYWwgZGVjaWxlcyAobXMpIikgKwogIGdndGl0bGUoIkxlZnQgbGF0ZXJhbCBzYWNjYWRlcyBkdXJpbmcgYmFzZWxpbmUiKQpgYGAKCiMjIyBEdXJpbmcgdERDUwoKYGBge3IgU2hpZnQgbGF0ZXJhbCBsZWZ0IHREQ1MsIGZpZy53aWR0aD0xMH0KZ2dwbG90KGZpbHRlcihxU3RhdHMsIGxlZyA9PSAidERDUyIsIHR5cGUgID09ICJsYXRlcmFsIiwgZGlyZWN0aW9uID09ICJsZWZ0IiksIGFlcyhhbm9kYWwsIGRpZmZlcmVuY2UpKSArCiAgZmFjZXRfd3JhcCh+c3ViamVjdCwgbmNvbCA9IDUsIHNjYWxlcyA9ICJmcmVlIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGFscGhhID0gMC41KSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IGFub2RhbF9tZWRpYW4pLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBhbHBoYSA9IDAuNSkgKwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluPWNpX2xvd2VyLCB5bWF4PWNpX3VwcGVyKSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fbGluZShzaXplID0gMSwgY29sb3VyID0gImdyZXk1MCIsIGFscGhhID0gMC41KSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGRlY28pLCBzaXplID0gMiwgY29sb3VyID0gImJsYWNrIiwgc2hhcGUgPSAyMSkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIndoaXRlIiwgaGlnaCA9ICJncmV5MzAiLCBndWlkZSA9IEZBTFNFKSArCiAgeGxhYigiYW5vZGFsIGRlY2lsZXMiKSArCiAgeWxhYigiYW5vZGFsIC0gY2F0aG9kYWwgZGVjaWxlcyAobXMpIikgKwogIGdndGl0bGUoIkxlZnQgbGF0ZXJhbCBzYWNjYWRlcyBkdXJpbmcgdERDUyIpCmBgYAoKIyMjIEFmdGVyIHREQ1MgKDAtMTUgbWluKQoKYGBge3IgU2hpZnQgbGF0ZXJhbCBsZWZ0IHBvc3QtMSwgZmlnLndpZHRoPTEwfQpnZ3Bsb3QoZmlsdGVyKHFTdGF0cywgbGVnID09ICJwb3N0LTEiLCB0eXBlICA9PSAibGF0ZXJhbCIsIGRpcmVjdGlvbiA9PSAibGVmdCIpLCBhZXMoYW5vZGFsLCBkaWZmZXJlbmNlKSkgKwogIGZhY2V0X3dyYXAofnN1YmplY3QsIG5jb2wgPSA1LCBzY2FsZXMgPSAiZnJlZSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBhbHBoYSA9IDAuNSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBhbm9kYWxfbWVkaWFuKSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgYWxwaGEgPSAwLjUpICsKICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbj1jaV9sb3dlciwgeW1heD1jaV91cHBlciksIGNvbG91ciA9ICJibGFjayIsIHNpemUgPSAwLjUpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDEsIGNvbG91ciA9ICJncmV5NTAiLCBhbHBoYSA9IDAuNSkgKwogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBkZWNvKSwgc2l6ZSA9IDIsIGNvbG91ciA9ICJibGFjayIsIHNoYXBlID0gMjEpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJ3aGl0ZSIsIGhpZ2ggPSAiZ3JleTMwIiwgZ3VpZGUgPSBGQUxTRSkgKwogIHhsYWIoImFub2RhbCBkZWNpbGVzIikgKwogIHlsYWIoImFub2RhbCAtIGNhdGhvZGFsIGRlY2lsZXMgKG1zKSIpICsKICBnZ3RpdGxlKCJMZWZ0IGxhdGVyYWwgc2FjY2FkZXMgcG9zdC10RENTICgwLTE1IG1pbikiKQpgYGAKCiMjIyBBZnRlciB0RENTICgxNS0zMCBtaW4pCgpgYGB7ciBTaGlmdCBsYXRlcmFsIGxlZnQgcG9zdC0yLCBmaWcud2lkdGg9MTB9CmdncGxvdChmaWx0ZXIocVN0YXRzLCBsZWcgPT0gInBvc3QtMiIsIHR5cGUgID09ICJsYXRlcmFsIiwgZGlyZWN0aW9uID09ICJsZWZ0IiksIGFlcyhhbm9kYWwsIGRpZmZlcmVuY2UpKSArCiAgZmFjZXRfd3JhcCh+c3ViamVjdCwgbmNvbCA9IDUsIHNjYWxlcyA9ICJmcmVlIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGFscGhhID0gMC41KSArCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IGFub2RhbF9tZWRpYW4pLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBhbHBoYSA9IDAuNSkgKwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluPWNpX2xvd2VyLCB5bWF4PWNpX3VwcGVyKSwgY29sb3VyID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKwogIGdlb21fbGluZShzaXplID0gMSwgY29sb3VyID0gImdyZXk1MCIsIGFscGhhID0gMC41KSArCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGRlY28pLCBzaXplID0gMiwgY29sb3VyID0gImJsYWNrIiwgc2hhcGUgPSAyMSkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIndoaXRlIiwgaGlnaCA9ICJncmV5MzAiLCBndWlkZSA9IEZBTFNFKSArCiAgeGxhYigiYW5vZGFsIGRlY2lsZXMiKSArCiAgeWxhYigiYW5vZGFsIC0gY2F0aG9kYWwgZGVjaWxlcyAobXMpIikgKwogIGdndGl0bGUoIkxlZnQgbGF0ZXJhbCBzYWNjYWRlcyBwb3N0LXREQ1MgKDE1LTMwIG1pbikiKQpgYGA=