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")


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)


### Summarizing it from tax code to municipality weights the rates incorrectly (since some tax codes have waaaay more pins than others) ### 


# taxcode_taxrates %>% 
#   right_join(muni_tax_codes, by = c("tax_code" = "tax_code_num")) %>% 
#   group_by(agency_num) %>% 
#   summarize(cur_comp_TC_rate = mean(cur_comp_TC_rate, na.rm=TRUE),
#             new_comp_TC_rate = mean(new_comp_TC_rate, na.rm = TRUE)) %>% right_join(muni_agency_names) %>%
#   arrange(agency_name) 
# %>% write_csv("4c_tc_taxrates.csv")

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.

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

head(pin_data2)
dim(pin_data2)
## [1] 1864594      53
pin_data2 <- pin_data2 %>% 
  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)


muni_taxrates <- pin_data2 %>% 
  group_by(agency_name)  %>%
  
  summarize(
    av = sum(av, na.rm = TRUE),
    eav = sum(eav, na.rm = TRUE),
    equalized_AV = sum(equalized_AV, na.rm = TRUE),
    pins_in_class = 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)) %>%
  select(agency_name, 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")

Bill Distributions

pin_data2 %>%
  filter(major_class_code == 2 & bill_current < 30000 & agency_name == "VILLAGE OF DOLTON") %>% 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, 1500))+
  labs(x="Dolton's Actual Tax Bills With Current Exemptions", y = "Number of Tax Bills")

pin_data2 %>%
  filter(major_class_code == 2 & bill_noexemps < 30000 & agency_name == "VILLAGE OF DOLTON") %>% 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, 1500))+

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

pin_data2 %>%
  filter(major_class_code == 2 & agency_name == "VILLAGE OF GLENCOE") %>% 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,60000)) + 
#    scale_y_continuous(limits = c(0, 1500))+

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

pin_data2 %>%
  filter(major_class_code == 2 & agency_name == "VILLAGE OF GLENCOE") %>% 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,60000)) + 
#    scale_y_continuous(limits = c(0, 1500))+

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

pin_data2 %>%
  filter(major_class_code == 2 & bill_current < 30000 & agency_name == "CITY OF CHICAGO") %>% 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="Chicago's Actual Tax Bills With Current Exemptions", x= "Dollars", y = "Number of Tax Bills")

pin_data2 %>%
  filter(major_class_code == 2  & agency_name == "CITY OF CHICAGO") %>% 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="Chicago'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 DOLTON") %>% 
  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(-2800,2800)) +
  scale_y_continuous(limits = c(0, 2000))+
  labs(title="Dolton'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 == "CITY OF CHICAGO") %>% 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(-2800,2800)) + 
  scale_y_continuous(limits = c(0, 200000))+

  labs(title ="Chicago'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 GLENCOE") %>% 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(-5,20000)) + 
#    scale_y_continuous(limits = c(0, 1500))+

  labs(title="Glencoe'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("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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()
)

For all Class 2 Properties:

In Chicago: If they didn’t claim an exemption (n = 331,492), median bill decreases by $168. If they do currently claim an exemption (n = 401,450), the median bill increases $330 (BUT they think they are saving $671 due to exempt EAV * higher tax rate amount that shows up on their tax bills!)

In Dolton: If they didn’t claim an exemption (n = 2,633), median bill decreases by $1241. If they do currently claim an exemption (n = 5,639), the median bill increases $1090 (BUT they think they are saving $2791 due to exempt EAV * higher tax rate amount that shows up on their tax bills!)

has_HO exemp median bill_cur median bill_new median change pin count perceived savings
Chicago 0 3389.3 3043.7 -168.2 331492 0.0
Chicago 1 3757.1 4029.7 330.5 401450 671.6
Dolton 0 6051.9 4792.4 -1241.1 2633 0.0
Dolton 1 3802.3 4868.6 1090.4 5639 2791.5

If we do not care whether they do or do not currently receive the general homestead exemption, then the median change is a decrease of $3 in Chicago (732,942 pins) and an increase of $769 in Dolton (8,272 pins).

median bill_current median bill_new median change pincount perceived savings
Chicago 3619 3642.87 -2.90 732942 669.7
Dolton 4305 4846.94 769.12 8272 2293.7

The median Class 2 tax payer thinks they are saving $670 when they really are saving no money due to current exemptions within Chicago and the median taxpayer in Dolton thinks they are saving \$2,294 but are only saving $770 due to the higher tax rates that result from the decrease in taxable EAV that occurs from those that claim the general homested exemption.

tax_bill_change_HO <- pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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) %>% 
  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))
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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))

has_HO_exemp

<dbl>

median_bill_cur

<dbl>

median_bill_new

<dbl>

median_change

<dbl>

pincount

<int>

perceived_savings

<dbl>

CITY OF CHICAGO 0 3418 2970 -369 32128 0.0
CITY OF CHICAGO 1 3151 3268 269 102677 6712
VILLAGE OF DOLTON 0 6298 5006 -1295 1103 0.0
VILLAGE OF DOLTON 1 3441 4629 1186 2506 2792

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

For Chicago class 213 properties, the median tax bill would go down $370 for those who don’t currently have a general homestead exemption and would increase $270 for people who do currently claim the general homestead exemption. 32K people don’t claim the exemption and 102K people do.

Dolton class 213 median properties have a decrease of $1295 if they didn’t claim homestead exemptions currently and increased $1186 f they did already claim the general homestead exemption. 1100 people do not claim the exemption and 2500 people do claim the general homestead exemption.

Class 213 Properties median bill_cur median bill_new median change pincount perceived savings
Chicago 3151 3258 175 134805 670
Dolton 4152 4770 1009 3609 2294

Compare AV=10,000

pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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()
)
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  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()
)

compare AV of 15K

Glencoe doesn’t have PINs that are in the 10,000 AV range… So same format as tables above but uses AV value = $15,000 +/- 500

pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
#  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, 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()
)
pin_data2 %>% 
filter(pin_AV > 0) %>% 
  filter(agency_name %in% c("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
#  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()
)

Class 300 & All Other Classes

pin_data2 %>% 
  filter(agency_name %in% c("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  filter(class >299 & class < 400) %>% 
  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) %>% 
  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))
pin_data2 %>% 
  filter(agency_name %in% c("CITY OF CHICAGO", "VILLAGE OF DOLTON", "VILLAGE OF GLENCOE")) %>%
  filter(class>399) %>% 
  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) %>% 
  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))
