1. Load necessary materials 📚

1.1. Load necessary libraries

library(metR)        # Tools for meteorological data processing
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
There were 50 or more warnings (use warnings() to see the first 50)
library(readr)       # For reading CSV files efficiently
library(dplyr)       # For data manipulation and transformation

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(tidyr)       # For tidying data (reshaping)
library(ggplot2)     # For creating complex data visualizations
library(lme4)        # For fitting linear mixed-effects models
Loading required package: Matrix

Attaching package: ‘Matrix’

The following objects are masked from ‘package:tidyr’:

    expand, pack, unpack
library(emmeans)     # For computing estimated marginal means (post hoc analysis)
Warning: package ‘emmeans’ was built under R version 4.3.3Welcome to emmeans.
Caution: You lose important information if you filter this package's results.
See '? untidy'
library(lmerTest)    # For hypothesis testing in linear mixed-effects models

Attaching package: ‘lmerTest’

The following object is masked from ‘package:lme4’:

    lmer

The following object is masked from ‘package:stats’:

    step
library(gridExtra)   # For arranging multiple grid graphics

Attaching package: ‘gridExtra’

The following object is masked from ‘package:dplyr’:

    combine
library(cowplot)     # For creating complex ggplot2 layouts
library(DescTools)   # For descriptive statistics and data exploration
library(sjmisc)      # For data preparation and variable recoding
Learn more about sjmisc with 'browseVignettes("sjmisc")'.

Attaching package: ‘sjmisc’

The following object is masked from ‘package:DescTools’:

    %nin%

The following object is masked from ‘package:tidyr’:

    replace_na
library(readxl)      # For reading Excel files
library(sjPlot)      # For generating plots and summary tables

Attaching package: ‘sjPlot’

The following objects are masked from ‘package:cowplot’:

    plot_grid, save_plot
library(broom.mixed) # For tidying up model outputs from mixed models
library(scales)      # For scaling and formatting of axes (e.g., percent_format)

Attaching package: ‘scales’

The following object is masked from ‘package:readr’:

    col_factor
library(ggeffects)   # For visualizing effects from regression models

Attaching package: ‘ggeffects’

The following object is masked from ‘package:cowplot’:

    get_title
library(ggridges)    # For creating ridge plots
library(patchwork)   # For combining ggplot2 plots

Attaching package: ‘patchwork’

The following object is masked from ‘package:cowplot’:

    align_plots
library(smplot2)     # For creating summary plots
Warning: package ‘smplot2’ was built under R version 4.3.3Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
Updated tutorial for smplot2: smin95.github.io/dataviz/
library(ggpubr)      # For ggplot2-based publication-ready plots

Attaching package: ‘ggpubr’

The following object is masked from ‘package:cowplot’:

    get_legend
library(purrr)       # For functional programming and data manipulation

Attaching package: ‘purrr’

The following object is masked from ‘package:scales’:

    discard

The following object is masked from ‘package:sjmisc’:

    is_empty

The following object is masked from ‘package:metR’:

    cross

1.2. Data Loading

# Read the main data file
df <- read_csv("~/Documents/Research/Code/F1_F0_cue_weighting/Data/data_annotated_v_optim_param_zsco_wth_outliers.csv",show_col_types = FALSE)

# Convert AGE column to factor and specify custom levels
df$AGE <- factor(df$AGE, levels = c("00;06", "00;07", "00;08", "00;09", "00;10", "00;11", "01;00", "01;01", "01;02", "01;03", "01;04", "01;05", "01;06", "01;07", "01;08", "01;09", "01;10", "01;11", "02;00"))


# Read the supplementary data file
cumvoc.y_ALLE_NH <- read_excel("/Users/jeremygenette_studio/Documents/Research/Code/F1_F0_cue_weighting/Data/cumvoc_ALLE_NH_vf.xlsx")

# Process supplementary data
cumvoc.y_ALLE_NH <- cumvoc.y_ALLE_NH %>% 
  filter(!is.na(`Cum voc`)) %>% 
  select(-`Chronage/HearAge`) %>% 
  mutate(item = sub("_.*", "",`OPMERKING: cum op woordvormen, niet op lemma`))

# Merge supplementary data with main data
df <- left_join(df, cumvoc.y_ALLE_NH, by = "item")

# Filter data based on utt_type
df <- df %>%
  filter(utt_type == "LEX") 
# Print the first few rows of the merged and filtered data frame

# Convert pho_vwl_nucl column to factor
df$pho_vwl_nucl <- as.factor(df$pho_vwl_nucl)

# Recode the levels for annotation consistency
df$pho_vwl_nucl <- recode_factor(df$pho_vwl_nucl,
                                  "M" = NA_character_, # diphtong
                                  "L" = NA_character_, # diphtong
                                  "K" = NA_character_, # diphtong
                                  "H" = NA_character_, # glottal stop
                                  "2" = "@", # annotation consistency
                                  "<" = "u", # annotation consistency
                                  ")" = "}") # annotation consistency

# Remove NA levels
df$pho_vwl_nucl <- droplevels(df$pho_vwl_nucl)

# Print the first few rows of the merged and filtered data frame
print(head(df))

2. Data preprocessing ⚙️

2.1. Normalization of F0 based on regression approach from Barreda and Nearey (2018) applied to Lobanov’s (1971) Normalization technique

2.1.1. Data preprocessing

“To implement this analysis in R, it is first assumed that the data are available in a data frame object in a “long” format with only one log-formant measurement per row. Further, it is assumed that each row of the data frame has (at least) four columns, labeled: G for the single formant measurement, V indicating vowel, K indicating formant number, and S indicating the speaker […]an additional variable (N) may be created to represent the Nvk terms, using the R command: N ¼ factor[interaction (V,K)].” (p.507)

# Convert from wide to long_F0 format
df_long_F0 <- df %>%  # Create a new data frame by transforming the existing one
  select(item, CHILD, AGE, ID_vwl, pho_vwl_nucl, F0) %>%  # Select specific columns from the original data frame
  gather(key = "Frequency", value = "Value", F0)  # Reshape the data from wide to long_F0 format, combining F0 and F1 columns into key-value pairs 

df_long_F0$G <- df_long_F0$Value  # assign Value to 'G'
df_long_F0$S <- as.factor(df_long_F0$item)  # Convert the 'item' (=recording session) column to a factor and assign it to 'S'
df_long_F0$V <- as.factor(df_long_F0$pho_vwl_nucl)  # Convert the 'pho_vwl_nucl' column to a factor and assign it to 'V'

2.1.2. Regression

Considering the anticipated variability in how different vowel types affect F0 and F1 frequencies across speakers, which was not addressed in Barreda’s study, we find it imperative to incorporate interactions.

M_F0 = lm(data = df_long_F0,
       formula = G ~ 0 + S * V, contrasts = list(V=contr.sum))

saveRDS(M_F0, "~/Documents/Research/Code/F1_F0_cue_weighting/VF/MF0.rds")

2.1.3. Coefficients extraction

# Extract coefficients for F0 for each speaker
Coefficients_F0 <- summary(M_F0)$coefficients %>%
  as.data.frame() %>%                                          # Convert coefficients to data frame
  filter(grepl("^S", rownames(.))) %>%                         # Filter rows with speaker IDs
  rename(Speaker_Estimate_F0 = Estimate, Speaker_Std_Error_F0 = `Std. Error`) %>%  # Rename columns
  mutate(item = sub("^S", "", rownames(.))) %>%                # Extract speaker IDs
  filter(!grepl(":", item))                                    # Exclude rows with ":" in speaker IDs

# Left join Coefficients_F0 with df_long_F0 by the 'item' column
df_long_with_coef_F0 <- left_join(df_long_F0, Coefficients_F0, by = "item")

# Calculate F0 regression Normalized values
df_long_with_coef_F0 <- df_long_with_coef_F0 %>%
  group_by(item) %>%                                           # Group by speaker IDs
  mutate(F0_Regression_Normalized = (Value - Speaker_Estimate_F0) / (Speaker_Std_Error_F0 * sqrt(n())))  # Calculate Normalized values

# Print head of df_long_with_coef_F0
head(df_long_with_coef_F0)

2.2. Normalization of F1 based on regression approach from Barreda and Nearey (2018) applied to Lobanov’s (1971) Normalization technique

2.2.1. Data preprocessing

“To implement this analysis in R, it is first assumed that the data are available in a data frame object in a “long” format with only one log-formant measurement per row. Further, it is assumed that each row of the data frame has (at least) four columns, labeled: G for the single formant measurement, V indicating vowel, K indicating formant number, and S indicating the speaker […]an additional variable (N) may be created to represent the Nvk terms, using the R command: N ¼ factor[interaction (V,K)].” (p.507)

# Convert from wide to long_F1 format
df_long_F1 <- df %>%  # Create a new data frame by transforming the existing one
  select(item, CHILD, AGE, ID_vwl, pho_vwl_nucl, F1) %>%  # Select specific columns from the original data frame
  gather(key = "Frequency", value = "Value", F1)  # Reshape the data from wide to long_F1 format, combining F1 and F1 columns into key-value pairs 

df_long_F1$G <- df_long_F1$Value  # assign Value to 'G'
df_long_F1$S <- as.factor(df_long_F1$item)  # Convert the 'item' (=recording session) column to a factor and assign it to 'S'
df_long_F1$V <- as.factor(df_long_F1$pho_vwl_nucl)  # Convert the 'pho_vwl_nucl' column to a factor and assign it to 'V'

2.2.2. Regression

Considering the anticipated variability in how different vowel types affect F0 and F1 frequencies across speakers, which was not addressed in Barreda’s study, we find it imperative to incorporate interactions.

M_F1 = lm(data = df_long_F1,
       formula = G ~ 0 + S * V, contrasts = list(V=contr.sum))

saveRDS(M_F1, "~/Documents/Research/Code/F1_F0_cue_weighting/VF/MF1.rds")

2.2.3. Coefficients extraction

# Extract coefficients for F1 for each speaker
Coefficients_F1 <- summary(M_F1)$coefficients %>%
  as.data.frame() %>%                                          # Convert coefficients to data frame
  filter(grepl("^S", rownames(.))) %>%                         # Filter rows with speaker IDs
  rename(Speaker_Estimate_F1 = Estimate, Speaker_Std_Error_F1 = `Std. Error`) %>%  # Rename columns
  mutate(item = sub("^S", "", rownames(.))) %>%                # Extract speaker IDs
  filter(!grepl(":", item))                                    # Exclude rows with ":" in speaker IDs

# Left join Coefficients_F1 with df_long_F1 by the 'item' column
df_long_with_coef_F1 <- left_join(df_long_F1, Coefficients_F1, by = "item")

# Calculate F1 regression Normalized values
df_long_with_coef_F1 <- df_long_with_coef_F1 %>%
  group_by(item) %>%                                           # Group by speaker IDs
  mutate(F1_Regression_Normalized = (Value - Speaker_Estimate_F1) / (Speaker_Std_Error_F1 * sqrt(n())))  # Calculate Normalized values

# Print head of df_long_with_coef_F1
head(df_long_with_coef_F1)

2.3 Gather Normalization of F0 and F1

# Left join df_long_with_coef_F0 with df_long_with_coef_F1 by the 'ID_vwl' column
df_with_coef_F0_F1_lex <- left_join(df_long_with_coef_F0, df_long_with_coef_F1, by = "ID_vwl") %>% 
  rename(item = item.x)  # Rename the 'item' column

# Define the indices of the columns to keep
cols_to_keep <- c(1, 2, 3, 4, 5, 15, 29, 7, 21)

# Extract the desired columns from the dataframe
df_with_coef_F0_F1_lex <- df_with_coef_F0_F1_lex[, cols_to_keep]

# Remove the suffix ".x" from the column names when needed
colnames(df_with_coef_F0_F1_lex) <- gsub("\\.x$", "", colnames(df_with_coef_F0_F1_lex))

df_with_coef_F0_F1_lex$F0 <- df_with_coef_F0_F1_lex$Value
df_with_coef_F0_F1_lex$F1 <- df_with_coef_F0_F1_lex$Value.y

df_with_coef_F0_F1_lex <- df_with_coef_F0_F1_lex %>% 
  select(-c(Value, Value.y))

head(df_with_coef_F0_F1_lex)

2.4. Selection of relevant items

df_combined<- df_with_coef_F0_F1_lex %>% 
  mutate(hgt = case_when(
    pho_vwl_nucl %in% c('A', 'a') ~ 'low',
    pho_vwl_nucl %in% c('u', '<', 'i') ~ 'high',
    TRUE ~ NA_character_  # Handle other cases if needed
  ))  %>% 
  filter(is.na(hgt)==F) %>% 
  select(ID_vwl, F0_Regression_Normalized, F1_Regression_Normalized, pho_vwl_nucl, hgt, CHILD, item, F0, F1)

2.5. Preparation df for analysis

# Converting 'hgt' to a factor
df_combined$hgt <- as.factor(df_combined$hgt)

# Categorizing 'frt' based on 'pho_vwl_nucl'
df_combined$frt[df_combined$pho_vwl_nucl %in% c("A", "u", "<")] <- "bck"
Warning: Unknown or uninitialised column: `frt`.
df_combined$frt[df_combined$pho_vwl_nucl %in% c("i", "a")] <- "frt"

# Merging supplementary data with main data and filtering based on a condition
df_combined <- left_join(df_combined, cumvoc.y_ALLE_NH, by = "item") 
df_combined <- df_combined %>% 
  filter(`Cum voc` > 0)

# Calculating the logarithm of 'cumvoc.y'
df_combined$log_cum <- log(df_combined$`Cum voc`)

# Final dataframe for analysis
df <- df_combined %>% 
  mutate(hgt = as.factor(hgt),
         CHILD = as.factor(CHILD),
         item = as.factor(item),
         frt = as.factor(frt))

 
# Apply deviation (sum) contrasts to 'hgt' and 'frt'
# This codes each level relative to the overall mean of the dependent variable
df$hgt <- factor(df$hgt, levels = c("low", "high"))  # Ensure 'hgt' is a factor with specified levels
contrasts(df$hgt) <- contr.sum(levels(df$hgt))  # Apply contr.sum to 'hgt'
contrasts(df$frt) <- contr.sum(levels(df$frt))  # Apply contr.sum to 'frt'

3. Data analysis 🧮

3.1. Descriptive Statistics

# Calculate mean and standard deviation of F1 for each pho_vwl_nucl category (Normalized)
df_descr <- df %>% 
  group_by(hgt) %>%   # Group by pho_vwl_nucl category
  mutate(F1_F0_Hz = F1-F0,
         F1_F0_Normalized = F1_Regression_Normalized-F0_Regression_Normalized) %>% 
  summarise(
    m_F1_Hz = round(mean(F1), 2),             # Mean F1 (Hz)
    sd_F1_Hz = round(sd(F1), 2),               # Standard deviation of F1 (Hz)
    m_F0_Hz = round(mean(F0), 2),                # Mean F0 (Hz)
    sd_F0_Hz = round(sd(F0), 2),                 # Standard deviation of F0 (Hz)
    m_F1_F0_Hz = round(mean(F1_F0_Hz), 2),          # Mean F1-F0 difference (Hz)
    sd_F1_F0_Hz = round(sd(F1_F0_Hz), 2),           # Standard deviation of F1-F0 difference (Hz)
    m_F1_Normalized = round(mean(F1_Regression_Normalized), 2),     # Mean F1 (Normalized)
    sd_F1_Normalized = round(sd(F1_Regression_Normalized), 2),       # Standard deviation of F1 (Normalized)
    m_F0_Normalized = round(mean(F0_Regression_Normalized), 2),       # Mean F0 (Normalized)
    sd_F0_Normalized = round(sd(F0_Regression_Normalized), 2),       # Standard deviation of F0 (Normalized)
    m_F1_F0_Normalized = round(mean(F1_F0_Normalized), 2),           # Mean F1-F0 difference (Normalized)
    sd_F1_F0_Normalized = round(sd(F1_F0_Normalized), 2)) %>%       # Standard deviation of F1-F0 difference (Normalized)
  filter(!is.na(hgt))   # Remove rows where hgt is NA

print(df_descr)

df_descr_phon <- df %>% 
  group_by( CHILD, pho_vwl_nucl) %>% 
  summarise(counts = n())
`summarise()` has grouped output by 'CHILD'. You can override using the `.groups` argument.
print(df_descr_phon)

df_descr_phon_avg <- df %>% 
  group_by( CHILD, pho_vwl_nucl) %>% 
  summarise(counts = n()) %>% 
  group_by(pho_vwl_nucl) %>%
  summarise(m_counts=mean(counts),
           sd=sd(counts))
`summarise()` has grouped output by 'CHILD'. You can override using the `.groups` argument.
print(df_descr_phon_avg)
NA

3.1.2. Graphs experimental data

# vowel distribution per child plot
df_descr_phon$pho_vwl_nucl <- factor(
  df_descr_phon$pho_vwl_nucl,
  levels = c("i", "u", "a", "A")
)

df_descr_phon <- df_descr_phon %>%
  ungroup() %>%   
  mutate(
    CHILD_anon = factor(
      CHILD,
      labels = paste0("ID",  seq_along(levels(CHILD)))
    )
  )

child_key <- df_descr_phon %>%
  ungroup() %>%
  distinct(CHILD) %>%
  arrange(CHILD) %>%   # optional: alphabetic order
  mutate(
    CHILD_anon = paste0("ID",  seq_along(levels(CHILD)))
  )

count <- ggplot(df_descr_phon,
       aes(x = CHILD_anon, y = counts,
           fill = pho_vwl_nucl, colour = pho_vwl_nucl)) +
  geom_col(alpha = 0.85) +
  labs(
    x = "Child",
    y = "Count",
    fill = "Vowel"
  ) +
  scale_fill_manual(
    values = c(
  "i" = "#1F77B4",  # blue
  "u" = "#17BECF",  # cyan
  "a" = "#FF7F0E",  # orange
  "A" = "#E41A1C"   # red
    ),
    labels = c(
      "i" = "[i]",
      "u" = "[u]",
      "a" = "[a]",
      "A" = "[ɑ]"
    )
  ) +
  scale_colour_manual(
    values = c(
  "i" = "#1F77B4",  # blue
  "u" = "#17BECF",  # cyan
  "a" = "#FF7F0E",  # orange
  "A" = "#E41A1C"   # red
    ),
    guide = "none"   
  ) +
  theme_minimal() +
  theme(
    plot.title = element_blank(),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank(),
    panel.grid.major.y = element_line(color = "grey85"),
axis.text.x = element_text(angle = 45, hjust = 1),
    legend.title = element_text(size = 14),
    legend.text  = element_text(size = 16)
  )

count 
ggsave(filename = "~/Desktop/image_eps.eps", plot = count,
       width = 15, height = 6, dpi = 1000)

# F1 density plot
p1 <- ggplot(data = df) +
  geom_density(aes(x = F1_Regression_Normalized, fill = hgt), alpha = 0.5) +
  scale_fill_manual(values = c("low" = "#9F3400", "high" = "#FFBE9F"), name = "Height") +
  labs(x = "F1 Normalized", y = "Density") +
  scale_x_continuous(limits = c(-1.2, 1.2)) +
  theme_minimal() +
  theme(
    legend.position = "bottom",
    panel.grid.major.y = element_blank(),
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank()  ,  legend.text = element_text(size = 14)      # Increase legend title size (optional)
  )
  

# F0 density plot
p2 <- ggplot(data = df) +
  geom_density(aes(x = F0_Regression_Normalized, fill = hgt), alpha = 0.5) +
  scale_fill_manual(values = c("low" = "#570987", "high" = "#D397F8"), name = "Height") +
  labs(x = "F0 Normalized", y = "Density") +
  scale_x_continuous(limits = c(-1.2, 1.2)) +
  theme_minimal() +
  theme(
    legend.position = "bottom",  # Position the legend on the right side,
    panel.grid.major.y = element_blank(),
   
    panel.grid.minor.y = element_blank(),
    panel.grid.minor.x = element_blank(),  legend.text = element_text(size = 14)  
  )

# Combine with shared legend
combined_plots <- (p1 + p2) +
 plot_layout(guides = "collect") &
  theme(legend.position = "bottom")

combined_plots

ggsave(filename = "~/Desktop/image_eps.eps", plot = combined_plots,
       width = 10, height = 6, dpi = 1000)

df$pho_vwl_nucl <- factor(
  df$pho_vwl_nucl,
  levels = c("i", "u", "a", "A")
)

f0_raw <- ggplot(df, aes(x = log_cum, y = F0_Regression_Normalized, group = pho_vwl_nucl)) +
  
  # Ribbon layer (legend shows only fill)
  geom_smooth(
    aes(fill = pho_vwl_nucl),
    method = "loess",
    linewidth = 1.2,
    color = NA,            # no line in this layer
    show.legend = TRUE
  ) +
  
  # Line layer (no legend)
  geom_smooth(
    aes(color = pho_vwl_nucl),
    method = "loess",
    linewidth = 1.2,
    fill = NA,             # don't fill this layer
    show.legend = FALSE
  ) +
  
  # Fill scale controls the legend
  scale_fill_manual(
    name = "Vowel",        # <- legend title
    values = c(
  "i" = "#1F77B4",  # blue
  "u" = "#17BECF",  # cyan
  "a" = "#FF7F0E",  # orange
  "A" = "#E41A1C"   # red
    ),
    labels = c(
      "i" = "[i]",
      "u" = "[u]",
      "a" = "[a]",
      "A" = "[ɑ]"
    )
  ) +
  
  scale_color_manual(
    values = c(
  "i" = "#1F77B4",  # blue
  "u" = "#17BECF",  # cyan
  "a" = "#FF7F0E",  # orange
  "A" = "#E41A1C"   # red
    ),
    guide = "none"           # hide the color legend
  ) +
  
  # Axis labels
  labs(
    x = "log(cumulative vocabulary)",
    y = "Normalized F0"
  ) +
  
  ylim(-1, 1) +
  theme_cowplot() +
  theme(
    legend.position = "right",
    legend.text = element_text(size = 14),
    legend.title = element_text(size = 16),  # bigger legend title
    panel.grid.major.y = element_blank(),
    panel.grid.minor = element_blank()
  )

f0_raw
ggsave(filename = "~/Desktop/f0_raw_eps.eps", plot = f0_raw,
       width = 6, height = 6, dpi = 1000)

df$pho_vwl_nucl <- factor(
  df$pho_vwl_nucl,
  levels = c("i", "u", "a", "A")
)

