library(tidyverse)
library(haven)
library(survey)
library(knitr)
library(kableExtra)
library(usmap)
library(ggplot2)
library(scales)

source("R/utils.R")

if (!dir.exists("outputs")) dir.create("outputs")

Dataset and documentation available at https://www.cdc.gov/brfss/annual_data/annual_2024.html

# Import the 2024 BRFSS dataset (SAS Transport Format)
brfss_data <- read_xpt("data/LLCP2024.XPT")

# Generate summary table of all variables. Labels are truncated-- the full titles are available in the 2024 BRFSS Codebook CDC.
var_dict <- build_variable_dictionary(brfss_data)
head(var_dict)
# List of columns to keep
keep_vars <- c("_STATE", "_LLCPWT", "_PSU", "_STSTR", 
               "_AGEG5YR", "_SEX", "_RACEGR3", "_URBSTAT",
               "_FLSHOT7", "_PNEUMO3", "_AIDTST4", "_CRVSCRN",
               "_BMI5CAT", "_RFSMOK3")

# Create smaller dataframe for more efficient analysis
brfss_small <- brfss_data[, keep_vars]
var_dict_small <- build_variable_dictionary(brfss_small)
# Optional after creating the smaller working dataset
rm(brfss_data)      # Remove the large original
gc()                # Run garbage collection to free memory
           used  (Mb) gc trigger   (Mb)  max used   (Mb)
Ncells  2864174 153.0    5457597  291.5   5457597  291.5
Vcells 12361681  94.4  306640558 2339.5 383159014 2923.3

Analysis of flu shot coverage for those > 65 years of age

Variable _FLSHOT7 already only includes those 65+. A response of ‘9’ indicates ‘Don’t know/Not Sure’ Or ‘Refused/Missing’. Dropped for analysis.

# Clean the flu shot variable and remove missing codes
brfss_small$flu_shot_clean <- ifelse(brfss_small$`_FLSHOT7` %in% c(9, NA), NA, brfss_small$`_FLSHOT7`)

# Calculate percentage of '9's in each state to make sure state-by-state comparison is valid after dropping
pct_9_by_state <- brfss_small %>%
  group_by(`_STATE`) %>%
  summarize(
    n_total = n(),
    n_9 = sum(`_FLSHOT7` == 9, na.rm = TRUE),
    pct_9 = n_9 / n_total * 100
  ) %>%
  arrange(desc(pct_9))  # sort from highest to lowest

pct_9_by_state

% of respondents answering “9” for _FLSHOT7 varies between 8.05 and 1.25% state-by-state. As it’s relatively low, it seems unlikely that it would meaningfully bias interstate comparisons.

# Adjust for "lonely" PSUs (strata with only one PSU) in variance estimation
options(survey.lonely.psu = "adjust")

# Define the survey design for flu vaccination data
flu_design <- svydesign(
  id = ~`_PSU`,           # Primary Sampling Unit
  strata = ~`_STSTR`,     # Stratification variable
  weights = ~`_LLCPWT`,   # Survey weights
  data = brfss_small,
  nest = TRUE            # Indicates nested structure
)

# Estimate the mean flu vaccination rate
flu_est <- svymean(~factor(flu_shot_clean), design = flu_design, na.rm = TRUE)

flu_est
                          mean    SE
factor(flu_shot_clean)1 0.6253 0.003
factor(flu_shot_clean)2 0.3747 0.003
# Format results for readability
flu_yes <- coef(flu_est)[1]
flu_ci  <- confint(flu_est)[1, ]

cat(sprintf(
  "Flu vaccination rate (age 65+): %.1f%% (95%% CI: %.1f%%–%.1f%%)\n",
  flu_yes * 100,
  flu_ci[1] * 100,
  flu_ci[2] * 100
))
Flu vaccination rate (age 65+): 62.5% (95% CI: 61.9%–63.1%)
flu_by_state <- svyby(
  ~factor(flu_shot_clean),
  ~`_STATE`,
  design = flu_design,
  FUN = svymean,
  na.rm = TRUE
)
# Map state codes to names
state_labels <- c(
  `1` = "Alabama", `2` = "Alaska", `4` = "Arizona", `5` = "Arkansas",
  `6` = "California", `8` = "Colorado", `9` = "Connecticut", `10` = "Delaware",
  `11` = "District of Columbia", `12` = "Florida", `13` = "Georgia", `15` = "Hawaii",
  `16` = "Idaho", `17` = "Illinois", `18` = "Indiana", `19` = "Iowa",
  `20` = "Kansas", `21` = "Kentucky", `22` = "Louisiana", `23` = "Maine",
  `24` = "Maryland", `25` = "Massachusetts", `26` = "Michigan", `27` = "Minnesota",
  `28` = "Mississippi", `29` = "Missouri", `30` = "Montana", `31` = "Nebraska",
  `32` = "Nevada", `33` = "New Hampshire", `34` = "New Jersey", `35` = "New Mexico",
  `36` = "New York", `37` = "North Carolina", `38` = "North Dakota", `39` = "Ohio",
  `40` = "Oklahoma", `41` = "Oregon", `42` = "Pennsylvania", `44` = "Rhode Island",
  `45` = "South Carolina", `46` = "South Dakota", `48` = "Texas", `49` = "Utah",
  `50` = "Vermont", `51` = "Virginia", `53` = "Washington", `54` = "West Virginia",
  `55` = "Wisconsin", `56` = "Wyoming", `66` = "Guam", `72` = "Puerto Rico",
  `78` = "Virgin Islands"
)

