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

#renv::install("ccao-data/ptaxsim")
library(tidyverse)
library(data.table)
library(gstat)
library(ptaxsim)
library(glue)


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


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




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

If munis that cross county lines are included, singfam_pins has 855,051 pins. When excluded, it decreases to 816,085 pins.

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

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

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

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

pin_data2 <- pin_data2 %>% left_join(class_dict)

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

Finding and Comparing “Median Properties”

Cook Median

Cook County Stats:

  • 25th percentile of PIN AV is $14,155 in Cook County (i.e., 25% of homes have AVs less than 14K and 75% have AVs more than 14K)
  • 50th percentile of PIN AV is $21,003
  • 75th percentile of PIN AV is $31,417

# Quartiles
#quantile(singfam_pins$av)


# Deciles
# quantile(singfam_pins$av, probs = c(0, .1, .2, .3, .4, .5, .6, .7, .8, .9, 1))


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


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

chosen3_ranked <- singfam_pins %>%  
  left_join(nicknames) %>% 
  filter(clean_name %in% c("Dolton", "Chicago", "Glencoe")) %>%
  mutate(rank = case_when(
    av > (cook_quartiles$quant25-500) & (av<cook_quartiles$quant25+500) ~ "q25",
    av > (cook_quartiles$quant50-500) & (av<cook_quartiles$quant50+500) ~ "q50",
    av > (cook_quartiles$quant75-500) & (av<cook_quartiles$quant75+500) ~ "q75")) %>%
  select(clean_name, rank, av, pin, class, everything()) %>% 
  filter(!is.na(rank)) # 25,413 pins kept for these 4 places


chosen3_billchange <-  chosen3_ranked %>% 
  group_by(clean_name, rank)%>%
  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(clean_name, rank, has_HO_exemp) %>% 
  summarize(median_AV = round(median(av)),
            median_EAV = round(median(eav)),
            # median_bill_cur = median(bill_current),
            # median_bill_new = median(bill_noexemps),
            # median_change = median(bill_change),
            mean_bill_cur = round(mean(bill_current, na.rm=TRUE)),
            mean_bill_new = round(mean(bill_noexemps, na.rm=TRUE)),
            mean_change = round(mean(bill_change, na.rm=TRUE)),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = round(mean(cur_comp_TC_rate), digits = 2),
            new_comp_TC_rate = round(mean(new_comp_TC_rate), digits = 2),
            pincount=n()
) %>%
  arrange(has_HO_exemp, rank)


write_csv(chosen3_billchange, "4d_quartiles_billchange.csv")

Bill change for those that Did Not Claim Exemptions:

Each Municipality has different composite tax rates. This causes the average tax bill to vary geographically within Cook County. For properties that are at the Cook County 25th percentile in assessed value ($14,000), current tax bills range from $2,800 in Chicago to over $10,000 in Dolton. The median Cook County property currently (AV= $21,000) has a $4,200 bill in Chicago, a $14,400 bill in Dolton, and a $6,000 bill in Glencoe.

If the general homestead exemption was terminated, additional EAV would become taxable which would then result in lower tax rates for all properties. This lower tax rate would result in lower tax bills for properties that were not claiming the general homestead exemption.1

When looking at those who did not claim the General Homestead Exemption (GHE) and own properties assessed at Cook County’s median AV (AV = $21,000), all tax bills would decrease from current amounts. A homeowner would experience a $500 decrease in their taxbill in Chicago and over a $2,100 decrease in Dolton if additional EAV became taxable from the termination of the GHE.

chosen3_billchange %>% 
  filter(has_HO_exemp == 0 & !is.na(rank)) %>%
  select(Municipality = clean_name, "Percentile" = rank,  "Avg Current Bill" = mean_bill_cur, "Avg New Bill" = mean_bill_new, "Tax Bill Change" = mean_change, "Perceived Savings" = perceived_savings, "# Pins in AV Range" = pincount, "AV" = median_AV, cur_comp_TC_rate, new_comp_TC_rate, everything())

Bill Change for those that did claim the General Homestead Exemption

When looking at those who did claim the General Homestead Exemption (GHE) and own properties assessed at Cook County’s median AV (AV = $21,000), all tax bills would increase from current amounts but the tax rate applied to all property owners would decrease. A homeowner would experience a $190 increase in their taxbill in Chicago and a $85 increase in Glencoe. While there are no properties valued at the county median AV in Dolton, a property valued at the county’s 25th percentile would experience a $650 increase if additional EAV became taxable from the termination of the GHE.

However, these hypothetical bill increases would be significantly less than property owners would initially think. All tax bills showthe amount that thetax bill was reduced due to exemptions: exempt EAV * current composite tax rate. However, this value is an over estimate of how the tax bill would change because it does not take into account the decrease in tax rate that would occur: if you increase the taxable EAV and hold the levy constant, then the tax rate decreases for all properties.

Overall, home owners believe they are benefiting more from the general homestead exemption than they would be in this scenario. Policymakers also likely believe exemptions are providing more benefits than they actually are to homeowners. While those who claim the exemption have less EAV that is taxed, the composite tax rate increases for all property owners. Ultimately some of the property tax burden is shifted from homeowners to other property owners. The amount of the burden shift depends on an area’s proportional land use (residential EAV / total EAV).2

chosen3_summarytable <- chosen3_billchange %>% 
  filter(has_HO_exemp == 1
         #& !is.na(rank)
         ) %>%
  #arrange(clean_name, rank) %>%
  select(Municipality = clean_name, "Percentile" = rank, "Avg Current Bill" = mean_bill_cur, "Avg New Bill" = mean_bill_new, "Tax Bill Change" = mean_change, "Perceived Savings" = perceived_savings, "# Pins in AV Range" = pincount,  "AV" = median_AV, cur_comp_TC_rate, new_comp_TC_rate, everything())

chosen3_summarytable

Alternative Method: Median of each Municipality

Assessed Value is used to identify the quartile breaks within each municipality for single-family properties. These break points will then be used to look at how the tax bill changes for properties with AVs at the 25th percentile, 50th percentile, and 75th percentile.

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.

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

muni_quartiles <- pin_data2 %>%
  filter(Option2 == "Single-Family")%>%
  group_by(agency_name ) %>%
  arrange(av) %>%
  summarize(count_pins = n(), 
            min = min(av),
            quant25 = round(quantile(av, probs = q[1])), 
            quant50 = round(quantile(av, probs = q[2])),
            quant75 = round(quantile(av, probs = q[3])),
            max = max(av)) %>% 
  arrange( desc( quant50)) 

chosen3 <- muni_quartiles %>% 
  left_join(nicknames) %>% 
  filter(clean_name %in% c("Dolton", "Chicago", "Glencoe"))
# chosen3

chosen3_ranked <- pin_data2 %>%
  inner_join(chosen3, by = "agency_name") %>%
  mutate(rank = case_when(
    av > (quant25-500) & (av<quant25+500) ~ "q25",
    av > (quant50-500) & (av<quant50+500) ~ "q50",
    av > (quant75-500) & (av<quant75+500) ~ "q75")) %>%
  select(clean_name, rank, av, pin, class, everything())


# chosen3_ranked %>% 
#   group_by(clean_name, rank)%>%
#  # 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(clean_name, rank, 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()
# )

# chosen3_ranked %>% 
#   group_by(clean_name, rank)%>%
#   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(clean_name, rank) %>% 
#   summarize(median_AV = round(median(av)),
#             median_EAV = round(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()
# )
chosen3_billchange <-  chosen3_ranked %>% 
  group_by(clean_name, rank)%>%
  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(clean_name, rank, has_HO_exemp) %>% 
  summarize(median_AV = round(median(av)),
            median_EAV = round(median(eav)),
            # median_bill_cur = median(bill_current),
            # median_bill_new = median(bill_noexemps),
            # median_change = median(bill_change),
            mean_bill_cur = round(mean(bill_current, na.rm=TRUE)),
            mean_bill_new = round(mean(bill_noexemps, na.rm=TRUE)),
            mean_change = round(mean(bill_change, na.rm=TRUE)),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = round(mean(cur_comp_TC_rate), digits = 2),
            new_comp_TC_rate = round(mean(new_comp_TC_rate), digits = 2),
            pincount=n()
) %>%
  arrange(has_HO_exemp, rank)

#chosen3_billchange


pin_data2 %>%
  left_join(nicknames) %>%
  filter(Option2 == "Single-Family") %>%
  filter(av < 500000) %>% # remove the couple really extreme outliers in Chicago
  filter(clean_name %in% c("Dolton", "Chicago", "Glencoe", "Oak Park")) %>%
  ggplot( aes(y=av, group = clean_name, fill = clean_name)) +
  geom_boxplot()+
 # facet_wrap(~agency_name, nrow=4) +
 coord_flip() +
  theme_bw()  +
    theme(axis.text.x = element_blank(), 
        axis.ticks.x = element_blank()) +
  labs(title = "Distribution of Residential Properties AV", y = "Assessed Value ($)") +
  scale_y_continuous(label = scales::dollar) 

#install.packages("ggridges")
library(ggridges)

pin_data2 %>%
  left_join(nicknames) %>%
  filter(Option2 == "Single-Family") %>%
  filter(av < 300000) %>% # remove the couple really extreme outliers in Chicago
 filter(clean_name %in% c("Dolton", "Chicago", "Glencoe")) %>%
  ggplot( aes(x = av, y= clean_name, fill = clean_name ) )+
  geom_density_ridges( aes(x = av, y=clean_name, fill = clean_name) )+
  viridis::scale_fill_viridis(discrete = T, name = "")+
  #facet_wrap(~agency_name, ncol=4) +
#  coord_flip() +
  theme_ridges() + 
  theme(#axis.text.x = element_blank(), 
 #       axis.ticks.x = element_blank(,
 legend.position = "none") +
  labs(title = "Distribution of Residential Properties' AV", 
       y = "Assessed Value", x= "" ) +
  scale_x_continuous(label = scales::dollar)

pin_data2 %>%
  left_join(nicknames) %>%
  filter(Option2 == "Single-Family") %>%
  filter(av < 300000) %>% # remove the couple really extreme outliers in Chicago
 filter(clean_name %in% c("Dolton", "Chicago", "Glencoe")) %>%
  ggplot( aes(x = av, fill = clean_name ) )+
  geom_histogram( )+
  facet_wrap(~agency_name, nrow=4) +
  theme_classic()+
  theme(#axis.text.x = element_blank(), 
 #       axis.ticks.x = element_blank(,
 legend.position = "none") +
  labs(title = "Distribution of Residential Properties' AV", 
       x = "Assessed Value", x= "# PINs" ) +
  scale_x_continuous(label = scales::dollar)

pin_data2 %>%
  left_join(nicknames) %>%
  #filter(Alea_cats == "Owner Occupied") %>%
  mutate(has_HO_exemp = factor(has_HO_exemp, levels = c("Did Not Claim", "Did Claim")),
         clean_name = factor(clean_name)) %>%
  filter(Option2 == "Single-Family") %>%
  filter(clean_name %in% c("Dolton", "Chicago", "Glencoe", "Oak Park")) %>%
  ggplot(aes(x = clean_name, y=log(av), fill = clean_name)  )+
  geom_violin(position = "dodge", alpha = 0.5, outlier.color = "transparent")+
      viridis::scale_fill_viridis(discrete=T, name="") +
  theme_classic() +
  coord_flip()+
  #facet_wrap(~agency_name, ncol=4) +
   theme(legend.position = "none") + 
  labs(title = "Distribution of Residential Properties' AV", y = "log(Assessed Value)", x= "" ) #+

 # scale_y_continuous(label = scales::dollar) #+ scale_x_continuous(labels = element_blank())
chosen3_billchange %>% 
  pivot_wider(id_cols = c(clean_name, has_HO_exemp), 
              names_from = "rank", values_from = "mean_change") %>%
    mutate(Claimed_Exemption= ifelse(has_HO_exemp == 0 , "Didn't Claim Exemption", "Did Claim Exemption")) %>%
  select(Municipality=clean_name, "Claimed_Exemption", "q25", "q50", "q75")
# chosen3_billchange %>% 
#   pivot_wider(id_cols = c(clean_name, has_HO_exemp, rank), 
#               names_from = "rank", values_from = "mean_change") %>%
#     mutate(Claimed_Exemption= ifelse(has_HO_exemp == 0 , "Didn't Claim Exemption", "Did Claim Exemption")) %>%
#   select(Municipality=clean_name, "Claimed_Exemption", "q25", "q50", "q75")

Bill change for those that Did Not Claim Exemptions:

chosen3_billchange %>% 
  filter(has_HO_exemp == 0 & !is.na(rank)) %>%
  select(Municipality = clean_name, "AV Percentile" = rank, "AV" = median_AV, "Average Current Bill" = mean_bill_cur, "Average New Bill" = mean_bill_new, "Tax Bill Change" = mean_change, "Perceived Savings" = perceived_savings, "# Pins in AV Range" = pincount, cur_comp_TC_rate, new_comp_TC_rate, everything())

Bill Change for those that did claim the General Homestead Exemption

