1 Abstract

Adult obesity prevalence varies across U.S. counties. This study examines whether county-level geographic differences remain after accounting for measured behavioral, socioeconomic, food-related, and environmental characteristics. County-level data are assembled from the IHME datasets and supporting public data files maintained in the project’s GitHub repository. The primary outcome is an approximate county-level adult obesity prevalence measure calculated as the arithmetic mean of the male and female 2009 IHME county estimates. Predictors are selected from the available county-level measures of physical inactivity, alcohol use, educational attainment, unemployment, household income or wealth, food insecurity, sunlight exposure, environmental quality, and population.

The analysis uses descriptive statistics, exploratory visualizations, multiple ordinary least squares regression, and a state fixed-effects model. Model fit is assessed using adjusted R-squared, root mean squared error, a nested-model comparison, and regression diagnostics. Because the data are observational and aggregated at the county level, all findings are interpreted as associations rather than causal effects. The final interpretation will focus on the amount of variation explained by measured county characteristics and whether adding state indicators provides additional explanatory value.

The numerical findings in this abstract are generated from the current data when the document is knitted. The outcome definition and the years represented by each source must be considered when interpreting the results.

Keywords: adult obesity, county-level analysis, geographic variation, physical inactivity, socioeconomic factors, state fixed effects, spatial disparities

2 1. Introduction

Adult obesity is an important public-health issue in the United States, and prevalence differs across geographic areas. National and state summaries can conceal substantial variation among counties. Counties differ in economic resources, educational attainment, employment conditions, food security, behavioral patterns, and environmental characteristics. These differences provide an important context for examining county-level variation in adult obesity.

Many known characteristics have been associated with obesity, including physical activity, socioeconomic conditions, and food-related circumstances. The purpose of this study is not simply to identify whether these established factors are associated with obesity. Instead, the central question is whether geographic differences among U.S. counties remain after accounting for measured county-level characteristics.

This study combines publicly available county-level data from multiple sources and uses regression modeling to estimate the relationship between adult obesity prevalence and selected explanatory variables. A baseline ordinary least squares (OLS) model is compared with a model that includes state fixed effects. The comparison evaluates whether state-level geographic indicators provide additional explanatory information after adjustment for the measured risk factors.

The analysis is observational. It does not establish that county location or any individual predictor causes obesity. Because the unit of analysis is the county, results describe county-level associations and should not be interpreted as individual-level relationships.

2.1 1.1 Importance of the Study

Understanding geographic differences in obesity may help identify communities where observed prevalence is higher or lower than expected given measured county characteristics. If geographic differences remain after adjustment, this may indicate that additional contextual, policy-related, healthcare, demographic, or spatially patterned factors warrant investigation.

The study also demonstrates how data from multiple public sources can be integrated and analyzed using reproducible statistical methods in R. The emphasis is on model comparison, effect estimates, uncertainty, and diagnostic evaluation rather than statistical significance alone.

3 2. Literature Review

3.1 2.1 Obesity and Geographic Differences

Public-health research has examined obesity in relation to behavioral, socioeconomic, and environmental characteristics. A county-level perspective is useful because counties within the same state can differ substantially in population composition, economic conditions, access to resources, and health-related environments. The present study uses this geographic variation as the focus of its analysis.

3.2 2.2 Behavioral and Socioeconomic Characteristics

Physical activity is an important behavioral characteristic in the study of obesity. County-level differences in physical activity may be associated with differences in obesity prevalence. Economic and educational characteristics may also be related to community resources, opportunities, and health conditions. This study therefore considers physical inactivity, alcohol use, education, unemployment, and household income or wealth as potential explanatory or control variables.

3.4 2.4 Geographic and Spatial Variation

State fixed effects represent systematic differences among states that are not captured by the measured explanatory variables. If the fixed-effects model improves model fit, this suggests that state membership provides additional explanatory information. State fixed effects do not, by themselves, identify local spatial dependence between neighboring counties. A separate spatial-autocorrelation analysis would be required to assess that question.

3.5 2.5 Research Contribution

The contribution of this study is its focus on the amount of county-level geographic variation that remains after adjustment for measured behavioral, socioeconomic, food-related, and environmental characteristics. The study does not claim that the selected predictors or the geographic approach are unprecedented. Rather, it applies a consistent county-level modeling framework to assess the additional explanatory value of state-level geographic indicators.

4 3. Research Questions and Hypotheses

4.1 3.1 Primary Research Question

To what extent do county-level geographic differences in adult obesity prevalence remain after controlling for known behavioral, socioeconomic, food-related, and environmental factors?

4.2 3.2 Supporting Research Questions

  1. How much variation in adult obesity prevalence exists across U.S. counties before accounting for other county-level characteristics?
  2. To what extent are measured behavioral, socioeconomic, food-related, and environmental characteristics associated with county-level adult obesity prevalence?
  3. Does adding state fixed effects improve the explanatory performance of the model after adjustment for the measured characteristics?
  4. Do residual diagnostics indicate important departures from the assumptions of the OLS regression model?

4.3 3.3 Hypotheses

  • H1: County-level adult obesity prevalence varies across U.S. counties.
  • H2: The selected behavioral, socioeconomic, food-related, and environmental characteristics jointly explain a statistically meaningful portion of the variation in county-level adult obesity prevalence.
  • H3: Adding state fixed effects improves model fit beyond the baseline model containing measured county-level characteristics.
  • H4: After adjustment, residuals may still exhibit patterns that indicate unexplained county-level variation. This hypothesis will be evaluated descriptively; state fixed effects alone are not a test of neighboring-county spatial autocorrelation.

5 4. Data and Variables

5.1 4.1 Data Sources

The project repository contains the county-level source files used for this analysis. The files are read directly from the public GitHub repository so the analysis can be reproduced. The principal sources identified in the approved proposal include the Institute for Health Metrics and Evaluation (IHME), U.S. government datasets, the U.S. Environmental Protection Agency, Feeding America, and CDC environmental data.

The data files include:

  • IHME_Obesity.csv
  • IHME_PhysicalActivity.csv
  • AlcoholConsumption.csv
  • Education.csv
  • Unemployment.csv
  • Wealth.csv
  • FoodInsecurity.csv
  • Sunlight.csv
  • EnvironmentalQualityIndex.csv
  • population.csv

The analysis uses only variables that can be identified and merged reliably from the available source files. The code below prints the selected source columns and reports any optional measure that is not found. Missing variables are not silently replaced with unrelated measures.

5.2 4.2 Outcome Variable

The IHME obesity file contains separate male and female county prevalence estimates for 2009. For this analysis, the primary outcome is defined as the arithmetic mean of those two estimates:

\[ \text{Adult Obesity}_{i} = \frac{\text{Male Obesity}_{i,2009}+ \text{Female Obesity}_{i,2009}}{2} \]

This is an approximation, not a population-weighted combined prevalence estimate. A population-weighted overall estimate would require county-level male and female population weights that are aligned to the same year and definition. The outcome is expressed in percentage points.

5.3 4.3 Explanatory Variables

Variable Role Measurement / interpretation
Physical inactivity Behavioral 100 minus the average male/female sufficient physical activity prevalence, where available
Alcohol use Behavioral County-level alcohol-use measure supplied in the project repository
Educational attainment Socioeconomic County-level college or bachelor’s attainment measure
Unemployment Socioeconomic County unemployment rate
Household income / wealth Socioeconomic County-level income or wealth measure
Food insecurity Food-related County-level food-insecurity measure
Sunlight exposure Environmental Average daily sunlight, where available
Environmental quality Environmental Environmental Quality Index, where available
Population Contextual County population; considered as log population in a sensitivity specification
State Geographic State indicator used for fixed effects

5.4 4.4 Geographic Data Integration

County records are matched using standardized state and county names. The original proposal described the use of five-digit FIPS codes. The current repository files do not all expose a consistently named FIPS field, so this version uses a normalized state-plus-county key. This approach avoids matching counties with the same name in different states, but it is not equivalent to a verified FIPS join. The merge diagnostics below report unmatched records and should be reviewed before the results are finalized.

repo_base <- "https://raw.githubusercontent.com/BIKASHBHOWMIK15/Data-698/main/"

read_project_csv <- function(filename) {
  url <- paste0(repo_base, filename)
  tryCatch(
    readr::read_csv(url, show_col_types = FALSE, name_repair = "unique"),
    error = function(e) {
      stop("Could not read ", filename, ". Check the repository filename and internet connection. Details: ",
           conditionMessage(e))
    }
  )
}

normalize_state <- function(x) {
  x <- stringr::str_squish(as.character(x))
  x <- stringr::str_replace_all(x, "\\.", "")
  abbr <- match(toupper(x), state.abb)
  x[!is.na(abbr)] <- state.name[abbr[!is.na(abbr)]]
  dplyr::case_when(
    toupper(x) %in% c("DC", "DISTRICT OF COLUMBIA") ~ "District of Columbia",
    TRUE ~ stringr::str_to_title(x)
  )
}

normalize_county <- function(x) {
  x <- as.character(x)
  x <- stringi::stri_trans_general(x, "Latin-ASCII")
  x <- stringr::str_to_lower(x)
  x <- stringr::str_replace(x, ",.*$", "")
  x <- stringr::str_remove(x, "\\s+(county|parish|borough|census area|municipality)$")
  x <- stringr::str_replace_all(x, "[^a-z0-9]", "")
  x
}

find_column <- function(data, patterns, required = TRUE, label = "variable") {
  nm <- names(data)
  hits <- unique(unlist(lapply(patterns, function(p) {
    which(stringr::str_detect(nm, stringr::regex(p, ignore_case = TRUE)))
  })))
  if (length(hits) == 0) {
    if (required) {
      stop("Could not identify ", label, ". Available columns: ",
           paste(nm, collapse = " | "))
    }
    return(NA_character_)
  }
  nm[hits[1]]
}

standardize_geo <- function(data, source_name = "dataset") {

  original_names <- names(data)

  # Normalize column names: remove spaces, underscores,
  # punctuation, and convert to lowercase
  normalized_names <- tolower(
    gsub("[^a-zA-Z0-9]", "", original_names)
  )

  # Identify state column
  state_idx <- which(
    normalized_names %in% c("state", "stabr", "statename", "stname")
  )[1]

  # Identify county column
  county_idx <- which(
    normalized_names %in% c(
      "county",
      "location",
      "areaname",
      "countyname",
      "countystate",
      "ctyname"
    )
  )[1]

  if (is.na(state_idx)) {
    stop(
      paste0(
        "Could not identify state column in ",
        source_name,
        ". Available columns: ",
        paste(original_names, collapse = " | ")
      )
    )
  }

  if (is.na(county_idx)) {
    stop(
      paste0(
        "Could not identify county column in ",
        source_name,
        ". Available columns: ",
        paste(original_names, collapse = " | ")
      )
    )
  }

  state_original <- original_names[state_idx]
  county_original <- original_names[county_idx]

  data %>%
    mutate(
      State = stringr::str_squish(as.character(.data[[state_original]])),
      County = stringr::str_squish(as.character(.data[[county_original]]))
    ) %>%
    mutate(
      County_key = paste(
        normalize_state(State),
        normalize_county(County),
        sep = "|"
      )
    )
}

numeric_value <- function(x) {
  readr::parse_number(as.character(x), na = c("", "NA", "N/A", "-", "—"))
}

make_one_variable <- function(filename, output_name, patterns,
                              required = FALSE, transform = identity) {
  raw <- read_project_csv(filename)
  geo <- standardize_geo(raw, filename)
  value_col <- find_column(
    geo, patterns, required = required,
    label = paste(output_name, "in", filename)
  )

  if (is.na(value_col)) {
    message("Optional variable not found; omitted: ", output_name,
            " (", filename, ")")
    return(NULL)
  }

  message("Mapped ", output_name, " from ", filename, " column: ", value_col)

  geo %>%
    transmute(
      State, County_key,
      !!output_name := transform(numeric_value(.data[[value_col]]))
    ) %>%
    distinct(State, County_key, .keep_all = TRUE)
}

5.5 4.5 Constructing the County-Level Analytical Dataset

# Outcome: average of the male and female 2009 obesity estimates.
obesity_raw <- read_project_csv("IHME_Obesity.csv")
obesity_geo <- standardize_geo(obesity_raw, "IHME_Obesity.csv")

male_obesity_col <- find_column(
  obesity_geo, "^Male obesity prevalence, 2009",
  label = "male 2009 obesity prevalence"
)
female_obesity_col <- find_column(
  obesity_geo, "^Female\\s+obesity\\s+prevalence,\\s*2009",
  label = "female 2009 obesity prevalence"
)

obesity_data <- obesity_geo %>%
  transmute(
    State, County_key,
    male_obesity_2009 = numeric_value(.data[[male_obesity_col]]),
    female_obesity_2009 = numeric_value(.data[[female_obesity_col]]),
    adult_obesity = rowMeans(
      cbind(
        numeric_value(.data[[male_obesity_col]]),
        numeric_value(.data[[female_obesity_col]])
      ),
      na.rm = TRUE
    )
  ) %>%
  mutate(
    adult_obesity = ifelse(is.nan(adult_obesity), NA_real_, adult_obesity)
  ) %>%
  distinct(State, County_key, .keep_all = TRUE)

# Physical inactivity: complement of sufficient physical activity prevalence.
activity_raw <- read_project_csv("IHME_PhysicalActivity.csv")
activity_geo <- standardize_geo(activity_raw, "IHME_PhysicalActivity.csv")

male_activity_col <- find_column(
  activity_geo,
  "^Male\\s+sufficient\\s+physical\\s+activity\\s+prevalence,\\s*2009",
  label = "male 2009 sufficient physical activity"
)
female_activity_col <- find_column(
  activity_geo,
  "^Female\\s+sufficient\\s+physical\\s+activity\\s+prevalence,\\s*2009",
  label = "female 2009 sufficient physical activity"
)

activity_data <- activity_geo %>%
  transmute(
    State, County_key,
    physical_inactivity = 100 - rowMeans(
      cbind(
        numeric_value(.data[[male_activity_col]]),
        numeric_value(.data[[female_activity_col]])
      ),
      na.rm = TRUE
    )
  ) %>%
  mutate(
    physical_inactivity = ifelse(
      is.nan(physical_inactivity), NA_real_, physical_inactivity
    )
  ) %>%
  distinct(State, County_key, .keep_all = TRUE)

# Additional candidate measures. A source variable is included only when a
# corresponding county-level column can be identified.
optional_sources <- list(
  make_one_variable(
    "AlcoholConsumption.csv", "alcohol_use",
    c("^Hvy$", "heavy.*(prevalence|rate)", "heavy drinking")
  ),
  make_one_variable(
    "Education.csv", "college_education",
    c("^College$", "bachelor", "college.*percent", "college.*rate")
  ),
  make_one_variable(
    "Unemployment.csv", "unemployment",
    c("^Unemployment_rate_2019$", "^Unemployment$", "unemployment.*2019")
  ),
  make_one_variable(
    "Wealth.csv", "median_income",
    c("^Income$", "median household income", "median.*income", "wealth")
  ),
  make_one_variable(
    "FoodInsecurity.csv", "food_insecurity",
    c("^FoodInsecurity$", "food insecurity.*(rate|percent|pct)?",
      "food insecurity")
  ),
  make_one_variable(
    "Sunlight.csv", "sunlight",
    c("^Sun$", "Avg Daily Sunlight", "average_daily_sunlight",
      "average daily sunlight")
  ),
  make_one_variable(
    "EnvironmentalQualityIndex.csv", "environmental_quality",
    c("^EQI$", "environmental quality index")
  ),
  make_one_variable(
    "population.csv", "population",
    c("^Population$", "POPESTIMATE2019", "population.*2019")
  )
)

optional_sources <- optional_sources[!vapply(optional_sources, is.null, logical(1))]

analysis_data <- obesity_data %>%
  left_join(activity_data, by = c("State", "County_key"))

for (source_data in optional_sources) {
  analysis_data <- analysis_data %>%
    left_join(source_data, by = c("State", "County_key"))
}

analysis_data <- analysis_data %>%
  mutate(
    log_population = if ("population" %in% names(.)) {
      ifelse(population > 0, log(population), NA_real_)
    } else {
      NA_real_
    }
  )

# Keep counties with a valid outcome.
analysis_data <- analysis_data %>%
  filter(is.finite(adult_obesity))

# Merge diagnostics.
merge_summary <- tibble(
  Measure = c(
    "Counties with obesity outcome",
    "Counties with physical inactivity",
    "Counties with missing physical inactivity"
  ),
  Count = c(
    nrow(analysis_data),
    sum(!is.na(analysis_data$physical_inactivity)),
    sum(is.na(analysis_data$physical_inactivity))
  )
)

knitr::kable(
  merge_summary,
  caption = "County-level data availability after merging"
) %>%
  kableExtra::kable_styling(full_width = FALSE)
County-level data availability after merging
Measure Count
Counties with obesity outcome 3194
Counties with physical inactivity 3194
Counties with missing physical inactivity 0
# Show available variables and their missingness.
missingness_table <- tibble(
  Variable = names(analysis_data),
  Non_Missing = vapply(analysis_data, function(x) sum(!is.na(x)), integer(1)),
  Missing = vapply(analysis_data, function(x) sum(is.na(x)), integer(1))
)

knitr::kable(
  missingness_table,
  caption = "Missing-value summary for the merged analytical dataset"
) %>%
  kableExtra::kable_styling(full_width = FALSE)
Missing-value summary for the merged analytical dataset
Variable Non_Missing Missing
State 3194 0
County_key 3194 0
male_obesity_2009 3194 0
female_obesity_2009 3194 0
adult_obesity 3194 0
physical_inactivity 3194 0
college_education 0 3194
unemployment 0 3194
median_income 0 3194
food_insecurity 0 3194
sunlight 3153 41
population 3135 59
log_population 3135 59

5.6 4.6 Data Quality and Analysis Sample

The number of counties available for each measure may differ because the source datasets may have different geographic coverage and missing values. The regression sample is therefore defined by the observations with complete data for the outcome and the predictors included in the final model. The final paper should report this sample size and should not imply that every model uses all U.S. counties.

summary(analysis_data$adult_obesity)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   18.00   34.70   36.85   36.94   39.40   52.25
county_counts <- analysis_data %>%
  summarise(
    counties = n(),
    states = n_distinct(State),
    mean_obesity = mean(adult_obesity, na.rm = TRUE),
    sd_obesity = sd(adult_obesity, na.rm = TRUE),
    min_obesity = min(adult_obesity, na.rm = TRUE),
    median_obesity = median(adult_obesity, na.rm = TRUE),
    max_obesity = max(adult_obesity, na.rm = TRUE)
  )

knitr::kable(
  county_counts,
  digits = 2,
  caption = "Summary of the county-level obesity outcome"
) %>%
  kableExtra::kable_styling(full_width = FALSE)
Summary of the county-level obesity outcome
counties states mean_obesity sd_obesity min_obesity median_obesity max_obesity
3194 52 36.94 4.28 18 36.85 52.25

6 5. Methodology

6.1 5.1 Exploratory Data Analysis

Exploratory data analysis is used to describe the distribution of adult obesity prevalence and examine the relationships among the outcome and available explanatory variables. Descriptive statistics and visualizations are reviewed before fitting regression models.

ggplot(analysis_data, aes(x = adult_obesity)) +
  geom_histogram(bins = 30, color = "white") +
  labs(
    title = "Distribution of County-Level Adult Obesity Prevalence",
    x = "Adult obesity prevalence (%)",
    y = "Number of counties"
  ) +
  theme_minimal()

