Question (Impact): Is there an emerging pattern of increasing delays for federal disaster response?

Data Sets: Disaster Declarations Summaries v2: https://drive.google.com/file/d/1YhwtLE-e428HYR-CLruthPc3VHoWb2cg/view?usp=sharing

Methodology

I used FEMA’s Disaster Declarations Summaries v2, a publicly available dataset spanning the Eisenhower administration to the present, where each row represents a county-level disaster designation. The variable days_to_declaration measures the number of calendar days between incidentBeginDate and declarationDate using difftime() in R, restricted to Major Disaster Declarations only (declarationType == “DR”) as these usually indicate more broad federal assistance.

Because each row is a county designation rather than a unique disaster, the data needed to be cleaned. A check of ~3,000 state-incident combinations found only 13 with variation in declaration dates within a single state which were nearly all attributable to tribal nations receiving separate, typically later, declarations. My analysis groups at the state level but keeps county-level rows to report minimum, median, and maximum lag in declaration per state rather than reducing to a single #. Median is used as the primary statistic over mean to try and avoid a single outlier county disproportionately skewing state-wide data.

Hurricane Helene is isolated by incidentId rather than name string, as a string search for “helene” returns rows from an older unrelated storm since FEMA reuses storm names. I chose Hurricanes Camille, Floyd, Frances, Ivan, Jeanne, Harvey, Ida, and Matthew as comparable storms because of their similar rapid intensification and extreme rainfall. I tried making both a median and a simple unweighted mean chart to compare. A weighted average by population or damage estimates would be more rigorous but would probably require joining an additional dataset?

I also tried to filter for those reservations to analyze that more closely. One key limitation throughout is that the lag clock starts at incident begin, but FEMA cannot declare until a state governor formally requests it, meaning some delay may reflect state-level decisions rather than federal response time.

library(dplyr)
library(stringr)
library(lubridate)
library(ggplot2)
df_FEMA_OG <- read.csv('FEMA_disaster_declarations.csv')
df_FEMA_clean <- df_FEMA_OG %>%
  mutate(
    declarationDate   = as_date(declarationDate),
    incidentBeginDate = as_date(incidentBeginDate),
    incidentEndDate   = as_date(incidentEndDate)
  )

Checking incidentId vs. string filtering (Professor’s note)

Filtering by name string catches an older storm also named Helene. Used incidentId.

helene_by_id <- df_FEMA_OG %>%
  filter(incidentId == '2024092301')

helene_by_string <- df_FEMA_OG %>%
  filter(grepl("helene", declarationTitle, ignore.case = TRUE))

#since helene by string has more, let's see what it has that's not in the list filtered by ID number

helene_missing_in_id <- helene_by_string %>%
  filter(!id %in% helene_by_id$id)

## and vice versa just in case 

helene_missing_in_string <- helene_by_id %>%
  filter(!id %in% helene_by_string$id)


#filtering using the string includes rows from another storm named helene before!!

cat("Rows caught by string but not ID (older storm):", nrow(helene_missing_in_id), "\n")
Rows caught by string but not ID (older storm): 9 
cat("Rows caught by ID but not string:", nrow(helene_missing_in_string), "\n")
Rows caught by ID but not string: 0 

Days to Declaration — All DR Declarations

all_DR_data <- df_FEMA_clean %>%
  filter(declarationType == 'DR') %>%
  mutate(days_to_declaration = as.numeric(difftime(declarationDate, incidentBeginDate, units = "days")))
DR_data_comparable <- all_DR_data %>%
  filter(incidentType %in% c("Hurricane", "Tropical Storm")) %>%
  filter(str_detect(str_to_lower(declarationTitle),
                    paste(comparable_names, collapse = "|"))) %>%
  distinct(declarationTitle, incidentId, incidentBeginDate) %>%
  arrange(incidentBeginDate)

DR_data_comparable
NA
# check whether declaration dates vary within a state for a given incident
# If count == 1 for all rows, every county in that state-incident got the same date
# only 13 out of ~3,000 state-incident combos have variation

DR_states_incidents <- all_DR_data %>%
  select(femaDeclarationString, state, incidentId, incidentBeginDate, declarationDate) %>%
  unique() %>%
  group_by(state, incidentId) %>%
  summarise(count = n(), .groups = "drop")

# View the 13 exceptions
DR_states_incidents %>%
  filter(count > 1) %>%
  arrange(desc(count))
# nearly all exceptions appear to be tribal declarations with a
# later date.

exception_ids <- DR_states_incidents %>%
  filter(count > 1) %>%
  pull(incidentId)

all_DR_data %>%
  filter(incidentId %in% exception_ids) %>%
  select(femaDeclarationString, state, incidentId, designatedArea,
         incidentBeginDate, declarationDate, days_to_declaration, tribalRequest) %>%
  unique() %>%
  arrange(incidentId, declarationDate)

Since within-state date variation is minimal and largely driven by tribal declarations, I grouped at the state level for the main analysis.

# One row per state-incident: take the earliest declaration date within each group
# (tribal declarations tend to be later and are a separate phenomenon)

DR_state_level <- all_DR_data %>%
  select(femaDeclarationString, state, incidentId, incidentType,
         declarationTitle, incidentBeginDate, declarationDate,
         days_to_declaration, tribalRequest, fyDeclared) %>%
  unique() %>%
  group_by(state, incidentId) %>%
  slice_min(declarationDate, n = 1, with_ties = FALSE) %>%
  ungroup()

Hurricane Helene

helene_data_DR <- df_FEMA_clean %>%
  filter(declarationType == 'DR') %>%
  filter(incidentId == '2024092301') %>%
  mutate(days_to_declaration = as.numeric(difftime(declarationDate, incidentBeginDate, units = "days")))
helene_state_summary <- helene_data_DR %>%
  group_by(state) %>%
  summarise(
    n_counties = n(),
    min_lag    = min(days_to_declaration),
    median_lag = median(days_to_declaration),
    max_lag    = max(days_to_declaration),
    .groups    = "drop"
  ) %>%
  arrange(median_lag)

helene_state_summary
# I heavily used the help of Claude here to help me chart what I found visually. I think for KY and WV being a lot later that might be because of delayed effects? Or maybe that's something to look further into.
# bar height shows median lag in response. States where min and max are far apart
# probably need closer inspection where one county may have had an unusually delayed declaration
helene_state_summary %>%  
ggplot(aes(x = reorder(state, -median_lag), y = median_lag, fill = median_lag)) +
  geom_col() +
  geom_text(aes(label = median_lag), hjust = -0.2, size = 3.5) +
  coord_flip() +
  scale_fill_gradient(low = "steelblue", high = "firebrick") +
  labs(
    title    = "Hurricane Helene: Median Days to DR Declaration by State",
    subtitle = "Incident began 2024-09-23; bar shows median, see helene_state_summary for min/max",
    x        = NULL,
    y        = "Median Days to Declaration"
  ) +
  theme_minimal() +
  theme(legend.position = "none")


Comparable Storms (grouped by incidentId)

Rather than filtering by name string, I grouped all DR declarations by incidentId and then label the storms of interest.

#trying to include storms to compare any delays via helene to
comparable_ids <- c(
  "69034", "69035", "69043",       # Camille (1969)
  "1999091407",                     # Floyd (1999)
  "8091000001",                     # Frances/Georges (1998)
  "2004082901",                     # Frances (2004)
  "2004090502",                     # Ivan (2004)
  "2004091501",                     # Jeanne (2004)
  "2009110901",                     # Ida (2009)
  "2016092802",                     # Matthew (2016)
  "2017082301",                     # Harvey (2017)
  "2021082601",                     # Ida (2021)
  "2022092201",               # Ian - Seminole Tribe (2022)
  "2023082403",                     # Idalia (2023)
  "2024092301"                      # Helene (2024)
)

