Install/Load PackAges


# Load the packages needed for data cleaning, analysis, and visualization
library(tidyverse) # Core data wrangling and plotting tools (dplyr, ggplot2, etc.)
library(janitor) # Helpful tools for cleaning data and summarizing missingness
library(psych) # Descriptive statistics and scale-related functions
library(patchwork) # Combine multiple ggplots into one figure
library(naniar)  # Missing data summaries and visualization

library(stringr) # cleaning messy text data
library(forcats) # working with categorical variables

library(purrr) # doing things repeatedly without loops
library(zipcodeR) # turn zip codes into locations
library(maps) # draw the U.S. map

library(Hmisc) # for correlations and significance tests

Load the dataset

# Set working directory
setwd("/Users/maya/Desktop")

# Read the CSV (prevents unwanted factor conversion)
df <- read.csv("MKTG 4450.csv")
head(df)
names(df)
 [1] "Start.Date"               "EndDate"                  "Status"                  
 [4] "IPAddress"                "Progress"                 "Duration..in.seconds."   
 [7] "Finished"                 "RecordedDate"             "ResponseId"              
[10] "UserLanguage"             "purchase.intention"       "brand.attitude_NPS_GROUP"
[13] "brand.attitude"           "seller.trust"             "fairness_1"              
[16] "fairness_2"               "quality.perception"       "perceived.benefits"      
[19] "seller.control"           "Attention.check"          "Year.of.Birth"           
[22] "EDU"                      "Ethnicity"                "Ethnicity1"              
[25] "Ethnicity2"               "Ethnicity3"               "Ethnicity4"              
[28] "Ethnicity5"               "Ethnicity6"               "Ethnicity7"              
[31] "Gender"                   "Income"                   "Zip.code"                
[34] "open.comments"            "Condition"                "IV1_price_format"        
[37] "IV2_Surcharge_type"      
# Check variable names (the name of each column in your cleaned excel dataset)
names(df)
 [1] "Start.Date"               "EndDate"                  "Status"                  
 [4] "IPAddress"                "Progress"                 "Duration..in.seconds."   
 [7] "Finished"                 "RecordedDate"             "ResponseId"              
[10] "UserLanguage"             "purchase.intention"       "brand.attitude_NPS_GROUP"
[13] "brand.attitude"           "seller.trust"             "fairness_1"              
[16] "fairness_2"               "quality.perception"       "perceived.benefits"      
[19] "seller.control"           "Attention.check"          "Year.of.Birth"           
[22] "EDU"                      "Ethnicity"                "Ethnicity1"              
[25] "Ethnicity2"               "Ethnicity3"               "Ethnicity4"              
[28] "Ethnicity5"               "Ethnicity6"               "Ethnicity7"              
[31] "Gender"                   "Income"                   "Zip.code"                
[34] "open.comments"            "Condition"                "IV1_price_format"        
[37] "IV2_Surcharge_type"      

Prepare the data

Check for missing values (nice to better understand the data, not necessary since we’ve cleaned up the dataset)

# Missing data overview
colSums(is.na(df)) # Count how many missing values for each variable
              Start.Date                  EndDate                   Status 
                       0                        0                        0 
               IPAddress                 Progress    Duration..in.seconds. 
                       0                        0                        0 
                Finished             RecordedDate               ResponseId 
                       0                        0                        0 
            UserLanguage       purchase.intention brand.attitude_NPS_GROUP 
                       0                        0                        0 
          brand.attitude             seller.trust               fairness_1 
                       0                        0                        0 
              fairness_2       quality.perception       perceived.benefits 
                       0                        0                        0 
          seller.control          Attention.check            Year.of.Birth 
                       0                        0                        0 
                     EDU                Ethnicity               Ethnicity1 
                       0                        0                        0 
              Ethnicity2               Ethnicity3               Ethnicity4 
                       0                        0                        0 
              Ethnicity5               Ethnicity6               Ethnicity7 
                       0                        0                        0 
                  Gender                   Income                 Zip.code 
                       0                        0                        0 
           open.comments                Condition         IV1_price_format 
                      12                        0                        0 
      IV2_Surcharge_type 
                       0 
miss_var_summary(df) # A cleaner summary of missing values by variable

Recorde variaboes, if necessary

# fairness_1 and fairness_2 are supposed to measure the same idea,
# but fairness_2 is worded/scaled in the opposite direction.
# fairness_1: 1 = very unfairly, 7 = very fairly; fairness_2: 1 = extremely fairly, 7= extremely unfairly; This is why we need to reverse code fairness_2 to make the scale consistent with fairness_1
df$fairness_2_reverse <- 8 - df$fairness_2
df$fairness <- (df$fairness_1 + df$fairness_2_reverse)/2 # Create a composite fairness score by averaging the two fairness items

# Age: We measured year of birth, and we want to turn it into participants' age for easier interpretation
df$Year.of.Birth <- as.numeric(df$Year.of.Birth) # Convert Year.of.Birth to numeric in case it was imported as text
df$Age <- 2026 - df$Year.of.Birth

Prepare variables

Goal: Make sure your IVs are categorical and DVs are numerical (the most common type of DVs; for linear regression) or categorical (for chi square test or logistic regression)

# Make sure IVs are categorical factors. as.factor() tells R that these are categorical variables
df$IV1_price_format <- as.factor(df$IV1_price_format) # Categorical
df$IV2_surcharge_type <- as.factor(df$IV2_surcharge_type) # Categorical
# Make sure (most of the) DVs and covariates are numerical values
#DVs
df$purchase.intention <- as.numeric(df$purchase.intention) # Numeric
df$brand.attitude_NPS_GROUP <- as.factor(df$brand.attitude_NPS_GROUP) # Categorical
df$brand.attitude <- as.numeric(df$brand.attitude) # Numeric
df$seller.trust <- as.numeric(df$seller.trust) # Numeric
df$fairness <- as.numeric(df$fairness) # Numeric

# Covariates
df$quality.perception <- as.numeric(df$quality.perception) # Numeric
df$perceived.benefits <- as.numeric(df$perceived.benefits) # Numeric
df$seller.control <- as.numeric(df$seller.control) # Numeric
df$surcharge.novelty <- as.numeric(df$surcharge.novelty) # Numeric

Assess the sample

a) Explore demographics

Goal: To understand who is in our data (their demographics)

# Make sure Age is numeric
df$Age <- as.numeric(df$Age)

# Age: summarize # of valid cases, mean, SD, min, median, and max (na.rm = TRUE: NAs are removed before calculation)
df %>%
  summarise(
    n_nonmissing = sum(!is.na(Age)),
    mean = mean(Age, na.rm = TRUE),
    sd = sd(Age, na.rm = TRUE),
    min = min(Age, na.rm = TRUE),
    median = median(Age, na.rm = TRUE),
    max = max(Age, na.rm = TRUE)
  )

# Age histogram
ggplot(df, aes(x = Age)) +
  geom_histogram(
    binwidth = 5,       # Each bar covers a 5-year range
    fill = "#7A0019",   # Bar color
    color = "white"    # White border around bars
  ) +
  labs(
    title = "Age Distribution",
    subtitle = "Sample Characteristics",
    x = "Age (years)",
    y = "Number of Participants"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank()
  )
# Gender distribution: frequency table and proportions (since Gender is a categorical variable)
df %>%
  count(Gender) %>%
  mutate(prop = n / sum(n))

# Bar chart for gender counts
df %>%
  count(Gender) %>%
  ggplot(aes(x = fct_reorder(Gender, n), y = n)) +
  geom_col() +
  coord_flip() +
  labs(
    title = "Gender",
    x = NULL,
    y = "Count"
  ) +
  theme_minimal()
# Education distribution: counts and proportions
df %>%
  count(EDU) %>%
  mutate(prop = n / sum(n)) %>%
  arrange(desc(n))

# Bar chart for education counts
df %>%
  count(EDU) %>%
  ggplot(aes(x = fct_reorder(EDU, n), y = n)) +
  geom_col() +
  coord_flip() +
  labs(
    title = "Education",
    x = NULL,
    y = "Count"
  ) +
  theme_minimal()
# Income distribution: counts and percentages
df %>%
  count(Income) %>%
  mutate(percent = round(100 * n / sum(n), 1))

# Bar chart of income categories
df %>%
  count(Income) %>%
  ggplot(aes(x = Income, y = n)) +
  geom_col() +
  coord_flip() +
  labs(
    title = "Income",
    x = NULL,
    y = "Count"
  ) +
  theme_minimal()
# Zip code: count how many zip codes are present and the number of unique zip codes 
df %>%
  summarise(
    n_zip_nonmissing = sum(!is.na(Zip.code) & Zip.code != ""),
    n_unique_zip = n_distinct(Zip.code[!is.na(Zip.code) & Zip.code != ""])
  )

# Show the 15 most common zip codes in the dataset
df %>%
  count(Zip.code, sort = TRUE) %>%
  filter(!is.na(Zip.code), Zip.code != "") %>%
  slice_head(n = 15)
