Loading packages
We start by loading the required packages. If they are not already
installed, then the code below will first install them, before loading
them. The package faux
is not available on CRAN for R
version 4.4.2, hence we will install it via github. See details here
requiredPackages = c('tidyverse', 'knitr', 'lme4', 'ggstats', 'ggstatsplot', 'sjPlot', 'paletteer', 'lattice', 'car')
for(p in requiredPackages){
if(!require(p,character.only = TRUE)) install.packages(p, dependencies = TRUE)
library(p,character.only = TRUE)
}
Specific to the faux
package
First install the package devtools, and then install the package
faux
via the github install.
# install.packages("devtools")
# devtools::install_github("debruine/faux")
library(faux)
Data set
Our experiment has the following structure: we asked 40 subjects to
respond to 40 items in a fully crossed design. There were two IVs:
Condition with congruent
and incongruent
and
Age with young
and old
. The Condition is a
within subject variable; age is a between subject. However, Condition
and Age were both within item variables. The dependant variable was
LookingTime.
This meant that we used items within each of the young
and the old
subjects in addition to items within each of
the congurent
and incongruent
conditions.
Our research question is as follows: Age
of subject will
impact the Looking Time
in the two conditions. Our
hypothesis is: The older a subject is, the more the looking time it is
to the incongruent condition.
We will use the package faux
to simulate a dataframe.
This step is crucial in assessing contributions of particular predictors
and for testing ideas as we already know the distribution of the data
and what to expect as an outcome when it comes to the fixed effect in
question.
The simulated data has the following parameters
set.seed(42)
# define parameters
Subj_n = 40 # number of subjects
Item_n = 40 # number of items
b0 = 100 # intercept
b1 = 2.5 * b0 # fixed effect of condition
u0s_sd = 300 # random intercept SD for subjects
u0i_sd = 200 # random intercept SD for items
u1s_sd = 100 # random b1 slope SD for subjects
u1i_sd = 50 # random b1 slope SD for items
r01s = -0.3 # correlation between random effects 0 and 1 for subjects
r01i = 0.2 # correlation between random effects 0 and 1 for items
sigma_sd = 150 # error SD
# set up data structure
dataCong <- add_random(Subj = Subj_n, Item = Item_n) %>%
# add within categorical variable for subject
add_within("Subj", Cond = c("Congruent", "Incongruent")) %>%
add_recode("Cond", "Cond.Incongruent", Congruent = 0, Incongruent = 1) %>%
# add between categorical variable for subject
add_between("Subj", Age = c("Young", "Old")) %>%
add_recode("Age", "Age.Old", Young = 0, Old = 1) %>%
# add random effects
add_ranef("Subj", u0s = u0s_sd, u1s = u1s_sd, .cors = r01s) %>%
add_ranef("Item", u0i = u0i_sd, u1i = u1i_sd, .cors = r01i) %>%
##add_ranef(c("Subj", "Item"), u0si = u0s_sd + u0i_sd) %>%
##add_ranef(c("Subj", "Item"), u1si = u1s_sd + u1i_sd) %>%
add_ranef(sigma = sigma_sd) %>%
# calculate DV
mutate(LookingTime = b0 + b1 + u0s + u0i + #u0si + u1si +
(((b1 + u1s) + 0.5) * Cond.Incongruent) + (((b1 + u1s) + 0.9) * Age.Old) + # subject specific variation
(((b1 + u1i) - 0.3) * Cond.Incongruent) + (((b1 + u1i) - 0.25) * Age.Old) + # item specific variation
sigma)
write.csv(dataCong, "dataCong.csv")
If you were not able to install the faux
package, simply
uncomment the following line of code below to import the dataset
#dataCong <- read.csv("dataCong.csv")[-1]
Verify dataframe
Tibble
dataCong <- dataCong %>%
mutate(Subj = factor(Subj),
Item = factor(Item))
dataCong
Counts
Subjects
dataCong %>%
group_by(Cond, Age, Subj) %>%
summarise(count = n())
Items
Age
dataCong %>%
group_by(Age, Item) %>%
summarise(count = n())
Cond
dataCong %>%
group_by(Cond, Item) %>%
summarise(count = n())
Visualisations
Condition by Age
The figure below confirms this, where we see an increase in
LookingTime in the incongruent
condition and oevrall,
older
participants show an increase in LookingTime
dataCong %>%
ggplot(aes(x = Cond,
y = LookingTime,
colour = Age)) +
theme_bw() +
geom_boxplot() +
geom_smooth(aes(as.numeric(Cond)), method = "lm")

Subject by
Condition
This figure shows that subjects are variable in how they responded to
this task
dataCong %>%
ggplot(aes(x = Cond,
y = LookingTime,
colour = Subj)) +
theme_bw() +
geom_point() +
geom_smooth(aes(as.numeric(Cond)), method = "lm", se = FALSE) +
scale_colour_manual(values = paletteer_c("grDevices::rainbow", length(unique(dataCong$Subj))))

Subject by Age
This figure shows that subjects had an impact on the LookingTime in
both age groups, simply due to their variable responses to the different
items
dataCong %>%
ggplot(aes(x = Age,
y = LookingTime,
colour = Subj)) +
theme_bw() +
geom_point() +
geom_smooth(aes(as.numeric(Cond)), method = "lm", se = FALSE) +
scale_colour_manual(values = paletteer_c("grDevices::rainbow", length(unique(dataCong$Subj))))

Item by
Condition
This figure shows that items had an impact on the LookingTime in both
conditions
dataCong %>%
ggplot(aes(x = Cond,
y = LookingTime,
colour = Item)) +
theme_bw() +
geom_point() +
geom_smooth(aes(as.numeric(Cond)), method = "lm", se = FALSE) +
scale_colour_manual(values = paletteer_c("grDevices::rainbow", length(unique(dataCong$Item))))

Subject by Age
This figure shows that items had an impact on the LookingTime in both
age groups
dataCong %>%
ggplot(aes(x = Age,
y = LookingTime,
colour = Item)) +
theme_bw() +
geom_point() +
geom_smooth(aes(as.numeric(Cond)), method = "lm", se = FALSE) +
scale_colour_manual(values = paletteer_c("grDevices::rainbow", length(unique(dataCong$Item))))

Modelling strategy
We use an LMER model with a crossed random effect. To choose our
optimal model, we start first by a simple model with only random
intercepts, increasing complexity by accounting for random slopes for
both subjects and items. It is clear from our visualisation above, that
there is no interaction between the two predictors. However, for
demonstration purposes, we do test for this
Simple Linear
Model
mdl.lm <- dataCong %>%
lm(LookingTime ~ Cond + Age, data = .)
summary(mdl.lm)
Call:
lm(formula = LookingTime ~ Cond + Age, data = .)
Residuals:
Min 1Q Median 3Q Max
-1215.59 -290.17 -21.78 264.89 1661.41
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 304.95 12.91 23.61 <2e-16 ***
CondIncongruent 504.35 14.91 33.82 <2e-16 ***
AgeOld 566.44 14.91 37.98 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 421.8 on 3197 degrees of freedom
Multiple R-squared: 0.4472, Adjusted R-squared: 0.4469
F-statistic: 1293 on 2 and 3197 DF, p-value: < 2.2e-16

qqnorm(residuals(mdl.lm)); qqline(residuals(mdl.lm))

plot(fitted(mdl.lm), residuals(mdl.lm), cex = 4)

No interaction
Crossed random
intercepts
xmdl.rand.Interc <- dataCong %>%
lmer(LookingTime ~ Cond + Age +
(1 | Subj) +
(1 | Item), data = ., REML = FALSE,
control = lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e5)))
Crossed random
intercepts + By-speaker random slopes
xmdl.rand.Slope1 <- dataCong %>%
lmer(LookingTime ~ Cond + Age +
(1 + Cond | Subj) +
(1 | Item), data = ., REML = FALSE,
control = lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e5)))
Crossed random
intercepts + By-speaker and by-item random slopes
xmdl.rand.Slope2 <- dataCong %>%
lmer(LookingTime ~ Cond + Age +
(1 + Cond | Subj) +
(1 + Cond | Item), data = ., REML = FALSE,
control = lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e5)))
Crossed random
intercepts + By-speaker and by-item random slopes
xmdl.rand.Slope3 <- dataCong %>%
lmer(LookingTime ~ Cond + Age +
(1 + Cond | Subj) +
(1 + Cond + Age| Item), data = ., REML = FALSE,
control = lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e5)))
With interaction
Crossed random
intercepts + Interaction
xmdl.rand.Interc.Int <- dataCong %>%
lmer(LookingTime ~ Cond * Age +
(1 | Subj) +
(1 | Item), data = ., REML = FALSE,
control = lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e5)))
Crossed random
intercepts + By-speaker random slopes + Interaction
xmdl.rand.Slope1.Int <- dataCong %>%
lmer(LookingTime ~ Cond * Age +
(1 + Cond | Subj) +
(1 | Item), data = ., REML = FALSE,
control = lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e5)))
Crossed random
intercepts + By-speaker and by-item random slopes + Interaction
xmdl.rand.Slope2.Int <- dataCong %>%
lmer(LookingTime ~ Cond * Age +
(1 + Cond | Subj) +
(1 + Cond | Item), data = ., REML = FALSE,
control = lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e5)))
Crossed random
intercepts + By-speaker and by-item random slopes
xmdl.rand.Slope3.Int <- dataCong %>%
lmer(LookingTime ~ Cond * Age +
(1 + Cond | Subj) +
(1 + Cond * Age| Item), data = ., REML = FALSE,
control = lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e5)))
Model comparison
anova(xmdl.rand.Interc, xmdl.rand.Slope1, xmdl.rand.Slope2, xmdl.rand.Slope3, xmdl.rand.Interc.Int, xmdl.rand.Slope1.Int, xmdl.rand.Slope2.Int, xmdl.rand.Slope3.Int)
Data: .
Models:
xmdl.rand.Interc: LookingTime ~ Cond + Age + (1 | Subj) + (1 | Item)
xmdl.rand.Interc.Int: LookingTime ~ Cond * Age + (1 | Subj) + (1 | Item)
xmdl.rand.Slope1: LookingTime ~ Cond + Age + (1 + Cond | Subj) + (1 | Item)
xmdl.rand.Slope1.Int: LookingTime ~ Cond * Age + (1 + Cond | Subj) + (1 | Item)
xmdl.rand.Slope2: LookingTime ~ Cond + Age + (1 + Cond | Subj) + (1 + Cond | Item)
xmdl.rand.Slope2.Int: LookingTime ~ Cond * Age + (1 + Cond | Subj) + (1 + Cond | Item)
xmdl.rand.Slope3: LookingTime ~ Cond + Age + (1 + Cond | Subj) + (1 + Cond + Age | Item)
xmdl.rand.Slope3.Int: LookingTime ~ Cond * Age + (1 + Cond | Subj) + (1 + Cond * Age | Item)
npar AIC BIC logLik deviance Chisq Df Pr(>Chisq)
xmdl.rand.Interc 6 42074 42110 -21031 42062
xmdl.rand.Interc.Int 7 42050 42093 -21018 42036 25.8359 1 3.717e-07 ***
xmdl.rand.Slope1 8 41834 41883 -20909 41818 217.8699 1 < 2.2e-16 ***
xmdl.rand.Slope1.Int 9 41833 41888 -20908 41815 3.0247 1 0.0820 .
xmdl.rand.Slope2 10 41808 41869 -20894 41788 27.3253 1 1.719e-07 ***
xmdl.rand.Slope2.Int 11 41807 41874 -20892 41785 3.0149 1 0.0825 .
xmdl.rand.Slope3 13 41780 41858 -20877 41754 31.2599 2 1.629e-07 ***
xmdl.rand.Slope3.Int 18 41786 41895 -20875 41750 3.3401 5 0.6477
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
The results above highlight that the model accounting for both
by-subject and by-item random intercepts and random slopes for Condition
are improving the model fit in comparison to a more complex model. We
rerun the model with REML = False
Optimal model
xmdl.Optimal <- dataCong %>%
lmer(LookingTime ~ Cond + Age +
(1 + Cond | Subj) +
(1 + Cond + Age | Item), data = ., REML = TRUE,
control = lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e5)))
Model criticism
hist(residuals(xmdl.Optimal))

qqnorm(residuals(xmdl.Optimal)); qqline(residuals(xmdl.Optimal))

plot(fitted(xmdl.Optimal), residuals(xmdl.Optimal), cex = 4)

Summary
xmdl.Optimal %>%
summary()
Linear mixed model fit by REML ['lmerMod']
Formula: LookingTime ~ Cond + Age + (1 + Cond | Subj) + (1 + Cond + Age | Item)
Data: .
Control: lmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 1e+05))
REML criterion at convergence: 41724.6
Scaled residuals:
Min 1Q Median 3Q Max
-3.5337 -0.6485 -0.0054 0.6647 3.5358
Random effects:
Groups Name Variance Std.Dev. Corr
Subj (Intercept) 123480 351.40
CondIncongruent 10746 103.66 -0.26
Item (Intercept) 38781 196.93
CondIncongruent 1872 43.27 0.31
AgeOld 1851 43.03 -0.13 0.69
Residual 22613 150.38
Number of obs: 3200, groups: Subj, 40; Item, 40
Fixed effects:
Estimate Std. Error t value
(Intercept) 315.04 83.42 3.777
CondIncongruent 504.35 18.54 27.204
AgeOld 546.28 107.70 5.072
Correlation of Fixed Effects:
(Intr) CndInc
CndIncngrnt -0.120
AgeOld -0.646 0.016
ANOVA
Analysis of Deviance Table (Type II Wald chisquare tests)
Response: LookingTime
Chisq Df Pr(>Chisq)
Cond 740.067 1 < 2.2e-16 ***
Age 25.729 1 3.928e-07 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Plotting model’s
output
With
ggstats
We use two functions from the package ggstats
.
A plot
ggcoef_model(xmdl.Optimal)

A plot + a table +
95% CI
ggcoef_table(xmdl.Optimal)

With
ggstatsplot
ggcoefstats(xmdl.Optimal, point.args = list(color = paletteer_c("grDevices::rainbow", 13), stats.label.color = paletteer_c("grDevices::rainbow", 13)))
Warning: Ignoring unknown parameters: `stats.label.colour`Number of labels is greater than default palette color count.
• Select another color `palette` (and/or `package`).

Exploring random
effects
Subject random
effects
random_effects <- ranef(xmdl.Optimal) %>%
pluck(1) %>%
rownames_to_column() %>%
rename(Subject = rowname, Intercept = "(Intercept)")
random_effects %>%
knitr::kable()
Subj01 |
-404.45054 |
58.1953368 |
Subj02 |
164.05584 |
56.9126271 |
Subj03 |
-56.37438 |
-104.0600477 |
Subj04 |
-87.06837 |
43.7884729 |
Subj05 |
-55.65214 |
104.5323900 |
Subj06 |
-42.39999 |
-7.1394328 |
Subj07 |
-448.81496 |
124.6524549 |
Subj08 |
-171.75810 |
-105.4504187 |
Subj09 |
-587.74594 |
123.6911001 |
Subj10 |
-44.50407 |
-50.9618431 |
Subj11 |
-346.46288 |
1.6396966 |
Subj12 |
-550.49633 |
158.6524706 |
Subj13 |
417.66027 |
-169.1409700 |
Subj14 |
-11.45716 |
-30.0008252 |
Subj15 |
62.46659 |
-14.3520076 |
Subj16 |
-210.03389 |
-23.9077430 |
Subj17 |
124.19946 |
-122.7635167 |
Subj18 |
666.67147 |
-42.1836697 |
Subj19 |
815.78333 |
217.1615447 |
Subj20 |
-393.58521 |
26.1633665 |
Subj21 |
120.64645 |
37.9297097 |
Subj22 |
455.31816 |
-46.4925696 |
Subj23 |
42.42431 |
-54.4053551 |
Subj24 |
-496.29436 |
-31.7202386 |
Subj25 |
-552.91357 |
144.2714898 |
Subj26 |
-21.91509 |
-159.7897817 |
Subj27 |
65.14521 |
54.5212747 |
Subj28 |
373.40089 |
-166.0862255 |
Subj29 |
-132.82108 |
-21.8820276 |
Subj30 |
104.73419 |
-112.8914459 |
Subj31 |
-79.72260 |
125.0118699 |
Subj32 |
-182.30982 |
15.3898936 |
Subj33 |
-303.68384 |
-0.1957386 |
Subj34 |
215.98609 |
136.5078869 |
Subj35 |
-152.60397 |
76.5559812 |
Subj36 |
401.50547 |
-145.0045141 |
Subj37 |
274.61818 |
-114.4122298 |
Subj38 |
139.48473 |
-82.7958618 |
Subj39 |
733.87830 |
58.5575032 |
Subj40 |
155.08935 |
41.5013939 |
Items random
effects
random_effects <- ranef(xmdl.Optimal) %>%
pluck(2) %>%
rownames_to_column() %>%
rename(Items = rowname, Intercept = "(Intercept)")
random_effects %>%
knitr::kable()
Item01 |
-247.414507 |
16.2991489 |
28.312990 |
Item02 |
-28.240445 |
20.6149279 |
37.267856 |
Item03 |
-27.548429 |
11.7099339 |
-3.218254 |
Item04 |
30.999046 |
32.2392558 |
32.548236 |
Item05 |
246.216859 |
38.0585978 |
2.963549 |
Item06 |
-135.583736 |
28.3151555 |
28.127356 |
Item07 |
75.461498 |
28.6715548 |
-2.095288 |
Item08 |
72.679400 |
69.1730999 |
73.479523 |
Item09 |
-180.071444 |
32.9237845 |
60.953057 |
Item10 |
-170.029328 |
8.4112590 |
23.865843 |
Item11 |
-278.857705 |
-39.6392919 |
-22.526611 |
Item12 |
114.001985 |
4.7652485 |
-15.353357 |
Item13 |
-137.533542 |
-49.5701246 |
-36.764423 |
Item14 |
-272.928912 |
-85.2576750 |
-45.340742 |
Item15 |
219.855541 |
-70.2475223 |
-83.121735 |
Item16 |
243.071753 |
13.0287924 |
-4.812872 |
Item17 |
210.792625 |
10.6898312 |
17.840004 |
Item18 |
328.737750 |
-36.9498461 |
-82.922663 |
Item19 |
-46.910049 |
28.2829527 |
22.930110 |
Item20 |
-107.870056 |
-25.5384308 |
-13.846115 |
Item21 |
-209.598744 |
-56.8339801 |
-29.482588 |
Item22 |
-190.253581 |
-3.0439700 |
20.502593 |
Item23 |
207.958662 |
34.4328035 |
33.373202 |
Item24 |
-371.211245 |
-46.1955836 |
1.751542 |
Item25 |
163.603914 |
15.0837752 |
-7.780876 |
Item26 |
-56.954235 |
-39.1972201 |
-59.652416 |
Item27 |
126.648406 |
7.5867262 |
-1.102683 |
Item28 |
48.176096 |
-0.4969082 |
1.358911 |
Item29 |
-76.699978 |
-27.4397677 |
-1.462473 |
Item30 |
-20.393146 |
33.1813806 |
36.286219 |
Item31 |
33.763413 |
-15.9993987 |
-14.400133 |
Item32 |
-15.979008 |
47.9237115 |
67.643383 |
Item33 |
64.451213 |
-8.2252951 |
-47.157817 |
Item34 |
102.286457 |
22.6554454 |
17.134672 |
Item35 |
319.882212 |
54.1470278 |
10.485257 |
Item36 |
115.886689 |
22.7596669 |
9.094458 |
Item37 |
93.471368 |
9.1514824 |
-17.490313 |
Item38 |
-523.293815 |
-46.1545897 |
-5.185309 |
Item39 |
287.858945 |
20.0462752 |
2.292928 |
Item40 |
-8.431927 |
-59.3622338 |
-34.495018 |
Plots
sjPlot
Fixed
effects
Condition
plot_model(xmdl.Optimal, type="pred", terms=c("Cond"), ci.lvl = NA, dodge = 0) + theme_bw() + geom_line()

