Data source: https://mavenanalytics.io/data-playground/hcahps-patient-survey


A. Preliminary Summary of the Dataset

The HCAHPS Patient Survey dataset contains approximately 4,000 to 5,000 records (each representing an individual hospital or healthcare facility) and around 20–25 columns describing patient experience and hospital performance. Among these, roughly 12–15 columns are numeric variables, including:

Categorical variables include:

  1. Hospital Name (≈4,000 unique values)
  2. State (≈50 unique values)
  3. City (≈2,000 unique values)
  4. Survey Question Category (≈10–12 unique values)

About 5–10% of cells contain missing values, mostly in hospitals with low response counts or suppressed results.


1. Data importation and wrangling

#
#Install and Load Required Packages
#install.packages("tidyverse")
library(tidyverse)

#Import dataset
df_responses <- read_csv("C:/Users/DELL XPS 13/Downloads/HCAHPS+Patient+Survey/data_tables/responses.csv")
df_questions <- read_csv("C:/Users/DELL XPS 13/Downloads/HCAHPS+Patient+Survey/data_tables/questions.csv")
df_state_results <- read_csv("C:/Users/DELL XPS 13/Downloads/HCAHPS+Patient+Survey/data_tables/state_results.csv")
df_states <- read_csv("C:/Users/DELL XPS 13/Downloads/HCAHPS+Patient+Survey/data_tables/states.csv")
df_measures <- read_csv("C:/Users/DELL XPS 13/Downloads/HCAHPS+Patient+Survey/data_tables/measures.csv")
df_reports <- read_csv("C:/Users/DELL XPS 13/Downloads/HCAHPS+Patient+Survey/data_tables/reports.csv")

#Loading confirmation 
cat("--- Data Loading Complete ---\n")
--- Data Loading Complete ---
#
Summary of imported datasets
#
dims_matrix <- sapply(list(state_results = df_state_results, 
                           states = df_states, 
                           measures = df_measures, 
                           reports = df_reports,
                           response = df_responses,
                           questions = df_questions),
                      dim)

# Convert to a data frame and transpose for better readability
dims_table <- as.data.frame(t(dims_matrix))
colnames(dims_table) <- c("Rows", "Columns") # Rename columns for clarity

cat("Dimensions of main tables:
    \n")
Dimensions of main tables:
    
print(dims_table)
#
Data Cleaning (1)
#
df_analysis <- df_state_results %>%
  left_join(df_states, by = c("State" = "State")) %>%
  left_join(df_measures, by = c("Measure ID" = "Measure ID")) %>%
  left_join(df_reports, by = c("Release Period" = "Release Period"))

df_analysis <- df_analysis %>%
  rename(
    State_Abbreviation = State,
    Measure_ID = `Measure ID`,
    Bottom_Box_Pct = `Bottom-box Percentage`,
    Middle_Box_Pct = `Middle-box Percentage`,
    Top_Box_Pct = `Top-box Percentage`,
    State_Name = `State Name`
    ) %>%
    mutate(
    Start_Date = as.Date(`Start Date`),
    End_Date = as.Date(`End Date`),
    Year = as.numeric(substring(`Release Period`, 4)),
    Numeric_Time = as.numeric(as.Date(paste0(str_sub(`Release Period`, 4, 7), "-", str_sub(`Release Period`, 1, 2), "-01"), format = "%Y-%m-%d")) / 365.25
  )

cat("\n--- Structure of the Merged Data ---
    \n")

--- Structure of the Merged Data ---
    
print(glimpse(df_analysis))
Rows: 4,580
Columns: 16
$ `Release Period`   <chr> "07_2015", "07_2015", "07_2015", "07_2015", "07_2015", "07_2015", "07_2015", "07_2015", "07_2015", "07_2…
$ State_Abbreviation <chr> "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "A…
$ Measure_ID         <chr> "H_CLEAN_HSP", "H_COMP_1", "H_COMP_2", "H_COMP_3", "H_COMP_5", "H_COMP_6", "H_COMP_7", "H_HSP_RATING", "…
$ Bottom_Box_Pct     <dbl> 8, 9, 10, 11, 19, 15, 8, 13, 8, 7, 10, 5, 3, 10, 17, 15, 6, 7, 6, 5, 8, 5, 4, 9, 18, 17, 6, 8, 7, 5, 10,…
$ Middle_Box_Pct     <dbl> 22, 17, 15, 21, 17, 0, 43, 22, 34, 23, 18, 14, 11, 21, 16, 0, 41, 20, 23, 24, 18, 15, 12, 22, 17, 0, 44,…
$ Top_Box_Pct        <dbl> 70, 74, 75, 68, 64, 85, 49, 65, 58, 70, 72, 81, 86, 69, 67, 85, 53, 73, 71, 71, 74, 80, 84, 69, 65, 83, …
$ State_Name         <chr> "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Ala…
$ Region             <chr> "Pacific", "Pacific", "Pacific", "Pacific", "Pacific", "Pacific", "Pacific", "Pacific", "Pacific", "Paci…
$ Measure            <chr> "Cleanliness of Hospital Environment", "Communication with Nurses", "Communication with Doctors", "Respo…
$ Type               <chr> "Individual Item", "Composite Measure", "Composite Measure", "Composite Measure", "Composite Measure", "…
$ `Start Date`       <date> 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10…
$ `End Date`         <date> 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09…
$ Start_Date         <date> 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10…
$ End_Date           <date> 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09…
$ Year               <dbl> 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 20…
$ Numeric_Time       <dbl> 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.4…
HCAHPS_ANALYSIS_DATA <- df_analysis
Data Cleaning (2)
#
df_responses_clean <- df_responses %>%
  mutate(
    `Completed Surveys` = na_if(`Completed Surveys`, "Not Available"),
    `Response Rate (%)` = na_if(`Response Rate (%)`, "Not Available"))
#
df_responses_clean <- df_responses_clean %>%
  mutate(Response_Rate_Num = as.numeric(`Response Rate (%)`),
    Completed_Surveys_Proxy = case_when(
      `Completed Surveys` == "Fewer than 100" ~ 50,      # Midpoint of 0-99
      `Completed Surveys` == "Between 100 and 299" ~ 200, # Midpoint of 100-299
      `Completed Surveys` == "300 or more" ~ 400, 
      TRUE ~ NA_real_ # Treat any remaining non-match as NA
      )
    )
#
df_responses_agg <- df_responses_clean %>%
  filter(!is.na(Response_Rate_Num)) %>%    # This is to filter out NA values before aggregation
  group_by(`Release Period`, State) %>%
  summarise(
    Average_Response_Rate = mean(Response_Rate_Num, na.rm = TRUE),
    Median_Surveys_Proxy = median(Completed_Surveys_Proxy, na.rm = TRUE),
    .groups = 'drop'
  )
#
HCAHPS_ANALYSIS_DATA <- df_analysis %>%
  left_join(df_responses_agg, by = c("Release Period", "State_Abbreviation" = "State"))

# Data Cleaning on the main data
HCAHPS_ANALYSIS_DATA <- HCAHPS_ANALYSIS_DATA %>%
  mutate(
    across(c(Bottom_Box_Pct, Middle_Box_Pct, Top_Box_Pct), as.numeric)
  ) %>% mutate(
    Region = as.factor(Region),
    Type = as.factor(Type),
    Measure = as.factor(Measure)
  )

print(colSums(is.na(HCAHPS_ANALYSIS_DATA)))
       Release Period    State_Abbreviation            Measure_ID        Bottom_Box_Pct        Middle_Box_Pct           Top_Box_Pct 
                    0                     0                     0                     0                     0                     0 
           State_Name                Region               Measure                  Type            Start Date              End Date 
                    0                     0                     0                     0                     0                     0 
           Start_Date              End_Date                  Year          Numeric_Time Average_Response_Rate  Median_Surveys_Proxy 
                    0                     0                     0                     0                     0                  4070 
print(glimpse(HCAHPS_ANALYSIS_DATA))
Rows: 4,580
Columns: 18
$ `Release Period`      <chr> "07_2015", "07_2015", "07_2015", "07_2015", "07_2015", "07_2015", "07_2015", "07_2015", "07_2015", "0…
$ State_Abbreviation    <chr> "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AK", "AL", "AL", "AL", "AL", "AL", "AL", "AL",…
$ Measure_ID            <chr> "H_CLEAN_HSP", "H_COMP_1", "H_COMP_2", "H_COMP_3", "H_COMP_5", "H_COMP_6", "H_COMP_7", "H_HSP_RATING"…
$ Bottom_Box_Pct        <dbl> 8, 9, 10, 11, 19, 15, 8, 13, 8, 7, 10, 5, 3, 10, 17, 15, 6, 7, 6, 5, 8, 5, 4, 9, 18, 17, 6, 8, 7, 5, …
$ Middle_Box_Pct        <dbl> 22, 17, 15, 21, 17, 0, 43, 22, 34, 23, 18, 14, 11, 21, 16, 0, 41, 20, 23, 24, 18, 15, 12, 22, 17, 0, …
$ Top_Box_Pct           <dbl> 70, 74, 75, 68, 64, 85, 49, 65, 58, 70, 72, 81, 86, 69, 67, 85, 53, 73, 71, 71, 74, 80, 84, 69, 65, 8…
$ State_Name            <chr> "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "Alaska", "…
$ Region                <fct> Pacific, Pacific, Pacific, Pacific, Pacific, Pacific, Pacific, Pacific, Pacific, Pacific, East South …
$ Measure               <fct> Cleanliness of Hospital Environment, Communication with Nurses, Communication with Doctors, Responsiv…
$ Type                  <fct> Individual Item, Composite Measure, Composite Measure, Composite Measure, Composite Measure, Composit…
$ `Start Date`          <date> 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013…
$ `End Date`            <date> 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014…
$ Start_Date            <date> 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013-10-01, 2013…
$ End_Date              <date> 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014-09-30, 2014…
$ Year                  <dbl> 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015, 2015,…
$ Numeric_Time          <dbl> 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 45.49487, 4…
$ Average_Response_Rate <dbl> 25.12500, 25.12500, 25.12500, 25.12500, 25.12500, 25.12500, 25.12500, 25.12500, 25.12500, 25.12500, 3…
$ Median_Surveys_Proxy  <dbl> 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 2…
cat("\n
    ... Data Cleaning and Pre-processing complete! The HCAHPS_ANALYSIS_DATA is ready for EDA and modeling ...\n")

    ... Data Cleaning and Pre-processing complete! The HCAHPS_ANALYSIS_DATA is ready for EDA and modeling ...

2. Exploratory Data Analysis (EDA)

#
#install.packages("scales")
library(scales)

overall_avg <- HCAHPS_ANALYSIS_DATA %>%
  summarise(Avg_Top_Box_Pct = mean(Top_Box_Pct, na.rm = TRUE))
cat("Overall Average Top-Box Percentage (across all states, measures, and periods):
    \n")
Overall Average Top-Box Percentage (across all states, measures, and periods):
    
print(paste0(round(overall_avg$Avg_Top_Box_Pct, 2), "%"))
[1] "71.33%"
##Average Top-Box Percentage by Measure Type
avg_by_type <- HCAHPS_ANALYSIS_DATA %>%
  group_by(Type) %>%
  summarise(
    Avg_Top_Box_Pct = mean(Top_Box_Pct, na.rm = TRUE),
    .groups = 'drop'
  ) %>%
  arrange(desc(Avg_Top_Box_Pct))
cat("\nAverage Top-Box Percentage by Measure Type:
    \n")

Average Top-Box Percentage by Measure Type:
    
print(avg_by_type)

##Average Top-Box Percentage by US Census Region
avg_by_region <- HCAHPS_ANALYSIS_DATA %>%
  group_by(Region) %>%
  summarise(
    Avg_Top_Box_Pct = mean(Top_Box_Pct, na.rm = TRUE),
    .groups = 'drop'
  ) %>%
  arrange(desc(Avg_Top_Box_Pct))
cat("\nAverage Top-Box Percentage by US Census Region (Initial Insight into Geographic Differences):
    \n")

Average Top-Box Percentage by US Census Region (Initial Insight into Geographic Differences):
    
print(avg_by_region)
#
Visualization: Performance Comparisons
#
##Top 5 and Bottom 5 Measures (Across All Time/States)
measure_performance <- HCAHPS_ANALYSIS_DATA %>%
  group_by(Measure, Type) %>%
  summarise(
    Avg_Top_Box_Pct = mean(Top_Box_Pct, na.rm = TRUE),
    .groups = 'drop'
  ) %>%
  arrange(desc(Avg_Top_Box_Pct))

top_measures <- head(measure_performance, 5)
bottom_measures <- tail(measure_performance, 5)
combined_measures <- bind_rows(top_measures, bottom_measures)

plot_measure_performance <- ggplot(combined_measures, 
                                   aes(x = reorder(Measure, Avg_Top_Box_Pct), 
                                       y = Avg_Top_Box_Pct, fill = Type)) +
  geom_bar(stat = "identity", color = "black", size = 0.5) +
  geom_text(aes(label = paste0(round(Avg_Top_Box_Pct, 1), "%")), 
            hjust = -0.1, size = 3) +
  coord_flip() +
  scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 20),
                     name = "Average Top-Box Percentage") +
  scale_fill_manual(values = c("Composite Measure" = "#4e79a7", 
                               "Global Item" = "#f28e2b", 
                               "Individual Item" = "#e15759")) +
  labs(title = "Best and Worst Performing HCAHPS Measures",
       subtitle = "Average Top-Box Percentage (Highest Patient Satisfaction)",
       x = "Measure") +
  theme_minimal(base_size = 10) +
  theme(plot.title = element_text(face = "bold"),
        axis.text.y = element_text(size = 10))
  
print(plot_measure_performance) 



##Top 5 and Bottom 5 States (Across All Time/Measures)
state_performance <- HCAHPS_ANALYSIS_DATA %>%
  group_by(State_Name, Region) %>%
  summarise(
    Avg_Top_Box_Pct = mean(Top_Box_Pct, na.rm = TRUE),
    .groups = 'drop'
  ) %>%
  arrange(desc(Avg_Top_Box_Pct))

top_states <- head(state_performance, 5)
bottom_states <- tail(state_performance, 5)
combined_states <- bind_rows(top_states, bottom_states)

plot_state_performance <- ggplot(combined_states, 
                                 aes(x = reorder(State_Name, Avg_Top_Box_Pct), 
                                     y = Avg_Top_Box_Pct, fill = Region)) +
  geom_bar(stat = "identity", color = "white") +
  geom_text(aes(label = paste0(round(Avg_Top_Box_Pct, 1), "%")), 
            hjust = -0.1, size = 3) +
  coord_flip() +
  scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 20),
                     name = "Average Top-Box Percentage") +
  labs(title = "Top and Bottom 5 States for Patient Satisfaction",
       subtitle = "Average Top-Box Percentage (All Measures Combined)",
       x = "State") +
  theme_bw(base_size = 10) +
  scale_fill_brewer(palette = "Set2") +
  theme(plot.title = element_text(face = "bold"),
        legend.position = "bottom")
        
print(plot_state_performance)

#
Trend over Time for Select Measures
#
## Calculating the national average Top-Box Percentage for each unique Measure (Measure_Name) in each reporting period (Numeric_Time)
df_trend <- HCAHPS_ANALYSIS_DATA %>%
  group_by(Numeric_Time, Measure) %>%
  summarise(
    National_Avg_Pct = mean(Top_Box_Pct, na.rm = TRUE),
    .groups = 'drop'
  )

## Identify the consistently highest and lowest performing measures to highlight in the plot (optional subsetting for cleaner visual)
top_measures <- df_trend %>%
  group_by(Measure) %>%
  summarise(Avg_Pct = mean(National_Avg_Pct)) %>%
  slice_max(Avg_Pct, n = 3) %>%
  pull(Measure)

bottom_measures <- df_trend %>%
  group_by(Measure) %>%
  summarise(Avg_Pct = mean(National_Avg_Pct)) %>%
  slice_min(Avg_Pct, n = 3) %>%
  pull(Measure)

## Combining the measures to focus on
highlight_measures <- unique(c(top_measures, bottom_measures))

df_trend_highlight <- df_trend %>%
  filter(Measure %in% highlight_measures)

time_breaks <- unique(df_trend$Numeric_Time)
custom_breaks <- time_breaks[c(1, 5, 9)]

trend_plot <- ggplot(df_trend_highlight, 
                     aes(x = Numeric_Time, y = National_Avg_Pct, 
                         color = Measure, group = Measure)) +
  geom_line(linewidth = 1.2) +
  geom_point(size = 3) +
  # Custom y-axis to show percentages
  scale_y_continuous(labels = label_percent(scale = 1, suffix = "%"), 
                     name = "Average Top-Box Percentage") +
  # Custom x-axis to map numeric time back to visible years
  scale_x_continuous(breaks = custom_breaks, 
                     labels = c("2015", "2019", "2023"),
                     name = "Report Period (Year)") +
  labs(title = "National Trend in Patient Satisfaction Over Time (2015 - 2023)",
       subtitle = "Comparing Consistently High and Low Performing Measures",
       color = "Measure") +
  theme_classic(base_size = 10) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5),
        legend.position = "bottom")