# Plot zip codes
# 1) Clean zip codes
zip_counts <- df %>%
  filter(!is.na(Zip.code), Zip.code != "") %>%   # Keep only non-missing zip codes
  mutate(
    Zip.code = str_extract(as.character(Zip.code), "\\d{5}"),  # Exact 5-digit zip code
    Zip.code = str_pad(Zip.code, width = 5, side = "left", pad = "0") # Add leading zeros if needed
  ) %>% 
  filter(!is.na(Zip.code)) %>%
  count(Zip.code, sort = TRUE) # Count participants per zip code

# 2) Look up zip metadata (lat/lng) with reverse_zipcode()
zip_lookup <- map_dfr(zip_counts$Zip.code, ~{
  out <- tryCatch(
    reverse_zipcode(.x),
    error = function(e) NULL
  )
  out
})

# 3) Keep only the columns needed for mapping
zip_lookup <- zip_lookup %>%
  select(zipcode, lat, lng, state, major_city)

# 4) Merge counts with coordinates
df_map <- zip_counts %>%
  left_join(zip_lookup, by = c("Zip.code" = "zipcode"))

# 5) Optional: check zips that did not match
df_map %>%
  filter(is.na(lat) | is.na(lng))

# 6) US base map
us_map <- map_data("state")

# 7) Plot
ggplot() +
  geom_polygon(
    data = us_map,
    aes(x = long, y = lat, group = group),
    fill = "gray95",
    color = "white",
    linewidth = 0.2
  ) +
  geom_point(
    data = df_map,
    aes(x = lng, y = lat, size = n, color = n),
    alpha = 0.75
  ) +
  scale_size(range = c(2, 8)) +
  scale_color_viridis_c() +
  coord_fixed(1.3) +
  labs(
    title = "Participant ZIP Codes Across the United States",
    x = NULL,
    y = NULL,
    size = "Count",
    color = "Count"
  ) +
  theme_minimal()

b) Distributions of covariates

Goal: To understand who is in our data (their consumption tendencies)

# Overall descriptives for covariates
covariates <- df %>% # Create a new data frame with only four covariate variables
  select(
    quality.perception,
    perceived.benefits,
    seller.control,
    surcharge.novelty,
  )

# Get descriptive stats for these covariates
describe(covariates)

b) Distributions of covariates (Visualizing the distributions)

Goal: Plot histograms and explore variables individually

# Histogram: quality.perception
p6 <- ggplot(df, aes(x = quality.perception)) + # initiate ggplot using dataset "df" and use quality.perception as the x-axis
  geom_histogram(
    binwidth = 1,    # each bar represents a width of 1 unit (this fits interval/ratio scales)
    boundary = 0.5,  # make bars centered on integers
    fill = "#7A0019", # set bar fill color
    color = "white"   # set border color of bars
  ) +
  geom_vline(  # add a vertical line
    xintercept = mean(df$quality.perception, na.rm = TRUE), # position line at the mean
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(
    title = "Distribution of Quality Perception", # add labels and titles
    subtitle = "Dashed line = Mean",
    x = "PQuality Perception (1–7 scale)",
    y = "Number of Participants"
  ) +
  theme_minimal(base_size = 14) + # apply a clean minimal theme with base front size 14
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"), # center and bold the title
    plot.subtitle = element_text(hjust = 0.5), # center the subtitle
    panel.grid.major.x = element_blank(), # remove vertical major grid lines
    panel.grid.minor = element_blank() # remove all minor grid lines
  )

