Evidence-synthesis worked example · prepared by Abdelwahab
Ghazy, MD Portfolio: add your link · ORCID: add
your ID · dr.abdelwahab.ghazy@gmail.com
In one breath. Pooling nine randomised trials gives
a headline “stroke units save ~15 days,” but the confidence interval
crosses zero and the trials disagree almost completely (I² ≈ 97%). That
disagreement is not noise — the benefit scales with how
sick the patients are. Where strokes are severe and stays are long,
stroke units help enormously; where stays are already short, they barely
move the needle. The professional deliverable here is not a single
pooled number — it is the explanation for why one pooled number
would mislead.
How to read this
document
New to R? Read this once and everything below will click. Already
fluent? Skip straight to the next section.
Each grey box is a code chunk — the exact
instructions R runs. Under most chunks sits a purple
Plain-English walkthrough that translates the code,
piece by piece. A little recurring grammar unlocks all of it:
- A function is a command that does a job; you call
it by its name followed by round brackets,
e.g.
forest(...). Whatever you put inside the brackets are
its arguments — the settings you hand the command.
<- means “save this as.”
m <- metacont(...) runs metacont and keeps
the result in a box named m; afterwards we just write
m to reuse it.
$ reaches inside a result to grab one
piece: m$TE.random = “the pooled estimate stored inside
m.”
|> is the pipe. It takes whatever
is on its left and feeds it into the function on its right, so a chain
reads left-to-right instead of inside-out.
- Some sentences contain a snippet written as an
r
followed by a short expression, all wrapped in back-ticks. That is
inline code: R replaces it with the live number when
the report is built, so the words and the numbers can never
disagree.
- Packages (
meta, metafor,
…) are toolboxes we load once at the top; each hands us ready-made
functions so we never reinvent them.
The clinical
question
We compared organised stroke-unit care — a dedicated
ward with a specialist multidisciplinary team — against
conventional care on a general ward, measuring
length of hospital stay, in days.
PICO — P stroke inpatients ·
I organised stroke-unit care · C
conventional general-ward care · O length of stay
(days).
Lower is better: a negative Mean Difference means
the stroke unit sends patients home sooner.
The data
Nine randomised trials assembled by Normand (1999) [1]. Each row is
one trial, with the mean, SD, and sample size for both arms.
data(dat.normand1999, package = "metafor")
d <- dat.normand1999 # source = trial label; 1 = stroke unit, 2 = conventional
kable(
d[, c("source", "n1i", "m1i", "sd1i", "n2i", "m2i", "sd2i")],
col.names = c("Trial", "N", "Mean", "SD", "N", "Mean", "SD"),
caption = "Length of hospital stay (days) by trial and arm."
) |>
add_header_above(c(" " = 1, "Stroke unit" = 3, "Conventional" = 3)) |>
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)
Length of hospital stay (days) by trial and arm.
|
|
Stroke unit
|
Conventional
|
|
Trial
|
N
|
Mean
|
SD
|
N
|
Mean
|
SD
|
|
Edinburgh
|
155
|
55
|
47
|
156
|
75
|
64
|
|
Orpington-Mild
|
31
|
27
|
7
|
32
|
29
|
4
|
|
Orpington-Moderate
|
75
|
64
|
17
|
71
|
119
|
29
|
|
Orpington-Severe
|
18
|
66
|
20
|
18
|
137
|
48
|
|
Montreal-Home
|
8
|
14
|
8
|
13
|
18
|
11
|
|
Montreal-Transfer
|
57
|
19
|
7
|
52
|
18
|
4
|
|
Newcastle
|
34
|
52
|
45
|
33
|
41
|
34
|
|
Umea
|
110
|
21
|
16
|
183
|
31
|
27
|
|
Uppsala
|
60
|
30
|
27
|
52
|
23
|
20
|
Plain-English walkthrough.
data(dat.normand1999, package = "metafor") loads a
ready-made example dataset that ships inside the metafor
toolbox.
d <- dat.normand1999 copies it into a short name,
d, that is quicker to type from here on.
d[, c("source", "n1i", ...)] picks out just the columns
we want to display, and kable(...) turns them into a tidy
table.
col.names = c(...) gives the columns human-friendly
headers, and caption = ... puts a title above the
table.
- The
|> pipe then passes that table on to
add_header_above() (which adds the “Stroke unit /
Conventional” spanning row) and to kable_styling() (the
striped, hover-highlight look).
How to read the columns. The suffix
1 is the intervention arm (stroke unit);
2 is the control arm (conventional care). Within each
arm: n = sample size, m = mean length
of stay, sd = standard deviation. (The trailing
i in n1i/m1i/… is simply
metafor’s naming convention and carries no analytic
meaning.)
Two things are already visible and will matter later:
conventional-care stay ranges from 18 to 137 days — a
nearly ten-fold spread — and three of the trials come from a single
centre (Orpington), deliberately split by stroke severity.
The analysis
We pool the trials as a Mean Difference under a
random-effects model, estimating the between-study
variance by REML and using the Hartung–Knapp adjustment
for the confidence interval [3] — the modern default that guards against
over-precise intervals when trials are few and heterogeneous.
m <- metacont(
n1i, m1i, sd1i, # stroke-unit arm
n2i, m2i, sd2i, # conventional arm
studlab = source, data = d,
sm = "MD", # effect measure: Mean Difference
random = TRUE, # random-effects model
common = FALSE,
method.tau = "REML",
method.random.ci = "HK", # Hartung-Knapp confidence interval
prediction = TRUE,
label.e = "Stroke unit", label.c = "Conventional"
)
summary(m)
## MD 95%-CI %W(random)
## Edinburgh -20.0000 [-32.4744; -7.5256] 11.0
## Orpington-Mild -2.0000 [ -4.8271; 0.8271] 11.7
## Orpington-Moderate -55.0000 [-62.7656; -47.2344] 11.4
## Orpington-Severe -71.0000 [-95.0223; -46.9777] 9.6
## Montreal-Home -4.0000 [-12.1539; 4.1539] 11.4
## Montreal-Transfer 1.0000 [ -1.1176; 3.1176] 11.7
## Newcastle 11.0000 [ -8.0620; 30.0620] 10.3
## Umea -10.0000 [-14.9237; -5.0763] 11.6
## Uppsala 7.0000 [ -1.7306; 15.7306] 11.4
##
## Number of studies: k = 9
## Number of observations: o = 1158 (o.e = 548, o.c = 610)
##
## MD 95%-CI t p-value
## Random effects model -15.1060 [-36.3187; 6.1067] -1.64 0.1392
## Prediction interval [-78.8739; 48.6618]
##
## Quantifying heterogeneity (with 95%-CIs):
## tau^2 = 684.6462 [292.9181; 2889.4513]; tau = 26.1657 [17.1149; 53.7536]
## I^2 = 96.7% [95.2%; 97.7%]; H = 5.46 [4.54; 6.58]
##
## Test of heterogeneity:
## Q d.f. p-value
## 238.92 8 < 0.0001
##
## Details of meta-analysis methods:
## - Inverse variance method
## - Restricted maximum-likelihood estimator for tau^2
## - Q-Profile method for confidence interval of tau^2 and tau
## - Calculation of I^2 based on Q
## - Hartung-Knapp adjustment for random effects model (df = 8)
## - Prediction interval based on t-distribution (df = 8)
Plain-English walkthrough — metacont().
The name is short for meta-analysis of a
continuous outcome. It takes each trial’s six summary
numbers and pools them into one result. Reading its arguments in
order:
n1i, m1i, sd1i then n2i, m2i, sd2i — the
six columns it needs: sample size, mean, and standard deviation for the
stroke-unit arm (1), then the same three for the
conventional arm (2).
studlab = source — which column holds the trial name to
print on each row.
data = d — the table where all those columns live.
sm = "MD" — the summary measure. “MD”
= Mean Difference; because both arms are measured in the same unit
(days), we can simply subtract them.
random = TRUE — produce the
random-effects result, which allows the true effect to
genuinely differ from trial to trial.
common = FALSE — hide the fixed-effect (“common
effect”) result, which would pretend every trial is estimating one
identical number.
method.tau = "REML" — the recipe for estimating how
much the trials differ (the between-study variance, τ²). REML is
the modern default.
method.random.ci = "HK" — use the
Hartung–Knapp confidence interval, which stays honest
(appropriately wide) when trials are few and disagree.
prediction = TRUE — also compute the prediction
interval: the range a brand-new trial might plausibly fall
in.
label.e / label.c — readable names for the
experimental and control arms, used later on the plot.
Then summary(m) prints everything metacont
just calculated.
The forest plot
forest(
m,
sortvar = TE,
leftcols = c("studlab", "n.e", "mean.e", "sd.e", "n.c", "mean.c", "sd.c"),
leftlabs = c("Trial", "Total", "Mean", "SD", "Total", "Mean", "SD"),
rightcols = c("effect", "ci", "w.random"),
rightlabs = c("MD", "95% CI", "Weight"),
label.e = "Stroke unit", label.c = "Conventional",
col.diamond = "darkred", col.diamond.lines = "black",
col.square = "steelblue3", col.square.lines = "steelblue3",
common = FALSE, random = TRUE, overall = TRUE, overall.hetstat = TRUE,
prediction = TRUE, # 95% prediction interval (red bar)
spacing = 1.2,
colgap = unit(3, "mm"),
colgap.forest.left = unit(0, "mm"),
colgap.forest.right = unit(1, "mm"),
xlab = "Favours stroke unit Favours conventional",
squaresize = 0.8,
digits = 1, digits.mean = 1, digits.sd = 1,
digits.pval = 2, digits.pval.Q = 2, digits.I2 = 1, digits.tau2 = 1,
fontsize = 11, fs.heading = 12, fs.study = 11, fs.random = 11,
fs.hetstat = 10, fs.axis = 10, fs.xlab = 12, fs.smlab = 12,
col.hetstat = "gray50"
)
Plain-English walkthrough — forest().
forest(m, ...) draws the classic forest plot from the
pooled object m. There are many arguments, but they only do
a handful of jobs:
- What to show, and where.
leftcols /
leftlabs list the columns (and their headers) down the left
side; rightcols / rightlabs do the same on the
right (the effect, its CI, and each trial’s weight).
sortvar = TE orders the trials by effect size.
- The overall result.
random = TRUE,
common = FALSE, overall, and
overall.hetstat show the random-effects diamond and the
heterogeneity statistics; prediction = TRUE adds the red
prediction-interval bar.
- Colours & sizes.
col.diamond,
col.square, squaresize, spacing,
and the colgap* arguments are pure cosmetics — the diamond
colour, the box colour, how big the boxes are, and the gaps between
columns.
- Rounding. Every
digits* argument sets
how many decimals a given number shows (e.g. digits = 1 →
one decimal place for the effects).
- Font sizes.
fontsize is the baseline;
each fs.* fine-tunes one element (heading, study rows,
heterogeneity line, axis, labels).
xlab = "Favours stroke unit … Favours conventional"
labels which side of the vertical line is the good-news side.
In short: the first few arguments decide the plot’s content,
and the long tail of col.*, fs.*, and
digits.* simply polishes its appearance.
What the numbers are
telling us
res <- data.frame(
Metric = c("Pooled MD (random effects)", "95% confidence interval",
"95% prediction interval", "I² (inconsistency)",
"τ² (between-trial variance)", "Cochran's Q (p-value)"),
Value = c(
sprintf("%.1f days", m$TE.random),
sprintf("%.1f to %.1f days", m$lower.random, m$upper.random),
sprintf("%.1f to %.1f days", m$lower.predict, m$upper.predict),
sprintf("%.0f%%", m$I2 * 100),
sprintf("%.1f", m$tau2),
format.pval(m$pval.Q, digits = 2, eps = 0.001)
)
)
kable(res, col.names = c("", "Result"),
caption = "Random-effects summary.") |>
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Random-effects summary.
|
|
Result
|
|
Pooled MD (random effects)
|
-15.1 days
|
|
95% confidence interval
|
-36.3 to 6.1 days
|
|
95% prediction interval
|
-78.9 to 48.7 days
|
|
I<U+00B2> (inconsistency)
|
97%
|
|
<U+03C4><U+00B2> (between-trial variance)
|
684.6
|
|
Cochran’s Q (p-value)
|
<0.001
|
Plain-English walkthrough. This chunk builds the
summary table by hand so we control exactly what appears.
data.frame(Metric = ..., Value = ...) makes a
two-column table: the labels on the left, the formatted results on the
right.
sprintf("%.1f days", m$TE.random) is text formatting:
%.1f means “a number with one decimal,” so the pooled
estimate prints as, e.g., -15.1 days. Each value is pulled
straight from the model with $ (m$TE.random,
m$I2, m$tau2, …), so the table can never drift
away from the analysis.
format.pval(..., eps = 0.001) prints very small
p-values neatly as < 0.001 instead of a long string of
zeros.
kable() |> kable_styling() renders and styles the
table, just as before.
The pooled estimate of -15.1 days looks impressive,
but two signals stop us from reporting it:
- The 95% confidence interval (-36.3 to 6.1) crosses
zero — the pooled effect is not statistically distinguishable
from “no difference.”
- I² is 97% [5] — the trials essentially do not
agree. The 95% prediction interval [7], -78.9 to 48.7
days, makes this concrete: a new trial could plausibly land
anywhere from a large benefit to a large harm.
When a prediction interval is that wide, a single pooled number is
not a finding — it is an average of things that don’t belong together.
So we don’t report it. We ask why the trials disagree.
Hunting for the
cause
The trial labels hint at the answer. Three trials come from one
centre (Orpington) split by stroke severity; the rest
span different countries and health systems, and length of stay depends
heavily on both case-mix and how each system manages discharge. Because
conventional-care stay ranges from 18 to 137 days, a natural question is
whether baseline stay explains the disagreement. We
test it with a meta-regression.
mr <- metareg(m, ~ m2i) # does control-arm mean explain the between-trial MD?
mr
##
## Mixed-Effects Model (k = 9; tau^2 estimator: REML)
##
## tau^2 (estimated amount of residual heterogeneity): 18.4346 (SE = 17.2577)
## tau (square root of estimated tau^2 value): 4.2936
## I^2 (residual heterogeneity / unaccounted variability): 72.19%
## H^2 (unaccounted variability / sampling variability): 3.60
## R^2 (amount of heterogeneity accounted for): 97.31%
##
## Test for Residual Heterogeneity:
## QE(df = 7) = 19.1945, p-val = 0.0076
##
## Test of Moderators (coefficient 2):
## F(df1 = 1, df2 = 7) = 68.4411, p-val < .0001
##
## Model Results:
##
## estimate se tval df pval ci.lb ci.ub
## intrcpt 12.5103 3.6203 3.4556 7 0.0106 3.9497 21.0709 *
## m2i -0.5505 0.0665 -8.2729 7 <.0001 -0.7079 -0.3932 ***
##
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Plain-English walkthrough — metareg().
A meta-regression asks whether some trait of the trials
explains why their results disagree.
metareg(m, ~ m2i) — take the pooled object
m and test one predictor. The ~ m2i part is an
R formula; read it as “explain the effect
using m2i” (the control-arm mean — i.e. baseline
length of stay).
- Printing
mr reports the slope (how
much the effect shifts per extra baseline day), its
p-value, and R² — the share of the
between-trial disagreement that this one predictor accounts for.
Baseline stay explains almost all of the
between-trial variation (R² ≈ 97%, slope p
< 0.001): trials where patients would otherwise stay a long time
(severe strokes) show the biggest reductions, while trials with
already-short stays show almost none. The heterogeneity was never noise
— it was baseline-dependence.
Read this before believing it. Regressing the Mean
Difference on the control-group mean is exploratory,
not confirmatory. The control mean is part of the outcome itself (MD =
intervention − control), so the two are mathematically linked and part
of this association is built in. Treat it as
hypothesis-generating, not proof.
A cleaner test: the
Orpington severity gradient
The caveat above has a clean answer. Instead of baseline stay — which
is tangled with the outcome — we use an independent
moderator: pre-randomisation stroke severity. The three
Orpington trials are ideal, because they hold the hospital, team, and
health system constant and vary only by severity.
orp <- subset(d, grepl("Orpington", source))
orp$severity <- c("Mild", "Moderate", "Severe")
orp$MD <- orp$m1i - orp$m2i # stroke unit - conventional
kable(orp[, c("severity", "m1i", "m2i", "MD")],
col.names = c("Stroke severity", "Stroke-unit mean",
"Conventional mean", "Mean difference (days)"),
caption = "Orpington trials — same centre, same team, severity the only difference.") |>
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Orpington trials <u+2014> same centre, same team, severity the
only difference.</u+2014>
|
|
Stroke severity
|
Stroke-unit mean
|
Conventional mean
|
Mean difference (days)
|
|
2
|
Mild
|
27
|
29
|
-2
|
|
3
|
Moderate
|
64
|
119
|
-55
|
|
4
|
Severe
|
66
|
137
|
-71
|
Plain-English walkthrough.
subset(d, grepl("Orpington", source)) — keep only the
rows whose source name contains the text
“Orpington.” grepl() is a text search that returns
TRUE/FALSE for every row, and subset() keeps the TRUE
ones.
orp$severity <- c("Mild", "Moderate", "Severe") —
add a new column by hand, labelling those three rows.
orp$MD <- orp$m1i - orp$m2i — compute each trial’s
mean difference directly (stroke-unit mean minus conventional mean) —
the very subtraction metacont does internally.
kable(...) |> kable_styling(...) — display it as a
tidy table.
Holding the system fixed, the mean difference goes from -2
days (mild) → -55 days (moderate) →
-71 days (severe). A clean, monotonic dose–response on
an independent clinical characteristic — exactly the
confirmatory signal the baseline-stay regression could only hint at.
This is the defensible version of the story: severity is clinically
meaningful, available in the source trials, and not mathematically bound
to the outcome. In a real review, we would pre-specify
it as the moderator and extract it during data collection.
Sensitivity: is any
single trial driving the result?
Before drawing conclusions, we check that no one trial is doing all
the work, by re-pooling with each trial removed in turn
(leave-one-out).
forest(metainf(m, pooled = "random"),
col.square = "steelblue3", col.diamond = "darkred",
fontsize = 11)
Plain-English walkthrough — metainf().
metainf(m, pooled = "random") re-runs the random-effects
pool nine times — each run leaving one trial out (“inf”
is short for influence). Wrapping it in
forest(...) draws one row per omission, so you can see at a
glance whether dropping any single trial would change the
conclusion.
The pooled estimate stays in a narrow band (roughly −9 to −18 days)
and never crosses to favouring conventional care, so no single trial is
fabricating the signal. The two omissions that pull the estimate
toward zero are the Orpington-Moderate and
Orpington-Severe trials — which is not fragility, but
the same message again: the high-severity trials carry the benefit.
A note on small-study
effects
With only 9 trials, a funnel plot and Egger’s test
are underpowered and easily misread — guidance is not to test for
small-study effects below ~10 studies, and severe heterogeneity makes an
asymmetry test uninterpretable here anyway [5]. We therefore
state the limitation explicitly rather than present a
plot that cannot support a conclusion. Naming this is the honest,
rigorous move.
What we learned
- The naive headline — “stroke units save 15 days” — is not
supported: the CI crosses zero and I² is 97%.
- The disagreement is not noise. The benefit
depends on baseline severity: largest where
conventional stays are longest (severe strokes), minimal where they are
already short — confirmed cleanly within the Orpington centre.
- The result is robust to leave-one-out, and
small-study-effect testing is correctly withheld at
this sample size.
- Transferable method habits: (1) pick the effect
measure from the outcome (MD for a shared scale); (2) default to
random-effects + Hartung–Knapp;
- read the prediction interval, not just the CI; (4)
explain heterogeneity before quoting any pooled number;
and (5) prefer a moderator that is independent of the
outcome.
Real-world
validation
This teaching result echoes the definitive evidence: the Cochrane
Stroke Unit Trialists’ Collaboration review found that
organised stroke-unit care improves outcomes, with effects that vary by
patient severity and care setting [4] — reassurance that the analytic
story here points the same way as the full body of trials.
Reproducibility &
data availability
- Data:
dat.normand1999 from the
metafor package (Normand 1999) [1;6] — no private data; the
analysis is fully reproducible from this document.
- Code: every figure and number is generated in-line
from the fitted model (no hard-coded results). Use the Code ▸
Download Rmd button (top-right) to get the source.
- Environment: exact package versions are recorded in
the appendix below.
References
- Normand SL. Meta-analysis: formulating, evaluating, combining, and
reporting. Stat Med. 1999;18(3):321–359.
- Balduzzi S, Rücker G, Schwarzer G. How to perform a meta-analysis
with R: a practical tutorial. Evid Based Ment Health.
2019;22(4):153–160. (the
meta package)
- IntHout J, Ioannidis JPA, Borm GF. The Hartung–Knapp–Sidik–Jonkman
method for random-effects meta-analysis is straightforward and
considerably outperforms the standard DerSimonian–Laird method. BMC
Med Res Methodol. 2014;14:25.
- Stroke Unit Trialists’ Collaboration. Organised inpatient (stroke
unit) care for stroke. Cochrane Database Syst Rev.
2013;(9):CD000197.
- Higgins JPT, Thompson SG. Quantifying heterogeneity in a
meta-analysis. Stat Med. 2002;21(11):1539–1558.
- Viechtbauer W. Conducting meta-analyses in R with the metafor
package. J Stat Softw. 2010;36(3):1–48.
- IntHout J, Ioannidis JPA, Rovers MM, Goeman JJ. Plea for routinely
presenting prediction intervals in meta-analysis. BMJ Open.
2016;6:e010247.
LS0tCnRpdGxlOiAiRG8gU3Ryb2tlIFVuaXRzIFNob3J0ZW4gSG9zcGl0YWwgU3RheT8iCnN1YnRpdGxlOiAiQSB3b3JrZWQgcmFuZG9tLWVmZmVjdHMgbWV0YS1hbmFseXNpcyBvZiA5IHJhbmRvbWlzZWQgdHJpYWxzIOKAlCBhbmQgYSBsZXNzb24gaW4gcmVhZGluZyBoZXRlcm9nZW5laXR5LCBub3QgaGlkaW5nIGl0IgphdXRob3I6CiAgLSAiQWJkZWx3YWhhYiBHaGF6eSwgTUQiCmRhdGU6ICJgciBmb3JtYXQoU3lzLkRhdGUoKSwgJyVCICVZJylgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICAgIHNtb290aF9zY3JvbGw6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICB0aGVtZTogZmxhdGx5CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGRmX3ByaW50OiBwYWdlZAogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAgIGZpZ19jYXB0aW9uOiB0cnVlCmVkaXRvcl9vcHRpb25zOgogIG1hcmtkb3duOgogICAgd3JhcDogNzIKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwKICBmaWcud2lkdGggPSA5LCBmaWcuaGVpZ2h0ID0gNSwgZmlnLmFsaWduID0gImNlbnRlciIKKQoKIyBPbmUgcGxhY2UgZm9yIGV2ZXJ5IGRlcGVuZGVuY3ksIHdpdGggYSBmcmllbmRseSBzdG9wIGlmIHNvbWV0aGluZyBpcyBtaXNzaW5nLgpuZWVkIDwtIGMoIm1ldGEiLCAibWV0YWZvciIsICJrbml0ciIsICJrYWJsZUV4dHJhIiwgImdyaWQiKQptaXNzaW5nIDwtIG5lZWRbIXZhcHBseShuZWVkLCByZXF1aXJlTmFtZXNwYWNlLCBsb2dpY2FsKDEpLCBxdWlldGx5ID0gVFJVRSldCmlmIChsZW5ndGgobWlzc2luZykpCiAgc3RvcCgiUGxlYXNlIGluc3RhbGw6ICIsIHBhc3RlKG1pc3NpbmcsIGNvbGxhcHNlID0gIiwgIiksIGNhbGwuID0gRkFMU0UpCgpsaWJyYXJ5KG1ldGEpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKbGlicmFyeShncmlkKQpgYGAKCmBgYHs9aHRtbH0KPHN0eWxlPgoudGxkciAgIHtiYWNrZ3JvdW5kOiNlYWY0ZmI7IGJvcmRlci1sZWZ0OjVweCBzb2xpZCAjMmM3ZmI4OyBwYWRkaW5nOjE0cHggMThweDsgYm9yZGVyLXJhZGl1czo2cHg7IG1hcmdpbjoxOHB4IDA7fQouY2F2ZWF0IHtiYWNrZ3JvdW5kOiNmZmY0ZTY7IGJvcmRlci1sZWZ0OjVweCBzb2xpZCAjZTg4NzFlOyBwYWRkaW5nOjE0cHggMThweDsgYm9yZGVyLXJhZGl1czo2cHg7IG1hcmdpbjoxOHB4IDA7fQouYnlsaW5lIHtjb2xvcjojNWI2YjdhOyBmb250LXNpemU6MC45NWVtOyBtYXJnaW4tdG9wOi04cHg7IG1hcmdpbi1ib3R0b206MjBweDt9Ci53aW4gICAge2JhY2tncm91bmQ6I2VlZjhlZTsgYm9yZGVyLWxlZnQ6NXB4IHNvbGlkICM0YTlkNGE7IHBhZGRpbmc6MTRweCAxOHB4OyBib3JkZXItcmFkaXVzOjZweDsgbWFyZ2luOjE4cHggMDt9Ci5leHBsYWluIHtiYWNrZ3JvdW5kOiNmNWYzZmI7IGJvcmRlcjoxcHggc29saWQgI2RkZDVmMDsgYm9yZGVyLWxlZnQ6NXB4IHNvbGlkICM3YjYxYzk7IHBhZGRpbmc6MTJweCAxOHB4OyBib3JkZXItcmFkaXVzOjZweDsgbWFyZ2luOjE0cHggMDsgZm9udC1zaXplOjAuOTVlbTt9Ci5leHBsYWluIGNvZGUge2JhY2tncm91bmQ6I2VjZTZmODt9Cjwvc3R5bGU+CmBgYAoKOjo6IGJ5bGluZQpFdmlkZW5jZS1zeW50aGVzaXMgd29ya2VkIGV4YW1wbGUgwrcgcHJlcGFyZWQgYnkgKipBYmRlbHdhaGFiIEdoYXp5LCBNRCoqClBvcnRmb2xpbzogKmFkZCB5b3VyIGxpbmsqIMK3IE9SQ0lEOiAqYWRkIHlvdXIgSUQqIMK3Cltkci5hYmRlbHdhaGFiLmdoYXp5XEBnbWFpbC5jb21dKG1haWx0bzpkci5hYmRlbHdhaGFiLmdoYXp5QGdtYWlsLmNvbSl7LmVtYWlsfQo6OjoKCjo6OiB0bGRyCioqSW4gb25lIGJyZWF0aC4qKiBQb29saW5nIG5pbmUgcmFuZG9taXNlZCB0cmlhbHMgZ2l2ZXMgYSBoZWFkbGluZQoic3Ryb2tlIHVuaXRzIHNhdmUgXH4xNSBkYXlzLCIgYnV0IHRoZSBjb25maWRlbmNlIGludGVydmFsIGNyb3NzZXMgemVybwphbmQgdGhlIHRyaWFscyBkaXNhZ3JlZSBhbG1vc3QgY29tcGxldGVseSAoScKyIOKJiCA5NyUpLiBUaGF0IGRpc2FncmVlbWVudAppcyAqKm5vdCBub2lzZSoqIOKAlCB0aGUgYmVuZWZpdCBzY2FsZXMgd2l0aCBob3cgc2ljayB0aGUgcGF0aWVudHMgYXJlLgpXaGVyZSBzdHJva2VzIGFyZSBzZXZlcmUgYW5kIHN0YXlzIGFyZSBsb25nLCBzdHJva2UgdW5pdHMgaGVscAplbm9ybW91c2x5OyB3aGVyZSBzdGF5cyBhcmUgYWxyZWFkeSBzaG9ydCwgdGhleSBiYXJlbHkgbW92ZSB0aGUgbmVlZGxlLgpUaGUgcHJvZmVzc2lvbmFsIGRlbGl2ZXJhYmxlIGhlcmUgaXMgbm90IGEgc2luZ2xlIHBvb2xlZCBudW1iZXIg4oCUIGl0IGlzCnRoZSAqZXhwbGFuYXRpb24qIGZvciB3aHkgb25lIHBvb2xlZCBudW1iZXIgd291bGQgbWlzbGVhZC4KOjo6CgojIEhvdyB0byByZWFkIHRoaXMgZG9jdW1lbnQKCipOZXcgdG8gUj8gUmVhZCB0aGlzIG9uY2UgYW5kIGV2ZXJ5dGhpbmcgYmVsb3cgd2lsbCBjbGljay4gQWxyZWFkeSBmbHVlbnQ/ClNraXAgc3RyYWlnaHQgdG8gdGhlIG5leHQgc2VjdGlvbi4qCgpFYWNoIGdyZXkgYm94IGlzIGEgKipjb2RlIGNodW5rKiog4oCUIHRoZSBleGFjdCBpbnN0cnVjdGlvbnMgUiBydW5zLiBVbmRlciBtb3N0CmNodW5rcyBzaXRzIGEgcHVycGxlICoqUGxhaW4tRW5nbGlzaCB3YWxrdGhyb3VnaCoqIHRoYXQgdHJhbnNsYXRlcyB0aGUgY29kZSwKcGllY2UgYnkgcGllY2UuIEEgbGl0dGxlIHJlY3VycmluZyBncmFtbWFyIHVubG9ja3MgYWxsIG9mIGl0OgoKLSBBICoqZnVuY3Rpb24qKiBpcyBhIGNvbW1hbmQgdGhhdCBkb2VzIGEgam9iOyB5b3UgY2FsbCBpdCBieSBpdHMgbmFtZSBmb2xsb3dlZAogIGJ5IHJvdW5kIGJyYWNrZXRzLCBlLmcuIGBmb3Jlc3QoLi4uKWAuIFdoYXRldmVyIHlvdSBwdXQgaW5zaWRlIHRoZSBicmFja2V0cyBhcmUKICBpdHMgKiphcmd1bWVudHMqKiDigJQgdGhlIHNldHRpbmdzIHlvdSBoYW5kIHRoZSBjb21tYW5kLgotIGA8LWAgbWVhbnMgKioic2F2ZSB0aGlzIGFzLiIqKiBgbSA8LSBtZXRhY29udCguLi4pYCBydW5zIGBtZXRhY29udGAgYW5kIGtlZXBzCiAgdGhlIHJlc3VsdCBpbiBhIGJveCBuYW1lZCBgbWA7IGFmdGVyd2FyZHMgd2UganVzdCB3cml0ZSBgbWAgdG8gcmV1c2UgaXQuCi0gYCRgIHJlYWNoZXMgKippbnNpZGUqKiBhIHJlc3VsdCB0byBncmFiIG9uZSBwaWVjZTogYG0kVEUucmFuZG9tYCA9ICJ0aGUgcG9vbGVkCiAgZXN0aW1hdGUgc3RvcmVkIGluc2lkZSBgbWAuIgotIGB8PmAgaXMgdGhlICoqcGlwZSoqLiBJdCB0YWtlcyB3aGF0ZXZlciBpcyBvbiBpdHMgbGVmdCBhbmQgZmVlZHMgaXQgaW50byB0aGUKICBmdW5jdGlvbiBvbiBpdHMgcmlnaHQsIHNvIGEgY2hhaW4gcmVhZHMgbGVmdC10by1yaWdodCBpbnN0ZWFkIG9mIGluc2lkZS1vdXQuCi0gU29tZSBzZW50ZW5jZXMgY29udGFpbiBhIHNuaXBwZXQgd3JpdHRlbiBhcyBhbiBgcmAgZm9sbG93ZWQgYnkgYSBzaG9ydAogIGV4cHJlc3Npb24sIGFsbCB3cmFwcGVkIGluIGJhY2stdGlja3MuIFRoYXQgaXMgKippbmxpbmUgY29kZSoqOiBSIHJlcGxhY2VzIGl0CiAgd2l0aCB0aGUgbGl2ZSBudW1iZXIgd2hlbiB0aGUgcmVwb3J0IGlzIGJ1aWx0LCBzbyB0aGUgd29yZHMgYW5kIHRoZSBudW1iZXJzIGNhbgogIG5ldmVyIGRpc2FncmVlLgotICoqUGFja2FnZXMqKiAoYG1ldGFgLCBgbWV0YWZvcmAsIOKApikgYXJlIHRvb2xib3hlcyB3ZSBsb2FkIG9uY2UgYXQgdGhlIHRvcDsgZWFjaAogIGhhbmRzIHVzIHJlYWR5LW1hZGUgZnVuY3Rpb25zIHNvIHdlIG5ldmVyIHJlaW52ZW50IHRoZW0uCgojIFRoZSBjbGluaWNhbCBxdWVzdGlvbgoKV2UgY29tcGFyZWQgKipvcmdhbmlzZWQgc3Ryb2tlLXVuaXQgY2FyZSoqIOKAlCBhIGRlZGljYXRlZCB3YXJkIHdpdGggYQpzcGVjaWFsaXN0IG11bHRpZGlzY2lwbGluYXJ5IHRlYW0g4oCUIGFnYWluc3QgKipjb252ZW50aW9uYWwgY2FyZSoqIG9uIGEKZ2VuZXJhbCB3YXJkLCBtZWFzdXJpbmcgKipsZW5ndGggb2YgaG9zcGl0YWwgc3RheSwgaW4gZGF5cyoqLgoKPiAqKlBJQ08qKiDigJQgKipQKiogc3Ryb2tlIGlucGF0aWVudHMgwrcgKipJKiogb3JnYW5pc2VkIHN0cm9rZS11bml0IGNhcmUKPiDCtyAqKkMqKiBjb252ZW50aW9uYWwgZ2VuZXJhbC13YXJkIGNhcmUgwrcgKipPKiogbGVuZ3RoIG9mIHN0YXkgKGRheXMpLgoKTG93ZXIgaXMgYmV0dGVyOiBhICoqbmVnYXRpdmUgTWVhbiBEaWZmZXJlbmNlKiogbWVhbnMgdGhlIHN0cm9rZSB1bml0CnNlbmRzIHBhdGllbnRzIGhvbWUgc29vbmVyLgoKIyBUaGUgZGF0YQoKTmluZSByYW5kb21pc2VkIHRyaWFscyBhc3NlbWJsZWQgYnkgTm9ybWFuZCAoMTk5OSkgWzFdLiBFYWNoIHJvdyBpcyBvbmUKdHJpYWwsIHdpdGggdGhlIG1lYW4sIFNELCBhbmQgc2FtcGxlIHNpemUgZm9yIGJvdGggYXJtcy4KCmBgYHtyIGRhdGF9CmRhdGEoZGF0Lm5vcm1hbmQxOTk5LCBwYWNrYWdlID0gIm1ldGFmb3IiKQpkIDwtIGRhdC5ub3JtYW5kMTk5OSAgICMgc291cmNlID0gdHJpYWwgbGFiZWw7IDEgPSBzdHJva2UgdW5pdCwgMiA9IGNvbnZlbnRpb25hbAoKa2FibGUoCiAgZFssIGMoInNvdXJjZSIsICJuMWkiLCAibTFpIiwgInNkMWkiLCAibjJpIiwgIm0yaSIsICJzZDJpIildLAogIGNvbC5uYW1lcyA9IGMoIlRyaWFsIiwgIk4iLCAiTWVhbiIsICJTRCIsICJOIiwgIk1lYW4iLCAiU0QiKSwKICBjYXB0aW9uID0gIkxlbmd0aCBvZiBob3NwaXRhbCBzdGF5IChkYXlzKSBieSB0cmlhbCBhbmQgYXJtLiIKKSB8PgogIGFkZF9oZWFkZXJfYWJvdmUoYygiICIgPSAxLCAiU3Ryb2tlIHVuaXQiID0gMywgIkNvbnZlbnRpb25hbCIgPSAzKSkgfD4KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkKYGBgCgo6OjogZXhwbGFpbgoqKlBsYWluLUVuZ2xpc2ggd2Fsa3Rocm91Z2guKioKCi0gYGRhdGEoZGF0Lm5vcm1hbmQxOTk5LCBwYWNrYWdlID0gIm1ldGFmb3IiKWAgbG9hZHMgYSByZWFkeS1tYWRlIGV4YW1wbGUKICBkYXRhc2V0IHRoYXQgc2hpcHMgaW5zaWRlIHRoZSBgbWV0YWZvcmAgdG9vbGJveC4KLSBgZCA8LSBkYXQubm9ybWFuZDE5OTlgIGNvcGllcyBpdCBpbnRvIGEgc2hvcnQgbmFtZSwgYGRgLCB0aGF0IGlzIHF1aWNrZXIgdG8KICB0eXBlIGZyb20gaGVyZSBvbi4KLSBgZFssIGMoInNvdXJjZSIsICJuMWkiLCAuLi4pXWAgcGlja3Mgb3V0IGp1c3QgdGhlIGNvbHVtbnMgd2Ugd2FudCB0byBkaXNwbGF5LAogIGFuZCBga2FibGUoLi4uKWAgdHVybnMgdGhlbSBpbnRvIGEgdGlkeSB0YWJsZS4KLSBgY29sLm5hbWVzID0gYyguLi4pYCBnaXZlcyB0aGUgY29sdW1ucyBodW1hbi1mcmllbmRseSBoZWFkZXJzLCBhbmQKICBgY2FwdGlvbiA9IC4uLmAgcHV0cyBhIHRpdGxlIGFib3ZlIHRoZSB0YWJsZS4KLSBUaGUgYHw+YCBwaXBlIHRoZW4gcGFzc2VzIHRoYXQgdGFibGUgb24gdG8gYGFkZF9oZWFkZXJfYWJvdmUoKWAgKHdoaWNoIGFkZHMgdGhlCiAgIlN0cm9rZSB1bml0IC8gQ29udmVudGlvbmFsIiBzcGFubmluZyByb3cpIGFuZCB0byBga2FibGVfc3R5bGluZygpYCAodGhlCiAgc3RyaXBlZCwgaG92ZXItaGlnaGxpZ2h0IGxvb2spLgo6OjoKCioqSG93IHRvIHJlYWQgdGhlIGNvbHVtbnMuKiogVGhlIHN1ZmZpeCAqKjEqKiBpcyB0aGUgaW50ZXJ2ZW50aW9uIGFybQooc3Ryb2tlIHVuaXQpOyAqKjIqKiBpcyB0aGUgY29udHJvbCBhcm0gKGNvbnZlbnRpb25hbCBjYXJlKS4gV2l0aGluIGVhY2gKYXJtOiAqKm4qKiA9IHNhbXBsZSBzaXplLCAqKm0qKiA9IG1lYW4gbGVuZ3RoIG9mIHN0YXksICoqc2QqKiA9IHN0YW5kYXJkCmRldmlhdGlvbi4gKFRoZSB0cmFpbGluZyBgaWAgaW4gYG4xaWAvYG0xaWAv4oCmIGlzIHNpbXBseSBgbWV0YWZvcmAncwpuYW1pbmcgY29udmVudGlvbiBhbmQgY2FycmllcyBubyBhbmFseXRpYyBtZWFuaW5nLikKClR3byB0aGluZ3MgYXJlIGFscmVhZHkgdmlzaWJsZSBhbmQgd2lsbCBtYXR0ZXIgbGF0ZXI6IGNvbnZlbnRpb25hbC1jYXJlCnN0YXkgcmFuZ2VzIGZyb20gKipgciBtaW4oZCRtMmkpYCB0byBgciBtYXgoZCRtMmkpYCBkYXlzKiog4oCUIGEgbmVhcmx5CnRlbi1mb2xkIHNwcmVhZCDigJQgYW5kIHRocmVlIG9mIHRoZSB0cmlhbHMgY29tZSBmcm9tIGEgc2luZ2xlIGNlbnRyZQooT3JwaW5ndG9uKSwgZGVsaWJlcmF0ZWx5IHNwbGl0IGJ5IHN0cm9rZSBzZXZlcml0eS4KCiMgVGhlIGFuYWx5c2lzCgpXZSBwb29sIHRoZSB0cmlhbHMgYXMgYSAqKk1lYW4gRGlmZmVyZW5jZSoqIHVuZGVyIGEgKipyYW5kb20tZWZmZWN0cyoqCm1vZGVsLCBlc3RpbWF0aW5nIHRoZSBiZXR3ZWVuLXN0dWR5IHZhcmlhbmNlIGJ5IFJFTUwgYW5kIHVzaW5nIHRoZQoqKkhhcnR1bmfigJNLbmFwcCoqIGFkanVzdG1lbnQgZm9yIHRoZSBjb25maWRlbmNlIGludGVydmFsIFszXSDigJQgdGhlCm1vZGVybiBkZWZhdWx0IHRoYXQgZ3VhcmRzIGFnYWluc3Qgb3Zlci1wcmVjaXNlIGludGVydmFscyB3aGVuIHRyaWFscwphcmUgZmV3IGFuZCBoZXRlcm9nZW5lb3VzLgoKYGBge3IgcG9vbH0KbSA8LSBtZXRhY29udCgKICBuMWksIG0xaSwgc2QxaSwgICAgICAgICAgICAgICAjIHN0cm9rZS11bml0IGFybQogIG4yaSwgbTJpLCBzZDJpLCAgICAgICAgICAgICAgICMgY29udmVudGlvbmFsIGFybQogIHN0dWRsYWIgPSBzb3VyY2UsIGRhdGEgPSBkLAogIHNtICAgICAgICAgICAgICAgPSAiTUQiLCAgICAgICMgZWZmZWN0IG1lYXN1cmU6IE1lYW4gRGlmZmVyZW5jZQogIHJhbmRvbSAgICAgICAgICAgPSBUUlVFLCAgICAgICMgcmFuZG9tLWVmZmVjdHMgbW9kZWwKICBjb21tb24gICAgICAgICAgID0gRkFMU0UsCiAgbWV0aG9kLnRhdSAgICAgICA9ICJSRU1MIiwKICBtZXRob2QucmFuZG9tLmNpID0gIkhLIiwgICAgICAjIEhhcnR1bmctS25hcHAgY29uZmlkZW5jZSBpbnRlcnZhbAogIHByZWRpY3Rpb24gICAgICAgPSBUUlVFLAogIGxhYmVsLmUgPSAiU3Ryb2tlIHVuaXQiLCBsYWJlbC5jID0gIkNvbnZlbnRpb25hbCIKKQpzdW1tYXJ5KG0pCmBgYAoKOjo6IGV4cGxhaW4KKipQbGFpbi1FbmdsaXNoIHdhbGt0aHJvdWdoIOKAlCBgbWV0YWNvbnQoKWAuKiogVGhlIG5hbWUgaXMgc2hvcnQgZm9yCioqbWV0YSoqLWFuYWx5c2lzIG9mIGEgKipjb250KippbnVvdXMgb3V0Y29tZS4gSXQgdGFrZXMgZWFjaCB0cmlhbCdzIHNpeCBzdW1tYXJ5Cm51bWJlcnMgYW5kIHBvb2xzIHRoZW0gaW50byBvbmUgcmVzdWx0LiBSZWFkaW5nIGl0cyBhcmd1bWVudHMgaW4gb3JkZXI6CgotIGBuMWksIG0xaSwgc2QxaWAgdGhlbiBgbjJpLCBtMmksIHNkMmlgIOKAlCB0aGUgc2l4IGNvbHVtbnMgaXQgbmVlZHM6IHNhbXBsZQogIHNpemUsIG1lYW4sIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gZm9yIHRoZSBzdHJva2UtdW5pdCBhcm0gKCoqMSoqKSwgdGhlbiB0aGUKICBzYW1lIHRocmVlIGZvciB0aGUgY29udmVudGlvbmFsIGFybSAoKioyKiopLgotIGBzdHVkbGFiID0gc291cmNlYCDigJQgd2hpY2ggY29sdW1uIGhvbGRzIHRoZSB0cmlhbCBuYW1lIHRvIHByaW50IG9uIGVhY2ggcm93LgotIGBkYXRhID0gZGAg4oCUIHRoZSB0YWJsZSB3aGVyZSBhbGwgdGhvc2UgY29sdW1ucyBsaXZlLgotIGBzbSA9ICJNRCJgIOKAlCB0aGUgKipzdW1tYXJ5IG1lYXN1cmUqKi4gIk1EIiA9IE1lYW4gRGlmZmVyZW5jZTsgYmVjYXVzZSBib3RoCiAgYXJtcyBhcmUgbWVhc3VyZWQgaW4gdGhlIHNhbWUgdW5pdCAoZGF5cyksIHdlIGNhbiBzaW1wbHkgc3VidHJhY3QgdGhlbS4KLSBgcmFuZG9tID0gVFJVRWAg4oCUIHByb2R1Y2UgdGhlICoqcmFuZG9tLWVmZmVjdHMqKiByZXN1bHQsIHdoaWNoIGFsbG93cyB0aGUgdHJ1ZQogIGVmZmVjdCB0byBnZW51aW5lbHkgZGlmZmVyIGZyb20gdHJpYWwgdG8gdHJpYWwuCi0gYGNvbW1vbiA9IEZBTFNFYCDigJQgaGlkZSB0aGUgZml4ZWQtZWZmZWN0ICgiY29tbW9uIGVmZmVjdCIpIHJlc3VsdCwgd2hpY2ggd291bGQKICBwcmV0ZW5kIGV2ZXJ5IHRyaWFsIGlzIGVzdGltYXRpbmcgb25lIGlkZW50aWNhbCBudW1iZXIuCi0gYG1ldGhvZC50YXUgPSAiUkVNTCJgIOKAlCB0aGUgcmVjaXBlIGZvciBlc3RpbWF0aW5nICpob3cgbXVjaCogdGhlIHRyaWFscyBkaWZmZXIKICAodGhlIGJldHdlZW4tc3R1ZHkgdmFyaWFuY2UsIM+EwrIpLiBSRU1MIGlzIHRoZSBtb2Rlcm4gZGVmYXVsdC4KLSBgbWV0aG9kLnJhbmRvbS5jaSA9ICJISyJgIOKAlCB1c2UgdGhlICoqSGFydHVuZ+KAk0tuYXBwKiogY29uZmlkZW5jZSBpbnRlcnZhbCwKICB3aGljaCBzdGF5cyBob25lc3QgKGFwcHJvcHJpYXRlbHkgd2lkZSkgd2hlbiB0cmlhbHMgYXJlIGZldyBhbmQgZGlzYWdyZWUuCi0gYHByZWRpY3Rpb24gPSBUUlVFYCDigJQgYWxzbyBjb21wdXRlIHRoZSAqKnByZWRpY3Rpb24gaW50ZXJ2YWwqKjogdGhlIHJhbmdlIGEKICBicmFuZC1uZXcgdHJpYWwgbWlnaHQgcGxhdXNpYmx5IGZhbGwgaW4uCi0gYGxhYmVsLmVgIC8gYGxhYmVsLmNgIOKAlCByZWFkYWJsZSBuYW1lcyBmb3IgdGhlIGV4cGVyaW1lbnRhbCBhbmQgY29udHJvbCBhcm1zLAogIHVzZWQgbGF0ZXIgb24gdGhlIHBsb3QuCgpUaGVuIGBzdW1tYXJ5KG0pYCBwcmludHMgZXZlcnl0aGluZyBgbWV0YWNvbnRgIGp1c3QgY2FsY3VsYXRlZC4KOjo6CgojIFRoZSBmb3Jlc3QgcGxvdAoKYGBge3IgZm9yZXN0LW1haW4sIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03LCBvdXQud2lkdGg9IjEwMCUiLCBmaWcuY2FwPSJGb3Jlc3QgcGxvdCBvZiB0aGUgbmluZSB0cmlhbHMuIFNxdWFyZXMgYXJlIHRyaWFsLWxldmVsIG1lYW4gZGlmZmVyZW5jZXMgKHNpemUg4oidIHdlaWdodCk7IHRoZSByZWQgZGlhbW9uZCBpcyB0aGUgcmFuZG9tLWVmZmVjdHMgcG9vbGVkIGVzdGltYXRlIGFuZCB0aGUgcmVkIGJhciBpcyB0aGUgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWwuIiwgZmlnLmFsdD0iRm9yZXN0IHBsb3Qgc2hvd2luZyB3aWRlIGRpc2FncmVlbWVudCBhY3Jvc3MgdGhlIG5pbmUgc3Ryb2tlLXVuaXQgdHJpYWxzLCB3aXRoIGEgcG9vbGVkIGRpYW1vbmQgd2hvc2UgY29uZmlkZW5jZSBpbnRlcnZhbCBjcm9zc2VzIHRoZSBsaW5lIG9mIG5vIGVmZmVjdC4ifQpmb3Jlc3QoCiAgbSwKICBzb3J0dmFyICAgICAgICAgICAgID0gVEUsCiAgbGVmdGNvbHMgICAgICAgICAgICA9IGMoInN0dWRsYWIiLCAibi5lIiwgIm1lYW4uZSIsICJzZC5lIiwgIm4uYyIsICJtZWFuLmMiLCAic2QuYyIpLAogIGxlZnRsYWJzICAgICAgICAgICAgPSBjKCJUcmlhbCIsICJUb3RhbCIsICJNZWFuIiwgIlNEIiwgIlRvdGFsIiwgIk1lYW4iLCAiU0QiKSwKICByaWdodGNvbHMgICAgICAgICAgID0gYygiZWZmZWN0IiwgImNpIiwgIncucmFuZG9tIiksCiAgcmlnaHRsYWJzICAgICAgICAgICA9IGMoIk1EIiwgIjk1JSBDSSIsICJXZWlnaHQiKSwKICBsYWJlbC5lICAgICAgICAgICAgID0gIlN0cm9rZSB1bml0IiwgbGFiZWwuYyA9ICJDb252ZW50aW9uYWwiLAogIGNvbC5kaWFtb25kICAgICAgICAgPSAiZGFya3JlZCIsICBjb2wuZGlhbW9uZC5saW5lcyA9ICJibGFjayIsCiAgY29sLnNxdWFyZSAgICAgICAgICA9ICJzdGVlbGJsdWUzIiwgY29sLnNxdWFyZS5saW5lcyA9ICJzdGVlbGJsdWUzIiwKICBjb21tb24gPSBGQUxTRSwgcmFuZG9tID0gVFJVRSwgb3ZlcmFsbCA9IFRSVUUsIG92ZXJhbGwuaGV0c3RhdCA9IFRSVUUsCiAgcHJlZGljdGlvbiAgICAgICAgICA9IFRSVUUsICAgICAgICAgICAgICAgICMgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWwgKHJlZCBiYXIpCiAgc3BhY2luZyAgICAgICAgICAgICA9IDEuMiwKICBjb2xnYXAgICAgICAgICAgICAgID0gdW5pdCgzLCAibW0iKSwKICBjb2xnYXAuZm9yZXN0LmxlZnQgID0gdW5pdCgwLCAibW0iKSwKICBjb2xnYXAuZm9yZXN0LnJpZ2h0ID0gdW5pdCgxLCAibW0iKSwKICB4bGFiICAgICAgICAgICAgICAgID0gIkZhdm91cnMgc3Ryb2tlIHVuaXQgICAgICAgICAgRmF2b3VycyBjb252ZW50aW9uYWwiLAogIHNxdWFyZXNpemUgPSAwLjgsCiAgZGlnaXRzID0gMSwgZGlnaXRzLm1lYW4gPSAxLCBkaWdpdHMuc2QgPSAxLAogIGRpZ2l0cy5wdmFsID0gMiwgZGlnaXRzLnB2YWwuUSA9IDIsIGRpZ2l0cy5JMiA9IDEsIGRpZ2l0cy50YXUyID0gMSwKICBmb250c2l6ZSA9IDExLCBmcy5oZWFkaW5nID0gMTIsIGZzLnN0dWR5ID0gMTEsIGZzLnJhbmRvbSA9IDExLAogIGZzLmhldHN0YXQgPSAxMCwgZnMuYXhpcyA9IDEwLCBmcy54bGFiID0gMTIsIGZzLnNtbGFiID0gMTIsCiAgY29sLmhldHN0YXQgPSAiZ3JheTUwIgopCmBgYAoKOjo6IGV4cGxhaW4KKipQbGFpbi1FbmdsaXNoIHdhbGt0aHJvdWdoIOKAlCBgZm9yZXN0KClgLioqIGBmb3Jlc3QobSwgLi4uKWAgZHJhd3MgdGhlIGNsYXNzaWMKZm9yZXN0IHBsb3QgZnJvbSB0aGUgcG9vbGVkIG9iamVjdCBgbWAuIFRoZXJlIGFyZSBtYW55IGFyZ3VtZW50cywgYnV0IHRoZXkgb25seQpkbyBhIGhhbmRmdWwgb2Ygam9iczoKCi0gKipXaGF0IHRvIHNob3csIGFuZCB3aGVyZS4qKiBgbGVmdGNvbHNgIC8gYGxlZnRsYWJzYCBsaXN0IHRoZSBjb2x1bW5zIChhbmQKICB0aGVpciBoZWFkZXJzKSBkb3duIHRoZSBsZWZ0IHNpZGU7IGByaWdodGNvbHNgIC8gYHJpZ2h0bGFic2AgZG8gdGhlIHNhbWUgb24gdGhlCiAgcmlnaHQgKHRoZSBlZmZlY3QsIGl0cyBDSSwgYW5kIGVhY2ggdHJpYWwncyB3ZWlnaHQpLiBgc29ydHZhciA9IFRFYCBvcmRlcnMgdGhlCiAgdHJpYWxzIGJ5IGVmZmVjdCBzaXplLgotICoqVGhlIG92ZXJhbGwgcmVzdWx0LioqIGByYW5kb20gPSBUUlVFYCwgYGNvbW1vbiA9IEZBTFNFYCwgYG92ZXJhbGxgLCBhbmQKICBgb3ZlcmFsbC5oZXRzdGF0YCBzaG93IHRoZSByYW5kb20tZWZmZWN0cyBkaWFtb25kIGFuZCB0aGUgaGV0ZXJvZ2VuZWl0eQogIHN0YXRpc3RpY3M7IGBwcmVkaWN0aW9uID0gVFJVRWAgYWRkcyB0aGUgcmVkIHByZWRpY3Rpb24taW50ZXJ2YWwgYmFyLgotICoqQ29sb3VycyAmIHNpemVzLioqIGBjb2wuZGlhbW9uZGAsIGBjb2wuc3F1YXJlYCwgYHNxdWFyZXNpemVgLCBgc3BhY2luZ2AsIGFuZAogIHRoZSBgY29sZ2FwKmAgYXJndW1lbnRzIGFyZSBwdXJlIGNvc21ldGljcyDigJQgdGhlIGRpYW1vbmQgY29sb3VyLCB0aGUgYm94CiAgY29sb3VyLCBob3cgYmlnIHRoZSBib3hlcyBhcmUsIGFuZCB0aGUgZ2FwcyBiZXR3ZWVuIGNvbHVtbnMuCi0gKipSb3VuZGluZy4qKiBFdmVyeSBgZGlnaXRzKmAgYXJndW1lbnQgc2V0cyBob3cgbWFueSBkZWNpbWFscyBhIGdpdmVuIG51bWJlcgogIHNob3dzIChlLmcuIGBkaWdpdHMgPSAxYCDihpIgb25lIGRlY2ltYWwgcGxhY2UgZm9yIHRoZSBlZmZlY3RzKS4KLSAqKkZvbnQgc2l6ZXMuKiogYGZvbnRzaXplYCBpcyB0aGUgYmFzZWxpbmU7IGVhY2ggYGZzLipgIGZpbmUtdHVuZXMgb25lIGVsZW1lbnQKICAoaGVhZGluZywgc3R1ZHkgcm93cywgaGV0ZXJvZ2VuZWl0eSBsaW5lLCBheGlzLCBsYWJlbHMpLgotIGB4bGFiID0gIkZhdm91cnMgc3Ryb2tlIHVuaXQg4oCmIEZhdm91cnMgY29udmVudGlvbmFsImAgbGFiZWxzIHdoaWNoIHNpZGUgb2YgdGhlCiAgdmVydGljYWwgbGluZSBpcyB0aGUgZ29vZC1uZXdzIHNpZGUuCgpJbiBzaG9ydDogdGhlIGZpcnN0IGZldyBhcmd1bWVudHMgZGVjaWRlIHRoZSBwbG90J3MgKmNvbnRlbnQqLCBhbmQgdGhlIGxvbmcgdGFpbApvZiBgY29sLipgLCBgZnMuKmAsIGFuZCBgZGlnaXRzLipgIHNpbXBseSBwb2xpc2hlcyBpdHMgKmFwcGVhcmFuY2UqLgo6OjoKCiMgV2hhdCB0aGUgbnVtYmVycyBhcmUgdGVsbGluZyB1cwoKYGBge3Igc3VtbWFyeS10YWJsZX0KcmVzIDwtIGRhdGEuZnJhbWUoCiAgTWV0cmljID0gYygiUG9vbGVkIE1EIChyYW5kb20gZWZmZWN0cykiLCAiOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwiLAogICAgICAgICAgICAgIjk1JSBwcmVkaWN0aW9uIGludGVydmFsIiwgIknCsiAoaW5jb25zaXN0ZW5jeSkiLAogICAgICAgICAgICAgIs+EwrIgKGJldHdlZW4tdHJpYWwgdmFyaWFuY2UpIiwgIkNvY2hyYW4ncyBRIChwLXZhbHVlKSIpLAogIFZhbHVlID0gYygKICAgIHNwcmludGYoIiUuMWYgZGF5cyIsIG0kVEUucmFuZG9tKSwKICAgIHNwcmludGYoIiUuMWYgdG8gJS4xZiBkYXlzIiwgbSRsb3dlci5yYW5kb20sIG0kdXBwZXIucmFuZG9tKSwKICAgIHNwcmludGYoIiUuMWYgdG8gJS4xZiBkYXlzIiwgbSRsb3dlci5wcmVkaWN0LCBtJHVwcGVyLnByZWRpY3QpLAogICAgc3ByaW50ZigiJS4wZiUlIiwgbSRJMiAqIDEwMCksCiAgICBzcHJpbnRmKCIlLjFmIiwgbSR0YXUyKSwKICAgIGZvcm1hdC5wdmFsKG0kcHZhbC5RLCBkaWdpdHMgPSAyLCBlcHMgPSAwLjAwMSkKICApCikKa2FibGUocmVzLCBjb2wubmFtZXMgPSBjKCIiLCAiUmVzdWx0IiksCiAgICAgIGNhcHRpb24gPSAiUmFuZG9tLWVmZmVjdHMgc3VtbWFyeS4iKSB8PgogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkKYGBgCgo6OjogZXhwbGFpbgoqKlBsYWluLUVuZ2xpc2ggd2Fsa3Rocm91Z2guKiogVGhpcyBjaHVuayBidWlsZHMgdGhlIHN1bW1hcnkgdGFibGUgYnkgaGFuZCBzbyB3ZQpjb250cm9sIGV4YWN0bHkgd2hhdCBhcHBlYXJzLgoKLSBgZGF0YS5mcmFtZShNZXRyaWMgPSAuLi4sIFZhbHVlID0gLi4uKWAgbWFrZXMgYSB0d28tY29sdW1uIHRhYmxlOiB0aGUgbGFiZWxzIG9uCiAgdGhlIGxlZnQsIHRoZSBmb3JtYXR0ZWQgcmVzdWx0cyBvbiB0aGUgcmlnaHQuCi0gYHNwcmludGYoIiUuMWYgZGF5cyIsIG0kVEUucmFuZG9tKWAgaXMgdGV4dCBmb3JtYXR0aW5nOiBgJS4xZmAgbWVhbnMgImEgbnVtYmVyCiAgd2l0aCBvbmUgZGVjaW1hbCwiIHNvIHRoZSBwb29sZWQgZXN0aW1hdGUgcHJpbnRzIGFzLCBlLmcuLCBgLTE1LjEgZGF5c2AuIEVhY2gKICB2YWx1ZSBpcyBwdWxsZWQgc3RyYWlnaHQgZnJvbSB0aGUgbW9kZWwgd2l0aCBgJGAgKGBtJFRFLnJhbmRvbWAsIGBtJEkyYCwKICBgbSR0YXUyYCwg4oCmKSwgc28gdGhlIHRhYmxlIGNhbiBuZXZlciBkcmlmdCBhd2F5IGZyb20gdGhlIGFuYWx5c2lzLgotIGBmb3JtYXQucHZhbCguLi4sIGVwcyA9IDAuMDAxKWAgcHJpbnRzIHZlcnkgc21hbGwgcC12YWx1ZXMgbmVhdGx5IGFzIGA8IDAuMDAxYAogIGluc3RlYWQgb2YgYSBsb25nIHN0cmluZyBvZiB6ZXJvcy4KLSBga2FibGUoKSB8PiBrYWJsZV9zdHlsaW5nKClgIHJlbmRlcnMgYW5kIHN0eWxlcyB0aGUgdGFibGUsIGp1c3QgYXMgYmVmb3JlLgo6OjoKClRoZSBwb29sZWQgZXN0aW1hdGUgb2YgKipgciByb3VuZChtJFRFLnJhbmRvbSwgMSlgIGRheXMqKiBsb29rcwppbXByZXNzaXZlLCBidXQgdHdvIHNpZ25hbHMgc3RvcCB1cyBmcm9tIHJlcG9ydGluZyBpdDoKCjEuICBUaGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgKGByIHJvdW5kKG0kbG93ZXIucmFuZG9tLCAxKWAgdG8KICAgIGByIHJvdW5kKG0kdXBwZXIucmFuZG9tLCAxKWApICoqY3Jvc3NlcyB6ZXJvKiog4oCUIHRoZSBwb29sZWQgZWZmZWN0CiAgICBpcyBub3Qgc3RhdGlzdGljYWxseSBkaXN0aW5ndWlzaGFibGUgZnJvbSAibm8gZGlmZmVyZW5jZS4iCjIuICAqKknCsiBpcyBgciByb3VuZChtJEkyICogMTAwKWAlKiogWzVdIOKAlCB0aGUgdHJpYWxzIGVzc2VudGlhbGx5IGRvIG5vdAogICAgYWdyZWUuIFRoZSA5NSUgKipwcmVkaWN0aW9uIGludGVydmFsKiogWzddLAogICAgYHIgcm91bmQobSRsb3dlci5wcmVkaWN0LCAxKWAgdG8gYHIgcm91bmQobSR1cHBlci5wcmVkaWN0LCAxKWAgZGF5cywKICAgIG1ha2VzIHRoaXMgY29uY3JldGU6IGEgKm5ldyogdHJpYWwgY291bGQgcGxhdXNpYmx5IGxhbmQgYW55d2hlcmUKICAgIGZyb20gYSBsYXJnZSBiZW5lZml0IHRvIGEgbGFyZ2UgaGFybS4KCldoZW4gYSBwcmVkaWN0aW9uIGludGVydmFsIGlzIHRoYXQgd2lkZSwgYSBzaW5nbGUgcG9vbGVkIG51bWJlciBpcyBub3QgYQpmaW5kaW5nIOKAlCBpdCBpcyBhbiBhdmVyYWdlIG9mIHRoaW5ncyB0aGF0IGRvbid0IGJlbG9uZyB0b2dldGhlci4gU28gd2UKZG9uJ3QgcmVwb3J0IGl0LiBXZSBhc2sgKndoeSB0aGUgdHJpYWxzIGRpc2FncmVlKi4KCiMgSHVudGluZyBmb3IgdGhlIGNhdXNlCgpUaGUgdHJpYWwgbGFiZWxzIGhpbnQgYXQgdGhlIGFuc3dlci4gVGhyZWUgdHJpYWxzIGNvbWUgZnJvbSBvbmUgY2VudHJlCihPcnBpbmd0b24pIHNwbGl0IGJ5ICoqc3Ryb2tlIHNldmVyaXR5Kio7IHRoZSByZXN0IHNwYW4gZGlmZmVyZW50CmNvdW50cmllcyBhbmQgaGVhbHRoIHN5c3RlbXMsIGFuZCBsZW5ndGggb2Ygc3RheSBkZXBlbmRzIGhlYXZpbHkgb24gYm90aApjYXNlLW1peCBhbmQgaG93IGVhY2ggc3lzdGVtIG1hbmFnZXMgZGlzY2hhcmdlLiBCZWNhdXNlCmNvbnZlbnRpb25hbC1jYXJlIHN0YXkgcmFuZ2VzIGZyb20gYHIgbWluKGQkbTJpKWAgdG8gYHIgbWF4KGQkbTJpKWAKZGF5cywgYSBuYXR1cmFsIHF1ZXN0aW9uIGlzIHdoZXRoZXIgKipiYXNlbGluZSBzdGF5KiogZXhwbGFpbnMgdGhlCmRpc2FncmVlbWVudC4gV2UgdGVzdCBpdCB3aXRoIGEgbWV0YS1yZWdyZXNzaW9uLgoKYGBge3IgZXhwbG9yZX0KbXIgPC0gbWV0YXJlZyhtLCB+IG0yaSkgICAjIGRvZXMgY29udHJvbC1hcm0gbWVhbiBleHBsYWluIHRoZSBiZXR3ZWVuLXRyaWFsIE1EPwptcgpgYGAKCjo6OiBleHBsYWluCioqUGxhaW4tRW5nbGlzaCB3YWxrdGhyb3VnaCDigJQgYG1ldGFyZWcoKWAuKiogQSAqKm1ldGEtcmVncmVzc2lvbioqIGFza3Mgd2hldGhlcgpzb21lIHRyYWl0IG9mIHRoZSB0cmlhbHMgZXhwbGFpbnMgd2h5IHRoZWlyIHJlc3VsdHMgZGlzYWdyZWUuCgotIGBtZXRhcmVnKG0sIH4gbTJpKWAg4oCUIHRha2UgdGhlIHBvb2xlZCBvYmplY3QgYG1gIGFuZCB0ZXN0IG9uZSBwcmVkaWN0b3IuIFRoZQogIGB+IG0yaWAgcGFydCBpcyBhbiBSICoqZm9ybXVsYSoqOyByZWFkIGl0IGFzICJleHBsYWluIHRoZSBlZmZlY3QgKnVzaW5nKiBgbTJpYCIKICAodGhlIGNvbnRyb2wtYXJtIG1lYW4g4oCUIGkuZS4gYmFzZWxpbmUgbGVuZ3RoIG9mIHN0YXkpLgotIFByaW50aW5nIGBtcmAgcmVwb3J0cyB0aGUgKipzbG9wZSoqIChob3cgbXVjaCB0aGUgZWZmZWN0IHNoaWZ0cyBwZXIgZXh0cmEKICBiYXNlbGluZSBkYXkpLCBpdHMgKipwLXZhbHVlKiosIGFuZCAqKlLCsioqIOKAlCB0aGUgc2hhcmUgb2YgdGhlIGJldHdlZW4tdHJpYWwKICBkaXNhZ3JlZW1lbnQgdGhhdCB0aGlzIG9uZSBwcmVkaWN0b3IgYWNjb3VudHMgZm9yLgo6OjoKCkJhc2VsaW5lIHN0YXkgZXhwbGFpbnMgKiphbG1vc3QgYWxsKiogb2YgdGhlIGJldHdlZW4tdHJpYWwgdmFyaWF0aW9uCigqKlLCsiDiiYggYHIgcm91bmQobXIkUjIpYCUqKiwgc2xvcGUgKnAqIFw8IDAuMDAxKTogdHJpYWxzIHdoZXJlIHBhdGllbnRzCndvdWxkIG90aGVyd2lzZSBzdGF5IGEgbG9uZyB0aW1lIChzZXZlcmUgc3Ryb2tlcykgc2hvdyB0aGUgYmlnZ2VzdApyZWR1Y3Rpb25zLCB3aGlsZSB0cmlhbHMgd2l0aCBhbHJlYWR5LXNob3J0IHN0YXlzIHNob3cgYWxtb3N0IG5vbmUuIFRoZQpoZXRlcm9nZW5laXR5IHdhcyBuZXZlciBub2lzZSDigJQgaXQgd2FzICoqYmFzZWxpbmUtZGVwZW5kZW5jZSoqLgoKOjo6IGNhdmVhdAoqKlJlYWQgdGhpcyBiZWZvcmUgYmVsaWV2aW5nIGl0LioqIFJlZ3Jlc3NpbmcgdGhlIE1lYW4gRGlmZmVyZW5jZSBvbiB0aGUKY29udHJvbC1ncm91cCBtZWFuIGlzICoqZXhwbG9yYXRvcnkqKiwgbm90IGNvbmZpcm1hdG9yeS4gVGhlIGNvbnRyb2wKbWVhbiBpcyBwYXJ0IG9mIHRoZSBvdXRjb21lIGl0c2VsZiAoTUQgPSBpbnRlcnZlbnRpb24g4oiSIGNvbnRyb2wpLCBzbyB0aGUKdHdvIGFyZSBtYXRoZW1hdGljYWxseSBsaW5rZWQgYW5kIHBhcnQgb2YgdGhpcyBhc3NvY2lhdGlvbiBpcyBidWlsdCBpbi4KVHJlYXQgaXQgYXMgKipoeXBvdGhlc2lzLWdlbmVyYXRpbmcqKiwgbm90IHByb29mLgo6OjoKCiMgQSBjbGVhbmVyIHRlc3Q6IHRoZSBPcnBpbmd0b24gc2V2ZXJpdHkgZ3JhZGllbnQKClRoZSBjYXZlYXQgYWJvdmUgaGFzIGEgY2xlYW4gYW5zd2VyLiBJbnN0ZWFkIG9mIGJhc2VsaW5lIHN0YXkg4oCUIHdoaWNoIGlzCnRhbmdsZWQgd2l0aCB0aGUgb3V0Y29tZSDigJQgd2UgdXNlIGFuICoqaW5kZXBlbmRlbnQqKiBtb2RlcmF0b3I6CnByZS1yYW5kb21pc2F0aW9uICoqc3Ryb2tlIHNldmVyaXR5KiouIFRoZSB0aHJlZSBPcnBpbmd0b24gdHJpYWxzIGFyZQppZGVhbCwgYmVjYXVzZSB0aGV5IGhvbGQgdGhlIGhvc3BpdGFsLCB0ZWFtLCBhbmQgaGVhbHRoIHN5c3RlbQoqY29uc3RhbnQqIGFuZCB2YXJ5IG9ubHkgYnkgc2V2ZXJpdHkuCgpgYGB7ciBvcnBpbmd0b259Cm9ycCA8LSBzdWJzZXQoZCwgZ3JlcGwoIk9ycGluZ3RvbiIsIHNvdXJjZSkpCm9ycCRzZXZlcml0eSA8LSBjKCJNaWxkIiwgIk1vZGVyYXRlIiwgIlNldmVyZSIpCm9ycCRNRCA8LSBvcnAkbTFpIC0gb3JwJG0yaSAgICAjIHN0cm9rZSB1bml0IC0gY29udmVudGlvbmFsCgprYWJsZShvcnBbLCBjKCJzZXZlcml0eSIsICJtMWkiLCAibTJpIiwgIk1EIildLAogICAgICBjb2wubmFtZXMgPSBjKCJTdHJva2Ugc2V2ZXJpdHkiLCAiU3Ryb2tlLXVuaXQgbWVhbiIsCiAgICAgICAgICAgICAgICAgICAgIkNvbnZlbnRpb25hbCBtZWFuIiwgIk1lYW4gZGlmZmVyZW5jZSAoZGF5cykiKSwKICAgICAgY2FwdGlvbiA9ICJPcnBpbmd0b24gdHJpYWxzIOKAlCBzYW1lIGNlbnRyZSwgc2FtZSB0ZWFtLCBzZXZlcml0eSB0aGUgb25seSBkaWZmZXJlbmNlLiIpIHw+CiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQpgYGAKCjo6OiBleHBsYWluCioqUGxhaW4tRW5nbGlzaCB3YWxrdGhyb3VnaC4qKgoKLSBgc3Vic2V0KGQsIGdyZXBsKCJPcnBpbmd0b24iLCBzb3VyY2UpKWAg4oCUIGtlZXAgb25seSB0aGUgcm93cyB3aG9zZSBgc291cmNlYAogIG5hbWUgKmNvbnRhaW5zKiB0aGUgdGV4dCAiT3JwaW5ndG9uLiIgYGdyZXBsKClgIGlzIGEgdGV4dCBzZWFyY2ggdGhhdCByZXR1cm5zCiAgVFJVRS9GQUxTRSBmb3IgZXZlcnkgcm93LCBhbmQgYHN1YnNldCgpYCBrZWVwcyB0aGUgVFJVRSBvbmVzLgotIGBvcnAkc2V2ZXJpdHkgPC0gYygiTWlsZCIsICJNb2RlcmF0ZSIsICJTZXZlcmUiKWAg4oCUIGFkZCBhIG5ldyBjb2x1bW4gYnkgaGFuZCwKICBsYWJlbGxpbmcgdGhvc2UgdGhyZWUgcm93cy4KLSBgb3JwJE1EIDwtIG9ycCRtMWkgLSBvcnAkbTJpYCDigJQgY29tcHV0ZSBlYWNoIHRyaWFsJ3MgbWVhbiBkaWZmZXJlbmNlIGRpcmVjdGx5CiAgKHN0cm9rZS11bml0IG1lYW4gbWludXMgY29udmVudGlvbmFsIG1lYW4pIOKAlCB0aGUgdmVyeSBzdWJ0cmFjdGlvbiBgbWV0YWNvbnRgCiAgZG9lcyBpbnRlcm5hbGx5LgotIGBrYWJsZSguLi4pIHw+IGthYmxlX3N0eWxpbmcoLi4uKWAg4oCUIGRpc3BsYXkgaXQgYXMgYSB0aWR5IHRhYmxlLgo6OjoKCjo6OiB3aW4KSG9sZGluZyB0aGUgc3lzdGVtIGZpeGVkLCB0aGUgbWVhbiBkaWZmZXJlbmNlIGdvZXMgZnJvbSAqKmByIG9ycCRNRFsxXWAKZGF5cyoqIChtaWxkKSDihpIgKipgciBvcnAkTURbMl1gIGRheXMqKiAobW9kZXJhdGUpIOKGkiAqKmByIG9ycCRNRFszXWAKZGF5cyoqIChzZXZlcmUpLiBBIGNsZWFuLCBtb25vdG9uaWMgZG9zZeKAk3Jlc3BvbnNlIG9uIGFuICppbmRlcGVuZGVudCoKY2xpbmljYWwgY2hhcmFjdGVyaXN0aWMg4oCUIGV4YWN0bHkgdGhlIGNvbmZpcm1hdG9yeSBzaWduYWwgdGhlCmJhc2VsaW5lLXN0YXkgcmVncmVzc2lvbiBjb3VsZCBvbmx5IGhpbnQgYXQuCjo6OgoKVGhpcyBpcyB0aGUgZGVmZW5zaWJsZSB2ZXJzaW9uIG9mIHRoZSBzdG9yeTogc2V2ZXJpdHkgaXMgY2xpbmljYWxseQptZWFuaW5nZnVsLCBhdmFpbGFibGUgaW4gdGhlIHNvdXJjZSB0cmlhbHMsIGFuZCBub3QgbWF0aGVtYXRpY2FsbHkgYm91bmQKdG8gdGhlIG91dGNvbWUuIEluIGEgcmVhbCByZXZpZXcsIHdlIHdvdWxkICoqcHJlLXNwZWNpZnkqKiBpdCBhcyB0aGUKbW9kZXJhdG9yIGFuZCBleHRyYWN0IGl0IGR1cmluZyBkYXRhIGNvbGxlY3Rpb24uCgojIFNlbnNpdGl2aXR5OiBpcyBhbnkgc2luZ2xlIHRyaWFsIGRyaXZpbmcgdGhlIHJlc3VsdD8KCkJlZm9yZSBkcmF3aW5nIGNvbmNsdXNpb25zLCB3ZSBjaGVjayB0aGF0IG5vIG9uZSB0cmlhbCBpcyBkb2luZyBhbGwgdGhlCndvcmssIGJ5IHJlLXBvb2xpbmcgd2l0aCBlYWNoIHRyaWFsIHJlbW92ZWQgaW4gdHVybiAobGVhdmUtb25lLW91dCkuCgpgYGB7ciBsb28sIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTUuNSwgb3V0LndpZHRoPSIxMDAlIiwgZmlnLmNhcD0iTGVhdmUtb25lLW91dCBhbmFseXNpczogdGhlIHBvb2xlZCBlc3RpbWF0ZSByZS1jb21wdXRlZCB3aXRoIGVhY2ggdHJpYWwgb21pdHRlZC4iLCBmaWcuYWx0PSJMZWF2ZS1vbmUtb3V0IGZvcmVzdCBwbG90OyB0aGUgcG9vbGVkIGVzdGltYXRlIHN0YXlzIG5lZ2F0aXZlIGJ1dCBtb2Rlc3QgcmVnYXJkbGVzcyBvZiB3aGljaCB0cmlhbCBpcyByZW1vdmVkLiJ9CmZvcmVzdChtZXRhaW5mKG0sIHBvb2xlZCA9ICJyYW5kb20iKSwKICAgICAgIGNvbC5zcXVhcmUgPSAic3RlZWxibHVlMyIsIGNvbC5kaWFtb25kID0gImRhcmtyZWQiLAogICAgICAgZm9udHNpemUgPSAxMSkKYGBgCgo6OjogZXhwbGFpbgoqKlBsYWluLUVuZ2xpc2ggd2Fsa3Rocm91Z2gg4oCUIGBtZXRhaW5mKClgLioqIGBtZXRhaW5mKG0sIHBvb2xlZCA9ICJyYW5kb20iKWAKcmUtcnVucyB0aGUgcmFuZG9tLWVmZmVjdHMgcG9vbCAqKm5pbmUgdGltZXMqKiDigJQgZWFjaCBydW4gbGVhdmluZyBvbmUgdHJpYWwgb3V0CigiaW5mIiBpcyBzaG9ydCBmb3IgKmluZmx1ZW5jZSopLiBXcmFwcGluZyBpdCBpbiBgZm9yZXN0KC4uLilgIGRyYXdzIG9uZSByb3cgcGVyCm9taXNzaW9uLCBzbyB5b3UgY2FuIHNlZSBhdCBhIGdsYW5jZSB3aGV0aGVyIGRyb3BwaW5nIGFueSBzaW5nbGUgdHJpYWwgd291bGQKY2hhbmdlIHRoZSBjb25jbHVzaW9uLgo6OjoKClRoZSBwb29sZWQgZXN0aW1hdGUgc3RheXMgaW4gYSBuYXJyb3cgYmFuZCAocm91Z2hseSDiiJI5IHRvIOKIkjE4IGRheXMpIGFuZApuZXZlciBjcm9zc2VzIHRvIGZhdm91cmluZyBjb252ZW50aW9uYWwgY2FyZSwgc28gbm8gc2luZ2xlIHRyaWFsIGlzCmZhYnJpY2F0aW5nIHRoZSBzaWduYWwuIFRoZSB0d28gb21pc3Npb25zIHRoYXQgcHVsbCB0aGUgZXN0aW1hdGUKKnRvd2FyZCogemVybyBhcmUgdGhlICoqT3JwaW5ndG9uLU1vZGVyYXRlKiogYW5kICoqT3JwaW5ndG9uLVNldmVyZSoqCnRyaWFscyDigJQgd2hpY2ggaXMgbm90IGZyYWdpbGl0eSwgYnV0IHRoZSBzYW1lIG1lc3NhZ2UgYWdhaW46IHRoZQpoaWdoLXNldmVyaXR5IHRyaWFscyBjYXJyeSB0aGUgYmVuZWZpdC4KCiMgQSBub3RlIG9uIHNtYWxsLXN0dWR5IGVmZmVjdHMKCldpdGggb25seSAqKmByIG0ka2AgdHJpYWxzKiosIGEgZnVubmVsIHBsb3QgYW5kIEVnZ2VyJ3MgdGVzdCBhcmUKdW5kZXJwb3dlcmVkIGFuZCBlYXNpbHkgbWlzcmVhZCDigJQgZ3VpZGFuY2UgaXMgbm90IHRvIHRlc3QgZm9yCnNtYWxsLXN0dWR5IGVmZmVjdHMgYmVsb3cgXH4xMCBzdHVkaWVzLCBhbmQgc2V2ZXJlIGhldGVyb2dlbmVpdHkgbWFrZXMKYW4gYXN5bW1ldHJ5IHRlc3QgdW5pbnRlcnByZXRhYmxlIGhlcmUgYW55d2F5IFs1XS4gV2UgdGhlcmVmb3JlICoqc3RhdGUKdGhlIGxpbWl0YXRpb24gZXhwbGljaXRseSoqIHJhdGhlciB0aGFuIHByZXNlbnQgYSBwbG90IHRoYXQgY2Fubm90CnN1cHBvcnQgYSBjb25jbHVzaW9uLiBOYW1pbmcgdGhpcyBpcyB0aGUgaG9uZXN0LCByaWdvcm91cyBtb3ZlLgoKIyBXaGF0IHdlIGxlYXJuZWQKCi0gVGhlIG5haXZlIGhlYWRsaW5lIOKAlCAic3Ryb2tlIHVuaXRzIHNhdmUgYHIgYWJzKHJvdW5kKG0kVEUucmFuZG9tKSlgCiAgZGF5cyIg4oCUIGlzICoqbm90IHN1cHBvcnRlZCoqOiB0aGUgQ0kgY3Jvc3NlcyB6ZXJvIGFuZCBJwrIgaXMKICBgciByb3VuZChtJEkyICogMTAwKWAlLgotIFRoZSBkaXNhZ3JlZW1lbnQgaXMgKipub3Qgbm9pc2UqKi4gVGhlIGJlbmVmaXQgKipkZXBlbmRzIG9uIGJhc2VsaW5lCiAgc2V2ZXJpdHkqKjogbGFyZ2VzdCB3aGVyZSBjb252ZW50aW9uYWwgc3RheXMgYXJlIGxvbmdlc3QgKHNldmVyZQogIHN0cm9rZXMpLCBtaW5pbWFsIHdoZXJlIHRoZXkgYXJlIGFscmVhZHkgc2hvcnQg4oCUIGNvbmZpcm1lZCBjbGVhbmx5CiAgd2l0aGluIHRoZSBPcnBpbmd0b24gY2VudHJlLgotIFRoZSByZXN1bHQgaXMgKipyb2J1c3QqKiB0byBsZWF2ZS1vbmUtb3V0LCBhbmQgc21hbGwtc3R1ZHktZWZmZWN0CiAgdGVzdGluZyBpcyBjb3JyZWN0bHkgKip3aXRoaGVsZCoqIGF0IHRoaXMgc2FtcGxlIHNpemUuCi0gKipUcmFuc2ZlcmFibGUgbWV0aG9kIGhhYml0czoqKiAoMSkgcGljayB0aGUgZWZmZWN0IG1lYXN1cmUgZnJvbSB0aGUKICBvdXRjb21lIChNRCBmb3IgYSBzaGFyZWQgc2NhbGUpOyAoMikgZGVmYXVsdCB0byByYW5kb20tZWZmZWN0cyArCiAgSGFydHVuZ+KAk0tuYXBwOwogICgzKSByZWFkIHRoZSAqKnByZWRpY3Rpb24gaW50ZXJ2YWwqKiwgbm90IGp1c3QgdGhlIENJOyAoNCkgKipleHBsYWluCiAgICAgIGhldGVyb2dlbmVpdHkqKiBiZWZvcmUgcXVvdGluZyBhbnkgcG9vbGVkIG51bWJlcjsgYW5kICg1KSBwcmVmZXIgYQogICAgICBtb2RlcmF0b3IgdGhhdCBpcyAqaW5kZXBlbmRlbnQqIG9mIHRoZSBvdXRjb21lLgoKIyBSZWFsLXdvcmxkIHZhbGlkYXRpb24KClRoaXMgdGVhY2hpbmcgcmVzdWx0IGVjaG9lcyB0aGUgZGVmaW5pdGl2ZSBldmlkZW5jZTogdGhlIENvY2hyYW5lCioqU3Ryb2tlIFVuaXQgVHJpYWxpc3RzJyBDb2xsYWJvcmF0aW9uKiogcmV2aWV3IGZvdW5kIHRoYXQgb3JnYW5pc2VkCnN0cm9rZS11bml0IGNhcmUgaW1wcm92ZXMgb3V0Y29tZXMsIHdpdGggZWZmZWN0cyB0aGF0IHZhcnkgYnkgcGF0aWVudApzZXZlcml0eSBhbmQgY2FyZSBzZXR0aW5nIFs0XSDigJQgcmVhc3N1cmFuY2UgdGhhdCB0aGUgYW5hbHl0aWMgc3RvcnkgaGVyZQpwb2ludHMgdGhlIHNhbWUgd2F5IGFzIHRoZSBmdWxsIGJvZHkgb2YgdHJpYWxzLgoKIyBSZXByb2R1Y2liaWxpdHkgJiBkYXRhIGF2YWlsYWJpbGl0eQoKLSAqKkRhdGE6KiogYGRhdC5ub3JtYW5kMTk5OWAgZnJvbSB0aGUgYG1ldGFmb3JgIHBhY2thZ2UgKE5vcm1hbmQgMTk5OSkKICBbMTs2XSDigJQgbm8gcHJpdmF0ZSBkYXRhOyB0aGUgYW5hbHlzaXMgaXMgZnVsbHkgcmVwcm9kdWNpYmxlIGZyb20gdGhpcwogIGRvY3VtZW50LgotICoqQ29kZToqKiBldmVyeSBmaWd1cmUgYW5kIG51bWJlciBpcyBnZW5lcmF0ZWQgaW4tbGluZSBmcm9tIHRoZSBmaXR0ZWQKICBtb2RlbCAobm8gaGFyZC1jb2RlZCByZXN1bHRzKS4gVXNlIHRoZSAqKkNvZGUg4pa4IERvd25sb2FkIFJtZCoqIGJ1dHRvbgogICh0b3AtcmlnaHQpIHRvIGdldCB0aGUgc291cmNlLgotICoqRW52aXJvbm1lbnQ6KiogZXhhY3QgcGFja2FnZSB2ZXJzaW9ucyBhcmUgcmVjb3JkZWQgaW4gdGhlIGFwcGVuZGl4CiAgYmVsb3cuCgojIFJlZmVyZW5jZXMgeyNyZWZlcmVuY2VzfQoKMS4gIE5vcm1hbmQgU0wuIE1ldGEtYW5hbHlzaXM6IGZvcm11bGF0aW5nLCBldmFsdWF0aW5nLCBjb21iaW5pbmcsIGFuZAogICAgcmVwb3J0aW5nLiAqU3RhdCBNZWQuKiAxOTk5OzE4KDMpOjMyMeKAkzM1OS4KMi4gIEJhbGR1enppIFMsIFLDvGNrZXIgRywgU2Nod2FyemVyIEcuIEhvdyB0byBwZXJmb3JtIGEgbWV0YS1hbmFseXNpcwogICAgd2l0aCBSOiBhIHByYWN0aWNhbCB0dXRvcmlhbC4gKkV2aWQgQmFzZWQgTWVudCBIZWFsdGguKgogICAgMjAxOTsyMig0KToxNTPigJMxNjAuICh0aGUgYG1ldGFgIHBhY2thZ2UpCjMuICBJbnRIb3V0IEosIElvYW5uaWRpcyBKUEEsIEJvcm0gR0YuIFRoZSBIYXJ0dW5n4oCTS25hcHDigJNTaWRpa+KAk0pvbmttYW4KICAgIG1ldGhvZCBmb3IgcmFuZG9tLWVmZmVjdHMgbWV0YS1hbmFseXNpcyBpcyBzdHJhaWdodGZvcndhcmQgYW5kCiAgICBjb25zaWRlcmFibHkgb3V0cGVyZm9ybXMgdGhlIHN0YW5kYXJkIERlclNpbW9uaWFu4oCTTGFpcmQgbWV0aG9kLiAqQk1DCiAgICBNZWQgUmVzIE1ldGhvZG9sLiogMjAxNDsxNDoyNS4KNC4gIFN0cm9rZSBVbml0IFRyaWFsaXN0cycgQ29sbGFib3JhdGlvbi4gT3JnYW5pc2VkIGlucGF0aWVudCAoc3Ryb2tlCiAgICB1bml0KSBjYXJlIGZvciBzdHJva2UuICpDb2NocmFuZSBEYXRhYmFzZSBTeXN0IFJldi4qCiAgICAyMDEzOyg5KTpDRDAwMDE5Ny4KNS4gIEhpZ2dpbnMgSlBULCBUaG9tcHNvbiBTRy4gUXVhbnRpZnlpbmcgaGV0ZXJvZ2VuZWl0eSBpbiBhCiAgICBtZXRhLWFuYWx5c2lzLiAqU3RhdCBNZWQuKiAyMDAyOzIxKDExKToxNTM54oCTMTU1OC4KNi4gIFZpZWNodGJhdWVyIFcuIENvbmR1Y3RpbmcgbWV0YS1hbmFseXNlcyBpbiBSIHdpdGggdGhlIG1ldGFmb3IKICAgIHBhY2thZ2UuICpKIFN0YXQgU29mdHcuKiAyMDEwOzM2KDMpOjHigJM0OC4KNy4gIEludEhvdXQgSiwgSW9hbm5pZGlzIEpQQSwgUm92ZXJzIE1NLCBHb2VtYW4gSkouIFBsZWEgZm9yIHJvdXRpbmVseQogICAgcHJlc2VudGluZyBwcmVkaWN0aW9uIGludGVydmFscyBpbiBtZXRhLWFuYWx5c2lzLiAqQk1KIE9wZW4uKgogICAgMjAxNjs2OmUwMTAyNDcuCgojIEFwcGVuZGl4OiBzZXNzaW9uIGluZm9ybWF0aW9uIHsudW5udW1iZXJlZH0KCjo6OiBleHBsYWluCioqUGxhaW4tRW5nbGlzaCB3YWxrdGhyb3VnaC4qKiBgc2Vzc2lvbkluZm8oKWAgcHJpbnRzIHRoZSBleGFjdCBSIHZlcnNpb24gYW5kIHRoZQp2ZXJzaW9uIG9mIGV2ZXJ5IHBhY2thZ2UgdXNlZC4gSW5jbHVkaW5nIGl0IGxldHMgYW55b25lIHJlcnVuIHRoaXMgYW5hbHlzaXMgd2l0aAp0aGUgc2FtZSB0b29scyBhbmQgZ2V0IHRoZSBzYW1lIG51bWJlcnMg4oCUIGEgaGFsbG1hcmsgb2YgdHJ1c3R3b3J0aHkgd29yay4KOjo6CgpgYGB7ciBzZXNzaW9uLCBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIn0Kc2Vzc2lvbkluZm8oKQpgYGAK