rm(list=ls(all=TRUE)) #clear previous
# Install pacman if not already installed
if (!require("pacman")) install.packages("pacman")
# Use pacman to load/install packages
pacman::p_load(
gratia,
gamm4,
mgcv,
segmented,
nlme,
mmrm,
tidyverse,
car,
languageR,
ggplot2,
lattice,
jtools,
sjPlot,
sjmisc,
sjlabelled,
gtools,
lmerTest,
ggeffects,
ggpubr,
corrplot,
gridExtra,
GGally,
irr,
blandr,
knitr,
kableExtra,
ggprism,
webshot2,
htmltools,
gt,
parameters
)
# Read in full data, both pre and post assoc
AssocLongint <- read.csv(file = "/Volumes/vosslabhpc/Projects/BikeExtend/3-Experiment/2-Data/BIDS/derivatives/Bryan/Projects/EXTEND_beh/BikeEXTEND_Assoc_post/AssocPostSummary.csv")
AssocLongint$Subject <- as.factor(AssocLongint$Subject)
AssocLongint$Block <- as.numeric(AssocLongint$Block)
AssocLongint$Time <- as.factor(AssocLongint$Time)
AssocLongint$Intgrp <- ifelse(AssocLongint$Intgrp == "Group 1: Moderate Intensity", "ModVig", "Light"
)
AssocLongint <- AssocLongint[!is.na(AssocLongint$Intgrp), ]
AssocLongint$Intgrp <- as.factor(AssocLongint$Intgrp)
# Filter out pre data for Cross-sectional models
Assoc_pre <- AssocLongint %>%
filter(Time == "preInt")
# Run GAMM model with only Block predicting Accuracy
gamm_model <- gamm(
avg_acc ~ s(Block, k = 6), # smooth term for block (nonlinear learning)
random = list(Subject = ~1), # random intercepts for each subject,
data = Assoc_pre
)
# ~1 indicates that each subject can have their own baseline (intercept), accounting for individual differences in average accuracy.
# This helps account for within-subject correlation, which is important in repeated-measures or longitudinal data (like multiple Blocks per subject)
# 'gamm()' fits a GAMM: it includes both smooth (nonlinear) terms and random effects.
# Unlike 'gam()', which only handles fixed effects, 'gamm()' is appropriate for repeated-measures data.
summary(gamm_model$gam) # fixed effects and smooth term
Family: gaussian
Link function: identity
Formula:
avg_acc ~ s(Block, k = 6)
Parametric coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.47901 0.01464 32.72 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Approximate significance of smooth terms:
edf Ref.df F p-value
s(Block) 3.262 3.262 486.7 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
R-sq.(adj) = 0.294
Scale est. = 0.010265 n = 1150
summary(gamm_model$lme) # random effects (subject-level)
Linear mixed-effects model fit by maximum likelihood
Data: strip.offset(mf)
Random effects:
Formula: ~Xr - 1 | g
Structure: pdIdnot
Xr1 Xr2 Xr3 Xr4
StdDev: 0.06800683 0.06800683 0.06800683 0.06800683
Formula: ~1 | Subject %in% g
(Intercept) Residual
StdDev: 0.1536245 0.1013163
Fixed effects: y ~ X - 1
Correlation:
X(Int)
Xs(Block)Fx1 0
Standardized Within-Group Residuals:
Min Q1 Med Q3 Max
-3.02328817 -0.60989638 -0.01281136 0.64526397 3.80618117
Number of Observations: 1150
Number of Groups:
g Subject %in% g
1 115
plot(gamm_model$gam, residuals = TRUE, pch = 16, main = "Smooth Term: ACC ~ BlockNum")

#library(gratia)
draw(gamm_model$gam) # uses ggplot under the hood for more control over aesthetics

# gamm4() uses the lme4 engine for random effects, which is more flexible and scalable than mgcv::gamm()
gamm4_model <- gamm4(
avg_acc ~ s(Block, k = 6), # Fixed effect: smooth spline over Block to model nonlinear learning
random = ~(1 | Subject), # Random effect: random intercepts for each subject
data = Assoc_pre
)
# Summary of the GAM component: shows fixed effects and smooth terms
summary(gamm4_model$gam)
Family: gaussian
Link function: identity
Formula:
avg_acc ~ s(Block, k = 6)
Parametric coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.4790 0.0147 32.59 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Approximate significance of smooth terms:
edf Ref.df F p-value
s(Block) 3.503 3.503 453.7 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
R-sq.(adj) = 0.294
lmer.REML = -1615.5 Scale est. = 0.010265 n = 1150
# Summary of the Mixed-Effects component: shows variance due to subjects (random effects)
summary(gamm4_model$lme)
Length Class Mode
0 NULL NULL
# Diagnostic plot: smooth function with residuals overlaid
plot(gamm4_model$gam, residuals = TRUE, pch = 16)

# Fit a Generalized Additive Mixed Model (GAMM) using mgcv::gamm()
gamm_model_group <- gamm(
avg_acc ~ Intgrp + Time + Age + Sex + YrsEdu + # Parametric fixed effects
s(Block, by = interaction(Intgrp, Time), k = 6), # Group × Time-specific nonlinear learning curve
random = list(Subject = ~1), # Random intercepts for each subject (nested design)
data = AssocLongint # Long-format dataset including pre and post data
)
# View summary of the GAM portion (fixed effects + smooth terms)
summary(gamm_model_group$gam)
Family: gaussian
Link function: identity
Formula:
avg_acc ~ Intgrp + Time + Age + Sex + YrsEdu + s(Block, by = interaction(Intgrp,
Time), k = 6)
Parametric coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.015223 0.151990 6.680 3.05e-11 ***
IntgrpModVig -0.059552 0.025638 -2.323 0.0203 *
TimepreInt -0.005090 0.005310 -0.959 0.3379
Age -0.010134 0.002286 -4.433 9.77e-06 ***
SexMale -0.012511 0.027061 -0.462 0.6439
YrsEdu 0.008795 0.005598 1.571 0.1163
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Approximate significance of smooth terms:
edf Ref.df F p-value
s(Block):interaction(Intgrp, Time)Light.postInt 2.347 2.347 264.9 <2e-16 ***
s(Block):interaction(Intgrp, Time)ModVig.postInt 3.776 3.776 120.8 <2e-16 ***
s(Block):interaction(Intgrp, Time)Light.preInt 2.971 2.971 197.6 <2e-16 ***
s(Block):interaction(Intgrp, Time)ModVig.preInt 2.082 2.082 281.0 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
R-sq.(adj) = 0.367
Scale est. = 0.013856 n = 2140
# View summary of the LME portion (random effects for subjects)
summary(gamm_model_group$lme)
Linear mixed-effects model fit by maximum likelihood
Data: strip.offset(mf)
Random effects:
Formula: ~Xr - 1 | g
Structure: pdIdnot
Xr1 Xr2 Xr3 Xr4
StdDev: 0.05642862 0.05642862 0.05642862 0.05642862
Formula: ~Xr.0 - 1 | g.0 %in% g
Structure: pdIdnot
Xr.01 Xr.02 Xr.03 Xr.04
StdDev: 0.1797177 0.1797177 0.1797177 0.1797177
Formula: ~Xr.1 - 1 | g.1 %in% g.0 %in% g
Structure: pdIdnot
Xr.11 Xr.12 Xr.13 Xr.14
StdDev: 0.09001205 0.09001205 0.09001205 0.09001205
Formula: ~Xr.2 - 1 | g.2 %in% g.1 %in% g.0 %in% g
Structure: pdIdnot
Xr.21 Xr.22 Xr.23 Xr.24
StdDev: 0.03975747 0.03975747 0.03975747 0.03975747
Formula: ~1 | Subject %in% g.2 %in% g.1 %in% g.0 %in% g
(Intercept) Residual
StdDev: 0.1345361 0.1177126
Fixed effects: y ~ X - 1
Correlation:
X(Int) XIntMV XTmprI XAge XSexMl XYrsEd Xs(Blck):ntrctn(Intgrp,Tm)Lght.psIF1 Xs(Blck):ntrctn(Intgrp,Tm)MdVg.psIF1 Xs(Blck):ntrctn(Intgrp,Tm)Lght.prIF1
XIntgrpModVig -0.108
XTimepreInt -0.025 -0.003
XAge -0.798 0.000 0.005
XSexMale 0.006 0.059 -0.010 -0.029
XYrsEdu -0.368 0.029 0.001 -0.251 -0.074
Xs(Block):interaction(Intgrp, Time)Light.postIntFx1 0.000 0.000 0.000 0.000 0.000 0.000
Xs(Block):interaction(Intgrp, Time)ModVig.postIntFx1 0.000 0.000 0.000 0.000 0.000 0.000 0.000
Xs(Block):interaction(Intgrp, Time)Light.preIntFx1 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
Xs(Block):interaction(Intgrp, Time)ModVig.preIntFx1 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
Standardized Within-Group Residuals:
Min Q1 Med Q3 Max
-3.55827765 -0.63617325 0.03270191 0.68153449 3.66596309
Number of Observations: 2140
Number of Groups:
g g.0 %in% g g.1 %in% g.0 %in% g g.2 %in% g.1 %in% g.0 %in% g Subject %in% g.2 %in% g.1 %in% g.0 %in% g
1 1 1 1 116
# Plot the smooth learning curves for each Group × Time interaction
# Shows the estimated smooth function with 95% confidence bands and residuals
plot(gamm_model_group$gam, pages = 1, residuals = TRUE, pch = 16)

NA
NA
# Fit a Generalized Additive Mixed Model using gamm4 (which uses lme4::lmer for random effects). Repeated model from above that used gamm()
gamm4_model_group <- gamm4(
avg_acc ~ Intgrp + Time + Age + Sex + YrsEdu + # Parametric fixed effects
s(Block, by = interaction(Intgrp, Time), k = 6), # Smooth term for Block by Group × Time interaction:Fits a separate smooth learning curve over Block for each unique combination of intervention group (Intgrp) and timepoint (Time).The interaction() function defines these subgroups.
random = ~(1 | Subject), # Random intercepts for each subject (lme4-style formula)
data = AssocLongint
)
# Summarize fixed effects and smooth terms from the GAM part (mgcv::gam object)
summary(gamm4_model_group$gam)
Family: gaussian
Link function: identity
Formula:
avg_acc ~ Intgrp + Time + Age + Sex + YrsEdu + s(Block, by = interaction(Intgrp,
Time), k = 6)
Parametric coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.015231 0.155175 6.542 7.56e-11 ***
IntgrpModVig -0.059574 0.026175 -2.276 0.0229 *
TimepreInt -0.005087 0.005305 -0.959 0.3378
Age -0.010135 0.002334 -4.342 1.48e-05 ***
SexMale -0.012517 0.027627 -0.453 0.6506
YrsEdu 0.008796 0.005715 1.539 0.1239
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Approximate significance of smooth terms:
edf Ref.df F p-value
s(Block):interaction(Intgrp, Time)Light.postInt 2.587 2.587 241.0 <2e-16 ***
s(Block):interaction(Intgrp, Time)ModVig.postInt 3.896 3.896 117.7 <2e-16 ***
s(Block):interaction(Intgrp, Time)Light.preInt 3.259 3.259 180.8 <2e-16 ***
s(Block):interaction(Intgrp, Time)ModVig.preInt 2.403 2.403 244.3 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
R-sq.(adj) = 0.367
lmer.REML = -2618.3 Scale est. = 0.013867 n = 2140
# Summarize random effects from the LME part (lme4::merMod object)
summary(gamm4_model_group$mer)
Linear mixed model fit by REML ['lmerMod']
REML criterion at convergence: -2618.3
Scaled residuals:
Min 1Q Median 3Q Max
-3.5568 -0.6334 0.0306 0.6855 3.6840
Random effects:
Groups Name Variance Std.Dev.
Subject (Intercept) 0.018954 0.13767
Xr.2 s(Block):interaction(Intgrp, Time)ModVig.preInt 0.002937 0.05419
Xr.1 s(Block):interaction(Intgrp, Time)Light.preInt 0.012783 0.11306
Xr.0 s(Block):interaction(Intgrp, Time)ModVig.postInt 0.039432 0.19858
Xr s(Block):interaction(Intgrp, Time)Light.postInt 0.004896 0.06997
Residual 0.013867 0.11776
Number of obs: 2140, groups: Subject, 116; Xr.2, 4; Xr.1, 4; Xr.0, 4; Xr, 4
Fixed effects:
Estimate Std. Error t value
X(Intercept) 1.015231 0.155175 6.542
XIntgrpModVig -0.059574 0.026175 -2.276
XTimepreInt -0.005087 0.005305 -0.959
XAge -0.010135 0.002334 -4.342
XSexMale -0.012517 0.027627 -0.453
XYrsEdu 0.008796 0.005715 1.539
Xs(Block):interaction(Intgrp, Time)Light.postIntFx1 -0.139448 0.020447 -6.820
Xs(Block):interaction(Intgrp, Time)ModVig.postIntFx1 -0.196712 0.034207 -5.751
Xs(Block):interaction(Intgrp, Time)Light.preIntFx1 -0.147200 0.025848 -5.695
Xs(Block):interaction(Intgrp, Time)ModVig.preIntFx1 -0.119246 0.016805 -7.096
Correlation of Fixed Effects:
X(Int) XIntMV XTmprI XAge XSexMl XYrsEd Xs(Blck):ntrctn(Intgrp,Tm)Lght.psIF1 Xs(Blck):ntrctn(Intgrp,Tm)MdVg.psIF1 Xs(Blck):ntrctn(Intgrp,Tm)Lght.prIF1
XIntgrpMdVg -0.108
XTimepreInt -0.024 -0.003
XAge -0.798 0.000 0.005
XSexMale 0.006 0.059 -0.009 -0.029
XYrsEdu -0.368 0.029 0.001 -0.251 -0.074
Xs(Blck):ntrctn(Intgrp,Tm)Lght.psIF1 0.000 0.000 0.000 0.000 0.000 0.000
Xs(Blck):ntrctn(Intgrp,Tm)MdVg.psIF1 0.000 0.000 0.000 0.000 0.000 0.000 0.000
Xs(Blck):ntrctn(Intgrp,Tm)Lght.prIF1 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
Xs(Blck):ntrctn(Intgrp,Tm)MdVg.prIF1 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
# Plot the smooth terms with residuals
plot(gamm4_model_group$gam, residuals = TRUE, pch = 16)




# Step 1: Extract smooth term estimates from the fitted GAMM model
# This includes estimated values and standard errors for each smooth function in the model
smooths_df <- gratia::smooth_estimates(gamm_model_group$gam)
# Step 2: Inspect the column names to identify how smooth terms are labeled
# Useful for confirming which column contains the smooth labels (e.g., ".smooth")
print(colnames(smooths_df)) # Diagnostic step to understand structure of smooths_df
[1] ".smooth" ".type" ".by" ".estimate" ".se" "Block" "interaction(Intgrp, Time)"
# Step 3: Create label for each group × time interaction
# Based on pattern matching within the `.smooth` column
# This is used for coloring and grouping in the plot
smooths_df <- smooths_df %>%
mutate(Group = case_when(
grepl("Light\\.postInt", .smooth) ~ "Light - Post",
grepl("ModVig\\.postInt", .smooth) ~ "ModVig - Post",
grepl("Light\\.preInt", .smooth) ~ "Light - Pre",
grepl("ModVig\\.preInt", .smooth) ~ "ModVig - Pre",
TRUE ~ "Other" # Catch-all fallback (shouldn’t typically occur)
))
# Step 1: Extract smooth term estimates from the fitted GAMM model
There were 50 or more warnings (use warnings() to see the first 50)
# This includes estimated values and standard errors for each smooth function in the model
smooths_df4 <- gratia::smooth_estimates(gamm4_model_group$gam)
# Step 2: Inspect the column names to identify how smooth terms are labeled
# Useful for confirming which column contains the smooth labels (e.g., ".smooth")
print(colnames(smooths_df4)) # Diagnostic step to understand structure of smooths_df
[1] ".smooth" ".type" ".by" ".estimate" ".se" "Block" "interaction(Intgrp, Time)"
# Step 3: Create label for each group × time interaction
# Based on pattern matching within the `.smooth` column
# This is used for coloring and grouping in the plot
smooths_df4 <- smooths_df4 %>%
mutate(Group = case_when(
grepl("Light\\.postInt", .smooth) ~ "Light - Post",
grepl("ModVig\\.postInt", .smooth) ~ "ModVig - Post",
grepl("Light\\.preInt", .smooth) ~ "Light - Pre",
grepl("ModVig\\.preInt", .smooth) ~ "ModVig - Pre",
TRUE ~ "Other" # Catch-all fallback (shouldn’t typically occur)
))
# Step 4: Create a TVEM-style line plot showing estimated learning curves over Block
# Each line represents the smooth trajectory for a Group × Time combination
# A ribbon is added to show ±1 standard error around the estimated smooth
ggplot(smooths_df, aes(x = Block, y = .estimate, color = Group, fill = Group)) +
geom_line(size = 1.2) + # Line plot of estimated smooth
geom_ribbon(aes(ymin = .estimate - .se, ymax = .estimate + .se),
alpha = 0.2, color = NA) + # Shaded confidence band
labs(
title = "TVEM-style Plot of Accuracy by Block and Group × Time\n - Gamm",
x = "Block", y = "Estimated Accuracy",
color = "Group × Time", fill = "Group × Time"
) +
theme_minimal(base_size = 14) # Clean visual style

ggplot(smooths_df4, aes(x = Block, y = .estimate, color = Group, fill = Group)) +
geom_line(size = 1.2) + # Line plot of estimated smooth
geom_ribbon(aes(ymin = .estimate - .se, ymax = .estimate + .se),
alpha = 0.2, color = NA) + # Shaded confidence band
labs(
title = "TVEM-style Plot of Accuracy by Block and Group × Time\n - Gamm4",
x = "Block", y = "Estimated Accuracy",
color = "Group × Time", fill = "Group × Time"
) +
theme_minimal(base_size = 14) # Clean visual style

# Step 1: Add TimePeriod column
smooths_df <- smooths_df %>%
mutate(TimePeriod = case_when(
grepl("preInt", .smooth) ~ "Pre",
grepl("postInt", .smooth) ~ "Post",
TRUE ~ "Other"
))
# Step 2: Plot with facets
ggplot(smooths_df, aes(x = Block, y = .estimate, color = Group, fill = Group)) +
geom_line(size = 1.2) +
geom_ribbon(aes(ymin = .estimate - .se, ymax = .estimate + .se), alpha = 0.2, color = NA) +
facet_wrap(~TimePeriod) +
labs(
title = "TVEM-style Plot of Accuracy by Block - Gamm",
x = "Block", y = "Estimated Accuracy",
color = "Group", fill = "Group"
) +
theme_minimal(base_size = 14)

# Step 1: Add TimePeriod column
smooths_df4 <- smooths_df4 %>%
mutate(TimePeriod = case_when(
grepl("preInt", .smooth) ~ "Pre",
grepl("postInt", .smooth) ~ "Post",
TRUE ~ "Other"
))
# Step 2: Plot with facets
ggplot(smooths_df4, aes(x = Block, y = .estimate, color = Group, fill = Group)) +
geom_line(size = 1.2) +
geom_ribbon(aes(ymin = .estimate - .se, ymax = .estimate + .se), alpha = 0.2, color = NA) +
facet_wrap(~TimePeriod) +
labs(
title = "TVEM-style Plot of Accuracy by Block - Gamm4",
x = "Block", y = "Estimated Accuracy",
color = "Group", fill = "Group"
) +
theme_minimal(base_size = 14)

