knitr::opts_chunk$set(echo = TRUE, warning = FALSE, message = FALSE)


library(tidyverse)
library(DBI)
library(data.table)
library(ggspatial)
library(gstat)
library(here)
library(httr)
library(jsonlite)
library(ptaxsim)
library(sf)
library(stars)
library(glue)
library(ggpattern)

# Create the DB connection with the default name expected by PTAXSIM functions
ptaxsim_db_conn <- DBI::dbConnect(RSQLite::SQLite(), "./ptaxsim.db/ptaxsim-2021.0.4.db")


options(digits=4, scipen = 999)


library(httr)
library(NatParksPalettes)

# link to the API output as a JSON file
muni_shp <- read_sf("https://gis.cookcountyil.gov/traditional/rest/services/politicalBoundary/MapServer/2/query?outFields=*&where=1%3D1&f=geojson")

cook_shp <- read_sf("https://gis.cookcountyil.gov/traditional/rest/services/plss/MapServer/1/query?outFields=*&where=1%3D1&f=geojson")



#muni_shp <- read_json("muni_shp.json")
nicknames <- readxl::read_excel("./Necessary_Files/muni_shortnames.xlsx")

class_dict <- read_csv("./Necessary_Files/class_dict_expanded.csv") %>% 
  mutate(class_code = as.character(class_code))



# `agency_dt` has all taxing agencies (but not TIFs) that existed each year and includes their total taxable base (cty_cook_eav), their levy, taxing rate, binary variables for if a municipality is home rule or not, as well as many other variables. tax_bill() uses this table for the taxable EAV that is used to  calculate the tax rates in the tax bills. For simulations, you must alter the taxable EAV or levy or other variables and then tell tax_bill() function to use the modified agency data table for simulated tax bills.
# 



# has EAV values, extensions by agency_num
agency_dt <- DBI::dbGetQuery(
  ptaxsim_db_conn,
  "SELECT *
  FROM agency
  WHERE year = 2021
  "
)


# cook_agency_names <- DBI::dbGetQuery(
#   ptaxsim_db_conn,
#   "SELECT DISTINCT agency_num, agency_name
#   FROM agency_info
#   "
# )
# 
#  
# 
# 
# # has all tax codes and the taxing agency that taxes them. Tax code rates and agency rates. 
# cook_tax_codes <- DBI::dbGetQuery(
#   ptaxsim_db_conn,
#   glue_sql("
#   SELECT*
#   FROM tax_code
#   WHERE agency_num IN ({cook_agency_names$agency_num*})
#   AND year = 2021
#   ",
#   .con = ptaxsim_db_conn
#   )
# )


muni_agency_names <- DBI::dbGetQuery(
  ptaxsim_db_conn,
  "SELECT DISTINCT agency_num, agency_name, minor_type
  FROM agency_info
  WHERE minor_type = 'MUNI'
  OR agency_num = '020060000'  

  "
)

muni_tax_codes <- DBI::dbGetQuery(
  ptaxsim_db_conn,
  glue_sql("
  SELECT*
  FROM tax_code
  WHERE agency_num IN ({muni_agency_names$agency_num*})
  AND year = 2021
  ",
  .con = ptaxsim_db_conn
  )
)  
  
tax_codes <- DBI::dbGetQuery(
  ptaxsim_db_conn,
  glue_sql("
  SELECT DISTINCT tax_code_num, tax_code_rate
  FROM tax_code
  WHERE year = 2021  
  ",
  .con = ptaxsim_db_conn
  )
)

## All tax codes. 
## tax codes within municipalities have additional info 
tc_muninames <- tax_codes %>% 
  left_join(muni_tax_codes) %>%
  left_join(muni_agency_names) %>% 
  select(-agency_rate) %>% 
  left_join(nicknames) %>% 
  select(-c(minor_type, short_name, `Column1`, `Most recent reassessed`, agency_number))


# Agency number and agency name for all TIFs
TIF_agencies <- DBI::dbGetQuery(
  ptaxsim_db_conn,
  "SELECT DISTINCT agency_num, agency_name, major_type, minor_type
  FROM agency_info
  WHERE minor_type = 'TIF'
  "
)

unique_tif_taxcodes <- DBI::dbGetQuery(
  ptaxsim_db_conn, 
  glue_sql("
  SELECT DISTINCT tax_code_num
  FROM tax_code
  WHERE agency_num IN ({TIF_agencies$agency_num*})
  AND year = 2021
  ",
  .con = ptaxsim_db_conn
  )
)


tif_distrib <- DBI::dbGetQuery(
  ptaxsim_db_conn, 
  glue_sql("
  SELECT *
  FROM tif_distribution
  WHERE tax_code_num IN ({muni_tax_codes$tax_code_num*})
  AND year = 2021
  ",
  .con = ptaxsim_db_conn
  )
) %>% mutate(tax_code_num = as.character(tax_code_num))



cross_county_lines <- c("030440000", "030585000", "030890000", "030320000", "031280000","030080000", "030560000", "031120000", "030280000", "030340000","030150000","030050000", "030180000","030500000","031210000")


cross_county_lines <- muni_agency_names %>% 
  filter(agency_num %in% cross_county_lines) %>% 
  left_join(nicknames, by = "agency_name")

Changing General Homeowner Exemption - Scenarios

Create a PIN input with modified exemption amounts, then recalculate the base by taking the difference between the real and hypothetical exemptions.

Then recalculate the tax base for each district. If increasing the exemption, the base should decrease because there is less taxable EAV.

Quartiles and Progressivity

class_dict <- read_csv("./Necessary_Files/class_dict_singlefamcodes.csv") %>% 
  mutate(class_code = as.character(class_code)) # change variable type to character so the join works.

nicknames <- readxl::read_xlsx("./Necessary_Files/muni_shortnames.xlsx")

#pin_data2 <- read_csv("./Output/4C_joined_PINs_bills_and_exemptions.csv")

muni_taxrates <- read_csv("./Output/4C_muni_taxrates.csv")

#pin_data2 <- pin_data2 %>% left_join(class_dict)

muni_TC_fullyCook <- muni_tax_codes %>%
  filter(!agency_num %in% cross_county_lines)


joined_pins <- read_csv("./Output/4C_joined_PINs_bills_and_exemptions.csv") %>%
  mutate(tax_code_num = as.character(tax_code_num)) %>%  
  left_join(tc_muninames) %>% left_join(class_dict)

# all pins in munis fully within cook county that are some form of single-family, detached home
singfam_pins <- joined_pins %>% 
  filter(tax_code %in% muni_TC_fullyCook$tax_code_num) %>% # excludes county line crossing munis
  filter(Option2 == "Single-Family")

Cook County Quartiles

Cook County quartiles are calculated fromg single family properties assessed value in 2021.

q = c(.25, .5, .75)


cook_quartiles <- singfam_pins %>%
  filter(Option2 == "Single-Family") %>%
  filter(tax_code %in% muni_TC_fullyCook$tax_code_num) %>% # excludes county line crossing munis
  arrange(av) %>%
  summarize(count_pins = n(), 
            min = min(av),
            quant25 = round(quantile(av, probs = q[1])), 
            quant50 = round(quantile(av, probs = q[2])),
            quant75 = round(quantile(av, probs = q[3])),
            max = max(av))
cook_quartiles

Scenarios & tax rates

Similar to File 5_Exemption_Scenarios.rmd.

  • Calculate Class 2 Burden –> Calculate the amount of taxable EAV in the Municipality (for each scenario) and multiply it by the new composite tax rate (for each scenario).

  • Burden Share = Taxable EAV within Property Class * Composite tax rate

  • Composite Tax Rate = (Municipal Levy / Taxable EAV )

## Bring in tax bills and exemption data for 2021 PINs ##
# 
# joined_pins <- read_csv("./Output/4C_joined_PINs_bills_and_exemptions.csv") %>%
#   mutate(tax_code_num = as.character(tax_code_num)) %>%  
#   left_join(tc_muninames) %>% left_join(class_dict)

MuniLevy <- joined_pins %>% 
  group_by(clean_name, agency_num) %>%
  
  summarize(MuniLevy = sum(final_tax_to_dist, na.rm = TRUE), # amount billed by munis with current exemptions in place
            current_nonTIF_EAV_post_exemps = sum(final_tax_to_dist/(tax_code_rate/100), na.rm = TRUE),
            current_TIF_increment_EAV = sum(final_tax_to_tif/(tax_code_rate/100), na.rm=TRUE),  
            current_Exempt_EAV = sum(tax_amt_exe/(tax_code_rate/100), na.rm=TRUE), 
            Total_EAV = sum((tax_amt_exe+final_tax_to_dist+final_tax_to_tif)/(tax_code_rate/100), na.rm = TRUE)) %>% 
  mutate(cur_muni_comp_rate = MuniLevy / current_nonTIF_EAV_post_exemps)

MuniLevy
joined_pins <- joined_pins %>% 
  mutate(exe_neg10 = 0,
         exe_0 = ifelse(eav < 10000 & exe_homeowner!=0, eav, 
                             ifelse(eav>10000 & exe_homeowner!=0, 10000, 0 )),  #would be if there is no change in exemptions
         exe_plus10 = ifelse(eav < 20000 & exe_homeowner!=0, eav, 
                             ifelse(eav>20000 & exe_homeowner!=0, 20000, 0 )),
         exe_plus20 = ifelse(eav < 30000 & exe_homeowner!=0, eav, 
                             ifelse(eav>30000 & exe_homeowner!=0, 30000, 0 ) ),
         exe_plus30 = ifelse(eav < 40000 & exe_homeowner!=0, eav, 
                             ifelse(eav>40000 & exe_homeowner!=0, 40000, 0) ),
         exe_plus40 = ifelse(eav < 50000 & exe_homeowner!=0, eav, 
                             ifelse(eav>50000 & exe_homeowner!=0, 50000, 0) ) )

scenario_calcs <- joined_pins %>%    
  group_by(clean_name) %>%

    summarize(MuniLevy = sum(final_tax_to_dist, na.rm = TRUE), # amount billed by munis with current exemptions in place
            current_nonTIF_EAV_post_exemps = sum(final_tax_to_dist/(tax_code_rate/100), na.rm = TRUE),
            current_TIF_increment_EAV = sum(final_tax_to_tif/(tax_code_rate/100), na.rm=TRUE),  
            current_Exempt_EAV = sum(tax_amt_exe/(tax_code_rate/100), na.rm=TRUE), 
            current_GHE = sum(exe_homeowner, na.rm=TRUE),
            Total_EAV = sum((tax_amt_exe+final_tax_to_dist+final_tax_to_tif)/(tax_code_rate/100), na.rm = TRUE),
            exe_neg10 = sum(exe_neg10),
            exe_0 = sum(exe_0), # no change, for comparison
            exe_plus10 = sum(exe_plus10),
            exe_plus20 = sum(exe_plus20),
            exe_plus30 = sum(exe_plus30),
            exe_plus40 = sum(exe_plus40)) %>%

  # remove all GHE (up to 10,000 EAV added back to base per PIN), 
  # add exe_homeowner back to taxable base
  mutate(neg10_taxable_eav = Total_EAV - current_TIF_increment_EAV - current_Exempt_EAV + current_GHE,    # adds GHE exempt EAV back to taxable base and decreases tax rates
         plus10_taxable_eav = Total_EAV - current_TIF_increment_EAV - current_Exempt_EAV + current_GHE - exe_plus10, # will increase tax rates
         plus20_taxable_eav = Total_EAV - current_TIF_increment_EAV - current_Exempt_EAV + current_GHE - exe_plus20,
         plus30_taxable_eav = Total_EAV - current_TIF_increment_EAV - current_Exempt_EAV + current_GHE - exe_plus30,
         plus40_taxable_eav = Total_EAV - current_TIF_increment_EAV - current_Exempt_EAV + current_GHE - exe_plus40,
         scenario_noexemptions_taxable_eav = Total_EAV - current_TIF_increment_EAV) %>%
  
  mutate(tr_neg10 = MuniLevy / neg10_taxable_eav,
         tr_nochange = MuniLevy / current_nonTIF_EAV_post_exemps,
         tr_plus10 = MuniLevy / plus10_taxable_eav,
         tr_plus20 = MuniLevy / plus20_taxable_eav,
         tr_plus30 = MuniLevy / plus30_taxable_eav,
         tr_plus40 = MuniLevy / plus40_taxable_eav, 
         tax_rate_current = MuniLevy/current_nonTIF_EAV_post_exemps,
         taxrate_noexemps = MuniLevy /(Total_EAV - current_TIF_increment_EAV  ),
         taxrate_noTIFs = MuniLevy / (Total_EAV - current_Exempt_EAV),
         taxrate_noTIFs_orExemps = MuniLevy / Total_EAV) %>%
  select(clean_name, MuniLevy, tr_neg10:taxrate_noTIFs_orExemps, everything())

write_csv(scenario_calcs, "5b_scenario_calcs.csv")


scenario_taxrates <- scenario_calcs %>%  select(clean_name, MuniLevy, tr_neg10:taxrate_noTIFs_orExemps) 

scenario_taxrates

Class 2 Burden Shift

C2_taxableEAV <- joined_pins %>%   
  filter(class >= 200 & class <= 300) %>% 
  #left_join(scenario_taxrates, by = c("tax_code" = "tax_code_num")) %>%
  group_by(clean_name) %>%

    summarize(
      C2_av = sum(av),
      C2_eav_original = sum(equalized_AV), 
      C2_DistrictRev = sum(final_tax_to_dist, na.rm=TRUE),
      C2_current_nonTIF_EAV_post_exemps = sum(final_tax_to_dist/(tax_code_rate/100), na.rm = TRUE),
      C2_current_TIF_increment_EAV = sum(final_tax_to_tif/(tax_code_rate/100), na.rm=TRUE),  
      C2_current_Exempt_EAV = sum(tax_amt_exe/(tax_code_rate/100), na.rm=TRUE), 
      C2_current_GHE = sum(exe_homeowner, na.rm=TRUE),
      C2_Total_EAV = sum((tax_amt_exe+final_tax_to_dist+final_tax_to_tif)/(tax_code_rate/100), na.rm = TRUE),
      C2_exe_neg10 = sum(exe_neg10),
      C2_exe_0 = sum(exe_0), # no change, for comparison
      C2_exe_plus10 = sum(exe_plus10),
      C2_exe_plus20 = sum(exe_plus20),
      C2_exe_plus30 = sum(exe_plus30),
      C2_exe_plus40 = sum(exe_plus40),
      C2_PC_permuni = n())  %>% 
  left_join(MuniLevy, by = "clean_name") %>%
  mutate(C2_EAV_pct = C2_eav_original / Total_EAV)



C2_burden_shift <- C2_taxableEAV %>%
  left_join(scenario_taxrates) %>%
  mutate(C2_neg10_taxableEAV = C2_Total_EAV - C2_current_TIF_increment_EAV - C2_current_Exempt_EAV + C2_current_GHE - C2_exe_neg10,
         C2_nochange = C2_Total_EAV - C2_current_TIF_increment_EAV - C2_current_Exempt_EAV,
         C2_plus10_taxableEAV = C2_Total_EAV - C2_current_TIF_increment_EAV - C2_current_Exempt_EAV + C2_current_GHE - C2_exe_plus10,
         C2_plus20_taxableEAV = C2_Total_EAV - C2_current_TIF_increment_EAV - C2_current_Exempt_EAV + C2_current_GHE - C2_exe_plus20,
        C2_plus30_taxableEAV = C2_Total_EAV - C2_current_TIF_increment_EAV - C2_current_Exempt_EAV + C2_current_GHE - C2_exe_plus30,
        C2_plus40_taxableEAV = C2_Total_EAV - C2_current_TIF_increment_EAV - C2_current_Exempt_EAV + C2_current_GHE - C2_exe_plus40
         ) %>%
  mutate(burden_C2_neg10 = (C2_neg10_taxableEAV * tr_neg10)/ MuniLevy,
         burden_C2_nochange = C2_nochange * tax_rate_current  / MuniLevy,
         burden_C2_plus10 = (C2_plus10_taxableEAV * tr_plus10) / MuniLevy,
         burden_C2_plus20 = C2_plus20_taxableEAV * tr_plus20/ MuniLevy,
         burden_C2_plus30 = C2_plus30_taxableEAV * tr_plus30/ MuniLevy,
         burden_C2_plus40 = C2_plus40_taxableEAV * tr_plus40/ MuniLevy,
         
        burden_C2_noexemps = ( (C2_Total_EAV - C2_current_TIF_increment_EAV)*taxrate_noexemps ) / MuniLevy) %>%
  select(clean_name, C2_EAV_pct, burden_C2_neg10:burden_C2_plus40, everything())

C2_burden_shift
write_csv(C2_burden_shift, "5b_Class2_burdenshift.csv")

Scenario Tax rate graphs

scenarios_long <- scenario_taxrates  %>% 
  select(clean_name, MuniLevy, tr_neg10:taxrate_noTIFs_orExemps) %>%
  pivot_longer(cols = c(tr_neg10:taxrate_noTIFs_orExemps), names_to = "GHE_Amount")


scenario_taxrates %>% 
  select(clean_name, MuniLevy, tr_neg10:taxrate_noTIFs_orExemps) %>%
  pivot_longer(cols = c(tr_neg10:taxrate_noTIFs_orExemps), names_to = "GHE_Amount") %>%
  ggplot() + 
  geom_col(aes(x=value, y = GHE_Amount))

scenario_taxrates %>% 
  filter(clean_name %in% c("Chicago", "Dolton", "Glencoe")) %>%
  select(clean_name, MuniLevy, tr_neg10:taxrate_noTIFs_orExemps) %>%
  pivot_longer(cols = c(tr_neg10:taxrate_noTIFs_orExemps), names_to = "GHE_Amount") %>%
  ggplot() + 
  geom_col(aes(x=value, y = GHE_Amount, fill = clean_name), position = "dodge")  + 
  labs(x = "Municipality Composite Tax Rate", y = "Exemption Scenarios")

Ranked Properties and Muni Quartiles

25 v 75 Percentile Homes

q = c(.25, .5, .75)

## ranks properties that are considered single family homes in order of AV for each Muni
muni_quartiles <- joined_pins %>%
  filter(Option2 == "Single-Family") %>% 
  filter(tax_code %in% muni_TC_fullyCook$tax_code_num) %>%
  group_by(agency_name, clean_name) %>%
  arrange(av) %>%
  summarize(count_pins = n(), 
            min = min(av),
            quant25 = round(quantile(av, probs = q[1])), 
            quant50 = round(quantile(av, probs = q[2])),
            quant75 = round(quantile(av, probs = q[3])),
            max = max(av)
           ) %>% 
  arrange( desc( quant50))
muni_quartiles
## create rank variable for properties that fall within the quartiles +/- $500 range
munis_ranked <- joined_pins  %>%
  inner_join(muni_quartiles, by = c("agency_name", "clean_name")) %>% 
  mutate(rank = case_when(
    av > (quant25-500) & (av<quant25+500) ~ "q25",
    av > (quant50-500) & (av<quant50+500) ~ "q50",
    av > (quant75-500) & (av<quant75+500) ~ "q75")
    ) %>%
  select(clean_name, rank, av, pin, class, everything()) %>%
  left_join(nicknames)




munis_billchange <-  munis_ranked %>% 
  group_by(clean_name, rank) %>%
  left_join(scenario_taxrates) %>%
  arrange(av) %>%
 # group_by(agency_name, has_HO_exemp) %>% 
  mutate(#taxable_eav = final_tax_to_dist / tax_code_rate,
    # current bill = current tax rate * portion of levy billed
    
    
   # ## Made negative tax bills!! ## #
         
         bill_neg10 = tr_neg10*(equalized_AV-all_exemptions+ exe_homeowner -exe_neg10),

         bill_current = cur_comp_TC_rate/100*(equalized_AV-all_exemptions),
         bill_plus10 =  tr_plus10*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus10),
         bill_plus20 = tr_plus20*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus20),
         bill_plus30 = tr_plus20*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus30),
         bill_plus40 = tr_plus20*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus40),
    
    # ## make bills $1 if they had been negative.    
         bill_neg10 = ifelse(bill_neg10 < 1, 1, bill_neg10),
         bill_current = ifelse(bill_current < 1, 1, bill_current),
         bill_plus10 = ifelse(bill_plus10 < 1, 1, bill_plus10),
         bill_plus20 = ifelse(bill_plus20 < 1, 1, bill_plus20),
         bill_plus30 = ifelse(bill_plus30 < 1, 1, bill_plus30),
         bill_plus40 = ifelse(bill_plus40 < 1, 1, bill_plus40),
         
## Prevent tax bills from having negative values  (if exemptions > eav of home)
         # bill_neg10 = ifelse(tr_neg10*(equalized_AV-all_exemptions+ exe_homeowner -exe_neg10) > 1,
         #                              tr_neg10*(equalized_AV-all_exemptions+ exe_homeowner -exe_neg10), 1),
         # 
         # bill_current = ifelse(cur_comp_TC_rate/100*(equalized_AV-all_exemptions) > 1,
         #                       cur_comp_TC_rate/100*(equalized_AV-all_exemptions), 1),
         # 
         # bill_plus10 =  ifelse(tr_plus10*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus10) > 1,
         #                       tr_plus10*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus10),1),
         # 
         # bill_plus20 = ifelse(tr_plus20*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus20) > 1,
         #                      tr_plus20*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus20), 1),
         # 
         # bill_plus30 = ifelse(tr_plus30*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus30) >1, 
         #                      tr_plus30*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus30), 1),
         #                      
         #                      
         # bill_plus40 = ifelse(tr_plus40*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus40) > 1,
         #                      tr_plus40*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus40), 1)
         )%>%
  mutate(
         zerodol_bills_ghe0 = ifelse(bill_neg10 < 5, 1, 0),
         zerodol_bills_current = ifelse(bill_current < 5, 1, 0),
         zerodol_bills_ghe20 = ifelse(bill_plus10 < 5, 1, 0),
         zerodol_bills_ghe30 = ifelse(bill_plus20 < 5, 1, 0),
         zerodol_bills_ghe40 = ifelse(bill_plus30 < 5, 1, 0),
         zerodol_bills_ghe50 = ifelse(bill_plus40 < 5, 1, 0),
  ) %>%
  group_by(clean_name, rank, has_HO_exemp) %>% 
  summarize(median_AV = round(median(av)),
            median_EAV = round(median(eav)),
            mean_bill_neg10 = round(mean(bill_neg10, na.rm=TRUE)),
            mean_bill_cur = round(mean(bill_current, na.rm=TRUE)),
            mean_bill_plus10 = round(mean(bill_plus10, na.rm=TRUE)),
            mean_bill_plus20 = round(mean(bill_plus20, na.rm=TRUE)),
            mean_bill_plus30 = round(mean(bill_plus30, na.rm=TRUE)),
            mean_bill_plus40 = round(mean(bill_plus40, na.rm=TRUE)),
            
            # current perceived_savings = median(tax_amt_exe),
            tr_neg10 = round(mean(tr_neg10*100), digits = 2), 
            cur_comp_TC_rate = round(mean(cur_comp_TC_rate), digits = 2),
            tr_plus10 = round(mean(tr_plus10*100), digits = 2),
            tr_plus20 = round(mean(tr_plus20*100), digits = 2),
            tr_plus30 = round(mean(tr_plus30*100), digits = 2),
            tr_plus40 = round(mean(tr_plus40*100), digits = 2),
            pincount=n(),
            zerodol_bills_ghe0 = sum(zerodol_bills_ghe0),           
            zerodol_bills_current = sum(zerodol_bills_current),
            zerodol_bills_ghe20 = sum(zerodol_bills_ghe20),
            zerodol_bills_ghe30 = sum(zerodol_bills_ghe30),
            zerodol_bills_ghe40 = sum(zerodol_bills_ghe40),
            zerodol_bills_ghe50 = sum(zerodol_bills_ghe50),


  ) %>%
  arrange(has_HO_exemp, rank)


