Bring in data

Bills were pulled from PTAXSIM amd summed to the pin level in files 1_...rmd and 2...rmd. Exemption data per PIN was pulled from PTAXSIM in file 3_.....rmd.

ptaxsim_db_conn <- DBI::dbConnect(RSQLite::SQLite(), "./ptaxsim.db/ptaxsim-2021.0.4.db")

eq_factor <- DBI::dbGetQuery(
  ptaxsim_db_conn,
  "SELECT*
  FROM eq_factor
  "
)

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 DISTINCT agency_num, tax_code_num
  FROM tax_code
  WHERE agency_num IN ({muni_agency_names$agency_num*})
  AND year = 2021
  ",
  .con = ptaxsim_db_conn
  )
) %>% 
  mutate(tax_code_num = as.numeric(tax_code_num))

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
  )
) %>% mutate(tax_code_num = as.numeric(tax_code_num))
taxbills_current <- read_csv("./Output/Dont_Upload/1_Get_All_Pins-CookPinTaxbills_2021_Actual.csv")
# 22,453,875 tax bills in 2021 in municipalities. 
# taxing agency-PIN is the unit of observation here (only partial property tax bills)
# Each PIN has multiple rows (because it is taxed by multiple taxing agencies)

sapply(taxbills_current, function(x) sum(is.na(x)))


# 1,825,816 billed properties with 14-digit PINs in incororated areas
# 1,864,594 in incorported and unincorporated areas.
pin14_bills_current <- taxbills_current %>%
  group_by(tax_code, class, pin) %>%
  
  mutate(total_bill = final_tax_to_dist + final_tax_to_tif) %>% # from each taxing agency
  
  summarize(
    total_billed = sum(total_bill, na.rm = TRUE), # total on someone's property tax bill
    av = first(av),
    eav = first(eav),
    # pin_count_in_parcel = n(),
    final_tax_to_dist = sum(final_tax_to_dist, na.rm = TRUE),
    final_tax_to_tif = sum(final_tax_to_tif, na.rm = TRUE),
    tax_amt_exe = sum(tax_amt_exe, na.rm = TRUE), # revenue lost due to exemptions
    tax_amt_pre_exe = sum(tax_amt_pre_exe, na.rm = TRUE), # total rev before all exemptions
    tax_amt_post_exe = sum(tax_amt_post_exe, na.rm = TRUE), # total rev after all exemptions
    rpm_tif_to_cps = sum(rpm_tif_to_cps, na.rm = TRUE), # not used
    rpm_tif_to_rpm = sum(rpm_tif_to_rpm, na.rm=TRUE), # not used
    rpm_tif_to_dist = sum(rpm_tif_to_dist, na.rm=TRUE), # not used
    tif_share = mean(tif_share, na.rm=TRUE), # not used
  )  %>% 
  mutate(propclass_1dig = str_sub(class, 1, 1))

# head(pin14_bills_current)

sapply(pin14_bills_current, function(x) sum(is.na(x)))


# Now group again and sum values for tax code and each property class!

# There are 28,381 property class - tax code group combinations in incorporated areas.
# There are 28,534 property class - tax code group combos in incorporated + unincorporated areas

rm(taxbills_current)

Add exemption types to pin level tax bills

Need to merge PIN level data of tax bills and exemptions per PIN if the goal is to calculate new tax rates for different scenarios AND view individual level tax bill changes. (i.e. if we want to look at the “median taxpayer” then need to use this method).

Note: The EAV from the exemption table is the original EAV (AV * equalizer) without consider TIFs or exemptions.

31,000 properties have $0 tax bills based on exemption data table made from PTAXSIM’s pin table. (Using the tax bill data allows for more in depth look at tax bills and can create variables such as small_bill if bills were less than $100 after exemptions were applied).

pin_eav <- read_csv("./Output/Dont_Upload/3_Exemption_Details_output-all_cook_pin_exemptions_2021_actual.csv") %>%
  #filter(class_code !=0) %>%
  
  mutate(all_exemptions = exe_homeowner + exe_senior + exe_freeze + exe_longtime_homeowner + 
           exe_disabled + exe_vet_returning + exe_vet_dis_lt50 + exe_vet_dis_50_69 + exe_vet_dis_ge70 + exe_abate) %>%
  mutate(zero_bill = ifelse(eav <= all_exemptions, 1, 0),
         has_HO_exemp = ifelse(exe_homeowner > 0, 1, 0)) %>%
  rename(equalized_AV = eav,
         pin_AV = av)

# table(pin_eav$zero_bill)

table(pin_eav$major_class_code, pin_eav$zero_bill)

# table(pin_eav$major_class_code, pin_eav$has_HO_exemp)



## Add exemption types and values to the tax bill data at PIN level
pin_data <- left_join(pin14_bills_current, pin_eav, by = c("pin", "class" = "class_code" ))

## Add tax code tax rate to PIN level data
pin_data <- left_join(pin_data, tax_codes, by = c("tax_code" = "tax_code_num"))

Calculate new tax rates

# taxcodes_by_class_current <- pin_data %>% 
#   group_by(tax_code, class)  %>%
#   
#   summarize(
#     av = sum(av),
#     eav = sum(eav),
#     equalized_AV = sum(equalized_AV),
#     pins_in_class = n(),
#     current_exemptions = sum(all_exemptions),
#     HO_exemps = sum(exe_homeowner),
#     tax_code_rate = first(tax_code_rate),
#     final_tax_to_dist = sum(final_tax_to_dist, na.rm = TRUE), # used as LEVY amount!! 
#     final_tax_to_tif = sum(final_tax_to_tif, na.rm = TRUE),
#     tax_amt_exe = sum(tax_amt_exe, na.rm = TRUE), 
#     tax_amt_pre_exe = sum(tax_amt_pre_exe, na.rm = TRUE), 
#     tax_amt_post_exe = sum(tax_amt_post_exe, na.rm = TRUE),
#     rpm_tif_to_cps = sum(rpm_tif_to_cps, na.rm = TRUE), # not used
#     rpm_tif_to_rpm = sum(rpm_tif_to_rpm, na.rm=TRUE), # not used
#     rpm_tif_to_dist = sum(rpm_tif_to_dist, na.rm=TRUE), # not used
#     tif_share = mean(tif_share, na.rm=TRUE), # not used
#   ) %>%
#   
#   mutate(total_bill_current = final_tax_to_dist + final_tax_to_tif) %>%
#   rename(cur_comp_TC_rate = tax_code_rate) %>%
#   mutate(current_taxable_eav = final_tax_to_dist/(cur_comp_TC_rate/100),
#          new_taxable_eav = final_tax_to_dist/(cur_comp_TC_rate/100) + HO_exemps) %>%
#   mutate(new_comp_TC_rate = (final_tax_to_dist / new_taxable_eav)*100) %>%
#   mutate(new_comp_TC_rate = ifelse(is.nan(new_comp_TC_rate), cur_comp_TC_rate, new_comp_TC_rate)) %>%
#   select(tax_code, class, cur_comp_TC_rate, new_comp_TC_rate, current_taxable_eav, new_taxable_eav, everything())
# 
# 
# head(taxcodes_by_class_current) 


taxcodes_current <- pin_data %>% 
  group_by(tax_code)  %>%
  summarize(
    av = sum(av),
    eav = sum(eav),
    equalized_AV = sum(equalized_AV),
    pins_in_class = n(),
    current_exemptions = sum(all_exemptions),
    HO_exemps = sum(exe_homeowner),
    tax_code_rate = first(tax_code_rate), 
    final_tax_to_dist = sum(final_tax_to_dist, na.rm = TRUE), # used as LEVY amount!! 
    final_tax_to_tif = sum(final_tax_to_tif, na.rm = TRUE),
    tax_amt_exe = sum(tax_amt_exe, na.rm = TRUE), 
    tax_amt_pre_exe = sum(tax_amt_pre_exe, na.rm = TRUE), 
    tax_amt_post_exe = sum(tax_amt_post_exe, na.rm = TRUE),
    rpm_tif_to_cps = sum(rpm_tif_to_cps, na.rm = TRUE), # not used
    rpm_tif_to_rpm = sum(rpm_tif_to_rpm, na.rm=TRUE), # not used
    rpm_tif_to_dist = sum(rpm_tif_to_dist, na.rm=TRUE), # not used
    tif_share = mean(tif_share, na.rm=TRUE), # not used
  ) %>%
  
  mutate(total_bill_current = final_tax_to_dist + final_tax_to_tif) %>%
  rename(cur_comp_TC_rate = tax_code_rate) %>%
  mutate(current_taxable_eav = final_tax_to_dist/(cur_comp_TC_rate/100),
         new_taxable_eav = final_tax_to_dist/(cur_comp_TC_rate/100) + HO_exemps) %>%
  mutate(new_comp_TC_rate = (final_tax_to_dist / new_taxable_eav)*100) %>%
  mutate(new_comp_TC_rate = ifelse(is.nan(new_comp_TC_rate), cur_comp_TC_rate, new_comp_TC_rate)) %>%
  select(tax_code, cur_comp_TC_rate, new_comp_TC_rate, current_taxable_eav, new_taxable_eav, everything())


#head(taxcodes_current) 


taxcode_taxrates <- taxcodes_current %>% 
  select(tax_code, cur_comp_TC_rate, new_comp_TC_rate, current_exemptions, HO_exemps)

Finding the “Median Property” or “Average Taxpayer”

The median assessed value is used to determine the median property for various groups (e.g. the municipality, the 1-digit major property class, and 3-digit property class).

The assessed value and original equalized assessed values come from the pin data table within PTAXSIM. This table also has every type of exemption that the property received and the amount of EAV that was exempt due to the exemption.

Download 4C_joined_PINs from Box link here:. I would move the downloaded file into your R project and then the code below should work without changing the file path.

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

# head(pin_data2)
# dim(pin_data2)

pin_data2 <- pin_data2 %>% 
  mutate(
    bill_current = (final_tax_to_dist + final_tax_to_tif),
    bill_noGHE = new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
    bill_noexemps = new_comp_TC_rate/100*(equalized_AV),
    bill_change = bill_noGHE - bill_current)
C2_munistats <- pin_data2 %>% 
  filter(class > 199 & class < 300) %>%
  group_by(agency_name)  %>%
  arrange(av) %>%
  summarize(
    median_eav = round(median(eav)), 
    median_av = round(median(av)), 
    avg_av = round(mean(av)),
    avg_eav = round(mean(eav)),
    C2_pins_in_muni = n(),
    C2_current_exemptions = sum(all_exemptions, na.rm = TRUE),
    C2_HO_exemps = sum(exe_homeowner, na.rm = TRUE),
  )
eq_2021 <- 3.0027


muni_taxrates <- pin_data2 %>% 
  group_by(agency_name)  %>%
  arrange(av) %>%
  
  summarize(
    muni_median_av = median(av, na.rm=TRUE),
    muni_median_eav = median(eav, na.rm=TRUE),
    muni_mean_av = round(mean(av, na.rm=TRUE)),
    muni_mean_eav = round(mean(eav, na.rm=TRUE)),
    av = sum(av, na.rm = TRUE),
    eav = sum(eav, na.rm = TRUE),
    equalized_AV = sum(equalized_AV, na.rm = TRUE),
    pins_in_muni = n(),
    current_exemptions = sum(all_exemptions, na.rm = TRUE),
    HO_exemps = sum(exe_homeowner, na.rm = TRUE),
    tax_code_rate = mean(tax_code_rate, na.rm = TRUE), # Changed from first() to mean() on Nov 1
    final_tax_to_dist = sum(final_tax_to_dist, na.rm = TRUE), # used as LEVY amount!! 
    final_tax_to_tif = sum(final_tax_to_tif, na.rm = TRUE),
    tax_amt_exe = sum(tax_amt_exe, na.rm = TRUE), 
    tax_amt_pre_exe = sum(tax_amt_pre_exe, na.rm = TRUE), 
    tax_amt_post_exe = sum(tax_amt_post_exe, na.rm = TRUE),
    rpm_tif_to_cps = sum(rpm_tif_to_cps, na.rm = TRUE), # not used
    rpm_tif_to_rpm = sum(rpm_tif_to_rpm, na.rm=TRUE), # not used
    rpm_tif_to_dist = sum(rpm_tif_to_dist, na.rm=TRUE), # not used
    tif_share = mean(tif_share, na.rm=TRUE), # not used
  ) %>%
  
  mutate(total_bill_current = final_tax_to_dist + final_tax_to_tif) %>%
  rename(cur_comp_TC_rate = tax_code_rate) %>%
  mutate(current_taxable_eav = final_tax_to_dist/(cur_comp_TC_rate/100),
         new_taxable_eav = final_tax_to_dist/(cur_comp_TC_rate/100) + HO_exemps) %>%
  mutate(new_comp_TC_rate = (final_tax_to_dist / new_taxable_eav)*100) %>%
  
  mutate(new_comp_TC_rate = ifelse(is.nan(new_comp_TC_rate), cur_comp_TC_rate, new_comp_TC_rate)) %>% 
  
  left_join(C2_munistats) %>%
  
  mutate(rate_change = cur_comp_TC_rate - new_comp_TC_rate,
    nobillchange_propertyEAV = round(10000 * ((cur_comp_TC_rate/100) / (rate_change/100))),
    nochange_av = round(nobillchange_propertyEAV / eq_2021),
         nochange_ratio = nochange_av / median_av) %>%
  select(agency_name, median_av, nochange_av, nochange_ratio, cur_comp_TC_rate, new_comp_TC_rate, current_taxable_eav, new_taxable_eav, everything())

muni_taxrates 
muni_taxrates %>% write_csv("./Output/4C_muni_taxrates.csv")

Most Common Class 2 Property Type

203 is most common in Riverdale, Phoenix, and Park Forest. 206 is most common in Winnetka

pin_data2 %>% 
  filter(pin_AV > 0 & (class > 199 & class < 300) )%>%
         #major_class_code == "2") %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  group_by(agency_name, class) %>%
  summarize(PIN_count = n()) %>% 
  arrange(-PIN_count)
pin_data2 %>% 
  filter(pin_AV > 0 & (class > 199 & class < 300) ) %>% 
 # filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  group_by(agency_name, class) %>%
  summarize(PIN_count = n()) %>% 
  arrange(agency_name, -PIN_count) %>%
 # group_by(agency_name) %>%
  summarize(agency_name = first(agency_name),
            class = first(class),
            PIN_count = first(PIN_count)
            )

Assessed Value PIN distribution