print(trend_plot)


cat("\n--- EDA Complete ---\n")

--- EDA Complete ---
#

4. Statistical Modeling

#install.packages("lme4")
#install.packages("car")
#install.packages("broom.mixed")

library(tidyverse)
library(lme4) 
library(broom.mixed)
ANOVA by Measure Type
  • If the P-value is very small (e.g., < 0.001), we reject H0. This confirms that the type of measure (e.g., Composite vs. Global) significantly impacts satisfaction scores.
  • H0: The mean Top-Box Percentage is the same for all Measure Types (Composite, Individual, Global).
  • Ha: At least one mean is different.
cat("\n--- 1. ANOVA: Top-Box Percentage by Measure Type ---\n")

--- 1. ANOVA: Top-Box Percentage by Measure Type ---
aov_measure_type <- aov(Top_Box_Pct ~ Type, data = HCAHPS_ANALYSIS_DATA)
summary_aov_type <- summary(aov_measure_type)
print(summary_aov_type)
              Df Sum Sq Mean Sq F value Pr(>F)    
Type           2  14320    7160   69.17 <2e-16 ***
Residuals   4577 473760     104                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
## Post-Hoc Test (Tukey's HSD): Check the P-value. If it's less than 0.05, the differences are significant.
if (summary_aov_type[[1]]$`Pr(>F)`[1] < 0.05) {
  cat("\n-- Post-Hoc (Tukey HSD) for Measure Type (Measures that are significantly different) --\n")
  tukey_type <- TukeyHSD(aov_measure_type)
  print(tukey_type)
  } else {
  cat("\nANOVA P-value is > 0.05. No statistically significant difference between measure types found.\n")
    }

-- Post-Hoc (Tukey HSD) for Measure Type (Measures that are significantly different) --
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = Top_Box_Pct ~ Type, data = HCAHPS_ANALYSIS_DATA)

$Type
                                        diff       lwr         upr     p adj
Global Item-Composite Measure     -0.8540757 -1.764102  0.05595103 0.0712129
Individual Item-Composite Measure -4.5560408 -5.466067 -3.64601404 0.0000000
Individual Item-Global Item       -3.7019651 -4.816516 -2.58741451 0.0000000
# Visualization of Box Plot
aov_type_plot <- HCAHPS_ANALYSIS_DATA %>%
  ggplot(aes(x = Type, y = Top_Box_Pct, fill = Type)) +
  geom_boxplot(alpha = 0.8, outlier.shape = NA) +
  geom_jitter(width = 0.2, alpha = 0.1, color = "black") +
  labs(
    title = "Patient Satisfaction (Top-Box %) Distribution by Type",
    subtitle = "ANOVA analysis confirms if these observed differences are statistically significant.",
    x = "HCAHPS Measure Category",
    y = "Top-Box Percentage (%)",
    fill = "Type"
  ) +
  scale_y_continuous(limits = c(30, 100)) + # Set limits for better comparison
  theme_minimal(base_size = 10) +
  theme(plot.title = element_text(face = "bold"),
        legend.position = "none")

print(aov_type_plot)

ANOVA by US Census Region
  • H0: The mean Top-Box Percentage is the same across all US Census Regions.
  • If the P-value is small, it confirms significant geographical differences in patient satisfaction.
cat("\n--- ANOVA: Top-Box Percentage by Region ---\n")

--- ANOVA: Top-Box Percentage by Region ---
aov_region <- aov(Top_Box_Pct ~ Region, data = HCAHPS_ANALYSIS_DATA)
summary_aov_region <- summary(aov_region)
print(summary_aov_region)
              Df Sum Sq Mean Sq F value Pr(>F)    
Region         8  21235  2654.3   25.99 <2e-16 ***
Residuals   4571 466845   102.1                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# Post-Hoc Test (Tukey's HSD) for Regional differences:
if (summary_aov_region[[1]]$`Pr(>F)`[1] < 0.05) {
  cat("\n-- Post-Hoc (Tukey HSD) for Region --\n")
  tukey_region <- TukeyHSD(aov_region)
  print(tukey_region)
}

-- Post-Hoc (Tukey HSD) for Region --
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = Top_Box_Pct ~ Region, data = HCAHPS_ANALYSIS_DATA)

$Region
                                             diff        lwr        upr     p adj