chosen3_summarytable <- chosen3_billchange %>% 
  filter(has_HO_exemp == 1 & !is.na(rank)) %>%
  arrange(clean_name, rank) %>%
  select(Municipality = clean_name, "AV Percentile" = rank, "AV" = median_AV, "Average Current Bill" = mean_bill_cur, "Average New Bill" = mean_bill_new, "Tax Bill Change" = mean_change, "Perceived Savings" = perceived_savings, "# Pins in AV Range" = pincount, cur_comp_TC_rate, new_comp_TC_rate, everything())

chosen3_summarytable

Graph requested Oct 4

For those that DID claim the exemption, create ratio of:

25th percentile home bill change / AV : 75th percentile home bill change/AV.

Graph the ratio points for all munis.

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

muni_quartiles <- pin_data2 %>%
  filter(Option2 == "Single-Family")%>%
  filter(tax_code %in% muni_TC_fullyCook$tax_code_num) %>%
  group_by(agency_name ) %>%
  arrange(av) %>%
  summarize(count_pins = n(), 
            min = min(av),
            quant25 = round(quantile(av, probs = q[1])), 
            quant50 = round(quantile(av, probs = q[2])),
            quant75 = round(quantile(av, probs = q[3])),
            max = max(av)) %>% 
  arrange( desc( quant50)) %>%
    left_join(nicknames)



munis_ranked <- pin_data2 %>%
  filter(tax_code %in% muni_TC_fullyCook$tax_code_num) %>%
  inner_join(muni_quartiles, by = "agency_name") %>%
  mutate(rank = case_when(
    av > (quant25-500) & (av<quant25+500) ~ "q25",
    av > (quant50-500) & (av<quant50+500) ~ "q50",
    av > (quant75-500) & (av<quant75+500) ~ "q75")) %>%
  select(clean_name, rank, av, pin, class, everything())
munis_billchange <-  munis_ranked  %>% 
  group_by(clean_name, rank) %>%
  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(clean_name, rank, has_HO_exemp) %>% 
  summarize(median_AV = round(median(av)),
            median_EAV = round(median(eav)),
            # median_bill_cur = median(bill_current),
            # median_bill_new = median(bill_noexemps),
            # median_change = median(bill_change),
            mean_bill_cur = round(mean(bill_current, na.rm=TRUE)),
            mean_bill_new = round(mean(bill_noexemps, na.rm=TRUE)),
            mean_change = round(mean(bill_change, na.rm=TRUE)),
            perceived_savings = median(tax_amt_exe),
            cur_comp_TC_rate = round(mean(cur_comp_TC_rate), digits = 2),
            new_comp_TC_rate = round(mean(new_comp_TC_rate), digits = 2),
            pincount=n()
) %>%
  arrange(has_HO_exemp, rank)

munis_billchange <- munis_billchange %>% left_join(muni_quartiles)

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

ratios

billchange_to_AV_25 is the amount the tax bill changed for properties at the municipality’s 25th percentile (based on Assessed Value) divided by the Assessed Value of that property. The larger the decimal, the more impact a bill reduction would have (change in property tax bill as a proportion of the proxy for an owner’s “wealth”).

billchange_to_AV_75 is the amount that a property tax bill changed from the removal of the general homeowner exemption / the AV of that property.

Municipalities with high ratios will have high composite tax rates. However the further the dot is from the m=1 sloped line, the more impactful exemptions are.

