Consistent country names

This is a perpetual nightmare in IR data. Here’s a master lookup table of COW codes, ISO3 codes, ISO2 codes, and Gleditsch Ward codes.

Gleditsch and Ward do not include a bunch of countries, so I create my own codes for relevant countries that appear in other datasets:

  • Somaliland: 521
  • Palestine (West Bank): 667
  • Palestine (Gaza): 668
  • Palestine (both): 669
  • Hong Kong: 715

Also, following Gleditsch and Ward, I treat Serbia as 340 and Serbia & Montenegro as a continuation of Yugoslavia, or 345.

Also, following V-Dem and Polity, I treat Vietnam as 816.

# Gleditsch Ward codes
#
# Download and cache data
gw.states.url <- "https://web.archive.org/web/20170302085046/http://privatewww.essex.ac.uk/~ksg/data/iisystem.dat"
gs.microstates.url <- "https://web.archive.org/web/20170302072201/http://privatewww.essex.ac.uk/~ksg/data/microstatessystem.dat"

gw.states.path <- here("Data", "data_raw", "Gleditsch Ward")

if (!file.exists(file.path(gw.states.path, basename(gw.states.url))) |
    !file.exists(file.path(gw.states.path, basename(gs.microstates.url)))) {
  GET(gw.states.url, 
      write_disk(file.path(gw.states.path, basename(gw.states.url)),
                 overwrite = TRUE))
  
  GET(gs.microstates.url, 
      write_disk(file.path(gw.states.path, basename(gs.microstates.url)),
                 overwrite = TRUE))
}

gw.date <- "%d:%m:%Y"
gw.states <- read_tsv(here("Data", "data_raw", "Gleditsch Ward", "iisystem.dat"),
                      col_names = c("gwcode", "cowc", "country.name",
                                    "date.start", "date.end"),
                      col_types = cols(
                        gwcode = col_integer(),
                        cowc = col_character(),
                        country.name = col_character(),
                        date.start = col_date(format = gw.date),
                        date.end = col_date(format = gw.date)
                      ),
                      locale = locale(encoding = "windows-1252"))

gw.microstates <- read_tsv(here("Data", "data_raw", "Gleditsch Ward", "microstatessystem.dat"),
                           col_names = c("gwcode", "cowc", "country.name",
                                         "date.start", "date.end"),
                           col_types = cols(
                             gwcode = col_integer(),
                             cowc = col_character(),
                             country.name = col_character(),
                             date.start = col_date(format = gw.date),
                             date.end = col_date(format = gw.date)
                           ),
                           locale = locale(encoding = "windows-1252"))

gw.codes <- bind_rows(gw.states, gw.microstates) %>%
  filter(date.end > ymd("2000-01-01")) %>%
  # Help out countrycode() 
  mutate(country.name = recode(country.name,
                               `Vietnam, Democratic Republic of` = "Vietnam",
                               `Yemen (Arab Republic of Yemen)` = "Yemen")) %>%
  mutate(iso3 = countrycode(country.name, "country.name", "iso3c",
                            custom_match = c(Abkhazia = NA, 
                                             `South Ossetia` = NA,
                                             Yugoslavia = "YUG",
                                             Kosovo = "XKK",
                                             `Korea, People's Republic of` = NA)),
         iso2 = countrycode(iso3, "iso3c", "iso2c",
                            custom_match = c(XKK = "XK",
                                             YUG = 345)),
         cowcode = countrycode(iso3, "iso3c", "cown",
                               custom_match = c(XKK = 347,
                                                SRB = 340,
                                                YUG = 345,
                                                VNM = 816))) %>%
  filter(!is.na(iso3)) %>%
  mutate(country.name = countrycode(iso3, "iso3c", "country.name",
                                    custom_match = c(XKK = "Kosovo",
                                                     YUG = "Yugoslavia"))) %>%
  select(country.name, iso3, iso2, gwcode, cowcode)

manual.gw <- tribble(
  ~country.name,            ~iso3,  ~iso2,   ~gwcode,  ~cowcode,
  "Somaliland",             "SOL",  NA,      521,      521,     
  "Palestine (West Bank)",  "PWB",  NA,      667,      667,     
  "Palestine (Gaza)",       "PGZ",  NA,      668,      668,     
  "Palestine",              "PSE",  "PS",    669,      669,     
  "Hong Kong",              "HKG",  "HK",    715,      715
)

gw.codes <- bind_rows(gw.codes, manual.gw) %>% 
  arrange(country.name)

gw.codes %>% datatable()

Foreign aid

OECD and AidData

The OECD collects detailed data on all foreign aid flows (ODA) from OECD member countries (and some non-member countries), mulilateral organizations, and the Bill and Melinda Gates Foundation (for some reason they’re the only nonprofit donor) to all DAC-eligible countries (and some non non-DAC-eligible countries).

The OECD tracks all this in a centralized Creditor Reporting System database and provides a nice front end for it at OECD.Stat with an open (but inscrutable) API (raw CRS data is also available). There are a set of pre-built queries with information about ODA flows by donor, recipient, and sector (purpose), but the pre-built data sources do not include all dimensions of the data. For example, Table DAC2a includes columns for donor, recipient, year, and total ODA (e.g. the US gave $X to Nigeria in 2008) , but does not indicate the purpose/sector for the ODA. Table DAC5 includes columns for the donor, sector, year, and total ODA (e.g. the US gave $X for education in 2008), but does not include recipient information.

Instead of using these pre-built queries or attempting to manipulate their parameters, it’s possible to use the OECD’s QWIDS query builder to create a custom download of data. However, it is slow and clunky and requires singificant munging and filtering after exporting.

The solution to all of this is to use data from AidData, which imports raw data from the OECD, cleans it, verifies it, and makes it freely available on GitHub.

AidData offers multiple versions of the data, including a full release, a thin release, aggregated donor/recipient/year data, and aggregated donor/recipient/year/purpose data. For the purposes of this study, all we care about are ODA flows by donor, recipient, year, and purpose, which is one of the ready-made datasets.

Notably, this aggregated data shows total aid commitments, not aid disbursements. Both types of ODA information are available from the OECD and it’s possible to get them using OECD’s raw data. However, AidData notes that disbursment data is sticky and slow—projects take a long time to fulfil and actual inflows of aid in a year can be tied to commitments made years before. Because we’re interested in donor reactions to restrictions on NGOs, any reaction would be visible in the decision to commit money to aid, not in the ultimate disbursement of aid, which is most likely already legally obligated and allocated to the country regardless of restrictions.

So, we look at ODA commitments.

aiddata.url <- "https://github.com/AidData-WM/public_datasets/releases/download/v3.1/AidDataCore_ResearchRelease_Level1_v3.1.zip"
aiddata.path <- here("Data", "data_raw", "AidData")
aiddata.zip.name <- basename(aiddata.url)
aiddata.name <- tools::file_path_sans_ext(aiddata.zip.name)

aiddata.final.name <- "AidDataCoreDonorRecipientYearPurpose_ResearchRelease_Level1_v3.1.csv"

# Download AidData data if needed
if (!file.exists(file.path(aiddata.path, aiddata.final.name))) {
  aiddata.get <- GET(aiddata.url, 
                     write_disk(file.path(aiddata.path, aiddata.zip.name),
                                overwrite = TRUE), 
                     progress())
  unzip(file.path(aiddata.path, aiddata.zip.name), exdir = aiddata.path)
  
  # Clean up zip file and unnecessary CSV files
  file.remove(file.path(aiddata.path, aiddata.zip.name))
  list.files(aiddata.path, pattern = "csv", full.names = TRUE) %>%
    map(~ ifelse(str_detect(.x, "DonorRecipientYearPurpose"), 0,
                 file.remove(file.path(.x))))
}

# Clean up AidData data
aiddata.raw <- read_csv(file.path(aiddata.path, aiddata.final.name),
                        col_types = cols(
                          donor = col_character(),
                          recipient = col_character(),
                          year = col_integer(),
                          coalesced_purpose_code = col_double(),
                          coalesced_purpose_name = col_character(),
                          commitment_amount_usd_constant_sum = col_double()
                        ))

aiddata.clean <- aiddata.raw %>%
  # Get rid of non-country recipients
  filter(!str_detect(recipient,
                     regex("regional|unspecified|multi|value|global|commission", 
                           ignore_case = TRUE))) %>%
  filter(year < 9999) %>%
  mutate(purpose.code.short = as.integer(str_sub(coalesced_purpose_code, 1, 3)))

# Donor, recipient, and purpose details
# I pulled these country names out of the dropdown menu at OECD.Stat Table 2a online
dac.donors <- c("Australia", "Austria", "Belgium", "Canada", "Czech Republic",
                "Denmark", "Finland", "France", "Germany", "Greece", "Iceland",
                "Ireland", "Italy", "Japan", "Korea", "Luxembourg", "Netherlands",
                "New Zealand", "Norway", "Poland", "Portugal", "Slovak Republic",
                "Slovenia", "Spain", "Sweden", "Switzerland", "United Kingdom",
                "United States")

non.dac.donors <- c("Bulgaria", "Croatia", "Cyprus", "Estonia", "Hungary",
                    "Israel", "Kazakhstan", "Kuwait", "Latvia", "Liechtenstein",
                    "Lithuania", "Malta", "Romania", "Russia", "Saudi Arabia",
                    "Chinese Taipei", "Thailand", "Timor Leste", "Turkey",
                    "United Arab Emirates")

other.countries <- c("Brazil", "Chile", "Colombia", "India", "Monaco", "Qatar",
                     "South Africa", "Taiwan")

donors.all <- aiddata.clean %>%
  distinct(donor) %>%
  mutate(donor.type = case_when(
    .$donor %in% c(dac.donors, non.dac.donors, other.countries) ~ "Country",
    .$donor == "Bill & Melinda Gates Foundation" ~ "Private donor",
    TRUE ~ "Multilateral or IGO"
  ))

donor.countries <- donors.all %>% 
  filter(donor.type == "Country") %>% 
  mutate(donor.cowcode = countrycode(donor, "country.name", "cown"),
         donor.iso3 = countrycode(donor, "country.name", "iso3c"))

donors <- bind_rows(filter(donors.all, donor.type != "Country"),
                    donor.countries)

recipients <- aiddata.clean %>%
  distinct(recipient) %>%
  mutate(iso3 = countrycode(recipient, "country.name", "iso3c",
                            custom_match = c(`Korea, Democratic Republic of` = NA,
                                             `Netherlands Antilles` = NA,
                                             Kosovo = "XKK",
                                             `Serbia and Montenegro` = "SCG",
                                             Yugoslavia = "YUG"
                                             ))) %>%
  left_join(gw.codes, by = "iso3") %>%
  # Get rid of tiny countries
  filter(!is.na(gwcode))

# Purposes
purposes <- aiddata.clean %>%
  count(coalesced_purpose_name, coalesced_purpose_code)

purposes.url <- "https://www.oecd.org/dac/stats/documentupload/DAC_codeLists.xml"
purpose.nodes <- read_xml(purposes.url) %>% xml_find_all("//codelist-item")

purpose.codes <- data_frame(
  code = purpose.nodes %>% xml_find_first(".//code") %>% xml_text(),
  category = purpose.nodes %>% xml_find_first(".//category") %>% xml_text(),
  name = purpose.nodes %>% xml_find_first(".//name") %>% xml_text(),
  description = purpose.nodes %>% xml_find_first(".//description") %>% xml_text()
) %>%
  mutate(code = as.integer(code))

# Extract the general categories of aid purposes (i.e. the first three digits of the purpose codes)
general.codes <- purpose.codes %>%
  filter(code %in% as.character(100:1000) & str_detect(name, "^\\d")) %>%
  mutate(code = as.integer(code)) %>%
  select(purpose.code.short = code, purpose.category.name = name) %>%
  mutate(purpose.category.clean = str_replace(purpose.category.name,
                                              "\\d\\.\\d ", "")) %>%
  separate(purpose.category.clean,
           into = c("purpose.sector", "purpose.category"), 
           sep = ", ") %>%
  mutate_at(vars(c(purpose.sector, purpose.category)), funs(str_to_title(.))) %>%
  select(-purpose.category.name)

# These 7 codes are weird and get filtered out inadvertantly
codes.not.in.oecd.list <- tribble(
  ~purpose.code.short, ~purpose.sector, ~purpose.category,
  100,                 "Social",        "Social Infrastructure",
  200,                 "Eco",           "Economic Infrastructure",
  300,                 "Prod",          "Production",
  310,                 "Prod",          "Agriculture",
  320,                 "Prod",          "Industry",
  420,                 "Multisector",   "Women in development",
  # NB: This actually is splict between 92010 (domestic NGOs), 92020
  # (international NGOs), and 92030 (local and regional NGOs)
  920,                 "Non Sector",    "Support to NGOs"
)

purpose.codes.clean <- general.codes %>%
  bind_rows(codes.not.in.oecd.list) %>%
  arrange(purpose.code.short) %>%
  mutate(purpose.contentiousness = "")

# Manually code contentiousness of purposes
write_csv(purpose.codes.clean,
          here("Data", "data_manual",
               "purpose_codes_contention_WILL_BE_OVERWRITTEN.csv"))

purpose.codes.contentiousness <- read_csv(here("Data", "data_manual",
                                               "purpose_codes_contention.csv"))

aiddata.final <- aiddata.clean %>%
  left_join(donors, by = "donor") %>%
  left_join(recipients, by = "recipient") %>%
  left_join(purpose.codes.contentiousness, by = "purpose.code.short") %>%
  mutate(donor.type.collapsed = ifelse(donor.type == "Country", "Country",
                                       "IGO, Multilateral, or Private")) %>%
  select(donor, donor.type, donor.type.collapsed,
         donor.cowcode, donor.iso3, year,
         country.name, cowcode, gwcode, iso2, iso3,
         oda = commitment_amount_usd_constant_sum,
         purpose.code.short, purpose.sector, purpose.category,
         purpose.contentiousness,
         coalesced_purpose_code, coalesced_purpose_name) %>%
  arrange(cowcode, year)

ever.dac.eligible <- read_csv(here("Data", "data_manual", 
                                   "oecd_dac_countries.csv")) %>%
  # Ignore High Income Countries and More Advanced Developing Countries
  filter(!(dac_abbr %in% c("HIC", "ADC"))) %>%
  left_join(gw.codes, by = "iso3") %>%
  select(cowcode) %>% unlist() %>% c() %>% unique()

List of donors

List of recipients

List of purposes

Summary of clean data

## Observations: 624,258
## Variables: 18
## $ donor                   <chr> "Islamic Development Bank (ISDB)", "Islamic Development Bank (ISDB)", "Islamic Deve...
## $ donor.type              <chr> "Multilateral or IGO", "Multilateral or IGO", "Multilateral or IGO", "Multilateral ...
## $ donor.type.collapsed    <chr> "IGO, Multilateral, or Private", "IGO, Multilateral, or Private", "IGO, Multilatera...
## $ donor.cowcode           <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,...
## $ donor.iso3              <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,...
## $ year                    <int> 1982, 1983, 1985, 1988, 1989, 1989, 1990, 1992, 1992, 1993, 1995, 1995, 1995, 1995,...
## $ country.name            <chr> "United States", "United States", "United States", "United States", "United States"...
## $ cowcode                 <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
## $ gwcode                  <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
## $ iso2                    <chr> "US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "US",...
## $ iso3                    <chr> "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA",...
## $ oda                     <dbl> 264104, 2657078, 2697117, 585643, 538475, 87616, 163344, 598636, 209523, 968333, 13...
## $ purpose.code.short      <int> 111, 114, 160, 111, 111, 160, 111, 111, 160, 111, 111, 112, 113, 160, 998, 111, 113...
## $ purpose.sector          <chr> "Social", "Social", "Social", "Social", "Social", "Social", "Social", "Social", "So...
## $ purpose.category        <chr> "Education", "Education", "Other", "Education", "Education", "Other", "Education", ...
## $ purpose.contentiousness <chr> "Low", "Low", "Low", "Low", "Low", "Low", "Low", "Low", "Low", "Low", "Low", "Low",...
## $ coalesced_purpose_code  <dbl> 11120, 11420, 16010, 11120, 11120, 16010, 11120, 11120, 16010, 11105, 11120, 11220,...
## $ coalesced_purpose_name  <chr> "Education facilities and training", "Higher education", "Social/ welfare services"...

USAID

USAID provides the complete dataset for its Foreign Aid Explorer as a giant CSV file. The data includes both economic and military aid, but it’s easy to filter out the military aid. Here we only look at obligations, not disbursements, so that the data is comparable to the OECD data from AidData. The data we downloaded provides constant amounts in 2015 dollars; we rescale that to 2011 to match all other variables.

usaid.url <- "https://explorer.usaid.gov/prepared/us_foreign_aid_complete.csv"
usaid.path <- here("Data", "data_raw", "USAID")
usaid.name <- basename(usaid.url)

# Download USAID data if needed
if (!file.exists(file.path(usaid.path, usaid.name))) {
  usaid.get <- GET(usaid.url, 
                   write_disk(file.path(usaid.path, usaid.name),
                              overwrite = TRUE), 
                   progress())
}

# Clean up USAID data
usaid.raw <- read_csv(file.path(usaid.path, usaid.name),
                      na = c("", "NA", "NULL"),
                      col_types = cols(
                        country_id = col_integer(),
                        country_code = col_character(),
                        country_name = col_character(),
                        region_id = col_integer(),
                        region_name = col_character(),
                        income_group_id = col_integer(),
                        income_group_name = col_character(),
                        income_group_acronym = col_character(),
                        implementing_agency_id = col_integer(),
                        implementing_agency_acronym = col_character(),
                        implementing_agency_name = col_character(),
                        implementing_subagency_id = col_integer(),
                        subagency_acronym = col_character(),
                        subagency_name = col_character(),
                        channel_category_id = col_integer(),
                        channel_category_name = col_character(),
                        channel_subcategory_id = col_integer(),
                        channel_subcategory_name = col_character(),
                        channel_id = col_integer(),
                        channel_name = col_character(),
                        dac_category_id = col_integer(),
                        dac_category_name = col_character(),
                        dac_sector_code = col_integer(),
                        dac_sector_name = col_character(),
                        dac_purpose_code = col_integer(),
                        dac_purpose_name = col_character(),
                        funding_account_id = col_character(),
                        funding_account_name = col_character(),
                        funding_agency_id = col_integer(),
                        funding_agency_name = col_character(),
                        funding_agency_acronym = col_character(),
                        assistance_category_id = col_integer(),
                        assistance_category_name = col_character(),
                        aid_type_group_id = col_integer(),
                        aid_type_group_name = col_character(),
                        activity_id = col_integer(),
                        activity_name = col_character(),
                        activity_project_number = col_character(),
                        activity_start_date = col_date(format = ""),
                        activity_end_date = col_date(format = ""),
                        transaction_type_id = col_integer(),
                        transaction_type_name = col_character(),
                        fiscal_year = col_character(),
                        current_amount = col_double(),
                        constant_amount = col_double(),
                        USG_sector_id = col_integer(),
                        USG_sector_name = col_character(),
                        submission_id = col_integer(),
                        numeric_year = col_double()
                      ))

usaid.clean <- usaid.raw %>%
  filter(assistance_category_name == "Economic") %>%
  filter(transaction_type_name == "Obligations") %>%
  mutate(country_code = recode(country_code, `CS-KM` = "XKK")) %>%
  # Remove regions and World
  filter(!str_detect(country_name, "Region")) %>%
  filter(!(country_name %in% c("World"))) %>%
  left_join(gw.codes, by = c("country_code" = "iso3")) %>%
  # Get rid of tiny and old states
  filter(!is.na(cowcode)) %>%
  select(cowcode, year = numeric_year, 
         implementing_agency_name, subagency_name, activity_name,
         channel_category_name, channel_subcategory_name, dac_sector_code,
         oda.us.current = current_amount, oda.us.2015 = constant_amount) %>%
  mutate(aid.deflator = oda.us.current / oda.us.2015 * 100) %>%
  mutate(channel.ngo.us = channel_subcategory_name == "NGO - United States",
         channel.ngo.int = channel_subcategory_name == "NGO - International",
         channel.ngo.dom = channel_subcategory_name == "NGO - Non United States")

# Get rid of this because it's huge and taking up lots of memory
rm(usaid.raw)

Implementing agencies

Here are the US government agencies giving out money:

Activities

The activities listed don’t follow any standard coding guidelines. There are tens of thousands of them. Here are the first 100, just for reference:

Channels

USAID distinguishes between domestic, foreign, and international NGOs, companies, multilateral organizations, etc. recipients (or channels) of money:

Summary of clean data

## Observations: 324,559
## Variables: 14
## $ cowcode                  <dbl> 200, 666, 666, 666, 666, 666, 666, 645, 200, 666, 666, 666, 666, 666, 666, 666, 66...
## $ year                     <dbl> 1947, 1985, 1985, 1986, 1986, 1991, 1991, 2004, 1949, 1994, 1992, 1989, 1998, 1993...
## $ implementing_agency_name <chr> "Department of the Treasury", "U.S. Agency for International Development", "U.S. A...
## $ subagency_name           <chr> "not applicable", "not applicable", "not applicable", "not applicable", "not appli...
## $ activity_name            <chr> "British Loan", "USAID Grants", "ESF", "ESF", "USAID Grants", "ESF", "USAID Grants...
## $ channel_category_name    <chr> "Government", "Government", "Government", "Government", "Government", "Government"...
## $ channel_subcategory_name <chr> "Government - United States", "Government - United States", "Government - United S...
## $ dac_sector_code          <int> 430, 430, 430, 430, 430, 430, 430, 210, 430, 430, 430, 430, 430, 430, 430, 430, 43...
## $ oda.us.current           <dbl> 3750000000, 1950050000, 1950050000, 1898400000, 1898400000, 1850000000, 1850000000...
## $ oda.us.2015              <dbl> 33891858552, 3761152948, 3761152948, 3579858613, 3579858613, 2962911687, 296291168...
## $ aid.deflator             <dbl> 11.06460, 51.84713, 51.84713, 53.03003, 53.03003, 62.43858, 62.43858, 80.55505, 12...
## $ channel.ngo.us           <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE...
## $ channel.ngo.int          <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE...
## $ channel.ngo.dom          <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE...

NGO regulations

NGO legislation

In 2013, Darin Christensen and Jeremy Weinstein collected detailed data on NGO regulations for their Journal of Democracy article. Suparna Chaudhry expanded this data as part of her dissertation research, but wants her data embargoed until some of her work is publsihed. To prevent data leakage, the code to make minor manual adjustments is included in an untracked file and not made public.

The code below will still work on the original Christensen and Weinstein data, but it will (obviously) not include Chaudhry’s expanded data.

# Original DCJW data
dcjw.orig.path <- here("Data", "data_raw", "DCJW NGO Laws", "DCJW_NGO_Laws.xlsx")

dcjw.orig <- read_excel(dcjw.orig.path)[,1:50] %>%
  select(-c(dplyr::contains("source"), dplyr::contains("burden"), 
            dplyr::contains("subset"), Coder, Date))


# Tidy DCJW data
dcjw.path <- here("Data", "data_raw", "DCJW NGO Laws", "Admn Crackdown_updated.xlsx")

dcjw.questions.raw <- read_csv(here("Data", "data_manual", "dcjw_questions.csv"))

dcjw.barriers.clean <- dcjw.questions.raw %>%
  distinct(question_cat, barrier)

dcjw.barriers.ignore <- dcjw.questions.raw %>%
  select(question, ignore_in_index)

dcjw <- read_excel(dcjw.path)[,1:50] %>%
  select(-c(dplyr::contains("source"), dplyr::contains("burden"), 
            dplyr::contains("subset"), Coder, Date)) %>%
  gather(key, value, -Country) %>%
  separate(key, c("question", "var.name"), 4) %>%
  filter(!is.na(Country)) %>%
  mutate(var.name = ifelse(var.name == "", "value", gsub("_", "", var.name))) %>%
  spread(var.name, value) %>%
  # Get rid of rows where year is missing and regulation was not imposed
  filter(!(is.na(year) & value == 0)) %>%
  # Some entries have multiple years; for now just use the first year
  mutate(year = str_split(year, ",")) %>% unnest(year) %>% 
  group_by(Country, question) %>% slice(1) %>% ungroup() %>%
  mutate(value = as.integer(value), year = as.integer(year)) %>%
  # If year is missing but some regulation exists, assume it has always already
  # existed (since 1950, arbitrarily)
  mutate(year = ifelse(is.na(year), 1950, year))

potential.dcjw.panel.question <- dcjw %>%
  tidyr::expand(Country, question, 
                year = min(.$year, na.rm = TRUE):2015)

dcjw.panel.all.laws <- dcjw %>%
  right_join(potential.dcjw.panel.question,
             by = c("Country", "question", "year"))

# Suparna Chaudry updated the original DCJW data, but wants the data embargoed 
# until some of her dissertation is published. To prevent data leakage onto the
# internet, minor manual adjustments are included in a hidden file here instead
# of this main file.
source(here("Data", "data_raw", "DCJW NGO Laws", "chaudhry_manual_changes.R"))

if (all.na.means.zero) {
  dcjw.panel.all.laws <- dcjw.panel.all.laws %>%
    group_by(Country, question) %>%
    # Bring most recent legislation forward
    mutate(value = zoo::na.locf(value, na.rm = FALSE)) %>%
    ungroup() %>%
    # Set defaults for columns that aren't all NA
    # I could be fancy and consolidate these conditionals into just one, but this
    # gives us more flexibility to set different defaults per law (like how q_2b
    # or q_4c might be better as NA_integer_ instead of 0)
    mutate(value.fixed = case_when(
      is.na(.$value) & .$question == "q_1a" ~ 0L,
      is.na(.$value) & .$question == "q_1b" ~ 0L,
      is.na(.$value) & .$question == "q_2a" ~ 0L,
      is.na(.$value) & .$question == "q_2b" ~ 0L,
      is.na(.$value) & .$question == "q_2c" ~ 0L,
      is.na(.$value) & .$question == "q_2d" ~ 0L,
      is.na(.$value) & .$question == "q_3a" ~ 0L,
      is.na(.$value) & .$question == "q_3b" ~ 0L,
      is.na(.$value) & .$question == "q_3c" ~ 0L,
      is.na(.$value) & .$question == "q_3d" ~ 0L,
      is.na(.$value) & .$question == "q_3e" ~ 0L,
      is.na(.$value) & .$question == "q_3f" ~ 0L,
      is.na(.$value) & .$question == "q_4a" ~ 0L,
      is.na(.$value) & .$question == "q_4b" ~ 0L,
      is.na(.$value) & .$question == "q_4c" ~ 0L,
      TRUE ~ .$value
    )) %>%
    select(-value) %>%
    spread(question, value.fixed) %>%
    ungroup()
} else {
  dcjw.panel.all.laws <- dcjw.panel.all.laws %>%
    group_by(Country, question) %>%
    # Bring most recent legislation forward
    mutate(value = zoo::na.locf(value, na.rm = FALSE)) %>%
    mutate(not.all.na = !all(is.na(value))) %>%
    ungroup() %>%
    # Set defaults for columns that aren't all NA
    # I could be fancy and consolidate these conditionals into just one, but this
    # gives us more flexibility to set different defaults per law (like how q_2b
    # or q_4c might be better as NA_integer_ instead of 0)
    mutate(value.fixed = case_when(
      .$not.all.na & is.na(.$value) & .$question == "q_1a" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_1b" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_2a" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_2b" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_2c" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_2d" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_3a" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_3b" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_3c" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_3d" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_3e" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_3f" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_4a" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_4b" ~ 0L,
      .$not.all.na & is.na(.$value) & .$question == "q_4c" ~ 0L,
      TRUE ~ .$value
    )) %>%
    select(-not.all.na, -value) %>%
    spread(question, value.fixed) %>%
    ungroup()
}

potential.dcjw.panel.barrier <- potential.dcjw.panel.question %>%
  mutate(question_cat = as.integer(substr(question, 3, 3))) %>%
  left_join(dcjw.barriers.clean, by = "question_cat") %>%
  distinct(Country, year, barrier)

dcjw.panel.barriers <- dcjw.panel.all.laws %>%
  gather(question, value, -Country, -year) %>%
  mutate(question_cat = as.integer(substr(question, 3, 3))) %>%
  left_join(dcjw.barriers.clean, by = "question_cat") %>%
  # Make an index for each type of barrier
  mutate(value = as.numeric(value)) %>%
  mutate(value = case_when(
    # Reverse values for associational rights
    .$question == "q_1a" & .$value == 0 ~ 1,
    .$question == "q_1a" & .$value == 1 ~ 0,
    .$question == "q_1b" & .$value == 0 ~ 1,
    .$question == "q_1b" & .$value == 1 ~ 0,
    # Reverse value for q_2c
    .$question == "q_2c" & .$value == 0 ~ 1,
    .$question == "q_2c" & .$value == 1 ~ 0,
    # Recode 0-2 questions as 0-1
    .$question == "q_3e" & .$value == 1 ~ 0.5,
    .$question == "q_3e" & .$value == 2 ~ 1,
    .$question == "q_3f" & .$value == 1 ~ 0.5,
    .$question == "q_3f" & .$value == 2 ~ 1,
    .$question == "q_4a" & .$value == 1 ~ 0.5,
    .$question == "q_4a" & .$value == 2 ~ 1,
    TRUE ~ .$value
  )) %>%
  # Ignore neutral indexes, like basic registration requirements
  left_join(dcjw.barriers.ignore, by = "question") %>%
  mutate(value_restrictive = ifelse(ignore_in_index, 0, value)) %>%
  group_by(Country, year, barrier) %>%
  # Add up all the barriers for each country year
  # Use a floor of zero to account for negative values
  summarise(all = sum(value, na.rm = TRUE),
            restrictive = sum(value_restrictive, na.rm = TRUE)) %>%
  mutate_at(vars(all, restrictive),
            funs(ifelse(. < 0, as.integer(0), .))) %>%
  # Join with full possible panel
  right_join(potential.dcjw.panel.barrier,
             by = c("Country", "barrier", "year")) %>%
  gather(temp, value, all, restrictive) %>%
  unite(temp1, barrier, temp, sep = "_") %>%
  spread(temp1, value) %>%
  ungroup() %>%
  # Take "_restrictive" out of the variable names. 
  # "entry" = all restrictive entry laws, "entry_all" = all entry laws
  rename_(.dots = setNames(paste0(unique(dcjw.questions.raw$barrier), "_restrictive"),
                           unique(dcjw.questions.raw$barrier))) %>%
  # Standardize barrier indexes by dividing by maximum number possible
  mutate_at(vars(entry, funding, advocacy),
            funs(std = . / max(.))) %>% 
  mutate(barriers.total = advocacy + entry + funding,
         barriers.total_std = advocacy_std + entry_std + funding_std)

dcjw.full <- dcjw.panel.all.laws %>%
  left_join(dcjw.panel.barriers, by = c("Country", "year")) %>%
  # Lop off the ancient observations
  filter(year > 1980) %>%
  # Rename q_* variables
  rename_(.dots = setNames(dcjw.questions.raw$question, 
                           dcjw.questions.raw$question_clean)) %>%
  # Add additional variables
  mutate(Country = countrycode(Country, "country.name", "country.name"),
         cowcode = countrycode(Country, "country.name", "cown",
                               custom_match = c(Serbia = 340,
                                                Vietnam = 816))) %>%
  select(country.name = Country, cowcode, year, everything())

Chaudhry’s data augments Christensen and Weinstein’s data substantially. Christensen and Weinstein include information for 98 countries, while Chaudhry includes 148 countries.

In addition to panel data on the presence or absence of specific NGO regulations, we create several indexes for each of the categories of regulation, following Christensen and Weinstein’s classification:

  • entry (Q2b, Q2c, Q2d; 3 points maximum, actual max = 3 points maximum): barriers to entry
    • Q2c is reversed, so not being allowed to appeal registration status earns 1 point.
    • Q2a is omitted because it’s benign
  • funding (Q3b, Q3c, Q3d, Q3e, Q3f; 5 points maximum, actual max = 4.5): barriers to funding
    • Q3a is omitted because it’s benign
    • Scores that range between 0–2 are rescaled to 0–1 (so 1 becomes 0.5)
  • advocacy (Q4a, Q4c; 2 points maximum, actual max = 2): barriers to advocacy
    • Q4b is omitted because it’s not a law
    • Scores that range between 0–2 are rescaled to 0–1 (so 1 becomes 0.5)
  • barriers.total (10 points maximum, actual max = 8.5): sum of all three indexes

These indexes are also standardized by dividing by the maximum, yielding the following variables:

  • entry_std: 1 point maximum, actual max = 1
  • funding_std: 1 point maximum, actual max = 1
  • advocacy_std: 1 point maximum, actual max = 1
  • barriers.total_std: 3 points maximum, actual max = 2.5
## Observations: 5,180
## Variables: 31
## $ country.name                   <chr> "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", "...
## $ cowcode                        <dbl> 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 700, 7...
## $ year                           <dbl> 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993...
## $ const_assoc                    <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1...
## $ political_parties              <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1...
## $ ngo_register                   <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1...
## $ ngo_register_burden            <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1...
## $ ngo_register_appeal            <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1...
## $ ngo_barrier_foreign_funds      <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1...
## $ ngo_disclose_funds             <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1...
## $ ngo_foreign_fund_approval      <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ ngo_foreign_fund_channel       <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ ngo_foreign_fund_restrict      <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ ngo_foreign_fund_prohibit      <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ ngo_type_foreign_fund_prohibit <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ ngo_politics                   <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ ngo_politics_intimidation      <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ ngo_politics_foreign_fund      <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ advocacy_all                   <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ advocacy                       <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ association_all                <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0...
## $ association                    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ entry_all                      <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3...
## $ entry                          <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2...
## $ funding_all                    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1...
## $ funding                        <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ entry_std                      <dbl> 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.3333333,...
## $ funding_std                    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ advocacy_std                   <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ barriers.total                 <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2...
## $ barriers.total_std             <dbl> 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.3333333, 0.3333333,...

Civil society regulatory environment

An alternative way of measuring civil society restrictions is to look at the overal civil society regulatory environment rather than specific laws, since de jure restrictions do not always map clearly into de facto restrictions (especially in dictatorships where the implementation of laws is more discretionary).

Andrew Heiss develops a new civil society regulatory environment index (CSRE) in his dissertation, which combines two civil society indexes from the Varieties of Democracy project (V-Dem): (1) civil society repression and (2) civil society entry and exit regulations. The CSRE ranges from roughly −6 to 6 (though typically only from −4 to 4ish), and shows more variation over time since it ostensibly captures changes in the implementation of the regulatory environment rather than the presence or absence of legislation.

While the main focus of this paper is donor response to new legislation, we also look at donor response to changes in the overall CSRE as a robustness check.

There’s no direct link for V-Dem data, since it’s behind a contact information form. So, download the 8.0 version of the “Country-Year: V-Dem + other” dataset and place it in Data/data_raw/V-Dem/v8

When loading the CSV, readr::read_csv() chokes on a bunch of rows for whatever reason and gives a ton of warnings, but it still works. Loading the Stata version of V-Dem doesn’t create the warnings, but it’s slower and it results in the same data. So we just load from CSV and make sure it has the right number of rows and columns in the end.

Civil society restrictions data

Summary of clean data

## Observations: 6,328
## Variables: 30
## $ country_name            <chr> "United States of America", "United States of America", "United States of America",...
## $ year                    <int> 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,...
## $ cowcode                 <int> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
## $ csre                    <dbl> 5.532625, 5.532625, 5.532625, 5.532625, 5.532625, 5.532625, 5.532625, 5.532625, 5.5...
## $ v2csreprss_ord          <ord> No, No, No, No, No, No, No, No, No, No, No, No, No, No, No, No, No, No, No, No, No,...
## $ v2csreprss              <dbl> 2.831333, 2.831333, 2.831333, 2.831333, 2.831333, 2.831333, 2.831333, 2.831333, 2.8...
## $ v2csreprss_codehigh     <dbl> 3.350354, 3.350354, 3.350354, 3.350354, 3.350354, 3.350354, 3.350354, 3.350354, 3.3...
## $ v2csreprss_codelow      <dbl> 1.970434, 1.970434, 1.970434, 1.970434, 1.970434, 1.970434, 1.970434, 1.970434, 1.9...
## $ v2csreprss_mean         <dbl> 4.000000, 4.000000, 4.000000, 4.000000, 4.000000, 4.000000, 4.000000, 4.000000, 4.0...
## $ v2csreprss_nr           <int> 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 15, 15, 15,...
## $ v2csreprss_ord_codehigh <int> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,...
## $ v2csreprss_ord_codelow  <int> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,...
## $ v2csreprss_osp          <dbl> 3.912476, 3.912476, 3.912476, 3.912476, 3.912476, 3.912476, 3.912476, 3.912476, 3.9...
## $ v2csreprss_osp_codehigh <dbl> 3.999951, 3.999951, 3.999951, 3.999951, 3.999951, 3.999951, 3.999951, 3.999951, 3.9...
## $ v2csreprss_osp_codelow  <dbl> 3.846990, 3.846990, 3.846990, 3.846990, 3.846990, 3.846990, 3.846990, 3.846990, 3.8...
## $ v2csreprss_osp_sd       <dbl> 0.1378864, 0.1378864, 0.1378864, 0.1378864, 0.1378864, 0.1378864, 0.1378864, 0.1378...
## $ v2csreprss_sd           <dbl> 0.6943592, 0.6943592, 0.6943592, 0.6943592, 0.6943592, 0.6943592, 0.6943592, 0.6943...
## $ v2cseeorgs              <dbl> 2.701292, 2.701292, 2.701292, 2.701292, 2.701292, 2.701292, 2.701292, 2.701292, 2.7...
## $ v2cseeorgs_codehigh     <dbl> 3.212703, 3.212703, 3.212703, 3.212703, 3.212703, 3.212703, 3.212703, 3.212703, 3.2...
## $ v2cseeorgs_codelow      <dbl> 2.277519, 2.277519, 2.277519, 2.277519, 2.277519, 2.277519, 2.277519, 2.277519, 2.2...
## $ v2cseeorgs_mean         <dbl> 3.625000, 3.625000, 3.625000, 3.625000, 3.625000, 3.625000, 3.625000, 3.625000, 3.6...
## $ v2cseeorgs_nr           <int> 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 15, 15, 15,...
## $ v2cseeorgs_ord          <int> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,...
## $ v2cseeorgs_ord_codehigh <int> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,...
## $ v2cseeorgs_ord_codelow  <int> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,...
## $ v2cseeorgs_osp          <dbl> 3.780493, 3.780493, 3.780493, 3.780493, 3.780493, 3.780493, 3.780493, 3.780493, 3.7...
## $ v2cseeorgs_osp_codehigh <dbl> 3.955077, 3.955077, 3.955077, 3.955077, 3.955077, 3.955077, 3.955077, 3.955077, 3.9...
## $ v2cseeorgs_osp_codelow  <dbl> 3.671487, 3.671487, 3.671487, 3.671487, 3.671487, 3.671487, 3.671487, 3.671487, 3.6...
## $ v2cseeorgs_osp_sd       <dbl> 0.16074768, 0.16074768, 0.16074768, 0.16074768, 0.16074768, 0.16074768, 0.16074768,...
## $ v2cseeorgs_sd           <dbl> 0.4812464, 0.4812464, 0.4812464, 0.4812464, 0.4812464, 0.4812464, 0.4812464, 0.4812...