East South Central-East North Central -0.02166667 -2.2392475  2.1959142 1.0000000
Mid-Atlantic-East North Central       -5.08370370 -7.4978999 -2.6695075 0.0000000
Mountain-East North Central           -1.22583333 -3.1104147  0.6587480 0.5303374
New England-East North Central        -1.21148148 -3.2132273  0.7902643 0.6290293
Pacific-East North Central            -2.42888889 -4.5196442 -0.3381336 0.0095679
South Atlantic-East North Central     -3.56125000 -5.4092340 -1.7132660 0.0000001
West North Central-East North Central  2.51365079  0.5779875  4.4493140 0.0018589
West South Central-East North Central  1.32277778 -0.8948031  3.5403586 0.6477020
Mid-Atlantic-East South Central       -5.06203704 -7.5868639 -2.5372102 0.0000001
Mountain-East South Central           -1.20416667 -3.2285318  0.8201984 0.6512329
New England-East South Central        -1.18981481 -3.3236830  0.9440533 0.7277900
Pacific-East South Central            -2.40722222 -4.6248031 -0.1896414 0.0217036
South Atlantic-East South Central     -3.53958333 -5.5299231 -1.5492436 0.0000013
West North Central-East South Central  2.53531746  0.4633137  4.6073212 0.0046815
West South Central-East South Central  1.34444444 -0.9930910  3.6819799 0.6924107
Mountain-Mid-Atlantic                  3.85787037  1.6198506  6.0958902 0.0000033
New England-Mid-Atlantic               3.87222222  1.5346868  6.2097577 0.0000102
Pacific-Mid-Atlantic                   2.65481481  0.2406186  5.0690111 0.0187396
South Atlantic-Mid-Atlantic            1.52245370 -0.6848367  3.7297441 0.4456123
West North Central-Mid-Atlantic        7.59735450  5.3161535  9.8785555 0.0000000
West South Central-Mid-Atlantic        6.40648148  3.8816546  8.9313083 0.0000000
New England-Mountain                   0.01435185 -1.7709703  1.7996740 1.0000000
Pacific-Mountain                      -1.20305556 -3.0876369  0.6815258 0.5568065
South Atlantic-Mountain               -2.33541667 -3.9464518 -0.7243815 0.0002412
West North Central-Mountain            3.73948413  2.0285834  5.4503849 0.0000000
West South Central-Mountain            2.54861111  0.5242460  4.5729762 0.0030519
Pacific-New England                   -1.21740741 -3.2191532  0.7843384 0.6226460
South Atlantic-New England            -2.34976852 -4.0964149 -0.6031221 0.0010141
West North Central-New England         3.72513228  1.8859692  5.5642953 0.0000001
West South Central-New England         2.53425926  0.4003911  4.6681274 0.0071310
South Atlantic-Pacific                -1.13236111 -2.9803451  0.7156229 0.6127308
West North Central-Pacific             4.94253968  3.0068764  6.8782029 0.0000000
West South Central-Pacific             3.75166667  1.5340858  5.9692475 0.0000057
West North Central-South Atlantic      6.07490079  4.4043980  7.7454036 0.0000000
West South Central-South Atlantic      4.88402778  2.8936881  6.8743675 0.0000000
West South Central-West North Central -1.19087302 -3.2628767  0.8811307 0.6932527
region_aov_plot <- HCAHPS_ANALYSIS_DATA %>%
  ggplot(aes(x = Region, y = Top_Box_Pct, fill = Region)) +
  geom_boxplot(alpha = 0.7, show.legend = FALSE) +
  labs(
    title = "Patient Satisfaction Distribution Across US Regions",
    subtitle = "Confirmed by ANOVA and Tukey Post-Hoc Test",
    x = "US Census Region",
    y = "Top-Box Percentage (%)"
  ) +
  theme_minimal(base_size = 14) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

print(region_aov_plot)


aov_region <- aov(Top_Box_Pct ~ Region, data = HCAHPS_ANALYSIS_DATA)
print(summary(aov_region))
              Df Sum Sq Mean Sq F value Pr(>F)    
Region         8  21235  2654.3   25.99 <2e-16 ***
Residuals   4571 466845   102.1                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
— Regression Analysis: Impact of Response Volume —

This is to determine if states with higher response rates or completed surveys report different levels of patient satisfaction.

  • The P-value for ‘Average_Response_Rate’ tells us if the response rate is a statistically significant predictor of patient satisfaction.
  • The coefficient estimate tells the direction of the relationship (positive or negative).
cat("\n--- Linear Regression: Predicting Top-Box % with Response Rate ---\n")

--- Linear Regression: Predicting Top-Box % with Response Rate ---
lm_response_rate <- lm(Top_Box_Pct ~ Average_Response_Rate, 
                       data = HCAHPS_ANALYSIS_DATA)
print(lm_response_rate)

Call:
lm(formula = Top_Box_Pct ~ Average_Response_Rate, data = HCAHPS_ANALYSIS_DATA)

Coefficients:
          (Intercept)  Average_Response_Rate  
              60.6883                 0.3981  
##Scatter Plot with Regression Line
plot_response_rate <- HCAHPS_ANALYSIS_DATA %>%
  # Filter out potential NA values that might have been introduced during cleaning
  filter(!is.na(Average_Response_Rate)) %>%
  ggplot(aes(x = Average_Response_Rate, y = Top_Box_Pct)) +
  geom_point(alpha = 0.3, color = "#0072B2") +
  # Add the linear regression line
  geom_smooth(method = "lm", color = "#D55E00", linewidth = 1.2, se = TRUE) +
  labs(
    title = "Does Response Rate Predict Patient Satisfaction?",
    subtitle = paste("R-squared:", round(summary_lm_response$r.squared, 4), " | P-value for Slope:", 
                     format.pval(summary_lm_response$coefficients[2, 4], digits = 3)),
    x = "Average Survey Response Rate (%)",
    y = "Average Top-Box Percentage (%)"
  ) +
  scale_y_continuous(labels = scales::label_percent(scale = 1, suffix = "%")) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))
print(plot_response_rate)




cat("\n--- Linear Regression: Predicting Top-Box % with Completed Surveys (Proxy) ---\n")

--- Linear Regression: Predicting Top-Box % with Completed Surveys (Proxy) ---
lm_survey_count <- lm(Top_Box_Pct ~ Median_Surveys_Proxy, 
                      data = HCAHPS_ANALYSIS_DATA)
print(lm_survey_count)

Call:
lm(formula = Top_Box_Pct ~ Median_Surveys_Proxy, data = HCAHPS_ANALYSIS_DATA)

Coefficients:
         (Intercept)  Median_Surveys_Proxy  
            74.23045              -0.01012  
##Scatter Plot with Regression Line
plot_survey_count <- HCAHPS_ANALYSIS_DATA %>%
  filter(!is.na(Median_Surveys_Proxy)) %>%
  ggplot(aes(x = Median_Surveys_Proxy, y = Top_Box_Pct)) +
  geom_point(alpha = 0.3, color = "#0072B2") +
  # Add the linear regression line
  geom_smooth(method = "lm", color = "#D55E00", linewidth = 1.2, se = TRUE) +
  labs(
    title = "Does Survey Volume Predict Patient Satisfaction?",
    subtitle = paste("R-squared:", round(summary_lm_surveys$r.squared, 4), " | P-value for Slope:", 
                     format.pval(summary_lm_surveys$coefficients[2, 4], digits = 3)),
    x = "Median Completed Surveys (Numeric Proxy)",
    y = "Average Top-Box Percentage (%)"
  ) +
  scale_y_continuous(labels = scales::label_percent(scale = 1, suffix = "%")) +
  theme(plot.title = element_text(face = "bold", hjust = 0.5),
        plot.subtitle = element_text(hjust = 0.5))
print(plot_survey_count)

#
— Time Series Trend Modeling —

This is to quantify the average annual change in Top-Box Percentage over the entire period. The ‘Numeric_Time’ variable is used as the predictor. The coefficient of Numeric_Time represents the change per unit of time (approximately 1 year).

  • P-value for Numeric_Time: Determines if the trend is statistically significant.
  • Coefficient Estimate for Numeric_Time: Represents the estimated annual change in the Top-Box Percentage. If estimate is 0.5, satisfaction is increasing by 0.5 percentage points per year.
cat("\n--- 5. Time Series Regression: Trend Over Time ---\n")

--- 5. Time Series Regression: Trend Over Time ---
lm_time_trend <- lm(Top_Box_Pct ~ Numeric_Time, data = HCAHPS_ANALYSIS_DATA)
summary_lm_time <- summary(lm_time_trend)
print(summary_lm_time)

Call:
lm(formula = Top_Box_Pct ~ Numeric_Time, data = HCAHPS_ANALYSIS_DATA)

Residuals:
    Min      1Q  Median      3Q     Max 
-29.737  -6.231   0.465   8.263  19.870 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   76.3385     2.9294  26.059   <2e-16 ***
Numeric_Time  -0.1011     0.0591  -1.711   0.0871 .  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 10.32 on 4578 degrees of freedom
Multiple R-squared:  0.0006393, Adjusted R-squared:  0.000421 
F-statistic: 2.929 on 1 and 4578 DF,  p-value: 0.08709
national_trend_data <- HCAHPS_ANALYSIS_DATA %>%
  group_by(Numeric_Time, Start_Date) %>%
  summarise(Avg_Top_Box_Pct = mean(Top_Box_Pct, na.rm = TRUE), .groups = 'drop') %>%
  mutate(Start_Date = as.Date(Start_Date, format = "%Y-%m-%d"))

time_trend_plot <- national_trend_data %>%
  ggplot(aes(x = Start_Date, y = Avg_Top_Box_Pct)) +
  geom_line(color = "#10b981", linewidth = 1) +
  geom_point(color = "#059669", size = 2) +
  geom_smooth(method = "lm", se = TRUE, color = "#ef4444", linewidth = 0.5, linetype = "dashed") +
  labs(
    title = "National Patient Satisfaction Trend with Linear Fit",
    subtitle = "The slope of the dashed line corresponds to the Numeric_Time coefficient.",
    x = "Reporting Period",
    y = "Average Top-Box Percentage (%)"
  ) +
  theme_light(base_size = 14)

print(time_trend_plot)


lm_time_trend <- lm(Top_Box_Pct ~ Numeric_Time, data = HCAHPS_ANALYSIS_DATA)
print(summary(lm_time_trend))

Call:
lm(formula = Top_Box_Pct ~ Numeric_Time, data = HCAHPS_ANALYSIS_DATA)

Residuals:
    Min      1Q  Median      3Q     Max 
-29.737  -6.231   0.465   8.263  19.870 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   76.3385     2.9294  26.059   <2e-16 ***
Numeric_Time  -0.1011     0.0591  -1.711   0.0871 .  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 10.32 on 4578 degrees of freedom
Multiple R-squared:  0.0006393, Adjusted R-squared:  0.000421 
F-statistic: 2.929 on 1 and 4578 DF,  p-value: 0.08709

Relationship Plot

cat("\n--- 3. Relationship Visualization: Top-Box % vs. Average Response Rate ---\n")

--- 3. Relationship Visualization: Top-Box % vs. Average Response Rate ---
# Plot the simple linear regression of Top-Box % vs. Average_Response_Rate.
response_rate_plot <- HCAHPS_ANALYSIS_DATA %>%
  ggplot(aes(x = Average_Response_Rate, y = Top_Box_Pct)) +
  # Use transparency for geom_point because data points overlap
  geom_point(alpha = 0.2, color = "#2563eb") + 
  geom_smooth(method = "lm", color = "#4c1d95", fill = "#57d2fe") + # Add regression line
  labs(
    title = "Does Response Rate Predict Patient Satisfaction?",
    subtitle = "Scatter plot with fitted linear regression line (Model 2.1)",
    x = "Average Response Rate (%)",
    y = "Top-Box Percentage (%)"
  ) +
  theme_minimal(base_size = 10)

print(response_rate_plot)


lm_response_rate <- lm(Top_Box_Pct ~ Average_Response_Rate, data = HCAHPS_ANALYSIS_DATA)
print(summary(lm_response_rate))

Call:
lm(formula = Top_Box_Pct ~ Average_Response_Rate, data = HCAHPS_ANALYSIS_DATA)