ggplot(data = ratios, aes(y = billchange_to_AV_25, x = billchange_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
  theme(legend.position = "none")

ratios %>% 
  filter(billchange_to_AV_25<.3) %>%
ggplot(aes(y = billchange_to_AV_25, x = billchange_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
  theme(legend.position = "none")

ratios %>% 
  filter(billchange_to_AV_25<.1) %>%
ggplot(aes(y = billchange_to_AV_25, x = billchange_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
  theme(legend.position = "none")

ratios %>% 
  filter(billchange_to_AV_25<.1) %>%
ggplot(aes(y = billchange_to_AV_25, x = billchange_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .03, nudge_y=0.01, size = 3, check_overlap = TRUE)+ 
  theme_classic() + 
  theme(legend.position = "none")

Current Bill / AV graphs

The property tax bill divided by the assessed value is just the tax composite tax rate for the municipality.

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


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

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none")

ratios %>% filter(currbill_to_AV_25<.3) %>%
  ggplot(aes(y = currbill_to_AV_25, x = currbill_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .02, nudge_y=0.0, size = 2.4, check_overlap = TRUE)+ 
  theme_classic() + 
  theme(legend.position = "none")

ratios %>% filter(currbill_to_AV_25<.2) %>%
  ggplot(aes(y = currbill_to_AV_25, x = currbill_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .02, nudge_y=0.00, size = 2.4, check_overlap = TRUE)+ 
  theme_classic() + 
  theme(legend.position = "none")

Hypothetical Bill after removing GHE

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


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

  scale_x_continuous(limits = c(0, .6))+
  theme(legend.position = "none")

new_ratios %>% filter(newbill_to_AV_25<.3) %>%
  ggplot(aes(y = newbill_to_AV_25, x = newbill_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .02, nudge_y=0.0, size = 2.4, check_overlap = TRUE)+ 
  theme_classic() + 
  theme(legend.position = "none")

new_ratios %>% filter(newbill_to_AV_25<.2) %>%
  ggplot(aes(y = newbill_to_AV_25, x = newbill_to_AV_75, label = clean_name)) + 
  geom_abline(intercept = 0, slope = 1) +
  geom_point(aes(alpha = .5)) + 
  geom_text(nudge_x = .02, nudge_y=0.00, size = 2.4, check_overlap = TRUE)+ 
  theme_classic() + 
  theme(legend.position = "none")


  1. A binary variable was created at the PIN level data for if exe_homeowner was > 0. If any amount of EAV was exempt within exe_homeowner, then the PIN was considered to have received the General Homestead Exemption. That specific exemption allows up to $10,000 in EAV to become tax exempt. Data was pulled from the pin table used in CCAO’s PTAXSIM.↩︎

  2. While the tax rate calculations do take into consideration TIF increments, we have not discussed the role that TIFs play in composite tax rates. If a TIF exists in the same tax code as a homeowner, the taxable EAV is frozen for years to come. However the levy amount needed to provide public services usually increases over time and results in higher tax rates for those in TIF areas compared to nearby non-TIF tax codes.↩︎

LS0tDQp0aXRsZTogJ0dlbmVyYWwgSG9tZXN0ZWFkIEV4ZW1wdGlvbiBFZmZlY3Qgb24gVGF4IFJhdGVzJw0Kc3VidGl0bGU6ICdBc3Nlc3NlZCBWYWx1ZSBRdWFydGlsZXMgaW4gTXVuaWNpcGFsaXRpZXMnDQphdXRob3I6ICJBbGVhIFdpbGJ1ciINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpDQoNCiNyZW52OjppbnN0YWxsKCJjY2FvLWRhdGEvcHRheHNpbSIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmxpYnJhcnkoZ3N0YXQpDQpsaWJyYXJ5KHB0YXhzaW0pDQpsaWJyYXJ5KGdsdWUpDQoNCg0KcHRheHNpbV9kYl9jb25uIDwtIERCSTo6ZGJDb25uZWN0KFJTUUxpdGU6OlNRTGl0ZSgpLCAiLi9wdGF4c2ltLmRiL3B0YXhzaW0tMjAyMS4wLjQuZGIiKQ0KDQoNCm11bmlfYWdlbmN5X25hbWVzIDwtIERCSTo6ZGJHZXRRdWVyeSgNCiAgcHRheHNpbV9kYl9jb25uLA0KICAiU0VMRUNUIERJU1RJTkNUIGFnZW5jeV9udW0sIGFnZW5jeV9uYW1lLCBtaW5vcl90eXBlDQogIEZST00gYWdlbmN5X2luZm8NCiAgV0hFUkUgbWlub3JfdHlwZSA9ICdNVU5JJw0KICBPUiBhZ2VuY3lfbnVtID0gJzAyMDA2MDAwMCcgIA0KDQogICINCikNCg0KbXVuaV90YXhfY29kZXMgPC0gREJJOjpkYkdldFF1ZXJ5KA0KICBwdGF4c2ltX2RiX2Nvbm4sDQogIGdsdWVfc3FsKCINCiAgU0VMRUNUIERJU1RJTkNUIGFnZW5jeV9udW0sIHRheF9jb2RlX251bQ0KICBGUk9NIHRheF9jb2RlDQogIFdIRVJFIGFnZW5jeV9udW0gSU4gKHttdW5pX2FnZW5jeV9uYW1lcyRhZ2VuY3lfbnVtKn0pDQogIEFORCB5ZWFyID0gMjAyMQ0KICAiLA0KICAuY29uID0gcHRheHNpbV9kYl9jb25uDQogICkNCikgJT4lIA0KICBtdXRhdGUodGF4X2NvZGVfbnVtID0gYXMubnVtZXJpYyh0YXhfY29kZV9udW0pKQ0KDQp0YXhfY29kZXMgPC0gREJJOjpkYkdldFF1ZXJ5KA0KICBwdGF4c2ltX2RiX2Nvbm4sDQogIGdsdWVfc3FsKCINCiAgU0VMRUNUIERJU1RJTkNUIHRheF9jb2RlX251bSwgdGF4X2NvZGVfcmF0ZQ0KICBGUk9NIHRheF9jb2RlDQogIFdIRVJFIHllYXIgPSAyMDIxDQogICIsDQogIC5jb24gPSBwdGF4c2ltX2RiX2Nvbm4NCiAgKQ0KKSAlPiUgbXV0YXRlKHRheF9jb2RlX251bSA9IGFzLm51bWVyaWModGF4X2NvZGVfbnVtKSkNCg0KDQpjcm9zc19jb3VudHlfbGluZXMgPC0gYygiMDMwNDQwMDAwIiwgIjAzMDU4NTAwMCIsICIwMzA4OTAwMDAiLCAiMDMwMzIwMDAwIiwgIjAzMTI4MDAwMCIsIjAzMDA4MDAwMCIsICIwMzA1NjAwMDAiLCAiMDMxMTIwMDAwIiwgIjAzMDI4MDAwMCIsICIwMzAzNDAwMDAiLCIwMzAxNTAwMDAiLCIwMzAwNTAwMDAiLCAiMDMwMTgwMDAwIiwiMDMwNTAwMDAwIiwiMDMxMjEwMDAwIikNCg0KDQoNCg0KbXVuaV9UQ19mdWxseUNvb2sgPC0gbXVuaV90YXhfY29kZXMgJT4lDQogIGZpbHRlcighYWdlbmN5X251bSAlaW4lIGNyb3NzX2NvdW50eV9saW5lcykNCg0KDQpgYGANCg0KDQpJZiBtdW5pcyB0aGF0IGNyb3NzIGNvdW50eSBsaW5lcyBhcmUgaW5jbHVkZWQsIHNpbmdmYW1fcGlucyBoYXMgODU1LDA1MSBwaW5zLiBXaGVuIGV4Y2x1ZGVkLCBpdCBkZWNyZWFzZXMgdG8gODE2LDA4NSBwaW5zLiANCg0KYGBge3IgcmVhZC1maWxlc30NCmNsYXNzX2RpY3QgPC0gcmVhZF9jc3YoIi4vTmVjZXNzYXJ5X0ZpbGVzL2NsYXNzX2RpY3Rfc2luZ2xlZmFtY29kZXMuY3N2IikgJT4lIA0KICBtdXRhdGUoY2xhc3NfY29kZSA9IGFzLmNoYXJhY3RlcihjbGFzc19jb2RlKSkgIyBjaGFuZ2UgdmFyaWFibGUgdHlwZSB0byBjaGFyYWN0ZXIgc28gdGhlIGpvaW4gd29ya3MuDQoNCm5pY2tuYW1lcyA8LSByZWFkeGw6OnJlYWRfeGxzeCgiLi9OZWNlc3NhcnlfRmlsZXMvbXVuaV9zaG9ydG5hbWVzLnhsc3giKQ0KDQpwaW5fZGF0YTIgPC0gcmVhZF9jc3YoIi4vT3V0cHV0LzRDX2pvaW5lZF9QSU5zX2JpbGxzX2FuZF9leGVtcHRpb25zLmNzdiIpDQoNCm11bmlfdGF4cmF0ZXMgPC0gcmVhZF9jc3YoIi4vT3V0cHV0LzRDX211bmlfdGF4cmF0ZXMuY3N2IikNCg0KcGluX2RhdGEyIDwtIHBpbl9kYXRhMiAlPiUgbGVmdF9qb2luKGNsYXNzX2RpY3QpDQoNCiMgYWxsIHBpbnMgaW4gbXVuaXMgZnVsbHkgd2l0aGluIGNvb2sgY291bnR5IHRoYXQgYXJlIHNvbWUgZm9ybSBvZiBzaW5nbGUtZmFtaWx5LCBkZXRhY2hlZCBob21lDQpzaW5nZmFtX3BpbnMgPC0gcGluX2RhdGEyICU+JSANCiAgZmlsdGVyKHRheF9jb2RlICVpbiUgbXVuaV9UQ19mdWxseUNvb2skdGF4X2NvZGVfbnVtKSAlPiUgIyBleGNsdWRlcyBjb3VudHkgbGluZSBjcm9zc2luZyBtdW5pcw0KICBmaWx0ZXIoT3B0aW9uMiA9PSAiU2luZ2xlLUZhbWlseSIpIA0KDQpgYGANCg0KIyBGaW5kaW5nIGFuZCBDb21wYXJpbmcgIk1lZGlhbiBQcm9wZXJ0aWVzIg0KDQojIyBDb29rIE1lZGlhbg0KDQpDb29rIENvdW50eSBTdGF0czoNCg0KLSAgIDI1dGggcGVyY2VudGlsZSBvZiBQSU4gQVYgaXMgXCQxNCwxNTUgaW4gQ29vayBDb3VudHkgKGkuZS4sIDI1JSBvZiBob21lcyBoYXZlIEFWcyBsZXNzIHRoYW4gMTRLIGFuZCA3NSUgaGF2ZSBBVnMgbW9yZSB0aGFuIDE0SykNCi0gICA1MHRoIHBlcmNlbnRpbGUgb2YgUElOIEFWIGlzIFwkMjEsMDAzDQotICAgNzV0aCBwZXJjZW50aWxlIG9mIFBJTiBBViBpcyBcJDMxLDQxNw0KDQoNCg0KYGBge3IsIG91dC53aWR0aD0iNTAlIiwgZmlnLnNob3c9J2hvbGQnLCBlY2hvPUZBTFNFfQ0KIyANCiMgc2luZ2ZhbV9waW5zICU+JQ0KIyBnZ3Bsb3QoYWVzKHggPSBPcHRpb24yLCB5PWF2KSkgKw0KIyAgIGdlb21fdmlvbGluKHdpZHRoID0gMS40KSAgKw0KIyAgIGdlb21fYm94cGxvdChjb2xvciA9ICJncmF5IiwgYWxwaGEgPSAwLjIpKw0KIyAgIHRoZW1lX2NsYXNzaWMoKSsNCiMgICMgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQojICAgY29vcmRfZmxpcCgpKw0KIyAgIGxhYnModGl0bGUgPSAiQ29vayBDb3VudHkgQ2xhc3MgRGlzdHJpYnV0aW9uIG9mIEFWIiwgeSA9ICJBc3Nlc3NlZCBWYWx1ZSAoJCkiLCB4PSIiKSArDQojICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVsID0gc2NhbGVzOjpkb2xsYXIpDQoNCnNpbmdmYW1fcGlucyAlPiUNCiAgIyAgZmlsdGVyKGF2IDwgMTAwMDAwMCkgJT4lICMganVzdCB0byBzZWUgdGhlIGhpc3RvZ3JhbSBiZXR0ZXINCiAgZmlsdGVyKGF2IDwgNTAwMDAwKSAlPiUgIyBqdXN0IHRvIHNlZSB0aGUgaGlzdG9ncmFtIGJldHRlcg0KICBmaWx0ZXIoYXYgPCAzMDAwMDApICU+JSAjIGp1c3QgdG8gc2VlIHRoZSBoaXN0b2dyYW0gYmV0dGVyDQogIA0KICBnZ3Bsb3QoIGFlcyh4PWF2KSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gNTApICArDQogIHRoZW1lX2NsYXNzaWMoKSsNCiAgIyBjb29yZF9mbGlwKCkrDQogIGxhYnModGl0bGUgPSAiQ29vayBDb3VudHkgU2luZ2xlLUZhbWlseSBQSU4gRGlzdHJpYnV0aW9uIG9mIEFWIiwgDQogICAgICAgeCA9ICJBc3Nlc3NlZCBWYWx1ZSAoJCkiLCB5PSIjIG9mIFBpbnMiLCANCiAgICAgICBjYXB0aW9uID0gIkRyb3BwZWQgUElOcyB3aXRoIEFWcyBvdmVyICQzMDAsMDAwIGZvciBiZXR0ZXIgdmlzdWFsIG9mIGhpc3RvZ3JhbSBiaW5zLiIpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVsID0gc2NhbGVzOjpkb2xsYXIpKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWwgPSBzY2FsZXM6OmNvbW1hKQ0KYGBgDQoNCmBgYHtyfQ0KIyBRdWFydGlsZXMNCiNxdWFudGlsZShzaW5nZmFtX3BpbnMkYXYpDQoNCg0KIyBEZWNpbGVzDQojIHF1YW50aWxlKHNpbmdmYW1fcGlucyRhdiwgcHJvYnMgPSBjKDAsIC4xLCAuMiwgLjMsIC40LCAuNSwgLjYsIC43LCAuOCwgLjksIDEpKQ0KDQoNCnEgPSBjKC4yNSwgLjUsIC43NSkNCg0KDQpjb29rX3F1YXJ0aWxlcyA8LSBzaW5nZmFtX3BpbnMgJT4lDQogIGZpbHRlcihPcHRpb24yID09ICJTaW5nbGUtRmFtaWx5IikgJT4lDQogIGZpbHRlcih0YXhfY29kZSAlaW4lIG11bmlfVENfZnVsbHlDb29rJHRheF9jb2RlX251bSkgJT4lICMgZXhjbHVkZXMgY291bnR5IGxpbmUgY3Jvc3NpbmcgbXVuaXMNCiAgYXJyYW5nZShhdikgJT4lDQogIHN1bW1hcml6ZShjb3VudF9waW5zID0gbigpLCANCiAgICAgICAgICAgIG1pbiA9IG1pbihhdiksDQogICAgICAgICAgICBxdWFudDI1ID0gcm91bmQocXVhbnRpbGUoYXYsIHByb2JzID0gcVsxXSkpLCANCiAgICAgICAgICAgIHF1YW50NTAgPSByb3VuZChxdWFudGlsZShhdiwgcHJvYnMgPSBxWzJdKSksDQogICAgICAgICAgICBxdWFudDc1ID0gcm91bmQocXVhbnRpbGUoYXYsIHByb2JzID0gcVszXSkpLA0KICAgICAgICAgICAgbWF4ID0gbWF4KGF2KSkNCg0KY2hvc2VuM19yYW5rZWQgPC0gc2luZ2ZhbV9waW5zICU+JSAgDQogIGxlZnRfam9pbihuaWNrbmFtZXMpICU+JSANCiAgZmlsdGVyKGNsZWFuX25hbWUgJWluJSBjKCJEb2x0b24iLCAiQ2hpY2FnbyIsICJHbGVuY29lIikpICU+JQ0KICBtdXRhdGUocmFuayA9IGNhc2Vfd2hlbigNCiAgICBhdiA+IChjb29rX3F1YXJ0aWxlcyRxdWFudDI1LTUwMCkgJiAoYXY8Y29va19xdWFydGlsZXMkcXVhbnQyNSs1MDApIH4gInEyNSIsDQogICAgYXYgPiAoY29va19xdWFydGlsZXMkcXVhbnQ1MC01MDApICYgKGF2PGNvb2tfcXVhcnRpbGVzJHF1YW50NTArNTAwKSB+ICJxNTAiLA0KICAgIGF2ID4gKGNvb2tfcXVhcnRpbGVzJHF1YW50NzUtNTAwKSAmIChhdjxjb29rX3F1YXJ0aWxlcyRxdWFudDc1KzUwMCkgfiAicTc1IikpICU+JQ0KICBzZWxlY3QoY2xlYW5fbmFtZSwgcmFuaywgYXYsIHBpbiwgY2xhc3MsIGV2ZXJ5dGhpbmcoKSkgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKHJhbmspKSAjIDI1LDQxMyBwaW5zIGtlcHQgZm9yIHRoZXNlIDQgcGxhY2VzDQoNCg0KY2hvc2VuM19iaWxsY2hhbmdlIDwtICBjaG9zZW4zX3JhbmtlZCAlPiUgDQogIGdyb3VwX2J5KGNsZWFuX25hbWUsIHJhbmspJT4lDQogIGFycmFuZ2UoYXYpICU+JQ0KICMgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KICBtdXRhdGUoI3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QgLyB0YXhfY29kZV9yYXRlLA0KICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSwgcmFuaywgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIHN1bW1hcml6ZShtZWRpYW5fQVYgPSByb3VuZChtZWRpYW4oYXYpKSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSByb3VuZChtZWRpYW4oZWF2KSksDQogICAgICAgICAgICAjIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgIyBtZWRpYW5fYmlsbF9uZXcgPSBtZWRpYW4oYmlsbF9ub2V4ZW1wcyksDQogICAgICAgICAgICAjIG1lZGlhbl9jaGFuZ2UgPSBtZWRpYW4oYmlsbF9jaGFuZ2UpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX2N1ciA9IHJvdW5kKG1lYW4oYmlsbF9jdXJyZW50LCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2JpbGxfbmV3ID0gcm91bmQobWVhbihiaWxsX25vZXhlbXBzLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2NoYW5nZSA9IHJvdW5kKG1lYW4oYmlsbF9jaGFuZ2UsIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSByb3VuZChtZWFuKGN1cl9jb21wX1RDX3JhdGUpLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSByb3VuZChtZWFuKG5ld19jb21wX1RDX3JhdGUpLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIHBpbmNvdW50PW4oKQ0KKSAlPiUNCiAgYXJyYW5nZShoYXNfSE9fZXhlbXAsIHJhbmspDQoNCg0Kd3JpdGVfY3N2KGNob3NlbjNfYmlsbGNoYW5nZSwgIjRkX3F1YXJ0aWxlc19iaWxsY2hhbmdlLmNzdiIpDQpgYGANCg0KDQpgYGB7ciBxdWFydGlsZS1iaWxsY2hhbmdlLWFsbENvb2ssIGV2YWw9RkFMU0UsIGluY2x1ZGUgPSBGQUxTRX0NCmFsbG11bmlzX3JhbmtlZCA8LSBzaW5nZmFtX3BpbnMgJT4lICANCiAgbGVmdF9qb2luKG5pY2tuYW1lcykgJT4lIA0KICMgZmlsdGVyKGNsZWFuX25hbWUgJWluJSBjKCJEb2x0b24iLCAiQ2hpY2FnbyIsICJHbGVuY29lIikpICU+JQ0KICBtdXRhdGUocmFuayA9IGNhc2Vfd2hlbigNCiAgICBhdiA+IChjb29rX3F1YXJ0aWxlcyRxdWFudDI1LTUwMCkgJiAoYXY8Y29va19xdWFydGlsZXMkcXVhbnQyNSs1MDApIH4gInEyNSIsDQogICAgYXYgPiAoY29va19xdWFydGlsZXMkcXVhbnQ1MC01MDApICYgKGF2PGNvb2tfcXVhcnRpbGVzJHF1YW50NTArNTAwKSB+ICJxNTAiLA0KICAgIGF2ID4gKGNvb2tfcXVhcnRpbGVzJHF1YW50NzUtNTAwKSAmIChhdjxjb29rX3F1YXJ0aWxlcyRxdWFudDc1KzUwMCkgfiAicTc1IikpICU+JQ0KICBzZWxlY3QoY2xlYW5fbmFtZSwgcmFuaywgYXYsIHBpbiwgY2xhc3MsIGV2ZXJ5dGhpbmcoKSkgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKHJhbmspKQ0KDQoNCmFsbG11bmlzX3JhbmtlZF9iaWxsY2hhbmdlIDwtICBhbGxtdW5pc19yYW5rZWQgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lLCByYW5rKSU+JQ0KICBhcnJhbmdlKGF2KSAlPiUNCiAjIGdyb3VwX2J5KGFnZW5jeV9uYW1lLCBoYXNfSE9fZXhlbXApICU+JSANCiAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQogICAgICAgICBiaWxsX2N1cnJlbnQgPSAoZmluYWxfdGF4X3RvX2Rpc3QgKyBmaW5hbF90YXhfdG9fdGlmKSwNCiAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQogIGdyb3VwX2J5KGNsZWFuX25hbWUsIHJhbmssIGhhc19IT19leGVtcCkgJT4lIA0KICBzdW1tYXJpemUobWVkaWFuX0FWID0gcm91bmQobWVkaWFuKGF2KSksDQogICAgICAgICAgICBtZWRpYW5fRUFWID0gcm91bmQobWVkaWFuKGVhdikpLA0KICAgICAgICAgICAgIyBtZWRpYW5fYmlsbF9jdXIgPSBtZWRpYW4oYmlsbF9jdXJyZW50KSwNCiAgICAgICAgICAgICMgbWVkaWFuX2JpbGxfbmV3ID0gbWVkaWFuKGJpbGxfbm9leGVtcHMpLA0KICAgICAgICAgICAgIyBtZWRpYW5fY2hhbmdlID0gbWVkaWFuKGJpbGxfY2hhbmdlKSwNCiAgICAgICAgICAgIG1lYW5fYmlsbF9jdXIgPSByb3VuZChtZWFuKGJpbGxfY3VycmVudCwgbmEucm09VFJVRSkpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX25ldyA9IHJvdW5kKG1lYW4oYmlsbF9ub2V4ZW1wcywgbmEucm09VFJVRSkpLA0KICAgICAgICAgICAgbWVhbl9jaGFuZ2UgPSByb3VuZChtZWFuKGJpbGxfY2hhbmdlLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBwZXJjZWl2ZWRfc2F2aW5ncyA9IG1lZGlhbih0YXhfYW10X2V4ZSksDQogICAgICAgICAgICBjdXJfY29tcF9UQ19yYXRlID0gcm91bmQobWVhbihjdXJfY29tcF9UQ19yYXRlKSwgZGlnaXRzID0gMiksDQogICAgICAgICAgICBuZXdfY29tcF9UQ19yYXRlID0gcm91bmQobWVhbihuZXdfY29tcF9UQ19yYXRlKSwgZGlnaXRzID0gMiksDQogICAgICAgICAgICBwaW5jb3VudD1uKCkNCikgJT4lDQogIGFycmFuZ2UoaGFzX0hPX2V4ZW1wLCByYW5rKSAlPiUNCiAgbXV0YXRlKHJhdGVfY2hhbmdlID0gbmV3X2NvbXBfVENfcmF0ZSAtIGN1cl9jb21wX1RDX3JhdGUpDQoNCg0Kd3JpdGVfY3N2KGFsbG11bmlzX3JhbmtlZF9iaWxsY2hhbmdlLCAiNGRfcXVhcnRpbGVzX2FsbE11bmlzX2JpbGxjaGFuZ2UuY3N2IikNCmBgYA0KDQojIyMjIEJpbGwgY2hhbmdlIGZvciB0aG9zZSB0aGF0IERpZCBOb3QgQ2xhaW0gRXhlbXB0aW9uczoNCg0KRWFjaCBNdW5pY2lwYWxpdHkgaGFzIGRpZmZlcmVudCBjb21wb3NpdGUgdGF4IHJhdGVzLiBUaGlzIGNhdXNlcyB0aGUgYXZlcmFnZSB0YXggYmlsbCB0byB2YXJ5IGdlb2dyYXBoaWNhbGx5IHdpdGhpbiBDb29rIENvdW50eS4gRm9yIHByb3BlcnRpZXMgdGhhdCBhcmUgYXQgdGhlIENvb2sgQ291bnR5IDI1dGggcGVyY2VudGlsZSBpbiBhc3Nlc3NlZCB2YWx1ZSAoXCQxNCwwMDApLCBjdXJyZW50IHRheCBiaWxscyByYW5nZSBmcm9tIFwkMiw4MDAgaW4gQ2hpY2FnbyB0byBvdmVyIFwkMTAsMDAwIGluIERvbHRvbi4gVGhlIG1lZGlhbiBDb29rIENvdW50eSBwcm9wZXJ0eSBjdXJyZW50bHkgKEFWPSBcJDIxLDAwMCkgaGFzIGEgXCQ0LDIwMCBiaWxsIGluIENoaWNhZ28sIGEgXCQxNCw0MDAgYmlsbCBpbiBEb2x0b24sIGFuZCBhIFwkNiwwMDAgYmlsbCBpbiBHbGVuY29lLg0KDQpJZiB0aGUgZ2VuZXJhbCBob21lc3RlYWQgZXhlbXB0aW9uIHdhcyB0ZXJtaW5hdGVkLCBhZGRpdGlvbmFsIEVBViB3b3VsZCBiZWNvbWUgdGF4YWJsZSB3aGljaCB3b3VsZCB0aGVuIHJlc3VsdCBpbiBsb3dlciB0YXggcmF0ZXMgZm9yIGFsbCBwcm9wZXJ0aWVzLiBUaGlzIGxvd2VyIHRheCByYXRlIHdvdWxkIHJlc3VsdCBpbiBsb3dlciB0YXggYmlsbHMgZm9yIHByb3BlcnRpZXMgdGhhdCB3ZXJlIG5vdCBjbGFpbWluZyB0aGUgZ2VuZXJhbCBob21lc3RlYWQgZXhlbXB0aW9uLlteMV0NCg0KW14xXTogQSBiaW5hcnkgdmFyaWFibGUgd2FzIGNyZWF0ZWQgYXQgdGhlIFBJTiBsZXZlbCBkYXRhIGZvciBpZiBleGVfaG9tZW93bmVyIHdhcyBcPiAwLiBJZiBhbnkgYW1vdW50IG9mIEVBViB3YXMgZXhlbXB0IHdpdGhpbiBleGVfaG9tZW93bmVyLCB0aGVuIHRoZSBQSU4gd2FzIGNvbnNpZGVyZWQgdG8gaGF2ZSByZWNlaXZlZCB0aGUgR2VuZXJhbCBIb21lc3RlYWQgRXhlbXB0aW9uLiBUaGF0IHNwZWNpZmljIGV4ZW1wdGlvbiBhbGxvd3MgdXAgdG8gXCQxMCwwMDAgaW4gRUFWIHRvIGJlY29tZSB0YXggZXhlbXB0LiBEYXRhIHdhcyBwdWxsZWQgZnJvbSB0aGUgYHBpbmAgdGFibGUgdXNlZCBpbiBDQ0FPJ3MgUFRBWFNJTS4NCg0KV2hlbiBsb29raW5nIGF0IHRob3NlIHdobyBkaWQgbm90IGNsYWltIHRoZSBHZW5lcmFsIEhvbWVzdGVhZCBFeGVtcHRpb24gKEdIRSkgYW5kIG93biBwcm9wZXJ0aWVzIGFzc2Vzc2VkIGF0IENvb2sgQ291bnR5J3MgbWVkaWFuIEFWIChBViA9IFwkMjEsMDAwKSwgYWxsIHRheCBiaWxscyB3b3VsZCBkZWNyZWFzZSBmcm9tIGN1cnJlbnQgYW1vdW50cy4gQSBob21lb3duZXIgd291bGQgZXhwZXJpZW5jZSBhIFwkNTAwIGRlY3JlYXNlIGluIHRoZWlyIHRheGJpbGwgaW4gQ2hpY2FnbyBhbmQgb3ZlciBhIFwkMiwxMDAgZGVjcmVhc2UgaW4gRG9sdG9uIGlmIGFkZGl0aW9uYWwgRUFWIGJlY2FtZSB0YXhhYmxlIGZyb20gdGhlIHRlcm1pbmF0aW9uIG9mIHRoZSBHSEUuDQoNCmBgYHtyfQ0KY2hvc2VuM19iaWxsY2hhbmdlICU+JSANCiAgZmlsdGVyKGhhc19IT19leGVtcCA9PSAwICYgIWlzLm5hKHJhbmspKSAlPiUNCiAgc2VsZWN0KE11bmljaXBhbGl0eSA9IGNsZWFuX25hbWUsICJQZXJjZW50aWxlIiA9IHJhbmssICAiQXZnIEN1cnJlbnQgQmlsbCIgPSBtZWFuX2JpbGxfY3VyLCAiQXZnIE5ldyBCaWxsIiA9IG1lYW5fYmlsbF9uZXcsICJUYXggQmlsbCBDaGFuZ2UiID0gbWVhbl9jaGFuZ2UsICJQZXJjZWl2ZWQgU2F2aW5ncyIgPSBwZXJjZWl2ZWRfc2F2aW5ncywgIiMgUGlucyBpbiBBViBSYW5nZSIgPSBwaW5jb3VudCwgIkFWIiA9IG1lZGlhbl9BViwgY3VyX2NvbXBfVENfcmF0ZSwgbmV3X2NvbXBfVENfcmF0ZSwgZXZlcnl0aGluZygpKQ0KYGBgDQoNCiMjIyMgQmlsbCBDaGFuZ2UgZm9yIHRob3NlIHRoYXQgZGlkIGNsYWltIHRoZSBHZW5lcmFsIEhvbWVzdGVhZCBFeGVtcHRpb24NCg0KV2hlbiBsb29raW5nIGF0IHRob3NlIHdobyBkaWQgY2xhaW0gdGhlIEdlbmVyYWwgSG9tZXN0ZWFkIEV4ZW1wdGlvbiAoR0hFKSBhbmQgb3duIHByb3BlcnRpZXMgYXNzZXNzZWQgYXQgQ29vayBDb3VudHkncyBtZWRpYW4gQVYgKEFWID0gXCQyMSwwMDApLCBhbGwgdGF4IGJpbGxzIHdvdWxkIGluY3JlYXNlIGZyb20gY3VycmVudCBhbW91bnRzIGJ1dCB0aGUgdGF4IHJhdGUgYXBwbGllZCB0byBhbGwgcHJvcGVydHkgb3duZXJzIHdvdWxkIGRlY3JlYXNlLiBBIGhvbWVvd25lciB3b3VsZCBleHBlcmllbmNlIGEgXCQxOTAgaW5jcmVhc2UgaW4gdGhlaXIgdGF4YmlsbCBpbiBDaGljYWdvIGFuZCBhIFwkODUgaW5jcmVhc2UgaW4gR2xlbmNvZS4gV2hpbGUgdGhlcmUgYXJlIG5vIHByb3BlcnRpZXMgdmFsdWVkIGF0IHRoZSBjb3VudHkgbWVkaWFuIEFWIGluIERvbHRvbiwgYSBwcm9wZXJ0eSB2YWx1ZWQgYXQgdGhlIGNvdW50eSdzIDI1dGggcGVyY2VudGlsZSB3b3VsZCBleHBlcmllbmNlIGEgXCQ2NTAgaW5jcmVhc2UgaWYgYWRkaXRpb25hbCBFQVYgYmVjYW1lIHRheGFibGUgZnJvbSB0aGUgdGVybWluYXRpb24gb2YgdGhlIEdIRS4NCg0KSG93ZXZlciwgdGhlc2UgaHlwb3RoZXRpY2FsIGJpbGwgaW5jcmVhc2VzIHdvdWxkIGJlIHNpZ25pZmljYW50bHkgbGVzcyB0aGFuIHByb3BlcnR5IG93bmVycyB3b3VsZCBpbml0aWFsbHkgdGhpbmsuIEFsbCB0YXggYmlsbHMgc2hvd3RoZSBhbW91bnQgdGhhdCB0aGV0YXggYmlsbCB3YXMgcmVkdWNlZCBkdWUgdG8gZXhlbXB0aW9uczogZXhlbXB0IEVBViBcKiBjdXJyZW50IGNvbXBvc2l0ZSB0YXggcmF0ZS4gSG93ZXZlciwgdGhpcyB2YWx1ZSBpcyBhbiBvdmVyIGVzdGltYXRlIG9mIGhvdyB0aGUgdGF4IGJpbGwgd291bGQgY2hhbmdlIGJlY2F1c2UgaXQgZG9lcyBub3QgdGFrZSBpbnRvIGFjY291bnQgdGhlIGRlY3JlYXNlIGluIHRheCByYXRlIHRoYXQgd291bGQgb2NjdXI6IGlmIHlvdSBpbmNyZWFzZSB0aGUgdGF4YWJsZSBFQVYgYW5kIGhvbGQgdGhlIGxldnkgY29uc3RhbnQsIHRoZW4gdGhlIHRheCByYXRlIGRlY3JlYXNlcyBmb3IgYWxsIHByb3BlcnRpZXMuDQoNCk92ZXJhbGwsIGhvbWUgb3duZXJzIGJlbGlldmUgdGhleSBhcmUgYmVuZWZpdGluZyBtb3JlIGZyb20gdGhlIGdlbmVyYWwgaG9tZXN0ZWFkIGV4ZW1wdGlvbiB0aGFuIHRoZXkgd291bGQgYmUgaW4gdGhpcyBzY2VuYXJpby4gUG9saWN5bWFrZXJzIGFsc28gbGlrZWx5IGJlbGlldmUgZXhlbXB0aW9ucyBhcmUgcHJvdmlkaW5nIG1vcmUgYmVuZWZpdHMgdGhhbiB0aGV5IGFjdHVhbGx5IGFyZSB0byBob21lb3duZXJzLiBXaGlsZSB0aG9zZSB3aG8gY2xhaW0gdGhlIGV4ZW1wdGlvbiBoYXZlIGxlc3MgRUFWIHRoYXQgaXMgdGF4ZWQsIHRoZSBjb21wb3NpdGUgdGF4IHJhdGUgaW5jcmVhc2VzIGZvciBhbGwgcHJvcGVydHkgb3duZXJzLiBVbHRpbWF0ZWx5IHNvbWUgb2YgdGhlIHByb3BlcnR5IHRheCBidXJkZW4gaXMgc2hpZnRlZCBmcm9tIGhvbWVvd25lcnMgdG8gb3RoZXIgcHJvcGVydHkgb3duZXJzLiBUaGUgYW1vdW50IG9mIHRoZSBidXJkZW4gc2hpZnQgZGVwZW5kcyBvbiBhbiBhcmVhJ3MgcHJvcG9ydGlvbmFsIGxhbmQgdXNlIChyZXNpZGVudGlhbCBFQVYgLyB0b3RhbCBFQVYpLlteMl0NCg0KW14yXTogV2hpbGUgdGhlIHRheCByYXRlIGNhbGN1bGF0aW9ucyBkbyB0YWtlIGludG8gY29uc2lkZXJhdGlvbiBUSUYgaW5jcmVtZW50cywgd2UgaGF2ZSBub3QgZGlzY3Vzc2VkIHRoZSByb2xlIHRoYXQgVElGcyBwbGF5IGluIGNvbXBvc2l0ZSB0YXggcmF0ZXMuIElmIGEgVElGIGV4aXN0cyBpbiB0aGUgc2FtZSB0YXggY29kZSBhcyBhIGhvbWVvd25lciwgdGhlIHRheGFibGUgRUFWIGlzIGZyb3plbiBmb3IgeWVhcnMgdG8gY29tZS4gSG93ZXZlciB0aGUgbGV2eSBhbW91bnQgbmVlZGVkIHRvIHByb3ZpZGUgcHVibGljIHNlcnZpY2VzIHVzdWFsbHkgaW5jcmVhc2VzIG92ZXIgdGltZSBhbmQgcmVzdWx0cyBpbiBoaWdoZXIgdGF4IHJhdGVzIGZvciB0aG9zZSBpbiBUSUYgYXJlYXMgY29tcGFyZWQgdG8gbmVhcmJ5IG5vbi1USUYgdGF4IGNvZGVzLg0KDQpgYGB7cn0NCmNob3NlbjNfc3VtbWFyeXRhYmxlIDwtIGNob3NlbjNfYmlsbGNoYW5nZSAlPiUgDQogIGZpbHRlcihoYXNfSE9fZXhlbXAgPT0gMQ0KICAgICAgICAgIyYgIWlzLm5hKHJhbmspDQogICAgICAgICApICU+JQ0KICAjYXJyYW5nZShjbGVhbl9uYW1lLCByYW5rKSAlPiUNCiAgc2VsZWN0KE11bmljaXBhbGl0eSA9IGNsZWFuX25hbWUsICJQZXJjZW50aWxlIiA9IHJhbmssICJBdmcgQ3VycmVudCBCaWxsIiA9IG1lYW5fYmlsbF9jdXIsICJBdmcgTmV3IEJpbGwiID0gbWVhbl9iaWxsX25ldywgIlRheCBCaWxsIENoYW5nZSIgPSBtZWFuX2NoYW5nZSwgIlBlcmNlaXZlZCBTYXZpbmdzIiA9IHBlcmNlaXZlZF9zYXZpbmdzLCAiIyBQaW5zIGluIEFWIFJhbmdlIiA9IHBpbmNvdW50LCAgIkFWIiA9IG1lZGlhbl9BViwgY3VyX2NvbXBfVENfcmF0ZSwgbmV3X2NvbXBfVENfcmF0ZSwgZXZlcnl0aGluZygpKQ0KDQpjaG9zZW4zX3N1bW1hcnl0YWJsZQ0KYGBgDQoNCiMjIEFsdGVybmF0aXZlIE1ldGhvZDogTWVkaWFuIG9mIGVhY2ggTXVuaWNpcGFsaXR5DQoNCkFzc2Vzc2VkIFZhbHVlIGlzIHVzZWQgdG8gaWRlbnRpZnkgdGhlIHF1YXJ0aWxlIGJyZWFrcyB3aXRoaW4gZWFjaCBtdW5pY2lwYWxpdHkgZm9yIHNpbmdsZS1mYW1pbHkgcHJvcGVydGllcy4gVGhlc2UgYnJlYWsgcG9pbnRzIHdpbGwgdGhlbiBiZSB1c2VkIHRvIGxvb2sgYXQgaG93IHRoZSB0YXggYmlsbCBjaGFuZ2VzIGZvciBwcm9wZXJ0aWVzIHdpdGggQVZzIGF0IHRoZSAyNXRoIHBlcmNlbnRpbGUsIDUwdGggcGVyY2VudGlsZSwgYW5kIDc1dGggcGVyY2VudGlsZS4NCg0KVGhlIGFzc2Vzc2VkIHZhbHVlIGFuZCBvcmlnaW5hbCBlcXVhbGl6ZWQgYXNzZXNzZWQgdmFsdWVzIGNvbWUgZnJvbSB0aGUgYHBpbmAgZGF0YSB0YWJsZSB3aXRoaW4gUFRBWFNJTS4gVGhpcyB0YWJsZSBhbHNvIGhhcyBldmVyeSB0eXBlIG9mIGV4ZW1wdGlvbiB0aGF0IHRoZSBwcm9wZXJ0eSByZWNlaXZlZCBhbmQgdGhlIGFtb3VudCBvZiBFQVYgdGhhdCB3YXMgZXhlbXB0IGR1ZSB0byB0aGUgZXhlbXB0aW9uLg0KDQpgYGB7cn0NCnEgPSBjKC4yNSwgLjUsIC43NSkNCg0KbXVuaV9xdWFydGlsZXMgPC0gcGluX2RhdGEyICU+JQ0KICBmaWx0ZXIoT3B0aW9uMiA9PSAiU2luZ2xlLUZhbWlseSIpJT4lDQogIGdyb3VwX2J5KGFnZW5jeV9uYW1lICkgJT4lDQogIGFycmFuZ2UoYXYpICU+JQ0KICBzdW1tYXJpemUoY291bnRfcGlucyA9IG4oKSwgDQogICAgICAgICAgICBtaW4gPSBtaW4oYXYpLA0KICAgICAgICAgICAgcXVhbnQyNSA9IHJvdW5kKHF1YW50aWxlKGF2LCBwcm9icyA9IHFbMV0pKSwgDQogICAgICAgICAgICBxdWFudDUwID0gcm91bmQocXVhbnRpbGUoYXYsIHByb2JzID0gcVsyXSkpLA0KICAgICAgICAgICAgcXVhbnQ3NSA9IHJvdW5kKHF1YW50aWxlKGF2LCBwcm9icyA9IHFbM10pKSwNCiAgICAgICAgICAgIG1heCA9IG1heChhdikpICU+JSANCiAgYXJyYW5nZSggZGVzYyggcXVhbnQ1MCkpIA0KDQpjaG9zZW4zIDwtIG11bmlfcXVhcnRpbGVzICU+JSANCiAgbGVmdF9qb2luKG5pY2tuYW1lcykgJT4lIA0KICBmaWx0ZXIoY2xlYW5fbmFtZSAlaW4lIGMoIkRvbHRvbiIsICJDaGljYWdvIiwgIkdsZW5jb2UiKSkNCiMgY2hvc2VuMw0KDQpjaG9zZW4zX3JhbmtlZCA8LSBwaW5fZGF0YTIgJT4lDQogIGlubmVyX2pvaW4oY2hvc2VuMywgYnkgPSAiYWdlbmN5X25hbWUiKSAlPiUNCiAgbXV0YXRlKHJhbmsgPSBjYXNlX3doZW4oDQogICAgYXYgPiAocXVhbnQyNS01MDApICYgKGF2PHF1YW50MjUrNTAwKSB+ICJxMjUiLA0KICAgIGF2ID4gKHF1YW50NTAtNTAwKSAmIChhdjxxdWFudDUwKzUwMCkgfiAicTUwIiwNCiAgICBhdiA+IChxdWFudDc1LTUwMCkgJiAoYXY8cXVhbnQ3NSs1MDApIH4gInE3NSIpKSAlPiUNCiAgc2VsZWN0KGNsZWFuX25hbWUsIHJhbmssIGF2LCBwaW4sIGNsYXNzLCBldmVyeXRoaW5nKCkpDQoNCg0KIyBjaG9zZW4zX3JhbmtlZCAlPiUgDQojICAgZ3JvdXBfYnkoY2xlYW5fbmFtZSwgcmFuayklPiUNCiMgICMgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KIyAgIG11dGF0ZSgjdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdCAvIHRheF9jb2RlX3JhdGUsDQojICAgICAjIGN1cnJlbnQgYmlsbCA9IGN1cnJlbnQgdGF4IHJhdGUgKiBwb3J0aW9uIG9mIGxldnkgYmlsbGVkDQojICAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KIyAgICAgICAgICBiaWxsX25vZXhlbXBzID0gIG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQojICAgICAgICAgIGJpbGxfY2hhbmdlID0gYmlsbF9ub2V4ZW1wcyAtIGJpbGxfY3VycmVudCkgJT4lDQojICAgZ3JvdXBfYnkoY2xlYW5fbmFtZSwgcmFuaywgemVyb19iaWxsLCBoYXNfSE9fZXhlbXApICU+JSANCiMgICBzdW1tYXJpemUobWVkaWFuX0FWID0gbWVkaWFuKGF2KSwNCiMgICAgICAgICAgICAgbWVkaWFuX0VBViA9IG1lZGlhbihlYXYpLA0KIyAgICAgICAgICAgICBtZWFuX2JpbGxfY3VyID0gbWVhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpLA0KIyAgICAgICAgICAgICBtZWRpYW5fYmlsbF9jdXIgPSBtZWRpYW4oYmlsbF9jdXJyZW50KSwNCiMgICAgICAgICAgICAgbWVhbl9iaWxsX25ldyA9IG1lYW4oYmlsbF9ub2V4ZW1wcywgbmEucm09VFJVRSksDQojICAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiMgICAgICAgICAgICAgbWVhbl9jaGFuZ2UgPSBtZWFuKGJpbGxfY2hhbmdlLCBuYS5ybT1UUlVFKSwNCiMgICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQojICAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiMgICAgICAgICAgICAgY3VyX2NvbXBfVENfcmF0ZSA9IG1lYW4oY3VyX2NvbXBfVENfcmF0ZSksDQojICAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KIyAgICAgICAgICAgICBwaW5jb3VudD1uKCkNCiMgKQ0KDQojIGNob3NlbjNfcmFua2VkICU+JSANCiMgICBncm91cF9ieShjbGVhbl9uYW1lLCByYW5rKSU+JQ0KIyAgIGFycmFuZ2UoYXYpICU+JQ0KIyAgIyBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUgDQojICAgbXV0YXRlKCN0YXhhYmxlX2VhdiA9IGZpbmFsX3RheF90b19kaXN0IC8gdGF4X2NvZGVfcmF0ZSwNCiMgICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiMgICAgICAgICAgYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQojICAgICAgICAgIGJpbGxfbm9leGVtcHMgPSAgbmV3X2NvbXBfVENfcmF0ZS8xMDAqKGVxdWFsaXplZF9BVi1hbGxfZXhlbXB0aW9ucytleGVfaG9tZW93bmVyKSwNCiMgICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiMgICBncm91cF9ieShjbGVhbl9uYW1lLCByYW5rKSAlPiUgDQojICAgc3VtbWFyaXplKG1lZGlhbl9BViA9IHJvdW5kKG1lZGlhbihhdikpLA0KIyAgICAgICAgICAgICBtZWRpYW5fRUFWID0gcm91bmQobWVkaWFuKGVhdikpLA0KIyAgICAgICAgICAgICBtZWFuX2JpbGxfY3VyID0gbWVhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpLA0KIyAgICAgICAgICAgICBtZWRpYW5fYmlsbF9jdXIgPSBtZWRpYW4oYmlsbF9jdXJyZW50KSwNCiMgICAgICAgICAgICAgbWVhbl9iaWxsX25ldyA9IG1lYW4oYmlsbF9ub2V4ZW1wcywgbmEucm09VFJVRSksDQojICAgICAgICAgICAgIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiMgICAgICAgICAgICAgbWVhbl9jaGFuZ2UgPSBtZWFuKGJpbGxfY2hhbmdlLCBuYS5ybT1UUlVFKSwNCiMgICAgICAgICAgICAgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQojICAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiMgICAgICAgICAgICAgY3VyX2NvbXBfVENfcmF0ZSA9IG1lYW4oY3VyX2NvbXBfVENfcmF0ZSksDQojICAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSBtZWFuKG5ld19jb21wX1RDX3JhdGUpLA0KIyAgICAgICAgICAgICBwaW5jb3VudD1uKCkNCiMgKQ0KY2hvc2VuM19iaWxsY2hhbmdlIDwtICBjaG9zZW4zX3JhbmtlZCAlPiUgDQogIGdyb3VwX2J5KGNsZWFuX25hbWUsIHJhbmspJT4lDQogIGFycmFuZ2UoYXYpICU+JQ0KICMgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KICBtdXRhdGUoI3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QgLyB0YXhfY29kZV9yYXRlLA0KICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSwgcmFuaywgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIHN1bW1hcml6ZShtZWRpYW5fQVYgPSByb3VuZChtZWRpYW4oYXYpKSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSByb3VuZChtZWRpYW4oZWF2KSksDQogICAgICAgICAgICAjIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgIyBtZWRpYW5fYmlsbF9uZXcgPSBtZWRpYW4oYmlsbF9ub2V4ZW1wcyksDQogICAgICAgICAgICAjIG1lZGlhbl9jaGFuZ2UgPSBtZWRpYW4oYmlsbF9jaGFuZ2UpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX2N1ciA9IHJvdW5kKG1lYW4oYmlsbF9jdXJyZW50LCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2JpbGxfbmV3ID0gcm91bmQobWVhbihiaWxsX25vZXhlbXBzLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2NoYW5nZSA9IHJvdW5kKG1lYW4oYmlsbF9jaGFuZ2UsIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSByb3VuZChtZWFuKGN1cl9jb21wX1RDX3JhdGUpLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSByb3VuZChtZWFuKG5ld19jb21wX1RDX3JhdGUpLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIHBpbmNvdW50PW4oKQ0KKSAlPiUNCiAgYXJyYW5nZShoYXNfSE9fZXhlbXAsIHJhbmspDQoNCiNjaG9zZW4zX2JpbGxjaGFuZ2UNCg0KDQpwaW5fZGF0YTIgJT4lDQogIGxlZnRfam9pbihuaWNrbmFtZXMpICU+JQ0KICBmaWx0ZXIoT3B0aW9uMiA9PSAiU2luZ2xlLUZhbWlseSIpICU+JQ0KICBmaWx0ZXIoYXYgPCA1MDAwMDApICU+JSAjIHJlbW92ZSB0aGUgY291cGxlIHJlYWxseSBleHRyZW1lIG91dGxpZXJzIGluIENoaWNhZ28NCiAgZmlsdGVyKGNsZWFuX25hbWUgJWluJSBjKCJEb2x0b24iLCAiQ2hpY2FnbyIsICJHbGVuY29lIiwgIk9hayBQYXJrIikpICU+JQ0KICBnZ3Bsb3QoIGFlcyh5PWF2LCBncm91cCA9IGNsZWFuX25hbWUsIGZpbGwgPSBjbGVhbl9uYW1lKSkgKw0KICBnZW9tX2JveHBsb3QoKSsNCiAjIGZhY2V0X3dyYXAofmFnZW5jeV9uYW1lLCBucm93PTQpICsNCiBjb29yZF9mbGlwKCkgKw0KICB0aGVtZV9idygpICArDQogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksIA0KICAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCkpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUmVzaWRlbnRpYWwgUHJvcGVydGllcyBBViIsIHkgPSAiQXNzZXNzZWQgVmFsdWUgKCQpIikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWwgPSBzY2FsZXM6OmRvbGxhcikgDQpgYGANCg0KYGBge3J9DQojaW5zdGFsbC5wYWNrYWdlcygiZ2dyaWRnZXMiKQ0KbGlicmFyeShnZ3JpZGdlcykNCg0KcGluX2RhdGEyICU+JQ0KICBsZWZ0X2pvaW4obmlja25hbWVzKSAlPiUNCiAgZmlsdGVyKE9wdGlvbjIgPT0gIlNpbmdsZS1GYW1pbHkiKSAlPiUNCiAgZmlsdGVyKGF2IDwgMzAwMDAwKSAlPiUgIyByZW1vdmUgdGhlIGNvdXBsZSByZWFsbHkgZXh0cmVtZSBvdXRsaWVycyBpbiBDaGljYWdvDQogZmlsdGVyKGNsZWFuX25hbWUgJWluJSBjKCJEb2x0b24iLCAiQ2hpY2FnbyIsICJHbGVuY29lIikpICU+JQ0KICBnZ3Bsb3QoIGFlcyh4ID0gYXYsIHk9IGNsZWFuX25hbWUsIGZpbGwgPSBjbGVhbl9uYW1lICkgKSsNCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyggYWVzKHggPSBhdiwgeT1jbGVhbl9uYW1lLCBmaWxsID0gY2xlYW5fbmFtZSkgKSsNCiAgdmlyaWRpczo6c2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCwgbmFtZSA9ICIiKSsNCiAgI2ZhY2V0X3dyYXAofmFnZW5jeV9uYW1lLCBuY29sPTQpICsNCiMgIGNvb3JkX2ZsaXAoKSArDQogIHRoZW1lX3JpZGdlcygpICsgDQogIHRoZW1lKCNheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgDQogIyAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCwNCiBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUmVzaWRlbnRpYWwgUHJvcGVydGllcycgQVYiLCANCiAgICAgICB5ID0gIkFzc2Vzc2VkIFZhbHVlIiwgeD0gIiIgKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbCA9IHNjYWxlczo6ZG9sbGFyKQ0KDQpwaW5fZGF0YTIgJT4lDQogIGxlZnRfam9pbihuaWNrbmFtZXMpICU+JQ0KICBmaWx0ZXIoT3B0aW9uMiA9PSAiU2luZ2xlLUZhbWlseSIpICU+JQ0KICBmaWx0ZXIoYXYgPCAzMDAwMDApICU+JSAjIHJlbW92ZSB0aGUgY291cGxlIHJlYWxseSBleHRyZW1lIG91dGxpZXJzIGluIENoaWNhZ28NCiBmaWx0ZXIoY2xlYW5fbmFtZSAlaW4lIGMoIkRvbHRvbiIsICJDaGljYWdvIiwgIkdsZW5jb2UiKSkgJT4lDQogIGdncGxvdCggYWVzKHggPSBhdiwgZmlsbCA9IGNsZWFuX25hbWUgKSApKw0KICBnZW9tX2hpc3RvZ3JhbSggKSsNCiAgZmFjZXRfd3JhcCh+YWdlbmN5X25hbWUsIG5yb3c9NCkgKw0KICB0aGVtZV9jbGFzc2ljKCkrDQogIHRoZW1lKCNheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSwgDQogIyAgICAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCwNCiBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUmVzaWRlbnRpYWwgUHJvcGVydGllcycgQVYiLCANCiAgICAgICB4ID0gIkFzc2Vzc2VkIFZhbHVlIiwgeD0gIiMgUElOcyIgKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbCA9IHNjYWxlczo6ZG9sbGFyKQ0KYGBgDQoNCmBgYHtyfQ0KcGluX2RhdGEyICU+JQ0KICBsZWZ0X2pvaW4obmlja25hbWVzKSAlPiUNCiAgI2ZpbHRlcihBbGVhX2NhdHMgPT0gIk93bmVyIE9jY3VwaWVkIikgJT4lDQogIG11dGF0ZShoYXNfSE9fZXhlbXAgPSBmYWN0b3IoaGFzX0hPX2V4ZW1wLCBsZXZlbHMgPSBjKCJEaWQgTm90IENsYWltIiwgIkRpZCBDbGFpbSIpKSwNCiAgICAgICAgIGNsZWFuX25hbWUgPSBmYWN0b3IoY2xlYW5fbmFtZSkpICU+JQ0KICBmaWx0ZXIoT3B0aW9uMiA9PSAiU2luZ2xlLUZhbWlseSIpICU+JQ0KICBmaWx0ZXIoY2xlYW5fbmFtZSAlaW4lIGMoIkRvbHRvbiIsICJDaGljYWdvIiwgIkdsZW5jb2UiLCAiT2FrIFBhcmsiKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IGNsZWFuX25hbWUsIHk9bG9nKGF2KSwgZmlsbCA9IGNsZWFuX25hbWUpICApKw0KICBnZW9tX3Zpb2xpbihwb3NpdGlvbiA9ICJkb2RnZSIsIGFscGhhID0gMC41LCBvdXRsaWVyLmNvbG9yID0gInRyYW5zcGFyZW50IikrDQogICAgICB2aXJpZGlzOjpzY2FsZV9maWxsX3ZpcmlkaXMoZGlzY3JldGU9VCwgbmFtZT0iIikgKw0KICB0aGVtZV9jbGFzc2ljKCkgKw0KICBjb29yZF9mbGlwKCkrDQogICNmYWNldF93cmFwKH5hZ2VuY3lfbmFtZSwgbmNvbD00KSArDQogICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsgDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFJlc2lkZW50aWFsIFByb3BlcnRpZXMnIEFWIiwgeSA9ICJsb2coQXNzZXNzZWQgVmFsdWUpIiwgeD0gIiIgKSAjKw0KICMgc2NhbGVfeV9jb250aW51b3VzKGxhYmVsID0gc2NhbGVzOjpkb2xsYXIpICMrIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBlbGVtZW50X2JsYW5rKCkpDQoNCg0KYGBgDQoNCmBgYHtyfQ0KY2hvc2VuM19iaWxsY2hhbmdlICU+JSANCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoY2xlYW5fbmFtZSwgaGFzX0hPX2V4ZW1wKSwgDQogICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSAicmFuayIsIHZhbHVlc19mcm9tID0gIm1lYW5fY2hhbmdlIikgJT4lDQogICAgbXV0YXRlKENsYWltZWRfRXhlbXB0aW9uPSBpZmVsc2UoaGFzX0hPX2V4ZW1wID09IDAgLCAiRGlkbid0IENsYWltIEV4ZW1wdGlvbiIsICJEaWQgQ2xhaW0gRXhlbXB0aW9uIikpICU+JQ0KICBzZWxlY3QoTXVuaWNpcGFsaXR5PWNsZWFuX25hbWUsICJDbGFpbWVkX0V4ZW1wdGlvbiIsICJxMjUiLCAicTUwIiwgInE3NSIpDQoNCiMgY2hvc2VuM19iaWxsY2hhbmdlICU+JSANCiMgICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhjbGVhbl9uYW1lLCBoYXNfSE9fZXhlbXAsIHJhbmspLCANCiMgICAgICAgICAgICAgICBuYW1lc19mcm9tID0gInJhbmsiLCB2YWx1ZXNfZnJvbSA9ICJtZWFuX2NoYW5nZSIpICU+JQ0KIyAgICAgbXV0YXRlKENsYWltZWRfRXhlbXB0aW9uPSBpZmVsc2UoaGFzX0hPX2V4ZW1wID09IDAgLCAiRGlkbid0IENsYWltIEV4ZW1wdGlvbiIsICJEaWQgQ2xhaW0gRXhlbXB0aW9uIikpICU+JQ0KIyAgIHNlbGVjdChNdW5pY2lwYWxpdHk9Y2xlYW5fbmFtZSwgIkNsYWltZWRfRXhlbXB0aW9uIiwgInEyNSIsICJxNTAiLCAicTc1IikNCmBgYA0KDQojIyMgQmlsbCBjaGFuZ2UgZm9yIHRob3NlIHRoYXQgRGlkIE5vdCBDbGFpbSBFeGVtcHRpb25zOg0KDQpgYGB7cn0NCmNob3NlbjNfYmlsbGNoYW5nZSAlPiUgDQogIGZpbHRlcihoYXNfSE9fZXhlbXAgPT0gMCAmICFpcy5uYShyYW5rKSkgJT4lDQogIHNlbGVjdChNdW5pY2lwYWxpdHkgPSBjbGVhbl9uYW1lLCAiQVYgUGVyY2VudGlsZSIgPSByYW5rLCAiQVYiID0gbWVkaWFuX0FWLCAiQXZlcmFnZSBDdXJyZW50IEJpbGwiID0gbWVhbl9iaWxsX2N1ciwgIkF2ZXJhZ2UgTmV3IEJpbGwiID0gbWVhbl9iaWxsX25ldywgIlRheCBCaWxsIENoYW5nZSIgPSBtZWFuX2NoYW5nZSwgIlBlcmNlaXZlZCBTYXZpbmdzIiA9IHBlcmNlaXZlZF9zYXZpbmdzLCAiIyBQaW5zIGluIEFWIFJhbmdlIiA9IHBpbmNvdW50LCBjdXJfY29tcF9UQ19yYXRlLCBuZXdfY29tcF9UQ19yYXRlLCBldmVyeXRoaW5nKCkpDQpgYGANCg0KIyMjIEJpbGwgQ2hhbmdlIGZvciB0aG9zZSB0aGF0IGRpZCBjbGFpbSB0aGUgR2VuZXJhbCBIb21lc3RlYWQgRXhlbXB0aW9uDQoNCmBgYHtyfQ0KY2hvc2VuM19zdW1tYXJ5dGFibGUgPC0gY2hvc2VuM19iaWxsY2hhbmdlICU+JSANCiAgZmlsdGVyKGhhc19IT19leGVtcCA9PSAxICYgIWlzLm5hKHJhbmspKSAlPiUNCiAgYXJyYW5nZShjbGVhbl9uYW1lLCByYW5rKSAlPiUNCiAgc2VsZWN0KE11bmljaXBhbGl0eSA9IGNsZWFuX25hbWUsICJBViBQZXJjZW50aWxlIiA9IHJhbmssICJBViIgPSBtZWRpYW5fQVYsICJBdmVyYWdlIEN1cnJlbnQgQmlsbCIgPSBtZWFuX2JpbGxfY3VyLCAiQXZlcmFnZSBOZXcgQmlsbCIgPSBtZWFuX2JpbGxfbmV3LCAiVGF4IEJpbGwgQ2hhbmdlIiA9IG1lYW5fY2hhbmdlLCAiUGVyY2VpdmVkIFNhdmluZ3MiID0gcGVyY2VpdmVkX3NhdmluZ3MsICIjIFBpbnMgaW4gQVYgUmFuZ2UiID0gcGluY291bnQsIGN1cl9jb21wX1RDX3JhdGUsIG5ld19jb21wX1RDX3JhdGUsIGV2ZXJ5dGhpbmcoKSkNCg0KY2hvc2VuM19zdW1tYXJ5dGFibGUNCmBgYA0KDQojIEdyYXBoIHJlcXVlc3RlZCBPY3QgNA0KDQpGb3IgdGhvc2UgdGhhdCBESUQgY2xhaW0gdGhlIGV4ZW1wdGlvbiwgY3JlYXRlIHJhdGlvIG9mOg0KDQoyNXRoIHBlcmNlbnRpbGUgaG9tZSBiaWxsIGNoYW5nZSAvIEFWIDogNzV0aCBwZXJjZW50aWxlIGhvbWUgYmlsbCBjaGFuZ2UvQVYuDQoNCkdyYXBoIHRoZSByYXRpbyBwb2ludHMgZm9yIGFsbCBtdW5pcy4NCg0KYGBge3J9DQpxID0gYyguMjUsIC41LCAuNzUpDQoNCm11bmlfcXVhcnRpbGVzIDwtIHBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKE9wdGlvbjIgPT0gIlNpbmdsZS1GYW1pbHkiKSU+JQ0KICBmaWx0ZXIodGF4X2NvZGUgJWluJSBtdW5pX1RDX2Z1bGx5Q29vayR0YXhfY29kZV9udW0pICU+JQ0KICBncm91cF9ieShhZ2VuY3lfbmFtZSApICU+JQ0KICBhcnJhbmdlKGF2KSAlPiUNCiAgc3VtbWFyaXplKGNvdW50X3BpbnMgPSBuKCksIA0KICAgICAgICAgICAgbWluID0gbWluKGF2KSwNCiAgICAgICAgICAgIHF1YW50MjUgPSByb3VuZChxdWFudGlsZShhdiwgcHJvYnMgPSBxWzFdKSksIA0KICAgICAgICAgICAgcXVhbnQ1MCA9IHJvdW5kKHF1YW50aWxlKGF2LCBwcm9icyA9IHFbMl0pKSwNCiAgICAgICAgICAgIHF1YW50NzUgPSByb3VuZChxdWFudGlsZShhdiwgcHJvYnMgPSBxWzNdKSksDQogICAgICAgICAgICBtYXggPSBtYXgoYXYpKSAlPiUgDQogIGFycmFuZ2UoIGRlc2MoIHF1YW50NTApKSAlPiUNCiAgICBsZWZ0X2pvaW4obmlja25hbWVzKQ0KDQoNCg0KbXVuaXNfcmFua2VkIDwtIHBpbl9kYXRhMiAlPiUNCiAgZmlsdGVyKHRheF9jb2RlICVpbiUgbXVuaV9UQ19mdWxseUNvb2skdGF4X2NvZGVfbnVtKSAlPiUNCiAgaW5uZXJfam9pbihtdW5pX3F1YXJ0aWxlcywgYnkgPSAiYWdlbmN5X25hbWUiKSAlPiUNCiAgbXV0YXRlKHJhbmsgPSBjYXNlX3doZW4oDQogICAgYXYgPiAocXVhbnQyNS01MDApICYgKGF2PHF1YW50MjUrNTAwKSB+ICJxMjUiLA0KICAgIGF2ID4gKHF1YW50NTAtNTAwKSAmIChhdjxxdWFudDUwKzUwMCkgfiAicTUwIiwNCiAgICBhdiA+IChxdWFudDc1LTUwMCkgJiAoYXY8cXVhbnQ3NSs1MDApIH4gInE3NSIpKSAlPiUNCiAgc2VsZWN0KGNsZWFuX25hbWUsIHJhbmssIGF2LCBwaW4sIGNsYXNzLCBldmVyeXRoaW5nKCkpDQoNCg0KYGBgDQoNCg0KYGBge3IgcGluLWNoZWNrLXBsdXNtaW51cy0xMDAwLCBpbmNsdWRlID0gRkFMU0V9DQoNCm11bmlzX3JhbmtlZF9waW5jaGVjayA8LSBwaW5fZGF0YTIgJT4lDQogIGlubmVyX2pvaW4obXVuaV9xdWFydGlsZXMsIGJ5ID0gImFnZW5jeV9uYW1lIikgJT4lDQogIGZpbHRlcih0YXhfY29kZSAlaW4lIG11bmlfVENfZnVsbHlDb29rJHRheF9jb2RlX251bSkgJT4lDQoNCiAgbXV0YXRlKHJhbmsgPSBjYXNlX3doZW4oDQogICAgYXYgPiAocXVhbnQyNS0xMDAwKSAmIChhdjxxdWFudDI1KzEwMDApIH4gInEyNSIsDQogICAgYXYgPiAocXVhbnQ1MC0xMDAwKSAmIChhdjxxdWFudDUwKzEwMDApIH4gInE1MCIsDQogICAgYXYgPiAocXVhbnQ3NS0xMDAwKSAmIChhdjxxdWFudDc1KzEwMDApIH4gInE3NSIpKSAlPiUNCiAgc2VsZWN0KGNsZWFuX25hbWUsIHJhbmssIGF2LCBwaW4sIGNsYXNzLCBldmVyeXRoaW5nKCkpDQoNCg0KbXVuaXNfYmlsbGNoYW5nZV8xMDAwIDwtICBtdW5pc19yYW5rZWRfcGluY2hlY2sgICU+JSANCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSwgcmFuaykgJT4lDQogIGFycmFuZ2UoYXYpICU+JQ0KICMgZ3JvdXBfYnkoYWdlbmN5X25hbWUsIGhhc19IT19leGVtcCkgJT4lIA0KICBtdXRhdGUoI3RheGFibGVfZWF2ID0gZmluYWxfdGF4X3RvX2Rpc3QgLyB0YXhfY29kZV9yYXRlLA0KICAgICMgY3VycmVudCBiaWxsID0gY3VycmVudCB0YXggcmF0ZSAqIHBvcnRpb24gb2YgbGV2eSBiaWxsZWQNCiAgICAgICAgIGJpbGxfY3VycmVudCA9IChmaW5hbF90YXhfdG9fZGlzdCArIGZpbmFsX3RheF90b190aWYpLA0KICAgICAgICAgYmlsbF9ub2V4ZW1wcyA9ICBuZXdfY29tcF9UQ19yYXRlLzEwMCooZXF1YWxpemVkX0FWLWFsbF9leGVtcHRpb25zK2V4ZV9ob21lb3duZXIpLA0KICAgICAgICAgYmlsbF9jaGFuZ2UgPSBiaWxsX25vZXhlbXBzIC0gYmlsbF9jdXJyZW50KSAlPiUNCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSwgcmFuaywgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIHN1bW1hcml6ZShtZWRpYW5fQVYgPSByb3VuZChtZWRpYW4oYXYpKSwNCiAgICAgICAgICAgIG1lZGlhbl9FQVYgPSByb3VuZChtZWRpYW4oZWF2KSksDQogICAgICAgICAgICAjIG1lZGlhbl9iaWxsX2N1ciA9IG1lZGlhbihiaWxsX2N1cnJlbnQpLA0KICAgICAgICAgICAgIyBtZWRpYW5fYmlsbF9uZXcgPSBtZWRpYW4oYmlsbF9ub2V4ZW1wcyksDQogICAgICAgICAgICAjIG1lZGlhbl9jaGFuZ2UgPSBtZWRpYW4oYmlsbF9jaGFuZ2UpLA0KICAgICAgICAgICAgbWVhbl9iaWxsX2N1ciA9IHJvdW5kKG1lYW4oYmlsbF9jdXJyZW50LCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2JpbGxfbmV3ID0gcm91bmQobWVhbihiaWxsX25vZXhlbXBzLCBuYS5ybT1UUlVFKSksDQogICAgICAgICAgICBtZWFuX2NoYW5nZSA9IHJvdW5kKG1lYW4oYmlsbF9jaGFuZ2UsIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIHBlcmNlaXZlZF9zYXZpbmdzID0gbWVkaWFuKHRheF9hbXRfZXhlKSwNCiAgICAgICAgICAgIGN1cl9jb21wX1RDX3JhdGUgPSByb3VuZChtZWFuKGN1cl9jb21wX1RDX3JhdGUpLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIG5ld19jb21wX1RDX3JhdGUgPSByb3VuZChtZWFuKG5ld19jb21wX1RDX3JhdGUpLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIHBpbmNvdW50PW4oKQ0KKSAlPiUNCiAgYXJyYW5nZShoYXNfSE9fZXhlbXAsIHJhbmspDQpgYGANCg0KDQpgYGB7cn0NCm11bmlzX2JpbGxjaGFuZ2UgPC0gIG11bmlzX3JhbmtlZCAgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lLCByYW5rKSAlPiUNCiAgYXJyYW5nZShhdikgJT4lDQogIyBncm91cF9ieShhZ2VuY3lfbmFtZSwgaGFzX0hPX2V4ZW1wKSAlPiUgDQogIG11dGF0ZSgjdGF4YWJsZV9lYXYgPSBmaW5hbF90YXhfdG9fZGlzdCAvIHRheF9jb2RlX3JhdGUsDQogICAgIyBjdXJyZW50IGJpbGwgPSBjdXJyZW50IHRheCByYXRlICogcG9ydGlvbiBvZiBsZXZ5IGJpbGxlZA0KICAgICAgICAgYmlsbF9jdXJyZW50ID0gKGZpbmFsX3RheF90b19kaXN0ICsgZmluYWxfdGF4X3RvX3RpZiksDQogICAgICAgICBiaWxsX25vZXhlbXBzID0gIG5ld19jb21wX1RDX3JhdGUvMTAwKihlcXVhbGl6ZWRfQVYtYWxsX2V4ZW1wdGlvbnMrZXhlX2hvbWVvd25lciksDQogICAgICAgICBiaWxsX2NoYW5nZSA9IGJpbGxfbm9leGVtcHMgLSBiaWxsX2N1cnJlbnQpICU+JQ0KICBncm91cF9ieShjbGVhbl9uYW1lLCByYW5rLCBoYXNfSE9fZXhlbXApICU+JSANCiAgc3VtbWFyaXplKG1lZGlhbl9BViA9IHJvdW5kKG1lZGlhbihhdikpLA0KICAgICAgICAgICAgbWVkaWFuX0VBViA9IHJvdW5kKG1lZGlhbihlYXYpKSwNCiAgICAgICAgICAgICMgbWVkaWFuX2JpbGxfY3VyID0gbWVkaWFuKGJpbGxfY3VycmVudCksDQogICAgICAgICAgICAjIG1lZGlhbl9iaWxsX25ldyA9IG1lZGlhbihiaWxsX25vZXhlbXBzKSwNCiAgICAgICAgICAgICMgbWVkaWFuX2NoYW5nZSA9IG1lZGlhbihiaWxsX2NoYW5nZSksDQogICAgICAgICAgICBtZWFuX2JpbGxfY3VyID0gcm91bmQobWVhbihiaWxsX2N1cnJlbnQsIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIG1lYW5fYmlsbF9uZXcgPSByb3VuZChtZWFuKGJpbGxfbm9leGVtcHMsIG5hLnJtPVRSVUUpKSwNCiAgICAgICAgICAgIG1lYW5fY2hhbmdlID0gcm91bmQobWVhbihiaWxsX2NoYW5nZSwgbmEucm09VFJVRSkpLA0KICAgICAgICAgICAgcGVyY2VpdmVkX3NhdmluZ3MgPSBtZWRpYW4odGF4X2FtdF9leGUpLA0KICAgICAgICAgICAgY3VyX2NvbXBfVENfcmF0ZSA9IHJvdW5kKG1lYW4oY3VyX2NvbXBfVENfcmF0ZSksIGRpZ2l0cyA9IDIpLA0KICAgICAgICAgICAgbmV3X2NvbXBfVENfcmF0ZSA9IHJvdW5kKG1lYW4obmV3X2NvbXBfVENfcmF0ZSksIGRpZ2l0cyA9IDIpLA0KICAgICAgICAgICAgcGluY291bnQ9bigpDQopICU+JQ0KICBhcnJhbmdlKGhhc19IT19leGVtcCwgcmFuaykNCg0KbXVuaXNfYmlsbGNoYW5nZSA8LSBtdW5pc19iaWxsY2hhbmdlICU+JSBsZWZ0X2pvaW4obXVuaV9xdWFydGlsZXMpDQoNCnJhdGlvczwtIG11bmlzX2JpbGxjaGFuZ2UgJT4lIA0KICBmaWx0ZXIoaGFzX0hPX2V4ZW1wID09IDEgJiAgIWlzLm5hKHJhbmspKSAlPiUgIyBjbGFpbWVkIGV4ZW1wdGlvbiBpbiAyMDIxDQogIG11dGF0ZShiaWxsY2hhbmdlX3RvX0FWXzI1ID0gaWZlbHNlKHJhbmsgPT0gInEyNSIsIG1lYW5fY2hhbmdlL21lZGlhbl9BViwgTkEpKSAlPiUNCiAgbXV0YXRlKGJpbGxjaGFuZ2VfdG9fQVZfNzUgPSBpZmVsc2UocmFuayA9PSAicTc1IiwgbWVhbl9jaGFuZ2UvbWVkaWFuX0FWLCBOQSkpICU+JSANCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSkgJT4lDQogIHN1bW1hcml6ZShiaWxsY2hhbmdlX3RvX0FWXzI1ID0gbWF4KGJpbGxjaGFuZ2VfdG9fQVZfMjUsIG5hLnJtPVRSVUUpLA0KICAgICAgICAgICAgYmlsbGNoYW5nZV90b19BVl83NSA9IG1heChiaWxsY2hhbmdlX3RvX0FWXzc1LCBuYS5ybT1UUlVFKSkgJT4lDQogIG11dGF0ZShtdW5pX3JhdGlvXzI1dG83NSA9IGJpbGxjaGFuZ2VfdG9fQVZfMjUvYmlsbGNoYW5nZV90b19BVl83NSkNCg0KcmF0aW9zDQpgYGANCmBiaWxsY2hhbmdlX3RvX0FWXzI1YCBpcyB0aGUgYW1vdW50IHRoZSB0YXggYmlsbCBjaGFuZ2VkIGZvciBwcm9wZXJ0aWVzIGF0IHRoZSBtdW5pY2lwYWxpdHkncyAyNXRoIHBlcmNlbnRpbGUgKGJhc2VkIG9uIEFzc2Vzc2VkIFZhbHVlKSBkaXZpZGVkIGJ5IHRoZSBBc3Nlc3NlZCBWYWx1ZSBvZiB0aGF0IHByb3BlcnR5LiBUaGUgbGFyZ2VyIHRoZSBkZWNpbWFsLCB0aGUgbW9yZSBpbXBhY3QgYSBiaWxsIHJlZHVjdGlvbiB3b3VsZCBoYXZlIChjaGFuZ2UgaW4gcHJvcGVydHkgdGF4IGJpbGwgYXMgYSBwcm9wb3J0aW9uIG9mIHRoZSBwcm94eSBmb3IgYW4gb3duZXIncyAid2VhbHRoIikuDQoNCg0KDQpgYmlsbGNoYW5nZV90b19BVl83NWAgaXMgdGhlIGFtb3VudCB0aGF0IGEgcHJvcGVydHkgdGF4IGJpbGwgY2hhbmdlZCBmcm9tIHRoZSByZW1vdmFsIG9mIHRoZSBnZW5lcmFsIGhvbWVvd25lciBleGVtcHRpb24gLyB0aGUgQVYgb2YgdGhhdCBwcm9wZXJ0eS4gDQoNCg0KTXVuaWNpcGFsaXRpZXMgd2l0aCBoaWdoIHJhdGlvcyB3aWxsIGhhdmUgaGlnaCBjb21wb3NpdGUgdGF4IHJhdGVzLiBIb3dldmVyIHRoZSBmdXJ0aGVyIHRoZSBkb3QgaXMgZnJvbSB0aGUgbT0xIHNsb3BlZCBsaW5lLCB0aGUgbW9yZSBpbXBhY3RmdWwgZXhlbXB0aW9ucyBhcmUuIA0KDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSByYXRpb3MsIGFlcyh5ID0gYmlsbGNoYW5nZV90b19BVl8yNSwgeCA9IGJpbGxjaGFuZ2VfdG9fQVZfNzUsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDMsIG51ZGdlX3k9MC4wMSwgc2l6ZSA9IDMsIGNoZWNrX292ZXJsYXAgPSBUUlVFKSsgDQogIHRoZW1lX2NsYXNzaWMoKSArIA0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCnJhdGlvcyAlPiUgDQogIGZpbHRlcihiaWxsY2hhbmdlX3RvX0FWXzI1PC4zKSAlPiUNCmdncGxvdChhZXMoeSA9IGJpbGxjaGFuZ2VfdG9fQVZfMjUsIHggPSBiaWxsY2hhbmdlX3RvX0FWXzc1LCBsYWJlbCA9IGNsZWFuX25hbWUpKSArIA0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsNCiAgZ2VvbV9wb2ludChhZXMoYWxwaGEgPSAuNSkpICsgDQogIGdlb21fdGV4dChudWRnZV94ID0gLjAzLCBudWRnZV95PTAuMDEsIHNpemUgPSAzLCBjaGVja19vdmVybGFwID0gVFJVRSkrIA0KICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQoNCnJhdGlvcyAlPiUgDQogIGZpbHRlcihiaWxsY2hhbmdlX3RvX0FWXzI1PC4xKSAlPiUNCmdncGxvdChhZXMoeSA9IGJpbGxjaGFuZ2VfdG9fQVZfMjUsIHggPSBiaWxsY2hhbmdlX3RvX0FWXzc1LCBsYWJlbCA9IGNsZWFuX25hbWUpKSArIA0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsNCiAgZ2VvbV9wb2ludChhZXMoYWxwaGEgPSAuNSkpICsgDQogIGdlb21fdGV4dChudWRnZV94ID0gLjAzLCBudWRnZV95PTAuMDEsIHNpemUgPSAzLCBjaGVja19vdmVybGFwID0gVFJVRSkrIA0KICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQpyYXRpb3MgJT4lIA0KICBmaWx0ZXIoYmlsbGNoYW5nZV90b19BVl8yNTwuMSkgJT4lDQpnZ3Bsb3QoYWVzKHkgPSBiaWxsY2hhbmdlX3RvX0FWXzI1LCB4ID0gYmlsbGNoYW5nZV90b19BVl83NSwgbGFiZWwgPSBjbGVhbl9uYW1lKSkgKyANCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArDQogIGdlb21fcG9pbnQoYWVzKGFscGhhID0gLjUpKSArIA0KICBnZW9tX3RleHQobnVkZ2VfeCA9IC4wMywgbnVkZ2VfeT0wLjAxLCBzaXplID0gMywgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KDQojIyBDdXJyZW50IEJpbGwgLyBBViBncmFwaHMNCg0KVGhlIHByb3BlcnR5IHRheCBiaWxsIGRpdmlkZWQgYnkgdGhlIGFzc2Vzc2VkIHZhbHVlIGlzIGp1c3QgdGhlIHRheCBjb21wb3NpdGUgdGF4IHJhdGUgZm9yIHRoZSBtdW5pY2lwYWxpdHkuDQoNCg0KYGBge3J9DQoNCnJhdGlvczwtIG11bmlzX2JpbGxjaGFuZ2UgJT4lIA0KICBmaWx0ZXIoaGFzX0hPX2V4ZW1wID09IDEgJiAgIWlzLm5hKHJhbmspKSAlPiUgIyBjbGFpbWVkIGV4ZW1wdGlvbiBpbiAyMDIxDQogIG11dGF0ZShjdXJyYmlsbF90b19BVl8yNSA9IGlmZWxzZShyYW5rID09ICJxMjUiLCBtZWFuX2JpbGxfY3VyL21lZGlhbl9BViwgTkEpKSAlPiUNCiAgbXV0YXRlKGN1cnJiaWxsX3RvX0FWXzc1ID0gaWZlbHNlKHJhbmsgPT0gInE3NSIsIG1lYW5fYmlsbF9jdXIvbWVkaWFuX0FWLCBOQSkpICU+JSANCiAgZ3JvdXBfYnkoY2xlYW5fbmFtZSkgJT4lDQogIHN1bW1hcml6ZShjdXJyYmlsbF90b19BVl8yNSA9IG1heChjdXJyYmlsbF90b19BVl8yNSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBjdXJyYmlsbF90b19BVl83NSA9IG1heChjdXJyYmlsbF90b19BVl83NSwgbmEucm09VFJVRSkpICU+JQ0KICBtdXRhdGUobXVuaV9yYXRpb18yNXRvNzUgPSBjdXJyYmlsbF90b19BVl8yNS9jdXJyYmlsbF90b19BVl83NSkNCg0KDQpnZ3Bsb3QoZGF0YSA9IHJhdGlvcywgYWVzKHkgPSBjdXJyYmlsbF90b19BVl8yNSwgeCA9IGN1cnJiaWxsX3RvX0FWXzc1LCBsYWJlbCA9IGNsZWFuX25hbWUpKSArIA0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsNCiAgZ2VvbV9wb2ludChhZXMoYWxwaGEgPSAuNSkpICsgDQogIGdlb21fdGV4dChudWRnZV94ID0gLjAzLCBudWRnZV95PTAuMDEsIHNpemUgPSAzLCBjaGVja19vdmVybGFwID0gVFJVRSkrIA0KICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIC42KSkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KICANCg0KcmF0aW9zICU+JSBmaWx0ZXIoY3VycmJpbGxfdG9fQVZfMjU8LjMpICU+JQ0KICBnZ3Bsb3QoYWVzKHkgPSBjdXJyYmlsbF90b19BVl8yNSwgeCA9IGN1cnJiaWxsX3RvX0FWXzc1LCBsYWJlbCA9IGNsZWFuX25hbWUpKSArIA0KICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsNCiAgZ2VvbV9wb2ludChhZXMoYWxwaGEgPSAuNSkpICsgDQogIGdlb21fdGV4dChudWRnZV94ID0gLjAyLCBudWRnZV95PTAuMCwgc2l6ZSA9IDIuNCwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KDQpyYXRpb3MgJT4lIGZpbHRlcihjdXJyYmlsbF90b19BVl8yNTwuMikgJT4lDQogIGdncGxvdChhZXMoeSA9IGN1cnJiaWxsX3RvX0FWXzI1LCB4ID0gY3VycmJpbGxfdG9fQVZfNzUsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDIsIG51ZGdlX3k9MC4wMCwgc2l6ZSA9IDIuNCwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0KDQojIyBIeXBvdGhldGljYWwgQmlsbCBhZnRlciByZW1vdmluZyBHSEUNCg0KYGBge3J9DQoNCm5ld19yYXRpb3M8LSBtdW5pc19iaWxsY2hhbmdlICU+JSANCiAgZmlsdGVyKGhhc19IT19leGVtcCA9PSAxICYgICFpcy5uYShyYW5rKSkgJT4lICMgY2xhaW1lZCBleGVtcHRpb24gaW4gMjAyMQ0KICBtdXRhdGUobmV3YmlsbF90b19BVl8yNSA9IGlmZWxzZShyYW5rID09ICJxMjUiLCBtZWFuX2JpbGxfbmV3L21lZGlhbl9BViwgTkEpKSAlPiUNCiAgbXV0YXRlKG5ld2JpbGxfdG9fQVZfNzUgPSBpZmVsc2UocmFuayA9PSAicTc1IiwgbWVhbl9iaWxsX25ldy9tZWRpYW5fQVYsIE5BKSkgJT4lIA0KICBncm91cF9ieShjbGVhbl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKG5ld2JpbGxfdG9fQVZfMjUgPSBtYXgobmV3YmlsbF90b19BVl8yNSwgbmEucm09VFJVRSksDQogICAgICAgICAgICBuZXdiaWxsX3RvX0FWXzc1ID0gbWF4KG5ld2JpbGxfdG9fQVZfNzUsIG5hLnJtPVRSVUUpKSAlPiUNCiAgbXV0YXRlKG11bmlfcmF0aW9fMjV0bzc1ID0gbmV3YmlsbF90b19BVl8yNS9uZXdiaWxsX3RvX0FWXzc1KQ0KDQoNCmdncGxvdChkYXRhID0gbmV3X3JhdGlvcywgYWVzKHkgPSBuZXdiaWxsX3RvX0FWXzI1LCB4ID0gbmV3YmlsbF90b19BVl83NSwgbGFiZWwgPSBjbGVhbl9uYW1lKSkgKyANCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArDQogIGdlb21fcG9pbnQoYWVzKGFscGhhID0gLjUpKSArIA0KICBnZW9tX3RleHQobnVkZ2VfeCA9IC4wMywgbnVkZ2VfeT0wLjAxLCBzaXplID0gMywgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgLjYpKSsNCg0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAuNikpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCiAgDQoNCm5ld19yYXRpb3MgJT4lIGZpbHRlcihuZXdiaWxsX3RvX0FWXzI1PC4zKSAlPiUNCiAgZ2dwbG90KGFlcyh5ID0gbmV3YmlsbF90b19BVl8yNSwgeCA9IG5ld2JpbGxfdG9fQVZfNzUsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDIsIG51ZGdlX3k9MC4wLCBzaXplID0gMi40LCBjaGVja19vdmVybGFwID0gVFJVRSkrIA0KICB0aGVtZV9jbGFzc2ljKCkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KDQoNCm5ld19yYXRpb3MgJT4lIGZpbHRlcihuZXdiaWxsX3RvX0FWXzI1PC4yKSAlPiUNCiAgZ2dwbG90KGFlcyh5ID0gbmV3YmlsbF90b19BVl8yNSwgeCA9IG5ld2JpbGxfdG9fQVZfNzUsIGxhYmVsID0gY2xlYW5fbmFtZSkpICsgDQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKw0KICBnZW9tX3BvaW50KGFlcyhhbHBoYSA9IC41KSkgKyANCiAgZ2VvbV90ZXh0KG51ZGdlX3ggPSAuMDIsIG51ZGdlX3k9MC4wMCwgc2l6ZSA9IDIuNCwgY2hlY2tfb3ZlcmxhcCA9IFRSVUUpKyANCiAgdGhlbWVfY2xhc3NpYygpICsgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCmBgYA0K