# Convert state variable in flu_by_state to the labels
flu_by_state$State <- state_labels[as.character(flu_by_state$`_STATE`)]

flu_by_state
# 95% CI using normal approximation
flu_by_state <- flu_by_state %>%
  mutate(
    flu_rate = `factor(flu_shot_clean)1`,              # your column with vaccination rate (1 = yes)
    flu_se = `se.factor(flu_shot_clean)1`,                    # your column with SE
    lower_ci = flu_rate - 1.96 * flu_se,
    upper_ci = flu_rate + 1.96 * flu_se
  )

# Create table of state flu vaccination data
flu_by_state %>%
  select(State, flu_rate, lower_ci, upper_ci) %>%
  arrange(desc(flu_rate)) %>%
  kable(digits = 3, 
        col.names = c("State", "Vaccination Rate", "Lower CI", "Upper CI"),
        caption = "Flu Vaccination Rates (Age 65+) by State with 95% CIs") %>%
  kable_styling(full_width = FALSE)
Flu Vaccination Rates (Age 65+) by State with 95% CIs
State Vaccination Rate Lower CI Upper CI
50 Vermont 0.731 0.708 0.754
25 Massachusetts 0.725 0.703 0.746
33 New Hampshire 0.715 0.696 0.734
24 Maryland 0.708 0.689 0.727
44 Rhode Island 0.706 0.677 0.735
11 District of Columbia 0.705 0.668 0.742
23 Maine 0.699 0.681 0.716
9 Connecticut 0.695 0.664 0.726
10 Delaware 0.690 0.660 0.721
51 Virginia 0.684 0.657 0.711
27 Minnesota 0.677 0.660 0.693
53 Washington 0.672 0.659 0.685
8 Colorado 0.671 0.653 0.690
37 North Carolina 0.669 0.635 0.703
41 Oregon 0.665 0.638 0.692
6 California 0.655 0.627 0.683
21 Kentucky 0.649 0.623 0.676
31 Nebraska 0.649 0.630 0.668
19 Iowa 0.649 0.627 0.670
35 New Mexico 0.645 0.609 0.681
29 Missouri 0.642 0.615 0.670
36 New York 0.636 0.620 0.653
46 South Dakota 0.636 0.577 0.695
55 Wisconsin 0.636 0.619 0.653
34 New Jersey 0.634 0.604 0.663
20 Kansas 0.633 0.613 0.653
42 Pennsylvania 0.631 0.588 0.675
26 Michigan 0.629 0.609 0.649
15 Hawaii 0.627 0.600 0.655
18 Indiana 0.625 0.606 0.643
39 Ohio 0.623 0.599 0.646
5 Arkansas 0.620 0.594 0.646
17 Illinois 0.619 0.597 0.641
38 North Dakota 0.612 0.588 0.636
54 West Virginia 0.611 0.588 0.634
40 Oklahoma 0.603 0.580 0.626
49 Utah 0.600 0.579 0.621
28 Mississippi 0.598 0.552 0.644
45 South Carolina 0.597 0.573 0.621
4 Arizona 0.596 0.563 0.628
1 Alabama 0.595 0.567 0.624
13 Georgia 0.589 0.557 0.620
30 Montana 0.583 0.561 0.605
48 Texas 0.578 0.541 0.615
16 Idaho 0.557 0.524 0.591
12 Florida 0.557 0.529 0.585
56 Wyoming 0.545 0.520 0.570
66 Guam 0.543 0.300 0.787
22 Louisiana 0.537 0.507 0.567
32 Nevada 0.525 0.469 0.580
2 Alaska 0.520 0.485 0.555
72 Puerto Rico 0.446 0.389 0.503
78 Virgin Islands 0.308 0.187 0.429
flu_by_state <- flu_by_state %>%
  mutate(state = state.abb[match(State, state.name)])

flu_by_state <- flu_by_state %>%
  mutate(flu_rate = `factor(flu_shot_clean)1`)

plot_usmap(
  data = flu_by_state,
  values = "flu_rate",
  regions = "states"
) +
  scale_fill_viridis_c(
    labels = percent_format(accuracy = 1),
    name = "Flu Vaccination Rate"
  ) +
  theme(legend.position = "right") +
  labs(title = "Flu Vaccination Rate (Age 65+) by State")

ggsave("outputs/flu_map.png", width = 10, height = 6, dpi = 300)

Note: Tennessee is absent from the 2024 BRFSS public dataset. CDC BRFSS 2024 documentation.

Comparison of flu vaccination rates (65+) for urban (1) vs rural (2) populations

# Estimate mean flu vaccination by urban/rural
flu_urban_est <- svyby(
  ~factor(flu_shot_clean),
  ~`_URBSTAT`,
  design = flu_design,
  FUN = svymean,
  na.rm = TRUE
)