pin_data2 %>%
  #  filter(major_class_code == 2 & agency_name == "VILLAGE OF PARK FOREST") %>% 
  filter((class > 199 & class < 300) & agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE", "VILLAGE OF WINNETKA")) %>%
  group_by(agency_name) %>%
  ggplot() +
  geom_histogram(aes(x = av, bins = 100)) +
#  geom_vline(aes(xintercept = median(av, na.rm=TRUE), color = "red")) +
  theme_classic()+
  theme(legend.position = "none") + 
 # geom_text(aes(x=(median(av) + 5000), y = 1500, label = median(av))) +
  scale_x_continuous(limits = c(-5, 50000)) +
  #   scale_y_continuous(limits = c(0, 1500))+
  labs(title = "PIN AV Distribution for All Class 2 Properties", x="AV", y="Number of PINs") +
  facet_wrap(~agency_name)

pin_data2 %>%
  #  filter(major_class_code == 2 & agency_name == "VILLAGE OF PARK FOREST") %>% 
  filter((class > 199 & class < 300) &  agency_name == "VILLAGE OF PHOENIX") %>%
         #  agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE", "VILLAGE OF WINNETKA")) %>%
  group_by(agency_name) %>%
  ggplot() +
  geom_histogram(aes(x = av, bins = 100)) +
  geom_vline(aes(xintercept = median(av, na.rm=TRUE), color = "red")) +
  geom_vline(aes(xintercept = 7974), linetype = "dashed", label = "Breakeven AV") +
  theme_classic()+
  theme(legend.position = "none") + 
  geom_text(aes(x=(median(av)), y = 450, label = median(av))) +
  geom_text(aes(x=14000, y = 350), label = "Breakeven AV = $7,974") +
  scale_x_continuous(limits = c(-5, 50000)) +
  #   scale_y_continuous(limits = c(0, 1500))+
  labs(title = "Phoneix PIN AV Distribution for All Class 2 Properties", x="AV", y="Number of PINs",
      caption =  "Median AV is $3,502, Breakeven AV is $7,974") 

pin_data2 %>%
  filter((class > 199 & class < 300) &  agency_name == "CITY OF CHICAGO") %>%
  ggplot() +
  geom_histogram(aes(x = av, bins = 100)) +
  geom_vline(aes(xintercept = median(av, na.rm=TRUE), color = "red")) +
  geom_vline(aes(xintercept = 84228), linetype = "dashed") +
  theme_classic()+
  theme(legend.position = "none") + 
  geom_text(aes(x=median(av)+20000, y = 300000, label = median(av))) +
 geom_text(aes(x=100000, y = 200000), label = "Breakeven AV = $84,228") +

  scale_x_continuous(limits = c(-5, 500000), labels = scales::dollar) +
  scale_y_continuous(limits = c(0, 300000))+
  labs(title = "Chicago PIN AV Distribution for All Class 2 Properties", 
       x="AV", y="Number of PINs",
      caption =  "Median AV is ~$21,000, Breakeven AV is ~$84,000") 

pin_data2 %>%
  filter((class > 199 & class < 300)  & agency_name == "VILLAGE OF PARK FOREST") %>% 
  group_by(agency_name) %>%
  ggplot() +
  geom_histogram(aes(x = av, bins = 100)) +
  theme_classic()+
  theme(legend.position = "none") + 
  scale_x_continuous(limits = c(-5, 10000)) +
  labs(title = "Park Forest PIN AV Distribution per Class", x="AV", y="Number of PINs") +
  facet_wrap(~class)

pin_data2 %>%
  filter((class > 199 & class < 300)  & agency_name == "VILLAGE OF PHOENIX") %>% 
  group_by(agency_name) %>%
  ggplot() +
  geom_histogram(aes(x = av, bins = 100)) +
  theme_classic()+
  theme(legend.position = "none") + 
  scale_x_continuous(limits = c(-5, 10000)) +
  labs(title = "Phoenix PIN AV Distribution per Class", x="AV", y="Number of PINs") +
  facet_wrap(~class)

pin_data2 %>%
    filter((class > 199 & class < 300)  & agency_name == "VILLAGE OF RIVERDALE") %>% 
  group_by(agency_name) %>%
  ggplot() +
  geom_histogram(aes(x = av, bins = 100)) +
  theme_classic()+
  theme(legend.position = "none") + 
  scale_x_continuous(limits = c(-5, 10000)) +
  labs(title = "Riverdale PIN AV Distribution per Class", x="AV", y="Number of PINs") +
  facet_wrap(~class)


pin_data2 %>%
    filter((class > 199 & class < 300)  & agency_name == "VILLAGE OF WINNETKA") %>% 
  group_by(agency_name) %>%
  ggplot() +
  geom_histogram(aes(x = av, bins = 100)) +
  theme_classic()+
  theme(legend.position = "none") + 
  scale_x_continuous(limits = c(-5, 200000)) +
  labs(title = "Winnetka PIN AV Distribution per Class", x="AV", y="Number of PINs") +
  facet_wrap(~class)

Property Value where Bill doesn’t change

nobillchange <- muni_taxrates

nobillchange %>%       
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE", "VILLAGE OF WINNETKA", "CITY OF CHICAGO")) %>%
  ggplot(aes(y=median_av, x = agency_name)) +
  geom_col()+
  #geom_text(aes(x =(nobillchange_propertyEAV), y = (median_eav+5000)), size = 1.5) +
  scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  scale_x_discrete(label = c("Chicago","Park Forest", "Phoenix", "Riverdale", "Winnetka")) + 
  labs(y = "Median Residential AV", x = "", title = "Median Residential Property Assessed Value - All Class 2 property Types")

nobillchange %>%       
  filter(agency_name %in% c("CITY OF CHICAGO", "VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE", "VILLAGE OF WINNETKA")) %>%
  ggplot(aes(y=(nobillchange_propertyEAV/eq_2021), x = agency_name)) +
  geom_col() +
  geom_text(aes(y=(nobillchange_propertyEAV/eq_2021)+3000, label = round(nobillchange_propertyEAV/eq_2021)) ) +
  scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  scale_x_discrete(label = c("Chicago", "Park Forest", "Phoenix", "Riverdale", "Winnetka")) + 
  labs(y = "Breakeven Point - Assessed Value", x = "", title = "Residential Property Assessed Value Breakeven Point", caption = "Residential properties above these values would have their bills decrease if the GHE were eliminated.")

nochange <- C2_munistats %>% left_join(muni_taxrates)


muni_taxrates %>%
  ggplot(aes(x=nochange_av, 
             y = median_av, 
             label=agency_name
             )) +
  geom_point() +
 # geom_smooth(method = "lm" )+
  geom_text(aes(x = (nochange_av), y = (median_av+1000)), size = 2)+
  theme_classic() +
  scale_x_continuous(labels = scales::dollar) +
  scale_y_continuous(labels = scales::dollar) +
  labs(x = "AV of Class 2 Property w/ No Bill Change", y = "Median AV of Class 2 Properties in Municipality", title = "Highly valued homes would have lower tax bills if the GHE were eliminated")

muni_taxrates %>%
      filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE", "VILLAGE OF WINNETKA")) %>%
  select(agency_name, nobillchange_propertyEAV, rate_change, everything()) %>%
 # filter(nobillchange_propertyEAV < 7000000) %>% 
  ggplot(aes(x=nobillchange_propertyEAV, y = median_eav, label=agency_name)) +
  geom_point()+
  geom_text(aes(x =(nobillchange_propertyEAV), y = (median_eav+5000)), size = 1.5) +
      scale_x_continuous(labels = scales::dollar) +
      scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  labs(x = "EAV of Class 2 Property w/ No Bill Change", y = "Median EAV of Municipality", title = "Can homeowners with GHE benefit from removal of the GHE?",
       subtitle = "Yes, if from a muni with high tax rates and if they have a property valued way above other properties in their taxing district",
       caption = "Homeowners in municipalities with high tax rates and AV's much higher
       the median AV in the municipality properties see their bill decrease in GHE removal scenario. 
       These are extreme situations that should not be used for policy decisions or examples.")

muni_taxrates %>%
      filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE") ) %>%
  filter(is.finite(nobillchange_propertyEAV) )%>%
  select(agency_name, nobillchange_propertyEAV, rate_change, everything()) %>%
 # filter(nobillchange_propertyEAV < 7000000) %>% 
  ggplot(aes(x=nobillchange_propertyEAV, y = median_eav, label=agency_name)) +
  geom_point()+
  geom_text(aes(x =(nobillchange_propertyEAV), y = (median_eav+500)), size = 2) +
      scale_x_continuous(labels = scales::dollar) +
      scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  labs(x = "EAV of Class 2 Property w/ No Bill Change", y = "Median EAV of Municipality", title = "Can homeowners have lower tax bills if the GHE exemption was ended?",
       subtitle = "Yes, in very, very rare cases. ")

muni_taxrates %>%
    #  filter(agency_name == "VILLAGE OF WINNETKA") %>%
        filter(median_eav > 150000) %>%
  filter(is.finite(nobillchange_propertyEAV) ) %>%
  select(agency_name, nobillchange_propertyEAV, rate_change, everything()) %>%
  #filter(nobillchange_propertyEAV < 7000000) %>% 
  ggplot(aes(x=nobillchange_propertyEAV, y = median_eav, label=agency_name)) +
  geom_point()+
  geom_text(aes(x =(nobillchange_propertyEAV), y = (median_eav+1000)), size = 2) +
      scale_x_continuous(labels = scales::dollar) +
      scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  labs(x = "EAV of Class 2 Property w/ No Bill Change", y = "Median EAV of Municipality", title = "Can homeowners with GHE benefit from removal of the GHE?",
       caption = "A $500K home in Winnetka would benefit if everyone else lost their General Homestead Exemption")

muni_taxrates  %>%
  filter(is.finite(nobillchange_propertyEAV) ) %>%
  select(agency_name,   nobillchange_propertyEAV, rate_change, everything()) %>%
#  filter(nobillchange_propertyEAV < 7000000) %>% 
  ggplot(aes(x=nobillchange_propertyEAV, y = median_eav, label=agency_name)) +
  # geom_smooth(method = "lm" )+
  geom_text(aes(x = (nobillchange_propertyEAV), y = (median_eav+1000)), size = 2)+
  theme_classic() +
  scale_x_continuous(labels = scales::dollar) +
  scale_y_continuous(labels = scales::dollar) +
  labs(x = "EAV of Class 2 Property w/ No Bill Change", y = "Median EAV of Municipality", title = "Can homeowners who claim GHE benefit from removal of the GHE?",
       subtitle = "In very, very rare instances: yes. ")

muni_taxrates %>%
  select(agency_name,   nobillchange_propertyEAV, rate_change, everything()) %>%
#  filter(nobillchange_propertyEAV < 7000000) %>% 
  ggplot(aes(y=rate_change, x = median_eav, label=agency_name)) +
  geom_point() +
  theme_classic() +
  scale_x_continuous(labels = scales::dollar) +
  labs(x= "EAV of Class 2 Property w/ No Bill Change", y = "Composite Tax Rate Change (Percentage Points)", title = "EAV of Residential Property 'Breakeven Point' & Composite Tax Rate Change 
       from Elimination of GHE")

muni_taxrates %>%
  select(agency_name,   nobillchange_propertyEAV, rate_change, everything()) %>%
  ggplot(aes(y=rate_change, x = median_av, label=agency_name)) +
  geom_point() +
  theme_classic() +
  scale_x_continuous(labels = scales::dollar) +
  labs(x= "AV of Class 2 Property w/ No Bill Change", y = "Composite Tax Rate Change (Percentage Points)", title = "AV of Residential Property 'Breakeven Point' & Composite Tax Rate Change 
       from Elimination of GHE")

muni_taxrates %>%
  select(agency_name,   nobillchange_propertyEAV, rate_change, everything()) %>%
  ggplot(aes(y=rate_change, x = median_av*10, label=agency_name)) +
  geom_point() +
  theme_classic() +
  scale_x_continuous(labels = scales::dollar) +
  labs(x= "Market Value of Class 2 Property 
       at 'Breakeven Point'", 
       y = "Composite Tax Rate Change 
       (Percentage Points)", 
       title = "Market Value of Residential Property 'Breakeven Point' & 
       Composite Tax Rate Change from Elimination of GHE")

muni_taxrates%>%
      filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE")) %>%
  select(agency_name, nobillchange_propertyEAV, rate_change, everything()) %>%
 # filter(nobillchange_propertyEAV < 7000000) %>% 
  ggplot(aes(y=median_av, x = agency_name)) +
  geom_col()+
  #geom_text(aes(x =(nobillchange_propertyEAV), y = (median_eav+5000)), size = 1.5) +
  scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  labs(y = "Median Residential AV", x = "", title = "Median Residential Property Assessed Value - All Class 2 property Types")

muni_taxrates %>%
      filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE")) %>%

  select(agency_name, nobillchange_propertyEAV, rate_change, everything()) %>%
 # filter(nobillchange_propertyEAV < 7000000) %>% 
  ggplot(aes(y=median_av*10, x = agency_name)) +
  geom_col()+
  #geom_text(aes(x =(nobillchange_propertyEAV), y = (median_eav+5000)), size = 1.5) +
  scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  labs(y = "Median Residential Market Value", x = "", title = "Median Residential Market Value (AV*10) - All Class 2 property Types")

muni_taxrates %>%
      filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE")) %>%
  select(agency_name, nobillchange_propertyEAV, rate_change, everything()) %>%
  ggplot(aes(y=median_eav, x = agency_name)) +
  geom_col()+
  scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  labs(y = "Median Residential EAV", x = "", title = "Median Residential EAV - All Class 2 property Types")

muni_taxrates %>%
      filter(agency_name %in% c("VILLAGE OF GLENCOE", "VILLAGE OF WINNETKA")) %>%

  select(agency_name, nobillchange_propertyEAV, rate_change, everything()) %>%
  ggplot(aes(y=median_av, x = agency_name)) +
  geom_col()+
  scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  labs(y = "Median Residential AV", x = "", title = "Median Residential Property AV - All Class 2 property Types")

muni_taxrates %>%
      filter(agency_name %in% c("VILLAGE OF GLENCOE", "VILLAGE OF WINNETKA")) %>%

  select(agency_name, nobillchange_propertyEAV, rate_change, everything()) %>%
  ggplot(aes(y=median_av*10, x = agency_name)) +
  geom_col()+
  scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  labs(y = "Median Residential Market Value", x = "", title = "Median Residential Property Market Value - All Class 2 property Types")

muni_taxrates %>%
      filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE", "VILLAGE OF WINNETKA")) %>%
  select(agency_name, nobillchange_propertyEAV, rate_change, everything()) %>%
  ggplot(aes(y=nobillchange_propertyEAV, x = agency_name)) +
  geom_col()+
  scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  labs(y = "EAV of Class 2 Property w/ No Bill Change", x = "", title = "Breakeven points - EAV where taxbill wouldn't change if GHE were eliminated",
       caption = "Homeowners in municipalities with high tax rates and AV's much higher
       the median AV in the municipality properties see their bill decrease in GHE removal scenario. 
       These are extreme situations that should not be used for policy decisions or examples.")

muni_taxrates %>%
      filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF RIVERDALE", "VILLAGE OF WINNETKA")) %>%

  select(agency_name, nobillchange_propertyEAV, rate_change, everything()) %>%
  ggplot(aes(y=nobillchange_propertyEAV/3*10, x = agency_name)) +
  geom_col()+
  scale_y_continuous(labels = scales::dollar) +
  theme_classic() +
  labs(y = "Approximate Market Value of Class 2 Property", x = "", title = "Breakeven points - Value of home where taxbill wouldn't change",
       subtitle = "If General Homestead Exemption were Eiminated",
       caption = "A home valued above the points in the graph would experience a lower tax bill if the GHE were eliminated from all other properties.
       These are not the type of properties we are trying to help. Their taxbill going down is NOT a benefit in the big picture.")

EAV PIN distribution

pin_data2 %>%
  filter((class > 199 & class < 300) & agency_name == "VILLAGE OF PARK FOREST") %>% 
  ggplot() +
  geom_histogram(aes(x= eav, bins = 100))+
    geom_vline(aes(xintercept=median(eav, na.rm=TRUE), color = "red")) +
    theme_classic()+
  theme(legend.position = "none") + 
  geom_text(aes(x=(median(eav)+5000), y = 1500, label = median(eav))) +
   scale_x_continuous(limits = c(-5,100000)) +
#   scale_y_continuous(limits = c(0, 1500))+
  labs(title="Park Forest's PIN EAV distribution", x= "EAV", y = "Number of PINs")


pin_data2 %>%
  filter((class > 199 & class < 300) & agency_name == "VILLAGE OF RIVERDALE") %>% 
  ggplot() +
  geom_histogram(aes(x= eav, bins = 100))+
    geom_vline(aes(xintercept=median(eav, na.rm=TRUE), color = "red")) +
    theme_classic()+
  theme(legend.position = "none") + 
  geom_text(aes(x=(median(eav)+5000), y = 1500, label = median(eav))) +
   scale_x_continuous(limits = c(-5,100000)) +
#   scale_y_continuous(limits = c(0, 1500))+
  labs(title = "Riverdale's PIN EAV distribution", x = "EAV", y = "Number of PINs")


pin_data2 %>%
  filter((class > 199 & class < 300) & agency_name == "VILLAGE OF PHOENIX") %>% 
  ggplot() +
  geom_histogram(aes(x= eav, bins = 100))+
    geom_vline(aes(xintercept=median(eav, na.rm=TRUE), color = "red")) +
    theme_classic()+
  theme(legend.position = "none") + 
  geom_text(aes(x=(median(eav)+5000), y = 400, label = median(eav))) +
   scale_x_continuous(limits = c(-5,100000)) +
#   scale_y_continuous(limits = c(0, 1500))+
  labs(title="Phoenix's PIN EAV distribution", x = "EAV", y = "Number of PINs")


pin_data2 %>%
  filter((class > 199 & class < 300) & agency_name == "VILLAGE OF WINNETKA") %>% 
  ggplot() +
  geom_histogram(aes(x= eav, bins = 100))+
    geom_vline(aes(xintercept=median(eav, na.rm=TRUE), color = "red")) +
    theme_classic()+
  theme(legend.position = "none") + 
  geom_text(aes(x=(median(eav)+50000), y = 1500, label = median(eav))) +
   scale_x_continuous(limits = c(-5, 3000000), label = scales::dollar) +
#   scale_y_continuous(limits = c(0, 1500))+
  labs(title="Winnetka's PIN EAV distribution", x="EAV", y = "Number of PINs")

Bill Distributions

pin_data2 %>%
  filter(major_class_code == 2 & bill_current < 30000 & agency_name == "VILLAGE OF PARK FOREST") %>% ggplot() +
  geom_histogram(aes(x= bill_current, bins = 100))+
    geom_vline(aes(xintercept=median(bill_current, na.rm=TRUE), color = "red")) +
    theme_classic()+theme(legend.position = "none") + 

  scale_x_continuous(limits = c(-5,20000), label = scales::dollar) +
  scale_y_continuous(limits = c(0, 1500), label = scales::comma)+
  labs(x="PF's Actual Tax Bills With Current Exemptions", y = "Number of Tax Bills")


pin_data2 %>%
  group_by(has_HO_exemp) %>%
  filter(major_class_code == 2 & bill_current < 30000 & agency_name == "VILLAGE OF PARK FOREST") %>% ggplot() +
  geom_histogram(aes(x= bill_current, bins = 100))+
    theme_classic()+theme(legend.position = "none") + 
  scale_x_continuous(limits = c(-5,20000), label = scales::dollar) +
  scale_y_continuous(limits = c(0, 1500), label = scales::comma)+
  labs(x="PF's Actual Tax Bills With Current Exemptions", y = "Number of Tax Bills") +
  facet_wrap(~has_HO_exemp)

pin_data2 %>%
  filter(major_class_code == 2 & bill_noexemps < 30000 & agency_name == "VILLAGE OF PARK FOREST") %>% ggplot() +
  geom_histogram(aes(x= bill_noexemps, bins = 100))+
    geom_vline(aes(xintercept=median(bill_noexemps, na.rm=TRUE), color = "red")) +
    theme_classic()+theme(legend.position = "none") + 

  scale_x_continuous(limits = c(-5,20000), label = scales::dollar) + 
    scale_y_continuous(limits = c(0, 1500), label = scales::comma)+

  labs(x="PF's Tax Bills Without General Homestead Exemptions", y = "Number of Tax Bills")

pin_data2 %>%
  filter(major_class_code == 2 & agency_name == "VILLAGE OF PHOENIX") %>% ggplot() +
  geom_histogram(aes(x= bill_current, bins = 100))+
    geom_vline(aes(xintercept=median(bill_current, na.rm=TRUE), color = "red")) +
    theme_classic()+theme(legend.position = "none") + 

  scale_x_continuous(limits = c(-5,20000)) + 
   scale_y_continuous(limits = c(0, 600))+

  labs(title="PHOENIX's Current Tax Bill Distribution", x = "Dollars", y = "Number of Tax Bills")

pin_data2 %>%
  filter(major_class_code == 2 & agency_name == "VILLAGE OF PHOENIX") %>% ggplot() +
  geom_histogram(aes(x= bill_noexemps, bins = 100))+
    geom_vline(aes(xintercept=median(bill_noexemps, na.rm=TRUE), color = "red")) +
    theme_classic()+theme(legend.position = "none") + 

  scale_x_continuous(limits = c(-5,20000)) + 
    scale_y_continuous(limits = c(0, 600))+

  labs(title="PHOENIX's Tax Bills Without General Homestead Exemptions", y = "Number of Tax Bills")

pin_data2 %>%
  filter(major_class_code == 2 & agency_name == "VILLAGE OF WINNETKA") %>% ggplot() +
  geom_histogram(aes(x= bill_current, bins = 100))+
    geom_vline(aes(xintercept=median(bill_current, na.rm=TRUE), color = "red")) +
    theme_classic()+theme(legend.position = "none") + 

 # scale_x_continuous(limits = c(-5,20000)) +
 # scale_y_continuous(limits = c(0, 80000)) +
  labs(title="WINNETKA's Actual Tax Bills With Current Exemptions", x= "Dollars", y = "Number of Tax Bills")

pin_data2 %>%
  filter(major_class_code == 2  & agency_name == "VILLAGE OF WINNETKA") %>% ggplot() +
  geom_histogram(aes(x= bill_noexemps, bins = 100))+
    geom_vline(aes(xintercept=median(bill_noexemps, na.rm=TRUE), color = "red")) +
    theme_classic()+theme(legend.position = "none") + 

  #scale_x_continuous(limits = c(-5,20000)) + 
  #scale_y_continuous(limits = c(0, 80000)) +

  labs(title="WINNETKA's Tax Bills Without General Homestead Exemptions", x="Dollars", y = "Number of Tax Bills")

pin_data2 %>%
  filter(major_class_code == 2 & agency_name == "VILLAGE OF PARK FOREST") %>% 
  ggplot() +
  geom_histogram(aes(x= bill_change, bins = 100))+
    geom_vline(aes(xintercept=median(bill_change, na.rm=TRUE), color = "red")) +
    theme_classic()+
  theme(legend.position = "none") + 
    scale_x_continuous(limits = c(-10000,10000)) +

#   scale_y_continuous(limits = c(0, 2000))+
  labs(title="Park Forest's Change in Tax Bills", subtitle =  "Hypothetical with no General Homestead Exemptions", x = "Change in Tax Bill ($)", y = "Number of Tax Bills")

pin_data2 %>%
  filter(major_class_code == 2 & agency_name == "VILLAGE OF PHOENIX") %>% ggplot() +
  geom_histogram(aes(x= bill_change, bins = 100))+
    geom_vline(aes(xintercept=median(bill_change, na.rm=TRUE), color = "red")) +
    theme_classic()+ theme(legend.position = "none") + 
   scale_x_continuous(limits = c(-10000,10000)) +

#   scale_x_continuous(limits = c(-2800,2800)) + 
#   scale_y_continuous(limits = c(0, 2000))+

  labs(title ="PHOENIX's Change in Tax Bills", subtitle = "Hypothetical with no General Homestead Exemptions", x = "Change in Tax Bill ($)", y = "Number of Tax Bills")

pin_data2 %>%
  filter(major_class_code == 2 & agency_name == "VILLAGE OF WINNETKA") %>% ggplot() +
  geom_histogram(aes(x= bill_change, bins = 100))+
    geom_vline(aes(xintercept=median(bill_change, na.rm=TRUE), color = "red")) +
    theme_classic()+theme(legend.position = "none") + 
   scale_x_continuous(limits = c(-10000,10000)) +

#  scale_x_continuous(limits = c(-5,20000)) + 
#    scale_y_continuous(limits = c(0, 1500))+

  labs(title="WINNETKA's Change in Tax Bills Without General Homestead Exemptions", y = "Number of Tax Bills", x = "Dollars")

pin_data2 %>%
  filter(major_class_code == 2 & agency_name == "VILLAGE OF RIVERDALE") %>% ggplot() +
  geom_histogram(aes(x= bill_change, bins = 100))+
    geom_vline(aes(xintercept=median(bill_change, na.rm=TRUE), color = "red")) +
    theme_classic()+
  theme(legend.position = "none") + 
   scale_x_continuous(limits = c(-10000,10000)) +
labs(title="RIVERDALE's Change in Tax Bills Without General Homestead Exemptions", y = "Number of Tax Bills", x = "Dollars")

pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA")) %>%
  filter(class >199 & class < 300) %>% 
  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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, zero_bill, has_HO_exemp) %>% 
  summarize(median_AV = median(av),
            median_EAV = median(eav),
            mean_bill_cur = mean(bill_current, na.rm=TRUE),
            median_bill_cur = median(bill_current),
            mean_bill_new = mean(bill_noexemps, na.rm=TRUE),
            median_bill_new = median(bill_noexemps),
            mean_change = mean(bill_change, na.rm=TRUE),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n()
)
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  filter(class >199 & class < 300) %>% 
  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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, has_HO_exemp) %>% 
  summarize(median_AV = median(av),
            median_EAV = median(eav),
            mean_bill_cur = mean(bill_current, na.rm=TRUE),
            median_bill_cur = median(bill_current),
            mean_bill_new = mean(bill_noexemps, na.rm=TRUE),
            median_bill_new = median(bill_noexemps),
            mean_change = mean(bill_change, na.rm=TRUE),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n()
)
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA","VILLAGE OF RIVERDALE")) %>%
  filter(class >199 & class < 300) %>% 
  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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name) %>% 
  summarize(median_AV = median(av),
            median_EAV = median(eav),
            mean_bill_cur = mean(bill_current, na.rm=TRUE),
            median_bill_cur = median(bill_current),
            mean_bill_new = mean(bill_noexemps, na.rm=TRUE),
            median_bill_new = median(bill_noexemps),
            mean_change = mean(bill_change, na.rm=TRUE),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n()
)
tax_bill_change_HO <- pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  filter(class == 203) %>% 
  arrange(av) %>%
    mutate(bill_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, has_HO_exemp) %>% 
  summarize(median_AV = median(av),
            median_EAV = median(eav),
            median_bill_cur = round(median(bill_current)),
            median_bill_new = round(median(bill_noexemps)),
            median_change = round(median(bill_change)),
            pincount=n(),
            perceived_savings = median(tax_amt_exe))

tax_bill_change_HO
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
    filter(class == 203) %>% 
  arrange(av) %>%
  mutate(median_EAV = median(eav),
            median_bill_cur = round(median(bill_current)),
            median_bill_new = round(median(bill_noexemps)),
            median_change = round(median(bill_change)),
            pincount=n(),
            perceived_savings = median(tax_amt_exe))
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  filter(class == 203) %>% 
  arrange(av) %>%
    mutate(bill_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, zero_bill, has_HO_exemp) %>% 
  summarize(median_AV = median(av),
            median_EAV = median(eav),
            median_bill_cur = round(median(bill_current)),
            median_bill_new = round(median(bill_noexemps)),
            median_change = round(median(bill_change)),
            pincount=n(),
            perceived_savings = median(tax_amt_exe))

If only “removing”/“refunding” the general homestead exemption:

For Park Forest class 203 properties, the median tax bill would go down $2,088 for those who don’t currently have a general homestead exemption and would increase $2,314 for people who do currently claim the general homestead exemption. 779 people don’t claim the exemption and 1398 people do. A home with EAV above 88,298 EAV would experience a lower tax bill and homes below 88,298 EAV would experience an increase in their taxbill. The median EAV for all class 2 properties is 18,320 in Park Forest.

Phoenix class 203 median properties have a decrease of $1,481 if they didn’t claim homestead exemptions currently and increased $1,468 f they did already claim the general homestead exemption. 137 people do not claim the exemption and 209 people do claim the general homestead exemption. A home with EAV above 79,946 EAV would experience a lower tax bill and homes below 29,946 EAV would experience an increase in their taxbill. The median EAV for all class 2 properties is 10,515 in Phoenix.

Riverdale class 203 median properties have a decrease of $2095 if they didn’t claim homestead exemptions currently and increased $1,155 f they did already claim the general homestead exemption. 209 people do not claim the exemption and 443 people do claim the general homestead exemption. A home with EAV above 170,261 EAV would experience a lower tax bill and homes below 170,261 EAV would experience an increase in their taxbill.

The median EAV for all Class 2 properties is 17,163 in Riverdale.

Winnetka class 203 median properties have a decrease of $281 if they didn’t claim homestead exemptions currently and increased $608 f they did already claim the general homestead exemption. 37 people do not claim the exemption and 91 people do claim the general homestead exemption. A home with EAV above 5,159,327 EAV would experience a lower tax bill and homes below 5,159,327 EAV would experience an increase in their taxbill. The median EAV for all Class 2 properties is 249,018 EAV in Winnetka.

Muni Comparison of AVs and Tax Bills

Compare AV=10,000

pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  filter(class > 199 & class < 300) %>% 
  arrange(av) %>%
    filter(av > 9500 & av < 10500) %>%

 # 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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, zero_bill, has_HO_exemp) %>% 
  summarize(median_AV = median(av),
            median_EAV = median(eav),
            median_bill_cur = median(bill_current),
            median_bill_new = median(bill_noexemps),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n()
)
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  filter(class >199 & class < 300) %>% 
  arrange(av) %>%
    filter(av > 9500 & av < 10500) %>%

 # 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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, has_HO_exemp) %>% 
    summarize(median_AV = median(av),
            median_equalizedAV =  median(equalized_AV),
            median_EAV = median(eav),
            median_bill_cur = median(bill_current),
            median_bill_new = median(bill_noexemps),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n()
)
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  filter(class >199 & class < 300) %>% 
  arrange(av) %>%
  filter(av > 9500 & av < 10500) %>%
 # 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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name) %>% 
    summarize(median_AV = median(av),
            median_equalizedAV =  median(equalized_AV),
            median_EAV = median(eav),
            median_bill_cur = median(bill_current),
            median_bill_new = median(bill_noexemps),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n()
)

Class 203 only

pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  filter(class ==203) %>% 
  arrange(av) %>%
  filter(av > 9500 & av < 10500) %>%
 # 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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name)
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  filter(class == 203) %>% 
  arrange(av) %>%
  filter(av > 9500 & av < 10500) %>%
 # 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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name) %>%
    summarize(median_AV = median(av),
            median_equalizedAV =  median(equalized_AV),
            median_EAV = median(eav),
            median_bill_cur = median(bill_current),
            median_bill_new = median(bill_noexemps),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n()
)
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
  filter(class == 203) %>% 
  arrange(av) %>%
  filter(av > 9500 & av < 10500) %>%
 # 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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, has_HO_exemp) %>%
    summarize(median_AV = median(av),
            median_equalizedAV =  median(equalized_AV),
            median_EAV = median(eav),
            median_bill_cur = median(bill_current),
            median_bill_new = median(bill_noexemps),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n()
)
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX",  "VILLAGE OF RIVERDALE")) %>%
 filter(class == 203) %>% 
# filter(class >199 & class < 300) %>% 

  arrange(av) %>%
  filter(av > 9000 & av < 11000) %>%
 # 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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, has_HO_exemp) %>%
    summarize(median_AV = median(av),
            median_equalizedAV =  median(equalized_AV),
            taxable_eav = mean(equalized_AV-all_exemptions+exe_homeowner),
            median_bill_cur = median(bill_current),
            median_bill_new = median(bill_noexemps),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n()
)

Export Data for All Municipalities

Exported file uses an AV of 15000 for the PIN AV range

# 
# ## AV range around 10000, all Class 2
# 
# pin_data2 %>% 
# filter(pin_AV > 0) %>% 
#   filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX",  "VILLAGE OF RIVERDALE")) %>%
#  # filter(class == 203) %>% 
#  filter(class >199 & class < 300) %>% 
# 
#   arrange(av) %>%
#   filter(av > 9000 & av < 11000) %>%
#  # 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_current = (final_tax_to_dist + final_tax_to_tif),
#          bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
#          bill_change = bill_noexemps - bill_current) %>%
#   group_by(agency_name, has_HO_exemp) %>%
#     summarize(median_AV = median(av),
#             median_equalizedAV =  median(equalized_AV),
#             taxable_eav = mean(equalized_AV-all_exemptions+exe_homeowner),
#             median_bill_cur = median(bill_current),
#             median_bill_new = median(bill_noexemps),
#             median_change = median(bill_change),
#             perceived_savings = median(tax_amt_exe),
#             cur_comp_TC_rate = mean(cur_comp_TC_rate),
#             new_comp_TC_rate = mean(new_comp_TC_rate),
#             class = first(class),
#             pincount=n()
# )
# #write_csv(medianEAVs_inMunis, "requests_medianEAV_inMunis.csv" )


## AV range around $15,000, all Class 2
pin_data2 %>% 
filter(pin_AV > 0) %>% 
 filter(class >199 & class < 300) %>% 

  arrange(av) %>%
  filter(av > 14000 & av < 16000) %>%
  mutate(
         # current bill = current tax rate * portion of levy billed
         bill_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, has_HO_exemp) %>%
    summarize(median_AV = median(av),
            median_equalizedAV =  median(equalized_AV),
            taxable_eav = mean(equalized_AV-all_exemptions+exe_homeowner),
            median_bill_cur = median(bill_current),
            median_bill_new = median(bill_noexemps),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            class = mode(class),
            pincount=n()) # %>% write_csv("requests_av15000_allMunis.csv")
# Calculations for bill change the median EAV in each muni
medianEAVs_inMunis <- pin_data2 %>% 
  filter(pin_AV > 0) %>% 
  filter(class >199 & class < 300) %>% 
  arrange(av) %>%
  mutate(
    # current bill = current tax rate * portion of levy billed
    bill_current = (final_tax_to_dist + final_tax_to_tif),
    bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
    bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, has_HO_exemp) %>%
  summarize(median_AV = median(av),
            median_equalizedAV =  median(equalized_AV),
            taxable_eav = mean(equalized_AV-all_exemptions+exe_homeowner),
            median_bill_cur = median(bill_current),
            median_bill_new = median(bill_noexemps),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n())

# Bill change calculations for properties with AVs of $150,000
pin_data2 %>% 
filter(pin_AV > 0) %>% 
 filter(class >199 & class < 300) %>% 
  arrange(av) %>%
  filter(av > 140000 & av < 160000) %>%
  mutate(
         # current bill = current tax rate * portion of levy billed
         bill_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name, has_HO_exemp) %>%
    summarize(median_AV = median(av),
            median_equalizedAV =  median(equalized_AV),
            taxable_eav = mean(equalized_AV-all_exemptions+exe_homeowner),
            median_bill_cur = median(bill_current),
            median_bill_new = median(bill_noexemps),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            class = first(class),
            pincount=n()) # %>% write_csv("requests_av150000_allMunis.csv")
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("VILLAGE OF PARK FOREST", "VILLAGE OF PHOENIX", "VILLAGE OF WINNETKA", "VILLAGE OF RIVERDALE")) %>%
#  filter(class == 203) %>% 
    filter(class >199 & class < 300) %>% 

  arrange(av) %>%
  filter(av > 14500 & av < 15500) %>%
 # 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_current = (final_tax_to_dist + final_tax_to_tif),
         bill_noexemps =  new_comp_TC_rate/100*(equalized_AV-all_exemptions+exe_homeowner),
         bill_change = bill_noexemps - bill_current) %>%
  group_by(agency_name) %>%
    summarize(median_AV = median(av),
            median_equalizedAV =  median(equalized_AV),
            taxable_eav = mean(equalized_AV-all_exemptions+exe_homeowner),
            median_bill_cur = median(bill_current),
            median_bill_new = median(bill_noexemps),
            median_change = median(bill_change),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = mean(cur_comp_TC_rate),
            new_comp_TC_rate = mean(new_comp_TC_rate),
            pincount=n()
)
LS0tDQp0aXRsZTogJ0h5cG90aGV0aWNhbCBUYXhiaWxsczogUmVtb3ZlIEdlbmVyYWwgSG9tZXN0ZWFkIEV4ZW1wdGlvbnMnDQphdXRob3I6ICJBV00iDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQotLS0NCg0KYGBge3Igc2V0dXAsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQ0KDQoNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShnc3RhdCkNCmxpYnJhcnkocHRheHNpbSkNCmxpYnJhcnkoZ2x1ZSkNCg0KDQoNCmBgYA0KDQojIEJyaW5nIGluIGRhdGENCg0KQmlsbHMgd2VyZSBwdWxsZWQgZnJvbSBQVEFYU0lNIGFtZCBzdW1tZWQgdG8gdGhlIHBpbiBsZXZlbCBpbiBmaWxlcyBgMV8uLi5ybWRgIGFuZCBgMi4uLnJtZGAuDQpFeGVtcHRpb24gZGF0YSBwZXIgUElOIHdhcyBwdWxsZWQgZnJvbSBQVEFYU0lNIGluIGZpbGUgYDNfLi4uLi5ybWRgLg0KDQpgYGB7cn0NCnB0YXhzaW1fZGJfY29ubiA8LSBEQkk6OmRiQ29ubmVjdChSU1FMaXRlOjpTUUxpdGUoKSwgIi4vcHRheHNpbS5kYi9wdGF4c2ltLTIwMjEuMC40LmRiIikNCg0KZXFfZmFjdG9yIDwtIERCSTo6ZGJHZXRRdWVyeSgNCiAgcHRheHNpbV9kYl9jb25uLA0KICAiU0VMRUNUKg0KICBGUk9NIGVxX2ZhY3Rvcg0KICAiDQopDQoNCm11bmlfYWdlbmN5X25hbWVzIDwtIERCSTo6ZGJHZXRRdWVyeSgNCiAgcHRheHNpbV9kYl9jb25uLA0KICAiU0VMRUNUIERJU1RJTkNUIGFnZW5jeV9udW0sIGFnZW5jeV9uYW1lLCBtaW5vcl90eXBlDQogIEZST00gYWdlbmN5X2luZm8NCiAgV0hFUkUgbWlub3JfdHlwZSA9ICdNVU5JJw0KICBPUiBhZ2VuY3lfbnVtID0gJzAyMDA2MDAwMCcgIA0KDQogICINCikNCg0KbXVuaV90YXhfY29kZXMgPC0gREJJOjpkYkdldFF1ZXJ5KA0KICBwdGF4c2ltX2RiX2Nvbm4sDQogIGdsdWVfc3FsKCINCiAgU0VMRUNUIERJU1RJTkNUIGFnZW5jeV9udW0sIHRheF9jb2RlX251bQ0KICBGUk9NIHRheF9jb2RlDQogIFdIRVJFIGFnZW5jeV9udW0gSU4gKHttdW5pX2FnZW5jeV9uYW1lcyRhZ2VuY3lfbnVtKn0pDQogIEFORCB5ZWFyID0gMjAyMQ0KICAiLA0KICAuY29uID0gcHRheHNpbV9kYl9jb25uDQogICkNCikgJT4lIA0KICBtdXRhdGUodGF4X2NvZGVfbnVtID0gYXMubnVtZXJpYyh0YXhfY29kZV9udW0pKQ0KDQp0YXhfY29kZXMgPC0gREJJOjpkYkdldFF1ZXJ5KA0KICBwdGF4c2ltX2RiX2Nvbm4sDQogIGdsdWVfc3FsKCINCiAgU0VMRUNUIERJU1RJTkNUIHRheF9jb2RlX251bSwgdGF4X2NvZGVfcmF0ZQ0KICBGUk9NIHRheF9jb2RlDQogIFdIRVJFIHllYXIgPSAyMDIxDQogICIsDQogIC5jb24gPSBwdGF4c2ltX2RiX2Nvbm4NCiAgKQ0KKSAlPiUgbXV0YXRlKHRheF9jb2RlX251bSA9IGFzLm51bWVyaWModGF4X2NvZGVfbnVtKSkNCmBgYA0KDQpgYGB7ciBldmFsID0gRkFMU0V9DQp0YXhiaWxsc19jdXJyZW50IDwtIHJlYWRfY3N2KCIuL091dHB1dC9Eb250X1VwbG9hZC8xX0dldF9BbGxfUGlucy1Db29rUGluVGF4YmlsbHNfMjAyMV9BY3R1YWwuY3N2IikNCiMgMjIsNDUzLDg3NSB0YXggYmlsbHMgaW4gMjAyMSBpbiBtdW5pY2lwYWxpdGllcy4gDQojIHRheGluZyBhZ2VuY3ktUElOIGlzIHRoZSB1bml0IG9mIG9ic2VydmF0aW9uIGhlcmUgKG9ubHkgcGFydGlhbCBwcm9wZXJ0eSB0YXggYmlsbHMpDQojIEVhY2ggUElOIGhhcyBtdWx0aXBsZSByb3dzIChiZWNhdXNlIGl0IGlzIHRheGVkIGJ5IG11bHRpcGxlIHRheGluZyBhZ2VuY2llcykNCg0Kc2FwcGx5KHRheGJpbGxzX2N1cnJlbnQsIGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpDQoNCg0KIyAxLDgyNSw4MTYgYmlsbGVkIHByb3BlcnRpZXMgd2l0aCAxNC1kaWdpdCBQSU5zIGluIGluY29yb3JhdGVkIGFyZWFzDQojIDEsODY0LDU5NCBpbiBpbmNvcnBvcnRlZCBhbmQgdW5pbmNvcnBvcmF0ZWQgYXJlYXMuDQpwaW4xNF9iaWxsc19jdXJyZW50IDwtIHRheGJpbGxzX2N1cnJlbnQgJT4lDQogIGdyb3VwX2J5KHRheF9jb2RlLCBjbGFzcywgcGluKSAlPiUNCiAgDQogIG11dGF0ZSh0b3RhbF9iaWxsID0gZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSAlPiUgIyBmcm9tIGVhY2ggdGF4aW5nIGFnZW5jeQ0KICANCiAgc3VtbWFyaXplKA0KICAgIHRvdGFsX2JpbGxlZCA9IHN1bSh0b3RhbF9iaWxsLCBuYS5ybSA9IFRSVUUpLCAjIHRvdGFsIG9uIHNvbWVvbmUncyBwcm9wZXJ0eSB0YXggYmlsbA0KICAgIGF2ID0gZmlyc3QoYXYpLA0KICAgIGVhdiA9IGZpcnN0KGVhdiksDQogICAgIyBwaW5fY291bnRfaW5fcGFyY2VsID0gbigpLA0KICAgIGZpbmFsX3RheF90b19kaXN0ID0gc3VtKGZpbmFsX3RheF90b19kaXN0LCBuYS5ybSA9IFRSVUUpLA0KICAgIGZpbmFsX3RheF90b190aWYgPSBzdW0oZmluYWxfdGF4X3RvX3RpZiwgbmEucm0gPSBUUlVFKSwNCiAgICB0YXhfYW10X2V4ZSA9IHN1bSh0YXhfYW10X2V4ZSwgbmEucm0gPSBUUlVFKSwgIyByZXZlbnVlIGxvc3QgZHVlIHRvIGV4ZW1wdGlvbnMNCiAgICB0YXhfYW10X3ByZV9leGUgPSBzdW0odGF4X2FtdF9wcmVfZXhlLCBuYS5ybSA9IFRSVUUpLCAjIHRvdGFsIHJldiBiZWZvcmUgYWxsIGV4ZW1wdGlvbnMNCiAgICB0YXhfYW10X3Bvc3RfZXhlID0gc3VtKHRheF9hbXRfcG9zdF9leGUsIG5hLnJtID0gVFJVRSksICMgdG90YWwgcmV2IGFmdGVyIGFsbCBleGVtcHRpb25zDQogICAgcnBtX3RpZl90b19jcHMgPSBzdW0ocnBtX3RpZl90b19jcHMsIG5hLnJtID0gVFJVRSksICMgbm90IHVzZWQNCiAgICBycG1fdGlmX3RvX3JwbSA9IHN1bShycG1fdGlmX3RvX3JwbSwgbmEucm09VFJVRSksICMgbm90IHVzZWQNCiAgICBycG1fdGlmX3RvX2Rpc3QgPSBzdW0ocnBtX3RpZl90b19kaXN0LCBuYS5ybT1UUlVFKSwgIyBub3QgdXNlZA0KICAgIHRpZl9zaGFyZSA9IG1lYW4odGlmX3NoYXJlLCBuYS5ybT1UUlVFKSwgIyBub3QgdXNlZA0KICApICAlPiUgDQogIG11dGF0ZShwcm9wY2xhc3NfMWRpZyA9IHN0cl9zdWIoY2xhc3MsIDEsIDEpKQ0KDQojIGhlYWQocGluMTRfYmlsbHNfY3VycmVudCkNCg0Kc2FwcGx5KHBpbjE0X2JpbGxzX2N1cnJlbnQsIGZ1bmN0aW9uKHgpIHN1bShpcy5uYSh4KSkpDQoNCg0KIyBOb3cgZ3JvdXAgYWdhaW4gYW5kIHN1bSB2YWx1ZXMgZm9yIHRheCBjb2RlIGFuZCBlYWNoIHByb3BlcnR5IGNsYXNzIQ0KDQojIFRoZXJlIGFyZSAyOCwzODEgcHJvcGVydHkgY2xhc3MgLSB0YXggY29kZSBncm91cCBjb21iaW5hdGlvbnMgaW4gaW5jb3Jwb3JhdGVkIGFyZWFzLg0KIyBUaGVyZSBhcmUgMjgsNTM0IHByb3BlcnR5IGNsYXNzIC0gdGF4IGNvZGUgZ3JvdXAgY29tYm9zIGluIGluY29ycG9yYXRlZCArIHVuaW5jb3Jwb3JhdGVkIGFyZWFzDQoNCnJtKHRheGJpbGxzX2N1cnJlbnQpDQpgYGANCg0KIyBBZGQgZXhlbXB0aW9uIHR5cGVzIHRvIHBpbiBsZXZlbCB0YXggYmlsbHMNCg0KTmVlZCB0byBtZXJnZSBQSU4gbGV2ZWwgZGF0YSBvZiB0YXggYmlsbHMgYW5kIGV4ZW1wdGlvbnMgcGVyIFBJTiBpZiB0aGUgZ29hbCBpcyB0byBjYWxjdWxhdGUgbmV3IHRheCByYXRlcyBmb3IgZGlmZmVyZW50IHNjZW5hcmlvcyBBTkQgdmlldyBpbmRpdmlkdWFsIGxldmVsIHRheCBiaWxsIGNoYW5nZXMuIChpLmUuIGlmIHdlIHdhbnQgdG8gbG9vayBhdCB0aGUgIm1lZGlhbiB0YXhwYXllciIgdGhlbiBuZWVkIHRvIHVzZSB0aGlzIG1ldGhvZCkuDQoNCk5vdGU6IFRoZSBFQVYgZnJvbSB0aGUgZXhlbXB0aW9uIHRhYmxlIGlzIHRoZSBvcmlnaW5hbCBFQVYgKEFWIFwqIGVxdWFsaXplcikgd2l0aG91dCBjb25zaWRlciBUSUZzIG9yIGV4ZW1wdGlvbnMuDQoNCjMxLDAwMCBwcm9wZXJ0aWVzIGhhdmUgJDAgdGF4IGJpbGxzIGJhc2VkIG9uIGV4ZW1wdGlvbiBkYXRhIHRhYmxlIG1hZGUgZnJvbSBQVEFYU0lNJ3MgYHBpbmAgdGFibGUuIA0KKFVzaW5nIHRoZSB0YXggYmlsbCBkYXRhIGFsbG93cyBmb3IgbW9yZSBpbiBkZXB0aCBsb29rIGF0IHRheCBiaWxscyBhbmQgY2FuIGNyZWF0ZSB2YXJpYWJsZXMgc3VjaCBhcyBgc21hbGxfYmlsbGAgaWYgYmlsbHMgd2VyZSBsZXNzIHRoYW4gJDEwMCBhZnRlciBleGVtcHRpb25zIHdlcmUgYXBwbGllZCkuIA0KDQpgYGB7ciBldmFsID0gRkFMU0V9DQpwaW5fZWF2IDwtIHJlYWRfY3N2KCIuL091dHB1dC9Eb250X1VwbG9hZC8zX0V4ZW1wdGlvbl9EZXRhaWxzX291dHB1dC1hbGxfY29va19waW5fZXhlbXB0aW9uc18yMDIxX2FjdHVhbC5jc3YiKSAlPiUNCiAgI2ZpbHRlcihjbGFzc19jb2RlICE9MCkgJT4lDQogIA0KICBtdXRhdGUoYWxsX2V4ZW1wdGlvbnMgPSBleGVfaG9tZW93bmVyICsgZXhlX3NlbmlvciArIGV4ZV9mcmVlemUgKyBleGVfbG9uZ3RpbWVfaG9tZW93bmVyICsgDQogICAgICAgICAgIGV4ZV9kaXNhYmxlZCArIGV4ZV92ZXRfcmV0dXJuaW5nICsgZXhlX3ZldF9kaXNfbHQ1MCArIGV4ZV92ZXRfZGlzXzUwXzY5ICsgZXhlX3ZldF9kaXNfZ2U3MCArIGV4ZV9hYmF0ZSkgJT4lDQogIG11dGF0ZSh6ZXJvX2JpbGwgPSBpZmVsc2UoZWF2IDw9IGFsbF9leGVtcHRpb25zLCAxLCAwKSwNCiAgICAgICAgIGhhc19IT19leGVtcCA9IGlmZWxzZShleGVfaG9tZW93bmVyID4gMCwgMSwgMCkpICU+JQ0KICByZW5hbWUoZXF1YWxpemVkX0FWID0gZWF2LA0KICAgICAgICAgcGluX0FWID0gYXYpDQoNCiMgdGFibGUocGluX2VhdiR6ZXJvX2JpbGwpDQoNCnRhYmxlKHBpbl9lYXYkbWFqb3JfY2xhc3NfY29kZSwgcGluX2VhdiR6ZXJvX2JpbGwpDQoNCiMgdGFibGUocGluX2VhdiRtYWpvcl9jbGFzc19jb2RlLCBwaW5fZWF2JGhhc19IT19leGVtcCkNCg0KDQoNCiMjIEFkZCBleGVtcHRpb24gdHlwZXMgYW5kIHZhbHVlcyB0byB0aGUgdGF4IGJpbGwgZGF0YSBhdCBQSU4gbGV2ZWwNCnBpbl9kYXRhIDwtIGxlZnRfam9pbihwaW4xNF9iaWxsc19jdXJyZW50LCBwaW5fZWF2LCBieSA9IGMoInBpbiIsICJjbGFzcyIgPSAiY2xhc3NfY29kZSIgKSkNCg0KIyMgQWRkIHRheCBjb2RlIHRheCByYXRlIHRvIFBJTiBsZXZlbCBkYXRhDQpwaW5fZGF0YSA8LSBsZWZ0X2pvaW4ocGluX2RhdGEsIHRheF9jb2RlcywgYnkgPSBjKCJ0YXhfY29kZSIgPSAidGF4X2NvZGVfbnVtIikpDQoNCg0KDQpgYGANCg0KDQoNCg0KIyMgQ2FsY3VsYXRlIG5ldyB0YXggcmF0ZXMNCg0KDQoNCmBgYHtyIHRheGNvZGUtdGF4cmF0ZXMsIGV2YWwgPSBGQUxTRX0NCiMgdGF4Y29kZXNfYnlfY2xhc3NfY3VycmVudCA8LSBwaW5fZGF0YSAlPiUgDQojICAgZ3JvdXBfYnkodGF4X2NvZGUsIGNsYXNzKSAgJT4lDQojICAgDQojICAgc3VtbWFyaXplKA0KIyAgICAgYXYgPSBzdW0oYXYpLA0KIyAgICAgZWF2ID0gc3VtKGVhdiksDQojICAgICBlcXVhbGl6ZWRfQVYgPSBzdW0oZXF1YWxpemVkX0FWKSwNCiMgICAgIHBpbnNfaW5fY2xhc3MgPSBuKCksDQojICAgICBjdXJyZW50X2V4ZW1wdGlvbnMgPSBzdW0oYWxsX2V4ZW1wdGlvbnMpLA0KIyAgICAgSE9fZXhlbXBzID0gc3VtKGV4ZV9ob21lb3duZXIpLA0KIyAgICAgdGF4X2NvZGVfcmF0ZSA9IGZpcnN0KHRheF9jb2RlX3JhdGUpLA0KIyAgICAgZmluYWxfdGF4X3RvX2Rpc3QgPSBzdW0oZmluYWxfdGF4X3RvX2Rpc3QsIG5hLnJtID0gVFJVRSksICMgdXNlZCBhcyBMRVZZIGFtb3VudCEhIA0KIyAgICAgZmluYWxfdGF4X3RvX3RpZiA9IHN1bShmaW5hbF90YXhfdG9fdGlmLCBuYS5ybSA9IFRSVUUpLA0KIyAgICAgdGF4X2FtdF9leGUgPSBzdW0odGF4X2FtdF9leGUsIG5hLnJtID0gVFJVRSksIA0KIyAgICAgdGF4X2FtdF9wcmVfZXhlID0gc3VtKHRheF9hbXRfcHJlX2V4ZSwgbmEucm0gPSBUUlVFKSwgDQojICAgICB0YXhfYW10X3Bvc3RfZXhlID0gc3VtKHRheF9hbXRfcG9zdF9leGUsIG5hLnJtID0gVFJVRSksDQojICAgICBycG1fdGlmX3RvX2NwcyA9IHN1bShycG1fdGlmX3RvX2NwcywgbmEucm0gPSBUUlVFKSwgIyBub3QgdXNlZA0KIyAgICAgcnBtX3RpZl90b19ycG0gPSBzdW0ocnBtX3RpZl90b19ycG0sIG5hLnJtPVRSVUUpLCAjIG5vdCB1c2VkDQojICAgICBycG1fdGlmX3RvX2Rpc3QgPSBzdW0ocnBtX3RpZl90b19kaXN0LCBuYS5ybT1UUlVFKSwgIyBub3QgdXNlZA0KIyAgICAgdGlmX3NoYXJlID0gbWVhbih0aWZfc2hhcmUsIG5hLnJtPVRSVUUpLCAjIG5vdCB1c2VkDQojICAgKSAlPiUNCiMgICANCiMgICBtdXRhdGUodG90YWxfYmlsbF9jdXJyZW50ID0gZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSAlPiUNCiMgICByZW5hbWUoY3VyX2NvbXBfVENfcmF0ZSA9IHRheF9jb2RlX3JhdGUpICU+JQ0KIyAgIG11dGF0ZShjdXJyZW50X3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QvKGN1cl9jb21wX1RDX3JhdGUvMTAwKSwNCiMgICAgICAgICAgbmV3X3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QvKGN1cl9jb21wX1RDX3JhdGUvMTAwKSArIEhPX2V4ZW1wcykgJT4lDQojICAgbXV0YXRlKG5ld19jb21wX1RDX3JhdGUgPSAoZmluYWxfdGF4X3RvX2Rpc3QgLyBuZXdfdGF4YWJsZV9lYXYpKjEwMCkgJT4lDQojICAgbXV0YXRlKG5ld19jb21wX1RDX3JhdGUgPSBpZmVsc2UoaXMubmFuKG5ld19jb21wX1RDX3JhdGUpLCBjdXJfY29tcF9UQ19yYXRlLCBuZXdfY29tcF9UQ19yYXRlKSkgJT4lDQojICAgc2VsZWN0KHRheF9jb2RlLCBjbGFzcywgY3VyX2NvbXBfVENfcmF0ZSwgbmV3X2NvbXBfVENfcmF0ZSwgY3VycmVudF90YXhhYmxlX2VhdiwgbmV3X3RheGFibGVfZWF2LCBldmVyeXRoaW5nKCkpDQojIA0KIyANCiMgaGVhZCh0YXhjb2Rlc19ieV9jbGFzc19jdXJyZW50KSANCg0KDQp0YXhjb2Rlc19jdXJyZW50IDwtIHBpbl9kYXRhICU+JSANCiAgZ3JvdXBfYnkodGF4X2NvZGUpICAlPiUNCiAgc3VtbWFyaXplKA0KICAgIGF2ID0gc3VtKGF2KSwNCiAgICBlYXYgPSBzdW0oZWF2KSwNCiAgICBlcXVhbGl6ZWRfQVYgPSBzdW0oZXF1YWxpemVkX0FWKSwNCiAgICBwaW5zX2luX2NsYXNzID0gbigpLA0KICAgIGN1cnJlbnRfZXhlbXB0aW9ucyA9IHN1bShhbGxfZXhlbXB0aW9ucyksDQogICAgSE9fZXhlbXBzID0gc3VtKGV4ZV9ob21lb3duZXIpLA0KICAgIHRheF9jb2RlX3JhdGUgPSBmaXJzdCh0YXhfY29kZV9yYXRlKSwgDQogICAgZmluYWxfdGF4X3RvX2Rpc3QgPSBzdW0oZmluYWxfdGF4X3RvX2Rpc3QsIG5hLnJtID0gVFJVRSksICMgdXNlZCBhcyBMRVZZIGFtb3VudCEhIA0KICAgIGZpbmFsX3RheF90b190aWYgPSBzdW0oZmluYWxfdGF4X3RvX3RpZiwgbmEucm0gPSBUUlVFKSwNCiAgICB0YXhfYW10X2V4ZSA9IHN1bSh0YXhfYW10X2V4ZSwgbmEucm0gPSBUUlVFKSwgDQogICAgdGF4X2FtdF9wcmVfZXhlID0gc3VtKHRheF9hbXRfcHJlX2V4ZSwgbmEucm0gPSBUUlVFKSwgDQogICAgdGF4X2FtdF9wb3N0X2V4ZSA9IHN1bSh0YXhfYW10X3Bvc3RfZXhlLCBuYS5ybSA9IFRSVUUpLA0KICAgIHJwbV90aWZfdG9fY3BzID0gc3VtKHJwbV90aWZfdG9fY3BzLCBuYS5ybSA9IFRSVUUpLCAjIG5vdCB1c2VkDQogICAgcnBtX3RpZl90b19ycG0gPSBzdW0ocnBtX3RpZl90b19ycG0sIG5hLnJtPVRSVUUpLCAjIG5vdCB1c2VkDQogICAgcnBtX3RpZl90b19kaXN0ID0gc3VtKHJwbV90aWZfdG9fZGlzdCwgbmEucm09VFJVRSksICMgbm90IHVzZWQNCiAgICB0aWZfc2hhcmUgPSBtZWFuKHRpZl9zaGFyZSwgbmEucm09VFJVRSksICMgbm90IHVzZWQNCiAgKSAlPiUNCiAgDQogIG11dGF0ZSh0b3RhbF9iaWxsX2N1cnJlbnQgPSBmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpICU+JQ0KICByZW5hbWUoY3VyX2NvbXBfVENfcmF0ZSA9IHRheF9jb2RlX3JhdGUpICU+JQ0KICBtdXRhdGUoY3VycmVudF90YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0LyhjdXJfY29tcF9UQ19yYXRlLzEwMCksDQogICAgICAgICBuZXdfdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdC8oY3VyX2NvbXBfVENfcmF0ZS8xMDApICsgSE9fZXhlbXBzKSAlPiUNCiAgbXV0YXRlKG5ld19jb21wX1RDX3JhdGUgPSAoZmluYWxfdGF4X3RvX2Rpc3QgLyBuZXdfdGF4YWJsZV9lYXYpKjEwMCkgJT4lDQogIG11dGF0ZShuZXdfY29tcF9UQ19yYXRlID0gaWZlbHNlKGlzLm5hbihuZXdfY29tcF9UQ19yYXRlKSwgY3VyX2NvbXBfVENfcmF0ZSwgbmV3X2NvbXBfVENfcmF0ZSkpICU+JQ0KICBzZWxlY3QodGF4X2NvZGUsIGN1cl9jb21wX1RDX3JhdGUsIG5ld19jb21wX1RDX3JhdGUsIGN1cnJlbnRfdGF4YWJsZV9lYXYsIG5ld190YXhhYmxlX2VhdiwgZXZlcnl0aGluZygpKQ0KDQoNCiNoZWFkKHRheGNvZGVzX2N1cnJlbnQpIA0KDQoNCnRheGNvZGVfdGF4cmF0ZXMgPC0gdGF4Y29kZXNfY3VycmVudCAlPiUgDQogIHNlbGVjdCh0YXhfY29kZSwgY3VyX2NvbXBfVENfcmF0ZSwgbmV3X2NvbXBfVENfcmF0ZSwgY3VycmVudF9leGVtcHRpb25zLCBIT19leGVtcHMpDQoNCg0KYGBgDQoNCiMgRmluZGluZyB0aGUgIk1lZGlhbiBQcm9wZXJ0eSIgb3IgIkF2ZXJhZ2UgVGF4cGF5ZXIiDQoNClRoZSBtZWRpYW4gYXNzZXNzZWQgdmFsdWUgaXMgdXNlZCB0byBkZXRlcm1pbmUgdGhlIGBtZWRpYW4gcHJvcGVydHlgIGZvciB2YXJpb3VzIGdyb3VwcyAoZS5nLiB0aGUgbXVuaWNpcGFsaXR5LCB0aGUgMS1kaWdpdCBtYWpvciBwcm9wZXJ0eSBjbGFzcywgYW5kIDMtZGlnaXQgcHJvcGVydHkgY2xhc3MpLg0KDQpUaGUgYXNzZXNzZWQgdmFsdWUgYW5kIG9yaWdpbmFsIGVxdWFsaXplZCBhc3Nlc3NlZCB2YWx1ZXMgY29tZSBmcm9tIHRoZSBgcGluYCBkYXRhIHRhYmxlIHdpdGhpbiBQVEFYU0lNLiBUaGlzIHRhYmxlIGFsc28gaGFzIGV2ZXJ5IHR5cGUgb2YgZXhlbXB0aW9uIHRoYXQgdGhlIHByb3BlcnR5IHJlY2VpdmVkIGFuZCB0aGUgYW1vdW50IG9mIEVBViB0aGF0IHdhcyBleGVtcHQgZHVlIHRvIHRoZSBleGVtcHRpb24uDQoNCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQpwaW5fZGF0YTIgPC0gbGVmdF9qb2luKHBpbl9kYXRhLCB0YXhjb2RlX3RheHJhdGVzLCBieSA9IGMoInRheF9jb2RlIiA9ICJ0YXhfY29kZSIpKQ0KDQoNCnBpbl9kYXRhMiA8LSBwaW5fZGF0YTIgJT4lIGxlZnRfam9pbihtdW5pX3RheF9jb2RlcykgDQoNCnBpbl9kYXRhMiA8LSBwaW5fZGF0YTIgJT4lIGxlZnRfam9pbihtdW5pX2FnZW5jeV9uYW1lcykNCg0Kd3JpdGVfY3N2KHBpbl9kYXRhMiwgIi4vT3V0cHV0LzRDX2pvaW5lZF9QSU5zX2JpbGxzX2FuZF9leGVtcHRpb25zLmNzdiIpDQoNCiNoZWFkKHBpbl9kYXRhMikNCg0KYGBgDQoNCjwhLS0tIENoYW5nZWQgY2FsY3VsYXRpb24gZm9yIG11bmkgdGF4IHJhdGVzIGJlbG93IG9uIE5vdmVtYmVyIDFzdC4gDQpXaGVuIGFnZ3JlZ2F0aW5nIHBpbiB0YXggYmlsbHMgdG8gdGhlIG11bmljaXBhbGl0eSBsZXZlbCwgZmlyc3QodGF4X2NvZGVfcmF0ZSkNCndhcyB1c2VkIGluc3RlYWQgb2YgYXZnKHRheF9jb2RlX3JhdGUpIHdoaWNoIHByb2JhYmx5IG1lc3NlcyB1cCBhIGZldyANCm11bmkncyBhdmcgY29tcG9zaXRlIHRheCByYXRlcy4gNGNfbXVuaV9yYXRlcy5jc3YgbWF5IGhhdmUgaGFkIGluY29ycmVjdCByYXRlcyAtLS0+DQoNCg0KPiBEb3dubG9hZCA0Q19qb2luZWRfUElOcyBmcm9tIFtCb3ggbGluayBoZXJlOiBdKGh0dHBzOi8vdW9maS5ib3guY29tL3MvY3ZwN3Bkamt4OGt0aDdvMHZnOWl0cHJhM3o4dmZrenEpLiBJIHdvdWxkIG1vdmUgdGhlIGRvd25sb2FkZWQgZmlsZSBpbnRvIHlvdXIgUiBwcm9qZWN0IGFuZCB0aGVuIHRoZSBjb2RlIGJlbG93IHNob3VsZCB3b3JrIHdpdGhvdXQgY2hhbmdpbmcgdGhlIGZpbGUgcGF0aC4gDQoNCmBgYHtyfQ0KcGluX2RhdGEyIDwtIHJlYWRfY3N2KCIuL091dHB1dC80Q19qb2luZWRfUElOc19iaWxsc19hbmRfZXhlbXB0aW9ucy5jc3YiKQ0KDQojIGhlYWQocGluX2RhdGEyKQ0KIyBkaW0ocGluX2RhdGEyKQ0KDQpwaW5fZGF0YTIgPC0gcGluX2RhdGEyICU+JSANCiAgbXV0YXRlKA0KICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgIGJpbGxfbm9HSEUgPSBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgIGJpbGxfbm9leGVtcHMgPSBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWKSwNCiAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9HSEUgLSBiaWxsX2N1cnJlbnQpDQpgYGANCg0KYGBge3J9DQpDMl9tdW5pc3RhdHMgPC0gcGluX2RhdGEyICU+JSANCiAgZmlsdGVyKGNsYXNzID4gMTk5ICYgY2xhc3MgPCAzMDApICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSkgICU+JQ0KICBhcnJhbmdlKGF2KSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG1lZGlhbl9lYXYgPSByb3VuZChtZWRpYW4oZWF2KSksIA0KICAgIG1lZGlhbl9hdiA9IHJvdW5kKG1lZGlhbihhdikpLCANCiAgICBhdmdfYXYgPSByb3VuZChtZWFuKGF2KSksDQogICAgYXZnX2VhdiA9IHJvdW5kKG1lYW4oZWF2KSksDQogICAgQzJfcGluc19pbl9tdW5pID0gbigpLA0KICAgIEMyX2N1cnJlbnRfZXhlbXB0aW9ucyA9IHN1bShhbGxfZXhlbXB0aW9ucywgbmEucm0gPSBUUlVFKSwNCiAgICBDMl9IT19leGVtcHMgPSBzdW0oZXhlX2hvbWVvd25lciwgbmEucm0gPSBUUlVFKSwNCiAgKQ0KDQpgYGANCg0KYGBge3J9DQplcV8yMDIxIDwtIDMuMDAyNw0KDQoNCm11bmlfdGF4cmF0ZXMgPC0gcGluX2RhdGEyICU+JSANCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUpICAlPiUNCiAgYXJyYW5nZShhdikgJT4lDQogIA0KICBzdW1tYXJpemUoDQogICAgbXVuaV9tZWRpYW5fYXYgPSBtZWRpYW4oYXYsIG5hLnJtPVRSVUUpLA0KICAgIG11bmlfbWVkaWFuX2VhdiA9IG1lZGlhbihlYXYsIG5hLnJtPVRSVUUpLA0KICAgIG11bmlfbWVhbl9hdiA9IHJvdW5kKG1lYW4oYXYsIG5hLnJtPVRSVUUpKSwNCiAgICBtdW5pX21lYW5fZWF2ID0gcm91bmQobWVhbihlYXYsIG5hLnJtPVRSVUUpKSwNCiAgICBhdiA9IHN1bShhdiwgbmEucm0gPSBUUlVFKSwNCiAgICBlYXYgPSBzdW0oZWF2LCBuYS5ybSA9IFRSVUUpLA0KICAgIGVxdWFsaXplZF9BViA9IHN1bShlcXVhbGl6ZWRfQVYsIG5hLnJtID0gVFJVRSksDQogICAgcGluc19pbl9tdW5pID0gbigpLA0KICAgIGN1cnJlbnRfZXhlbXB0aW9ucyA9IHN1bShhbGxfZXhlbXB0aW9ucywgbmEucm0gPSBUUlVFKSwNCiAgICBIT19leGVtcHMgPSBzdW0oZXhlX2hvbWVvd25lciwgbmEucm0gPSBUUlVFKSwNCiAgICB0YXhfY29kZV9yYXRlID0gbWVhbih0YXhfY29kZV9yYXRlLCBuYS5ybSA9IFRSVUUpLCAjIENoYW5nZWQgZnJvbSBmaXJzdCgpIHRvIG1lYW4oKSBvbiBOb3YgMQ0KICAgIGZpbmFsX3RheF90b19kaXN0ID0gc3VtKGZpbmFsX3RheF90b19kaXN0LCBuYS5ybSA9IFRSVUUpLCAjIHVzZWQgYXMgTEVWWSBhbW91bnQhISANCiAgICBmaW5hbF90YXhfdG9fdGlmID0gc3VtKGZpbmFsX3RheF90b190aWYsIG5hLnJtID0gVFJVRSksDQogICAgdGF4X2FtdF9leGUgPSBzdW0odGF4X2FtdF9leGUsIG5hLnJtID0gVFJVRSksIA0KICAgIHRheF9hbXRfcHJlX2V4ZSA9IHN1bSh0YXhfYW10X3ByZV9leGUsIG5hLnJtID0gVFJVRSksIA0KICAgIHRheF9hbXRfcG9zdF9leGUgPSBzdW0odGF4X2FtdF9wb3N0X2V4ZSwgbmEucm0gPSBUUlVFKSwNCiAgICBycG1fdGlmX3RvX2NwcyA9IHN1bShycG1fdGlmX3RvX2NwcywgbmEucm0gPSBUUlVFKSwgIyBub3QgdXNlZA0KICAgIHJwbV90aWZfdG9fcnBtID0gc3VtKHJwbV90aWZfdG9fcnBtLCBuYS5ybT1UUlVFKSwgIyBub3QgdXNlZA0KICAgIHJwbV90aWZfdG9fZGlzdCA9IHN1bShycG1fdGlmX3RvX2Rpc3QsIG5hLnJtPVRSVUUpLCAjIG5vdCB1c2VkDQogICAgdGlmX3NoYXJlID0gbWVhbih0aWZfc2hhcmUsIG5hLnJtPVRSVUUpLCAjIG5vdCB1c2VkDQogICkgJT4lDQogIA0KICBtdXRhdGUodG90YWxfYmlsbF9jdXJyZW50ID0gZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSAlPiUNCiAgcmVuYW1lKGN1cl9jb21wX1RDX3JhdGUgPSB0YXhfY29kZV9yYXRlKSAlPiUNCiAgbXV0YXRlKGN1cnJlbnRfdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdC8oY3VyX2NvbXBfVENfcmF0ZS8xMDApLA0KICAgICAgICAgbmV3X3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QvKGN1cl9jb21wX1RDX3JhdGUvMTAwKSArIEhPX2V4ZW1wcykgJT4lDQogIG11dGF0ZShuZXdfY29tcF9UQ19yYXRlID0gKGZpbmFsX3RheF90b19kaXN0IC8gbmV3X3RheGFibGVfZWF2KSoxMDApICU+JQ0KICANCiAgbXV0YXRlKG5ld19jb21wX1RDX3JhdGUgPSBpZmVsc2UoaXMubmFuKG5ld19jb21wX1RDX3JhdGUpLCBjdXJfY29tcF9UQ19yYXRlLCBuZXdfY29tcF9UQ19yYXRlKSkgJT4lIA0KICANCiAgbGVmdF9qb2luKEMyX211bmlzdGF0cykgJT4lDQogIA0KICBtdXRhdGUocmF0ZV9jaGFuZ2UgPSBjdXJfY29tcF9UQ19yYXRlIC0gbmV3X2NvbXBfVENfcmF0ZSwNCiAgICBub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYgPSByb3VuZCgxMDAwMCAqICgoY3VyX2NvbXBfVENfcmF0ZS8xMDApIC8gKHJhdGVfY2hhbmdlLzEwMCkpKSwNCiAgICBub2NoYW5nZV9hdiA9IHJvdW5kKG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViAvIGVxXzIwMjEpLA0KICAgICAgICAgbm9jaGFuZ2VfcmF0aW8gPSBub2NoYW5nZV9hdiAvIG1lZGlhbl9hdikgJT4lDQogIHNlbGVjdChhZ2VuY3lfbmFtZSwgbWVkaWFuX2F2LCBub2NoYW5nZV9hdiwgbm9jaGFuZ2VfcmF0aW8sIGN1cl9jb21wX1RDX3JhdGUsIG5ld19jb21wX1RDX3JhdGUsIGN1cnJlbnRfdGF4YWJsZV9lYXYsIG5ld190YXhhYmxlX2VhdiwgZXZlcnl0aGluZygpKQ0KDQptdW5pX3RheHJhdGVzIA0KDQptdW5pX3RheHJhdGVzICU+JSB3cml0ZV9jc3YoIi4vT3V0cHV0LzRDX211bmlfdGF4cmF0ZXMuY3N2IikNCmBgYA0KDQoNCiMjIE1vc3QgQ29tbW9uIENsYXNzIDIgUHJvcGVydHkgVHlwZQ0KDQoyMDMgaXMgbW9zdCBjb21tb24gaW4gUml2ZXJkYWxlLCBQaG9lbml4LCBhbmQgUGFyayBGb3Jlc3QuDQoyMDYgaXMgbW9zdCBjb21tb24gaW4gV2lubmV0a2ENCg0KYGBge3J9DQpwaW5fZGF0YTIgJT4lIA0KICBmaWx0ZXIocGluX0FWID4gMCAmIChjbGFzcyA+IDE5OSAmIGNsYXNzIDwgMzAwKSApJT4lDQogICAgICAgICAjbWFqb3JfY2xhc3NfY29kZSA9PSAiMiIpICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIsICJWSUxMQUdFIE9GIFBIT0VOSVgiLCAiVklMTEFHRSBPRiBXSU5ORVRLQSIsICJWSUxMQUdFIE9GIFJJVkVSREFMRSIpKSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGNsYXNzKSAlPiUNCiAgc3VtbWFyaXplKFBJTl9jb3VudCA9IG4oKSkgJT4lIA0KICBhcnJhbmdlKC1QSU5fY291bnQpDQoNCg0KDQpwaW5fZGF0YTIgJT4lIA0KICBmaWx0ZXIocGluX0FWID4gMCAmIChjbGFzcyA+IDE5OSAmIGNsYXNzIDwgMzAwKSApICU+JSANCiAjIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiKSkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBjbGFzcykgJT4lDQogIHN1bW1hcml6ZShQSU5fY291bnQgPSBuKCkpICU+JSANCiAgYXJyYW5nZShhZ2VuY3lfbmFtZSwgLVBJTl9jb3VudCkgJT4lDQogIyBncm91cF9ieShhZ2VuY3lfbmFtZSkgJT4lDQogIHN1bW1hcml6ZShhZ2VuY3lfbmFtZSA9IGZpcnN0KGFnZW5jeV9uYW1lKSwNCiAgICAgICAgICAgIGNsYXNzID0gZmlyc3QoY2xhc3MpLA0KICAgICAgICAgICAgUElOX2NvdW50ID0gZmlyc3QoUElOX2NvdW50KQ0KICAgICAgICAgICAgKQ0KYGBgDQoNCiMjIEFzc2Vzc2VkIFZhbHVlIFBJTiBkaXN0cmlidXRpb24NCg0KYGBge3J9DQpwaW5fZGF0YTIgJT4lDQogICMgIGZpbHRlcihtYWpvcl9jbGFzc19jb2RlID09IDIgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIpICU+JSANCiAgZmlsdGVyKChjbGFzcyA+IDE5OSAmIGNsYXNzIDwgMzAwKSAmIGFnZW5jeV9uYW1lICVpbiUgYygiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIsICJWSUxMQUdFIE9GIFBIT0VOSVgiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiLCAiVklMTEFHRSBPRiBXSU5ORVRLQSIpKSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUpICU+JQ0KICBnZ3Bsb3QoKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh4ID0gYXYsIGJpbnMgPSAxMDApKSArDQojICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gbWVkaWFuKGF2LCBuYS5ybT1UUlVFKSwgY29sb3IgPSAicmVkIikpICsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogIyBnZW9tX3RleHQoYWVzKHg9KG1lZGlhbihhdikgKyA1MDAwKSwgeSA9IDE1MDAsIGxhYmVsID0gbWVkaWFuKGF2KSkpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsIDUwMDAwKSkgKw0KICAjICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTUwMCkpKw0KICBsYWJzKHRpdGxlID0gIlBJTiBBViBEaXN0cmlidXRpb24gZm9yIEFsbCBDbGFzcyAyIFByb3BlcnRpZXMiLCB4PSJBViIsIHk9Ik51bWJlciBvZiBQSU5zIikgKw0KICBmYWNldF93cmFwKH5hZ2VuY3lfbmFtZSkNCg0KDQoNCg0KcGluX2RhdGEyICU+JQ0KICAjICBmaWx0ZXIobWFqb3JfY2xhc3NfY29kZSA9PSAyICYgYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiKSAlPiUgDQogIGZpbHRlcigoY2xhc3MgPiAxOTkgJiBjbGFzcyA8IDMwMCkgJiAgYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgUEhPRU5JWCIpICU+JQ0KICAgICAgICAgIyAgYWdlbmN5X25hbWUgJWluJSBjKCJWSUxMQUdFIE9GIFBBUksgRk9SRVNUIiwgIlZJTExBR0UgT0YgUEhPRU5JWCIsICJWSUxMQUdFIE9GIFJJVkVSREFMRSIsICJWSUxMQUdFIE9GIFdJTk5FVEtBIikpICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSkgJT4lDQogIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBhdiwgYmlucyA9IDEwMCkpICsNCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lZGlhbihhdiwgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSA3OTc0KSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgbGFiZWwgPSAiQnJlYWtldmVuIEFWIikgKw0KICB0aGVtZV9jbGFzc2ljKCkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCiAgZ2VvbV90ZXh0KGFlcyh4PShtZWRpYW4oYXYpKSwgeSA9IDQ1MCwgbGFiZWwgPSBtZWRpYW4oYXYpKSkgKw0KICBnZW9tX3RleHQoYWVzKHg9MTQwMDAsIHkgPSAzNTApLCBsYWJlbCA9ICJCcmVha2V2ZW4gQVYgPSAkNyw5NzQiKSArDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LCA1MDAwMCkpICsNCiAgIyAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDE1MDApKSsNCiAgbGFicyh0aXRsZSA9ICJQaG9uZWl4IFBJTiBBViBEaXN0cmlidXRpb24gZm9yIEFsbCBDbGFzcyAyIFByb3BlcnRpZXMiLCB4PSJBViIsIHk9Ik51bWJlciBvZiBQSU5zIiwNCiAgICAgIGNhcHRpb24gPSAgIk1lZGlhbiBBViBpcyAkMyw1MDIsIEJyZWFrZXZlbiBBViBpcyAkNyw5NzQiKSANCg0KDQoNCg0KDQoNCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKChjbGFzcyA+IDE5OSAmIGNsYXNzIDwgMzAwKSAmICBhZ2VuY3lfbmFtZSA9PSAiQ0lUWSBPRiBDSElDQUdPIikgJT4lDQogIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBhdiwgYmlucyA9IDEwMCkpICsNCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IG1lZGlhbihhdiwgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSA4NDIyOCksIGxpbmV0eXBlID0gImRhc2hlZCIpICsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogIGdlb21fdGV4dChhZXMoeD1tZWRpYW4oYXYpKzIwMDAwLCB5ID0gMzAwMDAwLCBsYWJlbCA9IG1lZGlhbihhdikpKSArDQogZ2VvbV90ZXh0KGFlcyh4PTEwMDAwMCwgeSA9IDIwMDAwMCksIGxhYmVsID0gIkJyZWFrZXZlbiBBViA9ICQ4NCwyMjgiKSArDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsIDUwMDAwMCksIGxhYmVscyA9IHNjYWxlczo6ZG9sbGFyKSArDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDMwMDAwMCkpKw0KICBsYWJzKHRpdGxlID0gIkNoaWNhZ28gUElOIEFWIERpc3RyaWJ1dGlvbiBmb3IgQWxsIENsYXNzIDIgUHJvcGVydGllcyIsIA0KICAgICAgIHg9IkFWIiwgeT0iTnVtYmVyIG9mIFBJTnMiLA0KICAgICAgY2FwdGlvbiA9ICAiTWVkaWFuIEFWIGlzIH4kMjEsMDAwLCBCcmVha2V2ZW4gQVYgaXMgfiQ4NCwwMDAiKSANCmBgYA0KDQoNCmBgYHtyLCBmaWcuc2hvdz0naG9sZCcsIG91dC53aWR0aD0iNTAlIn0NCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKChjbGFzcyA+IDE5OSAmIGNsYXNzIDwgMzAwKSAgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIpICU+JSANCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUpICU+JQ0KICBnZ3Bsb3QoKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh4ID0gYXYsIGJpbnMgPSAxMDApKSArDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIA0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtNSwgMTAwMDApKSArDQogIGxhYnModGl0bGUgPSAiUGFyayBGb3Jlc3QgUElOIEFWIERpc3RyaWJ1dGlvbiBwZXIgQ2xhc3MiLCB4PSJBViIsIHk9Ik51bWJlciBvZiBQSU5zIikgKw0KICBmYWNldF93cmFwKH5jbGFzcykNCg0KcGluX2RhdGEyICU+JQ0KICBmaWx0ZXIoKGNsYXNzID4gMTk5ICYgY2xhc3MgPCAzMDApICAmIGFnZW5jeV9uYW1lID09ICJWSUxMQUdFIE9GIFBIT0VOSVgiKSAlPiUgDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lKSAlPiUNCiAgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeCA9IGF2LCBiaW5zID0gMTAwKSkgKw0KICB0aGVtZV9jbGFzc2ljKCkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsIDEwMDAwKSkgKw0KICBsYWJzKHRpdGxlID0gIlBob2VuaXggUElOIEFWIERpc3RyaWJ1dGlvbiBwZXIgQ2xhc3MiLCB4PSJBViIsIHk9Ik51bWJlciBvZiBQSU5zIikgKw0KICBmYWNldF93cmFwKH5jbGFzcykNCg0KcGluX2RhdGEyICU+JQ0KICAgIGZpbHRlcigoY2xhc3MgPiAxOTkgJiBjbGFzcyA8IDMwMCkgICYgYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgUklWRVJEQUxFIikgJT4lIA0KICBncm91cF9ieShhZ2VuY3lfbmFtZSkgJT4lDQogIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHggPSBhdiwgYmlucyA9IDEwMCkpICsNCiAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LCAxMDAwMCkpICsNCiAgbGFicyh0aXRsZSA9ICJSaXZlcmRhbGUgUElOIEFWIERpc3RyaWJ1dGlvbiBwZXIgQ2xhc3MiLCB4PSJBViIsIHk9Ik51bWJlciBvZiBQSU5zIikgKw0KICBmYWNldF93cmFwKH5jbGFzcykNCg0KDQpwaW5fZGF0YTIgJT4lDQogICAgZmlsdGVyKChjbGFzcyA+IDE5OSAmIGNsYXNzIDwgMzAwKSAgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBXSU5ORVRLQSIpICU+JSANCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUpICU+JQ0KICBnZ3Bsb3QoKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh4ID0gYXYsIGJpbnMgPSAxMDApKSArDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIA0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtNSwgMjAwMDAwKSkgKw0KICBsYWJzKHRpdGxlID0gIldpbm5ldGthIFBJTiBBViBEaXN0cmlidXRpb24gcGVyIENsYXNzIiwgeD0iQVYiLCB5PSJOdW1iZXIgb2YgUElOcyIpICsNCiAgZmFjZXRfd3JhcCh+Y2xhc3MpDQpgYGANCg0KDQoNCg0KIyMjIFByb3BlcnR5IFZhbHVlIHdoZXJlIEJpbGwgZG9lc24ndCBjaGFuZ2UNCg0KYGBge3Igd3JvbmctY2FsYywgZXZhbD1GQUxTRSwgaW5jbHVkZSA9IEZBTFNFfQ0Kb3B0aW9ucyhzY2lwZW49OTk5ICkNCg0Kbm9iaWxsY2hhbmdlIDwtIG11bmlfdGF4cmF0ZXNfQzIgJT4lDQogICMgIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgUklWRVJEQUxFIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiKSkgJT4lDQogIG11dGF0ZShyYXRlX2NoYW5nZSA9IEMyX2N1cl9jb21wX1RDX3JhdGUgLSBDMl9uZXdfY29tcF9UQ19yYXRlLCAjIyANCiAgICAgICAgIG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViA9IHJvdW5kKDEwMDAwLyhyYXRlX2NoYW5nZS8xMDApKSkgJT4lDQogIGZpbHRlcihpcy5maW5pdGUobm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWKSApJT4lDQogIHNlbGVjdChhZ2VuY3lfbmFtZSwgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCByYXRlX2NoYW5nZSwgZXZlcnl0aGluZygpKQ0KDQpub2JpbGxjaGFuZ2UNCg0KDQptdW5pX3RheHJhdGVzX0MyICU+JQ0KICAgICAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIsICJWSUxMQUdFIE9GIFBIT0VOSVgiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiLCAiVklMTEFHRSBPRiBXSU5ORVRLQSIpKSAlPiUNCiAgbXV0YXRlKHJhdGVfY2hhbmdlID0gQzJfY3VyX2NvbXBfVENfcmF0ZSAtIEMyX25ld19jb21wX1RDX3JhdGUsICMjIA0KICAgICAgICAgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWID0gcm91bmQoMTAwMDAgLyAocmF0ZV9jaGFuZ2UvMTAwKSkpICU+JQ0KICBzZWxlY3QoYWdlbmN5X25hbWUsIG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViwgcmF0ZV9jaGFuZ2UsIGV2ZXJ5dGhpbmcoKSkgJT4lDQogIyBmaWx0ZXIobm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWIDwgNzAwMDAwMCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9bm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCB5ID0gbWVkaWFuX2VhdiwgbGFiZWw9YWdlbmN5X25hbWUpKSArDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV90ZXh0KGFlcyh4ID0obm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWKSwgeSA9IChtZWRpYW5fZWF2KzUwMDApKSwgc2l6ZSA9IDEuNSkgKw0KICAgICAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6ZG9sbGFyKSArDQogICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicyh4ID0gIkVBViBvZiBDbGFzcyAyIFByb3BlcnR5IHcvIE5vIEJpbGwgQ2hhbmdlIiwgeSA9ICJNZWRpYW4gRUFWIG9mIE11bmljaXBhbGl0eSIsIHRpdGxlID0gIkNhbiBob21lb3duZXJzIHdpdGggR0hFIGJlbmVmaXQgZnJvbSByZW1vdmFsIG9mIHRoZSBHSEU/IiwNCiAgICAgICBzdWJ0aXRsZSA9ICJZZXMsIGlmIGZyb20gYSBtdW5pIHdpdGggaGlnaCB0YXggcmF0ZXMgYW5kIGlmIHRoZXkgaGF2ZSBhIHByb3BlcnR5IHZhbHVlZCB3YXkgYWJvdmUgb3RoZXIgcHJvcGVydGllcyBpbiB0aGVpciB0YXhpbmcgZGlzdHJpY3QiLA0KICAgICAgIGNhcHRpb24gPSAiSG9tZW93bmVycyBpbiBtdW5pY2lwYWxpdGllcyB3aXRoIGhpZ2ggdGF4IHJhdGVzIGFuZCBBVidzIG11Y2ggaGlnaGVyDQogICAgICAgdGhlIG1lZGlhbiBBViBpbiB0aGUgbXVuaWNpcGFsaXR5IHByb3BlcnRpZXMgc2VlIHRoZWlyIGJpbGwgZGVjcmVhc2UgaW4gR0hFIHJlbW92YWwgc2NlbmFyaW8uIA0KICAgICAgIFRoZXNlIGFyZSBleHRyZW1lIHNpdHVhdGlvbnMgdGhhdCBzaG91bGQgbm90IGJlIHVzZWQgZm9yIHBvbGljeSBkZWNpc2lvbnMgb3IgZXhhbXBsZXMuIikNCg0KDQoNCm11bmlfdGF4cmF0ZXNfQzIgJT4lDQogICAgICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJWSUxMQUdFIE9GIFBBUksgRk9SRVNUIiwgIlZJTExBR0UgT0YgUEhPRU5JWCIsICJWSUxMQUdFIE9GIFJJVkVSREFMRSIpICkgJT4lDQogIG11dGF0ZShyYXRlX2NoYW5nZSA9IEMyX2N1cl9jb21wX1RDX3JhdGUgLSBDMl9uZXdfY29tcF9UQ19yYXRlLCAjIyANCiAgICAgICAgIG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViA9IHJvdW5kKDEwMDAwLyhyYXRlX2NoYW5nZS8xMDApKSApICU+JQ0KICBzZWxlY3QoYWdlbmN5X25hbWUsIG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViwgcmF0ZV9jaGFuZ2UsIGV2ZXJ5dGhpbmcoKSkgJT4lDQogIyBmaWx0ZXIobm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWIDwgNzAwMDAwMCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9bm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCB5ID0gbWVkaWFuX2VhdiwgbGFiZWw9YWdlbmN5X25hbWUpKSArDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV90ZXh0KGFlcyh4ID0obm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWKSwgeSA9IChtZWRpYW5fZWF2KzUwMCkpLCBzaXplID0gMikgKw0KICAgICAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6ZG9sbGFyKSArDQogICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicyh4ID0gIkVBViBvZiBDbGFzcyAyIFByb3BlcnR5IHcvIE5vIEJpbGwgQ2hhbmdlIiwgeSA9ICJNZWRpYW4gRUFWIG9mIE11bmljaXBhbGl0eSIsIHRpdGxlID0gIkNhbiBob21lb3duZXJzIGhhdmUgbG93ZXIgdGF4IGJpbGxzIGlmIHRoZSBHSEUgZXhlbXB0aW9uIHdhcyBlbmRlZD8iLA0KICAgICAgIHN1YnRpdGxlID0gIlllcywgaW4gdmVyeSwgdmVyeSByYXJlIGNhc2VzLiAiKQ0KDQoNCm11bmlfdGF4cmF0ZXNfQzIgJT4lDQogICAgIyAgZmlsdGVyKGFnZW5jeV9uYW1lID09ICJWSUxMQUdFIE9GIFdJTk5FVEtBIikgJT4lDQogICAgICAgIGZpbHRlcihtZWRpYW5fZWF2ID4gMTUwMDAwKSAlPiUNCiAgbXV0YXRlKHJhdGVfY2hhbmdlID0gQzJfY3VyX2NvbXBfVENfcmF0ZSAtIEMyX25ld19jb21wX1RDX3JhdGUsICMjIA0KICAgICAgICAgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWID0gcm91bmQoMTAwMDAvKHJhdGVfY2hhbmdlLzEwMCkpICkgJT4lDQogIHNlbGVjdChhZ2VuY3lfbmFtZSwgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCByYXRlX2NoYW5nZSwgZXZlcnl0aGluZygpKSAlPiUNCiAgI2ZpbHRlcihub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYgPCA3MDAwMDAwKSAlPiUgDQogIGdncGxvdChhZXMoeD1ub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYsIHkgPSBtZWRpYW5fZWF2LCBsYWJlbD1hZ2VuY3lfbmFtZSkpICsNCiAgZ2VvbV9wb2ludCgpKw0KICBnZW9tX3RleHQoYWVzKHggPShub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYpLCB5ID0gKG1lZGlhbl9lYXYrMTAwMCkpLCBzaXplID0gMikgKw0KICAgICAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6ZG9sbGFyKSArDQogICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicyh4ID0gIkVBViBvZiBDbGFzcyAyIFByb3BlcnR5IHcvIE5vIEJpbGwgQ2hhbmdlIiwgeSA9ICJNZWRpYW4gRUFWIG9mIE11bmljaXBhbGl0eSIsIHRpdGxlID0gIkNhbiBob21lb3duZXJzIHdpdGggR0hFIGJlbmVmaXQgZnJvbSByZW1vdmFsIG9mIHRoZSBHSEU/IiwNCiAgICAgICBjYXB0aW9uID0gIkEgJDUgbWlsbGlvbiBob21lIGluIFdpbm5ldGthIHdvdWxkIGJlbmVmaXQgaWYgZXZlcnlvbmUgZWxzZSBsb3N0IHRoZWlyIEdlbmVyYWwgSG9tZXN0ZWFkIEV4ZW1wdGlvbiIpDQoNCg0KbXVuaV90YXhyYXRlc19DMiAlPiUNCiAgbXV0YXRlKHJhdGVfY2hhbmdlID0gQzJfY3VyX2NvbXBfVENfcmF0ZSAtIEMyX25ld19jb21wX1RDX3JhdGUsICMjIA0KICAgICAgICAgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWID0gcm91bmQoMTAwMDAvKHJhdGVfY2hhbmdlLzEwMCkpICkgJT4lDQogIHNlbGVjdChhZ2VuY3lfbmFtZSwgICBub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYsIHJhdGVfY2hhbmdlLCBldmVyeXRoaW5nKCkpICU+JQ0KIyAgZmlsdGVyKG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViA8IDcwMDAwMDApICU+JSANCiAgZ2dwbG90KGFlcyh4PW5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViwgeSA9IG1lZGlhbl9lYXYsIGxhYmVsPWFnZW5jeV9uYW1lKSkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iICkrDQogIGdlb21fdGV4dChhZXMoeCA9IChub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYpLCB5ID0gKG1lZGlhbl9lYXYrMTAwMCkpLCBzaXplID0gMikrDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgbGFicyh4ID0gIkVBViBvZiBDbGFzcyAyIFByb3BlcnR5IHcvIE5vIEJpbGwgQ2hhbmdlIiwgeSA9ICJNZWRpYW4gRUFWIG9mIE11bmljaXBhbGl0eSIsIHRpdGxlID0gIkNhbiBob21lb3duZXJzIHdobyBjbGFpbSBHSEUgYmVuZWZpdCBmcm9tIHJlbW92YWwgb2YgdGhlIEdIRT8iLA0KICAgICAgIHN1YnRpdGxlID0gIkluIHZlcnksIHZlcnkgcmFyZSBpbnN0YW5jZXM6IHllcy4gIikNCg0KDQptdW5pX3RheHJhdGVzX0MyICU+JQ0KICBtdXRhdGUocmF0ZV9jaGFuZ2UgPSBDMl9jdXJfY29tcF9UQ19yYXRlIC0gQzJfbmV3X2NvbXBfVENfcmF0ZSwgIyMgDQogICAgICAgICBub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYgPSByb3VuZCgxMDAwMC8ocmF0ZV9jaGFuZ2UvMTAwKSkgKSAlPiUNCiAgc2VsZWN0KGFnZW5jeV9uYW1lLCAgIG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViwgcmF0ZV9jaGFuZ2UsIGV2ZXJ5dGhpbmcoKSkgJT4lDQojICBmaWx0ZXIobm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWIDwgNzAwMDAwMCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9cmF0ZV9jaGFuZ2UsIHkgPSBtZWRpYW5fZWF2LCBsYWJlbD1hZ2VuY3lfbmFtZSkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAjIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6ZG9sbGFyKSArDQogIGxhYnMoeSA9ICJFQVYgb2YgQ2xhc3MgMiBQcm9wZXJ0eSB3LyBObyBCaWxsIENoYW5nZSIsIHggPSAiQ29tcG9zaXRlIFRheCBSYXRlIENoYW5nZSAoUGVyY2VudGFnZSBQb2ludHMpIiwgdGl0bGUgPSAiTWVkaWFuIEVBViBpbiBNdW5pY2lwYWxpdHkgJiBDb21wb3NpdGUgVGF4IFJhdGUgQ2hhbmdlIA0KICAgICAgIGZyb20gRWxpbWluYXRpb24gb2YgR0hFIikNCg0KYGBgDQoNCg0KDQpgYGB7cn0NCm5vYmlsbGNoYW5nZSA8LSBtdW5pX3RheHJhdGVzDQoNCm5vYmlsbGNoYW5nZSAlPiUgICAgICAgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgUklWRVJEQUxFIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiLCAiQ0lUWSBPRiBDSElDQUdPIikpICU+JQ0KICBnZ3Bsb3QoYWVzKHk9bWVkaWFuX2F2LCB4ID0gYWdlbmN5X25hbWUpKSArDQogIGdlb21fY29sKCkrDQogICNnZW9tX3RleHQoYWVzKHggPShub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYpLCB5ID0gKG1lZGlhbl9lYXYrNTAwMCkpLCBzaXplID0gMS41KSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcikgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVsID0gYygiQ2hpY2FnbyIsIlBhcmsgRm9yZXN0IiwgIlBob2VuaXgiLCAiUml2ZXJkYWxlIiwgIldpbm5ldGthIikpICsgDQogIGxhYnMoeSA9ICJNZWRpYW4gUmVzaWRlbnRpYWwgQVYiLCB4ID0gIiIsIHRpdGxlID0gIk1lZGlhbiBSZXNpZGVudGlhbCBQcm9wZXJ0eSBBc3Nlc3NlZCBWYWx1ZSAtIEFsbCBDbGFzcyAyIHByb3BlcnR5IFR5cGVzIikNCg0KDQpub2JpbGxjaGFuZ2UgJT4lICAgICAgIA0KICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJDSVRZIE9GIENISUNBR08iLCAiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIsICJWSUxMQUdFIE9GIFBIT0VOSVgiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiLCAiVklMTEFHRSBPRiBXSU5ORVRLQSIpKSAlPiUNCiAgZ2dwbG90KGFlcyh5PShub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYvZXFfMjAyMSksIHggPSBhZ2VuY3lfbmFtZSkpICsNCiAgZ2VvbV9jb2woKSArDQogIGdlb21fdGV4dChhZXMoeT0obm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWL2VxXzIwMjEpKzMwMDAsIGxhYmVsID0gcm91bmQobm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWL2VxXzIwMjEpKSApICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6ZG9sbGFyKSArDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHNjYWxlX3hfZGlzY3JldGUobGFiZWwgPSBjKCJDaGljYWdvIiwgIlBhcmsgRm9yZXN0IiwgIlBob2VuaXgiLCAiUml2ZXJkYWxlIiwgIldpbm5ldGthIikpICsgDQogIGxhYnMoeSA9ICJCcmVha2V2ZW4gUG9pbnQgLSBBc3Nlc3NlZCBWYWx1ZSIsIHggPSAiIiwgdGl0bGUgPSAiUmVzaWRlbnRpYWwgUHJvcGVydHkgQXNzZXNzZWQgVmFsdWUgQnJlYWtldmVuIFBvaW50IiwgY2FwdGlvbiA9ICJSZXNpZGVudGlhbCBwcm9wZXJ0aWVzIGFib3ZlIHRoZXNlIHZhbHVlcyB3b3VsZCBoYXZlIHRoZWlyIGJpbGxzIGRlY3JlYXNlIGlmIHRoZSBHSEUgd2VyZSBlbGltaW5hdGVkLiIpDQpgYGANCg0KYGBge3J9DQoNCm5vY2hhbmdlIDwtIEMyX211bmlzdGF0cyAlPiUgbGVmdF9qb2luKG11bmlfdGF4cmF0ZXMpDQoNCg0KbXVuaV90YXhyYXRlcyAlPiUNCiAgZ2dwbG90KGFlcyh4PW5vY2hhbmdlX2F2LCANCiAgICAgICAgICAgICB5ID0gbWVkaWFuX2F2LCANCiAgICAgICAgICAgICBsYWJlbD1hZ2VuY3lfbmFtZQ0KICAgICAgICAgICAgICkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAjIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIgKSsNCiAgZ2VvbV90ZXh0KGFlcyh4ID0gKG5vY2hhbmdlX2F2KSwgeSA9IChtZWRpYW5fYXYrMTAwMCkpLCBzaXplID0gMikrDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgbGFicyh4ID0gIkFWIG9mIENsYXNzIDIgUHJvcGVydHkgdy8gTm8gQmlsbCBDaGFuZ2UiLCB5ID0gIk1lZGlhbiBBViBvZiBDbGFzcyAyIFByb3BlcnRpZXMgaW4gTXVuaWNpcGFsaXR5IiwgdGl0bGUgPSAiSGlnaGx5IHZhbHVlZCBob21lcyB3b3VsZCBoYXZlIGxvd2VyIHRheCBiaWxscyBpZiB0aGUgR0hFIHdlcmUgZWxpbWluYXRlZCIpDQpgYGANCg0KDQpgYGB7cn0NCm11bmlfdGF4cmF0ZXMgJT4lDQogICAgICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJWSUxMQUdFIE9GIFBBUksgRk9SRVNUIiwgIlZJTExBR0UgT0YgUEhPRU5JWCIsICJWSUxMQUdFIE9GIFJJVkVSREFMRSIsICJWSUxMQUdFIE9GIFdJTk5FVEtBIikpICU+JQ0KICBzZWxlY3QoYWdlbmN5X25hbWUsIG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViwgcmF0ZV9jaGFuZ2UsIGV2ZXJ5dGhpbmcoKSkgJT4lDQogIyBmaWx0ZXIobm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWIDwgNzAwMDAwMCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9bm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCB5ID0gbWVkaWFuX2VhdiwgbGFiZWw9YWdlbmN5X25hbWUpKSArDQogIGdlb21fcG9pbnQoKSsNCiAgZ2VvbV90ZXh0KGFlcyh4ID0obm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWKSwgeSA9IChtZWRpYW5fZWF2KzUwMDApKSwgc2l6ZSA9IDEuNSkgKw0KICAgICAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6ZG9sbGFyKSArDQogICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicyh4ID0gIkVBViBvZiBDbGFzcyAyIFByb3BlcnR5IHcvIE5vIEJpbGwgQ2hhbmdlIiwgeSA9ICJNZWRpYW4gRUFWIG9mIE11bmljaXBhbGl0eSIsIHRpdGxlID0gIkNhbiBob21lb3duZXJzIHdpdGggR0hFIGJlbmVmaXQgZnJvbSByZW1vdmFsIG9mIHRoZSBHSEU/IiwNCiAgICAgICBzdWJ0aXRsZSA9ICJZZXMsIGlmIGZyb20gYSBtdW5pIHdpdGggaGlnaCB0YXggcmF0ZXMgYW5kIGlmIHRoZXkgaGF2ZSBhIHByb3BlcnR5IHZhbHVlZCB3YXkgYWJvdmUgb3RoZXIgcHJvcGVydGllcyBpbiB0aGVpciB0YXhpbmcgZGlzdHJpY3QiLA0KICAgICAgIGNhcHRpb24gPSAiSG9tZW93bmVycyBpbiBtdW5pY2lwYWxpdGllcyB3aXRoIGhpZ2ggdGF4IHJhdGVzIGFuZCBBVidzIG11Y2ggaGlnaGVyDQogICAgICAgdGhlIG1lZGlhbiBBViBpbiB0aGUgbXVuaWNpcGFsaXR5IHByb3BlcnRpZXMgc2VlIHRoZWlyIGJpbGwgZGVjcmVhc2UgaW4gR0hFIHJlbW92YWwgc2NlbmFyaW8uIA0KICAgICAgIFRoZXNlIGFyZSBleHRyZW1lIHNpdHVhdGlvbnMgdGhhdCBzaG91bGQgbm90IGJlIHVzZWQgZm9yIHBvbGljeSBkZWNpc2lvbnMgb3IgZXhhbXBsZXMuIikNCg0KDQoNCm11bmlfdGF4cmF0ZXMgJT4lDQogICAgICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJWSUxMQUdFIE9GIFBBUksgRk9SRVNUIiwgIlZJTExBR0UgT0YgUEhPRU5JWCIsICJWSUxMQUdFIE9GIFJJVkVSREFMRSIpICkgJT4lDQogIGZpbHRlcihpcy5maW5pdGUobm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWKSApJT4lDQogIHNlbGVjdChhZ2VuY3lfbmFtZSwgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCByYXRlX2NoYW5nZSwgZXZlcnl0aGluZygpKSAlPiUNCiAjIGZpbHRlcihub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYgPCA3MDAwMDAwKSAlPiUgDQogIGdncGxvdChhZXMoeD1ub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYsIHkgPSBtZWRpYW5fZWF2LCBsYWJlbD1hZ2VuY3lfbmFtZSkpICsNCiAgZ2VvbV9wb2ludCgpKw0KICBnZW9tX3RleHQoYWVzKHggPShub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYpLCB5ID0gKG1lZGlhbl9lYXYrNTAwKSksIHNpemUgPSAyKSArDQogICAgICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcikgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBsYWJzKHggPSAiRUFWIG9mIENsYXNzIDIgUHJvcGVydHkgdy8gTm8gQmlsbCBDaGFuZ2UiLCB5ID0gIk1lZGlhbiBFQVYgb2YgTXVuaWNpcGFsaXR5IiwgdGl0bGUgPSAiQ2FuIGhvbWVvd25lcnMgaGF2ZSBsb3dlciB0YXggYmlsbHMgaWYgdGhlIEdIRSBleGVtcHRpb24gd2FzIGVuZGVkPyIsDQogICAgICAgc3VidGl0bGUgPSAiWWVzLCBpbiB2ZXJ5LCB2ZXJ5IHJhcmUgY2FzZXMuICIpDQoNCg0KbXVuaV90YXhyYXRlcyAlPiUNCiAgICAjICBmaWx0ZXIoYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgV0lOTkVUS0EiKSAlPiUNCiAgICAgICAgZmlsdGVyKG1lZGlhbl9lYXYgPiAxNTAwMDApICU+JQ0KICBmaWx0ZXIoaXMuZmluaXRlKG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBVikgKSAlPiUNCiAgc2VsZWN0KGFnZW5jeV9uYW1lLCBub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYsIHJhdGVfY2hhbmdlLCBldmVyeXRoaW5nKCkpICU+JQ0KICAjZmlsdGVyKG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViA8IDcwMDAwMDApICU+JSANCiAgZ2dwbG90KGFlcyh4PW5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViwgeSA9IG1lZGlhbl9lYXYsIGxhYmVsPWFnZW5jeV9uYW1lKSkgKw0KICBnZW9tX3BvaW50KCkrDQogIGdlb21fdGV4dChhZXMoeCA9KG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViksIHkgPSAobWVkaWFuX2VhdisxMDAwKSksIHNpemUgPSAyKSArDQogICAgICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcikgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBsYWJzKHggPSAiRUFWIG9mIENsYXNzIDIgUHJvcGVydHkgdy8gTm8gQmlsbCBDaGFuZ2UiLCB5ID0gIk1lZGlhbiBFQVYgb2YgTXVuaWNpcGFsaXR5IiwgdGl0bGUgPSAiQ2FuIGhvbWVvd25lcnMgd2l0aCBHSEUgYmVuZWZpdCBmcm9tIHJlbW92YWwgb2YgdGhlIEdIRT8iLA0KICAgICAgIGNhcHRpb24gPSAiQSAkNTAwSyBob21lIGluIFdpbm5ldGthIHdvdWxkIGJlbmVmaXQgaWYgZXZlcnlvbmUgZWxzZSBsb3N0IHRoZWlyIEdlbmVyYWwgSG9tZXN0ZWFkIEV4ZW1wdGlvbiIpDQoNCg0KbXVuaV90YXhyYXRlcyAgJT4lDQogIGZpbHRlcihpcy5maW5pdGUobm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWKSApICU+JQ0KICBzZWxlY3QoYWdlbmN5X25hbWUsICAgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCByYXRlX2NoYW5nZSwgZXZlcnl0aGluZygpKSAlPiUNCiMgIGZpbHRlcihub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYgPCA3MDAwMDAwKSAlPiUgDQogIGdncGxvdChhZXMoeD1ub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYsIHkgPSBtZWRpYW5fZWF2LCBsYWJlbD1hZ2VuY3lfbmFtZSkpICsNCiAgIyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iICkrDQogIGdlb21fdGV4dChhZXMoeCA9IChub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYpLCB5ID0gKG1lZGlhbl9lYXYrMTAwMCkpLCBzaXplID0gMikrDQogIHRoZW1lX2NsYXNzaWMoKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgbGFicyh4ID0gIkVBViBvZiBDbGFzcyAyIFByb3BlcnR5IHcvIE5vIEJpbGwgQ2hhbmdlIiwgeSA9ICJNZWRpYW4gRUFWIG9mIE11bmljaXBhbGl0eSIsIHRpdGxlID0gIkNhbiBob21lb3duZXJzIHdobyBjbGFpbSBHSEUgYmVuZWZpdCBmcm9tIHJlbW92YWwgb2YgdGhlIEdIRT8iLA0KICAgICAgIHN1YnRpdGxlID0gIkluIHZlcnksIHZlcnkgcmFyZSBpbnN0YW5jZXM6IHllcy4gIikNCg0KDQptdW5pX3RheHJhdGVzICU+JQ0KICBzZWxlY3QoYWdlbmN5X25hbWUsICAgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCByYXRlX2NoYW5nZSwgZXZlcnl0aGluZygpKSAlPiUNCiMgIGZpbHRlcihub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYgPCA3MDAwMDAwKSAlPiUgDQogIGdncGxvdChhZXMoeT1yYXRlX2NoYW5nZSwgeCA9IG1lZGlhbl9lYXYsIGxhYmVsPWFnZW5jeV9uYW1lKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgbGFicyh4PSAiRUFWIG9mIENsYXNzIDIgUHJvcGVydHkgdy8gTm8gQmlsbCBDaGFuZ2UiLCB5ID0gIkNvbXBvc2l0ZSBUYXggUmF0ZSBDaGFuZ2UgKFBlcmNlbnRhZ2UgUG9pbnRzKSIsIHRpdGxlID0gIkVBViBvZiBSZXNpZGVudGlhbCBQcm9wZXJ0eSAnQnJlYWtldmVuIFBvaW50JyAmIENvbXBvc2l0ZSBUYXggUmF0ZSBDaGFuZ2UgDQogICAgICAgZnJvbSBFbGltaW5hdGlvbiBvZiBHSEUiKQ0KDQptdW5pX3RheHJhdGVzICU+JQ0KICBzZWxlY3QoYWdlbmN5X25hbWUsICAgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCByYXRlX2NoYW5nZSwgZXZlcnl0aGluZygpKSAlPiUNCiAgZ2dwbG90KGFlcyh5PXJhdGVfY2hhbmdlLCB4ID0gbWVkaWFuX2F2LCBsYWJlbD1hZ2VuY3lfbmFtZSkpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6ZG9sbGFyKSArDQogIGxhYnMoeD0gIkFWIG9mIENsYXNzIDIgUHJvcGVydHkgdy8gTm8gQmlsbCBDaGFuZ2UiLCB5ID0gIkNvbXBvc2l0ZSBUYXggUmF0ZSBDaGFuZ2UgKFBlcmNlbnRhZ2UgUG9pbnRzKSIsIHRpdGxlID0gIkFWIG9mIFJlc2lkZW50aWFsIFByb3BlcnR5ICdCcmVha2V2ZW4gUG9pbnQnICYgQ29tcG9zaXRlIFRheCBSYXRlIENoYW5nZSANCiAgICAgICBmcm9tIEVsaW1pbmF0aW9uIG9mIEdIRSIpDQoNCm11bmlfdGF4cmF0ZXMgJT4lDQogIHNlbGVjdChhZ2VuY3lfbmFtZSwgICBub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYsIHJhdGVfY2hhbmdlLCBldmVyeXRoaW5nKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHk9cmF0ZV9jaGFuZ2UsIHggPSBtZWRpYW5fYXYqMTAsIGxhYmVsPWFnZW5jeV9uYW1lKSkgKw0KICBnZW9tX3BvaW50KCkgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgbGFicyh4PSAiTWFya2V0IFZhbHVlIG9mIENsYXNzIDIgUHJvcGVydHkgDQogICAgICAgYXQgJ0JyZWFrZXZlbiBQb2ludCciLCANCiAgICAgICB5ID0gIkNvbXBvc2l0ZSBUYXggUmF0ZSBDaGFuZ2UgDQogICAgICAgKFBlcmNlbnRhZ2UgUG9pbnRzKSIsIA0KICAgICAgIHRpdGxlID0gIk1hcmtldCBWYWx1ZSBvZiBSZXNpZGVudGlhbCBQcm9wZXJ0eSAnQnJlYWtldmVuIFBvaW50JyAmIA0KICAgICAgIENvbXBvc2l0ZSBUYXggUmF0ZSBDaGFuZ2UgZnJvbSBFbGltaW5hdGlvbiBvZiBHSEUiKQ0KYGBgDQoNCmBgYHtyfQ0KDQoNCm11bmlfdGF4cmF0ZXMlPiUNCiAgICAgIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgUklWRVJEQUxFIikpICU+JQ0KICBzZWxlY3QoYWdlbmN5X25hbWUsIG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViwgcmF0ZV9jaGFuZ2UsIGV2ZXJ5dGhpbmcoKSkgJT4lDQogIyBmaWx0ZXIobm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWIDwgNzAwMDAwMCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHk9bWVkaWFuX2F2LCB4ID0gYWdlbmN5X25hbWUpKSArDQogIGdlb21fY29sKCkrDQogICNnZW9tX3RleHQoYWVzKHggPShub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYpLCB5ID0gKG1lZGlhbl9lYXYrNTAwMCkpLCBzaXplID0gMS41KSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcikgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBsYWJzKHkgPSAiTWVkaWFuIFJlc2lkZW50aWFsIEFWIiwgeCA9ICIiLCB0aXRsZSA9ICJNZWRpYW4gUmVzaWRlbnRpYWwgUHJvcGVydHkgQXNzZXNzZWQgVmFsdWUgLSBBbGwgQ2xhc3MgMiBwcm9wZXJ0eSBUeXBlcyIpDQoNCm11bmlfdGF4cmF0ZXMgJT4lDQogICAgICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJWSUxMQUdFIE9GIFBBUksgRk9SRVNUIiwgIlZJTExBR0UgT0YgUEhPRU5JWCIsICJWSUxMQUdFIE9GIFJJVkVSREFMRSIpKSAlPiUNCg0KICBzZWxlY3QoYWdlbmN5X25hbWUsIG5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViwgcmF0ZV9jaGFuZ2UsIGV2ZXJ5dGhpbmcoKSkgJT4lDQogIyBmaWx0ZXIobm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWIDwgNzAwMDAwMCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHk9bWVkaWFuX2F2KjEwLCB4ID0gYWdlbmN5X25hbWUpKSArDQogIGdlb21fY29sKCkrDQogICNnZW9tX3RleHQoYWVzKHggPShub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYpLCB5ID0gKG1lZGlhbl9lYXYrNTAwMCkpLCBzaXplID0gMS41KSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcikgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBsYWJzKHkgPSAiTWVkaWFuIFJlc2lkZW50aWFsIE1hcmtldCBWYWx1ZSIsIHggPSAiIiwgdGl0bGUgPSAiTWVkaWFuIFJlc2lkZW50aWFsIE1hcmtldCBWYWx1ZSAoQVYqMTApIC0gQWxsIENsYXNzIDIgcHJvcGVydHkgVHlwZXMiKQ0KDQoNCm11bmlfdGF4cmF0ZXMgJT4lDQogICAgICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJWSUxMQUdFIE9GIFBBUksgRk9SRVNUIiwgIlZJTExBR0UgT0YgUEhPRU5JWCIsICJWSUxMQUdFIE9GIFJJVkVSREFMRSIpKSAlPiUNCiAgc2VsZWN0KGFnZW5jeV9uYW1lLCBub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYsIHJhdGVfY2hhbmdlLCBldmVyeXRoaW5nKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHk9bWVkaWFuX2VhdiwgeCA9IGFnZW5jeV9uYW1lKSkgKw0KICBnZW9tX2NvbCgpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicyh5ID0gIk1lZGlhbiBSZXNpZGVudGlhbCBFQVYiLCB4ID0gIiIsIHRpdGxlID0gIk1lZGlhbiBSZXNpZGVudGlhbCBFQVYgLSBBbGwgQ2xhc3MgMiBwcm9wZXJ0eSBUeXBlcyIpDQoNCg0KbXVuaV90YXhyYXRlcyAlPiUNCiAgICAgIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgR0xFTkNPRSIsICJWSUxMQUdFIE9GIFdJTk5FVEtBIikpICU+JQ0KDQogIHNlbGVjdChhZ2VuY3lfbmFtZSwgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCByYXRlX2NoYW5nZSwgZXZlcnl0aGluZygpKSAlPiUNCiAgZ2dwbG90KGFlcyh5PW1lZGlhbl9hdiwgeCA9IGFnZW5jeV9uYW1lKSkgKw0KICBnZW9tX2NvbCgpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicyh5ID0gIk1lZGlhbiBSZXNpZGVudGlhbCBBViIsIHggPSAiIiwgdGl0bGUgPSAiTWVkaWFuIFJlc2lkZW50aWFsIFByb3BlcnR5IEFWIC0gQWxsIENsYXNzIDIgcHJvcGVydHkgVHlwZXMiKQ0KDQptdW5pX3RheHJhdGVzICU+JQ0KICAgICAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiVklMTEFHRSBPRiBHTEVOQ09FIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiKSkgJT4lDQoNCiAgc2VsZWN0KGFnZW5jeV9uYW1lLCBub2JpbGxjaGFuZ2VfcHJvcGVydHlFQVYsIHJhdGVfY2hhbmdlLCBldmVyeXRoaW5nKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHk9bWVkaWFuX2F2KjEwLCB4ID0gYWdlbmN5X25hbWUpKSArDQogIGdlb21fY29sKCkrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcikgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBsYWJzKHkgPSAiTWVkaWFuIFJlc2lkZW50aWFsIE1hcmtldCBWYWx1ZSIsIHggPSAiIiwgdGl0bGUgPSAiTWVkaWFuIFJlc2lkZW50aWFsIFByb3BlcnR5IE1hcmtldCBWYWx1ZSAtIEFsbCBDbGFzcyAyIHByb3BlcnR5IFR5cGVzIikNCg0KDQoNCg0KbXVuaV90YXhyYXRlcyAlPiUNCiAgICAgIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgUklWRVJEQUxFIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiKSkgJT4lDQogIHNlbGVjdChhZ2VuY3lfbmFtZSwgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCByYXRlX2NoYW5nZSwgZXZlcnl0aGluZygpKSAlPiUNCiAgZ2dwbG90KGFlcyh5PW5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBViwgeCA9IGFnZW5jeV9uYW1lKSkgKw0KICBnZW9tX2NvbCgpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsNCiAgdGhlbWVfY2xhc3NpYygpICsNCiAgbGFicyh5ID0gIkVBViBvZiBDbGFzcyAyIFByb3BlcnR5IHcvIE5vIEJpbGwgQ2hhbmdlIiwgeCA9ICIiLCB0aXRsZSA9ICJCcmVha2V2ZW4gcG9pbnRzIC0gRUFWIHdoZXJlIHRheGJpbGwgd291bGRuJ3QgY2hhbmdlIGlmIEdIRSB3ZXJlIGVsaW1pbmF0ZWQiLA0KICAgICAgIGNhcHRpb24gPSAiSG9tZW93bmVycyBpbiBtdW5pY2lwYWxpdGllcyB3aXRoIGhpZ2ggdGF4IHJhdGVzIGFuZCBBVidzIG11Y2ggaGlnaGVyDQogICAgICAgdGhlIG1lZGlhbiBBViBpbiB0aGUgbXVuaWNpcGFsaXR5IHByb3BlcnRpZXMgc2VlIHRoZWlyIGJpbGwgZGVjcmVhc2UgaW4gR0hFIHJlbW92YWwgc2NlbmFyaW8uIA0KICAgICAgIFRoZXNlIGFyZSBleHRyZW1lIHNpdHVhdGlvbnMgdGhhdCBzaG91bGQgbm90IGJlIHVzZWQgZm9yIHBvbGljeSBkZWNpc2lvbnMgb3IgZXhhbXBsZXMuIikNCg0KDQoNCm11bmlfdGF4cmF0ZXMgJT4lDQogICAgICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJWSUxMQUdFIE9GIFBBUksgRk9SRVNUIiwgIlZJTExBR0UgT0YgUEhPRU5JWCIsICJWSUxMQUdFIE9GIFJJVkVSREFMRSIsICJWSUxMQUdFIE9GIFdJTk5FVEtBIikpICU+JQ0KDQogIHNlbGVjdChhZ2VuY3lfbmFtZSwgbm9iaWxsY2hhbmdlX3Byb3BlcnR5RUFWLCByYXRlX2NoYW5nZSwgZXZlcnl0aGluZygpKSAlPiUNCiAgZ2dwbG90KGFlcyh5PW5vYmlsbGNoYW5nZV9wcm9wZXJ0eUVBVi8zKjEwLCB4ID0gYWdlbmN5X25hbWUpKSArDQogIGdlb21fY29sKCkrDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcikgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBsYWJzKHkgPSAiQXBwcm94aW1hdGUgTWFya2V0IFZhbHVlIG9mIENsYXNzIDIgUHJvcGVydHkiLCB4ID0gIiIsIHRpdGxlID0gIkJyZWFrZXZlbiBwb2ludHMgLSBWYWx1ZSBvZiBob21lIHdoZXJlIHRheGJpbGwgd291bGRuJ3QgY2hhbmdlIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJJZiBHZW5lcmFsIEhvbWVzdGVhZCBFeGVtcHRpb24gd2VyZSBFaW1pbmF0ZWQiLA0KICAgICAgIGNhcHRpb24gPSAiQSBob21lIHZhbHVlZCBhYm92ZSB0aGUgcG9pbnRzIGluIHRoZSBncmFwaCB3b3VsZCBleHBlcmllbmNlIGEgbG93ZXIgdGF4IGJpbGwgaWYgdGhlIEdIRSB3ZXJlIGVsaW1pbmF0ZWQgZnJvbSBhbGwgb3RoZXIgcHJvcGVydGllcy4NCiAgICAgICBUaGVzZSBhcmUgbm90IHRoZSB0eXBlIG9mIHByb3BlcnRpZXMgd2UgYXJlIHRyeWluZyB0byBoZWxwLiBUaGVpciB0YXhiaWxsIGdvaW5nIGRvd24gaXMgTk9UIGEgYmVuZWZpdCBpbiB0aGUgYmlnIHBpY3R1cmUuIikNCg0KYGBgDQoNCg0KIyMgRUFWIFBJTiBkaXN0cmlidXRpb24NCg0KYGBge3IsIGZpZy5zaG93PSdob2xkJywgb3V0LndpZHRoPSI1MCUifQ0KcGluX2RhdGEyICU+JQ0KICBmaWx0ZXIoKGNsYXNzID4gMTk5ICYgY2xhc3MgPCAzMDApICYgYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiKSAlPiUgDQogIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHg9IGVhdiwgYmlucyA9IDEwMCkpKw0KICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVkaWFuKGVhdiwgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogIGdlb21fdGV4dChhZXMoeD0obWVkaWFuKGVhdikrNTAwMCksIHkgPSAxNTAwLCBsYWJlbCA9IG1lZGlhbihlYXYpKSkgKw0KICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsMTAwMDAwKSkgKw0KIyAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDE1MDApKSsNCiAgbGFicyh0aXRsZT0iUGFyayBGb3Jlc3QncyBQSU4gRUFWIGRpc3RyaWJ1dGlvbiIsIHg9ICJFQVYiLCB5ID0gIk51bWJlciBvZiBQSU5zIikNCg0KDQpwaW5fZGF0YTIgJT4lDQogIGZpbHRlcigoY2xhc3MgPiAxOTkgJiBjbGFzcyA8IDMwMCkgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBSSVZFUkRBTEUiKSAlPiUgDQogIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHg9IGVhdiwgYmlucyA9IDEwMCkpKw0KICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVkaWFuKGVhdiwgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogIGdlb21fdGV4dChhZXMoeD0obWVkaWFuKGVhdikrNTAwMCksIHkgPSAxNTAwLCBsYWJlbCA9IG1lZGlhbihlYXYpKSkgKw0KICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsMTAwMDAwKSkgKw0KIyAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDE1MDApKSsNCiAgbGFicyh0aXRsZSA9ICJSaXZlcmRhbGUncyBQSU4gRUFWIGRpc3RyaWJ1dGlvbiIsIHggPSAiRUFWIiwgeSA9ICJOdW1iZXIgb2YgUElOcyIpDQoNCg0KcGluX2RhdGEyICU+JQ0KICBmaWx0ZXIoKGNsYXNzID4gMTk5ICYgY2xhc3MgPCAzMDApICYgYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgUEhPRU5JWCIpICU+JSANCiAgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gZWF2LCBiaW5zID0gMTAwKSkrDQogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWRpYW4oZWF2LCBuYS5ybT1UUlVFKSwgY29sb3IgPSAicmVkIikpICsNCiAgICB0aGVtZV9jbGFzc2ljKCkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCiAgZ2VvbV90ZXh0KGFlcyh4PShtZWRpYW4oZWF2KSs1MDAwKSwgeSA9IDQwMCwgbGFiZWwgPSBtZWRpYW4oZWF2KSkpICsNCiAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LDEwMDAwMCkpICsNCiMgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxNTAwKSkrDQogIGxhYnModGl0bGU9IlBob2VuaXgncyBQSU4gRUFWIGRpc3RyaWJ1dGlvbiIsIHggPSAiRUFWIiwgeSA9ICJOdW1iZXIgb2YgUElOcyIpDQoNCg0KcGluX2RhdGEyICU+JQ0KICBmaWx0ZXIoKGNsYXNzID4gMTk5ICYgY2xhc3MgPCAzMDApICYgYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgV0lOTkVUS0EiKSAlPiUgDQogIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHg9IGVhdiwgYmlucyA9IDEwMCkpKw0KICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVkaWFuKGVhdiwgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogIGdlb21fdGV4dChhZXMoeD0obWVkaWFuKGVhdikrNTAwMDApLCB5ID0gMTUwMCwgbGFiZWwgPSBtZWRpYW4oZWF2KSkpICsNCiAgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LCAzMDAwMDAwKSwgbGFiZWwgPSBzY2FsZXM6OmRvbGxhcikgKw0KIyAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDE1MDApKSsNCiAgbGFicyh0aXRsZT0iV2lubmV0a2EncyBQSU4gRUFWIGRpc3RyaWJ1dGlvbiIsIHg9IkVBViIsIHkgPSAiTnVtYmVyIG9mIFBJTnMiKQ0KDQoNCg0KDQpgYGANCg0KDQojIyBCaWxsIERpc3RyaWJ1dGlvbnMgDQoNCmBgYHtyLCBmaWcuc2hvdz0naG9sZCcsIG91dC53aWR0aD0iNTAlIn0NCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKG1ham9yX2NsYXNzX2NvZGUgPT0gMiAmIGJpbGxfY3VycmVudCA8IDMwMDAwICYgYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiKSAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9jdXJyZW50LCBiaW5zID0gMTAwKSkrDQogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWRpYW4oYmlsbF9jdXJyZW50LCBuYS5ybT1UUlVFKSwgY29sb3IgPSAicmVkIikpICsNCiAgICB0aGVtZV9jbGFzc2ljKCkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIA0KDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LDIwMDAwKSwgbGFiZWwgPSBzY2FsZXM6OmRvbGxhcikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxNTAwKSwgbGFiZWwgPSBzY2FsZXM6OmNvbW1hKSsNCiAgbGFicyh4PSJQRidzIEFjdHVhbCBUYXggQmlsbHMgV2l0aCBDdXJyZW50IEV4ZW1wdGlvbnMiLCB5ID0gIk51bWJlciBvZiBUYXggQmlsbHMiKQ0KDQoNCnBpbl9kYXRhMiAlPiUNCiAgZ3JvdXBfYnkoaGFzX0hPX2V4ZW1wKSAlPiUNCiAgZmlsdGVyKG1ham9yX2NsYXNzX2NvZGUgPT0gMiAmIGJpbGxfY3VycmVudCA8IDMwMDAwICYgYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiKSAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9jdXJyZW50LCBiaW5zID0gMTAwKSkrDQogICAgdGhlbWVfY2xhc3NpYygpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsMjAwMDApLCBsYWJlbCA9IHNjYWxlczo6ZG9sbGFyKSArDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDE1MDApLCBsYWJlbCA9IHNjYWxlczo6Y29tbWEpKw0KICBsYWJzKHg9IlBGJ3MgQWN0dWFsIFRheCBCaWxscyBXaXRoIEN1cnJlbnQgRXhlbXB0aW9ucyIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIpICsNCiAgZmFjZXRfd3JhcCh+aGFzX0hPX2V4ZW1wKQ0KDQpwaW5fZGF0YTIgJT4lDQogIGZpbHRlcihtYWpvcl9jbGFzc19jb2RlID09IDIgJiBiaWxsX25vZXhlbXBzIDwgMzAwMDAgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIpICU+JSBnZ3Bsb3QoKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh4PSBiaWxsX25vZXhlbXBzLCBiaW5zID0gMTAwKSkrDQogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWRpYW4oYmlsbF9ub2V4ZW1wcywgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCg0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtNSwyMDAwMCksIGxhYmVsID0gc2NhbGVzOjpkb2xsYXIpICsgDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTUwMCksIGxhYmVsID0gc2NhbGVzOjpjb21tYSkrDQoNCiAgbGFicyh4PSJQRidzIFRheCBCaWxscyBXaXRob3V0IEdlbmVyYWwgSG9tZXN0ZWFkIEV4ZW1wdGlvbnMiLCB5ID0gIk51bWJlciBvZiBUYXggQmlsbHMiKQ0KDQoNCg0KYGBgDQoNCg0KYGBge3IsIGZpZy5zaG93PSdob2xkJywgb3V0LndpZHRoPSI1MCUifQ0KDQpwaW5fZGF0YTIgJT4lDQogIGZpbHRlcihtYWpvcl9jbGFzc19jb2RlID09IDIgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBQSE9FTklYIikgJT4lIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHg9IGJpbGxfY3VycmVudCwgYmlucyA9IDEwMCkpKw0KICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVkaWFuKGJpbGxfY3VycmVudCwgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCg0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtNSwyMDAwMCkpICsgDQogICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA2MDApKSsNCg0KICBsYWJzKHRpdGxlPSJQSE9FTklYJ3MgQ3VycmVudCBUYXggQmlsbCBEaXN0cmlidXRpb24iLCB4ID0gIkRvbGxhcnMiLCB5ID0gIk51bWJlciBvZiBUYXggQmlsbHMiKQ0KDQpwaW5fZGF0YTIgJT4lDQogIGZpbHRlcihtYWpvcl9jbGFzc19jb2RlID09IDIgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBQSE9FTklYIikgJT4lIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHg9IGJpbGxfbm9leGVtcHMsIGJpbnMgPSAxMDApKSsNCiAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PW1lZGlhbihiaWxsX25vZXhlbXBzLCBuYS5ybT1UUlVFKSwgY29sb3IgPSAicmVkIikpICsNCiAgICB0aGVtZV9jbGFzc2ljKCkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIA0KDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LDIwMDAwKSkgKyANCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA2MDApKSsNCg0KICBsYWJzKHRpdGxlPSJQSE9FTklYJ3MgVGF4IEJpbGxzIFdpdGhvdXQgR2VuZXJhbCBIb21lc3RlYWQgRXhlbXB0aW9ucyIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIpDQoNCg0KDQpgYGANCg0KYGBge3IsIGZpZy5zaG93PSdob2xkJywgb3V0LndpZHRoPSI1MCUifQ0KcGluX2RhdGEyICU+JQ0KICBmaWx0ZXIobWFqb3JfY2xhc3NfY29kZSA9PSAyICYgYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgV0lOTkVUS0EiKSAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9jdXJyZW50LCBiaW5zID0gMTAwKSkrDQogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWRpYW4oYmlsbF9jdXJyZW50LCBuYS5ybT1UUlVFKSwgY29sb3IgPSAicmVkIikpICsNCiAgICB0aGVtZV9jbGFzc2ljKCkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIA0KDQogIyBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtNSwyMDAwMCkpICsNCiAjIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDgwMDAwKSkgKw0KICBsYWJzKHRpdGxlPSJXSU5ORVRLQSdzIEFjdHVhbCBUYXggQmlsbHMgV2l0aCBDdXJyZW50IEV4ZW1wdGlvbnMiLCB4PSAiRG9sbGFycyIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIpDQoNCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKG1ham9yX2NsYXNzX2NvZGUgPT0gMiAgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBXSU5ORVRLQSIpICU+JSBnZ3Bsb3QoKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh4PSBiaWxsX25vZXhlbXBzLCBiaW5zID0gMTAwKSkrDQogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWRpYW4oYmlsbF9ub2V4ZW1wcywgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCg0KICAjc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsMjAwMDApKSArIA0KICAjc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgODAwMDApKSArDQoNCiAgbGFicyh0aXRsZT0iV0lOTkVUS0EncyBUYXggQmlsbHMgV2l0aG91dCBHZW5lcmFsIEhvbWVzdGVhZCBFeGVtcHRpb25zIiwgeD0iRG9sbGFycyIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIpDQoNCg0KDQpgYGANCg0KYGBge3IgYmlsbC1jaGFuZ2V9DQpwaW5fZGF0YTIgJT4lDQogIGZpbHRlcihtYWpvcl9jbGFzc19jb2RlID09IDIgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIpICU+JSANCiAgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9jaGFuZ2UsIGJpbnMgPSAxMDApKSsNCiAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PW1lZGlhbihiaWxsX2NoYW5nZSwgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogICAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTEwMDAwLDEwMDAwKSkgKw0KDQojICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMjAwMCkpKw0KICBsYWJzKHRpdGxlPSJQYXJrIEZvcmVzdCdzIENoYW5nZSBpbiBUYXggQmlsbHMiLCBzdWJ0aXRsZSA9ICAiSHlwb3RoZXRpY2FsIHdpdGggbm8gR2VuZXJhbCBIb21lc3RlYWQgRXhlbXB0aW9ucyIsIHggPSAiQ2hhbmdlIGluIFRheCBCaWxsICgkKSIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIpDQoNCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKG1ham9yX2NsYXNzX2NvZGUgPT0gMiAmIGFnZW5jeV9uYW1lID09ICJWSUxMQUdFIE9GIFBIT0VOSVgiKSAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9jaGFuZ2UsIGJpbnMgPSAxMDApKSsNCiAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PW1lZGlhbihiaWxsX2NoYW5nZSwgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTAwMDAsMTAwMDApKSArDQoNCiMgICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMjgwMCwyODAwKSkgKyANCiMgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAyMDAwKSkrDQoNCiAgbGFicyh0aXRsZSA9IlBIT0VOSVgncyBDaGFuZ2UgaW4gVGF4IEJpbGxzIiwgc3VidGl0bGUgPSAiSHlwb3RoZXRpY2FsIHdpdGggbm8gR2VuZXJhbCBIb21lc3RlYWQgRXhlbXB0aW9ucyIsIHggPSAiQ2hhbmdlIGluIFRheCBCaWxsICgkKSIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIpDQoNCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKG1ham9yX2NsYXNzX2NvZGUgPT0gMiAmIGFnZW5jeV9uYW1lID09ICJWSUxMQUdFIE9GIFdJTk5FVEtBIikgJT4lIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHg9IGJpbGxfY2hhbmdlLCBiaW5zID0gMTAwKSkrDQogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWRpYW4oYmlsbF9jaGFuZ2UsIG5hLnJtPVRSVUUpLCBjb2xvciA9ICJyZWQiKSkgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTAwMDAsMTAwMDApKSArDQoNCiMgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LDIwMDAwKSkgKyANCiMgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTUwMCkpKw0KDQogIGxhYnModGl0bGU9IldJTk5FVEtBJ3MgQ2hhbmdlIGluIFRheCBCaWxscyBXaXRob3V0IEdlbmVyYWwgSG9tZXN0ZWFkIEV4ZW1wdGlvbnMiLCB5ID0gIk51bWJlciBvZiBUYXggQmlsbHMiLCB4ID0gIkRvbGxhcnMiKQ0KDQpwaW5fZGF0YTIgJT4lDQogIGZpbHRlcihtYWpvcl9jbGFzc19jb2RlID09IDIgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBSSVZFUkRBTEUiKSAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9jaGFuZ2UsIGJpbnMgPSAxMDApKSsNCiAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PW1lZGlhbihiaWxsX2NoYW5nZSwgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMTAwMDAsMTAwMDApKSArDQpsYWJzKHRpdGxlPSJSSVZFUkRBTEUncyBDaGFuZ2UgaW4gVGF4IEJpbGxzIFdpdGhvdXQgR2VuZXJhbCBIb21lc3RlYWQgRXhlbXB0aW9ucyIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIsIHggPSAiRG9sbGFycyIpDQpgYGANCg0KDQpgYGB7cn0NCg0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA+MTk5ICYgY2xhc3MgPCAzMDApICU+JSANCiAgYXJyYW5nZShhdikgJT4lDQogIyBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIG11dGF0ZSgjdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdCAvIHRheF9jb2RlX3JhdGUsDQogICAgIyBjdXJyZW50IGJpbGwgPSBjdXJyZW50IHRheCByYXRlICogcG9ydGlvbiBvZiBsZXZ5IGJpbGxlZA0KICAgICAgICAgYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQogICAgICAgICBiaWxsX25vZXhlbXBzID0gIG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSwgemVyb19iaWxsLCBoYXNfSE9fZXhlbXApICU+JSANCiAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gbWVkaWFuKGVhdiksDQogICAgICAgICAgICBtZWFuX2JpbGxfY3VyID0gbWVhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWFuX2JpbGxfbmV3ID0gbWVhbihiaWxsX25vZXhlbXBzLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiAgICAgICAgICAgIG1lYW5fY2hhbmdlID0gbWVhbihiaWxsX2NoYW5nZSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkNCikNCg0KDQpwaW5fZGF0YTIgJT4lIA0KZmlsdGVyKHBpbl9BViA+IDApICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIsICJWSUxMQUdFIE9GIFBIT0VOSVgiLCAiVklMTEFHRSBPRiBXSU5ORVRLQSIsICJWSUxMQUdFIE9GIFJJVkVSREFMRSIpKSAlPiUNCiAgZmlsdGVyKGNsYXNzID4xOTkgJiBjbGFzcyA8IDMwMCkgJT4lIA0KICBhcnJhbmdlKGF2KSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gbWVkaWFuKGVhdiksDQogICAgICAgICAgICBtZWFuX2JpbGxfY3VyID0gbWVhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWFuX2JpbGxfbmV3ID0gbWVhbihiaWxsX25vZXhlbXBzLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiAgICAgICAgICAgIG1lYW5fY2hhbmdlID0gbWVhbihiaWxsX2NoYW5nZSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkNCikNCg0KDQpwaW5fZGF0YTIgJT4lIA0KZmlsdGVyKHBpbl9BViA+IDApICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIsICJWSUxMQUdFIE9GIFBIT0VOSVgiLCAiVklMTEFHRSBPRiBXSU5ORVRLQSIsIlZJTExBR0UgT0YgUklWRVJEQUxFIikpICU+JQ0KICBmaWx0ZXIoY2xhc3MgPjE5OSAmIGNsYXNzIDwgMzAwKSAlPiUgDQogIGFycmFuZ2UoYXYpICU+JQ0KICMgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KICBtdXRhdGUoI3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QgLyB0YXhfY29kZV9yYXRlLA0KICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUpICU+JSANCiAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gbWVkaWFuKGVhdiksDQogICAgICAgICAgICBtZWFuX2JpbGxfY3VyID0gbWVhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWFuX2JpbGxfbmV3ID0gbWVhbihiaWxsX25vZXhlbXBzLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiAgICAgICAgICAgIG1lYW5fY2hhbmdlID0gbWVhbihiaWxsX2NoYW5nZSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkNCikNCg0KDQpgYGANCg0KDQoNCmBgYHtyfQ0KdGF4X2JpbGxfY2hhbmdlX0hPIDwtIHBpbl9kYXRhMiAlPiUgDQpmaWx0ZXIocGluX0FWID4gMCkgJT4lIA0KICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJWSUxMQUdFIE9GIFBBUksgRk9SRVNUIiwgIlZJTExBR0UgT0YgUEhPRU5JWCIsICJWSUxMQUdFIE9GIFdJTk5FVEtBIiwgIlZJTExBR0UgT0YgUklWRVJEQUxFIikpICU+JQ0KICBmaWx0ZXIoY2xhc3MgPT0gMjAzKSAlPiUgDQogIGFycmFuZ2UoYXYpICU+JQ0KICAgIG11dGF0ZShiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gbWVkaWFuKGVhdiksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9jdXIgPSByb3VuZChtZWRpYW4oYmlsbF9jdXJyZW50KSksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9uZXcgPSByb3VuZChtZWRpYW4oYmlsbF9ub2V4ZW1wcykpLA0KICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IHJvdW5kKG1lZGlhbihiaWxsX2NoYW5nZSkpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpLA0KICAgICAgICAgICAgcGVyY2VpdmVkX3NhdmluZ3MgPSBtZWRpYW4odGF4X2FtdF9leGUpKQ0KDQp0YXhfYmlsbF9jaGFuZ2VfSE8NCg0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiKSkgJT4lDQogICAgZmlsdGVyKGNsYXNzID09IDIwMykgJT4lIA0KICBhcnJhbmdlKGF2KSAlPiUNCiAgbXV0YXRlKG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IHJvdW5kKG1lZGlhbihiaWxsX2N1cnJlbnQpKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IHJvdW5kKG1lZGlhbihiaWxsX25vZXhlbXBzKSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gcm91bmQobWVkaWFuKGJpbGxfY2hhbmdlKSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSkpDQoNCnBpbl9kYXRhMiAlPiUgDQpmaWx0ZXIocGluX0FWID4gMCkgJT4lIA0KICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJWSUxMQUdFIE9GIFBBUksgRk9SRVNUIiwgIlZJTExBR0UgT0YgUEhPRU5JWCIsICJWSUxMQUdFIE9GIFdJTk5FVEtBIiwgIlZJTExBR0UgT0YgUklWRVJEQUxFIikpICU+JQ0KICBmaWx0ZXIoY2xhc3MgPT0gMjAzKSAlPiUgDQogIGFycmFuZ2UoYXYpICU+JQ0KICAgIG11dGF0ZShiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCB6ZXJvX2JpbGwsIGhhc19IT19leGVtcCkgJT4lIA0KICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IHJvdW5kKG1lZGlhbihiaWxsX2N1cnJlbnQpKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IHJvdW5kKG1lZGlhbihiaWxsX25vZXhlbXBzKSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gcm91bmQobWVkaWFuKGJpbGxfY2hhbmdlKSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSkpDQoNCmBgYA0KDQoNCklmIG9ubHkgInJlbW92aW5nIi8icmVmdW5kaW5nIiB0aGUgZ2VuZXJhbCBob21lc3RlYWQgZXhlbXB0aW9uOg0KDQpGb3IgUGFyayBGb3Jlc3QgY2xhc3MgMjAzIHByb3BlcnRpZXMsIHRoZSBtZWRpYW4gdGF4IGJpbGwgd291bGQgZ28gZG93biBcJDIsMDg4IGZvciB0aG9zZSB3aG8gZG9uJ3QgY3VycmVudGx5IGhhdmUgYSBnZW5lcmFsIGhvbWVzdGVhZCBleGVtcHRpb24gYW5kIHdvdWxkIGluY3JlYXNlIFwkMiwzMTQgZm9yIHBlb3BsZSB3aG8gZG8gY3VycmVudGx5IGNsYWltIHRoZSBnZW5lcmFsIGhvbWVzdGVhZCBleGVtcHRpb24uIDc3OSBwZW9wbGUgZG9uJ3QgY2xhaW0gdGhlIGV4ZW1wdGlvbiBhbmQgMTM5OCBwZW9wbGUgZG8uIA0Kfn5BIGhvbWUgd2l0aCBFQVYgYWJvdmUgODgsMjk4IEVBViAgd291bGQgZXhwZXJpZW5jZSBhIGxvd2VyIHRheCBiaWxsIGFuZCBob21lcyBiZWxvdyA4OCwyOTggRUFWIHdvdWxkIGV4cGVyaWVuY2UgYW4gaW5jcmVhc2UgaW4gdGhlaXIgdGF4YmlsbC5+fiANClRoZSBtZWRpYW4gRUFWIGZvciBhbGwgY2xhc3MgMiBwcm9wZXJ0aWVzIGlzIDE4LDMyMCBpbiBQYXJrIEZvcmVzdC4gDQoNCg0KUGhvZW5peCBjbGFzcyAyMDMgbWVkaWFuIHByb3BlcnRpZXMgaGF2ZSBhIGRlY3JlYXNlIG9mIFwkMSw0ODEgaWYgdGhleSBkaWRuJ3QgY2xhaW0gaG9tZXN0ZWFkIGV4ZW1wdGlvbnMgY3VycmVudGx5IGFuZCBpbmNyZWFzZWQgXCQxLDQ2OCBmIHRoZXkgZGlkIGFscmVhZHkgY2xhaW0gdGhlIGdlbmVyYWwgaG9tZXN0ZWFkIGV4ZW1wdGlvbi4gMTM3IHBlb3BsZSBkbyBub3QgY2xhaW0gdGhlIGV4ZW1wdGlvbiBhbmQgMjA5IHBlb3BsZSBkbyBjbGFpbSB0aGUgZ2VuZXJhbCBob21lc3RlYWQgZXhlbXB0aW9uLg0Kfn5BIGhvbWUgd2l0aCBFQVYgYWJvdmUgNzksOTQ2IEVBViAgd291bGQgZXhwZXJpZW5jZSBhIGxvd2VyIHRheCBiaWxsIGFuZCBob21lcyBiZWxvdyAyOSw5NDYgRUFWIHdvdWxkIGV4cGVyaWVuY2UgYW4gaW5jcmVhc2UgaW4gdGhlaXIgdGF4YmlsbC5+fiBUaGUgbWVkaWFuIEVBViBmb3IgYWxsIGNsYXNzIDIgcHJvcGVydGllcyBpcyAxMCw1MTUgaW4gUGhvZW5peC4gDQoNCg0KUml2ZXJkYWxlIGNsYXNzIDIwMyBtZWRpYW4gcHJvcGVydGllcyBoYXZlIGEgZGVjcmVhc2Ugb2YgXCQyMDk1IGlmIHRoZXkgZGlkbid0IGNsYWltIGhvbWVzdGVhZCBleGVtcHRpb25zIGN1cnJlbnRseSBhbmQgaW5jcmVhc2VkIFwkMSwxNTUgZiB0aGV5IGRpZCBhbHJlYWR5IGNsYWltIHRoZSBnZW5lcmFsIGhvbWVzdGVhZCBleGVtcHRpb24uIDIwOSBwZW9wbGUgZG8gbm90IGNsYWltIHRoZSBleGVtcHRpb24gYW5kIDQ0MyBwZW9wbGUgZG8gY2xhaW0gdGhlIGdlbmVyYWwgaG9tZXN0ZWFkIGV4ZW1wdGlvbi4NCn5+QSBob21lIHdpdGggRUFWIGFib3ZlIDE3MCwyNjEgRUFWICB3b3VsZCBleHBlcmllbmNlIGEgbG93ZXIgdGF4IGJpbGwgYW5kIGhvbWVzIGJlbG93IDE3MCwyNjEgRUFWIHdvdWxkIGV4cGVyaWVuY2UgYW4gaW5jcmVhc2UgaW4gdGhlaXIgdGF4YmlsbC5+fg0KDQpUaGUgbWVkaWFuIEVBViBmb3IgYWxsIENsYXNzIDIgcHJvcGVydGllcyBpcyAxNywxNjMgaW4gUml2ZXJkYWxlLg0KDQpXaW5uZXRrYSBjbGFzcyAyMDMgbWVkaWFuIHByb3BlcnRpZXMgaGF2ZSBhIGRlY3JlYXNlIG9mIFwkMjgxIGlmIHRoZXkgZGlkbid0IGNsYWltIGhvbWVzdGVhZCBleGVtcHRpb25zIGN1cnJlbnRseSBhbmQgaW5jcmVhc2VkIFwkNjA4IGYgdGhleSBkaWQgYWxyZWFkeSBjbGFpbSB0aGUgZ2VuZXJhbCBob21lc3RlYWQgZXhlbXB0aW9uLiAzNyBwZW9wbGUgZG8gbm90IGNsYWltIHRoZSBleGVtcHRpb24gYW5kIDkxIHBlb3BsZSBkbyBjbGFpbSB0aGUgZ2VuZXJhbCBob21lc3RlYWQgZXhlbXB0aW9uLg0Kfn5BIGhvbWUgd2l0aCBFQVYgYWJvdmUgNSwxNTksMzI3IEVBViAgd291bGQgZXhwZXJpZW5jZSBhIGxvd2VyIHRheCBiaWxsIGFuZCBob21lcyBiZWxvdyA1LDE1OSwzMjcgRUFWIHdvdWxkIGV4cGVyaWVuY2UgYW4gaW5jcmVhc2UgaW4gdGhlaXIgdGF4YmlsbC5+fiAgVGhlIG1lZGlhbiBFQVYgZm9yIGFsbCBDbGFzcyAyIHByb3BlcnRpZXMgaXMgMjQ5LDAxOCBFQVYgaW4gV2lubmV0a2EuDQoNCiMgTXVuaSBDb21wYXJpc29uIG9mIEFWcyBhbmQgVGF4IEJpbGxzDQoNCiMjIENvbXBhcmUgQVY9MTAsMDAwDQoNCmBgYHtyfQ0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA+IDE5OSAmIGNsYXNzIDwgMzAwKSAlPiUgDQogIGFycmFuZ2UoYXYpICU+JQ0KICAgIGZpbHRlcihhdiA+IDk1MDAgJiBhdiA8IDEwNTAwKSAlPiUNCg0KICMgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KICBtdXRhdGUoI3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QgLyB0YXhfY29kZV9yYXRlLA0KICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIHplcm9fYmlsbCwgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIHN1bW1hcml6ZShtZWRpYW5fQVYgPSBtZWRpYW4oYXYpLA0KICAgICAgICAgICAgbWVkaWFuX0VBViA9IG1lZGlhbihlYXYpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9uZXcgPSBtZWRpYW4oYmlsbF9ub2V4ZW1wcyksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkNCikNCg0KDQpwaW5fZGF0YTIgJT4lIA0KZmlsdGVyKHBpbl9BViA+IDApICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIsICJWSUxMQUdFIE9GIFBIT0VOSVgiLCAiVklMTEFHRSBPRiBXSU5ORVRLQSIsICJWSUxMQUdFIE9GIFJJVkVSREFMRSIpKSAlPiUNCiAgZmlsdGVyKGNsYXNzID4xOTkgJiBjbGFzcyA8IDMwMCkgJT4lIA0KICBhcnJhbmdlKGF2KSAlPiUNCiAgICBmaWx0ZXIoYXYgPiA5NTAwICYgYXYgPCAxMDUwMCkgJT4lDQoNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9lcXVhbGl6ZWRBViA9ICBtZWRpYW4oZXF1YWxpemVkX0FWKSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfbmV3ID0gbWVkaWFuKGJpbGxfbm9leGVtcHMpLA0KICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICBjdXJfY29tcF9UQ19yYXRlID0gbWVhbihjdXJfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpDQopDQoNCg0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA+MTk5ICYgY2xhc3MgPCAzMDApICU+JSANCiAgYXJyYW5nZShhdikgJT4lDQogIGZpbHRlcihhdiA+IDk1MDAgJiBhdiA8IDEwNTAwKSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lKSAlPiUgDQogICAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fZXF1YWxpemVkQVYgPSAgbWVkaWFuKGVxdWFsaXplZF9BViksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gbWVkaWFuKGVhdiksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9jdXIgPSBtZWRpYW4oYmlsbF9jdXJyZW50KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiAgICAgICAgICAgIG1lZGlhbl9jaGFuZ2UgPSBtZWRpYW4oYmlsbF9jaGFuZ2UpLA0KICAgICAgICAgICAgcGVyY2VpdmVkX3NhdmluZ3MgPSBtZWRpYW4odGF4X2FtdF9leGUpLA0KICAgICAgICAgICAgY3VyX2NvbXBfVENfcmF0ZSA9IG1lYW4oY3VyX2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBuZXdfY29tcF9UQ19yYXRlID0gbWVhbihuZXdfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIHBpbmNvdW50PW4oKQ0KKQ0KDQoNCg0KDQpgYGANCg0KIyMjIENsYXNzIDIwMyBvbmx5DQoNCmBgYHtyfQ0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA9PTIwMykgJT4lIA0KICBhcnJhbmdlKGF2KSAlPiUNCiAgZmlsdGVyKGF2ID4gOTUwMCAmIGF2IDwgMTA1MDApICU+JQ0KICMgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KICBtdXRhdGUoI3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QgLyB0YXhfY29kZV9yYXRlLA0KICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUpDQoNCg0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA9PSAyMDMpICU+JSANCiAgYXJyYW5nZShhdikgJT4lDQogIGZpbHRlcihhdiA+IDk1MDAgJiBhdiA8IDEwNTAwKSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lKSAlPiUNCiAgICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9lcXVhbGl6ZWRBViA9ICBtZWRpYW4oZXF1YWxpemVkX0FWKSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfbmV3ID0gbWVkaWFuKGJpbGxfbm9leGVtcHMpLA0KICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICBjdXJfY29tcF9UQ19yYXRlID0gbWVhbihjdXJfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpDQopDQoNCg0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA9PSAyMDMpICU+JSANCiAgYXJyYW5nZShhdikgJT4lDQogIGZpbHRlcihhdiA+IDk1MDAgJiBhdiA8IDEwNTAwKSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JQ0KICAgIHN1bW1hcml6ZShtZWRpYW5fQVYgPSBtZWRpYW4oYXYpLA0KICAgICAgICAgICAgbWVkaWFuX2VxdWFsaXplZEFWID0gIG1lZGlhbihlcXVhbGl6ZWRfQVYpLA0KICAgICAgICAgICAgbWVkaWFuX0VBViA9IG1lZGlhbihlYXYpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9uZXcgPSBtZWRpYW4oYmlsbF9ub2V4ZW1wcyksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkNCikNCg0KDQpwaW5fZGF0YTIgJT4lIA0KZmlsdGVyKHBpbl9BViA+IDApICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiVklMTEFHRSBPRiBQQVJLIEZPUkVTVCIsICJWSUxMQUdFIE9GIFBIT0VOSVgiLCAgIlZJTExBR0UgT0YgUklWRVJEQUxFIikpICU+JQ0KIGZpbHRlcihjbGFzcyA9PSAyMDMpICU+JSANCiMgZmlsdGVyKGNsYXNzID4xOTkgJiBjbGFzcyA8IDMwMCkgJT4lIA0KDQogIGFycmFuZ2UoYXYpICU+JQ0KICBmaWx0ZXIoYXYgPiA5MDAwICYgYXYgPCAxMTAwMCkgJT4lDQogIyBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIG11dGF0ZSgjdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdCAvIHRheF9jb2RlX3JhdGUsDQogICAgIyBjdXJyZW50IGJpbGwgPSBjdXJyZW50IHRheCByYXRlICogcG9ydGlvbiBvZiBsZXZ5IGJpbGxlZA0KICAgICAgICAgYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQogICAgICAgICBiaWxsX25vZXhlbXBzID0gIG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUNCiAgICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9lcXVhbGl6ZWRBViA9ICBtZWRpYW4oZXF1YWxpemVkX0FWKSwNCiAgICAgICAgICAgIHRheGFibGVfZWF2ID0gbWVhbihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9jdXIgPSBtZWRpYW4oYmlsbF9jdXJyZW50KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiAgICAgICAgICAgIG1lZGlhbl9jaGFuZ2UgPSBtZWRpYW4oYmlsbF9jaGFuZ2UpLA0KICAgICAgICAgICAgcGVyY2VpdmVkX3NhdmluZ3MgPSBtZWRpYW4odGF4X2FtdF9leGUpLA0KICAgICAgICAgICAgY3VyX2NvbXBfVENfcmF0ZSA9IG1lYW4oY3VyX2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBuZXdfY29tcF9UQ19yYXRlID0gbWVhbihuZXdfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIHBpbmNvdW50PW4oKQ0KKQ0KYGBgDQojIEV4cG9ydCBEYXRhIGZvciBBbGwgTXVuaWNpcGFsaXRpZXMgDQoNCkV4cG9ydGVkIGZpbGUgdXNlcyBhbiBBViBvZiAxNTAwMCBmb3IgdGhlIFBJTiBBViByYW5nZQ0KYGBge3IgZXhwb3J0LWRhdGF9DQojIA0KIyAjIyBBViByYW5nZSBhcm91bmQgMTAwMDAsIGFsbCBDbGFzcyAyDQojIA0KIyBwaW5fZGF0YTIgJT4lIA0KIyBmaWx0ZXIocGluX0FWID4gMCkgJT4lIA0KIyAgIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgICJWSUxMQUdFIE9GIFJJVkVSREFMRSIpKSAlPiUNCiMgICMgZmlsdGVyKGNsYXNzID09IDIwMykgJT4lIA0KIyAgZmlsdGVyKGNsYXNzID4xOTkgJiBjbGFzcyA8IDMwMCkgJT4lIA0KIyANCiMgICBhcnJhbmdlKGF2KSAlPiUNCiMgICBmaWx0ZXIoYXYgPiA5MDAwICYgYXYgPCAxMTAwMCkgJT4lDQojICAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiMgICBtdXRhdGUoI3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QgLyB0YXhfY29kZV9yYXRlLA0KIyAgICAgIyBjdXJyZW50IGJpbGwgPSBjdXJyZW50IHRheCByYXRlICogcG9ydGlvbiBvZiBsZXZ5IGJpbGxlZA0KIyAgICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiMgICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KIyAgICAgICAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KIyAgIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JQ0KIyAgICAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQojICAgICAgICAgICAgIG1lZGlhbl9lcXVhbGl6ZWRBViA9ICBtZWRpYW4oZXF1YWxpemVkX0FWKSwNCiMgICAgICAgICAgICAgdGF4YWJsZV9lYXYgPSBtZWFuKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiMgICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQojICAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiMgICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQojICAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiMgICAgICAgICAgICAgY3VyX2NvbXBfVENfcmF0ZSA9IG1lYW4oY3VyX2NvbXBfVENfcmF0ZSksDQojICAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KIyAgICAgICAgICAgICBjbGFzcyA9IGZpcnN0KGNsYXNzKSwNCiMgICAgICAgICAgICAgcGluY291bnQ9bigpDQojICkNCiMgI3dyaXRlX2NzdihtZWRpYW5FQVZzX2luTXVuaXMsICJyZXF1ZXN0c19tZWRpYW5FQVZfaW5NdW5pcy5jc3YiICkNCg0KDQojIyBBViByYW5nZSBhcm91bmQgJDE1LDAwMCwgYWxsIENsYXNzIDINCnBpbl9kYXRhMiAlPiUgDQpmaWx0ZXIocGluX0FWID4gMCkgJT4lIA0KIGZpbHRlcihjbGFzcyA+MTk5ICYgY2xhc3MgPCAzMDApICU+JSANCg0KICBhcnJhbmdlKGF2KSAlPiUNCiAgZmlsdGVyKGF2ID4gMTQwMDAgJiBhdiA8IDE2MDAwKSAlPiUNCiAgbXV0YXRlKA0KICAgICAgICAgIyBjdXJyZW50IGJpbGwgPSBjdXJyZW50IHRheCByYXRlICogcG9ydGlvbiBvZiBsZXZ5IGJpbGxlZA0KICAgICAgICAgYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQogICAgICAgICBiaWxsX25vZXhlbXBzID0gIG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUNCiAgICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9lcXVhbGl6ZWRBViA9ICBtZWRpYW4oZXF1YWxpemVkX0FWKSwNCiAgICAgICAgICAgIHRheGFibGVfZWF2ID0gbWVhbihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9jdXIgPSBtZWRpYW4oYmlsbF9jdXJyZW50KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiAgICAgICAgICAgIG1lZGlhbl9jaGFuZ2UgPSBtZWRpYW4oYmlsbF9jaGFuZ2UpLA0KICAgICAgICAgICAgcGVyY2VpdmVkX3NhdmluZ3MgPSBtZWRpYW4odGF4X2FtdF9leGUpLA0KICAgICAgICAgICAgY3VyX2NvbXBfVENfcmF0ZSA9IG1lYW4oY3VyX2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBuZXdfY29tcF9UQ19yYXRlID0gbWVhbihuZXdfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIGNsYXNzID0gbW9kZShjbGFzcyksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkpICMgJT4lIHdyaXRlX2NzdigicmVxdWVzdHNfYXYxNTAwMF9hbGxNdW5pcy5jc3YiKQ0KDQoNCiMgQ2FsY3VsYXRpb25zIGZvciBiaWxsIGNoYW5nZSB0aGUgbWVkaWFuIEVBViBpbiBlYWNoIG11bmkNCm1lZGlhbkVBVnNfaW5NdW5pcyA8LSBwaW5fZGF0YTIgJT4lIA0KICBmaWx0ZXIocGluX0FWID4gMCkgJT4lIA0KICBmaWx0ZXIoY2xhc3MgPjE5OSAmIGNsYXNzIDwgMzAwKSAlPiUgDQogIGFycmFuZ2UoYXYpICU+JQ0KICBtdXRhdGUoDQogICAgIyBjdXJyZW50IGJpbGwgPSBjdXJyZW50IHRheCByYXRlICogcG9ydGlvbiBvZiBsZXZ5IGJpbGxlZA0KICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUNCiAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fZXF1YWxpemVkQVYgPSAgbWVkaWFuKGVxdWFsaXplZF9BViksDQogICAgICAgICAgICB0YXhhYmxlX2VhdiA9IG1lYW4oZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9uZXcgPSBtZWRpYW4oYmlsbF9ub2V4ZW1wcyksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkpDQoNCiMgQmlsbCBjaGFuZ2UgY2FsY3VsYXRpb25zIGZvciBwcm9wZXJ0aWVzIHdpdGggQVZzIG9mICQxNTAsMDAwDQpwaW5fZGF0YTIgJT4lIA0KZmlsdGVyKHBpbl9BViA+IDApICU+JSANCiBmaWx0ZXIoY2xhc3MgPjE5OSAmIGNsYXNzIDwgMzAwKSAlPiUgDQogIGFycmFuZ2UoYXYpICU+JQ0KICBmaWx0ZXIoYXYgPiAxNDAwMDAgJiBhdiA8IDE2MDAwMCkgJT4lDQogIG11dGF0ZSgNCiAgICAgICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lDQogICAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fZXF1YWxpemVkQVYgPSAgbWVkaWFuKGVxdWFsaXplZF9BViksDQogICAgICAgICAgICB0YXhhYmxlX2VhdiA9IG1lYW4oZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9uZXcgPSBtZWRpYW4oYmlsbF9ub2V4ZW1wcyksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBjbGFzcyA9IGZpcnN0KGNsYXNzKSwNCiAgICAgICAgICAgIHBpbmNvdW50PW4oKSkgIyAlPiUgd3JpdGVfY3N2KCJyZXF1ZXN0c19hdjE1MDAwMF9hbGxNdW5pcy5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIlZJTExBR0UgT0YgUEFSSyBGT1JFU1QiLCAiVklMTEFHRSBPRiBQSE9FTklYIiwgIlZJTExBR0UgT0YgV0lOTkVUS0EiLCAiVklMTEFHRSBPRiBSSVZFUkRBTEUiKSkgJT4lDQojICBmaWx0ZXIoY2xhc3MgPT0gMjAzKSAlPiUgDQogICAgZmlsdGVyKGNsYXNzID4xOTkgJiBjbGFzcyA8IDMwMCkgJT4lIA0KDQogIGFycmFuZ2UoYXYpICU+JQ0KICBmaWx0ZXIoYXYgPiAxNDUwMCAmIGF2IDwgMTU1MDApICU+JQ0KICMgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KICBtdXRhdGUoI3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QgLyB0YXhfY29kZV9yYXRlLA0KICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUpICU+JQ0KICAgIHN1bW1hcml6ZShtZWRpYW5fQVYgPSBtZWRpYW4oYXYpLA0KICAgICAgICAgICAgbWVkaWFuX2VxdWFsaXplZEFWID0gIG1lZGlhbihlcXVhbGl6ZWRfQVYpLA0KICAgICAgICAgICAgdGF4YWJsZV9lYXYgPSBtZWFuKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfbmV3ID0gbWVkaWFuKGJpbGxfbm9leGVtcHMpLA0KICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICBjdXJfY29tcF9UQ19yYXRlID0gbWVhbihjdXJfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpDQopDQpgYGANCg0KDQo=