1. Packages and data import
# Install packages if needed:
# install.packages("readxl")
# install.packages("dplyr")
# install.packages("tidyr")
# install.packages("ggplot2")
# install.packages("lme4")
library(readxl)
library(dplyr)
library(tidyr)
library(ggplot2)
library(lme4)
# Change file path if necessary
file <- "/Users/mette/Desktop/NTNU/Learning analytics/DataSet-ProTuS.xlsx"
learners <- read_excel(file, sheet = "Learners") %>%
select(where(~ !all(is.na(.))))
actions_raw <- read_excel(file, sheet = "Users actions") %>%
select(where(~ !all(is.na(.))))
action_types_raw <- read_excel(file, sheet = "Action type") %>%
select(where(~ !all(is.na(.))))
2. Initial data inspection
dim(learners)
[1] 116 5
dim(actions_raw)
[1] 13247 13
names(learners)
[1] "id" "year" "masteryID" "ELOrating" "iteraction_num"
names(actions_raw)
[1] "idUsers_action" "learner" "lesson" "type" "menu_item" "learning_content_name" "category" "Elo_rating_student" "Elo_rating_content"
[10] "session" "changed_item" "learning_content_type" "time"
nrow(learners)
[1] 116
n_distinct(actions_raw$learner)
[1] 81
sum(duplicated(actions_raw))
[1] 0
colSums(is.na(actions_raw))
idUsers_action learner lesson type menu_item learning_content_name category Elo_rating_student Elo_rating_content session
0 0 0 1 1 1 1 1 1 1
changed_item learning_content_type time
1 1 1
The Learners sheet contains 116 learners. Not all learners are
represented in the provided action log.
learner_action_coverage <- learners %>%
mutate(has_action_records = id %in% actions_raw$learner) %>%
count(has_action_records)
print(learner_action_coverage)
# A tibble: 2 × 2
has_action_records n
<lgl> <int>
1 FALSE 35
2 TRUE 81
3. Data cleaning
Create a clean lookup table for action types.
action_lookup <- action_types_raw %>%
select(idaction_type, action_type) %>%
filter(!is.na(idaction_type)) %>%
distinct(idaction_type, .keep_all = TRUE)
# Verify that each action type ID occurs only once
action_lookup %>%
count(idaction_type) %>%
filter(n > 1)
Remove the single malformed action record with a missing action type
and add the action labels.
actions_clean <- actions_raw %>%
filter(!is.na(type)) %>%
left_join(
action_lookup,
by = c("type" = "idaction_type"),
relationship = "many-to-one"
) %>%
arrange(learner, time, idUsers_action)
Verify the cleaned dataset.
data_summary <- tibble(
measure = c(
"Learners in Learners sheet",
"Learners represented in action log",
"Raw action records",
"Clean action records"
),
n = c(
nrow(learners),
n_distinct(actions_raw$learner),
nrow(actions_raw),
nrow(actions_clean)
)
)
print(data_summary)
# A tibble: 4 × 2
measure n
<chr> <int>
1 Learners in Learners sheet 116
2 Learners represented in action log 81
3 Raw action records 13247
4 Clean action records 13246
# Verify that action IDs are unique after cleaning
stopifnot(sum(duplicated(actions_clean$idUsers_action)) == 0)
4. Elo events and exercise data
Check which action types contain non-zero Elo values.
elo_events <- actions_clean %>%
filter(Elo_rating_student != 0)
elo_events %>%
count(type, action_type, sort = TRUE) %>%
print(n = Inf)
# A tibble: 1 × 3
type action_type n
<dbl> <chr> <int>
1 24 exercise started 2269
nrow(elo_events)
[1] 2269
n_distinct(elo_events$learner)
[1] 62
summary(elo_events$Elo_rating_student)
Min. 1st Qu. Median Mean 3rd Qu. Max.
1232 1332 1368 1394 1455 1672
All observed non-zero Elo values occur on coding exercise events
(type 24).
Construct the exercise-level data. Elo change is calculated between
consecutive observed exercise events within each learner.
exercise_data <- actions_clean %>%
filter(type == 24) %>%
arrange(learner, time, idUsers_action) %>%
group_by(learner) %>%
mutate(
exercise_number = row_number(),
previous_Elo = lag(Elo_rating_student),
Elo_gain = Elo_rating_student - previous_Elo
) %>%
ungroup()
The first observed exercise event for each learner has no preceding
observed Elo value and therefore has no calculable Elo change.
exercise_data %>%
summarise(
n_exercises = n(),
n_learners = n_distinct(learner),
n_Elo_transitions = sum(!is.na(Elo_gain)),
mean_gain = mean(Elo_gain, na.rm = TRUE),
median_gain = median(Elo_gain, na.rm = TRUE),
sd_gain = sd(Elo_gain, na.rm = TRUE),
min_gain = min(Elo_gain, na.rm = TRUE),
max_gain = max(Elo_gain, na.rm = TRUE),
positive = sum(Elo_gain > 0, na.rm = TRUE),
zero = sum(Elo_gain == 0, na.rm = TRUE),
negative = sum(Elo_gain < 0, na.rm = TRUE)
)
5. Construct preparatory engagement variables
The relevant action types are:
- 22 = coding example
- 23 = coding challenge
- 24 = coding exercise
Preparatory engagement is defined as example and challenge engagement
occurring after the preceding observed exercise and before the current
exercise.
actions_sequence <- actions_clean %>%
arrange(learner, time, idUsers_action) %>%
group_by(learner) %>%
mutate(
exercises_so_far = cumsum(type == 24),
upcoming_exercise = if_else(
type == 24,
exercises_so_far,
exercises_so_far + 1
)
) %>%
ungroup()
Count example and challenge engagement events before each
exercise.
Repeated engagement with the same content is retained as additional
observed engagement.
preparation <- actions_sequence %>%
filter(type %in% c(22, 23)) %>%
group_by(learner, upcoming_exercise) %>%
summarise(
examples_before = sum(type == 22),
challenges_before = sum(type == 23),
.groups = "drop"
) %>%
mutate(
preparatory_before = examples_before + challenges_before
)
Join the preparatory engagement variables to the exercise-level data.
Exercises without observed example or challenge engagement in the
preceding interval receive a count of zero.
exercise_data <- exercise_data %>%
left_join(
preparation,
by = c(
"learner",
"exercise_number" = "upcoming_exercise"
)
) %>%
mutate(
examples_before = replace_na(examples_before, 0),
challenges_before = replace_na(challenges_before, 0),
preparatory_before = replace_na(preparatory_before, 0)
)
6. Final analysis dataset
Exclude the first observed exercise for each learner because it has
no preceding observed exercise from which an Elo change can be
calculated.
Create binary variables used in the robustness analyses.
analysis_data <- exercise_data %>%
filter(!is.na(Elo_gain)) %>%
mutate(
any_examples = examples_before > 0,
any_preparation = preparatory_before > 0,
Elo_increased = Elo_gain > 0
)
Check the final analytical sample.
analysis_sample <- analysis_data %>%
summarise(
exercise_transitions = n(),
learners = n_distinct(learner)
)
print(analysis_sample)
# A tibble: 1 × 2
exercise_transitions learners
<int> <int>
1 2207 57
Five of the 62 learners with observed exercise events have only one
observed exercise and therefore cannot contribute to the analysis of
between-exercise Elo changes.
exercise_counts <- exercise_data %>%
group_by(learner) %>%
summarise(
n_exercises = n(),
n_Elo_transitions = sum(!is.na(Elo_gain)),
.groups = "drop"
) %>%
arrange(n_exercises)
exercise_counts %>%
filter(n_exercises == 1)
7. Descriptive statistics
descriptive_statistics <- analysis_data %>%
summarise(
n_observations = n(),
n_learners = n_distinct(learner),
mean_Elo_gain = mean(Elo_gain),
sd_Elo_gain = sd(Elo_gain),
median_Elo_gain = median(Elo_gain),
min_Elo_gain = min(Elo_gain),
max_Elo_gain = max(Elo_gain),
mean_examples = mean(examples_before),
median_examples = median(examples_before),
max_examples = max(examples_before),
mean_challenges = mean(challenges_before),
median_challenges = median(challenges_before),
max_challenges = max(challenges_before),
mean_preparatory = mean(preparatory_before),
median_preparatory = median(preparatory_before),
max_preparatory = max(preparatory_before),
pct_examples_before = mean(examples_before > 0) * 100,
pct_challenges_before = mean(challenges_before > 0) * 100,
pct_any_preparation = mean(preparatory_before > 0) * 100
)
print(descriptive_statistics)
# A tibble: 1 × 19
n_observations n_learners mean_Elo_gain sd_Elo_gain median_Elo_gain min_Elo_gain max_Elo_gain mean_examples median_examples max_examples mean_challenges median_challenges max_challenges mean_preparatory median_preparatory
<int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int> <int> <dbl> <int> <int> <dbl> <int>
1 2207 57 2.11 9.65 0 -62 156 0.225 0 25 0.0435 0 19 0.269 0
# ℹ 4 more variables: max_preparatory <int>, pct_examples_before <dbl>, pct_challenges_before <dbl>, pct_any_preparation <dbl>
Descriptive statistics by type of preparatory engagement.
preparation_summary <- analysis_data %>%
mutate(
preparation_group = case_when(
examples_before == 0 & challenges_before == 0 ~ "None",
examples_before > 0 & challenges_before == 0 ~ "Examples only",
examples_before == 0 & challenges_before > 0 ~ "Challenges only",
examples_before > 0 & challenges_before > 0 ~ "Examples + challenges"
),
preparation_group = factor(
preparation_group,
levels = c(
"None",
"Examples only",
"Challenges only",
"Examples + challenges"
)
)
) %>%
group_by(preparation_group) %>%
summarise(
n = n(),
mean_Elo_gain = mean(Elo_gain),
median_Elo_gain = median(Elo_gain),
sd_Elo_gain = sd(Elo_gain),
.groups = "drop"
)
print(preparation_summary)
# A tibble: 4 × 5
preparation_group n mean_Elo_gain median_Elo_gain sd_Elo_gain
<fct> <int> <dbl> <dbl> <dbl>
1 None 2043 1.71 0 8.76
2 Examples only 127 5.77 0 9.95
3 Challenges only 11 17.5 0 46.7
4 Examples + challenges 26 9 0 18.5
8. Primary inferential analysis
Because each learner contributes multiple exercise transitions,
linear mixed-effects models are used with a random intercept for
learner.
Exercise number is included as a control for practice volume.
H1a: Example engagement
model_H1a <- lmer(
Elo_gain ~ examples_before + exercise_number + (1 | learner),
data = analysis_data,
REML = FALSE
)
summary(model_H1a)
Linear mixed model fit by maximum likelihood ['lmerMod']
Formula: Elo_gain ~ examples_before + exercise_number + (1 | learner)
Data: analysis_data
AIC BIC logLik -2*log(L) df.resid
16215.0 16243.5 -8102.5 16205.0 2202
Scaled residuals:
Min 1Q Median 3Q Max
-6.6634 -0.2307 -0.1696 -0.1127 15.9841
Random effects:
Groups Name Variance Std.Dev.
learner (Intercept) 3.225 1.796
Residual 88.840 9.426
Number of obs: 2207, groups: learner, 57
Fixed effects:
Estimate Std. Error t value
(Intercept) 2.507127 0.409561 6.121
examples_before 1.153487 0.173649 6.643
exercise_number -0.006196 0.005340 -1.160
Correlation of Fixed Effects:
(Intr) exmpl_
exampls_bfr -0.157
exercs_nmbr -0.441 0.077
H1b: Preparatory engagement
model_H1b <- lmer(
Elo_gain ~ preparatory_before + exercise_number + (1 | learner),
data = analysis_data,
REML = FALSE
)
summary(model_H1b)
Linear mixed model fit by maximum likelihood ['lmerMod']
Formula: Elo_gain ~ preparatory_before + exercise_number + (1 | learner)
Data: analysis_data
AIC BIC logLik -2*log(L) df.resid
16194.1 16222.6 -8092.1 16184.1 2202
Scaled residuals:
Min 1Q Median 3Q Max
-6.6916 -0.2305 -0.1698 -0.1128 15.8619
Random effects:
Groups Name Variance Std.Dev.
learner (Intercept) 2.572 1.604
Residual 88.207 9.392
Number of obs: 2207, groups: learner, 57
Fixed effects:
Estimate Std. Error t value
(Intercept) 2.415102 0.390273 6.188
preparatory_before 1.101194 0.135372 8.135
exercise_number -0.005961 0.005248 -1.136
Correlation of Fixed Effects:
(Intr) prprt_
prprtry_bfr -0.156
exercs_nmbr -0.471 0.079
9. Model diagnostics
Residual diagnostics are examined for the primary mixed-effects
model.
par(mfrow = c(1, 2))
plot(
fitted(model_H1b),
resid(model_H1b),
xlab = "Fitted values",
ylab = "Residuals",
main = "Residuals vs fitted"
)
abline(h = 0, lty = 2)
qqnorm(
resid(model_H1b),
main = "Normal Q-Q plot"
)
qqline(resid(model_H1b))
par(mfrow = c(1, 1))

The residual diagnostics indicate substantial deviation from
normality. The Elo-change distribution also contains a large proportion
of zero changes. Logistic mixed-effects models are therefore used below
as a complementary robustness analysis.
10. Sensitivity analysis
The largest observed preparatory-engagement count is 44 events. A
sensitivity analysis excludes this single extreme observation to assess
its influence on the continuous mixed-model estimates.
analysis_sensitivity <- analysis_data %>%
filter(preparatory_before < 44)
model_H1a_sensitivity <- lmer(
Elo_gain ~ examples_before + exercise_number + (1 | learner),
data = analysis_sensitivity,
REML = FALSE
)
model_H1b_sensitivity <- lmer(
Elo_gain ~ preparatory_before + exercise_number + (1 | learner),
data = analysis_sensitivity,
REML = FALSE
)
summary(model_H1a_sensitivity)
Linear mixed model fit by maximum likelihood ['lmerMod']
Formula: Elo_gain ~ examples_before + exercise_number + (1 | learner)
Data: analysis_sensitivity
AIC BIC logLik -2*log(L) df.resid
16177.2 16205.7 -8083.6 16167.2 2201
Scaled residuals:
Min 1Q Median 3Q Max
-6.7118 -0.2449 -0.1847 -0.1219 16.1169
Random effects:
Groups Name Variance Std.Dev.
learner (Intercept) 2.508 1.584
Residual 87.845 9.373
Number of obs: 2206, groups: learner, 57
Fixed effects:
Estimate Std. Error t value
(Intercept) 2.598682 0.388928 6.682
examples_before 0.674130 0.192743 3.498
exercise_number -0.007559 0.005233 -1.445
Correlation of Fixed Effects:
(Intr) exmpl_
exampls_bfr -0.170
exercs_nmbr -0.474 0.085
summary(model_H1b_sensitivity)
Linear mixed model fit by maximum likelihood ['lmerMod']
Formula: Elo_gain ~ preparatory_before + exercise_number + (1 | learner)
Data: analysis_sensitivity
AIC BIC logLik -2*log(L) df.resid
16173.1 16201.5 -8081.5 16163.1 2201
Scaled residuals:
Min 1Q Median 3Q Max
-6.7167 -0.2427 -0.1822 -0.1216 15.9958
Random effects:
Groups Name Variance Std.Dev.
learner (Intercept) 2.375 1.541
Residual 87.724 9.366
Number of obs: 2206, groups: learner, 57
Fixed effects:
Estimate Std. Error t value
(Intercept) 2.543141 0.385531 6.596
preparatory_before 0.696274 0.171450 4.061
exercise_number -0.007171 0.005216 -1.375
Correlation of Fixed Effects:
(Intr) prprt_
prprtry_bfr -0.180
exercs_nmbr -0.483 0.096
Compare the primary and sensitivity estimates.
fixef(model_H1a)
(Intercept) examples_before exercise_number
2.507127432 1.153486703 -0.006195978
fixef(model_H1a_sensitivity)
(Intercept) examples_before exercise_number
2.598682080 0.674129935 -0.007559097
fixef(model_H1b)
(Intercept) preparatory_before exercise_number
2.415101609 1.101193953 -0.005960955
fixef(model_H1b_sensitivity)
(Intercept) preparatory_before exercise_number
2.543141007 0.696273513 -0.007170756
11. Logistic robustness analysis
The logistic robustness analysis examines whether engagement is
associated with the probability of a positive Elo change.
Here, Elo_increased = TRUE when
Elo_gain > 0. Zero and negative changes are therefore
classified as no positive increase.
Event-count models
model_H1a_logistic <- glmer(
Elo_increased ~ examples_before + exercise_number + (1 | learner),
data = analysis_data,
family = binomial
)
model_H1b_logistic <- glmer(
Elo_increased ~ preparatory_before + exercise_number + (1 | learner),
data = analysis_data,
family = binomial
)
summary(model_H1a_logistic)
Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
Family: binomial ( logit )
Formula: Elo_increased ~ examples_before + exercise_number + (1 | learner)
Data: analysis_data
AIC BIC logLik -2*log(L) df.resid
1582.3 1605.1 -787.2 1574.3 2203
Scaled residuals:
Min 1Q Median 3Q Max
-2.5193 -0.3867 -0.3129 -0.2578 5.0246
Random effects:
Groups Name Variance Std.Dev.
learner (Intercept) 0.4086 0.6392
Number of obs: 2207, groups: learner, 57
Fixed effects:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -2.004839 0.144031 -13.919 < 2e-16 ***
examples_before 0.209197 0.047729 4.383 1.17e-05 ***
exercise_number -0.002765 0.001929 -1.434 0.152
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) exmpl_
exampls_bfr -0.200
exercs_nmbr -0.430 0.099
summary(model_H1b_logistic)
Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
Family: binomial ( logit )
Formula: Elo_increased ~ preparatory_before + exercise_number + (1 | learner)
Data: analysis_data
AIC BIC logLik -2*log(L) df.resid
1579.9 1602.7 -786.0 1571.9 2203
Scaled residuals:
Min 1Q Median 3Q Max
-2.2700 -0.3859 -0.3130 -0.2587 5.0790
Random effects:
Groups Name Variance Std.Dev.
learner (Intercept) 0.3986 0.6313
Number of obs: 2207, groups: learner, 57
Fixed effects:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -2.016464 0.143615 -14.041 < 2e-16 ***
preparatory_before 0.196596 0.042392 4.638 3.52e-06 ***
exercise_number -0.002578 0.001928 -1.337 0.181
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) prprt_
prprtry_bfr -0.212
exercs_nmbr -0.437 0.122
Any engagement versus no engagement
model_H1a_logistic_any <- glmer(
Elo_increased ~ any_examples + exercise_number + (1 | learner),
data = analysis_data,
family = binomial
)
model_H1b_logistic_any <- glmer(
Elo_increased ~ any_preparation + exercise_number + (1 | learner),
data = analysis_data,
family = binomial
)
summary(model_H1a_logistic_any)
Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
Family: binomial ( logit )
Formula: Elo_increased ~ any_examples + exercise_number + (1 | learner)
Data: analysis_data
AIC BIC logLik -2*log(L) df.resid
1564.3 1587.1 -778.2 1556.3 2203
Scaled residuals:
Min 1Q Median 3Q Max
-1.2968 -0.3799 -0.2985 -0.2489 4.9066
Random effects:
Groups Name Variance Std.Dev.
learner (Intercept) 0.4212 0.649
Number of obs: 2207, groups: learner, 57
Fixed effects:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -2.113753 0.148887 -14.197 < 2e-16 ***
any_examplesTRUE 1.315045 0.203150 6.473 9.59e-11 ***
exercise_number -0.002168 0.001934 -1.121 0.262
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) a_TRUE
any_xmpTRUE -0.288
exercs_nmbr -0.430 0.126
summary(model_H1b_logistic_any)
Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
Family: binomial ( logit )
Formula: Elo_increased ~ any_preparation + exercise_number + (1 | learner)
Data: analysis_data
AIC BIC logLik -2*log(L) df.resid
1559.8 1582.6 -775.9 1551.8 2203
Scaled residuals:
Min 1Q Median 3Q Max
-1.3139 -0.3796 -0.2960 -0.2475 4.9103
Random effects:
Groups Name Variance Std.Dev.
learner (Intercept) 0.4215 0.6492
Number of obs: 2207, groups: learner, 57
Fixed effects:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -2.140276 0.149844 -14.283 < 2e-16 ***
any_preparationTRUE 1.354819 0.197975 6.843 7.74e-12 ***
exercise_number -0.001952 0.001933 -1.010 0.313
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) a_TRUE
any_prpTRUE -0.305
exercs_nmbr -0.433 0.139
12. Tables for the paper
Table 1: Analytical sample and Elo changes
table1 <- analysis_data %>%
summarise(
`Exercise transitions` = n(),
`Learners` = n_distinct(learner),
`Mean Elo change` = round(mean(Elo_gain), 2),
`SD Elo change` = round(sd(Elo_gain), 2),
`Median Elo change` = median(Elo_gain),
`Minimum` = min(Elo_gain),
`Maximum` = max(Elo_gain),
`Positive, n (%)` = paste0(
sum(Elo_gain > 0),
" (",
round(mean(Elo_gain > 0) * 100, 1),
"%)"
),
`Zero, n (%)` = paste0(
sum(Elo_gain == 0),
" (",
round(mean(Elo_gain == 0) * 100, 1),
"%)"
),
`Negative, n (%)` = paste0(
sum(Elo_gain < 0),
" (",
round(mean(Elo_gain < 0) * 100, 1),
"%)"
)
)
print(table1)
# A tibble: 1 × 10
`Exercise transitions` Learners `Mean Elo change` `SD Elo change` `Median Elo change` Minimum Maximum `Positive, n (%)` `Zero, n (%)` `Negative, n (%)`
<int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <chr> <chr> <chr>
1 2207 57 2.11 9.65 0 -62 156 272 (12.3%) 1852 (83.9%) 83 (3.8%)
Table 2: Elo change by preparatory engagement
table2 <- analysis_data %>%
mutate(
preparation_group = case_when(
examples_before == 0 & challenges_before == 0 ~ "None",
examples_before > 0 & challenges_before == 0 ~ "Examples only",
examples_before == 0 & challenges_before > 0 ~ "Challenges only",
examples_before > 0 & challenges_before > 0 ~ "Examples + challenges"
),
preparation_group = factor(
preparation_group,
levels = c(
"None",
"Examples only",
"Challenges only",
"Examples + challenges"
)
)
) %>%
group_by(preparation_group) %>%
summarise(
n = n(),
mean_Elo_change = round(mean(Elo_gain), 2),
SD = round(sd(Elo_gain), 2),
median_Elo_change = median(Elo_gain),
.groups = "drop"
)
print(table2)
# A tibble: 4 × 5
preparation_group n mean_Elo_change SD median_Elo_change
<fct> <int> <dbl> <dbl> <dbl>
1 None 2043 1.71 8.76 0
2 Examples only 127 5.77 9.95 0
3 Challenges only 11 17.4 46.7 0
4 Examples + challenges 26 9 18.5 0
Table 3: Primary linear mixed-effects models
Extract coefficients and 95% Wald confidence intervals directly from
the fitted models.
coef_H1a <- as.data.frame(coef(summary(model_H1a)))
coef_H1b <- as.data.frame(coef(summary(model_H1b)))
ci_H1a <- as.data.frame(
confint(
model_H1a,
parm = "beta_",
method = "Wald"
)
)
ci_H1b <- as.data.frame(
confint(
model_H1b,
parm = "beta_",
method = "Wald"
)
)
Create Table 3.
The intercepts are omitted from the paper table so that the table
focuses on the predictors relevant to H1a and H1b.
table3_H1a <- data.frame(
Model = "H1a",
Predictor = rownames(coef_H1a),
Beta = coef_H1a$Estimate,
SE = coef_H1a$`Std. Error`,
t = coef_H1a$`t value`,
CI_low = ci_H1a$`2.5 %`,
CI_high = ci_H1a$`97.5 %`
)
table3_H1b <- data.frame(
Model = "H1b",
Predictor = rownames(coef_H1b),
Beta = coef_H1b$Estimate,
SE = coef_H1b$`Std. Error`,
t = coef_H1b$`t value`,
CI_low = ci_H1b$`2.5 %`,
CI_high = ci_H1b$`97.5 %`
)
table3 <- bind_rows(
table3_H1a,
table3_H1b
) %>%
filter(Predictor != "(Intercept)") %>%
mutate(
Predictor = recode(
Predictor,
examples_before = "Example engagement events",
preparatory_before = "Preparatory engagement events",
exercise_number = "Exercise number"
),
across(
c(Beta, SE, t, CI_low, CI_high),
~ round(.x, 3)
)
)
print(table3)
Model Predictor Beta SE t CI_low CI_high
1 H1a Example engagement events 1.153 0.174 6.643 0.813 1.494
2 H1a Exercise number -0.006 0.005 -1.160 -0.017 0.004
3 H1b Preparatory engagement events 1.101 0.135 8.135 0.836 1.367
4 H1b Exercise number -0.006 0.005 -1.136 -0.016 0.004
Table 4: Logistic robustness analysis
Function for extracting odds ratios, Wald confidence intervals, and
p-values.
extract_logistic_result <- function(model, predictor, label) {
model_summary <- coef(summary(model))
beta <- model_summary[predictor, "Estimate"]
se <- model_summary[predictor, "Std. Error"]
p_value <- model_summary[predictor, "Pr(>|z|)"]
data.frame(
Predictor = label,
OR = exp(beta),
CI_low = exp(beta - 1.96 * se),
CI_high = exp(beta + 1.96 * se),
p = p_value
)
}
Create Table 4.
table4 <- bind_rows(
extract_logistic_result(
model_H1a_logistic,
"examples_before",
"Example-event count"
),
extract_logistic_result(
model_H1b_logistic,
"preparatory_before",
"Preparatory-event count"
),
extract_logistic_result(
model_H1a_logistic_any,
"any_examplesTRUE",
"Any example engagement"
),
extract_logistic_result(
model_H1b_logistic_any,
"any_preparationTRUE",
"Any preparatory engagement"
)
) %>%
mutate(
across(
c(OR, CI_low, CI_high),
~ round(.x, 3)
),
p = if_else(
p < .001,
"< .001",
format(round(p, 3), nsmall = 3)
)
)
print(table4)
Predictor OR CI_low CI_high p
1 Example-event count 1.233 1.123 1.354 < .001
2 Preparatory-event count 1.217 1.120 1.323 < .001
3 Any example engagement 3.725 2.501 5.547 < .001
4 Any preparatory engagement 3.876 2.629 5.714 < .001
13. Figures for the paper
LS0tCnRpdGxlOiAiUHJvVHVTIEFuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIDEuIFBhY2thZ2VzIGFuZCBkYXRhIGltcG9ydAoKYGBge3J9CiMgSW5zdGFsbCBwYWNrYWdlcyBpZiBuZWVkZWQ6CiMgaW5zdGFsbC5wYWNrYWdlcygicmVhZHhsIikKIyBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCiMgaW5zdGFsbC5wYWNrYWdlcygidGlkeXIiKQojIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQojIGluc3RhbGwucGFja2FnZXMoImxtZTQiKQoKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShsbWU0KQpgYGAKCmBgYHtyfQojIENoYW5nZSBmaWxlIHBhdGggaWYgbmVjZXNzYXJ5CmZpbGUgPC0gIi9Vc2Vycy9tZXR0ZS9EZXNrdG9wL05UTlUvTGVhcm5pbmcgYW5hbHl0aWNzL0RhdGFTZXQtUHJvVHVTLnhsc3giCgpsZWFybmVycyA8LSByZWFkX2V4Y2VsKGZpbGUsIHNoZWV0ID0gIkxlYXJuZXJzIikgJT4lCiAgc2VsZWN0KHdoZXJlKH4gIWFsbChpcy5uYSguKSkpKQoKYWN0aW9uc19yYXcgPC0gcmVhZF9leGNlbChmaWxlLCBzaGVldCA9ICJVc2VycyBhY3Rpb25zIikgJT4lCiAgc2VsZWN0KHdoZXJlKH4gIWFsbChpcy5uYSguKSkpKQoKYWN0aW9uX3R5cGVzX3JhdyA8LSByZWFkX2V4Y2VsKGZpbGUsIHNoZWV0ID0gIkFjdGlvbiB0eXBlIikgJT4lCiAgc2VsZWN0KHdoZXJlKH4gIWFsbChpcy5uYSguKSkpKQpgYGAKCiMgMi4gSW5pdGlhbCBkYXRhIGluc3BlY3Rpb24KCmBgYHtyfQpkaW0obGVhcm5lcnMpCmRpbShhY3Rpb25zX3JhdykKCm5hbWVzKGxlYXJuZXJzKQpuYW1lcyhhY3Rpb25zX3JhdykKCm5yb3cobGVhcm5lcnMpCm5fZGlzdGluY3QoYWN0aW9uc19yYXckbGVhcm5lcikKCnN1bShkdXBsaWNhdGVkKGFjdGlvbnNfcmF3KSkKY29sU3Vtcyhpcy5uYShhY3Rpb25zX3JhdykpCmBgYAoKVGhlIExlYXJuZXJzIHNoZWV0IGNvbnRhaW5zIDExNiBsZWFybmVycy4gTm90IGFsbCBsZWFybmVycyBhcmUgcmVwcmVzZW50ZWQgaW4gdGhlIHByb3ZpZGVkIGFjdGlvbiBsb2cuCgpgYGB7cn0KbGVhcm5lcl9hY3Rpb25fY292ZXJhZ2UgPC0gbGVhcm5lcnMgJT4lCiAgbXV0YXRlKGhhc19hY3Rpb25fcmVjb3JkcyA9IGlkICVpbiUgYWN0aW9uc19yYXckbGVhcm5lcikgJT4lCiAgY291bnQoaGFzX2FjdGlvbl9yZWNvcmRzKQoKcHJpbnQobGVhcm5lcl9hY3Rpb25fY292ZXJhZ2UpCmBgYAoKIyAzLiBEYXRhIGNsZWFuaW5nCgpDcmVhdGUgYSBjbGVhbiBsb29rdXAgdGFibGUgZm9yIGFjdGlvbiB0eXBlcy4KCmBgYHtyfQphY3Rpb25fbG9va3VwIDwtIGFjdGlvbl90eXBlc19yYXcgJT4lCiAgc2VsZWN0KGlkYWN0aW9uX3R5cGUsIGFjdGlvbl90eXBlKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGlkYWN0aW9uX3R5cGUpKSAlPiUKICBkaXN0aW5jdChpZGFjdGlvbl90eXBlLCAua2VlcF9hbGwgPSBUUlVFKQoKIyBWZXJpZnkgdGhhdCBlYWNoIGFjdGlvbiB0eXBlIElEIG9jY3VycyBvbmx5IG9uY2UKYWN0aW9uX2xvb2t1cCAlPiUKICBjb3VudChpZGFjdGlvbl90eXBlKSAlPiUKICBmaWx0ZXIobiA+IDEpCmBgYAoKUmVtb3ZlIHRoZSBzaW5nbGUgbWFsZm9ybWVkIGFjdGlvbiByZWNvcmQgd2l0aCBhIG1pc3NpbmcgYWN0aW9uIHR5cGUgYW5kIGFkZCB0aGUgYWN0aW9uIGxhYmVscy4KCmBgYHtyfQphY3Rpb25zX2NsZWFuIDwtIGFjdGlvbnNfcmF3ICU+JQogIGZpbHRlcighaXMubmEodHlwZSkpICU+JQogIGxlZnRfam9pbigKICAgIGFjdGlvbl9sb29rdXAsCiAgICBieSA9IGMoInR5cGUiID0gImlkYWN0aW9uX3R5cGUiKSwKICAgIHJlbGF0aW9uc2hpcCA9ICJtYW55LXRvLW9uZSIKICApICU+JQogIGFycmFuZ2UobGVhcm5lciwgdGltZSwgaWRVc2Vyc19hY3Rpb24pCmBgYAoKVmVyaWZ5IHRoZSBjbGVhbmVkIGRhdGFzZXQuCgpgYGB7cn0KZGF0YV9zdW1tYXJ5IDwtIHRpYmJsZSgKICBtZWFzdXJlID0gYygKICAgICJMZWFybmVycyBpbiBMZWFybmVycyBzaGVldCIsCiAgICAiTGVhcm5lcnMgcmVwcmVzZW50ZWQgaW4gYWN0aW9uIGxvZyIsCiAgICAiUmF3IGFjdGlvbiByZWNvcmRzIiwKICAgICJDbGVhbiBhY3Rpb24gcmVjb3JkcyIKICApLAogIG4gPSBjKAogICAgbnJvdyhsZWFybmVycyksCiAgICBuX2Rpc3RpbmN0KGFjdGlvbnNfcmF3JGxlYXJuZXIpLAogICAgbnJvdyhhY3Rpb25zX3JhdyksCiAgICBucm93KGFjdGlvbnNfY2xlYW4pCiAgKQopCgpwcmludChkYXRhX3N1bW1hcnkpCgojIFZlcmlmeSB0aGF0IGFjdGlvbiBJRHMgYXJlIHVuaXF1ZSBhZnRlciBjbGVhbmluZwpzdG9waWZub3Qoc3VtKGR1cGxpY2F0ZWQoYWN0aW9uc19jbGVhbiRpZFVzZXJzX2FjdGlvbikpID09IDApCmBgYAoKIyA0LiBFbG8gZXZlbnRzIGFuZCBleGVyY2lzZSBkYXRhCgpDaGVjayB3aGljaCBhY3Rpb24gdHlwZXMgY29udGFpbiBub24temVybyBFbG8gdmFsdWVzLgoKYGBge3J9CmVsb19ldmVudHMgPC0gYWN0aW9uc19jbGVhbiAlPiUKICBmaWx0ZXIoRWxvX3JhdGluZ19zdHVkZW50ICE9IDApCgplbG9fZXZlbnRzICU+JQogIGNvdW50KHR5cGUsIGFjdGlvbl90eXBlLCBzb3J0ID0gVFJVRSkgJT4lCiAgcHJpbnQobiA9IEluZikKCm5yb3coZWxvX2V2ZW50cykKbl9kaXN0aW5jdChlbG9fZXZlbnRzJGxlYXJuZXIpCnN1bW1hcnkoZWxvX2V2ZW50cyRFbG9fcmF0aW5nX3N0dWRlbnQpCmBgYAoKQWxsIG9ic2VydmVkIG5vbi16ZXJvIEVsbyB2YWx1ZXMgb2NjdXIgb24gY29kaW5nIGV4ZXJjaXNlIGV2ZW50cyAodHlwZSAyNCkuCgpDb25zdHJ1Y3QgdGhlIGV4ZXJjaXNlLWxldmVsIGRhdGEuIEVsbyBjaGFuZ2UgaXMgY2FsY3VsYXRlZCBiZXR3ZWVuIGNvbnNlY3V0aXZlIG9ic2VydmVkIGV4ZXJjaXNlIGV2ZW50cyB3aXRoaW4gZWFjaCBsZWFybmVyLgoKYGBge3J9CmV4ZXJjaXNlX2RhdGEgPC0gYWN0aW9uc19jbGVhbiAlPiUKICBmaWx0ZXIodHlwZSA9PSAyNCkgJT4lCiAgYXJyYW5nZShsZWFybmVyLCB0aW1lLCBpZFVzZXJzX2FjdGlvbikgJT4lCiAgZ3JvdXBfYnkobGVhcm5lcikgJT4lCiAgbXV0YXRlKAogICAgZXhlcmNpc2VfbnVtYmVyID0gcm93X251bWJlcigpLAogICAgcHJldmlvdXNfRWxvID0gbGFnKEVsb19yYXRpbmdfc3R1ZGVudCksCiAgICBFbG9fZ2FpbiA9IEVsb19yYXRpbmdfc3R1ZGVudCAtIHByZXZpb3VzX0VsbwogICkgJT4lCiAgdW5ncm91cCgpCmBgYAoKVGhlIGZpcnN0IG9ic2VydmVkIGV4ZXJjaXNlIGV2ZW50IGZvciBlYWNoIGxlYXJuZXIgaGFzIG5vIHByZWNlZGluZyBvYnNlcnZlZCBFbG8gdmFsdWUgYW5kIHRoZXJlZm9yZSBoYXMgbm8gY2FsY3VsYWJsZSBFbG8gY2hhbmdlLgoKYGBge3J9CmV4ZXJjaXNlX2RhdGEgJT4lCiAgc3VtbWFyaXNlKAogICAgbl9leGVyY2lzZXMgPSBuKCksCiAgICBuX2xlYXJuZXJzID0gbl9kaXN0aW5jdChsZWFybmVyKSwKICAgIG5fRWxvX3RyYW5zaXRpb25zID0gc3VtKCFpcy5uYShFbG9fZ2FpbikpLAogICAgbWVhbl9nYWluID0gbWVhbihFbG9fZ2FpbiwgbmEucm0gPSBUUlVFKSwKICAgIG1lZGlhbl9nYWluID0gbWVkaWFuKEVsb19nYWluLCBuYS5ybSA9IFRSVUUpLAogICAgc2RfZ2FpbiA9IHNkKEVsb19nYWluLCBuYS5ybSA9IFRSVUUpLAogICAgbWluX2dhaW4gPSBtaW4oRWxvX2dhaW4sIG5hLnJtID0gVFJVRSksCiAgICBtYXhfZ2FpbiA9IG1heChFbG9fZ2FpbiwgbmEucm0gPSBUUlVFKSwKICAgIHBvc2l0aXZlID0gc3VtKEVsb19nYWluID4gMCwgbmEucm0gPSBUUlVFKSwKICAgIHplcm8gPSBzdW0oRWxvX2dhaW4gPT0gMCwgbmEucm0gPSBUUlVFKSwKICAgIG5lZ2F0aXZlID0gc3VtKEVsb19nYWluIDwgMCwgbmEucm0gPSBUUlVFKQogICkKYGBgCgojIDUuIENvbnN0cnVjdCBwcmVwYXJhdG9yeSBlbmdhZ2VtZW50IHZhcmlhYmxlcwoKVGhlIHJlbGV2YW50IGFjdGlvbiB0eXBlcyBhcmU6CgotIDIyID0gY29kaW5nIGV4YW1wbGUKLSAyMyA9IGNvZGluZyBjaGFsbGVuZ2UKLSAyNCA9IGNvZGluZyBleGVyY2lzZQoKUHJlcGFyYXRvcnkgZW5nYWdlbWVudCBpcyBkZWZpbmVkIGFzIGV4YW1wbGUgYW5kIGNoYWxsZW5nZSBlbmdhZ2VtZW50IG9jY3VycmluZyBhZnRlciB0aGUgcHJlY2VkaW5nIG9ic2VydmVkIGV4ZXJjaXNlIGFuZCBiZWZvcmUgdGhlIGN1cnJlbnQgZXhlcmNpc2UuCgpgYGB7cn0KYWN0aW9uc19zZXF1ZW5jZSA8LSBhY3Rpb25zX2NsZWFuICU+JQogIGFycmFuZ2UobGVhcm5lciwgdGltZSwgaWRVc2Vyc19hY3Rpb24pICU+JQogIGdyb3VwX2J5KGxlYXJuZXIpICU+JQogIG11dGF0ZSgKICAgIGV4ZXJjaXNlc19zb19mYXIgPSBjdW1zdW0odHlwZSA9PSAyNCksCiAgICB1cGNvbWluZ19leGVyY2lzZSA9IGlmX2Vsc2UoCiAgICAgIHR5cGUgPT0gMjQsCiAgICAgIGV4ZXJjaXNlc19zb19mYXIsCiAgICAgIGV4ZXJjaXNlc19zb19mYXIgKyAxCiAgICApCiAgKSAlPiUKICB1bmdyb3VwKCkKYGBgCgpDb3VudCBleGFtcGxlIGFuZCBjaGFsbGVuZ2UgZW5nYWdlbWVudCBldmVudHMgYmVmb3JlIGVhY2ggZXhlcmNpc2UuCgpSZXBlYXRlZCBlbmdhZ2VtZW50IHdpdGggdGhlIHNhbWUgY29udGVudCBpcyByZXRhaW5lZCBhcyBhZGRpdGlvbmFsIG9ic2VydmVkIGVuZ2FnZW1lbnQuCgpgYGB7cn0KcHJlcGFyYXRpb24gPC0gYWN0aW9uc19zZXF1ZW5jZSAlPiUKICBmaWx0ZXIodHlwZSAlaW4lIGMoMjIsIDIzKSkgJT4lCiAgZ3JvdXBfYnkobGVhcm5lciwgdXBjb21pbmdfZXhlcmNpc2UpICU+JQogIHN1bW1hcmlzZSgKICAgIGV4YW1wbGVzX2JlZm9yZSA9IHN1bSh0eXBlID09IDIyKSwKICAgIGNoYWxsZW5nZXNfYmVmb3JlID0gc3VtKHR5cGUgPT0gMjMpLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgJT4lCiAgbXV0YXRlKAogICAgcHJlcGFyYXRvcnlfYmVmb3JlID0gZXhhbXBsZXNfYmVmb3JlICsgY2hhbGxlbmdlc19iZWZvcmUKICApCmBgYAoKSm9pbiB0aGUgcHJlcGFyYXRvcnkgZW5nYWdlbWVudCB2YXJpYWJsZXMgdG8gdGhlIGV4ZXJjaXNlLWxldmVsIGRhdGEuIEV4ZXJjaXNlcyB3aXRob3V0IG9ic2VydmVkIGV4YW1wbGUgb3IgY2hhbGxlbmdlIGVuZ2FnZW1lbnQgaW4gdGhlIHByZWNlZGluZyBpbnRlcnZhbCByZWNlaXZlIGEgY291bnQgb2YgemVyby4KCmBgYHtyfQpleGVyY2lzZV9kYXRhIDwtIGV4ZXJjaXNlX2RhdGEgJT4lCiAgbGVmdF9qb2luKAogICAgcHJlcGFyYXRpb24sCiAgICBieSA9IGMoCiAgICAgICJsZWFybmVyIiwKICAgICAgImV4ZXJjaXNlX251bWJlciIgPSAidXBjb21pbmdfZXhlcmNpc2UiCiAgICApCiAgKSAlPiUKICBtdXRhdGUoCiAgICBleGFtcGxlc19iZWZvcmUgPSByZXBsYWNlX25hKGV4YW1wbGVzX2JlZm9yZSwgMCksCiAgICBjaGFsbGVuZ2VzX2JlZm9yZSA9IHJlcGxhY2VfbmEoY2hhbGxlbmdlc19iZWZvcmUsIDApLAogICAgcHJlcGFyYXRvcnlfYmVmb3JlID0gcmVwbGFjZV9uYShwcmVwYXJhdG9yeV9iZWZvcmUsIDApCiAgKQpgYGAKCiMgNi4gRmluYWwgYW5hbHlzaXMgZGF0YXNldAoKRXhjbHVkZSB0aGUgZmlyc3Qgb2JzZXJ2ZWQgZXhlcmNpc2UgZm9yIGVhY2ggbGVhcm5lciBiZWNhdXNlIGl0IGhhcyBubyBwcmVjZWRpbmcgb2JzZXJ2ZWQgZXhlcmNpc2UgZnJvbSB3aGljaCBhbiBFbG8gY2hhbmdlIGNhbiBiZSBjYWxjdWxhdGVkLgoKQ3JlYXRlIGJpbmFyeSB2YXJpYWJsZXMgdXNlZCBpbiB0aGUgcm9idXN0bmVzcyBhbmFseXNlcy4KCmBgYHtyfQphbmFseXNpc19kYXRhIDwtIGV4ZXJjaXNlX2RhdGEgJT4lCiAgZmlsdGVyKCFpcy5uYShFbG9fZ2FpbikpICU+JQogIG11dGF0ZSgKICAgIGFueV9leGFtcGxlcyA9IGV4YW1wbGVzX2JlZm9yZSA+IDAsCiAgICBhbnlfcHJlcGFyYXRpb24gPSBwcmVwYXJhdG9yeV9iZWZvcmUgPiAwLAogICAgRWxvX2luY3JlYXNlZCA9IEVsb19nYWluID4gMAogICkKYGBgCgpDaGVjayB0aGUgZmluYWwgYW5hbHl0aWNhbCBzYW1wbGUuCgpgYGB7cn0KYW5hbHlzaXNfc2FtcGxlIDwtIGFuYWx5c2lzX2RhdGEgJT4lCiAgc3VtbWFyaXNlKAogICAgZXhlcmNpc2VfdHJhbnNpdGlvbnMgPSBuKCksCiAgICBsZWFybmVycyA9IG5fZGlzdGluY3QobGVhcm5lcikKICApCgpwcmludChhbmFseXNpc19zYW1wbGUpCmBgYAoKRml2ZSBvZiB0aGUgNjIgbGVhcm5lcnMgd2l0aCBvYnNlcnZlZCBleGVyY2lzZSBldmVudHMgaGF2ZSBvbmx5IG9uZSBvYnNlcnZlZCBleGVyY2lzZSBhbmQgdGhlcmVmb3JlIGNhbm5vdCBjb250cmlidXRlIHRvIHRoZSBhbmFseXNpcyBvZiBiZXR3ZWVuLWV4ZXJjaXNlIEVsbyBjaGFuZ2VzLgoKYGBge3J9CmV4ZXJjaXNlX2NvdW50cyA8LSBleGVyY2lzZV9kYXRhICU+JQogIGdyb3VwX2J5KGxlYXJuZXIpICU+JQogIHN1bW1hcmlzZSgKICAgIG5fZXhlcmNpc2VzID0gbigpLAogICAgbl9FbG9fdHJhbnNpdGlvbnMgPSBzdW0oIWlzLm5hKEVsb19nYWluKSksCiAgICAuZ3JvdXBzID0gImRyb3AiCiAgKSAlPiUKICBhcnJhbmdlKG5fZXhlcmNpc2VzKQoKZXhlcmNpc2VfY291bnRzICU+JQogIGZpbHRlcihuX2V4ZXJjaXNlcyA9PSAxKQpgYGAKCiMgNy4gRGVzY3JpcHRpdmUgc3RhdGlzdGljcwoKYGBge3J9CmRlc2NyaXB0aXZlX3N0YXRpc3RpY3MgPC0gYW5hbHlzaXNfZGF0YSAlPiUKICBzdW1tYXJpc2UoCiAgICBuX29ic2VydmF0aW9ucyA9IG4oKSwKICAgIG5fbGVhcm5lcnMgPSBuX2Rpc3RpbmN0KGxlYXJuZXIpLAoKICAgIG1lYW5fRWxvX2dhaW4gPSBtZWFuKEVsb19nYWluKSwKICAgIHNkX0Vsb19nYWluID0gc2QoRWxvX2dhaW4pLAogICAgbWVkaWFuX0Vsb19nYWluID0gbWVkaWFuKEVsb19nYWluKSwKICAgIG1pbl9FbG9fZ2FpbiA9IG1pbihFbG9fZ2FpbiksCiAgICBtYXhfRWxvX2dhaW4gPSBtYXgoRWxvX2dhaW4pLAoKICAgIG1lYW5fZXhhbXBsZXMgPSBtZWFuKGV4YW1wbGVzX2JlZm9yZSksCiAgICBtZWRpYW5fZXhhbXBsZXMgPSBtZWRpYW4oZXhhbXBsZXNfYmVmb3JlKSwKICAgIG1heF9leGFtcGxlcyA9IG1heChleGFtcGxlc19iZWZvcmUpLAoKICAgIG1lYW5fY2hhbGxlbmdlcyA9IG1lYW4oY2hhbGxlbmdlc19iZWZvcmUpLAogICAgbWVkaWFuX2NoYWxsZW5nZXMgPSBtZWRpYW4oY2hhbGxlbmdlc19iZWZvcmUpLAogICAgbWF4X2NoYWxsZW5nZXMgPSBtYXgoY2hhbGxlbmdlc19iZWZvcmUpLAoKICAgIG1lYW5fcHJlcGFyYXRvcnkgPSBtZWFuKHByZXBhcmF0b3J5X2JlZm9yZSksCiAgICBtZWRpYW5fcHJlcGFyYXRvcnkgPSBtZWRpYW4ocHJlcGFyYXRvcnlfYmVmb3JlKSwKICAgIG1heF9wcmVwYXJhdG9yeSA9IG1heChwcmVwYXJhdG9yeV9iZWZvcmUpLAoKICAgIHBjdF9leGFtcGxlc19iZWZvcmUgPSBtZWFuKGV4YW1wbGVzX2JlZm9yZSA+IDApICogMTAwLAogICAgcGN0X2NoYWxsZW5nZXNfYmVmb3JlID0gbWVhbihjaGFsbGVuZ2VzX2JlZm9yZSA+IDApICogMTAwLAogICAgcGN0X2FueV9wcmVwYXJhdGlvbiA9IG1lYW4ocHJlcGFyYXRvcnlfYmVmb3JlID4gMCkgKiAxMDAKICApCgpwcmludChkZXNjcmlwdGl2ZV9zdGF0aXN0aWNzKQpgYGAKCkRlc2NyaXB0aXZlIHN0YXRpc3RpY3MgYnkgdHlwZSBvZiBwcmVwYXJhdG9yeSBlbmdhZ2VtZW50LgoKYGBge3J9CnByZXBhcmF0aW9uX3N1bW1hcnkgPC0gYW5hbHlzaXNfZGF0YSAlPiUKICBtdXRhdGUoCiAgICBwcmVwYXJhdGlvbl9ncm91cCA9IGNhc2Vfd2hlbigKICAgICAgZXhhbXBsZXNfYmVmb3JlID09IDAgJiBjaGFsbGVuZ2VzX2JlZm9yZSA9PSAwIH4gIk5vbmUiLAogICAgICBleGFtcGxlc19iZWZvcmUgPiAwICYgY2hhbGxlbmdlc19iZWZvcmUgPT0gMCB+ICJFeGFtcGxlcyBvbmx5IiwKICAgICAgZXhhbXBsZXNfYmVmb3JlID09IDAgJiBjaGFsbGVuZ2VzX2JlZm9yZSA+IDAgfiAiQ2hhbGxlbmdlcyBvbmx5IiwKICAgICAgZXhhbXBsZXNfYmVmb3JlID4gMCAmIGNoYWxsZW5nZXNfYmVmb3JlID4gMCB+ICJFeGFtcGxlcyArIGNoYWxsZW5nZXMiCiAgICApLAogICAgcHJlcGFyYXRpb25fZ3JvdXAgPSBmYWN0b3IoCiAgICAgIHByZXBhcmF0aW9uX2dyb3VwLAogICAgICBsZXZlbHMgPSBjKAogICAgICAgICJOb25lIiwKICAgICAgICAiRXhhbXBsZXMgb25seSIsCiAgICAgICAgIkNoYWxsZW5nZXMgb25seSIsCiAgICAgICAgIkV4YW1wbGVzICsgY2hhbGxlbmdlcyIKICAgICAgKQogICAgKQogICkgJT4lCiAgZ3JvdXBfYnkocHJlcGFyYXRpb25fZ3JvdXApICU+JQogIHN1bW1hcmlzZSgKICAgIG4gPSBuKCksCiAgICBtZWFuX0Vsb19nYWluID0gbWVhbihFbG9fZ2FpbiksCiAgICBtZWRpYW5fRWxvX2dhaW4gPSBtZWRpYW4oRWxvX2dhaW4pLAogICAgc2RfRWxvX2dhaW4gPSBzZChFbG9fZ2FpbiksCiAgICAuZ3JvdXBzID0gImRyb3AiCiAgKQoKcHJpbnQocHJlcGFyYXRpb25fc3VtbWFyeSkKYGBgCgojIDguIFByaW1hcnkgaW5mZXJlbnRpYWwgYW5hbHlzaXMKCkJlY2F1c2UgZWFjaCBsZWFybmVyIGNvbnRyaWJ1dGVzIG11bHRpcGxlIGV4ZXJjaXNlIHRyYW5zaXRpb25zLCBsaW5lYXIgbWl4ZWQtZWZmZWN0cyBtb2RlbHMgYXJlIHVzZWQgd2l0aCBhIHJhbmRvbSBpbnRlcmNlcHQgZm9yIGxlYXJuZXIuCgpFeGVyY2lzZSBudW1iZXIgaXMgaW5jbHVkZWQgYXMgYSBjb250cm9sIGZvciBwcmFjdGljZSB2b2x1bWUuCgojIyBIMWE6IEV4YW1wbGUgZW5nYWdlbWVudAoKYGBge3J9Cm1vZGVsX0gxYSA8LSBsbWVyKAogIEVsb19nYWluIH4gZXhhbXBsZXNfYmVmb3JlICsgZXhlcmNpc2VfbnVtYmVyICsgKDEgfCBsZWFybmVyKSwKICBkYXRhID0gYW5hbHlzaXNfZGF0YSwKICBSRU1MID0gRkFMU0UKKQoKc3VtbWFyeShtb2RlbF9IMWEpCmBgYAoKIyMgSDFiOiBQcmVwYXJhdG9yeSBlbmdhZ2VtZW50CgpgYGB7cn0KbW9kZWxfSDFiIDwtIGxtZXIoCiAgRWxvX2dhaW4gfiBwcmVwYXJhdG9yeV9iZWZvcmUgKyBleGVyY2lzZV9udW1iZXIgKyAoMSB8IGxlYXJuZXIpLAogIGRhdGEgPSBhbmFseXNpc19kYXRhLAogIFJFTUwgPSBGQUxTRQopCgpzdW1tYXJ5KG1vZGVsX0gxYikKYGBgCgojIDkuIE1vZGVsIGRpYWdub3N0aWNzCgpSZXNpZHVhbCBkaWFnbm9zdGljcyBhcmUgZXhhbWluZWQgZm9yIHRoZSBwcmltYXJ5IG1peGVkLWVmZmVjdHMgbW9kZWwuCgpgYGB7cn0KcGFyKG1mcm93ID0gYygxLCAyKSkKCnBsb3QoCiAgZml0dGVkKG1vZGVsX0gxYiksCiAgcmVzaWQobW9kZWxfSDFiKSwKICB4bGFiID0gIkZpdHRlZCB2YWx1ZXMiLAogIHlsYWIgPSAiUmVzaWR1YWxzIiwKICBtYWluID0gIlJlc2lkdWFscyB2cyBmaXR0ZWQiCikKCmFibGluZShoID0gMCwgbHR5ID0gMikKCnFxbm9ybSgKICByZXNpZChtb2RlbF9IMWIpLAogIG1haW4gPSAiTm9ybWFsIFEtUSBwbG90IgopCgpxcWxpbmUocmVzaWQobW9kZWxfSDFiKSkKCnBhcihtZnJvdyA9IGMoMSwgMSkpCmBgYAoKVGhlIHJlc2lkdWFsIGRpYWdub3N0aWNzIGluZGljYXRlIHN1YnN0YW50aWFsIGRldmlhdGlvbiBmcm9tIG5vcm1hbGl0eS4gVGhlIEVsby1jaGFuZ2UgZGlzdHJpYnV0aW9uIGFsc28gY29udGFpbnMgYSBsYXJnZSBwcm9wb3J0aW9uIG9mIHplcm8gY2hhbmdlcy4gTG9naXN0aWMgbWl4ZWQtZWZmZWN0cyBtb2RlbHMgYXJlIHRoZXJlZm9yZSB1c2VkIGJlbG93IGFzIGEgY29tcGxlbWVudGFyeSByb2J1c3RuZXNzIGFuYWx5c2lzLgoKIyAxMC4gU2Vuc2l0aXZpdHkgYW5hbHlzaXMKClRoZSBsYXJnZXN0IG9ic2VydmVkIHByZXBhcmF0b3J5LWVuZ2FnZW1lbnQgY291bnQgaXMgNDQgZXZlbnRzLiBBIHNlbnNpdGl2aXR5IGFuYWx5c2lzIGV4Y2x1ZGVzIHRoaXMgc2luZ2xlIGV4dHJlbWUgb2JzZXJ2YXRpb24gdG8gYXNzZXNzIGl0cyBpbmZsdWVuY2Ugb24gdGhlIGNvbnRpbnVvdXMgbWl4ZWQtbW9kZWwgZXN0aW1hdGVzLgoKYGBge3J9CmFuYWx5c2lzX3NlbnNpdGl2aXR5IDwtIGFuYWx5c2lzX2RhdGEgJT4lCiAgZmlsdGVyKHByZXBhcmF0b3J5X2JlZm9yZSA8IDQ0KQoKbW9kZWxfSDFhX3NlbnNpdGl2aXR5IDwtIGxtZXIoCiAgRWxvX2dhaW4gfiBleGFtcGxlc19iZWZvcmUgKyBleGVyY2lzZV9udW1iZXIgKyAoMSB8IGxlYXJuZXIpLAogIGRhdGEgPSBhbmFseXNpc19zZW5zaXRpdml0eSwKICBSRU1MID0gRkFMU0UKKQoKbW9kZWxfSDFiX3NlbnNpdGl2aXR5IDwtIGxtZXIoCiAgRWxvX2dhaW4gfiBwcmVwYXJhdG9yeV9iZWZvcmUgKyBleGVyY2lzZV9udW1iZXIgKyAoMSB8IGxlYXJuZXIpLAogIGRhdGEgPSBhbmFseXNpc19zZW5zaXRpdml0eSwKICBSRU1MID0gRkFMU0UKKQoKc3VtbWFyeShtb2RlbF9IMWFfc2Vuc2l0aXZpdHkpCnN1bW1hcnkobW9kZWxfSDFiX3NlbnNpdGl2aXR5KQpgYGAKCkNvbXBhcmUgdGhlIHByaW1hcnkgYW5kIHNlbnNpdGl2aXR5IGVzdGltYXRlcy4KCmBgYHtyfQpmaXhlZihtb2RlbF9IMWEpCmZpeGVmKG1vZGVsX0gxYV9zZW5zaXRpdml0eSkKCmZpeGVmKG1vZGVsX0gxYikKZml4ZWYobW9kZWxfSDFiX3NlbnNpdGl2aXR5KQpgYGAKCiMgMTEuIExvZ2lzdGljIHJvYnVzdG5lc3MgYW5hbHlzaXMKClRoZSBsb2dpc3RpYyByb2J1c3RuZXNzIGFuYWx5c2lzIGV4YW1pbmVzIHdoZXRoZXIgZW5nYWdlbWVudCBpcyBhc3NvY2lhdGVkIHdpdGggdGhlIHByb2JhYmlsaXR5IG9mIGEgcG9zaXRpdmUgRWxvIGNoYW5nZS4KCkhlcmUsIGBFbG9faW5jcmVhc2VkID0gVFJVRWAgd2hlbiBgRWxvX2dhaW4gPiAwYC4gWmVybyBhbmQgbmVnYXRpdmUgY2hhbmdlcyBhcmUgdGhlcmVmb3JlIGNsYXNzaWZpZWQgYXMgbm8gcG9zaXRpdmUgaW5jcmVhc2UuCgojIyBFdmVudC1jb3VudCBtb2RlbHMKCmBgYHtyfQptb2RlbF9IMWFfbG9naXN0aWMgPC0gZ2xtZXIoCiAgRWxvX2luY3JlYXNlZCB+IGV4YW1wbGVzX2JlZm9yZSArIGV4ZXJjaXNlX251bWJlciArICgxIHwgbGVhcm5lciksCiAgZGF0YSA9IGFuYWx5c2lzX2RhdGEsCiAgZmFtaWx5ID0gYmlub21pYWwKKQoKbW9kZWxfSDFiX2xvZ2lzdGljIDwtIGdsbWVyKAogIEVsb19pbmNyZWFzZWQgfiBwcmVwYXJhdG9yeV9iZWZvcmUgKyBleGVyY2lzZV9udW1iZXIgKyAoMSB8IGxlYXJuZXIpLAogIGRhdGEgPSBhbmFseXNpc19kYXRhLAogIGZhbWlseSA9IGJpbm9taWFsCikKCnN1bW1hcnkobW9kZWxfSDFhX2xvZ2lzdGljKQpzdW1tYXJ5KG1vZGVsX0gxYl9sb2dpc3RpYykKYGBgCgojIyBBbnkgZW5nYWdlbWVudCB2ZXJzdXMgbm8gZW5nYWdlbWVudAoKYGBge3J9Cm1vZGVsX0gxYV9sb2dpc3RpY19hbnkgPC0gZ2xtZXIoCiAgRWxvX2luY3JlYXNlZCB+IGFueV9leGFtcGxlcyArIGV4ZXJjaXNlX251bWJlciArICgxIHwgbGVhcm5lciksCiAgZGF0YSA9IGFuYWx5c2lzX2RhdGEsCiAgZmFtaWx5ID0gYmlub21pYWwKKQoKbW9kZWxfSDFiX2xvZ2lzdGljX2FueSA8LSBnbG1lcigKICBFbG9faW5jcmVhc2VkIH4gYW55X3ByZXBhcmF0aW9uICsgZXhlcmNpc2VfbnVtYmVyICsgKDEgfCBsZWFybmVyKSwKICBkYXRhID0gYW5hbHlzaXNfZGF0YSwKICBmYW1pbHkgPSBiaW5vbWlhbAopCgpzdW1tYXJ5KG1vZGVsX0gxYV9sb2dpc3RpY19hbnkpCnN1bW1hcnkobW9kZWxfSDFiX2xvZ2lzdGljX2FueSkKYGBgCgojIDEyLiBUYWJsZXMgZm9yIHRoZSBwYXBlcgoKIyMgVGFibGUgMTogQW5hbHl0aWNhbCBzYW1wbGUgYW5kIEVsbyBjaGFuZ2VzCgpgYGB7cn0KdGFibGUxIDwtIGFuYWx5c2lzX2RhdGEgJT4lCiAgc3VtbWFyaXNlKAogICAgYEV4ZXJjaXNlIHRyYW5zaXRpb25zYCA9IG4oKSwKICAgIGBMZWFybmVyc2AgPSBuX2Rpc3RpbmN0KGxlYXJuZXIpLAogICAgYE1lYW4gRWxvIGNoYW5nZWAgPSByb3VuZChtZWFuKEVsb19nYWluKSwgMiksCiAgICBgU0QgRWxvIGNoYW5nZWAgPSByb3VuZChzZChFbG9fZ2FpbiksIDIpLAogICAgYE1lZGlhbiBFbG8gY2hhbmdlYCA9IG1lZGlhbihFbG9fZ2FpbiksCiAgICBgTWluaW11bWAgPSBtaW4oRWxvX2dhaW4pLAogICAgYE1heGltdW1gID0gbWF4KEVsb19nYWluKSwKICAgIGBQb3NpdGl2ZSwgbiAoJSlgID0gcGFzdGUwKAogICAgICBzdW0oRWxvX2dhaW4gPiAwKSwKICAgICAgIiAoIiwKICAgICAgcm91bmQobWVhbihFbG9fZ2FpbiA+IDApICogMTAwLCAxKSwKICAgICAgIiUpIgogICAgKSwKICAgIGBaZXJvLCBuICglKWAgPSBwYXN0ZTAoCiAgICAgIHN1bShFbG9fZ2FpbiA9PSAwKSwKICAgICAgIiAoIiwKICAgICAgcm91bmQobWVhbihFbG9fZ2FpbiA9PSAwKSAqIDEwMCwgMSksCiAgICAgICIlKSIKICAgICksCiAgICBgTmVnYXRpdmUsIG4gKCUpYCA9IHBhc3RlMCgKICAgICAgc3VtKEVsb19nYWluIDwgMCksCiAgICAgICIgKCIsCiAgICAgIHJvdW5kKG1lYW4oRWxvX2dhaW4gPCAwKSAqIDEwMCwgMSksCiAgICAgICIlKSIKICAgICkKICApCgpwcmludCh0YWJsZTEpCmBgYAoKIyMgVGFibGUgMjogRWxvIGNoYW5nZSBieSBwcmVwYXJhdG9yeSBlbmdhZ2VtZW50CgpgYGB7cn0KdGFibGUyIDwtIGFuYWx5c2lzX2RhdGEgJT4lCiAgbXV0YXRlKAogICAgcHJlcGFyYXRpb25fZ3JvdXAgPSBjYXNlX3doZW4oCiAgICAgIGV4YW1wbGVzX2JlZm9yZSA9PSAwICYgY2hhbGxlbmdlc19iZWZvcmUgPT0gMCB+ICJOb25lIiwKICAgICAgZXhhbXBsZXNfYmVmb3JlID4gMCAmIGNoYWxsZW5nZXNfYmVmb3JlID09IDAgfiAiRXhhbXBsZXMgb25seSIsCiAgICAgIGV4YW1wbGVzX2JlZm9yZSA9PSAwICYgY2hhbGxlbmdlc19iZWZvcmUgPiAwIH4gIkNoYWxsZW5nZXMgb25seSIsCiAgICAgIGV4YW1wbGVzX2JlZm9yZSA+IDAgJiBjaGFsbGVuZ2VzX2JlZm9yZSA+IDAgfiAiRXhhbXBsZXMgKyBjaGFsbGVuZ2VzIgogICAgKSwKICAgIHByZXBhcmF0aW9uX2dyb3VwID0gZmFjdG9yKAogICAgICBwcmVwYXJhdGlvbl9ncm91cCwKICAgICAgbGV2ZWxzID0gYygKICAgICAgICAiTm9uZSIsCiAgICAgICAgIkV4YW1wbGVzIG9ubHkiLAogICAgICAgICJDaGFsbGVuZ2VzIG9ubHkiLAogICAgICAgICJFeGFtcGxlcyArIGNoYWxsZW5nZXMiCiAgICAgICkKICAgICkKICApICU+JQogIGdyb3VwX2J5KHByZXBhcmF0aW9uX2dyb3VwKSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgbWVhbl9FbG9fY2hhbmdlID0gcm91bmQobWVhbihFbG9fZ2FpbiksIDIpLAogICAgU0QgPSByb3VuZChzZChFbG9fZ2FpbiksIDIpLAogICAgbWVkaWFuX0Vsb19jaGFuZ2UgPSBtZWRpYW4oRWxvX2dhaW4pLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkKCnByaW50KHRhYmxlMikKYGBgCgojIyBUYWJsZSAzOiBQcmltYXJ5IGxpbmVhciBtaXhlZC1lZmZlY3RzIG1vZGVscwoKRXh0cmFjdCBjb2VmZmljaWVudHMgYW5kIDk1JSBXYWxkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGRpcmVjdGx5IGZyb20gdGhlIGZpdHRlZCBtb2RlbHMuCgpgYGB7cn0KY29lZl9IMWEgPC0gYXMuZGF0YS5mcmFtZShjb2VmKHN1bW1hcnkobW9kZWxfSDFhKSkpCmNvZWZfSDFiIDwtIGFzLmRhdGEuZnJhbWUoY29lZihzdW1tYXJ5KG1vZGVsX0gxYikpKQoKY2lfSDFhIDwtIGFzLmRhdGEuZnJhbWUoCiAgY29uZmludCgKICAgIG1vZGVsX0gxYSwKICAgIHBhcm0gPSAiYmV0YV8iLAogICAgbWV0aG9kID0gIldhbGQiCiAgKQopCgpjaV9IMWIgPC0gYXMuZGF0YS5mcmFtZSgKICBjb25maW50KAogICAgbW9kZWxfSDFiLAogICAgcGFybSA9ICJiZXRhXyIsCiAgICBtZXRob2QgPSAiV2FsZCIKICApCikKYGBgCgpDcmVhdGUgVGFibGUgMy4KClRoZSBpbnRlcmNlcHRzIGFyZSBvbWl0dGVkIGZyb20gdGhlIHBhcGVyIHRhYmxlIHNvIHRoYXQgdGhlIHRhYmxlIGZvY3VzZXMgb24gdGhlIHByZWRpY3RvcnMgcmVsZXZhbnQgdG8gSDFhIGFuZCBIMWIuCgpgYGB7cn0KdGFibGUzX0gxYSA8LSBkYXRhLmZyYW1lKAogIE1vZGVsID0gIkgxYSIsCiAgUHJlZGljdG9yID0gcm93bmFtZXMoY29lZl9IMWEpLAogIEJldGEgPSBjb2VmX0gxYSRFc3RpbWF0ZSwKICBTRSA9IGNvZWZfSDFhJGBTdGQuIEVycm9yYCwKICB0ID0gY29lZl9IMWEkYHQgdmFsdWVgLAogIENJX2xvdyA9IGNpX0gxYSRgMi41ICVgLAogIENJX2hpZ2ggPSBjaV9IMWEkYDk3LjUgJWAKKQoKdGFibGUzX0gxYiA8LSBkYXRhLmZyYW1lKAogIE1vZGVsID0gIkgxYiIsCiAgUHJlZGljdG9yID0gcm93bmFtZXMoY29lZl9IMWIpLAogIEJldGEgPSBjb2VmX0gxYiRFc3RpbWF0ZSwKICBTRSA9IGNvZWZfSDFiJGBTdGQuIEVycm9yYCwKICB0ID0gY29lZl9IMWIkYHQgdmFsdWVgLAogIENJX2xvdyA9IGNpX0gxYiRgMi41ICVgLAogIENJX2hpZ2ggPSBjaV9IMWIkYDk3LjUgJWAKKQoKdGFibGUzIDwtIGJpbmRfcm93cygKICB0YWJsZTNfSDFhLAogIHRhYmxlM19IMWIKKSAlPiUKICBmaWx0ZXIoUHJlZGljdG9yICE9ICIoSW50ZXJjZXB0KSIpICU+JQogIG11dGF0ZSgKICAgIFByZWRpY3RvciA9IHJlY29kZSgKICAgICAgUHJlZGljdG9yLAogICAgICBleGFtcGxlc19iZWZvcmUgPSAiRXhhbXBsZSBlbmdhZ2VtZW50IGV2ZW50cyIsCiAgICAgIHByZXBhcmF0b3J5X2JlZm9yZSA9ICJQcmVwYXJhdG9yeSBlbmdhZ2VtZW50IGV2ZW50cyIsCiAgICAgIGV4ZXJjaXNlX251bWJlciA9ICJFeGVyY2lzZSBudW1iZXIiCiAgICApLAogICAgYWNyb3NzKAogICAgICBjKEJldGEsIFNFLCB0LCBDSV9sb3csIENJX2hpZ2gpLAogICAgICB+IHJvdW5kKC54LCAzKQogICAgKQogICkKCnByaW50KHRhYmxlMykKYGBgCgojIyBUYWJsZSA0OiBMb2dpc3RpYyByb2J1c3RuZXNzIGFuYWx5c2lzCgpGdW5jdGlvbiBmb3IgZXh0cmFjdGluZyBvZGRzIHJhdGlvcywgV2FsZCBjb25maWRlbmNlIGludGVydmFscywgYW5kIHAtdmFsdWVzLgoKYGBge3J9CmV4dHJhY3RfbG9naXN0aWNfcmVzdWx0IDwtIGZ1bmN0aW9uKG1vZGVsLCBwcmVkaWN0b3IsIGxhYmVsKSB7CgogIG1vZGVsX3N1bW1hcnkgPC0gY29lZihzdW1tYXJ5KG1vZGVsKSkKCiAgYmV0YSA8LSBtb2RlbF9zdW1tYXJ5W3ByZWRpY3RvciwgIkVzdGltYXRlIl0KICBzZSA8LSBtb2RlbF9zdW1tYXJ5W3ByZWRpY3RvciwgIlN0ZC4gRXJyb3IiXQogIHBfdmFsdWUgPC0gbW9kZWxfc3VtbWFyeVtwcmVkaWN0b3IsICJQcig+fHp8KSJdCgogIGRhdGEuZnJhbWUoCiAgICBQcmVkaWN0b3IgPSBsYWJlbCwKICAgIE9SID0gZXhwKGJldGEpLAogICAgQ0lfbG93ID0gZXhwKGJldGEgLSAxLjk2ICogc2UpLAogICAgQ0lfaGlnaCA9IGV4cChiZXRhICsgMS45NiAqIHNlKSwKICAgIHAgPSBwX3ZhbHVlCiAgKQp9CmBgYAoKQ3JlYXRlIFRhYmxlIDQuCgpgYGB7cn0KdGFibGU0IDwtIGJpbmRfcm93cygKICBleHRyYWN0X2xvZ2lzdGljX3Jlc3VsdCgKICAgIG1vZGVsX0gxYV9sb2dpc3RpYywKICAgICJleGFtcGxlc19iZWZvcmUiLAogICAgIkV4YW1wbGUtZXZlbnQgY291bnQiCiAgKSwKICBleHRyYWN0X2xvZ2lzdGljX3Jlc3VsdCgKICAgIG1vZGVsX0gxYl9sb2dpc3RpYywKICAgICJwcmVwYXJhdG9yeV9iZWZvcmUiLAogICAgIlByZXBhcmF0b3J5LWV2ZW50IGNvdW50IgogICksCiAgZXh0cmFjdF9sb2dpc3RpY19yZXN1bHQoCiAgICBtb2RlbF9IMWFfbG9naXN0aWNfYW55LAogICAgImFueV9leGFtcGxlc1RSVUUiLAogICAgIkFueSBleGFtcGxlIGVuZ2FnZW1lbnQiCiAgKSwKICBleHRyYWN0X2xvZ2lzdGljX3Jlc3VsdCgKICAgIG1vZGVsX0gxYl9sb2dpc3RpY19hbnksCiAgICAiYW55X3ByZXBhcmF0aW9uVFJVRSIsCiAgICAiQW55IHByZXBhcmF0b3J5IGVuZ2FnZW1lbnQiCiAgKQopICU+JQogIG11dGF0ZSgKICAgIGFjcm9zcygKICAgICAgYyhPUiwgQ0lfbG93LCBDSV9oaWdoKSwKICAgICAgfiByb3VuZCgueCwgMykKICAgICksCiAgICBwID0gaWZfZWxzZSgKICAgICAgcCA8IC4wMDEsCiAgICAgICI8IC4wMDEiLAogICAgICBmb3JtYXQocm91bmQocCwgMyksIG5zbWFsbCA9IDMpCiAgICApCiAgKQoKcHJpbnQodGFibGU0KQpgYGAKCiMgMTMuIEZpZ3VyZXMgZm9yIHRoZSBwYXBlcgoKIyMgRmlndXJlIDE6IERpc3RyaWJ1dGlvbiBvZiBFbG8gcmF0aW5nIGNoYW5nZXMKCmBgYHtyfQpnZ3Bsb3QoYW5hbHlzaXNfZGF0YSwgYWVzKHggPSBFbG9fZ2FpbikpICsKICBnZW9tX2hpc3RvZ3JhbSgKICAgIGJpbndpZHRoID0gNSwKICAgIGJvdW5kYXJ5ID0gMCwKICAgIGNvbG9yID0gImJsYWNrIgogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgRWxvIHJhdGluZyBjaGFuZ2VzIiwKICAgIHN1YnRpdGxlID0gcGFzdGUwKAogICAgICAiQ2hhbmdlcyBiZXR3ZWVuIGNvbnNlY3V0aXZlIG9ic2VydmVkIGV4ZXJjaXNlIGV2ZW50cyAoTiA9ICIsCiAgICAgIG5yb3coYW5hbHlzaXNfZGF0YSksCiAgICAgICIpIgogICAgKSwKICAgIHggPSAiRWxvIHJhdGluZyBjaGFuZ2UiLAogICAgeSA9ICJOdW1iZXIgb2YgZXhlcmNpc2UgdHJhbnNpdGlvbnMiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKIyMgRmlndXJlIDI6IE1lYW4gRWxvIGNoYW5nZSBieSBwcmVwYXJhdG9yeSBlbmdhZ2VtZW50CgpgYGB7cn0KcGxvdF9kYXRhIDwtIGFuYWx5c2lzX2RhdGEgJT4lCiAgbXV0YXRlKAogICAgcHJlcGFyYXRpb25fZ3JvdXAgPSBjYXNlX3doZW4oCiAgICAgIGV4YW1wbGVzX2JlZm9yZSA9PSAwICYgY2hhbGxlbmdlc19iZWZvcmUgPT0gMCB+ICJOb25lIiwKICAgICAgZXhhbXBsZXNfYmVmb3JlID4gMCAmIGNoYWxsZW5nZXNfYmVmb3JlID09IDAgfiAiRXhhbXBsZXMgb25seSIsCiAgICAgIGV4YW1wbGVzX2JlZm9yZSA9PSAwICYgY2hhbGxlbmdlc19iZWZvcmUgPiAwIH4gIkNoYWxsZW5nZXMgb25seSIsCiAgICAgIGV4YW1wbGVzX2JlZm9yZSA+IDAgJiBjaGFsbGVuZ2VzX2JlZm9yZSA+IDAgfiAiRXhhbXBsZXMgKyBjaGFsbGVuZ2VzIgogICAgKSwKICAgIHByZXBhcmF0aW9uX2dyb3VwID0gZmFjdG9yKAogICAgICBwcmVwYXJhdGlvbl9ncm91cCwKICAgICAgbGV2ZWxzID0gYygKICAgICAgICAiTm9uZSIsCiAgICAgICAgIkV4YW1wbGVzIG9ubHkiLAogICAgICAgICJDaGFsbGVuZ2VzIG9ubHkiLAogICAgICAgICJFeGFtcGxlcyArIGNoYWxsZW5nZXMiCiAgICAgICkKICAgICkKICApICU+JQogIGdyb3VwX2J5KHByZXBhcmF0aW9uX2dyb3VwKSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgbWVhbiA9IG1lYW4oRWxvX2dhaW4pLAogICAgU0UgPSBzZChFbG9fZ2FpbikgLyBzcXJ0KG4pLAogICAgbG93ZXIgPSBtZWFuIC0gMS45NiAqIFNFLAogICAgdXBwZXIgPSBtZWFuICsgMS45NiAqIFNFLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgJT4lCiAgbXV0YXRlKAogICAgZ3JvdXBfbGFiZWwgPSBwYXN0ZTAoCiAgICAgIHByZXBhcmF0aW9uX2dyb3VwLAogICAgICAiXG4obiA9ICIsCiAgICAgIG4sCiAgICAgICIpIgogICAgKQogICkKCmdncGxvdCgKICBwbG90X2RhdGEsCiAgYWVzKHggPSBncm91cF9sYWJlbCwgeSA9IG1lYW4pCikgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsKICBnZW9tX2Vycm9yYmFyKAogICAgYWVzKAogICAgICB5bWluID0gbG93ZXIsCiAgICAgIHltYXggPSB1cHBlcgogICAgKSwKICAgIHdpZHRoID0gMC4xNQogICkgKwogIGdlb21faGxpbmUoCiAgICB5aW50ZXJjZXB0ID0gMCwKICAgIGxpbmV0eXBlID0gImRhc2hlZCIKICApICsKICBsYWJzKAogICAgdGl0bGUgPSAiTWVhbiBFbG8gY2hhbmdlIGJ5IHByZXBhcmF0b3J5IGVuZ2FnZW1lbnQiLAogICAgc3VidGl0bGUgPSAiUG9pbnRzIHNob3cgZ3JvdXAgbWVhbnM7IGVycm9yIGJhcnMgc2hvdyA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMiLAogICAgeCA9ICJFbmdhZ2VtZW50IGJldHdlZW4gY29uc2VjdXRpdmUgZXhlcmNpc2UgZXZlbnRzIiwKICAgIHkgPSAiTWVhbiBFbG8gcmF0aW5nIGNoYW5nZSIKICApICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyBGaWd1cmUgMzogUHJlZGljdGVkIHByb2JhYmlsaXR5IG9mIGEgcG9zaXRpdmUgRWxvIGNoYW5nZQoKUHJlZGljdGlvbnMgYXJlIHNob3duIGZvciAw4oCTOCBwcmVwYXJhdG9yeSBldmVudHMgYmVjYXVzZSBvYnNlcnZhdGlvbnMgYmVjb21lIHNwYXJzZSBhdCBoaWdoZXIgZW5nYWdlbWVudCBjb3VudHMuCgpgYGB7cn0KcHJlZGljdGlvbl9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgcHJlcGFyYXRvcnlfYmVmb3JlID0gMDo4LAogIGV4ZXJjaXNlX251bWJlciA9IG1lZGlhbihhbmFseXNpc19kYXRhJGV4ZXJjaXNlX251bWJlcikKKQoKcHJlZGljdGlvbl9kYXRhJHByZWRpY3RlZF9wcm9iYWJpbGl0eSA8LSBwcmVkaWN0KAogIG1vZGVsX0gxYl9sb2dpc3RpYywKICBuZXdkYXRhID0gcHJlZGljdGlvbl9kYXRhLAogIHR5cGUgPSAicmVzcG9uc2UiLAogIHJlLmZvcm0gPSBOQQopCgpnZ3Bsb3QoCiAgcHJlZGljdGlvbl9kYXRhLAogIGFlcygKICAgIHggPSBwcmVwYXJhdG9yeV9iZWZvcmUsCiAgICB5ID0gcHJlZGljdGVkX3Byb2JhYmlsaXR5CiAgKQopICsKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICBsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkKICApICsKICBsYWJzKAogICAgdGl0bGUgPSAiUHJlZGljdGVkIHByb2JhYmlsaXR5IG9mIGEgcG9zaXRpdmUgRWxvIGNoYW5nZSIsCiAgICBzdWJ0aXRsZSA9IHBhc3RlMCgKICAgICAgIkV4ZXJjaXNlIHBvc2l0aW9uIGhlbGQgYXQgaXRzIG1lZGlhbjsgTiA9ICIsCiAgICAgIG5yb3coYW5hbHlzaXNfZGF0YSksCiAgICAgICIgdHJhbnNpdGlvbnMiCiAgICApLAogICAgeCA9ICJQcmVwYXJhdG9yeSBlbmdhZ2VtZW50IGV2ZW50cyBiZWZvcmUgZXhlcmNpc2UiLAogICAgeSA9ICJQcmVkaWN0ZWQgcHJvYmFiaWxpdHkiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKIyMgRmlndXJlIDQ6IFBvc2l0aXZlIEVsbyBjaGFuZ2VzIHdpdGggYW5kIHdpdGhvdXQgcHJlcGFyYXRpb24KCmBgYHtyfQphbnlfcHJlcF9wbG90IDwtIGFuYWx5c2lzX2RhdGEgJT4lCiAgbXV0YXRlKAogICAgcHJlcGFyYXRpb24gPSBpZl9lbHNlKAogICAgICBwcmVwYXJhdG9yeV9iZWZvcmUgPiAwLAogICAgICAiQW55IHByZXBhcmF0aW9uIiwKICAgICAgIk5vIHByZXBhcmF0aW9uIgogICAgKSwKICAgIHByZXBhcmF0aW9uID0gZmFjdG9yKAogICAgICBwcmVwYXJhdGlvbiwKICAgICAgbGV2ZWxzID0gYygKICAgICAgICAiTm8gcHJlcGFyYXRpb24iLAogICAgICAgICJBbnkgcHJlcGFyYXRpb24iCiAgICAgICkKICAgICkKICApICU+JQogIGdyb3VwX2J5KHByZXBhcmF0aW9uKSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgcG9zaXRpdmVfbiA9IHN1bShFbG9fZ2FpbiA+IDApLAogICAgcG9zaXRpdmVfcGN0ID0gbWVhbihFbG9fZ2FpbiA+IDApICogMTAwLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgJT4lCiAgbXV0YXRlKAogICAgbGFiZWwgPSBwYXN0ZTAoCiAgICAgIHByZXBhcmF0aW9uLAogICAgICAiXG4obiA9ICIsCiAgICAgIG4sCiAgICAgICIpIgogICAgKQogICkKCnByaW50KGFueV9wcmVwX3Bsb3QpCgpnZ3Bsb3QoCiAgYW55X3ByZXBfcGxvdCwKICBhZXMoeCA9IGxhYmVsLCB5ID0gcG9zaXRpdmVfcGN0KQopICsKICBnZW9tX2NvbCh3aWR0aCA9IDAuNikgKwogIGdlb21fdGV4dCgKICAgIGFlcygKICAgICAgbGFiZWwgPSBwYXN0ZTAoCiAgICAgICAgcm91bmQocG9zaXRpdmVfcGN0LCAxKSwKICAgICAgICAiJSIKICAgICAgKQogICAgKSwKICAgIHZqdXN0ID0gLTAuNQogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJQb3NpdGl2ZSBFbG8gY2hhbmdlcyBieSBwcmVwYXJhdG9yeSBlbmdhZ2VtZW50IiwKICAgIHggPSBOVUxMLAogICAgeSA9ICJFeGVyY2lzZSB0cmFuc2l0aW9ucyB3aXRoIHBvc2l0aXZlIEVsbyBjaGFuZ2UgKCUpIgogICkgKwogIHRoZW1lX21pbmltYWwoKQpgYGA=