comparable_storms <- all_DR_data %>%
  filter(incidentId %in% comparable_ids) %>%
  filter(days_to_declaration >= 0) %>%
  mutate(
    storm_label = case_when(
      incidentId %in% c("69034", "69035", "69043") ~ "Camille (1969)",
      incidentId == "1999091407" ~ "Floyd (1999)",
      incidentId == "8091000001" ~ "Frances/Georges (1998)",
      incidentId == "2004082901" ~ "Frances (2004)",
      incidentId == "2004090502" ~ "Ivan (2004)",
      incidentId == "2004091501" ~ "Jeanne (2004)",
      incidentId == "2009110901" ~ "Ida (2009)",
      incidentId == "2016092802" ~ "Matthew (2016)",
      incidentId == "2017082301" ~ "Harvey (2017)",
      incidentId == "2021082601" ~ "Ida (2021)",
      incidentId == "2022092201" ~ "Ian - Seminole (2022)",
      incidentId == "2023082403" ~ "Idalia (2023)",
      incidentId == "2024092301" ~ "Helene (2024)"
    )
  ) %>%
  distinct(incidentId, designatedArea, state, .keep_all = TRUE)%>%
  group_by(storm_label) %>%
  summarise(
    n_counties = n(),
    #thought this would be okay 
    min_lag    = min(days_to_declaration),
    median_lag = median(days_to_declaration),
    max_lag    = max(days_to_declaration),
    .groups    = "drop"
  )

comparable_storms
#plotting those comparable storms
comparable_storms %>%
  mutate(year = as.numeric(str_extract(storm_label, "\\d{4}"))) %>%
  ggplot(aes(x = reorder(storm_label, year), y = median_lag)) +
  geom_col(fill = "steelblue", alpha = 0.8) +
  geom_text(aes(label = round(median_lag, 0)), hjust = -0.2, size = 3.5) +
  coord_flip() +
    scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(
    title    = "Median Declaration Lag for Storms Comparable to Helene",
    subtitle = "DR declarations only; median across all designated counties",
    x        = NULL,
    y        = "Median Days from Incident Begin to Declaration"
  ) +
  theme_minimal()

#i wanted to include something that didn't take into account the number of counties in a state just in case it was useful to compare
comparable_storms_unweighted <- all_DR_data %>%
  filter(incidentId %in% comparable_ids) %>%
  filter(days_to_declaration >= 0) %>%
  mutate(
    storm_label = case_when(
      incidentId %in% c("69034", "69035", "69043") ~ "Camille (1969)",
      incidentId == "1999091407" ~ "Floyd (1999)",
      incidentId == "8091000001" ~ "Frances/Georges (1998)",
      incidentId == "2004082901" ~ "Frances (2004)",
      incidentId == "2004090502" ~ "Ivan (2004)",
      incidentId == "2004091501" ~ "Jeanne (2004)",
      incidentId == "2009110901" ~ "Ida (2009)",
      incidentId == "2016092802" ~ "Matthew (2016)",
      incidentId == "2017082301" ~ "Harvey (2017)",
      incidentId == "2021082601" ~ "Ida (2021)",
      incidentId == "2022092201" ~ "Ian (2022)",
      incidentId == "2023082403" ~ "Idalia (2023)",
      incidentId == "2024092301" ~ "Helene (2024)"
    )
  ) %>%
  filter(!is.na(storm_label)) %>%
  group_by(storm_label) %>%
  summarise(
    n_counties = n(),
    mean_lag   = round(mean(days_to_declaration), 1),
    .groups    = "drop"
  )
comparable_storms_unweighted %>%
  mutate(year = as.numeric(str_extract(storm_label, "\\d{4}"))) %>%
  ggplot(aes(x = reorder(storm_label, year), y = mean_lag)) +
  geom_col(fill = "firebrick", alpha = 0.8) +
  geom_text(aes(label = mean_lag), hjust = -0.2, size = 3.5) +
  coord_flip() +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(
    title    = "Unweighted Mean Declaration Lag for Storms Comparable to Helene",
    subtitle = "DR declarations only; simple mean across all designated counties — compare with median chart above",
    x        = NULL,
    y        = "Mean Days from Incident Begin to Declaration"
  ) +
  theme_minimal()

#Having trouble figuring out why one is showing up as NA. I used code below to try and filter for what was causing the problem and I guess Ian is Hurricane Ian + Hurricane Ian Seminole Tribe of Florida, both under the same incidentID.

df_findna <- all_DR_data %>%
  filter(incidentId %in% comparable_ids) %>%
  filter(days_to_declaration >= 0) %>%
  mutate(
    storm_label = case_when(
      incidentId %in% c("69034", "69035", "69043") ~ "Camille (1969)",
      incidentId == "1999091407" ~ "Floyd (1999)",
      incidentId == "8091000001" ~ "Frances/Georges (1998)",
      incidentId == "2004082901" ~ "Frances (2004)",
      incidentId == "2004090502" ~ "Ivan (2004)",
      incidentId == "2004091501" ~ "Jeanne (2004)",
      incidentId == "2009110901" ~ "Ida (2009)",
      incidentId == "2016092802" ~ "Matthew (2016)",
      incidentId == "2017082301" ~ "Harvey (2017)",
      incidentId == "2021082601" ~ "Ida (2021)",
      incidentId == "2023082403" ~ "Idalia (2023)",
      incidentId == "2024092301" ~ "Helene (2024)"
    )
  ) %>%
  filter(is.na(storm_label)) %>%
  distinct(incidentId, declarationTitle)
tribal_DR <- all_DR_data %>%
  filter(
  tribalRequest == 1 |
  str_detect(str_to_lower(designatedArea), "indian nation|indian reservation|indian tribe|band of cherokee|band of indian|pueblo|tribe of")
)%>%
  filter(
    str_detect(str_to_lower(declarationTitle),
               paste(comparable_names, collapse = "|")) | incidentId == "2024092301"
  ) %>%
  group_by(state, designatedArea, declarationTitle, fyDeclared) %>%
  summarise(
    n_declarations = n(),
    min_lag        = min(days_to_declaration),
    median_lag     = median(days_to_declaration),
    max_lag        = max(days_to_declaration),
    .groups        = "drop"
  ) %>%
  arrange(desc(median_lag))

tribal_DR
tribal_DR %>%
  mutate(area_label = paste0(designatedArea, " (", declarationTitle, ")")) %>%
  ggplot(aes(x = reorder(area_label, median_lag), y = median_lag, fill = median_lag)) +
  geom_col() +
  geom_text(aes(label = median_lag), hjust = -0.2, size = 3.5) +
  coord_flip() +
  scale_fill_gradient(low = "steelblue", high = "firebrick") +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(
    title    = "Declaration Lag for Tribal Areas",
    subtitle = "Helene + comparable storms",
    x        = NULL,
    y        = "Median Days to Declaration"
  ) +
  theme_minimal() +
  theme(legend.position = "none",
        axis.text.y = element_text(size = 7))

write.csv(helene_state_summary, "helene_state_summary.csv", row.names = FALSE)
write.csv(comparable_storms, "comparable_storms.csv", row.names = FALSE)
write.csv(comparable_storms_unweighted, "comparable_storms_unweighted.csv", row.names = FALSE)
write.csv(tribal_DR, "tribal_DR.csv", row.names = FALSE)

Conclusions/Answers

FEMA response for Helene was actually not terrible – most do not show a delay surpassing ~1 week. I feel like that may be explainable because of what my source told me, which is that for state-level funding/rsponse, there is a lot of paperwork and bureaucracy involved in that which could explain delays. Or the state simply took longer to expend their own resources. KY and WV are big outliers with 60 days between incident start and dec date. Every county listed had the same delay #.

Compared to other storms, Helene response was on the faster end, most similar to Hurricane Matthew in 2016. However, Helene’s max declaration date of 75 days in WV is the highest of any storm I selected.

Something interesting too and something I’d like to explore further is why tribal reservations, especially those in FL, experience delays in their declarations in comparison to the rest of the state. This was at its worst during Hurricane Ida, which had a 59 day delay.

Overall, I wouldn’t be comfortable making the claim that FEMA has an increasing pattern of a lack of disaster response. Delays seem to be isolated to certain storms, and I suspect there are more political factors involved with Hurricane Helene and FEMA issues behind public outcry against FEMA following the disaster. I’d say my hypothesis that there was a concrete pattern emerging is not all the way true, but it is something that can’t be simplified to looking at declaration dates alone because of other moving pieces in disaster response.

LS0tCnRpdGxlOiAiRkVNQSBEYXRhIERvYyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgUXVlc3Rpb24gKEltcGFjdCk6IElzIHRoZXJlIGFuIGVtZXJnaW5nIHBhdHRlcm4gb2YgaW5jcmVhc2luZyBkZWxheXMgZm9yIGZlZGVyYWwgZGlzYXN0ZXIgcmVzcG9uc2U/CgojIyBEYXRhIFNldHM6IERpc2FzdGVyIERlY2xhcmF0aW9ucyBTdW1tYXJpZXMgdjI6IDxodHRwczovL2RyaXZlLmdvb2dsZS5jb20vZmlsZS9kLzFZaHd0TEUtZTQyOEhZUi1DTHJ1dGhQYzNWSG9XYjJjZy92aWV3P3VzcD1zaGFyaW5nPgoKIyMgTWV0aG9kb2xvZ3kKCkkgdXNlZCBGRU1BJ3MgRGlzYXN0ZXIgRGVjbGFyYXRpb25zIFN1bW1hcmllcyB2MiwgYSBwdWJsaWNseSBhdmFpbGFibGUgZGF0YXNldCBzcGFubmluZyB0aGUgRWlzZW5ob3dlciBhZG1pbmlzdHJhdGlvbiB0byB0aGUgcHJlc2VudCwgd2hlcmUgZWFjaCByb3cgcmVwcmVzZW50cyBhIGNvdW50eS1sZXZlbCBkaXNhc3RlciBkZXNpZ25hdGlvbi4gVGhlIHZhcmlhYmxlIGRheXNfdG9fZGVjbGFyYXRpb24gbWVhc3VyZXMgdGhlIG51bWJlciBvZiBjYWxlbmRhciBkYXlzIGJldHdlZW4gaW5jaWRlbnRCZWdpbkRhdGUgYW5kIGRlY2xhcmF0aW9uRGF0ZSB1c2luZyBkaWZmdGltZSgpIGluIFIsIHJlc3RyaWN0ZWQgdG8gTWFqb3IgRGlzYXN0ZXIgRGVjbGFyYXRpb25zIG9ubHkgKGRlY2xhcmF0aW9uVHlwZSA9PSAiRFIiKSBhcyB0aGVzZSB1c3VhbGx5IGluZGljYXRlIG1vcmUgYnJvYWQgZmVkZXJhbCBhc3Npc3RhbmNlLgoKQmVjYXVzZSBlYWNoIHJvdyBpcyBhIGNvdW50eSBkZXNpZ25hdGlvbiByYXRoZXIgdGhhbiBhIHVuaXF1ZSBkaXNhc3RlciwgdGhlIGRhdGEgbmVlZGVkIHRvIGJlIGNsZWFuZWQuIEEgY2hlY2sgb2YgfjMsMDAwIHN0YXRlLWluY2lkZW50IGNvbWJpbmF0aW9ucyBmb3VuZCBvbmx5IDEzIHdpdGggdmFyaWF0aW9uIGluIGRlY2xhcmF0aW9uIGRhdGVzIHdpdGhpbiBhIHNpbmdsZSBzdGF0ZSB3aGljaCB3ZXJlIG5lYXJseSBhbGwgYXR0cmlidXRhYmxlIHRvIHRyaWJhbCBuYXRpb25zIHJlY2VpdmluZyBzZXBhcmF0ZSwgdHlwaWNhbGx5IGxhdGVyLCBkZWNsYXJhdGlvbnMuIE15IGFuYWx5c2lzIGdyb3VwcyBhdCB0aGUgc3RhdGUgbGV2ZWwgYnV0IGtlZXBzIGNvdW50eS1sZXZlbCByb3dzIHRvIHJlcG9ydCBtaW5pbXVtLCBtZWRpYW4sIGFuZCBtYXhpbXVtIGxhZyBpbiBkZWNsYXJhdGlvbiBwZXIgc3RhdGUgcmF0aGVyIHRoYW4gcmVkdWNpbmcgdG8gYSBzaW5nbGUgIy4gTWVkaWFuIGlzIHVzZWQgYXMgdGhlIHByaW1hcnkgc3RhdGlzdGljIG92ZXIgbWVhbiB0byB0cnkgYW5kIGF2b2lkIGEgc2luZ2xlIG91dGxpZXIgY291bnR5IGRpc3Byb3BvcnRpb25hdGVseSBza2V3aW5nIHN0YXRlLXdpZGUgZGF0YS4KCkh1cnJpY2FuZSBIZWxlbmUgaXMgaXNvbGF0ZWQgYnkgaW5jaWRlbnRJZCByYXRoZXIgdGhhbiBuYW1lIHN0cmluZywgYXMgYSBzdHJpbmcgc2VhcmNoIGZvciAiaGVsZW5lIiByZXR1cm5zIHJvd3MgZnJvbSBhbiBvbGRlciB1bnJlbGF0ZWQgc3Rvcm0gc2luY2UgRkVNQSByZXVzZXMgc3Rvcm0gbmFtZXMuIEkgY2hvc2UgSHVycmljYW5lcyBDYW1pbGxlLCBGbG95ZCwgRnJhbmNlcywgSXZhbiwgSmVhbm5lLCBIYXJ2ZXksIElkYSwgYW5kIE1hdHRoZXcgYXMgY29tcGFyYWJsZSBzdG9ybXMgYmVjYXVzZSBvZiB0aGVpciBzaW1pbGFyIHJhcGlkIGludGVuc2lmaWNhdGlvbiBhbmQgZXh0cmVtZSByYWluZmFsbC4gSSB0cmllZCBtYWtpbmcgYm90aCBhIG1lZGlhbiBhbmQgYSBzaW1wbGUgdW53ZWlnaHRlZCBtZWFuIGNoYXJ0IHRvIGNvbXBhcmUuICBBIHdlaWdodGVkIGF2ZXJhZ2UgYnkgcG9wdWxhdGlvbiBvciBkYW1hZ2UgZXN0aW1hdGVzIHdvdWxkIGJlIG1vcmUgcmlnb3JvdXMgYnV0IHdvdWxkIHByb2JhYmx5IHJlcXVpcmUgam9pbmluZyBhbiBhZGRpdGlvbmFsIGRhdGFzZXQ/CgpJIGFsc28gdHJpZWQgdG8gZmlsdGVyIGZvciB0aG9zZSByZXNlcnZhdGlvbnMgdG8gYW5hbHl6ZSB0aGF0IG1vcmUgY2xvc2VseS4gT25lIGtleSBsaW1pdGF0aW9uIHRocm91Z2hvdXQgaXMgdGhhdCB0aGUgbGFnIGNsb2NrIHN0YXJ0cyBhdCBpbmNpZGVudCBiZWdpbiwgYnV0IEZFTUEgY2Fubm90IGRlY2xhcmUgdW50aWwgYSBzdGF0ZSBnb3Zlcm5vciBmb3JtYWxseSByZXF1ZXN0cyBpdCwgbWVhbmluZyBzb21lIGRlbGF5IG1heSByZWZsZWN0IHN0YXRlLWxldmVsIGRlY2lzaW9ucyByYXRoZXIgdGhhbiBmZWRlcmFsIHJlc3BvbnNlIHRpbWUuCgpgYGB7ciBzZXR1cCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeShkcGx5cikKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeShnZ3Bsb3QyKQpgYGAKCmBgYHtyIGxvYWR9CmRmX0ZFTUFfT0cgPC0gcmVhZC5jc3YoJ0ZFTUFfZGlzYXN0ZXJfZGVjbGFyYXRpb25zLmNzdicpCmBgYAoKYGBge3IgY2xlYW4tZGF0ZXN9CmRmX0ZFTUFfY2xlYW4gPC0gZGZfRkVNQV9PRyAlPiUKICBtdXRhdGUoCiAgICBkZWNsYXJhdGlvbkRhdGUgICA9IGFzX2RhdGUoZGVjbGFyYXRpb25EYXRlKSwKICAgIGluY2lkZW50QmVnaW5EYXRlID0gYXNfZGF0ZShpbmNpZGVudEJlZ2luRGF0ZSksCiAgICBpbmNpZGVudEVuZERhdGUgICA9IGFzX2RhdGUoaW5jaWRlbnRFbmREYXRlKQogICkKYGBgCgotLS0KCiMjIENoZWNraW5nIGluY2lkZW50SWQgdnMuIHN0cmluZyBmaWx0ZXJpbmcgKFByb2Zlc3NvcidzIG5vdGUpCgpGaWx0ZXJpbmcgYnkgbmFtZSBzdHJpbmcgY2F0Y2hlcyBhbiBvbGRlciBzdG9ybSBhbHNvIG5hbWVkIEhlbGVuZS4gVXNlZCBgaW5jaWRlbnRJZGAuCgpgYGB7ciBoZWxlbmUtaWQtdnMtc3RyaW5nfQpoZWxlbmVfYnlfaWQgPC0gZGZfRkVNQV9PRyAlPiUKICBmaWx0ZXIoaW5jaWRlbnRJZCA9PSAnMjAyNDA5MjMwMScpCgpoZWxlbmVfYnlfc3RyaW5nIDwtIGRmX0ZFTUFfT0cgJT4lCiAgZmlsdGVyKGdyZXBsKCJoZWxlbmUiLCBkZWNsYXJhdGlvblRpdGxlLCBpZ25vcmUuY2FzZSA9IFRSVUUpKQoKI3NpbmNlIGhlbGVuZSBieSBzdHJpbmcgaGFzIG1vcmUsIGxldCdzIHNlZSB3aGF0IGl0IGhhcyB0aGF0J3Mgbm90IGluIHRoZSBsaXN0IGZpbHRlcmVkIGJ5IElEIG51bWJlcgoKaGVsZW5lX21pc3NpbmdfaW5faWQgPC0gaGVsZW5lX2J5X3N0cmluZyAlPiUKICBmaWx0ZXIoIWlkICVpbiUgaGVsZW5lX2J5X2lkJGlkKQoKIyMgYW5kIHZpY2UgdmVyc2EganVzdCBpbiBjYXNlIAoKaGVsZW5lX21pc3NpbmdfaW5fc3RyaW5nIDwtIGhlbGVuZV9ieV9pZCAlPiUKICBmaWx0ZXIoIWlkICVpbiUgaGVsZW5lX2J5X3N0cmluZyRpZCkKCgojZmlsdGVyaW5nIHVzaW5nIHRoZSBzdHJpbmcgaW5jbHVkZXMgcm93cyBmcm9tIGFub3RoZXIgc3Rvcm0gbmFtZWQgaGVsZW5lIGJlZm9yZSEhCgpjYXQoIlJvd3MgY2F1Z2h0IGJ5IHN0cmluZyBidXQgbm90IElEIChvbGRlciBzdG9ybSk6IiwgbnJvdyhoZWxlbmVfbWlzc2luZ19pbl9pZCksICJcbiIpCmNhdCgiUm93cyBjYXVnaHQgYnkgSUQgYnV0IG5vdCBzdHJpbmc6IiwgbnJvdyhoZWxlbmVfbWlzc2luZ19pbl9zdHJpbmcpLCAiXG4iKQpgYGAKCi0tLQoKIyMgRGF5cyB0byBEZWNsYXJhdGlvbiDigJQgQWxsIERSIERlY2xhcmF0aW9ucwoKYGBge3IgYWxsLWRyfQphbGxfRFJfZGF0YSA8LSBkZl9GRU1BX2NsZWFuICU+JQogIGZpbHRlcihkZWNsYXJhdGlvblR5cGUgPT0gJ0RSJykgJT4lCiAgbXV0YXRlKGRheXNfdG9fZGVjbGFyYXRpb24gPSBhcy5udW1lcmljKGRpZmZ0aW1lKGRlY2xhcmF0aW9uRGF0ZSwgaW5jaWRlbnRCZWdpbkRhdGUsIHVuaXRzID0gImRheXMiKSkpCmBgYAoKYGBge3IgYWxsLWRyLWNvbXBhcmFibGV9CkRSX2RhdGFfY29tcGFyYWJsZSA8LSBhbGxfRFJfZGF0YSAlPiUKICBmaWx0ZXIoaW5jaWRlbnRUeXBlICVpbiUgYygiSHVycmljYW5lIiwgIlRyb3BpY2FsIFN0b3JtIikpICU+JQogIGZpbHRlcihzdHJfZGV0ZWN0KHN0cl90b19sb3dlcihkZWNsYXJhdGlvblRpdGxlKSwKICAgICAgICAgICAgICAgICAgICBwYXN0ZShjb21wYXJhYmxlX25hbWVzLCBjb2xsYXBzZSA9ICJ8IikpKSAlPiUKICBkaXN0aW5jdChkZWNsYXJhdGlvblRpdGxlLCBpbmNpZGVudElkLCBpbmNpZGVudEJlZ2luRGF0ZSkgJT4lCiAgYXJyYW5nZShpbmNpZGVudEJlZ2luRGF0ZSkKCkRSX2RhdGFfY29tcGFyYWJsZQoKYGBgCgpgYGB7ciBkci1zdGF0ZXMtaW5jaWRlbnRzfQojIGNoZWNrIHdoZXRoZXIgZGVjbGFyYXRpb24gZGF0ZXMgdmFyeSB3aXRoaW4gYSBzdGF0ZSBmb3IgYSBnaXZlbiBpbmNpZGVudAojIElmIGNvdW50ID09IDEgZm9yIGFsbCByb3dzLCBldmVyeSBjb3VudHkgaW4gdGhhdCBzdGF0ZS1pbmNpZGVudCBnb3QgdGhlIHNhbWUgZGF0ZQojIG9ubHkgMTMgb3V0IG9mIH4zLDAwMCBzdGF0ZS1pbmNpZGVudCBjb21ib3MgaGF2ZSB2YXJpYXRpb24KCkRSX3N0YXRlc19pbmNpZGVudHMgPC0gYWxsX0RSX2RhdGEgJT4lCiAgc2VsZWN0KGZlbWFEZWNsYXJhdGlvblN0cmluZywgc3RhdGUsIGluY2lkZW50SWQsIGluY2lkZW50QmVnaW5EYXRlLCBkZWNsYXJhdGlvbkRhdGUpICU+JQogIHVuaXF1ZSgpICU+JQogIGdyb3VwX2J5KHN0YXRlLCBpbmNpZGVudElkKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIC5ncm91cHMgPSAiZHJvcCIpCgojIFZpZXcgdGhlIDEzIGV4Y2VwdGlvbnMKRFJfc3RhdGVzX2luY2lkZW50cyAlPiUKICBmaWx0ZXIoY291bnQgPiAxKSAlPiUKICBhcnJhbmdlKGRlc2MoY291bnQpKQpgYGAKCmBgYHtyIGNoZWNrLWV4Y2VwdGlvbnMtdHJpYmFsfQojIG5lYXJseSBhbGwgZXhjZXB0aW9ucyBhcHBlYXIgdG8gYmUgdHJpYmFsIGRlY2xhcmF0aW9ucyB3aXRoIGEKIyBsYXRlciBkYXRlLgoKZXhjZXB0aW9uX2lkcyA8LSBEUl9zdGF0ZXNfaW5jaWRlbnRzICU+JQogIGZpbHRlcihjb3VudCA+IDEpICU+JQogIHB1bGwoaW5jaWRlbnRJZCkKCmFsbF9EUl9kYXRhICU+JQogIGZpbHRlcihpbmNpZGVudElkICVpbiUgZXhjZXB0aW9uX2lkcykgJT4lCiAgc2VsZWN0KGZlbWFEZWNsYXJhdGlvblN0cmluZywgc3RhdGUsIGluY2lkZW50SWQsIGRlc2lnbmF0ZWRBcmVhLAogICAgICAgICBpbmNpZGVudEJlZ2luRGF0ZSwgZGVjbGFyYXRpb25EYXRlLCBkYXlzX3RvX2RlY2xhcmF0aW9uLCB0cmliYWxSZXF1ZXN0KSAlPiUKICB1bmlxdWUoKSAlPiUKICBhcnJhbmdlKGluY2lkZW50SWQsIGRlY2xhcmF0aW9uRGF0ZSkKYGBgCgpTaW5jZSB3aXRoaW4tc3RhdGUgZGF0ZSB2YXJpYXRpb24gaXMgbWluaW1hbCBhbmQgbGFyZ2VseSBkcml2ZW4gYnkgdHJpYmFsIGRlY2xhcmF0aW9ucywKSSBncm91cGVkIGF0IHRoZSBzdGF0ZSBsZXZlbCBmb3IgdGhlIG1haW4gYW5hbHlzaXMuCgpgYGB7ciBkci1zdGF0ZS1sZXZlbH0KIyBPbmUgcm93IHBlciBzdGF0ZS1pbmNpZGVudDogdGFrZSB0aGUgZWFybGllc3QgZGVjbGFyYXRpb24gZGF0ZSB3aXRoaW4gZWFjaCBncm91cAojICh0cmliYWwgZGVjbGFyYXRpb25zIHRlbmQgdG8gYmUgbGF0ZXIgYW5kIGFyZSBhIHNlcGFyYXRlIHBoZW5vbWVub24pCgpEUl9zdGF0ZV9sZXZlbCA8LSBhbGxfRFJfZGF0YSAlPiUKICBzZWxlY3QoZmVtYURlY2xhcmF0aW9uU3RyaW5nLCBzdGF0ZSwgaW5jaWRlbnRJZCwgaW5jaWRlbnRUeXBlLAogICAgICAgICBkZWNsYXJhdGlvblRpdGxlLCBpbmNpZGVudEJlZ2luRGF0ZSwgZGVjbGFyYXRpb25EYXRlLAogICAgICAgICBkYXlzX3RvX2RlY2xhcmF0aW9uLCB0cmliYWxSZXF1ZXN0LCBmeURlY2xhcmVkKSAlPiUKICB1bmlxdWUoKSAlPiUKICBncm91cF9ieShzdGF0ZSwgaW5jaWRlbnRJZCkgJT4lCiAgc2xpY2VfbWluKGRlY2xhcmF0aW9uRGF0ZSwgbiA9IDEsIHdpdGhfdGllcyA9IEZBTFNFKSAlPiUKICB1bmdyb3VwKCkKYGBgCgotLS0KCiMjIEh1cnJpY2FuZSBIZWxlbmUKCmBgYHtyIGhlbGVuZS1kcn0KaGVsZW5lX2RhdGFfRFIgPC0gZGZfRkVNQV9jbGVhbiAlPiUKICBmaWx0ZXIoZGVjbGFyYXRpb25UeXBlID09ICdEUicpICU+JQogIGZpbHRlcihpbmNpZGVudElkID09ICcyMDI0MDkyMzAxJykgJT4lCiAgbXV0YXRlKGRheXNfdG9fZGVjbGFyYXRpb24gPSBhcy5udW1lcmljKGRpZmZ0aW1lKGRlY2xhcmF0aW9uRGF0ZSwgaW5jaWRlbnRCZWdpbkRhdGUsIHVuaXRzID0gImRheXMiKSkpCmBgYAoKYGBge3IgaGVsZW5lLXN0YXRlLXN1bW1hcnl9CmhlbGVuZV9zdGF0ZV9zdW1tYXJ5IDwtIGhlbGVuZV9kYXRhX0RSICU+JQogIGdyb3VwX2J5KHN0YXRlKSAlPiUKICBzdW1tYXJpc2UoCiAgICBuX2NvdW50aWVzID0gbigpLAogICAgbWluX2xhZyAgICA9IG1pbihkYXlzX3RvX2RlY2xhcmF0aW9uKSwKICAgIG1lZGlhbl9sYWcgPSBtZWRpYW4oZGF5c190b19kZWNsYXJhdGlvbiksCiAgICBtYXhfbGFnICAgID0gbWF4KGRheXNfdG9fZGVjbGFyYXRpb24pLAogICAgLmdyb3VwcyAgICA9ICJkcm9wIgogICkgJT4lCiAgYXJyYW5nZShtZWRpYW5fbGFnKQoKaGVsZW5lX3N0YXRlX3N1bW1hcnkKYGBgCgpgYGB7ciBoZWxlbmUtcGxvdH0KIyBJIGhlYXZpbHkgdXNlZCB0aGUgaGVscCBvZiBDbGF1ZGUgaGVyZSB0byBoZWxwIG1lIGNoYXJ0IHdoYXQgSSBmb3VuZCB2aXN1YWxseS4gSSB0aGluayBmb3IgS1kgYW5kIFdWIGJlaW5nIGEgbG90IGxhdGVyIHRoYXQgbWlnaHQgYmUgYmVjYXVzZSBvZiBkZWxheWVkIGVmZmVjdHM/IE9yIG1heWJlIHRoYXQncyBzb21ldGhpbmcgdG8gbG9vayBmdXJ0aGVyIGludG8uCiMgYmFyIGhlaWdodCBzaG93cyBtZWRpYW4gbGFnIGluIHJlc3BvbnNlLiBTdGF0ZXMgd2hlcmUgbWluIGFuZCBtYXggYXJlIGZhciBhcGFydAojIHByb2JhYmx5IG5lZWQgY2xvc2VyIGluc3BlY3Rpb24gd2hlcmUgb25lIGNvdW50eSBtYXkgaGF2ZSBoYWQgYW4gdW51c3VhbGx5IGRlbGF5ZWQgZGVjbGFyYXRpb24KaGVsZW5lX3N0YXRlX3N1bW1hcnkgJT4lICAKZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihzdGF0ZSwgLW1lZGlhbl9sYWcpLCB5ID0gbWVkaWFuX2xhZywgZmlsbCA9IG1lZGlhbl9sYWcpKSArCiAgZ2VvbV9jb2woKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG1lZGlhbl9sYWcpLCBoanVzdCA9IC0wLjIsIHNpemUgPSAzLjUpICsKICBjb29yZF9mbGlwKCkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gInN0ZWVsYmx1ZSIsIGhpZ2ggPSAiZmlyZWJyaWNrIikgKwogIGxhYnMoCiAgICB0aXRsZSAgICA9ICJIdXJyaWNhbmUgSGVsZW5lOiBNZWRpYW4gRGF5cyB0byBEUiBEZWNsYXJhdGlvbiBieSBTdGF0ZSIsCiAgICBzdWJ0aXRsZSA9ICJJbmNpZGVudCBiZWdhbiAyMDI0LTA5LTIzOyBiYXIgc2hvd3MgbWVkaWFuLCBzZWUgaGVsZW5lX3N0YXRlX3N1bW1hcnkgZm9yIG1pbi9tYXgiLAogICAgeCAgICAgICAgPSBOVUxMLAogICAgeSAgICAgICAgPSAiTWVkaWFuIERheXMgdG8gRGVjbGFyYXRpb24iCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKLS0tCgojIyBDb21wYXJhYmxlIFN0b3JtcyAoZ3JvdXBlZCBieSBpbmNpZGVudElkKQoKUmF0aGVyIHRoYW4gZmlsdGVyaW5nIGJ5IG5hbWUgc3RyaW5nLCBJIGdyb3VwZWQgYWxsIERSIGRlY2xhcmF0aW9ucyBieSBgaW5jaWRlbnRJZGAKYW5kIHRoZW4gbGFiZWwgdGhlIHN0b3JtcyBvZiBpbnRlcmVzdC4KCmBgYHtyIGNvbXBhcmFibGUtc3Rvcm1zfQojdHJ5aW5nIHRvIGluY2x1ZGUgc3Rvcm1zIHRvIGNvbXBhcmUgYW55IGRlbGF5cyB2aWEgaGVsZW5lIHRvCmNvbXBhcmFibGVfaWRzIDwtIGMoCiAgIjY5MDM0IiwgIjY5MDM1IiwgIjY5MDQzIiwgICAgICAgIyBDYW1pbGxlICgxOTY5KQogICIxOTk5MDkxNDA3IiwgICAgICAgICAgICAgICAgICAgICAjIEZsb3lkICgxOTk5KQogICI4MDkxMDAwMDAxIiwgICAgICAgICAgICAgICAgICAgICAjIEZyYW5jZXMvR2VvcmdlcyAoMTk5OCkKICAiMjAwNDA4MjkwMSIsICAgICAgICAgICAgICAgICAgICAgIyBGcmFuY2VzICgyMDA0KQogICIyMDA0MDkwNTAyIiwgICAgICAgICAgICAgICAgICAgICAjIEl2YW4gKDIwMDQpCiAgIjIwMDQwOTE1MDEiLCAgICAgICAgICAgICAgICAgICAgICMgSmVhbm5lICgyMDA0KQogICIyMDA5MTEwOTAxIiwgICAgICAgICAgICAgICAgICAgICAjIElkYSAoMjAwOSkKICAiMjAxNjA5MjgwMiIsICAgICAgICAgICAgICAgICAgICAgIyBNYXR0aGV3ICgyMDE2KQogICIyMDE3MDgyMzAxIiwgICAgICAgICAgICAgICAgICAgICAjIEhhcnZleSAoMjAxNykKICAiMjAyMTA4MjYwMSIsICAgICAgICAgICAgICAgICAgICAgIyBJZGEgKDIwMjEpCiAgIjIwMjIwOTIyMDEiLCAgICAgICAgICAgICAgICMgSWFuIC0gU2VtaW5vbGUgVHJpYmUgKDIwMjIpCiAgIjIwMjMwODI0MDMiLCAgICAgICAgICAgICAgICAgICAgICMgSWRhbGlhICgyMDIzKQogICIyMDI0MDkyMzAxIiAgICAgICAgICAgICAgICAgICAgICAjIEhlbGVuZSAoMjAyNCkKKQoKY29tcGFyYWJsZV9zdG9ybXMgPC0gYWxsX0RSX2RhdGEgJT4lCiAgZmlsdGVyKGluY2lkZW50SWQgJWluJSBjb21wYXJhYmxlX2lkcykgJT4lCiAgZmlsdGVyKGRheXNfdG9fZGVjbGFyYXRpb24gPj0gMCkgJT4lCiAgbXV0YXRlKAogICAgc3Rvcm1fbGFiZWwgPSBjYXNlX3doZW4oCiAgICAgIGluY2lkZW50SWQgJWluJSBjKCI2OTAzNCIsICI2OTAzNSIsICI2OTA0MyIpIH4gIkNhbWlsbGUgKDE5NjkpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMTk5OTA5MTQwNyIgfiAiRmxveWQgKDE5OTkpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiODA5MTAwMDAwMSIgfiAiRnJhbmNlcy9HZW9yZ2VzICgxOTk4KSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjIwMDQwODI5MDEiIH4gIkZyYW5jZXMgKDIwMDQpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMjAwNDA5MDUwMiIgfiAiSXZhbiAoMjAwNCkiLAogICAgICBpbmNpZGVudElkID09ICIyMDA0MDkxNTAxIiB+ICJKZWFubmUgKDIwMDQpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMjAwOTExMDkwMSIgfiAiSWRhICgyMDA5KSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjIwMTYwOTI4MDIiIH4gIk1hdHRoZXcgKDIwMTYpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMjAxNzA4MjMwMSIgfiAiSGFydmV5ICgyMDE3KSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjIwMjEwODI2MDEiIH4gIklkYSAoMjAyMSkiLAogICAgICBpbmNpZGVudElkID09ICIyMDIyMDkyMjAxIiB+ICJJYW4gLSBTZW1pbm9sZSAoMjAyMikiLAogICAgICBpbmNpZGVudElkID09ICIyMDIzMDgyNDAzIiB+ICJJZGFsaWEgKDIwMjMpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMjAyNDA5MjMwMSIgfiAiSGVsZW5lICgyMDI0KSIKICAgICkKICApICU+JQogIGRpc3RpbmN0KGluY2lkZW50SWQsIGRlc2lnbmF0ZWRBcmVhLCBzdGF0ZSwgLmtlZXBfYWxsID0gVFJVRSklPiUKICBncm91cF9ieShzdG9ybV9sYWJlbCkgJT4lCiAgc3VtbWFyaXNlKAogICAgbl9jb3VudGllcyA9IG4oKSwKICAgICN0byBjb3VudCBudW1iZXIgb2YgY291bnRpZXMgJiBmaWx0ZXIgZm9yIHVuaXF1ZSBpbnN0YW5jZXMgd2l0aCBkaXN0aW5jdCB0byBwcmV2ZW50IGR1cGxpY2F0ZXMKICAgIG1pbl9sYWcgICAgPSBtaW4oZGF5c190b19kZWNsYXJhdGlvbiksCiAgICBtZWRpYW5fbGFnID0gbWVkaWFuKGRheXNfdG9fZGVjbGFyYXRpb24pLAogICAgbWF4X2xhZyAgICA9IG1heChkYXlzX3RvX2RlY2xhcmF0aW9uKSwKICAgIC5ncm91cHMgICAgPSAiZHJvcCIKICApCgpjb21wYXJhYmxlX3N0b3JtcwpgYGAKCmBgYHtyIGNvbXBhcmFibGUtcGxvdH0KI3Bsb3R0aW5nIHRob3NlIGNvbXBhcmFibGUgc3Rvcm1zCmNvbXBhcmFibGVfc3Rvcm1zICU+JQogIG11dGF0ZSh5ZWFyID0gYXMubnVtZXJpYyhzdHJfZXh0cmFjdChzdG9ybV9sYWJlbCwgIlxcZHs0fSIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihzdG9ybV9sYWJlbCwgeWVhciksIHkgPSBtZWRpYW5fbGFnKSkgKwogIGdlb21fY29sKGZpbGwgPSAic3RlZWxibHVlIiwgYWxwaGEgPSAwLjgpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobWVkaWFuX2xhZywgMCkpLCBoanVzdCA9IC0wLjIsIHNpemUgPSAzLjUpICsKICBjb29yZF9mbGlwKCkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLCAwLjE1KSkpICsKICBsYWJzKAogICAgdGl0bGUgICAgPSAiTWVkaWFuIERlY2xhcmF0aW9uIExhZyBmb3IgU3Rvcm1zIENvbXBhcmFibGUgdG8gSGVsZW5lIiwKICAgIHN1YnRpdGxlID0gIkRSIGRlY2xhcmF0aW9ucyBvbmx5OyBtZWRpYW4gYWNyb3NzIGFsbCBkZXNpZ25hdGVkIGNvdW50aWVzIiwKICAgIHggICAgICAgID0gTlVMTCwKICAgIHkgICAgICAgID0gIk1lZGlhbiBEYXlzIGZyb20gSW5jaWRlbnQgQmVnaW4gdG8gRGVjbGFyYXRpb24iCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpCmBgYAoKYGBge3IgY29tcGFyYWJsZS11bndlaWdodGVkfQojaSB3YW50ZWQgdG8gaW5jbHVkZSBzb21ldGhpbmcgdGhhdCBkaWRuJ3QgdGFrZSBpbnRvIGFjY291bnQgdGhlIG51bWJlciBvZiBjb3VudGllcyBpbiBhIHN0YXRlIGp1c3QgaW4gY2FzZSBpdCB3YXMgdXNlZnVsIHRvIGNvbXBhcmUKY29tcGFyYWJsZV9zdG9ybXNfdW53ZWlnaHRlZCA8LSBhbGxfRFJfZGF0YSAlPiUKICBmaWx0ZXIoaW5jaWRlbnRJZCAlaW4lIGNvbXBhcmFibGVfaWRzKSAlPiUKICBmaWx0ZXIoZGF5c190b19kZWNsYXJhdGlvbiA+PSAwKSAlPiUKICBtdXRhdGUoCiAgICBzdG9ybV9sYWJlbCA9IGNhc2Vfd2hlbigKICAgICAgaW5jaWRlbnRJZCAlaW4lIGMoIjY5MDM0IiwgIjY5MDM1IiwgIjY5MDQzIikgfiAiQ2FtaWxsZSAoMTk2OSkiLAogICAgICBpbmNpZGVudElkID09ICIxOTk5MDkxNDA3IiB+ICJGbG95ZCAoMTk5OSkiLAogICAgICBpbmNpZGVudElkID09ICI4MDkxMDAwMDAxIiB+ICJGcmFuY2VzL0dlb3JnZXMgKDE5OTgpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMjAwNDA4MjkwMSIgfiAiRnJhbmNlcyAoMjAwNCkiLAogICAgICBpbmNpZGVudElkID09ICIyMDA0MDkwNTAyIiB+ICJJdmFuICgyMDA0KSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjIwMDQwOTE1MDEiIH4gIkplYW5uZSAoMjAwNCkiLAogICAgICBpbmNpZGVudElkID09ICIyMDA5MTEwOTAxIiB+ICJJZGEgKDIwMDkpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMjAxNjA5MjgwMiIgfiAiTWF0dGhldyAoMjAxNikiLAogICAgICBpbmNpZGVudElkID09ICIyMDE3MDgyMzAxIiB+ICJIYXJ2ZXkgKDIwMTcpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMjAyMTA4MjYwMSIgfiAiSWRhICgyMDIxKSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjIwMjIwOTIyMDEiIH4gIklhbiAoMjAyMikiLAogICAgICBpbmNpZGVudElkID09ICIyMDIzMDgyNDAzIiB+ICJJZGFsaWEgKDIwMjMpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMjAyNDA5MjMwMSIgfiAiSGVsZW5lICgyMDI0KSIKICAgICkKICApICU+JQogIGZpbHRlcighaXMubmEoc3Rvcm1fbGFiZWwpKSAlPiUKICBncm91cF9ieShzdG9ybV9sYWJlbCkgJT4lCiAgc3VtbWFyaXNlKAogICAgbl9jb3VudGllcyA9IG4oKSwKICAgIG1lYW5fbGFnICAgPSByb3VuZChtZWFuKGRheXNfdG9fZGVjbGFyYXRpb24pLCAxKSwKICAgIC5ncm91cHMgICAgPSAiZHJvcCIKICApCmBgYAoKYGBge3IgY29tcGFyYWJsZS1wbG90LXVud2VpZ2h0ZWR9CmNvbXBhcmFibGVfc3Rvcm1zX3Vud2VpZ2h0ZWQgJT4lCiAgbXV0YXRlKHllYXIgPSBhcy5udW1lcmljKHN0cl9leHRyYWN0KHN0b3JtX2xhYmVsLCAiXFxkezR9IikpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKHN0b3JtX2xhYmVsLCB5ZWFyKSwgeSA9IG1lYW5fbGFnKSkgKwogIGdlb21fY29sKGZpbGwgPSAiZmlyZWJyaWNrIiwgYWxwaGEgPSAwLjgpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbWVhbl9sYWcpLCBoanVzdCA9IC0wLjIsIHNpemUgPSAzLjUpICsKICBjb29yZF9mbGlwKCkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMC4xNSkpKSArCiAgbGFicygKICAgIHRpdGxlICAgID0gIlVud2VpZ2h0ZWQgTWVhbiBEZWNsYXJhdGlvbiBMYWcgZm9yIFN0b3JtcyBDb21wYXJhYmxlIHRvIEhlbGVuZSIsCiAgICBzdWJ0aXRsZSA9ICJEUiBkZWNsYXJhdGlvbnMgb25seTsgc2ltcGxlIG1lYW4gYWNyb3NzIGFsbCBkZXNpZ25hdGVkIGNvdW50aWVzIOKAlCBjb21wYXJlIHdpdGggbWVkaWFuIGNoYXJ0IGFib3ZlIiwKICAgIHggICAgICAgID0gTlVMTCwKICAgIHkgICAgICAgID0gIk1lYW4gRGF5cyBmcm9tIEluY2lkZW50IEJlZ2luIHRvIERlY2xhcmF0aW9uIgogICkgKwogIHRoZW1lX21pbmltYWwoKQpgYGAKI0hhdmluZyB0cm91YmxlIGZpZ3VyaW5nIG91dCB3aHkgb25lIGlzIHNob3dpbmcgdXAgYXMgTkEuIEkgdXNlZCBjb2RlIGJlbG93IHRvIHRyeSBhbmQgZmlsdGVyIGZvciB3aGF0IHdhcyBjYXVzaW5nIHRoZSBwcm9ibGVtIGFuZCBJIGd1ZXNzIElhbiBpcyBIdXJyaWNhbmUgSWFuICsgSHVycmljYW5lIElhbiBTZW1pbm9sZSBUcmliZSBvZiBGbG9yaWRhLCBib3RoIHVuZGVyIHRoZSBzYW1lIGluY2lkZW50SUQuCgpgYGB7ciBuYX0KZGZfZmluZG5hIDwtIGFsbF9EUl9kYXRhICU+JQogIGZpbHRlcihpbmNpZGVudElkICVpbiUgY29tcGFyYWJsZV9pZHMpICU+JQogIGZpbHRlcihkYXlzX3RvX2RlY2xhcmF0aW9uID49IDApICU+JQogIG11dGF0ZSgKICAgIHN0b3JtX2xhYmVsID0gY2FzZV93aGVuKAogICAgICBpbmNpZGVudElkICVpbiUgYygiNjkwMzQiLCAiNjkwMzUiLCAiNjkwNDMiKSB+ICJDYW1pbGxlICgxOTY5KSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjE5OTkwOTE0MDciIH4gIkZsb3lkICgxOTk5KSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjgwOTEwMDAwMDEiIH4gIkZyYW5jZXMvR2VvcmdlcyAoMTk5OCkiLAogICAgICBpbmNpZGVudElkID09ICIyMDA0MDgyOTAxIiB+ICJGcmFuY2VzICgyMDA0KSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjIwMDQwOTA1MDIiIH4gIkl2YW4gKDIwMDQpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMjAwNDA5MTUwMSIgfiAiSmVhbm5lICgyMDA0KSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjIwMDkxMTA5MDEiIH4gIklkYSAoMjAwOSkiLAogICAgICBpbmNpZGVudElkID09ICIyMDE2MDkyODAyIiB+ICJNYXR0aGV3ICgyMDE2KSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjIwMTcwODIzMDEiIH4gIkhhcnZleSAoMjAxNykiLAogICAgICBpbmNpZGVudElkID09ICIyMDIxMDgyNjAxIiB+ICJJZGEgKDIwMjEpIiwKICAgICAgaW5jaWRlbnRJZCA9PSAiMjAyMzA4MjQwMyIgfiAiSWRhbGlhICgyMDIzKSIsCiAgICAgIGluY2lkZW50SWQgPT0gIjIwMjQwOTIzMDEiIH4gIkhlbGVuZSAoMjAyNCkiCiAgICApCiAgKSAlPiUKICBmaWx0ZXIoaXMubmEoc3Rvcm1fbGFiZWwpKSAlPiUKICBkaXN0aW5jdChpbmNpZGVudElkLCBkZWNsYXJhdGlvblRpdGxlKQoKYGBgCgpgYGB7ciB0cmliYWx9CnRyaWJhbF9EUiA8LSBhbGxfRFJfZGF0YSAlPiUKICBmaWx0ZXIoCiAgdHJpYmFsUmVxdWVzdCA9PSAxIHwKICBzdHJfZGV0ZWN0KHN0cl90b19sb3dlcihkZXNpZ25hdGVkQXJlYSksICJpbmRpYW4gbmF0aW9ufGluZGlhbiByZXNlcnZhdGlvbnxpbmRpYW4gdHJpYmV8YmFuZCBvZiBjaGVyb2tlZXxiYW5kIG9mIGluZGlhbnxwdWVibG98dHJpYmUgb2YiKQopJT4lCiAgZmlsdGVyKAogICAgc3RyX2RldGVjdChzdHJfdG9fbG93ZXIoZGVjbGFyYXRpb25UaXRsZSksCiAgICAgICAgICAgICAgIHBhc3RlKGNvbXBhcmFibGVfbmFtZXMsIGNvbGxhcHNlID0gInwiKSkgfCBpbmNpZGVudElkID09ICIyMDI0MDkyMzAxIgogICkgJT4lCiAgZ3JvdXBfYnkoc3RhdGUsIGRlc2lnbmF0ZWRBcmVhLCBkZWNsYXJhdGlvblRpdGxlLCBmeURlY2xhcmVkKSAlPiUKICBzdW1tYXJpc2UoCiAgICBuX2RlY2xhcmF0aW9ucyA9IG4oKSwKICAgIG1pbl9sYWcgICAgICAgID0gbWluKGRheXNfdG9fZGVjbGFyYXRpb24pLAogICAgbWVkaWFuX2xhZyAgICAgPSBtZWRpYW4oZGF5c190b19kZWNsYXJhdGlvbiksCiAgICBtYXhfbGFnICAgICAgICA9IG1heChkYXlzX3RvX2RlY2xhcmF0aW9uKSwKICAgIC5ncm91cHMgICAgICAgID0gImRyb3AiCiAgKSAlPiUKICBhcnJhbmdlKGRlc2MobWVkaWFuX2xhZykpCgp0cmliYWxfRFIKYGBgCgoKYGBge3IgdHJpYmFsLXBsb3R9CnRyaWJhbF9EUiAlPiUKICBtdXRhdGUoYXJlYV9sYWJlbCA9IHBhc3RlMChkZXNpZ25hdGVkQXJlYSwgIiAoIiwgZGVjbGFyYXRpb25UaXRsZSwgIikiKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihhcmVhX2xhYmVsLCBtZWRpYW5fbGFnKSwgeSA9IG1lZGlhbl9sYWcsIGZpbGwgPSBtZWRpYW5fbGFnKSkgKwogIGdlb21fY29sKCkgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBtZWRpYW5fbGFnKSwgaGp1c3QgPSAtMC4yLCBzaXplID0gMy41KSArCiAgY29vcmRfZmxpcCgpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdyA9ICJzdGVlbGJsdWUiLCBoaWdoID0gImZpcmVicmljayIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKDAsIDAuMTUpKSkgKwogIGxhYnMoCiAgICB0aXRsZSAgICA9ICJEZWNsYXJhdGlvbiBMYWcgZm9yIFRyaWJhbCBBcmVhcyIsCiAgICBzdWJ0aXRsZSA9ICJIZWxlbmUgKyBjb21wYXJhYmxlIHN0b3JtcyIsCiAgICB4ICAgICAgICA9IE5VTEwsCiAgICB5ICAgICAgICA9ICJNZWRpYW4gRGF5cyB0byBEZWNsYXJhdGlvbiIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gNykpCmBgYAoKYGBge3Igd3JpdGUtY3N2fQp3cml0ZS5jc3YoaGVsZW5lX3N0YXRlX3N1bW1hcnksICJoZWxlbmVfc3RhdGVfc3VtbWFyeS5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KGNvbXBhcmFibGVfc3Rvcm1zLCAiY29tcGFyYWJsZV9zdG9ybXMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCndyaXRlLmNzdihjb21wYXJhYmxlX3N0b3Jtc191bndlaWdodGVkLCAiY29tcGFyYWJsZV9zdG9ybXNfdW53ZWlnaHRlZC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KHRyaWJhbF9EUiwgInRyaWJhbF9EUi5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKYGBgCgojIyBDb25jbHVzaW9ucy9BbnN3ZXJzCgpGRU1BIHJlc3BvbnNlIGZvciBIZWxlbmUgd2FzIGFjdHVhbGx5IG5vdCB0ZXJyaWJsZSAtLSBtb3N0IGRvIG5vdCBzaG93IGEgZGVsYXkgc3VycGFzc2luZyB+MSB3ZWVrLiBJIGZlZWwgbGlrZSB0aGF0IG1heSBiZSBleHBsYWluYWJsZSBiZWNhdXNlIG9mIHdoYXQgbXkgc291cmNlIHRvbGQgbWUsIHdoaWNoIGlzIHRoYXQgZm9yIHN0YXRlLWxldmVsIGZ1bmRpbmcvcnNwb25zZSwgdGhlcmUgaXMgYSBsb3Qgb2YgcGFwZXJ3b3JrIGFuZCBidXJlYXVjcmFjeSBpbnZvbHZlZCBpbiB0aGF0IHdoaWNoIGNvdWxkIGV4cGxhaW4gZGVsYXlzLiBPciB0aGUgc3RhdGUgc2ltcGx5IHRvb2sgbG9uZ2VyIHRvIGV4cGVuZCB0aGVpciBvd24gcmVzb3VyY2VzLiBLWSBhbmQgV1YgYXJlIGJpZyBvdXRsaWVycyB3aXRoIDYwIGRheXMgYmV0d2VlbiBpbmNpZGVudCBzdGFydCBhbmQgZGVjIGRhdGUuIEV2ZXJ5IGNvdW50eSBsaXN0ZWQgaGFkIHRoZSBzYW1lIGRlbGF5ICMuCgpDb21wYXJlZCB0byBvdGhlciBzdG9ybXMsIEhlbGVuZSByZXNwb25zZSB3YXMgb24gdGhlIGZhc3RlciBlbmQsIG1vc3Qgc2ltaWxhciB0byBIdXJyaWNhbmUgTWF0dGhldyBpbiAyMDE2LiBIb3dldmVyLCBIZWxlbmUncyBtYXggZGVjbGFyYXRpb24gZGF0ZSBvZiA3NSBkYXlzIGluIFdWIGlzIHRoZSBoaWdoZXN0IG9mIGFueSBzdG9ybSBJIHNlbGVjdGVkLgoKU29tZXRoaW5nIGludGVyZXN0aW5nIHRvbyBhbmQgc29tZXRoaW5nIEknZCBsaWtlIHRvIGV4cGxvcmUgZnVydGhlciBpcyB3aHkgdHJpYmFsIHJlc2VydmF0aW9ucywgZXNwZWNpYWxseSB0aG9zZSBpbiBGTCwgZXhwZXJpZW5jZSBkZWxheXMgaW4gdGhlaXIgZGVjbGFyYXRpb25zIGluIGNvbXBhcmlzb24gdG8gdGhlIHJlc3Qgb2YgdGhlIHN0YXRlLiBUaGlzIHdhcyBhdCBpdHMgd29yc3QgZHVyaW5nIEh1cnJpY2FuZSBJZGEsIHdoaWNoIGhhZCBhIDU5IGRheSBkZWxheS4KCk92ZXJhbGwsIEkgd291bGRuJ3QgYmUgY29tZm9ydGFibGUgbWFraW5nIHRoZSBjbGFpbSB0aGF0IEZFTUEgaGFzIGFuIGluY3JlYXNpbmcgcGF0dGVybiBvZiBhIGxhY2sgb2YgZGlzYXN0ZXIgcmVzcG9uc2UuIERlbGF5cyBzZWVtIHRvIGJlIGlzb2xhdGVkIHRvIGNlcnRhaW4gc3Rvcm1zLCBhbmQgSSBzdXNwZWN0IHRoZXJlIGFyZSBtb3JlIHBvbGl0aWNhbCBmYWN0b3JzIGludm9sdmVkIHdpdGggSHVycmljYW5lIEhlbGVuZSBhbmQgRkVNQSBpc3N1ZXMgYmVoaW5kIHB1YmxpYyBvdXRjcnkgYWdhaW5zdCBGRU1BIGZvbGxvd2luZyB0aGUgZGlzYXN0ZXIuIEknZCBzYXkgbXkgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIHdhcyBhIGNvbmNyZXRlIHBhdHRlcm4gZW1lcmdpbmcgaXMgbm90IGFsbCB0aGUgd2F5IHRydWUsIGJ1dCBpdCBpcyBzb21ldGhpbmcgdGhhdCBjYW4ndCBiZSBzaW1wbGlmaWVkIHRvIGxvb2tpbmcgYXQgZGVjbGFyYXRpb24gZGF0ZXMgYWxvbmUgYmVjYXVzZSBvZiBvdGhlciBtb3ZpbmcgcGllY2VzIGluIGRpc2FzdGVyIHJlc3BvbnNlLgoK