Residuals:
     Min       1Q   Median       3Q      Max 
-28.4699  -6.1736   0.5404   7.9713  20.0966 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)    
(Intercept)           60.68831    0.85483   71.00   <2e-16 ***
Average_Response_Rate  0.39809    0.03148   12.65   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 10.15 on 4578 degrees of freedom
Multiple R-squared:  0.03376,   Adjusted R-squared:  0.03355 
F-statistic:   160 on 1 and 4578 DF,  p-value: < 2.2e-16
LS0tDQp0aXRsZTogIkhDQUhQUyAoSG9zcGl0YWwgQ29uc3VtZXIgQXNzZXNzbWVudCBvZiBIZWFsdGhjYXJlIFByb3ZpZGVycyBhbmQgU3lzdGVtcykiDQphdXRob3I6IGJ5IE1hcnRpbnMgTy4NCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQpib2R5eyAvKiBOb3JtYWwgdGV4dCAqLw0KICBmb250LWZhbWlseTogSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjsNCiAgfQ0KaDEsIGgyLCBoMywgaDQsIGg1LCBoNiB7IC8qIEhlYWRlcnMgKi8NCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIH0NCmNvZGUucnsgLyogUiBjb2RlIGJsb2NrcyAqLw0KICBmb250LWZhbWlseTogIkNvdXJpZXIgTmV3IiwgQ291cmllciwgbW9ub3NwYWNlOw0KICB9DQpwcmUgeyAvKiBDb2RlIGJsb2NrIHNwYWNpbmcgKi8NCiAgZm9udC1mYW1pbHk6ICJDb3VyaWVyIE5ldyIsIENvdXJpZXIsIG1vbm9zcGFjZTsNCiAgfQ0KPC9zdHlsZT4NCg0KLS0tDQoNCkRhdGEgc291cmNlOiBodHRwczovL21hdmVuYW5hbHl0aWNzLmlvL2RhdGEtcGxheWdyb3VuZC9oY2FocHMtcGF0aWVudC1zdXJ2ZXkNCg0KLS0tDQoNCiMjIyBBLiBQcmVsaW1pbmFyeSBTdW1tYXJ5IG9mIHRoZSBEYXRhc2V0DQoNClRoZSBIQ0FIUFMgUGF0aWVudCBTdXJ2ZXkgZGF0YXNldCBjb250YWlucyBhcHByb3hpbWF0ZWx5IDQsMDAwIHRvIDUsMDAwIHJlY29yZHMgKGVhY2ggcmVwcmVzZW50aW5nIGFuIGluZGl2aWR1YWwgaG9zcGl0YWwgb3IgaGVhbHRoY2FyZSBmYWNpbGl0eSkgYW5kIGFyb3VuZCAyMOKAkzI1IGNvbHVtbnMgZGVzY3JpYmluZyBwYXRpZW50IGV4cGVyaWVuY2UgYW5kIGhvc3BpdGFsIHBlcmZvcm1hbmNlLiBBbW9uZyB0aGVzZSwgcm91Z2hseSAxMuKAkzE1IGNvbHVtbnMgYXJlIG51bWVyaWMgdmFyaWFibGVzLCBpbmNsdWRpbmc6DQoNCi0gU3VydmV5IHJlc3BvbnNlIHJhdGUgKCUpOiBtZWFuIOKJiCAzMiUsIHJhbmdlIDEw4oCTODAlLg0KLSBPdmVyYWxsIGhvc3BpdGFsIHJhdGluZyAoMOKAkzEwIHNjYWxlKTogYXZlcmFnZSDiiYggNzEuNSUsIFNEIOKJiCAxMCUuDQotIFBhdGllbnRzIHJlY29tbWVuZGluZyBob3NwaXRhbCAoJSk6IG1lYW4g4omIIDcyJSwgcmFuZ2UgMzDigJM5NSUuDQotIENvbW11bmljYXRpb24gd2l0aCBudXJzZXMgKCUpOiBtZWFuIOKJiCA3OSUsIFNEIOKJiCA4JS4NCi0gQ29tbXVuaWNhdGlvbiB3aXRoIGRvY3RvcnMgKCUpOiBtZWFuIOKJiCA4MSUsIFNEIOKJiCA3JS4NCi0gQ2xlYW5saW5lc3MgYW5kIHF1aWV0bmVzcyBvZiBob3NwaXRhbCBlbnZpcm9ubWVudCAoJSk6IG1lYW4g4omIIDcwJSwgU0Qg4omIIDEyJS4NCi0gRGlzY2hhcmdlIGluZm9ybWF0aW9uIGFuZCBzdGFmZiByZXNwb25zaXZlbmVzcyBzY29yZXMgKCUpOiBtZWFuIOKJiCA3NyUsIFNEIOKJiCA5JS4NCg0KKipDYXRlZ29yaWNhbCB2YXJpYWJsZXMgaW5jbHVkZToqKg0KDQoxLiBIb3NwaXRhbCBOYW1lICjiiYg0LDAwMCB1bmlxdWUgdmFsdWVzKQ0KMi4gU3RhdGUgKOKJiDUwIHVuaXF1ZSB2YWx1ZXMpDQozLiBDaXR5ICjiiYgyLDAwMCB1bmlxdWUgdmFsdWVzKQ0KNC4gU3VydmV5IFF1ZXN0aW9uIENhdGVnb3J5ICjiiYgxMOKAkzEyIHVuaXF1ZSB2YWx1ZXMpDQoNCl9BYm91dCA14oCTMTAlIG9mIGNlbGxzIGNvbnRhaW4gbWlzc2luZyB2YWx1ZXMsIG1vc3RseSBpbiBob3NwaXRhbHMgd2l0aCBsb3cgcmVzcG9uc2UgY291bnRzIG9yIHN1cHByZXNzZWQgcmVzdWx0cy5fDQoNCi0tLQ0KDQojIyMgMS4gRGF0YSBpbXBvcnRhdGlvbiBhbmQgd3JhbmdsaW5nDQoNCmBgYHtyfQ0KIw0KI0luc3RhbGwgYW5kIExvYWQgUmVxdWlyZWQgUGFja2FnZXMNCiNpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQoNCiNJbXBvcnQgZGF0YXNldA0KZGZfcmVzcG9uc2VzIDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9ERUxMIFhQUyAxMy9Eb3dubG9hZHMvSENBSFBTK1BhdGllbnQrU3VydmV5L2RhdGFfdGFibGVzL3Jlc3BvbnNlcy5jc3YiKQ0KZGZfcXVlc3Rpb25zIDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9ERUxMIFhQUyAxMy9Eb3dubG9hZHMvSENBSFBTK1BhdGllbnQrU3VydmV5L2RhdGFfdGFibGVzL3F1ZXN0aW9ucy5jc3YiKQ0KZGZfc3RhdGVfcmVzdWx0cyA8LSByZWFkX2NzdigiQzovVXNlcnMvREVMTCBYUFMgMTMvRG93bmxvYWRzL0hDQUhQUytQYXRpZW50K1N1cnZleS9kYXRhX3RhYmxlcy9zdGF0ZV9yZXN1bHRzLmNzdiIpDQpkZl9zdGF0ZXMgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL0RFTEwgWFBTIDEzL0Rvd25sb2Fkcy9IQ0FIUFMrUGF0aWVudCtTdXJ2ZXkvZGF0YV90YWJsZXMvc3RhdGVzLmNzdiIpDQpkZl9tZWFzdXJlcyA8LSByZWFkX2NzdigiQzovVXNlcnMvREVMTCBYUFMgMTMvRG93bmxvYWRzL0hDQUhQUytQYXRpZW50K1N1cnZleS9kYXRhX3RhYmxlcy9tZWFzdXJlcy5jc3YiKQ0KZGZfcmVwb3J0cyA8LSByZWFkX2NzdigiQzovVXNlcnMvREVMTCBYUFMgMTMvRG93bmxvYWRzL0hDQUhQUytQYXRpZW50K1N1cnZleS9kYXRhX3RhYmxlcy9yZXBvcnRzLmNzdiIpDQoNCiNMb2FkaW5nIGNvbmZpcm1hdGlvbiANCmNhdCgiLS0tIERhdGEgTG9hZGluZyBDb21wbGV0ZSAtLS1cbiIpDQojDQpgYGANCg0KIyMjIyMjIFN1bW1hcnkgb2YgaW1wb3J0ZWQgZGF0YXNldHMNCg0KYGBge3J9DQojDQpkaW1zX21hdHJpeCA8LSBzYXBwbHkobGlzdChzdGF0ZV9yZXN1bHRzID0gZGZfc3RhdGVfcmVzdWx0cywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZXMgPSBkZl9zdGF0ZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZXMgPSBkZl9tZWFzdXJlcywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICByZXBvcnRzID0gZGZfcmVwb3J0cywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gZGZfcmVzcG9uc2VzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVlc3Rpb25zID0gZGZfcXVlc3Rpb25zKSwNCiAgICAgICAgICAgICAgICAgICAgICBkaW0pDQoNCiMgQ29udmVydCB0byBhIGRhdGEgZnJhbWUgYW5kIHRyYW5zcG9zZSBmb3IgYmV0dGVyIHJlYWRhYmlsaXR5DQpkaW1zX3RhYmxlIDwtIGFzLmRhdGEuZnJhbWUodChkaW1zX21hdHJpeCkpDQpjb2xuYW1lcyhkaW1zX3RhYmxlKSA8LSBjKCJSb3dzIiwgIkNvbHVtbnMiKSAjIFJlbmFtZSBjb2x1bW5zIGZvciBjbGFyaXR5DQoNCmNhdCgiRGltZW5zaW9ucyBvZiBtYWluIHRhYmxlczoNCiAgICBcbiIpDQoNCnByaW50KGRpbXNfdGFibGUpDQojDQpgYGANCg0KIyMjIyMjIERhdGEgQ2xlYW5pbmcgKDEpDQpgYGB7cn0NCiMNCmRmX2FuYWx5c2lzIDwtIGRmX3N0YXRlX3Jlc3VsdHMgJT4lDQogIGxlZnRfam9pbihkZl9zdGF0ZXMsIGJ5ID0gYygiU3RhdGUiID0gIlN0YXRlIikpICU+JQ0KICBsZWZ0X2pvaW4oZGZfbWVhc3VyZXMsIGJ5ID0gYygiTWVhc3VyZSBJRCIgPSAiTWVhc3VyZSBJRCIpKSAlPiUNCiAgbGVmdF9qb2luKGRmX3JlcG9ydHMsIGJ5ID0gYygiUmVsZWFzZSBQZXJpb2QiID0gIlJlbGVhc2UgUGVyaW9kIikpDQoNCmRmX2FuYWx5c2lzIDwtIGRmX2FuYWx5c2lzICU+JQ0KICByZW5hbWUoDQogICAgU3RhdGVfQWJicmV2aWF0aW9uID0gU3RhdGUsDQogICAgTWVhc3VyZV9JRCA9IGBNZWFzdXJlIElEYCwNCiAgICBCb3R0b21fQm94X1BjdCA9IGBCb3R0b20tYm94IFBlcmNlbnRhZ2VgLA0KICAgIE1pZGRsZV9Cb3hfUGN0ID0gYE1pZGRsZS1ib3ggUGVyY2VudGFnZWAsDQogICAgVG9wX0JveF9QY3QgPSBgVG9wLWJveCBQZXJjZW50YWdlYCwNCiAgICBTdGF0ZV9OYW1lID0gYFN0YXRlIE5hbWVgDQogICAgKSAlPiUNCiAgICBtdXRhdGUoDQogICAgU3RhcnRfRGF0ZSA9IGFzLkRhdGUoYFN0YXJ0IERhdGVgKSwNCiAgICBFbmRfRGF0ZSA9IGFzLkRhdGUoYEVuZCBEYXRlYCksDQogICAgWWVhciA9IGFzLm51bWVyaWMoc3Vic3RyaW5nKGBSZWxlYXNlIFBlcmlvZGAsIDQpKSwNCiAgICBOdW1lcmljX1RpbWUgPSBhcy5udW1lcmljKGFzLkRhdGUocGFzdGUwKHN0cl9zdWIoYFJlbGVhc2UgUGVyaW9kYCwgNCwgNyksICItIiwgc3RyX3N1YihgUmVsZWFzZSBQZXJpb2RgLCAxLCAyKSwgIi0wMSIpLCBmb3JtYXQgPSAiJVktJW0tJWQiKSkgLyAzNjUuMjUNCiAgKQ0KDQpjYXQoIlxuLS0tIFN0cnVjdHVyZSBvZiB0aGUgTWVyZ2VkIERhdGEgLS0tDQogICAgXG4iKQ0KDQpwcmludChnbGltcHNlKGRmX2FuYWx5c2lzKSkNCkhDQUhQU19BTkFMWVNJU19EQVRBIDwtIGRmX2FuYWx5c2lzDQoNCmBgYA0KDQojIyMjIyMgRGF0YSBDbGVhbmluZyAoMikNCg0KYGBge3J9DQojDQpkZl9yZXNwb25zZXNfY2xlYW4gPC0gZGZfcmVzcG9uc2VzICU+JQ0KICBtdXRhdGUoDQogICAgYENvbXBsZXRlZCBTdXJ2ZXlzYCA9IG5hX2lmKGBDb21wbGV0ZWQgU3VydmV5c2AsICJOb3QgQXZhaWxhYmxlIiksDQogICAgYFJlc3BvbnNlIFJhdGUgKCUpYCA9IG5hX2lmKGBSZXNwb25zZSBSYXRlICglKWAsICJOb3QgQXZhaWxhYmxlIikpDQojDQpkZl9yZXNwb25zZXNfY2xlYW4gPC0gZGZfcmVzcG9uc2VzX2NsZWFuICU+JQ0KICBtdXRhdGUoUmVzcG9uc2VfUmF0ZV9OdW0gPSBhcy5udW1lcmljKGBSZXNwb25zZSBSYXRlICglKWApLA0KICAgIENvbXBsZXRlZF9TdXJ2ZXlzX1Byb3h5ID0gY2FzZV93aGVuKA0KICAgICAgYENvbXBsZXRlZCBTdXJ2ZXlzYCA9PSAiRmV3ZXIgdGhhbiAxMDAiIH4gNTAsICAgICAgIyBNaWRwb2ludCBvZiAwLTk5DQogICAgICBgQ29tcGxldGVkIFN1cnZleXNgID09ICJCZXR3ZWVuIDEwMCBhbmQgMjk5IiB+IDIwMCwgIyBNaWRwb2ludCBvZiAxMDAtMjk5DQogICAgICBgQ29tcGxldGVkIFN1cnZleXNgID09ICIzMDAgb3IgbW9yZSIgfiA0MDAsIA0KICAgICAgVFJVRSB+IE5BX3JlYWxfICMgVHJlYXQgYW55IHJlbWFpbmluZyBub24tbWF0Y2ggYXMgTkENCiAgICAgICkNCiAgICApDQojDQpkZl9yZXNwb25zZXNfYWdnIDwtIGRmX3Jlc3BvbnNlc19jbGVhbiAlPiUNCiAgZmlsdGVyKCFpcy5uYShSZXNwb25zZV9SYXRlX051bSkpICU+JSAgICAjIFRoaXMgaXMgdG8gZmlsdGVyIG91dCBOQSB2YWx1ZXMgYmVmb3JlIGFnZ3JlZ2F0aW9uDQogIGdyb3VwX2J5KGBSZWxlYXNlIFBlcmlvZGAsIFN0YXRlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIEF2ZXJhZ2VfUmVzcG9uc2VfUmF0ZSA9IG1lYW4oUmVzcG9uc2VfUmF0ZV9OdW0sIG5hLnJtID0gVFJVRSksDQogICAgTWVkaWFuX1N1cnZleXNfUHJveHkgPSBtZWRpYW4oQ29tcGxldGVkX1N1cnZleXNfUHJveHksIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICdkcm9wJw0KICApDQojDQpIQ0FIUFNfQU5BTFlTSVNfREFUQSA8LSBkZl9hbmFseXNpcyAlPiUNCiAgbGVmdF9qb2luKGRmX3Jlc3BvbnNlc19hZ2csIGJ5ID0gYygiUmVsZWFzZSBQZXJpb2QiLCAiU3RhdGVfQWJicmV2aWF0aW9uIiA9ICJTdGF0ZSIpKQ0KDQojIERhdGEgQ2xlYW5pbmcgb24gdGhlIG1haW4gZGF0YQ0KSENBSFBTX0FOQUxZU0lTX0RBVEEgPC0gSENBSFBTX0FOQUxZU0lTX0RBVEEgJT4lDQogIG11dGF0ZSgNCiAgICBhY3Jvc3MoYyhCb3R0b21fQm94X1BjdCwgTWlkZGxlX0JveF9QY3QsIFRvcF9Cb3hfUGN0KSwgYXMubnVtZXJpYykNCiAgKSAlPiUgbXV0YXRlKA0KICAgIFJlZ2lvbiA9IGFzLmZhY3RvcihSZWdpb24pLA0KICAgIFR5cGUgPSBhcy5mYWN0b3IoVHlwZSksDQogICAgTWVhc3VyZSA9IGFzLmZhY3RvcihNZWFzdXJlKQ0KICApDQoNCnByaW50KGNvbFN1bXMoaXMubmEoSENBSFBTX0FOQUxZU0lTX0RBVEEpKSkNCnByaW50KGdsaW1wc2UoSENBSFBTX0FOQUxZU0lTX0RBVEEpKQ0KDQpjYXQoIlxuDQogICAgLi4uIERhdGEgQ2xlYW5pbmcgYW5kIFByZS1wcm9jZXNzaW5nIGNvbXBsZXRlISBUaGUgSENBSFBTX0FOQUxZU0lTX0RBVEEgaXMgcmVhZHkgZm9yIEVEQSBhbmQgbW9kZWxpbmcgLi4uXG4iKQ0KYGBgDQoNCiMjIyAyLiBFeHBsb3JhdG9yeSBEYXRhIEFuYWx5c2lzIChFREEpDQoNCmBgYHtyfQ0KIw0KI2luc3RhbGwucGFja2FnZXMoInNjYWxlcyIpDQpsaWJyYXJ5KHNjYWxlcykNCg0Kb3ZlcmFsbF9hdmcgPC0gSENBSFBTX0FOQUxZU0lTX0RBVEEgJT4lDQogIHN1bW1hcmlzZShBdmdfVG9wX0JveF9QY3QgPSBtZWFuKFRvcF9Cb3hfUGN0LCBuYS5ybSA9IFRSVUUpKQ0KY2F0KCJPdmVyYWxsIEF2ZXJhZ2UgVG9wLUJveCBQZXJjZW50YWdlIChhY3Jvc3MgYWxsIHN0YXRlcywgbWVhc3VyZXMsIGFuZCBwZXJpb2RzKToNCiAgICBcbiIpDQpwcmludChwYXN0ZTAocm91bmQob3ZlcmFsbF9hdmckQXZnX1RvcF9Cb3hfUGN0LCAyKSwgIiUiKSkNCg0KIyNBdmVyYWdlIFRvcC1Cb3ggUGVyY2VudGFnZSBieSBNZWFzdXJlIFR5cGUNCmF2Z19ieV90eXBlIDwtIEhDQUhQU19BTkFMWVNJU19EQVRBICU+JQ0KICBncm91cF9ieShUeXBlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIEF2Z19Ub3BfQm94X1BjdCA9IG1lYW4oVG9wX0JveF9QY3QsIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICdkcm9wJw0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MoQXZnX1RvcF9Cb3hfUGN0KSkNCmNhdCgiXG5BdmVyYWdlIFRvcC1Cb3ggUGVyY2VudGFnZSBieSBNZWFzdXJlIFR5cGU6DQogICAgXG4iKQ0KcHJpbnQoYXZnX2J5X3R5cGUpDQoNCiMjQXZlcmFnZSBUb3AtQm94IFBlcmNlbnRhZ2UgYnkgVVMgQ2Vuc3VzIFJlZ2lvbg0KYXZnX2J5X3JlZ2lvbiA8LSBIQ0FIUFNfQU5BTFlTSVNfREFUQSAlPiUNCiAgZ3JvdXBfYnkoUmVnaW9uKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIEF2Z19Ub3BfQm94X1BjdCA9IG1lYW4oVG9wX0JveF9QY3QsIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICdkcm9wJw0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MoQXZnX1RvcF9Cb3hfUGN0KSkNCmNhdCgiXG5BdmVyYWdlIFRvcC1Cb3ggUGVyY2VudGFnZSBieSBVUyBDZW5zdXMgUmVnaW9uIChJbml0aWFsIEluc2lnaHQgaW50byBHZW9ncmFwaGljIERpZmZlcmVuY2VzKToNCiAgICBcbiIpDQpwcmludChhdmdfYnlfcmVnaW9uKQ0KIw0KYGBgDQoNCg0KIyMjIyMjIFZpc3VhbGl6YXRpb246IFBlcmZvcm1hbmNlIENvbXBhcmlzb25zDQoNCmBgYHtyfQ0KIw0KIyNUb3AgNSBhbmQgQm90dG9tIDUgTWVhc3VyZXMgKEFjcm9zcyBBbGwgVGltZS9TdGF0ZXMpDQptZWFzdXJlX3BlcmZvcm1hbmNlIDwtIEhDQUhQU19BTkFMWVNJU19EQVRBICU+JQ0KICBncm91cF9ieShNZWFzdXJlLCBUeXBlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIEF2Z19Ub3BfQm94X1BjdCA9IG1lYW4oVG9wX0JveF9QY3QsIG5hLnJtID0gVFJVRSksDQogICAgLmdyb3VwcyA9ICdkcm9wJw0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MoQXZnX1RvcF9Cb3hfUGN0KSkNCg0KdG9wX21lYXN1cmVzIDwtIGhlYWQobWVhc3VyZV9wZXJmb3JtYW5jZSwgNSkNCmJvdHRvbV9tZWFzdXJlcyA8LSB0YWlsKG1lYXN1cmVfcGVyZm9ybWFuY2UsIDUpDQpjb21iaW5lZF9tZWFzdXJlcyA8LSBiaW5kX3Jvd3ModG9wX21lYXN1cmVzLCBib3R0b21fbWVhc3VyZXMpDQoNCnBsb3RfbWVhc3VyZV9wZXJmb3JtYW5jZSA8LSBnZ3Bsb3QoY29tYmluZWRfbWVhc3VyZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IHJlb3JkZXIoTWVhc3VyZSwgQXZnX1RvcF9Cb3hfUGN0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQXZnX1RvcF9Cb3hfUGN0LCBmaWxsID0gVHlwZSkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDAuNSkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHJvdW5kKEF2Z19Ub3BfQm94X1BjdCwgMSksICIlIikpLCANCiAgICAgICAgICAgIGhqdXN0ID0gLTAuMSwgc2l6ZSA9IDMpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTAwKSwgYnJlYWtzID0gc2VxKDAsIDEwMCwgMjApLA0KICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJBdmVyYWdlIFRvcC1Cb3ggUGVyY2VudGFnZSIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiQ29tcG9zaXRlIE1lYXN1cmUiID0gIiM0ZTc5YTciLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR2xvYmFsIEl0ZW0iID0gIiNmMjhlMmIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSW5kaXZpZHVhbCBJdGVtIiA9ICIjZTE1NzU5IikpICsNCiAgbGFicyh0aXRsZSA9ICJCZXN0IGFuZCBXb3JzdCBQZXJmb3JtaW5nIEhDQUhQUyBNZWFzdXJlcyIsDQogICAgICAgc3VidGl0bGUgPSAiQXZlcmFnZSBUb3AtQm94IFBlcmNlbnRhZ2UgKEhpZ2hlc3QgUGF0aWVudCBTYXRpc2ZhY3Rpb24pIiwNCiAgICAgICB4ID0gIk1lYXN1cmUiKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTApICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwNCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkNCiAgDQpwcmludChwbG90X21lYXN1cmVfcGVyZm9ybWFuY2UpIA0KDQoNCiMjVG9wIDUgYW5kIEJvdHRvbSA1IFN0YXRlcyAoQWNyb3NzIEFsbCBUaW1lL01lYXN1cmVzKQ0Kc3RhdGVfcGVyZm9ybWFuY2UgPC0gSENBSFBTX0FOQUxZU0lTX0RBVEEgJT4lDQogIGdyb3VwX2J5KFN0YXRlX05hbWUsIFJlZ2lvbikgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBBdmdfVG9wX0JveF9QY3QgPSBtZWFuKFRvcF9Cb3hfUGN0LCBuYS5ybSA9IFRSVUUpLA0KICAgIC5ncm91cHMgPSAnZHJvcCcNCiAgKSAlPiUNCiAgYXJyYW5nZShkZXNjKEF2Z19Ub3BfQm94X1BjdCkpDQoNCnRvcF9zdGF0ZXMgPC0gaGVhZChzdGF0ZV9wZXJmb3JtYW5jZSwgNSkNCmJvdHRvbV9zdGF0ZXMgPC0gdGFpbChzdGF0ZV9wZXJmb3JtYW5jZSwgNSkNCmNvbWJpbmVkX3N0YXRlcyA8LSBiaW5kX3Jvd3ModG9wX3N0YXRlcywgYm90dG9tX3N0YXRlcykNCg0KcGxvdF9zdGF0ZV9wZXJmb3JtYW5jZSA8LSBnZ3Bsb3QoY29tYmluZWRfc3RhdGVzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gcmVvcmRlcihTdGF0ZV9OYW1lLCBBdmdfVG9wX0JveF9QY3QpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gQXZnX1RvcF9Cb3hfUGN0LCBmaWxsID0gUmVnaW9uKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgY29sb3IgPSAid2hpdGUiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAocm91bmQoQXZnX1RvcF9Cb3hfUGN0LCAxKSwgIiUiKSksIA0KICAgICAgICAgICAgaGp1c3QgPSAtMC4xLCBzaXplID0gMykgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDApLCBicmVha3MgPSBzZXEoMCwgMTAwLCAyMCksDQogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkF2ZXJhZ2UgVG9wLUJveCBQZXJjZW50YWdlIikgKw0KICBsYWJzKHRpdGxlID0gIlRvcCBhbmQgQm90dG9tIDUgU3RhdGVzIGZvciBQYXRpZW50IFNhdGlzZmFjdGlvbiIsDQogICAgICAgc3VidGl0bGUgPSAiQXZlcmFnZSBUb3AtQm94IFBlcmNlbnRhZ2UgKEFsbCBNZWFzdXJlcyBDb21iaW5lZCkiLA0KICAgICAgIHggPSAiU3RhdGUiKSArDQogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDEwKSArDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQogICAgICAgIA0KcHJpbnQocGxvdF9zdGF0ZV9wZXJmb3JtYW5jZSkNCiMNCmBgYA0KDQojIyMjIyMgVHJlbmQgb3ZlciBUaW1lIGZvciBTZWxlY3QgTWVhc3VyZXMNCg0KYGBge3J9DQojDQojIyBDYWxjdWxhdGluZyB0aGUgbmF0aW9uYWwgYXZlcmFnZSBUb3AtQm94IFBlcmNlbnRhZ2UgZm9yIGVhY2ggdW5pcXVlIE1lYXN1cmUgKE1lYXN1cmVfTmFtZSkgaW4gZWFjaCByZXBvcnRpbmcgcGVyaW9kIChOdW1lcmljX1RpbWUpDQpkZl90cmVuZCA8LSBIQ0FIUFNfQU5BTFlTSVNfREFUQSAlPiUNCiAgZ3JvdXBfYnkoTnVtZXJpY19UaW1lLCBNZWFzdXJlKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE5hdGlvbmFsX0F2Z19QY3QgPSBtZWFuKFRvcF9Cb3hfUGN0LCBuYS5ybSA9IFRSVUUpLA0KICAgIC5ncm91cHMgPSAnZHJvcCcNCiAgKQ0KDQojIyBJZGVudGlmeSB0aGUgY29uc2lzdGVudGx5IGhpZ2hlc3QgYW5kIGxvd2VzdCBwZXJmb3JtaW5nIG1lYXN1cmVzIHRvIGhpZ2hsaWdodCBpbiB0aGUgcGxvdCAob3B0aW9uYWwgc3Vic2V0dGluZyBmb3IgY2xlYW5lciB2aXN1YWwpDQp0b3BfbWVhc3VyZXMgPC0gZGZfdHJlbmQgJT4lDQogIGdyb3VwX2J5KE1lYXN1cmUpICU+JQ0KICBzdW1tYXJpc2UoQXZnX1BjdCA9IG1lYW4oTmF0aW9uYWxfQXZnX1BjdCkpICU+JQ0KICBzbGljZV9tYXgoQXZnX1BjdCwgbiA9IDMpICU+JQ0KICBwdWxsKE1lYXN1cmUpDQoNCmJvdHRvbV9tZWFzdXJlcyA8LSBkZl90cmVuZCAlPiUNCiAgZ3JvdXBfYnkoTWVhc3VyZSkgJT4lDQogIHN1bW1hcmlzZShBdmdfUGN0ID0gbWVhbihOYXRpb25hbF9BdmdfUGN0KSkgJT4lDQogIHNsaWNlX21pbihBdmdfUGN0LCBuID0gMykgJT4lDQogIHB1bGwoTWVhc3VyZSkNCg0KIyMgQ29tYmluaW5nIHRoZSBtZWFzdXJlcyB0byBmb2N1cyBvbg0KaGlnaGxpZ2h0X21lYXN1cmVzIDwtIHVuaXF1ZShjKHRvcF9tZWFzdXJlcywgYm90dG9tX21lYXN1cmVzKSkNCg0KZGZfdHJlbmRfaGlnaGxpZ2h0IDwtIGRmX3RyZW5kICU+JQ0KICBmaWx0ZXIoTWVhc3VyZSAlaW4lIGhpZ2hsaWdodF9tZWFzdXJlcykNCg0KdGltZV9icmVha3MgPC0gdW5pcXVlKGRmX3RyZW5kJE51bWVyaWNfVGltZSkNCmN1c3RvbV9icmVha3MgPC0gdGltZV9icmVha3NbYygxLCA1LCA5KV0NCg0KdHJlbmRfcGxvdCA8LSBnZ3Bsb3QoZGZfdHJlbmRfaGlnaGxpZ2h0LCANCiAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gTnVtZXJpY19UaW1lLCB5ID0gTmF0aW9uYWxfQXZnX1BjdCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBNZWFzdXJlLCBncm91cCA9IE1lYXN1cmUpKSArDQogIGdlb21fbGluZShsaW5ld2lkdGggPSAxLjIpICsNCiAgZ2VvbV9wb2ludChzaXplID0gMykgKw0KICAjIEN1c3RvbSB5LWF4aXMgdG8gc2hvdyBwZXJjZW50YWdlcw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gbGFiZWxfcGVyY2VudChzY2FsZSA9IDEsIHN1ZmZpeCA9ICIlIiksIA0KICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJBdmVyYWdlIFRvcC1Cb3ggUGVyY2VudGFnZSIpICsNCiAgIyBDdXN0b20geC1heGlzIHRvIG1hcCBudW1lcmljIHRpbWUgYmFjayB0byB2aXNpYmxlIHllYXJzDQogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjdXN0b21fYnJlYWtzLCANCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIjIwMTUiLCAiMjAxOSIsICIyMDIzIiksDQogICAgICAgICAgICAgICAgICAgICBuYW1lID0gIlJlcG9ydCBQZXJpb2QgKFllYXIpIikgKw0KICBsYWJzKHRpdGxlID0gIk5hdGlvbmFsIFRyZW5kIGluIFBhdGllbnQgU2F0aXNmYWN0aW9uIE92ZXIgVGltZSAoMjAxNSAtIDIwMjMpIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJDb21wYXJpbmcgQ29uc2lzdGVudGx5IEhpZ2ggYW5kIExvdyBQZXJmb3JtaW5nIE1lYXN1cmVzIiwNCiAgICAgICBjb2xvciA9ICJNZWFzdXJlIikgKw0KICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDEwKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQoNCnByaW50KHRyZW5kX3Bsb3QpDQoNCmNhdCgiXG4tLS0gRURBIENvbXBsZXRlIC0tLVxuIikNCiMNCmBgYA0KDQojIyMgNC4gU3RhdGlzdGljYWwgTW9kZWxpbmcNCmBgYHtyfQ0KI2luc3RhbGwucGFja2FnZXMoImxtZTQiKQ0KI2luc3RhbGwucGFja2FnZXMoImNhciIpDQojaW5zdGFsbC5wYWNrYWdlcygiYnJvb20ubWl4ZWQiKQ0KDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobG1lNCkgDQpsaWJyYXJ5KGJyb29tLm1peGVkKQ0KYGBgDQoNCiMjIyMjIEFOT1ZBIGJ5IE1lYXN1cmUgVHlwZQ0KDQotIElmIHRoZSBQLXZhbHVlIGlzIHZlcnkgc21hbGwgKGUuZy4sIDwgMC4wMDEpLCB3ZSByZWplY3QgSDAuIFRoaXMgY29uZmlybXMgdGhhdCB0aGUgdHlwZSBvZiBtZWFzdXJlIChlLmcuLCBDb21wb3NpdGUgdnMuIEdsb2JhbCkgc2lnbmlmaWNhbnRseSBpbXBhY3RzIHNhdGlzZmFjdGlvbiBzY29yZXMuDQotIEgwOiBUaGUgbWVhbiBUb3AtQm94IFBlcmNlbnRhZ2UgaXMgdGhlIHNhbWUgZm9yIGFsbCBNZWFzdXJlIFR5cGVzIChDb21wb3NpdGUsIEluZGl2aWR1YWwsIEdsb2JhbCkuDQotIEhhOiBBdCBsZWFzdCBvbmUgbWVhbiBpcyBkaWZmZXJlbnQuDQoNCmBgYHtyfQ0KY2F0KCJcbi0tLSAxLiBBTk9WQTogVG9wLUJveCBQZXJjZW50YWdlIGJ5IE1lYXN1cmUgVHlwZSAtLS1cbiIpDQoNCmFvdl9tZWFzdXJlX3R5cGUgPC0gYW92KFRvcF9Cb3hfUGN0IH4gVHlwZSwgZGF0YSA9IEhDQUhQU19BTkFMWVNJU19EQVRBKQ0Kc3VtbWFyeV9hb3ZfdHlwZSA8LSBzdW1tYXJ5KGFvdl9tZWFzdXJlX3R5cGUpDQpwcmludChzdW1tYXJ5X2Fvdl90eXBlKQ0KDQojIyBQb3N0LUhvYyBUZXN0IChUdWtleSdzIEhTRCk6IENoZWNrIHRoZSBQLXZhbHVlLiBJZiBpdCdzIGxlc3MgdGhhbiAwLjA1LCB0aGUgZGlmZmVyZW5jZXMgYXJlIHNpZ25pZmljYW50Lg0KaWYgKHN1bW1hcnlfYW92X3R5cGVbWzFdXSRgUHIoPkYpYFsxXSA8IDAuMDUpIHsNCiAgY2F0KCJcbi0tIFBvc3QtSG9jIChUdWtleSBIU0QpIGZvciBNZWFzdXJlIFR5cGUgKE1lYXN1cmVzIHRoYXQgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50KSAtLVxuIikNCiAgdHVrZXlfdHlwZSA8LSBUdWtleUhTRChhb3ZfbWVhc3VyZV90eXBlKQ0KICBwcmludCh0dWtleV90eXBlKQ0KICB9IGVsc2Ugew0KICBjYXQoIlxuQU5PVkEgUC12YWx1ZSBpcyA+IDAuMDUuIE5vIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIG1lYXN1cmUgdHlwZXMgZm91bmQuXG4iKQ0KICAgIH0NCg0KIyBWaXN1YWxpemF0aW9uIG9mIEJveCBQbG90DQphb3ZfdHlwZV9wbG90IDwtIEhDQUhQU19BTkFMWVNJU19EQVRBICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBUeXBlLCB5ID0gVG9wX0JveF9QY3QsIGZpbGwgPSBUeXBlKSkgKw0KICBnZW9tX2JveHBsb3QoYWxwaGEgPSAwLjgsIG91dGxpZXIuc2hhcGUgPSBOQSkgKw0KICBnZW9tX2ppdHRlcih3aWR0aCA9IDAuMiwgYWxwaGEgPSAwLjEsIGNvbG9yID0gImJsYWNrIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIlBhdGllbnQgU2F0aXNmYWN0aW9uIChUb3AtQm94ICUpIERpc3RyaWJ1dGlvbiBieSBUeXBlIiwNCiAgICBzdWJ0aXRsZSA9ICJBTk9WQSBhbmFseXNpcyBjb25maXJtcyBpZiB0aGVzZSBvYnNlcnZlZCBkaWZmZXJlbmNlcyBhcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4iLA0KICAgIHggPSAiSENBSFBTIE1lYXN1cmUgQ2F0ZWdvcnkiLA0KICAgIHkgPSAiVG9wLUJveCBQZXJjZW50YWdlICglKSIsDQogICAgZmlsbCA9ICJUeXBlIg0KICApICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMzAsIDEwMCkpICsgIyBTZXQgbGltaXRzIGZvciBiZXR0ZXIgY29tcGFyaXNvbg0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksDQogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KcHJpbnQoYW92X3R5cGVfcGxvdCkNCmBgYA0KDQojIyMjIyBBTk9WQSBieSBVUyBDZW5zdXMgUmVnaW9uDQoNCi0gSDA6IFRoZSBtZWFuIFRvcC1Cb3ggUGVyY2VudGFnZSBpcyB0aGUgc2FtZSBhY3Jvc3MgYWxsIFVTIENlbnN1cyBSZWdpb25zLg0KLSBJZiB0aGUgUC12YWx1ZSBpcyBzbWFsbCwgaXQgY29uZmlybXMgc2lnbmlmaWNhbnQgZ2VvZ3JhcGhpY2FsIGRpZmZlcmVuY2VzIGluIHBhdGllbnQgc2F0aXNmYWN0aW9uLg0KDQpgYGB7cn0NCmNhdCgiXG4tLS0gQU5PVkE6IFRvcC1Cb3ggUGVyY2VudGFnZSBieSBSZWdpb24gLS0tXG4iKQ0KDQphb3ZfcmVnaW9uIDwtIGFvdihUb3BfQm94X1BjdCB+IFJlZ2lvbiwgZGF0YSA9IEhDQUhQU19BTkFMWVNJU19EQVRBKQ0Kc3VtbWFyeV9hb3ZfcmVnaW9uIDwtIHN1bW1hcnkoYW92X3JlZ2lvbikNCnByaW50KHN1bW1hcnlfYW92X3JlZ2lvbikNCg0KIyBQb3N0LUhvYyBUZXN0IChUdWtleSdzIEhTRCkgZm9yIFJlZ2lvbmFsIGRpZmZlcmVuY2VzOg0KaWYgKHN1bW1hcnlfYW92X3JlZ2lvbltbMV1dJGBQcig+RilgWzFdIDwgMC4wNSkgew0KICBjYXQoIlxuLS0gUG9zdC1Ib2MgKFR1a2V5IEhTRCkgZm9yIFJlZ2lvbiAtLVxuIikNCiAgdHVrZXlfcmVnaW9uIDwtIFR1a2V5SFNEKGFvdl9yZWdpb24pDQogIHByaW50KHR1a2V5X3JlZ2lvbikNCn0NCg0KcmVnaW9uX2Fvdl9wbG90IDwtIEhDQUhQU19BTkFMWVNJU19EQVRBICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBSZWdpb24sIHkgPSBUb3BfQm94X1BjdCwgZmlsbCA9IFJlZ2lvbikpICsNCiAgZ2VvbV9ib3hwbG90KGFscGhhID0gMC43LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiUGF0aWVudCBTYXRpc2ZhY3Rpb24gRGlzdHJpYnV0aW9uIEFjcm9zcyBVUyBSZWdpb25zIiwNCiAgICBzdWJ0aXRsZSA9ICJDb25maXJtZWQgYnkgQU5PVkEgYW5kIFR1a2V5IFBvc3QtSG9jIFRlc3QiLA0KICAgIHggPSAiVVMgQ2Vuc3VzIFJlZ2lvbiIsDQogICAgeSA9ICJUb3AtQm94IFBlcmNlbnRhZ2UgKCUpIg0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxNCkgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KDQpwcmludChyZWdpb25fYW92X3Bsb3QpDQoNCmFvdl9yZWdpb24gPC0gYW92KFRvcF9Cb3hfUGN0IH4gUmVnaW9uLCBkYXRhID0gSENBSFBTX0FOQUxZU0lTX0RBVEEpDQpwcmludChzdW1tYXJ5KGFvdl9yZWdpb24pKQ0KYGBgDQoNCiMjIyMjIC0tLSBSZWdyZXNzaW9uIEFuYWx5c2lzOiBJbXBhY3Qgb2YgUmVzcG9uc2UgVm9sdW1lIC0tLQ0KDQpUaGlzIGlzIHRvIGRldGVybWluZSBpZiBzdGF0ZXMgd2l0aCBoaWdoZXIgcmVzcG9uc2UgcmF0ZXMgb3IgY29tcGxldGVkIHN1cnZleXMgcmVwb3J0IGRpZmZlcmVudCBsZXZlbHMgb2YgcGF0aWVudCBzYXRpc2ZhY3Rpb24uDQoNCi0gVGhlIFAtdmFsdWUgZm9yICdBdmVyYWdlX1Jlc3BvbnNlX1JhdGUnIHRlbGxzIHVzIGlmIHRoZSByZXNwb25zZSByYXRlIGlzIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBwcmVkaWN0b3Igb2YgcGF0aWVudCBzYXRpc2ZhY3Rpb24uDQotIFRoZSBjb2VmZmljaWVudCBlc3RpbWF0ZSB0ZWxscyB0aGUgZGlyZWN0aW9uIG9mIHRoZSByZWxhdGlvbnNoaXAgKHBvc2l0aXZlIG9yIG5lZ2F0aXZlKS4NCg0KYGBge3J9DQpjYXQoIlxuLS0tIExpbmVhciBSZWdyZXNzaW9uOiBQcmVkaWN0aW5nIFRvcC1Cb3ggJSB3aXRoIFJlc3BvbnNlIFJhdGUgLS0tXG4iKQ0KbG1fcmVzcG9uc2VfcmF0ZSA8LSBsbShUb3BfQm94X1BjdCB+IEF2ZXJhZ2VfUmVzcG9uc2VfUmF0ZSwgDQogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBIQ0FIUFNfQU5BTFlTSVNfREFUQSkNCnByaW50KGxtX3Jlc3BvbnNlX3JhdGUpDQoNCiMjU2NhdHRlciBQbG90IHdpdGggUmVncmVzc2lvbiBMaW5lDQpwbG90X3Jlc3BvbnNlX3JhdGUgPC0gSENBSFBTX0FOQUxZU0lTX0RBVEEgJT4lDQogICMgRmlsdGVyIG91dCBwb3RlbnRpYWwgTkEgdmFsdWVzIHRoYXQgbWlnaHQgaGF2ZSBiZWVuIGludHJvZHVjZWQgZHVyaW5nIGNsZWFuaW5nDQogIGZpbHRlcighaXMubmEoQXZlcmFnZV9SZXNwb25zZV9SYXRlKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IEF2ZXJhZ2VfUmVzcG9uc2VfUmF0ZSwgeSA9IFRvcF9Cb3hfUGN0KSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gMC4zLCBjb2xvciA9ICIjMDA3MkIyIikgKw0KICAjIEFkZCB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbGluZQ0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICIjRDU1RTAwIiwgbGluZXdpZHRoID0gMS4yLCBzZSA9IFRSVUUpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEb2VzIFJlc3BvbnNlIFJhdGUgUHJlZGljdCBQYXRpZW50IFNhdGlzZmFjdGlvbj8iLA0KICAgIHN1YnRpdGxlID0gcGFzdGUoIlItc3F1YXJlZDoiLCByb3VuZChzdW1tYXJ5X2xtX3Jlc3BvbnNlJHIuc3F1YXJlZCwgNCksICIgfCBQLXZhbHVlIGZvciBTbG9wZToiLCANCiAgICAgICAgICAgICAgICAgICAgIGZvcm1hdC5wdmFsKHN1bW1hcnlfbG1fcmVzcG9uc2UkY29lZmZpY2llbnRzWzIsIDRdLCBkaWdpdHMgPSAzKSksDQogICAgeCA9ICJBdmVyYWdlIFN1cnZleSBSZXNwb25zZSBSYXRlICglKSIsDQogICAgeSA9ICJBdmVyYWdlIFRvcC1Cb3ggUGVyY2VudGFnZSAoJSkiDQogICkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpsYWJlbF9wZXJjZW50KHNjYWxlID0gMSwgc3VmZml4ID0gIiUiKSkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSwNCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpwcmludChwbG90X3Jlc3BvbnNlX3JhdGUpDQoNCg0KDQpjYXQoIlxuLS0tIExpbmVhciBSZWdyZXNzaW9uOiBQcmVkaWN0aW5nIFRvcC1Cb3ggJSB3aXRoIENvbXBsZXRlZCBTdXJ2ZXlzIChQcm94eSkgLS0tXG4iKQ0KbG1fc3VydmV5X2NvdW50IDwtIGxtKFRvcF9Cb3hfUGN0IH4gTWVkaWFuX1N1cnZleXNfUHJveHksIA0KICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBIQ0FIUFNfQU5BTFlTSVNfREFUQSkNCnByaW50KGxtX3N1cnZleV9jb3VudCkNCg0KIyNTY2F0dGVyIFBsb3Qgd2l0aCBSZWdyZXNzaW9uIExpbmUNCnBsb3Rfc3VydmV5X2NvdW50IDwtIEhDQUhQU19BTkFMWVNJU19EQVRBICU+JQ0KICBmaWx0ZXIoIWlzLm5hKE1lZGlhbl9TdXJ2ZXlzX1Byb3h5KSkgJT4lDQogIGdncGxvdChhZXMoeCA9IE1lZGlhbl9TdXJ2ZXlzX1Byb3h5LCB5ID0gVG9wX0JveF9QY3QpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMsIGNvbG9yID0gIiMwMDcyQjIiKSArDQogICMgQWRkIHRoZSBsaW5lYXIgcmVncmVzc2lvbiBsaW5lDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gIiNENTVFMDAiLCBsaW5ld2lkdGggPSAxLjIsIHNlID0gVFJVRSkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRvZXMgU3VydmV5IFZvbHVtZSBQcmVkaWN0IFBhdGllbnQgU2F0aXNmYWN0aW9uPyIsDQogICAgc3VidGl0bGUgPSBwYXN0ZSgiUi1zcXVhcmVkOiIsIHJvdW5kKHN1bW1hcnlfbG1fc3VydmV5cyRyLnNxdWFyZWQsIDQpLCAiIHwgUC12YWx1ZSBmb3IgU2xvcGU6IiwgDQogICAgICAgICAgICAgICAgICAgICBmb3JtYXQucHZhbChzdW1tYXJ5X2xtX3N1cnZleXMkY29lZmZpY2llbnRzWzIsIDRdLCBkaWdpdHMgPSAzKSksDQogICAgeCA9ICJNZWRpYW4gQ29tcGxldGVkIFN1cnZleXMgKE51bWVyaWMgUHJveHkpIiwNCiAgICB5ID0gIkF2ZXJhZ2UgVG9wLUJveCBQZXJjZW50YWdlICglKSINCiAgKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX3BlcmNlbnQoc2NhbGUgPSAxLCBzdWZmaXggPSAiJSIpKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCnByaW50KHBsb3Rfc3VydmV5X2NvdW50KQ0KIw0KYGBgDQoNCiMjIyMjIC0tLSBUaW1lIFNlcmllcyBUcmVuZCBNb2RlbGluZyAtLS0NCg0KVGhpcyBpcyB0byBxdWFudGlmeSB0aGUgYXZlcmFnZSBhbm51YWwgY2hhbmdlIGluIFRvcC1Cb3ggUGVyY2VudGFnZSBvdmVyIHRoZSBlbnRpcmUgcGVyaW9kLiBUaGUgJ051bWVyaWNfVGltZScgdmFyaWFibGUgaXMgdXNlZCBhcyB0aGUgcHJlZGljdG9yLiBUaGUgY29lZmZpY2llbnQgb2YgTnVtZXJpY19UaW1lIHJlcHJlc2VudHMgdGhlIGNoYW5nZSBwZXIgdW5pdCBvZiB0aW1lIChhcHByb3hpbWF0ZWx5IDEgeWVhcikuDQoNCi0gUC12YWx1ZSBmb3IgTnVtZXJpY19UaW1lOiBEZXRlcm1pbmVzIGlmIHRoZSB0cmVuZCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50Lg0KLSBDb2VmZmljaWVudCBFc3RpbWF0ZSBmb3IgTnVtZXJpY19UaW1lOiBSZXByZXNlbnRzIHRoZSBlc3RpbWF0ZWQgYW5udWFsIGNoYW5nZSBpbiB0aGUgVG9wLUJveCBQZXJjZW50YWdlLiBJZiBlc3RpbWF0ZSBpcyAwLjUsIHNhdGlzZmFjdGlvbiBpcyBpbmNyZWFzaW5nIGJ5IDAuNSBwZXJjZW50YWdlIHBvaW50cyBwZXIgeWVhci4NCg0KYGBge3J9DQpjYXQoIlxuLS0tIDUuIFRpbWUgU2VyaWVzIFJlZ3Jlc3Npb246IFRyZW5kIE92ZXIgVGltZSAtLS1cbiIpDQpsbV90aW1lX3RyZW5kIDwtIGxtKFRvcF9Cb3hfUGN0IH4gTnVtZXJpY19UaW1lLCBkYXRhID0gSENBSFBTX0FOQUxZU0lTX0RBVEEpDQpzdW1tYXJ5X2xtX3RpbWUgPC0gc3VtbWFyeShsbV90aW1lX3RyZW5kKQ0KcHJpbnQoc3VtbWFyeV9sbV90aW1lKQ0KDQpuYXRpb25hbF90cmVuZF9kYXRhIDwtIEhDQUhQU19BTkFMWVNJU19EQVRBICU+JQ0KICBncm91cF9ieShOdW1lcmljX1RpbWUsIFN0YXJ0X0RhdGUpICU+JQ0KICBzdW1tYXJpc2UoQXZnX1RvcF9Cb3hfUGN0ID0gbWVhbihUb3BfQm94X1BjdCwgbmEucm0gPSBUUlVFKSwgLmdyb3VwcyA9ICdkcm9wJykgJT4lDQogIG11dGF0ZShTdGFydF9EYXRlID0gYXMuRGF0ZShTdGFydF9EYXRlLCBmb3JtYXQgPSAiJVktJW0tJWQiKSkNCg0KdGltZV90cmVuZF9wbG90IDwtIG5hdGlvbmFsX3RyZW5kX2RhdGEgJT4lDQogIGdncGxvdChhZXMoeCA9IFN0YXJ0X0RhdGUsIHkgPSBBdmdfVG9wX0JveF9QY3QpKSArDQogIGdlb21fbGluZShjb2xvciA9ICIjMTBiOTgxIiwgbGluZXdpZHRoID0gMSkgKw0KICBnZW9tX3BvaW50KGNvbG9yID0gIiMwNTk2NjkiLCBzaXplID0gMikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUsIGNvbG9yID0gIiNlZjQ0NDQiLCBsaW5ld2lkdGggPSAwLjUsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJOYXRpb25hbCBQYXRpZW50IFNhdGlzZmFjdGlvbiBUcmVuZCB3aXRoIExpbmVhciBGaXQiLA0KICAgIHN1YnRpdGxlID0gIlRoZSBzbG9wZSBvZiB0aGUgZGFzaGVkIGxpbmUgY29ycmVzcG9uZHMgdG8gdGhlIE51bWVyaWNfVGltZSBjb2VmZmljaWVudC4iLA0KICAgIHggPSAiUmVwb3J0aW5nIFBlcmlvZCIsDQogICAgeSA9ICJBdmVyYWdlIFRvcC1Cb3ggUGVyY2VudGFnZSAoJSkiDQogICkgKw0KICB0aGVtZV9saWdodChiYXNlX3NpemUgPSAxNCkNCg0KcHJpbnQodGltZV90cmVuZF9wbG90KQ0KDQpsbV90aW1lX3RyZW5kIDwtIGxtKFRvcF9Cb3hfUGN0IH4gTnVtZXJpY19UaW1lLCBkYXRhID0gSENBSFBTX0FOQUxZU0lTX0RBVEEpDQpwcmludChzdW1tYXJ5KGxtX3RpbWVfdHJlbmQpKQ0KYGBgDQoNCiMjIyBSZWxhdGlvbnNoaXAgUGxvdA0KDQpgYGB7cn0NCmNhdCgiXG4tLS0gMy4gUmVsYXRpb25zaGlwIFZpc3VhbGl6YXRpb246IFRvcC1Cb3ggJSB2cy4gQXZlcmFnZSBSZXNwb25zZSBSYXRlIC0tLVxuIikNCg0KIyBQbG90IHRoZSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gb2YgVG9wLUJveCAlIHZzLiBBdmVyYWdlX1Jlc3BvbnNlX1JhdGUuDQpyZXNwb25zZV9yYXRlX3Bsb3QgPC0gSENBSFBTX0FOQUxZU0lTX0RBVEEgJT4lDQogIGdncGxvdChhZXMoeCA9IEF2ZXJhZ2VfUmVzcG9uc2VfUmF0ZSwgeSA9IFRvcF9Cb3hfUGN0KSkgKw0KICAjIFVzZSB0cmFuc3BhcmVuY3kgZm9yIGdlb21fcG9pbnQgYmVjYXVzZSBkYXRhIHBvaW50cyBvdmVybGFwDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjIsIGNvbG9yID0gIiMyNTYzZWIiKSArIA0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICIjNGMxZDk1IiwgZmlsbCA9ICIjNTdkMmZlIikgKyAjIEFkZCByZWdyZXNzaW9uIGxpbmUNCiAgbGFicygNCiAgICB0aXRsZSA9ICJEb2VzIFJlc3BvbnNlIFJhdGUgUHJlZGljdCBQYXRpZW50IFNhdGlzZmFjdGlvbj8iLA0KICAgIHN1YnRpdGxlID0gIlNjYXR0ZXIgcGxvdCB3aXRoIGZpdHRlZCBsaW5lYXIgcmVncmVzc2lvbiBsaW5lIChNb2RlbCAyLjEpIiwNCiAgICB4ID0gIkF2ZXJhZ2UgUmVzcG9uc2UgUmF0ZSAoJSkiLA0KICAgIHkgPSAiVG9wLUJveCBQZXJjZW50YWdlICglKSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTApDQoNCnByaW50KHJlc3BvbnNlX3JhdGVfcGxvdCkNCg0KbG1fcmVzcG9uc2VfcmF0ZSA8LSBsbShUb3BfQm94X1BjdCB+IEF2ZXJhZ2VfUmVzcG9uc2VfUmF0ZSwgZGF0YSA9IEhDQUhQU19BTkFMWVNJU19EQVRBKQ0KcHJpbnQoc3VtbWFyeShsbV9yZXNwb25zZV9yYXRlKSkNCmBgYA0KDQoNCg0K