# Format results
flu_urban_est <- flu_urban_est %>%
  mutate(
    flu_rate = `factor(flu_shot_clean)1`,      # vaccination = 1 (yes)
    flu_se = `se.factor(flu_shot_clean)1`,
    lower_ci = flu_rate - 1.96 * flu_se,
    upper_ci = flu_rate + 1.96 * flu_se,
    urban_rural = ifelse(`_URBSTAT` == 1, "Urban", "Rural")
  )

# Display
flu_urban_est[, c("urban_rural", "flu_rate", "lower_ci", "upper_ci")]

Comparison of flu vaccination rates (65+) by ethnicity

# Weighted mean by race (65+), ignoring 9 (Don't know/Refused)
flu_race_est <- svyby(
  ~factor(flu_shot_clean),
  ~factor(ifelse(`_RACEGR3` %in% c(1,2,3,4,5), `_RACEGR3`, NA)),
  design = flu_design,
  FUN = svymean,
  na.rm = TRUE
)

# Official 5-level race/ethnicity labels
race_labels <- c(
  "White only, Non-Hispanic",
  "Black only, Non-Hispanic",
  "Other race only, Non-Hispanic",
  "Multiracial, Non-Hispanic",
  "Hispanic"
)

# Explicit column names for "Yes" and its SE
rate_col <- "factor(flu_shot_clean)1"
se_col   <- "se.factor(flu_shot_clean)1"

# Print percentages with 95% CIs
for (i in seq_along(race_labels)) {
  rate <- flu_race_est[[rate_col]][i]
  se   <- flu_race_est[[se_col]][i]
  lower <- rate - 1.96 * se
  upper <- rate + 1.96 * se
  
  cat(sprintf(
    "Flu vaccination rate (%s, 65+): %.1f%% (95%% CI: %.1f%%–%.1f%%)\n",
    race_labels[i],
    rate * 100,
    lower * 100,
    upper * 100
  ))
}
Flu vaccination rate (White only, Non-Hispanic, 65+): 65.0% (95% CI: 64.4%–65.6%)
Flu vaccination rate (Black only, Non-Hispanic, 65+): 57.0% (95% CI: 54.7%–59.2%)
Flu vaccination rate (Other race only, Non-Hispanic, 65+): 59.3% (95% CI: 55.4%–63.1%)
Flu vaccination rate (Multiracial, Non-Hispanic, 65+): 56.0% (95% CI: 51.1%–61.0%)
Flu vaccination rate (Hispanic, 65+): 54.8% (95% CI: 51.9%–57.7%)
# Inspect column names once
names(flu_race_est)
[1] "factor(ifelse(`_RACEGR3` %in% c(1, 2, 3, 4, 5), `_RACEGR3`, NA))" "factor(flu_shot_clean)1"                                          "factor(flu_shot_clean)2"                                         
[4] "se.factor(flu_shot_clean)1"                                       "se.factor(flu_shot_clean)2"                                      

Comparison of flu vaccination rates (65+) by sex

# Adjust for "lonely" PSUs (strata with only one PSU) in variance estimation
options(survey.lonely.psu = "adjust")

# Estimate mean flu vaccination by male (1) or female (2)
flu_sex_est <- svyby(
  ~factor(flu_shot_clean),
  ~`_SEX`,
  design = flu_design,
  FUN = svymean,
  na.rm = TRUE
)

# Format results
flu_sex_est <- flu_sex_est %>%
  mutate(
    flu_rate = `factor(flu_shot_clean)1`,      # vaccination = 1 (yes)
    flu_se = `se.factor(flu_shot_clean)1`,
    lower_ci = flu_rate - 1.96 * flu_se,
    upper_ci = flu_rate + 1.96 * flu_se,
    male_female = case_when(
      `_SEX` == 1 ~ "Male",
      `_SEX` == 2 ~ "Female",
      TRUE ~ NA_character_
    )
  )