# Histogram: perceived benefits
p7 <- ggplot(df, aes(x = perceived.benefits)) +
  geom_histogram(
    binwidth = 1, 
    boundary = 0.5,
    fill = "#7A0019",
    color = "white"
  ) +
  geom_vline(
    xintercept = mean(df$perceived.benefits, na.rm = TRUE),
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(
    title = "Distribution of Perceived Benefits",
    subtitle = "Dashed line = Mean",
    x = "Perceived benefits (1–5 scale)",
    y = "Number of Participants"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank()
  )

# Histogram: seller control
p8 <- ggplot(df, aes(x = seller.control)) +
  geom_histogram(
    binwidth = 1, 
    boundary = 0.5,
    fill = "#7A0019",
    color = "white"
  ) +
  geom_vline(
    xintercept = mean(df$seller.control, na.rm = TRUE),
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(
    title = "Distribution of Seller Control",
    subtitle = "Dashed line = Mean",
    x = "Seller Control (1–7 scale)",
    y = "Number of Participants"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank()
  )

# Histogram: surcharge novelty
p9 <- ggplot(df, aes(x = surcharge.novelty)) +
  geom_histogram(
    binwidth = 1, 
    boundary = 0.5,
    fill = "#7A0019",
    color = "white"
  ) +
  geom_vline(
    xintercept = mean(df$surcharge.novelty, na.rm = TRUE),
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(
    title = "Distribution of Surcharge Novelty",
    subtitle = "Dashed line = Mean",
    x = "Surcharge Novelty (1–7 scale)",
    y = "Number of Participants"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank()
  )

p6 + p7 + p8 + p9 # Option#1: Combine the four plots into one figure
p6 # Option#2: Plot the four plots on separate pages
p7
p7
p9

Assess randomization

Overall descriptive stats

Goal: Check if the randomization is successful (the number of participants should be largely the same across conditions)

# Count number of participants in each 2 x 2 experimental cell
df %>%
  count(IV1_price_format, IV2_surcharge_type)

Variable distributions

# Overall descriptives for DVs
DVs <- df %>%
  select(
    purchase.intention,
    brand.attitude,
    seller.trust,
    fairness
  )

describe(DVs)

Distributions of DVs (Visualizing the distributions)

Goal: Plot histograms and explore variables individually

# Histogram: purchase intention
p1 <- ggplot(df, aes(x = purchase.intention)) +
  geom_histogram(
    binwidth = 1, 
    boundary = 0.5,
    fill = "#7A0019",
    color = "white"
  ) +
  geom_vline(
    xintercept = mean(df$purchase.intention, na.rm = TRUE),
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(
    title = "Distribution of Purchase Intention",
    subtitle = "Dashed line = Mean",
    x = "Purchase Intention (1–7 scale)",
    y = "Number of Participants"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank()
  )

# Histogram: brand attitude
p2 <- ggplot(df, aes(x = brand.attitude)) +
  geom_histogram(
    binwidth = 1, 
    boundary = 0.5,
    fill = "#7A0019",
    color = "white"
  ) +
  geom_vline(
    xintercept = mean(df$brand.attitude, na.rm = TRUE),
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(
    title = "Distribution of Brand Attitude",
    subtitle = "Dashed line = Mean",
    x = "Brand Attitude (1–10 scale)",
    y = "Number of Participants"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank()
  )

# Bar chart, brand attitude (NPS)
p3 <- ggplot(df, aes(x = brand.attitude_NPS_GROUP)) +
  geom_bar(fill = "#7A0019") +
  labs(
    title = "Distribution of NPS Groups",
    x = "NPS Group",
    y = "Number of Participants"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank()
  )

# Histogram: seller trust
p4 <- ggplot(df, aes(x = seller.trust)) +
  geom_histogram(
    binwidth = 1, 
    boundary = 0.5,
    fill = "#7A0019",
    color = "white"
  ) +
  geom_vline(
    xintercept = mean(df$seller.trust, na.rm = TRUE),
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(
    title = "Distribution of Seller Trust",
    subtitle = "Dashed line = Mean",
    x = "Seller trust (1–7 scale)",
    y = "Number of Participants"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank()
  )

# Histogram: fairness
p5 <- ggplot(df, aes(x = fairness)) +
  geom_histogram(
    binwidth = 1, 
    boundary = 0.5,
    fill = "#7A0019",
    color = "white"
  ) +
  geom_vline(
    xintercept = mean(df$fairness, na.rm = TRUE),
    linetype = "dashed",
    linewidth = 1
  ) +
  labs(
    title = "Distribution of Fairness",
    subtitle = "Dashed line = Mean",
    x = "Fairness (1–7 scale)",
    y = "Number of Participants"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank()
  )

p1 
p2 
p3 
p4 
p5

Variable relationships

Scatterplots for relationships among DVs

Goal: Visually assess many variable relationships at once

# Plot 1: brand attitude by purchase intention
ggplot(df, aes(x = brand.attitude, y = purchase.intention)) + # aes(...) = aesthetics (tell RStudio what goes on axes). Here we are plotting brand attitude on the x-axis and purchase intention on the y-axis
  geom_smooth(method = "lm", se = TRUE) + # We are using a linear regression model ("lm") to draw a best-fitting line between brand attitude and purchase intention 
  geom_jitter(width = 0.2, height = 0.2) + # this function helps us plot each participant as a dot
  theme_minimal() + # Make the plot cleaner and easier to read
  labs(title = "Brand Attitude and Purchase Intention", 
       x = "Brand Attitude", y = "Purchase Intention") # Add labels to the figure, x-axis, and y-axis

# Plot 2: seller trust by purchase intention
ggplot(df, aes(x = seller.trust, y = purchase.intention)) +
  geom_smooth(method = "lm", se = TRUE) +
  geom_jitter(width = 0.2, height = 0.2) +
  theme_minimal() +
  labs(title = "Seller Trust and Purchase Intention",
       x = "Seller Trust", y = "Purchase Intention")

# Plot 3: fairness by purchase intention
ggplot(df, aes(x = fairness, y = purchase.intention)) +
  geom_smooth(method = "lm", se = TRUE) +
  geom_jitter(width = 0.2, height = 0.2) +
  theme_minimal() +
  labs(title = "Fairness and Purchase Intention",
       x = "Perceived Fairness", y = "Purchase Intention")

# Plot 4: seller trust by brand attitude
ggplot(df, aes(x = seller.trust, y = brand.attitude)) +
  geom_smooth(method = "lm", se = TRUE) +
  geom_jitter(width = 0.2, height = 0.2) +
  theme_minimal() +
  labs(title = "Seller Trust and Brand Attitude",
       x = "Seller Trust", y = "Brand Attitude")

# Plot 5: fairness by brand attitude
ggplot(df, aes(x = fairness, y = brand.attitude)) +
  geom_smooth(method = "lm", se = TRUE) +
  geom_jitter(width = 0.2, height = 0.2) +
  theme_minimal() +
  labs(title = "Fairness and Brand Attitude",
       x = "Perceived Fairness", y = "Brand Attitude")

# Plot 6: fairness by seller trust
ggplot(df, aes(x = fairness, y = seller.trust)) +
  geom_smooth(method = "lm", se = TRUE) +
  geom_jitter(width = 0.2, height = 0.2) +
  theme_minimal() +
  labs(title = "Fairness and Seller Trust",
       x = "Perceived Fairness", y = "Seller Trust")

Correlation matrix

# Select the variables to include in the correlation matrix
corr_vars <- df%>%
  select(
    purchase.intention,
    brand.attitude,
    seller.trust,
    fairness,
    quality.perception,
    perceived.benefits,
    seller.control,
    surcharge.novelty
  )

# Compute correlations and p-values
cor_results <- rcorr(as.matrix(corr_vars))

# Correlation matrix
cor_matrix <- cor_results$r

# P-value matrix
p_matrix <- cor_results$P

# View correlation matrix
round(cor_matrix, 2)
# Convert correlation matrix to long format
cor_df <- as.data.frame(cor_matrix) %>%
  rownames_to_column("var1") %>%
  pivot_longer(-var1, names_to = "var2", values_to = "correlation")

# Convert p-value matrix to long format
p_df <- as.data.frame(p_matrix) %>%
  rownames_to_column("var1") %>%
  pivot_longer(-var1, names_to = "var2", values_to = "p_value")

# Merge correlations and p-values
cor_df <- cor_df %>%
  left_join(p_df, by = c("var1", "var2")) %>%
  mutate(
    sig = case_when(
      p_value < .001 ~ "***",
      p_value < .01  ~ "**",
      p_value < .05  ~ "*",
      TRUE ~ ""
    )
  )

# Plot the correlation matrix
ggplot(cor_df, aes(x = var1, y = var2)) +
  geom_point(aes(size = abs(correlation), color = correlation)) +
  geom_text(aes(label = paste0(round(correlation, 2), sig)), size = 3) +
  scale_size(range = c(2, 8)) +
  scale_color_gradient2(
    low = "#B2182B",
    mid = "white",
    high = "#2166AC",
    midpoint = 0
  ) +
  coord_equal() +
  labs(
    title = "Correlation Matrix (with Significance)",
    x = "",
    y = "",
    color = "Correlation",
    size = "|r|"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    panel.grid = element_blank(),
    plot.title = element_text(hjust = 0.5, face = "bold")
  )
# Your R code here
summary(cars)
plot(cars)
LS0tCnRpdGxlOiAiUHJpY2luZyBwcm9qZWN0IGRlbW87IGRhdGEgZXhwbG9yYXRpb247IFNwcmluZyAyMDI2IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIAoKIyBJbnN0YWxsL0xvYWQgUGFja0FnZXMKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgCgpgYGB7cn0KCiMgTG9hZCB0aGUgcGFja2FnZXMgbmVlZGVkIGZvciBkYXRhIGNsZWFuaW5nLCBhbmFseXNpcywgYW5kIHZpc3VhbGl6YXRpb24KbGlicmFyeSh0aWR5dmVyc2UpICMgQ29yZSBkYXRhIHdyYW5nbGluZyBhbmQgcGxvdHRpbmcgdG9vbHMgKGRwbHlyLCBnZ3Bsb3QyLCBldGMuKQpsaWJyYXJ5KGphbml0b3IpICMgSGVscGZ1bCB0b29scyBmb3IgY2xlYW5pbmcgZGF0YSBhbmQgc3VtbWFyaXppbmcgbWlzc2luZ25lc3MKbGlicmFyeShwc3ljaCkgIyBEZXNjcmlwdGl2ZSBzdGF0aXN0aWNzIGFuZCBzY2FsZS1yZWxhdGVkIGZ1bmN0aW9ucwpsaWJyYXJ5KHBhdGNod29yaykgIyBDb21iaW5lIG11bHRpcGxlIGdncGxvdHMgaW50byBvbmUgZmlndXJlCmxpYnJhcnkobmFuaWFyKSAgIyBNaXNzaW5nIGRhdGEgc3VtbWFyaWVzIGFuZCB2aXN1YWxpemF0aW9uCgpsaWJyYXJ5KHN0cmluZ3IpICMgY2xlYW5pbmcgbWVzc3kgdGV4dCBkYXRhCmxpYnJhcnkoZm9yY2F0cykgIyB3b3JraW5nIHdpdGggY2F0ZWdvcmljYWwgdmFyaWFibGVzCgpsaWJyYXJ5KHB1cnJyKSAjIGRvaW5nIHRoaW5ncyByZXBlYXRlZGx5IHdpdGhvdXQgbG9vcHMKbGlicmFyeSh6aXBjb2RlUikgIyB0dXJuIHppcCBjb2RlcyBpbnRvIGxvY2F0aW9ucwpsaWJyYXJ5KG1hcHMpICMgZHJhdyB0aGUgVS5TLiBtYXAKCmxpYnJhcnkoSG1pc2MpICMgZm9yIGNvcnJlbGF0aW9ucyBhbmQgc2lnbmlmaWNhbmNlIHRlc3RzCmBgYAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAKCiMgTG9hZCB0aGUgZGF0YXNldAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAKCmBgYHtyfQojIFNldCB3b3JraW5nIGRpcmVjdG9yeQpzZXR3ZCgiL1VzZXJzL21heWEvRGVza3RvcCIpCgojIFJlYWQgdGhlIENTViAocHJldmVudHMgdW53YW50ZWQgZmFjdG9yIGNvbnZlcnNpb24pCmRmIDwtIHJlYWQuY3N2KCJNS1RHIDQ0NTAuY3N2IikKaGVhZChkZikKbmFtZXMoZGYpCmBgYAoKYGBge3J9CiMgQ2hlY2sgdmFyaWFibGUgbmFtZXMgKHRoZSBuYW1lIG9mIGVhY2ggY29sdW1uIGluIHlvdXIgY2xlYW5lZCBleGNlbCBkYXRhc2V0KQpuYW1lcyhkZikKYGBgCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIAoKIyBQcmVwYXJlIHRoZSBkYXRhCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIAoKIyBDaGVjayBmb3IgbWlzc2luZyB2YWx1ZXMgKG5pY2UgdG8gYmV0dGVyIHVuZGVyc3RhbmQgdGhlIGRhdGEsIG5vdCBuZWNlc3Nhcnkgc2luY2Ugd2UndmUgY2xlYW5lZCB1cCB0aGUgZGF0YXNldCkKCmBgYHtyfQojIE1pc3NpbmcgZGF0YSBvdmVydmlldwpjb2xTdW1zKGlzLm5hKGRmKSkgIyBDb3VudCBob3cgbWFueSBtaXNzaW5nIHZhbHVlcyBmb3IgZWFjaCB2YXJpYWJsZQptaXNzX3Zhcl9zdW1tYXJ5KGRmKSAjIEEgY2xlYW5lciBzdW1tYXJ5IG9mIG1pc3NpbmcgdmFsdWVzIGJ5IHZhcmlhYmxlCmBgYAoKIyBSZWNvcmRlIHZhcmlhYm9lcywgaWYgbmVjZXNzYXJ5CgpgYGB7cn0KIyBmYWlybmVzc18xIGFuZCBmYWlybmVzc18yIGFyZSBzdXBwb3NlZCB0byBtZWFzdXJlIHRoZSBzYW1lIGlkZWEsCiMgYnV0IGZhaXJuZXNzXzIgaXMgd29yZGVkL3NjYWxlZCBpbiB0aGUgb3Bwb3NpdGUgZGlyZWN0aW9uLgojIGZhaXJuZXNzXzE6IDEgPSB2ZXJ5IHVuZmFpcmx5LCA3ID0gdmVyeSBmYWlybHk7IGZhaXJuZXNzXzI6IDEgPSBleHRyZW1lbHkgZmFpcmx5LCA3PSBleHRyZW1lbHkgdW5mYWlybHk7IFRoaXMgaXMgd2h5IHdlIG5lZWQgdG8gcmV2ZXJzZSBjb2RlIGZhaXJuZXNzXzIgdG8gbWFrZSB0aGUgc2NhbGUgY29uc2lzdGVudCB3aXRoIGZhaXJuZXNzXzEKZGYkZmFpcm5lc3NfMl9yZXZlcnNlIDwtIDggLSBkZiRmYWlybmVzc18yCmRmJGZhaXJuZXNzIDwtIChkZiRmYWlybmVzc18xICsgZGYkZmFpcm5lc3NfMl9yZXZlcnNlKS8yICMgQ3JlYXRlIGEgY29tcG9zaXRlIGZhaXJuZXNzIHNjb3JlIGJ5IGF2ZXJhZ2luZyB0aGUgdHdvIGZhaXJuZXNzIGl0ZW1zCgojIEFnZTogV2UgbWVhc3VyZWQgeWVhciBvZiBiaXJ0aCwgYW5kIHdlIHdhbnQgdG8gdHVybiBpdCBpbnRvIHBhcnRpY2lwYW50cycgYWdlIGZvciBlYXNpZXIgaW50ZXJwcmV0YXRpb24KZGYkWWVhci5vZi5CaXJ0aCA8LSBhcy5udW1lcmljKGRmJFllYXIub2YuQmlydGgpICMgQ29udmVydCBZZWFyLm9mLkJpcnRoIHRvIG51bWVyaWMgaW4gY2FzZSBpdCB3YXMgaW1wb3J0ZWQgYXMgdGV4dApkZiRBZ2UgPC0gMjAyNiAtIGRmJFllYXIub2YuQmlydGgKYGBgCgojIFByZXBhcmUgdmFyaWFibGVzCgojIEdvYWw6IE1ha2Ugc3VyZSB5b3VyIElWcyBhcmUgY2F0ZWdvcmljYWwgYW5kIERWcyBhcmUgbnVtZXJpY2FsICh0aGUgbW9zdCBjb21tb24gdHlwZSBvZiBEVnM7IGZvciBsaW5lYXIgcmVncmVzc2lvbikgb3IgY2F0ZWdvcmljYWwgKGZvciBjaGkgc3F1YXJlIHRlc3Qgb3IgbG9naXN0aWMgcmVncmVzc2lvbikKCmBgYHtyfQojIE1ha2Ugc3VyZSBJVnMgYXJlIGNhdGVnb3JpY2FsIGZhY3RvcnMuIGFzLmZhY3RvcigpIHRlbGxzIFIgdGhhdCB0aGVzZSBhcmUgY2F0ZWdvcmljYWwgdmFyaWFibGVzCmRmJElWMV9wcmljZV9mb3JtYXQgPC0gYXMuZmFjdG9yKGRmJElWMV9wcmljZV9mb3JtYXQpICMgQ2F0ZWdvcmljYWwKZGYkSVYyX3N1cmNoYXJnZV90eXBlIDwtIGFzLmZhY3RvcihkZiRJVjJfc3VyY2hhcmdlX3R5cGUpICMgQ2F0ZWdvcmljYWwKYGBgCgpgYGB7cn0KIyBNYWtlIHN1cmUgKG1vc3Qgb2YgdGhlKSBEVnMgYW5kIGNvdmFyaWF0ZXMgYXJlIG51bWVyaWNhbCB2YWx1ZXMKI0RWcwpkZiRwdXJjaGFzZS5pbnRlbnRpb24gPC0gYXMubnVtZXJpYyhkZiRwdXJjaGFzZS5pbnRlbnRpb24pICMgTnVtZXJpYwpkZiRicmFuZC5hdHRpdHVkZV9OUFNfR1JPVVAgPC0gYXMuZmFjdG9yKGRmJGJyYW5kLmF0dGl0dWRlX05QU19HUk9VUCkgIyBDYXRlZ29yaWNhbApkZiRicmFuZC5hdHRpdHVkZSA8LSBhcy5udW1lcmljKGRmJGJyYW5kLmF0dGl0dWRlKSAjIE51bWVyaWMKZGYkc2VsbGVyLnRydXN0IDwtIGFzLm51bWVyaWMoZGYkc2VsbGVyLnRydXN0KSAjIE51bWVyaWMKZGYkZmFpcm5lc3MgPC0gYXMubnVtZXJpYyhkZiRmYWlybmVzcykgIyBOdW1lcmljCgojIENvdmFyaWF0ZXMKZGYkcXVhbGl0eS5wZXJjZXB0aW9uIDwtIGFzLm51bWVyaWMoZGYkcXVhbGl0eS5wZXJjZXB0aW9uKSAjIE51bWVyaWMKZGYkcGVyY2VpdmVkLmJlbmVmaXRzIDwtIGFzLm51bWVyaWMoZGYkcGVyY2VpdmVkLmJlbmVmaXRzKSAjIE51bWVyaWMKZGYkc2VsbGVyLmNvbnRyb2wgPC0gYXMubnVtZXJpYyhkZiRzZWxsZXIuY29udHJvbCkgIyBOdW1lcmljCmRmJHN1cmNoYXJnZS5ub3ZlbHR5IDwtIGFzLm51bWVyaWMoZGYkc3VyY2hhcmdlLm5vdmVsdHkpICMgTnVtZXJpYwpgYGAKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgCgojIEFzc2VzcyB0aGUgc2FtcGxlCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIAoKIyBhKSBFeHBsb3JlIGRlbW9ncmFwaGljcwoKIyBHb2FsOiBUbyB1bmRlcnN0YW5kIHdobyBpcyBpbiBvdXIgZGF0YSAodGhlaXIgZGVtb2dyYXBoaWNzKQoKYGBge3J9CiMgTWFrZSBzdXJlIEFnZSBpcyBudW1lcmljCmRmJEFnZSA8LSBhcy5udW1lcmljKGRmJEFnZSkKCiMgQWdlOiBzdW1tYXJpemUgIyBvZiB2YWxpZCBjYXNlcywgbWVhbiwgU0QsIG1pbiwgbWVkaWFuLCBhbmQgbWF4IChuYS5ybSA9IFRSVUU6IE5BcyBhcmUgcmVtb3ZlZCBiZWZvcmUgY2FsY3VsYXRpb24pCmRmICU+JQogIHN1bW1hcmlzZSgKICAgIG5fbm9ubWlzc2luZyA9IHN1bSghaXMubmEoQWdlKSksCiAgICBtZWFuID0gbWVhbihBZ2UsIG5hLnJtID0gVFJVRSksCiAgICBzZCA9IHNkKEFnZSwgbmEucm0gPSBUUlVFKSwKICAgIG1pbiA9IG1pbihBZ2UsIG5hLnJtID0gVFJVRSksCiAgICBtZWRpYW4gPSBtZWRpYW4oQWdlLCBuYS5ybSA9IFRSVUUpLAogICAgbWF4ID0gbWF4KEFnZSwgbmEucm0gPSBUUlVFKQogICkKCiMgQWdlIGhpc3RvZ3JhbQpnZ3Bsb3QoZGYsIGFlcyh4ID0gQWdlKSkgKwogIGdlb21faGlzdG9ncmFtKAogICAgYmlud2lkdGggPSA1LCAgICAgICAjIEVhY2ggYmFyIGNvdmVycyBhIDUteWVhciByYW5nZQogICAgZmlsbCA9ICIjN0EwMDE5IiwgICAjIEJhciBjb2xvcgogICAgY29sb3IgPSAid2hpdGUiICAgICMgV2hpdGUgYm9yZGVyIGFyb3VuZCBiYXJzCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIkFnZSBEaXN0cmlidXRpb24iLAogICAgc3VidGl0bGUgPSAiU2FtcGxlIENoYXJhY3RlcmlzdGljcyIsCiAgICB4ID0gIkFnZSAoeWVhcnMpIiwKICAgIHkgPSAiTnVtYmVyIG9mIFBhcnRpY2lwYW50cyIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKYGBgCgpgYGB7cn0KIyBHZW5kZXIgZGlzdHJpYnV0aW9uOiBmcmVxdWVuY3kgdGFibGUgYW5kIHByb3BvcnRpb25zIChzaW5jZSBHZW5kZXIgaXMgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSkKZGYgJT4lCiAgY291bnQoR2VuZGVyKSAlPiUKICBtdXRhdGUocHJvcCA9IG4gLyBzdW0obikpCgojIEJhciBjaGFydCBmb3IgZ2VuZGVyIGNvdW50cwpkZiAlPiUKICBjb3VudChHZW5kZXIpICU+JQogIGdncGxvdChhZXMoeCA9IGZjdF9yZW9yZGVyKEdlbmRlciwgbiksIHkgPSBuKSkgKwogIGdlb21fY29sKCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIkdlbmRlciIsCiAgICB4ID0gTlVMTCwKICAgIHkgPSAiQ291bnQiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKYGBge3J9CiMgRWR1Y2F0aW9uIGRpc3RyaWJ1dGlvbjogY291bnRzIGFuZCBwcm9wb3J0aW9ucwpkZiAlPiUKICBjb3VudChFRFUpICU+JQogIG11dGF0ZShwcm9wID0gbiAvIHN1bShuKSkgJT4lCiAgYXJyYW5nZShkZXNjKG4pKQoKIyBCYXIgY2hhcnQgZm9yIGVkdWNhdGlvbiBjb3VudHMKZGYgJT4lCiAgY291bnQoRURVKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBmY3RfcmVvcmRlcihFRFUsIG4pLCB5ID0gbikpICsKICBnZW9tX2NvbCgpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJFZHVjYXRpb24iLAogICAgeCA9IE5VTEwsCiAgICB5ID0gIkNvdW50IgogICkgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKCmBgYHtyfQojIEluY29tZSBkaXN0cmlidXRpb246IGNvdW50cyBhbmQgcGVyY2VudGFnZXMKZGYgJT4lCiAgY291bnQoSW5jb21lKSAlPiUKICBtdXRhdGUocGVyY2VudCA9IHJvdW5kKDEwMCAqIG4gLyBzdW0obiksIDEpKQoKIyBCYXIgY2hhcnQgb2YgaW5jb21lIGNhdGVnb3JpZXMKZGYgJT4lCiAgY291bnQoSW5jb21lKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBJbmNvbWUsIHkgPSBuKSkgKwogIGdlb21fY29sKCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIkluY29tZSIsCiAgICB4ID0gTlVMTCwKICAgIHkgPSAiQ291bnQiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKYGBge3J9CiMgWmlwIGNvZGU6IGNvdW50IGhvdyBtYW55IHppcCBjb2RlcyBhcmUgcHJlc2VudCBhbmQgdGhlIG51bWJlciBvZiB1bmlxdWUgemlwIGNvZGVzIApkZiAlPiUKICBzdW1tYXJpc2UoCiAgICBuX3ppcF9ub25taXNzaW5nID0gc3VtKCFpcy5uYShaaXAuY29kZSkgJiBaaXAuY29kZSAhPSAiIiksCiAgICBuX3VuaXF1ZV96aXAgPSBuX2Rpc3RpbmN0KFppcC5jb2RlWyFpcy5uYShaaXAuY29kZSkgJiBaaXAuY29kZSAhPSAiIl0pCiAgKQoKIyBTaG93IHRoZSAxNSBtb3N0IGNvbW1vbiB6aXAgY29kZXMgaW4gdGhlIGRhdGFzZXQKZGYgJT4lCiAgY291bnQoWmlwLmNvZGUsIHNvcnQgPSBUUlVFKSAlPiUKICBmaWx0ZXIoIWlzLm5hKFppcC5jb2RlKSwgWmlwLmNvZGUgIT0gIiIpICU+JQogIHNsaWNlX2hlYWQobiA9IDE1KQpgYGAKCmBgYHtyfQojIFBsb3QgemlwIGNvZGVzCiMgMSkgQ2xlYW4gemlwIGNvZGVzCnppcF9jb3VudHMgPC0gZGYgJT4lCiAgZmlsdGVyKCFpcy5uYShaaXAuY29kZSksIFppcC5jb2RlICE9ICIiKSAlPiUgICAjIEtlZXAgb25seSBub24tbWlzc2luZyB6aXAgY29kZXMKICBtdXRhdGUoCiAgICBaaXAuY29kZSA9IHN0cl9leHRyYWN0KGFzLmNoYXJhY3RlcihaaXAuY29kZSksICJcXGR7NX0iKSwgICMgRXhhY3QgNS1kaWdpdCB6aXAgY29kZQogICAgWmlwLmNvZGUgPSBzdHJfcGFkKFppcC5jb2RlLCB3aWR0aCA9IDUsIHNpZGUgPSAibGVmdCIsIHBhZCA9ICIwIikgIyBBZGQgbGVhZGluZyB6ZXJvcyBpZiBuZWVkZWQKICApICU+JSAKICBmaWx0ZXIoIWlzLm5hKFppcC5jb2RlKSkgJT4lCiAgY291bnQoWmlwLmNvZGUsIHNvcnQgPSBUUlVFKSAjIENvdW50IHBhcnRpY2lwYW50cyBwZXIgemlwIGNvZGUKCiMgMikgTG9vayB1cCB6aXAgbWV0YWRhdGEgKGxhdC9sbmcpIHdpdGggcmV2ZXJzZV96aXBjb2RlKCkKemlwX2xvb2t1cCA8LSBtYXBfZGZyKHppcF9jb3VudHMkWmlwLmNvZGUsIH57CiAgb3V0IDwtIHRyeUNhdGNoKAogICAgcmV2ZXJzZV96aXBjb2RlKC54KSwKICAgIGVycm9yID0gZnVuY3Rpb24oZSkgTlVMTAogICkKICBvdXQKfSkKCiMgMykgS2VlcCBvbmx5IHRoZSBjb2x1bW5zIG5lZWRlZCBmb3IgbWFwcGluZwp6aXBfbG9va3VwIDwtIHppcF9sb29rdXAgJT4lCiAgc2VsZWN0KHppcGNvZGUsIGxhdCwgbG5nLCBzdGF0ZSwgbWFqb3JfY2l0eSkKCiMgNCkgTWVyZ2UgY291bnRzIHdpdGggY29vcmRpbmF0ZXMKZGZfbWFwIDwtIHppcF9jb3VudHMgJT4lCiAgbGVmdF9qb2luKHppcF9sb29rdXAsIGJ5ID0gYygiWmlwLmNvZGUiID0gInppcGNvZGUiKSkKCiMgNSkgT3B0aW9uYWw6IGNoZWNrIHppcHMgdGhhdCBkaWQgbm90IG1hdGNoCmRmX21hcCAlPiUKICBmaWx0ZXIoaXMubmEobGF0KSB8IGlzLm5hKGxuZykpCgojIDYpIFVTIGJhc2UgbWFwCnVzX21hcCA8LSBtYXBfZGF0YSgic3RhdGUiKQoKIyA3KSBQbG90CmdncGxvdCgpICsKICBnZW9tX3BvbHlnb24oCiAgICBkYXRhID0gdXNfbWFwLAogICAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwKICAgIGZpbGwgPSAiZ3JheTk1IiwKICAgIGNvbG9yID0gIndoaXRlIiwKICAgIGxpbmV3aWR0aCA9IDAuMgogICkgKwogIGdlb21fcG9pbnQoCiAgICBkYXRhID0gZGZfbWFwLAogICAgYWVzKHggPSBsbmcsIHkgPSBsYXQsIHNpemUgPSBuLCBjb2xvciA9IG4pLAogICAgYWxwaGEgPSAwLjc1CiAgKSArCiAgc2NhbGVfc2l6ZShyYW5nZSA9IGMoMiwgOCkpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzX2MoKSArCiAgY29vcmRfZml4ZWQoMS4zKSArCiAgbGFicygKICAgIHRpdGxlID0gIlBhcnRpY2lwYW50IFpJUCBDb2RlcyBBY3Jvc3MgdGhlIFVuaXRlZCBTdGF0ZXMiLAogICAgeCA9IE5VTEwsCiAgICB5ID0gTlVMTCwKICAgIHNpemUgPSAiQ291bnQiLAogICAgY29sb3IgPSAiQ291bnQiCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKIyBiKSBEaXN0cmlidXRpb25zIG9mIGNvdmFyaWF0ZXMKCiMgR29hbDogVG8gdW5kZXJzdGFuZCB3aG8gaXMgaW4gb3VyIGRhdGEgKHRoZWlyIGNvbnN1bXB0aW9uIHRlbmRlbmNpZXMpCgpgYGB7cn0KIyBPdmVyYWxsIGRlc2NyaXB0aXZlcyBmb3IgY292YXJpYXRlcwpjb3ZhcmlhdGVzIDwtIGRmICU+JSAjIENyZWF0ZSBhIG5ldyBkYXRhIGZyYW1lIHdpdGggb25seSBmb3VyIGNvdmFyaWF0ZSB2YXJpYWJsZXMKICBzZWxlY3QoCiAgICBxdWFsaXR5LnBlcmNlcHRpb24sCiAgICBwZXJjZWl2ZWQuYmVuZWZpdHMsCiAgICBzZWxsZXIuY29udHJvbCwKICAgIHN1cmNoYXJnZS5ub3ZlbHR5LAogICkKCiMgR2V0IGRlc2NyaXB0aXZlIHN0YXRzIGZvciB0aGVzZSBjb3ZhcmlhdGVzCmRlc2NyaWJlKGNvdmFyaWF0ZXMpCmBgYAoKIyBiKSBEaXN0cmlidXRpb25zIG9mIGNvdmFyaWF0ZXMgKFZpc3VhbGl6aW5nIHRoZSBkaXN0cmlidXRpb25zKQoKIyBHb2FsOiBQbG90IGhpc3RvZ3JhbXMgYW5kIGV4cGxvcmUgdmFyaWFibGVzIGluZGl2aWR1YWxseQoKYGBge3J9CiMgSGlzdG9ncmFtOiBxdWFsaXR5LnBlcmNlcHRpb24KcDYgPC0gZ2dwbG90KGRmLCBhZXMoeCA9IHF1YWxpdHkucGVyY2VwdGlvbikpICsgIyBpbml0aWF0ZSBnZ3Bsb3QgdXNpbmcgZGF0YXNldCAiZGYiIGFuZCB1c2UgcXVhbGl0eS5wZXJjZXB0aW9uIGFzIHRoZSB4LWF4aXMKICBnZW9tX2hpc3RvZ3JhbSgKICAgIGJpbndpZHRoID0gMSwgICAgIyBlYWNoIGJhciByZXByZXNlbnRzIGEgd2lkdGggb2YgMSB1bml0ICh0aGlzIGZpdHMgaW50ZXJ2YWwvcmF0aW8gc2NhbGVzKQogICAgYm91bmRhcnkgPSAwLjUsICAjIG1ha2UgYmFycyBjZW50ZXJlZCBvbiBpbnRlZ2VycwogICAgZmlsbCA9ICIjN0EwMDE5IiwgIyBzZXQgYmFyIGZpbGwgY29sb3IKICAgIGNvbG9yID0gIndoaXRlIiAgICMgc2V0IGJvcmRlciBjb2xvciBvZiBiYXJzCiAgKSArCiAgZ2VvbV92bGluZSggICMgYWRkIGEgdmVydGljYWwgbGluZQogICAgeGludGVyY2VwdCA9IG1lYW4oZGYkcXVhbGl0eS5wZXJjZXB0aW9uLCBuYS5ybSA9IFRSVUUpLCAjIHBvc2l0aW9uIGxpbmUgYXQgdGhlIG1lYW4KICAgIGxpbmV0eXBlID0gImRhc2hlZCIsCiAgICBsaW5ld2lkdGggPSAxCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBRdWFsaXR5IFBlcmNlcHRpb24iLCAjIGFkZCBsYWJlbHMgYW5kIHRpdGxlcwogICAgc3VidGl0bGUgPSAiRGFzaGVkIGxpbmUgPSBNZWFuIiwKICAgIHggPSAiUFF1YWxpdHkgUGVyY2VwdGlvbiAoMeKAkzcgc2NhbGUpIiwKICAgIHkgPSAiTnVtYmVyIG9mIFBhcnRpY2lwYW50cyIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArICMgYXBwbHkgYSBjbGVhbiBtaW5pbWFsIHRoZW1lIHdpdGggYmFzZSBmcm9udCBzaXplIDE0CiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwgIyBjZW50ZXIgYW5kIGJvbGQgdGhlIHRpdGxlCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgIyBjZW50ZXIgdGhlIHN1YnRpdGxlCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksICMgcmVtb3ZlIHZlcnRpY2FsIG1ham9yIGdyaWQgbGluZXMKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkgIyByZW1vdmUgYWxsIG1pbm9yIGdyaWQgbGluZXMKICApCgojIEhpc3RvZ3JhbTogcGVyY2VpdmVkIGJlbmVmaXRzCnA3IDwtIGdncGxvdChkZiwgYWVzKHggPSBwZXJjZWl2ZWQuYmVuZWZpdHMpKSArCiAgZ2VvbV9oaXN0b2dyYW0oCiAgICBiaW53aWR0aCA9IDEsIAogICAgYm91bmRhcnkgPSAwLjUsCiAgICBmaWxsID0gIiM3QTAwMTkiLAogICAgY29sb3IgPSAid2hpdGUiCiAgKSArCiAgZ2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSBtZWFuKGRmJHBlcmNlaXZlZC5iZW5lZml0cywgbmEucm0gPSBUUlVFKSwKICAgIGxpbmV0eXBlID0gImRhc2hlZCIsCiAgICBsaW5ld2lkdGggPSAxCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBQZXJjZWl2ZWQgQmVuZWZpdHMiLAogICAgc3VidGl0bGUgPSAiRGFzaGVkIGxpbmUgPSBNZWFuIiwKICAgIHggPSAiUGVyY2VpdmVkIGJlbmVmaXRzICgx4oCTNSBzY2FsZSkiLAogICAgeSA9ICJOdW1iZXIgb2YgUGFydGljaXBhbnRzIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIpLAogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpCiAgKQoKIyBIaXN0b2dyYW06IHNlbGxlciBjb250cm9sCnA4IDwtIGdncGxvdChkZiwgYWVzKHggPSBzZWxsZXIuY29udHJvbCkpICsKICBnZW9tX2hpc3RvZ3JhbSgKICAgIGJpbndpZHRoID0gMSwgCiAgICBib3VuZGFyeSA9IDAuNSwKICAgIGZpbGwgPSAiIzdBMDAxOSIsCiAgICBjb2xvciA9ICJ3aGl0ZSIKICApICsKICBnZW9tX3ZsaW5lKAogICAgeGludGVyY2VwdCA9IG1lYW4oZGYkc2VsbGVyLmNvbnRyb2wsIG5hLnJtID0gVFJVRSksCiAgICBsaW5ldHlwZSA9ICJkYXNoZWQiLAogICAgbGluZXdpZHRoID0gMQogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgU2VsbGVyIENvbnRyb2wiLAogICAgc3VidGl0bGUgPSAiRGFzaGVkIGxpbmUgPSBNZWFuIiwKICAgIHggPSAiU2VsbGVyIENvbnRyb2wgKDHigJM3IHNjYWxlKSIsCiAgICB5ID0gIk51bWJlciBvZiBQYXJ0aWNpcGFudHMiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCgojIEhpc3RvZ3JhbTogc3VyY2hhcmdlIG5vdmVsdHkKcDkgPC0gZ2dwbG90KGRmLCBhZXMoeCA9IHN1cmNoYXJnZS5ub3ZlbHR5KSkgKwogIGdlb21faGlzdG9ncmFtKAogICAgYmlud2lkdGggPSAxLCAKICAgIGJvdW5kYXJ5ID0gMC41LAogICAgZmlsbCA9ICIjN0EwMDE5IiwKICAgIGNvbG9yID0gIndoaXRlIgogICkgKwogIGdlb21fdmxpbmUoCiAgICB4aW50ZXJjZXB0ID0gbWVhbihkZiRzdXJjaGFyZ2Uubm92ZWx0eSwgbmEucm0gPSBUUlVFKSwKICAgIGxpbmV0eXBlID0gImRhc2hlZCIsCiAgICBsaW5ld2lkdGggPSAxCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBTdXJjaGFyZ2UgTm92ZWx0eSIsCiAgICBzdWJ0aXRsZSA9ICJEYXNoZWQgbGluZSA9IE1lYW4iLAogICAgeCA9ICJTdXJjaGFyZ2UgTm92ZWx0eSAoMeKAkzcgc2NhbGUpIiwKICAgIHkgPSAiTnVtYmVyIG9mIFBhcnRpY2lwYW50cyIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCnA2ICsgcDcgKyBwOCArIHA5ICMgT3B0aW9uIzE6IENvbWJpbmUgdGhlIGZvdXIgcGxvdHMgaW50byBvbmUgZmlndXJlCnA2ICMgT3B0aW9uIzI6IFBsb3QgdGhlIGZvdXIgcGxvdHMgb24gc2VwYXJhdGUgcGFnZXMKcDcKcDcKcDkKYGBgCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIAoKIyBBc3Nlc3MgcmFuZG9taXphdGlvbgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAKCiMgT3ZlcmFsbCBkZXNjcmlwdGl2ZSBzdGF0cwoKIyBHb2FsOiBDaGVjayBpZiB0aGUgcmFuZG9taXphdGlvbiBpcyBzdWNjZXNzZnVsICh0aGUgbnVtYmVyIG9mIHBhcnRpY2lwYW50cyBzaG91bGQgYmUgbGFyZ2VseSB0aGUgc2FtZSBhY3Jvc3MgY29uZGl0aW9ucykKCmBgYHtyfQojIENvdW50IG51bWJlciBvZiBwYXJ0aWNpcGFudHMgaW4gZWFjaCAyIHggMiBleHBlcmltZW50YWwgY2VsbApkZiAlPiUKICBjb3VudChJVjFfcHJpY2VfZm9ybWF0LCBJVjJfc3VyY2hhcmdlX3R5cGUpCmBgYAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAKCiMgVmFyaWFibGUgZGlzdHJpYnV0aW9ucwoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyAKCmBgYHtyfQojIE92ZXJhbGwgZGVzY3JpcHRpdmVzIGZvciBEVnMKRFZzIDwtIGRmICU+JQogIHNlbGVjdCgKICAgIHB1cmNoYXNlLmludGVudGlvbiwKICAgIGJyYW5kLmF0dGl0dWRlLAogICAgc2VsbGVyLnRydXN0LAogICAgZmFpcm5lc3MKICApCgpkZXNjcmliZShEVnMpCmBgYAoKIyBEaXN0cmlidXRpb25zIG9mIERWcyAoVmlzdWFsaXppbmcgdGhlIGRpc3RyaWJ1dGlvbnMpCgojIEdvYWw6IFBsb3QgaGlzdG9ncmFtcyBhbmQgZXhwbG9yZSB2YXJpYWJsZXMgaW5kaXZpZHVhbGx5CgpgYGB7cn0KIyBIaXN0b2dyYW06IHB1cmNoYXNlIGludGVudGlvbgpwMSA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gcHVyY2hhc2UuaW50ZW50aW9uKSkgKwogIGdlb21faGlzdG9ncmFtKAogICAgYmlud2lkdGggPSAxLCAKICAgIGJvdW5kYXJ5ID0gMC41LAogICAgZmlsbCA9ICIjN0EwMDE5IiwKICAgIGNvbG9yID0gIndoaXRlIgogICkgKwogIGdlb21fdmxpbmUoCiAgICB4aW50ZXJjZXB0ID0gbWVhbihkZiRwdXJjaGFzZS5pbnRlbnRpb24sIG5hLnJtID0gVFJVRSksCiAgICBsaW5ldHlwZSA9ICJkYXNoZWQiLAogICAgbGluZXdpZHRoID0gMQogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUHVyY2hhc2UgSW50ZW50aW9uIiwKICAgIHN1YnRpdGxlID0gIkRhc2hlZCBsaW5lID0gTWVhbiIsCiAgICB4ID0gIlB1cmNoYXNlIEludGVudGlvbiAoMeKAkzcgc2NhbGUpIiwKICAgIHkgPSAiTnVtYmVyIG9mIFBhcnRpY2lwYW50cyIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCiMgSGlzdG9ncmFtOiBicmFuZCBhdHRpdHVkZQpwMiA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gYnJhbmQuYXR0aXR1ZGUpKSArCiAgZ2VvbV9oaXN0b2dyYW0oCiAgICBiaW53aWR0aCA9IDEsIAogICAgYm91bmRhcnkgPSAwLjUsCiAgICBmaWxsID0gIiM3QTAwMTkiLAogICAgY29sb3IgPSAid2hpdGUiCiAgKSArCiAgZ2VvbV92bGluZSgKICAgIHhpbnRlcmNlcHQgPSBtZWFuKGRmJGJyYW5kLmF0dGl0dWRlLCBuYS5ybSA9IFRSVUUpLAogICAgbGluZXR5cGUgPSAiZGFzaGVkIiwKICAgIGxpbmV3aWR0aCA9IDEKICApICsKICBsYWJzKAogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEJyYW5kIEF0dGl0dWRlIiwKICAgIHN1YnRpdGxlID0gIkRhc2hlZCBsaW5lID0gTWVhbiIsCiAgICB4ID0gIkJyYW5kIEF0dGl0dWRlICgx4oCTMTAgc2NhbGUpIiwKICAgIHkgPSAiTnVtYmVyIG9mIFBhcnRpY2lwYW50cyIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCiMgQmFyIGNoYXJ0LCBicmFuZCBhdHRpdHVkZSAoTlBTKQpwMyA8LSBnZ3Bsb3QoZGYsIGFlcyh4ID0gYnJhbmQuYXR0aXR1ZGVfTlBTX0dST1VQKSkgKwogIGdlb21fYmFyKGZpbGwgPSAiIzdBMDAxOSIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIE5QUyBHcm91cHMiLAogICAgeCA9ICJOUFMgR3JvdXAiLAogICAgeSA9ICJOdW1iZXIgb2YgUGFydGljaXBhbnRzIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsKICB0aGVtZSgKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCiMgSGlzdG9ncmFtOiBzZWxsZXIgdHJ1c3QKcDQgPC0gZ2dwbG90KGRmLCBhZXMoeCA9IHNlbGxlci50cnVzdCkpICsKICBnZW9tX2hpc3RvZ3JhbSgKICAgIGJpbndpZHRoID0gMSwgCiAgICBib3VuZGFyeSA9IDAuNSwKICAgIGZpbGwgPSAiIzdBMDAxOSIsCiAgICBjb2xvciA9ICJ3aGl0ZSIKICApICsKICBnZW9tX3ZsaW5lKAogICAgeGludGVyY2VwdCA9IG1lYW4oZGYkc2VsbGVyLnRydXN0LCBuYS5ybSA9IFRSVUUpLAogICAgbGluZXR5cGUgPSAiZGFzaGVkIiwKICAgIGxpbmV3aWR0aCA9IDEKICApICsKICBsYWJzKAogICAgdGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFNlbGxlciBUcnVzdCIsCiAgICBzdWJ0aXRsZSA9ICJEYXNoZWQgbGluZSA9IE1lYW4iLAogICAgeCA9ICJTZWxsZXIgdHJ1c3QgKDHigJM3IHNjYWxlKSIsCiAgICB5ID0gIk51bWJlciBvZiBQYXJ0aWNpcGFudHMiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkKICApCgojIEhpc3RvZ3JhbTogZmFpcm5lc3MKcDUgPC0gZ2dwbG90KGRmLCBhZXMoeCA9IGZhaXJuZXNzKSkgKwogIGdlb21faGlzdG9ncmFtKAogICAgYmlud2lkdGggPSAxLCAKICAgIGJvdW5kYXJ5ID0gMC41LAogICAgZmlsbCA9ICIjN0EwMDE5IiwKICAgIGNvbG9yID0gIndoaXRlIgogICkgKwogIGdlb21fdmxpbmUoCiAgICB4aW50ZXJjZXB0ID0gbWVhbihkZiRmYWlybmVzcywgbmEucm0gPSBUUlVFKSwKICAgIGxpbmV0eXBlID0gImRhc2hlZCIsCiAgICBsaW5ld2lkdGggPSAxCiAgKSArCiAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBGYWlybmVzcyIsCiAgICBzdWJ0aXRsZSA9ICJEYXNoZWQgbGluZSA9IE1lYW4iLAogICAgeCA9ICJGYWlybmVzcyAoMeKAkzcgc2NhbGUpIiwKICAgIHkgPSAiTnVtYmVyIG9mIFBhcnRpY2lwYW50cyIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDE0KSArCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKQogICkKCnAxIApwMiAKcDMgCnA0IApwNQpgYGAKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgCgojIFZhcmlhYmxlIHJlbGF0aW9uc2hpcHMKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgCgojIFNjYXR0ZXJwbG90cyBmb3IgcmVsYXRpb25zaGlwcyBhbW9uZyBEVnMKCiMgR29hbDogVmlzdWFsbHkgYXNzZXNzIG1hbnkgdmFyaWFibGUgcmVsYXRpb25zaGlwcyBhdCBvbmNlCgpgYGB7cn0KIyBQbG90IDE6IGJyYW5kIGF0dGl0dWRlIGJ5IHB1cmNoYXNlIGludGVudGlvbgpnZ3Bsb3QoZGYsIGFlcyh4ID0gYnJhbmQuYXR0aXR1ZGUsIHkgPSBwdXJjaGFzZS5pbnRlbnRpb24pKSArICMgYWVzKC4uLikgPSBhZXN0aGV0aWNzICh0ZWxsIFJTdHVkaW8gd2hhdCBnb2VzIG9uIGF4ZXMpLiBIZXJlIHdlIGFyZSBwbG90dGluZyBicmFuZCBhdHRpdHVkZSBvbiB0aGUgeC1heGlzIGFuZCBwdXJjaGFzZSBpbnRlbnRpb24gb24gdGhlIHktYXhpcwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSkgKyAjIFdlIGFyZSB1c2luZyBhIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsICgibG0iKSB0byBkcmF3IGEgYmVzdC1maXR0aW5nIGxpbmUgYmV0d2VlbiBicmFuZCBhdHRpdHVkZSBhbmQgcHVyY2hhc2UgaW50ZW50aW9uIAogIGdlb21faml0dGVyKHdpZHRoID0gMC4yLCBoZWlnaHQgPSAwLjIpICsgIyB0aGlzIGZ1bmN0aW9uIGhlbHBzIHVzIHBsb3QgZWFjaCBwYXJ0aWNpcGFudCBhcyBhIGRvdAogIHRoZW1lX21pbmltYWwoKSArICMgTWFrZSB0aGUgcGxvdCBjbGVhbmVyIGFuZCBlYXNpZXIgdG8gcmVhZAogIGxhYnModGl0bGUgPSAiQnJhbmQgQXR0aXR1ZGUgYW5kIFB1cmNoYXNlIEludGVudGlvbiIsIAogICAgICAgeCA9ICJCcmFuZCBBdHRpdHVkZSIsIHkgPSAiUHVyY2hhc2UgSW50ZW50aW9uIikgIyBBZGQgbGFiZWxzIHRvIHRoZSBmaWd1cmUsIHgtYXhpcywgYW5kIHktYXhpcwoKIyBQbG90IDI6IHNlbGxlciB0cnVzdCBieSBwdXJjaGFzZSBpbnRlbnRpb24KZ2dwbG90KGRmLCBhZXMoeCA9IHNlbGxlci50cnVzdCwgeSA9IHB1cmNoYXNlLmludGVudGlvbikpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUpICsKICBnZW9tX2ppdHRlcih3aWR0aCA9IDAuMiwgaGVpZ2h0ID0gMC4yKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIlNlbGxlciBUcnVzdCBhbmQgUHVyY2hhc2UgSW50ZW50aW9uIiwKICAgICAgIHggPSAiU2VsbGVyIFRydXN0IiwgeSA9ICJQdXJjaGFzZSBJbnRlbnRpb24iKQoKIyBQbG90IDM6IGZhaXJuZXNzIGJ5IHB1cmNoYXNlIGludGVudGlvbgpnZ3Bsb3QoZGYsIGFlcyh4ID0gZmFpcm5lc3MsIHkgPSBwdXJjaGFzZS5pbnRlbnRpb24pKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFKSArCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIsIGhlaWdodCA9IDAuMikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJGYWlybmVzcyBhbmQgUHVyY2hhc2UgSW50ZW50aW9uIiwKICAgICAgIHggPSAiUGVyY2VpdmVkIEZhaXJuZXNzIiwgeSA9ICJQdXJjaGFzZSBJbnRlbnRpb24iKQoKIyBQbG90IDQ6IHNlbGxlciB0cnVzdCBieSBicmFuZCBhdHRpdHVkZQpnZ3Bsb3QoZGYsIGFlcyh4ID0gc2VsbGVyLnRydXN0LCB5ID0gYnJhbmQuYXR0aXR1ZGUpKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFKSArCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIsIGhlaWdodCA9IDAuMikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJTZWxsZXIgVHJ1c3QgYW5kIEJyYW5kIEF0dGl0dWRlIiwKICAgICAgIHggPSAiU2VsbGVyIFRydXN0IiwgeSA9ICJCcmFuZCBBdHRpdHVkZSIpCgojIFBsb3QgNTogZmFpcm5lc3MgYnkgYnJhbmQgYXR0aXR1ZGUKZ2dwbG90KGRmLCBhZXMoeCA9IGZhaXJuZXNzLCB5ID0gYnJhbmQuYXR0aXR1ZGUpKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFKSArCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAwLjIsIGhlaWdodCA9IDAuMikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJGYWlybmVzcyBhbmQgQnJhbmQgQXR0aXR1ZGUiLAogICAgICAgeCA9ICJQZXJjZWl2ZWQgRmFpcm5lc3MiLCB5ID0gIkJyYW5kIEF0dGl0dWRlIikKCiMgUGxvdCA2OiBmYWlybmVzcyBieSBzZWxsZXIgdHJ1c3QKZ2dwbG90KGRmLCBhZXMoeCA9IGZhaXJuZXNzLCB5ID0gc2VsbGVyLnRydXN0KSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSkgKwogIGdlb21faml0dGVyKHdpZHRoID0gMC4yLCBoZWlnaHQgPSAwLjIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiRmFpcm5lc3MgYW5kIFNlbGxlciBUcnVzdCIsCiAgICAgICB4ID0gIlBlcmNlaXZlZCBGYWlybmVzcyIsIHkgPSAiU2VsbGVyIFRydXN0IikKYGBgCgojIENvcnJlbGF0aW9uIG1hdHJpeAoKYGBge3J9CiMgU2VsZWN0IHRoZSB2YXJpYWJsZXMgdG8gaW5jbHVkZSBpbiB0aGUgY29ycmVsYXRpb24gbWF0cml4CmNvcnJfdmFycyA8LSBkZiU+JQogIHNlbGVjdCgKICAgIHB1cmNoYXNlLmludGVudGlvbiwKICAgIGJyYW5kLmF0dGl0dWRlLAogICAgc2VsbGVyLnRydXN0LAogICAgZmFpcm5lc3MsCiAgICBxdWFsaXR5LnBlcmNlcHRpb24sCiAgICBwZXJjZWl2ZWQuYmVuZWZpdHMsCiAgICBzZWxsZXIuY29udHJvbCwKICAgIHN1cmNoYXJnZS5ub3ZlbHR5CiAgKQoKIyBDb21wdXRlIGNvcnJlbGF0aW9ucyBhbmQgcC12YWx1ZXMKY29yX3Jlc3VsdHMgPC0gcmNvcnIoYXMubWF0cml4KGNvcnJfdmFycykpCgojIENvcnJlbGF0aW9uIG1hdHJpeApjb3JfbWF0cml4IDwtIGNvcl9yZXN1bHRzJHIKCiMgUC12YWx1ZSBtYXRyaXgKcF9tYXRyaXggPC0gY29yX3Jlc3VsdHMkUAoKIyBWaWV3IGNvcnJlbGF0aW9uIG1hdHJpeApyb3VuZChjb3JfbWF0cml4LCAyKQpgYGAKCmBgYHtyfQojIENvbnZlcnQgY29ycmVsYXRpb24gbWF0cml4IHRvIGxvbmcgZm9ybWF0CmNvcl9kZiA8LSBhcy5kYXRhLmZyYW1lKGNvcl9tYXRyaXgpICU+JQogIHJvd25hbWVzX3RvX2NvbHVtbigidmFyMSIpICU+JQogIHBpdm90X2xvbmdlcigtdmFyMSwgbmFtZXNfdG8gPSAidmFyMiIsIHZhbHVlc190byA9ICJjb3JyZWxhdGlvbiIpCgojIENvbnZlcnQgcC12YWx1ZSBtYXRyaXggdG8gbG9uZyBmb3JtYXQKcF9kZiA8LSBhcy5kYXRhLmZyYW1lKHBfbWF0cml4KSAlPiUKICByb3duYW1lc190b19jb2x1bW4oInZhcjEiKSAlPiUKICBwaXZvdF9sb25nZXIoLXZhcjEsIG5hbWVzX3RvID0gInZhcjIiLCB2YWx1ZXNfdG8gPSAicF92YWx1ZSIpCgojIE1lcmdlIGNvcnJlbGF0aW9ucyBhbmQgcC12YWx1ZXMKY29yX2RmIDwtIGNvcl9kZiAlPiUKICBsZWZ0X2pvaW4ocF9kZiwgYnkgPSBjKCJ2YXIxIiwgInZhcjIiKSkgJT4lCiAgbXV0YXRlKAogICAgc2lnID0gY2FzZV93aGVuKAogICAgICBwX3ZhbHVlIDwgLjAwMSB+ICIqKioiLAogICAgICBwX3ZhbHVlIDwgLjAxICB+ICIqKiIsCiAgICAgIHBfdmFsdWUgPCAuMDUgIH4gIioiLAogICAgICBUUlVFIH4gIiIKICAgICkKICApCgojIFBsb3QgdGhlIGNvcnJlbGF0aW9uIG1hdHJpeApnZ3Bsb3QoY29yX2RmLCBhZXMoeCA9IHZhcjEsIHkgPSB2YXIyKSkgKwogIGdlb21fcG9pbnQoYWVzKHNpemUgPSBhYnMoY29ycmVsYXRpb24pLCBjb2xvciA9IGNvcnJlbGF0aW9uKSkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAocm91bmQoY29ycmVsYXRpb24sIDIpLCBzaWcpKSwgc2l6ZSA9IDMpICsKICBzY2FsZV9zaXplKHJhbmdlID0gYygyLCA4KSkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50MigKICAgIGxvdyA9ICIjQjIxODJCIiwKICAgIG1pZCA9ICJ3aGl0ZSIsCiAgICBoaWdoID0gIiMyMTY2QUMiLAogICAgbWlkcG9pbnQgPSAwCiAgKSArCiAgY29vcmRfZXF1YWwoKSArCiAgbGFicygKICAgIHRpdGxlID0gIkNvcnJlbGF0aW9uIE1hdHJpeCAod2l0aCBTaWduaWZpY2FuY2UpIiwKICAgIHggPSAiIiwKICAgIHkgPSAiIiwKICAgIGNvbG9yID0gIkNvcnJlbGF0aW9uIiwKICAgIHNpemUgPSAifHJ8IgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTQpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIikKICApCmBgYAoKYGBge3J9CiMgWW91ciBSIGNvZGUgaGVyZQpzdW1tYXJ5KGNhcnMpCnBsb3QoY2FycykKYGBgCg==