Age
plot_model(xmdl.Optimal, type="pred", terms=c("Age"), ci.lvl = NA, dodge = 0) + theme_bw() + geom_line()

Condition by
Age
plot_model(xmdl.Optimal, type="emm", terms=c("Cond", "Age"), ci.lvl = NA, dodge = 0) + theme_bw() + geom_line()

Random
effects
Subject
plot_model(xmdl.Optimal, type="pred", terms=c("Subj"), pred.type="re", ci.lvl = NA, dodge = 0) + theme_bw() + geom_line()

Subject by
Condition
plot_model(xmdl.Optimal, type="pred", terms=c("Cond", "Subj"), pred.type="re", ci.lvl = NA, dodge = 0, colors = paletteer_c("grDevices::rainbow", length(unique(dataCong$Subj)))) + theme_bw() + geom_line()

Subject by
Age
plot_model(xmdl.Optimal, type="pred", terms=c("Age", "Subj"), pred.type="re", ci.lvl = NA, dodge = 0, colors = paletteer_c("grDevices::rainbow", length(unique(dataCong$Subj)))) + theme_bw() + geom_line()

Item
plot_model(xmdl.Optimal, type="pred", terms=c("Item"), pred.type="re", ci.lvl = NA, dodge = 0) + theme_bw() + geom_line()

Item by
Cond
plot_model(xmdl.Optimal, type="pred", terms=c("Cond", "Item"), pred.type="re", ci.lvl = NA, dodge = 0, colors = paletteer_c("grDevices::rainbow", length(unique(dataCong$Item)))) + theme_bw() + geom_line()

Item by
Age
plot_model(xmdl.Optimal, type="pred", terms=c("Age", "Item"), pred.type="re", ci.lvl = NA, dodge = 0, colors = paletteer_c("grDevices::rainbow", length(unique(dataCong$Item)))) + theme_bw() + geom_line()

Item by Cond
facetted by Age
plot_model(xmdl.Optimal, type="pred", terms=c("Cond", "Item", "Age"), pred.type="re", ci.lvl = NA, dodge = 0, colors = paletteer_c("grDevices::rainbow", length(unique(dataCong$Item)))) + theme_bw() + geom_line()

Subject by
Item
plot_model(xmdl.Optimal, type="pred", terms=c("Subj", "Item"), pred.type="re", ci.lvl = NA, dodge = 0, colors = paletteer_c("grDevices::rainbow", length(unique(dataCong$Subj)))) + theme_bw() + geom_line()

Subject by
Item facetted by Cond
plot_model(xmdl.Optimal, type="pred", terms=c("Subj", "Item", "Cond"), pred.type="re", ci.lvl = NA, dodge = 0, colors = paletteer_c("grDevices::rainbow", length(unique(dataCong$Subj)))) + theme_bw() + geom_line()

Subject by
Item facetted by Age
plot_model(xmdl.Optimal, type="pred", terms=c("Subj", "Item", "Age"), pred.type="re", ci.lvl = NA, dodge = 0, colors = paletteer_c("grDevices::rainbow", length(unique(dataCong$Subj)))) + theme_bw() + geom_line()

Lattice
Subject
Intercepts
dotplot(ranef(xmdl.Optimal))$Subj[1]

Subject
Slopes
dotplot(ranef(xmdl.Optimal), xlim = c(-350, 350))$Subj[2]

Item
Intercepts
dotplot(ranef(xmdl.Optimal))$Item[1]

Item Slopes for
Cond
dotplot(ranef(xmdl.Optimal), xlim = c(-150, 150))$Item[2]

Item Slopes for
Age
dotplot(ranef(xmdl.Optimal), xlim = c(-150, 150))$Item[3]