Neighboring states

Calculate three types of distance between all countries with the CShapes R package: mimimum distance, capital distance, and centroid distance. Because this takes a really long time, it’s best to run Data/get_distances.R separately elsewhere first (like on a VPS) and then save the resulting .rds files in Data/data_raw/Country Distances.

The all.distances data frame below contains all three distance types between every country and every other country in 2012 (though it could potentially include distances from 1991–2015). This is used later to weight variables by distance. It also includes an indicator variable called is.rough.neighbor that is true if the two countries are less than 900 km apart, which captures neighbor relationships better than simple contiguous borders.

distance.folder <- here("Data", "data_raw", "Country distances")

read_distances <- function(type, year) {
  stopifnot(year >= 1980, year <= 2015)
  stopifnot(type %in% c("capital", "cent", "min"))
  
  # Read in the RDS file for the type and year
  matrix.raw <- readRDS(file.path(distance.folder,
                                  paste0(type, "_", year, "-01-01.rds")))
  
  # Convert distance matrix to long dataframe
  df.clean <- as.data.frame(matrix.raw) %>%
    mutate(gwcode = rownames(.)) %>%
    gather(gwcode.other, distance, -gwcode) %>%
    # Set inverted diagonal 0s to 0, real 0s to 1
    mutate(distance.inv = ifelse(gwcode == gwcode.other & distance == 0, 0,
                                 ifelse(gwcode != gwcode.other & distance == 0, 1,
                                        1 / distance))) %>%
    mutate(type = type, year = year) %>%
    mutate_at(vars(starts_with("gwcode")), funs(as.numeric)) %>%
    # Mark if country is within 900 km
    mutate(is.rough.neighbor = distance < 900) %>%
    # Standardize inverted distances so that all rows within a country add to 1
    # so that it can be used in weighted.mean.
    # This is the same as calculating the row sum of the matrix
    group_by(gwcode) %>%
    mutate(distance.std = distance.inv / sum(distance.inv)) %>%
    ungroup() %>%
    left_join(gw.codes, by = "gwcode") %>%
    left_join(gw.codes, by = c("gwcode.other" = "gwcode"),
              suffix = c(".self", ".other"))
  
  return(df.clean)
}

# Load and combine minimum distance matrices for all years (could potentially
# also do "cent" or "capital")
all.distances <- expand.grid(year = 1980:2015,
                             type = "min",
                             stringsAsFactors = FALSE) %>%
  mutate(distances = map2(type, year, ~ read_distances(.x, .y))) %>% 
  unnest(distances)

all.distances %>% glimpse()
## Observations: 1,226,302
## Variables: 18
## $ year               <int> 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980...
## $ type               <chr> "min", "min", "min", "min", "min", "min", "min", "min", "min", "min", "min", "min", "min...
## $ gwcode             <dbl> 2, 20, 31, 40, 41, 42, 51, 52, 53, 54, 55, 56, 57, 70, 90, 91, 92, 93, 94, 95, 100, 101,...
## $ gwcode.other       <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2...
## $ distance           <dbl> 0.0000, 0.0000, 105.6785, 233.2897, 931.8133, 1070.4367, 782.9170, 2544.8651, 2540.5566,...
## $ distance.inv       <dbl> 0.0000000000, 1.0000000000, 0.0094626606, 0.0042865160, 0.0010731763, 0.0009341982, 0.00...
## $ type1              <chr> "min", "min", "min", "min", "min", "min", "min", "min", "min", "min", "min", "min", "min...
## $ year1              <int> 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980, 1980...
## $ is.rough.neighbor  <lgl> TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TR...
## $ distance.std       <dbl> 0.000000e+00, 9.684943e-01, 1.424432e-01, 5.810121e-02, 1.014570e-03, 8.934232e-04, 2.57...
## $ country.name.self  <chr> "United States", "Canada", "Bahamas", "Cuba", "Haiti", "Dominican Republic", "Jamaica", ...
## $ iso3.self          <chr> "USA", "CAN", "BHS", "CUB", "HTI", "DOM", "JAM", "TTO", "BRB", "DMA", "GRD", "LCA", "VCT...
## $ iso2.self          <chr> "US", "CA", "BS", "CU", "HT", "DO", "JM", "TT", "BB", "DM", "GD", "LC", "VC", "MX", "GT"...
## $ cowcode.self       <dbl> 2, 20, 31, 40, 41, 42, 51, 52, 53, 54, 55, 56, 57, 70, 90, 91, 92, 93, 94, 95, 100, 101,...
## $ country.name.other <chr> "United States", "United States", "United States", "United States", "United States", "Un...
## $ iso3.other         <chr> "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA", "USA...
## $ iso2.other         <chr> "US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "US", "US"...
## $ cowcode.other      <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2...

Other controls and alternative hypotheses

There are a bunch of reasons why overall aid flows might change over time. We controle for these alternative hypotheses:

  • Regime type: donors likely give less aid to democracies
  • Polity IV: polity (imputed 0-10 Polity score from V-Dem, originally e_fh_ipolity2)
  • Wealth: donors likely give less aid to richer countries
  • GDP per capita: gdp.capita (GDP per capita (constant 2011 USD) from WDI)
  • Trade as % of GDP: trade.pct.gdp (from WDI)
  • Aid dependency: aid.pct.gdp (Constant 2011 ODA as percent of constant 2011 GDP from AidData and WDI)
  • Government capacity: donors likely give more aid to NGOs in countries with weak institutions (and perhaps less aid overall?)
  • Corruption: corruption (0-10 scale from V-Dem: public sector + executive + + legislative + judicial corruption, originally v2x_corr on 0-1)
  • BAD VARIABLE, almost 50% missing; sadface Quality of governance: govt.effectiveness (≈-2 to 2 scale from V-Dem and WBGI, originally e_wbgi_gee)
  • Bad stuff: donors likely give more aid to countries when bad things happen like wars and natural disasters
  • Internal conflict: internal.conflict.past.5 (binary indicator variable if there was a conflict in that year or in the previous 5 years from UCDP/PRIO)
  • Disasters: natural_disaster.affected, natural_disaster.deaths, natural_disaster.occurrence, and natural_disaster.total.affected, among others (from EM-DAT)

World Bank and UN development indicators

The World Bank has a fantastic API for their statistical indicators and there’s already a nice R package for accessing it, so downloading indicators is trivial. For the sake of our models, we care about GDP per capita as a proxy for a country’s overall development. We also collect a few other relevant variables just for fun.

UN population

## Observations: 12,804
## Variables: 3
## $ cowcode       <dbl> 516, 581, 522, 531, 530, 501, 580, 553, 590, 541, 517, 591, 520, 626, 500, 510, 551, 552, 540...
## $ year          <int> 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 1950, 195...
## $ un.population <dbl> 2308923, 156334, 62001, 1142150, 18128034, 6076757, 4083554, 2953871, 493254, 6313290, 218618...

UN GDP

un.gdp <- bind_rows(un.gdp.raw, un.gdp.current.raw) %>%
  filter(Item %in% c("Gross Domestic Product (GDP)",
                     "Exports of goods and services",
                     "Imports of goods and services")) %>%
  left_join(un.codes, by = "un_code") %>%
  # Fix weird edge cases with country names
  # Get rid of Former Netherlands Antilles, Zanzibar, Former Czechoslovakia,
  # Former Yugoslavia, and Former USSR
  filter(!(un_code %in% c(530, 836, 200, 890, 810))) %>%
  # Add code for Kosovo, Tanzania, and Sudan
  mutate(iso3 = ifelse(un_code == 412, "XKK", iso3),
         iso3 = ifelse(un_code == 835, "TZA", iso3),
         iso3 = ifelse(un_code == 736, "SDN", iso3))

# Combine the two Yemens, then keep one of the values in the two overlapping years
un.gdp.yemen <- un.gdp %>%
  filter(un_code %in% c(720, 886)) %>%
  group_by(value.type, Item, Year) %>%
  mutate(Value.combined = sum(Value)) %>%
  ungroup() %>%
  filter(un_code == 720) %>%
  mutate(iso3 = "YEM") %>%
  select(-Value) %>% select(Value = Value.combined, everything()) %>%
  bind_rows(filter(un.gdp, un_code == 887)) %>%
  group_by(value.type, Item, Year) %>%
  slice(1) %>% ungroup()

# Keep one of the Ethiopias' GDP, since they overlap for a few years
un.gdp.ethiopia <- un.gdp %>%
  filter(un_code %in% c(230, 231)) %>%
  group_by(value.type, Item, Year) %>%
  # mutate(Value.combined = mean(Value)) %>%
  slice(1) %>% ungroup() %>%
  mutate(iso3 = "ETH")

un.gdp.clean <- un.gdp %>%
  # Remove Yemens and Ethiopias
  filter(!(un_code %in% c(720, 886, 230, 231))) %>%
  # Add consolidated Yemens and Ethiopias
  bind_rows(un.gdp.yemen) %>%
  bind_rows(un.gdp.ethiopia) %>%
  left_join(gw.codes, by = "iso3") %>%
  # Get rid of tiny places
  filter(!is.na(cowcode))

un.gdp.wide <- un.gdp.clean %>%
  select(cowcode, year = Year, Item, Value, value.type) %>%
  unite(temp, value.type, Item) %>%
  # Temporary id column for spreading correctly
  group_by(temp) %>% mutate(id = 1:n()) %>%
  spread(temp, Value) %>% select(-id) %>% ungroup() %>%
  rename(exports.constant.2005 = `Constant_Exports of goods and services`,
         imports.constant.2005 = `Constant_Imports of goods and services`,
         gdp.constant.2005 = `Constant_Gross Domestic Product (GDP)`,
         exports.current = `Current_Exports of goods and services`,
         imports.current = `Current_Imports of goods and services`,
         gdp.current = `Current_Gross Domestic Product (GDP)`) %>%
  mutate(gdp.deflator = gdp.current / gdp.constant.2005 * 100)

# Rescale the 2005 data to 2011 to match AidData
#
# Deflator = current GDP / constant GDP * 100
# Current GDP in year_t * (deflator in year_target / deflator in year_t)
un.gdp.rescaled <- un.gdp.wide %>%
  left_join(select(filter(un.gdp.wide, year == 2011),
                   cowcode, deflator.target.year = gdp.deflator),
            by = "cowcode") %>%
  mutate(un.gdp = gdp.current * (deflator.target.year / gdp.deflator),
         un.trade.pct.gdp = (imports.current + exports.current) / gdp.current)

un.gdp.final <- un.gdp.rescaled %>%
  select(cowcode, year, un.trade.pct.gdp, un.gdp) %>%
  group_by(cowcode, year) %>%
  slice(1) %>% ungroup()

un.gdp.final %>% head(50) %>% datatable(extensions = "Responsive")
## Observations: 8,217
## Variables: 4
## $ cowcode          <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...
## $ year             <int> 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, ...
## $ un.trade.pct.gdp <dbl> 0.1073520, 0.1072958, 0.1130692, 0.1305565, 0.1641271, 0.1547753, 0.1600980, 0.1638063, 0....
## $ un.gdp           <dbl> 4873912132562, 5034354414646, 5298624445277, 5597607036617, 5568679902693, 5557625605087, ...

World Bank indicators

wdi.indicators <- c("NY.GDP.PCAP.KD",        # GDP per capita (constant 2010 USD)
                    "NY.GDP.MKTP.CD",        # GDP (current dollars)
                    "NY.GDP.MKTP.KD",        # GDP (constant 2010 USD)
                    "SP.POP.TOTL",           # Population, total
                    "NE.TRD.GNFS.ZS")        # Trade as % of GDP

wdi.path <- here("data", "data_cache", "wdi.rds")

if (!file.exists(wdi.path)) {
  # Get all countries and regions because the World Bank chokes on ISO codes like
  # XK for Kosovo, even though it returns data for Kosovo with the XK code
  # ¯\_(ツ)_/¯
  wdi.raw <- WDI(country = "all", wdi.indicators,
                 extra = FALSE, start = 1980, end = 2015)
  
  saveRDS(wdi.raw, wdi.path)
} else {
  wdi.raw <- readRDS(wdi.path)
}

# Filter countries here instead
wdi.clean.intermediate <- wdi.raw %>%
  filter(iso2c %in% unique(gw.codes$iso2)) %>%
  arrange(iso2c, year) %>%
  rename(gdp.capita.2010 = NY.GDP.PCAP.KD, 
         gdp.2010 = NY.GDP.MKTP.KD, gdp.current = NY.GDP.MKTP.CD,
         population = SP.POP.TOTL, trade.pct.gdp = NE.TRD.GNFS.ZS) %>%
  mutate(gdp.deflator = gdp.current / gdp.2010 * 100)

# Rescale the 2010 data to 2011 to match AidData
#
# Deflator = current GDP / constant GDP * 100
# Current GDP in year_t * (deflator in year_target / deflator in year_t)
wdi.rescaled <- wdi.clean.intermediate %>%
  left_join(select(filter(wdi.clean.intermediate, year == 2011), 
                   iso2c, deflator.target.year = gdp.deflator), 
            by = "iso2c") %>%
  mutate(gdp = gdp.current * (deflator.target.year / gdp.deflator))

wdi.clean <- wdi.rescaled %>%
  left_join(select(gw.codes, iso2, cowcode), by = c("iso2c" = "iso2")) %>%
  select(-c(gdp.capita.2010, gdp.current, gdp.2010, 
            gdp.deflator, deflator.target.year))

wdi.clean %>% head(100) %>% datatable(extensions = "Responsive")
## Observations: 7,020
## Variables: 7
## $ iso2c         <chr> "AD", "AD", "AD", "AD", "AD", "AD", "AD", "AD", "AD", "AD", "AD", "AD", "AD", "AD", "AD", "AD...
## $ country       <chr> "Andorra", "Andorra", "Andorra", "Andorra", "Andorra", "Andorra", "Andorra", "Andorra", "Ando...
## $ year          <dbl> 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 199...
## $ population    <dbl> 36067, 37500, 39114, 40867, 42706, 44600, 46517, 48455, 50434, 52448, 54509, 56671, 58888, 60...
## $ trade.pct.gdp <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ gdp           <dbl> 1571153915, 1569072537, 1588630416, 1616751054, 1645604995, 1683806613, 1738586260, 183502776...
## $ cowcode       <dbl> 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232...

Former colonial status

Paul Hensel has collected data on each country’s former colonial status, indicating both a given country’s primary colonial ruler and the last colonial ruler prior to independence. The dataset also includes an estimated date of independence.

Colonial status could matter for aid, with donor countries favoring former colonies (i.e. France might be more likely to donate to former African colonies; Spain might be more likely to donate to Latin America; etc.)

Because there are so many columns, the data below has been horizontally collapsed—click on the green plus sign to see the rest of the data in a row.

col.url <- "http://www.paulhensel.org/Data/colhist.zip"
col.path <- here("Data", "data_raw")
col.zip.name <- basename(col.url)
col.name <- tools::file_path_sans_ext(col.zip.name)

col.final.name <- "coldata100.csv"
col.full.path <- file.path(col.path, "ICOW Colonial History 1.0", 
                           col.final.name)

# Download ICOW data if needed
if (!file.exists(col.full.path)) {
  col.get <- GET(col.url, 
                 write_disk(file.path(col.path, col.zip.name),
                            overwrite = TRUE), 
                 progress())
  unzip(file.path(col.path, col.zip.name), exdir = col.path)
  
  file.remove(file.path(col.path, col.zip.name))
}

col.raw <- read_csv(col.full.path, na = "-9",
                    col_types = cols(
                      State = col_integer(),
                      Name = col_character(),
                      ColRuler = col_integer(),
                      IndFrom = col_integer(),
                      IndDate = col_integer(),
                      IndViol = col_integer(),
                      IndType = col_integer(),
                      SecFrom = col_integer(),
                      SecDate = col_integer(),
                      SecViol = col_integer(),
                      Into = col_integer(),
                      IntoDate = col_integer(),
                      COWsys = col_integer(),
                      GWsys = col_integer(),
                      Notes = col_character()
                    )) 

col.clean <- col.raw %>%
  # Independence dates with unknown months are coded as 00, which makes
  # lubridate choke. So change those to 01
  mutate(IndDate.clean = str_replace(IndDate, "00$", "01")) %>%
  # Years less than 1000 make lubridate choke, so preface them with a 0
  mutate(IndDate.clean = ifelse(nchar(IndDate.clean) == 5, 
                                paste0(0, IndDate.clean), IndDate.clean)) %>%
  mutate(IndDate = ymd(paste0(IndDate.clean, "01"))) %>%
  left_join(select(gw.codes, iso3, cowcode, country.name),
            by = c("State" = "cowcode")) %>%
  left_join(select(gw.codes, col.ruler.cowcode = cowcode, 
                   col.ruler.iso3 = iso3, 
                   col.ruler.country.name = country.name),
            by = c("ColRuler" = "col.ruler.cowcode")) %>%
  left_join(select(gw.codes, ind.from.cowcode = cowcode,
                   ind.from.iso3 = iso3, 
                   ind.from.country.name = country.name),
            by = c("IndFrom" = "ind.from.cowcode")) %>%
  select(cowcode = State, country.name, col.ind.date = IndDate,
         col.ruler.country.name, col.ruler.cowcode = ColRuler, col.ruler.iso3,
         ind.from.country.name, ind.from.cowcode = IndFrom, ind.from.iso3) %>%
  # Get rid of smaller ancient states like Tuscany, Parma, and Zanzibar
  filter(!is.na(country.name)) %>%
  # Add country names and ISO codes for ancient places
  mutate(col.ruler.country.name = ifelse(col.ruler.cowcode == 300, 
                                         "Austria-Hungary",
                                         col.ruler.country.name),
         col.ruler.iso3 = ifelse(col.ruler.cowcode == 300, 
                                 "AUH",
                                 col.ruler.country.name)) %>%
  mutate(ind.from.country.name = case_when(
    .$ind.from.cowcode == 89 ~ "United Provinces of Central America",
    .$ind.from.cowcode == 300 ~ "Austria-Hungary",
    .$ind.from.cowcode == 315 ~ "Czechoslovakia",
    .$ind.from.cowcode == 678 ~ "Yemen (Arab Republic of Yemen)",
    .$ind.from.cowcode == 730 ~ "Korea",
    is.na(.$ind.from.cowcode) ~ NA_character_,
    TRUE ~ .$ind.from.country.name
  )) %>%
  mutate(ind.from.iso3 = case_when(
    .$ind.from.cowcode == 89 ~ "UPC",
    .$ind.from.cowcode == 300 ~ "AUH",
    .$ind.from.cowcode == 315 ~ "CZE",
    .$ind.from.cowcode == 678 ~ "YEM",
    .$ind.from.cowcode == 730 ~ "KOR",
    is.na(.$ind.from.cowcode) ~ NA_character_,
    TRUE ~ .$ind.from.iso3
  )) %>%
  # Mark never modernly colonzied countries as such instead of missing
  mutate(col.ruler.country.name = ifelse(is.na(col.ruler.cowcode), 
                                         "Not recently colonized",
                                         col.ruler.country.name),
         col.ruler.iso3 = ifelse(is.na(col.ruler.cowcode),
                                 "ZZZ", col.ruler.iso3),
         col.ruler.cowcode = ifelse(is.na(col.ruler.cowcode), 
                                    999, col.ruler.cowcode),
         ind.from.country.name = ifelse(is.na(ind.from.cowcode), 
                                        "Already independent",
                                        ind.from.country.name),
         ind.from.iso3 = ifelse(is.na(ind.from.cowcode),
                                "ZZZ", ind.from.iso3),
         ind.from.cowcode = ifelse(is.na(ind.from.cowcode), 
                                   999, ind.from.cowcode)) %>%
  # Serbia isn't included in the colonial ruler data because it's combined with
  # Yugoslavia and Montenegro. So here we duplicate the "Croatia" row for
  # Serbia to pick up the colonial relationship (even though it's technically
  # not 100% correct)
  bind_rows(filter(., cowcode == 344) %>% 
              mutate(cowcode = 340, country.name = "Serbia"))

Colonial status data

Summary of clean data

## Observations: 195
## Variables: 9
## $ cowcode                <dbl> 2, 20, 31, 40, 41, 42, 51, 52, 53, 54, 55, 56, 57, 58, 60, 70, 80, 90, 91, 92, 93, 9...
## $ country.name           <chr> "United States", "Canada", "Bahamas", "Cuba", "Haiti", "Dominican Republic", "Jamaic...
## $ col.ind.date           <date> 1783-09-01, 1867-07-01, 1973-07-01, 1902-05-01, 1804-01-01, 1844-02-01, 1962-08-01,...
## $ col.ruler.country.name <chr> "United Kingdom", "United Kingdom", "United Kingdom", "Spain", "France", "Spain", "U...
## $ col.ruler.cowcode      <dbl> 200, 200, 200, 230, 220, 230, 200, 200, 200, 200, 200, 200, 200, 200, 200, 230, 200,...
## $ col.ruler.iso3         <chr> "United Kingdom", "United Kingdom", "United Kingdom", "Spain", "France", "Spain", "U...
## $ ind.from.country.name  <chr> "United Kingdom", "United Kingdom", "United Kingdom", "United States", "France", "Ha...
## $ ind.from.cowcode       <dbl> 200, 200, 200, 2, 220, 41, 200, 200, 200, 200, 200, 200, 200, 200, 200, 230, 200, 89...
## $ ind.from.iso3          <chr> "GBR", "GBR", "GBR", "USA", "FRA", "HTI", "GBR", "GBR", "GBR", "GBR", "GBR", "GBR", ...

Conflict

The UCDP/PRIO Armed Conflict Dataset tracks a ton of conflict-releated data, including reasons for the conflict, parties in the conflict, intensity of the conflict, and deaths in the conflict. We’re only interested in whether a conflict happened in a given year (or in the past 5 years), so here we simply create an indicator variable for whether there was internal conflict in a country-year (conflict type = 3).

## Observations: 1,203
## Variables: 7
## $ gwcode            <dbl> 40, 40, 40, 40, 41, 41, 41, 42, 52, 70, 70, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 9...
## $ Year              <int> 1953, 1956, 1957, 1958, 1989, 1991, 2004, 1965, 1990, 1994, 1996, 1949, 1954, 1963, 1965,...
## $ conflict.internal <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,...
## $ country.name      <chr> "Cuba", "Cuba", "Cuba", "Cuba", "Haiti", "Haiti", "Haiti", "Dominican Republic", "Trinida...
## $ iso3              <chr> "CUB", "CUB", "CUB", "CUB", "HTI", "HTI", "HTI", "DOM", "TTO", "MEX", "MEX", "GTM", "GTM"...
## $ iso2              <chr> "CU", "CU", "CU", "CU", "HT", "HT", "HT", "DO", "TT", "MX", "MX", "GT", "GT", "GT", "GT",...
## $ cowcode           <dbl> 40, 40, 40, 40, 41, 41, 41, 42, 52, 70, 70, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 9...

Natural disasters

Natural disaster data comes from the International Disaster Database (EM-DAT). The data includes the number of deaths, injuries, homeless displacements, and monetary losses (in 2000 dollars) for a huge number of natural and technological disasters (see EM-DAT’s full classification).

Natural disasters could matter for aid too, since donor countries might increase their aid to countries suffering more.

EM-DAT does not provide a single link to download their data. Instead, you have to create a query using their advanced search form. We downloaded data using the following query:

  • Select all countries from up to 2016
  • Select all three disaster classification groups (natural, technological, complex)
  • Group results by country name, year, and disaster type
  • Download CSV and save in Data/data_raw/Disasters/Data.csv
# Disaster classification
disaster.classification.raw <- "https://web.archive.org/web/20161203165345/http://www.emdat.be/classification" %>%
  read_html() %>%
  html_nodes(., xpath = '//*[@id="article-14627"]/div/div/div/div/table[1]') %>%
  html_table(header = TRUE)

# For whatever reason, the downloaded data treats technological subgroups as
# main types (e.g. "industrial accident" is listed as a disaster type, not
# "chemical spill" or "fire" or whatever). So, make a new column of the actual
# disaster type using the real type for natural disasters and the subgroup for
# non-natural disasters.
#
# Also, add a couple rows for complex and miscellaneous disasters
disaster.classification <- disaster.classification.raw[[1]] %>%
  select(-Definition) %>%
  mutate_all(funs(str_trim(str_to_lower(.)))) %>%
  # Fix typo
  mutate(`Disaster Subgroup` = ifelse(`Disaster Subgroup` == "miscelleanous accident",
                                      "miscellaneous accident", `Disaster Subgroup`)) %>%
  mutate(`Actual Type` = ifelse(`Disaster Group` == "natural", 
                                `Disaster Main Type`, `Disaster Subgroup`)) %>%
  distinct(`Disaster Group`, `Disaster Subgroup`, `Actual Type`) %>%
  bind_rows(tribble(
    ~`Disaster Group`, ~`Disaster Subgroup`, ~`Actual Type`,
    "complex",         "complex disasters",  "complex disasters"
  ))

# Disaster data
# http://www.emdat.be/advanced_search/index.html

# Select all countries from whenever to 2016
# Select all three disaster classification groups (natural, technological, complex)
# Group results by country name, year, and disaster type
# Download CSV and save in Data/data_raw/Disasters

disasters.raw <- read_csv(here("Data", "data_raw", "Disasters", "data.csv"),
                          skip = 1)  # First row is junk

# Read in disaster data and join with classification data
disasters <- disasters.raw %>%
  mutate(`disaster type` = str_trim(str_to_lower(`disaster type`))) %>%
  mutate(`disaster type` = ifelse(`disaster type` == "mass movement (dry)",
                                  "mass movement", `disaster type`)) %>%
  left_join(disaster.classification, by = c("disaster type" = "Actual Type")) %>%
  # Get rid of tiny countries
  filter(!(iso %in% c("AIA", "ANT", "ASM", "AZO", "BMU", "COK", "CSK", "CYM", 
                      "DDR", "GLP", "GUF", "GUM", "MAC", "MNP", "MSR", "MTQ", 
                      "MYT", "NCL", "NIU", "PRI", "PYF", "REU", "SHN", "SPI", 
                      "TCA", "TKL", "VGB", "VIR", "WLF", "YMD"))) %>% 
  mutate(iso = str_to_upper(iso), 
         cowcode = countrycode(iso, "iso3c", "cown",
                               custom_match = c(HKG = 715, DFR = 255, PSE = 669,
                                                SUN = 365, YMN = 679, SRB = 340,
                                                SCG = 345, YUG = 345))) %>%
  # Fix missing names (collapsing old Germanies, Yemens, and USSR)
  mutate(country_name = countrycode(iso, "iso3c", "country.name",
                                    custom_match = c(DFR = "Germany",
                                                     SCG = "Yugoslavia",
                                                     YUG = "Yugoslavia",
                                                     SUN = "Russia",
                                                     YMN = "Yemen"))) %>%
  # Fix ISOs
  mutate(iso = countrycode(country_name, "country.name", "iso3c",
                           custom_match = c(Yugoslavia = "YUG"))) %>%
  select(country_name, year, iso3 = iso, cowcode, disaster.type = `disaster type`, 
         disaster.group = `Disaster Group`, disaster.subgroup = `Disaster Subgroup`,
         disaster.occurrence = occurrence, disaster.deaths = `Total deaths`,
         disaster.injured = `Injured`, disaster.affected = `Affected`,
         disaster.homeless = `Homeless`, disaster.total.affected = `Total affected`,
         disaster.total.damage = `Total damage`) %>%
  filter(disaster.group != "complex")

Clean disaster data

Summary of clean data

## Observations: 4,086
## Variables: 16
## $ cowcode                               <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, ...
## $ year                                  <int> 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 199...
## $ natural_disaster.affected             <int> 0, 36000, 1500, 14000, 1005550, 2150, 5400, 0, 300, 14188, 2900, 4545...
## $ natural_disaster.deaths               <int> 60, 514, 332, 1145, 375, 62, 239, 27, 259, 214, 132, 96, 542, 275, 87...
## $ natural_disaster.homeless             <int> 0, 15500, 6000, 5500, 20000, 0, 0, 0, 25015, 0, 300, 250540, 300, 210...
## $ natural_disaster.injured              <int> 0, 0, 53, 657, 500, 109, 94, 0, 3857, 30, 200, 481, 430, 7522, 160, 1...
## $ natural_disaster.occurrence           <int> 4, 13, 12, 14, 15, 7, 11, 22, 19, 24, 36, 32, 30, 16, 18, 15, 33, 32,...
## $ natural_disaster.total.affected       <int> 0, 51500, 7553, 20157, 1026050, 2259, 5494, 0, 29172, 14218, 3400, 29...
## $ natural_disaster.total.damage         <int> 861000, 2145900, 5107250, 2287600, 5094100, 1845720, 421000, 0, 13480...
## $ technological_disaster.affected       <int> 0, 23000, 2000, 0, 0, 0, 24000, 0, 0, 185, 16000, 0, 0, 9230, 200, 12...
## $ technological_disaster.deaths         <int> 26, 153, 0, 0, 12, 138, 296, 58, 344, 216, 170, 59, 172, 271, 41, 404...
## $ technological_disaster.homeless       <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 300, 0, 0, 0, 0, 0, 120, 0, 20...
## $ technological_disaster.injured        <int> 240, 355, 43, 396, 265, 0, 6, 0, 185, 336, 251, 24, 3156, 649, 485, 4...
## $ technological_disaster.occurrence     <int> 3, 5, 1, 3, 3, 3, 10, 4, 16, 8, 10, 3, 7, 13, 7, 10, 6, 9, 12, 7, 9, ...
## $ technological_disaster.total.affected <int> 240, 23355, 2043, 396, 265, 0, 24006, 0, 185, 521, 16251, 24, 3156, 1...
## $ technological_disaster.total.damage   <int> 0, 0, 0, 0, 0, 0, 0, 0, 1100000, 220000, 14500, 0, 0, 33000, 0, 35100...

Countries to exclude

We exclude long-term consolidated democracies from our analysis, following FinkelPerez-LinanSeligson:2007, 414. These are classified by the World Bank as high income; they score below 3 on Freedom House’s Scale, receive no aid from USAID, and are not newly independent states.

country.name iso3 cowcode
Andorra AND 232
Australia AUS 900
Austria AUT 305
Bahamas BHS 31
Barbados BRB 53
Belgium BEL 211
Canada CAN 20
Denmark DNK 390
Finland FIN 375
France FRA 220
Germany DEU 255
Greece GRC 350
Grenada GRD 55
Iceland ISL 395
Ireland IRL 205
Italy ITA 325
Japan JPN 740
Liechtenstein LIE 223
Luxembourg LUX 212
Malta MLT 338
Monaco MCO 221
Netherlands NLD 210
New Zealand NZL 920
Norway NOR 385
San Marino SMR 331
Spain ESP 230
Sweden SWE 380
Switzerland CHE 225
United Kingdom GBR 200
United States of America USA 2

Final clean combined data

With both donor- and country-level data, we have lots of different options for analysis. Since our hypotheses deal with questions of donor responses, the data we use to model donor responses uses donor-years as the unit of observation. Not all donors give money to the same countries, so this final data is not a complete panel (i.e. it does not include every combination of donors and years), which will pose some interesting methodological issues when modeling.

In H3 we hypothesize that more aid will be allocated to international or US-based NGOs than domestic NGOs in response to harsher anti-NGO restrictions. While AidData unfortunately does not categorize aid by channel (i.e. aid given to international vs. US vs. domestic NGOs), USAID does. For this hypothesis, then we only look at aid given by USAID, not the rest of the OECD. As with the proportion of contentious aid, we create similar variables to measure the proporition of aid given to international NGOs, US-based NGOs, and both international and US-based NGOs.

# Donor data
donor.level.data.raw <- aiddata.final %>%
  filter(cowcode %in% dcjw.full$cowcode) %>%
  filter(year > 1980) %>%
  filter(oda > 0) %>%  # Only look at positive aid
  mutate(oda_log = log1p(oda))

# Create fake country codes for non-country donors
fake.codes <- donor.level.data.raw %>%
  distinct(donor, donor.type) %>%
  filter(donor.type != "Country") %>%
  arrange(donor.type) %>% select(-donor.type) %>%
  mutate(fake.donor.cowcode = 2001:(2000 + n()),
         fake.donor.iso3 = paste0("Z", str_sub(fake.donor.cowcode, 3)))

donor.level.data <- donor.level.data.raw %>%
  left_join(fake.codes, by = "donor") %>%
  mutate(donor.cowcode = ifelse(is.na(donor.cowcode), 
                                fake.donor.cowcode, 
                                donor.cowcode),
         donor.iso3 = ifelse(is.na(donor.iso3), 
                             fake.donor.iso3, 
                             donor.iso3)) %>%
  select(-starts_with("fake"))


# USAID data
# USAID's conversion to constant 2015 dollars doesn't seem to take country differences into account—the deflator for each country in 2011 is essentially 96.65. When there are differences, it's because of floating point issues (like, if there are tiny grants of $3, there aren't enough decimal points to get the fraction to 96.65). So we just take the median value of the deflator for all countries and all grants and use that. 
#
# Rescale the 2015 data to 2011 to match AidData
#
# Deflator = current aid / constant aid * 100
# Current aid in year_t * (deflator in year_target / deflator in year_t)
usaid.deflator.2011 <- usaid.clean %>%
  filter(year == 2011) %>%
  summarise(deflator.target.year = median(aid.deflator, na.rm = TRUE)) %>%
  as.numeric()

donor.level.data.usaid <- usaid.clean %>%
  filter(cowcode %in% dcjw.full$cowcode) %>%
  filter(year > 1980) %>%
  filter(oda.us.current > 0) %>%
  mutate(oda.us.2011 = oda.us.current * (usaid.deflator.2011 / aid.deflator))

usaid.by.country.total <- donor.level.data.usaid %>%
  group_by(cowcode, year) %>%
  summarise(oda.us = sum(oda.us.2011, na.rm = TRUE))

usaid.by.country.channel <- donor.level.data.usaid %>%
  gather(key, value, c(channel.ngo.us, channel.ngo.int, channel.ngo.dom)) %>%
  group_by(cowcode, year, key, value) %>%
  summarise(total.oda.us = sum(oda.us.2011, na.rm = TRUE)) %>%
  ungroup() %>%
  unite(channel, key, value) %>%
  filter(str_detect(channel, "TRUE")) %>%
  mutate(channel = str_replace(channel, "channel", "oda.us"),
         channel = str_replace(channel, "_TRUE", "")) %>%
  spread(channel, total.oda.us, fill = 0)


# Country data
# Use DCJW 1980+ as base data, since we're limited to the countries included there
country.level.data <- dcjw.full %>%
  mutate(ever.dac.eligible = cowcode %in% ever.dac.eligible) %>%
  filter(!(cowcode %in% consolidated.democracies$cowcode)) %>% 
  left_join(select(vdem.cso, year, cowcode, csre, 
                   polity = e_fh_ipolity2, 
                   corruption = v2x_corr, 
                   govt.effectiveness = e_wbgi_gee),
            by = c("cowcode", "year")) %>%
  mutate(corruption = corruption * 10) %>%
  left_join(select(wdi.clean, -c(iso2c, country)), by = c("cowcode", "year")) %>%
  # Bring in UN population data
  left_join(un.pop, by = c("cowcode", "year")) %>%
  # Prefer UN population data, but use World Bank if missing
  mutate(population = ifelse(is.na(un.population), population, un.population)) %>%
  # Bring in UN GDP data
  # Prefer UN GDP data, but use World Bank if missing
  left_join(un.gdp.final, by = c("cowcode", "year")) %>%
  mutate(un.trade.pct.gdp = un.trade.pct.gdp * 100) %>%
  mutate(gdp = ifelse(is.na(un.gdp), gdp, un.gdp),
         trade.pct.gdp = ifelse(is.na(un.trade.pct.gdp), 
                                trade.pct.gdp, un.trade.pct.gdp)) %>%
  select(-starts_with("un.")) %>%
  left_join(select(col.clean, -country.name), by = c("cowcode")) %>%
  left_join(select(disasters.groups, cowcode, year, starts_with("natural_")), 
            by = c("cowcode", "year")) %>%
  # NAs in disasters are really 0, especially when occurrence is 0
  mutate_at(vars(starts_with("natural_")), funs(ifelse(is.na(.), 0, .))) %>%
  # Treat NAs in conflicts as FALSE
  left_join(select(conflicts, cowcode, year = Year, conflict.internal),
            by = c("cowcode", "year")) %>%
  mutate(conflict.internal = ifelse(is.na(conflict.internal),
                                    FALSE, conflict.internal)) %>%
  # Add indicator for post-Cold War, since all the former Soviet republics have
  # no GDP data before 1990
  mutate(post.1989 = year >= 1990)
testthat::expect_equal(nrow(country.level.data), 
                       nrow(filter(dcjw.full, 
                                   !(cowcode %in% consolidated.democracies$cowcode))))

# Combine country and donor data
donor.country.data <- donor.level.data %>%
  left_join(select(country.level.data, -country.name),
            by = c("year", "cowcode")) %>%
  mutate(former.colony = donor.cowcode == col.ruler.cowcode | 
           donor.cowcode == ind.from.cowcode) %>%
  arrange(donor, year)
testthat::expect_equal(nrow(donor.country.data), nrow(donor.level.data))

# Calculate different versions of aid variables
aid.by.country.total <- donor.country.data %>%
  group_by(cowcode, year) %>%
  summarise(total.oda = sum(oda, na.rm = TRUE))

aid.by.country.purpose <- donor.country.data %>%
  group_by(cowcode, year, purpose.contentiousness) %>%
  summarise(total.oda = sum(oda, na.rm = TRUE)) %>%
  spread(purpose.contentiousness, total.oda, fill = 0) %>%
  rename(oda.contentious.high = High, 
         oda.contentious.low = Low)

# Neighbor aid
# Join total oda to the huge distances dataframe and calculate total and
# average aid to neighboring countries
neighbor.oda <- all.distances %>%
  filter(is.rough.neighbor) %>%
  left_join(aid.by.country.total, by = c("cowcode.other" = "cowcode",
                                         "year")) %>%
  filter(cowcode.self != cowcode.other) %>%
  group_by(year, cowcode.self) %>%
  summarise_at(vars(total.oda), 
               funs(nb_oda.sum = sum(., na.rm = TRUE),
                    nb_oda.avg = mean(., na.rm = TRUE),
                    nb_oda.sd = sd(., na.rm = TRUE),
                    nb_oda.n = n())) %>%
  rename(cowcode = cowcode.self) %>%
  filter(year < 2014) %>%
  mutate_at(vars(starts_with("nb")),
            funs(ifelse(is.nan(.), 0, .)))

Missingness and imputation

The donor data is complete with no missing variables(!).

The country-level panel data is relatively complete, with only a few variables suffering from missing data, mostly from the World Bank and V-Dem.

That said, it’s still helpful to impute the missing variables, especially since polity, corruption, and GDP are all main controls (plus Lall 2016 shows the downsides of not imputing). So, we use Amelia to impute missing variables.

We ultimately create a long data frame with each of the imputed datasets stacked under the original dataset. Datasets are identified with the column m, like so:

m country year variable
original Afghanistan 2000 5
original Afghanistan 2001 NA
original Afghanistan 2002 6
NA
imp1 Afghanistan 2000 5
imp1 Afghanistan 2001 5.3
imp1 Afghanistan 2002 6
NA
imp2 Afghanistan 2000 5
imp2 Afghanistan 2001 5.8
imp2 Afghanistan 2002 6
NA

We estimate models for each of the imputed datasets and recombine their results. We use amelia::mi.meld() to combine estimates and standard errors from frequentist models (following King et al. 2001), and we merge the MCMC chains from Bayesian models (see also this).

We varied the number of datasets we imputed (m = 5 and m = 10) and found only trivial differences in coefficients between 5 and 10 datasets (as predicted by King et al.). In the interest of computational efficiency and speed, we only use 5 imputed datasets. To avoid needing to recreate both 5 and 10 datasets, we impute 10, but only use the first 5 for analysis.

imputation.rds <- here("Data", "data_cache", "country_aid_data_imputed_long.rds")

if (file.exists(imputation.rds)) {
  country.aid.data.imputed.long <- readRDS(here("Data", "data_cache",
                                                "country_aid_data_imputed_long.rds"))
} else {
  # THIS TAKES SO LONG.
  #
  # Combine aid data with country data
  country.aid.data.pre.transformation <- country.level.data %>%
    filter(year < 2014) %>%  # There's no aid data after 2013
    left_join(aid.by.country.total, by = c("cowcode", "year")) %>%
    left_join(aid.by.country.purpose, by = c("cowcode", "year")) %>%
    left_join(neighbor.oda, by = c("cowcode", "year")) %>%
    left_join(usaid.by.country.total, by = c("cowcode", "year")) %>%
    left_join(usaid.by.country.channel, by = c("cowcode", "year")) %>%
    mutate_at(vars(contains("oda")), funs(ifelse(is.na(.), 0, .)))
  
  # Missing Polity values are easy—most are just one-year gaps with the same
  # value before and after, so interpolate the missing values
  polity.imputed <- country.aid.data.pre.transformation %>%
    select(cowcode, year, polity) %>%
    group_by(cowcode) %>%
    mutate(impute.polity = !all(is.na(polity))) %>%
    mutate(polity = ifelse(impute.polity, na.interpolation(polity), polity)) %>%
    ungroup() %>% select(-impute.polity)
  
  country.aid.data.pre.amelia <- country.aid.data.pre.transformation %>% 
    select(-polity) %>% 
    left_join(polity.imputed, by = c("cowcode", "year"))
  
  # Select the variables to not include in the imputation model. Left join this
  # data frame later with the imputed data
  vars.to.include.in.imputation <- country.aid.data.pre.amelia %>%
    select(csre, corruption, govt.effectiveness, population, trade.pct.gdp,
           gdp, starts_with("natural"), total.oda, polity) %>%
    select(-natural_disaster.total.affected)
  
  # Vector of variables to include
  vars.to.include.sans.ids <- vars.to.include.in.imputation %>% colnames()
  
  # Stripped down dataset for imputation
  country.aid.data.to.impute <- country.aid.data.pre.amelia %>%
    select(year, cowcode, one_of(vars.to.include.sans.ids))
  
  # Imputation model tweaks
  # Variables that will be lagged and leaded
  vars.to.lag.lead <- c("csre", "polity", "corruption", "population",
                        "trade.pct.gdp", "gdp")
  # Variables that will be logged
  vars.to.log <- c("gdp", "population")
  
  # Run imputation model
  set.seed(my.seed)
  country.aid.data.amelia <- amelia(country.aid.data.to.impute,
                                    m = 10, ts = "year", cs = "cowcode", 
                                    intercs = TRUE,
                                    empri = 0.03 * nrow(country.aid.data.to.impute),
                                    p2s = 1, 
                                    lags = vars.to.lag.lead,
                                    leads = vars.to.lag.lead,
                                    logs = vars.to.log,
                                    parallel = "multicore",
                                    ncpus = parallel::detectCores())
  
  # Append list of imputed datasets to original in a long data frame and bring
  # back the omitted variables
  country.aid.data.imputed.long <- 
    bind_rows(mutate(country.aid.data.to.impute, m = "original"),
              bind_rows(unclass(country.aid.data.amelia$imputations), .id = "m")) %>%
    select(m, everything()) %>%
    left_join(select(country.aid.data.pre.amelia, 
                     -one_of(vars.to.include.sans.ids)), by = c("cowcode", "year"))
  
  saveRDS(country.aid.data.imputed.long, here("Data", "data_cache",
                                              "country_aid_data_imputed_long.rds"))
}
# Log, lead, and lag everything based on the big dataset of imputations

# pct.change <- function(x) {
#   (lead(x) / x) - 1
# }

# Determine if any of the values in the last k rows are TRUE
check_last_k <- function(x, k) {
  # This creates a matrix with a column for each lag value (e.g. column 1 = lag
  # 0, column 2 = lag 1, etc.)
  all.lags <- sapply(0:k, FUN = function(k) lag(x, k))
  
  # Marke TRUE if any of the columns have TRUE in them
  any.true.in.window <- apply(all.lags, MARGIN = 1, FUN = any, na.rm = TRUE)
  return(any.true.in.window)
}

country.aid.data <- country.aid.data.imputed.long %>%
  mutate(gdp.capita = gdp / population) %>%
  mutate_at(vars(gdp.capita, gdp, population), funs(log = log1p)) %>%
  # Calculate prop.contentious here since there should be some missing values
  # (since there are country-years where there's no ODA)
  mutate(prop.contentious = oda.contentious.high / 
           (oda.contentious.low + oda.contentious.high)) %>%
  mutate(prop.contentious = ifelse(is.nan(prop.contentious), 
                                   NA, prop.contentious)) %>%
  mutate(prop.contentious_logit = car::logit(prop.contentious, adjust = .001)) %>%
  # Calculate prop.ngo* here since there should also be some missing values
  mutate(prop.ngo.int = oda.us.ngo.int / oda.us,
         prop.ngo.us = oda.us.ngo.us / oda.us,
         prop.ngo.dom = oda.us.ngo.dom / oda.us,
         prop.ngo.foreign = (oda.us.ngo.int + oda.us.ngo.us) / oda.us) %>%
  # prop.ngo.dom.foreign = oda.us.ngo.dom / (oda.us.ngo.int + oda.us.ngo.us)) %>%
  mutate_at(vars(starts_with("prop.ngo")),
            funs(ifelse(is.nan(.), NA, .))) %>%
  mutate_at(vars(starts_with("prop.ngo")),
            funs(logit = car::logit(., adjust = .001))) %>%
  mutate_at(vars(total.oda, oda.contentious.high, oda.contentious.low, oda.us,
                 nb_oda.sum, nb_oda.avg, nb_oda.sd),
            funs(log = log1p(.))) %>%
  mutate(aid.pct.gdp = total.oda / gdp) %>%
  # Lag/lead/diff everything within countries and samples
  group_by(m, cowcode) %>%
  # Get leaded aid variables
  mutate_at(vars(contains("oda"), starts_with("prop.")),
            funs(next_year = lead(.),  # y_{i, t+1}
                 after_2 = lead(., 2),
                 after_5 = lead(., 5))) %>%  
  # Get diffed leaded aid variables
  mutate_at(vars(contains("next_year"), -contains("log")),
            funs(diff = lead(.) - .,  # (y_{it} - y_{i, t-1})_{t+1}
                 diff_log = sign(lead(.) - .) * 
                   log1p(abs(lead(.) - .)))) %>%  # sign(x) * log1p(abs(x))
  mutate_at(vars(contains("after_2"), -contains("log")),
            funs(diff = lead(., 2) - .,
                 diff_log = sign(lead(., 2) - .) * 
                   log1p(abs(lead(., 2) - .)))) %>%
  mutate_at(vars(contains("after_5"), -contains("log")),
            funs(diff = lead(., 5) - .,
                 diff_log = sign(lead(., 5) - .) * 
                   log1p(abs(lead(., 2) - .)))) %>%
  # Indicate changes in laws
  mutate_at(vars(advocacy, association, entry, funding, barriers.total),
            funs(new = . - lag(.),
                 worse = (. - lag(.)) > 0,
                 cat = cut(. - lag(.),
                           breaks = c(-Inf, -1, 0, Inf),
                           labels = c("New better law", "No new laws",
                                      "New worse law"),
                           ordered_result = TRUE))) %>%
  # Determine if there was conflict in the past 5 years
  mutate(internal.conflict.past.5 = check_last_k(conflict.internal, 5)) %>%
  ungroup()

# Save all 10 imputed datasets
country.aid.data.m10 <- country.aid.data

# Use just the first 5 imputed datasets
country.aid.data <- country.aid.data %>%
  filter(!(m %in% paste0("imp", 6:10)))

The final imputed dataset still has missing data, but that’s because of (1) prop.contentious, which is missing if there’s no aid in a country year, and (2) lags and leads create missing values at the beginnings and ends of the country windows.

Save final data

Final, clean country- and donor-level datasets are available in Data/data_clean/.

