This is part of the online course Statistical Genomics 2021
(SGA21)
Background
Histologic grade in breast cancer provides clinically important
prognostic information. Researchers examined whether histologic grade
was associated with gene expression profiles of breast cancers and
whether such profiles could be used to improve histologic grading. In
this tutorial we will assess the association between histologic grade
and the expression of the KPNA2 gene that is known to be associated with
poor BC prognosis. The patients, however, do not only differ in the
histologic grade, but also on their lymph node status. The lymph nodes
were not affected (0) or chirugically removed (1).
Data analysis
Import KPNA2 data in
R
kpna2 <- read.table("https://raw.githubusercontent.com/statOmics/SGA21/master/data/kpna2.txt",header=TRUE)
kpna2
Data exploration
Histologic grade and lymph node status can be associated with the
kpna2 gene expression. Moreover, it is also possible that the
differential expression associated with histological grade is different
in patients that have unaffected lymph nodes and patients for which the
lymph nodes had to be removed.
kpna2 %>%
ggplot(aes(x=node:grade,y=gene,fill=node:grade)) +
geom_boxplot(outlier.shape = NA) +
geom_jitter()
The plot suggests
- An effect of the histological grade
- An effect of node status
- The differential expression associated to grade seems to differ
according to the lymph node status (interaction)
- Mean variance relation?
Model
Histologic grade and lymph node status can be associated with the
kpna2 gene expression. Moreover, it is also possible that the
differential expression associated with histological grade is different
in patients that have unaffected lymph nodes and patients for which the
lymph nodes had to be removed. Hence, we will have to model the gene
expression by using main effects for grade, node and a grade x node
interaction.
#Model with main effects for histological grade and node and grade x node interaction
fit <- lm(gene~grade*node,data=kpna2)
plot(fit)
The variance seems to increase with the mean. The QQ-plot of the
residuals shows deviations from normality or some outliers.
We will first log transform the data.
fit <- lm(gene %>% log2~grade*node,data=kpna2)
plot(fit)
- The variance is now more or less equal for every treatment x node
combination.
- The QQ-plot of the residuals shows no deviations from
normality.
library(car)
Anova(fit,type="III")
The output shows that there is a very significant interaction (\(p=\) 0.0071). Hence, the association of the
histological grade on the gene expression differs according to the lymph
node status and vice versa.
The researchers are therefore interested in studying and reporting on
the following hypotheses:
Is the KPNA2 expression on average different between grade 3 and
grade 1 tumors from patients with unaffected lymph nodes (by testing
\(H_0: \log_2{FC}_{g3n0-g1n0}=0\text{ vs }H1:
\log_2{FC}_{g3n0-g1n0}\neq 0\))
Is the KPNA2 expression on average different between grade 3 and
grade 1 tumors from patients with affected lymph nodes (by testing \(H_0: \log_2{FC}_{g3n1-g1n1}=0\text{ vs }H1:
\log_2{FC}_{g3n1-g1n1}\neq 0\))
Is the KPNA2 expression on average different in grade 1 tumors of
patients with affected and patients with unaffected lymph nodes (by
testing \(H_0: \log_2{FC}_{g1n1-g1n0}=0\text{
vs }H1: \log_2{FC}_{g1n1-g1n0}\neq 0\))
Is the KPNA2 expression on average different in grade 3 tumors of
patients with affected and patients with unaffected lymph nodes (by
testing \(H_0: \log_2{FC}_{g3n1-g3n0}=0\text{
vs }H1: \log_2{FC}_{g3n1-g3n0}\neq 0\))
Is the fold change of the KPNA2 gene between grade 3 and grade 1
different according to the lymph node status and vice versa (tested
already by assessing the interaction: \(H_0:
\log_2{FC}_{g3n0-g1n0}=\log_2{FC}_{g3n1-g1n1} \text{ vs
}H1:\log_2{FC}_{g3n0-g1n0}\neq\log_2{FC}_{g3n1-g1n1}\)).
Interpretation of model
parameters and statistical tests
ExploreModelMatrix::VisualizeDesign(kpna2,~grade*node)$plotlist
[[1]]
Call:
lm(formula = gene %>% log2 ~ grade * node, data = kpna2)
Residuals:
Min 1Q Median 3Q Max
-0.57694 -0.19857 -0.04079 0.20807 0.64557
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 7.4796 0.1292 57.893 < 2e-16 ***
grade3 1.6675 0.1827 9.127 1.44e-08 ***
node1 0.6577 0.1827 3.600 0.00179 **
grade3:node1 -0.7748 0.2584 -2.998 0.00710 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.3165 on 20 degrees of freedom
Multiple R-squared: 0.848, Adjusted R-squared: 0.8252
F-statistic: 37.18 on 3 and 20 DF, p-value: 2.266e-08
#Calculate confidence intervals for parameters of model
CIfit <- confint(fit)
#log_2 FC between g3n0-g1n0, g1n1-g1n0
#and log_2 difference in FC g3n1-g1n1 and FC g3n0-g1n0
CIfit
2.5 % 97.5 %
(Intercept) 7.2101125 7.7491128
grade3 1.2864076 2.0486691
node1 0.2766005 1.0388620
grade3:node1 -1.3137511 -0.2357505
#Transform parameters and the CI back to the original scale
2^fit$coef
(Intercept) grade3 node1 grade3:node1
178.4792627 3.1767209 1.5775997 0.5844896
2.5 % 97.5 %
(Intercept) 148.0676336 215.1371400
grade3 2.4391992 4.1372414
node1 1.2113372 2.0546063
grade3:node1 0.4022736 0.8492431
2^-fit$coef["grade3:node1"]
grade3:node1
1.710895
2^-CIfit["grade3:node1",]
2.5 % 97.5 %
2.485870 1.177519
We model the log\(_2\)-transformed
intensities with the following model: \[
y=\beta_0+\beta_{g3}x_{g3}+\beta_{n1}x_{n1}+\beta_{g3n1}x_{g3}x_{n1},
\]
with \(\beta_0\) the intercept,
\(\beta_{g3}\) the main effect for
grade, \(x_{g3}\) a dummy variable for
grade which is 0 for the control treatment in the absence of grade and 1
for the treatment with grade, \(\beta_{n1}\) the main effect for node,
\(x_{n1}\) a dummy variable that is 0
for the measurements of patients with unaffected lymph nodes and 1 for
patients for which the lymph nodes were removed and \(\beta_{g3n1}\) the interaction effect
between grade and node. To ease the interpretation of the parameters,
\(\log_2\) transformed geometric mean
intensities are given for each treatment group as well as corresponding
contrasts between treatments, which have an interpretation in terms of
\(\log_2\) transformed fold changes
(FC).
\(\log_2\hat{\mu}_{g1n0}=\hat\beta_0\), \(\log_2
\hat{\mu}_{g3n0}=\hat\beta_0+\hat\beta_{g3}\) –> \(\log_2
\widehat{FC}_{g3n0-g1n0}=\hat\beta_{g3}\)
\(\log_2
\hat{\mu}_{g1n1}=\hat\beta_0+\hat\beta_{n1}\), \(\log_2 \hat
{\mu}_{g3n1}=\hat\beta_0+\hat\beta_{g3}+\hat\beta_{n1}+\hat\beta_{g3n1}\)
–> \(\log_2 \widehat{FC}_{g3n1-g1n1}=\hat
\beta_{g3} +\hat\beta_{g3n1}\)
Similarly, \(\log_2
\widehat{FC}_{g1n1-g1n0}=\hat\beta_{n1}\), \(\log_2
\widehat{FC}_{g3n1-g3n0}=\hat\beta_{n1}+\hat\beta_{g3n1}\)
\(\log_2\frac{\widehat{FC}_{g3n1-g1n1}}{\widehat{FC}_{g3n0-g1n0}}=\log_2\frac{\widehat{FC}_{g3n1-g3n0}}{\widehat{FC}_{g1n1-g1n0}}=\hat\beta_{g3n1}\)
with \(\log_2\hat{\mu}_{g1n0}\),
\(\log_2\hat{\mu}_{g3n0}\), \(\log_2\hat {\mu}_{g1n1}\) and \(\log_2\hat{\mu}_{g3n1}\) the estimated mean
\(\log_2\) transformed intensity for
patients with grade 1 and node 0 status, grade 3 and node 0 status,
grade 1 and node 1 status and grade 3 and node 1 status, respectively.
With \(\log_2 \widehat{FC}_{b-a}\) we
indicate \(\log_2\) transformed fold
change estimates between treatment b and treatment a, i.e. \(\log_2 \widehat{FC}_{b-a}=\log_2
\hat{\mu}_{b}-\log_2 \hat{\mu}_a=\log_2
\frac{\hat{\mu}_{b}}{\hat{\mu}_{a}}\).
The model immediately provides statistical tests for assessing the
significance of fold changes between grade 3 and grade 1 for patients
with unaffected lymph nodes (n=0) \(\log_2
{FC}_{g3n0-g1n0}\), fold changes between the grade 1-node 1
patients and grade 1- node 0 patients \(\log_2
{FC}_{g1n1-g3n0}\) and for differences in fold change related to
histological grade for node 1 patients and node 0 patients. \(\log_2\frac{{FC}_{g3n1-g1n1}}{{FC}_{g3n0-g1n0}}\),
the interaction term.
Interpretation of the model parameters in the model output:
- The geometric mean intensity for grade 1 patients with unaffected
lymph nodes equals \(\exp(\hat
\beta_0)\)= 178.48.
- When lymph nodes are unaffected, the expression is on average 3.18
times higher for patients with histological grade 3 than patients with
histological grade 1.
- The gene expression in histological grade 1 patients with affected
lymph nodes is on average 1.58 times higher than for grade 1 patients
with unaffected lymph nodes.
- The fold change corresponding to histological grade is on average
1.71 times lower in patients with affected lymph nodes as compared to
patients with unaffected lymph node.
For the remaining hypothesis of interest we will have to define
contrasts: linear combinations of the model parameters and evaluate the
contrasts with the multcomp package.
The F-test showed an extremely significant association of the node
status, hystological grade and/or the interaction between the node
status and the grade (p<<0.001).
Assessing the
significance of all hypothesis of interest
We can assess all contrasts of interest using the multcomp package.
This will also allow us to correct for multiple testing, since we assess
multiple hypotheses to answer the relevant research question.
- \(H_0: \log_2{FC}_{g3n0-g1n0}=
\beta_{g3}=0\) \(\rightarrow\)
“grade3 = 0”
- \(H_0: \log_2{FC}_{g3n1-g1n1}= \beta_{g3}
+ \hat\beta_{g3n1}=0\) \(\rightarrow\) “grade3+grade3:node1 =
0”
- \(H_0: \log_2{FC}_{g1n1-g1n0}=
\beta_{n1}\) \(\rightarrow\)
“node1 = 0”
- \(H_0: \log_2{FC}_{g3n1-g3n0}= \beta_{n1}
+ \hat\beta_{g3n1}=0\) \(\rightarrow\) “node1+grade3:node1 = 0”
- \(H_0: \log_2{FC}_{g3n1-g1n1} -
\log_2{FC}_{g3n0-g1n0} = \hat\beta_{g3n1}=0\), note that the
latter hypothesis is also equivalent to \(H_0:
\log_2{FC}_{g3n1-g3n0} - \log_2{FC}_{g1n1-g1n0} =
\hat\beta_{g3n1}=0\) \(\rightarrow\) “grade3:node1 = 0”
library(multcomp)
fitGlht<- glht(fit, linfct = c("grade3 = 0","grade3+grade3:node1 = 0","node1 = 0","node1+grade3:node1 = 0","grade3:node1 = 0"))
summary(fitGlht)
Simultaneous Tests for General Linear Hypotheses
Fit: lm(formula = gene %>% log2 ~ grade * node, data = kpna2)
Linear Hypotheses:
Estimate Std. Error t value Pr(>|t|)
grade3 == 0 1.6675 0.1827 9.127 < 0.001 ***
grade3 + grade3:node1 == 0 0.8928 0.1827 4.886 < 0.001 ***
node1 == 0 0.6577 0.1827 3.600 0.00714 **
node1 + grade3:node1 == 0 -0.1170 0.1827 -0.640 0.89814
grade3:node1 == 0 -0.7748 0.2584 -2.998 0.02669 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Adjusted p values reported -- single-step method)
Simultaneous Confidence Intervals
Fit: lm(formula = gene %>% log2 ~ grade * node, data = kpna2)
Quantile = 2.7003
95% family-wise confidence level
Linear Hypotheses:
Estimate lwr upr
grade3 == 0 1.6675 1.1742 2.1609
grade3 + grade3:node1 == 0 0.8928 0.3994 1.3862
node1 == 0 0.6577 0.1643 1.1511
node1 + grade3:node1 == 0 -0.1170 -0.6104 0.3764
grade3:node1 == 0 -0.7748 -1.4725 -0.0770
2^confint(fitGlht)$confint
Estimate lwr upr
grade3 3.1767209 2.2571225 4.4709829
grade3 + grade3:node1 1.8567602 1.3192645 2.6132428
node1 1.5775997 1.1209155 2.2203466
node1 + grade3:node1 0.9220906 0.6551634 1.2977694
grade3:node1 0.5844896 0.3604737 0.9477197
attr(,"conf.level")
[1] 0.95
attr(,"calpha")
[1] 2.698528
2^-confint(fitGlht)$confint["grade3:node1",]
Estimate lwr upr
1.710895 2.773652 1.055345
Conclusion
There is an extremely significant association between the KPNA2
expression and hystological grade in patients with unaffected as well as
in patients with affected lymph nodes (both p<<0.001). When lymph
nodes are unaffected, the expression is on average 3.18 times higher for
patients with histological grade 3 than patients with histological grade
1 (95% CI [2.26, 4.47]). For patients with affected lymph nodes the
expression is on average 1.86 times higher for patients with
histological grade 3 tumors than patients with histological grade 1
tumors (95% CI [1.32, 2.61]).
The association between the KPNA2 expression with the lymph node
status in grade 1 patients is very significant (\(p=\) 0.007).
The KPNA2 expression in histological grade 1 patients with affected
lymph nodes is on average 1.58 times higher than for grade 1 patients
with unaffected lymph nodes (95% CI [1.12, 2.22]). In grade 3 patients,
however, this association is not significant (\(p=\) 0.9, 95% CI [0.66, 1.3] ).
There is also a significant interaction between the hystological
grade and the lymph node status. So the association between the KPNA2
expression and the histological grade depends on the lymph node status
and vice versa (\(p=\) 0.026). The fold
change corresponding to histological grade is on average 1.71 times
lower in patients with affected lymph nodes as compared to patients with
unaffected lymph node (95% CI [1.06, 2.77]). (Similarly, the fold change
corresponding to the node status is on average 1.71 times lower in
patients with grade 3 tumors as compared to patients with grade 1
tumors, 95% CI [1.06, 2.77])
LS0tCnRpdGxlOiAiQnJlYXN0Y2FuY2VyIEdlbmUgRXhwcmVzc2lvbiBTdHVkeTogS1BOQTIgZ2VuZSIKYXV0aG9yOiAiTGlldmVuIENsZW1lbnQiCmRhdGU6ICJzdGF0T21pY3MsIEdoZW50IFVuaXZlcnNpdHkgKGh0dHBzOi8vc3RhdG9taWNzLmdpdGh1Yi5pbykiCm91dHB1dDoKICAgIGh0bWxfZG9jdW1lbnQ6CiAgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUgICAgCiAgICAgIHRoZW1lOiBjb3NtbwogICAgICB0b2M6IHRydWUKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBib29rZG93bjo6cGRmX2RvY3VtZW50MjoKICAgICAgdG9jOiB0cnVlCiAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXgKCi0tLQoKPGEgcmVsPSJsaWNlbnNlIiBocmVmPSJodHRwczovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMtc2EvNC4wIj48aW1nIGFsdD0iQ3JlYXRpdmUgQ29tbW9ucyBMaWNlbnNlIiBzdHlsZT0iYm9yZGVyLXdpZHRoOjAiIHNyYz0iaHR0cHM6Ly9pLmNyZWF0aXZlY29tbW9ucy5vcmcvbC9ieS1uYy1zYS80LjAvODh4MzEucG5nIiAvPjwvYT4KClRoaXMgaXMgcGFydCBvZiB0aGUgb25saW5lIGNvdXJzZSBbU3RhdGlzdGljYWwgR2Vub21pY3MgMjAyMSAoU0dBMjEpXShodHRwczovL3N0YXRvbWljcy5naXRodWIuaW8vU0dBMjEvKQoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSkKbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKIyBCYWNrZ3JvdW5kCgpIaXN0b2xvZ2ljIGdyYWRlIGluIGJyZWFzdCBjYW5jZXIgcHJvdmlkZXMgY2xpbmljYWxseSBpbXBvcnRhbnQgcHJvZ25vc3RpYyBpbmZvcm1hdGlvbi4gUmVzZWFyY2hlcnMgZXhhbWluZWQgd2hldGhlciBoaXN0b2xvZ2ljIGdyYWRlIHdhcyBhc3NvY2lhdGVkIHdpdGggZ2VuZSBleHByZXNzaW9uIHByb2ZpbGVzIG9mIGJyZWFzdCBjYW5jZXJzIGFuZCB3aGV0aGVyIHN1Y2ggcHJvZmlsZXMgY291bGQgYmUgdXNlZCB0byBpbXByb3ZlIGhpc3RvbG9naWMgZ3JhZGluZy4gSW4gdGhpcyB0dXRvcmlhbCB3ZSB3aWxsIGFzc2VzcyB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiBoaXN0b2xvZ2ljIGdyYWRlIGFuZCB0aGUgZXhwcmVzc2lvbiBvZiB0aGUgS1BOQTIgZ2VuZSB0aGF0IGlzIGtub3duIHRvIGJlIGFzc29jaWF0ZWQgd2l0aCBwb29yIEJDIHByb2dub3Npcy4KVGhlIHBhdGllbnRzLCBob3dldmVyLCBkbyBub3Qgb25seSBkaWZmZXIgaW4gdGhlIGhpc3RvbG9naWMgZ3JhZGUsIGJ1dCBhbHNvIG9uIHRoZWlyIGx5bXBoIG5vZGUgc3RhdHVzLiAKVGhlIGx5bXBoIG5vZGVzIHdlcmUgbm90IGFmZmVjdGVkICgwKSBvciBjaGlydWdpY2FsbHkgcmVtb3ZlZCAoMSkuCgoKIyBEYXRhIGFuYWx5c2lzCiMjIEltcG9ydCBLUE5BMiBkYXRhIGluIFIKYGBge3J9CmtwbmEyIDwtIHJlYWQudGFibGUoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9zdGF0T21pY3MvU0dBMjEvbWFzdGVyL2RhdGEva3BuYTIudHh0IixoZWFkZXI9VFJVRSkKa3BuYTIKYGBgCgojIyBUcmFuc2Zvcm0gdGhlIHZhcmlhYmxlIGdyYWRlIGFuZCBub2RlIHRvIGEgZmFjdG9yCmBgYHtyfQprcG5hMiRncmFkZSA8LSBhcy5mYWN0b3Ioa3BuYTIkZ3JhZGUpCmtwbmEyJG5vZGUgPC0gYXMuZmFjdG9yKGtwbmEyJG5vZGUpCmBgYAoKIyMgRGF0YSBleHBsb3JhdGlvbgpIaXN0b2xvZ2ljIGdyYWRlIGFuZCBseW1waCBub2RlIHN0YXR1cyBjYW4gYmUgYXNzb2NpYXRlZCB3aXRoIHRoZSBrcG5hMiBnZW5lIGV4cHJlc3Npb24uIE1vcmVvdmVyLCBpdCBpcyBhbHNvIHBvc3NpYmxlIHRoYXQgdGhlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFzc29jaWF0ZWQgd2l0aCBoaXN0b2xvZ2ljYWwgZ3JhZGUgaXMgZGlmZmVyZW50IGluIHBhdGllbnRzIHRoYXQgaGF2ZSB1bmFmZmVjdGVkIGx5bXBoIG5vZGVzIGFuZCBwYXRpZW50cyBmb3Igd2hpY2ggdGhlIGx5bXBoIG5vZGVzIGhhZCB0byBiZSByZW1vdmVkLiAKCmBgYHtyfQprcG5hMiAlPiUgCiAgZ2dwbG90KGFlcyh4PW5vZGU6Z3JhZGUseT1nZW5lLGZpbGw9bm9kZTpncmFkZSkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9qaXR0ZXIoKQpgYGAKClRoZSBwbG90IHN1Z2dlc3RzCgotIEFuIGVmZmVjdCBvZiB0aGUgaGlzdG9sb2dpY2FsIGdyYWRlCi0gQW4gZWZmZWN0IG9mIG5vZGUgc3RhdHVzCi0gVGhlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFzc29jaWF0ZWQgdG8gZ3JhZGUgc2VlbXMgdG8gZGlmZmVyIGFjY29yZGluZyB0byB0aGUgbHltcGggbm9kZSBzdGF0dXMgKGludGVyYWN0aW9uKSAKLSBNZWFuIHZhcmlhbmNlIHJlbGF0aW9uPwoKIyMgTW9kZWwKCkhpc3RvbG9naWMgZ3JhZGUgYW5kIGx5bXBoIG5vZGUgc3RhdHVzIGNhbiBiZSBhc3NvY2lhdGVkIHdpdGggdGhlIGtwbmEyIGdlbmUgZXhwcmVzc2lvbi4gTW9yZW92ZXIsIGl0IGlzIGFsc28gcG9zc2libGUgdGhhdCB0aGUgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYXNzb2NpYXRlZCB3aXRoIGhpc3RvbG9naWNhbCBncmFkZSBpcyBkaWZmZXJlbnQgaW4gcGF0aWVudHMgdGhhdCBoYXZlIHVuYWZmZWN0ZWQgbHltcGggbm9kZXMgYW5kIHBhdGllbnRzIGZvciB3aGljaCB0aGUgbHltcGggbm9kZXMgaGFkIHRvIGJlIHJlbW92ZWQuIEhlbmNlLCB3ZSB3aWxsIGhhdmUgdG8gbW9kZWwgdGhlIGdlbmUgZXhwcmVzc2lvbiBieSB1c2luZyBtYWluIGVmZmVjdHMgZm9yIGdyYWRlLCBub2RlIGFuZCBhIGdyYWRlIHggbm9kZSBpbnRlcmFjdGlvbi4gCiAKYGBge3J9CiNNb2RlbCB3aXRoIG1haW4gZWZmZWN0cyBmb3IgaGlzdG9sb2dpY2FsIGdyYWRlIGFuZCBub2RlIGFuZCBncmFkZSB4IG5vZGUgaW50ZXJhY3Rpb24KZml0IDwtIGxtKGdlbmV+Z3JhZGUqbm9kZSxkYXRhPWtwbmEyKQpwbG90KGZpdCkKYGBgCgpUaGUgdmFyaWFuY2Ugc2VlbXMgdG8gaW5jcmVhc2Ugd2l0aCB0aGUgbWVhbi4gClRoZSBRUS1wbG90IG9mIHRoZSByZXNpZHVhbHMgc2hvd3MgZGV2aWF0aW9ucyBmcm9tIG5vcm1hbGl0eSBvciBzb21lIG91dGxpZXJzLgoKV2Ugd2lsbCBmaXJzdCBsb2cgdHJhbnNmb3JtIHRoZSBkYXRhLgoKCmBgYHtyfQpmaXQgPC0gbG0oZ2VuZSAlPiUgbG9nMn5ncmFkZSpub2RlLGRhdGE9a3BuYTIpCnBsb3QoZml0KQpgYGAKCi0gVGhlIHZhcmlhbmNlIGlzIG5vdyBtb3JlIG9yIGxlc3MgZXF1YWwgZm9yIGV2ZXJ5IHRyZWF0bWVudCB4IG5vZGUgY29tYmluYXRpb24uIAotIFRoZSBRUS1wbG90IG9mIHRoZSByZXNpZHVhbHMgc2hvd3Mgbm8gZGV2aWF0aW9ucyBmcm9tIG5vcm1hbGl0eS4KCgpgYGB7cn0KbGlicmFyeShjYXIpCkFub3ZhKGZpdCx0eXBlPSJJSUkiKQpgYGAKClRoZSBvdXRwdXQgc2hvd3MgdGhhdCB0aGVyZSBpcyBhIHZlcnkgc2lnbmlmaWNhbnQgaW50ZXJhY3Rpb24gKCRwPSQgYHIgZm9ybWF0KEFub3ZhKGZpdCx0eXBlPSJJSUkiKVsiZ3JhZGU6bm9kZSIsNF0sZGlnaXRzPTIpYCkuIEhlbmNlLCB0aGUgYXNzb2NpYXRpb24gb2YgdGhlIGhpc3RvbG9naWNhbCBncmFkZSBvbiB0aGUgZ2VuZSBleHByZXNzaW9uIGRpZmZlcnMgYWNjb3JkaW5nIHRvIHRoZSBseW1waCBub2RlIHN0YXR1cyBhbmQgdmljZSB2ZXJzYS4KCgpUaGUgcmVzZWFyY2hlcnMgYXJlIHRoZXJlZm9yZSBpbnRlcmVzdGVkIGluIHN0dWR5aW5nIGFuZCByZXBvcnRpbmcgb24gdGhlIGZvbGxvd2luZyBoeXBvdGhlc2VzOgoKLSBJcyB0aGUgS1BOQTIgZXhwcmVzc2lvbiBvbiBhdmVyYWdlIGRpZmZlcmVudCBiZXR3ZWVuIGdyYWRlIDMgYW5kIGdyYWRlIDEgdHVtb3JzIGZyb20gcGF0aWVudHMgd2l0aCB1bmFmZmVjdGVkIGx5bXBoIG5vZGVzIChieSB0ZXN0aW5nICRIXzA6IFxsb2dfMntGQ31fe2czbjAtZzFuMH09MFx0ZXh0eyB2cyB9SDE6IFxsb2dfMntGQ31fe2czbjAtZzFuMH1cbmVxIDAkKQotIElzIHRoZSBLUE5BMiBleHByZXNzaW9uIG9uIGF2ZXJhZ2UgZGlmZmVyZW50IGJldHdlZW4gZ3JhZGUgMyBhbmQgZ3JhZGUgMSB0dW1vcnMgZnJvbSBwYXRpZW50cyB3aXRoIGFmZmVjdGVkIGx5bXBoIG5vZGVzIChieSB0ZXN0aW5nICRIXzA6IFxsb2dfMntGQ31fe2czbjEtZzFuMX09MFx0ZXh0eyB2cyB9SDE6IFxsb2dfMntGQ31fe2czbjEtZzFuMX1cbmVxIDAkKQoKLSBJcyB0aGUgS1BOQTIgZXhwcmVzc2lvbiBvbiBhdmVyYWdlIGRpZmZlcmVudCBpbiBncmFkZSAxIHR1bW9ycyBvZiBwYXRpZW50cyB3aXRoIGFmZmVjdGVkIGFuZCBwYXRpZW50cyB3aXRoIHVuYWZmZWN0ZWQgbHltcGggbm9kZXMgKGJ5IHRlc3RpbmcgJEhfMDogXGxvZ18ye0ZDfV97ZzFuMS1nMW4wfT0wXHRleHR7IHZzIH1IMTogXGxvZ18ye0ZDfV97ZzFuMS1nMW4wfVxuZXEgMCQpCgotIElzIHRoZSBLUE5BMiBleHByZXNzaW9uIG9uIGF2ZXJhZ2UgZGlmZmVyZW50IGluIGdyYWRlIDMgdHVtb3JzIG9mIHBhdGllbnRzIHdpdGggYWZmZWN0ZWQgYW5kIHBhdGllbnRzIHdpdGggdW5hZmZlY3RlZCBseW1waCBub2RlcyAoYnkgdGVzdGluZyAkSF8wOiBcbG9nXzJ7RkN9X3tnM24xLWczbjB9PTBcdGV4dHsgdnMgfUgxOiBcbG9nXzJ7RkN9X3tnM24xLWczbjB9XG5lcSAwJCkKCi0gSXMgdGhlIGZvbGQgY2hhbmdlIG9mIHRoZSBLUE5BMiBnZW5lIGJldHdlZW4gZ3JhZGUgMyBhbmQgZ3JhZGUgMSBkaWZmZXJlbnQgYWNjb3JkaW5nIHRvIHRoZSBseW1waCBub2RlIHN0YXR1cyBhbmQgdmljZSB2ZXJzYSAodGVzdGVkIGFscmVhZHkgYnkgYXNzZXNzaW5nIHRoZSBpbnRlcmFjdGlvbjogJEhfMDogXGxvZ18ye0ZDfV97ZzNuMC1nMW4wfT1cbG9nXzJ7RkN9X3tnM24xLWcxbjF9IFx0ZXh0eyB2cyB9SDE6XGxvZ18ye0ZDfV97ZzNuMC1nMW4wfVxuZXFcbG9nXzJ7RkN9X3tnM24xLWcxbjF9JCkuCgoKCiMgSW50ZXJwcmV0YXRpb24gb2YgbW9kZWwgcGFyYW1ldGVycyBhbmQgc3RhdGlzdGljYWwgdGVzdHMKCmBgYHtyfQpFeHBsb3JlTW9kZWxNYXRyaXg6OlZpc3VhbGl6ZURlc2lnbihrcG5hMix+Z3JhZGUqbm9kZSkkcGxvdGxpc3QKYGBgCgoKYGBge3J9CnN1bW1hcnkoZml0KQojQ2FsY3VsYXRlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciBwYXJhbWV0ZXJzIG9mIG1vZGVsCkNJZml0IDwtIGNvbmZpbnQoZml0KQojbG9nXzIgRkMgYmV0d2VlbiBnM24wLWcxbjAsIGcxbjEtZzFuMAojYW5kIGxvZ18yIGRpZmZlcmVuY2UgaW4gRkMgZzNuMS1nMW4xIGFuZCBGQyBnM24wLWcxbjAKQ0lmaXQKI1RyYW5zZm9ybSBwYXJhbWV0ZXJzIGFuZCB0aGUgQ0kgYmFjayB0byB0aGUgb3JpZ2luYWwgc2NhbGUKMl5maXQkY29lZgoyXkNJZml0CjJeLWZpdCRjb2VmWyJncmFkZTM6bm9kZTEiXQoyXi1DSWZpdFsiZ3JhZGUzOm5vZGUxIixdCmBgYAoKV2UgbW9kZWwgdGhlIGxvZyRfMiQtdHJhbnNmb3JtZWQgaW50ZW5zaXRpZXMgd2l0aCB0aGUgZm9sbG93aW5nIG1vZGVsOiAKJCQKeT1cYmV0YV8wK1xiZXRhX3tnM314X3tnM30rXGJldGFfe24xfXhfe24xfStcYmV0YV97ZzNuMX14X3tnM314X3tuMX0sCiQkCgp3aXRoICRcYmV0YV8wJCB0aGUgaW50ZXJjZXB0LCAkXGJldGFfe2czfSQgdGhlIG1haW4gZWZmZWN0IGZvciBncmFkZSwgJHhfe2czfSQgYSBkdW1teSB2YXJpYWJsZSBmb3IgZ3JhZGUgd2hpY2ggaXMgMCBmb3IgdGhlIGNvbnRyb2wgdHJlYXRtZW50IGluIHRoZSBhYnNlbmNlIG9mIGdyYWRlIGFuZCAxIGZvciB0aGUgdHJlYXRtZW50IHdpdGggZ3JhZGUsICRcYmV0YV97bjF9JCB0aGUgbWFpbiBlZmZlY3QgZm9yIG5vZGUsICR4X3tuMX0kIGEgZHVtbXkgdmFyaWFibGUgdGhhdCBpcyAwIGZvciB0aGUgbWVhc3VyZW1lbnRzIG9mIHBhdGllbnRzIHdpdGggdW5hZmZlY3RlZCBseW1waCBub2RlcyBhbmQgMSBmb3IgcGF0aWVudHMgZm9yIHdoaWNoIHRoZSBseW1waCBub2RlcyB3ZXJlIHJlbW92ZWQgYW5kICRcYmV0YV97ZzNuMX0kIHRoZSBpbnRlcmFjdGlvbiBlZmZlY3QgYmV0d2VlbiBncmFkZSBhbmQgbm9kZS4gClRvIGVhc2UgdGhlIGludGVycHJldGF0aW9uIG9mIHRoZSBwYXJhbWV0ZXJzLCAkXGxvZ18yJCB0cmFuc2Zvcm1lZCBnZW9tZXRyaWMgbWVhbiBpbnRlbnNpdGllcyBhcmUgZ2l2ZW4gZm9yIGVhY2ggdHJlYXRtZW50IGdyb3VwIGFzIHdlbGwgYXMgY29ycmVzcG9uZGluZyBjb250cmFzdHMgYmV0d2VlbiB0cmVhdG1lbnRzLCB3aGljaCBoYXZlIGFuIGludGVycHJldGF0aW9uIGluIHRlcm1zIG9mICRcbG9nXzIkIHRyYW5zZm9ybWVkIGZvbGQgY2hhbmdlcyAoRkMpLiAKCi0gJFxsb2dfMlxoYXR7XG11fV97ZzFuMH09XGhhdFxiZXRhXzAkLCAkXGxvZ18yIFxoYXR7XG11fV97ZzNuMH09XGhhdFxiZXRhXzArXGhhdFxiZXRhX3tnM30kIC0tPiAkXGxvZ18yIFx3aWRlaGF0e0ZDfV97ZzNuMC1nMW4wfT1caGF0XGJldGFfe2czfSQKCi0gJFxsb2dfMiBcaGF0e1xtdX1fe2cxbjF9PVxoYXRcYmV0YV8wK1xoYXRcYmV0YV97bjF9JCwgJFxsb2dfMiBcaGF0IHtcbXV9X3tnM24xfT1caGF0XGJldGFfMCtcaGF0XGJldGFfe2czfStcaGF0XGJldGFfe24xfStcaGF0XGJldGFfe2czbjF9JCAtLT4gJFxsb2dfMiBcd2lkZWhhdHtGQ31fe2czbjEtZzFuMX09XGhhdCBcYmV0YV97ZzN9ICtcaGF0XGJldGFfe2czbjF9JAoKLSBTaW1pbGFybHksICRcbG9nXzIgXHdpZGVoYXR7RkN9X3tnMW4xLWcxbjB9PVxoYXRcYmV0YV97bjF9JCwgJFxsb2dfMiBcd2lkZWhhdHtGQ31fe2czbjEtZzNuMH09XGhhdFxiZXRhX3tuMX0rXGhhdFxiZXRhX3tnM24xfSQgCgotICRcbG9nXzJcZnJhY3tcd2lkZWhhdHtGQ31fe2czbjEtZzFuMX19e1x3aWRlaGF0e0ZDfV97ZzNuMC1nMW4wfX09XGxvZ18yXGZyYWN7XHdpZGVoYXR7RkN9X3tnM24xLWczbjB9fXtcd2lkZWhhdHtGQ31fe2cxbjEtZzFuMH19PVxoYXRcYmV0YV97ZzNuMX0kCgp3aXRoICRcbG9nXzJcaGF0e1xtdX1fe2cxbjB9JCwgJFxsb2dfMlxoYXR7XG11fV97ZzNuMH0kLCAkXGxvZ18yXGhhdCB7XG11fV97ZzFuMX0kIGFuZCAkXGxvZ18yXGhhdHtcbXV9X3tnM24xfSQgdGhlIGVzdGltYXRlZCBtZWFuICRcbG9nXzIkIHRyYW5zZm9ybWVkIGludGVuc2l0eSBmb3IgcGF0aWVudHMgd2l0aCBncmFkZSAxIGFuZCBub2RlIDAgc3RhdHVzLCBncmFkZSAzIGFuZCBub2RlIDAgc3RhdHVzLCBncmFkZSAxIGFuZCBub2RlIDEgc3RhdHVzIGFuZCBncmFkZSAzIGFuZCBub2RlIDEgc3RhdHVzLCByZXNwZWN0aXZlbHkuIFdpdGggJFxsb2dfMiBcd2lkZWhhdHtGQ31fe2ItYX0kIHdlIGluZGljYXRlICRcbG9nXzIkIHRyYW5zZm9ybWVkIGZvbGQgY2hhbmdlIGVzdGltYXRlcyBiZXR3ZWVuIHRyZWF0bWVudCBiIGFuZCB0cmVhdG1lbnQgYSwgaS5lLiAkXGxvZ18yIFx3aWRlaGF0e0ZDfV97Yi1hfT1cbG9nXzIgXGhhdHtcbXV9X3tifS1cbG9nXzIgXGhhdHtcbXV9X2E9XGxvZ18yIFxmcmFje1xoYXR7XG11fV97Yn19e1xoYXR7XG11fV97YX19JC4KClRoZSBtb2RlbCBpbW1lZGlhdGVseSBwcm92aWRlcyBzdGF0aXN0aWNhbCB0ZXN0cyBmb3IgYXNzZXNzaW5nIHRoZSBzaWduaWZpY2FuY2Ugb2YgZm9sZCBjaGFuZ2VzIGJldHdlZW4gZ3JhZGUgMyBhbmQgZ3JhZGUgMSBmb3IgcGF0aWVudHMgd2l0aCB1bmFmZmVjdGVkIGx5bXBoIG5vZGVzIChuPTApICRcbG9nXzIge0ZDfV97ZzNuMC1nMW4wfSQsICBmb2xkIGNoYW5nZXMgYmV0d2VlbiB0aGUgZ3JhZGUgMS1ub2RlIDEgcGF0aWVudHMgYW5kIGdyYWRlIDEtIG5vZGUgMCBwYXRpZW50cyAkXGxvZ18yIHtGQ31fe2cxbjEtZzNuMH0kIGFuZCBmb3IgZGlmZmVyZW5jZXMgaW4gZm9sZCBjaGFuZ2UgcmVsYXRlZCB0byBoaXN0b2xvZ2ljYWwgZ3JhZGUgZm9yIG5vZGUgMSBwYXRpZW50cyBhbmQgbm9kZSAwIHBhdGllbnRzLiAkXGxvZ18yXGZyYWN7e0ZDfV97ZzNuMS1nMW4xfX17e0ZDfV97ZzNuMC1nMW4wfX0kLCB0aGUgaW50ZXJhY3Rpb24gdGVybS4gCgpJbnRlcnByZXRhdGlvbiBvZiB0aGUgbW9kZWwgcGFyYW1ldGVycyBpbiB0aGUgbW9kZWwgb3V0cHV0OgoKLSBUaGUgZ2VvbWV0cmljIG1lYW4gaW50ZW5zaXR5IGZvciBncmFkZSAxIHBhdGllbnRzIHdpdGggdW5hZmZlY3RlZCBseW1waCBub2RlcyBlcXVhbHMgJFxleHAoXGhhdCBcYmV0YV8wKSQ9CmByIHJvdW5kKDJeZml0JGNvZWZbIihJbnRlcmNlcHQpIl0sMilgLgoJLSBXaGVuIGx5bXBoIG5vZGVzIGFyZSB1bmFmZmVjdGVkLCB0aGUgZXhwcmVzc2lvbiBpcyBvbiBhdmVyYWdlIGByIHJvdW5kKDJeZml0JGNvZWZbImdyYWRlMyJdLDIpYCB0aW1lcyBoaWdoZXIgZm9yIHBhdGllbnRzIHdpdGggaGlzdG9sb2dpY2FsIGdyYWRlIDMgdGhhbiBwYXRpZW50cyB3aXRoIGhpc3RvbG9naWNhbCBncmFkZSAxLiAKCS0gVGhlIGdlbmUgZXhwcmVzc2lvbiBpbiBoaXN0b2xvZ2ljYWwgZ3JhZGUgMSBwYXRpZW50cyB3aXRoIGFmZmVjdGVkIGx5bXBoIG5vZGVzIGlzIG9uIGF2ZXJhZ2UgYHIgcm91bmQoMl5maXQkY29lZlsibm9kZTEiXSwyKWAgdGltZXMgaGlnaGVyIHRoYW4gZm9yIGdyYWRlIDEgcGF0aWVudHMgd2l0aCB1bmFmZmVjdGVkIGx5bXBoIG5vZGVzLgotIFRoZSBmb2xkIGNoYW5nZSBjb3JyZXNwb25kaW5nIHRvIGhpc3RvbG9naWNhbCBncmFkZSBpcyBvbiBhdmVyYWdlIGByIHJvdW5kKDEvMl5maXQkY29lZlsiZ3JhZGUzOm5vZGUxIl0sMilgIHRpbWVzIGxvd2VyIGluIHBhdGllbnRzIHdpdGggYWZmZWN0ZWQgbHltcGggbm9kZXMgYXMgY29tcGFyZWQgdG8gcGF0aWVudHMgd2l0aCB1bmFmZmVjdGVkIGx5bXBoIG5vZGUuCgoKRm9yIHRoZSByZW1haW5pbmcgaHlwb3RoZXNpcyBvZiBpbnRlcmVzdCB3ZSB3aWxsIGhhdmUgdG8gZGVmaW5lIGNvbnRyYXN0czogbGluZWFyIGNvbWJpbmF0aW9ucyBvZiB0aGUgbW9kZWwgcGFyYW1ldGVycyBhbmQgZXZhbHVhdGUgdGhlIGNvbnRyYXN0cyB3aXRoIHRoZSBtdWx0Y29tcCBwYWNrYWdlLgoKVGhlIEYtdGVzdCBzaG93ZWQgYW4gZXh0cmVtZWx5IHNpZ25pZmljYW50IGFzc29jaWF0aW9uIG9mIHRoZSBub2RlIHN0YXR1cywgaHlzdG9sb2dpY2FsIGdyYWRlIGFuZC9vciB0aGUgaW50ZXJhY3Rpb24gYmV0d2VlbiB0aGUgbm9kZSBzdGF0dXMgYW5kIHRoZSBncmFkZSAocDw8MC4wMDEpLiAKCiMgQXNzZXNzaW5nIHRoZSBzaWduaWZpY2FuY2Ugb2YgYWxsIGh5cG90aGVzaXMgb2YgaW50ZXJlc3QKV2UgY2FuIGFzc2VzcyBhbGwgY29udHJhc3RzIG9mIGludGVyZXN0IHVzaW5nIHRoZSBtdWx0Y29tcCBwYWNrYWdlLiBUaGlzIHdpbGwgYWxzbyBhbGxvdyB1cyB0byBjb3JyZWN0IGZvciBtdWx0aXBsZSB0ZXN0aW5nLCBzaW5jZSB3ZSBhc3Nlc3MgbXVsdGlwbGUgaHlwb3RoZXNlcyB0byBhbnN3ZXIgdGhlIHJlbGV2YW50IHJlc2VhcmNoIHF1ZXN0aW9uLgoKCi0gJEhfMDogXGxvZ18ye0ZDfV97ZzNuMC1nMW4wfT0gXGJldGFfe2czfT0wJCAkXHJpZ2h0YXJyb3ckICJncmFkZTMgPSAwIgotICRIXzA6IFxsb2dfMntGQ31fe2czbjEtZzFuMX09IFxiZXRhX3tnM30gKyBcaGF0XGJldGFfe2czbjF9PTAkICRccmlnaHRhcnJvdyQgImdyYWRlMytncmFkZTM6bm9kZTEgPSAwIgotICRIXzA6IFxsb2dfMntGQ31fe2cxbjEtZzFuMH09IFxiZXRhX3tuMX0kICAkXHJpZ2h0YXJyb3ckICJub2RlMSA9IDAiCi0gJEhfMDogXGxvZ18ye0ZDfV97ZzNuMS1nM24wfT0gXGJldGFfe24xfSArIFxoYXRcYmV0YV97ZzNuMX09MCQgJFxyaWdodGFycm93JCAibm9kZTErZ3JhZGUzOm5vZGUxID0gMCIKLSAkSF8wOiBcbG9nXzJ7RkN9X3tnM24xLWcxbjF9IC0gXGxvZ18ye0ZDfV97ZzNuMC1nMW4wfSA9IFxoYXRcYmV0YV97ZzNuMX09MCQsIG5vdGUgdGhhdCB0aGUgbGF0dGVyIGh5cG90aGVzaXMgaXMgYWxzbyBlcXVpdmFsZW50IHRvICRIXzA6IFxsb2dfMntGQ31fe2czbjEtZzNuMH0gLSBcbG9nXzJ7RkN9X3tnMW4xLWcxbjB9ID0gXGhhdFxiZXRhX3tnM24xfT0wJCAkXHJpZ2h0YXJyb3ckICJncmFkZTM6bm9kZTEgPSAwIgoKYGBge3J9CmxpYnJhcnkobXVsdGNvbXApCmZpdEdsaHQ8LSBnbGh0KGZpdCwgbGluZmN0ID0gYygiZ3JhZGUzID0gMCIsImdyYWRlMytncmFkZTM6bm9kZTEgPSAwIiwibm9kZTEgPSAwIiwibm9kZTErZ3JhZGUzOm5vZGUxID0gMCIsImdyYWRlMzpub2RlMSA9IDAiKSkKc3VtbWFyeShmaXRHbGh0KQpjb25maW50KGZpdEdsaHQpCjJeY29uZmludChmaXRHbGh0KSRjb25maW50CjJeLWNvbmZpbnQoZml0R2xodCkkY29uZmludFsiZ3JhZGUzOm5vZGUxIixdCmBgYAoKIyBDb25jbHVzaW9uCgotIFRoZXJlIGlzIGFuIGV4dHJlbWVseSBzaWduaWZpY2FudCBhc3NvY2lhdGlvbiBiZXR3ZWVuIHRoZSBLUE5BMiBleHByZXNzaW9uIGFuZCBoeXN0b2xvZ2ljYWwgZ3JhZGUgaW4gcGF0aWVudHMgd2l0aCB1bmFmZmVjdGVkIGFzIHdlbGwgYXMgaW4gcGF0aWVudHMgd2l0aCBhZmZlY3RlZCBseW1waCBub2RlcyAoYm90aCBwPDwwLjAwMSkuIAogIFdoZW4gbHltcGggbm9kZXMgYXJlIHVuYWZmZWN0ZWQsIHRoZSBleHByZXNzaW9uIGlzIG9uIGF2ZXJhZ2UgYHIgcm91bmQoMl5jb25maW50KGZpdEdsaHQpJGNvbmZpbnRbImdyYWRlMyIsMV0sMilgIHRpbWVzIGhpZ2hlciBmb3IgcGF0aWVudHMgd2l0aCBoaXN0b2xvZ2ljYWwgZ3JhZGUgMyB0aGFuIHBhdGllbnRzIHdpdGggaGlzdG9sb2dpY2FsIGdyYWRlIDEgKDk1JSBDSSBbYHIgcm91bmQoMl5jb25maW50KGZpdEdsaHQpJGNvbmZpbnRbImdyYWRlMyIsMjozXSwyKWBdKS4gCiAgRm9yIHBhdGllbnRzIHdpdGggYWZmZWN0ZWQgbHltcGggbm9kZXMgdGhlIGV4cHJlc3Npb24gaXMgb24gYXZlcmFnZSBgciByb3VuZCgyXmNvbmZpbnQoZml0R2xodCkkY29uZmludFsiZ3JhZGUzICsgZ3JhZGUzOm5vZGUxIiwxXSwyKWAgdGltZXMgaGlnaGVyIGZvciBwYXRpZW50cyB3aXRoIGhpc3RvbG9naWNhbCBncmFkZSAzIHR1bW9ycyB0aGFuIHBhdGllbnRzIHdpdGggaGlzdG9sb2dpY2FsIGdyYWRlIDEgdHVtb3JzICg5NSUgQ0kgW2ByIHJvdW5kKDJeY29uZmludChmaXRHbGh0KSRjb25maW50WyJncmFkZTMgKyBncmFkZTM6bm9kZTEiLDI6M10sMilgXSkuIAoKLSBUaGUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgS1BOQTIgZXhwcmVzc2lvbiB3aXRoIHRoZSBseW1waCBub2RlIHN0YXR1cyBpbiBncmFkZSAxIHBhdGllbnRzIGlzIHZlcnkgc2lnbmlmaWNhbnQgKCRwPSQgYHIgZm9ybWF0KHN1bW1hcnkoZml0R2xodCkkdGVzdCRwdmFsdWVzWzNdLGRpZ2l0cz0yKWApLiAgClRoZSBLUE5BMiBleHByZXNzaW9uIGluIGhpc3RvbG9naWNhbCBncmFkZSAxIHBhdGllbnRzIHdpdGggYWZmZWN0ZWQgbHltcGggbm9kZXMgaXMgb24gYXZlcmFnZSBgciByb3VuZCgyXmNvbmZpbnQoZml0R2xodCkkY29uZmludFsibm9kZTEiLDFdLDIpYCB0aW1lcyBoaWdoZXIgdGhhbiBmb3IgZ3JhZGUgMSBwYXRpZW50cyB3aXRoIHVuYWZmZWN0ZWQgbHltcGggbm9kZXMgKDk1JSBDSSBbYHIgcm91bmQoMl5jb25maW50KGZpdEdsaHQpJGNvbmZpbnRbIm5vZGUxIiwyOjNdLDIpYF0pLiAKSW4gZ3JhZGUgMyBwYXRpZW50cywgaG93ZXZlciwgdGhpcyBhc3NvY2lhdGlvbiBpcyBub3Qgc2lnbmlmaWNhbnQgKCRwPSQgYHIgZm9ybWF0KHN1bW1hcnkoZml0R2xodCkkdGVzdCRwdmFsdWVzWzRdLGRpZ2l0cz0yKWAsIDk1JSBDSSBbYHIgcm91bmQoMl5jb25maW50KGZpdEdsaHQpJGNvbmZpbnRbIm5vZGUxICsgZ3JhZGUzOm5vZGUxIiwyOjNdLDIpYF0gKS4KCi0gVGhlcmUgaXMgYWxzbyBhIHNpZ25pZmljYW50IGludGVyYWN0aW9uIGJldHdlZW4gdGhlIGh5c3RvbG9naWNhbCBncmFkZSBhbmQgdGhlIGx5bXBoIG5vZGUgc3RhdHVzLiBTbyB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgS1BOQTIgZXhwcmVzc2lvbiBhbmQgdGhlIGhpc3RvbG9naWNhbCBncmFkZSBkZXBlbmRzIG9uIHRoZSBseW1waCBub2RlIHN0YXR1cyBhbmQgdmljZSB2ZXJzYSAoJHA9JCBgciBmb3JtYXQoc3VtbWFyeShmaXRHbGh0KSR0ZXN0JHB2YWx1ZXNbNV0sZGlnaXRzPTIpYCkuIFRoZSBmb2xkIGNoYW5nZSBjb3JyZXNwb25kaW5nIHRvIGhpc3RvbG9naWNhbCBncmFkZSBpcyBvbiBhdmVyYWdlIGByIHJvdW5kKDEvMl5jb25maW50KGZpdEdsaHQpJGNvbmZpbnRbImdyYWRlMzpub2RlMSIsMV0sMilgIHRpbWVzIGxvd2VyIGluIHBhdGllbnRzIHdpdGggYWZmZWN0ZWQgbHltcGggbm9kZXMgYXMgY29tcGFyZWQgdG8gcGF0aWVudHMgd2l0aCB1bmFmZmVjdGVkIGx5bXBoIG5vZGUgKDk1JSBDSSBbYHIgcm91bmQoMS8yXmNvbmZpbnQoZml0R2xodCkkY29uZmludFsiZ3JhZGUzOm5vZGUxIiwzOjJdLDIpYF0pLiAoU2ltaWxhcmx5LCB0aGUgZm9sZCBjaGFuZ2UgY29ycmVzcG9uZGluZyB0byB0aGUgbm9kZSBzdGF0dXMgaXMgb24gYXZlcmFnZSBgciByb3VuZCgxLzJeY29uZmludChmaXRHbGh0KSRjb25maW50WyJncmFkZTM6bm9kZTEiLDFdLDIpYCB0aW1lcyBsb3dlciBpbiBwYXRpZW50cyB3aXRoIGdyYWRlIDMgdHVtb3JzIGFzIGNvbXBhcmVkIHRvIHBhdGllbnRzIHdpdGggZ3JhZGUgMSB0dW1vcnMsIDk1JSBDSSBbYHIgcm91bmQoMS8yXmNvbmZpbnQoZml0R2xodCkkY29uZmludFsiZ3JhZGUzOm5vZGUxIiwzOjJdLDIpYF0pCgo=