Conclusion
This tutorial showed how one can explore random effects and formally
assess the need for Random slopes
As a rule of thumb: Any within-subject (or within-item) should be
tested for a potential inclusion as a random slope
Fixed effects provides averages over all observations, even when
using mixed effects regressions; we need to explore what random effects
(intercepts and slopes) tell us.
In this example, we see that many subjects vary beyond the fixed
effect; Standard Errors are not enough to quantify this type of
variation. The same is true for items that are not explored
routinely!
I hope this tutorial helped you to uncover the role of participants
and items and what they can tell us beyond the fixed effect!
session info
R version 4.4.2 (2024-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 10 x64 (build 19045)
Matrix products: default
locale:
[1] LC_COLLATE=English_United Kingdom.utf8 LC_CTYPE=English_United Kingdom.utf8 LC_MONETARY=English_United Kingdom.utf8 LC_NUMERIC=C
[5] LC_TIME=English_United Kingdom.utf8
time zone: Europe/Paris
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] faux_1.2.1.9002 car_3.1-3 carData_3.0-5 lattice_0.22-6 paletteer_1.6.0 sjPlot_2.8.17 ggstatsplot_0.13.0 ggstats_0.7.0 lme4_1.1-35.5 Matrix_1.7-1
[11] knitr_1.49 lubridate_1.9.4 forcats_1.0.0 stringr_1.5.1 dplyr_1.1.4 purrr_1.0.2 readr_2.1.5 tidyr_1.3.1 tibble_3.2.1 ggplot2_3.5.1
[21] tidyverse_2.0.0
loaded via a namespace (and not attached):
[1] rematch2_2.1.2 sandwich_3.1-1 rlang_1.1.4 magrittr_2.0.3 multcomp_1.4-26 furrr_0.3.1 compiler_4.4.2 statsExpressions_1.6.2
[9] mgcv_1.9-1 vctrs_0.6.5 pkgconfig_2.0.3 fastmap_1.2.0 backports_1.5.0 labeling_0.4.3 effectsize_1.0.0 utf8_1.2.4
[17] rmarkdown_2.29 tzdb_0.4.0 haven_2.5.4 nloptr_2.1.1 xfun_0.49 cachem_1.1.0 labelled_2.13.0 jsonlite_1.8.9
[25] sjmisc_2.8.10 ggeffects_2.0.0 broom_1.0.7 parallel_4.4.2 R6_2.5.1 bslib_0.8.0 RColorBrewer_1.1-3 stringi_1.8.4
[33] parallelly_1.40.1 boot_1.3-31 jquerylib_0.1.4 estimability_1.5.1 Rcpp_1.0.13-1 zoo_1.8-12 parameters_0.24.0 correlation_0.8.6
[41] splines_4.4.2 timechange_0.3.0 tidyselect_1.2.1 rstudioapi_0.17.1 abind_1.4-8 yaml_2.3.10 codetools_0.2-20 sjlabelled_1.2.0
[49] listenv_0.9.1 withr_3.0.2 bayestestR_0.15.0 coda_0.19-4.1 evaluate_1.0.1 future_1.34.0 survival_3.7-0 RcppParallel_5.1.9
[57] pillar_1.9.0 insight_1.0.0 generics_0.1.3 hms_1.1.3 rstantools_2.4.0 munsell_0.5.1 scales_1.3.0 minqa_1.2.8
[65] globals_0.16.3 xtable_1.8-4 glue_1.8.0 emmeans_1.10.5 tools_4.4.2 mvtnorm_1.3-2 grid_4.4.2 cards_0.4.0
[73] datawizard_0.13.0 colorspace_2.1-1 nlme_3.1-166 patchwork_1.3.0 performance_0.12.4 Formula_1.2-5 cli_3.6.3 fansi_1.0.6
[81] broom.helpers_1.17.0 sjstats_0.19.0 gtable_0.3.6 broom.mixed_0.2.9.6 sass_0.4.9 zeallot_0.1.0 digest_0.6.37 prismatic_1.1.2
[89] ggrepel_0.9.6 TH.data_1.1-2 farver_2.1.2 htmltools_0.5.8.1 lifecycle_1.0.4 MASS_7.3-61
LS0tDQp0aXRsZTogIlR1dG9yaWFsOiBFeHBsb3JpbmcgUmFuZG9tIEVmZmVjdHM6IFdoYXQgRG8gUGFydGljaXBhbnRzIGFuZCBJdGVtcyBUZWxsIHVzIEJleW9uZCB0aGUgRml4ZWQgRWZmZWN0cz8iDQphdXRob3I6DQogIG5hbWU6ICJKYWxhbCBBbC1UYW1pbWkiDQogIGFmZmlsaWF0aW9uOiBVbml2ZXJzaXTDqSBQYXJpcyBDaXTDqQ0KZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6DQogICAgaGlnaGxpZ2h0OiBweWdtZW50cw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDYNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHllcw0KICAgICAgZmlnX2Nyb3A6IG5vDQplZGl0b3Jfb3B0aW9uczogDQogIG1hcmtkb3duOiANCiAgICB3cmFwOiBzZW50ZW5jZQ0KLS0tDQoNCg0KIyBMb2FkaW5nIHBhY2thZ2VzIA0KDQpXZSBzdGFydCBieSBsb2FkaW5nIHRoZSByZXF1aXJlZCBwYWNrYWdlcy4gSWYgdGhleSBhcmUgbm90IGFscmVhZHkgaW5zdGFsbGVkLCB0aGVuIHRoZSBjb2RlIGJlbG93IHdpbGwgZmlyc3QgaW5zdGFsbCB0aGVtLCBiZWZvcmUgbG9hZGluZyB0aGVtLiBUaGUgcGFja2FnZSBgZmF1eGAgaXMgbm90IGF2YWlsYWJsZSBvbiBDUkFOIGZvciBSIHZlcnNpb24gNC40LjIsIGhlbmNlIHdlIHdpbGwgaW5zdGFsbCBpdCB2aWEgZ2l0aHViLiBTZWUgZGV0YWlscyBbaGVyZV0oaHR0cHM6Ly9kZWJydWluZS5naXRodWIuaW8vZmF1eC8pDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KcmVxdWlyZWRQYWNrYWdlcyA9IGMoJ3RpZHl2ZXJzZScsICdrbml0cicsICdsbWU0JywgJ2dnc3RhdHMnLCAnZ2dzdGF0c3Bsb3QnLCAnc2pQbG90JywgJ3BhbGV0dGVlcicsICdsYXR0aWNlJywgJ2NhcicpDQoNCmZvcihwIGluIHJlcXVpcmVkUGFja2FnZXMpew0KICBpZighcmVxdWlyZShwLGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkpIGluc3RhbGwucGFja2FnZXMocCwgZGVwZW5kZW5jaWVzID0gVFJVRSkNCiAgbGlicmFyeShwLGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCn0NCmBgYA0KDQpTcGVjaWZpYyB0byB0aGUgYGZhdXhgIHBhY2thZ2UNCg0KRmlyc3QgaW5zdGFsbCB0aGUgcGFja2FnZSBkZXZ0b29scywgYW5kIHRoZW4gaW5zdGFsbCB0aGUgcGFja2FnZSBgZmF1eGAgdmlhIHRoZSBnaXRodWIgaW5zdGFsbC4gDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJkZXZ0b29scyIpDQojIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiZGVicnVpbmUvZmF1eCIpDQpsaWJyYXJ5KGZhdXgpDQpgYGANCg0KDQojIERhdGEgc2V0DQoNCk91ciBleHBlcmltZW50IGhhcyB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZTogd2UgYXNrZWQgNDAgc3ViamVjdHMgdG8gcmVzcG9uZCB0byA0MCBpdGVtcyBpbiBhIGZ1bGx5IGNyb3NzZWQgZGVzaWduLiBUaGVyZSB3ZXJlIHR3byBJVnM6IENvbmRpdGlvbiB3aXRoIGBjb25ncnVlbnRgIGFuZCBgaW5jb25ncnVlbnRgIGFuZCBBZ2Ugd2l0aCBgeW91bmdgIGFuZCBgb2xkYC4gVGhlIENvbmRpdGlvbiBpcyBhIHdpdGhpbiBzdWJqZWN0IHZhcmlhYmxlOyBhZ2UgaXMgYSBiZXR3ZWVuIHN1YmplY3QuIEhvd2V2ZXIsIENvbmRpdGlvbiBhbmQgQWdlIHdlcmUgYm90aCB3aXRoaW4gaXRlbSB2YXJpYWJsZXMuIFRoZSBkZXBlbmRhbnQgdmFyaWFibGUgd2FzIExvb2tpbmdUaW1lLiANCg0KVGhpcyBtZWFudCB0aGF0IHdlIHVzZWQgaXRlbXMgd2l0aGluIGVhY2ggb2YgdGhlIGB5b3VuZ2AgYW5kIHRoZSBgb2xkYCBzdWJqZWN0cyBpbiBhZGRpdGlvbiB0byBpdGVtcyB3aXRoaW4gZWFjaCBvZiB0aGUgYGNvbmd1cmVudGAgYW5kIGBpbmNvbmdydWVudGAgY29uZGl0aW9ucy4gIA0KDQpPdXIgcmVzZWFyY2ggcXVlc3Rpb24gaXMgYXMgZm9sbG93czogYEFnZWAgb2Ygc3ViamVjdCB3aWxsIGltcGFjdCB0aGUgYExvb2tpbmcgVGltZWAgaW4gdGhlIHR3byBjb25kaXRpb25zLiANCk91ciBoeXBvdGhlc2lzIGlzOiBUaGUgb2xkZXIgYSBzdWJqZWN0IGlzLCB0aGUgbW9yZSB0aGUgbG9va2luZyB0aW1lIGl0IGlzIHRvIHRoZSBpbmNvbmdydWVudCBjb25kaXRpb24uIA0KDQpXZSB3aWxsIHVzZSB0aGUgcGFja2FnZSBgZmF1eGAgdG8gc2ltdWxhdGUgYSBkYXRhZnJhbWUuIFRoaXMgc3RlcCBpcyBjcnVjaWFsIGluIGFzc2Vzc2luZyBjb250cmlidXRpb25zIG9mIHBhcnRpY3VsYXIgcHJlZGljdG9ycyBhbmQgZm9yIHRlc3RpbmcgaWRlYXMgYXMgd2UgYWxyZWFkeSBrbm93IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIGRhdGEgYW5kIHdoYXQgdG8gZXhwZWN0IGFzIGFuIG91dGNvbWUgd2hlbiBpdCBjb21lcyB0byB0aGUgZml4ZWQgZWZmZWN0IGluIHF1ZXN0aW9uLg0KDQoNClRoZSBzaW11bGF0ZWQgZGF0YSBoYXMgdGhlIGZvbGxvd2luZyBwYXJhbWV0ZXJzDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0Kc2V0LnNlZWQoNDIpDQojIGRlZmluZSBwYXJhbWV0ZXJzDQpTdWJqX24gPSA0MCAgIyBudW1iZXIgb2Ygc3ViamVjdHMNCkl0ZW1fbiA9IDQwICAjIG51bWJlciBvZiBpdGVtcw0KYjAgPSAxMDAgICAgICAgIyBpbnRlcmNlcHQNCmIxID0gMi41ICogYjAgICAjIGZpeGVkIGVmZmVjdCBvZiBjb25kaXRpb24NCnUwc19zZCA9IDMwMCAgICMgcmFuZG9tIGludGVyY2VwdCBTRCBmb3Igc3ViamVjdHMNCnUwaV9zZCA9IDIwMCAgICMgcmFuZG9tIGludGVyY2VwdCBTRCBmb3IgaXRlbXMNCnUxc19zZCA9IDEwMCAgICMgcmFuZG9tIGIxIHNsb3BlIFNEIGZvciBzdWJqZWN0cw0KdTFpX3NkID0gNTAgICAjIHJhbmRvbSBiMSBzbG9wZSBTRCBmb3IgaXRlbXMNCnIwMXMgPSAtMC4zICAgICAjIGNvcnJlbGF0aW9uIGJldHdlZW4gcmFuZG9tIGVmZmVjdHMgMCBhbmQgMSBmb3Igc3ViamVjdHMNCnIwMWkgPSAwLjIgICAgICMgY29ycmVsYXRpb24gYmV0d2VlbiByYW5kb20gZWZmZWN0cyAwIGFuZCAxIGZvciBpdGVtcw0Kc2lnbWFfc2QgPSAxNTAgIyBlcnJvciBTRA0KDQojIHNldCB1cCBkYXRhIHN0cnVjdHVyZQ0KZGF0YUNvbmcgPC0gYWRkX3JhbmRvbShTdWJqID0gU3Vial9uLCBJdGVtID0gSXRlbV9uKSAlPiUNCiAgIyBhZGQgd2l0aGluIGNhdGVnb3JpY2FsIHZhcmlhYmxlIGZvciBzdWJqZWN0DQogIGFkZF93aXRoaW4oIlN1YmoiLCBDb25kID0gYygiQ29uZ3J1ZW50IiwgIkluY29uZ3J1ZW50IikpICU+JQ0KICBhZGRfcmVjb2RlKCJDb25kIiwgIkNvbmQuSW5jb25ncnVlbnQiLCBDb25ncnVlbnQgPSAwLCBJbmNvbmdydWVudCA9IDEpICU+JQ0KICAjIGFkZCBiZXR3ZWVuIGNhdGVnb3JpY2FsIHZhcmlhYmxlIGZvciBzdWJqZWN0DQogIGFkZF9iZXR3ZWVuKCJTdWJqIiwgQWdlID0gYygiWW91bmciLCAiT2xkIikpICU+JQ0KICBhZGRfcmVjb2RlKCJBZ2UiLCAiQWdlLk9sZCIsIFlvdW5nID0gMCwgT2xkID0gMSkgJT4lDQogICMgYWRkIHJhbmRvbSBlZmZlY3RzIA0KICBhZGRfcmFuZWYoIlN1YmoiLCB1MHMgPSB1MHNfc2QsIHUxcyA9IHUxc19zZCwgLmNvcnMgPSByMDFzKSAlPiUNCiAgYWRkX3JhbmVmKCJJdGVtIiwgdTBpID0gdTBpX3NkLCB1MWkgPSB1MWlfc2QsIC5jb3JzID0gcjAxaSkgJT4lDQogICMjYWRkX3JhbmVmKGMoIlN1YmoiLCAiSXRlbSIpLCB1MHNpID0gdTBzX3NkICsgdTBpX3NkKSAlPiUNCiAgIyNhZGRfcmFuZWYoYygiU3ViaiIsICJJdGVtIiksIHUxc2kgPSB1MXNfc2QgKyB1MWlfc2QpICU+JQ0KICBhZGRfcmFuZWYoc2lnbWEgPSBzaWdtYV9zZCkgJT4lDQogICMgY2FsY3VsYXRlIERWDQogIG11dGF0ZShMb29raW5nVGltZSA9IGIwICsgYjEgKyB1MHMgKyB1MGkgKyAjdTBzaSArIHUxc2kgKw0KICAgICAgICAgICAoKChiMSArIHUxcykgKyAwLjUpICogQ29uZC5JbmNvbmdydWVudCkgKyAoKChiMSArIHUxcykgKyAwLjkpICogQWdlLk9sZCkgKyAjIHN1YmplY3Qgc3BlY2lmaWMgdmFyaWF0aW9uDQogICAgICAgICAgICgoKGIxICsgdTFpKSAtIDAuMykgKiBDb25kLkluY29uZ3J1ZW50KSArICgoKGIxICsgdTFpKSAtIDAuMjUpICogQWdlLk9sZCkgKyAjIGl0ZW0gc3BlY2lmaWMgdmFyaWF0aW9uICANCiAgICAgICAgICAgc2lnbWEpDQp3cml0ZS5jc3YoZGF0YUNvbmcsICJkYXRhQ29uZy5jc3YiKQ0KYGBgDQoNCg0KSWYgeW91IHdlcmUgbm90IGFibGUgdG8gaW5zdGFsbCB0aGUgYGZhdXhgIHBhY2thZ2UsIHNpbXBseSB1bmNvbW1lbnQgdGhlIGZvbGxvd2luZyBsaW5lIG9mIGNvZGUgYmVsb3cgdG8gaW1wb3J0IHRoZSBkYXRhc2V0DQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KI2RhdGFDb25nIDwtIHJlYWQuY3N2KCJkYXRhQ29uZy5jc3YiKVstMV0NCmBgYA0KDQojIFZlcmlmeSBkYXRhZnJhbWUNCg0KIyMgVGliYmxlDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KZGF0YUNvbmcgPC0gZGF0YUNvbmcgJT4lIA0KICBtdXRhdGUoU3ViaiA9IGZhY3RvcihTdWJqKSwNCiAgICAgICAgIEl0ZW0gPSBmYWN0b3IoSXRlbSkpDQpkYXRhQ29uZw0KYGBgDQoNCg0KIyMgQ291bnRzDQoNCiMjIyBTdWJqZWN0cw0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCmRhdGFDb25nICU+JSANCiAgZ3JvdXBfYnkoQ29uZCwgQWdlLCBTdWJqKSAlPiUgDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkNCmBgYA0KDQoNCg0KIyMjIEl0ZW1zDQoNCiMjIyMgQWdlDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KZGF0YUNvbmcgJT4lIA0KICBncm91cF9ieShBZ2UsIEl0ZW0pICU+JSANCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKQ0KYGBgDQoNCg0KIyMjIyBDb25kDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KZGF0YUNvbmcgJT4lIA0KICBncm91cF9ieShDb25kLCBJdGVtKSAlPiUgDQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkNCmBgYA0KDQoNCg0KIyBWaXN1YWxpc2F0aW9ucw0KDQojIyBDb25kaXRpb24gYnkgQWdlDQoNClRoZSBmaWd1cmUgYmVsb3cgY29uZmlybXMgdGhpcywgd2hlcmUgd2Ugc2VlIGFuIGluY3JlYXNlIGluIExvb2tpbmdUaW1lIGluIHRoZSBgaW5jb25ncnVlbnRgIGNvbmRpdGlvbiBhbmQgb2V2cmFsbCwgYG9sZGVyYCBwYXJ0aWNpcGFudHMgc2hvdyBhbiBpbmNyZWFzZSBpbiBMb29raW5nVGltZQ0KDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KZGF0YUNvbmcgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBDb25kLA0KICAgICAgICAgICAgIHkgPSBMb29raW5nVGltZSwNCiAgICAgICAgICAgICBjb2xvdXIgPSBBZ2UpKSArDQogIHRoZW1lX2J3KCkgKyANCiAgZ2VvbV9ib3hwbG90KCkgKw0KICBnZW9tX3Ntb290aChhZXMoYXMubnVtZXJpYyhDb25kKSksIG1ldGhvZCA9ICJsbSIpDQpgYGANCg0KIyMgU3ViamVjdCBieSBDb25kaXRpb24NCg0KVGhpcyBmaWd1cmUgc2hvd3MgdGhhdCBzdWJqZWN0cyBhcmUgdmFyaWFibGUgaW4gaG93IHRoZXkgcmVzcG9uZGVkIHRvIHRoaXMgdGFzaw0KDQoNCmBgYHtyIGVjaG89VFJVRSwgZXJyb3I9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpkYXRhQ29uZyAlPiUgDQogIGdncGxvdChhZXMoeCA9IENvbmQsDQogICAgICAgICAgICAgeSA9IExvb2tpbmdUaW1lLA0KICAgICAgICAgICAgIGNvbG91ciA9IFN1YmopKSArDQogIHRoZW1lX2J3KCkgKyANCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgoYWVzKGFzLm51bWVyaWMoQ29uZCkpLCBtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gcGFsZXR0ZWVyX2MoImdyRGV2aWNlczo6cmFpbmJvdyIsIGxlbmd0aCh1bmlxdWUoZGF0YUNvbmckU3ViaikpKSkNCmBgYA0KDQoNCiMjIFN1YmplY3QgYnkgQWdlDQoNClRoaXMgZmlndXJlIHNob3dzIHRoYXQgc3ViamVjdHMgaGFkIGFuIGltcGFjdCBvbiB0aGUgTG9va2luZ1RpbWUgaW4gYm90aCBhZ2UgZ3JvdXBzLCBzaW1wbHkgZHVlIHRvIHRoZWlyIHZhcmlhYmxlIHJlc3BvbnNlcyB0byB0aGUgZGlmZmVyZW50IGl0ZW1zDQoNCg0KYGBge3IgZWNobz1UUlVFLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmRhdGFDb25nICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gQWdlLA0KICAgICAgICAgICAgIHkgPSBMb29raW5nVGltZSwNCiAgICAgICAgICAgICBjb2xvdXIgPSBTdWJqKSkgKw0KICB0aGVtZV9idygpICsgDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKGFlcyhhcy5udW1lcmljKENvbmQpKSwgbWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHBhbGV0dGVlcl9jKCJnckRldmljZXM6OnJhaW5ib3ciLCBsZW5ndGgodW5pcXVlKGRhdGFDb25nJFN1YmopKSkpDQpgYGANCg0KDQoNCiMjIEl0ZW0gYnkgQ29uZGl0aW9uDQoNClRoaXMgZmlndXJlIHNob3dzIHRoYXQgaXRlbXMgaGFkIGFuIGltcGFjdCBvbiB0aGUgTG9va2luZ1RpbWUgaW4gYm90aCBjb25kaXRpb25zDQoNCg0KYGBge3IgZWNobz1UUlVFLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmRhdGFDb25nICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gQ29uZCwNCiAgICAgICAgICAgICB5ID0gTG9va2luZ1RpbWUsDQogICAgICAgICAgICAgY29sb3VyID0gSXRlbSkpICsNCiAgdGhlbWVfYncoKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3Ntb290aChhZXMoYXMubnVtZXJpYyhDb25kKSksIG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBwYWxldHRlZXJfYygiZ3JEZXZpY2VzOjpyYWluYm93IiwgbGVuZ3RoKHVuaXF1ZShkYXRhQ29uZyRJdGVtKSkpKQ0KYGBgDQoNCg0KIyMgU3ViamVjdCBieSBBZ2UNCg0KVGhpcyBmaWd1cmUgc2hvd3MgdGhhdCBpdGVtcyBoYWQgYW4gaW1wYWN0IG9uIHRoZSBMb29raW5nVGltZSBpbiBib3RoIGFnZSBncm91cHMNCg0KDQpgYGB7ciBlY2hvPVRSVUUsIGVycm9yPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KZGF0YUNvbmcgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBBZ2UsDQogICAgICAgICAgICAgeSA9IExvb2tpbmdUaW1lLA0KICAgICAgICAgICAgIGNvbG91ciA9IEl0ZW0pKSArDQogIHRoZW1lX2J3KCkgKyANCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgoYWVzKGFzLm51bWVyaWMoQ29uZCkpLCBtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArDQogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gcGFsZXR0ZWVyX2MoImdyRGV2aWNlczo6cmFpbmJvdyIsIGxlbmd0aCh1bmlxdWUoZGF0YUNvbmckSXRlbSkpKSkNCmBgYA0KDQojIE1vZGVsbGluZyBzdHJhdGVneQ0KDQpXZSB1c2UgYW4gTE1FUiBtb2RlbCB3aXRoIGEgY3Jvc3NlZCByYW5kb20gZWZmZWN0LiBUbyBjaG9vc2Ugb3VyIG9wdGltYWwgbW9kZWwsIHdlIHN0YXJ0IGZpcnN0IGJ5IGEgc2ltcGxlIG1vZGVsIHdpdGggb25seSByYW5kb20gaW50ZXJjZXB0cywgaW5jcmVhc2luZyBjb21wbGV4aXR5IGJ5IGFjY291bnRpbmcgZm9yIHJhbmRvbSBzbG9wZXMgZm9yIGJvdGggc3ViamVjdHMgYW5kIGl0ZW1zLiBJdCBpcyBjbGVhciBmcm9tIG91ciB2aXN1YWxpc2F0aW9uIGFib3ZlLCB0aGF0IHRoZXJlIGlzIG5vIGludGVyYWN0aW9uIGJldHdlZW4gdGhlIHR3byBwcmVkaWN0b3JzLiBIb3dldmVyLCBmb3IgZGVtb25zdHJhdGlvbiBwdXJwb3Nlcywgd2UgZG8gdGVzdCBmb3IgdGhpcw0KDQoNCiMgU2ltcGxlIExpbmVhciBNb2RlbA0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCm1kbC5sbSA8LSBkYXRhQ29uZyAlPiUgDQogIGxtKExvb2tpbmdUaW1lIH4gQ29uZCArIEFnZSwgZGF0YSA9IC4pDQpzdW1tYXJ5KG1kbC5sbSkNCmhpc3QocmVzaWR1YWxzKG1kbC5sbSkpDQpxcW5vcm0ocmVzaWR1YWxzKG1kbC5sbSkpOyBxcWxpbmUocmVzaWR1YWxzKG1kbC5sbSkpDQpwbG90KGZpdHRlZChtZGwubG0pLCByZXNpZHVhbHMobWRsLmxtKSwgY2V4ID0gNCkNCmBgYA0KDQojIyBObyBpbnRlcmFjdGlvbg0KDQojIyMgQ3Jvc3NlZCByYW5kb20gaW50ZXJjZXB0cw0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCnhtZGwucmFuZC5JbnRlcmMgPC0gZGF0YUNvbmcgJT4lIA0KICBsbWVyKExvb2tpbmdUaW1lIH4gQ29uZCArIEFnZSArIA0KICAgICAgICAgKDEgfCBTdWJqKSArIA0KICAgICAgICAgKDEgfCBJdGVtKSwgZGF0YSA9IC4sIFJFTUwgPSBGQUxTRSwNCiAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsIG9wdEN0cmwgPSBsaXN0KG1heGZ1biA9IDFlNSkpKQ0KYGBgDQoNCg0KIyMjIENyb3NzZWQgcmFuZG9tIGludGVyY2VwdHMgKyBCeS1zcGVha2VyIHJhbmRvbSBzbG9wZXMNCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQp4bWRsLnJhbmQuU2xvcGUxIDwtIGRhdGFDb25nICU+JSANCiAgbG1lcihMb29raW5nVGltZSB+IENvbmQgKyBBZ2UgKyANCiAgICAgICAgICgxICsgQ29uZCB8IFN1YmopICsgDQogICAgICAgICAoMSB8IEl0ZW0pLCBkYXRhID0gLiwgUkVNTCA9IEZBTFNFLA0KICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMWU1KSkpDQpgYGANCg0KIyMjIENyb3NzZWQgcmFuZG9tIGludGVyY2VwdHMgKyBCeS1zcGVha2VyIGFuZCBieS1pdGVtIHJhbmRvbSBzbG9wZXMNCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQp4bWRsLnJhbmQuU2xvcGUyIDwtIGRhdGFDb25nICU+JSANCiAgbG1lcihMb29raW5nVGltZSB+IENvbmQgKyBBZ2UgKyANCiAgICAgICAgICgxICsgQ29uZCB8IFN1YmopICsgDQogICAgICAgICAoMSArIENvbmQgfCBJdGVtKSwgZGF0YSA9IC4sIFJFTUwgPSBGQUxTRSwNCiAgICAgICBjb250cm9sID0gbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsIG9wdEN0cmwgPSBsaXN0KG1heGZ1biA9IDFlNSkpKQ0KYGBgDQoNCg0KIyMjIENyb3NzZWQgcmFuZG9tIGludGVyY2VwdHMgKyBCeS1zcGVha2VyIGFuZCBieS1pdGVtIHJhbmRvbSBzbG9wZXMNCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQp4bWRsLnJhbmQuU2xvcGUzIDwtIGRhdGFDb25nICU+JSANCiAgbG1lcihMb29raW5nVGltZSB+IENvbmQgKyBBZ2UgKyANCiAgICAgICAgICgxICsgQ29uZCB8IFN1YmopICsgDQogICAgICAgICAoMSArIENvbmQgKyBBZ2V8IEl0ZW0pLCBkYXRhID0gLiwgUkVNTCA9IEZBTFNFLA0KICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMWU1KSkpDQpgYGANCg0KDQojIyBXaXRoIGludGVyYWN0aW9uDQoNCiMjIyBDcm9zc2VkIHJhbmRvbSBpbnRlcmNlcHRzICsgSW50ZXJhY3Rpb24NCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQp4bWRsLnJhbmQuSW50ZXJjLkludCA8LSBkYXRhQ29uZyAlPiUgDQogIGxtZXIoTG9va2luZ1RpbWUgfiBDb25kICogQWdlICsgDQogICAgICAgICAoMSB8IFN1YmopICsgDQogICAgICAgICAoMSB8IEl0ZW0pLCBkYXRhID0gLiwgUkVNTCA9IEZBTFNFLA0KICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMWU1KSkpDQpgYGANCg0KDQojIyMgQ3Jvc3NlZCByYW5kb20gaW50ZXJjZXB0cyArIEJ5LXNwZWFrZXIgcmFuZG9tIHNsb3BlcyArIEludGVyYWN0aW9uDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KeG1kbC5yYW5kLlNsb3BlMS5JbnQgPC0gZGF0YUNvbmcgJT4lIA0KICBsbWVyKExvb2tpbmdUaW1lIH4gQ29uZCAqIEFnZSArIA0KICAgICAgICAgKDEgKyBDb25kIHwgU3ViaikgKyANCiAgICAgICAgICgxIHwgSXRlbSksIGRhdGEgPSAuLCBSRU1MID0gRkFMU0UsDQogICAgICAgY29udHJvbCA9IGxtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLCBvcHRDdHJsID0gbGlzdChtYXhmdW4gPSAxZTUpKSkNCmBgYA0KDQojIyMgQ3Jvc3NlZCByYW5kb20gaW50ZXJjZXB0cyArIEJ5LXNwZWFrZXIgYW5kIGJ5LWl0ZW0gcmFuZG9tIHNsb3BlcyArIEludGVyYWN0aW9uDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KeG1kbC5yYW5kLlNsb3BlMi5JbnQgPC0gZGF0YUNvbmcgJT4lIA0KICBsbWVyKExvb2tpbmdUaW1lIH4gQ29uZCAqIEFnZSArIA0KICAgICAgICAgKDEgKyBDb25kIHwgU3ViaikgKyANCiAgICAgICAgICgxICsgQ29uZCB8IEl0ZW0pLCBkYXRhID0gLiwgUkVNTCA9IEZBTFNFLA0KICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMWU1KSkpDQpgYGANCg0KDQojIyMgQ3Jvc3NlZCByYW5kb20gaW50ZXJjZXB0cyArIEJ5LXNwZWFrZXIgYW5kIGJ5LWl0ZW0gcmFuZG9tIHNsb3Blcw0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCnhtZGwucmFuZC5TbG9wZTMuSW50IDwtIGRhdGFDb25nICU+JSANCiAgbG1lcihMb29raW5nVGltZSB+IENvbmQgKiBBZ2UgKyANCiAgICAgICAgICgxICsgQ29uZCB8IFN1YmopICsgDQogICAgICAgICAoMSArIENvbmQgKiBBZ2V8IEl0ZW0pLCBkYXRhID0gLiwgUkVNTCA9IEZBTFNFLA0KICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMWU1KSkpDQpgYGANCg0KDQojIyBNb2RlbCBjb21wYXJpc29uDQoNCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQphbm92YSh4bWRsLnJhbmQuSW50ZXJjLCB4bWRsLnJhbmQuU2xvcGUxLCB4bWRsLnJhbmQuU2xvcGUyLCB4bWRsLnJhbmQuU2xvcGUzLCB4bWRsLnJhbmQuSW50ZXJjLkludCwgeG1kbC5yYW5kLlNsb3BlMS5JbnQsIHhtZGwucmFuZC5TbG9wZTIuSW50LCB4bWRsLnJhbmQuU2xvcGUzLkludCkNCmBgYA0KDQoNClRoZSByZXN1bHRzIGFib3ZlIGhpZ2hsaWdodCB0aGF0IHRoZSBtb2RlbCBhY2NvdW50aW5nIGZvciBib3RoIGJ5LXN1YmplY3QgYW5kIGJ5LWl0ZW0gcmFuZG9tIGludGVyY2VwdHMgYW5kIHJhbmRvbSBzbG9wZXMgZm9yIENvbmRpdGlvbiBhcmUgaW1wcm92aW5nIHRoZSBtb2RlbCBmaXQgaW4gY29tcGFyaXNvbiB0byBhIG1vcmUgY29tcGxleCBtb2RlbC4gV2UgcmVydW4gdGhlIG1vZGVsIHdpdGggYFJFTUwgPSBGYWxzZWANCg0KIyBPcHRpbWFsIG1vZGVsDQoNCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KeG1kbC5PcHRpbWFsIDwtIGRhdGFDb25nICU+JSANCiAgbG1lcihMb29raW5nVGltZSB+IENvbmQgKyBBZ2UgKyANCiAgICAgICAgICgxICsgQ29uZCB8IFN1YmopICsgDQogICAgICAgICAoMSArIENvbmQgKyBBZ2UgfCBJdGVtKSwgZGF0YSA9IC4sIFJFTUwgPSBUUlVFLA0KICAgICAgIGNvbnRyb2wgPSBsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMWU1KSkpDQpgYGANCg0KDQojIyBNb2RlbCBjcml0aWNpc20NCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQpoaXN0KHJlc2lkdWFscyh4bWRsLk9wdGltYWwpKQ0KcXFub3JtKHJlc2lkdWFscyh4bWRsLk9wdGltYWwpKTsgcXFsaW5lKHJlc2lkdWFscyh4bWRsLk9wdGltYWwpKQ0KcGxvdChmaXR0ZWQoeG1kbC5PcHRpbWFsKSwgcmVzaWR1YWxzKHhtZGwuT3B0aW1hbCksIGNleCA9IDQpDQpgYGANCg0KIyMgU3VtbWFyeQ0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCnhtZGwuT3B0aW1hbCAlPiUgDQogIHN1bW1hcnkoKQ0KYGBgDQoNCiMjIEFOT1ZBDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCkFub3ZhKHhtZGwuT3B0aW1hbCkNCmBgYA0KDQoNCiMjIFBsb3R0aW5nIG1vZGVsJ3Mgb3V0cHV0DQoNCiMjIyBXaXRoIGBnZ3N0YXRzYA0KDQpXZSB1c2UgdHdvIGZ1bmN0aW9ucyBmcm9tIHRoZSBwYWNrYWdlIGBnZ3N0YXRzYC4gDQoNCiMjIyMgQSBwbG90DQoNCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQpnZ2NvZWZfbW9kZWwoeG1kbC5PcHRpbWFsKQ0KYGBgDQoNCg0KDQojIyMgQSBwbG90ICsgYSB0YWJsZSArIDk1JSBDSQ0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCmdnY29lZl90YWJsZSh4bWRsLk9wdGltYWwpDQpgYGANCg0KDQoNCiMjIyBXaXRoIGBnZ3N0YXRzcGxvdGANCg0KYGBge3J9DQpnZ2NvZWZzdGF0cyh4bWRsLk9wdGltYWwsIHBvaW50LmFyZ3MgPSBsaXN0KGNvbG9yID0gcGFsZXR0ZWVyX2MoImdyRGV2aWNlczo6cmFpbmJvdyIsIDEzKSwgc3RhdHMubGFiZWwuY29sb3IgPSBwYWxldHRlZXJfYygiZ3JEZXZpY2VzOjpyYWluYm93IiwgMTMpKSkNCg0KYGBgDQoNCg0KIyMgRXhwbG9yaW5nIHJhbmRvbSBlZmZlY3RzDQoNCg0KIyMjIFN1YmplY3QgcmFuZG9tIGVmZmVjdHMNCg0KDQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRX0NCnJhbmRvbV9lZmZlY3RzIDwtIHJhbmVmKHhtZGwuT3B0aW1hbCkgJT4lDQogIHBsdWNrKDEpICU+JQ0KICByb3duYW1lc190b19jb2x1bW4oKSAlPiUNCiAgcmVuYW1lKFN1YmplY3QgPSByb3duYW1lLCBJbnRlcmNlcHQgPSAiKEludGVyY2VwdCkiKSANCiANCnJhbmRvbV9lZmZlY3RzICU+JQ0KICBrbml0cjo6a2FibGUoKQ0KDQpgYGANCg0KDQoNCg0KIyMjIEl0ZW1zIHJhbmRvbSBlZmZlY3RzDQoNCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQpyYW5kb21fZWZmZWN0cyA8LSByYW5lZih4bWRsLk9wdGltYWwpICU+JQ0KICBwbHVjaygyKSAlPiUNCiAgcm93bmFtZXNfdG9fY29sdW1uKCkgJT4lDQogIHJlbmFtZShJdGVtcyA9IHJvd25hbWUsIEludGVyY2VwdCA9ICIoSW50ZXJjZXB0KSIpIA0KIA0KcmFuZG9tX2VmZmVjdHMgJT4lDQogIGtuaXRyOjprYWJsZSgpDQoNCmBgYA0KDQoNCiMjIyBQbG90cw0KDQojIyMjIHNqUGxvdA0KDQojIyMjIyBGaXhlZCBlZmZlY3RzDQoNCiMjIyMjIyBDb25kaXRpb24NCg0KYGBge3J9DQpwbG90X21vZGVsKHhtZGwuT3B0aW1hbCwgdHlwZT0icHJlZCIsIHRlcm1zPWMoIkNvbmQiKSwgY2kubHZsID0gTkEsIGRvZGdlID0gMCkgKyB0aGVtZV9idygpICsgZ2VvbV9saW5lKCkNCg0KYGBgDQoNCiMjIyMjIyBBZ2UNCg0KYGBge3J9DQpwbG90X21vZGVsKHhtZGwuT3B0aW1hbCwgdHlwZT0icHJlZCIsIHRlcm1zPWMoIkFnZSIpLCBjaS5sdmwgPSBOQSwgZG9kZ2UgPSAwKSArIHRoZW1lX2J3KCkgKyBnZW9tX2xpbmUoKQ0KDQpgYGANCg0KDQojIyMjIyMgQ29uZGl0aW9uIGJ5IEFnZQ0KDQpgYGB7cn0NCnBsb3RfbW9kZWwoeG1kbC5PcHRpbWFsLCB0eXBlPSJlbW0iLCB0ZXJtcz1jKCJDb25kIiwgIkFnZSIpLCBjaS5sdmwgPSBOQSwgZG9kZ2UgPSAwKSArIHRoZW1lX2J3KCkgKyBnZW9tX2xpbmUoKQ0KDQpgYGANCg0KIyMjIyMgUmFuZG9tIGVmZmVjdHMNCg0KIyMjIyMjIFN1YmplY3QNCg0KYGBge3J9DQpwbG90X21vZGVsKHhtZGwuT3B0aW1hbCwgdHlwZT0icHJlZCIsIHRlcm1zPWMoIlN1YmoiKSwgcHJlZC50eXBlPSJyZSIsIGNpLmx2bCA9IE5BLCBkb2RnZSA9IDApICsgdGhlbWVfYncoKSArIGdlb21fbGluZSgpDQoNCmBgYA0KDQojIyMjIyMgU3ViamVjdCBieSBDb25kaXRpb24NCg0KYGBge3J9DQpwbG90X21vZGVsKHhtZGwuT3B0aW1hbCwgdHlwZT0icHJlZCIsIHRlcm1zPWMoIkNvbmQiLCAiU3ViaiIpLCBwcmVkLnR5cGU9InJlIiwgY2kubHZsID0gTkEsIGRvZGdlID0gMCwgY29sb3JzID0gcGFsZXR0ZWVyX2MoImdyRGV2aWNlczo6cmFpbmJvdyIsIGxlbmd0aCh1bmlxdWUoZGF0YUNvbmckU3ViaikpKSkgKyB0aGVtZV9idygpICsgZ2VvbV9saW5lKCkgDQoNCmBgYA0KDQojIyMjIyMgU3ViamVjdCBieSBBZ2UNCg0KYGBge3J9DQpwbG90X21vZGVsKHhtZGwuT3B0aW1hbCwgdHlwZT0icHJlZCIsIHRlcm1zPWMoIkFnZSIsICJTdWJqIiksIHByZWQudHlwZT0icmUiLCBjaS5sdmwgPSBOQSwgZG9kZ2UgPSAwLCBjb2xvcnMgPSBwYWxldHRlZXJfYygiZ3JEZXZpY2VzOjpyYWluYm93IiwgbGVuZ3RoKHVuaXF1ZShkYXRhQ29uZyRTdWJqKSkpKSArIHRoZW1lX2J3KCkgKyBnZW9tX2xpbmUoKQ0KDQpgYGANCg0KDQoNCiMjIyMjIyBJdGVtDQoNCmBgYHtyfQ0KcGxvdF9tb2RlbCh4bWRsLk9wdGltYWwsIHR5cGU9InByZWQiLCB0ZXJtcz1jKCJJdGVtIiksIHByZWQudHlwZT0icmUiLCBjaS5sdmwgPSBOQSwgZG9kZ2UgPSAwKSArIHRoZW1lX2J3KCkgKyBnZW9tX2xpbmUoKQ0KDQpgYGANCg0KDQoNCg0KDQojIyMjIyMgSXRlbSBieSBDb25kDQoNCmBgYHtyfQ0KcGxvdF9tb2RlbCh4bWRsLk9wdGltYWwsIHR5cGU9InByZWQiLCB0ZXJtcz1jKCJDb25kIiwgIkl0ZW0iKSwgcHJlZC50eXBlPSJyZSIsIGNpLmx2bCA9IE5BLCBkb2RnZSA9IDAsIGNvbG9ycyA9IHBhbGV0dGVlcl9jKCJnckRldmljZXM6OnJhaW5ib3ciLCBsZW5ndGgodW5pcXVlKGRhdGFDb25nJEl0ZW0pKSkpICsgdGhlbWVfYncoKSArIGdlb21fbGluZSgpDQoNCmBgYA0KDQoNCg0KDQojIyMjIyMgSXRlbSBieSBBZ2UNCg0KYGBge3J9DQpwbG90X21vZGVsKHhtZGwuT3B0aW1hbCwgdHlwZT0icHJlZCIsIHRlcm1zPWMoIkFnZSIsICJJdGVtIiksIHByZWQudHlwZT0icmUiLCBjaS5sdmwgPSBOQSwgZG9kZ2UgPSAwLCBjb2xvcnMgPSBwYWxldHRlZXJfYygiZ3JEZXZpY2VzOjpyYWluYm93IiwgbGVuZ3RoKHVuaXF1ZShkYXRhQ29uZyRJdGVtKSkpKSArIHRoZW1lX2J3KCkgKyBnZW9tX2xpbmUoKQ0KDQpgYGANCg0KDQoNCiMjIyMjIyBJdGVtIGJ5IENvbmQgZmFjZXR0ZWQgYnkgQWdlDQoNCmBgYHtyfQ0KcGxvdF9tb2RlbCh4bWRsLk9wdGltYWwsIHR5cGU9InByZWQiLCB0ZXJtcz1jKCJDb25kIiwgIkl0ZW0iLCAiQWdlIiksIHByZWQudHlwZT0icmUiLCBjaS5sdmwgPSBOQSwgZG9kZ2UgPSAwLCBjb2xvcnMgPSBwYWxldHRlZXJfYygiZ3JEZXZpY2VzOjpyYWluYm93IiwgbGVuZ3RoKHVuaXF1ZShkYXRhQ29uZyRJdGVtKSkpKSArIHRoZW1lX2J3KCkgKyBnZW9tX2xpbmUoKQ0KDQpgYGANCg0KDQojIyMjIyMgU3ViamVjdCBieSBJdGVtDQoNCmBgYHtyfQ0KcGxvdF9tb2RlbCh4bWRsLk9wdGltYWwsIHR5cGU9InByZWQiLCB0ZXJtcz1jKCJTdWJqIiwgIkl0ZW0iKSwgcHJlZC50eXBlPSJyZSIsIGNpLmx2bCA9IE5BLCBkb2RnZSA9IDAsIGNvbG9ycyA9IHBhbGV0dGVlcl9jKCJnckRldmljZXM6OnJhaW5ib3ciLCBsZW5ndGgodW5pcXVlKGRhdGFDb25nJFN1YmopKSkpICsgdGhlbWVfYncoKSArIGdlb21fbGluZSgpDQoNCmBgYA0KDQojIyMjIyMgU3ViamVjdCBieSBJdGVtIGZhY2V0dGVkIGJ5IENvbmQNCg0KYGBge3J9DQpwbG90X21vZGVsKHhtZGwuT3B0aW1hbCwgdHlwZT0icHJlZCIsIHRlcm1zPWMoIlN1YmoiLCAiSXRlbSIsICJDb25kIiksIHByZWQudHlwZT0icmUiLCBjaS5sdmwgPSBOQSwgZG9kZ2UgPSAwLCBjb2xvcnMgPSBwYWxldHRlZXJfYygiZ3JEZXZpY2VzOjpyYWluYm93IiwgbGVuZ3RoKHVuaXF1ZShkYXRhQ29uZyRTdWJqKSkpKSArIHRoZW1lX2J3KCkgKyBnZW9tX2xpbmUoKQ0KDQpgYGANCg0KDQojIyMjIyMgU3ViamVjdCBieSBJdGVtIGZhY2V0dGVkIGJ5IEFnZQ0KDQpgYGB7cn0NCnBsb3RfbW9kZWwoeG1kbC5PcHRpbWFsLCB0eXBlPSJwcmVkIiwgdGVybXM9YygiU3ViaiIsICJJdGVtIiwgIkFnZSIpLCBwcmVkLnR5cGU9InJlIiwgY2kubHZsID0gTkEsIGRvZGdlID0gMCwgY29sb3JzID0gcGFsZXR0ZWVyX2MoImdyRGV2aWNlczo6cmFpbmJvdyIsIGxlbmd0aCh1bmlxdWUoZGF0YUNvbmckU3ViaikpKSkgKyB0aGVtZV9idygpICsgZ2VvbV9saW5lKCkNCg0KYGBgDQoNCiMjIyMgTGF0dGljZQ0KDQojIyMjIyBTdWJqZWN0IEludGVyY2VwdHMNCg0KYGBge3J9DQpkb3RwbG90KHJhbmVmKHhtZGwuT3B0aW1hbCkpJFN1YmpbMV0NCmBgYA0KDQoNCiMjIyMjIFN1YmplY3QgU2xvcGVzDQoNCmBgYHtyfQ0KZG90cGxvdChyYW5lZih4bWRsLk9wdGltYWwpLCB4bGltID0gYygtMzUwLCAzNTApKSRTdWJqWzJdDQpgYGANCg0KDQoNCg0KIyMjIyMgSXRlbSBJbnRlcmNlcHRzDQoNCmBgYHtyfQ0KZG90cGxvdChyYW5lZih4bWRsLk9wdGltYWwpKSRJdGVtWzFdDQpgYGANCg0KDQojIyMjIyBJdGVtIFNsb3BlcyBmb3IgQ29uZA0KDQpgYGB7cn0NCmRvdHBsb3QocmFuZWYoeG1kbC5PcHRpbWFsKSwgeGxpbSA9IGMoLTE1MCwgMTUwKSkkSXRlbVsyXQ0KYGBgDQoNCg0KIyMjIyMgSXRlbSBTbG9wZXMgZm9yIEFnZQ0KDQpgYGB7cn0NCmRvdHBsb3QocmFuZWYoeG1kbC5PcHRpbWFsKSwgeGxpbSA9IGMoLTE1MCwgMTUwKSkkSXRlbVszXQ0KYGBgDQoNCg0KDQoNCiMgQ29uY2x1c2lvbg0KDQpUaGlzIHR1dG9yaWFsIHNob3dlZCBob3cgb25lIGNhbiBleHBsb3JlIHJhbmRvbSBlZmZlY3RzIGFuZCBmb3JtYWxseSBhc3Nlc3MgdGhlIG5lZWQgZm9yIFJhbmRvbSBzbG9wZXMNCg0KQXMgYSBydWxlIG9mIHRodW1iOiBBbnkgd2l0aGluLXN1YmplY3QgKG9yIHdpdGhpbi1pdGVtKSBzaG91bGQgYmUgdGVzdGVkIGZvciBhIHBvdGVudGlhbCBpbmNsdXNpb24gYXMgYSByYW5kb20gc2xvcGUNCg0KRml4ZWQgZWZmZWN0cyBwcm92aWRlcyBhdmVyYWdlcyBvdmVyIGFsbCBvYnNlcnZhdGlvbnMsIGV2ZW4gd2hlbiB1c2luZyBtaXhlZCBlZmZlY3RzIHJlZ3Jlc3Npb25zOyB3ZSBuZWVkIHRvIGV4cGxvcmUgd2hhdCByYW5kb20gZWZmZWN0cyAoaW50ZXJjZXB0cyBhbmQgc2xvcGVzKSB0ZWxsIHVzLg0KDQpJbiB0aGlzIGV4YW1wbGUsIHdlIHNlZSB0aGF0IG1hbnkgc3ViamVjdHMgdmFyeSBiZXlvbmQgdGhlIGZpeGVkIGVmZmVjdDsgU3RhbmRhcmQgRXJyb3JzIGFyZSBub3QgZW5vdWdoIHRvIHF1YW50aWZ5IHRoaXMgdHlwZSBvZiB2YXJpYXRpb24uIFRoZSBzYW1lIGlzIHRydWUgZm9yIGl0ZW1zIHRoYXQgYXJlIG5vdCBleHBsb3JlZCByb3V0aW5lbHkhDQoNCg0KSSBob3BlIHRoaXMgdHV0b3JpYWwgaGVscGVkIHlvdSB0byB1bmNvdmVyIHRoZSByb2xlIG9mIHBhcnRpY2lwYW50cyBhbmQgaXRlbXMgYW5kIHdoYXQgdGhleSBjYW4gdGVsbCB1cyBiZXlvbmQgdGhlIGZpeGVkIGVmZmVjdCENCg0KIyBzZXNzaW9uIGluZm8NCg0KYGBge3Igd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0V9DQpzZXNzaW9uSW5mbygpDQpgYGANCg0K