# Display
flu_sex_est[, c("male_female", "flu_rate", "lower_ci", "upper_ci")]
LS0tDQp0aXRsZTogIkJSRlNTIEhlYWx0aGNhcmUgQWNjZXNzIEFuYWx5c2lzIg0KYXV0aG9yOiAiQnJhbmRvbiBSdWdnIg0KZGF0ZTogIjIwMjYtMDQtMDIiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KYGBge3Igc2V0dXAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoaGF2ZW4pDQpsaWJyYXJ5KHN1cnZleSkNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpsaWJyYXJ5KHVzbWFwKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShzY2FsZXMpDQoNCnNvdXJjZSgiUi91dGlscy5SIikNCg0KaWYgKCFkaXIuZXhpc3RzKCJvdXRwdXRzIikpIGRpci5jcmVhdGUoIm91dHB1dHMiKQ0KYGBgDQoNCkRhdGFzZXQgYW5kIGRvY3VtZW50YXRpb24gYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3LmNkYy5nb3YvYnJmc3MvYW5udWFsX2RhdGEvYW5udWFsXzIwMjQuaHRtbA0KDQpgYGB7ciByZWFkX2RhdGF9DQojIEltcG9ydCB0aGUgMjAyNCBCUkZTUyBkYXRhc2V0IChTQVMgVHJhbnNwb3J0IEZvcm1hdCkNCmJyZnNzX2RhdGEgPC0gcmVhZF94cHQoImRhdGEvTExDUDIwMjQuWFBUIikNCg0KIyBHZW5lcmF0ZSBzdW1tYXJ5IHRhYmxlIG9mIGFsbCB2YXJpYWJsZXMuIExhYmVscyBhcmUgdHJ1bmNhdGVkLS0gdGhlIGZ1bGwgdGl0bGVzIGFyZSBhdmFpbGFibGUgaW4gdGhlIDIwMjQgQlJGU1MgQ29kZWJvb2sgQ0RDLg0KdmFyX2RpY3QgPC0gYnVpbGRfdmFyaWFibGVfZGljdGlvbmFyeShicmZzc19kYXRhKQ0KaGVhZCh2YXJfZGljdCkNCmBgYA0KDQpgYGB7cn0NCiMgTGlzdCBvZiBjb2x1bW5zIHRvIGtlZXANCmtlZXBfdmFycyA8LSBjKCJfU1RBVEUiLCAiX0xMQ1BXVCIsICJfUFNVIiwgIl9TVFNUUiIsIA0KICAgICAgICAgICAgICAgIl9BR0VHNVlSIiwgIl9TRVgiLCAiX1JBQ0VHUjMiLCAiX1VSQlNUQVQiLA0KICAgICAgICAgICAgICAgIl9GTFNIT1Q3IiwgIl9QTkVVTU8zIiwgIl9BSURUU1Q0IiwgIl9DUlZTQ1JOIiwNCiAgICAgICAgICAgICAgICJfQk1JNUNBVCIsICJfUkZTTU9LMyIpDQoNCiMgQ3JlYXRlIHNtYWxsZXIgZGF0YWZyYW1lIGZvciBtb3JlIGVmZmljaWVudCBhbmFseXNpcw0KYnJmc3Nfc21hbGwgPC0gYnJmc3NfZGF0YVssIGtlZXBfdmFyc10NCnZhcl9kaWN0X3NtYWxsIDwtIGJ1aWxkX3ZhcmlhYmxlX2RpY3Rpb25hcnkoYnJmc3Nfc21hbGwpDQpgYGANCmBgYHtyfQ0KIyBPcHRpb25hbCBhZnRlciBjcmVhdGluZyB0aGUgc21hbGxlciB3b3JraW5nIGRhdGFzZXQNCnJtKGJyZnNzX2RhdGEpICAgICAgIyBSZW1vdmUgdGhlIGxhcmdlIG9yaWdpbmFsDQpnYygpICAgICAgICAgICAgICAgICMgUnVuIGdhcmJhZ2UgY29sbGVjdGlvbiB0byBmcmVlIG1lbW9yeQ0KYGBgDQoNCi0tLQ0KIyMgQW5hbHlzaXMgb2YgZmx1IHNob3QgY292ZXJhZ2UgZm9yIHRob3NlID4gNjUgeWVhcnMgb2YgYWdlDQoNClZhcmlhYmxlIGBfRkxTSE9UN2AgYWxyZWFkeSBvbmx5IGluY2x1ZGVzIHRob3NlIDY1Ky4gQSByZXNwb25zZSBvZiAnOScgaW5kaWNhdGVzICdEb24ndCBrbm93L05vdCBTdXJlJyBPciAnUmVmdXNlZC9NaXNzaW5nJy4gRHJvcHBlZCBmb3IgYW5hbHlzaXMuDQpgYGB7cn0NCiMgQ2xlYW4gdGhlIGZsdSBzaG90IHZhcmlhYmxlIGFuZCByZW1vdmUgbWlzc2luZyBjb2Rlcw0KYnJmc3Nfc21hbGwkZmx1X3Nob3RfY2xlYW4gPC0gaWZlbHNlKGJyZnNzX3NtYWxsJGBfRkxTSE9UN2AgJWluJSBjKDksIE5BKSwgTkEsIGJyZnNzX3NtYWxsJGBfRkxTSE9UN2ApDQoNCiMgQ2FsY3VsYXRlIHBlcmNlbnRhZ2Ugb2YgJzkncyBpbiBlYWNoIHN0YXRlIHRvIG1ha2Ugc3VyZSBzdGF0ZS1ieS1zdGF0ZSBjb21wYXJpc29uIGlzIHZhbGlkIGFmdGVyIGRyb3BwaW5nDQpwY3RfOV9ieV9zdGF0ZSA8LSBicmZzc19zbWFsbCAlPiUNCiAgZ3JvdXBfYnkoYF9TVEFURWApICU+JQ0KICBzdW1tYXJpemUoDQogICAgbl90b3RhbCA9IG4oKSwNCiAgICBuXzkgPSBzdW0oYF9GTFNIT1Q3YCA9PSA5LCBuYS5ybSA9IFRSVUUpLA0KICAgIHBjdF85ID0gbl85IC8gbl90b3RhbCAqIDEwMA0KICApICU+JQ0KICBhcnJhbmdlKGRlc2MocGN0XzkpKSAgIyBzb3J0IGZyb20gaGlnaGVzdCB0byBsb3dlc3QNCg0KcGN0XzlfYnlfc3RhdGUNCmBgYA0KDQolIG9mIHJlc3BvbmRlbnRzIGFuc3dlcmluZyAiOSIgZm9yIGBfRkxTSE9UN2AgdmFyaWVzIGJldHdlZW4gOC4wNSBhbmQgMS4yNSUgc3RhdGUtYnktc3RhdGUuIEFzIGl0J3MgcmVsYXRpdmVseSBsb3csIGl0IHNlZW1zIHVubGlrZWx5IHRoYXQgaXQgd291bGQgbWVhbmluZ2Z1bGx5IGJpYXMgaW50ZXJzdGF0ZSBjb21wYXJpc29ucy4NCg0KYGBge3J9DQojIEFkanVzdCBmb3IgImxvbmVseSIgUFNVcyAoc3RyYXRhIHdpdGggb25seSBvbmUgUFNVKSBpbiB2YXJpYW5jZSBlc3RpbWF0aW9uDQpvcHRpb25zKHN1cnZleS5sb25lbHkucHN1ID0gImFkanVzdCIpDQoNCiMgRGVmaW5lIHRoZSBzdXJ2ZXkgZGVzaWduIGZvciBmbHUgdmFjY2luYXRpb24gZGF0YQ0KZmx1X2Rlc2lnbiA8LSBzdnlkZXNpZ24oDQogIGlkID0gfmBfUFNVYCwgICAgICAgICAgICMgUHJpbWFyeSBTYW1wbGluZyBVbml0DQogIHN0cmF0YSA9IH5gX1NUU1RSYCwgICAgICMgU3RyYXRpZmljYXRpb24gdmFyaWFibGUNCiAgd2VpZ2h0cyA9IH5gX0xMQ1BXVGAsICAgIyBTdXJ2ZXkgd2VpZ2h0cw0KICBkYXRhID0gYnJmc3Nfc21hbGwsDQogIG5lc3QgPSBUUlVFICAgICAgICAgICAgIyBJbmRpY2F0ZXMgbmVzdGVkIHN0cnVjdHVyZQ0KKQ0KDQojIEVzdGltYXRlIHRoZSBtZWFuIGZsdSB2YWNjaW5hdGlvbiByYXRlDQpmbHVfZXN0IDwtIHN2eW1lYW4ofmZhY3RvcihmbHVfc2hvdF9jbGVhbiksIGRlc2lnbiA9IGZsdV9kZXNpZ24sIG5hLnJtID0gVFJVRSkNCg0KZmx1X2VzdA0KYGBgDQpgYGB7cn0NCiMgRm9ybWF0IHJlc3VsdHMgZm9yIHJlYWRhYmlsaXR5DQpmbHVfeWVzIDwtIGNvZWYoZmx1X2VzdClbMV0NCmZsdV9jaSAgPC0gY29uZmludChmbHVfZXN0KVsxLCBdDQoNCmNhdChzcHJpbnRmKA0KICAiRmx1IHZhY2NpbmF0aW9uIHJhdGUgKGFnZSA2NSspOiAlLjFmJSUgKDk1JSUgQ0k6ICUuMWYlJeKAkyUuMWYlJSlcbiIsDQogIGZsdV95ZXMgKiAxMDAsDQogIGZsdV9jaVsxXSAqIDEwMCwNCiAgZmx1X2NpWzJdICogMTAwDQopKQ0KYGBgDQpgYGB7cn0NCmZsdV9ieV9zdGF0ZSA8LSBzdnlieSgNCiAgfmZhY3RvcihmbHVfc2hvdF9jbGVhbiksDQogIH5gX1NUQVRFYCwNCiAgZGVzaWduID0gZmx1X2Rlc2lnbiwNCiAgRlVOID0gc3Z5bWVhbiwNCiAgbmEucm0gPSBUUlVFDQopDQpgYGANCg0KDQpgYGB7cn0NCiMgTWFwIHN0YXRlIGNvZGVzIHRvIG5hbWVzDQpzdGF0ZV9sYWJlbHMgPC0gYygNCiAgYDFgID0gIkFsYWJhbWEiLCBgMmAgPSAiQWxhc2thIiwgYDRgID0gIkFyaXpvbmEiLCBgNWAgPSAiQXJrYW5zYXMiLA0KICBgNmAgPSAiQ2FsaWZvcm5pYSIsIGA4YCA9ICJDb2xvcmFkbyIsIGA5YCA9ICJDb25uZWN0aWN1dCIsIGAxMGAgPSAiRGVsYXdhcmUiLA0KICBgMTFgID0gIkRpc3RyaWN0IG9mIENvbHVtYmlhIiwgYDEyYCA9ICJGbG9yaWRhIiwgYDEzYCA9ICJHZW9yZ2lhIiwgYDE1YCA9ICJIYXdhaWkiLA0KICBgMTZgID0gIklkYWhvIiwgYDE3YCA9ICJJbGxpbm9pcyIsIGAxOGAgPSAiSW5kaWFuYSIsIGAxOWAgPSAiSW93YSIsDQogIGAyMGAgPSAiS2Fuc2FzIiwgYDIxYCA9ICJLZW50dWNreSIsIGAyMmAgPSAiTG91aXNpYW5hIiwgYDIzYCA9ICJNYWluZSIsDQogIGAyNGAgPSAiTWFyeWxhbmQiLCBgMjVgID0gIk1hc3NhY2h1c2V0dHMiLCBgMjZgID0gIk1pY2hpZ2FuIiwgYDI3YCA9ICJNaW5uZXNvdGEiLA0KICBgMjhgID0gIk1pc3Npc3NpcHBpIiwgYDI5YCA9ICJNaXNzb3VyaSIsIGAzMGAgPSAiTW9udGFuYSIsIGAzMWAgPSAiTmVicmFza2EiLA0KICBgMzJgID0gIk5ldmFkYSIsIGAzM2AgPSAiTmV3IEhhbXBzaGlyZSIsIGAzNGAgPSAiTmV3IEplcnNleSIsIGAzNWAgPSAiTmV3IE1leGljbyIsDQogIGAzNmAgPSAiTmV3IFlvcmsiLCBgMzdgID0gIk5vcnRoIENhcm9saW5hIiwgYDM4YCA9ICJOb3J0aCBEYWtvdGEiLCBgMzlgID0gIk9oaW8iLA0KICBgNDBgID0gIk9rbGFob21hIiwgYDQxYCA9ICJPcmVnb24iLCBgNDJgID0gIlBlbm5zeWx2YW5pYSIsIGA0NGAgPSAiUmhvZGUgSXNsYW5kIiwNCiAgYDQ1YCA9ICJTb3V0aCBDYXJvbGluYSIsIGA0NmAgPSAiU291dGggRGFrb3RhIiwgYDQ4YCA9ICJUZXhhcyIsIGA0OWAgPSAiVXRhaCIsDQogIGA1MGAgPSAiVmVybW9udCIsIGA1MWAgPSAiVmlyZ2luaWEiLCBgNTNgID0gIldhc2hpbmd0b24iLCBgNTRgID0gIldlc3QgVmlyZ2luaWEiLA0KICBgNTVgID0gIldpc2NvbnNpbiIsIGA1NmAgPSAiV3lvbWluZyIsIGA2NmAgPSAiR3VhbSIsIGA3MmAgPSAiUHVlcnRvIFJpY28iLA0KICBgNzhgID0gIlZpcmdpbiBJc2xhbmRzIg0KKQ0KDQojIENvbnZlcnQgc3RhdGUgdmFyaWFibGUgaW4gZmx1X2J5X3N0YXRlIHRvIHRoZSBsYWJlbHMNCmZsdV9ieV9zdGF0ZSRTdGF0ZSA8LSBzdGF0ZV9sYWJlbHNbYXMuY2hhcmFjdGVyKGZsdV9ieV9zdGF0ZSRgX1NUQVRFYCldDQoNCmZsdV9ieV9zdGF0ZQ0KYGBgDQoNCmBgYHtyfQ0KIyA5NSUgQ0kgdXNpbmcgbm9ybWFsIGFwcHJveGltYXRpb24NCmZsdV9ieV9zdGF0ZSA8LSBmbHVfYnlfc3RhdGUgJT4lDQogIG11dGF0ZSgNCiAgICBmbHVfcmF0ZSA9IGBmYWN0b3IoZmx1X3Nob3RfY2xlYW4pMWAsICAgICAgICAgICAgICAjIHlvdXIgY29sdW1uIHdpdGggdmFjY2luYXRpb24gcmF0ZSAoMSA9IHllcykNCiAgICBmbHVfc2UgPSBgc2UuZmFjdG9yKGZsdV9zaG90X2NsZWFuKTFgLCAgICAgICAgICAgICAgICAgICAgIyB5b3VyIGNvbHVtbiB3aXRoIFNFDQogICAgbG93ZXJfY2kgPSBmbHVfcmF0ZSAtIDEuOTYgKiBmbHVfc2UsDQogICAgdXBwZXJfY2kgPSBmbHVfcmF0ZSArIDEuOTYgKiBmbHVfc2UNCiAgKQ0KDQojIENyZWF0ZSB0YWJsZSBvZiBzdGF0ZSBmbHUgdmFjY2luYXRpb24gZGF0YQ0KZmx1X2J5X3N0YXRlICU+JQ0KICBzZWxlY3QoU3RhdGUsIGZsdV9yYXRlLCBsb3dlcl9jaSwgdXBwZXJfY2kpICU+JQ0KICBhcnJhbmdlKGRlc2MoZmx1X3JhdGUpKSAlPiUNCiAga2FibGUoZGlnaXRzID0gMywgDQogICAgICAgIGNvbC5uYW1lcyA9IGMoIlN0YXRlIiwgIlZhY2NpbmF0aW9uIFJhdGUiLCAiTG93ZXIgQ0kiLCAiVXBwZXIgQ0kiKSwNCiAgICAgICAgY2FwdGlvbiA9ICJGbHUgVmFjY2luYXRpb24gUmF0ZXMgKEFnZSA2NSspIGJ5IFN0YXRlIHdpdGggOTUlIENJcyIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGZ1bGxfd2lkdGggPSBGQUxTRSkNCmBgYA0KDQpgYGB7cn0NCmZsdV9ieV9zdGF0ZSA8LSBmbHVfYnlfc3RhdGUgJT4lDQogIG11dGF0ZShzdGF0ZSA9IHN0YXRlLmFiYlttYXRjaChTdGF0ZSwgc3RhdGUubmFtZSldKQ0KDQpmbHVfYnlfc3RhdGUgPC0gZmx1X2J5X3N0YXRlICU+JQ0KICBtdXRhdGUoZmx1X3JhdGUgPSBgZmFjdG9yKGZsdV9zaG90X2NsZWFuKTFgKQ0KDQpwbG90X3VzbWFwKA0KICBkYXRhID0gZmx1X2J5X3N0YXRlLA0KICB2YWx1ZXMgPSAiZmx1X3JhdGUiLA0KICByZWdpb25zID0gInN0YXRlcyINCikgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfYygNCiAgICBsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpLA0KICAgIG5hbWUgPSAiRmx1IFZhY2NpbmF0aW9uIFJhdGUiDQogICkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSArDQogIGxhYnModGl0bGUgPSAiRmx1IFZhY2NpbmF0aW9uIFJhdGUgKEFnZSA2NSspIGJ5IFN0YXRlIikNCg0KZ2dzYXZlKCJvdXRwdXRzL2ZsdV9tYXAucG5nIiwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gNiwgZHBpID0gMzAwKQ0KYGBgDQoqTm90ZTogVGVubmVzc2VlIGlzIGFic2VudCBmcm9tIHRoZSAyMDI0IEJSRlNTIHB1YmxpYyBkYXRhc2V0LiBbQ0RDIEJSRlNTIDIwMjQgZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cuY2RjLmdvdi9icmZzcy9hbm51YWxfZGF0YS9hbm51YWxfMjAyNC5odG1sKS4qDQoNCiMjIyBDb21wYXJpc29uIG9mIGZsdSB2YWNjaW5hdGlvbiByYXRlcyAoNjUrKSBmb3IgdXJiYW4gKDEpIHZzIHJ1cmFsICgyKSBwb3B1bGF0aW9ucw0KYGBge3J9DQojIEVzdGltYXRlIG1lYW4gZmx1IHZhY2NpbmF0aW9uIGJ5IHVyYmFuL3J1cmFsDQpmbHVfdXJiYW5fZXN0IDwtIHN2eWJ5KA0KICB+ZmFjdG9yKGZsdV9zaG90X2NsZWFuKSwNCiAgfmBfVVJCU1RBVGAsDQogIGRlc2lnbiA9IGZsdV9kZXNpZ24sDQogIEZVTiA9IHN2eW1lYW4sDQogIG5hLnJtID0gVFJVRQ0KKQ0KDQojIEZvcm1hdCByZXN1bHRzDQpmbHVfdXJiYW5fZXN0IDwtIGZsdV91cmJhbl9lc3QgJT4lDQogIG11dGF0ZSgNCiAgICBmbHVfcmF0ZSA9IGBmYWN0b3IoZmx1X3Nob3RfY2xlYW4pMWAsICAgICAgIyB2YWNjaW5hdGlvbiA9IDEgKHllcykNCiAgICBmbHVfc2UgPSBgc2UuZmFjdG9yKGZsdV9zaG90X2NsZWFuKTFgLA0KICAgIGxvd2VyX2NpID0gZmx1X3JhdGUgLSAxLjk2ICogZmx1X3NlLA0KICAgIHVwcGVyX2NpID0gZmx1X3JhdGUgKyAxLjk2ICogZmx1X3NlLA0KICAgIHVyYmFuX3J1cmFsID0gaWZlbHNlKGBfVVJCU1RBVGAgPT0gMSwgIlVyYmFuIiwgIlJ1cmFsIikNCiAgKQ0KDQojIERpc3BsYXkNCmZsdV91cmJhbl9lc3RbLCBjKCJ1cmJhbl9ydXJhbCIsICJmbHVfcmF0ZSIsICJsb3dlcl9jaSIsICJ1cHBlcl9jaSIpXQ0KYGBgDQojIyMgQ29tcGFyaXNvbiBvZiBmbHUgdmFjY2luYXRpb24gcmF0ZXMgKDY1KykgYnkgZXRobmljaXR5DQpgYGB7cn0NCiMgV2VpZ2h0ZWQgbWVhbiBieSByYWNlICg2NSspLCBpZ25vcmluZyA5IChEb24ndCBrbm93L1JlZnVzZWQpDQpmbHVfcmFjZV9lc3QgPC0gc3Z5YnkoDQogIH5mYWN0b3IoZmx1X3Nob3RfY2xlYW4pLA0KICB+ZmFjdG9yKGlmZWxzZShgX1JBQ0VHUjNgICVpbiUgYygxLDIsMyw0LDUpLCBgX1JBQ0VHUjNgLCBOQSkpLA0KICBkZXNpZ24gPSBmbHVfZGVzaWduLA0KICBGVU4gPSBzdnltZWFuLA0KICBuYS5ybSA9IFRSVUUNCikNCg0KIyBPZmZpY2lhbCA1LWxldmVsIHJhY2UvZXRobmljaXR5IGxhYmVscw0KcmFjZV9sYWJlbHMgPC0gYygNCiAgIldoaXRlIG9ubHksIE5vbi1IaXNwYW5pYyIsDQogICJCbGFjayBvbmx5LCBOb24tSGlzcGFuaWMiLA0KICAiT3RoZXIgcmFjZSBvbmx5LCBOb24tSGlzcGFuaWMiLA0KICAiTXVsdGlyYWNpYWwsIE5vbi1IaXNwYW5pYyIsDQogICJIaXNwYW5pYyINCikNCg0KIyBFeHBsaWNpdCBjb2x1bW4gbmFtZXMgZm9yICJZZXMiIGFuZCBpdHMgU0UNCnJhdGVfY29sIDwtICJmYWN0b3IoZmx1X3Nob3RfY2xlYW4pMSINCnNlX2NvbCAgIDwtICJzZS5mYWN0b3IoZmx1X3Nob3RfY2xlYW4pMSINCg0KIyBQcmludCBwZXJjZW50YWdlcyB3aXRoIDk1JSBDSXMNCmZvciAoaSBpbiBzZXFfYWxvbmcocmFjZV9sYWJlbHMpKSB7DQogIHJhdGUgPC0gZmx1X3JhY2VfZXN0W1tyYXRlX2NvbF1dW2ldDQogIHNlICAgPC0gZmx1X3JhY2VfZXN0W1tzZV9jb2xdXVtpXQ0KICBsb3dlciA8LSByYXRlIC0gMS45NiAqIHNlDQogIHVwcGVyIDwtIHJhdGUgKyAxLjk2ICogc2UNCiAgDQogIGNhdChzcHJpbnRmKA0KICAgICJGbHUgdmFjY2luYXRpb24gcmF0ZSAoJXMsIDY1Kyk6ICUuMWYlJSAoOTUlJSBDSTogJS4xZiUl4oCTJS4xZiUlKVxuIiwNCiAgICByYWNlX2xhYmVsc1tpXSwNCiAgICByYXRlICogMTAwLA0KICAgIGxvd2VyICogMTAwLA0KICAgIHVwcGVyICogMTAwDQogICkpDQp9DQpgYGANCmBgYHtyfQ0KIyBJbnNwZWN0IGNvbHVtbiBuYW1lcyBvbmNlDQpuYW1lcyhmbHVfcmFjZV9lc3QpDQpgYGANCiMjIyBDb21wYXJpc29uIG9mIGZsdSB2YWNjaW5hdGlvbiByYXRlcyAoNjUrKSBieSBzZXgNCmBgYHtyfQ0KIyBBZGp1c3QgZm9yICJsb25lbHkiIFBTVXMgKHN0cmF0YSB3aXRoIG9ubHkgb25lIFBTVSkgaW4gdmFyaWFuY2UgZXN0aW1hdGlvbg0Kb3B0aW9ucyhzdXJ2ZXkubG9uZWx5LnBzdSA9ICJhZGp1c3QiKQ0KDQojIEVzdGltYXRlIG1lYW4gZmx1IHZhY2NpbmF0aW9uIGJ5IG1hbGUgKDEpIG9yIGZlbWFsZSAoMikNCmZsdV9zZXhfZXN0IDwtIHN2eWJ5KA0KICB+ZmFjdG9yKGZsdV9zaG90X2NsZWFuKSwNCiAgfmBfU0VYYCwNCiAgZGVzaWduID0gZmx1X2Rlc2lnbiwNCiAgRlVOID0gc3Z5bWVhbiwNCiAgbmEucm0gPSBUUlVFDQopDQoNCiMgRm9ybWF0IHJlc3VsdHMNCmZsdV9zZXhfZXN0IDwtIGZsdV9zZXhfZXN0ICU+JQ0KICBtdXRhdGUoDQogICAgZmx1X3JhdGUgPSBgZmFjdG9yKGZsdV9zaG90X2NsZWFuKTFgLCAgICAgICMgdmFjY2luYXRpb24gPSAxICh5ZXMpDQogICAgZmx1X3NlID0gYHNlLmZhY3RvcihmbHVfc2hvdF9jbGVhbikxYCwNCiAgICBsb3dlcl9jaSA9IGZsdV9yYXRlIC0gMS45NiAqIGZsdV9zZSwNCiAgICB1cHBlcl9jaSA9IGZsdV9yYXRlICsgMS45NiAqIGZsdV9zZSwNCiAgICBtYWxlX2ZlbWFsZSA9IGNhc2Vfd2hlbigNCiAgICAgIGBfU0VYYCA9PSAxIH4gIk1hbGUiLA0KICAgICAgYF9TRVhgID09IDIgfiAiRmVtYWxlIiwNCiAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICAgKQ0KICApDQoNCiMgRGlzcGxheQ0KZmx1X3NleF9lc3RbLCBjKCJtYWxlX2ZlbWFsZSIsICJmbHVfcmF0ZSIsICJsb3dlcl9jaSIsICJ1cHBlcl9jaSIpXQ0KYGBgDQoNCg0KDQo=