1 Research Question 1: Prevalence Patterns of Antibiotic Use in Vietnamese Farms and Households

1.1 Introduction

This analysis addresses the first research question of our study on antimicrobial resistance in Vietnam: What are the prevalence patterns of antibiotic use on farms and in households, and how do they compare?

1.1.1 Research Hypotheses

  • H1.1: Prophylactic and growth promotion antibiotic use is widespread in farm animals, with prevalence higher than corresponding uses in human medicine.
  • H1.2: There are systematic differences in antibiotic use patterns among different animal types (chickens, pigs, cattle), reflecting structural needs of different production systems.
  • H1.3: There is a non-linear relationship between farm size and antibiotic use practices, with medium-sized farms potentially having the highest rates of inappropriate use.
  • H1.4: Human antibiotic use patterns in households show isomorphism with farm animal antibiotic use in the same community, influenced by common information sources and social norms.

1.1.2 Significance for One Health Framework

This research question directly supports the One Health framework by comparing antibiotic use patterns in human and animal health sectors. Understanding these patterns and their correlations is essential for:

  1. Establishing baseline prevalence of antibiotic use across sectors
  2. Identifying potential cross-sectoral influences on antibiotic use
  3. Guiding future interventions that target both human and animal antibiotic use
  4. Contextualizing antimicrobial resistance patterns observed in subsequent analyses

1.2 Data Preparation

1.2.1 Loading Required Packages

# List of required packages
packages <- c("tidyverse", "here", "haven", "knitr", "kableExtra",
              "janitor", "corrplot", "gtsummary", "sf", "ggpubr",
              "MASS", "segmented", "car", "psych", "lme4", "performance",
              "vegan", "geosphere", "igraph", "spdep", "binom",
              "reshape2", "scales", "patchwork", "gridExtra",
              "grid")

# Install packages that are not already installed
installed <- packages %in% installed.packages()[,"Package"]

if(any(!installed)) {
  install.packages(packages[!installed])
}

# Load all packages
invisible(lapply(packages, library, character.only = TRUE))


# Set options for better output
options(scipen = 999)        # Avoid scientific notation
options(digits = 2)          # Round to 2 decimal places
options(max.print = 1000)    # Limit output lines

# Function to safely read files with different formats
safe_read <- function(file_path) {
  # Get file extension
  ext <- tools::file_ext(file_path)
  
  # Read file based on extension
  if (ext == "csv") {
    data <- read.csv(file_path, stringsAsFactors = FALSE)
  } else if (ext == "rds") {
    data <- readRDS(file_path)
  } else if (ext == "sav") {
    data <- haven::read_spss(file_path)
  } else if (ext == "dta") {
    data <- haven::read_dta(file_path)
  } else if (ext == "txt") {
    # For txt files, attempt to determine delimiter
    data <- read.delim(file_path, sep = "\t", stringsAsFactors = FALSE)
  } else {
    stop("Unsupported file format")
  }
  
  return(data)
}

1.2.2 Loading and Examining Data

# Load farm and household data
# Adjust file paths to where your data is stored
farm_data <- safe_read(here("Data", "farm_amr_coded_anonymised.dta"))
household_data <- safe_read(here("Data", "coded_anonymised.dta"))

# Display basic information about datasets
farm_dimensions <- dim(farm_data)
household_dimensions <- dim(household_data)
 
# Print dataset dimensions
cat("Farm dataset dimensions:", farm_dimensions[1], "rows and", farm_dimensions[2], "columns\n")
## Farm dataset dimensions: 1156 rows and 710 columns
cat("Household dataset dimensions:", household_dimensions[1], "rows and", household_dimensions[2], "columns\n")
## Household dataset dimensions: 9411 rows and 991 columns
# Display the first few rows of each dataset to understand structure
farm_data %>%
  dplyr::select(farm_id, role, sex, birth_year, edu, 
                chickens, pigs, cattle, ducks, muscovy, geese, dogs, cats, 
                buffalo, goats, rabbits, area_farm, product1, product2, product3, 
                product4, product5, product6, virus, bacteria, resistant_body, 
                resistant_bacteria, transmission, residue, synonym, abu_general, 
                decision, advice1, advice2, advice3, purpose_antibiotic___1, 
                purpose_antibiotic___2, purpose_antibiotic___3, purpose_antibiotic___99, 
                purpose_antibiotic_other, dosage___1, dosage___2, dosage___3, dosage___99, 
                dosage_other, combination, combination_other, chlo, nitr, dime, metr, cipr, 
                oflo, carb, olaq, baci, withdrawal, withdrawal_other, species, abu_chicken, 
                abu_pig, abu_cattle, district, commune) %>%
  head(10) %>%
  kable() %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE, font_size = 12) %>%
  scroll_box(width = "100%", height = "500px")
farm_id role sex birth_year edu chickens pigs cattle ducks muscovy geese dogs cats buffalo goats rabbits area_farm product1 product2 product3 product4 product5 product6 virus bacteria resistant_body resistant_bacteria transmission residue synonym abu_general decision advice1 advice2 advice3 purpose_antibiotic___1 purpose_antibiotic___2 purpose_antibiotic___3 purpose_antibiotic___99 purpose_antibiotic_other dosage___1 dosage___2 dosage___3 dosage___99 dosage_other combination combination_other chlo nitr dime metr cipr oflo carb olaq baci withdrawal withdrawal_other species abu_chicken abu_pig abu_cattle district commune
40177 2 2 1973 3 60 0 0 0 0 0 1 1 0 0 0 250 1 1 1 1 2 2 1 1 2 1 1 1 1 2 2 Cửa hàng thuốc thú y Thú y xã 0 1 1 0 0 1 0 0 1 theo hướng dẫn của cửa hàng thuốc thú y 2 2 2 2 2 2 2 2 2 2 99 15-20 ngày 1 1 NA NA 4 1
40178 1 1 1954 2 30 0 0 4 0 0 1 0 0 0 0 432 1 1 1 1 1 1 1 1 1 3 3 1 2 2 2 Cửa hàng thuốc thú y 0 0 1 0 0 0 0 0 0 1 theo hướng dẫn của cửa hàng thuốc thú y 99 không rõ 2 2 2 2 2 2 2 2 2 99 15 ngày 1 1 NA NA 4 1
40179 1 1 1962 3 40 33 0 0 30 0 2 0 0 0 0 700 2 1 1 1 2 1 1 1 1 2 2 1 2 2 2 Cửa hàng thuốc thú y 0 0 1 1 0 0 0 0 0 1 theo hướng dẫn của cửa hàng thuốc thú y 3 2 2 2 2 2 2 2 2 2 99 10-15 ngày 2 NA 1 NA 4 1
40180 2 2 1962 3 20 4 0 0 0 0 2 0 0 0 0 700 1 1 1 1 2 2 1 1 2 1 2 1 2 2 2 Cửa hàng thuốc thú y 0 0 1 1 0 0 0 0 0 1 theo hướng dẫn của cửa hàng thuốc thú y 3 2 2 2 2 2 2 2 2 2 99 1 tháng trở lên 1 3 NA NA 4 1
40329 1 1 1969 3 0 10 0 0 0 0 0 0 0 0 0 1000 1 1 1 1 2 2 2 1 3 3 1 1 1 2 1 1 0 0 0 1 0 0 0 1 2 2 2 2 2 2 2 2 2 2 2 NA 1 NA 4 3
40334 1 1 1974 3 20 0 0 0 0 0 0 0 0 0 0 7200 1 1 1 1 2 2 2 1 1 1 1 1 1 2 2 Cửa hàng thuốc thú y bác sĩ thú y kinh nghiệm bản thân 1 0 0 0 1 0 0 0 1 2 2 2 2 2 2 2 2 3 99 trước 1 tháng 1 1 NA NA 4 3
40342 1 2 1994 3 0 20 0 0 0 0 0 0 0 0 0 800 1 1 1 1 2 2 2 1 1 1 1 1 1 1 NA 0 0 0 0 0 0 0 0 NA NA NA NA NA NA NA NA NA NA NA 2 NA 1 NA 4 3
40426 2 2 1987 3 2 5 0 3 0 0 2 2 0 0 0 1000 1 1 1 3 2 1 1 1 1 1 1 1 3 2 2 người bán thuốc người chăm nuôi khác không 1 0 0 0 1 0 0 0 1 2 2 2 2 2 2 2 2 2 99 ngưng sử dụng thuốc trước 1 tháng 2 NA 1 NA 4 4
40463 2 2 1993 7 20 16 0 10 20 0 2 2 0 0 0 1500 1 2 2 1 2 2 1 1 1 2 1 1 1 2 1 1 0 0 0 1 0 0 0 2 2 2 2 2 2 2 2 2 2 99 ngưng khoảng 1 tháng 2 NA 1 NA 4 4
40477 2 2 1971 4 20 0 0 0 0 0 2 0 0 0 0 1000 1 2 1 2 2 2 3 3 1 3 1 1 3 2 2 Cửa hàng thuốc thú y cán bộ thú y xã người chăn nuôi xung quanh 1 0 0 0 1 0 0 0 99 không rõ,người bán bán cho về dùng nên không để ý 2 2 2 2 2 2 2 2 2 1 1 1 NA NA 4 4
head(household_data, n = 10) %>% 
  dplyr::select(district, commune, village_x, starts_with("q7_1___"), 
                starts_with("q7_11___"), q7_17_lastab_n, 
                starts_with("q7_18_lastillness___"),
                starts_with("q7_19___"), q7_20_prescribe_n,
                q7_21_days, q7_22_stop_n, q7_23_timesab) %>% 
  kable() %>% 
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE) %>%
  scroll_box(width = "100%")
district commune village_x q7_1___0 q7_1___1 q7_1___2 q7_1___3 q7_1___4 q7_1___5 q7_1___6 q7_1___7 q7_1___8 q7_1___9 q7_1___10 q7_11___0 q7_11___1 q7_11___2 q7_11___3 q7_11___4 q7_11___5 q7_11___6 q7_11___7 q7_11___8 q7_11___9 q7_11___10 q7_11___11 q7_11___12 q7_11___13 q7_11___14 q7_11___15 q7_11___16 q7_11___17 q7_11___18 q7_11___19 q7_11___20 q7_11___21 q7_11___22 q7_11___23 q7_11___24 q7_11___25 q7_11___26 q7_11___97 q7_11___99 q7_17_lastab_n q7_18_lastillness___1 q7_18_lastillness___2 q7_18_lastillness___3 q7_18_lastillness___4 q7_18_lastillness___5 q7_18_lastillness___6 q7_18_lastillness___7 q7_18_lastillness___8 q7_18_lastillness___9 q7_18_lastillness___10 q7_18_lastillness___11 q7_18_lastillness___12 q7_18_lastillness___100 q7_18_lastillness___97 q7_18_lastillness___99 q7_19___1 q7_19___2 q7_19___3 q7_19___4 q7_19___5 q7_19___6 q7_19___7 q7_19___8 q7_19___9 q7_19___97 q7_19___99 q7_20_prescribe_n q7_21_days q7_22_stop_n q7_23_timesab
4 1 Xóm 4a 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NA NA
4 1 Xóm 4a 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NA NA
4 1 Xóm 4a 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NA NA
4 1 Xóm 4a 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NA NA
4 1 Xóm 4a 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NA NA
4 1 Xóm 4a 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NA NA
4 1 Xóm 4a 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NA NA
4 1 Xóm 4a 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NA NA
4 1 Xóm 4a 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NA NA
4 1 Xóm 4a 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 NA NA

1.2.3 Data Cleaning and Preparation

# Examine the structure of data to understand variable names
household_vars <- names(household_data)
farm_vars <- names(farm_data)

# Print first few variable names to inspect the pattern
cat("First few household variables:", head(household_vars), "\n")
## First few household variables: record_id record_id_n redcap_repeat_instrument redcap_repeat_instance thng_tin_chung_timestamp int_date
cat("First few farm variables:", head(farm_vars), "\n")
## First few farm variables: record_id redcap_survey_identifier all_farmers_timestamp farm_id enumerator date
# Check for variables related to antibiotic use in household data
household_ab_vars <- grep("q7_11___", household_vars, value = TRUE)
cat("Household antibiotic variables:", household_ab_vars, "\n")
## Household antibiotic variables: q7_11___0 q7_11___1 q7_11___2 q7_11___3 q7_11___4 q7_11___5 q7_11___6 q7_11___7 q7_11___8 q7_11___9 q7_11___10 q7_11___11 q7_11___12 q7_11___13 q7_11___14 q7_11___15 q7_11___16 q7_11___17 q7_11___18 q7_11___19 q7_11___20 q7_11___21 q7_11___22 q7_11___23 q7_11___24 q7_11___25 q7_11___26 q7_11___97 q7_11___99
# Check for variables related to antibiotic use purpose in farm data
farm_ab_purpose_vars <- grep("purpose_antibiotic___", farm_vars, value = TRUE)
cat("Farm antibiotic purpose variables:", farm_ab_purpose_vars, "\n")
## Farm antibiotic purpose variables: purpose_antibiotic___1 purpose_antibiotic___2 purpose_antibiotic___3 purpose_antibiotic___99
# Check for specific antibiotic use variables in farm data
farm_specific_ab_vars <- grep("^(chlo|nitr|dime|metr|cipr|oflo|carb|olaq|baci)$", farm_vars, value = TRUE)
cat("Farm specific antibiotic variables:", farm_specific_ab_vars, "\n")
## Farm specific antibiotic variables: chlo nitr dime metr cipr oflo carb olaq baci
# Check for variables related to farm characteristics
farm_animal_vars <- c("chickens", "pigs", "cattle", "ducks", "muscovy", "geese")
farm_animal_vars_exist <- farm_animal_vars %in% farm_vars
names(farm_animal_vars_exist) <- farm_animal_vars
cat("Farm animal variables exist:", farm_animal_vars_exist, "\n")
## Farm animal variables exist: TRUE TRUE TRUE TRUE TRUE TRUE
## Define antibiotic types based on variable inspection
# This list should be adjusted based on actual data structure
# Assuming q7_11___1 to q7_11___13 represent different antibiotics
antibiotic_options <- grep("q7_11___[1-9]|q7_11___1[0-3]", household_vars, value = TRUE)

# Define which options are antibiotics vs. other treatments
# This requires knowledge of the survey coding
antibiotic_vars <- c(
  "q7_11___1",  # Amoxicillin
  "q7_11___2",  # Ampicillin
  "q7_11___3",  # Amoxicillin-clavulanic acid
  "q7_11___4",  # Azithromycin/Erythromycin
  "q7_11___5",  # Cefalexin
  "q7_11___6",  # Cefixime
  "q7_11___7",  # Cefuroxim
  "q7_11___8",  # Ciprofloxacin/Levofloxacin
  "q7_11___9",  # Cotrimoxazole
  "q7_11___10", # Metronidazole
  "q7_11___11", # Penicillin
  "q7_11___12", # Another antibiotic pill/syrup/powder
  "q7_11___13"  # Antibiotic injection or IV fluid
)

# Check if these variables exist in the dataset
antibiotic_vars_exist <- antibiotic_vars %in% household_vars
if(any(!antibiotic_vars_exist)) {
  warning("Some expected antibiotic variables don't exist in the dataset. Please check variable names.")
  print(antibiotic_vars[!antibiotic_vars_exist])
}

## Create derived variables for farm data
farm_data <- farm_data %>%
  mutate(
    # Binary indicator for any antibiotic use
    any_ab_use = ifelse(abu_general == 2, 1, 0),
    
    # Create indicators for different antibiotic use purposes
    # Check if these are binary variables or multiple selection variables
    ab_treatment = ifelse(purpose_antibiotic___1 == 1, 1, 0),
    ab_prevention = ifelse(purpose_antibiotic___2 == 1, 1, 0),
    ab_growth = ifelse(purpose_antibiotic___3 == 1, 1, 0),
    
    # Create a summary variable for total number of purposes
    ab_purpose_count = ab_treatment + ab_prevention + ab_growth,
    
    # Farm size categories based on area_farm
    farm_size_cat = case_when(
      area_farm < 100 ~ "Small",
      area_farm >= 100 & area_farm < 1000 ~ "Medium",
      area_farm >= 1000 ~ "Large",
      TRUE ~ NA_character_
    ),
    
    # Animal type categories based on species
    animal_type = case_when(
      species == 1 ~ "Chicken",
      species == 2 ~ "Pig",
      species == 3 ~ "Cattle",
      TRUE ~ NA_character_
    ),
    
    # Create variable for restricted antibiotics use (antibiotics that should be restricted)
    # These are antibiotics that are particularly concerning for AMR
    restricted_ab_use = ifelse(chlo == 1 | cipr == 1 | oflo == 1, 1, 0)
  )

## Create derived variables for household data
# First, check how the antibiotic use variables are coded
if(length(antibiotic_vars) > 0) {
  # Check first few rows of first antibiotic variable
  ab_var_sample <- head(household_data[[antibiotic_vars[1]]])
  cat("Sample values for first antibiotic variable:", ab_var_sample, "\n")
  
  # Determine conversion function based on the variable type
  if(is.character(ab_var_sample)) {
    # If character (Yes/No), convert to binary
    convert_fn <- function(x) ifelse(x == "Yes", 1, 0)
  } else {
    # If already numeric (1/0), use as is
    convert_fn <- function(x) x
  }
  
  # Create derived variables
  household_data <- household_data %>%
    mutate(
      # Create binary indicator for any antibiotic use
      # Sum across all antibiotic variables and check if > 0
      any_ab_last_illness = case_when(
        rowSums(across(all_of(antibiotic_vars), ~convert_fn(.)), na.rm = TRUE) > 0 ~ 1,
        TRUE ~ 0
      ),
      
      # Create numeric versions of all antibiotic variables
      across(all_of(antibiotic_vars), ~convert_fn(.), .names = "num_{.col}")
    )
  
  # Check for recent illness variables
  illness_vars <- grep("q7_1___", household_vars, value = TRUE)
  
  if(length(illness_vars) > 0) {
    # Create illness type indicators
    household_data <- household_data %>%
      mutate(
        # Respiratory illness indicator
        resp_illness = case_when(
          rowSums(across(c("q7_1___2", "q7_1___4", "q7_1___5"), ~convert_fn(.)), na.rm = TRUE) > 0 ~ 1,
          TRUE ~ 0
        ),
        
        # Gastrointestinal illness indicator
        gi_illness = case_when(
          rowSums(across(c("q7_1___6", "q7_1___7"), ~convert_fn(.)), na.rm = TRUE) > 0 ~ 1,
          TRUE ~ 0
        ),
        
        # Fever indicator
        fever = convert_fn(q7_1___1)
      )
  }
}
## Sample values for first antibiotic variable: 0 0 0 0 0 0
## Create geographic linkage if possible
# Check if we have matching geographic variables
if(all(c("district", "commune") %in% farm_vars) && 
   all(c("district", "commune") %in% household_vars)) {
  
  # Create geographic ID for linkage
  farm_data <- farm_data %>%
    mutate(geo_id = paste(district, commune, sep = "_"))
  
  household_data <- household_data %>%
    mutate(geo_id = paste(district, commune, sep = "_"))
  
} else {
  # If standard geographic variables don't exist, check for alternatives
  warning("Standard geographic variables not found. Community-level analysis may not be possible.")
  
  # Try to use farm_id to extract geographic information if it follows a pattern
  # This is just an example and would need to be adjusted based on actual ID structure
  if("farm_id" %in% farm_vars) {
    farm_data <- farm_data %>%
      mutate(
        # Extract first part of farm_id as geographic identifier
        # This assumes farm_id has a structure where the first digits represent location
        geo_id = substr(as.character(farm_id), 1, 5)
      )
  }
}

## Check for missing values in key variables
# Farm data
farm_missing <- farm_data %>%
  dplyr::select(any_ab_use, ab_treatment, ab_prevention, ab_growth, animal_type, farm_size_cat) %>%
  summarise(across(everything(), ~sum(is.na(.)), .names = "missing_{.col}"))

# Display missing values summary
print("Missing values in key farm variables:")
## [1] "Missing values in key farm variables:"
print(farm_missing)
## # A tibble: 1 × 6
##   missing_any_ab_use missing_ab_treatment missing_ab_prevention
##                <int>                <int>                 <int>
## 1                  0                    0                     0
## # ℹ 3 more variables: missing_ab_growth <int>, missing_animal_type <int>,
## #   missing_farm_size_cat <int>
# Household data
if(exists("any_ab_last_illness", where = household_data)) {
  household_missing <- household_data %>%
    dplyr::select(any_ab_last_illness, matches("num_q7_11___")) %>%
    summarise(across(everything(), ~sum(is.na(.)), .names = "missing_{.col}"))
  
  print("Missing values in key household variables:")
  print(household_missing)
}
## [1] "Missing values in key household variables:"
## # A tibble: 1 × 14
##   missing_any_ab_last_illness missing_num_q7_11___1 missing_num_q7_11___2
##                         <int>                 <int>                 <int>
## 1                           0                     5                     5
## # ℹ 11 more variables: missing_num_q7_11___3 <int>,
## #   missing_num_q7_11___4 <int>, missing_num_q7_11___5 <int>,
## #   missing_num_q7_11___6 <int>, missing_num_q7_11___7 <int>,
## #   missing_num_q7_11___8 <int>, missing_num_q7_11___9 <int>,
## #   missing_num_q7_11___10 <int>, missing_num_q7_11___11 <int>,
## #   missing_num_q7_11___12 <int>, missing_num_q7_11___13 <int>
# Summary statistics on derived variables
farm_summary <- farm_data %>%
  summarise(
    n = n(),
    ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
    treatment_pct = mean(ab_treatment, na.rm = TRUE) * 100,
    prevention_pct = mean(ab_prevention, na.rm = TRUE) * 100,
    growth_pct = mean(ab_growth, na.rm = TRUE) * 100,
    restricted_ab_pct = mean(restricted_ab_use, na.rm = TRUE) * 100
  )

print("Summary of farm antibiotic use:")
## [1] "Summary of farm antibiotic use:"
print(farm_summary)
## # A tibble: 1 × 6
##       n ab_use_pct treatment_pct prevention_pct growth_pct restricted_ab_pct
##   <int>      <dbl>         <dbl>          <dbl>      <dbl>             <dbl>
## 1  1156       94.2          89.4           48.3      0.865              1.01
household_summary <- household_data %>%
  summarise(
    n = n(),
    ab_use_pct = mean(any_ab_last_illness, na.rm = TRUE) * 100
  )

print("Summary of household antibiotic use:")
## [1] "Summary of household antibiotic use:"
print(household_summary)
## # A tibble: 1 × 2
##       n ab_use_pct
##   <int>      <dbl>
## 1  9411       5.54
# Check the distribution of farm sizes and animal types
farm_size_dist <- farm_data %>%
  count(farm_size_cat) %>%
  mutate(pct = n / sum(n) * 100)

animal_type_dist <- farm_data %>%
  count(animal_type) %>%
  mutate(pct = n / sum(n) * 100)

print("Distribution of farm sizes:")
## [1] "Distribution of farm sizes:"
print(farm_size_dist)
## # A tibble: 3 × 3
##   farm_size_cat     n   pct
##   <chr>         <int> <dbl>
## 1 Large           485 42.0 
## 2 Medium          659 57.0 
## 3 Small            12  1.04
print("Distribution of animal types:")
## [1] "Distribution of animal types:"
print(animal_type_dist)
## # A tibble: 3 × 3
##   animal_type     n   pct
##   <chr>       <int> <dbl>
## 1 Cattle         85  7.35
## 2 Chicken       431 37.3 
## 3 Pig           640 55.4
# Save the processed data for subsequent analyses
# This allows us to checkpoint our progress
saveRDS(farm_data, here("Data", "processed", "farm_data_processed.rds"))
saveRDS(household_data, here("Data", "processed", "household_data_processed.rds"))

1.3 Results for Hypothesis 1.1: Prevalence of Antibiotic Use in Farms and Households

# =========================================================================
# RESEARCH QUESTION 1: HYPOTHESIS 1.1 ANALYSIS
# Preventive and growth-promoting antibiotic use is common in farm animals,
# with prevalence rates higher than corresponding use in human medicine
# =========================================================================

theme_set(
  theme_minimal(base_size = 12) + 
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major.x = element_blank(),
    panel.grid.major.y = element_line(color = "gray95", linewidth = 0.3),
    axis.text = element_text(color = "black", size = 9),
    axis.title = element_text(size = 10, face = "bold"),
    plot.title = element_text(size = 11, face = "bold"),
    plot.subtitle = element_text(size = 9, face = "italic", color = "gray30"),
    legend.position = "bottom",
    legend.title = element_text(size = 9),
    legend.text = element_text(size = 8),
    panel.border = element_rect(color = "white", fill = NA, linewidth = 0.5),
    strip.background = element_rect(fill = "white", color = NA),
    strip.text = element_text(size = 9, face = "bold", color = "gray30")
  )
)

low_sat_palette <- c("#a8c0e0", "#e0b5a8", "#a8d3b5", "#c3b5d3", "#d8cfb0", "#a9d0d3")

# -------------------------------------------------------------------------
# 1. DATA PREPARATION
# -------------------------------------------------------------------------

# Load datasets if not already in memory
if (!exists("farm_data")) {
  farm_data <- readRDS(here("Data", "processed", "farm_data_processed.rds"))
}
if (!exists("household_data")) {
  household_data <- readRDS(here("Data", "processed", "household_data_processed.rds"))
}

# Verify key variables in farm data
farm_vars_check <- c("any_ab_use", "ab_treatment", "ab_prevention", "ab_growth", 
                     "chlo", "nitr", "dime", "metr", "cipr", "oflo", "carb", "olaq", "baci")
missing_farm_vars <- farm_vars_check[!farm_vars_check %in% names(farm_data)]
if(length(missing_farm_vars) > 0) {
  warning(paste("Missing farm data variables:", paste(missing_farm_vars, collapse=", ")))
}

# Verify key variables in household data
household_vars_check <- c("any_ab_last_illness")
missing_household_vars <- household_vars_check[!household_vars_check %in% names(household_data)]
if(length(missing_household_vars) > 0) {
  warning(paste("Missing household data variables:", paste(missing_household_vars, collapse=", ")))
}

# Check for symptom-related variables in household data
symptom_vars <- grep("q7_1___", names(household_data), value = TRUE)
if(length(symptom_vars) == 0) {
  warning("No symptom variables found in household data. Cannot create preventive use proxy.")
}

# -------------------------------------------------------------------------
# 2. FARM ANTIBIOTIC USE PREVALENCE ANALYSIS
# -------------------------------------------------------------------------

# 2.1 Calculate farm antibiotic use prevalence with confidence intervals
farm_ab_ci <- farm_data %>%
  summarise(
    n = n(),
    ab_use = sum(any_ab_use, na.rm = TRUE),
    ab_treatment = sum(ab_treatment, na.rm = TRUE),
    ab_prevention = sum(ab_prevention, na.rm = TRUE),
    ab_growth = sum(ab_growth, na.rm = TRUE)
  ) %>%
  mutate(
    # Overall use with confidence intervals
    ab_use_pct = ab_use / n * 100,
    ab_use_ci_lower = binom.confint(ab_use, n, method = "wilson")$lower * 100,
    ab_use_ci_upper = binom.confint(ab_use, n, method = "wilson")$upper * 100,
    
    # Treatment use with confidence intervals
    ab_treatment_pct = ab_treatment / n * 100,
    ab_treatment_ci_lower = binom.confint(ab_treatment, n, method = "wilson")$lower * 100,
    ab_treatment_ci_upper = binom.confint(ab_treatment, n, method = "wilson")$upper * 100,
    
    # Preventive use with confidence intervals
    ab_prevention_pct = ab_prevention / n * 100,
    ab_prevention_ci_lower = binom.confint(ab_prevention, n, method = "wilson")$lower * 100,
    ab_prevention_ci_upper = binom.confint(ab_prevention, n, method = "wilson")$upper * 100,
    
    # Growth promotion use with confidence intervals
    ab_growth_pct = ab_growth / n * 100,
    ab_growth_ci_lower = binom.confint(ab_growth, n, method = "wilson")$lower * 100,
    ab_growth_ci_upper = binom.confint(ab_growth, n, method = "wilson")$upper * 100
  )

# 2.2 Calculate non-treatment antibiotic use in farms
farm_non_treatment <- farm_data %>%
  summarise(
    n = n(),
    any_non_treatment = sum(ab_prevention == 1 | ab_growth == 1, na.rm = TRUE),
    prevention_only = sum(ab_prevention == 1 & ab_treatment == 0 & ab_growth == 0, na.rm = TRUE),
    growth_only = sum(ab_growth == 1 & ab_treatment == 0 & ab_prevention == 0, na.rm = TRUE),
    both_purposes = sum(ab_prevention == 1 & ab_growth == 1 & ab_treatment == 0, na.rm = TRUE)
  ) %>%
  mutate(
    # Calculate percentages
    any_non_treatment_pct = any_non_treatment / n * 100,
    prevention_only_pct = prevention_only / n * 100,
    growth_only_pct = growth_only / n * 100,
    both_purposes_pct = both_purposes / n * 100,
    
    # Calculate confidence intervals
    any_non_treatment_ci_lower = binom.confint(any_non_treatment, n, method = "wilson")$lower * 100,
    any_non_treatment_ci_upper = binom.confint(any_non_treatment, n, method = "wilson")$upper * 100,
    prevention_only_ci_lower = binom.confint(prevention_only, n, method = "wilson")$lower * 100,
    prevention_only_ci_upper = binom.confint(prevention_only, n, method = "wilson")$upper * 100,
    growth_only_ci_lower = binom.confint(growth_only, n, method = "wilson")$lower * 100,
    growth_only_ci_upper = binom.confint(growth_only, n, method = "wilson")$upper * 100,
    both_purposes_ci_lower = binom.confint(both_purposes, n, method = "wilson")$lower * 100,
    both_purposes_ci_upper = binom.confint(both_purposes, n, method = "wilson")$upper * 100
  )

# 2.3 Display farm antibiotic use table
farm_ab_table <- data.frame(
  Purpose = c("Any use", "Treatment", "Prevention", "Growth promotion"),
  Count = c(farm_ab_ci$ab_use, farm_ab_ci$ab_treatment, 
            farm_ab_ci$ab_prevention, farm_ab_ci$ab_growth),
  Percentage = c(farm_ab_ci$ab_use_pct, farm_ab_ci$ab_treatment_pct, 
                farm_ab_ci$ab_prevention_pct, farm_ab_ci$ab_growth_pct),
  CI_Lower = c(farm_ab_ci$ab_use_ci_lower, farm_ab_ci$ab_treatment_ci_lower, 
              farm_ab_ci$ab_prevention_ci_lower, farm_ab_ci$ab_growth_ci_lower),
  CI_Upper = c(farm_ab_ci$ab_use_ci_upper, farm_ab_ci$ab_treatment_ci_upper, 
              farm_ab_ci$ab_prevention_ci_upper, farm_ab_ci$ab_growth_ci_upper)
) %>%
  mutate(
    CI = paste0(round(CI_Lower, 1), "-", round(CI_Upper, 1)),
    `Prevalence (95% CI)` = paste0(round(Percentage, 1), "% (", CI, ")")
  )

# Display farm antibiotic use table
kable(farm_ab_table %>% dplyr::select(Purpose, Count, `Prevalence (95% CI)`),
      caption = "Farm Antibiotic Use Prevalence with 95% Confidence Intervals",
      align = "lrr") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Farm Antibiotic Use Prevalence with 95% Confidence Intervals
Purpose Count Prevalence (95% CI)
Any use 1089 94.2% (92.7-95.4)
Treatment 1033 89.4% (87.5-91)
Prevention 558 48.3% (45.4-51.2)
Growth promotion 10 0.9% (0.5-1.6)
# -------------------------------------------------------------------------
# 3. HOUSEHOLD ANTIBIOTIC USE PREVALENCE ANALYSIS
# -------------------------------------------------------------------------

# 3.1 Calculate household antibiotic use prevalence with confidence intervals
household_ab_ci <- household_data %>%
  summarise(
    n = n(),
    ab_use = sum(any_ab_last_illness, na.rm = TRUE)
  ) %>%
  mutate(
    # Overall use with confidence intervals
    ab_use_pct = ab_use / n * 100,
    ab_use_ci_lower = binom.confint(ab_use, n, method = "wilson")$lower * 100,
    ab_use_ci_upper = binom.confint(ab_use, n, method = "wilson")$upper * 100
  )

# 3.2 Display household antibiotic use
household_ab_table <- data.frame(
  Purpose = "Any use",
  Count = household_ab_ci$ab_use,
  Percentage = household_ab_ci$ab_use_pct,
  CI_Lower = household_ab_ci$ab_use_ci_lower,
  CI_Upper = household_ab_ci$ab_use_ci_upper
) %>%
  mutate(
    CI = paste0(round(CI_Lower, 1), "-", round(CI_Upper, 1)),
    `Prevalence (95% CI)` = paste0(round(Percentage, 1), "% (", CI, ")")
  )

kable(household_ab_table %>% dplyr::select(Purpose, Count, `Prevalence (95% CI)`),
      caption = "Household Antibiotic Use Prevalence with 95% Confidence Intervals",
      align = "lrr") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Household Antibiotic Use Prevalence with 95% Confidence Intervals
Purpose Count Prevalence (95% CI)
Any use 521 5.5% (5.1-6)
# -------------------------------------------------------------------------
# 4. CREATING HOUSEHOLD PREVENTIVE USE PROXY INDICATOR
# -------------------------------------------------------------------------

# 4.1 Create symptom indicators 
# Helper function to safely check if a variable indicates a symptom
is_symptom_positive <- function(data, var_name) {
  # Check if variable exists
  if(!(var_name %in% names(data))) {
    return(rep(FALSE, nrow(data)))
  }
  
  # Get the variable
  var_data <- data[[var_name]]
  
  # Handle different data types
  result <- rep(FALSE, length(var_data))
  
  for(i in 1:length(var_data)) {
    val <- var_data[i]
    
    # Skip NA values
    if(is.na(val)) {
      result[i] <- FALSE
      next
    }
    
    # Handle character values
    if(is.character(val)) {
      result[i] <- (val == "Yes")
      next
    }
    
    # Handle numeric values
    if(is.numeric(val)) {
      result[i] <- (val == 1)
      next
    }
    
    # Default for other types
    result[i] <- FALSE
  }
  
  return(result)
}

# Create indicator variables for different symptom types
n_rows <- nrow(household_data)

# Initialize flags
has_fever <- rep(FALSE, n_rows)
has_resp <- rep(FALSE, n_rows)
has_gi <- rep(FALSE, n_rows)
has_any <- rep(FALSE, n_rows)

# Fever - variable q7_1___1 (adjust variable names if needed)
fever_var <- "q7_1___1"
if(fever_var %in% symptom_vars) {
  has_fever <- is_symptom_positive(household_data, fever_var)
}

# Respiratory symptoms - variables q7_1___2, q7_1___4, q7_1___5 (adjust as needed)
resp_vars <- c("q7_1___2", "q7_1___4", "q7_1___5")
for(var in intersect(resp_vars, symptom_vars)) {
  has_resp <- has_resp | is_symptom_positive(household_data, var)
}

# GI symptoms - variables q7_1___6, q7_1___7 (adjust as needed)
gi_vars <- c("q7_1___6", "q7_1___7")
for(var in intersect(gi_vars, symptom_vars)) {
  has_gi <- has_gi | is_symptom_positive(household_data, var)
}

# Any symptom - check all symptom variables
for(var in symptom_vars) {
  has_any <- has_any | is_symptom_positive(household_data, var)
}

# Add flags to the dataset
household_data$fever_indicator <- as.integer(has_fever)
household_data$resp_indicator <- as.integer(has_resp)
household_data$gi_indicator <- as.integer(has_gi)
household_data$any_symptom <- as.integer(has_any)

# 4.2 Create the primary preventive use proxy indicator (stringent definition)
household_data <- household_data %>%
  mutate(
    # Stringent definition: AB use with NO symptoms at all
    preventive_use_proxy_stringent = case_when(
      any_ab_last_illness == 1 & any_symptom == 0 ~ 1,
      TRUE ~ 0
    ),
    
    # Alternative definition: AB use with only minor symptoms 
    # (no fever, no respiratory symptoms, no GI symptoms)
    preventive_use_proxy_relaxed = case_when(
      any_ab_last_illness == 1 & fever_indicator == 0 & 
        resp_indicator == 0 & gi_indicator == 0 ~ 1,
      TRUE ~ 0
    )
  )

# 4.3 Calculate household preventive use statistics - primary definition
household_preventive_stringent <- household_data %>%
  summarise(
    n = n(),
    preventive_n = sum(preventive_use_proxy_stringent, na.rm = TRUE),
    preventive_pct = mean(preventive_use_proxy_stringent, na.rm = TRUE) * 100
  )

# Add confidence intervals
ci_stringent <- binom.test(household_preventive_stringent$preventive_n, 
                         household_preventive_stringent$n)$conf.int * 100
household_preventive_stringent$preventive_ci_lower <- ci_stringent[1]
household_preventive_stringent$preventive_ci_upper <- ci_stringent[2]

# 4.4 Calculate household preventive use with alternative definition
household_preventive_relaxed <- household_data %>%
  summarise(
    n = n(),
    preventive_n = sum(preventive_use_proxy_relaxed, na.rm = TRUE),
    preventive_pct = mean(preventive_use_proxy_relaxed, na.rm = TRUE) * 100
  )

# Add confidence intervals
ci_relaxed <- binom.test(household_preventive_relaxed$preventive_n, 
                       household_preventive_relaxed$n)$conf.int * 100
household_preventive_relaxed$preventive_ci_lower <- ci_relaxed[1]
household_preventive_relaxed$preventive_ci_upper <- ci_relaxed[2]

# Display results for both definitions
cat("\nHousehold Preventive Antibiotic Use - Sensitivity Analysis:\n")
## 
## Household Preventive Antibiotic Use - Sensitivity Analysis:
cat("1. Stringent definition (NO symptoms):\n")
## 1. Stringent definition (NO symptoms):
cat("   Count:", household_preventive_stringent$preventive_n, "out of", 
    household_preventive_stringent$n, "households\n")
##    Count: 0 out of 9411 households
cat("   Percentage:", round(household_preventive_stringent$preventive_pct, 1), 
    "% (95% CI:", round(household_preventive_stringent$preventive_ci_lower, 1), "-", 
    round(household_preventive_stringent$preventive_ci_upper, 1), "%)\n\n")
##    Percentage: 0 % (95% CI: 0 - 0 %)
cat("2. Relaxed definition (minor or no symptoms):\n")
## 2. Relaxed definition (minor or no symptoms):
cat("   Count:", household_preventive_relaxed$preventive_n, "out of", 
    household_preventive_relaxed$n, "households\n")
##    Count: 7 out of 9411 households
cat("   Percentage:", round(household_preventive_relaxed$preventive_pct, 1), 
    "% (95% CI:", round(household_preventive_relaxed$preventive_ci_lower, 1), "-", 
    round(household_preventive_relaxed$preventive_ci_upper, 1), "%)\n")
##    Percentage: 0.1 % (95% CI: 0 - 0.2 %)
# For subsequent analyses, use the stringent definition as primary
household_preventive <- household_preventive_stringent

# -------------------------------------------------------------------------
# 5. ANALYSIS BY SYMPTOM/DISEASE STATUS
# -------------------------------------------------------------------------

# 5.1 Create breakdown of household antibiotic use by symptom status
household_by_symptom <- household_data %>%
  mutate(
    symptom_status = case_when(
      resp_indicator == 1 ~ "Respiratory symptoms",
      gi_indicator == 1 ~ "GI symptoms",
      fever_indicator == 1 ~ "Fever",
      any_symptom == 1 ~ "Other symptoms",
      TRUE ~ "No symptoms"
    )
  ) %>%
  group_by(symptom_status) %>%
  summarise(
    n = n(),
    ab_use_n = sum(any_ab_last_illness, na.rm = TRUE),
    ab_use_pct = mean(any_ab_last_illness, na.rm = TRUE) * 100,
    .groups = "drop"
  )

# Calculate confidence intervals
household_by_symptom <- household_by_symptom %>%
  mutate(
    # Calculate CIs using a more robust method
    ab_use_ci_lower = mapply(function(x, n) {
      if(n == 0) return(0)
      ci <- binom.test(x, n)$conf.int
      return(ci[1] * 100)
    }, ab_use_n, n),
    
    ab_use_ci_upper = mapply(function(x, n) {
      if(n == 0) return(0)
      ci <- binom.test(x, n)$conf.int
      return(ci[2] * 100)
    }, ab_use_n, n),
    
    # Format the CI string properly, handling any NA values
    CI = ifelse(is.na(ab_use_ci_upper), 
                paste0(round(ab_use_ci_lower, 1), "-?"), 
                paste0(round(ab_use_ci_lower, 1), "-", round(ab_use_ci_upper, 1))),
    
    `Prevalence (95% CI)` = paste0(round(ab_use_pct, 1), "% (", CI, ")")
  )
ci_data <- binom.confint(household_by_symptom$ab_use_n, household_by_symptom$n, 
                        method = "wilson", conf.level = 0.95)
household_by_symptom$ab_use_ci_lower <- ci_data$lower * 100
household_by_symptom$ab_use_ci_upper <- ci_data$upper * 100

# Display the results
kable(household_by_symptom %>% 
        dplyr::select(symptom_status, n, ab_use_n, `Prevalence (95% CI)`),
      caption = "Household Antibiotic Use by Symptom Status",
      col.names = c("Symptom Status", "Sample Size", "AB Users", "Prevalence (95% CI)"),
      align = "lrrr") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Household Antibiotic Use by Symptom Status
Symptom Status Sample Size AB Users Prevalence (95% CI)
Fever 94 30 31.9% (22.7-42.3)
GI symptoms 36 16 44.4% (27.9-61.9)
No symptoms 6 0 0% (0-45.9)
Other symptoms 8381 7 0.1% (0-0.2)
Respiratory symptoms 894 468 52.3% (49-55.7)
# -------------------------------------------------------------------------
# 6. COMPARATIVE ANALYSIS OF FARM VS HOUSEHOLD ANTIBIOTIC USE
# -------------------------------------------------------------------------

# 6.1 Comparison of overall antibiotic use
# Create a contingency table
overall_table <- matrix(
  c(farm_ab_ci$ab_use, farm_ab_ci$n - farm_ab_ci$ab_use,
    household_ab_ci$ab_use, household_ab_ci$n - household_ab_ci$ab_use),
  nrow = 2,
  dimnames = list(
    c("Farm", "Household"),
    c("Antibiotic Use", "No Antibiotic Use")
  )
)

# Display the contingency table
kable(overall_table, caption = "Contingency Table for Overall Antibiotic Use") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE)
Contingency Table for Overall Antibiotic Use
Antibiotic Use No Antibiotic Use
Farm 1089 521
Household 67 8890
# Perform chi-square test
overall_chi <- chisq.test(overall_table)

# Calculate effect size (Phi coefficient)
overall_phi <- sqrt(overall_chi$statistic / sum(overall_table))

# Determine effect size interpretation
overall_effect <- case_when(
  abs(overall_phi) < 0.1 ~ "Negligible",
  abs(overall_phi) < 0.3 ~ "Small",
  abs(overall_phi) < 0.5 ~ "Medium",
  TRUE ~ "Large"
)

# 6.2 Comparison of preventive antibiotic use
# Create comparison data frame
preventive_comparison <- data.frame(
  Category = c("Farm Preventive Use", "Household Preventive Use (Proxy)"),
  Count = c(farm_ab_ci$ab_prevention, household_preventive$preventive_n),
  Total = c(farm_ab_ci$n, household_preventive$n),
  Percentage = c(farm_ab_ci$ab_prevention_pct, household_preventive$preventive_pct),
  CI_Lower = c(farm_ab_ci$ab_prevention_ci_lower, household_preventive$preventive_ci_lower),
  CI_Upper = c(farm_ab_ci$ab_prevention_ci_upper, household_preventive$preventive_ci_upper)
)

# Add formatted percentage and confidence intervals
preventive_comparison <- preventive_comparison %>%
  mutate(
    Percent_CI = paste0(
      round(Percentage, 1), "% (", 
      round(CI_Lower, 1), "-", 
      round(CI_Upper, 1), "%)"
    )
  )

# Display comparison table
kable(preventive_comparison %>% 
        dplyr::select(Category, Count, Total, Percent_CI),
      caption = "Comparison of Preventive Antibiotic Use in Farms and Households",
      col.names = c("Category", "Number of AB Users", "Total Sample", "Usage Rate (95% CI)"))
Comparison of Preventive Antibiotic Use in Farms and Households
Category Number of AB Users Total Sample Usage Rate (95% CI)
Farm Preventive Use 558 1156 48.3% (45.4-51.2%)
Household Preventive Use (Proxy) 0 9411 0% (0-0%)
# Create a contingency table for preventive use
preventive_table <- matrix(
  c(preventive_comparison$Count[1], preventive_comparison$Total[1] - preventive_comparison$Count[1],
    preventive_comparison$Count[2], preventive_comparison$Total[2] - preventive_comparison$Count[2]),
  nrow = 2,
  byrow = TRUE,
  dimnames = list(
    c("Farm", "Household"),
    c("Preventive Use", "No Preventive Use")
  )
)

# Perform chi-square test
preventive_chi <- chisq.test(preventive_table)

# Calculate effect size (Phi coefficient)
preventive_phi <- sqrt(preventive_chi$statistic / sum(preventive_table))

# Determine effect size interpretation
preventive_effect <- case_when(
  abs(preventive_phi) < 0.1 ~ "Negligible",
  abs(preventive_phi) < 0.3 ~ "Small",
  abs(preventive_phi) < 0.5 ~ "Medium",
  TRUE ~ "Large"
)

# Calculate the ratio of farm:household preventive use
preventive_ratio <- farm_ab_ci$ab_prevention_pct / household_preventive$preventive_pct

# 6.3 MULTILEVEL ANALYSIS OF ANTIBIOTIC USE
# Check if we have community identifiers
has_community_ids <- all(c("district", "commune") %in% names(farm_data)) && 
                     all(c("district", "commune") %in% names(household_data))

if(has_community_ids) {
  # Create community ID variable
  farm_data <- farm_data %>%
    mutate(community_id = paste(district, commune, sep = "_"))
  
  household_data <- household_data %>%
    mutate(community_id = paste(district, commune, sep = "_"))
  
  # Load required packages
  if(!require(lme4)) install.packages("lme4")
  library(lme4)
  if(!require(performance)) install.packages("performance")
  library(performance)
  
  cat("\nMultilevel Analysis of Antibiotic Use:\n")
  
  # Check for sufficient communities
  farm_communities <- unique(farm_data$community_id)
  household_communities <- unique(household_data$community_id)
  
  cat("Number of communities in farm data:", length(farm_communities), "\n")
  cat("Number of communities in household data:", length(household_communities), "\n")
  
  # Proceed with multilevel modeling if we have sufficient communities (at least 10)
  if(length(farm_communities) >= 10) {
    # Farm multilevel model for any antibiotic use
    tryCatch({
      farm_mlm <- glmer(any_ab_use ~ 1 + (1|community_id), 
                      family = binomial, data = farm_data)
      
      farm_icc <- performance::icc(farm_mlm)
      cat("\nFarm antibiotic use - Intraclass Correlation Coefficient:", 
          round(farm_icc, 3), "\n")
      cat("This means approximately", round(farm_icc*100, 1), 
          "% of the variance in farm antibiotic use is attributable to community-level factors.\n")
      
      # Farm multilevel model for preventive use
      farm_prev_mlm <- glmer(ab_prevention ~ 1 + (1|community_id), 
                           family = binomial, data = farm_data)
      
      farm_prev_icc <- performance::icc(farm_prev_mlm)
      cat("\nFarm preventive use - Intraclass Correlation Coefficient:", 
          round(farm_prev_icc, 3), "\n")
      cat("This means approximately", round(farm_prev_icc*100, 1), 
          "% of the variance in farm preventive use is attributable to community-level factors.\n")
    }, error = function(e) {
      cat("Could not fit multilevel model for farm data:", e$message, "\n")
    })
  } else {
    cat("Insufficient number of communities for farm multilevel modeling.\n")
  }
  
  # Proceed with household multilevel modeling if we have sufficient communities
  if(length(household_communities) >= 10) {
    # Household multilevel model
    tryCatch({
      household_mlm <- glmer(any_ab_last_illness ~ 1 + (1|community_id), 
                           family = binomial, data = household_data)
      
      household_icc <- performance::icc(household_mlm)
      cat("\nHousehold antibiotic use - Intraclass Correlation Coefficient:", 
          round(household_icc, 3), "\n")
      cat("This means approximately", round(household_icc*100, 1), 
          "% of the variance in household antibiotic use is attributable to community-level factors.\n")
      
      # If we used the same communities, calculate correlation between community effects
      shared_communities <- intersect(farm_communities, household_communities)
      
      if(length(shared_communities) >= 5) {
        cat("\nAnalyzing correlation between community effects in farm and household antibiotic use:\n")
        
        # Extract random effects
        farm_ranef <- ranef(farm_mlm)$community_id
        household_ranef <- ranef(household_mlm)$community_id
        
        # Prepare data
        ranef_data <- data.frame(
          community_id = rownames(farm_ranef),
          farm_effect = farm_ranef[,1],
          stringsAsFactors = FALSE
        )
        
        household_effects <- data.frame(
          community_id = rownames(household_ranef),
          household_effect = household_ranef[,1],
          stringsAsFactors = FALSE
        )
        
        ranef_data <- ranef_data %>%
          inner_join(household_effects, by = "community_id")
        
        # Calculate correlation
        community_cor <- cor.test(ranef_data$farm_effect, ranef_data$household_effect, 
                                method = "spearman")
        
        cat("Correlation between community effects:", round(community_cor$estimate, 3), 
            "(p =", round(community_cor$p.value, 3), ")\n")
        
        if(community_cor$p.value < 0.05) {
          cat("This suggests significant community-level correlation between farm and household antibiotic use patterns.\n")
        } else {
          cat("No significant community-level correlation detected between farm and household antibiotic use patterns.\n")
        }
      }
    }, error = function(e) {
      cat("Could not fit multilevel model for household data:", e$message, "\n")
    })
  } else {
    cat("Insufficient number of communities for household multilevel modeling.\n")
  }
} else {
  cat("\nCommunity identifiers not available - multilevel analysis skipped.\n")
}
## 
## Multilevel Analysis of Antibiotic Use:
## Number of communities in farm data: 64 
## Number of communities in household data: 64 
## 
## Farm antibiotic use - Intraclass Correlation Coefficient: Could not fit multilevel model for farm data: argument 2 (type 'list') cannot be handled by 'cat' 
## 
## Household antibiotic use - Intraclass Correlation Coefficient: Could not fit multilevel model for household data: argument 2 (type 'list') cannot be handled by 'cat'
# -------------------------------------------------------------------------
# 7. ANTIBIOTIC TYPES COMPARATIVE ANALYSIS
# -------------------------------------------------------------------------

# 7.1 Extract antibiotic type data from both datasets
# Farm antibiotic types - CORRECTED to properly handle binary variables (0/1)
farm_ab_types <- farm_data %>%
  summarise(
    n = n(),
    # Properly calculate percentage using binary indicators (== 1)
    # These variables are binary where 1 = Yes (used this antibiotic), 0 = No
    chloramphenicol = mean(chlo == 1, na.rm = TRUE) * 100,
    nitrofurans = mean(nitr == 1, na.rm = TRUE) * 100,
    dimetridazole = mean(dime == 1, na.rm = TRUE) * 100,
    metronidazole = mean(metr == 1, na.rm = TRUE) * 100,
    ciprofloxacin = mean(cipr == 1, na.rm = TRUE) * 100,
    ofloxacin = mean(oflo == 1, na.rm = TRUE) * 100,
    carbadox = mean(carb == 1, na.rm = TRUE) * 100,
    olaquindox = mean(olaq == 1, na.rm = TRUE) * 100,
    bacitracin = mean(baci == 1, na.rm = TRUE) * 100
  )

# Household antibiotic types - check and adapt to actual variable names
household_ab_cols <- grep("^num_q7_11___\\d+$", names(household_data), value = TRUE)

if(length(household_ab_cols) > 0) {
  household_ab_types <- household_data %>%
    summarise(across(all_of(household_ab_cols), ~mean(. == 1, na.rm = TRUE) * 100)) %>%
    mutate(n = nrow(household_data))
  
  # Map variable names to antibiotic types - adjust mapping as needed
  household_ab_map <- data.frame(
    variable = household_ab_cols,
    antibiotic = case_when(
      grepl("1$", household_ab_cols) ~ "amoxicillin",
      grepl("2$", household_ab_cols) ~ "ampicillin",
      grepl("3$", household_ab_cols) ~ "amoxicillin_clavulanic",
      grepl("4$", household_ab_cols) ~ "azithromycin",
      grepl("5$", household_ab_cols) ~ "cefalexin",
      grepl("6$", household_ab_cols) ~ "cefixime",
      grepl("7$", household_ab_cols) ~ "cefuroxime",
      grepl("8$", household_ab_cols) ~ "quinolones",
      grepl("9$", household_ab_cols) ~ "cotrimoxazole",
      grepl("10$", household_ab_cols) ~ "metronidazole",
      grepl("11$", household_ab_cols) ~ "penicillin",
      TRUE ~ "other"
    ),
    stringsAsFactors = FALSE
  )
  
  # Transform to long format
  household_ab_long <- household_ab_types %>%
    dplyr::select(-n) %>%
    pivot_longer(cols = everything(), names_to = "variable", values_to = "percentage") %>%
    left_join(household_ab_map, by = "variable") %>%
    group_by(antibiotic) %>%
    summarise(percentage = sum(percentage), .groups = "drop") %>%  # Sum by antibiotic type
    filter(!is.na(antibiotic)) %>%
    mutate(sector = "Household")
  
  # Farm antibiotic types - long format
  farm_ab_long <- farm_ab_types %>%
    dplyr::select(-n) %>%
    pivot_longer(cols = everything(), names_to = "antibiotic", values_to = "percentage") %>%
    mutate(sector = "Farm")
  
  # Classify antibiotics into broader classes
  household_ab_classes <- data.frame(
    antibiotic = c("amoxicillin", "ampicillin", "amoxicillin_clavulanic", "penicillin", 
                   "azithromycin", "cefalexin", "cefixime", "cefuroxime", 
                   "quinolones", "cotrimoxazole", "metronidazole"),
    class = c("Penicillins", "Penicillins", "Penicillins", "Penicillins",
              "Macrolides", "Cephalosporins", "Cephalosporins", "Cephalosporins",
              "Quinolones", "Sulfonamides", "Nitroimidazoles"),
    stringsAsFactors = FALSE
  )

  farm_ab_classes <- data.frame(
    antibiotic = c("chloramphenicol", "nitrofurans", "dimetridazole", "metronidazole", 
                   "ciprofloxacin", "ofloxacin", "carbadox", "olaquindox", "bacitracin"),
    class = c("Amphenicols", "Nitrofurans", "Nitroimidazoles", "Nitroimidazoles", 
              "Quinolones", "Quinolones", "Others", "Others", "Polypeptides"),
    stringsAsFactors = FALSE
  )

  # Group by antibiotic class with CORRECTED method to avoid double-counting
  # This ensures proper handling of multiple antibiotics within the same class
  household_class_usage <- household_ab_long %>%
    left_join(household_ab_classes, by = "antibiotic") %>%
    filter(!is.na(class)) %>%
    group_by(class) %>%
    # For household data, we'll assume percentage calculation was correct
    summarise(percentage = sum(percentage), .groups = "drop") %>%
    mutate(sector = "Household")

  # For farm data, we'll use a different approach to avoid double-counting
  # This is especially important for classes with multiple antibiotics
  farm_class_usage <- farm_data %>%
    # Create class indicators - a farm uses a class if it uses any antibiotic in that class
    mutate(
      Amphenicols = as.integer(chlo == 1),
      Nitrofurans = as.integer(nitr == 1),
      Nitroimidazoles = as.integer(dime == 1 | metr == 1),  # Either antibiotic counts
      Quinolones = as.integer(cipr == 1 | oflo == 1),       # Either antibiotic counts
      Others = as.integer(carb == 1 | olaq == 1),           # Either antibiotic counts
      Polypeptides = as.integer(baci == 1)
    ) %>%
    # Calculate percentage for each class
    summarise(across(c(Amphenicols, Nitrofurans, Nitroimidazoles, 
                      Quinolones, Others, Polypeptides), 
                    ~mean(., na.rm = TRUE) * 100)) %>%
    # Convert to long format
    pivot_longer(cols = everything(), names_to = "class", values_to = "percentage") %>%
    mutate(sector = "Farm")

  # Combine datasets for comparison
  ab_class_comparison <- bind_rows(household_class_usage, farm_class_usage)

  # Print corrected data to verify
  print("Corrected antibiotic class comparison data:")
  print(ab_class_comparison)

  # Find shared antibiotic classes
  shared_classes <- intersect(household_class_usage$class, farm_class_usage$class)
  shared_class_comparison <- ab_class_comparison %>%
    filter(class %in% shared_classes)

  # Calculate correlation for shared classes if sufficient data
  if(length(shared_classes) >= 3) {
    correlation_data <- shared_class_comparison %>%
      pivot_wider(names_from = sector, values_from = percentage)

    class_correlation <- cor.test(correlation_data$Household, correlation_data$Farm, 
                                 method = "spearman")
    
    print("Correlation between farm and household antibiotic class usage:")
    print(class_correlation)
  }




# -------------------------------------------------------------------------
# 8. VISUALIZATIONS
# -------------------------------------------------------------------------

# 8.1 Prepare visualization data

# Farm antibiotic use purposes data
farm_purposes <- data.frame(
  purpose = c("Treatment", "Prevention", "Growth Promotion"),
  percentage = c(
    farm_ab_ci$ab_treatment_pct,
    farm_ab_ci$ab_prevention_pct,
    farm_ab_ci$ab_growth_pct
  )
) %>%
  mutate(purpose = factor(purpose, levels = c("Treatment", "Prevention", "Growth Promotion")))

# Comparison data for farm vs household overall antibiotic use
comparison_data <- data.frame(
  sector = c("Farm", "Household"),
  prevalence = c(farm_ab_ci$ab_use_pct, household_ab_ci$ab_use_pct),
  ci_lower = c(farm_ab_ci$ab_use_ci_lower, household_ab_ci$ab_use_ci_lower),
  ci_upper = c(farm_ab_ci$ab_use_ci_upper, household_ab_ci$ab_use_ci_upper)
)

# Preventive use comparison data
preventive_data <- data.frame(
  Category = c("Farm Preventive Use", "Household Preventive Use (Proxy)"),
  Usage = c(farm_ab_ci$ab_prevention_pct, household_preventive$preventive_pct),
  Lower = c(farm_ab_ci$ab_prevention_ci_lower, household_preventive$preventive_ci_lower),
  Upper = c(farm_ab_ci$ab_prevention_ci_upper, household_preventive$preventive_ci_upper)
)

# Non-treatment antibiotic use data
non_treatment_data <- data.frame(
  purpose = c("Any Non-Treatment", "Prevention Only", "Growth Promotion Only", "Both Purposes"),
  percentage = c(
    farm_non_treatment$any_non_treatment_pct,
    farm_non_treatment$prevention_only_pct,
    farm_non_treatment$growth_only_pct,
    farm_non_treatment$both_purposes_pct
  ),
  ci_lower = c(
    farm_non_treatment$any_non_treatment_ci_lower,
    farm_non_treatment$prevention_only_ci_lower,
    farm_non_treatment$growth_only_ci_lower,
    farm_non_treatment$both_purposes_ci_lower
  ),
  ci_upper = c(
    farm_non_treatment$any_non_treatment_ci_upper,
    farm_non_treatment$prevention_only_ci_upper,
    farm_non_treatment$growth_only_ci_upper,
    farm_non_treatment$both_purposes_ci_upper
  )
) %>%
  arrange(desc(percentage))

# 8.2 Create individual visualizations

# 1. Overall antibiotic use prevalence comparison
overall_comparison_plot <- ggplot(comparison_data, aes(x = sector, y = prevalence, fill = sector)) +
  geom_bar(stat = "identity", width = 0.6, color = "gray30", linewidth = 0.2) +
  geom_errorbar(aes(ymin = ci_lower, ymax = ci_upper), width = 0.2, color = "gray30", linewidth = 0.5) +
  geom_text(aes(label = paste0(round(prevalence, 1), "%")), 
            vjust = -0.8, size = 3.2, color = "gray30") +
  labs(title = "Overall Antibiotic Use Prevalence",
       subtitle = paste0("Chi-square test: χ² = ", round(overall_chi$statistic, 1), 
                        ", p < 0.001; Effect size: ", round(overall_phi, 3), " (", overall_effect, ")"),
       x = "",
       y = "Prevalence (%)") +
  theme(legend.position = "none",
        axis.text.x = element_text(size = 10)) +
  scale_fill_manual(values = c("Farm" = "#a8c0e0", "Household" = "#e0b5a8")) +
  scale_y_continuous(limits = c(0, max(comparison_data$ci_upper) * 1.15), 
                    breaks = seq(0, 100, by = 20),
                    expand = c(0, 0))

print(overall_comparison_plot)


# 2. Preventive antibiotic use comparison
preventive_plot <- ggplot(preventive_data, aes(x = Category, y = Usage, fill = Category)) +
  geom_bar(stat = "identity", width = 0.6, color = "gray30", linewidth = 0.2) +
  geom_errorbar(aes(ymin = Lower, ymax = Upper), width = 0.2, color = "gray30", linewidth = 0.5) +
  geom_text(aes(label = sprintf("%.1f%%", Usage)), 
            vjust = -0.8, size = 3.2, color = "gray30") +
  labs(title = "Preventive Antibiotic Use Comparison",
       subtitle = paste0("Farm:Household ratio = ", round(preventive_ratio, 1), ":1"),
       x = "",
       y = "Prevalence (%)") +
  theme(legend.position = "none",
        axis.text.x = element_text(angle = 45, hjust = 1, size = 9)) +
  scale_fill_manual(values = c("Farm Preventive Use" = "#a8c0e0", 
                            "Household Preventive Use (Proxy)" = "#a8d3b5")) +
  scale_y_continuous(limits = c(0, max(preventive_data$Upper) * 1.15), 
                   breaks = seq(0, 60, by = 10),
                   expand = c(0, 0)) 

print(preventive_plot)


# 3. Farm antibiotic use purposes
total_percentage <- sum(farm_purposes$percentage)
cat("Total percentage across all purposes:", total_percentage, "%\n")

farm_purpose_plot <- ggplot(farm_purposes, aes(x = "Farm", y = percentage, fill = purpose)) +
  geom_bar(stat = "identity", position = "stack", width = 0.6, color = "white", linewidth = 0.2) +
  geom_text(aes(label = paste0(round(percentage, 1), "%")), 
            position = position_stack(vjust = 0.5), 
            color = "white", fontface = "bold", size = 3) +
  labs(title = "Antibiotic Use Purposes on Farms",
       subtitle = paste0("n = ", farm_ab_ci$n, " farms", 
                        ifelse(total_percentage > 100, 
                              "\nNote: Percentages sum to >100% as farms may use antibiotics for multiple purposes", 
                              "")),
       x = "",
       y = "Percentage of Farms (%)") +
  theme(legend.position = "right",
        legend.title = element_blank(),
        legend.key.size = unit(0.8, "cm"),
        panel.background = element_rect(fill = "white", color = NA),
        plot.background = element_rect(fill = "white", color = NA)) +
  scale_fill_manual(values = c(
    "Treatment" = "#a8c0e0",
    "Prevention" = "#e0b5a8", 
    "Growth Promotion" = "#a8d3b5"
  )) +
  scale_y_continuous(expand = c(0, 0), limits = c(0, 100))

print(farm_purpose_plot)


# 4. Non-treatment antibiotic use analysis
non_treatment_plot <- ggplot(non_treatment_data, 
                           aes(x = reorder(purpose, -percentage), y = percentage, fill = purpose)) +
  geom_bar(stat = "identity", width = 0.6, color = "gray30", linewidth = 0.2) +
  geom_errorbar(aes(ymin = ci_lower, ymax = ci_upper), width = 0.2, color = "gray30", linewidth = 0.5) +
  geom_text(aes(label = sprintf("%.1f%%", percentage)), 
            vjust = -0.5, size = 3, color = "gray30") +
  labs(title = "Non-Treatment Antibiotic Use in Farms",
       subtitle = paste0("n = ", farm_ab_ci$n, " farms"),
       x = "",
       y = "Prevalence (%)") +
  theme(legend.position = "none",
        axis.text.x = element_text(angle = 45, hjust = 1, size = 8.5)) +
  scale_fill_manual(values = c(
    "Any Non-Treatment" = "#a8c0e0",
    "Prevention Only" = "#e0b5a8",
    "Growth Promotion Only" = "#a8d3b5",
    "Both Purposes" = "#c3b5d3"
  )) +
  scale_y_continuous(limits = c(0, max(non_treatment_data$ci_upper) * 1.15),
                    expand = c(0, 0))
print(non_treatment_plot)


# 5. Household antibiotic use by symptom status (if available)
if(exists("household_by_symptom") && nrow(household_by_symptom) > 0) {
  household_by_symptom$symptom_status <- factor(
    household_by_symptom$symptom_status,
    levels = c("Respiratory symptoms", "GI symptoms", "Fever", 
              "Other symptoms", "No symptoms")
  )
  
  symptom_plot <- ggplot(household_by_symptom, 
                       aes(x = reorder(symptom_status, -ab_use_pct), y = ab_use_pct, 
                           fill = symptom_status)) +
    geom_bar(stat = "identity", width = 0.7, color = "gray30", linewidth = 0.2) +
    geom_errorbar(aes(ymin = ab_use_ci_lower, ymax = ab_use_ci_upper), 
                 width = 0.2, color = "gray30", linewidth = 0.5) +
    geom_text(aes(label = sprintf("%.1f%%", ab_use_pct)), 
              vjust = -0.5, size = 3, color = "gray30") +
    labs(title = "Household Antibiotic Use by Symptom Status",
         subtitle = paste0("n = ", household_ab_ci$n, " households"),
         x = "",
         y = "Antibiotic Use Rate (%)") +
    theme(legend.position = "none",
          axis.text.x = element_text(angle = 45, hjust = 1, size = 8.5)) +
    scale_fill_manual(values = c(
      "Respiratory symptoms" = "#a8c0e0",
      "GI symptoms" = "#e0b5a8",
      "Fever" = "#a8d3b5",
      "Other symptoms" = "#c3b5d3",
      "No symptoms" = "#d8cfb0"
    )) +
    scale_y_continuous(limits = c(0, max(household_by_symptom$ab_use_ci_upper) * 1.15),
                      expand = c(0, 0))
  
  print(symptom_plot)
}

# 6. Comparative chart of antibiotic classes - Science/Lancet style
class_plot <- ggplot(ab_class_comparison, 
                      aes(x = reorder(class, -percentage), y = percentage, fill = sector)) +
    geom_bar(stat = "identity", position = "dodge", width = 0.7, 
             color = "gray30", linewidth = 0.2) +
    geom_text(aes(label = sprintf("%.1f%%", percentage)),
              position = position_dodge(width = 0.7),
              vjust = -0.3, size = 2.8, color = "gray30") +
    labs(title = "Antibiotic Classes Used in Farms and Households",
         subtitle = "Proportion of farms/households using each antibiotic class",
         x = "",
         y = "Usage Rate (%)") +
    theme_minimal() +
    theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
          legend.position = "bottom",
          panel.background = element_rect(fill = "white", color = NA),
          plot.background = element_rect(fill = "white", color = NA),
          panel.grid.minor = element_blank(),
          panel.grid.major.x = element_blank()) +
    scale_fill_manual(values = c("Farm" = "#a8c0e0", "Household" = "#e0b5a8")) +
    scale_y_continuous(limits = c(0, max(ab_class_comparison$percentage) * 1.2), 
                      breaks = seq(0, 100, by = 20),
                      expand = c(0, 0))

  print(class_plot)
  ggsave("antibiotic_class_comparison.png", class_plot, 
         width = 8, height = 5, dpi = 300)
  
  # 2. Shared antibiotic classes (if available)
  if(length(shared_classes) > 0) {
    shared_class_plot <- ggplot(shared_class_comparison, 
                              aes(x = reorder(class, -percentage), y = percentage, fill = sector)) +
      geom_bar(stat = "identity", position = "dodge", width = 0.7, 
               color = "gray30", linewidth = 0.2) +
      geom_text(aes(label = sprintf("%.1f%%", percentage)),
                position = position_dodge(width = 0.7),
                vjust = -0.3, size = 2.8, color = "gray30") +
      labs(title = "Shared Antibiotic Classes in Farms and Households",
           subtitle = ifelse(exists("class_correlation"),
                           paste0("Spearman correlation: rho = ", 
                                 round(class_correlation$estimate, 2),
                                 ", p = ", round(class_correlation$p.value, 3)),
                           "Comparison of usage patterns across sectors"),
           x = "",
           y = "Usage Rate (%)") +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
            legend.position = "bottom",
            panel.background = element_rect(fill = "white", color = NA),
            plot.background = element_rect(fill = "white", color = NA),
            panel.grid.minor = element_blank(),
            panel.grid.major.x = element_blank()) +
      scale_fill_manual(values = c("Farm" = "#a8c0e0", "Household" = "#e0b5a8")) +
      scale_y_continuous(limits = c(0, max(shared_class_comparison$percentage) * 1.2), 
                        breaks = seq(0, 100, by = 20),
                        expand = c(0, 0))
    
    print(shared_class_plot)
  }
}
## [1] "Corrected antibiotic class comparison data:"
## # A tibble: 12 × 3
##    class           percentage sector   
##    <chr>                <dbl> <chr>    
##  1 Cephalosporins      2.66   Household
##  2 Macrolides          0.319  Household
##  3 Nitroimidazoles     0.128  Household
##  4 Penicillins         3.81   Household
##  5 Quinolones          0.0957 Household
##  6 Sulfonamides        0.0744 Household
##  7 Amphenicols         0.460  Farm     
##  8 Nitrofurans         0.276  Farm     
##  9 Nitroimidazoles     0.276  Farm     
## 10 Quinolones          0.736  Farm     
## 11 Others              0.276  Farm     
## 12 Polypeptides        0      Farm

## Total percentage across all purposes: 138 %

# 7. Comparison of common antibiotic classes - Science/Lancet style
if(exists("shared_class_comparison") && length(shared_classes) > 0) {
  shared_class_plot <- ggplot(shared_class_comparison, 
                            aes(x = reorder(class, -percentage), y = percentage, fill = sector)) +
    geom_bar(stat = "identity", position = "dodge", width = 0.7, 
             color = "gray30", linewidth = 0.2) +
    geom_text(aes(label = sprintf("%.1f%%", percentage)),
              position = position_dodge(width = 0.7),
              vjust = -0.3, size = 2.8, color = "gray30") +
    labs(title = "Shared Antibiotic Classes in Farms and Households",
         x = "",
         y = "Usage Rate (%)",
         fill = "") +
    theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 8),
          legend.position = "bottom") +
    scale_fill_manual(values = c("Farm" = "#a8c0e0", "Household" = "#e0b5a8")) +
    scale_y_continuous(limits = c(0, max(shared_class_comparison$percentage) * 1.2), 
                      breaks = seq(0, 50, by = 10),
                      expand = c(0, 0)) 
  
  print(shared_class_plot)
  ggsave("shared_antibiotic_classes.pdf", shared_class_plot, 
         width = 7, height = 5, dpi = 300)
  ggsave("shared_antibiotic_classes.png", shared_class_plot, 
         width = 7, height = 5, dpi = 300)

  if(length(shared_classes) >= 3 && exists("correlation_data")) {
    corr_plot <- ggplot(correlation_data, aes(x = Household, y = Farm, label = class)) +
      geom_point(color = "#a8c0e0", size = 3, alpha = 0.8) +
      geom_text_repel(size = 3, color = "gray30", box.padding = 0.5) +
      geom_smooth(method = "lm", se = TRUE, color = "#e0b5a8", fill = "#e0b5a8", alpha = 0.2) +
      labs(title = "Correlation of Antibiotic Class Usage",
           subtitle = paste0("Spearman correlation: rho = ", 
                           round(class_correlation$estimate, 2), 
                           ", p = ", round(class_correlation$p.value, 3)),
           x = "Household Usage Rate (%)",
           y = "Farm Usage Rate (%)") +
      theme(panel.grid.major = element_line(color = "gray95", linewidth = 0.3)) +
      coord_fixed(ratio = 1, xlim = c(0, max(correlation_data$Household, correlation_data$Farm) * 1.1),
                ylim = c(0, max(correlation_data$Household, correlation_data$Farm) * 1.1))
    
    print(corr_plot)
  }
}

# 8.3 Create forest plot comparing antibiotic use across different categories

# Prepare data for forest plot
forest_data <- bind_rows(
  # Farm data by purpose
  farm_purposes %>%
    mutate(
      category = "Farm",
      subcategory = purpose,
      estimate = percentage,
      # Add confidence intervals (approximate for visualization purposes)
      lower = pmax(0, percentage - 5),
      upper = pmin(100, percentage + 5)
    ) %>%
    dplyr::select(category, subcategory, estimate, lower, upper),
  
  # Household data
  data.frame(
    category = "Household",
    subcategory = "Any Use",
    estimate = household_ab_ci$ab_use_pct,
    lower = household_ab_ci$ab_use_ci_lower,
    upper = household_ab_ci$ab_use_ci_upper,
    stringsAsFactors = FALSE
  ),
  
  # Household preventive use (both definitions)
  data.frame(
    category = "Household",
    subcategory = c("Preventive (Stringent)", "Preventive (Relaxed)"),
    estimate = c(household_preventive_stringent$preventive_pct, 
                household_preventive_relaxed$preventive_pct),
    lower = c(household_preventive_stringent$preventive_ci_lower,
             household_preventive_relaxed$preventive_ci_lower),
    upper = c(household_preventive_stringent$preventive_ci_upper,
             household_preventive_relaxed$preventive_ci_upper),
    stringsAsFactors = FALSE
  )
) %>%
  # Create a combined label for ordering
  mutate(
    combined_label = paste0(category, ": ", subcategory),
    combined_label = factor(combined_label, 
                          levels = rev(unique(combined_label)))
  )

# Create the forest plot
forest_plot <- ggplot(forest_data, aes(x = estimate, y = combined_label, 
                                     color = category)) +
  geom_rect(aes(ymin = as.numeric(combined_label) - 0.5, 
               ymax = as.numeric(combined_label) + 0.5,
               xmin = 0, xmax = 100),
           fill = "gray97", alpha = 0.5, color = NA) +
  geom_point(size = 3) +
  geom_errorbarh(aes(xmin = lower, xmax = upper), height = 0.3, linewidth = 0.5) +
  labs(title = "Antibiotic Use Patterns in Farms and Households",
       subtitle = "Point estimates with 95% confidence intervals",
       x = "Prevalence (%)",
       y = "",
       color = "") +
  theme(panel.grid.major.x = element_line(color = "gray95", linewidth = 0.3),
        panel.grid.major.y = element_blank(),
        legend.position = "bottom") +
  scale_color_manual(values = c("Farm" = "#a8c0e0", "Household" = "#e0b5a8")) +
  scale_x_continuous(limits = c(0, 100), breaks = seq(0, 100, by = 20),
                    expand = c(0, 0)) +
  geom_text(aes(x = estimate + 3, label = sprintf("%.1f%%", estimate)), 
            size = 2.8, hjust = 0, color = "gray30")

print(forest_plot)

# 8.4 Create One Health perspective integrated visualization
# Prepare data for One Health visualization
one_health_data <- bind_rows(
  # Farm data
  data.frame(
    sector = "Farm",
    category = c("Treatment", "Prevention", "Growth Promotion"),
    percentage = c(farm_ab_ci$ab_treatment_pct, 
                 farm_ab_ci$ab_prevention_pct, 
                 farm_ab_ci$ab_growth_pct),
    stringsAsFactors = FALSE
  ),
  
  # Household data
  household_by_symptom %>%
    transmute(
      sector = "Household",
      category = symptom_status,
      percentage = ab_use_pct
    )
)

# Create the One Health visualization
one_health_plot <- ggplot(one_health_data, 
                        aes(x = sector, y = percentage, fill = category)) +
  geom_bar(stat = "identity", position = "stack", width = 0.7) +
  geom_text(aes(label = sprintf("%.1f%%", percentage)),
            position = position_stack(vjust = 0.5),
            color = "white", fontface = "bold", size = 3) +
  labs(title = "One Health Perspective: Integrated Antibiotic Use Patterns",
       subtitle = "Comparison of antibiotic use purposes across farm and household sectors",
       x = "",
       y = "Percentage (%)") +
  scale_fill_manual(values = c(
    # Farm colors (blues)
    "Treatment" = "#4a6fe3",
    "Prevention" = "#6aabcc",
    "Growth Promotion" = "#a8d5eb",
    # Household colors (reds/oranges)
    "Respiratory symptoms" = "#d3825f",
    "GI symptoms" = "#e9ae98",
    "Fever" = "#c15c41",
    "Other symptoms" = "#f3cfbf",
    "No symptoms" = "#fae3d7"
  )) +
  theme(legend.position = "right",
        legend.title = element_blank())

print(one_health_plot)

# -------------------------------------------------------------------------
# 9. SUMMARY OF FINDINGS
# -------------------------------------------------------------------------

# Create a comprehensive summary table
summary_table <- data.frame(
  Measure = c("Overall Antibiotic Use", "Farm Treatment Use", "Farm Prevention Use", 
              "Farm Growth Promotion Use", "Household Preventive Use (Proxy)"),
  Prevalence = c(
    paste0(round(farm_ab_ci$ab_use_pct, 1), "% vs ", round(household_ab_ci$ab_use_pct, 1), "%"),
    paste0(round(farm_ab_ci$ab_treatment_pct, 1), "%"),
    paste0(round(farm_ab_ci$ab_prevention_pct, 1), "%"),
    paste0(round(farm_ab_ci$ab_growth_pct, 1), "%"),
    paste0(round(household_preventive$preventive_pct, 1), "%")
  ),
  Comparison = c(
    paste0("χ² = ", round(overall_chi$statistic, 1), 
          ", p ", ifelse(overall_chi$p.value < 0.001, "< 0.001", 
                        paste0("= ", round(overall_chi$p.value, 3))),
          "; Effect: ", overall_effect),
    "N/A",
    paste0("Farm:Household ratio = ", round(preventive_ratio, 1), ":1"),
    "N/A",
    paste0("χ² = ", round(preventive_chi$statistic, 1), 
          ", p ", ifelse(preventive_chi$p.value < 0.001, "< 0.001", 
                        paste0("= ", round(preventive_chi$p.value, 3))),
          "; Effect: ", preventive_effect)
  ),
  Conclusion = c(
    ifelse(overall_chi$p.value < 0.05, 
          "Significant difference in overall use between farms and households", 
          "No significant difference in overall use"),
    "Most common purpose for antibiotic use in farms",
    ifelse(preventive_chi$p.value < 0.05,
          "Significantly higher preventive use in farms than households",
          "No significant difference in preventive use"),
    paste0(round(farm_non_treatment$any_non_treatment_pct, 1), 
          "% of farms use antibiotics for non-treatment purposes"),
    "Based on proxy measure of antibiotic use without symptoms"
  )
)

# Display the summary table
kable(summary_table,
      caption = "Summary of Key Findings for Hypothesis 1.1",
      align = "llll") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), 
                full_width = FALSE) %>%
  column_spec(1, bold = TRUE) %>%
  row_spec(0, bold = TRUE, background = "#f2f2f2")
Summary of Key Findings for Hypothesis 1.1
Measure Prevalence Comparison Conclusion
Overall Antibiotic Use 94.2% vs 5.5% χ² = 6260.6, p < 0.001; Effect: Large Significant difference in overall use between farms and households
Farm Treatment Use 89.4% N/A Most common purpose for antibiotic use in farms
Farm Prevention Use 48.3% Farm:Household ratio = Inf:1 Significantly higher preventive use in farms than households
Farm Growth Promotion Use 0.9% N/A 48.4% of farms use antibiotics for non-treatment purposes
Household Preventive Use (Proxy) 0% χ² = 4786.3, p < 0.001; Effect: Large Based on proxy measure of antibiotic use without symptoms
# -------------------------------------------------------------------------
# 10. FINAL CONCLUSION ON HYPOTHESIS 1.1
# -------------------------------------------------------------------------

cat("\n\n### CONCLUSION ON HYPOTHESIS 1.1 ###\n\n")
## 
## 
## ### CONCLUSION ON HYPOTHESIS 1.1 ###
cat("Hypothesis 1.1 states that preventive and growth-promoting antibiotic use is common in farm animals, with prevalence rates higher than corresponding use in human medicine.\n\n")
## Hypothesis 1.1 states that preventive and growth-promoting antibiotic use is common in farm animals, with prevalence rates higher than corresponding use in human medicine.
# Overall conclusion
if(farm_ab_ci$ab_prevention_pct > household_preventive$preventive_pct && preventive_chi$p.value < 0.05) {
  cat("CONCLUSION: The data SUPPORTS hypothesis 1.1. \n\n")
} else if(farm_ab_ci$ab_prevention_pct > household_preventive$preventive_pct && preventive_chi$p.value >= 0.05) {
  cat("CONCLUSION: The data PARTIALLY SUPPORTS hypothesis 1.1. \n\n")
} else {
  cat("CONCLUSION: The data DOES NOT SUPPORT hypothesis 1.1. \n\n")
}
## CONCLUSION: The data SUPPORTS hypothesis 1.1.
# Detailed explanation
cat(paste0("Farm preventive antibiotic use (", round(farm_ab_ci$ab_prevention_pct, 1), 
          "%, 95% CI: ", round(farm_ab_ci$ab_prevention_ci_lower, 1), "-", 
          round(farm_ab_ci$ab_prevention_ci_upper, 1), "%) is approximately ", 
          round(preventive_ratio, 1), " times higher than household preventive use (", 
          round(household_preventive$preventive_pct, 1), "%, 95% CI: ", 
          round(household_preventive$preventive_ci_lower, 1), "-", 
          round(household_preventive$preventive_ci_upper, 1), "%). "))
## Farm preventive antibiotic use (48.3%, 95% CI: 45.4-51.2%) is approximately Inf times higher than household preventive use (0%, 95% CI: 0-0%).
if(preventive_chi$p.value < 0.05) {
  cat(paste0("This difference is statistically significant (χ² = ", 
            round(preventive_chi$statistic, 1), ", p ", 
            ifelse(preventive_chi$p.value < 0.001, "< 0.001", paste0("= ", round(preventive_chi$p.value, 3))), 
            ") with a ", tolower(preventive_effect), " effect size (Phi = ", round(preventive_phi, 3), ").\n\n"))
} else {
  cat(paste0("However, this difference is not statistically significant (χ² = ", 
            round(preventive_chi$statistic, 1), ", p = ", round(preventive_chi$p.value, 3), 
            "), possibly due to limited sample size or high variability.\n\n"))
}
## This difference is statistically significant (χ² = 4786.3, p < 0.001) with a large effect size (Phi = 0.673).
cat(paste0("Additionally, ", round(farm_non_treatment$any_non_treatment_pct, 1), 
          "% of farms use antibiotics for non-treatment purposes, with ", 
          round(farm_ab_ci$ab_growth_pct, 1), "% specifically using antibiotics for growth promotion, 
          a practice not found in human medicine.\n\n"))
## Additionally, 48.4% of farms use antibiotics for non-treatment purposes, with 0.9% specifically using antibiotics for growth promotion, 
##           a practice not found in human medicine.
cat("These findings suggest that non-therapeutic antibiotic use is more prevalent in farm settings compared to household use, 
consistent with the hypothesis. This has important implications for antimicrobial resistance risks, as preventive and growth-promoting 
antibiotic use in agriculture may contribute significantly to the overall antibiotic selection pressure in the environment.\n\n")
## These findings suggest that non-therapeutic antibiotic use is more prevalent in farm settings compared to household use, 
## consistent with the hypothesis. This has important implications for antimicrobial resistance risks, as preventive and growth-promoting 
## antibiotic use in agriculture may contribute significantly to the overall antibiotic selection pressure in the environment.
cat("Limitations to consider include the use of a proxy measure for household preventive use and potential differences in antibiotic 
classification between sectors. Future research should include more direct measures of household antibiotic use purposes and examine 
the specific drivers of preventive antibiotic use in both sectors.")
## Limitations to consider include the use of a proxy measure for household preventive use and potential differences in antibiotic 
## classification between sectors. Future research should include more direct measures of household antibiotic use purposes and examine 
## the specific drivers of preventive antibiotic use in both sectors.

1.4 Results for Hypothesis 1.2: Differences in Antibiotic Use Among Animal Types

# Load processed data if not already in memory
if(!exists("farm_data")) {
  farm_data <- readRDS(here("data", "processed", "farm_data_processed.rds"))
}

# Calculate antibiotic use prevalence by animal type
ab_by_animal <- farm_data %>%
  group_by(animal_type) %>%
  summarise(
    n = n(),
    ab_use_any_n = sum(any_ab_use, na.rm = TRUE),
    ab_use_any_pct = mean(any_ab_use, na.rm = TRUE) * 100,
    ab_treatment_pct = mean(ab_treatment, na.rm = TRUE) * 100,
    ab_prevention_pct = mean(ab_prevention, na.rm = TRUE) * 100,
    ab_growth_pct = mean(ab_growth, na.rm = TRUE) * 100,
    .groups = "drop"
  ) %>%
  filter(!is.na(animal_type))  # Remove NA animal types

# Display results
ab_by_animal %>%
  kable(caption = "Antibiotic Use by Animal Type",
        col.names = c("Animal Type", "Number of Farms", "Farms Using Antibiotics", 
                      "% Any Use", "% Treatment", "% Prevention", "% Growth Promotion")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
Antibiotic Use by Animal Type
Animal Type Number of Farms Farms Using Antibiotics % Any Use % Treatment % Prevention % Growth Promotion
Cattle 85 74 87 80 41 0.00
Chicken 431 409 95 90 57 1.62
Pig 640 606 95 90 43 0.47
### Specific Antibiotic Types by Animal Type

# For each animal type, calculate prevalence of specific antibiotics
specific_ab_by_animal <- farm_data %>%
  group_by(animal_type) %>%
  summarise(
    n = n(),
    chlo_pct = mean(chlo, na.rm = TRUE) * 100,
    nitr_pct = mean(nitr, na.rm = TRUE) * 100,
    dime_pct = mean(dime, na.rm = TRUE) * 100,
    metr_pct = mean(metr, na.rm = TRUE) * 100,
    cipr_pct = mean(cipr, na.rm = TRUE) * 100,
    oflo_pct = mean(oflo, na.rm = TRUE) * 100,
    carb_pct = mean(carb, na.rm = TRUE) * 100,
    olaq_pct = mean(olaq, na.rm = TRUE) * 100,
    baci_pct = mean(baci, na.rm = TRUE) * 100,
    .groups = "drop"
  ) %>%
  filter(!is.na(animal_type))

# Display the results
specific_ab_by_animal %>%
  kable(caption = "Specific Antibiotic Use by Animal Type (%)",
        digits = 1) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE) %>%
  scroll_box(width = "100%")
Specific Antibiotic Use by Animal Type (%)
animal_type n chlo_pct nitr_pct dime_pct metr_pct cipr_pct oflo_pct carb_pct olaq_pct baci_pct
Cattle 85 207 205 207 207 204 207 208 208 208
Chicken 431 212 213 213 213 212 212 212 213 214
Pig 640 211 211 213 212 212 211 212 212 212
### Chi-square Tests for Differences Among Animal Types

# Prepare contingency table for overall antibiotic use
animal_ab_table <- farm_data %>%
  filter(!is.na(animal_type)) %>%
  group_by(animal_type) %>%
  summarise(
    ab_use = sum(any_ab_use, na.rm = TRUE),
    no_ab_use = sum(1 - any_ab_use, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  dplyr::select(-animal_type) %>%
  as.matrix()

# Set row names for the contingency table
rownames(animal_ab_table) <- ab_by_animal$animal_type

# Display the contingency table
kable(animal_ab_table, caption = "Contingency Table: Antibiotic Use by Animal Type") %>%
  kable_styling()
Contingency Table: Antibiotic Use by Animal Type
ab_use no_ab_use
Cattle 74 11
Chicken 409 22
Pig 606 34
# Perform chi-square test for overall use
animal_chi_test <- chisq.test(animal_ab_table)

# Display results
cat("Chi-square test for differences in overall antibiotic use among animal types:\n")
## Chi-square test for differences in overall antibiotic use among animal types:
cat("Chi-square value:", animal_chi_test$statistic, "\n")
## Chi-square value: 8.6
cat("Degrees of freedom:", animal_chi_test$parameter, "\n")
## Degrees of freedom: 2
cat("P-value:", animal_chi_test$p.value, "\n")
## P-value: 0.014
cat("Interpretation:", ifelse(animal_chi_test$p.value < 0.05, 
                              "Significant differences in antibiotic use among animal types", 
                              "No significant differences in antibiotic use among animal types"), "\n")
## Interpretation: Significant differences in antibiotic use among animal types
# Calculate Cramer's V for effect size
cramers_v <- sqrt(animal_chi_test$statistic / (sum(animal_ab_table) * (min(dim(animal_ab_table)) - 1)))
cat("Effect size (Cramer's V):", cramers_v, "\n")
## Effect size (Cramer's V): 0.086
cat("Interpretation of effect size:", 
    case_when(
      cramers_v < 0.1 ~ "Negligible effect",
      cramers_v < 0.3 ~ "Small effect",
      cramers_v < 0.5 ~ "Medium effect",
      TRUE ~ "Large effect"
    ), "\n")
## Interpretation of effect size: Negligible effect
# Chi-square tests for each purpose of antibiotic use
# 1. Treatment purpose
treatment_table <- farm_data %>%
  filter(!is.na(animal_type)) %>%
  group_by(animal_type) %>%
  summarise(
    treatment = sum(ab_treatment, na.rm = TRUE),
    no_treatment = sum(1 - ab_treatment, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  dplyr::select(-animal_type) %>%
  as.matrix()

rownames(treatment_table) <- ab_by_animal$animal_type

# Perform chi-square test for treatment purpose
treatment_chi_test <- chisq.test(treatment_table)

# 2. Prevention purpose
prevention_table <- farm_data %>%
  filter(!is.na(animal_type)) %>%
  group_by(animal_type) %>%
  summarise(
    prevention = sum(ab_prevention, na.rm = TRUE),
    no_prevention = sum(1 - ab_prevention, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  dplyr::select(-animal_type) %>%
  as.matrix()

rownames(prevention_table) <- ab_by_animal$animal_type

# Perform chi-square test for prevention purpose
prevention_chi_test <- chisq.test(prevention_table)

# 3. Growth promotion purpose
growth_table <- farm_data %>%
  filter(!is.na(animal_type)) %>%
  group_by(animal_type) %>%
  summarise(
    growth = sum(ab_growth, na.rm = TRUE),
    no_growth = sum(1 - ab_growth, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  dplyr::select(-animal_type) %>%
  as.matrix()

rownames(growth_table) <- ab_by_animal$animal_type

# Perform chi-square test for growth promotion purpose
growth_chi_test <- chisq.test(growth_table)

# Create a summary table of chi-square test results
chi_summary <- data.frame(
  Purpose = c("Overall Use", "Treatment", "Prevention", "Growth Promotion"),
  ChiSquare = c(
    animal_chi_test$statistic,
    treatment_chi_test$statistic,
    prevention_chi_test$statistic,
    growth_chi_test$statistic
  ),
  DF = c(
    animal_chi_test$parameter,
    treatment_chi_test$parameter,
    prevention_chi_test$parameter,
    growth_chi_test$parameter
  ),
  PValue = c(
    animal_chi_test$p.value,
    treatment_chi_test$p.value,
    prevention_chi_test$p.value,
    growth_chi_test$p.value
  ),
  Significant = c(
    animal_chi_test$p.value < 0.05,
    treatment_chi_test$p.value < 0.05,
    prevention_chi_test$p.value < 0.05,
    growth_chi_test$p.value < 0.05
  )
)

# Display the summary table
chi_summary %>%
  mutate(
    ChiSquare = round(ChiSquare, 2),
    PValue = round(PValue, 4),
    Significant = ifelse(Significant, "Yes", "No")
  ) %>%
  kable(caption = "Chi-square Tests for Differences in Antibiotic Use Purposes Among Animal Types",
        col.names = c("Purpose", "Chi-Square Value", "Degrees of Freedom", "P-Value", "Significant")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
Chi-square Tests for Differences in Antibiotic Use Purposes Among Animal Types
Purpose Chi-Square Value Degrees of Freedom P-Value Significant
Overall Use 8.6 2 0.01 Yes
Treatment 8.5 2 0.01 Yes
Prevention 20.4 2 0.00 Yes
Growth Promotion 4.8 2 0.09 No
### Visualization of Antibiotic Use Patterns by Animal Type

# Prepare data for visualization
animal_use_long <- ab_by_animal %>%
  dplyr::select(animal_type, ab_treatment_pct, ab_prevention_pct, ab_growth_pct) %>%
  gather(key = "purpose", value = "percentage", -animal_type) %>%
  mutate(
    purpose = case_when(
      purpose == "ab_treatment_pct" ~ "Treatment",
      purpose == "ab_prevention_pct" ~ "Prevention",
      purpose == "ab_growth_pct" ~ "Growth Promotion"
    )
  )

# Create grouped bar chart
ggplot(animal_use_long, aes(x = animal_type, y = percentage, fill = purpose)) +
  geom_bar(stat = "identity", position = "dodge") +
  geom_text(aes(label = paste0(round(percentage, 1), "%")), 
            position = position_dodge(width = 0.9), vjust = -0.5, size = 3) +
  labs(title = "Antibiotic Use Purpose by Animal Type",
       x = "Animal Type",
       y = "Percentage of Farms (%)",
       fill = "Purpose") +
  theme_minimal() +
  scale_fill_brewer(palette = "Blues") +
  ylim(0, max(animal_use_long$percentage) * 1.2)  # Add some space for labels

# Create a heatmap of specific antibiotic use by animal type
specific_ab_long <- specific_ab_by_animal %>%
  dplyr::select(-n) %>%
  pivot_longer(cols = -animal_type, 
               names_to = "antibiotic", 
               values_to = "percentage") %>%
  mutate(
    antibiotic = case_when(
      antibiotic == "chlo_pct" ~ "Chloramphenicol",
      antibiotic == "nitr_pct" ~ "Nitrofurans",
      antibiotic == "dime_pct" ~ "Dimetridazole",
      antibiotic == "metr_pct" ~ "Metronidazole",
      antibiotic == "cipr_pct" ~ "Ciprofloxacin",
      antibiotic == "oflo_pct" ~ "Ofloxacin",
      antibiotic == "carb_pct" ~ "Carbadox",
      antibiotic == "olaq_pct" ~ "Olaquindox",
      antibiotic == "baci_pct" ~ "Bacitracin",
      TRUE ~ antibiotic
    )
  )

# Create heatmap visualization
ggplot(specific_ab_long, aes(x = animal_type, y = antibiotic, fill = percentage)) +
  geom_tile(color = "white") +
  geom_text(aes(label = round(percentage, 1)), size = 3) +
  scale_fill_gradient(low = "white", high = "steelblue") +
  labs(title = "Heatmap of Specific Antibiotic Use by Animal Type",
       x = "Animal Type",
       y = "Antibiotic",
       fill = "Prevalence (%)") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 0, hjust = 0.5),
        axis.text.y = element_text(size = 8))

# Additional analysis: Pairwise comparisons using post-hoc tests
# Only perform if overall chi-square is significant
if(animal_chi_test$p.value < 0.05) {
  # Prepare data for pairwise comparisons
  animal_types <- unique(farm_data$animal_type[!is.na(farm_data$animal_type)])
  pairwise_results <- data.frame(
    Comparison = character(),
    ChiSquare = numeric(),
    PValue = numeric(),
    Significant = character(),
    stringsAsFactors = FALSE
  )
  
  # Perform pairwise comparisons for each pair of animal types
  for(i in 1:(length(animal_types)-1)) {
    for(j in (i+1):length(animal_types)) {
      # Subset data for current pair
      pair_data <- farm_data %>%
        filter(animal_type %in% c(animal_types[i], animal_types[j])) %>%
        droplevels()
      
      # Create contingency table
      pair_table <- table(pair_data$animal_type, pair_data$any_ab_use)
      
      # Perform chi-square test
      pair_test <- chisq.test(pair_table)
      
      # Store results
      pairwise_results <- rbind(pairwise_results, data.frame(
        Comparison = paste(animal_types[i], "vs", animal_types[j]),
        ChiSquare = pair_test$statistic,
        PValue = pair_test$p.value,
        Significant = ifelse(pair_test$p.value < 0.05/3, "Yes", "No"),  # Bonferroni correction
        stringsAsFactors = FALSE
      ))
    }
  }
  
  # Display pairwise comparison results
  pairwise_results %>%
    mutate(
      ChiSquare = round(ChiSquare, 2),
      PValue = round(PValue, 4)
    ) %>%
    kable(caption = "Pairwise Comparisons of Antibiotic Use Between Animal Types (with Bonferroni correction)") %>%
    kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
}
Pairwise Comparisons of Antibiotic Use Between Animal Types (with Bonferroni correction)
Comparison ChiSquare PValue Significant
X-squared Chicken vs Pig 0.0 0.99 No
X-squared1 Chicken vs Cattle 6.0 0.01 Yes
X-squared2 Pig vs Cattle 6.2 0.01 Yes

1.5 Results for Hypothesis 1.3: Non-linear Relationship Between Farm Size and Antibiotic Use

if(!exists("farm_data")) {
  farm_data <- readRDS(here("data", "processed", "farm_data_processed.rds"))
}

# Calculate antibiotic use prevalence by farm size category
ab_by_size <- farm_data %>%
  group_by(farm_size_cat) %>%
  summarise(
    n = n(),
    ab_use_any_n = sum(any_ab_use, na.rm = TRUE),
    ab_use_any_pct = mean(any_ab_use, na.rm = TRUE) * 100,
    ab_treatment_pct = mean(ab_treatment, na.rm = TRUE) * 100,
    ab_prevention_pct = mean(ab_prevention, na.rm = TRUE) * 100,
    ab_growth_pct = mean(ab_growth, na.rm = TRUE) * 100,
    .groups = "drop"
  ) %>%
  filter(!is.na(farm_size_cat))  # Remove NA farm sizes

# Display results
ab_by_size %>%
  kable(caption = "Antibiotic Use by Farm Size Category",
        col.names = c("Farm Size", "Number of Farms", "Farms Using Antibiotics", 
                      "% Any Use", "% Treatment", "% Prevention", "% Growth Promotion")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
Antibiotic Use by Farm Size Category
Farm Size Number of Farms Farms Using Antibiotics % Any Use % Treatment % Prevention % Growth Promotion
Large 485 464 96 91 50 0.62
Medium 659 614 93 88 47 0.91
Small 12 11 92 92 33 8.33
# Chi-square test for association between farm size category and antibiotic use
size_chi_table <- farm_data %>%
  filter(!is.na(farm_size_cat)) %>%
  group_by(farm_size_cat) %>%
  summarise(
    ab_use = sum(any_ab_use, na.rm = TRUE),
    no_ab_use = sum(1 - any_ab_use, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  dplyr::select(-farm_size_cat) %>%
  as.matrix()

rownames(size_chi_table) <- ab_by_size$farm_size_cat

# Display the contingency table
kable(size_chi_table, caption = "Contingency Table: Antibiotic Use by Farm Size Category") %>%
  kable_styling()
Contingency Table: Antibiotic Use by Farm Size Category
ab_use no_ab_use
Large 464 21
Medium 614 45
Small 11 1
# Perform chi-square test
size_chi_test <- chisq.test(size_chi_table)

# Display results
cat("Chi-square test for differences in antibiotic use among farm size categories:\n")
## Chi-square test for differences in antibiotic use among farm size categories:
cat("Chi-square value:", size_chi_test$statistic, "\n")
## Chi-square value: 3.3
cat("Degrees of freedom:", size_chi_test$parameter, "\n")
## Degrees of freedom: 2
cat("P-value:", size_chi_test$p.value, "\n")
## P-value: 0.19
cat("Interpretation:", ifelse(size_chi_test$p.value < 0.05, 
                             "Significant differences in antibiotic use among farm size categories", 
                             "No significant differences in antibiotic use among farm size categories"), "\n")
## Interpretation: No significant differences in antibiotic use among farm size categories
# Calculate Cramer's V for effect size
cramers_v <- sqrt(size_chi_test$statistic / (sum(size_chi_table) * (min(dim(size_chi_table)) - 1)))
cat("Effect size (Cramer's V):", cramers_v, "\n")
## Effect size (Cramer's V): 0.054
cat("Interpretation of effect size:", 
    case_when(
      cramers_v < 0.1 ~ "Negligible effect",
      cramers_v < 0.3 ~ "Small effect",
      cramers_v < 0.5 ~ "Medium effect",
      TRUE ~ "Large effect"
    ), "\n")
## Interpretation of effect size: Negligible effect
### LOESS Smoothing for Non-linear Relationship

# Prepare data for LOESS smoothing
size_ab_data <- farm_data %>%
  filter(!is.na(area_farm) & !is.na(any_ab_use)) %>%
  dplyr::select(area_farm, any_ab_use, ab_treatment, ab_prevention, ab_growth)

# Create LOESS smoothed curve for overall antibiotic use
overall_plot <- ggplot(size_ab_data, aes(x = area_farm, y = any_ab_use)) +
  geom_point(alpha = 0.3) +
  geom_smooth(method = "loess", se = TRUE) +
  labs(title = "Non-linear Relationship Between Farm Size and Antibiotic Use",
       subtitle = "LOESS Smoothing Curve with 95% Confidence Interval",
       x = "Farm Area (square meters)",
       y = "Probability of Antibiotic Use") +
  theme_minimal()

# Print the plot
print(overall_plot)

# Create LOESS smoothed curves for different purposes
treatment_plot <- ggplot(size_ab_data, aes(x = area_farm, y = ab_treatment)) +
  geom_point(alpha = 0.3) +
  geom_smooth(method = "loess", se = TRUE) +
  labs(title = "Farm Size and Treatment Antibiotic Use",
       x = "Farm Area (square meters)",
       y = "Probability of Treatment Use") +
  theme_minimal()

prevention_plot <- ggplot(size_ab_data, aes(x = area_farm, y = ab_prevention)) +
  geom_point(alpha = 0.3) +
  geom_smooth(method = "loess", se = TRUE) +
  labs(title = "Farm Size and Preventive Antibiotic Use",
       x = "Farm Area (square meters)",
       y = "Probability of Preventive Use") +
  theme_minimal()

growth_plot <- ggplot(size_ab_data, aes(x = area_farm, y = ab_growth)) +
  geom_point(alpha = 0.3) +
  geom_smooth(method = "loess", se = TRUE) +
  labs(title = "Farm Size and Growth Promotion Antibiotic Use",
       x = "Farm Area (square meters)",
       y = "Probability of Growth Promotion Use") +
  theme_minimal()

# Combine plots for purposes
purpose_plots <- ggarrange(treatment_plot, prevention_plot, growth_plot, 
                           ncol = 3, nrow = 1, common.legend = TRUE)

# Print combined plot
print(purpose_plots)

#######################################################################
# Enhancing Hypothesis 1.3: Non-linear relationship between farm size 
# and antibiotic use – Causal inference analysis
#######################################################################

# Insert after the "### LOESS Smoothing for Non-linear Relationship" 
# section in the h1-3-analysis.R script
# This code strengthens causal inference regarding farm size and antibiotic use
# by controlling for confounders and conducting deeper analyses

### Multivariate Analysis: Non-linear Relationship Controlling for Confounders

# Load necessary libraries
if(!requireNamespace("mgcv", quietly = TRUE)) {
  install.packages("mgcv")
}
library(mgcv)

# Data preparation
gam_data <- farm_data %>%
  filter(!is.na(area_farm) & !is.na(any_ab_use) & !is.na(animal_type) & !is.na(edu))

# Fit Generalized Additive Model (GAM) controlling for animal type and education level
cat("Fitting Generalized Additive Model (GAM) controlling for confounders...\n")
## Fitting Generalized Additive Model (GAM) controlling for confounders...
gam_model <- tryCatch({
  gam(any_ab_use ~ s(area_farm) + animal_type + edu, 
     family = binomial, data = gam_data)
}, error = function(e) {
  message("GAM model fitting failed: ", e$message)
  return(NULL)
})

# Display model summary
if(!is.null(gam_model)) {
  print(summary(gam_model))
  
  # Visualization of adjusted non-linear relationship between farm size and antibiotic use
  plot_data <- expand.grid(
    area_farm = seq(min(gam_data$area_farm, na.rm = TRUE), 
                    max(gam_data$area_farm, na.rm = TRUE), length.out = 100),
    animal_type = unique(gam_data$animal_type),
    edu = median(gam_data$edu, na.rm = TRUE)
  )
  
  # Predict values
  plot_data$predicted <- predict(gam_model, newdata = plot_data, type = "response")
  
  # Plot adjusted non-linear relationships by animal type
  adjusted_plot <- ggplot(plot_data, aes(x = area_farm, y = predicted, color = animal_type)) +
    geom_line(size = 1) +
    labs(title = "Adjusted Non-linear Relationship between Farm Size and Antibiotic Use",
         subtitle = "Controlling for Animal Type and Education Level",
         x = "Farm Size (m²)",
         y = "Probability of Antibiotic Use",
         color = "Animal Type") +
    theme_minimal() +
    scale_color_brewer(palette = "Set1") +
    theme(legend.position = "bottom")
  
  print(adjusted_plot)
  
  # Overall effect plot without grouping
  overall_data <- expand.grid(
    area_farm = seq(min(gam_data$area_farm, na.rm = TRUE), 
                    max(gam_data$area_farm, na.rm = TRUE), length.out = 100),
    animal_type = "Chicken", # reference category
    edu = median(gam_data$edu, na.rm = TRUE)
  )
  
  overall_data$predicted <- predict(gam_model, newdata = overall_data, type = "response")
  
  # Extract confidence intervals from smooth terms
  smooth_terms <- plot(gam_model, select = 1, seWithMean = TRUE)
  smooth_df <- data.frame(
    area_farm = smooth_terms[[1]]$x,
    fit = smooth_terms[[1]]$fit,
    se = smooth_terms[[1]]$se
  )
  
  # Calculate confidence intervals on logit scale
  smooth_df$upper <- smooth_df$fit + 1.96 * smooth_df$se
  smooth_df$lower <- smooth_df$fit - 1.96 * smooth_df$se
  
  # Convert to probability scale
  smooth_df$fit_prob <- plogis(smooth_df$fit)
  smooth_df$upper_prob <- plogis(smooth_df$upper)
  smooth_df$lower_prob <- plogis(smooth_df$lower)
  
  # Plot smooth effect with confidence intervals
  smooth_plot <- ggplot() +
    geom_ribbon(data = smooth_df, 
                aes(x = area_farm, ymin = lower_prob, ymax = upper_prob),
                fill = "lightblue", alpha = 0.3) +
    geom_line(data = overall_data, aes(x = area_farm, y = predicted), 
              color = "darkblue", size = 1) +
    labs(title = "Smooth Effect of Farm Size on Antibiotic Use",
         subtitle = "With 95% Confidence Interval (Controlling for Animal Type and Education Level)",
         x = "Farm Size (m²)",
         y = "Probability of Antibiotic Use") +
    theme_minimal()
  
  print(smooth_plot)
  
  # Identify potential breakpoint (highest curvature)
  diff_data <- data.frame(
    area_farm = overall_data$area_farm[-c(1, length(overall_data$area_farm))],
    second_deriv = diff(diff(overall_data$predicted))
  )
  potential_breakpoint <- diff_data$area_farm[which.max(abs(diff_data$second_deriv))]
  cat("Potential breakpoint based on curvature analysis:", round(potential_breakpoint, 0), "m²\n")
}
## 
## Family: binomial 
## Link function: logit 
## 
## Formula:
## any_ab_use ~ s(area_farm) + animal_type + edu
## 
## Parametric coefficients:
##                    Estimate Std. Error z value     Pr(>|z|)    
## (Intercept)          2.0308     0.3499    5.80 0.0000000065 ***
## animal_typeChicken   1.2361     0.4004    3.09       0.0020 ** 
## animal_typePig       1.0849     0.3729    2.91       0.0036 ** 
## edu                 -0.0608     0.0440   -1.38       0.1667    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Approximate significance of smooth terms:
##               edf Ref.df Chi.sq p-value
## s(area_farm) 3.16   3.92   4.98    0.29
## 
## R-sq.(adj) =  0.0226   Deviance explained =  3.9%
## UBRE = -0.56027  Scale est. = 1         n = 1149

## Potential breakpoint based on curvature analysis: 1151 m²
### Analysis of Farm Characteristics around Breakpoint

# Set breakpoint range
breakpoint <- ifelse(exists("potential_breakpoint"), potential_breakpoint, 500)
window_size <- 200

# Identify farms around breakpoint
transition_farms <- farm_data %>%
  filter(area_farm >= (breakpoint - window_size) & 
           area_farm <= (breakpoint + window_size))

# Farms before, at, and after breakpoint
before_transition <- farm_data %>% filter(area_farm < (breakpoint - window_size)) %>% mutate(transition_group = "Before Transition")
at_transition <- transition_farms %>% mutate(transition_group = "Transition Zone")
after_transition <- farm_data %>% filter(area_farm > (breakpoint + window_size)) %>% mutate(transition_group = "After Transition")

# Combine and analyze data
transition_analysis <- bind_rows(before_transition, at_transition, after_transition) %>%
  filter(!is.na(transition_group))

### Segmented Regression Analysis

# Fit a logistic regression model first
log_model <- glm(any_ab_use ~ area_farm, data = size_ab_data, family = binomial)

# Summarize the model
summary_log_model <- summary(log_model)
cat("Logistic regression of antibiotic use on farm size:\n")
## Logistic regression of antibiotic use on farm size:
cat("Coefficient for farm size:", coef(log_model)[2], "\n")
## Coefficient for farm size: 0.000042
cat("Standard error:", summary_log_model$coefficients[2, 2], "\n")
## Standard error: 0.000041
cat("p-value:", summary_log_model$coefficients[2, 4], "\n")
## p-value: 0.3
cat("Null deviance:", summary_log_model$null.deviance, "on", summary_log_model$df.null, "degrees of freedom\n")
## Null deviance: 512 on 1155 degrees of freedom
cat("Residual deviance:", summary_log_model$deviance, "on", summary_log_model$df.residual, "degrees of freedom\n")
## Residual deviance: 510 on 1154 degrees of freedom
cat("AIC:", summary_log_model$aic, "\n")
## AIC: 514
# Try to fit a segmented model
# This is wrapped in a tryCatch block because segmented regression might not converge
tryCatch({
  library(segmented)
  
  # Initial guess for breakpoint
  initial_bp <- median(size_ab_data$area_farm)
  
  # Fit segmented model
  segmented_model <- segmented(log_model, seg.Z = ~area_farm, psi = list(area_farm = c(initial_bp)))
  
  # Print summary
  print(summary(segmented_model))
  
  # Extract breakpoints
  breakpoints <- segmented_model$psi[, 2]
  cat("Estimated breakpoint in farm size:", breakpoints, "square meters\n")
  
  # Generate predictions for plotting
  new_data <- data.frame(area_farm = seq(min(size_ab_data$area_farm), 
                                        max(size_ab_data$area_farm), 
                                        length.out = 100))
  
  # Get predictions from both models
  new_data$pred_log <- predict(log_model, newdata = new_data, type = "response")
  new_data$pred_seg <- predict(segmented_model, newdata = new_data, type = "response")
  
  # Plot segmented regression results with comparison to regular logistic regression
  seg_plot <- ggplot(size_ab_data, aes(x = area_farm, y = any_ab_use)) +
    geom_point(alpha = 0.3) +
    geom_line(data = new_data, aes(x = area_farm, y = pred_log, color = "Logistic Regression"), 
              size = 1, linetype = "dashed") +
    geom_line(data = new_data, aes(x = area_farm, y = pred_seg, color = "Segmented Regression"), 
              size = 1) +
    geom_vline(xintercept = breakpoints, linetype = "dashed", color = "red") +
    labs(title = "Segmented Regression of Farm Size and Antibiotic Use",
         subtitle = paste("Breakpoint at", round(breakpoints, 0), "square meters"),
         x = "Farm Area (square meters)",
         y = "Probability of Antibiotic Use",
         color = "Model Type") +
    theme_minimal() +
    scale_color_manual(values = c("Logistic Regression" = "blue", "Segmented Regression" = "red"))
  
  # Print the segmented plot
  print(seg_plot)
  
}, error = function(e) {
  message("Segmented regression did not converge. Using only LOESS smoothing for visualization.")
  print(e)
})
## 
##  ***Regression Model with Segmented Relationship(s)***
## 
## Call: 
## segmented.glm(obj = log_model, seg.Z = ~area_farm, psi = list(area_farm = c(initial_bp)))
## 
## Estimated Break-Point(s):
##                  Est. St.Err
## psi1.area_farm 10000   9231
## 
## Coefficients of the linear terms:
##               Estimate Std. Error z value            Pr(>|z|)    
## (Intercept)   2.573098   0.173096   14.87 <0.0000000000000002 ***
## area_farm     0.000167   0.000120    1.40                0.16    
## U1.area_farm -0.000184   0.000124   -1.48                  NA    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
## Null     deviance: 511.68  on 1155  degrees of freedom
## Residual deviance: 507.02  on 1152  degrees of freedom
## AIC: 515
## 
## Boot restarting based on 9 samples. Last fit:
## Convergence attained in 0 iterations (rel. change -0.00000000000000078463)
## Estimated breakpoint in farm size: 10000 square meters

### Additional Analysis: Farm Size and Specific Antibiotic Types

# Calculate specific antibiotic use by farm size category
specific_ab_by_size <- farm_data %>%
  group_by(farm_size_cat) %>%
  summarise(
    n = n(),
    chlo_pct = mean(chlo, na.rm = TRUE) * 100,
    nitr_pct = mean(nitr, na.rm = TRUE) * 100,
    dime_pct = mean(dime, na.rm = TRUE) * 100,
    metr_pct = mean(metr, na.rm = TRUE) * 100,
    cipr_pct = mean(cipr, na.rm = TRUE) * 100,
    oflo_pct = mean(oflo, na.rm = TRUE) * 100,
    carb_pct = mean(carb, na.rm = TRUE) * 100,
    olaq_pct = mean(olaq, na.rm = TRUE) * 100,
    baci_pct = mean(baci, na.rm = TRUE) * 100,
    .groups = "drop"
  ) %>%
  filter(!is.na(farm_size_cat))

# Convert to long format for visualization
specific_ab_size_long <- specific_ab_by_size %>%
  dplyr::select(-n) %>%
  pivot_longer(cols = -farm_size_cat, 
               names_to = "antibiotic", 
               values_to = "percentage") %>%
  mutate(
    antibiotic = case_when(
      antibiotic == "chlo_pct" ~ "Chloramphenicol",
      antibiotic == "nitr_pct" ~ "Nitrofurans",
      antibiotic == "dime_pct" ~ "Dimetridazole",
      antibiotic == "metr_pct" ~ "Metronidazole",
      antibiotic == "cipr_pct" ~ "Ciprofloxacin",
      antibiotic == "oflo_pct" ~ "Ofloxacin",
      antibiotic == "carb_pct" ~ "Carbadox",
      antibiotic == "olaq_pct" ~ "Olaquindox",
      antibiotic == "baci_pct" ~ "Bacitracin",
      TRUE ~ antibiotic
    )
  )

# Create a heatmap of specific antibiotic use by farm size
size_heatmap <- ggplot(specific_ab_size_long, 
                        aes(x = farm_size_cat, y = antibiotic, fill = percentage)) +
  geom_tile(color = "white") +
  geom_text(aes(label = round(percentage, 1)), size = 3) +
  scale_fill_gradient(low = "white", high = "steelblue") +
  labs(title = "Heatmap of Specific Antibiotic Use by Farm Size Category",
       x = "Farm Size",
       y = "Antibiotic",
       fill = "Prevalence (%)") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 0, hjust = 0.5),
        axis.text.y = element_text(size = 8))

# Print the heatmap
print(size_heatmap)

### Farm Size and Inappropriate Antibiotic Use

# Create an indicator for potentially inappropriate use
# Define inappropriate use as preventive use without disease or growth promotion
farm_data <- farm_data %>%
  mutate(
    inappropriate_use = case_when(
      ab_prevention == 1 | ab_growth == 1 ~ 1,
      TRUE ~ 0
    )
  )

# Analyze inappropriate use by farm size
inappropriate_by_size <- farm_data %>%
  group_by(farm_size_cat) %>%
  summarise(
    n = n(),
    inappropriate_n = sum(inappropriate_use, na.rm = TRUE),
    inappropriate_pct = mean(inappropriate_use, na.rm = TRUE) * 100,
    .groups = "drop"
  ) %>%
  filter(!is.na(farm_size_cat))

# Display results
inappropriate_by_size %>%
  kable(caption = "Inappropriate Antibiotic Use by Farm Size Category",
        col.names = c("Farm Size", "Number of Farms", "Farms with Inappropriate Use", "% Inappropriate Use")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
Inappropriate Antibiotic Use by Farm Size Category
Farm Size Number of Farms Farms with Inappropriate Use % Inappropriate Use
Large 485 243 50
Medium 659 312 47
Small 12 4 33
# Create a bar chart of inappropriate use by farm size
inappropriate_plot <- ggplot(inappropriate_by_size, 
                             aes(x = farm_size_cat, y = inappropriate_pct, fill = farm_size_cat)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = paste0(round(inappropriate_pct, 1), "%")), 
            position = position_stack(vjust = 0.5)) +
  labs(title = "Inappropriate Antibiotic Use by Farm Size",
       subtitle = "Defined as preventive use or growth promotion",
       x = "Farm Size Category",
       y = "Percentage of Farms (%)") +
  theme_minimal() +
  theme(legend.position = "none") +
  scale_fill_brewer(palette = "Blues")

# Print the plot
print(inappropriate_plot)

# LOESS smoothing for inappropriate use by farm size
inappropriate_plot_loess <- ggplot(farm_data %>% filter(!is.na(area_farm)), 
                                   aes(x = area_farm, y = inappropriate_use)) +
  geom_point(alpha = 0.3) +
  geom_smooth(method = "loess", se = TRUE) +
  labs(title = "Non-linear Relationship Between Farm Size and Inappropriate Antibiotic Use",
       subtitle = "LOESS Smoothing Curve with 95% Confidence Interval",
       x = "Farm Area (square meters)",
       y = "Probability of Inappropriate Use") +
  theme_minimal()

# Print the LOESS plot
print(inappropriate_plot_loess)

1.6 Results for Hypothesis 1.4: Isomorphism in Antibiotic Use Patterns within Communities

if(!exists("farm_data")) {
  farm_data <- readRDS(here("data", "processed", "farm_data_processed.rds"))
}
if(!exists("household_data")) {
  household_data <- readRDS(here("data", "processed", "household_data_processed.rds"))
}

# Check if we have geographic identifiers for community-level analysis
if(!"geo_id" %in% names(farm_data) || !"geo_id" %in% names(household_data)) {
  cat("Geographic identifiers not found in one or both datasets.\n")
  cat("Creating proxy geographic identifiers based on available information.\n")
  
  # Check for district and commune variables
  if(all(c("district", "commune") %in% names(farm_data)) && 
     all(c("district", "commune") %in% names(household_data))) {
    
    # Create geographic ID for community-level analysis
    farm_data <- farm_data %>%
      mutate(geo_id = paste(district, commune, sep = "_"))
    
    household_data <- household_data %>%
      mutate(geo_id = paste(district, commune, sep = "_"))
    
    cat("Created geo_id using district and commune variables.\n")
  } else {
    # If standard geographic variables don't exist, use farm_id pattern if available
    if("farm_id" %in% names(farm_data)) {
      farm_data <- farm_data %>%
        mutate(
          # Extract first part of farm_id as geographic identifier
          # This assumes farm_id has a structure where the first digits represent location
          geo_id = substr(as.character(farm_id), 1, 5)
        )
      
      # For household data, create a mock geo_id for demonstration
      # In a real analysis, we would need a proper way to link households to communities
      household_data <- household_data %>%
        mutate(
          geo_id = sample(unique(farm_data$geo_id), size = n(), replace = TRUE)
        )
      
      cat("Created proxy geo_id using farm_id pattern. Note: This is for demonstration only.\n")
      cat("In a real analysis, proper geographic linkage is required.\n")
    } else {
      cat("No suitable geographic identifiers found. Community-level analysis will be skipped.\n")
      # Exit the analysis if no geographic identifiers are available
      return(NULL)
    }
  }
}

# Aggregate farm antibiotic use by community
farm_community <- farm_data %>%
  group_by(geo_id) %>%
  summarise(
    farm_count = n(),
    farm_ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
    farm_ab_treatment_pct = mean(ab_treatment, na.rm = TRUE) * 100,
    farm_ab_prevention_pct = mean(ab_prevention, na.rm = TRUE) * 100,
    farm_ab_growth_pct = mean(ab_growth, na.rm = TRUE) * 100,
    .groups = "drop"
  ) %>%
  filter(farm_count >= 3)  # Only include communities with at least 3 farms

# Aggregate household antibiotic use by community
household_community <- household_data %>%
  group_by(geo_id) %>%
  summarise(
    household_count = n(),
    household_ab_use_pct = mean(any_ab_last_illness, na.rm = TRUE) * 100,
    .groups = "drop"
  ) %>%
  filter(household_count >= 3)  # Only include communities with at least 3 households

# Join farm and household community data
community_comparison <- inner_join(farm_community, household_community, by = "geo_id")

# Display the number of communities with sufficient data
cat("Number of communities with sufficient data for comparison:", nrow(community_comparison), "\n")
## Number of communities with sufficient data for comparison: 64
# Display community-level comparison data
community_comparison %>%
  dplyr::select(geo_id, farm_count, household_count, farm_ab_use_pct, household_ab_use_pct) %>%
  kable(caption = "Community-level Antibiotic Use in Farms and Households",
        col.names = c("Community ID", "Number of Farms", "Number of Households", 
                     "Farm Antibiotic Use (%)", "Household Antibiotic Use (%)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
Community-level Antibiotic Use in Farms and Households
Community ID Number of Farms Number of Households Farm Antibiotic Use (%) Household Antibiotic Use (%)
4_1 20 219 100 0.46
4_10 20 161 100 8.07
4_11 18 151 94 2.65
4_12 20 147 100 3.40
4_13 20 135 85 11.11
4_14 16 156 100 3.85
4_15 20 153 100 3.92
4_16 20 166 100 6.02
4_17 18 182 100 9.34
4_18 20 175 100 5.71
4_19 20 167 95 8.98
4_2 16 154 94 5.84
4_20 18 186 100 5.38
4_21 20 160 95 1.87
4_22 20 139 75 5.04
4_23 20 156 100 4.49
4_24 19 131 100 17.56
4_25 20 187 100 1.60
4_26 19 184 89 2.72
4_27 20 176 85 5.11
4_28 18 228 78 13.16
4_3 19 154 95 3.25
4_4 20 162 100 8.02
4_5 20 181 95 6.08
4_6 20 195 75 8.72
4_7 20 136 100 1.47
4_8 20 152 100 3.95
4_9 19 194 95 1.03
5_1 16 152 75 1.97
5_10 11 120 100 12.50
5_11 16 129 100 0.00
5_12 16 127 100 1.57
5_13 16 100 94 0.00
5_14 16 167 88 12.57
5_15 16 103 100 0.97
5_16 16 106 100 9.43
5_17 16 159 100 3.14
5_18 17 134 100 0.00
5_19 16 154 69 4.55
5_2 16 99 94 25.25
5_20 16 57 100 8.77
5_3 16 135 100 24.44
5_4 13 104 100 23.08
5_5 16 137 100 3.65
5_6 16 186 94 3.76
5_7 16 135 94 0.74
5_8 16 120 100 6.67
5_9 16 119 69 2.52
6_1 18 113 94 4.42
6_10 20 178 85 0.56
6_11 20 123 100 0.00
6_12 19 156 95 0.00
6_13 15 147 80 4.76
6_14 19 169 89 1.78
6_15 17 149 100 0.00
6_16 20 131 95 5.34
6_2 19 103 100 2.91
6_3 18 119 100 6.72
6_4 19 97 79 5.15
6_5 20 137 95 0.00
6_6 19 120 95 7.50
6_7 20 150 100 6.67
6_8 20 148 95 16.22
6_9 20 141 100 0.00
### Correlation Analysis

# Calculate Pearson correlation between farm and household antibiotic use
correlation_result <- cor.test(
  community_comparison$farm_ab_use_pct,
  community_comparison$household_ab_use_pct,
  method = "pearson"
)

# Display correlation results
cat("Pearson correlation between farm and household antibiotic use at community level:\n")
## Pearson correlation between farm and household antibiotic use at community level:
cat("Correlation coefficient (r):", correlation_result$estimate, "\n")
## Correlation coefficient (r): 0.017
cat("95% confidence interval: [", correlation_result$conf.int[1], ",", correlation_result$conf.int[2], "]\n")
## 95% confidence interval: [ -0.23 , 0.26 ]
cat("t-statistic:", correlation_result$statistic, "\n")
## t-statistic: 0.13
cat("Degrees of freedom:", correlation_result$parameter, "\n")
## Degrees of freedom: 62
cat("P-value:", correlation_result$p.value, "\n")
## P-value: 0.9
cat("Interpretation:", ifelse(correlation_result$p.value < 0.05, 
                             "Significant correlation", 
                             "No significant correlation"), "\n")
## Interpretation: No significant correlation
# Calculate Spearman correlation (less sensitive to outliers)
spearman_result <- cor.test(
  community_comparison$farm_ab_use_pct,
  community_comparison$household_ab_use_pct,
  method = "spearman"
)

cat("\nSpearman rank correlation (robust to outliers):\n")
## 
## Spearman rank correlation (robust to outliers):
cat("Correlation coefficient (rho):", spearman_result$estimate, "\n")
## Correlation coefficient (rho): -0.014
cat("P-value:", spearman_result$p.value, "\n")
## P-value: 0.91
### Visualization of Community-level Patterns

# Scatter plot of farm vs. household antibiotic use at community level
community_plot <- ggplot(community_comparison, 
                         aes(x = farm_ab_use_pct, y = household_ab_use_pct)) +
  geom_point(aes(size = farm_count + household_count), alpha = 0.6) +
  geom_smooth(method = "lm", se = TRUE, color = "blue") +
  labs(title = "Community-level Correlation Between Farm and Household Antibiotic Use",
       subtitle = paste("Pearson correlation =", round(correlation_result$estimate, 2), 
                        ", p-value =", round(correlation_result$p.value, 3)),
       x = "Farm Antibiotic Use (%)",
       y = "Household Antibiotic Use (%)",
       size = "Number of Respondents") +
  theme_minimal()

# Print the community-level correlation plot
print(community_plot)

### Multiple Regression Analysis

# Prepare data for regression analysis - add more community characteristics if available
# For example, average educational level, socioeconomic indicators, etc.
if(all(c("edu", "area_farm") %in% names(farm_data))) {
  # Aggregate additional farm characteristics
  farm_community_extended <- farm_data %>%
    group_by(geo_id) %>%
    summarise(
      farm_count = n(),
      farm_ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
      farm_edu_mean = mean(as.numeric(edu), na.rm = TRUE),  # Assuming edu is a numeric or ordinal variable
      farm_size_mean = mean(area_farm, na.rm = TRUE),
      .groups = "drop"
    ) %>%
    filter(farm_count >= 3)
  
  # Join with household data
  if("edu" %in% names(household_data)) {
    household_community_extended <- household_data %>%
      group_by(geo_id) %>%
      summarise(
        household_count = n(),
        household_ab_use_pct = mean(any_ab_last_illness, na.rm = TRUE) * 100,
        household_edu_mean = mean(as.numeric(edu), na.rm = TRUE),
        .groups = "drop"
      ) %>%
      filter(household_count >= 3)
    
    # Join data
    community_regression <- inner_join(farm_community_extended, household_community_extended, by = "geo_id")
    
    # Regression model: Household antibiotic use as a function of farm antibiotic use and covariates
    model <- lm(household_ab_use_pct ~ farm_ab_use_pct + farm_edu_mean + household_edu_mean + farm_size_mean,
               data = community_regression)
    
    # Display regression results
    cat("\nMultiple regression analysis:\n")
    cat("Dependent variable: Household antibiotic use percentage\n\n")
    print(summary(model))
    
    # Calculate VIF to check for multicollinearity
    if(requireNamespace("car", quietly = TRUE)) {
      cat("\nVariance Inflation Factors (checking for multicollinearity):\n")
      print(car::vif(model))
    }
  }
}

### Analysis of Purpose-Specific Correlations

# Examine correlations between household antibiotic use and specific farm antibiotic purposes
purpose_correlations <- data.frame(
  Purpose = c("Treatment", "Prevention", "Growth Promotion"),
  Correlation = c(
    cor(community_comparison$household_ab_use_pct, community_comparison$farm_ab_treatment_pct, 
        use = "pairwise.complete.obs"),
    cor(community_comparison$household_ab_use_pct, community_comparison$farm_ab_prevention_pct, 
        use = "pairwise.complete.obs"),
    cor(community_comparison$household_ab_use_pct, community_comparison$farm_ab_growth_pct, 
        use = "pairwise.complete.obs")
  )
)

# Calculate p-values for these correlations
purpose_correlations$PValue <- c(
  cor.test(community_comparison$household_ab_use_pct, community_comparison$farm_ab_treatment_pct)$p.value,
  cor.test(community_comparison$household_ab_use_pct, community_comparison$farm_ab_prevention_pct)$p.value,
  cor.test(community_comparison$household_ab_use_pct, community_comparison$farm_ab_growth_pct)$p.value
)

purpose_correlations$Significant <- purpose_correlations$PValue < 0.05

# Display purpose-specific correlations
purpose_correlations %>%
  mutate(
    Correlation = round(Correlation, 3),
    PValue = round(PValue, 3),
    Significant = ifelse(Significant, "Yes", "No")
  ) %>%
  kable(caption = "Correlations Between Household Antibiotic Use and Farm Antibiotic Use by Purpose",
        col.names = c("Farm Antibiotic Purpose", "Correlation with Household Use", 
                     "P-Value", "Significant")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
Correlations Between Household Antibiotic Use and Farm Antibiotic Use by Purpose
Farm Antibiotic Purpose Correlation with Household Use P-Value Significant
Treatment 0.01 0.95 No
Prevention 0.00 0.99 No
Growth Promotion -0.09 0.49 No
# If information source data is available, analyze relationship with community patterns
if("q7_19" %in% names(household_data) & "advice1" %in% names(farm_data)) {
  # Categorize information sources and aggregate at community level
  household_info_sources <- household_data %>%
    group_by(geo_id) %>%
    summarise(
      # Count frequency of different information sources
      # This would need to be adapted based on actual coding of information sources
      household_info_healthcare = mean(q7_19 == 1 | q7_19 == 2 | q7_19 == 3, na.rm = TRUE) * 100,
      household_info_pharmacy = mean(q7_19 == 5, na.rm = TRUE) * 100,
      household_info_social = mean(q7_19 == 8, na.rm = TRUE) * 100,
      .groups = "drop"
    )
  
  farm_info_sources <- farm_data %>%
    group_by(geo_id) %>%
    summarise(
      # Count frequency of different information sources
      # This would need to be adapted based on actual coding of information sources
      farm_info_veterinary = mean(grepl("vet", advice1, ignore.case = TRUE), na.rm = TRUE) * 100,
      farm_info_pharmacy = mean(grepl("pharm", advice1, ignore.case = TRUE), na.rm = TRUE) * 100,
      farm_info_social = mean(grepl("friend|neighbor", advice1, ignore.case = TRUE), na.rm = TRUE) * 100,
      .groups = "drop"
    )
  
  # Join information source data with community comparison data
  community_info <- community_comparison %>%
    left_join(household_info_sources, by = "geo_id") %>%
    left_join(farm_info_sources, by = "geo_id")
  
  # Analyze correlation between similar information sources across sectors
  cat("\nCorrelations between information sources across sectors:\n")
  if(ncol(community_info) > 8) {  # Check if information source variables were successfully joined
    info_correlations <- data.frame(
      Sources = c("Healthcare/Veterinary", "Pharmacy", "Social Networks"),
      Correlation = c(
        cor(community_info$household_info_healthcare, community_info$farm_info_veterinary, 
            use = "pairwise.complete.obs"),
        cor(community_info$household_info_pharmacy, community_info$farm_info_pharmacy, 
            use = "pairwise.complete.obs"),
        cor(community_info$household_info_social, community_info$farm_info_social, 
            use = "pairwise.complete.obs")
      )
    )
    
    # Calculate p-values
    info_correlations$PValue <- c(
      cor.test(community_info$household_info_healthcare, community_info$farm_info_veterinary)$p.value,
      cor.test(community_info$household_info_pharmacy, community_info$farm_info_pharmacy)$p.value,
      cor.test(community_info$household_info_social, community_info$farm_info_social)$p.value
    )
    
    info_correlations$Significant <- info_correlations$PValue < 0.05
    
    # Display information source correlations
    info_correlations %>%
      mutate(
        Correlation = round(Correlation, 3),
        PValue = round(PValue, 3),
        Significant = ifelse(Significant, "Yes", "No")
      ) %>%
      kable(caption = "Correlations Between Information Sources in Households and Farms",
            col.names = c("Information Source", "Correlation", "P-Value", "Significant")) %>%
      kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
  } else {
    cat("Information source variables not available or not successfully joined.\n")
  }
}

### Multilevel Model for Community Effects

# For farm data
if(length(unique(farm_data$geo_id)) >= 10) {  # Need sufficient number of communities
  # Filter data for multilevel modeling
  farm_mlm <- farm_data %>%
    filter(!is.na(geo_id) & !is.na(any_ab_use))
  
  # Fit random intercept model
  farm_model <- tryCatch({
    library(lme4)
    glmer(any_ab_use ~ (1 | geo_id), data = farm_mlm, family = binomial)
  }, error = function(e) {
    message("Error fitting multilevel model for farm data: ", e$message)
    return(NULL)
  })
  
  # Display model summary if successful
  if(!is.null(farm_model)) {
    cat("\nMultilevel model for farm antibiotic use:\n")
    print(summary(farm_model))
    
    # Calculate intraclass correlation coefficient (ICC)
    if(requireNamespace("performance", quietly = TRUE)) {
      cat("\nIntraclass correlation coefficient (ICC) for farms:\n")
      farm_icc <- performance::icc(farm_model)
      print(farm_icc)
      cat("Interpretation: ", 
          ifelse(farm_icc$ICC > 0.05, 
                "Community membership explains a meaningful proportion of variance in farm antibiotic use.", 
                "Community membership explains little variance in farm antibiotic use."), 
          "\n")
    }
  }
  
  # For household data
  household_mlm <- household_data %>%
    filter(!is.na(geo_id) & !is.na(any_ab_last_illness))
  
  # Fit random intercept model
  household_model <- tryCatch({
    glmer(any_ab_last_illness ~ (1 | geo_id), data = household_mlm, family = binomial)
  }, error = function(e) {
    message("Error fitting multilevel model for household data: ", e$message)
    return(NULL)
  })
  
  # Display model summary if successful
  if(!is.null(household_model)) {
    cat("\nMultilevel model for household antibiotic use:\n")
    print(summary(household_model))
    
    # Calculate intraclass correlation coefficient (ICC)
    if(requireNamespace("performance", quietly = TRUE)) {
      cat("\nIntraclass correlation coefficient (ICC) for households:\n")
      household_icc <- performance::icc(household_model)
      print(household_icc)
      cat("Interpretation: ", 
          ifelse(household_icc$ICC > 0.05, 
                "Community membership explains a meaningful proportion of variance in household antibiotic use.", 
                "Community membership explains little variance in household antibiotic use."), 
          "\n")
    }
  }
} else {
  cat("\nInsufficient number of communities for multilevel modeling.\n")
}
## 
## Multilevel model for farm antibiotic use:
## Generalized linear mixed model fit by maximum likelihood (Laplace
##   Approximation) [glmerMod]
##  Family: binomial  ( logit )
## Formula: any_ab_use ~ (1 | geo_id)
##    Data: farm_mlm
## 
##      AIC      BIC   logLik deviance df.resid 
##      488      498     -242      484     1154 
## 
## Scaled residuals: 
##    Min     1Q Median     3Q    Max 
## -4.811  0.138  0.144  0.214  0.535 
## 
## Random effects:
##  Groups Name        Variance Std.Dev.
##  geo_id (Intercept) 1.5      1.22    
## Number of obs: 1156, groups:  geo_id, 64
## 
## Fixed effects:
##             Estimate Std. Error z value            Pr(>|z|)    
## (Intercept)    3.399      0.279    12.2 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Intraclass correlation coefficient (ICC) for farms:
## # Intraclass Correlation Coefficient
## 
##     Adjusted ICC: 0.313
##   Unadjusted ICC: 0.313
## Interpretation:   
## 
## Multilevel model for household antibiotic use:
## Generalized linear mixed model fit by maximum likelihood (Laplace
##   Approximation) [glmerMod]
##  Family: binomial  ( logit )
## Formula: any_ab_last_illness ~ (1 | geo_id)
##    Data: household_mlm
## 
##      AIC      BIC   logLik deviance df.resid 
##     3757     3771    -1876     3753     9409 
## 
## Scaled residuals: 
##    Min     1Q Median     3Q    Max 
## -0.552 -0.259 -0.200 -0.131  9.866 
## 
## Random effects:
##  Groups Name        Variance Std.Dev.
##  geo_id (Intercept) 1.09     1.05    
## Number of obs: 9411, groups:  geo_id, 64
## 
## Fixed effects:
##             Estimate Std. Error z value            Pr(>|z|)    
## (Intercept)   -3.237      0.147     -22 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Intraclass correlation coefficient (ICC) for households:
## # Intraclass Correlation Coefficient
## 
##     Adjusted ICC: 0.249
##   Unadjusted ICC: 0.249
## Interpretation:
### Sensitivity Analysis

# Perform sensitivity analysis with different community-level aggregation thresholds
thresholds <- c(2, 3, 5)
sensitivity_results <- data.frame(
  Threshold = integer(),
  NCommunities = integer(),
  Correlation = numeric(),
  PValue = numeric(),
  stringsAsFactors = FALSE
)

for(threshold in thresholds) {
  # Aggregate with current threshold
  farm_comm_sens <- farm_data %>%
    group_by(geo_id) %>%
    summarise(
      farm_count = n(),
      farm_ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
      .groups = "drop"
    ) %>%
    filter(farm_count >= threshold)
  
  household_comm_sens <- household_data %>%
    group_by(geo_id) %>%
    summarise(
      household_count = n(),
      household_ab_use_pct = mean(any_ab_last_illness, na.rm = TRUE) * 100,
      .groups = "drop"
    ) %>%
    filter(household_count >= threshold)
  
  # Join data
  comm_comp_sens <- inner_join(farm_comm_sens, household_comm_sens, by = "geo_id")
  
  # Calculate correlation
  if(nrow(comm_comp_sens) > 5) {  # Need at least a few communities for meaningful correlation
    corr_result <- cor.test(comm_comp_sens$farm_ab_use_pct, comm_comp_sens$household_ab_use_pct)
    
    # Store results
    sensitivity_results <- rbind(sensitivity_results, data.frame(
      Threshold = threshold,
      NCommunities = nrow(comm_comp_sens),
      Correlation = corr_result$estimate,
      PValue = corr_result$p.value,
      stringsAsFactors = FALSE
    ))
  }
}

# Display sensitivity analysis results
if(nrow(sensitivity_results) > 0) {
  sensitivity_results %>%
    mutate(
      Correlation = round(Correlation, 3),
      PValue = round(PValue, 3),
      Significant = ifelse(PValue < 0.05, "Yes", "No")
    ) %>%
    kable(caption = "Sensitivity Analysis: Community-Level Correlations with Different Thresholds",
          col.names = c("Minimum Respondents per Community", "Number of Communities", 
                       "Correlation", "P-Value", "Significant")) %>%
    kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
} else {
  cat("\nInsufficient data for sensitivity analysis with different thresholds.\n")
}
Sensitivity Analysis: Community-Level Correlations with Different Thresholds
Minimum Respondents per Community Number of Communities Correlation P-Value Significant
cor 2 64 0.02 0.9 No
cor1 3 64 0.02 0.9 No
cor2 5 64 0.02 0.9 No
#---------------------------------------------------------------------
# 1. Geographic Community Analysis with Enhanced Spatial Statistics
#---------------------------------------------------------------------

cat("\n## Geographic Community Analysis ##\n")
## 
## ## Geographic Community Analysis ##
# Check for geographical coordinates
has_geo_coords <- all(c("latitude", "longitude") %in% names(farm_data))

if(has_geo_coords) {
  # Filter farm data to records with valid coordinates
  geo_farms <- farm_data %>%
    filter(!is.na(latitude) & !is.na(longitude)) %>%
    dplyr::select(farm_id, latitude, longitude, any_ab_use, ab_treatment, ab_prevention, ab_growth)
  
  # Calculate distance matrix between farms (in meters)
  if(nrow(geo_farms) > 1000) {
  cat("Note: Farm size is large, use spatial index to optimise distance calculation.")
  geo_farms_sample <- geo_farms %>% sample_n(min(1000, nrow(geo_farms)))
  coords_matrix <- geo_farms_sample %>%
    dplyr::select(longitude, latitude) %>%
    as.matrix()
} else {
  coords_matrix <- geo_farms %>%
    dplyr::select(longitude, latitude) %>%
    as.matrix()
}
  
  dist_matrix <- distm(coords_matrix, fun = distHaversine)
  rownames(dist_matrix) <- geo_farms$farm_id
  colnames(dist_matrix) <- geo_farms$farm_id
  
  # Define distance thresholds to test (in kilometers)
  thresholds_km <- c(2, 5, 10)
  
  # Initialize results dataframe
  geo_community_results <- data.frame(
    threshold_km = numeric(),
    n_communities = numeric(),
    mean_community_size = numeric(),
    within_community_ab_correlation = numeric(),
    p_value = numeric(),
    stringsAsFactors = FALSE
  )
  
  for(threshold_km in thresholds_km) {
    threshold_m <- threshold_km * 1000
    
    # Create adjacency matrix based on threshold
    adj_matrix <- dist_matrix < threshold_m & dist_matrix > 0  # Exclude self-connections
    
    # Convert to igraph object
    g <- graph_from_adjacency_matrix(adj_matrix, mode = "undirected")
    
    # Identify communities (connected components)
    communities <- components(g)
    
    # Label each farm with its community ID
    geo_farms$geo_community_id <- communities$membership
    
    # Filter to communities with at least 3 farms
    valid_communities <- geo_farms %>%
      count(geo_community_id) %>%
      filter(n >= 3) %>%
      pull(geo_community_id)
    
    if(length(valid_communities) > 0) {
      # Filter farms to those in valid communities
      community_farms <- geo_farms %>%
        filter(geo_community_id %in% valid_communities)
      
      # Compute within-community similarity in antibiotic use
      if(nrow(community_farms) >= 10) {  # Need sufficient data for meaningful test
        # Calculate average within-community standard deviation of antibiotic use
        community_stats <- community_farms %>%
          group_by(geo_community_id) %>%
          summarize(
            ab_use_sd = sd(any_ab_use, na.rm = TRUE),
            ab_use_mean = mean(any_ab_use, na.rm = TRUE),
            n_farms = n(),
            .groups = "drop"
          )
          
        # Calculate overall standard deviation for comparison
        overall_sd <- sd(community_farms$any_ab_use, na.rm = TRUE)
          
        # Calculate weighted average of within-community SD
        weighted_avg_sd <- sum(community_stats$ab_use_sd * community_stats$n_farms) / sum(community_stats$n_farms)
          
        # Store results
        geo_community_results <- rbind(geo_community_results, data.frame(
          threshold_km = threshold_km,
          n_communities = length(valid_communities),
          mean_community_size = mean(community_stats$n_farms),
          within_community_ab_correlation = 1 - (weighted_avg_sd / overall_sd), # Higher value = more similarity
          p_value = NA, # Will fill with appropriate test if available
          stringsAsFactors = FALSE
        ))
        
        # Visualization for 5km threshold 
        if(threshold_km == 5) {
          # Convert to sf objects for mapping
          farms_sf <- st_as_sf(community_farms, coords = c("longitude", "latitude"), crs = 4326)
          
          # Create plot
          geo_community_plot <- ggplot() +
            geom_sf(data = farms_sf, aes(color = factor(geo_community_id), size = any_ab_use)) +
            scale_color_viridis_d(name = "Geographic\nCommunity") +
            scale_size_continuous(name = "Antibiotic Use", range = c(1, 5)) +
            labs(title = paste0("Geographic Communities of Farms (", threshold_km, "km threshold)"),
                 subtitle = "Point size indicates antibiotic use prevalence") +
            theme_minimal()
          
          print(geo_community_plot)
        }
      }
    }
  }
  
  # Display geographic community results table
  if(nrow(geo_community_results) > 0) {
    geo_community_results %>%
      mutate(
        within_community_ab_correlation = round(within_community_ab_correlation, 3),
        p_value = ifelse(is.na(p_value), NA, round(p_value, 3)),
        significant = ifelse(p_value < 0.05, "Yes", ifelse(is.na(p_value), "NA", "No"))
      ) %>%
      kable(caption = "Geographic Community Analysis Results for Different Distance Thresholds",
            col.names = c("Distance Threshold (km)", "Number of Communities", 
                         "Mean Community Size", "Within-Community Similarity", 
                         "P-Value", "Significant")) %>%
      kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
  }
  
  # Enhanced Spatial Analysis: Moran's I and LISA Statistics
  if(nrow(geo_farms) >= 10) {
    cat("\n## Spatial Autocorrelation Analysis ##\n")
    
    # Create spatial weights matrix for farms
    coordinates <- coords_matrix
    k <- min(15, nrow(geo_farms) - 1)  # Choose appropriate k value
    knn <- knearneigh(coordinates, k = k)
    neighbors <- knn2nb(knn)
    weights <- nb2listw(neighbors, style = "W")
    
    # Calculate Global Moran's I for antibiotic use
    moran_result <- moran.test(geo_farms$any_ab_use, weights)
    
    # Report Moran's I results
    cat("Global Moran's I for antibiotic use:", round(moran_result$estimate[1], 3), 
        ", p-value:", round(moran_result$p.value, 3), "\n")
    trend_model <- lm(any_ab_use ~ longitude + latitude, data = geo_farms)
trend_summary <- summary(trend_model)

cat("Examine spatial trends in antibiotic use\n")
cat("Spatial trend model R²:", round(trend_summary$r.squared, 3), 
    ", p_value:", round(trend_summary$coefficients[2,4], 3), "/", 
    round(trend_summary$coefficients[3,4], 3), "\n")

# If there is a spatial trend, spatial autocorrelation is analysed after considering de-trending
if(trend_summary$coefficients[2,4] < 0.05 || trend_summary$coefficients[3,4] < 0.05) {
  cat("There is a significant spatial trend. Consider detrending before spatial autocorrelation analysis\n")
  geo_farms$ab_use_detrended <- residuals(trend_model)
  
  # Recalculating spatial autocorrelation using detrended data
  moran_detrended <- moran.test(geo_farms$ab_use_detrended, weights)
  cat("Moran's I after trend removal:", round(moran_detrended$estimate[1], 3), 
      ", p_value:", round(moran_detrended$p.value, 3), "\n")
}
    
    # Calculate LISA
    lisa_results <- localmoran(geo_farms$any_ab_use, weights)
    
    # Add LISA results to farm data
    geo_farms$lisa_i <- lisa_results[, 1]
    geo_farms$lisa_p <- lisa_results[, 5]
    
    # Identify hotspots and coldspots
    mean_ab_use <- mean(geo_farms$any_ab_use, na.rm = TRUE)
    geo_farms <- geo_farms %>%
      mutate(
        cluster_type = case_when(
          lisa_p <= 0.05 & lisa_i > 0 & any_ab_use > mean_ab_use ~ "Hotspot",
          lisa_p <= 0.05 & lisa_i > 0 & any_ab_use <= mean_ab_use ~ "Coldspot",
          lisa_p <= 0.05 & lisa_i < 0 ~ "Spatial Outlier",
          TRUE ~ "Not Significant"
        )
      )
    
    # Visualize LISA clusters
    lisa_plot <- ggplot(geo_farms, aes(x = longitude, y = latitude, color = cluster_type)) +
      geom_point(size = 3, alpha = 0.8) +
      scale_color_manual(values = c("Hotspot" = "red", "Coldspot" = "blue", 
                                   "Spatial Outlier" = "purple", "Not Significant" = "grey")) +
      labs(title = "Spatial Clustering of Antibiotic Use",
           subtitle = "Based on Local Indicators of Spatial Association (LISA)",
           x = "Longitude",
           y = "Latitude",
           color = "Cluster Type") +
      theme_minimal()
    
    print(lisa_plot)
    
    # Show cluster summary statistics
    geo_farms %>%
      count(cluster_type) %>%
      mutate(percentage = n / sum(n) * 100) %>%
      arrange(desc(n)) %>%
      kable(caption = "Summary of Spatial Clustering",
            col.names = c("Cluster Type", "Number of Farms", "Percentage")) %>%
      kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
  }
  
  # Analyze distance decay effect
  cat("\n## Distance Decay Analysis ##\n")
  
  # Create distance bins (in kilometers)
  distance_bins <- c(0, 1, 2, 5, 10, 20, 50)
  distance_bins_m <- distance_bins * 1000  # Convert to meters
  
  # Initialize results dataframe
  distance_decay <- data.frame(
    distance_min_km = distance_bins[-length(distance_bins)],
    distance_max_km = distance_bins[-1],
    farm_pairs = numeric(length(distance_bins) - 1),
    correlation = numeric(length(distance_bins) - 1),
    stringsAsFactors = FALSE
  )
  
  # Calculate correlation at different distance bands
  for(i in 1:(length(distance_bins_m) - 1)) {
    # Filter farm pairs within this distance band
    pairs_mask <- dist_matrix > distance_bins_m[i] & dist_matrix <= distance_bins_m[i+1]
    
    # Need sufficient pairs for meaningful correlation
    if(sum(pairs_mask) >= 10) {
      # Get coordinates of pairs in this distance band
      farm_pairs <- which(pairs_mask, arr.ind = TRUE)
      
      # Extract antibiotic use values
      ab_use_1 <- geo_farms$any_ab_use[farm_pairs[, 1]]
      ab_use_2 <- geo_farms$any_ab_use[farm_pairs[, 2]]
      
      # Calculate correlation
      distance_decay$farm_pairs[i] <- length(ab_use_1)
      distance_decay$correlation[i] <- cor(ab_use_1, ab_use_2, use = "pairwise.complete.obs")
    }
  }
  
  # Display distance decay results
  distance_decay %>%
    filter(farm_pairs > 0) %>%
    mutate(correlation = round(correlation, 3)) %>%
    kable(caption = "Distance Decay Effect in Antibiotic Use Similarity",
          col.names = c("Min Distance (km)", "Max Distance (km)", 
                       "Number of Farm Pairs", "Correlation"),
          digits = c(1, 1, 0, 3)) %>%
    kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
  
  # Visualize distance decay effect
  decay_plot <- ggplot(distance_decay %>% filter(farm_pairs > 0), 
                       aes(x = (distance_min_km + distance_max_km)/2, y = correlation)) +
    geom_point(aes(size = farm_pairs), alpha = 0.7) +
    geom_line() +
    geom_hline(yintercept = 0, linetype = "dashed", color = "grey50") +
    labs(title = "Distance Decay Effect in Antibiotic Use Similarity",
         x = "Distance (km)",
         y = "Correlation Coefficient",
         size = "Number of Farm Pairs") +
    theme_minimal()
  
  print(decay_plot)
} else {
  cat("Geographic coordinates not available for spatial community analysis.\n")
}
## Geographic coordinates not available for spatial community analysis.
#---------------------------------------------------------------------
# 2. Information Transmission Network Analysis with Enhanced Source Analysis
#---------------------------------------------------------------------

cat("\n## Information Transmission Network Analysis ##\n")
## 
## ## Information Transmission Network Analysis ##
# Check for information source variables
if(all(c("advice1", "advice2", "advice3") %in% names(farm_data))) {
  # Standardize and clean information source variables
  farm_info <- farm_data %>%
    dplyr::select(farm_id, advice1, advice2, advice3, any_ab_use, ab_treatment, ab_prevention, ab_growth) %>%
    filter(!is.na(advice1))  # At least primary advice source must be available
  
  cat("Analyzing", nrow(farm_info), "farms with information source data...\n")
  
  # Convert to lowercase and standardize source names if text
  if(is.character(farm_info$advice1)) {
    # Create a function to categorize advice sources
    categorize_advice <- function(advice) {
      case_when(
        grepl("vet|doctor|health|medic", advice, ignore.case = TRUE) ~ "Professional healthcare",
        grepl("pharm|drug", advice, ignore.case = TRUE) ~ "Pharmacy/drug store",
        grepl("friend|neighbor|relative|family", advice, ignore.case = TRUE) ~ "Social network",
        grepl("tv|radio|internet|media|news", advice, ignore.case = TRUE) ~ "Media",
        grepl("company|supplier|sale", advice, ignore.case = TRUE) ~ "Supplier/company",
        !is.na(advice) ~ "Other",
        TRUE ~ NA_character_
      )
    }
    
    # Apply standardization to all advice sources
    unique_sources <- unique(na.omit(c(farm_info$advice1, farm_info$advice2, farm_info$advice3)))

if(length(unique_sources) > 20) {
  cat("Many different sources of information exist (", length(unique_sources), "),Consider using text analysis methods\n")
  if(requireNamespace("tm", quietly = TRUE) && requireNamespace("proxy", quietly = TRUE)) {
    source_corpus <- tm::Corpus(tm::VectorSource(unique_sources))
    source_dtm <- tm::DocumentTermMatrix(source_corpus)
    source_dist <- proxy::dist(as.matrix(source_dtm))
    source_clusters <- hclust(source_dist)
    num_clusters <- min(5, length(unique_sources) %/% 4) 
    source_categories <- cutree(source_clusters, k = num_clusters)
  }
}
    
    farm_info <- farm_info %>%
      mutate(
        advice1_category = categorize_advice(advice1),
        advice2_category = categorize_advice(advice2),
        advice3_category = categorize_advice(advice3),
        primary_source_std = advice1_category  # Use first advice source as primary
      )
    
    # Show distribution of primary information sources
    farm_info %>%
      count(primary_source_std) %>%
      mutate(percentage = n / sum(n) * 100) %>%
      arrange(desc(n)) %>%
      kable(caption = "Distribution of Primary Information Sources for Antibiotic Use",
            col.names = c("Information Source", "Number of Farms", "Percentage (%)"),
            digits = c(0, 0, 1)) %>%
      kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
    
    # Analyze antibiotic use by information source
    source_summary <- farm_info %>%
      group_by(primary_source_std) %>%
      summarise(
        n_farms = n(),
        ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
        ab_treatment_pct = mean(ab_treatment, na.rm = TRUE) * 100,
        ab_prevention_pct = mean(ab_prevention, na.rm = TRUE) * 100,
        ab_growth_pct = mean(ab_growth, na.rm = TRUE) * 100,
        .groups = "drop"
      ) %>%
      filter(n_farms >= 5)  # Only include sources with sufficient data
    
    # Display results
    source_summary %>%
      mutate(across(ends_with("_pct"), ~ round(., 1))) %>%
      kable(caption = "Antibiotic Use Patterns by Primary Information Source",
            col.names = c("Information Source", "Number of Farms", "Any Antibiotic Use (%)",
                         "Treatment Use (%)", "Prevention Use (%)", "Growth Promotion Use (%)")) %>%
      kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
    
    # Visualize antibiotic use by information source
    plot_data <- source_summary %>%
      filter(n_farms >= 5) %>%
      gather(key = "purpose", value = "percentage", 
             ab_use_pct, ab_treatment_pct, ab_prevention_pct, ab_growth_pct) %>%
      mutate(purpose = factor(purpose, 
                            levels = c("ab_use_pct", "ab_treatment_pct", 
                                       "ab_prevention_pct", "ab_growth_pct"),
                            labels = c("Any Use", "Treatment", "Prevention", "Growth")))
    
    # Create and display the bar chart
    source_purpose_plot <- ggplot(plot_data, aes(x = primary_source_std, y = percentage, fill = purpose)) +
      geom_bar(stat = "identity", position = "dodge") +
      geom_text(aes(label = sprintf("%.1f%%", percentage)), 
               position = position_dodge(width = 0.9), 
               vjust = -0.5, size = 3) +
      scale_fill_brewer(palette = "Set2") +
      labs(title = "Antibiotic Use Patterns by Primary Information Source",
           subtitle = "Comparing usage for different purposes",
           x = "Information Source",
           y = "Percentage of Farms",
           fill = "Usage Purpose") +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 45, hjust = 1))
    
    print(source_purpose_plot)
    
    # Statistical comparison of information sources
    if(nrow(source_summary) >= 2) {
      cat("\nStatistical comparison of antibiotic use across information sources:\n")
      
      # One-way ANOVA for any antibiotic use
      ab_use_aov <- aov(any_ab_use ~ primary_source_std, data = farm_info)
      ab_use_aov_summary <- summary(ab_use_aov)
      
      cat("ANOVA for any antibiotic use by information source:\n")
      print(ab_use_aov_summary)
      
      # Statistical significance
      if(ab_use_aov_summary[[1]][["Pr(>F)"]][1] < 0.05) {
        cat("There are statistically significant differences in antibiotic use across information sources (p =", 
            round(ab_use_aov_summary[[1]][["Pr(>F)"]][1], 3), ")\n")
        
        # Post-hoc test if ANOVA is significant
        if(requireNamespace("emmeans", quietly = TRUE)) {
          posthoc <- emmeans::emmeans(ab_use_aov, pairwise ~ primary_source_std)
          cat("Post-hoc pairwise comparisons:\n")
          print(posthoc$contrasts)
        }
      } else {
        cat("No statistically significant differences in antibiotic use across information sources (p =", 
            round(ab_use_aov_summary[[1]][["Pr(>F)"]][1], 3), ")\n")
      }
    }
    
    # Identify farms sharing common information sources
    cat("\nConstructing information source networks...\n")
    
    # Create information source network
    farm_pairs <- expand.grid(farm1 = farm_info$farm_id, 
                             farm2 = farm_info$farm_id, 
                             stringsAsFactors = FALSE) %>%
      filter(farm1 < farm2)  # Only include each pair once
    
    # Calculate information source overlap
    farm_pairs$source_overlap <- apply(farm_pairs, 1, function(pair) {
      farm1_idx <- which(farm_info$farm_id == pair["farm1"])
      farm2_idx <- which(farm_info$farm_id == pair["farm2"])
      
      # Get sources for each farm
      sources1 <- na.omit(c(farm_info$advice1_category[farm1_idx], 
                           farm_info$advice2_category[farm1_idx], 
                           farm_info$advice3_category[farm1_idx]))
      sources2 <- na.omit(c(farm_info$advice1_category[farm2_idx], 
                           farm_info$advice2_category[farm2_idx], 
                           farm_info$advice3_category[farm2_idx]))
      
      # Calculate Jaccard similarity (intersection over union)
      length(intersect(sources1, sources2)) / length(union(sources1, sources2))
    })
    
    # Summarize overlap distribution
    cat("Distribution of information source overlap between farm pairs:\n")
    overlap_summary <- farm_pairs %>%
      mutate(overlap_category = cut(source_overlap, 
                                   breaks = c(0, 0.25, 0.5, 0.75, 1.0),
                                   labels = c("0-25%", "26-50%", "51-75%", "76-100%"),
                                   include.lowest = TRUE)) %>%
      count(overlap_category) %>%
      mutate(percentage = n / sum(n) * 100)
    
    print(overlap_summary)
    
    # Define network ties based on minimum overlap
    min_overlap <- 0.5  # At least 50% source overlap
    farm_network_edges <- farm_pairs %>%
      filter(source_overlap >= min_overlap) %>%
      dplyr::select(farm1, farm2)
    
    if(nrow(farm_network_edges) > 0) {
      cat("Found", nrow(farm_network_edges), "farm pairs with significant information source overlap.\n")
      
      # Create network graph
      info_g <- graph_from_data_frame(farm_network_edges, 
                                     vertices = farm_info %>% dplyr::select(farm_id, any_ab_use),
                                     directed = FALSE)
      
      # Network statistics
      cat("\nInformation source network statistics:\n")
      cat("Number of nodes (farms):", vcount(info_g), "\n")
      cat("Number of edges (connections):", ecount(info_g), "\n")
      cat("Network density:", edge_density(info_g), "\n")
      cat("Average degree (connections per farm):", mean(degree(info_g)), "\n")
      
      # Community detection in information network
      info_communities <- cluster_louvain(info_g)
      
      cat("Number of detected information communities:", length(unique(membership(info_communities))), "\n")
      
      # Assign community IDs
      farm_info$info_community_id <- membership(info_communities)[match(farm_info$farm_id, names(V(info_g)))]
      
      # Visualize network with communities
      # Network statistics
cat("\nInformation source network statistics:\n")
cat("Number of nodes (farms):", vcount(info_g), "\n")
cat("Number of edges (connections):", ecount(info_g), "\n")
cat("Network density:", edge_density(info_g), "\n")
cat("Average degree (connections per farm):", mean(degree(info_g)), "\n")

# Create a simplified network by limiting edges per node
if(requireNamespace("tidygraph", quietly = TRUE)) {
  tg_simplified <- tidygraph::as_tbl_graph(info_g) %>%
    tidygraph::activate(nodes) %>%
    tidygraph::mutate(community = membership(info_communities),
                       antibiotic_use = any_ab_use) %>%
    tidygraph::activate(edges) %>%
    # Add edge weight based on overlap
    tidygraph::mutate(weight = farm_pairs$source_overlap[match(paste0(from, "-", to), 
                                                              paste0(farm_pairs$farm1, "-", farm_pairs$farm2))]) %>%
    # Keep only top connections per node - fixed approach without edge_rank()
    tidygraph::mutate(rank_in_from = rank(-weight, ties.method = "first"),
                      rank_in_to = rank(-weight, ties.method = "first")) %>%
    tidygraph::filter(rank_in_from <= 3 | rank_in_to <= 3)  # Keep top 3 connections per node
  
  # Count nodes in each community for sizing plots
  community_sizes <- table(membership(info_communities))
  largest_communities <- names(sort(community_sizes, decreasing = TRUE))[1:min(4, length(community_sizes))]
}
} else {
  # If tidygraph is not available, use the original graph
  tg_simplified <- info_g
  V(tg_simplified)$community <- membership(info_communities)
  V(tg_simplified)$antibiotic_use <- V(info_g)$any_ab_use
  
  # Identify largest communities
  community_sizes <- table(membership(info_communities))
  largest_communities <- names(sort(community_sizes, decreasing = TRUE))[1:min(4, length(community_sizes))]
}

# Network statistics
cat("\nInformation source network statistics:\n")
cat("Number of nodes (farms):", vcount(info_g), "\n")
cat("Number of edges (connections):", ecount(info_g), "\n")
cat("Network density:", edge_density(info_g), "\n")
cat("Average degree (connections per farm):", mean(degree(info_g)), "\n")

# Visualize network with multiple approaches
if(requireNamespace("ggraph", quietly = TRUE) && requireNamespace("tidygraph", quietly = TRUE)) {
  # Create tidygraph object
  tg <- tidygraph::as_tbl_graph(info_g) %>%
    tidygraph::activate(nodes) %>%
    tidygraph::mutate(community = membership(info_communities),
                      antibiotic_use = any_ab_use)
  
  # 1. Main network visualization with reduced clutter
  main_network_plot <- ggraph::ggraph(tg, layout = "fr") + 
    ggraph::geom_edge_link(alpha = 0.2, width = 0.3) + 
    ggraph::geom_node_point(aes(color = factor(community), 
                               size = antibiotic_use * 2 + 0.5), 
                           alpha = 0.7) +
    scale_size_continuous(range = c(0.5, 3)) +  # Reduce the range of node sizes
    scale_color_brewer(palette = "Set1") +
    labs(title = "Information Source Communities in Farms",
         subtitle = "Farms connected by shared information sources (simplified view)",
         color = "Community", 
         size = "Antibiotic Use") +
    theme_void() +
    theme(legend.position = "right")
  
  print(main_network_plot)
  
  # 2. Alternative layout visualization
  alt_network_plot <- ggraph::ggraph(tg, layout = "kk") + 
    ggraph::geom_edge_link(alpha = 0.2, width = 0.3) + 
    ggraph::geom_node_point(aes(color = factor(community), 
                               size = antibiotic_use * 2 + 0.5), 
                           alpha = 0.7) +
    scale_size_continuous(range = c(0.5, 3)) +
    scale_color_brewer(palette = "Set1") +
    labs(title = "Alternative View of Information Source Communities", 
         subtitle = "Using Kamada-Kawai layout algorithm",
         color = "Community", 
         size = "Antibiotic Use") +
    theme_void() +
    theme(legend.position = "right")
  
  print(alt_network_plot)
  
  # 3. Create a visualization with communities with different point shapes
  shape_plot <- ggraph::ggraph(tg, layout = "nicely") + 
    ggraph::geom_edge_link(alpha = 0.1, width = 0.2) + 
    ggraph::geom_node_point(aes(color = factor(community), 
                              size = antibiotic_use * 2 + 0.8,
                              shape = factor(community %% 5)), # Use modulo to limit to available shapes
                          alpha = 0.8) +
    scale_size_continuous(range = c(1, 4)) +
    scale_color_brewer(palette = "Set1") +
    scale_shape_manual(values = c(16, 17, 15, 18, 19), guide = "none") +
    labs(title = "Communities of Farms with Similar Information Sources",
         subtitle = "Different layouts highlight different aspects of community structure",
         color = "Community", 
         size = "Antibiotic Use") +
    theme_void() +
    theme(legend.position = "right")
  
  print(shape_plot)
  
} else {
  # Basic plot if ggraph is not available
  # Create a more visually appealing base plot
  op <- par(mar = c(1,1,3,1))  # Adjust margins
  set.seed(42)  # For reproducibility
  
  # Use a better layout
  layout_coords <- layout_with_fr(info_g)
  
  # Improve node appearance
  V(info_g)$color <- rainbow(length(unique(membership(info_communities))))[membership(info_communities)]
  V(info_g)$size <- 2 + 8 * V(info_g)$any_ab_use  # Scale node sizes
  E(info_g)$width <- 0.5  # Thinner edges
  E(info_g)$color <- rgb(0.5, 0.5, 0.5, 0.2)  # Transparent gray edges
  
  # Plot with improved aesthetics
  plot(info_g, 
       vertex.label = NA,
       vertex.size = V(info_g)$size,
       vertex.color = adjustcolor(V(info_g)$color, alpha.f = 0.7),
       edge.width = E(info_g)$width,
       edge.color = E(info_g)$color,
       layout = layout_coords,
       main = "Information Source Communities",
       sub = "Farms connected by shared information sources")
  
  legend("topright", 
         legend = paste("Community", sort(unique(membership(info_communities)))),
         fill = rainbow(length(unique(membership(info_communities)))),
         bty = "n",
         cex = 0.8)
  
  par(op)  # Reset graphics parameters
}
      
      # Analyze antibiotic use patterns by information community
      info_community_stats <- farm_info %>%
        filter(!is.na(info_community_id)) %>%
        group_by(info_community_id) %>%
        summarise(
          n_farms = n(),
          ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
          ab_prevention_pct = mean(ab_prevention, na.rm = TRUE) * 100,
          ab_growth_pct = mean(ab_growth, na.rm = TRUE) * 100,
          ab_use_sd = sd(any_ab_use, na.rm = TRUE) * 100,
          .groups = "drop"
        ) %>%
        filter(n_farms >= 3)  # Only include communities with sufficient data
      
      # Display community statistics
      info_community_stats %>%
        mutate(across(ends_with("_pct"), ~ round(., 1)),
               ab_use_sd = round(ab_use_sd, 1)) %>%
        kable(caption = "Antibiotic Use Statistics by Information Community",
              col.names = c("Community ID", "Number of Farms", "Any Antibiotic Use (%)",
                           "Prevention Use (%)", "Growth Promotion Use (%)", 
                           "Std Dev of Antibiotic Use (%)")) %>%
        kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
      
      # Compare within-community vs. between-community variance
      if(nrow(info_community_stats) > 1) {
        # Calculate overall variance
        overall_variance <- var(farm_info$any_ab_use, na.rm = TRUE) * 10000  # Convert to percentage scale
        
        # Calculate weighted average of within-community variance
        within_variance <- sum(info_community_stats$ab_use_sd^2 * info_community_stats$n_farms) / 
          sum(info_community_stats$n_farms)
        
        # Calculate variance explained by community membership (like R-squared)
        variance_explained <- 1 - (within_variance / overall_variance)
        
        cat("\nInformation community analysis:\n")
        cat("Number of information communities:", nrow(info_community_stats), "\n")
        cat("Variance in antibiotic use explained by information community membership:", 
            round(variance_explained * 100, 1), "%\n")
        
        # Visualize community differences
        if(nrow(info_community_stats) >= 3) {
          community_plot <- ggplot(info_community_stats, 
                                 aes(x = reorder(factor(info_community_id), ab_use_pct), 
                                     y = ab_use_pct)) +
            geom_bar(stat = "identity", fill = "steelblue") +
            geom_errorbar(aes(ymin = ab_use_pct - ab_use_sd, 
                             ymax = ab_use_pct + ab_use_sd), 
                         width = 0.2) +
            labs(title = "Antibiotic Use by Information Community",
                 subtitle = "Error bars represent standard deviation",
                 x = "Information Community ID",
                 y = "Antibiotic Use (%)") +
            theme_minimal()
          
          print(community_plot)
        }
      }
    } else {
      cat("Insufficient information source overlap to construct meaningful network.\n")
    }
  } else {
    # For numerical coding of advice sources
    source_summary <- farm_data %>%
      filter(!is.na(advice1)) %>%
      group_by(advice1) %>%
      summarise(
        n = n(),
        ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
        ab_prevention_pct = mean(ab_prevention, na.rm = TRUE) * 100,
        ab_growth_pct = mean(ab_growth, na.rm = TRUE) * 100,
        .groups = "drop"
      ) %>%
      filter(n >= 5)  # Only include sources with sufficient data
    
    # Display results
    source_summary %>%
      mutate(across(ends_with("_pct"), ~ round(., 1))) %>%
      kable(caption = "Antibiotic Use Patterns by Primary Information Source Code",
            col.names = c("Information Source Code", "Number of Farms", 
                         "Any Antibiotic Use (%)", "Prevention Use (%)", "Growth Promotion Use (%)")) %>%
      kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
} 
## Analyzing 1156 farms with information source data...
## Many different sources of information exist ( 182 ),Consider using text analysis methods

## 
## Constructing information source networks...
## Distribution of information source overlap between farm pairs:
##   overlap_category      n percentage
## 1           26-50%   1155       0.17
## 2          76-100% 666435      99.83
## Found 667590 farm pairs with significant information source overlap.
## 
## Information source network statistics:
## Number of nodes (farms): 1156 
## Number of edges (connections): 667590 
## Network density: 1 
## Average degree (connections per farm): 1155 
## Number of detected information communities: 1 
## 
## Information source network statistics:
## Number of nodes (farms): 1156 
## Number of edges (connections): 667590 
## Network density: 1 
## Average degree (connections per farm): 1155 
## 
## Information source network statistics:
## Number of nodes (farms): 1156 
## Number of edges (connections): 667590 
## Network density: 1 
## Average degree (connections per farm): 1155

#---------------------------------------------------------------------
# 3. Human-Animal Contact Pattern Analysis (continued)
#---------------------------------------------------------------------

# Check if we can identify farm-household links
# Method 1: Direct ID linking
if(any(grepl("farm_id", names(household_data)))) {
  cat("\n### Direct Farm-Household Link Analysis ###\n")
  household_farm_link_var <- names(household_data)[grepl("farm_id", names(household_data))][1]
  has_household_farm_link <- TRUE
  
  # Extract linked households-farms
  linked_households <- household_data %>%
    filter(!is.na(!!sym(household_farm_link_var))) %>%
    dplyr::select(household_id, !!household_farm_link_var, any_ab_last_illness)
  
  linked_farms <- farm_data %>%
    dplyr::select(farm_id, any_ab_use, ab_treatment, ab_prevention, ab_growth) %>%
    filter(farm_id %in% linked_households[[household_farm_link_var]])
  
  # Merge household and farm data
  if(nrow(linked_households) > 0 && nrow(linked_farms) > 0) {
    farm_household_pairs <- linked_households %>%
      rename(farm_id = !!household_farm_link_var) %>%
      inner_join(linked_farms, by = "farm_id")
    
    cat("Found", nrow(farm_household_pairs), "direct farm-household links.\n")
    
    # Display summary statistics of linked pairs
    farm_household_summary <- farm_household_pairs %>%
      summarise(
        n_pairs = n(),
        farm_ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
        household_ab_use_pct = mean(any_ab_last_illness, na.rm = TRUE) * 100,
        concordant_pairs = sum(any_ab_use == any_ab_last_illness, na.rm = TRUE),
        concordant_pct = concordant_pairs / n() * 100
      ) %>%
      mutate(across(ends_with("_pct"), ~ round(., 1)))
    
    # Display summary
    farm_household_summary %>%
      gather(key = "statistic", value = "value") %>%
      kable(caption = "Summary of Directly Linked Farm-Household Pairs",
            col.names = c("Statistic", "Value")) %>%
      kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
    
    # Create a cross-tabulation of farm and household antibiotic use
    cross_tab <- table(
      Farm = factor(farm_household_pairs$any_ab_use, levels = c(0, 1), labels = c("No", "Yes")),
      Household = factor(farm_household_pairs$any_ab_last_illness, levels = c(0, 1), labels = c("No", "Yes"))
    )
    
    # Display cross-tabulation
    cross_tab %>%
      kable(caption = "Cross-tabulation of Antibiotic Use in Linked Farm-Household Pairs") %>%
      kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
    
    # Calculate Cohen's Kappa for agreement
    if(requireNamespace("psych", quietly = TRUE)) {
      kappa <- psych::cohen.kappa(cross_tab)
      cat("\nCohen's Kappa for agreement in antibiotic use: ", round(kappa$kappa, 3),
          " (", kappa$agree*100, "% agreement)\n", sep = "")
    }
  }
}

# Method 2: Role-based identification (if method 1 fails)
has_household_farm_link <- FALSE
if(!has_household_farm_link && "role" %in% names(farm_data)) {
  cat("\n### Farm Owner-Household Matching Analysis ###\n")
  
  # Identify farm owners/workers
  farm_owners <- farm_data %>%
    filter(role == 1) %>%  # Assuming 1 = farm owner
    dplyr::select(farm_id, role, any_ab_use, ab_treatment, ab_prevention, ab_growth)
  
  # Try to match with households using common identifiers
  if("farm_district" %in% names(farm_data) && "district" %in% names(household_data) &&
     "farm_commune" %in% names(farm_data) && "commune" %in% names(household_data)) {
    
    # Match based on location and additional criteria if available
    potential_matches <- farm_owners %>%
      inner_join(household_data, 
                by = c("farm_district" = "district", "farm_commune" = "commune"))
    
    if(nrow(potential_matches) > 0) {
      has_household_farm_link <- TRUE
      farm_household_pairs <- potential_matches %>%
        dplyr::select(farm_id, household_id, any_ab_use, ab_treatment, ab_prevention, ab_growth, any_ab_last_illness)
      
      cat("Found", nrow(farm_household_pairs), "potential farm-household links based on location matching.\n")
      
      # Display summary of potential matches
      location_match_summary <- farm_household_pairs %>%
        summarise(
          n_pairs = n(),
          farm_ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
          household_ab_use_pct = mean(any_ab_last_illness, na.rm = TRUE) * 100
        ) %>%
        mutate(across(ends_with("_pct"), ~ round(., 1)))
      
      location_match_summary %>%
        gather(key = "statistic", value = "value") %>%
        kable(caption = "Summary of Location-Based Farm-Household Matches",
              col.names = c("Statistic", "Value")) %>%
        kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
    }
  }
}
## 
## ### Farm Owner-Household Matching Analysis ###
# Method 3: If we have a dataset with both farm and household info for same respondents
if(!has_household_farm_link && any(grepl("consumption", names(farm_data)))) {
  cat("\n### Household Consumption Pattern Analysis ###\n")
  
  # Assuming consumption variables indicate household members consuming farm products
  consumption_vars <- names(farm_data)[grepl("consumption", names(farm_data))]
  
  if(length(consumption_vars) > 0) {
    # Display distribution of consumption patterns
    consumption_distribution <- farm_data %>%
      count(!!sym(consumption_vars[1])) %>%
      mutate(percentage = n / sum(n) * 100,
             description = case_when(
               !!sym(consumption_vars[1]) == 1 ~ "Never from own farm",
               !!sym(consumption_vars[1]) == 2 ~ "More from other farms",
               !!sym(consumption_vars[1]) == 3 ~ "More from own farm",
               !!sym(consumption_vars[1]) == 4 ~ "Only from own farm",
               TRUE ~ "Unknown"
             ))
    
    consumption_distribution %>%
      dplyr::select(-!!sym(consumption_vars[1])) %>%
      mutate(percentage = round(percentage, 1)) %>%
      kable(caption = "Distribution of Household Consumption Patterns",
            col.names = c("Number of Farms", "Percentage (%)", "Consumption Pattern")) %>%
      kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
    
    # Create proxy links based on consumption patterns
    farm_household_proxy <- farm_data %>%
      filter(!!sym(consumption_vars[1]) %in% c(3, 4)) %>%  # 3-4 = consuming own farm products
      dplyr::select(farm_id, any_ab_use, ab_treatment, ab_prevention, ab_growth)
    
    if(nrow(farm_household_proxy) > 0) {
      has_household_farm_link <- TRUE
      
      cat("Found", nrow(farm_household_proxy), "farms with household consumption of farm products.\n")
      cat("Using these as proxy for farm-household overlap.\n")
      
      # Compare with farms without household consumption
      farm_data$household_consumption <- farm_data[[consumption_vars[1]]] %in% c(3, 4)
      
      consumption_comparison <- farm_data %>%
        group_by(household_consumption) %>%
        summarise(
          n = n(),
          ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
          ab_treatment_pct = mean(ab_treatment, na.rm = TRUE) * 100,
          ab_prevention_pct = mean(ab_prevention, na.rm = TRUE) * 100,
          ab_growth_pct = mean(ab_growth, na.rm = TRUE) * 100,
          .groups = "drop"
        )
      
      # Display results
      consumption_comparison %>%
        mutate(household_consumption = ifelse(household_consumption, "Yes", "No"),
               across(ends_with("_pct"), ~ round(., 1))) %>%
        kable(caption = "Antibiotic Use by Household Consumption of Farm Products",
              col.names = c("Household Consumes Farm Products", "Number of Farms", 
                           "Any Antibiotic Use (%)", "Treatment Use (%)", 
                           "Prevention Use (%)", "Growth Promotion Use (%)")) %>%
        kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
      
      # Statistical test for difference
      ab_use_test <- t.test(any_ab_use ~ household_consumption, data = farm_data)
      ab_prevention_test <- t.test(ab_prevention ~ household_consumption, data = farm_data)
      ab_growth_test <- t.test(ab_growth ~ household_consumption, data = farm_data)
      
      # Report test results
      cat("\nStatistical comparison of farms by household consumption:\n")
      cat("Any antibiotic use - difference:", 
          round(ab_use_test$estimate[2] - ab_use_test$estimate[1], 3) * 100, "%,",
          "p-value:", round(ab_use_test$p.value, 3), 
          ifelse(ab_use_test$p.value < 0.05, " (significant)", " (not significant)"), "\n")
      cat("Preventive use - difference:", 
          round(ab_prevention_test$estimate[2] - ab_prevention_test$estimate[1], 3) * 100, "%,",
          "p-value:", round(ab_prevention_test$p.value, 3), 
          ifelse(ab_prevention_test$p.value < 0.05, " (significant)", " (not significant)"), "\n")
      cat("Growth promotion use - difference:", 
          round(ab_growth_test$estimate[2] - ab_growth_test$estimate[1], 3) * 100, "%,",
          "p-value:", round(ab_growth_test$p.value, 3), 
          ifelse(ab_growth_test$p.value < 0.05, " (significant)", " (not significant)"), "\n")
      
      # Visualization
      farm_data_plot <- farm_data %>%
        mutate(household_consumption = ifelse(household_consumption, "Yes", "No")) %>%
        dplyr::select(household_consumption, any_ab_use, ab_treatment, ab_prevention, ab_growth) %>%
        pivot_longer(cols = c(any_ab_use, ab_treatment, ab_prevention, ab_growth),
                     names_to = "usage_type", values_to = "usage") %>%
        mutate(usage_type = factor(usage_type,
                                  levels = c("any_ab_use", "ab_treatment", "ab_prevention", "ab_growth"),
                                  labels = c("Any Use", "Treatment", "Prevention", "Growth Promotion")))
      
      # Create and display bar chart
      consumption_plot <- ggplot(farm_data_plot, aes(x = usage_type, y = usage * 100, fill = household_consumption)) +
        stat_summary(fun = mean, geom = "bar", position = "dodge") +
        stat_summary(fun.data = mean_cl_normal, geom = "errorbar", position = position_dodge(0.9), width = 0.2) +
        labs(title = "Antibiotic Use by Household Consumption Pattern",
             subtitle = "Comparison of farms where household members consume farm products",
             x = "Type of Antibiotic Use",
             y = "Percentage of Farms",
             fill = "Household Consumes\nFarm Products") +
        scale_fill_brewer(palette = "Set1") +
        theme_minimal()
      
      print(consumption_plot)
    }
  }
}
## 
## ### Household Consumption Pattern Analysis ###
## Found 400 farms with household consumption of farm products.
## Using these as proxy for farm-household overlap.
## 
## Statistical comparison of farms by household consumption:
## Any antibiotic use - difference: 2.4 %, p-value: 0.082  (not significant) 
## Preventive use - difference: 16 %, p-value: 0  (significant) 
## Growth promotion use - difference: 1.4 %, p-value: 0.052  (not significant)

# If we have direct farm-household pairs, analyze the correlation in antibiotic use
if(has_household_farm_link && exists("farm_household_pairs") && nrow(farm_household_pairs) >= 10) {
  cat("\n### Directly Linked Farm-Household Pair Analysis ###\n")
  
  # Calculate correlation between farm and household antibiotic use
  pair_correlation <- cor.test(
    farm_household_pairs$any_ab_use,
    farm_household_pairs$any_ab_last_illness
  )
  
  # Display correlation results
  cat("Number of farm-household pairs:", nrow(farm_household_pairs), "\n")
  cat("Correlation between farm and household antibiotic use:\n")
  cat("Correlation coefficient (r):", round(pair_correlation$estimate, 3), "\n")
  cat("95% confidence interval: [", 
      round(pair_correlation$conf.int[1], 3), ",", 
      round(pair_correlation$conf.int[2], 3), "]\n")
  cat("P-value:", round(pair_correlation$p.value, 3), 
      ifelse(pair_correlation$p.value < 0.05, " (significant)", " (not significant)"), "\n")
  
  # Visualize the relationship
  pair_plot <- ggplot(farm_household_pairs, aes(x = any_ab_use, y = any_ab_last_illness)) +
    geom_jitter(width = 0.1, height = 0.1, alpha = 0.7) +
    geom_smooth(method = "glm", method.args = list(family = "binomial"), se = TRUE, color = "blue") +
    labs(title = "Relationship Between Farm and Household Antibiotic Use",
         subtitle = paste("Correlation coefficient =", round(pair_correlation$estimate, 2)),
         x = "Farm Antibiotic Use (0=No, 1=Yes)",
         y = "Household Antibiotic Use (0=No, 1=Yes)") +
    theme_minimal()
  
  print(pair_plot)
  
  # Check for purpose-specific correlations
  purpose_cors <- data.frame(
    Purpose = c("Treatment", "Prevention", "Growth Promotion"),
    Correlation = c(
      cor(farm_household_pairs$ab_treatment, farm_household_pairs$any_ab_last_illness, use = "complete.obs"),
      cor(farm_household_pairs$ab_prevention, farm_household_pairs$any_ab_last_illness, use = "complete.obs"),
      cor(farm_household_pairs$ab_growth, farm_household_pairs$any_ab_last_illness, use = "complete.obs")
    )
  )
  
  # Calculate p-values
  purpose_cors$P_Value <- c(
    cor.test(farm_household_pairs$ab_treatment, farm_household_pairs$any_ab_last_illness)$p.value,
    cor.test(farm_household_pairs$ab_prevention, farm_household_pairs$any_ab_last_illness)$p.value,
    cor.test(farm_household_pairs$ab_growth, farm_household_pairs$any_ab_last_illness)$p.value
  )
  
  purpose_cors$Significant <- ifelse(purpose_cors$P_Value < 0.05, "Yes", "No")
  
  # Display purpose-specific correlations
  purpose_cors %>%
    mutate(
      Correlation = round(Correlation, 3),
      P_Value = round(P_Value, 3)
    ) %>%
    kable(caption = "Correlations Between Farm Purpose-Specific and Household Antibiotic Use",
          col.names = c("Farm Antibiotic Purpose", "Correlation with Household Use", 
                       "P-Value", "Significant")) %>%
    kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
  
  # Create bar chart of purpose-specific correlations
  purpose_plot <- ggplot(purpose_cors, aes(x = Purpose, y = Correlation, fill = Significant)) +
    geom_bar(stat = "identity") +
    geom_text(aes(label = sprintf("%.3f", Correlation)), vjust = -0.5) +
    scale_fill_manual(values = c("No" = "gray70", "Yes" = "steelblue")) +
    labs(title = "Purpose-Specific Correlations with Household Antibiotic Use",
         x = "Farm Antibiotic Purpose",
         y = "Correlation Coefficient") +
    theme_minimal()
  
  print(purpose_plot)
}

#---------------------------------------------------------------------
# 4. Integrated Analysis Across Multiple Community Definitions
#---------------------------------------------------------------------

cat("\n## Integrated Analysis Across Community Definitions ##\n")
## 
## ## Integrated Analysis Across Community Definitions ##
# Create a list to store results from different community definitions
community_results <- list()
if(all(c("edu", "income") %in% names(farm_data))) {
  cat("\n### Socioeconomic Community Analysis ###\n")
  
  socioeco_clusters <- farm_data %>%
    dplyr::select(farm_id, edu, income) %>%
    filter(!is.na(edu) & !is.na(income)) %>%
    mutate(
      edu_z = scale(as.numeric(edu)),
      income_z = scale(as.numeric(income))
    )
  
  if(nrow(socioeco_clusters) >= 20) {
    cluster_result <- kmeans(socioeco_clusters %>% dplyr::select(edu_z, income_z), 
                            centers = min(5, nrow(socioeco_clusters)/4))
    
    socioeco_clusters$se_community_id <- cluster_result$cluster
    
    farm_data <- farm_data %>%
      left_join(socioeco_clusters %>% dplyr::select(farm_id, se_community_id), by = "farm_id")
    
    cat("Defined based on socio-economic characteristics", length(unique(socioeco_clusters$se_community_id)), "communities\n")
    
  }
}

# 1. Administrative community (from original code)
if("geo_id" %in% names(farm_data) && "geo_id" %in% names(household_data)) {
  cat("\n### Administrative Community Analysis ###\n")
  
  admin_farm_community <- farm_data %>%
    group_by(geo_id) %>%
    summarise(
      farm_count = n(),
      farm_ab_use_pct = mean(any_ab_use, na.rm = TRUE) * 100,
      .groups = "drop"
    ) %>%
    filter(farm_count >= 3)
  
  admin_household_community <- household_data %>%
    group_by(geo_id) %>%
    summarise(
      household_count = n(),
      household_ab_use_pct = mean(any_ab_last_illness, na.rm = TRUE) * 100,
      .groups = "drop"
    ) %>%
    filter(household_count >= 3)
  
  admin_comparison <- inner_join(admin_farm_community, admin_household_community, by = "geo_id") %>%
    filter(farm_count >= 3 & household_count >= 3)
  
  if(nrow(admin_comparison) > 0) {
    cat("Found", nrow(admin_comparison), "administrative communities with sufficient data.\n")
    
    # Display summary statistics of administrative communities
    admin_comparison %>%
      summarise(
        n_communities = n(),
        avg_farm_count = mean(farm_count),
        avg_household_count = mean(household_count),
        avg_farm_ab_use = mean(farm_ab_use_pct),
        avg_household_ab_use = mean(household_ab_use_pct)
      ) %>%
      mutate(across(starts_with("avg_"), ~ round(., 1))) %>%
      gather(key = "statistic", value = "value") %>%
      kable(caption = "Summary Statistics of Administrative Communities",
            col.names = c("Statistic", "Value")) %>%
      kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
    
    # Calculate correlation
    admin_corr <- cor.test(admin_comparison$farm_ab_use_pct, admin_comparison$household_ab_use_pct)
    
    cat("Correlation between farm and household antibiotic use in administrative communities:\n")
    cat("Correlation coefficient (r):", round(admin_corr$estimate, 3), "\n")
    cat("95% confidence interval: [", 
        round(admin_corr$conf.int[1], 3), ",", 
        round(admin_corr$conf.int[2], 3), "]\n")
    cat("P-value:", round(admin_corr$p.value, 3), 
        ifelse(admin_corr$p.value < 0.05, " (significant)", " (not significant)"), "\n")
    
    # Visualize relationship
    admin_plot <- ggplot(admin_comparison, aes(x = farm_ab_use_pct, y = household_ab_use_pct)) +
      geom_point(aes(size = farm_count + household_count), alpha = 0.7) +
      geom_smooth(method = "lm", se = TRUE, color = "blue") +
      labs(title = "Correlation Between Farm and Household Antibiotic Use in Administrative Communities",
           subtitle = paste("Pearson correlation =", round(admin_corr$estimate, 2), 
                           ", p-value =", round(admin_corr$p.value, 3)),
           x = "Farm Antibiotic Use (%)",
           y = "Household Antibiotic Use (%)",
           size = "Number of Respondents") +
      theme_minimal()
    
    print(admin_plot)
    
    # Store results for comparison
    community_results[["Administrative"]] <- list(
      n_communities = nrow(admin_comparison),
      correlation = admin_corr$estimate,
      p_value = admin_corr$p.value
    )
  } else {
    cat("Insufficient data for administrative community analysis.\n")
  }
}
## 
## ### Administrative Community Analysis ###
## Found 64 administrative communities with sufficient data.
## Correlation between farm and household antibiotic use in administrative communities:
## Correlation coefficient (r): 0.017 
## 95% confidence interval: [ -0.23 , 0.26 ]
## P-value: 0.9  (not significant)

# 2. Geographic proximity communities (if available)
if(exists("mixed_community_data") && nrow(mixed_community_data) > 0) {
  cat("\n### Geographic Proximity Community Analysis ###\n")
  
  cat("Found", nrow(mixed_community_data), "geographic proximity communities with sufficient data.\n")
  
  # Calculate correlation
  geo_corr <- cor.test(mixed_community_data$farm_ab_use_pct, mixed_community_data$household_ab_use_pct)
  
  cat("Correlation between farm and household antibiotic use in geographic proximity communities:\n")
  cat("Correlation coefficient (r):", round(geo_corr$estimate, 3), "\n")
  cat("95% confidence interval: [", 
      round(geo_corr$conf.int[1], 3), ",", 
      round(geo_corr$conf.int[2], 3), "]\n")
  cat("P-value:", round(geo_corr$p.value, 3), 
      ifelse(geo_corr$p.value < 0.05, " (significant)", " (not significant)"), "\n")
  
  # Store results for comparison
  community_results[["Geographic"]] <- list(
    n_communities = nrow(mixed_community_data),
    correlation = geo_corr$estimate,
    p_value = geo_corr$p.value
  )
}

# 3. Information network communities (if available)
if(exists("info_community_stats") && nrow(info_community_stats) > 0 && 
   "q7_19" %in% names(household_data) && "info_community_id" %in% names(farm_info)) {
  
  cat("\n### Information Network Community Analysis ###\n")
  
  # Try to assign households to information communities based on shared sources
  if(exists("household_info")) {
    # Map each household to most similar information community
    household_info$info_community_id <- NA
    
    for(i in 1:nrow(household_info)) {
      household_source <- household_info$primary_source_std[i]
      
      # Find dominant source in each community
      community_sources <- farm_info %>%
        filter(!is.na(info_community_id)) %>%
        group_by(info_community_id, primary_source_std) %>%
        summarise(count = n(), .groups = "drop") %>%
        group_by(info_community_id) %>%
        filter(count == max(count)) %>%
        slice(1)
      
      # Assign to most matching community
      matching_community <- community_sources %>%
        filter(primary_source_std == household_source)
      
      if(nrow(matching_community) > 0) {
        household_info$info_community_id[i] <- matching_community$info_community_id[1]
      }
    }
    
    # Aggregate household data by information community
    household_info_community <- household_info %>%
      filter(!is.na(info_community_id)) %>%
      group_by(info_community_id) %>%
      summarise(
        household_count = n(),
        household_ab_use_pct = mean(any_ab_last_illness, na.rm = TRUE) * 100,
        .groups = "drop"
      ) %>%
      filter(household_count >= 3)
    
    # Join with farm community data
    info_comparison <- info_community_stats %>%
      rename(farm_count = n_farms, farm_ab_use_pct = ab_use_pct) %>%
      dplyr::select(info_community_id, farm_count, farm_ab_use_pct) %>%
      inner_join(household_info_community, by = "info_community_id")
    
    if(nrow(info_comparison) > 0) {
      cat("Found", nrow(info_comparison), "information network communities with sufficient data.\n")
      
      # Calculate correlation
      info_corr <- cor.test(info_comparison$farm_ab_use_pct, info_comparison$household_ab_use_pct)
      
      cat("Correlation between farm and household antibiotic use in information network communities:\n")
      cat("Correlation coefficient (r):", round(info_corr$estimate, 3), "\n")
      cat("95% confidence interval: [", 
          round(info_corr$conf.int[1], 3), ",", 
          round(info_corr$conf.int[2], 3), "]\n")
      cat("P-value:", round(info_corr$p.value, 3), 
          ifelse(info_corr$p.value < 0.05, " (significant)", " (not significant)"), "\n")
      
      # Store results for comparison
      community_results[["Information"]] <- list(
        n_communities = nrow(info_comparison),
        correlation = info_corr$estimate,
        p_value = info_corr$p.value
      )
    } else {
      cat("Insufficient data for information network community analysis.\n")
    }
  }
}

# 4. Human-animal contact (if we have direct links)
if(exists("farm_household_pairs") && nrow(farm_household_pairs) >= 10) {
  cat("\n### Direct Contact Analysis ###\n")
  
  # Use the correlation calculated earlier
  if(exists("pair_correlation")) {
    cat("Using", nrow(farm_household_pairs), "directly linked farm-household pairs.\n")
    
    # Store results for comparison
    community_results[["Direct Contact"]] <- list(
      n_pairs = nrow(farm_household_pairs),
      correlation = pair_correlation$estimate,
      p_value = pair_correlation$p.value
    )
  }
}

# Create a summary table of results across different definitions
if(length(community_results) > 0) {
  cat("\n### Comparative Analysis Across Community Definitions ###\n")
  
  results_df <- data.frame(
    Community_Definition = names(community_results),
    N_Units = sapply(community_results, function(x) ifelse(is.null(x$n_communities), x$n_pairs, x$n_communities)),
    Correlation = sapply(community_results, function(x) x$correlation),
    P_Value = sapply(community_results, function(x) x$p_value),
    stringsAsFactors = FALSE
  )
  
  # Create the Significant column explicitly
  results_df$Significant <- ifelse(results_df$P_Value < 0.05, "Yes", "No")
  
  # Display table
  results_df %>%
    mutate(
      Correlation = round(Correlation, 3),
      P_Value = round(P_Value, 3)
    ) %>%
    kable(caption = "Comparison of Farm-Household Antibiotic Use Correlation Across Different Community Definitions",
          col.names = c("Community Definition", "Number of Units", 
                       "Correlation", "P-Value", "Significant")) %>%
    kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
  
  # Visualize comparison
  comparison_plot <- ggplot(results_df, aes(x = Community_Definition, y = Correlation, fill = Significant)) +
    geom_bar(stat = "identity") +
    geom_text(aes(label = sprintf("%.3f", Correlation)), vjust = -0.5, size = 3.5) +
    geom_hline(yintercept = 0, linetype = "dashed", color = "gray50") +
    coord_cartesian(ylim = c(min(min(results_df$Correlation) - 0.1, -0.1), 
                            max(max(results_df$Correlation) + 0.1, 0.1))) +
    labs(title = "Comparison of Correlation Coefficients Across Community Definitions",
         subtitle = "Testing the robustness of community-level isomorphism",
         x = "Community Definition",
         y = "Correlation Coefficient",
         fill = "Statistically\nSignificant") +
    scale_fill_manual(values = c("No" = "gray70", "Yes" = "steelblue")) +
    theme_minimal()
  
  print(comparison_plot)
}
## 
## ### Comparative Analysis Across Community Definitions ###

LS0tCnRpdGxlOiAiRGVzY3JpcHRpdmUgQW5hbHlzaXMgb2YgSG91c2Vob2xkIERhdGEgZm9yIEFudGltaWNyb2JpYWwgUmVzaXN0YW5jZSBSZXNlYXJjaCIKYXV0aG9yOiAiQ2hhb2t1biBIb25nIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19kZXB0aDogMwogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICB0aGVtZTogam91cm5hbCAgICMg5oiWIGpvdXJuYWzjgIFmbGF0bHkg562JCiAgICBoaWdobGlnaHQ6IGthdGUKICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjc3M6IGN1c3RvbS5jc3MKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSkKYGBgCgojIFJlc2VhcmNoIFF1ZXN0aW9uIDE6IFByZXZhbGVuY2UgUGF0dGVybnMgb2YgQW50aWJpb3RpYyBVc2UgaW4gVmlldG5hbWVzZSBGYXJtcyBhbmQgSG91c2Vob2xkcwoKIyMgSW50cm9kdWN0aW9uCgpUaGlzIGFuYWx5c2lzIGFkZHJlc3NlcyB0aGUgZmlyc3QgcmVzZWFyY2ggcXVlc3Rpb24gb2Ygb3VyIHN0dWR5IG9uIGFudGltaWNyb2JpYWwgcmVzaXN0YW5jZSBpbiBWaWV0bmFtOiAqKldoYXQgYXJlIHRoZSBwcmV2YWxlbmNlIHBhdHRlcm5zIG9mIGFudGliaW90aWMgdXNlIG9uIGZhcm1zIGFuZCBpbiBob3VzZWhvbGRzLCBhbmQgaG93IGRvIHRoZXkgY29tcGFyZT8qKgoKIyMjIFJlc2VhcmNoIEh5cG90aGVzZXMKCi0gICAqKkgxLjEqKjogUHJvcGh5bGFjdGljIGFuZCBncm93dGggcHJvbW90aW9uIGFudGliaW90aWMgdXNlIGlzIHdpZGVzcHJlYWQgaW4gZmFybSBhbmltYWxzLCB3aXRoIHByZXZhbGVuY2UgaGlnaGVyIHRoYW4gY29ycmVzcG9uZGluZyB1c2VzIGluIGh1bWFuIG1lZGljaW5lLgotICAgKipIMS4yKio6IFRoZXJlIGFyZSBzeXN0ZW1hdGljIGRpZmZlcmVuY2VzIGluIGFudGliaW90aWMgdXNlIHBhdHRlcm5zIGFtb25nIGRpZmZlcmVudCBhbmltYWwgdHlwZXMgKGNoaWNrZW5zLCBwaWdzLCBjYXR0bGUpLCByZWZsZWN0aW5nIHN0cnVjdHVyYWwgbmVlZHMgb2YgZGlmZmVyZW50IHByb2R1Y3Rpb24gc3lzdGVtcy4KLSAgICoqSDEuMyoqOiBUaGVyZSBpcyBhIG5vbi1saW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gZmFybSBzaXplIGFuZCBhbnRpYmlvdGljIHVzZSBwcmFjdGljZXMsIHdpdGggbWVkaXVtLXNpemVkIGZhcm1zIHBvdGVudGlhbGx5IGhhdmluZyB0aGUgaGlnaGVzdCByYXRlcyBvZiBpbmFwcHJvcHJpYXRlIHVzZS4KLSAgICoqSDEuNCoqOiBIdW1hbiBhbnRpYmlvdGljIHVzZSBwYXR0ZXJucyBpbiBob3VzZWhvbGRzIHNob3cgaXNvbW9ycGhpc20gd2l0aCBmYXJtIGFuaW1hbCBhbnRpYmlvdGljIHVzZSBpbiB0aGUgc2FtZSBjb21tdW5pdHksIGluZmx1ZW5jZWQgYnkgY29tbW9uIGluZm9ybWF0aW9uIHNvdXJjZXMgYW5kIHNvY2lhbCBub3Jtcy4KCiMjIyBTaWduaWZpY2FuY2UgZm9yIE9uZSBIZWFsdGggRnJhbWV3b3JrCgpUaGlzIHJlc2VhcmNoIHF1ZXN0aW9uIGRpcmVjdGx5IHN1cHBvcnRzIHRoZSBPbmUgSGVhbHRoIGZyYW1ld29yayBieSBjb21wYXJpbmcgYW50aWJpb3RpYyB1c2UgcGF0dGVybnMgaW4gaHVtYW4gYW5kIGFuaW1hbCBoZWFsdGggc2VjdG9ycy4gVW5kZXJzdGFuZGluZyB0aGVzZSBwYXR0ZXJucyBhbmQgdGhlaXIgY29ycmVsYXRpb25zIGlzIGVzc2VudGlhbCBmb3I6CgoxLiAgRXN0YWJsaXNoaW5nIGJhc2VsaW5lIHByZXZhbGVuY2Ugb2YgYW50aWJpb3RpYyB1c2UgYWNyb3NzIHNlY3RvcnMKMi4gIElkZW50aWZ5aW5nIHBvdGVudGlhbCBjcm9zcy1zZWN0b3JhbCBpbmZsdWVuY2VzIG9uIGFudGliaW90aWMgdXNlCjMuICBHdWlkaW5nIGZ1dHVyZSBpbnRlcnZlbnRpb25zIHRoYXQgdGFyZ2V0IGJvdGggaHVtYW4gYW5kIGFuaW1hbCBhbnRpYmlvdGljIHVzZQo0LiAgQ29udGV4dHVhbGl6aW5nIGFudGltaWNyb2JpYWwgcmVzaXN0YW5jZSBwYXR0ZXJucyBvYnNlcnZlZCBpbiBzdWJzZXF1ZW50IGFuYWx5c2VzCgojIyBEYXRhIFByZXBhcmF0aW9uCgojIyMgTG9hZGluZyBSZXF1aXJlZCBQYWNrYWdlcwoKYGBge3IgbG9hZC1wYWNrYWdlcywgbWVzc2FnZT1GQUxTRX0KIyBMaXN0IG9mIHJlcXVpcmVkIHBhY2thZ2VzCnBhY2thZ2VzIDwtIGMoInRpZHl2ZXJzZSIsICJoZXJlIiwgImhhdmVuIiwgImtuaXRyIiwgImthYmxlRXh0cmEiLAogICAgICAgICAgICAgICJqYW5pdG9yIiwgImNvcnJwbG90IiwgImd0c3VtbWFyeSIsICJzZiIsICJnZ3B1YnIiLAogICAgICAgICAgICAgICJNQVNTIiwgInNlZ21lbnRlZCIsICJjYXIiLCAicHN5Y2giLCAibG1lNCIsICJwZXJmb3JtYW5jZSIsCiAgICAgICAgICAgICAgInZlZ2FuIiwgImdlb3NwaGVyZSIsICJpZ3JhcGgiLCAic3BkZXAiLCAiYmlub20iLAogICAgICAgICAgICAgICJyZXNoYXBlMiIsICJzY2FsZXMiLCAicGF0Y2h3b3JrIiwgImdyaWRFeHRyYSIsCiAgICAgICAgICAgICAgImdyaWQiKQoKIyBJbnN0YWxsIHBhY2thZ2VzIHRoYXQgYXJlIG5vdCBhbHJlYWR5IGluc3RhbGxlZAppbnN0YWxsZWQgPC0gcGFja2FnZXMgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKVssIlBhY2thZ2UiXQoKaWYoYW55KCFpbnN0YWxsZWQpKSB7CiAgaW5zdGFsbC5wYWNrYWdlcyhwYWNrYWdlc1shaW5zdGFsbGVkXSkKfQoKIyBMb2FkIGFsbCBwYWNrYWdlcwppbnZpc2libGUobGFwcGx5KHBhY2thZ2VzLCBsaWJyYXJ5LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKQoKCiMgU2V0IG9wdGlvbnMgZm9yIGJldHRlciBvdXRwdXQKb3B0aW9ucyhzY2lwZW4gPSA5OTkpICAgICAgICAjIEF2b2lkIHNjaWVudGlmaWMgbm90YXRpb24Kb3B0aW9ucyhkaWdpdHMgPSAyKSAgICAgICAgICAjIFJvdW5kIHRvIDIgZGVjaW1hbCBwbGFjZXMKb3B0aW9ucyhtYXgucHJpbnQgPSAxMDAwKSAgICAjIExpbWl0IG91dHB1dCBsaW5lcwoKIyBGdW5jdGlvbiB0byBzYWZlbHkgcmVhZCBmaWxlcyB3aXRoIGRpZmZlcmVudCBmb3JtYXRzCnNhZmVfcmVhZCA8LSBmdW5jdGlvbihmaWxlX3BhdGgpIHsKICAjIEdldCBmaWxlIGV4dGVuc2lvbgogIGV4dCA8LSB0b29sczo6ZmlsZV9leHQoZmlsZV9wYXRoKQogIAogICMgUmVhZCBmaWxlIGJhc2VkIG9uIGV4dGVuc2lvbgogIGlmIChleHQgPT0gImNzdiIpIHsKICAgIGRhdGEgPC0gcmVhZC5jc3YoZmlsZV9wYXRoLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCiAgfSBlbHNlIGlmIChleHQgPT0gInJkcyIpIHsKICAgIGRhdGEgPC0gcmVhZFJEUyhmaWxlX3BhdGgpCiAgfSBlbHNlIGlmIChleHQgPT0gInNhdiIpIHsKICAgIGRhdGEgPC0gaGF2ZW46OnJlYWRfc3BzcyhmaWxlX3BhdGgpCiAgfSBlbHNlIGlmIChleHQgPT0gImR0YSIpIHsKICAgIGRhdGEgPC0gaGF2ZW46OnJlYWRfZHRhKGZpbGVfcGF0aCkKICB9IGVsc2UgaWYgKGV4dCA9PSAidHh0IikgewogICAgIyBGb3IgdHh0IGZpbGVzLCBhdHRlbXB0IHRvIGRldGVybWluZSBkZWxpbWl0ZXIKICAgIGRhdGEgPC0gcmVhZC5kZWxpbShmaWxlX3BhdGgsIHNlcCA9ICJcdCIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKICB9IGVsc2UgewogICAgc3RvcCgiVW5zdXBwb3J0ZWQgZmlsZSBmb3JtYXQiKQogIH0KICAKICByZXR1cm4oZGF0YSkKfQpgYGAKCiMjIyBMb2FkaW5nIGFuZCBFeGFtaW5pbmcgRGF0YQoKYGBge3IgbG9hZC1kYXRhLCBtZXNzYWdlPUZBTFNFfQojIExvYWQgZmFybSBhbmQgaG91c2Vob2xkIGRhdGEKIyBBZGp1c3QgZmlsZSBwYXRocyB0byB3aGVyZSB5b3VyIGRhdGEgaXMgc3RvcmVkCmZhcm1fZGF0YSA8LSBzYWZlX3JlYWQoaGVyZSgiRGF0YSIsICJmYXJtX2Ftcl9jb2RlZF9hbm9ueW1pc2VkLmR0YSIpKQpob3VzZWhvbGRfZGF0YSA8LSBzYWZlX3JlYWQoaGVyZSgiRGF0YSIsICJjb2RlZF9hbm9ueW1pc2VkLmR0YSIpKQoKIyBEaXNwbGF5IGJhc2ljIGluZm9ybWF0aW9uIGFib3V0IGRhdGFzZXRzCmZhcm1fZGltZW5zaW9ucyA8LSBkaW0oZmFybV9kYXRhKQpob3VzZWhvbGRfZGltZW5zaW9ucyA8LSBkaW0oaG91c2Vob2xkX2RhdGEpCiAKIyBQcmludCBkYXRhc2V0IGRpbWVuc2lvbnMKY2F0KCJGYXJtIGRhdGFzZXQgZGltZW5zaW9uczoiLCBmYXJtX2RpbWVuc2lvbnNbMV0sICJyb3dzIGFuZCIsIGZhcm1fZGltZW5zaW9uc1syXSwgImNvbHVtbnNcbiIpCmNhdCgiSG91c2Vob2xkIGRhdGFzZXQgZGltZW5zaW9uczoiLCBob3VzZWhvbGRfZGltZW5zaW9uc1sxXSwgInJvd3MgYW5kIiwgaG91c2Vob2xkX2RpbWVuc2lvbnNbMl0sICJjb2x1bW5zXG4iKQoKIyBEaXNwbGF5IHRoZSBmaXJzdCBmZXcgcm93cyBvZiBlYWNoIGRhdGFzZXQgdG8gdW5kZXJzdGFuZCBzdHJ1Y3R1cmUKZmFybV9kYXRhICU+JQogIGRwbHlyOjpzZWxlY3QoZmFybV9pZCwgcm9sZSwgc2V4LCBiaXJ0aF95ZWFyLCBlZHUsIAogICAgICAgICAgICAgICAgY2hpY2tlbnMsIHBpZ3MsIGNhdHRsZSwgZHVja3MsIG11c2NvdnksIGdlZXNlLCBkb2dzLCBjYXRzLCAKICAgICAgICAgICAgICAgIGJ1ZmZhbG8sIGdvYXRzLCByYWJiaXRzLCBhcmVhX2Zhcm0sIHByb2R1Y3QxLCBwcm9kdWN0MiwgcHJvZHVjdDMsIAogICAgICAgICAgICAgICAgcHJvZHVjdDQsIHByb2R1Y3Q1LCBwcm9kdWN0NiwgdmlydXMsIGJhY3RlcmlhLCByZXNpc3RhbnRfYm9keSwgCiAgICAgICAgICAgICAgICByZXNpc3RhbnRfYmFjdGVyaWEsIHRyYW5zbWlzc2lvbiwgcmVzaWR1ZSwgc3lub255bSwgYWJ1X2dlbmVyYWwsIAogICAgICAgICAgICAgICAgZGVjaXNpb24sIGFkdmljZTEsIGFkdmljZTIsIGFkdmljZTMsIHB1cnBvc2VfYW50aWJpb3RpY19fXzEsIAogICAgICAgICAgICAgICAgcHVycG9zZV9hbnRpYmlvdGljX19fMiwgcHVycG9zZV9hbnRpYmlvdGljX19fMywgcHVycG9zZV9hbnRpYmlvdGljX19fOTksIAogICAgICAgICAgICAgICAgcHVycG9zZV9hbnRpYmlvdGljX290aGVyLCBkb3NhZ2VfX18xLCBkb3NhZ2VfX18yLCBkb3NhZ2VfX18zLCBkb3NhZ2VfX185OSwgCiAgICAgICAgICAgICAgICBkb3NhZ2Vfb3RoZXIsIGNvbWJpbmF0aW9uLCBjb21iaW5hdGlvbl9vdGhlciwgY2hsbywgbml0ciwgZGltZSwgbWV0ciwgY2lwciwgCiAgICAgICAgICAgICAgICBvZmxvLCBjYXJiLCBvbGFxLCBiYWNpLCB3aXRoZHJhd2FsLCB3aXRoZHJhd2FsX290aGVyLCBzcGVjaWVzLCBhYnVfY2hpY2tlbiwgCiAgICAgICAgICAgICAgICBhYnVfcGlnLCBhYnVfY2F0dGxlLCBkaXN0cmljdCwgY29tbXVuZSkgJT4lCiAgaGVhZCgxMCkgJT4lCiAga2FibGUoKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRkFMU0UsIGZvbnRfc2l6ZSA9IDEyKSAlPiUKICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiNTAwcHgiKQoKaGVhZChob3VzZWhvbGRfZGF0YSwgbiA9IDEwKSAlPiUgCiAgZHBseXI6OnNlbGVjdChkaXN0cmljdCwgY29tbXVuZSwgdmlsbGFnZV94LCBzdGFydHNfd2l0aCgicTdfMV9fXyIpLCAKICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJxN18xMV9fXyIpLCBxN18xN19sYXN0YWJfbiwgCiAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgicTdfMThfbGFzdGlsbG5lc3NfX18iKSwKICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJxN18xOV9fXyIpLCBxN18yMF9wcmVzY3JpYmVfbiwKICAgICAgICAgICAgICAgIHE3XzIxX2RheXMsIHE3XzIyX3N0b3BfbiwgcTdfMjNfdGltZXNhYikgJT4lIAogIGthYmxlKCkgJT4lIAogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCAKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIikKYGBgCgojIyMgRGF0YSBDbGVhbmluZyBhbmQgUHJlcGFyYXRpb24KCmBgYHtyIGRhdGEtY2xlYW5pbmcsIG1lc3NhZ2U9RkFMU0V9CiMgRXhhbWluZSB0aGUgc3RydWN0dXJlIG9mIGRhdGEgdG8gdW5kZXJzdGFuZCB2YXJpYWJsZSBuYW1lcwpob3VzZWhvbGRfdmFycyA8LSBuYW1lcyhob3VzZWhvbGRfZGF0YSkKZmFybV92YXJzIDwtIG5hbWVzKGZhcm1fZGF0YSkKCiMgUHJpbnQgZmlyc3QgZmV3IHZhcmlhYmxlIG5hbWVzIHRvIGluc3BlY3QgdGhlIHBhdHRlcm4KY2F0KCJGaXJzdCBmZXcgaG91c2Vob2xkIHZhcmlhYmxlczoiLCBoZWFkKGhvdXNlaG9sZF92YXJzKSwgIlxuIikKY2F0KCJGaXJzdCBmZXcgZmFybSB2YXJpYWJsZXM6IiwgaGVhZChmYXJtX3ZhcnMpLCAiXG4iKQoKIyBDaGVjayBmb3IgdmFyaWFibGVzIHJlbGF0ZWQgdG8gYW50aWJpb3RpYyB1c2UgaW4gaG91c2Vob2xkIGRhdGEKaG91c2Vob2xkX2FiX3ZhcnMgPC0gZ3JlcCgicTdfMTFfX18iLCBob3VzZWhvbGRfdmFycywgdmFsdWUgPSBUUlVFKQpjYXQoIkhvdXNlaG9sZCBhbnRpYmlvdGljIHZhcmlhYmxlczoiLCBob3VzZWhvbGRfYWJfdmFycywgIlxuIikKCiMgQ2hlY2sgZm9yIHZhcmlhYmxlcyByZWxhdGVkIHRvIGFudGliaW90aWMgdXNlIHB1cnBvc2UgaW4gZmFybSBkYXRhCmZhcm1fYWJfcHVycG9zZV92YXJzIDwtIGdyZXAoInB1cnBvc2VfYW50aWJpb3RpY19fXyIsIGZhcm1fdmFycywgdmFsdWUgPSBUUlVFKQpjYXQoIkZhcm0gYW50aWJpb3RpYyBwdXJwb3NlIHZhcmlhYmxlczoiLCBmYXJtX2FiX3B1cnBvc2VfdmFycywgIlxuIikKCiMgQ2hlY2sgZm9yIHNwZWNpZmljIGFudGliaW90aWMgdXNlIHZhcmlhYmxlcyBpbiBmYXJtIGRhdGEKZmFybV9zcGVjaWZpY19hYl92YXJzIDwtIGdyZXAoIl4oY2hsb3xuaXRyfGRpbWV8bWV0cnxjaXByfG9mbG98Y2FyYnxvbGFxfGJhY2kpJCIsIGZhcm1fdmFycywgdmFsdWUgPSBUUlVFKQpjYXQoIkZhcm0gc3BlY2lmaWMgYW50aWJpb3RpYyB2YXJpYWJsZXM6IiwgZmFybV9zcGVjaWZpY19hYl92YXJzLCAiXG4iKQoKIyBDaGVjayBmb3IgdmFyaWFibGVzIHJlbGF0ZWQgdG8gZmFybSBjaGFyYWN0ZXJpc3RpY3MKZmFybV9hbmltYWxfdmFycyA8LSBjKCJjaGlja2VucyIsICJwaWdzIiwgImNhdHRsZSIsICJkdWNrcyIsICJtdXNjb3Z5IiwgImdlZXNlIikKZmFybV9hbmltYWxfdmFyc19leGlzdCA8LSBmYXJtX2FuaW1hbF92YXJzICVpbiUgZmFybV92YXJzCm5hbWVzKGZhcm1fYW5pbWFsX3ZhcnNfZXhpc3QpIDwtIGZhcm1fYW5pbWFsX3ZhcnMKY2F0KCJGYXJtIGFuaW1hbCB2YXJpYWJsZXMgZXhpc3Q6IiwgZmFybV9hbmltYWxfdmFyc19leGlzdCwgIlxuIikKCiMjIERlZmluZSBhbnRpYmlvdGljIHR5cGVzIGJhc2VkIG9uIHZhcmlhYmxlIGluc3BlY3Rpb24KIyBUaGlzIGxpc3Qgc2hvdWxkIGJlIGFkanVzdGVkIGJhc2VkIG9uIGFjdHVhbCBkYXRhIHN0cnVjdHVyZQojIEFzc3VtaW5nIHE3XzExX19fMSB0byBxN18xMV9fXzEzIHJlcHJlc2VudCBkaWZmZXJlbnQgYW50aWJpb3RpY3MKYW50aWJpb3RpY19vcHRpb25zIDwtIGdyZXAoInE3XzExX19fWzEtOV18cTdfMTFfX18xWzAtM10iLCBob3VzZWhvbGRfdmFycywgdmFsdWUgPSBUUlVFKQoKIyBEZWZpbmUgd2hpY2ggb3B0aW9ucyBhcmUgYW50aWJpb3RpY3MgdnMuIG90aGVyIHRyZWF0bWVudHMKIyBUaGlzIHJlcXVpcmVzIGtub3dsZWRnZSBvZiB0aGUgc3VydmV5IGNvZGluZwphbnRpYmlvdGljX3ZhcnMgPC0gYygKICAicTdfMTFfX18xIiwgICMgQW1veGljaWxsaW4KICAicTdfMTFfX18yIiwgICMgQW1waWNpbGxpbgogICJxN18xMV9fXzMiLCAgIyBBbW94aWNpbGxpbi1jbGF2dWxhbmljIGFjaWQKICAicTdfMTFfX180IiwgICMgQXppdGhyb215Y2luL0VyeXRocm9teWNpbgogICJxN18xMV9fXzUiLCAgIyBDZWZhbGV4aW4KICAicTdfMTFfX182IiwgICMgQ2VmaXhpbWUKICAicTdfMTFfX183IiwgICMgQ2VmdXJveGltCiAgInE3XzExX19fOCIsICAjIENpcHJvZmxveGFjaW4vTGV2b2Zsb3hhY2luCiAgInE3XzExX19fOSIsICAjIENvdHJpbW94YXpvbGUKICAicTdfMTFfX18xMCIsICMgTWV0cm9uaWRhem9sZQogICJxN18xMV9fXzExIiwgIyBQZW5pY2lsbGluCiAgInE3XzExX19fMTIiLCAjIEFub3RoZXIgYW50aWJpb3RpYyBwaWxsL3N5cnVwL3Bvd2RlcgogICJxN18xMV9fXzEzIiAgIyBBbnRpYmlvdGljIGluamVjdGlvbiBvciBJViBmbHVpZAopCgojIENoZWNrIGlmIHRoZXNlIHZhcmlhYmxlcyBleGlzdCBpbiB0aGUgZGF0YXNldAphbnRpYmlvdGljX3ZhcnNfZXhpc3QgPC0gYW50aWJpb3RpY192YXJzICVpbiUgaG91c2Vob2xkX3ZhcnMKaWYoYW55KCFhbnRpYmlvdGljX3ZhcnNfZXhpc3QpKSB7CiAgd2FybmluZygiU29tZSBleHBlY3RlZCBhbnRpYmlvdGljIHZhcmlhYmxlcyBkb24ndCBleGlzdCBpbiB0aGUgZGF0YXNldC4gUGxlYXNlIGNoZWNrIHZhcmlhYmxlIG5hbWVzLiIpCiAgcHJpbnQoYW50aWJpb3RpY192YXJzWyFhbnRpYmlvdGljX3ZhcnNfZXhpc3RdKQp9CgojIyBDcmVhdGUgZGVyaXZlZCB2YXJpYWJsZXMgZm9yIGZhcm0gZGF0YQpmYXJtX2RhdGEgPC0gZmFybV9kYXRhICU+JQogIG11dGF0ZSgKICAgICMgQmluYXJ5IGluZGljYXRvciBmb3IgYW55IGFudGliaW90aWMgdXNlCiAgICBhbnlfYWJfdXNlID0gaWZlbHNlKGFidV9nZW5lcmFsID09IDIsIDEsIDApLAogICAgCiAgICAjIENyZWF0ZSBpbmRpY2F0b3JzIGZvciBkaWZmZXJlbnQgYW50aWJpb3RpYyB1c2UgcHVycG9zZXMKICAgICMgQ2hlY2sgaWYgdGhlc2UgYXJlIGJpbmFyeSB2YXJpYWJsZXMgb3IgbXVsdGlwbGUgc2VsZWN0aW9uIHZhcmlhYmxlcwogICAgYWJfdHJlYXRtZW50ID0gaWZlbHNlKHB1cnBvc2VfYW50aWJpb3RpY19fXzEgPT0gMSwgMSwgMCksCiAgICBhYl9wcmV2ZW50aW9uID0gaWZlbHNlKHB1cnBvc2VfYW50aWJpb3RpY19fXzIgPT0gMSwgMSwgMCksCiAgICBhYl9ncm93dGggPSBpZmVsc2UocHVycG9zZV9hbnRpYmlvdGljX19fMyA9PSAxLCAxLCAwKSwKICAgIAogICAgIyBDcmVhdGUgYSBzdW1tYXJ5IHZhcmlhYmxlIGZvciB0b3RhbCBudW1iZXIgb2YgcHVycG9zZXMKICAgIGFiX3B1cnBvc2VfY291bnQgPSBhYl90cmVhdG1lbnQgKyBhYl9wcmV2ZW50aW9uICsgYWJfZ3Jvd3RoLAogICAgCiAgICAjIEZhcm0gc2l6ZSBjYXRlZ29yaWVzIGJhc2VkIG9uIGFyZWFfZmFybQogICAgZmFybV9zaXplX2NhdCA9IGNhc2Vfd2hlbigKICAgICAgYXJlYV9mYXJtIDwgMTAwIH4gIlNtYWxsIiwKICAgICAgYXJlYV9mYXJtID49IDEwMCAmIGFyZWFfZmFybSA8IDEwMDAgfiAiTWVkaXVtIiwKICAgICAgYXJlYV9mYXJtID49IDEwMDAgfiAiTGFyZ2UiLAogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXwogICAgKSwKICAgIAogICAgIyBBbmltYWwgdHlwZSBjYXRlZ29yaWVzIGJhc2VkIG9uIHNwZWNpZXMKICAgIGFuaW1hbF90eXBlID0gY2FzZV93aGVuKAogICAgICBzcGVjaWVzID09IDEgfiAiQ2hpY2tlbiIsCiAgICAgIHNwZWNpZXMgPT0gMiB+ICJQaWciLAogICAgICBzcGVjaWVzID09IDMgfiAiQ2F0dGxlIiwKICAgICAgVFJVRSB+IE5BX2NoYXJhY3Rlcl8KICAgICksCiAgICAKICAgICMgQ3JlYXRlIHZhcmlhYmxlIGZvciByZXN0cmljdGVkIGFudGliaW90aWNzIHVzZSAoYW50aWJpb3RpY3MgdGhhdCBzaG91bGQgYmUgcmVzdHJpY3RlZCkKICAgICMgVGhlc2UgYXJlIGFudGliaW90aWNzIHRoYXQgYXJlIHBhcnRpY3VsYXJseSBjb25jZXJuaW5nIGZvciBBTVIKICAgIHJlc3RyaWN0ZWRfYWJfdXNlID0gaWZlbHNlKGNobG8gPT0gMSB8IGNpcHIgPT0gMSB8IG9mbG8gPT0gMSwgMSwgMCkKICApCgojIyBDcmVhdGUgZGVyaXZlZCB2YXJpYWJsZXMgZm9yIGhvdXNlaG9sZCBkYXRhCiMgRmlyc3QsIGNoZWNrIGhvdyB0aGUgYW50aWJpb3RpYyB1c2UgdmFyaWFibGVzIGFyZSBjb2RlZAppZihsZW5ndGgoYW50aWJpb3RpY192YXJzKSA+IDApIHsKICAjIENoZWNrIGZpcnN0IGZldyByb3dzIG9mIGZpcnN0IGFudGliaW90aWMgdmFyaWFibGUKICBhYl92YXJfc2FtcGxlIDwtIGhlYWQoaG91c2Vob2xkX2RhdGFbW2FudGliaW90aWNfdmFyc1sxXV1dKQogIGNhdCgiU2FtcGxlIHZhbHVlcyBmb3IgZmlyc3QgYW50aWJpb3RpYyB2YXJpYWJsZToiLCBhYl92YXJfc2FtcGxlLCAiXG4iKQogIAogICMgRGV0ZXJtaW5lIGNvbnZlcnNpb24gZnVuY3Rpb24gYmFzZWQgb24gdGhlIHZhcmlhYmxlIHR5cGUKICBpZihpcy5jaGFyYWN0ZXIoYWJfdmFyX3NhbXBsZSkpIHsKICAgICMgSWYgY2hhcmFjdGVyIChZZXMvTm8pLCBjb252ZXJ0IHRvIGJpbmFyeQogICAgY29udmVydF9mbiA8LSBmdW5jdGlvbih4KSBpZmVsc2UoeCA9PSAiWWVzIiwgMSwgMCkKICB9IGVsc2UgewogICAgIyBJZiBhbHJlYWR5IG51bWVyaWMgKDEvMCksIHVzZSBhcyBpcwogICAgY29udmVydF9mbiA8LSBmdW5jdGlvbih4KSB4CiAgfQogIAogICMgQ3JlYXRlIGRlcml2ZWQgdmFyaWFibGVzCiAgaG91c2Vob2xkX2RhdGEgPC0gaG91c2Vob2xkX2RhdGEgJT4lCiAgICBtdXRhdGUoCiAgICAgICMgQ3JlYXRlIGJpbmFyeSBpbmRpY2F0b3IgZm9yIGFueSBhbnRpYmlvdGljIHVzZQogICAgICAjIFN1bSBhY3Jvc3MgYWxsIGFudGliaW90aWMgdmFyaWFibGVzIGFuZCBjaGVjayBpZiA+IDAKICAgICAgYW55X2FiX2xhc3RfaWxsbmVzcyA9IGNhc2Vfd2hlbigKICAgICAgICByb3dTdW1zKGFjcm9zcyhhbGxfb2YoYW50aWJpb3RpY192YXJzKSwgfmNvbnZlcnRfZm4oLikpLCBuYS5ybSA9IFRSVUUpID4gMCB+IDEsCiAgICAgICAgVFJVRSB+IDAKICAgICAgKSwKICAgICAgCiAgICAgICMgQ3JlYXRlIG51bWVyaWMgdmVyc2lvbnMgb2YgYWxsIGFudGliaW90aWMgdmFyaWFibGVzCiAgICAgIGFjcm9zcyhhbGxfb2YoYW50aWJpb3RpY192YXJzKSwgfmNvbnZlcnRfZm4oLiksIC5uYW1lcyA9ICJudW1fey5jb2x9IikKICAgICkKICAKICAjIENoZWNrIGZvciByZWNlbnQgaWxsbmVzcyB2YXJpYWJsZXMKICBpbGxuZXNzX3ZhcnMgPC0gZ3JlcCgicTdfMV9fXyIsIGhvdXNlaG9sZF92YXJzLCB2YWx1ZSA9IFRSVUUpCiAgCiAgaWYobGVuZ3RoKGlsbG5lc3NfdmFycykgPiAwKSB7CiAgICAjIENyZWF0ZSBpbGxuZXNzIHR5cGUgaW5kaWNhdG9ycwogICAgaG91c2Vob2xkX2RhdGEgPC0gaG91c2Vob2xkX2RhdGEgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICAjIFJlc3BpcmF0b3J5IGlsbG5lc3MgaW5kaWNhdG9yCiAgICAgICAgcmVzcF9pbGxuZXNzID0gY2FzZV93aGVuKAogICAgICAgICAgcm93U3VtcyhhY3Jvc3MoYygicTdfMV9fXzIiLCAicTdfMV9fXzQiLCAicTdfMV9fXzUiKSwgfmNvbnZlcnRfZm4oLikpLCBuYS5ybSA9IFRSVUUpID4gMCB+IDEsCiAgICAgICAgICBUUlVFIH4gMAogICAgICAgICksCiAgICAgICAgCiAgICAgICAgIyBHYXN0cm9pbnRlc3RpbmFsIGlsbG5lc3MgaW5kaWNhdG9yCiAgICAgICAgZ2lfaWxsbmVzcyA9IGNhc2Vfd2hlbigKICAgICAgICAgIHJvd1N1bXMoYWNyb3NzKGMoInE3XzFfX182IiwgInE3XzFfX183IiksIH5jb252ZXJ0X2ZuKC4pKSwgbmEucm0gPSBUUlVFKSA+IDAgfiAxLAogICAgICAgICAgVFJVRSB+IDAKICAgICAgICApLAogICAgICAgIAogICAgICAgICMgRmV2ZXIgaW5kaWNhdG9yCiAgICAgICAgZmV2ZXIgPSBjb252ZXJ0X2ZuKHE3XzFfX18xKQogICAgICApCiAgfQp9CgojIyBDcmVhdGUgZ2VvZ3JhcGhpYyBsaW5rYWdlIGlmIHBvc3NpYmxlCiMgQ2hlY2sgaWYgd2UgaGF2ZSBtYXRjaGluZyBnZW9ncmFwaGljIHZhcmlhYmxlcwppZihhbGwoYygiZGlzdHJpY3QiLCAiY29tbXVuZSIpICVpbiUgZmFybV92YXJzKSAmJiAKICAgYWxsKGMoImRpc3RyaWN0IiwgImNvbW11bmUiKSAlaW4lIGhvdXNlaG9sZF92YXJzKSkgewogIAogICMgQ3JlYXRlIGdlb2dyYXBoaWMgSUQgZm9yIGxpbmthZ2UKICBmYXJtX2RhdGEgPC0gZmFybV9kYXRhICU+JQogICAgbXV0YXRlKGdlb19pZCA9IHBhc3RlKGRpc3RyaWN0LCBjb21tdW5lLCBzZXAgPSAiXyIpKQogIAogIGhvdXNlaG9sZF9kYXRhIDwtIGhvdXNlaG9sZF9kYXRhICU+JQogICAgbXV0YXRlKGdlb19pZCA9IHBhc3RlKGRpc3RyaWN0LCBjb21tdW5lLCBzZXAgPSAiXyIpKQogIAp9IGVsc2UgewogICMgSWYgc3RhbmRhcmQgZ2VvZ3JhcGhpYyB2YXJpYWJsZXMgZG9uJ3QgZXhpc3QsIGNoZWNrIGZvciBhbHRlcm5hdGl2ZXMKICB3YXJuaW5nKCJTdGFuZGFyZCBnZW9ncmFwaGljIHZhcmlhYmxlcyBub3QgZm91bmQuIENvbW11bml0eS1sZXZlbCBhbmFseXNpcyBtYXkgbm90IGJlIHBvc3NpYmxlLiIpCiAgCiAgIyBUcnkgdG8gdXNlIGZhcm1faWQgdG8gZXh0cmFjdCBnZW9ncmFwaGljIGluZm9ybWF0aW9uIGlmIGl0IGZvbGxvd3MgYSBwYXR0ZXJuCiAgIyBUaGlzIGlzIGp1c3QgYW4gZXhhbXBsZSBhbmQgd291bGQgbmVlZCB0byBiZSBhZGp1c3RlZCBiYXNlZCBvbiBhY3R1YWwgSUQgc3RydWN0dXJlCiAgaWYoImZhcm1faWQiICVpbiUgZmFybV92YXJzKSB7CiAgICBmYXJtX2RhdGEgPC0gZmFybV9kYXRhICU+JQogICAgICBtdXRhdGUoCiAgICAgICAgIyBFeHRyYWN0IGZpcnN0IHBhcnQgb2YgZmFybV9pZCBhcyBnZW9ncmFwaGljIGlkZW50aWZpZXIKICAgICAgICAjIFRoaXMgYXNzdW1lcyBmYXJtX2lkIGhhcyBhIHN0cnVjdHVyZSB3aGVyZSB0aGUgZmlyc3QgZGlnaXRzIHJlcHJlc2VudCBsb2NhdGlvbgogICAgICAgIGdlb19pZCA9IHN1YnN0cihhcy5jaGFyYWN0ZXIoZmFybV9pZCksIDEsIDUpCiAgICAgICkKICB9Cn0KCiMjIENoZWNrIGZvciBtaXNzaW5nIHZhbHVlcyBpbiBrZXkgdmFyaWFibGVzCiMgRmFybSBkYXRhCmZhcm1fbWlzc2luZyA8LSBmYXJtX2RhdGEgJT4lCiAgZHBseXI6OnNlbGVjdChhbnlfYWJfdXNlLCBhYl90cmVhdG1lbnQsIGFiX3ByZXZlbnRpb24sIGFiX2dyb3d0aCwgYW5pbWFsX3R5cGUsIGZhcm1fc2l6ZV9jYXQpICU+JQogIHN1bW1hcmlzZShhY3Jvc3MoZXZlcnl0aGluZygpLCB+c3VtKGlzLm5hKC4pKSwgLm5hbWVzID0gIm1pc3Npbmdfey5jb2x9IikpCgojIERpc3BsYXkgbWlzc2luZyB2YWx1ZXMgc3VtbWFyeQpwcmludCgiTWlzc2luZyB2YWx1ZXMgaW4ga2V5IGZhcm0gdmFyaWFibGVzOiIpCnByaW50KGZhcm1fbWlzc2luZykKCiMgSG91c2Vob2xkIGRhdGEKaWYoZXhpc3RzKCJhbnlfYWJfbGFzdF9pbGxuZXNzIiwgd2hlcmUgPSBob3VzZWhvbGRfZGF0YSkpIHsKICBob3VzZWhvbGRfbWlzc2luZyA8LSBob3VzZWhvbGRfZGF0YSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoYW55X2FiX2xhc3RfaWxsbmVzcywgbWF0Y2hlcygibnVtX3E3XzExX19fIikpICU+JQogICAgc3VtbWFyaXNlKGFjcm9zcyhldmVyeXRoaW5nKCksIH5zdW0oaXMubmEoLikpLCAubmFtZXMgPSAibWlzc2luZ197LmNvbH0iKSkKICAKICBwcmludCgiTWlzc2luZyB2YWx1ZXMgaW4ga2V5IGhvdXNlaG9sZCB2YXJpYWJsZXM6IikKICBwcmludChob3VzZWhvbGRfbWlzc2luZykKfQoKIyBTdW1tYXJ5IHN0YXRpc3RpY3Mgb24gZGVyaXZlZCB2YXJpYWJsZXMKZmFybV9zdW1tYXJ5IDwtIGZhcm1fZGF0YSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgYWJfdXNlX3BjdCA9IG1lYW4oYW55X2FiX3VzZSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIHRyZWF0bWVudF9wY3QgPSBtZWFuKGFiX3RyZWF0bWVudCwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIHByZXZlbnRpb25fcGN0ID0gbWVhbihhYl9wcmV2ZW50aW9uLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgZ3Jvd3RoX3BjdCA9IG1lYW4oYWJfZ3Jvd3RoLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgcmVzdHJpY3RlZF9hYl9wY3QgPSBtZWFuKHJlc3RyaWN0ZWRfYWJfdXNlLCBuYS5ybSA9IFRSVUUpICogMTAwCiAgKQoKcHJpbnQoIlN1bW1hcnkgb2YgZmFybSBhbnRpYmlvdGljIHVzZToiKQpwcmludChmYXJtX3N1bW1hcnkpCgpob3VzZWhvbGRfc3VtbWFyeSA8LSBob3VzZWhvbGRfZGF0YSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgYWJfdXNlX3BjdCA9IG1lYW4oYW55X2FiX2xhc3RfaWxsbmVzcywgbmEucm0gPSBUUlVFKSAqIDEwMAogICkKCnByaW50KCJTdW1tYXJ5IG9mIGhvdXNlaG9sZCBhbnRpYmlvdGljIHVzZToiKQpwcmludChob3VzZWhvbGRfc3VtbWFyeSkKCiMgQ2hlY2sgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmYXJtIHNpemVzIGFuZCBhbmltYWwgdHlwZXMKZmFybV9zaXplX2Rpc3QgPC0gZmFybV9kYXRhICU+JQogIGNvdW50KGZhcm1fc2l6ZV9jYXQpICU+JQogIG11dGF0ZShwY3QgPSBuIC8gc3VtKG4pICogMTAwKQoKYW5pbWFsX3R5cGVfZGlzdCA8LSBmYXJtX2RhdGEgJT4lCiAgY291bnQoYW5pbWFsX3R5cGUpICU+JQogIG11dGF0ZShwY3QgPSBuIC8gc3VtKG4pICogMTAwKQoKcHJpbnQoIkRpc3RyaWJ1dGlvbiBvZiBmYXJtIHNpemVzOiIpCnByaW50KGZhcm1fc2l6ZV9kaXN0KQoKcHJpbnQoIkRpc3RyaWJ1dGlvbiBvZiBhbmltYWwgdHlwZXM6IikKcHJpbnQoYW5pbWFsX3R5cGVfZGlzdCkKCiMgU2F2ZSB0aGUgcHJvY2Vzc2VkIGRhdGEgZm9yIHN1YnNlcXVlbnQgYW5hbHlzZXMKIyBUaGlzIGFsbG93cyB1cyB0byBjaGVja3BvaW50IG91ciBwcm9ncmVzcwpzYXZlUkRTKGZhcm1fZGF0YSwgaGVyZSgiRGF0YSIsICJwcm9jZXNzZWQiLCAiZmFybV9kYXRhX3Byb2Nlc3NlZC5yZHMiKSkKc2F2ZVJEUyhob3VzZWhvbGRfZGF0YSwgaGVyZSgiRGF0YSIsICJwcm9jZXNzZWQiLCAiaG91c2Vob2xkX2RhdGFfcHJvY2Vzc2VkLnJkcyIpKQpgYGAKCiMjIFJlc3VsdHMgZm9yIEh5cG90aGVzaXMgMS4xOiBQcmV2YWxlbmNlIG9mIEFudGliaW90aWMgVXNlIGluIEZhcm1zIGFuZCBIb3VzZWhvbGRzCgpgYGB7ciBoMX0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiMgUkVTRUFSQ0ggUVVFU1RJT04gMTogSFlQT1RIRVNJUyAxLjEgQU5BTFlTSVMKIyBQcmV2ZW50aXZlIGFuZCBncm93dGgtcHJvbW90aW5nIGFudGliaW90aWMgdXNlIGlzIGNvbW1vbiBpbiBmYXJtIGFuaW1hbHMsCiMgd2l0aCBwcmV2YWxlbmNlIHJhdGVzIGhpZ2hlciB0aGFuIGNvcnJlc3BvbmRpbmcgdXNlIGluIGh1bWFuIG1lZGljaW5lCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQoKdGhlbWVfc2V0KAogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpICsgCiAgdGhlbWUoCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyYXk5NSIsIGxpbmV3aWR0aCA9IDAuMyksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siLCBzaXplID0gOSksCiAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gIml0YWxpYyIsIGNvbG9yID0gImdyYXkzMCIpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpLAogICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KGNvbG9yID0gIndoaXRlIiwgZmlsbCA9IE5BLCBsaW5ld2lkdGggPSAwLjUpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3IgPSBOQSksCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gImJvbGQiLCBjb2xvciA9ICJncmF5MzAiKQogICkKKQoKbG93X3NhdF9wYWxldHRlIDwtIGMoIiNhOGMwZTAiLCAiI2UwYjVhOCIsICIjYThkM2I1IiwgIiNjM2I1ZDMiLCAiI2Q4Y2ZiMCIsICIjYTlkMGQzIikKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIDEuIERBVEEgUFJFUEFSQVRJT04KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIExvYWQgZGF0YXNldHMgaWYgbm90IGFscmVhZHkgaW4gbWVtb3J5CmlmICghZXhpc3RzKCJmYXJtX2RhdGEiKSkgewogIGZhcm1fZGF0YSA8LSByZWFkUkRTKGhlcmUoIkRhdGEiLCAicHJvY2Vzc2VkIiwgImZhcm1fZGF0YV9wcm9jZXNzZWQucmRzIikpCn0KaWYgKCFleGlzdHMoImhvdXNlaG9sZF9kYXRhIikpIHsKICBob3VzZWhvbGRfZGF0YSA8LSByZWFkUkRTKGhlcmUoIkRhdGEiLCAicHJvY2Vzc2VkIiwgImhvdXNlaG9sZF9kYXRhX3Byb2Nlc3NlZC5yZHMiKSkKfQoKIyBWZXJpZnkga2V5IHZhcmlhYmxlcyBpbiBmYXJtIGRhdGEKZmFybV92YXJzX2NoZWNrIDwtIGMoImFueV9hYl91c2UiLCAiYWJfdHJlYXRtZW50IiwgImFiX3ByZXZlbnRpb24iLCAiYWJfZ3Jvd3RoIiwgCiAgICAgICAgICAgICAgICAgICAgICJjaGxvIiwgIm5pdHIiLCAiZGltZSIsICJtZXRyIiwgImNpcHIiLCAib2ZsbyIsICJjYXJiIiwgIm9sYXEiLCAiYmFjaSIpCm1pc3NpbmdfZmFybV92YXJzIDwtIGZhcm1fdmFyc19jaGVja1shZmFybV92YXJzX2NoZWNrICVpbiUgbmFtZXMoZmFybV9kYXRhKV0KaWYobGVuZ3RoKG1pc3NpbmdfZmFybV92YXJzKSA+IDApIHsKICB3YXJuaW5nKHBhc3RlKCJNaXNzaW5nIGZhcm0gZGF0YSB2YXJpYWJsZXM6IiwgcGFzdGUobWlzc2luZ19mYXJtX3ZhcnMsIGNvbGxhcHNlPSIsICIpKSkKfQoKIyBWZXJpZnkga2V5IHZhcmlhYmxlcyBpbiBob3VzZWhvbGQgZGF0YQpob3VzZWhvbGRfdmFyc19jaGVjayA8LSBjKCJhbnlfYWJfbGFzdF9pbGxuZXNzIikKbWlzc2luZ19ob3VzZWhvbGRfdmFycyA8LSBob3VzZWhvbGRfdmFyc19jaGVja1shaG91c2Vob2xkX3ZhcnNfY2hlY2sgJWluJSBuYW1lcyhob3VzZWhvbGRfZGF0YSldCmlmKGxlbmd0aChtaXNzaW5nX2hvdXNlaG9sZF92YXJzKSA+IDApIHsKICB3YXJuaW5nKHBhc3RlKCJNaXNzaW5nIGhvdXNlaG9sZCBkYXRhIHZhcmlhYmxlczoiLCBwYXN0ZShtaXNzaW5nX2hvdXNlaG9sZF92YXJzLCBjb2xsYXBzZT0iLCAiKSkpCn0KCiMgQ2hlY2sgZm9yIHN5bXB0b20tcmVsYXRlZCB2YXJpYWJsZXMgaW4gaG91c2Vob2xkIGRhdGEKc3ltcHRvbV92YXJzIDwtIGdyZXAoInE3XzFfX18iLCBuYW1lcyhob3VzZWhvbGRfZGF0YSksIHZhbHVlID0gVFJVRSkKaWYobGVuZ3RoKHN5bXB0b21fdmFycykgPT0gMCkgewogIHdhcm5pbmcoIk5vIHN5bXB0b20gdmFyaWFibGVzIGZvdW5kIGluIGhvdXNlaG9sZCBkYXRhLiBDYW5ub3QgY3JlYXRlIHByZXZlbnRpdmUgdXNlIHByb3h5LiIpCn0KCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIDIuIEZBUk0gQU5USUJJT1RJQyBVU0UgUFJFVkFMRU5DRSBBTkFMWVNJUwojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgMi4xIENhbGN1bGF0ZSBmYXJtIGFudGliaW90aWMgdXNlIHByZXZhbGVuY2Ugd2l0aCBjb25maWRlbmNlIGludGVydmFscwpmYXJtX2FiX2NpIDwtIGZhcm1fZGF0YSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgYWJfdXNlID0gc3VtKGFueV9hYl91c2UsIG5hLnJtID0gVFJVRSksCiAgICBhYl90cmVhdG1lbnQgPSBzdW0oYWJfdHJlYXRtZW50LCBuYS5ybSA9IFRSVUUpLAogICAgYWJfcHJldmVudGlvbiA9IHN1bShhYl9wcmV2ZW50aW9uLCBuYS5ybSA9IFRSVUUpLAogICAgYWJfZ3Jvd3RoID0gc3VtKGFiX2dyb3d0aCwgbmEucm0gPSBUUlVFKQogICkgJT4lCiAgbXV0YXRlKAogICAgIyBPdmVyYWxsIHVzZSB3aXRoIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCiAgICBhYl91c2VfcGN0ID0gYWJfdXNlIC8gbiAqIDEwMCwKICAgIGFiX3VzZV9jaV9sb3dlciA9IGJpbm9tLmNvbmZpbnQoYWJfdXNlLCBuLCBtZXRob2QgPSAid2lsc29uIikkbG93ZXIgKiAxMDAsCiAgICBhYl91c2VfY2lfdXBwZXIgPSBiaW5vbS5jb25maW50KGFiX3VzZSwgbiwgbWV0aG9kID0gIndpbHNvbiIpJHVwcGVyICogMTAwLAogICAgCiAgICAjIFRyZWF0bWVudCB1c2Ugd2l0aCBjb25maWRlbmNlIGludGVydmFscwogICAgYWJfdHJlYXRtZW50X3BjdCA9IGFiX3RyZWF0bWVudCAvIG4gKiAxMDAsCiAgICBhYl90cmVhdG1lbnRfY2lfbG93ZXIgPSBiaW5vbS5jb25maW50KGFiX3RyZWF0bWVudCwgbiwgbWV0aG9kID0gIndpbHNvbiIpJGxvd2VyICogMTAwLAogICAgYWJfdHJlYXRtZW50X2NpX3VwcGVyID0gYmlub20uY29uZmludChhYl90cmVhdG1lbnQsIG4sIG1ldGhvZCA9ICJ3aWxzb24iKSR1cHBlciAqIDEwMCwKICAgIAogICAgIyBQcmV2ZW50aXZlIHVzZSB3aXRoIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCiAgICBhYl9wcmV2ZW50aW9uX3BjdCA9IGFiX3ByZXZlbnRpb24gLyBuICogMTAwLAogICAgYWJfcHJldmVudGlvbl9jaV9sb3dlciA9IGJpbm9tLmNvbmZpbnQoYWJfcHJldmVudGlvbiwgbiwgbWV0aG9kID0gIndpbHNvbiIpJGxvd2VyICogMTAwLAogICAgYWJfcHJldmVudGlvbl9jaV91cHBlciA9IGJpbm9tLmNvbmZpbnQoYWJfcHJldmVudGlvbiwgbiwgbWV0aG9kID0gIndpbHNvbiIpJHVwcGVyICogMTAwLAogICAgCiAgICAjIEdyb3d0aCBwcm9tb3Rpb24gdXNlIHdpdGggY29uZmlkZW5jZSBpbnRlcnZhbHMKICAgIGFiX2dyb3d0aF9wY3QgPSBhYl9ncm93dGggLyBuICogMTAwLAogICAgYWJfZ3Jvd3RoX2NpX2xvd2VyID0gYmlub20uY29uZmludChhYl9ncm93dGgsIG4sIG1ldGhvZCA9ICJ3aWxzb24iKSRsb3dlciAqIDEwMCwKICAgIGFiX2dyb3d0aF9jaV91cHBlciA9IGJpbm9tLmNvbmZpbnQoYWJfZ3Jvd3RoLCBuLCBtZXRob2QgPSAid2lsc29uIikkdXBwZXIgKiAxMDAKICApCgojIDIuMiBDYWxjdWxhdGUgbm9uLXRyZWF0bWVudCBhbnRpYmlvdGljIHVzZSBpbiBmYXJtcwpmYXJtX25vbl90cmVhdG1lbnQgPC0gZmFybV9kYXRhICU+JQogIHN1bW1hcmlzZSgKICAgIG4gPSBuKCksCiAgICBhbnlfbm9uX3RyZWF0bWVudCA9IHN1bShhYl9wcmV2ZW50aW9uID09IDEgfCBhYl9ncm93dGggPT0gMSwgbmEucm0gPSBUUlVFKSwKICAgIHByZXZlbnRpb25fb25seSA9IHN1bShhYl9wcmV2ZW50aW9uID09IDEgJiBhYl90cmVhdG1lbnQgPT0gMCAmIGFiX2dyb3d0aCA9PSAwLCBuYS5ybSA9IFRSVUUpLAogICAgZ3Jvd3RoX29ubHkgPSBzdW0oYWJfZ3Jvd3RoID09IDEgJiBhYl90cmVhdG1lbnQgPT0gMCAmIGFiX3ByZXZlbnRpb24gPT0gMCwgbmEucm0gPSBUUlVFKSwKICAgIGJvdGhfcHVycG9zZXMgPSBzdW0oYWJfcHJldmVudGlvbiA9PSAxICYgYWJfZ3Jvd3RoID09IDEgJiBhYl90cmVhdG1lbnQgPT0gMCwgbmEucm0gPSBUUlVFKQogICkgJT4lCiAgbXV0YXRlKAogICAgIyBDYWxjdWxhdGUgcGVyY2VudGFnZXMKICAgIGFueV9ub25fdHJlYXRtZW50X3BjdCA9IGFueV9ub25fdHJlYXRtZW50IC8gbiAqIDEwMCwKICAgIHByZXZlbnRpb25fb25seV9wY3QgPSBwcmV2ZW50aW9uX29ubHkgLyBuICogMTAwLAogICAgZ3Jvd3RoX29ubHlfcGN0ID0gZ3Jvd3RoX29ubHkgLyBuICogMTAwLAogICAgYm90aF9wdXJwb3Nlc19wY3QgPSBib3RoX3B1cnBvc2VzIC8gbiAqIDEwMCwKICAgIAogICAgIyBDYWxjdWxhdGUgY29uZmlkZW5jZSBpbnRlcnZhbHMKICAgIGFueV9ub25fdHJlYXRtZW50X2NpX2xvd2VyID0gYmlub20uY29uZmludChhbnlfbm9uX3RyZWF0bWVudCwgbiwgbWV0aG9kID0gIndpbHNvbiIpJGxvd2VyICogMTAwLAogICAgYW55X25vbl90cmVhdG1lbnRfY2lfdXBwZXIgPSBiaW5vbS5jb25maW50KGFueV9ub25fdHJlYXRtZW50LCBuLCBtZXRob2QgPSAid2lsc29uIikkdXBwZXIgKiAxMDAsCiAgICBwcmV2ZW50aW9uX29ubHlfY2lfbG93ZXIgPSBiaW5vbS5jb25maW50KHByZXZlbnRpb25fb25seSwgbiwgbWV0aG9kID0gIndpbHNvbiIpJGxvd2VyICogMTAwLAogICAgcHJldmVudGlvbl9vbmx5X2NpX3VwcGVyID0gYmlub20uY29uZmludChwcmV2ZW50aW9uX29ubHksIG4sIG1ldGhvZCA9ICJ3aWxzb24iKSR1cHBlciAqIDEwMCwKICAgIGdyb3d0aF9vbmx5X2NpX2xvd2VyID0gYmlub20uY29uZmludChncm93dGhfb25seSwgbiwgbWV0aG9kID0gIndpbHNvbiIpJGxvd2VyICogMTAwLAogICAgZ3Jvd3RoX29ubHlfY2lfdXBwZXIgPSBiaW5vbS5jb25maW50KGdyb3d0aF9vbmx5LCBuLCBtZXRob2QgPSAid2lsc29uIikkdXBwZXIgKiAxMDAsCiAgICBib3RoX3B1cnBvc2VzX2NpX2xvd2VyID0gYmlub20uY29uZmludChib3RoX3B1cnBvc2VzLCBuLCBtZXRob2QgPSAid2lsc29uIikkbG93ZXIgKiAxMDAsCiAgICBib3RoX3B1cnBvc2VzX2NpX3VwcGVyID0gYmlub20uY29uZmludChib3RoX3B1cnBvc2VzLCBuLCBtZXRob2QgPSAid2lsc29uIikkdXBwZXIgKiAxMDAKICApCgojIDIuMyBEaXNwbGF5IGZhcm0gYW50aWJpb3RpYyB1c2UgdGFibGUKZmFybV9hYl90YWJsZSA8LSBkYXRhLmZyYW1lKAogIFB1cnBvc2UgPSBjKCJBbnkgdXNlIiwgIlRyZWF0bWVudCIsICJQcmV2ZW50aW9uIiwgIkdyb3d0aCBwcm9tb3Rpb24iKSwKICBDb3VudCA9IGMoZmFybV9hYl9jaSRhYl91c2UsIGZhcm1fYWJfY2kkYWJfdHJlYXRtZW50LCAKICAgICAgICAgICAgZmFybV9hYl9jaSRhYl9wcmV2ZW50aW9uLCBmYXJtX2FiX2NpJGFiX2dyb3d0aCksCiAgUGVyY2VudGFnZSA9IGMoZmFybV9hYl9jaSRhYl91c2VfcGN0LCBmYXJtX2FiX2NpJGFiX3RyZWF0bWVudF9wY3QsIAogICAgICAgICAgICAgICAgZmFybV9hYl9jaSRhYl9wcmV2ZW50aW9uX3BjdCwgZmFybV9hYl9jaSRhYl9ncm93dGhfcGN0KSwKICBDSV9Mb3dlciA9IGMoZmFybV9hYl9jaSRhYl91c2VfY2lfbG93ZXIsIGZhcm1fYWJfY2kkYWJfdHJlYXRtZW50X2NpX2xvd2VyLCAKICAgICAgICAgICAgICBmYXJtX2FiX2NpJGFiX3ByZXZlbnRpb25fY2lfbG93ZXIsIGZhcm1fYWJfY2kkYWJfZ3Jvd3RoX2NpX2xvd2VyKSwKICBDSV9VcHBlciA9IGMoZmFybV9hYl9jaSRhYl91c2VfY2lfdXBwZXIsIGZhcm1fYWJfY2kkYWJfdHJlYXRtZW50X2NpX3VwcGVyLCAKICAgICAgICAgICAgICBmYXJtX2FiX2NpJGFiX3ByZXZlbnRpb25fY2lfdXBwZXIsIGZhcm1fYWJfY2kkYWJfZ3Jvd3RoX2NpX3VwcGVyKQopICU+JQogIG11dGF0ZSgKICAgIENJID0gcGFzdGUwKHJvdW5kKENJX0xvd2VyLCAxKSwgIi0iLCByb3VuZChDSV9VcHBlciwgMSkpLAogICAgYFByZXZhbGVuY2UgKDk1JSBDSSlgID0gcGFzdGUwKHJvdW5kKFBlcmNlbnRhZ2UsIDEpLCAiJSAoIiwgQ0ksICIpIikKICApCgojIERpc3BsYXkgZmFybSBhbnRpYmlvdGljIHVzZSB0YWJsZQprYWJsZShmYXJtX2FiX3RhYmxlICU+JSBkcGx5cjo6c2VsZWN0KFB1cnBvc2UsIENvdW50LCBgUHJldmFsZW5jZSAoOTUlIENJKWApLAogICAgICBjYXB0aW9uID0gIkZhcm0gQW50aWJpb3RpYyBVc2UgUHJldmFsZW5jZSB3aXRoIDk1JSBDb25maWRlbmNlIEludGVydmFscyIsCiAgICAgIGFsaWduID0gImxyciIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCAKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIDMuIEhPVVNFSE9MRCBBTlRJQklPVElDIFVTRSBQUkVWQUxFTkNFIEFOQUxZU0lTCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyAzLjEgQ2FsY3VsYXRlIGhvdXNlaG9sZCBhbnRpYmlvdGljIHVzZSBwcmV2YWxlbmNlIHdpdGggY29uZmlkZW5jZSBpbnRlcnZhbHMKaG91c2Vob2xkX2FiX2NpIDwtIGhvdXNlaG9sZF9kYXRhICU+JQogIHN1bW1hcmlzZSgKICAgIG4gPSBuKCksCiAgICBhYl91c2UgPSBzdW0oYW55X2FiX2xhc3RfaWxsbmVzcywgbmEucm0gPSBUUlVFKQogICkgJT4lCiAgbXV0YXRlKAogICAgIyBPdmVyYWxsIHVzZSB3aXRoIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCiAgICBhYl91c2VfcGN0ID0gYWJfdXNlIC8gbiAqIDEwMCwKICAgIGFiX3VzZV9jaV9sb3dlciA9IGJpbm9tLmNvbmZpbnQoYWJfdXNlLCBuLCBtZXRob2QgPSAid2lsc29uIikkbG93ZXIgKiAxMDAsCiAgICBhYl91c2VfY2lfdXBwZXIgPSBiaW5vbS5jb25maW50KGFiX3VzZSwgbiwgbWV0aG9kID0gIndpbHNvbiIpJHVwcGVyICogMTAwCiAgKQoKIyAzLjIgRGlzcGxheSBob3VzZWhvbGQgYW50aWJpb3RpYyB1c2UKaG91c2Vob2xkX2FiX3RhYmxlIDwtIGRhdGEuZnJhbWUoCiAgUHVycG9zZSA9ICJBbnkgdXNlIiwKICBDb3VudCA9IGhvdXNlaG9sZF9hYl9jaSRhYl91c2UsCiAgUGVyY2VudGFnZSA9IGhvdXNlaG9sZF9hYl9jaSRhYl91c2VfcGN0LAogIENJX0xvd2VyID0gaG91c2Vob2xkX2FiX2NpJGFiX3VzZV9jaV9sb3dlciwKICBDSV9VcHBlciA9IGhvdXNlaG9sZF9hYl9jaSRhYl91c2VfY2lfdXBwZXIKKSAlPiUKICBtdXRhdGUoCiAgICBDSSA9IHBhc3RlMChyb3VuZChDSV9Mb3dlciwgMSksICItIiwgcm91bmQoQ0lfVXBwZXIsIDEpKSwKICAgIGBQcmV2YWxlbmNlICg5NSUgQ0kpYCA9IHBhc3RlMChyb3VuZChQZXJjZW50YWdlLCAxKSwgIiUgKCIsIENJLCAiKSIpCiAgKQoKa2FibGUoaG91c2Vob2xkX2FiX3RhYmxlICU+JSBkcGx5cjo6c2VsZWN0KFB1cnBvc2UsIENvdW50LCBgUHJldmFsZW5jZSAoOTUlIENJKWApLAogICAgICBjYXB0aW9uID0gIkhvdXNlaG9sZCBBbnRpYmlvdGljIFVzZSBQcmV2YWxlbmNlIHdpdGggOTUlIENvbmZpZGVuY2UgSW50ZXJ2YWxzIiwKICAgICAgYWxpZ24gPSAibHJyIikgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIAogICAgICAgICAgICAgICAgZnVsbF93aWR0aCA9IEZBTFNFKQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgNC4gQ1JFQVRJTkcgSE9VU0VIT0xEIFBSRVZFTlRJVkUgVVNFIFBST1hZIElORElDQVRPUgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMgNC4xIENyZWF0ZSBzeW1wdG9tIGluZGljYXRvcnMgCiMgSGVscGVyIGZ1bmN0aW9uIHRvIHNhZmVseSBjaGVjayBpZiBhIHZhcmlhYmxlIGluZGljYXRlcyBhIHN5bXB0b20KaXNfc3ltcHRvbV9wb3NpdGl2ZSA8LSBmdW5jdGlvbihkYXRhLCB2YXJfbmFtZSkgewogICMgQ2hlY2sgaWYgdmFyaWFibGUgZXhpc3RzCiAgaWYoISh2YXJfbmFtZSAlaW4lIG5hbWVzKGRhdGEpKSkgewogICAgcmV0dXJuKHJlcChGQUxTRSwgbnJvdyhkYXRhKSkpCiAgfQogIAogICMgR2V0IHRoZSB2YXJpYWJsZQogIHZhcl9kYXRhIDwtIGRhdGFbW3Zhcl9uYW1lXV0KICAKICAjIEhhbmRsZSBkaWZmZXJlbnQgZGF0YSB0eXBlcwogIHJlc3VsdCA8LSByZXAoRkFMU0UsIGxlbmd0aCh2YXJfZGF0YSkpCiAgCiAgZm9yKGkgaW4gMTpsZW5ndGgodmFyX2RhdGEpKSB7CiAgICB2YWwgPC0gdmFyX2RhdGFbaV0KICAgIAogICAgIyBTa2lwIE5BIHZhbHVlcwogICAgaWYoaXMubmEodmFsKSkgewogICAgICByZXN1bHRbaV0gPC0gRkFMU0UKICAgICAgbmV4dAogICAgfQogICAgCiAgICAjIEhhbmRsZSBjaGFyYWN0ZXIgdmFsdWVzCiAgICBpZihpcy5jaGFyYWN0ZXIodmFsKSkgewogICAgICByZXN1bHRbaV0gPC0gKHZhbCA9PSAiWWVzIikKICAgICAgbmV4dAogICAgfQogICAgCiAgICAjIEhhbmRsZSBudW1lcmljIHZhbHVlcwogICAgaWYoaXMubnVtZXJpYyh2YWwpKSB7CiAgICAgIHJlc3VsdFtpXSA8LSAodmFsID09IDEpCiAgICAgIG5leHQKICAgIH0KICAgIAogICAgIyBEZWZhdWx0IGZvciBvdGhlciB0eXBlcwogICAgcmVzdWx0W2ldIDwtIEZBTFNFCiAgfQogIAogIHJldHVybihyZXN1bHQpCn0KCiMgQ3JlYXRlIGluZGljYXRvciB2YXJpYWJsZXMgZm9yIGRpZmZlcmVudCBzeW1wdG9tIHR5cGVzCm5fcm93cyA8LSBucm93KGhvdXNlaG9sZF9kYXRhKQoKIyBJbml0aWFsaXplIGZsYWdzCmhhc19mZXZlciA8LSByZXAoRkFMU0UsIG5fcm93cykKaGFzX3Jlc3AgPC0gcmVwKEZBTFNFLCBuX3Jvd3MpCmhhc19naSA8LSByZXAoRkFMU0UsIG5fcm93cykKaGFzX2FueSA8LSByZXAoRkFMU0UsIG5fcm93cykKCiMgRmV2ZXIgLSB2YXJpYWJsZSBxN18xX19fMSAoYWRqdXN0IHZhcmlhYmxlIG5hbWVzIGlmIG5lZWRlZCkKZmV2ZXJfdmFyIDwtICJxN18xX19fMSIKaWYoZmV2ZXJfdmFyICVpbiUgc3ltcHRvbV92YXJzKSB7CiAgaGFzX2ZldmVyIDwtIGlzX3N5bXB0b21fcG9zaXRpdmUoaG91c2Vob2xkX2RhdGEsIGZldmVyX3ZhcikKfQoKIyBSZXNwaXJhdG9yeSBzeW1wdG9tcyAtIHZhcmlhYmxlcyBxN18xX19fMiwgcTdfMV9fXzQsIHE3XzFfX181IChhZGp1c3QgYXMgbmVlZGVkKQpyZXNwX3ZhcnMgPC0gYygicTdfMV9fXzIiLCAicTdfMV9fXzQiLCAicTdfMV9fXzUiKQpmb3IodmFyIGluIGludGVyc2VjdChyZXNwX3ZhcnMsIHN5bXB0b21fdmFycykpIHsKICBoYXNfcmVzcCA8LSBoYXNfcmVzcCB8IGlzX3N5bXB0b21fcG9zaXRpdmUoaG91c2Vob2xkX2RhdGEsIHZhcikKfQoKIyBHSSBzeW1wdG9tcyAtIHZhcmlhYmxlcyBxN18xX19fNiwgcTdfMV9fXzcgKGFkanVzdCBhcyBuZWVkZWQpCmdpX3ZhcnMgPC0gYygicTdfMV9fXzYiLCAicTdfMV9fXzciKQpmb3IodmFyIGluIGludGVyc2VjdChnaV92YXJzLCBzeW1wdG9tX3ZhcnMpKSB7CiAgaGFzX2dpIDwtIGhhc19naSB8IGlzX3N5bXB0b21fcG9zaXRpdmUoaG91c2Vob2xkX2RhdGEsIHZhcikKfQoKIyBBbnkgc3ltcHRvbSAtIGNoZWNrIGFsbCBzeW1wdG9tIHZhcmlhYmxlcwpmb3IodmFyIGluIHN5bXB0b21fdmFycykgewogIGhhc19hbnkgPC0gaGFzX2FueSB8IGlzX3N5bXB0b21fcG9zaXRpdmUoaG91c2Vob2xkX2RhdGEsIHZhcikKfQoKIyBBZGQgZmxhZ3MgdG8gdGhlIGRhdGFzZXQKaG91c2Vob2xkX2RhdGEkZmV2ZXJfaW5kaWNhdG9yIDwtIGFzLmludGVnZXIoaGFzX2ZldmVyKQpob3VzZWhvbGRfZGF0YSRyZXNwX2luZGljYXRvciA8LSBhcy5pbnRlZ2VyKGhhc19yZXNwKQpob3VzZWhvbGRfZGF0YSRnaV9pbmRpY2F0b3IgPC0gYXMuaW50ZWdlcihoYXNfZ2kpCmhvdXNlaG9sZF9kYXRhJGFueV9zeW1wdG9tIDwtIGFzLmludGVnZXIoaGFzX2FueSkKCiMgNC4yIENyZWF0ZSB0aGUgcHJpbWFyeSBwcmV2ZW50aXZlIHVzZSBwcm94eSBpbmRpY2F0b3IgKHN0cmluZ2VudCBkZWZpbml0aW9uKQpob3VzZWhvbGRfZGF0YSA8LSBob3VzZWhvbGRfZGF0YSAlPiUKICBtdXRhdGUoCiAgICAjIFN0cmluZ2VudCBkZWZpbml0aW9uOiBBQiB1c2Ugd2l0aCBOTyBzeW1wdG9tcyBhdCBhbGwKICAgIHByZXZlbnRpdmVfdXNlX3Byb3h5X3N0cmluZ2VudCA9IGNhc2Vfd2hlbigKICAgICAgYW55X2FiX2xhc3RfaWxsbmVzcyA9PSAxICYgYW55X3N5bXB0b20gPT0gMCB+IDEsCiAgICAgIFRSVUUgfiAwCiAgICApLAogICAgCiAgICAjIEFsdGVybmF0aXZlIGRlZmluaXRpb246IEFCIHVzZSB3aXRoIG9ubHkgbWlub3Igc3ltcHRvbXMgCiAgICAjIChubyBmZXZlciwgbm8gcmVzcGlyYXRvcnkgc3ltcHRvbXMsIG5vIEdJIHN5bXB0b21zKQogICAgcHJldmVudGl2ZV91c2VfcHJveHlfcmVsYXhlZCA9IGNhc2Vfd2hlbigKICAgICAgYW55X2FiX2xhc3RfaWxsbmVzcyA9PSAxICYgZmV2ZXJfaW5kaWNhdG9yID09IDAgJiAKICAgICAgICByZXNwX2luZGljYXRvciA9PSAwICYgZ2lfaW5kaWNhdG9yID09IDAgfiAxLAogICAgICBUUlVFIH4gMAogICAgKQogICkKCiMgNC4zIENhbGN1bGF0ZSBob3VzZWhvbGQgcHJldmVudGl2ZSB1c2Ugc3RhdGlzdGljcyAtIHByaW1hcnkgZGVmaW5pdGlvbgpob3VzZWhvbGRfcHJldmVudGl2ZV9zdHJpbmdlbnQgPC0gaG91c2Vob2xkX2RhdGEgJT4lCiAgc3VtbWFyaXNlKAogICAgbiA9IG4oKSwKICAgIHByZXZlbnRpdmVfbiA9IHN1bShwcmV2ZW50aXZlX3VzZV9wcm94eV9zdHJpbmdlbnQsIG5hLnJtID0gVFJVRSksCiAgICBwcmV2ZW50aXZlX3BjdCA9IG1lYW4ocHJldmVudGl2ZV91c2VfcHJveHlfc3RyaW5nZW50LCBuYS5ybSA9IFRSVUUpICogMTAwCiAgKQoKIyBBZGQgY29uZmlkZW5jZSBpbnRlcnZhbHMKY2lfc3RyaW5nZW50IDwtIGJpbm9tLnRlc3QoaG91c2Vob2xkX3ByZXZlbnRpdmVfc3RyaW5nZW50JHByZXZlbnRpdmVfbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICBob3VzZWhvbGRfcHJldmVudGl2ZV9zdHJpbmdlbnQkbikkY29uZi5pbnQgKiAxMDAKaG91c2Vob2xkX3ByZXZlbnRpdmVfc3RyaW5nZW50JHByZXZlbnRpdmVfY2lfbG93ZXIgPC0gY2lfc3RyaW5nZW50WzFdCmhvdXNlaG9sZF9wcmV2ZW50aXZlX3N0cmluZ2VudCRwcmV2ZW50aXZlX2NpX3VwcGVyIDwtIGNpX3N0cmluZ2VudFsyXQoKIyA0LjQgQ2FsY3VsYXRlIGhvdXNlaG9sZCBwcmV2ZW50aXZlIHVzZSB3aXRoIGFsdGVybmF0aXZlIGRlZmluaXRpb24KaG91c2Vob2xkX3ByZXZlbnRpdmVfcmVsYXhlZCA8LSBob3VzZWhvbGRfZGF0YSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgcHJldmVudGl2ZV9uID0gc3VtKHByZXZlbnRpdmVfdXNlX3Byb3h5X3JlbGF4ZWQsIG5hLnJtID0gVFJVRSksCiAgICBwcmV2ZW50aXZlX3BjdCA9IG1lYW4ocHJldmVudGl2ZV91c2VfcHJveHlfcmVsYXhlZCwgbmEucm0gPSBUUlVFKSAqIDEwMAogICkKCiMgQWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCmNpX3JlbGF4ZWQgPC0gYmlub20udGVzdChob3VzZWhvbGRfcHJldmVudGl2ZV9yZWxheGVkJHByZXZlbnRpdmVfbiwgCiAgICAgICAgICAgICAgICAgICAgICAgaG91c2Vob2xkX3ByZXZlbnRpdmVfcmVsYXhlZCRuKSRjb25mLmludCAqIDEwMApob3VzZWhvbGRfcHJldmVudGl2ZV9yZWxheGVkJHByZXZlbnRpdmVfY2lfbG93ZXIgPC0gY2lfcmVsYXhlZFsxXQpob3VzZWhvbGRfcHJldmVudGl2ZV9yZWxheGVkJHByZXZlbnRpdmVfY2lfdXBwZXIgPC0gY2lfcmVsYXhlZFsyXQoKIyBEaXNwbGF5IHJlc3VsdHMgZm9yIGJvdGggZGVmaW5pdGlvbnMKY2F0KCJcbkhvdXNlaG9sZCBQcmV2ZW50aXZlIEFudGliaW90aWMgVXNlIC0gU2Vuc2l0aXZpdHkgQW5hbHlzaXM6XG4iKQpjYXQoIjEuIFN0cmluZ2VudCBkZWZpbml0aW9uIChOTyBzeW1wdG9tcyk6XG4iKQpjYXQoIiAgIENvdW50OiIsIGhvdXNlaG9sZF9wcmV2ZW50aXZlX3N0cmluZ2VudCRwcmV2ZW50aXZlX24sICJvdXQgb2YiLCAKICAgIGhvdXNlaG9sZF9wcmV2ZW50aXZlX3N0cmluZ2VudCRuLCAiaG91c2Vob2xkc1xuIikKY2F0KCIgICBQZXJjZW50YWdlOiIsIHJvdW5kKGhvdXNlaG9sZF9wcmV2ZW50aXZlX3N0cmluZ2VudCRwcmV2ZW50aXZlX3BjdCwgMSksIAogICAgIiUgKDk1JSBDSToiLCByb3VuZChob3VzZWhvbGRfcHJldmVudGl2ZV9zdHJpbmdlbnQkcHJldmVudGl2ZV9jaV9sb3dlciwgMSksICItIiwgCiAgICByb3VuZChob3VzZWhvbGRfcHJldmVudGl2ZV9zdHJpbmdlbnQkcHJldmVudGl2ZV9jaV91cHBlciwgMSksICIlKVxuXG4iKQoKY2F0KCIyLiBSZWxheGVkIGRlZmluaXRpb24gKG1pbm9yIG9yIG5vIHN5bXB0b21zKTpcbiIpCmNhdCgiICAgQ291bnQ6IiwgaG91c2Vob2xkX3ByZXZlbnRpdmVfcmVsYXhlZCRwcmV2ZW50aXZlX24sICJvdXQgb2YiLCAKICAgIGhvdXNlaG9sZF9wcmV2ZW50aXZlX3JlbGF4ZWQkbiwgImhvdXNlaG9sZHNcbiIpCmNhdCgiICAgUGVyY2VudGFnZToiLCByb3VuZChob3VzZWhvbGRfcHJldmVudGl2ZV9yZWxheGVkJHByZXZlbnRpdmVfcGN0LCAxKSwgCiAgICAiJSAoOTUlIENJOiIsIHJvdW5kKGhvdXNlaG9sZF9wcmV2ZW50aXZlX3JlbGF4ZWQkcHJldmVudGl2ZV9jaV9sb3dlciwgMSksICItIiwgCiAgICByb3VuZChob3VzZWhvbGRfcHJldmVudGl2ZV9yZWxheGVkJHByZXZlbnRpdmVfY2lfdXBwZXIsIDEpLCAiJSlcbiIpCgojIEZvciBzdWJzZXF1ZW50IGFuYWx5c2VzLCB1c2UgdGhlIHN0cmluZ2VudCBkZWZpbml0aW9uIGFzIHByaW1hcnkKaG91c2Vob2xkX3ByZXZlbnRpdmUgPC0gaG91c2Vob2xkX3ByZXZlbnRpdmVfc3RyaW5nZW50CgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyA1LiBBTkFMWVNJUyBCWSBTWU1QVE9NL0RJU0VBU0UgU1RBVFVTCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyA1LjEgQ3JlYXRlIGJyZWFrZG93biBvZiBob3VzZWhvbGQgYW50aWJpb3RpYyB1c2UgYnkgc3ltcHRvbSBzdGF0dXMKaG91c2Vob2xkX2J5X3N5bXB0b20gPC0gaG91c2Vob2xkX2RhdGEgJT4lCiAgbXV0YXRlKAogICAgc3ltcHRvbV9zdGF0dXMgPSBjYXNlX3doZW4oCiAgICAgIHJlc3BfaW5kaWNhdG9yID09IDEgfiAiUmVzcGlyYXRvcnkgc3ltcHRvbXMiLAogICAgICBnaV9pbmRpY2F0b3IgPT0gMSB+ICJHSSBzeW1wdG9tcyIsCiAgICAgIGZldmVyX2luZGljYXRvciA9PSAxIH4gIkZldmVyIiwKICAgICAgYW55X3N5bXB0b20gPT0gMSB+ICJPdGhlciBzeW1wdG9tcyIsCiAgICAgIFRSVUUgfiAiTm8gc3ltcHRvbXMiCiAgICApCiAgKSAlPiUKICBncm91cF9ieShzeW1wdG9tX3N0YXR1cykgJT4lCiAgc3VtbWFyaXNlKAogICAgbiA9IG4oKSwKICAgIGFiX3VzZV9uID0gc3VtKGFueV9hYl9sYXN0X2lsbG5lc3MsIG5hLnJtID0gVFJVRSksCiAgICBhYl91c2VfcGN0ID0gbWVhbihhbnlfYWJfbGFzdF9pbGxuZXNzLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkKCiMgQ2FsY3VsYXRlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCmhvdXNlaG9sZF9ieV9zeW1wdG9tIDwtIGhvdXNlaG9sZF9ieV9zeW1wdG9tICU+JQogIG11dGF0ZSgKICAgICMgQ2FsY3VsYXRlIENJcyB1c2luZyBhIG1vcmUgcm9idXN0IG1ldGhvZAogICAgYWJfdXNlX2NpX2xvd2VyID0gbWFwcGx5KGZ1bmN0aW9uKHgsIG4pIHsKICAgICAgaWYobiA9PSAwKSByZXR1cm4oMCkKICAgICAgY2kgPC0gYmlub20udGVzdCh4LCBuKSRjb25mLmludAogICAgICByZXR1cm4oY2lbMV0gKiAxMDApCiAgICB9LCBhYl91c2VfbiwgbiksCiAgICAKICAgIGFiX3VzZV9jaV91cHBlciA9IG1hcHBseShmdW5jdGlvbih4LCBuKSB7CiAgICAgIGlmKG4gPT0gMCkgcmV0dXJuKDApCiAgICAgIGNpIDwtIGJpbm9tLnRlc3QoeCwgbikkY29uZi5pbnQKICAgICAgcmV0dXJuKGNpWzJdICogMTAwKQogICAgfSwgYWJfdXNlX24sIG4pLAogICAgCiAgICAjIEZvcm1hdCB0aGUgQ0kgc3RyaW5nIHByb3Blcmx5LCBoYW5kbGluZyBhbnkgTkEgdmFsdWVzCiAgICBDSSA9IGlmZWxzZShpcy5uYShhYl91c2VfY2lfdXBwZXIpLCAKICAgICAgICAgICAgICAgIHBhc3RlMChyb3VuZChhYl91c2VfY2lfbG93ZXIsIDEpLCAiLT8iKSwgCiAgICAgICAgICAgICAgICBwYXN0ZTAocm91bmQoYWJfdXNlX2NpX2xvd2VyLCAxKSwgIi0iLCByb3VuZChhYl91c2VfY2lfdXBwZXIsIDEpKSksCiAgICAKICAgIGBQcmV2YWxlbmNlICg5NSUgQ0kpYCA9IHBhc3RlMChyb3VuZChhYl91c2VfcGN0LCAxKSwgIiUgKCIsIENJLCAiKSIpCiAgKQpjaV9kYXRhIDwtIGJpbm9tLmNvbmZpbnQoaG91c2Vob2xkX2J5X3N5bXB0b20kYWJfdXNlX24sIGhvdXNlaG9sZF9ieV9zeW1wdG9tJG4sIAogICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAid2lsc29uIiwgY29uZi5sZXZlbCA9IDAuOTUpCmhvdXNlaG9sZF9ieV9zeW1wdG9tJGFiX3VzZV9jaV9sb3dlciA8LSBjaV9kYXRhJGxvd2VyICogMTAwCmhvdXNlaG9sZF9ieV9zeW1wdG9tJGFiX3VzZV9jaV91cHBlciA8LSBjaV9kYXRhJHVwcGVyICogMTAwCgojIERpc3BsYXkgdGhlIHJlc3VsdHMKa2FibGUoaG91c2Vob2xkX2J5X3N5bXB0b20gJT4lIAogICAgICAgIGRwbHlyOjpzZWxlY3Qoc3ltcHRvbV9zdGF0dXMsIG4sIGFiX3VzZV9uLCBgUHJldmFsZW5jZSAoOTUlIENJKWApLAogICAgICBjYXB0aW9uID0gIkhvdXNlaG9sZCBBbnRpYmlvdGljIFVzZSBieSBTeW1wdG9tIFN0YXR1cyIsCiAgICAgIGNvbC5uYW1lcyA9IGMoIlN5bXB0b20gU3RhdHVzIiwgIlNhbXBsZSBTaXplIiwgIkFCIFVzZXJzIiwgIlByZXZhbGVuY2UgKDk1JSBDSSkiKSwKICAgICAgYWxpZ24gPSAibHJyciIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCAKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIDYuIENPTVBBUkFUSVZFIEFOQUxZU0lTIE9GIEZBUk0gVlMgSE9VU0VIT0xEIEFOVElCSU9USUMgVVNFCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyA2LjEgQ29tcGFyaXNvbiBvZiBvdmVyYWxsIGFudGliaW90aWMgdXNlCiMgQ3JlYXRlIGEgY29udGluZ2VuY3kgdGFibGUKb3ZlcmFsbF90YWJsZSA8LSBtYXRyaXgoCiAgYyhmYXJtX2FiX2NpJGFiX3VzZSwgZmFybV9hYl9jaSRuIC0gZmFybV9hYl9jaSRhYl91c2UsCiAgICBob3VzZWhvbGRfYWJfY2kkYWJfdXNlLCBob3VzZWhvbGRfYWJfY2kkbiAtIGhvdXNlaG9sZF9hYl9jaSRhYl91c2UpLAogIG5yb3cgPSAyLAogIGRpbW5hbWVzID0gbGlzdCgKICAgIGMoIkZhcm0iLCAiSG91c2Vob2xkIiksCiAgICBjKCJBbnRpYmlvdGljIFVzZSIsICJObyBBbnRpYmlvdGljIFVzZSIpCiAgKQopCgojIERpc3BsYXkgdGhlIGNvbnRpbmdlbmN5IHRhYmxlCmthYmxlKG92ZXJhbGxfdGFibGUsIGNhcHRpb24gPSAiQ29udGluZ2VuY3kgVGFibGUgZm9yIE92ZXJhbGwgQW50aWJpb3RpYyBVc2UiKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRkFMU0UpCgojIFBlcmZvcm0gY2hpLXNxdWFyZSB0ZXN0Cm92ZXJhbGxfY2hpIDwtIGNoaXNxLnRlc3Qob3ZlcmFsbF90YWJsZSkKCiMgQ2FsY3VsYXRlIGVmZmVjdCBzaXplIChQaGkgY29lZmZpY2llbnQpCm92ZXJhbGxfcGhpIDwtIHNxcnQob3ZlcmFsbF9jaGkkc3RhdGlzdGljIC8gc3VtKG92ZXJhbGxfdGFibGUpKQoKIyBEZXRlcm1pbmUgZWZmZWN0IHNpemUgaW50ZXJwcmV0YXRpb24Kb3ZlcmFsbF9lZmZlY3QgPC0gY2FzZV93aGVuKAogIGFicyhvdmVyYWxsX3BoaSkgPCAwLjEgfiAiTmVnbGlnaWJsZSIsCiAgYWJzKG92ZXJhbGxfcGhpKSA8IDAuMyB+ICJTbWFsbCIsCiAgYWJzKG92ZXJhbGxfcGhpKSA8IDAuNSB+ICJNZWRpdW0iLAogIFRSVUUgfiAiTGFyZ2UiCikKCiMgNi4yIENvbXBhcmlzb24gb2YgcHJldmVudGl2ZSBhbnRpYmlvdGljIHVzZQojIENyZWF0ZSBjb21wYXJpc29uIGRhdGEgZnJhbWUKcHJldmVudGl2ZV9jb21wYXJpc29uIDwtIGRhdGEuZnJhbWUoCiAgQ2F0ZWdvcnkgPSBjKCJGYXJtIFByZXZlbnRpdmUgVXNlIiwgIkhvdXNlaG9sZCBQcmV2ZW50aXZlIFVzZSAoUHJveHkpIiksCiAgQ291bnQgPSBjKGZhcm1fYWJfY2kkYWJfcHJldmVudGlvbiwgaG91c2Vob2xkX3ByZXZlbnRpdmUkcHJldmVudGl2ZV9uKSwKICBUb3RhbCA9IGMoZmFybV9hYl9jaSRuLCBob3VzZWhvbGRfcHJldmVudGl2ZSRuKSwKICBQZXJjZW50YWdlID0gYyhmYXJtX2FiX2NpJGFiX3ByZXZlbnRpb25fcGN0LCBob3VzZWhvbGRfcHJldmVudGl2ZSRwcmV2ZW50aXZlX3BjdCksCiAgQ0lfTG93ZXIgPSBjKGZhcm1fYWJfY2kkYWJfcHJldmVudGlvbl9jaV9sb3dlciwgaG91c2Vob2xkX3ByZXZlbnRpdmUkcHJldmVudGl2ZV9jaV9sb3dlciksCiAgQ0lfVXBwZXIgPSBjKGZhcm1fYWJfY2kkYWJfcHJldmVudGlvbl9jaV91cHBlciwgaG91c2Vob2xkX3ByZXZlbnRpdmUkcHJldmVudGl2ZV9jaV91cHBlcikKKQoKIyBBZGQgZm9ybWF0dGVkIHBlcmNlbnRhZ2UgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCnByZXZlbnRpdmVfY29tcGFyaXNvbiA8LSBwcmV2ZW50aXZlX2NvbXBhcmlzb24gJT4lCiAgbXV0YXRlKAogICAgUGVyY2VudF9DSSA9IHBhc3RlMCgKICAgICAgcm91bmQoUGVyY2VudGFnZSwgMSksICIlICgiLCAKICAgICAgcm91bmQoQ0lfTG93ZXIsIDEpLCAiLSIsIAogICAgICByb3VuZChDSV9VcHBlciwgMSksICIlKSIKICAgICkKICApCgojIERpc3BsYXkgY29tcGFyaXNvbiB0YWJsZQprYWJsZShwcmV2ZW50aXZlX2NvbXBhcmlzb24gJT4lIAogICAgICAgIGRwbHlyOjpzZWxlY3QoQ2F0ZWdvcnksIENvdW50LCBUb3RhbCwgUGVyY2VudF9DSSksCiAgICAgIGNhcHRpb24gPSAiQ29tcGFyaXNvbiBvZiBQcmV2ZW50aXZlIEFudGliaW90aWMgVXNlIGluIEZhcm1zIGFuZCBIb3VzZWhvbGRzIiwKICAgICAgY29sLm5hbWVzID0gYygiQ2F0ZWdvcnkiLCAiTnVtYmVyIG9mIEFCIFVzZXJzIiwgIlRvdGFsIFNhbXBsZSIsICJVc2FnZSBSYXRlICg5NSUgQ0kpIikpCgojIENyZWF0ZSBhIGNvbnRpbmdlbmN5IHRhYmxlIGZvciBwcmV2ZW50aXZlIHVzZQpwcmV2ZW50aXZlX3RhYmxlIDwtIG1hdHJpeCgKICBjKHByZXZlbnRpdmVfY29tcGFyaXNvbiRDb3VudFsxXSwgcHJldmVudGl2ZV9jb21wYXJpc29uJFRvdGFsWzFdIC0gcHJldmVudGl2ZV9jb21wYXJpc29uJENvdW50WzFdLAogICAgcHJldmVudGl2ZV9jb21wYXJpc29uJENvdW50WzJdLCBwcmV2ZW50aXZlX2NvbXBhcmlzb24kVG90YWxbMl0gLSBwcmV2ZW50aXZlX2NvbXBhcmlzb24kQ291bnRbMl0pLAogIG5yb3cgPSAyLAogIGJ5cm93ID0gVFJVRSwKICBkaW1uYW1lcyA9IGxpc3QoCiAgICBjKCJGYXJtIiwgIkhvdXNlaG9sZCIpLAogICAgYygiUHJldmVudGl2ZSBVc2UiLCAiTm8gUHJldmVudGl2ZSBVc2UiKQogICkKKQoKIyBQZXJmb3JtIGNoaS1zcXVhcmUgdGVzdApwcmV2ZW50aXZlX2NoaSA8LSBjaGlzcS50ZXN0KHByZXZlbnRpdmVfdGFibGUpCgojIENhbGN1bGF0ZSBlZmZlY3Qgc2l6ZSAoUGhpIGNvZWZmaWNpZW50KQpwcmV2ZW50aXZlX3BoaSA8LSBzcXJ0KHByZXZlbnRpdmVfY2hpJHN0YXRpc3RpYyAvIHN1bShwcmV2ZW50aXZlX3RhYmxlKSkKCiMgRGV0ZXJtaW5lIGVmZmVjdCBzaXplIGludGVycHJldGF0aW9uCnByZXZlbnRpdmVfZWZmZWN0IDwtIGNhc2Vfd2hlbigKICBhYnMocHJldmVudGl2ZV9waGkpIDwgMC4xIH4gIk5lZ2xpZ2libGUiLAogIGFicyhwcmV2ZW50aXZlX3BoaSkgPCAwLjMgfiAiU21hbGwiLAogIGFicyhwcmV2ZW50aXZlX3BoaSkgPCAwLjUgfiAiTWVkaXVtIiwKICBUUlVFIH4gIkxhcmdlIgopCgojIENhbGN1bGF0ZSB0aGUgcmF0aW8gb2YgZmFybTpob3VzZWhvbGQgcHJldmVudGl2ZSB1c2UKcHJldmVudGl2ZV9yYXRpbyA8LSBmYXJtX2FiX2NpJGFiX3ByZXZlbnRpb25fcGN0IC8gaG91c2Vob2xkX3ByZXZlbnRpdmUkcHJldmVudGl2ZV9wY3QKCiMgNi4zIE1VTFRJTEVWRUwgQU5BTFlTSVMgT0YgQU5USUJJT1RJQyBVU0UKIyBDaGVjayBpZiB3ZSBoYXZlIGNvbW11bml0eSBpZGVudGlmaWVycwpoYXNfY29tbXVuaXR5X2lkcyA8LSBhbGwoYygiZGlzdHJpY3QiLCAiY29tbXVuZSIpICVpbiUgbmFtZXMoZmFybV9kYXRhKSkgJiYgCiAgICAgICAgICAgICAgICAgICAgIGFsbChjKCJkaXN0cmljdCIsICJjb21tdW5lIikgJWluJSBuYW1lcyhob3VzZWhvbGRfZGF0YSkpCgppZihoYXNfY29tbXVuaXR5X2lkcykgewogICMgQ3JlYXRlIGNvbW11bml0eSBJRCB2YXJpYWJsZQogIGZhcm1fZGF0YSA8LSBmYXJtX2RhdGEgJT4lCiAgICBtdXRhdGUoY29tbXVuaXR5X2lkID0gcGFzdGUoZGlzdHJpY3QsIGNvbW11bmUsIHNlcCA9ICJfIikpCiAgCiAgaG91c2Vob2xkX2RhdGEgPC0gaG91c2Vob2xkX2RhdGEgJT4lCiAgICBtdXRhdGUoY29tbXVuaXR5X2lkID0gcGFzdGUoZGlzdHJpY3QsIGNvbW11bmUsIHNlcCA9ICJfIikpCiAgCiAgIyBMb2FkIHJlcXVpcmVkIHBhY2thZ2VzCiAgaWYoIXJlcXVpcmUobG1lNCkpIGluc3RhbGwucGFja2FnZXMoImxtZTQiKQogIGxpYnJhcnkobG1lNCkKICBpZighcmVxdWlyZShwZXJmb3JtYW5jZSkpIGluc3RhbGwucGFja2FnZXMoInBlcmZvcm1hbmNlIikKICBsaWJyYXJ5KHBlcmZvcm1hbmNlKQogIAogIGNhdCgiXG5NdWx0aWxldmVsIEFuYWx5c2lzIG9mIEFudGliaW90aWMgVXNlOlxuIikKICAKICAjIENoZWNrIGZvciBzdWZmaWNpZW50IGNvbW11bml0aWVzCiAgZmFybV9jb21tdW5pdGllcyA8LSB1bmlxdWUoZmFybV9kYXRhJGNvbW11bml0eV9pZCkKICBob3VzZWhvbGRfY29tbXVuaXRpZXMgPC0gdW5pcXVlKGhvdXNlaG9sZF9kYXRhJGNvbW11bml0eV9pZCkKICAKICBjYXQoIk51bWJlciBvZiBjb21tdW5pdGllcyBpbiBmYXJtIGRhdGE6IiwgbGVuZ3RoKGZhcm1fY29tbXVuaXRpZXMpLCAiXG4iKQogIGNhdCgiTnVtYmVyIG9mIGNvbW11bml0aWVzIGluIGhvdXNlaG9sZCBkYXRhOiIsIGxlbmd0aChob3VzZWhvbGRfY29tbXVuaXRpZXMpLCAiXG4iKQogIAogICMgUHJvY2VlZCB3aXRoIG11bHRpbGV2ZWwgbW9kZWxpbmcgaWYgd2UgaGF2ZSBzdWZmaWNpZW50IGNvbW11bml0aWVzIChhdCBsZWFzdCAxMCkKICBpZihsZW5ndGgoZmFybV9jb21tdW5pdGllcykgPj0gMTApIHsKICAgICMgRmFybSBtdWx0aWxldmVsIG1vZGVsIGZvciBhbnkgYW50aWJpb3RpYyB1c2UKICAgIHRyeUNhdGNoKHsKICAgICAgZmFybV9tbG0gPC0gZ2xtZXIoYW55X2FiX3VzZSB+IDEgKyAoMXxjb21tdW5pdHlfaWQpLCAKICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGJpbm9taWFsLCBkYXRhID0gZmFybV9kYXRhKQogICAgICAKICAgICAgZmFybV9pY2MgPC0gcGVyZm9ybWFuY2U6OmljYyhmYXJtX21sbSkKICAgICAgY2F0KCJcbkZhcm0gYW50aWJpb3RpYyB1c2UgLSBJbnRyYWNsYXNzIENvcnJlbGF0aW9uIENvZWZmaWNpZW50OiIsIAogICAgICAgICAgcm91bmQoZmFybV9pY2MsIDMpLCAiXG4iKQogICAgICBjYXQoIlRoaXMgbWVhbnMgYXBwcm94aW1hdGVseSIsIHJvdW5kKGZhcm1faWNjKjEwMCwgMSksIAogICAgICAgICAgIiUgb2YgdGhlIHZhcmlhbmNlIGluIGZhcm0gYW50aWJpb3RpYyB1c2UgaXMgYXR0cmlidXRhYmxlIHRvIGNvbW11bml0eS1sZXZlbCBmYWN0b3JzLlxuIikKICAgICAgCiAgICAgICMgRmFybSBtdWx0aWxldmVsIG1vZGVsIGZvciBwcmV2ZW50aXZlIHVzZQogICAgICBmYXJtX3ByZXZfbWxtIDwtIGdsbWVyKGFiX3ByZXZlbnRpb24gfiAxICsgKDF8Y29tbXVuaXR5X2lkKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGJpbm9taWFsLCBkYXRhID0gZmFybV9kYXRhKQogICAgICAKICAgICAgZmFybV9wcmV2X2ljYyA8LSBwZXJmb3JtYW5jZTo6aWNjKGZhcm1fcHJldl9tbG0pCiAgICAgIGNhdCgiXG5GYXJtIHByZXZlbnRpdmUgdXNlIC0gSW50cmFjbGFzcyBDb3JyZWxhdGlvbiBDb2VmZmljaWVudDoiLCAKICAgICAgICAgIHJvdW5kKGZhcm1fcHJldl9pY2MsIDMpLCAiXG4iKQogICAgICBjYXQoIlRoaXMgbWVhbnMgYXBwcm94aW1hdGVseSIsIHJvdW5kKGZhcm1fcHJldl9pY2MqMTAwLCAxKSwgCiAgICAgICAgICAiJSBvZiB0aGUgdmFyaWFuY2UgaW4gZmFybSBwcmV2ZW50aXZlIHVzZSBpcyBhdHRyaWJ1dGFibGUgdG8gY29tbXVuaXR5LWxldmVsIGZhY3RvcnMuXG4iKQogICAgfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7CiAgICAgIGNhdCgiQ291bGQgbm90IGZpdCBtdWx0aWxldmVsIG1vZGVsIGZvciBmYXJtIGRhdGE6IiwgZSRtZXNzYWdlLCAiXG4iKQogICAgfSkKICB9IGVsc2UgewogICAgY2F0KCJJbnN1ZmZpY2llbnQgbnVtYmVyIG9mIGNvbW11bml0aWVzIGZvciBmYXJtIG11bHRpbGV2ZWwgbW9kZWxpbmcuXG4iKQogIH0KICAKICAjIFByb2NlZWQgd2l0aCBob3VzZWhvbGQgbXVsdGlsZXZlbCBtb2RlbGluZyBpZiB3ZSBoYXZlIHN1ZmZpY2llbnQgY29tbXVuaXRpZXMKICBpZihsZW5ndGgoaG91c2Vob2xkX2NvbW11bml0aWVzKSA+PSAxMCkgewogICAgIyBIb3VzZWhvbGQgbXVsdGlsZXZlbCBtb2RlbAogICAgdHJ5Q2F0Y2goewogICAgICBob3VzZWhvbGRfbWxtIDwtIGdsbWVyKGFueV9hYl9sYXN0X2lsbG5lc3MgfiAxICsgKDF8Y29tbXVuaXR5X2lkKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseSA9IGJpbm9taWFsLCBkYXRhID0gaG91c2Vob2xkX2RhdGEpCiAgICAgIAogICAgICBob3VzZWhvbGRfaWNjIDwtIHBlcmZvcm1hbmNlOjppY2MoaG91c2Vob2xkX21sbSkKICAgICAgY2F0KCJcbkhvdXNlaG9sZCBhbnRpYmlvdGljIHVzZSAtIEludHJhY2xhc3MgQ29ycmVsYXRpb24gQ29lZmZpY2llbnQ6IiwgCiAgICAgICAgICByb3VuZChob3VzZWhvbGRfaWNjLCAzKSwgIlxuIikKICAgICAgY2F0KCJUaGlzIG1lYW5zIGFwcHJveGltYXRlbHkiLCByb3VuZChob3VzZWhvbGRfaWNjKjEwMCwgMSksIAogICAgICAgICAgIiUgb2YgdGhlIHZhcmlhbmNlIGluIGhvdXNlaG9sZCBhbnRpYmlvdGljIHVzZSBpcyBhdHRyaWJ1dGFibGUgdG8gY29tbXVuaXR5LWxldmVsIGZhY3RvcnMuXG4iKQogICAgICAKICAgICAgIyBJZiB3ZSB1c2VkIHRoZSBzYW1lIGNvbW11bml0aWVzLCBjYWxjdWxhdGUgY29ycmVsYXRpb24gYmV0d2VlbiBjb21tdW5pdHkgZWZmZWN0cwogICAgICBzaGFyZWRfY29tbXVuaXRpZXMgPC0gaW50ZXJzZWN0KGZhcm1fY29tbXVuaXRpZXMsIGhvdXNlaG9sZF9jb21tdW5pdGllcykKICAgICAgCiAgICAgIGlmKGxlbmd0aChzaGFyZWRfY29tbXVuaXRpZXMpID49IDUpIHsKICAgICAgICBjYXQoIlxuQW5hbHl6aW5nIGNvcnJlbGF0aW9uIGJldHdlZW4gY29tbXVuaXR5IGVmZmVjdHMgaW4gZmFybSBhbmQgaG91c2Vob2xkIGFudGliaW90aWMgdXNlOlxuIikKICAgICAgICAKICAgICAgICAjIEV4dHJhY3QgcmFuZG9tIGVmZmVjdHMKICAgICAgICBmYXJtX3JhbmVmIDwtIHJhbmVmKGZhcm1fbWxtKSRjb21tdW5pdHlfaWQKICAgICAgICBob3VzZWhvbGRfcmFuZWYgPC0gcmFuZWYoaG91c2Vob2xkX21sbSkkY29tbXVuaXR5X2lkCiAgICAgICAgCiAgICAgICAgIyBQcmVwYXJlIGRhdGEKICAgICAgICByYW5lZl9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgICAgICAgICBjb21tdW5pdHlfaWQgPSByb3duYW1lcyhmYXJtX3JhbmVmKSwKICAgICAgICAgIGZhcm1fZWZmZWN0ID0gZmFybV9yYW5lZlssMV0sCiAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UKICAgICAgICApCiAgICAgICAgCiAgICAgICAgaG91c2Vob2xkX2VmZmVjdHMgPC0gZGF0YS5mcmFtZSgKICAgICAgICAgIGNvbW11bml0eV9pZCA9IHJvd25hbWVzKGhvdXNlaG9sZF9yYW5lZiksCiAgICAgICAgICBob3VzZWhvbGRfZWZmZWN0ID0gaG91c2Vob2xkX3JhbmVmWywxXSwKICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQogICAgICAgICkKICAgICAgICAKICAgICAgICByYW5lZl9kYXRhIDwtIHJhbmVmX2RhdGEgJT4lCiAgICAgICAgICBpbm5lcl9qb2luKGhvdXNlaG9sZF9lZmZlY3RzLCBieSA9ICJjb21tdW5pdHlfaWQiKQogICAgICAgIAogICAgICAgICMgQ2FsY3VsYXRlIGNvcnJlbGF0aW9uCiAgICAgICAgY29tbXVuaXR5X2NvciA8LSBjb3IudGVzdChyYW5lZl9kYXRhJGZhcm1fZWZmZWN0LCByYW5lZl9kYXRhJGhvdXNlaG9sZF9lZmZlY3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJzcGVhcm1hbiIpCiAgICAgICAgCiAgICAgICAgY2F0KCJDb3JyZWxhdGlvbiBiZXR3ZWVuIGNvbW11bml0eSBlZmZlY3RzOiIsIHJvdW5kKGNvbW11bml0eV9jb3IkZXN0aW1hdGUsIDMpLCAKICAgICAgICAgICAgIihwID0iLCByb3VuZChjb21tdW5pdHlfY29yJHAudmFsdWUsIDMpLCAiKVxuIikKICAgICAgICAKICAgICAgICBpZihjb21tdW5pdHlfY29yJHAudmFsdWUgPCAwLjA1KSB7CiAgICAgICAgICBjYXQoIlRoaXMgc3VnZ2VzdHMgc2lnbmlmaWNhbnQgY29tbXVuaXR5LWxldmVsIGNvcnJlbGF0aW9uIGJldHdlZW4gZmFybSBhbmQgaG91c2Vob2xkIGFudGliaW90aWMgdXNlIHBhdHRlcm5zLlxuIikKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY2F0KCJObyBzaWduaWZpY2FudCBjb21tdW5pdHktbGV2ZWwgY29ycmVsYXRpb24gZGV0ZWN0ZWQgYmV0d2VlbiBmYXJtIGFuZCBob3VzZWhvbGQgYW50aWJpb3RpYyB1c2UgcGF0dGVybnMuXG4iKQogICAgICAgIH0KICAgICAgfQogICAgfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7CiAgICAgIGNhdCgiQ291bGQgbm90IGZpdCBtdWx0aWxldmVsIG1vZGVsIGZvciBob3VzZWhvbGQgZGF0YToiLCBlJG1lc3NhZ2UsICJcbiIpCiAgICB9KQogIH0gZWxzZSB7CiAgICBjYXQoIkluc3VmZmljaWVudCBudW1iZXIgb2YgY29tbXVuaXRpZXMgZm9yIGhvdXNlaG9sZCBtdWx0aWxldmVsIG1vZGVsaW5nLlxuIikKICB9Cn0gZWxzZSB7CiAgY2F0KCJcbkNvbW11bml0eSBpZGVudGlmaWVycyBub3QgYXZhaWxhYmxlIC0gbXVsdGlsZXZlbCBhbmFseXNpcyBza2lwcGVkLlxuIikKfQoKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyA3LiBBTlRJQklPVElDIFRZUEVTIENPTVBBUkFUSVZFIEFOQUxZU0lTCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyA3LjEgRXh0cmFjdCBhbnRpYmlvdGljIHR5cGUgZGF0YSBmcm9tIGJvdGggZGF0YXNldHMKIyBGYXJtIGFudGliaW90aWMgdHlwZXMgLSBDT1JSRUNURUQgdG8gcHJvcGVybHkgaGFuZGxlIGJpbmFyeSB2YXJpYWJsZXMgKDAvMSkKZmFybV9hYl90eXBlcyA8LSBmYXJtX2RhdGEgJT4lCiAgc3VtbWFyaXNlKAogICAgbiA9IG4oKSwKICAgICMgUHJvcGVybHkgY2FsY3VsYXRlIHBlcmNlbnRhZ2UgdXNpbmcgYmluYXJ5IGluZGljYXRvcnMgKD09IDEpCiAgICAjIFRoZXNlIHZhcmlhYmxlcyBhcmUgYmluYXJ5IHdoZXJlIDEgPSBZZXMgKHVzZWQgdGhpcyBhbnRpYmlvdGljKSwgMCA9IE5vCiAgICBjaGxvcmFtcGhlbmljb2wgPSBtZWFuKGNobG8gPT0gMSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIG5pdHJvZnVyYW5zID0gbWVhbihuaXRyID09IDEsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBkaW1ldHJpZGF6b2xlID0gbWVhbihkaW1lID09IDEsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBtZXRyb25pZGF6b2xlID0gbWVhbihtZXRyID09IDEsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBjaXByb2Zsb3hhY2luID0gbWVhbihjaXByID09IDEsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBvZmxveGFjaW4gPSBtZWFuKG9mbG8gPT0gMSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIGNhcmJhZG94ID0gbWVhbihjYXJiID09IDEsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBvbGFxdWluZG94ID0gbWVhbihvbGFxID09IDEsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBiYWNpdHJhY2luID0gbWVhbihiYWNpID09IDEsIG5hLnJtID0gVFJVRSkgKiAxMDAKICApCgojIEhvdXNlaG9sZCBhbnRpYmlvdGljIHR5cGVzIC0gY2hlY2sgYW5kIGFkYXB0IHRvIGFjdHVhbCB2YXJpYWJsZSBuYW1lcwpob3VzZWhvbGRfYWJfY29scyA8LSBncmVwKCJebnVtX3E3XzExX19fXFxkKyQiLCBuYW1lcyhob3VzZWhvbGRfZGF0YSksIHZhbHVlID0gVFJVRSkKCmlmKGxlbmd0aChob3VzZWhvbGRfYWJfY29scykgPiAwKSB7CiAgaG91c2Vob2xkX2FiX3R5cGVzIDwtIGhvdXNlaG9sZF9kYXRhICU+JQogICAgc3VtbWFyaXNlKGFjcm9zcyhhbGxfb2YoaG91c2Vob2xkX2FiX2NvbHMpLCB+bWVhbiguID09IDEsIG5hLnJtID0gVFJVRSkgKiAxMDApKSAlPiUKICAgIG11dGF0ZShuID0gbnJvdyhob3VzZWhvbGRfZGF0YSkpCiAgCiAgIyBNYXAgdmFyaWFibGUgbmFtZXMgdG8gYW50aWJpb3RpYyB0eXBlcyAtIGFkanVzdCBtYXBwaW5nIGFzIG5lZWRlZAogIGhvdXNlaG9sZF9hYl9tYXAgPC0gZGF0YS5mcmFtZSgKICAgIHZhcmlhYmxlID0gaG91c2Vob2xkX2FiX2NvbHMsCiAgICBhbnRpYmlvdGljID0gY2FzZV93aGVuKAogICAgICBncmVwbCgiMSQiLCBob3VzZWhvbGRfYWJfY29scykgfiAiYW1veGljaWxsaW4iLAogICAgICBncmVwbCgiMiQiLCBob3VzZWhvbGRfYWJfY29scykgfiAiYW1waWNpbGxpbiIsCiAgICAgIGdyZXBsKCIzJCIsIGhvdXNlaG9sZF9hYl9jb2xzKSB+ICJhbW94aWNpbGxpbl9jbGF2dWxhbmljIiwKICAgICAgZ3JlcGwoIjQkIiwgaG91c2Vob2xkX2FiX2NvbHMpIH4gImF6aXRocm9teWNpbiIsCiAgICAgIGdyZXBsKCI1JCIsIGhvdXNlaG9sZF9hYl9jb2xzKSB+ICJjZWZhbGV4aW4iLAogICAgICBncmVwbCgiNiQiLCBob3VzZWhvbGRfYWJfY29scykgfiAiY2VmaXhpbWUiLAogICAgICBncmVwbCgiNyQiLCBob3VzZWhvbGRfYWJfY29scykgfiAiY2VmdXJveGltZSIsCiAgICAgIGdyZXBsKCI4JCIsIGhvdXNlaG9sZF9hYl9jb2xzKSB+ICJxdWlub2xvbmVzIiwKICAgICAgZ3JlcGwoIjkkIiwgaG91c2Vob2xkX2FiX2NvbHMpIH4gImNvdHJpbW94YXpvbGUiLAogICAgICBncmVwbCgiMTAkIiwgaG91c2Vob2xkX2FiX2NvbHMpIH4gIm1ldHJvbmlkYXpvbGUiLAogICAgICBncmVwbCgiMTEkIiwgaG91c2Vob2xkX2FiX2NvbHMpIH4gInBlbmljaWxsaW4iLAogICAgICBUUlVFIH4gIm90aGVyIgogICAgKSwKICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQogICkKICAKICAjIFRyYW5zZm9ybSB0byBsb25nIGZvcm1hdAogIGhvdXNlaG9sZF9hYl9sb25nIDwtIGhvdXNlaG9sZF9hYl90eXBlcyAlPiUKICAgIGRwbHlyOjpzZWxlY3QoLW4pICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBldmVyeXRoaW5nKCksIG5hbWVzX3RvID0gInZhcmlhYmxlIiwgdmFsdWVzX3RvID0gInBlcmNlbnRhZ2UiKSAlPiUKICAgIGxlZnRfam9pbihob3VzZWhvbGRfYWJfbWFwLCBieSA9ICJ2YXJpYWJsZSIpICU+JQogICAgZ3JvdXBfYnkoYW50aWJpb3RpYykgJT4lCiAgICBzdW1tYXJpc2UocGVyY2VudGFnZSA9IHN1bShwZXJjZW50YWdlKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lICAjIFN1bSBieSBhbnRpYmlvdGljIHR5cGUKICAgIGZpbHRlcighaXMubmEoYW50aWJpb3RpYykpICU+JQogICAgbXV0YXRlKHNlY3RvciA9ICJIb3VzZWhvbGQiKQogIAogICMgRmFybSBhbnRpYmlvdGljIHR5cGVzIC0gbG9uZyBmb3JtYXQKICBmYXJtX2FiX2xvbmcgPC0gZmFybV9hYl90eXBlcyAlPiUKICAgIGRwbHlyOjpzZWxlY3QoLW4pICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBldmVyeXRoaW5nKCksIG5hbWVzX3RvID0gImFudGliaW90aWMiLCB2YWx1ZXNfdG8gPSAicGVyY2VudGFnZSIpICU+JQogICAgbXV0YXRlKHNlY3RvciA9ICJGYXJtIikKICAKICAjIENsYXNzaWZ5IGFudGliaW90aWNzIGludG8gYnJvYWRlciBjbGFzc2VzCiAgaG91c2Vob2xkX2FiX2NsYXNzZXMgPC0gZGF0YS5mcmFtZSgKICAgIGFudGliaW90aWMgPSBjKCJhbW94aWNpbGxpbiIsICJhbXBpY2lsbGluIiwgImFtb3hpY2lsbGluX2NsYXZ1bGFuaWMiLCAicGVuaWNpbGxpbiIsIAogICAgICAgICAgICAgICAgICAgImF6aXRocm9teWNpbiIsICJjZWZhbGV4aW4iLCAiY2VmaXhpbWUiLCAiY2VmdXJveGltZSIsIAogICAgICAgICAgICAgICAgICAgInF1aW5vbG9uZXMiLCAiY290cmltb3hhem9sZSIsICJtZXRyb25pZGF6b2xlIiksCiAgICBjbGFzcyA9IGMoIlBlbmljaWxsaW5zIiwgIlBlbmljaWxsaW5zIiwgIlBlbmljaWxsaW5zIiwgIlBlbmljaWxsaW5zIiwKICAgICAgICAgICAgICAiTWFjcm9saWRlcyIsICJDZXBoYWxvc3BvcmlucyIsICJDZXBoYWxvc3BvcmlucyIsICJDZXBoYWxvc3BvcmlucyIsCiAgICAgICAgICAgICAgIlF1aW5vbG9uZXMiLCAiU3VsZm9uYW1pZGVzIiwgIk5pdHJvaW1pZGF6b2xlcyIpLAogICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCiAgKQoKICBmYXJtX2FiX2NsYXNzZXMgPC0gZGF0YS5mcmFtZSgKICAgIGFudGliaW90aWMgPSBjKCJjaGxvcmFtcGhlbmljb2wiLCAibml0cm9mdXJhbnMiLCAiZGltZXRyaWRhem9sZSIsICJtZXRyb25pZGF6b2xlIiwgCiAgICAgICAgICAgICAgICAgICAiY2lwcm9mbG94YWNpbiIsICJvZmxveGFjaW4iLCAiY2FyYmFkb3giLCAib2xhcXVpbmRveCIsICJiYWNpdHJhY2luIiksCiAgICBjbGFzcyA9IGMoIkFtcGhlbmljb2xzIiwgIk5pdHJvZnVyYW5zIiwgIk5pdHJvaW1pZGF6b2xlcyIsICJOaXRyb2ltaWRhem9sZXMiLCAKICAgICAgICAgICAgICAiUXVpbm9sb25lcyIsICJRdWlub2xvbmVzIiwgIk90aGVycyIsICJPdGhlcnMiLCAiUG9seXBlcHRpZGVzIiksCiAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UKICApCgogICMgR3JvdXAgYnkgYW50aWJpb3RpYyBjbGFzcyB3aXRoIENPUlJFQ1RFRCBtZXRob2QgdG8gYXZvaWQgZG91YmxlLWNvdW50aW5nCiAgIyBUaGlzIGVuc3VyZXMgcHJvcGVyIGhhbmRsaW5nIG9mIG11bHRpcGxlIGFudGliaW90aWNzIHdpdGhpbiB0aGUgc2FtZSBjbGFzcwogIGhvdXNlaG9sZF9jbGFzc191c2FnZSA8LSBob3VzZWhvbGRfYWJfbG9uZyAlPiUKICAgIGxlZnRfam9pbihob3VzZWhvbGRfYWJfY2xhc3NlcywgYnkgPSAiYW50aWJpb3RpYyIpICU+JQogICAgZmlsdGVyKCFpcy5uYShjbGFzcykpICU+JQogICAgZ3JvdXBfYnkoY2xhc3MpICU+JQogICAgIyBGb3IgaG91c2Vob2xkIGRhdGEsIHdlJ2xsIGFzc3VtZSBwZXJjZW50YWdlIGNhbGN1bGF0aW9uIHdhcyBjb3JyZWN0CiAgICBzdW1tYXJpc2UocGVyY2VudGFnZSA9IHN1bShwZXJjZW50YWdlKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgICBtdXRhdGUoc2VjdG9yID0gIkhvdXNlaG9sZCIpCgogICMgRm9yIGZhcm0gZGF0YSwgd2UnbGwgdXNlIGEgZGlmZmVyZW50IGFwcHJvYWNoIHRvIGF2b2lkIGRvdWJsZS1jb3VudGluZwogICMgVGhpcyBpcyBlc3BlY2lhbGx5IGltcG9ydGFudCBmb3IgY2xhc3NlcyB3aXRoIG11bHRpcGxlIGFudGliaW90aWNzCiAgZmFybV9jbGFzc191c2FnZSA8LSBmYXJtX2RhdGEgJT4lCiAgICAjIENyZWF0ZSBjbGFzcyBpbmRpY2F0b3JzIC0gYSBmYXJtIHVzZXMgYSBjbGFzcyBpZiBpdCB1c2VzIGFueSBhbnRpYmlvdGljIGluIHRoYXQgY2xhc3MKICAgIG11dGF0ZSgKICAgICAgQW1waGVuaWNvbHMgPSBhcy5pbnRlZ2VyKGNobG8gPT0gMSksCiAgICAgIE5pdHJvZnVyYW5zID0gYXMuaW50ZWdlcihuaXRyID09IDEpLAogICAgICBOaXRyb2ltaWRhem9sZXMgPSBhcy5pbnRlZ2VyKGRpbWUgPT0gMSB8IG1ldHIgPT0gMSksICAjIEVpdGhlciBhbnRpYmlvdGljIGNvdW50cwogICAgICBRdWlub2xvbmVzID0gYXMuaW50ZWdlcihjaXByID09IDEgfCBvZmxvID09IDEpLCAgICAgICAjIEVpdGhlciBhbnRpYmlvdGljIGNvdW50cwogICAgICBPdGhlcnMgPSBhcy5pbnRlZ2VyKGNhcmIgPT0gMSB8IG9sYXEgPT0gMSksICAgICAgICAgICAjIEVpdGhlciBhbnRpYmlvdGljIGNvdW50cwogICAgICBQb2x5cGVwdGlkZXMgPSBhcy5pbnRlZ2VyKGJhY2kgPT0gMSkKICAgICkgJT4lCiAgICAjIENhbGN1bGF0ZSBwZXJjZW50YWdlIGZvciBlYWNoIGNsYXNzCiAgICBzdW1tYXJpc2UoYWNyb3NzKGMoQW1waGVuaWNvbHMsIE5pdHJvZnVyYW5zLCBOaXRyb2ltaWRhem9sZXMsIAogICAgICAgICAgICAgICAgICAgICAgUXVpbm9sb25lcywgT3RoZXJzLCBQb2x5cGVwdGlkZXMpLCAKICAgICAgICAgICAgICAgICAgICB+bWVhbiguLCBuYS5ybSA9IFRSVUUpICogMTAwKSkgJT4lCiAgICAjIENvbnZlcnQgdG8gbG9uZyBmb3JtYXQKICAgIHBpdm90X2xvbmdlcihjb2xzID0gZXZlcnl0aGluZygpLCBuYW1lc190byA9ICJjbGFzcyIsIHZhbHVlc190byA9ICJwZXJjZW50YWdlIikgJT4lCiAgICBtdXRhdGUoc2VjdG9yID0gIkZhcm0iKQoKICAjIENvbWJpbmUgZGF0YXNldHMgZm9yIGNvbXBhcmlzb24KICBhYl9jbGFzc19jb21wYXJpc29uIDwtIGJpbmRfcm93cyhob3VzZWhvbGRfY2xhc3NfdXNhZ2UsIGZhcm1fY2xhc3NfdXNhZ2UpCgogICMgUHJpbnQgY29ycmVjdGVkIGRhdGEgdG8gdmVyaWZ5CiAgcHJpbnQoIkNvcnJlY3RlZCBhbnRpYmlvdGljIGNsYXNzIGNvbXBhcmlzb24gZGF0YToiKQogIHByaW50KGFiX2NsYXNzX2NvbXBhcmlzb24pCgogICMgRmluZCBzaGFyZWQgYW50aWJpb3RpYyBjbGFzc2VzCiAgc2hhcmVkX2NsYXNzZXMgPC0gaW50ZXJzZWN0KGhvdXNlaG9sZF9jbGFzc191c2FnZSRjbGFzcywgZmFybV9jbGFzc191c2FnZSRjbGFzcykKICBzaGFyZWRfY2xhc3NfY29tcGFyaXNvbiA8LSBhYl9jbGFzc19jb21wYXJpc29uICU+JQogICAgZmlsdGVyKGNsYXNzICVpbiUgc2hhcmVkX2NsYXNzZXMpCgogICMgQ2FsY3VsYXRlIGNvcnJlbGF0aW9uIGZvciBzaGFyZWQgY2xhc3NlcyBpZiBzdWZmaWNpZW50IGRhdGEKICBpZihsZW5ndGgoc2hhcmVkX2NsYXNzZXMpID49IDMpIHsKICAgIGNvcnJlbGF0aW9uX2RhdGEgPC0gc2hhcmVkX2NsYXNzX2NvbXBhcmlzb24gJT4lCiAgICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzZWN0b3IsIHZhbHVlc19mcm9tID0gcGVyY2VudGFnZSkKCiAgICBjbGFzc19jb3JyZWxhdGlvbiA8LSBjb3IudGVzdChjb3JyZWxhdGlvbl9kYXRhJEhvdXNlaG9sZCwgY29ycmVsYXRpb25fZGF0YSRGYXJtLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInNwZWFybWFuIikKICAgIAogICAgcHJpbnQoIkNvcnJlbGF0aW9uIGJldHdlZW4gZmFybSBhbmQgaG91c2Vob2xkIGFudGliaW90aWMgY2xhc3MgdXNhZ2U6IikKICAgIHByaW50KGNsYXNzX2NvcnJlbGF0aW9uKQogIH0KCgoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIDguIFZJU1VBTElaQVRJT05TCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyA4LjEgUHJlcGFyZSB2aXN1YWxpemF0aW9uIGRhdGEKCiMgRmFybSBhbnRpYmlvdGljIHVzZSBwdXJwb3NlcyBkYXRhCmZhcm1fcHVycG9zZXMgPC0gZGF0YS5mcmFtZSgKICBwdXJwb3NlID0gYygiVHJlYXRtZW50IiwgIlByZXZlbnRpb24iLCAiR3Jvd3RoIFByb21vdGlvbiIpLAogIHBlcmNlbnRhZ2UgPSBjKAogICAgZmFybV9hYl9jaSRhYl90cmVhdG1lbnRfcGN0LAogICAgZmFybV9hYl9jaSRhYl9wcmV2ZW50aW9uX3BjdCwKICAgIGZhcm1fYWJfY2kkYWJfZ3Jvd3RoX3BjdAogICkKKSAlPiUKICBtdXRhdGUocHVycG9zZSA9IGZhY3RvcihwdXJwb3NlLCBsZXZlbHMgPSBjKCJUcmVhdG1lbnQiLCAiUHJldmVudGlvbiIsICJHcm93dGggUHJvbW90aW9uIikpKQoKIyBDb21wYXJpc29uIGRhdGEgZm9yIGZhcm0gdnMgaG91c2Vob2xkIG92ZXJhbGwgYW50aWJpb3RpYyB1c2UKY29tcGFyaXNvbl9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgc2VjdG9yID0gYygiRmFybSIsICJIb3VzZWhvbGQiKSwKICBwcmV2YWxlbmNlID0gYyhmYXJtX2FiX2NpJGFiX3VzZV9wY3QsIGhvdXNlaG9sZF9hYl9jaSRhYl91c2VfcGN0KSwKICBjaV9sb3dlciA9IGMoZmFybV9hYl9jaSRhYl91c2VfY2lfbG93ZXIsIGhvdXNlaG9sZF9hYl9jaSRhYl91c2VfY2lfbG93ZXIpLAogIGNpX3VwcGVyID0gYyhmYXJtX2FiX2NpJGFiX3VzZV9jaV91cHBlciwgaG91c2Vob2xkX2FiX2NpJGFiX3VzZV9jaV91cHBlcikKKQoKIyBQcmV2ZW50aXZlIHVzZSBjb21wYXJpc29uIGRhdGEKcHJldmVudGl2ZV9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgQ2F0ZWdvcnkgPSBjKCJGYXJtIFByZXZlbnRpdmUgVXNlIiwgIkhvdXNlaG9sZCBQcmV2ZW50aXZlIFVzZSAoUHJveHkpIiksCiAgVXNhZ2UgPSBjKGZhcm1fYWJfY2kkYWJfcHJldmVudGlvbl9wY3QsIGhvdXNlaG9sZF9wcmV2ZW50aXZlJHByZXZlbnRpdmVfcGN0KSwKICBMb3dlciA9IGMoZmFybV9hYl9jaSRhYl9wcmV2ZW50aW9uX2NpX2xvd2VyLCBob3VzZWhvbGRfcHJldmVudGl2ZSRwcmV2ZW50aXZlX2NpX2xvd2VyKSwKICBVcHBlciA9IGMoZmFybV9hYl9jaSRhYl9wcmV2ZW50aW9uX2NpX3VwcGVyLCBob3VzZWhvbGRfcHJldmVudGl2ZSRwcmV2ZW50aXZlX2NpX3VwcGVyKQopCgojIE5vbi10cmVhdG1lbnQgYW50aWJpb3RpYyB1c2UgZGF0YQpub25fdHJlYXRtZW50X2RhdGEgPC0gZGF0YS5mcmFtZSgKICBwdXJwb3NlID0gYygiQW55IE5vbi1UcmVhdG1lbnQiLCAiUHJldmVudGlvbiBPbmx5IiwgIkdyb3d0aCBQcm9tb3Rpb24gT25seSIsICJCb3RoIFB1cnBvc2VzIiksCiAgcGVyY2VudGFnZSA9IGMoCiAgICBmYXJtX25vbl90cmVhdG1lbnQkYW55X25vbl90cmVhdG1lbnRfcGN0LAogICAgZmFybV9ub25fdHJlYXRtZW50JHByZXZlbnRpb25fb25seV9wY3QsCiAgICBmYXJtX25vbl90cmVhdG1lbnQkZ3Jvd3RoX29ubHlfcGN0LAogICAgZmFybV9ub25fdHJlYXRtZW50JGJvdGhfcHVycG9zZXNfcGN0CiAgKSwKICBjaV9sb3dlciA9IGMoCiAgICBmYXJtX25vbl90cmVhdG1lbnQkYW55X25vbl90cmVhdG1lbnRfY2lfbG93ZXIsCiAgICBmYXJtX25vbl90cmVhdG1lbnQkcHJldmVudGlvbl9vbmx5X2NpX2xvd2VyLAogICAgZmFybV9ub25fdHJlYXRtZW50JGdyb3d0aF9vbmx5X2NpX2xvd2VyLAogICAgZmFybV9ub25fdHJlYXRtZW50JGJvdGhfcHVycG9zZXNfY2lfbG93ZXIKICApLAogIGNpX3VwcGVyID0gYygKICAgIGZhcm1fbm9uX3RyZWF0bWVudCRhbnlfbm9uX3RyZWF0bWVudF9jaV91cHBlciwKICAgIGZhcm1fbm9uX3RyZWF0bWVudCRwcmV2ZW50aW9uX29ubHlfY2lfdXBwZXIsCiAgICBmYXJtX25vbl90cmVhdG1lbnQkZ3Jvd3RoX29ubHlfY2lfdXBwZXIsCiAgICBmYXJtX25vbl90cmVhdG1lbnQkYm90aF9wdXJwb3Nlc19jaV91cHBlcgogICkKKSAlPiUKICBhcnJhbmdlKGRlc2MocGVyY2VudGFnZSkpCgojIDguMiBDcmVhdGUgaW5kaXZpZHVhbCB2aXN1YWxpemF0aW9ucwoKIyAxLiBPdmVyYWxsIGFudGliaW90aWMgdXNlIHByZXZhbGVuY2UgY29tcGFyaXNvbgpvdmVyYWxsX2NvbXBhcmlzb25fcGxvdCA8LSBnZ3Bsb3QoY29tcGFyaXNvbl9kYXRhLCBhZXMoeCA9IHNlY3RvciwgeSA9IHByZXZhbGVuY2UsIGZpbGwgPSBzZWN0b3IpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC42LCBjb2xvciA9ICJncmF5MzAiLCBsaW5ld2lkdGggPSAwLjIpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gY2lfbG93ZXIsIHltYXggPSBjaV91cHBlciksIHdpZHRoID0gMC4yLCBjb2xvciA9ICJncmF5MzAiLCBsaW5ld2lkdGggPSAwLjUpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHJvdW5kKHByZXZhbGVuY2UsIDEpLCAiJSIpKSwgCiAgICAgICAgICAgIHZqdXN0ID0gLTAuOCwgc2l6ZSA9IDMuMiwgY29sb3IgPSAiZ3JheTMwIikgKwogIGxhYnModGl0bGUgPSAiT3ZlcmFsbCBBbnRpYmlvdGljIFVzZSBQcmV2YWxlbmNlIiwKICAgICAgIHN1YnRpdGxlID0gcGFzdGUwKCJDaGktc3F1YXJlIHRlc3Q6IM+HwrIgPSAiLCByb3VuZChvdmVyYWxsX2NoaSRzdGF0aXN0aWMsIDEpLCAKICAgICAgICAgICAgICAgICAgICAgICAgIiwgcCA8IDAuMDAxOyBFZmZlY3Qgc2l6ZTogIiwgcm91bmQob3ZlcmFsbF9waGksIDMpLCAiICgiLCBvdmVyYWxsX2VmZmVjdCwgIikiKSwKICAgICAgIHggPSAiIiwKICAgICAgIHkgPSAiUHJldmFsZW5jZSAoJSkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJGYXJtIiA9ICIjYThjMGUwIiwgIkhvdXNlaG9sZCIgPSAiI2UwYjVhOCIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgbWF4KGNvbXBhcmlzb25fZGF0YSRjaV91cHBlcikgKiAxLjE1KSwgCiAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEwMCwgYnkgPSAyMCksCiAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gYygwLCAwKSkKCnByaW50KG92ZXJhbGxfY29tcGFyaXNvbl9wbG90KQoKCiMgMi4gUHJldmVudGl2ZSBhbnRpYmlvdGljIHVzZSBjb21wYXJpc29uCnByZXZlbnRpdmVfcGxvdCA8LSBnZ3Bsb3QocHJldmVudGl2ZV9kYXRhLCBhZXMoeCA9IENhdGVnb3J5LCB5ID0gVXNhZ2UsIGZpbGwgPSBDYXRlZ29yeSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjYsIGNvbG9yID0gImdyYXkzMCIsIGxpbmV3aWR0aCA9IDAuMikgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBMb3dlciwgeW1heCA9IFVwcGVyKSwgd2lkdGggPSAwLjIsIGNvbG9yID0gImdyYXkzMCIsIGxpbmV3aWR0aCA9IDAuNSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzcHJpbnRmKCIlLjFmJSUiLCBVc2FnZSkpLCAKICAgICAgICAgICAgdmp1c3QgPSAtMC44LCBzaXplID0gMy4yLCBjb2xvciA9ICJncmF5MzAiKSArCiAgbGFicyh0aXRsZSA9ICJQcmV2ZW50aXZlIEFudGliaW90aWMgVXNlIENvbXBhcmlzb24iLAogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoIkZhcm06SG91c2Vob2xkIHJhdGlvID0gIiwgcm91bmQocHJldmVudGl2ZV9yYXRpbywgMSksICI6MSIpLAogICAgICAgeCA9ICIiLAogICAgICAgeSA9ICJQcmV2YWxlbmNlICglKSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gOSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJGYXJtIFByZXZlbnRpdmUgVXNlIiA9ICIjYThjMGUwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSG91c2Vob2xkIFByZXZlbnRpdmUgVXNlIChQcm94eSkiID0gIiNhOGQzYjUiKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIG1heChwcmV2ZW50aXZlX2RhdGEkVXBwZXIpICogMS4xNSksIAogICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDYwLCBieSA9IDEwKSwKICAgICAgICAgICAgICAgICAgIGV4cGFuZCA9IGMoMCwgMCkpIAoKcHJpbnQocHJldmVudGl2ZV9wbG90KQoKCiMgMy4gRmFybSBhbnRpYmlvdGljIHVzZSBwdXJwb3Nlcwp0b3RhbF9wZXJjZW50YWdlIDwtIHN1bShmYXJtX3B1cnBvc2VzJHBlcmNlbnRhZ2UpCmNhdCgiVG90YWwgcGVyY2VudGFnZSBhY3Jvc3MgYWxsIHB1cnBvc2VzOiIsIHRvdGFsX3BlcmNlbnRhZ2UsICIlXG4iKQoKZmFybV9wdXJwb3NlX3Bsb3QgPC0gZ2dwbG90KGZhcm1fcHVycG9zZXMsIGFlcyh4ID0gIkZhcm0iLCB5ID0gcGVyY2VudGFnZSwgZmlsbCA9IHB1cnBvc2UpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gInN0YWNrIiwgd2lkdGggPSAwLjYsIGNvbG9yID0gIndoaXRlIiwgbGluZXdpZHRoID0gMC4yKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChyb3VuZChwZXJjZW50YWdlLCAxKSwgIiUiKSksIAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwgCiAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwgZm9udGZhY2UgPSAiYm9sZCIsIHNpemUgPSAzKSArCiAgbGFicyh0aXRsZSA9ICJBbnRpYmlvdGljIFVzZSBQdXJwb3NlcyBvbiBGYXJtcyIsCiAgICAgICBzdWJ0aXRsZSA9IHBhc3RlMCgibiA9ICIsIGZhcm1fYWJfY2kkbiwgIiBmYXJtcyIsIAogICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UodG90YWxfcGVyY2VudGFnZSA+IDEwMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcbk5vdGU6IFBlcmNlbnRhZ2VzIHN1bSB0byA+MTAwJSBhcyBmYXJtcyBtYXkgdXNlIGFudGliaW90aWNzIGZvciBtdWx0aXBsZSBwdXJwb3NlcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIikpLAogICAgICAgeCA9ICIiLAogICAgICAgeSA9ICJQZXJjZW50YWdlIG9mIEZhcm1zICglKSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuOCwgImNtIiksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3IgPSBOQSksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvciA9IE5BKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAiVHJlYXRtZW50IiA9ICIjYThjMGUwIiwKICAgICJQcmV2ZW50aW9uIiA9ICIjZTBiNWE4IiwgCiAgICAiR3Jvd3RoIFByb21vdGlvbiIgPSAiI2E4ZDNiNSIKICApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCksIGxpbWl0cyA9IGMoMCwgMTAwKSkKCnByaW50KGZhcm1fcHVycG9zZV9wbG90KQoKCiMgNC4gTm9uLXRyZWF0bWVudCBhbnRpYmlvdGljIHVzZSBhbmFseXNpcwpub25fdHJlYXRtZW50X3Bsb3QgPC0gZ2dwbG90KG5vbl90cmVhdG1lbnRfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gcmVvcmRlcihwdXJwb3NlLCAtcGVyY2VudGFnZSksIHkgPSBwZXJjZW50YWdlLCBmaWxsID0gcHVycG9zZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjYsIGNvbG9yID0gImdyYXkzMCIsIGxpbmV3aWR0aCA9IDAuMikgKwogIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBjaV9sb3dlciwgeW1heCA9IGNpX3VwcGVyKSwgd2lkdGggPSAwLjIsIGNvbG9yID0gImdyYXkzMCIsIGxpbmV3aWR0aCA9IDAuNSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBzcHJpbnRmKCIlLjFmJSUiLCBwZXJjZW50YWdlKSksIAogICAgICAgICAgICB2anVzdCA9IC0wLjUsIHNpemUgPSAzLCBjb2xvciA9ICJncmF5MzAiKSArCiAgbGFicyh0aXRsZSA9ICJOb24tVHJlYXRtZW50IEFudGliaW90aWMgVXNlIGluIEZhcm1zIiwKICAgICAgIHN1YnRpdGxlID0gcGFzdGUwKCJuID0gIiwgZmFybV9hYl9jaSRuLCAiIGZhcm1zIiksCiAgICAgICB4ID0gIiIsCiAgICAgICB5ID0gIlByZXZhbGVuY2UgKCUpIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSA4LjUpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygKICAgICJBbnkgTm9uLVRyZWF0bWVudCIgPSAiI2E4YzBlMCIsCiAgICAiUHJldmVudGlvbiBPbmx5IiA9ICIjZTBiNWE4IiwKICAgICJHcm93dGggUHJvbW90aW9uIE9ubHkiID0gIiNhOGQzYjUiLAogICAgIkJvdGggUHVycG9zZXMiID0gIiNjM2I1ZDMiCiAgKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIG1heChub25fdHJlYXRtZW50X2RhdGEkY2lfdXBwZXIpICogMS4xNSksCiAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gYygwLCAwKSkKcHJpbnQobm9uX3RyZWF0bWVudF9wbG90KQoKCiMgNS4gSG91c2Vob2xkIGFudGliaW90aWMgdXNlIGJ5IHN5bXB0b20gc3RhdHVzIChpZiBhdmFpbGFibGUpCmlmKGV4aXN0cygiaG91c2Vob2xkX2J5X3N5bXB0b20iKSAmJiBucm93KGhvdXNlaG9sZF9ieV9zeW1wdG9tKSA+IDApIHsKICBob3VzZWhvbGRfYnlfc3ltcHRvbSRzeW1wdG9tX3N0YXR1cyA8LSBmYWN0b3IoCiAgICBob3VzZWhvbGRfYnlfc3ltcHRvbSRzeW1wdG9tX3N0YXR1cywKICAgIGxldmVscyA9IGMoIlJlc3BpcmF0b3J5IHN5bXB0b21zIiwgIkdJIHN5bXB0b21zIiwgIkZldmVyIiwgCiAgICAgICAgICAgICAgIk90aGVyIHN5bXB0b21zIiwgIk5vIHN5bXB0b21zIikKICApCiAgCiAgc3ltcHRvbV9wbG90IDwtIGdncGxvdChob3VzZWhvbGRfYnlfc3ltcHRvbSwgCiAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSByZW9yZGVyKHN5bXB0b21fc3RhdHVzLCAtYWJfdXNlX3BjdCksIHkgPSBhYl91c2VfcGN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IHN5bXB0b21fc3RhdHVzKSkgKwogICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC43LCBjb2xvciA9ICJncmF5MzAiLCBsaW5ld2lkdGggPSAwLjIpICsKICAgIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBhYl91c2VfY2lfbG93ZXIsIHltYXggPSBhYl91c2VfY2lfdXBwZXIpLCAKICAgICAgICAgICAgICAgICB3aWR0aCA9IDAuMiwgY29sb3IgPSAiZ3JheTMwIiwgbGluZXdpZHRoID0gMC41KSArCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc3ByaW50ZigiJS4xZiUlIiwgYWJfdXNlX3BjdCkpLCAKICAgICAgICAgICAgICB2anVzdCA9IC0wLjUsIHNpemUgPSAzLCBjb2xvciA9ICJncmF5MzAiKSArCiAgICBsYWJzKHRpdGxlID0gIkhvdXNlaG9sZCBBbnRpYmlvdGljIFVzZSBieSBTeW1wdG9tIFN0YXR1cyIsCiAgICAgICAgIHN1YnRpdGxlID0gcGFzdGUwKCJuID0gIiwgaG91c2Vob2xkX2FiX2NpJG4sICIgaG91c2Vob2xkcyIpLAogICAgICAgICB4ID0gIiIsCiAgICAgICAgIHkgPSAiQW50aWJpb3RpYyBVc2UgUmF0ZSAoJSkiKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSA4LjUpKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKAogICAgICAiUmVzcGlyYXRvcnkgc3ltcHRvbXMiID0gIiNhOGMwZTAiLAogICAgICAiR0kgc3ltcHRvbXMiID0gIiNlMGI1YTgiLAogICAgICAiRmV2ZXIiID0gIiNhOGQzYjUiLAogICAgICAiT3RoZXIgc3ltcHRvbXMiID0gIiNjM2I1ZDMiLAogICAgICAiTm8gc3ltcHRvbXMiID0gIiNkOGNmYjAiCiAgICApKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCBtYXgoaG91c2Vob2xkX2J5X3N5bXB0b20kYWJfdXNlX2NpX3VwcGVyKSAqIDEuMTUpLAogICAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gYygwLCAwKSkKICAKICBwcmludChzeW1wdG9tX3Bsb3QpCn0KCiMgNi4gQ29tcGFyYXRpdmUgY2hhcnQgb2YgYW50aWJpb3RpYyBjbGFzc2VzIC0gU2NpZW5jZS9MYW5jZXQgc3R5bGUKY2xhc3NfcGxvdCA8LSBnZ3Bsb3QoYWJfY2xhc3NfY29tcGFyaXNvbiwgCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHJlb3JkZXIoY2xhc3MsIC1wZXJjZW50YWdlKSwgeSA9IHBlcmNlbnRhZ2UsIGZpbGwgPSBzZWN0b3IpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiLCB3aWR0aCA9IDAuNywgCiAgICAgICAgICAgICBjb2xvciA9ICJncmF5MzAiLCBsaW5ld2lkdGggPSAwLjIpICsKICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBzcHJpbnRmKCIlLjFmJSUiLCBwZXJjZW50YWdlKSksCiAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNyksCiAgICAgICAgICAgICAgdmp1c3QgPSAtMC4zLCBzaXplID0gMi44LCBjb2xvciA9ICJncmF5MzAiKSArCiAgICBsYWJzKHRpdGxlID0gIkFudGliaW90aWMgQ2xhc3NlcyBVc2VkIGluIEZhcm1zIGFuZCBIb3VzZWhvbGRzIiwKICAgICAgICAgc3VidGl0bGUgPSAiUHJvcG9ydGlvbiBvZiBmYXJtcy9ob3VzZWhvbGRzIHVzaW5nIGVhY2ggYW50aWJpb3RpYyBjbGFzcyIsCiAgICAgICAgIHggPSAiIiwKICAgICAgICAgeSA9ICJVc2FnZSBSYXRlICglKSIpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSA4KSwKICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3IgPSBOQSksCiAgICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gTkEpLAogICAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiRmFybSIgPSAiI2E4YzBlMCIsICJIb3VzZWhvbGQiID0gIiNlMGI1YTgiKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgbWF4KGFiX2NsYXNzX2NvbXBhcmlzb24kcGVyY2VudGFnZSkgKiAxLjIpLCAKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAxMDAsIGJ5ID0gMjApLAogICAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gYygwLCAwKSkKCiAgcHJpbnQoY2xhc3NfcGxvdCkKICBnZ3NhdmUoImFudGliaW90aWNfY2xhc3NfY29tcGFyaXNvbi5wbmciLCBjbGFzc19wbG90LCAKICAgICAgICAgd2lkdGggPSA4LCBoZWlnaHQgPSA1LCBkcGkgPSAzMDApCiAgCiAgIyAyLiBTaGFyZWQgYW50aWJpb3RpYyBjbGFzc2VzIChpZiBhdmFpbGFibGUpCiAgaWYobGVuZ3RoKHNoYXJlZF9jbGFzc2VzKSA+IDApIHsKICAgIHNoYXJlZF9jbGFzc19wbG90IDwtIGdncGxvdChzaGFyZWRfY2xhc3NfY29tcGFyaXNvbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gcmVvcmRlcihjbGFzcywgLXBlcmNlbnRhZ2UpLCB5ID0gcGVyY2VudGFnZSwgZmlsbCA9IHNlY3RvcikpICsKICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImRvZGdlIiwgd2lkdGggPSAwLjcsIAogICAgICAgICAgICAgICBjb2xvciA9ICJncmF5MzAiLCBsaW5ld2lkdGggPSAwLjIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNwcmludGYoIiUuMWYlJSIsIHBlcmNlbnRhZ2UpKSwKICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjcpLAogICAgICAgICAgICAgICAgdmp1c3QgPSAtMC4zLCBzaXplID0gMi44LCBjb2xvciA9ICJncmF5MzAiKSArCiAgICAgIGxhYnModGl0bGUgPSAiU2hhcmVkIEFudGliaW90aWMgQ2xhc3NlcyBpbiBGYXJtcyBhbmQgSG91c2Vob2xkcyIsCiAgICAgICAgICAgc3VidGl0bGUgPSBpZmVsc2UoZXhpc3RzKCJjbGFzc19jb3JyZWxhdGlvbiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoIlNwZWFybWFuIGNvcnJlbGF0aW9uOiByaG8gPSAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQoY2xhc3NfY29ycmVsYXRpb24kZXN0aW1hdGUsIDIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiLCBwID0gIiwgcm91bmQoY2xhc3NfY29ycmVsYXRpb24kcC52YWx1ZSwgMykpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29tcGFyaXNvbiBvZiB1c2FnZSBwYXR0ZXJucyBhY3Jvc3Mgc2VjdG9ycyIpLAogICAgICAgICAgIHggPSAiIiwKICAgICAgICAgICB5ID0gIlVzYWdlIFJhdGUgKCUpIikgKwogICAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSA4KSwKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gTkEpLAogICAgICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG9yID0gTkEpLAogICAgICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiRmFybSIgPSAiI2E4YzBlMCIsICJIb3VzZWhvbGQiID0gIiNlMGI1YTgiKSkgKwogICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCBtYXgoc2hhcmVkX2NsYXNzX2NvbXBhcmlzb24kcGVyY2VudGFnZSkgKiAxLjIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEwMCwgYnkgPSAyMCksCiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGFuZCA9IGMoMCwgMCkpCiAgICAKICAgIHByaW50KHNoYXJlZF9jbGFzc19wbG90KQogIH0KfQoKCiMgNy4gQ29tcGFyaXNvbiBvZiBjb21tb24gYW50aWJpb3RpYyBjbGFzc2VzIC0gU2NpZW5jZS9MYW5jZXQgc3R5bGUKaWYoZXhpc3RzKCJzaGFyZWRfY2xhc3NfY29tcGFyaXNvbiIpICYmIGxlbmd0aChzaGFyZWRfY2xhc3NlcykgPiAwKSB7CiAgc2hhcmVkX2NsYXNzX3Bsb3QgPC0gZ2dwbG90KHNoYXJlZF9jbGFzc19jb21wYXJpc29uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gcmVvcmRlcihjbGFzcywgLXBlcmNlbnRhZ2UpLCB5ID0gcGVyY2VudGFnZSwgZmlsbCA9IHNlY3RvcikpICsKICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIsIHdpZHRoID0gMC43LCAKICAgICAgICAgICAgIGNvbG9yID0gImdyYXkzMCIsIGxpbmV3aWR0aCA9IDAuMikgKwogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNwcmludGYoIiUuMWYlJSIsIHBlcmNlbnRhZ2UpKSwKICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC43KSwKICAgICAgICAgICAgICB2anVzdCA9IC0wLjMsIHNpemUgPSAyLjgsIGNvbG9yID0gImdyYXkzMCIpICsKICAgIGxhYnModGl0bGUgPSAiU2hhcmVkIEFudGliaW90aWMgQ2xhc3NlcyBpbiBGYXJtcyBhbmQgSG91c2Vob2xkcyIsCiAgICAgICAgIHggPSAiIiwKICAgICAgICAgeSA9ICJVc2FnZSBSYXRlICglKSIsCiAgICAgICAgIGZpbGwgPSAiIikgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gOCksCiAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiRmFybSIgPSAiI2E4YzBlMCIsICJIb3VzZWhvbGQiID0gIiNlMGI1YTgiKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgbWF4KHNoYXJlZF9jbGFzc19jb21wYXJpc29uJHBlcmNlbnRhZ2UpICogMS4yKSwgCiAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgNTAsIGJ5ID0gMTApLAogICAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gYygwLCAwKSkgCiAgCiAgcHJpbnQoc2hhcmVkX2NsYXNzX3Bsb3QpCiAgZ2dzYXZlKCJzaGFyZWRfYW50aWJpb3RpY19jbGFzc2VzLnBkZiIsIHNoYXJlZF9jbGFzc19wbG90LCAKICAgICAgICAgd2lkdGggPSA3LCBoZWlnaHQgPSA1LCBkcGkgPSAzMDApCiAgZ2dzYXZlKCJzaGFyZWRfYW50aWJpb3RpY19jbGFzc2VzLnBuZyIsIHNoYXJlZF9jbGFzc19wbG90LCAKICAgICAgICAgd2lkdGggPSA3LCBoZWlnaHQgPSA1LCBkcGkgPSAzMDApCgogIGlmKGxlbmd0aChzaGFyZWRfY2xhc3NlcykgPj0gMyAmJiBleGlzdHMoImNvcnJlbGF0aW9uX2RhdGEiKSkgewogICAgY29ycl9wbG90IDwtIGdncGxvdChjb3JyZWxhdGlvbl9kYXRhLCBhZXMoeCA9IEhvdXNlaG9sZCwgeSA9IEZhcm0sIGxhYmVsID0gY2xhc3MpKSArCiAgICAgIGdlb21fcG9pbnQoY29sb3IgPSAiI2E4YzBlMCIsIHNpemUgPSAzLCBhbHBoYSA9IDAuOCkgKwogICAgICBnZW9tX3RleHRfcmVwZWwoc2l6ZSA9IDMsIGNvbG9yID0gImdyYXkzMCIsIGJveC5wYWRkaW5nID0gMC41KSArCiAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSwgY29sb3IgPSAiI2UwYjVhOCIsIGZpbGwgPSAiI2UwYjVhOCIsIGFscGhhID0gMC4yKSArCiAgICAgIGxhYnModGl0bGUgPSAiQ29ycmVsYXRpb24gb2YgQW50aWJpb3RpYyBDbGFzcyBVc2FnZSIsCiAgICAgICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoIlNwZWFybWFuIGNvcnJlbGF0aW9uOiByaG8gPSAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQoY2xhc3NfY29ycmVsYXRpb24kZXN0aW1hdGUsIDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIiwgcCA9ICIsIHJvdW5kKGNsYXNzX2NvcnJlbGF0aW9uJHAudmFsdWUsIDMpKSwKICAgICAgICAgICB4ID0gIkhvdXNlaG9sZCBVc2FnZSBSYXRlICglKSIsCiAgICAgICAgICAgeSA9ICJGYXJtIFVzYWdlIFJhdGUgKCUpIikgKwogICAgICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyYXk5NSIsIGxpbmV3aWR0aCA9IDAuMykpICsKICAgICAgY29vcmRfZml4ZWQocmF0aW8gPSAxLCB4bGltID0gYygwLCBtYXgoY29ycmVsYXRpb25fZGF0YSRIb3VzZWhvbGQsIGNvcnJlbGF0aW9uX2RhdGEkRmFybSkgKiAxLjEpLAogICAgICAgICAgICAgICAgeWxpbSA9IGMoMCwgbWF4KGNvcnJlbGF0aW9uX2RhdGEkSG91c2Vob2xkLCBjb3JyZWxhdGlvbl9kYXRhJEZhcm0pICogMS4xKSkKICAgIAogICAgcHJpbnQoY29ycl9wbG90KQogIH0KfQoKIyA4LjMgQ3JlYXRlIGZvcmVzdCBwbG90IGNvbXBhcmluZyBhbnRpYmlvdGljIHVzZSBhY3Jvc3MgZGlmZmVyZW50IGNhdGVnb3JpZXMKCiMgUHJlcGFyZSBkYXRhIGZvciBmb3Jlc3QgcGxvdApmb3Jlc3RfZGF0YSA8LSBiaW5kX3Jvd3MoCiAgIyBGYXJtIGRhdGEgYnkgcHVycG9zZQogIGZhcm1fcHVycG9zZXMgJT4lCiAgICBtdXRhdGUoCiAgICAgIGNhdGVnb3J5ID0gIkZhcm0iLAogICAgICBzdWJjYXRlZ29yeSA9IHB1cnBvc2UsCiAgICAgIGVzdGltYXRlID0gcGVyY2VudGFnZSwKICAgICAgIyBBZGQgY29uZmlkZW5jZSBpbnRlcnZhbHMgKGFwcHJveGltYXRlIGZvciB2aXN1YWxpemF0aW9uIHB1cnBvc2VzKQogICAgICBsb3dlciA9IHBtYXgoMCwgcGVyY2VudGFnZSAtIDUpLAogICAgICB1cHBlciA9IHBtaW4oMTAwLCBwZXJjZW50YWdlICsgNSkKICAgICkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KGNhdGVnb3J5LCBzdWJjYXRlZ29yeSwgZXN0aW1hdGUsIGxvd2VyLCB1cHBlciksCiAgCiAgIyBIb3VzZWhvbGQgZGF0YQogIGRhdGEuZnJhbWUoCiAgICBjYXRlZ29yeSA9ICJIb3VzZWhvbGQiLAogICAgc3ViY2F0ZWdvcnkgPSAiQW55IFVzZSIsCiAgICBlc3RpbWF0ZSA9IGhvdXNlaG9sZF9hYl9jaSRhYl91c2VfcGN0LAogICAgbG93ZXIgPSBob3VzZWhvbGRfYWJfY2kkYWJfdXNlX2NpX2xvd2VyLAogICAgdXBwZXIgPSBob3VzZWhvbGRfYWJfY2kkYWJfdXNlX2NpX3VwcGVyLAogICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCiAgKSwKICAKICAjIEhvdXNlaG9sZCBwcmV2ZW50aXZlIHVzZSAoYm90aCBkZWZpbml0aW9ucykKICBkYXRhLmZyYW1lKAogICAgY2F0ZWdvcnkgPSAiSG91c2Vob2xkIiwKICAgIHN1YmNhdGVnb3J5ID0gYygiUHJldmVudGl2ZSAoU3RyaW5nZW50KSIsICJQcmV2ZW50aXZlIChSZWxheGVkKSIpLAogICAgZXN0aW1hdGUgPSBjKGhvdXNlaG9sZF9wcmV2ZW50aXZlX3N0cmluZ2VudCRwcmV2ZW50aXZlX3BjdCwgCiAgICAgICAgICAgICAgICBob3VzZWhvbGRfcHJldmVudGl2ZV9yZWxheGVkJHByZXZlbnRpdmVfcGN0KSwKICAgIGxvd2VyID0gYyhob3VzZWhvbGRfcHJldmVudGl2ZV9zdHJpbmdlbnQkcHJldmVudGl2ZV9jaV9sb3dlciwKICAgICAgICAgICAgIGhvdXNlaG9sZF9wcmV2ZW50aXZlX3JlbGF4ZWQkcHJldmVudGl2ZV9jaV9sb3dlciksCiAgICB1cHBlciA9IGMoaG91c2Vob2xkX3ByZXZlbnRpdmVfc3RyaW5nZW50JHByZXZlbnRpdmVfY2lfdXBwZXIsCiAgICAgICAgICAgICBob3VzZWhvbGRfcHJldmVudGl2ZV9yZWxheGVkJHByZXZlbnRpdmVfY2lfdXBwZXIpLAogICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCiAgKQopICU+JQogICMgQ3JlYXRlIGEgY29tYmluZWQgbGFiZWwgZm9yIG9yZGVyaW5nCiAgbXV0YXRlKAogICAgY29tYmluZWRfbGFiZWwgPSBwYXN0ZTAoY2F0ZWdvcnksICI6ICIsIHN1YmNhdGVnb3J5KSwKICAgIGNvbWJpbmVkX2xhYmVsID0gZmFjdG9yKGNvbWJpbmVkX2xhYmVsLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSByZXYodW5pcXVlKGNvbWJpbmVkX2xhYmVsKSkpCiAgKQoKIyBDcmVhdGUgdGhlIGZvcmVzdCBwbG90CmZvcmVzdF9wbG90IDwtIGdncGxvdChmb3Jlc3RfZGF0YSwgYWVzKHggPSBlc3RpbWF0ZSwgeSA9IGNvbWJpbmVkX2xhYmVsLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gY2F0ZWdvcnkpKSArCiAgZ2VvbV9yZWN0KGFlcyh5bWluID0gYXMubnVtZXJpYyhjb21iaW5lZF9sYWJlbCkgLSAwLjUsIAogICAgICAgICAgICAgICB5bWF4ID0gYXMubnVtZXJpYyhjb21iaW5lZF9sYWJlbCkgKyAwLjUsCiAgICAgICAgICAgICAgIHhtaW4gPSAwLCB4bWF4ID0gMTAwKSwKICAgICAgICAgICBmaWxsID0gImdyYXk5NyIsIGFscGhhID0gMC41LCBjb2xvciA9IE5BKSArCiAgZ2VvbV9wb2ludChzaXplID0gMykgKwogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gbG93ZXIsIHhtYXggPSB1cHBlciksIGhlaWdodCA9IDAuMywgbGluZXdpZHRoID0gMC41KSArCiAgbGFicyh0aXRsZSA9ICJBbnRpYmlvdGljIFVzZSBQYXR0ZXJucyBpbiBGYXJtcyBhbmQgSG91c2Vob2xkcyIsCiAgICAgICBzdWJ0aXRsZSA9ICJQb2ludCBlc3RpbWF0ZXMgd2l0aCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMiLAogICAgICAgeCA9ICJQcmV2YWxlbmNlICglKSIsCiAgICAgICB5ID0gIiIsCiAgICAgICBjb2xvciA9ICIiKSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyYXk5NSIsIGxpbmV3aWR0aCA9IDAuMyksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIkZhcm0iID0gIiNhOGMwZTAiLCAiSG91c2Vob2xkIiA9ICIjZTBiNWE4IikpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApLCBicmVha3MgPSBzZXEoMCwgMTAwLCBieSA9IDIwKSwKICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBjKDAsIDApKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gZXN0aW1hdGUgKyAzLCBsYWJlbCA9IHNwcmludGYoIiUuMWYlJSIsIGVzdGltYXRlKSksIAogICAgICAgICAgICBzaXplID0gMi44LCBoanVzdCA9IDAsIGNvbG9yID0gImdyYXkzMCIpCgpwcmludChmb3Jlc3RfcGxvdCkKCgojIDguNCBDcmVhdGUgT25lIEhlYWx0aCBwZXJzcGVjdGl2ZSBpbnRlZ3JhdGVkIHZpc3VhbGl6YXRpb24KIyBQcmVwYXJlIGRhdGEgZm9yIE9uZSBIZWFsdGggdmlzdWFsaXphdGlvbgpvbmVfaGVhbHRoX2RhdGEgPC0gYmluZF9yb3dzKAogICMgRmFybSBkYXRhCiAgZGF0YS5mcmFtZSgKICAgIHNlY3RvciA9ICJGYXJtIiwKICAgIGNhdGVnb3J5ID0gYygiVHJlYXRtZW50IiwgIlByZXZlbnRpb24iLCAiR3Jvd3RoIFByb21vdGlvbiIpLAogICAgcGVyY2VudGFnZSA9IGMoZmFybV9hYl9jaSRhYl90cmVhdG1lbnRfcGN0LCAKICAgICAgICAgICAgICAgICBmYXJtX2FiX2NpJGFiX3ByZXZlbnRpb25fcGN0LCAKICAgICAgICAgICAgICAgICBmYXJtX2FiX2NpJGFiX2dyb3d0aF9wY3QpLAogICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCiAgKSwKICAKICAjIEhvdXNlaG9sZCBkYXRhCiAgaG91c2Vob2xkX2J5X3N5bXB0b20gJT4lCiAgICB0cmFuc211dGUoCiAgICAgIHNlY3RvciA9ICJIb3VzZWhvbGQiLAogICAgICBjYXRlZ29yeSA9IHN5bXB0b21fc3RhdHVzLAogICAgICBwZXJjZW50YWdlID0gYWJfdXNlX3BjdAogICAgKQopCgojIENyZWF0ZSB0aGUgT25lIEhlYWx0aCB2aXN1YWxpemF0aW9uCm9uZV9oZWFsdGhfcGxvdCA8LSBnZ3Bsb3Qob25lX2hlYWx0aF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBzZWN0b3IsIHkgPSBwZXJjZW50YWdlLCBmaWxsID0gY2F0ZWdvcnkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gInN0YWNrIiwgd2lkdGggPSAwLjcpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc3ByaW50ZigiJS4xZiUlIiwgcGVyY2VudGFnZSkpLAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwKICAgICAgICAgICAgY29sb3IgPSAid2hpdGUiLCBmb250ZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDMpICsKICBsYWJzKHRpdGxlID0gIk9uZSBIZWFsdGggUGVyc3BlY3RpdmU6IEludGVncmF0ZWQgQW50aWJpb3RpYyBVc2UgUGF0dGVybnMiLAogICAgICAgc3VidGl0bGUgPSAiQ29tcGFyaXNvbiBvZiBhbnRpYmlvdGljIHVzZSBwdXJwb3NlcyBhY3Jvc3MgZmFybSBhbmQgaG91c2Vob2xkIHNlY3RvcnMiLAogICAgICAgeCA9ICIiLAogICAgICAgeSA9ICJQZXJjZW50YWdlICglKSIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKAogICAgIyBGYXJtIGNvbG9ycyAoYmx1ZXMpCiAgICAiVHJlYXRtZW50IiA9ICIjNGE2ZmUzIiwKICAgICJQcmV2ZW50aW9uIiA9ICIjNmFhYmNjIiwKICAgICJHcm93dGggUHJvbW90aW9uIiA9ICIjYThkNWViIiwKICAgICMgSG91c2Vob2xkIGNvbG9ycyAocmVkcy9vcmFuZ2VzKQogICAgIlJlc3BpcmF0b3J5IHN5bXB0b21zIiA9ICIjZDM4MjVmIiwKICAgICJHSSBzeW1wdG9tcyIgPSAiI2U5YWU5OCIsCiAgICAiRmV2ZXIiID0gIiNjMTVjNDEiLAogICAgIk90aGVyIHN5bXB0b21zIiA9ICIjZjNjZmJmIiwKICAgICJObyBzeW1wdG9tcyIgPSAiI2ZhZTNkNyIKICApKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCgpwcmludChvbmVfaGVhbHRoX3Bsb3QpCgoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIDkuIFNVTU1BUlkgT0YgRklORElOR1MKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIENyZWF0ZSBhIGNvbXByZWhlbnNpdmUgc3VtbWFyeSB0YWJsZQpzdW1tYXJ5X3RhYmxlIDwtIGRhdGEuZnJhbWUoCiAgTWVhc3VyZSA9IGMoIk92ZXJhbGwgQW50aWJpb3RpYyBVc2UiLCAiRmFybSBUcmVhdG1lbnQgVXNlIiwgIkZhcm0gUHJldmVudGlvbiBVc2UiLCAKICAgICAgICAgICAgICAiRmFybSBHcm93dGggUHJvbW90aW9uIFVzZSIsICJIb3VzZWhvbGQgUHJldmVudGl2ZSBVc2UgKFByb3h5KSIpLAogIFByZXZhbGVuY2UgPSBjKAogICAgcGFzdGUwKHJvdW5kKGZhcm1fYWJfY2kkYWJfdXNlX3BjdCwgMSksICIlIHZzICIsIHJvdW5kKGhvdXNlaG9sZF9hYl9jaSRhYl91c2VfcGN0LCAxKSwgIiUiKSwKICAgIHBhc3RlMChyb3VuZChmYXJtX2FiX2NpJGFiX3RyZWF0bWVudF9wY3QsIDEpLCAiJSIpLAogICAgcGFzdGUwKHJvdW5kKGZhcm1fYWJfY2kkYWJfcHJldmVudGlvbl9wY3QsIDEpLCAiJSIpLAogICAgcGFzdGUwKHJvdW5kKGZhcm1fYWJfY2kkYWJfZ3Jvd3RoX3BjdCwgMSksICIlIiksCiAgICBwYXN0ZTAocm91bmQoaG91c2Vob2xkX3ByZXZlbnRpdmUkcHJldmVudGl2ZV9wY3QsIDEpLCAiJSIpCiAgKSwKICBDb21wYXJpc29uID0gYygKICAgIHBhc3RlMCgiz4fCsiA9ICIsIHJvdW5kKG92ZXJhbGxfY2hpJHN0YXRpc3RpYywgMSksIAogICAgICAgICAgIiwgcCAiLCBpZmVsc2Uob3ZlcmFsbF9jaGkkcC52YWx1ZSA8IDAuMDAxLCAiPCAwLjAwMSIsIAogICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoIj0gIiwgcm91bmQob3ZlcmFsbF9jaGkkcC52YWx1ZSwgMykpKSwKICAgICAgICAgICI7IEVmZmVjdDogIiwgb3ZlcmFsbF9lZmZlY3QpLAogICAgIk4vQSIsCiAgICBwYXN0ZTAoIkZhcm06SG91c2Vob2xkIHJhdGlvID0gIiwgcm91bmQocHJldmVudGl2ZV9yYXRpbywgMSksICI6MSIpLAogICAgIk4vQSIsCiAgICBwYXN0ZTAoIs+HwrIgPSAiLCByb3VuZChwcmV2ZW50aXZlX2NoaSRzdGF0aXN0aWMsIDEpLCAKICAgICAgICAgICIsIHAgIiwgaWZlbHNlKHByZXZlbnRpdmVfY2hpJHAudmFsdWUgPCAwLjAwMSwgIjwgMC4wMDEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCI9ICIsIHJvdW5kKHByZXZlbnRpdmVfY2hpJHAudmFsdWUsIDMpKSksCiAgICAgICAgICAiOyBFZmZlY3Q6ICIsIHByZXZlbnRpdmVfZWZmZWN0KQogICksCiAgQ29uY2x1c2lvbiA9IGMoCiAgICBpZmVsc2Uob3ZlcmFsbF9jaGkkcC52YWx1ZSA8IDAuMDUsIAogICAgICAgICAgIlNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gb3ZlcmFsbCB1c2UgYmV0d2VlbiBmYXJtcyBhbmQgaG91c2Vob2xkcyIsIAogICAgICAgICAgIk5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgaW4gb3ZlcmFsbCB1c2UiKSwKICAgICJNb3N0IGNvbW1vbiBwdXJwb3NlIGZvciBhbnRpYmlvdGljIHVzZSBpbiBmYXJtcyIsCiAgICBpZmVsc2UocHJldmVudGl2ZV9jaGkkcC52YWx1ZSA8IDAuMDUsCiAgICAgICAgICAiU2lnbmlmaWNhbnRseSBoaWdoZXIgcHJldmVudGl2ZSB1c2UgaW4gZmFybXMgdGhhbiBob3VzZWhvbGRzIiwKICAgICAgICAgICJObyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHByZXZlbnRpdmUgdXNlIiksCiAgICBwYXN0ZTAocm91bmQoZmFybV9ub25fdHJlYXRtZW50JGFueV9ub25fdHJlYXRtZW50X3BjdCwgMSksIAogICAgICAgICAgIiUgb2YgZmFybXMgdXNlIGFudGliaW90aWNzIGZvciBub24tdHJlYXRtZW50IHB1cnBvc2VzIiksCiAgICAiQmFzZWQgb24gcHJveHkgbWVhc3VyZSBvZiBhbnRpYmlvdGljIHVzZSB3aXRob3V0IHN5bXB0b21zIgogICkKKQoKIyBEaXNwbGF5IHRoZSBzdW1tYXJ5IHRhYmxlCmthYmxlKHN1bW1hcnlfdGFibGUsCiAgICAgIGNhcHRpb24gPSAiU3VtbWFyeSBvZiBLZXkgRmluZGluZ3MgZm9yIEh5cG90aGVzaXMgMS4xIiwKICAgICAgYWxpZ24gPSAibGxsbCIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCAKICAgICAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGQUxTRSkgJT4lCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFRSVUUpICU+JQogIHJvd19zcGVjKDAsIGJvbGQgPSBUUlVFLCBiYWNrZ3JvdW5kID0gIiNmMmYyZjIiKQoKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgMTAuIEZJTkFMIENPTkNMVVNJT04gT04gSFlQT1RIRVNJUyAxLjEKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpjYXQoIlxuXG4jIyMgQ09OQ0xVU0lPTiBPTiBIWVBPVEhFU0lTIDEuMSAjIyNcblxuIikKY2F0KCJIeXBvdGhlc2lzIDEuMSBzdGF0ZXMgdGhhdCBwcmV2ZW50aXZlIGFuZCBncm93dGgtcHJvbW90aW5nIGFudGliaW90aWMgdXNlIGlzIGNvbW1vbiBpbiBmYXJtIGFuaW1hbHMsIHdpdGggcHJldmFsZW5jZSByYXRlcyBoaWdoZXIgdGhhbiBjb3JyZXNwb25kaW5nIHVzZSBpbiBodW1hbiBtZWRpY2luZS5cblxuIikKCiMgT3ZlcmFsbCBjb25jbHVzaW9uCmlmKGZhcm1fYWJfY2kkYWJfcHJldmVudGlvbl9wY3QgPiBob3VzZWhvbGRfcHJldmVudGl2ZSRwcmV2ZW50aXZlX3BjdCAmJiBwcmV2ZW50aXZlX2NoaSRwLnZhbHVlIDwgMC4wNSkgewogIGNhdCgiQ09OQ0xVU0lPTjogVGhlIGRhdGEgU1VQUE9SVFMgaHlwb3RoZXNpcyAxLjEuIFxuXG4iKQp9IGVsc2UgaWYoZmFybV9hYl9jaSRhYl9wcmV2ZW50aW9uX3BjdCA+IGhvdXNlaG9sZF9wcmV2ZW50aXZlJHByZXZlbnRpdmVfcGN0ICYmIHByZXZlbnRpdmVfY2hpJHAudmFsdWUgPj0gMC4wNSkgewogIGNhdCgiQ09OQ0xVU0lPTjogVGhlIGRhdGEgUEFSVElBTExZIFNVUFBPUlRTIGh5cG90aGVzaXMgMS4xLiBcblxuIikKfSBlbHNlIHsKICBjYXQoIkNPTkNMVVNJT046IFRoZSBkYXRhIERPRVMgTk9UIFNVUFBPUlQgaHlwb3RoZXNpcyAxLjEuIFxuXG4iKQp9CgojIERldGFpbGVkIGV4cGxhbmF0aW9uCmNhdChwYXN0ZTAoIkZhcm0gcHJldmVudGl2ZSBhbnRpYmlvdGljIHVzZSAoIiwgcm91bmQoZmFybV9hYl9jaSRhYl9wcmV2ZW50aW9uX3BjdCwgMSksIAogICAgICAgICAgIiUsIDk1JSBDSTogIiwgcm91bmQoZmFybV9hYl9jaSRhYl9wcmV2ZW50aW9uX2NpX2xvd2VyLCAxKSwgIi0iLCAKICAgICAgICAgIHJvdW5kKGZhcm1fYWJfY2kkYWJfcHJldmVudGlvbl9jaV91cHBlciwgMSksICIlKSBpcyBhcHByb3hpbWF0ZWx5ICIsIAogICAgICAgICAgcm91bmQocHJldmVudGl2ZV9yYXRpbywgMSksICIgdGltZXMgaGlnaGVyIHRoYW4gaG91c2Vob2xkIHByZXZlbnRpdmUgdXNlICgiLCAKICAgICAgICAgIHJvdW5kKGhvdXNlaG9sZF9wcmV2ZW50aXZlJHByZXZlbnRpdmVfcGN0LCAxKSwgIiUsIDk1JSBDSTogIiwgCiAgICAgICAgICByb3VuZChob3VzZWhvbGRfcHJldmVudGl2ZSRwcmV2ZW50aXZlX2NpX2xvd2VyLCAxKSwgIi0iLCAKICAgICAgICAgIHJvdW5kKGhvdXNlaG9sZF9wcmV2ZW50aXZlJHByZXZlbnRpdmVfY2lfdXBwZXIsIDEpLCAiJSkuICIpKQoKaWYocHJldmVudGl2ZV9jaGkkcC52YWx1ZSA8IDAuMDUpIHsKICBjYXQocGFzdGUwKCJUaGlzIGRpZmZlcmVuY2UgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCAoz4fCsiA9ICIsIAogICAgICAgICAgICByb3VuZChwcmV2ZW50aXZlX2NoaSRzdGF0aXN0aWMsIDEpLCAiLCBwICIsIAogICAgICAgICAgICBpZmVsc2UocHJldmVudGl2ZV9jaGkkcC52YWx1ZSA8IDAuMDAxLCAiPCAwLjAwMSIsIHBhc3RlMCgiPSAiLCByb3VuZChwcmV2ZW50aXZlX2NoaSRwLnZhbHVlLCAzKSkpLCAKICAgICAgICAgICAgIikgd2l0aCBhICIsIHRvbG93ZXIocHJldmVudGl2ZV9lZmZlY3QpLCAiIGVmZmVjdCBzaXplIChQaGkgPSAiLCByb3VuZChwcmV2ZW50aXZlX3BoaSwgMyksICIpLlxuXG4iKSkKfSBlbHNlIHsKICBjYXQocGFzdGUwKCJIb3dldmVyLCB0aGlzIGRpZmZlcmVuY2UgaXMgbm90IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKM+HwrIgPSAiLCAKICAgICAgICAgICAgcm91bmQocHJldmVudGl2ZV9jaGkkc3RhdGlzdGljLCAxKSwgIiwgcCA9ICIsIHJvdW5kKHByZXZlbnRpdmVfY2hpJHAudmFsdWUsIDMpLCAKICAgICAgICAgICAgIiksIHBvc3NpYmx5IGR1ZSB0byBsaW1pdGVkIHNhbXBsZSBzaXplIG9yIGhpZ2ggdmFyaWFiaWxpdHkuXG5cbiIpKQp9CgpjYXQocGFzdGUwKCJBZGRpdGlvbmFsbHksICIsIHJvdW5kKGZhcm1fbm9uX3RyZWF0bWVudCRhbnlfbm9uX3RyZWF0bWVudF9wY3QsIDEpLCAKICAgICAgICAgICIlIG9mIGZhcm1zIHVzZSBhbnRpYmlvdGljcyBmb3Igbm9uLXRyZWF0bWVudCBwdXJwb3Nlcywgd2l0aCAiLCAKICAgICAgICAgIHJvdW5kKGZhcm1fYWJfY2kkYWJfZ3Jvd3RoX3BjdCwgMSksICIlIHNwZWNpZmljYWxseSB1c2luZyBhbnRpYmlvdGljcyBmb3IgZ3Jvd3RoIHByb21vdGlvbiwgCiAgICAgICAgICBhIHByYWN0aWNlIG5vdCBmb3VuZCBpbiBodW1hbiBtZWRpY2luZS5cblxuIikpCgpjYXQoIlRoZXNlIGZpbmRpbmdzIHN1Z2dlc3QgdGhhdCBub24tdGhlcmFwZXV0aWMgYW50aWJpb3RpYyB1c2UgaXMgbW9yZSBwcmV2YWxlbnQgaW4gZmFybSBzZXR0aW5ncyBjb21wYXJlZCB0byBob3VzZWhvbGQgdXNlLCAKY29uc2lzdGVudCB3aXRoIHRoZSBoeXBvdGhlc2lzLiBUaGlzIGhhcyBpbXBvcnRhbnQgaW1wbGljYXRpb25zIGZvciBhbnRpbWljcm9iaWFsIHJlc2lzdGFuY2Ugcmlza3MsIGFzIHByZXZlbnRpdmUgYW5kIGdyb3d0aC1wcm9tb3RpbmcgCmFudGliaW90aWMgdXNlIGluIGFncmljdWx0dXJlIG1heSBjb250cmlidXRlIHNpZ25pZmljYW50bHkgdG8gdGhlIG92ZXJhbGwgYW50aWJpb3RpYyBzZWxlY3Rpb24gcHJlc3N1cmUgaW4gdGhlIGVudmlyb25tZW50LlxuXG4iKQoKY2F0KCJMaW1pdGF0aW9ucyB0byBjb25zaWRlciBpbmNsdWRlIHRoZSB1c2Ugb2YgYSBwcm94eSBtZWFzdXJlIGZvciBob3VzZWhvbGQgcHJldmVudGl2ZSB1c2UgYW5kIHBvdGVudGlhbCBkaWZmZXJlbmNlcyBpbiBhbnRpYmlvdGljIApjbGFzc2lmaWNhdGlvbiBiZXR3ZWVuIHNlY3RvcnMuIEZ1dHVyZSByZXNlYXJjaCBzaG91bGQgaW5jbHVkZSBtb3JlIGRpcmVjdCBtZWFzdXJlcyBvZiBob3VzZWhvbGQgYW50aWJpb3RpYyB1c2UgcHVycG9zZXMgYW5kIGV4YW1pbmUgCnRoZSBzcGVjaWZpYyBkcml2ZXJzIG9mIHByZXZlbnRpdmUgYW50aWJpb3RpYyB1c2UgaW4gYm90aCBzZWN0b3JzLiIpCmBgYAoKIyMgUmVzdWx0cyBmb3IgSHlwb3RoZXNpcyAxLjI6IERpZmZlcmVuY2VzIGluIEFudGliaW90aWMgVXNlIEFtb25nIEFuaW1hbCBUeXBlcwoKYGBge3IgaDItQ29tcGFyaXNvbiBvZiBBbnRpYmlvdGljIFVzZSBBY3Jvc3MgQW5pbWFsIFR5cGVzfQoKIyBMb2FkIHByb2Nlc3NlZCBkYXRhIGlmIG5vdCBhbHJlYWR5IGluIG1lbW9yeQppZighZXhpc3RzKCJmYXJtX2RhdGEiKSkgewogIGZhcm1fZGF0YSA8LSByZWFkUkRTKGhlcmUoImRhdGEiLCAicHJvY2Vzc2VkIiwgImZhcm1fZGF0YV9wcm9jZXNzZWQucmRzIikpCn0KCiMgQ2FsY3VsYXRlIGFudGliaW90aWMgdXNlIHByZXZhbGVuY2UgYnkgYW5pbWFsIHR5cGUKYWJfYnlfYW5pbWFsIDwtIGZhcm1fZGF0YSAlPiUKICBncm91cF9ieShhbmltYWxfdHlwZSkgJT4lCiAgc3VtbWFyaXNlKAogICAgbiA9IG4oKSwKICAgIGFiX3VzZV9hbnlfbiA9IHN1bShhbnlfYWJfdXNlLCBuYS5ybSA9IFRSVUUpLAogICAgYWJfdXNlX2FueV9wY3QgPSBtZWFuKGFueV9hYl91c2UsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBhYl90cmVhdG1lbnRfcGN0ID0gbWVhbihhYl90cmVhdG1lbnQsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBhYl9wcmV2ZW50aW9uX3BjdCA9IG1lYW4oYWJfcHJldmVudGlvbiwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIGFiX2dyb3d0aF9wY3QgPSBtZWFuKGFiX2dyb3d0aCwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIC5ncm91cHMgPSAiZHJvcCIKICApICU+JQogIGZpbHRlcighaXMubmEoYW5pbWFsX3R5cGUpKSAgIyBSZW1vdmUgTkEgYW5pbWFsIHR5cGVzCgojIERpc3BsYXkgcmVzdWx0cwphYl9ieV9hbmltYWwgJT4lCiAga2FibGUoY2FwdGlvbiA9ICJBbnRpYmlvdGljIFVzZSBieSBBbmltYWwgVHlwZSIsCiAgICAgICAgY29sLm5hbWVzID0gYygiQW5pbWFsIFR5cGUiLCAiTnVtYmVyIG9mIEZhcm1zIiwgIkZhcm1zIFVzaW5nIEFudGliaW90aWNzIiwgCiAgICAgICAgICAgICAgICAgICAgICAiJSBBbnkgVXNlIiwgIiUgVHJlYXRtZW50IiwgIiUgUHJldmVudGlvbiIsICIlIEdyb3d0aCBQcm9tb3Rpb24iKSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkKCiMjIyBTcGVjaWZpYyBBbnRpYmlvdGljIFR5cGVzIGJ5IEFuaW1hbCBUeXBlCgojIEZvciBlYWNoIGFuaW1hbCB0eXBlLCBjYWxjdWxhdGUgcHJldmFsZW5jZSBvZiBzcGVjaWZpYyBhbnRpYmlvdGljcwpzcGVjaWZpY19hYl9ieV9hbmltYWwgPC0gZmFybV9kYXRhICU+JQogIGdyb3VwX2J5KGFuaW1hbF90eXBlKSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgY2hsb19wY3QgPSBtZWFuKGNobG8sIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBuaXRyX3BjdCA9IG1lYW4obml0ciwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIGRpbWVfcGN0ID0gbWVhbihkaW1lLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgbWV0cl9wY3QgPSBtZWFuKG1ldHIsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBjaXByX3BjdCA9IG1lYW4oY2lwciwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIG9mbG9fcGN0ID0gbWVhbihvZmxvLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgY2FyYl9wY3QgPSBtZWFuKGNhcmIsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBvbGFxX3BjdCA9IG1lYW4ob2xhcSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIGJhY2lfcGN0ID0gbWVhbihiYWNpLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgJT4lCiAgZmlsdGVyKCFpcy5uYShhbmltYWxfdHlwZSkpCgojIERpc3BsYXkgdGhlIHJlc3VsdHMKc3BlY2lmaWNfYWJfYnlfYW5pbWFsICU+JQogIGthYmxlKGNhcHRpb24gPSAiU3BlY2lmaWMgQW50aWJpb3RpYyBVc2UgYnkgQW5pbWFsIFR5cGUgKCUpIiwKICAgICAgICBkaWdpdHMgPSAxKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEZBTFNFKSAlPiUKICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiKQoKIyMjIENoaS1zcXVhcmUgVGVzdHMgZm9yIERpZmZlcmVuY2VzIEFtb25nIEFuaW1hbCBUeXBlcwoKIyBQcmVwYXJlIGNvbnRpbmdlbmN5IHRhYmxlIGZvciBvdmVyYWxsIGFudGliaW90aWMgdXNlCmFuaW1hbF9hYl90YWJsZSA8LSBmYXJtX2RhdGEgJT4lCiAgZmlsdGVyKCFpcy5uYShhbmltYWxfdHlwZSkpICU+JQogIGdyb3VwX2J5KGFuaW1hbF90eXBlKSAlPiUKICBzdW1tYXJpc2UoCiAgICBhYl91c2UgPSBzdW0oYW55X2FiX3VzZSwgbmEucm0gPSBUUlVFKSwKICAgIG5vX2FiX3VzZSA9IHN1bSgxIC0gYW55X2FiX3VzZSwgbmEucm0gPSBUUlVFKSwKICAgIC5ncm91cHMgPSAiZHJvcCIKICApICU+JQogIGRwbHlyOjpzZWxlY3QoLWFuaW1hbF90eXBlKSAlPiUKICBhcy5tYXRyaXgoKQoKIyBTZXQgcm93IG5hbWVzIGZvciB0aGUgY29udGluZ2VuY3kgdGFibGUKcm93bmFtZXMoYW5pbWFsX2FiX3RhYmxlKSA8LSBhYl9ieV9hbmltYWwkYW5pbWFsX3R5cGUKCiMgRGlzcGxheSB0aGUgY29udGluZ2VuY3kgdGFibGUKa2FibGUoYW5pbWFsX2FiX3RhYmxlLCBjYXB0aW9uID0gIkNvbnRpbmdlbmN5IFRhYmxlOiBBbnRpYmlvdGljIFVzZSBieSBBbmltYWwgVHlwZSIpICU+JQogIGthYmxlX3N0eWxpbmcoKQoKIyBQZXJmb3JtIGNoaS1zcXVhcmUgdGVzdCBmb3Igb3ZlcmFsbCB1c2UKYW5pbWFsX2NoaV90ZXN0IDwtIGNoaXNxLnRlc3QoYW5pbWFsX2FiX3RhYmxlKQoKIyBEaXNwbGF5IHJlc3VsdHMKY2F0KCJDaGktc3F1YXJlIHRlc3QgZm9yIGRpZmZlcmVuY2VzIGluIG92ZXJhbGwgYW50aWJpb3RpYyB1c2UgYW1vbmcgYW5pbWFsIHR5cGVzOlxuIikKY2F0KCJDaGktc3F1YXJlIHZhbHVlOiIsIGFuaW1hbF9jaGlfdGVzdCRzdGF0aXN0aWMsICJcbiIpCmNhdCgiRGVncmVlcyBvZiBmcmVlZG9tOiIsIGFuaW1hbF9jaGlfdGVzdCRwYXJhbWV0ZXIsICJcbiIpCmNhdCgiUC12YWx1ZToiLCBhbmltYWxfY2hpX3Rlc3QkcC52YWx1ZSwgIlxuIikKY2F0KCJJbnRlcnByZXRhdGlvbjoiLCBpZmVsc2UoYW5pbWFsX2NoaV90ZXN0JHAudmFsdWUgPCAwLjA1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGluIGFudGliaW90aWMgdXNlIGFtb25nIGFuaW1hbCB0eXBlcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm8gc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgaW4gYW50aWJpb3RpYyB1c2UgYW1vbmcgYW5pbWFsIHR5cGVzIiksICJcbiIpCgojIENhbGN1bGF0ZSBDcmFtZXIncyBWIGZvciBlZmZlY3Qgc2l6ZQpjcmFtZXJzX3YgPC0gc3FydChhbmltYWxfY2hpX3Rlc3Qkc3RhdGlzdGljIC8gKHN1bShhbmltYWxfYWJfdGFibGUpICogKG1pbihkaW0oYW5pbWFsX2FiX3RhYmxlKSkgLSAxKSkpCmNhdCgiRWZmZWN0IHNpemUgKENyYW1lcidzIFYpOiIsIGNyYW1lcnNfdiwgIlxuIikKY2F0KCJJbnRlcnByZXRhdGlvbiBvZiBlZmZlY3Qgc2l6ZToiLCAKICAgIGNhc2Vfd2hlbigKICAgICAgY3JhbWVyc192IDwgMC4xIH4gIk5lZ2xpZ2libGUgZWZmZWN0IiwKICAgICAgY3JhbWVyc192IDwgMC4zIH4gIlNtYWxsIGVmZmVjdCIsCiAgICAgIGNyYW1lcnNfdiA8IDAuNSB+ICJNZWRpdW0gZWZmZWN0IiwKICAgICAgVFJVRSB+ICJMYXJnZSBlZmZlY3QiCiAgICApLCAiXG4iKQoKIyBDaGktc3F1YXJlIHRlc3RzIGZvciBlYWNoIHB1cnBvc2Ugb2YgYW50aWJpb3RpYyB1c2UKIyAxLiBUcmVhdG1lbnQgcHVycG9zZQp0cmVhdG1lbnRfdGFibGUgPC0gZmFybV9kYXRhICU+JQogIGZpbHRlcighaXMubmEoYW5pbWFsX3R5cGUpKSAlPiUKICBncm91cF9ieShhbmltYWxfdHlwZSkgJT4lCiAgc3VtbWFyaXNlKAogICAgdHJlYXRtZW50ID0gc3VtKGFiX3RyZWF0bWVudCwgbmEucm0gPSBUUlVFKSwKICAgIG5vX3RyZWF0bWVudCA9IHN1bSgxIC0gYWJfdHJlYXRtZW50LCBuYS5ybSA9IFRSVUUpLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgJT4lCiAgZHBseXI6OnNlbGVjdCgtYW5pbWFsX3R5cGUpICU+JQogIGFzLm1hdHJpeCgpCgpyb3duYW1lcyh0cmVhdG1lbnRfdGFibGUpIDwtIGFiX2J5X2FuaW1hbCRhbmltYWxfdHlwZQoKIyBQZXJmb3JtIGNoaS1zcXVhcmUgdGVzdCBmb3IgdHJlYXRtZW50IHB1cnBvc2UKdHJlYXRtZW50X2NoaV90ZXN0IDwtIGNoaXNxLnRlc3QodHJlYXRtZW50X3RhYmxlKQoKIyAyLiBQcmV2ZW50aW9uIHB1cnBvc2UKcHJldmVudGlvbl90YWJsZSA8LSBmYXJtX2RhdGEgJT4lCiAgZmlsdGVyKCFpcy5uYShhbmltYWxfdHlwZSkpICU+JQogIGdyb3VwX2J5KGFuaW1hbF90eXBlKSAlPiUKICBzdW1tYXJpc2UoCiAgICBwcmV2ZW50aW9uID0gc3VtKGFiX3ByZXZlbnRpb24sIG5hLnJtID0gVFJVRSksCiAgICBub19wcmV2ZW50aW9uID0gc3VtKDEgLSBhYl9wcmV2ZW50aW9uLCBuYS5ybSA9IFRSVUUpLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgJT4lCiAgZHBseXI6OnNlbGVjdCgtYW5pbWFsX3R5cGUpICU+JQogIGFzLm1hdHJpeCgpCgpyb3duYW1lcyhwcmV2ZW50aW9uX3RhYmxlKSA8LSBhYl9ieV9hbmltYWwkYW5pbWFsX3R5cGUKCiMgUGVyZm9ybSBjaGktc3F1YXJlIHRlc3QgZm9yIHByZXZlbnRpb24gcHVycG9zZQpwcmV2ZW50aW9uX2NoaV90ZXN0IDwtIGNoaXNxLnRlc3QocHJldmVudGlvbl90YWJsZSkKCiMgMy4gR3Jvd3RoIHByb21vdGlvbiBwdXJwb3NlCmdyb3d0aF90YWJsZSA8LSBmYXJtX2RhdGEgJT4lCiAgZmlsdGVyKCFpcy5uYShhbmltYWxfdHlwZSkpICU+JQogIGdyb3VwX2J5KGFuaW1hbF90eXBlKSAlPiUKICBzdW1tYXJpc2UoCiAgICBncm93dGggPSBzdW0oYWJfZ3Jvd3RoLCBuYS5ybSA9IFRSVUUpLAogICAgbm9fZ3Jvd3RoID0gc3VtKDEgLSBhYl9ncm93dGgsIG5hLnJtID0gVFJVRSksCiAgICAuZ3JvdXBzID0gImRyb3AiCiAgKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1hbmltYWxfdHlwZSkgJT4lCiAgYXMubWF0cml4KCkKCnJvd25hbWVzKGdyb3d0aF90YWJsZSkgPC0gYWJfYnlfYW5pbWFsJGFuaW1hbF90eXBlCgojIFBlcmZvcm0gY2hpLXNxdWFyZSB0ZXN0IGZvciBncm93dGggcHJvbW90aW9uIHB1cnBvc2UKZ3Jvd3RoX2NoaV90ZXN0IDwtIGNoaXNxLnRlc3QoZ3Jvd3RoX3RhYmxlKQoKIyBDcmVhdGUgYSBzdW1tYXJ5IHRhYmxlIG9mIGNoaS1zcXVhcmUgdGVzdCByZXN1bHRzCmNoaV9zdW1tYXJ5IDwtIGRhdGEuZnJhbWUoCiAgUHVycG9zZSA9IGMoIk92ZXJhbGwgVXNlIiwgIlRyZWF0bWVudCIsICJQcmV2ZW50aW9uIiwgIkdyb3d0aCBQcm9tb3Rpb24iKSwKICBDaGlTcXVhcmUgPSBjKAogICAgYW5pbWFsX2NoaV90ZXN0JHN0YXRpc3RpYywKICAgIHRyZWF0bWVudF9jaGlfdGVzdCRzdGF0aXN0aWMsCiAgICBwcmV2ZW50aW9uX2NoaV90ZXN0JHN0YXRpc3RpYywKICAgIGdyb3d0aF9jaGlfdGVzdCRzdGF0aXN0aWMKICApLAogIERGID0gYygKICAgIGFuaW1hbF9jaGlfdGVzdCRwYXJhbWV0ZXIsCiAgICB0cmVhdG1lbnRfY2hpX3Rlc3QkcGFyYW1ldGVyLAogICAgcHJldmVudGlvbl9jaGlfdGVzdCRwYXJhbWV0ZXIsCiAgICBncm93dGhfY2hpX3Rlc3QkcGFyYW1ldGVyCiAgKSwKICBQVmFsdWUgPSBjKAogICAgYW5pbWFsX2NoaV90ZXN0JHAudmFsdWUsCiAgICB0cmVhdG1lbnRfY2hpX3Rlc3QkcC52YWx1ZSwKICAgIHByZXZlbnRpb25fY2hpX3Rlc3QkcC52YWx1ZSwKICAgIGdyb3d0aF9jaGlfdGVzdCRwLnZhbHVlCiAgKSwKICBTaWduaWZpY2FudCA9IGMoCiAgICBhbmltYWxfY2hpX3Rlc3QkcC52YWx1ZSA8IDAuMDUsCiAgICB0cmVhdG1lbnRfY2hpX3Rlc3QkcC52YWx1ZSA8IDAuMDUsCiAgICBwcmV2ZW50aW9uX2NoaV90ZXN0JHAudmFsdWUgPCAwLjA1LAogICAgZ3Jvd3RoX2NoaV90ZXN0JHAudmFsdWUgPCAwLjA1CiAgKQopCgojIERpc3BsYXkgdGhlIHN1bW1hcnkgdGFibGUKY2hpX3N1bW1hcnkgJT4lCiAgbXV0YXRlKAogICAgQ2hpU3F1YXJlID0gcm91bmQoQ2hpU3F1YXJlLCAyKSwKICAgIFBWYWx1ZSA9IHJvdW5kKFBWYWx1ZSwgNCksCiAgICBTaWduaWZpY2FudCA9IGlmZWxzZShTaWduaWZpY2FudCwgIlllcyIsICJObyIpCiAgKSAlPiUKICBrYWJsZShjYXB0aW9uID0gIkNoaS1zcXVhcmUgVGVzdHMgZm9yIERpZmZlcmVuY2VzIGluIEFudGliaW90aWMgVXNlIFB1cnBvc2VzIEFtb25nIEFuaW1hbCBUeXBlcyIsCiAgICAgICAgY29sLm5hbWVzID0gYygiUHVycG9zZSIsICJDaGktU3F1YXJlIFZhbHVlIiwgIkRlZ3JlZXMgb2YgRnJlZWRvbSIsICJQLVZhbHVlIiwgIlNpZ25pZmljYW50IikpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRkFMU0UpCgojIyMgVmlzdWFsaXphdGlvbiBvZiBBbnRpYmlvdGljIFVzZSBQYXR0ZXJucyBieSBBbmltYWwgVHlwZQoKIyBQcmVwYXJlIGRhdGEgZm9yIHZpc3VhbGl6YXRpb24KYW5pbWFsX3VzZV9sb25nIDwtIGFiX2J5X2FuaW1hbCAlPiUKICBkcGx5cjo6c2VsZWN0KGFuaW1hbF90eXBlLCBhYl90cmVhdG1lbnRfcGN0LCBhYl9wcmV2ZW50aW9uX3BjdCwgYWJfZ3Jvd3RoX3BjdCkgJT4lCiAgZ2F0aGVyKGtleSA9ICJwdXJwb3NlIiwgdmFsdWUgPSAicGVyY2VudGFnZSIsIC1hbmltYWxfdHlwZSkgJT4lCiAgbXV0YXRlKAogICAgcHVycG9zZSA9IGNhc2Vfd2hlbigKICAgICAgcHVycG9zZSA9PSAiYWJfdHJlYXRtZW50X3BjdCIgfiAiVHJlYXRtZW50IiwKICAgICAgcHVycG9zZSA9PSAiYWJfcHJldmVudGlvbl9wY3QiIH4gIlByZXZlbnRpb24iLAogICAgICBwdXJwb3NlID09ICJhYl9ncm93dGhfcGN0IiB+ICJHcm93dGggUHJvbW90aW9uIgogICAgKQogICkKCiMgQ3JlYXRlIGdyb3VwZWQgYmFyIGNoYXJ0CmdncGxvdChhbmltYWxfdXNlX2xvbmcsIGFlcyh4ID0gYW5pbWFsX3R5cGUsIHkgPSBwZXJjZW50YWdlLCBmaWxsID0gcHVycG9zZSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChyb3VuZChwZXJjZW50YWdlLCAxKSwgIiUiKSksIAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSwgdmp1c3QgPSAtMC41LCBzaXplID0gMykgKwogIGxhYnModGl0bGUgPSAiQW50aWJpb3RpYyBVc2UgUHVycG9zZSBieSBBbmltYWwgVHlwZSIsCiAgICAgICB4ID0gIkFuaW1hbCBUeXBlIiwKICAgICAgIHkgPSAiUGVyY2VudGFnZSBvZiBGYXJtcyAoJSkiLAogICAgICAgZmlsbCA9ICJQdXJwb3NlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJCbHVlcyIpICsKICB5bGltKDAsIG1heChhbmltYWxfdXNlX2xvbmckcGVyY2VudGFnZSkgKiAxLjIpICAjIEFkZCBzb21lIHNwYWNlIGZvciBsYWJlbHMKCiMgQ3JlYXRlIGEgaGVhdG1hcCBvZiBzcGVjaWZpYyBhbnRpYmlvdGljIHVzZSBieSBhbmltYWwgdHlwZQpzcGVjaWZpY19hYl9sb25nIDwtIHNwZWNpZmljX2FiX2J5X2FuaW1hbCAlPiUKICBkcGx5cjo6c2VsZWN0KC1uKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC1hbmltYWxfdHlwZSwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gImFudGliaW90aWMiLCAKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInBlcmNlbnRhZ2UiKSAlPiUKICBtdXRhdGUoCiAgICBhbnRpYmlvdGljID0gY2FzZV93aGVuKAogICAgICBhbnRpYmlvdGljID09ICJjaGxvX3BjdCIgfiAiQ2hsb3JhbXBoZW5pY29sIiwKICAgICAgYW50aWJpb3RpYyA9PSAibml0cl9wY3QiIH4gIk5pdHJvZnVyYW5zIiwKICAgICAgYW50aWJpb3RpYyA9PSAiZGltZV9wY3QiIH4gIkRpbWV0cmlkYXpvbGUiLAogICAgICBhbnRpYmlvdGljID09ICJtZXRyX3BjdCIgfiAiTWV0cm9uaWRhem9sZSIsCiAgICAgIGFudGliaW90aWMgPT0gImNpcHJfcGN0IiB+ICJDaXByb2Zsb3hhY2luIiwKICAgICAgYW50aWJpb3RpYyA9PSAib2Zsb19wY3QiIH4gIk9mbG94YWNpbiIsCiAgICAgIGFudGliaW90aWMgPT0gImNhcmJfcGN0IiB+ICJDYXJiYWRveCIsCiAgICAgIGFudGliaW90aWMgPT0gIm9sYXFfcGN0IiB+ICJPbGFxdWluZG94IiwKICAgICAgYW50aWJpb3RpYyA9PSAiYmFjaV9wY3QiIH4gIkJhY2l0cmFjaW4iLAogICAgICBUUlVFIH4gYW50aWJpb3RpYwogICAgKQogICkKCiMgQ3JlYXRlIGhlYXRtYXAgdmlzdWFsaXphdGlvbgpnZ3Bsb3Qoc3BlY2lmaWNfYWJfbG9uZywgYWVzKHggPSBhbmltYWxfdHlwZSwgeSA9IGFudGliaW90aWMsIGZpbGwgPSBwZXJjZW50YWdlKSkgKwogIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQocGVyY2VudGFnZSwgMSkpLCBzaXplID0gMykgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gIndoaXRlIiwgaGlnaCA9ICJzdGVlbGJsdWUiKSArCiAgbGFicyh0aXRsZSA9ICJIZWF0bWFwIG9mIFNwZWNpZmljIEFudGliaW90aWMgVXNlIGJ5IEFuaW1hbCBUeXBlIiwKICAgICAgIHggPSAiQW5pbWFsIFR5cGUiLAogICAgICAgeSA9ICJBbnRpYmlvdGljIiwKICAgICAgIGZpbGwgPSAiUHJldmFsZW5jZSAoJSkiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMC41KSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpCgojIEFkZGl0aW9uYWwgYW5hbHlzaXM6IFBhaXJ3aXNlIGNvbXBhcmlzb25zIHVzaW5nIHBvc3QtaG9jIHRlc3RzCiMgT25seSBwZXJmb3JtIGlmIG92ZXJhbGwgY2hpLXNxdWFyZSBpcyBzaWduaWZpY2FudAppZihhbmltYWxfY2hpX3Rlc3QkcC52YWx1ZSA8IDAuMDUpIHsKICAjIFByZXBhcmUgZGF0YSBmb3IgcGFpcndpc2UgY29tcGFyaXNvbnMKICBhbmltYWxfdHlwZXMgPC0gdW5pcXVlKGZhcm1fZGF0YSRhbmltYWxfdHlwZVshaXMubmEoZmFybV9kYXRhJGFuaW1hbF90eXBlKV0pCiAgcGFpcndpc2VfcmVzdWx0cyA8LSBkYXRhLmZyYW1lKAogICAgQ29tcGFyaXNvbiA9IGNoYXJhY3RlcigpLAogICAgQ2hpU3F1YXJlID0gbnVtZXJpYygpLAogICAgUFZhbHVlID0gbnVtZXJpYygpLAogICAgU2lnbmlmaWNhbnQgPSBjaGFyYWN0ZXIoKSwKICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQogICkKICAKICAjIFBlcmZvcm0gcGFpcndpc2UgY29tcGFyaXNvbnMgZm9yIGVhY2ggcGFpciBvZiBhbmltYWwgdHlwZXMKICBmb3IoaSBpbiAxOihsZW5ndGgoYW5pbWFsX3R5cGVzKS0xKSkgewogICAgZm9yKGogaW4gKGkrMSk6bGVuZ3RoKGFuaW1hbF90eXBlcykpIHsKICAgICAgIyBTdWJzZXQgZGF0YSBmb3IgY3VycmVudCBwYWlyCiAgICAgIHBhaXJfZGF0YSA8LSBmYXJtX2RhdGEgJT4lCiAgICAgICAgZmlsdGVyKGFuaW1hbF90eXBlICVpbiUgYyhhbmltYWxfdHlwZXNbaV0sIGFuaW1hbF90eXBlc1tqXSkpICU+JQogICAgICAgIGRyb3BsZXZlbHMoKQogICAgICAKICAgICAgIyBDcmVhdGUgY29udGluZ2VuY3kgdGFibGUKICAgICAgcGFpcl90YWJsZSA8LSB0YWJsZShwYWlyX2RhdGEkYW5pbWFsX3R5cGUsIHBhaXJfZGF0YSRhbnlfYWJfdXNlKQogICAgICAKICAgICAgIyBQZXJmb3JtIGNoaS1zcXVhcmUgdGVzdAogICAgICBwYWlyX3Rlc3QgPC0gY2hpc3EudGVzdChwYWlyX3RhYmxlKQogICAgICAKICAgICAgIyBTdG9yZSByZXN1bHRzCiAgICAgIHBhaXJ3aXNlX3Jlc3VsdHMgPC0gcmJpbmQocGFpcndpc2VfcmVzdWx0cywgZGF0YS5mcmFtZSgKICAgICAgICBDb21wYXJpc29uID0gcGFzdGUoYW5pbWFsX3R5cGVzW2ldLCAidnMiLCBhbmltYWxfdHlwZXNbal0pLAogICAgICAgIENoaVNxdWFyZSA9IHBhaXJfdGVzdCRzdGF0aXN0aWMsCiAgICAgICAgUFZhbHVlID0gcGFpcl90ZXN0JHAudmFsdWUsCiAgICAgICAgU2lnbmlmaWNhbnQgPSBpZmVsc2UocGFpcl90ZXN0JHAudmFsdWUgPCAwLjA1LzMsICJZZXMiLCAiTm8iKSwgICMgQm9uZmVycm9uaSBjb3JyZWN0aW9uCiAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCiAgICAgICkpCiAgICB9CiAgfQogIAogICMgRGlzcGxheSBwYWlyd2lzZSBjb21wYXJpc29uIHJlc3VsdHMKICBwYWlyd2lzZV9yZXN1bHRzICU+JQogICAgbXV0YXRlKAogICAgICBDaGlTcXVhcmUgPSByb3VuZChDaGlTcXVhcmUsIDIpLAogICAgICBQVmFsdWUgPSByb3VuZChQVmFsdWUsIDQpCiAgICApICU+JQogICAga2FibGUoY2FwdGlvbiA9ICJQYWlyd2lzZSBDb21wYXJpc29ucyBvZiBBbnRpYmlvdGljIFVzZSBCZXR3ZWVuIEFuaW1hbCBUeXBlcyAod2l0aCBCb25mZXJyb25pIGNvcnJlY3Rpb24pIikgJT4lCiAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQp9CmBgYAoKIyMgUmVzdWx0cyBmb3IgSHlwb3RoZXNpcyAxLjM6IE5vbi1saW5lYXIgUmVsYXRpb25zaGlwIEJldHdlZW4gRmFybSBTaXplIGFuZCBBbnRpYmlvdGljIFVzZQoKYGBge3IgaDN9CmlmKCFleGlzdHMoImZhcm1fZGF0YSIpKSB7CiAgZmFybV9kYXRhIDwtIHJlYWRSRFMoaGVyZSgiZGF0YSIsICJwcm9jZXNzZWQiLCAiZmFybV9kYXRhX3Byb2Nlc3NlZC5yZHMiKSkKfQoKIyBDYWxjdWxhdGUgYW50aWJpb3RpYyB1c2UgcHJldmFsZW5jZSBieSBmYXJtIHNpemUgY2F0ZWdvcnkKYWJfYnlfc2l6ZSA8LSBmYXJtX2RhdGEgJT4lCiAgZ3JvdXBfYnkoZmFybV9zaXplX2NhdCkgJT4lCiAgc3VtbWFyaXNlKAogICAgbiA9IG4oKSwKICAgIGFiX3VzZV9hbnlfbiA9IHN1bShhbnlfYWJfdXNlLCBuYS5ybSA9IFRSVUUpLAogICAgYWJfdXNlX2FueV9wY3QgPSBtZWFuKGFueV9hYl91c2UsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBhYl90cmVhdG1lbnRfcGN0ID0gbWVhbihhYl90cmVhdG1lbnQsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBhYl9wcmV2ZW50aW9uX3BjdCA9IG1lYW4oYWJfcHJldmVudGlvbiwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIGFiX2dyb3d0aF9wY3QgPSBtZWFuKGFiX2dyb3d0aCwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIC5ncm91cHMgPSAiZHJvcCIKICApICU+JQogIGZpbHRlcighaXMubmEoZmFybV9zaXplX2NhdCkpICAjIFJlbW92ZSBOQSBmYXJtIHNpemVzCgojIERpc3BsYXkgcmVzdWx0cwphYl9ieV9zaXplICU+JQogIGthYmxlKGNhcHRpb24gPSAiQW50aWJpb3RpYyBVc2UgYnkgRmFybSBTaXplIENhdGVnb3J5IiwKICAgICAgICBjb2wubmFtZXMgPSBjKCJGYXJtIFNpemUiLCAiTnVtYmVyIG9mIEZhcm1zIiwgIkZhcm1zIFVzaW5nIEFudGliaW90aWNzIiwgCiAgICAgICAgICAgICAgICAgICAgICAiJSBBbnkgVXNlIiwgIiUgVHJlYXRtZW50IiwgIiUgUHJldmVudGlvbiIsICIlIEdyb3d0aCBQcm9tb3Rpb24iKSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkKCiMgQ2hpLXNxdWFyZSB0ZXN0IGZvciBhc3NvY2lhdGlvbiBiZXR3ZWVuIGZhcm0gc2l6ZSBjYXRlZ29yeSBhbmQgYW50aWJpb3RpYyB1c2UKc2l6ZV9jaGlfdGFibGUgPC0gZmFybV9kYXRhICU+JQogIGZpbHRlcighaXMubmEoZmFybV9zaXplX2NhdCkpICU+JQogIGdyb3VwX2J5KGZhcm1fc2l6ZV9jYXQpICU+JQogIHN1bW1hcmlzZSgKICAgIGFiX3VzZSA9IHN1bShhbnlfYWJfdXNlLCBuYS5ybSA9IFRSVUUpLAogICAgbm9fYWJfdXNlID0gc3VtKDEgLSBhbnlfYWJfdXNlLCBuYS5ybSA9IFRSVUUpLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgJT4lCiAgZHBseXI6OnNlbGVjdCgtZmFybV9zaXplX2NhdCkgJT4lCiAgYXMubWF0cml4KCkKCnJvd25hbWVzKHNpemVfY2hpX3RhYmxlKSA8LSBhYl9ieV9zaXplJGZhcm1fc2l6ZV9jYXQKCiMgRGlzcGxheSB0aGUgY29udGluZ2VuY3kgdGFibGUKa2FibGUoc2l6ZV9jaGlfdGFibGUsIGNhcHRpb24gPSAiQ29udGluZ2VuY3kgVGFibGU6IEFudGliaW90aWMgVXNlIGJ5IEZhcm0gU2l6ZSBDYXRlZ29yeSIpICU+JQogIGthYmxlX3N0eWxpbmcoKQoKIyBQZXJmb3JtIGNoaS1zcXVhcmUgdGVzdApzaXplX2NoaV90ZXN0IDwtIGNoaXNxLnRlc3Qoc2l6ZV9jaGlfdGFibGUpCgojIERpc3BsYXkgcmVzdWx0cwpjYXQoIkNoaS1zcXVhcmUgdGVzdCBmb3IgZGlmZmVyZW5jZXMgaW4gYW50aWJpb3RpYyB1c2UgYW1vbmcgZmFybSBzaXplIGNhdGVnb3JpZXM6XG4iKQpjYXQoIkNoaS1zcXVhcmUgdmFsdWU6Iiwgc2l6ZV9jaGlfdGVzdCRzdGF0aXN0aWMsICJcbiIpCmNhdCgiRGVncmVlcyBvZiBmcmVlZG9tOiIsIHNpemVfY2hpX3Rlc3QkcGFyYW1ldGVyLCAiXG4iKQpjYXQoIlAtdmFsdWU6Iiwgc2l6ZV9jaGlfdGVzdCRwLnZhbHVlLCAiXG4iKQpjYXQoIkludGVycHJldGF0aW9uOiIsIGlmZWxzZShzaXplX2NoaV90ZXN0JHAudmFsdWUgPCAwLjA1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgaW4gYW50aWJpb3RpYyB1c2UgYW1vbmcgZmFybSBzaXplIGNhdGVnb3JpZXMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm8gc2lnbmlmaWNhbnQgZGlmZmVyZW5jZXMgaW4gYW50aWJpb3RpYyB1c2UgYW1vbmcgZmFybSBzaXplIGNhdGVnb3JpZXMiKSwgIlxuIikKCiMgQ2FsY3VsYXRlIENyYW1lcidzIFYgZm9yIGVmZmVjdCBzaXplCmNyYW1lcnNfdiA8LSBzcXJ0KHNpemVfY2hpX3Rlc3Qkc3RhdGlzdGljIC8gKHN1bShzaXplX2NoaV90YWJsZSkgKiAobWluKGRpbShzaXplX2NoaV90YWJsZSkpIC0gMSkpKQpjYXQoIkVmZmVjdCBzaXplIChDcmFtZXIncyBWKToiLCBjcmFtZXJzX3YsICJcbiIpCmNhdCgiSW50ZXJwcmV0YXRpb24gb2YgZWZmZWN0IHNpemU6IiwgCiAgICBjYXNlX3doZW4oCiAgICAgIGNyYW1lcnNfdiA8IDAuMSB+ICJOZWdsaWdpYmxlIGVmZmVjdCIsCiAgICAgIGNyYW1lcnNfdiA8IDAuMyB+ICJTbWFsbCBlZmZlY3QiLAogICAgICBjcmFtZXJzX3YgPCAwLjUgfiAiTWVkaXVtIGVmZmVjdCIsCiAgICAgIFRSVUUgfiAiTGFyZ2UgZWZmZWN0IgogICAgKSwgIlxuIikKCiMjIyBMT0VTUyBTbW9vdGhpbmcgZm9yIE5vbi1saW5lYXIgUmVsYXRpb25zaGlwCgojIFByZXBhcmUgZGF0YSBmb3IgTE9FU1Mgc21vb3RoaW5nCnNpemVfYWJfZGF0YSA8LSBmYXJtX2RhdGEgJT4lCiAgZmlsdGVyKCFpcy5uYShhcmVhX2Zhcm0pICYgIWlzLm5hKGFueV9hYl91c2UpKSAlPiUKICBkcGx5cjo6c2VsZWN0KGFyZWFfZmFybSwgYW55X2FiX3VzZSwgYWJfdHJlYXRtZW50LCBhYl9wcmV2ZW50aW9uLCBhYl9ncm93dGgpCgojIENyZWF0ZSBMT0VTUyBzbW9vdGhlZCBjdXJ2ZSBmb3Igb3ZlcmFsbCBhbnRpYmlvdGljIHVzZQpvdmVyYWxsX3Bsb3QgPC0gZ2dwbG90KHNpemVfYWJfZGF0YSwgYWVzKHggPSBhcmVhX2Zhcm0sIHkgPSBhbnlfYWJfdXNlKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBzZSA9IFRSVUUpICsKICBsYWJzKHRpdGxlID0gIk5vbi1saW5lYXIgUmVsYXRpb25zaGlwIEJldHdlZW4gRmFybSBTaXplIGFuZCBBbnRpYmlvdGljIFVzZSIsCiAgICAgICBzdWJ0aXRsZSA9ICJMT0VTUyBTbW9vdGhpbmcgQ3VydmUgd2l0aCA5NSUgQ29uZmlkZW5jZSBJbnRlcnZhbCIsCiAgICAgICB4ID0gIkZhcm0gQXJlYSAoc3F1YXJlIG1ldGVycykiLAogICAgICAgeSA9ICJQcm9iYWJpbGl0eSBvZiBBbnRpYmlvdGljIFVzZSIpICsKICB0aGVtZV9taW5pbWFsKCkKCiMgUHJpbnQgdGhlIHBsb3QKcHJpbnQob3ZlcmFsbF9wbG90KQoKIyBDcmVhdGUgTE9FU1Mgc21vb3RoZWQgY3VydmVzIGZvciBkaWZmZXJlbnQgcHVycG9zZXMKdHJlYXRtZW50X3Bsb3QgPC0gZ2dwbG90KHNpemVfYWJfZGF0YSwgYWVzKHggPSBhcmVhX2Zhcm0sIHkgPSBhYl90cmVhdG1lbnQpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gVFJVRSkgKwogIGxhYnModGl0bGUgPSAiRmFybSBTaXplIGFuZCBUcmVhdG1lbnQgQW50aWJpb3RpYyBVc2UiLAogICAgICAgeCA9ICJGYXJtIEFyZWEgKHNxdWFyZSBtZXRlcnMpIiwKICAgICAgIHkgPSAiUHJvYmFiaWxpdHkgb2YgVHJlYXRtZW50IFVzZSIpICsKICB0aGVtZV9taW5pbWFsKCkKCnByZXZlbnRpb25fcGxvdCA8LSBnZ3Bsb3Qoc2l6ZV9hYl9kYXRhLCBhZXMoeCA9IGFyZWFfZmFybSwgeSA9IGFiX3ByZXZlbnRpb24pKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gVFJVRSkgKwogIGxhYnModGl0bGUgPSAiRmFybSBTaXplIGFuZCBQcmV2ZW50aXZlIEFudGliaW90aWMgVXNlIiwKICAgICAgIHggPSAiRmFybSBBcmVhIChzcXVhcmUgbWV0ZXJzKSIsCiAgICAgICB5ID0gIlByb2JhYmlsaXR5IG9mIFByZXZlbnRpdmUgVXNlIikgKwogIHRoZW1lX21pbmltYWwoKQoKZ3Jvd3RoX3Bsb3QgPC0gZ2dwbG90KHNpemVfYWJfZGF0YSwgYWVzKHggPSBhcmVhX2Zhcm0sIHkgPSBhYl9ncm93dGgpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMykgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIHNlID0gVFJVRSkgKwogIGxhYnModGl0bGUgPSAiRmFybSBTaXplIGFuZCBHcm93dGggUHJvbW90aW9uIEFudGliaW90aWMgVXNlIiwKICAgICAgIHggPSAiRmFybSBBcmVhIChzcXVhcmUgbWV0ZXJzKSIsCiAgICAgICB5ID0gIlByb2JhYmlsaXR5IG9mIEdyb3d0aCBQcm9tb3Rpb24gVXNlIikgKwogIHRoZW1lX21pbmltYWwoKQoKIyBDb21iaW5lIHBsb3RzIGZvciBwdXJwb3NlcwpwdXJwb3NlX3Bsb3RzIDwtIGdnYXJyYW5nZSh0cmVhdG1lbnRfcGxvdCwgcHJldmVudGlvbl9wbG90LCBncm93dGhfcGxvdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzLCBucm93ID0gMSwgY29tbW9uLmxlZ2VuZCA9IFRSVUUpCgojIFByaW50IGNvbWJpbmVkIHBsb3QKcHJpbnQocHVycG9zZV9wbG90cykKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMgRW5oYW5jaW5nIEh5cG90aGVzaXMgMS4zOiBOb24tbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGZhcm0gc2l6ZSAKIyBhbmQgYW50aWJpb3RpYyB1c2Ug4oCTIENhdXNhbCBpbmZlcmVuY2UgYW5hbHlzaXMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgSW5zZXJ0IGFmdGVyIHRoZSAiIyMjIExPRVNTIFNtb290aGluZyBmb3IgTm9uLWxpbmVhciBSZWxhdGlvbnNoaXAiIAojIHNlY3Rpb24gaW4gdGhlIGgxLTMtYW5hbHlzaXMuUiBzY3JpcHQKIyBUaGlzIGNvZGUgc3RyZW5ndGhlbnMgY2F1c2FsIGluZmVyZW5jZSByZWdhcmRpbmcgZmFybSBzaXplIGFuZCBhbnRpYmlvdGljIHVzZQojIGJ5IGNvbnRyb2xsaW5nIGZvciBjb25mb3VuZGVycyBhbmQgY29uZHVjdGluZyBkZWVwZXIgYW5hbHlzZXMKCiMjIyBNdWx0aXZhcmlhdGUgQW5hbHlzaXM6IE5vbi1saW5lYXIgUmVsYXRpb25zaGlwIENvbnRyb2xsaW5nIGZvciBDb25mb3VuZGVycwoKIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMKaWYoIXJlcXVpcmVOYW1lc3BhY2UoIm1nY3YiLCBxdWlldGx5ID0gVFJVRSkpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJtZ2N2IikKfQpsaWJyYXJ5KG1nY3YpCgojIERhdGEgcHJlcGFyYXRpb24KZ2FtX2RhdGEgPC0gZmFybV9kYXRhICU+JQogIGZpbHRlcighaXMubmEoYXJlYV9mYXJtKSAmICFpcy5uYShhbnlfYWJfdXNlKSAmICFpcy5uYShhbmltYWxfdHlwZSkgJiAhaXMubmEoZWR1KSkKCiMgRml0IEdlbmVyYWxpemVkIEFkZGl0aXZlIE1vZGVsIChHQU0pIGNvbnRyb2xsaW5nIGZvciBhbmltYWwgdHlwZSBhbmQgZWR1Y2F0aW9uIGxldmVsCmNhdCgiRml0dGluZyBHZW5lcmFsaXplZCBBZGRpdGl2ZSBNb2RlbCAoR0FNKSBjb250cm9sbGluZyBmb3IgY29uZm91bmRlcnMuLi5cbiIpCmdhbV9tb2RlbCA8LSB0cnlDYXRjaCh7CiAgZ2FtKGFueV9hYl91c2UgfiBzKGFyZWFfZmFybSkgKyBhbmltYWxfdHlwZSArIGVkdSwgCiAgICAgZmFtaWx5ID0gYmlub21pYWwsIGRhdGEgPSBnYW1fZGF0YSkKfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7CiAgbWVzc2FnZSgiR0FNIG1vZGVsIGZpdHRpbmcgZmFpbGVkOiAiLCBlJG1lc3NhZ2UpCiAgcmV0dXJuKE5VTEwpCn0pCgojIERpc3BsYXkgbW9kZWwgc3VtbWFyeQppZighaXMubnVsbChnYW1fbW9kZWwpKSB7CiAgcHJpbnQoc3VtbWFyeShnYW1fbW9kZWwpKQogIAogICMgVmlzdWFsaXphdGlvbiBvZiBhZGp1c3RlZCBub24tbGluZWFyIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGZhcm0gc2l6ZSBhbmQgYW50aWJpb3RpYyB1c2UKICBwbG90X2RhdGEgPC0gZXhwYW5kLmdyaWQoCiAgICBhcmVhX2Zhcm0gPSBzZXEobWluKGdhbV9kYXRhJGFyZWFfZmFybSwgbmEucm0gPSBUUlVFKSwgCiAgICAgICAgICAgICAgICAgICAgbWF4KGdhbV9kYXRhJGFyZWFfZmFybSwgbmEucm0gPSBUUlVFKSwgbGVuZ3RoLm91dCA9IDEwMCksCiAgICBhbmltYWxfdHlwZSA9IHVuaXF1ZShnYW1fZGF0YSRhbmltYWxfdHlwZSksCiAgICBlZHUgPSBtZWRpYW4oZ2FtX2RhdGEkZWR1LCBuYS5ybSA9IFRSVUUpCiAgKQogIAogICMgUHJlZGljdCB2YWx1ZXMKICBwbG90X2RhdGEkcHJlZGljdGVkIDwtIHByZWRpY3QoZ2FtX21vZGVsLCBuZXdkYXRhID0gcGxvdF9kYXRhLCB0eXBlID0gInJlc3BvbnNlIikKICAKICAjIFBsb3QgYWRqdXN0ZWQgbm9uLWxpbmVhciByZWxhdGlvbnNoaXBzIGJ5IGFuaW1hbCB0eXBlCiAgYWRqdXN0ZWRfcGxvdCA8LSBnZ3Bsb3QocGxvdF9kYXRhLCBhZXMoeCA9IGFyZWFfZmFybSwgeSA9IHByZWRpY3RlZCwgY29sb3IgPSBhbmltYWxfdHlwZSkpICsKICAgIGdlb21fbGluZShzaXplID0gMSkgKwogICAgbGFicyh0aXRsZSA9ICJBZGp1c3RlZCBOb24tbGluZWFyIFJlbGF0aW9uc2hpcCBiZXR3ZWVuIEZhcm0gU2l6ZSBhbmQgQW50aWJpb3RpYyBVc2UiLAogICAgICAgICBzdWJ0aXRsZSA9ICJDb250cm9sbGluZyBmb3IgQW5pbWFsIFR5cGUgYW5kIEVkdWNhdGlvbiBMZXZlbCIsCiAgICAgICAgIHggPSAiRmFybSBTaXplIChtwrIpIiwKICAgICAgICAgeSA9ICJQcm9iYWJpbGl0eSBvZiBBbnRpYmlvdGljIFVzZSIsCiAgICAgICAgIGNvbG9yID0gIkFuaW1hbCBUeXBlIikgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKICAKICBwcmludChhZGp1c3RlZF9wbG90KQogIAogICMgT3ZlcmFsbCBlZmZlY3QgcGxvdCB3aXRob3V0IGdyb3VwaW5nCiAgb3ZlcmFsbF9kYXRhIDwtIGV4cGFuZC5ncmlkKAogICAgYXJlYV9mYXJtID0gc2VxKG1pbihnYW1fZGF0YSRhcmVhX2Zhcm0sIG5hLnJtID0gVFJVRSksIAogICAgICAgICAgICAgICAgICAgIG1heChnYW1fZGF0YSRhcmVhX2Zhcm0sIG5hLnJtID0gVFJVRSksIGxlbmd0aC5vdXQgPSAxMDApLAogICAgYW5pbWFsX3R5cGUgPSAiQ2hpY2tlbiIsICMgcmVmZXJlbmNlIGNhdGVnb3J5CiAgICBlZHUgPSBtZWRpYW4oZ2FtX2RhdGEkZWR1LCBuYS5ybSA9IFRSVUUpCiAgKQogIAogIG92ZXJhbGxfZGF0YSRwcmVkaWN0ZWQgPC0gcHJlZGljdChnYW1fbW9kZWwsIG5ld2RhdGEgPSBvdmVyYWxsX2RhdGEsIHR5cGUgPSAicmVzcG9uc2UiKQogIAogICMgRXh0cmFjdCBjb25maWRlbmNlIGludGVydmFscyBmcm9tIHNtb290aCB0ZXJtcwogIHNtb290aF90ZXJtcyA8LSBwbG90KGdhbV9tb2RlbCwgc2VsZWN0ID0gMSwgc2VXaXRoTWVhbiA9IFRSVUUpCiAgc21vb3RoX2RmIDwtIGRhdGEuZnJhbWUoCiAgICBhcmVhX2Zhcm0gPSBzbW9vdGhfdGVybXNbWzFdXSR4LAogICAgZml0ID0gc21vb3RoX3Rlcm1zW1sxXV0kZml0LAogICAgc2UgPSBzbW9vdGhfdGVybXNbWzFdXSRzZQogICkKICAKICAjIENhbGN1bGF0ZSBjb25maWRlbmNlIGludGVydmFscyBvbiBsb2dpdCBzY2FsZQogIHNtb290aF9kZiR1cHBlciA8LSBzbW9vdGhfZGYkZml0ICsgMS45NiAqIHNtb290aF9kZiRzZQogIHNtb290aF9kZiRsb3dlciA8LSBzbW9vdGhfZGYkZml0IC0gMS45NiAqIHNtb290aF9kZiRzZQogIAogICMgQ29udmVydCB0byBwcm9iYWJpbGl0eSBzY2FsZQogIHNtb290aF9kZiRmaXRfcHJvYiA8LSBwbG9naXMoc21vb3RoX2RmJGZpdCkKICBzbW9vdGhfZGYkdXBwZXJfcHJvYiA8LSBwbG9naXMoc21vb3RoX2RmJHVwcGVyKQogIHNtb290aF9kZiRsb3dlcl9wcm9iIDwtIHBsb2dpcyhzbW9vdGhfZGYkbG93ZXIpCiAgCiAgIyBQbG90IHNtb290aCBlZmZlY3Qgd2l0aCBjb25maWRlbmNlIGludGVydmFscwogIHNtb290aF9wbG90IDwtIGdncGxvdCgpICsKICAgIGdlb21fcmliYm9uKGRhdGEgPSBzbW9vdGhfZGYsIAogICAgICAgICAgICAgICAgYWVzKHggPSBhcmVhX2Zhcm0sIHltaW4gPSBsb3dlcl9wcm9iLCB5bWF4ID0gdXBwZXJfcHJvYiksCiAgICAgICAgICAgICAgICBmaWxsID0gImxpZ2h0Ymx1ZSIsIGFscGhhID0gMC4zKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IG92ZXJhbGxfZGF0YSwgYWVzKHggPSBhcmVhX2Zhcm0sIHkgPSBwcmVkaWN0ZWQpLCAKICAgICAgICAgICAgICBjb2xvciA9ICJkYXJrYmx1ZSIsIHNpemUgPSAxKSArCiAgICBsYWJzKHRpdGxlID0gIlNtb290aCBFZmZlY3Qgb2YgRmFybSBTaXplIG9uIEFudGliaW90aWMgVXNlIiwKICAgICAgICAgc3VidGl0bGUgPSAiV2l0aCA5NSUgQ29uZmlkZW5jZSBJbnRlcnZhbCAoQ29udHJvbGxpbmcgZm9yIEFuaW1hbCBUeXBlIGFuZCBFZHVjYXRpb24gTGV2ZWwpIiwKICAgICAgICAgeCA9ICJGYXJtIFNpemUgKG3CsikiLAogICAgICAgICB5ID0gIlByb2JhYmlsaXR5IG9mIEFudGliaW90aWMgVXNlIikgKwogICAgdGhlbWVfbWluaW1hbCgpCiAgCiAgcHJpbnQoc21vb3RoX3Bsb3QpCiAgCiAgIyBJZGVudGlmeSBwb3RlbnRpYWwgYnJlYWtwb2ludCAoaGlnaGVzdCBjdXJ2YXR1cmUpCiAgZGlmZl9kYXRhIDwtIGRhdGEuZnJhbWUoCiAgICBhcmVhX2Zhcm0gPSBvdmVyYWxsX2RhdGEkYXJlYV9mYXJtWy1jKDEsIGxlbmd0aChvdmVyYWxsX2RhdGEkYXJlYV9mYXJtKSldLAogICAgc2Vjb25kX2Rlcml2ID0gZGlmZihkaWZmKG92ZXJhbGxfZGF0YSRwcmVkaWN0ZWQpKQogICkKICBwb3RlbnRpYWxfYnJlYWtwb2ludCA8LSBkaWZmX2RhdGEkYXJlYV9mYXJtW3doaWNoLm1heChhYnMoZGlmZl9kYXRhJHNlY29uZF9kZXJpdikpXQogIGNhdCgiUG90ZW50aWFsIGJyZWFrcG9pbnQgYmFzZWQgb24gY3VydmF0dXJlIGFuYWx5c2lzOiIsIHJvdW5kKHBvdGVudGlhbF9icmVha3BvaW50LCAwKSwgIm3CslxuIikKfQoKIyMjIEFuYWx5c2lzIG9mIEZhcm0gQ2hhcmFjdGVyaXN0aWNzIGFyb3VuZCBCcmVha3BvaW50CgojIFNldCBicmVha3BvaW50IHJhbmdlCmJyZWFrcG9pbnQgPC0gaWZlbHNlKGV4aXN0cygicG90ZW50aWFsX2JyZWFrcG9pbnQiKSwgcG90ZW50aWFsX2JyZWFrcG9pbnQsIDUwMCkKd2luZG93X3NpemUgPC0gMjAwCgojIElkZW50aWZ5IGZhcm1zIGFyb3VuZCBicmVha3BvaW50CnRyYW5zaXRpb25fZmFybXMgPC0gZmFybV9kYXRhICU+JQogIGZpbHRlcihhcmVhX2Zhcm0gPj0gKGJyZWFrcG9pbnQgLSB3aW5kb3dfc2l6ZSkgJiAKICAgICAgICAgICBhcmVhX2Zhcm0gPD0gKGJyZWFrcG9pbnQgKyB3aW5kb3dfc2l6ZSkpCgojIEZhcm1zIGJlZm9yZSwgYXQsIGFuZCBhZnRlciBicmVha3BvaW50CmJlZm9yZV90cmFuc2l0aW9uIDwtIGZhcm1fZGF0YSAlPiUgZmlsdGVyKGFyZWFfZmFybSA8IChicmVha3BvaW50IC0gd2luZG93X3NpemUpKSAlPiUgbXV0YXRlKHRyYW5zaXRpb25fZ3JvdXAgPSAiQmVmb3JlIFRyYW5zaXRpb24iKQphdF90cmFuc2l0aW9uIDwtIHRyYW5zaXRpb25fZmFybXMgJT4lIG11dGF0ZSh0cmFuc2l0aW9uX2dyb3VwID0gIlRyYW5zaXRpb24gWm9uZSIpCmFmdGVyX3RyYW5zaXRpb24gPC0gZmFybV9kYXRhICU+JSBmaWx0ZXIoYXJlYV9mYXJtID4gKGJyZWFrcG9pbnQgKyB3aW5kb3dfc2l6ZSkpICU+JSBtdXRhdGUodHJhbnNpdGlvbl9ncm91cCA9ICJBZnRlciBUcmFuc2l0aW9uIikKCiMgQ29tYmluZSBhbmQgYW5hbHl6ZSBkYXRhCnRyYW5zaXRpb25fYW5hbHlzaXMgPC0gYmluZF9yb3dzKGJlZm9yZV90cmFuc2l0aW9uLCBhdF90cmFuc2l0aW9uLCBhZnRlcl90cmFuc2l0aW9uKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHRyYW5zaXRpb25fZ3JvdXApKQoKIyMjIFNlZ21lbnRlZCBSZWdyZXNzaW9uIEFuYWx5c2lzCgojIEZpdCBhIGxvZ2lzdGljIHJlZ3Jlc3Npb24gbW9kZWwgZmlyc3QKbG9nX21vZGVsIDwtIGdsbShhbnlfYWJfdXNlIH4gYXJlYV9mYXJtLCBkYXRhID0gc2l6ZV9hYl9kYXRhLCBmYW1pbHkgPSBiaW5vbWlhbCkKCiMgU3VtbWFyaXplIHRoZSBtb2RlbApzdW1tYXJ5X2xvZ19tb2RlbCA8LSBzdW1tYXJ5KGxvZ19tb2RlbCkKY2F0KCJMb2dpc3RpYyByZWdyZXNzaW9uIG9mIGFudGliaW90aWMgdXNlIG9uIGZhcm0gc2l6ZTpcbiIpCmNhdCgiQ29lZmZpY2llbnQgZm9yIGZhcm0gc2l6ZToiLCBjb2VmKGxvZ19tb2RlbClbMl0sICJcbiIpCmNhdCgiU3RhbmRhcmQgZXJyb3I6Iiwgc3VtbWFyeV9sb2dfbW9kZWwkY29lZmZpY2llbnRzWzIsIDJdLCAiXG4iKQpjYXQoInAtdmFsdWU6Iiwgc3VtbWFyeV9sb2dfbW9kZWwkY29lZmZpY2llbnRzWzIsIDRdLCAiXG4iKQpjYXQoIk51bGwgZGV2aWFuY2U6Iiwgc3VtbWFyeV9sb2dfbW9kZWwkbnVsbC5kZXZpYW5jZSwgIm9uIiwgc3VtbWFyeV9sb2dfbW9kZWwkZGYubnVsbCwgImRlZ3JlZXMgb2YgZnJlZWRvbVxuIikKY2F0KCJSZXNpZHVhbCBkZXZpYW5jZToiLCBzdW1tYXJ5X2xvZ19tb2RlbCRkZXZpYW5jZSwgIm9uIiwgc3VtbWFyeV9sb2dfbW9kZWwkZGYucmVzaWR1YWwsICJkZWdyZWVzIG9mIGZyZWVkb21cbiIpCmNhdCgiQUlDOiIsIHN1bW1hcnlfbG9nX21vZGVsJGFpYywgIlxuIikKCiMgVHJ5IHRvIGZpdCBhIHNlZ21lbnRlZCBtb2RlbAojIFRoaXMgaXMgd3JhcHBlZCBpbiBhIHRyeUNhdGNoIGJsb2NrIGJlY2F1c2Ugc2VnbWVudGVkIHJlZ3Jlc3Npb24gbWlnaHQgbm90IGNvbnZlcmdlCnRyeUNhdGNoKHsKICBsaWJyYXJ5KHNlZ21lbnRlZCkKICAKICAjIEluaXRpYWwgZ3Vlc3MgZm9yIGJyZWFrcG9pbnQKICBpbml0aWFsX2JwIDwtIG1lZGlhbihzaXplX2FiX2RhdGEkYXJlYV9mYXJtKQogIAogICMgRml0IHNlZ21lbnRlZCBtb2RlbAogIHNlZ21lbnRlZF9tb2RlbCA8LSBzZWdtZW50ZWQobG9nX21vZGVsLCBzZWcuWiA9IH5hcmVhX2Zhcm0sIHBzaSA9IGxpc3QoYXJlYV9mYXJtID0gYyhpbml0aWFsX2JwKSkpCiAgCiAgIyBQcmludCBzdW1tYXJ5CiAgcHJpbnQoc3VtbWFyeShzZWdtZW50ZWRfbW9kZWwpKQogIAogICMgRXh0cmFjdCBicmVha3BvaW50cwogIGJyZWFrcG9pbnRzIDwtIHNlZ21lbnRlZF9tb2RlbCRwc2lbLCAyXQogIGNhdCgiRXN0aW1hdGVkIGJyZWFrcG9pbnQgaW4gZmFybSBzaXplOiIsIGJyZWFrcG9pbnRzLCAic3F1YXJlIG1ldGVyc1xuIikKICAKICAjIEdlbmVyYXRlIHByZWRpY3Rpb25zIGZvciBwbG90dGluZwogIG5ld19kYXRhIDwtIGRhdGEuZnJhbWUoYXJlYV9mYXJtID0gc2VxKG1pbihzaXplX2FiX2RhdGEkYXJlYV9mYXJtKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgoc2l6ZV9hYl9kYXRhJGFyZWFfZmFybSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoLm91dCA9IDEwMCkpCiAgCiAgIyBHZXQgcHJlZGljdGlvbnMgZnJvbSBib3RoIG1vZGVscwogIG5ld19kYXRhJHByZWRfbG9nIDwtIHByZWRpY3QobG9nX21vZGVsLCBuZXdkYXRhID0gbmV3X2RhdGEsIHR5cGUgPSAicmVzcG9uc2UiKQogIG5ld19kYXRhJHByZWRfc2VnIDwtIHByZWRpY3Qoc2VnbWVudGVkX21vZGVsLCBuZXdkYXRhID0gbmV3X2RhdGEsIHR5cGUgPSAicmVzcG9uc2UiKQogIAogICMgUGxvdCBzZWdtZW50ZWQgcmVncmVzc2lvbiByZXN1bHRzIHdpdGggY29tcGFyaXNvbiB0byByZWd1bGFyIGxvZ2lzdGljIHJlZ3Jlc3Npb24KICBzZWdfcGxvdCA8LSBnZ3Bsb3Qoc2l6ZV9hYl9kYXRhLCBhZXMoeCA9IGFyZWFfZmFybSwgeSA9IGFueV9hYl91c2UpKSArCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC4zKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IG5ld19kYXRhLCBhZXMoeCA9IGFyZWFfZmFybSwgeSA9IHByZWRfbG9nLCBjb2xvciA9ICJMb2dpc3RpYyBSZWdyZXNzaW9uIiksIAogICAgICAgICAgICAgIHNpemUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IG5ld19kYXRhLCBhZXMoeCA9IGFyZWFfZmFybSwgeSA9IHByZWRfc2VnLCBjb2xvciA9ICJTZWdtZW50ZWQgUmVncmVzc2lvbiIpLCAKICAgICAgICAgICAgICBzaXplID0gMSkgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYnJlYWtwb2ludHMsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gInJlZCIpICsKICAgIGxhYnModGl0bGUgPSAiU2VnbWVudGVkIFJlZ3Jlc3Npb24gb2YgRmFybSBTaXplIGFuZCBBbnRpYmlvdGljIFVzZSIsCiAgICAgICAgIHN1YnRpdGxlID0gcGFzdGUoIkJyZWFrcG9pbnQgYXQiLCByb3VuZChicmVha3BvaW50cywgMCksICJzcXVhcmUgbWV0ZXJzIiksCiAgICAgICAgIHggPSAiRmFybSBBcmVhIChzcXVhcmUgbWV0ZXJzKSIsCiAgICAgICAgIHkgPSAiUHJvYmFiaWxpdHkgb2YgQW50aWJpb3RpYyBVc2UiLAogICAgICAgICBjb2xvciA9ICJNb2RlbCBUeXBlIikgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJMb2dpc3RpYyBSZWdyZXNzaW9uIiA9ICJibHVlIiwgIlNlZ21lbnRlZCBSZWdyZXNzaW9uIiA9ICJyZWQiKSkKICAKICAjIFByaW50IHRoZSBzZWdtZW50ZWQgcGxvdAogIHByaW50KHNlZ19wbG90KQogIAp9LCBlcnJvciA9IGZ1bmN0aW9uKGUpIHsKICBtZXNzYWdlKCJTZWdtZW50ZWQgcmVncmVzc2lvbiBkaWQgbm90IGNvbnZlcmdlLiBVc2luZyBvbmx5IExPRVNTIHNtb290aGluZyBmb3IgdmlzdWFsaXphdGlvbi4iKQogIHByaW50KGUpCn0pCgojIyMgQWRkaXRpb25hbCBBbmFseXNpczogRmFybSBTaXplIGFuZCBTcGVjaWZpYyBBbnRpYmlvdGljIFR5cGVzCgojIENhbGN1bGF0ZSBzcGVjaWZpYyBhbnRpYmlvdGljIHVzZSBieSBmYXJtIHNpemUgY2F0ZWdvcnkKc3BlY2lmaWNfYWJfYnlfc2l6ZSA8LSBmYXJtX2RhdGEgJT4lCiAgZ3JvdXBfYnkoZmFybV9zaXplX2NhdCkgJT4lCiAgc3VtbWFyaXNlKAogICAgbiA9IG4oKSwKICAgIGNobG9fcGN0ID0gbWVhbihjaGxvLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgbml0cl9wY3QgPSBtZWFuKG5pdHIsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBkaW1lX3BjdCA9IG1lYW4oZGltZSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIG1ldHJfcGN0ID0gbWVhbihtZXRyLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgY2lwcl9wY3QgPSBtZWFuKGNpcHIsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBvZmxvX3BjdCA9IG1lYW4ob2ZsbywgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIGNhcmJfcGN0ID0gbWVhbihjYXJiLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgb2xhcV9wY3QgPSBtZWFuKG9sYXEsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBiYWNpX3BjdCA9IG1lYW4oYmFjaSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIC5ncm91cHMgPSAiZHJvcCIKICApICU+JQogIGZpbHRlcighaXMubmEoZmFybV9zaXplX2NhdCkpCgojIENvbnZlcnQgdG8gbG9uZyBmb3JtYXQgZm9yIHZpc3VhbGl6YXRpb24Kc3BlY2lmaWNfYWJfc2l6ZV9sb25nIDwtIHNwZWNpZmljX2FiX2J5X3NpemUgJT4lCiAgZHBseXI6OnNlbGVjdCgtbikgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtZmFybV9zaXplX2NhdCwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gImFudGliaW90aWMiLCAKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInBlcmNlbnRhZ2UiKSAlPiUKICBtdXRhdGUoCiAgICBhbnRpYmlvdGljID0gY2FzZV93aGVuKAogICAgICBhbnRpYmlvdGljID09ICJjaGxvX3BjdCIgfiAiQ2hsb3JhbXBoZW5pY29sIiwKICAgICAgYW50aWJpb3RpYyA9PSAibml0cl9wY3QiIH4gIk5pdHJvZnVyYW5zIiwKICAgICAgYW50aWJpb3RpYyA9PSAiZGltZV9wY3QiIH4gIkRpbWV0cmlkYXpvbGUiLAogICAgICBhbnRpYmlvdGljID09ICJtZXRyX3BjdCIgfiAiTWV0cm9uaWRhem9sZSIsCiAgICAgIGFudGliaW90aWMgPT0gImNpcHJfcGN0IiB+ICJDaXByb2Zsb3hhY2luIiwKICAgICAgYW50aWJpb3RpYyA9PSAib2Zsb19wY3QiIH4gIk9mbG94YWNpbiIsCiAgICAgIGFudGliaW90aWMgPT0gImNhcmJfcGN0IiB+ICJDYXJiYWRveCIsCiAgICAgIGFudGliaW90aWMgPT0gIm9sYXFfcGN0IiB+ICJPbGFxdWluZG94IiwKICAgICAgYW50aWJpb3RpYyA9PSAiYmFjaV9wY3QiIH4gIkJhY2l0cmFjaW4iLAogICAgICBUUlVFIH4gYW50aWJpb3RpYwogICAgKQogICkKCiMgQ3JlYXRlIGEgaGVhdG1hcCBvZiBzcGVjaWZpYyBhbnRpYmlvdGljIHVzZSBieSBmYXJtIHNpemUKc2l6ZV9oZWF0bWFwIDwtIGdncGxvdChzcGVjaWZpY19hYl9zaXplX2xvbmcsIAogICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IGZhcm1fc2l6ZV9jYXQsIHkgPSBhbnRpYmlvdGljLCBmaWxsID0gcGVyY2VudGFnZSkpICsKICBnZW9tX3RpbGUoY29sb3IgPSAid2hpdGUiKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHJvdW5kKHBlcmNlbnRhZ2UsIDEpKSwgc2l6ZSA9IDMpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJ3aGl0ZSIsIGhpZ2ggPSAic3RlZWxibHVlIikgKwogIGxhYnModGl0bGUgPSAiSGVhdG1hcCBvZiBTcGVjaWZpYyBBbnRpYmlvdGljIFVzZSBieSBGYXJtIFNpemUgQ2F0ZWdvcnkiLAogICAgICAgeCA9ICJGYXJtIFNpemUiLAogICAgICAgeSA9ICJBbnRpYmlvdGljIiwKICAgICAgIGZpbGwgPSAiUHJldmFsZW5jZSAoJSkiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMC41KSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpCgojIFByaW50IHRoZSBoZWF0bWFwCnByaW50KHNpemVfaGVhdG1hcCkKCiMjIyBGYXJtIFNpemUgYW5kIEluYXBwcm9wcmlhdGUgQW50aWJpb3RpYyBVc2UKCiMgQ3JlYXRlIGFuIGluZGljYXRvciBmb3IgcG90ZW50aWFsbHkgaW5hcHByb3ByaWF0ZSB1c2UKIyBEZWZpbmUgaW5hcHByb3ByaWF0ZSB1c2UgYXMgcHJldmVudGl2ZSB1c2Ugd2l0aG91dCBkaXNlYXNlIG9yIGdyb3d0aCBwcm9tb3Rpb24KZmFybV9kYXRhIDwtIGZhcm1fZGF0YSAlPiUKICBtdXRhdGUoCiAgICBpbmFwcHJvcHJpYXRlX3VzZSA9IGNhc2Vfd2hlbigKICAgICAgYWJfcHJldmVudGlvbiA9PSAxIHwgYWJfZ3Jvd3RoID09IDEgfiAxLAogICAgICBUUlVFIH4gMAogICAgKQogICkKCiMgQW5hbHl6ZSBpbmFwcHJvcHJpYXRlIHVzZSBieSBmYXJtIHNpemUKaW5hcHByb3ByaWF0ZV9ieV9zaXplIDwtIGZhcm1fZGF0YSAlPiUKICBncm91cF9ieShmYXJtX3NpemVfY2F0KSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgaW5hcHByb3ByaWF0ZV9uID0gc3VtKGluYXBwcm9wcmlhdGVfdXNlLCBuYS5ybSA9IFRSVUUpLAogICAgaW5hcHByb3ByaWF0ZV9wY3QgPSBtZWFuKGluYXBwcm9wcmlhdGVfdXNlLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgLmdyb3VwcyA9ICJkcm9wIgogICkgJT4lCiAgZmlsdGVyKCFpcy5uYShmYXJtX3NpemVfY2F0KSkKCiMgRGlzcGxheSByZXN1bHRzCmluYXBwcm9wcmlhdGVfYnlfc2l6ZSAlPiUKICBrYWJsZShjYXB0aW9uID0gIkluYXBwcm9wcmlhdGUgQW50aWJpb3RpYyBVc2UgYnkgRmFybSBTaXplIENhdGVnb3J5IiwKICAgICAgICBjb2wubmFtZXMgPSBjKCJGYXJtIFNpemUiLCAiTnVtYmVyIG9mIEZhcm1zIiwgIkZhcm1zIHdpdGggSW5hcHByb3ByaWF0ZSBVc2UiLCAiJSBJbmFwcHJvcHJpYXRlIFVzZSIpKSAlPiUKICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQoKIyBDcmVhdGUgYSBiYXIgY2hhcnQgb2YgaW5hcHByb3ByaWF0ZSB1c2UgYnkgZmFybSBzaXplCmluYXBwcm9wcmlhdGVfcGxvdCA8LSBnZ3Bsb3QoaW5hcHByb3ByaWF0ZV9ieV9zaXplLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IGZhcm1fc2l6ZV9jYXQsIHkgPSBpbmFwcHJvcHJpYXRlX3BjdCwgZmlsbCA9IGZhcm1fc2l6ZV9jYXQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHJvdW5kKGluYXBwcm9wcmlhdGVfcGN0LCAxKSwgIiUiKSksIAogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSkgKwogIGxhYnModGl0bGUgPSAiSW5hcHByb3ByaWF0ZSBBbnRpYmlvdGljIFVzZSBieSBGYXJtIFNpemUiLAogICAgICAgc3VidGl0bGUgPSAiRGVmaW5lZCBhcyBwcmV2ZW50aXZlIHVzZSBvciBncm93dGggcHJvbW90aW9uIiwKICAgICAgIHggPSAiRmFybSBTaXplIENhdGVnb3J5IiwKICAgICAgIHkgPSAiUGVyY2VudGFnZSBvZiBGYXJtcyAoJSkiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkJsdWVzIikKCiMgUHJpbnQgdGhlIHBsb3QKcHJpbnQoaW5hcHByb3ByaWF0ZV9wbG90KQoKIyBMT0VTUyBzbW9vdGhpbmcgZm9yIGluYXBwcm9wcmlhdGUgdXNlIGJ5IGZhcm0gc2l6ZQppbmFwcHJvcHJpYXRlX3Bsb3RfbG9lc3MgPC0gZ2dwbG90KGZhcm1fZGF0YSAlPiUgZmlsdGVyKCFpcy5uYShhcmVhX2Zhcm0pKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBhcmVhX2Zhcm0sIHkgPSBpbmFwcHJvcHJpYXRlX3VzZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4zKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc2UgPSBUUlVFKSArCiAgbGFicyh0aXRsZSA9ICJOb24tbGluZWFyIFJlbGF0aW9uc2hpcCBCZXR3ZWVuIEZhcm0gU2l6ZSBhbmQgSW5hcHByb3ByaWF0ZSBBbnRpYmlvdGljIFVzZSIsCiAgICAgICBzdWJ0aXRsZSA9ICJMT0VTUyBTbW9vdGhpbmcgQ3VydmUgd2l0aCA5NSUgQ29uZmlkZW5jZSBJbnRlcnZhbCIsCiAgICAgICB4ID0gIkZhcm0gQXJlYSAoc3F1YXJlIG1ldGVycykiLAogICAgICAgeSA9ICJQcm9iYWJpbGl0eSBvZiBJbmFwcHJvcHJpYXRlIFVzZSIpICsKICB0aGVtZV9taW5pbWFsKCkKCiMgUHJpbnQgdGhlIExPRVNTIHBsb3QKcHJpbnQoaW5hcHByb3ByaWF0ZV9wbG90X2xvZXNzKQpgYGAKCiMjIFJlc3VsdHMgZm9yIEh5cG90aGVzaXMgMS40OiBJc29tb3JwaGlzbSBpbiBBbnRpYmlvdGljIFVzZSBQYXR0ZXJucyB3aXRoaW4gQ29tbXVuaXRpZXMKCmBgYHtyIGg0LUNvbW11bml0eS1sZXZlbCBBbmFseXNpcyBvZiBBbnRpYmlvdGljIFVzZSBQYXR0ZXJuc30KaWYoIWV4aXN0cygiZmFybV9kYXRhIikpIHsKICBmYXJtX2RhdGEgPC0gcmVhZFJEUyhoZXJlKCJkYXRhIiwgInByb2Nlc3NlZCIsICJmYXJtX2RhdGFfcHJvY2Vzc2VkLnJkcyIpKQp9CmlmKCFleGlzdHMoImhvdXNlaG9sZF9kYXRhIikpIHsKICBob3VzZWhvbGRfZGF0YSA8LSByZWFkUkRTKGhlcmUoImRhdGEiLCAicHJvY2Vzc2VkIiwgImhvdXNlaG9sZF9kYXRhX3Byb2Nlc3NlZC5yZHMiKSkKfQoKIyBDaGVjayBpZiB3ZSBoYXZlIGdlb2dyYXBoaWMgaWRlbnRpZmllcnMgZm9yIGNvbW11bml0eS1sZXZlbCBhbmFseXNpcwppZighImdlb19pZCIgJWluJSBuYW1lcyhmYXJtX2RhdGEpIHx8ICEiZ2VvX2lkIiAlaW4lIG5hbWVzKGhvdXNlaG9sZF9kYXRhKSkgewogIGNhdCgiR2VvZ3JhcGhpYyBpZGVudGlmaWVycyBub3QgZm91bmQgaW4gb25lIG9yIGJvdGggZGF0YXNldHMuXG4iKQogIGNhdCgiQ3JlYXRpbmcgcHJveHkgZ2VvZ3JhcGhpYyBpZGVudGlmaWVycyBiYXNlZCBvbiBhdmFpbGFibGUgaW5mb3JtYXRpb24uXG4iKQogIAogICMgQ2hlY2sgZm9yIGRpc3RyaWN0IGFuZCBjb21tdW5lIHZhcmlhYmxlcwogIGlmKGFsbChjKCJkaXN0cmljdCIsICJjb21tdW5lIikgJWluJSBuYW1lcyhmYXJtX2RhdGEpKSAmJiAKICAgICBhbGwoYygiZGlzdHJpY3QiLCAiY29tbXVuZSIpICVpbiUgbmFtZXMoaG91c2Vob2xkX2RhdGEpKSkgewogICAgCiAgICAjIENyZWF0ZSBnZW9ncmFwaGljIElEIGZvciBjb21tdW5pdHktbGV2ZWwgYW5hbHlzaXMKICAgIGZhcm1fZGF0YSA8LSBmYXJtX2RhdGEgJT4lCiAgICAgIG11dGF0ZShnZW9faWQgPSBwYXN0ZShkaXN0cmljdCwgY29tbXVuZSwgc2VwID0gIl8iKSkKICAgIAogICAgaG91c2Vob2xkX2RhdGEgPC0gaG91c2Vob2xkX2RhdGEgJT4lCiAgICAgIG11dGF0ZShnZW9faWQgPSBwYXN0ZShkaXN0cmljdCwgY29tbXVuZSwgc2VwID0gIl8iKSkKICAgIAogICAgY2F0KCJDcmVhdGVkIGdlb19pZCB1c2luZyBkaXN0cmljdCBhbmQgY29tbXVuZSB2YXJpYWJsZXMuXG4iKQogIH0gZWxzZSB7CiAgICAjIElmIHN0YW5kYXJkIGdlb2dyYXBoaWMgdmFyaWFibGVzIGRvbid0IGV4aXN0LCB1c2UgZmFybV9pZCBwYXR0ZXJuIGlmIGF2YWlsYWJsZQogICAgaWYoImZhcm1faWQiICVpbiUgbmFtZXMoZmFybV9kYXRhKSkgewogICAgICBmYXJtX2RhdGEgPC0gZmFybV9kYXRhICU+JQogICAgICAgIG11dGF0ZSgKICAgICAgICAgICMgRXh0cmFjdCBmaXJzdCBwYXJ0IG9mIGZhcm1faWQgYXMgZ2VvZ3JhcGhpYyBpZGVudGlmaWVyCiAgICAgICAgICAjIFRoaXMgYXNzdW1lcyBmYXJtX2lkIGhhcyBhIHN0cnVjdHVyZSB3aGVyZSB0aGUgZmlyc3QgZGlnaXRzIHJlcHJlc2VudCBsb2NhdGlvbgogICAgICAgICAgZ2VvX2lkID0gc3Vic3RyKGFzLmNoYXJhY3RlcihmYXJtX2lkKSwgMSwgNSkKICAgICAgICApCiAgICAgIAogICAgICAjIEZvciBob3VzZWhvbGQgZGF0YSwgY3JlYXRlIGEgbW9jayBnZW9faWQgZm9yIGRlbW9uc3RyYXRpb24KICAgICAgIyBJbiBhIHJlYWwgYW5hbHlzaXMsIHdlIHdvdWxkIG5lZWQgYSBwcm9wZXIgd2F5IHRvIGxpbmsgaG91c2Vob2xkcyB0byBjb21tdW5pdGllcwogICAgICBob3VzZWhvbGRfZGF0YSA8LSBob3VzZWhvbGRfZGF0YSAlPiUKICAgICAgICBtdXRhdGUoCiAgICAgICAgICBnZW9faWQgPSBzYW1wbGUodW5pcXVlKGZhcm1fZGF0YSRnZW9faWQpLCBzaXplID0gbigpLCByZXBsYWNlID0gVFJVRSkKICAgICAgICApCiAgICAgIAogICAgICBjYXQoIkNyZWF0ZWQgcHJveHkgZ2VvX2lkIHVzaW5nIGZhcm1faWQgcGF0dGVybi4gTm90ZTogVGhpcyBpcyBmb3IgZGVtb25zdHJhdGlvbiBvbmx5LlxuIikKICAgICAgY2F0KCJJbiBhIHJlYWwgYW5hbHlzaXMsIHByb3BlciBnZW9ncmFwaGljIGxpbmthZ2UgaXMgcmVxdWlyZWQuXG4iKQogICAgfSBlbHNlIHsKICAgICAgY2F0KCJObyBzdWl0YWJsZSBnZW9ncmFwaGljIGlkZW50aWZpZXJzIGZvdW5kLiBDb21tdW5pdHktbGV2ZWwgYW5hbHlzaXMgd2lsbCBiZSBza2lwcGVkLlxuIikKICAgICAgIyBFeGl0IHRoZSBhbmFseXNpcyBpZiBubyBnZW9ncmFwaGljIGlkZW50aWZpZXJzIGFyZSBhdmFpbGFibGUKICAgICAgcmV0dXJuKE5VTEwpCiAgICB9CiAgfQp9CgojIEFnZ3JlZ2F0ZSBmYXJtIGFudGliaW90aWMgdXNlIGJ5IGNvbW11bml0eQpmYXJtX2NvbW11bml0eSA8LSBmYXJtX2RhdGEgJT4lCiAgZ3JvdXBfYnkoZ2VvX2lkKSAlPiUKICBzdW1tYXJpc2UoCiAgICBmYXJtX2NvdW50ID0gbigpLAogICAgZmFybV9hYl91c2VfcGN0ID0gbWVhbihhbnlfYWJfdXNlLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgZmFybV9hYl90cmVhdG1lbnRfcGN0ID0gbWVhbihhYl90cmVhdG1lbnQsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICBmYXJtX2FiX3ByZXZlbnRpb25fcGN0ID0gbWVhbihhYl9wcmV2ZW50aW9uLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgZmFybV9hYl9ncm93dGhfcGN0ID0gbWVhbihhYl9ncm93dGgsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICAuZ3JvdXBzID0gImRyb3AiCiAgKSAlPiUKICBmaWx0ZXIoZmFybV9jb3VudCA+PSAzKSAgIyBPbmx5IGluY2x1ZGUgY29tbXVuaXRpZXMgd2l0aCBhdCBsZWFzdCAzIGZhcm1zCgojIEFnZ3JlZ2F0ZSBob3VzZWhvbGQgYW50aWJpb3RpYyB1c2UgYnkgY29tbXVuaXR5CmhvdXNlaG9sZF9jb21tdW5pdHkgPC0gaG91c2Vob2xkX2RhdGEgJT4lCiAgZ3JvdXBfYnkoZ2VvX2lkKSAlPiUKICBzdW1tYXJpc2UoCiAgICBob3VzZWhvbGRfY291bnQgPSBuKCksCiAgICBob3VzZWhvbGRfYWJfdXNlX3BjdCA9IG1lYW4oYW55X2FiX2xhc3RfaWxsbmVzcywgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgIC5ncm91cHMgPSAiZHJvcCIKICApICU+JQogIGZpbHRlcihob3VzZWhvbGRfY291bnQgPj0gMykgICMgT25seSBpbmNsdWRlIGNvbW11bml0aWVzIHdpdGggYXQgbGVhc3QgMyBob3VzZWhvbGRzCgojIEpvaW4gZmFybSBhbmQgaG91c2Vob2xkIGNvbW11bml0eSBkYXRhCmNvbW11bml0eV9jb21wYXJpc29uIDwtIGlubmVyX2pvaW4oZmFybV9jb21tdW5pdHksIGhvdXNlaG9sZF9jb21tdW5pdHksIGJ5ID0gImdlb19pZCIpCgojIERpc3BsYXkgdGhlIG51bWJlciBvZiBjb21tdW5pdGllcyB3aXRoIHN1ZmZpY2llbnQgZGF0YQpjYXQoIk51bWJlciBvZiBjb21tdW5pdGllcyB3aXRoIHN1ZmZpY2llbnQgZGF0YSBmb3IgY29tcGFyaXNvbjoiLCBucm93KGNvbW11bml0eV9jb21wYXJpc29uKSwgIlxuIikKCiMgRGlzcGxheSBjb21tdW5pdHktbGV2ZWwgY29tcGFyaXNvbiBkYXRhCmNvbW11bml0eV9jb21wYXJpc29uICU+JQogIGRwbHlyOjpzZWxlY3QoZ2VvX2lkLCBmYXJtX2NvdW50LCBob3VzZWhvbGRfY291bnQsIGZhcm1fYWJfdXNlX3BjdCwgaG91c2Vob2xkX2FiX3VzZV9wY3QpICU+JQogIGthYmxlKGNhcHRpb24gPSAiQ29tbXVuaXR5LWxldmVsIEFudGliaW90aWMgVXNlIGluIEZhcm1zIGFuZCBIb3VzZWhvbGRzIiwKICAgICAgICBjb2wubmFtZXMgPSBjKCJDb21tdW5pdHkgSUQiLCAiTnVtYmVyIG9mIEZhcm1zIiwgIk51bWJlciBvZiBIb3VzZWhvbGRzIiwgCiAgICAgICAgICAgICAgICAgICAgICJGYXJtIEFudGliaW90aWMgVXNlICglKSIsICJIb3VzZWhvbGQgQW50aWJpb3RpYyBVc2UgKCUpIikpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRkFMU0UpCgojIyMgQ29ycmVsYXRpb24gQW5hbHlzaXMKCiMgQ2FsY3VsYXRlIFBlYXJzb24gY29ycmVsYXRpb24gYmV0d2VlbiBmYXJtIGFuZCBob3VzZWhvbGQgYW50aWJpb3RpYyB1c2UKY29ycmVsYXRpb25fcmVzdWx0IDwtIGNvci50ZXN0KAogIGNvbW11bml0eV9jb21wYXJpc29uJGZhcm1fYWJfdXNlX3BjdCwKICBjb21tdW5pdHlfY29tcGFyaXNvbiRob3VzZWhvbGRfYWJfdXNlX3BjdCwKICBtZXRob2QgPSAicGVhcnNvbiIKKQoKIyBEaXNwbGF5IGNvcnJlbGF0aW9uIHJlc3VsdHMKY2F0KCJQZWFyc29uIGNvcnJlbGF0aW9uIGJldHdlZW4gZmFybSBhbmQgaG91c2Vob2xkIGFudGliaW90aWMgdXNlIGF0IGNvbW11bml0eSBsZXZlbDpcbiIpCmNhdCgiQ29ycmVsYXRpb24gY29lZmZpY2llbnQgKHIpOiIsIGNvcnJlbGF0aW9uX3Jlc3VsdCRlc3RpbWF0ZSwgIlxuIikKY2F0KCI5NSUgY29uZmlkZW5jZSBpbnRlcnZhbDogWyIsIGNvcnJlbGF0aW9uX3Jlc3VsdCRjb25mLmludFsxXSwgIiwiLCBjb3JyZWxhdGlvbl9yZXN1bHQkY29uZi5pbnRbMl0sICJdXG4iKQpjYXQoInQtc3RhdGlzdGljOiIsIGNvcnJlbGF0aW9uX3Jlc3VsdCRzdGF0aXN0aWMsICJcbiIpCmNhdCgiRGVncmVlcyBvZiBmcmVlZG9tOiIsIGNvcnJlbGF0aW9uX3Jlc3VsdCRwYXJhbWV0ZXIsICJcbiIpCmNhdCgiUC12YWx1ZToiLCBjb3JyZWxhdGlvbl9yZXN1bHQkcC52YWx1ZSwgIlxuIikKY2F0KCJJbnRlcnByZXRhdGlvbjoiLCBpZmVsc2UoY29ycmVsYXRpb25fcmVzdWx0JHAudmFsdWUgPCAwLjA1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2lnbmlmaWNhbnQgY29ycmVsYXRpb24iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm8gc2lnbmlmaWNhbnQgY29ycmVsYXRpb24iKSwgIlxuIikKCiMgQ2FsY3VsYXRlIFNwZWFybWFuIGNvcnJlbGF0aW9uIChsZXNzIHNlbnNpdGl2ZSB0byBvdXRsaWVycykKc3BlYXJtYW5fcmVzdWx0IDwtIGNvci50ZXN0KAogIGNvbW11bml0eV9jb21wYXJpc29uJGZhcm1fYWJfdXNlX3BjdCwKICBjb21tdW5pdHlfY29tcGFyaXNvbiRob3VzZWhvbGRfYWJfdXNlX3BjdCwKICBtZXRob2QgPSAic3BlYXJtYW4iCikKCmNhdCgiXG5TcGVhcm1hbiByYW5rIGNvcnJlbGF0aW9uIChyb2J1c3QgdG8gb3V0bGllcnMpOlxuIikKY2F0KCJDb3JyZWxhdGlvbiBjb2VmZmljaWVudCAocmhvKToiLCBzcGVhcm1hbl9yZXN1bHQkZXN0aW1hdGUsICJcbiIpCmNhdCgiUC12YWx1ZToiLCBzcGVhcm1hbl9yZXN1bHQkcC52YWx1ZSwgIlxuIikKCiMjIyBWaXN1YWxpemF0aW9uIG9mIENvbW11bml0eS1sZXZlbCBQYXR0ZXJucwoKIyBTY2F0dGVyIHBsb3Qgb2YgZmFybSB2cy4gaG91c2Vob2xkIGFudGliaW90aWMgdXNlIGF0IGNvbW11bml0eSBsZXZlbApjb21tdW5pdHlfcGxvdCA8LSBnZ3Bsb3QoY29tbXVuaXR5X2NvbXBhcmlzb24sIAogICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSBmYXJtX2FiX3VzZV9wY3QsIHkgPSBob3VzZWhvbGRfYWJfdXNlX3BjdCkpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gZmFybV9jb3VudCArIGhvdXNlaG9sZF9jb3VudCksIGFscGhhID0gMC42KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBjb2xvciA9ICJibHVlIikgKwogIGxhYnModGl0bGUgPSAiQ29tbXVuaXR5LWxldmVsIENvcnJlbGF0aW9uIEJldHdlZW4gRmFybSBhbmQgSG91c2Vob2xkIEFudGliaW90aWMgVXNlIiwKICAgICAgIHN1YnRpdGxlID0gcGFzdGUoIlBlYXJzb24gY29ycmVsYXRpb24gPSIsIHJvdW5kKGNvcnJlbGF0aW9uX3Jlc3VsdCRlc3RpbWF0ZSwgMiksIAogICAgICAgICAgICAgICAgICAgICAgICAiLCBwLXZhbHVlID0iLCByb3VuZChjb3JyZWxhdGlvbl9yZXN1bHQkcC52YWx1ZSwgMykpLAogICAgICAgeCA9ICJGYXJtIEFudGliaW90aWMgVXNlICglKSIsCiAgICAgICB5ID0gIkhvdXNlaG9sZCBBbnRpYmlvdGljIFVzZSAoJSkiLAogICAgICAgc2l6ZSA9ICJOdW1iZXIgb2YgUmVzcG9uZGVudHMiKSArCiAgdGhlbWVfbWluaW1hbCgpCgojIFByaW50IHRoZSBjb21tdW5pdHktbGV2ZWwgY29ycmVsYXRpb24gcGxvdApwcmludChjb21tdW5pdHlfcGxvdCkKCiMjIyBNdWx0aXBsZSBSZWdyZXNzaW9uIEFuYWx5c2lzCgojIFByZXBhcmUgZGF0YSBmb3IgcmVncmVzc2lvbiBhbmFseXNpcyAtIGFkZCBtb3JlIGNvbW11bml0eSBjaGFyYWN0ZXJpc3RpY3MgaWYgYXZhaWxhYmxlCiMgRm9yIGV4YW1wbGUsIGF2ZXJhZ2UgZWR1Y2F0aW9uYWwgbGV2ZWwsIHNvY2lvZWNvbm9taWMgaW5kaWNhdG9ycywgZXRjLgppZihhbGwoYygiZWR1IiwgImFyZWFfZmFybSIpICVpbiUgbmFtZXMoZmFybV9kYXRhKSkpIHsKICAjIEFnZ3JlZ2F0ZSBhZGRpdGlvbmFsIGZhcm0gY2hhcmFjdGVyaXN0aWNzCiAgZmFybV9jb21tdW5pdHlfZXh0ZW5kZWQgPC0gZmFybV9kYXRhICU+JQogICAgZ3JvdXBfYnkoZ2VvX2lkKSAlPiUKICAgIHN1bW1hcmlzZSgKICAgICAgZmFybV9jb3VudCA9IG4oKSwKICAgICAgZmFybV9hYl91c2VfcGN0ID0gbWVhbihhbnlfYWJfdXNlLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICBmYXJtX2VkdV9tZWFuID0gbWVhbihhcy5udW1lcmljKGVkdSksIG5hLnJtID0gVFJVRSksICAjIEFzc3VtaW5nIGVkdSBpcyBhIG51bWVyaWMgb3Igb3JkaW5hbCB2YXJpYWJsZQogICAgICBmYXJtX3NpemVfbWVhbiA9IG1lYW4oYXJlYV9mYXJtLCBuYS5ybSA9IFRSVUUpLAogICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICApICU+JQogICAgZmlsdGVyKGZhcm1fY291bnQgPj0gMykKICAKICAjIEpvaW4gd2l0aCBob3VzZWhvbGQgZGF0YQogIGlmKCJlZHUiICVpbiUgbmFtZXMoaG91c2Vob2xkX2RhdGEpKSB7CiAgICBob3VzZWhvbGRfY29tbXVuaXR5X2V4dGVuZGVkIDwtIGhvdXNlaG9sZF9kYXRhICU+JQogICAgICBncm91cF9ieShnZW9faWQpICU+JQogICAgICBzdW1tYXJpc2UoCiAgICAgICAgaG91c2Vob2xkX2NvdW50ID0gbigpLAogICAgICAgIGhvdXNlaG9sZF9hYl91c2VfcGN0ID0gbWVhbihhbnlfYWJfbGFzdF9pbGxuZXNzLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICAgIGhvdXNlaG9sZF9lZHVfbWVhbiA9IG1lYW4oYXMubnVtZXJpYyhlZHUpLCBuYS5ybSA9IFRSVUUpLAogICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgKSAlPiUKICAgICAgZmlsdGVyKGhvdXNlaG9sZF9jb3VudCA+PSAzKQogICAgCiAgICAjIEpvaW4gZGF0YQogICAgY29tbXVuaXR5X3JlZ3Jlc3Npb24gPC0gaW5uZXJfam9pbihmYXJtX2NvbW11bml0eV9leHRlbmRlZCwgaG91c2Vob2xkX2NvbW11bml0eV9leHRlbmRlZCwgYnkgPSAiZ2VvX2lkIikKICAgIAogICAgIyBSZWdyZXNzaW9uIG1vZGVsOiBIb3VzZWhvbGQgYW50aWJpb3RpYyB1c2UgYXMgYSBmdW5jdGlvbiBvZiBmYXJtIGFudGliaW90aWMgdXNlIGFuZCBjb3ZhcmlhdGVzCiAgICBtb2RlbCA8LSBsbShob3VzZWhvbGRfYWJfdXNlX3BjdCB+IGZhcm1fYWJfdXNlX3BjdCArIGZhcm1fZWR1X21lYW4gKyBob3VzZWhvbGRfZWR1X21lYW4gKyBmYXJtX3NpemVfbWVhbiwKICAgICAgICAgICAgICAgZGF0YSA9IGNvbW11bml0eV9yZWdyZXNzaW9uKQogICAgCiAgICAjIERpc3BsYXkgcmVncmVzc2lvbiByZXN1bHRzCiAgICBjYXQoIlxuTXVsdGlwbGUgcmVncmVzc2lvbiBhbmFseXNpczpcbiIpCiAgICBjYXQoIkRlcGVuZGVudCB2YXJpYWJsZTogSG91c2Vob2xkIGFudGliaW90aWMgdXNlIHBlcmNlbnRhZ2VcblxuIikKICAgIHByaW50KHN1bW1hcnkobW9kZWwpKQogICAgCiAgICAjIENhbGN1bGF0ZSBWSUYgdG8gY2hlY2sgZm9yIG11bHRpY29sbGluZWFyaXR5CiAgICBpZihyZXF1aXJlTmFtZXNwYWNlKCJjYXIiLCBxdWlldGx5ID0gVFJVRSkpIHsKICAgICAgY2F0KCJcblZhcmlhbmNlIEluZmxhdGlvbiBGYWN0b3JzIChjaGVja2luZyBmb3IgbXVsdGljb2xsaW5lYXJpdHkpOlxuIikKICAgICAgcHJpbnQoY2FyOjp2aWYobW9kZWwpKQogICAgfQogIH0KfQoKIyMjIEFuYWx5c2lzIG9mIFB1cnBvc2UtU3BlY2lmaWMgQ29ycmVsYXRpb25zCgojIEV4YW1pbmUgY29ycmVsYXRpb25zIGJldHdlZW4gaG91c2Vob2xkIGFudGliaW90aWMgdXNlIGFuZCBzcGVjaWZpYyBmYXJtIGFudGliaW90aWMgcHVycG9zZXMKcHVycG9zZV9jb3JyZWxhdGlvbnMgPC0gZGF0YS5mcmFtZSgKICBQdXJwb3NlID0gYygiVHJlYXRtZW50IiwgIlByZXZlbnRpb24iLCAiR3Jvd3RoIFByb21vdGlvbiIpLAogIENvcnJlbGF0aW9uID0gYygKICAgIGNvcihjb21tdW5pdHlfY29tcGFyaXNvbiRob3VzZWhvbGRfYWJfdXNlX3BjdCwgY29tbXVuaXR5X2NvbXBhcmlzb24kZmFybV9hYl90cmVhdG1lbnRfcGN0LCAKICAgICAgICB1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIiksCiAgICBjb3IoY29tbXVuaXR5X2NvbXBhcmlzb24kaG91c2Vob2xkX2FiX3VzZV9wY3QsIGNvbW11bml0eV9jb21wYXJpc29uJGZhcm1fYWJfcHJldmVudGlvbl9wY3QsIAogICAgICAgIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKSwKICAgIGNvcihjb21tdW5pdHlfY29tcGFyaXNvbiRob3VzZWhvbGRfYWJfdXNlX3BjdCwgY29tbXVuaXR5X2NvbXBhcmlzb24kZmFybV9hYl9ncm93dGhfcGN0LCAKICAgICAgICB1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIikKICApCikKCiMgQ2FsY3VsYXRlIHAtdmFsdWVzIGZvciB0aGVzZSBjb3JyZWxhdGlvbnMKcHVycG9zZV9jb3JyZWxhdGlvbnMkUFZhbHVlIDwtIGMoCiAgY29yLnRlc3QoY29tbXVuaXR5X2NvbXBhcmlzb24kaG91c2Vob2xkX2FiX3VzZV9wY3QsIGNvbW11bml0eV9jb21wYXJpc29uJGZhcm1fYWJfdHJlYXRtZW50X3BjdCkkcC52YWx1ZSwKICBjb3IudGVzdChjb21tdW5pdHlfY29tcGFyaXNvbiRob3VzZWhvbGRfYWJfdXNlX3BjdCwgY29tbXVuaXR5X2NvbXBhcmlzb24kZmFybV9hYl9wcmV2ZW50aW9uX3BjdCkkcC52YWx1ZSwKICBjb3IudGVzdChjb21tdW5pdHlfY29tcGFyaXNvbiRob3VzZWhvbGRfYWJfdXNlX3BjdCwgY29tbXVuaXR5X2NvbXBhcmlzb24kZmFybV9hYl9ncm93dGhfcGN0KSRwLnZhbHVlCikKCnB1cnBvc2VfY29ycmVsYXRpb25zJFNpZ25pZmljYW50IDwtIHB1cnBvc2VfY29ycmVsYXRpb25zJFBWYWx1ZSA8IDAuMDUKCiMgRGlzcGxheSBwdXJwb3NlLXNwZWNpZmljIGNvcnJlbGF0aW9ucwpwdXJwb3NlX2NvcnJlbGF0aW9ucyAlPiUKICBtdXRhdGUoCiAgICBDb3JyZWxhdGlvbiA9IHJvdW5kKENvcnJlbGF0aW9uLCAzKSwKICAgIFBWYWx1ZSA9IHJvdW5kKFBWYWx1ZSwgMyksCiAgICBTaWduaWZpY2FudCA9IGlmZWxzZShTaWduaWZpY2FudCwgIlllcyIsICJObyIpCiAgKSAlPiUKICBrYWJsZShjYXB0aW9uID0gIkNvcnJlbGF0aW9ucyBCZXR3ZWVuIEhvdXNlaG9sZCBBbnRpYmlvdGljIFVzZSBhbmQgRmFybSBBbnRpYmlvdGljIFVzZSBieSBQdXJwb3NlIiwKICAgICAgICBjb2wubmFtZXMgPSBjKCJGYXJtIEFudGliaW90aWMgUHVycG9zZSIsICJDb3JyZWxhdGlvbiB3aXRoIEhvdXNlaG9sZCBVc2UiLCAKICAgICAgICAgICAgICAgICAgICAgIlAtVmFsdWUiLCAiU2lnbmlmaWNhbnQiKSkgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkKCiMgSWYgaW5mb3JtYXRpb24gc291cmNlIGRhdGEgaXMgYXZhaWxhYmxlLCBhbmFseXplIHJlbGF0aW9uc2hpcCB3aXRoIGNvbW11bml0eSBwYXR0ZXJucwppZigicTdfMTkiICVpbiUgbmFtZXMoaG91c2Vob2xkX2RhdGEpICYgImFkdmljZTEiICVpbiUgbmFtZXMoZmFybV9kYXRhKSkgewogICMgQ2F0ZWdvcml6ZSBpbmZvcm1hdGlvbiBzb3VyY2VzIGFuZCBhZ2dyZWdhdGUgYXQgY29tbXVuaXR5IGxldmVsCiAgaG91c2Vob2xkX2luZm9fc291cmNlcyA8LSBob3VzZWhvbGRfZGF0YSAlPiUKICAgIGdyb3VwX2J5KGdlb19pZCkgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgICMgQ291bnQgZnJlcXVlbmN5IG9mIGRpZmZlcmVudCBpbmZvcm1hdGlvbiBzb3VyY2VzCiAgICAgICMgVGhpcyB3b3VsZCBuZWVkIHRvIGJlIGFkYXB0ZWQgYmFzZWQgb24gYWN0dWFsIGNvZGluZyBvZiBpbmZvcm1hdGlvbiBzb3VyY2VzCiAgICAgIGhvdXNlaG9sZF9pbmZvX2hlYWx0aGNhcmUgPSBtZWFuKHE3XzE5ID09IDEgfCBxN18xOSA9PSAyIHwgcTdfMTkgPT0gMywgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgaG91c2Vob2xkX2luZm9fcGhhcm1hY3kgPSBtZWFuKHE3XzE5ID09IDUsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICAgIGhvdXNlaG9sZF9pbmZvX3NvY2lhbCA9IG1lYW4ocTdfMTkgPT0gOCwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgKQogIAogIGZhcm1faW5mb19zb3VyY2VzIDwtIGZhcm1fZGF0YSAlPiUKICAgIGdyb3VwX2J5KGdlb19pZCkgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgICMgQ291bnQgZnJlcXVlbmN5IG9mIGRpZmZlcmVudCBpbmZvcm1hdGlvbiBzb3VyY2VzCiAgICAgICMgVGhpcyB3b3VsZCBuZWVkIHRvIGJlIGFkYXB0ZWQgYmFzZWQgb24gYWN0dWFsIGNvZGluZyBvZiBpbmZvcm1hdGlvbiBzb3VyY2VzCiAgICAgIGZhcm1faW5mb192ZXRlcmluYXJ5ID0gbWVhbihncmVwbCgidmV0IiwgYWR2aWNlMSwgaWdub3JlLmNhc2UgPSBUUlVFKSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgZmFybV9pbmZvX3BoYXJtYWN5ID0gbWVhbihncmVwbCgicGhhcm0iLCBhZHZpY2UxLCBpZ25vcmUuY2FzZSA9IFRSVUUpLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICBmYXJtX2luZm9fc29jaWFsID0gbWVhbihncmVwbCgiZnJpZW5kfG5laWdoYm9yIiwgYWR2aWNlMSwgaWdub3JlLmNhc2UgPSBUUlVFKSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgKQogIAogICMgSm9pbiBpbmZvcm1hdGlvbiBzb3VyY2UgZGF0YSB3aXRoIGNvbW11bml0eSBjb21wYXJpc29uIGRhdGEKICBjb21tdW5pdHlfaW5mbyA8LSBjb21tdW5pdHlfY29tcGFyaXNvbiAlPiUKICAgIGxlZnRfam9pbihob3VzZWhvbGRfaW5mb19zb3VyY2VzLCBieSA9ICJnZW9faWQiKSAlPiUKICAgIGxlZnRfam9pbihmYXJtX2luZm9fc291cmNlcywgYnkgPSAiZ2VvX2lkIikKICAKICAjIEFuYWx5emUgY29ycmVsYXRpb24gYmV0d2VlbiBzaW1pbGFyIGluZm9ybWF0aW9uIHNvdXJjZXMgYWNyb3NzIHNlY3RvcnMKICBjYXQoIlxuQ29ycmVsYXRpb25zIGJldHdlZW4gaW5mb3JtYXRpb24gc291cmNlcyBhY3Jvc3Mgc2VjdG9yczpcbiIpCiAgaWYobmNvbChjb21tdW5pdHlfaW5mbykgPiA4KSB7ICAjIENoZWNrIGlmIGluZm9ybWF0aW9uIHNvdXJjZSB2YXJpYWJsZXMgd2VyZSBzdWNjZXNzZnVsbHkgam9pbmVkCiAgICBpbmZvX2NvcnJlbGF0aW9ucyA8LSBkYXRhLmZyYW1lKAogICAgICBTb3VyY2VzID0gYygiSGVhbHRoY2FyZS9WZXRlcmluYXJ5IiwgIlBoYXJtYWN5IiwgIlNvY2lhbCBOZXR3b3JrcyIpLAogICAgICBDb3JyZWxhdGlvbiA9IGMoCiAgICAgICAgY29yKGNvbW11bml0eV9pbmZvJGhvdXNlaG9sZF9pbmZvX2hlYWx0aGNhcmUsIGNvbW11bml0eV9pbmZvJGZhcm1faW5mb192ZXRlcmluYXJ5LCAKICAgICAgICAgICAgdXNlID0gInBhaXJ3aXNlLmNvbXBsZXRlLm9icyIpLAogICAgICAgIGNvcihjb21tdW5pdHlfaW5mbyRob3VzZWhvbGRfaW5mb19waGFybWFjeSwgY29tbXVuaXR5X2luZm8kZmFybV9pbmZvX3BoYXJtYWN5LCAKICAgICAgICAgICAgdXNlID0gInBhaXJ3aXNlLmNvbXBsZXRlLm9icyIpLAogICAgICAgIGNvcihjb21tdW5pdHlfaW5mbyRob3VzZWhvbGRfaW5mb19zb2NpYWwsIGNvbW11bml0eV9pbmZvJGZhcm1faW5mb19zb2NpYWwsIAogICAgICAgICAgICB1c2UgPSAicGFpcndpc2UuY29tcGxldGUub2JzIikKICAgICAgKQogICAgKQogICAgCiAgICAjIENhbGN1bGF0ZSBwLXZhbHVlcwogICAgaW5mb19jb3JyZWxhdGlvbnMkUFZhbHVlIDwtIGMoCiAgICAgIGNvci50ZXN0KGNvbW11bml0eV9pbmZvJGhvdXNlaG9sZF9pbmZvX2hlYWx0aGNhcmUsIGNvbW11bml0eV9pbmZvJGZhcm1faW5mb192ZXRlcmluYXJ5KSRwLnZhbHVlLAogICAgICBjb3IudGVzdChjb21tdW5pdHlfaW5mbyRob3VzZWhvbGRfaW5mb19waGFybWFjeSwgY29tbXVuaXR5X2luZm8kZmFybV9pbmZvX3BoYXJtYWN5KSRwLnZhbHVlLAogICAgICBjb3IudGVzdChjb21tdW5pdHlfaW5mbyRob3VzZWhvbGRfaW5mb19zb2NpYWwsIGNvbW11bml0eV9pbmZvJGZhcm1faW5mb19zb2NpYWwpJHAudmFsdWUKICAgICkKICAgIAogICAgaW5mb19jb3JyZWxhdGlvbnMkU2lnbmlmaWNhbnQgPC0gaW5mb19jb3JyZWxhdGlvbnMkUFZhbHVlIDwgMC4wNQogICAgCiAgICAjIERpc3BsYXkgaW5mb3JtYXRpb24gc291cmNlIGNvcnJlbGF0aW9ucwogICAgaW5mb19jb3JyZWxhdGlvbnMgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBDb3JyZWxhdGlvbiA9IHJvdW5kKENvcnJlbGF0aW9uLCAzKSwKICAgICAgICBQVmFsdWUgPSByb3VuZChQVmFsdWUsIDMpLAogICAgICAgIFNpZ25pZmljYW50ID0gaWZlbHNlKFNpZ25pZmljYW50LCAiWWVzIiwgIk5vIikKICAgICAgKSAlPiUKICAgICAga2FibGUoY2FwdGlvbiA9ICJDb3JyZWxhdGlvbnMgQmV0d2VlbiBJbmZvcm1hdGlvbiBTb3VyY2VzIGluIEhvdXNlaG9sZHMgYW5kIEZhcm1zIiwKICAgICAgICAgICAgY29sLm5hbWVzID0gYygiSW5mb3JtYXRpb24gU291cmNlIiwgIkNvcnJlbGF0aW9uIiwgIlAtVmFsdWUiLCAiU2lnbmlmaWNhbnQiKSkgJT4lCiAgICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRkFMU0UpCiAgfSBlbHNlIHsKICAgIGNhdCgiSW5mb3JtYXRpb24gc291cmNlIHZhcmlhYmxlcyBub3QgYXZhaWxhYmxlIG9yIG5vdCBzdWNjZXNzZnVsbHkgam9pbmVkLlxuIikKICB9Cn0KCiMjIyBNdWx0aWxldmVsIE1vZGVsIGZvciBDb21tdW5pdHkgRWZmZWN0cwoKIyBGb3IgZmFybSBkYXRhCmlmKGxlbmd0aCh1bmlxdWUoZmFybV9kYXRhJGdlb19pZCkpID49IDEwKSB7ICAjIE5lZWQgc3VmZmljaWVudCBudW1iZXIgb2YgY29tbXVuaXRpZXMKICAjIEZpbHRlciBkYXRhIGZvciBtdWx0aWxldmVsIG1vZGVsaW5nCiAgZmFybV9tbG0gPC0gZmFybV9kYXRhICU+JQogICAgZmlsdGVyKCFpcy5uYShnZW9faWQpICYgIWlzLm5hKGFueV9hYl91c2UpKQogIAogICMgRml0IHJhbmRvbSBpbnRlcmNlcHQgbW9kZWwKICBmYXJtX21vZGVsIDwtIHRyeUNhdGNoKHsKICAgIGxpYnJhcnkobG1lNCkKICAgIGdsbWVyKGFueV9hYl91c2UgfiAoMSB8IGdlb19pZCksIGRhdGEgPSBmYXJtX21sbSwgZmFtaWx5ID0gYmlub21pYWwpCiAgfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7CiAgICBtZXNzYWdlKCJFcnJvciBmaXR0aW5nIG11bHRpbGV2ZWwgbW9kZWwgZm9yIGZhcm0gZGF0YTogIiwgZSRtZXNzYWdlKQogICAgcmV0dXJuKE5VTEwpCiAgfSkKICAKICAjIERpc3BsYXkgbW9kZWwgc3VtbWFyeSBpZiBzdWNjZXNzZnVsCiAgaWYoIWlzLm51bGwoZmFybV9tb2RlbCkpIHsKICAgIGNhdCgiXG5NdWx0aWxldmVsIG1vZGVsIGZvciBmYXJtIGFudGliaW90aWMgdXNlOlxuIikKICAgIHByaW50KHN1bW1hcnkoZmFybV9tb2RlbCkpCiAgICAKICAgICMgQ2FsY3VsYXRlIGludHJhY2xhc3MgY29ycmVsYXRpb24gY29lZmZpY2llbnQgKElDQykKICAgIGlmKHJlcXVpcmVOYW1lc3BhY2UoInBlcmZvcm1hbmNlIiwgcXVpZXRseSA9IFRSVUUpKSB7CiAgICAgIGNhdCgiXG5JbnRyYWNsYXNzIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IChJQ0MpIGZvciBmYXJtczpcbiIpCiAgICAgIGZhcm1faWNjIDwtIHBlcmZvcm1hbmNlOjppY2MoZmFybV9tb2RlbCkKICAgICAgcHJpbnQoZmFybV9pY2MpCiAgICAgIGNhdCgiSW50ZXJwcmV0YXRpb246ICIsIAogICAgICAgICAgaWZlbHNlKGZhcm1faWNjJElDQyA+IDAuMDUsIAogICAgICAgICAgICAgICAgIkNvbW11bml0eSBtZW1iZXJzaGlwIGV4cGxhaW5zIGEgbWVhbmluZ2Z1bCBwcm9wb3J0aW9uIG9mIHZhcmlhbmNlIGluIGZhcm0gYW50aWJpb3RpYyB1c2UuIiwgCiAgICAgICAgICAgICAgICAiQ29tbXVuaXR5IG1lbWJlcnNoaXAgZXhwbGFpbnMgbGl0dGxlIHZhcmlhbmNlIGluIGZhcm0gYW50aWJpb3RpYyB1c2UuIiksIAogICAgICAgICAgIlxuIikKICAgIH0KICB9CiAgCiAgIyBGb3IgaG91c2Vob2xkIGRhdGEKICBob3VzZWhvbGRfbWxtIDwtIGhvdXNlaG9sZF9kYXRhICU+JQogICAgZmlsdGVyKCFpcy5uYShnZW9faWQpICYgIWlzLm5hKGFueV9hYl9sYXN0X2lsbG5lc3MpKQogIAogICMgRml0IHJhbmRvbSBpbnRlcmNlcHQgbW9kZWwKICBob3VzZWhvbGRfbW9kZWwgPC0gdHJ5Q2F0Y2goewogICAgZ2xtZXIoYW55X2FiX2xhc3RfaWxsbmVzcyB+ICgxIHwgZ2VvX2lkKSwgZGF0YSA9IGhvdXNlaG9sZF9tbG0sIGZhbWlseSA9IGJpbm9taWFsKQogIH0sIGVycm9yID0gZnVuY3Rpb24oZSkgewogICAgbWVzc2FnZSgiRXJyb3IgZml0dGluZyBtdWx0aWxldmVsIG1vZGVsIGZvciBob3VzZWhvbGQgZGF0YTogIiwgZSRtZXNzYWdlKQogICAgcmV0dXJuKE5VTEwpCiAgfSkKICAKICAjIERpc3BsYXkgbW9kZWwgc3VtbWFyeSBpZiBzdWNjZXNzZnVsCiAgaWYoIWlzLm51bGwoaG91c2Vob2xkX21vZGVsKSkgewogICAgY2F0KCJcbk11bHRpbGV2ZWwgbW9kZWwgZm9yIGhvdXNlaG9sZCBhbnRpYmlvdGljIHVzZTpcbiIpCiAgICBwcmludChzdW1tYXJ5KGhvdXNlaG9sZF9tb2RlbCkpCiAgICAKICAgICMgQ2FsY3VsYXRlIGludHJhY2xhc3MgY29ycmVsYXRpb24gY29lZmZpY2llbnQgKElDQykKICAgIGlmKHJlcXVpcmVOYW1lc3BhY2UoInBlcmZvcm1hbmNlIiwgcXVpZXRseSA9IFRSVUUpKSB7CiAgICAgIGNhdCgiXG5JbnRyYWNsYXNzIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IChJQ0MpIGZvciBob3VzZWhvbGRzOlxuIikKICAgICAgaG91c2Vob2xkX2ljYyA8LSBwZXJmb3JtYW5jZTo6aWNjKGhvdXNlaG9sZF9tb2RlbCkKICAgICAgcHJpbnQoaG91c2Vob2xkX2ljYykKICAgICAgY2F0KCJJbnRlcnByZXRhdGlvbjogIiwgCiAgICAgICAgICBpZmVsc2UoaG91c2Vob2xkX2ljYyRJQ0MgPiAwLjA1LCAKICAgICAgICAgICAgICAgICJDb21tdW5pdHkgbWVtYmVyc2hpcCBleHBsYWlucyBhIG1lYW5pbmdmdWwgcHJvcG9ydGlvbiBvZiB2YXJpYW5jZSBpbiBob3VzZWhvbGQgYW50aWJpb3RpYyB1c2UuIiwgCiAgICAgICAgICAgICAgICAiQ29tbXVuaXR5IG1lbWJlcnNoaXAgZXhwbGFpbnMgbGl0dGxlIHZhcmlhbmNlIGluIGhvdXNlaG9sZCBhbnRpYmlvdGljIHVzZS4iKSwgCiAgICAgICAgICAiXG4iKQogICAgfQogIH0KfSBlbHNlIHsKICBjYXQoIlxuSW5zdWZmaWNpZW50IG51bWJlciBvZiBjb21tdW5pdGllcyBmb3IgbXVsdGlsZXZlbCBtb2RlbGluZy5cbiIpCn0KCiMjIyBTZW5zaXRpdml0eSBBbmFseXNpcwoKIyBQZXJmb3JtIHNlbnNpdGl2aXR5IGFuYWx5c2lzIHdpdGggZGlmZmVyZW50IGNvbW11bml0eS1sZXZlbCBhZ2dyZWdhdGlvbiB0aHJlc2hvbGRzCnRocmVzaG9sZHMgPC0gYygyLCAzLCA1KQpzZW5zaXRpdml0eV9yZXN1bHRzIDwtIGRhdGEuZnJhbWUoCiAgVGhyZXNob2xkID0gaW50ZWdlcigpLAogIE5Db21tdW5pdGllcyA9IGludGVnZXIoKSwKICBDb3JyZWxhdGlvbiA9IG51bWVyaWMoKSwKICBQVmFsdWUgPSBudW1lcmljKCksCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCikKCmZvcih0aHJlc2hvbGQgaW4gdGhyZXNob2xkcykgewogICMgQWdncmVnYXRlIHdpdGggY3VycmVudCB0aHJlc2hvbGQKICBmYXJtX2NvbW1fc2VucyA8LSBmYXJtX2RhdGEgJT4lCiAgICBncm91cF9ieShnZW9faWQpICU+JQogICAgc3VtbWFyaXNlKAogICAgICBmYXJtX2NvdW50ID0gbigpLAogICAgICBmYXJtX2FiX3VzZV9wY3QgPSBtZWFuKGFueV9hYl91c2UsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICkgJT4lCiAgICBmaWx0ZXIoZmFybV9jb3VudCA+PSB0aHJlc2hvbGQpCiAgCiAgaG91c2Vob2xkX2NvbW1fc2VucyA8LSBob3VzZWhvbGRfZGF0YSAlPiUKICAgIGdyb3VwX2J5KGdlb19pZCkgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgIGhvdXNlaG9sZF9jb3VudCA9IG4oKSwKICAgICAgaG91c2Vob2xkX2FiX3VzZV9wY3QgPSBtZWFuKGFueV9hYl9sYXN0X2lsbG5lc3MsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICkgJT4lCiAgICBmaWx0ZXIoaG91c2Vob2xkX2NvdW50ID49IHRocmVzaG9sZCkKICAKICAjIEpvaW4gZGF0YQogIGNvbW1fY29tcF9zZW5zIDwtIGlubmVyX2pvaW4oZmFybV9jb21tX3NlbnMsIGhvdXNlaG9sZF9jb21tX3NlbnMsIGJ5ID0gImdlb19pZCIpCiAgCiAgIyBDYWxjdWxhdGUgY29ycmVsYXRpb24KICBpZihucm93KGNvbW1fY29tcF9zZW5zKSA+IDUpIHsgICMgTmVlZCBhdCBsZWFzdCBhIGZldyBjb21tdW5pdGllcyBmb3IgbWVhbmluZ2Z1bCBjb3JyZWxhdGlvbgogICAgY29ycl9yZXN1bHQgPC0gY29yLnRlc3QoY29tbV9jb21wX3NlbnMkZmFybV9hYl91c2VfcGN0LCBjb21tX2NvbXBfc2VucyRob3VzZWhvbGRfYWJfdXNlX3BjdCkKICAgIAogICAgIyBTdG9yZSByZXN1bHRzCiAgICBzZW5zaXRpdml0eV9yZXN1bHRzIDwtIHJiaW5kKHNlbnNpdGl2aXR5X3Jlc3VsdHMsIGRhdGEuZnJhbWUoCiAgICAgIFRocmVzaG9sZCA9IHRocmVzaG9sZCwKICAgICAgTkNvbW11bml0aWVzID0gbnJvdyhjb21tX2NvbXBfc2VucyksCiAgICAgIENvcnJlbGF0aW9uID0gY29ycl9yZXN1bHQkZXN0aW1hdGUsCiAgICAgIFBWYWx1ZSA9IGNvcnJfcmVzdWx0JHAudmFsdWUsCiAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQogICAgKSkKICB9Cn0KCiMgRGlzcGxheSBzZW5zaXRpdml0eSBhbmFseXNpcyByZXN1bHRzCmlmKG5yb3coc2Vuc2l0aXZpdHlfcmVzdWx0cykgPiAwKSB7CiAgc2Vuc2l0aXZpdHlfcmVzdWx0cyAlPiUKICAgIG11dGF0ZSgKICAgICAgQ29ycmVsYXRpb24gPSByb3VuZChDb3JyZWxhdGlvbiwgMyksCiAgICAgIFBWYWx1ZSA9IHJvdW5kKFBWYWx1ZSwgMyksCiAgICAgIFNpZ25pZmljYW50ID0gaWZlbHNlKFBWYWx1ZSA8IDAuMDUsICJZZXMiLCAiTm8iKQogICAgKSAlPiUKICAgIGthYmxlKGNhcHRpb24gPSAiU2Vuc2l0aXZpdHkgQW5hbHlzaXM6IENvbW11bml0eS1MZXZlbCBDb3JyZWxhdGlvbnMgd2l0aCBEaWZmZXJlbnQgVGhyZXNob2xkcyIsCiAgICAgICAgICBjb2wubmFtZXMgPSBjKCJNaW5pbXVtIFJlc3BvbmRlbnRzIHBlciBDb21tdW5pdHkiLCAiTnVtYmVyIG9mIENvbW11bml0aWVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIkNvcnJlbGF0aW9uIiwgIlAtVmFsdWUiLCAiU2lnbmlmaWNhbnQiKSkgJT4lCiAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQp9IGVsc2UgewogIGNhdCgiXG5JbnN1ZmZpY2llbnQgZGF0YSBmb3Igc2Vuc2l0aXZpdHkgYW5hbHlzaXMgd2l0aCBkaWZmZXJlbnQgdGhyZXNob2xkcy5cbiIpCn0KCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyAxLiBHZW9ncmFwaGljIENvbW11bml0eSBBbmFseXNpcyB3aXRoIEVuaGFuY2VkIFNwYXRpYWwgU3RhdGlzdGljcwojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpjYXQoIlxuIyMgR2VvZ3JhcGhpYyBDb21tdW5pdHkgQW5hbHlzaXMgIyNcbiIpCgojIENoZWNrIGZvciBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMKaGFzX2dlb19jb29yZHMgPC0gYWxsKGMoImxhdGl0dWRlIiwgImxvbmdpdHVkZSIpICVpbiUgbmFtZXMoZmFybV9kYXRhKSkKCmlmKGhhc19nZW9fY29vcmRzKSB7CiAgIyBGaWx0ZXIgZmFybSBkYXRhIHRvIHJlY29yZHMgd2l0aCB2YWxpZCBjb29yZGluYXRlcwogIGdlb19mYXJtcyA8LSBmYXJtX2RhdGEgJT4lCiAgICBmaWx0ZXIoIWlzLm5hKGxhdGl0dWRlKSAmICFpcy5uYShsb25naXR1ZGUpKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoZmFybV9pZCwgbGF0aXR1ZGUsIGxvbmdpdHVkZSwgYW55X2FiX3VzZSwgYWJfdHJlYXRtZW50LCBhYl9wcmV2ZW50aW9uLCBhYl9ncm93dGgpCiAgCiAgIyBDYWxjdWxhdGUgZGlzdGFuY2UgbWF0cml4IGJldHdlZW4gZmFybXMgKGluIG1ldGVycykKICBpZihucm93KGdlb19mYXJtcykgPiAxMDAwKSB7CiAgY2F0KCJOb3RlOiBGYXJtIHNpemUgaXMgbGFyZ2UsIHVzZSBzcGF0aWFsIGluZGV4IHRvIG9wdGltaXNlIGRpc3RhbmNlIGNhbGN1bGF0aW9uLiIpCiAgZ2VvX2Zhcm1zX3NhbXBsZSA8LSBnZW9fZmFybXMgJT4lIHNhbXBsZV9uKG1pbigxMDAwLCBucm93KGdlb19mYXJtcykpKQogIGNvb3Jkc19tYXRyaXggPC0gZ2VvX2Zhcm1zX3NhbXBsZSAlPiUKICAgIGRwbHlyOjpzZWxlY3QobG9uZ2l0dWRlLCBsYXRpdHVkZSkgJT4lCiAgICBhcy5tYXRyaXgoKQp9IGVsc2UgewogIGNvb3Jkc19tYXRyaXggPC0gZ2VvX2Zhcm1zICU+JQogICAgZHBseXI6OnNlbGVjdChsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICAgIGFzLm1hdHJpeCgpCn0KICAKICBkaXN0X21hdHJpeCA8LSBkaXN0bShjb29yZHNfbWF0cml4LCBmdW4gPSBkaXN0SGF2ZXJzaW5lKQogIHJvd25hbWVzKGRpc3RfbWF0cml4KSA8LSBnZW9fZmFybXMkZmFybV9pZAogIGNvbG5hbWVzKGRpc3RfbWF0cml4KSA8LSBnZW9fZmFybXMkZmFybV9pZAogIAogICMgRGVmaW5lIGRpc3RhbmNlIHRocmVzaG9sZHMgdG8gdGVzdCAoaW4ga2lsb21ldGVycykKICB0aHJlc2hvbGRzX2ttIDwtIGMoMiwgNSwgMTApCiAgCiAgIyBJbml0aWFsaXplIHJlc3VsdHMgZGF0YWZyYW1lCiAgZ2VvX2NvbW11bml0eV9yZXN1bHRzIDwtIGRhdGEuZnJhbWUoCiAgICB0aHJlc2hvbGRfa20gPSBudW1lcmljKCksCiAgICBuX2NvbW11bml0aWVzID0gbnVtZXJpYygpLAogICAgbWVhbl9jb21tdW5pdHlfc2l6ZSA9IG51bWVyaWMoKSwKICAgIHdpdGhpbl9jb21tdW5pdHlfYWJfY29ycmVsYXRpb24gPSBudW1lcmljKCksCiAgICBwX3ZhbHVlID0gbnVtZXJpYygpLAogICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCiAgKQogIAogIGZvcih0aHJlc2hvbGRfa20gaW4gdGhyZXNob2xkc19rbSkgewogICAgdGhyZXNob2xkX20gPC0gdGhyZXNob2xkX2ttICogMTAwMAogICAgCiAgICAjIENyZWF0ZSBhZGphY2VuY3kgbWF0cml4IGJhc2VkIG9uIHRocmVzaG9sZAogICAgYWRqX21hdHJpeCA8LSBkaXN0X21hdHJpeCA8IHRocmVzaG9sZF9tICYgZGlzdF9tYXRyaXggPiAwICAjIEV4Y2x1ZGUgc2VsZi1jb25uZWN0aW9ucwogICAgCiAgICAjIENvbnZlcnQgdG8gaWdyYXBoIG9iamVjdAogICAgZyA8LSBncmFwaF9mcm9tX2FkamFjZW5jeV9tYXRyaXgoYWRqX21hdHJpeCwgbW9kZSA9ICJ1bmRpcmVjdGVkIikKICAgIAogICAgIyBJZGVudGlmeSBjb21tdW5pdGllcyAoY29ubmVjdGVkIGNvbXBvbmVudHMpCiAgICBjb21tdW5pdGllcyA8LSBjb21wb25lbnRzKGcpCiAgICAKICAgICMgTGFiZWwgZWFjaCBmYXJtIHdpdGggaXRzIGNvbW11bml0eSBJRAogICAgZ2VvX2Zhcm1zJGdlb19jb21tdW5pdHlfaWQgPC0gY29tbXVuaXRpZXMkbWVtYmVyc2hpcAogICAgCiAgICAjIEZpbHRlciB0byBjb21tdW5pdGllcyB3aXRoIGF0IGxlYXN0IDMgZmFybXMKICAgIHZhbGlkX2NvbW11bml0aWVzIDwtIGdlb19mYXJtcyAlPiUKICAgICAgY291bnQoZ2VvX2NvbW11bml0eV9pZCkgJT4lCiAgICAgIGZpbHRlcihuID49IDMpICU+JQogICAgICBwdWxsKGdlb19jb21tdW5pdHlfaWQpCiAgICAKICAgIGlmKGxlbmd0aCh2YWxpZF9jb21tdW5pdGllcykgPiAwKSB7CiAgICAgICMgRmlsdGVyIGZhcm1zIHRvIHRob3NlIGluIHZhbGlkIGNvbW11bml0aWVzCiAgICAgIGNvbW11bml0eV9mYXJtcyA8LSBnZW9fZmFybXMgJT4lCiAgICAgICAgZmlsdGVyKGdlb19jb21tdW5pdHlfaWQgJWluJSB2YWxpZF9jb21tdW5pdGllcykKICAgICAgCiAgICAgICMgQ29tcHV0ZSB3aXRoaW4tY29tbXVuaXR5IHNpbWlsYXJpdHkgaW4gYW50aWJpb3RpYyB1c2UKICAgICAgaWYobnJvdyhjb21tdW5pdHlfZmFybXMpID49IDEwKSB7ICAjIE5lZWQgc3VmZmljaWVudCBkYXRhIGZvciBtZWFuaW5nZnVsIHRlc3QKICAgICAgICAjIENhbGN1bGF0ZSBhdmVyYWdlIHdpdGhpbi1jb21tdW5pdHkgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGFudGliaW90aWMgdXNlCiAgICAgICAgY29tbXVuaXR5X3N0YXRzIDwtIGNvbW11bml0eV9mYXJtcyAlPiUKICAgICAgICAgIGdyb3VwX2J5KGdlb19jb21tdW5pdHlfaWQpICU+JQogICAgICAgICAgc3VtbWFyaXplKAogICAgICAgICAgICBhYl91c2Vfc2QgPSBzZChhbnlfYWJfdXNlLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICBhYl91c2VfbWVhbiA9IG1lYW4oYW55X2FiX3VzZSwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgbl9mYXJtcyA9IG4oKSwKICAgICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgICAgICAgKQogICAgICAgICAgCiAgICAgICAgIyBDYWxjdWxhdGUgb3ZlcmFsbCBzdGFuZGFyZCBkZXZpYXRpb24gZm9yIGNvbXBhcmlzb24KICAgICAgICBvdmVyYWxsX3NkIDwtIHNkKGNvbW11bml0eV9mYXJtcyRhbnlfYWJfdXNlLCBuYS5ybSA9IFRSVUUpCiAgICAgICAgICAKICAgICAgICAjIENhbGN1bGF0ZSB3ZWlnaHRlZCBhdmVyYWdlIG9mIHdpdGhpbi1jb21tdW5pdHkgU0QKICAgICAgICB3ZWlnaHRlZF9hdmdfc2QgPC0gc3VtKGNvbW11bml0eV9zdGF0cyRhYl91c2Vfc2QgKiBjb21tdW5pdHlfc3RhdHMkbl9mYXJtcykgLyBzdW0oY29tbXVuaXR5X3N0YXRzJG5fZmFybXMpCiAgICAgICAgICAKICAgICAgICAjIFN0b3JlIHJlc3VsdHMKICAgICAgICBnZW9fY29tbXVuaXR5X3Jlc3VsdHMgPC0gcmJpbmQoZ2VvX2NvbW11bml0eV9yZXN1bHRzLCBkYXRhLmZyYW1lKAogICAgICAgICAgdGhyZXNob2xkX2ttID0gdGhyZXNob2xkX2ttLAogICAgICAgICAgbl9jb21tdW5pdGllcyA9IGxlbmd0aCh2YWxpZF9jb21tdW5pdGllcyksCiAgICAgICAgICBtZWFuX2NvbW11bml0eV9zaXplID0gbWVhbihjb21tdW5pdHlfc3RhdHMkbl9mYXJtcyksCiAgICAgICAgICB3aXRoaW5fY29tbXVuaXR5X2FiX2NvcnJlbGF0aW9uID0gMSAtICh3ZWlnaHRlZF9hdmdfc2QgLyBvdmVyYWxsX3NkKSwgIyBIaWdoZXIgdmFsdWUgPSBtb3JlIHNpbWlsYXJpdHkKICAgICAgICAgIHBfdmFsdWUgPSBOQSwgIyBXaWxsIGZpbGwgd2l0aCBhcHByb3ByaWF0ZSB0ZXN0IGlmIGF2YWlsYWJsZQogICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFCiAgICAgICAgKSkKICAgICAgICAKICAgICAgICAjIFZpc3VhbGl6YXRpb24gZm9yIDVrbSB0aHJlc2hvbGQgCiAgICAgICAgaWYodGhyZXNob2xkX2ttID09IDUpIHsKICAgICAgICAgICMgQ29udmVydCB0byBzZiBvYmplY3RzIGZvciBtYXBwaW5nCiAgICAgICAgICBmYXJtc19zZiA8LSBzdF9hc19zZihjb21tdW5pdHlfZmFybXMsIGNvb3JkcyA9IGMoImxvbmdpdHVkZSIsICJsYXRpdHVkZSIpLCBjcnMgPSA0MzI2KQogICAgICAgICAgCiAgICAgICAgICAjIENyZWF0ZSBwbG90CiAgICAgICAgICBnZW9fY29tbXVuaXR5X3Bsb3QgPC0gZ2dwbG90KCkgKwogICAgICAgICAgICBnZW9tX3NmKGRhdGEgPSBmYXJtc19zZiwgYWVzKGNvbG9yID0gZmFjdG9yKGdlb19jb21tdW5pdHlfaWQpLCBzaXplID0gYW55X2FiX3VzZSkpICsKICAgICAgICAgICAgc2NhbGVfY29sb3JfdmlyaWRpc19kKG5hbWUgPSAiR2VvZ3JhcGhpY1xuQ29tbXVuaXR5IikgKwogICAgICAgICAgICBzY2FsZV9zaXplX2NvbnRpbnVvdXMobmFtZSA9ICJBbnRpYmlvdGljIFVzZSIsIHJhbmdlID0gYygxLCA1KSkgKwogICAgICAgICAgICBsYWJzKHRpdGxlID0gcGFzdGUwKCJHZW9ncmFwaGljIENvbW11bml0aWVzIG9mIEZhcm1zICgiLCB0aHJlc2hvbGRfa20sICJrbSB0aHJlc2hvbGQpIiksCiAgICAgICAgICAgICAgICAgc3VidGl0bGUgPSAiUG9pbnQgc2l6ZSBpbmRpY2F0ZXMgYW50aWJpb3RpYyB1c2UgcHJldmFsZW5jZSIpICsKICAgICAgICAgICAgdGhlbWVfbWluaW1hbCgpCiAgICAgICAgICAKICAgICAgICAgIHByaW50KGdlb19jb21tdW5pdHlfcGxvdCkKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgCiAgIyBEaXNwbGF5IGdlb2dyYXBoaWMgY29tbXVuaXR5IHJlc3VsdHMgdGFibGUKICBpZihucm93KGdlb19jb21tdW5pdHlfcmVzdWx0cykgPiAwKSB7CiAgICBnZW9fY29tbXVuaXR5X3Jlc3VsdHMgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICB3aXRoaW5fY29tbXVuaXR5X2FiX2NvcnJlbGF0aW9uID0gcm91bmQod2l0aGluX2NvbW11bml0eV9hYl9jb3JyZWxhdGlvbiwgMyksCiAgICAgICAgcF92YWx1ZSA9IGlmZWxzZShpcy5uYShwX3ZhbHVlKSwgTkEsIHJvdW5kKHBfdmFsdWUsIDMpKSwKICAgICAgICBzaWduaWZpY2FudCA9IGlmZWxzZShwX3ZhbHVlIDwgMC4wNSwgIlllcyIsIGlmZWxzZShpcy5uYShwX3ZhbHVlKSwgIk5BIiwgIk5vIikpCiAgICAgICkgJT4lCiAgICAgIGthYmxlKGNhcHRpb24gPSAiR2VvZ3JhcGhpYyBDb21tdW5pdHkgQW5hbHlzaXMgUmVzdWx0cyBmb3IgRGlmZmVyZW50IERpc3RhbmNlIFRocmVzaG9sZHMiLAogICAgICAgICAgICBjb2wubmFtZXMgPSBjKCJEaXN0YW5jZSBUaHJlc2hvbGQgKGttKSIsICJOdW1iZXIgb2YgQ29tbXVuaXRpZXMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICJNZWFuIENvbW11bml0eSBTaXplIiwgIldpdGhpbi1Db21tdW5pdHkgU2ltaWxhcml0eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIlAtVmFsdWUiLCAiU2lnbmlmaWNhbnQiKSkgJT4lCiAgICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRkFMU0UpCiAgfQogIAogICMgRW5oYW5jZWQgU3BhdGlhbCBBbmFseXNpczogTW9yYW4ncyBJIGFuZCBMSVNBIFN0YXRpc3RpY3MKICBpZihucm93KGdlb19mYXJtcykgPj0gMTApIHsKICAgIGNhdCgiXG4jIyBTcGF0aWFsIEF1dG9jb3JyZWxhdGlvbiBBbmFseXNpcyAjI1xuIikKICAgIAogICAgIyBDcmVhdGUgc3BhdGlhbCB3ZWlnaHRzIG1hdHJpeCBmb3IgZmFybXMKICAgIGNvb3JkaW5hdGVzIDwtIGNvb3Jkc19tYXRyaXgKICAgIGsgPC0gbWluKDE1LCBucm93KGdlb19mYXJtcykgLSAxKSAgIyBDaG9vc2UgYXBwcm9wcmlhdGUgayB2YWx1ZQogICAga25uIDwtIGtuZWFybmVpZ2goY29vcmRpbmF0ZXMsIGsgPSBrKQogICAgbmVpZ2hib3JzIDwtIGtubjJuYihrbm4pCiAgICB3ZWlnaHRzIDwtIG5iMmxpc3R3KG5laWdoYm9ycywgc3R5bGUgPSAiVyIpCiAgICAKICAgICMgQ2FsY3VsYXRlIEdsb2JhbCBNb3JhbidzIEkgZm9yIGFudGliaW90aWMgdXNlCiAgICBtb3Jhbl9yZXN1bHQgPC0gbW9yYW4udGVzdChnZW9fZmFybXMkYW55X2FiX3VzZSwgd2VpZ2h0cykKICAgIAogICAgIyBSZXBvcnQgTW9yYW4ncyBJIHJlc3VsdHMKICAgIGNhdCgiR2xvYmFsIE1vcmFuJ3MgSSBmb3IgYW50aWJpb3RpYyB1c2U6Iiwgcm91bmQobW9yYW5fcmVzdWx0JGVzdGltYXRlWzFdLCAzKSwgCiAgICAgICAgIiwgcC12YWx1ZToiLCByb3VuZChtb3Jhbl9yZXN1bHQkcC52YWx1ZSwgMyksICJcbiIpCiAgICB0cmVuZF9tb2RlbCA8LSBsbShhbnlfYWJfdXNlIH4gbG9uZ2l0dWRlICsgbGF0aXR1ZGUsIGRhdGEgPSBnZW9fZmFybXMpCnRyZW5kX3N1bW1hcnkgPC0gc3VtbWFyeSh0cmVuZF9tb2RlbCkKCmNhdCgiRXhhbWluZSBzcGF0aWFsIHRyZW5kcyBpbiBhbnRpYmlvdGljIHVzZVxuIikKY2F0KCJTcGF0aWFsIHRyZW5kIG1vZGVsIFLCsjoiLCByb3VuZCh0cmVuZF9zdW1tYXJ5JHIuc3F1YXJlZCwgMyksIAogICAgIiwgcF92YWx1ZToiLCByb3VuZCh0cmVuZF9zdW1tYXJ5JGNvZWZmaWNpZW50c1syLDRdLCAzKSwgIi8iLCAKICAgIHJvdW5kKHRyZW5kX3N1bW1hcnkkY29lZmZpY2llbnRzWzMsNF0sIDMpLCAiXG4iKQoKIyBJZiB0aGVyZSBpcyBhIHNwYXRpYWwgdHJlbmQsIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGlzIGFuYWx5c2VkIGFmdGVyIGNvbnNpZGVyaW5nIGRlLXRyZW5kaW5nCmlmKHRyZW5kX3N1bW1hcnkkY29lZmZpY2llbnRzWzIsNF0gPCAwLjA1IHx8IHRyZW5kX3N1bW1hcnkkY29lZmZpY2llbnRzWzMsNF0gPCAwLjA1KSB7CiAgY2F0KCJUaGVyZSBpcyBhIHNpZ25pZmljYW50IHNwYXRpYWwgdHJlbmQuIENvbnNpZGVyIGRldHJlbmRpbmcgYmVmb3JlIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGFuYWx5c2lzXG4iKQogIGdlb19mYXJtcyRhYl91c2VfZGV0cmVuZGVkIDwtIHJlc2lkdWFscyh0cmVuZF9tb2RlbCkKICAKICAjIFJlY2FsY3VsYXRpbmcgc3BhdGlhbCBhdXRvY29ycmVsYXRpb24gdXNpbmcgZGV0cmVuZGVkIGRhdGEKICBtb3Jhbl9kZXRyZW5kZWQgPC0gbW9yYW4udGVzdChnZW9fZmFybXMkYWJfdXNlX2RldHJlbmRlZCwgd2VpZ2h0cykKICBjYXQoIk1vcmFuJ3MgSSBhZnRlciB0cmVuZCByZW1vdmFsOiIsIHJvdW5kKG1vcmFuX2RldHJlbmRlZCRlc3RpbWF0ZVsxXSwgMyksIAogICAgICAiLCBwX3ZhbHVlOiIsIHJvdW5kKG1vcmFuX2RldHJlbmRlZCRwLnZhbHVlLCAzKSwgIlxuIikKfQogICAgCiAgICAjIENhbGN1bGF0ZSBMSVNBCiAgICBsaXNhX3Jlc3VsdHMgPC0gbG9jYWxtb3JhbihnZW9fZmFybXMkYW55X2FiX3VzZSwgd2VpZ2h0cykKICAgIAogICAgIyBBZGQgTElTQSByZXN1bHRzIHRvIGZhcm0gZGF0YQogICAgZ2VvX2Zhcm1zJGxpc2FfaSA8LSBsaXNhX3Jlc3VsdHNbLCAxXQogICAgZ2VvX2Zhcm1zJGxpc2FfcCA8LSBsaXNhX3Jlc3VsdHNbLCA1XQogICAgCiAgICAjIElkZW50aWZ5IGhvdHNwb3RzIGFuZCBjb2xkc3BvdHMKICAgIG1lYW5fYWJfdXNlIDwtIG1lYW4oZ2VvX2Zhcm1zJGFueV9hYl91c2UsIG5hLnJtID0gVFJVRSkKICAgIGdlb19mYXJtcyA8LSBnZW9fZmFybXMgJT4lCiAgICAgIG11dGF0ZSgKICAgICAgICBjbHVzdGVyX3R5cGUgPSBjYXNlX3doZW4oCiAgICAgICAgICBsaXNhX3AgPD0gMC4wNSAmIGxpc2FfaSA+IDAgJiBhbnlfYWJfdXNlID4gbWVhbl9hYl91c2UgfiAiSG90c3BvdCIsCiAgICAgICAgICBsaXNhX3AgPD0gMC4wNSAmIGxpc2FfaSA+IDAgJiBhbnlfYWJfdXNlIDw9IG1lYW5fYWJfdXNlIH4gIkNvbGRzcG90IiwKICAgICAgICAgIGxpc2FfcCA8PSAwLjA1ICYgbGlzYV9pIDwgMCB+ICJTcGF0aWFsIE91dGxpZXIiLAogICAgICAgICAgVFJVRSB+ICJOb3QgU2lnbmlmaWNhbnQiCiAgICAgICAgKQogICAgICApCiAgICAKICAgICMgVmlzdWFsaXplIExJU0EgY2x1c3RlcnMKICAgIGxpc2FfcGxvdCA8LSBnZ3Bsb3QoZ2VvX2Zhcm1zLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBjb2xvciA9IGNsdXN0ZXJfdHlwZSkpICsKICAgICAgZ2VvbV9wb2ludChzaXplID0gMywgYWxwaGEgPSAwLjgpICsKICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIkhvdHNwb3QiID0gInJlZCIsICJDb2xkc3BvdCIgPSAiYmx1ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTcGF0aWFsIE91dGxpZXIiID0gInB1cnBsZSIsICJOb3QgU2lnbmlmaWNhbnQiID0gImdyZXkiKSkgKwogICAgICBsYWJzKHRpdGxlID0gIlNwYXRpYWwgQ2x1c3RlcmluZyBvZiBBbnRpYmlvdGljIFVzZSIsCiAgICAgICAgICAgc3VidGl0bGUgPSAiQmFzZWQgb24gTG9jYWwgSW5kaWNhdG9ycyBvZiBTcGF0aWFsIEFzc29jaWF0aW9uIChMSVNBKSIsCiAgICAgICAgICAgeCA9ICJMb25naXR1ZGUiLAogICAgICAgICAgIHkgPSAiTGF0aXR1ZGUiLAogICAgICAgICAgIGNvbG9yID0gIkNsdXN0ZXIgVHlwZSIpICsKICAgICAgdGhlbWVfbWluaW1hbCgpCiAgICAKICAgIHByaW50KGxpc2FfcGxvdCkKICAgIAogICAgIyBTaG93IGNsdXN0ZXIgc3VtbWFyeSBzdGF0aXN0aWNzCiAgICBnZW9fZmFybXMgJT4lCiAgICAgIGNvdW50KGNsdXN0ZXJfdHlwZSkgJT4lCiAgICAgIG11dGF0ZShwZXJjZW50YWdlID0gbiAvIHN1bShuKSAqIDEwMCkgJT4lCiAgICAgIGFycmFuZ2UoZGVzYyhuKSkgJT4lCiAgICAgIGthYmxlKGNhcHRpb24gPSAiU3VtbWFyeSBvZiBTcGF0aWFsIENsdXN0ZXJpbmciLAogICAgICAgICAgICBjb2wubmFtZXMgPSBjKCJDbHVzdGVyIFR5cGUiLCAiTnVtYmVyIG9mIEZhcm1zIiwgIlBlcmNlbnRhZ2UiKSkgJT4lCiAgICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRkFMU0UpCiAgfQogIAogICMgQW5hbHl6ZSBkaXN0YW5jZSBkZWNheSBlZmZlY3QKICBjYXQoIlxuIyMgRGlzdGFuY2UgRGVjYXkgQW5hbHlzaXMgIyNcbiIpCiAgCiAgIyBDcmVhdGUgZGlzdGFuY2UgYmlucyAoaW4ga2lsb21ldGVycykKICBkaXN0YW5jZV9iaW5zIDwtIGMoMCwgMSwgMiwgNSwgMTAsIDIwLCA1MCkKICBkaXN0YW5jZV9iaW5zX20gPC0gZGlzdGFuY2VfYmlucyAqIDEwMDAgICMgQ29udmVydCB0byBtZXRlcnMKICAKICAjIEluaXRpYWxpemUgcmVzdWx0cyBkYXRhZnJhbWUKICBkaXN0YW5jZV9kZWNheSA8LSBkYXRhLmZyYW1lKAogICAgZGlzdGFuY2VfbWluX2ttID0gZGlzdGFuY2VfYmluc1stbGVuZ3RoKGRpc3RhbmNlX2JpbnMpXSwKICAgIGRpc3RhbmNlX21heF9rbSA9IGRpc3RhbmNlX2JpbnNbLTFdLAogICAgZmFybV9wYWlycyA9IG51bWVyaWMobGVuZ3RoKGRpc3RhbmNlX2JpbnMpIC0gMSksCiAgICBjb3JyZWxhdGlvbiA9IG51bWVyaWMobGVuZ3RoKGRpc3RhbmNlX2JpbnMpIC0gMSksCiAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UKICApCiAgCiAgIyBDYWxjdWxhdGUgY29ycmVsYXRpb24gYXQgZGlmZmVyZW50IGRpc3RhbmNlIGJhbmRzCiAgZm9yKGkgaW4gMToobGVuZ3RoKGRpc3RhbmNlX2JpbnNfbSkgLSAxKSkgewogICAgIyBGaWx0ZXIgZmFybSBwYWlycyB3aXRoaW4gdGhpcyBkaXN0YW5jZSBiYW5kCiAgICBwYWlyc19tYXNrIDwtIGRpc3RfbWF0cml4ID4gZGlzdGFuY2VfYmluc19tW2ldICYgZGlzdF9tYXRyaXggPD0gZGlzdGFuY2VfYmluc19tW2krMV0KICAgIAogICAgIyBOZWVkIHN1ZmZpY2llbnQgcGFpcnMgZm9yIG1lYW5pbmdmdWwgY29ycmVsYXRpb24KICAgIGlmKHN1bShwYWlyc19tYXNrKSA+PSAxMCkgewogICAgICAjIEdldCBjb29yZGluYXRlcyBvZiBwYWlycyBpbiB0aGlzIGRpc3RhbmNlIGJhbmQKICAgICAgZmFybV9wYWlycyA8LSB3aGljaChwYWlyc19tYXNrLCBhcnIuaW5kID0gVFJVRSkKICAgICAgCiAgICAgICMgRXh0cmFjdCBhbnRpYmlvdGljIHVzZSB2YWx1ZXMKICAgICAgYWJfdXNlXzEgPC0gZ2VvX2Zhcm1zJGFueV9hYl91c2VbZmFybV9wYWlyc1ssIDFdXQogICAgICBhYl91c2VfMiA8LSBnZW9fZmFybXMkYW55X2FiX3VzZVtmYXJtX3BhaXJzWywgMl1dCiAgICAgIAogICAgICAjIENhbGN1bGF0ZSBjb3JyZWxhdGlvbgogICAgICBkaXN0YW5jZV9kZWNheSRmYXJtX3BhaXJzW2ldIDwtIGxlbmd0aChhYl91c2VfMSkKICAgICAgZGlzdGFuY2VfZGVjYXkkY29ycmVsYXRpb25baV0gPC0gY29yKGFiX3VzZV8xLCBhYl91c2VfMiwgdXNlID0gInBhaXJ3aXNlLmNvbXBsZXRlLm9icyIpCiAgICB9CiAgfQogIAogICMgRGlzcGxheSBkaXN0YW5jZSBkZWNheSByZXN1bHRzCiAgZGlzdGFuY2VfZGVjYXkgJT4lCiAgICBmaWx0ZXIoZmFybV9wYWlycyA+IDApICU+JQogICAgbXV0YXRlKGNvcnJlbGF0aW9uID0gcm91bmQoY29ycmVsYXRpb24sIDMpKSAlPiUKICAgIGthYmxlKGNhcHRpb24gPSAiRGlzdGFuY2UgRGVjYXkgRWZmZWN0IGluIEFudGliaW90aWMgVXNlIFNpbWlsYXJpdHkiLAogICAgICAgICAgY29sLm5hbWVzID0gYygiTWluIERpc3RhbmNlIChrbSkiLCAiTWF4IERpc3RhbmNlIChrbSkiLCAKICAgICAgICAgICAgICAgICAgICAgICAiTnVtYmVyIG9mIEZhcm0gUGFpcnMiLCAiQ29ycmVsYXRpb24iKSwKICAgICAgICAgIGRpZ2l0cyA9IGMoMSwgMSwgMCwgMykpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkKICAKICAjIFZpc3VhbGl6ZSBkaXN0YW5jZSBkZWNheSBlZmZlY3QKICBkZWNheV9wbG90IDwtIGdncGxvdChkaXN0YW5jZV9kZWNheSAlPiUgZmlsdGVyKGZhcm1fcGFpcnMgPiAwKSwgCiAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSAoZGlzdGFuY2VfbWluX2ttICsgZGlzdGFuY2VfbWF4X2ttKS8yLCB5ID0gY29ycmVsYXRpb24pKSArCiAgICBnZW9tX3BvaW50KGFlcyhzaXplID0gZmFybV9wYWlycyksIGFscGhhID0gMC43KSArCiAgICBnZW9tX2xpbmUoKSArCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJncmV5NTAiKSArCiAgICBsYWJzKHRpdGxlID0gIkRpc3RhbmNlIERlY2F5IEVmZmVjdCBpbiBBbnRpYmlvdGljIFVzZSBTaW1pbGFyaXR5IiwKICAgICAgICAgeCA9ICJEaXN0YW5jZSAoa20pIiwKICAgICAgICAgeSA9ICJDb3JyZWxhdGlvbiBDb2VmZmljaWVudCIsCiAgICAgICAgIHNpemUgPSAiTnVtYmVyIG9mIEZhcm0gUGFpcnMiKSArCiAgICB0aGVtZV9taW5pbWFsKCkKICAKICBwcmludChkZWNheV9wbG90KQp9IGVsc2UgewogIGNhdCgiR2VvZ3JhcGhpYyBjb29yZGluYXRlcyBub3QgYXZhaWxhYmxlIGZvciBzcGF0aWFsIGNvbW11bml0eSBhbmFseXNpcy5cbiIpCn0KCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyAyLiBJbmZvcm1hdGlvbiBUcmFuc21pc3Npb24gTmV0d29yayBBbmFseXNpcyB3aXRoIEVuaGFuY2VkIFNvdXJjZSBBbmFseXNpcwojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpjYXQoIlxuIyMgSW5mb3JtYXRpb24gVHJhbnNtaXNzaW9uIE5ldHdvcmsgQW5hbHlzaXMgIyNcbiIpCgojIENoZWNrIGZvciBpbmZvcm1hdGlvbiBzb3VyY2UgdmFyaWFibGVzCmlmKGFsbChjKCJhZHZpY2UxIiwgImFkdmljZTIiLCAiYWR2aWNlMyIpICVpbiUgbmFtZXMoZmFybV9kYXRhKSkpIHsKICAjIFN0YW5kYXJkaXplIGFuZCBjbGVhbiBpbmZvcm1hdGlvbiBzb3VyY2UgdmFyaWFibGVzCiAgZmFybV9pbmZvIDwtIGZhcm1fZGF0YSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoZmFybV9pZCwgYWR2aWNlMSwgYWR2aWNlMiwgYWR2aWNlMywgYW55X2FiX3VzZSwgYWJfdHJlYXRtZW50LCBhYl9wcmV2ZW50aW9uLCBhYl9ncm93dGgpICU+JQogICAgZmlsdGVyKCFpcy5uYShhZHZpY2UxKSkgICMgQXQgbGVhc3QgcHJpbWFyeSBhZHZpY2Ugc291cmNlIG11c3QgYmUgYXZhaWxhYmxlCiAgCiAgY2F0KCJBbmFseXppbmciLCBucm93KGZhcm1faW5mbyksICJmYXJtcyB3aXRoIGluZm9ybWF0aW9uIHNvdXJjZSBkYXRhLi4uXG4iKQogIAogICMgQ29udmVydCB0byBsb3dlcmNhc2UgYW5kIHN0YW5kYXJkaXplIHNvdXJjZSBuYW1lcyBpZiB0ZXh0CiAgaWYoaXMuY2hhcmFjdGVyKGZhcm1faW5mbyRhZHZpY2UxKSkgewogICAgIyBDcmVhdGUgYSBmdW5jdGlvbiB0byBjYXRlZ29yaXplIGFkdmljZSBzb3VyY2VzCiAgICBjYXRlZ29yaXplX2FkdmljZSA8LSBmdW5jdGlvbihhZHZpY2UpIHsKICAgICAgY2FzZV93aGVuKAogICAgICAgIGdyZXBsKCJ2ZXR8ZG9jdG9yfGhlYWx0aHxtZWRpYyIsIGFkdmljZSwgaWdub3JlLmNhc2UgPSBUUlVFKSB+ICJQcm9mZXNzaW9uYWwgaGVhbHRoY2FyZSIsCiAgICAgICAgZ3JlcGwoInBoYXJtfGRydWciLCBhZHZpY2UsIGlnbm9yZS5jYXNlID0gVFJVRSkgfiAiUGhhcm1hY3kvZHJ1ZyBzdG9yZSIsCiAgICAgICAgZ3JlcGwoImZyaWVuZHxuZWlnaGJvcnxyZWxhdGl2ZXxmYW1pbHkiLCBhZHZpY2UsIGlnbm9yZS5jYXNlID0gVFJVRSkgfiAiU29jaWFsIG5ldHdvcmsiLAogICAgICAgIGdyZXBsKCJ0dnxyYWRpb3xpbnRlcm5ldHxtZWRpYXxuZXdzIiwgYWR2aWNlLCBpZ25vcmUuY2FzZSA9IFRSVUUpIH4gIk1lZGlhIiwKICAgICAgICBncmVwbCgiY29tcGFueXxzdXBwbGllcnxzYWxlIiwgYWR2aWNlLCBpZ25vcmUuY2FzZSA9IFRSVUUpIH4gIlN1cHBsaWVyL2NvbXBhbnkiLAogICAgICAgICFpcy5uYShhZHZpY2UpIH4gIk90aGVyIiwKICAgICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXwogICAgICApCiAgICB9CiAgICAKICAgICMgQXBwbHkgc3RhbmRhcmRpemF0aW9uIHRvIGFsbCBhZHZpY2Ugc291cmNlcwogICAgdW5pcXVlX3NvdXJjZXMgPC0gdW5pcXVlKG5hLm9taXQoYyhmYXJtX2luZm8kYWR2aWNlMSwgZmFybV9pbmZvJGFkdmljZTIsIGZhcm1faW5mbyRhZHZpY2UzKSkpCgppZihsZW5ndGgodW5pcXVlX3NvdXJjZXMpID4gMjApIHsKICBjYXQoIk1hbnkgZGlmZmVyZW50IHNvdXJjZXMgb2YgaW5mb3JtYXRpb24gZXhpc3QgKCIsIGxlbmd0aCh1bmlxdWVfc291cmNlcyksICIp77yMQ29uc2lkZXIgdXNpbmcgdGV4dCBhbmFseXNpcyBtZXRob2RzXG4iKQogIGlmKHJlcXVpcmVOYW1lc3BhY2UoInRtIiwgcXVpZXRseSA9IFRSVUUpICYmIHJlcXVpcmVOYW1lc3BhY2UoInByb3h5IiwgcXVpZXRseSA9IFRSVUUpKSB7CiAgICBzb3VyY2VfY29ycHVzIDwtIHRtOjpDb3JwdXModG06OlZlY3RvclNvdXJjZSh1bmlxdWVfc291cmNlcykpCiAgICBzb3VyY2VfZHRtIDwtIHRtOjpEb2N1bWVudFRlcm1NYXRyaXgoc291cmNlX2NvcnB1cykKICAgIHNvdXJjZV9kaXN0IDwtIHByb3h5OjpkaXN0KGFzLm1hdHJpeChzb3VyY2VfZHRtKSkKICAgIHNvdXJjZV9jbHVzdGVycyA8LSBoY2x1c3Qoc291cmNlX2Rpc3QpCiAgICBudW1fY2x1c3RlcnMgPC0gbWluKDUsIGxlbmd0aCh1bmlxdWVfc291cmNlcykgJS8lIDQpIAogICAgc291cmNlX2NhdGVnb3JpZXMgPC0gY3V0cmVlKHNvdXJjZV9jbHVzdGVycywgayA9IG51bV9jbHVzdGVycykKICB9Cn0KICAgIAogICAgZmFybV9pbmZvIDwtIGZhcm1faW5mbyAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIGFkdmljZTFfY2F0ZWdvcnkgPSBjYXRlZ29yaXplX2FkdmljZShhZHZpY2UxKSwKICAgICAgICBhZHZpY2UyX2NhdGVnb3J5ID0gY2F0ZWdvcml6ZV9hZHZpY2UoYWR2aWNlMiksCiAgICAgICAgYWR2aWNlM19jYXRlZ29yeSA9IGNhdGVnb3JpemVfYWR2aWNlKGFkdmljZTMpLAogICAgICAgIHByaW1hcnlfc291cmNlX3N0ZCA9IGFkdmljZTFfY2F0ZWdvcnkgICMgVXNlIGZpcnN0IGFkdmljZSBzb3VyY2UgYXMgcHJpbWFyeQogICAgICApCiAgICAKICAgICMgU2hvdyBkaXN0cmlidXRpb24gb2YgcHJpbWFyeSBpbmZvcm1hdGlvbiBzb3VyY2VzCiAgICBmYXJtX2luZm8gJT4lCiAgICAgIGNvdW50KHByaW1hcnlfc291cmNlX3N0ZCkgJT4lCiAgICAgIG11dGF0ZShwZXJjZW50YWdlID0gbiAvIHN1bShuKSAqIDEwMCkgJT4lCiAgICAgIGFycmFuZ2UoZGVzYyhuKSkgJT4lCiAgICAgIGthYmxlKGNhcHRpb24gPSAiRGlzdHJpYnV0aW9uIG9mIFByaW1hcnkgSW5mb3JtYXRpb24gU291cmNlcyBmb3IgQW50aWJpb3RpYyBVc2UiLAogICAgICAgICAgICBjb2wubmFtZXMgPSBjKCJJbmZvcm1hdGlvbiBTb3VyY2UiLCAiTnVtYmVyIG9mIEZhcm1zIiwgIlBlcmNlbnRhZ2UgKCUpIiksCiAgICAgICAgICAgIGRpZ2l0cyA9IGMoMCwgMCwgMSkpICU+JQogICAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQogICAgCiAgICAjIEFuYWx5emUgYW50aWJpb3RpYyB1c2UgYnkgaW5mb3JtYXRpb24gc291cmNlCiAgICBzb3VyY2Vfc3VtbWFyeSA8LSBmYXJtX2luZm8gJT4lCiAgICAgIGdyb3VwX2J5KHByaW1hcnlfc291cmNlX3N0ZCkgJT4lCiAgICAgIHN1bW1hcmlzZSgKICAgICAgICBuX2Zhcm1zID0gbigpLAogICAgICAgIGFiX3VzZV9wY3QgPSBtZWFuKGFueV9hYl91c2UsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICAgICAgYWJfdHJlYXRtZW50X3BjdCA9IG1lYW4oYWJfdHJlYXRtZW50LCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICAgIGFiX3ByZXZlbnRpb25fcGN0ID0gbWVhbihhYl9wcmV2ZW50aW9uLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICAgIGFiX2dyb3d0aF9wY3QgPSBtZWFuKGFiX2dyb3d0aCwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICAgICkgJT4lCiAgICAgIGZpbHRlcihuX2Zhcm1zID49IDUpICAjIE9ubHkgaW5jbHVkZSBzb3VyY2VzIHdpdGggc3VmZmljaWVudCBkYXRhCiAgICAKICAgICMgRGlzcGxheSByZXN1bHRzCiAgICBzb3VyY2Vfc3VtbWFyeSAlPiUKICAgICAgbXV0YXRlKGFjcm9zcyhlbmRzX3dpdGgoIl9wY3QiKSwgfiByb3VuZCguLCAxKSkpICU+JQogICAgICBrYWJsZShjYXB0aW9uID0gIkFudGliaW90aWMgVXNlIFBhdHRlcm5zIGJ5IFByaW1hcnkgSW5mb3JtYXRpb24gU291cmNlIiwKICAgICAgICAgICAgY29sLm5hbWVzID0gYygiSW5mb3JtYXRpb24gU291cmNlIiwgIk51bWJlciBvZiBGYXJtcyIsICJBbnkgQW50aWJpb3RpYyBVc2UgKCUpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJUcmVhdG1lbnQgVXNlICglKSIsICJQcmV2ZW50aW9uIFVzZSAoJSkiLCAiR3Jvd3RoIFByb21vdGlvbiBVc2UgKCUpIikpICU+JQogICAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQogICAgCiAgICAjIFZpc3VhbGl6ZSBhbnRpYmlvdGljIHVzZSBieSBpbmZvcm1hdGlvbiBzb3VyY2UKICAgIHBsb3RfZGF0YSA8LSBzb3VyY2Vfc3VtbWFyeSAlPiUKICAgICAgZmlsdGVyKG5fZmFybXMgPj0gNSkgJT4lCiAgICAgIGdhdGhlcihrZXkgPSAicHVycG9zZSIsIHZhbHVlID0gInBlcmNlbnRhZ2UiLCAKICAgICAgICAgICAgIGFiX3VzZV9wY3QsIGFiX3RyZWF0bWVudF9wY3QsIGFiX3ByZXZlbnRpb25fcGN0LCBhYl9ncm93dGhfcGN0KSAlPiUKICAgICAgbXV0YXRlKHB1cnBvc2UgPSBmYWN0b3IocHVycG9zZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJhYl91c2VfcGN0IiwgImFiX3RyZWF0bWVudF9wY3QiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImFiX3ByZXZlbnRpb25fcGN0IiwgImFiX2dyb3d0aF9wY3QiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkFueSBVc2UiLCAiVHJlYXRtZW50IiwgIlByZXZlbnRpb24iLCAiR3Jvd3RoIikpKQogICAgCiAgICAjIENyZWF0ZSBhbmQgZGlzcGxheSB0aGUgYmFyIGNoYXJ0CiAgICBzb3VyY2VfcHVycG9zZV9wbG90IDwtIGdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0gcHJpbWFyeV9zb3VyY2Vfc3RkLCB5ID0gcGVyY2VudGFnZSwgZmlsbCA9IHB1cnBvc2UpKSArCiAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNwcmludGYoIiUuMWYlJSIsIHBlcmNlbnRhZ2UpKSwgCiAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpLCAKICAgICAgICAgICAgICAgdmp1c3QgPSAtMC41LCBzaXplID0gMykgKwogICAgICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNldDIiKSArCiAgICAgIGxhYnModGl0bGUgPSAiQW50aWJpb3RpYyBVc2UgUGF0dGVybnMgYnkgUHJpbWFyeSBJbmZvcm1hdGlvbiBTb3VyY2UiLAogICAgICAgICAgIHN1YnRpdGxlID0gIkNvbXBhcmluZyB1c2FnZSBmb3IgZGlmZmVyZW50IHB1cnBvc2VzIiwKICAgICAgICAgICB4ID0gIkluZm9ybWF0aW9uIFNvdXJjZSIsCiAgICAgICAgICAgeSA9ICJQZXJjZW50YWdlIG9mIEZhcm1zIiwKICAgICAgICAgICBmaWxsID0gIlVzYWdlIFB1cnBvc2UiKSArCiAgICAgIHRoZW1lX21pbmltYWwoKSArCiAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpCiAgICAKICAgIHByaW50KHNvdXJjZV9wdXJwb3NlX3Bsb3QpCiAgICAKICAgICMgU3RhdGlzdGljYWwgY29tcGFyaXNvbiBvZiBpbmZvcm1hdGlvbiBzb3VyY2VzCiAgICBpZihucm93KHNvdXJjZV9zdW1tYXJ5KSA+PSAyKSB7CiAgICAgIGNhdCgiXG5TdGF0aXN0aWNhbCBjb21wYXJpc29uIG9mIGFudGliaW90aWMgdXNlIGFjcm9zcyBpbmZvcm1hdGlvbiBzb3VyY2VzOlxuIikKICAgICAgCiAgICAgICMgT25lLXdheSBBTk9WQSBmb3IgYW55IGFudGliaW90aWMgdXNlCiAgICAgIGFiX3VzZV9hb3YgPC0gYW92KGFueV9hYl91c2UgfiBwcmltYXJ5X3NvdXJjZV9zdGQsIGRhdGEgPSBmYXJtX2luZm8pCiAgICAgIGFiX3VzZV9hb3Zfc3VtbWFyeSA8LSBzdW1tYXJ5KGFiX3VzZV9hb3YpCiAgICAgIAogICAgICBjYXQoIkFOT1ZBIGZvciBhbnkgYW50aWJpb3RpYyB1c2UgYnkgaW5mb3JtYXRpb24gc291cmNlOlxuIikKICAgICAgcHJpbnQoYWJfdXNlX2Fvdl9zdW1tYXJ5KQogICAgICAKICAgICAgIyBTdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UKICAgICAgaWYoYWJfdXNlX2Fvdl9zdW1tYXJ5W1sxXV1bWyJQcig+RikiXV1bMV0gPCAwLjA1KSB7CiAgICAgICAgY2F0KCJUaGVyZSBhcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlcyBpbiBhbnRpYmlvdGljIHVzZSBhY3Jvc3MgaW5mb3JtYXRpb24gc291cmNlcyAocCA9IiwgCiAgICAgICAgICAgIHJvdW5kKGFiX3VzZV9hb3Zfc3VtbWFyeVtbMV1dW1siUHIoPkYpIl1dWzFdLCAzKSwgIilcbiIpCiAgICAgICAgCiAgICAgICAgIyBQb3N0LWhvYyB0ZXN0IGlmIEFOT1ZBIGlzIHNpZ25pZmljYW50CiAgICAgICAgaWYocmVxdWlyZU5hbWVzcGFjZSgiZW1tZWFucyIsIHF1aWV0bHkgPSBUUlVFKSkgewogICAgICAgICAgcG9zdGhvYyA8LSBlbW1lYW5zOjplbW1lYW5zKGFiX3VzZV9hb3YsIHBhaXJ3aXNlIH4gcHJpbWFyeV9zb3VyY2Vfc3RkKQogICAgICAgICAgY2F0KCJQb3N0LWhvYyBwYWlyd2lzZSBjb21wYXJpc29uczpcbiIpCiAgICAgICAgICBwcmludChwb3N0aG9jJGNvbnRyYXN0cykKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2F0KCJObyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGluIGFudGliaW90aWMgdXNlIGFjcm9zcyBpbmZvcm1hdGlvbiBzb3VyY2VzIChwID0iLCAKICAgICAgICAgICAgcm91bmQoYWJfdXNlX2Fvdl9zdW1tYXJ5W1sxXV1bWyJQcig+RikiXV1bMV0sIDMpLCAiKVxuIikKICAgICAgfQogICAgfQogICAgCiAgICAjIElkZW50aWZ5IGZhcm1zIHNoYXJpbmcgY29tbW9uIGluZm9ybWF0aW9uIHNvdXJjZXMKICAgIGNhdCgiXG5Db25zdHJ1Y3RpbmcgaW5mb3JtYXRpb24gc291cmNlIG5ldHdvcmtzLi4uXG4iKQogICAgCiAgICAjIENyZWF0ZSBpbmZvcm1hdGlvbiBzb3VyY2UgbmV0d29yawogICAgZmFybV9wYWlycyA8LSBleHBhbmQuZ3JpZChmYXJtMSA9IGZhcm1faW5mbyRmYXJtX2lkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYXJtMiA9IGZhcm1faW5mbyRmYXJtX2lkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpICU+JQogICAgICBmaWx0ZXIoZmFybTEgPCBmYXJtMikgICMgT25seSBpbmNsdWRlIGVhY2ggcGFpciBvbmNlCiAgICAKICAgICMgQ2FsY3VsYXRlIGluZm9ybWF0aW9uIHNvdXJjZSBvdmVybGFwCiAgICBmYXJtX3BhaXJzJHNvdXJjZV9vdmVybGFwIDwtIGFwcGx5KGZhcm1fcGFpcnMsIDEsIGZ1bmN0aW9uKHBhaXIpIHsKICAgICAgZmFybTFfaWR4IDwtIHdoaWNoKGZhcm1faW5mbyRmYXJtX2lkID09IHBhaXJbImZhcm0xIl0pCiAgICAgIGZhcm0yX2lkeCA8LSB3aGljaChmYXJtX2luZm8kZmFybV9pZCA9PSBwYWlyWyJmYXJtMiJdKQogICAgICAKICAgICAgIyBHZXQgc291cmNlcyBmb3IgZWFjaCBmYXJtCiAgICAgIHNvdXJjZXMxIDwtIG5hLm9taXQoYyhmYXJtX2luZm8kYWR2aWNlMV9jYXRlZ29yeVtmYXJtMV9pZHhdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFybV9pbmZvJGFkdmljZTJfY2F0ZWdvcnlbZmFybTFfaWR4XSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhcm1faW5mbyRhZHZpY2UzX2NhdGVnb3J5W2Zhcm0xX2lkeF0pKQogICAgICBzb3VyY2VzMiA8LSBuYS5vbWl0KGMoZmFybV9pbmZvJGFkdmljZTFfY2F0ZWdvcnlbZmFybTJfaWR4XSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhcm1faW5mbyRhZHZpY2UyX2NhdGVnb3J5W2Zhcm0yX2lkeF0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICBmYXJtX2luZm8kYWR2aWNlM19jYXRlZ29yeVtmYXJtMl9pZHhdKSkKICAgICAgCiAgICAgICMgQ2FsY3VsYXRlIEphY2NhcmQgc2ltaWxhcml0eSAoaW50ZXJzZWN0aW9uIG92ZXIgdW5pb24pCiAgICAgIGxlbmd0aChpbnRlcnNlY3Qoc291cmNlczEsIHNvdXJjZXMyKSkgLyBsZW5ndGgodW5pb24oc291cmNlczEsIHNvdXJjZXMyKSkKICAgIH0pCiAgICAKICAgICMgU3VtbWFyaXplIG92ZXJsYXAgZGlzdHJpYnV0aW9uCiAgICBjYXQoIkRpc3RyaWJ1dGlvbiBvZiBpbmZvcm1hdGlvbiBzb3VyY2Ugb3ZlcmxhcCBiZXR3ZWVuIGZhcm0gcGFpcnM6XG4iKQogICAgb3ZlcmxhcF9zdW1tYXJ5IDwtIGZhcm1fcGFpcnMgJT4lCiAgICAgIG11dGF0ZShvdmVybGFwX2NhdGVnb3J5ID0gY3V0KHNvdXJjZV9vdmVybGFwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKDAsIDAuMjUsIDAuNSwgMC43NSwgMS4wKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCIwLTI1JSIsICIyNi01MCUiLCAiNTEtNzUlIiwgIjc2LTEwMCUiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpKSAlPiUKICAgICAgY291bnQob3ZlcmxhcF9jYXRlZ29yeSkgJT4lCiAgICAgIG11dGF0ZShwZXJjZW50YWdlID0gbiAvIHN1bShuKSAqIDEwMCkKICAgIAogICAgcHJpbnQob3ZlcmxhcF9zdW1tYXJ5KQogICAgCiAgICAjIERlZmluZSBuZXR3b3JrIHRpZXMgYmFzZWQgb24gbWluaW11bSBvdmVybGFwCiAgICBtaW5fb3ZlcmxhcCA8LSAwLjUgICMgQXQgbGVhc3QgNTAlIHNvdXJjZSBvdmVybGFwCiAgICBmYXJtX25ldHdvcmtfZWRnZXMgPC0gZmFybV9wYWlycyAlPiUKICAgICAgZmlsdGVyKHNvdXJjZV9vdmVybGFwID49IG1pbl9vdmVybGFwKSAlPiUKICAgICAgZHBseXI6OnNlbGVjdChmYXJtMSwgZmFybTIpCiAgICAKICAgIGlmKG5yb3coZmFybV9uZXR3b3JrX2VkZ2VzKSA+IDApIHsKICAgICAgY2F0KCJGb3VuZCIsIG5yb3coZmFybV9uZXR3b3JrX2VkZ2VzKSwgImZhcm0gcGFpcnMgd2l0aCBzaWduaWZpY2FudCBpbmZvcm1hdGlvbiBzb3VyY2Ugb3ZlcmxhcC5cbiIpCiAgICAgIAogICAgICAjIENyZWF0ZSBuZXR3b3JrIGdyYXBoCiAgICAgIGluZm9fZyA8LSBncmFwaF9mcm9tX2RhdGFfZnJhbWUoZmFybV9uZXR3b3JrX2VkZ2VzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcnRpY2VzID0gZmFybV9pbmZvICU+JSBkcGx5cjo6c2VsZWN0KGZhcm1faWQsIGFueV9hYl91c2UpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0ZWQgPSBGQUxTRSkKICAgICAgCiAgICAgICMgTmV0d29yayBzdGF0aXN0aWNzCiAgICAgIGNhdCgiXG5JbmZvcm1hdGlvbiBzb3VyY2UgbmV0d29yayBzdGF0aXN0aWNzOlxuIikKICAgICAgY2F0KCJOdW1iZXIgb2Ygbm9kZXMgKGZhcm1zKToiLCB2Y291bnQoaW5mb19nKSwgIlxuIikKICAgICAgY2F0KCJOdW1iZXIgb2YgZWRnZXMgKGNvbm5lY3Rpb25zKToiLCBlY291bnQoaW5mb19nKSwgIlxuIikKICAgICAgY2F0KCJOZXR3b3JrIGRlbnNpdHk6IiwgZWRnZV9kZW5zaXR5KGluZm9fZyksICJcbiIpCiAgICAgIGNhdCgiQXZlcmFnZSBkZWdyZWUgKGNvbm5lY3Rpb25zIHBlciBmYXJtKToiLCBtZWFuKGRlZ3JlZShpbmZvX2cpKSwgIlxuIikKICAgICAgCiAgICAgICMgQ29tbXVuaXR5IGRldGVjdGlvbiBpbiBpbmZvcm1hdGlvbiBuZXR3b3JrCiAgICAgIGluZm9fY29tbXVuaXRpZXMgPC0gY2x1c3Rlcl9sb3V2YWluKGluZm9fZykKICAgICAgCiAgICAgIGNhdCgiTnVtYmVyIG9mIGRldGVjdGVkIGluZm9ybWF0aW9uIGNvbW11bml0aWVzOiIsIGxlbmd0aCh1bmlxdWUobWVtYmVyc2hpcChpbmZvX2NvbW11bml0aWVzKSkpLCAiXG4iKQogICAgICAKICAgICAgIyBBc3NpZ24gY29tbXVuaXR5IElEcwogICAgICBmYXJtX2luZm8kaW5mb19jb21tdW5pdHlfaWQgPC0gbWVtYmVyc2hpcChpbmZvX2NvbW11bml0aWVzKVttYXRjaChmYXJtX2luZm8kZmFybV9pZCwgbmFtZXMoVihpbmZvX2cpKSldCiAgICAgIAogICAgICAjIFZpc3VhbGl6ZSBuZXR3b3JrIHdpdGggY29tbXVuaXRpZXMKICAgICAgIyBOZXR3b3JrIHN0YXRpc3RpY3MKY2F0KCJcbkluZm9ybWF0aW9uIHNvdXJjZSBuZXR3b3JrIHN0YXRpc3RpY3M6XG4iKQpjYXQoIk51bWJlciBvZiBub2RlcyAoZmFybXMpOiIsIHZjb3VudChpbmZvX2cpLCAiXG4iKQpjYXQoIk51bWJlciBvZiBlZGdlcyAoY29ubmVjdGlvbnMpOiIsIGVjb3VudChpbmZvX2cpLCAiXG4iKQpjYXQoIk5ldHdvcmsgZGVuc2l0eToiLCBlZGdlX2RlbnNpdHkoaW5mb19nKSwgIlxuIikKY2F0KCJBdmVyYWdlIGRlZ3JlZSAoY29ubmVjdGlvbnMgcGVyIGZhcm0pOiIsIG1lYW4oZGVncmVlKGluZm9fZykpLCAiXG4iKQoKIyBDcmVhdGUgYSBzaW1wbGlmaWVkIG5ldHdvcmsgYnkgbGltaXRpbmcgZWRnZXMgcGVyIG5vZGUKaWYocmVxdWlyZU5hbWVzcGFjZSgidGlkeWdyYXBoIiwgcXVpZXRseSA9IFRSVUUpKSB7CiAgdGdfc2ltcGxpZmllZCA8LSB0aWR5Z3JhcGg6OmFzX3RibF9ncmFwaChpbmZvX2cpICU+JQogICAgdGlkeWdyYXBoOjphY3RpdmF0ZShub2RlcykgJT4lCiAgICB0aWR5Z3JhcGg6Om11dGF0ZShjb21tdW5pdHkgPSBtZW1iZXJzaGlwKGluZm9fY29tbXVuaXRpZXMpLAogICAgICAgICAgICAgICAgICAgICAgIGFudGliaW90aWNfdXNlID0gYW55X2FiX3VzZSkgJT4lCiAgICB0aWR5Z3JhcGg6OmFjdGl2YXRlKGVkZ2VzKSAlPiUKICAgICMgQWRkIGVkZ2Ugd2VpZ2h0IGJhc2VkIG9uIG92ZXJsYXAKICAgIHRpZHlncmFwaDo6bXV0YXRlKHdlaWdodCA9IGZhcm1fcGFpcnMkc291cmNlX292ZXJsYXBbbWF0Y2gocGFzdGUwKGZyb20sICItIiwgdG8pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoZmFybV9wYWlycyRmYXJtMSwgIi0iLCBmYXJtX3BhaXJzJGZhcm0yKSldKSAlPiUKICAgICMgS2VlcCBvbmx5IHRvcCBjb25uZWN0aW9ucyBwZXIgbm9kZSAtIGZpeGVkIGFwcHJvYWNoIHdpdGhvdXQgZWRnZV9yYW5rKCkKICAgIHRpZHlncmFwaDo6bXV0YXRlKHJhbmtfaW5fZnJvbSA9IHJhbmsoLXdlaWdodCwgdGllcy5tZXRob2QgPSAiZmlyc3QiKSwKICAgICAgICAgICAgICAgICAgICAgIHJhbmtfaW5fdG8gPSByYW5rKC13ZWlnaHQsIHRpZXMubWV0aG9kID0gImZpcnN0IikpICU+JQogICAgdGlkeWdyYXBoOjpmaWx0ZXIocmFua19pbl9mcm9tIDw9IDMgfCByYW5rX2luX3RvIDw9IDMpICAjIEtlZXAgdG9wIDMgY29ubmVjdGlvbnMgcGVyIG5vZGUKICAKICAjIENvdW50IG5vZGVzIGluIGVhY2ggY29tbXVuaXR5IGZvciBzaXppbmcgcGxvdHMKICBjb21tdW5pdHlfc2l6ZXMgPC0gdGFibGUobWVtYmVyc2hpcChpbmZvX2NvbW11bml0aWVzKSkKICBsYXJnZXN0X2NvbW11bml0aWVzIDwtIG5hbWVzKHNvcnQoY29tbXVuaXR5X3NpemVzLCBkZWNyZWFzaW5nID0gVFJVRSkpWzE6bWluKDQsIGxlbmd0aChjb21tdW5pdHlfc2l6ZXMpKV0KfQp9IGVsc2UgewogICMgSWYgdGlkeWdyYXBoIGlzIG5vdCBhdmFpbGFibGUsIHVzZSB0aGUgb3JpZ2luYWwgZ3JhcGgKICB0Z19zaW1wbGlmaWVkIDwtIGluZm9fZwogIFYodGdfc2ltcGxpZmllZCkkY29tbXVuaXR5IDwtIG1lbWJlcnNoaXAoaW5mb19jb21tdW5pdGllcykKICBWKHRnX3NpbXBsaWZpZWQpJGFudGliaW90aWNfdXNlIDwtIFYoaW5mb19nKSRhbnlfYWJfdXNlCiAgCiAgIyBJZGVudGlmeSBsYXJnZXN0IGNvbW11bml0aWVzCiAgY29tbXVuaXR5X3NpemVzIDwtIHRhYmxlKG1lbWJlcnNoaXAoaW5mb19jb21tdW5pdGllcykpCiAgbGFyZ2VzdF9jb21tdW5pdGllcyA8LSBuYW1lcyhzb3J0KGNvbW11bml0eV9zaXplcywgZGVjcmVhc2luZyA9IFRSVUUpKVsxOm1pbig0LCBsZW5ndGgoY29tbXVuaXR5X3NpemVzKSldCn0KCiMgTmV0d29yayBzdGF0aXN0aWNzCmNhdCgiXG5JbmZvcm1hdGlvbiBzb3VyY2UgbmV0d29yayBzdGF0aXN0aWNzOlxuIikKY2F0KCJOdW1iZXIgb2Ygbm9kZXMgKGZhcm1zKToiLCB2Y291bnQoaW5mb19nKSwgIlxuIikKY2F0KCJOdW1iZXIgb2YgZWRnZXMgKGNvbm5lY3Rpb25zKToiLCBlY291bnQoaW5mb19nKSwgIlxuIikKY2F0KCJOZXR3b3JrIGRlbnNpdHk6IiwgZWRnZV9kZW5zaXR5KGluZm9fZyksICJcbiIpCmNhdCgiQXZlcmFnZSBkZWdyZWUgKGNvbm5lY3Rpb25zIHBlciBmYXJtKToiLCBtZWFuKGRlZ3JlZShpbmZvX2cpKSwgIlxuIikKCiMgVmlzdWFsaXplIG5ldHdvcmsgd2l0aCBtdWx0aXBsZSBhcHByb2FjaGVzCmlmKHJlcXVpcmVOYW1lc3BhY2UoImdncmFwaCIsIHF1aWV0bHkgPSBUUlVFKSAmJiByZXF1aXJlTmFtZXNwYWNlKCJ0aWR5Z3JhcGgiLCBxdWlldGx5ID0gVFJVRSkpIHsKICAjIENyZWF0ZSB0aWR5Z3JhcGggb2JqZWN0CiAgdGcgPC0gdGlkeWdyYXBoOjphc190YmxfZ3JhcGgoaW5mb19nKSAlPiUKICAgIHRpZHlncmFwaDo6YWN0aXZhdGUobm9kZXMpICU+JQogICAgdGlkeWdyYXBoOjptdXRhdGUoY29tbXVuaXR5ID0gbWVtYmVyc2hpcChpbmZvX2NvbW11bml0aWVzKSwKICAgICAgICAgICAgICAgICAgICAgIGFudGliaW90aWNfdXNlID0gYW55X2FiX3VzZSkKICAKICAjIDEuIE1haW4gbmV0d29yayB2aXN1YWxpemF0aW9uIHdpdGggcmVkdWNlZCBjbHV0dGVyCiAgbWFpbl9uZXR3b3JrX3Bsb3QgPC0gZ2dyYXBoOjpnZ3JhcGgodGcsIGxheW91dCA9ICJmciIpICsgCiAgICBnZ3JhcGg6Omdlb21fZWRnZV9saW5rKGFscGhhID0gMC4yLCB3aWR0aCA9IDAuMykgKyAKICAgIGdncmFwaDo6Z2VvbV9ub2RlX3BvaW50KGFlcyhjb2xvciA9IGZhY3Rvcihjb21tdW5pdHkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSBhbnRpYmlvdGljX3VzZSAqIDIgKyAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcpICsKICAgIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMC41LCAzKSkgKyAgIyBSZWR1Y2UgdGhlIHJhbmdlIG9mIG5vZGUgc2l6ZXMKICAgIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSArCiAgICBsYWJzKHRpdGxlID0gIkluZm9ybWF0aW9uIFNvdXJjZSBDb21tdW5pdGllcyBpbiBGYXJtcyIsCiAgICAgICAgIHN1YnRpdGxlID0gIkZhcm1zIGNvbm5lY3RlZCBieSBzaGFyZWQgaW5mb3JtYXRpb24gc291cmNlcyAoc2ltcGxpZmllZCB2aWV3KSIsCiAgICAgICAgIGNvbG9yID0gIkNvbW11bml0eSIsIAogICAgICAgICBzaXplID0gIkFudGliaW90aWMgVXNlIikgKwogICAgdGhlbWVfdm9pZCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCiAgCiAgcHJpbnQobWFpbl9uZXR3b3JrX3Bsb3QpCiAgCiAgIyAyLiBBbHRlcm5hdGl2ZSBsYXlvdXQgdmlzdWFsaXphdGlvbgogIGFsdF9uZXR3b3JrX3Bsb3QgPC0gZ2dyYXBoOjpnZ3JhcGgodGcsIGxheW91dCA9ICJrayIpICsgCiAgICBnZ3JhcGg6Omdlb21fZWRnZV9saW5rKGFscGhhID0gMC4yLCB3aWR0aCA9IDAuMykgKyAKICAgIGdncmFwaDo6Z2VvbV9ub2RlX3BvaW50KGFlcyhjb2xvciA9IGZhY3Rvcihjb21tdW5pdHkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSBhbnRpYmlvdGljX3VzZSAqIDIgKyAwLjUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAwLjcpICsKICAgIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMC41LCAzKSkgKwogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsKICAgIGxhYnModGl0bGUgPSAiQWx0ZXJuYXRpdmUgVmlldyBvZiBJbmZvcm1hdGlvbiBTb3VyY2UgQ29tbXVuaXRpZXMiLCAKICAgICAgICAgc3VidGl0bGUgPSAiVXNpbmcgS2FtYWRhLUthd2FpIGxheW91dCBhbGdvcml0aG0iLAogICAgICAgICBjb2xvciA9ICJDb21tdW5pdHkiLCAKICAgICAgICAgc2l6ZSA9ICJBbnRpYmlvdGljIFVzZSIpICsKICAgIHRoZW1lX3ZvaWQoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQogIAogIHByaW50KGFsdF9uZXR3b3JrX3Bsb3QpCiAgCiAgIyAzLiBDcmVhdGUgYSB2aXN1YWxpemF0aW9uIHdpdGggY29tbXVuaXRpZXMgd2l0aCBkaWZmZXJlbnQgcG9pbnQgc2hhcGVzCiAgc2hhcGVfcGxvdCA8LSBnZ3JhcGg6OmdncmFwaCh0ZywgbGF5b3V0ID0gIm5pY2VseSIpICsgCiAgICBnZ3JhcGg6Omdlb21fZWRnZV9saW5rKGFscGhhID0gMC4xLCB3aWR0aCA9IDAuMikgKyAKICAgIGdncmFwaDo6Z2VvbV9ub2RlX3BvaW50KGFlcyhjb2xvciA9IGZhY3Rvcihjb21tdW5pdHkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IGFudGliaW90aWNfdXNlICogMiArIDAuOCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hhcGUgPSBmYWN0b3IoY29tbXVuaXR5ICUlIDUpKSwgIyBVc2UgbW9kdWxvIHRvIGxpbWl0IHRvIGF2YWlsYWJsZSBzaGFwZXMKICAgICAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuOCkgKwogICAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygxLCA0KSkgKwogICAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU2V0MSIpICsKICAgIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDE2LCAxNywgMTUsIDE4LCAxOSksIGd1aWRlID0gIm5vbmUiKSArCiAgICBsYWJzKHRpdGxlID0gIkNvbW11bml0aWVzIG9mIEZhcm1zIHdpdGggU2ltaWxhciBJbmZvcm1hdGlvbiBTb3VyY2VzIiwKICAgICAgICAgc3VidGl0bGUgPSAiRGlmZmVyZW50IGxheW91dHMgaGlnaGxpZ2h0IGRpZmZlcmVudCBhc3BlY3RzIG9mIGNvbW11bml0eSBzdHJ1Y3R1cmUiLAogICAgICAgICBjb2xvciA9ICJDb21tdW5pdHkiLCAKICAgICAgICAgc2l6ZSA9ICJBbnRpYmlvdGljIFVzZSIpICsKICAgIHRoZW1lX3ZvaWQoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQogIAogIHByaW50KHNoYXBlX3Bsb3QpCiAgCn0gZWxzZSB7CiAgIyBCYXNpYyBwbG90IGlmIGdncmFwaCBpcyBub3QgYXZhaWxhYmxlCiAgIyBDcmVhdGUgYSBtb3JlIHZpc3VhbGx5IGFwcGVhbGluZyBiYXNlIHBsb3QKICBvcCA8LSBwYXIobWFyID0gYygxLDEsMywxKSkgICMgQWRqdXN0IG1hcmdpbnMKICBzZXQuc2VlZCg0MikgICMgRm9yIHJlcHJvZHVjaWJpbGl0eQogIAogICMgVXNlIGEgYmV0dGVyIGxheW91dAogIGxheW91dF9jb29yZHMgPC0gbGF5b3V0X3dpdGhfZnIoaW5mb19nKQogIAogICMgSW1wcm92ZSBub2RlIGFwcGVhcmFuY2UKICBWKGluZm9fZykkY29sb3IgPC0gcmFpbmJvdyhsZW5ndGgodW5pcXVlKG1lbWJlcnNoaXAoaW5mb19jb21tdW5pdGllcykpKSlbbWVtYmVyc2hpcChpbmZvX2NvbW11bml0aWVzKV0KICBWKGluZm9fZykkc2l6ZSA8LSAyICsgOCAqIFYoaW5mb19nKSRhbnlfYWJfdXNlICAjIFNjYWxlIG5vZGUgc2l6ZXMKICBFKGluZm9fZykkd2lkdGggPC0gMC41ICAjIFRoaW5uZXIgZWRnZXMKICBFKGluZm9fZykkY29sb3IgPC0gcmdiKDAuNSwgMC41LCAwLjUsIDAuMikgICMgVHJhbnNwYXJlbnQgZ3JheSBlZGdlcwogIAogICMgUGxvdCB3aXRoIGltcHJvdmVkIGFlc3RoZXRpY3MKICBwbG90KGluZm9fZywgCiAgICAgICB2ZXJ0ZXgubGFiZWwgPSBOQSwKICAgICAgIHZlcnRleC5zaXplID0gVihpbmZvX2cpJHNpemUsCiAgICAgICB2ZXJ0ZXguY29sb3IgPSBhZGp1c3Rjb2xvcihWKGluZm9fZykkY29sb3IsIGFscGhhLmYgPSAwLjcpLAogICAgICAgZWRnZS53aWR0aCA9IEUoaW5mb19nKSR3aWR0aCwKICAgICAgIGVkZ2UuY29sb3IgPSBFKGluZm9fZykkY29sb3IsCiAgICAgICBsYXlvdXQgPSBsYXlvdXRfY29vcmRzLAogICAgICAgbWFpbiA9ICJJbmZvcm1hdGlvbiBTb3VyY2UgQ29tbXVuaXRpZXMiLAogICAgICAgc3ViID0gIkZhcm1zIGNvbm5lY3RlZCBieSBzaGFyZWQgaW5mb3JtYXRpb24gc291cmNlcyIpCiAgCiAgbGVnZW5kKCJ0b3ByaWdodCIsIAogICAgICAgICBsZWdlbmQgPSBwYXN0ZSgiQ29tbXVuaXR5Iiwgc29ydCh1bmlxdWUobWVtYmVyc2hpcChpbmZvX2NvbW11bml0aWVzKSkpKSwKICAgICAgICAgZmlsbCA9IHJhaW5ib3cobGVuZ3RoKHVuaXF1ZShtZW1iZXJzaGlwKGluZm9fY29tbXVuaXRpZXMpKSkpLAogICAgICAgICBidHkgPSAibiIsCiAgICAgICAgIGNleCA9IDAuOCkKICAKICBwYXIob3ApICAjIFJlc2V0IGdyYXBoaWNzIHBhcmFtZXRlcnMKfQogICAgICAKICAgICAgIyBBbmFseXplIGFudGliaW90aWMgdXNlIHBhdHRlcm5zIGJ5IGluZm9ybWF0aW9uIGNvbW11bml0eQogICAgICBpbmZvX2NvbW11bml0eV9zdGF0cyA8LSBmYXJtX2luZm8gJT4lCiAgICAgICAgZmlsdGVyKCFpcy5uYShpbmZvX2NvbW11bml0eV9pZCkpICU+JQogICAgICAgIGdyb3VwX2J5KGluZm9fY29tbXVuaXR5X2lkKSAlPiUKICAgICAgICBzdW1tYXJpc2UoCiAgICAgICAgICBuX2Zhcm1zID0gbigpLAogICAgICAgICAgYWJfdXNlX3BjdCA9IG1lYW4oYW55X2FiX3VzZSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgICAgIGFiX3ByZXZlbnRpb25fcGN0ID0gbWVhbihhYl9wcmV2ZW50aW9uLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICAgICAgYWJfZ3Jvd3RoX3BjdCA9IG1lYW4oYWJfZ3Jvd3RoLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICAgICAgYWJfdXNlX3NkID0gc2QoYW55X2FiX3VzZSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgICApICU+JQogICAgICAgIGZpbHRlcihuX2Zhcm1zID49IDMpICAjIE9ubHkgaW5jbHVkZSBjb21tdW5pdGllcyB3aXRoIHN1ZmZpY2llbnQgZGF0YQogICAgICAKICAgICAgIyBEaXNwbGF5IGNvbW11bml0eSBzdGF0aXN0aWNzCiAgICAgIGluZm9fY29tbXVuaXR5X3N0YXRzICU+JQogICAgICAgIG11dGF0ZShhY3Jvc3MoZW5kc193aXRoKCJfcGN0IiksIH4gcm91bmQoLiwgMSkpLAogICAgICAgICAgICAgICBhYl91c2Vfc2QgPSByb3VuZChhYl91c2Vfc2QsIDEpKSAlPiUKICAgICAgICBrYWJsZShjYXB0aW9uID0gIkFudGliaW90aWMgVXNlIFN0YXRpc3RpY3MgYnkgSW5mb3JtYXRpb24gQ29tbXVuaXR5IiwKICAgICAgICAgICAgICBjb2wubmFtZXMgPSBjKCJDb21tdW5pdHkgSUQiLCAiTnVtYmVyIG9mIEZhcm1zIiwgIkFueSBBbnRpYmlvdGljIFVzZSAoJSkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAiUHJldmVudGlvbiBVc2UgKCUpIiwgIkdyb3d0aCBQcm9tb3Rpb24gVXNlICglKSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAiU3RkIERldiBvZiBBbnRpYmlvdGljIFVzZSAoJSkiKSkgJT4lCiAgICAgICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkKICAgICAgCiAgICAgICMgQ29tcGFyZSB3aXRoaW4tY29tbXVuaXR5IHZzLiBiZXR3ZWVuLWNvbW11bml0eSB2YXJpYW5jZQogICAgICBpZihucm93KGluZm9fY29tbXVuaXR5X3N0YXRzKSA+IDEpIHsKICAgICAgICAjIENhbGN1bGF0ZSBvdmVyYWxsIHZhcmlhbmNlCiAgICAgICAgb3ZlcmFsbF92YXJpYW5jZSA8LSB2YXIoZmFybV9pbmZvJGFueV9hYl91c2UsIG5hLnJtID0gVFJVRSkgKiAxMDAwMCAgIyBDb252ZXJ0IHRvIHBlcmNlbnRhZ2Ugc2NhbGUKICAgICAgICAKICAgICAgICAjIENhbGN1bGF0ZSB3ZWlnaHRlZCBhdmVyYWdlIG9mIHdpdGhpbi1jb21tdW5pdHkgdmFyaWFuY2UKICAgICAgICB3aXRoaW5fdmFyaWFuY2UgPC0gc3VtKGluZm9fY29tbXVuaXR5X3N0YXRzJGFiX3VzZV9zZF4yICogaW5mb19jb21tdW5pdHlfc3RhdHMkbl9mYXJtcykgLyAKICAgICAgICAgIHN1bShpbmZvX2NvbW11bml0eV9zdGF0cyRuX2Zhcm1zKQogICAgICAgIAogICAgICAgICMgQ2FsY3VsYXRlIHZhcmlhbmNlIGV4cGxhaW5lZCBieSBjb21tdW5pdHkgbWVtYmVyc2hpcCAobGlrZSBSLXNxdWFyZWQpCiAgICAgICAgdmFyaWFuY2VfZXhwbGFpbmVkIDwtIDEgLSAod2l0aGluX3ZhcmlhbmNlIC8gb3ZlcmFsbF92YXJpYW5jZSkKICAgICAgICAKICAgICAgICBjYXQoIlxuSW5mb3JtYXRpb24gY29tbXVuaXR5IGFuYWx5c2lzOlxuIikKICAgICAgICBjYXQoIk51bWJlciBvZiBpbmZvcm1hdGlvbiBjb21tdW5pdGllczoiLCBucm93KGluZm9fY29tbXVuaXR5X3N0YXRzKSwgIlxuIikKICAgICAgICBjYXQoIlZhcmlhbmNlIGluIGFudGliaW90aWMgdXNlIGV4cGxhaW5lZCBieSBpbmZvcm1hdGlvbiBjb21tdW5pdHkgbWVtYmVyc2hpcDoiLCAKICAgICAgICAgICAgcm91bmQodmFyaWFuY2VfZXhwbGFpbmVkICogMTAwLCAxKSwgIiVcbiIpCiAgICAgICAgCiAgICAgICAgIyBWaXN1YWxpemUgY29tbXVuaXR5IGRpZmZlcmVuY2VzCiAgICAgICAgaWYobnJvdyhpbmZvX2NvbW11bml0eV9zdGF0cykgPj0gMykgewogICAgICAgICAgY29tbXVuaXR5X3Bsb3QgPC0gZ2dwbG90KGluZm9fY29tbXVuaXR5X3N0YXRzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPSByZW9yZGVyKGZhY3RvcihpbmZvX2NvbW11bml0eV9pZCksIGFiX3VzZV9wY3QpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBhYl91c2VfcGN0KSkgKwogICAgICAgICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJzdGVlbGJsdWUiKSArCiAgICAgICAgICAgIGdlb21fZXJyb3JiYXIoYWVzKHltaW4gPSBhYl91c2VfcGN0IC0gYWJfdXNlX3NkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gYWJfdXNlX3BjdCArIGFiX3VzZV9zZCksIAogICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAwLjIpICsKICAgICAgICAgICAgbGFicyh0aXRsZSA9ICJBbnRpYmlvdGljIFVzZSBieSBJbmZvcm1hdGlvbiBDb21tdW5pdHkiLAogICAgICAgICAgICAgICAgIHN1YnRpdGxlID0gIkVycm9yIGJhcnMgcmVwcmVzZW50IHN0YW5kYXJkIGRldmlhdGlvbiIsCiAgICAgICAgICAgICAgICAgeCA9ICJJbmZvcm1hdGlvbiBDb21tdW5pdHkgSUQiLAogICAgICAgICAgICAgICAgIHkgPSAiQW50aWJpb3RpYyBVc2UgKCUpIikgKwogICAgICAgICAgICB0aGVtZV9taW5pbWFsKCkKICAgICAgICAgIAogICAgICAgICAgcHJpbnQoY29tbXVuaXR5X3Bsb3QpCiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjYXQoIkluc3VmZmljaWVudCBpbmZvcm1hdGlvbiBzb3VyY2Ugb3ZlcmxhcCB0byBjb25zdHJ1Y3QgbWVhbmluZ2Z1bCBuZXR3b3JrLlxuIikKICAgIH0KICB9IGVsc2UgewogICAgIyBGb3IgbnVtZXJpY2FsIGNvZGluZyBvZiBhZHZpY2Ugc291cmNlcwogICAgc291cmNlX3N1bW1hcnkgPC0gZmFybV9kYXRhICU+JQogICAgICBmaWx0ZXIoIWlzLm5hKGFkdmljZTEpKSAlPiUKICAgICAgZ3JvdXBfYnkoYWR2aWNlMSkgJT4lCiAgICAgIHN1bW1hcmlzZSgKICAgICAgICBuID0gbigpLAogICAgICAgIGFiX3VzZV9wY3QgPSBtZWFuKGFueV9hYl91c2UsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICAgICAgYWJfcHJldmVudGlvbl9wY3QgPSBtZWFuKGFiX3ByZXZlbnRpb24sIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICAgICAgYWJfZ3Jvd3RoX3BjdCA9IG1lYW4oYWJfZ3Jvd3RoLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgKSAlPiUKICAgICAgZmlsdGVyKG4gPj0gNSkgICMgT25seSBpbmNsdWRlIHNvdXJjZXMgd2l0aCBzdWZmaWNpZW50IGRhdGEKICAgIAogICAgIyBEaXNwbGF5IHJlc3VsdHMKICAgIHNvdXJjZV9zdW1tYXJ5ICU+JQogICAgICBtdXRhdGUoYWNyb3NzKGVuZHNfd2l0aCgiX3BjdCIpLCB+IHJvdW5kKC4sIDEpKSkgJT4lCiAgICAgIGthYmxlKGNhcHRpb24gPSAiQW50aWJpb3RpYyBVc2UgUGF0dGVybnMgYnkgUHJpbWFyeSBJbmZvcm1hdGlvbiBTb3VyY2UgQ29kZSIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IGMoIkluZm9ybWF0aW9uIFNvdXJjZSBDb2RlIiwgIk51bWJlciBvZiBGYXJtcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIkFueSBBbnRpYmlvdGljIFVzZSAoJSkiLCAiUHJldmVudGlvbiBVc2UgKCUpIiwgIkdyb3d0aCBQcm9tb3Rpb24gVXNlICglKSIpKSAlPiUKICAgICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkKfSAKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIDMuIEh1bWFuLUFuaW1hbCBDb250YWN0IFBhdHRlcm4gQW5hbHlzaXMgKGNvbnRpbnVlZCkKIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBDaGVjayBpZiB3ZSBjYW4gaWRlbnRpZnkgZmFybS1ob3VzZWhvbGQgbGlua3MKIyBNZXRob2QgMTogRGlyZWN0IElEIGxpbmtpbmcKaWYoYW55KGdyZXBsKCJmYXJtX2lkIiwgbmFtZXMoaG91c2Vob2xkX2RhdGEpKSkpIHsKICBjYXQoIlxuIyMjIERpcmVjdCBGYXJtLUhvdXNlaG9sZCBMaW5rIEFuYWx5c2lzICMjI1xuIikKICBob3VzZWhvbGRfZmFybV9saW5rX3ZhciA8LSBuYW1lcyhob3VzZWhvbGRfZGF0YSlbZ3JlcGwoImZhcm1faWQiLCBuYW1lcyhob3VzZWhvbGRfZGF0YSkpXVsxXQogIGhhc19ob3VzZWhvbGRfZmFybV9saW5rIDwtIFRSVUUKICAKICAjIEV4dHJhY3QgbGlua2VkIGhvdXNlaG9sZHMtZmFybXMKICBsaW5rZWRfaG91c2Vob2xkcyA8LSBob3VzZWhvbGRfZGF0YSAlPiUKICAgIGZpbHRlcighaXMubmEoISFzeW0oaG91c2Vob2xkX2Zhcm1fbGlua192YXIpKSkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KGhvdXNlaG9sZF9pZCwgISFob3VzZWhvbGRfZmFybV9saW5rX3ZhciwgYW55X2FiX2xhc3RfaWxsbmVzcykKICAKICBsaW5rZWRfZmFybXMgPC0gZmFybV9kYXRhICU+JQogICAgZHBseXI6OnNlbGVjdChmYXJtX2lkLCBhbnlfYWJfdXNlLCBhYl90cmVhdG1lbnQsIGFiX3ByZXZlbnRpb24sIGFiX2dyb3d0aCkgJT4lCiAgICBmaWx0ZXIoZmFybV9pZCAlaW4lIGxpbmtlZF9ob3VzZWhvbGRzW1tob3VzZWhvbGRfZmFybV9saW5rX3Zhcl1dKQogIAogICMgTWVyZ2UgaG91c2Vob2xkIGFuZCBmYXJtIGRhdGEKICBpZihucm93KGxpbmtlZF9ob3VzZWhvbGRzKSA+IDAgJiYgbnJvdyhsaW5rZWRfZmFybXMpID4gMCkgewogICAgZmFybV9ob3VzZWhvbGRfcGFpcnMgPC0gbGlua2VkX2hvdXNlaG9sZHMgJT4lCiAgICAgIHJlbmFtZShmYXJtX2lkID0gISFob3VzZWhvbGRfZmFybV9saW5rX3ZhcikgJT4lCiAgICAgIGlubmVyX2pvaW4obGlua2VkX2Zhcm1zLCBieSA9ICJmYXJtX2lkIikKICAgIAogICAgY2F0KCJGb3VuZCIsIG5yb3coZmFybV9ob3VzZWhvbGRfcGFpcnMpLCAiZGlyZWN0IGZhcm0taG91c2Vob2xkIGxpbmtzLlxuIikKICAgIAogICAgIyBEaXNwbGF5IHN1bW1hcnkgc3RhdGlzdGljcyBvZiBsaW5rZWQgcGFpcnMKICAgIGZhcm1faG91c2Vob2xkX3N1bW1hcnkgPC0gZmFybV9ob3VzZWhvbGRfcGFpcnMgJT4lCiAgICAgIHN1bW1hcmlzZSgKICAgICAgICBuX3BhaXJzID0gbigpLAogICAgICAgIGZhcm1fYWJfdXNlX3BjdCA9IG1lYW4oYW55X2FiX3VzZSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgICBob3VzZWhvbGRfYWJfdXNlX3BjdCA9IG1lYW4oYW55X2FiX2xhc3RfaWxsbmVzcywgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgICBjb25jb3JkYW50X3BhaXJzID0gc3VtKGFueV9hYl91c2UgPT0gYW55X2FiX2xhc3RfaWxsbmVzcywgbmEucm0gPSBUUlVFKSwKICAgICAgICBjb25jb3JkYW50X3BjdCA9IGNvbmNvcmRhbnRfcGFpcnMgLyBuKCkgKiAxMDAKICAgICAgKSAlPiUKICAgICAgbXV0YXRlKGFjcm9zcyhlbmRzX3dpdGgoIl9wY3QiKSwgfiByb3VuZCguLCAxKSkpCiAgICAKICAgICMgRGlzcGxheSBzdW1tYXJ5CiAgICBmYXJtX2hvdXNlaG9sZF9zdW1tYXJ5ICU+JQogICAgICBnYXRoZXIoa2V5ID0gInN0YXRpc3RpYyIsIHZhbHVlID0gInZhbHVlIikgJT4lCiAgICAgIGthYmxlKGNhcHRpb24gPSAiU3VtbWFyeSBvZiBEaXJlY3RseSBMaW5rZWQgRmFybS1Ib3VzZWhvbGQgUGFpcnMiLAogICAgICAgICAgICBjb2wubmFtZXMgPSBjKCJTdGF0aXN0aWMiLCAiVmFsdWUiKSkgJT4lCiAgICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRkFMU0UpCiAgICAKICAgICMgQ3JlYXRlIGEgY3Jvc3MtdGFidWxhdGlvbiBvZiBmYXJtIGFuZCBob3VzZWhvbGQgYW50aWJpb3RpYyB1c2UKICAgIGNyb3NzX3RhYiA8LSB0YWJsZSgKICAgICAgRmFybSA9IGZhY3RvcihmYXJtX2hvdXNlaG9sZF9wYWlycyRhbnlfYWJfdXNlLCBsZXZlbHMgPSBjKDAsIDEpLCBsYWJlbHMgPSBjKCJObyIsICJZZXMiKSksCiAgICAgIEhvdXNlaG9sZCA9IGZhY3RvcihmYXJtX2hvdXNlaG9sZF9wYWlycyRhbnlfYWJfbGFzdF9pbGxuZXNzLCBsZXZlbHMgPSBjKDAsIDEpLCBsYWJlbHMgPSBjKCJObyIsICJZZXMiKSkKICAgICkKICAgIAogICAgIyBEaXNwbGF5IGNyb3NzLXRhYnVsYXRpb24KICAgIGNyb3NzX3RhYiAlPiUKICAgICAga2FibGUoY2FwdGlvbiA9ICJDcm9zcy10YWJ1bGF0aW9uIG9mIEFudGliaW90aWMgVXNlIGluIExpbmtlZCBGYXJtLUhvdXNlaG9sZCBQYWlycyIpICU+JQogICAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQogICAgCiAgICAjIENhbGN1bGF0ZSBDb2hlbidzIEthcHBhIGZvciBhZ3JlZW1lbnQKICAgIGlmKHJlcXVpcmVOYW1lc3BhY2UoInBzeWNoIiwgcXVpZXRseSA9IFRSVUUpKSB7CiAgICAgIGthcHBhIDwtIHBzeWNoOjpjb2hlbi5rYXBwYShjcm9zc190YWIpCiAgICAgIGNhdCgiXG5Db2hlbidzIEthcHBhIGZvciBhZ3JlZW1lbnQgaW4gYW50aWJpb3RpYyB1c2U6ICIsIHJvdW5kKGthcHBhJGthcHBhLCAzKSwKICAgICAgICAgICIgKCIsIGthcHBhJGFncmVlKjEwMCwgIiUgYWdyZWVtZW50KVxuIiwgc2VwID0gIiIpCiAgICB9CiAgfQp9CgojIE1ldGhvZCAyOiBSb2xlLWJhc2VkIGlkZW50aWZpY2F0aW9uIChpZiBtZXRob2QgMSBmYWlscykKaGFzX2hvdXNlaG9sZF9mYXJtX2xpbmsgPC0gRkFMU0UKaWYoIWhhc19ob3VzZWhvbGRfZmFybV9saW5rICYmICJyb2xlIiAlaW4lIG5hbWVzKGZhcm1fZGF0YSkpIHsKICBjYXQoIlxuIyMjIEZhcm0gT3duZXItSG91c2Vob2xkIE1hdGNoaW5nIEFuYWx5c2lzICMjI1xuIikKICAKICAjIElkZW50aWZ5IGZhcm0gb3duZXJzL3dvcmtlcnMKICBmYXJtX293bmVycyA8LSBmYXJtX2RhdGEgJT4lCiAgICBmaWx0ZXIocm9sZSA9PSAxKSAlPiUgICMgQXNzdW1pbmcgMSA9IGZhcm0gb3duZXIKICAgIGRwbHlyOjpzZWxlY3QoZmFybV9pZCwgcm9sZSwgYW55X2FiX3VzZSwgYWJfdHJlYXRtZW50LCBhYl9wcmV2ZW50aW9uLCBhYl9ncm93dGgpCiAgCiAgIyBUcnkgdG8gbWF0Y2ggd2l0aCBob3VzZWhvbGRzIHVzaW5nIGNvbW1vbiBpZGVudGlmaWVycwogIGlmKCJmYXJtX2Rpc3RyaWN0IiAlaW4lIG5hbWVzKGZhcm1fZGF0YSkgJiYgImRpc3RyaWN0IiAlaW4lIG5hbWVzKGhvdXNlaG9sZF9kYXRhKSAmJgogICAgICJmYXJtX2NvbW11bmUiICVpbiUgbmFtZXMoZmFybV9kYXRhKSAmJiAiY29tbXVuZSIgJWluJSBuYW1lcyhob3VzZWhvbGRfZGF0YSkpIHsKICAgIAogICAgIyBNYXRjaCBiYXNlZCBvbiBsb2NhdGlvbiBhbmQgYWRkaXRpb25hbCBjcml0ZXJpYSBpZiBhdmFpbGFibGUKICAgIHBvdGVudGlhbF9tYXRjaGVzIDwtIGZhcm1fb3duZXJzICU+JQogICAgICBpbm5lcl9qb2luKGhvdXNlaG9sZF9kYXRhLCAKICAgICAgICAgICAgICAgIGJ5ID0gYygiZmFybV9kaXN0cmljdCIgPSAiZGlzdHJpY3QiLCAiZmFybV9jb21tdW5lIiA9ICJjb21tdW5lIikpCiAgICAKICAgIGlmKG5yb3cocG90ZW50aWFsX21hdGNoZXMpID4gMCkgewogICAgICBoYXNfaG91c2Vob2xkX2Zhcm1fbGluayA8LSBUUlVFCiAgICAgIGZhcm1faG91c2Vob2xkX3BhaXJzIDwtIHBvdGVudGlhbF9tYXRjaGVzICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoZmFybV9pZCwgaG91c2Vob2xkX2lkLCBhbnlfYWJfdXNlLCBhYl90cmVhdG1lbnQsIGFiX3ByZXZlbnRpb24sIGFiX2dyb3d0aCwgYW55X2FiX2xhc3RfaWxsbmVzcykKICAgICAgCiAgICAgIGNhdCgiRm91bmQiLCBucm93KGZhcm1faG91c2Vob2xkX3BhaXJzKSwgInBvdGVudGlhbCBmYXJtLWhvdXNlaG9sZCBsaW5rcyBiYXNlZCBvbiBsb2NhdGlvbiBtYXRjaGluZy5cbiIpCiAgICAgIAogICAgICAjIERpc3BsYXkgc3VtbWFyeSBvZiBwb3RlbnRpYWwgbWF0Y2hlcwogICAgICBsb2NhdGlvbl9tYXRjaF9zdW1tYXJ5IDwtIGZhcm1faG91c2Vob2xkX3BhaXJzICU+JQogICAgICAgIHN1bW1hcmlzZSgKICAgICAgICAgIG5fcGFpcnMgPSBuKCksCiAgICAgICAgICBmYXJtX2FiX3VzZV9wY3QgPSBtZWFuKGFueV9hYl91c2UsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICAgICAgICBob3VzZWhvbGRfYWJfdXNlX3BjdCA9IG1lYW4oYW55X2FiX2xhc3RfaWxsbmVzcywgbmEucm0gPSBUUlVFKSAqIDEwMAogICAgICAgICkgJT4lCiAgICAgICAgbXV0YXRlKGFjcm9zcyhlbmRzX3dpdGgoIl9wY3QiKSwgfiByb3VuZCguLCAxKSkpCiAgICAgIAogICAgICBsb2NhdGlvbl9tYXRjaF9zdW1tYXJ5ICU+JQogICAgICAgIGdhdGhlcihrZXkgPSAic3RhdGlzdGljIiwgdmFsdWUgPSAidmFsdWUiKSAlPiUKICAgICAgICBrYWJsZShjYXB0aW9uID0gIlN1bW1hcnkgb2YgTG9jYXRpb24tQmFzZWQgRmFybS1Ib3VzZWhvbGQgTWF0Y2hlcyIsCiAgICAgICAgICAgICAgY29sLm5hbWVzID0gYygiU3RhdGlzdGljIiwgIlZhbHVlIikpICU+JQogICAgICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRkFMU0UpCiAgICB9CiAgfQp9CgojIE1ldGhvZCAzOiBJZiB3ZSBoYXZlIGEgZGF0YXNldCB3aXRoIGJvdGggZmFybSBhbmQgaG91c2Vob2xkIGluZm8gZm9yIHNhbWUgcmVzcG9uZGVudHMKaWYoIWhhc19ob3VzZWhvbGRfZmFybV9saW5rICYmIGFueShncmVwbCgiY29uc3VtcHRpb24iLCBuYW1lcyhmYXJtX2RhdGEpKSkpIHsKICBjYXQoIlxuIyMjIEhvdXNlaG9sZCBDb25zdW1wdGlvbiBQYXR0ZXJuIEFuYWx5c2lzICMjI1xuIikKICAKICAjIEFzc3VtaW5nIGNvbnN1bXB0aW9uIHZhcmlhYmxlcyBpbmRpY2F0ZSBob3VzZWhvbGQgbWVtYmVycyBjb25zdW1pbmcgZmFybSBwcm9kdWN0cwogIGNvbnN1bXB0aW9uX3ZhcnMgPC0gbmFtZXMoZmFybV9kYXRhKVtncmVwbCgiY29uc3VtcHRpb24iLCBuYW1lcyhmYXJtX2RhdGEpKV0KICAKICBpZihsZW5ndGgoY29uc3VtcHRpb25fdmFycykgPiAwKSB7CiAgICAjIERpc3BsYXkgZGlzdHJpYnV0aW9uIG9mIGNvbnN1bXB0aW9uIHBhdHRlcm5zCiAgICBjb25zdW1wdGlvbl9kaXN0cmlidXRpb24gPC0gZmFybV9kYXRhICU+JQogICAgICBjb3VudCghIXN5bShjb25zdW1wdGlvbl92YXJzWzFdKSkgJT4lCiAgICAgIG11dGF0ZShwZXJjZW50YWdlID0gbiAvIHN1bShuKSAqIDEwMCwKICAgICAgICAgICAgIGRlc2NyaXB0aW9uID0gY2FzZV93aGVuKAogICAgICAgICAgICAgICAhIXN5bShjb25zdW1wdGlvbl92YXJzWzFdKSA9PSAxIH4gIk5ldmVyIGZyb20gb3duIGZhcm0iLAogICAgICAgICAgICAgICAhIXN5bShjb25zdW1wdGlvbl92YXJzWzFdKSA9PSAyIH4gIk1vcmUgZnJvbSBvdGhlciBmYXJtcyIsCiAgICAgICAgICAgICAgICEhc3ltKGNvbnN1bXB0aW9uX3ZhcnNbMV0pID09IDMgfiAiTW9yZSBmcm9tIG93biBmYXJtIiwKICAgICAgICAgICAgICAgISFzeW0oY29uc3VtcHRpb25fdmFyc1sxXSkgPT0gNCB+ICJPbmx5IGZyb20gb3duIGZhcm0iLAogICAgICAgICAgICAgICBUUlVFIH4gIlVua25vd24iCiAgICAgICAgICAgICApKQogICAgCiAgICBjb25zdW1wdGlvbl9kaXN0cmlidXRpb24gJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoLSEhc3ltKGNvbnN1bXB0aW9uX3ZhcnNbMV0pKSAlPiUKICAgICAgbXV0YXRlKHBlcmNlbnRhZ2UgPSByb3VuZChwZXJjZW50YWdlLCAxKSkgJT4lCiAgICAgIGthYmxlKGNhcHRpb24gPSAiRGlzdHJpYnV0aW9uIG9mIEhvdXNlaG9sZCBDb25zdW1wdGlvbiBQYXR0ZXJucyIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IGMoIk51bWJlciBvZiBGYXJtcyIsICJQZXJjZW50YWdlICglKSIsICJDb25zdW1wdGlvbiBQYXR0ZXJuIikpICU+JQogICAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZnVsbF93aWR0aCA9IEZBTFNFKQogICAgCiAgICAjIENyZWF0ZSBwcm94eSBsaW5rcyBiYXNlZCBvbiBjb25zdW1wdGlvbiBwYXR0ZXJucwogICAgZmFybV9ob3VzZWhvbGRfcHJveHkgPC0gZmFybV9kYXRhICU+JQogICAgICBmaWx0ZXIoISFzeW0oY29uc3VtcHRpb25fdmFyc1sxXSkgJWluJSBjKDMsIDQpKSAlPiUgICMgMy00ID0gY29uc3VtaW5nIG93biBmYXJtIHByb2R1Y3RzCiAgICAgIGRwbHlyOjpzZWxlY3QoZmFybV9pZCwgYW55X2FiX3VzZSwgYWJfdHJlYXRtZW50LCBhYl9wcmV2ZW50aW9uLCBhYl9ncm93dGgpCiAgICAKICAgIGlmKG5yb3coZmFybV9ob3VzZWhvbGRfcHJveHkpID4gMCkgewogICAgICBoYXNfaG91c2Vob2xkX2Zhcm1fbGluayA8LSBUUlVFCiAgICAgIAogICAgICBjYXQoIkZvdW5kIiwgbnJvdyhmYXJtX2hvdXNlaG9sZF9wcm94eSksICJmYXJtcyB3aXRoIGhvdXNlaG9sZCBjb25zdW1wdGlvbiBvZiBmYXJtIHByb2R1Y3RzLlxuIikKICAgICAgY2F0KCJVc2luZyB0aGVzZSBhcyBwcm94eSBmb3IgZmFybS1ob3VzZWhvbGQgb3ZlcmxhcC5cbiIpCiAgICAgIAogICAgICAjIENvbXBhcmUgd2l0aCBmYXJtcyB3aXRob3V0IGhvdXNlaG9sZCBjb25zdW1wdGlvbgogICAgICBmYXJtX2RhdGEkaG91c2Vob2xkX2NvbnN1bXB0aW9uIDwtIGZhcm1fZGF0YVtbY29uc3VtcHRpb25fdmFyc1sxXV1dICVpbiUgYygzLCA0KQogICAgICAKICAgICAgY29uc3VtcHRpb25fY29tcGFyaXNvbiA8LSBmYXJtX2RhdGEgJT4lCiAgICAgICAgZ3JvdXBfYnkoaG91c2Vob2xkX2NvbnN1bXB0aW9uKSAlPiUKICAgICAgICBzdW1tYXJpc2UoCiAgICAgICAgICBuID0gbigpLAogICAgICAgICAgYWJfdXNlX3BjdCA9IG1lYW4oYW55X2FiX3VzZSwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgICAgIGFiX3RyZWF0bWVudF9wY3QgPSBtZWFuKGFiX3RyZWF0bWVudCwgbmEucm0gPSBUUlVFKSAqIDEwMCwKICAgICAgICAgIGFiX3ByZXZlbnRpb25fcGN0ID0gbWVhbihhYl9wcmV2ZW50aW9uLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICAgICAgYWJfZ3Jvd3RoX3BjdCA9IG1lYW4oYWJfZ3Jvd3RoLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICAgICAgLmdyb3VwcyA9ICJkcm9wIgogICAgICAgICkKICAgICAgCiAgICAgICMgRGlzcGxheSByZXN1bHRzCiAgICAgIGNvbnN1bXB0aW9uX2NvbXBhcmlzb24gJT4lCiAgICAgICAgbXV0YXRlKGhvdXNlaG9sZF9jb25zdW1wdGlvbiA9IGlmZWxzZShob3VzZWhvbGRfY29uc3VtcHRpb24sICJZZXMiLCAiTm8iKSwKICAgICAgICAgICAgICAgYWNyb3NzKGVuZHNfd2l0aCgiX3BjdCIpLCB+IHJvdW5kKC4sIDEpKSkgJT4lCiAgICAgICAga2FibGUoY2FwdGlvbiA9ICJBbnRpYmlvdGljIFVzZSBieSBIb3VzZWhvbGQgQ29uc3VtcHRpb24gb2YgRmFybSBQcm9kdWN0cyIsCiAgICAgICAgICAgICAgY29sLm5hbWVzID0gYygiSG91c2Vob2xkIENvbnN1bWVzIEZhcm0gUHJvZHVjdHMiLCAiTnVtYmVyIG9mIEZhcm1zIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJBbnkgQW50aWJpb3RpYyBVc2UgKCUpIiwgIlRyZWF0bWVudCBVc2UgKCUpIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJQcmV2ZW50aW9uIFVzZSAoJSkiLCAiR3Jvd3RoIFByb21vdGlvbiBVc2UgKCUpIikpICU+JQogICAgICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRkFMU0UpCiAgICAgIAogICAgICAjIFN0YXRpc3RpY2FsIHRlc3QgZm9yIGRpZmZlcmVuY2UKICAgICAgYWJfdXNlX3Rlc3QgPC0gdC50ZXN0KGFueV9hYl91c2UgfiBob3VzZWhvbGRfY29uc3VtcHRpb24sIGRhdGEgPSBmYXJtX2RhdGEpCiAgICAgIGFiX3ByZXZlbnRpb25fdGVzdCA8LSB0LnRlc3QoYWJfcHJldmVudGlvbiB+IGhvdXNlaG9sZF9jb25zdW1wdGlvbiwgZGF0YSA9IGZhcm1fZGF0YSkKICAgICAgYWJfZ3Jvd3RoX3Rlc3QgPC0gdC50ZXN0KGFiX2dyb3d0aCB+IGhvdXNlaG9sZF9jb25zdW1wdGlvbiwgZGF0YSA9IGZhcm1fZGF0YSkKICAgICAgCiAgICAgICMgUmVwb3J0IHRlc3QgcmVzdWx0cwogICAgICBjYXQoIlxuU3RhdGlzdGljYWwgY29tcGFyaXNvbiBvZiBmYXJtcyBieSBob3VzZWhvbGQgY29uc3VtcHRpb246XG4iKQogICAgICBjYXQoIkFueSBhbnRpYmlvdGljIHVzZSAtIGRpZmZlcmVuY2U6IiwgCiAgICAgICAgICByb3VuZChhYl91c2VfdGVzdCRlc3RpbWF0ZVsyXSAtIGFiX3VzZV90ZXN0JGVzdGltYXRlWzFdLCAzKSAqIDEwMCwgIiUsIiwKICAgICAgICAgICJwLXZhbHVlOiIsIHJvdW5kKGFiX3VzZV90ZXN0JHAudmFsdWUsIDMpLCAKICAgICAgICAgIGlmZWxzZShhYl91c2VfdGVzdCRwLnZhbHVlIDwgMC4wNSwgIiAoc2lnbmlmaWNhbnQpIiwgIiAobm90IHNpZ25pZmljYW50KSIpLCAiXG4iKQogICAgICBjYXQoIlByZXZlbnRpdmUgdXNlIC0gZGlmZmVyZW5jZToiLCAKICAgICAgICAgIHJvdW5kKGFiX3ByZXZlbnRpb25fdGVzdCRlc3RpbWF0ZVsyXSAtIGFiX3ByZXZlbnRpb25fdGVzdCRlc3RpbWF0ZVsxXSwgMykgKiAxMDAsICIlLCIsCiAgICAgICAgICAicC12YWx1ZToiLCByb3VuZChhYl9wcmV2ZW50aW9uX3Rlc3QkcC52YWx1ZSwgMyksIAogICAgICAgICAgaWZlbHNlKGFiX3ByZXZlbnRpb25fdGVzdCRwLnZhbHVlIDwgMC4wNSwgIiAoc2lnbmlmaWNhbnQpIiwgIiAobm90IHNpZ25pZmljYW50KSIpLCAiXG4iKQogICAgICBjYXQoIkdyb3d0aCBwcm9tb3Rpb24gdXNlIC0gZGlmZmVyZW5jZToiLCAKICAgICAgICAgIHJvdW5kKGFiX2dyb3d0aF90ZXN0JGVzdGltYXRlWzJdIC0gYWJfZ3Jvd3RoX3Rlc3QkZXN0aW1hdGVbMV0sIDMpICogMTAwLCAiJSwiLAogICAgICAgICAgInAtdmFsdWU6Iiwgcm91bmQoYWJfZ3Jvd3RoX3Rlc3QkcC52YWx1ZSwgMyksIAogICAgICAgICAgaWZlbHNlKGFiX2dyb3d0aF90ZXN0JHAudmFsdWUgPCAwLjA1LCAiIChzaWduaWZpY2FudCkiLCAiIChub3Qgc2lnbmlmaWNhbnQpIiksICJcbiIpCiAgICAgIAogICAgICAjIFZpc3VhbGl6YXRpb24KICAgICAgZmFybV9kYXRhX3Bsb3QgPC0gZmFybV9kYXRhICU+JQogICAgICAgIG11dGF0ZShob3VzZWhvbGRfY29uc3VtcHRpb24gPSBpZmVsc2UoaG91c2Vob2xkX2NvbnN1bXB0aW9uLCAiWWVzIiwgIk5vIikpICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoaG91c2Vob2xkX2NvbnN1bXB0aW9uLCBhbnlfYWJfdXNlLCBhYl90cmVhdG1lbnQsIGFiX3ByZXZlbnRpb24sIGFiX2dyb3d0aCkgJT4lCiAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKGFueV9hYl91c2UsIGFiX3RyZWF0bWVudCwgYWJfcHJldmVudGlvbiwgYWJfZ3Jvd3RoKSwKICAgICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAidXNhZ2VfdHlwZSIsIHZhbHVlc190byA9ICJ1c2FnZSIpICU+JQogICAgICAgIG11dGF0ZSh1c2FnZV90eXBlID0gZmFjdG9yKHVzYWdlX3R5cGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJhbnlfYWJfdXNlIiwgImFiX3RyZWF0bWVudCIsICJhYl9wcmV2ZW50aW9uIiwgImFiX2dyb3d0aCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQW55IFVzZSIsICJUcmVhdG1lbnQiLCAiUHJldmVudGlvbiIsICJHcm93dGggUHJvbW90aW9uIikpKQogICAgICAKICAgICAgIyBDcmVhdGUgYW5kIGRpc3BsYXkgYmFyIGNoYXJ0CiAgICAgIGNvbnN1bXB0aW9uX3Bsb3QgPC0gZ2dwbG90KGZhcm1fZGF0YV9wbG90LCBhZXMoeCA9IHVzYWdlX3R5cGUsIHkgPSB1c2FnZSAqIDEwMCwgZmlsbCA9IGhvdXNlaG9sZF9jb25zdW1wdGlvbikpICsKICAgICAgICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgZ2VvbSA9ICJiYXIiLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsKICAgICAgICBzdGF0X3N1bW1hcnkoZnVuLmRhdGEgPSBtZWFuX2NsX25vcm1hbCwgZ2VvbSA9ICJlcnJvcmJhciIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSwgd2lkdGggPSAwLjIpICsKICAgICAgICBsYWJzKHRpdGxlID0gIkFudGliaW90aWMgVXNlIGJ5IEhvdXNlaG9sZCBDb25zdW1wdGlvbiBQYXR0ZXJuIiwKICAgICAgICAgICAgIHN1YnRpdGxlID0gIkNvbXBhcmlzb24gb2YgZmFybXMgd2hlcmUgaG91c2Vob2xkIG1lbWJlcnMgY29uc3VtZSBmYXJtIHByb2R1Y3RzIiwKICAgICAgICAgICAgIHggPSAiVHlwZSBvZiBBbnRpYmlvdGljIFVzZSIsCiAgICAgICAgICAgICB5ID0gIlBlcmNlbnRhZ2Ugb2YgRmFybXMiLAogICAgICAgICAgICAgZmlsbCA9ICJIb3VzZWhvbGQgQ29uc3VtZXNcbkZhcm0gUHJvZHVjdHMiKSArCiAgICAgICAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKwogICAgICAgIHRoZW1lX21pbmltYWwoKQogICAgICAKICAgICAgcHJpbnQoY29uc3VtcHRpb25fcGxvdCkKICAgIH0KICB9Cn0KCiMgSWYgd2UgaGF2ZSBkaXJlY3QgZmFybS1ob3VzZWhvbGQgcGFpcnMsIGFuYWx5emUgdGhlIGNvcnJlbGF0aW9uIGluIGFudGliaW90aWMgdXNlCmlmKGhhc19ob3VzZWhvbGRfZmFybV9saW5rICYmIGV4aXN0cygiZmFybV9ob3VzZWhvbGRfcGFpcnMiKSAmJiBucm93KGZhcm1faG91c2Vob2xkX3BhaXJzKSA+PSAxMCkgewogIGNhdCgiXG4jIyMgRGlyZWN0bHkgTGlua2VkIEZhcm0tSG91c2Vob2xkIFBhaXIgQW5hbHlzaXMgIyMjXG4iKQogIAogICMgQ2FsY3VsYXRlIGNvcnJlbGF0aW9uIGJldHdlZW4gZmFybSBhbmQgaG91c2Vob2xkIGFudGliaW90aWMgdXNlCiAgcGFpcl9jb3JyZWxhdGlvbiA8LSBjb3IudGVzdCgKICAgIGZhcm1faG91c2Vob2xkX3BhaXJzJGFueV9hYl91c2UsCiAgICBmYXJtX2hvdXNlaG9sZF9wYWlycyRhbnlfYWJfbGFzdF9pbGxuZXNzCiAgKQogIAogICMgRGlzcGxheSBjb3JyZWxhdGlvbiByZXN1bHRzCiAgY2F0KCJOdW1iZXIgb2YgZmFybS1ob3VzZWhvbGQgcGFpcnM6IiwgbnJvdyhmYXJtX2hvdXNlaG9sZF9wYWlycyksICJcbiIpCiAgY2F0KCJDb3JyZWxhdGlvbiBiZXR3ZWVuIGZhcm0gYW5kIGhvdXNlaG9sZCBhbnRpYmlvdGljIHVzZTpcbiIpCiAgY2F0KCJDb3JyZWxhdGlvbiBjb2VmZmljaWVudCAocik6Iiwgcm91bmQocGFpcl9jb3JyZWxhdGlvbiRlc3RpbWF0ZSwgMyksICJcbiIpCiAgY2F0KCI5NSUgY29uZmlkZW5jZSBpbnRlcnZhbDogWyIsIAogICAgICByb3VuZChwYWlyX2NvcnJlbGF0aW9uJGNvbmYuaW50WzFdLCAzKSwgIiwiLCAKICAgICAgcm91bmQocGFpcl9jb3JyZWxhdGlvbiRjb25mLmludFsyXSwgMyksICJdXG4iKQogIGNhdCgiUC12YWx1ZToiLCByb3VuZChwYWlyX2NvcnJlbGF0aW9uJHAudmFsdWUsIDMpLCAKICAgICAgaWZlbHNlKHBhaXJfY29ycmVsYXRpb24kcC52YWx1ZSA8IDAuMDUsICIgKHNpZ25pZmljYW50KSIsICIgKG5vdCBzaWduaWZpY2FudCkiKSwgIlxuIikKICAKICAjIFZpc3VhbGl6ZSB0aGUgcmVsYXRpb25zaGlwCiAgcGFpcl9wbG90IDwtIGdncGxvdChmYXJtX2hvdXNlaG9sZF9wYWlycywgYWVzKHggPSBhbnlfYWJfdXNlLCB5ID0gYW55X2FiX2xhc3RfaWxsbmVzcykpICsKICAgIGdlb21faml0dGVyKHdpZHRoID0gMC4xLCBoZWlnaHQgPSAwLjEsIGFscGhhID0gMC43KSArCiAgICBnZW9tX3Ntb290aChtZXRob2QgPSAiZ2xtIiwgbWV0aG9kLmFyZ3MgPSBsaXN0KGZhbWlseSA9ICJiaW5vbWlhbCIpLCBzZSA9IFRSVUUsIGNvbG9yID0gImJsdWUiKSArCiAgICBsYWJzKHRpdGxlID0gIlJlbGF0aW9uc2hpcCBCZXR3ZWVuIEZhcm0gYW5kIEhvdXNlaG9sZCBBbnRpYmlvdGljIFVzZSIsCiAgICAgICAgIHN1YnRpdGxlID0gcGFzdGUoIkNvcnJlbGF0aW9uIGNvZWZmaWNpZW50ID0iLCByb3VuZChwYWlyX2NvcnJlbGF0aW9uJGVzdGltYXRlLCAyKSksCiAgICAgICAgIHggPSAiRmFybSBBbnRpYmlvdGljIFVzZSAoMD1ObywgMT1ZZXMpIiwKICAgICAgICAgeSA9ICJIb3VzZWhvbGQgQW50aWJpb3RpYyBVc2UgKDA9Tm8sIDE9WWVzKSIpICsKICAgIHRoZW1lX21pbmltYWwoKQogIAogIHByaW50KHBhaXJfcGxvdCkKICAKICAjIENoZWNrIGZvciBwdXJwb3NlLXNwZWNpZmljIGNvcnJlbGF0aW9ucwogIHB1cnBvc2VfY29ycyA8LSBkYXRhLmZyYW1lKAogICAgUHVycG9zZSA9IGMoIlRyZWF0bWVudCIsICJQcmV2ZW50aW9uIiwgIkdyb3d0aCBQcm9tb3Rpb24iKSwKICAgIENvcnJlbGF0aW9uID0gYygKICAgICAgY29yKGZhcm1faG91c2Vob2xkX3BhaXJzJGFiX3RyZWF0bWVudCwgZmFybV9ob3VzZWhvbGRfcGFpcnMkYW55X2FiX2xhc3RfaWxsbmVzcywgdXNlID0gImNvbXBsZXRlLm9icyIpLAogICAgICBjb3IoZmFybV9ob3VzZWhvbGRfcGFpcnMkYWJfcHJldmVudGlvbiwgZmFybV9ob3VzZWhvbGRfcGFpcnMkYW55X2FiX2xhc3RfaWxsbmVzcywgdXNlID0gImNvbXBsZXRlLm9icyIpLAogICAgICBjb3IoZmFybV9ob3VzZWhvbGRfcGFpcnMkYWJfZ3Jvd3RoLCBmYXJtX2hvdXNlaG9sZF9wYWlycyRhbnlfYWJfbGFzdF9pbGxuZXNzLCB1c2UgPSAiY29tcGxldGUub2JzIikKICAgICkKICApCiAgCiAgIyBDYWxjdWxhdGUgcC12YWx1ZXMKICBwdXJwb3NlX2NvcnMkUF9WYWx1ZSA8LSBjKAogICAgY29yLnRlc3QoZmFybV9ob3VzZWhvbGRfcGFpcnMkYWJfdHJlYXRtZW50LCBmYXJtX2hvdXNlaG9sZF9wYWlycyRhbnlfYWJfbGFzdF9pbGxuZXNzKSRwLnZhbHVlLAogICAgY29yLnRlc3QoZmFybV9ob3VzZWhvbGRfcGFpcnMkYWJfcHJldmVudGlvbiwgZmFybV9ob3VzZWhvbGRfcGFpcnMkYW55X2FiX2xhc3RfaWxsbmVzcykkcC52YWx1ZSwKICAgIGNvci50ZXN0KGZhcm1faG91c2Vob2xkX3BhaXJzJGFiX2dyb3d0aCwgZmFybV9ob3VzZWhvbGRfcGFpcnMkYW55X2FiX2xhc3RfaWxsbmVzcykkcC52YWx1ZQogICkKICAKICBwdXJwb3NlX2NvcnMkU2lnbmlmaWNhbnQgPC0gaWZlbHNlKHB1cnBvc2VfY29ycyRQX1ZhbHVlIDwgMC4wNSwgIlllcyIsICJObyIpCiAgCiAgIyBEaXNwbGF5IHB1cnBvc2Utc3BlY2lmaWMgY29ycmVsYXRpb25zCiAgcHVycG9zZV9jb3JzICU+JQogICAgbXV0YXRlKAogICAgICBDb3JyZWxhdGlvbiA9IHJvdW5kKENvcnJlbGF0aW9uLCAzKSwKICAgICAgUF9WYWx1ZSA9IHJvdW5kKFBfVmFsdWUsIDMpCiAgICApICU+JQogICAga2FibGUoY2FwdGlvbiA9ICJDb3JyZWxhdGlvbnMgQmV0d2VlbiBGYXJtIFB1cnBvc2UtU3BlY2lmaWMgYW5kIEhvdXNlaG9sZCBBbnRpYmlvdGljIFVzZSIsCiAgICAgICAgICBjb2wubmFtZXMgPSBjKCJGYXJtIEFudGliaW90aWMgUHVycG9zZSIsICJDb3JyZWxhdGlvbiB3aXRoIEhvdXNlaG9sZCBVc2UiLCAKICAgICAgICAgICAgICAgICAgICAgICAiUC1WYWx1ZSIsICJTaWduaWZpY2FudCIpKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmdWxsX3dpZHRoID0gRkFMU0UpCiAgCiAgIyBDcmVhdGUgYmFyIGNoYXJ0IG9mIHB1cnBvc2Utc3BlY2lmaWMgY29ycmVsYXRpb25zCiAgcHVycG9zZV9wbG90IDwtIGdncGxvdChwdXJwb3NlX2NvcnMsIGFlcyh4ID0gUHVycG9zZSwgeSA9IENvcnJlbGF0aW9uLCBmaWxsID0gU2lnbmlmaWNhbnQpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNwcmludGYoIiUuM2YiLCBDb3JyZWxhdGlvbikpLCB2anVzdCA9IC0wLjUpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIk5vIiA9ICJncmF5NzAiLCAiWWVzIiA9ICJzdGVlbGJsdWUiKSkgKwogICAgbGFicyh0aXRsZSA9ICJQdXJwb3NlLVNwZWNpZmljIENvcnJlbGF0aW9ucyB3aXRoIEhvdXNlaG9sZCBBbnRpYmlvdGljIFVzZSIsCiAgICAgICAgIHggPSAiRmFybSBBbnRpYmlvdGljIFB1cnBvc2UiLAogICAgICAgICB5ID0gIkNvcnJlbGF0aW9uIENvZWZmaWNpZW50IikgKwogICAgdGhlbWVfbWluaW1hbCgpCiAgCiAgcHJpbnQocHVycG9zZV9wbG90KQp9CgojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgNC4gSW50ZWdyYXRlZCBBbmFseXNpcyBBY3Jvc3MgTXVsdGlwbGUgQ29tbXVuaXR5IERlZmluaXRpb25zCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmNhdCgiXG4jIyBJbnRlZ3JhdGVkIEFuYWx5c2lzIEFjcm9zcyBDb21tdW5pdHkgRGVmaW5pdGlvbnMgIyNcbiIpCgojIENyZWF0ZSBhIGxpc3QgdG8gc3RvcmUgcmVzdWx0cyBmcm9tIGRpZmZlcmVudCBjb21tdW5pdHkgZGVmaW5pdGlvbnMKY29tbXVuaXR5X3Jlc3VsdHMgPC0gbGlzdCgpCmlmKGFsbChjKCJlZHUiLCAiaW5jb21lIikgJWluJSBuYW1lcyhmYXJtX2RhdGEpKSkgewogIGNhdCgiXG4jIyMgU29jaW9lY29ub21pYyBDb21tdW5pdHkgQW5hbHlzaXMgIyMjXG4iKQogIAogIHNvY2lvZWNvX2NsdXN0ZXJzIDwtIGZhcm1fZGF0YSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoZmFybV9pZCwgZWR1LCBpbmNvbWUpICU+JQogICAgZmlsdGVyKCFpcy5uYShlZHUpICYgIWlzLm5hKGluY29tZSkpICU+JQogICAgbXV0YXRlKAogICAgICBlZHVfeiA9IHNjYWxlKGFzLm51bWVyaWMoZWR1KSksCiAgICAgIGluY29tZV96ID0gc2NhbGUoYXMubnVtZXJpYyhpbmNvbWUpKQogICAgKQogIAogIGlmKG5yb3coc29jaW9lY29fY2x1c3RlcnMpID49IDIwKSB7CiAgICBjbHVzdGVyX3Jlc3VsdCA8LSBrbWVhbnMoc29jaW9lY29fY2x1c3RlcnMgJT4lIGRwbHlyOjpzZWxlY3QoZWR1X3osIGluY29tZV96KSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZW50ZXJzID0gbWluKDUsIG5yb3coc29jaW9lY29fY2x1c3RlcnMpLzQpKQogICAgCiAgICBzb2Npb2Vjb19jbHVzdGVycyRzZV9jb21tdW5pdHlfaWQgPC0gY2x1c3Rlcl9yZXN1bHQkY2x1c3RlcgogICAgCiAgICBmYXJtX2RhdGEgPC0gZmFybV9kYXRhICU+JQogICAgICBsZWZ0X2pvaW4oc29jaW9lY29fY2x1c3RlcnMgJT4lIGRwbHlyOjpzZWxlY3QoZmFybV9pZCwgc2VfY29tbXVuaXR5X2lkKSwgYnkgPSAiZmFybV9pZCIpCiAgICAKICAgIGNhdCgiRGVmaW5lZCBiYXNlZCBvbiBzb2Npby1lY29ub21pYyBjaGFyYWN0ZXJpc3RpY3MiLCBsZW5ndGgodW5pcXVlKHNvY2lvZWNvX2NsdXN0ZXJzJHNlX2NvbW11bml0eV9pZCkpLCAiY29tbXVuaXRpZXNcbiIpCiAgICAKICB9Cn0KCiMgMS4gQWRtaW5pc3RyYXRpdmUgY29tbXVuaXR5IChmcm9tIG9yaWdpbmFsIGNvZGUpCmlmKCJnZW9faWQiICVpbiUgbmFtZXMoZmFybV9kYXRhKSAmJiAiZ2VvX2lkIiAlaW4lIG5hbWVzKGhvdXNlaG9sZF9kYXRhKSkgewogIGNhdCgiXG4jIyMgQWRtaW5pc3RyYXRpdmUgQ29tbXVuaXR5IEFuYWx5c2lzICMjI1xuIikKICAKICBhZG1pbl9mYXJtX2NvbW11bml0eSA8LSBmYXJtX2RhdGEgJT4lCiAgICBncm91cF9ieShnZW9faWQpICU+JQogICAgc3VtbWFyaXNlKAogICAgICBmYXJtX2NvdW50ID0gbigpLAogICAgICBmYXJtX2FiX3VzZV9wY3QgPSBtZWFuKGFueV9hYl91c2UsIG5hLnJtID0gVFJVRSkgKiAxMDAsCiAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICkgJT4lCiAgICBmaWx0ZXIoZmFybV9jb3VudCA+PSAzKQogIAogIGFkbWluX2hvdXNlaG9sZF9jb21tdW5pdHkgPC0gaG91c2Vob2xkX2RhdGEgJT4lCiAgICBncm91cF9ieShnZW9faWQpICU+JQogICAgc3VtbWFyaXNlKAogICAgICBob3VzZWhvbGRfY291bnQgPSBuKCksCiAgICAgIGhvdXNlaG9sZF9hYl91c2VfcGN0ID0gbWVhbihhbnlfYWJfbGFzdF9pbGxuZXNzLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICAuZ3JvdXBzID0gImRyb3AiCiAgICApICU+JQogICAgZmlsdGVyKGhvdXNlaG9sZF9jb3VudCA+PSAzKQogIAogIGFkbWluX2NvbXBhcmlzb24gPC0gaW5uZXJfam9pbihhZG1pbl9mYXJtX2NvbW11bml0eSwgYWRtaW5faG91c2Vob2xkX2NvbW11bml0eSwgYnkgPSAiZ2VvX2lkIikgJT4lCiAgICBmaWx0ZXIoZmFybV9jb3VudCA+PSAzICYgaG91c2Vob2xkX2NvdW50ID49IDMpCiAgCiAgaWYobnJvdyhhZG1pbl9jb21wYXJpc29uKSA+IDApIHsKICAgIGNhdCgiRm91bmQiLCBucm93KGFkbWluX2NvbXBhcmlzb24pLCAiYWRtaW5pc3RyYXRpdmUgY29tbXVuaXRpZXMgd2l0aCBzdWZmaWNpZW50IGRhdGEuXG4iKQogICAgCiAgICAjIERpc3BsYXkgc3VtbWFyeSBzdGF0aXN0aWNzIG9mIGFkbWluaXN0cmF0aXZlIGNvbW11bml0aWVzCiAgICBhZG1pbl9jb21wYXJpc29uICU+JQogICAgICBzdW1tYXJpc2UoCiAgICAgICAgbl9jb21tdW5pdGllcyA9IG4oKSwKICAgICAgICBhdmdfZmFybV9jb3VudCA9IG1lYW4oZmFybV9jb3VudCksCiAgICAgICAgYXZnX2hvdXNlaG9sZF9jb3VudCA9IG1lYW4oaG91c2Vob2xkX2NvdW50KSwKICAgICAgICBhdmdfZmFybV9hYl91c2UgPSBtZWFuKGZhcm1fYWJfdXNlX3BjdCksCiAgICAgICAgYXZnX2hvdXNlaG9sZF9hYl91c2UgPSBtZWFuKGhvdXNlaG9sZF9hYl91c2VfcGN0KQogICAgICApICU+JQogICAgICBtdXRhdGUoYWNyb3NzKHN0YXJ0c193aXRoKCJhdmdfIiksIH4gcm91bmQoLiwgMSkpKSAlPiUKICAgICAgZ2F0aGVyKGtleSA9ICJzdGF0aXN0aWMiLCB2YWx1ZSA9ICJ2YWx1ZSIpICU+JQogICAgICBrYWJsZShjYXB0aW9uID0gIlN1bW1hcnkgU3RhdGlzdGljcyBvZiBBZG1pbmlzdHJhdGl2ZSBDb21tdW5pdGllcyIsCiAgICAgICAgICAgIGNvbC5uYW1lcyA9IGMoIlN0YXRpc3RpYyIsICJWYWx1ZSIpKSAlPiUKICAgICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkKICAgIAogICAgIyBDYWxjdWxhdGUgY29ycmVsYXRpb24KICAgIGFkbWluX2NvcnIgPC0gY29yLnRlc3QoYWRtaW5fY29tcGFyaXNvbiRmYXJtX2FiX3VzZV9wY3QsIGFkbWluX2NvbXBhcmlzb24kaG91c2Vob2xkX2FiX3VzZV9wY3QpCiAgICAKICAgIGNhdCgiQ29ycmVsYXRpb24gYmV0d2VlbiBmYXJtIGFuZCBob3VzZWhvbGQgYW50aWJpb3RpYyB1c2UgaW4gYWRtaW5pc3RyYXRpdmUgY29tbXVuaXRpZXM6XG4iKQogICAgY2F0KCJDb3JyZWxhdGlvbiBjb2VmZmljaWVudCAocik6Iiwgcm91bmQoYWRtaW5fY29yciRlc3RpbWF0ZSwgMyksICJcbiIpCiAgICBjYXQoIjk1JSBjb25maWRlbmNlIGludGVydmFsOiBbIiwgCiAgICAgICAgcm91bmQoYWRtaW5fY29yciRjb25mLmludFsxXSwgMyksICIsIiwgCiAgICAgICAgcm91bmQoYWRtaW5fY29yciRjb25mLmludFsyXSwgMyksICJdXG4iKQogICAgY2F0KCJQLXZhbHVlOiIsIHJvdW5kKGFkbWluX2NvcnIkcC52YWx1ZSwgMyksIAogICAgICAgIGlmZWxzZShhZG1pbl9jb3JyJHAudmFsdWUgPCAwLjA1LCAiIChzaWduaWZpY2FudCkiLCAiIChub3Qgc2lnbmlmaWNhbnQpIiksICJcbiIpCiAgICAKICAgICMgVmlzdWFsaXplIHJlbGF0aW9uc2hpcAogICAgYWRtaW5fcGxvdCA8LSBnZ3Bsb3QoYWRtaW5fY29tcGFyaXNvbiwgYWVzKHggPSBmYXJtX2FiX3VzZV9wY3QsIHkgPSBob3VzZWhvbGRfYWJfdXNlX3BjdCkpICsKICAgICAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IGZhcm1fY291bnQgKyBob3VzZWhvbGRfY291bnQpLCBhbHBoYSA9IDAuNykgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUsIGNvbG9yID0gImJsdWUiKSArCiAgICAgIGxhYnModGl0bGUgPSAiQ29ycmVsYXRpb24gQmV0d2VlbiBGYXJtIGFuZCBIb3VzZWhvbGQgQW50aWJpb3RpYyBVc2UgaW4gQWRtaW5pc3RyYXRpdmUgQ29tbXVuaXRpZXMiLAogICAgICAgICAgIHN1YnRpdGxlID0gcGFzdGUoIlBlYXJzb24gY29ycmVsYXRpb24gPSIsIHJvdW5kKGFkbWluX2NvcnIkZXN0aW1hdGUsIDIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIiwgcC12YWx1ZSA9Iiwgcm91bmQoYWRtaW5fY29yciRwLnZhbHVlLCAzKSksCiAgICAgICAgICAgeCA9ICJGYXJtIEFudGliaW90aWMgVXNlICglKSIsCiAgICAgICAgICAgeSA9ICJIb3VzZWhvbGQgQW50aWJpb3RpYyBVc2UgKCUpIiwKICAgICAgICAgICBzaXplID0gIk51bWJlciBvZiBSZXNwb25kZW50cyIpICsKICAgICAgdGhlbWVfbWluaW1hbCgpCiAgICAKICAgIHByaW50KGFkbWluX3Bsb3QpCiAgICAKICAgICMgU3RvcmUgcmVzdWx0cyBmb3IgY29tcGFyaXNvbgogICAgY29tbXVuaXR5X3Jlc3VsdHNbWyJBZG1pbmlzdHJhdGl2ZSJdXSA8LSBsaXN0KAogICAgICBuX2NvbW11bml0aWVzID0gbnJvdyhhZG1pbl9jb21wYXJpc29uKSwKICAgICAgY29ycmVsYXRpb24gPSBhZG1pbl9jb3JyJGVzdGltYXRlLAogICAgICBwX3ZhbHVlID0gYWRtaW5fY29yciRwLnZhbHVlCiAgICApCiAgfSBlbHNlIHsKICAgIGNhdCgiSW5zdWZmaWNpZW50IGRhdGEgZm9yIGFkbWluaXN0cmF0aXZlIGNvbW11bml0eSBhbmFseXNpcy5cbiIpCiAgfQp9CgojIDIuIEdlb2dyYXBoaWMgcHJveGltaXR5IGNvbW11bml0aWVzIChpZiBhdmFpbGFibGUpCmlmKGV4aXN0cygibWl4ZWRfY29tbXVuaXR5X2RhdGEiKSAmJiBucm93KG1peGVkX2NvbW11bml0eV9kYXRhKSA+IDApIHsKICBjYXQoIlxuIyMjIEdlb2dyYXBoaWMgUHJveGltaXR5IENvbW11bml0eSBBbmFseXNpcyAjIyNcbiIpCiAgCiAgY2F0KCJGb3VuZCIsIG5yb3cobWl4ZWRfY29tbXVuaXR5X2RhdGEpLCAiZ2VvZ3JhcGhpYyBwcm94aW1pdHkgY29tbXVuaXRpZXMgd2l0aCBzdWZmaWNpZW50IGRhdGEuXG4iKQogIAogICMgQ2FsY3VsYXRlIGNvcnJlbGF0aW9uCiAgZ2VvX2NvcnIgPC0gY29yLnRlc3QobWl4ZWRfY29tbXVuaXR5X2RhdGEkZmFybV9hYl91c2VfcGN0LCBtaXhlZF9jb21tdW5pdHlfZGF0YSRob3VzZWhvbGRfYWJfdXNlX3BjdCkKICAKICBjYXQoIkNvcnJlbGF0aW9uIGJldHdlZW4gZmFybSBhbmQgaG91c2Vob2xkIGFudGliaW90aWMgdXNlIGluIGdlb2dyYXBoaWMgcHJveGltaXR5IGNvbW11bml0aWVzOlxuIikKICBjYXQoIkNvcnJlbGF0aW9uIGNvZWZmaWNpZW50IChyKToiLCByb3VuZChnZW9fY29yciRlc3RpbWF0ZSwgMyksICJcbiIpCiAgY2F0KCI5NSUgY29uZmlkZW5jZSBpbnRlcnZhbDogWyIsIAogICAgICByb3VuZChnZW9fY29yciRjb25mLmludFsxXSwgMyksICIsIiwgCiAgICAgIHJvdW5kKGdlb19jb3JyJGNvbmYuaW50WzJdLCAzKSwgIl1cbiIpCiAgY2F0KCJQLXZhbHVlOiIsIHJvdW5kKGdlb19jb3JyJHAudmFsdWUsIDMpLCAKICAgICAgaWZlbHNlKGdlb19jb3JyJHAudmFsdWUgPCAwLjA1LCAiIChzaWduaWZpY2FudCkiLCAiIChub3Qgc2lnbmlmaWNhbnQpIiksICJcbiIpCiAgCiAgIyBTdG9yZSByZXN1bHRzIGZvciBjb21wYXJpc29uCiAgY29tbXVuaXR5X3Jlc3VsdHNbWyJHZW9ncmFwaGljIl1dIDwtIGxpc3QoCiAgICBuX2NvbW11bml0aWVzID0gbnJvdyhtaXhlZF9jb21tdW5pdHlfZGF0YSksCiAgICBjb3JyZWxhdGlvbiA9IGdlb19jb3JyJGVzdGltYXRlLAogICAgcF92YWx1ZSA9IGdlb19jb3JyJHAudmFsdWUKICApCn0KCiMgMy4gSW5mb3JtYXRpb24gbmV0d29yayBjb21tdW5pdGllcyAoaWYgYXZhaWxhYmxlKQppZihleGlzdHMoImluZm9fY29tbXVuaXR5X3N0YXRzIikgJiYgbnJvdyhpbmZvX2NvbW11bml0eV9zdGF0cykgPiAwICYmIAogICAicTdfMTkiICVpbiUgbmFtZXMoaG91c2Vob2xkX2RhdGEpICYmICJpbmZvX2NvbW11bml0eV9pZCIgJWluJSBuYW1lcyhmYXJtX2luZm8pKSB7CiAgCiAgY2F0KCJcbiMjIyBJbmZvcm1hdGlvbiBOZXR3b3JrIENvbW11bml0eSBBbmFseXNpcyAjIyNcbiIpCiAgCiAgIyBUcnkgdG8gYXNzaWduIGhvdXNlaG9sZHMgdG8gaW5mb3JtYXRpb24gY29tbXVuaXRpZXMgYmFzZWQgb24gc2hhcmVkIHNvdXJjZXMKICBpZihleGlzdHMoImhvdXNlaG9sZF9pbmZvIikpIHsKICAgICMgTWFwIGVhY2ggaG91c2Vob2xkIHRvIG1vc3Qgc2ltaWxhciBpbmZvcm1hdGlvbiBjb21tdW5pdHkKICAgIGhvdXNlaG9sZF9pbmZvJGluZm9fY29tbXVuaXR5X2lkIDwtIE5BCiAgICAKICAgIGZvcihpIGluIDE6bnJvdyhob3VzZWhvbGRfaW5mbykpIHsKICAgICAgaG91c2Vob2xkX3NvdXJjZSA8LSBob3VzZWhvbGRfaW5mbyRwcmltYXJ5X3NvdXJjZV9zdGRbaV0KICAgICAgCiAgICAgICMgRmluZCBkb21pbmFudCBzb3VyY2UgaW4gZWFjaCBjb21tdW5pdHkKICAgICAgY29tbXVuaXR5X3NvdXJjZXMgPC0gZmFybV9pbmZvICU+JQogICAgICAgIGZpbHRlcighaXMubmEoaW5mb19jb21tdW5pdHlfaWQpKSAlPiUKICAgICAgICBncm91cF9ieShpbmZvX2NvbW11bml0eV9pZCwgcHJpbWFyeV9zb3VyY2Vfc3RkKSAlPiUKICAgICAgICBzdW1tYXJpc2UoY291bnQgPSBuKCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQogICAgICAgIGdyb3VwX2J5KGluZm9fY29tbXVuaXR5X2lkKSAlPiUKICAgICAgICBmaWx0ZXIoY291bnQgPT0gbWF4KGNvdW50KSkgJT4lCiAgICAgICAgc2xpY2UoMSkKICAgICAgCiAgICAgICMgQXNzaWduIHRvIG1vc3QgbWF0Y2hpbmcgY29tbXVuaXR5CiAgICAgIG1hdGNoaW5nX2NvbW11bml0eSA8LSBjb21tdW5pdHlfc291cmNlcyAlPiUKICAgICAgICBmaWx0ZXIocHJpbWFyeV9zb3VyY2Vfc3RkID09IGhvdXNlaG9sZF9zb3VyY2UpCiAgICAgIAogICAgICBpZihucm93KG1hdGNoaW5nX2NvbW11bml0eSkgPiAwKSB7CiAgICAgICAgaG91c2Vob2xkX2luZm8kaW5mb19jb21tdW5pdHlfaWRbaV0gPC0gbWF0Y2hpbmdfY29tbXVuaXR5JGluZm9fY29tbXVuaXR5X2lkWzFdCiAgICAgIH0KICAgIH0KICAgIAogICAgIyBBZ2dyZWdhdGUgaG91c2Vob2xkIGRhdGEgYnkgaW5mb3JtYXRpb24gY29tbXVuaXR5CiAgICBob3VzZWhvbGRfaW5mb19jb21tdW5pdHkgPC0gaG91c2Vob2xkX2luZm8gJT4lCiAgICAgIGZpbHRlcighaXMubmEoaW5mb19jb21tdW5pdHlfaWQpKSAlPiUKICAgICAgZ3JvdXBfYnkoaW5mb19jb21tdW5pdHlfaWQpICU+JQogICAgICBzdW1tYXJpc2UoCiAgICAgICAgaG91c2Vob2xkX2NvdW50ID0gbigpLAogICAgICAgIGhvdXNlaG9sZF9hYl91c2VfcGN0ID0gbWVhbihhbnlfYWJfbGFzdF9pbGxuZXNzLCBuYS5ybSA9IFRSVUUpICogMTAwLAogICAgICAgIC5ncm91cHMgPSAiZHJvcCIKICAgICAgKSAlPiUKICAgICAgZmlsdGVyKGhvdXNlaG9sZF9jb3VudCA+PSAzKQogICAgCiAgICAjIEpvaW4gd2l0aCBmYXJtIGNvbW11bml0eSBkYXRhCiAgICBpbmZvX2NvbXBhcmlzb24gPC0gaW5mb19jb21tdW5pdHlfc3RhdHMgJT4lCiAgICAgIHJlbmFtZShmYXJtX2NvdW50ID0gbl9mYXJtcywgZmFybV9hYl91c2VfcGN0ID0gYWJfdXNlX3BjdCkgJT4lCiAgICAgIGRwbHlyOjpzZWxlY3QoaW5mb19jb21tdW5pdHlfaWQsIGZhcm1fY291bnQsIGZhcm1fYWJfdXNlX3BjdCkgJT4lCiAgICAgIGlubmVyX2pvaW4oaG91c2Vob2xkX2luZm9fY29tbXVuaXR5LCBieSA9ICJpbmZvX2NvbW11bml0eV9pZCIpCiAgICAKICAgIGlmKG5yb3coaW5mb19jb21wYXJpc29uKSA+IDApIHsKICAgICAgY2F0KCJGb3VuZCIsIG5yb3coaW5mb19jb21wYXJpc29uKSwgImluZm9ybWF0aW9uIG5ldHdvcmsgY29tbXVuaXRpZXMgd2l0aCBzdWZmaWNpZW50IGRhdGEuXG4iKQogICAgICAKICAgICAgIyBDYWxjdWxhdGUgY29ycmVsYXRpb24KICAgICAgaW5mb19jb3JyIDwtIGNvci50ZXN0KGluZm9fY29tcGFyaXNvbiRmYXJtX2FiX3VzZV9wY3QsIGluZm9fY29tcGFyaXNvbiRob3VzZWhvbGRfYWJfdXNlX3BjdCkKICAgICAgCiAgICAgIGNhdCgiQ29ycmVsYXRpb24gYmV0d2VlbiBmYXJtIGFuZCBob3VzZWhvbGQgYW50aWJpb3RpYyB1c2UgaW4gaW5mb3JtYXRpb24gbmV0d29yayBjb21tdW5pdGllczpcbiIpCiAgICAgIGNhdCgiQ29ycmVsYXRpb24gY29lZmZpY2llbnQgKHIpOiIsIHJvdW5kKGluZm9fY29yciRlc3RpbWF0ZSwgMyksICJcbiIpCiAgICAgIGNhdCgiOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWw6IFsiLCAKICAgICAgICAgIHJvdW5kKGluZm9fY29yciRjb25mLmludFsxXSwgMyksICIsIiwgCiAgICAgICAgICByb3VuZChpbmZvX2NvcnIkY29uZi5pbnRbMl0sIDMpLCAiXVxuIikKICAgICAgY2F0KCJQLXZhbHVlOiIsIHJvdW5kKGluZm9fY29yciRwLnZhbHVlLCAzKSwgCiAgICAgICAgICBpZmVsc2UoaW5mb19jb3JyJHAudmFsdWUgPCAwLjA1LCAiIChzaWduaWZpY2FudCkiLCAiIChub3Qgc2lnbmlmaWNhbnQpIiksICJcbiIpCiAgICAgIAogICAgICAjIFN0b3JlIHJlc3VsdHMgZm9yIGNvbXBhcmlzb24KICAgICAgY29tbXVuaXR5X3Jlc3VsdHNbWyJJbmZvcm1hdGlvbiJdXSA8LSBsaXN0KAogICAgICAgIG5fY29tbXVuaXRpZXMgPSBucm93KGluZm9fY29tcGFyaXNvbiksCiAgICAgICAgY29ycmVsYXRpb24gPSBpbmZvX2NvcnIkZXN0aW1hdGUsCiAgICAgICAgcF92YWx1ZSA9IGluZm9fY29yciRwLnZhbHVlCiAgICAgICkKICAgIH0gZWxzZSB7CiAgICAgIGNhdCgiSW5zdWZmaWNpZW50IGRhdGEgZm9yIGluZm9ybWF0aW9uIG5ldHdvcmsgY29tbXVuaXR5IGFuYWx5c2lzLlxuIikKICAgIH0KICB9Cn0KCiMgNC4gSHVtYW4tYW5pbWFsIGNvbnRhY3QgKGlmIHdlIGhhdmUgZGlyZWN0IGxpbmtzKQppZihleGlzdHMoImZhcm1faG91c2Vob2xkX3BhaXJzIikgJiYgbnJvdyhmYXJtX2hvdXNlaG9sZF9wYWlycykgPj0gMTApIHsKICBjYXQoIlxuIyMjIERpcmVjdCBDb250YWN0IEFuYWx5c2lzICMjI1xuIikKICAKICAjIFVzZSB0aGUgY29ycmVsYXRpb24gY2FsY3VsYXRlZCBlYXJsaWVyCiAgaWYoZXhpc3RzKCJwYWlyX2NvcnJlbGF0aW9uIikpIHsKICAgIGNhdCgiVXNpbmciLCBucm93KGZhcm1faG91c2Vob2xkX3BhaXJzKSwgImRpcmVjdGx5IGxpbmtlZCBmYXJtLWhvdXNlaG9sZCBwYWlycy5cbiIpCiAgICAKICAgICMgU3RvcmUgcmVzdWx0cyBmb3IgY29tcGFyaXNvbgogICAgY29tbXVuaXR5X3Jlc3VsdHNbWyJEaXJlY3QgQ29udGFjdCJdXSA8LSBsaXN0KAogICAgICBuX3BhaXJzID0gbnJvdyhmYXJtX2hvdXNlaG9sZF9wYWlycyksCiAgICAgIGNvcnJlbGF0aW9uID0gcGFpcl9jb3JyZWxhdGlvbiRlc3RpbWF0ZSwKICAgICAgcF92YWx1ZSA9IHBhaXJfY29ycmVsYXRpb24kcC52YWx1ZQogICAgKQogIH0KfQoKIyBDcmVhdGUgYSBzdW1tYXJ5IHRhYmxlIG9mIHJlc3VsdHMgYWNyb3NzIGRpZmZlcmVudCBkZWZpbml0aW9ucwppZihsZW5ndGgoY29tbXVuaXR5X3Jlc3VsdHMpID4gMCkgewogIGNhdCgiXG4jIyMgQ29tcGFyYXRpdmUgQW5hbHlzaXMgQWNyb3NzIENvbW11bml0eSBEZWZpbml0aW9ucyAjIyNcbiIpCiAgCiAgcmVzdWx0c19kZiA8LSBkYXRhLmZyYW1lKAogICAgQ29tbXVuaXR5X0RlZmluaXRpb24gPSBuYW1lcyhjb21tdW5pdHlfcmVzdWx0cyksCiAgICBOX1VuaXRzID0gc2FwcGx5KGNvbW11bml0eV9yZXN1bHRzLCBmdW5jdGlvbih4KSBpZmVsc2UoaXMubnVsbCh4JG5fY29tbXVuaXRpZXMpLCB4JG5fcGFpcnMsIHgkbl9jb21tdW5pdGllcykpLAogICAgQ29ycmVsYXRpb24gPSBzYXBwbHkoY29tbXVuaXR5X3Jlc3VsdHMsIGZ1bmN0aW9uKHgpIHgkY29ycmVsYXRpb24pLAogICAgUF9WYWx1ZSA9IHNhcHBseShjb21tdW5pdHlfcmVzdWx0cywgZnVuY3Rpb24oeCkgeCRwX3ZhbHVlKSwKICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQogICkKICAKICAjIENyZWF0ZSB0aGUgU2lnbmlmaWNhbnQgY29sdW1uIGV4cGxpY2l0bHkKICByZXN1bHRzX2RmJFNpZ25pZmljYW50IDwtIGlmZWxzZShyZXN1bHRzX2RmJFBfVmFsdWUgPCAwLjA1LCAiWWVzIiwgIk5vIikKICAKICAjIERpc3BsYXkgdGFibGUKICByZXN1bHRzX2RmICU+JQogICAgbXV0YXRlKAogICAgICBDb3JyZWxhdGlvbiA9IHJvdW5kKENvcnJlbGF0aW9uLCAzKSwKICAgICAgUF9WYWx1ZSA9IHJvdW5kKFBfVmFsdWUsIDMpCiAgICApICU+JQogICAga2FibGUoY2FwdGlvbiA9ICJDb21wYXJpc29uIG9mIEZhcm0tSG91c2Vob2xkIEFudGliaW90aWMgVXNlIENvcnJlbGF0aW9uIEFjcm9zcyBEaWZmZXJlbnQgQ29tbXVuaXR5IERlZmluaXRpb25zIiwKICAgICAgICAgIGNvbC5uYW1lcyA9IGMoIkNvbW11bml0eSBEZWZpbml0aW9uIiwgIk51bWJlciBvZiBVbml0cyIsIAogICAgICAgICAgICAgICAgICAgICAgICJDb3JyZWxhdGlvbiIsICJQLVZhbHVlIiwgIlNpZ25pZmljYW50IikpICU+JQogICAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkKICAKICAjIFZpc3VhbGl6ZSBjb21wYXJpc29uCiAgY29tcGFyaXNvbl9wbG90IDwtIGdncGxvdChyZXN1bHRzX2RmLCBhZXMoeCA9IENvbW11bml0eV9EZWZpbml0aW9uLCB5ID0gQ29ycmVsYXRpb24sIGZpbGwgPSBTaWduaWZpY2FudCkpICsKICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc3ByaW50ZigiJS4zZiIsIENvcnJlbGF0aW9uKSksIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDMuNSkgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiZ3JheTUwIikgKwogICAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKG1pbihtaW4ocmVzdWx0c19kZiRDb3JyZWxhdGlvbikgLSAwLjEsIC0wLjEpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChtYXgocmVzdWx0c19kZiRDb3JyZWxhdGlvbikgKyAwLjEsIDAuMSkpKSArCiAgICBsYWJzKHRpdGxlID0gIkNvbXBhcmlzb24gb2YgQ29ycmVsYXRpb24gQ29lZmZpY2llbnRzIEFjcm9zcyBDb21tdW5pdHkgRGVmaW5pdGlvbnMiLAogICAgICAgICBzdWJ0aXRsZSA9ICJUZXN0aW5nIHRoZSByb2J1c3RuZXNzIG9mIGNvbW11bml0eS1sZXZlbCBpc29tb3JwaGlzbSIsCiAgICAgICAgIHggPSAiQ29tbXVuaXR5IERlZmluaXRpb24iLAogICAgICAgICB5ID0gIkNvcnJlbGF0aW9uIENvZWZmaWNpZW50IiwKICAgICAgICAgZmlsbCA9ICJTdGF0aXN0aWNhbGx5XG5TaWduaWZpY2FudCIpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIk5vIiA9ICJncmF5NzAiLCAiWWVzIiA9ICJzdGVlbGJsdWUiKSkgKwogICAgdGhlbWVfbWluaW1hbCgpCiAgCiAgcHJpbnQoY29tcGFyaXNvbl9wbG90KQp9CmBgYAo=