f1_raw <- ggplot(df, aes(x = log_cum, y = F1_Regression_Normalized, group = pho_vwl_nucl)) +
  
  # Ribbon layer (legend shows only fill)
  geom_smooth(
    aes(fill = pho_vwl_nucl),
    method = "loess",
    linewidth = 1.2,
    color = NA,            # no line in this layer
    show.legend = TRUE
  ) +
  
  # Line layer (no legend)
  geom_smooth(
    aes(color = pho_vwl_nucl),
    method = "loess",
    linewidth = 1.2,
    fill = NA,             # don't fill this layer
    show.legend = FALSE
  ) +
  
  # Fill scale controls the legend
  scale_fill_manual(
    name = "Vowel",        # <- legend title
    values = c(
  "i" = "#1F77B4",  # blue
  "u" = "#17BECF",  # cyan
  "a" = "#FF7F0E",  # orange
  "A" = "#E41A1C"   # red
    ),
    labels = c(
      "i" = "[i]",
      "u" = "[u]",
      "a" = "[a]",
      "A" = "[ɑ]"
    )
  ) +
  
  scale_color_manual(
    values = c(
  "i" = "#1F77B4",  # blue
  "u" = "#17BECF",  # cyan
  "a" = "#FF7F0E",  # orange
  "A" = "#E41A1C"   # red
    ),
    guide = "none"           # hide the color legend
  ) +
  
  # Axis labels
  labs(
    x = "log(cumulative vocabulary)",
    y = "Normalized F1"
  ) +
  
  ylim(-1, 1) +
  theme_cowplot() +
  theme(
    legend.position = "right",
    legend.text = element_text(size = 14),
    legend.title = element_text(size = 16),  # bigger legend title
    panel.grid.major.y = element_blank(),
    panel.grid.minor = element_blank()
  )

f1_raw

ggsave(filename = "~/Desktop/f1_raw.eps", plot = f1_raw,
       width = 6, height = 6, dpi = 1000)

3.2. MLM Modelling

3.2.1. Model 1: Base model

m1 <- glmer(data= df, 
            formula = hgt ~ 1+ 
              (1|CHILD),  family= "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m1, file = "m1.rds")

3.2.2. Model 2: Fixed effect of cumulative vocabulary

m2 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              (1|CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m2, file = "m2.rds")

as.data.frame(anova(m1,m2))

➡️ Better datafit with m2

3.2.3. Model 3: Random effect of cumulative vocabulary

m3 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              (1 + log_cum | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m3, file = "m3.rds")

as.data.frame(anova(m2,m3))

➡️ Better datafit with m3

3.2.4. Model 4: Fixed effect of F1

m4 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              (1 + log_cum | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m4, file = "m4.rds")

as.data.frame(anova(m3,m4))

➡️ Better datafit with m4

3.2.5. Model 5: Random slope effect of F1

m5 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              (1 + log_cum + F1_Regression_Normalized | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m5, file = "m5.rds")

as.data.frame(anova(m4,m5))

➡️ Better datafit with m5

3.2.6. Model 6: Fixed effect of F0

m6 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              (1 + log_cum + F1_Regression_Normalized | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m6, file = "m6.rds")

as.data.frame(anova(m5,m6))

➡️ Better datafit with m6

3.2.7. Model 7: Random slope effect of F0

m7 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m7, file = "m7.rds")

as.data.frame(anova(m6,m7))

➡️ Better datafit with m7

3.2.8. Model 8: Fixed effect of place of articulation

m8 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m8, file = "m8.rds")

as.data.frame(anova(m7,m8))

➡️ Better datafit with m8

3.2.9. Model 9: Random slope effect of place of articulation

m9 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized + frt | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m9, file = "m9.rds")

as.data.frame(anova(m8,m9))

➡️ Better datafit with m9

3.2.10. Model 10: Fixed quadratic effect of cumulative vocabulary interaction

m10 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              I(log_cum^2)+ 
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized + frt | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m10, file = "m10.rds")

as.data.frame(anova(m9,m10))

❌ No better datafit with m10

3.2.11. Model 11: Fixed effect of F0-F1 interaction

m11 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              F1_Regression_Normalized : F0_Regression_Normalized+
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized + frt | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m11, file = "m11.rds")


as.data.frame(anova(m9,m11))

➡️ Better datafit with m11

3.2.12. Model 12: Fixed effect of place of articulation-F1 interaction

m12 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              F1_Regression_Normalized : F0_Regression_Normalized+
              F1_Regression_Normalized : frt +
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized + frt | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m12, file = "m12.rds")

as.data.frame(anova(m11,m12))

➡️ Better datafit with m12

3.2.13. Model 13: Fixed effect of cumulative vocabulary-F1 interaction

m13 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              F1_Regression_Normalized : F0_Regression_Normalized+
              F1_Regression_Normalized : frt +
              F1_Regression_Normalized : log_cum +
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized + frt | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m13, file = "m13.rds")

as.data.frame(anova(m12,m13))

➡️ Better with m13

3.2.14. Model 14: Fixed effect of F0-place of articulation interaction

m14 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              F1_Regression_Normalized : F0_Regression_Normalized+
              F1_Regression_Normalized : frt +
              F1_Regression_Normalized : log_cum +
              F0_Regression_Normalized : frt +
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized + frt | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m14, file = "m14.rds")

as.data.frame(anova(m13,m14))

➡️ Better datafit with m14

3.2.15. Model 15: Fixed effect of cumulative vocabulary-F0 interaction

m15 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              F1_Regression_Normalized : F0_Regression_Normalized+
              F1_Regression_Normalized : frt +
              F1_Regression_Normalized : log_cum +
              F0_Regression_Normalized : frt +
              F0_Regression_Normalized : log_cum +
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized + frt | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m15, file = "m15.rds")

as.data.frame(anova(m14,m15))

➡️ Better datafit with m15

3.2.16. Model 16: Fixed effect of cumulative vocabulary-F0-F1 interaction

m16 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              F1_Regression_Normalized : F0_Regression_Normalized+
              F1_Regression_Normalized : frt +
              F1_Regression_Normalized : log_cum +
              F0_Regression_Normalized : frt +
              F0_Regression_Normalized : log_cum +
              F1_Regression_Normalized : F0_Regression_Normalized : log_cum +
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized + frt | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m16, file = "m16.rds")

as.data.frame(anova(m15,m16))

❌ No better datafit with m16

3.2.17. Model 17: Fixed effect of place of articulation-F0-F1 interaction

m17 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              F1_Regression_Normalized : F0_Regression_Normalized+
              F1_Regression_Normalized : frt +
              F1_Regression_Normalized : log_cum +
              F0_Regression_Normalized : frt +
              F0_Regression_Normalized : log_cum +
              F1_Regression_Normalized : F0_Regression_Normalized : frt +
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized + frt | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m17, file = "m17.rds")

as.data.frame(anova(m15,m17))

➡️ Better datafit with m17

3.2.18. Model 18: Fixed effect of cumulative vocabulary-place of articulation-F0-F1 interaction

m18 <- glmer(data = df, 
            formula = hgt ~ log_cum + 
              F1_Regression_Normalized+
              F0_Regression_Normalized+
              frt +
              F1_Regression_Normalized : F0_Regression_Normalized+
              F1_Regression_Normalized : frt +
              F1_Regression_Normalized : log_cum +
              F0_Regression_Normalized : frt +
              F0_Regression_Normalized : log_cum +
              F1_Regression_Normalized : F0_Regression_Normalized : frt +
              F1_Regression_Normalized : F0_Regression_Normalized : frt : log_cum +
              (1 + log_cum + F1_Regression_Normalized + F0_Regression_Normalized + frt | CHILD),  family = "binomial"(link = "logit"),
            control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2000000)))
saveRDS(m18, file = "m18.rds")

as.data.frame(anova(m17,m18))

❌ No better datafit with m18

3.3. Final Model ✅

final_model <- m17
print(summary(final_model))
Generalized linear mixed model fit by maximum likelihood (Laplace Approximation) ['glmerMod']
 Family: binomial  ( logit )
Formula: hgt ~ log_cum + F1_Regression_Normalized + F0_Regression_Normalized +  
    frt + F1_Regression_Normalized:F0_Regression_Normalized +  
    F1_Regression_Normalized:frt + F1_Regression_Normalized:log_cum +  
    F0_Regression_Normalized:frt + F0_Regression_Normalized:log_cum +  
    F1_Regression_Normalized:F0_Regression_Normalized:frt + (1 +  
    log_cum + F1_Regression_Normalized + F0_Regression_Normalized +      frt | CHILD)
   Data: df
Control: glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2e+06))

     AIC      BIC   logLik deviance df.resid 
  9029.2   9223.3  -4488.6   8977.2    12880 

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
 -6.281  -0.375  -0.156   0.248 240.387 

Random effects:
 Groups Name                     Variance Std.Dev. Corr                   
 CHILD  (Intercept)              2.2732   1.5077                          
        log_cum                  0.1064   0.3263   -0.97                  
        F1_Regression_Normalized 2.8553   1.6898    0.33 -0.44            
        F0_Regression_Normalized 3.0895   1.7577   -0.01  0.05 -0.02      
        frt1                     0.1505   0.3880    0.28 -0.32  0.34 -0.15
Number of obs: 12906, groups:  CHILD, 30

Fixed effects:
                                                       Estimate Std. Error z value Pr(>|z|)
(Intercept)                                            -2.00898    0.32324  -6.215 5.13e-10
log_cum                                                 0.27316    0.07079   3.859 0.000114
F1_Regression_Normalized                               -1.87675    0.70340  -2.668 0.007628
F0_Regression_Normalized                                1.66602    0.59373   2.806 0.005015
frt1                                                    0.52375    0.07874   6.651 2.91e-11
F1_Regression_Normalized:F0_Regression_Normalized      -1.87024    0.62241  -3.005 0.002657
F1_Regression_Normalized:frt1                           0.79509    0.17455   4.555 5.23e-06
log_cum:F1_Regression_Normalized                       -1.42642    0.14866  -9.595  < 2e-16
F0_Regression_Normalized:frt1                          -0.94897    0.14672  -6.468 9.95e-11
log_cum:F0_Regression_Normalized                        0.40528    0.11618   3.488 0.000486
F1_Regression_Normalized:F0_Regression_Normalized:frt1  1.16619    0.58946   1.978 0.047883
                                                          
(Intercept)                                            ***
log_cum                                                ***
F1_Regression_Normalized                               ** 
F0_Regression_Normalized                               ** 
frt1                                                   ***
F1_Regression_Normalized:F0_Regression_Normalized      ** 
F1_Regression_Normalized:frt1                          ***
log_cum:F1_Regression_Normalized                       ***
F0_Regression_Normalized:frt1                          ***
log_cum:F0_Regression_Normalized                       ***
F1_Regression_Normalized:F0_Regression_Normalized:frt1 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
               (Intr) log_cm F1_Rg_N F0_Rg_N frt1   F1_Rg_N:F0_R_N F1_R_N:1 l_:F1_ F0_R_N:
log_cum        -0.970                                                                     
F1_Rgrssn_N     0.084 -0.122                                                              
F0_Rgrssn_N    -0.002  0.017 -0.125                                                       
frt1            0.202 -0.234  0.158  -0.079                                               
F1_Rg_N:F0_R_N -0.056  0.047  0.109  -0.181   0.024                                       
F1_Rgrs_N:1     0.006 -0.020 -0.041  -0.002  -0.010  0.035                                
lg_c:F1_R_N     0.054 -0.057 -0.855   0.134  -0.039 -0.184          0.014                 
F0_Rgrs_N:1     0.021 -0.017  0.010  -0.049  -0.111  0.000         -0.141    0.004        
lg_c:F0_R_N    -0.011 -0.001  0.128  -0.786   0.015  0.176          0.018   -0.158  0.032 
F1_R_N:F0_R_N:  0.007  0.000 -0.012   0.135  -0.037 -0.197         -0.245    0.012 -0.203 
               l_:F0_
log_cum              
F1_Rgrssn_N          
F0_Rgrssn_N          
frt1                 
F1_Rg_N:F0_R_N       
F1_Rgrs_N:1          
lg_c:F1_R_N          
F0_Rgrs_N:1          
lg_c:F0_R_N          
F1_R_N:F0_R_N: -0.171
# Assuming final_model is your mixed-effects model
summary_final_model <- summary(final_model)

formula <- final_model@call$formula

# Fixed effects summary
print(as.data.frame(round(coef(summary_final_model),3)))

print(as.data.frame(coef(summary_final_model)))

4. Data vizaulization 📊

4.0. Refit model with cum.voc. centred at other values

# Center by subtracting the mean of 'log_cum'
df_no_ctr <- df
df_no_ctr$log_cum <- df_no_ctr$log_cum - mean(df_no_ctr$log_cum)  # Center by the mean

# Fit the model again using the centered log_cum (mean-centered)
refit_model_ctr_mean <- glmer(
  formula = final_model@call$formula,
  data = df_no_ctr,
  family = binomial,
  control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2e5))
)

df_max <- df
df_max$log_cum <- df_max$log_cum-max(df_max$log_cum)

refit_model_max <- glmer(
formula <- final_model@call$formula,
  data = df_max,
  family = binomial,
  control = glmerControl(optimizer = "bobyqa", optCtrl = list(maxfun = 2e5))
)

4.1. F0 and F1 effects on vowel height

# Plot F1 with separate lines for each level of facto_hgt
plot_f1 <- plot_model(final_model, 
                      type = "eff", 
                      terms = c("F1_Regression_Normalized [all]", "frt"),  
                      mdrt.values = "meansd", 
                      color = "orange") +  # color lines by factor
  theme_cowplot() +
  xlim(c(-2, 2)) +
  labs(y = "Probability of a vowel being high", 
       x = "Normalized F1") +
  theme(plot.title = element_blank(), 
        plot.subtitle = element_blank(), 
        plot.caption = element_blank())+
  aes(linetype = group_col)+
  scale_linetype_discrete(name = "Place of \narticulation",labels = c("back", "front"))  +
  scale_color_manual(values = c("orange","orange"), guide = "none")+
  scale_fill_manual(values = c("orange","orange"), guide = "none")
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.
plot_f0 <- plot_model(final_model, 
                      type = "eff", 
                      terms = c("F0_Regression_Normalized [all]", "frt"), 
                      mdrt.values = "meansd", 
                      at = list(log_cum = max(log_cum)),
                      color = "purple") +
    aes(linetype = group_col)+
  theme_cowplot() +
  xlim(c(-2, 2)) +
  labs(y = "", x = "Normalized F0") +
  theme(plot.title = element_blank(), 
        plot.subtitle = element_blank(), 
        plot.caption = element_blank())+
  scale_linetype_discrete(name = "Place of \narticulation",  labels = c("back", "front"))  +
  scale_color_manual(values = c("purple","purple"), guide = "none")+
  scale_fill_manual(values = c("purple","purple"), guide = "none")
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.
# Combine plots
combined_plots <- grid.arrange(plot_f1, plot_f0, ncol = 2)


# Print combined plot
print(combined_plots)
TableGrob (1 x 2) "arrange": 2 grobs
# Save
ggsave(filename = "~/Desktop/f1_vs_f0_by_frt_eps.eps", 
       plot = combined_plots, 
       width = 10, height = 6, dpi = 1000)
Warning: semi-transparency is not supported on this device: reported only once per page

4.2. Developmental trajectories

# Define colors for F1 and F0
f1_color <- c("#9F3400","#FF681F","#FFBE9F")
f0_color <- c("#570987","#A020F0","#D397F8")

# Plot for F1
plot_f1 <- plot_model(final_model, type = "eff", terms = c("log_cum [all]", "F1_Regression_Normalized")) +
  labs(color = "Normalized F1", y = "Predicted probability of a vowel being high", x = "log(cumulative vocabulary)", title = "") +
  theme_cowplot() +
  scale_color_manual(values = f1_color) +  # Specify color for F1
  scale_fill_manual(values = f1_color) +  # Specify color for F1
  scale_y_continuous(labels = percent_format(), limits = c(0, 1)) +    # Set y-axis limits from 0 to 1
  theme(legend.position = "bottom", legend.box = "horizontal")  
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.Scale for y is already present.
Adding another scale for y, which will replace the existing scale.
# Plot for F0
plot_f0 <- plot_model(final_model, type = "eff", terms = c("log_cum [all]", "F0_Regression_Normalized")) +
  labs(color = "Normalized F0", y = "Predicted probability of a vowel being high", x = "log(cumulative vocabulary)", title = "") +
  theme_cowplot() +
  scale_color_manual(values = f0_color) +  # Specify color for F0
  scale_fill_manual(values = f0_color) +  # Specify color for F0
   scale_y_continuous(labels = percent_format(), limits = c(0, 1)) +    # Set y-axis limits from 0 to 1
  theme(legend.position = "bottom", legend.box = "horizontal")  
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.Scale for y is already present.
Adding another scale for y, which will replace the existing scale.
# Adjust plot width and height
plot_f1 

plot_f0


ggsave(
  filename = "~/Desktop/plot_f1_eps.eps",
  plot = plot_f1,
  width = 6,
  height = 5,
  units = "in"
)

ggsave(
  filename = "~/Desktop/plot_f0_eps.eps",
  plot = plot_f0,
  width = 6,
  height = 5,
  units = "in"
)


df_plot_f1 <- plot_f1$data
df_plot_f0 <- plot_f0$data

print(as.data.frame(df_plot_f1))
print(as.data.frame(df_plot_f0))
pr_F1<-predict_response(final_model,c("F1_Regression_Normalized", "log_cum" ))
Data were 'prettified'. Consider using `terms="F1_Regression_Normalized [all]"` to
  get smooth plots.
jn_pr_F1 <- plot(johnson_neyman(pr_F1))  +
    scale_color_manual(values = c("inconsistent" = "grey", "positive/negative" = "orange")) +
  scale_fill_manual(values = c("inconsistent" = "grey", "positive/negative" = "orange")) +
  labs(y = "Slope of Normalized F1", x = "log(cumulative vocabulary)", title = "") +
  theme_cowplot() +
  theme(legend.position = "bottom", legend.box = "horizontal") + 
  ylim(c(-0.5,0.5))
Warning: For this model type, `marginaleffects` only takes into account the uncertainty in
  fixed-effect parameters. You can use the `re.form=NA` argument to acknowledge this
  explicitly and silence this warning.Warning: For this model type, `marginaleffects` only takes into account the uncertainty in
  fixed-effect parameters. You can use the `re.form=NA` argument to acknowledge this
  explicitly and silence this warning.
The association between `F1_Regression_Normalized` and `hgt` is negative for values
  of `log_cum` higher than 0.32. There were no clear associations for values of
  `log_cum` lower than 0.32.

pr_F0<-predict_response(final_model,c("F0_Regression_Normalized", "log_cum"))
Data were 'prettified'. Consider using `terms="F0_Regression_Normalized [all]"` to
  get smooth plots.
jn_pr_F0 <- plot(johnson_neyman(pr_F0))  +
  scale_color_manual(values = c("inconsistent" = "grey", "positive/negative" = "purple")) +
  scale_fill_manual(values = c("inconsistent" = "grey", "positive/negative" = "purple")) +
  labs(y = "Slope of Normalized F0", x = "log(cumulative vocabulary)", title = "") +
  theme_cowplot() +
  theme(legend.position = "bottom", 
        legend.box = "horizontal")+ 
  ylim(c(-0.5,0.5))
Warning: For this model type, `marginaleffects` only takes into account the uncertainty in
  fixed-effect parameters. You can use the `re.form=NA` argument to acknowledge this
  explicitly and silence this warning.Warning: For this model type, `marginaleffects` only takes into account the uncertainty in
  fixed-effect parameters. You can use the `re.form=NA` argument to acknowledge this
  explicitly and silence this warning.
The association between `F0_Regression_Normalized` and `hgt` is positive for values
  of `log_cum` higher than 0.85. There were no clear associations for values of
  `log_cum` lower than 0.85.

jn_pr_F1

jn_pr_F0

ggsave(filename = "~/Desktop/jn_pr_F0_eps.eps", 
       plot = jn_pr_F0, 
       width = 10, height = 6, dpi = 1000)

ggsave(filename = "~/Desktop/jn_pr_F1_eps.eps", 
       plot = jn_pr_F1, 
       width = 10, height = 6, dpi = 1000)

4.3. Correlation between cues

corr_full <- cor.test(df$F1_Regression_Normalized,
                      df$F0_Regression_Normalized, method = 'pearson')

high <- df %>% filter(hgt == "high" )
low  <- df %>% filter(hgt == "low")

corr_high <- cor.test(high$F1_Regression_Normalized,
                      high$F0_Regression_Normalized)

corr_low <- cor.test(low$F1_Regression_Normalized,
                     low$F0_Regression_Normalized)

# Put all results in a list
corr_results <- list(
  full = corr_full,
  high = corr_high,
  low  = corr_low
)

corr_results
$full

    Pearson's product-moment correlation

data:  df$F1_Regression_Normalized and df$F0_Regression_Normalized
t = 10.484, df = 12904, p-value < 2.2e-16
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.0747654 0.1089797
sample estimates:
       cor 
0.09189966 


$high

    Pearson's product-moment correlation

data:  high$F1_Regression_Normalized and high$F0_Regression_Normalized
t = 5.6985, df = 3349, p-value = 1.313e-08
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.06434937 0.13142014
sample estimates:
       cor 
0.09799603 


$low

    Pearson's product-moment correlation

data:  low$F1_Regression_Normalized and low$F0_Regression_Normalized
t = 21.73, df = 9553, p-value < 2.2e-16
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.1978370 0.2360515
sample estimates:
      cor 
0.2170274 


df_avg <- df %>%
  group_by(CHILD,hgt) %>%
  summarise(
    F1_avg = mean(F1_Regression_Normalized, na.rm = TRUE),
    F0_avg = mean(F0_Regression_Normalized, na.rm = TRUE),
    .groups = "drop"
  )

corr_full_avg <- cor.test(df_avg$F1_avg, df_avg$F0_avg, method = "pearson")

df_avg <- df %>%
  group_by(CHILD,hgt) %>%
  summarise(
    F1_avg = mean(F1_Regression_Normalized, na.rm = TRUE),
    F0_avg = mean(F0_Regression_Normalized, na.rm = TRUE),
    .groups = "drop"
  )

high_avg <- df_avg %>% filter(hgt == "high")
low_avg  <- df_avg %>% filter(hgt == "low")

corr_high_avg <- cor.test(high_avg$F1_avg, high_avg$F0_avg, method = "pearson")
corr_low_avg  <- cor.test(low_avg$F1_avg,  low_avg$F0_avg,  method = "pearson")


corr_results_avg <- list(
  full_avg = corr_full_avg,
  high_avg = corr_high_avg,
  low_avg  = corr_low_avg
)

corr_results_avg
$full_avg

    Pearson's product-moment correlation