LS0tDQp0aXRsZTogJ0h5cG90aGV0aWNhbCBUYXhiaWxsczogUmVtb3ZlIEdlbmVyYWwgSG9tZXN0ZWFkIEV4ZW1wdGlvbnMnDQphdXRob3I6ICJBV00iDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQotLS0NCg0KYGBge3Igc2V0dXAsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFKQ0KDQoNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShnc3RhdCkNCmxpYnJhcnkocHRheHNpbSkNCmxpYnJhcnkoZ2x1ZSkNCg0KDQoNCmBgYA0KDQojIEJyaW5nIGluIGRhdGENCg0KQmlsbHMgd2VyZSBwdWxsZWQgZnJvbSBQVEFYU0lNIGFtZCBzdW1tZWQgdG8gdGhlIHBpbiBsZXZlbCBpbiBmaWxlcyBgMV8uLi5ybWRgIGFuZCBgMi4uLnJtZGAuDQpFeGVtcHRpb24gZGF0YSBwZXIgUElOIHdhcyBwdWxsZWQgZnJvbSBQVEFYU0lNIGluIGZpbGUgYDNfLi4uLi5ybWRgLg0KDQpgYGB7cn0NCnB0YXhzaW1fZGJfY29ubiA8LSBEQkk6OmRiQ29ubmVjdChSU1FMaXRlOjpTUUxpdGUoKSwgIi4vcHRheHNpbS5kYi9wdGF4c2ltLTIwMjEuMC40LmRiIikNCg0KDQptdW5pX2FnZW5jeV9uYW1lcyA8LSBEQkk6OmRiR2V0UXVlcnkoDQogIHB0YXhzaW1fZGJfY29ubiwNCiAgIlNFTEVDVCBESVNUSU5DVCBhZ2VuY3lfbnVtLCBhZ2VuY3lfbmFtZSwgbWlub3JfdHlwZQ0KICBGUk9NIGFnZW5jeV9pbmZvDQogIFdIRVJFIG1pbm9yX3R5cGUgPSAnTVVOSScNCiAgT1IgYWdlbmN5X251bSA9ICcwMjAwNjAwMDAnICANCg0KICAiDQopDQoNCm11bmlfdGF4X2NvZGVzIDwtIERCSTo6ZGJHZXRRdWVyeSgNCiAgcHRheHNpbV9kYl9jb25uLA0KICBnbHVlX3NxbCgiDQogIFNFTEVDVCBESVNUSU5DVCBhZ2VuY3lfbnVtLCB0YXhfY29kZV9udW0NCiAgRlJPTSB0YXhfY29kZQ0KICBXSEVSRSBhZ2VuY3lfbnVtIElOICh7bXVuaV9hZ2VuY3lfbmFtZXMkYWdlbmN5X251bSp9KQ0KICBBTkQgeWVhciA9IDIwMjENCiAgIiwNCiAgLmNvbiA9IHB0YXhzaW1fZGJfY29ubg0KICApDQopICU+JSANCiAgbXV0YXRlKHRheF9jb2RlX251bSA9IGFzLm51bWVyaWModGF4X2NvZGVfbnVtKSkNCg0KdGF4X2NvZGVzIDwtIERCSTo6ZGJHZXRRdWVyeSgNCiAgcHRheHNpbV9kYl9jb25uLA0KICBnbHVlX3NxbCgiDQogIFNFTEVDVCBESVNUSU5DVCB0YXhfY29kZV9udW0sIHRheF9jb2RlX3JhdGUNCiAgRlJPTSB0YXhfY29kZQ0KICBXSEVSRSB5ZWFyID0gMjAyMQ0KICAiLA0KICAuY29uID0gcHRheHNpbV9kYl9jb25uDQogICkNCikgJT4lIG11dGF0ZSh0YXhfY29kZV9udW0gPSBhcy5udW1lcmljKHRheF9jb2RlX251bSkpDQpgYGANCg0KYGBge3IgZXZhbCA9IEZBTFNFfQ0KdGF4YmlsbHNfY3VycmVudCA8LSByZWFkX2NzdigiLi9PdXRwdXQvRG9udF9VcGxvYWQvMV9HZXRfQWxsX1BpbnMtQ29va1BpblRheGJpbGxzXzIwMjFfQWN0dWFsLmNzdiIpDQojIDIyLDQ1Myw4NzUgdGF4IGJpbGxzIGluIDIwMjEgaW4gbXVuaWNpcGFsaXRpZXMuIA0KIyB0YXhpbmcgYWdlbmN5LVBJTiBpcyB0aGUgdW5pdCBvZiBvYnNlcnZhdGlvbiBoZXJlIChvbmx5IHBhcnRpYWwgcHJvcGVydHkgdGF4IGJpbGxzKQ0KIyBFYWNoIFBJTiBoYXMgbXVsdGlwbGUgcm93cyAoYmVjYXVzZSBpdCBpcyB0YXhlZCBieSBtdWx0aXBsZSB0YXhpbmcgYWdlbmNpZXMpDQoNCnNhcHBseSh0YXhiaWxsc19jdXJyZW50LCBmdW5jdGlvbih4KSBzdW0oaXMubmEoeCkpKQ0KDQoNCiMgMSw4MjUsODE2IGJpbGxlZCBwcm9wZXJ0aWVzIHdpdGggMTQtZGlnaXQgUElOcyBpbiBpbmNvcm9yYXRlZCBhcmVhcw0KIyAxLDg2NCw1OTQgaW4gaW5jb3Jwb3J0ZWQgYW5kIHVuaW5jb3Jwb3JhdGVkIGFyZWFzLg0KcGluMTRfYmlsbHNfY3VycmVudCA8LSB0YXhiaWxsc19jdXJyZW50ICU+JQ0KICBncm91cF9ieSh0YXhfY29kZSwgY2xhc3MsIHBpbikgJT4lDQogIA0KICBtdXRhdGUodG90YWxfYmlsbCA9IGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZikgJT4lICMgZnJvbSBlYWNoIHRheGluZyBhZ2VuY3kNCiAgDQogIHN1bW1hcml6ZSgNCiAgICB0b3RhbF9iaWxsZWQgPSBzdW0odG90YWxfYmlsbCwgbmEucm0gPSBUUlVFKSwgIyB0b3RhbCBvbiBzb21lb25lJ3MgcHJvcGVydHkgdGF4IGJpbGwNCiAgICBhdiA9IGZpcnN0KGF2KSwNCiAgICBlYXYgPSBmaXJzdChlYXYpLA0KICAgICMgcGluX2NvdW50X2luX3BhcmNlbCA9IG4oKSwNCiAgICBmaW5hbF90YXhfdG9fZGlzdCA9IHN1bShmaW5hbF90YXhfdG9fZGlzdCwgbmEucm0gPSBUUlVFKSwNCiAgICBmaW5hbF90YXhfdG9fdGlmID0gc3VtKGZpbmFsX3RheF90b190aWYsIG5hLnJtID0gVFJVRSksDQogICAgdGF4X2FtdF9leGUgPSBzdW0odGF4X2FtdF9leGUsIG5hLnJtID0gVFJVRSksICMgcmV2ZW51ZSBsb3N0IGR1ZSB0byBleGVtcHRpb25zDQogICAgdGF4X2FtdF9wcmVfZXhlID0gc3VtKHRheF9hbXRfcHJlX2V4ZSwgbmEucm0gPSBUUlVFKSwgIyB0b3RhbCByZXYgYmVmb3JlIGFsbCBleGVtcHRpb25zDQogICAgdGF4X2FtdF9wb3N0X2V4ZSA9IHN1bSh0YXhfYW10X3Bvc3RfZXhlLCBuYS5ybSA9IFRSVUUpLCAjIHRvdGFsIHJldiBhZnRlciBhbGwgZXhlbXB0aW9ucw0KICAgIHJwbV90aWZfdG9fY3BzID0gc3VtKHJwbV90aWZfdG9fY3BzLCBuYS5ybSA9IFRSVUUpLCAjIG5vdCB1c2VkDQogICAgcnBtX3RpZl90b19ycG0gPSBzdW0ocnBtX3RpZl90b19ycG0sIG5hLnJtPVRSVUUpLCAjIG5vdCB1c2VkDQogICAgcnBtX3RpZl90b19kaXN0ID0gc3VtKHJwbV90aWZfdG9fZGlzdCwgbmEucm09VFJVRSksICMgbm90IHVzZWQNCiAgICB0aWZfc2hhcmUgPSBtZWFuKHRpZl9zaGFyZSwgbmEucm09VFJVRSksICMgbm90IHVzZWQNCiAgKSAgJT4lIA0KICBtdXRhdGUocHJvcGNsYXNzXzFkaWcgPSBzdHJfc3ViKGNsYXNzLCAxLCAxKSkNCg0KIyBoZWFkKHBpbjE0X2JpbGxzX2N1cnJlbnQpDQoNCnNhcHBseShwaW4xNF9iaWxsc19jdXJyZW50LCBmdW5jdGlvbih4KSBzdW0oaXMubmEoeCkpKQ0KDQoNCiMgTm93IGdyb3VwIGFnYWluIGFuZCBzdW0gdmFsdWVzIGZvciB0YXggY29kZSBhbmQgZWFjaCBwcm9wZXJ0eSBjbGFzcyENCg0KIyBUaGVyZSBhcmUgMjgsMzgxIHByb3BlcnR5IGNsYXNzIC0gdGF4IGNvZGUgZ3JvdXAgY29tYmluYXRpb25zIGluIGluY29ycG9yYXRlZCBhcmVhcy4NCiMgVGhlcmUgYXJlIDI4LDUzNCBwcm9wZXJ0eSBjbGFzcyAtIHRheCBjb2RlIGdyb3VwIGNvbWJvcyBpbiBpbmNvcnBvcmF0ZWQgKyB1bmluY29ycG9yYXRlZCBhcmVhcw0KDQpybSh0YXhiaWxsc19jdXJyZW50KQ0KYGBgDQoNCiMgQWRkIGV4ZW1wdGlvbiB0eXBlcyB0byBwaW4gbGV2ZWwgdGF4IGJpbGxzDQoNCk5lZWQgdG8gbWVyZ2UgUElOIGxldmVsIGRhdGEgb2YgdGF4IGJpbGxzIGFuZCBleGVtcHRpb25zIHBlciBQSU4gaWYgdGhlIGdvYWwgaXMgdG8gY2FsY3VsYXRlIG5ldyB0YXggcmF0ZXMgZm9yIGRpZmZlcmVudCBzY2VuYXJpb3MgQU5EIHZpZXcgaW5kaXZpZHVhbCBsZXZlbCB0YXggYmlsbCBjaGFuZ2VzLiAoaS5lLiBpZiB3ZSB3YW50IHRvIGxvb2sgYXQgdGhlICJtZWRpYW4gdGF4cGF5ZXIiIHRoZW4gbmVlZCB0byB1c2UgdGhpcyBtZXRob2QpLg0KDQpOb3RlOiBUaGUgRUFWIGZyb20gdGhlIGV4ZW1wdGlvbiB0YWJsZSBpcyB0aGUgb3JpZ2luYWwgRUFWIChBViBcKiBlcXVhbGl6ZXIpIHdpdGhvdXQgY29uc2lkZXIgVElGcyBvciBleGVtcHRpb25zLg0KDQozMSwwMDAgcHJvcGVydGllcyBoYXZlICQwIHRheCBiaWxscyBiYXNlZCBvbiBleGVtcHRpb24gZGF0YSB0YWJsZSBtYWRlIGZyb20gUFRBWFNJTSdzIGBwaW5gIHRhYmxlLiANCihVc2luZyB0aGUgdGF4IGJpbGwgZGF0YSBhbGxvd3MgZm9yIG1vcmUgaW4gZGVwdGggbG9vayBhdCB0YXggYmlsbHMgYW5kIGNhbiBjcmVhdGUgdmFyaWFibGVzIHN1Y2ggYXMgYHNtYWxsX2JpbGxgIGlmIGJpbGxzIHdlcmUgbGVzcyB0aGFuICQxMDAgYWZ0ZXIgZXhlbXB0aW9ucyB3ZXJlIGFwcGxpZWQpLiANCg0KYGBge3IgZXZhbCA9IEZBTFNFfQ0KcGluX2VhdiA8LSByZWFkX2NzdigiLi9PdXRwdXQvRG9udF9VcGxvYWQvM19FeGVtcHRpb25fRGV0YWlsc19vdXRwdXQtYWxsX2Nvb2tfcGluX2V4ZW1wdGlvbnNfMjAyMV9hY3R1YWwuY3N2IikgJT4lDQogICNmaWx0ZXIoY2xhc3NfY29kZSAhPTApICU+JQ0KICANCiAgbXV0YXRlKGFsbF9leGVtcHRpb25zID0gZXhlX2hvbWVvd25lciArIGV4ZV9zZW5pb3IgKyBleGVfZnJlZXplICsgZXhlX2xvbmd0aW1lX2hvbWVvd25lciArIA0KICAgICAgICAgICBleGVfZGlzYWJsZWQgKyBleGVfdmV0X3JldHVybmluZyArIGV4ZV92ZXRfZGlzX2x0NTAgKyBleGVfdmV0X2Rpc181MF82OSArIGV4ZV92ZXRfZGlzX2dlNzAgKyBleGVfYWJhdGUpICU+JQ0KICBtdXRhdGUoemVyb19iaWxsID0gaWZlbHNlKGVhdiA8PSBhbGxfZXhlbXB0aW9ucywgMSwgMCksDQogICAgICAgICBoYXNfSE9fZXhlbXAgPSBpZmVsc2UoZXhlX2hvbWVvd25lciA+IDAsIDEsIDApKSAlPiUNCiAgcmVuYW1lKGVxdWFsaXplZF9BViA9IGVhdiwNCiAgICAgICAgIHBpbl9BViA9IGF2KQ0KDQojIHRhYmxlKHBpbl9lYXYkemVyb19iaWxsKQ0KDQp0YWJsZShwaW5fZWF2JG1ham9yX2NsYXNzX2NvZGUsIHBpbl9lYXYkemVyb19iaWxsKQ0KDQojIHRhYmxlKHBpbl9lYXYkbWFqb3JfY2xhc3NfY29kZSwgcGluX2VhdiRoYXNfSE9fZXhlbXApDQoNCg0KDQojIyBBZGQgZXhlbXB0aW9uIHR5cGVzIGFuZCB2YWx1ZXMgdG8gdGhlIHRheCBiaWxsIGRhdGEgYXQgUElOIGxldmVsDQpwaW5fZGF0YSA8LSBsZWZ0X2pvaW4ocGluMTRfYmlsbHNfY3VycmVudCwgcGluX2VhdiwgYnkgPSBjKCJwaW4iLCAiY2xhc3MiID0gImNsYXNzX2NvZGUiICkpDQoNCiMjIEFkZCB0YXggY29kZSB0YXggcmF0ZSB0byBQSU4gbGV2ZWwgZGF0YQ0KcGluX2RhdGEgPC0gbGVmdF9qb2luKHBpbl9kYXRhLCB0YXhfY29kZXMsIGJ5ID0gYygidGF4X2NvZGUiID0gInRheF9jb2RlX251bSIpKQ0KDQoNCg0KYGBgDQoNCg0KDQoNCiMjIENhbGN1bGF0ZSBuZXcgdGF4IHJhdGVzDQoNCg0KDQpgYGB7ciB0YXhjb2RlLXRheHJhdGVzLCBldmFsID0gRkFMU0V9DQojIHRheGNvZGVzX2J5X2NsYXNzX2N1cnJlbnQgPC0gcGluX2RhdGEgJT4lIA0KIyAgIGdyb3VwX2J5KHRheF9jb2RlLCBjbGFzcykgICU+JQ0KIyAgIA0KIyAgIHN1bW1hcml6ZSgNCiMgICAgIGF2ID0gc3VtKGF2KSwNCiMgICAgIGVhdiA9IHN1bShlYXYpLA0KIyAgICAgZXF1YWxpemVkX0FWID0gc3VtKGVxdWFsaXplZF9BViksDQojICAgICBwaW5zX2luX2NsYXNzID0gbigpLA0KIyAgICAgY3VycmVudF9leGVtcHRpb25zID0gc3VtKGFsbF9leGVtcHRpb25zKSwNCiMgICAgIEhPX2V4ZW1wcyA9IHN1bShleGVfaG9tZW93bmVyKSwNCiMgICAgIHRheF9jb2RlX3JhdGUgPSBmaXJzdCh0YXhfY29kZV9yYXRlKSwNCiMgICAgIGZpbmFsX3RheF90b19kaXN0ID0gc3VtKGZpbmFsX3RheF90b19kaXN0LCBuYS5ybSA9IFRSVUUpLCAjIHVzZWQgYXMgTEVWWSBhbW91bnQhISANCiMgICAgIGZpbmFsX3RheF90b190aWYgPSBzdW0oZmluYWxfdGF4X3RvX3RpZiwgbmEucm0gPSBUUlVFKSwNCiMgICAgIHRheF9hbXRfZXhlID0gc3VtKHRheF9hbXRfZXhlLCBuYS5ybSA9IFRSVUUpLCANCiMgICAgIHRheF9hbXRfcHJlX2V4ZSA9IHN1bSh0YXhfYW10X3ByZV9leGUsIG5hLnJtID0gVFJVRSksIA0KIyAgICAgdGF4X2FtdF9wb3N0X2V4ZSA9IHN1bSh0YXhfYW10X3Bvc3RfZXhlLCBuYS5ybSA9IFRSVUUpLA0KIyAgICAgcnBtX3RpZl90b19jcHMgPSBzdW0ocnBtX3RpZl90b19jcHMsIG5hLnJtID0gVFJVRSksICMgbm90IHVzZWQNCiMgICAgIHJwbV90aWZfdG9fcnBtID0gc3VtKHJwbV90aWZfdG9fcnBtLCBuYS5ybT1UUlVFKSwgIyBub3QgdXNlZA0KIyAgICAgcnBtX3RpZl90b19kaXN0ID0gc3VtKHJwbV90aWZfdG9fZGlzdCwgbmEucm09VFJVRSksICMgbm90IHVzZWQNCiMgICAgIHRpZl9zaGFyZSA9IG1lYW4odGlmX3NoYXJlLCBuYS5ybT1UUlVFKSwgIyBub3QgdXNlZA0KIyAgICkgJT4lDQojICAgDQojICAgbXV0YXRlKHRvdGFsX2JpbGxfY3VycmVudCA9IGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZikgJT4lDQojICAgcmVuYW1lKGN1cl9jb21wX1RDX3JhdGUgPSB0YXhfY29kZV9yYXRlKSAlPiUNCiMgICBtdXRhdGUoY3VycmVudF90YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0LyhjdXJfY29tcF9UQ19yYXRlLzEwMCksDQojICAgICAgICAgIG5ld190YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0LyhjdXJfY29tcF9UQ19yYXRlLzEwMCkgKyBIT19leGVtcHMpICU+JQ0KIyAgIG11dGF0ZShuZXdfY29tcF9UQ19yYXRlID0gKGZpbmFsX3RheF90b19kaXN0IC8gbmV3X3RheGFibGVfZWF2KSoxMDApICU+JQ0KIyAgIG11dGF0ZShuZXdfY29tcF9UQ19yYXRlID0gaWZlbHNlKGlzLm5hbihuZXdfY29tcF9UQ19yYXRlKSwgY3VyX2NvbXBfVENfcmF0ZSwgbmV3X2NvbXBfVENfcmF0ZSkpICU+JQ0KIyAgIHNlbGVjdCh0YXhfY29kZSwgY2xhc3MsIGN1cl9jb21wX1RDX3JhdGUsIG5ld19jb21wX1RDX3JhdGUsIGN1cnJlbnRfdGF4YWJsZV9lYXYsIG5ld190YXhhYmxlX2VhdiwgZXZlcnl0aGluZygpKQ0KIyANCiMgDQojIGhlYWQodGF4Y29kZXNfYnlfY2xhc3NfY3VycmVudCkgDQoNCg0KdGF4Y29kZXNfY3VycmVudCA8LSBwaW5fZGF0YSAlPiUgDQogIGdyb3VwX2J5KHRheF9jb2RlKSAgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBhdiA9IHN1bShhdiksDQogICAgZWF2ID0gc3VtKGVhdiksDQogICAgZXF1YWxpemVkX0FWID0gc3VtKGVxdWFsaXplZF9BViksDQogICAgcGluc19pbl9jbGFzcyA9IG4oKSwNCiAgICBjdXJyZW50X2V4ZW1wdGlvbnMgPSBzdW0oYWxsX2V4ZW1wdGlvbnMpLA0KICAgIEhPX2V4ZW1wcyA9IHN1bShleGVfaG9tZW93bmVyKSwNCiAgICB0YXhfY29kZV9yYXRlID0gZmlyc3QodGF4X2NvZGVfcmF0ZSksIA0KICAgIGZpbmFsX3RheF90b19kaXN0ID0gc3VtKGZpbmFsX3RheF90b19kaXN0LCBuYS5ybSA9IFRSVUUpLCAjIHVzZWQgYXMgTEVWWSBhbW91bnQhISANCiAgICBmaW5hbF90YXhfdG9fdGlmID0gc3VtKGZpbmFsX3RheF90b190aWYsIG5hLnJtID0gVFJVRSksDQogICAgdGF4X2FtdF9leGUgPSBzdW0odGF4X2FtdF9leGUsIG5hLnJtID0gVFJVRSksIA0KICAgIHRheF9hbXRfcHJlX2V4ZSA9IHN1bSh0YXhfYW10X3ByZV9leGUsIG5hLnJtID0gVFJVRSksIA0KICAgIHRheF9hbXRfcG9zdF9leGUgPSBzdW0odGF4X2FtdF9wb3N0X2V4ZSwgbmEucm0gPSBUUlVFKSwNCiAgICBycG1fdGlmX3RvX2NwcyA9IHN1bShycG1fdGlmX3RvX2NwcywgbmEucm0gPSBUUlVFKSwgIyBub3QgdXNlZA0KICAgIHJwbV90aWZfdG9fcnBtID0gc3VtKHJwbV90aWZfdG9fcnBtLCBuYS5ybT1UUlVFKSwgIyBub3QgdXNlZA0KICAgIHJwbV90aWZfdG9fZGlzdCA9IHN1bShycG1fdGlmX3RvX2Rpc3QsIG5hLnJtPVRSVUUpLCAjIG5vdCB1c2VkDQogICAgdGlmX3NoYXJlID0gbWVhbih0aWZfc2hhcmUsIG5hLnJtPVRSVUUpLCAjIG5vdCB1c2VkDQogICkgJT4lDQogIA0KICBtdXRhdGUodG90YWxfYmlsbF9jdXJyZW50ID0gZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSAlPiUNCiAgcmVuYW1lKGN1cl9jb21wX1RDX3JhdGUgPSB0YXhfY29kZV9yYXRlKSAlPiUNCiAgbXV0YXRlKGN1cnJlbnRfdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdC8oY3VyX2NvbXBfVENfcmF0ZS8xMDApLA0KICAgICAgICAgbmV3X3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QvKGN1cl9jb21wX1RDX3JhdGUvMTAwKSArIEhPX2V4ZW1wcykgJT4lDQogIG11dGF0ZShuZXdfY29tcF9UQ19yYXRlID0gKGZpbmFsX3RheF90b19kaXN0IC8gbmV3X3RheGFibGVfZWF2KSoxMDApICU+JQ0KICBtdXRhdGUobmV3X2NvbXBfVENfcmF0ZSA9IGlmZWxzZShpcy5uYW4obmV3X2NvbXBfVENfcmF0ZSksIGN1cl9jb21wX1RDX3JhdGUsIG5ld19jb21wX1RDX3JhdGUpKSAlPiUNCiAgc2VsZWN0KHRheF9jb2RlLCBjdXJfY29tcF9UQ19yYXRlLCBuZXdfY29tcF9UQ19yYXRlLCBjdXJyZW50X3RheGFibGVfZWF2LCBuZXdfdGF4YWJsZV9lYXYsIGV2ZXJ5dGhpbmcoKSkNCg0KDQojaGVhZCh0YXhjb2Rlc19jdXJyZW50KSANCg0KDQp0YXhjb2RlX3RheHJhdGVzIDwtIHRheGNvZGVzX2N1cnJlbnQgJT4lIA0KICBzZWxlY3QodGF4X2NvZGUsIGN1cl9jb21wX1RDX3JhdGUsIG5ld19jb21wX1RDX3JhdGUsIGN1cnJlbnRfZXhlbXB0aW9ucywgSE9fZXhlbXBzKQ0KDQoNCiMjIyBTdW1tYXJpemluZyBpdCBmcm9tIHRheCBjb2RlIHRvIG11bmljaXBhbGl0eSB3ZWlnaHRzIHRoZSByYXRlcyBpbmNvcnJlY3RseSAoc2luY2Ugc29tZSB0YXggY29kZXMgaGF2ZSB3YWFhYXkgbW9yZSBwaW5zIHRoYW4gb3RoZXJzKSAjIyMgDQoNCg0KIyB0YXhjb2RlX3RheHJhdGVzICU+JSANCiMgICByaWdodF9qb2luKG11bmlfdGF4X2NvZGVzLCBieSA9IGMoInRheF9jb2RlIiA9ICJ0YXhfY29kZV9udW0iKSkgJT4lIA0KIyAgIGdyb3VwX2J5KGFnZW5jeV9udW0pICU+JSANCiMgICBzdW1tYXJpemUoY3VyX2NvbXBfVENfcmF0ZSA9IG1lYW4oY3VyX2NvbXBfVENfcmF0ZSwgbmEucm09VFJVRSksDQojICAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUsIG5hLnJtID0gVFJVRSkpICU+JSByaWdodF9qb2luKG11bmlfYWdlbmN5X25hbWVzKSAlPiUNCiMgICBhcnJhbmdlKGFnZW5jeV9uYW1lKSANCiMgJT4lIHdyaXRlX2NzdigiNGNfdGNfdGF4cmF0ZXMuY3N2IikNCg0KDQoNCmBgYA0KDQojIEZpbmRpbmcgdGhlICJNZWRpYW4gUHJvcGVydHkiIG9yICJBdmVyYWdlIFRheHBheWVyIg0KDQpUaGUgbWVkaWFuIGFzc2Vzc2VkIHZhbHVlIGlzIHVzZWQgdG8gZGV0ZXJtaW5lIHRoZSBgbWVkaWFuIHByb3BlcnR5YCBmb3IgdmFyaW91cyBncm91cHMgKGUuZy4gdGhlIG11bmljaXBhbGl0eSwgdGhlIDEtZGlnaXQgbWFqb3IgcHJvcGVydHkgY2xhc3MsIGFuZCAzLWRpZ2l0IHByb3BlcnR5IGNsYXNzKS4NCg0KVGhlIGFzc2Vzc2VkIHZhbHVlIGFuZCBvcmlnaW5hbCBlcXVhbGl6ZWQgYXNzZXNzZWQgdmFsdWVzIGNvbWUgZnJvbSB0aGUgYHBpbmAgZGF0YSB0YWJsZSB3aXRoaW4gUFRBWFNJTS4gVGhpcyB0YWJsZSBhbHNvIGhhcyBldmVyeSB0eXBlIG9mIGV4ZW1wdGlvbiB0aGF0IHRoZSBwcm9wZXJ0eSByZWNlaXZlZCBhbmQgdGhlIGFtb3VudCBvZiBFQVYgdGhhdCB3YXMgZXhlbXB0IGR1ZSB0byB0aGUgZXhlbXB0aW9uLg0KDQpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KcGluX2RhdGEyIDwtIGxlZnRfam9pbihwaW5fZGF0YSwgdGF4Y29kZV90YXhyYXRlcywgYnkgPSBjKCJ0YXhfY29kZSIgPSAidGF4X2NvZGUiKSkNCg0KDQpwaW5fZGF0YTIgPC0gcGluX2RhdGEyICU+JSBsZWZ0X2pvaW4obXVuaV90YXhfY29kZXMpIA0KDQpwaW5fZGF0YTIgPC0gcGluX2RhdGEyICU+JSBsZWZ0X2pvaW4obXVuaV9hZ2VuY3lfbmFtZXMpDQoNCndyaXRlX2NzdihwaW5fZGF0YTIsICIuL091dHB1dC80Q19qb2luZWRfUElOc19iaWxsc19hbmRfZXhlbXB0aW9ucy5jc3YiKQ0KDQojaGVhZChwaW5fZGF0YTIpDQoNCmBgYA0KDQo8IS0tLSBDaGFuZ2VkIGNhbGN1bGF0aW9uIGZvciBtdW5pIHRheCByYXRlcyBiZWxvdyBvbiBOb3ZlbWJlciAxc3QuIA0KV2hlbiBhZ2dyZWdhdGluZyBwaW4gdGF4IGJpbGxzIHRvIHRoZSBtdW5pY2lwYWxpdHkgbGV2ZWwsIGZpcnN0KHRheF9jb2RlX3JhdGUpDQp3YXMgdXNlZCBpbnN0ZWFkIG9mIGF2Zyh0YXhfY29kZV9yYXRlKSB3aGljaCBwcm9iYWJseSBtZXNzZXMgdXAgYSBmZXcgDQptdW5pJ3MgYXZnIGNvbXBvc2l0ZSB0YXggcmF0ZXMuIDRjX211bmlfcmF0ZXMuY3N2IG1heSBoYXZlIGhhZCBpbmNvcnJlY3QgcmF0ZXMgLS0tPg0KDQpgYGB7cn0NCg0KcGluX2RhdGEyIDwtIHJlYWRfY3N2KCIuL091dHB1dC80Q19qb2luZWRfUElOc19iaWxsc19hbmRfZXhlbXB0aW9ucy5jc3YiKQ0KDQpoZWFkKHBpbl9kYXRhMikNCmRpbShwaW5fZGF0YTIpDQoNCnBpbl9kYXRhMiA8LSBwaW5fZGF0YTIgJT4lIA0KICBtdXRhdGUoDQogICAgYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQogICAgYmlsbF9ub2V4ZW1wcyA9IG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KQ0KDQoNCm11bmlfdGF4cmF0ZXMgPC0gcGluX2RhdGEyICU+JSANCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUpICAlPiUNCiAgDQogIHN1bW1hcml6ZSgNCiAgICBhdiA9IHN1bShhdiwgbmEucm0gPSBUUlVFKSwNCiAgICBlYXYgPSBzdW0oZWF2LCBuYS5ybSA9IFRSVUUpLA0KICAgIGVxdWFsaXplZF9BViA9IHN1bShlcXVhbGl6ZWRfQVYsIG5hLnJtID0gVFJVRSksDQogICAgcGluc19pbl9jbGFzcyA9IG4oKSwNCiAgICBjdXJyZW50X2V4ZW1wdGlvbnMgPSBzdW0oYWxsX2V4ZW1wdGlvbnMsIG5hLnJtID0gVFJVRSksDQogICAgSE9fZXhlbXBzID0gc3VtKGV4ZV9ob21lb3duZXIsIG5hLnJtID0gVFJVRSksDQogICAgdGF4X2NvZGVfcmF0ZSA9IG1lYW4odGF4X2NvZGVfcmF0ZSwgbmEucm0gPSBUUlVFKSwgIyBDaGFuZ2VkIGZyb20gZmlyc3QoKSB0byBtZWFuKCkgb24gTm92IDENCiAgICBmaW5hbF90YXhfdG9fZGlzdCA9IHN1bShmaW5hbF90YXhfdG9fZGlzdCwgbmEucm0gPSBUUlVFKSwgIyB1c2VkIGFzIExFVlkgYW1vdW50ISEgDQogICAgZmluYWxfdGF4X3RvX3RpZiA9IHN1bShmaW5hbF90YXhfdG9fdGlmLCBuYS5ybSA9IFRSVUUpLA0KICAgIHRheF9hbXRfZXhlID0gc3VtKHRheF9hbXRfZXhlLCBuYS5ybSA9IFRSVUUpLCANCiAgICB0YXhfYW10X3ByZV9leGUgPSBzdW0odGF4X2FtdF9wcmVfZXhlLCBuYS5ybSA9IFRSVUUpLCANCiAgICB0YXhfYW10X3Bvc3RfZXhlID0gc3VtKHRheF9hbXRfcG9zdF9leGUsIG5hLnJtID0gVFJVRSksDQogICAgcnBtX3RpZl90b19jcHMgPSBzdW0ocnBtX3RpZl90b19jcHMsIG5hLnJtID0gVFJVRSksICMgbm90IHVzZWQNCiAgICBycG1fdGlmX3RvX3JwbSA9IHN1bShycG1fdGlmX3RvX3JwbSwgbmEucm09VFJVRSksICMgbm90IHVzZWQNCiAgICBycG1fdGlmX3RvX2Rpc3QgPSBzdW0ocnBtX3RpZl90b19kaXN0LCBuYS5ybT1UUlVFKSwgIyBub3QgdXNlZA0KICAgIHRpZl9zaGFyZSA9IG1lYW4odGlmX3NoYXJlLCBuYS5ybT1UUlVFKSwgIyBub3QgdXNlZA0KICApICU+JQ0KICANCiAgbXV0YXRlKHRvdGFsX2JpbGxfY3VycmVudCA9IGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZikgJT4lDQogIHJlbmFtZShjdXJfY29tcF9UQ19yYXRlID0gdGF4X2NvZGVfcmF0ZSkgJT4lDQogIG11dGF0ZShjdXJyZW50X3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QvKGN1cl9jb21wX1RDX3JhdGUvMTAwKSwNCiAgICAgICAgIG5ld190YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0LyhjdXJfY29tcF9UQ19yYXRlLzEwMCkgKyBIT19leGVtcHMpICU+JQ0KICBtdXRhdGUobmV3X2NvbXBfVENfcmF0ZSA9IChmaW5hbF90YXhfdG9fZGlzdCAvIG5ld190YXhhYmxlX2VhdikqMTAwKSAlPiUNCiAgbXV0YXRlKG5ld19jb21wX1RDX3JhdGUgPSBpZmVsc2UoaXMubmFuKG5ld19jb21wX1RDX3JhdGUpLCBjdXJfY29tcF9UQ19yYXRlLCBuZXdfY29tcF9UQ19yYXRlKSkgJT4lDQogIHNlbGVjdChhZ2VuY3lfbmFtZSwgY3VyX2NvbXBfVENfcmF0ZSwgbmV3X2NvbXBfVENfcmF0ZSwgY3VycmVudF90YXhhYmxlX2VhdiwgbmV3X3RheGFibGVfZWF2LCBldmVyeXRoaW5nKCkpDQoNCm11bmlfdGF4cmF0ZXMgDQoNCm11bmlfdGF4cmF0ZXMgJT4lIHdyaXRlX2NzdigiLi9PdXRwdXQvNENfbXVuaV90YXhyYXRlcy5jc3YiKQ0KYGBgDQoNCiMjIEJpbGwgRGlzdHJpYnV0aW9ucyANCg0KYGBge3IsIGZpZy5zaG93PSdob2xkJywgb3V0LndpZHRoPSI1MCUifQ0KcGluX2RhdGEyICU+JQ0KICBmaWx0ZXIobWFqb3JfY2xhc3NfY29kZSA9PSAyICYgYmlsbF9jdXJyZW50IDwgMzAwMDAgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBET0xUT04iKSAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9jdXJyZW50LCBiaW5zID0gMTAwKSkrDQogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWRpYW4oYmlsbF9jdXJyZW50LCBuYS5ybT1UUlVFKSwgY29sb3IgPSAicmVkIikpICsNCiAgICB0aGVtZV9jbGFzc2ljKCkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIA0KDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LDIwMDAwKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxNTAwKSkrDQogIGxhYnMoeD0iRG9sdG9uJ3MgQWN0dWFsIFRheCBCaWxscyBXaXRoIEN1cnJlbnQgRXhlbXB0aW9ucyIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIpDQoNCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKG1ham9yX2NsYXNzX2NvZGUgPT0gMiAmIGJpbGxfbm9leGVtcHMgPCAzMDAwMCAmIGFnZW5jeV9uYW1lID09ICJWSUxMQUdFIE9GIERPTFRPTiIpICU+JSBnZ3Bsb3QoKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh4PSBiaWxsX25vZXhlbXBzLCBiaW5zID0gMTAwKSkrDQogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWRpYW4oYmlsbF9ub2V4ZW1wcywgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCg0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtNSwyMDAwMCkpICsgDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTUwMCkpKw0KDQogIGxhYnMoeD0iRG9sdG9uJ3MgVGF4IEJpbGxzIFdpdGhvdXQgR2VuZXJhbCBIb21lc3RlYWQgRXhlbXB0aW9ucyIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIpDQoNCg0KDQpgYGANCg0KDQpgYGB7ciwgZmlnLnNob3c9J2hvbGQnLCBvdXQud2lkdGg9IjUwJSJ9DQoNCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKG1ham9yX2NsYXNzX2NvZGUgPT0gMiAmIGFnZW5jeV9uYW1lID09ICJWSUxMQUdFIE9GIEdMRU5DT0UiKSAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9jdXJyZW50LCBiaW5zID0gMTAwKSkrDQogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWRpYW4oYmlsbF9jdXJyZW50LCBuYS5ybT1UUlVFKSwgY29sb3IgPSAicmVkIikpICsNCiAgICB0aGVtZV9jbGFzc2ljKCkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArIA0KDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LDYwMDAwKSkgKyANCiMgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTUwMCkpKw0KDQogIGxhYnModGl0bGU9IkdsZW5jb2UncyBDdXJyZW50IFRheCBCaWxsIERpc3RyaWJ1dGlvbiIsIHggPSAiRG9sbGFycyIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIpDQoNCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKG1ham9yX2NsYXNzX2NvZGUgPT0gMiAmIGFnZW5jeV9uYW1lID09ICJWSUxMQUdFIE9GIEdMRU5DT0UiKSAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9ub2V4ZW1wcywgYmlucyA9IDEwMCkpKw0KICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVkaWFuKGJpbGxfbm9leGVtcHMsIG5hLnJtPVRSVUUpLCBjb2xvciA9ICJyZWQiKSkgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsNjAwMDApKSArIA0KIyAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxNTAwKSkrDQoNCiAgbGFicyh0aXRsZT0iR2xlbmNvZSdzIFRheCBCaWxscyBXaXRob3V0IEdlbmVyYWwgSG9tZXN0ZWFkIEV4ZW1wdGlvbnMiLCB5ID0gIk51bWJlciBvZiBUYXggQmlsbHMiKQ0KDQoNCg0KYGBgDQoNCmBgYHtyLCBmaWcuc2hvdz0naG9sZCcsIG91dC53aWR0aD0iNTAlIn0NCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKG1ham9yX2NsYXNzX2NvZGUgPT0gMiAmIGJpbGxfY3VycmVudCA8IDMwMDAwICYgYWdlbmN5X25hbWUgPT0gIkNJVFkgT0YgQ0hJQ0FHTyIpICU+JSBnZ3Bsb3QoKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh4PSBiaWxsX2N1cnJlbnQsIGJpbnMgPSAxMDApKSsNCiAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PW1lZGlhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpLCBjb2xvciA9ICJyZWQiKSkgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsMjAwMDApKSArDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDgwMDAwKSkgKw0KICBsYWJzKHRpdGxlPSJDaGljYWdvJ3MgQWN0dWFsIFRheCBCaWxscyBXaXRoIEN1cnJlbnQgRXhlbXB0aW9ucyIsIHg9ICJEb2xsYXJzIiwgeSA9ICJOdW1iZXIgb2YgVGF4IEJpbGxzIikNCg0KcGluX2RhdGEyICU+JQ0KICBmaWx0ZXIobWFqb3JfY2xhc3NfY29kZSA9PSAyICAmIGFnZW5jeV9uYW1lID09ICJDSVRZIE9GIENISUNBR08iKSAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9ub2V4ZW1wcywgYmlucyA9IDEwMCkpKw0KICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVkaWFuKGJpbGxfbm9leGVtcHMsIG5hLnJtPVRSVUUpLCBjb2xvciA9ICJyZWQiKSkgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTUsMjAwMDApKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCA4MDAwMCkpICsNCg0KICBsYWJzKHRpdGxlPSJDaGljYWdvJ3MgVGF4IEJpbGxzIFdpdGhvdXQgR2VuZXJhbCBIb21lc3RlYWQgRXhlbXB0aW9ucyIsIHg9IkRvbGxhcnMiLCB5ID0gIk51bWJlciBvZiBUYXggQmlsbHMiKQ0KDQoNCg0KYGBgDQoNCmBgYHtyIGJpbGwtY2hhbmdlfQ0KcGluX2RhdGEyICU+JQ0KICBmaWx0ZXIobWFqb3JfY2xhc3NfY29kZSA9PSAyICYgYWdlbmN5X25hbWUgPT0gIlZJTExBR0UgT0YgRE9MVE9OIikgJT4lIA0KICBnZ3Bsb3QoKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh4PSBiaWxsX2NoYW5nZSwgYmlucyA9IDEwMCkpKw0KICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQ9bWVkaWFuKGJpbGxfY2hhbmdlLCBuYS5ybT1UUlVFKSwgY29sb3IgPSAicmVkIikpICsNCiAgICB0aGVtZV9jbGFzc2ljKCkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyANCg0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygtMjgwMCwyODAwKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAyMDAwKSkrDQogIGxhYnModGl0bGU9IkRvbHRvbidzIENoYW5nZSBpbiBUYXggQmlsbHMiLCBzdWJ0aXRsZSA9ICAiSHlwb3RoZXRpY2FsIHdpdGggbm8gR2VuZXJhbCBIb21lc3RlYWQgRXhlbXB0aW9ucyIsIHggPSAiQ2hhbmdlIGluIFRheCBCaWxsICgkKSIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIpDQoNCnBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKG1ham9yX2NsYXNzX2NvZGUgPT0gMiAmIGFnZW5jeV9uYW1lID09ICJDSVRZIE9GIENISUNBR08iKSAlPiUgZ2dwbG90KCkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeD0gYmlsbF9jaGFuZ2UsIGJpbnMgPSAxMDApKSsNCiAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PW1lZGlhbihiaWxsX2NoYW5nZSwgbmEucm09VFJVRSksIGNvbG9yID0gInJlZCIpKSArDQogICAgdGhlbWVfY2xhc3NpYygpKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQoNCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoLTI4MDAsMjgwMCkpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDIwMDAwMCkpKw0KDQogIGxhYnModGl0bGUgPSJDaGljYWdvJ3MgQ2hhbmdlIGluIFRheCBCaWxscyIsIHN1YnRpdGxlID0gIkh5cG90aGV0aWNhbCB3aXRoIG5vIEdlbmVyYWwgSG9tZXN0ZWFkIEV4ZW1wdGlvbnMiLCB4ID0gIkNoYW5nZSBpbiBUYXggQmlsbCAoJCkiLCB5ID0gIk51bWJlciBvZiBUYXggQmlsbHMiKQ0KDQpwaW5fZGF0YTIgJT4lDQogIGZpbHRlcihtYWpvcl9jbGFzc19jb2RlID09IDIgJiBhZ2VuY3lfbmFtZSA9PSAiVklMTEFHRSBPRiBHTEVOQ09FIikgJT4lIGdncGxvdCgpICsNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHg9IGJpbGxfY2hhbmdlLCBiaW5zID0gMTAwKSkrDQogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD1tZWRpYW4oYmlsbF9jaGFuZ2UsIG5hLnJtPVRSVUUpLCBjb2xvciA9ICJyZWQiKSkgKw0KICAgIHRoZW1lX2NsYXNzaWMoKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQoNCiMgIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKC01LDIwMDAwKSkgKyANCiMgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTUwMCkpKw0KDQogIGxhYnModGl0bGU9IkdsZW5jb2UncyBDaGFuZ2UgaW4gVGF4IEJpbGxzIFdpdGhvdXQgR2VuZXJhbCBIb21lc3RlYWQgRXhlbXB0aW9ucyIsIHkgPSAiTnVtYmVyIG9mIFRheCBCaWxscyIsIHggPSAiRG9sbGFycyIpDQpgYGANCg0KDQpgYGB7cn0NCg0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIkNJVFkgT0YgQ0hJQ0FHTyIsICJWSUxMQUdFIE9GIERPTFRPTiIsICJWSUxMQUdFIE9GIEdMRU5DT0UiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA+MTk5ICYgY2xhc3MgPCAzMDApICU+JSANCiAgYXJyYW5nZShhdikgJT4lDQogIyBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIG11dGF0ZSgjdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdCAvIHRheF9jb2RlX3JhdGUsDQogICAgIyBjdXJyZW50IGJpbGwgPSBjdXJyZW50IHRheCByYXRlICogcG9ydGlvbiBvZiBsZXZ5IGJpbGxlZA0KICAgICAgICAgYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQogICAgICAgICBiaWxsX25vZXhlbXBzID0gIG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSwgemVyb19iaWxsLCBoYXNfSE9fZXhlbXApICU+JSANCiAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gbWVkaWFuKGVhdiksDQogICAgICAgICAgICBtZWFuX2JpbGxfY3VyID0gbWVhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWFuX2JpbGxfbmV3ID0gbWVhbihiaWxsX25vZXhlbXBzLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiAgICAgICAgICAgIG1lYW5fY2hhbmdlID0gbWVhbihiaWxsX2NoYW5nZSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkNCikNCg0KDQpwaW5fZGF0YTIgJT4lIA0KZmlsdGVyKHBpbl9BViA+IDApICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiQ0lUWSBPRiBDSElDQUdPIiwgIlZJTExBR0UgT0YgRE9MVE9OIiwgIlZJTExBR0UgT0YgR0xFTkNPRSIpKSAlPiUNCiAgZmlsdGVyKGNsYXNzID4xOTkgJiBjbGFzcyA8IDMwMCkgJT4lIA0KICBhcnJhbmdlKGF2KSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gbWVkaWFuKGVhdiksDQogICAgICAgICAgICBtZWFuX2JpbGxfY3VyID0gbWVhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWFuX2JpbGxfbmV3ID0gbWVhbihiaWxsX25vZXhlbXBzLCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiAgICAgICAgICAgIG1lYW5fY2hhbmdlID0gbWVhbihiaWxsX2NoYW5nZSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkNCikNCg0KDQpwaW5fZGF0YTIgJT4lIA0KZmlsdGVyKHBpbl9BViA+IDApICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiQ0lUWSBPRiBDSElDQUdPIiwgIlZJTExBR0UgT0YgRE9MVE9OIiwgIlZJTExBR0UgT0YgR0xFTkNPRSIpKSAlPiUNCiAgZmlsdGVyKGNsYXNzID4xOTkgJiBjbGFzcyA8IDMwMCkgJT4lIA0KICBhcnJhbmdlKGF2KSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lKSAlPiUgDQogIHN1bW1hcml6ZShtZWRpYW5fQVYgPSBtZWRpYW4oYXYpLA0KICAgICAgICAgICAgbWVkaWFuX0VBViA9IG1lZGlhbihlYXYpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX2N1ciA9IG1lYW4oYmlsbF9jdXJyZW50LCBuYS5ybT1UUlVFKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX25ldyA9IG1lYW4oYmlsbF9ub2V4ZW1wcywgbmEucm09VFJVRSksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9uZXcgPSBtZWRpYW4oYmlsbF9ub2V4ZW1wcyksDQogICAgICAgICAgICBtZWFuX2NoYW5nZSA9IG1lYW4oYmlsbF9jaGFuZ2UsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICBjdXJfY29tcF9UQ19yYXRlID0gbWVhbihjdXJfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpDQopDQoNCg0KYGBgDQoNCkZvciBhbGwgQ2xhc3MgMiBQcm9wZXJ0aWVzOg0KDQpJbiBDaGljYWdvOiBJZiB0aGV5IGRpZG4ndCBjbGFpbSBhbiBleGVtcHRpb24gKG4gPSAzMzEsNDkyKSwgbWVkaWFuIGJpbGwgZGVjcmVhc2VzIGJ5IFwkMTY4LiBJZiB0aGV5IGRvIGN1cnJlbnRseSBjbGFpbSBhbiBleGVtcHRpb24gKG4gPSA0MDEsNDUwKSwgdGhlIG1lZGlhbiBiaWxsIGluY3JlYXNlcyBcJDMzMCAoQlVUIHRoZXkgdGhpbmsgdGhleSBhcmUgc2F2aW5nIFwkNjcxIGR1ZSB0byBleGVtcHQgRUFWIFwqIGhpZ2hlciB0YXggcmF0ZSBhbW91bnQgdGhhdCBzaG93cyB1cCBvbiB0aGVpciB0YXggYmlsbHMhKQ0KDQpJbiBEb2x0b246IElmIHRoZXkgZGlkbid0IGNsYWltIGFuIGV4ZW1wdGlvbiAobiA9IDIsNjMzKSwgbWVkaWFuIGJpbGwgZGVjcmVhc2VzIGJ5IFwkMTI0MS4gSWYgdGhleSBkbyBjdXJyZW50bHkgY2xhaW0gYW4gZXhlbXB0aW9uIChuID0gNSw2MzkpLCB0aGUgbWVkaWFuIGJpbGwgaW5jcmVhc2VzIFwkMTA5MCAoQlVUIHRoZXkgdGhpbmsgdGhleSBhcmUgc2F2aW5nIFwkMjc5MSBkdWUgdG8gZXhlbXB0IEVBViBcKiBoaWdoZXIgdGF4IHJhdGUgYW1vdW50IHRoYXQgc2hvd3MgdXAgb24gdGhlaXIgdGF4IGJpbGxzISkNCg0KKy0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0rDQp8ICAgICAgICAgfCBoYXNfSE8gZXhlbXAgfCBtZWRpYW4gYmlsbF9jdXIgfCBtZWRpYW4gYmlsbF9uZXcgfCBtZWRpYW4gY2hhbmdlIHwgcGluIGNvdW50IHwgcGVyY2VpdmVkIHNhdmluZ3MgIHwNCis6PT09PT09PT0rPT09PT09PT09PT09PTorPT09PT09PT09PT09PT09PTorPT09PT09PT09PT09PT09PTorPT09PT09PT09PT09PT06Kz09PT09PT09PT06Kz09PT09PT09PT09PT09PT09PT06Kw0KfCBDaGljYWdvIHwgMCAgICAgICAgICAgIHwgMzM4OS4zICAgICAgICAgIHwgMzA0My43ICAgICAgICAgIHwgLTE2OC4yICAgICAgICB8IDMzMTQ5MiAgICB8IDAuMCAgICAgICAgICAgICAgICB8DQorLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLSsNCnwgQ2hpY2FnbyB8IDEgICAgICAgICAgICB8IDM3NTcuMSAgICAgICAgICB8IDQwMjkuNyAgICAgICAgICB8IDMzMC41ICAgICAgICAgfCA0MDE0NTAgICAgfCA2NzEuNiAgICAgICAgICAgICAgfA0KKy0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0rDQp8IERvbHRvbiAgfCAwICAgICAgICAgICAgfCA2MDUxLjkgICAgICAgICAgfCA0NzkyLjQgICAgICAgICAgfCAtMTI0MS4xICAgICAgIHwgMjYzMyAgICAgIHwgMC4wICAgICAgICAgICAgICAgIHwNCistLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0tKw0KfCBEb2x0b24gIHwgMSAgICAgICAgICAgIHwgMzgwMi4zICAgICAgICAgIHwgNDg2OC42ICAgICAgICAgIHwgMTA5MC40ICAgICAgICB8IDU2MzkgICAgICB8IDI3OTEuNSAgICAgICAgICAgICB8DQorLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLSsNCg0KSWYgd2UgZG8gbm90IGNhcmUgd2hldGhlciB0aGV5IGRvIG9yIGRvIG5vdCBjdXJyZW50bHkgcmVjZWl2ZSB0aGUgZ2VuZXJhbCBob21lc3RlYWQgZXhlbXB0aW9uLCB0aGVuIHRoZSBtZWRpYW4gY2hhbmdlIGlzIGEgZGVjcmVhc2Ugb2YgXCQzIGluIENoaWNhZ28gKDczMiw5NDIgcGlucykgYW5kIGFuIGluY3JlYXNlIG9mIFwkNzY5IGluIERvbHRvbiAoOCwyNzIgcGlucykuDQoNCistLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rDQp8ICAgICAgICAgICB8IG1lZGlhbiBiaWxsX2N1cnJlbnQgfCBtZWRpYW4gYmlsbF9uZXcgfCBtZWRpYW4gY2hhbmdlIHwgcGluY291bnQgIHwgcGVyY2VpdmVkIHNhdmluZ3MgfA0KKz09PT09PT09PT09Kz09PT09PT09PT09PT09PT09PT09PSs9PT09PT09PT09PT09PT09Ois9PT09PT09PT09PT09PTorPT09PT09PT09PTorPT09PT09PT09PT09PT09PT09OisNCnwgQ2hpY2FnbyAgIHwgMzYxOSAgICAgICAgICAgICAgICB8IDM2NDIuODcgICAgICAgICB8IC0yLjkwICAgICAgICAgfCA3MzI5NDIgICAgfCA2NjkuNyAgICAgICAgICAgICB8DQorLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKw0KfCBEb2x0b24gICAgfCA0MzA1ICAgICAgICAgICAgICAgIHwgNDg0Ni45NCAgICAgICAgIHwgNzY5LjEyICAgICAgICB8IDgyNzIgICAgICB8IDIyOTMuNyAgICAgICAgICAgIHwNCistLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rDQoNClRoZSBtZWRpYW4gQ2xhc3MgMiB0YXggcGF5ZXIgdGhpbmtzIHRoZXkgYXJlIHNhdmluZyBcJDY3MCB3aGVuIHRoZXkgcmVhbGx5IGFyZSBzYXZpbmcgbm8gbW9uZXkgZHVlIHRvIGN1cnJlbnQgZXhlbXB0aW9ucyB3aXRoaW4gQ2hpY2FnbyBhbmQgdGhlIG1lZGlhbiB0YXhwYXllciBpbiBEb2x0b24gdGhpbmtzIHRoZXkgYXJlIHNhdmluZyBcXFwkMiwyOTQgYnV0IGFyZSBvbmx5IHNhdmluZyBcJDc3MCBkdWUgdG8gdGhlIGhpZ2hlciB0YXggcmF0ZXMgdGhhdCByZXN1bHQgZnJvbSB0aGUgZGVjcmVhc2UgaW4gdGF4YWJsZSBFQVYgdGhhdCBvY2N1cnMgZnJvbSB0aG9zZSB0aGF0IGNsYWltIHRoZSBnZW5lcmFsIGhvbWVzdGVkIGV4ZW1wdGlvbi4NCg0KYGBge3J9DQp0YXhfYmlsbF9jaGFuZ2VfSE8gPC0gcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIkNJVFkgT0YgQ0hJQ0FHTyIsICJWSUxMQUdFIE9GIERPTFRPTiIsICJWSUxMQUdFIE9GIEdMRU5DT0UiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA9PSAyMDMpICU+JSANCiAgYXJyYW5nZShhdikgJT4lDQogICAgbXV0YXRlKGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IHJvdW5kKG1lZGlhbihiaWxsX2N1cnJlbnQpKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IHJvdW5kKG1lZGlhbihiaWxsX25vZXhlbXBzKSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gcm91bmQobWVkaWFuKGJpbGxfY2hhbmdlKSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSkpDQoNCnRheF9iaWxsX2NoYW5nZV9ITw0KDQpwaW5fZGF0YTIgJT4lIA0KZmlsdGVyKHBpbl9BViA+IDApICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiQ0lUWSBPRiBDSElDQUdPIiwgIlZJTExBR0UgT0YgRE9MVE9OIiwgIlZJTExBR0UgT0YgR0xFTkNPRSIpKSAlPiUNCiAgZmlsdGVyKGNsYXNzID09IDIwMykgJT4lIA0KICBhcnJhbmdlKGF2KSAlPiUNCiAgICBtdXRhdGUoYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQogICAgICAgICBiaWxsX25vZXhlbXBzID0gIG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSkgJT4lIA0KICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IHJvdW5kKG1lZGlhbihiaWxsX2N1cnJlbnQpKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IHJvdW5kKG1lZGlhbihiaWxsX25vZXhlbXBzKSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gcm91bmQobWVkaWFuKGJpbGxfY2hhbmdlKSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSkpDQoNCnBpbl9kYXRhMiAlPiUgDQpmaWx0ZXIocGluX0FWID4gMCkgJT4lIA0KICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJDSVRZIE9GIENISUNBR08iLCAiVklMTEFHRSBPRiBET0xUT04iLCAiVklMTEFHRSBPRiBHTEVOQ09FIikpICU+JQ0KICBmaWx0ZXIoY2xhc3MgPT0gMjAzKSAlPiUgDQogIGFycmFuZ2UoYXYpICU+JQ0KICAgIG11dGF0ZShiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCB6ZXJvX2JpbGwsIGhhc19IT19leGVtcCkgJT4lIA0KICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IHJvdW5kKG1lZGlhbihiaWxsX2N1cnJlbnQpKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IHJvdW5kKG1lZGlhbihiaWxsX25vZXhlbXBzKSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gcm91bmQobWVkaWFuKGJpbGxfY2hhbmdlKSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSkpDQoNCmBgYA0KDQorLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKw0KfCAgICAgICAgICAgICAgICAgICB8IGhhc19IT19leGVtcCB8IG1lZGlhbl9iaWxsX2N1ciB8IG1lZGlhbl9iaWxsX25ldyB8IG1lZGlhbl9jaGFuZ2UgfCBwaW5jb3VudCB8IHBlcmNlaXZlZF9zYXZpbmdzIHwNCnwgICAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgICAgfCAgICAgICAgICAgICAgIHwgICAgICAgICAgfCAgICAgICAgICAgICAgICAgICB8DQp8ICAgICAgICAgICAgICAgICAgIHwgXDxkYmxcPiAgICAgIHwgXDxkYmxcPiAgICAgICAgIHwgXDxkYmxcPiAgICAgICAgIHwgXDxkYmxcPiAgICAgICB8IFw8aW50XD4gIHwgXDxkYmxcPiAgICAgICAgICAgfA0KKzo9PT09PT09PT09PT09PT09PT0rPT09PT09PT09PT09PTorPT09PT09PT09PT09PT09PTorPT09PT09PT09PT09PT09PTorPT09PT09PT09PT09PT06Kz09PT09PT09PTorPT09PT09PT09PT09PT09PT09OisNCnwgQ0lUWSBPRiBDSElDQUdPICAgfCAwICAgICAgICAgICAgfCAzNDE4ICAgICAgICAgICAgfCAyOTcwICAgICAgICAgICAgfCAtMzY5ICAgICAgICAgIHwgMzIxMjggICAgfCAwLjAgICAgICAgICAgICAgICB8DQorLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKw0KfCBDSVRZIE9GIENISUNBR08gICB8IDEgICAgICAgICAgICB8IDMxNTEgICAgICAgICAgICB8IDMyNjggICAgICAgICAgICB8IDI2OSAgICAgICAgICAgfCAxMDI2NzcgICB8IDY3MTIgICAgICAgICAgICAgIHwNCistLS0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0tLS0rDQp8IFZJTExBR0UgT0YgRE9MVE9OIHwgMCAgICAgICAgICAgIHwgNjI5OCAgICAgICAgICAgIHwgNTAwNiAgICAgICAgICAgIHwgLTEyOTUgICAgICAgICB8IDExMDMgICAgIHwgMC4wICAgICAgICAgICAgICAgfA0KKy0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsNCnwgVklMTEFHRSBPRiBET0xUT04gfCAxICAgICAgICAgICAgfCAzNDQxICAgICAgICAgICAgfCA0NjI5ICAgICAgICAgICAgfCAxMTg2ICAgICAgICAgIHwgMjUwNiAgICAgfCAyNzkyICAgICAgICAgICAgICB8DQorLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKw0KDQpJZiBvbmx5ICJyZW1vdmluZyIvInJlZnVuZGluZyIgdGhlIGdlbmVyYWwgaG9tZXN0ZWFkIGV4ZW1wdGlvbjoNCg0KRm9yIENoaWNhZ28gY2xhc3MgMjEzIHByb3BlcnRpZXMsIHRoZSBtZWRpYW4gdGF4IGJpbGwgd291bGQgZ28gZG93biBcJDM3MCBmb3IgdGhvc2Ugd2hvIGRvbid0IGN1cnJlbnRseSBoYXZlIGEgZ2VuZXJhbCBob21lc3RlYWQgZXhlbXB0aW9uIGFuZCB3b3VsZCBpbmNyZWFzZSBcJDI3MCBmb3IgcGVvcGxlIHdobyBkbyBjdXJyZW50bHkgY2xhaW0gdGhlIGdlbmVyYWwgaG9tZXN0ZWFkIGV4ZW1wdGlvbi4gMzJLIHBlb3BsZSBkb24ndCBjbGFpbSB0aGUgZXhlbXB0aW9uIGFuZCAxMDJLIHBlb3BsZSBkby4NCg0KRG9sdG9uIGNsYXNzIDIxMyBtZWRpYW4gcHJvcGVydGllcyBoYXZlIGEgZGVjcmVhc2Ugb2YgXCQxMjk1IGlmIHRoZXkgZGlkbid0IGNsYWltIGhvbWVzdGVhZCBleGVtcHRpb25zIGN1cnJlbnRseSBhbmQgaW5jcmVhc2VkIFwkMTE4NiBmIHRoZXkgZGlkIGFscmVhZHkgY2xhaW0gdGhlIGdlbmVyYWwgaG9tZXN0ZWFkIGV4ZW1wdGlvbi4gMTEwMCBwZW9wbGUgZG8gbm90IGNsYWltIHRoZSBleGVtcHRpb24gYW5kIDI1MDAgcGVvcGxlIGRvIGNsYWltIHRoZSBnZW5lcmFsIGhvbWVzdGVhZMKgZXhlbXB0aW9uLg0KDQorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKw0KfCBDbGFzcyAyMTMgUHJvcGVydGllcyB8IG1lZGlhbiBiaWxsX2N1ciB8IG1lZGlhbiBiaWxsX25ldyB8IG1lZGlhbiBjaGFuZ2UgfCBwaW5jb3VudCB8IHBlcmNlaXZlZCBzYXZpbmdzIHwNCis6PT09PT09PT09PT09PT09PT09PT09Kz09PT09PT09PT09PT09PT06Kz09PT09PT09PT09PT09PT06Kz09PT09PT09PT09PT09Ois9PT09PT09PT06Kz09PT09PT09PT09PT09PT09PTorDQp8IENoaWNhZ28gICAgICAgICAgICAgIHwgMzE1MSAgICAgICAgICAgIHwgMzI1OCAgICAgICAgICAgIHwgMTc1ICAgICAgICAgICB8IDEzNDgwNSAgIHwgNjcwICAgICAgICAgICAgICAgfA0KKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLSsNCnwgRG9sdG9uICAgICAgICAgICAgICAgfCA0MTUyICAgICAgICAgICAgfCA0NzcwICAgICAgICAgICAgfCAxMDA5ICAgICAgICAgIHwgMzYwOSAgICAgfCAyMjk0ICAgICAgICAgICAgICB8DQorLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tKw0KDQojIENvbXBhcmUgQVY9MTAsMDAwDQoNCmBgYHtyfQ0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIkNJVFkgT0YgQ0hJQ0FHTyIsICJWSUxMQUdFIE9GIERPTFRPTiIsICJWSUxMQUdFIE9GIEdMRU5DT0UiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA+IDE5OSAmIGNsYXNzIDwgMzAwKSAlPiUgDQogIGFycmFuZ2UoYXYpICU+JQ0KICAgIGZpbHRlcihhdiA+IDk1MDAgJiBhdiA8IDEwNTAwKSAlPiUNCg0KICMgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KICBtdXRhdGUoI3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QgLyB0YXhfY29kZV9yYXRlLA0KICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIHplcm9fYmlsbCwgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIHN1bW1hcml6ZShtZWRpYW5fQVYgPSBtZWRpYW4oYXYpLA0KICAgICAgICAgICAgbWVkaWFuX0VBViA9IG1lZGlhbihlYXYpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9uZXcgPSBtZWRpYW4oYmlsbF9ub2V4ZW1wcyksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkNCikNCg0KDQpwaW5fZGF0YTIgJT4lIA0KZmlsdGVyKHBpbl9BViA+IDApICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiQ0lUWSBPRiBDSElDQUdPIiwgIlZJTExBR0UgT0YgRE9MVE9OIiwgIlZJTExBR0UgT0YgR0xFTkNPRSIpKSAlPiUNCiAgZmlsdGVyKGNsYXNzID4xOTkgJiBjbGFzcyA8IDMwMCkgJT4lIA0KICBhcnJhbmdlKGF2KSAlPiUNCiAgICBmaWx0ZXIoYXYgPiA5NTAwICYgYXYgPCAxMDUwMCkgJT4lDQoNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9lcXVhbGl6ZWRBViA9ICBtZWRpYW4oZXF1YWxpemVkX0FWKSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfbmV3ID0gbWVkaWFuKGJpbGxfbm9leGVtcHMpLA0KICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICBjdXJfY29tcF9UQ19yYXRlID0gbWVhbihjdXJfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpDQopDQoNCg0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIkNJVFkgT0YgQ0hJQ0FHTyIsICJWSUxMQUdFIE9GIERPTFRPTiIsICJWSUxMQUdFIE9GIEdMRU5DT0UiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA+MTk5ICYgY2xhc3MgPCAzMDApICU+JSANCiAgYXJyYW5nZShhdikgJT4lDQogIGZpbHRlcihhdiA+IDk1MDAgJiBhdiA8IDEwNTAwKSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lKSAlPiUgDQogICAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fZXF1YWxpemVkQVYgPSAgbWVkaWFuKGVxdWFsaXplZF9BViksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gbWVkaWFuKGVhdiksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9jdXIgPSBtZWRpYW4oYmlsbF9jdXJyZW50KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiAgICAgICAgICAgIG1lZGlhbl9jaGFuZ2UgPSBtZWRpYW4oYmlsbF9jaGFuZ2UpLA0KICAgICAgICAgICAgcGVyY2VpdmVkX3NhdmluZ3MgPSBtZWRpYW4odGF4X2FtdF9leGUpLA0KICAgICAgICAgICAgY3VyX2NvbXBfVENfcmF0ZSA9IG1lYW4oY3VyX2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBuZXdfY29tcF9UQ19yYXRlID0gbWVhbihuZXdfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIHBpbmNvdW50PW4oKQ0KKQ0KDQoNCg0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIkNJVFkgT0YgQ0hJQ0FHTyIsICJWSUxMQUdFIE9GIERPTFRPTiIsICJWSUxMQUdFIE9GIEdMRU5DT0UiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA9PTIwMykgJT4lIA0KICBhcnJhbmdlKGF2KSAlPiUNCiAgZmlsdGVyKGF2ID4gOTUwMCAmIGF2IDwgMTA1MDApICU+JQ0KICMgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KICBtdXRhdGUoI3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QgLyB0YXhfY29kZV9yYXRlLA0KICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUpDQoNCg0KcGluX2RhdGEyICU+JSANCmZpbHRlcihwaW5fQVYgPiAwKSAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIkNJVFkgT0YgQ0hJQ0FHTyIsICJWSUxMQUdFIE9GIERPTFRPTiIsICJWSUxMQUdFIE9GIEdMRU5DT0UiKSkgJT4lDQogIGZpbHRlcihjbGFzcyA9PSAyMDMpICU+JSANCiAgYXJyYW5nZShhdikgJT4lDQogIGZpbHRlcihhdiA+IDk1MDAgJiBhdiA8IDEwNTAwKSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lKSAlPiUNCiAgICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9lcXVhbGl6ZWRBViA9ICBtZWRpYW4oZXF1YWxpemVkX0FWKSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfbmV3ID0gbWVkaWFuKGJpbGxfbm9leGVtcHMpLA0KICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICBjdXJfY29tcF9UQ19yYXRlID0gbWVhbihjdXJfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpDQopDQoNCnBpbl9kYXRhMiAlPiUgDQpmaWx0ZXIocGluX0FWID4gMCkgJT4lIA0KICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJDSVRZIE9GIENISUNBR08iLCAiVklMTEFHRSBPRiBET0xUT04iLCAiVklMTEFHRSBPRiBHTEVOQ09FIikpICU+JQ0KICBmaWx0ZXIoY2xhc3MgPT0gMjAzKSAlPiUgDQogIGFycmFuZ2UoYXYpICU+JQ0KICBmaWx0ZXIoYXYgPiA5NTAwICYgYXYgPCAxMDUwMCkgJT4lDQogIyBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIG11dGF0ZSgjdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdCAvIHRheF9jb2RlX3JhdGUsDQogICAgIyBjdXJyZW50IGJpbGwgPSBjdXJyZW50IHRheCByYXRlICogcG9ydGlvbiBvZiBsZXZ5IGJpbGxlZA0KICAgICAgICAgYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQogICAgICAgICBiaWxsX25vZXhlbXBzID0gIG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUNCiAgICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9lcXVhbGl6ZWRBViA9ICBtZWRpYW4oZXF1YWxpemVkX0FWKSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfbmV3ID0gbWVkaWFuKGJpbGxfbm9leGVtcHMpLA0KICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICBjdXJfY29tcF9UQ19yYXRlID0gbWVhbihjdXJfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpDQopDQpgYGANCg0KIyMgY29tcGFyZSBBViBvZiAxNUsNCg0KR2xlbmNvZSBkb2Vzbid0IGhhdmUgUElOcyB0aGF0IGFyZSBpbiB0aGUgMTAsMDAwIEFWIHJhbmdlLi4uDQpTbyBzYW1lIGZvcm1hdCBhcyB0YWJsZXMgYWJvdmUgYnV0IHVzZXMgQVYgdmFsdWUgPSAkMTUsMDAwICsvLSA1MDANCg0KDQpgYGB7cn0NCnBpbl9kYXRhMiAlPiUgDQpmaWx0ZXIocGluX0FWID4gMCkgJT4lIA0KICBmaWx0ZXIoYWdlbmN5X25hbWUgJWluJSBjKCJDSVRZIE9GIENISUNBR08iLCAiVklMTEFHRSBPRiBET0xUT04iLCAiVklMTEFHRSBPRiBHTEVOQ09FIikpICU+JQ0KIyAgZmlsdGVyKGNsYXNzID09IDIwMykgJT4lIA0KICAgIGZpbHRlcihjbGFzcyA+MTk5ICYgY2xhc3MgPCAzMDApICU+JSANCg0KICBhcnJhbmdlKGF2KSAlPiUNCiAgZmlsdGVyKGF2ID4gMTQ1MDAgJiBhdiA8IDE1NTAwKSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JQ0KICAgIHN1bW1hcml6ZShtZWRpYW5fQVYgPSBtZWRpYW4oYXYpLA0KICAgICAgICAgICAgbWVkaWFuX2VxdWFsaXplZEFWID0gIG1lZGlhbihlcXVhbGl6ZWRfQVYpLA0KICAgICAgICAgICAgdGF4YWJsZV9lYXYgPSBtZWFuKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfbmV3ID0gbWVkaWFuKGJpbGxfbm9leGVtcHMpLA0KICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICBjdXJfY29tcF9UQ19yYXRlID0gbWVhbihjdXJfY29tcF9UQ19yYXRlKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpDQopDQpgYGANCg0KYGBge3J9DQpwaW5fZGF0YTIgJT4lIA0KZmlsdGVyKHBpbl9BViA+IDApICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiQ0lUWSBPRiBDSElDQUdPIiwgIlZJTExBR0UgT0YgRE9MVE9OIiwgIlZJTExBR0UgT0YgR0xFTkNPRSIpKSAlPiUNCiMgIGZpbHRlcihjbGFzcyA9PSAyMDMpICU+JSANCiAgICBmaWx0ZXIoY2xhc3MgPjE5OSAmIGNsYXNzIDwgMzAwKSAlPiUgDQoNCiAgYXJyYW5nZShhdikgJT4lDQogIGZpbHRlcihhdiA+IDE0NTAwICYgYXYgPCAxNTUwMCkgJT4lDQogIyBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIG11dGF0ZSgjdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdCAvIHRheF9jb2RlX3JhdGUsDQogICAgIyBjdXJyZW50IGJpbGwgPSBjdXJyZW50IHRheCByYXRlICogcG9ydGlvbiBvZiBsZXZ5IGJpbGxlZA0KICAgICAgICAgYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQogICAgICAgICBiaWxsX25vZXhlbXBzID0gIG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSkgJT4lDQogICAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fZXF1YWxpemVkQVYgPSAgbWVkaWFuKGVxdWFsaXplZF9BViksDQogICAgICAgICAgICB0YXhhYmxlX2VhdiA9IG1lYW4oZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgICAgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9uZXcgPSBtZWRpYW4oYmlsbF9ub2V4ZW1wcyksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSBtZWFuKGN1cl9jb21wX1RDX3JhdGUpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IG1lYW4obmV3X2NvbXBfVENfcmF0ZSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkNCikNCmBgYA0KDQoNCiMjIyBDbGFzcyAzMDAgJiBBbGwgT3RoZXIgQ2xhc3Nlcw0KDQoNCmBgYHtyfQ0KcGluX2RhdGEyICU+JSANCiAgZmlsdGVyKGFnZW5jeV9uYW1lICVpbiUgYygiQ0lUWSBPRiBDSElDQUdPIiwgIlZJTExBR0UgT0YgRE9MVE9OIiwgIlZJTExBR0UgT0YgR0xFTkNPRSIpKSAlPiUNCiAgZmlsdGVyKGNsYXNzID4yOTkgJiBjbGFzcyA8IDQwMCkgJT4lIA0KICBhcnJhbmdlKGF2KSAlPiUNCiAgICBtdXRhdGUoYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQogICAgICAgICBiaWxsX25vZXhlbXBzID0gIG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSkgJT4lIA0KICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSBtZWRpYW4oZWF2KSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX2N1ciA9IHJvdW5kKG1lZGlhbihiaWxsX2N1cnJlbnQpKSwNCiAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IHJvdW5kKG1lZGlhbihiaWxsX25vZXhlbXBzKSksDQogICAgICAgICAgICBtZWRpYW5fY2hhbmdlID0gcm91bmQobWVkaWFuKGJpbGxfY2hhbmdlKSksDQogICAgICAgICAgICBwaW5jb3VudD1uKCksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSkpDQoNCnBpbl9kYXRhMiAlPiUgDQogIGZpbHRlcihhZ2VuY3lfbmFtZSAlaW4lIGMoIkNJVFkgT0YgQ0hJQ0FHTyIsICJWSUxMQUdFIE9GIERPTFRPTiIsICJWSUxMQUdFIE9GIEdMRU5DT0UiKSkgJT4lDQogIGZpbHRlcihjbGFzcz4zOTkpICU+JSANCiAgYXJyYW5nZShhdikgJT4lDQogICAgbXV0YXRlKGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoYWdlbmN5X25hbWUpICU+JSANCiAgc3VtbWFyaXplKG1lZGlhbl9BViA9IG1lZGlhbihhdiksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gbWVkaWFuKGVhdiksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9jdXIgPSByb3VuZChtZWRpYW4oYmlsbF9jdXJyZW50KSksDQogICAgICAgICAgICBtZWRpYW5fYmlsbF9uZXcgPSByb3VuZChtZWRpYW4oYmlsbF9ub2V4ZW1wcykpLA0KICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IHJvdW5kKG1lZGlhbihiaWxsX2NoYW5nZSkpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpLA0KICAgICAgICAgICAgcGVyY2VpdmVkX3NhdmluZ3MgPSBtZWRpYW4odGF4X2FtdF9leGUpKQ0KYGBgDQo=