If you have any questions or queries, please reach me out at

last updated: 02 April, 2022

pacman::p_load(tidyverse, janitor, arsenal, DT, DataExplorer,summarytools, psych, lavaan, mirt)
load("C:/Users/luisf/Dropbox/Puc-Rio/Projeto - ASQ 4 2021/Base - ASQ 4.RData")

1 Compare ASQ-3 and ASQ-4

Data name: data_final_merged

1.1 Descriptives

ds_final_merged %>% 
  mutate(race = case_when(
    race == 2 ~ "White",
    race == 5 ~ "Black / African America",
    TRUE ~ "Other races"
  ),
  gender = if_else(gender == 3, NA_character_,gender)
  )  %>% 
  tableby(quest~gender + race + age_9,
          data = ., 
          test=FALSE) %>% summary() 

1.2 Cronbach’s alpha

ds_final_merged %>% 
  filter(quest == 4) %>% 
  select(com_a3_1, com_a3_2, com_a3_3, com_a3_4, com_a3_5, com_a3_6) %>% 
  alpha()
ds_final_merged %>% 
  filter(quest == 4) %>% 
  select(com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6) %>% 
  alpha()

1.2.1 ASQ-3

cronbach_asq_3 <- ds_final_merged %>% 
  select(quest, com_a3_1, com_a3_2, com_a3_3, com_a3_4, com_a3_5, com_a3_6,
                     gm_a3_1,   gm_a3_2,    gm_a3_3,    gm_a3_4,    gm_a3_5,    gm_a3_6,
                     fm_a3_1,   fm_a3_2,    fm_a3_3,    fm_a3_4,    fm_a3_5,    fm_a3_6,
                     cg_a3_1,   cg_a3_2,    cg_a3_3,    cg_a3_4,    cg_a3_5,    cg_a3_6,
                     ps_a3_1,   ps_a3_2,    ps_a3_3,    ps_a3_4,    ps_a3_5,    ps_a3_6) %>% 
    pivot_longer(cols = -quest,
                 names_to = c("scale", ".value"),
                 names_pattern = "(\\w+_\\w+_)(.)") %>%
    nest_by(quest, scale) %>%
    mutate(alpha(data)$total)

1.2.2 ASQ-4

cronbach_asq_4 <- ds_final_merged %>% 
  select(quest, com_a4_1, com_a4_2,com_a4_3, com_a4_4, com_a4_5, com_a4_6, 
         gm_a4_1, gm_a4_2,gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
         fm_a4_1, fm_a4_2,fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6, 
         cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
         ps_a4_1,  ps_a4_2,  ps_a4_3,  ps_a4_4, ps_a4_5,  ps_a4_6) %>% 
    pivot_longer(cols = -quest,
                 names_to = c("scale", ".value"),
                 names_pattern = "(\\w+_\\w+_)(.)") %>%
    nest_by(quest, scale) %>%
    mutate(alpha(data)$total)

1.2.3 Double-check

ds_final_merged %>% 
  filter(quest == 2) %>% 
  select(ps_a4_1,   ps_a4_2,    ps_a4_3,    ps_a4_4,    ps_a4_5,    ps_a4_6) %>% 
  alpha(.)
ds_final_merged %>% 
  filter(quest == 8) %>% 
  select(ps_a4_1,   ps_a4_2,    ps_a4_3,    ps_a4_4,    ps_a4_5,    ps_a4_6) %>% 
  alpha(.)
ds_final_merged %>% 
  filter(quest == 12) %>% 
  select(com_a3_1,  com_a3_2,   com_a3_3,   com_a3_4, com_a3_5, com_a3_6) %>% 
  alpha(.)

1.2.4 Table

cronbach_asq_4 %>% 
  group_by(quest, scale) %>% 
  summarise(alpha=mean(raw_alpha), cor=average_r)

1.2.5 Apprendix ASQ4 & ASQ3

left_join( #just to add sample size
   
bind_cols(
  cronbach_asq_3 %>% 
    select(quest, scale, raw_alpha, average_r), #get results of asq3
  
  cronbach_asq_4 %>% 
    select(quest, scale, raw_alpha, average_r) #get results of asq4
  ) %>% 
  as.data.frame() %>% #transform into dataframe
  janitor::clean_names() %>%
  rename(asq3 = raw_alpha_3, 
         asq4 = raw_alpha_7,
         cor3 = average_r_4,
         cor4 = average_r_8) %>% #rename to make easier
  select(-scale_6, -quest_5) %>% 
  pivot_longer(cols = -c(quest_1, scale_2)) %>%  #transpose
  mutate(name = case_when(
    name == "asq3" ~ "alpha_3",
    name == "cor3" ~ "cor_3",
    name == "asq4" ~ "alpha_4",
    name == "cor4" ~ "cor_4")) %>% #rename to make easier
  mutate(scale_2 = case_when(
    scale_2 == "com_a3_" ~ "Communication",
    scale_2 == "gm_a3_" ~ "Gross Motor",
    scale_2 == "fm_a3_" ~ "Fine Motor",
    scale_2 == "cg_a3_" ~ "Problem Solving",
    scale_2 == "ps_a3_" ~ "Personal-Social")) %>% 
  pivot_wider(names_from = name, values_from = value)#inverse tranpose 
  #pivot_wider(name, scale_2, values_fn = mean)
,

ds_final_merged %>% count(quest) %>% rename(quest_1=quest) #rename to make easier
) %>% 
  select(quest_1, scale_2, alpha_3, alpha_4, cor_3, cor_4) %>% #order
  mutate(delta_percent = (alpha_4-alpha_3)/alpha_3*100) %>% 
  mutate_if(is.numeric, round, 2) %>% #round
  arrange(desc(delta_percent))

1.2.6 Graph

bind_cols(
  cronbach_asq_3 %>% 
    select(quest, scale, raw_alpha),
  
  cronbach_asq_4 %>% 
    select(quest, scale, raw_alpha)) %>% 
  as.data.frame() %>% 
  janitor::clean_names() %>%
  rename(asq3 = raw_alpha_3, 
         asq4 = raw_alpha_6) %>% 
  select(-scale_5, -quest_4) %>% 
  pivot_longer(cols = -c(quest_1, scale_2))%>%
  mutate(scale_2 = case_when(
    scale_2 == "com_a3_" ~ "Communication",
    scale_2 == "gm_a3_" ~ "Gross Motor",
    scale_2 == "fm_a3_" ~ "Fine Motor",
    scale_2 == "cg_a3_" ~ "Problem Solving",
    scale_2 == "ps_a3_" ~ "Personal-Social")) %>% 
  ggplot(., aes(x=factor(scale_2, level = c('Communication', 'Gross Motor', 'Fine Motor',
                                            "Problem Solving", "Personal-Social")), y = value, fill = name)) +
  geom_col(stat = "summary", position="dodge") +
  facet_wrap(~quest_1) +
    theme_bw() +
   theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
  labs(x = "Domain", y = "Questionnaire")

1.3 Reliability loss

ASQ-4

ds_final_merged %>% 
  filter(quest==9) %>% 
  select(ps_a4_1,ps_a4_2,ps_a4_3,ps_a4_4,ps_a4_5,ps_a4_6) %>% 
  alpha() 
ds_final_merged %>% 
  filter(quest == 9) %>% 
  {cor(.$ps_a3_4, .$ps_a4_5)}

ASQ-3

ds_final_merged %>% 
  filter(quest==9) %>% 
  select(ps_a3_1,ps_a3_2,ps_a3_3,ps_a3_4,ps_a3_5,ps_a3_6) %>% 
  alpha()

1.4 Means

ds_final_merged %>%
  select(quest, c_sum_a3, gm_sum_a3, fm_sum_a3, cg_sum_a3, ps_sum_a3,
         c_sum, gm_sum, fm_sum, cg_sum, ps_sum) %>%
  group_by(quest) %>% 
  summarise(across(contains("sum"), 
                   ~mean(.)),
                   sample = n()) %>% 
  ungroup() %>% 
  mutate_if(is.numeric,round,2) %>% 
  select(quest, sample, order(colnames(.)))
ds_final_merged %>%
  select(quest, c_sum_a3, gm_sum_a3, fm_sum_a3, cg_sum_a3, ps_sum_a3,
         c_sum, gm_sum, fm_sum, cg_sum, ps_sum) %>%
  tableone::CreateTableOne(vars =  names(.), strata = c("quest"), data = .)
  #describeBy(., group = "quest")

1.5 T tests for means

ds_final_merged %>%
    select(quest, contains("sum")) %>% 
    nest_by(quest) %>%
    summarise(categ = combn(names(data), 2, paste, collapse="-"), 
       pval = combn(data, 2, function(x) 
          t.test(x[[1]], x[[2]], paired = TRUE)$p.value), .groups = 'drop') %>% 
  as.data.frame() %>% 
  separate(categ, into = c("a3","a4"), sep = "-") %>% 
  mutate(pval = round(pval, 2)) %>% 
  mutate_at(vars(a3, a4), ~str_remove_all(.,"_a3")) %>% 
  filter(a3 == a4) %>% 
  filter(pval < 0.05) %>% 
  arrange(quest)

Looping the ds to perform all pairwise comparisons

ds_final_merged %>%
  select(quest, contains("sum")) %>% 
   pivot_longer(cols = -quest) %>%
   group_by(quest) %>% 
   summarise(pout = list(broom::tidy(pairwise.t.test(value, name, 
        p.adjust.method = "none", paired = TRUE)))) %>% 
   unnest(pout) %>% 
  as.data.frame() %>% 
  mutate_at(vars(group1, group2), ~str_remove_all(.,"_a3")) %>% 
  filter(group1 == group2) %>% 
  arrange(quest) %>% 
  mutate(p.value = round(p.value,2))

1.6 Double check

ds_final_merged %>% 
  filter(quest==16) %>% 
  {t.test(.$gm_sum, .$gm_sum_a3, paired=T, data =.)}
ds_final_merged %>% 
  filter(quest==12) %>% 
  {t.test(.$ps_sum, .$ps_sum_a3, paired=T, data =.)}

1.7 Correlations

library(correlation)
ds_final_merged %>% 
  group_by(quest) %>% 
  select(quest, c_sum_a3, gm_sum_a3, fm_sum_a3, cg_sum_a3, ps_sum_a3,
         c_sum, gm_sum, fm_sum, cg_sum, ps_sum) %>% 
  correlation() %>% 
  as.data.frame() %>% 
  mutate_at(vars(Parameter1, Parameter2), ~str_remove_all(.,"_a3")) %>% 
  filter(Parameter1 == Parameter2) 
ds_final_merged %>%
  select(quest, c_sum_a3, gm_sum_a3, fm_sum_a3, cg_sum_a3, ps_sum_a3,
         c_sum, gm_sum, fm_sum, cg_sum, ps_sum) %>%
group_by(quest) %>%
  nest() %>%
  mutate(
    correlations = map(data, corrr::correlate)
  ) %>%
  unnest(correlations) %>% 
  select(-c(contains("_a3"))) %>% 
  filter(str_detect(term, 'a3')) %>% 
  select(-data) %>% 
  pivot_longer(-c(quest,term)) %>% 
  filter(term == paste0(name,"_a3")) 

2 Compare ASQ4 ds1 & Supplementary data

2.1 Descriptive

ds %>%
  #filter(base == "sup") %>% 
  select(quest, base,
         c_sum, gm_sum, fm_sum, cg_sum, ps_sum) %>%
  tableby(interaction(quest, base) ~ ., data = .) %>% 
  summary()
  #tableone::CreateTableOne(vars =  names(.[-1]), strata = c("quest","base"), data = .) %>% 
  #print()

2.2 Plot

ds %>% 
  select(quest, base, c_sum:ps_sum) %>% 
  pivot_longer(-c(quest,base)) %>%
    mutate(name = case_when(
    name == "c_sum" ~ "Communication",
    name == "gm_sum" ~ "Gross Motor",
    name == "fm_sum" ~ "Fine Motor",
    name == "cg_sum" ~ "Problem Solving",
    name == "ps_sum" ~ "Personal-Social")) %>% 
  ggplot(., aes(x = name, y = value, fill = base)) +
  geom_bar(stat = "summary", fun = "mean", position = "dodge") +
  facet_wrap(~quest) +
  theme_bw() +
   theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size=11,face="bold"))

2.3 T test for means

ds %>%
  filter(quest !=9 & quest != 72) %>% 
  select(quest, base, c_sum:ps_sum) %>% 
     pivot_longer(cols = -c(quest, base)) %>%
  group_by(quest, name)  %>%
  nest() %>% 
  mutate(mean1 = map_dbl(data, ~mean(.x$value[.x$base == "base1"]))) %>%  
  mutate(mean2 = map_dbl(data, ~mean(.x$value[.x$base == "sup"]))) %>%  
  mutate(pval = map(data, ~t.test(.x$value ~ .x$base)$p.value)) %>% 
  unnest(pval)  %>% 
  mutate(pval = round(pval, 2)) %>% 
  filter(pval > 0.05) %>% 
  arrange(quest) %>% 
  select(-data)

2.4 ASQ4 and ASQ3 (Manual)

2.4.1 Get table

asq_3_table <- read_csv("C:/Users/luisf/Downloads/asq_3_table.csv")
asq_3_table <- clean_names(asq_3_table)
asq_3_table <- remove_empty(asq_3_table)
asq_3_table <- asq_3_table %>% mutate(quest = as.factor(quest))
asq_3_table

2.4.2 Compare both

left_join(
  ds %>% #get ds
    select(quest, ends_with("sum")) %>% #select the focus variables 
    pivot_longer(-quest) %>% #transpose to long formata
    nest_by(quest, name) %>% #group
    mutate(mean = list(map_dbl(data, ~mean(.))),
           sd = list(map_dbl(data, ~sd(.))),
           m_1sd = mean-sd,
           m_1_half_sd = mean-1.5*sd,
           m_2sd = mean-2*sd) %>% 
    unnest(-data) %>% #unnest
    pivot_wider(id_cols = quest, names_from = name, values_from = mean:m_2sd) %>% 
    mutate_if(is.numeric, round, 2) %>% 
    ungroup()
  ,
  asq_3_table,
  by = "quest") %>% 
  pivot_longer(-quest) %>%
  arrange(quest,name) %>% 
  pivot_wider(id_cols = quest, names_from = name, values_from = value) %>%
  rename_all(.,~stringr::str_replace_all(., 'x', 'asq4')) %>% 
  rename_all(.,~stringr::str_replace_all(., 'y', 'asq3')) %>% 
  select(quest,contains("m_2sd"))

3 ASQ-4 (Manual)

4 Table Questionnaires by age interval and method of completion

ds %>% 
  tabyl(quest,website) %>% 
  adorn_totals(where = c("row","col")) %>% 
  adorn_percentages(denominator = "col") %>% 
  adorn_pct_formatting(digits = 0) %>% 
  adorn_ns(position = "front")

5 Table Gender of children

ds %>% 
  tableby(gender~quest,
          data = ., 
          test=FALSE) %>% summary()
ds %>% count(gender) %>% adorn_totals()
ds %>% 
  group_by(quest) %>% 
  summarise(pval = chisq.test(table(gender))$p.value) %>% 
  arrange(pval)

6 Table Mom’s age

ds %>% tableby(base~momage_numeric,data = .) %>% summary() 

7 Table mother’s education

ds %>% 
  tableby(~momed,data = ., test=FALSE) %>% summary() 
#%>% xlsx::write.xlsx(., file = "raw_results.xlsx", sheetName="momed", append=TRUE)

8 Table Family income level

On Dec 28, 2021

ds %>% 
  mutate(income = ifelse(as.integer(income)<7, income,NA)) %>%  #I changed the order of income in ds sup to compute the risk factor, but I did not changed this variable by itself
  tableby(~as.factor(income),data = ., test=FALSE) %>% 
  summary() 

9 Table at risk

On Dec 28, 2021

ds %>% 
  tableby(~summative_risk,data = ., test=FALSE) %>% summary() 
ds %>% 
  select(quest,summative_risk) %>% 
  mutate(summative_risk_sup = as_factor(summative_risk),
         summative_risk_sup = fct_inseq(summative_risk)) %>% 
  tableone::CreateTableOne(vars = "summative_risk", strata = "quest", data = .) %>% 
  print(.) %>% t(.) %>% as.data.frame() %>% rownames_to_column("quest")
ds %>% 
  filter(base=="base1") %>% 
  {gmodels::CrossTable(.$atrisk, .$summative_risk, chisq = T)} 

10 Table Race

ds %>% 
  tableby(~race,data = ., test=FALSE) %>% summary() 

11 Table Descriptive

ds %>% 
  filter(!is.na(quest)) %>% 
  select(quest, ends_with("sum")) %>% 
  tableby(quest ~ ., control = tableby.control(numeric.stats=c("mean", "sd")), data = .) %>% summary(. , digits = 2)
  #tableone::CreateTableOne(vars =  names(.), strata = c("quest"), data = .) %>% transpose()
  #table1::table1(~ .| quest, 
  #               transpose = TRUE,
  #               data = .) 

12 Plot Scores’ distribution

ds %>% 
  filter(!is.na(quest)) %>% 
  select(quest, ends_with("sum")) %>% 
  pivot_longer(-quest) %>% 
  mutate_at(vars(name), ~case_when(
    . == "ps_sum" ~ "Personal & Social",
    . == "gm_sum" ~ "Gross motor",
    . == "fm_sum" ~ "Fine motor",
    . == "c_sum" ~ "Communication",
    . == "cg_sum" ~ "Problem solving",
  )) %>% 
  ggplot(., aes(x = value, y = name, fill = name)) + 
  ggridges::geom_density_ridges(rel_min_height = 0.01) +
  facet_wrap(~quest) +
  ggridges::theme_ridges(grid = FALSE, center_axis_labels = TRUE) +
  theme(legend.position = "hide") + labs(y="") 

13 Table Internal consistency

reg_com <- "^com_a4_.*"
reg_fm <- "^fm_a4_.*"
reg_gm <- "^gm_a4_.*"
reg_cg <- "^cg_a4_.*"
reg_ps <- "^ps_a4_.*"

regs <- c(reg_fm, reg_com, reg_gm, reg_cg, reg_ps) %>% 
    set_names(c("fm_a4_", "com_a4_", "gm_a4_", "cg_a4_", 
                "ps_a4_"))
cronbachs_alpha <- 
    map_df(regs, ~ 
               ds %>% 
               select(dplyr::matches(.x)) %>% 
               psych::alpha(check.keys = TRUE) %>% .$total %>% 
               tibble::rownames_to_column()
           ,.id = "scale"
    )
apply_alpha <- function(data, nest_contains) {
  x<-data %>%
    select(quest, contains(nest_contains)) %>%
    group_by(quest) %>%
    do(alpha(.[-1])$total) #compute alpha
  
  y<-data %>% 
    count(quest) #get n
  
  z <- left_join(x,y, by = "quest") 

  z <- z %>% mutate_if(is.numeric, round,2)
  
  return(z)
}
apply_alpha(ds, 'com_a4_')

13.1 All questionnaires

left_join(
ds %>%
  #select items
    select(quest, com_a4_1:com_a4_6, gm_a4_1:gm_a4_6, fm_a4_1:fm_a4_6, cg_a4_1:cg_a4_6, ps_a4_1:ps_a4_6) %>% 
    pivot_longer(cols = -quest,
                 names_to = c("scale", ".value"),
                 names_pattern = "(\\w+_\\w+_)(.)") %>%
    nest_by(quest, scale) %>%
    #Compute cronbach´s alpha for all questionnaires and domains
    mutate(alpha(data)$total) %>% 
  select(quest, scale, std.alpha, average_r)
,

  ds %>% count(quest)
) %>% 
  mutate_if(is.numeric, round,2) %>% 
  pivot_wider(quest, names_from = scale, values_from = std.alpha:n)
#https://stackoverflow.com/questions/69302457/using-dplyr-to-nest-or-group-two-variables-then-perform-the-cronbachs-alpha-fu/69303641#69303641
ds %>%
  select(quest, com_a4_1:com_a4_6, gm_a4_1:gm_a4_6, fm_a4_1:fm_a4_6, cg_a4_1:cg_a4_6, ps_a4_1:ps_a4_6) %>% 
  mutate(id = 1:n()) %>%
  pivot_longer(cols = c(-id, -quest)) %>%
  separate(col = name,
           into = c("scale", "item"),
           sep = "_",
           extra = "merge") %>%
  pivot_wider(names_from = item) %>%
  select(-id) %>%
  group_by(quest, scale) %>%
  nest() %>%
  mutate(alpha_results = map(data, ~alpha(.)$total)) %>%
  unnest_wider(alpha_results) %>% #get alpha results
  select(quest, scale, std.alpha, average_r) %>%  #what I want to get
  arrange(quest, scale) %>% 
  pivot_wider(names_from = scale, values_from = std.alpha:average_r) %>% 
  mutate_if(is.numeric, round, 2) 

13.2 All data

ds %>%
    select(quest, com_a4_1:com_a4_6, gm_a4_1:gm_a4_6, fm_a4_1:fm_a4_6, cg_a4_1:cg_a4_6, ps_a4_1:ps_a4_6) %>% 
    group_by(quest) %>%
    do(alpha(.[-1])$total) %>% 
  select(quest, std.alpha) %>% 
  mutate_if(is.numeric, round, 2)

13.3 Double check

ds_1 %>% 
  filter(quest == 16) %>% 
  select( com_a4_1:com_a4_6, gm_a4_1:gm_a4_6, fm_a4_1:fm_a4_6, cg_a4_1:cg_a4_6, ps_a4_1:ps_a4_6) %>% 
  psych::alpha(.)

13.4 Graph

#make data
ds_1 %>%
    select(quest, com_a4_1:com_a4_6, gm_a4_1:gm_a4_6, fm_a4_1:fm_a4_6, cg_a4_1:cg_a4_6, ps_a4_1:ps_a4_6) %>% 
    pivot_longer(cols = -quest,
                 names_to = c("scale", ".value"),
                 names_pattern = "(\\w+_\\w+_)(.)") %>%
    nest_by(quest, scale)%>%
    mutate(alpha=alpha(data)$total$raw_alpha) ->x 

x %>% 
  mutate_at(vars(scale), ~case_when(
    . == "cg_a4_" ~ "Problem Solving",
    . == "com_a4_" ~ "Communication",
    . == "fm_a4_" ~ "Fine Motor",
    . == "gm_a4_" ~ "Gross Motor",
    . == "ps_a4_" ~ "Personal-Social",
  )) %>% 
  ggplot(., aes(x=quest, y = alpha, color = scale)) +
  stat_summary(geom = "line", size = 1) +
  stat_summary(geom = "point") +
  labs(y="Cronbach's Alpha", x="Age-interval") +
  theme_bw() +
  theme(legend.position = "bottom")

14 Table Correlation

ds %>%
    select(quest, com_a4_1:com_a4_6, gm_a4_1:gm_a4_6, fm_a4_1:fm_a4_6, cg_a4_1:cg_a4_6, ps_a4_1:ps_a4_6) %>% 
    pivot_longer(cols = -quest,
                 names_to = c("scale", ".value"),
                 names_pattern = "(\\w+_\\w+_)(.)") %>%
    nest_by(quest, scale) %>%
    mutate(cor=mean(alpha(data)$item.stats$r.cor)) %>% 
  mutate_if(is.numeric, round,2) %>% 
  pivot_wider(quest, names_from = scale, values_from = cor)

14.1 Minor check

ds_1 %>%
    select(quest, fm_a4_1:fm_a4_6) %>% 
  filter(quest == 4) %>% 
  {mean(alpha(.)$item.stats$r.cor)}
ds_1 %>%
    select(quest, com_a4_1:com_a4_6, gm_a4_1:gm_a4_6, fm_a4_1:fm_a4_6, cg_a4_1:cg_a4_6, ps_a4_1:ps_a4_6) %>% 
    pivot_longer(cols = -quest,
                 names_to = c("scale", ".value"),
                 names_pattern = "(\\w+_\\w+_)(.)") %>%
    nest_by(quest, scale) %>%
    mutate(cor=mean(alpha(data)$item.stats$r.cor))->x 

x %>% 
  mutate_at(vars(scale), ~case_when(
    . == "cg_a4_" ~ "Problem Solving",
    . == "com_a4_" ~ "Communication",
    . == "fm_a4_" ~ "Fine Motor",
    . == "gm_a4_" ~ "Gross Motor",
    . == "ps_a4_" ~ "Personal-Social",
  )) %>% 
  ggplot(., aes(x=quest, y = cor, color = scale)) +
  stat_summary(geom = "line", size = 1) +
  stat_summary(geom = "point") +
  labs(y="Correlation coefficient", x="Age-interval") +
  scale_x_continuous(breaks = seq(2, 72, by = 2))  +
    theme_bw() +
  theme(legend.position = "bottom")

15 Cutoff scores

Asked by Jane and Kimberly on March 3, 2022

15.1 Expressive vs receptive communication

compare_communication <- function(quest, items) {
  quest <- enquo(quest)
  items <- enquo(items)
  
    ds %>% #get data
    filter(quest == !!quest) %>% #select which questionnaire will be used
    mutate(com_exp = rowSums(select(., !!items), na.rm=T)) %>% #create a summative score for expressive items
    mutate(com_rec = c_sum-com_exp) %>% 
    select(com_exp, com_rec, c_sum) %>%
    summarise(n=n(),
              mean(com_exp),
              mean(com_rec),
              mean(c_sum),
    p = t.test(com_exp, com_rec, alternative = "two.sided", paired = T)$p.value) %>%
      t() #compare scores
}

list(
  compare_communication(quest = 2, items = c(com_a4_1,com_a4_2,com_a4_5)),
  compare_communication(quest =     4   , items = c(    com_a4_1,com_a4_4,com_a4_6  )),
  compare_communication(quest =     6   , items = c(    com_a4_1,com_a4_2,com_a4_5  )),
  compare_communication(quest =     8   , items = c(    com_a4_3,com_a4_4,com_a4_6  )),
  compare_communication(quest =     10  , items = c(    com_a4_1,com_a4_3,com_a4_6  )),
  compare_communication(quest =     12  , items = c(    com_a4_1,com_a4_4,com_a4_6  )),
  compare_communication(quest =     14  , items = c(    com_a4_1,com_a4_2,com_a4_5  )),
  compare_communication(quest =     16  , items = c(    com_a4_5,com_a4_3,com_a4_6  )),
  compare_communication(quest =     18  , items = c(    com_a4_3,com_a4_4,com_a4_6  )),
  compare_communication(quest =     20  , items = c(    com_a4_2,com_a4_3,com_a4_6  )),
  compare_communication(quest =     22  , items = c(    com_a4_3,com_a4_5 ,com_a4_6 )),
  compare_communication(quest =     24  , items = c(    com_a4_3,com_a4_5 ,com_a4_6 )),
  compare_communication(quest =     27  , items = c(    com_a4_2,com_a4_4,com_a4_5  )),
  compare_communication(quest =     30  , items = c(    com_a4_2,com_a4_4,com_a4_6  ))
)
ds %>% filter(quest == 4) %>%
  select(com_a4_1,com_a4_4,com_a4_6) %>%
  DataExplorer::profile_missing()


ds %>%
  filter(quest == 4) %>%
     rowid_to_column() %>%
     filter(is.na(com_a4_4)) #its missing because asq3 com 4 was missing and 2 and 4 months are equal

15.2 Means and SD

left_join(
  ds %>% #get ds
  select(quest, ends_with("sum")) %>% #select the focus variables 
  pivot_longer(-quest) %>% #transpose to long formata
  nest_by(quest, name) %>% #group
  mutate(mean = list(map_dbl(data, ~mean(.))),
         sd = list(map_dbl(data, ~sd(.))),
         m_1sd = mean-sd,
         m_1_half_sd = mean-1.5*sd,
         m_2sd = mean-2*sd) %>% 
  unnest(-data) %>% #unnest
  pivot_wider(id_cols = quest, names_from = name, values_from = mean:m_2sd) %>% 
  mutate_if(is.numeric, round, 2)
  ,
  ds %>% count(quest)
) %>% select(quest, n, everything())

15.3 Performance of the cutoff

15.3.1 Monitoring zone

ds %>% 
  select(quest, ends_with("sum")) %>% #get variable names
  pivot_longer(-quest) %>% #tranform into the long format
  nest_by(quest, name) %>% #group or nest
  mutate(
    questionnaire = quest,#compute questionnaire
    n = map_dbl(data, ~nrow(data.frame(.))), #compute sample size
    mean = map_dbl(data, ~mean(.)), #get the means
    sd = map_dbl(data, ~sd(.)), #get sd
    m_1sd = mean-sd, #1 below
    m_1_half_sd = mean-1.5*sd, #1.5 below
    m_2sd = mean-2*sd, #2 below
    how_many_c = map(data, ~ ifelse(name == "c_sum", #i'll count how many participants are below
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(c_sum > m_2sd & c_sum <= m_1sd) %>% 
        summarise(n()),
      NA_integer_)), # percentage of communication
    
    how_many_gm = map(data, ~ ifelse(name == "gm_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(gm_sum > m_2sd & gm_sum <= m_1sd) %>% 
        summarise(n()), #percentage of gross motor
    NA_integer_)),
    
    how_many_fm = map(data, ~ ifelse(name == "fm_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(fm_sum > m_2sd & fm_sum <= m_1sd) %>% 
        summarise(n()),#percentage of fine motor
      NA_integer_)), 
    
    how_many_cg = map(data, ~ ifelse(name == "cg_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(cg_sum > m_2sd & cg_sum <= m_1sd) %>% 
        summarise(n()), #percentage of problem-solving
    NA_integer_)), 

    how_many_ps = map(data, ~ ifelse(name == "ps_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(ps_sum > m_2sd & ps_sum <= m_1sd) %>% 
        summarise(n()), #percentage of personal social
        NA_integer_)))  %>% 
  mutate(n_com=
           paste0(how_many_c[[1]],"-",
                 round(how_many_c[[1]]/n*100,0),"%"), #I'll get the percentages
         n_gm=
           paste0(how_many_gm[[1]],"-",
                 round(how_many_gm[[1]]/n*100,0),"%"),
         n_fm=
           paste0(how_many_fm[[1]],"-",
                 round(how_many_fm[[1]]/n*100,0),"%"),
         n_cg=
           paste0(how_many_cg[[1]],"-",
                 round(how_many_cg[[1]]/n*100,0),"%"),
         n_ps=
           paste0(how_many_ps[[1]],"-",
                 round(how_many_ps[[1]]/n*100,0),"%")                           
         ) %>%
  unnest_wider(-quest) %>% #particular trickes (there is a lot of pseudo missing values)
  select(quest,how_many_ps:last_col(), -how_many_ps) %>%  #get some variables
  pivot_longer(-quest) %>%  #now transform to the long format
  filter(value != "NA-NA%") %>% #filter
  pivot_wider(id_cols = quest, names_from = name, values_from = value)
ds %>% filter(quest == 2 & c_sum <= 27.82241 & c_sum > 13.4012)
ds %>% 
  filter(quest == 4) %>% 
  filter(gm_sum > 35.2 & gm_sum <= 44.29)
ds %>% 
  filter(quest == 6) %>% 
  filter(fm_sum > 21.6 & fm_sum <= 34.71)
ds %>% 
  filter(quest == 27) %>% 
  filter(ps_sum > 22.02 & ps_sum <= 34.88)

15.3.2 Below the cutoff

ds %>% 
  select(quest, ends_with("sum")) %>% #get variable names
  pivot_longer(-quest) %>% #tranform into the long format
  nest_by(quest, name) %>% #group or nest
  mutate(
    questionnaire = quest,#compute questionnaire
    n = list(map_dbl(data, ~nrow(data.frame(.)))), #compute sample size
    mean = list(map_dbl(data, ~mean(.))), #get the means
    sd = list(map_dbl(data, ~sd(.))), #get sd
    m_1sd = mean-sd, #1 below
    m_1_half_sd = mean-1.5*sd, #1.5 below
    m_2sd = mean-2*sd, #2 below
    how_many_c = map(data, ~ ifelse(name == "c_sum", #i'll count how many participants are below
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(c_sum  <= m_2sd) %>% 
        summarise(n()),
      NA_integer_)), # percentage of communication
    
    how_many_gm = map(data, ~ ifelse(name == "gm_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(gm_sum <= m_2sd) %>% 
        summarise(n()), #percentage of gross motor
    NA_integer_)),
    
    how_many_fm = map(data, ~ ifelse(name == "fm_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(fm_sum <= m_2sd) %>% 
        summarise(n()),#percentage of fine motor
      NA_integer_)), 
    
    how_many_cg = map(data, ~ ifelse(name == "cg_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(cg_sum <= m_2sd) %>% 
        summarise(n()), #percentage of problem-solving
    NA_integer_)), 

    how_many_ps = map(data, ~ ifelse(name == "ps_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(ps_sum <= m_2sd) %>% 
        summarise(n()), #percentage of personal social
        NA_integer_)))  %>% 
  mutate(n_com=
           paste0(how_many_c[[1]],"-",
                 round(how_many_c[[1]]/n*100,0),"%"), #I'll get the percentages
         n_gm=
           paste0(how_many_gm[[1]],"-",
                 round(how_many_gm[[1]]/n*100,0),"%"),
         n_fm=
           paste0(how_many_fm[[1]],"-",
                 round(how_many_fm[[1]]/n*100,0),"%"),
         n_cg=
           paste0(how_many_cg[[1]],"-",
                 round(how_many_cg[[1]]/n*100,0),"%"),
         n_ps=
           paste0(how_many_ps[[1]],"-",
                 round(how_many_ps[[1]]/n*100,0),"%")                           
         ) %>%
  unnest_wider(-quest) %>% #particular trickes (there is a lot of pseudo missing values)
  select(quest,how_many_ps:last_col(), -how_many_ps) %>%  #get some variables
  pivot_longer(-quest) %>%  #now transform to the long format
  filter(value != "NA-NA%") %>% #filter
  pivot_wider(id_cols = quest, names_from = name, values_from = value)

15.3.3 Double check

ds %>% 
  filter(quest == 2) %>% 
  filter(c_sum > 13.4012211 & c_sum <=  27.82241 ) %>% 
  count()

ds %>% 
  filter(quest == 4) %>% 
  filter(c_sum > 30.542897 & c_sum <=   40.38866) %>% 
  count()

ds %>% 
  filter(quest == 6) %>% 
  filter(c_sum > 28.3859573 & c_sum <=  38.04648) %>% 
  count()

ds %>% 
  filter(quest == 2) %>% 
  filter(gm_sum > 38.2619752 & gm_sum <=    46.0505 ) %>% 
  count()

ds %>% 
  filter(quest == 36) %>% 
  filter(cg_sum > 23.3887282 & cg_sum <=    35.95029 ) %>% 
  count()

ds %>% 
  filter(quest == 24) %>% 
  filter(cg_sum < 18.14)

15.3.4 Fixing at zero comm

ds %>% 
  filter(quest %in% c(18,20,22)) %>% 
  group_by(quest) %>% 
  mutate(czero = ifelse(c_sum <= 0,1,0)) %>% 
  select(czero, everything()) %>% 
  summarise(n=n(), sum(czero), sum(czero)/n)
  
  select()

15.3.5 Percentage monitor

ds %>%
  select(id, quest, ends_with("sum")) %>%
  pivot_longer(-c(id, quest)) %>% #tranform into  long format
  nest_by(quest, name) %>% #nest (id will not be used this time)
  #here is the trick. all counts are here
  mutate(
    n = map_dbl(data[2], ~nrow(data.frame(.))), #compute sample size
    mean = map_dbl(data[2], ~mean(.)), #get the ROBUST means
    sd = map_dbl(data[2],  ~sd(.)), #get the ROBUST sd
    one_below = mean-sd, #1 below
    two_below = mean - 2 * sd,
    monitor = sum(one_below >= data[[2]] & two_below < data[[2]])/n,
    below = sum(two_below > data[[2]])/n) %>% 
  #outside of the map, add a new variable to nested data
  mutate(data = list(data %>% mutate(area_monitor = ifelse(data[[2]] > two_below & data[[2]] <= one_below, paste0(name),0)))) %>% 
  unnest(data) %>% #I'll unnest and get again the ids. my df will be very long
  pivot_wider(id_cols = c(id, quest), names_from = c(area_monitor), values_fn = length) %>% #now I'll group by ids!! my df will be sample size * quest
  ungroup() %>% #end of function 
  #now I'll count values
  mutate(how_many = select(.,ends_with("_sum")) %>% rowSums(., na.rm = T)) %>% 
  #now I'll present the results
  tabyl(quest, how_many)%>% 
  as.data.frame() %>% 
  # adorn_totals(c("row", "col")) %>% 
  #adorn_percentages("row") %>%
  #adorn_pct_formatting(digits = 2) %>%
  #adorn_ns() # 
  pivot_longer(-quest) %>%
  group_by(quest) %>% 
  mutate(prop = prop.table(value)) %>%
  ungroup()%>% 
  ggplot(., aes(x = name, y = prop, group=quest, color = quest, label=quest)) +
  stat_summary(geom = "line", fun = mean, size=1) +
  #ggrepel::geom_text_repel(data = . %>% filter(name == "0"), box.padding = 0.5, max.overlaps = Inf) +
  labs(x = "Domains at the monitoring zone", y = "Proportion", color = "Questionnaire") +
  theme_bw() +
  theme(legend.position = "bottom")

15.3.6 Percentage below

ds %>%
  select(id, quest, ends_with("sum")) %>%
  pivot_longer(-c(id, quest)) %>% #tranform into  long format
  nest_by(quest, name) %>% #nest (id will not be used this time)
  #here is the trick. all counts are here
  mutate(
    n = map_dbl(data[2], ~nrow(data.frame(.))), #compute sample size
    mean = map_dbl(data[2], ~mean(.)), #get the ROBUST means
    sd = map_dbl(data[2],  ~sd(.)), #get the ROBUST sd
    one_below = mean-sd, #1 below
    two_below = mean - 2 * sd,
    monitor = sum(one_below >= data[[2]] & two_below < data[[2]])/n,
    below = sum(two_below > data[[2]])/n) %>% 
  #outside of the map, add a new variable to nested data
  mutate(data = list(data %>% mutate(area_monitor = as.character(ifelse(data[[2]] <= two_below, paste0(name),0))))) %>% #attention here
  unnest(data) %>% #I'll unnest and get again the ids. my df will be very long
  pivot_wider(id_cols = c(id, quest), names_from = c(area_monitor), values_fn = length) %>% #now I'll group by ids!! my df will be sample size * quest
  ungroup() %>% #end of function 
  #now I'll count values
  mutate(how_many = select(.,ends_with("_sum")) %>% rowSums(., na.rm = T)) %>% 
  #now I'll present the results
  tabyl(quest, how_many)%>% 
  as.data.frame() %>% 
   adorn_totals(c("row", "col")) %>% 
  adorn_percentages("row") %>%
  adorn_pct_formatting(digits = 2) %>%
  adorn_ns() # 
  pivot_longer(-quest) %>%
  group_by(quest) %>% 
  mutate(prop = prop.table(value)) %>%
  ungroup()%>% 
  ggplot(., aes(x = name, y = prop, group=quest, color = quest, label=quest)) +
  stat_summary(geom = "line", fun = mean, size=1) +
  #ggrepel::geom_text_repel(data = . %>% filter(name == "0"), box.padding = 0.5, max.overlaps = Inf) +
  labs(x = "Domains below the cutoff", y = "Proportion", color = "Questionnaire") +
  theme_bw() +
  theme(legend.position = "bottom")

15.4 Robust

ds %>% 
  select(quest, ends_with("sum")) %>% 
  pivot_longer(-quest) %>% 
  nest_by(quest, name) %>% 
  mutate(x=list(map(data, ~psych::describe(.)))) %>% 
  unnest_wider(x) %>% 
  unnest_wider(value) %>% 
  mutate_if(is.numeric, round, 2)
ds %>% 
  select(quest, ends_with("sum")) %>% 
  pivot_longer(-quest) %>% 
  nest_by(quest, name) %>% 
  mutate(
    questionnaire = quest,
    mean_r = list(map_dbl(data, ~mean(., trim=0.25))),
    sd_r = list(map_dbl(data, ~chemometrics::sd_trim(., trim=0.25, const = TRUE))),
    m_1sd = mean_r-sd_r,
    m_1_half_sd = mean_r-1.5*sd_r,
    m_2sd = mean_r-2*sd_r) %>% 
  unnest(-data) %>% 
  #unnest_wider(-quest) %>% 
  pivot_wider(id_cols = quest, names_from = name, values_from = mean_r:m_2sd) %>% 
  mutate_if(is.numeric, round, 2)

15.5 Performance of the cutoff

15.5.1 Monitoring zone

ds %>% 
  select(quest, ends_with("sum")) %>% 
  pivot_longer(-quest) %>% 
  nest_by(quest, name) %>% 
  mutate(
    questionnaire = quest,
    n = list(map_dbl(data, ~nrow(data.frame(.)))),
    mean_r = list(map_dbl(data, ~mean(., trim=0.25))),
    sd_r = list(map_dbl(data, ~chemometrics::sd_trim(., trim=0.25, const = TRUE))),
    m_1sd = mean_r-sd_r,
    m_1_half_sd = mean_r-1.5*sd_r,
    m_2sd = mean_r-2*sd_r,
    how_many_c = map(data, ~ ifelse(name == "c_sum", #i'll count how many participants are below
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(c_sum > m_2sd & c_sum <= m_1sd) %>% 
        summarise(n()),
      NA_integer_)), # percentage of communication
    
    how_many_gm = map(data, ~ ifelse(name == "gm_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(gm_sum > m_2sd & gm_sum <= m_1sd) %>% 
        summarise(n()), #percentage of gross motor
    NA_integer_)),
    
    how_many_fm = map(data, ~ ifelse(name == "fm_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(fm_sum > m_2sd & fm_sum <= m_1sd) %>% 
        summarise(n()),#percentage of fine motor
      NA_integer_)), 
    
    how_many_cg = map(data, ~ ifelse(name == "cg_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(cg_sum > m_2sd & cg_sum <= m_1sd) %>% 
        summarise(n()), #percentage of problem-solving
    NA_integer_)), 

    how_many_ps = map(data, ~ ifelse(name == "ps_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(ps_sum > m_2sd & ps_sum <= m_1sd) %>% 
        summarise(n()), #percentage of personal social
        NA_integer_)))  %>% 
  mutate(n_com=
           paste0(how_many_c[[1]],"-",
                 round(how_many_c[[1]]/n*100,0),"%"), #I'll get the percentages
         n_gm=
           paste0(how_many_gm[[1]],"-",
                 round(how_many_gm[[1]]/n*100,0),"%"),
         n_fm=
           paste0(how_many_fm[[1]],"-",
                 round(how_many_fm[[1]]/n*100,0),"%"),
         n_cg=
           paste0(how_many_cg[[1]],"-",
                 round(how_many_cg[[1]]/n*100,0),"%"),
         n_ps=
           paste0(how_many_ps[[1]],"-",
                 round(how_many_ps[[1]]/n*100,0),"%")                           
         ) %>%
  unnest_wider(-quest) %>% #particular trickes (there is a lot of pseudo missing values)
  select(quest,how_many_ps:last_col(), -how_many_ps) %>%  #get some variables
  pivot_longer(-quest) %>%  #now transform to the long format
  filter(value != "NA-NA%") %>% #filter
  pivot_wider(id_cols = quest, names_from = name, values_from = value)

15.5.2 Below the cutoff

ds %>% 
  select(quest, ends_with("sum")) %>% 
  pivot_longer(-quest) %>% 
  nest_by(quest, name) %>% 
  mutate(
    questionnaire = quest,
    n = list(map_dbl(data, ~nrow(data.frame(.)))),
    mean_r = list(map_dbl(data, ~mean(., trim=0.25))),
    sd_r = list(map_dbl(data, ~chemometrics::sd_trim(., trim=0.25, const = TRUE))),
    m_1sd = mean_r-sd_r,
    m_1_half_sd = mean_r-1.5*sd_r,
    m_2sd = mean_r-2*sd_r,
        how_many_c = map(data, ~ ifelse(name == "c_sum", #i'll count how many participants are below
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(c_sum  <= m_2sd) %>%  #attention here!
        summarise(n()),
      NA_integer_)), # percentage of communication
    
    how_many_gm = map(data, ~ ifelse(name == "gm_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(gm_sum <= m_2sd) %>% 
        summarise(n()), #percentage of gross motor
    NA_integer_)),
    
    how_many_fm = map(data, ~ ifelse(name == "fm_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(fm_sum <= m_2sd) %>% 
        summarise(n()),#percentage of fine motor
      NA_integer_)), 
    
    how_many_cg = map(data, ~ ifelse(name == "cg_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(cg_sum <= m_2sd) %>% 
        summarise(n()), #percentage of problem-solving
    NA_integer_)), 

    how_many_ps = map(data, ~ ifelse(name == "ps_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(ps_sum <= m_2sd) %>% 
        summarise(n()), #percentage of personal social
        NA_integer_)))  %>% 
  mutate(n_com=
           paste0(how_many_c[[1]],"-",
                 round(how_many_c[[1]]/n*100,0),"%"), #I'll get the percentages
         n_gm=
           paste0(how_many_gm[[1]],"-",
                 round(how_many_gm[[1]]/n*100,0),"%"),
         n_fm=
           paste0(how_many_fm[[1]],"-",
                 round(how_many_fm[[1]]/n*100,0),"%"),
         n_cg=
           paste0(how_many_cg[[1]],"-",
                 round(how_many_cg[[1]]/n*100,0),"%"),
         n_ps=
           paste0(how_many_ps[[1]],"-",
                 round(how_many_ps[[1]]/n*100,0),"%")                           
         ) %>%
  unnest_wider(-quest) %>% #particular trickes (there is a lot of pseudo missing values)
  select(quest,how_many_ps:last_col(), -how_many_ps) %>%  #get some variables
  pivot_longer(-quest) %>%  #now transform to the long format
  filter(value != "NA-NA%") %>% #filter
  pivot_wider(id_cols = quest, names_from = name, values_from = value)

15.5.3 Double check

ds %>% 
  filter(quest == 16) %>% 
  filter(gm_sum > 55.49 & gm_sum <= 57.24)
ds %>% 
  filter(quest == 2) %>% 
  filter(c_sum <= 49.17 & c_sum > 43.62)
ds %>% 
  filter(quest == 18) %>% 
  filter(fm_sum < 45.38 & fm_sum <= 49.8)

15.5.4 Percentage monitor

ds %>%
  select(id, quest, ends_with("sum")) %>%
  pivot_longer(-c(id, quest)) %>% #tranform into  long format
  nest_by(quest, name) %>% #nest (id will not be used this time)
  #here is the trick. all counts are here
  mutate(
    n = map_dbl(data[2], ~nrow(data.frame(.))), #compute sample size
    mean = map_dbl(data[2], ~mean(., trim = 0.25)), #get the ROBUST means
    sd = map_dbl(data[2],   ~chemometrics::sd_trim(., trim=0.25, const = TRUE)), #get the ROBUST sd
    one_below = mean-sd, #1 below
    two_below = mean - 2 * sd,
    monitor = sum(one_below >= data[[2]] & two_below < data[[2]])/n,
    below = sum(two_below > data[[2]])/n) %>% 
  #outside of the map, add a new variable to nested data
  mutate(data = list(data %>% mutate(area_monitor = as.character(ifelse(data[[2]] > two_below & data[[2]] <= one_below, paste0(name),0))))) %>% 
  unnest(data) %>% #I'll unnest and get again the ids. my df will be very long
  pivot_wider(id_cols = c(id, quest), names_from = c(area_monitor), values_fn = length) %>% #now I'll group by ids!! my df will be sample size * quest
  ungroup() %>% #end of function 
  #now I'll count values
  mutate(how_many = select(.,ends_with("_sum")) %>% rowSums(., na.rm = T)) %>% 
  #now I'll present the results
  tabyl(quest, how_many)%>% 
  adorn_totals(c("row", "col")) %>% 
  adorn_percentages("row") %>%
  adorn_pct_formatting(digits = 2) %>%
  adorn_ns() # 
  pivot_longer(-quest) %>%
  group_by(quest) %>% 
  mutate(prop = prop.table(value)) %>%
  ungroup()%>% 
  ggplot(., aes(x = name, y = prop, group=quest, color = quest, label=quest)) +
  stat_summary(geom = "line", fun = mean, size=1) +
  #ggrepel::geom_text_repel(data = . %>% filter(name == "0"), box.padding = 0.5, max.overlaps = Inf) +
  labs(x = "Domains at the monitoring zone", y = "Proportion", color = "Questionnaire") +
  theme_bw() +
  theme(legend.position = "bottom")

15.5.5 Percentage below

ds %>%
  select(id, quest, ends_with("sum")) %>%
  pivot_longer(-c(id, quest)) %>% #tranform into  long format
  nest_by(quest, name) %>% #nest (id will not be used this time)
  #here is the trick. all counts are here
  mutate(
    n = map_dbl(data[2], ~nrow(data.frame(.))), #compute sample size
    mean = map_dbl(data[2], ~mean(., trim = 0.25)), #get the ROBUST means
    sd = map_dbl(data[2],   ~chemometrics::sd_trim(., trim=0.25, const = TRUE)), #get the ROBUST sd
    one_below = mean-sd, #1 below
    two_below = mean - 2 * sd) %>% 
  #outside of the map, add a new variable to nested data
  mutate(data = list(data %>% mutate(area_monitor = as.character(ifelse(data[[2]] <= two_below, paste0(name),0))))) %>% #here
  unnest(data) %>% #I'll unnest and get again the ids. my df will be very long
  pivot_wider(id_cols = c(id, quest), names_from = c(area_monitor), values_fn = length) %>% #now I'll group by ids!! my df will be sample size * quest
  ungroup() %>% #end of function 
  #now I'll count values
  mutate(how_many = select(.,ends_with("_sum")) %>% rowSums(., na.rm = T)) %>% 
  #now I'll present the results
  tabyl(quest, how_many)%>% 
  adorn_totals(c("row", "col")) %>% 
  adorn_percentages("row") %>%
  adorn_pct_formatting(digits = 2) %>%
  adorn_ns() # 
  pivot_longer(-quest) %>%
  group_by(quest) %>% 
  mutate(prop = prop.table(value)) %>%
  ungroup()%>% 
  ggplot(., aes(x = name, y = prop, group=quest, color = quest, label=quest)) +
  stat_summary(geom = "line", fun = mean, size=1) +
  #ggrepel::geom_text_repel(data = . %>% filter(name == "0"), box.padding = 0.5, max.overlaps = Inf) +
  labs(x = "Domains at the monitoring zone", y = "Proportion", color = "Questionnaire") +
  theme_bw() +
  theme(legend.position = "bottom")

15.6 Percentiles

ds %>% #get ds
  select(quest, ends_with("sum")) %>% #select the focus variables 
  pivot_longer(-quest) %>% #transpose to long formata
  nest_by(quest, name) %>% #group
 mutate(mean = list(map_dbl(data, ~mean(.))),
         p_05 = list(map_dbl(data, ~quantile(., prob = 0.05))),
         p_10 = list(map_dbl(data, ~quantile(., prob = 0.10)))
        ) %>% 
  unnest(-data) %>% #unnest
  pivot_wider(id_cols = quest, names_from = name, values_from = mean:p_10) %>% 
  mutate_if(is.numeric, round, 2)

Double check

ds %>% filter(quest==10) %>% summarise(x=ecdf(fm_sum)(30))
ds %>% filter(quest==10) %>% summarise(x=quantile(fm_sum, probs=c(.05)))

15.7 Performance of the cutoff

15.7.1 Below the cutoff

ds %>% 
  select(quest, ends_with("sum")) %>% #get variable names
  pivot_longer(-quest) %>% #tranform into the long format
  nest_by(quest, name) %>% #group or nest
  mutate(
    questionnaire = quest,#compute questionnaire
    n = list(map_dbl(data, ~nrow(data.frame(.)))), #compute sample size
    m_2sd = list(map_dbl(data, ~quantile(., prob = 0.05))), #2 below (now, 10th percentile)
    how_many_c = map(data, ~ ifelse(name == "c_sum", #i'll count how many participants are below
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(c_sum  <= m_2sd) %>% 
        summarise(n()),
      NA_integer_)), # percentage of communication
    
    how_many_gm = map(data, ~ ifelse(name == "gm_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(gm_sum <= m_2sd) %>% 
        summarise(n()), #percentage of gross motor
    NA_integer_)),
    
    how_many_fm = map(data, ~ ifelse(name == "fm_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(fm_sum <= m_2sd) %>% 
        summarise(n()),#percentage of fine motor
      NA_integer_)), 
    
    how_many_cg = map(data, ~ ifelse(name == "cg_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(cg_sum <= m_2sd) %>% 
        summarise(n()), #percentage of problem-solving
    NA_integer_)), 

    how_many_ps = map(data, ~ ifelse(name == "ps_sum",
      ds %>% 
        filter(quest == questionnaire) %>% 
        filter(ps_sum <= m_2sd) %>% 
        summarise(n()), #percentage of personal social
        NA_integer_)))  %>% 
  mutate(n_com=
           paste0(how_many_c[[1]],"-",
                 round(how_many_c[[1]]/n*100,0),"%"), #I'll get the percentages
         n_gm=
           paste0(how_many_gm[[1]],"-",
                 round(how_many_gm[[1]]/n*100,0),"%"),
         n_fm=
           paste0(how_many_fm[[1]],"-",
                 round(how_many_fm[[1]]/n*100,0),"%"),
         n_cg=
           paste0(how_many_cg[[1]],"-",
                 round(how_many_cg[[1]]/n*100,0),"%"),
         n_ps=
           paste0(how_many_ps[[1]],"-",
                 round(how_many_ps[[1]]/n*100,0),"%")                           
         ) %>%
  unnest_wider(-quest) %>% #particular trickes (there is a lot of pseudo missing values)
  select(quest,how_many_ps:last_col(), -how_many_ps) %>%  #get some variables
  pivot_longer(-quest) %>%  #now transform to the long format
  filter(value != "NA-NA%") %>% #filter
  pivot_wider(id_cols = quest, names_from = name, values_from = value)

15.7.2 Percentage monitor

ds %>%
  select(id, quest, ends_with("sum")) %>%
  pivot_longer(-c(id, quest)) %>% #tranform into  long format
  nest_by(quest, name) %>% #nest (id will not be used this time)
  #here is the trick. all counts are here
  mutate(mean = list(map_dbl(data[2], ~mean(.))),
         two_below = list(map_dbl(data[2], ~quantile(., prob = 0.05))),
         one_below = list(map_dbl(data[2], ~quantile(., prob = 0.10)))
  ) %>% 
  #outside of the map, add a new variable to nested data
  mutate(data = list(data %>% mutate(area_monitor = as.character(ifelse(data[[2]] > two_below & data[[2]] <= one_below, paste0(name),0))))) %>% 
  unnest(data) %>% #I'll unnest and get again the ids. my df will be very long
  pivot_wider(id_cols = c(id, quest), names_from = c(area_monitor), values_fn = length) %>% #now I'll group by ids!! my df will be sample size * quest
  ungroup() %>% #end of function 
  #now I'll count values
  mutate(how_many = select(.,ends_with("_sum")) %>% rowSums(., na.rm = T)) %>% 
  #now I'll present the results
  tabyl(quest, how_many)%>% 
  as.data.frame() %>% 
  #adorn_totals(c("row", "col")) %>% 
  #adorn_percentages("row") %>%
  #adorn_pct_formatting(digits = 2) %>%
  #adorn_ns() 
  pivot_longer(-quest) %>%
  group_by(quest) %>% 
  mutate(prop = prop.table(value)) %>%
  ungroup()%>% 
  ggplot(., aes(x = name, y = prop, group=quest, color = quest, label=quest)) +
  stat_summary(geom = "line", fun = mean, size=1) +
  #ggrepel::geom_text_repel(data = . %>% filter(name == "0"), box.padding = 0.5, max.overlaps = Inf) +
  labs(x = "Domains at the monitoring zone", y = "Proportion", color = "Questionnaire") +
  theme_bw() +
  theme(legend.position = "bottom")

15.7.3 Percentage below

ds %>%
  select(id, quest, ends_with("sum")) %>%
  pivot_longer(-c(id, quest)) %>% #tranform into  long format
  nest_by(quest, name) %>% #nest (id will not be used this time)
  #here is the trick. all counts are here
  mutate(mean = list(map_dbl(data[2], ~mean(.))),
         two_below = list(map_dbl(data[2], ~quantile(., prob = 0.05))),
         one_below = list(map_dbl(data[2], ~quantile(., prob = 0.10)))
  ) %>% 
  #outside of the map, add a new variable to nested data
  mutate(data = list(data %>% mutate(area_monitor = as.character(ifelse(data[[2]] <= two_below, paste0(name),0))))) %>% 
  unnest(data) %>% #I'll unnest and get again the ids. my df will be very long
  pivot_wider(id_cols = c(id, quest), names_from = c(area_monitor), values_fn = length) %>% #now I'll group by ids!! my df will be sample size * quest
  ungroup() %>% #end of function 
  #now I'll count values
  mutate(how_many = select(.,ends_with("_sum")) %>% rowSums(., na.rm = T)) %>% 
  #now I'll present the results
  tabyl(quest, how_many)%>% 
  as.data.frame() %>% 
  #adorn_totals(c("row", "col")) %>% 
  #adorn_percentages("row") %>%
  #adorn_pct_formatting(digits = 2) %>%
  #adorn_ns() 
  pivot_longer(-quest) %>%
  group_by(quest) %>% 
  mutate(prop = prop.table(value)) %>%
  ungroup()%>% 
  ggplot(., aes(x = name, y = prop, group=quest, color = quest, label=quest)) +
  stat_summary(geom = "line", fun = mean, size=1) +
  #ggrepel::geom_text_repel(data = . %>% filter(name == "0"), box.padding = 0.5, max.overlaps = Inf) +
  labs(x = "Domains below the cutoff", y = "Proportion", color = "Questionnaire") +
  theme_bw() +
  theme(legend.position = "bottom")

Testing to double check the differences between percentiles

#percentile 10

df_percentil_10 <- ds %>%
  filter(quest == 2) %>% 
  select(id, quest, ends_with("sum")) %>%
  pivot_longer(-c(id, quest)) %>% #tranform into  long format
  nest_by(quest, name) %>% #nest (id will not be used this time)
  #here is the trick. all counts are here
  mutate(mean = list(map_dbl(data[2], ~mean(.))),
         two_below = list(map_dbl(data[2], ~quantile(., prob = 0.05))),
         one_below = list(map_dbl(data[2], ~quantile(., prob = 0.10)))
  ) %>% 
  #outside of the map, add a new variable to nested data
  mutate(data = list(data %>% mutate(area_monitor = as.character(ifelse(data[[2]] > two_below & data[[2]] <= one_below, paste0(name),0))))) %>% 
  unnest(data) %>% 
  unnest(id) %>% 
  pivot_wider(id_cols = id, names_from = area_monitor, values_fn = length) %>% 
  mutate(how_many = select(.,ends_with("_sum")) %>% rowSums(., na.rm = T)) %>% 
  filter(how_many == 2) %>%
  rename_at(vars(ends_with("_sum")), ~paste(.,"_r")) %>% 
  mutate_all(~replace_na(., 0)) %>% 
  ungroup()


df_percentil_10 <- left_join(
df_percentil_10,
  ds %>% 
  select(id, ends_with("_sum")), 
by = "id") %>% 
  pivot_longer(-id) %>% 
  arrange(name) %>% 
  pivot_wider(id_cols = id, names_from = name, values_from = value, values_fill = 0) %>% 
  relocate(how_many, .before = "0") %>% 
  select(-"0",-how_many)
  
df_percentil_05 <- ds %>%
  filter(quest == 2) %>% 
  select(id, quest, ends_with("sum")) %>%
  pivot_longer(-c(id, quest)) %>% #tranform into  long format
  nest_by(quest, name) %>% #nest (id will not be used this time)
  #here is the trick. all counts are here
  mutate(mean = list(map_dbl(data[2], ~mean(.))),
         two_below = list(map_dbl(data[2], ~quantile(., prob = 0.05))),
         one_below = list(map_dbl(data[2], ~quantile(., prob = 0.10)))
  ) %>% 
  #outside of the map, add a new variable to nested data
mutate(data = list(data %>% mutate(area_monitor = as.character(ifelse(data[[2]] <= two_below, paste0(name),0))))) %>% 
unnest(data) %>% 
  unnest(id) %>% 
  pivot_wider(id_cols = id, names_from = area_monitor, values_fn = length) %>% 
  mutate(how_many = select(.,ends_with("_sum")) %>% rowSums(., na.rm = T)) %>% 
  filter(how_many == 2) %>%
  rename_at(vars(ends_with("_sum")), ~paste(.,"_r")) %>% 
  mutate_all(~replace_na(., 0)) %>% 
  ungroup()


df_percentil_05 <- left_join(
df_percentil_05,
  ds %>% 
  select(id, ends_with("_sum")), 
by = "id") %>% 
  pivot_longer(-id) %>% 
  arrange(name) %>% 
  pivot_wider(id_cols = id, names_from = name, values_from = value, values_fill = 0) %>% 
  relocate(how_many, .before = "0") %>% 
  select(-"0",-how_many)
rbind(df_percentil_10 %>% mutate(base="p10"),
df_percentil_05 %>% mutate(base="p05")) %>% 
  filter(id == "0931c359-d313-4f18-9d26-fc4bb192c0ed") %>% t()
  arrange(id) %>% 
  select(base, everything())

15.8 Decided on Feb 28, 22

decided_cutoff <- function(quest, domain, type) {
  quest = enquo(quest)
  domain = enquo(domain)
  ds2 = ds %>% mutate(quest = if_else(quest == "9", "10", as.character(quest))) #to combine 9 and 10 months questionnaires

  if (type == "trad") {
    #table 1
    x = ds2 %>% 
      filter(quest == !!quest) %>%
      summarise(n = n(),
                mean = mean(!!domain, na.rm=T), sd = sd(!!domain,na.rm=T),
                cutoff = mean-2*sd) %>% 
      mutate(quest = !!quest,domain = quo_name(domain)) #to identify which quest in the output list
    #table2
    y = ds2 %>% 
      filter(quest == !!quest) %>%
      mutate(n = n(),
             mean = mean(!!domain, na.rm=T), sd = sd(!!domain,na.rm=T),
             cutoff = mean-2*sd,
             class = ifelse(!!domain <= cutoff,"below","above")) %>%
      tabyl(class)
    
    j = cbind.data.frame(x,y)
    j = data.frame(lapply(j, function(j) if(is.numeric(j)) round(j, 2) else j)) #round
    j = j %>% select(quest, domain,everything()) #change position
    #https://stackoverflow.com/questions/9063889/how-to-round-a-data-frame-in-r-that-contains-some-character-variables
    
    return(j)
  }
  
  if (type == "10") {
    #table 1
    x = ds2 %>% 
      filter(quest == !!quest) %>%
      summarise(n = n(),
                mean = mean(!!domain, na.rm=T), sd = sd(!!domain,na.rm=T),
                p10 = quantile(x = !!domain, prob = 0.1),
                cutoff = p10) %>%
      mutate(quest = !!quest,domain = quo_name(domain)) #to identify which quest in the output list
   
    #table2
    y = ds2 %>% 
      filter(quest == !!quest) %>%
      mutate(cutoff = quantile(x = !!domain, prob = 0.1),
             class = ifelse(!!domain <= cutoff,"below","above")) %>%
      tabyl(class)
    
    j = cbind.data.frame(x,y)
    j = data.frame(lapply(j, function(j) if(is.numeric(j)) round(j, 2) else j)) #round
    j = j %>% select(quest, domain,everything()) #change position

    return(j)
  }
  

  if (type == "20p") {
    #table 1
    x = ds2 %>% 
      filter(quest == !!quest) %>%
      summarise(n = n(),
                mean = mean(!!domain, na.rm=T), sd = sd(!!domain,na.rm=T),
                cutoff = 20) %>%
      mutate(quest = !!quest,domain = quo_name(domain)) #to identify which quest in the output list
    
    #table2
    y = ds2 %>% 
      filter(quest == !!quest) %>%
      mutate(cutoff = 20,
             class = ifelse(!!domain <= cutoff,"below","above")) %>%
      tabyl(class)
    
    j = cbind.data.frame(x,y)
    j = data.frame(lapply(j, function(j) if(is.numeric(j)) round(j, 2) else j)) #round
    j = j %>% select(quest, domain,everything()) #change position
    
    return(j)
  }
  
  if (type == "25p") {
    #table 1
    x = ds2 %>% 
      filter(quest == !!quest) %>%
      summarise(n = n(),
                mean = mean(!!domain, na.rm=T), sd = sd(!!domain,na.rm=T),
                cutoff = 25) %>%
      mutate(quest = !!quest,domain = quo_name(domain)) #to identify which quest in the output list
   
    #table2
    y = ds2 %>% 
      filter(quest == !!quest) %>%
      mutate(cutoff = 25,
             class = ifelse(!!domain <= cutoff,"below","above")) %>%
      tabyl(class)
    
    j = cbind.data.frame(x,y)
    j = data.frame(lapply(j, function(j) if(is.numeric(j)) round(j, 2) else j)) #round
    j = j %>% select(quest, domain,everything()) #change position

    return(j)
    }

  if (type == "30p") {
    #table 1
    x = ds2 %>% 
      filter(quest == !!quest) %>%
      summarise(n = n(),
                mean = mean(!!domain, na.rm=T), sd = sd(!!domain,na.rm=T),
                cutoff = 30) %>%
      mutate(quest = !!quest,domain = quo_name(domain)) #to identify which quest in the output list
    
    #table2
    y = ds2 %>% 
      filter(quest == !!quest) %>%
      mutate(cutoff = 30,
             class = ifelse(!!domain <= cutoff,"below","above")) %>%
      tabyl(class)
    
    j = cbind.data.frame(x,y)
    j = data.frame(lapply(j, function(j) if(is.numeric(j)) round(j, 2) else j)) #round
    j = j %>% select(quest, domain,everything()) #change position
    
    return(j)
  }
    
     if (type == "35p") {
    #table 1
    x = ds2 %>% 
      filter(quest == !!quest) %>%
      summarise(n = n(),
                mean = mean(!!domain, na.rm=T), sd = sd(!!domain,na.rm=T),
                cutoff = 35) %>%
      mutate(quest = !!quest,domain = quo_name(domain)) #to identify which quest in the output list
   
    #table2
    y = ds2 %>% 
      filter(quest == !!quest) %>%
      mutate(cutoff = 35,
             class = ifelse(!!domain <= cutoff,"below","above")) %>%
      tabyl(class)
    
    j = cbind.data.frame(x,y)
    j = data.frame(lapply(j, function(j) if(is.numeric(j)) round(j, 2) else j)) #round
    j = j %>% select(quest, domain,everything()) #change position

    return(j)
    }
  
}

15.8.1 2 months

print(list(
  decided_cutoff(type = "trad", quest = 2, domain = c_sum),
  decided_cutoff(type = "trad", quest = 2, domain = gm_sum),
  decided_cutoff(type = "trad", quest = 2, domain = fm_sum),
  decided_cutoff(type = "trad", quest = 2, domain = cg_sum),
  decided_cutoff(type = "trad", quest = 2, domain = ps_sum)
))
[[1]]
  quest domain    n  mean    sd cutoff class  n.1 percent
1     2  c_sum 1404 42.24 14.42   13.4 above 1348    0.96
2     2  c_sum 1404 42.24 14.42   13.4 below   56    0.04

[[2]]
  quest domain    n  mean   sd cutoff class  n.1 percent
1     2 gm_sum 1404 53.84 7.79  38.26 above 1338    0.95
2     2 gm_sum 1404 53.84 7.79  38.26 below   66    0.05

[[3]]
  quest domain    n  mean    sd cutoff class  n.1 percent
1     2 fm_sum 1404 47.36 10.08   27.2 above 1355    0.97
2     2 fm_sum 1404 47.36 10.08   27.2 below   49    0.03

[[4]]
  quest domain    n  mean    sd cutoff class  n.1 percent
1     2 cg_sum 1404 45.38 10.98  23.43 above 1355    0.97
2     2 cg_sum 1404 45.38 10.98  23.43 below   49    0.03

[[5]]
  quest domain    n  mean    sd cutoff class  n.1 percent
1     2 ps_sum 1404 42.98 13.24  16.51 above 1342    0.96
2     2 ps_sum 1404 42.98 13.24  16.51 below   62    0.04

15.8.2 4 months

print(list(
  decided_cutoff(type = "trad", quest = 4, domain = c_sum),
  decided_cutoff(type = "trad", quest = 4, domain = gm_sum),
  decided_cutoff(type = "trad", quest = 4, domain = fm_sum),
  decided_cutoff(type = "trad", quest = 4, domain = cg_sum),
  decided_cutoff(type = "trad", quest = 4, domain = ps_sum)
))
[[1]]
  quest domain    n  mean   sd cutoff class  n.1 percent
1     4  c_sum 1365 50.23 9.85  30.54 above 1281    0.94
2     4  c_sum 1365 50.23 9.85  30.54 below   84    0.06

[[2]]
  quest domain    n  mean   sd cutoff class  n.1 percent
1     4 gm_sum 1365 53.38 9.09   35.2 above 1267    0.93
2     4 gm_sum 1365 53.38 9.09   35.2 below   98    0.07

[[3]]
  quest domain    n  mean   sd cutoff class  n.1 percent
1     4 fm_sum 1365 46.14 12.9  20.34 above 1277    0.94
2     4 fm_sum 1365 46.14 12.9  20.34 below   88    0.06

[[4]]
  quest domain    n  mean    sd cutoff class  n.1 percent
1     4 cg_sum 1365 48.82 10.79  27.25 above 1292    0.95
2     4 cg_sum 1365 48.82 10.79  27.25 below   73    0.05

[[5]]
  quest domain    n  mean   sd cutoff class  n.1 percent
1     4 ps_sum 1365 50.28 10.8  28.68 above 1307    0.96
2     4 ps_sum 1365 50.28 10.8  28.68 below   58    0.04

15.8.3 6 months

print(list(
  decided_cutoff(type = "trad", quest = 6, domain = c_sum),
  decided_cutoff(type = "trad", quest = 6, domain = gm_sum),
  decided_cutoff(type = "trad", quest = 6, domain = fm_sum),
  decided_cutoff(type = "trad", quest = 6, domain = cg_sum),
  decided_cutoff(type = "trad", quest = 6, domain = ps_sum)
))
[[1]]
  quest domain    n  mean   sd cutoff class  n.1 percent
1     6  c_sum 1099 47.71 9.66  28.39 above 1058    0.96
2     6  c_sum 1099 47.71 9.66  28.39 below   41    0.04

[[2]]
  quest domain    n mean    sd cutoff class  n.1 percent
1     6 gm_sum 1099 42.3 12.51  17.27 above 1052    0.96
2     6 gm_sum 1099 42.3 12.51  17.27 below   47    0.04

[[3]]
  quest domain    n  mean    sd cutoff class  n.1 percent
1     6 fm_sum 1099 47.56 12.85  21.85 above 1042    0.95
2     6 fm_sum 1099 47.56 12.85  21.85 below   57    0.05

[[4]]
  quest domain    n  mean    sd cutoff class  n.1 percent
1     6 cg_sum 1099 45.71 11.65  22.41 above 1054    0.96
2     6 cg_sum 1099 45.71 11.65  22.41 below   45    0.04

[[5]]
  quest domain    n mean    sd cutoff class  n.1 percent
1     6 ps_sum 1099   47 12.76  21.49 above 1034    0.94
2     6 ps_sum 1099   47 12.76  21.49 below   65    0.06

15.8.4 8 months

print(list(
  decided_cutoff(type = "10", quest = 8, domain = c_sum),
  decided_cutoff(type = "10", quest = 8, domain = gm_sum),
  decided_cutoff(type = "10", quest = 8, domain = fm_sum),
  decided_cutoff(type = "10", quest = 8, domain = cg_sum),
  decided_cutoff(type = "10", quest = 8, domain = ps_sum)
))
[[1]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1     8  c_sum 1020 49.42 11.02  35     35 above 862    0.85
2     8  c_sum 1020 49.42 11.02  35     35 below 158    0.15

[[2]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1     8 gm_sum 1020 48.48 12.75  30     30 above 895    0.88
2     8 gm_sum 1020 48.48 12.75  30     30 below 125    0.12

[[3]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1     8 fm_sum 1020 53.28 10.15  40     40 above 893    0.88
2     8 fm_sum 1020 53.28 10.15  40     40 below 127    0.12

[[4]]
  quest domain    n  mean sd p10 cutoff class n.1 percent
1     8 cg_sum 1020 49.24 11  35     35 above 869    0.85
2     8 cg_sum 1020 49.24 11  35     35 below 151    0.15

[[5]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1     8 ps_sum 1020 50.84 10.41  35     35 above 896    0.88
2     8 ps_sum 1020 50.84 10.41  35     35 below 124    0.12

15.8.5 9 and 10 months

print(list(
  decided_cutoff(type = "25p", quest = 10, domain = c_sum),
  decided_cutoff(type = "25p", quest = 10, domain = gm_sum),
  decided_cutoff(type = "10", quest = 10, domain = fm_sum),
  decided_cutoff(type = "10", quest = 10, domain = cg_sum),
  decided_cutoff(type = "10", quest = 10, domain = ps_sum)
))
[[1]]
  quest domain   n  mean   sd cutoff class n.1 percent
1    10  c_sum 937 41.86 13.9     25 above 793    0.85
2    10  c_sum 937 41.86 13.9     25 below 144    0.15

[[2]]
  quest domain   n mean    sd cutoff class n.1 percent
1    10 gm_sum 937 45.3 14.65     25 above 797    0.85
2    10 gm_sum 937 45.3 14.65     25 below 140    0.15

[[3]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    10 fm_sum 937 51.84 10.51  40     40 above 768    0.82
2    10 fm_sum 937 51.84 10.51  40     40 below 169    0.18

[[4]]
  quest domain   n  mean   sd p10 cutoff class n.1 percent
1    10 cg_sum 937 47.62 10.9  30     30 above 837    0.89
2    10 cg_sum 937 47.62 10.9  30     30 below 100    0.11

[[5]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    10 ps_sum 937 48.86 11.41  35     35 above 787    0.84
2    10 ps_sum 937 48.86 11.41  35     35 below 150    0.16

15.8.6 12 months

print(list(
  decided_cutoff(type = "10", quest = 12, domain = c_sum),
  decided_cutoff(type = "10", quest = 12, domain = gm_sum),
  decided_cutoff(type = "10", quest = 12, domain = fm_sum),
  decided_cutoff(type = "10", quest = 12, domain = cg_sum),
  decided_cutoff(type = "10", quest = 12, domain = ps_sum)
))
[[1]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    12  c_sum 1018 44.11 13.55  25     25 above 885    0.87
2    12  c_sum 1018 44.11 13.55  25     25 below 133    0.13

[[2]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    12 gm_sum 1018 48.21 13.31  30     30 above 888    0.87
2    12 gm_sum 1018 48.21 13.31  30     30 below 130    0.13

[[3]]
  quest domain    n  mean   sd p10 cutoff class n.1 percent
1    12 fm_sum 1018 44.95 11.2  30     30 above 874    0.86
2    12 fm_sum 1018 44.95 11.2  30     30 below 144    0.14

[[4]]
  quest domain    n  mean    sd  p10 cutoff class n.1 percent
1    12 cg_sum 1018 41.85 13.87 23.5   23.5 above 916     0.9
2    12 cg_sum 1018 41.85 13.87 23.5   23.5 below 102     0.1

[[5]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    12 ps_sum 1018 45.49 12.39  30     30 above 865    0.85
2    12 ps_sum 1018 45.49 12.39  30     30 below 153    0.15

15.8.7 14 months

print(list(
  decided_cutoff(type = "25p", quest = 14, domain = c_sum),
  decided_cutoff(type = "10", quest = 14, domain = gm_sum),
  decided_cutoff(type = "10", quest = 14, domain = fm_sum),
  decided_cutoff(type = "10", quest = 14, domain = cg_sum),
  decided_cutoff(type = "10", quest = 14, domain = ps_sum)
))
[[1]]
  quest domain   n  mean    sd cutoff class n.1 percent
1    14  c_sum 798 38.75 15.34     25 above 602    0.75
2    14  c_sum 798 38.75 15.34     25 below 196    0.25

[[2]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    14 gm_sum 798 51.64 13.98  30     30 above 682    0.85
2    14 gm_sum 798 51.64 13.98  30     30 below 116    0.15

[[3]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    14 fm_sum 798 45.64 12.05  30     30 above 677    0.85
2    14 fm_sum 798 45.64 12.05  30     30 below 121    0.15

[[4]]
  quest domain   n mean    sd p10 cutoff class n.1 percent
1    14 cg_sum 798 43.2 14.04  20     20 above 713    0.89
2    14 cg_sum 798 43.2 14.04  20     20 below  85    0.11

[[5]]
  quest domain   n  mean   sd p10 cutoff class n.1 percent
1    14 ps_sum 798 41.74 13.9  20     20 above 707    0.89
2    14 ps_sum 798 41.74 13.9  20     20 below  91    0.11

15.8.8 16 months

print(list(
  decided_cutoff(type = "25p", quest = 16, domain = c_sum),
  decided_cutoff(type = "10", quest = 16, domain = gm_sum),
  decided_cutoff(type = "10", quest = 16, domain = fm_sum),
  decided_cutoff(type = "10", quest = 16, domain = cg_sum),
  decided_cutoff(type = "10", quest = 16, domain = ps_sum)
))
[[1]]
  quest domain   n  mean    sd cutoff class n.1 percent
1    16  c_sum 915 39.12 14.96     25 above 721    0.79
2    16  c_sum 915 39.12 14.96     25 below 194    0.21

[[2]]
  quest domain   n mean    sd p10 cutoff class n.1 percent
1    16 gm_sum 915 53.2 13.73  35     35 above 818    0.89
2    16 gm_sum 915 53.2 13.73  35     35 below  97    0.11

[[3]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    16 fm_sum 915 49.64 11.08  35     35 above 793    0.87
2    16 fm_sum 915 49.64 11.08  35     35 below 122    0.13

[[4]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    16 cg_sum 915 46.61 13.62  25     25 above 809    0.88
2    16 cg_sum 915 46.61 13.62  25     25 below 106    0.12

[[5]]
  quest domain   n  mean   sd p10 cutoff class n.1 percent
1    16 ps_sum 915 44.22 14.4  20     20 above 820     0.9
2    16 ps_sum 915 44.22 14.4  20     20 below  95     0.1

15.8.9 18 months

print(list(
  decided_cutoff(type = "25p", quest = 18, domain = c_sum),
  decided_cutoff(type = "10", quest = 18, domain = gm_sum),
  decided_cutoff(type = "10", quest = 18, domain = fm_sum),
  decided_cutoff(type = "10", quest = 18, domain = cg_sum),
  decided_cutoff(type = "10", quest = 18, domain = ps_sum)
))
[[1]]
  quest domain    n  mean sd cutoff class n.1 percent
1    18  c_sum 1087 33.56 17     25 above 705    0.65
2    18  c_sum 1087 33.56 17     25 below 382    0.35

[[2]]
  quest domain    n  mean   sd p10 cutoff class n.1 percent
1    18 gm_sum 1087 54.52 9.09  45     45 above 932    0.86
2    18 gm_sum 1087 54.52 9.09  45     45 below 155    0.14

[[3]]
  quest domain    n  mean   sd p10 cutoff class n.1 percent
1    18 fm_sum 1087 51.69 9.53  40     40 above 923    0.85
2    18 fm_sum 1087 51.69 9.53  40     40 below 164    0.15

[[4]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    18 cg_sum 1087 48.22 11.64  35     35 above 921    0.85
2    18 cg_sum 1087 48.22 11.64  35     35 below 166    0.15

[[5]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    18 ps_sum 1087 47.71 11.55  30     30 above 960    0.88
2    18 ps_sum 1087 47.71 11.55  30     30 below 127    0.12

15.8.10 20 months

print(list(
  decided_cutoff(type = "25p", quest = 20, domain = c_sum),
  decided_cutoff(type = "10", quest = 20, domain = gm_sum),
  decided_cutoff(type = "10", quest = 20, domain = fm_sum),
  decided_cutoff(type = "10", quest = 20, domain = cg_sum),
  decided_cutoff(type = "10", quest = 20, domain = ps_sum)
))
[[1]]
  quest domain   n  mean    sd cutoff class n.1 percent
1    20  c_sum 756 36.12 19.87     25 above 492    0.65
2    20  c_sum 756 36.12 19.87     25 below 264    0.35

[[2]]
  quest domain   n  mean   sd p10 cutoff class n.1 percent
1    20 gm_sum 756 54.11 9.23  45     45 above 630    0.83
2    20 gm_sum 756 54.11 9.23  45     45 below 126    0.17

[[3]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    20 fm_sum 756 50.17 10.23  35     35 above 673    0.89
2    20 fm_sum 756 50.17 10.23  35     35 below  83    0.11

[[4]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    20 cg_sum 756 43.23 13.55  20     20 above 675    0.89
2    20 cg_sum 756 43.23 13.55  20     20 below  81    0.11

[[5]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    20 ps_sum 756 41.54 13.49  20     20 above 679     0.9
2    20 ps_sum 756 41.54 13.49  20     20 below  77     0.1

15.8.11 22 months

print(list(
  decided_cutoff(type = "25p", quest = 22, domain = c_sum),
  decided_cutoff(type = "10", quest = 22, domain = gm_sum),
  decided_cutoff(type = "10", quest = 22, domain = fm_sum),
  decided_cutoff(type = "10", quest = 22, domain = cg_sum),
  decided_cutoff(type = "10", quest = 22, domain = ps_sum)
))
[[1]]
  quest domain   n  mean    sd cutoff class n.1 percent
1    22  c_sum 708 37.81 19.49     25 above 477    0.67
2    22  c_sum 708 37.81 19.49     25 below 231    0.33

[[2]]
  quest domain   n  mean   sd p10 cutoff class n.1 percent
1    22 gm_sum 708 50.13 10.9  35     35 above 618    0.87
2    22 gm_sum 708 50.13 10.9  35     35 below  90    0.13

[[3]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    22 fm_sum 708 45.68 10.52  30     30 above 618    0.87
2    22 fm_sum 708 45.68 10.52  30     30 below  90    0.13

[[4]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    22 cg_sum 708 44.22 13.51  25     25 above 616    0.87
2    22 cg_sum 708 44.22 13.51  25     25 below  92    0.13

[[5]]
  quest domain   n mean   sd p10 cutoff class n.1 percent
1    22 ps_sum 708 49.4 11.9  30     30 above 634     0.9
2    22 ps_sum 708 49.4 11.9  30     30 below  74     0.1

15.8.12 24 months

print(list(
  decided_cutoff(type = "25p", quest = 24, domain = c_sum),
  decided_cutoff(type = "10", quest = 24, domain = gm_sum),
  decided_cutoff(type = "10", quest = 24, domain = fm_sum),
  decided_cutoff(type = "10", quest = 24, domain = cg_sum),
  decided_cutoff(type = "10", quest = 24, domain = ps_sum)
))
[[1]]
  quest domain    n  mean    sd cutoff class n.1 percent
1    24  c_sum 1043 41.49 19.31     25 above 775    0.74
2    24  c_sum 1043 41.49 19.31     25 below 268    0.26

[[2]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    24 gm_sum 1043 52.64 10.02  40     40 above 905    0.87
2    24 gm_sum 1043 52.64 10.02  40     40 below 138    0.13

[[3]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    24 fm_sum 1043 41.89 11.92  25     25 above 921    0.88
2    24 fm_sum 1043 41.89 11.92  25     25 below 122    0.12

[[4]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    24 cg_sum 1043 44.88 13.37  25     25 above 918    0.88
2    24 cg_sum 1043 44.88 13.37  25     25 below 125    0.12

[[5]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    24 ps_sum 1043 48.17 11.94  30     30 above 922    0.88
2    24 ps_sum 1043 48.17 11.94  30     30 below 121    0.12

15.8.13 27 months

print(list(
  decided_cutoff(type = "25p", quest = 27, domain = c_sum),
  decided_cutoff(type = "10", quest = 27, domain = gm_sum),
  decided_cutoff(type = "10", quest = 27, domain = fm_sum),
  decided_cutoff(type = "10", quest = 27, domain = cg_sum),
  decided_cutoff(type = "10", quest = 27, domain = ps_sum)
))
[[1]]
  quest domain   n  mean    sd cutoff class n.1 percent
1    27  c_sum 778 44.95 16.78     25 above 642    0.83
2    27  c_sum 778 44.95 16.78     25 below 136    0.17

[[2]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    27 gm_sum 778 51.25 10.37  35     35 above 692    0.89
2    27 gm_sum 778 51.25 10.37  35     35 below  86    0.11

[[3]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    27 fm_sum 778 39.81 14.34  20     20 above 687    0.88
2    27 fm_sum 778 39.81 14.34  20     20 below  91    0.12

[[4]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    27 cg_sum 778 44.16 14.03  25     25 above 668    0.86
2    27 cg_sum 778 44.16 14.03  25     25 below 110    0.14

[[5]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    27 ps_sum 778 47.74 12.86  30     30 above 672    0.86
2    27 ps_sum 778 47.74 12.86  30     30 below 106    0.14

15.8.14 30 months

print(list(
  decided_cutoff(type = "30p", quest = 30, domain = c_sum),
  decided_cutoff(type = "10", quest = 30, domain = gm_sum),
  decided_cutoff(type = "10", quest = 30, domain = fm_sum),
  decided_cutoff(type = "10", quest = 30, domain = cg_sum),
  decided_cutoff(type = "10", quest = 30, domain = ps_sum)
))
[[1]]
  quest domain   n  mean    sd cutoff class n.1 percent
1    30  c_sum 795 48.29 15.47     30 above 676    0.85
2    30  c_sum 795 48.29 15.47     30 below 119    0.15

[[2]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    30 gm_sum 795 50.75 10.69  35     35 above 703    0.88
2    30 gm_sum 795 50.75 10.69  35     35 below  92    0.12

[[3]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    30 fm_sum 795 41.79 14.85  20     20 above 684    0.86
2    30 fm_sum 795 41.79 14.85  20     20 below 111    0.14

[[4]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    30 cg_sum 795 46.38 13.11  27     27 above 715     0.9
2    30 cg_sum 795 46.38 13.11  27     27 below  80     0.1

[[5]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    30 ps_sum 795 45.87 13.07  27     27 above 715     0.9
2    30 ps_sum 795 45.87 13.07  27     27 below  80     0.1

15.8.15 33 months

print(list(
  decided_cutoff(type = "10", quest = 33, domain = c_sum),
  decided_cutoff(type = "10", quest = 33, domain = gm_sum),
  decided_cutoff(type = "10", quest = 33, domain = fm_sum),
  decided_cutoff(type = "10", quest = 33, domain = cg_sum),
  decided_cutoff(type = "10", quest = 33, domain = ps_sum)
))
[[1]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    33  c_sum 672 48.78 15.48  25     25 above 580    0.86
2    33  c_sum 672 48.78 15.48  25     25 below  92    0.14

[[2]]
  quest domain   n  mean  sd p10 cutoff class n.1 percent
1    33 gm_sum 672 52.72 9.7  40     40 above 582    0.87
2    33 gm_sum 672 52.72 9.7  40     40 below  90    0.13

[[3]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    33 fm_sum 672 38.93 16.47  15     15 above 579    0.86
2    33 fm_sum 672 38.93 16.47  15     15 below  93    0.14

[[4]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    33 cg_sum 672 47.47 12.46  30     30 above 587    0.87
2    33 cg_sum 672 47.47 12.46  30     30 below  85    0.13

[[5]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    33 ps_sum 672 48.42 12.33  30     30 above 583    0.87
2    33 ps_sum 672 48.42 12.33  30     30 below  89    0.13

15.8.16 36 months

print(list(
  decided_cutoff(type = "30p", quest = 36, domain = c_sum),
  decided_cutoff(type = "10", quest = 36, domain = gm_sum),
  decided_cutoff(type = "10", quest = 36, domain = fm_sum),
  decided_cutoff(type = "10", quest = 36, domain = cg_sum),
  decided_cutoff(type = "10", quest = 36, domain = ps_sum)
))
[[1]]
  quest domain    n  mean    sd cutoff class n.1 percent
1    36  c_sum 1055 48.55 14.24     30 above 911    0.86
2    36  c_sum 1055 48.55 14.24     30 below 144    0.14

[[2]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    36 gm_sum 1055 51.42 10.51  35     35 above 940    0.89
2    36 gm_sum 1055 51.42 10.51  35     35 below 115    0.11

[[3]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    36 fm_sum 1055 39.57 17.24  15     15 above 908    0.86
2    36 fm_sum 1055 39.57 17.24  15     15 below 147    0.14

[[4]]
  quest domain    n  mean    sd p10 cutoff class n.1 percent
1    36 cg_sum 1055 48.51 12.56  30     30 above 922    0.87
2    36 cg_sum 1055 48.51 12.56  30     30 below 133    0.13

[[5]]
  quest domain    n  mean   sd p10 cutoff class n.1 percent
1    36 ps_sum 1055 50.26 11.2  35     35 above 920    0.87
2    36 ps_sum 1055 50.26 11.2  35     35 below 135    0.13

15.8.17 42 months

print(list(
  decided_cutoff(type = "10", quest = 42, domain = c_sum),
  decided_cutoff(type = "10", quest = 42, domain = gm_sum),
  decided_cutoff(type = "25p", quest = 42, domain = fm_sum),
  decided_cutoff(type = "10", quest = 42, domain = cg_sum),
  decided_cutoff(type = "10", quest = 42, domain = ps_sum)
))
[[1]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    42  c_sum 1256 51.29 12.39  35     35 above 1094    0.87
2    42  c_sum 1256 51.29 12.39  35     35 below  162    0.13

[[2]]
  quest domain    n  mean   sd p10 cutoff class  n.1 percent
1    42 gm_sum 1256 52.52 9.65  40     40 above 1091    0.87
2    42 gm_sum 1256 52.52 9.65  40     40 below  165    0.13

[[3]]
  quest domain    n  mean    sd cutoff class  n.1 percent
1    42 fm_sum 1256 42.17 16.18     25 above 1012    0.81
2    42 fm_sum 1256 42.17 16.18     25 below  244    0.19

[[4]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    42 cg_sum 1256 49.42 12.27  30     30 above 1121    0.89
2    42 cg_sum 1256 49.42 12.27  30     30 below  135    0.11

[[5]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    42 ps_sum 1256 50.53 11.54  35     35 above 1099    0.88
2    42 ps_sum 1256 50.53 11.54  35     35 below  157    0.12

15.8.18 48 months

print(list(
  decided_cutoff(type = "10", quest = 48, domain = c_sum),
  decided_cutoff(type = "10", quest = 48, domain = gm_sum),
  decided_cutoff(type = "10", quest = 48, domain = fm_sum),
  decided_cutoff(type = "10", quest = 48, domain = cg_sum),
  decided_cutoff(type = "10", quest = 48, domain = ps_sum)
))
[[1]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    48  c_sum 1210 51.49 12.59  35     35 above 1068    0.88
2    48  c_sum 1210 51.49 12.59  35     35 below  142    0.12

[[2]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    48 gm_sum 1210 52.09 10.71  35     35 above 1085     0.9
2    48 gm_sum 1210 52.09 10.71  35     35 below  125     0.1

[[3]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    48 fm_sum 1210 39.92 16.07  15     15 above 1067    0.88
2    48 fm_sum 1210 39.92 16.07  15     15 below  143    0.12

[[4]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    48 cg_sum 1210 47.63 12.43  30     30 above 1059    0.88
2    48 cg_sum 1210 47.63 12.43  30     30 below  151    0.12

[[5]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    48 ps_sum 1210 51.54 10.65  35     35 above 1080    0.89
2    48 ps_sum 1210 51.54 10.65  35     35 below  130    0.11

15.8.19 54 months

print(list(
  decided_cutoff(type = "10", quest = 54, domain = c_sum),
  decided_cutoff(type = "35p", quest = 54, domain = gm_sum),
  decided_cutoff(type = "10", quest = 54, domain = fm_sum),
  decided_cutoff(type = "10", quest = 54, domain = cg_sum),
  decided_cutoff(type = "10", quest = 54, domain = ps_sum)
))
[[1]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    54  c_sum 1193 52.92 10.91  40     40 above 1031    0.86
2    54  c_sum 1193 52.92 10.91  40     40 below  162    0.14

[[2]]
  quest domain    n mean   sd cutoff class  n.1 percent
1    54 gm_sum 1193 52.7 10.6     35 above 1077     0.9
2    54 gm_sum 1193 52.7 10.6     35 below  116     0.1

[[3]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    54 fm_sum 1193 42.26 16.14  15     15 above 1066    0.89
2    54 fm_sum 1193 42.26 16.14  15     15 below  127    0.11

[[4]]
  quest domain    n  mean    sd p10 cutoff class  n.1 percent
1    54 cg_sum 1193 48.16 11.99  30     30 above 1062    0.89
2    54 cg_sum 1193 48.16 11.99  30     30 below  131    0.11

[[5]]
  quest domain    n  mean   sd p10 cutoff class  n.1 percent
1    54 ps_sum 1193 50.49 10.4  35     35 above 1053    0.88
2    54 ps_sum 1193 50.49 10.4  35     35 below  140    0.12

15.8.20 60 months

print(list(
  decided_cutoff(type = "10", quest = 60, domain = c_sum),
  decided_cutoff(type = "10", quest = 60, domain = gm_sum),
  decided_cutoff(type = "10", quest = 60, domain = fm_sum),
  decided_cutoff(type = "10", quest = 60, domain = cg_sum),
  decided_cutoff(type = "10", quest = 60, domain = ps_sum)
))
[[1]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    60  c_sum 921 50.62 11.14  35     35 above 813    0.88
2    60  c_sum 921 50.62 11.14  35     35 below 108    0.12

[[2]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    60 gm_sum 921 51.06 10.76  35     35 above 809    0.88
2    60 gm_sum 921 51.06 10.76  35     35 below 112    0.12

[[3]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    60 fm_sum 921 48.26 14.94  25     25 above 811    0.88
2    60 fm_sum 921 48.26 14.94  25     25 below 110    0.12

[[4]]
  quest domain   n  mean   sd p10 cutoff class n.1 percent
1    60 cg_sum 921 51.05 10.8  35     35 above 824    0.89
2    60 cg_sum 921 51.05 10.8  35     35 below  97    0.11

[[5]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    60 ps_sum 921 49.95 12.24  35     35 above 777    0.84
2    60 ps_sum 921 49.95 12.24  35     35 below 144    0.16

15.8.21 72 months

print(list(
  decided_cutoff(type = "10", quest = 72, domain = c_sum),
  decided_cutoff(type = "10", quest = 72, domain = gm_sum),
  decided_cutoff(type = "10", quest = 72, domain = fm_sum),
  decided_cutoff(type = "10", quest = 72, domain = cg_sum),
  decided_cutoff(type = "10", quest = 72, domain = ps_sum)
))
[[1]]
  quest domain   n  mean   sd p10 cutoff class n.1 percent
1    72  c_sum 791 50.71 12.2  35     35 above 687    0.87
2    72  c_sum 791 50.71 12.2  35     35 below 104    0.13

[[2]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    72 gm_sum 791 49.32 12.71  30     30 above 701    0.89
2    72 gm_sum 791 49.32 12.71  30     30 below  90    0.11

[[3]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    72 fm_sum 791 53.84 10.43  40     40 above 700    0.88
2    72 fm_sum 791 53.84 10.43  40     40 below  91    0.12

[[4]]
  quest domain   n  mean    sd p10 cutoff class n.1 percent
1    72 cg_sum 791 48.02 11.91  30     30 above 697    0.88
2    72 cg_sum 791 48.02 11.91  30     30 below  94    0.12

[[5]]
  quest domain   n mean    sd p10 cutoff class n.1 percent
1    72 ps_sum 791 49.9 12.21  35     35 above 683    0.86
2    72 ps_sum 791 49.9 12.21  35     35 below 108    0.14

16 ROC CURVE

16.1 Descriptive

ds_eligible %>% 
  select(quest,ends_with("_sum")) %>% 
    tableby(quest ~ ., control = tableby.control(numeric.stats=c("mean", "sd")), data = .) %>% 
  summary(. , digits = 2)
ds_eligible %>% tabyl(gender)

16.2 Results n>1

ds_eligible %>%
  select(quest,ends_with("_sum")) %>% 
  group_by(quest) %>%
  filter(n()>1) %>%
  ungroup() %>%
  pivot_longer(-quest) %>%
  group_by(quest, name) %>% 
  mutate(
    n=n(),
    m=mean(value),
    sd=sd(value),
    monitor=m-sd,
    below=m-2*sd)%>%
  select(-value) %>% 
  distinct() %>% #remove duplicate
  pivot_wider(id_cols = quest, names_from = name, values_from = n:below, names_glue = "{name}_{.value}") %>%
  mutate_if(is.numeric, round, 2) %>%
  .[gtools::mixedorder(.$quest), ] 

16.3 T tests

#check which bases I can compare (2 groups)
bind_rows(
  ds_eligible %>%
    select(quest,ends_with("_sum")) %>% 
    group_by(quest) %>%
    filter(n()>1) %>%
    ungroup() %>%
    mutate(base="eligible")
  ,
  ds %>% 
    select(quest,ends_with("_sum")) %>% 
    mutate(base="original")
) %>%
  group_by(quest) %>%
  count(base)%>% #check each age inerval
  filter(n()>1) %>% #remove if just one group
  ungroup() %>%
  select(quest) %>% distinct() %>%
  pull(quest) -> questionnaires_to_compare

#define a df to compare 
bind_rows(
  ds_eligible %>%
    select(quest,ends_with("_sum")) %>% 
    group_by(quest) %>%
    filter(n()>1) %>%
    ungroup() %>%
    mutate(base="eligible")
  ,
  ds %>% 
    select(quest,ends_with("_sum")) %>% 
    mutate(base="original")
) %>%
  #filter those ages in which I have just one group
  filter(quest %in% c(questionnaires_to_compare)) %>%
  #need to have the long format to nest the all questionnaires
  pivot_longer(c_sum:ps_sum) %>%
  nest_by(quest,name) %>%
  summarise(model = list(t.test(value ~ base, data = data, var.equal=T , alternative = "less"))) %>%  #https://stackoverflow.com/questions/51074328/perform-several-t-tests-simultaneously-on-tidy-data-in-r
  mutate(model = map(model, broom::tidy)) %>%
  unnest(cols = c(model)) %>%
  select(quest, name, estimate1, estimate2, p.value) %>%
  mutate_if(is.numeric, round, 2)%>%
  #presenting
  pivot_wider(id_cols = quest, names_from =name, values_from = c(estimate1, estimate2, p.value), names_glue = "{name}_{.value}") %>%
   select("quest", sort(colnames(.)))

16.4 ROC graph

#library(cutpointr)
set.seed(13)
bind_rows(
  #typical  
  ds %>% 
    filter(quest == 24) %>%
    select(c_sum) %>%
    mutate(group = 0) %>%
    sample_n(., 24)
  ,
  #eligible
  ds_eligible %>% 
    filter(quest == 36) %>% 
    mutate(group =1) %>%
    select(group, c_sum)
) %>%
  cutpointr(., c_sum, group, 
            pos_class = 1,
            method = maximize_metric,  
            metric = youden) %>% 
  #plot_x()
  #plot_roc() + geom_abline(slope = 1) + theme_bw()
  summary(.)

17 Test-Retest reliability

ds_retest_analysis 
ds_retest_analysis %>%
  select_if(is.numeric) %>%
  group_by(quest) %>%
  nest() %>%
  mutate(
    correlations = map(data, corrr::correlate)
  ) %>%
  unnest(correlations)

17.1 Grouped corr

# pearson correlation
retest_cor <- ds_retest_analysis %>% 
  split(list(.$quest)) %>% 
  map(~Hmisc::rcorr(as.matrix(.))$r) 
# create a column with questionnaire
retest_cor <- do.call(rbind.data.frame, retest_cor)

# P vaues of pearson correlation
retest_cor_pval <- ds_retest_analysis %>% 
  split(list(.$quest)) %>% 
  map(~Hmisc::rcorr(as.matrix(.))$P)
# create a column with questionnaire
retest_cor_pval <- do.call(rbind.data.frame, retest_cor_pval)

17.2 Table

17.2.1 RECHECK communicationg ?!?! (RECHECK !!! On Feb 1,2022 – Really recheck!)

test_rest_table <- left_join(
  # R COEF
  retest_cor %>% 
    select(-quest) %>% # remove questionnaires
    rownames_to_column(var = "quest") %>%  #add real questionnaires
    separate(., col = "quest", into = c("quest","domain","sum", "time")) %>%#rename and separate
    filter(time == "x") %>% 
    select(-sum, -time) %>% 
    select(quest, domain, ends_with("y")) %>% #select everything
    pivot_longer(-c("quest","domain")) %>%  #to match
    mutate(name =str_extract_all(name, "\\w+(?=_)", simplify = T)) %>% #filter same domain
    filter(domain == name)
  ,
  # P values
  retest_cor_pval %>% 
    select(-quest) %>% # remove questionnaires
    rownames_to_column(var = "quest") %>%  #add real questionnaires
    separate(., col = "quest", into = c("quest","domain","sum", "time")) %>%#rename and separate
    filter(time == "x") %>% 
    select(-sum, -time) %>% 
    select(quest, domain, ends_with("y")) %>% #select everything
    pivot_longer(-c("quest","domain"))%>%  #to match
    mutate(name =str_extract_all(name, "\\w+(?=_)", simplify = T)) %>% #filter same domain
    filter(domain == name) %>% 
    rename(pval=value) %>% mutate(pval = round(pval,3))
) %>% 
 mutate_at(vars(domain, name), ~str_replace(., "c","Communication") %>% 
             str_replace_all(., "gm","Gross Motor") %>% 
             str_replace_all(., "Communicationg","Problem Solving") %>% #gambiarra
             str_replace_all(., "ps","Personal-Social") %>% 
             str_replace_all(., "fm","Fine Motor"))
  

left_join(test_rest_table,  
ds_retest_analysis %>% 
  count(quest) %>% mutate(quest=as.character(quest)))
ds_retest_analysis %>% 
  filter(quest == 4) %>% 
  {cor.test(.$c_sum.x, .$c_sum.y)}
ds_retest_analysis %>% 
  filter(quest == 16) %>% 
  {cor.test(.$fm_sum.x, .$fm_sum.y)}

17.3 Retest summary

test_rest_table %>% 
  filter(pval <= 0.05) %>% 
  tableby(domain~value, data = .) %>% 
  summary()

17.4 Graph

test_rest_table %>% 
  mutate(quest=  as.numeric(quest)) %>% 
  filter(pval <= 0.05) %>% 
  ggplot(aes(x = quest, y = value)) +
  geom_point(aes(color = domain), alpha = 0.5, show.legend = FALSE) +
  #geom_smooth(method = "lm", color = "darkgray", se = FALSE) +
  facet_wrap(. ~ domain, ncol = 2) +
  labs(x="", y = "r") +
  ylim(0,1)+
  theme_bw()

18 Interobs

19 Test-Retest reliability

ds_rater_analysis 
ds_rater_analysis %>%
  select_if(is.numeric) %>%
  group_by(quest) %>%
  nest() %>%
  mutate(
    correlations = map(data, corrr::correlate)
  ) %>%
  unnest(correlations)

19.1 Grouped corr

ds_rater_analysis %>% 
  count(quest)
# pearson correlation
rater_cor <- ds_rater_analysis %>% 
  split(list(.$quest)) %>% 
  keep(~nrow(.) > 4) %>% 
  map(~Hmisc::rcorr(as.matrix(.))$r) 
# create a column with questionnaire

rater_cor <- do.call(rbind.data.frame, rater_cor)

# P vaues of pearson correlation
rater_cor_pval <- ds_rater_analysis %>% 
  split(list(.$quest)) %>% 
  keep(~nrow(.) > 4) %>% 
  map(~Hmisc::rcorr(as.matrix(.))$P)
# create a column with questionnaire
rater_cor_pval <- do.call(rbind.data.frame, rater_cor_pval)

19.2 Table

rater_table <- left_join(
  # R COEF
  rater_cor %>% 
    select(-quest) %>% # remove questionnaires
    rownames_to_column(var = "quest") %>%  #add real questionnaires
    separate(., col = "quest", into = c("quest","domain","sum", "time")) %>%#rename and separate
    filter(time == "x") %>% 
    select(-sum, -time) %>% 
    select(quest, domain, ends_with("y")) %>% #select everything
    pivot_longer(-c("quest","domain")) %>%  #to match
    mutate(name =str_extract_all(name, "\\w+(?=_)", simplify = T)) %>% #filter same domain
    filter(domain == name)
  ,
  # P values
  rater_cor_pval %>% 
    select(-quest) %>% # remove questionnaires
    rownames_to_column(var = "quest") %>%  #add real questionnaires
    separate(., col = "quest", into = c("quest","domain","sum", "time")) %>%#rename and separate
    filter(time == "x") %>% 
    select(-sum, -time) %>% 
    select(quest, domain, ends_with("y")) %>% #select everything
    pivot_longer(-c("quest","domain"))%>%  #to match
    mutate(name =str_extract_all(name, "\\w+(?=_)", simplify = T)) %>% #filter same domain
    filter(domain == name) %>% 
    rename(pval=value) %>% mutate(pval = round(pval,3))
) %>% 
 mutate_at(vars(domain, name), ~str_replace(., "c","Communication") %>% 
             str_replace_all(., "gm","Gross Motor") %>% 
             str_replace_all(., "Communicationg","Problem Solving") %>% #gambiarra
             str_replace_all(., "ps","Personal-Social") %>% 
             str_replace_all(., "fm","Fine Motor"))
  

left_join(rater_table,  
ds_rater_analysis %>% 
  count(quest) %>% mutate(quest=as.character(quest))) %>% write.csv(., "icc.csv")
ds_rater_analysis %>% 
  filter(quest == 72) %>% 
  {cor.test(.$gm_sum.x, .$gm_sum.y)}
ds_rater_analysis %>% 
  filter(quest == 16) %>% 
  {cor.test(.$fm_sum.x, .$fm_sum.y)}

19.3 Rater summary

rater_table %>% 
  filter(pval <= 0.05) %>% 
  tableby(domain~value, data = .) %>% 
  summary()

19.4 Graph

rater_table %>% 
  mutate(quest=  as.numeric(quest)) %>% 
  filter(pval <= 0.05) %>% 
  ggplot(aes(x = quest, y = value)) +
  geom_point(aes(color = domain), alpha = 0.5, show.legend = FALSE) +
  #geom_smooth(method = "lm", color = "darkgray", se = FALSE) +
  facet_wrap(. ~ domain, ncol = 2) +
  labs(x="", y = "r") +
  ylim(0,1)+
  theme_bw()

20 IRT analysis

#mirt(data = ds_com_2[,-c(1:2)], model = 1, itemtype = "graded") %>% 
#  itemplot(., 1)
#https://groups.google.com/g/mirt-package/c/V0AX2aIXS10
plogis(3.119, location = -5)
plogis(3.119)-plogis(1.286)
help(plogis)

20.1 General function

library(mirt)
apply_irt_cfa <- function(data) {
  
  #IRT
  set.seed(123)
  mod_irt <- mirt(data = data, model = 1, itemtype = "graded")
  mod_coef <- coef(mod_irt, IRTpars = T, simplify = T) #get classical IRT parameterization
  mod_fit <- M2(mod_irt,na.rm=TRUE)
  mod_plot_trace <- plot(mod_irt, type = "trace")
  
  #CFA
  library(lavaan)
  mod_cfa <- cfa(model = paste("f1=~", paste(names(data), collapse=" + ")), 
                          data=data, 
                          estimator = 'WLSM', 
                          ordered=names(data)) 

  mod_cfa_result <- summary(mod_cfa, standardized=TRUE, fit.measures = TRUE)  

  #Return
  
  return(list(mod_plot_trace,mod_fit, mod_coef))
}

21 Risk

ds %>% tabyl(summative_risk) %>% adorn_totals("row") %>%
  adorn_pct_formatting(digits = 2)
level_order <- c('Communication', 'Gross Motor', 'Fine Motor',"Problem Solving", "Personal-Social") 
ds %>%
  filter(!is.na(summative_risk)) %>%  #don't use
  filter(quest !=9 & quest != 72) %>% 
  select(quest, summative_risk, c_sum:ps_sum) %>% 
  mutate(summative_risk = as.numeric(as.character(summative_risk))) %>% 
  pivot_longer(cols = -c(quest, summative_risk))%>%
  group_by(quest, name, summative_risk) %>%
  nest() %>% 
  mutate(mean = map_dbl(data, ~mean(.x$value))) %>%  
  mutate(summative_risk = as.factor(summative_risk)) %>% 
  #plot
  mutate(name = case_when(
    name == "c_sum" ~ "Communication",
    name == "gm_sum" ~ "Gross Motor",
    name == "fm_sum" ~ "Fine Motor",
    name == "cg_sum" ~ "Problem Solving",
    name == "ps_sum" ~ "Personal-Social")) %>% 
  ggplot(.,
         aes(x=factor(name, levels = level_order), y=mean, group = summative_risk, fill=summative_risk)) +
  stat_summary(fun.y=mean,position=position_dodge(width=0.95),geom="bar") +
  stat_summary(fun.data=mean_cl_normal,position=position_dodge(0.95),geom="errorbar") + 
  labs(x = "Domain", y = "Mean scores", fill = "Risk") +
  theme_bw()  #+ facet_wrap(~quest)

Nice plot but not used

ds %>%
  filter(!is.na(summative_risk)) %>% 
  filter(quest !=9 & quest != 72) %>% 
  select(quest, summative_risk, c_sum:ps_sum) %>% 
  mutate(summative_risk = as.numeric(as.character(summative_risk))) %>% 
  pivot_longer(cols = -c(quest, summative_risk))%>%
  group_by(quest, name, summative_risk) %>%
  nest() %>% 
  mutate(mean = map_dbl(data, ~mean(.x$value))) %>%  
  mutate(summative_risk = as.factor(summative_risk)) %>% 
  ggplot(.,
         aes(x=quest, y=mean, group = interaction(name ,summative_risk), color=name)) +
  #stat_summary(geom="line", size=1.5, aes(linetype=summative_risk)) +
  stat_summary(fun.y=mean,position=position_dodge(width=0.95),geom="bar", aes(fill = summative_risk)) +
  stat_summary(geom="errorbar", size=0.2, width = .2)

21.1 Plot for report

ds %>%
  filter(!is.na(summative_risk)) %>%  #don`t use missing cases on risk
  filter(summative_risk %in% c(0,3)) %>% #extreme groups (no risk vs high risk)
  mutate(summative_risk = if_else(summative_risk == 0,"Nonrisk","Risk")) %>% 
  select(quest, summative_risk, ends_with("sum"))%>% #get all variables
  pivot_longer(c_sum:ps_sum) %>% #tranform to long format
  mutate(name = case_when(
    name == "c_sum" ~ "Communication",
    name == "gm_sum" ~ "Gross Motor",
    name == "fm_sum" ~ "Fine Motor",
    name == "cg_sum" ~ "Problem Solving",
    name == "ps_sum" ~ "Personal-Social")) %>% 
  #plot
  ggplot(., aes(x = quest, y = value, group = summative_risk)) +
  stat_summary(geom = "line", fun = mean, aes(linetype = summative_risk), size=1) +
  theme_bw() +
  labs(x = "", y = "Mean scores", linetype = "Risk group") +
  facet_wrap(~name) +
  theme(legend.position = "bottom")
#stat_summary(geom="errorbar", size=0.1, width = .2)

21.2 Table with p values

ds %>%
  filter(quest != 9) %>% #no risk here
  filter(!is.na(summative_risk)) %>%  #don`t use missing cases on risk
  filter(summative_risk %in% c(0,3)) %>% #extreme groups (no risk vs high risk)
  mutate(summative_risk = if_else(summative_risk == 0,"Nonrisk","Risk")) %>% 
  select(quest, summative_risk, ends_with("sum"))%>% #get all variables
  pivot_longer(c_sum:ps_sum) %>% 
  nest_by(name,quest) %>% #group!!!
  mutate(model = list(t.test(value ~ summative_risk, data = data, var.equal=T)$p.value)) %>% #compute p values
  unnest(model) %>% 
  #split(.$quest)%>%  #ungroup
  filter(model <= 0.05) %>% 
  pivot_wider(id_cols = quest, names_from = name, values_from = model) %>% #unnest based on p values
  #present
  mutate_if(is.numeric, round, 2) %>% 
  arrange(quest)

21.3 Individual plot if needed

21.3.1 Communication

ds %>% 
  filter(!is.na(summative_risk)) %>% 
    filter(summative_risk %in% c(0,3)) %>% #extreme groups
  mutate(summative_risk = if_else(summative_risk == 0,"Nonrisk","Risk")) %>% 
  ggplot(., aes(x=quest, y = c_sum, linetype=summative_risk, group=summative_risk)) +
  stat_summary(geom = "line", fun = mean, size=1) +
  stat_summary(geom="errorbar", size=0.1, width = .2)+
  theme_bw() +
  labs(x = "", y = "Mean scores", title = "Communication", linetype = "Risk group") +
  theme(legend.position = "bottom")

21.3.2 Gross Motor

ds %>% 
  filter(!is.na(summative_risk)) %>% 
    filter(summative_risk %in% c(0,3)) %>% #extreme groups
  mutate(summative_risk = if_else(summative_risk == 0,"Nonrisk","Risk")) %>% 
  ggplot(., aes(x=quest, y = gm_sum, linetype=summative_risk, group=summative_risk)) + #attention here!!!
  stat_summary(geom = "line", fun = mean, size=1) +
  stat_summary(geom="errorbar", size=0.1, width = .2)+
  theme_bw() +
  labs(x = "", y = "Mean scores", title = "Gross Motor", linetype = "Risk group") +
  theme(legend.position = "bottom")

21.3.3 Fine Motor

ds %>% 
  filter(!is.na(summative_risk)) %>% 
    filter(summative_risk %in% c(0,3)) %>% #extreme groups
  mutate(summative_risk = if_else(summative_risk == 0,"Nonrisk","Risk")) %>% 
  ggplot(., aes(x=quest, y = fm_sum, linetype=summative_risk, group=summative_risk)) + ## Fine motor!!
  stat_summary(geom = "line", fun = mean, size=1) +
  stat_summary(geom="errorbar", size=0.1, width = .2)+
  theme_bw() +
  labs(x = "", y = "Mean scores", title = "Fine Motor", linetype = "Risk group") +
  theme(legend.position = "bottom")

21.3.4 Problem Solving

ds %>% 
  filter(!is.na(summative_risk)) %>% 
    filter(summative_risk %in% c(0,3)) %>% #extreme groups
  mutate(summative_risk = if_else(summative_risk == 0,"Nonrisk","Risk")) %>% 
  ggplot(., aes(x=quest, y = cg_sum, linetype=summative_risk, group=summative_risk)) + ## Problem Solving = Cognition
  stat_summary(geom = "line", fun = mean, size=1) +
  stat_summary(geom="errorbar", size=0.1, width = .2)+
  theme_bw() +
  labs(x = "", y = "Mean scores", title = "Problem Solving", linetype = "Risk group") +
  theme(legend.position = "bottom")

21.3.5 Personal-Social

ds %>% 
  filter(!is.na(summative_risk)) %>% 
    filter(summative_risk %in% c(0,3)) %>% #extreme groups
  mutate(summative_risk = if_else(summative_risk == 0,"Nonrisk","Risk")) %>% 
  ggplot(., aes(x=quest, y = ps_sum, linetype=summative_risk, group=summative_risk)) + ## Personal-Social
  stat_summary(geom = "line", fun = mean, size=1) +
  stat_summary(geom="errorbar", size=0.1, width = .2)+
  theme_bw() +
  labs(x = "", y = "Mean scores", title = "Personal-Social", linetype = "Risk group") +
  theme(legend.position = "bottom")

21.4 At risk descriptive

ds %>% 
  filter(!is.na(summative_risk)) %>% 
  select(quest, summative_risk, c_sum:ps_sum) %>% 
  pivot_longer(c_sum:ps_sum) %>% 
  group_by(quest,summative_risk,name) %>%
  summarise(mean=mean(value, na.rm=T), sd = sd(value, na.rm = T)) %>% 
  #first level
  pivot_wider(id_cols = quest, names_from = summative_risk:name, values_from = mean:sd,  names_glue = "{name}_{summative_risk}_{.value}") %>% 
  #second level
  pivot_longer(cols = -c(quest)) %>% 
  arrange(quest,name) %>% 
  separate(name, into = c("domain","constant","risk","result")) %>% 
  #third level
  select(-constant) %>% 
  pivot_wider(id_cols = quest, names_from = domain:result, values_from = value) %>% 
  mutate_if(is.numeric, round, 2) 

21.5 At Risk T-Test

ds %>% 
    filter(!is.na(summative_risk)) %>% 
  filter(summative_risk %in% c(0,3)) %>% #contrasting groups T TEST HERE
  filter(quest !=9) %>% 
  select(quest, summative_risk, c_sum:ps_sum) %>% 
  pivot_longer(c_sum:ps_sum) %>% 
  group_by(quest,name) %>% 
  nest() %>% 
  mutate(p_risk = map(data, ~aov(value ~ summative_risk, data = .) %>% {summary(.)[[1]][["Pr(>F)"]][1]})) %>% 
  unnest_wider(p_risk) %>% 
  rename(p_val = "...1") %>% 
  pivot_wider(id_cols = quest, names_from = name, values_from = p_val) %>% 
  mutate_if(is.numeric, round, 3)
ds %>% 
filter(quest == 2) %>% 
  filter(summative_risk %in% c(0,3)) %>% 
  t.test(c_sum ~ summative_risk, data = ., var.equal=T)
  #aov(c_sum ~ summative_risk, data = .) %>% summary()
library(ggpubr)
ds %>% 
    filter(!is.na(summative_risk)) %>% 
  filter(quest != "9") %>% 
  filter(summative_risk %in% c(0,3)) %>% #extreme groups
  mutate(summative_risk = if_else(summative_risk == 0,"Nonrisk","Risk")) %>% 
  select(quest, summative_risk, c_sum)%>% 
  ggboxplot(., x = "summative_risk", y = "c_sum",
            facet.by = "quest", short.panel.labs = FALSE) +
  stat_compare_means(label = "p.format", method = "t.test",label.x = c("Risk"), label.y = 1.5)

22 DS for IRT and CFA analysis

22.1 General model

mod_cfa <- 'com =~ com_a4_1 + com_a4_2 + com_a4_3 + com_a4_4 + com_a4_5 + com_a4_6
gross =~  gm_a4_1 + gm_a4_2 + gm_a4_3 + gm_a4_4 + gm_a4_5 + gm_a4_6
fine =~ fm_a4_1 + fm_a4_2 + fm_a4_3 + fm_a4_4 + fm_a4_5 + fm_a4_6
cog =~ cg_a4_1 + cg_a4_2 + cg_a4_3 + cg_a4_4 + cg_a4_5 + cg_a4_6
ps =~ ps_a4_1 + ps_a4_2 + ps_a4_3 + ps_a4_4 + ps_a4_5 + ps_a4_6
'
mod_cfa_asq3 <- 'com =~ com_a3_1 + com_a3_2 + com_a3_3 + com_a3_4 + com_a3_5 + com_a3_6
gross =~  gm_a3_1 + gm_a3_2 + gm_a3_3 + gm_a3_4 + gm_a3_5 + gm_a3_6
fine =~ fm_a3_1 + fm_a3_2 + fm_a3_3 + fm_a3_4 + fm_a3_5 + fm_a3_6
cog =~ cg_a3_1 + cg_a3_2 + cg_a3_3 + cg_a3_4 + cg_a3_5 + cg_a3_6
ps =~ ps_a3_1 + ps_a3_2 + ps_a3_3 + ps_a3_4 + ps_a3_5 + ps_a3_6
'

22.2 2-months

Dataset

ds_2_full <- ds %>% 
  filter(quest == 2) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

ds_2_full %>% mutate_all(replace_na,-99)%>% 
  write.table(., file="ds_2_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_2 <- cfa(model = mod_cfa, 
                          data=ds_2_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_2_full))

CFA results

summary(mod_cfa_2, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_2, what = "est")$psi)
cfa(model = mod_cfa_asq3, 
    data = 
      ds_final_merged %>% 
      filter(quest == 2) %>% 
      select(
        com_a3_1, com_a3_2, com_a3_3, com_a3_4, com_a3_5, com_a3_6,
        gm_a3_1, gm_a3_2, gm_a3_3, gm_a3_4, gm_a3_5, gm_a3_6,
        fm_a3_1, fm_a3_2, fm_a3_3, fm_a3_4, fm_a3_5, fm_a3_6,
        cg_a3_1, cg_a3_2, cg_a3_3, cg_a3_4, cg_a3_5, cg_a3_6,
        ps_a3_1, ps_a3_2, ps_a3_3, ps_a3_4, ps_a3_5, ps_a3_6)
      ,
    estimator = 'WLSM',
    ordered=names(
      ds_final_merged %>% 
      filter(quest == 2) %>% 
      select(
        com_a3_1, com_a3_2, com_a3_3, com_a3_4, com_a3_5, com_a3_6,
        gm_a3_1, gm_a3_2, gm_a3_3, gm_a3_4, gm_a3_5, gm_a3_6,
        fm_a3_1, fm_a3_2, fm_a3_3, fm_a3_4, fm_a3_5, fm_a3_6,
        cg_a3_1, cg_a3_2, cg_a3_3, cg_a3_4, cg_a3_5, cg_a3_6,
        ps_a3_1, ps_a3_2, ps_a3_3, ps_a3_4, ps_a3_5, ps_a3_6)
    )) %>% summary(., standardized=TRUE, fit.measures = TRUE)

22.3 4-months

Dataset

ds_4_full <- ds %>% #attention here to specify the correct dataset 
  filter(quest == 4) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_4_full, file="ds_4_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_4 <- cfa(model = mod_cfa, 
                          data=ds_4_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_4_full))

CFA results

summary(mod_cfa_4, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_4, what = "est")$psi)

22.4 6-months

Dataset

ds_6_full <- ds %>% 
  filter(quest == 6) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_6_full, file="ds_6_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_6 <- cfa(model = mod_cfa, 
                          data=ds_6_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_6_full))

CFA results

summary(mod_cfa_6, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_6, what = "est")$psi)

22.5 8-months

Dataset

ds_8_full <- ds %>% 
  filter(quest == 8) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)
#write.table(ds_8_full, file="ds_8_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_8 <- cfa(model = mod_cfa, 
                          data=ds_8_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_8_full))

CFA results

summary(mod_cfa_8, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_8, what = "est")$psi)

22.6 10-months

Dataset

ds_10_full <- ds %>% 
  filter(quest == 10) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_10_full, file="ds_10_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_10 <- cfa(model = mod_cfa, 
                          data=ds_10_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_10_full))

CFA results

summary(mod_cfa_10, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_10, what = "est")$psi)

22.7 12-months

Dataset

ds_12_full <- ds %>% 
  filter(quest == 12) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_12_full, file="ds_12_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_12 <- cfa(model = mod_cfa, 
                          data=ds_12_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_12_full))

CFA results

summary(mod_cfa_12, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_12, what = "est")$psi)

22.8 14-months

Dataset

ds_14_full <- ds %>% 
  filter(quest == 14) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_14_full, file="ds_14_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_14 <- cfa(model = mod_cfa, 
                          data=ds_14_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_14_full))

CFA results

summary(mod_cfa_14, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_14, what = "est")$psi)

22.9 16-months

Dataset

ds_16_full <- ds %>% 
  filter(quest == 16) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_16_full, file="ds_16_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_16 <- cfa(model = mod_cfa, 
                          data=ds_16_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_16_full))

CFA results

summary(mod_cfa_16, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_16, what = "est")$psi)

22.10 18-months

Dataset

ds_18_full <- ds %>% 
  filter(quest == 18) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_18_full, file="ds_18_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_18 <- cfa(model = mod_cfa, 
                          data=ds_18_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_18_full))

CFA results

summary(mod_cfa_18, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_18, what = "est")$psi)

22.11 20-months

Dataset

ds_20_full <- ds %>% 
  filter(quest == 20) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_20_full, file="ds_20_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_20 <- cfa(model = mod_cfa, 
                          data=ds_20_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_20_full))

CFA results

summary(mod_cfa_20, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_20, what = "est")$psi)

22.12 22-months

Dataset

ds_22_full <- ds %>% 
  filter(quest == 22) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_22_full, file="ds_22_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_22 <- cfa(model = mod_cfa, 
                          data=ds_22_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_22_full))

CFA results

summary(mod_cfa_22, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_22, what = "est")$psi)

22.13 24-months

Dataset

ds_24_full <- ds %>% 
  filter(quest == 24) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_24_full, file="ds_24_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_24 <- cfa(model = mod_cfa, 
                          data=ds_24_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_24_full))

CFA results

summary(mod_cfa_24, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_24, what = "est")$psi)

22.14 27-months

Dataset

ds_27_full <- ds %>% 
  filter(quest == 27) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_27_full, file="ds_27_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_27 <- cfa(model = mod_cfa, 
                          data=ds_27_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_27_full))

CFA results

summary(mod_cfa_27, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_27, what = "est")$psi)

22.15 30-months

Dataset

ds_30_full <- ds %>% 
  filter(quest == 30) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_30_full, file="ds_33_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_30 <- cfa(model = mod_cfa, 
                          data=ds_30_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_30_full))

CFA results

summary(mod_cfa_30, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_30, what = "est")$psi)

22.16 33-months

Dataset

ds_33_full <- ds %>% 
  filter(quest == 33) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_33_full, file="ds_33_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_33 <- cfa(model = mod_cfa, 
                          data=ds_33_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_33_full))

CFA results

summary(mod_cfa_33, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_33, what = "est")$psi)

22.17 36-months

Dataset

ds_36_full <- ds %>% 
  filter(quest == 36) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_36_full, file="ds_36_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_36 <- cfa(model = mod_cfa, 
                          data=ds_36_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_36_full))

CFA results

summary(mod_cfa_36, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_36, what = "est")$psi)

22.18 42-months

Dataset

ds_42_full <- ds %>% 
  filter(quest == 42) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_42_full, file="ds_42_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_42 <- cfa(model = mod_cfa, 
                          data=ds_42_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_42_full))

CFA results

summary(mod_cfa_42, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_42, what = "est")$psi)

22.19 48-months

Dataset

ds_48_full <- ds %>% 
  filter(quest == 48) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_48_full, file="ds_48_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_48 <- cfa(model = mod_cfa, 
                          data=ds_48_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_48_full))

CFA results

summary(mod_cfa_48, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_48, what = "est")$psi)

22.20 54-months

Dataset

ds_54_full <- ds %>% 
  filter(quest == 54) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_54_full, file="ds_54_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_54 <- cfa(model = mod_cfa, 
                          data=ds_54_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_54_full))

CFA results

summary(mod_cfa_54, standardized=TRUE, fit.measures = TRUE)  

Correlations

cov2cor(inspect(mod_cfa_54, what = "est")$psi)

22.21 60-months

Dataset

ds_60_full <- ds %>% 
  filter(quest == 60) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_60_full, file="ds_60_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   

CFA model

mod_cfa_60 <- cfa(model = mod_cfa, 
                          data=ds_60_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_60_full))

CFA results

summary(mod_cfa_60, standardized=TRUE, fit.measures = TRUE)  

Correlation s

cov2cor(inspect(mod_cfa_60, what = "est")$psi)

22.22 72 months

ds_72_full <- ds %>% 
  filter(quest == 72) %>% 
  select(
  com_a4_1, com_a4_2, com_a4_3, com_a4_4, com_a4_5, com_a4_6,
  gm_a4_1, gm_a4_2, gm_a4_3, gm_a4_4, gm_a4_5, gm_a4_6,
  fm_a4_1, fm_a4_2, fm_a4_3, fm_a4_4, fm_a4_5, fm_a4_6,
  cg_a4_1, cg_a4_2, cg_a4_3, cg_a4_4, cg_a4_5, cg_a4_6,
  ps_a4_1, ps_a4_2, ps_a4_3, ps_a4_4, ps_a4_5, ps_a4_6)

#write.table(ds_72_full, file="ds_72_full.dat", row.names=FALSE, col.names=FALSE, sep="\t", quote=FALSE)   
mod_cfa_72 <- cfa(model = mod_cfa, 
                          data=ds_72_full, 
                          estimator = 'WLSM', 
                          ordered=names(ds_72_full))
summary(mod_cfa_72, standardized=TRUE, fit.measures = TRUE)  
cov2cor(inspect(mod_cfa_72, what = "est")$psi)

22.23 Communication

set.seed(123)
ds_1 %>%
  select(quest,id,com_a4_1:com_a4_6) %>% 
  group_split(quest) %>% 
  map(. %>%   
  sample_n(500)) -> x
for (i in 1:length(x)) {
  assign(paste0("ds_com_", unique(x[[i]][1])), as.data.frame(x[[i]]))
}

22.23.0.1 2 months

apply_irt_cfa(ds_com_2[,-c(1:2)])
ds_final_merged %>% 
  filter(quest == 2) %>% 
  select(
  com_a3_1, com_a3_2, com_a3_3, com_a3_4, com_a3_5, com_a3_6,
  gm_a3_1, gm_a3_2, gm_a3_3, gm_a3_4, gm_a3_5, gm_a3_6,
  fm_a3_1, fm_a3_2, fm_a3_3, fm_a3_4, fm_a3_5, fm_a3_6,
  cg_a3_1, cg_a3_2, cg_a3_3, cg_a3_4, cg_a3_5, cg_a3_6,
  ps_a3_1, ps_a3_2, ps_a3_3, ps_a3_4, ps_a3_5, ps_a3_6) %>% 
  apply_irt_cfa(.)

22.23.0.2 4 months

apply_irt_cfa(ds_com_4[,-c(1:2)])

22.23.0.3 6 months

apply_irt_cfa(ds_com_6[,-c(1:2)])

22.23.0.4 8 months

apply_irt_cfa(ds_com_8[,-c(1:2)])

22.23.0.5 10 months

apply_irt_cfa(ds_com_10[,-c(1:2)])

22.23.0.6 12 months

apply_irt_cfa(ds_com_12[,-c(1:2)])

22.23.0.7 14 months

apply_irt_cfa(ds_com_14[,-c(1:2)])

22.23.0.8 16 months

apply_irt_cfa(ds_com_16[,-c(1:2)])

22.23.0.9 18 months

apply_irt_cfa(ds_com_18[,-c(1:2)])

22.23.0.10 20 months

apply_irt_cfa(ds_com_20[,-c(1:2)])

22.23.0.11 22 months

apply_irt_cfa(ds_com_22[,-c(1:2)])

22.23.0.12 24 months

apply_irt_cfa(ds_com_24[,-c(1:2)])

22.23.0.13 27 months

apply_irt_cfa(ds_com_27[,-c(1:2)])

22.23.0.14 30 months

apply_irt_cfa(ds_com_30[,-c(1:2)])

22.23.0.15 33 months

apply_irt_cfa(ds_com_33[,-c(1:2)])

22.23.0.16 36 months

apply_irt_cfa(ds_com_36[,-c(1:2)])

22.23.0.17 42 months

apply_irt_cfa(ds_com_42[,-c(1:2)])

22.23.0.18 48 months

apply_irt_cfa(ds_com_48[,-c(1:2)])

22.23.0.19 54 months

apply_irt_cfa(ds_com_54[,-c(1:2)])

22.23.0.20 60 months

apply_irt_cfa(ds_com_60[,-c(1:2)])

22.23.0.21 72 months

apply_irt_cfa(ds_com_72[,-c(1:2)])

23 ASQ3-ASQ4 comparison

ds_1 %>% names
LS0tDQp0aXRsZTogIkFTUSA0IC0gRGF0YSBhbmFseXNpcyINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtZTogdW5pdGVkDQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQogIG1hcmtkb3duOiANCiAgICB3cmFwOiA3Mg0KLS0tDQoNCjxkaXYgY2xhc3M9ImFsZXJ0IGFsZXJ0LWluZm8iPg0KDQpJZiB5b3UgaGF2ZSBhbnkgcXVlc3Rpb25zIG9yIHF1ZXJpZXMsIHBsZWFzZSByZWFjaCBtZSBvdXQgYXQgbHVpc2ZjYUBwdWMtcmlvLmJyDQoNCmxhc3QgdXBkYXRlZDogYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWANCjwvZGl2Pg0KDQpgYGB7cn0NCnBhY21hbjo6cF9sb2FkKHRpZHl2ZXJzZSwgamFuaXRvciwgYXJzZW5hbCwgRFQsIERhdGFFeHBsb3JlcixzdW1tYXJ5dG9vbHMsIHBzeWNoLCBsYXZhYW4sIG1pcnQpDQpgYGANCg0KDQpgYGB7cn0NCmxvYWQoIkM6L1VzZXJzL2x1aXNmL0Ryb3Bib3gvUHVjLVJpby9Qcm9qZXRvIC0gQVNRIDQgMjAyMS9CYXNlIC0gQVNRIDQuUkRhdGEiKQ0KYGBgDQoNCg0KIyBDb21wYXJlIEFTUS0zIGFuZCBBU1EtNA0KDQpEYXRhIG5hbWU6IGRhdGFfZmluYWxfbWVyZ2VkDQoNCiMjIERlc2NyaXB0aXZlcw0KDQpgYGB7cn0NCmRzX2ZpbmFsX21lcmdlZCAlPiUgDQogIG11dGF0ZShyYWNlID0gY2FzZV93aGVuKA0KICAgIHJhY2UgPT0gMiB+ICJXaGl0ZSIsDQogICAgcmFjZSA9PSA1IH4gIkJsYWNrIC8gQWZyaWNhbiBBbWVyaWNhIiwNCiAgICBUUlVFIH4gIk90aGVyIHJhY2VzIg0KICApLA0KICBnZW5kZXIgPSBpZl9lbHNlKGdlbmRlciA9PSAzLCBOQV9jaGFyYWN0ZXJfLGdlbmRlcikNCiAgKSAgJT4lIA0KICB0YWJsZWJ5KHF1ZXN0fmdlbmRlciArIHJhY2UgKyBhZ2VfOSwNCiAgICAgICAgICBkYXRhID0gLiwgDQogICAgICAgICAgdGVzdD1GQUxTRSkgJT4lIHN1bW1hcnkoKSANCmBgYA0KDQojIyBDcm9uYmFjaCdzIGFscGhhDQoNCmBgYHtyfQ0KZHNfZmluYWxfbWVyZ2VkICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDQpICU+JSANCiAgc2VsZWN0KGNvbV9hM18xLCBjb21fYTNfMiwgY29tX2EzXzMsIGNvbV9hM180LCBjb21fYTNfNSwgY29tX2EzXzYpICU+JSANCiAgYWxwaGEoKQ0KYGBgDQoNCmBgYHtyfQ0KZHNfZmluYWxfbWVyZ2VkICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDQpICU+JSANCiAgc2VsZWN0KGNvbV9hNF8xLCBjb21fYTRfMiwgY29tX2E0XzMsIGNvbV9hNF80LCBjb21fYTRfNSwgY29tX2E0XzYpICU+JSANCiAgYWxwaGEoKQ0KYGBgDQoNCg0KIyMjIEFTUS0zDQoNCmBgYHtyfQ0KY3JvbmJhY2hfYXNxXzMgPC0gZHNfZmluYWxfbWVyZ2VkICU+JSANCiAgc2VsZWN0KHF1ZXN0LCBjb21fYTNfMSwgY29tX2EzXzIsIGNvbV9hM18zLCBjb21fYTNfNCwgY29tX2EzXzUsIGNvbV9hM182LA0KICAgICAgICAgICAgICAgICAgICAgZ21fYTNfMSwJZ21fYTNfMiwJZ21fYTNfMywJZ21fYTNfNCwJZ21fYTNfNSwJZ21fYTNfNiwNCiAgICAgICAgICAgICAgICAgICAgIGZtX2EzXzEsCWZtX2EzXzIsCWZtX2EzXzMsCWZtX2EzXzQsCWZtX2EzXzUsCWZtX2EzXzYsDQogICAgICAgICAgICAgICAgICAgICBjZ19hM18xLAljZ19hM18yLAljZ19hM18zLAljZ19hM180LAljZ19hM181LAljZ19hM182LA0KICAgICAgICAgICAgICAgICAgICAgcHNfYTNfMSwJcHNfYTNfMiwJcHNfYTNfMywJcHNfYTNfNCwJcHNfYTNfNSwJcHNfYTNfNikgJT4lIA0KICAgIHBpdm90X2xvbmdlcihjb2xzID0gLXF1ZXN0LA0KICAgICAgICAgICAgICAgICBuYW1lc190byA9IGMoInNjYWxlIiwgIi52YWx1ZSIpLA0KICAgICAgICAgICAgICAgICBuYW1lc19wYXR0ZXJuID0gIihcXHcrX1xcdytfKSguKSIpICU+JQ0KICAgIG5lc3RfYnkocXVlc3QsIHNjYWxlKSAlPiUNCiAgICBtdXRhdGUoYWxwaGEoZGF0YSkkdG90YWwpDQpgYGANCg0KDQojIyMgQVNRLTQNCg0KYGBge3J9DQpjcm9uYmFjaF9hc3FfNCA8LSBkc19maW5hbF9tZXJnZWQgJT4lIA0KICBzZWxlY3QocXVlc3QsIGNvbV9hNF8xLCBjb21fYTRfMixjb21fYTRfMywgY29tX2E0XzQsIGNvbV9hNF81LCBjb21fYTRfNiwgDQogICAgICAgICBnbV9hNF8xLCBnbV9hNF8yLGdtX2E0XzMsIGdtX2E0XzQsIGdtX2E0XzUsIGdtX2E0XzYsDQogICAgICAgICBmbV9hNF8xLCBmbV9hNF8yLGZtX2E0XzMsIGZtX2E0XzQsIGZtX2E0XzUsIGZtX2E0XzYsIA0KICAgICAgICAgY2dfYTRfMSwgY2dfYTRfMiwgY2dfYTRfMywgY2dfYTRfNCwgY2dfYTRfNSwgY2dfYTRfNiwNCiAgICAgICAgIHBzX2E0XzEsICBwc19hNF8yLCAgcHNfYTRfMywgIHBzX2E0XzQsIHBzX2E0XzUsICBwc19hNF82KSAlPiUgDQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtcXVlc3QsDQogICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gYygic2NhbGUiLCAiLnZhbHVlIiksDQogICAgICAgICAgICAgICAgIG5hbWVzX3BhdHRlcm4gPSAiKFxcdytfXFx3K18pKC4pIikgJT4lDQogICAgbmVzdF9ieShxdWVzdCwgc2NhbGUpICU+JQ0KICAgIG11dGF0ZShhbHBoYShkYXRhKSR0b3RhbCkNCmBgYA0KDQojIyMgRG91YmxlLWNoZWNrDQoNCmBgYHtyfQ0KZHNfZmluYWxfbWVyZ2VkICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDIpICU+JSANCiAgc2VsZWN0KHBzX2E0XzEsCXBzX2E0XzIsCXBzX2E0XzMsCXBzX2E0XzQsCXBzX2E0XzUsCXBzX2E0XzYpICU+JSANCiAgYWxwaGEoLikNCmBgYA0KDQoNCmBgYHtyfQ0KZHNfZmluYWxfbWVyZ2VkICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDgpICU+JSANCiAgc2VsZWN0KHBzX2E0XzEsCXBzX2E0XzIsCXBzX2E0XzMsCXBzX2E0XzQsCXBzX2E0XzUsCXBzX2E0XzYpICU+JSANCiAgYWxwaGEoLikNCmBgYA0KDQpgYGB7cn0NCmRzX2ZpbmFsX21lcmdlZCAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSAxMikgJT4lIA0KICBzZWxlY3QoY29tX2EzXzEsCWNvbV9hM18yLAljb21fYTNfMywJY29tX2EzXzQsIGNvbV9hM181LAljb21fYTNfNikgJT4lIA0KICBhbHBoYSguKQ0KYGBgDQoNCg0KIyMjIFRhYmxlDQoNCmBgYHtyfQ0KY3JvbmJhY2hfYXNxXzQgJT4lIA0KICBncm91cF9ieShxdWVzdCwgc2NhbGUpICU+JSANCiAgc3VtbWFyaXNlKGFscGhhPW1lYW4ocmF3X2FscGhhKSwgY29yPWF2ZXJhZ2VfcikNCg0KYGBgDQoNCiMjIyBBcHByZW5kaXggQVNRNCAmIEFTUTMNCg0KYGBge3J9DQpsZWZ0X2pvaW4oICNqdXN0IHRvIGFkZCBzYW1wbGUgc2l6ZQ0KICAgDQpiaW5kX2NvbHMoDQogIGNyb25iYWNoX2FzcV8zICU+JSANCiAgICBzZWxlY3QocXVlc3QsIHNjYWxlLCByYXdfYWxwaGEsIGF2ZXJhZ2VfciksICNnZXQgcmVzdWx0cyBvZiBhc3EzDQogIA0KICBjcm9uYmFjaF9hc3FfNCAlPiUgDQogICAgc2VsZWN0KHF1ZXN0LCBzY2FsZSwgcmF3X2FscGhhLCBhdmVyYWdlX3IpICNnZXQgcmVzdWx0cyBvZiBhc3E0DQogICkgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkgJT4lICN0cmFuc2Zvcm0gaW50byBkYXRhZnJhbWUNCiAgamFuaXRvcjo6Y2xlYW5fbmFtZXMoKSAlPiUNCiAgcmVuYW1lKGFzcTMgPSByYXdfYWxwaGFfMywgDQogICAgICAgICBhc3E0ID0gcmF3X2FscGhhXzcsDQogICAgICAgICBjb3IzID0gYXZlcmFnZV9yXzQsDQogICAgICAgICBjb3I0ID0gYXZlcmFnZV9yXzgpICU+JSAjcmVuYW1lIHRvIG1ha2UgZWFzaWVyDQogIHNlbGVjdCgtc2NhbGVfNiwgLXF1ZXN0XzUpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtYyhxdWVzdF8xLCBzY2FsZV8yKSkgJT4lICAjdHJhbnNwb3NlDQogIG11dGF0ZShuYW1lID0gY2FzZV93aGVuKA0KICAgIG5hbWUgPT0gImFzcTMiIH4gImFscGhhXzMiLA0KICAgIG5hbWUgPT0gImNvcjMiIH4gImNvcl8zIiwNCiAgICBuYW1lID09ICJhc3E0IiB+ICJhbHBoYV80IiwNCiAgICBuYW1lID09ICJjb3I0IiB+ICJjb3JfNCIpKSAlPiUgI3JlbmFtZSB0byBtYWtlIGVhc2llcg0KICBtdXRhdGUoc2NhbGVfMiA9IGNhc2Vfd2hlbigNCiAgICBzY2FsZV8yID09ICJjb21fYTNfIiB+ICJDb21tdW5pY2F0aW9uIiwNCiAgICBzY2FsZV8yID09ICJnbV9hM18iIH4gIkdyb3NzIE1vdG9yIiwNCiAgICBzY2FsZV8yID09ICJmbV9hM18iIH4gIkZpbmUgTW90b3IiLA0KICAgIHNjYWxlXzIgPT0gImNnX2EzXyIgfiAiUHJvYmxlbSBTb2x2aW5nIiwNCiAgICBzY2FsZV8yID09ICJwc19hM18iIH4gIlBlcnNvbmFsLVNvY2lhbCIpKSAlPiUgDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBuYW1lLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKSNpbnZlcnNlIHRyYW5wb3NlIA0KICAjcGl2b3Rfd2lkZXIobmFtZSwgc2NhbGVfMiwgdmFsdWVzX2ZuID0gbWVhbikNCiwNCg0KZHNfZmluYWxfbWVyZ2VkICU+JSBjb3VudChxdWVzdCkgJT4lIHJlbmFtZShxdWVzdF8xPXF1ZXN0KSAjcmVuYW1lIHRvIG1ha2UgZWFzaWVyDQopICU+JSANCiAgc2VsZWN0KHF1ZXN0XzEsIHNjYWxlXzIsIGFscGhhXzMsIGFscGhhXzQsIGNvcl8zLCBjb3JfNCkgJT4lICNvcmRlcg0KICBtdXRhdGUoZGVsdGFfcGVyY2VudCA9IChhbHBoYV80LWFscGhhXzMpL2FscGhhXzMqMTAwKSAlPiUgDQogIG11dGF0ZV9pZihpcy5udW1lcmljLCByb3VuZCwgMikgJT4lICNyb3VuZA0KICBhcnJhbmdlKGRlc2MoZGVsdGFfcGVyY2VudCkpDQpgYGANCg0KIyMjIEdyYXBoDQoNCmBgYHtyfQ0KYmluZF9jb2xzKA0KICBjcm9uYmFjaF9hc3FfMyAlPiUgDQogICAgc2VsZWN0KHF1ZXN0LCBzY2FsZSwgcmF3X2FscGhhKSwNCiAgDQogIGNyb25iYWNoX2FzcV80ICU+JSANCiAgICBzZWxlY3QocXVlc3QsIHNjYWxlLCByYXdfYWxwaGEpKSAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogIGphbml0b3I6OmNsZWFuX25hbWVzKCkgJT4lDQogIHJlbmFtZShhc3EzID0gcmF3X2FscGhhXzMsIA0KICAgICAgICAgYXNxNCA9IHJhd19hbHBoYV82KSAlPiUgDQogIHNlbGVjdCgtc2NhbGVfNSwgLXF1ZXN0XzQpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtYyhxdWVzdF8xLCBzY2FsZV8yKSklPiUNCiAgbXV0YXRlKHNjYWxlXzIgPSBjYXNlX3doZW4oDQogICAgc2NhbGVfMiA9PSAiY29tX2EzXyIgfiAiQ29tbXVuaWNhdGlvbiIsDQogICAgc2NhbGVfMiA9PSAiZ21fYTNfIiB+ICJHcm9zcyBNb3RvciIsDQogICAgc2NhbGVfMiA9PSAiZm1fYTNfIiB+ICJGaW5lIE1vdG9yIiwNCiAgICBzY2FsZV8yID09ICJjZ19hM18iIH4gIlByb2JsZW0gU29sdmluZyIsDQogICAgc2NhbGVfMiA9PSAicHNfYTNfIiB+ICJQZXJzb25hbC1Tb2NpYWwiKSkgJT4lIA0KICBnZ3Bsb3QoLiwgYWVzKHg9ZmFjdG9yKHNjYWxlXzIsIGxldmVsID0gYygnQ29tbXVuaWNhdGlvbicsICdHcm9zcyBNb3RvcicsICdGaW5lIE1vdG9yJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlByb2JsZW0gU29sdmluZyIsICJQZXJzb25hbC1Tb2NpYWwiKSksIHkgPSB2YWx1ZSwgZmlsbCA9IG5hbWUpKSArDQogIGdlb21fY29sKHN0YXQgPSAic3VtbWFyeSIsIHBvc2l0aW9uPSJkb2RnZSIpICsNCiAgZmFjZXRfd3JhcCh+cXVlc3RfMSkgKw0KICAgIHRoZW1lX2J3KCkgKw0KICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpKSArDQogIGxhYnMoeCA9ICJEb21haW4iLCB5ID0gIlF1ZXN0aW9ubmFpcmUiKQ0KDQpgYGANCg0KDQojIyBSZWxpYWJpbGl0eSBsb3NzDQoNCkFTUS00IA0KYGBge3J9DQpkc19maW5hbF9tZXJnZWQgJT4lIA0KICBmaWx0ZXIocXVlc3Q9PTkpICU+JSANCiAgc2VsZWN0KHBzX2E0XzEscHNfYTRfMixwc19hNF8zLHBzX2E0XzQscHNfYTRfNSxwc19hNF82KSAlPiUgDQogIGFscGhhKCkgDQpgYGANCg0KDQpgYGB7cn0NCmRzX2ZpbmFsX21lcmdlZCAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSA5KSAlPiUgDQogIHtjb3IoLiRwc19hM180LCAuJHBzX2E0XzUpfQ0KYGBgDQpBU1EtMyANCg0KYGBge3J9DQpkc19maW5hbF9tZXJnZWQgJT4lIA0KICBmaWx0ZXIocXVlc3Q9PTkpICU+JSANCiAgc2VsZWN0KHBzX2EzXzEscHNfYTNfMixwc19hM18zLHBzX2EzXzQscHNfYTNfNSxwc19hM182KSAlPiUgDQogIGFscGhhKCkNCmBgYA0KDQoNCiMjIE1lYW5zDQoNCmBgYHtyLCBldmFsID0gRkFMU0UgfQ0KZHNfZmluYWxfbWVyZ2VkICU+JQ0KICBzZWxlY3QocXVlc3QsIGNfc3VtX2EzLCBnbV9zdW1fYTMsIGZtX3N1bV9hMywgY2dfc3VtX2EzLCBwc19zdW1fYTMsDQogICAgICAgICBjX3N1bSwgZ21fc3VtLCBmbV9zdW0sIGNnX3N1bSwgcHNfc3VtKSAlPiUNCiAgZ3JvdXBfYnkocXVlc3QpICU+JSANCiAgc3VtbWFyaXNlKGFjcm9zcyhjb250YWlucygic3VtIiksIA0KICAgICAgICAgICAgICAgICAgIH5tZWFuKC4pKSwNCiAgICAgICAgICAgICAgICAgICBzYW1wbGUgPSBuKCkpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMscm91bmQsMikgJT4lIA0KICBzZWxlY3QocXVlc3QsIHNhbXBsZSwgb3JkZXIoY29sbmFtZXMoLikpKQ0KYGBgDQoNCmBgYHtyfQ0KZHNfZmluYWxfbWVyZ2VkICU+JQ0KICBzZWxlY3QocXVlc3QsIGNfc3VtX2EzLCBnbV9zdW1fYTMsIGZtX3N1bV9hMywgY2dfc3VtX2EzLCBwc19zdW1fYTMsDQogICAgICAgICBjX3N1bSwgZ21fc3VtLCBmbV9zdW0sIGNnX3N1bSwgcHNfc3VtKSAlPiUNCiAgdGFibGVvbmU6OkNyZWF0ZVRhYmxlT25lKHZhcnMgPSAgbmFtZXMoLiksIHN0cmF0YSA9IGMoInF1ZXN0IiksIGRhdGEgPSAuKQ0KICAjZGVzY3JpYmVCeSguLCBncm91cCA9ICJxdWVzdCIpDQpgYGANCg0KIyMgVCB0ZXN0cyBmb3IgbWVhbnMNCg0KYGBge3J9DQpkc19maW5hbF9tZXJnZWQgJT4lDQogICAgc2VsZWN0KHF1ZXN0LCBjb250YWlucygic3VtIikpICU+JSANCiAgICBuZXN0X2J5KHF1ZXN0KSAlPiUNCiAgICBzdW1tYXJpc2UoY2F0ZWcgPSBjb21ibihuYW1lcyhkYXRhKSwgMiwgcGFzdGUsIGNvbGxhcHNlPSItIiksIA0KICAgICAgIHB2YWwgPSBjb21ibihkYXRhLCAyLCBmdW5jdGlvbih4KSANCiAgICAgICAgICB0LnRlc3QoeFtbMV1dLCB4W1syXV0sIHBhaXJlZCA9IFRSVUUpJHAudmFsdWUpLCAuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogIHNlcGFyYXRlKGNhdGVnLCBpbnRvID0gYygiYTMiLCJhNCIpLCBzZXAgPSAiLSIpICU+JSANCiAgbXV0YXRlKHB2YWwgPSByb3VuZChwdmFsLCAyKSkgJT4lIA0KICBtdXRhdGVfYXQodmFycyhhMywgYTQpLCB+c3RyX3JlbW92ZV9hbGwoLiwiX2EzIikpICU+JSANCiAgZmlsdGVyKGEzID09IGE0KSAlPiUgDQogIGZpbHRlcihwdmFsIDwgMC4wNSkgJT4lIA0KICBhcnJhbmdlKHF1ZXN0KQ0KYGBgDQoNCg0KTG9vcGluZyB0aGUgZHMgdG8gcGVyZm9ybSBhbGwgcGFpcndpc2UgY29tcGFyaXNvbnMgDQoNCmBgYHtyfQ0KZHNfZmluYWxfbWVyZ2VkICU+JQ0KICBzZWxlY3QocXVlc3QsIGNvbnRhaW5zKCJzdW0iKSkgJT4lIA0KICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtcXVlc3QpICU+JQ0KICAgZ3JvdXBfYnkocXVlc3QpICU+JSANCiAgIHN1bW1hcmlzZShwb3V0ID0gbGlzdChicm9vbTo6dGlkeShwYWlyd2lzZS50LnRlc3QodmFsdWUsIG5hbWUsIA0KICAgICAgICBwLmFkanVzdC5tZXRob2QgPSAibm9uZSIsIHBhaXJlZCA9IFRSVUUpKSkpICU+JSANCiAgIHVubmVzdChwb3V0KSAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogIG11dGF0ZV9hdCh2YXJzKGdyb3VwMSwgZ3JvdXAyKSwgfnN0cl9yZW1vdmVfYWxsKC4sIl9hMyIpKSAlPiUgDQogIGZpbHRlcihncm91cDEgPT0gZ3JvdXAyKSAlPiUgDQogIGFycmFuZ2UocXVlc3QpICU+JSANCiAgbXV0YXRlKHAudmFsdWUgPSByb3VuZChwLnZhbHVlLDIpKQ0KYGBgDQoNCiMjIERvdWJsZSBjaGVjaw0KDQpgYGB7cn0NCmRzX2ZpbmFsX21lcmdlZCAlPiUgDQogIGZpbHRlcihxdWVzdD09MTYpICU+JSANCiAge3QudGVzdCguJGdtX3N1bSwgLiRnbV9zdW1fYTMsIHBhaXJlZD1ULCBkYXRhID0uKX0NCmBgYA0KDQpgYGB7cn0NCmRzX2ZpbmFsX21lcmdlZCAlPiUgDQogIGZpbHRlcihxdWVzdD09MTIpICU+JSANCiAge3QudGVzdCguJHBzX3N1bSwgLiRwc19zdW1fYTMsIHBhaXJlZD1ULCBkYXRhID0uKX0NCmBgYA0KDQojIyBDb3JyZWxhdGlvbnMNCg0KDQpgYGB7cn0NCmxpYnJhcnkoY29ycmVsYXRpb24pDQpkc19maW5hbF9tZXJnZWQgJT4lIA0KICBncm91cF9ieShxdWVzdCkgJT4lIA0KICBzZWxlY3QocXVlc3QsIGNfc3VtX2EzLCBnbV9zdW1fYTMsIGZtX3N1bV9hMywgY2dfc3VtX2EzLCBwc19zdW1fYTMsDQogICAgICAgICBjX3N1bSwgZ21fc3VtLCBmbV9zdW0sIGNnX3N1bSwgcHNfc3VtKSAlPiUgDQogIGNvcnJlbGF0aW9uKCkgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICBtdXRhdGVfYXQodmFycyhQYXJhbWV0ZXIxLCBQYXJhbWV0ZXIyKSwgfnN0cl9yZW1vdmVfYWxsKC4sIl9hMyIpKSAlPiUgDQogIGZpbHRlcihQYXJhbWV0ZXIxID09IFBhcmFtZXRlcjIpIA0KYGBgDQoNCg0KYGBge3IsIGV2YWwgPSBGQUxTRSB9DQpkc19maW5hbF9tZXJnZWQgJT4lDQogIHNlbGVjdChxdWVzdCwgY19zdW1fYTMsIGdtX3N1bV9hMywgZm1fc3VtX2EzLCBjZ19zdW1fYTMsIHBzX3N1bV9hMywNCiAgICAgICAgIGNfc3VtLCBnbV9zdW0sIGZtX3N1bSwgY2dfc3VtLCBwc19zdW0pICU+JQ0KZ3JvdXBfYnkocXVlc3QpICU+JQ0KICBuZXN0KCkgJT4lDQogIG11dGF0ZSgNCiAgICBjb3JyZWxhdGlvbnMgPSBtYXAoZGF0YSwgY29ycnI6OmNvcnJlbGF0ZSkNCiAgKSAlPiUNCiAgdW5uZXN0KGNvcnJlbGF0aW9ucykgJT4lIA0KICBzZWxlY3QoLWMoY29udGFpbnMoIl9hMyIpKSkgJT4lIA0KICBmaWx0ZXIoc3RyX2RldGVjdCh0ZXJtLCAnYTMnKSkgJT4lIA0KICBzZWxlY3QoLWRhdGEpICU+JSANCiAgcGl2b3RfbG9uZ2VyKC1jKHF1ZXN0LHRlcm0pKSAlPiUgDQogIGZpbHRlcih0ZXJtID09IHBhc3RlMChuYW1lLCJfYTMiKSkgDQoNCmBgYA0KDQoNCiMgQ29tcGFyZSBBU1E0IGRzMSAmIFN1cHBsZW1lbnRhcnkgZGF0YQ0KDQojIyBEZXNjcmlwdGl2ZQ0KDQpgYGB7cn0NCmRzICU+JQ0KICAjZmlsdGVyKGJhc2UgPT0gInN1cCIpICU+JSANCiAgc2VsZWN0KHF1ZXN0LCBiYXNlLA0KICAgICAgICAgY19zdW0sIGdtX3N1bSwgZm1fc3VtLCBjZ19zdW0sIHBzX3N1bSkgJT4lDQogIHRhYmxlYnkoaW50ZXJhY3Rpb24ocXVlc3QsIGJhc2UpIH4gLiwgZGF0YSA9IC4pICU+JSANCiAgc3VtbWFyeSgpDQogICN0YWJsZW9uZTo6Q3JlYXRlVGFibGVPbmUodmFycyA9ICBuYW1lcyguWy0xXSksIHN0cmF0YSA9IGMoInF1ZXN0IiwiYmFzZSIpLCBkYXRhID0gLikgJT4lIA0KICAjcHJpbnQoKQ0KYGBgDQoNCiMjIFBsb3QNCg0KYGBge3J9DQpkcyAlPiUgDQogIHNlbGVjdChxdWVzdCwgYmFzZSwgY19zdW06cHNfc3VtKSAlPiUgDQogIHBpdm90X2xvbmdlcigtYyhxdWVzdCxiYXNlKSkgJT4lDQogICAgbXV0YXRlKG5hbWUgPSBjYXNlX3doZW4oDQogICAgbmFtZSA9PSAiY19zdW0iIH4gIkNvbW11bmljYXRpb24iLA0KICAgIG5hbWUgPT0gImdtX3N1bSIgfiAiR3Jvc3MgTW90b3IiLA0KICAgIG5hbWUgPT0gImZtX3N1bSIgfiAiRmluZSBNb3RvciIsDQogICAgbmFtZSA9PSAiY2dfc3VtIiB+ICJQcm9ibGVtIFNvbHZpbmciLA0KICAgIG5hbWUgPT0gInBzX3N1bSIgfiAiUGVyc29uYWwtU29jaWFsIikpICU+JSANCiAgZ2dwbG90KC4sIGFlcyh4ID0gbmFtZSwgeSA9IHZhbHVlLCBmaWxsID0gYmFzZSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJzdW1tYXJ5IiwgZnVuID0gIm1lYW4iLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgZmFjZXRfd3JhcCh+cXVlc3QpICsNCiAgdGhlbWVfYncoKSArDQogICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSwgc2l6ZT0xMSxmYWNlPSJib2xkIikpDQpgYGANCg0KIyMgVCB0ZXN0IGZvciBtZWFucw0KDQpgYGB7cn0NCmRzICU+JQ0KICBmaWx0ZXIocXVlc3QgIT05ICYgcXVlc3QgIT0gNzIpICU+JSANCiAgc2VsZWN0KHF1ZXN0LCBiYXNlLCBjX3N1bTpwc19zdW0pICU+JSANCiAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtYyhxdWVzdCwgYmFzZSkpICU+JQ0KICBncm91cF9ieShxdWVzdCwgbmFtZSkgICU+JQ0KICBuZXN0KCkgJT4lIA0KICBtdXRhdGUobWVhbjEgPSBtYXBfZGJsKGRhdGEsIH5tZWFuKC54JHZhbHVlWy54JGJhc2UgPT0gImJhc2UxIl0pKSkgJT4lICANCiAgbXV0YXRlKG1lYW4yID0gbWFwX2RibChkYXRhLCB+bWVhbigueCR2YWx1ZVsueCRiYXNlID09ICJzdXAiXSkpKSAlPiUgIA0KICBtdXRhdGUocHZhbCA9IG1hcChkYXRhLCB+dC50ZXN0KC54JHZhbHVlIH4gLngkYmFzZSkkcC52YWx1ZSkpICU+JSANCiAgdW5uZXN0KHB2YWwpICAlPiUgDQogIG11dGF0ZShwdmFsID0gcm91bmQocHZhbCwgMikpICU+JSANCiAgZmlsdGVyKHB2YWwgPiAwLjA1KSAlPiUgDQogIGFycmFuZ2UocXVlc3QpICU+JSANCiAgc2VsZWN0KC1kYXRhKQ0KYGBgDQoNCiMjIEFTUTQgYW5kIEFTUTMgKE1hbnVhbCkNCg0KDQojIyMgR2V0IHRhYmxlDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KYXNxXzNfdGFibGUgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL2x1aXNmL0Rvd25sb2Fkcy9hc3FfM190YWJsZS5jc3YiKQ0KYXNxXzNfdGFibGUgPC0gY2xlYW5fbmFtZXMoYXNxXzNfdGFibGUpDQphc3FfM190YWJsZSA8LSByZW1vdmVfZW1wdHkoYXNxXzNfdGFibGUpDQphc3FfM190YWJsZSA8LSBhc3FfM190YWJsZSAlPiUgbXV0YXRlKHF1ZXN0ID0gYXMuZmFjdG9yKHF1ZXN0KSkNCmFzcV8zX3RhYmxlDQpgYGANCg0KIyMjIENvbXBhcmUgYm90aA0KDQpgYGB7cn0NCmxlZnRfam9pbigNCiAgZHMgJT4lICNnZXQgZHMNCiAgICBzZWxlY3QocXVlc3QsIGVuZHNfd2l0aCgic3VtIikpICU+JSAjc2VsZWN0IHRoZSBmb2N1cyB2YXJpYWJsZXMgDQogICAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lICN0cmFuc3Bvc2UgdG8gbG9uZyBmb3JtYXRhDQogICAgbmVzdF9ieShxdWVzdCwgbmFtZSkgJT4lICNncm91cA0KICAgIG11dGF0ZShtZWFuID0gbGlzdChtYXBfZGJsKGRhdGEsIH5tZWFuKC4pKSksDQogICAgICAgICAgIHNkID0gbGlzdChtYXBfZGJsKGRhdGEsIH5zZCguKSkpLA0KICAgICAgICAgICBtXzFzZCA9IG1lYW4tc2QsDQogICAgICAgICAgIG1fMV9oYWxmX3NkID0gbWVhbi0xLjUqc2QsDQogICAgICAgICAgIG1fMnNkID0gbWVhbi0yKnNkKSAlPiUgDQogICAgdW5uZXN0KC1kYXRhKSAlPiUgI3VubmVzdA0KICAgIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBxdWVzdCwgbmFtZXNfZnJvbSA9IG5hbWUsIHZhbHVlc19mcm9tID0gbWVhbjptXzJzZCkgJT4lIA0KICAgIG11dGF0ZV9pZihpcy5udW1lcmljLCByb3VuZCwgMikgJT4lIA0KICAgIHVuZ3JvdXAoKQ0KICAsDQogIGFzcV8zX3RhYmxlLA0KICBieSA9ICJxdWVzdCIpICU+JSANCiAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lDQogIGFycmFuZ2UocXVlc3QsbmFtZSkgJT4lIA0KICBwaXZvdF93aWRlcihpZF9jb2xzID0gcXVlc3QsIG5hbWVzX2Zyb20gPSBuYW1lLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKSAlPiUNCiAgcmVuYW1lX2FsbCguLH5zdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoLiwgJ3gnLCAnYXNxNCcpKSAlPiUgDQogIHJlbmFtZV9hbGwoLix+c3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKC4sICd5JywgJ2FzcTMnKSkgJT4lIA0KICBzZWxlY3QocXVlc3QsY29udGFpbnMoIm1fMnNkIikpDQpgYGANCg0KIyBBU1EtNCAoTWFudWFsKQ0KDQojIFRhYmxlIFF1ZXN0aW9ubmFpcmVzIGJ5IGFnZSBpbnRlcnZhbCBhbmQgbWV0aG9kIG9mIGNvbXBsZXRpb24NCg0KDQpgYGB7cn0NCmRzICU+JSANCiAgdGFieWwocXVlc3Qsd2Vic2l0ZSkgJT4lIA0KICBhZG9ybl90b3RhbHMod2hlcmUgPSBjKCJyb3ciLCJjb2wiKSkgJT4lIA0KICBhZG9ybl9wZXJjZW50YWdlcyhkZW5vbWluYXRvciA9ICJjb2wiKSAlPiUgDQogIGFkb3JuX3BjdF9mb3JtYXR0aW5nKGRpZ2l0cyA9IDApICU+JSANCiAgYWRvcm5fbnMocG9zaXRpb24gPSAiZnJvbnQiKQ0KDQpgYGANCg0KIyBUYWJsZSBHZW5kZXIgb2YgY2hpbGRyZW4NCg0KYGBge3J9DQpkcyAlPiUgDQogIHRhYmxlYnkoZ2VuZGVyfnF1ZXN0LA0KICAgICAgICAgIGRhdGEgPSAuLCANCiAgICAgICAgICB0ZXN0PUZBTFNFKSAlPiUgc3VtbWFyeSgpDQpgYGANCg0KYGBge3J9DQpkcyAlPiUgY291bnQoZ2VuZGVyKSAlPiUgYWRvcm5fdG90YWxzKCkNCmBgYA0KDQoNCmBgYHtyfQ0KZHMgJT4lIA0KICBncm91cF9ieShxdWVzdCkgJT4lIA0KICBzdW1tYXJpc2UocHZhbCA9IGNoaXNxLnRlc3QodGFibGUoZ2VuZGVyKSkkcC52YWx1ZSkgJT4lIA0KICBhcnJhbmdlKHB2YWwpDQpgYGANCg0KDQoNCiMgVGFibGUgTW9tJ3MgYWdlDQoNCmBgYHtyfQ0KZHMgJT4lIHRhYmxlYnkoYmFzZX5tb21hZ2VfbnVtZXJpYyxkYXRhID0gLikgJT4lIHN1bW1hcnkoKSANCmBgYA0KDQoNCiMgVGFibGUgbW90aGVy4oCZcyBlZHVjYXRpb24NCg0KYGBge3J9DQpkcyAlPiUgDQogIHRhYmxlYnkofm1vbWVkLGRhdGEgPSAuLCB0ZXN0PUZBTFNFKSAlPiUgc3VtbWFyeSgpIA0KIyU+JSB4bHN4Ojp3cml0ZS54bHN4KC4sIGZpbGUgPSAicmF3X3Jlc3VsdHMueGxzeCIsIHNoZWV0TmFtZT0ibW9tZWQiLCBhcHBlbmQ9VFJVRSkNCmBgYA0KDQoNCiMgVGFibGUgRmFtaWx5IGluY29tZSBsZXZlbA0KDQpPbiBEZWMgMjgsIDIwMjENCg0KYGBge3J9DQpkcyAlPiUgDQogIG11dGF0ZShpbmNvbWUgPSBpZmVsc2UoYXMuaW50ZWdlcihpbmNvbWUpPDcsIGluY29tZSxOQSkpICU+JSAgI0kgY2hhbmdlZCB0aGUgb3JkZXIgb2YgaW5jb21lIGluIGRzIHN1cCB0byBjb21wdXRlIHRoZSByaXNrIGZhY3RvciwgYnV0IEkgZGlkIG5vdCBjaGFuZ2VkIHRoaXMgdmFyaWFibGUgYnkgaXRzZWxmDQogIHRhYmxlYnkofmFzLmZhY3RvcihpbmNvbWUpLGRhdGEgPSAuLCB0ZXN0PUZBTFNFKSAlPiUgDQogIHN1bW1hcnkoKSANCmBgYA0KDQoNCiMgVGFibGUgYXQgcmlzaw0KDQpPbiBEZWMgMjgsIDIwMjENCg0KDQpgYGB7cn0NCmRzICU+JSANCiAgdGFibGVieSh+c3VtbWF0aXZlX3Jpc2ssZGF0YSA9IC4sIHRlc3Q9RkFMU0UpICU+JSBzdW1tYXJ5KCkgDQpgYGANCg0KDQpgYGB7cn0NCmRzICU+JSANCiAgc2VsZWN0KHF1ZXN0LHN1bW1hdGl2ZV9yaXNrKSAlPiUgDQogIG11dGF0ZShzdW1tYXRpdmVfcmlza19zdXAgPSBhc19mYWN0b3Ioc3VtbWF0aXZlX3Jpc2spLA0KICAgICAgICAgc3VtbWF0aXZlX3Jpc2tfc3VwID0gZmN0X2luc2VxKHN1bW1hdGl2ZV9yaXNrKSkgJT4lIA0KICB0YWJsZW9uZTo6Q3JlYXRlVGFibGVPbmUodmFycyA9ICJzdW1tYXRpdmVfcmlzayIsIHN0cmF0YSA9ICJxdWVzdCIsIGRhdGEgPSAuKSAlPiUgDQogIHByaW50KC4pICU+JSB0KC4pICU+JSBhcy5kYXRhLmZyYW1lKCkgJT4lIHJvd25hbWVzX3RvX2NvbHVtbigicXVlc3QiKQ0KYGBgDQoNCmBgYHtyfQ0KZHMgJT4lIA0KICBmaWx0ZXIoYmFzZT09ImJhc2UxIikgJT4lIA0KICB7Z21vZGVsczo6Q3Jvc3NUYWJsZSguJGF0cmlzaywgLiRzdW1tYXRpdmVfcmlzaywgY2hpc3EgPSBUKX0gDQpgYGANCg0KDQojIFRhYmxlIFJhY2UNCg0KYGBge3J9DQpkcyAlPiUgDQogIHRhYmxlYnkofnJhY2UsZGF0YSA9IC4sIHRlc3Q9RkFMU0UpICU+JSBzdW1tYXJ5KCkgDQpgYGANCg0KIyBUYWJsZSBEZXNjcmlwdGl2ZQ0KDQpgYGB7cn0NCmRzICU+JSANCiAgZmlsdGVyKCFpcy5uYShxdWVzdCkpICU+JSANCiAgc2VsZWN0KHF1ZXN0LCBlbmRzX3dpdGgoInN1bSIpKSAlPiUgDQogIHRhYmxlYnkocXVlc3QgfiAuLCBjb250cm9sID0gdGFibGVieS5jb250cm9sKG51bWVyaWMuc3RhdHM9YygibWVhbiIsICJzZCIpKSwgZGF0YSA9IC4pICU+JSBzdW1tYXJ5KC4gLCBkaWdpdHMgPSAyKQ0KICAjdGFibGVvbmU6OkNyZWF0ZVRhYmxlT25lKHZhcnMgPSAgbmFtZXMoLiksIHN0cmF0YSA9IGMoInF1ZXN0IiksIGRhdGEgPSAuKSAlPiUgdHJhbnNwb3NlKCkNCiAgI3RhYmxlMTo6dGFibGUxKH4gLnwgcXVlc3QsIA0KICAjICAgICAgICAgICAgICAgdHJhbnNwb3NlID0gVFJVRSwNCiAgIyAgICAgICAgICAgICAgIGRhdGEgPSAuKSANCmBgYA0KDQojIFBsb3QgU2NvcmVzJyBkaXN0cmlidXRpb24NCg0KYGBge3J9DQpkcyAlPiUgDQogIGZpbHRlcighaXMubmEocXVlc3QpKSAlPiUgDQogIHNlbGVjdChxdWVzdCwgZW5kc193aXRoKCJzdW0iKSkgJT4lIA0KICBwaXZvdF9sb25nZXIoLXF1ZXN0KSAlPiUgDQogIG11dGF0ZV9hdCh2YXJzKG5hbWUpLCB+Y2FzZV93aGVuKA0KICAgIC4gPT0gInBzX3N1bSIgfiAiUGVyc29uYWwgJiBTb2NpYWwiLA0KICAgIC4gPT0gImdtX3N1bSIgfiAiR3Jvc3MgbW90b3IiLA0KICAgIC4gPT0gImZtX3N1bSIgfiAiRmluZSBtb3RvciIsDQogICAgLiA9PSAiY19zdW0iIH4gIkNvbW11bmljYXRpb24iLA0KICAgIC4gPT0gImNnX3N1bSIgfiAiUHJvYmxlbSBzb2x2aW5nIiwNCiAgKSkgJT4lIA0KICBnZ3Bsb3QoLiwgYWVzKHggPSB2YWx1ZSwgeSA9IG5hbWUsIGZpbGwgPSBuYW1lKSkgKyANCiAgZ2dyaWRnZXM6Omdlb21fZGVuc2l0eV9yaWRnZXMocmVsX21pbl9oZWlnaHQgPSAwLjAxKSArDQogIGZhY2V0X3dyYXAofnF1ZXN0KSArDQogIGdncmlkZ2VzOjp0aGVtZV9yaWRnZXMoZ3JpZCA9IEZBTFNFLCBjZW50ZXJfYXhpc19sYWJlbHMgPSBUUlVFKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJoaWRlIikgKyBsYWJzKHk9IiIpIA0KDQpgYGANCg0KDQoNCg0KIyBUYWJsZSBJbnRlcm5hbCBjb25zaXN0ZW5jeQ0KDQoNCmBgYHtyLCBldmFsID0gRkFMU0UgfQ0KcmVnX2NvbSA8LSAiXmNvbV9hNF8uKiINCnJlZ19mbSA8LSAiXmZtX2E0Xy4qIg0KcmVnX2dtIDwtICJeZ21fYTRfLioiDQpyZWdfY2cgPC0gIl5jZ19hNF8uKiINCnJlZ19wcyA8LSAiXnBzX2E0Xy4qIg0KDQpyZWdzIDwtIGMocmVnX2ZtLCByZWdfY29tLCByZWdfZ20sIHJlZ19jZywgcmVnX3BzKSAlPiUgDQogICAgc2V0X25hbWVzKGMoImZtX2E0XyIsICJjb21fYTRfIiwgImdtX2E0XyIsICJjZ19hNF8iLCANCiAgICAgICAgICAgICAgICAicHNfYTRfIikpDQpjcm9uYmFjaHNfYWxwaGEgPC0gDQogICAgbWFwX2RmKHJlZ3MsIH4gDQogICAgICAgICAgICAgICBkcyAlPiUgDQogICAgICAgICAgICAgICBzZWxlY3QoZHBseXI6Om1hdGNoZXMoLngpKSAlPiUgDQogICAgICAgICAgICAgICBwc3ljaDo6YWxwaGEoY2hlY2sua2V5cyA9IFRSVUUpICU+JSAuJHRvdGFsICU+JSANCiAgICAgICAgICAgICAgIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKCkNCiAgICAgICAgICAgLC5pZCA9ICJzY2FsZSINCiAgICApDQoNCg0KYGBgDQoNCg0KYGBge3IsIGV2YWwgPSBGQUxTRSB9DQphcHBseV9hbHBoYSA8LSBmdW5jdGlvbihkYXRhLCBuZXN0X2NvbnRhaW5zKSB7DQogIHg8LWRhdGEgJT4lDQogICAgc2VsZWN0KHF1ZXN0LCBjb250YWlucyhuZXN0X2NvbnRhaW5zKSkgJT4lDQogICAgZ3JvdXBfYnkocXVlc3QpICU+JQ0KICAgIGRvKGFscGhhKC5bLTFdKSR0b3RhbCkgI2NvbXB1dGUgYWxwaGENCiAgDQogIHk8LWRhdGEgJT4lIA0KICAgIGNvdW50KHF1ZXN0KSAjZ2V0IG4NCiAgDQogIHogPC0gbGVmdF9qb2luKHgseSwgYnkgPSAicXVlc3QiKSANCg0KICB6IDwtIHogJT4lIG11dGF0ZV9pZihpcy5udW1lcmljLCByb3VuZCwyKQ0KICANCiAgcmV0dXJuKHopDQp9DQpgYGANCg0KDQpgYGB7ciwgZXZhbCA9IEZBTFNFIH0NCmFwcGx5X2FscGhhKGRzLCAnY29tX2E0XycpDQpgYGANCg0KDQoNCiMjIEFsbCBxdWVzdGlvbm5haXJlcyANCg0KYGBge3IsIGV2YWwgPSBUUlVFICB9DQpsZWZ0X2pvaW4oDQpkcyAlPiUNCiAgI3NlbGVjdCBpdGVtcw0KICAgIHNlbGVjdChxdWVzdCwgY29tX2E0XzE6Y29tX2E0XzYsIGdtX2E0XzE6Z21fYTRfNiwgZm1fYTRfMTpmbV9hNF82LCBjZ19hNF8xOmNnX2E0XzYsIHBzX2E0XzE6cHNfYTRfNikgJT4lIA0KICAgIHBpdm90X2xvbmdlcihjb2xzID0gLXF1ZXN0LA0KICAgICAgICAgICAgICAgICBuYW1lc190byA9IGMoInNjYWxlIiwgIi52YWx1ZSIpLA0KICAgICAgICAgICAgICAgICBuYW1lc19wYXR0ZXJuID0gIihcXHcrX1xcdytfKSguKSIpICU+JQ0KICAgIG5lc3RfYnkocXVlc3QsIHNjYWxlKSAlPiUNCiAgICAjQ29tcHV0ZSBjcm9uYmFjaMK0cyBhbHBoYSBmb3IgYWxsIHF1ZXN0aW9ubmFpcmVzIGFuZCBkb21haW5zDQogICAgbXV0YXRlKGFscGhhKGRhdGEpJHRvdGFsKSAlPiUgDQogIHNlbGVjdChxdWVzdCwgc2NhbGUsIHN0ZC5hbHBoYSwgYXZlcmFnZV9yKQ0KLA0KDQogIGRzICU+JSBjb3VudChxdWVzdCkNCikgJT4lIA0KICBtdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsMikgJT4lIA0KICBwaXZvdF93aWRlcihxdWVzdCwgbmFtZXNfZnJvbSA9IHNjYWxlLCB2YWx1ZXNfZnJvbSA9IHN0ZC5hbHBoYTpuKQ0KYGBgDQoNCg0KDQoNCmBgYHtyLCBldmFsID0gRkFMU0UgfQ0KI2h0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzY5MzAyNDU3L3VzaW5nLWRwbHlyLXRvLW5lc3Qtb3ItZ3JvdXAtdHdvLXZhcmlhYmxlcy10aGVuLXBlcmZvcm0tdGhlLWNyb25iYWNocy1hbHBoYS1mdS82OTMwMzY0MSM2OTMwMzY0MQ0KZHMgJT4lDQogIHNlbGVjdChxdWVzdCwgY29tX2E0XzE6Y29tX2E0XzYsIGdtX2E0XzE6Z21fYTRfNiwgZm1fYTRfMTpmbV9hNF82LCBjZ19hNF8xOmNnX2E0XzYsIHBzX2E0XzE6cHNfYTRfNikgJT4lIA0KICBtdXRhdGUoaWQgPSAxOm4oKSkgJT4lDQogIHBpdm90X2xvbmdlcihjb2xzID0gYygtaWQsIC1xdWVzdCkpICU+JQ0KICBzZXBhcmF0ZShjb2wgPSBuYW1lLA0KICAgICAgICAgICBpbnRvID0gYygic2NhbGUiLCAiaXRlbSIpLA0KICAgICAgICAgICBzZXAgPSAiXyIsDQogICAgICAgICAgIGV4dHJhID0gIm1lcmdlIikgJT4lDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBpdGVtKSAlPiUNCiAgc2VsZWN0KC1pZCkgJT4lDQogIGdyb3VwX2J5KHF1ZXN0LCBzY2FsZSkgJT4lDQogIG5lc3QoKSAlPiUNCiAgbXV0YXRlKGFscGhhX3Jlc3VsdHMgPSBtYXAoZGF0YSwgfmFscGhhKC4pJHRvdGFsKSkgJT4lDQogIHVubmVzdF93aWRlcihhbHBoYV9yZXN1bHRzKSAlPiUgI2dldCBhbHBoYSByZXN1bHRzDQogIHNlbGVjdChxdWVzdCwgc2NhbGUsIHN0ZC5hbHBoYSwgYXZlcmFnZV9yKSAlPiUgICN3aGF0IEkgd2FudCB0byBnZXQNCiAgYXJyYW5nZShxdWVzdCwgc2NhbGUpICU+JSANCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHNjYWxlLCB2YWx1ZXNfZnJvbSA9IHN0ZC5hbHBoYTphdmVyYWdlX3IpICU+JSANCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIHJvdW5kLCAyKSANCg0KYGBgDQoNCg0KIyMgQWxsIGRhdGENCg0KYGBge3J9DQpkcyAlPiUNCiAgICBzZWxlY3QocXVlc3QsIGNvbV9hNF8xOmNvbV9hNF82LCBnbV9hNF8xOmdtX2E0XzYsIGZtX2E0XzE6Zm1fYTRfNiwgY2dfYTRfMTpjZ19hNF82LCBwc19hNF8xOnBzX2E0XzYpICU+JSANCiAgICBncm91cF9ieShxdWVzdCkgJT4lDQogICAgZG8oYWxwaGEoLlstMV0pJHRvdGFsKSAlPiUgDQogIHNlbGVjdChxdWVzdCwgc3RkLmFscGhhKSAlPiUgDQogIG11dGF0ZV9pZihpcy5udW1lcmljLCByb3VuZCwgMikNCmBgYA0KDQojIyBEb3VibGUgY2hlY2sNCg0KDQpgYGB7cn0NCmRzXzEgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gMTYpICU+JSANCiAgc2VsZWN0KCBjb21fYTRfMTpjb21fYTRfNiwgZ21fYTRfMTpnbV9hNF82LCBmbV9hNF8xOmZtX2E0XzYsIGNnX2E0XzE6Y2dfYTRfNiwgcHNfYTRfMTpwc19hNF82KSAlPiUgDQogIHBzeWNoOjphbHBoYSguKQ0KYGBgDQoNCiMjIEdyYXBoDQoNCg0KYGBge3J9DQojbWFrZSBkYXRhDQpkc18xICU+JQ0KICAgIHNlbGVjdChxdWVzdCwgY29tX2E0XzE6Y29tX2E0XzYsIGdtX2E0XzE6Z21fYTRfNiwgZm1fYTRfMTpmbV9hNF82LCBjZ19hNF8xOmNnX2E0XzYsIHBzX2E0XzE6cHNfYTRfNikgJT4lIA0KICAgIHBpdm90X2xvbmdlcihjb2xzID0gLXF1ZXN0LA0KICAgICAgICAgICAgICAgICBuYW1lc190byA9IGMoInNjYWxlIiwgIi52YWx1ZSIpLA0KICAgICAgICAgICAgICAgICBuYW1lc19wYXR0ZXJuID0gIihcXHcrX1xcdytfKSguKSIpICU+JQ0KICAgIG5lc3RfYnkocXVlc3QsIHNjYWxlKSU+JQ0KICAgIG11dGF0ZShhbHBoYT1hbHBoYShkYXRhKSR0b3RhbCRyYXdfYWxwaGEpIC0+eCANCg0KeCAlPiUgDQogIG11dGF0ZV9hdCh2YXJzKHNjYWxlKSwgfmNhc2Vfd2hlbigNCiAgICAuID09ICJjZ19hNF8iIH4gIlByb2JsZW0gU29sdmluZyIsDQogICAgLiA9PSAiY29tX2E0XyIgfiAiQ29tbXVuaWNhdGlvbiIsDQogICAgLiA9PSAiZm1fYTRfIiB+ICJGaW5lIE1vdG9yIiwNCiAgICAuID09ICJnbV9hNF8iIH4gIkdyb3NzIE1vdG9yIiwNCiAgICAuID09ICJwc19hNF8iIH4gIlBlcnNvbmFsLVNvY2lhbCIsDQogICkpICU+JSANCiAgZ2dwbG90KC4sIGFlcyh4PXF1ZXN0LCB5ID0gYWxwaGEsIGNvbG9yID0gc2NhbGUpKSArDQogIHN0YXRfc3VtbWFyeShnZW9tID0gImxpbmUiLCBzaXplID0gMSkgKw0KICBzdGF0X3N1bW1hcnkoZ2VvbSA9ICJwb2ludCIpICsNCiAgbGFicyh5PSJDcm9uYmFjaCdzIEFscGhhIiwgeD0iQWdlLWludGVydmFsIikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQpgYGANCg0KDQojIFRhYmxlIENvcnJlbGF0aW9uDQoNCmBgYHtyfQ0KZHMgJT4lDQogICAgc2VsZWN0KHF1ZXN0LCBjb21fYTRfMTpjb21fYTRfNiwgZ21fYTRfMTpnbV9hNF82LCBmbV9hNF8xOmZtX2E0XzYsIGNnX2E0XzE6Y2dfYTRfNiwgcHNfYTRfMTpwc19hNF82KSAlPiUgDQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtcXVlc3QsDQogICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gYygic2NhbGUiLCAiLnZhbHVlIiksDQogICAgICAgICAgICAgICAgIG5hbWVzX3BhdHRlcm4gPSAiKFxcdytfXFx3K18pKC4pIikgJT4lDQogICAgbmVzdF9ieShxdWVzdCwgc2NhbGUpICU+JQ0KICAgIG11dGF0ZShjb3I9bWVhbihhbHBoYShkYXRhKSRpdGVtLnN0YXRzJHIuY29yKSkgJT4lIA0KICBtdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsMikgJT4lIA0KICBwaXZvdF93aWRlcihxdWVzdCwgbmFtZXNfZnJvbSA9IHNjYWxlLCB2YWx1ZXNfZnJvbSA9IGNvcikNCmBgYA0KDQojIyBNaW5vciBjaGVjaw0KDQpgYGB7cn0NCmRzXzEgJT4lDQogICAgc2VsZWN0KHF1ZXN0LCBmbV9hNF8xOmZtX2E0XzYpICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDQpICU+JSANCiAge21lYW4oYWxwaGEoLikkaXRlbS5zdGF0cyRyLmNvcil9DQpgYGANCg0KYGBge3J9DQpkc18xICU+JQ0KICAgIHNlbGVjdChxdWVzdCwgY29tX2E0XzE6Y29tX2E0XzYsIGdtX2E0XzE6Z21fYTRfNiwgZm1fYTRfMTpmbV9hNF82LCBjZ19hNF8xOmNnX2E0XzYsIHBzX2E0XzE6cHNfYTRfNikgJT4lIA0KICAgIHBpdm90X2xvbmdlcihjb2xzID0gLXF1ZXN0LA0KICAgICAgICAgICAgICAgICBuYW1lc190byA9IGMoInNjYWxlIiwgIi52YWx1ZSIpLA0KICAgICAgICAgICAgICAgICBuYW1lc19wYXR0ZXJuID0gIihcXHcrX1xcdytfKSguKSIpICU+JQ0KICAgIG5lc3RfYnkocXVlc3QsIHNjYWxlKSAlPiUNCiAgICBtdXRhdGUoY29yPW1lYW4oYWxwaGEoZGF0YSkkaXRlbS5zdGF0cyRyLmNvcikpLT54IA0KDQp4ICU+JSANCiAgbXV0YXRlX2F0KHZhcnMoc2NhbGUpLCB+Y2FzZV93aGVuKA0KICAgIC4gPT0gImNnX2E0XyIgfiAiUHJvYmxlbSBTb2x2aW5nIiwNCiAgICAuID09ICJjb21fYTRfIiB+ICJDb21tdW5pY2F0aW9uIiwNCiAgICAuID09ICJmbV9hNF8iIH4gIkZpbmUgTW90b3IiLA0KICAgIC4gPT0gImdtX2E0XyIgfiAiR3Jvc3MgTW90b3IiLA0KICAgIC4gPT0gInBzX2E0XyIgfiAiUGVyc29uYWwtU29jaWFsIiwNCiAgKSkgJT4lIA0KICBnZ3Bsb3QoLiwgYWVzKHg9cXVlc3QsIHkgPSBjb3IsIGNvbG9yID0gc2NhbGUpKSArDQogIHN0YXRfc3VtbWFyeShnZW9tID0gImxpbmUiLCBzaXplID0gMSkgKw0KICBzdGF0X3N1bW1hcnkoZ2VvbSA9ICJwb2ludCIpICsNCiAgbGFicyh5PSJDb3JyZWxhdGlvbiBjb2VmZmljaWVudCIsIHg9IkFnZS1pbnRlcnZhbCIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyLCA3MiwgYnkgPSAyKSkgICsNCiAgICB0aGVtZV9idygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQpgYGANCg0KDQojIEN1dG9mZiBzY29yZXMNCg0KQXNrZWQgYnkgSmFuZSBhbmQgS2ltYmVybHkgb24gTWFyY2ggMywgMjAyMg0KDQojIyBFeHByZXNzaXZlIHZzIHJlY2VwdGl2ZSBjb21tdW5pY2F0aW9uDQoNCmBgYHtyfQ0KY29tcGFyZV9jb21tdW5pY2F0aW9uIDwtIGZ1bmN0aW9uKHF1ZXN0LCBpdGVtcykgew0KICBxdWVzdCA8LSBlbnF1byhxdWVzdCkNCiAgaXRlbXMgPC0gZW5xdW8oaXRlbXMpDQogIA0KICAgIGRzICU+JSAjZ2V0IGRhdGENCiAgICBmaWx0ZXIocXVlc3QgPT0gISFxdWVzdCkgJT4lICNzZWxlY3Qgd2hpY2ggcXVlc3Rpb25uYWlyZSB3aWxsIGJlIHVzZWQNCiAgICBtdXRhdGUoY29tX2V4cCA9IHJvd1N1bXMoc2VsZWN0KC4sICEhaXRlbXMpLCBuYS5ybT1UKSkgJT4lICNjcmVhdGUgYSBzdW1tYXRpdmUgc2NvcmUgZm9yIGV4cHJlc3NpdmUgaXRlbXMNCiAgICBtdXRhdGUoY29tX3JlYyA9IGNfc3VtLWNvbV9leHApICU+JSANCiAgICBzZWxlY3QoY29tX2V4cCwgY29tX3JlYywgY19zdW0pICU+JQ0KICAgIHN1bW1hcmlzZShuPW4oKSwNCiAgICAgICAgICAgICAgbWVhbihjb21fZXhwKSwNCiAgICAgICAgICAgICAgbWVhbihjb21fcmVjKSwNCiAgICAgICAgICAgICAgbWVhbihjX3N1bSksDQogICAgcCA9IHQudGVzdChjb21fZXhwLCBjb21fcmVjLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLCBwYWlyZWQgPSBUKSRwLnZhbHVlKSAlPiUNCiAgICAgIHQoKSAjY29tcGFyZSBzY29yZXMNCn0NCmBgYA0KDQpgYGB7cn0NCg0KbGlzdCgNCiAgY29tcGFyZV9jb21tdW5pY2F0aW9uKHF1ZXN0ID0gMiwgaXRlbXMgPSBjKGNvbV9hNF8xLGNvbV9hNF8yLGNvbV9hNF81KSksDQogIGNvbXBhcmVfY29tbXVuaWNhdGlvbihxdWVzdCA9IAk0CSwgaXRlbXMgPSBjKAljb21fYTRfMSxjb21fYTRfNCxjb21fYTRfNgkpKSwNCiAgY29tcGFyZV9jb21tdW5pY2F0aW9uKHF1ZXN0ID0gCTYJLCBpdGVtcyA9IGMoCWNvbV9hNF8xLGNvbV9hNF8yLGNvbV9hNF81CSkpLA0KICBjb21wYXJlX2NvbW11bmljYXRpb24ocXVlc3QgPSAJOAksIGl0ZW1zID0gYygJY29tX2E0XzMsY29tX2E0XzQsY29tX2E0XzYJKSksDQogIGNvbXBhcmVfY29tbXVuaWNhdGlvbihxdWVzdCA9IAkxMAksIGl0ZW1zID0gYygJY29tX2E0XzEsY29tX2E0XzMsY29tX2E0XzYJKSksDQogIGNvbXBhcmVfY29tbXVuaWNhdGlvbihxdWVzdCA9IAkxMgksIGl0ZW1zID0gYygJY29tX2E0XzEsY29tX2E0XzQsY29tX2E0XzYJKSksDQogIGNvbXBhcmVfY29tbXVuaWNhdGlvbihxdWVzdCA9IAkxNAksIGl0ZW1zID0gYygJY29tX2E0XzEsY29tX2E0XzIsY29tX2E0XzUJKSksDQogIGNvbXBhcmVfY29tbXVuaWNhdGlvbihxdWVzdCA9IAkxNgksIGl0ZW1zID0gYygJY29tX2E0XzUsY29tX2E0XzMsY29tX2E0XzYJKSksDQogIGNvbXBhcmVfY29tbXVuaWNhdGlvbihxdWVzdCA9IAkxOAksIGl0ZW1zID0gYygJY29tX2E0XzMsY29tX2E0XzQsY29tX2E0XzYJKSksDQogIGNvbXBhcmVfY29tbXVuaWNhdGlvbihxdWVzdCA9IAkyMAksIGl0ZW1zID0gYygJY29tX2E0XzIsY29tX2E0XzMsY29tX2E0XzYJKSksDQogIGNvbXBhcmVfY29tbXVuaWNhdGlvbihxdWVzdCA9IAkyMgksIGl0ZW1zID0gYygJY29tX2E0XzMsY29tX2E0XzUgLGNvbV9hNF82CSkpLA0KICBjb21wYXJlX2NvbW11bmljYXRpb24ocXVlc3QgPSAJMjQJLCBpdGVtcyA9IGMoCWNvbV9hNF8zLGNvbV9hNF81ICxjb21fYTRfNgkpKSwNCiAgY29tcGFyZV9jb21tdW5pY2F0aW9uKHF1ZXN0ID0gCTI3CSwgaXRlbXMgPSBjKAljb21fYTRfMixjb21fYTRfNCxjb21fYTRfNQkpKSwNCiAgY29tcGFyZV9jb21tdW5pY2F0aW9uKHF1ZXN0ID0gCTMwCSwgaXRlbXMgPSBjKAljb21fYTRfMixjb21fYTRfNCxjb21fYTRfNgkpKQ0KKQ0KYGBgDQoNCmBgYHtyfQ0KZHMgJT4lIGZpbHRlcihxdWVzdCA9PSA0KSAlPiUNCiAgc2VsZWN0KGNvbV9hNF8xLGNvbV9hNF80LGNvbV9hNF82KSAlPiUNCiAgRGF0YUV4cGxvcmVyOjpwcm9maWxlX21pc3NpbmcoKQ0KDQoNCmRzICU+JQ0KICBmaWx0ZXIocXVlc3QgPT0gNCkgJT4lDQogICAgIHJvd2lkX3RvX2NvbHVtbigpICU+JQ0KICAgICBmaWx0ZXIoaXMubmEoY29tX2E0XzQpKSAjaXRzIG1pc3NpbmcgYmVjYXVzZSBhc3EzIGNvbSA0IHdhcyBtaXNzaW5nIGFuZCAyIGFuZCA0IG1vbnRocyBhcmUgZXF1YWwNCg0KDQpgYGANCg0KDQojIyBNZWFucyBhbmQgU0QgDQoNCmBgYHtyfQ0KbGVmdF9qb2luKA0KICBkcyAlPiUgI2dldCBkcw0KICBzZWxlY3QocXVlc3QsIGVuZHNfd2l0aCgic3VtIikpICU+JSAjc2VsZWN0IHRoZSBmb2N1cyB2YXJpYWJsZXMgDQogIHBpdm90X2xvbmdlcigtcXVlc3QpICU+JSAjdHJhbnNwb3NlIHRvIGxvbmcgZm9ybWF0YQ0KICBuZXN0X2J5KHF1ZXN0LCBuYW1lKSAlPiUgI2dyb3VwDQogIG11dGF0ZShtZWFuID0gbGlzdChtYXBfZGJsKGRhdGEsIH5tZWFuKC4pKSksDQogICAgICAgICBzZCA9IGxpc3QobWFwX2RibChkYXRhLCB+c2QoLikpKSwNCiAgICAgICAgIG1fMXNkID0gbWVhbi1zZCwNCiAgICAgICAgIG1fMV9oYWxmX3NkID0gbWVhbi0xLjUqc2QsDQogICAgICAgICBtXzJzZCA9IG1lYW4tMipzZCkgJT4lIA0KICB1bm5lc3QoLWRhdGEpICU+JSAjdW5uZXN0DQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBxdWVzdCwgbmFtZXNfZnJvbSA9IG5hbWUsIHZhbHVlc19mcm9tID0gbWVhbjptXzJzZCkgJT4lIA0KICBtdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsIDIpDQogICwNCiAgZHMgJT4lIGNvdW50KHF1ZXN0KQ0KKSAlPiUgc2VsZWN0KHF1ZXN0LCBuLCBldmVyeXRoaW5nKCkpDQpgYGANCg0KIyMgUGVyZm9ybWFuY2Ugb2YgdGhlIGN1dG9mZg0KDQojIyMgTW9uaXRvcmluZyB6b25lDQoNCmBgYHtyfQ0KZHMgJT4lIA0KICBzZWxlY3QocXVlc3QsIGVuZHNfd2l0aCgic3VtIikpICU+JSAjZ2V0IHZhcmlhYmxlIG5hbWVzDQogIHBpdm90X2xvbmdlcigtcXVlc3QpICU+JSAjdHJhbmZvcm0gaW50byB0aGUgbG9uZyBmb3JtYXQNCiAgbmVzdF9ieShxdWVzdCwgbmFtZSkgJT4lICNncm91cCBvciBuZXN0DQogIG11dGF0ZSgNCiAgICBxdWVzdGlvbm5haXJlID0gcXVlc3QsI2NvbXB1dGUgcXVlc3Rpb25uYWlyZQ0KICAgIG4gPSBtYXBfZGJsKGRhdGEsIH5ucm93KGRhdGEuZnJhbWUoLikpKSwgI2NvbXB1dGUgc2FtcGxlIHNpemUNCiAgICBtZWFuID0gbWFwX2RibChkYXRhLCB+bWVhbiguKSksICNnZXQgdGhlIG1lYW5zDQogICAgc2QgPSBtYXBfZGJsKGRhdGEsIH5zZCguKSksICNnZXQgc2QNCiAgICBtXzFzZCA9IG1lYW4tc2QsICMxIGJlbG93DQogICAgbV8xX2hhbGZfc2QgPSBtZWFuLTEuNSpzZCwgIzEuNSBiZWxvdw0KICAgIG1fMnNkID0gbWVhbi0yKnNkLCAjMiBiZWxvdw0KICAgIGhvd19tYW55X2MgPSBtYXAoZGF0YSwgfiBpZmVsc2UobmFtZSA9PSAiY19zdW0iLCAjaSdsbCBjb3VudCBob3cgbWFueSBwYXJ0aWNpcGFudHMgYXJlIGJlbG93DQogICAgICBkcyAlPiUgDQogICAgICAgIGZpbHRlcihxdWVzdCA9PSBxdWVzdGlvbm5haXJlKSAlPiUgDQogICAgICAgIGZpbHRlcihjX3N1bSA+IG1fMnNkICYgY19zdW0gPD0gbV8xc2QpICU+JSANCiAgICAgICAgc3VtbWFyaXNlKG4oKSksDQogICAgICBOQV9pbnRlZ2VyXykpLCAjIHBlcmNlbnRhZ2Ugb2YgY29tbXVuaWNhdGlvbg0KICAgIA0KICAgIGhvd19tYW55X2dtID0gbWFwKGRhdGEsIH4gaWZlbHNlKG5hbWUgPT0gImdtX3N1bSIsDQogICAgICBkcyAlPiUgDQogICAgICAgIGZpbHRlcihxdWVzdCA9PSBxdWVzdGlvbm5haXJlKSAlPiUgDQogICAgICAgIGZpbHRlcihnbV9zdW0gPiBtXzJzZCAmIGdtX3N1bSA8PSBtXzFzZCkgJT4lIA0KICAgICAgICBzdW1tYXJpc2UobigpKSwgI3BlcmNlbnRhZ2Ugb2YgZ3Jvc3MgbW90b3INCiAgICBOQV9pbnRlZ2VyXykpLA0KICAgIA0KICAgIGhvd19tYW55X2ZtID0gbWFwKGRhdGEsIH4gaWZlbHNlKG5hbWUgPT0gImZtX3N1bSIsDQogICAgICBkcyAlPiUgDQogICAgICAgIGZpbHRlcihxdWVzdCA9PSBxdWVzdGlvbm5haXJlKSAlPiUgDQogICAgICAgIGZpbHRlcihmbV9zdW0gPiBtXzJzZCAmIGZtX3N1bSA8PSBtXzFzZCkgJT4lIA0KICAgICAgICBzdW1tYXJpc2UobigpKSwjcGVyY2VudGFnZSBvZiBmaW5lIG1vdG9yDQogICAgICBOQV9pbnRlZ2VyXykpLCANCiAgICANCiAgICBob3dfbWFueV9jZyA9IG1hcChkYXRhLCB+IGlmZWxzZShuYW1lID09ICJjZ19zdW0iLA0KICAgICAgZHMgJT4lIA0KICAgICAgICBmaWx0ZXIocXVlc3QgPT0gcXVlc3Rpb25uYWlyZSkgJT4lIA0KICAgICAgICBmaWx0ZXIoY2dfc3VtID4gbV8yc2QgJiBjZ19zdW0gPD0gbV8xc2QpICU+JSANCiAgICAgICAgc3VtbWFyaXNlKG4oKSksICNwZXJjZW50YWdlIG9mIHByb2JsZW0tc29sdmluZw0KICAgIE5BX2ludGVnZXJfKSksIA0KDQogICAgaG93X21hbnlfcHMgPSBtYXAoZGF0YSwgfiBpZmVsc2UobmFtZSA9PSAicHNfc3VtIiwNCiAgICAgIGRzICU+JSANCiAgICAgICAgZmlsdGVyKHF1ZXN0ID09IHF1ZXN0aW9ubmFpcmUpICU+JSANCiAgICAgICAgZmlsdGVyKHBzX3N1bSA+IG1fMnNkICYgcHNfc3VtIDw9IG1fMXNkKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZShuKCkpLCAjcGVyY2VudGFnZSBvZiBwZXJzb25hbCBzb2NpYWwNCiAgICAgICAgTkFfaW50ZWdlcl8pKSkgICU+JSANCiAgbXV0YXRlKG5fY29tPQ0KICAgICAgICAgICBwYXN0ZTAoaG93X21hbnlfY1tbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfY1tbMV1dL24qMTAwLDApLCIlIiksICNJJ2xsIGdldCB0aGUgcGVyY2VudGFnZXMNCiAgICAgICAgIG5fZ209DQogICAgICAgICAgIHBhc3RlMChob3dfbWFueV9nbVtbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfZ21bWzFdXS9uKjEwMCwwKSwiJSIpLA0KICAgICAgICAgbl9mbT0NCiAgICAgICAgICAgcGFzdGUwKGhvd19tYW55X2ZtW1sxXV0sIi0iLA0KICAgICAgICAgICAgICAgICByb3VuZChob3dfbWFueV9mbVtbMV1dL24qMTAwLDApLCIlIiksDQogICAgICAgICBuX2NnPQ0KICAgICAgICAgICBwYXN0ZTAoaG93X21hbnlfY2dbWzFdXSwiLSIsDQogICAgICAgICAgICAgICAgIHJvdW5kKGhvd19tYW55X2NnW1sxXV0vbioxMDAsMCksIiUiKSwNCiAgICAgICAgIG5fcHM9DQogICAgICAgICAgIHBhc3RlMChob3dfbWFueV9wc1tbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfcHNbWzFdXS9uKjEwMCwwKSwiJSIpICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICApICU+JQ0KICB1bm5lc3Rfd2lkZXIoLXF1ZXN0KSAlPiUgI3BhcnRpY3VsYXIgdHJpY2tlcyAodGhlcmUgaXMgYSBsb3Qgb2YgcHNldWRvIG1pc3NpbmcgdmFsdWVzKQ0KICBzZWxlY3QocXVlc3QsaG93X21hbnlfcHM6bGFzdF9jb2woKSwgLWhvd19tYW55X3BzKSAlPiUgICNnZXQgc29tZSB2YXJpYWJsZXMNCiAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lICAjbm93IHRyYW5zZm9ybSB0byB0aGUgbG9uZyBmb3JtYXQNCiAgZmlsdGVyKHZhbHVlICE9ICJOQS1OQSUiKSAlPiUgI2ZpbHRlcg0KICBwaXZvdF93aWRlcihpZF9jb2xzID0gcXVlc3QsIG5hbWVzX2Zyb20gPSBuYW1lLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKQ0KDQpgYGANCg0KDQpgYGB7cn0NCmRzICU+JSBmaWx0ZXIocXVlc3QgPT0gMiAmIGNfc3VtIDw9IDI3LjgyMjQxICYgY19zdW0gPiAxMy40MDEyKQ0KDQpgYGANCg0KDQpgYGB7cn0NCmRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDQpICU+JSANCiAgZmlsdGVyKGdtX3N1bSA+IDM1LjIgJiBnbV9zdW0gPD0gNDQuMjkpDQpgYGANCg0KDQpgYGB7cn0NCmRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDYpICU+JSANCiAgZmlsdGVyKGZtX3N1bSA+IDIxLjYgJiBmbV9zdW0gPD0gMzQuNzEpDQpgYGANCg0KYGBge3J9DQpkcyAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSAyNykgJT4lIA0KICBmaWx0ZXIocHNfc3VtID4gMjIuMDIgJiBwc19zdW0gPD0gMzQuODgpDQpgYGANCg0KDQojIyMgQmVsb3cgdGhlIGN1dG9mZg0KDQpgYGB7cn0NCmRzICU+JSANCiAgc2VsZWN0KHF1ZXN0LCBlbmRzX3dpdGgoInN1bSIpKSAlPiUgI2dldCB2YXJpYWJsZSBuYW1lcw0KICBwaXZvdF9sb25nZXIoLXF1ZXN0KSAlPiUgI3RyYW5mb3JtIGludG8gdGhlIGxvbmcgZm9ybWF0DQogIG5lc3RfYnkocXVlc3QsIG5hbWUpICU+JSAjZ3JvdXAgb3IgbmVzdA0KICBtdXRhdGUoDQogICAgcXVlc3Rpb25uYWlyZSA9IHF1ZXN0LCNjb21wdXRlIHF1ZXN0aW9ubmFpcmUNCiAgICBuID0gbGlzdChtYXBfZGJsKGRhdGEsIH5ucm93KGRhdGEuZnJhbWUoLikpKSksICNjb21wdXRlIHNhbXBsZSBzaXplDQogICAgbWVhbiA9IGxpc3QobWFwX2RibChkYXRhLCB+bWVhbiguKSkpLCAjZ2V0IHRoZSBtZWFucw0KICAgIHNkID0gbGlzdChtYXBfZGJsKGRhdGEsIH5zZCguKSkpLCAjZ2V0IHNkDQogICAgbV8xc2QgPSBtZWFuLXNkLCAjMSBiZWxvdw0KICAgIG1fMV9oYWxmX3NkID0gbWVhbi0xLjUqc2QsICMxLjUgYmVsb3cNCiAgICBtXzJzZCA9IG1lYW4tMipzZCwgIzIgYmVsb3cNCiAgICBob3dfbWFueV9jID0gbWFwKGRhdGEsIH4gaWZlbHNlKG5hbWUgPT0gImNfc3VtIiwgI2knbGwgY291bnQgaG93IG1hbnkgcGFydGljaXBhbnRzIGFyZSBiZWxvdw0KICAgICAgZHMgJT4lIA0KICAgICAgICBmaWx0ZXIocXVlc3QgPT0gcXVlc3Rpb25uYWlyZSkgJT4lIA0KICAgICAgICBmaWx0ZXIoY19zdW0gIDw9IG1fMnNkKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZShuKCkpLA0KICAgICAgTkFfaW50ZWdlcl8pKSwgIyBwZXJjZW50YWdlIG9mIGNvbW11bmljYXRpb24NCiAgICANCiAgICBob3dfbWFueV9nbSA9IG1hcChkYXRhLCB+IGlmZWxzZShuYW1lID09ICJnbV9zdW0iLA0KICAgICAgZHMgJT4lIA0KICAgICAgICBmaWx0ZXIocXVlc3QgPT0gcXVlc3Rpb25uYWlyZSkgJT4lIA0KICAgICAgICBmaWx0ZXIoZ21fc3VtIDw9IG1fMnNkKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZShuKCkpLCAjcGVyY2VudGFnZSBvZiBncm9zcyBtb3Rvcg0KICAgIE5BX2ludGVnZXJfKSksDQogICAgDQogICAgaG93X21hbnlfZm0gPSBtYXAoZGF0YSwgfiBpZmVsc2UobmFtZSA9PSAiZm1fc3VtIiwNCiAgICAgIGRzICU+JSANCiAgICAgICAgZmlsdGVyKHF1ZXN0ID09IHF1ZXN0aW9ubmFpcmUpICU+JSANCiAgICAgICAgZmlsdGVyKGZtX3N1bSA8PSBtXzJzZCkgJT4lIA0KICAgICAgICBzdW1tYXJpc2UobigpKSwjcGVyY2VudGFnZSBvZiBmaW5lIG1vdG9yDQogICAgICBOQV9pbnRlZ2VyXykpLCANCiAgICANCiAgICBob3dfbWFueV9jZyA9IG1hcChkYXRhLCB+IGlmZWxzZShuYW1lID09ICJjZ19zdW0iLA0KICAgICAgZHMgJT4lIA0KICAgICAgICBmaWx0ZXIocXVlc3QgPT0gcXVlc3Rpb25uYWlyZSkgJT4lIA0KICAgICAgICBmaWx0ZXIoY2dfc3VtIDw9IG1fMnNkKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZShuKCkpLCAjcGVyY2VudGFnZSBvZiBwcm9ibGVtLXNvbHZpbmcNCiAgICBOQV9pbnRlZ2VyXykpLCANCg0KICAgIGhvd19tYW55X3BzID0gbWFwKGRhdGEsIH4gaWZlbHNlKG5hbWUgPT0gInBzX3N1bSIsDQogICAgICBkcyAlPiUgDQogICAgICAgIGZpbHRlcihxdWVzdCA9PSBxdWVzdGlvbm5haXJlKSAlPiUgDQogICAgICAgIGZpbHRlcihwc19zdW0gPD0gbV8yc2QpICU+JSANCiAgICAgICAgc3VtbWFyaXNlKG4oKSksICNwZXJjZW50YWdlIG9mIHBlcnNvbmFsIHNvY2lhbA0KICAgICAgICBOQV9pbnRlZ2VyXykpKSAgJT4lIA0KICBtdXRhdGUobl9jb209DQogICAgICAgICAgIHBhc3RlMChob3dfbWFueV9jW1sxXV0sIi0iLA0KICAgICAgICAgICAgICAgICByb3VuZChob3dfbWFueV9jW1sxXV0vbioxMDAsMCksIiUiKSwgI0knbGwgZ2V0IHRoZSBwZXJjZW50YWdlcw0KICAgICAgICAgbl9nbT0NCiAgICAgICAgICAgcGFzdGUwKGhvd19tYW55X2dtW1sxXV0sIi0iLA0KICAgICAgICAgICAgICAgICByb3VuZChob3dfbWFueV9nbVtbMV1dL24qMTAwLDApLCIlIiksDQogICAgICAgICBuX2ZtPQ0KICAgICAgICAgICBwYXN0ZTAoaG93X21hbnlfZm1bWzFdXSwiLSIsDQogICAgICAgICAgICAgICAgIHJvdW5kKGhvd19tYW55X2ZtW1sxXV0vbioxMDAsMCksIiUiKSwNCiAgICAgICAgIG5fY2c9DQogICAgICAgICAgIHBhc3RlMChob3dfbWFueV9jZ1tbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfY2dbWzFdXS9uKjEwMCwwKSwiJSIpLA0KICAgICAgICAgbl9wcz0NCiAgICAgICAgICAgcGFzdGUwKGhvd19tYW55X3BzW1sxXV0sIi0iLA0KICAgICAgICAgICAgICAgICByb3VuZChob3dfbWFueV9wc1tbMV1dL24qMTAwLDApLCIlIikgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICkgJT4lDQogIHVubmVzdF93aWRlcigtcXVlc3QpICU+JSAjcGFydGljdWxhciB0cmlja2VzICh0aGVyZSBpcyBhIGxvdCBvZiBwc2V1ZG8gbWlzc2luZyB2YWx1ZXMpDQogIHNlbGVjdChxdWVzdCxob3dfbWFueV9wczpsYXN0X2NvbCgpLCAtaG93X21hbnlfcHMpICU+JSAgI2dldCBzb21lIHZhcmlhYmxlcw0KICBwaXZvdF9sb25nZXIoLXF1ZXN0KSAlPiUgICNub3cgdHJhbnNmb3JtIHRvIHRoZSBsb25nIGZvcm1hdA0KICBmaWx0ZXIodmFsdWUgIT0gIk5BLU5BJSIpICU+JSAjZmlsdGVyDQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBxdWVzdCwgbmFtZXNfZnJvbSA9IG5hbWUsIHZhbHVlc19mcm9tID0gdmFsdWUpDQpgYGANCg0KDQoNCiMjIyBEb3VibGUgY2hlY2sNCg0KYGBge3J9DQpkcyAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSAyKSAlPiUgDQogIGZpbHRlcihjX3N1bSA+IDEzLjQwMTIyMTEgJiBjX3N1bSA8PSAJMjcuODIyNDEgKSAlPiUgDQogIGNvdW50KCkNCg0KZHMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gNCkgJT4lIA0KICBmaWx0ZXIoY19zdW0gPiAzMC41NDI4OTcgJiBjX3N1bSA8PSAJNDAuMzg4NjYpICU+JSANCiAgY291bnQoKQ0KDQpkcyAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSA2KSAlPiUgDQogIGZpbHRlcihjX3N1bSA+IDI4LjM4NTk1NzMgJiBjX3N1bSA8PSAJMzguMDQ2NDgpICU+JSANCiAgY291bnQoKQ0KDQpkcyAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSAyKSAlPiUgDQogIGZpbHRlcihnbV9zdW0gPiAzOC4yNjE5NzUyICYgZ21fc3VtIDw9IAk0Ni4wNTA1ICkgJT4lIA0KICBjb3VudCgpDQoNCmRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDM2KSAlPiUgDQogIGZpbHRlcihjZ19zdW0gPiAyMy4zODg3MjgyICYgY2dfc3VtIDw9IAkzNS45NTAyOSApICU+JSANCiAgY291bnQoKQ0KDQpkcyAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSAyNCkgJT4lIA0KICBmaWx0ZXIoY2dfc3VtIDwgMTguMTQpDQpgYGANCg0KIyMjIEZpeGluZyBhdCB6ZXJvIGNvbW0NCg0KYGBge3J9DQpkcyAlPiUgDQogIGZpbHRlcihxdWVzdCAlaW4lIGMoMTgsMjAsMjIpKSAlPiUgDQogIGdyb3VwX2J5KHF1ZXN0KSAlPiUgDQogIG11dGF0ZShjemVybyA9IGlmZWxzZShjX3N1bSA8PSAwLDEsMCkpICU+JSANCiAgc2VsZWN0KGN6ZXJvLCBldmVyeXRoaW5nKCkpICU+JSANCiAgc3VtbWFyaXNlKG49bigpLCBzdW0oY3plcm8pLCBzdW0oY3plcm8pL24pDQogIA0KICBzZWxlY3QoKQ0KYGBgDQoNCg0KIyMjIFBlcmNlbnRhZ2UgbW9uaXRvcg0KDQpgYGB7cn0NCmRzICU+JQ0KICBzZWxlY3QoaWQsIHF1ZXN0LCBlbmRzX3dpdGgoInN1bSIpKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKC1jKGlkLCBxdWVzdCkpICU+JSAjdHJhbmZvcm0gaW50byAgbG9uZyBmb3JtYXQNCiAgbmVzdF9ieShxdWVzdCwgbmFtZSkgJT4lICNuZXN0IChpZCB3aWxsIG5vdCBiZSB1c2VkIHRoaXMgdGltZSkNCiAgI2hlcmUgaXMgdGhlIHRyaWNrLiBhbGwgY291bnRzIGFyZSBoZXJlDQogIG11dGF0ZSgNCiAgICBuID0gbWFwX2RibChkYXRhWzJdLCB+bnJvdyhkYXRhLmZyYW1lKC4pKSksICNjb21wdXRlIHNhbXBsZSBzaXplDQogICAgbWVhbiA9IG1hcF9kYmwoZGF0YVsyXSwgfm1lYW4oLikpLCAjZ2V0IHRoZSBST0JVU1QgbWVhbnMNCiAgICBzZCA9IG1hcF9kYmwoZGF0YVsyXSwgIH5zZCguKSksICNnZXQgdGhlIFJPQlVTVCBzZA0KICAgIG9uZV9iZWxvdyA9IG1lYW4tc2QsICMxIGJlbG93DQogICAgdHdvX2JlbG93ID0gbWVhbiAtIDIgKiBzZCwNCiAgICBtb25pdG9yID0gc3VtKG9uZV9iZWxvdyA+PSBkYXRhW1syXV0gJiB0d29fYmVsb3cgPCBkYXRhW1syXV0pL24sDQogICAgYmVsb3cgPSBzdW0odHdvX2JlbG93ID4gZGF0YVtbMl1dKS9uKSAlPiUgDQogICNvdXRzaWRlIG9mIHRoZSBtYXAsIGFkZCBhIG5ldyB2YXJpYWJsZSB0byBuZXN0ZWQgZGF0YQ0KICBtdXRhdGUoZGF0YSA9IGxpc3QoZGF0YSAlPiUgbXV0YXRlKGFyZWFfbW9uaXRvciA9IGlmZWxzZShkYXRhW1syXV0gPiB0d29fYmVsb3cgJiBkYXRhW1syXV0gPD0gb25lX2JlbG93LCBwYXN0ZTAobmFtZSksMCkpKSkgJT4lIA0KICB1bm5lc3QoZGF0YSkgJT4lICNJJ2xsIHVubmVzdCBhbmQgZ2V0IGFnYWluIHRoZSBpZHMuIG15IGRmIHdpbGwgYmUgdmVyeSBsb25nDQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKGlkLCBxdWVzdCksIG5hbWVzX2Zyb20gPSBjKGFyZWFfbW9uaXRvciksIHZhbHVlc19mbiA9IGxlbmd0aCkgJT4lICNub3cgSSdsbCBncm91cCBieSBpZHMhISBteSBkZiB3aWxsIGJlIHNhbXBsZSBzaXplICogcXVlc3QNCiAgdW5ncm91cCgpICU+JSAjZW5kIG9mIGZ1bmN0aW9uIA0KICAjbm93IEknbGwgY291bnQgdmFsdWVzDQogIG11dGF0ZShob3dfbWFueSA9IHNlbGVjdCguLGVuZHNfd2l0aCgiX3N1bSIpKSAlPiUgcm93U3VtcyguLCBuYS5ybSA9IFQpKSAlPiUgDQogICNub3cgSSdsbCBwcmVzZW50IHRoZSByZXN1bHRzDQogIHRhYnlsKHF1ZXN0LCBob3dfbWFueSklPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICMgYWRvcm5fdG90YWxzKGMoInJvdyIsICJjb2wiKSkgJT4lIA0KICAjYWRvcm5fcGVyY2VudGFnZXMoInJvdyIpICU+JQ0KICAjYWRvcm5fcGN0X2Zvcm1hdHRpbmcoZGlnaXRzID0gMikgJT4lDQogICNhZG9ybl9ucygpICMgDQogIHBpdm90X2xvbmdlcigtcXVlc3QpICU+JQ0KICBncm91cF9ieShxdWVzdCkgJT4lIA0KICBtdXRhdGUocHJvcCA9IHByb3AudGFibGUodmFsdWUpKSAlPiUNCiAgdW5ncm91cCgpJT4lIA0KICBnZ3Bsb3QoLiwgYWVzKHggPSBuYW1lLCB5ID0gcHJvcCwgZ3JvdXA9cXVlc3QsIGNvbG9yID0gcXVlc3QsIGxhYmVsPXF1ZXN0KSkgKw0KICBzdGF0X3N1bW1hcnkoZ2VvbSA9ICJsaW5lIiwgZnVuID0gbWVhbiwgc2l6ZT0xKSArDQogICNnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoZGF0YSA9IC4gJT4lIGZpbHRlcihuYW1lID09ICIwIiksIGJveC5wYWRkaW5nID0gMC41LCBtYXgub3ZlcmxhcHMgPSBJbmYpICsNCiAgbGFicyh4ID0gIkRvbWFpbnMgYXQgdGhlIG1vbml0b3Jpbmcgem9uZSIsIHkgPSAiUHJvcG9ydGlvbiIsIGNvbG9yID0gIlF1ZXN0aW9ubmFpcmUiKSArDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCmBgYA0KDQoNCg0KIyMjIFBlcmNlbnRhZ2UgYmVsb3cNCg0KYGBge3J9DQpkcyAlPiUNCiAgc2VsZWN0KGlkLCBxdWVzdCwgZW5kc193aXRoKCJzdW0iKSkgJT4lDQogIHBpdm90X2xvbmdlcigtYyhpZCwgcXVlc3QpKSAlPiUgI3RyYW5mb3JtIGludG8gIGxvbmcgZm9ybWF0DQogIG5lc3RfYnkocXVlc3QsIG5hbWUpICU+JSAjbmVzdCAoaWQgd2lsbCBub3QgYmUgdXNlZCB0aGlzIHRpbWUpDQogICNoZXJlIGlzIHRoZSB0cmljay4gYWxsIGNvdW50cyBhcmUgaGVyZQ0KICBtdXRhdGUoDQogICAgbiA9IG1hcF9kYmwoZGF0YVsyXSwgfm5yb3coZGF0YS5mcmFtZSguKSkpLCAjY29tcHV0ZSBzYW1wbGUgc2l6ZQ0KICAgIG1lYW4gPSBtYXBfZGJsKGRhdGFbMl0sIH5tZWFuKC4pKSwgI2dldCB0aGUgUk9CVVNUIG1lYW5zDQogICAgc2QgPSBtYXBfZGJsKGRhdGFbMl0sICB+c2QoLikpLCAjZ2V0IHRoZSBST0JVU1Qgc2QNCiAgICBvbmVfYmVsb3cgPSBtZWFuLXNkLCAjMSBiZWxvdw0KICAgIHR3b19iZWxvdyA9IG1lYW4gLSAyICogc2QsDQogICAgbW9uaXRvciA9IHN1bShvbmVfYmVsb3cgPj0gZGF0YVtbMl1dICYgdHdvX2JlbG93IDwgZGF0YVtbMl1dKS9uLA0KICAgIGJlbG93ID0gc3VtKHR3b19iZWxvdyA+IGRhdGFbWzJdXSkvbikgJT4lIA0KICAjb3V0c2lkZSBvZiB0aGUgbWFwLCBhZGQgYSBuZXcgdmFyaWFibGUgdG8gbmVzdGVkIGRhdGENCiAgbXV0YXRlKGRhdGEgPSBsaXN0KGRhdGEgJT4lIG11dGF0ZShhcmVhX21vbml0b3IgPSBhcy5jaGFyYWN0ZXIoaWZlbHNlKGRhdGFbWzJdXSA8PSB0d29fYmVsb3csIHBhc3RlMChuYW1lKSwwKSkpKSkgJT4lICNhdHRlbnRpb24gaGVyZQ0KICB1bm5lc3QoZGF0YSkgJT4lICNJJ2xsIHVubmVzdCBhbmQgZ2V0IGFnYWluIHRoZSBpZHMuIG15IGRmIHdpbGwgYmUgdmVyeSBsb25nDQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKGlkLCBxdWVzdCksIG5hbWVzX2Zyb20gPSBjKGFyZWFfbW9uaXRvciksIHZhbHVlc19mbiA9IGxlbmd0aCkgJT4lICNub3cgSSdsbCBncm91cCBieSBpZHMhISBteSBkZiB3aWxsIGJlIHNhbXBsZSBzaXplICogcXVlc3QNCiAgdW5ncm91cCgpICU+JSAjZW5kIG9mIGZ1bmN0aW9uIA0KICAjbm93IEknbGwgY291bnQgdmFsdWVzDQogIG11dGF0ZShob3dfbWFueSA9IHNlbGVjdCguLGVuZHNfd2l0aCgiX3N1bSIpKSAlPiUgcm93U3VtcyguLCBuYS5ybSA9IFQpKSAlPiUgDQogICNub3cgSSdsbCBwcmVzZW50IHRoZSByZXN1bHRzDQogIHRhYnlsKHF1ZXN0LCBob3dfbWFueSklPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICBhZG9ybl90b3RhbHMoYygicm93IiwgImNvbCIpKSAlPiUgDQogIGFkb3JuX3BlcmNlbnRhZ2VzKCJyb3ciKSAlPiUNCiAgYWRvcm5fcGN0X2Zvcm1hdHRpbmcoZGlnaXRzID0gMikgJT4lDQogIGFkb3JuX25zKCkgIyANCiAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lDQogIGdyb3VwX2J5KHF1ZXN0KSAlPiUgDQogIG11dGF0ZShwcm9wID0gcHJvcC50YWJsZSh2YWx1ZSkpICU+JQ0KICB1bmdyb3VwKCklPiUgDQogIGdncGxvdCguLCBhZXMoeCA9IG5hbWUsIHkgPSBwcm9wLCBncm91cD1xdWVzdCwgY29sb3IgPSBxdWVzdCwgbGFiZWw9cXVlc3QpKSArDQogIHN0YXRfc3VtbWFyeShnZW9tID0gImxpbmUiLCBmdW4gPSBtZWFuLCBzaXplPTEpICsNCiAgI2dncmVwZWw6Omdlb21fdGV4dF9yZXBlbChkYXRhID0gLiAlPiUgZmlsdGVyKG5hbWUgPT0gIjAiKSwgYm94LnBhZGRpbmcgPSAwLjUsIG1heC5vdmVybGFwcyA9IEluZikgKw0KICBsYWJzKHggPSAiRG9tYWlucyBiZWxvdyB0aGUgY3V0b2ZmIiwgeSA9ICJQcm9wb3J0aW9uIiwgY29sb3IgPSAiUXVlc3Rpb25uYWlyZSIpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQ0KYGBgDQoNCiMjIFJvYnVzdA0KDQpgYGB7cn0NCmRzICU+JSANCiAgc2VsZWN0KHF1ZXN0LCBlbmRzX3dpdGgoInN1bSIpKSAlPiUgDQogIHBpdm90X2xvbmdlcigtcXVlc3QpICU+JSANCiAgbmVzdF9ieShxdWVzdCwgbmFtZSkgJT4lIA0KICBtdXRhdGUoeD1saXN0KG1hcChkYXRhLCB+cHN5Y2g6OmRlc2NyaWJlKC4pKSkpICU+JSANCiAgdW5uZXN0X3dpZGVyKHgpICU+JSANCiAgdW5uZXN0X3dpZGVyKHZhbHVlKSAlPiUgDQogIG11dGF0ZV9pZihpcy5udW1lcmljLCByb3VuZCwgMikNCg0KYGBgDQoNCmBgYHtyfQ0KZHMgJT4lIA0KICBzZWxlY3QocXVlc3QsIGVuZHNfd2l0aCgic3VtIikpICU+JSANCiAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lIA0KICBuZXN0X2J5KHF1ZXN0LCBuYW1lKSAlPiUgDQogIG11dGF0ZSgNCiAgICBxdWVzdGlvbm5haXJlID0gcXVlc3QsDQogICAgbWVhbl9yID0gbGlzdChtYXBfZGJsKGRhdGEsIH5tZWFuKC4sIHRyaW09MC4yNSkpKSwNCiAgICBzZF9yID0gbGlzdChtYXBfZGJsKGRhdGEsIH5jaGVtb21ldHJpY3M6OnNkX3RyaW0oLiwgdHJpbT0wLjI1LCBjb25zdCA9IFRSVUUpKSksDQogICAgbV8xc2QgPSBtZWFuX3Itc2RfciwNCiAgICBtXzFfaGFsZl9zZCA9IG1lYW5fci0xLjUqc2RfciwNCiAgICBtXzJzZCA9IG1lYW5fci0yKnNkX3IpICU+JSANCiAgdW5uZXN0KC1kYXRhKSAlPiUgDQogICN1bm5lc3Rfd2lkZXIoLXF1ZXN0KSAlPiUgDQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBxdWVzdCwgbmFtZXNfZnJvbSA9IG5hbWUsIHZhbHVlc19mcm9tID0gbWVhbl9yOm1fMnNkKSAlPiUgDQogIG11dGF0ZV9pZihpcy5udW1lcmljLCByb3VuZCwgMikNCmBgYA0KDQoNCg0KIyMgUGVyZm9ybWFuY2Ugb2YgdGhlIGN1dG9mZg0KDQojIyMgTW9uaXRvcmluZyB6b25lDQoNCmBgYHtyfQ0KZHMgJT4lIA0KICBzZWxlY3QocXVlc3QsIGVuZHNfd2l0aCgic3VtIikpICU+JSANCiAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lIA0KICBuZXN0X2J5KHF1ZXN0LCBuYW1lKSAlPiUgDQogIG11dGF0ZSgNCiAgICBxdWVzdGlvbm5haXJlID0gcXVlc3QsDQogICAgbiA9IGxpc3QobWFwX2RibChkYXRhLCB+bnJvdyhkYXRhLmZyYW1lKC4pKSkpLA0KICAgIG1lYW5fciA9IGxpc3QobWFwX2RibChkYXRhLCB+bWVhbiguLCB0cmltPTAuMjUpKSksDQogICAgc2RfciA9IGxpc3QobWFwX2RibChkYXRhLCB+Y2hlbW9tZXRyaWNzOjpzZF90cmltKC4sIHRyaW09MC4yNSwgY29uc3QgPSBUUlVFKSkpLA0KICAgIG1fMXNkID0gbWVhbl9yLXNkX3IsDQogICAgbV8xX2hhbGZfc2QgPSBtZWFuX3ItMS41KnNkX3IsDQogICAgbV8yc2QgPSBtZWFuX3ItMipzZF9yLA0KICAgIGhvd19tYW55X2MgPSBtYXAoZGF0YSwgfiBpZmVsc2UobmFtZSA9PSAiY19zdW0iLCAjaSdsbCBjb3VudCBob3cgbWFueSBwYXJ0aWNpcGFudHMgYXJlIGJlbG93DQogICAgICBkcyAlPiUgDQogICAgICAgIGZpbHRlcihxdWVzdCA9PSBxdWVzdGlvbm5haXJlKSAlPiUgDQogICAgICAgIGZpbHRlcihjX3N1bSA+IG1fMnNkICYgY19zdW0gPD0gbV8xc2QpICU+JSANCiAgICAgICAgc3VtbWFyaXNlKG4oKSksDQogICAgICBOQV9pbnRlZ2VyXykpLCAjIHBlcmNlbnRhZ2Ugb2YgY29tbXVuaWNhdGlvbg0KICAgIA0KICAgIGhvd19tYW55X2dtID0gbWFwKGRhdGEsIH4gaWZlbHNlKG5hbWUgPT0gImdtX3N1bSIsDQogICAgICBkcyAlPiUgDQogICAgICAgIGZpbHRlcihxdWVzdCA9PSBxdWVzdGlvbm5haXJlKSAlPiUgDQogICAgICAgIGZpbHRlcihnbV9zdW0gPiBtXzJzZCAmIGdtX3N1bSA8PSBtXzFzZCkgJT4lIA0KICAgICAgICBzdW1tYXJpc2UobigpKSwgI3BlcmNlbnRhZ2Ugb2YgZ3Jvc3MgbW90b3INCiAgICBOQV9pbnRlZ2VyXykpLA0KICAgIA0KICAgIGhvd19tYW55X2ZtID0gbWFwKGRhdGEsIH4gaWZlbHNlKG5hbWUgPT0gImZtX3N1bSIsDQogICAgICBkcyAlPiUgDQogICAgICAgIGZpbHRlcihxdWVzdCA9PSBxdWVzdGlvbm5haXJlKSAlPiUgDQogICAgICAgIGZpbHRlcihmbV9zdW0gPiBtXzJzZCAmIGZtX3N1bSA8PSBtXzFzZCkgJT4lIA0KICAgICAgICBzdW1tYXJpc2UobigpKSwjcGVyY2VudGFnZSBvZiBmaW5lIG1vdG9yDQogICAgICBOQV9pbnRlZ2VyXykpLCANCiAgICANCiAgICBob3dfbWFueV9jZyA9IG1hcChkYXRhLCB+IGlmZWxzZShuYW1lID09ICJjZ19zdW0iLA0KICAgICAgZHMgJT4lIA0KICAgICAgICBmaWx0ZXIocXVlc3QgPT0gcXVlc3Rpb25uYWlyZSkgJT4lIA0KICAgICAgICBmaWx0ZXIoY2dfc3VtID4gbV8yc2QgJiBjZ19zdW0gPD0gbV8xc2QpICU+JSANCiAgICAgICAgc3VtbWFyaXNlKG4oKSksICNwZXJjZW50YWdlIG9mIHByb2JsZW0tc29sdmluZw0KICAgIE5BX2ludGVnZXJfKSksIA0KDQogICAgaG93X21hbnlfcHMgPSBtYXAoZGF0YSwgfiBpZmVsc2UobmFtZSA9PSAicHNfc3VtIiwNCiAgICAgIGRzICU+JSANCiAgICAgICAgZmlsdGVyKHF1ZXN0ID09IHF1ZXN0aW9ubmFpcmUpICU+JSANCiAgICAgICAgZmlsdGVyKHBzX3N1bSA+IG1fMnNkICYgcHNfc3VtIDw9IG1fMXNkKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZShuKCkpLCAjcGVyY2VudGFnZSBvZiBwZXJzb25hbCBzb2NpYWwNCiAgICAgICAgTkFfaW50ZWdlcl8pKSkgICU+JSANCiAgbXV0YXRlKG5fY29tPQ0KICAgICAgICAgICBwYXN0ZTAoaG93X21hbnlfY1tbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfY1tbMV1dL24qMTAwLDApLCIlIiksICNJJ2xsIGdldCB0aGUgcGVyY2VudGFnZXMNCiAgICAgICAgIG5fZ209DQogICAgICAgICAgIHBhc3RlMChob3dfbWFueV9nbVtbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfZ21bWzFdXS9uKjEwMCwwKSwiJSIpLA0KICAgICAgICAgbl9mbT0NCiAgICAgICAgICAgcGFzdGUwKGhvd19tYW55X2ZtW1sxXV0sIi0iLA0KICAgICAgICAgICAgICAgICByb3VuZChob3dfbWFueV9mbVtbMV1dL24qMTAwLDApLCIlIiksDQogICAgICAgICBuX2NnPQ0KICAgICAgICAgICBwYXN0ZTAoaG93X21hbnlfY2dbWzFdXSwiLSIsDQogICAgICAgICAgICAgICAgIHJvdW5kKGhvd19tYW55X2NnW1sxXV0vbioxMDAsMCksIiUiKSwNCiAgICAgICAgIG5fcHM9DQogICAgICAgICAgIHBhc3RlMChob3dfbWFueV9wc1tbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfcHNbWzFdXS9uKjEwMCwwKSwiJSIpICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICApICU+JQ0KICB1bm5lc3Rfd2lkZXIoLXF1ZXN0KSAlPiUgI3BhcnRpY3VsYXIgdHJpY2tlcyAodGhlcmUgaXMgYSBsb3Qgb2YgcHNldWRvIG1pc3NpbmcgdmFsdWVzKQ0KICBzZWxlY3QocXVlc3QsaG93X21hbnlfcHM6bGFzdF9jb2woKSwgLWhvd19tYW55X3BzKSAlPiUgICNnZXQgc29tZSB2YXJpYWJsZXMNCiAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lICAjbm93IHRyYW5zZm9ybSB0byB0aGUgbG9uZyBmb3JtYXQNCiAgZmlsdGVyKHZhbHVlICE9ICJOQS1OQSUiKSAlPiUgI2ZpbHRlcg0KICBwaXZvdF93aWRlcihpZF9jb2xzID0gcXVlc3QsIG5hbWVzX2Zyb20gPSBuYW1lLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKQ0KDQpgYGANCg0KIyMjIEJlbG93IHRoZSBjdXRvZmYNCg0KYGBge3J9DQpkcyAlPiUgDQogIHNlbGVjdChxdWVzdCwgZW5kc193aXRoKCJzdW0iKSkgJT4lIA0KICBwaXZvdF9sb25nZXIoLXF1ZXN0KSAlPiUgDQogIG5lc3RfYnkocXVlc3QsIG5hbWUpICU+JSANCiAgbXV0YXRlKA0KICAgIHF1ZXN0aW9ubmFpcmUgPSBxdWVzdCwNCiAgICBuID0gbGlzdChtYXBfZGJsKGRhdGEsIH5ucm93KGRhdGEuZnJhbWUoLikpKSksDQogICAgbWVhbl9yID0gbGlzdChtYXBfZGJsKGRhdGEsIH5tZWFuKC4sIHRyaW09MC4yNSkpKSwNCiAgICBzZF9yID0gbGlzdChtYXBfZGJsKGRhdGEsIH5jaGVtb21ldHJpY3M6OnNkX3RyaW0oLiwgdHJpbT0wLjI1LCBjb25zdCA9IFRSVUUpKSksDQogICAgbV8xc2QgPSBtZWFuX3Itc2RfciwNCiAgICBtXzFfaGFsZl9zZCA9IG1lYW5fci0xLjUqc2RfciwNCiAgICBtXzJzZCA9IG1lYW5fci0yKnNkX3IsDQogICAgICAgIGhvd19tYW55X2MgPSBtYXAoZGF0YSwgfiBpZmVsc2UobmFtZSA9PSAiY19zdW0iLCAjaSdsbCBjb3VudCBob3cgbWFueSBwYXJ0aWNpcGFudHMgYXJlIGJlbG93DQogICAgICBkcyAlPiUgDQogICAgICAgIGZpbHRlcihxdWVzdCA9PSBxdWVzdGlvbm5haXJlKSAlPiUgDQogICAgICAgIGZpbHRlcihjX3N1bSAgPD0gbV8yc2QpICU+JSAgI2F0dGVudGlvbiBoZXJlIQ0KICAgICAgICBzdW1tYXJpc2UobigpKSwNCiAgICAgIE5BX2ludGVnZXJfKSksICMgcGVyY2VudGFnZSBvZiBjb21tdW5pY2F0aW9uDQogICAgDQogICAgaG93X21hbnlfZ20gPSBtYXAoZGF0YSwgfiBpZmVsc2UobmFtZSA9PSAiZ21fc3VtIiwNCiAgICAgIGRzICU+JSANCiAgICAgICAgZmlsdGVyKHF1ZXN0ID09IHF1ZXN0aW9ubmFpcmUpICU+JSANCiAgICAgICAgZmlsdGVyKGdtX3N1bSA8PSBtXzJzZCkgJT4lIA0KICAgICAgICBzdW1tYXJpc2UobigpKSwgI3BlcmNlbnRhZ2Ugb2YgZ3Jvc3MgbW90b3INCiAgICBOQV9pbnRlZ2VyXykpLA0KICAgIA0KICAgIGhvd19tYW55X2ZtID0gbWFwKGRhdGEsIH4gaWZlbHNlKG5hbWUgPT0gImZtX3N1bSIsDQogICAgICBkcyAlPiUgDQogICAgICAgIGZpbHRlcihxdWVzdCA9PSBxdWVzdGlvbm5haXJlKSAlPiUgDQogICAgICAgIGZpbHRlcihmbV9zdW0gPD0gbV8yc2QpICU+JSANCiAgICAgICAgc3VtbWFyaXNlKG4oKSksI3BlcmNlbnRhZ2Ugb2YgZmluZSBtb3Rvcg0KICAgICAgTkFfaW50ZWdlcl8pKSwgDQogICAgDQogICAgaG93X21hbnlfY2cgPSBtYXAoZGF0YSwgfiBpZmVsc2UobmFtZSA9PSAiY2dfc3VtIiwNCiAgICAgIGRzICU+JSANCiAgICAgICAgZmlsdGVyKHF1ZXN0ID09IHF1ZXN0aW9ubmFpcmUpICU+JSANCiAgICAgICAgZmlsdGVyKGNnX3N1bSA8PSBtXzJzZCkgJT4lIA0KICAgICAgICBzdW1tYXJpc2UobigpKSwgI3BlcmNlbnRhZ2Ugb2YgcHJvYmxlbS1zb2x2aW5nDQogICAgTkFfaW50ZWdlcl8pKSwgDQoNCiAgICBob3dfbWFueV9wcyA9IG1hcChkYXRhLCB+IGlmZWxzZShuYW1lID09ICJwc19zdW0iLA0KICAgICAgZHMgJT4lIA0KICAgICAgICBmaWx0ZXIocXVlc3QgPT0gcXVlc3Rpb25uYWlyZSkgJT4lIA0KICAgICAgICBmaWx0ZXIocHNfc3VtIDw9IG1fMnNkKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZShuKCkpLCAjcGVyY2VudGFnZSBvZiBwZXJzb25hbCBzb2NpYWwNCiAgICAgICAgTkFfaW50ZWdlcl8pKSkgICU+JSANCiAgbXV0YXRlKG5fY29tPQ0KICAgICAgICAgICBwYXN0ZTAoaG93X21hbnlfY1tbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfY1tbMV1dL24qMTAwLDApLCIlIiksICNJJ2xsIGdldCB0aGUgcGVyY2VudGFnZXMNCiAgICAgICAgIG5fZ209DQogICAgICAgICAgIHBhc3RlMChob3dfbWFueV9nbVtbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfZ21bWzFdXS9uKjEwMCwwKSwiJSIpLA0KICAgICAgICAgbl9mbT0NCiAgICAgICAgICAgcGFzdGUwKGhvd19tYW55X2ZtW1sxXV0sIi0iLA0KICAgICAgICAgICAgICAgICByb3VuZChob3dfbWFueV9mbVtbMV1dL24qMTAwLDApLCIlIiksDQogICAgICAgICBuX2NnPQ0KICAgICAgICAgICBwYXN0ZTAoaG93X21hbnlfY2dbWzFdXSwiLSIsDQogICAgICAgICAgICAgICAgIHJvdW5kKGhvd19tYW55X2NnW1sxXV0vbioxMDAsMCksIiUiKSwNCiAgICAgICAgIG5fcHM9DQogICAgICAgICAgIHBhc3RlMChob3dfbWFueV9wc1tbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfcHNbWzFdXS9uKjEwMCwwKSwiJSIpICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICApICU+JQ0KICB1bm5lc3Rfd2lkZXIoLXF1ZXN0KSAlPiUgI3BhcnRpY3VsYXIgdHJpY2tlcyAodGhlcmUgaXMgYSBsb3Qgb2YgcHNldWRvIG1pc3NpbmcgdmFsdWVzKQ0KICBzZWxlY3QocXVlc3QsaG93X21hbnlfcHM6bGFzdF9jb2woKSwgLWhvd19tYW55X3BzKSAlPiUgICNnZXQgc29tZSB2YXJpYWJsZXMNCiAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lICAjbm93IHRyYW5zZm9ybSB0byB0aGUgbG9uZyBmb3JtYXQNCiAgZmlsdGVyKHZhbHVlICE9ICJOQS1OQSUiKSAlPiUgI2ZpbHRlcg0KICBwaXZvdF93aWRlcihpZF9jb2xzID0gcXVlc3QsIG5hbWVzX2Zyb20gPSBuYW1lLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKQ0KYGBgDQoNCg0KIyMjIERvdWJsZSBjaGVjaw0KDQpgYGB7cn0NCmRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDE2KSAlPiUgDQogIGZpbHRlcihnbV9zdW0gPiA1NS40OSAmIGdtX3N1bSA8PSA1Ny4yNCkNCmBgYA0KDQoNCmBgYHtyfQ0KZHMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gMikgJT4lIA0KICBmaWx0ZXIoY19zdW0gPD0gNDkuMTcgJiBjX3N1bSA+IDQzLjYyKQ0KYGBgDQpgYGB7cn0NCmRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDE4KSAlPiUgDQogIGZpbHRlcihmbV9zdW0gPCA0NS4zOCAmIGZtX3N1bSA8PSA0OS44KQ0KYGBgDQoNCiMjIyBQZXJjZW50YWdlIG1vbml0b3INCg0KYGBge3J9DQpkcyAlPiUNCiAgc2VsZWN0KGlkLCBxdWVzdCwgZW5kc193aXRoKCJzdW0iKSkgJT4lDQogIHBpdm90X2xvbmdlcigtYyhpZCwgcXVlc3QpKSAlPiUgI3RyYW5mb3JtIGludG8gIGxvbmcgZm9ybWF0DQogIG5lc3RfYnkocXVlc3QsIG5hbWUpICU+JSAjbmVzdCAoaWQgd2lsbCBub3QgYmUgdXNlZCB0aGlzIHRpbWUpDQogICNoZXJlIGlzIHRoZSB0cmljay4gYWxsIGNvdW50cyBhcmUgaGVyZQ0KICBtdXRhdGUoDQogICAgbiA9IG1hcF9kYmwoZGF0YVsyXSwgfm5yb3coZGF0YS5mcmFtZSguKSkpLCAjY29tcHV0ZSBzYW1wbGUgc2l6ZQ0KICAgIG1lYW4gPSBtYXBfZGJsKGRhdGFbMl0sIH5tZWFuKC4sIHRyaW0gPSAwLjI1KSksICNnZXQgdGhlIFJPQlVTVCBtZWFucw0KICAgIHNkID0gbWFwX2RibChkYXRhWzJdLCAgIH5jaGVtb21ldHJpY3M6OnNkX3RyaW0oLiwgdHJpbT0wLjI1LCBjb25zdCA9IFRSVUUpKSwgI2dldCB0aGUgUk9CVVNUIHNkDQogICAgb25lX2JlbG93ID0gbWVhbi1zZCwgIzEgYmVsb3cNCiAgICB0d29fYmVsb3cgPSBtZWFuIC0gMiAqIHNkLA0KICAgIG1vbml0b3IgPSBzdW0ob25lX2JlbG93ID49IGRhdGFbWzJdXSAmIHR3b19iZWxvdyA8IGRhdGFbWzJdXSkvbiwNCiAgICBiZWxvdyA9IHN1bSh0d29fYmVsb3cgPiBkYXRhW1syXV0pL24pICU+JSANCiAgI291dHNpZGUgb2YgdGhlIG1hcCwgYWRkIGEgbmV3IHZhcmlhYmxlIHRvIG5lc3RlZCBkYXRhDQogIG11dGF0ZShkYXRhID0gbGlzdChkYXRhICU+JSBtdXRhdGUoYXJlYV9tb25pdG9yID0gYXMuY2hhcmFjdGVyKGlmZWxzZShkYXRhW1syXV0gPiB0d29fYmVsb3cgJiBkYXRhW1syXV0gPD0gb25lX2JlbG93LCBwYXN0ZTAobmFtZSksMCkpKSkpICU+JSANCiAgdW5uZXN0KGRhdGEpICU+JSAjSSdsbCB1bm5lc3QgYW5kIGdldCBhZ2FpbiB0aGUgaWRzLiBteSBkZiB3aWxsIGJlIHZlcnkgbG9uZw0KICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhpZCwgcXVlc3QpLCBuYW1lc19mcm9tID0gYyhhcmVhX21vbml0b3IpLCB2YWx1ZXNfZm4gPSBsZW5ndGgpICU+JSAjbm93IEknbGwgZ3JvdXAgYnkgaWRzISEgbXkgZGYgd2lsbCBiZSBzYW1wbGUgc2l6ZSAqIHF1ZXN0DQogIHVuZ3JvdXAoKSAlPiUgI2VuZCBvZiBmdW5jdGlvbiANCiAgI25vdyBJJ2xsIGNvdW50IHZhbHVlcw0KICBtdXRhdGUoaG93X21hbnkgPSBzZWxlY3QoLixlbmRzX3dpdGgoIl9zdW0iKSkgJT4lIHJvd1N1bXMoLiwgbmEucm0gPSBUKSkgJT4lIA0KICAjbm93IEknbGwgcHJlc2VudCB0aGUgcmVzdWx0cw0KICB0YWJ5bChxdWVzdCwgaG93X21hbnkpJT4lIA0KICBhZG9ybl90b3RhbHMoYygicm93IiwgImNvbCIpKSAlPiUgDQogIGFkb3JuX3BlcmNlbnRhZ2VzKCJyb3ciKSAlPiUNCiAgYWRvcm5fcGN0X2Zvcm1hdHRpbmcoZGlnaXRzID0gMikgJT4lDQogIGFkb3JuX25zKCkgIyANCiAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lDQogIGdyb3VwX2J5KHF1ZXN0KSAlPiUgDQogIG11dGF0ZShwcm9wID0gcHJvcC50YWJsZSh2YWx1ZSkpICU+JQ0KICB1bmdyb3VwKCklPiUgDQogIGdncGxvdCguLCBhZXMoeCA9IG5hbWUsIHkgPSBwcm9wLCBncm91cD1xdWVzdCwgY29sb3IgPSBxdWVzdCwgbGFiZWw9cXVlc3QpKSArDQogIHN0YXRfc3VtbWFyeShnZW9tID0gImxpbmUiLCBmdW4gPSBtZWFuLCBzaXplPTEpICsNCiAgI2dncmVwZWw6Omdlb21fdGV4dF9yZXBlbChkYXRhID0gLiAlPiUgZmlsdGVyKG5hbWUgPT0gIjAiKSwgYm94LnBhZGRpbmcgPSAwLjUsIG1heC5vdmVybGFwcyA9IEluZikgKw0KICBsYWJzKHggPSAiRG9tYWlucyBhdCB0aGUgbW9uaXRvcmluZyB6b25lIiwgeSA9ICJQcm9wb3J0aW9uIiwgY29sb3IgPSAiUXVlc3Rpb25uYWlyZSIpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQ0KYGBgDQoNCg0KDQojIyMgUGVyY2VudGFnZSBiZWxvdw0KDQpgYGB7cn0NCmRzICU+JQ0KICBzZWxlY3QoaWQsIHF1ZXN0LCBlbmRzX3dpdGgoInN1bSIpKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKC1jKGlkLCBxdWVzdCkpICU+JSAjdHJhbmZvcm0gaW50byAgbG9uZyBmb3JtYXQNCiAgbmVzdF9ieShxdWVzdCwgbmFtZSkgJT4lICNuZXN0IChpZCB3aWxsIG5vdCBiZSB1c2VkIHRoaXMgdGltZSkNCiAgI2hlcmUgaXMgdGhlIHRyaWNrLiBhbGwgY291bnRzIGFyZSBoZXJlDQogIG11dGF0ZSgNCiAgICBuID0gbWFwX2RibChkYXRhWzJdLCB+bnJvdyhkYXRhLmZyYW1lKC4pKSksICNjb21wdXRlIHNhbXBsZSBzaXplDQogICAgbWVhbiA9IG1hcF9kYmwoZGF0YVsyXSwgfm1lYW4oLiwgdHJpbSA9IDAuMjUpKSwgI2dldCB0aGUgUk9CVVNUIG1lYW5zDQogICAgc2QgPSBtYXBfZGJsKGRhdGFbMl0sICAgfmNoZW1vbWV0cmljczo6c2RfdHJpbSguLCB0cmltPTAuMjUsIGNvbnN0ID0gVFJVRSkpLCAjZ2V0IHRoZSBST0JVU1Qgc2QNCiAgICBvbmVfYmVsb3cgPSBtZWFuLXNkLCAjMSBiZWxvdw0KICAgIHR3b19iZWxvdyA9IG1lYW4gLSAyICogc2QpICU+JSANCiAgI291dHNpZGUgb2YgdGhlIG1hcCwgYWRkIGEgbmV3IHZhcmlhYmxlIHRvIG5lc3RlZCBkYXRhDQogIG11dGF0ZShkYXRhID0gbGlzdChkYXRhICU+JSBtdXRhdGUoYXJlYV9tb25pdG9yID0gYXMuY2hhcmFjdGVyKGlmZWxzZShkYXRhW1syXV0gPD0gdHdvX2JlbG93LCBwYXN0ZTAobmFtZSksMCkpKSkpICU+JSAjaGVyZQ0KICB1bm5lc3QoZGF0YSkgJT4lICNJJ2xsIHVubmVzdCBhbmQgZ2V0IGFnYWluIHRoZSBpZHMuIG15IGRmIHdpbGwgYmUgdmVyeSBsb25nDQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKGlkLCBxdWVzdCksIG5hbWVzX2Zyb20gPSBjKGFyZWFfbW9uaXRvciksIHZhbHVlc19mbiA9IGxlbmd0aCkgJT4lICNub3cgSSdsbCBncm91cCBieSBpZHMhISBteSBkZiB3aWxsIGJlIHNhbXBsZSBzaXplICogcXVlc3QNCiAgdW5ncm91cCgpICU+JSAjZW5kIG9mIGZ1bmN0aW9uIA0KICAjbm93IEknbGwgY291bnQgdmFsdWVzDQogIG11dGF0ZShob3dfbWFueSA9IHNlbGVjdCguLGVuZHNfd2l0aCgiX3N1bSIpKSAlPiUgcm93U3VtcyguLCBuYS5ybSA9IFQpKSAlPiUgDQogICNub3cgSSdsbCBwcmVzZW50IHRoZSByZXN1bHRzDQogIHRhYnlsKHF1ZXN0LCBob3dfbWFueSklPiUgDQogIGFkb3JuX3RvdGFscyhjKCJyb3ciLCAiY29sIikpICU+JSANCiAgYWRvcm5fcGVyY2VudGFnZXMoInJvdyIpICU+JQ0KICBhZG9ybl9wY3RfZm9ybWF0dGluZyhkaWdpdHMgPSAyKSAlPiUNCiAgYWRvcm5fbnMoKSAjIA0KICBwaXZvdF9sb25nZXIoLXF1ZXN0KSAlPiUNCiAgZ3JvdXBfYnkocXVlc3QpICU+JSANCiAgbXV0YXRlKHByb3AgPSBwcm9wLnRhYmxlKHZhbHVlKSkgJT4lDQogIHVuZ3JvdXAoKSU+JSANCiAgZ2dwbG90KC4sIGFlcyh4ID0gbmFtZSwgeSA9IHByb3AsIGdyb3VwPXF1ZXN0LCBjb2xvciA9IHF1ZXN0LCBsYWJlbD1xdWVzdCkpICsNCiAgc3RhdF9zdW1tYXJ5KGdlb20gPSAibGluZSIsIGZ1biA9IG1lYW4sIHNpemU9MSkgKw0KICAjZ2dyZXBlbDo6Z2VvbV90ZXh0X3JlcGVsKGRhdGEgPSAuICU+JSBmaWx0ZXIobmFtZSA9PSAiMCIpLCBib3gucGFkZGluZyA9IDAuNSwgbWF4Lm92ZXJsYXBzID0gSW5mKSArDQogIGxhYnMoeCA9ICJEb21haW5zIGF0IHRoZSBtb25pdG9yaW5nIHpvbmUiLCB5ID0gIlByb3BvcnRpb24iLCBjb2xvciA9ICJRdWVzdGlvbm5haXJlIikgKw0KICB0aGVtZV9idygpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQpgYGANCg0KDQoNCiMjIFBlcmNlbnRpbGVzDQoNCmBgYHtyfQ0KZHMgJT4lICNnZXQgZHMNCiAgc2VsZWN0KHF1ZXN0LCBlbmRzX3dpdGgoInN1bSIpKSAlPiUgI3NlbGVjdCB0aGUgZm9jdXMgdmFyaWFibGVzIA0KICBwaXZvdF9sb25nZXIoLXF1ZXN0KSAlPiUgI3RyYW5zcG9zZSB0byBsb25nIGZvcm1hdGENCiAgbmVzdF9ieShxdWVzdCwgbmFtZSkgJT4lICNncm91cA0KIG11dGF0ZShtZWFuID0gbGlzdChtYXBfZGJsKGRhdGEsIH5tZWFuKC4pKSksDQogICAgICAgICBwXzA1ID0gbGlzdChtYXBfZGJsKGRhdGEsIH5xdWFudGlsZSguLCBwcm9iID0gMC4wNSkpKSwNCiAgICAgICAgIHBfMTAgPSBsaXN0KG1hcF9kYmwoZGF0YSwgfnF1YW50aWxlKC4sIHByb2IgPSAwLjEwKSkpDQogICAgICAgICkgJT4lIA0KICB1bm5lc3QoLWRhdGEpICU+JSAjdW5uZXN0DQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBxdWVzdCwgbmFtZXNfZnJvbSA9IG5hbWUsIHZhbHVlc19mcm9tID0gbWVhbjpwXzEwKSAlPiUgDQogIG11dGF0ZV9pZihpcy5udW1lcmljLCByb3VuZCwgMikNCmBgYA0KDQoNCg0KRG91YmxlIGNoZWNrDQoNCmBgYHtyfQ0KZHMgJT4lIGZpbHRlcihxdWVzdD09MTApICU+JSBzdW1tYXJpc2UoeD1lY2RmKGZtX3N1bSkoMzApKQ0KZHMgJT4lIGZpbHRlcihxdWVzdD09MTApICU+JSBzdW1tYXJpc2UoeD1xdWFudGlsZShmbV9zdW0sIHByb2JzPWMoLjA1KSkpDQpgYGANCg0KIyMgUGVyZm9ybWFuY2Ugb2YgdGhlIGN1dG9mZg0KDQojIyMgQmVsb3cgdGhlIGN1dG9mZg0KDQpgYGB7cn0NCmRzICU+JSANCiAgc2VsZWN0KHF1ZXN0LCBlbmRzX3dpdGgoInN1bSIpKSAlPiUgI2dldCB2YXJpYWJsZSBuYW1lcw0KICBwaXZvdF9sb25nZXIoLXF1ZXN0KSAlPiUgI3RyYW5mb3JtIGludG8gdGhlIGxvbmcgZm9ybWF0DQogIG5lc3RfYnkocXVlc3QsIG5hbWUpICU+JSAjZ3JvdXAgb3IgbmVzdA0KICBtdXRhdGUoDQogICAgcXVlc3Rpb25uYWlyZSA9IHF1ZXN0LCNjb21wdXRlIHF1ZXN0aW9ubmFpcmUNCiAgICBuID0gbGlzdChtYXBfZGJsKGRhdGEsIH5ucm93KGRhdGEuZnJhbWUoLikpKSksICNjb21wdXRlIHNhbXBsZSBzaXplDQogICAgbV8yc2QgPSBsaXN0KG1hcF9kYmwoZGF0YSwgfnF1YW50aWxlKC4sIHByb2IgPSAwLjA1KSkpLCAjMiBiZWxvdyAobm93LCAxMHRoIHBlcmNlbnRpbGUpDQogICAgaG93X21hbnlfYyA9IG1hcChkYXRhLCB+IGlmZWxzZShuYW1lID09ICJjX3N1bSIsICNpJ2xsIGNvdW50IGhvdyBtYW55IHBhcnRpY2lwYW50cyBhcmUgYmVsb3cNCiAgICAgIGRzICU+JSANCiAgICAgICAgZmlsdGVyKHF1ZXN0ID09IHF1ZXN0aW9ubmFpcmUpICU+JSANCiAgICAgICAgZmlsdGVyKGNfc3VtICA8PSBtXzJzZCkgJT4lIA0KICAgICAgICBzdW1tYXJpc2UobigpKSwNCiAgICAgIE5BX2ludGVnZXJfKSksICMgcGVyY2VudGFnZSBvZiBjb21tdW5pY2F0aW9uDQogICAgDQogICAgaG93X21hbnlfZ20gPSBtYXAoZGF0YSwgfiBpZmVsc2UobmFtZSA9PSAiZ21fc3VtIiwNCiAgICAgIGRzICU+JSANCiAgICAgICAgZmlsdGVyKHF1ZXN0ID09IHF1ZXN0aW9ubmFpcmUpICU+JSANCiAgICAgICAgZmlsdGVyKGdtX3N1bSA8PSBtXzJzZCkgJT4lIA0KICAgICAgICBzdW1tYXJpc2UobigpKSwgI3BlcmNlbnRhZ2Ugb2YgZ3Jvc3MgbW90b3INCiAgICBOQV9pbnRlZ2VyXykpLA0KICAgIA0KICAgIGhvd19tYW55X2ZtID0gbWFwKGRhdGEsIH4gaWZlbHNlKG5hbWUgPT0gImZtX3N1bSIsDQogICAgICBkcyAlPiUgDQogICAgICAgIGZpbHRlcihxdWVzdCA9PSBxdWVzdGlvbm5haXJlKSAlPiUgDQogICAgICAgIGZpbHRlcihmbV9zdW0gPD0gbV8yc2QpICU+JSANCiAgICAgICAgc3VtbWFyaXNlKG4oKSksI3BlcmNlbnRhZ2Ugb2YgZmluZSBtb3Rvcg0KICAgICAgTkFfaW50ZWdlcl8pKSwgDQogICAgDQogICAgaG93X21hbnlfY2cgPSBtYXAoZGF0YSwgfiBpZmVsc2UobmFtZSA9PSAiY2dfc3VtIiwNCiAgICAgIGRzICU+JSANCiAgICAgICAgZmlsdGVyKHF1ZXN0ID09IHF1ZXN0aW9ubmFpcmUpICU+JSANCiAgICAgICAgZmlsdGVyKGNnX3N1bSA8PSBtXzJzZCkgJT4lIA0KICAgICAgICBzdW1tYXJpc2UobigpKSwgI3BlcmNlbnRhZ2Ugb2YgcHJvYmxlbS1zb2x2aW5nDQogICAgTkFfaW50ZWdlcl8pKSwgDQoNCiAgICBob3dfbWFueV9wcyA9IG1hcChkYXRhLCB+IGlmZWxzZShuYW1lID09ICJwc19zdW0iLA0KICAgICAgZHMgJT4lIA0KICAgICAgICBmaWx0ZXIocXVlc3QgPT0gcXVlc3Rpb25uYWlyZSkgJT4lIA0KICAgICAgICBmaWx0ZXIocHNfc3VtIDw9IG1fMnNkKSAlPiUgDQogICAgICAgIHN1bW1hcmlzZShuKCkpLCAjcGVyY2VudGFnZSBvZiBwZXJzb25hbCBzb2NpYWwNCiAgICAgICAgTkFfaW50ZWdlcl8pKSkgICU+JSANCiAgbXV0YXRlKG5fY29tPQ0KICAgICAgICAgICBwYXN0ZTAoaG93X21hbnlfY1tbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfY1tbMV1dL24qMTAwLDApLCIlIiksICNJJ2xsIGdldCB0aGUgcGVyY2VudGFnZXMNCiAgICAgICAgIG5fZ209DQogICAgICAgICAgIHBhc3RlMChob3dfbWFueV9nbVtbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfZ21bWzFdXS9uKjEwMCwwKSwiJSIpLA0KICAgICAgICAgbl9mbT0NCiAgICAgICAgICAgcGFzdGUwKGhvd19tYW55X2ZtW1sxXV0sIi0iLA0KICAgICAgICAgICAgICAgICByb3VuZChob3dfbWFueV9mbVtbMV1dL24qMTAwLDApLCIlIiksDQogICAgICAgICBuX2NnPQ0KICAgICAgICAgICBwYXN0ZTAoaG93X21hbnlfY2dbWzFdXSwiLSIsDQogICAgICAgICAgICAgICAgIHJvdW5kKGhvd19tYW55X2NnW1sxXV0vbioxMDAsMCksIiUiKSwNCiAgICAgICAgIG5fcHM9DQogICAgICAgICAgIHBhc3RlMChob3dfbWFueV9wc1tbMV1dLCItIiwNCiAgICAgICAgICAgICAgICAgcm91bmQoaG93X21hbnlfcHNbWzFdXS9uKjEwMCwwKSwiJSIpICAgICAgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICApICU+JQ0KICB1bm5lc3Rfd2lkZXIoLXF1ZXN0KSAlPiUgI3BhcnRpY3VsYXIgdHJpY2tlcyAodGhlcmUgaXMgYSBsb3Qgb2YgcHNldWRvIG1pc3NpbmcgdmFsdWVzKQ0KICBzZWxlY3QocXVlc3QsaG93X21hbnlfcHM6bGFzdF9jb2woKSwgLWhvd19tYW55X3BzKSAlPiUgICNnZXQgc29tZSB2YXJpYWJsZXMNCiAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lICAjbm93IHRyYW5zZm9ybSB0byB0aGUgbG9uZyBmb3JtYXQNCiAgZmlsdGVyKHZhbHVlICE9ICJOQS1OQSUiKSAlPiUgI2ZpbHRlcg0KICBwaXZvdF93aWRlcihpZF9jb2xzID0gcXVlc3QsIG5hbWVzX2Zyb20gPSBuYW1lLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKQ0KYGBgDQoNCiMjIyBQZXJjZW50YWdlIG1vbml0b3INCg0KYGBge3J9DQpkcyAlPiUNCiAgc2VsZWN0KGlkLCBxdWVzdCwgZW5kc193aXRoKCJzdW0iKSkgJT4lDQogIHBpdm90X2xvbmdlcigtYyhpZCwgcXVlc3QpKSAlPiUgI3RyYW5mb3JtIGludG8gIGxvbmcgZm9ybWF0DQogIG5lc3RfYnkocXVlc3QsIG5hbWUpICU+JSAjbmVzdCAoaWQgd2lsbCBub3QgYmUgdXNlZCB0aGlzIHRpbWUpDQogICNoZXJlIGlzIHRoZSB0cmljay4gYWxsIGNvdW50cyBhcmUgaGVyZQ0KICBtdXRhdGUobWVhbiA9IGxpc3QobWFwX2RibChkYXRhWzJdLCB+bWVhbiguKSkpLA0KICAgICAgICAgdHdvX2JlbG93ID0gbGlzdChtYXBfZGJsKGRhdGFbMl0sIH5xdWFudGlsZSguLCBwcm9iID0gMC4wNSkpKSwNCiAgICAgICAgIG9uZV9iZWxvdyA9IGxpc3QobWFwX2RibChkYXRhWzJdLCB+cXVhbnRpbGUoLiwgcHJvYiA9IDAuMTApKSkNCiAgKSAlPiUgDQogICNvdXRzaWRlIG9mIHRoZSBtYXAsIGFkZCBhIG5ldyB2YXJpYWJsZSB0byBuZXN0ZWQgZGF0YQ0KICBtdXRhdGUoZGF0YSA9IGxpc3QoZGF0YSAlPiUgbXV0YXRlKGFyZWFfbW9uaXRvciA9IGFzLmNoYXJhY3RlcihpZmVsc2UoZGF0YVtbMl1dID4gdHdvX2JlbG93ICYgZGF0YVtbMl1dIDw9IG9uZV9iZWxvdywgcGFzdGUwKG5hbWUpLDApKSkpKSAlPiUgDQogIHVubmVzdChkYXRhKSAlPiUgI0knbGwgdW5uZXN0IGFuZCBnZXQgYWdhaW4gdGhlIGlkcy4gbXkgZGYgd2lsbCBiZSB2ZXJ5IGxvbmcNCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoaWQsIHF1ZXN0KSwgbmFtZXNfZnJvbSA9IGMoYXJlYV9tb25pdG9yKSwgdmFsdWVzX2ZuID0gbGVuZ3RoKSAlPiUgI25vdyBJJ2xsIGdyb3VwIGJ5IGlkcyEhIG15IGRmIHdpbGwgYmUgc2FtcGxlIHNpemUgKiBxdWVzdA0KICB1bmdyb3VwKCkgJT4lICNlbmQgb2YgZnVuY3Rpb24gDQogICNub3cgSSdsbCBjb3VudCB2YWx1ZXMNCiAgbXV0YXRlKGhvd19tYW55ID0gc2VsZWN0KC4sZW5kc193aXRoKCJfc3VtIikpICU+JSByb3dTdW1zKC4sIG5hLnJtID0gVCkpICU+JSANCiAgI25vdyBJJ2xsIHByZXNlbnQgdGhlIHJlc3VsdHMNCiAgdGFieWwocXVlc3QsIGhvd19tYW55KSU+JSANCiAgYXMuZGF0YS5mcmFtZSgpICU+JSANCiAgI2Fkb3JuX3RvdGFscyhjKCJyb3ciLCAiY29sIikpICU+JSANCiAgI2Fkb3JuX3BlcmNlbnRhZ2VzKCJyb3ciKSAlPiUNCiAgI2Fkb3JuX3BjdF9mb3JtYXR0aW5nKGRpZ2l0cyA9IDIpICU+JQ0KICAjYWRvcm5fbnMoKSANCiAgcGl2b3RfbG9uZ2VyKC1xdWVzdCkgJT4lDQogIGdyb3VwX2J5KHF1ZXN0KSAlPiUgDQogIG11dGF0ZShwcm9wID0gcHJvcC50YWJsZSh2YWx1ZSkpICU+JQ0KICB1bmdyb3VwKCklPiUgDQogIGdncGxvdCguLCBhZXMoeCA9IG5hbWUsIHkgPSBwcm9wLCBncm91cD1xdWVzdCwgY29sb3IgPSBxdWVzdCwgbGFiZWw9cXVlc3QpKSArDQogIHN0YXRfc3VtbWFyeShnZW9tID0gImxpbmUiLCBmdW4gPSBtZWFuLCBzaXplPTEpICsNCiAgI2dncmVwZWw6Omdlb21fdGV4dF9yZXBlbChkYXRhID0gLiAlPiUgZmlsdGVyKG5hbWUgPT0gIjAiKSwgYm94LnBhZGRpbmcgPSAwLjUsIG1heC5vdmVybGFwcyA9IEluZikgKw0KICBsYWJzKHggPSAiRG9tYWlucyBhdCB0aGUgbW9uaXRvcmluZyB6b25lIiwgeSA9ICJQcm9wb3J0aW9uIiwgY29sb3IgPSAiUXVlc3Rpb25uYWlyZSIpICsNCiAgdGhlbWVfYncoKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQ0KYGBgDQoNCiMjIyBQZXJjZW50YWdlIGJlbG93DQoNCmBgYHtyfQ0KZHMgJT4lDQogIHNlbGVjdChpZCwgcXVlc3QsIGVuZHNfd2l0aCgic3VtIikpICU+JQ0KICBwaXZvdF9sb25nZXIoLWMoaWQsIHF1ZXN0KSkgJT4lICN0cmFuZm9ybSBpbnRvICBsb25nIGZvcm1hdA0KICBuZXN0X2J5KHF1ZXN0LCBuYW1lKSAlPiUgI25lc3QgKGlkIHdpbGwgbm90IGJlIHVzZWQgdGhpcyB0aW1lKQ0KICAjaGVyZSBpcyB0aGUgdHJpY2suIGFsbCBjb3VudHMgYXJlIGhlcmUNCiAgbXV0YXRlKG1lYW4gPSBsaXN0KG1hcF9kYmwoZGF0YVsyXSwgfm1lYW4oLikpKSwNCiAgICAgICAgIHR3b19iZWxvdyA9IGxpc3QobWFwX2RibChkYXRhWzJdLCB+cXVhbnRpbGUoLiwgcHJvYiA9IDAuMDUpKSksDQogICAgICAgICBvbmVfYmVsb3cgPSBsaXN0KG1hcF9kYmwoZGF0YVsyXSwgfnF1YW50aWxlKC4sIHByb2IgPSAwLjEwKSkpDQogICkgJT4lIA0KICAjb3V0c2lkZSBvZiB0aGUgbWFwLCBhZGQgYSBuZXcgdmFyaWFibGUgdG8gbmVzdGVkIGRhdGENCiAgbXV0YXRlKGRhdGEgPSBsaXN0KGRhdGEgJT4lIG11dGF0ZShhcmVhX21vbml0b3IgPSBhcy5jaGFyYWN0ZXIoaWZlbHNlKGRhdGFbWzJdXSA8PSB0d29fYmVsb3csIHBhc3RlMChuYW1lKSwwKSkpKSkgJT4lIA0KICB1bm5lc3QoZGF0YSkgJT4lICNJJ2xsIHVubmVzdCBhbmQgZ2V0IGFnYWluIHRoZSBpZHMuIG15IGRmIHdpbGwgYmUgdmVyeSBsb25nDQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKGlkLCBxdWVzdCksIG5hbWVzX2Zyb20gPSBjKGFyZWFfbW9uaXRvciksIHZhbHVlc19mbiA9IGxlbmd0aCkgJT4lICNub3cgSSdsbCBncm91cCBieSBpZHMhISBteSBkZiB3aWxsIGJlIHNhbXBsZSBzaXplICogcXVlc3QNCiAgdW5ncm91cCgpICU+JSAjZW5kIG9mIGZ1bmN0aW9uIA0KICAjbm93IEknbGwgY291bnQgdmFsdWVzDQogIG11dGF0ZShob3dfbWFueSA9IHNlbGVjdCguLGVuZHNfd2l0aCgiX3N1bSIpKSAlPiUgcm93U3VtcyguLCBuYS5ybSA9IFQpKSAlPiUgDQogICNub3cgSSdsbCBwcmVzZW50IHRoZSByZXN1bHRzDQogIHRhYnlsKHF1ZXN0LCBob3dfbWFueSklPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogICNhZG9ybl90b3RhbHMoYygicm93IiwgImNvbCIpKSAlPiUgDQogICNhZG9ybl9wZXJjZW50YWdlcygicm93IikgJT4lDQogICNhZG9ybl9wY3RfZm9ybWF0dGluZyhkaWdpdHMgPSAyKSAlPiUNCiAgI2Fkb3JuX25zKCkgDQogIHBpdm90X2xvbmdlcigtcXVlc3QpICU+JQ0KICBncm91cF9ieShxdWVzdCkgJT4lIA0KICBtdXRhdGUocHJvcCA9IHByb3AudGFibGUodmFsdWUpKSAlPiUNCiAgdW5ncm91cCgpJT4lIA0KICBnZ3Bsb3QoLiwgYWVzKHggPSBuYW1lLCB5ID0gcHJvcCwgZ3JvdXA9cXVlc3QsIGNvbG9yID0gcXVlc3QsIGxhYmVsPXF1ZXN0KSkgKw0KICBzdGF0X3N1bW1hcnkoZ2VvbSA9ICJsaW5lIiwgZnVuID0gbWVhbiwgc2l6ZT0xKSArDQogICNnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoZGF0YSA9IC4gJT4lIGZpbHRlcihuYW1lID09ICIwIiksIGJveC5wYWRkaW5nID0gMC41LCBtYXgub3ZlcmxhcHMgPSBJbmYpICsNCiAgbGFicyh4ID0gIkRvbWFpbnMgYmVsb3cgdGhlIGN1dG9mZiIsIHkgPSAiUHJvcG9ydGlvbiIsIGNvbG9yID0gIlF1ZXN0aW9ubmFpcmUiKSArDQogIHRoZW1lX2J3KCkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCmBgYA0KDQpUZXN0aW5nIHRvIGRvdWJsZSBjaGVjayB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBwZXJjZW50aWxlcw0KDQpgYGB7cn0NCiNwZXJjZW50aWxlIDEwDQoNCmRmX3BlcmNlbnRpbF8xMCA8LSBkcyAlPiUNCiAgZmlsdGVyKHF1ZXN0ID09IDIpICU+JSANCiAgc2VsZWN0KGlkLCBxdWVzdCwgZW5kc193aXRoKCJzdW0iKSkgJT4lDQogIHBpdm90X2xvbmdlcigtYyhpZCwgcXVlc3QpKSAlPiUgI3RyYW5mb3JtIGludG8gIGxvbmcgZm9ybWF0DQogIG5lc3RfYnkocXVlc3QsIG5hbWUpICU+JSAjbmVzdCAoaWQgd2lsbCBub3QgYmUgdXNlZCB0aGlzIHRpbWUpDQogICNoZXJlIGlzIHRoZSB0cmljay4gYWxsIGNvdW50cyBhcmUgaGVyZQ0KICBtdXRhdGUobWVhbiA9IGxpc3QobWFwX2RibChkYXRhWzJdLCB+bWVhbiguKSkpLA0KICAgICAgICAgdHdvX2JlbG93ID0gbGlzdChtYXBfZGJsKGRhdGFbMl0sIH5xdWFudGlsZSguLCBwcm9iID0gMC4wNSkpKSwNCiAgICAgICAgIG9uZV9iZWxvdyA9IGxpc3QobWFwX2RibChkYXRhWzJdLCB+cXVhbnRpbGUoLiwgcHJvYiA9IDAuMTApKSkNCiAgKSAlPiUgDQogICNvdXRzaWRlIG9mIHRoZSBtYXAsIGFkZCBhIG5ldyB2YXJpYWJsZSB0byBuZXN0ZWQgZGF0YQ0KICBtdXRhdGUoZGF0YSA9IGxpc3QoZGF0YSAlPiUgbXV0YXRlKGFyZWFfbW9uaXRvciA9IGFzLmNoYXJhY3RlcihpZmVsc2UoZGF0YVtbMl1dID4gdHdvX2JlbG93ICYgZGF0YVtbMl1dIDw9IG9uZV9iZWxvdywgcGFzdGUwKG5hbWUpLDApKSkpKSAlPiUgDQogIHVubmVzdChkYXRhKSAlPiUgDQogIHVubmVzdChpZCkgJT4lIA0KICBwaXZvdF93aWRlcihpZF9jb2xzID0gaWQsIG5hbWVzX2Zyb20gPSBhcmVhX21vbml0b3IsIHZhbHVlc19mbiA9IGxlbmd0aCkgJT4lIA0KICBtdXRhdGUoaG93X21hbnkgPSBzZWxlY3QoLixlbmRzX3dpdGgoIl9zdW0iKSkgJT4lIHJvd1N1bXMoLiwgbmEucm0gPSBUKSkgJT4lIA0KICBmaWx0ZXIoaG93X21hbnkgPT0gMikgJT4lDQogIHJlbmFtZV9hdCh2YXJzKGVuZHNfd2l0aCgiX3N1bSIpKSwgfnBhc3RlKC4sIl9yIikpICU+JSANCiAgbXV0YXRlX2FsbCh+cmVwbGFjZV9uYSguLCAwKSkgJT4lIA0KICB1bmdyb3VwKCkNCg0KDQpkZl9wZXJjZW50aWxfMTAgPC0gbGVmdF9qb2luKA0KZGZfcGVyY2VudGlsXzEwLA0KICBkcyAlPiUgDQogIHNlbGVjdChpZCwgZW5kc193aXRoKCJfc3VtIikpLCANCmJ5ID0gImlkIikgJT4lIA0KICBwaXZvdF9sb25nZXIoLWlkKSAlPiUgDQogIGFycmFuZ2UobmFtZSkgJT4lIA0KICBwaXZvdF93aWRlcihpZF9jb2xzID0gaWQsIG5hbWVzX2Zyb20gPSBuYW1lLCB2YWx1ZXNfZnJvbSA9IHZhbHVlLCB2YWx1ZXNfZmlsbCA9IDApICU+JSANCiAgcmVsb2NhdGUoaG93X21hbnksIC5iZWZvcmUgPSAiMCIpICU+JSANCiAgc2VsZWN0KC0iMCIsLWhvd19tYW55KQ0KICANCg0KYGBgDQoNCmBgYHtyfQ0KZGZfcGVyY2VudGlsXzA1IDwtIGRzICU+JQ0KICBmaWx0ZXIocXVlc3QgPT0gMikgJT4lIA0KICBzZWxlY3QoaWQsIHF1ZXN0LCBlbmRzX3dpdGgoInN1bSIpKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKC1jKGlkLCBxdWVzdCkpICU+JSAjdHJhbmZvcm0gaW50byAgbG9uZyBmb3JtYXQNCiAgbmVzdF9ieShxdWVzdCwgbmFtZSkgJT4lICNuZXN0IChpZCB3aWxsIG5vdCBiZSB1c2VkIHRoaXMgdGltZSkNCiAgI2hlcmUgaXMgdGhlIHRyaWNrLiBhbGwgY291bnRzIGFyZSBoZXJlDQogIG11dGF0ZShtZWFuID0gbGlzdChtYXBfZGJsKGRhdGFbMl0sIH5tZWFuKC4pKSksDQogICAgICAgICB0d29fYmVsb3cgPSBsaXN0KG1hcF9kYmwoZGF0YVsyXSwgfnF1YW50aWxlKC4sIHByb2IgPSAwLjA1KSkpLA0KICAgICAgICAgb25lX2JlbG93ID0gbGlzdChtYXBfZGJsKGRhdGFbMl0sIH5xdWFudGlsZSguLCBwcm9iID0gMC4xMCkpKQ0KICApICU+JSANCiAgI291dHNpZGUgb2YgdGhlIG1hcCwgYWRkIGEgbmV3IHZhcmlhYmxlIHRvIG5lc3RlZCBkYXRhDQptdXRhdGUoZGF0YSA9IGxpc3QoZGF0YSAlPiUgbXV0YXRlKGFyZWFfbW9uaXRvciA9IGFzLmNoYXJhY3RlcihpZmVsc2UoZGF0YVtbMl1dIDw9IHR3b19iZWxvdywgcGFzdGUwKG5hbWUpLDApKSkpKSAlPiUgDQp1bm5lc3QoZGF0YSkgJT4lIA0KICB1bm5lc3QoaWQpICU+JSANCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGlkLCBuYW1lc19mcm9tID0gYXJlYV9tb25pdG9yLCB2YWx1ZXNfZm4gPSBsZW5ndGgpICU+JSANCiAgbXV0YXRlKGhvd19tYW55ID0gc2VsZWN0KC4sZW5kc193aXRoKCJfc3VtIikpICU+JSByb3dTdW1zKC4sIG5hLnJtID0gVCkpICU+JSANCiAgZmlsdGVyKGhvd19tYW55ID09IDIpICU+JQ0KICByZW5hbWVfYXQodmFycyhlbmRzX3dpdGgoIl9zdW0iKSksIH5wYXN0ZSguLCJfciIpKSAlPiUgDQogIG11dGF0ZV9hbGwofnJlcGxhY2VfbmEoLiwgMCkpICU+JSANCiAgdW5ncm91cCgpDQoNCg0KZGZfcGVyY2VudGlsXzA1IDwtIGxlZnRfam9pbigNCmRmX3BlcmNlbnRpbF8wNSwNCiAgZHMgJT4lIA0KICBzZWxlY3QoaWQsIGVuZHNfd2l0aCgiX3N1bSIpKSwgDQpieSA9ICJpZCIpICU+JSANCiAgcGl2b3RfbG9uZ2VyKC1pZCkgJT4lIA0KICBhcnJhbmdlKG5hbWUpICU+JSANCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGlkLCBuYW1lc19mcm9tID0gbmFtZSwgdmFsdWVzX2Zyb20gPSB2YWx1ZSwgdmFsdWVzX2ZpbGwgPSAwKSAlPiUgDQogIHJlbG9jYXRlKGhvd19tYW55LCAuYmVmb3JlID0gIjAiKSAlPiUgDQogIHNlbGVjdCgtIjAiLC1ob3dfbWFueSkNCg0KYGBgDQoNCmBgYHtyfQ0KcmJpbmQoZGZfcGVyY2VudGlsXzEwICU+JSBtdXRhdGUoYmFzZT0icDEwIiksDQpkZl9wZXJjZW50aWxfMDUgJT4lIG11dGF0ZShiYXNlPSJwMDUiKSkgJT4lIA0KICBmaWx0ZXIoaWQgPT0gIjA5MzFjMzU5LWQzMTMtNGYxOC05ZDI2LWZjNGJiMTkyYzBlZCIpICU+JSB0KCkNCiAgYXJyYW5nZShpZCkgJT4lIA0KICBzZWxlY3QoYmFzZSwgZXZlcnl0aGluZygpKQ0KYGBgDQoNCiMjIERlY2lkZWQgb24gRmViIDI4LCAyMg0KDQpgYGB7cn0NCmRlY2lkZWRfY3V0b2ZmIDwtIGZ1bmN0aW9uKHF1ZXN0LCBkb21haW4sIHR5cGUpIHsNCiAgcXVlc3QgPSBlbnF1byhxdWVzdCkNCiAgZG9tYWluID0gZW5xdW8oZG9tYWluKQ0KICBkczIgPSBkcyAlPiUgbXV0YXRlKHF1ZXN0ID0gaWZfZWxzZShxdWVzdCA9PSAiOSIsICIxMCIsIGFzLmNoYXJhY3RlcihxdWVzdCkpKSAjdG8gY29tYmluZSA5IGFuZCAxMCBtb250aHMgcXVlc3Rpb25uYWlyZXMNCg0KICBpZiAodHlwZSA9PSAidHJhZCIpIHsNCiAgICAjdGFibGUgMQ0KICAgIHggPSBkczIgJT4lIA0KICAgICAgZmlsdGVyKHF1ZXN0ID09ICEhcXVlc3QpICU+JQ0KICAgICAgc3VtbWFyaXNlKG4gPSBuKCksDQogICAgICAgICAgICAgICAgbWVhbiA9IG1lYW4oISFkb21haW4sIG5hLnJtPVQpLCBzZCA9IHNkKCEhZG9tYWluLG5hLnJtPVQpLA0KICAgICAgICAgICAgICAgIGN1dG9mZiA9IG1lYW4tMipzZCkgJT4lIA0KICAgICAgbXV0YXRlKHF1ZXN0ID0gISFxdWVzdCxkb21haW4gPSBxdW9fbmFtZShkb21haW4pKSAjdG8gaWRlbnRpZnkgd2hpY2ggcXVlc3QgaW4gdGhlIG91dHB1dCBsaXN0DQogICAgI3RhYmxlMg0KICAgIHkgPSBkczIgJT4lIA0KICAgICAgZmlsdGVyKHF1ZXN0ID09ICEhcXVlc3QpICU+JQ0KICAgICAgbXV0YXRlKG4gPSBuKCksDQogICAgICAgICAgICAgbWVhbiA9IG1lYW4oISFkb21haW4sIG5hLnJtPVQpLCBzZCA9IHNkKCEhZG9tYWluLG5hLnJtPVQpLA0KICAgICAgICAgICAgIGN1dG9mZiA9IG1lYW4tMipzZCwNCiAgICAgICAgICAgICBjbGFzcyA9IGlmZWxzZSghIWRvbWFpbiA8PSBjdXRvZmYsImJlbG93IiwiYWJvdmUiKSkgJT4lDQogICAgICB0YWJ5bChjbGFzcykNCiAgICANCiAgICBqID0gY2JpbmQuZGF0YS5mcmFtZSh4LHkpDQogICAgaiA9IGRhdGEuZnJhbWUobGFwcGx5KGosIGZ1bmN0aW9uKGopIGlmKGlzLm51bWVyaWMoaikpIHJvdW5kKGosIDIpIGVsc2UgaikpICNyb3VuZA0KICAgIGogPSBqICU+JSBzZWxlY3QocXVlc3QsIGRvbWFpbixldmVyeXRoaW5nKCkpICNjaGFuZ2UgcG9zaXRpb24NCiAgICAjaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvOTA2Mzg4OS9ob3ctdG8tcm91bmQtYS1kYXRhLWZyYW1lLWluLXItdGhhdC1jb250YWlucy1zb21lLWNoYXJhY3Rlci12YXJpYWJsZXMNCiAgICANCiAgICByZXR1cm4oaikNCiAgfQ0KICANCiAgaWYgKHR5cGUgPT0gIjEwIikgew0KICAgICN0YWJsZSAxDQogICAgeCA9IGRzMiAlPiUgDQogICAgICBmaWx0ZXIocXVlc3QgPT0gISFxdWVzdCkgJT4lDQogICAgICBzdW1tYXJpc2UobiA9IG4oKSwNCiAgICAgICAgICAgICAgICBtZWFuID0gbWVhbighIWRvbWFpbiwgbmEucm09VCksIHNkID0gc2QoISFkb21haW4sbmEucm09VCksDQogICAgICAgICAgICAgICAgcDEwID0gcXVhbnRpbGUoeCA9ICEhZG9tYWluLCBwcm9iID0gMC4xKSwNCiAgICAgICAgICAgICAgICBjdXRvZmYgPSBwMTApICU+JQ0KICAgICAgbXV0YXRlKHF1ZXN0ID0gISFxdWVzdCxkb21haW4gPSBxdW9fbmFtZShkb21haW4pKSAjdG8gaWRlbnRpZnkgd2hpY2ggcXVlc3QgaW4gdGhlIG91dHB1dCBsaXN0DQogICANCiAgICAjdGFibGUyDQogICAgeSA9IGRzMiAlPiUgDQogICAgICBmaWx0ZXIocXVlc3QgPT0gISFxdWVzdCkgJT4lDQogICAgICBtdXRhdGUoY3V0b2ZmID0gcXVhbnRpbGUoeCA9ICEhZG9tYWluLCBwcm9iID0gMC4xKSwNCiAgICAgICAgICAgICBjbGFzcyA9IGlmZWxzZSghIWRvbWFpbiA8PSBjdXRvZmYsImJlbG93IiwiYWJvdmUiKSkgJT4lDQogICAgICB0YWJ5bChjbGFzcykNCiAgICANCiAgICBqID0gY2JpbmQuZGF0YS5mcmFtZSh4LHkpDQogICAgaiA9IGRhdGEuZnJhbWUobGFwcGx5KGosIGZ1bmN0aW9uKGopIGlmKGlzLm51bWVyaWMoaikpIHJvdW5kKGosIDIpIGVsc2UgaikpICNyb3VuZA0KICAgIGogPSBqICU+JSBzZWxlY3QocXVlc3QsIGRvbWFpbixldmVyeXRoaW5nKCkpICNjaGFuZ2UgcG9zaXRpb24NCg0KICAgIHJldHVybihqKQ0KICB9DQogIA0KDQogIGlmICh0eXBlID09ICIyMHAiKSB7DQogICAgI3RhYmxlIDENCiAgICB4ID0gZHMyICU+JSANCiAgICAgIGZpbHRlcihxdWVzdCA9PSAhIXF1ZXN0KSAlPiUNCiAgICAgIHN1bW1hcmlzZShuID0gbigpLA0KICAgICAgICAgICAgICAgIG1lYW4gPSBtZWFuKCEhZG9tYWluLCBuYS5ybT1UKSwgc2QgPSBzZCghIWRvbWFpbixuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICBjdXRvZmYgPSAyMCkgJT4lDQogICAgICBtdXRhdGUocXVlc3QgPSAhIXF1ZXN0LGRvbWFpbiA9IHF1b19uYW1lKGRvbWFpbikpICN0byBpZGVudGlmeSB3aGljaCBxdWVzdCBpbiB0aGUgb3V0cHV0IGxpc3QNCiAgICANCiAgICAjdGFibGUyDQogICAgeSA9IGRzMiAlPiUgDQogICAgICBmaWx0ZXIocXVlc3QgPT0gISFxdWVzdCkgJT4lDQogICAgICBtdXRhdGUoY3V0b2ZmID0gMjAsDQogICAgICAgICAgICAgY2xhc3MgPSBpZmVsc2UoISFkb21haW4gPD0gY3V0b2ZmLCJiZWxvdyIsImFib3ZlIikpICU+JQ0KICAgICAgdGFieWwoY2xhc3MpDQogICAgDQogICAgaiA9IGNiaW5kLmRhdGEuZnJhbWUoeCx5KQ0KICAgIGogPSBkYXRhLmZyYW1lKGxhcHBseShqLCBmdW5jdGlvbihqKSBpZihpcy5udW1lcmljKGopKSByb3VuZChqLCAyKSBlbHNlIGopKSAjcm91bmQNCiAgICBqID0gaiAlPiUgc2VsZWN0KHF1ZXN0LCBkb21haW4sZXZlcnl0aGluZygpKSAjY2hhbmdlIHBvc2l0aW9uDQogICAgDQogICAgcmV0dXJuKGopDQogIH0NCiAgDQogIGlmICh0eXBlID09ICIyNXAiKSB7DQogICAgI3RhYmxlIDENCiAgICB4ID0gZHMyICU+JSANCiAgICAgIGZpbHRlcihxdWVzdCA9PSAhIXF1ZXN0KSAlPiUNCiAgICAgIHN1bW1hcmlzZShuID0gbigpLA0KICAgICAgICAgICAgICAgIG1lYW4gPSBtZWFuKCEhZG9tYWluLCBuYS5ybT1UKSwgc2QgPSBzZCghIWRvbWFpbixuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICBjdXRvZmYgPSAyNSkgJT4lDQogICAgICBtdXRhdGUocXVlc3QgPSAhIXF1ZXN0LGRvbWFpbiA9IHF1b19uYW1lKGRvbWFpbikpICN0byBpZGVudGlmeSB3aGljaCBxdWVzdCBpbiB0aGUgb3V0cHV0IGxpc3QNCiAgIA0KICAgICN0YWJsZTINCiAgICB5ID0gZHMyICU+JSANCiAgICAgIGZpbHRlcihxdWVzdCA9PSAhIXF1ZXN0KSAlPiUNCiAgICAgIG11dGF0ZShjdXRvZmYgPSAyNSwNCiAgICAgICAgICAgICBjbGFzcyA9IGlmZWxzZSghIWRvbWFpbiA8PSBjdXRvZmYsImJlbG93IiwiYWJvdmUiKSkgJT4lDQogICAgICB0YWJ5bChjbGFzcykNCiAgICANCiAgICBqID0gY2JpbmQuZGF0YS5mcmFtZSh4LHkpDQogICAgaiA9IGRhdGEuZnJhbWUobGFwcGx5KGosIGZ1bmN0aW9uKGopIGlmKGlzLm51bWVyaWMoaikpIHJvdW5kKGosIDIpIGVsc2UgaikpICNyb3VuZA0KICAgIGogPSBqICU+JSBzZWxlY3QocXVlc3QsIGRvbWFpbixldmVyeXRoaW5nKCkpICNjaGFuZ2UgcG9zaXRpb24NCg0KICAgIHJldHVybihqKQ0KICAgIH0NCg0KICBpZiAodHlwZSA9PSAiMzBwIikgew0KICAgICN0YWJsZSAxDQogICAgeCA9IGRzMiAlPiUgDQogICAgICBmaWx0ZXIocXVlc3QgPT0gISFxdWVzdCkgJT4lDQogICAgICBzdW1tYXJpc2UobiA9IG4oKSwNCiAgICAgICAgICAgICAgICBtZWFuID0gbWVhbighIWRvbWFpbiwgbmEucm09VCksIHNkID0gc2QoISFkb21haW4sbmEucm09VCksDQogICAgICAgICAgICAgICAgY3V0b2ZmID0gMzApICU+JQ0KICAgICAgbXV0YXRlKHF1ZXN0ID0gISFxdWVzdCxkb21haW4gPSBxdW9fbmFtZShkb21haW4pKSAjdG8gaWRlbnRpZnkgd2hpY2ggcXVlc3QgaW4gdGhlIG91dHB1dCBsaXN0DQogICAgDQogICAgI3RhYmxlMg0KICAgIHkgPSBkczIgJT4lIA0KICAgICAgZmlsdGVyKHF1ZXN0ID09ICEhcXVlc3QpICU+JQ0KICAgICAgbXV0YXRlKGN1dG9mZiA9IDMwLA0KICAgICAgICAgICAgIGNsYXNzID0gaWZlbHNlKCEhZG9tYWluIDw9IGN1dG9mZiwiYmVsb3ciLCJhYm92ZSIpKSAlPiUNCiAgICAgIHRhYnlsKGNsYXNzKQ0KICAgIA0KICAgIGogPSBjYmluZC5kYXRhLmZyYW1lKHgseSkNCiAgICBqID0gZGF0YS5mcmFtZShsYXBwbHkoaiwgZnVuY3Rpb24oaikgaWYoaXMubnVtZXJpYyhqKSkgcm91bmQoaiwgMikgZWxzZSBqKSkgI3JvdW5kDQogICAgaiA9IGogJT4lIHNlbGVjdChxdWVzdCwgZG9tYWluLGV2ZXJ5dGhpbmcoKSkgI2NoYW5nZSBwb3NpdGlvbg0KICAgIA0KICAgIHJldHVybihqKQ0KICB9DQogICAgDQogICAgIGlmICh0eXBlID09ICIzNXAiKSB7DQogICAgI3RhYmxlIDENCiAgICB4ID0gZHMyICU+JSANCiAgICAgIGZpbHRlcihxdWVzdCA9PSAhIXF1ZXN0KSAlPiUNCiAgICAgIHN1bW1hcmlzZShuID0gbigpLA0KICAgICAgICAgICAgICAgIG1lYW4gPSBtZWFuKCEhZG9tYWluLCBuYS5ybT1UKSwgc2QgPSBzZCghIWRvbWFpbixuYS5ybT1UKSwNCiAgICAgICAgICAgICAgICBjdXRvZmYgPSAzNSkgJT4lDQogICAgICBtdXRhdGUocXVlc3QgPSAhIXF1ZXN0LGRvbWFpbiA9IHF1b19uYW1lKGRvbWFpbikpICN0byBpZGVudGlmeSB3aGljaCBxdWVzdCBpbiB0aGUgb3V0cHV0IGxpc3QNCiAgIA0KICAgICN0YWJsZTINCiAgICB5ID0gZHMyICU+JSANCiAgICAgIGZpbHRlcihxdWVzdCA9PSAhIXF1ZXN0KSAlPiUNCiAgICAgIG11dGF0ZShjdXRvZmYgPSAzNSwNCiAgICAgICAgICAgICBjbGFzcyA9IGlmZWxzZSghIWRvbWFpbiA8PSBjdXRvZmYsImJlbG93IiwiYWJvdmUiKSkgJT4lDQogICAgICB0YWJ5bChjbGFzcykNCiAgICANCiAgICBqID0gY2JpbmQuZGF0YS5mcmFtZSh4LHkpDQogICAgaiA9IGRhdGEuZnJhbWUobGFwcGx5KGosIGZ1bmN0aW9uKGopIGlmKGlzLm51bWVyaWMoaikpIHJvdW5kKGosIDIpIGVsc2UgaikpICNyb3VuZA0KICAgIGogPSBqICU+JSBzZWxlY3QocXVlc3QsIGRvbWFpbixldmVyeXRoaW5nKCkpICNjaGFuZ2UgcG9zaXRpb24NCg0KICAgIHJldHVybihqKQ0KICAgIH0NCiAgDQp9DQpgYGANCg0KDQojIyMgMiBtb250aHMNCg0KYGBge3J9DQpwcmludChsaXN0KA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gInRyYWQiLCBxdWVzdCA9IDIsIGRvbWFpbiA9IGNfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICJ0cmFkIiwgcXVlc3QgPSAyLCBkb21haW4gPSBnbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gInRyYWQiLCBxdWVzdCA9IDIsIGRvbWFpbiA9IGZtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAidHJhZCIsIHF1ZXN0ID0gMiwgZG9tYWluID0gY2dfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICJ0cmFkIiwgcXVlc3QgPSAyLCBkb21haW4gPSBwc19zdW0pDQopKQ0KYGBgDQoNCiMjIyA0IG1vbnRocw0KDQpgYGB7cn0NCnByaW50KGxpc3QoDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAidHJhZCIsIHF1ZXN0ID0gNCwgZG9tYWluID0gY19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gInRyYWQiLCBxdWVzdCA9IDQsIGRvbWFpbiA9IGdtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAidHJhZCIsIHF1ZXN0ID0gNCwgZG9tYWluID0gZm1fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICJ0cmFkIiwgcXVlc3QgPSA0LCBkb21haW4gPSBjZ19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gInRyYWQiLCBxdWVzdCA9IDQsIGRvbWFpbiA9IHBzX3N1bSkNCikpDQpgYGANCg0KDQojIyMgNiBtb250aHMNCg0KYGBge3J9DQpwcmludChsaXN0KA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gInRyYWQiLCBxdWVzdCA9IDYsIGRvbWFpbiA9IGNfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICJ0cmFkIiwgcXVlc3QgPSA2LCBkb21haW4gPSBnbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gInRyYWQiLCBxdWVzdCA9IDYsIGRvbWFpbiA9IGZtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAidHJhZCIsIHF1ZXN0ID0gNiwgZG9tYWluID0gY2dfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICJ0cmFkIiwgcXVlc3QgPSA2LCBkb21haW4gPSBwc19zdW0pDQopKQ0KYGBgDQoNCiMjIyA4IG1vbnRocw0KDQpgYGB7cn0NCnByaW50KGxpc3QoDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDgsIGRvbWFpbiA9IGNfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gOCwgZG9tYWluID0gZ21fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gOCwgZG9tYWluID0gZm1fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gOCwgZG9tYWluID0gY2dfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gOCwgZG9tYWluID0gcHNfc3VtKQ0KKSkNCmBgYA0KDQoNCiMjIyA5IGFuZCAxMCBtb250aHMNCg0KYGBge3J9DQpwcmludChsaXN0KA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjI1cCIsIHF1ZXN0ID0gMTAsIGRvbWFpbiA9IGNfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIyNXAiLCBxdWVzdCA9IDEwLCBkb21haW4gPSBnbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAxMCwgZG9tYWluID0gZm1fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMTAsIGRvbWFpbiA9IGNnX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDEwLCBkb21haW4gPSBwc19zdW0pDQopKQ0KYGBgDQoNCg0KIyMjIDEyIG1vbnRocw0KDQpgYGB7cn0NCnByaW50KGxpc3QoDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDEyLCBkb21haW4gPSBjX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDEyLCBkb21haW4gPSBnbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAxMiwgZG9tYWluID0gZm1fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMTIsIGRvbWFpbiA9IGNnX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDEyLCBkb21haW4gPSBwc19zdW0pDQopKQ0KYGBgDQoNCiMjIyAxNCBtb250aHMNCg0KYGBge3J9DQpwcmludChsaXN0KA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjI1cCIsIHF1ZXN0ID0gMTQsIGRvbWFpbiA9IGNfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMTQsIGRvbWFpbiA9IGdtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDE0LCBkb21haW4gPSBmbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAxNCwgZG9tYWluID0gY2dfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMTQsIGRvbWFpbiA9IHBzX3N1bSkNCikpDQpgYGANCg0KIyMjIDE2IG1vbnRocw0KDQpgYGB7cn0NCnByaW50KGxpc3QoDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMjVwIiwgcXVlc3QgPSAxNiwgZG9tYWluID0gY19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAxNiwgZG9tYWluID0gZ21fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMTYsIGRvbWFpbiA9IGZtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDE2LCBkb21haW4gPSBjZ19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAxNiwgZG9tYWluID0gcHNfc3VtKQ0KKSkNCmBgYA0KIyMjIDE4IG1vbnRocw0KDQpgYGB7cn0NCnByaW50KGxpc3QoDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMjVwIiwgcXVlc3QgPSAxOCwgZG9tYWluID0gY19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAxOCwgZG9tYWluID0gZ21fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMTgsIGRvbWFpbiA9IGZtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDE4LCBkb21haW4gPSBjZ19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAxOCwgZG9tYWluID0gcHNfc3VtKQ0KKSkNCmBgYA0KIyMjIDIwIG1vbnRocw0KDQpgYGB7cn0NCnByaW50KGxpc3QoDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMjVwIiwgcXVlc3QgPSAyMCwgZG9tYWluID0gY19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAyMCwgZG9tYWluID0gZ21fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMjAsIGRvbWFpbiA9IGZtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDIwLCBkb21haW4gPSBjZ19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAyMCwgZG9tYWluID0gcHNfc3VtKQ0KKSkNCmBgYA0KDQojIyMgMjIgbW9udGhzDQoNCmBgYHtyfQ0KcHJpbnQobGlzdCgNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIyNXAiLCBxdWVzdCA9IDIyLCBkb21haW4gPSBjX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDIyLCBkb21haW4gPSBnbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAyMiwgZG9tYWluID0gZm1fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMjIsIGRvbWFpbiA9IGNnX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDIyLCBkb21haW4gPSBwc19zdW0pDQopKQ0KYGBgDQoNCg0KIyMjIDI0IG1vbnRocw0KDQpgYGB7cn0NCnByaW50KGxpc3QoDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMjVwIiwgcXVlc3QgPSAyNCwgZG9tYWluID0gY19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAyNCwgZG9tYWluID0gZ21fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMjQsIGRvbWFpbiA9IGZtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDI0LCBkb21haW4gPSBjZ19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAyNCwgZG9tYWluID0gcHNfc3VtKQ0KKSkNCmBgYA0KDQoNCiMjIyAyNyBtb250aHMNCg0KYGBge3J9DQpwcmludChsaXN0KA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjI1cCIsIHF1ZXN0ID0gMjcsIGRvbWFpbiA9IGNfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMjcsIGRvbWFpbiA9IGdtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDI3LCBkb21haW4gPSBmbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAyNywgZG9tYWluID0gY2dfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMjcsIGRvbWFpbiA9IHBzX3N1bSkNCikpDQoNCmBgYA0KDQoNCiMjIyAzMCBtb250aHMNCg0KYGBge3J9DQpwcmludChsaXN0KA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjMwcCIsIHF1ZXN0ID0gMzAsIGRvbWFpbiA9IGNfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMzAsIGRvbWFpbiA9IGdtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDMwLCBkb21haW4gPSBmbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAzMCwgZG9tYWluID0gY2dfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMzAsIGRvbWFpbiA9IHBzX3N1bSkNCikpDQpgYGANCiMjIyAzMyBtb250aHMNCg0KYGBge3J9DQpwcmludChsaXN0KA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAzMywgZG9tYWluID0gY19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAzMywgZG9tYWluID0gZ21fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMzMsIGRvbWFpbiA9IGZtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDMzLCBkb21haW4gPSBjZ19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAzMywgZG9tYWluID0gcHNfc3VtKQ0KKSkNCmBgYA0KDQojIyMgMzYgbW9udGhzDQoNCmBgYHtyfQ0KcHJpbnQobGlzdCgNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIzMHAiLCBxdWVzdCA9IDM2LCBkb21haW4gPSBjX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDM2LCBkb21haW4gPSBnbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSAzNiwgZG9tYWluID0gZm1fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gMzYsIGRvbWFpbiA9IGNnX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDM2LCBkb21haW4gPSBwc19zdW0pDQopKQ0KYGBgDQojIyMgNDIgbW9udGhzDQoNCmBgYHtyfQ0KcHJpbnQobGlzdCgNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gNDIsIGRvbWFpbiA9IGNfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gNDIsIGRvbWFpbiA9IGdtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMjVwIiwgcXVlc3QgPSA0MiwgZG9tYWluID0gZm1fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gNDIsIGRvbWFpbiA9IGNnX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDQyLCBkb21haW4gPSBwc19zdW0pDQopKQ0KYGBgDQoNCiMjIyA0OCBtb250aHMNCg0KYGBge3J9DQpwcmludChsaXN0KA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSA0OCwgZG9tYWluID0gY19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSA0OCwgZG9tYWluID0gZ21fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gNDgsIGRvbWFpbiA9IGZtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDQ4LCBkb21haW4gPSBjZ19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSA0OCwgZG9tYWluID0gcHNfc3VtKQ0KKSkNCmBgYA0KDQojIyMgNTQgbW9udGhzDQoNCmBgYHtyfQ0KcHJpbnQobGlzdCgNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gNTQsIGRvbWFpbiA9IGNfc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIzNXAiLCBxdWVzdCA9IDU0LCBkb21haW4gPSBnbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSA1NCwgZG9tYWluID0gZm1fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gNTQsIGRvbWFpbiA9IGNnX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDU0LCBkb21haW4gPSBwc19zdW0pDQopKQ0KYGBgDQoNCg0KIyMjIDYwIG1vbnRocw0KDQpgYGB7cn0NCnByaW50KGxpc3QoDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDYwLCBkb21haW4gPSBjX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDYwLCBkb21haW4gPSBnbV9zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSA2MCwgZG9tYWluID0gZm1fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gNjAsIGRvbWFpbiA9IGNnX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDYwLCBkb21haW4gPSBwc19zdW0pDQopKQ0KYGBgDQoNCiMjIyA3MiBtb250aHMNCg0KYGBge3J9DQpwcmludChsaXN0KA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSA3MiwgZG9tYWluID0gY19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSA3MiwgZG9tYWluID0gZ21fc3VtKSwNCiAgZGVjaWRlZF9jdXRvZmYodHlwZSA9ICIxMCIsIHF1ZXN0ID0gNzIsIGRvbWFpbiA9IGZtX3N1bSksDQogIGRlY2lkZWRfY3V0b2ZmKHR5cGUgPSAiMTAiLCBxdWVzdCA9IDcyLCBkb21haW4gPSBjZ19zdW0pLA0KICBkZWNpZGVkX2N1dG9mZih0eXBlID0gIjEwIiwgcXVlc3QgPSA3MiwgZG9tYWluID0gcHNfc3VtKQ0KKSkNCmBgYA0KDQojIFJPQyBDVVJWRSANCg0KIyMgRGVzY3JpcHRpdmUNCg0KYGBge3IgcmVzdWx0cyA9ICJhc2lzIn0NCmRzX2VsaWdpYmxlICU+JSANCiAgc2VsZWN0KHF1ZXN0LGVuZHNfd2l0aCgiX3N1bSIpKSAlPiUgDQogICAgdGFibGVieShxdWVzdCB+IC4sIGNvbnRyb2wgPSB0YWJsZWJ5LmNvbnRyb2wobnVtZXJpYy5zdGF0cz1jKCJtZWFuIiwgInNkIikpLCBkYXRhID0gLikgJT4lIA0KICBzdW1tYXJ5KC4gLCBkaWdpdHMgPSAyKQ0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KZHNfZWxpZ2libGUgJT4lIHRhYnlsKGdlbmRlcikNCmBgYA0KDQoNCiMjIFJlc3VsdHMgbj4xDQoNCg0KYGBge3J9DQpkc19lbGlnaWJsZSAlPiUNCiAgc2VsZWN0KHF1ZXN0LGVuZHNfd2l0aCgiX3N1bSIpKSAlPiUgDQogIGdyb3VwX2J5KHF1ZXN0KSAlPiUNCiAgZmlsdGVyKG4oKT4xKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBwaXZvdF9sb25nZXIoLXF1ZXN0KSAlPiUNCiAgZ3JvdXBfYnkocXVlc3QsIG5hbWUpICU+JSANCiAgbXV0YXRlKA0KICAgIG49bigpLA0KICAgIG09bWVhbih2YWx1ZSksDQogICAgc2Q9c2QodmFsdWUpLA0KICAgIG1vbml0b3I9bS1zZCwNCiAgICBiZWxvdz1tLTIqc2QpJT4lDQogIHNlbGVjdCgtdmFsdWUpICU+JSANCiAgZGlzdGluY3QoKSAlPiUgI3JlbW92ZSBkdXBsaWNhdGUNCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IHF1ZXN0LCBuYW1lc19mcm9tID0gbmFtZSwgdmFsdWVzX2Zyb20gPSBuOmJlbG93LCBuYW1lc19nbHVlID0gIntuYW1lfV97LnZhbHVlfSIpICU+JQ0KICBtdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsIDIpICU+JQ0KICAuW2d0b29sczo6bWl4ZWRvcmRlciguJHF1ZXN0KSwgXSANCg0KDQpgYGANCg0KIyMgVCB0ZXN0cw0KDQoNCmBgYHtyfQ0KI2NoZWNrIHdoaWNoIGJhc2VzIEkgY2FuIGNvbXBhcmUgKDIgZ3JvdXBzKQ0KYmluZF9yb3dzKA0KICBkc19lbGlnaWJsZSAlPiUNCiAgICBzZWxlY3QocXVlc3QsZW5kc193aXRoKCJfc3VtIikpICU+JSANCiAgICBncm91cF9ieShxdWVzdCkgJT4lDQogICAgZmlsdGVyKG4oKT4xKSAlPiUNCiAgICB1bmdyb3VwKCkgJT4lDQogICAgbXV0YXRlKGJhc2U9ImVsaWdpYmxlIikNCiAgLA0KICBkcyAlPiUgDQogICAgc2VsZWN0KHF1ZXN0LGVuZHNfd2l0aCgiX3N1bSIpKSAlPiUgDQogICAgbXV0YXRlKGJhc2U9Im9yaWdpbmFsIikNCikgJT4lDQogIGdyb3VwX2J5KHF1ZXN0KSAlPiUNCiAgY291bnQoYmFzZSklPiUgI2NoZWNrIGVhY2ggYWdlIGluZXJ2YWwNCiAgZmlsdGVyKG4oKT4xKSAlPiUgI3JlbW92ZSBpZiBqdXN0IG9uZSBncm91cA0KICB1bmdyb3VwKCkgJT4lDQogIHNlbGVjdChxdWVzdCkgJT4lIGRpc3RpbmN0KCkgJT4lDQogIHB1bGwocXVlc3QpIC0+IHF1ZXN0aW9ubmFpcmVzX3RvX2NvbXBhcmUNCg0KI2RlZmluZSBhIGRmIHRvIGNvbXBhcmUgDQpiaW5kX3Jvd3MoDQogIGRzX2VsaWdpYmxlICU+JQ0KICAgIHNlbGVjdChxdWVzdCxlbmRzX3dpdGgoIl9zdW0iKSkgJT4lIA0KICAgIGdyb3VwX2J5KHF1ZXN0KSAlPiUNCiAgICBmaWx0ZXIobigpPjEpICU+JQ0KICAgIHVuZ3JvdXAoKSAlPiUNCiAgICBtdXRhdGUoYmFzZT0iZWxpZ2libGUiKQ0KICAsDQogIGRzICU+JSANCiAgICBzZWxlY3QocXVlc3QsZW5kc193aXRoKCJfc3VtIikpICU+JSANCiAgICBtdXRhdGUoYmFzZT0ib3JpZ2luYWwiKQ0KKSAlPiUNCiAgI2ZpbHRlciB0aG9zZSBhZ2VzIGluIHdoaWNoIEkgaGF2ZSBqdXN0IG9uZSBncm91cA0KICBmaWx0ZXIocXVlc3QgJWluJSBjKHF1ZXN0aW9ubmFpcmVzX3RvX2NvbXBhcmUpKSAlPiUNCiAgI25lZWQgdG8gaGF2ZSB0aGUgbG9uZyBmb3JtYXQgdG8gbmVzdCB0aGUgYWxsIHF1ZXN0aW9ubmFpcmVzDQogIHBpdm90X2xvbmdlcihjX3N1bTpwc19zdW0pICU+JQ0KICBuZXN0X2J5KHF1ZXN0LG5hbWUpICU+JQ0KICBzdW1tYXJpc2UobW9kZWwgPSBsaXN0KHQudGVzdCh2YWx1ZSB+IGJhc2UsIGRhdGEgPSBkYXRhLCB2YXIuZXF1YWw9VCAsIGFsdGVybmF0aXZlID0gImxlc3MiKSkpICU+JSAgI2h0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzUxMDc0MzI4L3BlcmZvcm0tc2V2ZXJhbC10LXRlc3RzLXNpbXVsdGFuZW91c2x5LW9uLXRpZHktZGF0YS1pbi1yDQogIG11dGF0ZShtb2RlbCA9IG1hcChtb2RlbCwgYnJvb206OnRpZHkpKSAlPiUNCiAgdW5uZXN0KGNvbHMgPSBjKG1vZGVsKSkgJT4lDQogIHNlbGVjdChxdWVzdCwgbmFtZSwgZXN0aW1hdGUxLCBlc3RpbWF0ZTIsIHAudmFsdWUpICU+JQ0KICBtdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsIDIpJT4lDQogICNwcmVzZW50aW5nDQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBxdWVzdCwgbmFtZXNfZnJvbSA9bmFtZSwgdmFsdWVzX2Zyb20gPSBjKGVzdGltYXRlMSwgZXN0aW1hdGUyLCBwLnZhbHVlKSwgbmFtZXNfZ2x1ZSA9ICJ7bmFtZX1fey52YWx1ZX0iKSAlPiUNCiAgIHNlbGVjdCgicXVlc3QiLCBzb3J0KGNvbG5hbWVzKC4pKSkNCg0KYGBgDQoNCiMjIFJPQyBncmFwaA0KDQoNCmBgYHtyfQ0KI2xpYnJhcnkoY3V0cG9pbnRyKQ0Kc2V0LnNlZWQoMTMpDQpiaW5kX3Jvd3MoDQogICN0eXBpY2FsICANCiAgZHMgJT4lIA0KICAgIGZpbHRlcihxdWVzdCA9PSAyNCkgJT4lDQogICAgc2VsZWN0KGNfc3VtKSAlPiUNCiAgICBtdXRhdGUoZ3JvdXAgPSAwKSAlPiUNCiAgICBzYW1wbGVfbiguLCAyNCkNCiAgLA0KICAjZWxpZ2libGUNCiAgZHNfZWxpZ2libGUgJT4lIA0KICAgIGZpbHRlcihxdWVzdCA9PSAzNikgJT4lIA0KICAgIG11dGF0ZShncm91cCA9MSkgJT4lDQogICAgc2VsZWN0KGdyb3VwLCBjX3N1bSkNCikgJT4lDQogIGN1dHBvaW50ciguLCBjX3N1bSwgZ3JvdXAsIA0KICAgICAgICAgICAgcG9zX2NsYXNzID0gMSwNCiAgICAgICAgICAgIG1ldGhvZCA9IG1heGltaXplX21ldHJpYywgIA0KICAgICAgICAgICAgbWV0cmljID0geW91ZGVuKSAlPiUgDQogICNwbG90X3goKQ0KICAjcGxvdF9yb2MoKSArIGdlb21fYWJsaW5lKHNsb3BlID0gMSkgKyB0aGVtZV9idygpDQogIHN1bW1hcnkoLikNCmBgYA0KDQoNCg0KIyBUZXN0LVJldGVzdCByZWxpYWJpbGl0eQ0KDQoNCmBgYHtyfQ0KZHNfcmV0ZXN0X2FuYWx5c2lzIA0KYGBgDQoNCg0KYGBge3IgY29ycmVsYXRpb24gb2xkLCBldmFsID0gRkFMU0UgfQ0KZHNfcmV0ZXN0X2FuYWx5c2lzICU+JQ0KICBzZWxlY3RfaWYoaXMubnVtZXJpYykgJT4lDQogIGdyb3VwX2J5KHF1ZXN0KSAlPiUNCiAgbmVzdCgpICU+JQ0KICBtdXRhdGUoDQogICAgY29ycmVsYXRpb25zID0gbWFwKGRhdGEsIGNvcnJyOjpjb3JyZWxhdGUpDQogICkgJT4lDQogIHVubmVzdChjb3JyZWxhdGlvbnMpDQoNCmBgYA0KDQojIyBHcm91cGVkIGNvcnINCg0KYGBge3J9DQojIHBlYXJzb24gY29ycmVsYXRpb24NCnJldGVzdF9jb3IgPC0gZHNfcmV0ZXN0X2FuYWx5c2lzICU+JSANCiAgc3BsaXQobGlzdCguJHF1ZXN0KSkgJT4lIA0KICBtYXAofkhtaXNjOjpyY29ycihhcy5tYXRyaXgoLikpJHIpIA0KIyBjcmVhdGUgYSBjb2x1bW4gd2l0aCBxdWVzdGlvbm5haXJlDQpyZXRlc3RfY29yIDwtIGRvLmNhbGwocmJpbmQuZGF0YS5mcmFtZSwgcmV0ZXN0X2NvcikNCg0KIyBQIHZhdWVzIG9mIHBlYXJzb24gY29ycmVsYXRpb24NCnJldGVzdF9jb3JfcHZhbCA8LSBkc19yZXRlc3RfYW5hbHlzaXMgJT4lIA0KICBzcGxpdChsaXN0KC4kcXVlc3QpKSAlPiUgDQogIG1hcCh+SG1pc2M6OnJjb3JyKGFzLm1hdHJpeCguKSkkUCkNCiMgY3JlYXRlIGEgY29sdW1uIHdpdGggcXVlc3Rpb25uYWlyZQ0KcmV0ZXN0X2Nvcl9wdmFsIDwtIGRvLmNhbGwocmJpbmQuZGF0YS5mcmFtZSwgcmV0ZXN0X2Nvcl9wdmFsKQ0KDQpgYGANCg0KIyMgVGFibGUNCg0KIyMjIFJFQ0hFQ0sgY29tbXVuaWNhdGlvbmcgPyE/ISAoUkVDSEVDSyAhISEgT24gRmViIDEsMjAyMiAtLSBSZWFsbHkgcmVjaGVjayEpDQoNCmBgYHtyfQ0KdGVzdF9yZXN0X3RhYmxlIDwtIGxlZnRfam9pbigNCiAgIyBSIENPRUYNCiAgcmV0ZXN0X2NvciAlPiUgDQogICAgc2VsZWN0KC1xdWVzdCkgJT4lICMgcmVtb3ZlIHF1ZXN0aW9ubmFpcmVzDQogICAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJxdWVzdCIpICU+JSAgI2FkZCByZWFsIHF1ZXN0aW9ubmFpcmVzDQogICAgc2VwYXJhdGUoLiwgY29sID0gInF1ZXN0IiwgaW50byA9IGMoInF1ZXN0IiwiZG9tYWluIiwic3VtIiwgInRpbWUiKSkgJT4lI3JlbmFtZSBhbmQgc2VwYXJhdGUNCiAgICBmaWx0ZXIodGltZSA9PSAieCIpICU+JSANCiAgICBzZWxlY3QoLXN1bSwgLXRpbWUpICU+JSANCiAgICBzZWxlY3QocXVlc3QsIGRvbWFpbiwgZW5kc193aXRoKCJ5IikpICU+JSAjc2VsZWN0IGV2ZXJ5dGhpbmcNCiAgICBwaXZvdF9sb25nZXIoLWMoInF1ZXN0IiwiZG9tYWluIikpICU+JSAgI3RvIG1hdGNoDQogICAgbXV0YXRlKG5hbWUgPXN0cl9leHRyYWN0X2FsbChuYW1lLCAiXFx3Kyg/PV8pIiwgc2ltcGxpZnkgPSBUKSkgJT4lICNmaWx0ZXIgc2FtZSBkb21haW4NCiAgICBmaWx0ZXIoZG9tYWluID09IG5hbWUpDQogICwNCiAgIyBQIHZhbHVlcw0KICByZXRlc3RfY29yX3B2YWwgJT4lIA0KICAgIHNlbGVjdCgtcXVlc3QpICU+JSAjIHJlbW92ZSBxdWVzdGlvbm5haXJlcw0KICAgIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAicXVlc3QiKSAlPiUgICNhZGQgcmVhbCBxdWVzdGlvbm5haXJlcw0KICAgIHNlcGFyYXRlKC4sIGNvbCA9ICJxdWVzdCIsIGludG8gPSBjKCJxdWVzdCIsImRvbWFpbiIsInN1bSIsICJ0aW1lIikpICU+JSNyZW5hbWUgYW5kIHNlcGFyYXRlDQogICAgZmlsdGVyKHRpbWUgPT0gIngiKSAlPiUgDQogICAgc2VsZWN0KC1zdW0sIC10aW1lKSAlPiUgDQogICAgc2VsZWN0KHF1ZXN0LCBkb21haW4sIGVuZHNfd2l0aCgieSIpKSAlPiUgI3NlbGVjdCBldmVyeXRoaW5nDQogICAgcGl2b3RfbG9uZ2VyKC1jKCJxdWVzdCIsImRvbWFpbiIpKSU+JSAgI3RvIG1hdGNoDQogICAgbXV0YXRlKG5hbWUgPXN0cl9leHRyYWN0X2FsbChuYW1lLCAiXFx3Kyg/PV8pIiwgc2ltcGxpZnkgPSBUKSkgJT4lICNmaWx0ZXIgc2FtZSBkb21haW4NCiAgICBmaWx0ZXIoZG9tYWluID09IG5hbWUpICU+JSANCiAgICByZW5hbWUocHZhbD12YWx1ZSkgJT4lIG11dGF0ZShwdmFsID0gcm91bmQocHZhbCwzKSkNCikgJT4lIA0KIG11dGF0ZV9hdCh2YXJzKGRvbWFpbiwgbmFtZSksIH5zdHJfcmVwbGFjZSguLCAiYyIsIkNvbW11bmljYXRpb24iKSAlPiUgDQogICAgICAgICAgICAgc3RyX3JlcGxhY2VfYWxsKC4sICJnbSIsIkdyb3NzIE1vdG9yIikgJT4lIA0KICAgICAgICAgICAgIHN0cl9yZXBsYWNlX2FsbCguLCAiQ29tbXVuaWNhdGlvbmciLCJQcm9ibGVtIFNvbHZpbmciKSAlPiUgI2dhbWJpYXJyYQ0KICAgICAgICAgICAgIHN0cl9yZXBsYWNlX2FsbCguLCAicHMiLCJQZXJzb25hbC1Tb2NpYWwiKSAlPiUgDQogICAgICAgICAgICAgc3RyX3JlcGxhY2VfYWxsKC4sICJmbSIsIkZpbmUgTW90b3IiKSkNCiAgDQoNCmxlZnRfam9pbih0ZXN0X3Jlc3RfdGFibGUsICANCmRzX3JldGVzdF9hbmFseXNpcyAlPiUgDQogIGNvdW50KHF1ZXN0KSAlPiUgbXV0YXRlKHF1ZXN0PWFzLmNoYXJhY3RlcihxdWVzdCkpKQ0KYGBgDQoNCg0KYGBge3J9DQpkc19yZXRlc3RfYW5hbHlzaXMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gNCkgJT4lIA0KICB7Y29yLnRlc3QoLiRjX3N1bS54LCAuJGNfc3VtLnkpfQ0KYGBgDQpgYGB7cn0NCmRzX3JldGVzdF9hbmFseXNpcyAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSAxNikgJT4lIA0KICB7Y29yLnRlc3QoLiRmbV9zdW0ueCwgLiRmbV9zdW0ueSl9DQpgYGANCg0KIyMgUmV0ZXN0IHN1bW1hcnkNCg0KYGBge3J9DQp0ZXN0X3Jlc3RfdGFibGUgJT4lIA0KICBmaWx0ZXIocHZhbCA8PSAwLjA1KSAlPiUgDQogIHRhYmxlYnkoZG9tYWlufnZhbHVlLCBkYXRhID0gLikgJT4lIA0KICBzdW1tYXJ5KCkNCmBgYA0KDQoNCg0KIyMgR3JhcGgNCg0KYGBge3J9DQp0ZXN0X3Jlc3RfdGFibGUgJT4lIA0KICBtdXRhdGUocXVlc3Q9ICBhcy5udW1lcmljKHF1ZXN0KSkgJT4lIA0KICBmaWx0ZXIocHZhbCA8PSAwLjA1KSAlPiUgDQogIGdncGxvdChhZXMoeCA9IHF1ZXN0LCB5ID0gdmFsdWUpKSArDQogIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gZG9tYWluKSwgYWxwaGEgPSAwLjUsIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgI2dlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gImRhcmtncmF5Iiwgc2UgPSBGQUxTRSkgKw0KICBmYWNldF93cmFwKC4gfiBkb21haW4sIG5jb2wgPSAyKSArDQogIGxhYnMoeD0iIiwgeSA9ICJyIikgKw0KICB5bGltKDAsMSkrDQogIHRoZW1lX2J3KCkNCmBgYA0KIyBJbnRlcm9icw0KDQojIFRlc3QtUmV0ZXN0IHJlbGlhYmlsaXR5DQoNCg0KYGBge3J9DQpkc19yYXRlcl9hbmFseXNpcyANCmBgYA0KDQoNCmBgYHtyIGNvcnJlbGF0aW9uIG9sZDIsIGV2YWwgPSBGQUxTRSB9DQpkc19yYXRlcl9hbmFseXNpcyAlPiUNCiAgc2VsZWN0X2lmKGlzLm51bWVyaWMpICU+JQ0KICBncm91cF9ieShxdWVzdCkgJT4lDQogIG5lc3QoKSAlPiUNCiAgbXV0YXRlKA0KICAgIGNvcnJlbGF0aW9ucyA9IG1hcChkYXRhLCBjb3Jycjo6Y29ycmVsYXRlKQ0KICApICU+JQ0KICB1bm5lc3QoY29ycmVsYXRpb25zKQ0KDQpgYGANCg0KIyMgR3JvdXBlZCBjb3JyDQoNCmBgYHtyfQ0KZHNfcmF0ZXJfYW5hbHlzaXMgJT4lIA0KICBjb3VudChxdWVzdCkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBwZWFyc29uIGNvcnJlbGF0aW9uDQpyYXRlcl9jb3IgPC0gZHNfcmF0ZXJfYW5hbHlzaXMgJT4lIA0KICBzcGxpdChsaXN0KC4kcXVlc3QpKSAlPiUgDQogIGtlZXAofm5yb3coLikgPiA0KSAlPiUgDQogIG1hcCh+SG1pc2M6OnJjb3JyKGFzLm1hdHJpeCguKSkkcikgDQojIGNyZWF0ZSBhIGNvbHVtbiB3aXRoIHF1ZXN0aW9ubmFpcmUNCg0KcmF0ZXJfY29yIDwtIGRvLmNhbGwocmJpbmQuZGF0YS5mcmFtZSwgcmF0ZXJfY29yKQ0KDQojIFAgdmF1ZXMgb2YgcGVhcnNvbiBjb3JyZWxhdGlvbg0KcmF0ZXJfY29yX3B2YWwgPC0gZHNfcmF0ZXJfYW5hbHlzaXMgJT4lIA0KICBzcGxpdChsaXN0KC4kcXVlc3QpKSAlPiUgDQogIGtlZXAofm5yb3coLikgPiA0KSAlPiUgDQogIG1hcCh+SG1pc2M6OnJjb3JyKGFzLm1hdHJpeCguKSkkUCkNCiMgY3JlYXRlIGEgY29sdW1uIHdpdGggcXVlc3Rpb25uYWlyZQ0KcmF0ZXJfY29yX3B2YWwgPC0gZG8uY2FsbChyYmluZC5kYXRhLmZyYW1lLCByYXRlcl9jb3JfcHZhbCkNCg0KYGBgDQoNCiMjIFRhYmxlDQoNCmBgYHtyfQ0KcmF0ZXJfdGFibGUgPC0gbGVmdF9qb2luKA0KICAjIFIgQ09FRg0KICByYXRlcl9jb3IgJT4lIA0KICAgIHNlbGVjdCgtcXVlc3QpICU+JSAjIHJlbW92ZSBxdWVzdGlvbm5haXJlcw0KICAgIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAicXVlc3QiKSAlPiUgICNhZGQgcmVhbCBxdWVzdGlvbm5haXJlcw0KICAgIHNlcGFyYXRlKC4sIGNvbCA9ICJxdWVzdCIsIGludG8gPSBjKCJxdWVzdCIsImRvbWFpbiIsInN1bSIsICJ0aW1lIikpICU+JSNyZW5hbWUgYW5kIHNlcGFyYXRlDQogICAgZmlsdGVyKHRpbWUgPT0gIngiKSAlPiUgDQogICAgc2VsZWN0KC1zdW0sIC10aW1lKSAlPiUgDQogICAgc2VsZWN0KHF1ZXN0LCBkb21haW4sIGVuZHNfd2l0aCgieSIpKSAlPiUgI3NlbGVjdCBldmVyeXRoaW5nDQogICAgcGl2b3RfbG9uZ2VyKC1jKCJxdWVzdCIsImRvbWFpbiIpKSAlPiUgICN0byBtYXRjaA0KICAgIG11dGF0ZShuYW1lID1zdHJfZXh0cmFjdF9hbGwobmFtZSwgIlxcdysoPz1fKSIsIHNpbXBsaWZ5ID0gVCkpICU+JSAjZmlsdGVyIHNhbWUgZG9tYWluDQogICAgZmlsdGVyKGRvbWFpbiA9PSBuYW1lKQ0KICAsDQogICMgUCB2YWx1ZXMNCiAgcmF0ZXJfY29yX3B2YWwgJT4lIA0KICAgIHNlbGVjdCgtcXVlc3QpICU+JSAjIHJlbW92ZSBxdWVzdGlvbm5haXJlcw0KICAgIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAicXVlc3QiKSAlPiUgICNhZGQgcmVhbCBxdWVzdGlvbm5haXJlcw0KICAgIHNlcGFyYXRlKC4sIGNvbCA9ICJxdWVzdCIsIGludG8gPSBjKCJxdWVzdCIsImRvbWFpbiIsInN1bSIsICJ0aW1lIikpICU+JSNyZW5hbWUgYW5kIHNlcGFyYXRlDQogICAgZmlsdGVyKHRpbWUgPT0gIngiKSAlPiUgDQogICAgc2VsZWN0KC1zdW0sIC10aW1lKSAlPiUgDQogICAgc2VsZWN0KHF1ZXN0LCBkb21haW4sIGVuZHNfd2l0aCgieSIpKSAlPiUgI3NlbGVjdCBldmVyeXRoaW5nDQogICAgcGl2b3RfbG9uZ2VyKC1jKCJxdWVzdCIsImRvbWFpbiIpKSU+JSAgI3RvIG1hdGNoDQogICAgbXV0YXRlKG5hbWUgPXN0cl9leHRyYWN0X2FsbChuYW1lLCAiXFx3Kyg/PV8pIiwgc2ltcGxpZnkgPSBUKSkgJT4lICNmaWx0ZXIgc2FtZSBkb21haW4NCiAgICBmaWx0ZXIoZG9tYWluID09IG5hbWUpICU+JSANCiAgICByZW5hbWUocHZhbD12YWx1ZSkgJT4lIG11dGF0ZShwdmFsID0gcm91bmQocHZhbCwzKSkNCikgJT4lIA0KIG11dGF0ZV9hdCh2YXJzKGRvbWFpbiwgbmFtZSksIH5zdHJfcmVwbGFjZSguLCAiYyIsIkNvbW11bmljYXRpb24iKSAlPiUgDQogICAgICAgICAgICAgc3RyX3JlcGxhY2VfYWxsKC4sICJnbSIsIkdyb3NzIE1vdG9yIikgJT4lIA0KICAgICAgICAgICAgIHN0cl9yZXBsYWNlX2FsbCguLCAiQ29tbXVuaWNhdGlvbmciLCJQcm9ibGVtIFNvbHZpbmciKSAlPiUgI2dhbWJpYXJyYQ0KICAgICAgICAgICAgIHN0cl9yZXBsYWNlX2FsbCguLCAicHMiLCJQZXJzb25hbC1Tb2NpYWwiKSAlPiUgDQogICAgICAgICAgICAgc3RyX3JlcGxhY2VfYWxsKC4sICJmbSIsIkZpbmUgTW90b3IiKSkNCiAgDQoNCmxlZnRfam9pbihyYXRlcl90YWJsZSwgIA0KZHNfcmF0ZXJfYW5hbHlzaXMgJT4lIA0KICBjb3VudChxdWVzdCkgJT4lIG11dGF0ZShxdWVzdD1hcy5jaGFyYWN0ZXIocXVlc3QpKSkgJT4lIHdyaXRlLmNzdiguLCAiaWNjLmNzdiIpDQpgYGANCg0KDQpgYGB7cn0NCmRzX3JhdGVyX2FuYWx5c2lzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDcyKSAlPiUgDQogIHtjb3IudGVzdCguJGdtX3N1bS54LCAuJGdtX3N1bS55KX0NCmBgYA0KDQoNCmBgYHtyfQ0KZHNfcmF0ZXJfYW5hbHlzaXMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gMTYpICU+JSANCiAge2Nvci50ZXN0KC4kZm1fc3VtLngsIC4kZm1fc3VtLnkpfQ0KYGBgDQoNCiMjIFJhdGVyIHN1bW1hcnkNCg0KYGBge3J9DQpyYXRlcl90YWJsZSAlPiUgDQogIGZpbHRlcihwdmFsIDw9IDAuMDUpICU+JSANCiAgdGFibGVieShkb21haW5+dmFsdWUsIGRhdGEgPSAuKSAlPiUgDQogIHN1bW1hcnkoKQ0KYGBgDQoNCg0KDQojIyBHcmFwaA0KDQpgYGB7cn0NCnJhdGVyX3RhYmxlICU+JSANCiAgbXV0YXRlKHF1ZXN0PSAgYXMubnVtZXJpYyhxdWVzdCkpICU+JSANCiAgZmlsdGVyKHB2YWwgPD0gMC4wNSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBxdWVzdCwgeSA9IHZhbHVlKSkgKw0KICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGRvbWFpbiksIGFscGhhID0gMC41LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogICNnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICJkYXJrZ3JheSIsIHNlID0gRkFMU0UpICsNCiAgZmFjZXRfd3JhcCguIH4gZG9tYWluLCBuY29sID0gMikgKw0KICBsYWJzKHg9IiIsIHkgPSAiciIpICsNCiAgeWxpbSgwLDEpKw0KICB0aGVtZV9idygpDQpgYGANCg0KDQojIElSVCBhbmFseXNpcw0KDQpgYGB7cn0NCiNtaXJ0KGRhdGEgPSBkc19jb21fMlssLWMoMToyKV0sIG1vZGVsID0gMSwgaXRlbXR5cGUgPSAiZ3JhZGVkIikgJT4lIA0KIyAgaXRlbXBsb3QoLiwgMSkNCiNodHRwczovL2dyb3Vwcy5nb29nbGUuY29tL2cvbWlydC1wYWNrYWdlL2MvVjBBWDJhSVhTMTANCnBsb2dpcygzLjExOSwgbG9jYXRpb24gPSAtNSkNCnBsb2dpcygzLjExOSktcGxvZ2lzKDEuMjg2KQ0KaGVscChwbG9naXMpDQpgYGANCg0KDQojIyBHZW5lcmFsIGZ1bmN0aW9uDQoNCmBgYHtyfQ0KbGlicmFyeShtaXJ0KQ0KYXBwbHlfaXJ0X2NmYSA8LSBmdW5jdGlvbihkYXRhKSB7DQogIA0KICAjSVJUDQogIHNldC5zZWVkKDEyMykNCiAgbW9kX2lydCA8LSBtaXJ0KGRhdGEgPSBkYXRhLCBtb2RlbCA9IDEsIGl0ZW10eXBlID0gImdyYWRlZCIpDQogIG1vZF9jb2VmIDwtIGNvZWYobW9kX2lydCwgSVJUcGFycyA9IFQsIHNpbXBsaWZ5ID0gVCkgI2dldCBjbGFzc2ljYWwgSVJUIHBhcmFtZXRlcml6YXRpb24NCiAgbW9kX2ZpdCA8LSBNMihtb2RfaXJ0LG5hLnJtPVRSVUUpDQogIG1vZF9wbG90X3RyYWNlIDwtIHBsb3QobW9kX2lydCwgdHlwZSA9ICJ0cmFjZSIpDQogIA0KICAjQ0ZBDQogIGxpYnJhcnkobGF2YWFuKQ0KICBtb2RfY2ZhIDwtIGNmYShtb2RlbCA9IHBhc3RlKCJmMT1+IiwgcGFzdGUobmFtZXMoZGF0YSksIGNvbGxhcHNlPSIgKyAiKSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWRhdGEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0b3IgPSAnV0xTTScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkPW5hbWVzKGRhdGEpKSANCg0KICBtb2RfY2ZhX3Jlc3VsdCA8LSBzdW1tYXJ5KG1vZF9jZmEsIHN0YW5kYXJkaXplZD1UUlVFLCBmaXQubWVhc3VyZXMgPSBUUlVFKSAgDQoNCiAgI1JldHVybg0KICANCiAgcmV0dXJuKGxpc3QobW9kX3Bsb3RfdHJhY2UsbW9kX2ZpdCwgbW9kX2NvZWYpKQ0KfQ0KYGBgDQoNCg0KDQojIFJpc2sNCg0KYGBge3J9DQpkcyAlPiUgdGFieWwoc3VtbWF0aXZlX3Jpc2spICU+JSBhZG9ybl90b3RhbHMoInJvdyIpICU+JQ0KICBhZG9ybl9wY3RfZm9ybWF0dGluZyhkaWdpdHMgPSAyKQ0KYGBgDQoNCg0KYGBge3J9DQpsZXZlbF9vcmRlciA8LSBjKCdDb21tdW5pY2F0aW9uJywgJ0dyb3NzIE1vdG9yJywgJ0ZpbmUgTW90b3InLCJQcm9ibGVtIFNvbHZpbmciLCAiUGVyc29uYWwtU29jaWFsIikgDQpkcyAlPiUNCiAgZmlsdGVyKCFpcy5uYShzdW1tYXRpdmVfcmlzaykpICU+JSAgI2Rvbid0IHVzZQ0KICBmaWx0ZXIocXVlc3QgIT05ICYgcXVlc3QgIT0gNzIpICU+JSANCiAgc2VsZWN0KHF1ZXN0LCBzdW1tYXRpdmVfcmlzaywgY19zdW06cHNfc3VtKSAlPiUgDQogIG11dGF0ZShzdW1tYXRpdmVfcmlzayA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHN1bW1hdGl2ZV9yaXNrKSkpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtYyhxdWVzdCwgc3VtbWF0aXZlX3Jpc2spKSU+JQ0KICBncm91cF9ieShxdWVzdCwgbmFtZSwgc3VtbWF0aXZlX3Jpc2spICU+JQ0KICBuZXN0KCkgJT4lIA0KICBtdXRhdGUobWVhbiA9IG1hcF9kYmwoZGF0YSwgfm1lYW4oLngkdmFsdWUpKSkgJT4lICANCiAgbXV0YXRlKHN1bW1hdGl2ZV9yaXNrID0gYXMuZmFjdG9yKHN1bW1hdGl2ZV9yaXNrKSkgJT4lIA0KICAjcGxvdA0KICBtdXRhdGUobmFtZSA9IGNhc2Vfd2hlbigNCiAgICBuYW1lID09ICJjX3N1bSIgfiAiQ29tbXVuaWNhdGlvbiIsDQogICAgbmFtZSA9PSAiZ21fc3VtIiB+ICJHcm9zcyBNb3RvciIsDQogICAgbmFtZSA9PSAiZm1fc3VtIiB+ICJGaW5lIE1vdG9yIiwNCiAgICBuYW1lID09ICJjZ19zdW0iIH4gIlByb2JsZW0gU29sdmluZyIsDQogICAgbmFtZSA9PSAicHNfc3VtIiB+ICJQZXJzb25hbC1Tb2NpYWwiKSkgJT4lIA0KICBnZ3Bsb3QoLiwNCiAgICAgICAgIGFlcyh4PWZhY3RvcihuYW1lLCBsZXZlbHMgPSBsZXZlbF9vcmRlciksIHk9bWVhbiwgZ3JvdXAgPSBzdW1tYXRpdmVfcmlzaywgZmlsbD1zdW1tYXRpdmVfcmlzaykpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1bi55PW1lYW4scG9zaXRpb249cG9zaXRpb25fZG9kZ2Uod2lkdGg9MC45NSksZ2VvbT0iYmFyIikgKw0KICBzdGF0X3N1bW1hcnkoZnVuLmRhdGE9bWVhbl9jbF9ub3JtYWwscG9zaXRpb249cG9zaXRpb25fZG9kZ2UoMC45NSksZ2VvbT0iZXJyb3JiYXIiKSArIA0KICBsYWJzKHggPSAiRG9tYWluIiwgeSA9ICJNZWFuIHNjb3JlcyIsIGZpbGwgPSAiUmlzayIpICsNCiAgdGhlbWVfYncoKSAgIysgZmFjZXRfd3JhcCh+cXVlc3QpDQpgYGANCg0KDQpOaWNlIHBsb3QgYnV0IG5vdCB1c2VkDQoNCmBgYHtyfQ0KZHMgJT4lDQogIGZpbHRlcighaXMubmEoc3VtbWF0aXZlX3Jpc2spKSAlPiUgDQogIGZpbHRlcihxdWVzdCAhPTkgJiBxdWVzdCAhPSA3MikgJT4lIA0KICBzZWxlY3QocXVlc3QsIHN1bW1hdGl2ZV9yaXNrLCBjX3N1bTpwc19zdW0pICU+JSANCiAgbXV0YXRlKHN1bW1hdGl2ZV9yaXNrID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoc3VtbWF0aXZlX3Jpc2spKSkgJT4lIA0KICBwaXZvdF9sb25nZXIoY29scyA9IC1jKHF1ZXN0LCBzdW1tYXRpdmVfcmlzaykpJT4lDQogIGdyb3VwX2J5KHF1ZXN0LCBuYW1lLCBzdW1tYXRpdmVfcmlzaykgJT4lDQogIG5lc3QoKSAlPiUgDQogIG11dGF0ZShtZWFuID0gbWFwX2RibChkYXRhLCB+bWVhbigueCR2YWx1ZSkpKSAlPiUgIA0KICBtdXRhdGUoc3VtbWF0aXZlX3Jpc2sgPSBhcy5mYWN0b3Ioc3VtbWF0aXZlX3Jpc2spKSAlPiUgDQogIGdncGxvdCguLA0KICAgICAgICAgYWVzKHg9cXVlc3QsIHk9bWVhbiwgZ3JvdXAgPSBpbnRlcmFjdGlvbihuYW1lICxzdW1tYXRpdmVfcmlzayksIGNvbG9yPW5hbWUpKSArDQogICNzdGF0X3N1bW1hcnkoZ2VvbT0ibGluZSIsIHNpemU9MS41LCBhZXMobGluZXR5cGU9c3VtbWF0aXZlX3Jpc2spKSArDQogIHN0YXRfc3VtbWFyeShmdW4ueT1tZWFuLHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuOTUpLGdlb209ImJhciIsIGFlcyhmaWxsID0gc3VtbWF0aXZlX3Jpc2spKSArDQogIHN0YXRfc3VtbWFyeShnZW9tPSJlcnJvcmJhciIsIHNpemU9MC4yLCB3aWR0aCA9IC4yKQ0KDQpgYGANCg0KDQojIyBQbG90IGZvciByZXBvcnQgDQoNCmBgYHtyfQ0KZHMgJT4lDQogIGZpbHRlcighaXMubmEoc3VtbWF0aXZlX3Jpc2spKSAlPiUgICNkb25gdCB1c2UgbWlzc2luZyBjYXNlcyBvbiByaXNrDQogIGZpbHRlcihzdW1tYXRpdmVfcmlzayAlaW4lIGMoMCwzKSkgJT4lICNleHRyZW1lIGdyb3VwcyAobm8gcmlzayB2cyBoaWdoIHJpc2spDQogIG11dGF0ZShzdW1tYXRpdmVfcmlzayA9IGlmX2Vsc2Uoc3VtbWF0aXZlX3Jpc2sgPT0gMCwiTm9ucmlzayIsIlJpc2siKSkgJT4lIA0KICBzZWxlY3QocXVlc3QsIHN1bW1hdGl2ZV9yaXNrLCBlbmRzX3dpdGgoInN1bSIpKSU+JSAjZ2V0IGFsbCB2YXJpYWJsZXMNCiAgcGl2b3RfbG9uZ2VyKGNfc3VtOnBzX3N1bSkgJT4lICN0cmFuZm9ybSB0byBsb25nIGZvcm1hdA0KICBtdXRhdGUobmFtZSA9IGNhc2Vfd2hlbigNCiAgICBuYW1lID09ICJjX3N1bSIgfiAiQ29tbXVuaWNhdGlvbiIsDQogICAgbmFtZSA9PSAiZ21fc3VtIiB+ICJHcm9zcyBNb3RvciIsDQogICAgbmFtZSA9PSAiZm1fc3VtIiB+ICJGaW5lIE1vdG9yIiwNCiAgICBuYW1lID09ICJjZ19zdW0iIH4gIlByb2JsZW0gU29sdmluZyIsDQogICAgbmFtZSA9PSAicHNfc3VtIiB+ICJQZXJzb25hbC1Tb2NpYWwiKSkgJT4lIA0KICAjcGxvdA0KICBnZ3Bsb3QoLiwgYWVzKHggPSBxdWVzdCwgeSA9IHZhbHVlLCBncm91cCA9IHN1bW1hdGl2ZV9yaXNrKSkgKw0KICBzdGF0X3N1bW1hcnkoZ2VvbSA9ICJsaW5lIiwgZnVuID0gbWVhbiwgYWVzKGxpbmV0eXBlID0gc3VtbWF0aXZlX3Jpc2spLCBzaXplPTEpICsNCiAgdGhlbWVfYncoKSArDQogIGxhYnMoeCA9ICIiLCB5ID0gIk1lYW4gc2NvcmVzIiwgbGluZXR5cGUgPSAiUmlzayBncm91cCIpICsNCiAgZmFjZXRfd3JhcCh+bmFtZSkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCiNzdGF0X3N1bW1hcnkoZ2VvbT0iZXJyb3JiYXIiLCBzaXplPTAuMSwgd2lkdGggPSAuMikNCmBgYA0KDQojIyBUYWJsZSB3aXRoIHAgdmFsdWVzDQpgYGB7cn0NCmRzICU+JQ0KICBmaWx0ZXIocXVlc3QgIT0gOSkgJT4lICNubyByaXNrIGhlcmUNCiAgZmlsdGVyKCFpcy5uYShzdW1tYXRpdmVfcmlzaykpICU+JSAgI2RvbmB0IHVzZSBtaXNzaW5nIGNhc2VzIG9uIHJpc2sNCiAgZmlsdGVyKHN1bW1hdGl2ZV9yaXNrICVpbiUgYygwLDMpKSAlPiUgI2V4dHJlbWUgZ3JvdXBzIChubyByaXNrIHZzIGhpZ2ggcmlzaykNCiAgbXV0YXRlKHN1bW1hdGl2ZV9yaXNrID0gaWZfZWxzZShzdW1tYXRpdmVfcmlzayA9PSAwLCJOb25yaXNrIiwiUmlzayIpKSAlPiUgDQogIHNlbGVjdChxdWVzdCwgc3VtbWF0aXZlX3Jpc2ssIGVuZHNfd2l0aCgic3VtIikpJT4lICNnZXQgYWxsIHZhcmlhYmxlcw0KICBwaXZvdF9sb25nZXIoY19zdW06cHNfc3VtKSAlPiUgDQogIG5lc3RfYnkobmFtZSxxdWVzdCkgJT4lICNncm91cCEhIQ0KICBtdXRhdGUobW9kZWwgPSBsaXN0KHQudGVzdCh2YWx1ZSB+IHN1bW1hdGl2ZV9yaXNrLCBkYXRhID0gZGF0YSwgdmFyLmVxdWFsPVQpJHAudmFsdWUpKSAlPiUgI2NvbXB1dGUgcCB2YWx1ZXMNCiAgdW5uZXN0KG1vZGVsKSAlPiUgDQogICNzcGxpdCguJHF1ZXN0KSU+JSAgI3VuZ3JvdXANCiAgZmlsdGVyKG1vZGVsIDw9IDAuMDUpICU+JSANCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IHF1ZXN0LCBuYW1lc19mcm9tID0gbmFtZSwgdmFsdWVzX2Zyb20gPSBtb2RlbCkgJT4lICN1bm5lc3QgYmFzZWQgb24gcCB2YWx1ZXMNCiAgI3ByZXNlbnQNCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIHJvdW5kLCAyKSAlPiUgDQogIGFycmFuZ2UocXVlc3QpDQoNCmBgYA0KDQoNCg0KIyMgSW5kaXZpZHVhbCBwbG90IGlmIG5lZWRlZA0KDQojIyMgQ29tbXVuaWNhdGlvbiANCg0KYGBge3J9DQpkcyAlPiUgDQogIGZpbHRlcighaXMubmEoc3VtbWF0aXZlX3Jpc2spKSAlPiUgDQogICAgZmlsdGVyKHN1bW1hdGl2ZV9yaXNrICVpbiUgYygwLDMpKSAlPiUgI2V4dHJlbWUgZ3JvdXBzDQogIG11dGF0ZShzdW1tYXRpdmVfcmlzayA9IGlmX2Vsc2Uoc3VtbWF0aXZlX3Jpc2sgPT0gMCwiTm9ucmlzayIsIlJpc2siKSkgJT4lIA0KICBnZ3Bsb3QoLiwgYWVzKHg9cXVlc3QsIHkgPSBjX3N1bSwgbGluZXR5cGU9c3VtbWF0aXZlX3Jpc2ssIGdyb3VwPXN1bW1hdGl2ZV9yaXNrKSkgKw0KICBzdGF0X3N1bW1hcnkoZ2VvbSA9ICJsaW5lIiwgZnVuID0gbWVhbiwgc2l6ZT0xKSArDQogIHN0YXRfc3VtbWFyeShnZW9tPSJlcnJvcmJhciIsIHNpemU9MC4xLCB3aWR0aCA9IC4yKSsNCiAgdGhlbWVfYncoKSArDQogIGxhYnMoeCA9ICIiLCB5ID0gIk1lYW4gc2NvcmVzIiwgdGl0bGUgPSAiQ29tbXVuaWNhdGlvbiIsIGxpbmV0eXBlID0gIlJpc2sgZ3JvdXAiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQ0KYGBgDQoNCiMjIyBHcm9zcyBNb3RvciANCg0KYGBge3J9DQpkcyAlPiUgDQogIGZpbHRlcighaXMubmEoc3VtbWF0aXZlX3Jpc2spKSAlPiUgDQogICAgZmlsdGVyKHN1bW1hdGl2ZV9yaXNrICVpbiUgYygwLDMpKSAlPiUgI2V4dHJlbWUgZ3JvdXBzDQogIG11dGF0ZShzdW1tYXRpdmVfcmlzayA9IGlmX2Vsc2Uoc3VtbWF0aXZlX3Jpc2sgPT0gMCwiTm9ucmlzayIsIlJpc2siKSkgJT4lIA0KICBnZ3Bsb3QoLiwgYWVzKHg9cXVlc3QsIHkgPSBnbV9zdW0sIGxpbmV0eXBlPXN1bW1hdGl2ZV9yaXNrLCBncm91cD1zdW1tYXRpdmVfcmlzaykpICsgI2F0dGVudGlvbiBoZXJlISEhDQogIHN0YXRfc3VtbWFyeShnZW9tID0gImxpbmUiLCBmdW4gPSBtZWFuLCBzaXplPTEpICsNCiAgc3RhdF9zdW1tYXJ5KGdlb209ImVycm9yYmFyIiwgc2l6ZT0wLjEsIHdpZHRoID0gLjIpKw0KICB0aGVtZV9idygpICsNCiAgbGFicyh4ID0gIiIsIHkgPSAiTWVhbiBzY29yZXMiLCB0aXRsZSA9ICJHcm9zcyBNb3RvciIsIGxpbmV0eXBlID0gIlJpc2sgZ3JvdXAiKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQ0KYGBgDQojIyMgRmluZSBNb3RvciANCg0KYGBge3J9DQpkcyAlPiUgDQogIGZpbHRlcighaXMubmEoc3VtbWF0aXZlX3Jpc2spKSAlPiUgDQogICAgZmlsdGVyKHN1bW1hdGl2ZV9yaXNrICVpbiUgYygwLDMpKSAlPiUgI2V4dHJlbWUgZ3JvdXBzDQogIG11dGF0ZShzdW1tYXRpdmVfcmlzayA9IGlmX2Vsc2Uoc3VtbWF0aXZlX3Jpc2sgPT0gMCwiTm9ucmlzayIsIlJpc2siKSkgJT4lIA0KICBnZ3Bsb3QoLiwgYWVzKHg9cXVlc3QsIHkgPSBmbV9zdW0sIGxpbmV0eXBlPXN1bW1hdGl2ZV9yaXNrLCBncm91cD1zdW1tYXRpdmVfcmlzaykpICsgIyMgRmluZSBtb3RvciEhDQogIHN0YXRfc3VtbWFyeShnZW9tID0gImxpbmUiLCBmdW4gPSBtZWFuLCBzaXplPTEpICsNCiAgc3RhdF9zdW1tYXJ5KGdlb209ImVycm9yYmFyIiwgc2l6ZT0wLjEsIHdpZHRoID0gLjIpKw0KICB0aGVtZV9idygpICsNCiAgbGFicyh4ID0gIiIsIHkgPSAiTWVhbiBzY29yZXMiLCB0aXRsZSA9ICJGaW5lIE1vdG9yIiwgbGluZXR5cGUgPSAiUmlzayBncm91cCIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQpgYGANCg0KIyMjIFByb2JsZW0gU29sdmluZyANCg0KYGBge3J9DQpkcyAlPiUgDQogIGZpbHRlcighaXMubmEoc3VtbWF0aXZlX3Jpc2spKSAlPiUgDQogICAgZmlsdGVyKHN1bW1hdGl2ZV9yaXNrICVpbiUgYygwLDMpKSAlPiUgI2V4dHJlbWUgZ3JvdXBzDQogIG11dGF0ZShzdW1tYXRpdmVfcmlzayA9IGlmX2Vsc2Uoc3VtbWF0aXZlX3Jpc2sgPT0gMCwiTm9ucmlzayIsIlJpc2siKSkgJT4lIA0KICBnZ3Bsb3QoLiwgYWVzKHg9cXVlc3QsIHkgPSBjZ19zdW0sIGxpbmV0eXBlPXN1bW1hdGl2ZV9yaXNrLCBncm91cD1zdW1tYXRpdmVfcmlzaykpICsgIyMgUHJvYmxlbSBTb2x2aW5nID0gQ29nbml0aW9uDQogIHN0YXRfc3VtbWFyeShnZW9tID0gImxpbmUiLCBmdW4gPSBtZWFuLCBzaXplPTEpICsNCiAgc3RhdF9zdW1tYXJ5KGdlb209ImVycm9yYmFyIiwgc2l6ZT0wLjEsIHdpZHRoID0gLjIpKw0KICB0aGVtZV9idygpICsNCiAgbGFicyh4ID0gIiIsIHkgPSAiTWVhbiBzY29yZXMiLCB0aXRsZSA9ICJQcm9ibGVtIFNvbHZpbmciLCBsaW5ldHlwZSA9ICJSaXNrIGdyb3VwIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCmBgYA0KDQoNCiMjIyBQZXJzb25hbC1Tb2NpYWwNCg0KYGBge3J9DQpkcyAlPiUgDQogIGZpbHRlcighaXMubmEoc3VtbWF0aXZlX3Jpc2spKSAlPiUgDQogICAgZmlsdGVyKHN1bW1hdGl2ZV9yaXNrICVpbiUgYygwLDMpKSAlPiUgI2V4dHJlbWUgZ3JvdXBzDQogIG11dGF0ZShzdW1tYXRpdmVfcmlzayA9IGlmX2Vsc2Uoc3VtbWF0aXZlX3Jpc2sgPT0gMCwiTm9ucmlzayIsIlJpc2siKSkgJT4lIA0KICBnZ3Bsb3QoLiwgYWVzKHg9cXVlc3QsIHkgPSBwc19zdW0sIGxpbmV0eXBlPXN1bW1hdGl2ZV9yaXNrLCBncm91cD1zdW1tYXRpdmVfcmlzaykpICsgIyMgUGVyc29uYWwtU29jaWFsDQogIHN0YXRfc3VtbWFyeShnZW9tID0gImxpbmUiLCBmdW4gPSBtZWFuLCBzaXplPTEpICsNCiAgc3RhdF9zdW1tYXJ5KGdlb209ImVycm9yYmFyIiwgc2l6ZT0wLjEsIHdpZHRoID0gLjIpKw0KICB0aGVtZV9idygpICsNCiAgbGFicyh4ID0gIiIsIHkgPSAiTWVhbiBzY29yZXMiLCB0aXRsZSA9ICJQZXJzb25hbC1Tb2NpYWwiLCBsaW5ldHlwZSA9ICJSaXNrIGdyb3VwIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikNCmBgYA0KDQoNCiMjIEF0IHJpc2sgZGVzY3JpcHRpdmUNCg0KYGBge3J9DQpkcyAlPiUgDQogIGZpbHRlcighaXMubmEoc3VtbWF0aXZlX3Jpc2spKSAlPiUgDQogIHNlbGVjdChxdWVzdCwgc3VtbWF0aXZlX3Jpc2ssIGNfc3VtOnBzX3N1bSkgJT4lIA0KICBwaXZvdF9sb25nZXIoY19zdW06cHNfc3VtKSAlPiUgDQogIGdyb3VwX2J5KHF1ZXN0LHN1bW1hdGl2ZV9yaXNrLG5hbWUpICU+JQ0KICBzdW1tYXJpc2UobWVhbj1tZWFuKHZhbHVlLCBuYS5ybT1UKSwgc2QgPSBzZCh2YWx1ZSwgbmEucm0gPSBUKSkgJT4lIA0KICAjZmlyc3QgbGV2ZWwNCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IHF1ZXN0LCBuYW1lc19mcm9tID0gc3VtbWF0aXZlX3Jpc2s6bmFtZSwgdmFsdWVzX2Zyb20gPSBtZWFuOnNkLCAgbmFtZXNfZ2x1ZSA9ICJ7bmFtZX1fe3N1bW1hdGl2ZV9yaXNrfV97LnZhbHVlfSIpICU+JSANCiAgI3NlY29uZCBsZXZlbA0KICBwaXZvdF9sb25nZXIoY29scyA9IC1jKHF1ZXN0KSkgJT4lIA0KICBhcnJhbmdlKHF1ZXN0LG5hbWUpICU+JSANCiAgc2VwYXJhdGUobmFtZSwgaW50byA9IGMoImRvbWFpbiIsImNvbnN0YW50IiwicmlzayIsInJlc3VsdCIpKSAlPiUgDQogICN0aGlyZCBsZXZlbA0KICBzZWxlY3QoLWNvbnN0YW50KSAlPiUgDQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBxdWVzdCwgbmFtZXNfZnJvbSA9IGRvbWFpbjpyZXN1bHQsIHZhbHVlc19mcm9tID0gdmFsdWUpICU+JSANCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIHJvdW5kLCAyKSANCmBgYA0KDQoNCiMjIEF0IFJpc2sgVC1UZXN0DQoNCg0KYGBge3J9DQpkcyAlPiUgDQogICAgZmlsdGVyKCFpcy5uYShzdW1tYXRpdmVfcmlzaykpICU+JSANCiAgZmlsdGVyKHN1bW1hdGl2ZV9yaXNrICVpbiUgYygwLDMpKSAlPiUgI2NvbnRyYXN0aW5nIGdyb3VwcyBUIFRFU1QgSEVSRQ0KICBmaWx0ZXIocXVlc3QgIT05KSAlPiUgDQogIHNlbGVjdChxdWVzdCwgc3VtbWF0aXZlX3Jpc2ssIGNfc3VtOnBzX3N1bSkgJT4lIA0KICBwaXZvdF9sb25nZXIoY19zdW06cHNfc3VtKSAlPiUgDQogIGdyb3VwX2J5KHF1ZXN0LG5hbWUpICU+JSANCiAgbmVzdCgpICU+JSANCiAgbXV0YXRlKHBfcmlzayA9IG1hcChkYXRhLCB+YW92KHZhbHVlIH4gc3VtbWF0aXZlX3Jpc2ssIGRhdGEgPSAuKSAlPiUge3N1bW1hcnkoLilbWzFdXVtbIlByKD5GKSJdXVsxXX0pKSAlPiUgDQogIHVubmVzdF93aWRlcihwX3Jpc2spICU+JSANCiAgcmVuYW1lKHBfdmFsID0gIi4uLjEiKSAlPiUgDQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBxdWVzdCwgbmFtZXNfZnJvbSA9IG5hbWUsIHZhbHVlc19mcm9tID0gcF92YWwpICU+JSANCiAgbXV0YXRlX2lmKGlzLm51bWVyaWMsIHJvdW5kLCAzKQ0KDQpgYGANCg0KDQoNCg0KDQpgYGB7cn0NCmRzICU+JSANCmZpbHRlcihxdWVzdCA9PSAyKSAlPiUgDQogIGZpbHRlcihzdW1tYXRpdmVfcmlzayAlaW4lIGMoMCwzKSkgJT4lIA0KICB0LnRlc3QoY19zdW0gfiBzdW1tYXRpdmVfcmlzaywgZGF0YSA9IC4sIHZhci5lcXVhbD1UKQ0KICAjYW92KGNfc3VtIH4gc3VtbWF0aXZlX3Jpc2ssIGRhdGEgPSAuKSAlPiUgc3VtbWFyeSgpDQpgYGANCg0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwdWJyKQ0KZHMgJT4lIA0KICAgIGZpbHRlcighaXMubmEoc3VtbWF0aXZlX3Jpc2spKSAlPiUgDQogIGZpbHRlcihxdWVzdCAhPSAiOSIpICU+JSANCiAgZmlsdGVyKHN1bW1hdGl2ZV9yaXNrICVpbiUgYygwLDMpKSAlPiUgI2V4dHJlbWUgZ3JvdXBzDQogIG11dGF0ZShzdW1tYXRpdmVfcmlzayA9IGlmX2Vsc2Uoc3VtbWF0aXZlX3Jpc2sgPT0gMCwiTm9ucmlzayIsIlJpc2siKSkgJT4lIA0KICBzZWxlY3QocXVlc3QsIHN1bW1hdGl2ZV9yaXNrLCBjX3N1bSklPiUgDQogIGdnYm94cGxvdCguLCB4ID0gInN1bW1hdGl2ZV9yaXNrIiwgeSA9ICJjX3N1bSIsDQogICAgICAgICAgICBmYWNldC5ieSA9ICJxdWVzdCIsIHNob3J0LnBhbmVsLmxhYnMgPSBGQUxTRSkgKw0KICBzdGF0X2NvbXBhcmVfbWVhbnMobGFiZWwgPSAicC5mb3JtYXQiLCBtZXRob2QgPSAidC50ZXN0IixsYWJlbC54ID0gYygiUmlzayIpLCBsYWJlbC55ID0gMS41KQ0KYGBgDQoNCg0KDQoNCiMgRFMgZm9yIElSVCBhbmQgQ0ZBIGFuYWx5c2lzDQoNCiMjIEdlbmVyYWwgbW9kZWwNCg0KYGBge3J9DQptb2RfY2ZhIDwtICdjb20gPX4gY29tX2E0XzEgKyBjb21fYTRfMiArIGNvbV9hNF8zICsgY29tX2E0XzQgKyBjb21fYTRfNSArIGNvbV9hNF82DQpncm9zcyA9fiAgZ21fYTRfMSArIGdtX2E0XzIgKyBnbV9hNF8zICsgZ21fYTRfNCArIGdtX2E0XzUgKyBnbV9hNF82DQpmaW5lID1+IGZtX2E0XzEgKyBmbV9hNF8yICsgZm1fYTRfMyArIGZtX2E0XzQgKyBmbV9hNF81ICsgZm1fYTRfNg0KY29nID1+IGNnX2E0XzEgKyBjZ19hNF8yICsgY2dfYTRfMyArIGNnX2E0XzQgKyBjZ19hNF81ICsgY2dfYTRfNg0KcHMgPX4gcHNfYTRfMSArIHBzX2E0XzIgKyBwc19hNF8zICsgcHNfYTRfNCArIHBzX2E0XzUgKyBwc19hNF82DQonDQpgYGANCg0KDQpgYGB7cn0NCm1vZF9jZmFfYXNxMyA8LSAnY29tID1+IGNvbV9hM18xICsgY29tX2EzXzIgKyBjb21fYTNfMyArIGNvbV9hM180ICsgY29tX2EzXzUgKyBjb21fYTNfNg0KZ3Jvc3MgPX4gIGdtX2EzXzEgKyBnbV9hM18yICsgZ21fYTNfMyArIGdtX2EzXzQgKyBnbV9hM181ICsgZ21fYTNfNg0KZmluZSA9fiBmbV9hM18xICsgZm1fYTNfMiArIGZtX2EzXzMgKyBmbV9hM180ICsgZm1fYTNfNSArIGZtX2EzXzYNCmNvZyA9fiBjZ19hM18xICsgY2dfYTNfMiArIGNnX2EzXzMgKyBjZ19hM180ICsgY2dfYTNfNSArIGNnX2EzXzYNCnBzID1+IHBzX2EzXzEgKyBwc19hM18yICsgcHNfYTNfMyArIHBzX2EzXzQgKyBwc19hM181ICsgcHNfYTNfNg0KJw0KYGBgDQoNCg0KIyMgMi1tb250aHMNCg0KRGF0YXNldCANCg0KYGBge3J9DQpkc18yX2Z1bGwgPC0gZHMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gMikgJT4lIA0KICBzZWxlY3QoDQogIGNvbV9hNF8xLCBjb21fYTRfMiwgY29tX2E0XzMsIGNvbV9hNF80LCBjb21fYTRfNSwgY29tX2E0XzYsDQogIGdtX2E0XzEsIGdtX2E0XzIsIGdtX2E0XzMsIGdtX2E0XzQsIGdtX2E0XzUsIGdtX2E0XzYsDQogIGZtX2E0XzEsIGZtX2E0XzIsIGZtX2E0XzMsIGZtX2E0XzQsIGZtX2E0XzUsIGZtX2E0XzYsDQogIGNnX2E0XzEsIGNnX2E0XzIsIGNnX2E0XzMsIGNnX2E0XzQsIGNnX2E0XzUsIGNnX2E0XzYsDQogIHBzX2E0XzEsIHBzX2E0XzIsIHBzX2E0XzMsIHBzX2E0XzQsIHBzX2E0XzUsIHBzX2E0XzYpDQoNCmRzXzJfZnVsbCAlPiUgbXV0YXRlX2FsbChyZXBsYWNlX25hLC05OSklPiUgDQogIHdyaXRlLnRhYmxlKC4sIGZpbGU9ImRzXzJfZnVsbC5kYXQiLCByb3cubmFtZXM9RkFMU0UsIGNvbC5uYW1lcz1GQUxTRSwgc2VwPSJcdCIsIHF1b3RlPUZBTFNFKSAgIA0KDQpgYGANCg0KDQpDRkEgbW9kZWwNCg0KYGBge3J9DQptb2RfY2ZhXzIgPC0gY2ZhKG1vZGVsID0gbW9kX2NmYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZHNfMl9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc18yX2Z1bGwpKQ0KYGBgDQoNCkNGQSByZXN1bHRzDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RfY2ZhXzIsIHN0YW5kYXJkaXplZD1UUlVFLCBmaXQubWVhc3VyZXMgPSBUUlVFKSAgDQpgYGANCg0KDQpDb3JyZWxhdGlvbnMNCg0KDQpgYGB7cn0NCmNvdjJjb3IoaW5zcGVjdChtb2RfY2ZhXzIsIHdoYXQgPSAiZXN0IikkcHNpKQ0KYGBgDQoNCg0KYGBge3J9DQpjZmEobW9kZWwgPSBtb2RfY2ZhX2FzcTMsIA0KICAgIGRhdGEgPSANCiAgICAgIGRzX2ZpbmFsX21lcmdlZCAlPiUgDQogICAgICBmaWx0ZXIocXVlc3QgPT0gMikgJT4lIA0KICAgICAgc2VsZWN0KA0KICAgICAgICBjb21fYTNfMSwgY29tX2EzXzIsIGNvbV9hM18zLCBjb21fYTNfNCwgY29tX2EzXzUsIGNvbV9hM182LA0KICAgICAgICBnbV9hM18xLCBnbV9hM18yLCBnbV9hM18zLCBnbV9hM180LCBnbV9hM181LCBnbV9hM182LA0KICAgICAgICBmbV9hM18xLCBmbV9hM18yLCBmbV9hM18zLCBmbV9hM180LCBmbV9hM181LCBmbV9hM182LA0KICAgICAgICBjZ19hM18xLCBjZ19hM18yLCBjZ19hM18zLCBjZ19hM180LCBjZ19hM181LCBjZ19hM182LA0KICAgICAgICBwc19hM18xLCBwc19hM18yLCBwc19hM18zLCBwc19hM180LCBwc19hM181LCBwc19hM182KQ0KICAgICAgLA0KICAgIGVzdGltYXRvciA9ICdXTFNNJywNCiAgICBvcmRlcmVkPW5hbWVzKA0KICAgICAgZHNfZmluYWxfbWVyZ2VkICU+JSANCiAgICAgIGZpbHRlcihxdWVzdCA9PSAyKSAlPiUgDQogICAgICBzZWxlY3QoDQogICAgICAgIGNvbV9hM18xLCBjb21fYTNfMiwgY29tX2EzXzMsIGNvbV9hM180LCBjb21fYTNfNSwgY29tX2EzXzYsDQogICAgICAgIGdtX2EzXzEsIGdtX2EzXzIsIGdtX2EzXzMsIGdtX2EzXzQsIGdtX2EzXzUsIGdtX2EzXzYsDQogICAgICAgIGZtX2EzXzEsIGZtX2EzXzIsIGZtX2EzXzMsIGZtX2EzXzQsIGZtX2EzXzUsIGZtX2EzXzYsDQogICAgICAgIGNnX2EzXzEsIGNnX2EzXzIsIGNnX2EzXzMsIGNnX2EzXzQsIGNnX2EzXzUsIGNnX2EzXzYsDQogICAgICAgIHBzX2EzXzEsIHBzX2EzXzIsIHBzX2EzXzMsIHBzX2EzXzQsIHBzX2EzXzUsIHBzX2EzXzYpDQogICAgKSkgJT4lIHN1bW1hcnkoLiwgc3RhbmRhcmRpemVkPVRSVUUsIGZpdC5tZWFzdXJlcyA9IFRSVUUpDQoNCmBgYA0KDQoNCg0KIyMgNC1tb250aHMNCg0KRGF0YXNldCANCg0KYGBge3J9DQpkc180X2Z1bGwgPC0gZHMgJT4lICNhdHRlbnRpb24gaGVyZSB0byBzcGVjaWZ5IHRoZSBjb3JyZWN0IGRhdGFzZXQgDQogIGZpbHRlcihxdWVzdCA9PSA0KSAlPiUgDQogIHNlbGVjdCgNCiAgY29tX2E0XzEsIGNvbV9hNF8yLCBjb21fYTRfMywgY29tX2E0XzQsIGNvbV9hNF81LCBjb21fYTRfNiwNCiAgZ21fYTRfMSwgZ21fYTRfMiwgZ21fYTRfMywgZ21fYTRfNCwgZ21fYTRfNSwgZ21fYTRfNiwNCiAgZm1fYTRfMSwgZm1fYTRfMiwgZm1fYTRfMywgZm1fYTRfNCwgZm1fYTRfNSwgZm1fYTRfNiwNCiAgY2dfYTRfMSwgY2dfYTRfMiwgY2dfYTRfMywgY2dfYTRfNCwgY2dfYTRfNSwgY2dfYTRfNiwNCiAgcHNfYTRfMSwgcHNfYTRfMiwgcHNfYTRfMywgcHNfYTRfNCwgcHNfYTRfNSwgcHNfYTRfNikNCg0KI3dyaXRlLnRhYmxlKGRzXzRfZnVsbCwgZmlsZT0iZHNfNF9mdWxsLmRhdCIsIHJvdy5uYW1lcz1GQUxTRSwgY29sLm5hbWVzPUZBTFNFLCBzZXA9Ilx0IiwgcXVvdGU9RkFMU0UpICAgDQoNCmBgYA0KDQpDRkEgbW9kZWwNCg0KYGBge3J9DQptb2RfY2ZhXzQgPC0gY2ZhKG1vZGVsID0gbW9kX2NmYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZHNfNF9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc180X2Z1bGwpKQ0KYGBgDQoNCkNGQSByZXN1bHRzDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RfY2ZhXzQsIHN0YW5kYXJkaXplZD1UUlVFLCBmaXQubWVhc3VyZXMgPSBUUlVFKSAgDQpgYGANCg0KDQpDb3JyZWxhdGlvbnMNCg0KDQpgYGB7cn0NCmNvdjJjb3IoaW5zcGVjdChtb2RfY2ZhXzQsIHdoYXQgPSAiZXN0IikkcHNpKQ0KYGBgDQoNCg0KDQoNCiMjIDYtbW9udGhzDQoNCkRhdGFzZXQgDQoNCmBgYHtyfQ0KZHNfNl9mdWxsIDwtIGRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDYpICU+JSANCiAgc2VsZWN0KA0KICBjb21fYTRfMSwgY29tX2E0XzIsIGNvbV9hNF8zLCBjb21fYTRfNCwgY29tX2E0XzUsIGNvbV9hNF82LA0KICBnbV9hNF8xLCBnbV9hNF8yLCBnbV9hNF8zLCBnbV9hNF80LCBnbV9hNF81LCBnbV9hNF82LA0KICBmbV9hNF8xLCBmbV9hNF8yLCBmbV9hNF8zLCBmbV9hNF80LCBmbV9hNF81LCBmbV9hNF82LA0KICBjZ19hNF8xLCBjZ19hNF8yLCBjZ19hNF8zLCBjZ19hNF80LCBjZ19hNF81LCBjZ19hNF82LA0KICBwc19hNF8xLCBwc19hNF8yLCBwc19hNF8zLCBwc19hNF80LCBwc19hNF81LCBwc19hNF82KQ0KDQojd3JpdGUudGFibGUoZHNfNl9mdWxsLCBmaWxlPSJkc182X2Z1bGwuZGF0Iiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UsIHNlcD0iXHQiLCBxdW90ZT1GQUxTRSkgICANCmBgYA0KDQpDRkEgbW9kZWwNCg0KYGBge3J9DQptb2RfY2ZhXzYgPC0gY2ZhKG1vZGVsID0gbW9kX2NmYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZHNfNl9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc182X2Z1bGwpKQ0KYGBgDQoNCkNGQSByZXN1bHRzDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RfY2ZhXzYsIHN0YW5kYXJkaXplZD1UUlVFLCBmaXQubWVhc3VyZXMgPSBUUlVFKSAgDQpgYGANCg0KDQpDb3JyZWxhdGlvbnMNCg0KDQpgYGB7cn0NCmNvdjJjb3IoaW5zcGVjdChtb2RfY2ZhXzYsIHdoYXQgPSAiZXN0IikkcHNpKQ0KYGBgDQoNCg0KIyMgOC1tb250aHMNCg0KRGF0YXNldCANCg0KYGBge3J9DQpkc184X2Z1bGwgPC0gZHMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gOCkgJT4lIA0KICBzZWxlY3QoDQogIGNvbV9hNF8xLCBjb21fYTRfMiwgY29tX2E0XzMsIGNvbV9hNF80LCBjb21fYTRfNSwgY29tX2E0XzYsDQogIGdtX2E0XzEsIGdtX2E0XzIsIGdtX2E0XzMsIGdtX2E0XzQsIGdtX2E0XzUsIGdtX2E0XzYsDQogIGZtX2E0XzEsIGZtX2E0XzIsIGZtX2E0XzMsIGZtX2E0XzQsIGZtX2E0XzUsIGZtX2E0XzYsDQogIGNnX2E0XzEsIGNnX2E0XzIsIGNnX2E0XzMsIGNnX2E0XzQsIGNnX2E0XzUsIGNnX2E0XzYsDQogIHBzX2E0XzEsIHBzX2E0XzIsIHBzX2E0XzMsIHBzX2E0XzQsIHBzX2E0XzUsIHBzX2E0XzYpDQojd3JpdGUudGFibGUoZHNfOF9mdWxsLCBmaWxlPSJkc184X2Z1bGwuZGF0Iiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UsIHNlcD0iXHQiLCBxdW90ZT1GQUxTRSkgICANCmBgYA0KDQoNCkNGQSBtb2RlbA0KDQpgYGB7cn0NCm1vZF9jZmFfOCA8LSBjZmEobW9kZWwgPSBtb2RfY2ZhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1kc184X2Z1bGwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0b3IgPSAnV0xTTScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkPW5hbWVzKGRzXzhfZnVsbCkpDQpgYGANCg0KQ0ZBIHJlc3VsdHMNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZF9jZmFfOCwgc3RhbmRhcmRpemVkPVRSVUUsIGZpdC5tZWFzdXJlcyA9IFRSVUUpICANCmBgYA0KDQoNCkNvcnJlbGF0aW9ucw0KDQoNCmBgYHtyfQ0KY292MmNvcihpbnNwZWN0KG1vZF9jZmFfOCwgd2hhdCA9ICJlc3QiKSRwc2kpDQpgYGANCg0KDQojIyAxMC1tb250aHMNCg0KRGF0YXNldCANCg0KYGBge3J9DQpkc18xMF9mdWxsIDwtIGRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDEwKSAlPiUgDQogIHNlbGVjdCgNCiAgY29tX2E0XzEsIGNvbV9hNF8yLCBjb21fYTRfMywgY29tX2E0XzQsIGNvbV9hNF81LCBjb21fYTRfNiwNCiAgZ21fYTRfMSwgZ21fYTRfMiwgZ21fYTRfMywgZ21fYTRfNCwgZ21fYTRfNSwgZ21fYTRfNiwNCiAgZm1fYTRfMSwgZm1fYTRfMiwgZm1fYTRfMywgZm1fYTRfNCwgZm1fYTRfNSwgZm1fYTRfNiwNCiAgY2dfYTRfMSwgY2dfYTRfMiwgY2dfYTRfMywgY2dfYTRfNCwgY2dfYTRfNSwgY2dfYTRfNiwNCiAgcHNfYTRfMSwgcHNfYTRfMiwgcHNfYTRfMywgcHNfYTRfNCwgcHNfYTRfNSwgcHNfYTRfNikNCg0KI3dyaXRlLnRhYmxlKGRzXzEwX2Z1bGwsIGZpbGU9ImRzXzEwX2Z1bGwuZGF0Iiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UsIHNlcD0iXHQiLCBxdW90ZT1GQUxTRSkgICANCg0KYGBgDQoNCg0KQ0ZBIG1vZGVsDQoNCmBgYHtyfQ0KbW9kX2NmYV8xMCA8LSBjZmEobW9kZWwgPSBtb2RfY2ZhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1kc18xMF9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc18xMF9mdWxsKSkNCmBgYA0KDQpDRkEgcmVzdWx0cw0KDQpgYGB7cn0NCnN1bW1hcnkobW9kX2NmYV8xMCwgc3RhbmRhcmRpemVkPVRSVUUsIGZpdC5tZWFzdXJlcyA9IFRSVUUpICANCmBgYA0KDQoNCkNvcnJlbGF0aW9ucw0KDQoNCmBgYHtyfQ0KY292MmNvcihpbnNwZWN0KG1vZF9jZmFfMTAsIHdoYXQgPSAiZXN0IikkcHNpKQ0KYGBgDQoNCg0KDQojIyAxMi1tb250aHMNCg0KRGF0YXNldCANCg0KYGBge3J9DQpkc18xMl9mdWxsIDwtIGRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDEyKSAlPiUgDQogIHNlbGVjdCgNCiAgY29tX2E0XzEsIGNvbV9hNF8yLCBjb21fYTRfMywgY29tX2E0XzQsIGNvbV9hNF81LCBjb21fYTRfNiwNCiAgZ21fYTRfMSwgZ21fYTRfMiwgZ21fYTRfMywgZ21fYTRfNCwgZ21fYTRfNSwgZ21fYTRfNiwNCiAgZm1fYTRfMSwgZm1fYTRfMiwgZm1fYTRfMywgZm1fYTRfNCwgZm1fYTRfNSwgZm1fYTRfNiwNCiAgY2dfYTRfMSwgY2dfYTRfMiwgY2dfYTRfMywgY2dfYTRfNCwgY2dfYTRfNSwgY2dfYTRfNiwNCiAgcHNfYTRfMSwgcHNfYTRfMiwgcHNfYTRfMywgcHNfYTRfNCwgcHNfYTRfNSwgcHNfYTRfNikNCg0KI3dyaXRlLnRhYmxlKGRzXzEyX2Z1bGwsIGZpbGU9ImRzXzEyX2Z1bGwuZGF0Iiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UsIHNlcD0iXHQiLCBxdW90ZT1GQUxTRSkgICANCg0KYGBgDQoNCg0KQ0ZBIG1vZGVsDQoNCmBgYHtyfQ0KbW9kX2NmYV8xMiA8LSBjZmEobW9kZWwgPSBtb2RfY2ZhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1kc18xMl9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc18xMl9mdWxsKSkNCmBgYA0KDQpDRkEgcmVzdWx0cw0KDQpgYGB7cn0NCnN1bW1hcnkobW9kX2NmYV8xMiwgc3RhbmRhcmRpemVkPVRSVUUsIGZpdC5tZWFzdXJlcyA9IFRSVUUpICANCmBgYA0KDQoNCkNvcnJlbGF0aW9ucw0KDQoNCmBgYHtyfQ0KY292MmNvcihpbnNwZWN0KG1vZF9jZmFfMTIsIHdoYXQgPSAiZXN0IikkcHNpKQ0KYGBgDQoNCg0KIyMgMTQtbW9udGhzDQoNCkRhdGFzZXQgDQoNCmBgYHtyfQ0KZHNfMTRfZnVsbCA8LSBkcyAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSAxNCkgJT4lIA0KICBzZWxlY3QoDQogIGNvbV9hNF8xLCBjb21fYTRfMiwgY29tX2E0XzMsIGNvbV9hNF80LCBjb21fYTRfNSwgY29tX2E0XzYsDQogIGdtX2E0XzEsIGdtX2E0XzIsIGdtX2E0XzMsIGdtX2E0XzQsIGdtX2E0XzUsIGdtX2E0XzYsDQogIGZtX2E0XzEsIGZtX2E0XzIsIGZtX2E0XzMsIGZtX2E0XzQsIGZtX2E0XzUsIGZtX2E0XzYsDQogIGNnX2E0XzEsIGNnX2E0XzIsIGNnX2E0XzMsIGNnX2E0XzQsIGNnX2E0XzUsIGNnX2E0XzYsDQogIHBzX2E0XzEsIHBzX2E0XzIsIHBzX2E0XzMsIHBzX2E0XzQsIHBzX2E0XzUsIHBzX2E0XzYpDQoNCiN3cml0ZS50YWJsZShkc18xNF9mdWxsLCBmaWxlPSJkc18xNF9mdWxsLmRhdCIsIHJvdy5uYW1lcz1GQUxTRSwgY29sLm5hbWVzPUZBTFNFLCBzZXA9Ilx0IiwgcXVvdGU9RkFMU0UpICAgDQpgYGANCg0KDQpDRkEgbW9kZWwNCg0KYGBge3J9DQptb2RfY2ZhXzE0IDwtIGNmYShtb2RlbCA9IG1vZF9jZmEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWRzXzE0X2Z1bGwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0b3IgPSAnV0xTTScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkPW5hbWVzKGRzXzE0X2Z1bGwpKQ0KYGBgDQoNCkNGQSByZXN1bHRzDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RfY2ZhXzE0LCBzdGFuZGFyZGl6ZWQ9VFJVRSwgZml0Lm1lYXN1cmVzID0gVFJVRSkgIA0KYGBgDQoNCg0KQ29ycmVsYXRpb25zDQoNCg0KYGBge3J9DQpjb3YyY29yKGluc3BlY3QobW9kX2NmYV8xNCwgd2hhdCA9ICJlc3QiKSRwc2kpDQpgYGANCg0KDQojIyAxNi1tb250aHMNCg0KRGF0YXNldCANCg0KYGBge3J9DQpkc18xNl9mdWxsIDwtIGRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDE2KSAlPiUgDQogIHNlbGVjdCgNCiAgY29tX2E0XzEsIGNvbV9hNF8yLCBjb21fYTRfMywgY29tX2E0XzQsIGNvbV9hNF81LCBjb21fYTRfNiwNCiAgZ21fYTRfMSwgZ21fYTRfMiwgZ21fYTRfMywgZ21fYTRfNCwgZ21fYTRfNSwgZ21fYTRfNiwNCiAgZm1fYTRfMSwgZm1fYTRfMiwgZm1fYTRfMywgZm1fYTRfNCwgZm1fYTRfNSwgZm1fYTRfNiwNCiAgY2dfYTRfMSwgY2dfYTRfMiwgY2dfYTRfMywgY2dfYTRfNCwgY2dfYTRfNSwgY2dfYTRfNiwNCiAgcHNfYTRfMSwgcHNfYTRfMiwgcHNfYTRfMywgcHNfYTRfNCwgcHNfYTRfNSwgcHNfYTRfNikNCg0KI3dyaXRlLnRhYmxlKGRzXzE2X2Z1bGwsIGZpbGU9ImRzXzE2X2Z1bGwuZGF0Iiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UsIHNlcD0iXHQiLCBxdW90ZT1GQUxTRSkgICANCg0KYGBgDQoNCg0KQ0ZBIG1vZGVsDQoNCmBgYHtyfQ0KbW9kX2NmYV8xNiA8LSBjZmEobW9kZWwgPSBtb2RfY2ZhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1kc18xNl9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc18xNl9mdWxsKSkNCmBgYA0KDQpDRkEgcmVzdWx0cw0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RfY2ZhXzE2LCBzdGFuZGFyZGl6ZWQ9VFJVRSwgZml0Lm1lYXN1cmVzID0gVFJVRSkgIA0KYGBgDQoNCg0KQ29ycmVsYXRpb25zDQoNCg0KYGBge3J9DQpjb3YyY29yKGluc3BlY3QobW9kX2NmYV8xNiwgd2hhdCA9ICJlc3QiKSRwc2kpDQpgYGANCg0KDQoNCiMjIDE4LW1vbnRocw0KDQpEYXRhc2V0IA0KDQpgYGB7cn0NCmRzXzE4X2Z1bGwgPC0gZHMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gMTgpICU+JSANCiAgc2VsZWN0KA0KICBjb21fYTRfMSwgY29tX2E0XzIsIGNvbV9hNF8zLCBjb21fYTRfNCwgY29tX2E0XzUsIGNvbV9hNF82LA0KICBnbV9hNF8xLCBnbV9hNF8yLCBnbV9hNF8zLCBnbV9hNF80LCBnbV9hNF81LCBnbV9hNF82LA0KICBmbV9hNF8xLCBmbV9hNF8yLCBmbV9hNF8zLCBmbV9hNF80LCBmbV9hNF81LCBmbV9hNF82LA0KICBjZ19hNF8xLCBjZ19hNF8yLCBjZ19hNF8zLCBjZ19hNF80LCBjZ19hNF81LCBjZ19hNF82LA0KICBwc19hNF8xLCBwc19hNF8yLCBwc19hNF8zLCBwc19hNF80LCBwc19hNF81LCBwc19hNF82KQ0KDQojd3JpdGUudGFibGUoZHNfMThfZnVsbCwgZmlsZT0iZHNfMThfZnVsbC5kYXQiLCByb3cubmFtZXM9RkFMU0UsIGNvbC5uYW1lcz1GQUxTRSwgc2VwPSJcdCIsIHF1b3RlPUZBTFNFKSAgIA0KDQpgYGANCg0KDQpDRkEgbW9kZWwNCg0KYGBge3J9DQptb2RfY2ZhXzE4IDwtIGNmYShtb2RlbCA9IG1vZF9jZmEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWRzXzE4X2Z1bGwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0b3IgPSAnV0xTTScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkPW5hbWVzKGRzXzE4X2Z1bGwpKQ0KYGBgDQoNCkNGQSByZXN1bHRzDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RfY2ZhXzE4LCBzdGFuZGFyZGl6ZWQ9VFJVRSwgZml0Lm1lYXN1cmVzID0gVFJVRSkgIA0KYGBgDQoNCkNvcnJlbGF0aW9ucw0KDQoNCmBgYHtyfQ0KY292MmNvcihpbnNwZWN0KG1vZF9jZmFfMTgsIHdoYXQgPSAiZXN0IikkcHNpKQ0KYGBgDQoNCiMjIDIwLW1vbnRocw0KDQpEYXRhc2V0IA0KDQpgYGB7cn0NCmRzXzIwX2Z1bGwgPC0gZHMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gMjApICU+JSANCiAgc2VsZWN0KA0KICBjb21fYTRfMSwgY29tX2E0XzIsIGNvbV9hNF8zLCBjb21fYTRfNCwgY29tX2E0XzUsIGNvbV9hNF82LA0KICBnbV9hNF8xLCBnbV9hNF8yLCBnbV9hNF8zLCBnbV9hNF80LCBnbV9hNF81LCBnbV9hNF82LA0KICBmbV9hNF8xLCBmbV9hNF8yLCBmbV9hNF8zLCBmbV9hNF80LCBmbV9hNF81LCBmbV9hNF82LA0KICBjZ19hNF8xLCBjZ19hNF8yLCBjZ19hNF8zLCBjZ19hNF80LCBjZ19hNF81LCBjZ19hNF82LA0KICBwc19hNF8xLCBwc19hNF8yLCBwc19hNF8zLCBwc19hNF80LCBwc19hNF81LCBwc19hNF82KQ0KDQojd3JpdGUudGFibGUoZHNfMjBfZnVsbCwgZmlsZT0iZHNfMjBfZnVsbC5kYXQiLCByb3cubmFtZXM9RkFMU0UsIGNvbC5uYW1lcz1GQUxTRSwgc2VwPSJcdCIsIHF1b3RlPUZBTFNFKSAgIA0KDQpgYGANCg0KDQpDRkEgbW9kZWwNCg0KYGBge3J9DQptb2RfY2ZhXzIwIDwtIGNmYShtb2RlbCA9IG1vZF9jZmEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWRzXzIwX2Z1bGwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0b3IgPSAnV0xTTScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkPW5hbWVzKGRzXzIwX2Z1bGwpKQ0KYGBgDQoNCkNGQSByZXN1bHRzDQoNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZF9jZmFfMjAsIHN0YW5kYXJkaXplZD1UUlVFLCBmaXQubWVhc3VyZXMgPSBUUlVFKSAgDQpgYGANCg0KQ29ycmVsYXRpb25zDQoNCg0KYGBge3J9DQpjb3YyY29yKGluc3BlY3QobW9kX2NmYV8yMCwgd2hhdCA9ICJlc3QiKSRwc2kpDQpgYGANCg0KDQojIyAyMi1tb250aHMNCg0KRGF0YXNldCANCg0KYGBge3J9DQpkc18yMl9mdWxsIDwtIGRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDIyKSAlPiUgDQogIHNlbGVjdCgNCiAgY29tX2E0XzEsIGNvbV9hNF8yLCBjb21fYTRfMywgY29tX2E0XzQsIGNvbV9hNF81LCBjb21fYTRfNiwNCiAgZ21fYTRfMSwgZ21fYTRfMiwgZ21fYTRfMywgZ21fYTRfNCwgZ21fYTRfNSwgZ21fYTRfNiwNCiAgZm1fYTRfMSwgZm1fYTRfMiwgZm1fYTRfMywgZm1fYTRfNCwgZm1fYTRfNSwgZm1fYTRfNiwNCiAgY2dfYTRfMSwgY2dfYTRfMiwgY2dfYTRfMywgY2dfYTRfNCwgY2dfYTRfNSwgY2dfYTRfNiwNCiAgcHNfYTRfMSwgcHNfYTRfMiwgcHNfYTRfMywgcHNfYTRfNCwgcHNfYTRfNSwgcHNfYTRfNikNCg0KI3dyaXRlLnRhYmxlKGRzXzIyX2Z1bGwsIGZpbGU9ImRzXzIyX2Z1bGwuZGF0Iiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UsIHNlcD0iXHQiLCBxdW90ZT1GQUxTRSkgICANCg0KYGBgDQoNCkNGQSBtb2RlbA0KDQpgYGB7cn0NCm1vZF9jZmFfMjIgPC0gY2ZhKG1vZGVsID0gbW9kX2NmYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZHNfMjJfZnVsbCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGVzdGltYXRvciA9ICdXTFNNJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQ9bmFtZXMoZHNfMjJfZnVsbCkpDQpgYGANCg0KQ0ZBIHJlc3VsdHMNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZF9jZmFfMjIsIHN0YW5kYXJkaXplZD1UUlVFLCBmaXQubWVhc3VyZXMgPSBUUlVFKSAgDQpgYGANCg0KQ29ycmVsYXRpb25zDQoNCg0KYGBge3J9DQpjb3YyY29yKGluc3BlY3QobW9kX2NmYV8yMiwgd2hhdCA9ICJlc3QiKSRwc2kpDQpgYGANCg0KDQoNCiMjIDI0LW1vbnRocw0KDQpEYXRhc2V0IA0KDQpgYGB7cn0NCmRzXzI0X2Z1bGwgPC0gZHMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gMjQpICU+JSANCiAgc2VsZWN0KA0KICBjb21fYTRfMSwgY29tX2E0XzIsIGNvbV9hNF8zLCBjb21fYTRfNCwgY29tX2E0XzUsIGNvbV9hNF82LA0KICBnbV9hNF8xLCBnbV9hNF8yLCBnbV9hNF8zLCBnbV9hNF80LCBnbV9hNF81LCBnbV9hNF82LA0KICBmbV9hNF8xLCBmbV9hNF8yLCBmbV9hNF8zLCBmbV9hNF80LCBmbV9hNF81LCBmbV9hNF82LA0KICBjZ19hNF8xLCBjZ19hNF8yLCBjZ19hNF8zLCBjZ19hNF80LCBjZ19hNF81LCBjZ19hNF82LA0KICBwc19hNF8xLCBwc19hNF8yLCBwc19hNF8zLCBwc19hNF80LCBwc19hNF81LCBwc19hNF82KQ0KDQojd3JpdGUudGFibGUoZHNfMjRfZnVsbCwgZmlsZT0iZHNfMjRfZnVsbC5kYXQiLCByb3cubmFtZXM9RkFMU0UsIGNvbC5uYW1lcz1GQUxTRSwgc2VwPSJcdCIsIHF1b3RlPUZBTFNFKSAgIA0KDQpgYGANCg0KDQpDRkEgbW9kZWwNCg0KYGBge3J9DQptb2RfY2ZhXzI0IDwtIGNmYShtb2RlbCA9IG1vZF9jZmEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWRzXzI0X2Z1bGwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0b3IgPSAnV0xTTScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkPW5hbWVzKGRzXzI0X2Z1bGwpKQ0KYGBgDQoNCkNGQSByZXN1bHRzDQoNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZF9jZmFfMjQsIHN0YW5kYXJkaXplZD1UUlVFLCBmaXQubWVhc3VyZXMgPSBUUlVFKSAgDQpgYGANCg0KQ29ycmVsYXRpb25zDQoNCg0KYGBge3J9DQpjb3YyY29yKGluc3BlY3QobW9kX2NmYV8yNCwgd2hhdCA9ICJlc3QiKSRwc2kpDQpgYGANCg0KDQojIyAyNy1tb250aHMNCg0KRGF0YXNldCANCg0KYGBge3J9DQpkc18yN19mdWxsIDwtIGRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDI3KSAlPiUgDQogIHNlbGVjdCgNCiAgY29tX2E0XzEsIGNvbV9hNF8yLCBjb21fYTRfMywgY29tX2E0XzQsIGNvbV9hNF81LCBjb21fYTRfNiwNCiAgZ21fYTRfMSwgZ21fYTRfMiwgZ21fYTRfMywgZ21fYTRfNCwgZ21fYTRfNSwgZ21fYTRfNiwNCiAgZm1fYTRfMSwgZm1fYTRfMiwgZm1fYTRfMywgZm1fYTRfNCwgZm1fYTRfNSwgZm1fYTRfNiwNCiAgY2dfYTRfMSwgY2dfYTRfMiwgY2dfYTRfMywgY2dfYTRfNCwgY2dfYTRfNSwgY2dfYTRfNiwNCiAgcHNfYTRfMSwgcHNfYTRfMiwgcHNfYTRfMywgcHNfYTRfNCwgcHNfYTRfNSwgcHNfYTRfNikNCg0KI3dyaXRlLnRhYmxlKGRzXzI3X2Z1bGwsIGZpbGU9ImRzXzI3X2Z1bGwuZGF0Iiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UsIHNlcD0iXHQiLCBxdW90ZT1GQUxTRSkgICANCmBgYA0KDQoNCkNGQSBtb2RlbA0KDQpgYGB7cn0NCm1vZF9jZmFfMjcgPC0gY2ZhKG1vZGVsID0gbW9kX2NmYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZHNfMjdfZnVsbCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGVzdGltYXRvciA9ICdXTFNNJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQ9bmFtZXMoZHNfMjdfZnVsbCkpDQpgYGANCg0KQ0ZBIHJlc3VsdHMNCg0KDQpgYGB7cn0NCnN1bW1hcnkobW9kX2NmYV8yNywgc3RhbmRhcmRpemVkPVRSVUUsIGZpdC5tZWFzdXJlcyA9IFRSVUUpICANCmBgYA0KDQpDb3JyZWxhdGlvbnMNCg0KDQpgYGB7cn0NCmNvdjJjb3IoaW5zcGVjdChtb2RfY2ZhXzI3LCB3aGF0ID0gImVzdCIpJHBzaSkNCmBgYA0KDQoNCiMjIDMwLW1vbnRocw0KDQpEYXRhc2V0IA0KDQpgYGB7cn0NCmRzXzMwX2Z1bGwgPC0gZHMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gMzApICU+JSANCiAgc2VsZWN0KA0KICBjb21fYTRfMSwgY29tX2E0XzIsIGNvbV9hNF8zLCBjb21fYTRfNCwgY29tX2E0XzUsIGNvbV9hNF82LA0KICBnbV9hNF8xLCBnbV9hNF8yLCBnbV9hNF8zLCBnbV9hNF80LCBnbV9hNF81LCBnbV9hNF82LA0KICBmbV9hNF8xLCBmbV9hNF8yLCBmbV9hNF8zLCBmbV9hNF80LCBmbV9hNF81LCBmbV9hNF82LA0KICBjZ19hNF8xLCBjZ19hNF8yLCBjZ19hNF8zLCBjZ19hNF80LCBjZ19hNF81LCBjZ19hNF82LA0KICBwc19hNF8xLCBwc19hNF8yLCBwc19hNF8zLCBwc19hNF80LCBwc19hNF81LCBwc19hNF82KQ0KDQojd3JpdGUudGFibGUoZHNfMzBfZnVsbCwgZmlsZT0iZHNfMzNfZnVsbC5kYXQiLCByb3cubmFtZXM9RkFMU0UsIGNvbC5uYW1lcz1GQUxTRSwgc2VwPSJcdCIsIHF1b3RlPUZBTFNFKSAgIA0KYGBgDQoNCg0KQ0ZBIG1vZGVsDQoNCmBgYHtyfQ0KbW9kX2NmYV8zMCA8LSBjZmEobW9kZWwgPSBtb2RfY2ZhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1kc18zMF9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc18zMF9mdWxsKSkNCmBgYA0KDQpDRkEgcmVzdWx0cw0KDQpgYGB7cn0NCnN1bW1hcnkobW9kX2NmYV8zMCwgc3RhbmRhcmRpemVkPVRSVUUsIGZpdC5tZWFzdXJlcyA9IFRSVUUpICANCmBgYA0KDQpDb3JyZWxhdGlvbnMNCg0KDQpgYGB7cn0NCmNvdjJjb3IoaW5zcGVjdChtb2RfY2ZhXzMwLCB3aGF0ID0gImVzdCIpJHBzaSkNCmBgYA0KDQoNCiMjIDMzLW1vbnRocw0KDQpEYXRhc2V0IA0KDQpgYGB7cn0NCmRzXzMzX2Z1bGwgPC0gZHMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gMzMpICU+JSANCiAgc2VsZWN0KA0KICBjb21fYTRfMSwgY29tX2E0XzIsIGNvbV9hNF8zLCBjb21fYTRfNCwgY29tX2E0XzUsIGNvbV9hNF82LA0KICBnbV9hNF8xLCBnbV9hNF8yLCBnbV9hNF8zLCBnbV9hNF80LCBnbV9hNF81LCBnbV9hNF82LA0KICBmbV9hNF8xLCBmbV9hNF8yLCBmbV9hNF8zLCBmbV9hNF80LCBmbV9hNF81LCBmbV9hNF82LA0KICBjZ19hNF8xLCBjZ19hNF8yLCBjZ19hNF8zLCBjZ19hNF80LCBjZ19hNF81LCBjZ19hNF82LA0KICBwc19hNF8xLCBwc19hNF8yLCBwc19hNF8zLCBwc19hNF80LCBwc19hNF81LCBwc19hNF82KQ0KDQojd3JpdGUudGFibGUoZHNfMzNfZnVsbCwgZmlsZT0iZHNfMzNfZnVsbC5kYXQiLCByb3cubmFtZXM9RkFMU0UsIGNvbC5uYW1lcz1GQUxTRSwgc2VwPSJcdCIsIHF1b3RlPUZBTFNFKSAgIA0KYGBgDQoNCg0KQ0ZBIG1vZGVsDQoNCmBgYHtyfQ0KbW9kX2NmYV8zMyA8LSBjZmEobW9kZWwgPSBtb2RfY2ZhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1kc18zM19mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc18zM19mdWxsKSkNCmBgYA0KDQpDRkEgcmVzdWx0cw0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RfY2ZhXzMzLCBzdGFuZGFyZGl6ZWQ9VFJVRSwgZml0Lm1lYXN1cmVzID0gVFJVRSkgIA0KYGBgDQoNCkNvcnJlbGF0aW9ucw0KDQoNCmBgYHtyfQ0KY292MmNvcihpbnNwZWN0KG1vZF9jZmFfMzMsIHdoYXQgPSAiZXN0IikkcHNpKQ0KYGBgDQoNCg0KDQoNCg0KIyMgMzYtbW9udGhzDQoNCkRhdGFzZXQgDQoNCmBgYHtyfQ0KZHNfMzZfZnVsbCA8LSBkcyAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSAzNikgJT4lIA0KICBzZWxlY3QoDQogIGNvbV9hNF8xLCBjb21fYTRfMiwgY29tX2E0XzMsIGNvbV9hNF80LCBjb21fYTRfNSwgY29tX2E0XzYsDQogIGdtX2E0XzEsIGdtX2E0XzIsIGdtX2E0XzMsIGdtX2E0XzQsIGdtX2E0XzUsIGdtX2E0XzYsDQogIGZtX2E0XzEsIGZtX2E0XzIsIGZtX2E0XzMsIGZtX2E0XzQsIGZtX2E0XzUsIGZtX2E0XzYsDQogIGNnX2E0XzEsIGNnX2E0XzIsIGNnX2E0XzMsIGNnX2E0XzQsIGNnX2E0XzUsIGNnX2E0XzYsDQogIHBzX2E0XzEsIHBzX2E0XzIsIHBzX2E0XzMsIHBzX2E0XzQsIHBzX2E0XzUsIHBzX2E0XzYpDQoNCiN3cml0ZS50YWJsZShkc18zNl9mdWxsLCBmaWxlPSJkc18zNl9mdWxsLmRhdCIsIHJvdy5uYW1lcz1GQUxTRSwgY29sLm5hbWVzPUZBTFNFLCBzZXA9Ilx0IiwgcXVvdGU9RkFMU0UpICAgDQpgYGANCg0KDQpDRkEgbW9kZWwNCg0KYGBge3J9DQptb2RfY2ZhXzM2IDwtIGNmYShtb2RlbCA9IG1vZF9jZmEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWRzXzM2X2Z1bGwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0b3IgPSAnV0xTTScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkPW5hbWVzKGRzXzM2X2Z1bGwpKQ0KYGBgDQoNCkNGQSByZXN1bHRzDQoNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZF9jZmFfMzYsIHN0YW5kYXJkaXplZD1UUlVFLCBmaXQubWVhc3VyZXMgPSBUUlVFKSAgDQpgYGANCg0KQ29ycmVsYXRpb25zDQoNCg0KYGBge3J9DQpjb3YyY29yKGluc3BlY3QobW9kX2NmYV8zNiwgd2hhdCA9ICJlc3QiKSRwc2kpDQpgYGANCg0KDQoNCg0KDQojIyA0Mi1tb250aHMNCg0KRGF0YXNldCANCg0KYGBge3J9DQpkc180Ml9mdWxsIDwtIGRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDQyKSAlPiUgDQogIHNlbGVjdCgNCiAgY29tX2E0XzEsIGNvbV9hNF8yLCBjb21fYTRfMywgY29tX2E0XzQsIGNvbV9hNF81LCBjb21fYTRfNiwNCiAgZ21fYTRfMSwgZ21fYTRfMiwgZ21fYTRfMywgZ21fYTRfNCwgZ21fYTRfNSwgZ21fYTRfNiwNCiAgZm1fYTRfMSwgZm1fYTRfMiwgZm1fYTRfMywgZm1fYTRfNCwgZm1fYTRfNSwgZm1fYTRfNiwNCiAgY2dfYTRfMSwgY2dfYTRfMiwgY2dfYTRfMywgY2dfYTRfNCwgY2dfYTRfNSwgY2dfYTRfNiwNCiAgcHNfYTRfMSwgcHNfYTRfMiwgcHNfYTRfMywgcHNfYTRfNCwgcHNfYTRfNSwgcHNfYTRfNikNCg0KI3dyaXRlLnRhYmxlKGRzXzQyX2Z1bGwsIGZpbGU9ImRzXzQyX2Z1bGwuZGF0Iiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UsIHNlcD0iXHQiLCBxdW90ZT1GQUxTRSkgICANCmBgYA0KDQoNCkNGQSBtb2RlbA0KDQpgYGB7cn0NCm1vZF9jZmFfNDIgPC0gY2ZhKG1vZGVsID0gbW9kX2NmYSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE9ZHNfNDJfZnVsbCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGVzdGltYXRvciA9ICdXTFNNJywgDQogICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQ9bmFtZXMoZHNfNDJfZnVsbCkpDQpgYGANCg0KQ0ZBIHJlc3VsdHMNCg0KDQpgYGB7cn0NCnN1bW1hcnkobW9kX2NmYV80Miwgc3RhbmRhcmRpemVkPVRSVUUsIGZpdC5tZWFzdXJlcyA9IFRSVUUpICANCmBgYA0KDQpDb3JyZWxhdGlvbnMNCg0KDQpgYGB7cn0NCmNvdjJjb3IoaW5zcGVjdChtb2RfY2ZhXzQyLCB3aGF0ID0gImVzdCIpJHBzaSkNCmBgYA0KDQoNCg0KDQoNCiMjIDQ4LW1vbnRocw0KDQpEYXRhc2V0IA0KDQpgYGB7cn0NCmRzXzQ4X2Z1bGwgPC0gZHMgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gNDgpICU+JSANCiAgc2VsZWN0KA0KICBjb21fYTRfMSwgY29tX2E0XzIsIGNvbV9hNF8zLCBjb21fYTRfNCwgY29tX2E0XzUsIGNvbV9hNF82LA0KICBnbV9hNF8xLCBnbV9hNF8yLCBnbV9hNF8zLCBnbV9hNF80LCBnbV9hNF81LCBnbV9hNF82LA0KICBmbV9hNF8xLCBmbV9hNF8yLCBmbV9hNF8zLCBmbV9hNF80LCBmbV9hNF81LCBmbV9hNF82LA0KICBjZ19hNF8xLCBjZ19hNF8yLCBjZ19hNF8zLCBjZ19hNF80LCBjZ19hNF81LCBjZ19hNF82LA0KICBwc19hNF8xLCBwc19hNF8yLCBwc19hNF8zLCBwc19hNF80LCBwc19hNF81LCBwc19hNF82KQ0KDQojd3JpdGUudGFibGUoZHNfNDhfZnVsbCwgZmlsZT0iZHNfNDhfZnVsbC5kYXQiLCByb3cubmFtZXM9RkFMU0UsIGNvbC5uYW1lcz1GQUxTRSwgc2VwPSJcdCIsIHF1b3RlPUZBTFNFKSAgIA0KYGBgDQoNCg0KQ0ZBIG1vZGVsDQoNCmBgYHtyfQ0KbW9kX2NmYV80OCA8LSBjZmEobW9kZWwgPSBtb2RfY2ZhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1kc180OF9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc180OF9mdWxsKSkNCmBgYA0KDQpDRkEgcmVzdWx0cw0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RfY2ZhXzQ4LCBzdGFuZGFyZGl6ZWQ9VFJVRSwgZml0Lm1lYXN1cmVzID0gVFJVRSkgIA0KYGBgDQoNCkNvcnJlbGF0aW9ucw0KDQoNCmBgYHtyfQ0KY292MmNvcihpbnNwZWN0KG1vZF9jZmFfNDgsIHdoYXQgPSAiZXN0IikkcHNpKQ0KYGBgDQoNCg0KDQojIyA1NC1tb250aHMNCg0KRGF0YXNldCANCg0KYGBge3J9DQpkc181NF9mdWxsIDwtIGRzICU+JSANCiAgZmlsdGVyKHF1ZXN0ID09IDU0KSAlPiUgDQogIHNlbGVjdCgNCiAgY29tX2E0XzEsIGNvbV9hNF8yLCBjb21fYTRfMywgY29tX2E0XzQsIGNvbV9hNF81LCBjb21fYTRfNiwNCiAgZ21fYTRfMSwgZ21fYTRfMiwgZ21fYTRfMywgZ21fYTRfNCwgZ21fYTRfNSwgZ21fYTRfNiwNCiAgZm1fYTRfMSwgZm1fYTRfMiwgZm1fYTRfMywgZm1fYTRfNCwgZm1fYTRfNSwgZm1fYTRfNiwNCiAgY2dfYTRfMSwgY2dfYTRfMiwgY2dfYTRfMywgY2dfYTRfNCwgY2dfYTRfNSwgY2dfYTRfNiwNCiAgcHNfYTRfMSwgcHNfYTRfMiwgcHNfYTRfMywgcHNfYTRfNCwgcHNfYTRfNSwgcHNfYTRfNikNCg0KI3dyaXRlLnRhYmxlKGRzXzU0X2Z1bGwsIGZpbGU9ImRzXzU0X2Z1bGwuZGF0Iiwgcm93Lm5hbWVzPUZBTFNFLCBjb2wubmFtZXM9RkFMU0UsIHNlcD0iXHQiLCBxdW90ZT1GQUxTRSkgICANCg0KYGBgDQoNCg0KQ0ZBIG1vZGVsDQoNCmBgYHtyfQ0KbW9kX2NmYV81NCA8LSBjZmEobW9kZWwgPSBtb2RfY2ZhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1kc181NF9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc181NF9mdWxsKSkNCmBgYA0KDQpDRkEgcmVzdWx0cw0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RfY2ZhXzU0LCBzdGFuZGFyZGl6ZWQ9VFJVRSwgZml0Lm1lYXN1cmVzID0gVFJVRSkgIA0KYGBgDQoNCkNvcnJlbGF0aW9ucw0KDQoNCmBgYHtyfQ0KY292MmNvcihpbnNwZWN0KG1vZF9jZmFfNTQsIHdoYXQgPSAiZXN0IikkcHNpKQ0KYGBgDQoNCg0KIyMgNjAtbW9udGhzDQoNCkRhdGFzZXQgDQoNCmBgYHtyfQ0KZHNfNjBfZnVsbCA8LSBkcyAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSA2MCkgJT4lIA0KICBzZWxlY3QoDQogIGNvbV9hNF8xLCBjb21fYTRfMiwgY29tX2E0XzMsIGNvbV9hNF80LCBjb21fYTRfNSwgY29tX2E0XzYsDQogIGdtX2E0XzEsIGdtX2E0XzIsIGdtX2E0XzMsIGdtX2E0XzQsIGdtX2E0XzUsIGdtX2E0XzYsDQogIGZtX2E0XzEsIGZtX2E0XzIsIGZtX2E0XzMsIGZtX2E0XzQsIGZtX2E0XzUsIGZtX2E0XzYsDQogIGNnX2E0XzEsIGNnX2E0XzIsIGNnX2E0XzMsIGNnX2E0XzQsIGNnX2E0XzUsIGNnX2E0XzYsDQogIHBzX2E0XzEsIHBzX2E0XzIsIHBzX2E0XzMsIHBzX2E0XzQsIHBzX2E0XzUsIHBzX2E0XzYpDQoNCiN3cml0ZS50YWJsZShkc182MF9mdWxsLCBmaWxlPSJkc182MF9mdWxsLmRhdCIsIHJvdy5uYW1lcz1GQUxTRSwgY29sLm5hbWVzPUZBTFNFLCBzZXA9Ilx0IiwgcXVvdGU9RkFMU0UpICAgDQoNCmBgYA0KDQpDRkEgbW9kZWwNCg0KYGBge3J9DQptb2RfY2ZhXzYwIDwtIGNmYShtb2RlbCA9IG1vZF9jZmEsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhPWRzXzYwX2Z1bGwsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RpbWF0b3IgPSAnV0xTTScsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkPW5hbWVzKGRzXzYwX2Z1bGwpKQ0KYGBgDQoNCkNGQSByZXN1bHRzDQoNCg0KYGBge3J9DQpzdW1tYXJ5KG1vZF9jZmFfNjAsIHN0YW5kYXJkaXplZD1UUlVFLCBmaXQubWVhc3VyZXMgPSBUUlVFKSAgDQpgYGANCg0KDQpDb3JyZWxhdGlvbiBzDQoNCg0KYGBge3J9DQpjb3YyY29yKGluc3BlY3QobW9kX2NmYV82MCwgd2hhdCA9ICJlc3QiKSRwc2kpDQpgYGANCg0KDQoNCg0KIyMgNzIgbW9udGhzDQoNCmBgYHtyfQ0KZHNfNzJfZnVsbCA8LSBkcyAlPiUgDQogIGZpbHRlcihxdWVzdCA9PSA3MikgJT4lIA0KICBzZWxlY3QoDQogIGNvbV9hNF8xLCBjb21fYTRfMiwgY29tX2E0XzMsIGNvbV9hNF80LCBjb21fYTRfNSwgY29tX2E0XzYsDQogIGdtX2E0XzEsIGdtX2E0XzIsIGdtX2E0XzMsIGdtX2E0XzQsIGdtX2E0XzUsIGdtX2E0XzYsDQogIGZtX2E0XzEsIGZtX2E0XzIsIGZtX2E0XzMsIGZtX2E0XzQsIGZtX2E0XzUsIGZtX2E0XzYsDQogIGNnX2E0XzEsIGNnX2E0XzIsIGNnX2E0XzMsIGNnX2E0XzQsIGNnX2E0XzUsIGNnX2E0XzYsDQogIHBzX2E0XzEsIHBzX2E0XzIsIHBzX2E0XzMsIHBzX2E0XzQsIHBzX2E0XzUsIHBzX2E0XzYpDQoNCiN3cml0ZS50YWJsZShkc183Ml9mdWxsLCBmaWxlPSJkc183Ml9mdWxsLmRhdCIsIHJvdy5uYW1lcz1GQUxTRSwgY29sLm5hbWVzPUZBTFNFLCBzZXA9Ilx0IiwgcXVvdGU9RkFMU0UpICAgDQpgYGANCg0KDQoNCmBgYHtyfQ0KbW9kX2NmYV83MiA8LSBjZmEobW9kZWwgPSBtb2RfY2ZhLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YT1kc183Ml9mdWxsLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0aW1hdG9yID0gJ1dMU00nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZD1uYW1lcyhkc183Ml9mdWxsKSkNCmBgYA0KDQoNCmBgYHtyfQ0Kc3VtbWFyeShtb2RfY2ZhXzcyLCBzdGFuZGFyZGl6ZWQ9VFJVRSwgZml0Lm1lYXN1cmVzID0gVFJVRSkgIA0KYGBgDQoNCg0KYGBge3J9DQpjb3YyY29yKGluc3BlY3QobW9kX2NmYV83Miwgd2hhdCA9ICJlc3QiKSRwc2kpDQpgYGANCg0KDQoNCg0KIyMgQ29tbXVuaWNhdGlvbg0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMykNCmRzXzEgJT4lDQogIHNlbGVjdChxdWVzdCxpZCxjb21fYTRfMTpjb21fYTRfNikgJT4lIA0KICBncm91cF9zcGxpdChxdWVzdCkgJT4lIA0KICBtYXAoLiAlPiUgICANCiAgc2FtcGxlX24oNTAwKSkgLT4geA0KYGBgDQoNCmBgYHtyfQ0KZm9yIChpIGluIDE6bGVuZ3RoKHgpKSB7DQogIGFzc2lnbihwYXN0ZTAoImRzX2NvbV8iLCB1bmlxdWUoeFtbaV1dWzFdKSksIGFzLmRhdGEuZnJhbWUoeFtbaV1dKSkNCn0NCmBgYA0KDQojIyMjIDIgbW9udGhzDQoNCmBgYHtyfQ0KYXBwbHlfaXJ0X2NmYShkc19jb21fMlssLWMoMToyKV0pDQpgYGANCg0KYGBge3J9DQpkc19maW5hbF9tZXJnZWQgJT4lIA0KICBmaWx0ZXIocXVlc3QgPT0gMikgJT4lIA0KICBzZWxlY3QoDQogIGNvbV9hM18xLCBjb21fYTNfMiwgY29tX2EzXzMsIGNvbV9hM180LCBjb21fYTNfNSwgY29tX2EzXzYsDQogIGdtX2EzXzEsIGdtX2EzXzIsIGdtX2EzXzMsIGdtX2EzXzQsIGdtX2EzXzUsIGdtX2EzXzYsDQogIGZtX2EzXzEsIGZtX2EzXzIsIGZtX2EzXzMsIGZtX2EzXzQsIGZtX2EzXzUsIGZtX2EzXzYsDQogIGNnX2EzXzEsIGNnX2EzXzIsIGNnX2EzXzMsIGNnX2EzXzQsIGNnX2EzXzUsIGNnX2EzXzYsDQogIHBzX2EzXzEsIHBzX2EzXzIsIHBzX2EzXzMsIHBzX2EzXzQsIHBzX2EzXzUsIHBzX2EzXzYpICU+JSANCiAgYXBwbHlfaXJ0X2NmYSguKQ0KYGBgDQoNCg0KIyMjIyA0IG1vbnRocw0KDQpgYGB7cn0NCmFwcGx5X2lydF9jZmEoZHNfY29tXzRbLC1jKDE6MildKQ0KYGBgDQoNCiMjIyMgNiBtb250aHMNCg0KYGBge3J9DQphcHBseV9pcnRfY2ZhKGRzX2NvbV82WywtYygxOjIpXSkNCmBgYA0KDQojIyMjIDggbW9udGhzDQoNCmBgYHtyfQ0KYXBwbHlfaXJ0X2NmYShkc19jb21fOFssLWMoMToyKV0pDQpgYGANCg0KIyMjIyAxMCBtb250aHMNCg0KYGBge3J9DQphcHBseV9pcnRfY2ZhKGRzX2NvbV8xMFssLWMoMToyKV0pDQpgYGANCg0KDQojIyMjIDEyIG1vbnRocw0KDQpgYGB7cn0NCmFwcGx5X2lydF9jZmEoZHNfY29tXzEyWywtYygxOjIpXSkNCmBgYA0KDQojIyMjIDE0IG1vbnRocw0KDQpgYGB7cn0NCmFwcGx5X2lydF9jZmEoZHNfY29tXzE0WywtYygxOjIpXSkNCmBgYA0KDQoNCg0KIyMjIyAxNiBtb250aHMNCg0KYGBge3J9DQphcHBseV9pcnRfY2ZhKGRzX2NvbV8xNlssLWMoMToyKV0pDQpgYGANCg0KDQojIyMjIDE4IG1vbnRocw0KDQpgYGB7cn0NCmFwcGx5X2lydF9jZmEoZHNfY29tXzE4WywtYygxOjIpXSkNCmBgYA0KDQoNCiMjIyMgMjAgbW9udGhzDQoNCmBgYHtyfQ0KYXBwbHlfaXJ0X2NmYShkc19jb21fMjBbLC1jKDE6MildKQ0KYGBgDQoNCg0KIyMjIyAyMiBtb250aHMNCg0KYGBge3J9DQphcHBseV9pcnRfY2ZhKGRzX2NvbV8yMlssLWMoMToyKV0pDQpgYGANCg0KDQojIyMjIDI0IG1vbnRocw0KDQpgYGB7cn0NCmFwcGx5X2lydF9jZmEoZHNfY29tXzI0WywtYygxOjIpXSkNCmBgYA0KDQoNCiMjIyMgMjcgbW9udGhzDQoNCmBgYHtyfQ0KYXBwbHlfaXJ0X2NmYShkc19jb21fMjdbLC1jKDE6MildKQ0KYGBgDQoNCiMjIyMgMzAgbW9udGhzDQoNCmBgYHtyfQ0KYXBwbHlfaXJ0X2NmYShkc19jb21fMzBbLC1jKDE6MildKQ0KYGBgDQoNCg0KIyMjIyAzMyBtb250aHMNCg0KYGBge3J9DQphcHBseV9pcnRfY2ZhKGRzX2NvbV8zM1ssLWMoMToyKV0pDQpgYGANCg0KDQojIyMjIDM2IG1vbnRocw0KDQpgYGB7cn0NCmFwcGx5X2lydF9jZmEoZHNfY29tXzM2WywtYygxOjIpXSkNCmBgYA0KDQojIyMjIDQyIG1vbnRocw0KDQpgYGB7cn0NCmFwcGx5X2lydF9jZmEoZHNfY29tXzQyWywtYygxOjIpXSkNCmBgYA0KDQojIyMjIDQ4IG1vbnRocw0KDQpgYGB7cn0NCmFwcGx5X2lydF9jZmEoZHNfY29tXzQ4WywtYygxOjIpXSkNCmBgYA0KDQojIyMjIDU0IG1vbnRocw0KDQpgYGB7cn0NCmFwcGx5X2lydF9jZmEoZHNfY29tXzU0WywtYygxOjIpXSkNCmBgYA0KDQoNCiMjIyMgNjAgbW9udGhzDQoNCmBgYHtyfQ0KYXBwbHlfaXJ0X2NmYShkc19jb21fNjBbLC1jKDE6MildKQ0KYGBgDQoNCg0KIyMjIyA3MiBtb250aHMNCg0KYGBge3J9DQphcHBseV9pcnRfY2ZhKGRzX2NvbV83MlssLWMoMToyKV0pDQpgYGANCg0KDQoNCg0KDQoNCiMgQVNRMy1BU1E0IGNvbXBhcmlzb24NCg0KDQpgYGB7cn0NCmRzXzEgJT4lIG5hbWVzDQpgYGANCg0KDQo=