data:  df_avg$F1_avg and df_avg$F0_avg
t = -4.3161, df = 58, p-value = 6.269e-05
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.6638678 -0.2733592
sample estimates:
       cor 
-0.4930594 


$high_avg

    Pearson's product-moment correlation

data:  high_avg$F1_avg and high_avg$F0_avg
t = -0.16062, df = 28, p-value = 0.8735
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.3863857  0.3335755
sample estimates:
        cor 
-0.03033985 


$low_avg

    Pearson's product-moment correlation

data:  low_avg$F1_avg and low_avg$F0_avg
t = 1.4681, df = 28, p-value = 0.1532
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 -0.1028207  0.5724807
sample estimates:
      cor 
0.2673521 

# Extract coefficient values and convert to a data frame for mean-centered model
coefficients_mean <- as.data.frame(coef(refit_model_ctr_mean )$CHILD)
coefficients_mean$id <- row.names(coefficients_mean)
coefficients_mean$model <- "mean_centered"

# Combine final, refit, and mean-centered coefficients into one data frame
coefficients_combined <- rbind(coefficients_mean)

# Make sure id is a factor
coefficients_combined$id <- as.factor(coefficients_combined$id)

# Gather F1 and F0 into one 'variable' column
coefficients_long <- coefficients_combined %>%
  select(id, model, F1_Regression_Normalized, F0_Regression_Normalized) %>%
  gather(key = "variable", value = "value", F1_Regression_Normalized, F0_Regression_Normalized)

# Spread by model (final, refit, and mean-centered)
coefficients_wide <- coefficients_long %>%
  spread(key = model, value = value)

# Pivot wider to include final, refit, and mean-centered values
coefficients_final_wide <- coefficients_wide %>%
  pivot_wider(
    names_from = variable,
    values_from = c(mean_centered)
  )

plot <- ggplot(coefficients_final_wide, aes(x =F1_Regression_Normalized,
                                    y = F0_Regression_Normalized)) +
  geom_point(color = "grey60", size = 3, alpha = 0.8) +
  sm_statCorr(color = "#5F021F")+
  xlim(-12,0)+
  ylim(0,12)+
  theme_minimal() +
  theme(
    legend.position = "bottom",
    legend.direction = "horizontal",
    legend.box = "horizontal",
    panel.grid.major = element_line(color = "gray95", size = 0.5),  # Subtle grid lines
    panel.grid.minor = element_blank(),  # Remove minor grid lines for a cleaner look
    axis.title = element_text(size = 14, face = "bold"),
    axis.text = element_text(size = 12),
    plot.title = element_text(size = 16, face = "bold", hjust = 0.5),,
    plot.margin = margin(20, 20, 20, 20)  # Add margin for aesthetics
  ) +
  labs(
    x = "F1 Regression Normalized",
    y = "F0 Regression Normalized")+
  coord_fixed()

plot

ggsave(filename = "~/Desktop/corr_eps.eps", 
       plot = plot, 
       width = 10, height = 6, dpi = 1000)

4.4. Between children variability

# Extract coefficient values and convert to a data frame
coefficients_0<- as.data.frame(coef(final_model)$CHILD)
coefficients_0$id <- row.names(coefficients_0)   # Add ID as a column
coefficients_0$id <- as.factor(coefficients_0$id)   # Convert ID to factor

# Reshape the data frame from wide to long format
coefficients_0<- pivot_longer(coefficients_0, cols = c(F0_Regression_Normalized, F1_Regression_Normalized), names_to = "Variable", values_to = "Value")

# Extract coefficient values and convert to a data frame
coefficients_max<- as.data.frame(coef(refit_model_max)$CHILD)
coefficients_max$id <- row.names(coefficients_max)   # Add ID as a column
coefficients_max$id <- as.factor(coefficients_max$id)   # Convert ID to factor


# Reshape the data frame from wide to long format
coefficients_max<- pivot_longer(coefficients_max, cols = c(F0_Regression_Normalized, F1_Regression_Normalized), names_to = "Variable", values_to = "Value")

# Add a "Centering" column to identify where the coefficients come from
coefficients_0$Centering <- "Centered_at_0"
coefficients_max$Centering <- "Centered_at_Max"


# Combine the two data frames
coef_full <- bind_rows(coefficients_0, coefficients_max)

# Add a new column to control alpha
coef_full$Alpha <- ifelse(coef_full$Centering == "Centered_at_0", 0.9, 1)  # Circles = 0.3, Triangles = 1

# Update the levels and labels for better readability
coef_full$Variable <- factor(coef_full$Variable, 
                             levels = c("F0_Regression_Normalized", "F1_Regression_Normalized"),
                             labels = c("F0", "F1"))

coef_full$Centering <- factor(coef_full$Centering,
                              levels = c("Centered_at_0", "Centered_at_Max"),
                              labels = c("At cumulative vocabulary = 0", "At maximum cumulative vocabulary"))


# Reorder ids based on F1 values (choose which centering you want)
coef_full_ordered <- coef_full %>%
  filter(Variable == "F0") %>%
  arrange(Value) %>%
  mutate(id = factor(id, levels = unique(id))) %>%
  select(id) %>%
  right_join(coef_full, by = "id") %>%   # restore full dataset with ordering
  left_join(
    df_descr_phon %>% distinct(id = CHILD, label = CHILD_anon),
    by = "id"
  )
Warning: Detected an unexpected many-to-many relationship between `x` and `y`.
coef_full_ordered <- coef_full_ordered %>%
  mutate(label = factor(label, levels = unique(label[order(id)])))

plot <- ggplot(coef_full_ordered, aes(x = label, y = Value)) +
  geom_point(size = 3, aes(color = Variable, shape = Centering)) +
  scale_shape_manual(values = c(
    "At cumulative vocabulary = 0" = 1,
    "At maximum cumulative vocabulary" = 16
  )) +
  scale_color_manual(values = c("F0" = "purple", "F1" = "orange")) +
  geom_segment(aes(x = label, xend = label, y = 0, yend = Value, color = Variable),
               size = 0.5) +
  labs(
    title = "",
    x = "Child label",
    y = "Individual Coefficient Value",
    color = "Cue",
    shape = "Cumulative vocabulary"
  ) +
  #scale_x_discrete(labels = label) +
  theme_minimal() +
  theme(
    legend.position = "right",
    legend.direction = "vertical",
    legend.box = "vertical",
    axis.text.x = element_text(angle = 45, hjust = 1),
    plot.title = element_text(size = 16, hjust = 0.5),
    panel.grid.minor.y = element_blank(),
    legend.text = element_text(size = 12),
    legend.title = element_text(size = 13)
  )

plot

ggsave(filename = "~/Desktop/lolliplot_eps.eps", 
       plot = plot, 
       width = 20, height = 6, dpi = 1000)

# Choose constant values for F1_Regression_Normalized and F0_Regression_Normalized
constant_F1_low <- mean(df$F1_Regression_Normalized) - 1*sd(df$F1_Regression_Normalized)
constant_F0_high <- mean(df$F0_Regression_Normalized) + 1*sd(df$F0_Regression_Normalized)
constant_F1_high <- mean(df$F1_Regression_Normalized) + 1*sd(df$F1_Regression_Normalized)
constant_F0_low <- mean(df$F0_Regression_Normalized) - 1*sd(df$F0_Regression_Normalized)

# Define a sequence of values for log_cum
log_cum_seq <- seq(from = min(df$log_cum), to = max(df$log_cum), length.out = 100)

# Create new data for both scenarios
new_data_low_F1 <- data.frame(
  F1_Regression_Normalized = constant_F1_low,
  F0_Regression_Normalized = mean(df$F0_Regression_Normalized, na.rm=T),
  log_cum = log_cum_seq,
  frt = "bck",
  CHILD = rep(unique(df$CHILD), each = length(log_cum_seq))
)

new_data_high_F0 <- data.frame(
  F0_Regression_Normalized = constant_F0_high,
  F1_Regression_Normalized = mean(df$F1_Regression_Normalized, na.rm=T),
  log_cum = log_cum_seq,
    frt = "bck",
  CHILD = rep(unique(df$CHILD), each = length(log_cum_seq))
)

new_data_high_F1 <- data.frame(
  F1_Regression_Normalized = constant_F1_high,
  F0_Regression_Normalized = mean(df$F0_Regression_Normalized, na.rm=T),
  log_cum = log_cum_seq,
    frt = "bck",
  CHILD = rep(unique(df$CHILD), each = length(log_cum_seq))
)

new_data_low_F0 <- data.frame(
  F0_Regression_Normalized = constant_F0_low,
  F1_Regression_Normalized = mean(df$F1_Regression_Normalized, na.rm=T),
  log_cum = log_cum_seq,
    frt = "bck",
  CHILD = rep(unique(df$CHILD), each = length(log_cum_seq))
)

# Predict probabilities for the new data
predicted_probs_low_F1 <- predict(final_model, newdata = new_data_low_F1, type = "response")
predicted_probs_high_F0 <- predict(final_model, newdata = new_data_high_F0, type = "response")
predicted_probs_high_F1 <- predict(final_model, newdata = new_data_high_F1, type = "response")
predicted_probs_low_F0 <- predict(final_model, newdata = new_data_low_F0, type = "response")

# Combine log_cum_seq, predicted_probs, and CHILD into data frames
predicted_df_low_F1 <- data.frame(
  log_cum = rep(log_cum_seq, length(unique(df$CHILD))),
  predicted_prob = predicted_probs_low_F1,
  CHILD = rep(unique(df$CHILD), each = length(log_cum_seq))
)

predicted_df_high_F0 <- data.frame(
  log_cum = rep(log_cum_seq, length(unique(df$CHILD))),
  predicted_prob = predicted_probs_high_F0,
  CHILD = rep(unique(df$CHILD), each = length(log_cum_seq))
)

predicted_df_high_F1 <- data.frame(
  log_cum = rep(log_cum_seq, length(unique(df$CHILD))),
  predicted_prob = predicted_probs_high_F1,
  CHILD = rep(unique(df$CHILD), each = length(log_cum_seq))
)

predicted_df_low_F0 <- data.frame(
  log_cum = rep(log_cum_seq, length(unique(df$CHILD))),
  predicted_prob = predicted_probs_low_F0,
  CHILD = rep(unique(df$CHILD), each = length(log_cum_seq))
)

# Calculate average predicted probabilities
average_prob_low_F1 <- predicted_df_low_F1 %>%
  group_by(log_cum) %>%
  summarize(average_prob = mean(predicted_prob))

average_prob_high_F0 <- predicted_df_high_F0 %>%
  group_by(log_cum) %>%
  summarize(average_prob = mean(predicted_prob))

average_prob_high_F1 <- predicted_df_high_F1 %>%
  group_by(log_cum) %>%
  summarize(average_prob = mean(predicted_prob))

average_prob_low_F0 <- predicted_df_low_F0 %>%
  group_by(log_cum) %>%
  summarize(average_prob = mean(predicted_prob))

# Plot the lines
plot1 <- ggplot(predicted_df_low_F1) +
  geom_line(aes(x = log_cum, y = predicted_prob, group = CHILD), color = "orange", alpha = 0.2) +
  geom_line(data = average_prob_low_F1, aes(x = log_cum, y = average_prob), color = "orange", size = 2) +
  labs(x = "", y = "", title = "a low F1 (mean-SD)") +
     scale_y_continuous(labels = percent_format(), limits = c(0, 1)) + 
  theme_minimal()

plot2 <- ggplot(predicted_df_high_F0) +
  geom_line(aes(x = log_cum, y = predicted_prob, group = CHILD), color = "purple", alpha = 0.2) +
  geom_line(data = average_prob_high_F0, aes(x = log_cum, y = average_prob), color = "purple", size = 2) +
  labs(x = "", y = "", title = "a high F0 (mean+SD)") +
     scale_y_continuous(labels = percent_format(), limits = c(0, 1)) + 
  theme_minimal()

plot3 <- ggplot(predicted_df_high_F1) +
  geom_line(aes(x = log_cum, y = predicted_prob, group = CHILD), color = "orange", alpha = 0.2) +
  geom_line(data = average_prob_high_F1, aes(x = log_cum, y = average_prob), color = "orange", size = 2) +
  labs(x = "log (cumulative vocabulary)", y = "", title = "a high F1 (mean+SD)") +
     scale_y_continuous(labels = percent_format(), limits = c(0, 1)) + 
  theme_minimal()

plot4 <- ggplot(predicted_df_low_F0) +
  geom_line(aes(x = log_cum, y = predicted_prob, group = CHILD), color = "purple", alpha = 0.2) +
  geom_line(data = average_prob_low_F0, aes(x = log_cum, y = average_prob), color = "purple", size = 2) +
  labs(x = "log (cumulative vocabulary)", y = "", title = "a low F0 (mean-SD)") +
     scale_y_continuous(labels = percent_format(), limits = c(0, 1)) + 
  theme_minimal()

# Combine plots
combined_plots <- grid.arrange(plot1, plot2, plot3, plot4, ncol = 2)


# Add overall title
overall_title <- ggdraw() + 
  draw_label("Individual trajectories for the effect of", size = 15, fontface = "bold", x = 0.5)

# Add single y-axis label
y_label <- ggdraw() + 
  draw_label("Predicted probability of a vowel being high", size = 12, angle = 90, 
             x = 0.015, y = -1, vjust = 0.5, hjust = 1)
# Print combined plot with overall title
grid.arrange(overall_title, y_label, combined_plots, ncol = 1, heights = c(0.05, 0.05, 0.9))