state_summary <- analysis_data %>%
  group_by(State) %>%
  summarise(
    counties = n(),
    mean_obesity = mean(adult_obesity, na.rm = TRUE),
    median_obesity = median(adult_obesity, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  arrange(desc(mean_obesity))

knitr::kable(
  head(state_summary, 15),
  digits = 2,
  caption = "States with the highest mean county-level obesity prevalence (top 15)"
) %>%
  kableExtra::kable_styling(full_width = FALSE)
States with the highest mean county-level obesity prevalence (top 15)
State counties mean_obesity median_obesity
Mississippi 83 42.44 42.10
Louisiana 65 41.58 41.85
Alabama 68 41.05 40.40
South Carolina 47 40.23 39.70
Georgia 160 39.94 40.58
Kentucky 121 39.35 39.00
Arkansas 76 39.19 38.38
West Virginia 56 39.15 38.70
Tennessee 96 38.72 39.02
Oklahoma 78 38.56 38.40
Texas 255 38.25 38.30
North Carolina 101 37.96 37.10
Ohio 89 37.93 37.95
Missouri 116 37.88 37.68
Delaware 4 37.56 37.15
library(dplyr)
library(ggplot2)

state_extremes <- bind_rows(
  state_summary %>%
    slice_max(mean_obesity, n = 10) %>%
    mutate(Group = "Highest"),

  state_summary %>%
    slice_min(mean_obesity, n = 10) %>%
    mutate(Group = "Lowest")
) %>%
  arrange(mean_obesity) %>%
  mutate(State = factor(State, levels = State))

ggplot(state_extremes,
       aes(x = State, y = mean_obesity, fill = Group)) +
  geom_col(width = 0.7) +
  coord_flip() +
  labs(
    title = "States with the Highest and Lowest Mean County Obesity",
    x = NULL,
    y = "Mean county obesity prevalence (%)",
    fill = "State group"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(face = "bold"),
    legend.position = "bottom"
  )

6.2 5.2 Correlation Analysis

Pearson correlations are used as an exploratory measure of linear association among numeric variables. Correlation does not establish causation and does not account for other variables in the model.

numeric_data <- analysis_data %>%
  select(where(is.numeric)) %>%
  select(where(~ sum(!is.na(.x)) > 10))

correlation_matrix <- cor(
  numeric_data,
  use = "pairwise.complete.obs"
)

corrplot_available <- requireNamespace("corrplot", quietly = TRUE)

if (corrplot_available) {
  corrplot::corrplot(
    correlation_matrix,
    method = "color",
    type = "upper",
    tl.col = "black",
    tl.cex = 0.75,
    addCoef.col = "black",
    number.cex = 0.5
  )
} else {
  knitr::kable(
    round(correlation_matrix, 2),
    caption = "Pearson correlation matrix"
  )
}

6.3 5.3 Multiple Linear Regression

The baseline model uses adult obesity prevalence as the dependent variable and the available county-level explanatory variables as predictors. The model is specified using the predictors that are successfully identified in the repository and have sufficient non-missing observations.

The general model is:

\[ Obesity_i = \beta_0 + \sum_{k=1}^{K}\beta_k X_{ki} + \epsilon_i \]

where \(Obesity_i\) is the adult obesity prevalence measure for county \(i\), \(X_{ki}\) represents the measured county-level characteristics, and \(\epsilon_i\) is the error term.

candidate_predictors <- c(
  "physical_inactivity",
  "alcohol_use",
  "college_education",
  "unemployment",
  "median_income",
  "food_insecurity",
  "sunlight",
  "environmental_quality",
  "population"
)

# Identify predictors available in the dataset
existing_predictors <- intersect(
  candidate_predictors,
  names(analysis_data)
)

# Check predictor quality
predictor_diagnostics <- purrr::map_dfr(
  existing_predictors,
  function(v) {

    x <- analysis_data[[v]]

    tibble(
      Variable = v,
      Non_Missing = sum(!is.na(x)),
      Distinct_Values = dplyr::n_distinct(x, na.rm = TRUE),
      Data_Type = class(x)[1]
    )
  }
)

knitr::kable(
  predictor_diagnostics,
  caption = "Regression predictor diagnostics"
) %>%
  kableExtra::kable_styling(full_width = FALSE)
Regression predictor diagnostics
Variable Non_Missing Distinct_Values Data_Type
physical_inactivity 3194 756 numeric
college_education 0 0 numeric
unemployment 0 0 numeric
median_income 0 0 numeric
food_insecurity 0 0 numeric
sunlight 3153 3141 numeric
population 3135 3081 numeric
# Select usable numerical predictors
available_predictors <- predictor_diagnostics %>%
  filter(
    Non_Missing >= 100,
    Distinct_Values > 1,
    Data_Type %in% c("numeric", "integer")
  ) %>%
  pull(Variable)

cat("Usable predictors:",
    paste(available_predictors, collapse = ", "))
## Usable predictors: physical_inactivity, sunlight, population
if (length(available_predictors) < 3) {
  stop(
    "Fewer than three usable predictors. ",
    "Review the diagnostic table before continuing."
  )
}

# Create complete-case regression dataset
model_variables <- c(
  "adult_obesity",
  "State",
  "County_key",
  available_predictors
)

model_data <- analysis_data %>%
  select(all_of(model_variables)) %>%
  drop_na() %>%
  mutate(State = factor(State))

if (nrow(model_data) < 100) {
  stop("Regression sample contains fewer than 100 counties.")
}

# Baseline OLS model
baseline_formula <- as.formula(
  paste(
    "adult_obesity ~",
    paste(available_predictors, collapse = " + ")
  )
)

model_ols <- lm(
  baseline_formula,
  data = model_data
)

# State fixed-effects model
state_formula <- as.formula(
  paste(
    "adult_obesity ~",
    paste(available_predictors, collapse = " + "),
    "+ State"
  )
)

model_state <- lm(
  state_formula,
  data = model_data
)

cat("\nRegression sample:",
    nrow(model_data), "counties")
## 
## Regression sample: 3101 counties
cat("\nStates represented:",
    n_distinct(model_data$State))
## 
## States represented: 49
cat("\nBaseline adjusted R-squared:",
    round(summary(model_ols)$adj.r.squared, 4))
## 
## Baseline adjusted R-squared: 0.707
cat("\nState model adjusted R-squared:",
    round(summary(model_state)$adj.r.squared, 4))
## 
## State model adjusted R-squared: 0.7971

6.4 5.4 State Fixed-Effects Model

The geographic model adds state indicators to the baseline regression:

\[ Obesity_{is} = \beta_0 + \sum_{k=1}^{K}\beta_k X_{kis} + \gamma_s + \epsilon_{is} \]

where \(\gamma_s\) represents the state fixed effect. One state is treated as the reference category by the regression software.

The state fixed-effects model tests whether state membership adds explanatory information after adjustment for the measured county-level variables. It does not establish that state location causes differences in obesity prevalence.

6.5 5.5 Model Evaluation

The models are compared using adjusted R-squared and RMSE. A nested-model F-test evaluates whether the state indicators collectively improve the in-sample fit. These measures describe explanatory performance in the analysis sample and should not be confused with out-of-sample predictive validation.

rmse <- function(model) {
  sqrt(mean(residuals(model)^2))
}

model_comparison <- tibble(
  Model = c("Baseline OLS", "OLS with state fixed effects"),
  Observations = c(nobs(model_ols), nobs(model_state)),
  R_Squared = c(summary(model_ols)$r.squared,
                summary(model_state)$r.squared),
  Adjusted_R_Squared = c(summary(model_ols)$adj.r.squared,
                         summary(model_state)$adj.r.squared),
  RMSE = c(rmse(model_ols), rmse(model_state))
)

knitr::kable(
  model_comparison,
  digits = 4,
  caption = "Comparison of baseline and state fixed-effects models"
) %>%
  kableExtra::kable_styling(full_width = FALSE)
Comparison of baseline and state fixed-effects models
Model Observations R_Squared Adjusted_R_Squared RMSE
Baseline OLS 3101 0.7073 0.7070 2.3016
OLS with state fixed effects 3101 0.8004 0.7971 1.9003
state_model_test <- anova(model_ols, model_state)
knitr::kable(
  broom::tidy(state_model_test),
  digits = 4,
  caption = "Nested-model F-test: additional contribution of state fixed effects"
) %>%
  kableExtra::kable_styling(full_width = FALSE)
Nested-model F-test: additional contribution of state fixed effects
term df.residual rss df sumsq statistic p.value
adult_obesity ~ physical_inactivity + sunlight + population 3097 16427.01 NA NA NA NA
adult_obesity ~ physical_inactivity + sunlight + population + State 3049 11197.89 48 5229.118 29.6625 0

6.6 5.6 Regression Coefficients and Uncertainty

The coefficients are interpreted as adjusted county-level associations. A coefficient represents the estimated difference in adult obesity prevalence associated with a one-unit difference in a predictor, holding the other included variables constant. Units must be considered when interpreting the size of each coefficient.

Heteroscedasticity-consistent standard errors (HC3) are reported as a robustness measure.

robust_results <- lmtest::coeftest(
  model_state,
  vcov. = sandwich::vcovHC(model_state, type = "HC3")
)

coefficient_table <- broom::tidy(robust_results) %>%
  rename(
    Estimate = estimate,
    Std_Error_HC3 = std.error,
    t_value = statistic,
    p_value = p.value
  ) %>%
  mutate(
    CI_Lower = Estimate - qt(0.975, df.residual(model_state)) * Std_Error_HC3,
    CI_Upper = Estimate + qt(0.975, df.residual(model_state)) * Std_Error_HC3
  )

knitr::kable(
  coefficient_table,
  digits = 4,
  caption = "State fixed-effects regression coefficients with HC3 robust standard errors"
) %>%
  kableExtra::kable_styling(full_width = FALSE, font_size = 13)
State fixed-effects regression coefficients with HC3 robust standard errors
term Estimate Std_Error_HC3 t_value p_value CI_Lower CI_Upper
(Intercept) -1.8414 NaN NaN NaN NaN NaN
physical_inactivity 0.6658 NaN NaN NaN NaN NaN
sunlight 0.0003 NaN NaN NaN NaN NaN
population 0.0000 NaN NaN NaN NaN NaN
StateArizona 2.0828 NaN NaN NaN NaN NaN
StateArkansas 0.4114 NaN NaN NaN NaN NaN
StateCalifornia 2.1268 NaN NaN NaN NaN NaN
StateColorado -0.3809 NaN NaN NaN NaN NaN
StateConnecticut -0.0820 NaN NaN NaN NaN NaN
StateDelaware 3.0589 NaN NaN NaN NaN NaN
StateDistrict of Columbia -1.0196 NaN NaN NaN NaN NaN
StateFlorida 0.6223 NaN NaN NaN NaN NaN
StateGeorgia 1.2014 NaN NaN NaN NaN NaN
StateIdaho 3.0474 NaN NaN NaN NaN NaN
StateIllinois 2.3759 NaN NaN NaN NaN NaN
StateIndiana 1.2373 NaN NaN NaN NaN NaN
StateIowa 2.1367 NaN NaN NaN NaN NaN
StateKansas 1.8379 NaN NaN NaN NaN NaN
StateKentucky -0.2502 NaN NaN NaN NaN NaN
StateLouisiana 0.6253 NaN NaN NaN NaN NaN
StateMaine 4.3100 NaN NaN NaN NaN NaN
StateMaryland 2.9480 NaN NaN NaN NaN NaN
StateMassachusetts -0.3727 NaN NaN NaN NaN NaN
StateMichigan 5.4586 NaN NaN NaN NaN NaN
StateMinnesota 3.0931 NaN NaN NaN NaN NaN
StateMississippi 0.2031 NaN NaN NaN NaN NaN
StateMissouri 1.8512 NaN NaN NaN NaN NaN
StateMontana 2.4744 NaN NaN NaN NaN NaN
StateNebraska 2.8708 NaN NaN NaN NaN NaN
StateNevada 1.7372 NaN NaN NaN NaN NaN
StateNew Hampshire 3.9369 NaN NaN NaN NaN NaN
StateNew Jersey -0.6874 NaN NaN NaN NaN NaN
StateNew Mexico 0.2666 NaN NaN NaN NaN NaN
StateNew York 2.4980 NaN NaN NaN NaN NaN
StateNorth Carolina 0.9091 NaN NaN NaN NaN NaN
StateNorth Dakota 2.5510 NaN NaN NaN NaN NaN
StateOhio 3.0466 NaN NaN NaN NaN NaN
StateOklahoma 1.0174 NaN NaN NaN NaN NaN
StateOregon 5.5529 NaN NaN NaN NaN NaN
StatePennsylvania 3.3849 NaN NaN NaN NaN NaN
StateRhode Island -1.4941 NaN NaN NaN NaN NaN
StateSouth Carolina 2.8095 NaN NaN NaN NaN NaN
StateSouth Dakota 2.4899 NaN NaN NaN NaN NaN
StateTennessee -2.7053 NaN NaN NaN NaN NaN
StateTexas 0.6439 NaN NaN NaN NaN NaN
StateUtah 1.7079 NaN NaN NaN NaN NaN
StateVermont 3.0854 NaN NaN NaN NaN NaN
StateVirginia 1.2315 NaN NaN NaN NaN NaN
StateWashington 5.9157 NaN NaN NaN NaN NaN
StateWest Virginia 0.2676 NaN NaN NaN NaN NaN
StateWisconsin 4.9081 NaN NaN NaN NaN NaN
StateWyoming 1.9160 NaN NaN NaN NaN NaN

6.7 5.7 Regression Diagnostics

Regression diagnostics are used to evaluate whether the fitted models show important departures from the assumptions of linear regression. The analysis examines residual patterns, approximate normality, heteroscedasticity, and multicollinearity. Statistical significance should be interpreted cautiously because counties may not be statistically independent.

old_par <- par(no.readonly = TRUE)
par(mfrow = c(2, 2))
plot(model_state)

par(old_par)
vif_values <- tryCatch(
  car::vif(model_state),
  error = function(e) NULL
)

if (!is.null(vif_values)) {
  if (is.matrix(vif_values)) {
    vif_output <- as.data.frame(vif_values) %>%
      tibble::rownames_to_column("Variable")
  } else {
    vif_output <- tibble(
      Variable = names(vif_values),
      VIF = as.numeric(vif_values)
    )
  }

  knitr::kable(
    vif_output,
    digits = 3,
    caption = "Variance inflation factor diagnostics"
  ) %>%
    kableExtra::kable_styling(full_width = FALSE)
} else {
  cat("VIF could not be calculated for this model specification.")
}
Variance inflation factor diagnostics
Variable GVIF Df GVIF^(1/(2*Df))
physical_inactivity 2.512 1 1.585
sunlight 12.270 1 3.503
population 1.096 1 1.047
State 29.607 48 1.036

6.8 5.8 Residual Geographic Variation

A residual is the difference between observed and model-predicted obesity prevalence:

\[ Residual_i = Observed_i - Predicted_i \]

Positive residuals indicate that the observed county prevalence is higher than the model predicts. Negative residuals indicate that observed prevalence is lower than predicted. Residuals are examined to identify counties with larger deviations from the model.

model_data <- model_data %>%
  mutate(
    fitted_obesity = fitted(model_state),
    residual = residuals(model_state),
    absolute_residual = abs(residual)
  )

residual_summary <- model_data %>%
  summarise(
    Mean_residual = mean(residual),
    SD_residual = sd(residual),
    Mean_absolute_residual = mean(absolute_residual),
    Minimum_residual = min(residual),
    Maximum_residual = max(residual)
  )

knitr::kable(
  residual_summary,
  digits = 3,
  caption = "Summary of residuals from the state fixed-effects model"
) %>%
  kableExtra::kable_styling(full_width = FALSE)
Summary of residuals from the state fixed-effects model
Mean_residual SD_residual Mean_absolute_residual Minimum_residual Maximum_residual
0 1.901 1.448 -10.788 7.618
ggplot(model_data, aes(x = fitted_obesity, y = residual)) +
  geom_point(alpha = 0.45) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  labs(
    title = "Residuals Versus Fitted Values",
    x = "Predicted adult obesity prevalence (%)",
    y = "Residual (percentage points)"
  ) +
  theme_minimal()

largest_residuals <- model_data %>%
  mutate(County = analysis_data$County_key[match(
    paste(State, County_key), paste(analysis_data$State, analysis_data$County_key)
  )]) %>%
  arrange(desc(absolute_residual)) %>%
  select(State, County, adult_obesity, fitted_obesity, residual) %>%
  slice_head(n = 15)

knitr::kable(
  largest_residuals,
  digits = 2,
  caption = "Counties with the largest absolute model residuals"
) %>%
  kableExtra::kable_styling(full_width = FALSE)
Counties with the largest absolute model residuals
State County adult_obesity fitted_obesity residual
Virginia Virginia&#124;fallschurchcity 18.00 28.79 -10.79
Pennsylvania Pennsylvania&#124;montour 27.10 37.47 -10.37
California California&#124;sanfrancisco 19.00 29.17 -10.17
New York New York&#124;richmond 28.95 38.38 -9.43
Virginia Virginia&#124;fairfaxcity 22.70 31.66 -8.96
New York New York&#124;queens 29.10 37.39 -8.29
New York New York&#124;nassau 28.70 36.53 -7.83
Virginia Virginia&#124;portsmouthcity 45.35 37.73 7.62
Alabama Alabama&#124;marion 37.70 45.28 -7.58
North Carolina North Carolina&#124;orange 23.45 30.89 -7.44
Maryland Maryland&#124;montgomery 24.40 31.65 -7.25
New Mexico New Mexico&#124;mckinley 41.70 34.63 7.07
New York New York&#124;westchester 25.50 32.44 -6.94
New York New York&#124;kings 32.05 38.80 -6.75
North Carolina North Carolina&#124;ashe 32.30 38.83 -6.53

7 6. Results

7.1 6.1 County-Level Variation in Adult Obesity

The descriptive analysis reports the distribution of the county-level adult obesity outcome. The final interpretation should describe the range, central tendency, and variability shown in the generated summary and histogram.

The analysis includes 3194 counties with an available outcome measure. The mean county-level adult obesity prevalence is 36.94%, and the standard deviation is 4.28 percentage points.

7.2 6.2 Regression Results

The baseline OLS model has an adjusted R-squared of 0.707. The state fixed-effects model has an adjusted R-squared of 0.797. The corresponding RMSE values are 2.302 and 1.9 percentage points, respectively.

The nested-model F-test evaluates whether adding the state indicators improves model fit. Its result should be interpreted together with the change in adjusted R-squared and RMSE, rather than relying only on the p-value.

7.3 6.3 Geographic Differences After Adjustment

The state fixed-effects model evaluates whether state indicators collectively explain additional variation after accounting for the measured county characteristics. A statistically significant nested-model test would indicate that state indicators add explanatory information in this sample. It would not demonstrate that every state differs from every other state, nor would it identify the specific local mechanisms responsible for the differences.

The residual analysis identifies counties where observed prevalence differs most from model predictions. These residual differences may reflect unmeasured county characteristics, measurement error, differences in source years, model misspecification, or spatially patterned factors.

7.4 6.4 Model Diagnostics

The diagnostic plots and VIF results should be reviewed before final interpretation. Potential issues include nonlinearity, heteroscedasticity, influential observations, and multicollinearity. HC3 robust standard errors help address heteroscedasticity in coefficient uncertainty estimates, but they do not correct spatial dependence between neighboring counties.

8 7. Discussion

The purpose of this study is to determine whether geographic differences in adult obesity prevalence remain after controlling for measured county-level characteristics. The comparison between the baseline OLS model and the state fixed-effects model provides the primary evidence for evaluating the research question.

Complete this discussion after reviewing the knitted results. Specifically, explain:

  1. Whether the county-level obesity outcome shows substantial variation.
  2. Which measured predictors have the largest estimated associations, including their direction, units, and confidence intervals.
  3. Whether the state fixed-effects model improves adjusted R-squared and RMSE.
  4. Whether the nested-model F-test supports the conclusion that state indicators add explanatory information.
  5. What the residual diagnostics suggest about unexplained county-level differences.

The findings should be compared with the literature reviewed in Section 2. Avoid describing an association as a causal effect. A statistically significant coefficient does not necessarily indicate a large or practically important association.

9 8. Limitations

Several limitations should be considered when interpreting the findings.

First, the study uses aggregated county-level data. County-level associations cannot automatically be generalized to individuals; doing so would risk an ecological fallacy.

Second, the outcome is calculated as the arithmetic mean of male and female IHME 2009 obesity estimates. It is not a population-weighted overall prevalence estimate. This definition should be kept explicit throughout the paper.

Third, the source datasets may represent different years. Differences in the timing of obesity, physical activity, socioeconomic, food-related, and environmental measurements may affect the estimated relationships.

Fourth, the analysis relies on county-name and state-name standardization for files without a consistently available FIPS identifier. Although state-plus-county matching reduces ambiguity, a verified five-digit FIPS crosswalk would be preferable for the final data integration.

Fifth, the selected variables do not capture every factor associated with obesity. Potentially relevant omitted characteristics include healthcare access, transportation infrastructure, demographic composition, housing, local policy, and neighborhood-level resources.

Sixth, state fixed effects capture average differences between states but do not directly test spatial autocorrelation among neighboring counties. A separate spatial analysis using validated county geometries and a defensible spatial-weights matrix would be needed to assess neighboring-county dependence.

Finally, OLS estimates may be sensitive to influential observations, multicollinearity, heteroscedasticity, and measurement error. The diagnostic results should therefore be considered alongside the coefficient estimates.

10 9. Conclusion

This study examines county-level geographic differences in adult obesity prevalence after adjustment for measured behavioral, socioeconomic, food-related, and environmental characteristics. It uses a sequential modeling strategy that compares a baseline OLS regression with a model containing state fixed effects.

The final conclusion should be completed after the data and model outputs have been reviewed. It should state how much variation the baseline model explains, whether the state fixed-effects model adds explanatory value, which measured associations are most important, and what geographic differences remain unexplained.

The findings should be interpreted as county-level observational associations. They may help identify geographic patterns that warrant additional public-health investigation, but they do not establish causal effects or explain all sources of obesity differences across communities.

11 10. Reproducibility and Final Checks

The analysis is designed to be reproducible from the public project repository. Before submission, confirm that the repository files have not changed, that each source column was mapped correctly, and that the final complete-case sample is appropriate for the research question.

final_checks <- tibble(
  Check = c(
    "Outcome variable present",
    "At least 3 predictors included",
    "Regression sample has at least 100 counties",
    "More than one state represented",
    "Baseline and state models use same observations",
    "Model coefficients are finite"
  ),
  Passed = c(
    "adult_obesity" %in% names(model_data),
    length(available_predictors) >= 3,
    nrow(model_data) >= 100,
    n_distinct(model_data$State) > 1,
    nobs(model_ols) == nobs(model_state),
    all(is.finite(coef(model_state)))
  )
)

knitr::kable(
  final_checks,
  caption = "Reproducibility and model validation checks"
) %>%
  kableExtra::kable_styling(full_width = FALSE)
Reproducibility and model validation checks
Check Passed
Outcome variable present TRUE
At least 3 predictors included TRUE
Regression sample has at least 100 counties TRUE
More than one state represented TRUE
Baseline and state models use same observations TRUE
Model coefficients are finite TRUE

12 References

Ahern, M., Brown, C., & Dukas, S. (2011). A national study of the association between food environments and county-level health outcomes. The Journal of Rural Health. [Verify volume, issue, pages, and DOI before submission.]

An, R., Li, X., & Jiang, N. (2017). Geographical variations in the environmental determinants of physical inactivity among U.S. adults. [Verify complete publication details before submission.]

Centers for Disease Control and Prevention. (n.d.). North America Land Data Assimilation System (NLDAS) daily sunlight (kJ/m²), 1979–2011. https://wonder.cdc.gov/controller/datarequest/D80

Feeding America. (n.d.). Map the Meal Gap: County-level food insecurity data. https://www.feedingamerica.org/research/map-the-meal-gap/by-county

Hammarström, A., Janlert, U., & Winefield, H. (2014). Length of unemployment and health-related outcomes. [Verify complete publication details before submission.]

Holick, M. F., & Wacker, M. (2013). Sunlight and vitamin D. [Verify publisher and edition or article details before submission.]

Institute for Health Metrics and Evaluation. (n.d.). United States alcohol use prevalence by county, 2002–2012. Global Health Data Exchange. http://ghdx.healthdata.org/record/ihme-data/united-states-alcohol-use-prevalence-county-2002-2012

Institute for Health Metrics and Evaluation. (n.d.). United States physical activity and obesity prevalence by county. Global Health Data Exchange. https://ghdx.healthdata.org/

U.S. Census Bureau. (2019). Small Area Income and Poverty Estimates (SAIPE): State and county estimates. https://www.census.gov/data/datasets/2019/demo/saipe/2019-state-and-county.html

U.S. Department of Agriculture, Economic Research Service. (n.d.). County-level data sets. https://www.ers.usda.gov/data-products/county-level-data-sets/download-data/

U.S. Environmental Protection Agency. (n.d.). Environmental Quality Index (EQI), 2006–2010. https://edg.epa.gov/EPADataCommons/public/ORD/CPHEA/EQI_2006_2010/


Submission note: Complete the discussion and conclusion using the actual output from the final knit. Verify every literature reference’s full bibliographic details and add in-text citations where the cited studies are discussed. The final paper should not be submitted with unresolved source mappings, incomplete references, or unreviewed model diagnostics.

LS0tDQp0aXRsZTogIkNvdW50eS1MZXZlbCBHZW9ncmFwaGljIERpZmZlcmVuY2VzIGluIEFkdWx0IE9iZXNpdHkgUHJldmFsZW5jZSBBZnRlciBDb250cm9sbGluZyBmb3IgS25vd24gUmlzayBGYWN0b3JzIg0KYXV0aG9yOiAiQmlrYXNoIEJob3dtaWsiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBmYWxzZQ0KICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICB0aGVtZTogY29zbW8NCiAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgZWNobyA9IFRSVUUsDQogIG1lc3NhZ2UgPSBGQUxTRSwNCiAgd2FybmluZyA9IEZBTFNFLA0KICBmaWcuYWxpZ24gPSAiY2VudGVyIiwNCiAgZmlnLndpZHRoID0gOCwNCiAgZmlnLmhlaWdodCA9IDUsDQogIG91dC53aWR0aCA9ICI5NSUiDQopDQoNCnJlcXVpcmVkX3BhY2thZ2VzIDwtIGMoDQogICJ0aWR5dmVyc2UiLCAiamFuaXRvciIsICJrbml0ciIsICJrYWJsZUV4dHJhIiwNCiAgImJyb29tIiwgImNhciIsICJsbXRlc3QiLCAic2FuZHdpY2giLCAic2NhbGVzIiwNCiAgInN0cmluZ2kiDQopDQoNCm1pc3NpbmdfcGFja2FnZXMgPC0gcmVxdWlyZWRfcGFja2FnZXNbDQogICF2YXBwbHkocmVxdWlyZWRfcGFja2FnZXMsIHJlcXVpcmVOYW1lc3BhY2UsIGxvZ2ljYWwoMSksIHF1aWV0bHkgPSBUUlVFKQ0KXQ0KDQppZiAobGVuZ3RoKG1pc3NpbmdfcGFja2FnZXMpID4gMCkgew0KICBzdG9wKA0KICAgICJJbnN0YWxsIHRoZXNlIHBhY2thZ2VzIGJlZm9yZSBrbml0dGluZzogIiwNCiAgICBwYXN0ZShtaXNzaW5nX3BhY2thZ2VzLCBjb2xsYXBzZSA9ICIsICIpDQogICkNCn0NCg0KaW52aXNpYmxlKGxhcHBseShyZXF1aXJlZF9wYWNrYWdlcywgbGlicmFyeSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkNCg0Kb3B0aW9ucyhzY2lwZW4gPSA5OTkpDQpzZXQuc2VlZCg2OTgpDQpgYGANCg0KIyBBYnN0cmFjdA0KDQpBZHVsdCBvYmVzaXR5IHByZXZhbGVuY2UgdmFyaWVzIGFjcm9zcyBVLlMuIGNvdW50aWVzLiBUaGlzIHN0dWR5IGV4YW1pbmVzIHdoZXRoZXIgY291bnR5LWxldmVsIGdlb2dyYXBoaWMgZGlmZmVyZW5jZXMgcmVtYWluIGFmdGVyIGFjY291bnRpbmcgZm9yIG1lYXN1cmVkIGJlaGF2aW9yYWwsIHNvY2lvZWNvbm9taWMsIGZvb2QtcmVsYXRlZCwgYW5kIGVudmlyb25tZW50YWwgY2hhcmFjdGVyaXN0aWNzLiBDb3VudHktbGV2ZWwgZGF0YSBhcmUgYXNzZW1ibGVkIGZyb20gdGhlIElITUUgZGF0YXNldHMgYW5kIHN1cHBvcnRpbmcgcHVibGljIGRhdGEgZmlsZXMgbWFpbnRhaW5lZCBpbiB0aGUgcHJvamVjdCdzIEdpdEh1YiByZXBvc2l0b3J5LiBUaGUgcHJpbWFyeSBvdXRjb21lIGlzIGFuIGFwcHJveGltYXRlIGNvdW50eS1sZXZlbCBhZHVsdCBvYmVzaXR5IHByZXZhbGVuY2UgbWVhc3VyZSBjYWxjdWxhdGVkIGFzIHRoZSBhcml0aG1ldGljIG1lYW4gb2YgdGhlIG1hbGUgYW5kIGZlbWFsZSAyMDA5IElITUUgY291bnR5IGVzdGltYXRlcy4gUHJlZGljdG9ycyBhcmUgc2VsZWN0ZWQgZnJvbSB0aGUgYXZhaWxhYmxlIGNvdW50eS1sZXZlbCBtZWFzdXJlcyBvZiBwaHlzaWNhbCBpbmFjdGl2aXR5LCBhbGNvaG9sIHVzZSwgZWR1Y2F0aW9uYWwgYXR0YWlubWVudCwgdW5lbXBsb3ltZW50LCBob3VzZWhvbGQgaW5jb21lIG9yIHdlYWx0aCwgZm9vZCBpbnNlY3VyaXR5LCBzdW5saWdodCBleHBvc3VyZSwgZW52aXJvbm1lbnRhbCBxdWFsaXR5LCBhbmQgcG9wdWxhdGlvbi4NCg0KVGhlIGFuYWx5c2lzIHVzZXMgZGVzY3JpcHRpdmUgc3RhdGlzdGljcywgZXhwbG9yYXRvcnkgdmlzdWFsaXphdGlvbnMsIG11bHRpcGxlIG9yZGluYXJ5IGxlYXN0IHNxdWFyZXMgcmVncmVzc2lvbiwgYW5kIGEgc3RhdGUgZml4ZWQtZWZmZWN0cyBtb2RlbC4gTW9kZWwgZml0IGlzIGFzc2Vzc2VkIHVzaW5nIGFkanVzdGVkIFItc3F1YXJlZCwgcm9vdCBtZWFuIHNxdWFyZWQgZXJyb3IsIGEgbmVzdGVkLW1vZGVsIGNvbXBhcmlzb24sIGFuZCByZWdyZXNzaW9uIGRpYWdub3N0aWNzLiBCZWNhdXNlIHRoZSBkYXRhIGFyZSBvYnNlcnZhdGlvbmFsIGFuZCBhZ2dyZWdhdGVkIGF0IHRoZSBjb3VudHkgbGV2ZWwsIGFsbCBmaW5kaW5ncyBhcmUgaW50ZXJwcmV0ZWQgYXMgYXNzb2NpYXRpb25zIHJhdGhlciB0aGFuIGNhdXNhbCBlZmZlY3RzLiBUaGUgZmluYWwgaW50ZXJwcmV0YXRpb24gd2lsbCBmb2N1cyBvbiB0aGUgYW1vdW50IG9mIHZhcmlhdGlvbiBleHBsYWluZWQgYnkgbWVhc3VyZWQgY291bnR5IGNoYXJhY3RlcmlzdGljcyBhbmQgd2hldGhlciBhZGRpbmcgc3RhdGUgaW5kaWNhdG9ycyBwcm92aWRlcyBhZGRpdGlvbmFsIGV4cGxhbmF0b3J5IHZhbHVlLg0KDQoqKlRoZSBudW1lcmljYWwgZmluZGluZ3MgaW4gdGhpcyBhYnN0cmFjdCBhcmUgZ2VuZXJhdGVkIGZyb20gdGhlIGN1cnJlbnQgZGF0YSB3aGVuIHRoZSBkb2N1bWVudCBpcyBrbml0dGVkLioqIFRoZSBvdXRjb21lIGRlZmluaXRpb24gYW5kIHRoZSB5ZWFycyByZXByZXNlbnRlZCBieSBlYWNoIHNvdXJjZSBtdXN0IGJlIGNvbnNpZGVyZWQgd2hlbiBpbnRlcnByZXRpbmcgdGhlIHJlc3VsdHMuDQoNCioqS2V5d29yZHM6KiogYWR1bHQgb2Jlc2l0eSwgY291bnR5LWxldmVsIGFuYWx5c2lzLCBnZW9ncmFwaGljIHZhcmlhdGlvbiwgcGh5c2ljYWwgaW5hY3Rpdml0eSwgc29jaW9lY29ub21pYyBmYWN0b3JzLCBzdGF0ZSBmaXhlZCBlZmZlY3RzLCBzcGF0aWFsIGRpc3Bhcml0aWVzDQoNCiMgMS4gSW50cm9kdWN0aW9uDQoNCkFkdWx0IG9iZXNpdHkgaXMgYW4gaW1wb3J0YW50IHB1YmxpYy1oZWFsdGggaXNzdWUgaW4gdGhlIFVuaXRlZCBTdGF0ZXMsIGFuZCBwcmV2YWxlbmNlIGRpZmZlcnMgYWNyb3NzIGdlb2dyYXBoaWMgYXJlYXMuIE5hdGlvbmFsIGFuZCBzdGF0ZSBzdW1tYXJpZXMgY2FuIGNvbmNlYWwgc3Vic3RhbnRpYWwgdmFyaWF0aW9uIGFtb25nIGNvdW50aWVzLiBDb3VudGllcyBkaWZmZXIgaW4gZWNvbm9taWMgcmVzb3VyY2VzLCBlZHVjYXRpb25hbCBhdHRhaW5tZW50LCBlbXBsb3ltZW50IGNvbmRpdGlvbnMsIGZvb2Qgc2VjdXJpdHksIGJlaGF2aW9yYWwgcGF0dGVybnMsIGFuZCBlbnZpcm9ubWVudGFsIGNoYXJhY3RlcmlzdGljcy4gVGhlc2UgZGlmZmVyZW5jZXMgcHJvdmlkZSBhbiBpbXBvcnRhbnQgY29udGV4dCBmb3IgZXhhbWluaW5nIGNvdW50eS1sZXZlbCB2YXJpYXRpb24gaW4gYWR1bHQgb2Jlc2l0eS4NCg0KTWFueSBrbm93biBjaGFyYWN0ZXJpc3RpY3MgaGF2ZSBiZWVuIGFzc29jaWF0ZWQgd2l0aCBvYmVzaXR5LCBpbmNsdWRpbmcgcGh5c2ljYWwgYWN0aXZpdHksIHNvY2lvZWNvbm9taWMgY29uZGl0aW9ucywgYW5kIGZvb2QtcmVsYXRlZCBjaXJjdW1zdGFuY2VzLiBUaGUgcHVycG9zZSBvZiB0aGlzIHN0dWR5IGlzIG5vdCBzaW1wbHkgdG8gaWRlbnRpZnkgd2hldGhlciB0aGVzZSBlc3RhYmxpc2hlZCBmYWN0b3JzIGFyZSBhc3NvY2lhdGVkIHdpdGggb2Jlc2l0eS4gSW5zdGVhZCwgdGhlIGNlbnRyYWwgcXVlc3Rpb24gaXMgd2hldGhlciBnZW9ncmFwaGljIGRpZmZlcmVuY2VzIGFtb25nIFUuUy4gY291bnRpZXMgcmVtYWluIGFmdGVyIGFjY291bnRpbmcgZm9yIG1lYXN1cmVkIGNvdW50eS1sZXZlbCBjaGFyYWN0ZXJpc3RpY3MuDQoNClRoaXMgc3R1ZHkgY29tYmluZXMgcHVibGljbHkgYXZhaWxhYmxlIGNvdW50eS1sZXZlbCBkYXRhIGZyb20gbXVsdGlwbGUgc291cmNlcyBhbmQgdXNlcyByZWdyZXNzaW9uIG1vZGVsaW5nIHRvIGVzdGltYXRlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBhZHVsdCBvYmVzaXR5IHByZXZhbGVuY2UgYW5kIHNlbGVjdGVkIGV4cGxhbmF0b3J5IHZhcmlhYmxlcy4gQSBiYXNlbGluZSBvcmRpbmFyeSBsZWFzdCBzcXVhcmVzIChPTFMpIG1vZGVsIGlzIGNvbXBhcmVkIHdpdGggYSBtb2RlbCB0aGF0IGluY2x1ZGVzIHN0YXRlIGZpeGVkIGVmZmVjdHMuIFRoZSBjb21wYXJpc29uIGV2YWx1YXRlcyB3aGV0aGVyIHN0YXRlLWxldmVsIGdlb2dyYXBoaWMgaW5kaWNhdG9ycyBwcm92aWRlIGFkZGl0aW9uYWwgZXhwbGFuYXRvcnkgaW5mb3JtYXRpb24gYWZ0ZXIgYWRqdXN0bWVudCBmb3IgdGhlIG1lYXN1cmVkIHJpc2sgZmFjdG9ycy4NCg0KVGhlIGFuYWx5c2lzIGlzIG9ic2VydmF0aW9uYWwuIEl0IGRvZXMgbm90IGVzdGFibGlzaCB0aGF0IGNvdW50eSBsb2NhdGlvbiBvciBhbnkgaW5kaXZpZHVhbCBwcmVkaWN0b3IgY2F1c2VzIG9iZXNpdHkuIEJlY2F1c2UgdGhlIHVuaXQgb2YgYW5hbHlzaXMgaXMgdGhlIGNvdW50eSwgcmVzdWx0cyBkZXNjcmliZSBjb3VudHktbGV2ZWwgYXNzb2NpYXRpb25zIGFuZCBzaG91bGQgbm90IGJlIGludGVycHJldGVkIGFzIGluZGl2aWR1YWwtbGV2ZWwgcmVsYXRpb25zaGlwcy4NCg0KIyMgMS4xIEltcG9ydGFuY2Ugb2YgdGhlIFN0dWR5DQoNClVuZGVyc3RhbmRpbmcgZ2VvZ3JhcGhpYyBkaWZmZXJlbmNlcyBpbiBvYmVzaXR5IG1heSBoZWxwIGlkZW50aWZ5IGNvbW11bml0aWVzIHdoZXJlIG9ic2VydmVkIHByZXZhbGVuY2UgaXMgaGlnaGVyIG9yIGxvd2VyIHRoYW4gZXhwZWN0ZWQgZ2l2ZW4gbWVhc3VyZWQgY291bnR5IGNoYXJhY3RlcmlzdGljcy4gSWYgZ2VvZ3JhcGhpYyBkaWZmZXJlbmNlcyByZW1haW4gYWZ0ZXIgYWRqdXN0bWVudCwgdGhpcyBtYXkgaW5kaWNhdGUgdGhhdCBhZGRpdGlvbmFsIGNvbnRleHR1YWwsIHBvbGljeS1yZWxhdGVkLCBoZWFsdGhjYXJlLCBkZW1vZ3JhcGhpYywgb3Igc3BhdGlhbGx5IHBhdHRlcm5lZCBmYWN0b3JzIHdhcnJhbnQgaW52ZXN0aWdhdGlvbi4NCg0KVGhlIHN0dWR5IGFsc28gZGVtb25zdHJhdGVzIGhvdyBkYXRhIGZyb20gbXVsdGlwbGUgcHVibGljIHNvdXJjZXMgY2FuIGJlIGludGVncmF0ZWQgYW5kIGFuYWx5emVkIHVzaW5nIHJlcHJvZHVjaWJsZSBzdGF0aXN0aWNhbCBtZXRob2RzIGluIFIuIFRoZSBlbXBoYXNpcyBpcyBvbiBtb2RlbCBjb21wYXJpc29uLCBlZmZlY3QgZXN0aW1hdGVzLCB1bmNlcnRhaW50eSwgYW5kIGRpYWdub3N0aWMgZXZhbHVhdGlvbiByYXRoZXIgdGhhbiBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UgYWxvbmUuDQoNCiMgMi4gTGl0ZXJhdHVyZSBSZXZpZXcNCg0KIyMgMi4xIE9iZXNpdHkgYW5kIEdlb2dyYXBoaWMgRGlmZmVyZW5jZXMNCg0KUHVibGljLWhlYWx0aCByZXNlYXJjaCBoYXMgZXhhbWluZWQgb2Jlc2l0eSBpbiByZWxhdGlvbiB0byBiZWhhdmlvcmFsLCBzb2Npb2Vjb25vbWljLCBhbmQgZW52aXJvbm1lbnRhbCBjaGFyYWN0ZXJpc3RpY3MuIEEgY291bnR5LWxldmVsIHBlcnNwZWN0aXZlIGlzIHVzZWZ1bCBiZWNhdXNlIGNvdW50aWVzIHdpdGhpbiB0aGUgc2FtZSBzdGF0ZSBjYW4gZGlmZmVyIHN1YnN0YW50aWFsbHkgaW4gcG9wdWxhdGlvbiBjb21wb3NpdGlvbiwgZWNvbm9taWMgY29uZGl0aW9ucywgYWNjZXNzIHRvIHJlc291cmNlcywgYW5kIGhlYWx0aC1yZWxhdGVkIGVudmlyb25tZW50cy4gVGhlIHByZXNlbnQgc3R1ZHkgdXNlcyB0aGlzIGdlb2dyYXBoaWMgdmFyaWF0aW9uIGFzIHRoZSBmb2N1cyBvZiBpdHMgYW5hbHlzaXMuDQoNCiMjIDIuMiBCZWhhdmlvcmFsIGFuZCBTb2Npb2Vjb25vbWljIENoYXJhY3RlcmlzdGljcw0KDQpQaHlzaWNhbCBhY3Rpdml0eSBpcyBhbiBpbXBvcnRhbnQgYmVoYXZpb3JhbCBjaGFyYWN0ZXJpc3RpYyBpbiB0aGUgc3R1ZHkgb2Ygb2Jlc2l0eS4gQ291bnR5LWxldmVsIGRpZmZlcmVuY2VzIGluIHBoeXNpY2FsIGFjdGl2aXR5IG1heSBiZSBhc3NvY2lhdGVkIHdpdGggZGlmZmVyZW5jZXMgaW4gb2Jlc2l0eSBwcmV2YWxlbmNlLiBFY29ub21pYyBhbmQgZWR1Y2F0aW9uYWwgY2hhcmFjdGVyaXN0aWNzIG1heSBhbHNvIGJlIHJlbGF0ZWQgdG8gY29tbXVuaXR5IHJlc291cmNlcywgb3Bwb3J0dW5pdGllcywgYW5kIGhlYWx0aCBjb25kaXRpb25zLiBUaGlzIHN0dWR5IHRoZXJlZm9yZSBjb25zaWRlcnMgcGh5c2ljYWwgaW5hY3Rpdml0eSwgYWxjb2hvbCB1c2UsIGVkdWNhdGlvbiwgdW5lbXBsb3ltZW50LCBhbmQgaG91c2Vob2xkIGluY29tZSBvciB3ZWFsdGggYXMgcG90ZW50aWFsIGV4cGxhbmF0b3J5IG9yIGNvbnRyb2wgdmFyaWFibGVzLg0KDQojIyAyLjMgRm9vZC1SZWxhdGVkIGFuZCBFbnZpcm9ubWVudGFsIENoYXJhY3RlcmlzdGljcw0KDQpGb29kIGluc2VjdXJpdHkgaXMgaW5jbHVkZWQgYXMgYSBjb3VudHktbGV2ZWwgbWVhc3VyZSBvZiBmb29kLXJlbGF0ZWQgZWNvbm9taWMgaGFyZHNoaXAuIEVudmlyb25tZW50YWwgY2hhcmFjdGVyaXN0aWNzLCBpbmNsdWRpbmcgc3VubGlnaHQgZXhwb3N1cmUgYW5kIHRoZSBFbnZpcm9ubWVudGFsIFF1YWxpdHkgSW5kZXggd2hlcmUgYXZhaWxhYmxlLCBhcmUgY29uc2lkZXJlZCBhcyBhZGRpdGlvbmFsIGNvbnRleHR1YWwgbWVhc3VyZXMuIFRoZXNlIHZhcmlhYmxlcyBhcmUgbm90IGFzc3VtZWQgdG8gcmVwcmVzZW50IGV2ZXJ5IGFzcGVjdCBvZiB0aGUgbG9jYWwgZm9vZCBvciBwaHlzaWNhbCBlbnZpcm9ubWVudDsgdGhleSBhcmUgaW5jbHVkZWQgYmVjYXVzZSB0aGV5IGFyZSBhdmFpbGFibGUgaW4gdGhlIHByb2plY3QncyBjb21waWxlZCBwdWJsaWMgZGF0YXNldHMuDQoNCiMjIDIuNCBHZW9ncmFwaGljIGFuZCBTcGF0aWFsIFZhcmlhdGlvbg0KDQpTdGF0ZSBmaXhlZCBlZmZlY3RzIHJlcHJlc2VudCBzeXN0ZW1hdGljIGRpZmZlcmVuY2VzIGFtb25nIHN0YXRlcyB0aGF0IGFyZSBub3QgY2FwdHVyZWQgYnkgdGhlIG1lYXN1cmVkIGV4cGxhbmF0b3J5IHZhcmlhYmxlcy4gSWYgdGhlIGZpeGVkLWVmZmVjdHMgbW9kZWwgaW1wcm92ZXMgbW9kZWwgZml0LCB0aGlzIHN1Z2dlc3RzIHRoYXQgc3RhdGUgbWVtYmVyc2hpcCBwcm92aWRlcyBhZGRpdGlvbmFsIGV4cGxhbmF0b3J5IGluZm9ybWF0aW9uLiBTdGF0ZSBmaXhlZCBlZmZlY3RzIGRvIG5vdCwgYnkgdGhlbXNlbHZlcywgaWRlbnRpZnkgbG9jYWwgc3BhdGlhbCBkZXBlbmRlbmNlIGJldHdlZW4gbmVpZ2hib3JpbmcgY291bnRpZXMuIEEgc2VwYXJhdGUgc3BhdGlhbC1hdXRvY29ycmVsYXRpb24gYW5hbHlzaXMgd291bGQgYmUgcmVxdWlyZWQgdG8gYXNzZXNzIHRoYXQgcXVlc3Rpb24uDQoNCiMjIDIuNSBSZXNlYXJjaCBDb250cmlidXRpb24NCg0KVGhlIGNvbnRyaWJ1dGlvbiBvZiB0aGlzIHN0dWR5IGlzIGl0cyBmb2N1cyBvbiB0aGUgYW1vdW50IG9mIGNvdW50eS1sZXZlbCBnZW9ncmFwaGljIHZhcmlhdGlvbiB0aGF0IHJlbWFpbnMgYWZ0ZXIgYWRqdXN0bWVudCBmb3IgbWVhc3VyZWQgYmVoYXZpb3JhbCwgc29jaW9lY29ub21pYywgZm9vZC1yZWxhdGVkLCBhbmQgZW52aXJvbm1lbnRhbCBjaGFyYWN0ZXJpc3RpY3MuIFRoZSBzdHVkeSBkb2VzIG5vdCBjbGFpbSB0aGF0IHRoZSBzZWxlY3RlZCBwcmVkaWN0b3JzIG9yIHRoZSBnZW9ncmFwaGljIGFwcHJvYWNoIGFyZSB1bnByZWNlZGVudGVkLiBSYXRoZXIsIGl0IGFwcGxpZXMgYSBjb25zaXN0ZW50IGNvdW50eS1sZXZlbCBtb2RlbGluZyBmcmFtZXdvcmsgdG8gYXNzZXNzIHRoZSBhZGRpdGlvbmFsIGV4cGxhbmF0b3J5IHZhbHVlIG9mIHN0YXRlLWxldmVsIGdlb2dyYXBoaWMgaW5kaWNhdG9ycy4NCg0KIyAzLiBSZXNlYXJjaCBRdWVzdGlvbnMgYW5kIEh5cG90aGVzZXMNCg0KIyMgMy4xIFByaW1hcnkgUmVzZWFyY2ggUXVlc3Rpb24NCg0KVG8gd2hhdCBleHRlbnQgZG8gY291bnR5LWxldmVsIGdlb2dyYXBoaWMgZGlmZmVyZW5jZXMgaW4gYWR1bHQgb2Jlc2l0eSBwcmV2YWxlbmNlIHJlbWFpbiBhZnRlciBjb250cm9sbGluZyBmb3Iga25vd24gYmVoYXZpb3JhbCwgc29jaW9lY29ub21pYywgZm9vZC1yZWxhdGVkLCBhbmQgZW52aXJvbm1lbnRhbCBmYWN0b3JzPw0KDQojIyAzLjIgU3VwcG9ydGluZyBSZXNlYXJjaCBRdWVzdGlvbnMNCg0KMS4gSG93IG11Y2ggdmFyaWF0aW9uIGluIGFkdWx0IG9iZXNpdHkgcHJldmFsZW5jZSBleGlzdHMgYWNyb3NzIFUuUy4gY291bnRpZXMgYmVmb3JlIGFjY291bnRpbmcgZm9yIG90aGVyIGNvdW50eS1sZXZlbCBjaGFyYWN0ZXJpc3RpY3M/DQoyLiBUbyB3aGF0IGV4dGVudCBhcmUgbWVhc3VyZWQgYmVoYXZpb3JhbCwgc29jaW9lY29ub21pYywgZm9vZC1yZWxhdGVkLCBhbmQgZW52aXJvbm1lbnRhbCBjaGFyYWN0ZXJpc3RpY3MgYXNzb2NpYXRlZCB3aXRoIGNvdW50eS1sZXZlbCBhZHVsdCBvYmVzaXR5IHByZXZhbGVuY2U/DQozLiBEb2VzIGFkZGluZyBzdGF0ZSBmaXhlZCBlZmZlY3RzIGltcHJvdmUgdGhlIGV4cGxhbmF0b3J5IHBlcmZvcm1hbmNlIG9mIHRoZSBtb2RlbCBhZnRlciBhZGp1c3RtZW50IGZvciB0aGUgbWVhc3VyZWQgY2hhcmFjdGVyaXN0aWNzPw0KNC4gRG8gcmVzaWR1YWwgZGlhZ25vc3RpY3MgaW5kaWNhdGUgaW1wb3J0YW50IGRlcGFydHVyZXMgZnJvbSB0aGUgYXNzdW1wdGlvbnMgb2YgdGhlIE9MUyByZWdyZXNzaW9uIG1vZGVsPw0KDQojIyAzLjMgSHlwb3RoZXNlcw0KDQotICoqSDE6KiogQ291bnR5LWxldmVsIGFkdWx0IG9iZXNpdHkgcHJldmFsZW5jZSB2YXJpZXMgYWNyb3NzIFUuUy4gY291bnRpZXMuDQotICoqSDI6KiogVGhlIHNlbGVjdGVkIGJlaGF2aW9yYWwsIHNvY2lvZWNvbm9taWMsIGZvb2QtcmVsYXRlZCwgYW5kIGVudmlyb25tZW50YWwgY2hhcmFjdGVyaXN0aWNzIGpvaW50bHkgZXhwbGFpbiBhIHN0YXRpc3RpY2FsbHkgbWVhbmluZ2Z1bCBwb3J0aW9uIG9mIHRoZSB2YXJpYXRpb24gaW4gY291bnR5LWxldmVsIGFkdWx0IG9iZXNpdHkgcHJldmFsZW5jZS4NCi0gKipIMzoqKiBBZGRpbmcgc3RhdGUgZml4ZWQgZWZmZWN0cyBpbXByb3ZlcyBtb2RlbCBmaXQgYmV5b25kIHRoZSBiYXNlbGluZSBtb2RlbCBjb250YWluaW5nIG1lYXN1cmVkIGNvdW50eS1sZXZlbCBjaGFyYWN0ZXJpc3RpY3MuDQotICoqSDQ6KiogQWZ0ZXIgYWRqdXN0bWVudCwgcmVzaWR1YWxzIG1heSBzdGlsbCBleGhpYml0IHBhdHRlcm5zIHRoYXQgaW5kaWNhdGUgdW5leHBsYWluZWQgY291bnR5LWxldmVsIHZhcmlhdGlvbi4gVGhpcyBoeXBvdGhlc2lzIHdpbGwgYmUgZXZhbHVhdGVkIGRlc2NyaXB0aXZlbHk7IHN0YXRlIGZpeGVkIGVmZmVjdHMgYWxvbmUgYXJlIG5vdCBhIHRlc3Qgb2YgbmVpZ2hib3JpbmctY291bnR5IHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uLg0KDQojIDQuIERhdGEgYW5kIFZhcmlhYmxlcw0KDQojIyA0LjEgRGF0YSBTb3VyY2VzDQoNClRoZSBwcm9qZWN0IHJlcG9zaXRvcnkgY29udGFpbnMgdGhlIGNvdW50eS1sZXZlbCBzb3VyY2UgZmlsZXMgdXNlZCBmb3IgdGhpcyBhbmFseXNpcy4gVGhlIGZpbGVzIGFyZSByZWFkIGRpcmVjdGx5IGZyb20gdGhlIHB1YmxpYyBHaXRIdWIgcmVwb3NpdG9yeSBzbyB0aGUgYW5hbHlzaXMgY2FuIGJlIHJlcHJvZHVjZWQuIFRoZSBwcmluY2lwYWwgc291cmNlcyBpZGVudGlmaWVkIGluIHRoZSBhcHByb3ZlZCBwcm9wb3NhbCBpbmNsdWRlIHRoZSBJbnN0aXR1dGUgZm9yIEhlYWx0aCBNZXRyaWNzIGFuZCBFdmFsdWF0aW9uIChJSE1FKSwgVS5TLiBnb3Zlcm5tZW50IGRhdGFzZXRzLCB0aGUgVS5TLiBFbnZpcm9ubWVudGFsIFByb3RlY3Rpb24gQWdlbmN5LCBGZWVkaW5nIEFtZXJpY2EsIGFuZCBDREMgZW52aXJvbm1lbnRhbCBkYXRhLg0KDQpUaGUgZGF0YSBmaWxlcyBpbmNsdWRlOg0KDQotIGBJSE1FX09iZXNpdHkuY3N2YA0KLSBgSUhNRV9QaHlzaWNhbEFjdGl2aXR5LmNzdmANCi0gYEFsY29ob2xDb25zdW1wdGlvbi5jc3ZgDQotIGBFZHVjYXRpb24uY3N2YA0KLSBgVW5lbXBsb3ltZW50LmNzdmANCi0gYFdlYWx0aC5jc3ZgDQotIGBGb29kSW5zZWN1cml0eS5jc3ZgDQotIGBTdW5saWdodC5jc3ZgDQotIGBFbnZpcm9ubWVudGFsUXVhbGl0eUluZGV4LmNzdmANCi0gYHBvcHVsYXRpb24uY3N2YA0KDQpUaGUgYW5hbHlzaXMgdXNlcyBvbmx5IHZhcmlhYmxlcyB0aGF0IGNhbiBiZSBpZGVudGlmaWVkIGFuZCBtZXJnZWQgcmVsaWFibHkgZnJvbSB0aGUgYXZhaWxhYmxlIHNvdXJjZSBmaWxlcy4gVGhlIGNvZGUgYmVsb3cgcHJpbnRzIHRoZSBzZWxlY3RlZCBzb3VyY2UgY29sdW1ucyBhbmQgcmVwb3J0cyBhbnkgb3B0aW9uYWwgbWVhc3VyZSB0aGF0IGlzIG5vdCBmb3VuZC4gTWlzc2luZyB2YXJpYWJsZXMgYXJlIG5vdCBzaWxlbnRseSByZXBsYWNlZCB3aXRoIHVucmVsYXRlZCBtZWFzdXJlcy4NCg0KIyMgNC4yIE91dGNvbWUgVmFyaWFibGUNCg0KVGhlIElITUUgb2Jlc2l0eSBmaWxlIGNvbnRhaW5zIHNlcGFyYXRlIG1hbGUgYW5kIGZlbWFsZSBjb3VudHkgcHJldmFsZW5jZSBlc3RpbWF0ZXMgZm9yIDIwMDkuIEZvciB0aGlzIGFuYWx5c2lzLCB0aGUgcHJpbWFyeSBvdXRjb21lIGlzIGRlZmluZWQgYXMgdGhlIGFyaXRobWV0aWMgbWVhbiBvZiB0aG9zZSB0d28gZXN0aW1hdGVzOg0KDQpcWw0KXHRleHR7QWR1bHQgT2Jlc2l0eX1fe2l9ID0NClxmcmFje1x0ZXh0e01hbGUgT2Jlc2l0eX1fe2ksMjAwOX0rDQpcdGV4dHtGZW1hbGUgT2Jlc2l0eX1fe2ksMjAwOX19ezJ9DQpcXQ0KDQpUaGlzIGlzIGFuIGFwcHJveGltYXRpb24sIG5vdCBhIHBvcHVsYXRpb24td2VpZ2h0ZWQgY29tYmluZWQgcHJldmFsZW5jZSBlc3RpbWF0ZS4gQSBwb3B1bGF0aW9uLXdlaWdodGVkIG92ZXJhbGwgZXN0aW1hdGUgd291bGQgcmVxdWlyZSBjb3VudHktbGV2ZWwgbWFsZSBhbmQgZmVtYWxlIHBvcHVsYXRpb24gd2VpZ2h0cyB0aGF0IGFyZSBhbGlnbmVkIHRvIHRoZSBzYW1lIHllYXIgYW5kIGRlZmluaXRpb24uIFRoZSBvdXRjb21lIGlzIGV4cHJlc3NlZCBpbiBwZXJjZW50YWdlIHBvaW50cy4NCg0KIyMgNC4zIEV4cGxhbmF0b3J5IFZhcmlhYmxlcw0KDQp8IFZhcmlhYmxlIHwgUm9sZSB8IE1lYXN1cmVtZW50IC8gaW50ZXJwcmV0YXRpb24gfA0KfDotLXw6LS18Oi0tfA0KfCBQaHlzaWNhbCBpbmFjdGl2aXR5IHwgQmVoYXZpb3JhbCB8IDEwMCBtaW51cyB0aGUgYXZlcmFnZSBtYWxlL2ZlbWFsZSBzdWZmaWNpZW50IHBoeXNpY2FsIGFjdGl2aXR5IHByZXZhbGVuY2UsIHdoZXJlIGF2YWlsYWJsZSB8DQp8IEFsY29ob2wgdXNlIHwgQmVoYXZpb3JhbCB8IENvdW50eS1sZXZlbCBhbGNvaG9sLXVzZSBtZWFzdXJlIHN1cHBsaWVkIGluIHRoZSBwcm9qZWN0IHJlcG9zaXRvcnkgfA0KfCBFZHVjYXRpb25hbCBhdHRhaW5tZW50IHwgU29jaW9lY29ub21pYyB8IENvdW50eS1sZXZlbCBjb2xsZWdlIG9yIGJhY2hlbG9yJ3MgYXR0YWlubWVudCBtZWFzdXJlIHwNCnwgVW5lbXBsb3ltZW50IHwgU29jaW9lY29ub21pYyB8IENvdW50eSB1bmVtcGxveW1lbnQgcmF0ZSB8DQp8IEhvdXNlaG9sZCBpbmNvbWUgLyB3ZWFsdGggfCBTb2Npb2Vjb25vbWljIHwgQ291bnR5LWxldmVsIGluY29tZSBvciB3ZWFsdGggbWVhc3VyZSB8DQp8IEZvb2QgaW5zZWN1cml0eSB8IEZvb2QtcmVsYXRlZCB8IENvdW50eS1sZXZlbCBmb29kLWluc2VjdXJpdHkgbWVhc3VyZSB8DQp8IFN1bmxpZ2h0IGV4cG9zdXJlIHwgRW52aXJvbm1lbnRhbCB8IEF2ZXJhZ2UgZGFpbHkgc3VubGlnaHQsIHdoZXJlIGF2YWlsYWJsZSB8DQp8IEVudmlyb25tZW50YWwgcXVhbGl0eSB8IEVudmlyb25tZW50YWwgfCBFbnZpcm9ubWVudGFsIFF1YWxpdHkgSW5kZXgsIHdoZXJlIGF2YWlsYWJsZSB8DQp8IFBvcHVsYXRpb24gfCBDb250ZXh0dWFsIHwgQ291bnR5IHBvcHVsYXRpb247IGNvbnNpZGVyZWQgYXMgbG9nIHBvcHVsYXRpb24gaW4gYSBzZW5zaXRpdml0eSBzcGVjaWZpY2F0aW9uIHwNCnwgU3RhdGUgfCBHZW9ncmFwaGljIHwgU3RhdGUgaW5kaWNhdG9yIHVzZWQgZm9yIGZpeGVkIGVmZmVjdHMgfA0KDQojIyA0LjQgR2VvZ3JhcGhpYyBEYXRhIEludGVncmF0aW9uDQoNCkNvdW50eSByZWNvcmRzIGFyZSBtYXRjaGVkIHVzaW5nIHN0YW5kYXJkaXplZCBzdGF0ZSBhbmQgY291bnR5IG5hbWVzLiBUaGUgb3JpZ2luYWwgcHJvcG9zYWwgZGVzY3JpYmVkIHRoZSB1c2Ugb2YgZml2ZS1kaWdpdCBGSVBTIGNvZGVzLiBUaGUgY3VycmVudCByZXBvc2l0b3J5IGZpbGVzIGRvIG5vdCBhbGwgZXhwb3NlIGEgY29uc2lzdGVudGx5IG5hbWVkIEZJUFMgZmllbGQsIHNvIHRoaXMgdmVyc2lvbiB1c2VzIGEgbm9ybWFsaXplZCBzdGF0ZS1wbHVzLWNvdW50eSBrZXkuIFRoaXMgYXBwcm9hY2ggYXZvaWRzIG1hdGNoaW5nIGNvdW50aWVzIHdpdGggdGhlIHNhbWUgbmFtZSBpbiBkaWZmZXJlbnQgc3RhdGVzLCBidXQgaXQgaXMgbm90IGVxdWl2YWxlbnQgdG8gYSB2ZXJpZmllZCBGSVBTIGpvaW4uIFRoZSBtZXJnZSBkaWFnbm9zdGljcyBiZWxvdyByZXBvcnQgdW5tYXRjaGVkIHJlY29yZHMgYW5kIHNob3VsZCBiZSByZXZpZXdlZCBiZWZvcmUgdGhlIHJlc3VsdHMgYXJlIGZpbmFsaXplZC4NCg0KYGBge3IgZGF0YS1pbXBvcnR9DQpyZXBvX2Jhc2UgPC0gImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9CSUtBU0hCSE9XTUlLMTUvRGF0YS02OTgvbWFpbi8iDQoNCnJlYWRfcHJvamVjdF9jc3YgPC0gZnVuY3Rpb24oZmlsZW5hbWUpIHsNCiAgdXJsIDwtIHBhc3RlMChyZXBvX2Jhc2UsIGZpbGVuYW1lKQ0KICB0cnlDYXRjaCgNCiAgICByZWFkcjo6cmVhZF9jc3YodXJsLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFLCBuYW1lX3JlcGFpciA9ICJ1bmlxdWUiKSwNCiAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsNCiAgICAgIHN0b3AoIkNvdWxkIG5vdCByZWFkICIsIGZpbGVuYW1lLCAiLiBDaGVjayB0aGUgcmVwb3NpdG9yeSBmaWxlbmFtZSBhbmQgaW50ZXJuZXQgY29ubmVjdGlvbi4gRGV0YWlsczogIiwNCiAgICAgICAgICAgY29uZGl0aW9uTWVzc2FnZShlKSkNCiAgICB9DQogICkNCn0NCg0Kbm9ybWFsaXplX3N0YXRlIDwtIGZ1bmN0aW9uKHgpIHsNCiAgeCA8LSBzdHJpbmdyOjpzdHJfc3F1aXNoKGFzLmNoYXJhY3Rlcih4KSkNCiAgeCA8LSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwoeCwgIlxcLiIsICIiKQ0KICBhYmJyIDwtIG1hdGNoKHRvdXBwZXIoeCksIHN0YXRlLmFiYikNCiAgeFshaXMubmEoYWJicildIDwtIHN0YXRlLm5hbWVbYWJiclshaXMubmEoYWJicildXQ0KICBkcGx5cjo6Y2FzZV93aGVuKA0KICAgIHRvdXBwZXIoeCkgJWluJSBjKCJEQyIsICJESVNUUklDVCBPRiBDT0xVTUJJQSIpIH4gIkRpc3RyaWN0IG9mIENvbHVtYmlhIiwNCiAgICBUUlVFIH4gc3RyaW5ncjo6c3RyX3RvX3RpdGxlKHgpDQogICkNCn0NCg0Kbm9ybWFsaXplX2NvdW50eSA8LSBmdW5jdGlvbih4KSB7DQogIHggPC0gYXMuY2hhcmFjdGVyKHgpDQogIHggPC0gc3RyaW5naTo6c3RyaV90cmFuc19nZW5lcmFsKHgsICJMYXRpbi1BU0NJSSIpDQogIHggPC0gc3RyaW5ncjo6c3RyX3RvX2xvd2VyKHgpDQogIHggPC0gc3RyaW5ncjo6c3RyX3JlcGxhY2UoeCwgIiwuKiQiLCAiIikNCiAgeCA8LSBzdHJpbmdyOjpzdHJfcmVtb3ZlKHgsICJcXHMrKGNvdW50eXxwYXJpc2h8Ym9yb3VnaHxjZW5zdXMgYXJlYXxtdW5pY2lwYWxpdHkpJCIpDQogIHggPC0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKHgsICJbXmEtejAtOV0iLCAiIikNCiAgeA0KfQ0KDQpmaW5kX2NvbHVtbiA8LSBmdW5jdGlvbihkYXRhLCBwYXR0ZXJucywgcmVxdWlyZWQgPSBUUlVFLCBsYWJlbCA9ICJ2YXJpYWJsZSIpIHsNCiAgbm0gPC0gbmFtZXMoZGF0YSkNCiAgaGl0cyA8LSB1bmlxdWUodW5saXN0KGxhcHBseShwYXR0ZXJucywgZnVuY3Rpb24ocCkgew0KICAgIHdoaWNoKHN0cmluZ3I6OnN0cl9kZXRlY3Qobm0sIHN0cmluZ3I6OnJlZ2V4KHAsIGlnbm9yZV9jYXNlID0gVFJVRSkpKQ0KICB9KSkpDQogIGlmIChsZW5ndGgoaGl0cykgPT0gMCkgew0KICAgIGlmIChyZXF1aXJlZCkgew0KICAgICAgc3RvcCgiQ291bGQgbm90IGlkZW50aWZ5ICIsIGxhYmVsLCAiLiBBdmFpbGFibGUgY29sdW1uczogIiwNCiAgICAgICAgICAgcGFzdGUobm0sIGNvbGxhcHNlID0gIiB8ICIpKQ0KICAgIH0NCiAgICByZXR1cm4oTkFfY2hhcmFjdGVyXykNCiAgfQ0KICBubVtoaXRzWzFdXQ0KfQ0KDQpzdGFuZGFyZGl6ZV9nZW8gPC0gZnVuY3Rpb24oZGF0YSwgc291cmNlX25hbWUgPSAiZGF0YXNldCIpIHsNCg0KICBvcmlnaW5hbF9uYW1lcyA8LSBuYW1lcyhkYXRhKQ0KDQogICMgTm9ybWFsaXplIGNvbHVtbiBuYW1lczogcmVtb3ZlIHNwYWNlcywgdW5kZXJzY29yZXMsDQogICMgcHVuY3R1YXRpb24sIGFuZCBjb252ZXJ0IHRvIGxvd2VyY2FzZQ0KICBub3JtYWxpemVkX25hbWVzIDwtIHRvbG93ZXIoDQogICAgZ3N1YigiW15hLXpBLVowLTldIiwgIiIsIG9yaWdpbmFsX25hbWVzKQ0KICApDQoNCiAgIyBJZGVudGlmeSBzdGF0ZSBjb2x1bW4NCiAgc3RhdGVfaWR4IDwtIHdoaWNoKA0KICAgIG5vcm1hbGl6ZWRfbmFtZXMgJWluJSBjKCJzdGF0ZSIsICJzdGFiciIsICJzdGF0ZW5hbWUiLCAic3RuYW1lIikNCiAgKVsxXQ0KDQogICMgSWRlbnRpZnkgY291bnR5IGNvbHVtbg0KICBjb3VudHlfaWR4IDwtIHdoaWNoKA0KICAgIG5vcm1hbGl6ZWRfbmFtZXMgJWluJSBjKA0KICAgICAgImNvdW50eSIsDQogICAgICAibG9jYXRpb24iLA0KICAgICAgImFyZWFuYW1lIiwNCiAgICAgICJjb3VudHluYW1lIiwNCiAgICAgICJjb3VudHlzdGF0ZSIsDQogICAgICAiY3R5bmFtZSINCiAgICApDQogIClbMV0NCg0KICBpZiAoaXMubmEoc3RhdGVfaWR4KSkgew0KICAgIHN0b3AoDQogICAgICBwYXN0ZTAoDQogICAgICAgICJDb3VsZCBub3QgaWRlbnRpZnkgc3RhdGUgY29sdW1uIGluICIsDQogICAgICAgIHNvdXJjZV9uYW1lLA0KICAgICAgICAiLiBBdmFpbGFibGUgY29sdW1uczogIiwNCiAgICAgICAgcGFzdGUob3JpZ2luYWxfbmFtZXMsIGNvbGxhcHNlID0gIiB8ICIpDQogICAgICApDQogICAgKQ0KICB9DQoNCiAgaWYgKGlzLm5hKGNvdW50eV9pZHgpKSB7DQogICAgc3RvcCgNCiAgICAgIHBhc3RlMCgNCiAgICAgICAgIkNvdWxkIG5vdCBpZGVudGlmeSBjb3VudHkgY29sdW1uIGluICIsDQogICAgICAgIHNvdXJjZV9uYW1lLA0KICAgICAgICAiLiBBdmFpbGFibGUgY29sdW1uczogIiwNCiAgICAgICAgcGFzdGUob3JpZ2luYWxfbmFtZXMsIGNvbGxhcHNlID0gIiB8ICIpDQogICAgICApDQogICAgKQ0KICB9DQoNCiAgc3RhdGVfb3JpZ2luYWwgPC0gb3JpZ2luYWxfbmFtZXNbc3RhdGVfaWR4XQ0KICBjb3VudHlfb3JpZ2luYWwgPC0gb3JpZ2luYWxfbmFtZXNbY291bnR5X2lkeF0NCg0KICBkYXRhICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgIFN0YXRlID0gc3RyaW5ncjo6c3RyX3NxdWlzaChhcy5jaGFyYWN0ZXIoLmRhdGFbW3N0YXRlX29yaWdpbmFsXV0pKSwNCiAgICAgIENvdW50eSA9IHN0cmluZ3I6OnN0cl9zcXVpc2goYXMuY2hhcmFjdGVyKC5kYXRhW1tjb3VudHlfb3JpZ2luYWxdXSkpDQogICAgKSAlPiUNCiAgICBtdXRhdGUoDQogICAgICBDb3VudHlfa2V5ID0gcGFzdGUoDQogICAgICAgIG5vcm1hbGl6ZV9zdGF0ZShTdGF0ZSksDQogICAgICAgIG5vcm1hbGl6ZV9jb3VudHkoQ291bnR5KSwNCiAgICAgICAgc2VwID0gInwiDQogICAgICApDQogICAgKQ0KfQ0KDQpudW1lcmljX3ZhbHVlIDwtIGZ1bmN0aW9uKHgpIHsNCiAgcmVhZHI6OnBhcnNlX251bWJlcihhcy5jaGFyYWN0ZXIoeCksIG5hID0gYygiIiwgIk5BIiwgIk4vQSIsICItIiwgIuKAlCIpKQ0KfQ0KDQptYWtlX29uZV92YXJpYWJsZSA8LSBmdW5jdGlvbihmaWxlbmFtZSwgb3V0cHV0X25hbWUsIHBhdHRlcm5zLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZWQgPSBGQUxTRSwgdHJhbnNmb3JtID0gaWRlbnRpdHkpIHsNCiAgcmF3IDwtIHJlYWRfcHJvamVjdF9jc3YoZmlsZW5hbWUpDQogIGdlbyA8LSBzdGFuZGFyZGl6ZV9nZW8ocmF3LCBmaWxlbmFtZSkNCiAgdmFsdWVfY29sIDwtIGZpbmRfY29sdW1uKA0KICAgIGdlbywgcGF0dGVybnMsIHJlcXVpcmVkID0gcmVxdWlyZWQsDQogICAgbGFiZWwgPSBwYXN0ZShvdXRwdXRfbmFtZSwgImluIiwgZmlsZW5hbWUpDQogICkNCg0KICBpZiAoaXMubmEodmFsdWVfY29sKSkgew0KICAgIG1lc3NhZ2UoIk9wdGlvbmFsIHZhcmlhYmxlIG5vdCBmb3VuZDsgb21pdHRlZDogIiwgb3V0cHV0X25hbWUsDQogICAgICAgICAgICAiICgiLCBmaWxlbmFtZSwgIikiKQ0KICAgIHJldHVybihOVUxMKQ0KICB9DQoNCiAgbWVzc2FnZSgiTWFwcGVkICIsIG91dHB1dF9uYW1lLCAiIGZyb20gIiwgZmlsZW5hbWUsICIgY29sdW1uOiAiLCB2YWx1ZV9jb2wpDQoNCiAgZ2VvICU+JQ0KICAgIHRyYW5zbXV0ZSgNCiAgICAgIFN0YXRlLCBDb3VudHlfa2V5LA0KICAgICAgISFvdXRwdXRfbmFtZSA6PSB0cmFuc2Zvcm0obnVtZXJpY192YWx1ZSguZGF0YVtbdmFsdWVfY29sXV0pKQ0KICAgICkgJT4lDQogICAgZGlzdGluY3QoU3RhdGUsIENvdW50eV9rZXksIC5rZWVwX2FsbCA9IFRSVUUpDQp9DQpgYGANCg0KIyMgNC41IENvbnN0cnVjdGluZyB0aGUgQ291bnR5LUxldmVsIEFuYWx5dGljYWwgRGF0YXNldA0KDQpgYGB7ciBidWlsZC1kYXRhc2V0fQ0KIyBPdXRjb21lOiBhdmVyYWdlIG9mIHRoZSBtYWxlIGFuZCBmZW1hbGUgMjAwOSBvYmVzaXR5IGVzdGltYXRlcy4NCm9iZXNpdHlfcmF3IDwtIHJlYWRfcHJvamVjdF9jc3YoIklITUVfT2Jlc2l0eS5jc3YiKQ0Kb2Jlc2l0eV9nZW8gPC0gc3RhbmRhcmRpemVfZ2VvKG9iZXNpdHlfcmF3LCAiSUhNRV9PYmVzaXR5LmNzdiIpDQoNCm1hbGVfb2Jlc2l0eV9jb2wgPC0gZmluZF9jb2x1bW4oDQogIG9iZXNpdHlfZ2VvLCAiXk1hbGUgb2Jlc2l0eSBwcmV2YWxlbmNlLCAyMDA5IiwNCiAgbGFiZWwgPSAibWFsZSAyMDA5IG9iZXNpdHkgcHJldmFsZW5jZSINCikNCmZlbWFsZV9vYmVzaXR5X2NvbCA8LSBmaW5kX2NvbHVtbigNCiAgb2Jlc2l0eV9nZW8sICJeRmVtYWxlXFxzK29iZXNpdHlcXHMrcHJldmFsZW5jZSxcXHMqMjAwOSIsDQogIGxhYmVsID0gImZlbWFsZSAyMDA5IG9iZXNpdHkgcHJldmFsZW5jZSINCikNCg0Kb2Jlc2l0eV9kYXRhIDwtIG9iZXNpdHlfZ2VvICU+JQ0KICB0cmFuc211dGUoDQogICAgU3RhdGUsIENvdW50eV9rZXksDQogICAgbWFsZV9vYmVzaXR5XzIwMDkgPSBudW1lcmljX3ZhbHVlKC5kYXRhW1ttYWxlX29iZXNpdHlfY29sXV0pLA0KICAgIGZlbWFsZV9vYmVzaXR5XzIwMDkgPSBudW1lcmljX3ZhbHVlKC5kYXRhW1tmZW1hbGVfb2Jlc2l0eV9jb2xdXSksDQogICAgYWR1bHRfb2Jlc2l0eSA9IHJvd01lYW5zKA0KICAgICAgY2JpbmQoDQogICAgICAgIG51bWVyaWNfdmFsdWUoLmRhdGFbW21hbGVfb2Jlc2l0eV9jb2xdXSksDQogICAgICAgIG51bWVyaWNfdmFsdWUoLmRhdGFbW2ZlbWFsZV9vYmVzaXR5X2NvbF1dKQ0KICAgICAgKSwNCiAgICAgIG5hLnJtID0gVFJVRQ0KICAgICkNCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIGFkdWx0X29iZXNpdHkgPSBpZmVsc2UoaXMubmFuKGFkdWx0X29iZXNpdHkpLCBOQV9yZWFsXywgYWR1bHRfb2Jlc2l0eSkNCiAgKSAlPiUNCiAgZGlzdGluY3QoU3RhdGUsIENvdW50eV9rZXksIC5rZWVwX2FsbCA9IFRSVUUpDQoNCiMgUGh5c2ljYWwgaW5hY3Rpdml0eTogY29tcGxlbWVudCBvZiBzdWZmaWNpZW50IHBoeXNpY2FsIGFjdGl2aXR5IHByZXZhbGVuY2UuDQphY3Rpdml0eV9yYXcgPC0gcmVhZF9wcm9qZWN0X2NzdigiSUhNRV9QaHlzaWNhbEFjdGl2aXR5LmNzdiIpDQphY3Rpdml0eV9nZW8gPC0gc3RhbmRhcmRpemVfZ2VvKGFjdGl2aXR5X3JhdywgIklITUVfUGh5c2ljYWxBY3Rpdml0eS5jc3YiKQ0KDQptYWxlX2FjdGl2aXR5X2NvbCA8LSBmaW5kX2NvbHVtbigNCiAgYWN0aXZpdHlfZ2VvLA0KICAiXk1hbGVcXHMrc3VmZmljaWVudFxccytwaHlzaWNhbFxccythY3Rpdml0eVxccytwcmV2YWxlbmNlLFxccyoyMDA5IiwNCiAgbGFiZWwgPSAibWFsZSAyMDA5IHN1ZmZpY2llbnQgcGh5c2ljYWwgYWN0aXZpdHkiDQopDQpmZW1hbGVfYWN0aXZpdHlfY29sIDwtIGZpbmRfY29sdW1uKA0KICBhY3Rpdml0eV9nZW8sDQogICJeRmVtYWxlXFxzK3N1ZmZpY2llbnRcXHMrcGh5c2ljYWxcXHMrYWN0aXZpdHlcXHMrcHJldmFsZW5jZSxcXHMqMjAwOSIsDQogIGxhYmVsID0gImZlbWFsZSAyMDA5IHN1ZmZpY2llbnQgcGh5c2ljYWwgYWN0aXZpdHkiDQopDQoNCmFjdGl2aXR5X2RhdGEgPC0gYWN0aXZpdHlfZ2VvICU+JQ0KICB0cmFuc211dGUoDQogICAgU3RhdGUsIENvdW50eV9rZXksDQogICAgcGh5c2ljYWxfaW5hY3Rpdml0eSA9IDEwMCAtIHJvd01lYW5zKA0KICAgICAgY2JpbmQoDQogICAgICAgIG51bWVyaWNfdmFsdWUoLmRhdGFbW21hbGVfYWN0aXZpdHlfY29sXV0pLA0KICAgICAgICBudW1lcmljX3ZhbHVlKC5kYXRhW1tmZW1hbGVfYWN0aXZpdHlfY29sXV0pDQogICAgICApLA0KICAgICAgbmEucm0gPSBUUlVFDQogICAgKQ0KICApICU+JQ0KICBtdXRhdGUoDQogICAgcGh5c2ljYWxfaW5hY3Rpdml0eSA9IGlmZWxzZSgNCiAgICAgIGlzLm5hbihwaHlzaWNhbF9pbmFjdGl2aXR5KSwgTkFfcmVhbF8sIHBoeXNpY2FsX2luYWN0aXZpdHkNCiAgICApDQogICkgJT4lDQogIGRpc3RpbmN0KFN0YXRlLCBDb3VudHlfa2V5LCAua2VlcF9hbGwgPSBUUlVFKQ0KDQojIEFkZGl0aW9uYWwgY2FuZGlkYXRlIG1lYXN1cmVzLiBBIHNvdXJjZSB2YXJpYWJsZSBpcyBpbmNsdWRlZCBvbmx5IHdoZW4gYQ0KIyBjb3JyZXNwb25kaW5nIGNvdW50eS1sZXZlbCBjb2x1bW4gY2FuIGJlIGlkZW50aWZpZWQuDQpvcHRpb25hbF9zb3VyY2VzIDwtIGxpc3QoDQogIG1ha2Vfb25lX3ZhcmlhYmxlKA0KICAgICJBbGNvaG9sQ29uc3VtcHRpb24uY3N2IiwgImFsY29ob2xfdXNlIiwNCiAgICBjKCJeSHZ5JCIsICJoZWF2eS4qKHByZXZhbGVuY2V8cmF0ZSkiLCAiaGVhdnkgZHJpbmtpbmciKQ0KICApLA0KICBtYWtlX29uZV92YXJpYWJsZSgNCiAgICAiRWR1Y2F0aW9uLmNzdiIsICJjb2xsZWdlX2VkdWNhdGlvbiIsDQogICAgYygiXkNvbGxlZ2UkIiwgImJhY2hlbG9yIiwgImNvbGxlZ2UuKnBlcmNlbnQiLCAiY29sbGVnZS4qcmF0ZSIpDQogICksDQogIG1ha2Vfb25lX3ZhcmlhYmxlKA0KICAgICJVbmVtcGxveW1lbnQuY3N2IiwgInVuZW1wbG95bWVudCIsDQogICAgYygiXlVuZW1wbG95bWVudF9yYXRlXzIwMTkkIiwgIl5VbmVtcGxveW1lbnQkIiwgInVuZW1wbG95bWVudC4qMjAxOSIpDQogICksDQogIG1ha2Vfb25lX3ZhcmlhYmxlKA0KICAgICJXZWFsdGguY3N2IiwgIm1lZGlhbl9pbmNvbWUiLA0KICAgIGMoIl5JbmNvbWUkIiwgIm1lZGlhbiBob3VzZWhvbGQgaW5jb21lIiwgIm1lZGlhbi4qaW5jb21lIiwgIndlYWx0aCIpDQogICksDQogIG1ha2Vfb25lX3ZhcmlhYmxlKA0KICAgICJGb29kSW5zZWN1cml0eS5jc3YiLCAiZm9vZF9pbnNlY3VyaXR5IiwNCiAgICBjKCJeRm9vZEluc2VjdXJpdHkkIiwgImZvb2QgaW5zZWN1cml0eS4qKHJhdGV8cGVyY2VudHxwY3QpPyIsDQogICAgICAiZm9vZCBpbnNlY3VyaXR5IikNCiAgKSwNCiAgbWFrZV9vbmVfdmFyaWFibGUoDQogICAgIlN1bmxpZ2h0LmNzdiIsICJzdW5saWdodCIsDQogICAgYygiXlN1biQiLCAiQXZnIERhaWx5IFN1bmxpZ2h0IiwgImF2ZXJhZ2VfZGFpbHlfc3VubGlnaHQiLA0KICAgICAgImF2ZXJhZ2UgZGFpbHkgc3VubGlnaHQiKQ0KICApLA0KICBtYWtlX29uZV92YXJpYWJsZSgNCiAgICAiRW52aXJvbm1lbnRhbFF1YWxpdHlJbmRleC5jc3YiLCAiZW52aXJvbm1lbnRhbF9xdWFsaXR5IiwNCiAgICBjKCJeRVFJJCIsICJlbnZpcm9ubWVudGFsIHF1YWxpdHkgaW5kZXgiKQ0KICApLA0KICBtYWtlX29uZV92YXJpYWJsZSgNCiAgICAicG9wdWxhdGlvbi5jc3YiLCAicG9wdWxhdGlvbiIsDQogICAgYygiXlBvcHVsYXRpb24kIiwgIlBPUEVTVElNQVRFMjAxOSIsICJwb3B1bGF0aW9uLioyMDE5IikNCiAgKQ0KKQ0KDQpvcHRpb25hbF9zb3VyY2VzIDwtIG9wdGlvbmFsX3NvdXJjZXNbIXZhcHBseShvcHRpb25hbF9zb3VyY2VzLCBpcy5udWxsLCBsb2dpY2FsKDEpKV0NCg0KYW5hbHlzaXNfZGF0YSA8LSBvYmVzaXR5X2RhdGEgJT4lDQogIGxlZnRfam9pbihhY3Rpdml0eV9kYXRhLCBieSA9IGMoIlN0YXRlIiwgIkNvdW50eV9rZXkiKSkNCg0KZm9yIChzb3VyY2VfZGF0YSBpbiBvcHRpb25hbF9zb3VyY2VzKSB7DQogIGFuYWx5c2lzX2RhdGEgPC0gYW5hbHlzaXNfZGF0YSAlPiUNCiAgICBsZWZ0X2pvaW4oc291cmNlX2RhdGEsIGJ5ID0gYygiU3RhdGUiLCAiQ291bnR5X2tleSIpKQ0KfQ0KDQphbmFseXNpc19kYXRhIDwtIGFuYWx5c2lzX2RhdGEgJT4lDQogIG11dGF0ZSgNCiAgICBsb2dfcG9wdWxhdGlvbiA9IGlmICgicG9wdWxhdGlvbiIgJWluJSBuYW1lcyguKSkgew0KICAgICAgaWZlbHNlKHBvcHVsYXRpb24gPiAwLCBsb2cocG9wdWxhdGlvbiksIE5BX3JlYWxfKQ0KICAgIH0gZWxzZSB7DQogICAgICBOQV9yZWFsXw0KICAgIH0NCiAgKQ0KDQojIEtlZXAgY291bnRpZXMgd2l0aCBhIHZhbGlkIG91dGNvbWUuDQphbmFseXNpc19kYXRhIDwtIGFuYWx5c2lzX2RhdGEgJT4lDQogIGZpbHRlcihpcy5maW5pdGUoYWR1bHRfb2Jlc2l0eSkpDQoNCiMgTWVyZ2UgZGlhZ25vc3RpY3MuDQptZXJnZV9zdW1tYXJ5IDwtIHRpYmJsZSgNCiAgTWVhc3VyZSA9IGMoDQogICAgIkNvdW50aWVzIHdpdGggb2Jlc2l0eSBvdXRjb21lIiwNCiAgICAiQ291bnRpZXMgd2l0aCBwaHlzaWNhbCBpbmFjdGl2aXR5IiwNCiAgICAiQ291bnRpZXMgd2l0aCBtaXNzaW5nIHBoeXNpY2FsIGluYWN0aXZpdHkiDQogICksDQogIENvdW50ID0gYygNCiAgICBucm93KGFuYWx5c2lzX2RhdGEpLA0KICAgIHN1bSghaXMubmEoYW5hbHlzaXNfZGF0YSRwaHlzaWNhbF9pbmFjdGl2aXR5KSksDQogICAgc3VtKGlzLm5hKGFuYWx5c2lzX2RhdGEkcGh5c2ljYWxfaW5hY3Rpdml0eSkpDQogICkNCikNCg0Ka25pdHI6OmthYmxlKA0KICBtZXJnZV9zdW1tYXJ5LA0KICBjYXB0aW9uID0gIkNvdW50eS1sZXZlbCBkYXRhIGF2YWlsYWJpbGl0eSBhZnRlciBtZXJnaW5nIg0KKSAlPiUNCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UpDQoNCiMgU2hvdyBhdmFpbGFibGUgdmFyaWFibGVzIGFuZCB0aGVpciBtaXNzaW5nbmVzcy4NCm1pc3NpbmduZXNzX3RhYmxlIDwtIHRpYmJsZSgNCiAgVmFyaWFibGUgPSBuYW1lcyhhbmFseXNpc19kYXRhKSwNCiAgTm9uX01pc3NpbmcgPSB2YXBwbHkoYW5hbHlzaXNfZGF0YSwgZnVuY3Rpb24oeCkgc3VtKCFpcy5uYSh4KSksIGludGVnZXIoMSkpLA0KICBNaXNzaW5nID0gdmFwcGx5KGFuYWx5c2lzX2RhdGEsIGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSksIGludGVnZXIoMSkpDQopDQoNCmtuaXRyOjprYWJsZSgNCiAgbWlzc2luZ25lc3NfdGFibGUsDQogIGNhcHRpb24gPSAiTWlzc2luZy12YWx1ZSBzdW1tYXJ5IGZvciB0aGUgbWVyZ2VkIGFuYWx5dGljYWwgZGF0YXNldCINCikgJT4lDQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFKQ0KYGBgDQoNCiMjIDQuNiBEYXRhIFF1YWxpdHkgYW5kIEFuYWx5c2lzIFNhbXBsZQ0KDQpUaGUgbnVtYmVyIG9mIGNvdW50aWVzIGF2YWlsYWJsZSBmb3IgZWFjaCBtZWFzdXJlIG1heSBkaWZmZXIgYmVjYXVzZSB0aGUgc291cmNlIGRhdGFzZXRzIG1heSBoYXZlIGRpZmZlcmVudCBnZW9ncmFwaGljIGNvdmVyYWdlIGFuZCBtaXNzaW5nIHZhbHVlcy4gVGhlIHJlZ3Jlc3Npb24gc2FtcGxlIGlzIHRoZXJlZm9yZSBkZWZpbmVkIGJ5IHRoZSBvYnNlcnZhdGlvbnMgd2l0aCBjb21wbGV0ZSBkYXRhIGZvciB0aGUgb3V0Y29tZSBhbmQgdGhlIHByZWRpY3RvcnMgaW5jbHVkZWQgaW4gdGhlIGZpbmFsIG1vZGVsLiBUaGUgZmluYWwgcGFwZXIgc2hvdWxkIHJlcG9ydCB0aGlzIHNhbXBsZSBzaXplIGFuZCBzaG91bGQgbm90IGltcGx5IHRoYXQgZXZlcnkgbW9kZWwgdXNlcyBhbGwgVS5TLiBjb3VudGllcy4NCg0KYGBge3IgZGF0YS1xdWFsaXR5fQ0Kc3VtbWFyeShhbmFseXNpc19kYXRhJGFkdWx0X29iZXNpdHkpDQoNCmNvdW50eV9jb3VudHMgPC0gYW5hbHlzaXNfZGF0YSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGNvdW50aWVzID0gbigpLA0KICAgIHN0YXRlcyA9IG5fZGlzdGluY3QoU3RhdGUpLA0KICAgIG1lYW5fb2Jlc2l0eSA9IG1lYW4oYWR1bHRfb2Jlc2l0eSwgbmEucm0gPSBUUlVFKSwNCiAgICBzZF9vYmVzaXR5ID0gc2QoYWR1bHRfb2Jlc2l0eSwgbmEucm0gPSBUUlVFKSwNCiAgICBtaW5fb2Jlc2l0eSA9IG1pbihhZHVsdF9vYmVzaXR5LCBuYS5ybSA9IFRSVUUpLA0KICAgIG1lZGlhbl9vYmVzaXR5ID0gbWVkaWFuKGFkdWx0X29iZXNpdHksIG5hLnJtID0gVFJVRSksDQogICAgbWF4X29iZXNpdHkgPSBtYXgoYWR1bHRfb2Jlc2l0eSwgbmEucm0gPSBUUlVFKQ0KICApDQoNCmtuaXRyOjprYWJsZSgNCiAgY291bnR5X2NvdW50cywNCiAgZGlnaXRzID0gMiwNCiAgY2FwdGlvbiA9ICJTdW1tYXJ5IG9mIHRoZSBjb3VudHktbGV2ZWwgb2Jlc2l0eSBvdXRjb21lIg0KKSAlPiUNCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UpDQpgYGANCg0KIyA1LiBNZXRob2RvbG9neQ0KDQojIyA1LjEgRXhwbG9yYXRvcnkgRGF0YSBBbmFseXNpcw0KDQpFeHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIGlzIHVzZWQgdG8gZGVzY3JpYmUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBhZHVsdCBvYmVzaXR5IHByZXZhbGVuY2UgYW5kIGV4YW1pbmUgdGhlIHJlbGF0aW9uc2hpcHMgYW1vbmcgdGhlIG91dGNvbWUgYW5kIGF2YWlsYWJsZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMuIERlc2NyaXB0aXZlIHN0YXRpc3RpY3MgYW5kIHZpc3VhbGl6YXRpb25zIGFyZSByZXZpZXdlZCBiZWZvcmUgZml0dGluZyByZWdyZXNzaW9uIG1vZGVscy4NCg0KYGBge3Igb2Jlc2l0eS1kaXN0cmlidXRpb259DQpnZ3Bsb3QoYW5hbHlzaXNfZGF0YSwgYWVzKHggPSBhZHVsdF9vYmVzaXR5KSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMzAsIGNvbG9yID0gIndoaXRlIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBDb3VudHktTGV2ZWwgQWR1bHQgT2Jlc2l0eSBQcmV2YWxlbmNlIiwNCiAgICB4ID0gIkFkdWx0IG9iZXNpdHkgcHJldmFsZW5jZSAoJSkiLA0KICAgIHkgPSAiTnVtYmVyIG9mIGNvdW50aWVzIg0KICApICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0KYGBge3Igc3RhdGUtZGlzdHJpYnV0aW9ufQ0Kc3RhdGVfc3VtbWFyeSA8LSBhbmFseXNpc19kYXRhICU+JQ0KICBncm91cF9ieShTdGF0ZSkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBjb3VudGllcyA9IG4oKSwNCiAgICBtZWFuX29iZXNpdHkgPSBtZWFuKGFkdWx0X29iZXNpdHksIG5hLnJtID0gVFJVRSksDQogICAgbWVkaWFuX29iZXNpdHkgPSBtZWRpYW4oYWR1bHRfb2Jlc2l0eSwgbmEucm0gPSBUUlVFKSwNCiAgICAuZ3JvdXBzID0gImRyb3AiDQogICkgJT4lDQogIGFycmFuZ2UoZGVzYyhtZWFuX29iZXNpdHkpKQ0KDQprbml0cjo6a2FibGUoDQogIGhlYWQoc3RhdGVfc3VtbWFyeSwgMTUpLA0KICBkaWdpdHMgPSAyLA0KICBjYXB0aW9uID0gIlN0YXRlcyB3aXRoIHRoZSBoaWdoZXN0IG1lYW4gY291bnR5LWxldmVsIG9iZXNpdHkgcHJldmFsZW5jZSAodG9wIDE1KSINCikgJT4lDQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFKQ0KDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQpzdGF0ZV9leHRyZW1lcyA8LSBiaW5kX3Jvd3MoDQogIHN0YXRlX3N1bW1hcnkgJT4lDQogICAgc2xpY2VfbWF4KG1lYW5fb2Jlc2l0eSwgbiA9IDEwKSAlPiUNCiAgICBtdXRhdGUoR3JvdXAgPSAiSGlnaGVzdCIpLA0KDQogIHN0YXRlX3N1bW1hcnkgJT4lDQogICAgc2xpY2VfbWluKG1lYW5fb2Jlc2l0eSwgbiA9IDEwKSAlPiUNCiAgICBtdXRhdGUoR3JvdXAgPSAiTG93ZXN0IikNCikgJT4lDQogIGFycmFuZ2UobWVhbl9vYmVzaXR5KSAlPiUNCiAgbXV0YXRlKFN0YXRlID0gZmFjdG9yKFN0YXRlLCBsZXZlbHMgPSBTdGF0ZSkpDQoNCmdncGxvdChzdGF0ZV9leHRyZW1lcywNCiAgICAgICBhZXMoeCA9IFN0YXRlLCB5ID0gbWVhbl9vYmVzaXR5LCBmaWxsID0gR3JvdXApKSArDQogIGdlb21fY29sKHdpZHRoID0gMC43KSArDQogIGNvb3JkX2ZsaXAoKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiU3RhdGVzIHdpdGggdGhlIEhpZ2hlc3QgYW5kIExvd2VzdCBNZWFuIENvdW50eSBPYmVzaXR5IiwNCiAgICB4ID0gTlVMTCwNCiAgICB5ID0gIk1lYW4gY291bnR5IG9iZXNpdHkgcHJldmFsZW5jZSAoJSkiLA0KICAgIGZpbGwgPSAiU3RhdGUgZ3JvdXAiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEyKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSINCiAgKQ0KYGBgDQoNCiMjIDUuMiBDb3JyZWxhdGlvbiBBbmFseXNpcw0KDQpQZWFyc29uIGNvcnJlbGF0aW9ucyBhcmUgdXNlZCBhcyBhbiBleHBsb3JhdG9yeSBtZWFzdXJlIG9mIGxpbmVhciBhc3NvY2lhdGlvbiBhbW9uZyBudW1lcmljIHZhcmlhYmxlcy4gQ29ycmVsYXRpb24gZG9lcyBub3QgZXN0YWJsaXNoIGNhdXNhdGlvbiBhbmQgZG9lcyBub3QgYWNjb3VudCBmb3Igb3RoZXIgdmFyaWFibGVzIGluIHRoZSBtb2RlbC4NCg0KYGBge3IgY29ycmVsYXRpb24tYW5hbHlzaXN9DQpudW1lcmljX2RhdGEgPC0gYW5hbHlzaXNfZGF0YSAlPiUNCiAgc2VsZWN0KHdoZXJlKGlzLm51bWVyaWMpKSAlPiUNCiAgc2VsZWN0KHdoZXJlKH4gc3VtKCFpcy5uYSgueCkpID4gMTApKQ0KDQpjb3JyZWxhdGlvbl9tYXRyaXggPC0gY29yKA0KICBudW1lcmljX2RhdGEsDQogIHVzZSA9ICJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiDQopDQoNCmNvcnJwbG90X2F2YWlsYWJsZSA8LSByZXF1aXJlTmFtZXNwYWNlKCJjb3JycGxvdCIsIHF1aWV0bHkgPSBUUlVFKQ0KDQppZiAoY29ycnBsb3RfYXZhaWxhYmxlKSB7DQogIGNvcnJwbG90Ojpjb3JycGxvdCgNCiAgICBjb3JyZWxhdGlvbl9tYXRyaXgsDQogICAgbWV0aG9kID0gImNvbG9yIiwNCiAgICB0eXBlID0gInVwcGVyIiwNCiAgICB0bC5jb2wgPSAiYmxhY2siLA0KICAgIHRsLmNleCA9IDAuNzUsDQogICAgYWRkQ29lZi5jb2wgPSAiYmxhY2siLA0KICAgIG51bWJlci5jZXggPSAwLjUNCiAgKQ0KfSBlbHNlIHsNCiAga25pdHI6OmthYmxlKA0KICAgIHJvdW5kKGNvcnJlbGF0aW9uX21hdHJpeCwgMiksDQogICAgY2FwdGlvbiA9ICJQZWFyc29uIGNvcnJlbGF0aW9uIG1hdHJpeCINCiAgKQ0KfQ0KYGBgDQoNCiMjIDUuMyBNdWx0aXBsZSBMaW5lYXIgUmVncmVzc2lvbg0KDQpUaGUgYmFzZWxpbmUgbW9kZWwgdXNlcyBhZHVsdCBvYmVzaXR5IHByZXZhbGVuY2UgYXMgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBhbmQgdGhlIGF2YWlsYWJsZSBjb3VudHktbGV2ZWwgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGFzIHByZWRpY3RvcnMuIFRoZSBtb2RlbCBpcyBzcGVjaWZpZWQgdXNpbmcgdGhlIHByZWRpY3RvcnMgdGhhdCBhcmUgc3VjY2Vzc2Z1bGx5IGlkZW50aWZpZWQgaW4gdGhlIHJlcG9zaXRvcnkgYW5kIGhhdmUgc3VmZmljaWVudCBub24tbWlzc2luZyBvYnNlcnZhdGlvbnMuDQoNClRoZSBnZW5lcmFsIG1vZGVsIGlzOg0KDQpcWw0KT2Jlc2l0eV9pID0gXGJldGFfMCArIFxzdW1fe2s9MX1ee0t9XGJldGFfayBYX3traX0gKyBcZXBzaWxvbl9pDQpcXQ0KDQp3aGVyZSBcKE9iZXNpdHlfaVwpIGlzIHRoZSBhZHVsdCBvYmVzaXR5IHByZXZhbGVuY2UgbWVhc3VyZSBmb3IgY291bnR5IFwoaVwpLCBcKFhfe2tpfVwpIHJlcHJlc2VudHMgdGhlIG1lYXN1cmVkIGNvdW50eS1sZXZlbCBjaGFyYWN0ZXJpc3RpY3MsIGFuZCBcKFxlcHNpbG9uX2lcKSBpcyB0aGUgZXJyb3IgdGVybS4NCg0KDQpgYGB7ciBtb2RlbC1lc3RpbWF0aW9ufQ0KY2FuZGlkYXRlX3ByZWRpY3RvcnMgPC0gYygNCiAgInBoeXNpY2FsX2luYWN0aXZpdHkiLA0KICAiYWxjb2hvbF91c2UiLA0KICAiY29sbGVnZV9lZHVjYXRpb24iLA0KICAidW5lbXBsb3ltZW50IiwNCiAgIm1lZGlhbl9pbmNvbWUiLA0KICAiZm9vZF9pbnNlY3VyaXR5IiwNCiAgInN1bmxpZ2h0IiwNCiAgImVudmlyb25tZW50YWxfcXVhbGl0eSIsDQogICJwb3B1bGF0aW9uIg0KKQ0KDQojIElkZW50aWZ5IHByZWRpY3RvcnMgYXZhaWxhYmxlIGluIHRoZSBkYXRhc2V0DQpleGlzdGluZ19wcmVkaWN0b3JzIDwtIGludGVyc2VjdCgNCiAgY2FuZGlkYXRlX3ByZWRpY3RvcnMsDQogIG5hbWVzKGFuYWx5c2lzX2RhdGEpDQopDQoNCiMgQ2hlY2sgcHJlZGljdG9yIHF1YWxpdHkNCnByZWRpY3Rvcl9kaWFnbm9zdGljcyA8LSBwdXJycjo6bWFwX2RmcigNCiAgZXhpc3RpbmdfcHJlZGljdG9ycywNCiAgZnVuY3Rpb24odikgew0KDQogICAgeCA8LSBhbmFseXNpc19kYXRhW1t2XV0NCg0KICAgIHRpYmJsZSgNCiAgICAgIFZhcmlhYmxlID0gdiwNCiAgICAgIE5vbl9NaXNzaW5nID0gc3VtKCFpcy5uYSh4KSksDQogICAgICBEaXN0aW5jdF9WYWx1ZXMgPSBkcGx5cjo6bl9kaXN0aW5jdCh4LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgRGF0YV9UeXBlID0gY2xhc3MoeClbMV0NCiAgICApDQogIH0NCikNCg0Ka25pdHI6OmthYmxlKA0KICBwcmVkaWN0b3JfZGlhZ25vc3RpY3MsDQogIGNhcHRpb24gPSAiUmVncmVzc2lvbiBwcmVkaWN0b3IgZGlhZ25vc3RpY3MiDQopICU+JQ0KICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSkNCg0KIyBTZWxlY3QgdXNhYmxlIG51bWVyaWNhbCBwcmVkaWN0b3JzDQphdmFpbGFibGVfcHJlZGljdG9ycyA8LSBwcmVkaWN0b3JfZGlhZ25vc3RpY3MgJT4lDQogIGZpbHRlcigNCiAgICBOb25fTWlzc2luZyA+PSAxMDAsDQogICAgRGlzdGluY3RfVmFsdWVzID4gMSwNCiAgICBEYXRhX1R5cGUgJWluJSBjKCJudW1lcmljIiwgImludGVnZXIiKQ0KICApICU+JQ0KICBwdWxsKFZhcmlhYmxlKQ0KDQpjYXQoIlVzYWJsZSBwcmVkaWN0b3JzOiIsDQogICAgcGFzdGUoYXZhaWxhYmxlX3ByZWRpY3RvcnMsIGNvbGxhcHNlID0gIiwgIikpDQoNCmlmIChsZW5ndGgoYXZhaWxhYmxlX3ByZWRpY3RvcnMpIDwgMykgew0KICBzdG9wKA0KICAgICJGZXdlciB0aGFuIHRocmVlIHVzYWJsZSBwcmVkaWN0b3JzLiAiLA0KICAgICJSZXZpZXcgdGhlIGRpYWdub3N0aWMgdGFibGUgYmVmb3JlIGNvbnRpbnVpbmcuIg0KICApDQp9DQoNCiMgQ3JlYXRlIGNvbXBsZXRlLWNhc2UgcmVncmVzc2lvbiBkYXRhc2V0DQptb2RlbF92YXJpYWJsZXMgPC0gYygNCiAgImFkdWx0X29iZXNpdHkiLA0KICAiU3RhdGUiLA0KICAiQ291bnR5X2tleSIsDQogIGF2YWlsYWJsZV9wcmVkaWN0b3JzDQopDQoNCm1vZGVsX2RhdGEgPC0gYW5hbHlzaXNfZGF0YSAlPiUNCiAgc2VsZWN0KGFsbF9vZihtb2RlbF92YXJpYWJsZXMpKSAlPiUNCiAgZHJvcF9uYSgpICU+JQ0KICBtdXRhdGUoU3RhdGUgPSBmYWN0b3IoU3RhdGUpKQ0KDQppZiAobnJvdyhtb2RlbF9kYXRhKSA8IDEwMCkgew0KICBzdG9wKCJSZWdyZXNzaW9uIHNhbXBsZSBjb250YWlucyBmZXdlciB0aGFuIDEwMCBjb3VudGllcy4iKQ0KfQ0KDQojIEJhc2VsaW5lIE9MUyBtb2RlbA0KYmFzZWxpbmVfZm9ybXVsYSA8LSBhcy5mb3JtdWxhKA0KICBwYXN0ZSgNCiAgICAiYWR1bHRfb2Jlc2l0eSB+IiwNCiAgICBwYXN0ZShhdmFpbGFibGVfcHJlZGljdG9ycywgY29sbGFwc2UgPSAiICsgIikNCiAgKQ0KKQ0KDQptb2RlbF9vbHMgPC0gbG0oDQogIGJhc2VsaW5lX2Zvcm11bGEsDQogIGRhdGEgPSBtb2RlbF9kYXRhDQopDQoNCiMgU3RhdGUgZml4ZWQtZWZmZWN0cyBtb2RlbA0Kc3RhdGVfZm9ybXVsYSA8LSBhcy5mb3JtdWxhKA0KICBwYXN0ZSgNCiAgICAiYWR1bHRfb2Jlc2l0eSB+IiwNCiAgICBwYXN0ZShhdmFpbGFibGVfcHJlZGljdG9ycywgY29sbGFwc2UgPSAiICsgIiksDQogICAgIisgU3RhdGUiDQogICkNCikNCg0KbW9kZWxfc3RhdGUgPC0gbG0oDQogIHN0YXRlX2Zvcm11bGEsDQogIGRhdGEgPSBtb2RlbF9kYXRhDQopDQoNCmNhdCgiXG5SZWdyZXNzaW9uIHNhbXBsZToiLA0KICAgIG5yb3cobW9kZWxfZGF0YSksICJjb3VudGllcyIpDQoNCmNhdCgiXG5TdGF0ZXMgcmVwcmVzZW50ZWQ6IiwNCiAgICBuX2Rpc3RpbmN0KG1vZGVsX2RhdGEkU3RhdGUpKQ0KDQpjYXQoIlxuQmFzZWxpbmUgYWRqdXN0ZWQgUi1zcXVhcmVkOiIsDQogICAgcm91bmQoc3VtbWFyeShtb2RlbF9vbHMpJGFkai5yLnNxdWFyZWQsIDQpKQ0KDQpjYXQoIlxuU3RhdGUgbW9kZWwgYWRqdXN0ZWQgUi1zcXVhcmVkOiIsDQogICAgcm91bmQoc3VtbWFyeShtb2RlbF9zdGF0ZSkkYWRqLnIuc3F1YXJlZCwgNCkpDQpgYGANCg0KDQoNCiMjIDUuNCBTdGF0ZSBGaXhlZC1FZmZlY3RzIE1vZGVsDQoNClRoZSBnZW9ncmFwaGljIG1vZGVsIGFkZHMgc3RhdGUgaW5kaWNhdG9ycyB0byB0aGUgYmFzZWxpbmUgcmVncmVzc2lvbjoNCg0KXFsNCk9iZXNpdHlfe2lzfSA9IFxiZXRhXzAgKyBcc3VtX3trPTF9XntLfVxiZXRhX2sgWF97a2lzfSArIFxnYW1tYV9zICsgXGVwc2lsb25fe2lzfQ0KXF0NCg0Kd2hlcmUgXChcZ2FtbWFfc1wpIHJlcHJlc2VudHMgdGhlIHN0YXRlIGZpeGVkIGVmZmVjdC4gT25lIHN0YXRlIGlzIHRyZWF0ZWQgYXMgdGhlIHJlZmVyZW5jZSBjYXRlZ29yeSBieSB0aGUgcmVncmVzc2lvbiBzb2Z0d2FyZS4NCg0KVGhlIHN0YXRlIGZpeGVkLWVmZmVjdHMgbW9kZWwgdGVzdHMgd2hldGhlciBzdGF0ZSBtZW1iZXJzaGlwIGFkZHMgZXhwbGFuYXRvcnkgaW5mb3JtYXRpb24gYWZ0ZXIgYWRqdXN0bWVudCBmb3IgdGhlIG1lYXN1cmVkIGNvdW50eS1sZXZlbCB2YXJpYWJsZXMuIEl0IGRvZXMgbm90IGVzdGFibGlzaCB0aGF0IHN0YXRlIGxvY2F0aW9uIGNhdXNlcyBkaWZmZXJlbmNlcyBpbiBvYmVzaXR5IHByZXZhbGVuY2UuDQoNCiMjIDUuNSBNb2RlbCBFdmFsdWF0aW9uDQoNClRoZSBtb2RlbHMgYXJlIGNvbXBhcmVkIHVzaW5nIGFkanVzdGVkIFItc3F1YXJlZCBhbmQgUk1TRS4gQSBuZXN0ZWQtbW9kZWwgRi10ZXN0IGV2YWx1YXRlcyB3aGV0aGVyIHRoZSBzdGF0ZSBpbmRpY2F0b3JzIGNvbGxlY3RpdmVseSBpbXByb3ZlIHRoZSBpbi1zYW1wbGUgZml0LiBUaGVzZSBtZWFzdXJlcyBkZXNjcmliZSBleHBsYW5hdG9yeSBwZXJmb3JtYW5jZSBpbiB0aGUgYW5hbHlzaXMgc2FtcGxlIGFuZCBzaG91bGQgbm90IGJlIGNvbmZ1c2VkIHdpdGggb3V0LW9mLXNhbXBsZSBwcmVkaWN0aXZlIHZhbGlkYXRpb24uDQoNCmBgYHtyIG1vZGVsLWNvbXBhcmlzb259DQpybXNlIDwtIGZ1bmN0aW9uKG1vZGVsKSB7DQogIHNxcnQobWVhbihyZXNpZHVhbHMobW9kZWwpXjIpKQ0KfQ0KDQptb2RlbF9jb21wYXJpc29uIDwtIHRpYmJsZSgNCiAgTW9kZWwgPSBjKCJCYXNlbGluZSBPTFMiLCAiT0xTIHdpdGggc3RhdGUgZml4ZWQgZWZmZWN0cyIpLA0KICBPYnNlcnZhdGlvbnMgPSBjKG5vYnMobW9kZWxfb2xzKSwgbm9icyhtb2RlbF9zdGF0ZSkpLA0KICBSX1NxdWFyZWQgPSBjKHN1bW1hcnkobW9kZWxfb2xzKSRyLnNxdWFyZWQsDQogICAgICAgICAgICAgICAgc3VtbWFyeShtb2RlbF9zdGF0ZSkkci5zcXVhcmVkKSwNCiAgQWRqdXN0ZWRfUl9TcXVhcmVkID0gYyhzdW1tYXJ5KG1vZGVsX29scykkYWRqLnIuc3F1YXJlZCwNCiAgICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5KG1vZGVsX3N0YXRlKSRhZGouci5zcXVhcmVkKSwNCiAgUk1TRSA9IGMocm1zZShtb2RlbF9vbHMpLCBybXNlKG1vZGVsX3N0YXRlKSkNCikNCg0Ka25pdHI6OmthYmxlKA0KICBtb2RlbF9jb21wYXJpc29uLA0KICBkaWdpdHMgPSA0LA0KICBjYXB0aW9uID0gIkNvbXBhcmlzb24gb2YgYmFzZWxpbmUgYW5kIHN0YXRlIGZpeGVkLWVmZmVjdHMgbW9kZWxzIg0KKSAlPiUNCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UpDQoNCnN0YXRlX21vZGVsX3Rlc3QgPC0gYW5vdmEobW9kZWxfb2xzLCBtb2RlbF9zdGF0ZSkNCmtuaXRyOjprYWJsZSgNCiAgYnJvb206OnRpZHkoc3RhdGVfbW9kZWxfdGVzdCksDQogIGRpZ2l0cyA9IDQsDQogIGNhcHRpb24gPSAiTmVzdGVkLW1vZGVsIEYtdGVzdDogYWRkaXRpb25hbCBjb250cmlidXRpb24gb2Ygc3RhdGUgZml4ZWQgZWZmZWN0cyINCikgJT4lDQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFKQ0KYGBgDQoNCiMjIDUuNiBSZWdyZXNzaW9uIENvZWZmaWNpZW50cyBhbmQgVW5jZXJ0YWludHkNCg0KVGhlIGNvZWZmaWNpZW50cyBhcmUgaW50ZXJwcmV0ZWQgYXMgYWRqdXN0ZWQgY291bnR5LWxldmVsIGFzc29jaWF0aW9ucy4gQSBjb2VmZmljaWVudCByZXByZXNlbnRzIHRoZSBlc3RpbWF0ZWQgZGlmZmVyZW5jZSBpbiBhZHVsdCBvYmVzaXR5IHByZXZhbGVuY2UgYXNzb2NpYXRlZCB3aXRoIGEgb25lLXVuaXQgZGlmZmVyZW5jZSBpbiBhIHByZWRpY3RvciwgaG9sZGluZyB0aGUgb3RoZXIgaW5jbHVkZWQgdmFyaWFibGVzIGNvbnN0YW50LiBVbml0cyBtdXN0IGJlIGNvbnNpZGVyZWQgd2hlbiBpbnRlcnByZXRpbmcgdGhlIHNpemUgb2YgZWFjaCBjb2VmZmljaWVudC4NCg0KSGV0ZXJvc2NlZGFzdGljaXR5LWNvbnNpc3RlbnQgc3RhbmRhcmQgZXJyb3JzIChIQzMpIGFyZSByZXBvcnRlZCBhcyBhIHJvYnVzdG5lc3MgbWVhc3VyZS4NCg0KYGBge3IgY29lZmZpY2llbnQtcmVzdWx0c30NCnJvYnVzdF9yZXN1bHRzIDwtIGxtdGVzdDo6Y29lZnRlc3QoDQogIG1vZGVsX3N0YXRlLA0KICB2Y292LiA9IHNhbmR3aWNoOjp2Y292SEMobW9kZWxfc3RhdGUsIHR5cGUgPSAiSEMzIikNCikNCg0KY29lZmZpY2llbnRfdGFibGUgPC0gYnJvb206OnRpZHkocm9idXN0X3Jlc3VsdHMpICU+JQ0KICByZW5hbWUoDQogICAgRXN0aW1hdGUgPSBlc3RpbWF0ZSwNCiAgICBTdGRfRXJyb3JfSEMzID0gc3RkLmVycm9yLA0KICAgIHRfdmFsdWUgPSBzdGF0aXN0aWMsDQogICAgcF92YWx1ZSA9IHAudmFsdWUNCiAgKSAlPiUNCiAgbXV0YXRlKA0KICAgIENJX0xvd2VyID0gRXN0aW1hdGUgLSBxdCgwLjk3NSwgZGYucmVzaWR1YWwobW9kZWxfc3RhdGUpKSAqIFN0ZF9FcnJvcl9IQzMsDQogICAgQ0lfVXBwZXIgPSBFc3RpbWF0ZSArIHF0KDAuOTc1LCBkZi5yZXNpZHVhbChtb2RlbF9zdGF0ZSkpICogU3RkX0Vycm9yX0hDMw0KICApDQoNCmtuaXRyOjprYWJsZSgNCiAgY29lZmZpY2llbnRfdGFibGUsDQogIGRpZ2l0cyA9IDQsDQogIGNhcHRpb24gPSAiU3RhdGUgZml4ZWQtZWZmZWN0cyByZWdyZXNzaW9uIGNvZWZmaWNpZW50cyB3aXRoIEhDMyByb2J1c3Qgc3RhbmRhcmQgZXJyb3JzIg0KKSAlPiUNCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UsIGZvbnRfc2l6ZSA9IDEzKQ0KYGBgDQoNCiMjIDUuNyBSZWdyZXNzaW9uIERpYWdub3N0aWNzDQoNClJlZ3Jlc3Npb24gZGlhZ25vc3RpY3MgYXJlIHVzZWQgdG8gZXZhbHVhdGUgd2hldGhlciB0aGUgZml0dGVkIG1vZGVscyBzaG93IGltcG9ydGFudCBkZXBhcnR1cmVzIGZyb20gdGhlIGFzc3VtcHRpb25zIG9mIGxpbmVhciByZWdyZXNzaW9uLiBUaGUgYW5hbHlzaXMgZXhhbWluZXMgcmVzaWR1YWwgcGF0dGVybnMsIGFwcHJveGltYXRlIG5vcm1hbGl0eSwgaGV0ZXJvc2NlZGFzdGljaXR5LCBhbmQgbXVsdGljb2xsaW5lYXJpdHkuIFN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgY2F1dGlvdXNseSBiZWNhdXNlIGNvdW50aWVzIG1heSBub3QgYmUgc3RhdGlzdGljYWxseSBpbmRlcGVuZGVudC4NCg0KYGBge3IgZGlhZ25vc3RpYy1wbG90cywgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9OH0NCm9sZF9wYXIgPC0gcGFyKG5vLnJlYWRvbmx5ID0gVFJVRSkNCnBhcihtZnJvdyA9IGMoMiwgMikpDQpwbG90KG1vZGVsX3N0YXRlKQ0KcGFyKG9sZF9wYXIpDQpgYGANCg0KYGBge3IgdmlmLWRpYWdub3N0aWNzfQ0KdmlmX3ZhbHVlcyA8LSB0cnlDYXRjaCgNCiAgY2FyOjp2aWYobW9kZWxfc3RhdGUpLA0KICBlcnJvciA9IGZ1bmN0aW9uKGUpIE5VTEwNCikNCg0KaWYgKCFpcy5udWxsKHZpZl92YWx1ZXMpKSB7DQogIGlmIChpcy5tYXRyaXgodmlmX3ZhbHVlcykpIHsNCiAgICB2aWZfb3V0cHV0IDwtIGFzLmRhdGEuZnJhbWUodmlmX3ZhbHVlcykgJT4lDQogICAgICB0aWJibGU6OnJvd25hbWVzX3RvX2NvbHVtbigiVmFyaWFibGUiKQ0KICB9IGVsc2Ugew0KICAgIHZpZl9vdXRwdXQgPC0gdGliYmxlKA0KICAgICAgVmFyaWFibGUgPSBuYW1lcyh2aWZfdmFsdWVzKSwNCiAgICAgIFZJRiA9IGFzLm51bWVyaWModmlmX3ZhbHVlcykNCiAgICApDQogIH0NCg0KICBrbml0cjo6a2FibGUoDQogICAgdmlmX291dHB1dCwNCiAgICBkaWdpdHMgPSAzLA0KICAgIGNhcHRpb24gPSAiVmFyaWFuY2UgaW5mbGF0aW9uIGZhY3RvciBkaWFnbm9zdGljcyINCiAgKSAlPiUNCiAgICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSkNCn0gZWxzZSB7DQogIGNhdCgiVklGIGNvdWxkIG5vdCBiZSBjYWxjdWxhdGVkIGZvciB0aGlzIG1vZGVsIHNwZWNpZmljYXRpb24uIikNCn0NCmBgYA0KDQojIyA1LjggUmVzaWR1YWwgR2VvZ3JhcGhpYyBWYXJpYXRpb24NCg0KQSByZXNpZHVhbCBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG9ic2VydmVkIGFuZCBtb2RlbC1wcmVkaWN0ZWQgb2Jlc2l0eSBwcmV2YWxlbmNlOg0KDQpcWw0KUmVzaWR1YWxfaSA9IE9ic2VydmVkX2kgLSBQcmVkaWN0ZWRfaQ0KXF0NCg0KUG9zaXRpdmUgcmVzaWR1YWxzIGluZGljYXRlIHRoYXQgdGhlIG9ic2VydmVkIGNvdW50eSBwcmV2YWxlbmNlIGlzIGhpZ2hlciB0aGFuIHRoZSBtb2RlbCBwcmVkaWN0cy4gTmVnYXRpdmUgcmVzaWR1YWxzIGluZGljYXRlIHRoYXQgb2JzZXJ2ZWQgcHJldmFsZW5jZSBpcyBsb3dlciB0aGFuIHByZWRpY3RlZC4gUmVzaWR1YWxzIGFyZSBleGFtaW5lZCB0byBpZGVudGlmeSBjb3VudGllcyB3aXRoIGxhcmdlciBkZXZpYXRpb25zIGZyb20gdGhlIG1vZGVsLg0KDQpgYGB7ciByZXNpZHVhbC1hbmFseXNpc30NCm1vZGVsX2RhdGEgPC0gbW9kZWxfZGF0YSAlPiUNCiAgbXV0YXRlKA0KICAgIGZpdHRlZF9vYmVzaXR5ID0gZml0dGVkKG1vZGVsX3N0YXRlKSwNCiAgICByZXNpZHVhbCA9IHJlc2lkdWFscyhtb2RlbF9zdGF0ZSksDQogICAgYWJzb2x1dGVfcmVzaWR1YWwgPSBhYnMocmVzaWR1YWwpDQogICkNCg0KcmVzaWR1YWxfc3VtbWFyeSA8LSBtb2RlbF9kYXRhICU+JQ0KICBzdW1tYXJpc2UoDQogICAgTWVhbl9yZXNpZHVhbCA9IG1lYW4ocmVzaWR1YWwpLA0KICAgIFNEX3Jlc2lkdWFsID0gc2QocmVzaWR1YWwpLA0KICAgIE1lYW5fYWJzb2x1dGVfcmVzaWR1YWwgPSBtZWFuKGFic29sdXRlX3Jlc2lkdWFsKSwNCiAgICBNaW5pbXVtX3Jlc2lkdWFsID0gbWluKHJlc2lkdWFsKSwNCiAgICBNYXhpbXVtX3Jlc2lkdWFsID0gbWF4KHJlc2lkdWFsKQ0KICApDQoNCmtuaXRyOjprYWJsZSgNCiAgcmVzaWR1YWxfc3VtbWFyeSwNCiAgZGlnaXRzID0gMywNCiAgY2FwdGlvbiA9ICJTdW1tYXJ5IG9mIHJlc2lkdWFscyBmcm9tIHRoZSBzdGF0ZSBmaXhlZC1lZmZlY3RzIG1vZGVsIg0KKSAlPiUNCiAga2FibGVFeHRyYTo6a2FibGVfc3R5bGluZyhmdWxsX3dpZHRoID0gRkFMU0UpDQoNCmdncGxvdChtb2RlbF9kYXRhLCBhZXMoeCA9IGZpdHRlZF9vYmVzaXR5LCB5ID0gcmVzaWR1YWwpKSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjQ1KSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJSZXNpZHVhbHMgVmVyc3VzIEZpdHRlZCBWYWx1ZXMiLA0KICAgIHggPSAiUHJlZGljdGVkIGFkdWx0IG9iZXNpdHkgcHJldmFsZW5jZSAoJSkiLA0KICAgIHkgPSAiUmVzaWR1YWwgKHBlcmNlbnRhZ2UgcG9pbnRzKSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpsYXJnZXN0X3Jlc2lkdWFscyA8LSBtb2RlbF9kYXRhICU+JQ0KICBtdXRhdGUoQ291bnR5ID0gYW5hbHlzaXNfZGF0YSRDb3VudHlfa2V5W21hdGNoKA0KICAgIHBhc3RlKFN0YXRlLCBDb3VudHlfa2V5KSwgcGFzdGUoYW5hbHlzaXNfZGF0YSRTdGF0ZSwgYW5hbHlzaXNfZGF0YSRDb3VudHlfa2V5KQ0KICApXSkgJT4lDQogIGFycmFuZ2UoZGVzYyhhYnNvbHV0ZV9yZXNpZHVhbCkpICU+JQ0KICBzZWxlY3QoU3RhdGUsIENvdW50eSwgYWR1bHRfb2Jlc2l0eSwgZml0dGVkX29iZXNpdHksIHJlc2lkdWFsKSAlPiUNCiAgc2xpY2VfaGVhZChuID0gMTUpDQoNCmtuaXRyOjprYWJsZSgNCiAgbGFyZ2VzdF9yZXNpZHVhbHMsDQogIGRpZ2l0cyA9IDIsDQogIGNhcHRpb24gPSAiQ291bnRpZXMgd2l0aCB0aGUgbGFyZ2VzdCBhYnNvbHV0ZSBtb2RlbCByZXNpZHVhbHMiDQopICU+JQ0KICBrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSkNCmBgYA0KDQojIDYuIFJlc3VsdHMNCg0KIyMgNi4xIENvdW50eS1MZXZlbCBWYXJpYXRpb24gaW4gQWR1bHQgT2Jlc2l0eQ0KDQpUaGUgZGVzY3JpcHRpdmUgYW5hbHlzaXMgcmVwb3J0cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBjb3VudHktbGV2ZWwgYWR1bHQgb2Jlc2l0eSBvdXRjb21lLiBUaGUgZmluYWwgaW50ZXJwcmV0YXRpb24gc2hvdWxkIGRlc2NyaWJlIHRoZSByYW5nZSwgY2VudHJhbCB0ZW5kZW5jeSwgYW5kIHZhcmlhYmlsaXR5IHNob3duIGluIHRoZSBnZW5lcmF0ZWQgc3VtbWFyeSBhbmQgaGlzdG9ncmFtLg0KDQpUaGUgYW5hbHlzaXMgaW5jbHVkZXMgKipgciBucm93KGFuYWx5c2lzX2RhdGEpYCBjb3VudGllcyoqIHdpdGggYW4gYXZhaWxhYmxlIG91dGNvbWUgbWVhc3VyZS4gVGhlIG1lYW4gY291bnR5LWxldmVsIGFkdWx0IG9iZXNpdHkgcHJldmFsZW5jZSBpcyAqKmByIHJvdW5kKG1lYW4oYW5hbHlzaXNfZGF0YSRhZHVsdF9vYmVzaXR5LCBuYS5ybSA9IFRSVUUpLCAyKWAlKiosIGFuZCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIGlzICoqYHIgcm91bmQoc2QoYW5hbHlzaXNfZGF0YSRhZHVsdF9vYmVzaXR5LCBuYS5ybSA9IFRSVUUpLCAyKWAgcGVyY2VudGFnZSBwb2ludHMqKi4NCg0KIyMgNi4yIFJlZ3Jlc3Npb24gUmVzdWx0cw0KDQpUaGUgYmFzZWxpbmUgT0xTIG1vZGVsIGhhcyBhbiBhZGp1c3RlZCBSLXNxdWFyZWQgb2YgKipgciByb3VuZChzdW1tYXJ5KG1vZGVsX29scykkYWRqLnIuc3F1YXJlZCwgMylgKiouIFRoZSBzdGF0ZSBmaXhlZC1lZmZlY3RzIG1vZGVsIGhhcyBhbiBhZGp1c3RlZCBSLXNxdWFyZWQgb2YgKipgciByb3VuZChzdW1tYXJ5KG1vZGVsX3N0YXRlKSRhZGouci5zcXVhcmVkLCAzKWAqKi4gVGhlIGNvcnJlc3BvbmRpbmcgUk1TRSB2YWx1ZXMgYXJlICoqYHIgcm91bmQocm1zZShtb2RlbF9vbHMpLCAzKWAqKiBhbmQgKipgciByb3VuZChybXNlKG1vZGVsX3N0YXRlKSwgMylgIHBlcmNlbnRhZ2UgcG9pbnRzKiosIHJlc3BlY3RpdmVseS4NCg0KVGhlIG5lc3RlZC1tb2RlbCBGLXRlc3QgZXZhbHVhdGVzIHdoZXRoZXIgYWRkaW5nIHRoZSBzdGF0ZSBpbmRpY2F0b3JzIGltcHJvdmVzIG1vZGVsIGZpdC4gSXRzIHJlc3VsdCBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgdG9nZXRoZXIgd2l0aCB0aGUgY2hhbmdlIGluIGFkanVzdGVkIFItc3F1YXJlZCBhbmQgUk1TRSwgcmF0aGVyIHRoYW4gcmVseWluZyBvbmx5IG9uIHRoZSBwLXZhbHVlLg0KDQojIyA2LjMgR2VvZ3JhcGhpYyBEaWZmZXJlbmNlcyBBZnRlciBBZGp1c3RtZW50DQoNClRoZSBzdGF0ZSBmaXhlZC1lZmZlY3RzIG1vZGVsIGV2YWx1YXRlcyB3aGV0aGVyIHN0YXRlIGluZGljYXRvcnMgY29sbGVjdGl2ZWx5IGV4cGxhaW4gYWRkaXRpb25hbCB2YXJpYXRpb24gYWZ0ZXIgYWNjb3VudGluZyBmb3IgdGhlIG1lYXN1cmVkIGNvdW50eSBjaGFyYWN0ZXJpc3RpY3MuIEEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBuZXN0ZWQtbW9kZWwgdGVzdCB3b3VsZCBpbmRpY2F0ZSB0aGF0IHN0YXRlIGluZGljYXRvcnMgYWRkIGV4cGxhbmF0b3J5IGluZm9ybWF0aW9uIGluIHRoaXMgc2FtcGxlLiBJdCB3b3VsZCBub3QgZGVtb25zdHJhdGUgdGhhdCBldmVyeSBzdGF0ZSBkaWZmZXJzIGZyb20gZXZlcnkgb3RoZXIgc3RhdGUsIG5vciB3b3VsZCBpdCBpZGVudGlmeSB0aGUgc3BlY2lmaWMgbG9jYWwgbWVjaGFuaXNtcyByZXNwb25zaWJsZSBmb3IgdGhlIGRpZmZlcmVuY2VzLg0KDQpUaGUgcmVzaWR1YWwgYW5hbHlzaXMgaWRlbnRpZmllcyBjb3VudGllcyB3aGVyZSBvYnNlcnZlZCBwcmV2YWxlbmNlIGRpZmZlcnMgbW9zdCBmcm9tIG1vZGVsIHByZWRpY3Rpb25zLiBUaGVzZSByZXNpZHVhbCBkaWZmZXJlbmNlcyBtYXkgcmVmbGVjdCB1bm1lYXN1cmVkIGNvdW50eSBjaGFyYWN0ZXJpc3RpY3MsIG1lYXN1cmVtZW50IGVycm9yLCBkaWZmZXJlbmNlcyBpbiBzb3VyY2UgeWVhcnMsIG1vZGVsIG1pc3NwZWNpZmljYXRpb24sIG9yIHNwYXRpYWxseSBwYXR0ZXJuZWQgZmFjdG9ycy4NCg0KIyMgNi40IE1vZGVsIERpYWdub3N0aWNzDQoNClRoZSBkaWFnbm9zdGljIHBsb3RzIGFuZCBWSUYgcmVzdWx0cyBzaG91bGQgYmUgcmV2aWV3ZWQgYmVmb3JlIGZpbmFsIGludGVycHJldGF0aW9uLiBQb3RlbnRpYWwgaXNzdWVzIGluY2x1ZGUgbm9ubGluZWFyaXR5LCBoZXRlcm9zY2VkYXN0aWNpdHksIGluZmx1ZW50aWFsIG9ic2VydmF0aW9ucywgYW5kIG11bHRpY29sbGluZWFyaXR5LiBIQzMgcm9idXN0IHN0YW5kYXJkIGVycm9ycyBoZWxwIGFkZHJlc3MgaGV0ZXJvc2NlZGFzdGljaXR5IGluIGNvZWZmaWNpZW50IHVuY2VydGFpbnR5IGVzdGltYXRlcywgYnV0IHRoZXkgZG8gbm90IGNvcnJlY3Qgc3BhdGlhbCBkZXBlbmRlbmNlIGJldHdlZW4gbmVpZ2hib3JpbmcgY291bnRpZXMuDQoNCiMgNy4gRGlzY3Vzc2lvbg0KDQpUaGUgcHVycG9zZSBvZiB0aGlzIHN0dWR5IGlzIHRvIGRldGVybWluZSB3aGV0aGVyIGdlb2dyYXBoaWMgZGlmZmVyZW5jZXMgaW4gYWR1bHQgb2Jlc2l0eSBwcmV2YWxlbmNlIHJlbWFpbiBhZnRlciBjb250cm9sbGluZyBmb3IgbWVhc3VyZWQgY291bnR5LWxldmVsIGNoYXJhY3RlcmlzdGljcy4gVGhlIGNvbXBhcmlzb24gYmV0d2VlbiB0aGUgYmFzZWxpbmUgT0xTIG1vZGVsIGFuZCB0aGUgc3RhdGUgZml4ZWQtZWZmZWN0cyBtb2RlbCBwcm92aWRlcyB0aGUgcHJpbWFyeSBldmlkZW5jZSBmb3IgZXZhbHVhdGluZyB0aGUgcmVzZWFyY2ggcXVlc3Rpb24uDQoNCioqQ29tcGxldGUgdGhpcyBkaXNjdXNzaW9uIGFmdGVyIHJldmlld2luZyB0aGUga25pdHRlZCByZXN1bHRzLioqIFNwZWNpZmljYWxseSwgZXhwbGFpbjoNCg0KMS4gV2hldGhlciB0aGUgY291bnR5LWxldmVsIG9iZXNpdHkgb3V0Y29tZSBzaG93cyBzdWJzdGFudGlhbCB2YXJpYXRpb24uDQoyLiBXaGljaCBtZWFzdXJlZCBwcmVkaWN0b3JzIGhhdmUgdGhlIGxhcmdlc3QgZXN0aW1hdGVkIGFzc29jaWF0aW9ucywgaW5jbHVkaW5nIHRoZWlyIGRpcmVjdGlvbiwgdW5pdHMsIGFuZCBjb25maWRlbmNlIGludGVydmFscy4NCjMuIFdoZXRoZXIgdGhlIHN0YXRlIGZpeGVkLWVmZmVjdHMgbW9kZWwgaW1wcm92ZXMgYWRqdXN0ZWQgUi1zcXVhcmVkIGFuZCBSTVNFLg0KNC4gV2hldGhlciB0aGUgbmVzdGVkLW1vZGVsIEYtdGVzdCBzdXBwb3J0cyB0aGUgY29uY2x1c2lvbiB0aGF0IHN0YXRlIGluZGljYXRvcnMgYWRkIGV4cGxhbmF0b3J5IGluZm9ybWF0aW9uLg0KNS4gV2hhdCB0aGUgcmVzaWR1YWwgZGlhZ25vc3RpY3Mgc3VnZ2VzdCBhYm91dCB1bmV4cGxhaW5lZCBjb3VudHktbGV2ZWwgZGlmZmVyZW5jZXMuDQoNClRoZSBmaW5kaW5ncyBzaG91bGQgYmUgY29tcGFyZWQgd2l0aCB0aGUgbGl0ZXJhdHVyZSByZXZpZXdlZCBpbiBTZWN0aW9uIDIuIEF2b2lkIGRlc2NyaWJpbmcgYW4gYXNzb2NpYXRpb24gYXMgYSBjYXVzYWwgZWZmZWN0LiBBIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgY29lZmZpY2llbnQgZG9lcyBub3QgbmVjZXNzYXJpbHkgaW5kaWNhdGUgYSBsYXJnZSBvciBwcmFjdGljYWxseSBpbXBvcnRhbnQgYXNzb2NpYXRpb24uDQoNCiMgOC4gTGltaXRhdGlvbnMNCg0KU2V2ZXJhbCBsaW1pdGF0aW9ucyBzaG91bGQgYmUgY29uc2lkZXJlZCB3aGVuIGludGVycHJldGluZyB0aGUgZmluZGluZ3MuDQoNCkZpcnN0LCB0aGUgc3R1ZHkgdXNlcyBhZ2dyZWdhdGVkIGNvdW50eS1sZXZlbCBkYXRhLiBDb3VudHktbGV2ZWwgYXNzb2NpYXRpb25zIGNhbm5vdCBhdXRvbWF0aWNhbGx5IGJlIGdlbmVyYWxpemVkIHRvIGluZGl2aWR1YWxzOyBkb2luZyBzbyB3b3VsZCByaXNrIGFuIGVjb2xvZ2ljYWwgZmFsbGFjeS4NCg0KU2Vjb25kLCB0aGUgb3V0Y29tZSBpcyBjYWxjdWxhdGVkIGFzIHRoZSBhcml0aG1ldGljIG1lYW4gb2YgbWFsZSBhbmQgZmVtYWxlIElITUUgMjAwOSBvYmVzaXR5IGVzdGltYXRlcy4gSXQgaXMgbm90IGEgcG9wdWxhdGlvbi13ZWlnaHRlZCBvdmVyYWxsIHByZXZhbGVuY2UgZXN0aW1hdGUuIFRoaXMgZGVmaW5pdGlvbiBzaG91bGQgYmUga2VwdCBleHBsaWNpdCB0aHJvdWdob3V0IHRoZSBwYXBlci4NCg0KVGhpcmQsIHRoZSBzb3VyY2UgZGF0YXNldHMgbWF5IHJlcHJlc2VudCBkaWZmZXJlbnQgeWVhcnMuIERpZmZlcmVuY2VzIGluIHRoZSB0aW1pbmcgb2Ygb2Jlc2l0eSwgcGh5c2ljYWwgYWN0aXZpdHksIHNvY2lvZWNvbm9taWMsIGZvb2QtcmVsYXRlZCwgYW5kIGVudmlyb25tZW50YWwgbWVhc3VyZW1lbnRzIG1heSBhZmZlY3QgdGhlIGVzdGltYXRlZCByZWxhdGlvbnNoaXBzLg0KDQpGb3VydGgsIHRoZSBhbmFseXNpcyByZWxpZXMgb24gY291bnR5LW5hbWUgYW5kIHN0YXRlLW5hbWUgc3RhbmRhcmRpemF0aW9uIGZvciBmaWxlcyB3aXRob3V0IGEgY29uc2lzdGVudGx5IGF2YWlsYWJsZSBGSVBTIGlkZW50aWZpZXIuIEFsdGhvdWdoIHN0YXRlLXBsdXMtY291bnR5IG1hdGNoaW5nIHJlZHVjZXMgYW1iaWd1aXR5LCBhIHZlcmlmaWVkIGZpdmUtZGlnaXQgRklQUyBjcm9zc3dhbGsgd291bGQgYmUgcHJlZmVyYWJsZSBmb3IgdGhlIGZpbmFsIGRhdGEgaW50ZWdyYXRpb24uDQoNCkZpZnRoLCB0aGUgc2VsZWN0ZWQgdmFyaWFibGVzIGRvIG5vdCBjYXB0dXJlIGV2ZXJ5IGZhY3RvciBhc3NvY2lhdGVkIHdpdGggb2Jlc2l0eS4gUG90ZW50aWFsbHkgcmVsZXZhbnQgb21pdHRlZCBjaGFyYWN0ZXJpc3RpY3MgaW5jbHVkZSBoZWFsdGhjYXJlIGFjY2VzcywgdHJhbnNwb3J0YXRpb24gaW5mcmFzdHJ1Y3R1cmUsIGRlbW9ncmFwaGljIGNvbXBvc2l0aW9uLCBob3VzaW5nLCBsb2NhbCBwb2xpY3ksIGFuZCBuZWlnaGJvcmhvb2QtbGV2ZWwgcmVzb3VyY2VzLg0KDQpTaXh0aCwgc3RhdGUgZml4ZWQgZWZmZWN0cyBjYXB0dXJlIGF2ZXJhZ2UgZGlmZmVyZW5jZXMgYmV0d2VlbiBzdGF0ZXMgYnV0IGRvIG5vdCBkaXJlY3RseSB0ZXN0IHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGFtb25nIG5laWdoYm9yaW5nIGNvdW50aWVzLiBBIHNlcGFyYXRlIHNwYXRpYWwgYW5hbHlzaXMgdXNpbmcgdmFsaWRhdGVkIGNvdW50eSBnZW9tZXRyaWVzIGFuZCBhIGRlZmVuc2libGUgc3BhdGlhbC13ZWlnaHRzIG1hdHJpeCB3b3VsZCBiZSBuZWVkZWQgdG8gYXNzZXNzIG5laWdoYm9yaW5nLWNvdW50eSBkZXBlbmRlbmNlLg0KDQpGaW5hbGx5LCBPTFMgZXN0aW1hdGVzIG1heSBiZSBzZW5zaXRpdmUgdG8gaW5mbHVlbnRpYWwgb2JzZXJ2YXRpb25zLCBtdWx0aWNvbGxpbmVhcml0eSwgaGV0ZXJvc2NlZGFzdGljaXR5LCBhbmQgbWVhc3VyZW1lbnQgZXJyb3IuIFRoZSBkaWFnbm9zdGljIHJlc3VsdHMgc2hvdWxkIHRoZXJlZm9yZSBiZSBjb25zaWRlcmVkIGFsb25nc2lkZSB0aGUgY29lZmZpY2llbnQgZXN0aW1hdGVzLg0KDQojIDkuIENvbmNsdXNpb24NCg0KVGhpcyBzdHVkeSBleGFtaW5lcyBjb3VudHktbGV2ZWwgZ2VvZ3JhcGhpYyBkaWZmZXJlbmNlcyBpbiBhZHVsdCBvYmVzaXR5IHByZXZhbGVuY2UgYWZ0ZXIgYWRqdXN0bWVudCBmb3IgbWVhc3VyZWQgYmVoYXZpb3JhbCwgc29jaW9lY29ub21pYywgZm9vZC1yZWxhdGVkLCBhbmQgZW52aXJvbm1lbnRhbCBjaGFyYWN0ZXJpc3RpY3MuIEl0IHVzZXMgYSBzZXF1ZW50aWFsIG1vZGVsaW5nIHN0cmF0ZWd5IHRoYXQgY29tcGFyZXMgYSBiYXNlbGluZSBPTFMgcmVncmVzc2lvbiB3aXRoIGEgbW9kZWwgY29udGFpbmluZyBzdGF0ZSBmaXhlZCBlZmZlY3RzLg0KDQpUaGUgZmluYWwgY29uY2x1c2lvbiBzaG91bGQgYmUgY29tcGxldGVkIGFmdGVyIHRoZSBkYXRhIGFuZCBtb2RlbCBvdXRwdXRzIGhhdmUgYmVlbiByZXZpZXdlZC4gSXQgc2hvdWxkIHN0YXRlIGhvdyBtdWNoIHZhcmlhdGlvbiB0aGUgYmFzZWxpbmUgbW9kZWwgZXhwbGFpbnMsIHdoZXRoZXIgdGhlIHN0YXRlIGZpeGVkLWVmZmVjdHMgbW9kZWwgYWRkcyBleHBsYW5hdG9yeSB2YWx1ZSwgd2hpY2ggbWVhc3VyZWQgYXNzb2NpYXRpb25zIGFyZSBtb3N0IGltcG9ydGFudCwgYW5kIHdoYXQgZ2VvZ3JhcGhpYyBkaWZmZXJlbmNlcyByZW1haW4gdW5leHBsYWluZWQuDQoNClRoZSBmaW5kaW5ncyBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgYXMgY291bnR5LWxldmVsIG9ic2VydmF0aW9uYWwgYXNzb2NpYXRpb25zLiBUaGV5IG1heSBoZWxwIGlkZW50aWZ5IGdlb2dyYXBoaWMgcGF0dGVybnMgdGhhdCB3YXJyYW50IGFkZGl0aW9uYWwgcHVibGljLWhlYWx0aCBpbnZlc3RpZ2F0aW9uLCBidXQgdGhleSBkbyBub3QgZXN0YWJsaXNoIGNhdXNhbCBlZmZlY3RzIG9yIGV4cGxhaW4gYWxsIHNvdXJjZXMgb2Ygb2Jlc2l0eSBkaWZmZXJlbmNlcyBhY3Jvc3MgY29tbXVuaXRpZXMuDQoNCiMgMTAuIFJlcHJvZHVjaWJpbGl0eSBhbmQgRmluYWwgQ2hlY2tzDQoNClRoZSBhbmFseXNpcyBpcyBkZXNpZ25lZCB0byBiZSByZXByb2R1Y2libGUgZnJvbSB0aGUgcHVibGljIHByb2plY3QgcmVwb3NpdG9yeS4gQmVmb3JlIHN1Ym1pc3Npb24sIGNvbmZpcm0gdGhhdCB0aGUgcmVwb3NpdG9yeSBmaWxlcyBoYXZlIG5vdCBjaGFuZ2VkLCB0aGF0IGVhY2ggc291cmNlIGNvbHVtbiB3YXMgbWFwcGVkIGNvcnJlY3RseSwgYW5kIHRoYXQgdGhlIGZpbmFsIGNvbXBsZXRlLWNhc2Ugc2FtcGxlIGlzIGFwcHJvcHJpYXRlIGZvciB0aGUgcmVzZWFyY2ggcXVlc3Rpb24uDQoNCmBgYHtyIGZpbmFsLWNoZWNrc30NCmZpbmFsX2NoZWNrcyA8LSB0aWJibGUoDQogIENoZWNrID0gYygNCiAgICAiT3V0Y29tZSB2YXJpYWJsZSBwcmVzZW50IiwNCiAgICAiQXQgbGVhc3QgMyBwcmVkaWN0b3JzIGluY2x1ZGVkIiwNCiAgICAiUmVncmVzc2lvbiBzYW1wbGUgaGFzIGF0IGxlYXN0IDEwMCBjb3VudGllcyIsDQogICAgIk1vcmUgdGhhbiBvbmUgc3RhdGUgcmVwcmVzZW50ZWQiLA0KICAgICJCYXNlbGluZSBhbmQgc3RhdGUgbW9kZWxzIHVzZSBzYW1lIG9ic2VydmF0aW9ucyIsDQogICAgIk1vZGVsIGNvZWZmaWNpZW50cyBhcmUgZmluaXRlIg0KICApLA0KICBQYXNzZWQgPSBjKA0KICAgICJhZHVsdF9vYmVzaXR5IiAlaW4lIG5hbWVzKG1vZGVsX2RhdGEpLA0KICAgIGxlbmd0aChhdmFpbGFibGVfcHJlZGljdG9ycykgPj0gMywNCiAgICBucm93KG1vZGVsX2RhdGEpID49IDEwMCwNCiAgICBuX2Rpc3RpbmN0KG1vZGVsX2RhdGEkU3RhdGUpID4gMSwNCiAgICBub2JzKG1vZGVsX29scykgPT0gbm9icyhtb2RlbF9zdGF0ZSksDQogICAgYWxsKGlzLmZpbml0ZShjb2VmKG1vZGVsX3N0YXRlKSkpDQogICkNCikNCg0Ka25pdHI6OmthYmxlKA0KICBmaW5hbF9jaGVja3MsDQogIGNhcHRpb24gPSAiUmVwcm9kdWNpYmlsaXR5IGFuZCBtb2RlbCB2YWxpZGF0aW9uIGNoZWNrcyINCikgJT4lDQogIGthYmxlRXh0cmE6OmthYmxlX3N0eWxpbmcoZnVsbF93aWR0aCA9IEZBTFNFKQ0KYGBgDQoNCiMgUmVmZXJlbmNlcw0KDQpBaGVybiwgTS4sIEJyb3duLCBDLiwgJiBEdWthcywgUy4gKDIwMTEpLiBBIG5hdGlvbmFsIHN0dWR5IG9mIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGZvb2QgZW52aXJvbm1lbnRzIGFuZCBjb3VudHktbGV2ZWwgaGVhbHRoIG91dGNvbWVzLiAqVGhlIEpvdXJuYWwgb2YgUnVyYWwgSGVhbHRoKi4gW1ZlcmlmeSB2b2x1bWUsIGlzc3VlLCBwYWdlcywgYW5kIERPSSBiZWZvcmUgc3VibWlzc2lvbi5dDQoNCkFuLCBSLiwgTGksIFguLCAmIEppYW5nLCBOLiAoMjAxNykuIEdlb2dyYXBoaWNhbCB2YXJpYXRpb25zIGluIHRoZSBlbnZpcm9ubWVudGFsIGRldGVybWluYW50cyBvZiBwaHlzaWNhbCBpbmFjdGl2aXR5IGFtb25nIFUuUy4gYWR1bHRzLiBbVmVyaWZ5IGNvbXBsZXRlIHB1YmxpY2F0aW9uIGRldGFpbHMgYmVmb3JlIHN1Ym1pc3Npb24uXQ0KDQpDZW50ZXJzIGZvciBEaXNlYXNlIENvbnRyb2wgYW5kIFByZXZlbnRpb24uIChuLmQuKS4gKk5vcnRoIEFtZXJpY2EgTGFuZCBEYXRhIEFzc2ltaWxhdGlvbiBTeXN0ZW0gKE5MREFTKSBkYWlseSBzdW5saWdodCAoa0ovbcKyKSwgMTk3OeKAkzIwMTEqLiBodHRwczovL3dvbmRlci5jZGMuZ292L2NvbnRyb2xsZXIvZGF0YXJlcXVlc3QvRDgwDQoNCkZlZWRpbmcgQW1lcmljYS4gKG4uZC4pLiAqTWFwIHRoZSBNZWFsIEdhcDogQ291bnR5LWxldmVsIGZvb2QgaW5zZWN1cml0eSBkYXRhKi4gaHR0cHM6Ly93d3cuZmVlZGluZ2FtZXJpY2Eub3JnL3Jlc2VhcmNoL21hcC10aGUtbWVhbC1nYXAvYnktY291bnR5DQoNCkhhbW1hcnN0csO2bSwgQS4sIEphbmxlcnQsIFUuLCAmIFdpbmVmaWVsZCwgSC4gKDIwMTQpLiBMZW5ndGggb2YgdW5lbXBsb3ltZW50IGFuZCBoZWFsdGgtcmVsYXRlZCBvdXRjb21lcy4gW1ZlcmlmeSBjb21wbGV0ZSBwdWJsaWNhdGlvbiBkZXRhaWxzIGJlZm9yZSBzdWJtaXNzaW9uLl0NCg0KSG9saWNrLCBNLiBGLiwgJiBXYWNrZXIsIE0uICgyMDEzKS4gKlN1bmxpZ2h0IGFuZCB2aXRhbWluIEQqLiBbVmVyaWZ5IHB1Ymxpc2hlciBhbmQgZWRpdGlvbiBvciBhcnRpY2xlIGRldGFpbHMgYmVmb3JlIHN1Ym1pc3Npb24uXQ0KDQpJbnN0aXR1dGUgZm9yIEhlYWx0aCBNZXRyaWNzIGFuZCBFdmFsdWF0aW9uLiAobi5kLikuICpVbml0ZWQgU3RhdGVzIGFsY29ob2wgdXNlIHByZXZhbGVuY2UgYnkgY291bnR5LCAyMDAy4oCTMjAxMiouIEdsb2JhbCBIZWFsdGggRGF0YSBFeGNoYW5nZS4gaHR0cDovL2doZHguaGVhbHRoZGF0YS5vcmcvcmVjb3JkL2lobWUtZGF0YS91bml0ZWQtc3RhdGVzLWFsY29ob2wtdXNlLXByZXZhbGVuY2UtY291bnR5LTIwMDItMjAxMg0KDQpJbnN0aXR1dGUgZm9yIEhlYWx0aCBNZXRyaWNzIGFuZCBFdmFsdWF0aW9uLiAobi5kLikuICpVbml0ZWQgU3RhdGVzIHBoeXNpY2FsIGFjdGl2aXR5IGFuZCBvYmVzaXR5IHByZXZhbGVuY2UgYnkgY291bnR5Ki4gR2xvYmFsIEhlYWx0aCBEYXRhIEV4Y2hhbmdlLiBodHRwczovL2doZHguaGVhbHRoZGF0YS5vcmcvDQoNClUuUy4gQ2Vuc3VzIEJ1cmVhdS4gKDIwMTkpLiAqU21hbGwgQXJlYSBJbmNvbWUgYW5kIFBvdmVydHkgRXN0aW1hdGVzIChTQUlQRSk6IFN0YXRlIGFuZCBjb3VudHkgZXN0aW1hdGVzKi4gaHR0cHM6Ly93d3cuY2Vuc3VzLmdvdi9kYXRhL2RhdGFzZXRzLzIwMTkvZGVtby9zYWlwZS8yMDE5LXN0YXRlLWFuZC1jb3VudHkuaHRtbA0KDQpVLlMuIERlcGFydG1lbnQgb2YgQWdyaWN1bHR1cmUsIEVjb25vbWljIFJlc2VhcmNoIFNlcnZpY2UuIChuLmQuKS4gKkNvdW50eS1sZXZlbCBkYXRhIHNldHMqLiBodHRwczovL3d3dy5lcnMudXNkYS5nb3YvZGF0YS1wcm9kdWN0cy9jb3VudHktbGV2ZWwtZGF0YS1zZXRzL2Rvd25sb2FkLWRhdGEvDQoNClUuUy4gRW52aXJvbm1lbnRhbCBQcm90ZWN0aW9uIEFnZW5jeS4gKG4uZC4pLiAqRW52aXJvbm1lbnRhbCBRdWFsaXR5IEluZGV4IChFUUkpLCAyMDA24oCTMjAxMCouIGh0dHBzOi8vZWRnLmVwYS5nb3YvRVBBRGF0YUNvbW1vbnMvcHVibGljL09SRC9DUEhFQS9FUUlfMjAwNl8yMDEwLw0KDQotLS0NCg0KKipTdWJtaXNzaW9uIG5vdGU6KiogQ29tcGxldGUgdGhlIGRpc2N1c3Npb24gYW5kIGNvbmNsdXNpb24gdXNpbmcgdGhlIGFjdHVhbCBvdXRwdXQgZnJvbSB0aGUgZmluYWwga25pdC4gVmVyaWZ5IGV2ZXJ5IGxpdGVyYXR1cmUgcmVmZXJlbmNlJ3MgZnVsbCBiaWJsaW9ncmFwaGljIGRldGFpbHMgYW5kIGFkZCBpbi10ZXh0IGNpdGF0aW9ucyB3aGVyZSB0aGUgY2l0ZWQgc3R1ZGllcyBhcmUgZGlzY3Vzc2VkLiBUaGUgZmluYWwgcGFwZXIgc2hvdWxkIG5vdCBiZSBzdWJtaXR0ZWQgd2l0aCB1bnJlc29sdmVkIHNvdXJjZSBtYXBwaW5ncywgaW5jb21wbGV0ZSByZWZlcmVuY2VzLCBvciB1bnJldmlld2VkIG1vZGVsIGRpYWdub3N0aWNzLg0K