munis_billchange <- munis_billchange %>% left_join(muni_quartiles)
munis_billchange
write_csv(munis_billchange, "5b_muni_billchange_scenarios.csv")
ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(currbill_to_AV_25 = ifelse(rank == "q25", mean_bill_neg10/median_AV, NA)) %>%
  mutate(currbill_to_AV_75 = ifelse(rank == "q75", mean_bill_neg10/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(GHE_0_bill_to_AV_25 = max(currbill_to_AV_25, na.rm=TRUE),
            GHE_0_bill_to_AV_75 = max(currbill_to_AV_75, na.rm=TRUE)) %>%
  mutate(muni_ratio_25to75 = GHE_0_bill_to_AV_25/GHE_0_bill_to_AV_75)


ggplot(data = ratios, aes(y = GHE_0_bill_to_AV_25, x = GHE_0_bill_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") +
  labs(title = "Reduced GHE Amount by 10,000 EAV (0 EAV exempt from GHE)",
       subtitle = "Other exemptions still in place")

ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(currbill_to_AV_25 = ifelse(rank == "q25", mean_bill_cur/median_AV, NA)) %>%
  mutate(currbill_to_AV_75 = ifelse(rank == "q75", mean_bill_cur/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(currbill_to_AV_25 = max(currbill_to_AV_25, na.rm=TRUE),
            currbill_to_AV_75 = max(currbill_to_AV_75, na.rm=TRUE)) %>%
  mutate(muni_ratio_25to75 = currbill_to_AV_25/currbill_to_AV_75)


ggplot(data = ratios, aes(y = currbill_to_AV_25, x = currbill_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") +
  labs(title = "Current GHE Amount (up to 10,000 EAV exempt per property)")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_25 = ifelse(rank == "q25", mean_bill_plus10/median_AV, NA)) %>%
  mutate(newbill_to_AV_75 = ifelse(rank == "q75", mean_bill_plus10/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_25 = max(newbill_to_AV_25, na.rm=TRUE),
            newbill_to_AV_75 = max(newbill_to_AV_75, na.rm=TRUE)) %>%
  mutate(muni_ratio_25to75 = newbill_to_AV_25/newbill_to_AV_75)


ggplot(data = new_ratios, aes(y = newbill_to_AV_25, x = newbill_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
  scale_y_continuous(limits = c(0, .6))+
  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 10,000 EAV (for up to 20,000 EAV exempt) ", 
                                         y = "25th percentile of homes, taxbill:AV",
                                         x= "75th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 20K per property")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_25 = ifelse(rank == "q25", mean_bill_plus20/median_AV, NA)) %>%
  mutate(newbill_to_AV_75 = ifelse(rank == "q75", mean_bill_plus20/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_25 = max(newbill_to_AV_25, na.rm=TRUE),
            newbill_to_AV_75 = max(newbill_to_AV_75, na.rm=TRUE)) %>%
  mutate(muni_ratio_25to75 = newbill_to_AV_25/newbill_to_AV_75)


ggplot(data = new_ratios, aes(y = newbill_to_AV_25, x = newbill_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 20,000 EAV (for up to 30,000 EAV exempt) ", 
                                         y = "25th percentile of homes, taxbill:AV",
                                         x= "75th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 30K per property")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_25 = ifelse(rank == "q25", mean_bill_plus30/median_AV, NA)) %>%
  mutate(newbill_to_AV_75 = ifelse(rank == "q75", mean_bill_plus30/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_25 = max(newbill_to_AV_25, na.rm=TRUE),
            newbill_to_AV_75 = max(newbill_to_AV_75, na.rm=TRUE)) %>%
  mutate(muni_ratio_25to75 = newbill_to_AV_25/newbill_to_AV_75)


ggplot(data = new_ratios, aes(y = newbill_to_AV_25, x = newbill_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 30,000 EAV (for up to 40,000 EAV exempt) ", 
                                         y = "25th percentile of homes, taxbill:AV",
                                         x= "75th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 40K per property")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_25 = ifelse(rank == "q25", mean_bill_plus40/median_AV, NA)) %>%
  mutate(newbill_to_AV_75 = ifelse(rank == "q75", mean_bill_plus40/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_25 = max(newbill_to_AV_25, na.rm=TRUE),
            newbill_to_AV_75 = max(newbill_to_AV_75, na.rm=TRUE)) %>%
  mutate(muni_ratio_25to75 = newbill_to_AV_25/newbill_to_AV_75)


ggplot(data = new_ratios, aes(y = newbill_to_AV_25, x = newbill_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 40,000 EAV (for up to 50,000 EAV exempt) ", 
                                         y = "25th percentile of homes, taxbill:AV",
                                         x= "75th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 50K per property")

90/10 deciles

q = c(.1, .5, .9)

## ranks properties that are considered single family homes in order of AV for each Muni
muni_quartiles <- joined_pins %>%
  filter(Option2 == "Single-Family") %>% 
  filter(tax_code %in% muni_TC_fullyCook$tax_code_num) %>%
  group_by(agency_name, clean_name) %>%
  arrange(av) %>%
  summarize(count_pins = n(), 
            min = min(av),
            quant10 = round(quantile(av, probs = q[1])), 
            quant50 = round(quantile(av, probs = q[2])),
            quant90 = round(quantile(av, probs = q[3])),
            max = max(av)
           ) %>% 
  arrange( desc( quant50))
muni_quartiles
## create rank variable for properties that fall within the quartiles +/- $500 range
munis_ranked <- joined_pins  %>%
  inner_join(muni_quartiles, by = c("agency_name", "clean_name")) %>% 
  mutate(rank = case_when(
    av > (quant10-500) & (av<quant10+500) ~ "q10",
    av > (quant50-500) & (av<quant50+500) ~ "q50",
    av > (quant90-500) & (av<quant90+500) ~ "q90")
    ) %>%
  select(clean_name, rank, av, pin, class, everything()) %>%
  left_join(nicknames)




munis_billchange <-  munis_ranked %>% 
  group_by(clean_name, rank) %>%
  left_join(scenario_taxrates) %>%
  arrange(av) %>%
 # group_by(agency_name, has_HO_exemp) %>% 
  mutate(#taxable_eav = final_tax_to_dist / tax_code_rate,
    # current bill = current tax rate * portion of levy billed
         bill_neg10 = tr_neg10*(equalized_AV-all_exemptions+ exe_homeowner -exe_neg10),

         bill_current = cur_comp_TC_rate/100*(equalized_AV-all_exemptions),
         bill_plus10 =  tr_plus10*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus10),
         bill_plus20 = tr_plus20*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus20),
         bill_plus30 = tr_plus30*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus30),
         bill_plus40 = tr_plus40*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus40),

    # ## make bills $1 if they had been negative.    
         bill_neg10 = ifelse(bill_neg10 < 1, 1, bill_neg10),
         bill_current = ifelse(bill_current < 1, 1, bill_current),
         bill_plus10 = ifelse(bill_plus10 < 1, 1, bill_plus10),
         bill_plus20 = ifelse(bill_plus20 < 1, 1, bill_plus20),
         bill_plus30 = ifelse(bill_plus30 < 1, 1, bill_plus30),
         bill_plus40 = ifelse(bill_plus40 < 1, 1, bill_plus40)) %>%

  mutate(
         zerodol_bills_ghe0 = ifelse(bill_neg10 < 5, 1, 0),
         zerodol_bills_current = ifelse(bill_current < 5, 1, 0),
         zerodol_bills_ghe20 = ifelse(bill_plus10 < 5, 1, 0),
         zerodol_bills_ghe30 = ifelse(bill_plus20 < 5, 1, 0),
         zerodol_bills_ghe40 = ifelse(bill_plus30 < 5, 1, 0),
         zerodol_bills_ghe50 = ifelse(bill_plus40 < 5, 1, 0),
  ) %>%
  group_by(clean_name, rank, has_HO_exemp) %>% 
  summarize(median_AV = round(median(av)),
            median_EAV = round(median(eav)),
            mean_bill_neg10 = round(mean(bill_neg10, na.rm=TRUE)),
            mean_bill_cur = round(mean(bill_current, na.rm=TRUE)),
            mean_bill_plus10 = round(mean(bill_plus10, na.rm=TRUE)),
            mean_bill_plus20 = round(mean(bill_plus20, na.rm=TRUE)),
            mean_bill_plus30 = round(mean(bill_plus30, na.rm=TRUE)),
            mean_bill_plus40 = round(mean(bill_plus40, na.rm=TRUE)),
            
            # current perceived_savings = median(tax_amt_exe),
            tr_neg10 = round(mean(tr_neg10*100), digits = 2), 
            cur_comp_TC_rate = round(mean(cur_comp_TC_rate), digits = 2),
            tr_plus10 = round(mean(tr_plus10*100), digits = 2),
            tr_plus20 = round(mean(tr_plus20*100), digits = 2),
            tr_plus30 = round(mean(tr_plus30*100), digits = 2),
            tr_plus40 = round(mean(tr_plus40*100), digits = 2),
            pincount=n()
  ) %>%
  arrange(has_HO_exemp, rank)


munis_billchange <- munis_billchange %>% left_join(muni_quartiles)
munis_billchange
ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(currbill_to_AV_10 = ifelse(rank == "q10", mean_bill_neg10/median_AV, NA)) %>%
  mutate(currbill_to_AV_90 = ifelse(rank == "q90", mean_bill_neg10/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(GHE_0_bill_to_AV_10 = max(currbill_to_AV_10, na.rm=TRUE),
            GHE_0_bill_to_AV_90 = max(currbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = GHE_0_bill_to_AV_10/GHE_0_bill_to_AV_90)


ggplot(data = ratios, aes(y = GHE_0_bill_to_AV_10, x = GHE_0_bill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") +
  labs(title = "Reduced GHE Amount by 10,000 EAV (0 EAV exempt from GHE)",
       subtitle = "Other exemptions still in place")

ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(currbill_to_AV_10 = ifelse(rank == "q10", mean_bill_cur/median_AV, NA)) %>%
  mutate(currbill_to_AV_90 = ifelse(rank == "q90", mean_bill_cur/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(currbill_to_AV_10 = max(currbill_to_AV_10, na.rm=TRUE),
            currbill_to_AV_90 = max(currbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = currbill_to_AV_10/currbill_to_AV_90)


ggplot(data = ratios, aes(y = currbill_to_AV_10, x = currbill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") +
  labs(title = "Current GHE Amount (up to 10,000 EAV exempt per property)")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_10 = ifelse(rank == "q10", mean_bill_plus10/median_AV, NA)) %>%
  mutate(newbill_to_AV_90 = ifelse(rank == "q90", mean_bill_plus10/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_10 = max(newbill_to_AV_10, na.rm=TRUE),
            newbill_to_AV_90 = max(newbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = newbill_to_AV_10/newbill_to_AV_90)


ggplot(data = new_ratios, aes(y = newbill_to_AV_10, x = newbill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
  scale_y_continuous(limits = c(0, .6))+
  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 10,000 EAV (for up to 20,000 EAV exempt) ", 
                                         y = "10th percentile of homes, taxbill:AV",
                                         x= "90th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 20K per property")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_10 = ifelse(rank == "q10", mean_bill_plus20/median_AV, NA)) %>%
  mutate(newbill_to_AV_90 = ifelse(rank == "q90", mean_bill_plus20/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_10 = max(newbill_to_AV_10, na.rm=TRUE),
            newbill_to_AV_90 = max(newbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = newbill_to_AV_10/newbill_to_AV_90)


ggplot(data = new_ratios, aes(y = newbill_to_AV_10, x = newbill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 20,000 EAV (for up to 30,000 EAV exempt) ", 
                                         y = "10th percentile of homes, taxbill:AV",
                                         x= "90th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 30K per property")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_10 = ifelse(rank == "q10", mean_bill_plus30/median_AV, NA)) %>%
  mutate(newbill_to_AV_90 = ifelse(rank == "q90", mean_bill_plus30/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_10 = max(newbill_to_AV_10, na.rm=TRUE),
            newbill_to_AV_90 = max(newbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = newbill_to_AV_10/newbill_to_AV_90)


ggplot(data = new_ratios, aes(y = newbill_to_AV_10, x = newbill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 30,000 EAV (for up to 40,000 EAV exempt) ", 
                                         y = "10th percentile of homes, taxbill:AV",
                                         x= "90th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 40K per property")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_10 = ifelse(rank == "q10", mean_bill_plus40/median_AV, NA)) %>%
  mutate(newbill_to_AV_90 = ifelse(rank == "q90", mean_bill_plus40/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_10 = max(newbill_to_AV_10, na.rm=TRUE),
            newbill_to_AV_90 = max(newbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = newbill_to_AV_10/newbill_to_AV_90)


ggplot(data = new_ratios, aes(y = newbill_to_AV_10, x = newbill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 40,000 EAV (for up to 50,000 EAV exempt) ", 
                                         y = "10th percentile of homes, taxbill:AV",
                                         x= "90th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 50K per property")

90/10 deciles - Bigger AV range

Increased range of homes included in quantile to avoid having municipalities drop out if there were no tax bills. Not sure if it addresses the problem.

q = c(.1, .5, .9)

## ranks properties that are considered single family homes in order of AV for each Muni
muni_quartiles <- joined_pins %>%
  filter(Option2 == "Single-Family") %>% 
  filter(tax_code %in% muni_TC_fullyCook$tax_code_num) %>%
  group_by(agency_name, clean_name) %>%
  arrange(av) %>%
  summarize(count_pins = n(), 
            min = min(av),
            quant10 = round(quantile(av, probs = q[1])), 
            quant50 = round(quantile(av, probs = q[2])),
            quant90 = round(quantile(av, probs = q[3])),
            max = max(av)
           ) %>% 
  arrange( desc( quant50))
muni_quartiles
## create rank variable for properties that fall within the quartiles +/- $500 range
munis_ranked <- joined_pins  %>%
  inner_join(muni_quartiles, by = c("agency_name", "clean_name")) %>% 
  mutate(rank = case_when(
    av > (quant10-1000) & (av<quant10+1000) ~ "q10",
    av > (quant50-1000) & (av<quant50+1000) ~ "q50",
    av > (quant90-1000) & (av<quant90+1000) ~ "q90")
    ) %>%
  select(clean_name, rank, av, pin, class, everything()) %>%
  left_join(nicknames)




munis_billchange <-  munis_ranked %>% 
  group_by(clean_name, rank) %>%
  left_join(scenario_taxrates) %>%
  arrange(av) %>%
  mutate(#taxable_eav = final_tax_to_dist / tax_code_rate,
    # current bill = current tax rate * portion of levy billed
         bill_neg10 = tr_neg10*(equalized_AV-all_exemptions+ exe_homeowner -exe_neg10),

         bill_current = cur_comp_TC_rate/100*(equalized_AV-all_exemptions),
         bill_plus10 =  tr_plus10*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus10),
         bill_plus20 = tr_plus20*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus20),
         bill_plus30 = tr_plus30*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus30),
         bill_plus40 = tr_plus40*(equalized_AV-all_exemptions+ exe_homeowner -exe_plus40),

    # ## make bills $1 if they had been negative.    
         bill_neg10 = ifelse(bill_neg10 < 1, 1, bill_neg10),
         bill_current = ifelse(bill_current < 1, 1, bill_current),
         bill_plus10 = ifelse(bill_plus10 < 1, 1, bill_plus10),
         bill_plus20 = ifelse(bill_plus20 < 1, 1, bill_plus20),
         bill_plus30 = ifelse(bill_plus30 < 1, 1, bill_plus30),
         bill_plus40 = ifelse(bill_plus40 < 1, 1, bill_plus40)) %>%

  mutate(
         zerodol_bills_ghe0 = ifelse(bill_neg10 < 5, 1, 0),
         zerodol_bills_current = ifelse(bill_current < 5, 1, 0),
         zerodol_bills_ghe20 = ifelse(bill_plus10 < 5, 1, 0),
         zerodol_bills_ghe30 = ifelse(bill_plus20 < 5, 1, 0),
         zerodol_bills_ghe40 = ifelse(bill_plus30 < 5, 1, 0),
         zerodol_bills_ghe50 = ifelse(bill_plus40 < 5, 1, 0),
  ) %>%
  group_by(clean_name, rank, has_HO_exemp) %>% 
  summarize(median_AV = round(median(av)),
            median_EAV = round(median(eav)),
            mean_bill_neg10 = round(mean(bill_neg10, na.rm=TRUE)),
            mean_bill_cur = round(mean(bill_current, na.rm=TRUE)),
            mean_bill_plus10 = round(mean(bill_plus10, na.rm=TRUE)),
            mean_bill_plus20 = round(mean(bill_plus20, na.rm=TRUE)),
            mean_bill_plus30 = round(mean(bill_plus30, na.rm=TRUE)),
            mean_bill_plus40 = round(mean(bill_plus40, na.rm=TRUE)),
            
            # current perceived_savings = median(tax_amt_exe),
            tr_neg10 = round(mean(tr_neg10), digits = 2), 
            cur_comp_TC_rate = round(mean(cur_comp_TC_rate), digits = 2),
            tr_plus10 = round(mean(tr_plus10*100), digits = 2),
            tr_plus20 = round(mean(tr_plus20*100), digits = 2),
            tr_plus30 = round(mean(tr_plus30*100), digits = 2),
            tr_plus40 = round(mean(tr_plus40*100), digits = 2),
            pincount=n()
  ) %>%
  arrange(has_HO_exemp, rank)


munis_billchange <- munis_billchange %>% left_join(muni_quartiles)
munis_billchange
ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(currbill_to_AV_10 = ifelse(rank == "q10", mean_bill_neg10/median_AV, NA)) %>%
  mutate(currbill_to_AV_90 = ifelse(rank == "q90", mean_bill_neg10/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(GHE_0_bill_to_AV_10 = max(currbill_to_AV_10, na.rm=TRUE),
            GHE_0_bill_to_AV_90 = max(currbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = GHE_0_bill_to_AV_10/GHE_0_bill_to_AV_90)


ggplot(data = ratios, aes(y = GHE_0_bill_to_AV_10, x = GHE_0_bill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") +
  labs(title = "Reduced GHE Amount by 10,000 EAV (0 EAV exempt from GHE)",
       subtitle = "Other exemptions still in place")

ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(currbill_to_AV_10 = ifelse(rank == "q10", mean_bill_cur/median_AV, NA)) %>%
  mutate(currbill_to_AV_90 = ifelse(rank == "q90", mean_bill_cur/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(currbill_to_AV_10 = max(currbill_to_AV_10, na.rm=TRUE),
            currbill_to_AV_90 = max(currbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = currbill_to_AV_10/currbill_to_AV_90)


ggplot(data = ratios, aes(y = currbill_to_AV_10, x = currbill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") +
  labs(title = "Current GHE Amount (up to 10,000 EAV exempt per property)")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_10 = ifelse(rank == "q10", mean_bill_plus10/median_AV, NA)) %>%
  mutate(newbill_to_AV_90 = ifelse(rank == "q90", mean_bill_plus10/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_10 = max(newbill_to_AV_10, na.rm=TRUE),
            newbill_to_AV_90 = max(newbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = newbill_to_AV_10/newbill_to_AV_90)


ggplot(data = new_ratios, aes(y = newbill_to_AV_10, x = newbill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
  scale_y_continuous(limits = c(0, .6))+
  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 10,000 EAV (for up to 20,000 EAV exempt) ", 
                                         y = "10th percentile of homes, taxbill:AV",
                                         x= "90th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 20K per property")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_10 = ifelse(rank == "q10", mean_bill_plus20/median_AV, NA)) %>%
  mutate(newbill_to_AV_90 = ifelse(rank == "q90", mean_bill_plus20/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_10 = max(newbill_to_AV_10, na.rm=TRUE),
            newbill_to_AV_90 = max(newbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = newbill_to_AV_10/newbill_to_AV_90)


ggplot(data = new_ratios, aes(y = newbill_to_AV_10, x = newbill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 20,000 EAV (for up to 30,000 EAV exempt) ", 
                                         y = "10th percentile of homes, taxbill:AV",
                                         x= "90th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 30K per property")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_10 = ifelse(rank == "q10", mean_bill_plus30/median_AV, NA)) %>%
  mutate(newbill_to_AV_90 = ifelse(rank == "q90", mean_bill_plus30/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_10 = max(newbill_to_AV_10, na.rm=TRUE),
            newbill_to_AV_90 = max(newbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = newbill_to_AV_10/newbill_to_AV_90)


ggplot(data = new_ratios, aes(y = newbill_to_AV_10, x = newbill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 30,000 EAV (for up to 40,000 EAV exempt) ", 
                                         y = "10th percentile of homes, taxbill:AV",
                                         x= "90th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 40K per property")

new_ratios<- munis_billchange %>% 
  filter(has_HO_exemp == 1 &  !is.na(rank)) %>% # claimed exemption in 2021
  mutate(newbill_to_AV_10 = ifelse(rank == "q10", mean_bill_plus40/median_AV, NA)) %>%
  mutate(newbill_to_AV_90 = ifelse(rank == "q90", mean_bill_plus40/median_AV, NA)) %>% 
  group_by(clean_name) %>%
  summarize(newbill_to_AV_10 = max(newbill_to_AV_10, na.rm=TRUE),
            newbill_to_AV_90 = max(newbill_to_AV_90, na.rm=TRUE)) %>%
  mutate(muni_ratio_10to90 = newbill_to_AV_10/newbill_to_AV_90)


ggplot(data = new_ratios, aes(y = newbill_to_AV_10, x = newbill_to_AV_90, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
    scale_y_continuous(limits = c(0, .6))+

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none") + labs(title = "Increase GHE by 40,000 EAV (for up to 50,000 EAV exempt) ", 
                                         y = "10th percentile of homes, taxbill:AV",
                                         x= "90th percentile of homes, taxbill:AV",
                                         caption =  "Uses single-family properties. Exempt EAV up to 50K per property")

LS0tDQp0aXRsZTogIkV4ZW1wdGlvbiBTY2VuYXJpb3MgLSBSZXF1ZXN0ZWQgaW4gT2N0b2JlciAyNSBNZWV0aW5nIg0KYXV0aG9yOiAiQWxlYSBXaWxidXIiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQotLS0NCg0KDQoNCmBgYHtyIHNldHVwLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpDQoNCg0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KERCSSkNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkoZ2dzcGF0aWFsKQ0KbGlicmFyeShnc3RhdCkNCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkoaHR0cikNCmxpYnJhcnkoanNvbmxpdGUpDQpsaWJyYXJ5KHB0YXhzaW0pDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShzdGFycykNCmxpYnJhcnkoZ2x1ZSkNCmxpYnJhcnkoZ2dwYXR0ZXJuKQ0KDQojIENyZWF0ZSB0aGUgREIgY29ubmVjdGlvbiB3aXRoIHRoZSBkZWZhdWx0IG5hbWUgZXhwZWN0ZWQgYnkgUFRBWFNJTSBmdW5jdGlvbnMNCnB0YXhzaW1fZGJfY29ubiA8LSBEQkk6OmRiQ29ubmVjdChSU1FMaXRlOjpTUUxpdGUoKSwgIi4vcHRheHNpbS5kYi9wdGF4c2ltLTIwMjEuMC40LmRiIikNCg0KDQpvcHRpb25zKGRpZ2l0cz00LCBzY2lwZW4gPSA5OTkpDQoNCg0KbGlicmFyeShodHRyKQ0KbGlicmFyeShOYXRQYXJrc1BhbGV0dGVzKQ0KDQojIGxpbmsgdG8gdGhlIEFQSSBvdXRwdXQgYXMgYSBKU09OIGZpbGUNCm11bmlfc2hwIDwtIHJlYWRfc2YoImh0dHBzOi8vZ2lzLmNvb2tjb3VudHlpbC5nb3YvdHJhZGl0aW9uYWwvcmVzdC9zZXJ2aWNlcy9wb2xpdGljYWxCb3VuZGFyeS9NYXBTZXJ2ZXIvMi9xdWVyeT9vdXRGaWVsZHM9KiZ3aGVyZT0xJTNEMSZmPWdlb2pzb24iKQ0KDQpjb29rX3NocCA8LSByZWFkX3NmKCJodHRwczovL2dpcy5jb29rY291bnR5aWwuZ292L3RyYWRpdGlvbmFsL3Jlc3Qvc2VydmljZXMvcGxzcy9NYXBTZXJ2ZXIvMS9xdWVyeT9vdXRGaWVsZHM9KiZ3aGVyZT0xJTNEMSZmPWdlb2pzb24iKQ0KDQoNCg0KI211bmlfc2hwIDwtIHJlYWRfanNvbigibXVuaV9zaHAuanNvbiIpDQpuaWNrbmFtZXMgPC0gcmVhZHhsOjpyZWFkX2V4Y2VsKCIuL05lY2Vzc2FyeV9GaWxlcy9tdW5pX3Nob3J0bmFtZXMueGxzeCIpDQoNCmNsYXNzX2RpY3QgPC0gcmVhZF9jc3YoIi4vTmVjZXNzYXJ5X0ZpbGVzL2NsYXNzX2RpY3RfZXhwYW5kZWQuY3N2IikgJT4lIA0KICBtdXRhdGUoY2xhc3NfY29kZSA9IGFzLmNoYXJhY3RlcihjbGFzc19jb2RlKSkNCg0KDQoNCiMgYGFnZW5jeV9kdGAgaGFzIGFsbCB0YXhpbmcgYWdlbmNpZXMgKGJ1dCBub3QgVElGcykgdGhhdCBleGlzdGVkIGVhY2ggeWVhciBhbmQgaW5jbHVkZXMgdGhlaXIgdG90YWwgdGF4YWJsZSBiYXNlIChjdHlfY29va19lYXYpLCB0aGVpciBsZXZ5LCB0YXhpbmcgcmF0ZSwgYmluYXJ5IHZhcmlhYmxlcyBmb3IgaWYgYSBtdW5pY2lwYWxpdHkgaXMgaG9tZSBydWxlIG9yIG5vdCwgYXMgd2VsbCBhcyBtYW55IG90aGVyIHZhcmlhYmxlcy4gdGF4X2JpbGwoKSB1c2VzIHRoaXMgdGFibGUgZm9yIHRoZSB0YXhhYmxlIEVBViB0aGF0IGlzIHVzZWQgdG8gIGNhbGN1bGF0ZSB0aGUgdGF4IHJhdGVzIGluIHRoZSB0YXggYmlsbHMuIEZvciBzaW11bGF0aW9ucywgeW91IG11c3QgYWx0ZXIgdGhlIHRheGFibGUgRUFWIG9yIGxldnkgb3Igb3RoZXIgdmFyaWFibGVzIGFuZCB0aGVuIHRlbGwgdGF4X2JpbGwoKSBmdW5jdGlvbiB0byB1c2UgdGhlIG1vZGlmaWVkIGFnZW5jeSBkYXRhIHRhYmxlIGZvciBzaW11bGF0ZWQgdGF4IGJpbGxzLg0KIyANCg0KDQoNCiMgaGFzIEVBViB2YWx1ZXMsIGV4dGVuc2lvbnMgYnkgYWdlbmN5X251bQ0KYWdlbmN5X2R0IDwtIERCSTo6ZGJHZXRRdWVyeSgNCiAgcHRheHNpbV9kYl9jb25uLA0KICAiU0VMRUNUICoNCiAgRlJPTSBhZ2VuY3kNCiAgV0hFUkUgeWVhciA9IDIwMjENCiAgIg0KKQ0KDQoNCiMgY29va19hZ2VuY3lfbmFtZXMgPC0gREJJOjpkYkdldFF1ZXJ5KA0KIyAgIHB0YXhzaW1fZGJfY29ubiwNCiMgICAiU0VMRUNUIERJU1RJTkNUIGFnZW5jeV9udW0sIGFnZW5jeV9uYW1lDQojICAgRlJPTSBhZ2VuY3lfaW5mbw0KIyAgICINCiMgKQ0KIyANCiMgIA0KIyANCiMgDQojICMgaGFzIGFsbCB0YXggY29kZXMgYW5kIHRoZSB0YXhpbmcgYWdlbmN5IHRoYXQgdGF4ZXMgdGhlbS4gVGF4IGNvZGUgcmF0ZXMgYW5kIGFnZW5jeSByYXRlcy4gDQojIGNvb2tfdGF4X2NvZGVzIDwtIERCSTo6ZGJHZXRRdWVyeSgNCiMgICBwdGF4c2ltX2RiX2Nvbm4sDQojICAgZ2x1ZV9zcWwoIg0KIyAgIFNFTEVDVCoNCiMgICBGUk9NIHRheF9jb2RlDQojICAgV0hFUkUgYWdlbmN5X251bSBJTiAoe2Nvb2tfYWdlbmN5X25hbWVzJGFnZW5jeV9udW0qfSkNCiMgICBBTkQgeWVhciA9IDIwMjENCiMgICAiLA0KIyAgIC5jb24gPSBwdGF4c2ltX2RiX2Nvbm4NCiMgICApDQojICkNCg0KDQptdW5pX2FnZW5jeV9uYW1lcyA8LSBEQkk6OmRiR2V0UXVlcnkoDQogIHB0YXhzaW1fZGJfY29ubiwNCiAgIlNFTEVDVCBESVNUSU5DVCBhZ2VuY3lfbnVtLCBhZ2VuY3lfbmFtZSwgbWlub3JfdHlwZQ0KICBGUk9NIGFnZW5jeV9pbmZvDQogIFdIRVJFIG1pbm9yX3R5cGUgPSAnTVVOSScNCiAgT1IgYWdlbmN5X251bSA9ICcwMjAwNjAwMDAnICANCg0KICAiDQopDQoNCm11bmlfdGF4X2NvZGVzIDwtIERCSTo6ZGJHZXRRdWVyeSgNCiAgcHRheHNpbV9kYl9jb25uLA0KICBnbHVlX3NxbCgiDQogIFNFTEVDVCoNCiAgRlJPTSB0YXhfY29kZQ0KICBXSEVSRSBhZ2VuY3lfbnVtIElOICh7bXVuaV9hZ2VuY3lfbmFtZXMkYWdlbmN5X251bSp9KQ0KICBBTkQgeWVhciA9IDIwMjENCiAgIiwNCiAgLmNvbiA9IHB0YXhzaW1fZGJfY29ubg0KICApDQopICANCiAgDQp0YXhfY29kZXMgPC0gREJJOjpkYkdldFF1ZXJ5KA0KICBwdGF4c2ltX2RiX2Nvbm4sDQogIGdsdWVfc3FsKCINCiAgU0VMRUNUIERJU1RJTkNUIHRheF9jb2RlX251bSwgdGF4X2NvZGVfcmF0ZQ0KICBGUk9NIHRheF9jb2RlDQogIFdIRVJFIHllYXIgPSAyMDIxICANCiAgIiwNCiAgLmNvbiA9IHB0YXhzaW1fZGJfY29ubg0KICApDQopDQoNCiMjIEFsbCB0YXggY29kZXMuIA0KIyMgdGF4IGNvZGVzIHdpdGhpbiBtdW5pY2lwYWxpdGllcyBoYXZlIGFkZGl0aW9uYWwgaW5mbyANCnRjX211bmluYW1lcyA8LSB0YXhfY29kZXMgJT4lIA0KICBsZWZ0X2pvaW4obXVuaV90YXhfY29kZXMpICU+JQ0KICBsZWZ0X2pvaW4obXVuaV9hZ2VuY3lfbmFtZXMpICU+JSANCiAgc2VsZWN0KC1hZ2VuY3lfcmF0ZSkgJT4lIA0KICBsZWZ0X2pvaW4obmlja25hbWVzKSAlPiUgDQogIHNlbGVjdCgtYyhtaW5vcl90eXBlLCBzaG9ydF9uYW1lLCBgQ29sdW1uMWAsIGBNb3N0IHJlY2VudCByZWFzc2Vzc2VkYCwgYWdlbmN5X251bWJlcikpDQoNCg0KIyBBZ2VuY3kgbnVtYmVyIGFuZCBhZ2VuY3kgbmFtZSBmb3IgYWxsIFRJRnMNClRJRl9hZ2VuY2llcyA8LSBEQkk6OmRiR2V0UXVlcnkoDQogIHB0YXhzaW1fZGJfY29ubiwNCiAgIlNFTEVDVCBESVNUSU5DVCBhZ2VuY3lfbnVtLCBhZ2VuY3lfbmFtZSwgbWFqb3JfdHlwZSwgbWlub3JfdHlwZQ0KICBGUk9NIGFnZW5jeV9pbmZvDQogIFdIRVJFIG1pbm9yX3R5cGUgPSAnVElGJw0KICAiDQopDQoNCnVuaXF1ZV90aWZfdGF4Y29kZXMgPC0gREJJOjpkYkdldFF1ZXJ5KA0KICBwdGF4c2ltX2RiX2Nvbm4sIA0KICBnbHVlX3NxbCgiDQogIFNFTEVDVCBESVNUSU5DVCB0YXhfY29kZV9udW0NCiAgRlJPTSB0YXhfY29kZQ0KICBXSEVSRSBhZ2VuY3lfbnVtIElOICh7VElGX2FnZW5jaWVzJGFnZW5jeV9udW0qfSkNCiAgQU5EIHllYXIgPSAyMDIxDQogICIsDQogIC5jb24gPSBwdGF4c2ltX2RiX2Nvbm4NCiAgKQ0KKQ0KDQoNCnRpZl9kaXN0cmliIDwtIERCSTo6ZGJHZXRRdWVyeSgNCiAgcHRheHNpbV9kYl9jb25uLCANCiAgZ2x1ZV9zcWwoIg0KICBTRUxFQ1QgKg0KICBGUk9NIHRpZl9kaXN0cmlidXRpb24NCiAgV0hFUkUgdGF4X2NvZGVfbnVtIElOICh7bXVuaV90YXhfY29kZXMkdGF4X2NvZGVfbnVtKn0pDQogIEFORCB5ZWFyID0gMjAyMQ0KICAiLA0KICAuY29uID0gcHRheHNpbV9kYl9jb25uDQogICkNCikgJT4lIG11dGF0ZSh0YXhfY29kZV9udW0gPSBhcy5jaGFyYWN0ZXIodGF4X2NvZGVfbnVtKSkNCg0KDQoNCmNyb3NzX2NvdW50eV9saW5lcyA8LSBjKCIwMzA0NDAwMDAiLCAiMDMwNTg1MDAwIiwgIjAzMDg5MDAwMCIsICIwMzAzMjAwMDAiLCAiMDMxMjgwMDAwIiwiMDMwMDgwMDAwIiwgIjAzMDU2MDAwMCIsICIwMzExMjAwMDAiLCAiMDMwMjgwMDAwIiwgIjAzMDM0MDAwMCIsIjAzMDE1MDAwMCIsIjAzMDA1MDAwMCIsICIwMzAxODAwMDAiLCIwMzA1MDAwMDAiLCIwMzEyMTAwMDAiKQ0KDQoNCmNyb3NzX2NvdW50eV9saW5lcyA8LSBtdW5pX2FnZW5jeV9uYW1lcyAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbnVtICVpbiUgY3Jvc3NfY291bnR5X2xpbmVzKSAlPiUgDQogIGxlZnRfam9pbihuaWNrbmFtZXMsIGJ5ID0gImFnZW5jeV9uYW1lIikNCmBgYA0KDQojIENoYW5naW5nIEdlbmVyYWwgSG9tZW93bmVyIEV4ZW1wdGlvbiAtIFNjZW5hcmlvcw0KDQpDcmVhdGUgYSBQSU4gaW5wdXQgd2l0aCBtb2RpZmllZCBleGVtcHRpb24gYW1vdW50cywgdGhlbiByZWNhbGN1bGF0ZSB0aGUgYmFzZSBieSB0YWtpbmcgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcmVhbCBhbmQgaHlwb3RoZXRpY2FsIGV4ZW1wdGlvbnMuDQoNClRoZW4gcmVjYWxjdWxhdGUgdGhlIHRheCBiYXNlIGZvciBlYWNoIGRpc3RyaWN0LiBJZiBpbmNyZWFzaW5nIHRoZSBleGVtcHRpb24sIHRoZSBiYXNlIHNob3VsZCBkZWNyZWFzZSBiZWNhdXNlIHRoZXJlIGlzIGxlc3MgdGF4YWJsZSBFQVYuDQoNCmBgYHtyIGN1cnJlbnQtdGF4c3lzdGVtLCBldmFsPUZBTFNFLCBpbmNsdWRlID1GQUxTRX0NCg0KIyMjIE5PVCBORUVERUQgIyMjIA0KDQojIyBVc2VkIHRvIGNoZWNrIHRoZSAiY3VycmVudCB5ZWFyIiBpbiB0aGUgY29kZSBjaHVuayBiZWxvdw0KIyMgV2hlcmUgdGhlIGN1cnJlbnQgZXhlbXB0aW9uIGlzIHJlZHVjZWQgYnkgMTAsMDAwIA0KIyMgTGlrZSBvdXIgdmVyeSBtYWluIHNjZW5hcmlvIHdoZXJlIHdlIGRyb3BwZWQgZXhlbXB0aW9ucyANCg0KDQp0YXhfY29kZXMgPC0gREJJOjpkYkdldFF1ZXJ5KA0KICBwdGF4c2ltX2RiX2Nvbm4sDQogIGdsdWVfc3FsKCINCiAgU0VMRUNUIERJU1RJTkNUIHRheF9jb2RlX251bSwgdGF4X2NvZGVfcmF0ZQ0KICBGUk9NIHRheF9jb2RlDQogIFdIRVJFIHllYXIgPSAyMDIxDQogICIsDQogIC5jb24gPSBwdGF4c2ltX2RiX2Nvbm4NCiAgKQ0KKSAlPiUgbXV0YXRlKHRheF9jb2RlX251bSA9IGFzLm51bWVyaWModGF4X2NvZGVfbnVtKSkNCg0KDQoNCiMgTG9hZCBwaW5zDQp0X3BpbnMgPC0gREJJOjpkYkdldFF1ZXJ5KA0KICBwdGF4c2ltX2RiX2Nvbm4sDQogICINCiAgU0VMRUNUIERJU1RJTkNUIHBpbg0KICBGUk9NIHBpbg0KICBXSEVSRSB5ZWFyID0gMjAyMQ0KICAiDQopDQoNCnRfcGlucyA8LSB0X3BpbnMkcGluDQp0X3llYXJzIDwtIDIwMjENCg0KcmF0ZXMgPC0gTlVMTA0KZXhlX3N0ZXBzIDwtIGMoMCkNCg0KZm9yKG0gaW4gZXhlX3N0ZXBzKXsNCiAgDQojIFNldCBleGVtcHRpb24gdmFsdWUNCiAgdF9waW5fZHRfbmV3X2V4ZSA8LSBsb29rdXBfcGluKHRfeWVhcnMsIHRfcGlucykNCiAjIHRfcGluX2R0X25ld19leGVbLCB0YXhfY29kZSA6PSBsb29rdXBfdGF4X2NvZGUoeWVhciwgcGluKV0NCiAgDQogICMgbmV3IHRheGNvZGUgbGV2ZWwgc3VtcyBvZiBleGVtcHRpb24NCiAgDQogICB0X3Bpbl9kdF9uZXdfZXhlIDwtIHRfcGluX2R0X25ld19leGVbDQogICAgLC4oZXhlX2hvbWVvd25lciA9IGlmZWxzZShtKmV4ZV9ob21lb3duZXIhPTAgPiBlYXYsIGVhdiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UobSpleGVfaG9tZW93bmVyIT0wPGVhdiwgbSwgZXhlX2hvbWVvd25lcikpKQ0KICAgIF0NCiAgIA0KICAgDQogIHRfdGNfc3VtX25ld19leGUgPC0gdF9waW5fZHRfbmV3X2V4ZVsNCiAgICAsLihleGVfaG9tZW93bmVyID0gaWZlbHNlKG0qZXhlX2hvbWVvd25lciE9MCA+IGVhdiwgZWF2LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShtKmV4ZV9ob21lb3duZXIhPTA8ZWF2LCBtLCBleGVfaG9tZW93bmVyKSkpDQogICAgXVsNCiAgICAsLihleGVfaG9tZW93bmVyID0gc3VtKG0qZXhlX2hvbWVvd25lciE9MCkpLA0KICAgIGJ5ID0gLih5ZWFyLCB0YXhfY29kZSldDQogIFsNCiAgICAjIGlmIGV4ZV9ob21lb3duZXIgPiAwLCB0aGVuIGFkZCB0aGUgYWx0ZXJuYXRlIEdIRSBhbW91bnQgdG8gdGhlIGN1cnJlbnQgR0hFIGFtb3VudA0KICAgICMgY2FsY3VsYXRlcyB0aGUgYW1vdW50IG9mIEVBViB0byBiZSBhZGRlZC9zdWJ0cmFjdGVkIGZyb20gdGF4YWJsZSBiYXNlIG9mIHRheGluZyBhZ2VuY2llcw0KICAgICwgLihleGVfdG90YWwgPSBzdW0oKChtICogZXhlX2hvbWVvd25lciE9MCkpKSksDQogICAgYnkgPSAuKHllYXIsIHRheF9jb2RlKQ0KICBdDQogIA0KICAjIENhbGN1bGF0ZSBiYXNlcyBieSBhZGRpbmcgYWdlbmN5IHRvdGFsIGFuZCB0aGUgZXhlbXB0aW9uIGFtb3VudA0KICAjIG1vcmUgY29tcGxleCB0aGFuIGl0IG5lZWRzIHRvIGJlIHNpbmNlIHdlIG9ubHkgYXJlIHdvcmtpbmcgd2l0aCAxIHllYXIgb2YgZGF0YQ0KICB0X2FnZW5jeV9kdF9uZXdfZXhlIDwtIGxvb2t1cF9hZ2VuY3kodF95ZWFycywgdF9waW5fZHRfbmV3X2V4ZSR0YXhfY29kZSkNCiAgdF9hZ2VuY3lfZHRfbmV3X2V4ZVsNCiAgICB0X3RjX3N1bV9uZXdfZXhlLA0KICAgIG9uID0gLih5ZWFyLCB0YXhfY29kZSksDQogICAgYWdlbmN5X3RvdGFsX2VhdiA6PSBhZ2VuY3lfdG90YWxfZWF2IC0gZXhlX3RvdGFsDQogIF1bLCB0b3RhbF9maW5hbF9yYXRlIDo9IHRvdGFsX2V4dC9jdHlfY29va19lYXZdDQogIA0KICAjIFJlY2FsY3VsYXRlIHRheCBiaWxscw0KICB0X3Bpbl9kdF9uZXdfZXhlIDwtIHRfcGluX2R0X25ld19leGVbDQogICAjIGV4ZV9ob21lb3duZXIhPTAsIGV4ZV9ob21lb3duZXIgOj0gZXhlX2hvbWVvd25lcittDQogICAgZXhlX2hvbWVvd25lciE9MCwgZXhlX2hvbWVvd25lciA6PSBpZmVsc2UoZXhlX2hvbWVvd25lciArIG0gPiBlYXYgLCBlYXYsIGV4ZV9ob21lb3duZXIgKyBtKQ0KDQogIF1bDQogICAgLCBjKCJ0YXhfY29kZSIpIDo9IE5VTEwgICAgICAgIyBkZWxldGVzIHRheF9jb2RlIGNvbHVtbg0KICBdDQogIA0KICBiaWxscyA8LSB0YXhfYmlsbCgNCiAgICB5ZWFyX3ZlYyA9IHRfeWVhcnMsDQogICAgcGluX3ZlYyA9IHRfcGlucywNCiAgICBhZ2VuY3lfZHQgPSB0X2FnZW5jeV9kdF9uZXdfZXhlLA0KICAgIHBpbl9kdCA9IHRfcGluX2R0X25ld19leGUsDQogICAgc2ltcGxpZnkgPSBGQUxTRQ0KICApDQogIA0KIyBDbGVhciB1cCBtZW1vcnkNCiAgcm0odF9waW5fZHRfbmV3X2V4ZSwgdF90Y19zdW1fbmV3X2V4ZSkNCiAgDQogICAgIyBDb21iaW5lIGJpbGxzLCBhZ2dyZWdhdGUgdG8gcGluIGJ5IHllYXINCiAgY3VycmVudF9yYXRlcyA8LSBiaWxscyAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkocGluLCB0YXhfY29kZSkgJT4lDQogICAgbXV0YXRlKHRvdGFsX2JpbGwgPSBmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpICU+JSAjIGZyb20gZWFjaCB0YXhpbmcgYWdlbmN5DQogICAgDQogICAgc3VtbWFyaXplKA0KICAgICAgdG90YWxfYmlsbGVkID0gc3VtKHRvdGFsX2JpbGwsIG5hLnJtID0gVFJVRSksICMgdG90YWwgb24gc29tZW9uZSdzIHByb3BlcnR5IHRheCBiaWxsDQogICAgICBhdiA9IGZpcnN0KGF2KSwNCiAgICAgIGVhdiA9IGZpcnN0KGVhdiksDQogICAgICB0YXhpbmdfYWdlbmN5X2NvdW50ID0gbigpLCAjIG51bWJlciBvZiB0YXhpbmcgYWdlbmNpZXMgdGhhdCB0YXggdGhlIHBpbg0KICAgICAgZmluYWxfdGF4X3RvX2Rpc3QgPSBzdW0oZmluYWxfdGF4X3RvX2Rpc3QsIG5hLnJtID0gVFJVRSksICMgcG9ydGlvbiBvZiBhbGwgbGV2aWVzIHBhaWQgYnkgdGhlIHBpbg0KICAgICAgZmluYWxfdGF4X3RvX3RpZiA9IHN1bShmaW5hbF90YXhfdG9fdGlmLCBuYS5ybSA9IFRSVUUpLCANCiAgICAgIHRheF9hbXRfZXhlID0gc3VtKHRheF9hbXRfZXhlLCBuYS5ybSA9IFRSVUUpLCAgICAgICAgICAgIyByZXZlbnVlICJsb3N0IiBkdWUgdG8gZXhlbXB0aW9ucw0KICAgICAgdGF4X2FtdF9wcmVfZXhlID0gc3VtKHRheF9hbXRfcHJlX2V4ZSwgbmEucm0gPSBUUlVFKSwgICAjIHRvdGFsIHJldiBiZWZvcmUgYWxsIGV4ZW1wdGlvbnMNCiAgICAgIHRheF9hbXRfcG9zdF9leGUgPSBzdW0odGF4X2FtdF9wb3N0X2V4ZSwgbmEucm0gPSBUUlVFKSwgIyB0b3RhbCByZXYgYWZ0ZXIgYWxsIGV4ZW1wdGlvbnMNCiAgICAgICMgcnBtX3RpZl90b19jcHMgPSBzdW0ocnBtX3RpZl90b19jcHMsIG5hLnJtID0gVFJVRSksICAgICAjIG5vdCB1c2VkDQogICAgICAjIHJwbV90aWZfdG9fcnBtID0gc3VtKHJwbV90aWZfdG9fcnBtLCBuYS5ybT1UUlVFKSwgICAgICAgIyBub3QgdXNlZA0KICAgICAgIyBycG1fdGlmX3RvX2Rpc3QgPSBzdW0ocnBtX3RpZl90b19kaXN0LCBuYS5ybT1UUlVFKSwgICAgICMgbm90IHVzZWQNCiAgICAgICMgdGlmX3NoYXJlID0gbWVhbih0aWZfc2hhcmUsIG5hLnJtPVRSVUUpLCAgICAgICAgICAgICAgICAjIG5vdCB1c2VkDQogICAgKSAlPiUNCiAgICBtdXRhdGUodGF4X2NvZGUgPSBhcy5udW1lcmljKHRheF9jb2RlKSkgJT4lIA0KICAgIGxlZnRfam9pbih0YXhfY29kZXMsIGJ5ID0gYygidGF4X2NvZGUiID0gInRheF9jb2RlX251bSIpICkgJT4lICMgYWRkIGN1cnJlbnQsIHJlYWwgdGF4IGNvZGUgbGV2ZWwgdGF4IHJhdGVzDQogICAgbXV0YXRlKGV4ZW1wdGlvbl9sZXZlbCA9IG0pICU+JQ0KICAgIGRwbHlyOjpncm91cF9ieSh0YXhfY29kZSwgZXhlbXB0aW9uX2xldmVsKSAlPiUNCiAgICBkcGx5cjo6c3VtbWFyaXplKA0KICAgICAgdGNfbGV2eSA9IHN1bShmaW5hbF90YXhfdG9fZGlzdCwgbmEucm0gPSBUUlVFKSwgIyBhbW91bnQgYmlsbGVkIGJ5IG11bmlzIHdpdGggY3VycmVudCBleGVtcHRpb25zIGluIHBsYWNlDQogICAgICBub25USUZfRUFWX3Bvc3RfZXhlbXBzID0gc3VtKGZpbmFsX3RheF90b19kaXN0Lyh0YXhfY29kZV9yYXRlLzEwMCksIG5hLnJtID0gVFJVRSksDQogICAgICBUSUZfaW5jcmVtZW50X0VBViA9IHN1bShmaW5hbF90YXhfdG9fdGlmLyh0YXhfY29kZV9yYXRlLzEwMCksIG5hLnJtPVRSVUUpLCAgDQogICAgICBFeGVtcHRfRUFWID0gc3VtKHRheF9hbXRfZXhlLyh0YXhfY29kZV9yYXRlLzEwMCksIG5hLnJtPVRSVUUpLCANCiAgICAgIFRvdGFsX0VBViA9IHN1bSgodGF4X2FtdF9leGUrZmluYWxfdGF4X3RvX2Rpc3QrZmluYWxfdGF4X3RvX3RpZikvKHRheF9jb2RlX3JhdGUvMTAwKSwgbmEucm0gPSBUUlVFKSwNCiAgICApICU+JQ0KICANCiAgICBtdXRhdGUoDQogICAgICB0YXhfcmF0ZV9jdXJyZW50ID0gdGNfbGV2eS9ub25USUZfRUFWX3Bvc3RfZXhlbXBzLA0KICAgICAgbm9uVElGX0VBVl9wcmVfZXhlbXBzID0gbm9uVElGX0VBVl9wb3N0X2V4ZW1wcyArIEV4ZW1wdF9FQVYsDQogICAgICB0YXhyYXRlX25ldyA9IHRjX2xldnkvbm9uVElGX0VBVl9wcmVfZXhlbXBzLCAjIHRheCByYXRlIGlmIHRoZXJlIHdlcmUgbm8gZXhlbXB0aW9ucw0KICAgICAgdGF4cmF0ZV9jaGFuZ2UgPSB0YXhfcmF0ZV9jdXJyZW50LXRheHJhdGVfbmV3LA0KICAgICkgJT4lIA0KICAgIHNlbGVjdCh0YXhfY29kZSwgdGF4cmF0ZV9jaGFuZ2UsIHRheF9yYXRlX2N1cnJlbnQsIHRheHJhdGVfbmV3LCBldmVyeXRoaW5nKCkpICU+JSANCiAgICBhcnJhbmdlKGRlc2ModGF4X2NvZGUpKQ0KICANCiAgICMgcm0oYmlsbHMpDQp9DQoNCnRjX2N1cnJlbnRfcmF0ZXMgPC0gcmF0ZXMNCg0KYmlsbHMgPC0gdGF4X2JpbGwoMjAyMSwgcGluX3ZlYyA9IHRfcGlucywgc2ltcGxpZnkgPSBGQUxTRSkNCg0KDQptdW5pbGV2ZWxfY3VycmVudF9yYXRlcyA8LSBiaWxscyAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkocGluLCB0YXhfY29kZSkgJT4lDQogICAgbXV0YXRlKHRvdGFsX2JpbGwgPSBmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpICU+JSAgICAgICMgZnJvbSBlYWNoIHRheGluZyBhZ2VuY3kNCiAgICBzdW1tYXJpemUoDQogICAgICB0b3RhbF9iaWxsZWQgPSBzdW0odG90YWxfYmlsbCwgbmEucm0gPSBUUlVFKSwgICAgICAgICAgICAgICAgICAgICMgdG90YWwgb24gc29tZW9uZSdzIHByb3BlcnR5IHRheCBiaWxsDQogICAgICBhdiA9IGZpcnN0KGF2KSwNCiAgICAgIGVhdiA9IGZpcnN0KGVhdiksDQogICAgICB0YXhpbmdfYWdlbmN5X2NvdW50ID0gbigpLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgbnVtYmVyIG9mIHRheGluZyBhZ2VuY2llcyB0aGF0IHRheCB0aGUgcGluDQogICAgICBmaW5hbF90YXhfdG9fZGlzdCA9IHN1bShmaW5hbF90YXhfdG9fZGlzdCwgbmEucm0gPSBUUlVFKSwgICAgICAgICMgcG9ydGlvbiBvZiBhbGwgbGV2aWVzIHBhaWQgYnkgdGhlIHBpbg0KICAgICAgZmluYWxfdGF4X3RvX3RpZiA9IHN1bShmaW5hbF90YXhfdG9fdGlmLCBuYS5ybSA9IFRSVUUpLCANCiAgICAgIHRheF9hbXRfZXhlID0gc3VtKHRheF9hbXRfZXhlLCBuYS5ybSA9IFRSVUUpLCAgICAgICAgICAgIyByZXZlbnVlIGxvc3QgZHVlIHRvIGV4ZW1wdGlvbnMNCiAgICAgIHRheF9hbXRfcHJlX2V4ZSA9IHN1bSh0YXhfYW10X3ByZV9leGUsIG5hLnJtID0gVFJVRSksICAgIyB0b3RhbCByZXYgYmVmb3JlIGFsbCBleGVtcHRpb25zDQogICAgICB0YXhfYW10X3Bvc3RfZXhlID0gc3VtKHRheF9hbXRfcG9zdF9leGUsIG5hLnJtID0gVFJVRSksICMgdG90YWwgcmV2IGFmdGVyIGFsbCBleGVtcHRpb25zDQogICAgICApICU+JQ0KICAgICMgbXV0YXRlKHRheF9jb2RlID0gYXMubnVtZXJpYyh0YXhfY29kZSkpICU+JSANCiAgICBsZWZ0X2pvaW4odGNfbXVuaW5hbWVzLCBieSA9IGMoInRheF9jb2RlIiA9ICJ0YXhfY29kZV9udW0iKSApICU+JQ0KICAjIGFkZCBjdXJyZW50LCByZWFsIHRheCBjb2RlIGxldmVsIHRheCByYXRlcw0KICAgIGRwbHlyOjpncm91cF9ieShjbGVhbl9uYW1lLCBhZ2VuY3lfbnVtKSAlPiUNCiAgICBkcGx5cjo6c3VtbWFyaXplKA0KICAgICAgbXVuaV9sZXZ5ID0gc3VtKGZpbmFsX3RheF90b19kaXN0LCBuYS5ybSA9IFRSVUUpLCAjIGFtb3VudCBiaWxsZWQgYnkgbXVuaXMgd2l0aCBjdXJyZW50IGV4ZW1wdGlvbnMgaW4gcGxhY2UNCiAgICAgIG5vblRJRl9FQVZfcG9zdF9leGVtcHMgPSBzdW0oZmluYWxfdGF4X3RvX2Rpc3QvKHRheF9jb2RlX3JhdGUvMTAwKSwgbmEucm0gPSBUUlVFKSwNCiAgICAgIFRJRl9pbmNyZW1lbnRfRUFWID0gc3VtKGZpbmFsX3RheF90b190aWYvKHRheF9jb2RlX3JhdGUvMTAwKSwgbmEucm09VFJVRSksICANCiAgICAgIEV4ZW1wdF9FQVYgPSBzdW0odGF4X2FtdF9leGUvKHRheF9jb2RlX3JhdGUvMTAwKSwgbmEucm09VFJVRSksIA0KICAgICAgVG90YWxfRUFWID0gc3VtKCh0YXhfYW10X2V4ZStmaW5hbF90YXhfdG9fZGlzdCtmaW5hbF90YXhfdG9fdGlmKS8odGF4X2NvZGVfcmF0ZS8xMDApLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgcGluX2NvdW50ID0gbigpDQogICAgKSAlPiUNCiAgDQogICAgbXV0YXRlKA0KICAgICAgdGF4X3JhdGVfY3VycmVudCA9IG11bmlfbGV2eS9ub25USUZfRUFWX3Bvc3RfZXhlbXBzLA0KICAgICAgbm9uVElGX0VBVl9wcmVfZXhlbXBzID0gbm9uVElGX0VBVl9wb3N0X2V4ZW1wcyArIEV4ZW1wdF9FQVYsDQogICAgICB0YXhyYXRlX25ldyA9IG11bmlfbGV2eS9ub25USUZfRUFWX3ByZV9leGVtcHMsICMgdGF4IHJhdGUgaWYgdGhlcmUgd2VyZSBubyBleGVtcHRpb25zIGF0IGFsbA0KICAgICAgdGF4cmF0ZV9jaGFuZ2UgPSB0YXhfcmF0ZV9jdXJyZW50LXRheHJhdGVfbmV3LA0KICAgICkNCiAgDQogIA0KYGBgDQoNCmBgYHtyIHNjZW5hcmlvcy10YXhjb2RlbGV2ZWwsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQoNCnRheF9jb2RlcyA8LSBEQkk6OmRiR2V0UXVlcnkoDQogIHB0YXhzaW1fZGJfY29ubiwNCiAgZ2x1ZV9zcWwoIg0KICBTRUxFQ1QgRElTVElOQ1QgdGF4X2NvZGVfbnVtLCB0YXhfY29kZV9yYXRlDQogIEZST00gdGF4X2NvZGUNCiAgV0hFUkUgeWVhciA9IDIwMjENCiAgIiwNCiAgLmNvbiA9IHB0YXhzaW1fZGJfY29ubg0KICApDQopICU+JSBtdXRhdGUodGF4X2NvZGVfbnVtID0gYXMubnVtZXJpYyh0YXhfY29kZV9udW0pKQ0KDQoNCg0KIyBMb2FkIHBpbnMNCnRfcGlucyA8LSBEQkk6OmRiR2V0UXVlcnkoDQogIHB0YXhzaW1fZGJfY29ubiwNCiAgIg0KICBTRUxFQ1QgRElTVElOQ1QgcGluDQogIEZST00gcGluDQogICINCikNCg0KdF9waW5zIDwtIHRfcGlucyRwaW4NCnRfeWVhcnMgPC0gMjAyMQ0KDQpyYXRlcyA8LSBOVUxMDQpleGVfc3RlcHMgPC0gYygtMTAwMDAsIC01MDAwLCAwLCA1MDAwLCAxMDAwMCwgMTUwMDAsIDIwMDAwLCAzMDAwMCwgNDAwMDApDQoNCnN0YXJ0X3RpbWUgPC0gU3lzLnRpbWUoKQ0KZm9yKG0gaW4gZXhlX3N0ZXBzKXsNCiAgDQojIFNldCBleGVtcHRpb24gdmFsdWUNCiAgdF9waW5fZHRfbmV3X2V4ZSA8LSBsb29rdXBfcGluKHRfeWVhcnMsIHRfcGlucykNCiAgdF9waW5fZHRfbmV3X2V4ZVssIHRheF9jb2RlIDo9IGxvb2t1cF90YXhfY29kZSh5ZWFyLCBwaW4pXQ0KICANCiAgIyBuZXcgdGF4Y29kZSBsZXZlbCBzdW1zIG9mIGV4ZW1wdGlvbg0KICB0X3RjX3N1bV9uZXdfZXhlIDwtIHRfcGluX2R0X25ld19leGVbDQogICAgIyBpZiBleGVfaG9tZW93bmVyID4gMCwgdGhlbiBhZGQgdGhlIGFsdGVybmF0ZSBHSEUgYW1vdW50IHRvIHRoZSBjdXJyZW50IEdIRSBhbW91bnQNCiAgICAjIGNhbGN1bGF0ZXMgdGhlIGFtb3VudCBvZiBFQVYgdG8gYmUgYWRkZWQvc3VidHJhY3RlZCBmcm9tIHRheGFibGUgYmFzZSBvZiB0YXhpbmcgYWdlbmNpZXMNCiAgICAsIC4oZXhlX3RvdGFsID0gc3VtKCgobSAqIGV4ZV9ob21lb3duZXIhPTApKSkpLA0KICAgIGJ5ID0gLih5ZWFyLCB0YXhfY29kZSkNCiAgXQ0KICANCiAgIyBDYWxjdWxhdGUgYmFzZXMgYnkgYWRkaW5nIGFnZW5jeSB0b3RhbCBhbmQgdGhlIGV4ZW1wdGlvbiBhbW91bnQNCiAgdF9hZ2VuY3lfZHRfbmV3X2V4ZSA8LSBsb29rdXBfYWdlbmN5KHRfeWVhcnMsIHRfcGluX2R0X25ld19leGUkdGF4X2NvZGUpDQogIHRfYWdlbmN5X2R0X25ld19leGVbDQogICAgdF90Y19zdW1fbmV3X2V4ZSwNCiAgICBvbiA9IC4oeWVhciwgdGF4X2NvZGUpLA0KICAgIGFnZW5jeV90b3RhbF9lYXYgOj0gYWdlbmN5X3RvdGFsX2VhdiAtIGV4ZV90b3RhbA0KICBdDQogIA0KICAjIFJlY2FsY3VsYXRlIHRheCBiaWxscw0KICB0X3Bpbl9kdF9uZXdfZXhlIDwtIHRfcGluX2R0X25ld19leGVbDQogICAgZXhlX2hvbWVvd25lciE9MCwgZXhlX2hvbWVvd25lciA6PSBleGVfaG9tZW93bmVyK20NCiAgXVsNCiAgICAjIyMgQUREIElGIEVMU0UgU1RBVEVNRU5UIA0KICAgIA0KICAgIA0KICAgICwgYygidGF4X2NvZGUiKSA6PSBOVUxMICAgICAgICMgZGVsZXRlcyB0YXhfY29kZSBjb2x1bW4NCiAgXQ0KICANCiAgYmlsbHMgPC0gdGF4X2JpbGwoDQogICAgeWVhcl92ZWMgPSB0X3llYXJzLA0KICAgIHBpbl92ZWMgPSB0X3BpbnMsDQogICAgYWdlbmN5X2R0ID0gdF9hZ2VuY3lfZHRfbmV3X2V4ZSwNCiAgICBwaW5fZHQgPSB0X3Bpbl9kdF9uZXdfZXhlLA0KICAgIHNpbXBsaWZ5ID0gRkFMU0UNCiAgKQ0KICANCiMgQ2xlYXIgdXAgbWVtb3J5DQogIHJtKHRfcGluX2R0X25ld19leGUsIHRfdGNfc3VtX25ld19leGUpDQogIA0KICAgICMgQ29tYmluZSBiaWxscywgYWdncmVnYXRlIHRvIHBpbiBieSB5ZWFyDQogIHJhdGVzMiA8LSBiaWxscyAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkocGluLCB0YXhfY29kZSkgJT4lDQogICAgDQogICAgbXV0YXRlKHRvdGFsX2JpbGwgPSBmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpICU+JSAjIGZyb20gZWFjaCB0YXhpbmcgYWdlbmN5DQogICAgDQogICAgc3VtbWFyaXplKA0KICAgICAgdG90YWxfYmlsbGVkID0gc3VtKHRvdGFsX2JpbGwsIG5hLnJtID0gVFJVRSksICMgdG90YWwgb24gc29tZW9uZSdzIHByb3BlcnR5IHRheCBiaWxsDQogICAgICBhdiA9IGZpcnN0KGF2KSwNCiAgICAgIGVhdiA9IGZpcnN0KGVhdiksDQogICAgICB0YXhpbmdfYWdlbmN5X2NvdW50ID0gbigpLCAjIG51bWJlciBvZiB0YXhpbmcgYWdlbmNpZXMgdGhhdCB0YXggdGhlIHBpbg0KICAgICAgZmluYWxfdGF4X3RvX2Rpc3QgPSBzdW0oZmluYWxfdGF4X3RvX2Rpc3QsIG5hLnJtID0gVFJVRSksICMgcG9ydGlvbiBvZiBhbGwgbGV2aWVzIHBhaWQgYnkgdGhlIHBpbg0KICAgICAgZmluYWxfdGF4X3RvX3RpZiA9IHN1bShmaW5hbF90YXhfdG9fdGlmLCBuYS5ybSA9IFRSVUUpLCANCiAgICAgIHRheF9hbXRfZXhlID0gc3VtKHRheF9hbXRfZXhlLCBuYS5ybSA9IFRSVUUpLCAgICAgICAgICAgIyByZXZlbnVlIGxvc3QgZHVlIHRvIGV4ZW1wdGlvbnMNCiAgICAgIHRheF9hbXRfcHJlX2V4ZSA9IHN1bSh0YXhfYW10X3ByZV9leGUsIG5hLnJtID0gVFJVRSksICAgIyB0b3RhbCByZXYgYmVmb3JlIGFsbCBleGVtcHRpb25zDQogICAgICB0YXhfYW10X3Bvc3RfZXhlID0gc3VtKHRheF9hbXRfcG9zdF9leGUsIG5hLnJtID0gVFJVRSkjLCAjIHRvdGFsIHJldiBhZnRlciBhbGwgZXhlbXB0aW9ucw0KICAgICAgIyBycG1fdGlmX3RvX2NwcyA9IHN1bShycG1fdGlmX3RvX2NwcywgbmEucm0gPSBUUlVFKSwgICAgICMgbm90IHVzZWQNCiAgICAgICMgcnBtX3RpZl90b19ycG0gPSBzdW0ocnBtX3RpZl90b19ycG0sIG5hLnJtPVRSVUUpLCAgICAgICAjIG5vdCB1c2VkDQogICAgICAjIHJwbV90aWZfdG9fZGlzdCA9IHN1bShycG1fdGlmX3RvX2Rpc3QsIG5hLnJtPVRSVUUpLCAgICAgIyBub3QgdXNlZA0KICAgICAgIyB0aWZfc2hhcmUgPSBtZWFuKHRpZl9zaGFyZSwgbmEucm09VFJVRSksICAgICAgICAgICAgICAgICMgbm90IHVzZWQNCiAgICApICU+JQ0KICAgIyBtdXRhdGUodGF4X2NvZGUgPSBhcy5udW1lcmljKHRheF9jb2RlKSkgJT4lIA0KICAgIG11dGF0ZShleGVtcHRpb25fbGV2ZWwgPSBtKSAlPiUNCiAgICMgbGVmdF9qb2luKHRheF9jb2RlcywgYnkgPSBjKCJ0YXhfY29kZSIgPSAidGF4X2NvZGVfbnVtIikgKSAlPiUgIyBhZGQgY3VycmVudCwgcmVhbCB0YXggY29kZSBsZXZlbCB0YXggcmF0ZXMNCiAgICBkcGx5cjo6Z3JvdXBfYnkodGF4X2NvZGUsIGV4ZW1wdGlvbl9sZXZlbCkgJT4lDQogICAgZHBseXI6OnN1bW1hcml6ZSgNCiAgICAgIHRvdGFsX2JpbGxlZCA9IHN1bSh0b3RhbF9iaWxsZWQsIG5hLnJtID0gVFJVRSksICMgdG90YWwgb24gc29tZW9uZSdzIHByb3BlcnR5IHRheCBiaWxsDQogICAgICBhdiA9IHN1bShhdiwgbmEucm09VFJVRSksDQogICAgICBlYXYgPSBzdW0oZWF2LCBuYS5ybSA9IFRSVUUpLA0KICAgICAgdGF4aW5nX2FnZW5jeV9jb3VudCA9IGZpcnN0KHRheGluZ19hZ2VuY3lfY291bnQpLCAjIG51bWJlciBvZiB0YXhpbmcgYWdlbmNpZXMgdGhhdCB0YXggdGhlIHBpbg0KICAgICAgZmluYWxfdGF4X3RvX2Rpc3QgPSBzdW0oZmluYWxfdGF4X3RvX2Rpc3QsIG5hLnJtID0gVFJVRSksICMgcG9ydGlvbiBvZiBhbGwgbGV2aWVzIHBhaWQgYnkgdGhlIHBpbg0KICAgICAgZmluYWxfdGF4X3RvX3RpZiA9IHN1bShmaW5hbF90YXhfdG9fdGlmLCBuYS5ybSA9IFRSVUUpLCANCiAgICAgIHRheF9hbXRfZXhlID0gc3VtKHRheF9hbXRfZXhlLCBuYS5ybSA9IFRSVUUpLCAgICAgICAgICAgIyByZXZlbnVlIGxvc3QgZHVlIHRvIGV4ZW1wdGlvbnMNCiAgICAgIHRheF9hbXRfcHJlX2V4ZSA9IHN1bSh0YXhfYW10X3ByZV9leGUsIG5hLnJtID0gVFJVRSksICAgIyB0b3RhbCByZXYgYmVmb3JlIGFsbCBleGVtcHRpb25zDQogICAgICB0YXhfYW10X3Bvc3RfZXhlID0gc3VtKHRheF9hbXRfcG9zdF9leGUsIG5hLnJtID0gVFJVRSkgKSAlPiUgIyB0b3RhbCByZXYgYWZ0ZXIgYWxsIGV4ZW1wdGlvbnMNCiMgDQojICAgICBkcGx5cjo6c3VtbWFyaXplKA0KIyAgICAgICB0Y19sZXZ5ID0gc3VtKGZpbmFsX3RheF90b19kaXN0LCBuYS5ybSA9IFRSVUUpLCAjIGFtb3VudCBiaWxsZWQgYnkgbXVuaXMgd2l0aCBjdXJyZW50IGV4ZW1wdGlvbnMgaW4gcGxhY2UNCiMgICAgICAgbm9uVElGX0VBVl9wb3N0X2V4ZW1wcyA9IHN1bShmaW5hbF90YXhfdG9fZGlzdC8odGF4X2NvZGVfcmF0ZS8xMDApLCBuYS5ybSA9IFRSVUUpLA0KIyAgICAgICBUSUZfaW5jcmVtZW50X0VBViA9IHN1bShmaW5hbF90YXhfdG9fdGlmLyh0YXhfY29kZV9yYXRlLzEwMCksIG5hLnJtPVRSVUUpLCAgDQojICAgICAgIEV4ZW1wdF9FQVYgPSBzdW0odGF4X2FtdF9leGUvKHRheF9jb2RlX3JhdGUvMTAwKSwgbmEucm09VFJVRSksIA0KIyAgICAgICBUb3RhbF9FQVYgPSBzdW0oKHRheF9hbXRfZXhlK2ZpbmFsX3RheF90b19kaXN0K2ZpbmFsX3RheF90b190aWYpLyh0YXhfY29kZV9yYXRlLzEwMCksIG5hLnJtID0gVFJVRSksDQojICAgICApICU+JQ0KICANCiAgICAjIG11dGF0ZSgNCiAgICAjICAgdGNfbGV2eSA9IHN1bShmaW5hbF90YXhfdG9fZGlzdCwgbmEucm0gPSBUUlVFKSwgIyBhbW91bnQgYmlsbGVkIGJ5IG11bmlzIHdpdGggY3VycmVudCBleGVtcHRpb25zIGluIHBsYWNlDQogICAgIyAgIA0KICAgICMgICB0YXhfcmF0ZV9jdXJyZW50ID0gdGNfbGV2eS9ub25USUZfRUFWX3Bvc3RfZXhlbXBzLA0KICAgICMgICBub25USUZfRUFWX3ByZV9leGVtcHMgPSBub25USUZfRUFWX3Bvc3RfZXhlbXBzICsgRXhlbXB0X0VBViwNCiAgICAjICAgdGF4cmF0ZV9uZXcgPSB0Y19sZXZ5L25vblRJRl9FQVZfcHJlX2V4ZW1wcywNCiAgICAjICAgdGF4cmF0ZV9jaGFuZ2UgPSB0YXhfcmF0ZV9jdXJyZW50LXRheHJhdGVfbmV3LA0KICAgICMgKSAlPiUgDQogICAgIHNlbGVjdCh0YXhfY29kZSwgZXZlcnl0aGluZygpKQ0KDQogIA0KICBpZihpcy5kYXRhLmZyYW1lKHJhdGVzKSl7cmF0ZXMgPC0gcmJpbmQocmF0ZXMyLCByYXRlcyl9ZWxzZXtyYXRlcyA8LSByYXRlczJ9DQogIHJtKHJhdGVzMiwgYmlsbHMpDQp9DQplbmRfdGltZSA8LSBTeXMudGltZSgpDQplbmRfdGltZSAtIHN0YXJ0X3RpbWUNCg0Kd3JpdGVfY3N2KHJhdGVzLCAiQzovVXNlcnMvYWxlYXcvT25lRHJpdmUvRG9jdW1lbnRzL1BoRCBGYWxsIDIwMjEgLSBTcHJpbmcgMjAyMi9NZXJyaW1hbiBSQS9wdGF4L091dHB1dC81Yl9zY2VuYXJpb19yYXRlczMuY3N2IikNCmBgYA0KDQo8IS0tLSBsaW5lIDUyMSAtIGZpbmlzaCB0aG91Z2h0ISAgLS0tPg0KDQoNCmBgYHtyIHNjZW5hcmlvcy1tdW5pbGV2ZWwsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQoNCnJhdGVzIDwtIE5VTEwNCmV4ZV9zdGVwcyA8LSBjKC0xMDAwMCwgLTUwMDAsIDAsIDUwMDAsIDEwMDAwLCAxNTAwMCwgMjAwMDAsIDMwMDAwLCA0MDAwMCkNCg0Kc3RhcnRfdGltZSA8LSBTeXMudGltZSgpDQoNCmZvcihtIGluIGV4ZV9zdGVwcyl7DQogIA0KIyBTZXQgZXhlbXB0aW9uIHZhbHVlDQogIHRfcGluX2R0X25ld19leGUgPC0gbG9va3VwX3Bpbih0X3llYXJzLCB0X3BpbnMpICAgICAgIyBjcmVhdGVzICJjdXJyZW50IiB0YXggc3lzdGVtIHBpbiBkYXRhIHdpdGggY3VycmVudCBleGVtcHRpb25zDQogIA0KICB0X3Bpbl9kdF9uZXdfZXhlWywgdGF4X2NvZGUgOj0gbG9va3VwX3RheF9jb2RlKHllYXIsIHBpbildICAjIGFkZHMgdGF4IGNvZGUgdmFyaWFibGUgdG8gcGluICYgZXhlbXB0aW9uIGRhdGEgDQogIA0KICANCiAgDQoNCiAgIyBuZXcgdGF4Y29kZSBsZXZlbCBzdW1zIG9mIGV4ZW1wdGlvbg0KICANCiAjIHN1bW1hcml6ZXMgcGluIGRhdGEgdGFibGUgdGhhdCBoYXMgdGhlIHRheCBjb2RlIHZhcmlhYmxlIGJ5IHllYXIgYW5kIHRheCBjb2RlDQogIyBjcmVhdGVzIGEgbmV3IHZhcmlhYmxlIGV4ZV90b3RhbA0KICB0X3RjX3N1bV9uZXdfZXhlIDwtIHRfcGluX2R0X25ld19leGVbDQogICAgIyBpZiBleGVfaG9tZW93bmVyID4gMCwgdGhlbiBhZGQgdGhlIGFsdGVybmF0ZSBHSEUgYW1vdW50IHRvIHRoZSBjdXJyZW50IEdIRSBhbW91bnQNCiAgICAjIGNhbGN1bGF0ZXMgdGhlIGFtb3VudCBvZiBFQVYgdG8gYmUgYWRkZWQvc3VidHJhY3RlZCBmcm9tIHRheGFibGUgYmFzZSBvZiB0YXhpbmcgYWdlbmNpZXMNCiAgICAsIC4oZXhlX2NoYW5nZSA9IHN1bSgoKG0gKiBleGVfaG9tZW93bmVyIT0wKSkpKSwNCiAgICBieSA9IC4oeWVhciwgdGF4X2NvZGUpDQogIF0NCiAgDQojIyMjIyBDT01FIEJBQ0sgVE8gVEhJUyBQT0lOVCAjIyMjIyMgDQogIA0KIyAjIENhbGN1bGF0ZSBiYXNlcyBieSBhZGRpbmcgYWdlbmN5IHRvdGFsIGFuZCB0aGUgZXhlbXB0aW9uIGFtb3VudCAjICMgDQogIA0KICAjIG5ldyBhZ2VuY3kgZGF0YSB0YWJsZSA8LSAjIHNhbWUgaW5wdXQgYXMgbm9ybWFsIGFnZW5jeSB0YWJsZQ0KICB0X2FnZW5jeV9kdF9uZXdfZXhlIDwtIGxvb2t1cF9hZ2VuY3kodF95ZWFycywgdF9waW5fZHRfbmV3X2V4ZSR0YXhfY29kZSkNCiAgDQogICMjIHVwZGF0ZXMgdGF4YWJsZSBiYXNlIEVBViBpbiBhZ2VuY3kgZGF0YSB0YWJsZQ0KICB0X2FnZW5jeV9kdF9uZXdfZXhlWw0KICAgIHRfdGNfc3VtX25ld19leGUsDQogICAgb24gPSAuKHllYXIsIHRheF9jb2RlKSwNCiAgICBhZ2VuY3lfdG90YWxfZWF2IDo9IGFnZW5jeV90b3RhbF9lYXYgLSBleGVfY2hhbmdlDQogIF0NCiAgDQogICMgIyBSZWNhbGN1bGF0ZSB0YXggYmlsbHMNCiAgIyB0X3Bpbl9kdF9uZXdfZXhlIDwtIHRfcGluX2R0X25ld19leGVbDQogICMgICBleGVfaG9tZW93bmVyIT0wLCBleGVfaG9tZW93bmVyIDo9IGV4ZV9ob21lb3duZXIgKyBtDQogICMgXVsNCiAgIyAgIGV4ZV9ob21lb3duZXIgPiBlYXYsIGV4ZV9ob21lb3duZXI6PSBlYXYNCiAgIyBdWw0KICAjICAgLCBjKCJ0YXhfY29kZSIpIDo9IE5VTEwgICAgICAgIyBkZWxldGVzIHRheF9jb2RlIGNvbHVtbg0KICAjIF0NCg0KIyBSZWNhbGN1bGF0ZSB0YXggYmlsbHMNCnRfcGluX2R0X25ld19leGUgPC0gdF9waW5fZHRfbmV3X2V4ZVsNCiBleGVfaG9tZW93bmVyIT0gMCwgZXhlX2hvbWVvd25lciA6PSBpZmVsc2UoZXhlX2hvbWVvd25lciArIG0gPiBlYXYgLCBlYXYsIGV4ZV9ob21lb3duZXIgKyBtKQ0KIF1bDQogICAgLCBjKCJ0YXhfY29kZSIpIDo9IE5VTEwgICAgICAgIyBkZWxldGVzIHRheF9jb2RlIGNvbHVtbiBmcm9tIHBpbiB0YWJsZSB0aGF0IGhhcyBleGVtcHRpb24gZGF0YQ0KICBdDQoNCiMjIHJlLXN1bSBhbGwgaG9tZW93bmVyIGV4ZW1wdGlvbnMgYnkgYWdlbmN5ICogdXBkYXRlIHRheGFibGUgRUFWIGluIGFnZW5jeV9kdCANCiAgDQogIGJpbGxzIDwtIHRheF9iaWxsKA0KICAgIHllYXJfdmVjID0gdF95ZWFycywNCiAgICBwaW5fdmVjID0gdF9waW5zLA0KICAgIGFnZW5jeV9kdCA9IHRfYWdlbmN5X2R0X25ld19leGUsDQogICAgcGluX2R0ID0gdF9waW5fZHRfbmV3X2V4ZSwNCiAgICBzaW1wbGlmeSA9IEZBTFNFDQogICkNCiAgDQojIENsZWFyIHVwIG1lbW9yeQ0KICBybSh0X3Bpbl9kdF9uZXdfZXhlLCB0X3RjX3N1bV9uZXdfZXhlKQ0KICANCiAgICAjIENvbWJpbmUgYmlsbHMsIGFnZ3JlZ2F0ZSB0byBwaW4gYnkgeWVhcg0KICByYXRlczIgPC0gYmlsbHMgJT4lDQogICAgZHBseXI6Omdyb3VwX2J5KHBpbiwgdGF4X2NvZGUpICU+JQ0KICAgIA0KICAgIG11dGF0ZSh0b3RhbF9iaWxsID0gZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSAlPiUgIyBmcm9tIGVhY2ggdGF4aW5nIGFnZW5jeQ0KICAgIA0KICAgIHN1bW1hcml6ZSgNCiAgICAgIHRvdGFsX2JpbGxlZCA9IHN1bSh0b3RhbF9iaWxsLCBuYS5ybSA9IFRSVUUpLCAjIHRvdGFsIG9uIHNvbWVvbmUncyBwcm9wZXJ0eSB0YXggYmlsbA0KICAgICAgYXYgPSBmaXJzdChhdiksDQogICAgICBlYXYgPSBmaXJzdChlYXYpLA0KICAgICAgdGF4aW5nX2FnZW5jeV9jb3VudCA9IG4oKSwgIyBudW1iZXIgb2YgdGF4aW5nIGFnZW5jaWVzIHRoYXQgdGF4IHRoZSBwaW4NCiAgICAgIGZpbmFsX3RheF90b19kaXN0ID0gc3VtKGZpbmFsX3RheF90b19kaXN0LCBuYS5ybSA9IFRSVUUpLCAjIHBvcnRpb24gb2YgYWxsIGxldmllcyBwYWlkIGJ5IHRoZSBwaW4NCiAgICAgIGZpbmFsX3RheF90b190aWYgPSBzdW0oZmluYWxfdGF4X3RvX3RpZiwgbmEucm0gPSBUUlVFKSwgDQogICAgICB0YXhfYW10X2V4ZSA9IHN1bSh0YXhfYW10X2V4ZSwgbmEucm0gPSBUUlVFKSwgICAgICAgICAgICMgcmV2ZW51ZSBsb3N0IGR1ZSB0byBleGVtcHRpb25zDQogICAgICB0YXhfYW10X3ByZV9leGUgPSBzdW0odGF4X2FtdF9wcmVfZXhlLCBuYS5ybSA9IFRSVUUpLCAgICMgdG90YWwgcmV2IGJlZm9yZSBhbGwgZXhlbXB0aW9ucw0KICAgICAgdGF4X2FtdF9wb3N0X2V4ZSA9IHN1bSh0YXhfYW10X3Bvc3RfZXhlLCBuYS5ybSA9IFRSVUUpIywgIyB0b3RhbCByZXYgYWZ0ZXIgYWxsIGV4ZW1wdGlvbnMNCikgJT4lDQogICAjIG11dGF0ZSh0YXhfY29kZSA9IGFzLm51bWVyaWModGF4X2NvZGUpKSAlPiUgDQogICAgbXV0YXRlKGV4ZW1wdGlvbl9sZXZlbCA9IG0pICU+JQ0KICAgIyBsZWZ0X2pvaW4odGF4X2NvZGVzLCBieSA9IGMoInRheF9jb2RlIiA9ICJ0YXhfY29kZV9udW0iKSApICU+JSAjIGFkZCBjdXJyZW50LCByZWFsIHRheCBjb2RlIGxldmVsIHRheCByYXRlcw0KICAgIGxlZnRfam9pbih0Y19tdW5pbmFtZXMsIGJ5ID0gYygidGF4X2NvZGUiID0gInRheF9jb2RlX251bSIpKSAlPiUNCiAgICBkcGx5cjo6Z3JvdXBfYnkoY2xlYW5fbmFtZSwgYWdlbmN5X251bSwgZXhlbXB0aW9uX2xldmVsKSAlPiUNCiAgICBkcGx5cjo6c3VtbWFyaXplKA0KICAgICAgdG90YWxfYmlsbGVkID0gc3VtKHRvdGFsX2JpbGxlZCwgbmEucm0gPSBUUlVFKSwgIyB0b3RhbCBvbiBzb21lb25lJ3MgcHJvcGVydHkgdGF4IGJpbGwNCiAgICAgIGF2ID0gc3VtKGF2LCBuYS5ybT1UUlVFKSwNCiAgICAgIGVhdiA9IHN1bShlYXYsIG5hLnJtID0gVFJVRSksDQogICAgICANCiAgICAgIG5vblRJRl9FQVZfcG9zdF9leGVtcHMgPSBzdW0oZmluYWxfdGF4X3RvX2Rpc3QvKHRheF9jb2RlX3JhdGUvMTAwKSwgbmEucm0gPSBUUlVFKSwNCiAgICAgIFRJRl9pbmNyZW1lbnRfRUFWID0gc3VtKGZpbmFsX3RheF90b190aWYvKHRheF9jb2RlX3JhdGUvMTAwKSwgbmEucm09VFJVRSksDQogICAgICBFeGVtcHRfRUFWID0gc3VtKHRheF9hbXRfZXhlLyh0YXhfY29kZV9yYXRlLzEwMCksIG5hLnJtPVRSVUUpLA0KICAgICAgVG90YWxfRUFWID0gc3VtKCh0YXhfYW10X2V4ZStmaW5hbF90YXhfdG9fZGlzdCtmaW5hbF90YXhfdG9fdGlmKS8odGF4X2NvZGVfcmF0ZS8xMDApLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgZmluYWxfdGF4X3RvX2Rpc3QgPSBzdW0oZmluYWxfdGF4X3RvX2Rpc3QsIG5hLnJtID0gVFJVRSksIA0KICAgICAgZmluYWxfdGF4X3RvX3RpZiA9IHN1bShmaW5hbF90YXhfdG9fdGlmLCBuYS5ybSA9IFRSVUUpLCANCiAgICAgIHRheF9hbXRfZXhlID0gc3VtKHRheF9hbXRfZXhlLCBuYS5ybSA9IFRSVUUpLCAgICANCiAgICAgIHRheF9hbXRfcHJlX2V4ZSA9IHN1bSh0YXhfYW10X3ByZV9leGUsIG5hLnJtID0gVFJVRSksICAgDQogICAgICB0YXhfYW10X3Bvc3RfZXhlID0gc3VtKHRheF9hbXRfcG9zdF9leGUsIG5hLnJtID0gVFJVRSksDQogICAgICBwaW5fY291bnQgPSBuKCkNCg0KICAgICkgJT4lDQogIA0KICAgIG11dGF0ZSgNCiAgICAgIHRheF9yYXRlX2N1cnJlbnQgPSBmaW5hbF90YXhfdG9fZGlzdC9ub25USUZfRUFWX3Bvc3RfZXhlbXBzLA0KICAgICAgbm9uVElGX0VBVl9wcmVfZXhlbXBzID0gbm9uVElGX0VBVl9wb3N0X2V4ZW1wcyArIEV4ZW1wdF9FQVYsDQogICAgICB0YXhyYXRlX25ldyA9IGZpbmFsX3RheF90b19kaXN0L25vblRJRl9FQVZfcHJlX2V4ZW1wcywNCiAgICAgIHRheHJhdGVfY2hhbmdlID0gdGF4X3JhdGVfY3VycmVudC10YXhyYXRlX25ldywNCiAgICApICU+JQ0KICAgICBzZWxlY3QoY2xlYW5fbmFtZSwgZXZlcnl0aGluZygpKQ0KDQogIA0KICANCiAgaWYoaXMuZGF0YS5mcmFtZShyYXRlcykpe3JhdGVzIDwtIHJiaW5kKHJhdGVzMiwgcmF0ZXMpfWVsc2V7cmF0ZXMgPC0gcmF0ZXMyfQ0KICBybShyYXRlczIsIGJpbGxzKQ0KfQ0KZW5kX3RpbWUgPC0gU3lzLnRpbWUoKQ0KZW5kX3RpbWUgLSBzdGFydF90aW1lDQoNCg0Kd3JpdGVfY3N2KHJhdGVzLCAiQzovVXNlcnMvYWxlYXcvT25lRHJpdmUvRG9jdW1lbnRzL1BoRCBGYWxsIDIwMjEgLSBTcHJpbmcgMjAyMi9NZXJyaW1hbiBSQS9wdGF4L091dHB1dC81Yl9zY2VuYXJpb19yYXRlc19tdW5pbGV2ZWxfc2NlbmFyaW9zMi5jc3YiKQ0KDQoNCg0KYGBgDQoNCg0KYGBge3IgcmVhZC1pbi1yYXRlcywgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0NCnNjZW5hcmlvX3JhdGVzIDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9hbGVhdy9PbmVEcml2ZS9Eb2N1bWVudHMvUGhEIEZhbGwgMjAyMSAtIFNwcmluZyAyMDIyL01lcnJpbWFuIFJBL3B0YXgvT3V0cHV0LzViX3NjZW5hcmlvX3JhdGVzMy5jc3YiKSAlPiUNCiAjIHJlYWRfY3N2KCJDOi9Vc2Vycy9hbGVhdy9PbmVEcml2ZS9Eb2N1bWVudHMvUGhEIEZhbGwgMjAyMSAtIFNwcmluZyAyMDIyL01lcnJpbWFuIFJBL3B0YXgvT3V0cHV0LzViX3NjZW5hcmlvX3JhdGVzLmNzdiIpICU+JQ0KICBtdXRhdGUodGF4X2NvZGUgPSBhcy5jaGFyYWN0ZXIodGF4X2NvZGUpKSAlPiUgDQogIGxlZnRfam9pbih0Y19tdW5pbmFtZXMsIGJ5ID0gYygidGF4X2NvZGUiID0gInRheF9jb2RlX251bSIpKSAlPiUNCiAgc2VsZWN0KGNsZWFuX25hbWUsIHRheF9jb2RlLCBldmVyeXRoaW5nKCkpDQoNCiAjIHNjZW5hcmlvX3JhdGVzICU+JSB3cml0ZV9jc3YoIkM6L1VzZXJzL2FsZWF3L09uZURyaXZlL0RvY3VtZW50cy9QaEQgRmFsbCAyMDIxIC0gU3ByaW5nIDIwMjIvTWVycmltYW4gUkEvcHRheC9PdXRwdXQvNWJfc2NlbmFyaW9fcmF0ZXNfbGFiZWxlZDIuY3N2IikNCg0Kc2NlbmFyaW9fcmF0ZXMNCg0Kc2NlbmFyaW9fcmF0ZXNfbXVuaWxldmVsX3NjZW5hcmlvcyA8LSByZWFkX2NzdigiQzovVXNlcnMvYWxlYXcvT25lRHJpdmUvRG9jdW1lbnRzL1BoRCBGYWxsIDIwMjEgLSBTcHJpbmcgMjAyMi9NZXJyaW1hbiBSQS9wdGF4L091dHB1dC81Yl9zY2VuYXJpb19yYXRlc19tdW5pbGV2ZWxfc2NlbmFyaW9zLmNzdiIpDQoNCnNjZW5hcmlvX3JhdGVzX211bmlsZXZlbF9zY2VuYXJpb3MNCg0KYGBgDQoNCg0KIyMgUXVhcnRpbGVzIGFuZCBQcm9ncmVzc2l2aXR5DQoNCmBgYHtyfQ0KY2xhc3NfZGljdCA8LSByZWFkX2NzdigiLi9OZWNlc3NhcnlfRmlsZXMvY2xhc3NfZGljdF9zaW5nbGVmYW1jb2Rlcy5jc3YiKSAlPiUgDQogIG11dGF0ZShjbGFzc19jb2RlID0gYXMuY2hhcmFjdGVyKGNsYXNzX2NvZGUpKSAjIGNoYW5nZSB2YXJpYWJsZSB0eXBlIHRvIGNoYXJhY3RlciBzbyB0aGUgam9pbiB3b3Jrcy4NCg0Kbmlja25hbWVzIDwtIHJlYWR4bDo6cmVhZF94bHN4KCIuL05lY2Vzc2FyeV9GaWxlcy9tdW5pX3Nob3J0bmFtZXMueGxzeCIpDQoNCiNwaW5fZGF0YTIgPC0gcmVhZF9jc3YoIi4vT3V0cHV0LzRDX2pvaW5lZF9QSU5zX2JpbGxzX2FuZF9leGVtcHRpb25zLmNzdiIpDQoNCm11bmlfdGF4cmF0ZXMgPC0gcmVhZF9jc3YoIi4vT3V0cHV0LzRDX211bmlfdGF4cmF0ZXMuY3N2IikNCg0KI3Bpbl9kYXRhMiA8LSBwaW5fZGF0YTIgJT4lIGxlZnRfam9pbihjbGFzc19kaWN0KQ0KDQptdW5pX1RDX2Z1bGx5Q29vayA8LSBtdW5pX3RheF9jb2RlcyAlPiUNCiAgZmlsdGVyKCFhZ2VuY3lfbnVtICVpbiUgY3Jvc3NfY291bnR5X2xpbmVzKQ0KDQoNCmpvaW5lZF9waW5zIDwtIHJlYWRfY3N2KCIuL091dHB1dC80Q19qb2luZWRfUElOc19iaWxsc19hbmRfZXhlbXB0aW9ucy5jc3YiKSAlPiUNCiAgbXV0YXRlKHRheF9jb2RlX251bSA9IGFzLmNoYXJhY3Rlcih0YXhfY29kZV9udW0pKSAlPiUgIA0KICBsZWZ0X2pvaW4odGNfbXVuaW5hbWVzKSAlPiUgbGVmdF9qb2luKGNsYXNzX2RpY3QpDQoNCiMgYWxsIHBpbnMgaW4gbXVuaXMgZnVsbHkgd2l0aGluIGNvb2sgY291bnR5IHRoYXQgYXJlIHNvbWUgZm9ybSBvZiBzaW5nbGUtZmFtaWx5LCBkZXRhY2hlZCBob21lDQpzaW5nZmFtX3BpbnMgPC0gam9pbmVkX3BpbnMgJT4lIA0KICBmaWx0ZXIodGF4X2NvZGUgJWluJSBtdW5pX1RDX2Z1bGx5Q29vayR0YXhfY29kZV9udW0pICU+JSAjIGV4Y2x1ZGVzIGNvdW50eSBsaW5lIGNyb3NzaW5nIG11bmlzDQogIGZpbHRlcihPcHRpb24yID09ICJTaW5nbGUtRmFtaWx5IikNCmBgYA0KDQojIyBDb29rIENvdW50eSBRdWFydGlsZXMNCg0KQ29vayBDb3VudHkgcXVhcnRpbGVzIGFyZSBjYWxjdWxhdGVkIGZyb21nIHNpbmdsZSBmYW1pbHkgcHJvcGVydGllcyBhc3Nlc3NlZCB2YWx1ZSBpbiAyMDIxLiANCg0KDQpgYGB7cn0NCnEgPSBjKC4yNSwgLjUsIC43NSkNCg0KDQpjb29rX3F1YXJ0aWxlcyA8LSBzaW5nZmFtX3BpbnMgJT4lDQogIGZpbHRlcihPcHRpb24yID09ICJTaW5nbGUtRmFtaWx5IikgJT4lDQogIGZpbHRlcih0YXhfY29kZSAlaW4lIG11bmlfVENfZnVsbHlDb29rJHRheF9jb2RlX251bSkgJT4lICMgZXhjbHVkZXMgY291bnR5IGxpbmUgY3Jvc3NpbmcgbXVuaXMNCiAgYXJyYW5nZShhdikgJT4lDQogIHN1bW1hcml6ZShjb3VudF9waW5zID0gbigpLCANCiAgICAgICAgICAgIG1pbiA9IG1pbihhdiksDQogICAgICAgICAgICBxdWFudDI1ID0gcm91bmQocXVhbnRpbGUoYXYsIHByb2JzID0gcVsxXSkpLCANCiAgICAgICAgICAgIHF1YW50NTAgPSByb3VuZChxdWFudGlsZShhdiwgcHJvYnMgPSBxWzJdKSksDQogICAgICAgICAgICBxdWFudDc1ID0gcm91bmQocXVhbnRpbGUoYXYsIHByb2JzID0gcVszXSkpLA0KICAgICAgICAgICAgbWF4ID0gbWF4KGF2KSkNCmNvb2tfcXVhcnRpbGVzDQoNCmBgYA0KDQoNCg0KDQojIyBTY2VuYXJpb3MgJiB0YXggcmF0ZXMNCg0KU2ltaWxhciB0byBGaWxlIDVfRXhlbXB0aW9uX1NjZW5hcmlvcy5ybWQuIA0KDQotIENhbGN1bGF0ZSBDbGFzcyAyIEJ1cmRlbiAtLT4gQ2FsY3VsYXRlIHRoZSBhbW91bnQgb2YgdGF4YWJsZSBFQVYgaW4gdGhlIE11bmljaXBhbGl0eSAoZm9yIGVhY2ggc2NlbmFyaW8pIGFuZCBtdWx0aXBseSBpdCBieSB0aGUgbmV3IGNvbXBvc2l0ZSB0YXggcmF0ZSAoZm9yIGVhY2ggc2NlbmFyaW8pLiAgIA0KDQoNCi0gQnVyZGVuIFNoYXJlICA9IFRheGFibGUgRUFWIHdpdGhpbiBQcm9wZXJ0eSBDbGFzcyAqIENvbXBvc2l0ZSB0YXggcmF0ZSAgIA0KDQotIENvbXBvc2l0ZSBUYXggUmF0ZSA9IChNdW5pY2lwYWwgTGV2eSAvIFRheGFibGUgRUFWICkgICAgDQoNCg0KYGBge3J9DQojIyBCcmluZyBpbiB0YXggYmlsbHMgYW5kIGV4ZW1wdGlvbiBkYXRhIGZvciAyMDIxIFBJTnMgIyMNCiMgDQojIGpvaW5lZF9waW5zIDwtIHJlYWRfY3N2KCIuL091dHB1dC80Q19qb2luZWRfUElOc19iaWxsc19hbmRfZXhlbXB0aW9ucy5jc3YiKSAlPiUNCiMgICBtdXRhdGUodGF4X2NvZGVfbnVtID0gYXMuY2hhcmFjdGVyKHRheF9jb2RlX251bSkpICU+JSAgDQojICAgbGVmdF9qb2luKHRjX211bmluYW1lcykgJT4lIGxlZnRfam9pbihjbGFzc19kaWN0KQ0KDQpNdW5pTGV2eSA8LSBqb2luZWRfcGlucyAlPiUgDQogIGdyb3VwX2J5KGNsZWFuX25hbWUsIGFnZW5jeV9udW0pICU+JQ0KICANCiAgc3VtbWFyaXplKE11bmlMZXZ5ID0gc3VtKGZpbmFsX3RheF90b19kaXN0LCBuYS5ybSA9IFRSVUUpLCAjIGFtb3VudCBiaWxsZWQgYnkgbXVuaXMgd2l0aCBjdXJyZW50IGV4ZW1wdGlvbnMgaW4gcGxhY2UNCiAgICAgICAgICAgIGN1cnJlbnRfbm9uVElGX0VBVl9wb3N0X2V4ZW1wcyA9IHN1bShmaW5hbF90YXhfdG9fZGlzdC8odGF4X2NvZGVfcmF0ZS8xMDApLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgY3VycmVudF9USUZfaW5jcmVtZW50X0VBViA9IHN1bShmaW5hbF90YXhfdG9fdGlmLyh0YXhfY29kZV9yYXRlLzEwMCksIG5hLnJtPVRSVUUpLCAgDQogICAgICAgICAgICBjdXJyZW50X0V4ZW1wdF9FQVYgPSBzdW0odGF4X2FtdF9leGUvKHRheF9jb2RlX3JhdGUvMTAwKSwgbmEucm09VFJVRSksIA0KICAgICAgICAgICAgVG90YWxfRUFWID0gc3VtKCh0YXhfYW10X2V4ZStmaW5hbF90YXhfdG9fZGlzdCtmaW5hbF90YXhfdG9fdGlmKS8odGF4X2NvZGVfcmF0ZS8xMDApLCBuYS5ybSA9IFRSVUUpKSAlPiUgDQogIG11dGF0ZShjdXJfbXVuaV9jb21wX3JhdGUgPSBNdW5pTGV2eSAvIGN1cnJlbnRfbm9uVElGX0VBVl9wb3N0X2V4ZW1wcykNCg0KTXVuaUxldnkNCmBgYA0KDQpgYGB7cn0NCmpvaW5lZF9waW5zIDwtIGpvaW5lZF9waW5zICU+JSANCiAgbXV0YXRlKGV4ZV9uZWcxMCA9IDAsDQogICAgICAgICBleGVfMCA9IGlmZWxzZShlYXYgPCAxMDAwMCAmIGV4ZV9ob21lb3duZXIhPTAsIGVhdiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShlYXY+MTAwMDAgJiBleGVfaG9tZW93bmVyIT0wLCAxMDAwMCwgMCApKSwgICN3b3VsZCBiZSBpZiB0aGVyZSBpcyBubyBjaGFuZ2UgaW4gZXhlbXB0aW9ucw0KICAgICAgICAgZXhlX3BsdXMxMCA9IGlmZWxzZShlYXYgPCAyMDAwMCAmIGV4ZV9ob21lb3duZXIhPTAsIGVhdiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShlYXY+MjAwMDAgJiBleGVfaG9tZW93bmVyIT0wLCAyMDAwMCwgMCApKSwNCiAgICAgICAgIGV4ZV9wbHVzMjAgPSBpZmVsc2UoZWF2IDwgMzAwMDAgJiBleGVfaG9tZW93bmVyIT0wLCBlYXYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZWF2PjMwMDAwICYgZXhlX2hvbWVvd25lciE9MCwgMzAwMDAsIDAgKSApLA0KICAgICAgICAgZXhlX3BsdXMzMCA9IGlmZWxzZShlYXYgPCA0MDAwMCAmIGV4ZV9ob21lb3duZXIhPTAsIGVhdiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShlYXY+NDAwMDAgJiBleGVfaG9tZW93bmVyIT0wLCA0MDAwMCwgMCkgKSwNCiAgICAgICAgIGV4ZV9wbHVzNDAgPSBpZmVsc2UoZWF2IDwgNTAwMDAgJiBleGVfaG9tZW93bmVyIT0wLCBlYXYsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZWF2PjUwMDAwICYgZXhlX2hvbWVvd25lciE9MCwgNTAwMDAsIDApICkgKQ0KDQpzY2VuYXJpb19jYWxjcyA8LSBqb2luZWRfcGlucyAlPiUgICAgDQogIGdyb3VwX2J5KGNsZWFuX25hbWUpICU+JQ0KDQogICAgc3VtbWFyaXplKE11bmlMZXZ5ID0gc3VtKGZpbmFsX3RheF90b19kaXN0LCBuYS5ybSA9IFRSVUUpLCAjIGFtb3VudCBiaWxsZWQgYnkgbXVuaXMgd2l0aCBjdXJyZW50IGV4ZW1wdGlvbnMgaW4gcGxhY2UNCiAgICAgICAgICAgIGN1cnJlbnRfbm9uVElGX0VBVl9wb3N0X2V4ZW1wcyA9IHN1bShmaW5hbF90YXhfdG9fZGlzdC8odGF4X2NvZGVfcmF0ZS8xMDApLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgY3VycmVudF9USUZfaW5jcmVtZW50X0VBViA9IHN1bShmaW5hbF90YXhfdG9fdGlmLyh0YXhfY29kZV9yYXRlLzEwMCksIG5hLnJtPVRSVUUpLCAgDQogICAgICAgICAgICBjdXJyZW50X0V4ZW1wdF9FQVYgPSBzdW0odGF4X2FtdF9leGUvKHRheF9jb2RlX3JhdGUvMTAwKSwgbmEucm09VFJVRSksIA0KICAgICAgICAgICAgY3VycmVudF9HSEUgPSBzdW0oZXhlX2hvbWVvd25lciwgbmEucm09VFJVRSksDQogICAgICAgICAgICBUb3RhbF9FQVYgPSBzdW0oKHRheF9hbXRfZXhlK2ZpbmFsX3RheF90b19kaXN0K2ZpbmFsX3RheF90b190aWYpLyh0YXhfY29kZV9yYXRlLzEwMCksIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBleGVfbmVnMTAgPSBzdW0oZXhlX25lZzEwKSwNCiAgICAgICAgICAgIGV4ZV8wID0gc3VtKGV4ZV8wKSwgIyBubyBjaGFuZ2UsIGZvciBjb21wYXJpc29uDQogICAgICAgICAgICBleGVfcGx1czEwID0gc3VtKGV4ZV9wbHVzMTApLA0KICAgICAgICAgICAgZXhlX3BsdXMyMCA9IHN1bShleGVfcGx1czIwKSwNCiAgICAgICAgICAgIGV4ZV9wbHVzMzAgPSBzdW0oZXhlX3BsdXMzMCksDQogICAgICAgICAgICBleGVfcGx1czQwID0gc3VtKGV4ZV9wbHVzNDApKSAlPiUNCg0KICAjIHJlbW92ZSBhbGwgR0hFICh1cCB0byAxMCwwMDAgRUFWIGFkZGVkIGJhY2sgdG8gYmFzZSBwZXIgUElOKSwgDQogICMgYWRkIGV4ZV9ob21lb3duZXIgYmFjayB0byB0YXhhYmxlIGJhc2UNCiAgbXV0YXRlKG5lZzEwX3RheGFibGVfZWF2ID0gVG90YWxfRUFWIC0gY3VycmVudF9USUZfaW5jcmVtZW50X0VBViAtIGN1cnJlbnRfRXhlbXB0X0VBViArIGN1cnJlbnRfR0hFLCAgICAjIGFkZHMgR0hFIGV4ZW1wdCBFQVYgYmFjayB0byB0YXhhYmxlIGJhc2UgYW5kIGRlY3JlYXNlcyB0YXggcmF0ZXMNCiAgICAgICAgIHBsdXMxMF90YXhhYmxlX2VhdiA9IFRvdGFsX0VBViAtIGN1cnJlbnRfVElGX2luY3JlbWVudF9FQVYgLSBjdXJyZW50X0V4ZW1wdF9FQVYgKyBjdXJyZW50X0dIRSAtIGV4ZV9wbHVzMTAsICMgd2lsbCBpbmNyZWFzZSB0YXggcmF0ZXMNCiAgICAgICAgIHBsdXMyMF90YXhhYmxlX2VhdiA9IFRvdGFsX0VBViAtIGN1cnJlbnRfVElGX2luY3JlbWVudF9FQVYgLSBjdXJyZW50X0V4ZW1wdF9FQVYgKyBjdXJyZW50X0dIRSAtIGV4ZV9wbHVzMjAsDQogICAgICAgICBwbHVzMzBfdGF4YWJsZV9lYXYgPSBUb3RhbF9FQVYgLSBjdXJyZW50X1RJRl9pbmNyZW1lbnRfRUFWIC0gY3VycmVudF9FeGVtcHRfRUFWICsgY3VycmVudF9HSEUgLSBleGVfcGx1czMwLA0KICAgICAgICAgcGx1czQwX3RheGFibGVfZWF2ID0gVG90YWxfRUFWIC0gY3VycmVudF9USUZfaW5jcmVtZW50X0VBViAtIGN1cnJlbnRfRXhlbXB0X0VBViArIGN1cnJlbnRfR0hFIC0gZXhlX3BsdXM0MCwNCiAgICAgICAgIHNjZW5hcmlvX25vZXhlbXB0aW9uc190YXhhYmxlX2VhdiA9IFRvdGFsX0VBViAtIGN1cnJlbnRfVElGX2luY3JlbWVudF9FQVYpICU+JQ0KICANCiAgbXV0YXRlKHRyX25lZzEwID0gTXVuaUxldnkgLyBuZWcxMF90YXhhYmxlX2VhdiwNCiAgICAgICAgIHRyX25vY2hhbmdlID0gTXVuaUxldnkgLyBjdXJyZW50X25vblRJRl9FQVZfcG9zdF9leGVtcHMsDQogICAgICAgICB0cl9wbHVzMTAgPSBNdW5pTGV2eSAvIHBsdXMxMF90YXhhYmxlX2VhdiwNCiAgICAgICAgIHRyX3BsdXMyMCA9IE11bmlMZXZ5IC8gcGx1czIwX3RheGFibGVfZWF2LA0KICAgICAgICAgdHJfcGx1czMwID0gTXVuaUxldnkgLyBwbHVzMzBfdGF4YWJsZV9lYXYsDQogICAgICAgICB0cl9wbHVzNDAgPSBNdW5pTGV2eSAvIHBsdXM0MF90YXhhYmxlX2VhdiwgDQogICAgICAgICB0YXhfcmF0ZV9jdXJyZW50ID0gTXVuaUxldnkvY3VycmVudF9ub25USUZfRUFWX3Bvc3RfZXhlbXBzLA0KICAgICAgICAgdGF4cmF0ZV9ub2V4ZW1wcyA9IE11bmlMZXZ5IC8oVG90YWxfRUFWIC0gY3VycmVudF9USUZfaW5jcmVtZW50X0VBViAgKSwNCiAgICAgICAgIHRheHJhdGVfbm9USUZzID0gTXVuaUxldnkgLyAoVG90YWxfRUFWIC0gY3VycmVudF9FeGVtcHRfRUFWKSwNCiAgICAgICAgIHRheHJhdGVfbm9USUZzX29yRXhlbXBzID0gTXVuaUxldnkgLyBUb3RhbF9FQVYpICU+JQ0KICBzZWxlY3QoY2xlYW5fbmFtZSwgTXVuaUxldnksIHRyX25lZzEwOnRheHJhdGVfbm9USUZzX29yRXhlbXBzLCBldmVyeXRoaW5nKCkpDQoNCndyaXRlX2NzdihzY2VuYXJpb19jYWxjcywgIjViX3NjZW5hcmlvX2NhbGNzLmNzdiIpDQoNCg0Kc2NlbmFyaW9fdGF4cmF0ZXMgPC0gc2NlbmFyaW9fY2FsY3MgJT4lICBzZWxlY3QoY2xlYW5fbmFtZSwgTXVuaUxldnksIHRyX25lZzEwOnRheHJhdGVfbm9USUZzX29yRXhlbXBzKSANCg0Kc2NlbmFyaW9fdGF4cmF0ZXMNCg0KYGBgDQoNCiMjIENsYXNzIDIgQnVyZGVuIFNoaWZ0DQoNCmBgYHtyfQ0KDQpDMl90YXhhYmxlRUFWIDwtIGpvaW5lZF9waW5zICU+JSAgIA0KICBmaWx0ZXIoY2xhc3MgPj0gMjAwICYgY2xhc3MgPD0gMzAwKSAlPiUgDQogICNsZWZ0X2pvaW4oc2NlbmFyaW9fdGF4cmF0ZXMsIGJ5ID0gYygidGF4X2NvZGUiID0gInRheF9jb2RlX251bSIpKSAlPiUNCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSkgJT4lDQoNCiAgICBzdW1tYXJpemUoDQogICAgICBDMl9hdiA9IHN1bShhdiksDQogICAgICBDMl9lYXZfb3JpZ2luYWwgPSBzdW0oZXF1YWxpemVkX0FWKSwgDQogICAgICBDMl9EaXN0cmljdFJldiA9IHN1bShmaW5hbF90YXhfdG9fZGlzdCwgbmEucm09VFJVRSksDQogICAgICBDMl9jdXJyZW50X25vblRJRl9FQVZfcG9zdF9leGVtcHMgPSBzdW0oZmluYWxfdGF4X3RvX2Rpc3QvKHRheF9jb2RlX3JhdGUvMTAwKSwgbmEucm0gPSBUUlVFKSwNCiAgICAgIEMyX2N1cnJlbnRfVElGX2luY3JlbWVudF9FQVYgPSBzdW0oZmluYWxfdGF4X3RvX3RpZi8odGF4X2NvZGVfcmF0ZS8xMDApLCBuYS5ybT1UUlVFKSwgIA0KICAgICAgQzJfY3VycmVudF9FeGVtcHRfRUFWID0gc3VtKHRheF9hbXRfZXhlLyh0YXhfY29kZV9yYXRlLzEwMCksIG5hLnJtPVRSVUUpLCANCiAgICAgIEMyX2N1cnJlbnRfR0hFID0gc3VtKGV4ZV9ob21lb3duZXIsIG5hLnJtPVRSVUUpLA0KICAgICAgQzJfVG90YWxfRUFWID0gc3VtKCh0YXhfYW10X2V4ZStmaW5hbF90YXhfdG9fZGlzdCtmaW5hbF90YXhfdG9fdGlmKS8odGF4X2NvZGVfcmF0ZS8xMDApLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgQzJfZXhlX25lZzEwID0gc3VtKGV4ZV9uZWcxMCksDQogICAgICBDMl9leGVfMCA9IHN1bShleGVfMCksICMgbm8gY2hhbmdlLCBmb3IgY29tcGFyaXNvbg0KICAgICAgQzJfZXhlX3BsdXMxMCA9IHN1bShleGVfcGx1czEwKSwNCiAgICAgIEMyX2V4ZV9wbHVzMjAgPSBzdW0oZXhlX3BsdXMyMCksDQogICAgICBDMl9leGVfcGx1czMwID0gc3VtKGV4ZV9wbHVzMzApLA0KICAgICAgQzJfZXhlX3BsdXM0MCA9IHN1bShleGVfcGx1czQwKSwNCiAgICAgIEMyX1BDX3Blcm11bmkgPSBuKCkpICAlPiUgDQogIGxlZnRfam9pbihNdW5pTGV2eSwgYnkgPSAiY2xlYW5fbmFtZSIpICU+JQ0KICBtdXRhdGUoQzJfRUFWX3BjdCA9IEMyX2Vhdl9vcmlnaW5hbCAvIFRvdGFsX0VBVikNCg0KDQoNCkMyX2J1cmRlbl9zaGlmdCA8LSBDMl90YXhhYmxlRUFWICU+JQ0KICBsZWZ0X2pvaW4oc2NlbmFyaW9fdGF4cmF0ZXMpICU+JQ0KICBtdXRhdGUoQzJfbmVnMTBfdGF4YWJsZUVBViA9IEMyX1RvdGFsX0VBViAtIEMyX2N1cnJlbnRfVElGX2luY3JlbWVudF9FQVYgLSBDMl9jdXJyZW50X0V4ZW1wdF9FQVYgKyBDMl9jdXJyZW50X0dIRSAtIEMyX2V4ZV9uZWcxMCwNCiAgICAgICAgIEMyX25vY2hhbmdlID0gQzJfVG90YWxfRUFWIC0gQzJfY3VycmVudF9USUZfaW5jcmVtZW50X0VBViAtIEMyX2N1cnJlbnRfRXhlbXB0X0VBViwNCiAgICAgICAgIEMyX3BsdXMxMF90YXhhYmxlRUFWID0gQzJfVG90YWxfRUFWIC0gQzJfY3VycmVudF9USUZfaW5jcmVtZW50X0VBViAtIEMyX2N1cnJlbnRfRXhlbXB0X0VBViArIEMyX2N1cnJlbnRfR0hFIC0gQzJfZXhlX3BsdXMxMCwNCiAgICAgICAgIEMyX3BsdXMyMF90YXhhYmxlRUFWID0gQzJfVG90YWxfRUFWIC0gQzJfY3VycmVudF9USUZfaW5jcmVtZW50X0VBViAtIEMyX2N1cnJlbnRfRXhlbXB0X0VBViArIEMyX2N1cnJlbnRfR0hFIC0gQzJfZXhlX3BsdXMyMCwNCiAgICAgICAgQzJfcGx1czMwX3RheGFibGVFQVYgPSBDMl9Ub3RhbF9FQVYgLSBDMl9jdXJyZW50X1RJRl9pbmNyZW1lbnRfRUFWIC0gQzJfY3VycmVudF9FeGVtcHRfRUFWICsgQzJfY3VycmVudF9HSEUgLSBDMl9leGVfcGx1czMwLA0KICAgICAgICBDMl9wbHVzNDBfdGF4YWJsZUVBViA9IEMyX1RvdGFsX0VBViAtIEMyX2N1cnJlbnRfVElGX2luY3JlbWVudF9FQVYgLSBDMl9jdXJyZW50X0V4ZW1wdF9FQVYgKyBDMl9jdXJyZW50X0dIRSAtIEMyX2V4ZV9wbHVzNDANCiAgICAgICAgICkgJT4lDQogIG11dGF0ZShidXJkZW5fQzJfbmVnMTAgPSAoQzJfbmVnMTBfdGF4YWJsZUVBViAqIHRyX25lZzEwKS8gTXVuaUxldnksDQogICAgICAgICBidXJkZW5fQzJfbm9jaGFuZ2UgPSBDMl9ub2NoYW5nZSAqIHRheF9yYXRlX2N1cnJlbnQgIC8gTXVuaUxldnksDQogICAgICAgICBidXJkZW5fQzJfcGx1czEwID0gKEMyX3BsdXMxMF90YXhhYmxlRUFWICogdHJfcGx1czEwKSAvIE11bmlMZXZ5LA0KICAgICAgICAgYnVyZGVuX0MyX3BsdXMyMCA9IEMyX3BsdXMyMF90YXhhYmxlRUFWICogdHJfcGx1czIwLyBNdW5pTGV2eSwNCiAgICAgICAgIGJ1cmRlbl9DMl9wbHVzMzAgPSBDMl9wbHVzMzBfdGF4YWJsZUVBViAqIHRyX3BsdXMzMC8gTXVuaUxldnksDQogICAgICAgICBidXJkZW5fQzJfcGx1czQwID0gQzJfcGx1czQwX3RheGFibGVFQVYgKiB0cl9wbHVzNDAvIE11bmlMZXZ5LA0KICAgICAgICAgDQogICAgICAgIGJ1cmRlbl9DMl9ub2V4ZW1wcyA9ICggKEMyX1RvdGFsX0VBViAtIEMyX2N1cnJlbnRfVElGX2luY3JlbWVudF9FQVYpKnRheHJhdGVfbm9leGVtcHMgKSAvIE11bmlMZXZ5KSAlPiUNCiAgc2VsZWN0KGNsZWFuX25hbWUsIEMyX0VBVl9wY3QsIGJ1cmRlbl9DMl9uZWcxMDpidXJkZW5fQzJfcGx1czQwLCBldmVyeXRoaW5nKCkpDQoNCkMyX2J1cmRlbl9zaGlmdA0KDQp3cml0ZV9jc3YoQzJfYnVyZGVuX3NoaWZ0LCAiNWJfQ2xhc3MyX2J1cmRlbnNoaWZ0LmNzdiIpDQpgYGANCg0KDQojIyMjIFNjZW5hcmlvIFRheCByYXRlIGdyYXBocyANCg0KYGBge3J9DQpzY2VuYXJpb3NfbG9uZyA8LSBzY2VuYXJpb190YXhyYXRlcyAgJT4lIA0KICBzZWxlY3QoY2xlYW5fbmFtZSwgTXVuaUxldnksIHRyX25lZzEwOnRheHJhdGVfbm9USUZzX29yRXhlbXBzKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKHRyX25lZzEwOnRheHJhdGVfbm9USUZzX29yRXhlbXBzKSwgbmFtZXNfdG8gPSAiR0hFX0Ftb3VudCIpDQoNCg0Kc2NlbmFyaW9fdGF4cmF0ZXMgJT4lIA0KICBzZWxlY3QoY2xlYW5fbmFtZSwgTXVuaUxldnksIHRyX25lZzEwOnRheHJhdGVfbm9USUZzX29yRXhlbXBzKSAlPiUNCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKHRyX25lZzEwOnRheHJhdGVfbm9USUZzX29yRXhlbXBzKSwgbmFtZXNfdG8gPSAiR0hFX0Ftb3VudCIpICU+JQ0KICBnZ3Bsb3QoKSArIA0KICBnZW9tX2NvbChhZXMoeD12YWx1ZSwgeSA9IEdIRV9BbW91bnQpKQ0KDQpzY2VuYXJpb190YXhyYXRlcyAlPiUgDQogIGZpbHRlcihjbGVhbl9uYW1lICVpbiUgYygiQ2hpY2FnbyIsICJEb2x0b24iLCAiR2xlbmNvZSIpKSAlPiUNCiAgc2VsZWN0KGNsZWFuX25hbWUsIE11bmlMZXZ5LCB0cl9uZWcxMDp0YXhyYXRlX25vVElGc19vckV4ZW1wcykgJT4lDQogIHBpdm90X2xvbmdlcihjb2xzID0gYyh0cl9uZWcxMDp0YXhyYXRlX25vVElGc19vckV4ZW1wcyksIG5hbWVzX3RvID0gIkdIRV9BbW91bnQiKSAlPiUNCiAgZ2dwbG90KCkgKyANCiAgZ2VvbV9jb2woYWVzKHg9dmFsdWUsIHkgPSBHSEVfQW1vdW50LCBmaWxsID0gY2xlYW5fbmFtZSksIHBvc2l0aW9uID0gImRvZGdlIikgICsgDQogIGxhYnMoeCA9ICJNdW5pY2lwYWxpdHkgQ29tcG9zaXRlIFRheCBSYXRlIiwgeSA9ICJFeGVtcHRpb24gU2NlbmFyaW9zIikNCmBgYA0KDQoNCiMgUmFua2VkIFByb3BlcnRpZXMgYW5kIE11bmkgUXVhcnRpbGVzDQoNCiMjIDI1IHYgNzUgUGVyY2VudGlsZSBIb21lcw0KDQpgYGB7cn0NCnEgPSBjKC4yNSwgLjUsIC43NSkNCg0KIyMgcmFua3MgcHJvcGVydGllcyB0aGF0IGFyZSBjb25zaWRlcmVkIHNpbmdsZSBmYW1pbHkgaG9tZXMgaW4gb3JkZXIgb2YgQVYgZm9yIGVhY2ggTXVuaQ0KbXVuaV9xdWFydGlsZXMgPC0gam9pbmVkX3BpbnMgJT4lDQogIGZpbHRlcihPcHRpb24yID09ICJTaW5nbGUtRmFtaWx5IikgJT4lIA0KICBmaWx0ZXIodGF4X2NvZGUgJWluJSBtdW5pX1RDX2Z1bGx5Q29vayR0YXhfY29kZV9udW0pICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSwgY2xlYW5fbmFtZSkgJT4lDQogIGFycmFuZ2UoYXYpICU+JQ0KICBzdW1tYXJpemUoY291bnRfcGlucyA9IG4oKSwgDQogICAgICAgICAgICBtaW4gPSBtaW4oYXYpLA0KICAgICAgICAgICAgcXVhbnQyNSA9IHJvdW5kKHF1YW50aWxlKGF2LCBwcm9icyA9IHFbMV0pKSwgDQogICAgICAgICAgICBxdWFudDUwID0gcm91bmQocXVhbnRpbGUoYXYsIHByb2JzID0gcVsyXSkpLA0KICAgICAgICAgICAgcXVhbnQ3NSA9IHJvdW5kKHF1YW50aWxlKGF2LCBwcm9icyA9IHFbM10pKSwNCiAgICAgICAgICAgIG1heCA9IG1heChhdikNCiAgICAgICAgICAgKSAlPiUgDQogIGFycmFuZ2UoIGRlc2MoIHF1YW50NTApKQ0KbXVuaV9xdWFydGlsZXMNCmBgYA0KDQoNCmBgYHtyfQ0KIyMgY3JlYXRlIHJhbmsgdmFyaWFibGUgZm9yIHByb3BlcnRpZXMgdGhhdCBmYWxsIHdpdGhpbiB0aGUgcXVhcnRpbGVzICsvLSAkNTAwIHJhbmdlDQptdW5pc19yYW5rZWQgPC0gam9pbmVkX3BpbnMgICU+JQ0KICBpbm5lcl9qb2luKG11bmlfcXVhcnRpbGVzLCBieSA9IGMoImFnZW5jeV9uYW1lIiwgImNsZWFuX25hbWUiKSkgJT4lIA0KICBtdXRhdGUocmFuayA9IGNhc2Vfd2hlbigNCiAgICBhdiA+IChxdWFudDI1LTUwMCkgJiAoYXY8cXVhbnQyNSs1MDApIH4gInEyNSIsDQogICAgYXYgPiAocXVhbnQ1MC01MDApICYgKGF2PHF1YW50NTArNTAwKSB+ICJxNTAiLA0KICAgIGF2ID4gKHF1YW50NzUtNTAwKSAmIChhdjxxdWFudDc1KzUwMCkgfiAicTc1IikNCiAgICApICU+JQ0KICBzZWxlY3QoY2xlYW5fbmFtZSwgcmFuaywgYXYsIHBpbiwgY2xhc3MsIGV2ZXJ5dGhpbmcoKSkgJT4lDQogIGxlZnRfam9pbihuaWNrbmFtZXMpDQoNCg0KDQoNCm11bmlzX2JpbGxjaGFuZ2UgPC0gIG11bmlzX3JhbmtlZCAlPiUgDQogIGdyb3VwX2J5KGNsZWFuX25hbWUsIHJhbmspICU+JQ0KICBsZWZ0X2pvaW4oc2NlbmFyaW9fdGF4cmF0ZXMpICU+JQ0KICBhcnJhbmdlKGF2KSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgDQogICAgDQogICAjICMjIE1hZGUgbmVnYXRpdmUgdGF4IGJpbGxzISEgIyMgIw0KICAgICAgICAgDQogICAgICAgICBiaWxsX25lZzEwID0gdHJfbmVnMTAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX25lZzEwKSwNCg0KICAgICAgICAgYmlsbF9jdXJyZW50ID0gY3VyX2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucyksDQogICAgICAgICBiaWxsX3BsdXMxMCA9ICB0cl9wbHVzMTAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX3BsdXMxMCksDQogICAgICAgICBiaWxsX3BsdXMyMCA9IHRyX3BsdXMyMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zKyBleGVfaG9tZW93bmVyIC1leGVfcGx1czIwKSwNCiAgICAgICAgIGJpbGxfcGx1czMwID0gdHJfcGx1czIwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrIGV4ZV9ob21lb3duZXIgLWV4ZV9wbHVzMzApLA0KICAgICAgICAgYmlsbF9wbHVzNDAgPSB0cl9wbHVzMjAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX3BsdXM0MCksDQogICAgDQogICAgIyAjIyBtYWtlIGJpbGxzICQxIGlmIHRoZXkgaGFkIGJlZW4gbmVnYXRpdmUuICAgIA0KICAgICAgICAgYmlsbF9uZWcxMCA9IGlmZWxzZShiaWxsX25lZzEwIDwgMSwgMSwgYmlsbF9uZWcxMCksDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSBpZmVsc2UoYmlsbF9jdXJyZW50IDwgMSwgMSwgYmlsbF9jdXJyZW50KSwNCiAgICAgICAgIGJpbGxfcGx1czEwID0gaWZlbHNlKGJpbGxfcGx1czEwIDwgMSwgMSwgYmlsbF9wbHVzMTApLA0KICAgICAgICAgYmlsbF9wbHVzMjAgPSBpZmVsc2UoYmlsbF9wbHVzMjAgPCAxLCAxLCBiaWxsX3BsdXMyMCksDQogICAgICAgICBiaWxsX3BsdXMzMCA9IGlmZWxzZShiaWxsX3BsdXMzMCA8IDEsIDEsIGJpbGxfcGx1czMwKSwNCiAgICAgICAgIGJpbGxfcGx1czQwID0gaWZlbHNlKGJpbGxfcGx1czQwIDwgMSwgMSwgYmlsbF9wbHVzNDApLA0KICAgICAgICAgDQojIyBQcmV2ZW50IHRheCBiaWxscyBmcm9tIGhhdmluZyBuZWdhdGl2ZSB2YWx1ZXMgIChpZiBleGVtcHRpb25zID4gZWF2IG9mIGhvbWUpDQogICAgICAgICAjIGJpbGxfbmVnMTAgPSBpZmVsc2UodHJfbmVnMTAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX25lZzEwKSA+IDEsDQogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJfbmVnMTAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX25lZzEwKSwgMSksDQogICAgICAgICAjIA0KICAgICAgICAgIyBiaWxsX2N1cnJlbnQgPSBpZmVsc2UoY3VyX2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucykgPiAxLA0KICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgY3VyX2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucyksIDEpLA0KICAgICAgICAgIyANCiAgICAgICAgICMgYmlsbF9wbHVzMTAgPSAgaWZlbHNlKHRyX3BsdXMxMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zKyBleGVfaG9tZW93bmVyIC1leGVfcGx1czEwKSA+IDEsDQogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgICB0cl9wbHVzMTAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX3BsdXMxMCksMSksDQogICAgICAgICAjIA0KICAgICAgICAgIyBiaWxsX3BsdXMyMCA9IGlmZWxzZSh0cl9wbHVzMjAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX3BsdXMyMCkgPiAxLA0KICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICB0cl9wbHVzMjAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX3BsdXMyMCksIDEpLA0KICAgICAgICAgIyANCiAgICAgICAgICMgYmlsbF9wbHVzMzAgPSBpZmVsc2UodHJfcGx1czMwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrIGV4ZV9ob21lb3duZXIgLWV4ZV9wbHVzMzApID4xLCANCiAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgdHJfcGx1czMwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrIGV4ZV9ob21lb3duZXIgLWV4ZV9wbHVzMzApLCAxKSwNCiAgICAgICAgICMgICAgICAgICAgICAgICAgICAgICAgDQogICAgICAgICAjICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgIyBiaWxsX3BsdXM0MCA9IGlmZWxzZSh0cl9wbHVzNDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX3BsdXM0MCkgPiAxLA0KICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICB0cl9wbHVzNDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX3BsdXM0MCksIDEpDQogICAgICAgICApJT4lDQogIG11dGF0ZSgNCiAgICAgICAgIHplcm9kb2xfYmlsbHNfZ2hlMCA9IGlmZWxzZShiaWxsX25lZzEwIDwgNSwgMSwgMCksDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2N1cnJlbnQgPSBpZmVsc2UoYmlsbF9jdXJyZW50IDwgNSwgMSwgMCksDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTIwID0gaWZlbHNlKGJpbGxfcGx1czEwIDwgNSwgMSwgMCksDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTMwID0gaWZlbHNlKGJpbGxfcGx1czIwIDwgNSwgMSwgMCksDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTQwID0gaWZlbHNlKGJpbGxfcGx1czMwIDwgNSwgMSwgMCksDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTUwID0gaWZlbHNlKGJpbGxfcGx1czQwIDwgNSwgMSwgMCksDQogICkgJT4lDQogIGdyb3VwX2J5KGNsZWFuX25hbWUsIHJhbmssIGhhc19IT19leGVtcCkgJT4lIA0KICBzdW1tYXJpemUobWVkaWFuX0FWID0gcm91bmQobWVkaWFuKGF2KSksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gcm91bmQobWVkaWFuKGVhdikpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX25lZzEwID0gcm91bmQobWVhbihiaWxsX25lZzEwLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2JpbGxfY3VyID0gcm91bmQobWVhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIG1lYW5fYmlsbF9wbHVzMTAgPSByb3VuZChtZWFuKGJpbGxfcGx1czEwLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2JpbGxfcGx1czIwID0gcm91bmQobWVhbihiaWxsX3BsdXMyMCwgbmEucm09VFJVRSkpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX3BsdXMzMCA9IHJvdW5kKG1lYW4oYmlsbF9wbHVzMzAsIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIG1lYW5fYmlsbF9wbHVzNDAgPSByb3VuZChtZWFuKGJpbGxfcGx1czQwLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICANCiAgICAgICAgICAgICMgY3VycmVudCBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICB0cl9uZWcxMCA9IHJvdW5kKG1lYW4odHJfbmVnMTAqMTAwKSwgZGlnaXRzID0gMiksIA0KICAgICAgICAgICAgY3VyX2NvbXBfVENfcmF0ZSA9IHJvdW5kKG1lYW4oY3VyX2NvbXBfVENfcmF0ZSksIGRpZ2l0cyA9IDIpLA0KICAgICAgICAgICAgdHJfcGx1czEwID0gcm91bmQobWVhbih0cl9wbHVzMTAqMTAwKSwgZGlnaXRzID0gMiksDQogICAgICAgICAgICB0cl9wbHVzMjAgPSByb3VuZChtZWFuKHRyX3BsdXMyMCoxMDApLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIHRyX3BsdXMzMCA9IHJvdW5kKG1lYW4odHJfcGx1czMwKjEwMCksIGRpZ2l0cyA9IDIpLA0KICAgICAgICAgICAgdHJfcGx1czQwID0gcm91bmQobWVhbih0cl9wbHVzNDAqMTAwKSwgZGlnaXRzID0gMiksDQogICAgICAgICAgICBwaW5jb3VudD1uKCksDQogICAgICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTAgPSBzdW0oemVyb2RvbF9iaWxsc19naGUwKSwgICAgICAgICAgIA0KICAgICAgICAgICAgemVyb2RvbF9iaWxsc19jdXJyZW50ID0gc3VtKHplcm9kb2xfYmlsbHNfY3VycmVudCksDQogICAgICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTIwID0gc3VtKHplcm9kb2xfYmlsbHNfZ2hlMjApLA0KICAgICAgICAgICAgemVyb2RvbF9iaWxsc19naGUzMCA9IHN1bSh6ZXJvZG9sX2JpbGxzX2doZTMwKSwNCiAgICAgICAgICAgIHplcm9kb2xfYmlsbHNfZ2hlNDAgPSBzdW0oemVyb2RvbF9iaWxsc19naGU0MCksDQogICAgICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTUwID0gc3VtKHplcm9kb2xfYmlsbHNfZ2hlNTApLA0KDQoNCiAgKSAlPiUNCiAgYXJyYW5nZShoYXNfSE9fZXhlbXAsIHJhbmspDQoNCg0KbXVuaXNfYmlsbGNoYW5nZSA8LSBtdW5pc19iaWxsY2hhbmdlICU+JSBsZWZ0X2pvaW4obXVuaV9xdWFydGlsZXMpDQptdW5pc19iaWxsY2hhbmdlDQoNCndyaXRlX2NzdihtdW5pc19iaWxsY2hhbmdlLCAiNWJfbXVuaV9iaWxsY2hhbmdlX3NjZW5hcmlvcy5jc3YiKQ0KYGBgDQoNCg0KYGBge3J9DQoNCnJhdGlvczwtIG11bmlzX2JpbGxjaGFuZ2UgJT4lIA0KICBmaWx0ZXIoaGFzX0hPX2V4ZW1wID09IDEgJiAgIWlzLm5hKHJhbmspKSAlPiUgIyBjbGFpbWVkIGV4ZW1wdGlvbiBpbiAyMDIxDQogIG11dGF0ZShjdXJyYmlsbF90b19BVl8yNSA9IGlmZWxzZShyYW5rID09ICJxMjUiLCBtZWFuX2JpbGxfbmVnMTAvbWVkaWFuX0FWLCBOQSkpICU+JQ0KICBtdXRhdGUoY3VycmJpbGxfdG9fQVZfNzUgPSBpZmVsc2UocmFuayA9PSAicTc1IiwgbWVhbl9iaWxsX25lZzEwL21lZGlhbl9BViwgTkEpKSAlPiUgDQogIGdyb3VwX2J5KGNsZWFuX25hbWUpICU+JQ0KICBzdW1tYXJpemUoR0hFXzBfYmlsbF90b19BVl8yNSA9IG1heChjdXJyYmlsbF90b19BVl8yNSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBHSEVfMF9iaWxsX3RvX0FWXzc1ID0gbWF4KGN1cnJiaWxsX3RvX0FWXzc1LCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzI1dG83NSA9IEdIRV8wX2JpbGxfdG9fQVZfMjUvR0hFXzBfYmlsbF90b19BVl83NSkNCg0KDQpnZ3Bsb3QoZGF0YSA9IHJhdGlvcywgYWVzKHkgPSBHSEVfMF9iaWxsX3RvX0FWXzI1LCB4ID0gR0hFXzBfYmlsbF90b19BVl83NSwgbGFiZWwgPSBjbGVhbl9uYW1lKSkgKyANCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArDQogIGdlb21fcG9pbnQoYWVzKGFscGhhID0gLjUpKSArIA0KICBnZW9tX3RleHQobnVkZ2VfeCA9IC4wMywgbnVkZ2VfeT0wLjAxLCBzaXplID0gMywgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCg0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicyh0aXRsZSA9ICJSZWR1Y2VkIEdIRSBBbW91bnQgYnkgMTAsMDAwIEVBViAoMCBFQVYgZXhlbXB0IGZyb20gR0hFKSIsDQogICAgICAgc3VidGl0bGUgPSAiT3RoZXIgZXhlbXB0aW9ucyBzdGlsbCBpbiBwbGFjZSIpDQoNCg0KcmF0aW9zPC0gbXVuaXNfYmlsbGNoYW5nZSAlPiUgDQogIGZpbHRlcihoYXNfSE9fZXhlbXAgPT0gMSAmICAhaXMubmEocmFuaykpICU+JSAjIGNsYWltZWQgZXhlbXB0aW9uIGluIDIwMjENCiAgbXV0YXRlKGN1cnJiaWxsX3RvX0FWXzI1ID0gaWZlbHNlKHJhbmsgPT0gInEyNSIsIG1lYW5fYmlsbF9jdXIvbWVkaWFuX0FWLCBOQSkpICU+JQ0KICBtdXRhdGUoY3VycmJpbGxfdG9fQVZfNzUgPSBpZmVsc2UocmFuayA9PSAicTc1IiwgbWVhbl9iaWxsX2N1ci9tZWRpYW5fQVYsIE5BKSkgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKGN1cnJiaWxsX3RvX0FWXzI1ID0gbWF4KGN1cnJiaWxsX3RvX0FWXzI1LCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIGN1cnJiaWxsX3RvX0FWXzc1ID0gbWF4KGN1cnJiaWxsX3RvX0FWXzc1LCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzI1dG83NSA9IGN1cnJiaWxsX3RvX0FWXzI1L2N1cnJiaWxsX3RvX0FWXzc1KQ0KDQoNCmdncGxvdChkYXRhID0gcmF0aW9zLCBhZXMoeSA9IGN1cnJiaWxsX3RvX0FWXzI1LCB4ID0gY3VycmJpbGxfdG9fQVZfNzUsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDMsIG51ZGdlX3k9MC4wMSwgc2l6ZSA9IDMsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnModGl0bGUgPSAiQ3VycmVudCBHSEUgQW1vdW50ICh1cCB0byAxMCwwMDAgRUFWIGV4ZW1wdCBwZXIgcHJvcGVydHkpIikNCmBgYA0KDQpgYGB7cn0NCm5ld19yYXRpb3M8LSBtdW5pc19iaWxsY2hhbmdlICU+JSANCiAgZmlsdGVyKGhhc19IT19leGVtcCA9PSAxICYgICFpcy5uYShyYW5rKSkgJT4lICMgY2xhaW1lZCBleGVtcHRpb24gaW4gMjAyMQ0KICBtdXRhdGUobmV3YmlsbF90b19BVl8yNSA9IGlmZWxzZShyYW5rID09ICJxMjUiLCBtZWFuX2JpbGxfcGx1czEwL21lZGlhbl9BViwgTkEpKSAlPiUNCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfNzUgPSBpZmVsc2UocmFuayA9PSAicTc1IiwgbWVhbl9iaWxsX3BsdXMxMC9tZWRpYW5fQVYsIE5BKSkgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKG5ld2JpbGxfdG9fQVZfMjUgPSBtYXgobmV3YmlsbF90b19BVl8yNSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBuZXdiaWxsX3RvX0FWXzc1ID0gbWF4KG5ld2JpbGxfdG9fQVZfNzUsIG5hLnJtPVRSVUUpKSAlPiUNCiAgbXV0YXRlKG11bmlfcmF0aW9fMjV0bzc1ID0gbmV3YmlsbF90b19BVl8yNS9uZXdiaWxsX3RvX0FWXzc1KQ0KDQoNCmdncGxvdChkYXRhID0gbmV3X3JhdGlvcywgYWVzKHkgPSBuZXdiaWxsX3RvX0FWXzI1LCB4ID0gbmV3YmlsbF90b19BVl83NSwgbGFiZWwgPSBjbGVhbl9uYW1lKSkgKyANCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArDQogIGdlb21fcG9pbnQoYWVzKGFscGhhID0gLjUpKSArIA0KICBnZW9tX3RleHQobnVkZ2VfeCA9IC4wMywgbnVkZ2VfeT0wLjAxLCBzaXplID0gMywgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyBsYWJzKHRpdGxlID0gIkluY3JlYXNlIEdIRSBieSAxMCwwMDAgRUFWIChmb3IgdXAgdG8gMjAsMDAwIEVBViBleGVtcHQpICIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gIjI1dGggcGVyY2VudGlsZSBvZiBob21lcywgdGF4YmlsbDpBViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHg9ICI3NXRoIHBlcmNlbnRpbGUgb2YgaG9tZXMsIHRheGJpbGw6QVYiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gICJVc2VzIHNpbmdsZS1mYW1pbHkgcHJvcGVydGllcy4gRXhlbXB0IEVBViB1cCB0byAyMEsgcGVyIHByb3BlcnR5IikNCg0KDQpuZXdfcmF0aW9zPC0gbXVuaXNfYmlsbGNoYW5nZSAlPiUgDQogIGZpbHRlcihoYXNfSE9fZXhlbXAgPT0gMSAmICAhaXMubmEocmFuaykpICU+JSAjIGNsYWltZWQgZXhlbXB0aW9uIGluIDIwMjENCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfMjUgPSBpZmVsc2UocmFuayA9PSAicTI1IiwgbWVhbl9iaWxsX3BsdXMyMC9tZWRpYW5fQVYsIE5BKSkgJT4lDQogIG11dGF0ZShuZXdiaWxsX3RvX0FWXzc1ID0gaWZlbHNlKHJhbmsgPT0gInE3NSIsIG1lYW5fYmlsbF9wbHVzMjAvbWVkaWFuX0FWLCBOQSkpICU+JSANCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSkgJT4lDQogIHN1bW1hcml6ZShuZXdiaWxsX3RvX0FWXzI1ID0gbWF4KG5ld2JpbGxfdG9fQVZfMjUsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbmV3YmlsbF90b19BVl83NSA9IG1heChuZXdiaWxsX3RvX0FWXzc1LCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzI1dG83NSA9IG5ld2JpbGxfdG9fQVZfMjUvbmV3YmlsbF90b19BVl83NSkNCg0KDQpnZ3Bsb3QoZGF0YSA9IG5ld19yYXRpb3MsIGFlcyh5ID0gbmV3YmlsbF90b19BVl8yNSwgeCA9IG5ld2JpbGxfdG9fQVZfNzUsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDMsIG51ZGdlX3k9MC4wMSwgc2l6ZSA9IDMsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIGxhYnModGl0bGUgPSAiSW5jcmVhc2UgR0hFIGJ5IDIwLDAwMCBFQVYgKGZvciB1cCB0byAzMCwwMDAgRUFWIGV4ZW1wdCkgIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAiMjV0aCBwZXJjZW50aWxlIG9mIGhvbWVzLCB0YXhiaWxsOkFWIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeD0gIjc1dGggcGVyY2VudGlsZSBvZiBob21lcywgdGF4YmlsbDpBViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAgIlVzZXMgc2luZ2xlLWZhbWlseSBwcm9wZXJ0aWVzLiBFeGVtcHQgRUFWIHVwIHRvIDMwSyBwZXIgcHJvcGVydHkiKQ0KDQpuZXdfcmF0aW9zPC0gbXVuaXNfYmlsbGNoYW5nZSAlPiUgDQogIGZpbHRlcihoYXNfSE9fZXhlbXAgPT0gMSAmICAhaXMubmEocmFuaykpICU+JSAjIGNsYWltZWQgZXhlbXB0aW9uIGluIDIwMjENCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfMjUgPSBpZmVsc2UocmFuayA9PSAicTI1IiwgbWVhbl9iaWxsX3BsdXMzMC9tZWRpYW5fQVYsIE5BKSkgJT4lDQogIG11dGF0ZShuZXdiaWxsX3RvX0FWXzc1ID0gaWZlbHNlKHJhbmsgPT0gInE3NSIsIG1lYW5fYmlsbF9wbHVzMzAvbWVkaWFuX0FWLCBOQSkpICU+JSANCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSkgJT4lDQogIHN1bW1hcml6ZShuZXdiaWxsX3RvX0FWXzI1ID0gbWF4KG5ld2JpbGxfdG9fQVZfMjUsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbmV3YmlsbF90b19BVl83NSA9IG1heChuZXdiaWxsX3RvX0FWXzc1LCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzI1dG83NSA9IG5ld2JpbGxfdG9fQVZfMjUvbmV3YmlsbF90b19BVl83NSkNCg0KDQpnZ3Bsb3QoZGF0YSA9IG5ld19yYXRpb3MsIGFlcyh5ID0gbmV3YmlsbF90b19BVl8yNSwgeCA9IG5ld2JpbGxfdG9fQVZfNzUsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDMsIG51ZGdlX3k9MC4wMSwgc2l6ZSA9IDMsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIGxhYnModGl0bGUgPSAiSW5jcmVhc2UgR0hFIGJ5IDMwLDAwMCBFQVYgKGZvciB1cCB0byA0MCwwMDAgRUFWIGV4ZW1wdCkgIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAiMjV0aCBwZXJjZW50aWxlIG9mIGhvbWVzLCB0YXhiaWxsOkFWIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeD0gIjc1dGggcGVyY2VudGlsZSBvZiBob21lcywgdGF4YmlsbDpBViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAgIlVzZXMgc2luZ2xlLWZhbWlseSBwcm9wZXJ0aWVzLiBFeGVtcHQgRUFWIHVwIHRvIDQwSyBwZXIgcHJvcGVydHkiKQ0KDQoNCm5ld19yYXRpb3M8LSBtdW5pc19iaWxsY2hhbmdlICU+JSANCiAgZmlsdGVyKGhhc19IT19leGVtcCA9PSAxICYgICFpcy5uYShyYW5rKSkgJT4lICMgY2xhaW1lZCBleGVtcHRpb24gaW4gMjAyMQ0KICBtdXRhdGUobmV3YmlsbF90b19BVl8yNSA9IGlmZWxzZShyYW5rID09ICJxMjUiLCBtZWFuX2JpbGxfcGx1czQwL21lZGlhbl9BViwgTkEpKSAlPiUNCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfNzUgPSBpZmVsc2UocmFuayA9PSAicTc1IiwgbWVhbl9iaWxsX3BsdXM0MC9tZWRpYW5fQVYsIE5BKSkgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKG5ld2JpbGxfdG9fQVZfMjUgPSBtYXgobmV3YmlsbF90b19BVl8yNSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBuZXdiaWxsX3RvX0FWXzc1ID0gbWF4KG5ld2JpbGxfdG9fQVZfNzUsIG5hLnJtPVRSVUUpKSAlPiUNCiAgbXV0YXRlKG11bmlfcmF0aW9fMjV0bzc1ID0gbmV3YmlsbF90b19BVl8yNS9uZXdiaWxsX3RvX0FWXzc1KQ0KDQoNCmdncGxvdChkYXRhID0gbmV3X3JhdGlvcywgYWVzKHkgPSBuZXdiaWxsX3RvX0FWXzI1LCB4ID0gbmV3YmlsbF90b19BVl83NSwgbGFiZWwgPSBjbGVhbl9uYW1lKSkgKyANCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArDQogIGdlb21fcG9pbnQoYWVzKGFscGhhID0gLjUpKSArIA0KICBnZW9tX3RleHQobnVkZ2VfeCA9IC4wMywgbnVkZ2VfeT0wLjAxLCBzaXplID0gMywgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCg0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgbGFicyh0aXRsZSA9ICJJbmNyZWFzZSBHSEUgYnkgNDAsMDAwIEVBViAoZm9yIHVwIHRvIDUwLDAwMCBFQVYgZXhlbXB0KSAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9ICIyNXRoIHBlcmNlbnRpbGUgb2YgaG9tZXMsIHRheGJpbGw6QVYiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4PSAiNzV0aCBwZXJjZW50aWxlIG9mIGhvbWVzLCB0YXhiaWxsOkFWIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICAiVXNlcyBzaW5nbGUtZmFtaWx5IHByb3BlcnRpZXMuIEV4ZW1wdCBFQVYgdXAgdG8gNTBLIHBlciBwcm9wZXJ0eSIpDQpgYGANCg0KDQoNCg0KDQoNCg0KIyMgOTAvMTAgZGVjaWxlcw0KDQpgYGB7cn0NCnEgPSBjKC4xLCAuNSwgLjkpDQoNCiMjIHJhbmtzIHByb3BlcnRpZXMgdGhhdCBhcmUgY29uc2lkZXJlZCBzaW5nbGUgZmFtaWx5IGhvbWVzIGluIG9yZGVyIG9mIEFWIGZvciBlYWNoIE11bmkNCm11bmlfcXVhcnRpbGVzIDwtIGpvaW5lZF9waW5zICU+JQ0KICBmaWx0ZXIoT3B0aW9uMiA9PSAiU2luZ2xlLUZhbWlseSIpICU+JSANCiAgZmlsdGVyKHRheF9jb2RlICVpbiUgbXVuaV9UQ19mdWxseUNvb2skdGF4X2NvZGVfbnVtKSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGNsZWFuX25hbWUpICU+JQ0KICBhcnJhbmdlKGF2KSAlPiUNCiAgc3VtbWFyaXplKGNvdW50X3BpbnMgPSBuKCksIA0KICAgICAgICAgICAgbWluID0gbWluKGF2KSwNCiAgICAgICAgICAgIHF1YW50MTAgPSByb3VuZChxdWFudGlsZShhdiwgcHJvYnMgPSBxWzFdKSksIA0KICAgICAgICAgICAgcXVhbnQ1MCA9IHJvdW5kKHF1YW50aWxlKGF2LCBwcm9icyA9IHFbMl0pKSwNCiAgICAgICAgICAgIHF1YW50OTAgPSByb3VuZChxdWFudGlsZShhdiwgcHJvYnMgPSBxWzNdKSksDQogICAgICAgICAgICBtYXggPSBtYXgoYXYpDQogICAgICAgICAgICkgJT4lIA0KICBhcnJhbmdlKCBkZXNjKCBxdWFudDUwKSkNCm11bmlfcXVhcnRpbGVzDQpgYGANCg0KDQpgYGB7cn0NCiMjIGNyZWF0ZSByYW5rIHZhcmlhYmxlIGZvciBwcm9wZXJ0aWVzIHRoYXQgZmFsbCB3aXRoaW4gdGhlIHF1YXJ0aWxlcyArLy0gJDUwMCByYW5nZQ0KbXVuaXNfcmFua2VkIDwtIGpvaW5lZF9waW5zICAlPiUNCiAgaW5uZXJfam9pbihtdW5pX3F1YXJ0aWxlcywgYnkgPSBjKCJhZ2VuY3lfbmFtZSIsICJjbGVhbl9uYW1lIikpICU+JSANCiAgbXV0YXRlKHJhbmsgPSBjYXNlX3doZW4oDQogICAgYXYgPiAocXVhbnQxMC01MDApICYgKGF2PHF1YW50MTArNTAwKSB+ICJxMTAiLA0KICAgIGF2ID4gKHF1YW50NTAtNTAwKSAmIChhdjxxdWFudDUwKzUwMCkgfiAicTUwIiwNCiAgICBhdiA+IChxdWFudDkwLTUwMCkgJiAoYXY8cXVhbnQ5MCs1MDApIH4gInE5MCIpDQogICAgKSAlPiUNCiAgc2VsZWN0KGNsZWFuX25hbWUsIHJhbmssIGF2LCBwaW4sIGNsYXNzLCBldmVyeXRoaW5nKCkpICU+JQ0KICBsZWZ0X2pvaW4obmlja25hbWVzKQ0KDQoNCg0KDQptdW5pc19iaWxsY2hhbmdlIDwtICBtdW5pc19yYW5rZWQgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lLCByYW5rKSAlPiUNCiAgbGVmdF9qb2luKHNjZW5hcmlvX3RheHJhdGVzKSAlPiUNCiAgYXJyYW5nZShhdikgJT4lDQogIyBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIG11dGF0ZSgjdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdCAvIHRheF9jb2RlX3JhdGUsDQogICAgIyBjdXJyZW50IGJpbGwgPSBjdXJyZW50IHRheCByYXRlICogcG9ydGlvbiBvZiBsZXZ5IGJpbGxlZA0KICAgICAgICAgYmlsbF9uZWcxMCA9IHRyX25lZzEwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrIGV4ZV9ob21lb3duZXIgLWV4ZV9uZWcxMCksDQoNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IGN1cl9jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMpLA0KICAgICAgICAgYmlsbF9wbHVzMTAgPSAgdHJfcGx1czEwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrIGV4ZV9ob21lb3duZXIgLWV4ZV9wbHVzMTApLA0KICAgICAgICAgYmlsbF9wbHVzMjAgPSB0cl9wbHVzMjAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX3BsdXMyMCksDQogICAgICAgICBiaWxsX3BsdXMzMCA9IHRyX3BsdXMzMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zKyBleGVfaG9tZW93bmVyIC1leGVfcGx1czMwKSwNCiAgICAgICAgIGJpbGxfcGx1czQwID0gdHJfcGx1czQwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrIGV4ZV9ob21lb3duZXIgLWV4ZV9wbHVzNDApLA0KDQogICAgIyAjIyBtYWtlIGJpbGxzICQxIGlmIHRoZXkgaGFkIGJlZW4gbmVnYXRpdmUuICAgIA0KICAgICAgICAgYmlsbF9uZWcxMCA9IGlmZWxzZShiaWxsX25lZzEwIDwgMSwgMSwgYmlsbF9uZWcxMCksDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSBpZmVsc2UoYmlsbF9jdXJyZW50IDwgMSwgMSwgYmlsbF9jdXJyZW50KSwNCiAgICAgICAgIGJpbGxfcGx1czEwID0gaWZlbHNlKGJpbGxfcGx1czEwIDwgMSwgMSwgYmlsbF9wbHVzMTApLA0KICAgICAgICAgYmlsbF9wbHVzMjAgPSBpZmVsc2UoYmlsbF9wbHVzMjAgPCAxLCAxLCBiaWxsX3BsdXMyMCksDQogICAgICAgICBiaWxsX3BsdXMzMCA9IGlmZWxzZShiaWxsX3BsdXMzMCA8IDEsIDEsIGJpbGxfcGx1czMwKSwNCiAgICAgICAgIGJpbGxfcGx1czQwID0gaWZlbHNlKGJpbGxfcGx1czQwIDwgMSwgMSwgYmlsbF9wbHVzNDApKSAlPiUNCg0KICBtdXRhdGUoDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTAgPSBpZmVsc2UoYmlsbF9uZWcxMCA8IDUsIDEsIDApLA0KICAgICAgICAgemVyb2RvbF9iaWxsc19jdXJyZW50ID0gaWZlbHNlKGJpbGxfY3VycmVudCA8IDUsIDEsIDApLA0KICAgICAgICAgemVyb2RvbF9iaWxsc19naGUyMCA9IGlmZWxzZShiaWxsX3BsdXMxMCA8IDUsIDEsIDApLA0KICAgICAgICAgemVyb2RvbF9iaWxsc19naGUzMCA9IGlmZWxzZShiaWxsX3BsdXMyMCA8IDUsIDEsIDApLA0KICAgICAgICAgemVyb2RvbF9iaWxsc19naGU0MCA9IGlmZWxzZShiaWxsX3BsdXMzMCA8IDUsIDEsIDApLA0KICAgICAgICAgemVyb2RvbF9iaWxsc19naGU1MCA9IGlmZWxzZShiaWxsX3BsdXM0MCA8IDUsIDEsIDApLA0KICApICU+JQ0KICBncm91cF9ieShjbGVhbl9uYW1lLCByYW5rLCBoYXNfSE9fZXhlbXApICU+JSANCiAgc3VtbWFyaXplKG1lZGlhbl9BViA9IHJvdW5kKG1lZGlhbihhdikpLA0KICAgICAgICAgICAgbWVkaWFuX0VBViA9IHJvdW5kKG1lZGlhbihlYXYpKSwNCiAgICAgICAgICAgIG1lYW5fYmlsbF9uZWcxMCA9IHJvdW5kKG1lYW4oYmlsbF9uZWcxMCwgbmEucm09VFJVRSkpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX2N1ciA9IHJvdW5kKG1lYW4oYmlsbF9jdXJyZW50LCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2JpbGxfcGx1czEwID0gcm91bmQobWVhbihiaWxsX3BsdXMxMCwgbmEucm09VFJVRSkpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX3BsdXMyMCA9IHJvdW5kKG1lYW4oYmlsbF9wbHVzMjAsIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIG1lYW5fYmlsbF9wbHVzMzAgPSByb3VuZChtZWFuKGJpbGxfcGx1czMwLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2JpbGxfcGx1czQwID0gcm91bmQobWVhbihiaWxsX3BsdXM0MCwgbmEucm09VFJVRSkpLA0KICAgICAgICAgICAgDQogICAgICAgICAgICAjIGN1cnJlbnQgcGVyY2VpdmVkX3NhdmluZ3MgPSBtZWRpYW4odGF4X2FtdF9leGUpLA0KICAgICAgICAgICAgdHJfbmVnMTAgPSByb3VuZChtZWFuKHRyX25lZzEwKjEwMCksIGRpZ2l0cyA9IDIpLCANCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSByb3VuZChtZWFuKGN1cl9jb21wX1RDX3JhdGUpLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIHRyX3BsdXMxMCA9IHJvdW5kKG1lYW4odHJfcGx1czEwKjEwMCksIGRpZ2l0cyA9IDIpLA0KICAgICAgICAgICAgdHJfcGx1czIwID0gcm91bmQobWVhbih0cl9wbHVzMjAqMTAwKSwgZGlnaXRzID0gMiksDQogICAgICAgICAgICB0cl9wbHVzMzAgPSByb3VuZChtZWFuKHRyX3BsdXMzMCoxMDApLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIHRyX3BsdXM0MCA9IHJvdW5kKG1lYW4odHJfcGx1czQwKjEwMCksIGRpZ2l0cyA9IDIpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpDQogICkgJT4lDQogIGFycmFuZ2UoaGFzX0hPX2V4ZW1wLCByYW5rKQ0KDQoNCm11bmlzX2JpbGxjaGFuZ2UgPC0gbXVuaXNfYmlsbGNoYW5nZSAlPiUgbGVmdF9qb2luKG11bmlfcXVhcnRpbGVzKQ0KbXVuaXNfYmlsbGNoYW5nZQ0KYGBgDQoNCg0KYGBge3J9DQoNCnJhdGlvczwtIG11bmlzX2JpbGxjaGFuZ2UgJT4lIA0KICBmaWx0ZXIoaGFzX0hPX2V4ZW1wID09IDEgJiAgIWlzLm5hKHJhbmspKSAlPiUgIyBjbGFpbWVkIGV4ZW1wdGlvbiBpbiAyMDIxDQogIG11dGF0ZShjdXJyYmlsbF90b19BVl8xMCA9IGlmZWxzZShyYW5rID09ICJxMTAiLCBtZWFuX2JpbGxfbmVnMTAvbWVkaWFuX0FWLCBOQSkpICU+JQ0KICBtdXRhdGUoY3VycmJpbGxfdG9fQVZfOTAgPSBpZmVsc2UocmFuayA9PSAicTkwIiwgbWVhbl9iaWxsX25lZzEwL21lZGlhbl9BViwgTkEpKSAlPiUgDQogIGdyb3VwX2J5KGNsZWFuX25hbWUpICU+JQ0KICBzdW1tYXJpemUoR0hFXzBfYmlsbF90b19BVl8xMCA9IG1heChjdXJyYmlsbF90b19BVl8xMCwgbmEucm09VFJVRSksDQogICAgICAgICAgICBHSEVfMF9iaWxsX3RvX0FWXzkwID0gbWF4KGN1cnJiaWxsX3RvX0FWXzkwLCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzEwdG85MCA9IEdIRV8wX2JpbGxfdG9fQVZfMTAvR0hFXzBfYmlsbF90b19BVl85MCkNCg0KDQpnZ3Bsb3QoZGF0YSA9IHJhdGlvcywgYWVzKHkgPSBHSEVfMF9iaWxsX3RvX0FWXzEwLCB4ID0gR0hFXzBfYmlsbF90b19BVl85MCwgbGFiZWwgPSBjbGVhbl9uYW1lKSkgKyANCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArDQogIGdlb21fcG9pbnQoYWVzKGFscGhhID0gLjUpKSArIA0KICBnZW9tX3RleHQobnVkZ2VfeCA9IC4wMywgbnVkZ2VfeT0wLjAxLCBzaXplID0gMywgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCg0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicyh0aXRsZSA9ICJSZWR1Y2VkIEdIRSBBbW91bnQgYnkgMTAsMDAwIEVBViAoMCBFQVYgZXhlbXB0IGZyb20gR0hFKSIsDQogICAgICAgc3VidGl0bGUgPSAiT3RoZXIgZXhlbXB0aW9ucyBzdGlsbCBpbiBwbGFjZSIpDQoNCg0KcmF0aW9zPC0gbXVuaXNfYmlsbGNoYW5nZSAlPiUgDQogIGZpbHRlcihoYXNfSE9fZXhlbXAgPT0gMSAmICAhaXMubmEocmFuaykpICU+JSAjIGNsYWltZWQgZXhlbXB0aW9uIGluIDIwMjENCiAgbXV0YXRlKGN1cnJiaWxsX3RvX0FWXzEwID0gaWZlbHNlKHJhbmsgPT0gInExMCIsIG1lYW5fYmlsbF9jdXIvbWVkaWFuX0FWLCBOQSkpICU+JQ0KICBtdXRhdGUoY3VycmJpbGxfdG9fQVZfOTAgPSBpZmVsc2UocmFuayA9PSAicTkwIiwgbWVhbl9iaWxsX2N1ci9tZWRpYW5fQVYsIE5BKSkgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKGN1cnJiaWxsX3RvX0FWXzEwID0gbWF4KGN1cnJiaWxsX3RvX0FWXzEwLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIGN1cnJiaWxsX3RvX0FWXzkwID0gbWF4KGN1cnJiaWxsX3RvX0FWXzkwLCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzEwdG85MCA9IGN1cnJiaWxsX3RvX0FWXzEwL2N1cnJiaWxsX3RvX0FWXzkwKQ0KDQoNCmdncGxvdChkYXRhID0gcmF0aW9zLCBhZXMoeSA9IGN1cnJiaWxsX3RvX0FWXzEwLCB4ID0gY3VycmJpbGxfdG9fQVZfOTAsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDMsIG51ZGdlX3k9MC4wMSwgc2l6ZSA9IDMsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnModGl0bGUgPSAiQ3VycmVudCBHSEUgQW1vdW50ICh1cCB0byAxMCwwMDAgRUFWIGV4ZW1wdCBwZXIgcHJvcGVydHkpIikNCmBgYA0KDQpgYGB7cn0NCm5ld19yYXRpb3M8LSBtdW5pc19iaWxsY2hhbmdlICU+JSANCiAgZmlsdGVyKGhhc19IT19leGVtcCA9PSAxICYgICFpcy5uYShyYW5rKSkgJT4lICMgY2xhaW1lZCBleGVtcHRpb24gaW4gMjAyMQ0KICBtdXRhdGUobmV3YmlsbF90b19BVl8xMCA9IGlmZWxzZShyYW5rID09ICJxMTAiLCBtZWFuX2JpbGxfcGx1czEwL21lZGlhbl9BViwgTkEpKSAlPiUNCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfOTAgPSBpZmVsc2UocmFuayA9PSAicTkwIiwgbWVhbl9iaWxsX3BsdXMxMC9tZWRpYW5fQVYsIE5BKSkgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKG5ld2JpbGxfdG9fQVZfMTAgPSBtYXgobmV3YmlsbF90b19BVl8xMCwgbmEucm09VFJVRSksDQogICAgICAgICAgICBuZXdiaWxsX3RvX0FWXzkwID0gbWF4KG5ld2JpbGxfdG9fQVZfOTAsIG5hLnJtPVRSVUUpKSAlPiUNCiAgbXV0YXRlKG11bmlfcmF0aW9fMTB0bzkwID0gbmV3YmlsbF90b19BVl8xMC9uZXdiaWxsX3RvX0FWXzkwKQ0KDQoNCmdncGxvdChkYXRhID0gbmV3X3JhdGlvcywgYWVzKHkgPSBuZXdiaWxsX3RvX0FWXzEwLCB4ID0gbmV3YmlsbF90b19BVl85MCwgbGFiZWwgPSBjbGVhbl9uYW1lKSkgKyANCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArDQogIGdlb21fcG9pbnQoYWVzKGFscGhhID0gLjUpKSArIA0KICBnZW9tX3RleHQobnVkZ2VfeCA9IC4wMywgbnVkZ2VfeT0wLjAxLCBzaXplID0gMywgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyBsYWJzKHRpdGxlID0gIkluY3JlYXNlIEdIRSBieSAxMCwwMDAgRUFWIChmb3IgdXAgdG8gMjAsMDAwIEVBViBleGVtcHQpICIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gIjEwdGggcGVyY2VudGlsZSBvZiBob21lcywgdGF4YmlsbDpBViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHg9ICI5MHRoIHBlcmNlbnRpbGUgb2YgaG9tZXMsIHRheGJpbGw6QVYiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gICJVc2VzIHNpbmdsZS1mYW1pbHkgcHJvcGVydGllcy4gRXhlbXB0IEVBViB1cCB0byAyMEsgcGVyIHByb3BlcnR5IikNCg0KDQpuZXdfcmF0aW9zPC0gbXVuaXNfYmlsbGNoYW5nZSAlPiUgDQogIGZpbHRlcihoYXNfSE9fZXhlbXAgPT0gMSAmICAhaXMubmEocmFuaykpICU+JSAjIGNsYWltZWQgZXhlbXB0aW9uIGluIDIwMjENCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfMTAgPSBpZmVsc2UocmFuayA9PSAicTEwIiwgbWVhbl9iaWxsX3BsdXMyMC9tZWRpYW5fQVYsIE5BKSkgJT4lDQogIG11dGF0ZShuZXdiaWxsX3RvX0FWXzkwID0gaWZlbHNlKHJhbmsgPT0gInE5MCIsIG1lYW5fYmlsbF9wbHVzMjAvbWVkaWFuX0FWLCBOQSkpICU+JSANCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSkgJT4lDQogIHN1bW1hcml6ZShuZXdiaWxsX3RvX0FWXzEwID0gbWF4KG5ld2JpbGxfdG9fQVZfMTAsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbmV3YmlsbF90b19BVl85MCA9IG1heChuZXdiaWxsX3RvX0FWXzkwLCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzEwdG85MCA9IG5ld2JpbGxfdG9fQVZfMTAvbmV3YmlsbF90b19BVl85MCkNCg0KDQpnZ3Bsb3QoZGF0YSA9IG5ld19yYXRpb3MsIGFlcyh5ID0gbmV3YmlsbF90b19BVl8xMCwgeCA9IG5ld2JpbGxfdG9fQVZfOTAsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDMsIG51ZGdlX3k9MC4wMSwgc2l6ZSA9IDMsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIGxhYnModGl0bGUgPSAiSW5jcmVhc2UgR0hFIGJ5IDIwLDAwMCBFQVYgKGZvciB1cCB0byAzMCwwMDAgRUFWIGV4ZW1wdCkgIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAiMTB0aCBwZXJjZW50aWxlIG9mIGhvbWVzLCB0YXhiaWxsOkFWIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeD0gIjkwdGggcGVyY2VudGlsZSBvZiBob21lcywgdGF4YmlsbDpBViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAgIlVzZXMgc2luZ2xlLWZhbWlseSBwcm9wZXJ0aWVzLiBFeGVtcHQgRUFWIHVwIHRvIDMwSyBwZXIgcHJvcGVydHkiKQ0KDQpuZXdfcmF0aW9zPC0gbXVuaXNfYmlsbGNoYW5nZSAlPiUgDQogIGZpbHRlcihoYXNfSE9fZXhlbXAgPT0gMSAmICAhaXMubmEocmFuaykpICU+JSAjIGNsYWltZWQgZXhlbXB0aW9uIGluIDIwMjENCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfMTAgPSBpZmVsc2UocmFuayA9PSAicTEwIiwgbWVhbl9iaWxsX3BsdXMzMC9tZWRpYW5fQVYsIE5BKSkgJT4lDQogIG11dGF0ZShuZXdiaWxsX3RvX0FWXzkwID0gaWZlbHNlKHJhbmsgPT0gInE5MCIsIG1lYW5fYmlsbF9wbHVzMzAvbWVkaWFuX0FWLCBOQSkpICU+JSANCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSkgJT4lDQogIHN1bW1hcml6ZShuZXdiaWxsX3RvX0FWXzEwID0gbWF4KG5ld2JpbGxfdG9fQVZfMTAsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbmV3YmlsbF90b19BVl85MCA9IG1heChuZXdiaWxsX3RvX0FWXzkwLCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzEwdG85MCA9IG5ld2JpbGxfdG9fQVZfMTAvbmV3YmlsbF90b19BVl85MCkNCg0KDQpnZ3Bsb3QoZGF0YSA9IG5ld19yYXRpb3MsIGFlcyh5ID0gbmV3YmlsbF90b19BVl8xMCwgeCA9IG5ld2JpbGxfdG9fQVZfOTAsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDMsIG51ZGdlX3k9MC4wMSwgc2l6ZSA9IDMsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIGxhYnModGl0bGUgPSAiSW5jcmVhc2UgR0hFIGJ5IDMwLDAwMCBFQVYgKGZvciB1cCB0byA0MCwwMDAgRUFWIGV4ZW1wdCkgIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAiMTB0aCBwZXJjZW50aWxlIG9mIGhvbWVzLCB0YXhiaWxsOkFWIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeD0gIjkwdGggcGVyY2VudGlsZSBvZiBob21lcywgdGF4YmlsbDpBViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAgIlVzZXMgc2luZ2xlLWZhbWlseSBwcm9wZXJ0aWVzLiBFeGVtcHQgRUFWIHVwIHRvIDQwSyBwZXIgcHJvcGVydHkiKQ0KDQoNCm5ld19yYXRpb3M8LSBtdW5pc19iaWxsY2hhbmdlICU+JSANCiAgZmlsdGVyKGhhc19IT19leGVtcCA9PSAxICYgICFpcy5uYShyYW5rKSkgJT4lICMgY2xhaW1lZCBleGVtcHRpb24gaW4gMjAyMQ0KICBtdXRhdGUobmV3YmlsbF90b19BVl8xMCA9IGlmZWxzZShyYW5rID09ICJxMTAiLCBtZWFuX2JpbGxfcGx1czQwL21lZGlhbl9BViwgTkEpKSAlPiUNCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfOTAgPSBpZmVsc2UocmFuayA9PSAicTkwIiwgbWVhbl9iaWxsX3BsdXM0MC9tZWRpYW5fQVYsIE5BKSkgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKG5ld2JpbGxfdG9fQVZfMTAgPSBtYXgobmV3YmlsbF90b19BVl8xMCwgbmEucm09VFJVRSksDQogICAgICAgICAgICBuZXdiaWxsX3RvX0FWXzkwID0gbWF4KG5ld2JpbGxfdG9fQVZfOTAsIG5hLnJtPVRSVUUpKSAlPiUNCiAgbXV0YXRlKG11bmlfcmF0aW9fMTB0bzkwID0gbmV3YmlsbF90b19BVl8xMC9uZXdiaWxsX3RvX0FWXzkwKQ0KDQoNCmdncGxvdChkYXRhID0gbmV3X3JhdGlvcywgYWVzKHkgPSBuZXdiaWxsX3RvX0FWXzEwLCB4ID0gbmV3YmlsbF90b19BVl85MCwgbGFiZWwgPSBjbGVhbl9uYW1lKSkgKyANCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArDQogIGdlb21fcG9pbnQoYWVzKGFscGhhID0gLjUpKSArIA0KICBnZW9tX3RleHQobnVkZ2VfeCA9IC4wMywgbnVkZ2VfeT0wLjAxLCBzaXplID0gMywgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCg0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgbGFicyh0aXRsZSA9ICJJbmNyZWFzZSBHSEUgYnkgNDAsMDAwIEVBViAoZm9yIHVwIHRvIDUwLDAwMCBFQVYgZXhlbXB0KSAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9ICIxMHRoIHBlcmNlbnRpbGUgb2YgaG9tZXMsIHRheGJpbGw6QVYiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4PSAiOTB0aCBwZXJjZW50aWxlIG9mIGhvbWVzLCB0YXhiaWxsOkFWIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICAiVXNlcyBzaW5nbGUtZmFtaWx5IHByb3BlcnRpZXMuIEV4ZW1wdCBFQVYgdXAgdG8gNTBLIHBlciBwcm9wZXJ0eSIpDQpgYGANCg0KDQoNCg0KDQoNCiMjIyA5MC8xMCBkZWNpbGVzIC0gQmlnZ2VyIEFWIHJhbmdlDQoNCkluY3JlYXNlZCByYW5nZSBvZiBob21lcyBpbmNsdWRlZCBpbiBxdWFudGlsZSB0byBhdm9pZCBoYXZpbmcgbXVuaWNpcGFsaXRpZXMgZHJvcCBvdXQgaWYgdGhlcmUgd2VyZSBubyB0YXggYmlsbHMuIE5vdCBzdXJlIGlmIGl0IGFkZHJlc3NlcyB0aGUgcHJvYmxlbS4gDQoNCmBgYHtyfQ0KcSA9IGMoLjEsIC41LCAuOSkNCg0KIyMgcmFua3MgcHJvcGVydGllcyB0aGF0IGFyZSBjb25zaWRlcmVkIHNpbmdsZSBmYW1pbHkgaG9tZXMgaW4gb3JkZXIgb2YgQVYgZm9yIGVhY2ggTXVuaQ0KbXVuaV9xdWFydGlsZXMgPC0gam9pbmVkX3BpbnMgJT4lDQogIGZpbHRlcihPcHRpb24yID09ICJTaW5nbGUtRmFtaWx5IikgJT4lIA0KICBmaWx0ZXIodGF4X2NvZGUgJWluJSBtdW5pX1RDX2Z1bGx5Q29vayR0YXhfY29kZV9udW0pICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSwgY2xlYW5fbmFtZSkgJT4lDQogIGFycmFuZ2UoYXYpICU+JQ0KICBzdW1tYXJpemUoY291bnRfcGlucyA9IG4oKSwgDQogICAgICAgICAgICBtaW4gPSBtaW4oYXYpLA0KICAgICAgICAgICAgcXVhbnQxMCA9IHJvdW5kKHF1YW50aWxlKGF2LCBwcm9icyA9IHFbMV0pKSwgDQogICAgICAgICAgICBxdWFudDUwID0gcm91bmQocXVhbnRpbGUoYXYsIHByb2JzID0gcVsyXSkpLA0KICAgICAgICAgICAgcXVhbnQ5MCA9IHJvdW5kKHF1YW50aWxlKGF2LCBwcm9icyA9IHFbM10pKSwNCiAgICAgICAgICAgIG1heCA9IG1heChhdikNCiAgICAgICAgICAgKSAlPiUgDQogIGFycmFuZ2UoIGRlc2MoIHF1YW50NTApKQ0KbXVuaV9xdWFydGlsZXMNCmBgYA0KDQoNCmBgYHtyfQ0KIyMgY3JlYXRlIHJhbmsgdmFyaWFibGUgZm9yIHByb3BlcnRpZXMgdGhhdCBmYWxsIHdpdGhpbiB0aGUgcXVhcnRpbGVzICsvLSAkNTAwIHJhbmdlDQptdW5pc19yYW5rZWQgPC0gam9pbmVkX3BpbnMgICU+JQ0KICBpbm5lcl9qb2luKG11bmlfcXVhcnRpbGVzLCBieSA9IGMoImFnZW5jeV9uYW1lIiwgImNsZWFuX25hbWUiKSkgJT4lIA0KICBtdXRhdGUocmFuayA9IGNhc2Vfd2hlbigNCiAgICBhdiA+IChxdWFudDEwLTEwMDApICYgKGF2PHF1YW50MTArMTAwMCkgfiAicTEwIiwNCiAgICBhdiA+IChxdWFudDUwLTEwMDApICYgKGF2PHF1YW50NTArMTAwMCkgfiAicTUwIiwNCiAgICBhdiA+IChxdWFudDkwLTEwMDApICYgKGF2PHF1YW50OTArMTAwMCkgfiAicTkwIikNCiAgICApICU+JQ0KICBzZWxlY3QoY2xlYW5fbmFtZSwgcmFuaywgYXYsIHBpbiwgY2xhc3MsIGV2ZXJ5dGhpbmcoKSkgJT4lDQogIGxlZnRfam9pbihuaWNrbmFtZXMpDQoNCg0KDQoNCm11bmlzX2JpbGxjaGFuZ2UgPC0gIG11bmlzX3JhbmtlZCAlPiUgDQogIGdyb3VwX2J5KGNsZWFuX25hbWUsIHJhbmspICU+JQ0KICBsZWZ0X2pvaW4oc2NlbmFyaW9fdGF4cmF0ZXMpICU+JQ0KICBhcnJhbmdlKGF2KSAlPiUNCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX25lZzEwID0gdHJfbmVnMTAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX25lZzEwKSwNCg0KICAgICAgICAgYmlsbF9jdXJyZW50ID0gY3VyX2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucyksDQogICAgICAgICBiaWxsX3BsdXMxMCA9ICB0cl9wbHVzMTAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX3BsdXMxMCksDQogICAgICAgICBiaWxsX3BsdXMyMCA9IHRyX3BsdXMyMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zKyBleGVfaG9tZW93bmVyIC1leGVfcGx1czIwKSwNCiAgICAgICAgIGJpbGxfcGx1czMwID0gdHJfcGx1czMwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrIGV4ZV9ob21lb3duZXIgLWV4ZV9wbHVzMzApLA0KICAgICAgICAgYmlsbF9wbHVzNDAgPSB0cl9wbHVzNDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucysgZXhlX2hvbWVvd25lciAtZXhlX3BsdXM0MCksDQoNCiAgICAjICMjIG1ha2UgYmlsbHMgJDEgaWYgdGhleSBoYWQgYmVlbiBuZWdhdGl2ZS4gICAgDQogICAgICAgICBiaWxsX25lZzEwID0gaWZlbHNlKGJpbGxfbmVnMTAgPCAxLCAxLCBiaWxsX25lZzEwKSwNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IGlmZWxzZShiaWxsX2N1cnJlbnQgPCAxLCAxLCBiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgYmlsbF9wbHVzMTAgPSBpZmVsc2UoYmlsbF9wbHVzMTAgPCAxLCAxLCBiaWxsX3BsdXMxMCksDQogICAgICAgICBiaWxsX3BsdXMyMCA9IGlmZWxzZShiaWxsX3BsdXMyMCA8IDEsIDEsIGJpbGxfcGx1czIwKSwNCiAgICAgICAgIGJpbGxfcGx1czMwID0gaWZlbHNlKGJpbGxfcGx1czMwIDwgMSwgMSwgYmlsbF9wbHVzMzApLA0KICAgICAgICAgYmlsbF9wbHVzNDAgPSBpZmVsc2UoYmlsbF9wbHVzNDAgPCAxLCAxLCBiaWxsX3BsdXM0MCkpICU+JQ0KDQogIG11dGF0ZSgNCiAgICAgICAgIHplcm9kb2xfYmlsbHNfZ2hlMCA9IGlmZWxzZShiaWxsX25lZzEwIDwgNSwgMSwgMCksDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2N1cnJlbnQgPSBpZmVsc2UoYmlsbF9jdXJyZW50IDwgNSwgMSwgMCksDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTIwID0gaWZlbHNlKGJpbGxfcGx1czEwIDwgNSwgMSwgMCksDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTMwID0gaWZlbHNlKGJpbGxfcGx1czIwIDwgNSwgMSwgMCksDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTQwID0gaWZlbHNlKGJpbGxfcGx1czMwIDwgNSwgMSwgMCksDQogICAgICAgICB6ZXJvZG9sX2JpbGxzX2doZTUwID0gaWZlbHNlKGJpbGxfcGx1czQwIDwgNSwgMSwgMCksDQogICkgJT4lDQogIGdyb3VwX2J5KGNsZWFuX25hbWUsIHJhbmssIGhhc19IT19leGVtcCkgJT4lIA0KICBzdW1tYXJpemUobWVkaWFuX0FWID0gcm91bmQobWVkaWFuKGF2KSksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gcm91bmQobWVkaWFuKGVhdikpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX25lZzEwID0gcm91bmQobWVhbihiaWxsX25lZzEwLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2JpbGxfY3VyID0gcm91bmQobWVhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIG1lYW5fYmlsbF9wbHVzMTAgPSByb3VuZChtZWFuKGJpbGxfcGx1czEwLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2JpbGxfcGx1czIwID0gcm91bmQobWVhbihiaWxsX3BsdXMyMCwgbmEucm09VFJVRSkpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX3BsdXMzMCA9IHJvdW5kKG1lYW4oYmlsbF9wbHVzMzAsIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIG1lYW5fYmlsbF9wbHVzNDAgPSByb3VuZChtZWFuKGJpbGxfcGx1czQwLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICANCiAgICAgICAgICAgICMgY3VycmVudCBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICB0cl9uZWcxMCA9IHJvdW5kKG1lYW4odHJfbmVnMTApLCBkaWdpdHMgPSAyKSwgDQogICAgICAgICAgICBjdXJfY29tcF9UQ19yYXRlID0gcm91bmQobWVhbihjdXJfY29tcF9UQ19yYXRlKSwgZGlnaXRzID0gMiksDQogICAgICAgICAgICB0cl9wbHVzMTAgPSByb3VuZChtZWFuKHRyX3BsdXMxMCoxMDApLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIHRyX3BsdXMyMCA9IHJvdW5kKG1lYW4odHJfcGx1czIwKjEwMCksIGRpZ2l0cyA9IDIpLA0KICAgICAgICAgICAgdHJfcGx1czMwID0gcm91bmQobWVhbih0cl9wbHVzMzAqMTAwKSwgZGlnaXRzID0gMiksDQogICAgICAgICAgICB0cl9wbHVzNDAgPSByb3VuZChtZWFuKHRyX3BsdXM0MCoxMDApLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIHBpbmNvdW50PW4oKQ0KICApICU+JQ0KICBhcnJhbmdlKGhhc19IT19leGVtcCwgcmFuaykNCg0KDQptdW5pc19iaWxsY2hhbmdlIDwtIG11bmlzX2JpbGxjaGFuZ2UgJT4lIGxlZnRfam9pbihtdW5pX3F1YXJ0aWxlcykNCm11bmlzX2JpbGxjaGFuZ2UNCmBgYA0KDQoNCmBgYHtyfQ0KDQpyYXRpb3M8LSBtdW5pc19iaWxsY2hhbmdlICU+JSANCiAgZmlsdGVyKGhhc19IT19leGVtcCA9PSAxICYgICFpcy5uYShyYW5rKSkgJT4lICMgY2xhaW1lZCBleGVtcHRpb24gaW4gMjAyMQ0KICBtdXRhdGUoY3VycmJpbGxfdG9fQVZfMTAgPSBpZmVsc2UocmFuayA9PSAicTEwIiwgbWVhbl9iaWxsX25lZzEwL21lZGlhbl9BViwgTkEpKSAlPiUNCiAgbXV0YXRlKGN1cnJiaWxsX3RvX0FWXzkwID0gaWZlbHNlKHJhbmsgPT0gInE5MCIsIG1lYW5fYmlsbF9uZWcxMC9tZWRpYW5fQVYsIE5BKSkgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKEdIRV8wX2JpbGxfdG9fQVZfMTAgPSBtYXgoY3VycmJpbGxfdG9fQVZfMTAsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgR0hFXzBfYmlsbF90b19BVl85MCA9IG1heChjdXJyYmlsbF90b19BVl85MCwgbmEucm09VFJVRSkpICU+JQ0KICBtdXRhdGUobXVuaV9yYXRpb18xMHRvOTAgPSBHSEVfMF9iaWxsX3RvX0FWXzEwL0dIRV8wX2JpbGxfdG9fQVZfOTApDQoNCg0KZ2dwbG90KGRhdGEgPSByYXRpb3MsIGFlcyh5ID0gR0hFXzBfYmlsbF90b19BVl8xMCwgeCA9IEdIRV8wX2JpbGxfdG9fQVZfOTAsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDMsIG51ZGdlX3k9MC4wMSwgc2l6ZSA9IDMsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIGxhYnModGl0bGUgPSAiUmVkdWNlZCBHSEUgQW1vdW50IGJ5IDEwLDAwMCBFQVYgKDAgRUFWIGV4ZW1wdCBmcm9tIEdIRSkiLA0KICAgICAgIHN1YnRpdGxlID0gIk90aGVyIGV4ZW1wdGlvbnMgc3RpbGwgaW4gcGxhY2UiKQ0KDQoNCnJhdGlvczwtIG11bmlzX2JpbGxjaGFuZ2UgJT4lIA0KICBmaWx0ZXIoaGFzX0hPX2V4ZW1wID09IDEgJiAgIWlzLm5hKHJhbmspKSAlPiUgIyBjbGFpbWVkIGV4ZW1wdGlvbiBpbiAyMDIxDQogIG11dGF0ZShjdXJyYmlsbF90b19BVl8xMCA9IGlmZWxzZShyYW5rID09ICJxMTAiLCBtZWFuX2JpbGxfY3VyL21lZGlhbl9BViwgTkEpKSAlPiUNCiAgbXV0YXRlKGN1cnJiaWxsX3RvX0FWXzkwID0gaWZlbHNlKHJhbmsgPT0gInE5MCIsIG1lYW5fYmlsbF9jdXIvbWVkaWFuX0FWLCBOQSkpICU+JSANCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSkgJT4lDQogIHN1bW1hcml6ZShjdXJyYmlsbF90b19BVl8xMCA9IG1heChjdXJyYmlsbF90b19BVl8xMCwgbmEucm09VFJVRSksDQogICAgICAgICAgICBjdXJyYmlsbF90b19BVl85MCA9IG1heChjdXJyYmlsbF90b19BVl85MCwgbmEucm09VFJVRSkpICU+JQ0KICBtdXRhdGUobXVuaV9yYXRpb18xMHRvOTAgPSBjdXJyYmlsbF90b19BVl8xMC9jdXJyYmlsbF90b19BVl85MCkNCg0KDQpnZ3Bsb3QoZGF0YSA9IHJhdGlvcywgYWVzKHkgPSBjdXJyYmlsbF90b19BVl8xMCwgeCA9IGN1cnJiaWxsX3RvX0FWXzkwLCBsYWJlbCA9IGNsZWFuX25hbWUpKSArIA0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsNCiAgZ2VvbV9wb2ludChhZXMoYWxwaGEgPSAuNSkpICsgDQogIGdlb21fdGV4dChudWRnZV94ID0gLjAzLCBudWRnZV95PTAuMDEsIHNpemUgPSAzLCBjaGVja19vdmVybGFwID0gVFJVRSkrIA0KICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBsYWJzKHRpdGxlID0gIkN1cnJlbnQgR0hFIEFtb3VudCAodXAgdG8gMTAsMDAwIEVBViBleGVtcHQgcGVyIHByb3BlcnR5KSIpDQpgYGANCg0KYGBge3J9DQpuZXdfcmF0aW9zPC0gbXVuaXNfYmlsbGNoYW5nZSAlPiUgDQogIGZpbHRlcihoYXNfSE9fZXhlbXAgPT0gMSAmICAhaXMubmEocmFuaykpICU+JSAjIGNsYWltZWQgZXhlbXB0aW9uIGluIDIwMjENCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfMTAgPSBpZmVsc2UocmFuayA9PSAicTEwIiwgbWVhbl9iaWxsX3BsdXMxMC9tZWRpYW5fQVYsIE5BKSkgJT4lDQogIG11dGF0ZShuZXdiaWxsX3RvX0FWXzkwID0gaWZlbHNlKHJhbmsgPT0gInE5MCIsIG1lYW5fYmlsbF9wbHVzMTAvbWVkaWFuX0FWLCBOQSkpICU+JSANCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSkgJT4lDQogIHN1bW1hcml6ZShuZXdiaWxsX3RvX0FWXzEwID0gbWF4KG5ld2JpbGxfdG9fQVZfMTAsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbmV3YmlsbF90b19BVl85MCA9IG1heChuZXdiaWxsX3RvX0FWXzkwLCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzEwdG85MCA9IG5ld2JpbGxfdG9fQVZfMTAvbmV3YmlsbF90b19BVl85MCkNCg0KDQpnZ3Bsb3QoZGF0YSA9IG5ld19yYXRpb3MsIGFlcyh5ID0gbmV3YmlsbF90b19BVl8xMCwgeCA9IG5ld2JpbGxfdG9fQVZfOTAsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDMsIG51ZGdlX3k9MC4wMSwgc2l6ZSA9IDMsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgbGFicyh0aXRsZSA9ICJJbmNyZWFzZSBHSEUgYnkgMTAsMDAwIEVBViAoZm9yIHVwIHRvIDIwLDAwMCBFQVYgZXhlbXB0KSAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9ICIxMHRoIHBlcmNlbnRpbGUgb2YgaG9tZXMsIHRheGJpbGw6QVYiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4PSAiOTB0aCBwZXJjZW50aWxlIG9mIGhvbWVzLCB0YXhiaWxsOkFWIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbiA9ICAiVXNlcyBzaW5nbGUtZmFtaWx5IHByb3BlcnRpZXMuIEV4ZW1wdCBFQVYgdXAgdG8gMjBLIHBlciBwcm9wZXJ0eSIpDQoNCg0KbmV3X3JhdGlvczwtIG11bmlzX2JpbGxjaGFuZ2UgJT4lIA0KICBmaWx0ZXIoaGFzX0hPX2V4ZW1wID09IDEgJiAgIWlzLm5hKHJhbmspKSAlPiUgIyBjbGFpbWVkIGV4ZW1wdGlvbiBpbiAyMDIxDQogIG11dGF0ZShuZXdiaWxsX3RvX0FWXzEwID0gaWZlbHNlKHJhbmsgPT0gInExMCIsIG1lYW5fYmlsbF9wbHVzMjAvbWVkaWFuX0FWLCBOQSkpICU+JQ0KICBtdXRhdGUobmV3YmlsbF90b19BVl85MCA9IGlmZWxzZShyYW5rID09ICJxOTAiLCBtZWFuX2JpbGxfcGx1czIwL21lZGlhbl9BViwgTkEpKSAlPiUgDQogIGdyb3VwX2J5KGNsZWFuX25hbWUpICU+JQ0KICBzdW1tYXJpemUobmV3YmlsbF90b19BVl8xMCA9IG1heChuZXdiaWxsX3RvX0FWXzEwLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIG5ld2JpbGxfdG9fQVZfOTAgPSBtYXgobmV3YmlsbF90b19BVl85MCwgbmEucm09VFJVRSkpICU+JQ0KICBtdXRhdGUobXVuaV9yYXRpb18xMHRvOTAgPSBuZXdiaWxsX3RvX0FWXzEwL25ld2JpbGxfdG9fQVZfOTApDQoNCg0KZ2dwbG90KGRhdGEgPSBuZXdfcmF0aW9zLCBhZXMoeSA9IG5ld2JpbGxfdG9fQVZfMTAsIHggPSBuZXdiaWxsX3RvX0FWXzkwLCBsYWJlbCA9IGNsZWFuX25hbWUpKSArIA0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsNCiAgZ2VvbV9wb2ludChhZXMoYWxwaGEgPSAuNSkpICsgDQogIGdlb21fdGV4dChudWRnZV94ID0gLjAzLCBudWRnZV95PTAuMDEsIHNpemUgPSAzLCBjaGVja19vdmVybGFwID0gVFJVRSkrIA0KICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyBsYWJzKHRpdGxlID0gIkluY3JlYXNlIEdIRSBieSAyMCwwMDAgRUFWIChmb3IgdXAgdG8gMzAsMDAwIEVBViBleGVtcHQpICIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gIjEwdGggcGVyY2VudGlsZSBvZiBob21lcywgdGF4YmlsbDpBViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHg9ICI5MHRoIHBlcmNlbnRpbGUgb2YgaG9tZXMsIHRheGJpbGw6QVYiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gICJVc2VzIHNpbmdsZS1mYW1pbHkgcHJvcGVydGllcy4gRXhlbXB0IEVBViB1cCB0byAzMEsgcGVyIHByb3BlcnR5IikNCg0KbmV3X3JhdGlvczwtIG11bmlzX2JpbGxjaGFuZ2UgJT4lIA0KICBmaWx0ZXIoaGFzX0hPX2V4ZW1wID09IDEgJiAgIWlzLm5hKHJhbmspKSAlPiUgIyBjbGFpbWVkIGV4ZW1wdGlvbiBpbiAyMDIxDQogIG11dGF0ZShuZXdiaWxsX3RvX0FWXzEwID0gaWZlbHNlKHJhbmsgPT0gInExMCIsIG1lYW5fYmlsbF9wbHVzMzAvbWVkaWFuX0FWLCBOQSkpICU+JQ0KICBtdXRhdGUobmV3YmlsbF90b19BVl85MCA9IGlmZWxzZShyYW5rID09ICJxOTAiLCBtZWFuX2JpbGxfcGx1czMwL21lZGlhbl9BViwgTkEpKSAlPiUgDQogIGdyb3VwX2J5KGNsZWFuX25hbWUpICU+JQ0KICBzdW1tYXJpemUobmV3YmlsbF90b19BVl8xMCA9IG1heChuZXdiaWxsX3RvX0FWXzEwLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIG5ld2JpbGxfdG9fQVZfOTAgPSBtYXgobmV3YmlsbF90b19BVl85MCwgbmEucm09VFJVRSkpICU+JQ0KICBtdXRhdGUobXVuaV9yYXRpb18xMHRvOTAgPSBuZXdiaWxsX3RvX0FWXzEwL25ld2JpbGxfdG9fQVZfOTApDQoNCg0KZ2dwbG90KGRhdGEgPSBuZXdfcmF0aW9zLCBhZXMoeSA9IG5ld2JpbGxfdG9fQVZfMTAsIHggPSBuZXdiaWxsX3RvX0FWXzkwLCBsYWJlbCA9IGNsZWFuX25hbWUpKSArIA0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsNCiAgZ2VvbV9wb2ludChhZXMoYWxwaGEgPSAuNSkpICsgDQogIGdlb21fdGV4dChudWRnZV94ID0gLjAzLCBudWRnZV95PTAuMDEsIHNpemUgPSAzLCBjaGVja19vdmVybGFwID0gVFJVRSkrIA0KICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyBsYWJzKHRpdGxlID0gIkluY3JlYXNlIEdIRSBieSAzMCwwMDAgRUFWIChmb3IgdXAgdG8gNDAsMDAwIEVBViBleGVtcHQpICIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gIjEwdGggcGVyY2VudGlsZSBvZiBob21lcywgdGF4YmlsbDpBViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHg9ICI5MHRoIHBlcmNlbnRpbGUgb2YgaG9tZXMsIHRheGJpbGw6QVYiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXB0aW9uID0gICJVc2VzIHNpbmdsZS1mYW1pbHkgcHJvcGVydGllcy4gRXhlbXB0IEVBViB1cCB0byA0MEsgcGVyIHByb3BlcnR5IikNCg0KDQpuZXdfcmF0aW9zPC0gbXVuaXNfYmlsbGNoYW5nZSAlPiUgDQogIGZpbHRlcihoYXNfSE9fZXhlbXAgPT0gMSAmICAhaXMubmEocmFuaykpICU+JSAjIGNsYWltZWQgZXhlbXB0aW9uIGluIDIwMjENCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfMTAgPSBpZmVsc2UocmFuayA9PSAicTEwIiwgbWVhbl9iaWxsX3BsdXM0MC9tZWRpYW5fQVYsIE5BKSkgJT4lDQogIG11dGF0ZShuZXdiaWxsX3RvX0FWXzkwID0gaWZlbHNlKHJhbmsgPT0gInE5MCIsIG1lYW5fYmlsbF9wbHVzNDAvbWVkaWFuX0FWLCBOQSkpICU+JSANCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSkgJT4lDQogIHN1bW1hcml6ZShuZXdiaWxsX3RvX0FWXzEwID0gbWF4KG5ld2JpbGxfdG9fQVZfMTAsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbmV3YmlsbF90b19BVl85MCA9IG1heChuZXdiaWxsX3RvX0FWXzkwLCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzEwdG85MCA9IG5ld2JpbGxfdG9fQVZfMTAvbmV3YmlsbF90b19BVl85MCkNCg0KDQpnZ3Bsb3QoZGF0YSA9IG5ld19yYXRpb3MsIGFlcyh5ID0gbmV3YmlsbF90b19BVl8xMCwgeCA9IG5ld2JpbGxfdG9fQVZfOTAsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDMsIG51ZGdlX3k9MC4wMSwgc2l6ZSA9IDMsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIGxhYnModGl0bGUgPSAiSW5jcmVhc2UgR0hFIGJ5IDQwLDAwMCBFQVYgKGZvciB1cCB0byA1MCwwMDAgRUFWIGV4ZW1wdCkgIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAiMTB0aCBwZXJjZW50aWxlIG9mIGhvbWVzLCB0YXhiaWxsOkFWIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeD0gIjkwdGggcGVyY2VudGlsZSBvZiBob21lcywgdGF4YmlsbDpBViIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcHRpb24gPSAgIlVzZXMgc2luZ2xlLWZhbWlseSBwcm9wZXJ0aWVzLiBFeGVtcHQgRUFWIHVwIHRvIDUwSyBwZXIgcHJvcGVydHkiKQ0KYGBgDQoNCg0KDQoNCg==