LS0tCnRpdGxlOiAiR2V0LCBjbGVhbiwgYW5kIG1lcmdlIGRhdGEiCmF1dGhvcjogIlN1cGFybmEgQ2hhdWRocnkgYW5kIEFuZHJldyBIZWlzcyIKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJUYnKWAiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZm9sZGluZzogaGlkZQplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCgpgYGB7ciBsb2FkLWxpYnJhcmllcywgbWVzc2FnZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5yZXRpbmEgPSAyLAogICAgICAgICAgICAgICAgICAgICAgdGlkeS5vcHRzID0gbGlzdCh3aWR0aC5jdXRvZmYgPSAxMjApLCAgIyBGb3IgY29kZQogICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyh3aWR0aCA9IDEyMCkpICAjIEZvciBvdXRwdXQKCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGh0dHIpCmxpYnJhcnkocnZlc3QpCmxpYnJhcnkoY291bnRyeWNvZGUpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KERUKQpsaWJyYXJ5KFdESSkKbGlicmFyeSh4bWwyKQpsaWJyYXJ5KGdnc3RhbmNlKQpsaWJyYXJ5KEFtZWxpYSkKbGlicmFyeShpbXB1dGVUUykKbGlicmFyeSh2YWxpZGF0ZSkKbGlicmFyeShoZXJlKQoKc291cmNlKGhlcmUoImxpYiIsICJncmFwaGljcy5SIikpCnNvdXJjZShoZXJlKCJsaWIiLCAicGFuZG9jLlIiKSkKCmFsbC5uYS5tZWFucy56ZXJvIDwtIFRSVUUKCm15LnNlZWQgPC0gMTIzNApzZXQuc2VlZChteS5zZWVkKQpgYGAKCiMjIENvbnNpc3RlbnQgY291bnRyeSBuYW1lcwoKVGhpcyBpcyBhIHBlcnBldHVhbCBuaWdodG1hcmUgaW4gSVIgZGF0YS4gSGVyZSdzIGEgbWFzdGVyIGxvb2t1cCB0YWJsZSBvZiBDT1cgY29kZXMsIElTTzMgY29kZXMsIElTTzIgY29kZXMsIGFuZCBHbGVkaXRzY2ggV2FyZCBjb2Rlcy4gCgpHbGVkaXRzY2ggYW5kIFdhcmQgZG8gbm90IGluY2x1ZGUgYSBidW5jaCBvZiBjb3VudHJpZXMsIHNvIEkgY3JlYXRlIG15IG93biBjb2RlcyBmb3IgcmVsZXZhbnQgY291bnRyaWVzIHRoYXQgYXBwZWFyIGluIG90aGVyIGRhdGFzZXRzOgoKLSBTb21hbGlsYW5kOiA1MjEKLSBQYWxlc3RpbmUgKFdlc3QgQmFuayk6IDY2NwotIFBhbGVzdGluZSAoR2F6YSk6IDY2OAotIFBhbGVzdGluZSAoYm90aCk6IDY2OQotIEhvbmcgS29uZzogNzE1CgpBbHNvLCBbZm9sbG93aW5nIEdsZWRpdHNjaCBhbmQgV2FyZF0oaHR0cDovL3ByaXZhdGV3d3cuZXNzZXguYWMudWsvfmtzZy9kYXRhL2lpc3lzdF9jYXNlZGVzYy5wZGYpLCBJIHRyZWF0IFNlcmJpYSBhcyAzNDAgYW5kIFNlcmJpYSAmIE1vbnRlbmVncm8gYXMgYSBjb250aW51YXRpb24gb2YgWXVnb3NsYXZpYSwgb3IgMzQ1LgoKKkFsc28qLCBmb2xsb3dpbmcgVi1EZW0gYW5kIFBvbGl0eSwgSSB0cmVhdCBWaWV0bmFtIGFzIDgxNi4KCmBgYHtyIGxvYWQtZ3djb2RlcywgbWVzc2FnZT1GQUxTRX0KIyBHbGVkaXRzY2ggV2FyZCBjb2RlcwojCiMgRG93bmxvYWQgYW5kIGNhY2hlIGRhdGEKZ3cuc3RhdGVzLnVybCA8LSAiaHR0cHM6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMTcwMzAyMDg1MDQ2L2h0dHA6Ly9wcml2YXRld3d3LmVzc2V4LmFjLnVrL35rc2cvZGF0YS9paXN5c3RlbS5kYXQiCmdzLm1pY3Jvc3RhdGVzLnVybCA8LSAiaHR0cHM6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMTcwMzAyMDcyMjAxL2h0dHA6Ly9wcml2YXRld3d3LmVzc2V4LmFjLnVrL35rc2cvZGF0YS9taWNyb3N0YXRlc3N5c3RlbS5kYXQiCgpndy5zdGF0ZXMucGF0aCA8LSBoZXJlKCJEYXRhIiwgImRhdGFfcmF3IiwgIkdsZWRpdHNjaCBXYXJkIikKCmlmICghZmlsZS5leGlzdHMoZmlsZS5wYXRoKGd3LnN0YXRlcy5wYXRoLCBiYXNlbmFtZShndy5zdGF0ZXMudXJsKSkpIHwKICAgICFmaWxlLmV4aXN0cyhmaWxlLnBhdGgoZ3cuc3RhdGVzLnBhdGgsIGJhc2VuYW1lKGdzLm1pY3Jvc3RhdGVzLnVybCkpKSkgewogIEdFVChndy5zdGF0ZXMudXJsLCAKICAgICAgd3JpdGVfZGlzayhmaWxlLnBhdGgoZ3cuc3RhdGVzLnBhdGgsIGJhc2VuYW1lKGd3LnN0YXRlcy51cmwpKSwKICAgICAgICAgICAgICAgICBvdmVyd3JpdGUgPSBUUlVFKSkKICAKICBHRVQoZ3MubWljcm9zdGF0ZXMudXJsLCAKICAgICAgd3JpdGVfZGlzayhmaWxlLnBhdGgoZ3cuc3RhdGVzLnBhdGgsIGJhc2VuYW1lKGdzLm1pY3Jvc3RhdGVzLnVybCkpLAogICAgICAgICAgICAgICAgIG92ZXJ3cml0ZSA9IFRSVUUpKQp9Cgpndy5kYXRlIDwtICIlZDolbTolWSIKZ3cuc3RhdGVzIDwtIHJlYWRfdHN2KGhlcmUoIkRhdGEiLCAiZGF0YV9yYXciLCAiR2xlZGl0c2NoIFdhcmQiLCAiaWlzeXN0ZW0uZGF0IiksCiAgICAgICAgICAgICAgICAgICAgICBjb2xfbmFtZXMgPSBjKCJnd2NvZGUiLCAiY293YyIsICJjb3VudHJ5Lm5hbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZGF0ZS5zdGFydCIsICJkYXRlLmVuZCIpLAogICAgICAgICAgICAgICAgICAgICAgY29sX3R5cGVzID0gY29scygKICAgICAgICAgICAgICAgICAgICAgICAgZ3djb2RlID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgY293YyA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgY291bnRyeS5uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBkYXRlLnN0YXJ0ID0gY29sX2RhdGUoZm9ybWF0ID0gZ3cuZGF0ZSksCiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGUuZW5kID0gY29sX2RhdGUoZm9ybWF0ID0gZ3cuZGF0ZSkKICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICBsb2NhbGUgPSBsb2NhbGUoZW5jb2RpbmcgPSAid2luZG93cy0xMjUyIikpCgpndy5taWNyb3N0YXRlcyA8LSByZWFkX3RzdihoZXJlKCJEYXRhIiwgImRhdGFfcmF3IiwgIkdsZWRpdHNjaCBXYXJkIiwgIm1pY3Jvc3RhdGVzc3lzdGVtLmRhdCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xfbmFtZXMgPSBjKCJnd2NvZGUiLCAiY293YyIsICJjb3VudHJ5Lm5hbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJkYXRlLnN0YXJ0IiwgImRhdGUuZW5kIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGNvbHMoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3djb2RlID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3djID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cnkubmFtZSA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRlLnN0YXJ0ID0gY29sX2RhdGUoZm9ybWF0ID0gZ3cuZGF0ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZS5lbmQgPSBjb2xfZGF0ZShmb3JtYXQgPSBndy5kYXRlKQogICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbGUgPSBsb2NhbGUoZW5jb2RpbmcgPSAid2luZG93cy0xMjUyIikpCgpndy5jb2RlcyA8LSBiaW5kX3Jvd3MoZ3cuc3RhdGVzLCBndy5taWNyb3N0YXRlcykgJT4lCiAgZmlsdGVyKGRhdGUuZW5kID4geW1kKCIyMDAwLTAxLTAxIikpICU+JQogICMgSGVscCBvdXQgY291bnRyeWNvZGUoKSAKICBtdXRhdGUoY291bnRyeS5uYW1lID0gcmVjb2RlKGNvdW50cnkubmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBWaWV0bmFtLCBEZW1vY3JhdGljIFJlcHVibGljIG9mYCA9ICJWaWV0bmFtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBZZW1lbiAoQXJhYiBSZXB1YmxpYyBvZiBZZW1lbilgID0gIlllbWVuIikpICU+JQogIG11dGF0ZShpc28zID0gY291bnRyeWNvZGUoY291bnRyeS5uYW1lLCAiY291bnRyeS5uYW1lIiwgImlzbzNjIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1c3RvbV9tYXRjaCA9IGMoQWJraGF6aWEgPSBOQSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBTb3V0aCBPc3NldGlhYCA9IE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBZdWdvc2xhdmlhID0gIllVRyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEtvc292byA9ICJYS0siLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgS29yZWEsIFBlb3BsZSdzIFJlcHVibGljIG9mYCA9IE5BKSksCiAgICAgICAgIGlzbzIgPSBjb3VudHJ5Y29kZShpc28zLCAiaXNvM2MiLCAiaXNvMmMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VzdG9tX21hdGNoID0gYyhYS0sgPSAiWEsiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBZVUcgPSAzNDUpKSwKICAgICAgICAgY293Y29kZSA9IGNvdW50cnljb2RlKGlzbzMsICJpc28zYyIsICJjb3duIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1c3RvbV9tYXRjaCA9IGMoWEtLID0gMzQ3LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTUkIgPSAzNDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFlVRyA9IDM0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVk5NID0gODE2KSkpICU+JQogIGZpbHRlcighaXMubmEoaXNvMykpICU+JQogIG11dGF0ZShjb3VudHJ5Lm5hbWUgPSBjb3VudHJ5Y29kZShpc28zLCAiaXNvM2MiLCAiY291bnRyeS5uYW1lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VzdG9tX21hdGNoID0gYyhYS0sgPSAiS29zb3ZvIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBZVUcgPSAiWXVnb3NsYXZpYSIpKSkgJT4lCiAgc2VsZWN0KGNvdW50cnkubmFtZSwgaXNvMywgaXNvMiwgZ3djb2RlLCBjb3djb2RlKQoKbWFudWFsLmd3IDwtIHRyaWJibGUoCiAgfmNvdW50cnkubmFtZSwgICAgICAgICAgICB+aXNvMywgIH5pc28yLCAgIH5nd2NvZGUsICB+Y293Y29kZSwKICAiU29tYWxpbGFuZCIsICAgICAgICAgICAgICJTT0wiLCAgTkEsICAgICAgNTIxLCAgICAgIDUyMSwgICAgIAogICJQYWxlc3RpbmUgKFdlc3QgQmFuaykiLCAgIlBXQiIsICBOQSwgICAgICA2NjcsICAgICAgNjY3LCAgICAgCiAgIlBhbGVzdGluZSAoR2F6YSkiLCAgICAgICAiUEdaIiwgIE5BLCAgICAgIDY2OCwgICAgICA2NjgsICAgICAKICAiUGFsZXN0aW5lIiwgICAgICAgICAgICAgICJQU0UiLCAgIlBTIiwgICAgNjY5LCAgICAgIDY2OSwgICAgIAogICJIb25nIEtvbmciLCAgICAgICAgICAgICAgIkhLRyIsICAiSEsiLCAgICA3MTUsICAgICAgNzE1CikKCmd3LmNvZGVzIDwtIGJpbmRfcm93cyhndy5jb2RlcywgbWFudWFsLmd3KSAlPiUgCiAgYXJyYW5nZShjb3VudHJ5Lm5hbWUpCgpndy5jb2RlcyAlPiUgZGF0YXRhYmxlKCkKYGBgCgoKIyMgRm9yZWlnbiBhaWQKCiMjIyBPRUNEIGFuZCBBaWREYXRhIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKVGhlIE9FQ0QgY29sbGVjdHMgZGV0YWlsZWQgZGF0YSBvbiBhbGwgZm9yZWlnbiBhaWQgZmxvd3MgKE9EQSkgZnJvbSBPRUNEIG1lbWJlciBjb3VudHJpZXMgKGFuZCBzb21lIG5vbi1tZW1iZXIgY291bnRyaWVzKSwgbXVsaWxhdGVyYWwgb3JnYW5pemF0aW9ucywgYW5kIHRoZSBCaWxsIGFuZCBNZWxpbmRhIEdhdGVzIEZvdW5kYXRpb24gKGZvciBzb21lIHJlYXNvbiB0aGV5J3JlIHRoZSBvbmx5IG5vbnByb2ZpdCBkb25vcikgdG8gYWxsIERBQy1lbGlnaWJsZSBjb3VudHJpZXMgKGFuZCBzb21lIG5vbiBub24tREFDLWVsaWdpYmxlIGNvdW50cmllcykuIAoKVGhlIE9FQ0QgdHJhY2tzIGFsbCB0aGlzIGluIGEgY2VudHJhbGl6ZWQgQ3JlZGl0b3IgUmVwb3J0aW5nIFN5c3RlbSBkYXRhYmFzZSBhbmQgcHJvdmlkZXMgYSBuaWNlIGZyb250IGVuZCBmb3IgaXQgYXQgW09FQ0QuU3RhdF0oaHR0cDovL3N0YXRzLm9lY2Qub3JnLykgd2l0aCBhbiBvcGVuIChidXQgaW5zY3J1dGFibGUpIEFQSSAoW3JhdyBDUlMgZGF0YV0oaHR0cDovL3N0YXRzLm9lY2Qub3JnL0Rvd25sb2FkRmlsZXMuYXNweD9IaWRlVG9wTWVudT15ZXMmRGF0YXNldENvZGU9Q1JTMSkgaXMgYWxzbyBhdmFpbGFibGUpLiBUaGVyZSBhcmUgYSBzZXQgb2YgcHJlLWJ1aWx0IHF1ZXJpZXMgd2l0aCBpbmZvcm1hdGlvbiBhYm91dCBPREEgZmxvd3MgYnkgZG9ub3IsIHJlY2lwaWVudCwgYW5kIHNlY3RvciAocHVycG9zZSksIGJ1dCB0aGUgcHJlLWJ1aWx0IGRhdGEgc291cmNlcyBkbyBub3QgaW5jbHVkZSBhbGwgZGltZW5zaW9ucyBvZiB0aGUgZGF0YS4gRm9yIGV4YW1wbGUsIFtUYWJsZSBEQUMyYV0oaHR0cDovL3N0YXRzLm9lY2Qub3JnL0luZGV4LmFzcHg/RGF0YVNldENvZGU9VEFCTEUyQSkgaW5jbHVkZXMgY29sdW1ucyBmb3IgZG9ub3IsIHJlY2lwaWVudCwgeWVhciwgYW5kIHRvdGFsIE9EQSAoZS5nLiB0aGUgVVMgZ2F2ZSBcJFggdG8gTmlnZXJpYSBpbiAyMDA4KSAsIGJ1dCBkb2VzIG5vdCBpbmRpY2F0ZSB0aGUgcHVycG9zZS9zZWN0b3IgZm9yIHRoZSBPREEuIFtUYWJsZSBEQUM1XShodHRwOi8vc3RhdHMub2VjZC5vcmcvSW5kZXguYXNweD9EYXRhU2V0Q29kZT1UQUJMRTUpIGluY2x1ZGVzIGNvbHVtbnMgZm9yIHRoZSBkb25vciwgc2VjdG9yLCB5ZWFyLCBhbmQgdG90YWwgT0RBIChlLmcuIHRoZSBVUyBnYXZlIFwkWCBmb3IgZWR1Y2F0aW9uIGluIDIwMDgpLCBidXQgZG9lcyBub3QgaW5jbHVkZSByZWNpcGllbnQgaW5mb3JtYXRpb24uIAoKSW5zdGVhZCBvZiB1c2luZyB0aGVzZSBwcmUtYnVpbHQgcXVlcmllcyBvciBhdHRlbXB0aW5nIHRvIG1hbmlwdWxhdGUgdGhlaXIgcGFyYW1ldGVycywgaXQncyBwb3NzaWJsZSB0byB1c2UgdGhlIFtPRUNEJ3MgUVdJRFMgcXVlcnkgYnVpbGRlcl0oaHR0cHM6Ly9zdGF0cy5vZWNkLm9yZy9xd2lkcy8pIHRvIGNyZWF0ZSBhIGN1c3RvbSBkb3dubG9hZCBvZiBkYXRhLiBIb3dldmVyLCBpdCBpcyBzbG93IGFuZCBjbHVua3kgYW5kIHJlcXVpcmVzIHNpbmdpZmljYW50IG11bmdpbmcgYW5kIGZpbHRlcmluZyBhZnRlciBleHBvcnRpbmcuIAoKVGhlIHNvbHV0aW9uIHRvIGFsbCBvZiB0aGlzIGlzIHRvIHVzZSBbZGF0YSBmcm9tIEFpZERhdGFdKGh0dHA6Ly9haWRkYXRhLm9yZy9haWRkYXRhLXJlc2VhcmNoLXJlbGVhc2VzKSwgd2hpY2ggaW1wb3J0cyByYXcgZGF0YSBmcm9tIHRoZSBPRUNELCBjbGVhbnMgaXQsIHZlcmlmaWVzIGl0LCBhbmQgbWFrZXMgaXQgZnJlZWx5IGF2YWlsYWJsZSBvbiBHaXRIdWIuCgpBaWREYXRhIG9mZmVycyBtdWx0aXBsZSB2ZXJzaW9ucyBvZiB0aGUgZGF0YSwgaW5jbHVkaW5nIGEgZnVsbCByZWxlYXNlLCBhIHRoaW4gcmVsZWFzZSwgYWdncmVnYXRlZCBkb25vci9yZWNpcGllbnQveWVhciBkYXRhLCBhbmQgYWdncmVnYXRlZCBkb25vci9yZWNpcGllbnQveWVhci9wdXJwb3NlIGRhdGEuIEZvciB0aGUgcHVycG9zZXMgb2YgdGhpcyBzdHVkeSwgYWxsIHdlIGNhcmUgYWJvdXQgYXJlIE9EQSBmbG93cyBieSBkb25vciwgcmVjaXBpZW50LCB5ZWFyLCBhbmQgcHVycG9zZSwgd2hpY2ggaXMgb25lIG9mIHRoZSByZWFkeS1tYWRlIGRhdGFzZXRzLiAKCk5vdGFibHksIHRoaXMgYWdncmVnYXRlZCBkYXRhIHNob3dzIHRvdGFsIGFpZCAqY29tbWl0bWVudHMqLCBub3QgYWlkICpkaXNidXJzZW1lbnRzKi4gQm90aCB0eXBlcyBvZiBPREEgaW5mb3JtYXRpb24gYXJlIGF2YWlsYWJsZSBmcm9tIHRoZSBPRUNEIGFuZCBpdCdzIHBvc3NpYmxlIHRvIGdldCB0aGVtIHVzaW5nIE9FQ0QncyByYXcgZGF0YS4gSG93ZXZlciwgW0FpZERhdGEgbm90ZXNdKGh0dHA6Ly9haWRkYXRhLm9yZy9mYXFzLWFib3V0LW91ci1kYXRhKSB0aGF0IGRpc2J1cnNtZW50IGRhdGEgaXMgc3RpY2t5IGFuZCBzbG934oCUcHJvamVjdHMgdGFrZSBhIGxvbmcgdGltZSB0byBmdWxmaWwgYW5kIGFjdHVhbCBpbmZsb3dzIG9mIGFpZCBpbiBhIHllYXIgY2FuIGJlIHRpZWQgdG8gY29tbWl0bWVudHMgbWFkZSB5ZWFycyBiZWZvcmUuIEJlY2F1c2Ugd2UncmUgaW50ZXJlc3RlZCBpbiBkb25vciByZWFjdGlvbnMgdG8gcmVzdHJpY3Rpb25zIG9uIE5HT3MsIGFueSByZWFjdGlvbiB3b3VsZCBiZSB2aXNpYmxlIGluIHRoZSBkZWNpc2lvbiB0byBjb21taXQgbW9uZXkgdG8gYWlkLCBub3QgaW4gdGhlIHVsdGltYXRlIGRpc2J1cnNlbWVudCBvZiBhaWQsIHdoaWNoIGlzIG1vc3QgbGlrZWx5IGFscmVhZHkgbGVnYWxseSBvYmxpZ2F0ZWQgYW5kIGFsbG9jYXRlZCB0byB0aGUgY291bnRyeSByZWdhcmRsZXNzIG9mIHJlc3RyaWN0aW9ucy4KClNvLCB3ZSBsb29rIGF0IE9EQSAqY29tbWl0bWVudHMqLgoKYGBge3IgbG9hZC1haWRkYXRhLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBjYWNoZT1UUlVFfQphaWRkYXRhLnVybCA8LSAiaHR0cHM6Ly9naXRodWIuY29tL0FpZERhdGEtV00vcHVibGljX2RhdGFzZXRzL3JlbGVhc2VzL2Rvd25sb2FkL3YzLjEvQWlkRGF0YUNvcmVfUmVzZWFyY2hSZWxlYXNlX0xldmVsMV92My4xLnppcCIKYWlkZGF0YS5wYXRoIDwtIGhlcmUoIkRhdGEiLCAiZGF0YV9yYXciLCAiQWlkRGF0YSIpCmFpZGRhdGEuemlwLm5hbWUgPC0gYmFzZW5hbWUoYWlkZGF0YS51cmwpCmFpZGRhdGEubmFtZSA8LSB0b29sczo6ZmlsZV9wYXRoX3NhbnNfZXh0KGFpZGRhdGEuemlwLm5hbWUpCgphaWRkYXRhLmZpbmFsLm5hbWUgPC0gIkFpZERhdGFDb3JlRG9ub3JSZWNpcGllbnRZZWFyUHVycG9zZV9SZXNlYXJjaFJlbGVhc2VfTGV2ZWwxX3YzLjEuY3N2IgoKIyBEb3dubG9hZCBBaWREYXRhIGRhdGEgaWYgbmVlZGVkCmlmICghZmlsZS5leGlzdHMoZmlsZS5wYXRoKGFpZGRhdGEucGF0aCwgYWlkZGF0YS5maW5hbC5uYW1lKSkpIHsKICBhaWRkYXRhLmdldCA8LSBHRVQoYWlkZGF0YS51cmwsIAogICAgICAgICAgICAgICAgICAgICB3cml0ZV9kaXNrKGZpbGUucGF0aChhaWRkYXRhLnBhdGgsIGFpZGRhdGEuemlwLm5hbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZSA9IFRSVUUpLCAKICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3MoKSkKICB1bnppcChmaWxlLnBhdGgoYWlkZGF0YS5wYXRoLCBhaWRkYXRhLnppcC5uYW1lKSwgZXhkaXIgPSBhaWRkYXRhLnBhdGgpCiAgCiAgIyBDbGVhbiB1cCB6aXAgZmlsZSBhbmQgdW5uZWNlc3NhcnkgQ1NWIGZpbGVzCiAgZmlsZS5yZW1vdmUoZmlsZS5wYXRoKGFpZGRhdGEucGF0aCwgYWlkZGF0YS56aXAubmFtZSkpCiAgbGlzdC5maWxlcyhhaWRkYXRhLnBhdGgsIHBhdHRlcm4gPSAiY3N2IiwgZnVsbC5uYW1lcyA9IFRSVUUpICU+JQogICAgbWFwKH4gaWZlbHNlKHN0cl9kZXRlY3QoLngsICJEb25vclJlY2lwaWVudFllYXJQdXJwb3NlIiksIDAsCiAgICAgICAgICAgICAgICAgZmlsZS5yZW1vdmUoZmlsZS5wYXRoKC54KSkpKQp9CgojIENsZWFuIHVwIEFpZERhdGEgZGF0YQphaWRkYXRhLnJhdyA8LSByZWFkX2NzdihmaWxlLnBhdGgoYWlkZGF0YS5wYXRoLCBhaWRkYXRhLmZpbmFsLm5hbWUpLAogICAgICAgICAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBjb2xzKAogICAgICAgICAgICAgICAgICAgICAgICAgIGRvbm9yID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHJlY2lwaWVudCA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ZWFyID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBjb2FsZXNjZWRfcHVycG9zZV9jb2RlID0gY29sX2RvdWJsZSgpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNvYWxlc2NlZF9wdXJwb3NlX25hbWUgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29tbWl0bWVudF9hbW91bnRfdXNkX2NvbnN0YW50X3N1bSA9IGNvbF9kb3VibGUoKQogICAgICAgICAgICAgICAgICAgICAgICApKQoKYWlkZGF0YS5jbGVhbiA8LSBhaWRkYXRhLnJhdyAlPiUKICAjIEdldCByaWQgb2Ygbm9uLWNvdW50cnkgcmVjaXBpZW50cwogIGZpbHRlcighc3RyX2RldGVjdChyZWNpcGllbnQsCiAgICAgICAgICAgICAgICAgICAgIHJlZ2V4KCJyZWdpb25hbHx1bnNwZWNpZmllZHxtdWx0aXx2YWx1ZXxnbG9iYWx8Y29tbWlzc2lvbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmVfY2FzZSA9IFRSVUUpKSkgJT4lCiAgZmlsdGVyKHllYXIgPCA5OTk5KSAlPiUKICBtdXRhdGUocHVycG9zZS5jb2RlLnNob3J0ID0gYXMuaW50ZWdlcihzdHJfc3ViKGNvYWxlc2NlZF9wdXJwb3NlX2NvZGUsIDEsIDMpKSkKCiMgRG9ub3IsIHJlY2lwaWVudCwgYW5kIHB1cnBvc2UgZGV0YWlscwojIEkgcHVsbGVkIHRoZXNlIGNvdW50cnkgbmFtZXMgb3V0IG9mIHRoZSBkcm9wZG93biBtZW51IGF0IE9FQ0QuU3RhdCBUYWJsZSAyYSBvbmxpbmUKZGFjLmRvbm9ycyA8LSBjKCJBdXN0cmFsaWEiLCAiQXVzdHJpYSIsICJCZWxnaXVtIiwgIkNhbmFkYSIsICJDemVjaCBSZXB1YmxpYyIsCiAgICAgICAgICAgICAgICAiRGVubWFyayIsICJGaW5sYW5kIiwgIkZyYW5jZSIsICJHZXJtYW55IiwgIkdyZWVjZSIsICJJY2VsYW5kIiwKICAgICAgICAgICAgICAgICJJcmVsYW5kIiwgIkl0YWx5IiwgIkphcGFuIiwgIktvcmVhIiwgIkx1eGVtYm91cmciLCAiTmV0aGVybGFuZHMiLAogICAgICAgICAgICAgICAgIk5ldyBaZWFsYW5kIiwgIk5vcndheSIsICJQb2xhbmQiLCAiUG9ydHVnYWwiLCAiU2xvdmFrIFJlcHVibGljIiwKICAgICAgICAgICAgICAgICJTbG92ZW5pYSIsICJTcGFpbiIsICJTd2VkZW4iLCAiU3dpdHplcmxhbmQiLCAiVW5pdGVkIEtpbmdkb20iLAogICAgICAgICAgICAgICAgIlVuaXRlZCBTdGF0ZXMiKQoKbm9uLmRhYy5kb25vcnMgPC0gYygiQnVsZ2FyaWEiLCAiQ3JvYXRpYSIsICJDeXBydXMiLCAiRXN0b25pYSIsICJIdW5nYXJ5IiwKICAgICAgICAgICAgICAgICAgICAiSXNyYWVsIiwgIkthemFraHN0YW4iLCAiS3V3YWl0IiwgIkxhdHZpYSIsICJMaWVjaHRlbnN0ZWluIiwKICAgICAgICAgICAgICAgICAgICAiTGl0aHVhbmlhIiwgIk1hbHRhIiwgIlJvbWFuaWEiLCAiUnVzc2lhIiwgIlNhdWRpIEFyYWJpYSIsCiAgICAgICAgICAgICAgICAgICAgIkNoaW5lc2UgVGFpcGVpIiwgIlRoYWlsYW5kIiwgIlRpbW9yIExlc3RlIiwgIlR1cmtleSIsCiAgICAgICAgICAgICAgICAgICAgIlVuaXRlZCBBcmFiIEVtaXJhdGVzIikKCm90aGVyLmNvdW50cmllcyA8LSBjKCJCcmF6aWwiLCAiQ2hpbGUiLCAiQ29sb21iaWEiLCAiSW5kaWEiLCAiTW9uYWNvIiwgIlFhdGFyIiwKICAgICAgICAgICAgICAgICAgICAgIlNvdXRoIEFmcmljYSIsICJUYWl3YW4iKQoKZG9ub3JzLmFsbCA8LSBhaWRkYXRhLmNsZWFuICU+JQogIGRpc3RpbmN0KGRvbm9yKSAlPiUKICBtdXRhdGUoZG9ub3IudHlwZSA9IGNhc2Vfd2hlbigKICAgIC4kZG9ub3IgJWluJSBjKGRhYy5kb25vcnMsIG5vbi5kYWMuZG9ub3JzLCBvdGhlci5jb3VudHJpZXMpIH4gIkNvdW50cnkiLAogICAgLiRkb25vciA9PSAiQmlsbCAmIE1lbGluZGEgR2F0ZXMgRm91bmRhdGlvbiIgfiAiUHJpdmF0ZSBkb25vciIsCiAgICBUUlVFIH4gIk11bHRpbGF0ZXJhbCBvciBJR08iCiAgKSkKCmRvbm9yLmNvdW50cmllcyA8LSBkb25vcnMuYWxsICU+JSAKICBmaWx0ZXIoZG9ub3IudHlwZSA9PSAiQ291bnRyeSIpICU+JSAKICBtdXRhdGUoZG9ub3IuY293Y29kZSA9IGNvdW50cnljb2RlKGRvbm9yLCAiY291bnRyeS5uYW1lIiwgImNvd24iKSwKICAgICAgICAgZG9ub3IuaXNvMyA9IGNvdW50cnljb2RlKGRvbm9yLCAiY291bnRyeS5uYW1lIiwgImlzbzNjIikpCgpkb25vcnMgPC0gYmluZF9yb3dzKGZpbHRlcihkb25vcnMuYWxsLCBkb25vci50eXBlICE9ICJDb3VudHJ5IiksCiAgICAgICAgICAgICAgICAgICAgZG9ub3IuY291bnRyaWVzKQoKcmVjaXBpZW50cyA8LSBhaWRkYXRhLmNsZWFuICU+JQogIGRpc3RpbmN0KHJlY2lwaWVudCkgJT4lCiAgbXV0YXRlKGlzbzMgPSBjb3VudHJ5Y29kZShyZWNpcGllbnQsICJjb3VudHJ5Lm5hbWUiLCAiaXNvM2MiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VzdG9tX21hdGNoID0gYyhgS29yZWEsIERlbW9jcmF0aWMgUmVwdWJsaWMgb2ZgID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBOZXRoZXJsYW5kcyBBbnRpbGxlc2AgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgS29zb3ZvID0gIlhLSyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBTZXJiaWEgYW5kIE1vbnRlbmVncm9gID0gIlNDRyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFl1Z29zbGF2aWEgPSAiWVVHIgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSkgJT4lCiAgbGVmdF9qb2luKGd3LmNvZGVzLCBieSA9ICJpc28zIikgJT4lCiAgIyBHZXQgcmlkIG9mIHRpbnkgY291bnRyaWVzCiAgZmlsdGVyKCFpcy5uYShnd2NvZGUpKQoKIyBQdXJwb3NlcwpwdXJwb3NlcyA8LSBhaWRkYXRhLmNsZWFuICU+JQogIGNvdW50KGNvYWxlc2NlZF9wdXJwb3NlX25hbWUsIGNvYWxlc2NlZF9wdXJwb3NlX2NvZGUpCgpwdXJwb3Nlcy51cmwgPC0gImh0dHBzOi8vd3d3Lm9lY2Qub3JnL2RhYy9zdGF0cy9kb2N1bWVudHVwbG9hZC9EQUNfY29kZUxpc3RzLnhtbCIKcHVycG9zZS5ub2RlcyA8LSByZWFkX3htbChwdXJwb3Nlcy51cmwpICU+JSB4bWxfZmluZF9hbGwoIi8vY29kZWxpc3QtaXRlbSIpCgpwdXJwb3NlLmNvZGVzIDwtIGRhdGFfZnJhbWUoCiAgY29kZSA9IHB1cnBvc2Uubm9kZXMgJT4lIHhtbF9maW5kX2ZpcnN0KCIuLy9jb2RlIikgJT4lIHhtbF90ZXh0KCksCiAgY2F0ZWdvcnkgPSBwdXJwb3NlLm5vZGVzICU+JSB4bWxfZmluZF9maXJzdCgiLi8vY2F0ZWdvcnkiKSAlPiUgeG1sX3RleHQoKSwKICBuYW1lID0gcHVycG9zZS5ub2RlcyAlPiUgeG1sX2ZpbmRfZmlyc3QoIi4vL25hbWUiKSAlPiUgeG1sX3RleHQoKSwKICBkZXNjcmlwdGlvbiA9IHB1cnBvc2Uubm9kZXMgJT4lIHhtbF9maW5kX2ZpcnN0KCIuLy9kZXNjcmlwdGlvbiIpICU+JSB4bWxfdGV4dCgpCikgJT4lCiAgbXV0YXRlKGNvZGUgPSBhcy5pbnRlZ2VyKGNvZGUpKQoKIyBFeHRyYWN0IHRoZSBnZW5lcmFsIGNhdGVnb3JpZXMgb2YgYWlkIHB1cnBvc2VzIChpLmUuIHRoZSBmaXJzdCB0aHJlZSBkaWdpdHMgb2YgdGhlIHB1cnBvc2UgY29kZXMpCmdlbmVyYWwuY29kZXMgPC0gcHVycG9zZS5jb2RlcyAlPiUKICBmaWx0ZXIoY29kZSAlaW4lIGFzLmNoYXJhY3RlcigxMDA6MTAwMCkgJiBzdHJfZGV0ZWN0KG5hbWUsICJeXFxkIikpICU+JQogIG11dGF0ZShjb2RlID0gYXMuaW50ZWdlcihjb2RlKSkgJT4lCiAgc2VsZWN0KHB1cnBvc2UuY29kZS5zaG9ydCA9IGNvZGUsIHB1cnBvc2UuY2F0ZWdvcnkubmFtZSA9IG5hbWUpICU+JQogIG11dGF0ZShwdXJwb3NlLmNhdGVnb3J5LmNsZWFuID0gc3RyX3JlcGxhY2UocHVycG9zZS5jYXRlZ29yeS5uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlxcZFxcLlxcZCAiLCAiIikpICU+JQogIHNlcGFyYXRlKHB1cnBvc2UuY2F0ZWdvcnkuY2xlYW4sCiAgICAgICAgICAgaW50byA9IGMoInB1cnBvc2Uuc2VjdG9yIiwgInB1cnBvc2UuY2F0ZWdvcnkiKSwgCiAgICAgICAgICAgc2VwID0gIiwgIikgJT4lCiAgbXV0YXRlX2F0KHZhcnMoYyhwdXJwb3NlLnNlY3RvciwgcHVycG9zZS5jYXRlZ29yeSkpLCBmdW5zKHN0cl90b190aXRsZSguKSkpICU+JQogIHNlbGVjdCgtcHVycG9zZS5jYXRlZ29yeS5uYW1lKQoKIyBUaGVzZSA3IGNvZGVzIGFyZSB3ZWlyZCBhbmQgZ2V0IGZpbHRlcmVkIG91dCBpbmFkdmVydGFudGx5CmNvZGVzLm5vdC5pbi5vZWNkLmxpc3QgPC0gdHJpYmJsZSgKICB+cHVycG9zZS5jb2RlLnNob3J0LCB+cHVycG9zZS5zZWN0b3IsIH5wdXJwb3NlLmNhdGVnb3J5LAogIDEwMCwgICAgICAgICAgICAgICAgICJTb2NpYWwiLCAgICAgICAgIlNvY2lhbCBJbmZyYXN0cnVjdHVyZSIsCiAgMjAwLCAgICAgICAgICAgICAgICAgIkVjbyIsICAgICAgICAgICAiRWNvbm9taWMgSW5mcmFzdHJ1Y3R1cmUiLAogIDMwMCwgICAgICAgICAgICAgICAgICJQcm9kIiwgICAgICAgICAgIlByb2R1Y3Rpb24iLAogIDMxMCwgICAgICAgICAgICAgICAgICJQcm9kIiwgICAgICAgICAgIkFncmljdWx0dXJlIiwKICAzMjAsICAgICAgICAgICAgICAgICAiUHJvZCIsICAgICAgICAgICJJbmR1c3RyeSIsCiAgNDIwLCAgICAgICAgICAgICAgICAgIk11bHRpc2VjdG9yIiwgICAiV29tZW4gaW4gZGV2ZWxvcG1lbnQiLAogICMgTkI6IFRoaXMgYWN0dWFsbHkgaXMgc3BsaWN0IGJldHdlZW4gOTIwMTAgKGRvbWVzdGljIE5HT3MpLCA5MjAyMAogICMgKGludGVybmF0aW9uYWwgTkdPcyksIGFuZCA5MjAzMCAobG9jYWwgYW5kIHJlZ2lvbmFsIE5HT3MpCiAgOTIwLCAgICAgICAgICAgICAgICAgIk5vbiBTZWN0b3IiLCAgICAiU3VwcG9ydCB0byBOR09zIgopCgpwdXJwb3NlLmNvZGVzLmNsZWFuIDwtIGdlbmVyYWwuY29kZXMgJT4lCiAgYmluZF9yb3dzKGNvZGVzLm5vdC5pbi5vZWNkLmxpc3QpICU+JQogIGFycmFuZ2UocHVycG9zZS5jb2RlLnNob3J0KSAlPiUKICBtdXRhdGUocHVycG9zZS5jb250ZW50aW91c25lc3MgPSAiIikKCiMgTWFudWFsbHkgY29kZSBjb250ZW50aW91c25lc3Mgb2YgcHVycG9zZXMKd3JpdGVfY3N2KHB1cnBvc2UuY29kZXMuY2xlYW4sCiAgICAgICAgICBoZXJlKCJEYXRhIiwgImRhdGFfbWFudWFsIiwKICAgICAgICAgICAgICAgInB1cnBvc2VfY29kZXNfY29udGVudGlvbl9XSUxMX0JFX09WRVJXUklUVEVOLmNzdiIpKQoKcHVycG9zZS5jb2Rlcy5jb250ZW50aW91c25lc3MgPC0gcmVhZF9jc3YoaGVyZSgiRGF0YSIsICJkYXRhX21hbnVhbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInB1cnBvc2VfY29kZXNfY29udGVudGlvbi5jc3YiKSkKCmFpZGRhdGEuZmluYWwgPC0gYWlkZGF0YS5jbGVhbiAlPiUKICBsZWZ0X2pvaW4oZG9ub3JzLCBieSA9ICJkb25vciIpICU+JQogIGxlZnRfam9pbihyZWNpcGllbnRzLCBieSA9ICJyZWNpcGllbnQiKSAlPiUKICBsZWZ0X2pvaW4ocHVycG9zZS5jb2Rlcy5jb250ZW50aW91c25lc3MsIGJ5ID0gInB1cnBvc2UuY29kZS5zaG9ydCIpICU+JQogIG11dGF0ZShkb25vci50eXBlLmNvbGxhcHNlZCA9IGlmZWxzZShkb25vci50eXBlID09ICJDb3VudHJ5IiwgIkNvdW50cnkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSUdPLCBNdWx0aWxhdGVyYWwsIG9yIFByaXZhdGUiKSkgJT4lCiAgc2VsZWN0KGRvbm9yLCBkb25vci50eXBlLCBkb25vci50eXBlLmNvbGxhcHNlZCwKICAgICAgICAgZG9ub3IuY293Y29kZSwgZG9ub3IuaXNvMywgeWVhciwKICAgICAgICAgY291bnRyeS5uYW1lLCBjb3djb2RlLCBnd2NvZGUsIGlzbzIsIGlzbzMsCiAgICAgICAgIG9kYSA9IGNvbW1pdG1lbnRfYW1vdW50X3VzZF9jb25zdGFudF9zdW0sCiAgICAgICAgIHB1cnBvc2UuY29kZS5zaG9ydCwgcHVycG9zZS5zZWN0b3IsIHB1cnBvc2UuY2F0ZWdvcnksCiAgICAgICAgIHB1cnBvc2UuY29udGVudGlvdXNuZXNzLAogICAgICAgICBjb2FsZXNjZWRfcHVycG9zZV9jb2RlLCBjb2FsZXNjZWRfcHVycG9zZV9uYW1lKSAlPiUKICBhcnJhbmdlKGNvd2NvZGUsIHllYXIpCgpldmVyLmRhYy5lbGlnaWJsZSA8LSByZWFkX2NzdihoZXJlKCJEYXRhIiwgImRhdGFfbWFudWFsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm9lY2RfZGFjX2NvdW50cmllcy5jc3YiKSkgJT4lCiAgIyBJZ25vcmUgSGlnaCBJbmNvbWUgQ291bnRyaWVzIGFuZCBNb3JlIEFkdmFuY2VkIERldmVsb3BpbmcgQ291bnRyaWVzCiAgZmlsdGVyKCEoZGFjX2FiYnIgJWluJSBjKCJISUMiLCAiQURDIikpKSAlPiUKICBsZWZ0X2pvaW4oZ3cuY29kZXMsIGJ5ID0gImlzbzMiKSAlPiUKICBzZWxlY3QoY293Y29kZSkgJT4lIHVubGlzdCgpICU+JSBjKCkgJT4lIHVuaXF1ZSgpCmBgYAoKIyMjIyBMaXN0IG9mIGRvbm9ycwoKYGBge3Igc2hvdy1kb25vcnN9CmRvbm9ycyAlPiUgZGF0YXRhYmxlKCkKYGBgCgojIyMjIExpc3Qgb2YgcmVjaXBpZW50cwoKYGBge3Igc2hvdy1yZWNpcGllbnRzfQpzZWxlY3QocmVjaXBpZW50cywgcmVjaXBpZW50KSAlPiUgZGF0YXRhYmxlKCkKYGBgCgojIyMjIExpc3Qgb2YgcHVycG9zZXMKCmBgYHtyIHNob3ctcHVycG9zZXN9CmFycmFuZ2UocHVycG9zZXMsIGRlc2MobikpICU+JSBkYXRhdGFibGUoKQpgYGAKCiMjIyMgU3VtbWFyeSBvZiBjbGVhbiBkYXRhCgpgYGB7ciBhaWRkYXRhLXN1bW1hcnl9CmFpZGRhdGEuZmluYWwgJT4lIGdsaW1wc2UoKQpgYGAKCiMjIyBVU0FJRCB7LnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KClVTQUlEIHByb3ZpZGVzIHRoZSBjb21wbGV0ZSBkYXRhc2V0IGZvciBpdHMgW0ZvcmVpZ24gQWlkIEV4cGxvcmVyXShodHRwczovL2V4cGxvcmVyLnVzYWlkLmdvdi9haWQtZGFzaGJvYXJkLmh0bWwpIGFzIGEgW2dpYW50IENTViBmaWxlXShodHRwczovL2V4cGxvcmVyLnVzYWlkLmdvdi9kYXRhLmh0bWwpLiBUaGUgZGF0YSBpbmNsdWRlcyBib3RoIGVjb25vbWljIGFuZCBtaWxpdGFyeSBhaWQsIGJ1dCBpdCdzIGVhc3kgdG8gZmlsdGVyIG91dCB0aGUgbWlsaXRhcnkgYWlkLiBIZXJlIHdlIG9ubHkgbG9vayBhdCBvYmxpZ2F0aW9ucywgbm90IGRpc2J1cnNlbWVudHMsIHNvIHRoYXQgdGhlIGRhdGEgaXMgY29tcGFyYWJsZSB0byB0aGUgT0VDRCBkYXRhIGZyb20gQWlkRGF0YS4gVGhlIGRhdGEgd2UgZG93bmxvYWRlZCBwcm92aWRlcyBjb25zdGFudCBhbW91bnRzIGluIDIwMTUgZG9sbGFyczsgd2UgcmVzY2FsZSB0aGF0IHRvIDIwMTEgdG8gbWF0Y2ggYWxsIG90aGVyIHZhcmlhYmxlcy4gCgpgYGB7ciBsb2FkLXVzYWlkLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQp1c2FpZC51cmwgPC0gImh0dHBzOi8vZXhwbG9yZXIudXNhaWQuZ292L3ByZXBhcmVkL3VzX2ZvcmVpZ25fYWlkX2NvbXBsZXRlLmNzdiIKdXNhaWQucGF0aCA8LSBoZXJlKCJEYXRhIiwgImRhdGFfcmF3IiwgIlVTQUlEIikKdXNhaWQubmFtZSA8LSBiYXNlbmFtZSh1c2FpZC51cmwpCgojIERvd25sb2FkIFVTQUlEIGRhdGEgaWYgbmVlZGVkCmlmICghZmlsZS5leGlzdHMoZmlsZS5wYXRoKHVzYWlkLnBhdGgsIHVzYWlkLm5hbWUpKSkgewogIHVzYWlkLmdldCA8LSBHRVQodXNhaWQudXJsLCAKICAgICAgICAgICAgICAgICAgIHdyaXRlX2Rpc2soZmlsZS5wYXRoKHVzYWlkLnBhdGgsIHVzYWlkLm5hbWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVyd3JpdGUgPSBUUlVFKSwgCiAgICAgICAgICAgICAgICAgICBwcm9ncmVzcygpKQp9CgojIENsZWFuIHVwIFVTQUlEIGRhdGEKdXNhaWQucmF3IDwtIHJlYWRfY3N2KGZpbGUucGF0aCh1c2FpZC5wYXRoLCB1c2FpZC5uYW1lKSwKICAgICAgICAgICAgICAgICAgICAgIG5hID0gYygiIiwgIk5BIiwgIk5VTEwiKSwKICAgICAgICAgICAgICAgICAgICAgIGNvbF90eXBlcyA9IGNvbHMoCiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cnlfaWQgPSBjb2xfaW50ZWdlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBjb3VudHJ5X2NvZGUgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cnlfbmFtZSA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgcmVnaW9uX2lkID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgcmVnaW9uX25hbWUgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIGluY29tZV9ncm91cF9pZCA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIGluY29tZV9ncm91cF9uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBpbmNvbWVfZ3JvdXBfYWNyb255bSA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgaW1wbGVtZW50aW5nX2FnZW5jeV9pZCA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIGltcGxlbWVudGluZ19hZ2VuY3lfYWNyb255bSA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgaW1wbGVtZW50aW5nX2FnZW5jeV9uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBpbXBsZW1lbnRpbmdfc3ViYWdlbmN5X2lkID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgc3ViYWdlbmN5X2Fjcm9ueW0gPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIHN1YmFnZW5jeV9uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBjaGFubmVsX2NhdGVnb3J5X2lkID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgY2hhbm5lbF9jYXRlZ29yeV9uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBjaGFubmVsX3N1YmNhdGVnb3J5X2lkID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgY2hhbm5lbF9zdWJjYXRlZ29yeV9uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBjaGFubmVsX2lkID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgY2hhbm5lbF9uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBkYWNfY2F0ZWdvcnlfaWQgPSBjb2xfaW50ZWdlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBkYWNfY2F0ZWdvcnlfbmFtZSA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgZGFjX3NlY3Rvcl9jb2RlID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgZGFjX3NlY3Rvcl9uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBkYWNfcHVycG9zZV9jb2RlID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgZGFjX3B1cnBvc2VfbmFtZSA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgZnVuZGluZ19hY2NvdW50X2lkID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBmdW5kaW5nX2FjY291bnRfbmFtZSA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgZnVuZGluZ19hZ2VuY3lfaWQgPSBjb2xfaW50ZWdlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBmdW5kaW5nX2FnZW5jeV9uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBmdW5kaW5nX2FnZW5jeV9hY3JvbnltID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBhc3Npc3RhbmNlX2NhdGVnb3J5X2lkID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgYXNzaXN0YW5jZV9jYXRlZ29yeV9uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBhaWRfdHlwZV9ncm91cF9pZCA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIGFpZF90eXBlX2dyb3VwX25hbWUgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGl2aXR5X2lkID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgYWN0aXZpdHlfbmFtZSA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgYWN0aXZpdHlfcHJvamVjdF9udW1iZXIgPSBjb2xfY2hhcmFjdGVyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGl2aXR5X3N0YXJ0X2RhdGUgPSBjb2xfZGF0ZShmb3JtYXQgPSAiIiksCiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGl2aXR5X2VuZF9kYXRlID0gY29sX2RhdGUoZm9ybWF0ID0gIiIpLAogICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2FjdGlvbl90eXBlX2lkID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNhY3Rpb25fdHlwZV9uYW1lID0gY29sX2NoYXJhY3RlcigpLAogICAgICAgICAgICAgICAgICAgICAgICBmaXNjYWxfeWVhciA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudF9hbW91bnQgPSBjb2xfZG91YmxlKCksCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0YW50X2Ftb3VudCA9IGNvbF9kb3VibGUoKSwKICAgICAgICAgICAgICAgICAgICAgICAgVVNHX3NlY3Rvcl9pZCA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIFVTR19zZWN0b3JfbmFtZSA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgICAgc3VibWlzc2lvbl9pZCA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICAgIG51bWVyaWNfeWVhciA9IGNvbF9kb3VibGUoKQogICAgICAgICAgICAgICAgICAgICAgKSkKCnVzYWlkLmNsZWFuIDwtIHVzYWlkLnJhdyAlPiUKICBmaWx0ZXIoYXNzaXN0YW5jZV9jYXRlZ29yeV9uYW1lID09ICJFY29ub21pYyIpICU+JQogIGZpbHRlcih0cmFuc2FjdGlvbl90eXBlX25hbWUgPT0gIk9ibGlnYXRpb25zIikgJT4lCiAgbXV0YXRlKGNvdW50cnlfY29kZSA9IHJlY29kZShjb3VudHJ5X2NvZGUsIGBDUy1LTWAgPSAiWEtLIikpICU+JQogICMgUmVtb3ZlIHJlZ2lvbnMgYW5kIFdvcmxkCiAgZmlsdGVyKCFzdHJfZGV0ZWN0KGNvdW50cnlfbmFtZSwgIlJlZ2lvbiIpKSAlPiUKICBmaWx0ZXIoIShjb3VudHJ5X25hbWUgJWluJSBjKCJXb3JsZCIpKSkgJT4lCiAgbGVmdF9qb2luKGd3LmNvZGVzLCBieSA9IGMoImNvdW50cnlfY29kZSIgPSAiaXNvMyIpKSAlPiUKICAjIEdldCByaWQgb2YgdGlueSBhbmQgb2xkIHN0YXRlcwogIGZpbHRlcighaXMubmEoY293Y29kZSkpICU+JQogIHNlbGVjdChjb3djb2RlLCB5ZWFyID0gbnVtZXJpY195ZWFyLCAKICAgICAgICAgaW1wbGVtZW50aW5nX2FnZW5jeV9uYW1lLCBzdWJhZ2VuY3lfbmFtZSwgYWN0aXZpdHlfbmFtZSwKICAgICAgICAgY2hhbm5lbF9jYXRlZ29yeV9uYW1lLCBjaGFubmVsX3N1YmNhdGVnb3J5X25hbWUsIGRhY19zZWN0b3JfY29kZSwKICAgICAgICAgb2RhLnVzLmN1cnJlbnQgPSBjdXJyZW50X2Ftb3VudCwgb2RhLnVzLjIwMTUgPSBjb25zdGFudF9hbW91bnQpICU+JQogIG11dGF0ZShhaWQuZGVmbGF0b3IgPSBvZGEudXMuY3VycmVudCAvIG9kYS51cy4yMDE1ICogMTAwKSAlPiUKICBtdXRhdGUoY2hhbm5lbC5uZ28udXMgPSBjaGFubmVsX3N1YmNhdGVnb3J5X25hbWUgPT0gIk5HTyAtIFVuaXRlZCBTdGF0ZXMiLAogICAgICAgICBjaGFubmVsLm5nby5pbnQgPSBjaGFubmVsX3N1YmNhdGVnb3J5X25hbWUgPT0gIk5HTyAtIEludGVybmF0aW9uYWwiLAogICAgICAgICBjaGFubmVsLm5nby5kb20gPSBjaGFubmVsX3N1YmNhdGVnb3J5X25hbWUgPT0gIk5HTyAtIE5vbiBVbml0ZWQgU3RhdGVzIikKCiMgR2V0IHJpZCBvZiB0aGlzIGJlY2F1c2UgaXQncyBodWdlIGFuZCB0YWtpbmcgdXAgbG90cyBvZiBtZW1vcnkKcm0odXNhaWQucmF3KQpgYGAKCiMjIyMgSW1wbGVtZW50aW5nIGFnZW5jaWVzCgpIZXJlIGFyZSB0aGUgVVMgZ292ZXJubWVudCBhZ2VuY2llcyBnaXZpbmcgb3V0IG1vbmV5OgoKYGBge3Igc2hvdy1hZ2VuY2llc30KaW1wbGVtZW50aW5nLmFnZW5jaWVzIDwtIHVzYWlkLmNsZWFuICU+JQogIGNvdW50KGltcGxlbWVudGluZ19hZ2VuY3lfbmFtZSwgc3ViYWdlbmN5X25hbWUpICU+JQogIGFycmFuZ2UoZGVzYyhuKSwgaW1wbGVtZW50aW5nX2FnZW5jeV9uYW1lKQoKaW1wbGVtZW50aW5nLmFnZW5jaWVzICU+JSBkYXRhdGFibGUoKQpgYGAKCiMjIyMgQWN0aXZpdGllcwoKVGhlIGFjdGl2aXRpZXMgbGlzdGVkIGRvbid0IGZvbGxvdyBhbnkgc3RhbmRhcmQgY29kaW5nIGd1aWRlbGluZXMuIFRoZXJlIGFyZSB0ZW5zIG9mIHRob3VzYW5kcyBvZiB0aGVtLiBIZXJlIGFyZSB0aGUgZmlyc3QgMTAwLCBqdXN0IGZvciByZWZlcmVuY2U6CgpgYGB7ciBzaG93LWFjdGl2aXRpZXN9CmFjdGl2aXRpZXMgPC0gdXNhaWQuY2xlYW4gJT4lCiAgY291bnQoYWN0aXZpdHlfbmFtZSkgJT4lCiAgc2xpY2UoMToxMDApCgphY3Rpdml0aWVzICU+JSBkYXRhdGFibGUoKQpgYGAKCiMjIyMgQ2hhbm5lbHMKClVTQUlEIGRpc3Rpbmd1aXNoZXMgYmV0d2VlbiBkb21lc3RpYywgZm9yZWlnbiwgYW5kIGludGVybmF0aW9uYWwgTkdPcywgY29tcGFuaWVzLCBtdWx0aWxhdGVyYWwgb3JnYW5pemF0aW9ucywgZXRjLiByZWNpcGllbnRzIChvciBjaGFubmVscykgb2YgbW9uZXk6CgpgYGB7ciBzaG93LWNoYW5uZWxzfQpjaGFubmVscyA8LSB1c2FpZC5jbGVhbiAlPiUKICBjb3VudChjaGFubmVsX2NhdGVnb3J5X25hbWUsIGNoYW5uZWxfc3ViY2F0ZWdvcnlfbmFtZSkgJT4lCiAgZmlsdGVyKCFpcy5uYShjaGFubmVsX2NhdGVnb3J5X25hbWUpKQoKY2hhbm5lbHMgJT4lIGRhdGF0YWJsZShvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMjApKQpgYGAKCiMjIyMgU3VtbWFyeSBvZiBjbGVhbiBkYXRhCgpgYGB7ciB1c2FpZC1zdW1tYXJ5fQp1c2FpZC5jbGVhbiAlPiUgZ2xpbXBzZSgpCmBgYAoKCiMjIE5HTyByZWd1bGF0aW9ucwoKIyMjIE5HTyBsZWdpc2xhdGlvbgoKSW4gMjAxMywgRGFyaW4gQ2hyaXN0ZW5zZW4gYW5kIEplcmVteSBXZWluc3RlaW4gY29sbGVjdGVkIFtkZXRhaWxlZCBkYXRhXShodHRwczovL2RhcmluY2hyaXN0ZW5zZW4uZ2l0aHViLmlvL3Jlc2VhcmNoLyNwcm90ZXN0LWFuZC1yZXByZXNzaW9uKSBvbiBOR08gcmVndWxhdGlvbnMgZm9yIFt0aGVpciAqSm91cm5hbCBvZiBEZW1vY3JhY3kqIGFydGljbGVdKGh0dHA6Ly93d3cuam91cm5hbG9mZGVtb2NyYWN5Lm9yZy9hcnRpY2xlL2RlZnVuZGluZy1kaXNzZW50LXJlc3RyaWN0aW9ucy1haWQtbmdvcykuIFN1cGFybmEgQ2hhdWRocnkgZXhwYW5kZWQgdGhpcyBkYXRhIGFzIHBhcnQgb2YgaGVyIGRpc3NlcnRhdGlvbiByZXNlYXJjaCwgYnV0IHdhbnRzIGhlciBkYXRhIGVtYmFyZ29lZCB1bnRpbCBzb21lIG9mIGhlciB3b3JrIGlzIHB1YmxzaWhlZC4gVG8gcHJldmVudCBkYXRhIGxlYWthZ2UsIHRoZSBjb2RlIHRvIG1ha2UgbWlub3IgbWFudWFsIGFkanVzdG1lbnRzIGlzIGluY2x1ZGVkIGluIGFuIHVudHJhY2tlZCBmaWxlIGFuZCBub3QgbWFkZSBwdWJsaWMuCgpUaGUgY29kZSBiZWxvdyB3aWxsIHN0aWxsIHdvcmsgb24gdGhlIG9yaWdpbmFsIENocmlzdGVuc2VuIGFuZCBXZWluc3RlaW4gZGF0YSwgYnV0IGl0IHdpbGwgKG9idmlvdXNseSkgbm90IGluY2x1ZGUgQ2hhdWRocnkncyBleHBhbmRlZCBkYXRhLgoKYGBge3IgbG9hZC1kY2p3LCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIE9yaWdpbmFsIERDSlcgZGF0YQpkY2p3Lm9yaWcucGF0aCA8LSBoZXJlKCJEYXRhIiwgImRhdGFfcmF3IiwgIkRDSlcgTkdPIExhd3MiLCAiRENKV19OR09fTGF3cy54bHN4IikKCmRjancub3JpZyA8LSByZWFkX2V4Y2VsKGRjancub3JpZy5wYXRoKVssMTo1MF0gJT4lCiAgc2VsZWN0KC1jKGRwbHlyOjpjb250YWlucygic291cmNlIiksIGRwbHlyOjpjb250YWlucygiYnVyZGVuIiksIAogICAgICAgICAgICBkcGx5cjo6Y29udGFpbnMoInN1YnNldCIpLCBDb2RlciwgRGF0ZSkpCgoKIyBUaWR5IERDSlcgZGF0YQpkY2p3LnBhdGggPC0gaGVyZSgiRGF0YSIsICJkYXRhX3JhdyIsICJEQ0pXIE5HTyBMYXdzIiwgIkFkbW4gQ3JhY2tkb3duX3VwZGF0ZWQueGxzeCIpCgpkY2p3LnF1ZXN0aW9ucy5yYXcgPC0gcmVhZF9jc3YoaGVyZSgiRGF0YSIsICJkYXRhX21hbnVhbCIsICJkY2p3X3F1ZXN0aW9ucy5jc3YiKSkKCmRjancuYmFycmllcnMuY2xlYW4gPC0gZGNqdy5xdWVzdGlvbnMucmF3ICU+JQogIGRpc3RpbmN0KHF1ZXN0aW9uX2NhdCwgYmFycmllcikKCmRjancuYmFycmllcnMuaWdub3JlIDwtIGRjancucXVlc3Rpb25zLnJhdyAlPiUKICBzZWxlY3QocXVlc3Rpb24sIGlnbm9yZV9pbl9pbmRleCkKCmRjancgPC0gcmVhZF9leGNlbChkY2p3LnBhdGgpWywxOjUwXSAlPiUKICBzZWxlY3QoLWMoZHBseXI6OmNvbnRhaW5zKCJzb3VyY2UiKSwgZHBseXI6OmNvbnRhaW5zKCJidXJkZW4iKSwgCiAgICAgICAgICAgIGRwbHlyOjpjb250YWlucygic3Vic2V0IiksIENvZGVyLCBEYXRlKSkgJT4lCiAgZ2F0aGVyKGtleSwgdmFsdWUsIC1Db3VudHJ5KSAlPiUKICBzZXBhcmF0ZShrZXksIGMoInF1ZXN0aW9uIiwgInZhci5uYW1lIiksIDQpICU+JQogIGZpbHRlcighaXMubmEoQ291bnRyeSkpICU+JQogIG11dGF0ZSh2YXIubmFtZSA9IGlmZWxzZSh2YXIubmFtZSA9PSAiIiwgInZhbHVlIiwgZ3N1YigiXyIsICIiLCB2YXIubmFtZSkpKSAlPiUKICBzcHJlYWQodmFyLm5hbWUsIHZhbHVlKSAlPiUKICAjIEdldCByaWQgb2Ygcm93cyB3aGVyZSB5ZWFyIGlzIG1pc3NpbmcgYW5kIHJlZ3VsYXRpb24gd2FzIG5vdCBpbXBvc2VkCiAgZmlsdGVyKCEoaXMubmEoeWVhcikgJiB2YWx1ZSA9PSAwKSkgJT4lCiAgIyBTb21lIGVudHJpZXMgaGF2ZSBtdWx0aXBsZSB5ZWFyczsgZm9yIG5vdyBqdXN0IHVzZSB0aGUgZmlyc3QgeWVhcgogIG11dGF0ZSh5ZWFyID0gc3RyX3NwbGl0KHllYXIsICIsIikpICU+JSB1bm5lc3QoeWVhcikgJT4lIAogIGdyb3VwX2J5KENvdW50cnksIHF1ZXN0aW9uKSAlPiUgc2xpY2UoMSkgJT4lIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUodmFsdWUgPSBhcy5pbnRlZ2VyKHZhbHVlKSwgeWVhciA9IGFzLmludGVnZXIoeWVhcikpICU+JQogICMgSWYgeWVhciBpcyBtaXNzaW5nIGJ1dCBzb21lIHJlZ3VsYXRpb24gZXhpc3RzLCBhc3N1bWUgaXQgaGFzIGFsd2F5cyBhbHJlYWR5CiAgIyBleGlzdGVkIChzaW5jZSAxOTUwLCBhcmJpdHJhcmlseSkKICBtdXRhdGUoeWVhciA9IGlmZWxzZShpcy5uYSh5ZWFyKSwgMTk1MCwgeWVhcikpCgpwb3RlbnRpYWwuZGNqdy5wYW5lbC5xdWVzdGlvbiA8LSBkY2p3ICU+JQogIHRpZHlyOjpleHBhbmQoQ291bnRyeSwgcXVlc3Rpb24sIAogICAgICAgICAgICAgICAgeWVhciA9IG1pbiguJHllYXIsIG5hLnJtID0gVFJVRSk6MjAxNSkKCmRjancucGFuZWwuYWxsLmxhd3MgPC0gZGNqdyAlPiUKICByaWdodF9qb2luKHBvdGVudGlhbC5kY2p3LnBhbmVsLnF1ZXN0aW9uLAogICAgICAgICAgICAgYnkgPSBjKCJDb3VudHJ5IiwgInF1ZXN0aW9uIiwgInllYXIiKSkKCiMgU3VwYXJuYSBDaGF1ZHJ5IHVwZGF0ZWQgdGhlIG9yaWdpbmFsIERDSlcgZGF0YSwgYnV0IHdhbnRzIHRoZSBkYXRhIGVtYmFyZ29lZCAKIyB1bnRpbCBzb21lIG9mIGhlciBkaXNzZXJ0YXRpb24gaXMgcHVibGlzaGVkLiBUbyBwcmV2ZW50IGRhdGEgbGVha2FnZSBvbnRvIHRoZQojIGludGVybmV0LCBtaW5vciBtYW51YWwgYWRqdXN0bWVudHMgYXJlIGluY2x1ZGVkIGluIGEgaGlkZGVuIGZpbGUgaGVyZSBpbnN0ZWFkCiMgb2YgdGhpcyBtYWluIGZpbGUuCnNvdXJjZShoZXJlKCJEYXRhIiwgImRhdGFfcmF3IiwgIkRDSlcgTkdPIExhd3MiLCAiY2hhdWRocnlfbWFudWFsX2NoYW5nZXMuUiIpKQoKaWYgKGFsbC5uYS5tZWFucy56ZXJvKSB7CiAgZGNqdy5wYW5lbC5hbGwubGF3cyA8LSBkY2p3LnBhbmVsLmFsbC5sYXdzICU+JQogICAgZ3JvdXBfYnkoQ291bnRyeSwgcXVlc3Rpb24pICU+JQogICAgIyBCcmluZyBtb3N0IHJlY2VudCBsZWdpc2xhdGlvbiBmb3J3YXJkCiAgICBtdXRhdGUodmFsdWUgPSB6b286Om5hLmxvY2YodmFsdWUsIG5hLnJtID0gRkFMU0UpKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgICMgU2V0IGRlZmF1bHRzIGZvciBjb2x1bW5zIHRoYXQgYXJlbid0IGFsbCBOQQogICAgIyBJIGNvdWxkIGJlIGZhbmN5IGFuZCBjb25zb2xpZGF0ZSB0aGVzZSBjb25kaXRpb25hbHMgaW50byBqdXN0IG9uZSwgYnV0IHRoaXMKICAgICMgZ2l2ZXMgdXMgbW9yZSBmbGV4aWJpbGl0eSB0byBzZXQgZGlmZmVyZW50IGRlZmF1bHRzIHBlciBsYXcgKGxpa2UgaG93IHFfMmIKICAgICMgb3IgcV80YyBtaWdodCBiZSBiZXR0ZXIgYXMgTkFfaW50ZWdlcl8gaW5zdGVhZCBvZiAwKQogICAgbXV0YXRlKHZhbHVlLmZpeGVkID0gY2FzZV93aGVuKAogICAgICBpcy5uYSguJHZhbHVlKSAmIC4kcXVlc3Rpb24gPT0gInFfMWEiIH4gMEwsCiAgICAgIGlzLm5hKC4kdmFsdWUpICYgLiRxdWVzdGlvbiA9PSAicV8xYiIgfiAwTCwKICAgICAgaXMubmEoLiR2YWx1ZSkgJiAuJHF1ZXN0aW9uID09ICJxXzJhIiB+IDBMLAogICAgICBpcy5uYSguJHZhbHVlKSAmIC4kcXVlc3Rpb24gPT0gInFfMmIiIH4gMEwsCiAgICAgIGlzLm5hKC4kdmFsdWUpICYgLiRxdWVzdGlvbiA9PSAicV8yYyIgfiAwTCwKICAgICAgaXMubmEoLiR2YWx1ZSkgJiAuJHF1ZXN0aW9uID09ICJxXzJkIiB+IDBMLAogICAgICBpcy5uYSguJHZhbHVlKSAmIC4kcXVlc3Rpb24gPT0gInFfM2EiIH4gMEwsCiAgICAgIGlzLm5hKC4kdmFsdWUpICYgLiRxdWVzdGlvbiA9PSAicV8zYiIgfiAwTCwKICAgICAgaXMubmEoLiR2YWx1ZSkgJiAuJHF1ZXN0aW9uID09ICJxXzNjIiB+IDBMLAogICAgICBpcy5uYSguJHZhbHVlKSAmIC4kcXVlc3Rpb24gPT0gInFfM2QiIH4gMEwsCiAgICAgIGlzLm5hKC4kdmFsdWUpICYgLiRxdWVzdGlvbiA9PSAicV8zZSIgfiAwTCwKICAgICAgaXMubmEoLiR2YWx1ZSkgJiAuJHF1ZXN0aW9uID09ICJxXzNmIiB+IDBMLAogICAgICBpcy5uYSguJHZhbHVlKSAmIC4kcXVlc3Rpb24gPT0gInFfNGEiIH4gMEwsCiAgICAgIGlzLm5hKC4kdmFsdWUpICYgLiRxdWVzdGlvbiA9PSAicV80YiIgfiAwTCwKICAgICAgaXMubmEoLiR2YWx1ZSkgJiAuJHF1ZXN0aW9uID09ICJxXzRjIiB+IDBMLAogICAgICBUUlVFIH4gLiR2YWx1ZQogICAgKSkgJT4lCiAgICBzZWxlY3QoLXZhbHVlKSAlPiUKICAgIHNwcmVhZChxdWVzdGlvbiwgdmFsdWUuZml4ZWQpICU+JQogICAgdW5ncm91cCgpCn0gZWxzZSB7CiAgZGNqdy5wYW5lbC5hbGwubGF3cyA8LSBkY2p3LnBhbmVsLmFsbC5sYXdzICU+JQogICAgZ3JvdXBfYnkoQ291bnRyeSwgcXVlc3Rpb24pICU+JQogICAgIyBCcmluZyBtb3N0IHJlY2VudCBsZWdpc2xhdGlvbiBmb3J3YXJkCiAgICBtdXRhdGUodmFsdWUgPSB6b286Om5hLmxvY2YodmFsdWUsIG5hLnJtID0gRkFMU0UpKSAlPiUKICAgIG11dGF0ZShub3QuYWxsLm5hID0gIWFsbChpcy5uYSh2YWx1ZSkpKSAlPiUKICAgIHVuZ3JvdXAoKSAlPiUKICAgICMgU2V0IGRlZmF1bHRzIGZvciBjb2x1bW5zIHRoYXQgYXJlbid0IGFsbCBOQQogICAgIyBJIGNvdWxkIGJlIGZhbmN5IGFuZCBjb25zb2xpZGF0ZSB0aGVzZSBjb25kaXRpb25hbHMgaW50byBqdXN0IG9uZSwgYnV0IHRoaXMKICAgICMgZ2l2ZXMgdXMgbW9yZSBmbGV4aWJpbGl0eSB0byBzZXQgZGlmZmVyZW50IGRlZmF1bHRzIHBlciBsYXcgKGxpa2UgaG93IHFfMmIKICAgICMgb3IgcV80YyBtaWdodCBiZSBiZXR0ZXIgYXMgTkFfaW50ZWdlcl8gaW5zdGVhZCBvZiAwKQogICAgbXV0YXRlKHZhbHVlLmZpeGVkID0gY2FzZV93aGVuKAogICAgICAuJG5vdC5hbGwubmEgJiBpcy5uYSguJHZhbHVlKSAmIC4kcXVlc3Rpb24gPT0gInFfMWEiIH4gMEwsCiAgICAgIC4kbm90LmFsbC5uYSAmIGlzLm5hKC4kdmFsdWUpICYgLiRxdWVzdGlvbiA9PSAicV8xYiIgfiAwTCwKICAgICAgLiRub3QuYWxsLm5hICYgaXMubmEoLiR2YWx1ZSkgJiAuJHF1ZXN0aW9uID09ICJxXzJhIiB+IDBMLAogICAgICAuJG5vdC5hbGwubmEgJiBpcy5uYSguJHZhbHVlKSAmIC4kcXVlc3Rpb24gPT0gInFfMmIiIH4gMEwsCiAgICAgIC4kbm90LmFsbC5uYSAmIGlzLm5hKC4kdmFsdWUpICYgLiRxdWVzdGlvbiA9PSAicV8yYyIgfiAwTCwKICAgICAgLiRub3QuYWxsLm5hICYgaXMubmEoLiR2YWx1ZSkgJiAuJHF1ZXN0aW9uID09ICJxXzJkIiB+IDBMLAogICAgICAuJG5vdC5hbGwubmEgJiBpcy5uYSguJHZhbHVlKSAmIC4kcXVlc3Rpb24gPT0gInFfM2EiIH4gMEwsCiAgICAgIC4kbm90LmFsbC5uYSAmIGlzLm5hKC4kdmFsdWUpICYgLiRxdWVzdGlvbiA9PSAicV8zYiIgfiAwTCwKICAgICAgLiRub3QuYWxsLm5hICYgaXMubmEoLiR2YWx1ZSkgJiAuJHF1ZXN0aW9uID09ICJxXzNjIiB+IDBMLAogICAgICAuJG5vdC5hbGwubmEgJiBpcy5uYSguJHZhbHVlKSAmIC4kcXVlc3Rpb24gPT0gInFfM2QiIH4gMEwsCiAgICAgIC4kbm90LmFsbC5uYSAmIGlzLm5hKC4kdmFsdWUpICYgLiRxdWVzdGlvbiA9PSAicV8zZSIgfiAwTCwKICAgICAgLiRub3QuYWxsLm5hICYgaXMubmEoLiR2YWx1ZSkgJiAuJHF1ZXN0aW9uID09ICJxXzNmIiB+IDBMLAogICAgICAuJG5vdC5hbGwubmEgJiBpcy5uYSguJHZhbHVlKSAmIC4kcXVlc3Rpb24gPT0gInFfNGEiIH4gMEwsCiAgICAgIC4kbm90LmFsbC5uYSAmIGlzLm5hKC4kdmFsdWUpICYgLiRxdWVzdGlvbiA9PSAicV80YiIgfiAwTCwKICAgICAgLiRub3QuYWxsLm5hICYgaXMubmEoLiR2YWx1ZSkgJiAuJHF1ZXN0aW9uID09ICJxXzRjIiB+IDBMLAogICAgICBUUlVFIH4gLiR2YWx1ZQogICAgKSkgJT4lCiAgICBzZWxlY3QoLW5vdC5hbGwubmEsIC12YWx1ZSkgJT4lCiAgICBzcHJlYWQocXVlc3Rpb24sIHZhbHVlLmZpeGVkKSAlPiUKICAgIHVuZ3JvdXAoKQp9Cgpwb3RlbnRpYWwuZGNqdy5wYW5lbC5iYXJyaWVyIDwtIHBvdGVudGlhbC5kY2p3LnBhbmVsLnF1ZXN0aW9uICU+JQogIG11dGF0ZShxdWVzdGlvbl9jYXQgPSBhcy5pbnRlZ2VyKHN1YnN0cihxdWVzdGlvbiwgMywgMykpKSAlPiUKICBsZWZ0X2pvaW4oZGNqdy5iYXJyaWVycy5jbGVhbiwgYnkgPSAicXVlc3Rpb25fY2F0IikgJT4lCiAgZGlzdGluY3QoQ291bnRyeSwgeWVhciwgYmFycmllcikKCmRjancucGFuZWwuYmFycmllcnMgPC0gZGNqdy5wYW5lbC5hbGwubGF3cyAlPiUKICBnYXRoZXIocXVlc3Rpb24sIHZhbHVlLCAtQ291bnRyeSwgLXllYXIpICU+JQogIG11dGF0ZShxdWVzdGlvbl9jYXQgPSBhcy5pbnRlZ2VyKHN1YnN0cihxdWVzdGlvbiwgMywgMykpKSAlPiUKICBsZWZ0X2pvaW4oZGNqdy5iYXJyaWVycy5jbGVhbiwgYnkgPSAicXVlc3Rpb25fY2F0IikgJT4lCiAgIyBNYWtlIGFuIGluZGV4IGZvciBlYWNoIHR5cGUgb2YgYmFycmllcgogIG11dGF0ZSh2YWx1ZSA9IGFzLm51bWVyaWModmFsdWUpKSAlPiUKICBtdXRhdGUodmFsdWUgPSBjYXNlX3doZW4oCiAgICAjIFJldmVyc2UgdmFsdWVzIGZvciBhc3NvY2lhdGlvbmFsIHJpZ2h0cwogICAgLiRxdWVzdGlvbiA9PSAicV8xYSIgJiAuJHZhbHVlID09IDAgfiAxLAogICAgLiRxdWVzdGlvbiA9PSAicV8xYSIgJiAuJHZhbHVlID09IDEgfiAwLAogICAgLiRxdWVzdGlvbiA9PSAicV8xYiIgJiAuJHZhbHVlID09IDAgfiAxLAogICAgLiRxdWVzdGlvbiA9PSAicV8xYiIgJiAuJHZhbHVlID09IDEgfiAwLAogICAgIyBSZXZlcnNlIHZhbHVlIGZvciBxXzJjCiAgICAuJHF1ZXN0aW9uID09ICJxXzJjIiAmIC4kdmFsdWUgPT0gMCB+IDEsCiAgICAuJHF1ZXN0aW9uID09ICJxXzJjIiAmIC4kdmFsdWUgPT0gMSB+IDAsCiAgICAjIFJlY29kZSAwLTIgcXVlc3Rpb25zIGFzIDAtMQogICAgLiRxdWVzdGlvbiA9PSAicV8zZSIgJiAuJHZhbHVlID09IDEgfiAwLjUsCiAgICAuJHF1ZXN0aW9uID09ICJxXzNlIiAmIC4kdmFsdWUgPT0gMiB+IDEsCiAgICAuJHF1ZXN0aW9uID09ICJxXzNmIiAmIC4kdmFsdWUgPT0gMSB+IDAuNSwKICAgIC4kcXVlc3Rpb24gPT0gInFfM2YiICYgLiR2YWx1ZSA9PSAyIH4gMSwKICAgIC4kcXVlc3Rpb24gPT0gInFfNGEiICYgLiR2YWx1ZSA9PSAxIH4gMC41LAogICAgLiRxdWVzdGlvbiA9PSAicV80YSIgJiAuJHZhbHVlID09IDIgfiAxLAogICAgVFJVRSB+IC4kdmFsdWUKICApKSAlPiUKICAjIElnbm9yZSBuZXV0cmFsIGluZGV4ZXMsIGxpa2UgYmFzaWMgcmVnaXN0cmF0aW9uIHJlcXVpcmVtZW50cwogIGxlZnRfam9pbihkY2p3LmJhcnJpZXJzLmlnbm9yZSwgYnkgPSAicXVlc3Rpb24iKSAlPiUKICBtdXRhdGUodmFsdWVfcmVzdHJpY3RpdmUgPSBpZmVsc2UoaWdub3JlX2luX2luZGV4LCAwLCB2YWx1ZSkpICU+JQogIGdyb3VwX2J5KENvdW50cnksIHllYXIsIGJhcnJpZXIpICU+JQogICMgQWRkIHVwIGFsbCB0aGUgYmFycmllcnMgZm9yIGVhY2ggY291bnRyeSB5ZWFyCiAgIyBVc2UgYSBmbG9vciBvZiB6ZXJvIHRvIGFjY291bnQgZm9yIG5lZ2F0aXZlIHZhbHVlcwogIHN1bW1hcmlzZShhbGwgPSBzdW0odmFsdWUsIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgIHJlc3RyaWN0aXZlID0gc3VtKHZhbHVlX3Jlc3RyaWN0aXZlLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBtdXRhdGVfYXQodmFycyhhbGwsIHJlc3RyaWN0aXZlKSwKICAgICAgICAgICAgZnVucyhpZmVsc2UoLiA8IDAsIGFzLmludGVnZXIoMCksIC4pKSkgJT4lCiAgIyBKb2luIHdpdGggZnVsbCBwb3NzaWJsZSBwYW5lbAogIHJpZ2h0X2pvaW4ocG90ZW50aWFsLmRjancucGFuZWwuYmFycmllciwKICAgICAgICAgICAgIGJ5ID0gYygiQ291bnRyeSIsICJiYXJyaWVyIiwgInllYXIiKSkgJT4lCiAgZ2F0aGVyKHRlbXAsIHZhbHVlLCBhbGwsIHJlc3RyaWN0aXZlKSAlPiUKICB1bml0ZSh0ZW1wMSwgYmFycmllciwgdGVtcCwgc2VwID0gIl8iKSAlPiUKICBzcHJlYWQodGVtcDEsIHZhbHVlKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgIyBUYWtlICJfcmVzdHJpY3RpdmUiIG91dCBvZiB0aGUgdmFyaWFibGUgbmFtZXMuIAogICMgImVudHJ5IiA9IGFsbCByZXN0cmljdGl2ZSBlbnRyeSBsYXdzLCAiZW50cnlfYWxsIiA9IGFsbCBlbnRyeSBsYXdzCiAgcmVuYW1lXyguZG90cyA9IHNldE5hbWVzKHBhc3RlMCh1bmlxdWUoZGNqdy5xdWVzdGlvbnMucmF3JGJhcnJpZXIpLCAiX3Jlc3RyaWN0aXZlIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaXF1ZShkY2p3LnF1ZXN0aW9ucy5yYXckYmFycmllcikpKSAlPiUKICAjIFN0YW5kYXJkaXplIGJhcnJpZXIgaW5kZXhlcyBieSBkaXZpZGluZyBieSBtYXhpbXVtIG51bWJlciBwb3NzaWJsZQogIG11dGF0ZV9hdCh2YXJzKGVudHJ5LCBmdW5kaW5nLCBhZHZvY2FjeSksCiAgICAgICAgICAgIGZ1bnMoc3RkID0gLiAvIG1heCguKSkpICU+JSAKICBtdXRhdGUoYmFycmllcnMudG90YWwgPSBhZHZvY2FjeSArIGVudHJ5ICsgZnVuZGluZywKICAgICAgICAgYmFycmllcnMudG90YWxfc3RkID0gYWR2b2NhY3lfc3RkICsgZW50cnlfc3RkICsgZnVuZGluZ19zdGQpCgpkY2p3LmZ1bGwgPC0gZGNqdy5wYW5lbC5hbGwubGF3cyAlPiUKICBsZWZ0X2pvaW4oZGNqdy5wYW5lbC5iYXJyaWVycywgYnkgPSBjKCJDb3VudHJ5IiwgInllYXIiKSkgJT4lCiAgIyBMb3Agb2ZmIHRoZSBhbmNpZW50IG9ic2VydmF0aW9ucwogIGZpbHRlcih5ZWFyID4gMTk4MCkgJT4lCiAgIyBSZW5hbWUgcV8qIHZhcmlhYmxlcwogIHJlbmFtZV8oLmRvdHMgPSBzZXROYW1lcyhkY2p3LnF1ZXN0aW9ucy5yYXckcXVlc3Rpb24sIAogICAgICAgICAgICAgICAgICAgICAgICAgICBkY2p3LnF1ZXN0aW9ucy5yYXckcXVlc3Rpb25fY2xlYW4pKSAlPiUKICAjIEFkZCBhZGRpdGlvbmFsIHZhcmlhYmxlcwogIG11dGF0ZShDb3VudHJ5ID0gY291bnRyeWNvZGUoQ291bnRyeSwgImNvdW50cnkubmFtZSIsICJjb3VudHJ5Lm5hbWUiKSwKICAgICAgICAgY293Y29kZSA9IGNvdW50cnljb2RlKENvdW50cnksICJjb3VudHJ5Lm5hbWUiLCAiY293biIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXN0b21fbWF0Y2ggPSBjKFNlcmJpYSA9IDM0MCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVmlldG5hbSA9IDgxNikpKSAlPiUKICBzZWxlY3QoY291bnRyeS5uYW1lID0gQ291bnRyeSwgY293Y29kZSwgeWVhciwgZXZlcnl0aGluZygpKQpgYGAKCkNoYXVkaHJ5J3MgZGF0YSBhdWdtZW50cyBDaHJpc3RlbnNlbiBhbmQgV2VpbnN0ZWluJ3MgZGF0YSBzdWJzdGFudGlhbGx5LiBDaHJpc3RlbnNlbiBhbmQgV2VpbnN0ZWluIGluY2x1ZGUgaW5mb3JtYXRpb24gZm9yIGByIG5yb3coZGNqdy5vcmlnKWAgY291bnRyaWVzLCB3aGlsZSBDaGF1ZGhyeSBpbmNsdWRlcyBgciBsZW5ndGgodW5pcXVlKGRjancuZnVsbCRjb3VudHJ5Lm5hbWUpKWAgY291bnRyaWVzLgoKSW4gYWRkaXRpb24gdG8gcGFuZWwgZGF0YSBvbiB0aGUgcHJlc2VuY2Ugb3IgYWJzZW5jZSBvZiBzcGVjaWZpYyBOR08gcmVndWxhdGlvbnMsIHdlIGNyZWF0ZSBzZXZlcmFsIGluZGV4ZXMgZm9yIGVhY2ggb2YgdGhlIGNhdGVnb3JpZXMgb2YgcmVndWxhdGlvbiwgW2ZvbGxvd2luZyBDaHJpc3RlbnNlbiBhbmQgV2VpbnN0ZWluJ3MgY2xhc3NpZmljYXRpb25dKGh0dHBzOi8vZGFyaW5jaHJpc3RlbnNlbi5naXRodWIuaW8vRGF0YS9EQ0pXX0NvZGVib29rLnBkZik6CgotIGBlbnRyeWAgKFEyYiwgUTJjLCBRMmQ7IDMgcG9pbnRzIG1heGltdW0sIGFjdHVhbCBtYXggPSBgciBtYXgoZGNqdy5mdWxsJGVudHJ5KWAgcG9pbnRzIG1heGltdW0pOiBiYXJyaWVycyB0byBlbnRyeQogICAgLSBRMmMgaXMgcmV2ZXJzZWQsIHNvICpub3QqIGJlaW5nIGFsbG93ZWQgdG8gYXBwZWFsIHJlZ2lzdHJhdGlvbiBzdGF0dXMgZWFybnMgMSBwb2ludC4KICAgIC0gUTJhIGlzIG9taXR0ZWQgYmVjYXVzZSBpdCdzIGJlbmlnbgotIGBmdW5kaW5nYCAoUTNiLCBRM2MsIFEzZCwgUTNlLCBRM2Y7IDUgcG9pbnRzIG1heGltdW0sIGFjdHVhbCBtYXggPSBgciBtYXgoZGNqdy5mdWxsJGZ1bmRpbmcpYCk6IGJhcnJpZXJzIHRvIGZ1bmRpbmcKICAgIC0gUTNhIGlzIG9taXR0ZWQgYmVjYXVzZSBpdCdzIGJlbmlnbgogICAgLSBTY29yZXMgdGhhdCByYW5nZSBiZXR3ZWVuIDDigJMyIGFyZSByZXNjYWxlZCB0byAw4oCTMSAoc28gMSBiZWNvbWVzIDAuNSkKLSBgYWR2b2NhY3lgIChRNGEsIFE0YzsgMiBwb2ludHMgbWF4aW11bSwgYWN0dWFsIG1heCA9IGByIG1heChkY2p3LmZ1bGwkYWR2b2NhY3kpYCk6IGJhcnJpZXJzIHRvIGFkdm9jYWN5CiAgICAtIFE0YiBpcyBvbWl0dGVkIGJlY2F1c2UgaXQncyBub3QgYSBsYXcKICAgIC0gU2NvcmVzIHRoYXQgcmFuZ2UgYmV0d2VlbiAw4oCTMiBhcmUgcmVzY2FsZWQgdG8gMOKAkzEgKHNvIDEgYmVjb21lcyAwLjUpCi0gYGJhcnJpZXJzLnRvdGFsYCAoMTAgcG9pbnRzIG1heGltdW0sIGFjdHVhbCBtYXggPSBgciBtYXgoZGNqdy5mdWxsJGJhcnJpZXJzLnRvdGFsKWApOiBzdW0gb2YgYWxsIHRocmVlIGluZGV4ZXMKClRoZXNlIGluZGV4ZXMgYXJlIGFsc28gc3RhbmRhcmRpemVkIGJ5IGRpdmlkaW5nIGJ5IHRoZSBtYXhpbXVtLCB5aWVsZGluZyB0aGUgZm9sbG93aW5nIHZhcmlhYmxlczoKCi0gYGVudHJ5X3N0ZGA6IDEgcG9pbnQgbWF4aW11bSwgYWN0dWFsIG1heCA9IGByIG1heChkY2p3LmZ1bGwkZW50cnlfc3RkKWAKLSBgZnVuZGluZ19zdGRgOiAxIHBvaW50IG1heGltdW0sIGFjdHVhbCBtYXggPSBgciBtYXgoZGNqdy5mdWxsJGZ1bmRpbmdfc3RkKWAKLSBgYWR2b2NhY3lfc3RkYDogMSBwb2ludCBtYXhpbXVtLCBhY3R1YWwgbWF4ID0gYHIgbWF4KGRjancuZnVsbCRhZHZvY2FjeV9zdGQpYAotIGBiYXJyaWVycy50b3RhbF9zdGRgOiAzIHBvaW50cyBtYXhpbXVtLCBhY3R1YWwgbWF4ID0gYHIgbWF4KGRjancuZnVsbCRiYXJyaWVycy50b3RhbF9zdGQpYAoKYGBge3IgZGNqdy1nbGltcHNlfQpkY2p3LmZ1bGwgJT4lIGdsaW1wc2UoKQpgYGAKCiMjIyBDaXZpbCBzb2NpZXR5IHJlZ3VsYXRvcnkgZW52aXJvbm1lbnQgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpBbiBhbHRlcm5hdGl2ZSB3YXkgb2YgbWVhc3VyaW5nIGNpdmlsIHNvY2lldHkgcmVzdHJpY3Rpb25zIGlzIHRvIGxvb2sgYXQgdGhlIG92ZXJhbCBjaXZpbCBzb2NpZXR5IHJlZ3VsYXRvcnkgZW52aXJvbm1lbnQgcmF0aGVyIHRoYW4gc3BlY2lmaWMgbGF3cywgc2luY2UgZGUganVyZSByZXN0cmljdGlvbnMgZG8gbm90IGFsd2F5cyBtYXAgY2xlYXJseSBpbnRvIGRlIGZhY3RvIHJlc3RyaWN0aW9ucyAoZXNwZWNpYWxseSBpbiBkaWN0YXRvcnNoaXBzIHdoZXJlIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiBsYXdzIGlzIG1vcmUgZGlzY3JldGlvbmFyeSkuIAoKQW5kcmV3IEhlaXNzIGRldmVsb3BzIGEgbmV3IGNpdmlsIHNvY2lldHkgcmVndWxhdG9yeSBlbnZpcm9ubWVudCBpbmRleCAoQ1NSRSkgaW4gaGlzIGRpc3NlcnRhdGlvbiwgd2hpY2ggY29tYmluZXMgdHdvIGNpdmlsIHNvY2lldHkgaW5kZXhlcyBmcm9tIHRoZSBbVmFyaWV0aWVzIG9mIERlbW9jcmFjeSBwcm9qZWN0IChWLURlbSldKGh0dHBzOi8vd3d3LnYtZGVtLm5ldC9lbi8pOiAoMSkgY2l2aWwgc29jaWV0eSByZXByZXNzaW9uIGFuZCAoMikgY2l2aWwgc29jaWV0eSBlbnRyeSBhbmQgZXhpdCByZWd1bGF0aW9ucy4gVGhlIENTUkUgcmFuZ2VzIGZyb20gcm91Z2hseSDiiJI2IHRvIDYgKHRob3VnaCB0eXBpY2FsbHkgb25seSBmcm9tIOKIkjQgdG8gNGlzaCksIGFuZCBzaG93cyBtb3JlIHZhcmlhdGlvbiBvdmVyIHRpbWUgc2luY2UgaXQgb3N0ZW5zaWJseSBjYXB0dXJlcyBjaGFuZ2VzIGluIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgcmVndWxhdG9yeSBlbnZpcm9ubWVudCByYXRoZXIgdGhhbiB0aGUgcHJlc2VuY2Ugb3IgYWJzZW5jZSBvZiBsZWdpc2xhdGlvbi4KCldoaWxlIHRoZSBtYWluIGZvY3VzIG9mIHRoaXMgcGFwZXIgaXMgZG9ub3IgcmVzcG9uc2UgdG8gbmV3ICpsZWdpc2xhdGlvbiosIHdlIGFsc28gbG9vayBhdCBkb25vciByZXNwb25zZSB0byBjaGFuZ2VzIGluIHRoZSBvdmVyYWxsIENTUkUgYXMgYSByb2J1c3RuZXNzIGNoZWNrLgoKVGhlcmUncyBubyBkaXJlY3QgbGluayBmb3IgVi1EZW0gZGF0YSwgc2luY2UgaXQncyBiZWhpbmQgYSBjb250YWN0IGluZm9ybWF0aW9uIGZvcm0uIFNvLCBkb3dubG9hZCB0aGUgWzguMCB2ZXJzaW9uIG9mIHRoZSAiQ291bnRyeS1ZZWFyOiBWLURlbSArIG90aGVyIiBkYXRhc2V0XShodHRwczovL3d3dy52LWRlbS5uZXQvZW4vZGF0YS9kYXRhLXZlcnNpb24tOC8pIGFuZCBwbGFjZSBpdCBpbiBgRGF0YS9kYXRhX3Jhdy9WLURlbS92OGAKCldoZW4gbG9hZGluZyB0aGUgQ1NWLCBgcmVhZHI6OnJlYWRfY3N2KClgIGNob2tlcyBvbiBhIGJ1bmNoIG9mIHJvd3MgZm9yIHdoYXRldmVyIHJlYXNvbiBhbmQgZ2l2ZXMgYSB0b24gb2Ygd2FybmluZ3MsIGJ1dCBpdCBzdGlsbCB3b3Jrcy4gTG9hZGluZyB0aGUgU3RhdGEgdmVyc2lvbiBvZiBWLURlbSBkb2Vzbid0IGNyZWF0ZSB0aGUgd2FybmluZ3MsIGJ1dCBpdCdzIHNsb3dlciBhbmQgaXQgcmVzdWx0cyBpbiB0aGUgc2FtZSBkYXRhLiBTbyB3ZSBqdXN0IGxvYWQgZnJvbSBDU1YgYW5kIG1ha2Ugc3VyZSBpdCBoYXMgdGhlIHJpZ2h0IG51bWJlciBvZiByb3dzIGFuZCBjb2x1bW5zIGluIHRoZSBlbmQuIAoKYGBge3IgbG9hZC12ZGVtLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQp2ZGVtLnJhdyA8LSByZWFkX2NzdihoZXJlKCJEYXRhIiwgImRhdGFfcmF3IiwgIlYtRGVtIiwgInY4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAiVi1EZW0tQ1krT3RoZXJzLXY4LmNzdiIpKQoKdGVzdHRoYXQ6OmV4cGVjdF9lcXVhbChucm93KHZkZW0ucmF3KSwgMjY1MzcpCnRlc3R0aGF0OjpleHBlY3RfZXF1YWwobmNvbCh2ZGVtLnJhdyksIDQ2NDEpCmBgYAoKYGBge3IgY2xlYW4tdmRlbSwgY2FjaGU9VFJVRX0KIyBFeHRyYWN0IGNpdmlsIHNvY2lldHktcmVsYXRlZCB2YXJpYWJsZXMgYW5kIGNyZWF0ZSBDU1JFIGluZGV4CnZkZW0uY3NvIDwtIHZkZW0ucmF3ICU+JSAKICAjIE1pc3NpbmcgQ09XIGNvZGVzCiAgbXV0YXRlKENPV2NvZGUgPSBjYXNlX3doZW4oCiAgICAuJGNvdW50cnlfdGV4dF9pZCA9PSAiU01MIiB+IDUyMUwsCiAgICAuJGNvdW50cnlfdGV4dF9pZCA9PSAiUFNFIiB+IDY2N0wsCiAgICAuJGNvdW50cnlfdGV4dF9pZCA9PSAiUFNHIiB+IDY2OEwsIAogICAgVFJVRSB+IC4kQ09XY29kZSkpICU+JSAKICBzZWxlY3QoY291bnRyeV9uYW1lLCB5ZWFyLCBjb3djb2RlID0gQ09XY29kZSwgCiAgICAgICAgIGVfZmhfaXBvbGl0eTIsIHYyeF9jb3JyLCBlX3diZ2lfZ2VlLAogICAgICAgICB2MnhfZnJhc3NvY190aGljaywgdjJ4Y3NfY2NzaSwKICAgICAgICAgc3RhcnRzX3dpdGgoInYyY3NlZW9yZ3MiKSwgCiAgICAgICAgIHN0YXJ0c193aXRoKCJ2MmNzcmVwcnNzIiksIAogICAgICAgICBzdGFydHNfd2l0aCgidjJjc2Nuc3VsdCIpLAogICAgICAgICBzdGFydHNfd2l0aCgidjJjc3BydGNwdCIpLCAKICAgICAgICAgc3RhcnRzX3dpdGgoInYyY3NnZW5kZXIiKSwgCiAgICAgICAgIHN0YXJ0c193aXRoKCJ2MmNzYW50aW12IikpICU+JQogIG11dGF0ZSh2MmNzcmVwcnNzX29yZCA9IGZhY3Rvcih2MmNzcmVwcnNzX29yZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlNldmVyZWx5IiwgIlN1YnN0YW50aWFsbHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTW9kZXJhdGVseSIsICJXZWFrbHkiLCAiTm8iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpLAogICAgICAgICBjc3JlID0gdjJjc3JlcHJzcyArIHYyY3NlZW9yZ3MpICU+JQogIGZpbHRlcih5ZWFyID4gMTk4MCkKYGBgCgojIyMjIENpdmlsIHNvY2lldHkgcmVzdHJpY3Rpb25zIGRhdGEKCmBgYHtyIHZkZW0tY3NvLW1pbmltYWx9CnZkZW0uY3NvLm1pbiA8LSB2ZGVtLmNzbyAlPiUKICBzZWxlY3QoY291bnRyeV9uYW1lLCB5ZWFyLCBjb3djb2RlLCBjc3JlLCB2MmNzcmVwcnNzX29yZCwKICAgICAgICAgc3RhcnRzX3dpdGgoInYyY3NyZXByc3MiKSwgc3RhcnRzX3dpdGgoInYyY3NlZW9yZ3MiKSkgJT4lCiAgYXJyYW5nZShjb3djb2RlLCB5ZWFyKQoKdmRlbS5jc28ubWluICU+JSBoZWFkKDUwKSAlPiUgZGF0YXRhYmxlKGV4dGVuc2lvbnMgPSAiUmVzcG9uc2l2ZSIpCmBgYAoKIyMjIyBTdW1tYXJ5IG9mIGNsZWFuIGRhdGEKCmBgYHtyIHZkZW0tY3NvLXN1bW1hcnl9CnZkZW0uY3NvLm1pbiAlPiUgZ2xpbXBzZSgpCmBgYAoKCiMjIE5laWdoYm9yaW5nIHN0YXRlcwoKQ2FsY3VsYXRlIHRocmVlIHR5cGVzIG9mIGRpc3RhbmNlIGJldHdlZW4gYWxsIGNvdW50cmllcyB3aXRoIHRoZSBbYENTaGFwZXNgIFIgcGFja2FnZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvcGFja2FnZT1jc2hhcGVzKTogbWltaW11bSBkaXN0YW5jZSwgY2FwaXRhbCBkaXN0YW5jZSwgYW5kIGNlbnRyb2lkIGRpc3RhbmNlLiBCZWNhdXNlIHRoaXMgdGFrZXMgYSByZWFsbHkgbG9uZyB0aW1lLCBpdCdzIGJlc3QgdG8gcnVuIGBEYXRhL2dldF9kaXN0YW5jZXMuUmAgc2VwYXJhdGVseSBlbHNld2hlcmUgZmlyc3QgKGxpa2Ugb24gYSBWUFMpIGFuZCB0aGVuIHNhdmUgdGhlIHJlc3VsdGluZyBgLnJkc2AgZmlsZXMgaW4gYERhdGEvZGF0YV9yYXcvQ291bnRyeSBEaXN0YW5jZXNgLiAKClRoZSBgYWxsLmRpc3RhbmNlc2AgZGF0YSBmcmFtZSBiZWxvdyBjb250YWlucyBhbGwgdGhyZWUgZGlzdGFuY2UgdHlwZXMgYmV0d2VlbiBldmVyeSBjb3VudHJ5IGFuZCBldmVyeSBvdGhlciBjb3VudHJ5IGluIDIwMTIgKHRob3VnaCBpdCBjb3VsZCBwb3RlbnRpYWxseSBpbmNsdWRlIGRpc3RhbmNlcyBmcm9tIDE5OTHigJMyMDE1KS4gVGhpcyBpcyB1c2VkIGxhdGVyIHRvIHdlaWdodCB2YXJpYWJsZXMgYnkgZGlzdGFuY2UuIEl0IGFsc28gaW5jbHVkZXMgYW4gaW5kaWNhdG9yIHZhcmlhYmxlIGNhbGxlZCBgaXMucm91Z2gubmVpZ2hib3JgIHRoYXQgaXMgdHJ1ZSBpZiB0aGUgdHdvIGNvdW50cmllcyBhcmUgbGVzcyB0aGFuIDkwMCBrbSBhcGFydCwgd2hpY2ggY2FwdHVyZXMgbmVpZ2hib3IgcmVsYXRpb25zaGlwcyBiZXR0ZXIgdGhhbiBzaW1wbGUgY29udGlndW91cyBib3JkZXJzLgoKYGBge3IgbG9hZC1jc2hhcGVzLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQpkaXN0YW5jZS5mb2xkZXIgPC0gaGVyZSgiRGF0YSIsICJkYXRhX3JhdyIsICJDb3VudHJ5IGRpc3RhbmNlcyIpCgpyZWFkX2Rpc3RhbmNlcyA8LSBmdW5jdGlvbih0eXBlLCB5ZWFyKSB7CiAgc3RvcGlmbm90KHllYXIgPj0gMTk4MCwgeWVhciA8PSAyMDE1KQogIHN0b3BpZm5vdCh0eXBlICVpbiUgYygiY2FwaXRhbCIsICJjZW50IiwgIm1pbiIpKQogIAogICMgUmVhZCBpbiB0aGUgUkRTIGZpbGUgZm9yIHRoZSB0eXBlIGFuZCB5ZWFyCiAgbWF0cml4LnJhdyA8LSByZWFkUkRTKGZpbGUucGF0aChkaXN0YW5jZS5mb2xkZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAodHlwZSwgIl8iLCB5ZWFyLCAiLTAxLTAxLnJkcyIpKSkKICAKICAjIENvbnZlcnQgZGlzdGFuY2UgbWF0cml4IHRvIGxvbmcgZGF0YWZyYW1lCiAgZGYuY2xlYW4gPC0gYXMuZGF0YS5mcmFtZShtYXRyaXgucmF3KSAlPiUKICAgIG11dGF0ZShnd2NvZGUgPSByb3duYW1lcyguKSkgJT4lCiAgICBnYXRoZXIoZ3djb2RlLm90aGVyLCBkaXN0YW5jZSwgLWd3Y29kZSkgJT4lCiAgICAjIFNldCBpbnZlcnRlZCBkaWFnb25hbCAwcyB0byAwLCByZWFsIDBzIHRvIDEKICAgIG11dGF0ZShkaXN0YW5jZS5pbnYgPSBpZmVsc2UoZ3djb2RlID09IGd3Y29kZS5vdGhlciAmIGRpc3RhbmNlID09IDAsIDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShnd2NvZGUgIT0gZ3djb2RlLm90aGVyICYgZGlzdGFuY2UgPT0gMCwgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEgLyBkaXN0YW5jZSkpKSAlPiUKICAgIG11dGF0ZSh0eXBlID0gdHlwZSwgeWVhciA9IHllYXIpICU+JQogICAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoImd3Y29kZSIpKSwgZnVucyhhcy5udW1lcmljKSkgJT4lCiAgICAjIE1hcmsgaWYgY291bnRyeSBpcyB3aXRoaW4gOTAwIGttCiAgICBtdXRhdGUoaXMucm91Z2gubmVpZ2hib3IgPSBkaXN0YW5jZSA8IDkwMCkgJT4lCiAgICAjIFN0YW5kYXJkaXplIGludmVydGVkIGRpc3RhbmNlcyBzbyB0aGF0IGFsbCByb3dzIHdpdGhpbiBhIGNvdW50cnkgYWRkIHRvIDEKICAgICMgc28gdGhhdCBpdCBjYW4gYmUgdXNlZCBpbiB3ZWlnaHRlZC5tZWFuLgogICAgIyBUaGlzIGlzIHRoZSBzYW1lIGFzIGNhbGN1bGF0aW5nIHRoZSByb3cgc3VtIG9mIHRoZSBtYXRyaXgKICAgIGdyb3VwX2J5KGd3Y29kZSkgJT4lCiAgICBtdXRhdGUoZGlzdGFuY2Uuc3RkID0gZGlzdGFuY2UuaW52IC8gc3VtKGRpc3RhbmNlLmludikpICU+JQogICAgdW5ncm91cCgpICU+JQogICAgbGVmdF9qb2luKGd3LmNvZGVzLCBieSA9ICJnd2NvZGUiKSAlPiUKICAgIGxlZnRfam9pbihndy5jb2RlcywgYnkgPSBjKCJnd2NvZGUub3RoZXIiID0gImd3Y29kZSIpLAogICAgICAgICAgICAgIHN1ZmZpeCA9IGMoIi5zZWxmIiwgIi5vdGhlciIpKQogIAogIHJldHVybihkZi5jbGVhbikKfQoKIyBMb2FkIGFuZCBjb21iaW5lIG1pbmltdW0gZGlzdGFuY2UgbWF0cmljZXMgZm9yIGFsbCB5ZWFycyAoY291bGQgcG90ZW50aWFsbHkKIyBhbHNvIGRvICJjZW50IiBvciAiY2FwaXRhbCIpCmFsbC5kaXN0YW5jZXMgPC0gZXhwYW5kLmdyaWQoeWVhciA9IDE5ODA6MjAxNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gIm1pbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKSAlPiUKICBtdXRhdGUoZGlzdGFuY2VzID0gbWFwMih0eXBlLCB5ZWFyLCB+IHJlYWRfZGlzdGFuY2VzKC54LCAueSkpKSAlPiUgCiAgdW5uZXN0KGRpc3RhbmNlcykKCmFsbC5kaXN0YW5jZXMgJT4lIGdsaW1wc2UoKQpgYGAKCgojIyBPdGhlciBjb250cm9scyBhbmQgYWx0ZXJuYXRpdmUgaHlwb3RoZXNlcwoKVGhlcmUgYXJlIGEgYnVuY2ggb2YgcmVhc29ucyB3aHkgb3ZlcmFsbCBhaWQgZmxvd3MgbWlnaHQgY2hhbmdlIG92ZXIgdGltZS4gV2UgY29udHJvbGUgZm9yIHRoZXNlIGFsdGVybmF0aXZlIGh5cG90aGVzZXM6CgotICoqUmVnaW1lIHR5cGUqKjogZG9ub3JzIGxpa2VseSBnaXZlIGxlc3MgYWlkIHRvIGRlbW9jcmFjaWVzCi0gUG9saXR5IElWOiBgcG9saXR5YCAoaW1wdXRlZCAwLTEwIFBvbGl0eSBzY29yZSBmcm9tIFYtRGVtLCBvcmlnaW5hbGx5IGBlX2ZoX2lwb2xpdHkyYCkKLSAqKldlYWx0aCoqOiBkb25vcnMgbGlrZWx5IGdpdmUgbGVzcyBhaWQgdG8gcmljaGVyIGNvdW50cmllcwotIEdEUCBwZXIgY2FwaXRhOiBgZ2RwLmNhcGl0YWAgKEdEUCBwZXIgY2FwaXRhIChjb25zdGFudCAyMDExIFVTRCkgZnJvbSBXREkpCi0gVHJhZGUgYXMgJSBvZiBHRFA6IGB0cmFkZS5wY3QuZ2RwYCAoZnJvbSBXREkpCi0gQWlkIGRlcGVuZGVuY3k6IGBhaWQucGN0LmdkcGAgKENvbnN0YW50IDIwMTEgT0RBIGFzIHBlcmNlbnQgb2YgY29uc3RhbnQgMjAxMSBHRFAgZnJvbSBBaWREYXRhIGFuZCBXREkpCi0gKipHb3Zlcm5tZW50IGNhcGFjaXR5Kio6IGRvbm9ycyBsaWtlbHkgZ2l2ZSBtb3JlIGFpZCB0byBOR09zIGluIGNvdW50cmllcyB3aXRoIHdlYWsgaW5zdGl0dXRpb25zIChhbmQgcGVyaGFwcyBsZXNzIGFpZCBvdmVyYWxsPykKLSBDb3JydXB0aW9uOiBgY29ycnVwdGlvbmAgKDAtMTAgc2NhbGUgZnJvbSBWLURlbTogcHVibGljIHNlY3RvciArIGV4ZWN1dGl2ZSArICsgbGVnaXNsYXRpdmUgKyBqdWRpY2lhbCBjb3JydXB0aW9uLCBvcmlnaW5hbGx5IGB2MnhfY29ycmAgb24gMC0xKQotICoqQkFEIFZBUklBQkxFLCBhbG1vc3QgNTAlIG1pc3Npbmc7IHNhZGZhY2UqKiBRdWFsaXR5IG9mIGdvdmVybmFuY2U6IGBnb3Z0LmVmZmVjdGl2ZW5lc3NgICjiiYgtMiB0byAyIHNjYWxlIGZyb20gVi1EZW0gYW5kIFdCR0ksIG9yaWdpbmFsbHkgYGVfd2JnaV9nZWVgKQotICoqQmFkIHN0dWZmKio6IGRvbm9ycyBsaWtlbHkgZ2l2ZSBtb3JlIGFpZCB0byBjb3VudHJpZXMgd2hlbiBiYWQgdGhpbmdzIGhhcHBlbiBsaWtlIHdhcnMgYW5kIG5hdHVyYWwgZGlzYXN0ZXJzCi0gSW50ZXJuYWwgY29uZmxpY3Q6IGBpbnRlcm5hbC5jb25mbGljdC5wYXN0LjVgIChiaW5hcnkgaW5kaWNhdG9yIHZhcmlhYmxlIGlmIHRoZXJlIHdhcyBhIGNvbmZsaWN0IGluIHRoYXQgeWVhciBvciBpbiB0aGUgcHJldmlvdXMgNSB5ZWFycyBmcm9tIFVDRFAvUFJJTykKLSBEaXNhc3RlcnM6IGBuYXR1cmFsX2Rpc2FzdGVyLmFmZmVjdGVkYCwgYG5hdHVyYWxfZGlzYXN0ZXIuZGVhdGhzYCwgYG5hdHVyYWxfZGlzYXN0ZXIub2NjdXJyZW5jZWAsIGFuZCBgbmF0dXJhbF9kaXNhc3Rlci50b3RhbC5hZmZlY3RlZGAsIGFtb25nIG90aGVycyAoZnJvbSBFTS1EQVQpCgoKIyMjIFdvcmxkIEJhbmsgYW5kIFVOIGRldmVsb3BtZW50IGluZGljYXRvcnMgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpUaGUgV29ybGQgQmFuayBoYXMgYSBmYW50YXN0aWMgQVBJIGZvciBbdGhlaXIgc3RhdGlzdGljYWwgaW5kaWNhdG9yc10oaHR0cDovL2RhdGEud29ybGRiYW5rLm9yZy8pIGFuZCB0aGVyZSdzIGFscmVhZHkgW2EgbmljZSBSIHBhY2thZ2VdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3BhY2thZ2U9V0RJKSBmb3IgYWNjZXNzaW5nIGl0LCBzbyBkb3dubG9hZGluZyBpbmRpY2F0b3JzIGlzIHRyaXZpYWwuIEZvciB0aGUgc2FrZSBvZiBvdXIgbW9kZWxzLCB3ZSBjYXJlIGFib3V0IEdEUCBwZXIgY2FwaXRhIGFzIGEgcHJveHkgZm9yIGEgY291bnRyeSdzIG92ZXJhbGwgZGV2ZWxvcG1lbnQuIFdlIGFsc28gY29sbGVjdCBhIGZldyBvdGhlciByZWxldmFudCB2YXJpYWJsZXMganVzdCBmb3IgZnVuLgoKYGBge3IgbG9hZC11biwgbWVzc2FnZT1GQUxTRX0KIyBVTiBjb3VudHJ5IGNvZGVzCnVuLmNvZGVzIDwtIHJlYWRfY3N2KGhlcmUoIkRhdGEiLCAiZGF0YV9tYW51YWwiLCAidW5fY29kZXMuY3N2IikpICU+JQogIHNlbGVjdCh1bl9jb2RlLCBpc28zKQoKIyBHRFAgYnkgVHlwZSBvZiBFeHBlbmRpdHVyZSBhdCBjb25zdGFudCAoMjAwNSkgcHJpY2VzIC0gVVMgZG9sbGFycwojIGh0dHA6Ly9kYXRhLnVuLm9yZy9EYXRhLmFzcHg/cT1nZHAmZD1TTkFBTUEmZj1ncklEJTNhMTAyJTNiY3VycklEJTNhVVNEJTNicGNGbGFnJTNhMAp1bi5nZHAucmF3IDwtIHJlYWRfY3N2KGhlcmUoIkRhdGEiLCAiZGF0YV9yYXciLCAiVU4gZGF0YSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVU5kYXRhX0V4cG9ydF8yMDE3MDEyNV8wNDI4MTgwNDYuY3N2IikpICU+JQogIHJlbmFtZSh1bl9jb2RlID0gYENvdW50cnkgb3IgQXJlYSBDb2RlYCkgJT4lCiAgbXV0YXRlKHZhbHVlLnR5cGUgPSAiQ29uc3RhbnQiKQoKIyBodHRwOi8vZGF0YS51bi5vcmcvRGF0YS5hc3B4P3E9Z2RwJmQ9U05BQU1BJmY9Z3JJRCUzYTEwMSUzYmN1cnJJRCUzYVVTRCUzYnBjRmxhZyUzYTAKdW4uZ2RwLmN1cnJlbnQucmF3IDwtIHJlYWRfY3N2KGhlcmUoIkRhdGEiLCAiZGF0YV9yYXciLCAiVU4gZGF0YSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVTmRhdGFfRXhwb3J0XzIwMTcwMTI1XzA2MzcxODQ5OS5jc3YiKSkgJT4lCiAgcmVuYW1lKHVuX2NvZGUgPSBgQ291bnRyeSBvciBBcmVhIENvZGVgKSAlPiUKICBtdXRhdGUodmFsdWUudHlwZSA9ICJDdXJyZW50IikKCiMgaHR0cHM6Ly9lc2EudW4ub3JnL3VucGQvd3BwL0Rvd25sb2FkL1N0YW5kYXJkL1BvcHVsYXRpb24vCnVuLnBvcC5yYXcgPC0gcmVhZF9leGNlbChoZXJlKCJEYXRhIiwgImRhdGFfcmF3IiwgIlVOIGRhdGEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV1BQMjAxNV9QT1BfRjAxXzFfVE9UQUxfUE9QVUxBVElPTl9CT1RIX1NFWEVTLnhscyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgc2tpcCA9IDE2KQpgYGAKCiMjIyMgVU4gcG9wdWxhdGlvbgoKYGBge3IgdW4tcG9wfQp1bi5wb3AgPC0gdW4ucG9wLnJhdyAlPiUKICBmaWx0ZXIoKGBDb3VudHJ5IGNvZGVgICVpbiUgdW4uY29kZXMkdW5fY29kZSkpICU+JQogIHNlbGVjdCgtYyhJbmRleCwgVmFyaWFudCwgTm90ZXMsIGBNYWpvciBhcmVhLCByZWdpb24sIGNvdW50cnkgb3IgYXJlYSAqYCksIAogICAgICAgICB1bl9jb2RlID0gYENvdW50cnkgY29kZWApICU+JQogIGdhdGhlcih5ZWFyLCBwb3B1bGF0aW9uLCAtdW5fY29kZSkgJT4lCiAgbGVmdF9qb2luKHVuLmNvZGVzLCBieSA9ICJ1bl9jb2RlIikgJT4lIGZpbHRlcighaXMubmEoaXNvMykpICU+JQogIG11dGF0ZSh5ZWFyID0gYXMuaW50ZWdlcih5ZWFyKSwKICAgICAgICAgdW4ucG9wdWxhdGlvbiA9IHBvcHVsYXRpb24gKiAxMDAwKSAlPiUgICMgVmFsdWVzIGFyZSBpbiAxMDAwcwogIGxlZnRfam9pbihndy5jb2RlcywgYnkgPSAiaXNvMyIpICU+JQogICMgR2V0IHJpZCBvZiB0aW55IGNvdW50cmllcwogIGZpbHRlcighaXMubmEoY293Y29kZSkpICU+JQogIHNlbGVjdChjb3djb2RlLCB5ZWFyLCB1bi5wb3B1bGF0aW9uKQoKdW4ucG9wICU+JSBnbGltcHNlKCkKYGBgCgojIyMjIFVOIEdEUAoKYGBge3J9CnVuLmdkcCA8LSBiaW5kX3Jvd3ModW4uZ2RwLnJhdywgdW4uZ2RwLmN1cnJlbnQucmF3KSAlPiUKICBmaWx0ZXIoSXRlbSAlaW4lIGMoIkdyb3NzIERvbWVzdGljIFByb2R1Y3QgKEdEUCkiLAogICAgICAgICAgICAgICAgICAgICAiRXhwb3J0cyBvZiBnb29kcyBhbmQgc2VydmljZXMiLAogICAgICAgICAgICAgICAgICAgICAiSW1wb3J0cyBvZiBnb29kcyBhbmQgc2VydmljZXMiKSkgJT4lCiAgbGVmdF9qb2luKHVuLmNvZGVzLCBieSA9ICJ1bl9jb2RlIikgJT4lCiAgIyBGaXggd2VpcmQgZWRnZSBjYXNlcyB3aXRoIGNvdW50cnkgbmFtZXMKICAjIEdldCByaWQgb2YgRm9ybWVyIE5ldGhlcmxhbmRzIEFudGlsbGVzLCBaYW56aWJhciwgRm9ybWVyIEN6ZWNob3Nsb3Zha2lhLAogICMgRm9ybWVyIFl1Z29zbGF2aWEsIGFuZCBGb3JtZXIgVVNTUgogIGZpbHRlcighKHVuX2NvZGUgJWluJSBjKDUzMCwgODM2LCAyMDAsIDg5MCwgODEwKSkpICU+JQogICMgQWRkIGNvZGUgZm9yIEtvc292bywgVGFuemFuaWEsIGFuZCBTdWRhbgogIG11dGF0ZShpc28zID0gaWZlbHNlKHVuX2NvZGUgPT0gNDEyLCAiWEtLIiwgaXNvMyksCiAgICAgICAgIGlzbzMgPSBpZmVsc2UodW5fY29kZSA9PSA4MzUsICJUWkEiLCBpc28zKSwKICAgICAgICAgaXNvMyA9IGlmZWxzZSh1bl9jb2RlID09IDczNiwgIlNETiIsIGlzbzMpKQoKIyBDb21iaW5lIHRoZSB0d28gWWVtZW5zLCB0aGVuIGtlZXAgb25lIG9mIHRoZSB2YWx1ZXMgaW4gdGhlIHR3byBvdmVybGFwcGluZyB5ZWFycwp1bi5nZHAueWVtZW4gPC0gdW4uZ2RwICU+JQogIGZpbHRlcih1bl9jb2RlICVpbiUgYyg3MjAsIDg4NikpICU+JQogIGdyb3VwX2J5KHZhbHVlLnR5cGUsIEl0ZW0sIFllYXIpICU+JQogIG11dGF0ZShWYWx1ZS5jb21iaW5lZCA9IHN1bShWYWx1ZSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBmaWx0ZXIodW5fY29kZSA9PSA3MjApICU+JQogIG11dGF0ZShpc28zID0gIllFTSIpICU+JQogIHNlbGVjdCgtVmFsdWUpICU+JSBzZWxlY3QoVmFsdWUgPSBWYWx1ZS5jb21iaW5lZCwgZXZlcnl0aGluZygpKSAlPiUKICBiaW5kX3Jvd3MoZmlsdGVyKHVuLmdkcCwgdW5fY29kZSA9PSA4ODcpKSAlPiUKICBncm91cF9ieSh2YWx1ZS50eXBlLCBJdGVtLCBZZWFyKSAlPiUKICBzbGljZSgxKSAlPiUgdW5ncm91cCgpCgojIEtlZXAgb25lIG9mIHRoZSBFdGhpb3BpYXMnIEdEUCwgc2luY2UgdGhleSBvdmVybGFwIGZvciBhIGZldyB5ZWFycwp1bi5nZHAuZXRoaW9waWEgPC0gdW4uZ2RwICU+JQogIGZpbHRlcih1bl9jb2RlICVpbiUgYygyMzAsIDIzMSkpICU+JQogIGdyb3VwX2J5KHZhbHVlLnR5cGUsIEl0ZW0sIFllYXIpICU+JQogICMgbXV0YXRlKFZhbHVlLmNvbWJpbmVkID0gbWVhbihWYWx1ZSkpICU+JQogIHNsaWNlKDEpICU+JSB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGlzbzMgPSAiRVRIIikKCnVuLmdkcC5jbGVhbiA8LSB1bi5nZHAgJT4lCiAgIyBSZW1vdmUgWWVtZW5zIGFuZCBFdGhpb3BpYXMKICBmaWx0ZXIoISh1bl9jb2RlICVpbiUgYyg3MjAsIDg4NiwgMjMwLCAyMzEpKSkgJT4lCiAgIyBBZGQgY29uc29saWRhdGVkIFllbWVucyBhbmQgRXRoaW9waWFzCiAgYmluZF9yb3dzKHVuLmdkcC55ZW1lbikgJT4lCiAgYmluZF9yb3dzKHVuLmdkcC5ldGhpb3BpYSkgJT4lCiAgbGVmdF9qb2luKGd3LmNvZGVzLCBieSA9ICJpc28zIikgJT4lCiAgIyBHZXQgcmlkIG9mIHRpbnkgcGxhY2VzCiAgZmlsdGVyKCFpcy5uYShjb3djb2RlKSkKCnVuLmdkcC53aWRlIDwtIHVuLmdkcC5jbGVhbiAlPiUKICBzZWxlY3QoY293Y29kZSwgeWVhciA9IFllYXIsIEl0ZW0sIFZhbHVlLCB2YWx1ZS50eXBlKSAlPiUKICB1bml0ZSh0ZW1wLCB2YWx1ZS50eXBlLCBJdGVtKSAlPiUKICAjIFRlbXBvcmFyeSBpZCBjb2x1bW4gZm9yIHNwcmVhZGluZyBjb3JyZWN0bHkKICBncm91cF9ieSh0ZW1wKSAlPiUgbXV0YXRlKGlkID0gMTpuKCkpICU+JQogIHNwcmVhZCh0ZW1wLCBWYWx1ZSkgJT4lIHNlbGVjdCgtaWQpICU+JSB1bmdyb3VwKCkgJT4lCiAgcmVuYW1lKGV4cG9ydHMuY29uc3RhbnQuMjAwNSA9IGBDb25zdGFudF9FeHBvcnRzIG9mIGdvb2RzIGFuZCBzZXJ2aWNlc2AsCiAgICAgICAgIGltcG9ydHMuY29uc3RhbnQuMjAwNSA9IGBDb25zdGFudF9JbXBvcnRzIG9mIGdvb2RzIGFuZCBzZXJ2aWNlc2AsCiAgICAgICAgIGdkcC5jb25zdGFudC4yMDA1ID0gYENvbnN0YW50X0dyb3NzIERvbWVzdGljIFByb2R1Y3QgKEdEUClgLAogICAgICAgICBleHBvcnRzLmN1cnJlbnQgPSBgQ3VycmVudF9FeHBvcnRzIG9mIGdvb2RzIGFuZCBzZXJ2aWNlc2AsCiAgICAgICAgIGltcG9ydHMuY3VycmVudCA9IGBDdXJyZW50X0ltcG9ydHMgb2YgZ29vZHMgYW5kIHNlcnZpY2VzYCwKICAgICAgICAgZ2RwLmN1cnJlbnQgPSBgQ3VycmVudF9Hcm9zcyBEb21lc3RpYyBQcm9kdWN0IChHRFApYCkgJT4lCiAgbXV0YXRlKGdkcC5kZWZsYXRvciA9IGdkcC5jdXJyZW50IC8gZ2RwLmNvbnN0YW50LjIwMDUgKiAxMDApCgojIFJlc2NhbGUgdGhlIDIwMDUgZGF0YSB0byAyMDExIHRvIG1hdGNoIEFpZERhdGEKIwojIERlZmxhdG9yID0gY3VycmVudCBHRFAgLyBjb25zdGFudCBHRFAgKiAxMDAKIyBDdXJyZW50IEdEUCBpbiB5ZWFyX3QgKiAoZGVmbGF0b3IgaW4geWVhcl90YXJnZXQgLyBkZWZsYXRvciBpbiB5ZWFyX3QpCnVuLmdkcC5yZXNjYWxlZCA8LSB1bi5nZHAud2lkZSAlPiUKICBsZWZ0X2pvaW4oc2VsZWN0KGZpbHRlcih1bi5nZHAud2lkZSwgeWVhciA9PSAyMDExKSwKICAgICAgICAgICAgICAgICAgIGNvd2NvZGUsIGRlZmxhdG9yLnRhcmdldC55ZWFyID0gZ2RwLmRlZmxhdG9yKSwKICAgICAgICAgICAgYnkgPSAiY293Y29kZSIpICU+JQogIG11dGF0ZSh1bi5nZHAgPSBnZHAuY3VycmVudCAqIChkZWZsYXRvci50YXJnZXQueWVhciAvIGdkcC5kZWZsYXRvciksCiAgICAgICAgIHVuLnRyYWRlLnBjdC5nZHAgPSAoaW1wb3J0cy5jdXJyZW50ICsgZXhwb3J0cy5jdXJyZW50KSAvIGdkcC5jdXJyZW50KQoKdW4uZ2RwLmZpbmFsIDwtIHVuLmdkcC5yZXNjYWxlZCAlPiUKICBzZWxlY3QoY293Y29kZSwgeWVhciwgdW4udHJhZGUucGN0LmdkcCwgdW4uZ2RwKSAlPiUKICBncm91cF9ieShjb3djb2RlLCB5ZWFyKSAlPiUKICBzbGljZSgxKSAlPiUgdW5ncm91cCgpCgp1bi5nZHAuZmluYWwgJT4lIGhlYWQoNTApICU+JSBkYXRhdGFibGUoZXh0ZW5zaW9ucyA9ICJSZXNwb25zaXZlIikKCnVuLmdkcC5maW5hbCAlPiUgZ2xpbXBzZSgpCmBgYAoKIyMjIyBXb3JsZCBCYW5rIGluZGljYXRvcnMKCmBgYHtyIGxvYWQtd2RpLCBjYWNoZT1UUlVFfQp3ZGkuaW5kaWNhdG9ycyA8LSBjKCJOWS5HRFAuUENBUC5LRCIsICAgICAgICAjIEdEUCBwZXIgY2FwaXRhIChjb25zdGFudCAyMDEwIFVTRCkKICAgICAgICAgICAgICAgICAgICAiTlkuR0RQLk1LVFAuQ0QiLCAgICAgICAgIyBHRFAgKGN1cnJlbnQgZG9sbGFycykKICAgICAgICAgICAgICAgICAgICAiTlkuR0RQLk1LVFAuS0QiLCAgICAgICAgIyBHRFAgKGNvbnN0YW50IDIwMTAgVVNEKQogICAgICAgICAgICAgICAgICAgICJTUC5QT1AuVE9UTCIsICAgICAgICAgICAjIFBvcHVsYXRpb24sIHRvdGFsCiAgICAgICAgICAgICAgICAgICAgIk5FLlRSRC5HTkZTLlpTIikgICAgICAgICMgVHJhZGUgYXMgJSBvZiBHRFAKCndkaS5wYXRoIDwtIGhlcmUoImRhdGEiLCAiZGF0YV9jYWNoZSIsICJ3ZGkucmRzIikKCmlmICghZmlsZS5leGlzdHMod2RpLnBhdGgpKSB7CiAgIyBHZXQgYWxsIGNvdW50cmllcyBhbmQgcmVnaW9ucyBiZWNhdXNlIHRoZSBXb3JsZCBCYW5rIGNob2tlcyBvbiBJU08gY29kZXMgbGlrZQogICMgWEsgZm9yIEtvc292bywgZXZlbiB0aG91Z2ggaXQgcmV0dXJucyBkYXRhIGZvciBLb3Nvdm8gd2l0aCB0aGUgWEsgY29kZQogICMgwq9cXyjjg4QpXy/CrwogIHdkaS5yYXcgPC0gV0RJKGNvdW50cnkgPSAiYWxsIiwgd2RpLmluZGljYXRvcnMsCiAgICAgICAgICAgICAgICAgZXh0cmEgPSBGQUxTRSwgc3RhcnQgPSAxOTgwLCBlbmQgPSAyMDE1KQogIAogIHNhdmVSRFMod2RpLnJhdywgd2RpLnBhdGgpCn0gZWxzZSB7CiAgd2RpLnJhdyA8LSByZWFkUkRTKHdkaS5wYXRoKQp9CgojIEZpbHRlciBjb3VudHJpZXMgaGVyZSBpbnN0ZWFkCndkaS5jbGVhbi5pbnRlcm1lZGlhdGUgPC0gd2RpLnJhdyAlPiUKICBmaWx0ZXIoaXNvMmMgJWluJSB1bmlxdWUoZ3cuY29kZXMkaXNvMikpICU+JQogIGFycmFuZ2UoaXNvMmMsIHllYXIpICU+JQogIHJlbmFtZShnZHAuY2FwaXRhLjIwMTAgPSBOWS5HRFAuUENBUC5LRCwgCiAgICAgICAgIGdkcC4yMDEwID0gTlkuR0RQLk1LVFAuS0QsIGdkcC5jdXJyZW50ID0gTlkuR0RQLk1LVFAuQ0QsCiAgICAgICAgIHBvcHVsYXRpb24gPSBTUC5QT1AuVE9UTCwgdHJhZGUucGN0LmdkcCA9IE5FLlRSRC5HTkZTLlpTKSAlPiUKICBtdXRhdGUoZ2RwLmRlZmxhdG9yID0gZ2RwLmN1cnJlbnQgLyBnZHAuMjAxMCAqIDEwMCkKCiMgUmVzY2FsZSB0aGUgMjAxMCBkYXRhIHRvIDIwMTEgdG8gbWF0Y2ggQWlkRGF0YQojCiMgRGVmbGF0b3IgPSBjdXJyZW50IEdEUCAvIGNvbnN0YW50IEdEUCAqIDEwMAojIEN1cnJlbnQgR0RQIGluIHllYXJfdCAqIChkZWZsYXRvciBpbiB5ZWFyX3RhcmdldCAvIGRlZmxhdG9yIGluIHllYXJfdCkKd2RpLnJlc2NhbGVkIDwtIHdkaS5jbGVhbi5pbnRlcm1lZGlhdGUgJT4lCiAgbGVmdF9qb2luKHNlbGVjdChmaWx0ZXIod2RpLmNsZWFuLmludGVybWVkaWF0ZSwgeWVhciA9PSAyMDExKSwgCiAgICAgICAgICAgICAgICAgICBpc28yYywgZGVmbGF0b3IudGFyZ2V0LnllYXIgPSBnZHAuZGVmbGF0b3IpLCAKICAgICAgICAgICAgYnkgPSAiaXNvMmMiKSAlPiUKICBtdXRhdGUoZ2RwID0gZ2RwLmN1cnJlbnQgKiAoZGVmbGF0b3IudGFyZ2V0LnllYXIgLyBnZHAuZGVmbGF0b3IpKQoKd2RpLmNsZWFuIDwtIHdkaS5yZXNjYWxlZCAlPiUKICBsZWZ0X2pvaW4oc2VsZWN0KGd3LmNvZGVzLCBpc28yLCBjb3djb2RlKSwgYnkgPSBjKCJpc28yYyIgPSAiaXNvMiIpKSAlPiUKICBzZWxlY3QoLWMoZ2RwLmNhcGl0YS4yMDEwLCBnZHAuY3VycmVudCwgZ2RwLjIwMTAsIAogICAgICAgICAgICBnZHAuZGVmbGF0b3IsIGRlZmxhdG9yLnRhcmdldC55ZWFyKSkKCndkaS5jbGVhbiAlPiUgaGVhZCgxMDApICU+JSBkYXRhdGFibGUoZXh0ZW5zaW9ucyA9ICJSZXNwb25zaXZlIikKCndkaS5jbGVhbiAlPiUgZ2xpbXBzZSgpCmBgYAoKCiMjIyBGb3JtZXIgY29sb25pYWwgc3RhdHVzIHsudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKW1BhdWwgSGVuc2VsIGhhcyBjb2xsZWN0ZWQgZGF0YV0oaHR0cDovL3d3dy5wYXVsaGVuc2VsLm9yZy9pY293Y29sLmh0bWwpIG9uIGVhY2ggY291bnRyeSdzIGZvcm1lciBjb2xvbmlhbCBzdGF0dXMsIGluZGljYXRpbmcgYm90aCBhIGdpdmVuIGNvdW50cnkncyBwcmltYXJ5IGNvbG9uaWFsIHJ1bGVyIGFuZCB0aGUgbGFzdCBjb2xvbmlhbCBydWxlciBwcmlvciB0byBpbmRlcGVuZGVuY2UuIFRoZSBkYXRhc2V0IGFsc28gaW5jbHVkZXMgYW4gZXN0aW1hdGVkIGRhdGUgb2YgaW5kZXBlbmRlbmNlLgoKQ29sb25pYWwgc3RhdHVzIGNvdWxkIG1hdHRlciBmb3IgYWlkLCB3aXRoIGRvbm9yIGNvdW50cmllcyBmYXZvcmluZyBmb3JtZXIgY29sb25pZXMgKGkuZS4gRnJhbmNlIG1pZ2h0IGJlIG1vcmUgbGlrZWx5IHRvIGRvbmF0ZSB0byBmb3JtZXIgQWZyaWNhbiBjb2xvbmllczsgU3BhaW4gbWlnaHQgYmUgbW9yZSBsaWtlbHkgdG8gZG9uYXRlIHRvIExhdGluIEFtZXJpY2E7IGV0Yy4pCgpCZWNhdXNlIHRoZXJlIGFyZSBzbyBtYW55IGNvbHVtbnMsIHRoZSBkYXRhIGJlbG93IGhhcyBiZWVuIGhvcml6b250YWxseSBjb2xsYXBzZWTigJRjbGljayBvbiB0aGUgZ3JlZW4gcGx1cyBzaWduIHRvIHNlZSB0aGUgcmVzdCBvZiB0aGUgZGF0YSBpbiBhIHJvdy4KCmBgYHtyIGxvYWQtY29sb25pYWwtc3RhdHVzLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQpjb2wudXJsIDwtICJodHRwOi8vd3d3LnBhdWxoZW5zZWwub3JnL0RhdGEvY29saGlzdC56aXAiCmNvbC5wYXRoIDwtIGhlcmUoIkRhdGEiLCAiZGF0YV9yYXciKQpjb2wuemlwLm5hbWUgPC0gYmFzZW5hbWUoY29sLnVybCkKY29sLm5hbWUgPC0gdG9vbHM6OmZpbGVfcGF0aF9zYW5zX2V4dChjb2wuemlwLm5hbWUpCgpjb2wuZmluYWwubmFtZSA8LSAiY29sZGF0YTEwMC5jc3YiCmNvbC5mdWxsLnBhdGggPC0gZmlsZS5wYXRoKGNvbC5wYXRoLCAiSUNPVyBDb2xvbmlhbCBIaXN0b3J5IDEuMCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2wuZmluYWwubmFtZSkKCiMgRG93bmxvYWQgSUNPVyBkYXRhIGlmIG5lZWRlZAppZiAoIWZpbGUuZXhpc3RzKGNvbC5mdWxsLnBhdGgpKSB7CiAgY29sLmdldCA8LSBHRVQoY29sLnVybCwgCiAgICAgICAgICAgICAgICAgd3JpdGVfZGlzayhmaWxlLnBhdGgoY29sLnBhdGgsIGNvbC56aXAubmFtZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVyd3JpdGUgPSBUUlVFKSwgCiAgICAgICAgICAgICAgICAgcHJvZ3Jlc3MoKSkKICB1bnppcChmaWxlLnBhdGgoY29sLnBhdGgsIGNvbC56aXAubmFtZSksIGV4ZGlyID0gY29sLnBhdGgpCiAgCiAgZmlsZS5yZW1vdmUoZmlsZS5wYXRoKGNvbC5wYXRoLCBjb2wuemlwLm5hbWUpKQp9Cgpjb2wucmF3IDwtIHJlYWRfY3N2KGNvbC5mdWxsLnBhdGgsIG5hID0gIi05IiwKICAgICAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSBjb2xzKAogICAgICAgICAgICAgICAgICAgICAgU3RhdGUgPSBjb2xfaW50ZWdlcigpLAogICAgICAgICAgICAgICAgICAgICAgTmFtZSA9IGNvbF9jaGFyYWN0ZXIoKSwKICAgICAgICAgICAgICAgICAgICAgIENvbFJ1bGVyID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgIEluZEZyb20gPSBjb2xfaW50ZWdlcigpLAogICAgICAgICAgICAgICAgICAgICAgSW5kRGF0ZSA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICBJbmRWaW9sID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgIEluZFR5cGUgPSBjb2xfaW50ZWdlcigpLAogICAgICAgICAgICAgICAgICAgICAgU2VjRnJvbSA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICBTZWNEYXRlID0gY29sX2ludGVnZXIoKSwKICAgICAgICAgICAgICAgICAgICAgIFNlY1Zpb2wgPSBjb2xfaW50ZWdlcigpLAogICAgICAgICAgICAgICAgICAgICAgSW50byA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICBJbnRvRGF0ZSA9IGNvbF9pbnRlZ2VyKCksCiAgICAgICAgICAgICAgICAgICAgICBDT1dzeXMgPSBjb2xfaW50ZWdlcigpLAogICAgICAgICAgICAgICAgICAgICAgR1dzeXMgPSBjb2xfaW50ZWdlcigpLAogICAgICAgICAgICAgICAgICAgICAgTm90ZXMgPSBjb2xfY2hhcmFjdGVyKCkKICAgICAgICAgICAgICAgICAgICApKSAKCmNvbC5jbGVhbiA8LSBjb2wucmF3ICU+JQogICMgSW5kZXBlbmRlbmNlIGRhdGVzIHdpdGggdW5rbm93biBtb250aHMgYXJlIGNvZGVkIGFzIDAwLCB3aGljaCBtYWtlcwogICMgbHVicmlkYXRlIGNob2tlLiBTbyBjaGFuZ2UgdGhvc2UgdG8gMDEKICBtdXRhdGUoSW5kRGF0ZS5jbGVhbiA9IHN0cl9yZXBsYWNlKEluZERhdGUsICIwMCQiLCAiMDEiKSkgJT4lCiAgIyBZZWFycyBsZXNzIHRoYW4gMTAwMCBtYWtlIGx1YnJpZGF0ZSBjaG9rZSwgc28gcHJlZmFjZSB0aGVtIHdpdGggYSAwCiAgbXV0YXRlKEluZERhdGUuY2xlYW4gPSBpZmVsc2UobmNoYXIoSW5kRGF0ZS5jbGVhbikgPT0gNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKDAsIEluZERhdGUuY2xlYW4pLCBJbmREYXRlLmNsZWFuKSkgJT4lCiAgbXV0YXRlKEluZERhdGUgPSB5bWQocGFzdGUwKEluZERhdGUuY2xlYW4sICIwMSIpKSkgJT4lCiAgbGVmdF9qb2luKHNlbGVjdChndy5jb2RlcywgaXNvMywgY293Y29kZSwgY291bnRyeS5uYW1lKSwKICAgICAgICAgICAgYnkgPSBjKCJTdGF0ZSIgPSAiY293Y29kZSIpKSAlPiUKICBsZWZ0X2pvaW4oc2VsZWN0KGd3LmNvZGVzLCBjb2wucnVsZXIuY293Y29kZSA9IGNvd2NvZGUsIAogICAgICAgICAgICAgICAgICAgY29sLnJ1bGVyLmlzbzMgPSBpc28zLCAKICAgICAgICAgICAgICAgICAgIGNvbC5ydWxlci5jb3VudHJ5Lm5hbWUgPSBjb3VudHJ5Lm5hbWUpLAogICAgICAgICAgICBieSA9IGMoIkNvbFJ1bGVyIiA9ICJjb2wucnVsZXIuY293Y29kZSIpKSAlPiUKICBsZWZ0X2pvaW4oc2VsZWN0KGd3LmNvZGVzLCBpbmQuZnJvbS5jb3djb2RlID0gY293Y29kZSwKICAgICAgICAgICAgICAgICAgIGluZC5mcm9tLmlzbzMgPSBpc28zLCAKICAgICAgICAgICAgICAgICAgIGluZC5mcm9tLmNvdW50cnkubmFtZSA9IGNvdW50cnkubmFtZSksCiAgICAgICAgICAgIGJ5ID0gYygiSW5kRnJvbSIgPSAiaW5kLmZyb20uY293Y29kZSIpKSAlPiUKICBzZWxlY3QoY293Y29kZSA9IFN0YXRlLCBjb3VudHJ5Lm5hbWUsIGNvbC5pbmQuZGF0ZSA9IEluZERhdGUsCiAgICAgICAgIGNvbC5ydWxlci5jb3VudHJ5Lm5hbWUsIGNvbC5ydWxlci5jb3djb2RlID0gQ29sUnVsZXIsIGNvbC5ydWxlci5pc28zLAogICAgICAgICBpbmQuZnJvbS5jb3VudHJ5Lm5hbWUsIGluZC5mcm9tLmNvd2NvZGUgPSBJbmRGcm9tLCBpbmQuZnJvbS5pc28zKSAlPiUKICAjIEdldCByaWQgb2Ygc21hbGxlciBhbmNpZW50IHN0YXRlcyBsaWtlIFR1c2NhbnksIFBhcm1hLCBhbmQgWmFuemliYXIKICBmaWx0ZXIoIWlzLm5hKGNvdW50cnkubmFtZSkpICU+JQogICMgQWRkIGNvdW50cnkgbmFtZXMgYW5kIElTTyBjb2RlcyBmb3IgYW5jaWVudCBwbGFjZXMKICBtdXRhdGUoY29sLnJ1bGVyLmNvdW50cnkubmFtZSA9IGlmZWxzZShjb2wucnVsZXIuY293Y29kZSA9PSAzMDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBdXN0cmlhLUh1bmdhcnkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbC5ydWxlci5jb3VudHJ5Lm5hbWUpLAogICAgICAgICBjb2wucnVsZXIuaXNvMyA9IGlmZWxzZShjb2wucnVsZXIuY293Y29kZSA9PSAzMDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQVVIIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sLnJ1bGVyLmNvdW50cnkubmFtZSkpICU+JQogIG11dGF0ZShpbmQuZnJvbS5jb3VudHJ5Lm5hbWUgPSBjYXNlX3doZW4oCiAgICAuJGluZC5mcm9tLmNvd2NvZGUgPT0gODkgfiAiVW5pdGVkIFByb3ZpbmNlcyBvZiBDZW50cmFsIEFtZXJpY2EiLAogICAgLiRpbmQuZnJvbS5jb3djb2RlID09IDMwMCB+ICJBdXN0cmlhLUh1bmdhcnkiLAogICAgLiRpbmQuZnJvbS5jb3djb2RlID09IDMxNSB+ICJDemVjaG9zbG92YWtpYSIsCiAgICAuJGluZC5mcm9tLmNvd2NvZGUgPT0gNjc4IH4gIlllbWVuIChBcmFiIFJlcHVibGljIG9mIFllbWVuKSIsCiAgICAuJGluZC5mcm9tLmNvd2NvZGUgPT0gNzMwIH4gIktvcmVhIiwKICAgIGlzLm5hKC4kaW5kLmZyb20uY293Y29kZSkgfiBOQV9jaGFyYWN0ZXJfLAogICAgVFJVRSB+IC4kaW5kLmZyb20uY291bnRyeS5uYW1lCiAgKSkgJT4lCiAgbXV0YXRlKGluZC5mcm9tLmlzbzMgPSBjYXNlX3doZW4oCiAgICAuJGluZC5mcm9tLmNvd2NvZGUgPT0gODkgfiAiVVBDIiwKICAgIC4kaW5kLmZyb20uY293Y29kZSA9PSAzMDAgfiAiQVVIIiwKICAgIC4kaW5kLmZyb20uY293Y29kZSA9PSAzMTUgfiAiQ1pFIiwKICAgIC4kaW5kLmZyb20uY293Y29kZSA9PSA2NzggfiAiWUVNIiwKICAgIC4kaW5kLmZyb20uY293Y29kZSA9PSA3MzAgfiAiS09SIiwKICAgIGlzLm5hKC4kaW5kLmZyb20uY293Y29kZSkgfiBOQV9jaGFyYWN0ZXJfLAogICAgVFJVRSB+IC4kaW5kLmZyb20uaXNvMwogICkpICU+JQogICMgTWFyayBuZXZlciBtb2Rlcm5seSBjb2xvbnppZWQgY291bnRyaWVzIGFzIHN1Y2ggaW5zdGVhZCBvZiBtaXNzaW5nCiAgbXV0YXRlKGNvbC5ydWxlci5jb3VudHJ5Lm5hbWUgPSBpZmVsc2UoaXMubmEoY29sLnJ1bGVyLmNvd2NvZGUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm90IHJlY2VudGx5IGNvbG9uaXplZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sLnJ1bGVyLmNvdW50cnkubmFtZSksCiAgICAgICAgIGNvbC5ydWxlci5pc28zID0gaWZlbHNlKGlzLm5hKGNvbC5ydWxlci5jb3djb2RlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlpaWiIsIGNvbC5ydWxlci5pc28zKSwKICAgICAgICAgY29sLnJ1bGVyLmNvd2NvZGUgPSBpZmVsc2UoaXMubmEoY29sLnJ1bGVyLmNvd2NvZGUpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOTk5LCBjb2wucnVsZXIuY293Y29kZSksCiAgICAgICAgIGluZC5mcm9tLmNvdW50cnkubmFtZSA9IGlmZWxzZShpcy5uYShpbmQuZnJvbS5jb3djb2RlKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQWxyZWFkeSBpbmRlcGVuZGVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmQuZnJvbS5jb3VudHJ5Lm5hbWUpLAogICAgICAgICBpbmQuZnJvbS5pc28zID0gaWZlbHNlKGlzLm5hKGluZC5mcm9tLmNvd2NvZGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJaWloiLCBpbmQuZnJvbS5pc28zKSwKICAgICAgICAgaW5kLmZyb20uY293Y29kZSA9IGlmZWxzZShpcy5uYShpbmQuZnJvbS5jb3djb2RlKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOTk5LCBpbmQuZnJvbS5jb3djb2RlKSkgJT4lCiAgIyBTZXJiaWEgaXNuJ3QgaW5jbHVkZWQgaW4gdGhlIGNvbG9uaWFsIHJ1bGVyIGRhdGEgYmVjYXVzZSBpdCdzIGNvbWJpbmVkIHdpdGgKICAjIFl1Z29zbGF2aWEgYW5kIE1vbnRlbmVncm8uIFNvIGhlcmUgd2UgZHVwbGljYXRlIHRoZSAiQ3JvYXRpYSIgcm93IGZvcgogICMgU2VyYmlhIHRvIHBpY2sgdXAgdGhlIGNvbG9uaWFsIHJlbGF0aW9uc2hpcCAoZXZlbiB0aG91Z2ggaXQncyB0ZWNobmljYWxseQogICMgbm90IDEwMCUgY29ycmVjdCkKICBiaW5kX3Jvd3MoZmlsdGVyKC4sIGNvd2NvZGUgPT0gMzQ0KSAlPiUgCiAgICAgICAgICAgICAgbXV0YXRlKGNvd2NvZGUgPSAzNDAsIGNvdW50cnkubmFtZSA9ICJTZXJiaWEiKSkKYGBgCgojIyMjIENvbG9uaWFsIHN0YXR1cyBkYXRhCgpgYGB7ciBjb2xvbmlhbC1zdGF0dXMtdGFibGV9CmNvbC5jbGVhbiAlPiUgZGF0YXRhYmxlKGV4dGVuc2lvbnMgPSAiUmVzcG9uc2l2ZSIpCmBgYAoKIyMjIyBTdW1tYXJ5IG9mIGNsZWFuIGRhdGEKCmBgYHtyIGNvbG9uaWFsLXN0YXR1cy1nbGltcHNlfQpjb2wuY2xlYW4gJT4lIGdsaW1wc2UoKQpgYGAKCgojIyMgQ29uZmxpY3QKClRoZSBbVUNEUC9QUklPIEFybWVkIENvbmZsaWN0IERhdGFzZXRdKGh0dHA6Ly91Y2RwLnV1LnNlL2Rvd25sb2Fkcy8pIHRyYWNrcyBhIHRvbiBvZiBjb25mbGljdC1yZWxlYXRlZCBkYXRhLCBpbmNsdWRpbmcgcmVhc29ucyBmb3IgdGhlIGNvbmZsaWN0LCBwYXJ0aWVzIGluIHRoZSBjb25mbGljdCwgaW50ZW5zaXR5IG9mIHRoZSBjb25mbGljdCwgYW5kIGRlYXRocyBpbiB0aGUgY29uZmxpY3QuIFdlJ3JlIG9ubHkgaW50ZXJlc3RlZCBpbiB3aGV0aGVyIGEgY29uZmxpY3QgaGFwcGVuZWQgaW4gYSBnaXZlbiB5ZWFyIChvciBpbiB0aGUgcGFzdCA1IHllYXJzKSwgc28gaGVyZSB3ZSBzaW1wbHkgY3JlYXRlIGFuIGluZGljYXRvciB2YXJpYWJsZSBmb3Igd2hldGhlciB0aGVyZSB3YXMgaW50ZXJuYWwgY29uZmxpY3QgaW4gYSBjb3VudHJ5LXllYXIgKGNvbmZsaWN0IHR5cGUgPSAzKS4gIAoKYGBge3IgbG9hZC1jb25mbGljdCwgbWVzc2FnZT1GQUxTRX0KIyBVcHBzYWxhIGNvbmZsaWN0IGRhdGEKIyBodHRwOi8vd3d3LnBjci51dS5zZS9yZXNlYXJjaC91Y2RwL2RhdGFzZXRzL2dlbmVyYXRlX3lvdXJfb3duX2RhdGFzZXRzL2R5bmFtaWNfZGF0YXNldHMvCiMgY29uZmxpY3RzIDwtIHJlYWRfdHN2KGhlcmUoIkRhdGEiLCAiZGF0YV9yYXciLCAiRXh0ZXJuYWwiLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJVcHBzYWxhIiwgInl3ZF9kYXRhc2V0LmNzdiIpKSAlPiUKIyAgIG11dGF0ZShpbnRlbnNpdHkgPSBmYWN0b3IoaW50ZW5zaXR5LCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiTm8iLCAiTWlub3IiLCAiSW50ZXJtZWRpYXRlIiwgIldhciIpLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZCA9IFRSVUUpKQoKY29uZmxpY3RzLnVybCA8LSAiaHR0cDovL3VjZHAudXUuc2UvZG93bmxvYWRzL3VjZHBwcmlvL3VjZHAtcHJpby1hY2QtNC0yMDE2LmNzdiIKCmNvbmZsaWN0cy5wYXRoIDwtIGhlcmUoIkRhdGEiLCAiZGF0YV9yYXciLCAiVUNEUCIpCgppZiAoIWZpbGUuZXhpc3RzKGZpbGUucGF0aChjb25mbGljdHMucGF0aCwgYmFzZW5hbWUoY29uZmxpY3RzLnVybCkpKSkgewogIEdFVChjb25mbGljdHMudXJsLCAKICAgICAgd3JpdGVfZGlzayhmaWxlLnBhdGgoY29uZmxpY3RzLnBhdGgsIGJhc2VuYW1lKGNvbmZsaWN0cy51cmwpKSwKICAgICAgICAgICAgICAgICBvdmVyd3JpdGUgPSBUUlVFKSkKfQoKY29uZmxpY3RzLnJhdyA8LSByZWFkX2NzdihmaWxlLnBhdGgoY29uZmxpY3RzLnBhdGgsIGJhc2VuYW1lKGNvbmZsaWN0cy51cmwpKSkKCmNvbmZsaWN0cyA8LSBjb25mbGljdHMucmF3ICU+JQogIGZpbHRlcihUeXBlT2ZDb25mbGljdCA9PSAzKSAlPiUKICBtdXRhdGUoZ3djb2RlID0gYXMuaW50ZWdlcihHV05vQSkpICU+JQogIGdyb3VwX2J5KGd3Y29kZSwgWWVhcikgJT4lCiAgc3VtbWFyaXNlKGNvbmZsaWN0LmludGVybmFsID0gbigpID4gMCkgJT4lCiAgdW5ncm91cCgpICU+JQogIGxlZnRfam9pbihndy5jb2RlcywgYnkgPSAiZ3djb2RlIikgJT4lCiAgZmlsdGVyKCFpcy5uYShjb3djb2RlKSkKCmdsaW1wc2UoY29uZmxpY3RzKQpgYGAKCgojIyMgTmF0dXJhbCBkaXNhc3RlcnMgey50YWJzZXQgLnRhYnNldC1mYWRlIC50YWJzZXQtcGlsbHN9CgpOYXR1cmFsIGRpc2FzdGVyIGRhdGEgY29tZXMgZnJvbSB0aGUgW0ludGVybmF0aW9uYWwgRGlzYXN0ZXIgRGF0YWJhc2UgKEVNLURBVCldKGh0dHA6Ly93d3cuZW1kYXQuYmUvZGF0YWJhc2UpLiBUaGUgZGF0YSBpbmNsdWRlcyB0aGUgbnVtYmVyIG9mIGRlYXRocywgaW5qdXJpZXMsIGhvbWVsZXNzIGRpc3BsYWNlbWVudHMsIGFuZCBtb25ldGFyeSBsb3NzZXMgKGluIDIwMDAgZG9sbGFycykgZm9yIGEgaHVnZSBudW1iZXIgb2YgbmF0dXJhbCBhbmQgdGVjaG5vbG9naWNhbCBkaXNhc3RlcnMgKHNlZSBbRU0tREFUJ3MgZnVsbCBjbGFzc2lmaWNhdGlvbl0oaHR0cDovL3d3dy5lbWRhdC5iZS9jbGFzc2lmaWNhdGlvbikpLgoKTmF0dXJhbCBkaXNhc3RlcnMgY291bGQgbWF0dGVyIGZvciBhaWQgdG9vLCBzaW5jZSBkb25vciBjb3VudHJpZXMgbWlnaHQgaW5jcmVhc2UgdGhlaXIgYWlkIHRvIGNvdW50cmllcyBzdWZmZXJpbmcgbW9yZS4gCgpFTS1EQVQgZG9lcyBub3QgcHJvdmlkZSBhIHNpbmdsZSBsaW5rIHRvIGRvd25sb2FkIHRoZWlyIGRhdGEuIEluc3RlYWQsIHlvdSBoYXZlIHRvIGNyZWF0ZSBhIHF1ZXJ5IHVzaW5nIFt0aGVpciBhZHZhbmNlZCBzZWFyY2ggZm9ybV0oaHR0cDovL3d3dy5lbWRhdC5iZS9hZHZhbmNlZF9zZWFyY2gvaW5kZXguaHRtbCkuIFdlIGRvd25sb2FkZWQgZGF0YSB1c2luZyB0aGUgZm9sbG93aW5nIHF1ZXJ5OgoKLSBTZWxlY3QgYWxsIGNvdW50cmllcyBmcm9tIHVwIHRvIDIwMTYKLSBTZWxlY3QgYWxsIHRocmVlIGRpc2FzdGVyIGNsYXNzaWZpY2F0aW9uIGdyb3VwcyAobmF0dXJhbCwgdGVjaG5vbG9naWNhbCwgY29tcGxleCkKLSBHcm91cCByZXN1bHRzIGJ5IGNvdW50cnkgbmFtZSwgeWVhciwgYW5kIGRpc2FzdGVyIHR5cGUKLSBEb3dubG9hZCBDU1YgYW5kIHNhdmUgaW4gYERhdGEvZGF0YV9yYXcvRGlzYXN0ZXJzL0RhdGEuY3N2YAoKCmBgYHtyIGxvYWQtZGlzYXN0ZXJzLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1UUlVFfQojIERpc2FzdGVyIGNsYXNzaWZpY2F0aW9uCmRpc2FzdGVyLmNsYXNzaWZpY2F0aW9uLnJhdyA8LSAiaHR0cHM6Ly93ZWIuYXJjaGl2ZS5vcmcvd2ViLzIwMTYxMjAzMTY1MzQ1L2h0dHA6Ly93d3cuZW1kYXQuYmUvY2xhc3NpZmljYXRpb24iICU+JQogIHJlYWRfaHRtbCgpICU+JQogIGh0bWxfbm9kZXMoLiwgeHBhdGggPSAnLy8qW0BpZD0iYXJ0aWNsZS0xNDYyNyJdL2Rpdi9kaXYvZGl2L2Rpdi90YWJsZVsxXScpICU+JQogIGh0bWxfdGFibGUoaGVhZGVyID0gVFJVRSkKCiMgRm9yIHdoYXRldmVyIHJlYXNvbiwgdGhlIGRvd25sb2FkZWQgZGF0YSB0cmVhdHMgdGVjaG5vbG9naWNhbCBzdWJncm91cHMgYXMKIyBtYWluIHR5cGVzIChlLmcuICJpbmR1c3RyaWFsIGFjY2lkZW50IiBpcyBsaXN0ZWQgYXMgYSBkaXNhc3RlciB0eXBlLCBub3QKIyAiY2hlbWljYWwgc3BpbGwiIG9yICJmaXJlIiBvciB3aGF0ZXZlcikuIFNvLCBtYWtlIGEgbmV3IGNvbHVtbiBvZiB0aGUgYWN0dWFsCiMgZGlzYXN0ZXIgdHlwZSB1c2luZyB0aGUgcmVhbCB0eXBlIGZvciBuYXR1cmFsIGRpc2FzdGVycyBhbmQgdGhlIHN1Ymdyb3VwIGZvcgojIG5vbi1uYXR1cmFsIGRpc2FzdGVycy4KIwojIEFsc28sIGFkZCBhIGNvdXBsZSByb3dzIGZvciBjb21wbGV4IGFuZCBtaXNjZWxsYW5lb3VzIGRpc2FzdGVycwpkaXNhc3Rlci5jbGFzc2lmaWNhdGlvbiA8LSBkaXNhc3Rlci5jbGFzc2lmaWNhdGlvbi5yYXdbWzFdXSAlPiUKICBzZWxlY3QoLURlZmluaXRpb24pICU+JQogIG11dGF0ZV9hbGwoZnVucyhzdHJfdHJpbShzdHJfdG9fbG93ZXIoLikpKSkgJT4lCiAgIyBGaXggdHlwbwogIG11dGF0ZShgRGlzYXN0ZXIgU3ViZ3JvdXBgID0gaWZlbHNlKGBEaXNhc3RlciBTdWJncm91cGAgPT0gIm1pc2NlbGxlYW5vdXMgYWNjaWRlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtaXNjZWxsYW5lb3VzIGFjY2lkZW50IiwgYERpc2FzdGVyIFN1Ymdyb3VwYCkpICU+JQogIG11dGF0ZShgQWN0dWFsIFR5cGVgID0gaWZlbHNlKGBEaXNhc3RlciBHcm91cGAgPT0gIm5hdHVyYWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgRGlzYXN0ZXIgTWFpbiBUeXBlYCwgYERpc2FzdGVyIFN1Ymdyb3VwYCkpICU+JQogIGRpc3RpbmN0KGBEaXNhc3RlciBHcm91cGAsIGBEaXNhc3RlciBTdWJncm91cGAsIGBBY3R1YWwgVHlwZWApICU+JQogIGJpbmRfcm93cyh0cmliYmxlKAogICAgfmBEaXNhc3RlciBHcm91cGAsIH5gRGlzYXN0ZXIgU3ViZ3JvdXBgLCB+YEFjdHVhbCBUeXBlYCwKICAgICJjb21wbGV4IiwgICAgICAgICAiY29tcGxleCBkaXNhc3RlcnMiLCAgImNvbXBsZXggZGlzYXN0ZXJzIgogICkpCgojIERpc2FzdGVyIGRhdGEKIyBodHRwOi8vd3d3LmVtZGF0LmJlL2FkdmFuY2VkX3NlYXJjaC9pbmRleC5odG1sCgojIFNlbGVjdCBhbGwgY291bnRyaWVzIGZyb20gd2hlbmV2ZXIgdG8gMjAxNgojIFNlbGVjdCBhbGwgdGhyZWUgZGlzYXN0ZXIgY2xhc3NpZmljYXRpb24gZ3JvdXBzIChuYXR1cmFsLCB0ZWNobm9sb2dpY2FsLCBjb21wbGV4KQojIEdyb3VwIHJlc3VsdHMgYnkgY291bnRyeSBuYW1lLCB5ZWFyLCBhbmQgZGlzYXN0ZXIgdHlwZQojIERvd25sb2FkIENTViBhbmQgc2F2ZSBpbiBEYXRhL2RhdGFfcmF3L0Rpc2FzdGVycwoKZGlzYXN0ZXJzLnJhdyA8LSByZWFkX2NzdihoZXJlKCJEYXRhIiwgImRhdGFfcmF3IiwgIkRpc2FzdGVycyIsICJkYXRhLmNzdiIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHNraXAgPSAxKSAgIyBGaXJzdCByb3cgaXMganVuawoKIyBSZWFkIGluIGRpc2FzdGVyIGRhdGEgYW5kIGpvaW4gd2l0aCBjbGFzc2lmaWNhdGlvbiBkYXRhCmRpc2FzdGVycyA8LSBkaXNhc3RlcnMucmF3ICU+JQogIG11dGF0ZShgZGlzYXN0ZXIgdHlwZWAgPSBzdHJfdHJpbShzdHJfdG9fbG93ZXIoYGRpc2FzdGVyIHR5cGVgKSkpICU+JQogIG11dGF0ZShgZGlzYXN0ZXIgdHlwZWAgPSBpZmVsc2UoYGRpc2FzdGVyIHR5cGVgID09ICJtYXNzIG1vdmVtZW50IChkcnkpIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtYXNzIG1vdmVtZW50IiwgYGRpc2FzdGVyIHR5cGVgKSkgJT4lCiAgbGVmdF9qb2luKGRpc2FzdGVyLmNsYXNzaWZpY2F0aW9uLCBieSA9IGMoImRpc2FzdGVyIHR5cGUiID0gIkFjdHVhbCBUeXBlIikpICU+JQogICMgR2V0IHJpZCBvZiB0aW55IGNvdW50cmllcwogIGZpbHRlcighKGlzbyAlaW4lIGMoIkFJQSIsICJBTlQiLCAiQVNNIiwgIkFaTyIsICJCTVUiLCAiQ09LIiwgIkNTSyIsICJDWU0iLCAKICAgICAgICAgICAgICAgICAgICAgICJERFIiLCAiR0xQIiwgIkdVRiIsICJHVU0iLCAiTUFDIiwgIk1OUCIsICJNU1IiLCAiTVRRIiwgCiAgICAgICAgICAgICAgICAgICAgICAiTVlUIiwgIk5DTCIsICJOSVUiLCAiUFJJIiwgIlBZRiIsICJSRVUiLCAiU0hOIiwgIlNQSSIsIAogICAgICAgICAgICAgICAgICAgICAgIlRDQSIsICJUS0wiLCAiVkdCIiwgIlZJUiIsICJXTEYiLCAiWU1EIikpKSAlPiUgCiAgbXV0YXRlKGlzbyA9IHN0cl90b191cHBlcihpc28pLCAKICAgICAgICAgY293Y29kZSA9IGNvdW50cnljb2RlKGlzbywgImlzbzNjIiwgImNvd24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VzdG9tX21hdGNoID0gYyhIS0cgPSA3MTUsIERGUiA9IDI1NSwgUFNFID0gNjY5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTVU4gPSAzNjUsIFlNTiA9IDY3OSwgU1JCID0gMzQwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTQ0cgPSAzNDUsIFlVRyA9IDM0NSkpKSAlPiUKICAjIEZpeCBtaXNzaW5nIG5hbWVzIChjb2xsYXBzaW5nIG9sZCBHZXJtYW5pZXMsIFllbWVucywgYW5kIFVTU1IpCiAgbXV0YXRlKGNvdW50cnlfbmFtZSA9IGNvdW50cnljb2RlKGlzbywgImlzbzNjIiwgImNvdW50cnkubmFtZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1c3RvbV9tYXRjaCA9IGMoREZSID0gIkdlcm1hbnkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNDRyA9ICJZdWdvc2xhdmlhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBZVUcgPSAiWXVnb3NsYXZpYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU1VOID0gIlJ1c3NpYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWU1OID0gIlllbWVuIikpKSAlPiUKICAjIEZpeCBJU09zCiAgbXV0YXRlKGlzbyA9IGNvdW50cnljb2RlKGNvdW50cnlfbmFtZSwgImNvdW50cnkubmFtZSIsICJpc28zYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1c3RvbV9tYXRjaCA9IGMoWXVnb3NsYXZpYSA9ICJZVUciKSkpICU+JQogIHNlbGVjdChjb3VudHJ5X25hbWUsIHllYXIsIGlzbzMgPSBpc28sIGNvd2NvZGUsIGRpc2FzdGVyLnR5cGUgPSBgZGlzYXN0ZXIgdHlwZWAsIAogICAgICAgICBkaXNhc3Rlci5ncm91cCA9IGBEaXNhc3RlciBHcm91cGAsIGRpc2FzdGVyLnN1Ymdyb3VwID0gYERpc2FzdGVyIFN1Ymdyb3VwYCwKICAgICAgICAgZGlzYXN0ZXIub2NjdXJyZW5jZSA9IG9jY3VycmVuY2UsIGRpc2FzdGVyLmRlYXRocyA9IGBUb3RhbCBkZWF0aHNgLAogICAgICAgICBkaXNhc3Rlci5pbmp1cmVkID0gYEluanVyZWRgLCBkaXNhc3Rlci5hZmZlY3RlZCA9IGBBZmZlY3RlZGAsCiAgICAgICAgIGRpc2FzdGVyLmhvbWVsZXNzID0gYEhvbWVsZXNzYCwgZGlzYXN0ZXIudG90YWwuYWZmZWN0ZWQgPSBgVG90YWwgYWZmZWN0ZWRgLAogICAgICAgICBkaXNhc3Rlci50b3RhbC5kYW1hZ2UgPSBgVG90YWwgZGFtYWdlYCkgJT4lCiAgZmlsdGVyKGRpc2FzdGVyLmdyb3VwICE9ICJjb21wbGV4IikKYGBgCgojIyMjIENsZWFuIGRpc2FzdGVyIGRhdGEKCmBgYHtyIHN1bW1hcml6ZS1kaXNhc3RlcnN9CiMgU3VtbWFyaXplIGRpc2FzdGVyIHZhcmlhYmxlcyBieSBjb3VudHJ5LCB5ZWFyLCBhbmQgdHlwZS9ncm91cC9zdWJncm91cApkaXNhc3Rlci52YXJzIDwtIHZhcnMoZGlzYXN0ZXIub2NjdXJyZW5jZSwgZGlzYXN0ZXIuZGVhdGhzLCBkaXNhc3Rlci5pbmp1cmVkLCAKICAgICAgICAgICAgICAgICAgICAgIGRpc2FzdGVyLmFmZmVjdGVkLCBkaXNhc3Rlci5ob21lbGVzcywgZGlzYXN0ZXIudG90YWwuYWZmZWN0ZWQsCiAgICAgICAgICAgICAgICAgICAgICBkaXNhc3Rlci50b3RhbC5kYW1hZ2UpCgpkaXNhc3RlcnMuZ3JvdXBzIDwtIGRpc2FzdGVycyAlPiUKICBncm91cF9ieShjb3djb2RlLCB5ZWFyLCBkaXNhc3Rlci5ncm91cCkgJT4lCiAgc3VtbWFyaXNlX2F0KGRpc2FzdGVyLnZhcnMsIGZ1bnMoc3VtKC4sIG5hLnJtID0gVFJVRSkpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ2F0aGVyKGtleSwgdmFsdWUsIGRpc2FzdGVyLm9jY3VycmVuY2UsIGRpc2FzdGVyLmRlYXRocywgZGlzYXN0ZXIuaW5qdXJlZCwgCiAgICAgICAgIGRpc2FzdGVyLmFmZmVjdGVkLCBkaXNhc3Rlci5ob21lbGVzcywgZGlzYXN0ZXIudG90YWwuYWZmZWN0ZWQsCiAgICAgICAgIGRpc2FzdGVyLnRvdGFsLmRhbWFnZSkgJT4lCiAgdW5pdGUoa2V5LCBkaXNhc3Rlci5ncm91cCwga2V5KSAlPiUKICBzcHJlYWQoa2V5LCB2YWx1ZSkgJT4lCiAgZmlsdGVyKHllYXIgPiAxOTgwLCB5ZWFyIDwgMjAxNikKCmRpc2FzdGVycy5ncm91cHMgJT4lIGhlYWQoMTAwKSAlPiUgZGF0YXRhYmxlKGV4dGVuc2lvbnMgPSAiUmVzcG9uc2l2ZSIpCmBgYAoKIyMjIyBTdW1tYXJ5IG9mIGNsZWFuIGRhdGEKCmBgYHtyIHNob3ctZGlzYXN0ZXJzfQpkaXNhc3RlcnMuZ3JvdXBzICU+JSBnbGltcHNlKCkKYGBgCgoKIyMgQ291bnRyaWVzIHRvIGV4Y2x1ZGUKCldlIGV4Y2x1ZGUgbG9uZy10ZXJtIGNvbnNvbGlkYXRlZCBkZW1vY3JhY2llcyBmcm9tIG91ciBhbmFseXNpcywgZm9sbG93aW5nIEZpbmtlbFBlcmV6LUxpbmFuU2VsaWdzb246MjAwNywgNDE0LiBUaGVzZSBhcmUgY2xhc3NpZmllZCBieSB0aGUgV29ybGQgQmFuayBhcyBoaWdoIGluY29tZTsgdGhleSBzY29yZSBiZWxvdyAzIG9uIEZyZWVkb20gSG91c2UncyBTY2FsZSwgcmVjZWl2ZSBubyBhaWQgZnJvbSBVU0FJRCwgYW5kIGFyZSBub3QgbmV3bHkgaW5kZXBlbmRlbnQgc3RhdGVzLgoKYGBge3IgY3JlYXRlLWNvbnNvbGlkYXRlZC1kZW1vY3JhY2llcywgcmVzdWx0cz0iYXNpcyJ9CmNvbnNvbGlkYXRlZC5kZW1vY3JhY2llcyA8LSAKICBkYXRhX2ZyYW1lKGNvdW50cnkubmFtZSA9IGMoIkFuZG9ycmEiLCAiQXVzdHJhbGlhIiwgIkF1c3RyaWEiLCAiQmFoYW1hcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmFyYmFkb3MiLCAiQmVsZ2l1bSIsICJDYW5hZGEiLCAiRGVubWFyayIsICJGaW5sYW5kIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGcmFuY2UiLCAiR2VybWFueSIsICJHcmVlY2UiLCAiR3JlbmFkYSIsICJJY2VsYW5kIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJcmVsYW5kIiwgIkl0YWx5IiwgIkphcGFuIiwgIkxpZWNodGVuc3RlaW4iLCAiTHV4ZW1ib3VyZyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWFsdGEiLCAiTW9uYWNvIiwgIk5ldGhlcmxhbmRzIiwgIk5ldyBaZWFsYW5kIiwgIk5vcndheSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2FuIE1hcmlubyIsICJTcGFpbiIsICJTd2VkZW4iLCAiU3dpdHplcmxhbmQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVuaXRlZCBLaW5nZG9tIiwgIlVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSIpKSAlPiUgCiAgbXV0YXRlKGlzbzMgPSBjb3VudHJ5Y29kZShjb3VudHJ5Lm5hbWUsICJjb3VudHJ5Lm5hbWUiLCAiaXNvM2MiKSwKICAgICAgICAgY293Y29kZSA9IGNvdW50cnljb2RlKGNvdW50cnkubmFtZSwgImNvdW50cnkubmFtZSIsICJjb3duIikpCgpjb25zb2xpZGF0ZWQuZGVtb2NyYWNpZXMgJT4lIHBhbmRvYy50YWJsZSgpCmBgYAoKCiMjIEZpbmFsIGNsZWFuIGNvbWJpbmVkIGRhdGEKCldpdGggYm90aCBkb25vci0gYW5kIGNvdW50cnktbGV2ZWwgZGF0YSwgd2UgaGF2ZSBsb3RzIG9mIGRpZmZlcmVudCBvcHRpb25zIGZvciBhbmFseXNpcy4gU2luY2Ugb3VyIGh5cG90aGVzZXMgZGVhbCB3aXRoIHF1ZXN0aW9ucyBvZiAqZG9ub3IqIHJlc3BvbnNlcywgdGhlIGRhdGEgd2UgdXNlIHRvIG1vZGVsIGRvbm9yIHJlc3BvbnNlcyB1c2VzIGRvbm9yLXllYXJzIGFzIHRoZSB1bml0IG9mIG9ic2VydmF0aW9uLiBOb3QgYWxsIGRvbm9ycyBnaXZlIG1vbmV5IHRvIHRoZSBzYW1lIGNvdW50cmllcywgc28gdGhpcyBmaW5hbCBkYXRhIGlzIG5vdCBhIGNvbXBsZXRlIHBhbmVsIChpLmUuIGl0IGRvZXMgbm90IGluY2x1ZGUgZXZlcnkgY29tYmluYXRpb24gb2YgZG9ub3JzIGFuZCB5ZWFycyksIHdoaWNoIHdpbGwgcG9zZSBzb21lIGludGVyZXN0aW5nIG1ldGhvZG9sb2dpY2FsIGlzc3VlcyB3aGVuIG1vZGVsaW5nLgoKSW4gSH4zfiB3ZSBoeXBvdGhlc2l6ZSB0aGF0IG1vcmUgYWlkIHdpbGwgYmUgYWxsb2NhdGVkIHRvIGludGVybmF0aW9uYWwgb3IgVVMtYmFzZWQgTkdPcyB0aGFuIGRvbWVzdGljIE5HT3MgaW4gcmVzcG9uc2UgdG8gaGFyc2hlciBhbnRpLU5HTyByZXN0cmljdGlvbnMuIFdoaWxlIEFpZERhdGEgdW5mb3J0dW5hdGVseSBkb2VzIG5vdCBjYXRlZ29yaXplIGFpZCBieSBjaGFubmVsIChpLmUuIGFpZCBnaXZlbiB0byBpbnRlcm5hdGlvbmFsIHZzLiBVUyB2cy4gZG9tZXN0aWMgTkdPcyksIFVTQUlEIGRvZXMuIEZvciB0aGlzIGh5cG90aGVzaXMsIHRoZW4gd2Ugb25seSBsb29rIGF0IGFpZCBnaXZlbiBieSBVU0FJRCwgbm90IHRoZSByZXN0IG9mIHRoZSBPRUNELiBBcyB3aXRoIHRoZSBwcm9wb3J0aW9uIG9mIGNvbnRlbnRpb3VzIGFpZCwgd2UgY3JlYXRlIHNpbWlsYXIgdmFyaWFibGVzIHRvIG1lYXN1cmUgdGhlIHByb3Bvcml0aW9uIG9mIGFpZCBnaXZlbiB0byBpbnRlcm5hdGlvbmFsIE5HT3MsIFVTLWJhc2VkIE5HT3MsIGFuZCBib3RoIGludGVybmF0aW9uYWwgYW5kIFVTLWJhc2VkIE5HT3MuCgpgYGB7ciBjb21iaW5lLWRvbm9yLWNvdW50cnktZGF0YX0KIyBEb25vciBkYXRhCmRvbm9yLmxldmVsLmRhdGEucmF3IDwtIGFpZGRhdGEuZmluYWwgJT4lCiAgZmlsdGVyKGNvd2NvZGUgJWluJSBkY2p3LmZ1bGwkY293Y29kZSkgJT4lCiAgZmlsdGVyKHllYXIgPiAxOTgwKSAlPiUKICBmaWx0ZXIob2RhID4gMCkgJT4lICAjIE9ubHkgbG9vayBhdCBwb3NpdGl2ZSBhaWQKICBtdXRhdGUob2RhX2xvZyA9IGxvZzFwKG9kYSkpCgojIENyZWF0ZSBmYWtlIGNvdW50cnkgY29kZXMgZm9yIG5vbi1jb3VudHJ5IGRvbm9ycwpmYWtlLmNvZGVzIDwtIGRvbm9yLmxldmVsLmRhdGEucmF3ICU+JQogIGRpc3RpbmN0KGRvbm9yLCBkb25vci50eXBlKSAlPiUKICBmaWx0ZXIoZG9ub3IudHlwZSAhPSAiQ291bnRyeSIpICU+JQogIGFycmFuZ2UoZG9ub3IudHlwZSkgJT4lIHNlbGVjdCgtZG9ub3IudHlwZSkgJT4lCiAgbXV0YXRlKGZha2UuZG9ub3IuY293Y29kZSA9IDIwMDE6KDIwMDAgKyBuKCkpLAogICAgICAgICBmYWtlLmRvbm9yLmlzbzMgPSBwYXN0ZTAoIloiLCBzdHJfc3ViKGZha2UuZG9ub3IuY293Y29kZSwgMykpKQoKZG9ub3IubGV2ZWwuZGF0YSA8LSBkb25vci5sZXZlbC5kYXRhLnJhdyAlPiUKICBsZWZ0X2pvaW4oZmFrZS5jb2RlcywgYnkgPSAiZG9ub3IiKSAlPiUKICBtdXRhdGUoZG9ub3IuY293Y29kZSA9IGlmZWxzZShpcy5uYShkb25vci5jb3djb2RlKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFrZS5kb25vci5jb3djb2RlLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25vci5jb3djb2RlKSwKICAgICAgICAgZG9ub3IuaXNvMyA9IGlmZWxzZShpcy5uYShkb25vci5pc28zKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFrZS5kb25vci5pc28zLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25vci5pc28zKSkgJT4lCiAgc2VsZWN0KC1zdGFydHNfd2l0aCgiZmFrZSIpKQoKCiMgVVNBSUQgZGF0YQojIFVTQUlEJ3MgY29udmVyc2lvbiB0byBjb25zdGFudCAyMDE1IGRvbGxhcnMgZG9lc24ndCBzZWVtIHRvIHRha2UgY291bnRyeSBkaWZmZXJlbmNlcyBpbnRvIGFjY291bnTigJR0aGUgZGVmbGF0b3IgZm9yIGVhY2ggY291bnRyeSBpbiAyMDExIGlzIGVzc2VudGlhbGx5IDk2LjY1LiBXaGVuIHRoZXJlIGFyZSBkaWZmZXJlbmNlcywgaXQncyBiZWNhdXNlIG9mIGZsb2F0aW5nIHBvaW50IGlzc3VlcyAobGlrZSwgaWYgdGhlcmUgYXJlIHRpbnkgZ3JhbnRzIG9mICQzLCB0aGVyZSBhcmVuJ3QgZW5vdWdoIGRlY2ltYWwgcG9pbnRzIHRvIGdldCB0aGUgZnJhY3Rpb24gdG8gOTYuNjUpLiBTbyB3ZSBqdXN0IHRha2UgdGhlIG1lZGlhbiB2YWx1ZSBvZiB0aGUgZGVmbGF0b3IgZm9yIGFsbCBjb3VudHJpZXMgYW5kIGFsbCBncmFudHMgYW5kIHVzZSB0aGF0LiAKIwojIFJlc2NhbGUgdGhlIDIwMTUgZGF0YSB0byAyMDExIHRvIG1hdGNoIEFpZERhdGEKIwojIERlZmxhdG9yID0gY3VycmVudCBhaWQgLyBjb25zdGFudCBhaWQgKiAxMDAKIyBDdXJyZW50IGFpZCBpbiB5ZWFyX3QgKiAoZGVmbGF0b3IgaW4geWVhcl90YXJnZXQgLyBkZWZsYXRvciBpbiB5ZWFyX3QpCnVzYWlkLmRlZmxhdG9yLjIwMTEgPC0gdXNhaWQuY2xlYW4gJT4lCiAgZmlsdGVyKHllYXIgPT0gMjAxMSkgJT4lCiAgc3VtbWFyaXNlKGRlZmxhdG9yLnRhcmdldC55ZWFyID0gbWVkaWFuKGFpZC5kZWZsYXRvciwgbmEucm0gPSBUUlVFKSkgJT4lCiAgYXMubnVtZXJpYygpCgpkb25vci5sZXZlbC5kYXRhLnVzYWlkIDwtIHVzYWlkLmNsZWFuICU+JQogIGZpbHRlcihjb3djb2RlICVpbiUgZGNqdy5mdWxsJGNvd2NvZGUpICU+JQogIGZpbHRlcih5ZWFyID4gMTk4MCkgJT4lCiAgZmlsdGVyKG9kYS51cy5jdXJyZW50ID4gMCkgJT4lCiAgbXV0YXRlKG9kYS51cy4yMDExID0gb2RhLnVzLmN1cnJlbnQgKiAodXNhaWQuZGVmbGF0b3IuMjAxMSAvIGFpZC5kZWZsYXRvcikpCgp1c2FpZC5ieS5jb3VudHJ5LnRvdGFsIDwtIGRvbm9yLmxldmVsLmRhdGEudXNhaWQgJT4lCiAgZ3JvdXBfYnkoY293Y29kZSwgeWVhcikgJT4lCiAgc3VtbWFyaXNlKG9kYS51cyA9IHN1bShvZGEudXMuMjAxMSwgbmEucm0gPSBUUlVFKSkKCnVzYWlkLmJ5LmNvdW50cnkuY2hhbm5lbCA8LSBkb25vci5sZXZlbC5kYXRhLnVzYWlkICU+JQogIGdhdGhlcihrZXksIHZhbHVlLCBjKGNoYW5uZWwubmdvLnVzLCBjaGFubmVsLm5nby5pbnQsIGNoYW5uZWwubmdvLmRvbSkpICU+JQogIGdyb3VwX2J5KGNvd2NvZGUsIHllYXIsIGtleSwgdmFsdWUpICU+JQogIHN1bW1hcmlzZSh0b3RhbC5vZGEudXMgPSBzdW0ob2RhLnVzLjIwMTEsIG5hLnJtID0gVFJVRSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICB1bml0ZShjaGFubmVsLCBrZXksIHZhbHVlKSAlPiUKICBmaWx0ZXIoc3RyX2RldGVjdChjaGFubmVsLCAiVFJVRSIpKSAlPiUKICBtdXRhdGUoY2hhbm5lbCA9IHN0cl9yZXBsYWNlKGNoYW5uZWwsICJjaGFubmVsIiwgIm9kYS51cyIpLAogICAgICAgICBjaGFubmVsID0gc3RyX3JlcGxhY2UoY2hhbm5lbCwgIl9UUlVFIiwgIiIpKSAlPiUKICBzcHJlYWQoY2hhbm5lbCwgdG90YWwub2RhLnVzLCBmaWxsID0gMCkKCgojIENvdW50cnkgZGF0YQojIFVzZSBEQ0pXIDE5ODArIGFzIGJhc2UgZGF0YSwgc2luY2Ugd2UncmUgbGltaXRlZCB0byB0aGUgY291bnRyaWVzIGluY2x1ZGVkIHRoZXJlCmNvdW50cnkubGV2ZWwuZGF0YSA8LSBkY2p3LmZ1bGwgJT4lCiAgbXV0YXRlKGV2ZXIuZGFjLmVsaWdpYmxlID0gY293Y29kZSAlaW4lIGV2ZXIuZGFjLmVsaWdpYmxlKSAlPiUKICBmaWx0ZXIoIShjb3djb2RlICVpbiUgY29uc29saWRhdGVkLmRlbW9jcmFjaWVzJGNvd2NvZGUpKSAlPiUgCiAgbGVmdF9qb2luKHNlbGVjdCh2ZGVtLmNzbywgeWVhciwgY293Y29kZSwgY3NyZSwgCiAgICAgICAgICAgICAgICAgICBwb2xpdHkgPSBlX2ZoX2lwb2xpdHkyLCAKICAgICAgICAgICAgICAgICAgIGNvcnJ1cHRpb24gPSB2MnhfY29yciwgCiAgICAgICAgICAgICAgICAgICBnb3Z0LmVmZmVjdGl2ZW5lc3MgPSBlX3diZ2lfZ2VlKSwKICAgICAgICAgICAgYnkgPSBjKCJjb3djb2RlIiwgInllYXIiKSkgJT4lCiAgbXV0YXRlKGNvcnJ1cHRpb24gPSBjb3JydXB0aW9uICogMTApICU+JQogIGxlZnRfam9pbihzZWxlY3Qod2RpLmNsZWFuLCAtYyhpc28yYywgY291bnRyeSkpLCBieSA9IGMoImNvd2NvZGUiLCAieWVhciIpKSAlPiUKICAjIEJyaW5nIGluIFVOIHBvcHVsYXRpb24gZGF0YQogIGxlZnRfam9pbih1bi5wb3AsIGJ5ID0gYygiY293Y29kZSIsICJ5ZWFyIikpICU+JQogICMgUHJlZmVyIFVOIHBvcHVsYXRpb24gZGF0YSwgYnV0IHVzZSBXb3JsZCBCYW5rIGlmIG1pc3NpbmcKICBtdXRhdGUocG9wdWxhdGlvbiA9IGlmZWxzZShpcy5uYSh1bi5wb3B1bGF0aW9uKSwgcG9wdWxhdGlvbiwgdW4ucG9wdWxhdGlvbikpICU+JQogICMgQnJpbmcgaW4gVU4gR0RQIGRhdGEKICAjIFByZWZlciBVTiBHRFAgZGF0YSwgYnV0IHVzZSBXb3JsZCBCYW5rIGlmIG1pc3NpbmcKICBsZWZ0X2pvaW4odW4uZ2RwLmZpbmFsLCBieSA9IGMoImNvd2NvZGUiLCAieWVhciIpKSAlPiUKICBtdXRhdGUodW4udHJhZGUucGN0LmdkcCA9IHVuLnRyYWRlLnBjdC5nZHAgKiAxMDApICU+JQogIG11dGF0ZShnZHAgPSBpZmVsc2UoaXMubmEodW4uZ2RwKSwgZ2RwLCB1bi5nZHApLAogICAgICAgICB0cmFkZS5wY3QuZ2RwID0gaWZlbHNlKGlzLm5hKHVuLnRyYWRlLnBjdC5nZHApLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFkZS5wY3QuZ2RwLCB1bi50cmFkZS5wY3QuZ2RwKSkgJT4lCiAgc2VsZWN0KC1zdGFydHNfd2l0aCgidW4uIikpICU+JQogIGxlZnRfam9pbihzZWxlY3QoY29sLmNsZWFuLCAtY291bnRyeS5uYW1lKSwgYnkgPSBjKCJjb3djb2RlIikpICU+JQogIGxlZnRfam9pbihzZWxlY3QoZGlzYXN0ZXJzLmdyb3VwcywgY293Y29kZSwgeWVhciwgc3RhcnRzX3dpdGgoIm5hdHVyYWxfIikpLCAKICAgICAgICAgICAgYnkgPSBjKCJjb3djb2RlIiwgInllYXIiKSkgJT4lCiAgIyBOQXMgaW4gZGlzYXN0ZXJzIGFyZSByZWFsbHkgMCwgZXNwZWNpYWxseSB3aGVuIG9jY3VycmVuY2UgaXMgMAogIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJuYXR1cmFsXyIpKSwgZnVucyhpZmVsc2UoaXMubmEoLiksIDAsIC4pKSkgJT4lCiAgIyBUcmVhdCBOQXMgaW4gY29uZmxpY3RzIGFzIEZBTFNFCiAgbGVmdF9qb2luKHNlbGVjdChjb25mbGljdHMsIGNvd2NvZGUsIHllYXIgPSBZZWFyLCBjb25mbGljdC5pbnRlcm5hbCksCiAgICAgICAgICAgIGJ5ID0gYygiY293Y29kZSIsICJ5ZWFyIikpICU+JQogIG11dGF0ZShjb25mbGljdC5pbnRlcm5hbCA9IGlmZWxzZShpcy5uYShjb25mbGljdC5pbnRlcm5hbCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZBTFNFLCBjb25mbGljdC5pbnRlcm5hbCkpICU+JQogICMgQWRkIGluZGljYXRvciBmb3IgcG9zdC1Db2xkIFdhciwgc2luY2UgYWxsIHRoZSBmb3JtZXIgU292aWV0IHJlcHVibGljcyBoYXZlCiAgIyBubyBHRFAgZGF0YSBiZWZvcmUgMTk5MAogIG11dGF0ZShwb3N0LjE5ODkgPSB5ZWFyID49IDE5OTApCnRlc3R0aGF0OjpleHBlY3RfZXF1YWwobnJvdyhjb3VudHJ5LmxldmVsLmRhdGEpLCAKICAgICAgICAgICAgICAgICAgICAgICBucm93KGZpbHRlcihkY2p3LmZ1bGwsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICEoY293Y29kZSAlaW4lIGNvbnNvbGlkYXRlZC5kZW1vY3JhY2llcyRjb3djb2RlKSkpKQoKIyBDb21iaW5lIGNvdW50cnkgYW5kIGRvbm9yIGRhdGEKZG9ub3IuY291bnRyeS5kYXRhIDwtIGRvbm9yLmxldmVsLmRhdGEgJT4lCiAgbGVmdF9qb2luKHNlbGVjdChjb3VudHJ5LmxldmVsLmRhdGEsIC1jb3VudHJ5Lm5hbWUpLAogICAgICAgICAgICBieSA9IGMoInllYXIiLCAiY293Y29kZSIpKSAlPiUKICBtdXRhdGUoZm9ybWVyLmNvbG9ueSA9IGRvbm9yLmNvd2NvZGUgPT0gY29sLnJ1bGVyLmNvd2NvZGUgfCAKICAgICAgICAgICBkb25vci5jb3djb2RlID09IGluZC5mcm9tLmNvd2NvZGUpICU+JQogIGFycmFuZ2UoZG9ub3IsIHllYXIpCnRlc3R0aGF0OjpleHBlY3RfZXF1YWwobnJvdyhkb25vci5jb3VudHJ5LmRhdGEpLCBucm93KGRvbm9yLmxldmVsLmRhdGEpKQoKIyBDYWxjdWxhdGUgZGlmZmVyZW50IHZlcnNpb25zIG9mIGFpZCB2YXJpYWJsZXMKYWlkLmJ5LmNvdW50cnkudG90YWwgPC0gZG9ub3IuY291bnRyeS5kYXRhICU+JQogIGdyb3VwX2J5KGNvd2NvZGUsIHllYXIpICU+JQogIHN1bW1hcmlzZSh0b3RhbC5vZGEgPSBzdW0ob2RhLCBuYS5ybSA9IFRSVUUpKQoKYWlkLmJ5LmNvdW50cnkucHVycG9zZSA8LSBkb25vci5jb3VudHJ5LmRhdGEgJT4lCiAgZ3JvdXBfYnkoY293Y29kZSwgeWVhciwgcHVycG9zZS5jb250ZW50aW91c25lc3MpICU+JQogIHN1bW1hcmlzZSh0b3RhbC5vZGEgPSBzdW0ob2RhLCBuYS5ybSA9IFRSVUUpKSAlPiUKICBzcHJlYWQocHVycG9zZS5jb250ZW50aW91c25lc3MsIHRvdGFsLm9kYSwgZmlsbCA9IDApICU+JQogIHJlbmFtZShvZGEuY29udGVudGlvdXMuaGlnaCA9IEhpZ2gsIAogICAgICAgICBvZGEuY29udGVudGlvdXMubG93ID0gTG93KQoKIyBOZWlnaGJvciBhaWQKIyBKb2luIHRvdGFsIG9kYSB0byB0aGUgaHVnZSBkaXN0YW5jZXMgZGF0YWZyYW1lIGFuZCBjYWxjdWxhdGUgdG90YWwgYW5kCiMgYXZlcmFnZSBhaWQgdG8gbmVpZ2hib3JpbmcgY291bnRyaWVzCm5laWdoYm9yLm9kYSA8LSBhbGwuZGlzdGFuY2VzICU+JQogIGZpbHRlcihpcy5yb3VnaC5uZWlnaGJvcikgJT4lCiAgbGVmdF9qb2luKGFpZC5ieS5jb3VudHJ5LnRvdGFsLCBieSA9IGMoImNvd2NvZGUub3RoZXIiID0gImNvd2NvZGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ5ZWFyIikpICU+JQogIGZpbHRlcihjb3djb2RlLnNlbGYgIT0gY293Y29kZS5vdGhlcikgJT4lCiAgZ3JvdXBfYnkoeWVhciwgY293Y29kZS5zZWxmKSAlPiUKICBzdW1tYXJpc2VfYXQodmFycyh0b3RhbC5vZGEpLCAKICAgICAgICAgICAgICAgZnVucyhuYl9vZGEuc3VtID0gc3VtKC4sIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgbmJfb2RhLmF2ZyA9IG1lYW4oLiwgbmEucm0gPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgICBuYl9vZGEuc2QgPSBzZCguLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgIG5iX29kYS5uID0gbigpKSkgJT4lCiAgcmVuYW1lKGNvd2NvZGUgPSBjb3djb2RlLnNlbGYpICU+JQogIGZpbHRlcih5ZWFyIDwgMjAxNCkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIm5iIikpLAogICAgICAgICAgICBmdW5zKGlmZWxzZShpcy5uYW4oLiksIDAsIC4pKSkKYGBgCgojIyMgTWlzc2luZ25lc3MgYW5kIGltcHV0YXRpb24KClRoZSBkb25vciBkYXRhIGlzIGNvbXBsZXRlIHdpdGggbm8gbWlzc2luZyB2YXJpYWJsZXMoISkuCgpgYGB7ciBmaW5hbC1kYXRhLW1pc3NpbmctZG9ub3JzLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD0zfQpwbG90LnBlcmNlbnQubWlzc2luZyhkb25vci5sZXZlbC5kYXRhKQpgYGAKClRoZSBjb3VudHJ5LWxldmVsIHBhbmVsIGRhdGEgaXMgcmVsYXRpdmVseSBjb21wbGV0ZSwgd2l0aCBvbmx5IGEgZmV3IHZhcmlhYmxlcyBzdWZmZXJpbmcgZnJvbSBtaXNzaW5nIGRhdGEsIG1vc3RseSBmcm9tIHRoZSBXb3JsZCBCYW5rIGFuZCBWLURlbS4KCmBgYHtyIGZpbmFsLWRhdGEtbWlzc2luZy1jb3VudHJpZXMsIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTV9CnBsb3QucGVyY2VudC5taXNzaW5nKGNvdW50cnkubGV2ZWwuZGF0YSkKYGBgCgpUaGF0IHNhaWQsIGl0J3Mgc3RpbGwgaGVscGZ1bCB0byBpbXB1dGUgdGhlIG1pc3NpbmcgdmFyaWFibGVzLCBlc3BlY2lhbGx5IHNpbmNlIHBvbGl0eSwgY29ycnVwdGlvbiwgYW5kIEdEUCBhcmUgYWxsIG1haW4gY29udHJvbHMgKHBsdXMgW0xhbGwgMjAxNl0oaHR0cHM6Ly9kb2kub3JnLzEwLjEwOTMvcGFuL21wdzAyMCkgc2hvd3MgdGhlIGRvd25zaWRlcyBvZiBub3QgaW1wdXRpbmcpLiBTbywgd2UgdXNlIFtBbWVsaWFdKGh0dHA6Ly9na2luZy5oYXJ2YXJkLmVkdS9hbWVsaWEpIHRvIGltcHV0ZSBtaXNzaW5nIHZhcmlhYmxlcy4KCldlIHVsdGltYXRlbHkgY3JlYXRlIGEgbG9uZyBkYXRhIGZyYW1lIHdpdGggZWFjaCBvZiB0aGUgaW1wdXRlZCBkYXRhc2V0cyBzdGFja2VkIHVuZGVyIHRoZSBvcmlnaW5hbCBkYXRhc2V0LiBEYXRhc2V0cyBhcmUgaWRlbnRpZmllZCB3aXRoIHRoZSBjb2x1bW4gYG1gLCBsaWtlIHNvOgoKYGBge3Igc3RhY2tlZC1kYXRhLWV4YW1wbGUsIHJlc3VsdHM9ImFzaXMifQpzdGFja2VkLmRhdGEgPC0gdHJpYmJsZSgKICB+bSwgfmNvdW50cnksIH55ZWFyLCB+dmFyaWFibGUsCiAgIm9yaWdpbmFsIiwgIkFmZ2hhbmlzdGFuIiwgIjIwMDAiLCA1LAogICJvcmlnaW5hbCIsICJBZmdoYW5pc3RhbiIsICIyMDAxIiwgTkEsCiAgIm9yaWdpbmFsIiwgIkFmZ2hhbmlzdGFuIiwgIjIwMDIiLCA2LAogICIuLi4iLCAiLi4uIiwgIi4uLiIsIE5BLAogICJpbXAxIiwgIkFmZ2hhbmlzdGFuIiwgIjIwMDAiLCA1LAogICJpbXAxIiwgIkFmZ2hhbmlzdGFuIiwgIjIwMDEiLCA1LjMsCiAgImltcDEiLCAiQWZnaGFuaXN0YW4iLCAiMjAwMiIsIDYsCiAgIi4uLiIsICIuLi4iLCAiLi4uIiwgTkEsCiAgImltcDIiLCAiQWZnaGFuaXN0YW4iLCAiMjAwMCIsIDUsCiAgImltcDIiLCAiQWZnaGFuaXN0YW4iLCAiMjAwMSIsIDUuOCwKICAiaW1wMiIsICJBZmdoYW5pc3RhbiIsICIyMDAyIiwgNiwKICAiLi4uIiwgIi4uLiIsICIuLi4iLCBOQQopCgpwYW5kb2MudGFibGUoc3RhY2tlZC5kYXRhKQpgYGAKCldlIGVzdGltYXRlIG1vZGVscyBmb3IgZWFjaCBvZiB0aGUgaW1wdXRlZCBkYXRhc2V0cyBhbmQgcmVjb21iaW5lIHRoZWlyIHJlc3VsdHMuIFdlIHVzZSBgYW1lbGlhOjptaS5tZWxkKClgIHRvIGNvbWJpbmUgZXN0aW1hdGVzIGFuZCBzdGFuZGFyZCBlcnJvcnMgZnJvbSBmcmVxdWVudGlzdCBtb2RlbHMgKGZvbGxvd2luZyBbS2luZyBldCBhbC4gMjAwMV0oaHR0cDovL2draW5nLmhhcnZhcmQuZWR1L2ZpbGVzL2Ficy9ldmlsLWFicy5zaHRtbCkpLCBhbmQgd2UgW21lcmdlIHRoZSBNQ01DIGNoYWluc10oaHR0cHM6Ly9ncm91cHMuZ29vZ2xlLmNvbS9kL21zZy9zdGFuLXVzZXJzL2RhcVA4OGNGUUdZL0YtZ0pMa0Z1WGxRSikgZnJvbSBCYXllc2lhbiBtb2RlbHMgKFtzZWUgYWxzbyB0aGlzXShodHRwczovL2dyb3Vwcy5nb29nbGUuY29tL2ZvcnVtLyMhdG9waWMvc3Rhbi11c2Vycy8waHFWX1JEeDlNVSkpLgoKV2UgdmFyaWVkIHRoZSBudW1iZXIgb2YgZGF0YXNldHMgd2UgaW1wdXRlZCAoKm0qID0gNSBhbmQgKm0qID0gMTApIGFuZCBbZm91bmQgb25seSB0cml2aWFsIGRpZmZlcmVuY2VzIGluIGNvZWZmaWNpZW50cyBiZXR3ZWVuIDUgYW5kIDEwIGRhdGFzZXRzXSguLi9BbmFseXNpcy9tb2RlbHMuaHRtbCNpbXB1dGF0aW9uKSAoYXMgcHJlZGljdGVkIGJ5IEtpbmcgZXQgYWwuKS4gSW4gdGhlIGludGVyZXN0IG9mIGNvbXB1dGF0aW9uYWwgZWZmaWNpZW5jeSBhbmQgc3BlZWQsIHdlIG9ubHkgdXNlIDUgaW1wdXRlZCBkYXRhc2V0cy4gVG8gYXZvaWQgbmVlZGluZyB0byByZWNyZWF0ZSBib3RoIDUgYW5kIDEwIGRhdGFzZXRzLCB3ZSBpbXB1dGUgMTAsIGJ1dCBvbmx5IHVzZSB0aGUgZmlyc3QgNSBmb3IgYW5hbHlzaXMuCgpgYGB7ciBpbXB1dGUtbWlzc2luZy1kYXRhLCByZXN1bHRzPSJoaWRlIn0KaW1wdXRhdGlvbi5yZHMgPC0gaGVyZSgiRGF0YSIsICJkYXRhX2NhY2hlIiwgImNvdW50cnlfYWlkX2RhdGFfaW1wdXRlZF9sb25nLnJkcyIpCgppZiAoZmlsZS5leGlzdHMoaW1wdXRhdGlvbi5yZHMpKSB7CiAgY291bnRyeS5haWQuZGF0YS5pbXB1dGVkLmxvbmcgPC0gcmVhZFJEUyhoZXJlKCJEYXRhIiwgImRhdGFfY2FjaGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiY291bnRyeV9haWRfZGF0YV9pbXB1dGVkX2xvbmcucmRzIikpCn0gZWxzZSB7CiAgIyBUSElTIFRBS0VTIFNPIExPTkcuCiAgIwogICMgQ29tYmluZSBhaWQgZGF0YSB3aXRoIGNvdW50cnkgZGF0YQogIGNvdW50cnkuYWlkLmRhdGEucHJlLnRyYW5zZm9ybWF0aW9uIDwtIGNvdW50cnkubGV2ZWwuZGF0YSAlPiUKICAgIGZpbHRlcih5ZWFyIDwgMjAxNCkgJT4lICAjIFRoZXJlJ3Mgbm8gYWlkIGRhdGEgYWZ0ZXIgMjAxMwogICAgbGVmdF9qb2luKGFpZC5ieS5jb3VudHJ5LnRvdGFsLCBieSA9IGMoImNvd2NvZGUiLCAieWVhciIpKSAlPiUKICAgIGxlZnRfam9pbihhaWQuYnkuY291bnRyeS5wdXJwb3NlLCBieSA9IGMoImNvd2NvZGUiLCAieWVhciIpKSAlPiUKICAgIGxlZnRfam9pbihuZWlnaGJvci5vZGEsIGJ5ID0gYygiY293Y29kZSIsICJ5ZWFyIikpICU+JQogICAgbGVmdF9qb2luKHVzYWlkLmJ5LmNvdW50cnkudG90YWwsIGJ5ID0gYygiY293Y29kZSIsICJ5ZWFyIikpICU+JQogICAgbGVmdF9qb2luKHVzYWlkLmJ5LmNvdW50cnkuY2hhbm5lbCwgYnkgPSBjKCJjb3djb2RlIiwgInllYXIiKSkgJT4lCiAgICBtdXRhdGVfYXQodmFycyhjb250YWlucygib2RhIikpLCBmdW5zKGlmZWxzZShpcy5uYSguKSwgMCwgLikpKQogIAogICMgTWlzc2luZyBQb2xpdHkgdmFsdWVzIGFyZSBlYXN54oCUbW9zdCBhcmUganVzdCBvbmUteWVhciBnYXBzIHdpdGggdGhlIHNhbWUKICAjIHZhbHVlIGJlZm9yZSBhbmQgYWZ0ZXIsIHNvIGludGVycG9sYXRlIHRoZSBtaXNzaW5nIHZhbHVlcwogIHBvbGl0eS5pbXB1dGVkIDwtIGNvdW50cnkuYWlkLmRhdGEucHJlLnRyYW5zZm9ybWF0aW9uICU+JQogICAgc2VsZWN0KGNvd2NvZGUsIHllYXIsIHBvbGl0eSkgJT4lCiAgICBncm91cF9ieShjb3djb2RlKSAlPiUKICAgIG11dGF0ZShpbXB1dGUucG9saXR5ID0gIWFsbChpcy5uYShwb2xpdHkpKSkgJT4lCiAgICBtdXRhdGUocG9saXR5ID0gaWZlbHNlKGltcHV0ZS5wb2xpdHksIG5hLmludGVycG9sYXRpb24ocG9saXR5KSwgcG9saXR5KSkgJT4lCiAgICB1bmdyb3VwKCkgJT4lIHNlbGVjdCgtaW1wdXRlLnBvbGl0eSkKICAKICBjb3VudHJ5LmFpZC5kYXRhLnByZS5hbWVsaWEgPC0gY291bnRyeS5haWQuZGF0YS5wcmUudHJhbnNmb3JtYXRpb24gJT4lIAogICAgc2VsZWN0KC1wb2xpdHkpICU+JSAKICAgIGxlZnRfam9pbihwb2xpdHkuaW1wdXRlZCwgYnkgPSBjKCJjb3djb2RlIiwgInllYXIiKSkKICAKICAjIFNlbGVjdCB0aGUgdmFyaWFibGVzIHRvIG5vdCBpbmNsdWRlIGluIHRoZSBpbXB1dGF0aW9uIG1vZGVsLiBMZWZ0IGpvaW4gdGhpcwogICMgZGF0YSBmcmFtZSBsYXRlciB3aXRoIHRoZSBpbXB1dGVkIGRhdGEKICB2YXJzLnRvLmluY2x1ZGUuaW4uaW1wdXRhdGlvbiA8LSBjb3VudHJ5LmFpZC5kYXRhLnByZS5hbWVsaWEgJT4lCiAgICBzZWxlY3QoY3NyZSwgY29ycnVwdGlvbiwgZ292dC5lZmZlY3RpdmVuZXNzLCBwb3B1bGF0aW9uLCB0cmFkZS5wY3QuZ2RwLAogICAgICAgICAgIGdkcCwgc3RhcnRzX3dpdGgoIm5hdHVyYWwiKSwgdG90YWwub2RhLCBwb2xpdHkpICU+JQogICAgc2VsZWN0KC1uYXR1cmFsX2Rpc2FzdGVyLnRvdGFsLmFmZmVjdGVkKQogIAogICMgVmVjdG9yIG9mIHZhcmlhYmxlcyB0byBpbmNsdWRlCiAgdmFycy50by5pbmNsdWRlLnNhbnMuaWRzIDwtIHZhcnMudG8uaW5jbHVkZS5pbi5pbXB1dGF0aW9uICU+JSBjb2xuYW1lcygpCiAgCiAgIyBTdHJpcHBlZCBkb3duIGRhdGFzZXQgZm9yIGltcHV0YXRpb24KICBjb3VudHJ5LmFpZC5kYXRhLnRvLmltcHV0ZSA8LSBjb3VudHJ5LmFpZC5kYXRhLnByZS5hbWVsaWEgJT4lCiAgICBzZWxlY3QoeWVhciwgY293Y29kZSwgb25lX29mKHZhcnMudG8uaW5jbHVkZS5zYW5zLmlkcykpCiAgCiAgIyBJbXB1dGF0aW9uIG1vZGVsIHR3ZWFrcwogICMgVmFyaWFibGVzIHRoYXQgd2lsbCBiZSBsYWdnZWQgYW5kIGxlYWRlZAogIHZhcnMudG8ubGFnLmxlYWQgPC0gYygiY3NyZSIsICJwb2xpdHkiLCAiY29ycnVwdGlvbiIsICJwb3B1bGF0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgICAgInRyYWRlLnBjdC5nZHAiLCAiZ2RwIikKICAjIFZhcmlhYmxlcyB0aGF0IHdpbGwgYmUgbG9nZ2VkCiAgdmFycy50by5sb2cgPC0gYygiZ2RwIiwgInBvcHVsYXRpb24iKQogIAogICMgUnVuIGltcHV0YXRpb24gbW9kZWwKICBzZXQuc2VlZChteS5zZWVkKQogIGNvdW50cnkuYWlkLmRhdGEuYW1lbGlhIDwtIGFtZWxpYShjb3VudHJ5LmFpZC5kYXRhLnRvLmltcHV0ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbSA9IDEwLCB0cyA9ICJ5ZWFyIiwgY3MgPSAiY293Y29kZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmNzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW1wcmkgPSAwLjAzICogbnJvdyhjb3VudHJ5LmFpZC5kYXRhLnRvLmltcHV0ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAycyA9IDEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWdzID0gdmFycy50by5sYWcubGVhZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVhZHMgPSB2YXJzLnRvLmxhZy5sZWFkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2dzID0gdmFycy50by5sb2csCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFsbGVsID0gIm11bHRpY29yZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jcHVzID0gcGFyYWxsZWw6OmRldGVjdENvcmVzKCkpCiAgCiAgIyBBcHBlbmQgbGlzdCBvZiBpbXB1dGVkIGRhdGFzZXRzIHRvIG9yaWdpbmFsIGluIGEgbG9uZyBkYXRhIGZyYW1lIGFuZCBicmluZwogICMgYmFjayB0aGUgb21pdHRlZCB2YXJpYWJsZXMKICBjb3VudHJ5LmFpZC5kYXRhLmltcHV0ZWQubG9uZyA8LSAKICAgIGJpbmRfcm93cyhtdXRhdGUoY291bnRyeS5haWQuZGF0YS50by5pbXB1dGUsIG0gPSAib3JpZ2luYWwiKSwKICAgICAgICAgICAgICBiaW5kX3Jvd3ModW5jbGFzcyhjb3VudHJ5LmFpZC5kYXRhLmFtZWxpYSRpbXB1dGF0aW9ucyksIC5pZCA9ICJtIikpICU+JQogICAgc2VsZWN0KG0sIGV2ZXJ5dGhpbmcoKSkgJT4lCiAgICBsZWZ0X2pvaW4oc2VsZWN0KGNvdW50cnkuYWlkLmRhdGEucHJlLmFtZWxpYSwgCiAgICAgICAgICAgICAgICAgICAgIC1vbmVfb2YodmFycy50by5pbmNsdWRlLnNhbnMuaWRzKSksIGJ5ID0gYygiY293Y29kZSIsICJ5ZWFyIikpCiAgCiAgc2F2ZVJEUyhjb3VudHJ5LmFpZC5kYXRhLmltcHV0ZWQubG9uZywgaGVyZSgiRGF0YSIsICJkYXRhX2NhY2hlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjb3VudHJ5X2FpZF9kYXRhX2ltcHV0ZWRfbG9uZy5yZHMiKSkKfQpgYGAKCmBgYHtyIGxvZy1sZWFkLWxhZy1ldmVyeXRoaW5nLCBjYWNoZT1UUlVFfQojIExvZywgbGVhZCwgYW5kIGxhZyBldmVyeXRoaW5nIGJhc2VkIG9uIHRoZSBiaWcgZGF0YXNldCBvZiBpbXB1dGF0aW9ucwoKIyBwY3QuY2hhbmdlIDwtIGZ1bmN0aW9uKHgpIHsKIyAgIChsZWFkKHgpIC8geCkgLSAxCiMgfQoKIyBEZXRlcm1pbmUgaWYgYW55IG9mIHRoZSB2YWx1ZXMgaW4gdGhlIGxhc3QgayByb3dzIGFyZSBUUlVFCmNoZWNrX2xhc3RfayA8LSBmdW5jdGlvbih4LCBrKSB7CiAgIyBUaGlzIGNyZWF0ZXMgYSBtYXRyaXggd2l0aCBhIGNvbHVtbiBmb3IgZWFjaCBsYWcgdmFsdWUgKGUuZy4gY29sdW1uIDEgPSBsYWcKICAjIDAsIGNvbHVtbiAyID0gbGFnIDEsIGV0Yy4pCiAgYWxsLmxhZ3MgPC0gc2FwcGx5KDA6aywgRlVOID0gZnVuY3Rpb24oaykgbGFnKHgsIGspKQogIAogICMgTWFya2UgVFJVRSBpZiBhbnkgb2YgdGhlIGNvbHVtbnMgaGF2ZSBUUlVFIGluIHRoZW0KICBhbnkudHJ1ZS5pbi53aW5kb3cgPC0gYXBwbHkoYWxsLmxhZ3MsIE1BUkdJTiA9IDEsIEZVTiA9IGFueSwgbmEucm0gPSBUUlVFKQogIHJldHVybihhbnkudHJ1ZS5pbi53aW5kb3cpCn0KCmNvdW50cnkuYWlkLmRhdGEgPC0gY291bnRyeS5haWQuZGF0YS5pbXB1dGVkLmxvbmcgJT4lCiAgbXV0YXRlKGdkcC5jYXBpdGEgPSBnZHAgLyBwb3B1bGF0aW9uKSAlPiUKICBtdXRhdGVfYXQodmFycyhnZHAuY2FwaXRhLCBnZHAsIHBvcHVsYXRpb24pLCBmdW5zKGxvZyA9IGxvZzFwKSkgJT4lCiAgIyBDYWxjdWxhdGUgcHJvcC5jb250ZW50aW91cyBoZXJlIHNpbmNlIHRoZXJlIHNob3VsZCBiZSBzb21lIG1pc3NpbmcgdmFsdWVzCiAgIyAoc2luY2UgdGhlcmUgYXJlIGNvdW50cnkteWVhcnMgd2hlcmUgdGhlcmUncyBubyBPREEpCiAgbXV0YXRlKHByb3AuY29udGVudGlvdXMgPSBvZGEuY29udGVudGlvdXMuaGlnaCAvIAogICAgICAgICAgIChvZGEuY29udGVudGlvdXMubG93ICsgb2RhLmNvbnRlbnRpb3VzLmhpZ2gpKSAlPiUKICBtdXRhdGUocHJvcC5jb250ZW50aW91cyA9IGlmZWxzZShpcy5uYW4ocHJvcC5jb250ZW50aW91cyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLCBwcm9wLmNvbnRlbnRpb3VzKSkgJT4lCiAgbXV0YXRlKHByb3AuY29udGVudGlvdXNfbG9naXQgPSBjYXI6OmxvZ2l0KHByb3AuY29udGVudGlvdXMsIGFkanVzdCA9IC4wMDEpKSAlPiUKICAjIENhbGN1bGF0ZSBwcm9wLm5nbyogaGVyZSBzaW5jZSB0aGVyZSBzaG91bGQgYWxzbyBiZSBzb21lIG1pc3NpbmcgdmFsdWVzCiAgbXV0YXRlKHByb3AubmdvLmludCA9IG9kYS51cy5uZ28uaW50IC8gb2RhLnVzLAogICAgICAgICBwcm9wLm5nby51cyA9IG9kYS51cy5uZ28udXMgLyBvZGEudXMsCiAgICAgICAgIHByb3AubmdvLmRvbSA9IG9kYS51cy5uZ28uZG9tIC8gb2RhLnVzLAogICAgICAgICBwcm9wLm5nby5mb3JlaWduID0gKG9kYS51cy5uZ28uaW50ICsgb2RhLnVzLm5nby51cykgLyBvZGEudXMpICU+JQogICMgcHJvcC5uZ28uZG9tLmZvcmVpZ24gPSBvZGEudXMubmdvLmRvbSAvIChvZGEudXMubmdvLmludCArIG9kYS51cy5uZ28udXMpKSAlPiUKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgicHJvcC5uZ28iKSksCiAgICAgICAgICAgIGZ1bnMoaWZlbHNlKGlzLm5hbiguKSwgTkEsIC4pKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoInByb3AubmdvIikpLAogICAgICAgICAgICBmdW5zKGxvZ2l0ID0gY2FyOjpsb2dpdCguLCBhZGp1c3QgPSAuMDAxKSkpICU+JQogIG11dGF0ZV9hdCh2YXJzKHRvdGFsLm9kYSwgb2RhLmNvbnRlbnRpb3VzLmhpZ2gsIG9kYS5jb250ZW50aW91cy5sb3csIG9kYS51cywKICAgICAgICAgICAgICAgICBuYl9vZGEuc3VtLCBuYl9vZGEuYXZnLCBuYl9vZGEuc2QpLAogICAgICAgICAgICBmdW5zKGxvZyA9IGxvZzFwKC4pKSkgJT4lCiAgbXV0YXRlKGFpZC5wY3QuZ2RwID0gdG90YWwub2RhIC8gZ2RwKSAlPiUKICAjIExhZy9sZWFkL2RpZmYgZXZlcnl0aGluZyB3aXRoaW4gY291bnRyaWVzIGFuZCBzYW1wbGVzCiAgZ3JvdXBfYnkobSwgY293Y29kZSkgJT4lCiAgIyBHZXQgbGVhZGVkIGFpZCB2YXJpYWJsZXMKICBtdXRhdGVfYXQodmFycyhjb250YWlucygib2RhIiksIHN0YXJ0c193aXRoKCJwcm9wLiIpKSwKICAgICAgICAgICAgZnVucyhuZXh0X3llYXIgPSBsZWFkKC4pLCAgIyB5X3tpLCB0KzF9CiAgICAgICAgICAgICAgICAgYWZ0ZXJfMiA9IGxlYWQoLiwgMiksCiAgICAgICAgICAgICAgICAgYWZ0ZXJfNSA9IGxlYWQoLiwgNSkpKSAlPiUgIAogICMgR2V0IGRpZmZlZCBsZWFkZWQgYWlkIHZhcmlhYmxlcwogIG11dGF0ZV9hdCh2YXJzKGNvbnRhaW5zKCJuZXh0X3llYXIiKSwgLWNvbnRhaW5zKCJsb2ciKSksCiAgICAgICAgICAgIGZ1bnMoZGlmZiA9IGxlYWQoLikgLSAuLCAgIyAoeV97aXR9IC0geV97aSwgdC0xfSlfe3QrMX0KICAgICAgICAgICAgICAgICBkaWZmX2xvZyA9IHNpZ24obGVhZCguKSAtIC4pICogCiAgICAgICAgICAgICAgICAgICBsb2cxcChhYnMobGVhZCguKSAtIC4pKSkpICU+JSAgIyBzaWduKHgpICogbG9nMXAoYWJzKHgpKQogIG11dGF0ZV9hdCh2YXJzKGNvbnRhaW5zKCJhZnRlcl8yIiksIC1jb250YWlucygibG9nIikpLAogICAgICAgICAgICBmdW5zKGRpZmYgPSBsZWFkKC4sIDIpIC0gLiwKICAgICAgICAgICAgICAgICBkaWZmX2xvZyA9IHNpZ24obGVhZCguLCAyKSAtIC4pICogCiAgICAgICAgICAgICAgICAgICBsb2cxcChhYnMobGVhZCguLCAyKSAtIC4pKSkpICU+JQogIG11dGF0ZV9hdCh2YXJzKGNvbnRhaW5zKCJhZnRlcl81IiksIC1jb250YWlucygibG9nIikpLAogICAgICAgICAgICBmdW5zKGRpZmYgPSBsZWFkKC4sIDUpIC0gLiwKICAgICAgICAgICAgICAgICBkaWZmX2xvZyA9IHNpZ24obGVhZCguLCA1KSAtIC4pICogCiAgICAgICAgICAgICAgICAgICBsb2cxcChhYnMobGVhZCguLCAyKSAtIC4pKSkpICU+JQogICMgSW5kaWNhdGUgY2hhbmdlcyBpbiBsYXdzCiAgbXV0YXRlX2F0KHZhcnMoYWR2b2NhY3ksIGFzc29jaWF0aW9uLCBlbnRyeSwgZnVuZGluZywgYmFycmllcnMudG90YWwpLAogICAgICAgICAgICBmdW5zKG5ldyA9IC4gLSBsYWcoLiksCiAgICAgICAgICAgICAgICAgd29yc2UgPSAoLiAtIGxhZyguKSkgPiAwLAogICAgICAgICAgICAgICAgIGNhdCA9IGN1dCguIC0gbGFnKC4pLAogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKC1JbmYsIC0xLCAwLCBJbmYpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJOZXcgYmV0dGVyIGxhdyIsICJObyBuZXcgbGF3cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ldyB3b3JzZSBsYXciKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZF9yZXN1bHQgPSBUUlVFKSkpICU+JQogICMgRGV0ZXJtaW5lIGlmIHRoZXJlIHdhcyBjb25mbGljdCBpbiB0aGUgcGFzdCA1IHllYXJzCiAgbXV0YXRlKGludGVybmFsLmNvbmZsaWN0LnBhc3QuNSA9IGNoZWNrX2xhc3Rfayhjb25mbGljdC5pbnRlcm5hbCwgNSkpICU+JQogIHVuZ3JvdXAoKQoKIyBTYXZlIGFsbCAxMCBpbXB1dGVkIGRhdGFzZXRzCmNvdW50cnkuYWlkLmRhdGEubTEwIDwtIGNvdW50cnkuYWlkLmRhdGEKCiMgVXNlIGp1c3QgdGhlIGZpcnN0IDUgaW1wdXRlZCBkYXRhc2V0cwpjb3VudHJ5LmFpZC5kYXRhIDwtIGNvdW50cnkuYWlkLmRhdGEgJT4lCiAgZmlsdGVyKCEobSAlaW4lIHBhc3RlMCgiaW1wIiwgNjoxMCkpKQpgYGAKClRoZSBmaW5hbCBpbXB1dGVkIGRhdGFzZXQgc3RpbGwgaGFzIG1pc3NpbmcgZGF0YSwgYnV0IHRoYXQncyBiZWNhdXNlIG9mICgxKSBgcHJvcC5jb250ZW50aW91c2AsIHdoaWNoIGlzIG1pc3NpbmcgaWYgdGhlcmUncyBubyBhaWQgaW4gYSBjb3VudHJ5IHllYXIsIGFuZCAoMikgbGFncyBhbmQgbGVhZHMgY3JlYXRlIG1pc3NpbmcgdmFsdWVzIGF0IHRoZSBiZWdpbm5pbmdzIGFuZCBlbmRzIG9mIHRoZSBjb3VudHJ5IHdpbmRvd3MuCgpgYGB7ciBwbG90LW1pc3NpbmctaW1wdXRlZCwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NSwgY2FjaGU9VFJVRX0KcGxvdC5wZXJjZW50Lm1pc3NpbmcoZmlsdGVyKGNvdW50cnkuYWlkLmRhdGEsIG0gIT0gIm9yaWdpbmFsIiksIDMpCmBgYAoKCiMjIyBTYXZlIGZpbmFsIGRhdGEKCkZpbmFsLCBjbGVhbiBjb3VudHJ5LSBhbmQgZG9ub3ItbGV2ZWwgZGF0YXNldHMgYXJlIGF2YWlsYWJsZSBpbiBgRGF0YS9kYXRhX2NsZWFuL2AuCgpgYGB7ciBzYXZlLWZpbmFsLWRhdGEsIGVjaG89RkFMU0UsIGNhY2hlPVRSVUV9CnNhdmVSRFMoZmlsdGVyKGNvdW50cnkuYWlkLmRhdGEsIG0gPT0gIm9yaWdpbmFsIiksCiAgICAgICAgZmlsZSA9IGhlcmUoIkRhdGEiLCAiZGF0YV9jbGVhbiIsICJkZl9jb3VudHJ5X2FpZF9ub19pbXB1dGF0aW9uLnJkcyIpKQoKc2F2ZVJEUyhmaWx0ZXIoY291bnRyeS5haWQuZGF0YSwgbSAhPSAib3JpZ2luYWwiKSwKICAgICAgICBmaWxlID0gaGVyZSgiRGF0YSIsICJkYXRhX2NsZWFuIiwgImRmX2NvdW50cnlfYWlkX2ltcHV0YXRpb24ucmRzIikpCgpzYXZlUkRTKGZpbHRlcihjb3VudHJ5LmFpZC5kYXRhLm0xMCwgbSAhPSAib3JpZ2luYWwiKSwKICAgICAgICBmaWxlID0gaGVyZSgiRGF0YSIsICJkYXRhX2NsZWFuIiwgImRmX2NvdW50cnlfYWlkX2ltcHV0YXRpb25fbTEwLnJkcyIpKQoKc2F2ZVJEUyhkb25vci5sZXZlbC5kYXRhLAogICAgICAgIGZpbGUgPSBoZXJlKCJEYXRhIiwgImRhdGFfY2xlYW4iLCAiZGZfZG9ub3IucmRzIikpCgpzYXZlUkRTKGRvbm9yLmxldmVsLmRhdGEudXNhaWQsCiAgICAgICAgZmlsZSA9IGhlcmUoIkRhdGEiLCAiZGF0YV9jbGVhbiIsICJkZl9kb25vcl91c2FpZC5yZHMiKSkKYGBgCg==