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==