Load and preprocess certainty data

Preprocessing: For all the analysis below, we omitted data of 3 participants who have failed at least one attention check during the experiments, omitted all individual lesson data where the participants’ initial certainty score was below 10 points on the 15-point scale and removed any outliers (1.5 IQR).

library(readr)
library(dplyr)
library(stringr)

data <- read_csv("certainty.csv", show_col_types = FALSE) %>%
  filter(exclude == 0) %>%
  filter(participant_id > -1)
  

# Get all unique suffixes for lessons and conditions
likert_pre_cols <- grep("^likert_pre_", names(data), value = TRUE)
suffixes <- str_replace(likert_pre_cols, "^likert_pre_", "")

for (suf in suffixes) {
  pre_col <- paste0("likert_pre_", suf)
  mid_col <- paste0("likert_mid_", suf)
  post_col <- paste0("likert_post_", suf)
  
  # Check all columns exist
  if (all(c(pre_col, mid_col, post_col) %in% names(data))) {
    data <- data %>%
      mutate(
        across(
          all_of(c(pre_col, mid_col, post_col)),
          ~ if_else(.data[[pre_col]] < 10, NA_real_, .)
        )
      )
  }
}

print(data)
NA
NA

Demographics

# Load necessary library
library(dplyr)

# Load the data from the CSV file
demographics_data <- read.csv("demographics.csv", stringsAsFactors = FALSE)

# Specify the IDs to remove
ids_to_remove <- c("682f47a03095562bd581bd06", "674d7a89f564e8bbe0a7af1c", "65537e14439274fe5036b4d2")

# Filter the data to remove participants with the specified IDs
filtered_data <- demographics_data %>%
  filter(!Participant.id %in% ids_to_remove)

# Filter out rows where Status is not 'APPROVED'
accepted_data <- filtered_data %>%
  filter(Status == "APPROVED")
# Assuming 'accepted_data' is the filtered dataset for participants with 'Status' == 'ACCEPTED'
# Ensure Age column is numeric
accepted_data$Age <- as.numeric(accepted_data$Age)

# Check for conversion issues and warn if any entries became NA
conversion_issues <- sum(is.na(accepted_data$Age))
if (conversion_issues > 0) {
  warning(paste(conversion_issues, "non-numeric entries were converted to NA in the Age column."))
}

# Calculate mean and standard deviation, ignoring NAs
age_stats <- accepted_data %>%
  summarise(
    Mean_Age = mean(Age, na.rm = TRUE),
    SD_Age = sd(Age, na.rm = TRUE)
  )

age_summary <- paste0("Mean: ", round(age_stats$Mean_Age, 2), ", SD: ", round(age_stats$SD_Age, 2))


# Calculate gender distribution
gender_distribution <- paste(names(table(accepted_data$Sex)), 
                             table(accepted_data$Sex), 
                             sep = ": ", 
                             collapse = ", ")

# Calculate ethnicity distribution
ethnicity_distribution <- paste(names(table(accepted_data$Ethnicity.simplified)), 
                                table(accepted_data$Ethnicity.simplified), 
                                sep = ": ", 
                                collapse = ", ")

# List all nationalities with counts
nationality_distribution <- paste(names(table(accepted_data$Nationality)), 
                                  table(accepted_data$Nationality), 
                                  sep = ": ", 
                                  collapse = ", ")

# Calculate student status distribution
student_status_distribution <- paste(names(table(accepted_data$Student.status)), 
                                     table(accepted_data$Student.status), 
                                     sep = ": ", 
                                     collapse = ", ")

# Calculate employment status distribution
employment_status_distribution <- paste(names(table(accepted_data$Employment.status)), 
                                        table(accepted_data$Employment.status), 
                                        sep = ": ", 
                                        collapse = ", ")

# Compile results into a data frame
demographics_summary <- data.frame(
  Statistic = c(
    "Age (Mean, SD)",
    "Gender Distribution",
    "Ethnicity Distribution",
    "Nationalities",
    "Student Status Distribution",
    "Employment Status Distribution"
  ),
  Value = c(
    age_summary,
    gender_distribution,
    ethnicity_distribution,
    nationality_distribution,
    student_status_distribution,
    employment_status_distribution
  ),
  stringsAsFactors = FALSE
)

# Print the summary table
print(demographics_summary)

Timeline data

library(DBI)
library(RSQLite)
library(dplyr)
library(ggplot2)
library(lubridate)

# Connect to DB and load filtered data
con <- dbConnect(RSQLite::SQLite(), "database.db")

load_phase <- function(table, phase) {
  dbReadTable(con, table) %>%
    filter(user_id >= 0, user_id <= 2000) %>%
    arrange(user_id, created_at) %>%
    group_by(user_id) %>%
    mutate(phase = phase, index = row_number()) %>%
    ungroup()
}

# Load each phase
pre <- load_phase("likert_pre", "pre")
mid <- load_phase("likert_mid", "mid")
post <- load_phase("likert_post", "post")

# Combine all
all_data <- bind_rows(pre, mid, post) %>%
  mutate(created_at = ymd_hms(created_at))

# Create interleaved step label: pre_1, mid_1, post_1, ..., post_4
all_data <- all_data %>%
  mutate(step = paste0(phase, "_", index))

# Normalize time per user relative to their first submission
all_data <- all_data %>%
  group_by(user_id) %>%
  arrange(created_at) %>%
  mutate(rel_time = as.numeric(difftime(created_at, min(created_at), units = "mins"))) %>%
  ungroup()

# Set ordered factor for correct x-axis sequencing
# Interleaved step order: pre_1, mid_1, post_1, ..., post_4
step_levels <- as.vector(t(outer(1:4, c("pre", "mid", "post"), function(i, p) paste0(p, "_", i))))
all_data$step <- factor(all_data$step, levels = step_levels)

# Plot progression
ggplot(all_data, aes(x = step, y = rel_time, group = user_id, color = as.factor(user_id))) +
  geom_line(linewidth = 1) +
  geom_point(size = 2.5) +
  labs(
    title = "User Progression Across All Steps (Relative Time)",
    x = "Step",
    y = "Time Since First Submission (minutes)",
    color = "User ID"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))



# Disconnect from database
dbDisconnect(con)

Data Integrity Assertions

Assertion 1: The pre-scores are not significantly different across conditions.
Assertion 2: The pre-scores are significantly different across conditions. Assertion 3: Participant has exactly 4 imi scores and are in the right order (lesson 0, 1, 2, 3) based on submission time

library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)
library(stringr)
library(purrr)

# STEP 1: Extract and reshape pre scores for conditions
condition_pre <- data %>%
  select(matches("likert_pre_condition\\d+")) %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = "condition",
    names_pattern = "likert_pre_condition(\\d+)",
    values_to = "score"
  ) %>%
  mutate(condition = paste0("Condition ", condition))

# STEP 2: Extract and reshape pre scores for lessons
lesson_pre <- data %>%
  select(matches("likert_pre_lesson\\d+")) %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = "lesson",
    names_pattern = "likert_pre_lesson(\\d+)",
    values_to = "score"
  ) %>%
  mutate(lesson = paste0("Lesson ", lesson))

# STEP 3: Plot pre scores per condition
plot_conditions <- ggplot(condition_pre, aes(x = condition, y = score, fill = condition)) +
  geom_boxplot(alpha = 0.6, outlier.shape = NA) +
  geom_dotplot(binaxis = "y", stackdir = "center", dotsize = 0.5, aes(color = condition)) +
  labs(title = "Pre Scores by Condition", x = "Condition", y = "Pre Score") +
  theme_minimal() +
  theme(legend.position = "none")

# STEP 4: Plot pre scores per LESSON
plot_lessons <- ggplot(lesson_pre, aes(x = lesson, y = score, fill = lesson)) +
  geom_boxplot(alpha = 0.6, outlier.shape = NA) +
  geom_dotplot(binaxis = "y", stackdir = "center", dotsize = 0.5, aes(color = lesson)) +
  labs(title = "Pre Scores by Lesson", x = "Lesson", y = "Pre Score") +
  theme_minimal() +
  theme(legend.position = "none")

# Show plots
print(plot_conditions)
print(plot_lessons)

library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)

# Reshape pre condition scores
condition_pre <- data %>%
  select(matches("likert_pre_condition\\d+")) %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = "condition",
    names_pattern = "likert_pre_condition(\\d+)",
    values_to = "score"
  ) %>%
  mutate(condition = factor(paste0("Condition ", condition)))

# Kruskal-Wallis test
kw <- kruskal.test(score ~ condition, data = condition_pre)

cat("Kruskal-Wallis test p-value:", kw$p.value, "\n")

# If significant, run post-hoc pairwise Wilcoxon tests
if (kw$p.value < 0.05) {
  cat("Significant differences found — pairwise Wilcoxon tests:\n")
  pw <- pairwise.wilcox.test(condition_pre$score, condition_pre$condition, p.adjust.method = "BH")
  print(pw$p.value)
} else {
  cat("No significant differences between conditions for pre scores.\n")
}

library(readr)
library(dplyr)
library(tidyr)

# Reshape pre lesson scores
lesson_pre <- data %>%
  select(matches("likert_pre_lesson\\d+")) %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = "lesson",
    names_pattern = "likert_pre_lesson(\\d+)",
    values_to = "score"
  ) %>%
  mutate(lesson = factor(paste0("Lesson ", lesson)))

# Kruskal-Wallis test
kw <- kruskal.test(score ~ lesson, data = lesson_pre)

cat("Kruskal-Wallis test p-value (by lesson):", kw$p.value, "\n")

# Post-hoc pairwise Wilcoxon if significant
if (kw$p.value < 0.05) {
  cat("Significant differences found — pairwise Wilcoxon tests:\n")
  pw <- pairwise.wilcox.test(lesson_pre$score, lesson_pre$lesson, p.adjust.method = "BH")
  print(pw$p.value)
} else {
  cat("No significant differences between lessons for pre scores.\n")
}

Certainty

! Certainty per Condition

library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)
library(stringr)

# Extract condition-related likert columns
condition_data <- data %>% select(matches("likert_.*_condition"))

# Reshape to long format
long_condition_data <- condition_data %>%
  pivot_longer(cols = everything(),
               names_to = c("phase", "condition"),
               names_pattern = "likert_(pre|mid|post)_condition(\\d+)",
               values_to = "score") %>%
  mutate(phase = factor(phase, levels = c("pre", "mid", "post")),
         condition = paste0("condition ", condition))

# Summarize by phase and condition
summary_data <- long_condition_data %>%
  group_by(phase, condition) %>%
  summarise(mean_score = mean(score, na.rm = TRUE), .groups = "drop")

# Line plot: 4 lines (conditions), x-axis is phase
ggplot(summary_data, aes(x = phase, y = mean_score, group = condition, color = condition)) +
  geom_line(size = 1.2) +
  geom_point(size = 3) +
  labs(title = "Mean Likert Scores per condition Over Phases",
       x = "Phase",
       y = "Mean Likert Score",
       color = "condition") +
  theme_minimal()

condition_data <- data %>% select(matches("likert_.*_condition"))

long_condition_data <- condition_data %>%
  pivot_longer(
    cols = everything(),
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    condition = factor(paste0("condition ", condition), levels = paste0("condition ", 1:4))
  )

# Calculate means for labels
means <- long_condition_data %>%
  group_by(condition, phase) %>%
  summarise(mean_score = mean(score, na.rm = TRUE), .groups = "drop")

ggplot(long_condition_data, aes(x = phase, y = score, fill = phase)) +
  geom_boxplot(position = position_dodge(width = 0.8), alpha = 0.5, outlier.shape = NA) +
  geom_jitter(aes(color = phase), position = position_jitterdodge(jitter.width = 0.15, dodge.width = 0.8),
              size = 2, alpha = 0.7) +
  geom_text(data = means, aes(x = phase, y = mean_score + 0.15, label = round(mean_score, 2)),
            position = position_dodge(width = 0.8), inherit.aes = FALSE,
            size = 3, fontface = "bold", color = "black") +
  facet_wrap(~ condition, nrow = 1) +  # All conditions in one row, visually grouped by facets
  scale_fill_manual(values = c("pre" = "#a6cee3", "mid" = "#1f78b4", "post" = "#b2df8a")) +
  scale_color_manual(values = c("pre" = "#a6cee3", "mid" = "#1f78b4", "post" = "#b2df8a")) +
  labs(
    title = "Likert Scores by Phase and condition (overall)",
    x = "Phase",
    y = "Likert Score",
    fill = "Phase",
    color = "Phase"
  ) +
  theme_minimal() +
  theme(
    strip.text = element_text(size = 12, face = "bold"), # facet label style
    legend.position = "top"
  )


# Prepare condition_order in long format
condition_order_long <- data %>%
  mutate(id = row_number()) %>%
  separate(condition_order, into = paste0("lesson_", 1:4), sep = ",", convert = TRUE) %>%
  pivot_longer(
    cols = starts_with("lesson_"),
    names_to = "lesson",
    names_pattern = "lesson_(\\d+)",
    values_to = "condition_index"
  ) %>%
  mutate(
    lesson = as.integer(lesson),
    condition = factor(paste0("condition ", condition_index + 1), levels = paste0("condition ", 1:4))
  ) %>%
  select(id, lesson, condition)

# Prepare long_condition_data with participant id
long_condition_data <- data %>%
  mutate(id = row_number()) %>%
  select(id, matches("likert_.*_condition")) %>%
  pivot_longer(
    cols = -id,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    condition = factor(paste0("condition ", condition), levels = paste0("condition ", 1:4))
  )

# Join lesson info to condition data
long_condition_with_lesson <- long_condition_data %>%
  left_join(condition_order_long, by = c("id", "condition"))

# Titles for each lesson
comparison_titles <- paste("Lesson", 1:4)

# Generate plots for each lesson and print
for (lesson_num in 1:4) {
  plot_data <- long_condition_with_lesson %>% filter(lesson == lesson_num)
  
  means_lesson <- plot_data %>%
    group_by(condition, phase) %>%
    summarise(mean_score = mean(score, na.rm = TRUE), .groups = "drop")
  
  p <- ggplot(plot_data, aes(x = phase, y = score, fill = phase)) +
    geom_boxplot(position = position_dodge(width = 0.8), alpha = 0.5, outlier.shape = NA) +
    geom_jitter(aes(color = phase), position = position_jitterdodge(jitter.width = 0.15, dodge.width = 0.8),
                size = 2, alpha = 0.7) +
    geom_text(data = means_lesson, aes(x = phase, y = mean_score + 0.15, label = round(mean_score, 2)),
              position = position_dodge(width = 0.8), inherit.aes = FALSE,
              size = 3, fontface = "bold", color = "black") +
    facet_wrap(~ condition, nrow = 1) +
    scale_fill_manual(values = c("pre" = "#a6cee3", "mid" = "#1f78b4", "post" = "#b2df8a")) +
    scale_color_manual(values = c("pre" = "#a6cee3", "mid" = "#1f78b4", "post" = "#b2df8a")) +
    labs(
      title = paste("Likert Scores by Phase and condition -", comparison_titles[lesson_num]),
      x = "Phase",
      y = "Likert Score",
      fill = "Phase",
      color = "Phase"
    ) +
    theme_minimal() +
    theme(
      strip.text = element_text(size = 12, face = "bold"),
      legend.position = "top"
    )
  
  print(p)
}

! Certainty per Condition - ANOVA

library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)

# Reshape condition-related Likert columns
condition_data <- data %>% select(matches("likert_.*_condition"))

long_condition_data <- condition_data %>%
  pivot_longer(
    cols = everything(),
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    condition = factor(paste0("condition ", condition), levels = paste0("condition ", 1:4))
  )

print("\n\nIs there a difference between conditions for pre, mid or post values?")
# Function to run Kruskal-Wallis + pairwise Wilcoxon for one phase
test_phase <- function(phase_name) {
  df <- long_condition_data %>% filter(phase == phase_name)
  
  kw <- kruskal.test(score ~ condition, data = df)
  
  cat("\nPhase:", phase_name, "\n")
  cat("Kruskal-Wallis p-value:", kw$p.value, "\n")
  
  if (kw$p.value < 0.05) {
    cat("Significant difference found, running pairwise Wilcoxon tests:\n")
    pw <- pairwise.wilcox.test(df$score, df$condition, p.adjust.method = "BH")
    print(pw$p.value)
  } 
}

# Run tests for each phase
for (ph in levels(long_condition_data$phase)) {
  test_phase(ph)
}

library(readr)
library(dplyr)
library(tidyr)
library(stringr)
library(purrr)

# Step 1: Reshape likert columns to long format
condition_data <- data %>%
  select(condition_order, matches("likert_.*_condition\\d+"))

long_condition_data <- condition_data %>%
  pivot_longer(
    cols = -condition_order,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    condition = as.integer(condition),
    phase = factor(phase, levels = c("pre", "mid", "post"))
  )

# Step 2: Map each condition to its lesson using condition_order
long_condition_data <- long_condition_data %>%
  mutate(
    lesson = map2_int(condition_order, condition, ~ {
      # Split the condition_order string into numeric vector
      lesson_vector <- as.integer(str_split(.x, ",", simplify = TRUE))
      # Return the lesson index for that condition
      lesson_vector[.y + 1]  # condition is 0-based index in condition_order
    })
  )


# Step 3: Function to test within one lesson
test_lesson_phases <- function(lesson_id) {
  cat("\n\nLesson:", lesson_id, "")
  
  lesson_data <- long_condition_data %>% filter(lesson == lesson_id)
  
  for (ph in levels(lesson_data$phase)) {
    df <- lesson_data %>% filter(phase == ph)
    
    kw <- kruskal.test(score ~ factor(condition), data = df)
    
    cat("\nPhase:", ph, "\n")
    cat("Kruskal-Wallis p-value:", kw$p.value, "")
    
    if (kw$p.value < 0.05) {
      cat("Significant difference found, running pairwise Wilcoxon tests:\n")
      pw <- pairwise.wilcox.test(df$score, factor(df$condition), p.adjust.method = "BH")
      print(pw$p.value)
    } 
  }
}

print("\n\nIs there a difference between conditions for pre, mid or post values in certain lessons?")
# Step 4: Run the test for each lesson (0 to 3)
for (les in 0:3) {
  test_lesson_phases(les)
}

Certainty per Lesson

library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)

# Extract lesson-related likert columns
lesson_data <- data %>% select(matches("likert_.*_lesson"))

# Reshape to long format
long_lesson_data <- lesson_data %>%
  pivot_longer(cols = everything(),
               names_to = c("phase", "lesson"),
               names_pattern = "likert_(pre|mid|post)_lesson(\\d+)",
               values_to = "score") %>%
  mutate(phase = factor(phase, levels = c("pre", "mid", "post")),
         lesson = paste0("lesson ", lesson))

# Summarize by phase and lesson
summary_data <- long_lesson_data %>%
  group_by(phase, lesson) %>%
  summarise(mean_score = mean(score, na.rm = TRUE), .groups = "drop")

# Line plot: 4 lines (lessons), x-axis is phase
ggplot(summary_data, aes(x = phase, y = mean_score, group = lesson, color = lesson)) +
  geom_line(size = 1.2) +
  geom_point(size = 3) +
  labs(title = "Mean Likert Scores per lesson Over Phases",
       x = "Phase",
       y = "Mean Likert Score",
       color = "lesson") +
  theme_minimal()

library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)
library(ggplot2)
library(ggsignif)

lesson_data <- data %>% select(matches("likert_.*_lesson"))

long_lesson_data <- lesson_data %>%
  pivot_longer(
    cols = everything(),
    names_to = c("phase", "lesson"),
    names_pattern = "likert_(pre|mid|post)_lesson(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    lesson = factor(paste0("Lesson ", lesson), levels = paste0("Lesson ", 1:4))
  )

# Calculate means for labels
means <- long_lesson_data %>%
  group_by(lesson, phase) %>%
  summarise(mean_score = mean(score, na.rm = TRUE), .groups = "drop")

ggplot(long_lesson_data, aes(x = phase, y = score, fill = phase)) +
  geom_boxplot(position = position_dodge(width = 0.8), alpha = 0.5, outlier.shape = NA) +
  geom_jitter(aes(color = phase), position = position_jitterdodge(jitter.width = 0.15, dodge.width = 0.8),
              size = 2, alpha = 0.7) +
  geom_text(data = means, aes(x = phase, y = mean_score + 0.15, label = round(mean_score, 2)),
            position = position_dodge(width = 0.8), inherit.aes = FALSE,
            size = 3, fontface = "bold", color = "black") +
  geom_signif(
    comparisons = list(c("post")),
    map_signif_level = TRUE
  ) +
  facet_wrap(~ lesson, nrow = 1) +  # All lessons in one row, visually grouped by facets
  scale_fill_manual(values = c("pre" = "#a6cee3", "mid" = "#1f78b4", "post" = "#b2df8a")) +
  scale_color_manual(values = c("pre" = "#a6cee3", "mid" = "#1f78b4", "post" = "#b2df8a")) +
  labs(
    title = "Likert Scores by Phase and Lesson",
    x = "Phase",
    y = "Likert Score",
    fill = "Phase",
    color = "Phase"
  ) +
  theme_minimal() +
  theme(
    strip.text = element_text(size = 12, face = "bold"), # facet label style
    legend.position = "top"
  )

library(ggplot2)
library(ggsignif)

# Your long_lesson_data is already fine

# Define lesson comparisons (pairwise between all 4 lessons)
lesson_comparisons <- combn(levels(long_lesson_data$lesson), 2, simplify = FALSE)

# Plot: X = lesson, facet by phase
ggplot(long_lesson_data, aes(x = lesson, y = score, fill = lesson)) +
  geom_boxplot(alpha = 0.5, outlier.shape = NA) +
  geom_jitter(aes(color = lesson), position = position_jitter(width = 0.15), size = 2, alpha = 0.7) +
  geom_signif(
    comparisons = lesson_comparisons,
    step_increase = 0.2,
    map_signif_level=c("***"=0.001,"**"=0.01, "*"=0.05, " "=2),
    test = "wilcox.test"
  ) +
  facet_wrap(~ phase, nrow = 1) +
  scale_fill_brewer(palette = "Set2") +
  scale_color_brewer(palette = "Set2") +
  labs(
    title = "Likert Scores Across Lessons (by Phase)",
    x = "Lesson",
    y = "Likert Score",
    fill = "Lesson",
    color = "Lesson"
  ) +
  theme_minimal() +
  theme(
    strip.text = element_text(size = 12, face = "bold"),
    legend.position = "top"
  )

Certainty per Lesson - ANOVA

Finding Kruskal-Wallis shows there is significant difference between lessons in their pre scores (p < 0.05) and post scores (p < 0.05). Pairwise Wilcoxon test shows Lesson 4 is significantly different from Lessons 1 and 2 in pre scores (p < 0.05) and Lesson 1 in post scores (p < 0.05).


library(readr)
library(dplyr)
library(tidyr)

# Select lesson-related Likert columns
lesson_data <- data %>% select(matches("likert_.*_lesson"))

# Reshape to long format: id, phase, lesson, score
long_lesson_data <- lesson_data %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = c("phase", "lesson"),
    names_pattern = "likert_(pre|mid|post)_lesson(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    lesson = paste0("Lesson ", lesson)
  )

# Run Kruskal-Wallis test for each phase comparing lessons
kruskal_phase <- long_lesson_data %>%
  group_by(phase) %>%
  summarise(
    kruskal_p = kruskal.test(score ~ lesson)$p.value
  )

print(kruskal_phase)

# Only for phases with significant Kruskal-Wallis results
significant_phases <- kruskal_phase %>% filter(kruskal_p < 0.05) %>% pull(phase)

for (ph in significant_phases) {
  cat("\n=== Phase:", ph, "===\n")
  df <- long_lesson_data %>% filter(phase == ph)
  
  # Pairwise Wilcoxon
  pairwise_result <- pairwise.wilcox.test(df$score, df$lesson, p.adjust.method = "BH")
  
  print(pairwise_result$p.value)
}

Certainty Deltas per Condition

library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)

# Extract and reshape condition-related likert columns
condition_data <- data %>% select(matches("likert_.*_condition"))

long_condition_data <- condition_data %>%
  pivot_longer(
    cols = everything(),
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    condition = paste0("condition ", condition)
  )

# Compute mean scores per phase and condition
mean_scores <- long_condition_data %>%
  group_by(condition, phase) %>%
  summarise(mean_score = mean(score, na.rm = TRUE), .groups = "drop")

# Join with pre scores to compute difference
pre_scores <- mean_scores %>% filter(phase == "pre") %>%
  rename(pre_score = mean_score) %>%
  select(condition, pre_score)

diff_data <- mean_scores %>%
  left_join(pre_scores, by = "condition") %>%
  mutate(diff_from_pre = mean_score - pre_score)

# Plot differences, with pre as baseline (0), mid/post as deltas
ggplot(diff_data, aes(x = phase, y = diff_from_pre, group = condition, color = condition)) +
  geom_line(size = 1.2) +
  geom_point(size = 3) +
  labs(
    title = "Mean Likert Score Changes Relative to Pre",
    x = "Phase",
    y = "Score Difference from Pre",
    color = "condition"
  ) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray") +
  theme_minimal()
library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)

# Extract and reshape condition-related Likert columns
condition_data <- data %>% select(matches("likert_.*_condition"))

# Long format with phase and condition
long_condition_data <- condition_data %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    condition = paste0("condition ", condition)
  )

# Calculate differences: mid-pre, post-pre, and post-mid
pivoted <- long_condition_data %>%
  pivot_wider(names_from = phase, values_from = score) %>%
  mutate(
    diff_mid = mid - pre,
    diff_post = post - pre,
    diff_mid_post = post - mid
  ) %>%
  pivot_longer(
    cols = c(diff_mid, diff_post, diff_mid_post),
    names_to = "phase",
    values_to = "diff_from_pre"
  ) %>%
  mutate(
    phase = recode(phase,
                   diff_mid = "mid-pre",
                   diff_post = "post-pre",
                   diff_mid_post = "post-mid"),
    phase = factor(phase, levels = c("mid-pre", "post-pre", "post-mid"))
  )

# Calculate means for labels/points
means <- pivoted %>%
  group_by(condition, phase) %>%
  summarise(mean_val = mean(diff_from_pre, na.rm = TRUE), .groups = "drop")

# Plot all conditions side by side, phase as fill dodge, with mean points
ggplot(pivoted, aes(x = condition, y = diff_from_pre, fill = phase)) +
  geom_boxplot(position = position_dodge(width = 0.8), alpha = 0.5, outlier.shape = NA) +
  geom_jitter(aes(color = phase), position = position_jitterdodge(jitter.width = 0.2, dodge.width = 0.8), alpha = 0.7, size = 2) +
  geom_point(data = means, aes(x = condition, y = mean_val, group = phase),
             position = position_dodge(width = 0.8), color = "black", size = 3, shape = 18) +
  scale_y_continuous(limits = c(-15, 15)) +
  labs(
    title = "Differences between Phases per condition",
    x = "condition",
    y = "Score Difference",
    fill = "Phase Comparison",
    color = "Phase Comparison"
  ) +
  theme_minimal() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray")

Certainty Deltas per Condition - ANOVA

library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)

# Extract and reshape only condition-related Likert columns
condition_data <- data %>% select(matches("likert_.*_condition"))

# Long format with phase and condition
long_condition_data <- condition_data %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    condition = paste0("condition ", condition)
  )

# Calculate differences from pre per individual and condition
delta_data <- long_condition_data %>%
  pivot_wider(names_from = phase, values_from = score) %>%
  mutate(
    diff_mid = mid - pre,
    diff_post = post - pre
  ) %>%
  pivot_longer(
    cols = c(diff_mid, diff_post),
    names_to = "phase",
    values_to = "diff_from_pre"
  ) %>%
  mutate(
    phase = recode(phase, diff_mid = "mid", diff_post = "post"),
    phase = factor(phase, levels = c("mid", "post"))
  )

# Perform Shapiro-Wilk test by condition and phase
normality_tests <- delta_data %>%
  group_by(condition, phase) %>%
  summarise(
    p_value = shapiro.test(diff_from_pre)$p.value,
    .groups = "drop"
  )


print("Shapiro-Wilk Normality Test (p < 0.05 = not normal):")
print(normality_tests)
library(readr)
library(dplyr)
library(tidyr)
# Select condition-related Likert columns
condition_data <- data %>% select(matches("likert_.*_condition"))

# Reshape to long format: id, phase, condition, score
long_condition_data <- condition_data %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    condition = paste0("condition ", condition)
  )

# Run Kruskal-Wallis test for each phase comparing conditions
kruskal_phase <- long_condition_data %>%
  group_by(phase) %>%
  summarise(
    kruskal_p = kruskal.test(score ~ condition)$p.value
  )

print(kruskal_phase)

Certainty Deltas per Lesson

library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)

# Extract and reshape lesson-related likert columns
condition_data <- data %>% select(matches("likert_.*_lesson"))

long_lesson_data <- condition_data %>%
  pivot_longer(
    cols = everything(),
    names_to = c("phase", "lesson"),
    names_pattern = "likert_(pre|mid|post)_lesson(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    lesson = paste0("condition ", lesson)
  )

# Compute mean scores per phase and lesson
mean_scores <- long_lesson_data %>%
  group_by(lesson, phase) %>%
  summarise(mean_score = mean(score, na.rm = TRUE), .groups = "drop")

# Join with pre scores to compute difference
pre_scores <- mean_scores %>% filter(phase == "pre") %>%
  rename(pre_score = mean_score) %>%
  select(lesson, pre_score)

diff_data <- mean_scores %>%
  left_join(pre_scores, by = "lesson") %>%
  mutate(diff_from_pre = mean_score - pre_score)

# Plot differences, with pre as baseline (0), mid/post as deltas
ggplot(diff_data, aes(x = phase, y = diff_from_pre, group = lesson, color = lesson)) +
  geom_line(size = 1.2) +
  geom_point(size = 3) +
  labs(
    title = "Mean Likert Score Changes Relative to Pre",
    x = "Phase",
    y = "Score Difference from Pre",
    color = "Lesson"
  ) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray") +
  theme_minimal()
library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)


# Extract and reshape condition-related Likert columns
condition_data <- data %>% select(matches("likert_.*_lesson"))

# Long format with phase and condition
long_lesson_data <- condition_data %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = c("phase", "lesson"),
    names_pattern = "likert_(pre|mid|post)_lesson(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    condition = paste0("Lesson ", lesson)
  )

# Calculate differences: mid-pre, post-pre, and post-mid
pivoted <- long_lesson_data %>%
  pivot_wider(names_from = phase, values_from = score) %>%
  mutate(
    diff_mid = mid - pre,
    diff_post = post - pre,
    diff_mid_post = post - mid
  ) %>%
  pivot_longer(
    cols = c(diff_mid, diff_post, diff_mid_post),
    names_to = "phase",
    values_to = "diff_from_pre"
  ) %>%
  mutate(
    phase = recode(phase,
                   diff_mid = "mid-pre",
                   diff_post = "post-pre",
                   diff_mid_post = "post-mid"),
    phase = factor(phase, levels = c("mid-pre", "post-pre", "post-mid"))
  )

# Calculate means for labels/points
means <- pivoted %>%
  group_by(condition, phase) %>%
  summarise(mean_val = mean(diff_from_pre, na.rm = TRUE), .groups = "drop")

# Plot all conditions side by side, phase as fill dodge, with mean points
ggplot(pivoted, aes(x = condition, y = diff_from_pre, fill = phase)) +
  geom_boxplot(position = position_dodge(width = 0.8), alpha = 0.5, outlier.shape = NA) +
  geom_jitter(aes(color = phase), position = position_jitterdodge(jitter.width = 0.2, dodge.width = 0.8), alpha = 0.7, size = 2) +
  geom_point(data = means, aes(x = condition, y = mean_val, group = phase),
             position = position_dodge(width = 0.8), color = "black", size = 3, shape = 18) +
  scale_y_continuous(limits = c(-15, 15)) +
  labs(
    title = "Differences between Phases per Lesson",
    x = "Lesson",
    y = "Score Difference",
    fill = "Phase Comparison",
    color = "Phase Comparison"
  ) +
  theme_minimal() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray")

Certainty Deltas per Lesson - ANOVA

Certainty for all Lessons and conditions


library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)
library(stringr)

lesson_data <- data %>% 
  select(matches("likert_.*_lesson")) %>%
  mutate(id = row_number())  # Add this line

long_lesson_data <- lesson_data %>%
  pivot_longer(
    cols = -id,  # Exclude 'id' from pivoting
    names_to = c("phase", "lesson"),
    names_pattern = "likert_(pre|mid|post)_lesson(\\d+)",
    values_to = "score"
  ) %>%
  mutate(
    phase = factor(phase, levels = c("pre", "mid", "post")),
    lesson = paste0("Lesson ", lesson)
  )

# Split 'condition_order' into separate rows
condition_order_long <- data %>%
  mutate(id = row_number()) %>%
  separate(condition_order, into = paste0("lesson_", 1:4), sep = ",", convert = TRUE) %>%
  pivot_longer(
    cols = starts_with("lesson_"),
    names_to = "lesson",
    names_pattern = "lesson_(\\d+)",
    values_to = "condition_index"
  ) %>%
  mutate(
    lesson = paste0("Lesson ", as.integer(lesson)),
    condition = paste0("condition ", condition_index + 1)
  ) %>%
  select(id, lesson, condition)

# ✅ JOIN to get full combined data
combined <- long_lesson_data %>%
  left_join(condition_order_long, by = c("id", "lesson")) %>%
  mutate(condition_lesson = paste(condition, lesson, sep = " - "))

# Join lesson scores with their corresponding condition (via condition_order)
combined <- combined %>%
  mutate(condition_lesson = paste(condition, lesson, sep = " - "))


# Step 4: Get means for label
means <- combined %>%
  group_by(condition_lesson, phase) %>%
  summarise(mean_score = mean(score, na.rm = TRUE), .groups = "drop")

# Step 5: Plot
# Define color scales
fill_colors <- c("pre" = "#a6cee3", "mid" = "#1f78b4", "post" = "#b2df8a")
text_color <- "black"

# Function to generate a plot for a specific phase
plot_by_phase <- function(phase_input) {
  # Filter combined data and means for the given phase
  plot_data <- combined %>% filter(phase == phase_input)
  phase_means <- means %>% filter(phase == phase_input)
  
  ggplot(plot_data, aes(x = phase, y = score, fill = phase)) +
    geom_boxplot(alpha = 0.5, outlier.shape = NA) +
    geom_jitter(aes(color = phase), position = position_jitter(width = 0.15),
                size = 1.5, alpha = 0.7) +
    geom_text(data = phase_means, aes(x = phase, y = mean_score + 0.15, label = round(mean_score, 2)),
              inherit.aes = FALSE,
              size = 2.5, fontface = "bold", color = text_color) +
    facet_wrap(~ condition_lesson, ncol = 4) +
    scale_fill_manual(values = fill_colors) +
    scale_color_manual(values = fill_colors) +
    labs(
      title = paste("Likert Scores for", tools::toTitleCase(phase_input), "Phase"),
      x = NULL,
      y = "Likert Score",
      fill = "Phase",
      color = "Phase"
    ) +
    theme_minimal() +
    theme(
      axis.text.x = element_blank(),
      axis.ticks.x = element_blank(),
      strip.text = element_text(size = 10, face = "bold"),
      legend.position = "none"
    )
}

# Now generate plots
plot_pre <- plot_by_phase("pre")
plot_mid <- plot_by_phase("mid")
plot_post <- plot_by_phase("post")

# Print them one after another (in an R script or notebook)
print(plot_pre)
print(plot_mid)
print(plot_post)


library(ggplot2)
library(tidyr)
library(dplyr)
library(patchwork)

means_heatmap <- means %>%
  separate(condition_lesson, into = c("condition", "lesson"), sep = " - ") %>%
  mutate(
    condition = factor(str_remove(condition, "condition "), levels = c("1", "2", "3", "4")),
    lesson = factor(str_remove(lesson, "Lesson "), levels = c("1", "2", "3", "4")),
    phase = factor(phase, levels = c("pre", "mid", "post"))
  ) %>%
  complete(phase, condition, lesson)

min_score <- floor(min(means_heatmap$mean_score, na.rm = TRUE))
max_score <- ceiling(max(means_heatmap$mean_score, na.rm = TRUE))

plot_heatmap <- function(phase_name, show_x = TRUE, show_y = TRUE) {
  ggplot(means_heatmap %>% filter(phase == phase_name), aes(x = lesson, y = condition, fill = mean_score)) +
    geom_tile(color = "white") +
    geom_label(aes(label = round(mean_score, 2)), 
               fill = alpha("white", 0.5),   # faint white background
               color = "black", 
               size = 2,                    # smaller text size
               label.size = 0) +            # remove label border
    scale_fill_viridis_c(option = "C", direction = -1, limits = c(min_score, max_score), na.value = "grey90") +
    labs(title = paste(toupper(phase_name), "Phase"),
         x = ifelse(show_x, "Lesson", ""),
         y = ifelse(show_y, "condition", ""),
         fill = "Mean Score") +
    theme_minimal() +
    theme(
      axis.text.x = element_text(angle = 45, hjust = 1, size = 12),
      axis.text.y = element_text(size = 12),
      plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
      axis.title.x = element_text(size = 13, face = "bold"),
      axis.title.y = element_text(size = 13, face = "bold")
    )
}

# Show y-axis labels only on leftmost plot, x-axis only on bottom plots
heatmap_pre <- plot_heatmap("pre", show_x = FALSE, show_y = TRUE)
heatmap_mid <- plot_heatmap("mid", show_x = FALSE, show_y = FALSE)
heatmap_post <- plot_heatmap("post", show_x = TRUE, show_y = FALSE)

combined_heatmaps <- heatmap_pre + heatmap_mid + heatmap_post + 
  plot_layout(ncol = 3, guides = "collect") & 
  theme(legend.position = "right")

print(combined_heatmaps)

Certainty deltas for all Lessons and conditions

library(dplyr)
library(tidyr)
library(ggplot2)
library(patchwork)

# Spread phases wide
means_wide <- means_heatmap %>%
  select(condition, lesson, phase, mean_score) %>%
  pivot_wider(names_from = phase, values_from = mean_score)

# Calculate deltas as later phase minus earlier phase
deltas <- means_wide %>%
  mutate(
    mid_pre = mid - pre,        # Change after Inoculation
    post_pre = post - pre,      # Change after Inoculation and Strong attack
    post_mid = post - mid       # Change after Strong attack
  ) %>%
  select(condition, lesson, mid_pre, post_pre, post_mid) %>%
  pivot_longer(cols = c(mid_pre, post_pre, post_mid),
               names_to = "comparison",
               values_to = "delta")

# Named titles for the plots
comparison_titles <- c(
  mid_pre = "Change after\nInoculation",
  post_pre = "Change after\nInoculation and\nStrong attack",
  post_mid = "Change after\nStrong attack"
)

plot_delta_heatmap <- function(comp_name) {
  ggplot(deltas %>% filter(comparison == comp_name), aes(x = lesson, y = condition, fill = delta)) +
    geom_tile(color = "white") +
    geom_label(aes(label = round(delta, 2)), 
               fill = alpha("white", 0.5), 
               color = "black", 
               size = 2, 
               label.size = 0) +
    scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0,
                         limits = c(min(deltas$delta, na.rm = TRUE), max(deltas$delta, na.rm = TRUE)),
                         na.value = "grey90") +
    labs(
      title = comparison_titles[comp_name],
      x = ifelse(comp_name == "mid_pre", "Lesson", ""),
      y = ifelse(comp_name == "mid_pre", "condition", ""),
      fill = "Delta"
    ) +
    theme_minimal() +
    theme(
      axis.text.x = element_text(angle = 45, hjust = 1, size = 12),
      axis.text.y = element_text(size = 12),
      plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
      axis.title.x = element_text(size = 13, face = "bold"),
      axis.title.y = element_text(size = 13, face = "bold")
    )
}

heatmap_mid_pre <- plot_delta_heatmap("mid_pre")
heatmap_post_pre <- plot_delta_heatmap("post_pre")
heatmap_post_mid <- plot_delta_heatmap("post_mid")

combined_deltas <- heatmap_mid_pre +  heatmap_post_mid + heatmap_post_pre +
  plot_layout(ncol = 3, guides = "collect") & 
  theme(legend.position = "right")

print(combined_deltas)

library(dplyr)
library(tidyr)
library(ggplot2)
library(patchwork)
library(stringr)

# Assuming you have 'combined' dataframe with participant_id, condition, lesson, phase, score

# Pivot wider to get pre, mid, post scores per participant-condition-lesson
participant_wide <- combined %>%
  select(id, condition, lesson, phase, score) %>%
  pivot_wider(names_from = phase, values_from = score)

# Calculate participant-level deltas (later - earlier)
participant_deltas <- participant_wide %>%
  mutate(
    mid_pre = mid - pre,
    post_pre = post - pre,
    post_mid = post - mid
  ) %>%
  select(id, condition, lesson, mid_pre, post_pre, post_mid) %>%
  pivot_longer(cols = c(mid_pre, post_pre, post_mid),
               names_to = "comparison",
               values_to = "delta")

# Fix factors for plotting
participant_deltas <- participant_deltas %>%
  mutate(
    condition = factor(str_remove(condition, "condition "), levels = c("1", "2", "3", "4")),
    lesson = factor(str_remove(lesson, "Lesson "), levels = c("1", "2", "3", "4")),
    comparison = factor(comparison, levels = c("mid_pre", "post_pre", "post_mid"))
  )

# Named titles for the plots
comparison_titles <- c(
  mid_pre = "Change after\nInoculation",
  post_pre = "Change after\nInoculation and\nStrong attack",
  post_mid = "Change after\nStrong attack"
)

# Plotting function for boxplots + scatter
plot_delta_boxplots <- function(comp_name) {
  df <- participant_deltas %>% filter(comparison == comp_name)
  
  ggplot(df, aes(x = lesson, y = delta)) +
    geom_boxplot(outlier.shape = NA, fill = "#a6cee3", alpha = 0.5) +
    geom_jitter(width = 0.2, alpha = 0.7, size = 1.5, color = "#1f78b4") +
    facet_wrap(~condition, nrow = 4, ncol = 1, strip.position = "right") +
    ylim(-15, 15) +    # Fixed y-axis scale here
    labs(
      title = comparison_titles[comp_name],
      x = "Lesson",
      y = "Delta Score"
    ) +
    theme_minimal() +
    theme(
      strip.text.y = element_text(angle = 0, size = 12, face = "bold"),
      plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
      axis.text.x = element_text(angle = 45, hjust = 1)
    )
}


# Generate plots
plot_mid_pre <- plot_delta_boxplots("mid_pre")
plot_post_pre <- plot_delta_boxplots("post_pre")
plot_post_mid <- plot_delta_boxplots("post_mid")

# Combine plots side by side with shared legend area (no legend here actually)
combined_boxplots <- plot_mid_pre + plot_post_pre + plot_post_mid + 
  plot_layout(ncol = 3, guides = "collect") & 
  theme(legend.position = "bottom")

# Show combined plot
print(combined_boxplots)

Resistance to Persuasion (Certainty mid-post)

! All certainty deltas

# Step 1: Reshape and compute differences
all_certainty_deltas <- data %>%
  select(matches("likert_(mid|post)_condition\\d+")) %>%
  mutate(participant_id = row_number()) %>%
  pivot_longer(
    cols = -participant_id,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  pivot_wider(names_from = phase, values_from = score) %>%
  mutate(
    diff = post - mid,
    condition = case_when(
      condition == "1" ~ "Control",
      condition == "2" ~ "Reading",
      condition == "3" ~ "Writing",
      condition == "4" ~ "Chatbot",
      TRUE ~ condition
    )
  ) %>%
  select(participant_id, condition, diff) %>%
  pivot_wider(names_from = condition, values_from = diff)

# Step 2: View the result
print(all_certainty_deltas)

# Optional: Save to CSV
write.csv(all_certainty_deltas, "participant_differences_by_condition.csv", row.names = FALSE)

!! Resistance to Persuasion per Condition

!! Resistance to Persuasion per Condition - ANOVA

Finding: We performed a Shapiro-Wilk normality test, which determined that the certainty scores are not normally distributed in either of the conditions (p < 0.01). Then, we performed Wilcoxon pairwise tests to compare the Chatbot condition to each of the three other condition. Talking to Forty the chatbot made participants significantly more resistant to a strong counter-attitudinal message than the writing task (p = .02, r =.38), the reading task (p = .02, r = .34) and control condition (p = .02, r = .33).

Resistance to Persuasion per Lesson (all conditions)

library(dplyr)
library(tidyr)
library(ggplot2)
library(scales)
library(ggpubr)

plot_data <- data %>%
  select(matches("likert_(mid|post)_lesson\\d+")) %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = c("phase", "lesson"),
    names_pattern = "likert_(mid|post)_lesson(\\d+)",
    values_to = "score"
  ) %>%
  pivot_wider(names_from = phase, values_from = score) %>%
  mutate(
    diff_value = post - mid,
    condition = case_when(
      condition == "1" ~ "Control",
      condition == "2" ~ "Reading",
      condition == "3" ~ "Writing",
      condition == "4" ~ "Chatbot",
      TRUE ~ condition  # serves as a failsafe
    ),
    # Convert condition to a factor with specified levels
    condition = factor(condition, levels = c("Control", "Reading", "Writing", "Chatbot"))
  )
Error in `mutate()`:
ℹ In argument: `condition = case_when(...)`.
Caused by error in `case_when()`:
! Failed to evaluate the left-hand side of formula 1.
Caused by error:
! object 'condition' not found
Run `]8;;x-r-run:rlang::last_trace()rlang::last_trace()]8;;` to see where the error occurred.

Resistance to Persuasion per Lesson (all conditions) - ANOVA

library(dplyr)
library(rcompanion)

# ---- Normality check per lesson ----
normality_results <- plot_data %>%
  group_by(lesson) %>%
  summarise(
    shapiro_p = ifelse(length(diff_value) >= 3,  # Shapiro test requires at least 3 obs
                       shapiro.test(diff_value)$p.value,
                       NA_real_)
  )

print(normality_results)


# ---- Outlier detection and removal ----
plot_data_with_flags <- plot_data %>%
  group_by(lesson) %>%
  mutate(
    Q1 = quantile(diff_value, 0.25, na.rm = TRUE),
    Q3 = quantile(diff_value, 0.75, na.rm = TRUE),
    IQR = Q3 - Q1,
    lower_bound = Q1 - 1.5 * IQR,
    upper_bound = Q3 + 1.5 * IQR,
    is_outlier = diff_value < lower_bound | diff_value > upper_bound
  ) %>%
  ungroup()

print(table(plot_data_with_flags$is_outlier, plot_data_with_flags$lesson))
       
        Exercise and\nMental Health Binge Drinking Protecting Nature Dental Hygiene
  FALSE                          58             51                53             49
  TRUE                            0              0                 5              9
plot_data_clean <- plot_data_with_flags %>%
  filter(!is_outlier) %>%
  select(-Q1, -Q3, -IQR, -lower_bound, -upper_bound, -is_outlier)


# ---- Compute all pairwise comparisons with effect sizes ----
pairwise_comparisons <- combn(unique(plot_data_clean$lesson), 2, simplify = FALSE)

compute_pairwise_wilcox <- function(group1, group2, data) {
  subset <- data %>% filter(lesson %in% c(group1, group2))
  
  subset <- subset %>%
    mutate(group_numeric = ifelse(lesson == group1, 1, 2))
  
   test <- wilcox.test(diff_value ~ group_numeric,
                       data = subset, 
                       exact = FALSE, 
                       p.adjust.method = 'none',
                       alternative = "less")

  print(test)
  effect_size_r <- wilcoxonR(x = subset$diff_value, g = subset$group_numeric)
  
  tibble(
    group1 = group1,
    group2 = group2,
    p_value_uncorrected = test$p.value,
    effect_size_r = effect_size_r
  )
}

effect_size_results <- bind_rows(
  lapply(pairwise_comparisons, function(g) {
    compute_pairwise_wilcox(g[1], g[2], plot_data_clean)
  })
)

    Wilcoxon rank sum test with continuity correction

data:  diff_value by group_numeric
W = 1444, p-value = 0.4164
alternative hypothesis: true location shift is less than 0


    Wilcoxon rank sum test with continuity correction

data:  diff_value by group_numeric
W = 955, p-value = 0.0002137
alternative hypothesis: true location shift is less than 0


    Wilcoxon rank sum test with continuity correction

data:  diff_value by group_numeric
W = 635, p-value = 1.613e-07
alternative hypothesis: true location shift is less than 0


    Wilcoxon rank sum test with continuity correction

data:  diff_value by group_numeric
W = 912.5, p-value = 0.001617
alternative hypothesis: true location shift is less than 0


    Wilcoxon rank sum test with continuity correction

data:  diff_value by group_numeric
W = 627, p-value = 3.236e-06
alternative hypothesis: true location shift is less than 0


    Wilcoxon rank sum test with continuity correction

data:  diff_value by group_numeric
W = 970.5, p-value = 0.006495
alternative hypothesis: true location shift is less than 0
# ---- Now, adjust p-values only for pairs involving the NEW lesson (e.g., "Chatbot") ----
new_lesson <- "Chatbot"

# Filter rows with Chatbot involved
effect_size_new <- effect_size_results %>%
  filter(group1 == new_lesson | group2 == new_lesson) %>%
  mutate(
    p_adj_bonf_subset = p.adjust(p_value_uncorrected, method = "bonferroni"),
    p_adj_bh_subset = p.adjust(p_value_uncorrected, method = "BH")
  )

# Print full effect size results for reference
print(effect_size_results)

cat("\nAdjusted p-values ONLY for comparisons involving", new_lesson, ":\n")

Adjusted p-values ONLY for comparisons involving Chatbot :
print(effect_size_new)
NA

Overall Change in Certainty

Per Condition

library(dplyr)
library(tidyr)
library(ggplot2)
library(scales)
library(ggpubr)

# Data wrangling
plot_data <- data %>%
  select(matches("likert_(pre|post)_condition\\d+")) %>%
  mutate(id = row_number()) %>%
  pivot_longer(
    cols = -id,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  pivot_wider(names_from = phase, values_from = score) %>%
  mutate(
    diff_value = post - pre,
    condition = recode(condition,
      "1" = "Control",
      "2" = "Reading",
      "3" = "Writing",
      "4" = "Chatbot"
    ),
    condition = factor(condition, levels = c("Control", "Reading", "Writing", "Chatbot"))
  )

# Remove outliers (per condition, 1.5 × IQR rule)
plot_data_clean <- plot_data %>%
  group_by(condition) %>%
  mutate(
    Q1 = quantile(diff_value, 0.25, na.rm = TRUE),
    Q3 = quantile(diff_value, 0.75, na.rm = TRUE),
    IQR = Q3 - Q1,
    lower_bound = Q1 - 1.5 * IQR,
    upper_bound = Q3 + 1.5 * IQR,
    is_outlier = diff_value < lower_bound | diff_value > upper_bound
  ) %>%
  filter(!is_outlier) %>%
  ungroup() %>%
  select(-Q1, -Q3, -IQR, -lower_bound, -upper_bound, -is_outlier)

# Summary statistics (use cleaned data)
summary_stats_clean <- plot_data_clean %>%
  group_by(condition) %>%
  summarise(mean_val = mean(diff_value, na.rm = TRUE), .groups = "drop")

pvals <- data.frame(
  group1 = c("Control", "Reading", "Writing"),
  group2 = c("Chatbot", "Chatbot", "Chatbot"),
  p_value = c(0.01, 0.01, 0.01),  # replace with your actual p-values
  xstart = c(1, 2, 3),            # numeric x for groups; adjust if your factor levels differ
  xend = c(4, 4, 4),              # "Chatbot" assumed at position 4
  y = c(5, 6.8, 8.6)               # y positions for brackets, adjust based on your data range
)


# Plot using cleaned data
ggplot(plot_data_clean, aes(x = condition, y = diff_value, fill = condition)) +
  geom_boxplot(alpha = 0.5, outlier.shape = NA) +
  geom_dotplot(binaxis = "y", stackdir = "center", dotsize = 0.5, aes(color = condition)) +
  geom_point(data = summary_stats_clean, aes(x = condition, y = mean_val),
             color = "black", size = 3, shape = 18) +
  geom_text(data = summary_stats_clean, aes(x = condition, y = mean_val, label = round(mean_val, 2)),
            vjust = -1, color = "black", size = 4) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray") +
  scale_y_continuous(breaks = pretty_breaks(n = 10)) +
  labs(
    title = "Change in certainty after strong attack",
    x = "Condition",
    y = "Certainty score change",
    fill = "Condition",
    color = "Condition"
  ) +
  theme_minimal() +

  # Add brackets as lines
  geom_segment(data = pvals, aes(x = xstart, xend = xend, y = y, yend = y),
               inherit.aes = FALSE) +
  geom_segment(data = pvals, aes(x = xstart, xend = xstart, y = y, yend = y - 0.3),
               inherit.aes = FALSE) +
  geom_segment(data = pvals, aes(x = xend, xend = xend, y = y, yend = y - 0.3),
               inherit.aes = FALSE) +

  # Add p-value labels, show "p < 0.05" if below threshold, else blank
  geom_text(
    data = pvals,
    aes(x = (xstart + xend) / 2, y = y + 0.5,
        label = ifelse(p_value < 0.05, "*", "")),
    inherit.aes = FALSE,
    size = 3
  )

IMI Data

Overall Mindfort IMI

library(readr)
library(dplyr)
library(tidyr)
library(likert)

# Load and clean
imi <- read_csv("imi.csv", show_col_types = FALSE)
excluded_ids <- c("682f47a03095562bd581bd06", "674d7a89f564e8bbe0a7af1c", "65537e14439274fe5036b4d2")
imi_clean <- imi %>% filter(!prolific_id %in% excluded_ids)

# Select all lesson columns (lesson1 to lesson4)
lesson_cols <- imi_clean %>% 
  select(participant_id, matches("^imi\\d+_lesson[1-4]$"))

# Convert from wide to long format
long_data <- lesson_cols %>%
  pivot_longer(
    cols = -participant_id,
    names_to = c("question", "lesson"),
    names_pattern = "imi(\\d+)_lesson(\\d)",
    values_to = "response"
  ) %>%
  mutate(
    question = factor(paste0("Q", question), levels = paste0("Q", 1:25), ordered = TRUE),
    response = factor(as.numeric(response),
                      levels = 1:7,
                      labels = c("Extremely disagree", "Disagree", "Slightly disagree",
                                 "Neutral", "Slightly agree", "Agree", "Extremely agree"),
                      ordered = TRUE)
  )

# Convert to wide format for likert: rows = responses, columns = Q1–Q25
likert_ready <- long_data %>%
  arrange(participant_id, lesson) %>%
  group_by(participant_id, lesson) %>%
  mutate(response_id = cur_group_id()) %>%
  ungroup() %>%
  select(response_id, question, response) %>%
  pivot_wider(names_from = question, values_from = response) %>%
  select(paste0("Q", 1:25))  # Ensure correct order

# Convert to data.frame for likert package
likert_ready <- as.data.frame(likert_ready)

# Create and plot
likert_obj <- likert(likert_ready)
plot(likert_obj, group.order = paste0("Q", 1:25))


library(readr)
library(dplyr)
library(tidyr)

# Load and clean
imi <- read_csv("imi.csv", show_col_types = FALSE)
excluded_ids <- c("682f47a03095562bd581bd06", "674d7a89f564e8bbe0a7af1c", "65537e14439274fe5036b4d2")
imi_clean <- imi %>% filter(!prolific_id %in% excluded_ids)

# Select all lesson columns (lesson1 to lesson4)
lesson_cols <- imi_clean %>% 
  select(participant_id, matches("^imi\\d+_lesson[1-4]$"))

# Convert from wide to long format
long_data <- lesson_cols %>%
  pivot_longer(
    cols = -participant_id,
    names_to = c("question", "lesson"),
    names_pattern = "imi(\\d+)_lesson(\\d)",
    values_to = "response"
  ) %>%
  mutate(
    # Q1 is imi0, so Qn = imin-1, now label nicely again for reporting
    question = factor(paste0("Q", question), levels = paste0("Q", 1:25), ordered = TRUE)
  )

# Reverse-score the right questions
reverse_questions <- c("Q8", "Q12", "Q14", "Q18", "Q20", "Q24")
long_data <- long_data %>%
  mutate(
    response_num = as.numeric(response),
    response_num = ifelse(question %in% reverse_questions, 8 - response_num, response_num)
  )

# Calculate and print means for each question
question_means <- long_data %>%
  group_by(question) %>%
  summarise(mean = mean(response_num, na.rm = TRUE)) %>%
  arrange(question)

print(question_means)

IMI All Subscales per Condition

# Load libraries
library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)

# Define subscale map
subscale_map <- tribble(
  ~qn, ~subscale, ~reverse,
   1,     1,      FALSE,
   2,     1,      FALSE,
   3,     1,      TRUE,
   4,     1,      TRUE,
   5,     1,      FALSE,
   6,     1,      FALSE,
   7,     1,      FALSE,
   8,     2,      FALSE,
   9,     2,      FALSE,
  10,     2,      FALSE,
  11,     2,      FALSE,
  12,     2,      FALSE,
  13,     2,      TRUE,
  14,     3,      FALSE,
  15,     3,      TRUE,
  16,     3,      FALSE,
  17,     3,      FALSE,
  18,     3,      TRUE,
  19,     4,      FALSE,
  20,     4,      FALSE,
  21,     4,      FALSE,
  22,     4,      FALSE,
  23,     4,      FALSE,
  24,     4,      FALSE,
  25,     4,      FALSE
)

# Load and clean
imi <- read_csv("imi.csv", show_col_types = FALSE)
excluded_ids <- c("682f47a03095562bd581bd06", "674d7a89f564e8bbe0a7af1c", "65537e14439274fe5036b4d2")
imi_clean <- imi %>% filter(!prolific_id %in% excluded_ids)

# Prepare question columns
qnums_all <- 1:25
condition_cols <- imi_clean %>%
  select(
    participant_id,
    # Conditions 1–4
    all_of(unlist(lapply(1:4, function(c) paste0("imi", qnums_all, "_condition", c)))),
    # Condition 5 (_final)
    all_of(paste0("imi", qnums_all, "_final"))
  )

# Pivot to long format (handle both patterns)
long_data <- condition_cols %>%
  pivot_longer(
    cols = -participant_id,
    names_to = "item",
    values_to = "response"
  ) %>%
  filter(!is.na(response)) %>%
  mutate(
    qn = as.integer(str_extract(item, "\\d+")),
    condition = case_when(
      grepl("_condition(\\d)", item) ~ str_extract(item, "(?<=_condition)\\d"),
      grepl("_final$", item) ~ "5"
    ),
    response_num = as.numeric(response)
  ) %>%
  left_join(subscale_map, by = "qn") %>%
  mutate(
    response_num = ifelse(reverse, 8 - response_num, response_num)
  )

# Average per subscale
subscale_scores <- long_data %>%
  group_by(participant_id, condition, subscale) %>%
  summarise(avg_score = mean(response_num, na.rm = TRUE), .groups = "drop")

# 1.5*IQR outlier removal
filtered_scores <- subscale_scores %>%
  group_by(condition, subscale) %>%
  mutate(
    Q1 = quantile(avg_score, 0.25),
    Q3 = quantile(avg_score, 0.75),
    IQR = Q3 - Q1,
    lower = Q1 - 1.5 * IQR,
    upper = Q3 + 1.5 * IQR
  ) %>%
  filter(avg_score >= lower & avg_score <= upper) %>%
  ungroup()

# Mean labels
mean_labels <- filtered_scores %>%
  group_by(condition, subscale) %>%
  summarise(mean_val = mean(avg_score), .groups = "drop")

# Define subscale names
subscale_names <- c(
  "1" = "Interest/Enjoyment",
  "2" = "Perceived Competence",
  "3" = "Effort/Importance",
  "4" = "Value/Usefulness"
)

# Apply factor labels
filtered_scores <- filtered_scores %>%
  mutate(subscale = factor(subscale, levels = names(subscale_names), labels = subscale_names))

mean_labels <- mean_labels %>%
  mutate(subscale = factor(subscale, levels = names(subscale_names), labels = subscale_names))

# Define all condition labels including "Final"
condition_labels <- c(
  "1" = "Control",
  "2" = "Reading",
  "3" = "Writing",
  "4" = "Chatbot",
  "5" = "Final"
)

# Apply descriptive labels
filtered_scores <- filtered_scores %>%
  mutate(condition_label = factor(condition, levels = names(condition_labels), labels = condition_labels))

mean_labels <- mean_labels %>%
  mutate(condition_label = factor(condition, levels = names(condition_labels), labels = condition_labels))

# Plot with all 5 conditions
ggplot(filtered_scores, aes(x = subscale, y = avg_score, fill = condition_label)) +
  geom_boxplot(outlier.shape = NA, position = position_dodge(width = 0.75)) +
  geom_jitter(aes(color = condition_label), size = 1.5, alpha = 0.5,
              position = position_jitterdodge(jitter.width = 0.1, dodge.width = 0.75)) +
  geom_text(
    data = mean_labels,
    aes(label = round(mean_val, 2), y = mean_val),
    position = position_dodge(width = 0.75),
    vjust = -0.5,
    size = 3,
    color = "black"
  ) +
  labs(
    title = "Average Subscale Scores by Condition (Outliers Removed)",
    x = "Subscale",
    y = "Average Score (Reversed where needed)",
    fill = "Condition",
    color = "Condition"
  ) +
  theme_minimal()

IMI All Subscales per Condition - ANOVA

# Load libraries
library(readr)
library(dplyr)
library(tidyr)
library(ggplot2)
library(stats)

# Define subscale map
subscale_map <- tribble(
  ~qn, ~subscale, ~reverse,
   1,     1,      FALSE,
   2,     1,      FALSE,
   3,     1,      TRUE,
   4,     1,      TRUE,
   5,     1,      FALSE,
   6,     1,      FALSE,
   7,     1,      FALSE,
   8,     2,      FALSE,
   9,     2,      FALSE,
  10,     2,      FALSE,
  11,     2,      FALSE,
  12,     2,      FALSE,
  13,     2,      TRUE,
  14,     3,      FALSE,
  15,     3,      TRUE,
  16,     3,      FALSE,
  17,     3,      FALSE,
  18,     3,      TRUE,
  19,     4,      FALSE,
  20,     4,      FALSE,
  21,     4,      FALSE,
  22,     4,      FALSE,
  23,     4,      FALSE,
  24,     4,      FALSE,
  25,     4,      FALSE
)

# Load data
imi <- read_csv("imi.csv", show_col_types = FALSE)

# Exclude problematic participant IDs
excluded_ids <- c("682f47a03095562bd581bd06", "674d7a89f564e8bbe0a7af1c", "65537e14439274fe5036b4d2")
imi_clean <- imi %>% filter(!prolific_id %in% excluded_ids)

# Prepare column names
qnums_all <- 1:25
condition_1_4_cols <- paste0("imi", qnums_all, "_condition", rep(1:4, each = 25))
condition_5_cols <- paste0("imi", qnums_all, "_final")
all_imi_cols <- unique(c("participant_id", condition_1_4_cols, condition_5_cols))

# Select relevant columns
condition_cols <- imi_clean %>% select(any_of(all_imi_cols))

# Pivot longer to include both condition types
long_data <- condition_cols %>%
  pivot_longer(
    cols = -participant_id,
    names_to = "item",
    values_to = "response"
  ) %>%
  filter(!is.na(response)) %>%
  mutate(
    qn = as.integer(str_extract(item, "\\d+")),
    condition = case_when(
      grepl("_condition(\\d)", item) ~ str_extract(item, "(?<=_condition)\\d"),
      grepl("_final$", item) ~ "5"
    ),
    response_num = as.numeric(response)
  ) %>%
  left_join(subscale_map, by = "qn") %>%
  mutate(
    response_num = ifelse(reverse, 8 - response_num, response_num)
  )


# Average score per participant, condition, subscale
subscale_scores <- long_data %>%
  group_by(participant_id, condition, subscale) %>%
  summarise(avg_score = mean(response_num, na.rm = TRUE), .groups = "drop")


# Remove 1.5*IQR outliers within each condition and subscale
subscale_scores_filtered <- subscale_scores %>%
  group_by(condition, subscale) %>%
  mutate(
    Q1 = quantile(avg_score, 0.25, na.rm = TRUE),
    Q3 = quantile(avg_score, 0.75, na.rm = TRUE),
    IQR = Q3 - Q1,
    lower = Q1 - 1.5 * IQR,
    upper = Q3 + 1.5 * IQR
  ) %>%
  ungroup() %>%
  filter(avg_score >= lower, avg_score <= upper) %>%
  select(participant_id, condition, subscale, avg_score)

# Reshape for tests: one row per participant per subscale
test_data <- subscale_scores_filtered %>%
  pivot_wider(
    names_from = condition,
    values_from = avg_score,
    names_prefix = "condition"
  )

# STEP 1: Overall Friedman tests per subscale
overall_results <- list()
significant_subscales <- c()

for (s in unique(subscale_scores$subscale)) {
  sub_data <- test_data %>% filter(subscale == s)
  scores_mat <- sub_data %>%
    select(starts_with("condition")) %>%
    na.omit() %>%
    as.matrix()

  if (nrow(scores_mat) >= 3) {
    friedman_res <- friedman.test(scores_mat)
    overall_results[[length(overall_results) + 1]] <- data.frame(
      subscale = s,
      p_value = friedman_res$p.value
    )
    if (friedman_res$p.value < 0.05) {
      significant_subscales <- c(significant_subscales, s)
    }
  }
}

overall_df <- bind_rows(overall_results)
overall_df$p_adj_bh <- p.adjust(overall_df$p_value, method = "BH")

# STEP 2: Post-hoc pairwise Wilcoxon tests
pairwise_results <- list()
conditions <- c("1", "2", "3", "4", "5")
pair_combinations <- combn(conditions, 2, simplify = FALSE)

for (s in significant_subscales) {
  sub_data <- test_data %>% filter(subscale == s)
  for (pair in pair_combinations) {
    c1 <- paste0("condition", pair[1])
    c2 <- paste0("condition", pair[2])
    paired_data <- sub_data %>%
      select(participant_id, all_of(c(c1, c2))) %>%
      na.omit()

    if (nrow(paired_data) >= 3) {
      test <- wilcox.test(paired_data[[c1]], paired_data[[c2]], paired = TRUE)
      pairwise_results[[length(pairwise_results) + 1]] <- data.frame(
        subscale = s,
        comparison = paste("Condition", pair[1], "vs", pair[2]),
        p_value = test$p.value
      )
    }
  }
}

pairwise_df <- bind_rows(pairwise_results)
pairwise_df$p_adj_bh <- p.adjust(pairwise_df$p_value, method = "BH")

# Label subscales
subscale_names <- c(
  "1" = "Interest/Enjoyment",
  "2" = "Perceived Competence",
  "3" = "Effort/Importance",
  "4" = "Value/Usefulness"
)

# Final formatting
overall_df$subscale <- factor(overall_df$subscale, levels = names(subscale_names), labels = subscale_names)
pairwise_df$subscale <- factor(pairwise_df$subscale, levels = names(subscale_names), labels = subscale_names)

# View results
cat("=== Overall Friedman Test Results ===\n")
print(overall_df)

cat("\n=== Pairwise Wilcoxon Comparisons (Only for Significant Subscales) ===\n")
pairwise_df = pairwise_df  %>% filter(p_value < 0.05)
print(pairwise_df )

Per-lesson IMI

library(readr)
library(dplyr)
library(tidyr)
library(likert)
library(ggplot2)  # for ggtitle()

# Load and clean data
imi <- read_csv("imi.csv", show_col_types = FALSE)
excluded_ids <- c("682f47a03095562bd581bd06", "674d7a89f564e8bbe0a7af1c", "65537e14439274fe5036b4d2")
imi_clean <- imi %>% filter(!prolific_id %in% excluded_ids)

# Select all lesson columns (lesson1 to lesson4)
lesson_cols <- imi_clean %>% 
  select(participant_id, matches("^imi\\d+_lesson[1-4]$"))

# Convert from wide to long format (all lessons)
long_data <- lesson_cols %>%
  pivot_longer(
    cols = -participant_id,
    names_to = c("question", "lesson"),
    names_pattern = "imi(\\d+)_lesson(\\d)",
    values_to = "response"
  ) %>%
  mutate(
    question = factor(paste0("Q", question), levels = paste0("Q", 1:25), ordered = TRUE),
    response = factor(as.numeric(response),
                      levels = 1:7,
                      labels = c("Extremely disagree", "Disagree", "Slightly disagree",
                                 "Neutral", "Slightly agree", "Agree", "Extremely agree"),
                      ordered = TRUE)
  )

full_levels <- c("Extremely disagree", "Disagree", "Slightly disagree",
                 "Neutral", "Slightly agree", "Agree", "Extremely agree")

# Loop over each lesson and create separate likert plots
for (lesson_num in unique(long_data$lesson)) {
  
  lesson_data <- long_data %>% filter(lesson == lesson_num)
  
  likert_ready <- lesson_data %>%
    group_by(participant_id) %>%
    select(participant_id, question, response) %>%
    pivot_wider(names_from = question, values_from = response) %>%
    select(paste0("Q", 1:25))
  
  likert_ready <- as.data.frame(likert_ready)
  
  # Ensure all columns have the same ordered factor levels:
  likert_ready[] <- lapply(likert_ready, function(x) {
    factor(x, levels = full_levels, ordered = TRUE)
  })
  
  likert_obj <- likert(likert_ready)
  
  print(plot(likert_obj, group.order = paste0("Q", 1:25)) + 
          ggtitle(paste("Likert Plot for Lesson", lesson_num)))
}

Per-lesson IMI - ANOVA

library(readr)
library(dplyr)
library(tidyr)
library(purrr)

# Load and clean data
imi <- read_csv("imi.csv", show_col_types = FALSE)
excluded_ids <- c("682f47a03095562bd581bd06", "674d7a89f564e8bbe0a7af1c", "65537e14439274fe5036b4d2")
imi_clean <- imi %>% filter(!prolific_id %in% excluded_ids)

# Select relevant lesson columns
lesson_cols <- imi_clean %>% 
  select(participant_id, matches("^imi\\d+_lesson[1-4]$"))

# Convert from wide to long format
long_data <- lesson_cols %>%
  pivot_longer(
    cols = -participant_id,
    names_to = c("question", "lesson"),
    names_pattern = "imi(\\d+)_lesson(\\d)",
    values_to = "response"
  ) %>%
  mutate(
    question = factor(paste0("Q", question), levels = paste0("Q", 1:25), ordered = TRUE),
    lesson = factor(lesson, levels = 1:4),
    response_num = as.numeric(response)
  )

# Shapiro-Wilk test for normality per question (combining lessons)
normality_results <- long_data %>%
  group_by(question) %>%
  summarise(
    shapiro_p = if(n() >= 3) shapiro.test(response_num)$p.value else NA_real_
  )

print(normality_results)

# Prepare data wide: each row = participant & question, columns = lessons
friedman_data <- long_data %>%
  select(participant_id, question, lesson, response_num) %>%
  pivot_wider(names_from = lesson, values_from = response_num) %>%
  filter(complete.cases(.))  # only keep participants with all lessons

# Run Friedman test per question
friedman_results <- friedman_data %>%
  group_by(question) %>%
  summarise(
    p_value = {
      mat <- as.matrix(select(cur_data(), `1`, `2`, `3`, `4`))
      friedman.test(mat)$p.value
    }
  )

print(friedman_results)

# Step 2: Post-hoc pairwise Wilcoxon signed-rank tests for those questions

# Function to do pairwise Wilcoxon for a question
posthoc_wilcox <- function(df) {
  # df: filtered for one question, wide format with lessons columns
  lessons <- c("1","2","3","4")
  pairs <- combn(lessons, 2, simplify = FALSE)
  
  results <- map_dfr(pairs, function(pair) {
    res <- wilcox.test(df[[pair[1]]], df[[pair[2]]], paired = TRUE, exact = FALSE)
    mean_diff <- mean(df[[pair[1]]] - df[[pair[2]]])
    tibble(
      lesson_1 = pair[1],
      lesson_2 = pair[2],
      p_value = res$p.value,
      mean_difference = mean_diff
    )
  })
  
  # Adjust p-values for multiple comparisons (Bonferroni)
  results <- results %>%
    mutate(p_adj = p.adjust(p_value, method = "bonferroni"))
  
  return(results)
}

# Run posthoc tests for each significant question
posthoc_results <- friedman_results %>%
  pull(question) %>%
  set_names() %>%
  map_df(function(q) {
    df_q <- friedman_data %>% filter(question == q)
    res <- posthoc_wilcox(df_q)
    res$question <- q
    res
  }, .id = "question")

# Filter only pairs with significant adjusted p-values < 0.05
significant_pairs <- posthoc_results %>%
  filter(p_adj < 0.05) %>%
  select(question, lesson_1, lesson_2, mean_difference, p_value, p_adj)

print(significant_pairs)

Per-condition IMI

library(readr)
library(dplyr)
library(tidyr)
library(likert)
library(ggplot2)  # for ggtitle()

# Load and clean data
imi <- read_csv("imi.csv", show_col_types = FALSE)
excluded_ids <- c("682f47a03095562bd581bd06", "674d7a89f564e8bbe0a7af1c", "65537e14439274fe5036b4d2")
imi_clean <- imi %>% filter(!prolific_id %in% excluded_ids)

# Select all condition columns (condition1 to condition4)
condition_cols <- imi_clean %>% 
  select(participant_id, matches("^imi\\d+_condition[1-4]$"))

# Convert from wide to long format (all conditions)
long_data <- condition_cols %>%
  pivot_longer(
    cols = -participant_id,
    names_to = c("question", "condition"),
    names_pattern = "imi(\\d+)_condition(\\d)",
    values_to = "response"
  ) %>%
  mutate(
    question = factor(paste0("Q", question), levels = paste0("Q", 1:25), ordered = TRUE),
    response = factor(as.numeric(response),
                      levels = 1:7,
                      labels = c("Extremely disagree", "Disagree", "Slightly disagree",
                                 "Neutral", "Slightly agree", "Agree", "Extremely agree"),
                      ordered = TRUE)
  )

full_levels <- c("Extremely disagree", "Disagree", "Slightly disagree",
                 "Neutral", "Slightly agree", "Agree", "Extremely agree")

# Loop over each condition and create separate likert plots
for (condition_num in unique(long_data$condition)) {
  
  condition_data <- long_data %>% filter(condition == condition_num)
  
  likert_ready <- condition_data %>%
    group_by(participant_id) %>%
    select(participant_id, question, response) %>%
    pivot_wider(names_from = question, values_from = response) %>%
    select(paste0("Q", 1:25))
  
  likert_ready <- as.data.frame(likert_ready)
  
  # Ensure all columns have the same ordered factor levels:
  likert_ready[] <- lapply(likert_ready, function(x) {
    factor(x, levels = full_levels, ordered = TRUE)
  })
  
  likert_obj <- likert(likert_ready)
  
  print(plot(likert_obj, group.order = paste0("Q", 1:25)) + 
          ggtitle(paste("Likert Plot for Condition", condition_num)))
}

Per-condition IMI - ANOVA

library(readr)
library(dplyr)
library(tidyr)

# Load and clean data
imi <- read_csv("imi.csv", show_col_types = FALSE)
excluded_ids <- c("682f47a03095562bd581bd06", "674d7a89f564e8bbe0a7af1c", "65537e14439274fe5036b4d2")
imi_clean <- imi %>% filter(!prolific_id %in% excluded_ids)

# Select relevant condition columns
lesson_cols <- imi_clean %>% 
  select(participant_id, matches("^imi\\d+_condition[1-4]$"))

# Convert from wide to long format
long_data <- lesson_cols %>%
  pivot_longer(
    cols = -participant_id,
    names_to = c("question", "condition"),
    names_pattern = "imi(\\d+)_condition(\\d)",
    values_to = "response"
  ) %>%
  mutate(
    question = factor(paste0("Q", question), levels = paste0("Q", 1:25), ordered = TRUE),
    lesson = factor(condition, levels = 1:4),
    response_num = as.numeric(response)
  )

# Shapiro-Wilk test for normality per question (combining lessons)
normality_results <- long_data %>%
  group_by(question) %>%
  summarise(
    shapiro_p = if(n() >= 3) shapiro.test(response_num)$p.value else NA_real_
  )

print(normality_results)

# Prepare data wide: each row = participant & question, columns = lessons
friedman_data <- long_data %>%
  select(participant_id, question, condition, response_num) %>%
  pivot_wider(names_from = condition, values_from = response_num) %>%
  filter(complete.cases(.))  # only keep participants with all lessons

# Run Friedman test per question
friedman_results <- friedman_data %>%
  group_by(question) %>%
  summarise(
    p_value = {
      mat <- as.matrix(select(cur_data(), `1`, `2`, `3`, `4`))
      friedman.test(mat)$p.value
    }
  )

print(friedman_results)


# Step 2: Post-hoc pairwise Wilcoxon signed-rank tests for those questions

# Function to do pairwise Wilcoxon for a question
posthoc_wilcox <- function(df) {
  # df: filtered for one question, wide format with lessons columns
  conditions <- c("1","2","3","4")
  pairs <- combn(conditions, 2, simplify = FALSE)
  
  results <- map_dfr(pairs, function(pair) {
    res <- wilcox.test(df[[pair[1]]], df[[pair[2]]], paired = TRUE, exact = FALSE)
    mean_diff <- mean(df[[pair[1]]] - df[[pair[2]]])
    tibble(
      condition_1 = pair[1],
      condition_2 = pair[2],
      p_value = res$p.value,
      mean_difference = mean_diff
    )
  })
  
  # Adjust p-values for multiple comparisons (bh)
  results <- results %>%
    mutate(p_adj_bh = p.adjust(p_value, method = "BH"))
  
   results <- results %>%
    mutate(p_adj_bonferroni = p.adjust(p_value, method = "bonferroni"))
  
  return(results)
}

# Run posthoc tests for each significant question
posthoc_results <- friedman_results %>%
  pull(question) %>%
  set_names() %>%
  map_df(function(q) {
    df_q <- friedman_data %>% filter(question == q)
    res <- posthoc_wilcox(df_q)
    res$question <- q
    res
  }, .id = "question")

# Filter only pairs with significant adjusted p-values < 0.05
significant_pairs <- posthoc_results %>%
  filter(p_value < 0.1) %>%
  filter(condition_2 == 4) %>%
  select(question, condition_1, condition_2, mean_difference, p_value, p_adj_bh, p_adj_bonferroni)

print(significant_pairs)

LIWC

Correlations on Users (mid to post)


library(readr)
library(dplyr)
library(corrr)


print(data)

# Step 1: Reshape and compute differences
all_certainty_deltas <- data %>%
  select(user_id, matches("likert_(mid|post)_condition\\d+")) %>%  # keep user_id
  pivot_longer(
    cols = -user_id,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  pivot_wider(names_from = phase, values_from = score) %>%
  mutate(
    diff = post - mid,
    condition = case_when(
      condition == "1" ~ "Control",
      condition == "2" ~ "Reading",
      condition == "3" ~ "Writing",
      condition == "4" ~ "Chatbot",
      TRUE ~ condition
    )
  ) %>%
  select(user_id, condition, diff) %>%
  pivot_wider(names_from = condition, values_from = diff)


# 1. Load the LIWC and delta data
liwc_data <- readr::read_delim("LIWC-22 Results - participant_texts - LIWC Analysis.csv", delim = ";")

# 2. Drop unwanted user_ids (assuming Segment contains user ID or a name like "user_10")
excluded_ids <- c(10, 26, 29, 48, 49, 52)
liwc_filtered <- liwc_data %>%
  mutate(user_id = as.numeric(gsub("\\D+", "", Segment))) %>%  # Extract numeric ID from "user_XX"
  filter(!user_id %in% excluded_ids)

# 3. Prepare all_certainty_deltas (ensure participant_id format matches)
all_certainty_deltas <- all_certainty_deltas %>%
  mutate(user_id = as.numeric(user_id)) %>%
  filter(!user_id %in% excluded_ids)

liwc_filtered <- liwc_data %>%
  mutate(user_id = as.numeric(gsub("user_(\\d+)\\.txt", "\\1", Filename))) %>%
  filter(!user_id %in% excluded_ids)


# 4. Join LIWC and delta data
merged_data <- inner_join(liwc_filtered, all_certainty_deltas, by = "user_id")

print(merged_data)

# 5. Run correlation between all LIWC features and Chatbot deltas
# Exclude non-numeric or identifier columns first
liwc_columns <- liwc_filtered %>%
  select(-Segment, -user_id) %>%
  select(where(is.numeric)) %>% names()

cor_input <- merged_data %>%
  select(all_of(liwc_columns), Chatbot)

cor_results <- correlate(cor_input) %>%
  focus(Chatbot) %>%
  arrange(desc(abs(Chatbot)))  # Sort by strength of correlation

# 6. View results
print(cor_results)

# Optional: Filter for meaningful correlation (e.g. > 0.3 or < -0.3)
strong_corrs <- cor_results %>%
  filter(abs(Chatbot) > 0.3)
print(strong_corrs)

# Select numeric columns and Chatbot delta
numeric_vars <- merged_data %>%
  select(all_of(liwc_columns))

chatbot_scores <- merged_data$Chatbot

# Initialize a results data frame
results <- data.frame(term = character(), 
                      cor = numeric(), 
                      p_value = numeric(), 
                      stringsAsFactors = FALSE)

# Loop over each LIWC variable and run cor.test with Chatbot
for (var in colnames(numeric_vars)) {
  test <- cor.test(numeric_vars[[var]], chatbot_scores, use = "pairwise.complete.obs")
  
  results <- rbind(results, data.frame(
    term = var,
    cor = test$estimate,
    p_value = test$p.value
  ))
}

# Sort by absolute correlation
results <- results %>% arrange(desc(abs(cor)))

results <- results %>%
  mutate(p_adj = p.adjust(p_value, method = "BH"))  # FDR correction

# View significant after correction
sig_results <- results %>%
  filter(p_value < 0.05)

print(sig_results)
library(tidyr)
library(ggplot2)
library(dplyr)

# Select LIWC columns + Chatbot delta and user_id
plot_data <- merged_data %>%
  select(user_id, Chatbot, all_of(liwc_columns))

# Convert LIWC terms to long format
long_data <- plot_data %>%
  pivot_longer(
    cols = -c(user_id, Chatbot),
    names_to = "LIWC_term",
    values_to = "LIWC_value"
  )

# Assuming 'results' already contains the correlation data for LIWC terms
library(dplyr)
library(tidyr)
library(ggplot2)

# Calculate proportion of non-zero values for each LIWC term
non_zero_proportion <- long_data %>%
  group_by(LIWC_term) %>%
  summarize(non_zero_ratio = sum(LIWC_value != 0) / n(), .groups = 'drop')

# Merge with the correlation results
results_with_proportion <- results %>%
  inner_join(non_zero_proportion, by = c("term" = "LIWC_term"))

# Set thresholds
cor_threshold <- 0.3 
nz_threshold <- 0.3 

# Filter for strong correlations and non-zero inflated terms

# Filter specifically for "Health" term
filtered_terms <- results_with_proportion %>%
  filter(term == "health") %>%
  pull(term)

# Filter long_data for these terms
top_non_zero_long_data <- long_data %>%
  filter(LIWC_term %in% filtered_terms)

library(dplyr)
library(tidyr)
library(ggplot2)

# Add custom names mapping
custom_names <- c(
  "health" = "Health"
)

# Filter and prepare annotations
annotations <- results_with_proportion %>%
  filter(term %in% filtered_terms) %>%
  mutate(
    label = paste0("r = ", round(cor, 2), ", p = ", format(p_adj, digits = 2)),
    LIWC_term = term
  ) %>%
  select(LIWC_term, label)

# Add annotations to the long data for plotting
top_non_zero_long_data <- top_non_zero_long_data %>%
  left_join(annotations, by = "LIWC_term")

# Plot with custom facet labels
ggplot(top_non_zero_long_data, aes(x = LIWC_value, y = Chatbot)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE, color = "steelblue") +
  facet_wrap(~ LIWC_term, scales = "free_x", labeller = labeller(LIWC_term = custom_names)) +
  labs(
    title = "Correlation of LIWC 'Health' Term Value\nand Post-Attack Certainty Change",
    x = "LIWC 'Health' Term Value",
    y = "Post-Attack Certainty Change"
  ) +
  theme_minimal(base_size = 14) +
  theme(strip.text = element_text(size = 12, face = "bold")) +
  geom_label(
    data = annotations,
    mapping = aes(x = Inf, y = Inf, label = label),
    hjust = 1.1, vjust = 1.5,
    inherit.aes = FALSE,
    fill = alpha("white", 0.5)
  )

Correlations on Users (pre to mid)


library(readr)
library(dplyr)
library(corrr)


print(data)

# Step 1: Reshape and compute differences
all_certainty_deltas <- data %>%
  select(user_id, matches("likert_(pre|mid)_condition\\d+")) %>%  # keep user_id
  pivot_longer(
    cols = -user_id,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|mid)_condition(\\d+)",
    values_to = "score"
  ) %>%
  pivot_wider(names_from = phase, values_from = score) %>%
  mutate(
    diff = mid - pre,
    condition = case_when(
      condition == "1" ~ "Control",
      condition == "2" ~ "Reading",
      condition == "3" ~ "Writing",
      condition == "4" ~ "Chatbot",
      TRUE ~ condition
    )
  ) %>%
  select(user_id, condition, diff) %>%
  pivot_wider(names_from = condition, values_from = diff)


# 1. Load the LIWC and delta data
liwc_data <- readr::read_delim("LIWC-22 Results - participant_texts - LIWC Analysis.csv", delim = ";")

# 2. Drop unwanted user_ids (assuming Segment contains user ID or a name like "user_10")
excluded_ids <- c(10, 26, 29, 48, 49, 52)
liwc_filtered <- liwc_data %>%
  mutate(user_id = as.numeric(gsub("\\D+", "", Segment))) %>%  # Extract numeric ID from "user_XX"
  filter(!user_id %in% excluded_ids)

# 3. Prepare all_certainty_deltas (ensure participant_id format matches)
all_certainty_deltas <- all_certainty_deltas %>%
  mutate(user_id = as.numeric(user_id)) %>%
  filter(!user_id %in% excluded_ids)

liwc_filtered <- liwc_data %>%
  mutate(user_id = as.numeric(gsub("user_(\\d+)\\.txt", "\\1", Filename))) %>%
  filter(!user_id %in% excluded_ids)


# 4. Join LIWC and delta data
merged_data <- inner_join(liwc_filtered, all_certainty_deltas, by = "user_id")

print(merged_data)

# 5. Run correlation between all LIWC features and Chatbot deltas
# Exclude non-numeric or identifier columns first
liwc_columns <- liwc_filtered %>%
  select(-Segment, -user_id) %>%
  select(where(is.numeric)) %>% names()

cor_input <- merged_data %>%
  select(all_of(liwc_columns), Chatbot)

cor_results <- correlate(cor_input) %>%
  focus(Chatbot) %>%
  arrange(desc(abs(Chatbot)))  # Sort by strength of correlation

# 6. View results
print(cor_results)

# Optional: Filter for meaningful correlation (e.g. > 0.3 or < -0.3)
strong_corrs <- cor_results %>%
  filter(abs(Chatbot) > 0.3)
print(strong_corrs)

# Select numeric columns and Chatbot delta
numeric_vars <- merged_data %>%
  select(all_of(liwc_columns))

chatbot_scores <- merged_data$Chatbot

# Initialize a results data frame
results <- data.frame(term = character(), 
                      cor = numeric(), 
                      p_value = numeric(), 
                      stringsAsFactors = FALSE)

# Loop over each LIWC variable and run cor.test with Chatbot
for (var in colnames(numeric_vars)) {
  test <- cor.test(numeric_vars[[var]], chatbot_scores, use = "pairwise.complete.obs")
  
  results <- rbind(results, data.frame(
    term = var,
    cor = test$estimate,
    p_value = test$p.value
  ))
}

# Sort by absolute correlation
results <- results %>% arrange(desc(abs(cor)))

results <- results %>%
  mutate(p_adj = p.adjust(p_value, method = "BH"))  # FDR correction

# View significant after correction
sig_results <- results %>%
  filter(p_value < 0.05)

print(sig_results)
library(tidyr)
library(ggplot2)
library(dplyr)

# Select LIWC columns + Chatbot delta and user_id
plot_data <- merged_data %>%
  select(user_id, Chatbot, all_of(liwc_columns))

# Convert LIWC terms to long format
long_data <- plot_data %>%
  pivot_longer(
    cols = -c(user_id, Chatbot),
    names_to = "LIWC_term",
    values_to = "LIWC_value"
  )

# Assuming 'results' already contains the correlation data for LIWC terms
library(dplyr)
library(tidyr)
library(ggplot2)

# Calculate proportion of non-zero values for each LIWC term
non_zero_proportion <- long_data %>%
  group_by(LIWC_term) %>%
  summarize(non_zero_ratio = sum(LIWC_value != 0) / n(), .groups = 'drop')

# Merge with the correlation results
results_with_proportion <- results %>%
  inner_join(non_zero_proportion, by = c("term" = "LIWC_term"))

# Set thresholds
cor_threshold <- 0.3 
nz_threshold <- 0.3 

# Filter for strong correlations and non-zero inflated terms

# Filter specifically for "Health" term
filtered_terms <- results_with_proportion %>%
  filter(term == "health") %>%
  pull(term)

# Filter long_data for these terms
top_non_zero_long_data <- long_data %>%
  filter(LIWC_term %in% filtered_terms)

Correlations on Chatbot (mid to post)


library(readr)
library(dplyr)
library(corrr)


print(data)

# Step 1: Reshape and compute differences
all_certainty_deltas <- data %>%
  select(user_id, matches("likert_(mid|post)_condition\\d+")) %>%  # keep user_id
  pivot_longer(
    cols = -user_id,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(mid|post)_condition(\\d+)",
    values_to = "score"
  ) %>%
  pivot_wider(names_from = phase, values_from = score) %>%
  mutate(
    diff = post - mid,
    condition = case_when(
      condition == "1" ~ "Control",
      condition == "2" ~ "Reading",
      condition == "3" ~ "Writing",
      condition == "4" ~ "Chatbot",
      TRUE ~ condition
    )
  ) %>%
  select(user_id, condition, diff) %>%
  pivot_wider(names_from = condition, values_from = diff)


# 1. Load the LIWC and delta data
liwc_data <- readr::read_delim("LIWC-22 Results - bot_texts - LIWC Analysis.csv", delim = ";")

# 2. Drop unwanted user_ids (assuming Segment contains user ID or a name like "user_10")
excluded_ids <- c(10, 26, 29, 48, 49, 52)
liwc_filtered <- liwc_data %>%
  mutate(user_id = as.numeric(gsub("\\D+", "", Segment))) %>%  # Extract numeric ID from "user_XX"
  filter(!user_id %in% excluded_ids)

# 3. Prepare all_certainty_deltas (ensure participant_id format matches)
all_certainty_deltas <- all_certainty_deltas %>%
  mutate(user_id = as.numeric(user_id)) %>%
  filter(!user_id %in% excluded_ids)

liwc_filtered <- liwc_data %>%
  mutate(user_id = as.numeric(gsub("user_(\\d+)\\.txt", "\\1", Filename))) %>%
  filter(!user_id %in% excluded_ids)


# 4. Join LIWC and delta data
merged_data <- inner_join(liwc_filtered, all_certainty_deltas, by = "user_id")

print(merged_data)

# 5. Run correlation between all LIWC features and Chatbot deltas
# Exclude non-numeric or identifier columns first
liwc_columns <- liwc_filtered %>%
  select(-Segment, -user_id) %>%
  select(where(is.numeric)) %>% names()

cor_input <- merged_data %>%
  select(all_of(liwc_columns), Chatbot)

cor_results <- correlate(cor_input) %>%
  focus(Chatbot) %>%
  arrange(desc(abs(Chatbot)))  # Sort by strength of correlation

# 6. View results
print(cor_results)

# Optional: Filter for meaningful correlation (e.g. > 0.3 or < -0.3)
strong_corrs <- cor_results %>%
  filter(abs(Chatbot) > 0.3)
print(strong_corrs)

# Select numeric columns and Chatbot delta
numeric_vars <- merged_data %>%
  select(all_of(liwc_columns))

chatbot_scores <- merged_data$Chatbot

# Initialize a results data frame
results <- data.frame(term = character(), 
                      cor = numeric(), 
                      p_value = numeric(), 
                      stringsAsFactors = FALSE)

# Loop over each LIWC variable and run cor.test with Chatbot
for (var in colnames(numeric_vars)) {
  test <- cor.test(numeric_vars[[var]], chatbot_scores, use = "pairwise.complete.obs")
  
  results <- rbind(results, data.frame(
    term = var,
    cor = test$estimate,
    p_value = test$p.value
  ))
}

# Sort by absolute correlation
results <- results %>% arrange(desc(abs(cor)))

results <- results %>%
  mutate(p_adj = p.adjust(p_value, method = "BH"))  # FDR correction

# View significant after correction
sig_results <- results %>%
  filter(p_value < 0.05)

print(sig_results)
library(tidyr)
library(ggplot2)
library(dplyr)

# Select LIWC columns + Chatbot delta and user_id
plot_data <- merged_data %>%
  select(user_id, Chatbot, all_of(liwc_columns))

# Convert LIWC terms to long format
long_data <- plot_data %>%
  pivot_longer(
    cols = -c(user_id, Chatbot),
    names_to = "LIWC_term",
    values_to = "LIWC_value"
  )

# Assuming 'results' already contains the correlation data for LIWC terms
library(dplyr)
library(tidyr)
library(ggplot2)

# Calculate proportion of non-zero values for each LIWC term
non_zero_proportion <- long_data %>%
  group_by(LIWC_term) %>%
  summarize(non_zero_ratio = sum(LIWC_value != 0) / n(), .groups = 'drop')

# Merge with the correlation results
results_with_proportion <- results %>%
  inner_join(non_zero_proportion, by = c("term" = "LIWC_term"))

# Set thresholds
cor_threshold <- 0.3 
nz_threshold <- 0.3 

# Filter for strong correlations and non-zero inflated terms

# Filter specifically for "Health" term
filtered_terms <- results_with_proportion %>%
  filter(term == "health") %>%
  pull(term)

# Filter long_data for these terms
top_non_zero_long_data <- long_data %>%
  filter(LIWC_term %in% filtered_terms)

library(dplyr)
library(tidyr)
library(ggplot2)

# Add custom names mapping
custom_names <- c(
  "health" = "Health"
)

# Filter and prepare annotations
annotations <- results_with_proportion %>%
  filter(term %in% filtered_terms) %>%
  mutate(
    label = paste0("r = ", round(cor, 2), ", p = ", format(p_adj, digits = 2)),
    LIWC_term = term
  ) %>%
  select(LIWC_term, label)

# Add annotations to the long data for plotting
top_non_zero_long_data <- top_non_zero_long_data %>%
  left_join(annotations, by = "LIWC_term")

# Plot with custom facet labels
ggplot(top_non_zero_long_data, aes(x = LIWC_value, y = Chatbot)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE, color = "steelblue") +
  facet_wrap(~ LIWC_term, scales = "free_x", labeller = labeller(LIWC_term = custom_names)) +
  labs(
    title = "Correlation of LIWC 'Health' Term Value\nand Post-Inoculation Certainty Change",
    x = "LIWC 'Health' Term Value",
    y = "Post-Attack Certainty Change"
  ) +
  theme_minimal(base_size = 14) +
  theme(strip.text = element_text(size = 12, face = "bold")) +
  geom_label(
    data = annotations,
    mapping = aes(x = Inf, y = Inf, label = label),
    hjust = 1.1, vjust = 1.5,
    inherit.aes = FALSE,
    fill = alpha("white", 0.5)
  )

Correlations on Chatbot (pre to mid)


library(readr)
library(dplyr)
library(corrr)


print(data)

# Step 1: Reshape and compute differences
all_certainty_deltas <- data %>%
  select(user_id, matches("likert_(pre|mid)_condition\\d+")) %>%  # keep user_id
  pivot_longer(
    cols = -user_id,
    names_to = c("phase", "condition"),
    names_pattern = "likert_(pre|mid)_condition(\\d+)",
    values_to = "score"
  ) %>%
  pivot_wider(names_from = phase, values_from = score) %>%
  mutate(
    diff = mid - pre,
    condition = case_when(
      condition == "1" ~ "Control",
      condition == "2" ~ "Reading",
      condition == "3" ~ "Writing",
      condition == "4" ~ "Chatbot",
      TRUE ~ condition
    )
  ) %>%
  select(user_id, condition, diff) %>%
  pivot_wider(names_from = condition, values_from = diff)

print(all_certainty_deltas)

# 1. Load the LIWC and delta data
liwc_data <- readr::read_delim("LIWC-22 Results - bot_texts - LIWC Analysis.csv", delim = ";")

# 2. Drop unwanted user_ids (assuming Segment contains user ID or a name like "user_10")
excluded_ids <- c(10, 26, 29, 48, 49, 52)
liwc_filtered <- liwc_data %>%
  mutate(user_id = as.numeric(gsub("\\D+", "", Segment))) %>%  # Extract numeric ID from "user_XX"
  filter(!user_id %in% excluded_ids)

# 3. Prepare all_certainty_deltas (ensure participant_id format matches)
all_certainty_deltas <- all_certainty_deltas %>%
  mutate(user_id = as.numeric(user_id)) %>%
  filter(!user_id %in% excluded_ids)

liwc_filtered <- liwc_data %>%
  mutate(user_id = as.numeric(gsub("user_(\\d+)\\.txt", "\\1", Filename))) %>%
  filter(!user_id %in% excluded_ids)


# 4. Join LIWC and delta data
merged_data <- inner_join(liwc_filtered, all_certainty_deltas, by = "user_id")

print(merged_data)

# 5. Run correlation between all LIWC features and Chatbot deltas
# Exclude non-numeric or identifier columns first
liwc_columns <- liwc_filtered %>%
  select(-Segment, -user_id) %>%
  select(where(is.numeric)) %>% names()

cor_input <- merged_data %>%
  select(all_of(liwc_columns), Chatbot)

cor_results <- correlate(cor_input) %>%
  focus(Chatbot) %>%
  arrange(desc(abs(Chatbot)))  # Sort by strength of correlation

# 6. View results
print(cor_results)

# Optional: Filter for meaningful correlation (e.g. > 0.3 or < -0.3)
strong_corrs <- cor_results %>%
  filter(abs(Chatbot) > 0.3)
print(strong_corrs)

# Select numeric columns and Chatbot delta
numeric_vars <- merged_data %>%
  select(all_of(liwc_columns))

chatbot_scores <- merged_data$Chatbot

# Initialize a results data frame
results <- data.frame(term = character(), 
                      cor = numeric(), 
                      p_value = numeric(), 
                      stringsAsFactors = FALSE)

# Loop over each LIWC variable and run cor.test with Chatbot
for (var in colnames(numeric_vars)) {
  test <- cor.test(numeric_vars[[var]], chatbot_scores, use = "pairwise.complete.obs")
  
  results <- rbind(results, data.frame(
    term = var,
    cor = test$estimate,
    p_value = test$p.value
  ))
}

# Sort by absolute correlation
results <- results %>% arrange(desc(abs(cor)))

results <- results %>%
  mutate(p_adj = p.adjust(p_value, method = "BH"))  # FDR correction

# View significant after correction
sig_results <- results %>%
  filter(p_value < 0.05)

print(sig_results)
library(tidyr)
library(ggplot2)
library(dplyr)

# Select LIWC columns + Chatbot delta and user_id
plot_data <- merged_data %>%
  select(user_id, Chatbot, all_of(liwc_columns))

# Convert LIWC terms to long format
long_data <- plot_data %>%
  pivot_longer(
    cols = -c(user_id, Chatbot),
    names_to = "LIWC_term",
    values_to = "LIWC_value"
  )

# Assuming 'results' already contains the correlation data for LIWC terms
library(dplyr)
library(tidyr)
library(ggplot2)

# Calculate proportion of non-zero values for each LIWC term
non_zero_proportion <- long_data %>%
  group_by(LIWC_term) %>%
  summarize(non_zero_ratio = sum(LIWC_value != 0) / n(), .groups = 'drop')

# Merge with the correlation results
results_with_proportion <- results %>%
  inner_join(non_zero_proportion, by = c("term" = "LIWC_term"))

# Set thresholds
cor_threshold <- 0.3 
nz_threshold <- 0.3 

# Filter for strong correlations and non-zero inflated terms

# Filter specifically for "Health" term
filtered_terms <- results_with_proportion %>%
  filter(term == "health") %>%
  pull(term)

# Filter long_data for these terms
top_non_zero_long_data <- long_data %>%
  filter(LIWC_term %in% filtered_terms)

library(dplyr)
library(tidyr)
library(ggplot2)

# Add custom names mapping
custom_names <- c(
  "health" = "Health"
)

# Filter and prepare annotations
annotations <- results_with_proportion %>%
  filter(term %in% filtered_terms) %>%
  mutate(
    label = paste0("r = ", round(cor, 2), ", p = ", format(p_adj, digits = 2)),
    LIWC_term = term
  ) %>%
  select(LIWC_term, label)

# Add annotations to the long data for plotting
top_non_zero_long_data <- top_non_zero_long_data %>%
  left_join(annotations, by = "LIWC_term")

# Plot with custom facet labels
ggplot(top_non_zero_long_data, aes(x = LIWC_value, y = Chatbot)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE, color = "steelblue") +
  facet_wrap(~ LIWC_term, scales = "free_x", labeller = labeller(LIWC_term = custom_names)) +
  labs(
    title = "Correlation of LIWC 'Health' Term Value\nand Post-Inoculation Certainty Change",
    x = "LIWC 'Health' Term Value",
    y = "Post-Inoculation Certainty Change"
  ) +
  theme_minimal(base_size = 14) +
  theme(strip.text = element_text(size = 12, face = "bold")) +
  geom_label(
    data = annotations,
    mapping = aes(x = Inf, y = Inf, label = label),
    hjust = 1.1, vjust = 1.5,
    inherit.aes = FALSE,
    fill = alpha("white", 0.5)
  )
LS0tCnRpdGxlOiAiTWluZEZvcnQgQW5hbHlzaXMgTm90ZWJvb2siCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMgTG9hZCBhbmQgcHJlcHJvY2VzcyBjZXJ0YWludHkgZGF0YQoKKipQcmVwcm9jZXNzaW5nKio6IEZvciBhbGwgdGhlIGFuYWx5c2lzIGJlbG93LCB3ZSBvbWl0dGVkIGRhdGEgb2YgMyBwYXJ0aWNpcGFudHMgd2hvIGhhdmUgZmFpbGVkIGF0IGxlYXN0IG9uZSBhdHRlbnRpb24gY2hlY2sgZHVyaW5nIHRoZSBleHBlcmltZW50cywgb21pdHRlZCBhbGwgaW5kaXZpZHVhbCBsZXNzb24gZGF0YSB3aGVyZSB0aGUgcGFydGljaXBhbnRzJyBpbml0aWFsIGNlcnRhaW50eSBzY29yZSB3YXMgYmVsb3cgMTAgcG9pbnRzIG9uIHRoZSAxNS1wb2ludCBzY2FsZSBhbmQgcmVtb3ZlZCBhbnkgb3V0bGllcnMgKDEuNSBJUVIpLgoKYGBge3J9CmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoc3RyaW5ncikKCmRhdGEgPC0gcmVhZF9jc3YoImNlcnRhaW50eS5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUKICBmaWx0ZXIoZXhjbHVkZSA9PSAwKSAlPiUKICBmaWx0ZXIocGFydGljaXBhbnRfaWQgPiAtMSkKICAKCiMgR2V0IGFsbCB1bmlxdWUgc3VmZml4ZXMgZm9yIGxlc3NvbnMgYW5kIGNvbmRpdGlvbnMKbGlrZXJ0X3ByZV9jb2xzIDwtIGdyZXAoIl5saWtlcnRfcHJlXyIsIG5hbWVzKGRhdGEpLCB2YWx1ZSA9IFRSVUUpCnN1ZmZpeGVzIDwtIHN0cl9yZXBsYWNlKGxpa2VydF9wcmVfY29scywgIl5saWtlcnRfcHJlXyIsICIiKQoKZm9yIChzdWYgaW4gc3VmZml4ZXMpIHsKICBwcmVfY29sIDwtIHBhc3RlMCgibGlrZXJ0X3ByZV8iLCBzdWYpCiAgbWlkX2NvbCA8LSBwYXN0ZTAoImxpa2VydF9taWRfIiwgc3VmKQogIHBvc3RfY29sIDwtIHBhc3RlMCgibGlrZXJ0X3Bvc3RfIiwgc3VmKQogIAogICMgQ2hlY2sgYWxsIGNvbHVtbnMgZXhpc3QKICBpZiAoYWxsKGMocHJlX2NvbCwgbWlkX2NvbCwgcG9zdF9jb2wpICVpbiUgbmFtZXMoZGF0YSkpKSB7CiAgICBkYXRhIDwtIGRhdGEgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBhY3Jvc3MoCiAgICAgICAgICBhbGxfb2YoYyhwcmVfY29sLCBtaWRfY29sLCBwb3N0X2NvbCkpLAogICAgICAgICAgfiBpZl9lbHNlKC5kYXRhW1twcmVfY29sXV0gPCAxMCwgTkFfcmVhbF8sIC4pCiAgICAgICAgKQogICAgICApCiAgfQp9CgpwcmludChkYXRhKQoKCmBgYAoKIyBEZW1vZ3JhcGhpY3MKCmBgYHtyfQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcnkKbGlicmFyeShkcGx5cikKCiMgTG9hZCB0aGUgZGF0YSBmcm9tIHRoZSBDU1YgZmlsZQpkZW1vZ3JhcGhpY3NfZGF0YSA8LSByZWFkLmNzdigiZGVtb2dyYXBoaWNzLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCiMgU3BlY2lmeSB0aGUgSURzIHRvIHJlbW92ZQppZHNfdG9fcmVtb3ZlIDwtIGMoIjY4MmY0N2EwMzA5NTU2MmJkNTgxYmQwNiIsICI2NzRkN2E4OWY1NjRlOGJiZTBhN2FmMWMiLCAiNjU1MzdlMTQ0MzkyNzRmZTUwMzZiNGQyIikKCiMgRmlsdGVyIHRoZSBkYXRhIHRvIHJlbW92ZSBwYXJ0aWNpcGFudHMgd2l0aCB0aGUgc3BlY2lmaWVkIElEcwpmaWx0ZXJlZF9kYXRhIDwtIGRlbW9ncmFwaGljc19kYXRhICU+JQogIGZpbHRlcighUGFydGljaXBhbnQuaWQgJWluJSBpZHNfdG9fcmVtb3ZlKQoKIyBGaWx0ZXIgb3V0IHJvd3Mgd2hlcmUgU3RhdHVzIGlzIG5vdCAnQVBQUk9WRUQnCmFjY2VwdGVkX2RhdGEgPC0gZmlsdGVyZWRfZGF0YSAlPiUKICBmaWx0ZXIoU3RhdHVzID09ICJBUFBST1ZFRCIpCiMgQXNzdW1pbmcgJ2FjY2VwdGVkX2RhdGEnIGlzIHRoZSBmaWx0ZXJlZCBkYXRhc2V0IGZvciBwYXJ0aWNpcGFudHMgd2l0aCAnU3RhdHVzJyA9PSAnQUNDRVBURUQnCiMgRW5zdXJlIEFnZSBjb2x1bW4gaXMgbnVtZXJpYwphY2NlcHRlZF9kYXRhJEFnZSA8LSBhcy5udW1lcmljKGFjY2VwdGVkX2RhdGEkQWdlKQoKIyBDaGVjayBmb3IgY29udmVyc2lvbiBpc3N1ZXMgYW5kIHdhcm4gaWYgYW55IGVudHJpZXMgYmVjYW1lIE5BCmNvbnZlcnNpb25faXNzdWVzIDwtIHN1bShpcy5uYShhY2NlcHRlZF9kYXRhJEFnZSkpCmlmIChjb252ZXJzaW9uX2lzc3VlcyA+IDApIHsKICB3YXJuaW5nKHBhc3RlKGNvbnZlcnNpb25faXNzdWVzLCAibm9uLW51bWVyaWMgZW50cmllcyB3ZXJlIGNvbnZlcnRlZCB0byBOQSBpbiB0aGUgQWdlIGNvbHVtbi4iKSkKfQoKIyBDYWxjdWxhdGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uLCBpZ25vcmluZyBOQXMKYWdlX3N0YXRzIDwtIGFjY2VwdGVkX2RhdGEgJT4lCiAgc3VtbWFyaXNlKAogICAgTWVhbl9BZ2UgPSBtZWFuKEFnZSwgbmEucm0gPSBUUlVFKSwKICAgIFNEX0FnZSA9IHNkKEFnZSwgbmEucm0gPSBUUlVFKQogICkKCmFnZV9zdW1tYXJ5IDwtIHBhc3RlMCgiTWVhbjogIiwgcm91bmQoYWdlX3N0YXRzJE1lYW5fQWdlLCAyKSwgIiwgU0Q6ICIsIHJvdW5kKGFnZV9zdGF0cyRTRF9BZ2UsIDIpKQoKCiMgQ2FsY3VsYXRlIGdlbmRlciBkaXN0cmlidXRpb24KZ2VuZGVyX2Rpc3RyaWJ1dGlvbiA8LSBwYXN0ZShuYW1lcyh0YWJsZShhY2NlcHRlZF9kYXRhJFNleCkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWJsZShhY2NlcHRlZF9kYXRhJFNleCksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICI6ICIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiwgIikKCiMgQ2FsY3VsYXRlIGV0aG5pY2l0eSBkaXN0cmlidXRpb24KZXRobmljaXR5X2Rpc3RyaWJ1dGlvbiA8LSBwYXN0ZShuYW1lcyh0YWJsZShhY2NlcHRlZF9kYXRhJEV0aG5pY2l0eS5zaW1wbGlmaWVkKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhYmxlKGFjY2VwdGVkX2RhdGEkRXRobmljaXR5LnNpbXBsaWZpZWQpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiOiAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9ICIsICIpCgojIExpc3QgYWxsIG5hdGlvbmFsaXRpZXMgd2l0aCBjb3VudHMKbmF0aW9uYWxpdHlfZGlzdHJpYnV0aW9uIDwtIHBhc3RlKG5hbWVzKHRhYmxlKGFjY2VwdGVkX2RhdGEkTmF0aW9uYWxpdHkpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWJsZShhY2NlcHRlZF9kYXRhJE5hdGlvbmFsaXR5KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiOiAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlID0gIiwgIikKCiMgQ2FsY3VsYXRlIHN0dWRlbnQgc3RhdHVzIGRpc3RyaWJ1dGlvbgpzdHVkZW50X3N0YXR1c19kaXN0cmlidXRpb24gPC0gcGFzdGUobmFtZXModGFibGUoYWNjZXB0ZWRfZGF0YSRTdHVkZW50LnN0YXR1cykpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhYmxlKGFjY2VwdGVkX2RhdGEkU3R1ZGVudC5zdGF0dXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcCA9ICI6ICIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSAiLCAiKQoKIyBDYWxjdWxhdGUgZW1wbG95bWVudCBzdGF0dXMgZGlzdHJpYnV0aW9uCmVtcGxveW1lbnRfc3RhdHVzX2Rpc3RyaWJ1dGlvbiA8LSBwYXN0ZShuYW1lcyh0YWJsZShhY2NlcHRlZF9kYXRhJEVtcGxveW1lbnQuc3RhdHVzKSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFibGUoYWNjZXB0ZWRfZGF0YSRFbXBsb3ltZW50LnN0YXR1cyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwID0gIjogIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZSA9ICIsICIpCgojIENvbXBpbGUgcmVzdWx0cyBpbnRvIGEgZGF0YSBmcmFtZQpkZW1vZ3JhcGhpY3Nfc3VtbWFyeSA8LSBkYXRhLmZyYW1lKAogIFN0YXRpc3RpYyA9IGMoCiAgICAiQWdlIChNZWFuLCBTRCkiLAogICAgIkdlbmRlciBEaXN0cmlidXRpb24iLAogICAgIkV0aG5pY2l0eSBEaXN0cmlidXRpb24iLAogICAgIk5hdGlvbmFsaXRpZXMiLAogICAgIlN0dWRlbnQgU3RhdHVzIERpc3RyaWJ1dGlvbiIsCiAgICAiRW1wbG95bWVudCBTdGF0dXMgRGlzdHJpYnV0aW9uIgogICksCiAgVmFsdWUgPSBjKAogICAgYWdlX3N1bW1hcnksCiAgICBnZW5kZXJfZGlzdHJpYnV0aW9uLAogICAgZXRobmljaXR5X2Rpc3RyaWJ1dGlvbiwKICAgIG5hdGlvbmFsaXR5X2Rpc3RyaWJ1dGlvbiwKICAgIHN0dWRlbnRfc3RhdHVzX2Rpc3RyaWJ1dGlvbiwKICAgIGVtcGxveW1lbnRfc3RhdHVzX2Rpc3RyaWJ1dGlvbgogICksCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCikKCiMgUHJpbnQgdGhlIHN1bW1hcnkgdGFibGUKcHJpbnQoZGVtb2dyYXBoaWNzX3N1bW1hcnkpCmBgYAoKIyBUaW1lbGluZSBkYXRhCgpgYGB7cn0KbGlicmFyeShEQkkpCmxpYnJhcnkoUlNRTGl0ZSkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKCiMgQ29ubmVjdCB0byBEQiBhbmQgbG9hZCBmaWx0ZXJlZCBkYXRhCmNvbiA8LSBkYkNvbm5lY3QoUlNRTGl0ZTo6U1FMaXRlKCksICJkYXRhYmFzZS5kYiIpCgpsb2FkX3BoYXNlIDwtIGZ1bmN0aW9uKHRhYmxlLCBwaGFzZSkgewogIGRiUmVhZFRhYmxlKGNvbiwgdGFibGUpICU+JQogICAgZmlsdGVyKHVzZXJfaWQgPj0gMCwgdXNlcl9pZCA8PSAyMDAwKSAlPiUKICAgIGFycmFuZ2UodXNlcl9pZCwgY3JlYXRlZF9hdCkgJT4lCiAgICBncm91cF9ieSh1c2VyX2lkKSAlPiUKICAgIG11dGF0ZShwaGFzZSA9IHBoYXNlLCBpbmRleCA9IHJvd19udW1iZXIoKSkgJT4lCiAgICB1bmdyb3VwKCkKfQoKIyBMb2FkIGVhY2ggcGhhc2UKcHJlIDwtIGxvYWRfcGhhc2UoImxpa2VydF9wcmUiLCAicHJlIikKbWlkIDwtIGxvYWRfcGhhc2UoImxpa2VydF9taWQiLCAibWlkIikKcG9zdCA8LSBsb2FkX3BoYXNlKCJsaWtlcnRfcG9zdCIsICJwb3N0IikKCiMgQ29tYmluZSBhbGwKYWxsX2RhdGEgPC0gYmluZF9yb3dzKHByZSwgbWlkLCBwb3N0KSAlPiUKICBtdXRhdGUoY3JlYXRlZF9hdCA9IHltZF9obXMoY3JlYXRlZF9hdCkpCgojIENyZWF0ZSBpbnRlcmxlYXZlZCBzdGVwIGxhYmVsOiBwcmVfMSwgbWlkXzEsIHBvc3RfMSwgLi4uLCBwb3N0XzQKYWxsX2RhdGEgPC0gYWxsX2RhdGEgJT4lCiAgbXV0YXRlKHN0ZXAgPSBwYXN0ZTAocGhhc2UsICJfIiwgaW5kZXgpKQoKIyBOb3JtYWxpemUgdGltZSBwZXIgdXNlciByZWxhdGl2ZSB0byB0aGVpciBmaXJzdCBzdWJtaXNzaW9uCmFsbF9kYXRhIDwtIGFsbF9kYXRhICU+JQogIGdyb3VwX2J5KHVzZXJfaWQpICU+JQogIGFycmFuZ2UoY3JlYXRlZF9hdCkgJT4lCiAgbXV0YXRlKHJlbF90aW1lID0gYXMubnVtZXJpYyhkaWZmdGltZShjcmVhdGVkX2F0LCBtaW4oY3JlYXRlZF9hdCksIHVuaXRzID0gIm1pbnMiKSkpICU+JQogIHVuZ3JvdXAoKQoKIyBTZXQgb3JkZXJlZCBmYWN0b3IgZm9yIGNvcnJlY3QgeC1heGlzIHNlcXVlbmNpbmcKIyBJbnRlcmxlYXZlZCBzdGVwIG9yZGVyOiBwcmVfMSwgbWlkXzEsIHBvc3RfMSwgLi4uLCBwb3N0XzQKc3RlcF9sZXZlbHMgPC0gYXMudmVjdG9yKHQob3V0ZXIoMTo0LCBjKCJwcmUiLCAibWlkIiwgInBvc3QiKSwgZnVuY3Rpb24oaSwgcCkgcGFzdGUwKHAsICJfIiwgaSkpKSkKYWxsX2RhdGEkc3RlcCA8LSBmYWN0b3IoYWxsX2RhdGEkc3RlcCwgbGV2ZWxzID0gc3RlcF9sZXZlbHMpCgojIFBsb3QgcHJvZ3Jlc3Npb24KZ2dwbG90KGFsbF9kYXRhLCBhZXMoeCA9IHN0ZXAsIHkgPSByZWxfdGltZSwgZ3JvdXAgPSB1c2VyX2lkLCBjb2xvciA9IGFzLmZhY3Rvcih1c2VyX2lkKSkpICsKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIuNSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJVc2VyIFByb2dyZXNzaW9uIEFjcm9zcyBBbGwgU3RlcHMgKFJlbGF0aXZlIFRpbWUpIiwKICAgIHggPSAiU3RlcCIsCiAgICB5ID0gIlRpbWUgU2luY2UgRmlyc3QgU3VibWlzc2lvbiAobWludXRlcykiLAogICAgY29sb3IgPSAiVXNlciBJRCIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCgoKIyBEaXNjb25uZWN0IGZyb20gZGF0YWJhc2UKZGJEaXNjb25uZWN0KGNvbikKCmBgYAoKIyBEYXRhIEludGVncml0eSBBc3NlcnRpb25zCgoqKkFzc2VydGlvbiAxOioqIFRoZSBwcmUtc2NvcmVzIGFyZSBub3Qgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgYWNyb3NzIGNvbmRpdGlvbnMuXAoqKkFzc2VydGlvbiAyOioqIFRoZSBwcmUtc2NvcmVzIGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBhY3Jvc3MgY29uZGl0aW9ucy4gKipBc3NlcnRpb24gMzoqKiBQYXJ0aWNpcGFudCBoYXMgZXhhY3RseSA0IGltaSBzY29yZXMgYW5kIGFyZSBpbiB0aGUgcmlnaHQgb3JkZXIgKGxlc3NvbiAwLCAxLCAyLCAzKSBiYXNlZCBvbiBzdWJtaXNzaW9uIHRpbWUKCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShwdXJycikKCiMgU1RFUCAxOiBFeHRyYWN0IGFuZCByZXNoYXBlIHByZSBzY29yZXMgZm9yIGNvbmRpdGlvbnMKY29uZGl0aW9uX3ByZSA8LSBkYXRhICU+JQogIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfcHJlX2NvbmRpdGlvblxcZCsiKSkgJT4lCiAgbXV0YXRlKGlkID0gcm93X251bWJlcigpKSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLWlkLAogICAgbmFtZXNfdG8gPSAiY29uZGl0aW9uIiwKICAgIG5hbWVzX3BhdHRlcm4gPSAibGlrZXJ0X3ByZV9jb25kaXRpb24oXFxkKykiLAogICAgdmFsdWVzX3RvID0gInNjb3JlIgogICkgJT4lCiAgbXV0YXRlKGNvbmRpdGlvbiA9IHBhc3RlMCgiQ29uZGl0aW9uICIsIGNvbmRpdGlvbikpCgojIFNURVAgMjogRXh0cmFjdCBhbmQgcmVzaGFwZSBwcmUgc2NvcmVzIGZvciBsZXNzb25zCmxlc3Nvbl9wcmUgPC0gZGF0YSAlPiUKICBzZWxlY3QobWF0Y2hlcygibGlrZXJ0X3ByZV9sZXNzb25cXGQrIikpICU+JQogIG11dGF0ZShpZCA9IHJvd19udW1iZXIoKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC1pZCwKICAgIG5hbWVzX3RvID0gImxlc3NvbiIsCiAgICBuYW1lc19wYXR0ZXJuID0gImxpa2VydF9wcmVfbGVzc29uKFxcZCspIiwKICAgIHZhbHVlc190byA9ICJzY29yZSIKICApICU+JQogIG11dGF0ZShsZXNzb24gPSBwYXN0ZTAoIkxlc3NvbiAiLCBsZXNzb24pKQoKIyBTVEVQIDM6IFBsb3QgcHJlIHNjb3JlcyBwZXIgY29uZGl0aW9uCnBsb3RfY29uZGl0aW9ucyA8LSBnZ3Bsb3QoY29uZGl0aW9uX3ByZSwgYWVzKHggPSBjb25kaXRpb24sIHkgPSBzY29yZSwgZmlsbCA9IGNvbmRpdGlvbikpICsKICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjYsIG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGdlb21fZG90cGxvdChiaW5heGlzID0gInkiLCBzdGFja2RpciA9ICJjZW50ZXIiLCBkb3RzaXplID0gMC41LCBhZXMoY29sb3IgPSBjb25kaXRpb24pKSArCiAgbGFicyh0aXRsZSA9ICJQcmUgU2NvcmVzIGJ5IENvbmRpdGlvbiIsIHggPSAiQ29uZGl0aW9uIiwgeSA9ICJQcmUgU2NvcmUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCgojIFNURVAgNDogUGxvdCBwcmUgc2NvcmVzIHBlciBMRVNTT04KcGxvdF9sZXNzb25zIDwtIGdncGxvdChsZXNzb25fcHJlLCBhZXMoeCA9IGxlc3NvbiwgeSA9IHNjb3JlLCBmaWxsID0gbGVzc29uKSkgKwogIGdlb21fYm94cGxvdChhbHBoYSA9IDAuNiwgb3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9kb3RwbG90KGJpbmF4aXMgPSAieSIsIHN0YWNrZGlyID0gImNlbnRlciIsIGRvdHNpemUgPSAwLjUsIGFlcyhjb2xvciA9IGxlc3NvbikpICsKICBsYWJzKHRpdGxlID0gIlByZSBTY29yZXMgYnkgTGVzc29uIiwgeCA9ICJMZXNzb24iLCB5ID0gIlByZSBTY29yZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCiMgU2hvdyBwbG90cwpwcmludChwbG90X2NvbmRpdGlvbnMpCnByaW50KHBsb3RfbGVzc29ucykKCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgUmVzaGFwZSBwcmUgY29uZGl0aW9uIHNjb3Jlcwpjb25kaXRpb25fcHJlIDwtIGRhdGEgJT4lCiAgc2VsZWN0KG1hdGNoZXMoImxpa2VydF9wcmVfY29uZGl0aW9uXFxkKyIpKSAlPiUKICBtdXRhdGUoaWQgPSByb3dfbnVtYmVyKCkpICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtaWQsCiAgICBuYW1lc190byA9ICJjb25kaXRpb24iLAogICAgbmFtZXNfcGF0dGVybiA9ICJsaWtlcnRfcHJlX2NvbmRpdGlvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBtdXRhdGUoY29uZGl0aW9uID0gZmFjdG9yKHBhc3RlMCgiQ29uZGl0aW9uICIsIGNvbmRpdGlvbikpKQoKIyBLcnVza2FsLVdhbGxpcyB0ZXN0Cmt3IDwtIGtydXNrYWwudGVzdChzY29yZSB+IGNvbmRpdGlvbiwgZGF0YSA9IGNvbmRpdGlvbl9wcmUpCgpjYXQoIktydXNrYWwtV2FsbGlzIHRlc3QgcC12YWx1ZToiLCBrdyRwLnZhbHVlLCAiXG4iKQoKIyBJZiBzaWduaWZpY2FudCwgcnVuIHBvc3QtaG9jIHBhaXJ3aXNlIFdpbGNveG9uIHRlc3RzCmlmIChrdyRwLnZhbHVlIDwgMC4wNSkgewogIGNhdCgiU2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgZm91bmQg4oCUIHBhaXJ3aXNlIFdpbGNveG9uIHRlc3RzOlxuIikKICBwdyA8LSBwYWlyd2lzZS53aWxjb3gudGVzdChjb25kaXRpb25fcHJlJHNjb3JlLCBjb25kaXRpb25fcHJlJGNvbmRpdGlvbiwgcC5hZGp1c3QubWV0aG9kID0gIkJIIikKICBwcmludChwdyRwLnZhbHVlKQp9IGVsc2UgewogIGNhdCgiTm8gc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgYmV0d2VlbiBjb25kaXRpb25zIGZvciBwcmUgc2NvcmVzLlxuIikKfQoKbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKCiMgUmVzaGFwZSBwcmUgbGVzc29uIHNjb3JlcwpsZXNzb25fcHJlIDwtIGRhdGEgJT4lCiAgc2VsZWN0KG1hdGNoZXMoImxpa2VydF9wcmVfbGVzc29uXFxkKyIpKSAlPiUKICBtdXRhdGUoaWQgPSByb3dfbnVtYmVyKCkpICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtaWQsCiAgICBuYW1lc190byA9ICJsZXNzb24iLAogICAgbmFtZXNfcGF0dGVybiA9ICJsaWtlcnRfcHJlX2xlc3NvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBtdXRhdGUobGVzc29uID0gZmFjdG9yKHBhc3RlMCgiTGVzc29uICIsIGxlc3NvbikpKQoKIyBLcnVza2FsLVdhbGxpcyB0ZXN0Cmt3IDwtIGtydXNrYWwudGVzdChzY29yZSB+IGxlc3NvbiwgZGF0YSA9IGxlc3Nvbl9wcmUpCgpjYXQoIktydXNrYWwtV2FsbGlzIHRlc3QgcC12YWx1ZSAoYnkgbGVzc29uKToiLCBrdyRwLnZhbHVlLCAiXG4iKQoKIyBQb3N0LWhvYyBwYWlyd2lzZSBXaWxjb3hvbiBpZiBzaWduaWZpY2FudAppZiAoa3ckcC52YWx1ZSA8IDAuMDUpIHsKICBjYXQoIlNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGZvdW5kIOKAlCBwYWlyd2lzZSBXaWxjb3hvbiB0ZXN0czpcbiIpCiAgcHcgPC0gcGFpcndpc2Uud2lsY294LnRlc3QobGVzc29uX3ByZSRzY29yZSwgbGVzc29uX3ByZSRsZXNzb24sIHAuYWRqdXN0Lm1ldGhvZCA9ICJCSCIpCiAgcHJpbnQocHckcC52YWx1ZSkKfSBlbHNlIHsKICBjYXQoIk5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGJldHdlZW4gbGVzc29ucyBmb3IgcHJlIHNjb3Jlcy5cbiIpCn0KCmBgYAoKIyBDZXJ0YWludHkKCiMjICEgQ2VydGFpbnR5IHBlciBDb25kaXRpb24KCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKCiMgRXh0cmFjdCBjb25kaXRpb24tcmVsYXRlZCBsaWtlcnQgY29sdW1ucwpjb25kaXRpb25fZGF0YSA8LSBkYXRhICU+JSBzZWxlY3QobWF0Y2hlcygibGlrZXJ0Xy4qX2NvbmRpdGlvbiIpKQoKIyBSZXNoYXBlIHRvIGxvbmcgZm9ybWF0CmxvbmdfY29uZGl0aW9uX2RhdGEgPC0gY29uZGl0aW9uX2RhdGEgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBldmVyeXRoaW5nKCksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gYygicGhhc2UiLCAiY29uZGl0aW9uIiksCiAgICAgICAgICAgICAgIG5hbWVzX3BhdHRlcm4gPSAibGlrZXJ0XyhwcmV8bWlkfHBvc3QpX2NvbmRpdGlvbihcXGQrKSIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJzY29yZSIpICU+JQogIG11dGF0ZShwaGFzZSA9IGZhY3RvcihwaGFzZSwgbGV2ZWxzID0gYygicHJlIiwgIm1pZCIsICJwb3N0IikpLAogICAgICAgICBjb25kaXRpb24gPSBwYXN0ZTAoImNvbmRpdGlvbiAiLCBjb25kaXRpb24pKQoKIyBTdW1tYXJpemUgYnkgcGhhc2UgYW5kIGNvbmRpdGlvbgpzdW1tYXJ5X2RhdGEgPC0gbG9uZ19jb25kaXRpb25fZGF0YSAlPiUKICBncm91cF9ieShwaGFzZSwgY29uZGl0aW9uKSAlPiUKICBzdW1tYXJpc2UobWVhbl9zY29yZSA9IG1lYW4oc2NvcmUsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpCgojIExpbmUgcGxvdDogNCBsaW5lcyAoY29uZGl0aW9ucyksIHgtYXhpcyBpcyBwaGFzZQpnZ3Bsb3Qoc3VtbWFyeV9kYXRhLCBhZXMoeCA9IHBoYXNlLCB5ID0gbWVhbl9zY29yZSwgZ3JvdXAgPSBjb25kaXRpb24sIGNvbG9yID0gY29uZGl0aW9uKSkgKwogIGdlb21fbGluZShzaXplID0gMS4yKSArCiAgZ2VvbV9wb2ludChzaXplID0gMykgKwogIGxhYnModGl0bGUgPSAiTWVhbiBMaWtlcnQgU2NvcmVzIHBlciBjb25kaXRpb24gT3ZlciBQaGFzZXMiLAogICAgICAgeCA9ICJQaGFzZSIsCiAgICAgICB5ID0gIk1lYW4gTGlrZXJ0IFNjb3JlIiwKICAgICAgIGNvbG9yID0gImNvbmRpdGlvbiIpICsKICB0aGVtZV9taW5pbWFsKCkKCmNvbmRpdGlvbl9kYXRhIDwtIGRhdGEgJT4lIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfLipfY29uZGl0aW9uIikpCgpsb25nX2NvbmRpdGlvbl9kYXRhIDwtIGNvbmRpdGlvbl9kYXRhICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSBldmVyeXRoaW5nKCksCiAgICBuYW1lc190byA9IGMoInBoYXNlIiwgImNvbmRpdGlvbiIpLAogICAgbmFtZXNfcGF0dGVybiA9ICJsaWtlcnRfKHByZXxtaWR8cG9zdClfY29uZGl0aW9uKFxcZCspIiwKICAgIHZhbHVlc190byA9ICJzY29yZSIKICApICU+JQogIG11dGF0ZSgKICAgIHBoYXNlID0gZmFjdG9yKHBoYXNlLCBsZXZlbHMgPSBjKCJwcmUiLCAibWlkIiwgInBvc3QiKSksCiAgICBjb25kaXRpb24gPSBmYWN0b3IocGFzdGUwKCJjb25kaXRpb24gIiwgY29uZGl0aW9uKSwgbGV2ZWxzID0gcGFzdGUwKCJjb25kaXRpb24gIiwgMTo0KSkKICApCgojIENhbGN1bGF0ZSBtZWFucyBmb3IgbGFiZWxzCm1lYW5zIDwtIGxvbmdfY29uZGl0aW9uX2RhdGEgJT4lCiAgZ3JvdXBfYnkoY29uZGl0aW9uLCBwaGFzZSkgJT4lCiAgc3VtbWFyaXNlKG1lYW5fc2NvcmUgPSBtZWFuKHNjb3JlLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQoKZ2dwbG90KGxvbmdfY29uZGl0aW9uX2RhdGEsIGFlcyh4ID0gcGhhc2UsIHkgPSBzY29yZSwgZmlsbCA9IHBoYXNlKSkgKwogIGdlb21fYm94cGxvdChwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwgYWxwaGEgPSAwLjUsIG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGdlb21faml0dGVyKGFlcyhjb2xvciA9IHBoYXNlKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjE1LCBkb2RnZS53aWR0aCA9IDAuOCksCiAgICAgICAgICAgICAgc2l6ZSA9IDIsIGFscGhhID0gMC43KSArCiAgZ2VvbV90ZXh0KGRhdGEgPSBtZWFucywgYWVzKHggPSBwaGFzZSwgeSA9IG1lYW5fc2NvcmUgKyAwLjE1LCBsYWJlbCA9IHJvdW5kKG1lYW5fc2NvcmUsIDIpKSwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgICAgIHNpemUgPSAzLCBmb250ZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiYmxhY2siKSArCiAgZmFjZXRfd3JhcCh+IGNvbmRpdGlvbiwgbnJvdyA9IDEpICsgICMgQWxsIGNvbmRpdGlvbnMgaW4gb25lIHJvdywgdmlzdWFsbHkgZ3JvdXBlZCBieSBmYWNldHMKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJwcmUiID0gIiNhNmNlZTMiLCAibWlkIiA9ICIjMWY3OGI0IiwgInBvc3QiID0gIiNiMmRmOGEiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJwcmUiID0gIiNhNmNlZTMiLCAibWlkIiA9ICIjMWY3OGI0IiwgInBvc3QiID0gIiNiMmRmOGEiKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJMaWtlcnQgU2NvcmVzIGJ5IFBoYXNlIGFuZCBjb25kaXRpb24gKG92ZXJhbGwpIiwKICAgIHggPSAiUGhhc2UiLAogICAgeSA9ICJMaWtlcnQgU2NvcmUiLAogICAgZmlsbCA9ICJQaGFzZSIsCiAgICBjb2xvciA9ICJQaGFzZSIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAjIGZhY2V0IGxhYmVsIHN0eWxlCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIgogICkKCgojIFByZXBhcmUgY29uZGl0aW9uX29yZGVyIGluIGxvbmcgZm9ybWF0CmNvbmRpdGlvbl9vcmRlcl9sb25nIDwtIGRhdGEgJT4lCiAgbXV0YXRlKGlkID0gcm93X251bWJlcigpKSAlPiUKICBzZXBhcmF0ZShjb25kaXRpb25fb3JkZXIsIGludG8gPSBwYXN0ZTAoImxlc3Nvbl8iLCAxOjQpLCBzZXAgPSAiLCIsIGNvbnZlcnQgPSBUUlVFKSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gc3RhcnRzX3dpdGgoImxlc3Nvbl8iKSwKICAgIG5hbWVzX3RvID0gImxlc3NvbiIsCiAgICBuYW1lc19wYXR0ZXJuID0gImxlc3Nvbl8oXFxkKykiLAogICAgdmFsdWVzX3RvID0gImNvbmRpdGlvbl9pbmRleCIKICApICU+JQogIG11dGF0ZSgKICAgIGxlc3NvbiA9IGFzLmludGVnZXIobGVzc29uKSwKICAgIGNvbmRpdGlvbiA9IGZhY3RvcihwYXN0ZTAoImNvbmRpdGlvbiAiLCBjb25kaXRpb25faW5kZXggKyAxKSwgbGV2ZWxzID0gcGFzdGUwKCJjb25kaXRpb24gIiwgMTo0KSkKICApICU+JQogIHNlbGVjdChpZCwgbGVzc29uLCBjb25kaXRpb24pCgojIFByZXBhcmUgbG9uZ19jb25kaXRpb25fZGF0YSB3aXRoIHBhcnRpY2lwYW50IGlkCmxvbmdfY29uZGl0aW9uX2RhdGEgPC0gZGF0YSAlPiUKICBtdXRhdGUoaWQgPSByb3dfbnVtYmVyKCkpICU+JQogIHNlbGVjdChpZCwgbWF0Y2hlcygibGlrZXJ0Xy4qX2NvbmRpdGlvbiIpKSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLWlkLAogICAgbmFtZXNfdG8gPSBjKCJwaGFzZSIsICJjb25kaXRpb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAibGlrZXJ0XyhwcmV8bWlkfHBvc3QpX2NvbmRpdGlvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwaGFzZSA9IGZhY3RvcihwaGFzZSwgbGV2ZWxzID0gYygicHJlIiwgIm1pZCIsICJwb3N0IikpLAogICAgY29uZGl0aW9uID0gZmFjdG9yKHBhc3RlMCgiY29uZGl0aW9uICIsIGNvbmRpdGlvbiksIGxldmVscyA9IHBhc3RlMCgiY29uZGl0aW9uICIsIDE6NCkpCiAgKQoKIyBKb2luIGxlc3NvbiBpbmZvIHRvIGNvbmRpdGlvbiBkYXRhCmxvbmdfY29uZGl0aW9uX3dpdGhfbGVzc29uIDwtIGxvbmdfY29uZGl0aW9uX2RhdGEgJT4lCiAgbGVmdF9qb2luKGNvbmRpdGlvbl9vcmRlcl9sb25nLCBieSA9IGMoImlkIiwgImNvbmRpdGlvbiIpKQoKIyBUaXRsZXMgZm9yIGVhY2ggbGVzc29uCmNvbXBhcmlzb25fdGl0bGVzIDwtIHBhc3RlKCJMZXNzb24iLCAxOjQpCgojIEdlbmVyYXRlIHBsb3RzIGZvciBlYWNoIGxlc3NvbiBhbmQgcHJpbnQKZm9yIChsZXNzb25fbnVtIGluIDE6NCkgewogIHBsb3RfZGF0YSA8LSBsb25nX2NvbmRpdGlvbl93aXRoX2xlc3NvbiAlPiUgZmlsdGVyKGxlc3NvbiA9PSBsZXNzb25fbnVtKQogIAogIG1lYW5zX2xlc3NvbiA8LSBwbG90X2RhdGEgJT4lCiAgICBncm91cF9ieShjb25kaXRpb24sIHBoYXNlKSAlPiUKICAgIHN1bW1hcmlzZShtZWFuX3Njb3JlID0gbWVhbihzY29yZSwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikKICAKICBwIDwtIGdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0gcGhhc2UsIHkgPSBzY29yZSwgZmlsbCA9IHBoYXNlKSkgKwogICAgZ2VvbV9ib3hwbG90KHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLCBhbHBoYSA9IDAuNSwgb3V0bGllci5zaGFwZSA9IE5BKSArCiAgICBnZW9tX2ppdHRlcihhZXMoY29sb3IgPSBwaGFzZSksIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xNSwgZG9kZ2Uud2lkdGggPSAwLjgpLAogICAgICAgICAgICAgICAgc2l6ZSA9IDIsIGFscGhhID0gMC43KSArCiAgICBnZW9tX3RleHQoZGF0YSA9IG1lYW5zX2xlc3NvbiwgYWVzKHggPSBwaGFzZSwgeSA9IG1lYW5fc2NvcmUgKyAwLjE1LCBsYWJlbCA9IHJvdW5kKG1lYW5fc2NvcmUsIDIpKSwKICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwgaW5oZXJpdC5hZXMgPSBGQUxTRSwKICAgICAgICAgICAgICBzaXplID0gMywgZm9udGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gImJsYWNrIikgKwogICAgZmFjZXRfd3JhcCh+IGNvbmRpdGlvbiwgbnJvdyA9IDEpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInByZSIgPSAiI2E2Y2VlMyIsICJtaWQiID0gIiMxZjc4YjQiLCAicG9zdCIgPSAiI2IyZGY4YSIpKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygicHJlIiA9ICIjYTZjZWUzIiwgIm1pZCIgPSAiIzFmNzhiNCIsICJwb3N0IiA9ICIjYjJkZjhhIikpICsKICAgIGxhYnMoCiAgICAgIHRpdGxlID0gcGFzdGUoIkxpa2VydCBTY29yZXMgYnkgUGhhc2UgYW5kIGNvbmRpdGlvbiAtIiwgY29tcGFyaXNvbl90aXRsZXNbbGVzc29uX251bV0pLAogICAgICB4ID0gIlBoYXNlIiwKICAgICAgeSA9ICJMaWtlcnQgU2NvcmUiLAogICAgICBmaWxsID0gIlBoYXNlIiwKICAgICAgY29sb3IgPSAiUGhhc2UiCiAgICApICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZSgKICAgICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLAogICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIgogICAgKQogIAogIHByaW50KHApCn0KCgpgYGAKCiMjICEgQ2VydGFpbnR5IHBlciBDb25kaXRpb24gLSBBTk9WQQoKYGBge3J9CmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgUmVzaGFwZSBjb25kaXRpb24tcmVsYXRlZCBMaWtlcnQgY29sdW1ucwpjb25kaXRpb25fZGF0YSA8LSBkYXRhICU+JSBzZWxlY3QobWF0Y2hlcygibGlrZXJ0Xy4qX2NvbmRpdGlvbiIpKQoKbG9uZ19jb25kaXRpb25fZGF0YSA8LSBjb25kaXRpb25fZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gZXZlcnl0aGluZygpLAogICAgbmFtZXNfdG8gPSBjKCJwaGFzZSIsICJjb25kaXRpb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAibGlrZXJ0XyhwcmV8bWlkfHBvc3QpX2NvbmRpdGlvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwaGFzZSA9IGZhY3RvcihwaGFzZSwgbGV2ZWxzID0gYygicHJlIiwgIm1pZCIsICJwb3N0IikpLAogICAgY29uZGl0aW9uID0gZmFjdG9yKHBhc3RlMCgiY29uZGl0aW9uICIsIGNvbmRpdGlvbiksIGxldmVscyA9IHBhc3RlMCgiY29uZGl0aW9uICIsIDE6NCkpCiAgKQoKcHJpbnQoIlxuXG5JcyB0aGVyZSBhIGRpZmZlcmVuY2UgYmV0d2VlbiBjb25kaXRpb25zIGZvciBwcmUsIG1pZCBvciBwb3N0IHZhbHVlcz8iKQojIEZ1bmN0aW9uIHRvIHJ1biBLcnVza2FsLVdhbGxpcyArIHBhaXJ3aXNlIFdpbGNveG9uIGZvciBvbmUgcGhhc2UKdGVzdF9waGFzZSA8LSBmdW5jdGlvbihwaGFzZV9uYW1lKSB7CiAgZGYgPC0gbG9uZ19jb25kaXRpb25fZGF0YSAlPiUgZmlsdGVyKHBoYXNlID09IHBoYXNlX25hbWUpCiAgCiAga3cgPC0ga3J1c2thbC50ZXN0KHNjb3JlIH4gY29uZGl0aW9uLCBkYXRhID0gZGYpCiAgCiAgY2F0KCJcblBoYXNlOiIsIHBoYXNlX25hbWUsICJcbiIpCiAgY2F0KCJLcnVza2FsLVdhbGxpcyBwLXZhbHVlOiIsIGt3JHAudmFsdWUsICJcbiIpCiAgCiAgaWYgKGt3JHAudmFsdWUgPCAwLjA1KSB7CiAgICBjYXQoIlNpZ25pZmljYW50IGRpZmZlcmVuY2UgZm91bmQsIHJ1bm5pbmcgcGFpcndpc2UgV2lsY294b24gdGVzdHM6XG4iKQogICAgcHcgPC0gcGFpcndpc2Uud2lsY294LnRlc3QoZGYkc2NvcmUsIGRmJGNvbmRpdGlvbiwgcC5hZGp1c3QubWV0aG9kID0gIkJIIikKICAgIHByaW50KHB3JHAudmFsdWUpCiAgfSAKfQoKIyBSdW4gdGVzdHMgZm9yIGVhY2ggcGhhc2UKZm9yIChwaCBpbiBsZXZlbHMobG9uZ19jb25kaXRpb25fZGF0YSRwaGFzZSkpIHsKICB0ZXN0X3BoYXNlKHBoKQp9CgpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkocHVycnIpCgojIFN0ZXAgMTogUmVzaGFwZSBsaWtlcnQgY29sdW1ucyB0byBsb25nIGZvcm1hdApjb25kaXRpb25fZGF0YSA8LSBkYXRhICU+JQogIHNlbGVjdChjb25kaXRpb25fb3JkZXIsIG1hdGNoZXMoImxpa2VydF8uKl9jb25kaXRpb25cXGQrIikpCgpsb25nX2NvbmRpdGlvbl9kYXRhIDwtIGNvbmRpdGlvbl9kYXRhICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtY29uZGl0aW9uX29yZGVyLAogICAgbmFtZXNfdG8gPSBjKCJwaGFzZSIsICJjb25kaXRpb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAibGlrZXJ0XyhwcmV8bWlkfHBvc3QpX2NvbmRpdGlvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBtdXRhdGUoCiAgICBjb25kaXRpb24gPSBhcy5pbnRlZ2VyKGNvbmRpdGlvbiksCiAgICBwaGFzZSA9IGZhY3RvcihwaGFzZSwgbGV2ZWxzID0gYygicHJlIiwgIm1pZCIsICJwb3N0IikpCiAgKQoKIyBTdGVwIDI6IE1hcCBlYWNoIGNvbmRpdGlvbiB0byBpdHMgbGVzc29uIHVzaW5nIGNvbmRpdGlvbl9vcmRlcgpsb25nX2NvbmRpdGlvbl9kYXRhIDwtIGxvbmdfY29uZGl0aW9uX2RhdGEgJT4lCiAgbXV0YXRlKAogICAgbGVzc29uID0gbWFwMl9pbnQoY29uZGl0aW9uX29yZGVyLCBjb25kaXRpb24sIH4gewogICAgICAjIFNwbGl0IHRoZSBjb25kaXRpb25fb3JkZXIgc3RyaW5nIGludG8gbnVtZXJpYyB2ZWN0b3IKICAgICAgbGVzc29uX3ZlY3RvciA8LSBhcy5pbnRlZ2VyKHN0cl9zcGxpdCgueCwgIiwiLCBzaW1wbGlmeSA9IFRSVUUpKQogICAgICAjIFJldHVybiB0aGUgbGVzc29uIGluZGV4IGZvciB0aGF0IGNvbmRpdGlvbgogICAgICBsZXNzb25fdmVjdG9yWy55ICsgMV0gICMgY29uZGl0aW9uIGlzIDAtYmFzZWQgaW5kZXggaW4gY29uZGl0aW9uX29yZGVyCiAgICB9KQogICkKCgojIFN0ZXAgMzogRnVuY3Rpb24gdG8gdGVzdCB3aXRoaW4gb25lIGxlc3Nvbgp0ZXN0X2xlc3Nvbl9waGFzZXMgPC0gZnVuY3Rpb24obGVzc29uX2lkKSB7CiAgY2F0KCJcblxuTGVzc29uOiIsIGxlc3Nvbl9pZCwgIiIpCiAgCiAgbGVzc29uX2RhdGEgPC0gbG9uZ19jb25kaXRpb25fZGF0YSAlPiUgZmlsdGVyKGxlc3NvbiA9PSBsZXNzb25faWQpCiAgCiAgZm9yIChwaCBpbiBsZXZlbHMobGVzc29uX2RhdGEkcGhhc2UpKSB7CiAgICBkZiA8LSBsZXNzb25fZGF0YSAlPiUgZmlsdGVyKHBoYXNlID09IHBoKQogICAgCiAgICBrdyA8LSBrcnVza2FsLnRlc3Qoc2NvcmUgfiBmYWN0b3IoY29uZGl0aW9uKSwgZGF0YSA9IGRmKQogICAgCiAgICBjYXQoIlxuUGhhc2U6IiwgcGgsICJcbiIpCiAgICBjYXQoIktydXNrYWwtV2FsbGlzIHAtdmFsdWU6Iiwga3ckcC52YWx1ZSwgIiIpCiAgICAKICAgIGlmIChrdyRwLnZhbHVlIDwgMC4wNSkgewogICAgICBjYXQoIlNpZ25pZmljYW50IGRpZmZlcmVuY2UgZm91bmQsIHJ1bm5pbmcgcGFpcndpc2UgV2lsY294b24gdGVzdHM6XG4iKQogICAgICBwdyA8LSBwYWlyd2lzZS53aWxjb3gudGVzdChkZiRzY29yZSwgZmFjdG9yKGRmJGNvbmRpdGlvbiksIHAuYWRqdXN0Lm1ldGhvZCA9ICJCSCIpCiAgICAgIHByaW50KHB3JHAudmFsdWUpCiAgICB9IAogIH0KfQoKcHJpbnQoIlxuXG5JcyB0aGVyZSBhIGRpZmZlcmVuY2UgYmV0d2VlbiBjb25kaXRpb25zIGZvciBwcmUsIG1pZCBvciBwb3N0IHZhbHVlcyBpbiBjZXJ0YWluIGxlc3NvbnM/IikKIyBTdGVwIDQ6IFJ1biB0aGUgdGVzdCBmb3IgZWFjaCBsZXNzb24gKDAgdG8gMykKZm9yIChsZXMgaW4gMDozKSB7CiAgdGVzdF9sZXNzb25fcGhhc2VzKGxlcykKfQpgYGAKCiMjIENlcnRhaW50eSBwZXIgTGVzc29uCgpgYGB7cn0KbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQoKIyBFeHRyYWN0IGxlc3Nvbi1yZWxhdGVkIGxpa2VydCBjb2x1bW5zCmxlc3Nvbl9kYXRhIDwtIGRhdGEgJT4lIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfLipfbGVzc29uIikpCgojIFJlc2hhcGUgdG8gbG9uZyBmb3JtYXQKbG9uZ19sZXNzb25fZGF0YSA8LSBsZXNzb25fZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGV2ZXJ5dGhpbmcoKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSBjKCJwaGFzZSIsICJsZXNzb24iKSwKICAgICAgICAgICAgICAgbmFtZXNfcGF0dGVybiA9ICJsaWtlcnRfKHByZXxtaWR8cG9zdClfbGVzc29uKFxcZCspIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInNjb3JlIikgJT4lCiAgbXV0YXRlKHBoYXNlID0gZmFjdG9yKHBoYXNlLCBsZXZlbHMgPSBjKCJwcmUiLCAibWlkIiwgInBvc3QiKSksCiAgICAgICAgIGxlc3NvbiA9IHBhc3RlMCgibGVzc29uICIsIGxlc3NvbikpCgojIFN1bW1hcml6ZSBieSBwaGFzZSBhbmQgbGVzc29uCnN1bW1hcnlfZGF0YSA8LSBsb25nX2xlc3Nvbl9kYXRhICU+JQogIGdyb3VwX2J5KHBoYXNlLCBsZXNzb24pICU+JQogIHN1bW1hcmlzZShtZWFuX3Njb3JlID0gbWVhbihzY29yZSwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikKCiMgTGluZSBwbG90OiA0IGxpbmVzIChsZXNzb25zKSwgeC1heGlzIGlzIHBoYXNlCmdncGxvdChzdW1tYXJ5X2RhdGEsIGFlcyh4ID0gcGhhc2UsIHkgPSBtZWFuX3Njb3JlLCBncm91cCA9IGxlc3NvbiwgY29sb3IgPSBsZXNzb24pKSArCiAgZ2VvbV9saW5lKHNpemUgPSAxLjIpICsKICBnZW9tX3BvaW50KHNpemUgPSAzKSArCiAgbGFicyh0aXRsZSA9ICJNZWFuIExpa2VydCBTY29yZXMgcGVyIGxlc3NvbiBPdmVyIFBoYXNlcyIsCiAgICAgICB4ID0gIlBoYXNlIiwKICAgICAgIHkgPSAiTWVhbiBMaWtlcnQgU2NvcmUiLAogICAgICAgY29sb3IgPSAibGVzc29uIikgKwogIHRoZW1lX21pbmltYWwoKQoKbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dzaWduaWYpCgpsZXNzb25fZGF0YSA8LSBkYXRhICU+JSBzZWxlY3QobWF0Y2hlcygibGlrZXJ0Xy4qX2xlc3NvbiIpKQoKbG9uZ19sZXNzb25fZGF0YSA8LSBsZXNzb25fZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gZXZlcnl0aGluZygpLAogICAgbmFtZXNfdG8gPSBjKCJwaGFzZSIsICJsZXNzb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAibGlrZXJ0XyhwcmV8bWlkfHBvc3QpX2xlc3NvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwaGFzZSA9IGZhY3RvcihwaGFzZSwgbGV2ZWxzID0gYygicHJlIiwgIm1pZCIsICJwb3N0IikpLAogICAgbGVzc29uID0gZmFjdG9yKHBhc3RlMCgiTGVzc29uICIsIGxlc3NvbiksIGxldmVscyA9IHBhc3RlMCgiTGVzc29uICIsIDE6NCkpCiAgKQoKIyBDYWxjdWxhdGUgbWVhbnMgZm9yIGxhYmVscwptZWFucyA8LSBsb25nX2xlc3Nvbl9kYXRhICU+JQogIGdyb3VwX2J5KGxlc3NvbiwgcGhhc2UpICU+JQogIHN1bW1hcmlzZShtZWFuX3Njb3JlID0gbWVhbihzY29yZSwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikKCmdncGxvdChsb25nX2xlc3Nvbl9kYXRhLCBhZXMoeCA9IHBoYXNlLCB5ID0gc2NvcmUsIGZpbGwgPSBwaGFzZSkpICsKICBnZW9tX2JveHBsb3QocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIGFscGhhID0gMC41LCBvdXRsaWVyLnNoYXBlID0gTkEpICsKICBnZW9tX2ppdHRlcihhZXMoY29sb3IgPSBwaGFzZSksIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4xNSwgZG9kZ2Uud2lkdGggPSAwLjgpLAogICAgICAgICAgICAgIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKwogIGdlb21fdGV4dChkYXRhID0gbWVhbnMsIGFlcyh4ID0gcGhhc2UsIHkgPSBtZWFuX3Njb3JlICsgMC4xNSwgbGFiZWwgPSByb3VuZChtZWFuX3Njb3JlLCAyKSksCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLCBpbmhlcml0LmFlcyA9IEZBTFNFLAogICAgICAgICAgICBzaXplID0gMywgZm9udGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fc2lnbmlmKAogICAgY29tcGFyaXNvbnMgPSBsaXN0KGMoInBvc3QiKSksCiAgICBtYXBfc2lnbmlmX2xldmVsID0gVFJVRQogICkgKwogIGZhY2V0X3dyYXAofiBsZXNzb24sIG5yb3cgPSAxKSArICAjIEFsbCBsZXNzb25zIGluIG9uZSByb3csIHZpc3VhbGx5IGdyb3VwZWQgYnkgZmFjZXRzCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygicHJlIiA9ICIjYTZjZWUzIiwgIm1pZCIgPSAiIzFmNzhiNCIsICJwb3N0IiA9ICIjYjJkZjhhIikpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygicHJlIiA9ICIjYTZjZWUzIiwgIm1pZCIgPSAiIzFmNzhiNCIsICJwb3N0IiA9ICIjYjJkZjhhIikpICsKICBsYWJzKAogICAgdGl0bGUgPSAiTGlrZXJ0IFNjb3JlcyBieSBQaGFzZSBhbmQgTGVzc29uIiwKICAgIHggPSAiUGhhc2UiLAogICAgeSA9ICJMaWtlcnQgU2NvcmUiLAogICAgZmlsbCA9ICJQaGFzZSIsCiAgICBjb2xvciA9ICJQaGFzZSIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpLCAjIGZhY2V0IGxhYmVsIHN0eWxlCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIgogICkKCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3NpZ25pZikKCiMgWW91ciBsb25nX2xlc3Nvbl9kYXRhIGlzIGFscmVhZHkgZmluZQoKIyBEZWZpbmUgbGVzc29uIGNvbXBhcmlzb25zIChwYWlyd2lzZSBiZXR3ZWVuIGFsbCA0IGxlc3NvbnMpCmxlc3Nvbl9jb21wYXJpc29ucyA8LSBjb21ibihsZXZlbHMobG9uZ19sZXNzb25fZGF0YSRsZXNzb24pLCAyLCBzaW1wbGlmeSA9IEZBTFNFKQoKIyBQbG90OiBYID0gbGVzc29uLCBmYWNldCBieSBwaGFzZQpnZ3Bsb3QobG9uZ19sZXNzb25fZGF0YSwgYWVzKHggPSBsZXNzb24sIHkgPSBzY29yZSwgZmlsbCA9IGxlc3NvbikpICsKICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjUsIG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGdlb21faml0dGVyKGFlcyhjb2xvciA9IGxlc3NvbiksIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMC4xNSksIHNpemUgPSAyLCBhbHBoYSA9IDAuNykgKwogIGdlb21fc2lnbmlmKAogICAgY29tcGFyaXNvbnMgPSBsZXNzb25fY29tcGFyaXNvbnMsCiAgICBzdGVwX2luY3JlYXNlID0gMC4yLAogICAgbWFwX3NpZ25pZl9sZXZlbD1jKCIqKioiPTAuMDAxLCIqKiI9MC4wMSwgIioiPTAuMDUsICIgIj0yKSwKICAgIHRlc3QgPSAid2lsY294LnRlc3QiCiAgKSArCiAgZmFjZXRfd3JhcCh+IHBoYXNlLCBucm93ID0gMSkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpICsKICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZSA9ICJTZXQyIikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJMaWtlcnQgU2NvcmVzIEFjcm9zcyBMZXNzb25zIChieSBQaGFzZSkiLAogICAgeCA9ICJMZXNzb24iLAogICAgeSA9ICJMaWtlcnQgU2NvcmUiLAogICAgZmlsbCA9ICJMZXNzb24iLAogICAgY29sb3IgPSAiTGVzc29uIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUoCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIgogICkKCgpgYGAKCiMjIENlcnRhaW50eSBwZXIgTGVzc29uIC0gQU5PVkEKCioqRmluZGluZyoqIEtydXNrYWwtV2FsbGlzIHNob3dzIHRoZXJlIGlzIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiBsZXNzb25zIGluIHRoZWlyIHByZSBzY29yZXMgKHAgXDwgMC4wNSkgYW5kIHBvc3Qgc2NvcmVzIChwIFw8IDAuMDUpLiBQYWlyd2lzZSBXaWxjb3hvbiB0ZXN0IHNob3dzIExlc3NvbiA0IGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50IGZyb20gTGVzc29ucyAxIGFuZCAyIGluIHByZSBzY29yZXMgKHAgXDwgMC4wNSkgYW5kIExlc3NvbiAxIGluIHBvc3Qgc2NvcmVzIChwIFw8IDAuMDUpLgoKYGBge3J9CgpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQoKIyBTZWxlY3QgbGVzc29uLXJlbGF0ZWQgTGlrZXJ0IGNvbHVtbnMKbGVzc29uX2RhdGEgPC0gZGF0YSAlPiUgc2VsZWN0KG1hdGNoZXMoImxpa2VydF8uKl9sZXNzb24iKSkKCiMgUmVzaGFwZSB0byBsb25nIGZvcm1hdDogaWQsIHBoYXNlLCBsZXNzb24sIHNjb3JlCmxvbmdfbGVzc29uX2RhdGEgPC0gbGVzc29uX2RhdGEgJT4lCiAgbXV0YXRlKGlkID0gcm93X251bWJlcigpKSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLWlkLAogICAgbmFtZXNfdG8gPSBjKCJwaGFzZSIsICJsZXNzb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAibGlrZXJ0XyhwcmV8bWlkfHBvc3QpX2xlc3NvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwaGFzZSA9IGZhY3RvcihwaGFzZSwgbGV2ZWxzID0gYygicHJlIiwgIm1pZCIsICJwb3N0IikpLAogICAgbGVzc29uID0gcGFzdGUwKCJMZXNzb24gIiwgbGVzc29uKQogICkKCiMgUnVuIEtydXNrYWwtV2FsbGlzIHRlc3QgZm9yIGVhY2ggcGhhc2UgY29tcGFyaW5nIGxlc3NvbnMKa3J1c2thbF9waGFzZSA8LSBsb25nX2xlc3Nvbl9kYXRhICU+JQogIGdyb3VwX2J5KHBoYXNlKSAlPiUKICBzdW1tYXJpc2UoCiAgICBrcnVza2FsX3AgPSBrcnVza2FsLnRlc3Qoc2NvcmUgfiBsZXNzb24pJHAudmFsdWUKICApCgpwcmludChrcnVza2FsX3BoYXNlKQoKIyBPbmx5IGZvciBwaGFzZXMgd2l0aCBzaWduaWZpY2FudCBLcnVza2FsLVdhbGxpcyByZXN1bHRzCnNpZ25pZmljYW50X3BoYXNlcyA8LSBrcnVza2FsX3BoYXNlICU+JSBmaWx0ZXIoa3J1c2thbF9wIDwgMC4wNSkgJT4lIHB1bGwocGhhc2UpCgpmb3IgKHBoIGluIHNpZ25pZmljYW50X3BoYXNlcykgewogIGNhdCgiXG49PT0gUGhhc2U6IiwgcGgsICI9PT1cbiIpCiAgZGYgPC0gbG9uZ19sZXNzb25fZGF0YSAlPiUgZmlsdGVyKHBoYXNlID09IHBoKQogIAogICMgUGFpcndpc2UgV2lsY294b24KICBwYWlyd2lzZV9yZXN1bHQgPC0gcGFpcndpc2Uud2lsY294LnRlc3QoZGYkc2NvcmUsIGRmJGxlc3NvbiwgcC5hZGp1c3QubWV0aG9kID0gIkJIIikKICAKICBwcmludChwYWlyd2lzZV9yZXN1bHQkcC52YWx1ZSkKfQoKYGBgCgojIyBDZXJ0YWludHkgRGVsdGFzIHBlciBDb25kaXRpb24KCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCgojIEV4dHJhY3QgYW5kIHJlc2hhcGUgY29uZGl0aW9uLXJlbGF0ZWQgbGlrZXJ0IGNvbHVtbnMKY29uZGl0aW9uX2RhdGEgPC0gZGF0YSAlPiUgc2VsZWN0KG1hdGNoZXMoImxpa2VydF8uKl9jb25kaXRpb24iKSkKCmxvbmdfY29uZGl0aW9uX2RhdGEgPC0gY29uZGl0aW9uX2RhdGEgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IGV2ZXJ5dGhpbmcoKSwKICAgIG5hbWVzX3RvID0gYygicGhhc2UiLCAiY29uZGl0aW9uIiksCiAgICBuYW1lc19wYXR0ZXJuID0gImxpa2VydF8ocHJlfG1pZHxwb3N0KV9jb25kaXRpb24oXFxkKykiLAogICAgdmFsdWVzX3RvID0gInNjb3JlIgogICkgJT4lCiAgbXV0YXRlKAogICAgcGhhc2UgPSBmYWN0b3IocGhhc2UsIGxldmVscyA9IGMoInByZSIsICJtaWQiLCAicG9zdCIpKSwKICAgIGNvbmRpdGlvbiA9IHBhc3RlMCgiY29uZGl0aW9uICIsIGNvbmRpdGlvbikKICApCgojIENvbXB1dGUgbWVhbiBzY29yZXMgcGVyIHBoYXNlIGFuZCBjb25kaXRpb24KbWVhbl9zY29yZXMgPC0gbG9uZ19jb25kaXRpb25fZGF0YSAlPiUKICBncm91cF9ieShjb25kaXRpb24sIHBoYXNlKSAlPiUKICBzdW1tYXJpc2UobWVhbl9zY29yZSA9IG1lYW4oc2NvcmUsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpCgojIEpvaW4gd2l0aCBwcmUgc2NvcmVzIHRvIGNvbXB1dGUgZGlmZmVyZW5jZQpwcmVfc2NvcmVzIDwtIG1lYW5fc2NvcmVzICU+JSBmaWx0ZXIocGhhc2UgPT0gInByZSIpICU+JQogIHJlbmFtZShwcmVfc2NvcmUgPSBtZWFuX3Njb3JlKSAlPiUKICBzZWxlY3QoY29uZGl0aW9uLCBwcmVfc2NvcmUpCgpkaWZmX2RhdGEgPC0gbWVhbl9zY29yZXMgJT4lCiAgbGVmdF9qb2luKHByZV9zY29yZXMsIGJ5ID0gImNvbmRpdGlvbiIpICU+JQogIG11dGF0ZShkaWZmX2Zyb21fcHJlID0gbWVhbl9zY29yZSAtIHByZV9zY29yZSkKCiMgUGxvdCBkaWZmZXJlbmNlcywgd2l0aCBwcmUgYXMgYmFzZWxpbmUgKDApLCBtaWQvcG9zdCBhcyBkZWx0YXMKZ2dwbG90KGRpZmZfZGF0YSwgYWVzKHggPSBwaGFzZSwgeSA9IGRpZmZfZnJvbV9wcmUsIGdyb3VwID0gY29uZGl0aW9uLCBjb2xvciA9IGNvbmRpdGlvbikpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDEuMikgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsKICBsYWJzKAogICAgdGl0bGUgPSAiTWVhbiBMaWtlcnQgU2NvcmUgQ2hhbmdlcyBSZWxhdGl2ZSB0byBQcmUiLAogICAgeCA9ICJQaGFzZSIsCiAgICB5ID0gIlNjb3JlIERpZmZlcmVuY2UgZnJvbSBQcmUiLAogICAgY29sb3IgPSAiY29uZGl0aW9uIgogICkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImdyYXkiKSArCiAgdGhlbWVfbWluaW1hbCgpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgRXh0cmFjdCBhbmQgcmVzaGFwZSBjb25kaXRpb24tcmVsYXRlZCBMaWtlcnQgY29sdW1ucwpjb25kaXRpb25fZGF0YSA8LSBkYXRhICU+JSBzZWxlY3QobWF0Y2hlcygibGlrZXJ0Xy4qX2NvbmRpdGlvbiIpKQoKIyBMb25nIGZvcm1hdCB3aXRoIHBoYXNlIGFuZCBjb25kaXRpb24KbG9uZ19jb25kaXRpb25fZGF0YSA8LSBjb25kaXRpb25fZGF0YSAlPiUKICBtdXRhdGUoaWQgPSByb3dfbnVtYmVyKCkpICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtaWQsCiAgICBuYW1lc190byA9IGMoInBoYXNlIiwgImNvbmRpdGlvbiIpLAogICAgbmFtZXNfcGF0dGVybiA9ICJsaWtlcnRfKHByZXxtaWR8cG9zdClfY29uZGl0aW9uKFxcZCspIiwKICAgIHZhbHVlc190byA9ICJzY29yZSIKICApICU+JQogIG11dGF0ZSgKICAgIHBoYXNlID0gZmFjdG9yKHBoYXNlLCBsZXZlbHMgPSBjKCJwcmUiLCAibWlkIiwgInBvc3QiKSksCiAgICBjb25kaXRpb24gPSBwYXN0ZTAoImNvbmRpdGlvbiAiLCBjb25kaXRpb24pCiAgKQoKIyBDYWxjdWxhdGUgZGlmZmVyZW5jZXM6IG1pZC1wcmUsIHBvc3QtcHJlLCBhbmQgcG9zdC1taWQKcGl2b3RlZCA8LSBsb25nX2NvbmRpdGlvbl9kYXRhICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBwaGFzZSwgdmFsdWVzX2Zyb20gPSBzY29yZSkgJT4lCiAgbXV0YXRlKAogICAgZGlmZl9taWQgPSBtaWQgLSBwcmUsCiAgICBkaWZmX3Bvc3QgPSBwb3N0IC0gcHJlLAogICAgZGlmZl9taWRfcG9zdCA9IHBvc3QgLSBtaWQKICApICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSBjKGRpZmZfbWlkLCBkaWZmX3Bvc3QsIGRpZmZfbWlkX3Bvc3QpLAogICAgbmFtZXNfdG8gPSAicGhhc2UiLAogICAgdmFsdWVzX3RvID0gImRpZmZfZnJvbV9wcmUiCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwaGFzZSA9IHJlY29kZShwaGFzZSwKICAgICAgICAgICAgICAgICAgIGRpZmZfbWlkID0gIm1pZC1wcmUiLAogICAgICAgICAgICAgICAgICAgZGlmZl9wb3N0ID0gInBvc3QtcHJlIiwKICAgICAgICAgICAgICAgICAgIGRpZmZfbWlkX3Bvc3QgPSAicG9zdC1taWQiKSwKICAgIHBoYXNlID0gZmFjdG9yKHBoYXNlLCBsZXZlbHMgPSBjKCJtaWQtcHJlIiwgInBvc3QtcHJlIiwgInBvc3QtbWlkIikpCiAgKQoKIyBDYWxjdWxhdGUgbWVhbnMgZm9yIGxhYmVscy9wb2ludHMKbWVhbnMgPC0gcGl2b3RlZCAlPiUKICBncm91cF9ieShjb25kaXRpb24sIHBoYXNlKSAlPiUKICBzdW1tYXJpc2UobWVhbl92YWwgPSBtZWFuKGRpZmZfZnJvbV9wcmUsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpCgojIFBsb3QgYWxsIGNvbmRpdGlvbnMgc2lkZSBieSBzaWRlLCBwaGFzZSBhcyBmaWxsIGRvZGdlLCB3aXRoIG1lYW4gcG9pbnRzCmdncGxvdChwaXZvdGVkLCBhZXMoeCA9IGNvbmRpdGlvbiwgeSA9IGRpZmZfZnJvbV9wcmUsIGZpbGwgPSBwaGFzZSkpICsKICBnZW9tX2JveHBsb3QocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIGFscGhhID0gMC41LCBvdXRsaWVyLnNoYXBlID0gTkEpICsKICBnZW9tX2ppdHRlcihhZXMoY29sb3IgPSBwaGFzZSksIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2Uoaml0dGVyLndpZHRoID0gMC4yLCBkb2RnZS53aWR0aCA9IDAuOCksIGFscGhhID0gMC43LCBzaXplID0gMikgKwogIGdlb21fcG9pbnQoZGF0YSA9IG1lYW5zLCBhZXMoeCA9IGNvbmRpdGlvbiwgeSA9IG1lYW5fdmFsLCBncm91cCA9IHBoYXNlKSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzLCBzaGFwZSA9IDE4KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTE1LCAxNSkpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRGlmZmVyZW5jZXMgYmV0d2VlbiBQaGFzZXMgcGVyIGNvbmRpdGlvbiIsCiAgICB4ID0gImNvbmRpdGlvbiIsCiAgICB5ID0gIlNjb3JlIERpZmZlcmVuY2UiLAogICAgZmlsbCA9ICJQaGFzZSBDb21wYXJpc29uIiwKICAgIGNvbG9yID0gIlBoYXNlIENvbXBhcmlzb24iCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5IikKCmBgYAoKIyMgQ2VydGFpbnR5IERlbHRhcyBwZXIgQ29uZGl0aW9uIC0gQU5PVkEKCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCgojIEV4dHJhY3QgYW5kIHJlc2hhcGUgb25seSBjb25kaXRpb24tcmVsYXRlZCBMaWtlcnQgY29sdW1ucwpjb25kaXRpb25fZGF0YSA8LSBkYXRhICU+JSBzZWxlY3QobWF0Y2hlcygibGlrZXJ0Xy4qX2NvbmRpdGlvbiIpKQoKIyBMb25nIGZvcm1hdCB3aXRoIHBoYXNlIGFuZCBjb25kaXRpb24KbG9uZ19jb25kaXRpb25fZGF0YSA8LSBjb25kaXRpb25fZGF0YSAlPiUKICBtdXRhdGUoaWQgPSByb3dfbnVtYmVyKCkpICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtaWQsCiAgICBuYW1lc190byA9IGMoInBoYXNlIiwgImNvbmRpdGlvbiIpLAogICAgbmFtZXNfcGF0dGVybiA9ICJsaWtlcnRfKHByZXxtaWR8cG9zdClfY29uZGl0aW9uKFxcZCspIiwKICAgIHZhbHVlc190byA9ICJzY29yZSIKICApICU+JQogIG11dGF0ZSgKICAgIHBoYXNlID0gZmFjdG9yKHBoYXNlLCBsZXZlbHMgPSBjKCJwcmUiLCAibWlkIiwgInBvc3QiKSksCiAgICBjb25kaXRpb24gPSBwYXN0ZTAoImNvbmRpdGlvbiAiLCBjb25kaXRpb24pCiAgKQoKIyBDYWxjdWxhdGUgZGlmZmVyZW5jZXMgZnJvbSBwcmUgcGVyIGluZGl2aWR1YWwgYW5kIGNvbmRpdGlvbgpkZWx0YV9kYXRhIDwtIGxvbmdfY29uZGl0aW9uX2RhdGEgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHBoYXNlLCB2YWx1ZXNfZnJvbSA9IHNjb3JlKSAlPiUKICBtdXRhdGUoCiAgICBkaWZmX21pZCA9IG1pZCAtIHByZSwKICAgIGRpZmZfcG9zdCA9IHBvc3QgLSBwcmUKICApICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSBjKGRpZmZfbWlkLCBkaWZmX3Bvc3QpLAogICAgbmFtZXNfdG8gPSAicGhhc2UiLAogICAgdmFsdWVzX3RvID0gImRpZmZfZnJvbV9wcmUiCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwaGFzZSA9IHJlY29kZShwaGFzZSwgZGlmZl9taWQgPSAibWlkIiwgZGlmZl9wb3N0ID0gInBvc3QiKSwKICAgIHBoYXNlID0gZmFjdG9yKHBoYXNlLCBsZXZlbHMgPSBjKCJtaWQiLCAicG9zdCIpKQogICkKCiMgUGVyZm9ybSBTaGFwaXJvLVdpbGsgdGVzdCBieSBjb25kaXRpb24gYW5kIHBoYXNlCm5vcm1hbGl0eV90ZXN0cyA8LSBkZWx0YV9kYXRhICU+JQogIGdyb3VwX2J5KGNvbmRpdGlvbiwgcGhhc2UpICU+JQogIHN1bW1hcmlzZSgKICAgIHBfdmFsdWUgPSBzaGFwaXJvLnRlc3QoZGlmZl9mcm9tX3ByZSkkcC52YWx1ZSwKICAgIC5ncm91cHMgPSAiZHJvcCIKICApCgoKcHJpbnQoIlNoYXBpcm8tV2lsayBOb3JtYWxpdHkgVGVzdCAocCA8IDAuMDUgPSBub3Qgbm9ybWFsKToiKQpwcmludChub3JtYWxpdHlfdGVzdHMpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCiMgU2VsZWN0IGNvbmRpdGlvbi1yZWxhdGVkIExpa2VydCBjb2x1bW5zCmNvbmRpdGlvbl9kYXRhIDwtIGRhdGEgJT4lIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfLipfY29uZGl0aW9uIikpCgojIFJlc2hhcGUgdG8gbG9uZyBmb3JtYXQ6IGlkLCBwaGFzZSwgY29uZGl0aW9uLCBzY29yZQpsb25nX2NvbmRpdGlvbl9kYXRhIDwtIGNvbmRpdGlvbl9kYXRhICU+JQogIG11dGF0ZShpZCA9IHJvd19udW1iZXIoKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC1pZCwKICAgIG5hbWVzX3RvID0gYygicGhhc2UiLCAiY29uZGl0aW9uIiksCiAgICBuYW1lc19wYXR0ZXJuID0gImxpa2VydF8ocHJlfG1pZHxwb3N0KV9jb25kaXRpb24oXFxkKykiLAogICAgdmFsdWVzX3RvID0gInNjb3JlIgogICkgJT4lCiAgbXV0YXRlKAogICAgcGhhc2UgPSBmYWN0b3IocGhhc2UsIGxldmVscyA9IGMoInByZSIsICJtaWQiLCAicG9zdCIpKSwKICAgIGNvbmRpdGlvbiA9IHBhc3RlMCgiY29uZGl0aW9uICIsIGNvbmRpdGlvbikKICApCgojIFJ1biBLcnVza2FsLVdhbGxpcyB0ZXN0IGZvciBlYWNoIHBoYXNlIGNvbXBhcmluZyBjb25kaXRpb25zCmtydXNrYWxfcGhhc2UgPC0gbG9uZ19jb25kaXRpb25fZGF0YSAlPiUKICBncm91cF9ieShwaGFzZSkgJT4lCiAgc3VtbWFyaXNlKAogICAga3J1c2thbF9wID0ga3J1c2thbC50ZXN0KHNjb3JlIH4gY29uZGl0aW9uKSRwLnZhbHVlCiAgKQoKcHJpbnQoa3J1c2thbF9waGFzZSkKCmBgYAoKIyMgQ2VydGFpbnR5IERlbHRhcyBwZXIgTGVzc29uCgpgYGB7cn0KbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQoKIyBFeHRyYWN0IGFuZCByZXNoYXBlIGxlc3Nvbi1yZWxhdGVkIGxpa2VydCBjb2x1bW5zCmNvbmRpdGlvbl9kYXRhIDwtIGRhdGEgJT4lIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfLipfbGVzc29uIikpCgpsb25nX2xlc3Nvbl9kYXRhIDwtIGNvbmRpdGlvbl9kYXRhICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSBldmVyeXRoaW5nKCksCiAgICBuYW1lc190byA9IGMoInBoYXNlIiwgImxlc3NvbiIpLAogICAgbmFtZXNfcGF0dGVybiA9ICJsaWtlcnRfKHByZXxtaWR8cG9zdClfbGVzc29uKFxcZCspIiwKICAgIHZhbHVlc190byA9ICJzY29yZSIKICApICU+JQogIG11dGF0ZSgKICAgIHBoYXNlID0gZmFjdG9yKHBoYXNlLCBsZXZlbHMgPSBjKCJwcmUiLCAibWlkIiwgInBvc3QiKSksCiAgICBsZXNzb24gPSBwYXN0ZTAoImNvbmRpdGlvbiAiLCBsZXNzb24pCiAgKQoKIyBDb21wdXRlIG1lYW4gc2NvcmVzIHBlciBwaGFzZSBhbmQgbGVzc29uCm1lYW5fc2NvcmVzIDwtIGxvbmdfbGVzc29uX2RhdGEgJT4lCiAgZ3JvdXBfYnkobGVzc29uLCBwaGFzZSkgJT4lCiAgc3VtbWFyaXNlKG1lYW5fc2NvcmUgPSBtZWFuKHNjb3JlLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQoKIyBKb2luIHdpdGggcHJlIHNjb3JlcyB0byBjb21wdXRlIGRpZmZlcmVuY2UKcHJlX3Njb3JlcyA8LSBtZWFuX3Njb3JlcyAlPiUgZmlsdGVyKHBoYXNlID09ICJwcmUiKSAlPiUKICByZW5hbWUocHJlX3Njb3JlID0gbWVhbl9zY29yZSkgJT4lCiAgc2VsZWN0KGxlc3NvbiwgcHJlX3Njb3JlKQoKZGlmZl9kYXRhIDwtIG1lYW5fc2NvcmVzICU+JQogIGxlZnRfam9pbihwcmVfc2NvcmVzLCBieSA9ICJsZXNzb24iKSAlPiUKICBtdXRhdGUoZGlmZl9mcm9tX3ByZSA9IG1lYW5fc2NvcmUgLSBwcmVfc2NvcmUpCgojIFBsb3QgZGlmZmVyZW5jZXMsIHdpdGggcHJlIGFzIGJhc2VsaW5lICgwKSwgbWlkL3Bvc3QgYXMgZGVsdGFzCmdncGxvdChkaWZmX2RhdGEsIGFlcyh4ID0gcGhhc2UsIHkgPSBkaWZmX2Zyb21fcHJlLCBncm91cCA9IGxlc3NvbiwgY29sb3IgPSBsZXNzb24pKSArCiAgZ2VvbV9saW5lKHNpemUgPSAxLjIpICsKICBnZW9tX3BvaW50KHNpemUgPSAzKSArCiAgbGFicygKICAgIHRpdGxlID0gIk1lYW4gTGlrZXJ0IFNjb3JlIENoYW5nZXMgUmVsYXRpdmUgdG8gUHJlIiwKICAgIHggPSAiUGhhc2UiLAogICAgeSA9ICJTY29yZSBEaWZmZXJlbmNlIGZyb20gUHJlIiwKICAgIGNvbG9yID0gIkxlc3NvbiIKICApICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5IikgKwogIHRoZW1lX21pbmltYWwoKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCgoKIyBFeHRyYWN0IGFuZCByZXNoYXBlIGNvbmRpdGlvbi1yZWxhdGVkIExpa2VydCBjb2x1bW5zCmNvbmRpdGlvbl9kYXRhIDwtIGRhdGEgJT4lIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfLipfbGVzc29uIikpCgojIExvbmcgZm9ybWF0IHdpdGggcGhhc2UgYW5kIGNvbmRpdGlvbgpsb25nX2xlc3Nvbl9kYXRhIDwtIGNvbmRpdGlvbl9kYXRhICU+JQogIG11dGF0ZShpZCA9IHJvd19udW1iZXIoKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC1pZCwKICAgIG5hbWVzX3RvID0gYygicGhhc2UiLCAibGVzc29uIiksCiAgICBuYW1lc19wYXR0ZXJuID0gImxpa2VydF8ocHJlfG1pZHxwb3N0KV9sZXNzb24oXFxkKykiLAogICAgdmFsdWVzX3RvID0gInNjb3JlIgogICkgJT4lCiAgbXV0YXRlKAogICAgcGhhc2UgPSBmYWN0b3IocGhhc2UsIGxldmVscyA9IGMoInByZSIsICJtaWQiLCAicG9zdCIpKSwKICAgIGNvbmRpdGlvbiA9IHBhc3RlMCgiTGVzc29uICIsIGxlc3NvbikKICApCgojIENhbGN1bGF0ZSBkaWZmZXJlbmNlczogbWlkLXByZSwgcG9zdC1wcmUsIGFuZCBwb3N0LW1pZApwaXZvdGVkIDwtIGxvbmdfbGVzc29uX2RhdGEgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHBoYXNlLCB2YWx1ZXNfZnJvbSA9IHNjb3JlKSAlPiUKICBtdXRhdGUoCiAgICBkaWZmX21pZCA9IG1pZCAtIHByZSwKICAgIGRpZmZfcG9zdCA9IHBvc3QgLSBwcmUsCiAgICBkaWZmX21pZF9wb3N0ID0gcG9zdCAtIG1pZAogICkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IGMoZGlmZl9taWQsIGRpZmZfcG9zdCwgZGlmZl9taWRfcG9zdCksCiAgICBuYW1lc190byA9ICJwaGFzZSIsCiAgICB2YWx1ZXNfdG8gPSAiZGlmZl9mcm9tX3ByZSIKICApICU+JQogIG11dGF0ZSgKICAgIHBoYXNlID0gcmVjb2RlKHBoYXNlLAogICAgICAgICAgICAgICAgICAgZGlmZl9taWQgPSAibWlkLXByZSIsCiAgICAgICAgICAgICAgICAgICBkaWZmX3Bvc3QgPSAicG9zdC1wcmUiLAogICAgICAgICAgICAgICAgICAgZGlmZl9taWRfcG9zdCA9ICJwb3N0LW1pZCIpLAogICAgcGhhc2UgPSBmYWN0b3IocGhhc2UsIGxldmVscyA9IGMoIm1pZC1wcmUiLCAicG9zdC1wcmUiLCAicG9zdC1taWQiKSkKICApCgojIENhbGN1bGF0ZSBtZWFucyBmb3IgbGFiZWxzL3BvaW50cwptZWFucyA8LSBwaXZvdGVkICU+JQogIGdyb3VwX2J5KGNvbmRpdGlvbiwgcGhhc2UpICU+JQogIHN1bW1hcmlzZShtZWFuX3ZhbCA9IG1lYW4oZGlmZl9mcm9tX3ByZSwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikKCiMgUGxvdCBhbGwgY29uZGl0aW9ucyBzaWRlIGJ5IHNpZGUsIHBoYXNlIGFzIGZpbGwgZG9kZ2UsIHdpdGggbWVhbiBwb2ludHMKZ2dwbG90KHBpdm90ZWQsIGFlcyh4ID0gY29uZGl0aW9uLCB5ID0gZGlmZl9mcm9tX3ByZSwgZmlsbCA9IHBoYXNlKSkgKwogIGdlb21fYm94cGxvdChwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwgYWxwaGEgPSAwLjUsIG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGdlb21faml0dGVyKGFlcyhjb2xvciA9IHBoYXNlKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXJkb2RnZShqaXR0ZXIud2lkdGggPSAwLjIsIGRvZGdlLndpZHRoID0gMC44KSwgYWxwaGEgPSAwLjcsIHNpemUgPSAyKSArCiAgZ2VvbV9wb2ludChkYXRhID0gbWVhbnMsIGFlcyh4ID0gY29uZGl0aW9uLCB5ID0gbWVhbl92YWwsIGdyb3VwID0gcGhhc2UpLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMsIHNoYXBlID0gMTgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTUsIDE1KSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEaWZmZXJlbmNlcyBiZXR3ZWVuIFBoYXNlcyBwZXIgTGVzc29uIiwKICAgIHggPSAiTGVzc29uIiwKICAgIHkgPSAiU2NvcmUgRGlmZmVyZW5jZSIsCiAgICBmaWxsID0gIlBoYXNlIENvbXBhcmlzb24iLAogICAgY29sb3IgPSAiUGhhc2UgQ29tcGFyaXNvbiIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImdyYXkiKQoKYGBgCgojIyBDZXJ0YWludHkgRGVsdGFzIHBlciBMZXNzb24gLSBBTk9WQQoKYGBge3J9CmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgRXh0cmFjdCBhbmQgcmVzaGFwZSBvbmx5IGxlc3Nvbi1yZWxhdGVkIExpa2VydCBjb2x1bW5zCmxlc3Nvbl9kYXRhIDwtIGRhdGEgJT4lIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfLipfbGVzc29uIikpCgojIExvbmcgZm9ybWF0IHdpdGggcGhhc2UgYW5kIGxlc3Nvbgpsb25nX2xlc3Nvbl9kYXRhIDwtIGxlc3Nvbl9kYXRhICU+JQogIG11dGF0ZShpZCA9IHJvd19udW1iZXIoKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC1pZCwKICAgIG5hbWVzX3RvID0gYygicGhhc2UiLCAibGVzc29uIiksCiAgICBuYW1lc19wYXR0ZXJuID0gImxpa2VydF8ocHJlfG1pZHxwb3N0KV9sZXNzb24oXFxkKykiLAogICAgdmFsdWVzX3RvID0gInNjb3JlIgogICkgJT4lCiAgbXV0YXRlKAogICAgcGhhc2UgPSBmYWN0b3IocGhhc2UsIGxldmVscyA9IGMoInByZSIsICJtaWQiLCAicG9zdCIpKSwKICAgIGxlc3NvbiA9IHBhc3RlMCgiTGVzc29uICIsIGxlc3NvbikKICApCgojIENhbGN1bGF0ZSBkaWZmZXJlbmNlcyBmcm9tIHByZSBwZXIgaW5kaXZpZHVhbCBhbmQgbGVzc29uCmRlbHRhX2RhdGEgPC0gbG9uZ19sZXNzb25fZGF0YSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcGhhc2UsIHZhbHVlc19mcm9tID0gc2NvcmUpICU+JQogIG11dGF0ZSgKICAgIGRpZmZfbWlkID0gbWlkIC0gcHJlLAogICAgZGlmZl9wb3N0ID0gcG9zdCAtIHByZQogICkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IGMoZGlmZl9taWQsIGRpZmZfcG9zdCksCiAgICBuYW1lc190byA9ICJwaGFzZSIsCiAgICB2YWx1ZXNfdG8gPSAiZGlmZl9mcm9tX3ByZSIKICApICU+JQogIG11dGF0ZSgKICAgIHBoYXNlID0gcmVjb2RlKHBoYXNlLCBkaWZmX21pZCA9ICJtaWQiLCBkaWZmX3Bvc3QgPSAicG9zdCIpLAogICAgcGhhc2UgPSBmYWN0b3IocGhhc2UsIGxldmVscyA9IGMoIm1pZCIsICJwb3N0IikpCiAgKQoKIyBQZXJmb3JtIFNoYXBpcm8tV2lsayB0ZXN0IGJ5IGxlc3NvbiBhbmQgcGhhc2UKbm9ybWFsaXR5X3Rlc3RzIDwtIGRlbHRhX2RhdGEgJT4lCiAgZ3JvdXBfYnkobGVzc29uLCBwaGFzZSkgJT4lCiAgc3VtbWFyaXNlKAogICAgcF92YWx1ZSA9IHNoYXBpcm8udGVzdChkaWZmX2Zyb21fcHJlKSRwLnZhbHVlLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkKCgpwcmludCgiU2hhcGlyby1XaWxrIE5vcm1hbGl0eSBUZXN0IChwIDwgMC4wNSA9IG5vdCBub3JtYWwpOiIpCnByaW50KG5vcm1hbGl0eV90ZXN0cykKCmBgYAoKIyMgQ2VydGFpbnR5IGZvciBhbGwgTGVzc29ucyBhbmQgY29uZGl0aW9ucwoKYGBge3J9CgpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc3RyaW5ncikKCmxlc3Nvbl9kYXRhIDwtIGRhdGEgJT4lIAogIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfLipfbGVzc29uIikpICU+JQogIG11dGF0ZShpZCA9IHJvd19udW1iZXIoKSkgICMgQWRkIHRoaXMgbGluZQoKbG9uZ19sZXNzb25fZGF0YSA8LSBsZXNzb25fZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLWlkLCAgIyBFeGNsdWRlICdpZCcgZnJvbSBwaXZvdGluZwogICAgbmFtZXNfdG8gPSBjKCJwaGFzZSIsICJsZXNzb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAibGlrZXJ0XyhwcmV8bWlkfHBvc3QpX2xlc3NvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwaGFzZSA9IGZhY3RvcihwaGFzZSwgbGV2ZWxzID0gYygicHJlIiwgIm1pZCIsICJwb3N0IikpLAogICAgbGVzc29uID0gcGFzdGUwKCJMZXNzb24gIiwgbGVzc29uKQogICkKCiMgU3BsaXQgJ2NvbmRpdGlvbl9vcmRlcicgaW50byBzZXBhcmF0ZSByb3dzCmNvbmRpdGlvbl9vcmRlcl9sb25nIDwtIGRhdGEgJT4lCiAgbXV0YXRlKGlkID0gcm93X251bWJlcigpKSAlPiUKICBzZXBhcmF0ZShjb25kaXRpb25fb3JkZXIsIGludG8gPSBwYXN0ZTAoImxlc3Nvbl8iLCAxOjQpLCBzZXAgPSAiLCIsIGNvbnZlcnQgPSBUUlVFKSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gc3RhcnRzX3dpdGgoImxlc3Nvbl8iKSwKICAgIG5hbWVzX3RvID0gImxlc3NvbiIsCiAgICBuYW1lc19wYXR0ZXJuID0gImxlc3Nvbl8oXFxkKykiLAogICAgdmFsdWVzX3RvID0gImNvbmRpdGlvbl9pbmRleCIKICApICU+JQogIG11dGF0ZSgKICAgIGxlc3NvbiA9IHBhc3RlMCgiTGVzc29uICIsIGFzLmludGVnZXIobGVzc29uKSksCiAgICBjb25kaXRpb24gPSBwYXN0ZTAoImNvbmRpdGlvbiAiLCBjb25kaXRpb25faW5kZXggKyAxKQogICkgJT4lCiAgc2VsZWN0KGlkLCBsZXNzb24sIGNvbmRpdGlvbikKCiMg4pyFIEpPSU4gdG8gZ2V0IGZ1bGwgY29tYmluZWQgZGF0YQpjb21iaW5lZCA8LSBsb25nX2xlc3Nvbl9kYXRhICU+JQogIGxlZnRfam9pbihjb25kaXRpb25fb3JkZXJfbG9uZywgYnkgPSBjKCJpZCIsICJsZXNzb24iKSkgJT4lCiAgbXV0YXRlKGNvbmRpdGlvbl9sZXNzb24gPSBwYXN0ZShjb25kaXRpb24sIGxlc3Nvbiwgc2VwID0gIiAtICIpKQoKIyBKb2luIGxlc3NvbiBzY29yZXMgd2l0aCB0aGVpciBjb3JyZXNwb25kaW5nIGNvbmRpdGlvbiAodmlhIGNvbmRpdGlvbl9vcmRlcikKY29tYmluZWQgPC0gY29tYmluZWQgJT4lCiAgbXV0YXRlKGNvbmRpdGlvbl9sZXNzb24gPSBwYXN0ZShjb25kaXRpb24sIGxlc3Nvbiwgc2VwID0gIiAtICIpKQoKCiMgU3RlcCA0OiBHZXQgbWVhbnMgZm9yIGxhYmVsCm1lYW5zIDwtIGNvbWJpbmVkICU+JQogIGdyb3VwX2J5KGNvbmRpdGlvbl9sZXNzb24sIHBoYXNlKSAlPiUKICBzdW1tYXJpc2UobWVhbl9zY29yZSA9IG1lYW4oc2NvcmUsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpCgojIFN0ZXAgNTogUGxvdAojIERlZmluZSBjb2xvciBzY2FsZXMKZmlsbF9jb2xvcnMgPC0gYygicHJlIiA9ICIjYTZjZWUzIiwgIm1pZCIgPSAiIzFmNzhiNCIsICJwb3N0IiA9ICIjYjJkZjhhIikKdGV4dF9jb2xvciA8LSAiYmxhY2siCgojIEZ1bmN0aW9uIHRvIGdlbmVyYXRlIGEgcGxvdCBmb3IgYSBzcGVjaWZpYyBwaGFzZQpwbG90X2J5X3BoYXNlIDwtIGZ1bmN0aW9uKHBoYXNlX2lucHV0KSB7CiAgIyBGaWx0ZXIgY29tYmluZWQgZGF0YSBhbmQgbWVhbnMgZm9yIHRoZSBnaXZlbiBwaGFzZQogIHBsb3RfZGF0YSA8LSBjb21iaW5lZCAlPiUgZmlsdGVyKHBoYXNlID09IHBoYXNlX2lucHV0KQogIHBoYXNlX21lYW5zIDwtIG1lYW5zICU+JSBmaWx0ZXIocGhhc2UgPT0gcGhhc2VfaW5wdXQpCiAgCiAgZ2dwbG90KHBsb3RfZGF0YSwgYWVzKHggPSBwaGFzZSwgeSA9IHNjb3JlLCBmaWxsID0gcGhhc2UpKSArCiAgICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjUsIG91dGxpZXIuc2hhcGUgPSBOQSkgKwogICAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gcGhhc2UpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMTUpLAogICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwgYWxwaGEgPSAwLjcpICsKICAgIGdlb21fdGV4dChkYXRhID0gcGhhc2VfbWVhbnMsIGFlcyh4ID0gcGhhc2UsIHkgPSBtZWFuX3Njb3JlICsgMC4xNSwgbGFiZWwgPSByb3VuZChtZWFuX3Njb3JlLCAyKSksCiAgICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSwKICAgICAgICAgICAgICBzaXplID0gMi41LCBmb250ZmFjZSA9ICJib2xkIiwgY29sb3IgPSB0ZXh0X2NvbG9yKSArCiAgICBmYWNldF93cmFwKH4gY29uZGl0aW9uX2xlc3NvbiwgbmNvbCA9IDQpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGZpbGxfY29sb3JzKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gZmlsbF9jb2xvcnMpICsKICAgIGxhYnMoCiAgICAgIHRpdGxlID0gcGFzdGUoIkxpa2VydCBTY29yZXMgZm9yIiwgdG9vbHM6OnRvVGl0bGVDYXNlKHBoYXNlX2lucHV0KSwgIlBoYXNlIiksCiAgICAgIHggPSBOVUxMLAogICAgICB5ID0gIkxpa2VydCBTY29yZSIsCiAgICAgIGZpbGwgPSAiUGhhc2UiLAogICAgICBjb2xvciA9ICJQaGFzZSIKICAgICkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKAogICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFjZSA9ICJib2xkIiksCiAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIgogICAgKQp9CgojIE5vdyBnZW5lcmF0ZSBwbG90cwpwbG90X3ByZSA8LSBwbG90X2J5X3BoYXNlKCJwcmUiKQpwbG90X21pZCA8LSBwbG90X2J5X3BoYXNlKCJtaWQiKQpwbG90X3Bvc3QgPC0gcGxvdF9ieV9waGFzZSgicG9zdCIpCgojIFByaW50IHRoZW0gb25lIGFmdGVyIGFub3RoZXIgKGluIGFuIFIgc2NyaXB0IG9yIG5vdGVib29rKQpwcmludChwbG90X3ByZSkKcHJpbnQocGxvdF9taWQpCnByaW50KHBsb3RfcG9zdCkKCgpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocGF0Y2h3b3JrKQoKbWVhbnNfaGVhdG1hcCA8LSBtZWFucyAlPiUKICBzZXBhcmF0ZShjb25kaXRpb25fbGVzc29uLCBpbnRvID0gYygiY29uZGl0aW9uIiwgImxlc3NvbiIpLCBzZXAgPSAiIC0gIikgJT4lCiAgbXV0YXRlKAogICAgY29uZGl0aW9uID0gZmFjdG9yKHN0cl9yZW1vdmUoY29uZGl0aW9uLCAiY29uZGl0aW9uICIpLCBsZXZlbHMgPSBjKCIxIiwgIjIiLCAiMyIsICI0IikpLAogICAgbGVzc29uID0gZmFjdG9yKHN0cl9yZW1vdmUobGVzc29uLCAiTGVzc29uICIpLCBsZXZlbHMgPSBjKCIxIiwgIjIiLCAiMyIsICI0IikpLAogICAgcGhhc2UgPSBmYWN0b3IocGhhc2UsIGxldmVscyA9IGMoInByZSIsICJtaWQiLCAicG9zdCIpKQogICkgJT4lCiAgY29tcGxldGUocGhhc2UsIGNvbmRpdGlvbiwgbGVzc29uKQoKbWluX3Njb3JlIDwtIGZsb29yKG1pbihtZWFuc19oZWF0bWFwJG1lYW5fc2NvcmUsIG5hLnJtID0gVFJVRSkpCm1heF9zY29yZSA8LSBjZWlsaW5nKG1heChtZWFuc19oZWF0bWFwJG1lYW5fc2NvcmUsIG5hLnJtID0gVFJVRSkpCgpwbG90X2hlYXRtYXAgPC0gZnVuY3Rpb24ocGhhc2VfbmFtZSwgc2hvd194ID0gVFJVRSwgc2hvd195ID0gVFJVRSkgewogIGdncGxvdChtZWFuc19oZWF0bWFwICU+JSBmaWx0ZXIocGhhc2UgPT0gcGhhc2VfbmFtZSksIGFlcyh4ID0gbGVzc29uLCB5ID0gY29uZGl0aW9uLCBmaWxsID0gbWVhbl9zY29yZSkpICsKICAgIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIpICsKICAgIGdlb21fbGFiZWwoYWVzKGxhYmVsID0gcm91bmQobWVhbl9zY29yZSwgMikpLCAKICAgICAgICAgICAgICAgZmlsbCA9IGFscGhhKCJ3aGl0ZSIsIDAuNSksICAgIyBmYWludCB3aGl0ZSBiYWNrZ3JvdW5kCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgCiAgICAgICAgICAgICAgIHNpemUgPSAyLCAgICAgICAgICAgICAgICAgICAgIyBzbWFsbGVyIHRleHQgc2l6ZQogICAgICAgICAgICAgICBsYWJlbC5zaXplID0gMCkgKyAgICAgICAgICAgICMgcmVtb3ZlIGxhYmVsIGJvcmRlcgogICAgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uID0gIkMiLCBkaXJlY3Rpb24gPSAtMSwgbGltaXRzID0gYyhtaW5fc2NvcmUsIG1heF9zY29yZSksIG5hLnZhbHVlID0gImdyZXk5MCIpICsKICAgIGxhYnModGl0bGUgPSBwYXN0ZSh0b3VwcGVyKHBoYXNlX25hbWUpLCAiUGhhc2UiKSwKICAgICAgICAgeCA9IGlmZWxzZShzaG93X3gsICJMZXNzb24iLCAiIiksCiAgICAgICAgIHkgPSBpZmVsc2Uoc2hvd195LCAiY29uZGl0aW9uIiwgIiIpLAogICAgICAgICBmaWxsID0gIk1lYW4gU2NvcmUiKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUoCiAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDEyKSwKICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMywgZmFjZSA9ICJib2xkIiksCiAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMsIGZhY2UgPSAiYm9sZCIpCiAgICApCn0KCiMgU2hvdyB5LWF4aXMgbGFiZWxzIG9ubHkgb24gbGVmdG1vc3QgcGxvdCwgeC1heGlzIG9ubHkgb24gYm90dG9tIHBsb3RzCmhlYXRtYXBfcHJlIDwtIHBsb3RfaGVhdG1hcCgicHJlIiwgc2hvd194ID0gRkFMU0UsIHNob3dfeSA9IFRSVUUpCmhlYXRtYXBfbWlkIDwtIHBsb3RfaGVhdG1hcCgibWlkIiwgc2hvd194ID0gRkFMU0UsIHNob3dfeSA9IEZBTFNFKQpoZWF0bWFwX3Bvc3QgPC0gcGxvdF9oZWF0bWFwKCJwb3N0Iiwgc2hvd194ID0gVFJVRSwgc2hvd195ID0gRkFMU0UpCgpjb21iaW5lZF9oZWF0bWFwcyA8LSBoZWF0bWFwX3ByZSArIGhlYXRtYXBfbWlkICsgaGVhdG1hcF9wb3N0ICsgCiAgcGxvdF9sYXlvdXQobmNvbCA9IDMsIGd1aWRlcyA9ICJjb2xsZWN0IikgJiAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKcHJpbnQoY29tYmluZWRfaGVhdG1hcHMpCgpgYGAKCiMjIENlcnRhaW50eSBkZWx0YXMgZm9yIGFsbCBMZXNzb25zIGFuZCBjb25kaXRpb25zCgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBhdGNod29yaykKCiMgU3ByZWFkIHBoYXNlcyB3aWRlCm1lYW5zX3dpZGUgPC0gbWVhbnNfaGVhdG1hcCAlPiUKICBzZWxlY3QoY29uZGl0aW9uLCBsZXNzb24sIHBoYXNlLCBtZWFuX3Njb3JlKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcGhhc2UsIHZhbHVlc19mcm9tID0gbWVhbl9zY29yZSkKCiMgQ2FsY3VsYXRlIGRlbHRhcyBhcyBsYXRlciBwaGFzZSBtaW51cyBlYXJsaWVyIHBoYXNlCmRlbHRhcyA8LSBtZWFuc193aWRlICU+JQogIG11dGF0ZSgKICAgIG1pZF9wcmUgPSBtaWQgLSBwcmUsICAgICAgICAjIENoYW5nZSBhZnRlciBJbm9jdWxhdGlvbgogICAgcG9zdF9wcmUgPSBwb3N0IC0gcHJlLCAgICAgICMgQ2hhbmdlIGFmdGVyIElub2N1bGF0aW9uIGFuZCBTdHJvbmcgYXR0YWNrCiAgICBwb3N0X21pZCA9IHBvc3QgLSBtaWQgICAgICAgIyBDaGFuZ2UgYWZ0ZXIgU3Ryb25nIGF0dGFjawogICkgJT4lCiAgc2VsZWN0KGNvbmRpdGlvbiwgbGVzc29uLCBtaWRfcHJlLCBwb3N0X3ByZSwgcG9zdF9taWQpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhtaWRfcHJlLCBwb3N0X3ByZSwgcG9zdF9taWQpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJjb21wYXJpc29uIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImRlbHRhIikKCiMgTmFtZWQgdGl0bGVzIGZvciB0aGUgcGxvdHMKY29tcGFyaXNvbl90aXRsZXMgPC0gYygKICBtaWRfcHJlID0gIkNoYW5nZSBhZnRlclxuSW5vY3VsYXRpb24iLAogIHBvc3RfcHJlID0gIkNoYW5nZSBhZnRlclxuSW5vY3VsYXRpb24gYW5kXG5TdHJvbmcgYXR0YWNrIiwKICBwb3N0X21pZCA9ICJDaGFuZ2UgYWZ0ZXJcblN0cm9uZyBhdHRhY2siCikKCnBsb3RfZGVsdGFfaGVhdG1hcCA8LSBmdW5jdGlvbihjb21wX25hbWUpIHsKICBnZ3Bsb3QoZGVsdGFzICU+JSBmaWx0ZXIoY29tcGFyaXNvbiA9PSBjb21wX25hbWUpLCBhZXMoeCA9IGxlc3NvbiwgeSA9IGNvbmRpdGlvbiwgZmlsbCA9IGRlbHRhKSkgKwogICAgZ2VvbV90aWxlKGNvbG9yID0gIndoaXRlIikgKwogICAgZ2VvbV9sYWJlbChhZXMobGFiZWwgPSByb3VuZChkZWx0YSwgMikpLCAKICAgICAgICAgICAgICAgZmlsbCA9IGFscGhhKCJ3aGl0ZSIsIDAuNSksIAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIsIAogICAgICAgICAgICAgICBzaXplID0gMiwgCiAgICAgICAgICAgICAgIGxhYmVsLnNpemUgPSAwKSArCiAgICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAiYmx1ZSIsIG1pZCA9ICJ3aGl0ZSIsIGhpZ2ggPSAicmVkIiwgbWlkcG9pbnQgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYyhtaW4oZGVsdGFzJGRlbHRhLCBuYS5ybSA9IFRSVUUpLCBtYXgoZGVsdGFzJGRlbHRhLCBuYS5ybSA9IFRSVUUpKSwKICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gImdyZXk5MCIpICsKICAgIGxhYnMoCiAgICAgIHRpdGxlID0gY29tcGFyaXNvbl90aXRsZXNbY29tcF9uYW1lXSwKICAgICAgeCA9IGlmZWxzZShjb21wX25hbWUgPT0gIm1pZF9wcmUiLCAiTGVzc29uIiwgIiIpLAogICAgICB5ID0gaWZlbHNlKGNvbXBfbmFtZSA9PSAibWlkX3ByZSIsICJjb25kaXRpb24iLCAiIiksCiAgICAgIGZpbGwgPSAiRGVsdGEiCiAgICApICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZSgKICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gMTIpLAogICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUpLAogICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzLCBmYWNlID0gImJvbGQiKSwKICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMywgZmFjZSA9ICJib2xkIikKICAgICkKfQoKaGVhdG1hcF9taWRfcHJlIDwtIHBsb3RfZGVsdGFfaGVhdG1hcCgibWlkX3ByZSIpCmhlYXRtYXBfcG9zdF9wcmUgPC0gcGxvdF9kZWx0YV9oZWF0bWFwKCJwb3N0X3ByZSIpCmhlYXRtYXBfcG9zdF9taWQgPC0gcGxvdF9kZWx0YV9oZWF0bWFwKCJwb3N0X21pZCIpCgpjb21iaW5lZF9kZWx0YXMgPC0gaGVhdG1hcF9taWRfcHJlICsgIGhlYXRtYXBfcG9zdF9taWQgKyBoZWF0bWFwX3Bvc3RfcHJlICsKICBwbG90X2xheW91dChuY29sID0gMywgZ3VpZGVzID0gImNvbGxlY3QiKSAmIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpwcmludChjb21iaW5lZF9kZWx0YXMpCgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHN0cmluZ3IpCgojIEFzc3VtaW5nIHlvdSBoYXZlICdjb21iaW5lZCcgZGF0YWZyYW1lIHdpdGggcGFydGljaXBhbnRfaWQsIGNvbmRpdGlvbiwgbGVzc29uLCBwaGFzZSwgc2NvcmUKCiMgUGl2b3Qgd2lkZXIgdG8gZ2V0IHByZSwgbWlkLCBwb3N0IHNjb3JlcyBwZXIgcGFydGljaXBhbnQtY29uZGl0aW9uLWxlc3NvbgpwYXJ0aWNpcGFudF93aWRlIDwtIGNvbWJpbmVkICU+JQogIHNlbGVjdChpZCwgY29uZGl0aW9uLCBsZXNzb24sIHBoYXNlLCBzY29yZSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHBoYXNlLCB2YWx1ZXNfZnJvbSA9IHNjb3JlKQoKIyBDYWxjdWxhdGUgcGFydGljaXBhbnQtbGV2ZWwgZGVsdGFzIChsYXRlciAtIGVhcmxpZXIpCnBhcnRpY2lwYW50X2RlbHRhcyA8LSBwYXJ0aWNpcGFudF93aWRlICU+JQogIG11dGF0ZSgKICAgIG1pZF9wcmUgPSBtaWQgLSBwcmUsCiAgICBwb3N0X3ByZSA9IHBvc3QgLSBwcmUsCiAgICBwb3N0X21pZCA9IHBvc3QgLSBtaWQKICApICU+JQogIHNlbGVjdChpZCwgY29uZGl0aW9uLCBsZXNzb24sIG1pZF9wcmUsIHBvc3RfcHJlLCBwb3N0X21pZCkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKG1pZF9wcmUsIHBvc3RfcHJlLCBwb3N0X21pZCksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gImNvbXBhcmlzb24iLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiZGVsdGEiKQoKIyBGaXggZmFjdG9ycyBmb3IgcGxvdHRpbmcKcGFydGljaXBhbnRfZGVsdGFzIDwtIHBhcnRpY2lwYW50X2RlbHRhcyAlPiUKICBtdXRhdGUoCiAgICBjb25kaXRpb24gPSBmYWN0b3Ioc3RyX3JlbW92ZShjb25kaXRpb24sICJjb25kaXRpb24gIiksIGxldmVscyA9IGMoIjEiLCAiMiIsICIzIiwgIjQiKSksCiAgICBsZXNzb24gPSBmYWN0b3Ioc3RyX3JlbW92ZShsZXNzb24sICJMZXNzb24gIiksIGxldmVscyA9IGMoIjEiLCAiMiIsICIzIiwgIjQiKSksCiAgICBjb21wYXJpc29uID0gZmFjdG9yKGNvbXBhcmlzb24sIGxldmVscyA9IGMoIm1pZF9wcmUiLCAicG9zdF9wcmUiLCAicG9zdF9taWQiKSkKICApCgojIE5hbWVkIHRpdGxlcyBmb3IgdGhlIHBsb3RzCmNvbXBhcmlzb25fdGl0bGVzIDwtIGMoCiAgbWlkX3ByZSA9ICJDaGFuZ2UgYWZ0ZXJcbklub2N1bGF0aW9uIiwKICBwb3N0X3ByZSA9ICJDaGFuZ2UgYWZ0ZXJcbklub2N1bGF0aW9uIGFuZFxuU3Ryb25nIGF0dGFjayIsCiAgcG9zdF9taWQgPSAiQ2hhbmdlIGFmdGVyXG5TdHJvbmcgYXR0YWNrIgopCgojIFBsb3R0aW5nIGZ1bmN0aW9uIGZvciBib3hwbG90cyArIHNjYXR0ZXIKcGxvdF9kZWx0YV9ib3hwbG90cyA8LSBmdW5jdGlvbihjb21wX25hbWUpIHsKICBkZiA8LSBwYXJ0aWNpcGFudF9kZWx0YXMgJT4lIGZpbHRlcihjb21wYXJpc29uID09IGNvbXBfbmFtZSkKICAKICBnZ3Bsb3QoZGYsIGFlcyh4ID0gbGVzc29uLCB5ID0gZGVsdGEpKSArCiAgICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BLCBmaWxsID0gIiNhNmNlZTMiLCBhbHBoYSA9IDAuNSkgKwogICAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIsIGFscGhhID0gMC43LCBzaXplID0gMS41LCBjb2xvciA9ICIjMWY3OGI0IikgKwogICAgZmFjZXRfd3JhcCh+Y29uZGl0aW9uLCBucm93ID0gNCwgbmNvbCA9IDEsIHN0cmlwLnBvc2l0aW9uID0gInJpZ2h0IikgKwogICAgeWxpbSgtMTUsIDE1KSArICAgICMgRml4ZWQgeS1heGlzIHNjYWxlIGhlcmUKICAgIGxhYnMoCiAgICAgIHRpdGxlID0gY29tcGFyaXNvbl90aXRsZXNbY29tcF9uYW1lXSwKICAgICAgeCA9ICJMZXNzb24iLAogICAgICB5ID0gIkRlbHRhIFNjb3JlIgogICAgKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUoCiAgICAgIHN0cmlwLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiksCiAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiLCBoanVzdCA9IDAuNSksCiAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkKICAgICkKfQoKCiMgR2VuZXJhdGUgcGxvdHMKcGxvdF9taWRfcHJlIDwtIHBsb3RfZGVsdGFfYm94cGxvdHMoIm1pZF9wcmUiKQpwbG90X3Bvc3RfcHJlIDwtIHBsb3RfZGVsdGFfYm94cGxvdHMoInBvc3RfcHJlIikKcGxvdF9wb3N0X21pZCA8LSBwbG90X2RlbHRhX2JveHBsb3RzKCJwb3N0X21pZCIpCgojIENvbWJpbmUgcGxvdHMgc2lkZSBieSBzaWRlIHdpdGggc2hhcmVkIGxlZ2VuZCBhcmVhIChubyBsZWdlbmQgaGVyZSBhY3R1YWxseSkKY29tYmluZWRfYm94cGxvdHMgPC0gcGxvdF9taWRfcHJlICsgcGxvdF9wb3N0X3ByZSArIHBsb3RfcG9zdF9taWQgKyAKICBwbG90X2xheW91dChuY29sID0gMywgZ3VpZGVzID0gImNvbGxlY3QiKSAmIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQoKIyBTaG93IGNvbWJpbmVkIHBsb3QKcHJpbnQoY29tYmluZWRfYm94cGxvdHMpCgoKCmBgYAoKIyBSZXNpc3RhbmNlIHRvIFBlcnN1YXNpb24gKENlcnRhaW50eSBtaWQtcG9zdCkKCiMjICEgQWxsIGNlcnRhaW50eSBkZWx0YXMKCmBgYHtyfQojIFN0ZXAgMTogUmVzaGFwZSBhbmQgY29tcHV0ZSBkaWZmZXJlbmNlcwphbGxfY2VydGFpbnR5X2RlbHRhcyA8LSBkYXRhICU+JQogIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfKG1pZHxwb3N0KV9jb25kaXRpb25cXGQrIikpICU+JQogIG11dGF0ZShwYXJ0aWNpcGFudF9pZCA9IHJvd19udW1iZXIoKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC1wYXJ0aWNpcGFudF9pZCwKICAgIG5hbWVzX3RvID0gYygicGhhc2UiLCAiY29uZGl0aW9uIiksCiAgICBuYW1lc19wYXR0ZXJuID0gImxpa2VydF8obWlkfHBvc3QpX2NvbmRpdGlvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcGhhc2UsIHZhbHVlc19mcm9tID0gc2NvcmUpICU+JQogIG11dGF0ZSgKICAgIGRpZmYgPSBwb3N0IC0gbWlkLAogICAgY29uZGl0aW9uID0gY2FzZV93aGVuKAogICAgICBjb25kaXRpb24gPT0gIjEiIH4gIkNvbnRyb2wiLAogICAgICBjb25kaXRpb24gPT0gIjIiIH4gIlJlYWRpbmciLAogICAgICBjb25kaXRpb24gPT0gIjMiIH4gIldyaXRpbmciLAogICAgICBjb25kaXRpb24gPT0gIjQiIH4gIkNoYXRib3QiLAogICAgICBUUlVFIH4gY29uZGl0aW9uCiAgICApCiAgKSAlPiUKICBzZWxlY3QocGFydGljaXBhbnRfaWQsIGNvbmRpdGlvbiwgZGlmZikgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGNvbmRpdGlvbiwgdmFsdWVzX2Zyb20gPSBkaWZmKQoKIyBTdGVwIDI6IFZpZXcgdGhlIHJlc3VsdApwcmludChhbGxfY2VydGFpbnR5X2RlbHRhcykKCiMgT3B0aW9uYWw6IFNhdmUgdG8gQ1NWCndyaXRlLmNzdihhbGxfY2VydGFpbnR5X2RlbHRhcywgInBhcnRpY2lwYW50X2RpZmZlcmVuY2VzX2J5X2NvbmRpdGlvbi5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCmBgYAoKIyMgISEgUmVzaXN0YW5jZSB0byBQZXJzdWFzaW9uIHBlciBDb25kaXRpb24KCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGdncHVicikKCnBsb3RfZGF0YSA8LSBkYXRhICU+JQogIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfKG1pZHxwb3N0KV9jb25kaXRpb25cXGQrIikpICU+JQogIG11dGF0ZShpZCA9IHJvd19udW1iZXIoKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC1pZCwKICAgIG5hbWVzX3RvID0gYygicGhhc2UiLCAiY29uZGl0aW9uIiksCiAgICBuYW1lc19wYXR0ZXJuID0gImxpa2VydF8obWlkfHBvc3QpX2NvbmRpdGlvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcGhhc2UsIHZhbHVlc19mcm9tID0gc2NvcmUpICU+JQogIG11dGF0ZSgKICAgIGRpZmZfdmFsdWUgPSBwb3N0IC0gbWlkLAogICAgY29uZGl0aW9uID0gY2FzZV93aGVuKAogICAgICBjb25kaXRpb24gPT0gIjEiIH4gIkNvbnRyb2wiLAogICAgICBjb25kaXRpb24gPT0gIjIiIH4gIlJlYWRpbmciLAogICAgICBjb25kaXRpb24gPT0gIjMiIH4gIldyaXRpbmciLAogICAgICBjb25kaXRpb24gPT0gIjQiIH4gIkNoYXRib3QiLAogICAgICBUUlVFIH4gY29uZGl0aW9uICAjIHNlcnZlcyBhcyBhIGZhaWxzYWZlCiAgICApLAogICAgIyBDb252ZXJ0IGNvbmRpdGlvbiB0byBhIGZhY3RvciB3aXRoIHNwZWNpZmllZCBsZXZlbHMKICAgIGNvbmRpdGlvbiA9IGZhY3Rvcihjb25kaXRpb24sIGxldmVscyA9IGMoIkNvbnRyb2wiLCAiUmVhZGluZyIsICJXcml0aW5nIiwgIkNoYXRib3QiKSkKICApCgojIFJlbW92ZSBvdXRsaWVycyAocGVyIGNvbmRpdGlvbiwgMS41IMOXIElRUiBydWxlKQpwbG90X2RhdGFfY2xlYW4gPC0gcGxvdF9kYXRhICU+JQogIGdyb3VwX2J5KGNvbmRpdGlvbikgJT4lCiAgbXV0YXRlKAogICAgUTEgPSBxdWFudGlsZShkaWZmX3ZhbHVlLCAwLjI1LCBuYS5ybSA9IFRSVUUpLAogICAgUTMgPSBxdWFudGlsZShkaWZmX3ZhbHVlLCAwLjc1LCBuYS5ybSA9IFRSVUUpLAogICAgSVFSID0gUTMgLSBRMSwKICAgIGxvd2VyX2JvdW5kID0gUTEgLSAxLjUgKiBJUVIsCiAgICB1cHBlcl9ib3VuZCA9IFEzICsgMS41ICogSVFSLAogICAgaXNfb3V0bGllciA9IGRpZmZfdmFsdWUgPCBsb3dlcl9ib3VuZCB8IGRpZmZfdmFsdWUgPiB1cHBlcl9ib3VuZAogICkgJT4lCiAgZmlsdGVyKCFpc19vdXRsaWVyKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgc2VsZWN0KC1RMSwgLVEzLCAtSVFSLCAtbG93ZXJfYm91bmQsIC11cHBlcl9ib3VuZCwgLWlzX291dGxpZXIpCgojIFN1bW1hcnkgc3RhdGlzdGljcyAodXNlIGNsZWFuZWQgZGF0YSkKc3VtbWFyeV9zdGF0c19jbGVhbiA8LSBwbG90X2RhdGFfY2xlYW4gJT4lCiAgZ3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBzdW1tYXJpc2UobWVhbl92YWwgPSBtZWFuKGRpZmZfdmFsdWUsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpCgpwdmFscyA8LSBkYXRhLmZyYW1lKAogIGdyb3VwMSA9IGMoIkNvbnRyb2wiLCAiUmVhZGluZyIsICJXcml0aW5nIiksCiAgZ3JvdXAyID0gYygiQ2hhdGJvdCIsICJDaGF0Ym90IiwgIkNoYXRib3QiKSwKICBwX3ZhbHVlID0gYygwLjAwMSwgMC4wMiwgMC4wMiksICAjIHJlcGxhY2Ugd2l0aCB5b3VyIGFjdHVhbCBwLXZhbHVlcwogIHhzdGFydCA9IGMoMSwgMiwgMyksICAgICAgICAgICAgIyBudW1lcmljIHggZm9yIGdyb3VwczsgYWRqdXN0IGlmIHlvdXIgZmFjdG9yIGxldmVscyBkaWZmZXIKICB4ZW5kID0gYyg0LCA0LCA0KSwgICAgICAgICAgICAgICMgIkNoYXRib3QiIGFzc3VtZWQgYXQgcG9zaXRpb24gNAogIHkgPSBjKDUsIDYuOCwgOC42KSAgICAgICAgICAgICAgICMgeSBwb3NpdGlvbnMgZm9yIGJyYWNrZXRzLCBhZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCikKCnB2YWxzIDwtIGRhdGEuZnJhbWUoCiAgZ3JvdXAxID0gYygiQ29udHJvbCIpLAogIGdyb3VwMiA9IGMoIkNoYXRib3QiKSwKICBwX3ZhbHVlID0gYygwLjAwMSksICAjIHJlcGxhY2Ugd2l0aCB5b3VyIGFjdHVhbCBwLXZhbHVlcwogIHhzdGFydCA9IGMoMSksICAgICAgICAgICAgIyBudW1lcmljIHggZm9yIGdyb3VwczsgYWRqdXN0IGlmIHlvdXIgZmFjdG9yIGxldmVscyBkaWZmZXIKICB4ZW5kID0gYyg0KSwgICAgICAgICAgICAgICMgIkNoYXRib3QiIGFzc3VtZWQgYXQgcG9zaXRpb24gNAogIHkgPSBjKDUpICAgICAgICAgICAgICAgIyB5IHBvc2l0aW9ucyBmb3IgYnJhY2tldHMsIGFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKKQoKCiMgUGxvdCB1c2luZyBjbGVhbmVkIGRhdGEKZ2dwbG90KHBsb3RfZGF0YV9jbGVhbiwgYWVzKHggPSBjb25kaXRpb24sIHkgPSBkaWZmX3ZhbHVlLCBmaWxsID0gY29uZGl0aW9uKSkgKwogIGdlb21fYm94cGxvdChhbHBoYSA9IDAuNSwgb3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9kb3RwbG90KGJpbmF4aXMgPSAieSIsIHN0YWNrZGlyID0gImNlbnRlciIsIGRvdHNpemUgPSAwLjUsIGFlcyhjb2xvciA9IGNvbmRpdGlvbikpICsKICBnZW9tX3BvaW50KGRhdGEgPSBzdW1tYXJ5X3N0YXRzX2NsZWFuLCBhZXMoeCA9IGNvbmRpdGlvbiwgeSA9IG1lYW5fdmFsKSwKICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMsIHNoYXBlID0gMTgpICsKICBnZW9tX3RleHQoZGF0YSA9IHN1bW1hcnlfc3RhdHNfY2xlYW4sIGFlcyh4ID0gY29uZGl0aW9uLCB5ID0gbWVhbl92YWwsIGxhYmVsID0gcm91bmQobWVhbl92YWwsIDIpKSwKICAgICAgICAgICAgdmp1c3QgPSAtMSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gNCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImdyYXkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHByZXR0eV9icmVha3MobiA9IDEwKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDaGFuZ2UgaW4gY2VydGFpbnR5IGFmdGVyIHN0cm9uZyBhdHRhY2siLAogICAgeCA9ICJDb25kaXRpb24iLAogICAgeSA9ICJDZXJ0YWludHkgc2NvcmUgY2hhbmdlIiwKICAgIGZpbGwgPSAiQ29uZGl0aW9uIiwKICAgIGNvbG9yID0gIkNvbmRpdGlvbiIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwoKICAjIEFkZCBicmFja2V0cyBhcyBsaW5lcwogIGdlb21fc2VnbWVudChkYXRhID0gcHZhbHMsIGFlcyh4ID0geHN0YXJ0LCB4ZW5kID0geGVuZCwgeSA9IHksIHllbmQgPSB5KSwKICAgICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSkgKwogIGdlb21fc2VnbWVudChkYXRhID0gcHZhbHMsIGFlcyh4ID0geHN0YXJ0LCB4ZW5kID0geHN0YXJ0LCB5ID0geSwgeWVuZCA9IHkgLSAwLjMpLAogICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFKSArCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBwdmFscywgYWVzKHggPSB4ZW5kLCB4ZW5kID0geGVuZCwgeSA9IHksIHllbmQgPSB5IC0gMC4zKSwKICAgICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSkgKwoKICAjIEFkZCBwLXZhbHVlIGxhYmVscywgc2hvdyAicCA8IDAuMDUiIGlmIGJlbG93IHRocmVzaG9sZCwgZWxzZSBibGFuawogIGdlb21fdGV4dCgKICBkYXRhID0gcHZhbHMsCiAgYWVzKHggPSAoeHN0YXJ0ICsgeGVuZCkgLyAyLCB5ID0geSArIDAuNSwKICAgICAgbGFiZWwgPSBjYXNlX3doZW4oCiAgICAgICAgcF92YWx1ZSA8IDAuMDAxIH4gIioqKioiLAogICAgICAgIHBfdmFsdWUgPCAwLjAwNSB+ICIqKioiLAogICAgICAgIHBfdmFsdWUgPCAwLjAxICB+ICIqKiIsCiAgICAgICAgcF92YWx1ZSA8IDAuMDUgIH4gIioiLAogICAgICAgIFRSVUUgfiAiIgogICAgICApKSwKICBpbmhlcml0LmFlcyA9IEZBTFNFLAogIHNpemUgPSAzCikKCmdncGxvdChwbG90X2RhdGFfY2xlYW4sIGFlcyh4ID0gY29uZGl0aW9uLCB5ID0gZGlmZl92YWx1ZSwgZmlsbCA9IGNvbmRpdGlvbikpICsKICBnZW9tX3Zpb2xpbih0cmltID0gRkFMU0UsIGFscGhhID0gMC42LCBjb2xvciA9IE5BLCBhZGp1c3QgPSAwLjYpICsgICMgVmlvbGluIG9ubHkKICBnZW9tX3BvaW50KAogICAgZGF0YSA9IHN1bW1hcnlfc3RhdHNfY2xlYW4sCiAgICBhZXMoeCA9IGNvbmRpdGlvbiwgeSA9IG1lYW5fdmFsKSwKICAgIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMsIHNoYXBlID0gMTgKICApICsKICBnZW9tX3RleHQoCiAgICBkYXRhID0gc3VtbWFyeV9zdGF0c19jbGVhbiwKICAgIGFlcyh4ID0gY29uZGl0aW9uLCB5ID0gbWVhbl92YWwsIGxhYmVsID0gcm91bmQobWVhbl92YWwsIDIpKSwKICAgIHZqdXN0ID0gLTEsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDQKICApICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5IikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MobiA9IDEwKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDaGFuZ2UgaW4gY2VydGFpbnR5IGFmdGVyIHN0cm9uZyBhdHRhY2siLAogICAgeCA9ICJDb25kaXRpb24iLAogICAgeSA9ICJDZXJ0YWludHkgc2NvcmUgY2hhbmdlIiwKICAgIGZpbGwgPSAiQ29uZGl0aW9uIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgZ2VvbV9zZWdtZW50KAogICAgZGF0YSA9IHB2YWxzLAogICAgYWVzKHggPSB4c3RhcnQsIHhlbmQgPSB4ZW5kLCB5ID0geSwgeWVuZCA9IHkpLAogICAgaW5oZXJpdC5hZXMgPSBGQUxTRQogICkgKwogIGdlb21fc2VnbWVudCgKICAgIGRhdGEgPSBwdmFscywKICAgIGFlcyh4ID0geHN0YXJ0LCB4ZW5kID0geHN0YXJ0LCB5ID0geSwgeWVuZCA9IHkgLSAwLjMpLAogICAgaW5oZXJpdC5hZXMgPSBGQUxTRQogICkgKwogIGdlb21fc2VnbWVudCgKICAgIGRhdGEgPSBwdmFscywKICAgIGFlcyh4ID0geGVuZCwgeGVuZCA9IHhlbmQsIHkgPSB5LCB5ZW5kID0geSAtIDAuMyksCiAgICBpbmhlcml0LmFlcyA9IEZBTFNFCiAgKSArCiAgZ2VvbV90ZXh0KAogICAgZGF0YSA9IHB2YWxzLAogICAgYWVzKAogICAgICB4ID0gKHhzdGFydCArIHhlbmQpIC8gMiwKICAgICAgeSA9IHkgKyAwLjUsCiAgICAgIGxhYmVsID0gY2FzZV93aGVuKAogICAgICAgIHBfdmFsdWUgPCAwLjAwMSB+ICIqKioqIiwKICAgICAgICBwX3ZhbHVlIDwgMC4wMDUgfiAiKioqIiwKICAgICAgICBwX3ZhbHVlIDwgMC4wMSAgfiAiKioiLAogICAgICAgIHBfdmFsdWUgPCAwLjA1ICB+ICIqIiwKICAgICAgICBUUlVFIH4gIiIKICAgICAgKQogICAgKSwKICAgIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICBzaXplID0gNAogICkKCmBgYAoKIyMgISEgUmVzaXN0YW5jZSB0byBQZXJzdWFzaW9uIHBlciBDb25kaXRpb24gLSBBTk9WQQoKKipGaW5kaW5nKio6IFdlIHBlcmZvcm1lZCBhIFNoYXBpcm8tV2lsayBub3JtYWxpdHkgdGVzdCwgd2hpY2ggZGV0ZXJtaW5lZCB0aGF0IHRoZSBjZXJ0YWludHkgc2NvcmVzIGFyZSBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgaW4gZWl0aGVyIG9mIHRoZSBjb25kaXRpb25zIChwIFw8IDAuMDEpLiBUaGVuLCB3ZSBwZXJmb3JtZWQgV2lsY294b24gcGFpcndpc2UgdGVzdHMgdG8gY29tcGFyZSB0aGUgQ2hhdGJvdCBjb25kaXRpb24gdG8gZWFjaCBvZiB0aGUgdGhyZWUgb3RoZXIgY29uZGl0aW9uLiBUYWxraW5nIHRvIEZvcnR5IHRoZSBjaGF0Ym90IG1hZGUgcGFydGljaXBhbnRzIHNpZ25pZmljYW50bHkgbW9yZSByZXNpc3RhbnQgdG8gYSBzdHJvbmcgY291bnRlci1hdHRpdHVkaW5hbCBtZXNzYWdlIHRoYW4gdGhlIHdyaXRpbmcgdGFzayAocCA9IC4wMiwgciA9LjM4KSwgdGhlIHJlYWRpbmcgdGFzayAocCA9IC4wMiwgciA9IC4zNCkgYW5kIGNvbnRyb2wgY29uZGl0aW9uIChwID0gLjAyLCByID0gLjMzKS4KCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJjb21wYW5pb24pCgojIC0tLS0gTm9ybWFsaXR5IGNoZWNrIHBlciBjb25kaXRpb24gLS0tLQpub3JtYWxpdHlfcmVzdWx0cyA8LSBwbG90X2RhdGEgJT4lCiAgZ3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBzdW1tYXJpc2UoCiAgICBzaGFwaXJvX3AgPSBpZmVsc2UobGVuZ3RoKGRpZmZfdmFsdWUpID49IDMsICAjIFNoYXBpcm8gdGVzdCByZXF1aXJlcyBhdCBsZWFzdCAzIG9icwogICAgICAgICAgICAgICAgICAgICAgIHNoYXBpcm8udGVzdChkaWZmX3ZhbHVlKSRwLnZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgIE5BX3JlYWxfKQogICkKCnByaW50KG5vcm1hbGl0eV9yZXN1bHRzKQoKCiMgLS0tLSBPdXRsaWVyIGRldGVjdGlvbiBhbmQgcmVtb3ZhbCAtLS0tCnBsb3RfZGF0YV93aXRoX2ZsYWdzIDwtIHBsb3RfZGF0YSAlPiUKICBncm91cF9ieShjb25kaXRpb24pICU+JQogIG11dGF0ZSgKICAgIFExID0gcXVhbnRpbGUoZGlmZl92YWx1ZSwgMC4yNSwgbmEucm0gPSBUUlVFKSwKICAgIFEzID0gcXVhbnRpbGUoZGlmZl92YWx1ZSwgMC43NSwgbmEucm0gPSBUUlVFKSwKICAgIElRUiA9IFEzIC0gUTEsCiAgICBsb3dlcl9ib3VuZCA9IFExIC0gMS41ICogSVFSLAogICAgdXBwZXJfYm91bmQgPSBRMyArIDEuNSAqIElRUiwKICAgIGlzX291dGxpZXIgPSBkaWZmX3ZhbHVlIDwgbG93ZXJfYm91bmQgfCBkaWZmX3ZhbHVlID4gdXBwZXJfYm91bmQKICApICU+JQogIHVuZ3JvdXAoKQoKcHJpbnQodGFibGUocGxvdF9kYXRhX3dpdGhfZmxhZ3MkaXNfb3V0bGllciwgcGxvdF9kYXRhX3dpdGhfZmxhZ3MkY29uZGl0aW9uKSkKCnBsb3RfZGF0YV9jbGVhbiA8LSBwbG90X2RhdGFfd2l0aF9mbGFncyAlPiUKICBmaWx0ZXIoIWlzX291dGxpZXIpICU+JQogIHNlbGVjdCgtUTEsIC1RMywgLUlRUiwgLWxvd2VyX2JvdW5kLCAtdXBwZXJfYm91bmQsIC1pc19vdXRsaWVyKQoKCiMgLS0tLSBDb21wdXRlIGFsbCBwYWlyd2lzZSBjb21wYXJpc29ucyB3aXRoIGVmZmVjdCBzaXplcyAtLS0tCnBhaXJ3aXNlX2NvbXBhcmlzb25zIDwtIGNvbWJuKHVuaXF1ZShwbG90X2RhdGFfY2xlYW4kY29uZGl0aW9uKSwgMiwgc2ltcGxpZnkgPSBGQUxTRSkKCmNvbXB1dGVfcGFpcndpc2Vfd2lsY294IDwtIGZ1bmN0aW9uKGdyb3VwMSwgZ3JvdXAyLCBkYXRhKSB7CiAgc3Vic2V0IDwtIGRhdGEgJT4lIGZpbHRlcihjb25kaXRpb24gJWluJSBjKGdyb3VwMSwgZ3JvdXAyKSkKICAKICBzdWJzZXQgPC0gc3Vic2V0ICU+JQogICAgbXV0YXRlKGdyb3VwX251bWVyaWMgPSBpZmVsc2UoY29uZGl0aW9uID09IGdyb3VwMSwgMSwgMikpCiAgCiAgIHRlc3QgPC0gd2lsY294LnRlc3QoZGlmZl92YWx1ZSB+IGdyb3VwX251bWVyaWMsCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHN1YnNldCwgCiAgICAgICAgICAgICAgICAgICAgICAgZXhhY3QgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgcC5hZGp1c3QubWV0aG9kID0gJ25vbmUnLAogICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0aXZlID0gImxlc3MiKQoKICBwcmludCh0ZXN0KQogIGVmZmVjdF9zaXplX3IgPC0gd2lsY294b25SKHggPSBzdWJzZXQkZGlmZl92YWx1ZSwgZyA9IHN1YnNldCRncm91cF9udW1lcmljKQogIAogIHRpYmJsZSgKICAgIGdyb3VwMSA9IGdyb3VwMSwKICAgIGdyb3VwMiA9IGdyb3VwMiwKICAgIHBfdmFsdWVfdW5jb3JyZWN0ZWQgPSB0ZXN0JHAudmFsdWUsCiAgICBlZmZlY3Rfc2l6ZV9yID0gZWZmZWN0X3NpemVfcgogICkKfQoKZWZmZWN0X3NpemVfcmVzdWx0cyA8LSBiaW5kX3Jvd3MoCiAgbGFwcGx5KHBhaXJ3aXNlX2NvbXBhcmlzb25zLCBmdW5jdGlvbihnKSB7CiAgICBjb21wdXRlX3BhaXJ3aXNlX3dpbGNveChnWzFdLCBnWzJdLCBwbG90X2RhdGFfY2xlYW4pCiAgfSkKKQoKIyAtLS0tIE5vdywgYWRqdXN0IHAtdmFsdWVzIG9ubHkgZm9yIHBhaXJzIGludm9sdmluZyB0aGUgTkVXIGNvbmRpdGlvbiAoZS5nLiwgIkNoYXRib3QiKSAtLS0tCm5ld19jb25kaXRpb24gPC0gIkNoYXRib3QiCgojIEZpbHRlciByb3dzIHdpdGggQ2hhdGJvdCBpbnZvbHZlZAplZmZlY3Rfc2l6ZV9uZXcgPC0gZWZmZWN0X3NpemVfcmVzdWx0cyAlPiUKICBmaWx0ZXIoZ3JvdXAxID09IG5ld19jb25kaXRpb24gfCBncm91cDIgPT0gbmV3X2NvbmRpdGlvbikgJT4lCiAgbXV0YXRlKAogICAgcF9hZGpfYm9uZl9zdWJzZXQgPSBwLmFkanVzdChwX3ZhbHVlX3VuY29ycmVjdGVkLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpLAogICAgcF9hZGpfYmhfc3Vic2V0ID0gcC5hZGp1c3QocF92YWx1ZV91bmNvcnJlY3RlZCwgbWV0aG9kID0gIkJIIikKICApCgojIFByaW50IGZ1bGwgZWZmZWN0IHNpemUgcmVzdWx0cyBmb3IgcmVmZXJlbmNlCnByaW50KGVmZmVjdF9zaXplX3Jlc3VsdHMpCgpjYXQoIlxuQWRqdXN0ZWQgcC12YWx1ZXMgT05MWSBmb3IgY29tcGFyaXNvbnMgaW52b2x2aW5nIiwgbmV3X2NvbmRpdGlvbiwgIjpcbiIpCnByaW50KGVmZmVjdF9zaXplX25ldykKCmBgYAoKIyMgUmVzaXN0YW5jZSB0byBQZXJzdWFzaW9uIHBlciBMZXNzb24gKGFsbCBjb25kaXRpb25zKQoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoZ2dwdWJyKQoKcGxvdF9kYXRhIDwtIGRhdGEgJT4lCiAgc2VsZWN0KG1hdGNoZXMoImxpa2VydF8obWlkfHBvc3QpX2xlc3NvblxcZCsiKSkgJT4lCiAgbXV0YXRlKGlkID0gcm93X251bWJlcigpKSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLWlkLAogICAgbmFtZXNfdG8gPSBjKCJwaGFzZSIsICJsZXNzb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAibGlrZXJ0XyhtaWR8cG9zdClfbGVzc29uKFxcZCspIiwKICAgIHZhbHVlc190byA9ICJzY29yZSIKICApICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBwaGFzZSwgdmFsdWVzX2Zyb20gPSBzY29yZSkgJT4lCiAgbXV0YXRlKAogICAgZGlmZl92YWx1ZSA9IHBvc3QgLSBtaWQsCiAgICBsZXNzb24gPSBjYXNlX3doZW4oCiAgICAgIGxlc3NvbiA9PSAiMSIgfiAiRXhlcmNpc2UgYW5kXG5NZW50YWwgSGVhbHRoIiwKICAgICAgbGVzc29uID09ICIyIiB+ICJCaW5nZSBEcmlua2luZyIsCiAgICAgIGxlc3NvbiA9PSAiMyIgfiAiUHJvdGVjdGluZyBOYXR1cmUiLAogICAgICBsZXNzb24gPT0gIjQiIH4gIkRlbnRhbCBIeWdpZW5lIiwKICAgICAgVFJVRSB+IGxlc3NvbiAgIyBzZXJ2ZXMgYXMgYSBmYWlsc2FmZQogICAgKSwKICAgICMgQ29udmVydCBsZXNzb24gdG8gYSBmYWN0b3Igd2l0aCBzcGVjaWZpZWQgbGV2ZWxzCiAgICBsZXNzb24gPSBmYWN0b3IobGVzc29uLCBsZXZlbHMgPSBjKCJFeGVyY2lzZSBhbmRcbk1lbnRhbCBIZWFsdGgiLCAiQmluZ2UgRHJpbmtpbmciLCAiUHJvdGVjdGluZyBOYXR1cmUiLCAiRGVudGFsIEh5Z2llbmUiKSkKICApCgojIFJlbW92ZSBvdXRsaWVycyAocGVyIGNvbmRpdGlvbiwgMS41IMOXIElRUiBydWxlKQpwbG90X2RhdGFfY2xlYW4gPC0gcGxvdF9kYXRhICU+JQogIGdyb3VwX2J5KGxlc3NvbikgJT4lCiAgbXV0YXRlKAogICAgUTEgPSBxdWFudGlsZShkaWZmX3ZhbHVlLCAwLjI1LCBuYS5ybSA9IFRSVUUpLAogICAgUTMgPSBxdWFudGlsZShkaWZmX3ZhbHVlLCAwLjc1LCBuYS5ybSA9IFRSVUUpLAogICAgSVFSID0gUTMgLSBRMSwKICAgIGxvd2VyX2JvdW5kID0gUTEgLSAxLjUgKiBJUVIsCiAgICB1cHBlcl9ib3VuZCA9IFEzICsgMS41ICogSVFSLAogICAgaXNfb3V0bGllciA9IGRpZmZfdmFsdWUgPCBsb3dlcl9ib3VuZCB8IGRpZmZfdmFsdWUgPiB1cHBlcl9ib3VuZAogICkgJT4lCiAgZmlsdGVyKCFpc19vdXRsaWVyKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgc2VsZWN0KC1RMSwgLVEzLCAtSVFSLCAtbG93ZXJfYm91bmQsIC11cHBlcl9ib3VuZCwgLWlzX291dGxpZXIpCgojIFN1bW1hcnkgc3RhdGlzdGljcyAodXNlIGNsZWFuZWQgZGF0YSkKc3VtbWFyeV9zdGF0c19jbGVhbiA8LSBwbG90X2RhdGFfY2xlYW4gJT4lCiAgZ3JvdXBfYnkobGVzc29uKSAlPiUKICBzdW1tYXJpc2UobWVhbl92YWwgPSBtZWFuKGRpZmZfdmFsdWUsIG5hLnJtID0gVFJVRSksIC5ncm91cHMgPSAiZHJvcCIpCgpwdmFscyA8LSBkYXRhLmZyYW1lKAogIGdyb3VwMSA9IGMoIkNvbnRyb2wiLCAiUmVhZGluZyIsICJXcml0aW5nIiksCiAgZ3JvdXAyID0gYygiQ2hhdGJvdCIsICJDaGF0Ym90IiwgIkNoYXRib3QiKSwKICBwX3ZhbHVlID0gYygwLjAwMSwgMC4wMiwgMC4wMiksICAjIHJlcGxhY2Ugd2l0aCB5b3VyIGFjdHVhbCBwLXZhbHVlcwogIHhzdGFydCA9IGMoMSwgMiwgMyksICAgICAgICAgICAgIyBudW1lcmljIHggZm9yIGdyb3VwczsgYWRqdXN0IGlmIHlvdXIgZmFjdG9yIGxldmVscyBkaWZmZXIKICB4ZW5kID0gYyg0LCA0LCA0KSwgICAgICAgICAgICAgICMgIkNoYXRib3QiIGFzc3VtZWQgYXQgcG9zaXRpb24gNAogIHkgPSBjKDUsIDYuOCwgOC42KSAgICAgICAgICAgICAgICMgeSBwb3NpdGlvbnMgZm9yIGJyYWNrZXRzLCBhZGp1c3QgYmFzZWQgb24geW91ciBkYXRhIHJhbmdlCikKCnB2YWxzIDwtIGRhdGEuZnJhbWUoCiAgZ3JvdXAxID0gYygiQ29udHJvbCIpLAogIGdyb3VwMiA9IGMoIkNoYXRib3QiKSwKICBwX3ZhbHVlID0gYygwLjAwMSksICAjIHJlcGxhY2Ugd2l0aCB5b3VyIGFjdHVhbCBwLXZhbHVlcwogIHhzdGFydCA9IGMoMSksICAgICAgICAgICAgIyBudW1lcmljIHggZm9yIGdyb3VwczsgYWRqdXN0IGlmIHlvdXIgZmFjdG9yIGxldmVscyBkaWZmZXIKICB4ZW5kID0gYyg0KSwgICAgICAgICAgICAgICMgIkNoYXRib3QiIGFzc3VtZWQgYXQgcG9zaXRpb24gNAogIHkgPSBjKDUpICAgICAgICAgICAgICAgIyB5IHBvc2l0aW9ucyBmb3IgYnJhY2tldHMsIGFkanVzdCBiYXNlZCBvbiB5b3VyIGRhdGEgcmFuZ2UKKQoKCiMgUGxvdCB1c2luZyBjbGVhbmVkIGRhdGEKZ2dwbG90KHBsb3RfZGF0YV9jbGVhbiwgYWVzKHggPSBsZXNzb24sIHkgPSBkaWZmX3ZhbHVlLCBmaWxsID0gbGVzc29uKSkgKwogIGdlb21fYm94cGxvdChhbHBoYSA9IDAuNSwgb3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9kb3RwbG90KGJpbmF4aXMgPSAieSIsIHN0YWNrZGlyID0gImNlbnRlciIsIGRvdHNpemUgPSAwLjUsIGFlcyhjb2xvciA9IGxlc3NvbikpICsKICBnZW9tX3BvaW50KGRhdGEgPSBzdW1tYXJ5X3N0YXRzX2NsZWFuLCBhZXMoeCA9IGxlc3NvbiwgeSA9IG1lYW5fdmFsKSwKICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMsIHNoYXBlID0gMTgpICsKICBnZW9tX3RleHQoZGF0YSA9IHN1bW1hcnlfc3RhdHNfY2xlYW4sIGFlcyh4ID0gbGVzc29uLCB5ID0gbWVhbl92YWwsIGxhYmVsID0gcm91bmQobWVhbl92YWwsIDIpKSwKICAgICAgICAgICAgdmp1c3QgPSAtMSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gNCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gImdyYXkiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHByZXR0eV9icmVha3MobiA9IDEwKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDaGFuZ2UgaW4gY2VydGFpbnR5IGFmdGVyIHN0cm9uZyBhdHRhY2siLAogICAgeCA9ICJMZXNzb24iLAogICAgeSA9ICJDZXJ0YWludHkgc2NvcmUgY2hhbmdlIiwKICAgIGZpbGwgPSAiTGVzc29uIiwKICAgIGNvbG9yID0gIkxlc3NvbiIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwoKICAjIEFkZCBicmFja2V0cyBhcyBsaW5lcwogIGdlb21fc2VnbWVudChkYXRhID0gcHZhbHMsIGFlcyh4ID0geHN0YXJ0LCB4ZW5kID0geGVuZCwgeSA9IHksIHllbmQgPSB5KSwKICAgICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSkgKwogIGdlb21fc2VnbWVudChkYXRhID0gcHZhbHMsIGFlcyh4ID0geHN0YXJ0LCB4ZW5kID0geHN0YXJ0LCB5ID0geSwgeWVuZCA9IHkgLSAwLjMpLAogICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFKSArCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBwdmFscywgYWVzKHggPSB4ZW5kLCB4ZW5kID0geGVuZCwgeSA9IHksIHllbmQgPSB5IC0gMC4zKSwKICAgICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSkgKwoKICAjIEFkZCBwLXZhbHVlIGxhYmVscywgc2hvdyAicCA8IDAuMDUiIGlmIGJlbG93IHRocmVzaG9sZCwgZWxzZSBibGFuawogIGdlb21fdGV4dCgKICBkYXRhID0gcHZhbHMsCiAgYWVzKHggPSAoeHN0YXJ0ICsgeGVuZCkgLyAyLCB5ID0geSArIDAuNSwKICAgICAgbGFiZWwgPSBjYXNlX3doZW4oCiAgICAgICAgcF92YWx1ZSA8IDAuMDAxIH4gIioqKioiLAogICAgICAgIHBfdmFsdWUgPCAwLjAwNSB+ICIqKioiLAogICAgICAgIHBfdmFsdWUgPCAwLjAxICB+ICIqKiIsCiAgICAgICAgcF92YWx1ZSA8IDAuMDUgIH4gIioiLAogICAgICAgIFRSVUUgfiAiIgogICAgICApKSwKICBpbmhlcml0LmFlcyA9IEZBTFNFLAogIHNpemUgPSAzCikKCmdncGxvdChwbG90X2RhdGFfY2xlYW4sIGFlcyh4ID0gbGVzc29uLCB5ID0gZGlmZl92YWx1ZSwgZmlsbCA9IGxlc3NvbikpICsKICBnZW9tX3Zpb2xpbih0cmltID0gRkFMU0UsIGFscGhhID0gMC42LCBjb2xvciA9IE5BLCBhZGp1c3QgPSAwLjYpICsgICMgVmlvbGluIG9ubHkKICBnZW9tX3BvaW50KAogICAgZGF0YSA9IHN1bW1hcnlfc3RhdHNfY2xlYW4sCiAgICBhZXMoeCA9IGxlc3NvbiwgeSA9IG1lYW5fdmFsKSwKICAgIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMsIHNoYXBlID0gMTgKICApICsKICBnZW9tX3RleHQoCiAgICBkYXRhID0gc3VtbWFyeV9zdGF0c19jbGVhbiwKICAgIGFlcyh4ID0gbGVzc29uLCB5ID0gbWVhbl92YWwsIGxhYmVsID0gcm91bmQobWVhbl92YWwsIDIpKSwKICAgIHZqdXN0ID0gLTEsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDQKICApICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmF5IikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MobiA9IDEwKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDaGFuZ2UgaW4gY2VydGFpbnR5IGFmdGVyIHN0cm9uZyBhdHRhY2siLAogICAgeCA9ICJMZXNzb24iLAogICAgeSA9ICJDZXJ0YWludHkgc2NvcmUgY2hhbmdlIiwKICAgIGZpbGwgPSAiTGVzc29uIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgZ2VvbV9zZWdtZW50KAogICAgZGF0YSA9IHB2YWxzLAogICAgYWVzKHggPSB4c3RhcnQsIHhlbmQgPSB4ZW5kLCB5ID0geSwgeWVuZCA9IHkpLAogICAgaW5oZXJpdC5hZXMgPSBGQUxTRQogICkgKwogIGdlb21fc2VnbWVudCgKICAgIGRhdGEgPSBwdmFscywKICAgIGFlcyh4ID0geHN0YXJ0LCB4ZW5kID0geHN0YXJ0LCB5ID0geSwgeWVuZCA9IHkgLSAwLjMpLAogICAgaW5oZXJpdC5hZXMgPSBGQUxTRQogICkgKwogIGdlb21fc2VnbWVudCgKICAgIGRhdGEgPSBwdmFscywKICAgIGFlcyh4ID0geGVuZCwgeGVuZCA9IHhlbmQsIHkgPSB5LCB5ZW5kID0geSAtIDAuMyksCiAgICBpbmhlcml0LmFlcyA9IEZBTFNFCiAgKSArCiAgZ2VvbV90ZXh0KAogICAgZGF0YSA9IHB2YWxzLAogICAgYWVzKAogICAgICB4ID0gKHhzdGFydCArIHhlbmQpIC8gMiwKICAgICAgeSA9IHkgKyAwLjUsCiAgICAgIGxhYmVsID0gY2FzZV93aGVuKAogICAgICAgIHBfdmFsdWUgPCAwLjAwMSB+ICIqKioqIiwKICAgICAgICBwX3ZhbHVlIDwgMC4wMDUgfiAiKioqIiwKICAgICAgICBwX3ZhbHVlIDwgMC4wMSAgfiAiKioiLAogICAgICAgIHBfdmFsdWUgPCAwLjA1ICB+ICIqIiwKICAgICAgICBUUlVFIH4gIiIKICAgICAgKQogICAgKSwKICAgIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICBzaXplID0gNAogICkKCmBgYAoKIyMgUmVzaXN0YW5jZSB0byBQZXJzdWFzaW9uIHBlciBMZXNzb24gKGFsbCBjb25kaXRpb25zKSAtIEFOT1ZBCgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeShyY29tcGFuaW9uKQoKIyAtLS0tIE5vcm1hbGl0eSBjaGVjayBwZXIgbGVzc29uIC0tLS0Kbm9ybWFsaXR5X3Jlc3VsdHMgPC0gcGxvdF9kYXRhICU+JQogIGdyb3VwX2J5KGxlc3NvbikgJT4lCiAgc3VtbWFyaXNlKAogICAgc2hhcGlyb19wID0gaWZlbHNlKGxlbmd0aChkaWZmX3ZhbHVlKSA+PSAzLCAgIyBTaGFwaXJvIHRlc3QgcmVxdWlyZXMgYXQgbGVhc3QgMyBvYnMKICAgICAgICAgICAgICAgICAgICAgICBzaGFwaXJvLnRlc3QoZGlmZl92YWx1ZSkkcC52YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICBOQV9yZWFsXykKICApCgpwcmludChub3JtYWxpdHlfcmVzdWx0cykKCgojIC0tLS0gT3V0bGllciBkZXRlY3Rpb24gYW5kIHJlbW92YWwgLS0tLQpwbG90X2RhdGFfd2l0aF9mbGFncyA8LSBwbG90X2RhdGEgJT4lCiAgZ3JvdXBfYnkobGVzc29uKSAlPiUKICBtdXRhdGUoCiAgICBRMSA9IHF1YW50aWxlKGRpZmZfdmFsdWUsIDAuMjUsIG5hLnJtID0gVFJVRSksCiAgICBRMyA9IHF1YW50aWxlKGRpZmZfdmFsdWUsIDAuNzUsIG5hLnJtID0gVFJVRSksCiAgICBJUVIgPSBRMyAtIFExLAogICAgbG93ZXJfYm91bmQgPSBRMSAtIDEuNSAqIElRUiwKICAgIHVwcGVyX2JvdW5kID0gUTMgKyAxLjUgKiBJUVIsCiAgICBpc19vdXRsaWVyID0gZGlmZl92YWx1ZSA8IGxvd2VyX2JvdW5kIHwgZGlmZl92YWx1ZSA+IHVwcGVyX2JvdW5kCiAgKSAlPiUKICB1bmdyb3VwKCkKCnByaW50KHRhYmxlKHBsb3RfZGF0YV93aXRoX2ZsYWdzJGlzX291dGxpZXIsIHBsb3RfZGF0YV93aXRoX2ZsYWdzJGxlc3NvbikpCgpwbG90X2RhdGFfY2xlYW4gPC0gcGxvdF9kYXRhX3dpdGhfZmxhZ3MgJT4lCiAgZmlsdGVyKCFpc19vdXRsaWVyKSAlPiUKICBzZWxlY3QoLVExLCAtUTMsIC1JUVIsIC1sb3dlcl9ib3VuZCwgLXVwcGVyX2JvdW5kLCAtaXNfb3V0bGllcikKCgojIC0tLS0gQ29tcHV0ZSBhbGwgcGFpcndpc2UgY29tcGFyaXNvbnMgd2l0aCBlZmZlY3Qgc2l6ZXMgLS0tLQpwYWlyd2lzZV9jb21wYXJpc29ucyA8LSBjb21ibih1bmlxdWUocGxvdF9kYXRhX2NsZWFuJGxlc3NvbiksIDIsIHNpbXBsaWZ5ID0gRkFMU0UpCgpjb21wdXRlX3BhaXJ3aXNlX3dpbGNveCA8LSBmdW5jdGlvbihncm91cDEsIGdyb3VwMiwgZGF0YSkgewogIHN1YnNldCA8LSBkYXRhICU+JSBmaWx0ZXIobGVzc29uICVpbiUgYyhncm91cDEsIGdyb3VwMikpCiAgCiAgc3Vic2V0IDwtIHN1YnNldCAlPiUKICAgIG11dGF0ZShncm91cF9udW1lcmljID0gaWZlbHNlKGxlc3NvbiA9PSBncm91cDEsIDEsIDIpKQogIAogICB0ZXN0IDwtIHdpbGNveC50ZXN0KGRpZmZfdmFsdWUgfiBncm91cF9udW1lcmljLAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBzdWJzZXQsIAogICAgICAgICAgICAgICAgICAgICAgIGV4YWN0ID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgIHAuYWRqdXN0Lm1ldGhvZCA9ICdub25lJywKICAgICAgICAgICAgICAgICAgICAgICBhbHRlcm5hdGl2ZSA9ICJsZXNzIikKCiAgcHJpbnQodGVzdCkKICBlZmZlY3Rfc2l6ZV9yIDwtIHdpbGNveG9uUih4ID0gc3Vic2V0JGRpZmZfdmFsdWUsIGcgPSBzdWJzZXQkZ3JvdXBfbnVtZXJpYykKICAKICB0aWJibGUoCiAgICBncm91cDEgPSBncm91cDEsCiAgICBncm91cDIgPSBncm91cDIsCiAgICBwX3ZhbHVlX3VuY29ycmVjdGVkID0gdGVzdCRwLnZhbHVlLAogICAgZWZmZWN0X3NpemVfciA9IGVmZmVjdF9zaXplX3IKICApCn0KCmVmZmVjdF9zaXplX3Jlc3VsdHMgPC0gYmluZF9yb3dzKAogIGxhcHBseShwYWlyd2lzZV9jb21wYXJpc29ucywgZnVuY3Rpb24oZykgewogICAgY29tcHV0ZV9wYWlyd2lzZV93aWxjb3goZ1sxXSwgZ1syXSwgcGxvdF9kYXRhX2NsZWFuKQogIH0pCikKCiMgLS0tLSBOb3csIGFkanVzdCBwLXZhbHVlcyBvbmx5IGZvciBwYWlycyBpbnZvbHZpbmcgdGhlIE5FVyBsZXNzb24gKGUuZy4sICJDaGF0Ym90IikgLS0tLQpuZXdfbGVzc29uIDwtICJDaGF0Ym90IgoKIyBGaWx0ZXIgcm93cyB3aXRoIENoYXRib3QgaW52b2x2ZWQKZWZmZWN0X3NpemVfbmV3IDwtIGVmZmVjdF9zaXplX3Jlc3VsdHMgJT4lCiAgZmlsdGVyKGdyb3VwMSA9PSBuZXdfbGVzc29uIHwgZ3JvdXAyID09IG5ld19sZXNzb24pICU+JQogIG11dGF0ZSgKICAgIHBfYWRqX2JvbmZfc3Vic2V0ID0gcC5hZGp1c3QocF92YWx1ZV91bmNvcnJlY3RlZCwgbWV0aG9kID0gImJvbmZlcnJvbmkiKSwKICAgIHBfYWRqX2JoX3N1YnNldCA9IHAuYWRqdXN0KHBfdmFsdWVfdW5jb3JyZWN0ZWQsIG1ldGhvZCA9ICJCSCIpCiAgKQoKIyBQcmludCBmdWxsIGVmZmVjdCBzaXplIHJlc3VsdHMgZm9yIHJlZmVyZW5jZQpwcmludChlZmZlY3Rfc2l6ZV9yZXN1bHRzKQoKY2F0KCJcbkFkanVzdGVkIHAtdmFsdWVzIE9OTFkgZm9yIGNvbXBhcmlzb25zIGludm9sdmluZyIsIG5ld19sZXNzb24sICI6XG4iKQpwcmludChlZmZlY3Rfc2l6ZV9uZXcpCgpgYGAKCiMgT3ZlcmFsbCBDaGFuZ2UgaW4gQ2VydGFpbnR5CgojIyBQZXIgQ29uZGl0aW9uCgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShnZ3B1YnIpCgojIERhdGEgd3JhbmdsaW5nCnBsb3RfZGF0YSA8LSBkYXRhICU+JQogIHNlbGVjdChtYXRjaGVzKCJsaWtlcnRfKHByZXxwb3N0KV9jb25kaXRpb25cXGQrIikpICU+JQogIG11dGF0ZShpZCA9IHJvd19udW1iZXIoKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC1pZCwKICAgIG5hbWVzX3RvID0gYygicGhhc2UiLCAiY29uZGl0aW9uIiksCiAgICBuYW1lc19wYXR0ZXJuID0gImxpa2VydF8ocHJlfHBvc3QpX2NvbmRpdGlvbihcXGQrKSIsCiAgICB2YWx1ZXNfdG8gPSAic2NvcmUiCiAgKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcGhhc2UsIHZhbHVlc19mcm9tID0gc2NvcmUpICU+JQogIG11dGF0ZSgKICAgIGRpZmZfdmFsdWUgPSBwb3N0IC0gcHJlLAogICAgY29uZGl0aW9uID0gcmVjb2RlKGNvbmRpdGlvbiwKICAgICAgIjEiID0gIkNvbnRyb2wiLAogICAgICAiMiIgPSAiUmVhZGluZyIsCiAgICAgICIzIiA9ICJXcml0aW5nIiwKICAgICAgIjQiID0gIkNoYXRib3QiCiAgICApLAogICAgY29uZGl0aW9uID0gZmFjdG9yKGNvbmRpdGlvbiwgbGV2ZWxzID0gYygiQ29udHJvbCIsICJSZWFkaW5nIiwgIldyaXRpbmciLCAiQ2hhdGJvdCIpKQogICkKCiMgUmVtb3ZlIG91dGxpZXJzIChwZXIgY29uZGl0aW9uLCAxLjUgw5cgSVFSIHJ1bGUpCnBsb3RfZGF0YV9jbGVhbiA8LSBwbG90X2RhdGEgJT4lCiAgZ3JvdXBfYnkoY29uZGl0aW9uKSAlPiUKICBtdXRhdGUoCiAgICBRMSA9IHF1YW50aWxlKGRpZmZfdmFsdWUsIDAuMjUsIG5hLnJtID0gVFJVRSksCiAgICBRMyA9IHF1YW50aWxlKGRpZmZfdmFsdWUsIDAuNzUsIG5hLnJtID0gVFJVRSksCiAgICBJUVIgPSBRMyAtIFExLAogICAgbG93ZXJfYm91bmQgPSBRMSAtIDEuNSAqIElRUiwKICAgIHVwcGVyX2JvdW5kID0gUTMgKyAxLjUgKiBJUVIsCiAgICBpc19vdXRsaWVyID0gZGlmZl92YWx1ZSA8IGxvd2VyX2JvdW5kIHwgZGlmZl92YWx1ZSA+IHVwcGVyX2JvdW5kCiAgKSAlPiUKICBmaWx0ZXIoIWlzX291dGxpZXIpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBzZWxlY3QoLVExLCAtUTMsIC1JUVIsIC1sb3dlcl9ib3VuZCwgLXVwcGVyX2JvdW5kLCAtaXNfb3V0bGllcikKCiMgU3VtbWFyeSBzdGF0aXN0aWNzICh1c2UgY2xlYW5lZCBkYXRhKQpzdW1tYXJ5X3N0YXRzX2NsZWFuIDwtIHBsb3RfZGF0YV9jbGVhbiAlPiUKICBncm91cF9ieShjb25kaXRpb24pICU+JQogIHN1bW1hcmlzZShtZWFuX3ZhbCA9IG1lYW4oZGlmZl92YWx1ZSwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICJkcm9wIikKCnB2YWxzIDwtIGRhdGEuZnJhbWUoCiAgZ3JvdXAxID0gYygiQ29udHJvbCIsICJSZWFkaW5nIiwgIldyaXRpbmciKSwKICBncm91cDIgPSBjKCJDaGF0Ym90IiwgIkNoYXRib3QiLCAiQ2hhdGJvdCIpLAogIHBfdmFsdWUgPSBjKDAuMDEsIDAuMDEsIDAuMDEpLCAgIyByZXBsYWNlIHdpdGggeW91ciBhY3R1YWwgcC12YWx1ZXMKICB4c3RhcnQgPSBjKDEsIDIsIDMpLCAgICAgICAgICAgICMgbnVtZXJpYyB4IGZvciBncm91cHM7IGFkanVzdCBpZiB5b3VyIGZhY3RvciBsZXZlbHMgZGlmZmVyCiAgeGVuZCA9IGMoNCwgNCwgNCksICAgICAgICAgICAgICAjICJDaGF0Ym90IiBhc3N1bWVkIGF0IHBvc2l0aW9uIDQKICB5ID0gYyg1LCA2LjgsIDguNikgICAgICAgICAgICAgICAjIHkgcG9zaXRpb25zIGZvciBicmFja2V0cywgYWRqdXN0IGJhc2VkIG9uIHlvdXIgZGF0YSByYW5nZQopCgoKIyBQbG90IHVzaW5nIGNsZWFuZWQgZGF0YQpnZ3Bsb3QocGxvdF9kYXRhX2NsZWFuLCBhZXMoeCA9IGNvbmRpdGlvbiwgeSA9IGRpZmZfdmFsdWUsIGZpbGwgPSBjb25kaXRpb24pKSArCiAgZ2VvbV9ib3hwbG90KGFscGhhID0gMC41LCBvdXRsaWVyLnNoYXBlID0gTkEpICsKICBnZW9tX2RvdHBsb3QoYmluYXhpcyA9ICJ5Iiwgc3RhY2tkaXIgPSAiY2VudGVyIiwgZG90c2l6ZSA9IDAuNSwgYWVzKGNvbG9yID0gY29uZGl0aW9uKSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IHN1bW1hcnlfc3RhdHNfY2xlYW4sIGFlcyh4ID0gY29uZGl0aW9uLCB5ID0gbWVhbl92YWwpLAogICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMywgc2hhcGUgPSAxOCkgKwogIGdlb21fdGV4dChkYXRhID0gc3VtbWFyeV9zdGF0c19jbGVhbiwgYWVzKHggPSBjb25kaXRpb24sIHkgPSBtZWFuX3ZhbCwgbGFiZWwgPSByb3VuZChtZWFuX3ZhbCwgMikpLAogICAgICAgICAgICB2anVzdCA9IC0xLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSA0KSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JheSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gcHJldHR5X2JyZWFrcyhuID0gMTApKSArCiAgbGFicygKICAgIHRpdGxlID0gIkNoYW5nZSBpbiBjZXJ0YWludHkgYWZ0ZXIgc3Ryb25nIGF0dGFjayIsCiAgICB4ID0gIkNvbmRpdGlvbiIsCiAgICB5ID0gIkNlcnRhaW50eSBzY29yZSBjaGFuZ2UiLAogICAgZmlsbCA9ICJDb25kaXRpb24iLAogICAgY29sb3IgPSAiQ29uZGl0aW9uIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCgogICMgQWRkIGJyYWNrZXRzIGFzIGxpbmVzCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBwdmFscywgYWVzKHggPSB4c3RhcnQsIHhlbmQgPSB4ZW5kLCB5ID0geSwgeWVuZCA9IHkpLAogICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFKSArCiAgZ2VvbV9zZWdtZW50KGRhdGEgPSBwdmFscywgYWVzKHggPSB4c3RhcnQsIHhlbmQgPSB4c3RhcnQsIHkgPSB5LCB5ZW5kID0geSAtIDAuMyksCiAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UpICsKICBnZW9tX3NlZ21lbnQoZGF0YSA9IHB2YWxzLCBhZXMoeCA9IHhlbmQsIHhlbmQgPSB4ZW5kLCB5ID0geSwgeWVuZCA9IHkgLSAwLjMpLAogICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFKSArCgogICMgQWRkIHAtdmFsdWUgbGFiZWxzLCBzaG93ICJwIDwgMC4wNSIgaWYgYmVsb3cgdGhyZXNob2xkLCBlbHNlIGJsYW5rCiAgZ2VvbV90ZXh0KAogICAgZGF0YSA9IHB2YWxzLAogICAgYWVzKHggPSAoeHN0YXJ0ICsgeGVuZCkgLyAyLCB5ID0geSArIDAuNSwKICAgICAgICBsYWJlbCA9IGlmZWxzZShwX3ZhbHVlIDwgMC4wNSwgIioiLCAiIikpLAogICAgaW5oZXJpdC5hZXMgPSBGQUxTRSwKICAgIHNpemUgPSAzCiAgKQoKCmBgYAoKIyBJTUkgRGF0YQoKIyMgT3ZlcmFsbCBNaW5kZm9ydCBJTUkKCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGxpa2VydCkKCiMgTG9hZCBhbmQgY2xlYW4KaW1pIDwtIHJlYWRfY3N2KCJpbWkuY3N2Iiwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkKZXhjbHVkZWRfaWRzIDwtIGMoIjY4MmY0N2EwMzA5NTU2MmJkNTgxYmQwNiIsICI2NzRkN2E4OWY1NjRlOGJiZTBhN2FmMWMiLCAiNjU1MzdlMTQ0MzkyNzRmZTUwMzZiNGQyIikKaW1pX2NsZWFuIDwtIGltaSAlPiUgZmlsdGVyKCFwcm9saWZpY19pZCAlaW4lIGV4Y2x1ZGVkX2lkcykKCiMgU2VsZWN0IGFsbCBsZXNzb24gY29sdW1ucyAobGVzc29uMSB0byBsZXNzb240KQpsZXNzb25fY29scyA8LSBpbWlfY2xlYW4gJT4lIAogIHNlbGVjdChwYXJ0aWNpcGFudF9pZCwgbWF0Y2hlcygiXmltaVxcZCtfbGVzc29uWzEtNF0kIikpCgojIENvbnZlcnQgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0CmxvbmdfZGF0YSA8LSBsZXNzb25fY29scyAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLXBhcnRpY2lwYW50X2lkLAogICAgbmFtZXNfdG8gPSBjKCJxdWVzdGlvbiIsICJsZXNzb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAiaW1pKFxcZCspX2xlc3NvbihcXGQpIiwKICAgIHZhbHVlc190byA9ICJyZXNwb25zZSIKICApICU+JQogIG11dGF0ZSgKICAgIHF1ZXN0aW9uID0gZmFjdG9yKHBhc3RlMCgiUSIsIHF1ZXN0aW9uKSwgbGV2ZWxzID0gcGFzdGUwKCJRIiwgMToyNSksIG9yZGVyZWQgPSBUUlVFKSwKICAgIHJlc3BvbnNlID0gZmFjdG9yKGFzLm51bWVyaWMocmVzcG9uc2UpLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gMTo3LAogICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiRXh0cmVtZWx5IGRpc2FncmVlIiwgIkRpc2FncmVlIiwgIlNsaWdodGx5IGRpc2FncmVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXRyYWwiLCAiU2xpZ2h0bHkgYWdyZWUiLCAiQWdyZWUiLCAiRXh0cmVtZWx5IGFncmVlIiksCiAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkKICApCgojIENvbnZlcnQgdG8gd2lkZSBmb3JtYXQgZm9yIGxpa2VydDogcm93cyA9IHJlc3BvbnNlcywgY29sdW1ucyA9IFEx4oCTUTI1Cmxpa2VydF9yZWFkeSA8LSBsb25nX2RhdGEgJT4lCiAgYXJyYW5nZShwYXJ0aWNpcGFudF9pZCwgbGVzc29uKSAlPiUKICBncm91cF9ieShwYXJ0aWNpcGFudF9pZCwgbGVzc29uKSAlPiUKICBtdXRhdGUocmVzcG9uc2VfaWQgPSBjdXJfZ3JvdXBfaWQoKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIHNlbGVjdChyZXNwb25zZV9pZCwgcXVlc3Rpb24sIHJlc3BvbnNlKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcXVlc3Rpb24sIHZhbHVlc19mcm9tID0gcmVzcG9uc2UpICU+JQogIHNlbGVjdChwYXN0ZTAoIlEiLCAxOjI1KSkgICMgRW5zdXJlIGNvcnJlY3Qgb3JkZXIKCiMgQ29udmVydCB0byBkYXRhLmZyYW1lIGZvciBsaWtlcnQgcGFja2FnZQpsaWtlcnRfcmVhZHkgPC0gYXMuZGF0YS5mcmFtZShsaWtlcnRfcmVhZHkpCgojIENyZWF0ZSBhbmQgcGxvdApsaWtlcnRfb2JqIDwtIGxpa2VydChsaWtlcnRfcmVhZHkpCnBsb3QobGlrZXJ0X29iaiwgZ3JvdXAub3JkZXIgPSBwYXN0ZTAoIlEiLCAxOjI1KSkKCgpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQoKIyBMb2FkIGFuZCBjbGVhbgppbWkgPC0gcmVhZF9jc3YoImltaS5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQpleGNsdWRlZF9pZHMgPC0gYygiNjgyZjQ3YTAzMDk1NTYyYmQ1ODFiZDA2IiwgIjY3NGQ3YTg5ZjU2NGU4YmJlMGE3YWYxYyIsICI2NTUzN2UxNDQzOTI3NGZlNTAzNmI0ZDIiKQppbWlfY2xlYW4gPC0gaW1pICU+JSBmaWx0ZXIoIXByb2xpZmljX2lkICVpbiUgZXhjbHVkZWRfaWRzKQoKIyBTZWxlY3QgYWxsIGxlc3NvbiBjb2x1bW5zIChsZXNzb24xIHRvIGxlc3NvbjQpCmxlc3Nvbl9jb2xzIDwtIGltaV9jbGVhbiAlPiUgCiAgc2VsZWN0KHBhcnRpY2lwYW50X2lkLCBtYXRjaGVzKCJeaW1pXFxkK19sZXNzb25bMS00XSQiKSkKCiMgQ29udmVydCBmcm9tIHdpZGUgdG8gbG9uZyBmb3JtYXQKbG9uZ19kYXRhIDwtIGxlc3Nvbl9jb2xzICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtcGFydGljaXBhbnRfaWQsCiAgICBuYW1lc190byA9IGMoInF1ZXN0aW9uIiwgImxlc3NvbiIpLAogICAgbmFtZXNfcGF0dGVybiA9ICJpbWkoXFxkKylfbGVzc29uKFxcZCkiLAogICAgdmFsdWVzX3RvID0gInJlc3BvbnNlIgogICkgJT4lCiAgbXV0YXRlKAogICAgIyBRMSBpcyBpbWkwLCBzbyBRbiA9IGltaW4tMSwgbm93IGxhYmVsIG5pY2VseSBhZ2FpbiBmb3IgcmVwb3J0aW5nCiAgICBxdWVzdGlvbiA9IGZhY3RvcihwYXN0ZTAoIlEiLCBxdWVzdGlvbiksIGxldmVscyA9IHBhc3RlMCgiUSIsIDE6MjUpLCBvcmRlcmVkID0gVFJVRSkKICApCgojIFJldmVyc2Utc2NvcmUgdGhlIHJpZ2h0IHF1ZXN0aW9ucwpyZXZlcnNlX3F1ZXN0aW9ucyA8LSBjKCJROCIsICJRMTIiLCAiUTE0IiwgIlExOCIsICJRMjAiLCAiUTI0IikKbG9uZ19kYXRhIDwtIGxvbmdfZGF0YSAlPiUKICBtdXRhdGUoCiAgICByZXNwb25zZV9udW0gPSBhcy5udW1lcmljKHJlc3BvbnNlKSwKICAgIHJlc3BvbnNlX251bSA9IGlmZWxzZShxdWVzdGlvbiAlaW4lIHJldmVyc2VfcXVlc3Rpb25zLCA4IC0gcmVzcG9uc2VfbnVtLCByZXNwb25zZV9udW0pCiAgKQoKIyBDYWxjdWxhdGUgYW5kIHByaW50IG1lYW5zIGZvciBlYWNoIHF1ZXN0aW9uCnF1ZXN0aW9uX21lYW5zIDwtIGxvbmdfZGF0YSAlPiUKICBncm91cF9ieShxdWVzdGlvbikgJT4lCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHJlc3BvbnNlX251bSwgbmEucm0gPSBUUlVFKSkgJT4lCiAgYXJyYW5nZShxdWVzdGlvbikKCnByaW50KHF1ZXN0aW9uX21lYW5zKQoKYGBgCgojIyBJTUkgQWxsIFN1YnNjYWxlcyBwZXIgQ29uZGl0aW9uCgpgYGB7cn0KIyBMb2FkIGxpYnJhcmllcwpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCgojIERlZmluZSBzdWJzY2FsZSBtYXAKc3Vic2NhbGVfbWFwIDwtIHRyaWJibGUoCiAgfnFuLCB+c3Vic2NhbGUsIH5yZXZlcnNlLAogICAxLCAgICAgMSwgICAgICBGQUxTRSwKICAgMiwgICAgIDEsICAgICAgRkFMU0UsCiAgIDMsICAgICAxLCAgICAgIFRSVUUsCiAgIDQsICAgICAxLCAgICAgIFRSVUUsCiAgIDUsICAgICAxLCAgICAgIEZBTFNFLAogICA2LCAgICAgMSwgICAgICBGQUxTRSwKICAgNywgICAgIDEsICAgICAgRkFMU0UsCiAgIDgsICAgICAyLCAgICAgIEZBTFNFLAogICA5LCAgICAgMiwgICAgICBGQUxTRSwKICAxMCwgICAgIDIsICAgICAgRkFMU0UsCiAgMTEsICAgICAyLCAgICAgIEZBTFNFLAogIDEyLCAgICAgMiwgICAgICBGQUxTRSwKICAxMywgICAgIDIsICAgICAgVFJVRSwKICAxNCwgICAgIDMsICAgICAgRkFMU0UsCiAgMTUsICAgICAzLCAgICAgIFRSVUUsCiAgMTYsICAgICAzLCAgICAgIEZBTFNFLAogIDE3LCAgICAgMywgICAgICBGQUxTRSwKICAxOCwgICAgIDMsICAgICAgVFJVRSwKICAxOSwgICAgIDQsICAgICAgRkFMU0UsCiAgMjAsICAgICA0LCAgICAgIEZBTFNFLAogIDIxLCAgICAgNCwgICAgICBGQUxTRSwKICAyMiwgICAgIDQsICAgICAgRkFMU0UsCiAgMjMsICAgICA0LCAgICAgIEZBTFNFLAogIDI0LCAgICAgNCwgICAgICBGQUxTRSwKICAyNSwgICAgIDQsICAgICAgRkFMU0UKKQoKIyBMb2FkIGFuZCBjbGVhbgppbWkgPC0gcmVhZF9jc3YoImltaS5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQpleGNsdWRlZF9pZHMgPC0gYygiNjgyZjQ3YTAzMDk1NTYyYmQ1ODFiZDA2IiwgIjY3NGQ3YTg5ZjU2NGU4YmJlMGE3YWYxYyIsICI2NTUzN2UxNDQzOTI3NGZlNTAzNmI0ZDIiKQppbWlfY2xlYW4gPC0gaW1pICU+JSBmaWx0ZXIoIXByb2xpZmljX2lkICVpbiUgZXhjbHVkZWRfaWRzKQoKIyBQcmVwYXJlIHF1ZXN0aW9uIGNvbHVtbnMKcW51bXNfYWxsIDwtIDE6MjUKY29uZGl0aW9uX2NvbHMgPC0gaW1pX2NsZWFuICU+JQogIHNlbGVjdCgKICAgIHBhcnRpY2lwYW50X2lkLAogICAgIyBDb25kaXRpb25zIDHigJM0CiAgICBhbGxfb2YodW5saXN0KGxhcHBseSgxOjQsIGZ1bmN0aW9uKGMpIHBhc3RlMCgiaW1pIiwgcW51bXNfYWxsLCAiX2NvbmRpdGlvbiIsIGMpKSkpLAogICAgIyBDb25kaXRpb24gNSAoX2ZpbmFsKQogICAgYWxsX29mKHBhc3RlMCgiaW1pIiwgcW51bXNfYWxsLCAiX2ZpbmFsIikpCiAgKQoKIyBQaXZvdCB0byBsb25nIGZvcm1hdCAoaGFuZGxlIGJvdGggcGF0dGVybnMpCmxvbmdfZGF0YSA8LSBjb25kaXRpb25fY29scyAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLXBhcnRpY2lwYW50X2lkLAogICAgbmFtZXNfdG8gPSAiaXRlbSIsCiAgICB2YWx1ZXNfdG8gPSAicmVzcG9uc2UiCiAgKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHJlc3BvbnNlKSkgJT4lCiAgbXV0YXRlKAogICAgcW4gPSBhcy5pbnRlZ2VyKHN0cl9leHRyYWN0KGl0ZW0sICJcXGQrIikpLAogICAgY29uZGl0aW9uID0gY2FzZV93aGVuKAogICAgICBncmVwbCgiX2NvbmRpdGlvbihcXGQpIiwgaXRlbSkgfiBzdHJfZXh0cmFjdChpdGVtLCAiKD88PV9jb25kaXRpb24pXFxkIiksCiAgICAgIGdyZXBsKCJfZmluYWwkIiwgaXRlbSkgfiAiNSIKICAgICksCiAgICByZXNwb25zZV9udW0gPSBhcy5udW1lcmljKHJlc3BvbnNlKQogICkgJT4lCiAgbGVmdF9qb2luKHN1YnNjYWxlX21hcCwgYnkgPSAicW4iKSAlPiUKICBtdXRhdGUoCiAgICByZXNwb25zZV9udW0gPSBpZmVsc2UocmV2ZXJzZSwgOCAtIHJlc3BvbnNlX251bSwgcmVzcG9uc2VfbnVtKQogICkKCiMgQXZlcmFnZSBwZXIgc3Vic2NhbGUKc3Vic2NhbGVfc2NvcmVzIDwtIGxvbmdfZGF0YSAlPiUKICBncm91cF9ieShwYXJ0aWNpcGFudF9pZCwgY29uZGl0aW9uLCBzdWJzY2FsZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z19zY29yZSA9IG1lYW4ocmVzcG9uc2VfbnVtLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQoKIyAxLjUqSVFSIG91dGxpZXIgcmVtb3ZhbApmaWx0ZXJlZF9zY29yZXMgPC0gc3Vic2NhbGVfc2NvcmVzICU+JQogIGdyb3VwX2J5KGNvbmRpdGlvbiwgc3Vic2NhbGUpICU+JQogIG11dGF0ZSgKICAgIFExID0gcXVhbnRpbGUoYXZnX3Njb3JlLCAwLjI1KSwKICAgIFEzID0gcXVhbnRpbGUoYXZnX3Njb3JlLCAwLjc1KSwKICAgIElRUiA9IFEzIC0gUTEsCiAgICBsb3dlciA9IFExIC0gMS41ICogSVFSLAogICAgdXBwZXIgPSBRMyArIDEuNSAqIElRUgogICkgJT4lCiAgZmlsdGVyKGF2Z19zY29yZSA+PSBsb3dlciAmIGF2Z19zY29yZSA8PSB1cHBlcikgJT4lCiAgdW5ncm91cCgpCgojIE1lYW4gbGFiZWxzCm1lYW5fbGFiZWxzIDwtIGZpbHRlcmVkX3Njb3JlcyAlPiUKICBncm91cF9ieShjb25kaXRpb24sIHN1YnNjYWxlKSAlPiUKICBzdW1tYXJpc2UobWVhbl92YWwgPSBtZWFuKGF2Z19zY29yZSksIC5ncm91cHMgPSAiZHJvcCIpCgojIERlZmluZSBzdWJzY2FsZSBuYW1lcwpzdWJzY2FsZV9uYW1lcyA8LSBjKAogICIxIiA9ICJJbnRlcmVzdC9FbmpveW1lbnQiLAogICIyIiA9ICJQZXJjZWl2ZWQgQ29tcGV0ZW5jZSIsCiAgIjMiID0gIkVmZm9ydC9JbXBvcnRhbmNlIiwKICAiNCIgPSAiVmFsdWUvVXNlZnVsbmVzcyIKKQoKIyBBcHBseSBmYWN0b3IgbGFiZWxzCmZpbHRlcmVkX3Njb3JlcyA8LSBmaWx0ZXJlZF9zY29yZXMgJT4lCiAgbXV0YXRlKHN1YnNjYWxlID0gZmFjdG9yKHN1YnNjYWxlLCBsZXZlbHMgPSBuYW1lcyhzdWJzY2FsZV9uYW1lcyksIGxhYmVscyA9IHN1YnNjYWxlX25hbWVzKSkKCm1lYW5fbGFiZWxzIDwtIG1lYW5fbGFiZWxzICU+JQogIG11dGF0ZShzdWJzY2FsZSA9IGZhY3RvcihzdWJzY2FsZSwgbGV2ZWxzID0gbmFtZXMoc3Vic2NhbGVfbmFtZXMpLCBsYWJlbHMgPSBzdWJzY2FsZV9uYW1lcykpCgojIERlZmluZSBhbGwgY29uZGl0aW9uIGxhYmVscyBpbmNsdWRpbmcgIkZpbmFsIgpjb25kaXRpb25fbGFiZWxzIDwtIGMoCiAgIjEiID0gIkNvbnRyb2wiLAogICIyIiA9ICJSZWFkaW5nIiwKICAiMyIgPSAiV3JpdGluZyIsCiAgIjQiID0gIkNoYXRib3QiLAogICI1IiA9ICJGaW5hbCIKKQoKIyBBcHBseSBkZXNjcmlwdGl2ZSBsYWJlbHMKZmlsdGVyZWRfc2NvcmVzIDwtIGZpbHRlcmVkX3Njb3JlcyAlPiUKICBtdXRhdGUoY29uZGl0aW9uX2xhYmVsID0gZmFjdG9yKGNvbmRpdGlvbiwgbGV2ZWxzID0gbmFtZXMoY29uZGl0aW9uX2xhYmVscyksIGxhYmVscyA9IGNvbmRpdGlvbl9sYWJlbHMpKQoKbWVhbl9sYWJlbHMgPC0gbWVhbl9sYWJlbHMgJT4lCiAgbXV0YXRlKGNvbmRpdGlvbl9sYWJlbCA9IGZhY3Rvcihjb25kaXRpb24sIGxldmVscyA9IG5hbWVzKGNvbmRpdGlvbl9sYWJlbHMpLCBsYWJlbHMgPSBjb25kaXRpb25fbGFiZWxzKSkKCiMgUGxvdCB3aXRoIGFsbCA1IGNvbmRpdGlvbnMKZ2dwbG90KGZpbHRlcmVkX3Njb3JlcywgYWVzKHggPSBzdWJzY2FsZSwgeSA9IGF2Z19zY29yZSwgZmlsbCA9IGNvbmRpdGlvbl9sYWJlbCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43NSkpICsKICBnZW9tX2ppdHRlcihhZXMoY29sb3IgPSBjb25kaXRpb25fbGFiZWwpLCBzaXplID0gMS41LCBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcmRvZGdlKGppdHRlci53aWR0aCA9IDAuMSwgZG9kZ2Uud2lkdGggPSAwLjc1KSkgKwogIGdlb21fdGV4dCgKICAgIGRhdGEgPSBtZWFuX2xhYmVscywKICAgIGFlcyhsYWJlbCA9IHJvdW5kKG1lYW5fdmFsLCAyKSwgeSA9IG1lYW5fdmFsKSwKICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjc1KSwKICAgIHZqdXN0ID0gLTAuNSwKICAgIHNpemUgPSAzLAogICAgY29sb3IgPSAiYmxhY2siCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIkF2ZXJhZ2UgU3Vic2NhbGUgU2NvcmVzIGJ5IENvbmRpdGlvbiAoT3V0bGllcnMgUmVtb3ZlZCkiLAogICAgeCA9ICJTdWJzY2FsZSIsCiAgICB5ID0gIkF2ZXJhZ2UgU2NvcmUgKFJldmVyc2VkIHdoZXJlIG5lZWRlZCkiLAogICAgZmlsbCA9ICJDb25kaXRpb24iLAogICAgY29sb3IgPSAiQ29uZGl0aW9uIgogICkgKwogIHRoZW1lX21pbmltYWwoKQoKYGBgCgojIyBJTUkgQWxsIFN1YnNjYWxlcyBwZXIgQ29uZGl0aW9uIC0gQU5PVkEKCmBgYHtyfQojIExvYWQgbGlicmFyaWVzCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShzdGF0cykKCiMgRGVmaW5lIHN1YnNjYWxlIG1hcApzdWJzY2FsZV9tYXAgPC0gdHJpYmJsZSgKICB+cW4sIH5zdWJzY2FsZSwgfnJldmVyc2UsCiAgIDEsICAgICAxLCAgICAgIEZBTFNFLAogICAyLCAgICAgMSwgICAgICBGQUxTRSwKICAgMywgICAgIDEsICAgICAgVFJVRSwKICAgNCwgICAgIDEsICAgICAgVFJVRSwKICAgNSwgICAgIDEsICAgICAgRkFMU0UsCiAgIDYsICAgICAxLCAgICAgIEZBTFNFLAogICA3LCAgICAgMSwgICAgICBGQUxTRSwKICAgOCwgICAgIDIsICAgICAgRkFMU0UsCiAgIDksICAgICAyLCAgICAgIEZBTFNFLAogIDEwLCAgICAgMiwgICAgICBGQUxTRSwKICAxMSwgICAgIDIsICAgICAgRkFMU0UsCiAgMTIsICAgICAyLCAgICAgIEZBTFNFLAogIDEzLCAgICAgMiwgICAgICBUUlVFLAogIDE0LCAgICAgMywgICAgICBGQUxTRSwKICAxNSwgICAgIDMsICAgICAgVFJVRSwKICAxNiwgICAgIDMsICAgICAgRkFMU0UsCiAgMTcsICAgICAzLCAgICAgIEZBTFNFLAogIDE4LCAgICAgMywgICAgICBUUlVFLAogIDE5LCAgICAgNCwgICAgICBGQUxTRSwKICAyMCwgICAgIDQsICAgICAgRkFMU0UsCiAgMjEsICAgICA0LCAgICAgIEZBTFNFLAogIDIyLCAgICAgNCwgICAgICBGQUxTRSwKICAyMywgICAgIDQsICAgICAgRkFMU0UsCiAgMjQsICAgICA0LCAgICAgIEZBTFNFLAogIDI1LCAgICAgNCwgICAgICBGQUxTRQopCgojIExvYWQgZGF0YQppbWkgPC0gcmVhZF9jc3YoImltaS5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQoKIyBFeGNsdWRlIHByb2JsZW1hdGljIHBhcnRpY2lwYW50IElEcwpleGNsdWRlZF9pZHMgPC0gYygiNjgyZjQ3YTAzMDk1NTYyYmQ1ODFiZDA2IiwgIjY3NGQ3YTg5ZjU2NGU4YmJlMGE3YWYxYyIsICI2NTUzN2UxNDQzOTI3NGZlNTAzNmI0ZDIiKQppbWlfY2xlYW4gPC0gaW1pICU+JSBmaWx0ZXIoIXByb2xpZmljX2lkICVpbiUgZXhjbHVkZWRfaWRzKQoKIyBQcmVwYXJlIGNvbHVtbiBuYW1lcwpxbnVtc19hbGwgPC0gMToyNQpjb25kaXRpb25fMV80X2NvbHMgPC0gcGFzdGUwKCJpbWkiLCBxbnVtc19hbGwsICJfY29uZGl0aW9uIiwgcmVwKDE6NCwgZWFjaCA9IDI1KSkKY29uZGl0aW9uXzVfY29scyA8LSBwYXN0ZTAoImltaSIsIHFudW1zX2FsbCwgIl9maW5hbCIpCmFsbF9pbWlfY29scyA8LSB1bmlxdWUoYygicGFydGljaXBhbnRfaWQiLCBjb25kaXRpb25fMV80X2NvbHMsIGNvbmRpdGlvbl81X2NvbHMpKQoKIyBTZWxlY3QgcmVsZXZhbnQgY29sdW1ucwpjb25kaXRpb25fY29scyA8LSBpbWlfY2xlYW4gJT4lIHNlbGVjdChhbnlfb2YoYWxsX2ltaV9jb2xzKSkKCiMgUGl2b3QgbG9uZ2VyIHRvIGluY2x1ZGUgYm90aCBjb25kaXRpb24gdHlwZXMKbG9uZ19kYXRhIDwtIGNvbmRpdGlvbl9jb2xzICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtcGFydGljaXBhbnRfaWQsCiAgICBuYW1lc190byA9ICJpdGVtIiwKICAgIHZhbHVlc190byA9ICJyZXNwb25zZSIKICApICU+JQogIGZpbHRlcighaXMubmEocmVzcG9uc2UpKSAlPiUKICBtdXRhdGUoCiAgICBxbiA9IGFzLmludGVnZXIoc3RyX2V4dHJhY3QoaXRlbSwgIlxcZCsiKSksCiAgICBjb25kaXRpb24gPSBjYXNlX3doZW4oCiAgICAgIGdyZXBsKCJfY29uZGl0aW9uKFxcZCkiLCBpdGVtKSB+IHN0cl9leHRyYWN0KGl0ZW0sICIoPzw9X2NvbmRpdGlvbilcXGQiKSwKICAgICAgZ3JlcGwoIl9maW5hbCQiLCBpdGVtKSB+ICI1IgogICAgKSwKICAgIHJlc3BvbnNlX251bSA9IGFzLm51bWVyaWMocmVzcG9uc2UpCiAgKSAlPiUKICBsZWZ0X2pvaW4oc3Vic2NhbGVfbWFwLCBieSA9ICJxbiIpICU+JQogIG11dGF0ZSgKICAgIHJlc3BvbnNlX251bSA9IGlmZWxzZShyZXZlcnNlLCA4IC0gcmVzcG9uc2VfbnVtLCByZXNwb25zZV9udW0pCiAgKQoKCiMgQXZlcmFnZSBzY29yZSBwZXIgcGFydGljaXBhbnQsIGNvbmRpdGlvbiwgc3Vic2NhbGUKc3Vic2NhbGVfc2NvcmVzIDwtIGxvbmdfZGF0YSAlPiUKICBncm91cF9ieShwYXJ0aWNpcGFudF9pZCwgY29uZGl0aW9uLCBzdWJzY2FsZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z19zY29yZSA9IG1lYW4ocmVzcG9uc2VfbnVtLCBuYS5ybSA9IFRSVUUpLCAuZ3JvdXBzID0gImRyb3AiKQoKCiMgUmVtb3ZlIDEuNSpJUVIgb3V0bGllcnMgd2l0aGluIGVhY2ggY29uZGl0aW9uIGFuZCBzdWJzY2FsZQpzdWJzY2FsZV9zY29yZXNfZmlsdGVyZWQgPC0gc3Vic2NhbGVfc2NvcmVzICU+JQogIGdyb3VwX2J5KGNvbmRpdGlvbiwgc3Vic2NhbGUpICU+JQogIG11dGF0ZSgKICAgIFExID0gcXVhbnRpbGUoYXZnX3Njb3JlLCAwLjI1LCBuYS5ybSA9IFRSVUUpLAogICAgUTMgPSBxdWFudGlsZShhdmdfc2NvcmUsIDAuNzUsIG5hLnJtID0gVFJVRSksCiAgICBJUVIgPSBRMyAtIFExLAogICAgbG93ZXIgPSBRMSAtIDEuNSAqIElRUiwKICAgIHVwcGVyID0gUTMgKyAxLjUgKiBJUVIKICApICU+JQogIHVuZ3JvdXAoKSAlPiUKICBmaWx0ZXIoYXZnX3Njb3JlID49IGxvd2VyLCBhdmdfc2NvcmUgPD0gdXBwZXIpICU+JQogIHNlbGVjdChwYXJ0aWNpcGFudF9pZCwgY29uZGl0aW9uLCBzdWJzY2FsZSwgYXZnX3Njb3JlKQoKIyBSZXNoYXBlIGZvciB0ZXN0czogb25lIHJvdyBwZXIgcGFydGljaXBhbnQgcGVyIHN1YnNjYWxlCnRlc3RfZGF0YSA8LSBzdWJzY2FsZV9zY29yZXNfZmlsdGVyZWQgJT4lCiAgcGl2b3Rfd2lkZXIoCiAgICBuYW1lc19mcm9tID0gY29uZGl0aW9uLAogICAgdmFsdWVzX2Zyb20gPSBhdmdfc2NvcmUsCiAgICBuYW1lc19wcmVmaXggPSAiY29uZGl0aW9uIgogICkKCiMgU1RFUCAxOiBPdmVyYWxsIEZyaWVkbWFuIHRlc3RzIHBlciBzdWJzY2FsZQpvdmVyYWxsX3Jlc3VsdHMgPC0gbGlzdCgpCnNpZ25pZmljYW50X3N1YnNjYWxlcyA8LSBjKCkKCmZvciAocyBpbiB1bmlxdWUoc3Vic2NhbGVfc2NvcmVzJHN1YnNjYWxlKSkgewogIHN1Yl9kYXRhIDwtIHRlc3RfZGF0YSAlPiUgZmlsdGVyKHN1YnNjYWxlID09IHMpCiAgc2NvcmVzX21hdCA8LSBzdWJfZGF0YSAlPiUKICAgIHNlbGVjdChzdGFydHNfd2l0aCgiY29uZGl0aW9uIikpICU+JQogICAgbmEub21pdCgpICU+JQogICAgYXMubWF0cml4KCkKCiAgaWYgKG5yb3coc2NvcmVzX21hdCkgPj0gMykgewogICAgZnJpZWRtYW5fcmVzIDwtIGZyaWVkbWFuLnRlc3Qoc2NvcmVzX21hdCkKICAgIG92ZXJhbGxfcmVzdWx0c1tbbGVuZ3RoKG92ZXJhbGxfcmVzdWx0cykgKyAxXV0gPC0gZGF0YS5mcmFtZSgKICAgICAgc3Vic2NhbGUgPSBzLAogICAgICBwX3ZhbHVlID0gZnJpZWRtYW5fcmVzJHAudmFsdWUKICAgICkKICAgIGlmIChmcmllZG1hbl9yZXMkcC52YWx1ZSA8IDAuMDUpIHsKICAgICAgc2lnbmlmaWNhbnRfc3Vic2NhbGVzIDwtIGMoc2lnbmlmaWNhbnRfc3Vic2NhbGVzLCBzKQogICAgfQogIH0KfQoKb3ZlcmFsbF9kZiA8LSBiaW5kX3Jvd3Mob3ZlcmFsbF9yZXN1bHRzKQpvdmVyYWxsX2RmJHBfYWRqX2JoIDwtIHAuYWRqdXN0KG92ZXJhbGxfZGYkcF92YWx1ZSwgbWV0aG9kID0gIkJIIikKCiMgU1RFUCAyOiBQb3N0LWhvYyBwYWlyd2lzZSBXaWxjb3hvbiB0ZXN0cwpwYWlyd2lzZV9yZXN1bHRzIDwtIGxpc3QoKQpjb25kaXRpb25zIDwtIGMoIjEiLCAiMiIsICIzIiwgIjQiLCAiNSIpCnBhaXJfY29tYmluYXRpb25zIDwtIGNvbWJuKGNvbmRpdGlvbnMsIDIsIHNpbXBsaWZ5ID0gRkFMU0UpCgpmb3IgKHMgaW4gc2lnbmlmaWNhbnRfc3Vic2NhbGVzKSB7CiAgc3ViX2RhdGEgPC0gdGVzdF9kYXRhICU+JSBmaWx0ZXIoc3Vic2NhbGUgPT0gcykKICBmb3IgKHBhaXIgaW4gcGFpcl9jb21iaW5hdGlvbnMpIHsKICAgIGMxIDwtIHBhc3RlMCgiY29uZGl0aW9uIiwgcGFpclsxXSkKICAgIGMyIDwtIHBhc3RlMCgiY29uZGl0aW9uIiwgcGFpclsyXSkKICAgIHBhaXJlZF9kYXRhIDwtIHN1Yl9kYXRhICU+JQogICAgICBzZWxlY3QocGFydGljaXBhbnRfaWQsIGFsbF9vZihjKGMxLCBjMikpKSAlPiUKICAgICAgbmEub21pdCgpCgogICAgaWYgKG5yb3cocGFpcmVkX2RhdGEpID49IDMpIHsKICAgICAgdGVzdCA8LSB3aWxjb3gudGVzdChwYWlyZWRfZGF0YVtbYzFdXSwgcGFpcmVkX2RhdGFbW2MyXV0sIHBhaXJlZCA9IFRSVUUpCiAgICAgIHBhaXJ3aXNlX3Jlc3VsdHNbW2xlbmd0aChwYWlyd2lzZV9yZXN1bHRzKSArIDFdXSA8LSBkYXRhLmZyYW1lKAogICAgICAgIHN1YnNjYWxlID0gcywKICAgICAgICBjb21wYXJpc29uID0gcGFzdGUoIkNvbmRpdGlvbiIsIHBhaXJbMV0sICJ2cyIsIHBhaXJbMl0pLAogICAgICAgIHBfdmFsdWUgPSB0ZXN0JHAudmFsdWUKICAgICAgKQogICAgfQogIH0KfQoKcGFpcndpc2VfZGYgPC0gYmluZF9yb3dzKHBhaXJ3aXNlX3Jlc3VsdHMpCnBhaXJ3aXNlX2RmJHBfYWRqX2JoIDwtIHAuYWRqdXN0KHBhaXJ3aXNlX2RmJHBfdmFsdWUsIG1ldGhvZCA9ICJCSCIpCgojIExhYmVsIHN1YnNjYWxlcwpzdWJzY2FsZV9uYW1lcyA8LSBjKAogICIxIiA9ICJJbnRlcmVzdC9FbmpveW1lbnQiLAogICIyIiA9ICJQZXJjZWl2ZWQgQ29tcGV0ZW5jZSIsCiAgIjMiID0gIkVmZm9ydC9JbXBvcnRhbmNlIiwKICAiNCIgPSAiVmFsdWUvVXNlZnVsbmVzcyIKKQoKIyBGaW5hbCBmb3JtYXR0aW5nCm92ZXJhbGxfZGYkc3Vic2NhbGUgPC0gZmFjdG9yKG92ZXJhbGxfZGYkc3Vic2NhbGUsIGxldmVscyA9IG5hbWVzKHN1YnNjYWxlX25hbWVzKSwgbGFiZWxzID0gc3Vic2NhbGVfbmFtZXMpCnBhaXJ3aXNlX2RmJHN1YnNjYWxlIDwtIGZhY3RvcihwYWlyd2lzZV9kZiRzdWJzY2FsZSwgbGV2ZWxzID0gbmFtZXMoc3Vic2NhbGVfbmFtZXMpLCBsYWJlbHMgPSBzdWJzY2FsZV9uYW1lcykKCiMgVmlldyByZXN1bHRzCmNhdCgiPT09IE92ZXJhbGwgRnJpZWRtYW4gVGVzdCBSZXN1bHRzID09PVxuIikKcHJpbnQob3ZlcmFsbF9kZikKCmNhdCgiXG49PT0gUGFpcndpc2UgV2lsY294b24gQ29tcGFyaXNvbnMgKE9ubHkgZm9yIFNpZ25pZmljYW50IFN1YnNjYWxlcykgPT09XG4iKQpwYWlyd2lzZV9kZiA9IHBhaXJ3aXNlX2RmICAlPiUgZmlsdGVyKHBfdmFsdWUgPCAwLjA1KQpwcmludChwYWlyd2lzZV9kZiApCgpgYGAKCiMjIFBlci1sZXNzb24gSU1JCgpgYGB7cn0KbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShsaWtlcnQpCmxpYnJhcnkoZ2dwbG90MikgICMgZm9yIGdndGl0bGUoKQoKIyBMb2FkIGFuZCBjbGVhbiBkYXRhCmltaSA8LSByZWFkX2NzdigiaW1pLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpCmV4Y2x1ZGVkX2lkcyA8LSBjKCI2ODJmNDdhMDMwOTU1NjJiZDU4MWJkMDYiLCAiNjc0ZDdhODlmNTY0ZThiYmUwYTdhZjFjIiwgIjY1NTM3ZTE0NDM5Mjc0ZmU1MDM2YjRkMiIpCmltaV9jbGVhbiA8LSBpbWkgJT4lIGZpbHRlcighcHJvbGlmaWNfaWQgJWluJSBleGNsdWRlZF9pZHMpCgojIFNlbGVjdCBhbGwgbGVzc29uIGNvbHVtbnMgKGxlc3NvbjEgdG8gbGVzc29uNCkKbGVzc29uX2NvbHMgPC0gaW1pX2NsZWFuICU+JSAKICBzZWxlY3QocGFydGljaXBhbnRfaWQsIG1hdGNoZXMoIl5pbWlcXGQrX2xlc3NvblsxLTRdJCIpKQoKIyBDb252ZXJ0IGZyb20gd2lkZSB0byBsb25nIGZvcm1hdCAoYWxsIGxlc3NvbnMpCmxvbmdfZGF0YSA8LSBsZXNzb25fY29scyAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLXBhcnRpY2lwYW50X2lkLAogICAgbmFtZXNfdG8gPSBjKCJxdWVzdGlvbiIsICJsZXNzb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAiaW1pKFxcZCspX2xlc3NvbihcXGQpIiwKICAgIHZhbHVlc190byA9ICJyZXNwb25zZSIKICApICU+JQogIG11dGF0ZSgKICAgIHF1ZXN0aW9uID0gZmFjdG9yKHBhc3RlMCgiUSIsIHF1ZXN0aW9uKSwgbGV2ZWxzID0gcGFzdGUwKCJRIiwgMToyNSksIG9yZGVyZWQgPSBUUlVFKSwKICAgIHJlc3BvbnNlID0gZmFjdG9yKGFzLm51bWVyaWMocmVzcG9uc2UpLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gMTo3LAogICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiRXh0cmVtZWx5IGRpc2FncmVlIiwgIkRpc2FncmVlIiwgIlNsaWdodGx5IGRpc2FncmVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXRyYWwiLCAiU2xpZ2h0bHkgYWdyZWUiLCAiQWdyZWUiLCAiRXh0cmVtZWx5IGFncmVlIiksCiAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkKICApCgpmdWxsX2xldmVscyA8LSBjKCJFeHRyZW1lbHkgZGlzYWdyZWUiLCAiRGlzYWdyZWUiLCAiU2xpZ2h0bHkgZGlzYWdyZWUiLAogICAgICAgICAgICAgICAgICJOZXV0cmFsIiwgIlNsaWdodGx5IGFncmVlIiwgIkFncmVlIiwgIkV4dHJlbWVseSBhZ3JlZSIpCgojIExvb3Agb3ZlciBlYWNoIGxlc3NvbiBhbmQgY3JlYXRlIHNlcGFyYXRlIGxpa2VydCBwbG90cwpmb3IgKGxlc3Nvbl9udW0gaW4gdW5pcXVlKGxvbmdfZGF0YSRsZXNzb24pKSB7CiAgCiAgbGVzc29uX2RhdGEgPC0gbG9uZ19kYXRhICU+JSBmaWx0ZXIobGVzc29uID09IGxlc3Nvbl9udW0pCiAgCiAgbGlrZXJ0X3JlYWR5IDwtIGxlc3Nvbl9kYXRhICU+JQogICAgZ3JvdXBfYnkocGFydGljaXBhbnRfaWQpICU+JQogICAgc2VsZWN0KHBhcnRpY2lwYW50X2lkLCBxdWVzdGlvbiwgcmVzcG9uc2UpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHF1ZXN0aW9uLCB2YWx1ZXNfZnJvbSA9IHJlc3BvbnNlKSAlPiUKICAgIHNlbGVjdChwYXN0ZTAoIlEiLCAxOjI1KSkKICAKICBsaWtlcnRfcmVhZHkgPC0gYXMuZGF0YS5mcmFtZShsaWtlcnRfcmVhZHkpCiAgCiAgIyBFbnN1cmUgYWxsIGNvbHVtbnMgaGF2ZSB0aGUgc2FtZSBvcmRlcmVkIGZhY3RvciBsZXZlbHM6CiAgbGlrZXJ0X3JlYWR5W10gPC0gbGFwcGx5KGxpa2VydF9yZWFkeSwgZnVuY3Rpb24oeCkgewogICAgZmFjdG9yKHgsIGxldmVscyA9IGZ1bGxfbGV2ZWxzLCBvcmRlcmVkID0gVFJVRSkKICB9KQogIAogIGxpa2VydF9vYmogPC0gbGlrZXJ0KGxpa2VydF9yZWFkeSkKICAKICBwcmludChwbG90KGxpa2VydF9vYmosIGdyb3VwLm9yZGVyID0gcGFzdGUwKCJRIiwgMToyNSkpICsgCiAgICAgICAgICBnZ3RpdGxlKHBhc3RlKCJMaWtlcnQgUGxvdCBmb3IgTGVzc29uIiwgbGVzc29uX251bSkpKQp9CgpgYGAKCiMjIFBlci1sZXNzb24gSU1JIC0gQU5PVkEKCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHB1cnJyKQoKIyBMb2FkIGFuZCBjbGVhbiBkYXRhCmltaSA8LSByZWFkX2NzdigiaW1pLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpCmV4Y2x1ZGVkX2lkcyA8LSBjKCI2ODJmNDdhMDMwOTU1NjJiZDU4MWJkMDYiLCAiNjc0ZDdhODlmNTY0ZThiYmUwYTdhZjFjIiwgIjY1NTM3ZTE0NDM5Mjc0ZmU1MDM2YjRkMiIpCmltaV9jbGVhbiA8LSBpbWkgJT4lIGZpbHRlcighcHJvbGlmaWNfaWQgJWluJSBleGNsdWRlZF9pZHMpCgojIFNlbGVjdCByZWxldmFudCBsZXNzb24gY29sdW1ucwpsZXNzb25fY29scyA8LSBpbWlfY2xlYW4gJT4lIAogIHNlbGVjdChwYXJ0aWNpcGFudF9pZCwgbWF0Y2hlcygiXmltaVxcZCtfbGVzc29uWzEtNF0kIikpCgojIENvbnZlcnQgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0CmxvbmdfZGF0YSA8LSBsZXNzb25fY29scyAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLXBhcnRpY2lwYW50X2lkLAogICAgbmFtZXNfdG8gPSBjKCJxdWVzdGlvbiIsICJsZXNzb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAiaW1pKFxcZCspX2xlc3NvbihcXGQpIiwKICAgIHZhbHVlc190byA9ICJyZXNwb25zZSIKICApICU+JQogIG11dGF0ZSgKICAgIHF1ZXN0aW9uID0gZmFjdG9yKHBhc3RlMCgiUSIsIHF1ZXN0aW9uKSwgbGV2ZWxzID0gcGFzdGUwKCJRIiwgMToyNSksIG9yZGVyZWQgPSBUUlVFKSwKICAgIGxlc3NvbiA9IGZhY3RvcihsZXNzb24sIGxldmVscyA9IDE6NCksCiAgICByZXNwb25zZV9udW0gPSBhcy5udW1lcmljKHJlc3BvbnNlKQogICkKCiMgU2hhcGlyby1XaWxrIHRlc3QgZm9yIG5vcm1hbGl0eSBwZXIgcXVlc3Rpb24gKGNvbWJpbmluZyBsZXNzb25zKQpub3JtYWxpdHlfcmVzdWx0cyA8LSBsb25nX2RhdGEgJT4lCiAgZ3JvdXBfYnkocXVlc3Rpb24pICU+JQogIHN1bW1hcmlzZSgKICAgIHNoYXBpcm9fcCA9IGlmKG4oKSA+PSAzKSBzaGFwaXJvLnRlc3QocmVzcG9uc2VfbnVtKSRwLnZhbHVlIGVsc2UgTkFfcmVhbF8KICApCgpwcmludChub3JtYWxpdHlfcmVzdWx0cykKCiMgUHJlcGFyZSBkYXRhIHdpZGU6IGVhY2ggcm93ID0gcGFydGljaXBhbnQgJiBxdWVzdGlvbiwgY29sdW1ucyA9IGxlc3NvbnMKZnJpZWRtYW5fZGF0YSA8LSBsb25nX2RhdGEgJT4lCiAgc2VsZWN0KHBhcnRpY2lwYW50X2lkLCBxdWVzdGlvbiwgbGVzc29uLCByZXNwb25zZV9udW0pICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBsZXNzb24sIHZhbHVlc19mcm9tID0gcmVzcG9uc2VfbnVtKSAlPiUKICBmaWx0ZXIoY29tcGxldGUuY2FzZXMoLikpICAjIG9ubHkga2VlcCBwYXJ0aWNpcGFudHMgd2l0aCBhbGwgbGVzc29ucwoKIyBSdW4gRnJpZWRtYW4gdGVzdCBwZXIgcXVlc3Rpb24KZnJpZWRtYW5fcmVzdWx0cyA8LSBmcmllZG1hbl9kYXRhICU+JQogIGdyb3VwX2J5KHF1ZXN0aW9uKSAlPiUKICBzdW1tYXJpc2UoCiAgICBwX3ZhbHVlID0gewogICAgICBtYXQgPC0gYXMubWF0cml4KHNlbGVjdChjdXJfZGF0YSgpLCBgMWAsIGAyYCwgYDNgLCBgNGApKQogICAgICBmcmllZG1hbi50ZXN0KG1hdCkkcC52YWx1ZQogICAgfQogICkKCnByaW50KGZyaWVkbWFuX3Jlc3VsdHMpCgojIFN0ZXAgMjogUG9zdC1ob2MgcGFpcndpc2UgV2lsY294b24gc2lnbmVkLXJhbmsgdGVzdHMgZm9yIHRob3NlIHF1ZXN0aW9ucwoKIyBGdW5jdGlvbiB0byBkbyBwYWlyd2lzZSBXaWxjb3hvbiBmb3IgYSBxdWVzdGlvbgpwb3N0aG9jX3dpbGNveCA8LSBmdW5jdGlvbihkZikgewogICMgZGY6IGZpbHRlcmVkIGZvciBvbmUgcXVlc3Rpb24sIHdpZGUgZm9ybWF0IHdpdGggbGVzc29ucyBjb2x1bW5zCiAgbGVzc29ucyA8LSBjKCIxIiwiMiIsIjMiLCI0IikKICBwYWlycyA8LSBjb21ibihsZXNzb25zLCAyLCBzaW1wbGlmeSA9IEZBTFNFKQogIAogIHJlc3VsdHMgPC0gbWFwX2RmcihwYWlycywgZnVuY3Rpb24ocGFpcikgewogICAgcmVzIDwtIHdpbGNveC50ZXN0KGRmW1twYWlyWzFdXV0sIGRmW1twYWlyWzJdXV0sIHBhaXJlZCA9IFRSVUUsIGV4YWN0ID0gRkFMU0UpCiAgICBtZWFuX2RpZmYgPC0gbWVhbihkZltbcGFpclsxXV1dIC0gZGZbW3BhaXJbMl1dXSkKICAgIHRpYmJsZSgKICAgICAgbGVzc29uXzEgPSBwYWlyWzFdLAogICAgICBsZXNzb25fMiA9IHBhaXJbMl0sCiAgICAgIHBfdmFsdWUgPSByZXMkcC52YWx1ZSwKICAgICAgbWVhbl9kaWZmZXJlbmNlID0gbWVhbl9kaWZmCiAgICApCiAgfSkKICAKICAjIEFkanVzdCBwLXZhbHVlcyBmb3IgbXVsdGlwbGUgY29tcGFyaXNvbnMgKEJvbmZlcnJvbmkpCiAgcmVzdWx0cyA8LSByZXN1bHRzICU+JQogICAgbXV0YXRlKHBfYWRqID0gcC5hZGp1c3QocF92YWx1ZSwgbWV0aG9kID0gImJvbmZlcnJvbmkiKSkKICAKICByZXR1cm4ocmVzdWx0cykKfQoKIyBSdW4gcG9zdGhvYyB0ZXN0cyBmb3IgZWFjaCBzaWduaWZpY2FudCBxdWVzdGlvbgpwb3N0aG9jX3Jlc3VsdHMgPC0gZnJpZWRtYW5fcmVzdWx0cyAlPiUKICBwdWxsKHF1ZXN0aW9uKSAlPiUKICBzZXRfbmFtZXMoKSAlPiUKICBtYXBfZGYoZnVuY3Rpb24ocSkgewogICAgZGZfcSA8LSBmcmllZG1hbl9kYXRhICU+JSBmaWx0ZXIocXVlc3Rpb24gPT0gcSkKICAgIHJlcyA8LSBwb3N0aG9jX3dpbGNveChkZl9xKQogICAgcmVzJHF1ZXN0aW9uIDwtIHEKICAgIHJlcwogIH0sIC5pZCA9ICJxdWVzdGlvbiIpCgojIEZpbHRlciBvbmx5IHBhaXJzIHdpdGggc2lnbmlmaWNhbnQgYWRqdXN0ZWQgcC12YWx1ZXMgPCAwLjA1CnNpZ25pZmljYW50X3BhaXJzIDwtIHBvc3Rob2NfcmVzdWx0cyAlPiUKICBmaWx0ZXIocF9hZGogPCAwLjA1KSAlPiUKICBzZWxlY3QocXVlc3Rpb24sIGxlc3Nvbl8xLCBsZXNzb25fMiwgbWVhbl9kaWZmZXJlbmNlLCBwX3ZhbHVlLCBwX2FkaikKCnByaW50KHNpZ25pZmljYW50X3BhaXJzKQoKCgpgYGAKCiMjIFBlci1jb25kaXRpb24gSU1JCgpgYGB7cn0KbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShsaWtlcnQpCmxpYnJhcnkoZ2dwbG90MikgICMgZm9yIGdndGl0bGUoKQoKIyBMb2FkIGFuZCBjbGVhbiBkYXRhCmltaSA8LSByZWFkX2NzdigiaW1pLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpCmV4Y2x1ZGVkX2lkcyA8LSBjKCI2ODJmNDdhMDMwOTU1NjJiZDU4MWJkMDYiLCAiNjc0ZDdhODlmNTY0ZThiYmUwYTdhZjFjIiwgIjY1NTM3ZTE0NDM5Mjc0ZmU1MDM2YjRkMiIpCmltaV9jbGVhbiA8LSBpbWkgJT4lIGZpbHRlcighcHJvbGlmaWNfaWQgJWluJSBleGNsdWRlZF9pZHMpCgojIFNlbGVjdCBhbGwgY29uZGl0aW9uIGNvbHVtbnMgKGNvbmRpdGlvbjEgdG8gY29uZGl0aW9uNCkKY29uZGl0aW9uX2NvbHMgPC0gaW1pX2NsZWFuICU+JSAKICBzZWxlY3QocGFydGljaXBhbnRfaWQsIG1hdGNoZXMoIl5pbWlcXGQrX2NvbmRpdGlvblsxLTRdJCIpKQoKIyBDb252ZXJ0IGZyb20gd2lkZSB0byBsb25nIGZvcm1hdCAoYWxsIGNvbmRpdGlvbnMpCmxvbmdfZGF0YSA8LSBjb25kaXRpb25fY29scyAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLXBhcnRpY2lwYW50X2lkLAogICAgbmFtZXNfdG8gPSBjKCJxdWVzdGlvbiIsICJjb25kaXRpb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAiaW1pKFxcZCspX2NvbmRpdGlvbihcXGQpIiwKICAgIHZhbHVlc190byA9ICJyZXNwb25zZSIKICApICU+JQogIG11dGF0ZSgKICAgIHF1ZXN0aW9uID0gZmFjdG9yKHBhc3RlMCgiUSIsIHF1ZXN0aW9uKSwgbGV2ZWxzID0gcGFzdGUwKCJRIiwgMToyNSksIG9yZGVyZWQgPSBUUlVFKSwKICAgIHJlc3BvbnNlID0gZmFjdG9yKGFzLm51bWVyaWMocmVzcG9uc2UpLAogICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gMTo3LAogICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiRXh0cmVtZWx5IGRpc2FncmVlIiwgIkRpc2FncmVlIiwgIlNsaWdodGx5IGRpc2FncmVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldXRyYWwiLCAiU2xpZ2h0bHkgYWdyZWUiLCAiQWdyZWUiLCAiRXh0cmVtZWx5IGFncmVlIiksCiAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSkKICApCgpmdWxsX2xldmVscyA8LSBjKCJFeHRyZW1lbHkgZGlzYWdyZWUiLCAiRGlzYWdyZWUiLCAiU2xpZ2h0bHkgZGlzYWdyZWUiLAogICAgICAgICAgICAgICAgICJOZXV0cmFsIiwgIlNsaWdodGx5IGFncmVlIiwgIkFncmVlIiwgIkV4dHJlbWVseSBhZ3JlZSIpCgojIExvb3Agb3ZlciBlYWNoIGNvbmRpdGlvbiBhbmQgY3JlYXRlIHNlcGFyYXRlIGxpa2VydCBwbG90cwpmb3IgKGNvbmRpdGlvbl9udW0gaW4gdW5pcXVlKGxvbmdfZGF0YSRjb25kaXRpb24pKSB7CiAgCiAgY29uZGl0aW9uX2RhdGEgPC0gbG9uZ19kYXRhICU+JSBmaWx0ZXIoY29uZGl0aW9uID09IGNvbmRpdGlvbl9udW0pCiAgCiAgbGlrZXJ0X3JlYWR5IDwtIGNvbmRpdGlvbl9kYXRhICU+JQogICAgZ3JvdXBfYnkocGFydGljaXBhbnRfaWQpICU+JQogICAgc2VsZWN0KHBhcnRpY2lwYW50X2lkLCBxdWVzdGlvbiwgcmVzcG9uc2UpICU+JQogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHF1ZXN0aW9uLCB2YWx1ZXNfZnJvbSA9IHJlc3BvbnNlKSAlPiUKICAgIHNlbGVjdChwYXN0ZTAoIlEiLCAxOjI1KSkKICAKICBsaWtlcnRfcmVhZHkgPC0gYXMuZGF0YS5mcmFtZShsaWtlcnRfcmVhZHkpCiAgCiAgIyBFbnN1cmUgYWxsIGNvbHVtbnMgaGF2ZSB0aGUgc2FtZSBvcmRlcmVkIGZhY3RvciBsZXZlbHM6CiAgbGlrZXJ0X3JlYWR5W10gPC0gbGFwcGx5KGxpa2VydF9yZWFkeSwgZnVuY3Rpb24oeCkgewogICAgZmFjdG9yKHgsIGxldmVscyA9IGZ1bGxfbGV2ZWxzLCBvcmRlcmVkID0gVFJVRSkKICB9KQogIAogIGxpa2VydF9vYmogPC0gbGlrZXJ0KGxpa2VydF9yZWFkeSkKICAKICBwcmludChwbG90KGxpa2VydF9vYmosIGdyb3VwLm9yZGVyID0gcGFzdGUwKCJRIiwgMToyNSkpICsgCiAgICAgICAgICBnZ3RpdGxlKHBhc3RlKCJMaWtlcnQgUGxvdCBmb3IgQ29uZGl0aW9uIiwgY29uZGl0aW9uX251bSkpKQp9CgpgYGAKCiMjIFBlci1jb25kaXRpb24gSU1JIC0gQU5PVkEKCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQoKIyBMb2FkIGFuZCBjbGVhbiBkYXRhCmltaSA8LSByZWFkX2NzdigiaW1pLmNzdiIsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpCmV4Y2x1ZGVkX2lkcyA8LSBjKCI2ODJmNDdhMDMwOTU1NjJiZDU4MWJkMDYiLCAiNjc0ZDdhODlmNTY0ZThiYmUwYTdhZjFjIiwgIjY1NTM3ZTE0NDM5Mjc0ZmU1MDM2YjRkMiIpCmltaV9jbGVhbiA8LSBpbWkgJT4lIGZpbHRlcighcHJvbGlmaWNfaWQgJWluJSBleGNsdWRlZF9pZHMpCgojIFNlbGVjdCByZWxldmFudCBjb25kaXRpb24gY29sdW1ucwpsZXNzb25fY29scyA8LSBpbWlfY2xlYW4gJT4lIAogIHNlbGVjdChwYXJ0aWNpcGFudF9pZCwgbWF0Y2hlcygiXmltaVxcZCtfY29uZGl0aW9uWzEtNF0kIikpCgojIENvbnZlcnQgZnJvbSB3aWRlIHRvIGxvbmcgZm9ybWF0CmxvbmdfZGF0YSA8LSBsZXNzb25fY29scyAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLXBhcnRpY2lwYW50X2lkLAogICAgbmFtZXNfdG8gPSBjKCJxdWVzdGlvbiIsICJjb25kaXRpb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAiaW1pKFxcZCspX2NvbmRpdGlvbihcXGQpIiwKICAgIHZhbHVlc190byA9ICJyZXNwb25zZSIKICApICU+JQogIG11dGF0ZSgKICAgIHF1ZXN0aW9uID0gZmFjdG9yKHBhc3RlMCgiUSIsIHF1ZXN0aW9uKSwgbGV2ZWxzID0gcGFzdGUwKCJRIiwgMToyNSksIG9yZGVyZWQgPSBUUlVFKSwKICAgIGxlc3NvbiA9IGZhY3Rvcihjb25kaXRpb24sIGxldmVscyA9IDE6NCksCiAgICByZXNwb25zZV9udW0gPSBhcy5udW1lcmljKHJlc3BvbnNlKQogICkKCiMgU2hhcGlyby1XaWxrIHRlc3QgZm9yIG5vcm1hbGl0eSBwZXIgcXVlc3Rpb24gKGNvbWJpbmluZyBsZXNzb25zKQpub3JtYWxpdHlfcmVzdWx0cyA8LSBsb25nX2RhdGEgJT4lCiAgZ3JvdXBfYnkocXVlc3Rpb24pICU+JQogIHN1bW1hcmlzZSgKICAgIHNoYXBpcm9fcCA9IGlmKG4oKSA+PSAzKSBzaGFwaXJvLnRlc3QocmVzcG9uc2VfbnVtKSRwLnZhbHVlIGVsc2UgTkFfcmVhbF8KICApCgpwcmludChub3JtYWxpdHlfcmVzdWx0cykKCiMgUHJlcGFyZSBkYXRhIHdpZGU6IGVhY2ggcm93ID0gcGFydGljaXBhbnQgJiBxdWVzdGlvbiwgY29sdW1ucyA9IGxlc3NvbnMKZnJpZWRtYW5fZGF0YSA8LSBsb25nX2RhdGEgJT4lCiAgc2VsZWN0KHBhcnRpY2lwYW50X2lkLCBxdWVzdGlvbiwgY29uZGl0aW9uLCByZXNwb25zZV9udW0pICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBjb25kaXRpb24sIHZhbHVlc19mcm9tID0gcmVzcG9uc2VfbnVtKSAlPiUKICBmaWx0ZXIoY29tcGxldGUuY2FzZXMoLikpICAjIG9ubHkga2VlcCBwYXJ0aWNpcGFudHMgd2l0aCBhbGwgbGVzc29ucwoKIyBSdW4gRnJpZWRtYW4gdGVzdCBwZXIgcXVlc3Rpb24KZnJpZWRtYW5fcmVzdWx0cyA8LSBmcmllZG1hbl9kYXRhICU+JQogIGdyb3VwX2J5KHF1ZXN0aW9uKSAlPiUKICBzdW1tYXJpc2UoCiAgICBwX3ZhbHVlID0gewogICAgICBtYXQgPC0gYXMubWF0cml4KHNlbGVjdChjdXJfZGF0YSgpLCBgMWAsIGAyYCwgYDNgLCBgNGApKQogICAgICBmcmllZG1hbi50ZXN0KG1hdCkkcC52YWx1ZQogICAgfQogICkKCnByaW50KGZyaWVkbWFuX3Jlc3VsdHMpCgoKIyBTdGVwIDI6IFBvc3QtaG9jIHBhaXJ3aXNlIFdpbGNveG9uIHNpZ25lZC1yYW5rIHRlc3RzIGZvciB0aG9zZSBxdWVzdGlvbnMKCiMgRnVuY3Rpb24gdG8gZG8gcGFpcndpc2UgV2lsY294b24gZm9yIGEgcXVlc3Rpb24KcG9zdGhvY193aWxjb3ggPC0gZnVuY3Rpb24oZGYpIHsKICAjIGRmOiBmaWx0ZXJlZCBmb3Igb25lIHF1ZXN0aW9uLCB3aWRlIGZvcm1hdCB3aXRoIGxlc3NvbnMgY29sdW1ucwogIGNvbmRpdGlvbnMgPC0gYygiMSIsIjIiLCIzIiwiNCIpCiAgcGFpcnMgPC0gY29tYm4oY29uZGl0aW9ucywgMiwgc2ltcGxpZnkgPSBGQUxTRSkKICAKICByZXN1bHRzIDwtIG1hcF9kZnIocGFpcnMsIGZ1bmN0aW9uKHBhaXIpIHsKICAgIHJlcyA8LSB3aWxjb3gudGVzdChkZltbcGFpclsxXV1dLCBkZltbcGFpclsyXV1dLCBwYWlyZWQgPSBUUlVFLCBleGFjdCA9IEZBTFNFKQogICAgbWVhbl9kaWZmIDwtIG1lYW4oZGZbW3BhaXJbMV1dXSAtIGRmW1twYWlyWzJdXV0pCiAgICB0aWJibGUoCiAgICAgIGNvbmRpdGlvbl8xID0gcGFpclsxXSwKICAgICAgY29uZGl0aW9uXzIgPSBwYWlyWzJdLAogICAgICBwX3ZhbHVlID0gcmVzJHAudmFsdWUsCiAgICAgIG1lYW5fZGlmZmVyZW5jZSA9IG1lYW5fZGlmZgogICAgKQogIH0pCiAgCiAgIyBBZGp1c3QgcC12YWx1ZXMgZm9yIG11bHRpcGxlIGNvbXBhcmlzb25zIChiaCkKICByZXN1bHRzIDwtIHJlc3VsdHMgJT4lCiAgICBtdXRhdGUocF9hZGpfYmggPSBwLmFkanVzdChwX3ZhbHVlLCBtZXRob2QgPSAiQkgiKSkKICAKICAgcmVzdWx0cyA8LSByZXN1bHRzICU+JQogICAgbXV0YXRlKHBfYWRqX2JvbmZlcnJvbmkgPSBwLmFkanVzdChwX3ZhbHVlLCBtZXRob2QgPSAiYm9uZmVycm9uaSIpKQogIAogIHJldHVybihyZXN1bHRzKQp9CgojIFJ1biBwb3N0aG9jIHRlc3RzIGZvciBlYWNoIHNpZ25pZmljYW50IHF1ZXN0aW9uCnBvc3Rob2NfcmVzdWx0cyA8LSBmcmllZG1hbl9yZXN1bHRzICU+JQogIHB1bGwocXVlc3Rpb24pICU+JQogIHNldF9uYW1lcygpICU+JQogIG1hcF9kZihmdW5jdGlvbihxKSB7CiAgICBkZl9xIDwtIGZyaWVkbWFuX2RhdGEgJT4lIGZpbHRlcihxdWVzdGlvbiA9PSBxKQogICAgcmVzIDwtIHBvc3Rob2Nfd2lsY294KGRmX3EpCiAgICByZXMkcXVlc3Rpb24gPC0gcQogICAgcmVzCiAgfSwgLmlkID0gInF1ZXN0aW9uIikKCiMgRmlsdGVyIG9ubHkgcGFpcnMgd2l0aCBzaWduaWZpY2FudCBhZGp1c3RlZCBwLXZhbHVlcyA8IDAuMDUKc2lnbmlmaWNhbnRfcGFpcnMgPC0gcG9zdGhvY19yZXN1bHRzICU+JQogIGZpbHRlcihwX3ZhbHVlIDwgMC4xKSAlPiUKICBmaWx0ZXIoY29uZGl0aW9uXzIgPT0gNCkgJT4lCiAgc2VsZWN0KHF1ZXN0aW9uLCBjb25kaXRpb25fMSwgY29uZGl0aW9uXzIsIG1lYW5fZGlmZmVyZW5jZSwgcF92YWx1ZSwgcF9hZGpfYmgsIHBfYWRqX2JvbmZlcnJvbmkpCgpwcmludChzaWduaWZpY2FudF9wYWlycykKCmBgYAoKIyBMSVdDCgojIyBDb3JyZWxhdGlvbnMgb24gVXNlcnMgKG1pZCB0byBwb3N0KQoKYGBge3J9CgpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGNvcnJyKQoKCnByaW50KGRhdGEpCgojIFN0ZXAgMTogUmVzaGFwZSBhbmQgY29tcHV0ZSBkaWZmZXJlbmNlcwphbGxfY2VydGFpbnR5X2RlbHRhcyA8LSBkYXRhICU+JQogIHNlbGVjdCh1c2VyX2lkLCBtYXRjaGVzKCJsaWtlcnRfKG1pZHxwb3N0KV9jb25kaXRpb25cXGQrIikpICU+JSAgIyBrZWVwIHVzZXJfaWQKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLXVzZXJfaWQsCiAgICBuYW1lc190byA9IGMoInBoYXNlIiwgImNvbmRpdGlvbiIpLAogICAgbmFtZXNfcGF0dGVybiA9ICJsaWtlcnRfKG1pZHxwb3N0KV9jb25kaXRpb24oXFxkKykiLAogICAgdmFsdWVzX3RvID0gInNjb3JlIgogICkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHBoYXNlLCB2YWx1ZXNfZnJvbSA9IHNjb3JlKSAlPiUKICBtdXRhdGUoCiAgICBkaWZmID0gcG9zdCAtIG1pZCwKICAgIGNvbmRpdGlvbiA9IGNhc2Vfd2hlbigKICAgICAgY29uZGl0aW9uID09ICIxIiB+ICJDb250cm9sIiwKICAgICAgY29uZGl0aW9uID09ICIyIiB+ICJSZWFkaW5nIiwKICAgICAgY29uZGl0aW9uID09ICIzIiB+ICJXcml0aW5nIiwKICAgICAgY29uZGl0aW9uID09ICI0IiB+ICJDaGF0Ym90IiwKICAgICAgVFJVRSB+IGNvbmRpdGlvbgogICAgKQogICkgJT4lCiAgc2VsZWN0KHVzZXJfaWQsIGNvbmRpdGlvbiwgZGlmZikgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGNvbmRpdGlvbiwgdmFsdWVzX2Zyb20gPSBkaWZmKQoKCiMgMS4gTG9hZCB0aGUgTElXQyBhbmQgZGVsdGEgZGF0YQpsaXdjX2RhdGEgPC0gcmVhZHI6OnJlYWRfZGVsaW0oIkxJV0MtMjIgUmVzdWx0cyAtIHBhcnRpY2lwYW50X3RleHRzIC0gTElXQyBBbmFseXNpcy5jc3YiLCBkZWxpbSA9ICI7IikKCiMgMi4gRHJvcCB1bndhbnRlZCB1c2VyX2lkcyAoYXNzdW1pbmcgU2VnbWVudCBjb250YWlucyB1c2VyIElEIG9yIGEgbmFtZSBsaWtlICJ1c2VyXzEwIikKZXhjbHVkZWRfaWRzIDwtIGMoMTAsIDI2LCAyOSwgNDgsIDQ5LCA1MikKbGl3Y19maWx0ZXJlZCA8LSBsaXdjX2RhdGEgJT4lCiAgbXV0YXRlKHVzZXJfaWQgPSBhcy5udW1lcmljKGdzdWIoIlxcRCsiLCAiIiwgU2VnbWVudCkpKSAlPiUgICMgRXh0cmFjdCBudW1lcmljIElEIGZyb20gInVzZXJfWFgiCiAgZmlsdGVyKCF1c2VyX2lkICVpbiUgZXhjbHVkZWRfaWRzKQoKIyAzLiBQcmVwYXJlIGFsbF9jZXJ0YWludHlfZGVsdGFzIChlbnN1cmUgcGFydGljaXBhbnRfaWQgZm9ybWF0IG1hdGNoZXMpCmFsbF9jZXJ0YWludHlfZGVsdGFzIDwtIGFsbF9jZXJ0YWludHlfZGVsdGFzICU+JQogIG11dGF0ZSh1c2VyX2lkID0gYXMubnVtZXJpYyh1c2VyX2lkKSkgJT4lCiAgZmlsdGVyKCF1c2VyX2lkICVpbiUgZXhjbHVkZWRfaWRzKQoKbGl3Y19maWx0ZXJlZCA8LSBsaXdjX2RhdGEgJT4lCiAgbXV0YXRlKHVzZXJfaWQgPSBhcy5udW1lcmljKGdzdWIoInVzZXJfKFxcZCspXFwudHh0IiwgIlxcMSIsIEZpbGVuYW1lKSkpICU+JQogIGZpbHRlcighdXNlcl9pZCAlaW4lIGV4Y2x1ZGVkX2lkcykKCgojIDQuIEpvaW4gTElXQyBhbmQgZGVsdGEgZGF0YQptZXJnZWRfZGF0YSA8LSBpbm5lcl9qb2luKGxpd2NfZmlsdGVyZWQsIGFsbF9jZXJ0YWludHlfZGVsdGFzLCBieSA9ICJ1c2VyX2lkIikKCnByaW50KG1lcmdlZF9kYXRhKQoKIyA1LiBSdW4gY29ycmVsYXRpb24gYmV0d2VlbiBhbGwgTElXQyBmZWF0dXJlcyBhbmQgQ2hhdGJvdCBkZWx0YXMKIyBFeGNsdWRlIG5vbi1udW1lcmljIG9yIGlkZW50aWZpZXIgY29sdW1ucyBmaXJzdApsaXdjX2NvbHVtbnMgPC0gbGl3Y19maWx0ZXJlZCAlPiUKICBzZWxlY3QoLVNlZ21lbnQsIC11c2VyX2lkKSAlPiUKICBzZWxlY3Qod2hlcmUoaXMubnVtZXJpYykpICU+JSBuYW1lcygpCgpjb3JfaW5wdXQgPC0gbWVyZ2VkX2RhdGEgJT4lCiAgc2VsZWN0KGFsbF9vZihsaXdjX2NvbHVtbnMpLCBDaGF0Ym90KQoKY29yX3Jlc3VsdHMgPC0gY29ycmVsYXRlKGNvcl9pbnB1dCkgJT4lCiAgZm9jdXMoQ2hhdGJvdCkgJT4lCiAgYXJyYW5nZShkZXNjKGFicyhDaGF0Ym90KSkpICAjIFNvcnQgYnkgc3RyZW5ndGggb2YgY29ycmVsYXRpb24KCiMgNi4gVmlldyByZXN1bHRzCnByaW50KGNvcl9yZXN1bHRzKQoKIyBPcHRpb25hbDogRmlsdGVyIGZvciBtZWFuaW5nZnVsIGNvcnJlbGF0aW9uIChlLmcuID4gMC4zIG9yIDwgLTAuMykKc3Ryb25nX2NvcnJzIDwtIGNvcl9yZXN1bHRzICU+JQogIGZpbHRlcihhYnMoQ2hhdGJvdCkgPiAwLjMpCnByaW50KHN0cm9uZ19jb3JycykKCiMgU2VsZWN0IG51bWVyaWMgY29sdW1ucyBhbmQgQ2hhdGJvdCBkZWx0YQpudW1lcmljX3ZhcnMgPC0gbWVyZ2VkX2RhdGEgJT4lCiAgc2VsZWN0KGFsbF9vZihsaXdjX2NvbHVtbnMpKQoKY2hhdGJvdF9zY29yZXMgPC0gbWVyZ2VkX2RhdGEkQ2hhdGJvdAoKIyBJbml0aWFsaXplIGEgcmVzdWx0cyBkYXRhIGZyYW1lCnJlc3VsdHMgPC0gZGF0YS5mcmFtZSh0ZXJtID0gY2hhcmFjdGVyKCksIAogICAgICAgICAgICAgICAgICAgICAgY29yID0gbnVtZXJpYygpLCAKICAgICAgICAgICAgICAgICAgICAgIHBfdmFsdWUgPSBudW1lcmljKCksIAogICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBMb29wIG92ZXIgZWFjaCBMSVdDIHZhcmlhYmxlIGFuZCBydW4gY29yLnRlc3Qgd2l0aCBDaGF0Ym90CmZvciAodmFyIGluIGNvbG5hbWVzKG51bWVyaWNfdmFycykpIHsKICB0ZXN0IDwtIGNvci50ZXN0KG51bWVyaWNfdmFyc1tbdmFyXV0sIGNoYXRib3Rfc2NvcmVzLCB1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIikKICAKICByZXN1bHRzIDwtIHJiaW5kKHJlc3VsdHMsIGRhdGEuZnJhbWUoCiAgICB0ZXJtID0gdmFyLAogICAgY29yID0gdGVzdCRlc3RpbWF0ZSwKICAgIHBfdmFsdWUgPSB0ZXN0JHAudmFsdWUKICApKQp9CgojIFNvcnQgYnkgYWJzb2x1dGUgY29ycmVsYXRpb24KcmVzdWx0cyA8LSByZXN1bHRzICU+JSBhcnJhbmdlKGRlc2MoYWJzKGNvcikpKQoKcmVzdWx0cyA8LSByZXN1bHRzICU+JQogIG11dGF0ZShwX2FkaiA9IHAuYWRqdXN0KHBfdmFsdWUsIG1ldGhvZCA9ICJCSCIpKSAgIyBGRFIgY29ycmVjdGlvbgoKIyBWaWV3IHNpZ25pZmljYW50IGFmdGVyIGNvcnJlY3Rpb24Kc2lnX3Jlc3VsdHMgPC0gcmVzdWx0cyAlPiUKICBmaWx0ZXIocF92YWx1ZSA8IDAuMDUpCgpwcmludChzaWdfcmVzdWx0cykKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQoKIyBTZWxlY3QgTElXQyBjb2x1bW5zICsgQ2hhdGJvdCBkZWx0YSBhbmQgdXNlcl9pZApwbG90X2RhdGEgPC0gbWVyZ2VkX2RhdGEgJT4lCiAgc2VsZWN0KHVzZXJfaWQsIENoYXRib3QsIGFsbF9vZihsaXdjX2NvbHVtbnMpKQoKIyBDb252ZXJ0IExJV0MgdGVybXMgdG8gbG9uZyBmb3JtYXQKbG9uZ19kYXRhIDwtIHBsb3RfZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLWModXNlcl9pZCwgQ2hhdGJvdCksCiAgICBuYW1lc190byA9ICJMSVdDX3Rlcm0iLAogICAgdmFsdWVzX3RvID0gIkxJV0NfdmFsdWUiCiAgKQoKIyBBc3N1bWluZyAncmVzdWx0cycgYWxyZWFkeSBjb250YWlucyB0aGUgY29ycmVsYXRpb24gZGF0YSBmb3IgTElXQyB0ZXJtcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCgojIENhbGN1bGF0ZSBwcm9wb3J0aW9uIG9mIG5vbi16ZXJvIHZhbHVlcyBmb3IgZWFjaCBMSVdDIHRlcm0Kbm9uX3plcm9fcHJvcG9ydGlvbiA8LSBsb25nX2RhdGEgJT4lCiAgZ3JvdXBfYnkoTElXQ190ZXJtKSAlPiUKICBzdW1tYXJpemUobm9uX3plcm9fcmF0aW8gPSBzdW0oTElXQ192YWx1ZSAhPSAwKSAvIG4oKSwgLmdyb3VwcyA9ICdkcm9wJykKCiMgTWVyZ2Ugd2l0aCB0aGUgY29ycmVsYXRpb24gcmVzdWx0cwpyZXN1bHRzX3dpdGhfcHJvcG9ydGlvbiA8LSByZXN1bHRzICU+JQogIGlubmVyX2pvaW4obm9uX3plcm9fcHJvcG9ydGlvbiwgYnkgPSBjKCJ0ZXJtIiA9ICJMSVdDX3Rlcm0iKSkKCiMgU2V0IHRocmVzaG9sZHMKY29yX3RocmVzaG9sZCA8LSAwLjMgCm56X3RocmVzaG9sZCA8LSAwLjMgCgojIEZpbHRlciBmb3Igc3Ryb25nIGNvcnJlbGF0aW9ucyBhbmQgbm9uLXplcm8gaW5mbGF0ZWQgdGVybXMKCiMgRmlsdGVyIHNwZWNpZmljYWxseSBmb3IgIkhlYWx0aCIgdGVybQpmaWx0ZXJlZF90ZXJtcyA8LSByZXN1bHRzX3dpdGhfcHJvcG9ydGlvbiAlPiUKICBmaWx0ZXIodGVybSA9PSAiaGVhbHRoIikgJT4lCiAgcHVsbCh0ZXJtKQoKIyBGaWx0ZXIgbG9uZ19kYXRhIGZvciB0aGVzZSB0ZXJtcwp0b3Bfbm9uX3plcm9fbG9uZ19kYXRhIDwtIGxvbmdfZGF0YSAlPiUKICBmaWx0ZXIoTElXQ190ZXJtICVpbiUgZmlsdGVyZWRfdGVybXMpCgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCgojIEFkZCBjdXN0b20gbmFtZXMgbWFwcGluZwpjdXN0b21fbmFtZXMgPC0gYygKICAiaGVhbHRoIiA9ICJIZWFsdGgiCikKCiMgRmlsdGVyIGFuZCBwcmVwYXJlIGFubm90YXRpb25zCmFubm90YXRpb25zIDwtIHJlc3VsdHNfd2l0aF9wcm9wb3J0aW9uICU+JQogIGZpbHRlcih0ZXJtICVpbiUgZmlsdGVyZWRfdGVybXMpICU+JQogIG11dGF0ZSgKICAgIGxhYmVsID0gcGFzdGUwKCJyID0gIiwgcm91bmQoY29yLCAyKSwgIiwgcCA9ICIsIGZvcm1hdChwX2FkaiwgZGlnaXRzID0gMikpLAogICAgTElXQ190ZXJtID0gdGVybQogICkgJT4lCiAgc2VsZWN0KExJV0NfdGVybSwgbGFiZWwpCgojIEFkZCBhbm5vdGF0aW9ucyB0byB0aGUgbG9uZyBkYXRhIGZvciBwbG90dGluZwp0b3Bfbm9uX3plcm9fbG9uZ19kYXRhIDwtIHRvcF9ub25femVyb19sb25nX2RhdGEgJT4lCiAgbGVmdF9qb2luKGFubm90YXRpb25zLCBieSA9ICJMSVdDX3Rlcm0iKQoKIyBQbG90IHdpdGggY3VzdG9tIGZhY2V0IGxhYmVscwpnZ3Bsb3QodG9wX25vbl96ZXJvX2xvbmdfZGF0YSwgYWVzKHggPSBMSVdDX3ZhbHVlLCB5ID0gQ2hhdGJvdCkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC42KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAic3RlZWxibHVlIikgKwogIGZhY2V0X3dyYXAofiBMSVdDX3Rlcm0sIHNjYWxlcyA9ICJmcmVlX3giLCBsYWJlbGxlciA9IGxhYmVsbGVyKExJV0NfdGVybSA9IGN1c3RvbV9uYW1lcykpICsKICBsYWJzKAogICAgdGl0bGUgPSAiQ29ycmVsYXRpb24gb2YgTElXQyAnSGVhbHRoJyBUZXJtIFZhbHVlXG5hbmQgUG9zdC1BdHRhY2sgQ2VydGFpbnR5IENoYW5nZSIsCiAgICB4ID0gIkxJV0MgJ0hlYWx0aCcgVGVybSBWYWx1ZSIsCiAgICB5ID0gIlBvc3QtQXR0YWNrIENlcnRhaW50eSBDaGFuZ2UiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSkgKwogIGdlb21fbGFiZWwoCiAgICBkYXRhID0gYW5ub3RhdGlvbnMsCiAgICBtYXBwaW5nID0gYWVzKHggPSBJbmYsIHkgPSBJbmYsIGxhYmVsID0gbGFiZWwpLAogICAgaGp1c3QgPSAxLjEsIHZqdXN0ID0gMS41LAogICAgaW5oZXJpdC5hZXMgPSBGQUxTRSwKICAgIGZpbGwgPSBhbHBoYSgid2hpdGUiLCAwLjUpCiAgKQoKCmBgYAoKIyMgQ29ycmVsYXRpb25zIG9uIFVzZXJzIChwcmUgdG8gbWlkKQoKYGBge3J9CgpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGNvcnJyKQoKCnByaW50KGRhdGEpCgojIFN0ZXAgMTogUmVzaGFwZSBhbmQgY29tcHV0ZSBkaWZmZXJlbmNlcwphbGxfY2VydGFpbnR5X2RlbHRhcyA8LSBkYXRhICU+JQogIHNlbGVjdCh1c2VyX2lkLCBtYXRjaGVzKCJsaWtlcnRfKHByZXxtaWQpX2NvbmRpdGlvblxcZCsiKSkgJT4lICAjIGtlZXAgdXNlcl9pZAogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtdXNlcl9pZCwKICAgIG5hbWVzX3RvID0gYygicGhhc2UiLCAiY29uZGl0aW9uIiksCiAgICBuYW1lc19wYXR0ZXJuID0gImxpa2VydF8ocHJlfG1pZClfY29uZGl0aW9uKFxcZCspIiwKICAgIHZhbHVlc190byA9ICJzY29yZSIKICApICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBwaGFzZSwgdmFsdWVzX2Zyb20gPSBzY29yZSkgJT4lCiAgbXV0YXRlKAogICAgZGlmZiA9IG1pZCAtIHByZSwKICAgIGNvbmRpdGlvbiA9IGNhc2Vfd2hlbigKICAgICAgY29uZGl0aW9uID09ICIxIiB+ICJDb250cm9sIiwKICAgICAgY29uZGl0aW9uID09ICIyIiB+ICJSZWFkaW5nIiwKICAgICAgY29uZGl0aW9uID09ICIzIiB+ICJXcml0aW5nIiwKICAgICAgY29uZGl0aW9uID09ICI0IiB+ICJDaGF0Ym90IiwKICAgICAgVFJVRSB+IGNvbmRpdGlvbgogICAgKQogICkgJT4lCiAgc2VsZWN0KHVzZXJfaWQsIGNvbmRpdGlvbiwgZGlmZikgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGNvbmRpdGlvbiwgdmFsdWVzX2Zyb20gPSBkaWZmKQoKCiMgMS4gTG9hZCB0aGUgTElXQyBhbmQgZGVsdGEgZGF0YQpsaXdjX2RhdGEgPC0gcmVhZHI6OnJlYWRfZGVsaW0oIkxJV0MtMjIgUmVzdWx0cyAtIHBhcnRpY2lwYW50X3RleHRzIC0gTElXQyBBbmFseXNpcy5jc3YiLCBkZWxpbSA9ICI7IikKCiMgMi4gRHJvcCB1bndhbnRlZCB1c2VyX2lkcyAoYXNzdW1pbmcgU2VnbWVudCBjb250YWlucyB1c2VyIElEIG9yIGEgbmFtZSBsaWtlICJ1c2VyXzEwIikKZXhjbHVkZWRfaWRzIDwtIGMoMTAsIDI2LCAyOSwgNDgsIDQ5LCA1MikKbGl3Y19maWx0ZXJlZCA8LSBsaXdjX2RhdGEgJT4lCiAgbXV0YXRlKHVzZXJfaWQgPSBhcy5udW1lcmljKGdzdWIoIlxcRCsiLCAiIiwgU2VnbWVudCkpKSAlPiUgICMgRXh0cmFjdCBudW1lcmljIElEIGZyb20gInVzZXJfWFgiCiAgZmlsdGVyKCF1c2VyX2lkICVpbiUgZXhjbHVkZWRfaWRzKQoKIyAzLiBQcmVwYXJlIGFsbF9jZXJ0YWludHlfZGVsdGFzIChlbnN1cmUgcGFydGljaXBhbnRfaWQgZm9ybWF0IG1hdGNoZXMpCmFsbF9jZXJ0YWludHlfZGVsdGFzIDwtIGFsbF9jZXJ0YWludHlfZGVsdGFzICU+JQogIG11dGF0ZSh1c2VyX2lkID0gYXMubnVtZXJpYyh1c2VyX2lkKSkgJT4lCiAgZmlsdGVyKCF1c2VyX2lkICVpbiUgZXhjbHVkZWRfaWRzKQoKbGl3Y19maWx0ZXJlZCA8LSBsaXdjX2RhdGEgJT4lCiAgbXV0YXRlKHVzZXJfaWQgPSBhcy5udW1lcmljKGdzdWIoInVzZXJfKFxcZCspXFwudHh0IiwgIlxcMSIsIEZpbGVuYW1lKSkpICU+JQogIGZpbHRlcighdXNlcl9pZCAlaW4lIGV4Y2x1ZGVkX2lkcykKCgojIDQuIEpvaW4gTElXQyBhbmQgZGVsdGEgZGF0YQptZXJnZWRfZGF0YSA8LSBpbm5lcl9qb2luKGxpd2NfZmlsdGVyZWQsIGFsbF9jZXJ0YWludHlfZGVsdGFzLCBieSA9ICJ1c2VyX2lkIikKCnByaW50KG1lcmdlZF9kYXRhKQoKIyA1LiBSdW4gY29ycmVsYXRpb24gYmV0d2VlbiBhbGwgTElXQyBmZWF0dXJlcyBhbmQgQ2hhdGJvdCBkZWx0YXMKIyBFeGNsdWRlIG5vbi1udW1lcmljIG9yIGlkZW50aWZpZXIgY29sdW1ucyBmaXJzdApsaXdjX2NvbHVtbnMgPC0gbGl3Y19maWx0ZXJlZCAlPiUKICBzZWxlY3QoLVNlZ21lbnQsIC11c2VyX2lkKSAlPiUKICBzZWxlY3Qod2hlcmUoaXMubnVtZXJpYykpICU+JSBuYW1lcygpCgpjb3JfaW5wdXQgPC0gbWVyZ2VkX2RhdGEgJT4lCiAgc2VsZWN0KGFsbF9vZihsaXdjX2NvbHVtbnMpLCBDaGF0Ym90KQoKY29yX3Jlc3VsdHMgPC0gY29ycmVsYXRlKGNvcl9pbnB1dCkgJT4lCiAgZm9jdXMoQ2hhdGJvdCkgJT4lCiAgYXJyYW5nZShkZXNjKGFicyhDaGF0Ym90KSkpICAjIFNvcnQgYnkgc3RyZW5ndGggb2YgY29ycmVsYXRpb24KCiMgNi4gVmlldyByZXN1bHRzCnByaW50KGNvcl9yZXN1bHRzKQoKIyBPcHRpb25hbDogRmlsdGVyIGZvciBtZWFuaW5nZnVsIGNvcnJlbGF0aW9uIChlLmcuID4gMC4zIG9yIDwgLTAuMykKc3Ryb25nX2NvcnJzIDwtIGNvcl9yZXN1bHRzICU+JQogIGZpbHRlcihhYnMoQ2hhdGJvdCkgPiAwLjMpCnByaW50KHN0cm9uZ19jb3JycykKCiMgU2VsZWN0IG51bWVyaWMgY29sdW1ucyBhbmQgQ2hhdGJvdCBkZWx0YQpudW1lcmljX3ZhcnMgPC0gbWVyZ2VkX2RhdGEgJT4lCiAgc2VsZWN0KGFsbF9vZihsaXdjX2NvbHVtbnMpKQoKY2hhdGJvdF9zY29yZXMgPC0gbWVyZ2VkX2RhdGEkQ2hhdGJvdAoKIyBJbml0aWFsaXplIGEgcmVzdWx0cyBkYXRhIGZyYW1lCnJlc3VsdHMgPC0gZGF0YS5mcmFtZSh0ZXJtID0gY2hhcmFjdGVyKCksIAogICAgICAgICAgICAgICAgICAgICAgY29yID0gbnVtZXJpYygpLCAKICAgICAgICAgICAgICAgICAgICAgIHBfdmFsdWUgPSBudW1lcmljKCksIAogICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBMb29wIG92ZXIgZWFjaCBMSVdDIHZhcmlhYmxlIGFuZCBydW4gY29yLnRlc3Qgd2l0aCBDaGF0Ym90CmZvciAodmFyIGluIGNvbG5hbWVzKG51bWVyaWNfdmFycykpIHsKICB0ZXN0IDwtIGNvci50ZXN0KG51bWVyaWNfdmFyc1tbdmFyXV0sIGNoYXRib3Rfc2NvcmVzLCB1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIikKICAKICByZXN1bHRzIDwtIHJiaW5kKHJlc3VsdHMsIGRhdGEuZnJhbWUoCiAgICB0ZXJtID0gdmFyLAogICAgY29yID0gdGVzdCRlc3RpbWF0ZSwKICAgIHBfdmFsdWUgPSB0ZXN0JHAudmFsdWUKICApKQp9CgojIFNvcnQgYnkgYWJzb2x1dGUgY29ycmVsYXRpb24KcmVzdWx0cyA8LSByZXN1bHRzICU+JSBhcnJhbmdlKGRlc2MoYWJzKGNvcikpKQoKcmVzdWx0cyA8LSByZXN1bHRzICU+JQogIG11dGF0ZShwX2FkaiA9IHAuYWRqdXN0KHBfdmFsdWUsIG1ldGhvZCA9ICJCSCIpKSAgIyBGRFIgY29ycmVjdGlvbgoKIyBWaWV3IHNpZ25pZmljYW50IGFmdGVyIGNvcnJlY3Rpb24Kc2lnX3Jlc3VsdHMgPC0gcmVzdWx0cyAlPiUKICBmaWx0ZXIocF92YWx1ZSA8IDAuMDUpCgpwcmludChzaWdfcmVzdWx0cykKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQoKIyBTZWxlY3QgTElXQyBjb2x1bW5zICsgQ2hhdGJvdCBkZWx0YSBhbmQgdXNlcl9pZApwbG90X2RhdGEgPC0gbWVyZ2VkX2RhdGEgJT4lCiAgc2VsZWN0KHVzZXJfaWQsIENoYXRib3QsIGFsbF9vZihsaXdjX2NvbHVtbnMpKQoKIyBDb252ZXJ0IExJV0MgdGVybXMgdG8gbG9uZyBmb3JtYXQKbG9uZ19kYXRhIDwtIHBsb3RfZGF0YSAlPiUKICBwaXZvdF9sb25nZXIoCiAgICBjb2xzID0gLWModXNlcl9pZCwgQ2hhdGJvdCksCiAgICBuYW1lc190byA9ICJMSVdDX3Rlcm0iLAogICAgdmFsdWVzX3RvID0gIkxJV0NfdmFsdWUiCiAgKQoKIyBBc3N1bWluZyAncmVzdWx0cycgYWxyZWFkeSBjb250YWlucyB0aGUgY29ycmVsYXRpb24gZGF0YSBmb3IgTElXQyB0ZXJtcwpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCgojIENhbGN1bGF0ZSBwcm9wb3J0aW9uIG9mIG5vbi16ZXJvIHZhbHVlcyBmb3IgZWFjaCBMSVdDIHRlcm0Kbm9uX3plcm9fcHJvcG9ydGlvbiA8LSBsb25nX2RhdGEgJT4lCiAgZ3JvdXBfYnkoTElXQ190ZXJtKSAlPiUKICBzdW1tYXJpemUobm9uX3plcm9fcmF0aW8gPSBzdW0oTElXQ192YWx1ZSAhPSAwKSAvIG4oKSwgLmdyb3VwcyA9ICdkcm9wJykKCiMgTWVyZ2Ugd2l0aCB0aGUgY29ycmVsYXRpb24gcmVzdWx0cwpyZXN1bHRzX3dpdGhfcHJvcG9ydGlvbiA8LSByZXN1bHRzICU+JQogIGlubmVyX2pvaW4obm9uX3plcm9fcHJvcG9ydGlvbiwgYnkgPSBjKCJ0ZXJtIiA9ICJMSVdDX3Rlcm0iKSkKCiMgU2V0IHRocmVzaG9sZHMKY29yX3RocmVzaG9sZCA8LSAwLjMgCm56X3RocmVzaG9sZCA8LSAwLjMgCgojIEZpbHRlciBmb3Igc3Ryb25nIGNvcnJlbGF0aW9ucyBhbmQgbm9uLXplcm8gaW5mbGF0ZWQgdGVybXMKCiMgRmlsdGVyIHNwZWNpZmljYWxseSBmb3IgIkhlYWx0aCIgdGVybQpmaWx0ZXJlZF90ZXJtcyA8LSByZXN1bHRzX3dpdGhfcHJvcG9ydGlvbiAlPiUKICBmaWx0ZXIodGVybSA9PSAiaGVhbHRoIikgJT4lCiAgcHVsbCh0ZXJtKQoKIyBGaWx0ZXIgbG9uZ19kYXRhIGZvciB0aGVzZSB0ZXJtcwp0b3Bfbm9uX3plcm9fbG9uZ19kYXRhIDwtIGxvbmdfZGF0YSAlPiUKICBmaWx0ZXIoTElXQ190ZXJtICVpbiUgZmlsdGVyZWRfdGVybXMpCgpgYGAKCiMjIENvcnJlbGF0aW9ucyBvbiBDaGF0Ym90IChtaWQgdG8gcG9zdCkKCmBgYHtyfQoKbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeShjb3JycikKCgpwcmludChkYXRhKQoKIyBTdGVwIDE6IFJlc2hhcGUgYW5kIGNvbXB1dGUgZGlmZmVyZW5jZXMKYWxsX2NlcnRhaW50eV9kZWx0YXMgPC0gZGF0YSAlPiUKICBzZWxlY3QodXNlcl9pZCwgbWF0Y2hlcygibGlrZXJ0XyhtaWR8cG9zdClfY29uZGl0aW9uXFxkKyIpKSAlPiUgICMga2VlcCB1c2VyX2lkCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC11c2VyX2lkLAogICAgbmFtZXNfdG8gPSBjKCJwaGFzZSIsICJjb25kaXRpb24iKSwKICAgIG5hbWVzX3BhdHRlcm4gPSAibGlrZXJ0XyhtaWR8cG9zdClfY29uZGl0aW9uKFxcZCspIiwKICAgIHZhbHVlc190byA9ICJzY29yZSIKICApICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBwaGFzZSwgdmFsdWVzX2Zyb20gPSBzY29yZSkgJT4lCiAgbXV0YXRlKAogICAgZGlmZiA9IHBvc3QgLSBtaWQsCiAgICBjb25kaXRpb24gPSBjYXNlX3doZW4oCiAgICAgIGNvbmRpdGlvbiA9PSAiMSIgfiAiQ29udHJvbCIsCiAgICAgIGNvbmRpdGlvbiA9PSAiMiIgfiAiUmVhZGluZyIsCiAgICAgIGNvbmRpdGlvbiA9PSAiMyIgfiAiV3JpdGluZyIsCiAgICAgIGNvbmRpdGlvbiA9PSAiNCIgfiAiQ2hhdGJvdCIsCiAgICAgIFRSVUUgfiBjb25kaXRpb24KICAgICkKICApICU+JQogIHNlbGVjdCh1c2VyX2lkLCBjb25kaXRpb24sIGRpZmYpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBjb25kaXRpb24sIHZhbHVlc19mcm9tID0gZGlmZikKCgojIDEuIExvYWQgdGhlIExJV0MgYW5kIGRlbHRhIGRhdGEKbGl3Y19kYXRhIDwtIHJlYWRyOjpyZWFkX2RlbGltKCJMSVdDLTIyIFJlc3VsdHMgLSBib3RfdGV4dHMgLSBMSVdDIEFuYWx5c2lzLmNzdiIsIGRlbGltID0gIjsiKQoKIyAyLiBEcm9wIHVud2FudGVkIHVzZXJfaWRzIChhc3N1bWluZyBTZWdtZW50IGNvbnRhaW5zIHVzZXIgSUQgb3IgYSBuYW1lIGxpa2UgInVzZXJfMTAiKQpleGNsdWRlZF9pZHMgPC0gYygxMCwgMjYsIDI5LCA0OCwgNDksIDUyKQpsaXdjX2ZpbHRlcmVkIDwtIGxpd2NfZGF0YSAlPiUKICBtdXRhdGUodXNlcl9pZCA9IGFzLm51bWVyaWMoZ3N1YigiXFxEKyIsICIiLCBTZWdtZW50KSkpICU+JSAgIyBFeHRyYWN0IG51bWVyaWMgSUQgZnJvbSAidXNlcl9YWCIKICBmaWx0ZXIoIXVzZXJfaWQgJWluJSBleGNsdWRlZF9pZHMpCgojIDMuIFByZXBhcmUgYWxsX2NlcnRhaW50eV9kZWx0YXMgKGVuc3VyZSBwYXJ0aWNpcGFudF9pZCBmb3JtYXQgbWF0Y2hlcykKYWxsX2NlcnRhaW50eV9kZWx0YXMgPC0gYWxsX2NlcnRhaW50eV9kZWx0YXMgJT4lCiAgbXV0YXRlKHVzZXJfaWQgPSBhcy5udW1lcmljKHVzZXJfaWQpKSAlPiUKICBmaWx0ZXIoIXVzZXJfaWQgJWluJSBleGNsdWRlZF9pZHMpCgpsaXdjX2ZpbHRlcmVkIDwtIGxpd2NfZGF0YSAlPiUKICBtdXRhdGUodXNlcl9pZCA9IGFzLm51bWVyaWMoZ3N1YigidXNlcl8oXFxkKylcXC50eHQiLCAiXFwxIiwgRmlsZW5hbWUpKSkgJT4lCiAgZmlsdGVyKCF1c2VyX2lkICVpbiUgZXhjbHVkZWRfaWRzKQoKCiMgNC4gSm9pbiBMSVdDIGFuZCBkZWx0YSBkYXRhCm1lcmdlZF9kYXRhIDwtIGlubmVyX2pvaW4obGl3Y19maWx0ZXJlZCwgYWxsX2NlcnRhaW50eV9kZWx0YXMsIGJ5ID0gInVzZXJfaWQiKQoKcHJpbnQobWVyZ2VkX2RhdGEpCgojIDUuIFJ1biBjb3JyZWxhdGlvbiBiZXR3ZWVuIGFsbCBMSVdDIGZlYXR1cmVzIGFuZCBDaGF0Ym90IGRlbHRhcwojIEV4Y2x1ZGUgbm9uLW51bWVyaWMgb3IgaWRlbnRpZmllciBjb2x1bW5zIGZpcnN0Cmxpd2NfY29sdW1ucyA8LSBsaXdjX2ZpbHRlcmVkICU+JQogIHNlbGVjdCgtU2VnbWVudCwgLXVzZXJfaWQpICU+JQogIHNlbGVjdCh3aGVyZShpcy5udW1lcmljKSkgJT4lIG5hbWVzKCkKCmNvcl9pbnB1dCA8LSBtZXJnZWRfZGF0YSAlPiUKICBzZWxlY3QoYWxsX29mKGxpd2NfY29sdW1ucyksIENoYXRib3QpCgpjb3JfcmVzdWx0cyA8LSBjb3JyZWxhdGUoY29yX2lucHV0KSAlPiUKICBmb2N1cyhDaGF0Ym90KSAlPiUKICBhcnJhbmdlKGRlc2MoYWJzKENoYXRib3QpKSkgICMgU29ydCBieSBzdHJlbmd0aCBvZiBjb3JyZWxhdGlvbgoKIyA2LiBWaWV3IHJlc3VsdHMKcHJpbnQoY29yX3Jlc3VsdHMpCgojIE9wdGlvbmFsOiBGaWx0ZXIgZm9yIG1lYW5pbmdmdWwgY29ycmVsYXRpb24gKGUuZy4gPiAwLjMgb3IgPCAtMC4zKQpzdHJvbmdfY29ycnMgPC0gY29yX3Jlc3VsdHMgJT4lCiAgZmlsdGVyKGFicyhDaGF0Ym90KSA+IDAuMykKcHJpbnQoc3Ryb25nX2NvcnJzKQoKIyBTZWxlY3QgbnVtZXJpYyBjb2x1bW5zIGFuZCBDaGF0Ym90IGRlbHRhCm51bWVyaWNfdmFycyA8LSBtZXJnZWRfZGF0YSAlPiUKICBzZWxlY3QoYWxsX29mKGxpd2NfY29sdW1ucykpCgpjaGF0Ym90X3Njb3JlcyA8LSBtZXJnZWRfZGF0YSRDaGF0Ym90CgojIEluaXRpYWxpemUgYSByZXN1bHRzIGRhdGEgZnJhbWUKcmVzdWx0cyA8LSBkYXRhLmZyYW1lKHRlcm0gPSBjaGFyYWN0ZXIoKSwgCiAgICAgICAgICAgICAgICAgICAgICBjb3IgPSBudW1lcmljKCksIAogICAgICAgICAgICAgICAgICAgICAgcF92YWx1ZSA9IG51bWVyaWMoKSwgCiAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojIExvb3Agb3ZlciBlYWNoIExJV0MgdmFyaWFibGUgYW5kIHJ1biBjb3IudGVzdCB3aXRoIENoYXRib3QKZm9yICh2YXIgaW4gY29sbmFtZXMobnVtZXJpY192YXJzKSkgewogIHRlc3QgPC0gY29yLnRlc3QobnVtZXJpY192YXJzW1t2YXJdXSwgY2hhdGJvdF9zY29yZXMsIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQogIAogIHJlc3VsdHMgPC0gcmJpbmQocmVzdWx0cywgZGF0YS5mcmFtZSgKICAgIHRlcm0gPSB2YXIsCiAgICBjb3IgPSB0ZXN0JGVzdGltYXRlLAogICAgcF92YWx1ZSA9IHRlc3QkcC52YWx1ZQogICkpCn0KCiMgU29ydCBieSBhYnNvbHV0ZSBjb3JyZWxhdGlvbgpyZXN1bHRzIDwtIHJlc3VsdHMgJT4lIGFycmFuZ2UoZGVzYyhhYnMoY29yKSkpCgpyZXN1bHRzIDwtIHJlc3VsdHMgJT4lCiAgbXV0YXRlKHBfYWRqID0gcC5hZGp1c3QocF92YWx1ZSwgbWV0aG9kID0gIkJIIikpICAjIEZEUiBjb3JyZWN0aW9uCgojIFZpZXcgc2lnbmlmaWNhbnQgYWZ0ZXIgY29ycmVjdGlvbgpzaWdfcmVzdWx0cyA8LSByZXN1bHRzICU+JQogIGZpbHRlcihwX3ZhbHVlIDwgMC4wNSkKCnByaW50KHNpZ19yZXN1bHRzKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCgojIFNlbGVjdCBMSVdDIGNvbHVtbnMgKyBDaGF0Ym90IGRlbHRhIGFuZCB1c2VyX2lkCnBsb3RfZGF0YSA8LSBtZXJnZWRfZGF0YSAlPiUKICBzZWxlY3QodXNlcl9pZCwgQ2hhdGJvdCwgYWxsX29mKGxpd2NfY29sdW1ucykpCgojIENvbnZlcnQgTElXQyB0ZXJtcyB0byBsb25nIGZvcm1hdApsb25nX2RhdGEgPC0gcGxvdF9kYXRhICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtYyh1c2VyX2lkLCBDaGF0Ym90KSwKICAgIG5hbWVzX3RvID0gIkxJV0NfdGVybSIsCiAgICB2YWx1ZXNfdG8gPSAiTElXQ192YWx1ZSIKICApCgojIEFzc3VtaW5nICdyZXN1bHRzJyBhbHJlYWR5IGNvbnRhaW5zIHRoZSBjb3JyZWxhdGlvbiBkYXRhIGZvciBMSVdDIHRlcm1zCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgQ2FsY3VsYXRlIHByb3BvcnRpb24gb2Ygbm9uLXplcm8gdmFsdWVzIGZvciBlYWNoIExJV0MgdGVybQpub25femVyb19wcm9wb3J0aW9uIDwtIGxvbmdfZGF0YSAlPiUKICBncm91cF9ieShMSVdDX3Rlcm0pICU+JQogIHN1bW1hcml6ZShub25femVyb19yYXRpbyA9IHN1bShMSVdDX3ZhbHVlICE9IDApIC8gbigpLCAuZ3JvdXBzID0gJ2Ryb3AnKQoKIyBNZXJnZSB3aXRoIHRoZSBjb3JyZWxhdGlvbiByZXN1bHRzCnJlc3VsdHNfd2l0aF9wcm9wb3J0aW9uIDwtIHJlc3VsdHMgJT4lCiAgaW5uZXJfam9pbihub25femVyb19wcm9wb3J0aW9uLCBieSA9IGMoInRlcm0iID0gIkxJV0NfdGVybSIpKQoKIyBTZXQgdGhyZXNob2xkcwpjb3JfdGhyZXNob2xkIDwtIDAuMyAKbnpfdGhyZXNob2xkIDwtIDAuMyAKCiMgRmlsdGVyIGZvciBzdHJvbmcgY29ycmVsYXRpb25zIGFuZCBub24temVybyBpbmZsYXRlZCB0ZXJtcwoKIyBGaWx0ZXIgc3BlY2lmaWNhbGx5IGZvciAiSGVhbHRoIiB0ZXJtCmZpbHRlcmVkX3Rlcm1zIDwtIHJlc3VsdHNfd2l0aF9wcm9wb3J0aW9uICU+JQogIGZpbHRlcih0ZXJtID09ICJoZWFsdGgiKSAlPiUKICBwdWxsKHRlcm0pCgojIEZpbHRlciBsb25nX2RhdGEgZm9yIHRoZXNlIHRlcm1zCnRvcF9ub25femVyb19sb25nX2RhdGEgPC0gbG9uZ19kYXRhICU+JQogIGZpbHRlcihMSVdDX3Rlcm0gJWluJSBmaWx0ZXJlZF90ZXJtcykKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgQWRkIGN1c3RvbSBuYW1lcyBtYXBwaW5nCmN1c3RvbV9uYW1lcyA8LSBjKAogICJoZWFsdGgiID0gIkhlYWx0aCIKKQoKIyBGaWx0ZXIgYW5kIHByZXBhcmUgYW5ub3RhdGlvbnMKYW5ub3RhdGlvbnMgPC0gcmVzdWx0c193aXRoX3Byb3BvcnRpb24gJT4lCiAgZmlsdGVyKHRlcm0gJWluJSBmaWx0ZXJlZF90ZXJtcykgJT4lCiAgbXV0YXRlKAogICAgbGFiZWwgPSBwYXN0ZTAoInIgPSAiLCByb3VuZChjb3IsIDIpLCAiLCBwID0gIiwgZm9ybWF0KHBfYWRqLCBkaWdpdHMgPSAyKSksCiAgICBMSVdDX3Rlcm0gPSB0ZXJtCiAgKSAlPiUKICBzZWxlY3QoTElXQ190ZXJtLCBsYWJlbCkKCiMgQWRkIGFubm90YXRpb25zIHRvIHRoZSBsb25nIGRhdGEgZm9yIHBsb3R0aW5nCnRvcF9ub25femVyb19sb25nX2RhdGEgPC0gdG9wX25vbl96ZXJvX2xvbmdfZGF0YSAlPiUKICBsZWZ0X2pvaW4oYW5ub3RhdGlvbnMsIGJ5ID0gIkxJV0NfdGVybSIpCgojIFBsb3Qgd2l0aCBjdXN0b20gZmFjZXQgbGFiZWxzCmdncGxvdCh0b3Bfbm9uX3plcm9fbG9uZ19kYXRhLCBhZXMoeCA9IExJV0NfdmFsdWUsIHkgPSBDaGF0Ym90KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJzdGVlbGJsdWUiKSArCiAgZmFjZXRfd3JhcCh+IExJV0NfdGVybSwgc2NhbGVzID0gImZyZWVfeCIsIGxhYmVsbGVyID0gbGFiZWxsZXIoTElXQ190ZXJtID0gY3VzdG9tX25hbWVzKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDb3JyZWxhdGlvbiBvZiBMSVdDICdIZWFsdGgnIFRlcm0gVmFsdWVcbmFuZCBQb3N0LUlub2N1bGF0aW9uIENlcnRhaW50eSBDaGFuZ2UiLAogICAgeCA9ICJMSVdDICdIZWFsdGgnIFRlcm0gVmFsdWUiLAogICAgeSA9ICJQb3N0LUF0dGFjayBDZXJ0YWludHkgQ2hhbmdlIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIikpICsKICBnZW9tX2xhYmVsKAogICAgZGF0YSA9IGFubm90YXRpb25zLAogICAgbWFwcGluZyA9IGFlcyh4ID0gSW5mLCB5ID0gSW5mLCBsYWJlbCA9IGxhYmVsKSwKICAgIGhqdXN0ID0gMS4xLCB2anVzdCA9IDEuNSwKICAgIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICBmaWxsID0gYWxwaGEoIndoaXRlIiwgMC41KQogICkKCgpgYGAKCiMjIENvcnJlbGF0aW9ucyBvbiBDaGF0Ym90IChwcmUgdG8gbWlkKQoKYGBge3J9CgpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGNvcnJyKQoKCnByaW50KGRhdGEpCgojIFN0ZXAgMTogUmVzaGFwZSBhbmQgY29tcHV0ZSBkaWZmZXJlbmNlcwphbGxfY2VydGFpbnR5X2RlbHRhcyA8LSBkYXRhICU+JQogIHNlbGVjdCh1c2VyX2lkLCBtYXRjaGVzKCJsaWtlcnRfKHByZXxtaWQpX2NvbmRpdGlvblxcZCsiKSkgJT4lICAjIGtlZXAgdXNlcl9pZAogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtdXNlcl9pZCwKICAgIG5hbWVzX3RvID0gYygicGhhc2UiLCAiY29uZGl0aW9uIiksCiAgICBuYW1lc19wYXR0ZXJuID0gImxpa2VydF8ocHJlfG1pZClfY29uZGl0aW9uKFxcZCspIiwKICAgIHZhbHVlc190byA9ICJzY29yZSIKICApICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBwaGFzZSwgdmFsdWVzX2Zyb20gPSBzY29yZSkgJT4lCiAgbXV0YXRlKAogICAgZGlmZiA9IG1pZCAtIHByZSwKICAgIGNvbmRpdGlvbiA9IGNhc2Vfd2hlbigKICAgICAgY29uZGl0aW9uID09ICIxIiB+ICJDb250cm9sIiwKICAgICAgY29uZGl0aW9uID09ICIyIiB+ICJSZWFkaW5nIiwKICAgICAgY29uZGl0aW9uID09ICIzIiB+ICJXcml0aW5nIiwKICAgICAgY29uZGl0aW9uID09ICI0IiB+ICJDaGF0Ym90IiwKICAgICAgVFJVRSB+IGNvbmRpdGlvbgogICAgKQogICkgJT4lCiAgc2VsZWN0KHVzZXJfaWQsIGNvbmRpdGlvbiwgZGlmZikgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGNvbmRpdGlvbiwgdmFsdWVzX2Zyb20gPSBkaWZmKQoKcHJpbnQoYWxsX2NlcnRhaW50eV9kZWx0YXMpCgojIDEuIExvYWQgdGhlIExJV0MgYW5kIGRlbHRhIGRhdGEKbGl3Y19kYXRhIDwtIHJlYWRyOjpyZWFkX2RlbGltKCJMSVdDLTIyIFJlc3VsdHMgLSBib3RfdGV4dHMgLSBMSVdDIEFuYWx5c2lzLmNzdiIsIGRlbGltID0gIjsiKQoKIyAyLiBEcm9wIHVud2FudGVkIHVzZXJfaWRzIChhc3N1bWluZyBTZWdtZW50IGNvbnRhaW5zIHVzZXIgSUQgb3IgYSBuYW1lIGxpa2UgInVzZXJfMTAiKQpleGNsdWRlZF9pZHMgPC0gYygxMCwgMjYsIDI5LCA0OCwgNDksIDUyKQpsaXdjX2ZpbHRlcmVkIDwtIGxpd2NfZGF0YSAlPiUKICBtdXRhdGUodXNlcl9pZCA9IGFzLm51bWVyaWMoZ3N1YigiXFxEKyIsICIiLCBTZWdtZW50KSkpICU+JSAgIyBFeHRyYWN0IG51bWVyaWMgSUQgZnJvbSAidXNlcl9YWCIKICBmaWx0ZXIoIXVzZXJfaWQgJWluJSBleGNsdWRlZF9pZHMpCgojIDMuIFByZXBhcmUgYWxsX2NlcnRhaW50eV9kZWx0YXMgKGVuc3VyZSBwYXJ0aWNpcGFudF9pZCBmb3JtYXQgbWF0Y2hlcykKYWxsX2NlcnRhaW50eV9kZWx0YXMgPC0gYWxsX2NlcnRhaW50eV9kZWx0YXMgJT4lCiAgbXV0YXRlKHVzZXJfaWQgPSBhcy5udW1lcmljKHVzZXJfaWQpKSAlPiUKICBmaWx0ZXIoIXVzZXJfaWQgJWluJSBleGNsdWRlZF9pZHMpCgpsaXdjX2ZpbHRlcmVkIDwtIGxpd2NfZGF0YSAlPiUKICBtdXRhdGUodXNlcl9pZCA9IGFzLm51bWVyaWMoZ3N1YigidXNlcl8oXFxkKylcXC50eHQiLCAiXFwxIiwgRmlsZW5hbWUpKSkgJT4lCiAgZmlsdGVyKCF1c2VyX2lkICVpbiUgZXhjbHVkZWRfaWRzKQoKCiMgNC4gSm9pbiBMSVdDIGFuZCBkZWx0YSBkYXRhCm1lcmdlZF9kYXRhIDwtIGlubmVyX2pvaW4obGl3Y19maWx0ZXJlZCwgYWxsX2NlcnRhaW50eV9kZWx0YXMsIGJ5ID0gInVzZXJfaWQiKQoKcHJpbnQobWVyZ2VkX2RhdGEpCgojIDUuIFJ1biBjb3JyZWxhdGlvbiBiZXR3ZWVuIGFsbCBMSVdDIGZlYXR1cmVzIGFuZCBDaGF0Ym90IGRlbHRhcwojIEV4Y2x1ZGUgbm9uLW51bWVyaWMgb3IgaWRlbnRpZmllciBjb2x1bW5zIGZpcnN0Cmxpd2NfY29sdW1ucyA8LSBsaXdjX2ZpbHRlcmVkICU+JQogIHNlbGVjdCgtU2VnbWVudCwgLXVzZXJfaWQpICU+JQogIHNlbGVjdCh3aGVyZShpcy5udW1lcmljKSkgJT4lIG5hbWVzKCkKCmNvcl9pbnB1dCA8LSBtZXJnZWRfZGF0YSAlPiUKICBzZWxlY3QoYWxsX29mKGxpd2NfY29sdW1ucyksIENoYXRib3QpCgpjb3JfcmVzdWx0cyA8LSBjb3JyZWxhdGUoY29yX2lucHV0KSAlPiUKICBmb2N1cyhDaGF0Ym90KSAlPiUKICBhcnJhbmdlKGRlc2MoYWJzKENoYXRib3QpKSkgICMgU29ydCBieSBzdHJlbmd0aCBvZiBjb3JyZWxhdGlvbgoKIyA2LiBWaWV3IHJlc3VsdHMKcHJpbnQoY29yX3Jlc3VsdHMpCgojIE9wdGlvbmFsOiBGaWx0ZXIgZm9yIG1lYW5pbmdmdWwgY29ycmVsYXRpb24gKGUuZy4gPiAwLjMgb3IgPCAtMC4zKQpzdHJvbmdfY29ycnMgPC0gY29yX3Jlc3VsdHMgJT4lCiAgZmlsdGVyKGFicyhDaGF0Ym90KSA+IDAuMykKcHJpbnQoc3Ryb25nX2NvcnJzKQoKIyBTZWxlY3QgbnVtZXJpYyBjb2x1bW5zIGFuZCBDaGF0Ym90IGRlbHRhCm51bWVyaWNfdmFycyA8LSBtZXJnZWRfZGF0YSAlPiUKICBzZWxlY3QoYWxsX29mKGxpd2NfY29sdW1ucykpCgpjaGF0Ym90X3Njb3JlcyA8LSBtZXJnZWRfZGF0YSRDaGF0Ym90CgojIEluaXRpYWxpemUgYSByZXN1bHRzIGRhdGEgZnJhbWUKcmVzdWx0cyA8LSBkYXRhLmZyYW1lKHRlcm0gPSBjaGFyYWN0ZXIoKSwgCiAgICAgICAgICAgICAgICAgICAgICBjb3IgPSBudW1lcmljKCksIAogICAgICAgICAgICAgICAgICAgICAgcF92YWx1ZSA9IG51bWVyaWMoKSwgCiAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojIExvb3Agb3ZlciBlYWNoIExJV0MgdmFyaWFibGUgYW5kIHJ1biBjb3IudGVzdCB3aXRoIENoYXRib3QKZm9yICh2YXIgaW4gY29sbmFtZXMobnVtZXJpY192YXJzKSkgewogIHRlc3QgPC0gY29yLnRlc3QobnVtZXJpY192YXJzW1t2YXJdXSwgY2hhdGJvdF9zY29yZXMsIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQogIAogIHJlc3VsdHMgPC0gcmJpbmQocmVzdWx0cywgZGF0YS5mcmFtZSgKICAgIHRlcm0gPSB2YXIsCiAgICBjb3IgPSB0ZXN0JGVzdGltYXRlLAogICAgcF92YWx1ZSA9IHRlc3QkcC52YWx1ZQogICkpCn0KCiMgU29ydCBieSBhYnNvbHV0ZSBjb3JyZWxhdGlvbgpyZXN1bHRzIDwtIHJlc3VsdHMgJT4lIGFycmFuZ2UoZGVzYyhhYnMoY29yKSkpCgpyZXN1bHRzIDwtIHJlc3VsdHMgJT4lCiAgbXV0YXRlKHBfYWRqID0gcC5hZGp1c3QocF92YWx1ZSwgbWV0aG9kID0gIkJIIikpICAjIEZEUiBjb3JyZWN0aW9uCgojIFZpZXcgc2lnbmlmaWNhbnQgYWZ0ZXIgY29ycmVjdGlvbgpzaWdfcmVzdWx0cyA8LSByZXN1bHRzICU+JQogIGZpbHRlcihwX3ZhbHVlIDwgMC4wNSkKCnByaW50KHNpZ19yZXN1bHRzKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCgojIFNlbGVjdCBMSVdDIGNvbHVtbnMgKyBDaGF0Ym90IGRlbHRhIGFuZCB1c2VyX2lkCnBsb3RfZGF0YSA8LSBtZXJnZWRfZGF0YSAlPiUKICBzZWxlY3QodXNlcl9pZCwgQ2hhdGJvdCwgYWxsX29mKGxpd2NfY29sdW1ucykpCgojIENvbnZlcnQgTElXQyB0ZXJtcyB0byBsb25nIGZvcm1hdApsb25nX2RhdGEgPC0gcGxvdF9kYXRhICU+JQogIHBpdm90X2xvbmdlcigKICAgIGNvbHMgPSAtYyh1c2VyX2lkLCBDaGF0Ym90KSwKICAgIG5hbWVzX3RvID0gIkxJV0NfdGVybSIsCiAgICB2YWx1ZXNfdG8gPSAiTElXQ192YWx1ZSIKICApCgojIEFzc3VtaW5nICdyZXN1bHRzJyBhbHJlYWR5IGNvbnRhaW5zIHRoZSBjb3JyZWxhdGlvbiBkYXRhIGZvciBMSVdDIHRlcm1zCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgQ2FsY3VsYXRlIHByb3BvcnRpb24gb2Ygbm9uLXplcm8gdmFsdWVzIGZvciBlYWNoIExJV0MgdGVybQpub25femVyb19wcm9wb3J0aW9uIDwtIGxvbmdfZGF0YSAlPiUKICBncm91cF9ieShMSVdDX3Rlcm0pICU+JQogIHN1bW1hcml6ZShub25femVyb19yYXRpbyA9IHN1bShMSVdDX3ZhbHVlICE9IDApIC8gbigpLCAuZ3JvdXBzID0gJ2Ryb3AnKQoKIyBNZXJnZSB3aXRoIHRoZSBjb3JyZWxhdGlvbiByZXN1bHRzCnJlc3VsdHNfd2l0aF9wcm9wb3J0aW9uIDwtIHJlc3VsdHMgJT4lCiAgaW5uZXJfam9pbihub25femVyb19wcm9wb3J0aW9uLCBieSA9IGMoInRlcm0iID0gIkxJV0NfdGVybSIpKQoKIyBTZXQgdGhyZXNob2xkcwpjb3JfdGhyZXNob2xkIDwtIDAuMyAKbnpfdGhyZXNob2xkIDwtIDAuMyAKCiMgRmlsdGVyIGZvciBzdHJvbmcgY29ycmVsYXRpb25zIGFuZCBub24temVybyBpbmZsYXRlZCB0ZXJtcwoKIyBGaWx0ZXIgc3BlY2lmaWNhbGx5IGZvciAiSGVhbHRoIiB0ZXJtCmZpbHRlcmVkX3Rlcm1zIDwtIHJlc3VsdHNfd2l0aF9wcm9wb3J0aW9uICU+JQogIGZpbHRlcih0ZXJtID09ICJoZWFsdGgiKSAlPiUKICBwdWxsKHRlcm0pCgojIEZpbHRlciBsb25nX2RhdGEgZm9yIHRoZXNlIHRlcm1zCnRvcF9ub25femVyb19sb25nX2RhdGEgPC0gbG9uZ19kYXRhICU+JQogIGZpbHRlcihMSVdDX3Rlcm0gJWluJSBmaWx0ZXJlZF90ZXJtcykKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgQWRkIGN1c3RvbSBuYW1lcyBtYXBwaW5nCmN1c3RvbV9uYW1lcyA8LSBjKAogICJoZWFsdGgiID0gIkhlYWx0aCIKKQoKIyBGaWx0ZXIgYW5kIHByZXBhcmUgYW5ub3RhdGlvbnMKYW5ub3RhdGlvbnMgPC0gcmVzdWx0c193aXRoX3Byb3BvcnRpb24gJT4lCiAgZmlsdGVyKHRlcm0gJWluJSBmaWx0ZXJlZF90ZXJtcykgJT4lCiAgbXV0YXRlKAogICAgbGFiZWwgPSBwYXN0ZTAoInIgPSAiLCByb3VuZChjb3IsIDIpLCAiLCBwID0gIiwgZm9ybWF0KHBfYWRqLCBkaWdpdHMgPSAyKSksCiAgICBMSVdDX3Rlcm0gPSB0ZXJtCiAgKSAlPiUKICBzZWxlY3QoTElXQ190ZXJtLCBsYWJlbCkKCiMgQWRkIGFubm90YXRpb25zIHRvIHRoZSBsb25nIGRhdGEgZm9yIHBsb3R0aW5nCnRvcF9ub25femVyb19sb25nX2RhdGEgPC0gdG9wX25vbl96ZXJvX2xvbmdfZGF0YSAlPiUKICBsZWZ0X2pvaW4oYW5ub3RhdGlvbnMsIGJ5ID0gIkxJV0NfdGVybSIpCgojIFBsb3Qgd2l0aCBjdXN0b20gZmFjZXQgbGFiZWxzCmdncGxvdCh0b3Bfbm9uX3plcm9fbG9uZ19kYXRhLCBhZXMoeCA9IExJV0NfdmFsdWUsIHkgPSBDaGF0Ym90KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjYpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJzdGVlbGJsdWUiKSArCiAgZmFjZXRfd3JhcCh+IExJV0NfdGVybSwgc2NhbGVzID0gImZyZWVfeCIsIGxhYmVsbGVyID0gbGFiZWxsZXIoTElXQ190ZXJtID0gY3VzdG9tX25hbWVzKSkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJDb3JyZWxhdGlvbiBvZiBMSVdDICdIZWFsdGgnIFRlcm0gVmFsdWVcbmFuZCBQb3N0LUlub2N1bGF0aW9uIENlcnRhaW50eSBDaGFuZ2UiLAogICAgeCA9ICJMSVdDICdIZWFsdGgnIFRlcm0gVmFsdWUiLAogICAgeSA9ICJQb3N0LUlub2N1bGF0aW9uIENlcnRhaW50eSBDaGFuZ2UiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSkgKwogIGdlb21fbGFiZWwoCiAgICBkYXRhID0gYW5ub3RhdGlvbnMsCiAgICBtYXBwaW5nID0gYWVzKHggPSBJbmYsIHkgPSBJbmYsIGxhYmVsID0gbGFiZWwpLAogICAgaGp1c3QgPSAxLjEsIHZqdXN0ID0gMS41LAogICAgaW5oZXJpdC5hZXMgPSBGQUxTRSwKICAgIGZpbGwgPSBhbHBoYSgid2hpdGUiLCAwLjUpCiAgKQoKCmBgYAo=