#
#
`
This section look at the EXTEND baseline data with the addition of
the Midlife sample
These demographics has only Age for midlife because at the time
collected, rest of demo var were missing. Need to return to Redcap to
retrieve the rest
# TaskSwitchMOb <- read.csv("/Volumes/vosslabhpc/Projects/BikeExtend/3-Experiment/2-Data/Participants/BaselineSummaries/TaskSwitch_Trial_Pre_Full.csv", stringsAsFactors = FALSE)[, -1]
# TaskSwitchMOb <- TaskSwitchMOb[, c(1:7,12:33)]
# This df has already dropped the same subs dropped in the intervention analysis
TaskSwitchMO <- read.csv("/Volumes/vosslabhpc/Projects/BikeExtend/3-Experiment/2-Data/BIDS/derivatives/Bryan/Projects/Task_Switch-Intervention/Arch/Pre_TS_Long.csv", stringsAsFactors = FALSE)[, -1] %>% mutate(Time = "pre")
TaskSwitchMO <- TaskSwitchMO[, -c(31:35)]
bike <- read.csv("/Volumes/vosslabhpc/Projects/BikeExtend/3-Experiment/2-Data/BIDS/derivatives/Bryan/Projects/TertiarySulci/EXTEND_labels/code/00_Analysis/00_Variables/BikeDemo.csv", header = TRUE, sep = ",", stringsAsFactors = FALSE)
colnames(bike)[1:12] <- c("Subject", "Sex", "Age", "YrsEdu", "Moca", "RAVLT", "RAVLTpost",
"AnimalFlency", "Intgrp", "Rel_Vo2m", "RespExRatio", "DSST")
bike <- bike[, -c(2,3)]
# Drop rows with missing cardiorespiratory fitness data
bike <- bike %>% drop_na(Rel_Vo2m)
TaskSwitchMO <- TaskSwitchMO %>%
left_join(bike, by = "Subject")
# Ensure Subject is treated as a character to extract prefix to create grouping variable
TaskSwitchMO <- TaskSwitchMO %>%
mutate(
Subject = as.character(Subject),
EXTGroup = case_when(
str_starts(Subject, "5") ~ "Midlife",
str_starts(Subject, "2") ~ "Older",
TRUE ~ NA_character_ # in case there are other IDs
)
)
TaskSwitchMO$Subject <- as.factor(TaskSwitchMO$Subject)
TaskSwitchMO$EXTGroup <- as.factor(TaskSwitchMO$EXTGroup)
TaskSwitchMO$Age <- as.integer(TaskSwitchMO$Age)
TaskSwitchMO$YrsEdu <- as.integer(TaskSwitchMO$YrsEdu)
TaskSwitchMO$Condition <- as.factor(TaskSwitchMO$Condition)
TaskSwitchMO$Trial.Type <- as.factor(TaskSwitchMO$Trial.Type)
TaskSwitchMO$Sex <- as.factor(TaskSwitchMO$Sex)
contrasts(TaskSwitchMO$Trial.Type)
Single Switched
Repeated 0 0
Single 1 0
Switched 0 1
print("Mixing Cost is referencing Repaeted, Single-Repeat, therefore take the negative of the beta shown for single (multiply by -1)")
[1] "Mixing Cost is referencing Repaeted, Single-Repeat, therefore take the negative of the beta shown for single (multiply by -1)"
print("Switching Cost is referenced here correctly, Switching - Repeated, therfore interpret the beta as is")
[1] "Switching Cost is referenced here correctly, Switching - Repeated, therfore interpret the beta as is"
Analysing Age as a continous variable
Age + Condition * Trial.Type
Age <- Min=40, Max=80
Agingsimple_model <- lmer(
Correct.RT ~ Age + Condition * Trial.Type + (1 | Subject),
data = TaskSwitchMO
)
summary(Agingsimple_model) #, ddf=c("Kenward-Roger"))
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: Correct.RT ~ Age + Condition * Trial.Type + (1 | Subject)
Data: TaskSwitchMO
REML criterion at convergence: 1215709
Scaled residuals:
Min 1Q Median 3Q Max
-4.0743 -0.6255 -0.1863 0.4148 5.5438
Random effects:
Groups Name Variance Std.Dev.
Subject (Intercept) 12023 109.7
Residual 110000 331.7
Number of obs: 84115, groups: Subject, 148
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 913.114 76.403 156.049 11.951 < 2e-16 ***
Age 3.596 1.237 155.862 2.908 0.00417 **
ConditionSeparate -373.395 3.892 83999.363 -95.936 < 2e-16 ***
Trial.TypeSingle -287.071 4.042 83966.690 -71.020 < 2e-16 ***
Trial.TypeSwitched 232.757 4.049 83967.964 57.483 < 2e-16 ***
ConditionSeparate:Trial.TypeSingle 275.732 5.608 83964.760 49.165 < 2e-16 ***
ConditionSeparate:Trial.TypeSwitched -57.726 5.559 83966.107 -10.384 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) Age CndtnS Trl.TypSn Trl.TypSw CndtnSprt:Trl.TypSn
Age -0.992
ConditnSprt -0.026 -0.001
Trl.TypSngl -0.025 -0.001 0.501
Trl.TypSwtc -0.027 0.001 0.500 0.482
CndtnSprt:Trl.TypSn 0.018 0.000 -0.689 -0.720 -0.347
CndtnSprt:Trl.TypSw 0.020 -0.001 -0.694 -0.351 -0.727 0.482
print("Note: Recall to interpret the single trial betas as negative (multiply by -1) to infer Mixing Cost")
[1] "Note: Recall to interpret the single trial betas as negative (multiply by -1) to infer Mixing Cost"
# Predict RT across Condition and Trial.Type for three representative age values
Agingsimple_model.predict <- ggpredict(
Agingsimple_model,
terms = c("Condition", "Trial.Type") # You can change these age values as needed
)
Agingsimple_model.PLOT <- ggplot(Agingsimple_model.predict, aes(x = x, y = predicted, group = group)) +
geom_line(aes(linetype = group, color = group), size = 1.2) + # Trial.Type as line types/colors
geom_ribbon(aes(ymin = conf.low, ymax = conf.high, fill = group),
alpha = 0.2, color = NA) +
theme_bw() +
theme(
text = element_text(size = 16),
strip.background = element_blank(),
strip.text = element_text(size = 12, face = "bold"),
legend.position = "bottom",
legend.title = element_text(size = 11),
legend.text = element_text(size = 11),
plot.title = element_text(hjust = 0.5)
) +
labs(
title = "Predicted RT by Condition and Trial Type",
x = "Condition",
y = "Predicted RT (ms)",
linetype = "Trial Type",
color = "Trial Type",
fill = "Trial Type"
)
Agingsimple_model.PLOT

Analysing Age as a continous variable
Age + Condition * Trial.Type
Age <- Min=40, Max=80
Agingsimple_model <- lmer(
Correct.RT ~ Age + Condition * Trial.Type + (1 | Subject),
data = TaskSwitchMO
)
summary(Agingsimple_model) #, ddf=c("Kenward-Roger"))
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: Correct.RT ~ Age + Condition * Trial.Type + (1 | Subject)
Data: TaskSwitchMO
REML criterion at convergence: 1215709
Scaled residuals:
Min 1Q Median 3Q Max
-4.0743 -0.6255 -0.1863 0.4148 5.5438
Random effects:
Groups Name Variance Std.Dev.
Subject (Intercept) 12023 109.7
Residual 110000 331.7
Number of obs: 84115, groups: Subject, 148
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 913.114 76.403 156.049 11.951 < 2e-16 ***
Age 3.596 1.237 155.862 2.908 0.00417 **
ConditionSeparate -373.395 3.892 83999.363 -95.936 < 2e-16 ***
Trial.TypeSingle -287.071 4.042 83966.690 -71.020 < 2e-16 ***
Trial.TypeSwitched 232.757 4.049 83967.964 57.483 < 2e-16 ***
ConditionSeparate:Trial.TypeSingle 275.732 5.608 83964.760 49.165 < 2e-16 ***
ConditionSeparate:Trial.TypeSwitched -57.726 5.559 83966.107 -10.384 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) Age CndtnS Trl.TypSn Trl.TypSw CndtnSprt:Trl.TypSn
Age -0.992
ConditnSprt -0.026 -0.001
Trl.TypSngl -0.025 -0.001 0.501
Trl.TypSwtc -0.027 0.001 0.500 0.482
CndtnSprt:Trl.TypSn 0.018 0.000 -0.689 -0.720 -0.347
CndtnSprt:Trl.TypSw 0.020 -0.001 -0.694 -0.351 -0.727 0.482
print("Note: Recall to interpret the single trial betas as negative (multiply by -1) to infer Mixing Cost")
[1] "Note: Recall to interpret the single trial betas as negative (multiply by -1) to infer Mixing Cost"
# Predict RT across Condition and Trial.Type for three representative age values
Agingsimple_model.predict <- ggpredict(
Agingsimple_model,
terms = c("Condition", "Trial.Type") # You can change these age values as needed
)
Agingsimple_model.PLOT <- ggplot(Agingsimple_model.predict, aes(x = x, y = predicted, group = group)) +
geom_line(aes(linetype = group, color = group), size = 1.2) + # Trial.Type as line types/colors
geom_ribbon(aes(ymin = conf.low, ymax = conf.high, fill = group),
alpha = 0.2, color = NA) +
theme_bw() +
theme(
text = element_text(size = 16),
strip.background = element_blank(),
strip.text = element_text(size = 12, face = "bold"),
legend.position = "bottom",
legend.title = element_text(size = 11),
legend.text = element_text(size = 11),
plot.title = element_text(hjust = 0.5)
) +
labs(
title = "Predicted RT by Condition and Trial Type at Selected Ages",
x = "Condition",
y = "Predicted RT (ms)",
linetype = "Trial Type",
color = "Trial Type",
fill = "Trial Type"
)
Agingsimple_model.PLOT

# Predict RT across Condition and Trial.Type for three representative age values
Agingsimple_model.predict <- ggpredict(
Agingsimple_model,
terms = c("Condition", "Trial.Type", "Age [50,65,80]") # You can change these age values as needed
)
Agingsimple.PLOT2 <- ggplot(Agingsimple_model.predict, aes(x = x, y = predicted, group = group)) +
geom_line(aes(linetype = group, color = group), size = 1.2) + # Trial.Type as line types/colors
geom_ribbon(aes(ymin = conf.low, ymax = conf.high, fill = group),
alpha = 0.2, color = NA) +
facet_wrap(~facet, labeller = label_both) + # Facets by Age value
ylim(600, 1500) +
theme_bw() +
theme(
text = element_text(size = 16),
strip.background = element_blank(),
strip.text = element_text(size = 12, face = "bold"),
legend.position = "bottom",
legend.title = element_text(size = 11),
legend.text = element_text(size = 11),
plot.title = element_text(hjust = 0.5)
) +
labs(
title = "Predicted RT by Condition and Trial Type\n at Selected Ages",
x = "Condition",
y = "Predicted RT (ms)",
linetype = "Trial Type",
color = "Trial Type",
fill = "Trial Type"
)
Agingsimple.PLOT2

Analysing Age as a continous variable
Age + Condition * Trial.Type
Age <- Min=40, Max=80
Fitness_simple_model <- lmer(
Correct.RT ~ Age + Rel_Vo2m + Condition * Trial.Type + (1 | Subject),
data = TaskSwitchMO
)
summary(Fitness_simple_model) #, ddf=c("Kenward-Roger"))
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: Correct.RT ~ Age + Rel_Vo2m + Condition * Trial.Type + (1 | Subject)
Data: TaskSwitchMO
REML criterion at convergence: 961599.8
Scaled residuals:
Min 1Q Median 3Q Max
-4.0723 -0.6276 -0.1876 0.4193 5.4583
Random effects:
Groups Name Variance Std.Dev.
Subject (Intercept) 11829 108.8
Residual 110720 332.7
Number of obs: 66504, groups: Subject, 118
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 957.010 130.145 115.148 7.353 3.05e-11 ***
Age 3.789 1.788 115.080 2.119 0.0362 *
Rel_Vo2m -2.817 1.957 114.859 -1.439 0.1528
ConditionSeparate -368.451 4.386 66386.032 -83.999 < 2e-16 ***
Trial.TypeSingle -280.990 4.583 66385.389 -61.312 < 2e-16 ***
Trial.TypeSwitched 241.920 4.602 66386.341 52.564 < 2e-16 ***
ConditionSeparate:Trial.TypeSingle 268.785 6.332 66383.294 42.450 < 2e-16 ***
ConditionSeparate:Trial.TypeSwitched -63.766 6.282 66384.363 -10.151 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Correlation of Fixed Effects:
(Intr) Age Rl_V2m CndtnS Trl.TypSn Trl.TypSw CndtnSprt:Trl.TypSn
Age -0.950
Rel_Vo2m -0.536 0.258
ConditnSprt -0.017 -0.001 0.001
Trl.TypSngl -0.017 0.000 0.000 0.506
Trl.TypSwtc -0.018 0.001 -0.001 0.503 0.483
CndtnSprt:Trl.TypSn 0.012 0.000 0.000 -0.692 -0.723 -0.349
CndtnSprt:Trl.TypSw 0.013 -0.001 0.000 -0.697 -0.353 -0.732 0.483
print("Note: Recall to interpret the single trial betas as negative (multiply by -1) to infer Mixing Cost")
[1] "Note: Recall to interpret the single trial betas as negative (multiply by -1) to infer Mixing Cost"
# Predict RT across Condition and Trial.Type for three representative age values
Fitness_simple_model.predict <- ggpredict(
Fitness_simple_model,
terms = c("Condition", "Trial.Type") # You can change these age values as needed
)
Fitness_simple_model.PLOT <- ggplot(Fitness_simple_model.predict, aes(x = x, y = predicted, group = group)) +
geom_line(aes(linetype = group, color = group), size = 1.2) + # Trial.Type as line types/colors
geom_ribbon(aes(ymin = conf.low, ymax = conf.high, fill = group),
alpha = 0.2, color = NA) +
theme_bw() +
theme(
text = element_text(size = 16),
strip.background = element_blank(),
strip.text = element_text(size = 12, face = "bold"),
legend.position = "bottom",
legend.title = element_text(size = 11),
legend.text = element_text(size = 11),
plot.title = element_text(hjust = 0.5)
) +
labs(
title = "Predicted RT by Condition and Trial Type",
x = "Condition",
y = "Predicted RT (ms)",
linetype = "Trial Type",
color = "Trial Type",
fill = "Trial Type"
)
Fitness_simple_model.PLOT

# Predict RT across Condition and Trial.Type for three representative age values
Fitness_simple_model.predict <- ggpredict(
Fitness_simple_model,
terms = c("Condition", "Trial.Type", "Rel_Vo2m [16.30,19.70,24.90]") # You can change these age values as needed
)
Fitness_simple_model.PLOT2 <- ggplot(Fitness_simple_model.predict, aes(x = x, y = predicted, group = group)) +
geom_line(aes(linetype = group, color = group), size = 1.2) + # Trial.Type as line types/colors
geom_ribbon(aes(ymin = conf.low, ymax = conf.high, fill = group),
alpha = 0.2, color = NA) +
facet_wrap(~facet, labeller = label_both) + # Facets by Age value
ylim(600, 1500) +
theme_bw() +
theme(
text = element_text(size = 16),
strip.background = element_blank(),
strip.text = element_text(size = 12, face = "bold"),
legend.position = "bottom",
legend.title = element_text(size = 11),
legend.text = element_text(size = 11),
plot.title = element_text(hjust = 0.5)
) +
labs(
title = "Predicted RT by Condition and Trial Type\n at Selected RelVo2m",
x = "Condition",
y = "Predicted RT (ms)",
linetype = "Trial Type",
color = "Trial Type",
fill = "Trial Type"
)
Fitness_simple_model.PLOT2

Fitness_simple_model.PLOT2

Agingsimple.PLOT2

Analysing Age as a continous variable
Age * Condition * Trial.Type
Age <- Min=40, Max=80
Analysing Age as a continous variable w/ the agegroup variable
(Midlife and Older)
Condition * Trial.Type * AgeGroup - with Age as a covariate
Age <- Min=40, Max=80
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3IgQ2xlYXIgR0V9CnJtKGxpc3Q9bHMoYWxsPVRSVUUpKSAgI2NsZWFyIHByZXZpb3VzCmBgYAoKYGBge3J9CiMgSW5zdGFsbCBwYWNtYW4gaWYgbm90IGFscmVhZHkgaW5zdGFsbGVkCmlmICghcmVxdWlyZSgicGFjbWFuIikpIGluc3RhbGwucGFja2FnZXMoInBhY21hbiIpCgojIFVzZSBwYWNtYW4gdG8gbG9hZC9pbnN0YWxsIHBhY2thZ2VzCnBhY21hbjo6cF9sb2FkKAogIGdyYXRpYSwKICBnYW1tNCwKICBtZ2N2LAogIHNlZ21lbnRlZCwKICBubG1lLAogIG1tcm0sCiAgdGlkeXZlcnNlLAogIGNhciwKICBsYW5ndWFnZVIsCiAgZ2dwbG90MiwKICBsYXR0aWNlLAogIGp0b29scywKICBzalBsb3QsCiAgc2ptaXNjLAogIHNqbGFiZWxsZWQsCiAgZ3Rvb2xzLAogIGxtZXJUZXN0LAogIGdnZWZmZWN0cywKICBnZ3B1YnIsCiAgY29ycnBsb3QsCiAgZ3JpZEV4dHJhLAogIEdHYWxseSwKICBpcnIsCiAgYmxhbmRyLAogIGtuaXRyLAogIGthYmxlRXh0cmEsCiAgZ2dwcmlzbSwKICB3ZWJzaG90MiwKICBodG1sdG9vbHMsCiAgZ3QsCiAgcGFyYW1ldGVycwopCmBgYAoKYGBge3J9CiMgUmVhZCBpbiBmdWxsIGRhdGEsIGJvdGggcHJlIGFuZCBwb3N0IGFzc29jCkFzc29jTG9uZ2ludCA8LSByZWFkLmNzdihmaWxlID0gIi9Wb2x1bWVzL3Zvc3NsYWJocGMvUHJvamVjdHMvQmlrZUV4dGVuZC8zLUV4cGVyaW1lbnQvMi1EYXRhL0JJRFMvZGVyaXZhdGl2ZXMvQnJ5YW4vUHJvamVjdHMvRVhURU5EX2JlaC9CaWtlRVhURU5EX0Fzc29jX3Bvc3QvQXNzb2NQb3N0U3VtbWFyeS5jc3YiKQpBc3NvY0xvbmdpbnQkU3ViamVjdCA8LSBhcy5mYWN0b3IoQXNzb2NMb25naW50JFN1YmplY3QpCkFzc29jTG9uZ2ludCRCbG9jayA8LSBhcy5udW1lcmljKEFzc29jTG9uZ2ludCRCbG9jaykKQXNzb2NMb25naW50JFRpbWUgPC0gYXMuZmFjdG9yKEFzc29jTG9uZ2ludCRUaW1lKQpBc3NvY0xvbmdpbnQkSW50Z3JwIDwtIGlmZWxzZShBc3NvY0xvbmdpbnQkSW50Z3JwID09ICJHcm91cCAxOiBNb2RlcmF0ZSBJbnRlbnNpdHkiLCAiTW9kVmlnIiwgIkxpZ2h0IgopCkFzc29jTG9uZ2ludCA8LSBBc3NvY0xvbmdpbnRbIWlzLm5hKEFzc29jTG9uZ2ludCRJbnRncnApLCBdCkFzc29jTG9uZ2ludCRJbnRncnAgPC0gYXMuZmFjdG9yKEFzc29jTG9uZ2ludCRJbnRncnApCgoKIyBGaWx0ZXIgb3V0IHByZSBkYXRhIGZvciBDcm9zcy1zZWN0aW9uYWwgbW9kZWxzCkFzc29jX3ByZSA8LSBBc3NvY0xvbmdpbnQgJT4lCiAgZmlsdGVyKFRpbWUgPT0gInByZUludCIpCmBgYAoKYGBge3J9CiMgUnVuIEdBTU0gbW9kZWwgd2l0aCBvbmx5IEJsb2NrIHByZWRpY3RpbmcgQWNjdXJhY3kKZ2FtbV9tb2RlbCA8LSBnYW1tKAogIGF2Z19hY2MgfiBzKEJsb2NrLCBrID0gNiksICAgICAgICAjIHNtb290aCB0ZXJtIGZvciBibG9jayAobm9ubGluZWFyIGxlYXJuaW5nKQogIHJhbmRvbSA9IGxpc3QoU3ViamVjdCA9IH4xKSwgICAgICAjIHJhbmRvbSBpbnRlcmNlcHRzIGZvciBlYWNoIHN1YmplY3QsIAogIGRhdGEgPSBBc3NvY19wcmUKKQoKIyB+MSBpbmRpY2F0ZXMgdGhhdCBlYWNoIHN1YmplY3QgY2FuIGhhdmUgdGhlaXIgb3duIGJhc2VsaW5lIChpbnRlcmNlcHQpLCBhY2NvdW50aW5nIGZvciBpbmRpdmlkdWFsIGRpZmZlcmVuY2VzIGluIGF2ZXJhZ2UgYWNjdXJhY3kuCgojIFRoaXMgaGVscHMgYWNjb3VudCBmb3Igd2l0aGluLXN1YmplY3QgY29ycmVsYXRpb24sIHdoaWNoIGlzIGltcG9ydGFudCBpbiByZXBlYXRlZC1tZWFzdXJlcyBvciBsb25naXR1ZGluYWwgZGF0YSAobGlrZSBtdWx0aXBsZSBCbG9ja3MgcGVyIHN1YmplY3QpCgojICdnYW1tKCknIGZpdHMgYSBHQU1NOiBpdCBpbmNsdWRlcyBib3RoIHNtb290aCAobm9ubGluZWFyKSB0ZXJtcyBhbmQgcmFuZG9tIGVmZmVjdHMuCgojIFVubGlrZSAnZ2FtKCknLCB3aGljaCBvbmx5IGhhbmRsZXMgZml4ZWQgZWZmZWN0cywgJ2dhbW0oKScgaXMgYXBwcm9wcmlhdGUgZm9yIHJlcGVhdGVkLW1lYXN1cmVzIGRhdGEuCgpgYGAKCgpgYGB7cn0Kc3VtbWFyeShnYW1tX21vZGVsJGdhbSkgICMgZml4ZWQgZWZmZWN0cyBhbmQgc21vb3RoIHRlcm0Kc3VtbWFyeShnYW1tX21vZGVsJGxtZSkgICMgcmFuZG9tIGVmZmVjdHMgKHN1YmplY3QtbGV2ZWwpCgoKcGxvdChnYW1tX21vZGVsJGdhbSwgcmVzaWR1YWxzID0gVFJVRSwgcGNoID0gMTYsIG1haW4gPSAiU21vb3RoIFRlcm06IEFDQyB+IEJsb2NrTnVtIikKCiNsaWJyYXJ5KGdyYXRpYSkKZHJhdyhnYW1tX21vZGVsJGdhbSkgIyB1c2VzIGdncGxvdCB1bmRlciB0aGUgaG9vZCBmb3IgbW9yZSBjb250cm9sIG92ZXIgYWVzdGhldGljcwoKYGBgCgoKYGBge3J9CiMgZ2FtbTQoKSB1c2VzIHRoZSBsbWU0IGVuZ2luZSBmb3IgcmFuZG9tIGVmZmVjdHMsIHdoaWNoIGlzIG1vcmUgZmxleGlibGUgYW5kIHNjYWxhYmxlIHRoYW4gbWdjdjo6Z2FtbSgpCgoKZ2FtbTRfbW9kZWwgPC0gZ2FtbTQoCiAgYXZnX2FjYyB+IHMoQmxvY2ssIGsgPSA2KSwgICAgICMgRml4ZWQgZWZmZWN0OiBzbW9vdGggc3BsaW5lIG92ZXIgQmxvY2sgdG8gbW9kZWwgbm9ubGluZWFyIGxlYXJuaW5nCiAgcmFuZG9tID0gfigxIHwgU3ViamVjdCksICAgICAgICMgUmFuZG9tIGVmZmVjdDogcmFuZG9tIGludGVyY2VwdHMgZm9yIGVhY2ggc3ViamVjdAogIGRhdGEgPSBBc3NvY19wcmUgICAgICAgICAgICAgIAopCgojIFN1bW1hcnkgb2YgdGhlIEdBTSBjb21wb25lbnQ6IHNob3dzIGZpeGVkIGVmZmVjdHMgYW5kIHNtb290aCB0ZXJtcwpzdW1tYXJ5KGdhbW00X21vZGVsJGdhbSkKCiMgU3VtbWFyeSBvZiB0aGUgTWl4ZWQtRWZmZWN0cyBjb21wb25lbnQ6IHNob3dzIHZhcmlhbmNlIGR1ZSB0byBzdWJqZWN0cyAocmFuZG9tIGVmZmVjdHMpCnN1bW1hcnkoZ2FtbTRfbW9kZWwkbG1lKQoKIyBEaWFnbm9zdGljIHBsb3Q6IHNtb290aCBmdW5jdGlvbiB3aXRoIHJlc2lkdWFscyBvdmVybGFpZApwbG90KGdhbW00X21vZGVsJGdhbSwgcmVzaWR1YWxzID0gVFJVRSwgcGNoID0gMTYpCgpgYGAKCgpgYGB7cn0KCiMgRml0IGEgR2VuZXJhbGl6ZWQgQWRkaXRpdmUgTWl4ZWQgTW9kZWwgKEdBTU0pIHVzaW5nIG1nY3Y6OmdhbW0oKQoKZ2FtbV9tb2RlbF9ncm91cCA8LSBnYW1tKAogIGF2Z19hY2MgfiBJbnRncnAgKyBUaW1lICsgQWdlICsgU2V4ICsgWXJzRWR1ICsgICAgICAgICAgICMgUGFyYW1ldHJpYyBmaXhlZCBlZmZlY3RzCiAgICBzKEJsb2NrLCBieSA9IGludGVyYWN0aW9uKEludGdycCwgVGltZSksIGsgPSA2KSwgICAgICAgIyBHcm91cCDDlyBUaW1lLXNwZWNpZmljIG5vbmxpbmVhciBsZWFybmluZyBjdXJ2ZQogIHJhbmRvbSA9IGxpc3QoU3ViamVjdCA9IH4xKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgUmFuZG9tIGludGVyY2VwdHMgZm9yIGVhY2ggc3ViamVjdCAobmVzdGVkIGRlc2lnbikKICBkYXRhID0gQXNzb2NMb25naW50ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIExvbmctZm9ybWF0IGRhdGFzZXQgaW5jbHVkaW5nIHByZSBhbmQgcG9zdCBkYXRhCikKCiMgVmlldyBzdW1tYXJ5IG9mIHRoZSBHQU0gcG9ydGlvbiAoZml4ZWQgZWZmZWN0cyArIHNtb290aCB0ZXJtcykKc3VtbWFyeShnYW1tX21vZGVsX2dyb3VwJGdhbSkKCiMgVmlldyBzdW1tYXJ5IG9mIHRoZSBMTUUgcG9ydGlvbiAocmFuZG9tIGVmZmVjdHMgZm9yIHN1YmplY3RzKQpzdW1tYXJ5KGdhbW1fbW9kZWxfZ3JvdXAkbG1lKQoKIyBQbG90IHRoZSBzbW9vdGggbGVhcm5pbmcgY3VydmVzIGZvciBlYWNoIEdyb3VwIMOXIFRpbWUgaW50ZXJhY3Rpb24KIyBTaG93cyB0aGUgZXN0aW1hdGVkIHNtb290aCBmdW5jdGlvbiB3aXRoIDk1JSBjb25maWRlbmNlIGJhbmRzIGFuZCByZXNpZHVhbHMKcGxvdChnYW1tX21vZGVsX2dyb3VwJGdhbSwgcGFnZXMgPSAxLCByZXNpZHVhbHMgPSBUUlVFLCBwY2ggPSAxNikKCgpgYGAKCmBgYHtyfQoKIyBGaXQgYSBHZW5lcmFsaXplZCBBZGRpdGl2ZSBNaXhlZCBNb2RlbCB1c2luZyBnYW1tNCAod2hpY2ggdXNlcyBsbWU0OjpsbWVyIGZvciByYW5kb20gZWZmZWN0cykuIFJlcGVhdGVkIG1vZGVsIGZyb20gYWJvdmUgdGhhdCB1c2VkIGdhbW0oKQpnYW1tNF9tb2RlbF9ncm91cCA8LSBnYW1tNCgKICBhdmdfYWNjIH4gSW50Z3JwICsgVGltZSArIEFnZSArIFNleCArIFlyc0VkdSArICAgICAgICAgICMgUGFyYW1ldHJpYyBmaXhlZCBlZmZlY3RzCiAgICBzKEJsb2NrLCBieSA9IGludGVyYWN0aW9uKEludGdycCwgVGltZSksIGsgPSA2KSwgICAgICAjIFNtb290aCB0ZXJtIGZvciBCbG9jayBieSBHcm91cCDDlyBUaW1lIGludGVyYWN0aW9uOkZpdHMgYSBzZXBhcmF0ZSBzbW9vdGggbGVhcm5pbmcgY3VydmUgb3ZlciBCbG9jayBmb3IgZWFjaCB1bmlxdWUgY29tYmluYXRpb24gb2YgaW50ZXJ2ZW50aW9uIGdyb3VwIChJbnRncnApIGFuZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lcG9pbnQgKFRpbWUpLlRoZSBpbnRlcmFjdGlvbigpIGZ1bmN0aW9uIGRlZmluZXMgdGhlc2Ugc3ViZ3JvdXBzLgogIHJhbmRvbSA9IH4oMSB8IFN1YmplY3QpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSYW5kb20gaW50ZXJjZXB0cyBmb3IgZWFjaCBzdWJqZWN0IChsbWU0LXN0eWxlIGZvcm11bGEpCiAgZGF0YSA9IEFzc29jTG9uZ2ludCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKKQoKIyBTdW1tYXJpemUgZml4ZWQgZWZmZWN0cyBhbmQgc21vb3RoIHRlcm1zIGZyb20gdGhlIEdBTSBwYXJ0IChtZ2N2OjpnYW0gb2JqZWN0KQpzdW1tYXJ5KGdhbW00X21vZGVsX2dyb3VwJGdhbSkKCiMgU3VtbWFyaXplIHJhbmRvbSBlZmZlY3RzIGZyb20gdGhlIExNRSBwYXJ0IChsbWU0OjptZXJNb2Qgb2JqZWN0KQpzdW1tYXJ5KGdhbW00X21vZGVsX2dyb3VwJG1lcikKCiMgUGxvdCB0aGUgc21vb3RoIHRlcm1zIHdpdGggcmVzaWR1YWxzCnBsb3QoZ2FtbTRfbW9kZWxfZ3JvdXAkZ2FtLCByZXNpZHVhbHMgPSBUUlVFLCBwY2ggPSAxNikKYGBgCgoKYGBge3J9CiMgU3RlcCAxOiBFeHRyYWN0IHNtb290aCB0ZXJtIGVzdGltYXRlcyBmcm9tIHRoZSBmaXR0ZWQgR0FNTSBtb2RlbAojIFRoaXMgaW5jbHVkZXMgZXN0aW1hdGVkIHZhbHVlcyBhbmQgc3RhbmRhcmQgZXJyb3JzIGZvciBlYWNoIHNtb290aCBmdW5jdGlvbiBpbiB0aGUgbW9kZWwKc21vb3Roc19kZiA8LSBncmF0aWE6OnNtb290aF9lc3RpbWF0ZXMoZ2FtbV9tb2RlbF9ncm91cCRnYW0pCgojIFN0ZXAgMjogSW5zcGVjdCB0aGUgY29sdW1uIG5hbWVzIHRvIGlkZW50aWZ5IGhvdyBzbW9vdGggdGVybXMgYXJlIGxhYmVsZWQKIyBVc2VmdWwgZm9yIGNvbmZpcm1pbmcgd2hpY2ggY29sdW1uIGNvbnRhaW5zIHRoZSBzbW9vdGggbGFiZWxzIChlLmcuLCAiLnNtb290aCIpCnByaW50KGNvbG5hbWVzKHNtb290aHNfZGYpKSAgIyBEaWFnbm9zdGljIHN0ZXAgdG8gdW5kZXJzdGFuZCBzdHJ1Y3R1cmUgb2Ygc21vb3Roc19kZgoKCiMgU3RlcCAzOiBDcmVhdGUgbGFiZWwgZm9yIGVhY2ggZ3JvdXAgw5cgdGltZSBpbnRlcmFjdGlvbgojIEJhc2VkIG9uIHBhdHRlcm4gbWF0Y2hpbmcgd2l0aGluIHRoZSBgLnNtb290aGAgY29sdW1uCiMgVGhpcyBpcyB1c2VkIGZvciBjb2xvcmluZyBhbmQgZ3JvdXBpbmcgaW4gdGhlIHBsb3QKc21vb3Roc19kZiA8LSBzbW9vdGhzX2RmICU+JQogIG11dGF0ZShHcm91cCA9IGNhc2Vfd2hlbigKICAgIGdyZXBsKCJMaWdodFxcLnBvc3RJbnQiLCAuc21vb3RoKSB+ICJMaWdodCAtIFBvc3QiLAogICAgZ3JlcGwoIk1vZFZpZ1xcLnBvc3RJbnQiLCAuc21vb3RoKSB+ICJNb2RWaWcgLSBQb3N0IiwKICAgIGdyZXBsKCJMaWdodFxcLnByZUludCIsIC5zbW9vdGgpIH4gIkxpZ2h0IC0gUHJlIiwKICAgIGdyZXBsKCJNb2RWaWdcXC5wcmVJbnQiLCAuc21vb3RoKSB+ICJNb2RWaWcgLSBQcmUiLAogICAgVFJVRSB+ICJPdGhlciIgICMgQ2F0Y2gtYWxsIGZhbGxiYWNrIChzaG91bGRu4oCZdCB0eXBpY2FsbHkgb2NjdXIpCiAgKSkKYGBgCgpgYGB7cn0KIyBTdGVwIDE6IEV4dHJhY3Qgc21vb3RoIHRlcm0gZXN0aW1hdGVzIGZyb20gdGhlIGZpdHRlZCBHQU1NIG1vZGVsCiMgVGhpcyBpbmNsdWRlcyBlc3RpbWF0ZWQgdmFsdWVzIGFuZCBzdGFuZGFyZCBlcnJvcnMgZm9yIGVhY2ggc21vb3RoIGZ1bmN0aW9uIGluIHRoZSBtb2RlbApzbW9vdGhzX2RmNCA8LSBncmF0aWE6OnNtb290aF9lc3RpbWF0ZXMoZ2FtbTRfbW9kZWxfZ3JvdXAkZ2FtKQoKIyBTdGVwIDI6IEluc3BlY3QgdGhlIGNvbHVtbiBuYW1lcyB0byBpZGVudGlmeSBob3cgc21vb3RoIHRlcm1zIGFyZSBsYWJlbGVkCiMgVXNlZnVsIGZvciBjb25maXJtaW5nIHdoaWNoIGNvbHVtbiBjb250YWlucyB0aGUgc21vb3RoIGxhYmVscyAoZS5nLiwgIi5zbW9vdGgiKQpwcmludChjb2xuYW1lcyhzbW9vdGhzX2RmNCkpICAjIERpYWdub3N0aWMgc3RlcCB0byB1bmRlcnN0YW5kIHN0cnVjdHVyZSBvZiBzbW9vdGhzX2RmCgoKIyBTdGVwIDM6IENyZWF0ZSBsYWJlbCBmb3IgZWFjaCBncm91cCDDlyB0aW1lIGludGVyYWN0aW9uCiMgQmFzZWQgb24gcGF0dGVybiBtYXRjaGluZyB3aXRoaW4gdGhlIGAuc21vb3RoYCBjb2x1bW4KIyBUaGlzIGlzIHVzZWQgZm9yIGNvbG9yaW5nIGFuZCBncm91cGluZyBpbiB0aGUgcGxvdApzbW9vdGhzX2RmNCA8LSBzbW9vdGhzX2RmNCAlPiUKICBtdXRhdGUoR3JvdXAgPSBjYXNlX3doZW4oCiAgICBncmVwbCgiTGlnaHRcXC5wb3N0SW50IiwgLnNtb290aCkgfiAiTGlnaHQgLSBQb3N0IiwKICAgIGdyZXBsKCJNb2RWaWdcXC5wb3N0SW50IiwgLnNtb290aCkgfiAiTW9kVmlnIC0gUG9zdCIsCiAgICBncmVwbCgiTGlnaHRcXC5wcmVJbnQiLCAuc21vb3RoKSB+ICJMaWdodCAtIFByZSIsCiAgICBncmVwbCgiTW9kVmlnXFwucHJlSW50IiwgLnNtb290aCkgfiAiTW9kVmlnIC0gUHJlIiwKICAgIFRSVUUgfiAiT3RoZXIiICAjIENhdGNoLWFsbCBmYWxsYmFjayAoc2hvdWxkbuKAmXQgdHlwaWNhbGx5IG9jY3VyKQogICkpCgojIFN0ZXAgNDogQ3JlYXRlIGEgVFZFTS1zdHlsZSBsaW5lIHBsb3Qgc2hvd2luZyBlc3RpbWF0ZWQgbGVhcm5pbmcgY3VydmVzIG92ZXIgQmxvY2sKIyBFYWNoIGxpbmUgcmVwcmVzZW50cyB0aGUgc21vb3RoIHRyYWplY3RvcnkgZm9yIGEgR3JvdXAgw5cgVGltZSBjb21iaW5hdGlvbgojIEEgcmliYm9uIGlzIGFkZGVkIHRvIHNob3cgwrExIHN0YW5kYXJkIGVycm9yIGFyb3VuZCB0aGUgZXN0aW1hdGVkIHNtb290aApnZ3Bsb3Qoc21vb3Roc19kZiwgYWVzKHggPSBCbG9jaywgeSA9IC5lc3RpbWF0ZSwgY29sb3IgPSBHcm91cCwgZmlsbCA9IEdyb3VwKSkgKwogIGdlb21fbGluZShzaXplID0gMS4yKSArICAjIExpbmUgcGxvdCBvZiBlc3RpbWF0ZWQgc21vb3RoCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSAuZXN0aW1hdGUgLSAuc2UsIHltYXggPSAuZXN0aW1hdGUgKyAuc2UpLCAKICAgICAgICAgICAgICBhbHBoYSA9IDAuMiwgY29sb3IgPSBOQSkgKyAgIyBTaGFkZWQgY29uZmlkZW5jZSBiYW5kCiAgbGFicygKICAgIHRpdGxlID0gIlRWRU0tc3R5bGUgUGxvdCBvZiBBY2N1cmFjeSBieSBCbG9jayBhbmQgR3JvdXAgw5cgVGltZVxuIC0gR2FtbSIsCiAgICB4ID0gIkJsb2NrIiwgeSA9ICJFc3RpbWF0ZWQgQWNjdXJhY3kiLAogICAgY29sb3IgPSAiR3JvdXAgw5cgVGltZSIsIGZpbGwgPSAiR3JvdXAgw5cgVGltZSIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSAgIyBDbGVhbiB2aXN1YWwgc3R5bGUKCgpnZ3Bsb3Qoc21vb3Roc19kZjQsIGFlcyh4ID0gQmxvY2ssIHkgPSAuZXN0aW1hdGUsIGNvbG9yID0gR3JvdXAsIGZpbGwgPSBHcm91cCkpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDEuMikgKyAgIyBMaW5lIHBsb3Qgb2YgZXN0aW1hdGVkIHNtb290aAogIGdlb21fcmliYm9uKGFlcyh5bWluID0gLmVzdGltYXRlIC0gLnNlLCB5bWF4ID0gLmVzdGltYXRlICsgLnNlKSwgCiAgICAgICAgICAgICAgYWxwaGEgPSAwLjIsIGNvbG9yID0gTkEpICsgICMgU2hhZGVkIGNvbmZpZGVuY2UgYmFuZAogIGxhYnMoCiAgICB0aXRsZSA9ICJUVkVNLXN0eWxlIFBsb3Qgb2YgQWNjdXJhY3kgYnkgQmxvY2sgYW5kIEdyb3VwIMOXIFRpbWVcbiAtIEdhbW00IiwKICAgIHggPSAiQmxvY2siLCB5ID0gIkVzdGltYXRlZCBBY2N1cmFjeSIsCiAgICBjb2xvciA9ICJHcm91cCDDlyBUaW1lIiwgZmlsbCA9ICJHcm91cCDDlyBUaW1lIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICAjIENsZWFuIHZpc3VhbCBzdHlsZQpgYGAKCgoKYGBge3J9CiMgU3RlcCAxOiBBZGQgVGltZVBlcmlvZCBjb2x1bW4Kc21vb3Roc19kZiA8LSBzbW9vdGhzX2RmICU+JQogIG11dGF0ZShUaW1lUGVyaW9kID0gY2FzZV93aGVuKAogICAgZ3JlcGwoInByZUludCIsIC5zbW9vdGgpIH4gIlByZSIsCiAgICBncmVwbCgicG9zdEludCIsIC5zbW9vdGgpIH4gIlBvc3QiLAogICAgVFJVRSB+ICJPdGhlciIKICApKQoKIyBTdGVwIDI6IFBsb3Qgd2l0aCBmYWNldHMKZ2dwbG90KHNtb290aHNfZGYsIGFlcyh4ID0gQmxvY2ssIHkgPSAuZXN0aW1hdGUsIGNvbG9yID0gR3JvdXAsIGZpbGwgPSBHcm91cCkpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDEuMikgKwogIGdlb21fcmliYm9uKGFlcyh5bWluID0gLmVzdGltYXRlIC0gLnNlLCB5bWF4ID0gLmVzdGltYXRlICsgLnNlKSwgYWxwaGEgPSAwLjIsIGNvbG9yID0gTkEpICsKICBmYWNldF93cmFwKH5UaW1lUGVyaW9kKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRWRU0tc3R5bGUgUGxvdCBvZiBBY2N1cmFjeSBieSBCbG9jayAtIEdhbW0iLAogICAgeCA9ICJCbG9jayIsIHkgPSAiRXN0aW1hdGVkIEFjY3VyYWN5IiwKICAgIGNvbG9yID0gIkdyb3VwIiwgZmlsbCA9ICJHcm91cCIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KQoKCiMgU3RlcCAxOiBBZGQgVGltZVBlcmlvZCBjb2x1bW4Kc21vb3Roc19kZjQgPC0gc21vb3Roc19kZjQgJT4lCiAgbXV0YXRlKFRpbWVQZXJpb2QgPSBjYXNlX3doZW4oCiAgICBncmVwbCgicHJlSW50IiwgLnNtb290aCkgfiAiUHJlIiwKICAgIGdyZXBsKCJwb3N0SW50IiwgLnNtb290aCkgfiAiUG9zdCIsCiAgICBUUlVFIH4gIk90aGVyIgogICkpCgojIFN0ZXAgMjogUGxvdCB3aXRoIGZhY2V0cwpnZ3Bsb3Qoc21vb3Roc19kZjQsIGFlcyh4ID0gQmxvY2ssIHkgPSAuZXN0aW1hdGUsIGNvbG9yID0gR3JvdXAsIGZpbGwgPSBHcm91cCkpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDEuMikgKwogIGdlb21fcmliYm9uKGFlcyh5bWluID0gLmVzdGltYXRlIC0gLnNlLCB5bWF4ID0gLmVzdGltYXRlICsgLnNlKSwgYWxwaGEgPSAwLjIsIGNvbG9yID0gTkEpICsKICBmYWNldF93cmFwKH5UaW1lUGVyaW9kKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRWRU0tc3R5bGUgUGxvdCBvZiBBY2N1cmFjeSBieSBCbG9jayAtIEdhbW00IiwKICAgIHggPSAiQmxvY2siLCB5ID0gIkVzdGltYXRlZCBBY2N1cmFjeSIsCiAgICBjb2xvciA9ICJHcm91cCIsIGZpbGwgPSAiR3JvdXAiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkKCmBgYAoKCiMgYAojIGAKIyBgCiMgYAojIGAKCiMgVGhpcyBzZWN0aW9uIGxvb2sgYXQgdGhlIEVYVEVORCBiYXNlbGluZSBkYXRhIHdpdGggdGhlIGFkZGl0aW9uIG9mIHRoZSBNaWRsaWZlIHNhbXBsZQoKIyMjIyBUaGVzZSBkZW1vZ3JhcGhpY3MgaGFzIG9ubHkgQWdlIGZvciBtaWRsaWZlIGJlY2F1c2UgYXQgdGhlIHRpbWUgY29sbGVjdGVkLCByZXN0IG9mIGRlbW8gdmFyIHdlcmUgbWlzc2luZy4gTmVlZCB0byByZXR1cm4gdG8gUmVkY2FwIHRvIHJldHJpZXZlIHRoZSByZXN0CmBgYHtyfQojIFRhc2tTd2l0Y2hNT2IgPC0gcmVhZC5jc3YoIi9Wb2x1bWVzL3Zvc3NsYWJocGMvUHJvamVjdHMvQmlrZUV4dGVuZC8zLUV4cGVyaW1lbnQvMi1EYXRhL1BhcnRpY2lwYW50cy9CYXNlbGluZVN1bW1hcmllcy9UYXNrU3dpdGNoX1RyaWFsX1ByZV9GdWxsLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSlbLCAtMV0KIyBUYXNrU3dpdGNoTU9iIDwtIFRhc2tTd2l0Y2hNT2JbLCBjKDE6NywxMjozMyldCgojIFRoaXMgZGYgaGFzIGFscmVhZHkgZHJvcHBlZCB0aGUgc2FtZSBzdWJzIGRyb3BwZWQgaW4gdGhlIGludGVydmVudGlvbiBhbmFseXNpcwpUYXNrU3dpdGNoTU8gPC0gcmVhZC5jc3YoIi9Wb2x1bWVzL3Zvc3NsYWJocGMvUHJvamVjdHMvQmlrZUV4dGVuZC8zLUV4cGVyaW1lbnQvMi1EYXRhL0JJRFMvZGVyaXZhdGl2ZXMvQnJ5YW4vUHJvamVjdHMvVGFza19Td2l0Y2gtSW50ZXJ2ZW50aW9uL0FyY2gvUHJlX1RTX0xvbmcuY3N2Iiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKVssIC0xXSAlPiUgbXV0YXRlKFRpbWUgPSAicHJlIikKVGFza1N3aXRjaE1PIDwtIFRhc2tTd2l0Y2hNT1ssIC1jKDMxOjM1KV0KYmlrZSA8LSByZWFkLmNzdigiL1ZvbHVtZXMvdm9zc2xhYmhwYy9Qcm9qZWN0cy9CaWtlRXh0ZW5kLzMtRXhwZXJpbWVudC8yLURhdGEvQklEUy9kZXJpdmF0aXZlcy9Ccnlhbi9Qcm9qZWN0cy9UZXJ0aWFyeVN1bGNpL0VYVEVORF9sYWJlbHMvY29kZS8wMF9BbmFseXNpcy8wMF9WYXJpYWJsZXMvQmlrZURlbW8uY3N2IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCmNvbG5hbWVzKGJpa2UpWzE6MTJdIDwtIGMoIlN1YmplY3QiLCAiU2V4IiwgIkFnZSIsICJZcnNFZHUiLCAiTW9jYSIsICJSQVZMVCIsICJSQVZMVHBvc3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICJBbmltYWxGbGVuY3kiLCAiSW50Z3JwIiwgIlJlbF9WbzJtIiwgIlJlc3BFeFJhdGlvIiwgIkRTU1QiKQpiaWtlIDwtIGJpa2VbLCAtYygyLDMpXQoKIyBEcm9wIHJvd3Mgd2l0aCBtaXNzaW5nIGNhcmRpb3Jlc3BpcmF0b3J5IGZpdG5lc3MgZGF0YQpiaWtlIDwtIGJpa2UgJT4lIGRyb3BfbmEoUmVsX1ZvMm0pCgpUYXNrU3dpdGNoTU8gPC0gVGFza1N3aXRjaE1PICU+JQogIGxlZnRfam9pbihiaWtlLCBieSA9ICJTdWJqZWN0IikKCiMgRW5zdXJlIFN1YmplY3QgaXMgdHJlYXRlZCBhcyBhIGNoYXJhY3RlciB0byBleHRyYWN0IHByZWZpeCB0byBjcmVhdGUgZ3JvdXBpbmcgdmFyaWFibGUKVGFza1N3aXRjaE1PIDwtIFRhc2tTd2l0Y2hNTyAlPiUKICBtdXRhdGUoCiAgICBTdWJqZWN0ID0gYXMuY2hhcmFjdGVyKFN1YmplY3QpLAogICAgRVhUR3JvdXAgPSBjYXNlX3doZW4oCiAgICAgIHN0cl9zdGFydHMoU3ViamVjdCwgIjUiKSB+ICJNaWRsaWZlIiwKICAgICAgc3RyX3N0YXJ0cyhTdWJqZWN0LCAiMiIpIH4gIk9sZGVyIiwKICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8gICMgaW4gY2FzZSB0aGVyZSBhcmUgb3RoZXIgSURzCiAgICApCiAgKQoKVGFza1N3aXRjaE1PJFN1YmplY3QgPC0gYXMuZmFjdG9yKFRhc2tTd2l0Y2hNTyRTdWJqZWN0KQpUYXNrU3dpdGNoTU8kRVhUR3JvdXAgPC0gYXMuZmFjdG9yKFRhc2tTd2l0Y2hNTyRFWFRHcm91cCkKVGFza1N3aXRjaE1PJEFnZSA8LSBhcy5pbnRlZ2VyKFRhc2tTd2l0Y2hNTyRBZ2UpClRhc2tTd2l0Y2hNTyRZcnNFZHUgPC0gYXMuaW50ZWdlcihUYXNrU3dpdGNoTU8kWXJzRWR1KQpUYXNrU3dpdGNoTU8kQ29uZGl0aW9uIDwtIGFzLmZhY3RvcihUYXNrU3dpdGNoTU8kQ29uZGl0aW9uKQpUYXNrU3dpdGNoTU8kVHJpYWwuVHlwZSA8LSBhcy5mYWN0b3IoVGFza1N3aXRjaE1PJFRyaWFsLlR5cGUpClRhc2tTd2l0Y2hNTyRTZXggPC0gYXMuZmFjdG9yKFRhc2tTd2l0Y2hNTyRTZXgpCgpgYGAKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnN1YnMxIDwtIHVuaXF1ZShUYXNrU3dpdGNoTU9iJFN1YmplY3QpCnN1YnMyIDwtIHVuaXF1ZShUYXNrU3dpdGNoTU8kU3ViamVjdCkKCm1pc3NpbmdfaW5fZGYyIDwtIHNldGRpZmYoc3ViczEsIHN1YnMyKQoKbWlzc2luZ19pbl9kZjEgPC0gc2V0ZGlmZihzdWJzMiwgc3ViczEpCgpjYXQoIlN1YmplY3RzIGluIGRmMSBidXQgbm90IGluIGRmMjpcbiIpCnByaW50KG1pc3NpbmdfaW5fZGYyKQoKY2F0KCJcblN1YmplY3RzIGluIGRmMiBidXQgbm90IGluIGRmMTpcbiIpCnByaW50KG1pc3NpbmdfaW5fZGYxKQoKYGBgCgoKYGBge3J9CmNvbnRyYXN0cyhUYXNrU3dpdGNoTU8kVHJpYWwuVHlwZSkKcHJpbnQoIk1peGluZyBDb3N0IGlzIHJlZmVyZW5jaW5nIFJlcGFldGVkLCBTaW5nbGUtUmVwZWF0LCB0aGVyZWZvcmUgdGFrZSB0aGUgbmVnYXRpdmUgb2YgdGhlIGJldGEgc2hvd24gZm9yIHNpbmdsZSAobXVsdGlwbHkgYnkgLTEpIikKcHJpbnQoIlN3aXRjaGluZyBDb3N0IGlzIHJlZmVyZW5jZWQgaGVyZSBjb3JyZWN0bHksIFN3aXRjaGluZyAtIFJlcGVhdGVkLCB0aGVyZm9yZSBpbnRlcnByZXQgdGhlIGJldGEgYXMgaXMiKQpgYGAKCgojIyMjIEFuYWx5c2luZyBBZ2UgYXMgYSBjb250aW5vdXMgdmFyaWFibGUKIyMjIEFnZSArIENvbmRpdGlvbiAqIFRyaWFsLlR5cGUKIyMjIyBBZ2UgPC0gTWluPTQwLCBNYXg9ODAgCgpgYGB7cn0KCkFnaW5nc2ltcGxlX21vZGVsIDwtIGxtZXIoCiAgQ29ycmVjdC5SVCB+IEFnZSArIENvbmRpdGlvbiAqIFRyaWFsLlR5cGUgKyAoMSB8IFN1YmplY3QpLAogIGRhdGEgPSBUYXNrU3dpdGNoTU8KKQpzdW1tYXJ5KEFnaW5nc2ltcGxlX21vZGVsKSAjLCBkZGY9YygiS2Vud2FyZC1Sb2dlciIpKQpwcmludCgiTm90ZTogUmVjYWxsIHRvIGludGVycHJldCB0aGUgc2luZ2xlIHRyaWFsIGJldGFzIGFzIG5lZ2F0aXZlIChtdWx0aXBseSBieSAtMSkgdG8gaW5mZXIgTWl4aW5nIENvc3QiKQoKCiMgUHJlZGljdCBSVCBhY3Jvc3MgQ29uZGl0aW9uIGFuZCBUcmlhbC5UeXBlIGZvciB0aHJlZSByZXByZXNlbnRhdGl2ZSBhZ2UgdmFsdWVzCkFnaW5nc2ltcGxlX21vZGVsLnByZWRpY3QgPC0gZ2dwcmVkaWN0KAogIEFnaW5nc2ltcGxlX21vZGVsLAogIHRlcm1zID0gYygiQ29uZGl0aW9uIiwgIlRyaWFsLlR5cGUiKSAgIyBZb3UgY2FuIGNoYW5nZSB0aGVzZSBhZ2UgdmFsdWVzIGFzIG5lZWRlZAopCgpBZ2luZ3NpbXBsZV9tb2RlbC5QTE9UIDwtIGdncGxvdChBZ2luZ3NpbXBsZV9tb2RlbC5wcmVkaWN0LCBhZXMoeCA9IHgsIHkgPSBwcmVkaWN0ZWQsIGdyb3VwID0gZ3JvdXApKSArCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZSA9IGdyb3VwLCBjb2xvciA9IGdyb3VwKSwgc2l6ZSA9IDEuMikgKyAgIyBUcmlhbC5UeXBlIGFzIGxpbmUgdHlwZXMvY29sb3JzCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCwgZmlsbCA9IGdyb3VwKSwgCiAgICAgICAgICAgICAgYWxwaGEgPSAwLjIsIGNvbG9yID0gTkEpICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIlByZWRpY3RlZCBSVCBieSBDb25kaXRpb24gYW5kIFRyaWFsIFR5cGUiLAogICAgeCA9ICJDb25kaXRpb24iLAogICAgeSA9ICJQcmVkaWN0ZWQgUlQgKG1zKSIsCiAgICBsaW5ldHlwZSA9ICJUcmlhbCBUeXBlIiwKICAgIGNvbG9yID0gIlRyaWFsIFR5cGUiLAogICAgZmlsbCA9ICJUcmlhbCBUeXBlIgogICkKQWdpbmdzaW1wbGVfbW9kZWwuUExPVAoKYGBgCgoKIyMjIyBBbmFseXNpbmcgQWdlIGFzIGEgY29udGlub3VzIHZhcmlhYmxlCiMjIyBBZ2UgKyBDb25kaXRpb24gKiBUcmlhbC5UeXBlCiMjIyMgQWdlIDwtIE1pbj00MCwgTWF4PTgwIAoKYGBge3J9CgpBZ2luZ3NpbXBsZV9tb2RlbCA8LSBsbWVyKAogIENvcnJlY3QuUlQgfiBBZ2UgKyBDb25kaXRpb24gKiBUcmlhbC5UeXBlICsgKDEgfCBTdWJqZWN0KSwKICBkYXRhID0gVGFza1N3aXRjaE1PCikKc3VtbWFyeShBZ2luZ3NpbXBsZV9tb2RlbCkgIywgZGRmPWMoIktlbndhcmQtUm9nZXIiKSkKcHJpbnQoIk5vdGU6IFJlY2FsbCB0byBpbnRlcnByZXQgdGhlIHNpbmdsZSB0cmlhbCBiZXRhcyBhcyBuZWdhdGl2ZSAobXVsdGlwbHkgYnkgLTEpIHRvIGluZmVyIE1peGluZyBDb3N0IikKCgojIFByZWRpY3QgUlQgYWNyb3NzIENvbmRpdGlvbiBhbmQgVHJpYWwuVHlwZSBmb3IgdGhyZWUgcmVwcmVzZW50YXRpdmUgYWdlIHZhbHVlcwpBZ2luZ3NpbXBsZV9tb2RlbC5wcmVkaWN0IDwtIGdncHJlZGljdCgKICBBZ2luZ3NpbXBsZV9tb2RlbCwKICB0ZXJtcyA9IGMoIkNvbmRpdGlvbiIsICJUcmlhbC5UeXBlIikgICMgWW91IGNhbiBjaGFuZ2UgdGhlc2UgYWdlIHZhbHVlcyBhcyBuZWVkZWQKKQoKQWdpbmdzaW1wbGVfbW9kZWwuUExPVCA8LSBnZ3Bsb3QoQWdpbmdzaW1wbGVfbW9kZWwucHJlZGljdCwgYWVzKHggPSB4LCB5ID0gcHJlZGljdGVkLCBncm91cCA9IGdyb3VwKSkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGUgPSBncm91cCwgY29sb3IgPSBncm91cCksIHNpemUgPSAxLjIpICsgICMgVHJpYWwuVHlwZSBhcyBsaW5lIHR5cGVzL2NvbG9ycwogIGdlb21fcmliYm9uKGFlcyh5bWluID0gY29uZi5sb3csIHltYXggPSBjb25mLmhpZ2gsIGZpbGwgPSBncm91cCksIAogICAgICAgICAgICAgIGFscGhhID0gMC4yLCBjb2xvciA9IE5BKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KQogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJQcmVkaWN0ZWQgUlQgYnkgQ29uZGl0aW9uIGFuZCBUcmlhbCBUeXBlIGF0IFNlbGVjdGVkIEFnZXMiLAogICAgeCA9ICJDb25kaXRpb24iLAogICAgeSA9ICJQcmVkaWN0ZWQgUlQgKG1zKSIsCiAgICBsaW5ldHlwZSA9ICJUcmlhbCBUeXBlIiwKICAgIGNvbG9yID0gIlRyaWFsIFR5cGUiLAogICAgZmlsbCA9ICJUcmlhbCBUeXBlIgogICkKQWdpbmdzaW1wbGVfbW9kZWwuUExPVAoKCiMgUHJlZGljdCBSVCBhY3Jvc3MgQ29uZGl0aW9uIGFuZCBUcmlhbC5UeXBlIGZvciB0aHJlZSByZXByZXNlbnRhdGl2ZSBhZ2UgdmFsdWVzCkFnaW5nc2ltcGxlX21vZGVsLnByZWRpY3QgPC0gZ2dwcmVkaWN0KAogIEFnaW5nc2ltcGxlX21vZGVsLAogIHRlcm1zID0gYygiQ29uZGl0aW9uIiwgIlRyaWFsLlR5cGUiLCAiQWdlIFs1MCw2NSw4MF0iKSAgIyBZb3UgY2FuIGNoYW5nZSB0aGVzZSBhZ2UgdmFsdWVzIGFzIG5lZWRlZAopCgpBZ2luZ3NpbXBsZS5QTE9UMiA8LSBnZ3Bsb3QoQWdpbmdzaW1wbGVfbW9kZWwucHJlZGljdCwgYWVzKHggPSB4LCB5ID0gcHJlZGljdGVkLCBncm91cCA9IGdyb3VwKSkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGUgPSBncm91cCwgY29sb3IgPSBncm91cCksIHNpemUgPSAxLjIpICsgICMgVHJpYWwuVHlwZSBhcyBsaW5lIHR5cGVzL2NvbG9ycwogIGdlb21fcmliYm9uKGFlcyh5bWluID0gY29uZi5sb3csIHltYXggPSBjb25mLmhpZ2gsIGZpbGwgPSBncm91cCksIAogICAgICAgICAgICAgIGFscGhhID0gMC4yLCBjb2xvciA9IE5BKSArCiAgZmFjZXRfd3JhcCh+ZmFjZXQsIGxhYmVsbGVyID0gbGFiZWxfYm90aCkgKyAgIyBGYWNldHMgYnkgQWdlIHZhbHVlCiAgeWxpbSg2MDAsIDE1MDApICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIlByZWRpY3RlZCBSVCBieSBDb25kaXRpb24gYW5kIFRyaWFsIFR5cGVcbiBhdCBTZWxlY3RlZCBBZ2VzIiwKICAgIHggPSAiQ29uZGl0aW9uIiwKICAgIHkgPSAiUHJlZGljdGVkIFJUIChtcykiLAogICAgbGluZXR5cGUgPSAiVHJpYWwgVHlwZSIsCiAgICBjb2xvciA9ICJUcmlhbCBUeXBlIiwKICAgIGZpbGwgPSAiVHJpYWwgVHlwZSIKICApCkFnaW5nc2ltcGxlLlBMT1QyCgpgYGAKCgojIyMjIEFuYWx5c2luZyBBZ2UgYXMgYSBjb250aW5vdXMgdmFyaWFibGUKIyMjIEFnZSArIENvbmRpdGlvbiAqIFRyaWFsLlR5cGUKIyMjIyBBZ2UgPC0gTWluPTQwLCBNYXg9ODAgCgpgYGB7cn0KCkZpdG5lc3Nfc2ltcGxlX21vZGVsIDwtIGxtZXIoCiAgQ29ycmVjdC5SVCB+IEFnZSArIFJlbF9WbzJtICsgQ29uZGl0aW9uICogVHJpYWwuVHlwZSArICgxIHwgU3ViamVjdCksCiAgZGF0YSA9IFRhc2tTd2l0Y2hNTwopCnN1bW1hcnkoRml0bmVzc19zaW1wbGVfbW9kZWwpICMsIGRkZj1jKCJLZW53YXJkLVJvZ2VyIikpCnByaW50KCJOb3RlOiBSZWNhbGwgdG8gaW50ZXJwcmV0IHRoZSBzaW5nbGUgdHJpYWwgYmV0YXMgYXMgbmVnYXRpdmUgKG11bHRpcGx5IGJ5IC0xKSB0byBpbmZlciBNaXhpbmcgQ29zdCIpCgoKIyBQcmVkaWN0IFJUIGFjcm9zcyBDb25kaXRpb24gYW5kIFRyaWFsLlR5cGUgZm9yIHRocmVlIHJlcHJlc2VudGF0aXZlIGFnZSB2YWx1ZXMKRml0bmVzc19zaW1wbGVfbW9kZWwucHJlZGljdCA8LSBnZ3ByZWRpY3QoCiAgRml0bmVzc19zaW1wbGVfbW9kZWwsCiAgdGVybXMgPSBjKCJDb25kaXRpb24iLCAiVHJpYWwuVHlwZSIpICAjIFlvdSBjYW4gY2hhbmdlIHRoZXNlIGFnZSB2YWx1ZXMgYXMgbmVlZGVkCikKCkZpdG5lc3Nfc2ltcGxlX21vZGVsLlBMT1QgPC0gZ2dwbG90KEZpdG5lc3Nfc2ltcGxlX21vZGVsLnByZWRpY3QsIGFlcyh4ID0geCwgeSA9IHByZWRpY3RlZCwgZ3JvdXAgPSBncm91cCkpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlID0gZ3JvdXAsIGNvbG9yID0gZ3JvdXApLCBzaXplID0gMS4yKSArICAjIFRyaWFsLlR5cGUgYXMgbGluZSB0eXBlcy9jb2xvcnMKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGNvbmYubG93LCB5bWF4ID0gY29uZi5oaWdoLCBmaWxsID0gZ3JvdXApLCAKICAgICAgICAgICAgICBhbHBoYSA9IDAuMiwgY29sb3IgPSBOQSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksCiAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkKICApICsKICBsYWJzKAogICAgdGl0bGUgPSAiUHJlZGljdGVkIFJUIGJ5IENvbmRpdGlvbiBhbmQgVHJpYWwgVHlwZSIsCiAgICB4ID0gIkNvbmRpdGlvbiIsCiAgICB5ID0gIlByZWRpY3RlZCBSVCAobXMpIiwKICAgIGxpbmV0eXBlID0gIlRyaWFsIFR5cGUiLAogICAgY29sb3IgPSAiVHJpYWwgVHlwZSIsCiAgICBmaWxsID0gIlRyaWFsIFR5cGUiCiAgKQpGaXRuZXNzX3NpbXBsZV9tb2RlbC5QTE9UCgoKIyBQcmVkaWN0IFJUIGFjcm9zcyBDb25kaXRpb24gYW5kIFRyaWFsLlR5cGUgZm9yIHRocmVlIHJlcHJlc2VudGF0aXZlIGFnZSB2YWx1ZXMKRml0bmVzc19zaW1wbGVfbW9kZWwucHJlZGljdCA8LSBnZ3ByZWRpY3QoCiAgRml0bmVzc19zaW1wbGVfbW9kZWwsCiAgdGVybXMgPSBjKCJDb25kaXRpb24iLCAiVHJpYWwuVHlwZSIsICJSZWxfVm8ybSBbMTYuMzAsMTkuNzAsMjQuOTBdIikgICMgWW91IGNhbiBjaGFuZ2UgdGhlc2UgYWdlIHZhbHVlcyBhcyBuZWVkZWQKKQoKRml0bmVzc19zaW1wbGVfbW9kZWwuUExPVDIgPC0gZ2dwbG90KEZpdG5lc3Nfc2ltcGxlX21vZGVsLnByZWRpY3QsIGFlcyh4ID0geCwgeSA9IHByZWRpY3RlZCwgZ3JvdXAgPSBncm91cCkpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlID0gZ3JvdXAsIGNvbG9yID0gZ3JvdXApLCBzaXplID0gMS4yKSArICAjIFRyaWFsLlR5cGUgYXMgbGluZSB0eXBlcy9jb2xvcnMKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGNvbmYubG93LCB5bWF4ID0gY29uZi5oaWdoLCBmaWxsID0gZ3JvdXApLCAKICAgICAgICAgICAgICBhbHBoYSA9IDAuMiwgY29sb3IgPSBOQSkgKwogIGZhY2V0X3dyYXAofmZhY2V0LCBsYWJlbGxlciA9IGxhYmVsX2JvdGgpICsgICMgRmFjZXRzIGJ5IEFnZSB2YWx1ZQogIHlsaW0oNjAwLCAxNTAwKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KQogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJQcmVkaWN0ZWQgUlQgYnkgQ29uZGl0aW9uIGFuZCBUcmlhbCBUeXBlXG4gYXQgU2VsZWN0ZWQgUmVsVm8ybSIsCiAgICB4ID0gIkNvbmRpdGlvbiIsCiAgICB5ID0gIlByZWRpY3RlZCBSVCAobXMpIiwKICAgIGxpbmV0eXBlID0gIlRyaWFsIFR5cGUiLAogICAgY29sb3IgPSAiVHJpYWwgVHlwZSIsCiAgICBmaWxsID0gIlRyaWFsIFR5cGUiCiAgKQpGaXRuZXNzX3NpbXBsZV9tb2RlbC5QTE9UMgoKYGBgCmBgYHtyfQpGaXRuZXNzX3NpbXBsZV9tb2RlbC5QTE9UMgpBZ2luZ3NpbXBsZS5QTE9UMgpgYGAKCgoKCiMjIyMgQW5hbHlzaW5nIEFnZSBhcyBhIGNvbnRpbm91cyB2YXJpYWJsZQojIyMgQWdlICogQ29uZGl0aW9uICogVHJpYWwuVHlwZQojIyMjIEFnZSA8LSBNaW49NDAsIE1heD04MCAKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CgpBZ2luZ19tb2RlbCA8LSBsbWVyKAogIENvcnJlY3QuUlQgfiBBZ2UgKiBDb25kaXRpb24gKiBUcmlhbC5UeXBlICsgKDEgfCBTdWJqZWN0KSwKICBkYXRhID0gVGFza1N3aXRjaE1PCikKc3VtbWFyeShBZ2luZ19tb2RlbCkgIywgZGRmPWMoIktlbndhcmQtUm9nZXIiKSkKcHJpbnQoIk5vdGU6IFJlY2FsbCB0byBpbnRlcnByZXQgdGhlIHNpbmdsZSB0cmlhbCBiZXRhcyBhcyBuZWdhdGl2ZSAobXVsdGlwbHkgYnkgLTEpIHRvIGluZmVyIE1peGluZyBDb3N0IikKCgojIFByZWRpY3QgUlQgYWNyb3NzIENvbmRpdGlvbiBhbmQgVHJpYWwuVHlwZSBmb3IgdGhyZWUgcmVwcmVzZW50YXRpdmUgYWdlIHZhbHVlcwpBZ2luZ19tb2RlbC5wcmVkaWN0IDwtIGdncHJlZGljdCgKICBBZ2luZ19tb2RlbCwKICB0ZXJtcyA9IGMoIkNvbmRpdGlvbiIsICJUcmlhbC5UeXBlIiwgIkFnZSBbNTAsNjUsODBdIikgICMgWW91IGNhbiBjaGFuZ2UgdGhlc2UgYWdlIHZhbHVlcyBhcyBuZWVkZWQKKQoKQWdpbmdfbW9kZWwuUExPVCA8LSBnZ3Bsb3QoQWdpbmdfbW9kZWwucHJlZGljdCwgYWVzKHggPSB4LCB5ID0gcHJlZGljdGVkLCBncm91cCA9IGdyb3VwKSkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGUgPSBncm91cCwgY29sb3IgPSBncm91cCksIHNpemUgPSAxLjIpICsgICMgVHJpYWwuVHlwZSBhcyBsaW5lIHR5cGVzL2NvbG9ycwogIGdlb21fcmliYm9uKGFlcyh5bWluID0gY29uZi5sb3csIHltYXggPSBjb25mLmhpZ2gsIGZpbGwgPSBncm91cCksIAogICAgICAgICAgICAgIGFscGhhID0gMC4yLCBjb2xvciA9IE5BKSArCiAgZmFjZXRfd3JhcCh+ZmFjZXQsIGxhYmVsbGVyID0gbGFiZWxfYm90aCkgKyAgIyBGYWNldHMgYnkgQWdlIHZhbHVlCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KQogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJQcmVkaWN0ZWQgUlQgYnkgQ29uZGl0aW9uIGFuZCBUcmlhbCBUeXBlIGF0IFNlbGVjdGVkIEFnZXMiLAogICAgeCA9ICJDb25kaXRpb24iLAogICAgeSA9ICJQcmVkaWN0ZWQgUlQgKG1zKSIsCiAgICBsaW5ldHlwZSA9ICJUcmlhbCBUeXBlIiwKICAgIGNvbG9yID0gIlRyaWFsIFR5cGUiLAogICAgZmlsbCA9ICJUcmlhbCBUeXBlIgogICkKQWdpbmdfbW9kZWwuUExPVAoKYGBgCgojIyMjIEFuYWx5c2luZyBBZ2UgYXMgYSBjb250aW5vdXMgdmFyaWFibGUgdy8gdGhlIGFnZWdyb3VwIHZhcmlhYmxlIChNaWRsaWZlIGFuZCBPbGRlcikKIyMjIENvbmRpdGlvbiAqIFRyaWFsLlR5cGUgKiBBZ2VHcm91cCAtIHdpdGggQWdlIGFzIGEgY292YXJpYXRlCiMjIyMgQWdlIDwtIE1pbj00MCwgTWF4PTgwIApgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpBZ2luZ19taWRPbGQgPC0gbG1lcigKICBDb3JyZWN0LlJUIH4gQWdlICsgQ29uZGl0aW9uICogVHJpYWwuVHlwZSAqIEVYVEdyb3VwICsgKDEgfCBTdWJqZWN0KSwKICBkYXRhID0gVGFza1N3aXRjaE1PCikKc3VtbWFyeShBZ2luZ19taWRPbGQpICMsIGRkZj1jKCJLZW53YXJkLVJvZ2VyIikpCnByaW50KCJOb3RlOiBSZWNhbGwgdG8gaW50ZXJwcmV0IHRoZSBzaW5nbGUgdHJpYWwgYmV0YXMgYXMgbmVnYXRpdmUgKG11bHRpcGx5IGJ5IC0xKSB0byBpbmZlciBNaXhpbmcgQ29zdCIpCgoKIyBQcmVkaWN0IFJUIGFjcm9zcyBDb25kaXRpb24gYW5kIFRyaWFsLlR5cGUgZm9yIHRocmVlIHJlcHJlc2VudGF0aXZlIGFnZSB2YWx1ZXMKQWdpbmdfbWlkT2xkLnByZWRpY3QgPC0gZ2dwcmVkaWN0KAogIEFnaW5nX21pZE9sZCwKICB0ZXJtcyA9IGMoIkNvbmRpdGlvbiIsICJUcmlhbC5UeXBlIiwgIkVYVEdyb3VwIikgICMgWW91IGNhbiBjaGFuZ2UgdGhlc2UgYWdlIHZhbHVlcyBhcyBuZWVkZWQKKQoKQWdpbmdfbWlkT2xkLlBMT1QgPC0gZ2dwbG90KEFnaW5nX21pZE9sZC5wcmVkaWN0LCBhZXMoeCA9IHgsIHkgPSBwcmVkaWN0ZWQsIGdyb3VwID0gZ3JvdXApKSArCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZSA9IGdyb3VwLCBjb2xvciA9IGdyb3VwKSwgc2l6ZSA9IDEuMikgKyAgIyBUcmlhbC5UeXBlIGFzIGxpbmUgdHlwZXMvY29sb3JzCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBjb25mLmxvdywgeW1heCA9IGNvbmYuaGlnaCwgZmlsbCA9IGdyb3VwKSwgCiAgICAgICAgICAgICAgYWxwaGEgPSAwLjIsIGNvbG9yID0gTkEpICsKICBmYWNldF93cmFwKH5mYWNldCwgbGFiZWxsZXIgPSBsYWJlbF9ib3RoKSArICAjIEZhY2V0cyBieSBBZ2UgdmFsdWUKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIlByZWRpY3RlZCBSVCBieSBDb25kaXRpb24gYW5kIFRyaWFsIFR5cGUgYXQgU2VsZWN0ZWQgQWdlcyIsCiAgICB4ID0gIkNvbmRpdGlvbiIsCiAgICB5ID0gIlByZWRpY3RlZCBSVCAobXMpIiwKICAgIGxpbmV0eXBlID0gIlRyaWFsIFR5cGUiLAogICAgY29sb3IgPSAiVHJpYWwgVHlwZSIsCiAgICBmaWxsID0gIlRyaWFsIFR5cGUiCiAgKQpBZ2luZ19taWRPbGQuUExPVAoKYGBgCmBgYHtyfQpgYGAKCgpgYGB7cn0KYGBgCgoKYGBge3J9CmBgYAoKCmBgYHtyfQpgYGAKCg==