save.image(file = "analysis_F1_F0.RData")
LS0tCnRpdGxlOiAiRjEgRjAgY3VlLXdlaWdodGluZyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyAxLiBMb2FkIG5lY2Vzc2FyeSBtYXRlcmlhbHMg8J+TmgoKIyMgMS4xLiBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMgCmBgYHtyfQpsaWJyYXJ5KG1ldFIpICAgICAgICAjIFRvb2xzIGZvciBtZXRlb3JvbG9naWNhbCBkYXRhIHByb2Nlc3NpbmcKbGlicmFyeShyZWFkcikgICAgICAgIyBGb3IgcmVhZGluZyBDU1YgZmlsZXMgZWZmaWNpZW50bHkKbGlicmFyeShkcGx5cikgICAgICAgIyBGb3IgZGF0YSBtYW5pcHVsYXRpb24gYW5kIHRyYW5zZm9ybWF0aW9uCmxpYnJhcnkodGlkeXIpICAgICAgICMgRm9yIHRpZHlpbmcgZGF0YSAocmVzaGFwaW5nKQpsaWJyYXJ5KGdncGxvdDIpICAgICAjIEZvciBjcmVhdGluZyBjb21wbGV4IGRhdGEgdmlzdWFsaXphdGlvbnMKbGlicmFyeShsbWU0KSAgICAgICAgIyBGb3IgZml0dGluZyBsaW5lYXIgbWl4ZWQtZWZmZWN0cyBtb2RlbHMKbGlicmFyeShlbW1lYW5zKSAgICAgIyBGb3IgY29tcHV0aW5nIGVzdGltYXRlZCBtYXJnaW5hbCBtZWFucyAocG9zdCBob2MgYW5hbHlzaXMpCmxpYnJhcnkobG1lclRlc3QpICAgICMgRm9yIGh5cG90aGVzaXMgdGVzdGluZyBpbiBsaW5lYXIgbWl4ZWQtZWZmZWN0cyBtb2RlbHMKbGlicmFyeShncmlkRXh0cmEpICAgIyBGb3IgYXJyYW5naW5nIG11bHRpcGxlIGdyaWQgZ3JhcGhpY3MKbGlicmFyeShjb3dwbG90KSAgICAgIyBGb3IgY3JlYXRpbmcgY29tcGxleCBnZ3Bsb3QyIGxheW91dHMKbGlicmFyeShEZXNjVG9vbHMpICAgIyBGb3IgZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBhbmQgZGF0YSBleHBsb3JhdGlvbgpsaWJyYXJ5KHNqbWlzYykgICAgICAjIEZvciBkYXRhIHByZXBhcmF0aW9uIGFuZCB2YXJpYWJsZSByZWNvZGluZwpsaWJyYXJ5KHJlYWR4bCkgICAgICAjIEZvciByZWFkaW5nIEV4Y2VsIGZpbGVzCmxpYnJhcnkoc2pQbG90KSAgICAgICMgRm9yIGdlbmVyYXRpbmcgcGxvdHMgYW5kIHN1bW1hcnkgdGFibGVzCmxpYnJhcnkoYnJvb20ubWl4ZWQpICMgRm9yIHRpZHlpbmcgdXAgbW9kZWwgb3V0cHV0cyBmcm9tIG1peGVkIG1vZGVscwpsaWJyYXJ5KHNjYWxlcykgICAgICAjIEZvciBzY2FsaW5nIGFuZCBmb3JtYXR0aW5nIG9mIGF4ZXMgKGUuZy4sIHBlcmNlbnRfZm9ybWF0KQpsaWJyYXJ5KGdnZWZmZWN0cykgICAjIEZvciB2aXN1YWxpemluZyBlZmZlY3RzIGZyb20gcmVncmVzc2lvbiBtb2RlbHMKbGlicmFyeShnZ3JpZGdlcykgICAgIyBGb3IgY3JlYXRpbmcgcmlkZ2UgcGxvdHMKbGlicmFyeShwYXRjaHdvcmspICAgIyBGb3IgY29tYmluaW5nIGdncGxvdDIgcGxvdHMKbGlicmFyeShzbXBsb3QyKSAgICAgIyBGb3IgY3JlYXRpbmcgc3VtbWFyeSBwbG90cwpsaWJyYXJ5KGdncHVicikgICAgICAjIEZvciBnZ3Bsb3QyLWJhc2VkIHB1YmxpY2F0aW9uLXJlYWR5IHBsb3RzCmxpYnJhcnkocHVycnIpICAgICAgICMgRm9yIGZ1bmN0aW9uYWwgcHJvZ3JhbW1pbmcgYW5kIGRhdGEgbWFuaXB1bGF0aW9uCmBgYAoKCiMjIDEuMi4gRGF0YSBMb2FkaW5nIApgYGB7cn0KIyBSZWFkIHRoZSBtYWluIGRhdGEgZmlsZQpkZiA8LSByZWFkX2Nzdigifi9Eb2N1bWVudHMvUmVzZWFyY2gvQ29kZS9GMV9GMF9jdWVfd2VpZ2h0aW5nL0RhdGEvZGF0YV9hbm5vdGF0ZWRfdl9vcHRpbV9wYXJhbV96c2NvX3d0aF9vdXRsaWVycy5jc3YiLHNob3dfY29sX3R5cGVzID0gRkFMU0UpCgojIENvbnZlcnQgQUdFIGNvbHVtbiB0byBmYWN0b3IgYW5kIHNwZWNpZnkgY3VzdG9tIGxldmVscwpkZiRBR0UgPC0gZmFjdG9yKGRmJEFHRSwgbGV2ZWxzID0gYygiMDA7MDYiLCAiMDA7MDciLCAiMDA7MDgiLCAiMDA7MDkiLCAiMDA7MTAiLCAiMDA7MTEiLCAiMDE7MDAiLCAiMDE7MDEiLCAiMDE7MDIiLCAiMDE7MDMiLCAiMDE7MDQiLCAiMDE7MDUiLCAiMDE7MDYiLCAiMDE7MDciLCAiMDE7MDgiLCAiMDE7MDkiLCAiMDE7MTAiLCAiMDE7MTEiLCAiMDI7MDAiKSkKCgojIFJlYWQgdGhlIHN1cHBsZW1lbnRhcnkgZGF0YSBmaWxlCmN1bXZvYy55X0FMTEVfTkggPC0gcmVhZF9leGNlbCgiL1VzZXJzL2plcmVteWdlbmV0dGVfc3R1ZGlvL0RvY3VtZW50cy9SZXNlYXJjaC9Db2RlL0YxX0YwX2N1ZV93ZWlnaHRpbmcvRGF0YS9jdW12b2NfQUxMRV9OSF92Zi54bHN4IikKCiMgUHJvY2VzcyBzdXBwbGVtZW50YXJ5IGRhdGEKY3Vtdm9jLnlfQUxMRV9OSCA8LSBjdW12b2MueV9BTExFX05IICU+JSAKICBmaWx0ZXIoIWlzLm5hKGBDdW0gdm9jYCkpICU+JSAKICBzZWxlY3QoLWBDaHJvbmFnZS9IZWFyQWdlYCkgJT4lIAogIG11dGF0ZShpdGVtID0gc3ViKCJfLioiLCAiIixgT1BNRVJLSU5HOiBjdW0gb3Agd29vcmR2b3JtZW4sIG5pZXQgb3AgbGVtbWFgKSkKCiMgTWVyZ2Ugc3VwcGxlbWVudGFyeSBkYXRhIHdpdGggbWFpbiBkYXRhCmRmIDwtIGxlZnRfam9pbihkZiwgY3Vtdm9jLnlfQUxMRV9OSCwgYnkgPSAiaXRlbSIpCgojIEZpbHRlciBkYXRhIGJhc2VkIG9uIHV0dF90eXBlCmRmIDwtIGRmICU+JQogIGZpbHRlcih1dHRfdHlwZSA9PSAiTEVYIikgCiMgUHJpbnQgdGhlIGZpcnN0IGZldyByb3dzIG9mIHRoZSBtZXJnZWQgYW5kIGZpbHRlcmVkIGRhdGEgZnJhbWUKCiMgQ29udmVydCBwaG9fdndsX251Y2wgY29sdW1uIHRvIGZhY3RvcgpkZiRwaG9fdndsX251Y2wgPC0gYXMuZmFjdG9yKGRmJHBob192d2xfbnVjbCkKCiMgUmVjb2RlIHRoZSBsZXZlbHMgZm9yIGFubm90YXRpb24gY29uc2lzdGVuY3kKZGYkcGhvX3Z3bF9udWNsIDwtIHJlY29kZV9mYWN0b3IoZGYkcGhvX3Z3bF9udWNsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk0iID0gTkFfY2hhcmFjdGVyXywgIyBkaXBodG9uZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkwiID0gTkFfY2hhcmFjdGVyXywgIyBkaXBodG9uZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIksiID0gTkFfY2hhcmFjdGVyXywgIyBkaXBodG9uZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkgiID0gTkFfY2hhcmFjdGVyXywgIyBnbG90dGFsIHN0b3AKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyIiA9ICJAIiwgIyBhbm5vdGF0aW9uIGNvbnNpc3RlbmN5CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPCIgPSAidSIsICMgYW5ub3RhdGlvbiBjb25zaXN0ZW5jeQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIikiID0gIn0iKSAjIGFubm90YXRpb24gY29uc2lzdGVuY3kKCiMgUmVtb3ZlIE5BIGxldmVscwpkZiRwaG9fdndsX251Y2wgPC0gZHJvcGxldmVscyhkZiRwaG9fdndsX251Y2wpCgojIFByaW50IHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgbWVyZ2VkIGFuZCBmaWx0ZXJlZCBkYXRhIGZyYW1lCnByaW50KGhlYWQoZGYpKQpgYGAKCgojIDIuIERhdGEgcHJlcHJvY2Vzc2luZyDimpnvuI8KCiMjIDIuMS4gTm9ybWFsaXphdGlvbiBvZiAqKkYwKiogYmFzZWQgb24gcmVncmVzc2lvbiBhcHByb2FjaCBmcm9tIEJhcnJlZGEgYW5kIE5lYXJleSAoMjAxOCkgYXBwbGllZCB0byBMb2Jhbm92J3MgKDE5NzEpIE5vcm1hbGl6YXRpb24gdGVjaG5pcXVlCgojIyMgMi4xLjEuIERhdGEgcHJlcHJvY2Vzc2luZwoKIlRvIGltcGxlbWVudCB0aGlzIGFuYWx5c2lzIGluIFIsIGl0IGlzIGZpcnN0IGFzc3VtZWQgdGhhdCB0aGUgZGF0YSBhcmUgYXZhaWxhYmxlIGluIGEgZGF0YSBmcmFtZSBvYmplY3QgaW4gYSDigJxsb25n4oCdIGZvcm1hdCB3aXRoIG9ubHkgb25lIGxvZy1mb3JtYW50IG1lYXN1cmVtZW50IHBlciByb3cuIEZ1cnRoZXIsIGl0IGlzIGFzc3VtZWQgdGhhdCBlYWNoIHJvdyBvZiB0aGUgZGF0YSBmcmFtZSBoYXMgKGF0IGxlYXN0KSBmb3VyIGNvbHVtbnMsIGxhYmVsZWQ6IEcgZm9yIHRoZSBzaW5nbGUgZm9ybWFudCBtZWFzdXJlbWVudCwgViBpbmRpY2F0aW5nIHZvd2VsLCBLIGluZGljYXRpbmcgZm9ybWFudCBudW1iZXIsIGFuZCBTIGluZGljYXRpbmcgdGhlIHNwZWFrZXIgWy4uLl1hbiBhZGRpdGlvbmFsIHZhcmlhYmxlIChOKSBtYXkgYmUgY3JlYXRlZCB0byByZXByZXNlbnQgdGhlIE52ayB0ZXJtcywgdXNpbmcgdGhlIFIgY29tbWFuZDogTiDCvCBmYWN0b3JbaW50ZXJhY3Rpb24gKFYsSyldLiIgKHAuNTA3KSAKCmBgYHtyfQojIENvbnZlcnQgZnJvbSB3aWRlIHRvIGxvbmdfRjAgZm9ybWF0CmRmX2xvbmdfRjAgPC0gZGYgJT4lICAjIENyZWF0ZSBhIG5ldyBkYXRhIGZyYW1lIGJ5IHRyYW5zZm9ybWluZyB0aGUgZXhpc3Rpbmcgb25lCiAgc2VsZWN0KGl0ZW0sIENISUxELCBBR0UsIElEX3Z3bCwgcGhvX3Z3bF9udWNsLCBGMCkgJT4lICAjIFNlbGVjdCBzcGVjaWZpYyBjb2x1bW5zIGZyb20gdGhlIG9yaWdpbmFsIGRhdGEgZnJhbWUKICBnYXRoZXIoa2V5ID0gIkZyZXF1ZW5jeSIsIHZhbHVlID0gIlZhbHVlIiwgRjApICAjIFJlc2hhcGUgdGhlIGRhdGEgZnJvbSB3aWRlIHRvIGxvbmdfRjAgZm9ybWF0LCBjb21iaW5pbmcgRjAgYW5kIEYxIGNvbHVtbnMgaW50byBrZXktdmFsdWUgcGFpcnMgCgpkZl9sb25nX0YwJEcgPC0gZGZfbG9uZ19GMCRWYWx1ZSAgIyBhc3NpZ24gVmFsdWUgdG8gJ0cnCmRmX2xvbmdfRjAkUyA8LSBhcy5mYWN0b3IoZGZfbG9uZ19GMCRpdGVtKSAgIyBDb252ZXJ0IHRoZSAnaXRlbScgKD1yZWNvcmRpbmcgc2Vzc2lvbikgY29sdW1uIHRvIGEgZmFjdG9yIGFuZCBhc3NpZ24gaXQgdG8gJ1MnCmRmX2xvbmdfRjAkViA8LSBhcy5mYWN0b3IoZGZfbG9uZ19GMCRwaG9fdndsX251Y2wpICAjIENvbnZlcnQgdGhlICdwaG9fdndsX251Y2wnIGNvbHVtbiB0byBhIGZhY3RvciBhbmQgYXNzaWduIGl0IHRvICdWJwpgYGAKCgojIyMgMi4xLjIuIFJlZ3Jlc3Npb24gCgpDb25zaWRlcmluZyB0aGUgYW50aWNpcGF0ZWQgdmFyaWFiaWxpdHkgaW4gaG93IGRpZmZlcmVudCB2b3dlbCB0eXBlcyBhZmZlY3QgRjAgYW5kIEYxIGZyZXF1ZW5jaWVzIGFjcm9zcyBzcGVha2Vycywgd2hpY2ggd2FzIG5vdCBhZGRyZXNzZWQgaW4gQmFycmVkYSdzIHN0dWR5LCB3ZSBmaW5kIGl0IGltcGVyYXRpdmUgdG8gaW5jb3Jwb3JhdGUgaW50ZXJhY3Rpb25zLgoKYGBge3J9Ck1fRjAgPSBsbShkYXRhID0gZGZfbG9uZ19GMCwKICAgICAgIGZvcm11bGEgPSBHIH4gMCArIFMgKiBWLCBjb250cmFzdHMgPSBsaXN0KFY9Y29udHIuc3VtKSkKCnNhdmVSRFMoTV9GMCwgIn4vRG9jdW1lbnRzL1Jlc2VhcmNoL0NvZGUvRjFfRjBfY3VlX3dlaWdodGluZy9WRi9NRjAucmRzIikKYGBgCgoKIyMjIDIuMS4zLiBDb2VmZmljaWVudHMgZXh0cmFjdGlvbgoKYGBge3J9CiMgRXh0cmFjdCBjb2VmZmljaWVudHMgZm9yIEYwIGZvciBlYWNoIHNwZWFrZXIKQ29lZmZpY2llbnRzX0YwIDwtIHN1bW1hcnkoTV9GMCkkY29lZmZpY2llbnRzICU+JQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIENvbnZlcnQgY29lZmZpY2llbnRzIHRvIGRhdGEgZnJhbWUKICBmaWx0ZXIoZ3JlcGwoIl5TIiwgcm93bmFtZXMoLikpKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgIyBGaWx0ZXIgcm93cyB3aXRoIHNwZWFrZXIgSURzCiAgcmVuYW1lKFNwZWFrZXJfRXN0aW1hdGVfRjAgPSBFc3RpbWF0ZSwgU3BlYWtlcl9TdGRfRXJyb3JfRjAgPSBgU3RkLiBFcnJvcmApICU+JSAgIyBSZW5hbWUgY29sdW1ucwogIG11dGF0ZShpdGVtID0gc3ViKCJeUyIsICIiLCByb3duYW1lcyguKSkpICU+JSAgICAgICAgICAgICAgICAjIEV4dHJhY3Qgc3BlYWtlciBJRHMKICBmaWx0ZXIoIWdyZXBsKCI6IiwgaXRlbSkpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBFeGNsdWRlIHJvd3Mgd2l0aCAiOiIgaW4gc3BlYWtlciBJRHMKCiMgTGVmdCBqb2luIENvZWZmaWNpZW50c19GMCB3aXRoIGRmX2xvbmdfRjAgYnkgdGhlICdpdGVtJyBjb2x1bW4KZGZfbG9uZ193aXRoX2NvZWZfRjAgPC0gbGVmdF9qb2luKGRmX2xvbmdfRjAsIENvZWZmaWNpZW50c19GMCwgYnkgPSAiaXRlbSIpCgojIENhbGN1bGF0ZSBGMCByZWdyZXNzaW9uIE5vcm1hbGl6ZWQgdmFsdWVzCmRmX2xvbmdfd2l0aF9jb2VmX0YwIDwtIGRmX2xvbmdfd2l0aF9jb2VmX0YwICU+JQogIGdyb3VwX2J5KGl0ZW0pICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEdyb3VwIGJ5IHNwZWFrZXIgSURzCiAgbXV0YXRlKEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA9IChWYWx1ZSAtIFNwZWFrZXJfRXN0aW1hdGVfRjApIC8gKFNwZWFrZXJfU3RkX0Vycm9yX0YwICogc3FydChuKCkpKSkgICMgQ2FsY3VsYXRlIE5vcm1hbGl6ZWQgdmFsdWVzCgojIFByaW50IGhlYWQgb2YgZGZfbG9uZ193aXRoX2NvZWZfRjAKaGVhZChkZl9sb25nX3dpdGhfY29lZl9GMCkKYGBgCgojIyAyLjIuIE5vcm1hbGl6YXRpb24gb2YgKipGMSoqIGJhc2VkIG9uIHJlZ3Jlc3Npb24gYXBwcm9hY2ggZnJvbSBCYXJyZWRhIGFuZCBOZWFyZXkgKDIwMTgpIGFwcGxpZWQgdG8gTG9iYW5vdidzICgxOTcxKSBOb3JtYWxpemF0aW9uIHRlY2huaXF1ZQoKIyMjIDIuMi4xLiBEYXRhIHByZXByb2Nlc3NpbmcKIlRvIGltcGxlbWVudCB0aGlzIGFuYWx5c2lzIGluIFIsIGl0IGlzIGZpcnN0IGFzc3VtZWQgdGhhdCB0aGUgZGF0YSBhcmUgYXZhaWxhYmxlIGluIGEgZGF0YSBmcmFtZSBvYmplY3QgaW4gYSDigJxsb25n4oCdIGZvcm1hdCB3aXRoIG9ubHkgb25lIGxvZy1mb3JtYW50IG1lYXN1cmVtZW50IHBlciByb3cuIEZ1cnRoZXIsIGl0IGlzIGFzc3VtZWQgdGhhdCBlYWNoIHJvdyBvZiB0aGUgZGF0YSBmcmFtZSBoYXMgKGF0IGxlYXN0KSBmb3VyIGNvbHVtbnMsIGxhYmVsZWQ6IEcgZm9yIHRoZSBzaW5nbGUgZm9ybWFudCBtZWFzdXJlbWVudCwgViBpbmRpY2F0aW5nIHZvd2VsLCBLIGluZGljYXRpbmcgZm9ybWFudCBudW1iZXIsIGFuZCBTIGluZGljYXRpbmcgdGhlIHNwZWFrZXIgWy4uLl1hbiBhZGRpdGlvbmFsIHZhcmlhYmxlIChOKSBtYXkgYmUgY3JlYXRlZCB0byByZXByZXNlbnQgdGhlIE52ayB0ZXJtcywgdXNpbmcgdGhlIFIgY29tbWFuZDogTiDCvCBmYWN0b3JbaW50ZXJhY3Rpb24gKFYsSyldLiIgKHAuNTA3KQoKYGBge3J9CiMgQ29udmVydCBmcm9tIHdpZGUgdG8gbG9uZ19GMSBmb3JtYXQKZGZfbG9uZ19GMSA8LSBkZiAlPiUgICMgQ3JlYXRlIGEgbmV3IGRhdGEgZnJhbWUgYnkgdHJhbnNmb3JtaW5nIHRoZSBleGlzdGluZyBvbmUKICBzZWxlY3QoaXRlbSwgQ0hJTEQsIEFHRSwgSURfdndsLCBwaG9fdndsX251Y2wsIEYxKSAlPiUgICMgU2VsZWN0IHNwZWNpZmljIGNvbHVtbnMgZnJvbSB0aGUgb3JpZ2luYWwgZGF0YSBmcmFtZQogIGdhdGhlcihrZXkgPSAiRnJlcXVlbmN5IiwgdmFsdWUgPSAiVmFsdWUiLCBGMSkgICMgUmVzaGFwZSB0aGUgZGF0YSBmcm9tIHdpZGUgdG8gbG9uZ19GMSBmb3JtYXQsIGNvbWJpbmluZyBGMSBhbmQgRjEgY29sdW1ucyBpbnRvIGtleS12YWx1ZSBwYWlycyAKCmRmX2xvbmdfRjEkRyA8LSBkZl9sb25nX0YxJFZhbHVlICAjIGFzc2lnbiBWYWx1ZSB0byAnRycKZGZfbG9uZ19GMSRTIDwtIGFzLmZhY3RvcihkZl9sb25nX0YxJGl0ZW0pICAjIENvbnZlcnQgdGhlICdpdGVtJyAoPXJlY29yZGluZyBzZXNzaW9uKSBjb2x1bW4gdG8gYSBmYWN0b3IgYW5kIGFzc2lnbiBpdCB0byAnUycKZGZfbG9uZ19GMSRWIDwtIGFzLmZhY3RvcihkZl9sb25nX0YxJHBob192d2xfbnVjbCkgICMgQ29udmVydCB0aGUgJ3Bob192d2xfbnVjbCcgY29sdW1uIHRvIGEgZmFjdG9yIGFuZCBhc3NpZ24gaXQgdG8gJ1YnCmBgYAoKIyMjIDIuMi4yLiBSZWdyZXNzaW9uCgpDb25zaWRlcmluZyB0aGUgYW50aWNpcGF0ZWQgdmFyaWFiaWxpdHkgaW4gaG93IGRpZmZlcmVudCB2b3dlbCB0eXBlcyBhZmZlY3QgRjAgYW5kIEYxIGZyZXF1ZW5jaWVzIGFjcm9zcyBzcGVha2Vycywgd2hpY2ggd2FzIG5vdCBhZGRyZXNzZWQgaW4gQmFycmVkYSdzIHN0dWR5LCB3ZSBmaW5kIGl0IGltcGVyYXRpdmUgdG8gaW5jb3Jwb3JhdGUgaW50ZXJhY3Rpb25zLgoKYGBge3J9Ck1fRjEgPSBsbShkYXRhID0gZGZfbG9uZ19GMSwKICAgICAgIGZvcm11bGEgPSBHIH4gMCArIFMgKiBWLCBjb250cmFzdHMgPSBsaXN0KFY9Y29udHIuc3VtKSkKCnNhdmVSRFMoTV9GMSwgIn4vRG9jdW1lbnRzL1Jlc2VhcmNoL0NvZGUvRjFfRjBfY3VlX3dlaWdodGluZy9WRi9NRjEucmRzIikKYGBgCgojIyMgMi4yLjMuIENvZWZmaWNpZW50cyBleHRyYWN0aW9uCgpgYGB7cn0KIyBFeHRyYWN0IGNvZWZmaWNpZW50cyBmb3IgRjEgZm9yIGVhY2ggc3BlYWtlcgpDb2VmZmljaWVudHNfRjEgPC0gc3VtbWFyeShNX0YxKSRjb2VmZmljaWVudHMgJT4lCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgQ29udmVydCBjb2VmZmljaWVudHMgdG8gZGF0YSBmcmFtZQogIGZpbHRlcihncmVwbCgiXlMiLCByb3duYW1lcyguKSkpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAjIEZpbHRlciByb3dzIHdpdGggc3BlYWtlciBJRHMKICByZW5hbWUoU3BlYWtlcl9Fc3RpbWF0ZV9GMSA9IEVzdGltYXRlLCBTcGVha2VyX1N0ZF9FcnJvcl9GMSA9IGBTdGQuIEVycm9yYCkgJT4lICAjIFJlbmFtZSBjb2x1bW5zCiAgbXV0YXRlKGl0ZW0gPSBzdWIoIl5TIiwgIiIsIHJvd25hbWVzKC4pKSkgJT4lICAgICAgICAgICAgICAgICMgRXh0cmFjdCBzcGVha2VyIElEcwogIGZpbHRlcighZ3JlcGwoIjoiLCBpdGVtKSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIEV4Y2x1ZGUgcm93cyB3aXRoICI6IiBpbiBzcGVha2VyIElEcwoKIyBMZWZ0IGpvaW4gQ29lZmZpY2llbnRzX0YxIHdpdGggZGZfbG9uZ19GMSBieSB0aGUgJ2l0ZW0nIGNvbHVtbgpkZl9sb25nX3dpdGhfY29lZl9GMSA8LSBsZWZ0X2pvaW4oZGZfbG9uZ19GMSwgQ29lZmZpY2llbnRzX0YxLCBieSA9ICJpdGVtIikKCiMgQ2FsY3VsYXRlIEYxIHJlZ3Jlc3Npb24gTm9ybWFsaXplZCB2YWx1ZXMKZGZfbG9uZ193aXRoX2NvZWZfRjEgPC0gZGZfbG9uZ193aXRoX2NvZWZfRjEgJT4lCiAgZ3JvdXBfYnkoaXRlbSkgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgR3JvdXAgYnkgc3BlYWtlciBJRHMKICBtdXRhdGUoRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkID0gKFZhbHVlIC0gU3BlYWtlcl9Fc3RpbWF0ZV9GMSkgLyAoU3BlYWtlcl9TdGRfRXJyb3JfRjEgKiBzcXJ0KG4oKSkpKSAgIyBDYWxjdWxhdGUgTm9ybWFsaXplZCB2YWx1ZXMKCiMgUHJpbnQgaGVhZCBvZiBkZl9sb25nX3dpdGhfY29lZl9GMQpoZWFkKGRmX2xvbmdfd2l0aF9jb2VmX0YxKQpgYGAKCiMjIDIuMyBHYXRoZXIgTm9ybWFsaXphdGlvbiBvZiBGMCBhbmQgRjEgCmBgYHtyfQojIExlZnQgam9pbiBkZl9sb25nX3dpdGhfY29lZl9GMCB3aXRoIGRmX2xvbmdfd2l0aF9jb2VmX0YxIGJ5IHRoZSAnSURfdndsJyBjb2x1bW4KZGZfd2l0aF9jb2VmX0YwX0YxX2xleCA8LSBsZWZ0X2pvaW4oZGZfbG9uZ193aXRoX2NvZWZfRjAsIGRmX2xvbmdfd2l0aF9jb2VmX0YxLCBieSA9ICJJRF92d2wiKSAlPiUgCiAgcmVuYW1lKGl0ZW0gPSBpdGVtLngpICAjIFJlbmFtZSB0aGUgJ2l0ZW0nIGNvbHVtbgoKIyBEZWZpbmUgdGhlIGluZGljZXMgb2YgdGhlIGNvbHVtbnMgdG8ga2VlcApjb2xzX3RvX2tlZXAgPC0gYygxLCAyLCAzLCA0LCA1LCAxNSwgMjksIDcsIDIxKQoKIyBFeHRyYWN0IHRoZSBkZXNpcmVkIGNvbHVtbnMgZnJvbSB0aGUgZGF0YWZyYW1lCmRmX3dpdGhfY29lZl9GMF9GMV9sZXggPC0gZGZfd2l0aF9jb2VmX0YwX0YxX2xleFssIGNvbHNfdG9fa2VlcF0KCiMgUmVtb3ZlIHRoZSBzdWZmaXggIi54IiBmcm9tIHRoZSBjb2x1bW4gbmFtZXMgd2hlbiBuZWVkZWQKY29sbmFtZXMoZGZfd2l0aF9jb2VmX0YwX0YxX2xleCkgPC0gZ3N1YigiXFwueCQiLCAiIiwgY29sbmFtZXMoZGZfd2l0aF9jb2VmX0YwX0YxX2xleCkpCgpkZl93aXRoX2NvZWZfRjBfRjFfbGV4JEYwIDwtIGRmX3dpdGhfY29lZl9GMF9GMV9sZXgkVmFsdWUKZGZfd2l0aF9jb2VmX0YwX0YxX2xleCRGMSA8LSBkZl93aXRoX2NvZWZfRjBfRjFfbGV4JFZhbHVlLnkKCmRmX3dpdGhfY29lZl9GMF9GMV9sZXggPC0gZGZfd2l0aF9jb2VmX0YwX0YxX2xleCAlPiUgCiAgc2VsZWN0KC1jKFZhbHVlLCBWYWx1ZS55KSkKCmhlYWQoZGZfd2l0aF9jb2VmX0YwX0YxX2xleCkKYGBgCgoKCiMjIDIuNC4gU2VsZWN0aW9uIG9mIHJlbGV2YW50IGl0ZW1zCgpgYGB7cn0KZGZfY29tYmluZWQ8LSBkZl93aXRoX2NvZWZfRjBfRjFfbGV4ICU+JSAKICBtdXRhdGUoaGd0ID0gY2FzZV93aGVuKAogICAgcGhvX3Z3bF9udWNsICVpbiUgYygnQScsICdhJykgfiAnbG93JywKICAgIHBob192d2xfbnVjbCAlaW4lIGMoJ3UnLCAnPCcsICdpJykgfiAnaGlnaCcsCiAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXyAgIyBIYW5kbGUgb3RoZXIgY2FzZXMgaWYgbmVlZGVkCiAgKSkgICU+JSAKICBmaWx0ZXIoaXMubmEoaGd0KT09RikgJT4lIAogIHNlbGVjdChJRF92d2wsIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCwgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkLCBwaG9fdndsX251Y2wsIGhndCwgQ0hJTEQsIGl0ZW0sIEYwLCBGMSkKYGBgCgojIyAyLjUuIFByZXBhcmF0aW9uIGRmIGZvciBhbmFseXNpcwpgYGB7cn0KIyBDb252ZXJ0aW5nICdoZ3QnIHRvIGEgZmFjdG9yCmRmX2NvbWJpbmVkJGhndCA8LSBhcy5mYWN0b3IoZGZfY29tYmluZWQkaGd0KQoKIyBDYXRlZ29yaXppbmcgJ2ZydCcgYmFzZWQgb24gJ3Bob192d2xfbnVjbCcKZGZfY29tYmluZWQkZnJ0W2RmX2NvbWJpbmVkJHBob192d2xfbnVjbCAlaW4lIGMoIkEiLCAidSIsICI8IildIDwtICJiY2siCmRmX2NvbWJpbmVkJGZydFtkZl9jb21iaW5lZCRwaG9fdndsX251Y2wgJWluJSBjKCJpIiwgImEiKV0gPC0gImZydCIKCiMgTWVyZ2luZyBzdXBwbGVtZW50YXJ5IGRhdGEgd2l0aCBtYWluIGRhdGEgYW5kIGZpbHRlcmluZyBiYXNlZCBvbiBhIGNvbmRpdGlvbgpkZl9jb21iaW5lZCA8LSBsZWZ0X2pvaW4oZGZfY29tYmluZWQsIGN1bXZvYy55X0FMTEVfTkgsIGJ5ID0gIml0ZW0iKSAKZGZfY29tYmluZWQgPC0gZGZfY29tYmluZWQgJT4lIAogIGZpbHRlcihgQ3VtIHZvY2AgPiAwKQoKIyBDYWxjdWxhdGluZyB0aGUgbG9nYXJpdGhtIG9mICdjdW12b2MueScKZGZfY29tYmluZWQkbG9nX2N1bSA8LSBsb2coZGZfY29tYmluZWQkYEN1bSB2b2NgKQoKIyBGaW5hbCBkYXRhZnJhbWUgZm9yIGFuYWx5c2lzCmRmIDwtIGRmX2NvbWJpbmVkICU+JSAKICBtdXRhdGUoaGd0ID0gYXMuZmFjdG9yKGhndCksCiAgICAgICAgIENISUxEID0gYXMuZmFjdG9yKENISUxEKSwKICAgICAgICAgaXRlbSA9IGFzLmZhY3RvcihpdGVtKSwKICAgICAgICAgZnJ0ID0gYXMuZmFjdG9yKGZydCkpCgogCiMgQXBwbHkgZGV2aWF0aW9uIChzdW0pIGNvbnRyYXN0cyB0byAnaGd0JyBhbmQgJ2ZydCcKIyBUaGlzIGNvZGVzIGVhY2ggbGV2ZWwgcmVsYXRpdmUgdG8gdGhlIG92ZXJhbGwgbWVhbiBvZiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlCmRmJGhndCA8LSBmYWN0b3IoZGYkaGd0LCBsZXZlbHMgPSBjKCJsb3ciLCAiaGlnaCIpKSAgIyBFbnN1cmUgJ2hndCcgaXMgYSBmYWN0b3Igd2l0aCBzcGVjaWZpZWQgbGV2ZWxzCmNvbnRyYXN0cyhkZiRoZ3QpIDwtIGNvbnRyLnN1bShsZXZlbHMoZGYkaGd0KSkgICMgQXBwbHkgY29udHIuc3VtIHRvICdoZ3QnCmNvbnRyYXN0cyhkZiRmcnQpIDwtIGNvbnRyLnN1bShsZXZlbHMoZGYkZnJ0KSkgICMgQXBwbHkgY29udHIuc3VtIHRvICdmcnQnCmBgYAoKIyAzLiBEYXRhIGFuYWx5c2lzIPCfp64KCiMjIDMuMS4gRGVzY3JpcHRpdmUgU3RhdGlzdGljcyAKCmBgYHtyfQojIENhbGN1bGF0ZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgRjEgZm9yIGVhY2ggcGhvX3Z3bF9udWNsIGNhdGVnb3J5IChOb3JtYWxpemVkKQpkZl9kZXNjciA8LSBkZiAlPiUgCiAgZ3JvdXBfYnkoaGd0KSAlPiUgICAjIEdyb3VwIGJ5IHBob192d2xfbnVjbCBjYXRlZ29yeQogIG11dGF0ZShGMV9GMF9IeiA9IEYxLUYwLAogICAgICAgICBGMV9GMF9Ob3JtYWxpemVkID0gRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkLUYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCkgJT4lIAogIHN1bW1hcmlzZSgKICAgIG1fRjFfSHogPSByb3VuZChtZWFuKEYxKSwgMiksICAgICAgICAgICAgICMgTWVhbiBGMSAoSHopCiAgICBzZF9GMV9IeiA9IHJvdW5kKHNkKEYxKSwgMiksICAgICAgICAgICAgICAgIyBTdGFuZGFyZCBkZXZpYXRpb24gb2YgRjEgKEh6KQogICAgbV9GMF9IeiA9IHJvdW5kKG1lYW4oRjApLCAyKSwgICAgICAgICAgICAgICAgIyBNZWFuIEYwIChIeikKICAgIHNkX0YwX0h6ID0gcm91bmQoc2QoRjApLCAyKSwgICAgICAgICAgICAgICAgICMgU3RhbmRhcmQgZGV2aWF0aW9uIG9mIEYwIChIeikKICAgIG1fRjFfRjBfSHogPSByb3VuZChtZWFuKEYxX0YwX0h6KSwgMiksICAgICAgICAgICMgTWVhbiBGMS1GMCBkaWZmZXJlbmNlIChIeikKICAgIHNkX0YxX0YwX0h6ID0gcm91bmQoc2QoRjFfRjBfSHopLCAyKSwgICAgICAgICAgICMgU3RhbmRhcmQgZGV2aWF0aW9uIG9mIEYxLUYwIGRpZmZlcmVuY2UgKEh6KQogICAgbV9GMV9Ob3JtYWxpemVkID0gcm91bmQobWVhbihGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQpLCAyKSwgICAgICMgTWVhbiBGMSAoTm9ybWFsaXplZCkKICAgIHNkX0YxX05vcm1hbGl6ZWQgPSByb3VuZChzZChGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQpLCAyKSwgICAgICAgIyBTdGFuZGFyZCBkZXZpYXRpb24gb2YgRjEgKE5vcm1hbGl6ZWQpCiAgICBtX0YwX05vcm1hbGl6ZWQgPSByb3VuZChtZWFuKEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCksIDIpLCAgICAgICAjIE1lYW4gRjAgKE5vcm1hbGl6ZWQpCiAgICBzZF9GMF9Ob3JtYWxpemVkID0gcm91bmQoc2QoRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKSwgMiksICAgICAgICMgU3RhbmRhcmQgZGV2aWF0aW9uIG9mIEYwIChOb3JtYWxpemVkKQogICAgbV9GMV9GMF9Ob3JtYWxpemVkID0gcm91bmQobWVhbihGMV9GMF9Ob3JtYWxpemVkKSwgMiksICAgICAgICAgICAjIE1lYW4gRjEtRjAgZGlmZmVyZW5jZSAoTm9ybWFsaXplZCkKICAgIHNkX0YxX0YwX05vcm1hbGl6ZWQgPSByb3VuZChzZChGMV9GMF9Ob3JtYWxpemVkKSwgMikpICU+JSAgICAgICAjIFN0YW5kYXJkIGRldmlhdGlvbiBvZiBGMS1GMCBkaWZmZXJlbmNlIChOb3JtYWxpemVkKQogIGZpbHRlcighaXMubmEoaGd0KSkgICAjIFJlbW92ZSByb3dzIHdoZXJlIGhndCBpcyBOQQoKcHJpbnQoZGZfZGVzY3IpCgpkZl9kZXNjcl9waG9uIDwtIGRmICU+JSAKICBncm91cF9ieSggQ0hJTEQsIHBob192d2xfbnVjbCkgJT4lIAogIHN1bW1hcmlzZShjb3VudHMgPSBuKCkpCgpwcmludChkZl9kZXNjcl9waG9uKQoKZGZfZGVzY3JfcGhvbl9hdmcgPC0gZGYgJT4lIAogIGdyb3VwX2J5KCBDSElMRCwgcGhvX3Z3bF9udWNsKSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50cyA9IG4oKSkgJT4lIAogIGdyb3VwX2J5KHBob192d2xfbnVjbCkgJT4lCiAgc3VtbWFyaXNlKG1fY291bnRzPW1lYW4oY291bnRzKSwKICAgICAgICAgICBzZD1zZChjb3VudHMpKQoKcHJpbnQoZGZfZGVzY3JfcGhvbl9hdmcpCgpgYGAKCgojIyAzLjEuMi4gR3JhcGhzIGV4cGVyaW1lbnRhbCBkYXRhCgpgYGB7cn0KIyB2b3dlbCBkaXN0cmlidXRpb24gcGVyIGNoaWxkIHBsb3QKZGZfZGVzY3JfcGhvbiRwaG9fdndsX251Y2wgPC0gZmFjdG9yKAogIGRmX2Rlc2NyX3Bob24kcGhvX3Z3bF9udWNsLAogIGxldmVscyA9IGMoImkiLCAidSIsICJhIiwgIkEiKQopCgpkZl9kZXNjcl9waG9uIDwtIGRmX2Rlc2NyX3Bob24gJT4lCiAgdW5ncm91cCgpICU+JSAgIAogIG11dGF0ZSgKICAgIENISUxEX2Fub24gPSBmYWN0b3IoCiAgICAgIENISUxELAogICAgICBsYWJlbHMgPSBwYXN0ZTAoIklEIiwgIHNlcV9hbG9uZyhsZXZlbHMoQ0hJTEQpKSkKICAgICkKICApCgpjaGlsZF9rZXkgPC0gZGZfZGVzY3JfcGhvbiAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZGlzdGluY3QoQ0hJTEQpICU+JQogIGFycmFuZ2UoQ0hJTEQpICU+JSAgICMgb3B0aW9uYWw6IGFscGhhYmV0aWMgb3JkZXIKICBtdXRhdGUoCiAgICBDSElMRF9hbm9uID0gcGFzdGUwKCJJRCIsICBzZXFfYWxvbmcobGV2ZWxzKENISUxEKSkpCiAgKQoKY291bnQgPC0gZ2dwbG90KGRmX2Rlc2NyX3Bob24sCiAgICAgICBhZXMoeCA9IENISUxEX2Fub24sIHkgPSBjb3VudHMsCiAgICAgICAgICAgZmlsbCA9IHBob192d2xfbnVjbCwgY29sb3VyID0gcGhvX3Z3bF9udWNsKSkgKwogIGdlb21fY29sKGFscGhhID0gMC44NSkgKwogIGxhYnMoCiAgICB4ID0gIkNoaWxkIiwKICAgIHkgPSAiQ291bnQiLAogICAgZmlsbCA9ICJWb3dlbCIKICApICsKICBzY2FsZV9maWxsX21hbnVhbCgKICAgIHZhbHVlcyA9IGMoCiAgImkiID0gIiMxRjc3QjQiLCAgIyBibHVlCiAgInUiID0gIiMxN0JFQ0YiLCAgIyBjeWFuCiAgImEiID0gIiNGRjdGMEUiLCAgIyBvcmFuZ2UKICAiQSIgPSAiI0U0MUExQyIgICAjIHJlZAogICAgKSwKICAgIGxhYmVscyA9IGMoCiAgICAgICJpIiA9ICJbaV0iLAogICAgICAidSIgPSAiW3VdIiwKICAgICAgImEiID0gIlthXSIsCiAgICAgICJBIiA9ICJbyZFdIgogICAgKQogICkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKAogICJpIiA9ICIjMUY3N0I0IiwgICMgYmx1ZQogICJ1IiA9ICIjMTdCRUNGIiwgICMgY3lhbgogICJhIiA9ICIjRkY3RjBFIiwgICMgb3JhbmdlCiAgIkEiID0gIiNFNDFBMUMiICAgIyByZWQKICAgICksCiAgICBndWlkZSA9ICJub25lIiAgIAogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmV5ODUiKSwKYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgbGVnZW5kLnRleHQgID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNikKICApCgpjb3VudCAKZ2dzYXZlKGZpbGVuYW1lID0gIn4vRGVza3RvcC9pbWFnZV9lcHMuZXBzIiwgcGxvdCA9IGNvdW50LAogICAgICAgd2lkdGggPSAxNSwgaGVpZ2h0ID0gNiwgZHBpID0gMTAwMCkKYGBgCgoKYGBge3J9CiMgRjEgZGVuc2l0eSBwbG90CnAxIDwtIGdncGxvdChkYXRhID0gZGYpICsKICBnZW9tX2RlbnNpdHkoYWVzKHggPSBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQsIGZpbGwgPSBoZ3QpLCBhbHBoYSA9IDAuNSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImxvdyIgPSAiIzlGMzQwMCIsICJoaWdoIiA9ICIjRkZCRTlGIiksIG5hbWUgPSAiSGVpZ2h0IikgKwogIGxhYnMoeCA9ICJGMSBOb3JtYWxpemVkIiwgeSA9ICJEZW5zaXR5IikgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC0xLjIsIDEuMikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCkgICwgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkgICAgICAjIEluY3JlYXNlIGxlZ2VuZCB0aXRsZSBzaXplIChvcHRpb25hbCkKICApCiAgCgojIEYwIGRlbnNpdHkgcGxvdApwMiA8LSBnZ3Bsb3QoZGF0YSA9IGRmKSArCiAgZ2VvbV9kZW5zaXR5KGFlcyh4ID0gRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkLCBmaWxsID0gaGd0KSwgYWxwaGEgPSAwLjUpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJsb3ciID0gIiM1NzA5ODciLCAiaGlnaCIgPSAiI0QzOTdGOCIpLCBuYW1lID0gIkhlaWdodCIpICsKICBsYWJzKHggPSAiRjAgTm9ybWFsaXplZCIsIHkgPSAiRGVuc2l0eSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMS4yLCAxLjIpKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSgKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCAgIyBQb3NpdGlvbiB0aGUgbGVnZW5kIG9uIHRoZSByaWdodCBzaWRlLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAKICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkgIAogICkKCiMgQ29tYmluZSB3aXRoIHNoYXJlZCBsZWdlbmQKY29tYmluZWRfcGxvdHMgPC0gKHAxICsgcDIpICsKIHBsb3RfbGF5b3V0KGd1aWRlcyA9ICJjb2xsZWN0IikgJgogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKY29tYmluZWRfcGxvdHMKCmdnc2F2ZShmaWxlbmFtZSA9ICJ+L0Rlc2t0b3AvaW1hZ2VfZXBzLmVwcyIsIHBsb3QgPSBjb21iaW5lZF9wbG90cywKICAgICAgIHdpZHRoID0gMTAsIGhlaWdodCA9IDYsIGRwaSA9IDEwMDApCmBgYAoKCmBgYHtyfQpkZiRwaG9fdndsX251Y2wgPC0gZmFjdG9yKAogIGRmJHBob192d2xfbnVjbCwKICBsZXZlbHMgPSBjKCJpIiwgInUiLCAiYSIsICJBIikKKQoKZjBfcmF3IDwtIGdncGxvdChkZiwgYWVzKHggPSBsb2dfY3VtLCB5ID0gRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkLCBncm91cCA9IHBob192d2xfbnVjbCkpICsKICAKICAjIFJpYmJvbiBsYXllciAobGVnZW5kIHNob3dzIG9ubHkgZmlsbCkKICBnZW9tX3Ntb290aCgKICAgIGFlcyhmaWxsID0gcGhvX3Z3bF9udWNsKSwKICAgIG1ldGhvZCA9ICJsb2VzcyIsCiAgICBsaW5ld2lkdGggPSAxLjIsCiAgICBjb2xvciA9IE5BLCAgICAgICAgICAgICMgbm8gbGluZSBpbiB0aGlzIGxheWVyCiAgICBzaG93LmxlZ2VuZCA9IFRSVUUKICApICsKICAKICAjIExpbmUgbGF5ZXIgKG5vIGxlZ2VuZCkKICBnZW9tX3Ntb290aCgKICAgIGFlcyhjb2xvciA9IHBob192d2xfbnVjbCksCiAgICBtZXRob2QgPSAibG9lc3MiLAogICAgbGluZXdpZHRoID0gMS4yLAogICAgZmlsbCA9IE5BLCAgICAgICAgICAgICAjIGRvbid0IGZpbGwgdGhpcyBsYXllcgogICAgc2hvdy5sZWdlbmQgPSBGQUxTRQogICkgKwogIAogICMgRmlsbCBzY2FsZSBjb250cm9scyB0aGUgbGVnZW5kCiAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICBuYW1lID0gIlZvd2VsIiwgICAgICAgICMgPC0gbGVnZW5kIHRpdGxlCiAgICB2YWx1ZXMgPSBjKAogICJpIiA9ICIjMUY3N0I0IiwgICMgYmx1ZQogICJ1IiA9ICIjMTdCRUNGIiwgICMgY3lhbgogICJhIiA9ICIjRkY3RjBFIiwgICMgb3JhbmdlCiAgIkEiID0gIiNFNDFBMUMiICAgIyByZWQKICAgICksCiAgICBsYWJlbHMgPSBjKAogICAgICAiaSIgPSAiW2ldIiwKICAgICAgInUiID0gIlt1XSIsCiAgICAgICJhIiA9ICJbYV0iLAogICAgICAiQSIgPSAiW8mRXSIKICAgICkKICApICsKICAKICBzY2FsZV9jb2xvcl9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKAogICJpIiA9ICIjMUY3N0I0IiwgICMgYmx1ZQogICJ1IiA9ICIjMTdCRUNGIiwgICMgY3lhbgogICJhIiA9ICIjRkY3RjBFIiwgICMgb3JhbmdlCiAgIkEiID0gIiNFNDFBMUMiICAgIyByZWQKICAgICksCiAgICBndWlkZSA9ICJub25lIiAgICAgICAgICAgIyBoaWRlIHRoZSBjb2xvciBsZWdlbmQKICApICsKICAKICAjIEF4aXMgbGFiZWxzCiAgbGFicygKICAgIHggPSAibG9nKGN1bXVsYXRpdmUgdm9jYWJ1bGFyeSkiLAogICAgeSA9ICJOb3JtYWxpemVkIEYwIgogICkgKwogIAogIHlsaW0oLTEsIDEpICsKICB0aGVtZV9jb3dwbG90KCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwgICMgYmlnZ2VyIGxlZ2VuZCB0aXRsZQogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCmYwX3JhdwpnZ3NhdmUoZmlsZW5hbWUgPSAifi9EZXNrdG9wL2YwX3Jhd19lcHMuZXBzIiwgcGxvdCA9IGYwX3JhdywKICAgICAgIHdpZHRoID0gNiwgaGVpZ2h0ID0gNiwgZHBpID0gMTAwMCkKYGBgCgoKYGBge3J9CmRmJHBob192d2xfbnVjbCA8LSBmYWN0b3IoCiAgZGYkcGhvX3Z3bF9udWNsLAogIGxldmVscyA9IGMoImkiLCAidSIsICJhIiwgIkEiKQopCgpmMV9yYXcgPC0gZ2dwbG90KGRmLCBhZXMoeCA9IGxvZ19jdW0sIHkgPSBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQsIGdyb3VwID0gcGhvX3Z3bF9udWNsKSkgKwogIAogICMgUmliYm9uIGxheWVyIChsZWdlbmQgc2hvd3Mgb25seSBmaWxsKQogIGdlb21fc21vb3RoKAogICAgYWVzKGZpbGwgPSBwaG9fdndsX251Y2wpLAogICAgbWV0aG9kID0gImxvZXNzIiwKICAgIGxpbmV3aWR0aCA9IDEuMiwKICAgIGNvbG9yID0gTkEsICAgICAgICAgICAgIyBubyBsaW5lIGluIHRoaXMgbGF5ZXIKICAgIHNob3cubGVnZW5kID0gVFJVRQogICkgKwogIAogICMgTGluZSBsYXllciAobm8gbGVnZW5kKQogIGdlb21fc21vb3RoKAogICAgYWVzKGNvbG9yID0gcGhvX3Z3bF9udWNsKSwKICAgIG1ldGhvZCA9ICJsb2VzcyIsCiAgICBsaW5ld2lkdGggPSAxLjIsCiAgICBmaWxsID0gTkEsICAgICAgICAgICAgICMgZG9uJ3QgZmlsbCB0aGlzIGxheWVyCiAgICBzaG93LmxlZ2VuZCA9IEZBTFNFCiAgKSArCiAgCiAgIyBGaWxsIHNjYWxlIGNvbnRyb2xzIHRoZSBsZWdlbmQKICBzY2FsZV9maWxsX21hbnVhbCgKICAgIG5hbWUgPSAiVm93ZWwiLCAgICAgICAgIyA8LSBsZWdlbmQgdGl0bGUKICAgIHZhbHVlcyA9IGMoCiAgImkiID0gIiMxRjc3QjQiLCAgIyBibHVlCiAgInUiID0gIiMxN0JFQ0YiLCAgIyBjeWFuCiAgImEiID0gIiNGRjdGMEUiLCAgIyBvcmFuZ2UKICAiQSIgPSAiI0U0MUExQyIgICAjIHJlZAogICAgKSwKICAgIGxhYmVscyA9IGMoCiAgICAgICJpIiA9ICJbaV0iLAogICAgICAidSIgPSAiW3VdIiwKICAgICAgImEiID0gIlthXSIsCiAgICAgICJBIiA9ICJbyZFdIgogICAgKQogICkgKwogIAogIHNjYWxlX2NvbG9yX21hbnVhbCgKICAgIHZhbHVlcyA9IGMoCiAgImkiID0gIiMxRjc3QjQiLCAgIyBibHVlCiAgInUiID0gIiMxN0JFQ0YiLCAgIyBjeWFuCiAgImEiID0gIiNGRjdGMEUiLCAgIyBvcmFuZ2UKICAiQSIgPSAiI0U0MUExQyIgICAjIHJlZAogICAgKSwKICAgIGd1aWRlID0gIm5vbmUiICAgICAgICAgICAjIGhpZGUgdGhlIGNvbG9yIGxlZ2VuZAogICkgKwogIAogICMgQXhpcyBsYWJlbHMKICBsYWJzKAogICAgeCA9ICJsb2coY3VtdWxhdGl2ZSB2b2NhYnVsYXJ5KSIsCiAgICB5ID0gIk5vcm1hbGl6ZWQgRjEiCiAgKSArCiAgCiAgeWxpbSgtMSwgMSkgKwogIHRoZW1lX2Nvd3Bsb3QoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLCAgIyBiaWdnZXIgbGVnZW5kIHRpdGxlCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpCiAgKQoKZjFfcmF3CgpnZ3NhdmUoZmlsZW5hbWUgPSAifi9EZXNrdG9wL2YxX3Jhdy5lcHMiLCBwbG90ID0gZjFfcmF3LAogICAgICAgd2lkdGggPSA2LCBoZWlnaHQgPSA2LCBkcGkgPSAxMDAwKQpgYGAKCiMjIDMuMi4gTUxNIE1vZGVsbGluZwoKIyMjIDMuMi4xLiBNb2RlbCAxOiBCYXNlIG1vZGVsCmBgYHtyfQptMSA8LSBnbG1lcihkYXRhPSBkZiwgCiAgICAgICAgICAgIGZvcm11bGEgPSBoZ3QgfiAxKyAKICAgICAgICAgICAgICAoMXxDSElMRCksICBmYW1pbHk9ICJiaW5vbWlhbCIobGluayA9ICJsb2dpdCIpLAogICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLCBvcHRDdHJsID0gbGlzdChtYXhmdW4gPSAyMDAwMDAwKSkpCnNhdmVSRFMobTEsIGZpbGUgPSAibTEucmRzIikKYGBgCgojIyMgMy4yLjIuIE1vZGVsIDI6IEZpeGVkIGVmZmVjdCBvZiBjdW11bGF0aXZlIHZvY2FidWxhcnkKYGBge3J9Cm0yIDwtIGdsbWVyKGRhdGEgPSBkZiwgCiAgICAgICAgICAgIGZvcm11bGEgPSBoZ3QgfiBsb2dfY3VtICsgCiAgICAgICAgICAgICAgKDF8Q0hJTEQpLCAgZmFtaWx5ID0gImJpbm9taWFsIihsaW5rID0gImxvZ2l0IiksCiAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsIG9wdEN0cmwgPSBsaXN0KG1heGZ1biA9IDIwMDAwMDApKSkKc2F2ZVJEUyhtMiwgZmlsZSA9ICJtMi5yZHMiKQoKYXMuZGF0YS5mcmFtZShhbm92YShtMSxtMikpCmBgYArinqHvuI8gQmV0dGVyIGRhdGFmaXQgd2l0aCBtMgoKIyMjIDMuMi4zLiBNb2RlbCAzOiBSYW5kb20gZWZmZWN0IG9mIGN1bXVsYXRpdmUgdm9jYWJ1bGFyeQpgYGB7cn0KbTMgPC0gZ2xtZXIoZGF0YSA9IGRmLCAKICAgICAgICAgICAgZm9ybXVsYSA9IGhndCB+IGxvZ19jdW0gKyAKICAgICAgICAgICAgICAoMSArIGxvZ19jdW0gfCBDSElMRCksICBmYW1pbHkgPSAiYmlub21pYWwiKGxpbmsgPSAibG9naXQiKSwKICAgICAgICAgICAgY29udHJvbCA9IGdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMjAwMDAwMCkpKQpzYXZlUkRTKG0zLCBmaWxlID0gIm0zLnJkcyIpCgphcy5kYXRhLmZyYW1lKGFub3ZhKG0yLG0zKSkKYGBgCuKeoe+4jyBCZXR0ZXIgZGF0YWZpdCB3aXRoIG0zCgojIyMgMy4yLjQuIE1vZGVsIDQ6IEZpeGVkIGVmZmVjdCBvZiBGMQpgYGB7cn0KbTQgPC0gZ2xtZXIoZGF0YSA9IGRmLCAKICAgICAgICAgICAgZm9ybXVsYSA9IGhndCB+IGxvZ19jdW0gKyAKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgKDEgKyBsb2dfY3VtIHwgQ0hJTEQpLCAgZmFtaWx5ID0gImJpbm9taWFsIihsaW5rID0gImxvZ2l0IiksCiAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsIG9wdEN0cmwgPSBsaXN0KG1heGZ1biA9IDIwMDAwMDApKSkKc2F2ZVJEUyhtNCwgZmlsZSA9ICJtNC5yZHMiKQoKYXMuZGF0YS5mcmFtZShhbm92YShtMyxtNCkpCmBgYArinqHvuI8gQmV0dGVyIGRhdGFmaXQgd2l0aCBtNAoKIyMjIDMuMi41LiBNb2RlbCA1OiBSYW5kb20gc2xvcGUgZWZmZWN0IG9mIEYxCmBgYHtyfQptNSA8LSBnbG1lcihkYXRhID0gZGYsIAogICAgICAgICAgICBmb3JtdWxhID0gaGd0IH4gbG9nX2N1bSArIAogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICAoMSArIGxvZ19jdW0gKyBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgfCBDSElMRCksICBmYW1pbHkgPSAiYmlub21pYWwiKGxpbmsgPSAibG9naXQiKSwKICAgICAgICAgICAgY29udHJvbCA9IGdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMjAwMDAwMCkpKQpzYXZlUkRTKG01LCBmaWxlID0gIm01LnJkcyIpCgphcy5kYXRhLmZyYW1lKGFub3ZhKG00LG01KSkKYGBgCuKeoe+4jyBCZXR0ZXIgZGF0YWZpdCB3aXRoIG01CgojIyMgMy4yLjYuIE1vZGVsIDY6IEZpeGVkIGVmZmVjdCBvZiBGMApgYGB7cn0KbTYgPC0gZ2xtZXIoZGF0YSA9IGRmLCAKICAgICAgICAgICAgZm9ybXVsYSA9IGhndCB+IGxvZ19jdW0gKyAKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgICgxICsgbG9nX2N1bSArIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCB8IENISUxEKSwgIGZhbWlseSA9ICJiaW5vbWlhbCIobGluayA9ICJsb2dpdCIpLAogICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLCBvcHRDdHJsID0gbGlzdChtYXhmdW4gPSAyMDAwMDAwKSkpCnNhdmVSRFMobTYsIGZpbGUgPSAibTYucmRzIikKCmFzLmRhdGEuZnJhbWUoYW5vdmEobTUsbTYpKQpgYGAK4p6h77iPIEJldHRlciBkYXRhZml0IHdpdGggbTYKCiMjIyAzLjIuNy4gTW9kZWwgNzogUmFuZG9tIHNsb3BlIGVmZmVjdCBvZiBGMApgYGB7cn0KbTcgPC0gZ2xtZXIoZGF0YSA9IGRmLCAKICAgICAgICAgICAgZm9ybXVsYSA9IGhndCB+IGxvZ19jdW0gKyAKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgICgxICsgbG9nX2N1bSArIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCArIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCB8IENISUxEKSwgIGZhbWlseSA9ICJiaW5vbWlhbCIobGluayA9ICJsb2dpdCIpLAogICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLCBvcHRDdHJsID0gbGlzdChtYXhmdW4gPSAyMDAwMDAwKSkpCnNhdmVSRFMobTcsIGZpbGUgPSAibTcucmRzIikKCmFzLmRhdGEuZnJhbWUoYW5vdmEobTYsbTcpKQpgYGAK4p6h77iPIEJldHRlciBkYXRhZml0IHdpdGggbTcKCiMjIyAzLjIuOC4gTW9kZWwgODogRml4ZWQgZWZmZWN0IG9mIHBsYWNlIG9mIGFydGljdWxhdGlvbgpgYGB7cn0KbTggPC0gZ2xtZXIoZGF0YSA9IGRmLCAKICAgICAgICAgICAgZm9ybXVsYSA9IGhndCB+IGxvZ19jdW0gKyAKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgIGZydCArCiAgICAgICAgICAgICAgKDEgKyBsb2dfY3VtICsgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkICsgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkIHwgQ0hJTEQpLCAgZmFtaWx5ID0gImJpbm9taWFsIihsaW5rID0gImxvZ2l0IiksCiAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsIG9wdEN0cmwgPSBsaXN0KG1heGZ1biA9IDIwMDAwMDApKSkKc2F2ZVJEUyhtOCwgZmlsZSA9ICJtOC5yZHMiKQoKYXMuZGF0YS5mcmFtZShhbm92YShtNyxtOCkpCmBgYArinqHvuI8gQmV0dGVyIGRhdGFmaXQgd2l0aCBtOAoKIyMjIDMuMi45LiBNb2RlbCA5OiBSYW5kb20gc2xvcGUgZWZmZWN0IG9mIHBsYWNlIG9mIGFydGljdWxhdGlvbgpgYGB7cn0KbTkgPC0gZ2xtZXIoZGF0YSA9IGRmLCAKICAgICAgICAgICAgZm9ybXVsYSA9IGhndCB+IGxvZ19jdW0gKyAKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgIGZydCArCiAgICAgICAgICAgICAgKDEgKyBsb2dfY3VtICsgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkICsgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkICsgZnJ0IHwgQ0hJTEQpLCAgZmFtaWx5ID0gImJpbm9taWFsIihsaW5rID0gImxvZ2l0IiksCiAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsIG9wdEN0cmwgPSBsaXN0KG1heGZ1biA9IDIwMDAwMDApKSkKc2F2ZVJEUyhtOSwgZmlsZSA9ICJtOS5yZHMiKQoKYXMuZGF0YS5mcmFtZShhbm92YShtOCxtOSkpCmBgYArinqHvuI8gQmV0dGVyIGRhdGFmaXQgd2l0aCBtOQoKIyMjIDMuMi4xMC4gTW9kZWwgMTA6IEZpeGVkIHF1YWRyYXRpYyBlZmZlY3Qgb2YgY3VtdWxhdGl2ZSB2b2NhYnVsYXJ5IGludGVyYWN0aW9uCmBgYHtyfSAKbTEwIDwtIGdsbWVyKGRhdGEgPSBkZiwgCiAgICAgICAgICAgIGZvcm11bGEgPSBoZ3QgfiBsb2dfY3VtICsgCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICBmcnQgKwogICAgICAgICAgICAgIEkobG9nX2N1bV4yKSsgCiAgICAgICAgICAgICAgKDEgKyBsb2dfY3VtICsgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkICsgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkICsgZnJ0IHwgQ0hJTEQpLCAgZmFtaWx5ID0gImJpbm9taWFsIihsaW5rID0gImxvZ2l0IiksCiAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsIG9wdEN0cmwgPSBsaXN0KG1heGZ1biA9IDIwMDAwMDApKSkKc2F2ZVJEUyhtMTAsIGZpbGUgPSAibTEwLnJkcyIpCgphcy5kYXRhLmZyYW1lKGFub3ZhKG05LG0xMCkpCmBgYArinYwgTm8gYmV0dGVyIGRhdGFmaXQgd2l0aCBtMTAKCiMjIyAzLjIuMTEuIE1vZGVsIDExOiBGaXhlZCBlZmZlY3Qgb2YgRjAtRjEgaW50ZXJhY3Rpb24KYGBge3J9Cm0xMSA8LSBnbG1lcihkYXRhID0gZGYsIAogICAgICAgICAgICBmb3JtdWxhID0gaGd0IH4gbG9nX2N1bSArIAogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgZnJ0ICsKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgKDEgKyBsb2dfY3VtICsgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkICsgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkICsgZnJ0IHwgQ0hJTEQpLCAgZmFtaWx5ID0gImJpbm9taWFsIihsaW5rID0gImxvZ2l0IiksCiAgICAgICAgICAgIGNvbnRyb2wgPSBnbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsIG9wdEN0cmwgPSBsaXN0KG1heGZ1biA9IDIwMDAwMDApKSkKc2F2ZVJEUyhtMTEsIGZpbGUgPSAibTExLnJkcyIpCgoKYXMuZGF0YS5mcmFtZShhbm92YShtOSxtMTEpKQpgYGAK4p6h77iPIEJldHRlciBkYXRhZml0IHdpdGggbTExCgoKIyMjIDMuMi4xMi4gTW9kZWwgMTI6IEZpeGVkIGVmZmVjdCBvZiBwbGFjZSBvZiBhcnRpY3VsYXRpb24tRjEgaW50ZXJhY3Rpb24KYGBge3J9Cm0xMiA8LSBnbG1lcihkYXRhID0gZGYsIAogICAgICAgICAgICBmb3JtdWxhID0gaGd0IH4gbG9nX2N1bSArIAogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgZnJ0ICsKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogZnJ0ICsKICAgICAgICAgICAgICAoMSArIGxvZ19jdW0gKyBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgKyBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgKyBmcnQgfCBDSElMRCksICBmYW1pbHkgPSAiYmlub21pYWwiKGxpbmsgPSAibG9naXQiKSwKICAgICAgICAgICAgY29udHJvbCA9IGdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMjAwMDAwMCkpKQpzYXZlUkRTKG0xMiwgZmlsZSA9ICJtMTIucmRzIikKCmFzLmRhdGEuZnJhbWUoYW5vdmEobTExLG0xMikpCmBgYArinqHvuI8gQmV0dGVyIGRhdGFmaXQgd2l0aCBtMTIKCgojIyMgMy4yLjEzLiBNb2RlbCAxMzogRml4ZWQgZWZmZWN0IG9mIGN1bXVsYXRpdmUgdm9jYWJ1bGFyeS1GMSBpbnRlcmFjdGlvbgpgYGB7cn0KbTEzIDwtIGdsbWVyKGRhdGEgPSBkZiwgCiAgICAgICAgICAgIGZvcm11bGEgPSBoZ3QgfiBsb2dfY3VtICsgCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICBmcnQgKwogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA6IEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBmcnQgKwogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA6IGxvZ19jdW0gKwogICAgICAgICAgICAgICgxICsgbG9nX2N1bSArIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCArIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCArIGZydCB8IENISUxEKSwgIGZhbWlseSA9ICJiaW5vbWlhbCIobGluayA9ICJsb2dpdCIpLAogICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLCBvcHRDdHJsID0gbGlzdChtYXhmdW4gPSAyMDAwMDAwKSkpCnNhdmVSRFMobTEzLCBmaWxlID0gIm0xMy5yZHMiKQoKYXMuZGF0YS5mcmFtZShhbm92YShtMTIsbTEzKSkKYGBgCuKeoe+4jyBCZXR0ZXIgd2l0aCBtMTMKCgojIyMgMy4yLjE0LiBNb2RlbCAxNDogIEZpeGVkIGVmZmVjdCBvZiBGMC1wbGFjZSBvZiBhcnRpY3VsYXRpb24gaW50ZXJhY3Rpb24KYGBge3J9Cm0xNCA8LSBnbG1lcihkYXRhID0gZGYsIAogICAgICAgICAgICBmb3JtdWxhID0gaGd0IH4gbG9nX2N1bSArIAogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgZnJ0ICsKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogZnJ0ICsKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBsb2dfY3VtICsKICAgICAgICAgICAgICBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBmcnQgKwogICAgICAgICAgICAgICgxICsgbG9nX2N1bSArIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCArIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCArIGZydCB8IENISUxEKSwgIGZhbWlseSA9ICJiaW5vbWlhbCIobGluayA9ICJsb2dpdCIpLAogICAgICAgICAgICBjb250cm9sID0gZ2xtZXJDb250cm9sKG9wdGltaXplciA9ICJib2J5cWEiLCBvcHRDdHJsID0gbGlzdChtYXhmdW4gPSAyMDAwMDAwKSkpCnNhdmVSRFMobTE0LCBmaWxlID0gIm0xNC5yZHMiKQoKYXMuZGF0YS5mcmFtZShhbm92YShtMTMsbTE0KSkKYGBgCuKeoe+4jyBCZXR0ZXIgZGF0YWZpdCB3aXRoIG0xNAoKCiMjIyAzLjIuMTUuIE1vZGVsIDE1OiBGaXhlZCBlZmZlY3Qgb2YgY3VtdWxhdGl2ZSB2b2NhYnVsYXJ5LUYwIGludGVyYWN0aW9uCmBgYHtyfQptMTUgPC0gZ2xtZXIoZGF0YSA9IGRmLCAKICAgICAgICAgICAgZm9ybXVsYSA9IGhndCB+IGxvZ19jdW0gKyAKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgIGZydCArCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA6IGZydCArCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogbG9nX2N1bSArCiAgICAgICAgICAgICAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogZnJ0ICsKICAgICAgICAgICAgICBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBsb2dfY3VtICsKICAgICAgICAgICAgICAoMSArIGxvZ19jdW0gKyBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgKyBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgKyBmcnQgfCBDSElMRCksICBmYW1pbHkgPSAiYmlub21pYWwiKGxpbmsgPSAibG9naXQiKSwKICAgICAgICAgICAgY29udHJvbCA9IGdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMjAwMDAwMCkpKQpzYXZlUkRTKG0xNSwgZmlsZSA9ICJtMTUucmRzIikKCmFzLmRhdGEuZnJhbWUoYW5vdmEobTE0LG0xNSkpCmBgYArinqHvuI8gQmV0dGVyIGRhdGFmaXQgd2l0aCBtMTUKCiMjIyAzLjIuMTYuIE1vZGVsIDE2OiBGaXhlZCBlZmZlY3Qgb2YgY3VtdWxhdGl2ZSB2b2NhYnVsYXJ5LUYwLUYxIGludGVyYWN0aW9uCmBgYHtyfQptMTYgPC0gZ2xtZXIoZGF0YSA9IGRmLCAKICAgICAgICAgICAgZm9ybXVsYSA9IGhndCB+IGxvZ19jdW0gKyAKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQrCiAgICAgICAgICAgICAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgIGZydCArCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA6IGZydCArCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogbG9nX2N1bSArCiAgICAgICAgICAgICAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogZnJ0ICsKICAgICAgICAgICAgICBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBsb2dfY3VtICsKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBsb2dfY3VtICsKICAgICAgICAgICAgICAoMSArIGxvZ19jdW0gKyBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgKyBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgKyBmcnQgfCBDSElMRCksICBmYW1pbHkgPSAiYmlub21pYWwiKGxpbmsgPSAibG9naXQiKSwKICAgICAgICAgICAgY29udHJvbCA9IGdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMjAwMDAwMCkpKQpzYXZlUkRTKG0xNiwgZmlsZSA9ICJtMTYucmRzIikKCmFzLmRhdGEuZnJhbWUoYW5vdmEobTE1LG0xNikpCmBgYArinYwgTm8gYmV0dGVyIGRhdGFmaXQgd2l0aCBtMTYKCiMjIyAzLjIuMTcuIE1vZGVsIDE3OiBGaXhlZCBlZmZlY3Qgb2YgcGxhY2Ugb2YgYXJ0aWN1bGF0aW9uLUYwLUYxIGludGVyYWN0aW9uCmBgYHtyfSAKbTE3IDwtIGdsbWVyKGRhdGEgPSBkZiwgCiAgICAgICAgICAgIGZvcm11bGEgPSBoZ3QgfiBsb2dfY3VtICsgCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICBmcnQgKwogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA6IEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBmcnQgKwogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA6IGxvZ19jdW0gKwogICAgICAgICAgICAgIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA6IGZydCArCiAgICAgICAgICAgICAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogbG9nX2N1bSArCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogZnJ0ICsKICAgICAgICAgICAgICAoMSArIGxvZ19jdW0gKyBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgKyBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgKyBmcnQgfCBDSElMRCksICBmYW1pbHkgPSAiYmlub21pYWwiKGxpbmsgPSAibG9naXQiKSwKICAgICAgICAgICAgY29udHJvbCA9IGdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMjAwMDAwMCkpKQpzYXZlUkRTKG0xNywgZmlsZSA9ICJtMTcucmRzIikKCmFzLmRhdGEuZnJhbWUoYW5vdmEobTE1LG0xNykpCmBgYArinqHvuI8gQmV0dGVyIGRhdGFmaXQgd2l0aCBtMTcKCiMjIyAzLjIuMTguIE1vZGVsIDE4OiBGaXhlZCBlZmZlY3Qgb2YgY3VtdWxhdGl2ZSB2b2NhYnVsYXJ5LXBsYWNlIG9mIGFydGljdWxhdGlvbi1GMC1GMSBpbnRlcmFjdGlvbgpgYGB7cn0KbTE4IDwtIGdsbWVyKGRhdGEgPSBkZiwgCiAgICAgICAgICAgIGZvcm11bGEgPSBoZ3QgfiBsb2dfY3VtICsgCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkKwogICAgICAgICAgICAgIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICBmcnQgKwogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA6IEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCsKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBmcnQgKwogICAgICAgICAgICAgIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA6IGxvZ19jdW0gKwogICAgICAgICAgICAgIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA6IGZydCArCiAgICAgICAgICAgICAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogbG9nX2N1bSArCiAgICAgICAgICAgICAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkIDogZnJ0ICsKICAgICAgICAgICAgICBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgOiBmcnQgOiBsb2dfY3VtICsKICAgICAgICAgICAgICAoMSArIGxvZ19jdW0gKyBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgKyBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgKyBmcnQgfCBDSElMRCksICBmYW1pbHkgPSAiYmlub21pYWwiKGxpbmsgPSAibG9naXQiKSwKICAgICAgICAgICAgY29udHJvbCA9IGdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMjAwMDAwMCkpKQpzYXZlUkRTKG0xOCwgZmlsZSA9ICJtMTgucmRzIikKCmFzLmRhdGEuZnJhbWUoYW5vdmEobTE3LG0xOCkpCmBgYArinYwgTm8gYmV0dGVyIGRhdGFmaXQgd2l0aCBtMTgKCiMjIDMuMy4gRmluYWwgTW9kZWwg4pyFCmBgYHtyfQpmaW5hbF9tb2RlbCA8LSBtMTcKcHJpbnQoc3VtbWFyeShmaW5hbF9tb2RlbCkpCiMgQXNzdW1pbmcgZmluYWxfbW9kZWwgaXMgeW91ciBtaXhlZC1lZmZlY3RzIG1vZGVsCnN1bW1hcnlfZmluYWxfbW9kZWwgPC0gc3VtbWFyeShmaW5hbF9tb2RlbCkKCmZvcm11bGEgPC0gZmluYWxfbW9kZWxAY2FsbCRmb3JtdWxhCgojIEZpeGVkIGVmZmVjdHMgc3VtbWFyeQpwcmludChhcy5kYXRhLmZyYW1lKHJvdW5kKGNvZWYoc3VtbWFyeV9maW5hbF9tb2RlbCksMykpKQoKcHJpbnQoYXMuZGF0YS5mcmFtZShjb2VmKHN1bW1hcnlfZmluYWxfbW9kZWwpKSkKYGBgCgojIDQuIERhdGEgdml6YXVsaXphdGlvbiDwn5OKCgojIyA0LjAuIFJlZml0IG1vZGVsIHdpdGggY3VtLnZvYy4gY2VudHJlZCBhdCBvdGhlciB2YWx1ZXMKYGBge3J9CiMgQ2VudGVyIGJ5IHN1YnRyYWN0aW5nIHRoZSBtZWFuIG9mICdsb2dfY3VtJwpkZl9ub19jdHIgPC0gZGYKZGZfbm9fY3RyJGxvZ19jdW0gPC0gZGZfbm9fY3RyJGxvZ19jdW0gLSBtZWFuKGRmX25vX2N0ciRsb2dfY3VtKSAgIyBDZW50ZXIgYnkgdGhlIG1lYW4KCiMgRml0IHRoZSBtb2RlbCBhZ2FpbiB1c2luZyB0aGUgY2VudGVyZWQgbG9nX2N1bSAobWVhbi1jZW50ZXJlZCkKcmVmaXRfbW9kZWxfY3RyX21lYW4gPC0gZ2xtZXIoCiAgZm9ybXVsYSA9IGZpbmFsX21vZGVsQGNhbGwkZm9ybXVsYSwKICBkYXRhID0gZGZfbm9fY3RyLAogIGZhbWlseSA9IGJpbm9taWFsLAogIGNvbnRyb2wgPSBnbG1lckNvbnRyb2wob3B0aW1pemVyID0gImJvYnlxYSIsIG9wdEN0cmwgPSBsaXN0KG1heGZ1biA9IDJlNSkpCikKCmRmX21heCA8LSBkZgpkZl9tYXgkbG9nX2N1bSA8LSBkZl9tYXgkbG9nX2N1bS1tYXgoZGZfbWF4JGxvZ19jdW0pCgpyZWZpdF9tb2RlbF9tYXggPC0gZ2xtZXIoCmZvcm11bGEgPC0gZmluYWxfbW9kZWxAY2FsbCRmb3JtdWxhLAogIGRhdGEgPSBkZl9tYXgsCiAgZmFtaWx5ID0gYmlub21pYWwsCiAgY29udHJvbCA9IGdsbWVyQ29udHJvbChvcHRpbWl6ZXIgPSAiYm9ieXFhIiwgb3B0Q3RybCA9IGxpc3QobWF4ZnVuID0gMmU1KSkKKQpgYGAKCgoKIyMgNC4xLiBGMCBhbmQgRjEgZWZmZWN0cyBvbiB2b3dlbCBoZWlnaHQgCgoKYGBge3J9CiMgUGxvdCBGMSB3aXRoIHNlcGFyYXRlIGxpbmVzIGZvciBlYWNoIGxldmVsIG9mIGZhY3RvX2hndApwbG90X2YxIDwtIHBsb3RfbW9kZWwoZmluYWxfbW9kZWwsIAogICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJlZmYiLCAKICAgICAgICAgICAgICAgICAgICAgIHRlcm1zID0gYygiRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIFthbGxdIiwgImZydCIpLCAgCiAgICAgICAgICAgICAgICAgICAgICBtZHJ0LnZhbHVlcyA9ICJtZWFuc2QiLCAKICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIm9yYW5nZSIpICsgICMgY29sb3IgbGluZXMgYnkgZmFjdG9yCiAgdGhlbWVfY293cGxvdCgpICsKICB4bGltKGMoLTIsIDIpKSArCiAgbGFicyh5ID0gIlByb2JhYmlsaXR5IG9mIGEgdm93ZWwgYmVpbmcgaGlnaCIsIAogICAgICAgeCA9ICJOb3JtYWxpemVkIEYxIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfYmxhbmsoKSkrCiAgYWVzKGxpbmV0eXBlID0gZ3JvdXBfY29sKSsKICBzY2FsZV9saW5ldHlwZV9kaXNjcmV0ZShuYW1lID0gIlBsYWNlIG9mIFxuYXJ0aWN1bGF0aW9uIixsYWJlbHMgPSBjKCJiYWNrIiwgImZyb250IikpICArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIm9yYW5nZSIsIm9yYW5nZSIpLCBndWlkZSA9ICJub25lIikrCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygib3JhbmdlIiwib3JhbmdlIiksIGd1aWRlID0gIm5vbmUiKQoKcGxvdF9mMCA8LSBwbG90X21vZGVsKGZpbmFsX21vZGVsLCAKICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAiZWZmIiwgCiAgICAgICAgICAgICAgICAgICAgICB0ZXJtcyA9IGMoIkYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCBbYWxsXSIsICJmcnQiKSwgCiAgICAgICAgICAgICAgICAgICAgICBtZHJ0LnZhbHVlcyA9ICJtZWFuc2QiLCAKICAgICAgICAgICAgICAgICAgICAgIGF0ID0gbGlzdChsb2dfY3VtID0gbWF4KGxvZ19jdW0pKSwKICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gInB1cnBsZSIpICsKICAgIGFlcyhsaW5ldHlwZSA9IGdyb3VwX2NvbCkrCiAgdGhlbWVfY293cGxvdCgpICsKICB4bGltKGMoLTIsIDIpKSArCiAgbGFicyh5ID0gIiIsIHggPSAiTm9ybWFsaXplZCBGMCIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X2JsYW5rKCkpKwogIHNjYWxlX2xpbmV0eXBlX2Rpc2NyZXRlKG5hbWUgPSAiUGxhY2Ugb2YgXG5hcnRpY3VsYXRpb24iLCAgbGFiZWxzID0gYygiYmFjayIsICJmcm9udCIpKSAgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJwdXJwbGUiLCJwdXJwbGUiKSwgZ3VpZGUgPSAibm9uZSIpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInB1cnBsZSIsInB1cnBsZSIpLCBndWlkZSA9ICJub25lIikKCiMgQ29tYmluZSBwbG90cwpjb21iaW5lZF9wbG90cyA8LSBncmlkLmFycmFuZ2UocGxvdF9mMSwgcGxvdF9mMCwgbmNvbCA9IDIpCgojIFByaW50IGNvbWJpbmVkIHBsb3QKcHJpbnQoY29tYmluZWRfcGxvdHMpCgojIFNhdmUKZ2dzYXZlKGZpbGVuYW1lID0gIn4vRGVza3RvcC9mMV92c19mMF9ieV9mcnRfZXBzLmVwcyIsIAogICAgICAgcGxvdCA9IGNvbWJpbmVkX3Bsb3RzLCAKICAgICAgIHdpZHRoID0gMTAsIGhlaWdodCA9IDYsIGRwaSA9IDEwMDApCgpgYGAKCgoKIyMgNC4yLiBEZXZlbG9wbWVudGFsIHRyYWplY3RvcmllcwpgYGB7cn0KIyBEZWZpbmUgY29sb3JzIGZvciBGMSBhbmQgRjAKZjFfY29sb3IgPC0gYygiIzlGMzQwMCIsIiNGRjY4MUYiLCIjRkZCRTlGIikKZjBfY29sb3IgPC0gYygiIzU3MDk4NyIsIiNBMDIwRjAiLCIjRDM5N0Y4IikKCiMgUGxvdCBmb3IgRjEKcGxvdF9mMSA8LSBwbG90X21vZGVsKGZpbmFsX21vZGVsLCB0eXBlID0gImVmZiIsIHRlcm1zID0gYygibG9nX2N1bSBbYWxsXSIsICJGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQiKSkgKwogIGxhYnMoY29sb3IgPSAiTm9ybWFsaXplZCBGMSIsIHkgPSAiUHJlZGljdGVkIHByb2JhYmlsaXR5IG9mIGEgdm93ZWwgYmVpbmcgaGlnaCIsIHggPSAibG9nKGN1bXVsYXRpdmUgdm9jYWJ1bGFyeSkiLCB0aXRsZSA9ICIiKSArCiAgdGhlbWVfY293cGxvdCgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gZjFfY29sb3IpICsgICMgU3BlY2lmeSBjb2xvciBmb3IgRjEKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBmMV9jb2xvcikgKyAgIyBTcGVjaWZ5IGNvbG9yIGZvciBGMQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdCgpLCBsaW1pdHMgPSBjKDAsIDEpKSArICAgICMgU2V0IHktYXhpcyBsaW1pdHMgZnJvbSAwIHRvIDEKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwgbGVnZW5kLmJveCA9ICJob3Jpem9udGFsIikgIAoKCiMgUGxvdCBmb3IgRjAKcGxvdF9mMCA8LSBwbG90X21vZGVsKGZpbmFsX21vZGVsLCB0eXBlID0gImVmZiIsIHRlcm1zID0gYygibG9nX2N1bSBbYWxsXSIsICJGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQiKSkgKwogIGxhYnMoY29sb3IgPSAiTm9ybWFsaXplZCBGMCIsIHkgPSAiUHJlZGljdGVkIHByb2JhYmlsaXR5IG9mIGEgdm93ZWwgYmVpbmcgaGlnaCIsIHggPSAibG9nKGN1bXVsYXRpdmUgdm9jYWJ1bGFyeSkiLCB0aXRsZSA9ICIiKSArCiAgdGhlbWVfY293cGxvdCgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gZjBfY29sb3IpICsgICMgU3BlY2lmeSBjb2xvciBmb3IgRjAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBmMF9jb2xvcikgKyAgIyBTcGVjaWZ5IGNvbG9yIGZvciBGMAogICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoKSwgbGltaXRzID0gYygwLCAxKSkgKyAgICAjIFNldCB5LWF4aXMgbGltaXRzIGZyb20gMCB0byAxCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGxlZ2VuZC5ib3ggPSAiaG9yaXpvbnRhbCIpICAKCiMgQWRqdXN0IHBsb3Qgd2lkdGggYW5kIGhlaWdodApwbG90X2YxIApwbG90X2YwCgoKZ2dzYXZlKAogIGZpbGVuYW1lID0gIn4vRGVza3RvcC9wbG90X2YxX2Vwcy5lcHMiLAogIHBsb3QgPSBwbG90X2YxLAogIHdpZHRoID0gNiwKICBoZWlnaHQgPSA1LAogIHVuaXRzID0gImluIgopCgpnZ3NhdmUoCiAgZmlsZW5hbWUgPSAifi9EZXNrdG9wL3Bsb3RfZjBfZXBzLmVwcyIsCiAgcGxvdCA9IHBsb3RfZjAsCiAgd2lkdGggPSA2LAogIGhlaWdodCA9IDUsCiAgdW5pdHMgPSAiaW4iCikKCmRmX3Bsb3RfZjEgPC0gcGxvdF9mMSRkYXRhCmRmX3Bsb3RfZjAgPC0gcGxvdF9mMCRkYXRhCgpwcmludChhcy5kYXRhLmZyYW1lKGRmX3Bsb3RfZjEpKQpwcmludChhcy5kYXRhLmZyYW1lKGRmX3Bsb3RfZjApKQpgYGAKCgoKCgpgYGB7cn0KcHJfRjE8LXByZWRpY3RfcmVzcG9uc2UoZmluYWxfbW9kZWwsYygiRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIiwgImxvZ19jdW0iICkpCmpuX3ByX0YxIDwtIHBsb3Qoam9obnNvbl9uZXltYW4ocHJfRjEpKSAgKwogICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImluY29uc2lzdGVudCIgPSAiZ3JleSIsICJwb3NpdGl2ZS9uZWdhdGl2ZSIgPSAib3JhbmdlIikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJpbmNvbnNpc3RlbnQiID0gImdyZXkiLCAicG9zaXRpdmUvbmVnYXRpdmUiID0gIm9yYW5nZSIpKSArCiAgbGFicyh5ID0gIlNsb3BlIG9mIE5vcm1hbGl6ZWQgRjEiLCB4ID0gImxvZyhjdW11bGF0aXZlIHZvY2FidWxhcnkpIiwgdGl0bGUgPSAiIikgKwogIHRoZW1lX2Nvd3Bsb3QoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIGxlZ2VuZC5ib3ggPSAiaG9yaXpvbnRhbCIpICsgCiAgeWxpbShjKC0wLjUsMC41KSkKCnByX0YwPC1wcmVkaWN0X3Jlc3BvbnNlKGZpbmFsX21vZGVsLGMoIkYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCIsICJsb2dfY3VtIikpCmpuX3ByX0YwIDwtIHBsb3Qoam9obnNvbl9uZXltYW4ocHJfRjApKSAgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJpbmNvbnNpc3RlbnQiID0gImdyZXkiLCAicG9zaXRpdmUvbmVnYXRpdmUiID0gInB1cnBsZSIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiaW5jb25zaXN0ZW50IiA9ICJncmV5IiwgInBvc2l0aXZlL25lZ2F0aXZlIiA9ICJwdXJwbGUiKSkgKwogIGxhYnMoeSA9ICJTbG9wZSBvZiBOb3JtYWxpemVkIEYwIiwgeCA9ICJsb2coY3VtdWxhdGl2ZSB2b2NhYnVsYXJ5KSIsIHRpdGxlID0gIiIpICsKICB0aGVtZV9jb3dwbG90KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLCAKICAgICAgICBsZWdlbmQuYm94ID0gImhvcml6b250YWwiKSsgCiAgeWxpbShjKC0wLjUsMC41KSkKCgpqbl9wcl9GMQpqbl9wcl9GMAoKZ2dzYXZlKGZpbGVuYW1lID0gIn4vRGVza3RvcC9qbl9wcl9GMF9lcHMuZXBzIiwgCiAgICAgICBwbG90ID0gam5fcHJfRjAsIAogICAgICAgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNiwgZHBpID0gMTAwMCkKCmdnc2F2ZShmaWxlbmFtZSA9ICJ+L0Rlc2t0b3Avam5fcHJfRjFfZXBzLmVwcyIsIAogICAgICAgcGxvdCA9IGpuX3ByX0YxLCAKICAgICAgIHdpZHRoID0gMTAsIGhlaWdodCA9IDYsIGRwaSA9IDEwMDApCmBgYAoKIyMgNC4zLiBDb3JyZWxhdGlvbiBiZXR3ZWVuIGN1ZXMKCmBgYHtyfQpjb3JyX2Z1bGwgPC0gY29yLnRlc3QoZGYkRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkLAogICAgICAgICAgICAgICAgICAgICAgZGYkRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkLCBtZXRob2QgPSAncGVhcnNvbicpCgpoaWdoIDwtIGRmICU+JSBmaWx0ZXIoaGd0ID09ICJoaWdoIiApCmxvdyAgPC0gZGYgJT4lIGZpbHRlcihoZ3QgPT0gImxvdyIpCgpjb3JyX2hpZ2ggPC0gY29yLnRlc3QoaGlnaCRGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQsCiAgICAgICAgICAgICAgICAgICAgICBoaWdoJEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCkKCmNvcnJfbG93IDwtIGNvci50ZXN0KGxvdyRGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQsCiAgICAgICAgICAgICAgICAgICAgIGxvdyRGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQpCgojIFB1dCBhbGwgcmVzdWx0cyBpbiBhIGxpc3QKY29ycl9yZXN1bHRzIDwtIGxpc3QoCiAgZnVsbCA9IGNvcnJfZnVsbCwKICBoaWdoID0gY29ycl9oaWdoLAogIGxvdyAgPSBjb3JyX2xvdwopCgpjb3JyX3Jlc3VsdHMKYGBgCgpgYGB7cn0KCgpkZl9hdmcgPC0gZGYgJT4lCiAgZ3JvdXBfYnkoQ0hJTEQsaGd0KSAlPiUKICBzdW1tYXJpc2UoCiAgICBGMV9hdmcgPSBtZWFuKEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCwgbmEucm0gPSBUUlVFKSwKICAgIEYwX2F2ZyA9IG1lYW4oRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkLCBuYS5ybSA9IFRSVUUpLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkKCmNvcnJfZnVsbF9hdmcgPC0gY29yLnRlc3QoZGZfYXZnJEYxX2F2ZywgZGZfYXZnJEYwX2F2ZywgbWV0aG9kID0gInBlYXJzb24iKQoKZGZfYXZnIDwtIGRmICU+JQogIGdyb3VwX2J5KENISUxELGhndCkgJT4lCiAgc3VtbWFyaXNlKAogICAgRjFfYXZnID0gbWVhbihGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQsIG5hLnJtID0gVFJVRSksCiAgICBGMF9hdmcgPSBtZWFuKEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCwgbmEucm0gPSBUUlVFKSwKICAgIC5ncm91cHMgPSAiZHJvcCIKICApCgpoaWdoX2F2ZyA8LSBkZl9hdmcgJT4lIGZpbHRlcihoZ3QgPT0gImhpZ2giKQpsb3dfYXZnICA8LSBkZl9hdmcgJT4lIGZpbHRlcihoZ3QgPT0gImxvdyIpCgpjb3JyX2hpZ2hfYXZnIDwtIGNvci50ZXN0KGhpZ2hfYXZnJEYxX2F2ZywgaGlnaF9hdmckRjBfYXZnLCBtZXRob2QgPSAicGVhcnNvbiIpCmNvcnJfbG93X2F2ZyAgPC0gY29yLnRlc3QobG93X2F2ZyRGMV9hdmcsICBsb3dfYXZnJEYwX2F2ZywgIG1ldGhvZCA9ICJwZWFyc29uIikKCgpjb3JyX3Jlc3VsdHNfYXZnIDwtIGxpc3QoCiAgZnVsbF9hdmcgPSBjb3JyX2Z1bGxfYXZnLAogIGhpZ2hfYXZnID0gY29ycl9oaWdoX2F2ZywKICBsb3dfYXZnICA9IGNvcnJfbG93X2F2ZwopCgpjb3JyX3Jlc3VsdHNfYXZnCmBgYAoKYGBge3J9CgojIEV4dHJhY3QgY29lZmZpY2llbnQgdmFsdWVzIGFuZCBjb252ZXJ0IHRvIGEgZGF0YSBmcmFtZSBmb3IgbWVhbi1jZW50ZXJlZCBtb2RlbApjb2VmZmljaWVudHNfbWVhbiA8LSBhcy5kYXRhLmZyYW1lKGNvZWYocmVmaXRfbW9kZWxfY3RyX21lYW4gKSRDSElMRCkKY29lZmZpY2llbnRzX21lYW4kaWQgPC0gcm93Lm5hbWVzKGNvZWZmaWNpZW50c19tZWFuKQpjb2VmZmljaWVudHNfbWVhbiRtb2RlbCA8LSAibWVhbl9jZW50ZXJlZCIKCiMgQ29tYmluZSBmaW5hbCwgcmVmaXQsIGFuZCBtZWFuLWNlbnRlcmVkIGNvZWZmaWNpZW50cyBpbnRvIG9uZSBkYXRhIGZyYW1lCmNvZWZmaWNpZW50c19jb21iaW5lZCA8LSByYmluZChjb2VmZmljaWVudHNfbWVhbikKCiMgTWFrZSBzdXJlIGlkIGlzIGEgZmFjdG9yCmNvZWZmaWNpZW50c19jb21iaW5lZCRpZCA8LSBhcy5mYWN0b3IoY29lZmZpY2llbnRzX2NvbWJpbmVkJGlkKQoKIyBHYXRoZXIgRjEgYW5kIEYwIGludG8gb25lICd2YXJpYWJsZScgY29sdW1uCmNvZWZmaWNpZW50c19sb25nIDwtIGNvZWZmaWNpZW50c19jb21iaW5lZCAlPiUKICBzZWxlY3QoaWQsIG1vZGVsLCBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQsIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCkgJT4lCiAgZ2F0aGVyKGtleSA9ICJ2YXJpYWJsZSIsIHZhbHVlID0gInZhbHVlIiwgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkLCBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQpCgojIFNwcmVhZCBieSBtb2RlbCAoZmluYWwsIHJlZml0LCBhbmQgbWVhbi1jZW50ZXJlZCkKY29lZmZpY2llbnRzX3dpZGUgPC0gY29lZmZpY2llbnRzX2xvbmcgJT4lCiAgc3ByZWFkKGtleSA9IG1vZGVsLCB2YWx1ZSA9IHZhbHVlKQoKIyBQaXZvdCB3aWRlciB0byBpbmNsdWRlIGZpbmFsLCByZWZpdCwgYW5kIG1lYW4tY2VudGVyZWQgdmFsdWVzCmNvZWZmaWNpZW50c19maW5hbF93aWRlIDwtIGNvZWZmaWNpZW50c193aWRlICU+JQogIHBpdm90X3dpZGVyKAogICAgbmFtZXNfZnJvbSA9IHZhcmlhYmxlLAogICAgdmFsdWVzX2Zyb20gPSBjKG1lYW5fY2VudGVyZWQpCiAgKQoKcGxvdCA8LSBnZ3Bsb3QoY29lZmZpY2llbnRzX2ZpbmFsX3dpZGUsIGFlcyh4ID1GMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQpKSArCiAgZ2VvbV9wb2ludChjb2xvciA9ICJncmV5NjAiLCBzaXplID0gMywgYWxwaGEgPSAwLjgpICsKICBzbV9zdGF0Q29ycihjb2xvciA9ICIjNUYwMjFGIikrCiAgeGxpbSgtMTIsMCkrCiAgeWxpbSgwLDEyKSsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiLAogICAgbGVnZW5kLmJveCA9ICJob3Jpem9udGFsIiwKICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTk1Iiwgc2l6ZSA9IDAuNSksICAjIFN1YnRsZSBncmlkIGxpbmVzCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAgIyBSZW1vdmUgbWlub3IgZ3JpZCBsaW5lcyBmb3IgYSBjbGVhbmVyIGxvb2sKICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSwsCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigyMCwgMjAsIDIwLCAyMCkgICMgQWRkIG1hcmdpbiBmb3IgYWVzdGhldGljcwogICkgKwogIGxhYnMoCiAgICB4ID0gIkYxIFJlZ3Jlc3Npb24gTm9ybWFsaXplZCIsCiAgICB5ID0gIkYwIFJlZ3Jlc3Npb24gTm9ybWFsaXplZCIpKwogIGNvb3JkX2ZpeGVkKCkKCnBsb3QKCmdnc2F2ZShmaWxlbmFtZSA9ICJ+L0Rlc2t0b3AvY29ycl9lcHMuZXBzIiwgCiAgICAgICBwbG90ID0gcGxvdCwgCiAgICAgICB3aWR0aCA9IDEwLCBoZWlnaHQgPSA2LCBkcGkgPSAxMDAwKQoKYGBgCgoKIyMgNC40LiBCZXR3ZWVuIGNoaWxkcmVuIHZhcmlhYmlsaXR5IAoKCmBgYHtyfQojIEV4dHJhY3QgY29lZmZpY2llbnQgdmFsdWVzIGFuZCBjb252ZXJ0IHRvIGEgZGF0YSBmcmFtZQpjb2VmZmljaWVudHNfMDwtIGFzLmRhdGEuZnJhbWUoY29lZihmaW5hbF9tb2RlbCkkQ0hJTEQpCmNvZWZmaWNpZW50c18wJGlkIDwtIHJvdy5uYW1lcyhjb2VmZmljaWVudHNfMCkgICAjIEFkZCBJRCBhcyBhIGNvbHVtbgpjb2VmZmljaWVudHNfMCRpZCA8LSBhcy5mYWN0b3IoY29lZmZpY2llbnRzXzAkaWQpICAgIyBDb252ZXJ0IElEIHRvIGZhY3RvcgoKIyBSZXNoYXBlIHRoZSBkYXRhIGZyYW1lIGZyb20gd2lkZSB0byBsb25nIGZvcm1hdApjb2VmZmljaWVudHNfMDwtIHBpdm90X2xvbmdlcihjb2VmZmljaWVudHNfMCwgY29scyA9IGMoRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkLCBGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQpLCBuYW1lc190byA9ICJWYXJpYWJsZSIsIHZhbHVlc190byA9ICJWYWx1ZSIpCgojIEV4dHJhY3QgY29lZmZpY2llbnQgdmFsdWVzIGFuZCBjb252ZXJ0IHRvIGEgZGF0YSBmcmFtZQpjb2VmZmljaWVudHNfbWF4PC0gYXMuZGF0YS5mcmFtZShjb2VmKHJlZml0X21vZGVsX21heCkkQ0hJTEQpCmNvZWZmaWNpZW50c19tYXgkaWQgPC0gcm93Lm5hbWVzKGNvZWZmaWNpZW50c19tYXgpICAgIyBBZGQgSUQgYXMgYSBjb2x1bW4KY29lZmZpY2llbnRzX21heCRpZCA8LSBhcy5mYWN0b3IoY29lZmZpY2llbnRzX21heCRpZCkgICAjIENvbnZlcnQgSUQgdG8gZmFjdG9yCgoKIyBSZXNoYXBlIHRoZSBkYXRhIGZyYW1lIGZyb20gd2lkZSB0byBsb25nIGZvcm1hdApjb2VmZmljaWVudHNfbWF4PC0gcGl2b3RfbG9uZ2VyKGNvZWZmaWNpZW50c19tYXgsIGNvbHMgPSBjKEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCwgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkKSwgbmFtZXNfdG8gPSAiVmFyaWFibGUiLCB2YWx1ZXNfdG8gPSAiVmFsdWUiKQoKIyBBZGQgYSAiQ2VudGVyaW5nIiBjb2x1bW4gdG8gaWRlbnRpZnkgd2hlcmUgdGhlIGNvZWZmaWNpZW50cyBjb21lIGZyb20KY29lZmZpY2llbnRzXzAkQ2VudGVyaW5nIDwtICJDZW50ZXJlZF9hdF8wIgpjb2VmZmljaWVudHNfbWF4JENlbnRlcmluZyA8LSAiQ2VudGVyZWRfYXRfTWF4IgoKCiMgQ29tYmluZSB0aGUgdHdvIGRhdGEgZnJhbWVzCmNvZWZfZnVsbCA8LSBiaW5kX3Jvd3MoY29lZmZpY2llbnRzXzAsIGNvZWZmaWNpZW50c19tYXgpCgojIEFkZCBhIG5ldyBjb2x1bW4gdG8gY29udHJvbCBhbHBoYQpjb2VmX2Z1bGwkQWxwaGEgPC0gaWZlbHNlKGNvZWZfZnVsbCRDZW50ZXJpbmcgPT0gIkNlbnRlcmVkX2F0XzAiLCAwLjksIDEpICAjIENpcmNsZXMgPSAwLjMsIFRyaWFuZ2xlcyA9IDEKCiMgVXBkYXRlIHRoZSBsZXZlbHMgYW5kIGxhYmVscyBmb3IgYmV0dGVyIHJlYWRhYmlsaXR5CmNvZWZfZnVsbCRWYXJpYWJsZSA8LSBmYWN0b3IoY29lZl9mdWxsJFZhcmlhYmxlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQiLCAiRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiRjAiLCAiRjEiKSkKCmNvZWZfZnVsbCRDZW50ZXJpbmcgPC0gZmFjdG9yKGNvZWZfZnVsbCRDZW50ZXJpbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkNlbnRlcmVkX2F0XzAiLCAiQ2VudGVyZWRfYXRfTWF4IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkF0IGN1bXVsYXRpdmUgdm9jYWJ1bGFyeSA9IDAiLCAiQXQgbWF4aW11bSBjdW11bGF0aXZlIHZvY2FidWxhcnkiKSkKCgojIFJlb3JkZXIgaWRzIGJhc2VkIG9uIEYxIHZhbHVlcyAoY2hvb3NlIHdoaWNoIGNlbnRlcmluZyB5b3Ugd2FudCkKY29lZl9mdWxsX29yZGVyZWQgPC0gY29lZl9mdWxsICU+JQogIGZpbHRlcihWYXJpYWJsZSA9PSAiRjAiKSAlPiUKICBhcnJhbmdlKFZhbHVlKSAlPiUKICBtdXRhdGUoaWQgPSBmYWN0b3IoaWQsIGxldmVscyA9IHVuaXF1ZShpZCkpKSAlPiUKICBzZWxlY3QoaWQpICU+JQogIHJpZ2h0X2pvaW4oY29lZl9mdWxsLCBieSA9ICJpZCIpICU+JSAgICMgcmVzdG9yZSBmdWxsIGRhdGFzZXQgd2l0aCBvcmRlcmluZwogIGxlZnRfam9pbigKICAgIGRmX2Rlc2NyX3Bob24gJT4lIGRpc3RpbmN0KGlkID0gQ0hJTEQsIGxhYmVsID0gQ0hJTERfYW5vbiksCiAgICBieSA9ICJpZCIKICApCgpjb2VmX2Z1bGxfb3JkZXJlZCA8LSBjb2VmX2Z1bGxfb3JkZXJlZCAlPiUKICBtdXRhdGUobGFiZWwgPSBmYWN0b3IobGFiZWwsIGxldmVscyA9IHVuaXF1ZShsYWJlbFtvcmRlcihpZCldKSkpCgpwbG90IDwtIGdncGxvdChjb2VmX2Z1bGxfb3JkZXJlZCwgYWVzKHggPSBsYWJlbCwgeSA9IFZhbHVlKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGFlcyhjb2xvciA9IFZhcmlhYmxlLCBzaGFwZSA9IENlbnRlcmluZykpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gYygKICAgICJBdCBjdW11bGF0aXZlIHZvY2FidWxhcnkgPSAwIiA9IDEsCiAgICAiQXQgbWF4aW11bSBjdW11bGF0aXZlIHZvY2FidWxhcnkiID0gMTYKICApKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIkYwIiA9ICJwdXJwbGUiLCAiRjEiID0gIm9yYW5nZSIpKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gbGFiZWwsIHhlbmQgPSBsYWJlbCwgeSA9IDAsIHllbmQgPSBWYWx1ZSwgY29sb3IgPSBWYXJpYWJsZSksCiAgICAgICAgICAgICAgIHNpemUgPSAwLjUpICsKICBsYWJzKAogICAgdGl0bGUgPSAiIiwKICAgIHggPSAiQ2hpbGQgbGFiZWwiLAogICAgeSA9ICJJbmRpdmlkdWFsIENvZWZmaWNpZW50IFZhbHVlIiwKICAgIGNvbG9yID0gIkN1ZSIsCiAgICBzaGFwZSA9ICJDdW11bGF0aXZlIHZvY2FidWxhcnkiCiAgKSArCiAgI3NjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gbGFiZWwpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwKICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAidmVydGljYWwiLAogICAgbGVnZW5kLmJveCA9ICJ2ZXJ0aWNhbCIsCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGhqdXN0ID0gMC41KSwKICAgIHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKQogICkKCnBsb3QKCmdnc2F2ZShmaWxlbmFtZSA9ICJ+L0Rlc2t0b3AvbG9sbGlwbG90X2Vwcy5lcHMiLCAKICAgICAgIHBsb3QgPSBwbG90LCAKICAgICAgIHdpZHRoID0gMjAsIGhlaWdodCA9IDYsIGRwaSA9IDEwMDApCmBgYAoKCgoKYGBge3IgZWNobyA9IFQsIHJlc3VsdHMgPSAnaGlkZSd9CiMgQ2hvb3NlIGNvbnN0YW50IHZhbHVlcyBmb3IgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkIGFuZCBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQKY29uc3RhbnRfRjFfbG93IDwtIG1lYW4oZGYkRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkKSAtIDEqc2QoZGYkRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkKQpjb25zdGFudF9GMF9oaWdoIDwtIG1lYW4oZGYkRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKSArIDEqc2QoZGYkRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkKQpjb25zdGFudF9GMV9oaWdoIDwtIG1lYW4oZGYkRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkKSArIDEqc2QoZGYkRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkKQpjb25zdGFudF9GMF9sb3cgPC0gbWVhbihkZiRGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQpIC0gMSpzZChkZiRGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQpCgojIERlZmluZSBhIHNlcXVlbmNlIG9mIHZhbHVlcyBmb3IgbG9nX2N1bQpsb2dfY3VtX3NlcSA8LSBzZXEoZnJvbSA9IG1pbihkZiRsb2dfY3VtKSwgdG8gPSBtYXgoZGYkbG9nX2N1bSksIGxlbmd0aC5vdXQgPSAxMDApCgojIENyZWF0ZSBuZXcgZGF0YSBmb3IgYm90aCBzY2VuYXJpb3MKbmV3X2RhdGFfbG93X0YxIDwtIGRhdGEuZnJhbWUoCiAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkID0gY29uc3RhbnRfRjFfbG93LAogIEYwX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA9IG1lYW4oZGYkRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkLCBuYS5ybT1UKSwKICBsb2dfY3VtID0gbG9nX2N1bV9zZXEsCiAgZnJ0ID0gImJjayIsCiAgQ0hJTEQgPSByZXAodW5pcXVlKGRmJENISUxEKSwgZWFjaCA9IGxlbmd0aChsb2dfY3VtX3NlcSkpCikKCm5ld19kYXRhX2hpZ2hfRjAgPC0gZGF0YS5mcmFtZSgKICBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgPSBjb25zdGFudF9GMF9oaWdoLAogIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA9IG1lYW4oZGYkRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkLCBuYS5ybT1UKSwKICBsb2dfY3VtID0gbG9nX2N1bV9zZXEsCiAgICBmcnQgPSAiYmNrIiwKICBDSElMRCA9IHJlcCh1bmlxdWUoZGYkQ0hJTEQpLCBlYWNoID0gbGVuZ3RoKGxvZ19jdW1fc2VxKSkKKQoKbmV3X2RhdGFfaGlnaF9GMSA8LSBkYXRhLmZyYW1lKAogIEYxX1JlZ3Jlc3Npb25fTm9ybWFsaXplZCA9IGNvbnN0YW50X0YxX2hpZ2gsCiAgRjBfUmVncmVzc2lvbl9Ob3JtYWxpemVkID0gbWVhbihkZiRGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQsIG5hLnJtPVQpLAogIGxvZ19jdW0gPSBsb2dfY3VtX3NlcSwKICAgIGZydCA9ICJiY2siLAogIENISUxEID0gcmVwKHVuaXF1ZShkZiRDSElMRCksIGVhY2ggPSBsZW5ndGgobG9nX2N1bV9zZXEpKQopCgpuZXdfZGF0YV9sb3dfRjAgPC0gZGF0YS5mcmFtZSgKICBGMF9SZWdyZXNzaW9uX05vcm1hbGl6ZWQgPSBjb25zdGFudF9GMF9sb3csCiAgRjFfUmVncmVzc2lvbl9Ob3JtYWxpemVkID0gbWVhbihkZiRGMV9SZWdyZXNzaW9uX05vcm1hbGl6ZWQsIG5hLnJtPVQpLAogIGxvZ19jdW0gPSBsb2dfY3VtX3NlcSwKICAgIGZydCA9ICJiY2siLAogIENISUxEID0gcmVwKHVuaXF1ZShkZiRDSElMRCksIGVhY2ggPSBsZW5ndGgobG9nX2N1bV9zZXEpKQopCgojIFByZWRpY3QgcHJvYmFiaWxpdGllcyBmb3IgdGhlIG5ldyBkYXRhCnByZWRpY3RlZF9wcm9ic19sb3dfRjEgPC0gcHJlZGljdChmaW5hbF9tb2RlbCwgbmV3ZGF0YSA9IG5ld19kYXRhX2xvd19GMSwgdHlwZSA9ICJyZXNwb25zZSIpCnByZWRpY3RlZF9wcm9ic19oaWdoX0YwIDwtIHByZWRpY3QoZmluYWxfbW9kZWwsIG5ld2RhdGEgPSBuZXdfZGF0YV9oaWdoX0YwLCB0eXBlID0gInJlc3BvbnNlIikKcHJlZGljdGVkX3Byb2JzX2hpZ2hfRjEgPC0gcHJlZGljdChmaW5hbF9tb2RlbCwgbmV3ZGF0YSA9IG5ld19kYXRhX2hpZ2hfRjEsIHR5cGUgPSAicmVzcG9uc2UiKQpwcmVkaWN0ZWRfcHJvYnNfbG93X0YwIDwtIHByZWRpY3QoZmluYWxfbW9kZWwsIG5ld2RhdGEgPSBuZXdfZGF0YV9sb3dfRjAsIHR5cGUgPSAicmVzcG9uc2UiKQoKIyBDb21iaW5lIGxvZ19jdW1fc2VxLCBwcmVkaWN0ZWRfcHJvYnMsIGFuZCBDSElMRCBpbnRvIGRhdGEgZnJhbWVzCnByZWRpY3RlZF9kZl9sb3dfRjEgPC0gZGF0YS5mcmFtZSgKICBsb2dfY3VtID0gcmVwKGxvZ19jdW1fc2VxLCBsZW5ndGgodW5pcXVlKGRmJENISUxEKSkpLAogIHByZWRpY3RlZF9wcm9iID0gcHJlZGljdGVkX3Byb2JzX2xvd19GMSwKICBDSElMRCA9IHJlcCh1bmlxdWUoZGYkQ0hJTEQpLCBlYWNoID0gbGVuZ3RoKGxvZ19jdW1fc2VxKSkKKQoKcHJlZGljdGVkX2RmX2hpZ2hfRjAgPC0gZGF0YS5mcmFtZSgKICBsb2dfY3VtID0gcmVwKGxvZ19jdW1fc2VxLCBsZW5ndGgodW5pcXVlKGRmJENISUxEKSkpLAogIHByZWRpY3RlZF9wcm9iID0gcHJlZGljdGVkX3Byb2JzX2hpZ2hfRjAsCiAgQ0hJTEQgPSByZXAodW5pcXVlKGRmJENISUxEKSwgZWFjaCA9IGxlbmd0aChsb2dfY3VtX3NlcSkpCikKCnByZWRpY3RlZF9kZl9oaWdoX0YxIDwtIGRhdGEuZnJhbWUoCiAgbG9nX2N1bSA9IHJlcChsb2dfY3VtX3NlcSwgbGVuZ3RoKHVuaXF1ZShkZiRDSElMRCkpKSwKICBwcmVkaWN0ZWRfcHJvYiA9IHByZWRpY3RlZF9wcm9ic19oaWdoX0YxLAogIENISUxEID0gcmVwKHVuaXF1ZShkZiRDSElMRCksIGVhY2ggPSBsZW5ndGgobG9nX2N1bV9zZXEpKQopCgpwcmVkaWN0ZWRfZGZfbG93X0YwIDwtIGRhdGEuZnJhbWUoCiAgbG9nX2N1bSA9IHJlcChsb2dfY3VtX3NlcSwgbGVuZ3RoKHVuaXF1ZShkZiRDSElMRCkpKSwKICBwcmVkaWN0ZWRfcHJvYiA9IHByZWRpY3RlZF9wcm9ic19sb3dfRjAsCiAgQ0hJTEQgPSByZXAodW5pcXVlKGRmJENISUxEKSwgZWFjaCA9IGxlbmd0aChsb2dfY3VtX3NlcSkpCikKCiMgQ2FsY3VsYXRlIGF2ZXJhZ2UgcHJlZGljdGVkIHByb2JhYmlsaXRpZXMKYXZlcmFnZV9wcm9iX2xvd19GMSA8LSBwcmVkaWN0ZWRfZGZfbG93X0YxICU+JQogIGdyb3VwX2J5KGxvZ19jdW0pICU+JQogIHN1bW1hcml6ZShhdmVyYWdlX3Byb2IgPSBtZWFuKHByZWRpY3RlZF9wcm9iKSkKCmF2ZXJhZ2VfcHJvYl9oaWdoX0YwIDwtIHByZWRpY3RlZF9kZl9oaWdoX0YwICU+JQogIGdyb3VwX2J5KGxvZ19jdW0pICU+JQogIHN1bW1hcml6ZShhdmVyYWdlX3Byb2IgPSBtZWFuKHByZWRpY3RlZF9wcm9iKSkKCmF2ZXJhZ2VfcHJvYl9oaWdoX0YxIDwtIHByZWRpY3RlZF9kZl9oaWdoX0YxICU+JQogIGdyb3VwX2J5KGxvZ19jdW0pICU+JQogIHN1bW1hcml6ZShhdmVyYWdlX3Byb2IgPSBtZWFuKHByZWRpY3RlZF9wcm9iKSkKCmF2ZXJhZ2VfcHJvYl9sb3dfRjAgPC0gcHJlZGljdGVkX2RmX2xvd19GMCAlPiUKICBncm91cF9ieShsb2dfY3VtKSAlPiUKICBzdW1tYXJpemUoYXZlcmFnZV9wcm9iID0gbWVhbihwcmVkaWN0ZWRfcHJvYikpCgojIFBsb3QgdGhlIGxpbmVzCnBsb3QxIDwtIGdncGxvdChwcmVkaWN0ZWRfZGZfbG93X0YxKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gbG9nX2N1bSwgeSA9IHByZWRpY3RlZF9wcm9iLCBncm91cCA9IENISUxEKSwgY29sb3IgPSAib3JhbmdlIiwgYWxwaGEgPSAwLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IGF2ZXJhZ2VfcHJvYl9sb3dfRjEsIGFlcyh4ID0gbG9nX2N1bSwgeSA9IGF2ZXJhZ2VfcHJvYiksIGNvbG9yID0gIm9yYW5nZSIsIHNpemUgPSAyKSArCiAgbGFicyh4ID0gIiIsIHkgPSAiIiwgdGl0bGUgPSAiYSBsb3cgRjEgKG1lYW4tU0QpIikgKwogICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdCgpLCBsaW1pdHMgPSBjKDAsIDEpKSArIAogIHRoZW1lX21pbmltYWwoKQoKcGxvdDIgPC0gZ2dwbG90KHByZWRpY3RlZF9kZl9oaWdoX0YwKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gbG9nX2N1bSwgeSA9IHByZWRpY3RlZF9wcm9iLCBncm91cCA9IENISUxEKSwgY29sb3IgPSAicHVycGxlIiwgYWxwaGEgPSAwLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IGF2ZXJhZ2VfcHJvYl9oaWdoX0YwLCBhZXMoeCA9IGxvZ19jdW0sIHkgPSBhdmVyYWdlX3Byb2IpLCBjb2xvciA9ICJwdXJwbGUiLCBzaXplID0gMikgKwogIGxhYnMoeCA9ICIiLCB5ID0gIiIsIHRpdGxlID0gImEgaGlnaCBGMCAobWVhbitTRCkiKSArCiAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCksIGxpbWl0cyA9IGMoMCwgMSkpICsgCiAgdGhlbWVfbWluaW1hbCgpCgpwbG90MyA8LSBnZ3Bsb3QocHJlZGljdGVkX2RmX2hpZ2hfRjEpICsKICBnZW9tX2xpbmUoYWVzKHggPSBsb2dfY3VtLCB5ID0gcHJlZGljdGVkX3Byb2IsIGdyb3VwID0gQ0hJTEQpLCBjb2xvciA9ICJvcmFuZ2UiLCBhbHBoYSA9IDAuMikgKwogIGdlb21fbGluZShkYXRhID0gYXZlcmFnZV9wcm9iX2hpZ2hfRjEsIGFlcyh4ID0gbG9nX2N1bSwgeSA9IGF2ZXJhZ2VfcHJvYiksIGNvbG9yID0gIm9yYW5nZSIsIHNpemUgPSAyKSArCiAgbGFicyh4ID0gImxvZyAoY3VtdWxhdGl2ZSB2b2NhYnVsYXJ5KSIsIHkgPSAiIiwgdGl0bGUgPSAiYSBoaWdoIEYxIChtZWFuK1NEKSIpICsKICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoKSwgbGltaXRzID0gYygwLCAxKSkgKyAKICB0aGVtZV9taW5pbWFsKCkKCnBsb3Q0IDwtIGdncGxvdChwcmVkaWN0ZWRfZGZfbG93X0YwKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0gbG9nX2N1bSwgeSA9IHByZWRpY3RlZF9wcm9iLCBncm91cCA9IENISUxEKSwgY29sb3IgPSAicHVycGxlIiwgYWxwaGEgPSAwLjIpICsKICBnZW9tX2xpbmUoZGF0YSA9IGF2ZXJhZ2VfcHJvYl9sb3dfRjAsIGFlcyh4ID0gbG9nX2N1bSwgeSA9IGF2ZXJhZ2VfcHJvYiksIGNvbG9yID0gInB1cnBsZSIsIHNpemUgPSAyKSArCiAgbGFicyh4ID0gImxvZyAoY3VtdWxhdGl2ZSB2b2NhYnVsYXJ5KSIsIHkgPSAiIiwgdGl0bGUgPSAiYSBsb3cgRjAgKG1lYW4tU0QpIikgKwogICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdCgpLCBsaW1pdHMgPSBjKDAsIDEpKSArIAogIHRoZW1lX21pbmltYWwoKQoKIyBDb21iaW5lIHBsb3RzCmNvbWJpbmVkX3Bsb3RzIDwtIGdyaWQuYXJyYW5nZShwbG90MSwgcGxvdDIsIHBsb3QzLCBwbG90NCwgbmNvbCA9IDIpCgojIEFkZCBvdmVyYWxsIHRpdGxlCm92ZXJhbGxfdGl0bGUgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKCJJbmRpdmlkdWFsIHRyYWplY3RvcmllcyBmb3IgdGhlIGVmZmVjdCBvZiIsIHNpemUgPSAxNSwgZm9udGZhY2UgPSAiYm9sZCIsIHggPSAwLjUpCgojIEFkZCBzaW5nbGUgeS1heGlzIGxhYmVsCnlfbGFiZWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKCJQcmVkaWN0ZWQgcHJvYmFiaWxpdHkgb2YgYSB2b3dlbCBiZWluZyBoaWdoIiwgc2l6ZSA9IDEyLCBhbmdsZSA9IDkwLCAKICAgICAgICAgICAgIHggPSAwLjAxNSwgeSA9IC0xLCB2anVzdCA9IDAuNSwgaGp1c3QgPSAxKQojIFByaW50IGNvbWJpbmVkIHBsb3Qgd2l0aCBvdmVyYWxsIHRpdGxlCmdyaWQuYXJyYW5nZShvdmVyYWxsX3RpdGxlLCB5X2xhYmVsLCBjb21iaW5lZF9wbG90cywgbmNvbCA9IDEsIGhlaWdodHMgPSBjKDAuMDUsIDAuMDUsIDAuOSkpCgpzYXZlLmltYWdlKGZpbGUgPSAiYW5hbHlzaXNfRjFfRjAuUkRhdGEiKQpgYGAKCgo=