Tasks

1. Debt over time

scf.2016.stats.2 <- scf.2016 %>%
  group_by(YEAR) %>%
  summarise_at(vars(PIRMORT, PIRTOTAL, DEBT2INC, LEVRATIO), list(mean = mean, median = median, total = sum)) 
p1 <- ggplot(data = scf.2016.stats.2, aes(x = YEAR)) +
  geom_smooth(aes(y = LEVRATIO_median, color = "Median debt to assets")) +
  geom_smooth(aes(y = DEBT2INC_median, color = "Median debt to income"))
p1 +
  theme_wsj() +
  scale_color_jcolors(palette = "pal6") +
  scale_x_continuous(breaks=seq(1990, 2015, 5)) +
  labs(caption = "Source: 2016 Survey of Consumer Finances (SCF)") +
  theme(plot.caption = element_text(size = 8),
        plot.title = element_text(size=18),
        legend.title=element_blank(),
        panel.background = element_rect(fill = NA),
        panel.ontop = TRUE) +
  ggtitle("Median ratio of debt to assets and income")

Plot 1 is a fitted curve of the median debt-to-income ratio and the debt-to-assets ratio over time. Both ratios are for all debt, not only student loan debt, which shows the historical changes to household debt as a whole. The debt-to-income ratio grew until the 2008 recession, and has been shrinking since then. However the debt-to-assets ratio has grown steadily over the same time, somewhat flattening in recent years.

scf.2016.stats.8 <- scf.2016 %>%
  group_by(YEAR) %>%
  summarise_at(vars(NH_MORT, CCBAL, EDN_INST, VEH_INST, OTHLOC), list(mean = mean)) %>%
  gather(NH_MORT_mean:OTHLOC_mean, key = "type", value = "mean") %>%
  arrange(type, YEAR)
scf.2016.stats.9 <- scf.2016.stats.8 %>%
  mutate(type = case_when(type == "NH_MORT_mean" ~ "Mortgage", 
                          type == "CCBAL_mean" ~ "Credit card", 
                          type == "EDN_INST_mean" ~ "Student loan", 
                          type == "VEH_INST_mean" ~ "Car payment", 
                          type == "OTHLOC_mean" ~ "Other"))
p2 <- ggplot(scf.2016.stats.9, aes(x = YEAR, 
                             y = mean,
                             fill = fct_reorder(type, mean))) + 
  geom_area() 
p2i <- p2 +
  theme_wsj() +
  scale_fill_viridis_d() +
  scale_x_continuous(breaks=seq(1990, 2015, 5)) +
  scale_y_continuous(labels = dollar) +
  labs(caption = "Source: 2016 Survey of Consumer Finances (SCF)") +
  theme(plot.caption = element_text(size = 8),
        plot.title = element_text(size = 18),
        legend.title = element_blank(),
        panel.background = element_rect(fill = NA),
        panel.ontop = TRUE) +
  ggtitle("Average household debt")
p2i

Plot 2 is a stacked area chart of average debt over time, color-coded for type of debt. This allows comparison between different types of debt, both in raw numbers and proportionally. For instance, although the average household debt has decreased since 2008, student loans grew in both raw numbers and as a proportion of the total debt, although they still account for only a small fraction of that debt.

I would recommend plot 2 over plot 1, since it is easier for readers to understand dollar values than it is to intrpret ratios, and better highlights the historical patterns of both student debt and debt as a whole.

2. Tell me who you are

scf.2016.only <- filter(scf.2016, YEAR == 2016)
scf.2016.only.2 <- scf.2016.only %>%
  mutate(ed_rat = EDN_INST / DEBT) %>%
  replace_na(list(ed_rat = 0))
scf.2016.only.3 <- scf.2016.only.2 %>%
  mutate(AGECL.cat = as.character(AGECL),
         HHSEX.cat = as.character(HHSEX),
         EDCL.cat = as.character(EDCL),
         FAMSTRUCT.cat = as.character(FAMSTRUCT),
         HOUSECL.cat = as.character(HOUSECL),
         MARRIED.cat = as.character(MARRIED),
         RACE.cat = as.character(RACE))
scf.2016.only.4 <- scf.2016.only.3 %>%
  mutate(KIDS.cat = case_when(
    KIDS > 0 ~ 1,
    TRUE     ~ 0)) %>%
  mutate(KIDS.cat = as.character(KIDS.cat)) %>%
  mutate(gen_kids = case_when(HHSEX.cat == "1" & KIDS.cat == "1" ~ "Man with children", 
                              HHSEX.cat == "1" & KIDS.cat == "0" ~ "Man without children",
                              HHSEX.cat == "2" & KIDS.cat == "1" ~ "Woman with children",
                              HHSEX.cat == "2" & KIDS.cat == "0" ~ "Woman without children")) %>%
  mutate(KIDS.cat.2 = case_when(KIDS.cat == "0" ~ "No children",
                                KIDS.cat == "1" ~ "Children")) %>%
  mutate(HHSEX.cat.2 = case_when(HHSEX.cat == "1" ~ "Men",
                                 HHSEX.cat == "2" ~ "Women"))
scf.2016.only.educ.gen_kids.2 <- scf.2016.only.4 %>%
  group_by(EDUC, KIDS.cat.2, HHSEX.cat.2) %>%
  summarise_at(vars(PIRMORT, PIRTOTAL, DEBT2INC, LEVRATIO, DEBT, EDN_INST, ed_rat), list(mean = mean, median = median, total = sum))
p3 <- ggplot(scf.2016.only.educ.gen_kids.2, aes(x = EDUC, y = EDN_INST_mean, group = KIDS.cat.2, color = KIDS.cat.2)) +
  geom_line(lwd = 1.5) +
  xlim(7, NA) +
  facet_wrap(~HHSEX.cat.2)
p3 +
  theme_wsj() +
  scale_color_jcolors(palette = "pal6") +
  scale_y_continuous(labels = dollar) +
  labs(caption = "Source: 2016 Survey of Consumer Finances (SCF)") +
  xlab("Years of education") +
  theme(axis.title = element_text(size = 14),
        axis.title.y = element_blank(),
        plot.caption = element_text(size = 8),
        plot.title = element_text(size = 18),
        legend.title = element_blank(),
        panel.background = element_rect(fill = NA),
        panel.ontop = TRUE) +
  ggtitle("Average student loan debt")

Plot 3 is a line chart of household debt for 2016 only, comparing the average student loan debt over years of education for heads of household both with and without children, for both men and women. Predictably, student loan debt increases after high school (10 years), and is slightly higher for parents of both genders. However, women’s student debt rises much faster than men’s; the difference is not so apparent at the undergraduate level (12 years), but at the doctoral level women’s debt is more than double men’s.

scf.2016.only.5 <- scf.2016.only.4 %>%
  mutate(MARRIED.cat.2 = case_when(
    MARRIED.cat == "1" ~ "Married", 
    MARRIED.cat == "2" ~ "Single"))
scf.2016.only.educ.gen_marr.2 <- scf.2016.only.5 %>%
  group_by(EDUC, MARRIED.cat.2, HHSEX.cat.2) %>%
  summarise_at(vars(PIRMORT, PIRTOTAL, DEBT2INC, LEVRATIO, DEBT, EDN_INST, ed_rat), list(mean = mean, median = median, total = sum))
p4 <- ggplot(scf.2016.only.educ.gen_marr.2, aes(x = EDUC, y = EDN_INST_mean, group = MARRIED.cat.2, color = MARRIED.cat.2)) +
  geom_smooth(se = FALSE, lwd = 1.5) +
  xlim(7, NA) +
  facet_wrap(~HHSEX.cat.2)
p4 +
  theme_wsj() +
  scale_color_jcolors(palette = "pal6") +
  scale_y_continuous(labels = dollar) +
  labs(caption = "Source: 2016 Survey of Consumer Finances (SCF)") +
  xlab("Years of education") +
  theme(axis.title = element_text(size = 14),
        axis.title.y = element_blank(),
        plot.caption = element_text(size = 8),
        plot.title = element_text(size = 18),
        legend.title = element_blank(),
        panel.background = element_rect(fill = NA),
        panel.ontop = TRUE) +
  ggtitle("Average student debt")

Plot 4 is similar except that is displays a fitted curve instead of a line, and it compares average student debt by marriage, not parenthood. Here the pattern differs by gender. For men, being married increases student debt until the graduate level (13 years), after which is goes down. This suggests that married men’s education is subsidized by their spouses. For women, marriage only increases student loan debt after starting college (9 years), and only drops below the rate for single women at the graduate level (13 years), but only by a smakk margin. Once again, the average student loan debt for women is higher than for men, increasing sharply after the start of college (9 years).

scf.2016.only.7 <- scf.2016.only.5 %>%
  mutate(EDUC_cat = case_when(
    EDUC <= 7  ~ "None", 
    EDUC == 8  ~ "High school",
    EDUC == 9  ~ "High school",
    EDUC == 10 ~ "Associate's",
    EDUC == 11 ~ "Associate's",
    EDUC == 12 ~ "Bachelor's",
    EDUC == 13 ~ "Master's",
    EDUC == 14 ~ "Doctorate",
    TRUE       ~ "other")) %>%
  filter(!(EDUC_cat == "other")) %>%
  mutate(EDUC_fac = factor(EDUC_cat, levels = c("None", "High school", "Associate's", "Bachelor's", "Master's", "Doctorate")))
scf.2016.only.educ_fac <- scf.2016.only.7 %>%
  group_by(EDUC_fac) %>%
  summarise_at(vars(NH_MORT, CCBAL, EDN_INST, VEH_INST, OTHLOC), list(mean = mean)) %>%
  gather(NH_MORT_mean:OTHLOC_mean, key = "type", value = "mean") %>%
  arrange(type, EDUC_fac) %>%
  mutate(type = case_when(type == "NH_MORT_mean" ~ "Mortgage", 
                          type == "CCBAL_mean" ~ "Credit card", 
                          type == "EDN_INST_mean" ~ "Student loan", 
                          type == "VEH_INST_mean" ~ "Car payment", 
                          type == "OTHLOC_mean" ~ "Other"))
p5 <- ggplot(scf.2016.only.educ_fac, aes(fill = fct_reorder(type, mean), y = mean, x = EDUC_fac)) + 
  geom_bar(position="stack", stat="identity")
p5i <- p5 +
  theme_wsj() +
  scale_fill_jcolors(palette = "pal7") +
  scale_y_continuous(labels = dollar) +
  labs(caption = "Source: 2016 Survey of Consumer Finances (SCF)") +
  theme(plot.caption = element_text(size = 8),
        plot.title = element_text(size = 18),
        legend.title = element_blank(),
        panel.background = element_rect(fill = NA),
        panel.ontop = TRUE) +
  ggtitle("Average debt by highest degree earned")
p5i

Plot 5 is a stacked bar chart of average debt for 2016 only by highest degree obtained, color-coded for type of debt. It is similar to the second chart, but groups the debt by categorical level of education instead of by continuous years. Once again this presentation facilitates comparing different types of debt in both raw numbers and proportion. As expected, the average total debt increases with each level of education up to the doctoral level. Debt jumps significantly from a two-year degree to a four-year degree, and again from a bachelor’s degree to a master’s degree, likely due to the average age difference between degree-holders of each type. Interestingly, the amount of student loan debt specifically is the same for both associate’s degrees and bachelor’s dgrees, and again the same for both master’s degrees and PhDs.

I would recommend using plot 5, along either plot 3 or 4. While years of education is a somewhat difficult variable to understand, it is important to highlight demographic patterns.

3. Wealth and income distribution

scf.2016.2 <- scf.2016 %>%
  mutate(mort_rat = NH_MORT / DEBT,
         cred_rat = CCBAL / DEBT,
         ed_rat = EDN_INST / DEBT,
         car_rat = VEH_INST / DEBT) %>%
  replace_na(list(mort_rat = 0,
                  cred_rat = 0,
                  ed_rat = 0,
                  car_rat = 0)) %>%
  mutate(INCCAT.cat = as.character(INCCAT),
         NWCAT.cat = as.character(NWCAT)) %>%
  mutate(INCCAT.cat.2 = case_when(
    INCCAT.cat == "1" ~ "0-19", 
    INCCAT.cat == "2" ~ "20-39",
    INCCAT.cat == "3" ~ "40-59",
    INCCAT.cat == "4" ~ "60-79",
    INCCAT.cat == "5" ~ "80-99",
    INCCAT.cat == "6" ~ "80-9")) %>%
  mutate(INCCAT.cat.2 = factor(INCCAT.cat.2, levels = c("0-19", "20-39", "40-59", "60-79", "80-100"))) %>%
  mutate(NWCAT.cat.2 = case_when(
    NWCAT.cat == "1" ~ "0-25", 
    NWCAT.cat == "2" ~ "25-50",
    NWCAT.cat == "3" ~ "50-75",
    NWCAT.cat == "4" ~ "75-100",
    NWCAT.cat == "5" ~ "75-100")) %>%
  mutate(NWCAT.cat.2 = factor(NWCAT.cat.2, levels = c("0-25", "25-50", "50-75", "75-100")))
scf.2016.2.only <- scf.2016.2 %>%
  filter(YEAR == 2016)
scf.2016.stats.15 <- scf.2016.2.only %>%
  group_by(INCOME) %>%
  summarise_at(vars(DEBT, EDN_INST, ed_rat, DEBT2INC, LEVRATIO), list(mean = mean, median = median, total = sum))
p6 <- ggplot() + 
  geom_smooth(mapping = aes(x = scf.2016.stats.15$INCOME, y = scf.2016.stats.15$EDN_INST_mean), color = "#009E73") +
  geom_smooth(mapping = aes(x = scf.2016.stats.15$INCOME, y = scf.2016.stats.15$DEBT_mean/100), color = "#0072B2") + 
  scale_x_continuous(limits = c(0, 1000000), labels = dollar) +
  scale_y_continuous(name = "Student loans", labels = dollar,
                     sec.axis = sec_axis(~.*100, name = "Total debt", labels = dollar)) + 
  coord_cartesian(ylim = c(0, 7500))
 p6 + 
  theme_wsj() +
  labs(caption = "Source: 2016 Survey of Consumer Finances (SCF)") +
  theme(axis.title = element_text(size = 12),
        axis.title.y = element_text(color = "#009E73"),
        axis.title.y.right = element_text(color = "#0072B2"), 
        axis.title.x = element_blank(),
        plot.caption = element_text(size = 8),
        plot.title = element_text(size = 18),
        legend.title = element_blank(),
        panel.background = element_rect(fill = NA),
        panel.ontop = TRUE) +
  ggtitle("Average debt by income")

Plot 6 is a fitted curve of the student loan debt and total debt averages by income up to $1 million. Because student loan debt is so much smaller than total loan debt, the plot has two y-axes. This makes it possible to see the patterns of both types of debt on the same graph: Student loan debt increases slightly up to around $300,000, after which it decreases sharply, while total debt increases steadily with income, flattening briefly around $500,000.

scf.2016.stats.18 <- scf.2016.2.only %>%
  group_by(NETWORTH) %>%
  summarise_at(vars(DEBT, EDN_INST, ed_rat, DEBT2INC, LEVRATIO), list(mean = mean, median = median, total = sum))
p7 <- ggplot() + 
  geom_smooth(mapping = aes(x = scf.2016.stats.18$NETWORTH, y = scf.2016.stats.18$EDN_INST_mean), color = "#009E73") +
  geom_smooth(mapping = aes(x = scf.2016.stats.18$NETWORTH, y = scf.2016.stats.18$DEBT_mean/20), color = "#0072B2") + 
  scale_x_continuous(limits = c(0, 1000000), labels = dollar) +
  scale_y_continuous(name = "Student loans", labels = dollar,
                     sec.axis = sec_axis(~.*20, name = "Total debt", labels = dollar)) + 
  coord_cartesian(ylim = c(0, 10000))
p7 +
  theme_wsj() +
  labs(caption = "Source: 2016 Survey of Consumer Finances (SCF)") +
  theme(axis.title = element_text(size = 12),
        axis.title.y = element_text(color = "#009E73"),
        axis.title.y.right = element_text(color = "#0072B2"), 
        axis.title.x = element_blank(),
        plot.caption = element_text(size = 8),
        plot.title = element_text(size = 18),
        legend.title = element_blank(),
        panel.background = element_rect(fill = NA),
        panel.ontop = TRUE) +
  ggtitle("Average debt by net worth")

Plot 7 is similar to plot 6, only the x-axis is for net worth. By this measure, student loan debt follows a more nuanced pattern, with sveral local maxima and minima, but generally increasing exponentially up to $200,000, after which it decreases until $750,000. By contrast, total debt increases logarithmically as it approaches the $1 million cutoff, with only a slight dip around $500,000.

I recommend using plot 6, although the double axes might not be immediately clear to readers. I would only recommend using plot 7 as a comparison to plot 6, and not on its own, since the relationship of debt to net worth is also more difficult to interpret.

4. Going broke

scf.2016.bank <- filter(scf.2016.2, BNKRUPLAST5 == 1)
scf.2016.bank.stats <- scf.2016.bank %>%
  group_by(YEAR) %>%
  summarise_at(vars(PIRMORT, PIRTOTAL, DEBT2INC, LEVRATIO, DEBT, EDN_INST), list(mean = mean, median = median, total = sum))
p8 <- ggplot(scf.2016.bank.stats, aes(x = YEAR)) +
  geom_smooth(se = FALSE, aes(y = DEBT_mean, color = "Total debt")) + 
  geom_smooth(se = FALSE, aes(y = EDN_INST_mean, color="Student loans"))
p8 + 
  theme_wsj() +
  scale_color_jcolors(palette = "pal6") +
  scale_x_continuous(breaks=seq(1990, 2015, 5)) +
  scale_y_continuous(labels = dollar) +
  labs(caption = "Source: 2016 Survey of Consumer Finances (SCF)") +
  theme(plot.caption = element_text(size = 8),
        plot.title = element_text(size=18),
        legend.title=element_blank(),
        panel.background = element_rect(fill = NA),
        panel.ontop = TRUE) +
  ggtitle("Average debt in households \nwith a recent bankruptcy")

Plot 8 is a fitted curve of mean student loan debt and total debt over time for households that had a bankruptcy in the past 5 years. It shows that while the average total debt for recently bankrupt households has gone up and down over the years, the average student loan debt for these households has steadily increased.

scf.2016.bank.stats.2 <- scf.2016.bank %>%
  group_by(YEAR) %>%
  summarise_at(vars(NH_MORT, CCBAL, EDN_INST, VEH_INST, OTHLOC), list(mean = mean)) %>%
  gather(NH_MORT_mean:OTHLOC_mean, key = "type", value = "mean") %>%
  arrange(type, YEAR) %>%
  mutate(type = case_when(type == "NH_MORT_mean" ~ "Mortgage", 
                          type == "CCBAL_mean" ~ "Credit card", 
                          type == "EDN_INST_mean" ~ "Student loan", 
                          type == "VEH_INST_mean" ~ "Car payment", 
                          type == "OTHLOC_mean" ~ "Other"))
p9 <- ggplot(scf.2016.bank.stats.2, aes(x = YEAR, 
                             y = mean,
                             fill = fct_reorder(type, mean))) + 
    geom_area()
p9 +
  theme_wsj() +
  scale_fill_viridis_d() +
  scale_x_continuous(breaks=seq(1990, 2015, 5)) +
  scale_y_continuous(labels = dollar) +
  labs(caption = "Source: 2016 Survey of Consumer Finances (SCF)") +
  theme(plot.caption = element_text(size = 8),
        plot.title = element_text(size = 18),
        legend.title = element_blank(),
        panel.background = element_rect(fill = NA),
        panel.ontop = TRUE) +
  ggtitle("Average debt in households \nwith a recent bankruptcy")

Plot 9 is a stacked area chart of average debt over time for households that had a bankruptcy in the past 5 years, color-coded for type of debt. It is the same as plot 2, but only for those households with recent bankruptcies. Once again this allows for easy comparison between different types of debt. In this case, while the average debt of recently bankrupt households has flatlined since 2010, their average student loan debt has steadily increased.

scf.2016.bank.2 <- scf.2016.2 %>%
  mutate(bank.cat = case_when(BNKRUPLAST5 == 0 ~ "No recent bankruptcy", 
                              BNKRUPLAST5 == 1 ~ "Recent bankruptcy",
                              TRUE             ~ "unknown")) %>%
  filter(!(bank.cat == "unknown")) %>%
  mutate(food_all = (FOODHOME + FOODDELV + FOODAWAY)) %>%
  mutate(FOODDELV.pct = (FOODDELV/food_all)) %>%
  mutate(FOODAWAY.pct = (FOODAWAY/food_all)) %>%
  rationalize() %>%
  replace_na(list(FOODDELV.pct = 0,
                  FOODAWAY.pct = 0))
scf.2016.bank.stats.7 <- scf.2016.bank.2 %>%
  group_by(YEAR, bank.cat) %>%
  summarise_at(vars(FOODDELV.pct, FOODAWAY.pct), list(mean = mean, median = median, total = sum))
p10 <- ggplot(scf.2016.bank.stats.7, aes(x = YEAR, y = FOODDELV.pct_mean, group = bank.cat, color = bank.cat)) + 
  geom_line(lwd = 1.5) +
  xlim(2004, NA)
p10 +
  theme_wsj() +
  scale_color_jcolors(palette = "pal6") +
  scale_y_continuous(labels = percent) +
  labs(caption = "Source: 2016 Survey of Consumer Finances (SCF)") +
  theme(plot.caption = element_text(size = 8),
        plot.title = element_text(size = 18),
        legend.title = element_blank(),
        panel.background = element_rect(fill = NA),
        panel.ontop = TRUE) +
  ggtitle("Food budget spent on delivery")

As requested, my final static plot concerns food spending and bankruptcies. Plot 10 is a line chart showing the percentage of the average food budget spent on delivery for both households that recently experienced bankruptcy and those that did not. While recently bankrupt households did have a small spike of delivery spending in 2007, it has been decreasing overall since then. For non-bankrupt households, it has also been decreasing steadily, with a small uptick in 2016. It is important to note that this data is only available starting in 2004, and as such there is not enough data to calculate a reliable fitted line or curve. In addition, all of these changes are with 1% and 3% of the total food budget.

I would recommend against using plot 10, and also recommend using plot 9 over plot 8. Plot 9 conveys a great deal of information clearly and efficiently, especially if displayed alongside plot 2 to highlight the differences in debt composition between and bankrupt-only households and households in general. However, in the absence of a deeper discussion on bankruptcy, plot 8 should suffice.

Interactivity

5. Make two plots interactive

ggplotly(p2i)
ggplotly(p5i)

Plots 2 and 5 would benefit from interactive online versions, since stacked plots can be difficult to interpret. Being able to hover over each type of debt for a given year or category would allow readers to further explore the data and reliably compare values that do not begin at the same point on the y-axis.

6. Data Table

scf.2016.stats.9.p <- scf.2016 %>%
  group_by(YEAR) %>%
  summarise_at(vars(DEBT, NH_MORT, CCBAL, EDN_INST, VEH_INST, OTHLOC), list(mean = mean)) %>%
  rename("All debt mean" = "DEBT_mean",
         "Mortgage mean" = "NH_MORT_mean",
         "Credit card mean" = "CCBAL_mean",
         "Student loan mean" = "EDN_INST_mean",
         "Car payment mean" = "VEH_INST_mean",
         "Other debt mean" = "OTHLOC_mean")
datatable(scf.2016.stats.9.p)

This table shows the data used for plot 2, the mean values of all debt types for each year of the survey. Presenting the data in this way would allow readers to order the data by each data type, to see which years had the highest and lowest average student loan debt, for instance, compared to other types of debt.

LS0tCnRpdGxlOiAiSG9tZXdvcmsgMTogU3R1ZGVudCBMb2FucyIKYXV0aG9yOiAiQWxpc29uIFJ5bGFuZCIKZGF0ZTogIkZlYnJ1YXJ5IDI1LCAyMDIwIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyIFNldHVwLCBpbmNsdWRlPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgd2FybmluZz1GQUxTRX0KbGlicmFyeShrbml0cikKCm9wdHNfY2h1bmskc2V0KGZpZy5wYXRoPSJpbWFnZXMvIiwgY2FjaGUucGF0aD0iY2FjaGUvIiwgY2FjaGU9RkFMU0UsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSkKCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShoYWJsYXIpCmxpYnJhcnkoZ2d0aGVtZXMpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KGpjb2xvcnMpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KERUKQogCnNjZi4yMDE2IDwtIHJlYWRfY3N2KCJzdXJ2ZXlfU0NGLnR4dCIsIGNvbF90eXBlcyA9IGNvbHMoRVhQRU5TSElMTyA9IGNvbF9kb3VibGUoKSwgU0FWRUQgPSBjb2xfZG91YmxlKCkpKQpgYGAKCiMjIFRhc2tzCgojIyMgMS4gRGVidCBvdmVyIHRpbWUKCmBgYHtyfQpzY2YuMjAxNi5zdGF0cy4yIDwtIHNjZi4yMDE2ICU+JQogIGdyb3VwX2J5KFlFQVIpICU+JQogIHN1bW1hcmlzZV9hdCh2YXJzKFBJUk1PUlQsIFBJUlRPVEFMLCBERUJUMklOQywgTEVWUkFUSU8pLCBsaXN0KG1lYW4gPSBtZWFuLCBtZWRpYW4gPSBtZWRpYW4sIHRvdGFsID0gc3VtKSkgCmBgYAoKYGBge3J9CnAxIDwtIGdncGxvdChkYXRhID0gc2NmLjIwMTYuc3RhdHMuMiwgYWVzKHggPSBZRUFSKSkgKwogIGdlb21fc21vb3RoKGFlcyh5ID0gTEVWUkFUSU9fbWVkaWFuLCBjb2xvciA9ICJNZWRpYW4gZGVidCB0byBhc3NldHMiKSkgKwogIGdlb21fc21vb3RoKGFlcyh5ID0gREVCVDJJTkNfbWVkaWFuLCBjb2xvciA9ICJNZWRpYW4gZGVidCB0byBpbmNvbWUiKSkKYGBgCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KcDEgKwogIHRoZW1lX3dzaigpICsKICBzY2FsZV9jb2xvcl9qY29sb3JzKHBhbGV0dGUgPSAicGFsNiIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgxOTkwLCAyMDE1LCA1KSkgKwogIGxhYnMoY2FwdGlvbiA9ICJTb3VyY2U6IDIwMTYgU3VydmV5IG9mIENvbnN1bWVyIEZpbmFuY2VzIChTQ0YpIikgKwogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE4KSwKICAgICAgICBsZWdlbmQudGl0bGU9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwKICAgICAgICBwYW5lbC5vbnRvcCA9IFRSVUUpICsKICBnZ3RpdGxlKCJNZWRpYW4gcmF0aW8gb2YgZGVidCB0byBhc3NldHMgYW5kIGluY29tZSIpCmBgYAoKUGxvdCAxIGlzIGEgZml0dGVkIGN1cnZlIG9mIHRoZSBtZWRpYW4gZGVidC10by1pbmNvbWUgcmF0aW8gYW5kIHRoZSBkZWJ0LXRvLWFzc2V0cyByYXRpbyBvdmVyIHRpbWUuIEJvdGggcmF0aW9zIGFyZSBmb3IgYWxsIGRlYnQsIG5vdCBvbmx5IHN0dWRlbnQgbG9hbiBkZWJ0LCB3aGljaCBzaG93cyB0aGUgaGlzdG9yaWNhbCBjaGFuZ2VzIHRvIGhvdXNlaG9sZCBkZWJ0IGFzIGEgd2hvbGUuIFRoZSBkZWJ0LXRvLWluY29tZSByYXRpbyBncmV3IHVudGlsIHRoZSAyMDA4IHJlY2Vzc2lvbiwgYW5kIGhhcyBiZWVuIHNocmlua2luZyBzaW5jZSB0aGVuLiBIb3dldmVyIHRoZSBkZWJ0LXRvLWFzc2V0cyByYXRpbyBoYXMgZ3Jvd24gc3RlYWRpbHkgb3ZlciB0aGUgc2FtZSB0aW1lLCBzb21ld2hhdCBmbGF0dGVuaW5nIGluIHJlY2VudCB5ZWFycy4KCmBgYHtyfQpzY2YuMjAxNi5zdGF0cy44IDwtIHNjZi4yMDE2ICU+JQogIGdyb3VwX2J5KFlFQVIpICU+JQogIHN1bW1hcmlzZV9hdCh2YXJzKE5IX01PUlQsIENDQkFMLCBFRE5fSU5TVCwgVkVIX0lOU1QsIE9USExPQyksIGxpc3QobWVhbiA9IG1lYW4pKSAlPiUKICBnYXRoZXIoTkhfTU9SVF9tZWFuOk9USExPQ19tZWFuLCBrZXkgPSAidHlwZSIsIHZhbHVlID0gIm1lYW4iKSAlPiUKICBhcnJhbmdlKHR5cGUsIFlFQVIpCgpzY2YuMjAxNi5zdGF0cy45IDwtIHNjZi4yMDE2LnN0YXRzLjggJT4lCiAgbXV0YXRlKHR5cGUgPSBjYXNlX3doZW4odHlwZSA9PSAiTkhfTU9SVF9tZWFuIiB+ICJNb3J0Z2FnZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPT0gIkNDQkFMX21lYW4iIH4gIkNyZWRpdCBjYXJkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9PSAiRUROX0lOU1RfbWVhbiIgfiAiU3R1ZGVudCBsb2FuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9PSAiVkVIX0lOU1RfbWVhbiIgfiAiQ2FyIHBheW1lbnQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID09ICJPVEhMT0NfbWVhbiIgfiAiT3RoZXIiKSkKYGBgCgpgYGB7cn0KcDIgPC0gZ2dwbG90KHNjZi4yMDE2LnN0YXRzLjksIGFlcyh4ID0gWUVBUiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IG1lYW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGZjdF9yZW9yZGVyKHR5cGUsIG1lYW4pKSkgKyAKICBnZW9tX2FyZWEoKSAKYGBgCgpgYGB7cn0KcDJpIDwtIHAyICsKICB0aGVtZV93c2ooKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMTk5MCwgMjAxNSwgNSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZG9sbGFyKSArCiAgbGFicyhjYXB0aW9uID0gIlNvdXJjZTogMjAxNiBTdXJ2ZXkgb2YgQ29uc3VtZXIgRmluYW5jZXMgKFNDRikiKSArCiAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwKICAgICAgICBwYW5lbC5vbnRvcCA9IFRSVUUpICsKICBnZ3RpdGxlKCJBdmVyYWdlIGhvdXNlaG9sZCBkZWJ0IikKCnAyaQpgYGAKClBsb3QgMiBpcyBhIHN0YWNrZWQgYXJlYSBjaGFydCBvZiBhdmVyYWdlIGRlYnQgb3ZlciB0aW1lLCBjb2xvci1jb2RlZCBmb3IgdHlwZSBvZiBkZWJ0LiBUaGlzIGFsbG93cyBjb21wYXJpc29uIGJldHdlZW4gZGlmZmVyZW50IHR5cGVzIG9mIGRlYnQsIGJvdGggaW4gcmF3IG51bWJlcnMgYW5kIHByb3BvcnRpb25hbGx5LiBGb3IgaW5zdGFuY2UsIGFsdGhvdWdoIHRoZSBhdmVyYWdlIGhvdXNlaG9sZCBkZWJ0IGhhcyBkZWNyZWFzZWQgc2luY2UgMjAwOCwgc3R1ZGVudCBsb2FucyBncmV3IGluIGJvdGggcmF3IG51bWJlcnMgYW5kIGFzIGEgcHJvcG9ydGlvbiBvZiB0aGUgdG90YWwgZGVidCwgYWx0aG91Z2ggdGhleSBzdGlsbCBhY2NvdW50IGZvciBvbmx5IGEgc21hbGwgZnJhY3Rpb24gb2YgdGhhdCBkZWJ0LgoKSSB3b3VsZCByZWNvbW1lbmQgcGxvdCAyIG92ZXIgcGxvdCAxLCBzaW5jZSBpdCBpcyBlYXNpZXIgZm9yIHJlYWRlcnMgdG8gdW5kZXJzdGFuZCBkb2xsYXIgdmFsdWVzIHRoYW4gaXQgaXMgdG8gaW50cnByZXQgcmF0aW9zLCBhbmQgYmV0dGVyIGhpZ2hsaWdodHMgdGhlIGhpc3RvcmljYWwgcGF0dGVybnMgb2YgYm90aCBzdHVkZW50IGRlYnQgYW5kIGRlYnQgYXMgYSB3aG9sZS4gCgoKIyMjIDIuIFRlbGwgbWUgd2hvIHlvdSBhcmUKCmBgYHtyfQpzY2YuMjAxNi5vbmx5IDwtIGZpbHRlcihzY2YuMjAxNiwgWUVBUiA9PSAyMDE2KQoKc2NmLjIwMTYub25seS4yIDwtIHNjZi4yMDE2Lm9ubHkgJT4lCiAgbXV0YXRlKGVkX3JhdCA9IEVETl9JTlNUIC8gREVCVCkgJT4lCiAgcmVwbGFjZV9uYShsaXN0KGVkX3JhdCA9IDApKQoKc2NmLjIwMTYub25seS4zIDwtIHNjZi4yMDE2Lm9ubHkuMiAlPiUKICBtdXRhdGUoQUdFQ0wuY2F0ID0gYXMuY2hhcmFjdGVyKEFHRUNMKSwKICAgICAgICAgSEhTRVguY2F0ID0gYXMuY2hhcmFjdGVyKEhIU0VYKSwKICAgICAgICAgRURDTC5jYXQgPSBhcy5jaGFyYWN0ZXIoRURDTCksCiAgICAgICAgIEZBTVNUUlVDVC5jYXQgPSBhcy5jaGFyYWN0ZXIoRkFNU1RSVUNUKSwKICAgICAgICAgSE9VU0VDTC5jYXQgPSBhcy5jaGFyYWN0ZXIoSE9VU0VDTCksCiAgICAgICAgIE1BUlJJRUQuY2F0ID0gYXMuY2hhcmFjdGVyKE1BUlJJRUQpLAogICAgICAgICBSQUNFLmNhdCA9IGFzLmNoYXJhY3RlcihSQUNFKSkKCnNjZi4yMDE2Lm9ubHkuNCA8LSBzY2YuMjAxNi5vbmx5LjMgJT4lCiAgbXV0YXRlKEtJRFMuY2F0ID0gY2FzZV93aGVuKAogICAgS0lEUyA+IDAgfiAxLAogICAgVFJVRSAgICAgfiAwKSkgJT4lCiAgbXV0YXRlKEtJRFMuY2F0ID0gYXMuY2hhcmFjdGVyKEtJRFMuY2F0KSkgJT4lCiAgbXV0YXRlKGdlbl9raWRzID0gY2FzZV93aGVuKEhIU0VYLmNhdCA9PSAiMSIgJiBLSURTLmNhdCA9PSAiMSIgfiAiTWFuIHdpdGggY2hpbGRyZW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSEhTRVguY2F0ID09ICIxIiAmIEtJRFMuY2F0ID09ICIwIiB+ICJNYW4gd2l0aG91dCBjaGlsZHJlbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEhIU0VYLmNhdCA9PSAiMiIgJiBLSURTLmNhdCA9PSAiMSIgfiAiV29tYW4gd2l0aCBjaGlsZHJlbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEhIU0VYLmNhdCA9PSAiMiIgJiBLSURTLmNhdCA9PSAiMCIgfiAiV29tYW4gd2l0aG91dCBjaGlsZHJlbiIpKSAlPiUKICBtdXRhdGUoS0lEUy5jYXQuMiA9IGNhc2Vfd2hlbihLSURTLmNhdCA9PSAiMCIgfiAiTm8gY2hpbGRyZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEtJRFMuY2F0ID09ICIxIiB+ICJDaGlsZHJlbiIpKSAlPiUKICBtdXRhdGUoSEhTRVguY2F0LjIgPSBjYXNlX3doZW4oSEhTRVguY2F0ID09ICIxIiB+ICJNZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBISFNFWC5jYXQgPT0gIjIiIH4gIldvbWVuIikpCgpzY2YuMjAxNi5vbmx5LmVkdWMuZ2VuX2tpZHMuMiA8LSBzY2YuMjAxNi5vbmx5LjQgJT4lCiAgZ3JvdXBfYnkoRURVQywgS0lEUy5jYXQuMiwgSEhTRVguY2F0LjIpICU+JQogIHN1bW1hcmlzZV9hdCh2YXJzKFBJUk1PUlQsIFBJUlRPVEFMLCBERUJUMklOQywgTEVWUkFUSU8sIERFQlQsIEVETl9JTlNULCBlZF9yYXQpLCBsaXN0KG1lYW4gPSBtZWFuLCBtZWRpYW4gPSBtZWRpYW4sIHRvdGFsID0gc3VtKSkKYGBgCgpgYGB7cn0KcDMgPC0gZ2dwbG90KHNjZi4yMDE2Lm9ubHkuZWR1Yy5nZW5fa2lkcy4yLCBhZXMoeCA9IEVEVUMsIHkgPSBFRE5fSU5TVF9tZWFuLCBncm91cCA9IEtJRFMuY2F0LjIsIGNvbG9yID0gS0lEUy5jYXQuMikpICsKICBnZW9tX2xpbmUobHdkID0gMS41KSArCiAgeGxpbSg3LCBOQSkgKwogIGZhY2V0X3dyYXAofkhIU0VYLmNhdC4yKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQpwMyArCiAgdGhlbWVfd3NqKCkgKwogIHNjYWxlX2NvbG9yX2pjb2xvcnMocGFsZXR0ZSA9ICJwYWw2IikgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBkb2xsYXIpICsKICBsYWJzKGNhcHRpb24gPSAiU291cmNlOiAyMDE2IFN1cnZleSBvZiBDb25zdW1lciBGaW5hbmNlcyAoU0NGKSIpICsKICB4bGFiKCJZZWFycyBvZiBlZHVjYXRpb24iKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLAogICAgICAgIHBhbmVsLm9udG9wID0gVFJVRSkgKwogIGdndGl0bGUoIkF2ZXJhZ2Ugc3R1ZGVudCBsb2FuIGRlYnQiKQpgYGAKClBsb3QgMyBpcyBhIGxpbmUgY2hhcnQgb2YgaG91c2Vob2xkIGRlYnQgZm9yIDIwMTYgb25seSwgY29tcGFyaW5nIHRoZSBhdmVyYWdlIHN0dWRlbnQgbG9hbiBkZWJ0IG92ZXIgeWVhcnMgb2YgZWR1Y2F0aW9uIGZvciBoZWFkcyBvZiBob3VzZWhvbGQgYm90aCB3aXRoIGFuZCB3aXRob3V0IGNoaWxkcmVuLCBmb3IgYm90aCBtZW4gYW5kIHdvbWVuLiBQcmVkaWN0YWJseSwgc3R1ZGVudCBsb2FuIGRlYnQgaW5jcmVhc2VzIGFmdGVyIGhpZ2ggc2Nob29sICgxMCB5ZWFycyksIGFuZCBpcyBzbGlnaHRseSBoaWdoZXIgZm9yIHBhcmVudHMgb2YgYm90aCBnZW5kZXJzLiBIb3dldmVyLCB3b21lbidzIHN0dWRlbnQgZGVidCByaXNlcyBtdWNoIGZhc3RlciB0aGFuIG1lbidzOyB0aGUgZGlmZmVyZW5jZSBpcyBub3Qgc28gYXBwYXJlbnQgYXQgdGhlIHVuZGVyZ3JhZHVhdGUgbGV2ZWwgKDEyIHllYXJzKSwgYnV0IGF0IHRoZSBkb2N0b3JhbCBsZXZlbCB3b21lbidzIGRlYnQgaXMgbW9yZSB0aGFuIGRvdWJsZSBtZW4ncy4KCmBgYHtyfQpzY2YuMjAxNi5vbmx5LjUgPC0gc2NmLjIwMTYub25seS40ICU+JQogIG11dGF0ZShNQVJSSUVELmNhdC4yID0gY2FzZV93aGVuKAogICAgTUFSUklFRC5jYXQgPT0gIjEiIH4gIk1hcnJpZWQiLCAKICAgIE1BUlJJRUQuY2F0ID09ICIyIiB+ICJTaW5nbGUiKSkKCnNjZi4yMDE2Lm9ubHkuZWR1Yy5nZW5fbWFyci4yIDwtIHNjZi4yMDE2Lm9ubHkuNSAlPiUKICBncm91cF9ieShFRFVDLCBNQVJSSUVELmNhdC4yLCBISFNFWC5jYXQuMikgJT4lCiAgc3VtbWFyaXNlX2F0KHZhcnMoUElSTU9SVCwgUElSVE9UQUwsIERFQlQySU5DLCBMRVZSQVRJTywgREVCVCwgRUROX0lOU1QsIGVkX3JhdCksIGxpc3QobWVhbiA9IG1lYW4sIG1lZGlhbiA9IG1lZGlhbiwgdG90YWwgPSBzdW0pKQpgYGAKCmBgYHtyfQpwNCA8LSBnZ3Bsb3Qoc2NmLjIwMTYub25seS5lZHVjLmdlbl9tYXJyLjIsIGFlcyh4ID0gRURVQywgeSA9IEVETl9JTlNUX21lYW4sIGdyb3VwID0gTUFSUklFRC5jYXQuMiwgY29sb3IgPSBNQVJSSUVELmNhdC4yKSkgKwogIGdlb21fc21vb3RoKHNlID0gRkFMU0UsIGx3ZCA9IDEuNSkgKwogIHhsaW0oNywgTkEpICsKICBmYWNldF93cmFwKH5ISFNFWC5jYXQuMikKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KcDQgKwogIHRoZW1lX3dzaigpICsKICBzY2FsZV9jb2xvcl9qY29sb3JzKHBhbGV0dGUgPSAicGFsNiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZG9sbGFyKSArCiAgbGFicyhjYXB0aW9uID0gIlNvdXJjZTogMjAxNiBTdXJ2ZXkgb2YgQ29uc3VtZXIgRmluYW5jZXMgKFNDRikiKSArCiAgeGxhYigiWWVhcnMgb2YgZWR1Y2F0aW9uIikgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwKICAgICAgICBwYW5lbC5vbnRvcCA9IFRSVUUpICsKICBnZ3RpdGxlKCJBdmVyYWdlIHN0dWRlbnQgZGVidCIpCmBgYAoKUGxvdCA0IGlzIHNpbWlsYXIgZXhjZXB0IHRoYXQgaXMgZGlzcGxheXMgYSBmaXR0ZWQgY3VydmUgaW5zdGVhZCBvZiBhIGxpbmUsIGFuZCBpdCBjb21wYXJlcyBhdmVyYWdlIHN0dWRlbnQgZGVidCBieSBtYXJyaWFnZSwgbm90IHBhcmVudGhvb2QuIEhlcmUgdGhlIHBhdHRlcm4gZGlmZmVycyBieSBnZW5kZXIuIEZvciBtZW4sIGJlaW5nIG1hcnJpZWQgaW5jcmVhc2VzIHN0dWRlbnQgZGVidCB1bnRpbCB0aGUgZ3JhZHVhdGUgbGV2ZWwgKDEzIHllYXJzKSwgYWZ0ZXIgd2hpY2ggaXMgZ29lcyBkb3duLiBUaGlzIHN1Z2dlc3RzIHRoYXQgbWFycmllZCBtZW4ncyBlZHVjYXRpb24gaXMgc3Vic2lkaXplZCBieSB0aGVpciBzcG91c2VzLiBGb3Igd29tZW4sIG1hcnJpYWdlIG9ubHkgaW5jcmVhc2VzIHN0dWRlbnQgbG9hbiBkZWJ0IGFmdGVyIHN0YXJ0aW5nIGNvbGxlZ2UgKDkgeWVhcnMpLCBhbmQgb25seSBkcm9wcyBiZWxvdyB0aGUgcmF0ZSBmb3Igc2luZ2xlIHdvbWVuIGF0IHRoZSBncmFkdWF0ZSBsZXZlbCAoMTMgeWVhcnMpLCBidXQgb25seSBieSBhIHNtYWtrIG1hcmdpbi4gT25jZSBhZ2FpbiwgdGhlIGF2ZXJhZ2Ugc3R1ZGVudCBsb2FuIGRlYnQgZm9yIHdvbWVuIGlzIGhpZ2hlciB0aGFuIGZvciBtZW4sIGluY3JlYXNpbmcgc2hhcnBseSBhZnRlciB0aGUgc3RhcnQgb2YgY29sbGVnZSAoOSB5ZWFycykuIAoKYGBge3J9CnNjZi4yMDE2Lm9ubHkuNyA8LSBzY2YuMjAxNi5vbmx5LjUgJT4lCiAgbXV0YXRlKEVEVUNfY2F0ID0gY2FzZV93aGVuKAogICAgRURVQyA8PSA3ICB+ICJOb25lIiwgCiAgICBFRFVDID09IDggIH4gIkhpZ2ggc2Nob29sIiwKICAgIEVEVUMgPT0gOSAgfiAiSGlnaCBzY2hvb2wiLAogICAgRURVQyA9PSAxMCB+ICJBc3NvY2lhdGUncyIsCiAgICBFRFVDID09IDExIH4gIkFzc29jaWF0ZSdzIiwKICAgIEVEVUMgPT0gMTIgfiAiQmFjaGVsb3IncyIsCiAgICBFRFVDID09IDEzIH4gIk1hc3RlcidzIiwKICAgIEVEVUMgPT0gMTQgfiAiRG9jdG9yYXRlIiwKICAgIFRSVUUgICAgICAgfiAib3RoZXIiKSkgJT4lCiAgZmlsdGVyKCEoRURVQ19jYXQgPT0gIm90aGVyIikpICU+JQogIG11dGF0ZShFRFVDX2ZhYyA9IGZhY3RvcihFRFVDX2NhdCwgbGV2ZWxzID0gYygiTm9uZSIsICJIaWdoIHNjaG9vbCIsICJBc3NvY2lhdGUncyIsICJCYWNoZWxvcidzIiwgIk1hc3RlcidzIiwgIkRvY3RvcmF0ZSIpKSkKCnNjZi4yMDE2Lm9ubHkuZWR1Y19mYWMgPC0gc2NmLjIwMTYub25seS43ICU+JQogIGdyb3VwX2J5KEVEVUNfZmFjKSAlPiUKICBzdW1tYXJpc2VfYXQodmFycyhOSF9NT1JULCBDQ0JBTCwgRUROX0lOU1QsIFZFSF9JTlNULCBPVEhMT0MpLCBsaXN0KG1lYW4gPSBtZWFuKSkgJT4lCiAgZ2F0aGVyKE5IX01PUlRfbWVhbjpPVEhMT0NfbWVhbiwga2V5ID0gInR5cGUiLCB2YWx1ZSA9ICJtZWFuIikgJT4lCiAgYXJyYW5nZSh0eXBlLCBFRFVDX2ZhYykgJT4lCiAgbXV0YXRlKHR5cGUgPSBjYXNlX3doZW4odHlwZSA9PSAiTkhfTU9SVF9tZWFuIiB+ICJNb3J0Z2FnZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPT0gIkNDQkFMX21lYW4iIH4gIkNyZWRpdCBjYXJkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9PSAiRUROX0lOU1RfbWVhbiIgfiAiU3R1ZGVudCBsb2FuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9PSAiVkVIX0lOU1RfbWVhbiIgfiAiQ2FyIHBheW1lbnQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID09ICJPVEhMT0NfbWVhbiIgfiAiT3RoZXIiKSkKYGBgCgpgYGB7cn0KcDUgPC0gZ2dwbG90KHNjZi4yMDE2Lm9ubHkuZWR1Y19mYWMsIGFlcyhmaWxsID0gZmN0X3Jlb3JkZXIodHlwZSwgbWVhbiksIHkgPSBtZWFuLCB4ID0gRURVQ19mYWMpKSArIAogIGdlb21fYmFyKHBvc2l0aW9uPSJzdGFjayIsIHN0YXQ9ImlkZW50aXR5IikKYGBgCgpgYGB7cn0KcDVpIDwtIHA1ICsKICB0aGVtZV93c2ooKSArCiAgc2NhbGVfZmlsbF9qY29sb3JzKHBhbGV0dGUgPSAicGFsNyIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZG9sbGFyKSArCiAgbGFicyhjYXB0aW9uID0gIlNvdXJjZTogMjAxNiBTdXJ2ZXkgb2YgQ29uc3VtZXIgRmluYW5jZXMgKFNDRikiKSArCiAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOCksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9IE5BKSwKICAgICAgICBwYW5lbC5vbnRvcCA9IFRSVUUpICsKICBnZ3RpdGxlKCJBdmVyYWdlIGRlYnQgYnkgaGlnaGVzdCBkZWdyZWUgZWFybmVkIikKCnA1aQpgYGAKClBsb3QgNSBpcyBhIHN0YWNrZWQgYmFyIGNoYXJ0IG9mIGF2ZXJhZ2UgZGVidCBmb3IgMjAxNiBvbmx5IGJ5IGhpZ2hlc3QgZGVncmVlIG9idGFpbmVkLCBjb2xvci1jb2RlZCBmb3IgdHlwZSBvZiBkZWJ0LiBJdCBpcyBzaW1pbGFyIHRvIHRoZSBzZWNvbmQgY2hhcnQsIGJ1dCBncm91cHMgdGhlIGRlYnQgYnkgY2F0ZWdvcmljYWwgbGV2ZWwgb2YgZWR1Y2F0aW9uIGluc3RlYWQgb2YgYnkgY29udGludW91cyB5ZWFycy4gT25jZSBhZ2FpbiB0aGlzIHByZXNlbnRhdGlvbiBmYWNpbGl0YXRlcyBjb21wYXJpbmcgZGlmZmVyZW50IHR5cGVzIG9mIGRlYnQgaW4gYm90aCByYXcgbnVtYmVycyBhbmQgcHJvcG9ydGlvbi4gQXMgZXhwZWN0ZWQsIHRoZSBhdmVyYWdlIHRvdGFsIGRlYnQgaW5jcmVhc2VzIHdpdGggZWFjaCBsZXZlbCBvZiBlZHVjYXRpb24gdXAgdG8gdGhlIGRvY3RvcmFsIGxldmVsLiBEZWJ0IGp1bXBzIHNpZ25pZmljYW50bHkgZnJvbSBhIHR3by15ZWFyIGRlZ3JlZSB0byBhIGZvdXIteWVhciBkZWdyZWUsIGFuZCBhZ2FpbiBmcm9tIGEgYmFjaGVsb3IncyBkZWdyZWUgdG8gYSBtYXN0ZXIncyBkZWdyZWUsIGxpa2VseSBkdWUgdG8gdGhlIGF2ZXJhZ2UgYWdlIGRpZmZlcmVuY2UgYmV0d2VlbiBkZWdyZWUtaG9sZGVycyBvZiBlYWNoIHR5cGUuIEludGVyZXN0aW5nbHksIHRoZSBhbW91bnQgb2Ygc3R1ZGVudCBsb2FuIGRlYnQgc3BlY2lmaWNhbGx5IGlzIHRoZSBzYW1lIGZvciBib3RoIGFzc29jaWF0ZSdzIGRlZ3JlZXMgYW5kIGJhY2hlbG9yJ3MgZGdyZWVzLCBhbmQgYWdhaW4gdGhlIHNhbWUgZm9yIGJvdGggbWFzdGVyJ3MgZGVncmVlcyBhbmQgUGhEcy4KCkkgd291bGQgcmVjb21tZW5kIHVzaW5nIHBsb3QgNSwgYWxvbmcgZWl0aGVyIHBsb3QgMyBvciA0LiBXaGlsZSB5ZWFycyBvZiBlZHVjYXRpb24gaXMgYSBzb21ld2hhdCBkaWZmaWN1bHQgdmFyaWFibGUgdG8gdW5kZXJzdGFuZCwgaXQgaXMgaW1wb3J0YW50IHRvIGhpZ2hsaWdodCBkZW1vZ3JhcGhpYyBwYXR0ZXJucy4KCgojIyMgMy4gV2VhbHRoIGFuZCBpbmNvbWUgZGlzdHJpYnV0aW9uCgpgYGB7cn0Kc2NmLjIwMTYuMiA8LSBzY2YuMjAxNiAlPiUKICBtdXRhdGUobW9ydF9yYXQgPSBOSF9NT1JUIC8gREVCVCwKICAgICAgICAgY3JlZF9yYXQgPSBDQ0JBTCAvIERFQlQsCiAgICAgICAgIGVkX3JhdCA9IEVETl9JTlNUIC8gREVCVCwKICAgICAgICAgY2FyX3JhdCA9IFZFSF9JTlNUIC8gREVCVCkgJT4lCiAgcmVwbGFjZV9uYShsaXN0KG1vcnRfcmF0ID0gMCwKICAgICAgICAgICAgICAgICAgY3JlZF9yYXQgPSAwLAogICAgICAgICAgICAgICAgICBlZF9yYXQgPSAwLAogICAgICAgICAgICAgICAgICBjYXJfcmF0ID0gMCkpICU+JQogIG11dGF0ZShJTkNDQVQuY2F0ID0gYXMuY2hhcmFjdGVyKElOQ0NBVCksCiAgICAgICAgIE5XQ0FULmNhdCA9IGFzLmNoYXJhY3RlcihOV0NBVCkpICU+JQogIG11dGF0ZShJTkNDQVQuY2F0LjIgPSBjYXNlX3doZW4oCiAgICBJTkNDQVQuY2F0ID09ICIxIiB+ICIwLTE5IiwgCiAgICBJTkNDQVQuY2F0ID09ICIyIiB+ICIyMC0zOSIsCiAgICBJTkNDQVQuY2F0ID09ICIzIiB+ICI0MC01OSIsCiAgICBJTkNDQVQuY2F0ID09ICI0IiB+ICI2MC03OSIsCiAgICBJTkNDQVQuY2F0ID09ICI1IiB+ICI4MC05OSIsCiAgICBJTkNDQVQuY2F0ID09ICI2IiB+ICI4MC05IikpICU+JQogIG11dGF0ZShJTkNDQVQuY2F0LjIgPSBmYWN0b3IoSU5DQ0FULmNhdC4yLCBsZXZlbHMgPSBjKCIwLTE5IiwgIjIwLTM5IiwgIjQwLTU5IiwgIjYwLTc5IiwgIjgwLTEwMCIpKSkgJT4lCiAgbXV0YXRlKE5XQ0FULmNhdC4yID0gY2FzZV93aGVuKAogICAgTldDQVQuY2F0ID09ICIxIiB+ICIwLTI1IiwgCiAgICBOV0NBVC5jYXQgPT0gIjIiIH4gIjI1LTUwIiwKICAgIE5XQ0FULmNhdCA9PSAiMyIgfiAiNTAtNzUiLAogICAgTldDQVQuY2F0ID09ICI0IiB+ICI3NS0xMDAiLAogICAgTldDQVQuY2F0ID09ICI1IiB+ICI3NS0xMDAiKSkgJT4lCiAgbXV0YXRlKE5XQ0FULmNhdC4yID0gZmFjdG9yKE5XQ0FULmNhdC4yLCBsZXZlbHMgPSBjKCIwLTI1IiwgIjI1LTUwIiwgIjUwLTc1IiwgIjc1LTEwMCIpKSkKYGBgCgpgYGB7cn0Kc2NmLjIwMTYuMi5vbmx5IDwtIHNjZi4yMDE2LjIgJT4lCiAgZmlsdGVyKFlFQVIgPT0gMjAxNikKCnNjZi4yMDE2LnN0YXRzLjE1IDwtIHNjZi4yMDE2LjIub25seSAlPiUKICBncm91cF9ieShJTkNPTUUpICU+JQogIHN1bW1hcmlzZV9hdCh2YXJzKERFQlQsIEVETl9JTlNULCBlZF9yYXQsIERFQlQySU5DLCBMRVZSQVRJTyksIGxpc3QobWVhbiA9IG1lYW4sIG1lZGlhbiA9IG1lZGlhbiwgdG90YWwgPSBzdW0pKQpgYGAKCmBgYHtyfQpwNiA8LSBnZ3Bsb3QoKSArIAogIGdlb21fc21vb3RoKG1hcHBpbmcgPSBhZXMoeCA9IHNjZi4yMDE2LnN0YXRzLjE1JElOQ09NRSwgeSA9IHNjZi4yMDE2LnN0YXRzLjE1JEVETl9JTlNUX21lYW4pLCBjb2xvciA9ICIjMDA5RTczIikgKwogIGdlb21fc21vb3RoKG1hcHBpbmcgPSBhZXMoeCA9IHNjZi4yMDE2LnN0YXRzLjE1JElOQ09NRSwgeSA9IHNjZi4yMDE2LnN0YXRzLjE1JERFQlRfbWVhbi8xMDApLCBjb2xvciA9ICIjMDA3MkIyIikgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCAxMDAwMDAwKSwgbGFiZWxzID0gZG9sbGFyKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiU3R1ZGVudCBsb2FucyIsIGxhYmVscyA9IGRvbGxhciwKICAgICAgICAgICAgICAgICAgICAgc2VjLmF4aXMgPSBzZWNfYXhpcyh+LioxMDAsIG5hbWUgPSAiVG90YWwgZGVidCIsIGxhYmVscyA9IGRvbGxhcikpICsgCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsIDc1MDApKQpgYGAgCgpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KIHA2ICsgCiAgdGhlbWVfd3NqKCkgKwogIGxhYnMoY2FwdGlvbiA9ICJTb3VyY2U6IDIwMTYgU3VydmV5IG9mIENvbnN1bWVyIEZpbmFuY2VzIChTQ0YpIikgKwogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiIzAwOUU3MyIpLAogICAgICAgIGF4aXMudGl0bGUueS5yaWdodCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICIjMDA3MkIyIiksIAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE4KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gTkEpLAogICAgICAgIHBhbmVsLm9udG9wID0gVFJVRSkgKwogIGdndGl0bGUoIkF2ZXJhZ2UgZGVidCBieSBpbmNvbWUiKQpgYGAKClBsb3QgNiBpcyBhIGZpdHRlZCBjdXJ2ZSBvZiB0aGUgc3R1ZGVudCBsb2FuIGRlYnQgYW5kIHRvdGFsIGRlYnQgYXZlcmFnZXMgYnkgaW5jb21lIHVwIHRvIGAkYDEgbWlsbGlvbi4gQmVjYXVzZSBzdHVkZW50IGxvYW4gZGVidCBpcyBzbyBtdWNoIHNtYWxsZXIgdGhhbiB0b3RhbCBsb2FuIGRlYnQsIHRoZSBwbG90IGhhcyB0d28geS1heGVzLiBUaGlzIG1ha2VzIGl0IHBvc3NpYmxlIHRvIHNlZSB0aGUgcGF0dGVybnMgb2YgYm90aCB0eXBlcyBvZiBkZWJ0IG9uIHRoZSBzYW1lIGdyYXBoOiBTdHVkZW50IGxvYW4gZGVidCBpbmNyZWFzZXMgc2xpZ2h0bHkgdXAgdG8gYXJvdW5kIGAkYDMwMCwwMDAsIGFmdGVyIHdoaWNoIGl0IGRlY3JlYXNlcyBzaGFycGx5LCB3aGlsZSB0b3RhbCBkZWJ0IGluY3JlYXNlcyBzdGVhZGlseSB3aXRoIGluY29tZSwgZmxhdHRlbmluZyBicmllZmx5IGFyb3VuZCBgJGA1MDAsMDAwLgoKYGBge3J9CnNjZi4yMDE2LnN0YXRzLjE4IDwtIHNjZi4yMDE2LjIub25seSAlPiUKICBncm91cF9ieShORVRXT1JUSCkgJT4lCiAgc3VtbWFyaXNlX2F0KHZhcnMoREVCVCwgRUROX0lOU1QsIGVkX3JhdCwgREVCVDJJTkMsIExFVlJBVElPKSwgbGlzdChtZWFuID0gbWVhbiwgbWVkaWFuID0gbWVkaWFuLCB0b3RhbCA9IHN1bSkpCmBgYAoKYGBge3J9CnA3IDwtIGdncGxvdCgpICsgCiAgZ2VvbV9zbW9vdGgobWFwcGluZyA9IGFlcyh4ID0gc2NmLjIwMTYuc3RhdHMuMTgkTkVUV09SVEgsIHkgPSBzY2YuMjAxNi5zdGF0cy4xOCRFRE5fSU5TVF9tZWFuKSwgY29sb3IgPSAiIzAwOUU3MyIpICsKICBnZW9tX3Ntb290aChtYXBwaW5nID0gYWVzKHggPSBzY2YuMjAxNi5zdGF0cy4xOCRORVRXT1JUSCwgeSA9IHNjZi4yMDE2LnN0YXRzLjE4JERFQlRfbWVhbi8yMCksIGNvbG9yID0gIiMwMDcyQjIiKSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEwMDAwMDApLCBsYWJlbHMgPSBkb2xsYXIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJTdHVkZW50IGxvYW5zIiwgbGFiZWxzID0gZG9sbGFyLAogICAgICAgICAgICAgICAgICAgICBzZWMuYXhpcyA9IHNlY19heGlzKH4uKjIwLCBuYW1lID0gIlRvdGFsIGRlYnQiLCBsYWJlbHMgPSBkb2xsYXIpKSArIAogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLCAxMDAwMCkpCmBgYAoKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnA3ICsKICB0aGVtZV93c2ooKSArCiAgbGFicyhjYXB0aW9uID0gIlNvdXJjZTogMjAxNiBTdXJ2ZXkgb2YgQ29uc3VtZXIgRmluYW5jZXMgKFNDRikiKSArCiAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICIjMDA5RTczIiksCiAgICAgICAgYXhpcy50aXRsZS55LnJpZ2h0ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gIiMwMDcyQjIiKSwgCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksCiAgICAgICAgcGFuZWwub250b3AgPSBUUlVFKSArCiAgZ2d0aXRsZSgiQXZlcmFnZSBkZWJ0IGJ5IG5ldCB3b3J0aCIpCmBgYAoKUGxvdCA3IGlzIHNpbWlsYXIgdG8gcGxvdCA2LCBvbmx5IHRoZSB4LWF4aXMgaXMgZm9yIG5ldCB3b3J0aC4gQnkgdGhpcyBtZWFzdXJlLCBzdHVkZW50IGxvYW4gZGVidCBmb2xsb3dzIGEgbW9yZSBudWFuY2VkIHBhdHRlcm4sIHdpdGggc3ZlcmFsIGxvY2FsIG1heGltYSBhbmQgbWluaW1hLCBidXQgZ2VuZXJhbGx5IGluY3JlYXNpbmcgZXhwb25lbnRpYWxseSB1cCB0byBgJGAyMDAsMDAwLCBhZnRlciB3aGljaCBpdCBkZWNyZWFzZXMgdW50aWwgYCRgNzUwLDAwMC4gQnkgY29udHJhc3QsIHRvdGFsIGRlYnQgaW5jcmVhc2VzIGxvZ2FyaXRobWljYWxseSBhcyBpdCBhcHByb2FjaGVzIHRoZSBgJGAxIG1pbGxpb24gY3V0b2ZmLCB3aXRoIG9ubHkgYSBzbGlnaHQgZGlwIGFyb3VuZCBgJGA1MDAsMDAwLiAKCkkgcmVjb21tZW5kIHVzaW5nIHBsb3QgNiwgYWx0aG91Z2ggdGhlIGRvdWJsZSBheGVzIG1pZ2h0IG5vdCBiZSBpbW1lZGlhdGVseSBjbGVhciB0byByZWFkZXJzLiBJIHdvdWxkIG9ubHkgcmVjb21tZW5kIHVzaW5nIHBsb3QgNyBhcyBhIGNvbXBhcmlzb24gdG8gcGxvdCA2LCBhbmQgbm90IG9uIGl0cyBvd24sIHNpbmNlIHRoZSByZWxhdGlvbnNoaXAgb2YgZGVidCB0byBuZXQgd29ydGggaXMgYWxzbyBtb3JlIGRpZmZpY3VsdCB0byBpbnRlcnByZXQuIAoKIyMjIDQuIEdvaW5nIGJyb2tlCgpgYGB7cn0Kc2NmLjIwMTYuYmFuayA8LSBmaWx0ZXIoc2NmLjIwMTYuMiwgQk5LUlVQTEFTVDUgPT0gMSkKCnNjZi4yMDE2LmJhbmsuc3RhdHMgPC0gc2NmLjIwMTYuYmFuayAlPiUKICBncm91cF9ieShZRUFSKSAlPiUKICBzdW1tYXJpc2VfYXQodmFycyhQSVJNT1JULCBQSVJUT1RBTCwgREVCVDJJTkMsIExFVlJBVElPLCBERUJULCBFRE5fSU5TVCksIGxpc3QobWVhbiA9IG1lYW4sIG1lZGlhbiA9IG1lZGlhbiwgdG90YWwgPSBzdW0pKQpgYGAKCmBgYHtyfQpwOCA8LSBnZ3Bsb3Qoc2NmLjIwMTYuYmFuay5zdGF0cywgYWVzKHggPSBZRUFSKSkgKwogIGdlb21fc21vb3RoKHNlID0gRkFMU0UsIGFlcyh5ID0gREVCVF9tZWFuLCBjb2xvciA9ICJUb3RhbCBkZWJ0IikpICsgCiAgZ2VvbV9zbW9vdGgoc2UgPSBGQUxTRSwgYWVzKHkgPSBFRE5fSU5TVF9tZWFuLCBjb2xvcj0iU3R1ZGVudCBsb2FucyIpKQpgYGAKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpwOCArIAogIHRoZW1lX3dzaigpICsKICBzY2FsZV9jb2xvcl9qY29sb3JzKHBhbGV0dGUgPSAicGFsNiIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgxOTkwLCAyMDE1LCA1KSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBkb2xsYXIpICsKICBsYWJzKGNhcHRpb24gPSAiU291cmNlOiAyMDE2IFN1cnZleSBvZiBDb25zdW1lciBGaW5hbmNlcyAoU0NGKSIpICsKICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xOCksCiAgICAgICAgbGVnZW5kLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksCiAgICAgICAgcGFuZWwub250b3AgPSBUUlVFKSArCiAgZ2d0aXRsZSgiQXZlcmFnZSBkZWJ0IGluIGhvdXNlaG9sZHMgXG53aXRoIGEgcmVjZW50IGJhbmtydXB0Y3kiKQpgYGAKClBsb3QgOCBpcyBhIGZpdHRlZCBjdXJ2ZSBvZiBtZWFuIHN0dWRlbnQgbG9hbiBkZWJ0IGFuZCB0b3RhbCBkZWJ0IG92ZXIgdGltZSBmb3IgaG91c2Vob2xkcyB0aGF0IGhhZCBhIGJhbmtydXB0Y3kgaW4gdGhlIHBhc3QgNSB5ZWFycy4gSXQgc2hvd3MgdGhhdCB3aGlsZSB0aGUgYXZlcmFnZSB0b3RhbCBkZWJ0IGZvciByZWNlbnRseSBiYW5rcnVwdCBob3VzZWhvbGRzIGhhcyBnb25lIHVwIGFuZCBkb3duIG92ZXIgdGhlIHllYXJzLCB0aGUgYXZlcmFnZSBzdHVkZW50IGxvYW4gZGVidCBmb3IgdGhlc2UgaG91c2Vob2xkcyBoYXMgc3RlYWRpbHkgaW5jcmVhc2VkLiAKCmBgYHtyfQpzY2YuMjAxNi5iYW5rLnN0YXRzLjIgPC0gc2NmLjIwMTYuYmFuayAlPiUKICBncm91cF9ieShZRUFSKSAlPiUKICBzdW1tYXJpc2VfYXQodmFycyhOSF9NT1JULCBDQ0JBTCwgRUROX0lOU1QsIFZFSF9JTlNULCBPVEhMT0MpLCBsaXN0KG1lYW4gPSBtZWFuKSkgJT4lCiAgZ2F0aGVyKE5IX01PUlRfbWVhbjpPVEhMT0NfbWVhbiwga2V5ID0gInR5cGUiLCB2YWx1ZSA9ICJtZWFuIikgJT4lCiAgYXJyYW5nZSh0eXBlLCBZRUFSKSAlPiUKICBtdXRhdGUodHlwZSA9IGNhc2Vfd2hlbih0eXBlID09ICJOSF9NT1JUX21lYW4iIH4gIk1vcnRnYWdlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9PSAiQ0NCQUxfbWVhbiIgfiAiQ3JlZGl0IGNhcmQiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID09ICJFRE5fSU5TVF9tZWFuIiB+ICJTdHVkZW50IGxvYW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID09ICJWRUhfSU5TVF9tZWFuIiB+ICJDYXIgcGF5bWVudCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPT0gIk9USExPQ19tZWFuIiB+ICJPdGhlciIpKQpgYGAKCmBgYHtyfQpwOSA8LSBnZ3Bsb3Qoc2NmLjIwMTYuYmFuay5zdGF0cy4yLCBhZXMoeCA9IFlFQVIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBmY3RfcmVvcmRlcih0eXBlLCBtZWFuKSkpICsgCiAgICBnZW9tX2FyZWEoKQpgYGAKCmBgYHtyfQpwOSArCiAgdGhlbWVfd3NqKCkgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19kKCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDE5OTAsIDIwMTUsIDUpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGRvbGxhcikgKwogIGxhYnMoY2FwdGlvbiA9ICJTb3VyY2U6IDIwMTYgU3VydmV5IG9mIENvbnN1bWVyIEZpbmFuY2VzIChTQ0YpIikgKwogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksCiAgICAgICAgcGFuZWwub250b3AgPSBUUlVFKSArCiAgZ2d0aXRsZSgiQXZlcmFnZSBkZWJ0IGluIGhvdXNlaG9sZHMgXG53aXRoIGEgcmVjZW50IGJhbmtydXB0Y3kiKQpgYGAKCgpQbG90IDkgaXMgYSBzdGFja2VkIGFyZWEgY2hhcnQgb2YgYXZlcmFnZSBkZWJ0IG92ZXIgdGltZSBmb3IgaG91c2Vob2xkcyB0aGF0IGhhZCBhIGJhbmtydXB0Y3kgaW4gdGhlIHBhc3QgNSB5ZWFycywgY29sb3ItY29kZWQgZm9yIHR5cGUgb2YgZGVidC4gSXQgaXMgdGhlIHNhbWUgYXMgcGxvdCAyLCBidXQgb25seSBmb3IgdGhvc2UgaG91c2Vob2xkcyB3aXRoIHJlY2VudCBiYW5rcnVwdGNpZXMuIE9uY2UgYWdhaW4gdGhpcyBhbGxvd3MgZm9yIGVhc3kgY29tcGFyaXNvbiBiZXR3ZWVuIGRpZmZlcmVudCB0eXBlcyBvZiBkZWJ0LiBJbiB0aGlzIGNhc2UsIHdoaWxlIHRoZSBhdmVyYWdlIGRlYnQgb2YgcmVjZW50bHkgYmFua3J1cHQgaG91c2Vob2xkcyBoYXMgZmxhdGxpbmVkIHNpbmNlIDIwMTAsIHRoZWlyIGF2ZXJhZ2Ugc3R1ZGVudCBsb2FuIGRlYnQgaGFzIHN0ZWFkaWx5IGluY3JlYXNlZC4KCgpgYGB7cn0Kc2NmLjIwMTYuYmFuay4yIDwtIHNjZi4yMDE2LjIgJT4lCiAgbXV0YXRlKGJhbmsuY2F0ID0gY2FzZV93aGVuKEJOS1JVUExBU1Q1ID09IDAgfiAiTm8gcmVjZW50IGJhbmtydXB0Y3kiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQk5LUlVQTEFTVDUgPT0gMSB+ICJSZWNlbnQgYmFua3J1cHRjeSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgICAgICAgICAgICAgfiAidW5rbm93biIpKSAlPiUKICBmaWx0ZXIoIShiYW5rLmNhdCA9PSAidW5rbm93biIpKSAlPiUKICBtdXRhdGUoZm9vZF9hbGwgPSAoRk9PREhPTUUgKyBGT09EREVMViArIEZPT0RBV0FZKSkgJT4lCiAgbXV0YXRlKEZPT0RERUxWLnBjdCA9IChGT09EREVMVi9mb29kX2FsbCkpICU+JQogIG11dGF0ZShGT09EQVdBWS5wY3QgPSAoRk9PREFXQVkvZm9vZF9hbGwpKSAlPiUKICByYXRpb25hbGl6ZSgpICU+JQogIHJlcGxhY2VfbmEobGlzdChGT09EREVMVi5wY3QgPSAwLAogICAgICAgICAgICAgICAgICBGT09EQVdBWS5wY3QgPSAwKSkKCgpzY2YuMjAxNi5iYW5rLnN0YXRzLjcgPC0gc2NmLjIwMTYuYmFuay4yICU+JQogIGdyb3VwX2J5KFlFQVIsIGJhbmsuY2F0KSAlPiUKICBzdW1tYXJpc2VfYXQodmFycyhGT09EREVMVi5wY3QsIEZPT0RBV0FZLnBjdCksIGxpc3QobWVhbiA9IG1lYW4sIG1lZGlhbiA9IG1lZGlhbiwgdG90YWwgPSBzdW0pKQpgYGAKCmBgYHtyfQpwMTAgPC0gZ2dwbG90KHNjZi4yMDE2LmJhbmsuc3RhdHMuNywgYWVzKHggPSBZRUFSLCB5ID0gRk9PRERFTFYucGN0X21lYW4sIGdyb3VwID0gYmFuay5jYXQsIGNvbG9yID0gYmFuay5jYXQpKSArIAogIGdlb21fbGluZShsd2QgPSAxLjUpICsKICB4bGltKDIwMDQsIE5BKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQpwMTAgKwogIHRoZW1lX3dzaigpICsKICBzY2FsZV9jb2xvcl9qY29sb3JzKHBhbGV0dGUgPSAicGFsNiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudCkgKwogIGxhYnMoY2FwdGlvbiA9ICJTb3VyY2U6IDIwMTYgU3VydmV5IG9mIENvbnN1bWVyIEZpbmFuY2VzIChTQ0YpIikgKwogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSBOQSksCiAgICAgICAgcGFuZWwub250b3AgPSBUUlVFKSArCiAgZ2d0aXRsZSgiRm9vZCBidWRnZXQgc3BlbnQgb24gZGVsaXZlcnkiKQpgYGAKCkFzIHJlcXVlc3RlZCwgbXkgZmluYWwgc3RhdGljIHBsb3QgY29uY2VybnMgZm9vZCBzcGVuZGluZyBhbmQgYmFua3J1cHRjaWVzLiBQbG90IDEwIGlzIGEgbGluZSBjaGFydCBzaG93aW5nIHRoZSBwZXJjZW50YWdlIG9mIHRoZSBhdmVyYWdlIGZvb2QgYnVkZ2V0IHNwZW50IG9uIGRlbGl2ZXJ5IGZvciBib3RoIGhvdXNlaG9sZHMgdGhhdCByZWNlbnRseSBleHBlcmllbmNlZCBiYW5rcnVwdGN5IGFuZCB0aG9zZSB0aGF0IGRpZCBub3QuIFdoaWxlIHJlY2VudGx5IGJhbmtydXB0IGhvdXNlaG9sZHMgZGlkIGhhdmUgYSBzbWFsbCBzcGlrZSBvZiBkZWxpdmVyeSBzcGVuZGluZyBpbiAyMDA3LCBpdCBoYXMgYmVlbiBkZWNyZWFzaW5nIG92ZXJhbGwgc2luY2UgdGhlbi4gRm9yIG5vbi1iYW5rcnVwdCBob3VzZWhvbGRzLCBpdCBoYXMgYWxzbyBiZWVuIGRlY3JlYXNpbmcgc3RlYWRpbHksIHdpdGggYSBzbWFsbCB1cHRpY2sgaW4gMjAxNi4gSXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCB0aGlzIGRhdGEgaXMgb25seSBhdmFpbGFibGUgc3RhcnRpbmcgaW4gMjAwNCwgYW5kIGFzIHN1Y2ggdGhlcmUgaXMgbm90IGVub3VnaCBkYXRhIHRvIGNhbGN1bGF0ZSBhIHJlbGlhYmxlIGZpdHRlZCBsaW5lIG9yIGN1cnZlLiBJbiBhZGRpdGlvbiwgYWxsIG9mIHRoZXNlIGNoYW5nZXMgYXJlIHdpdGggMSUgYW5kIDMlIG9mIHRoZSB0b3RhbCBmb29kIGJ1ZGdldC4gCgpJIHdvdWxkIHJlY29tbWVuZCBhZ2FpbnN0IHVzaW5nIHBsb3QgMTAsIGFuZCBhbHNvIHJlY29tbWVuZCB1c2luZyBwbG90IDkgb3ZlciBwbG90IDguIFBsb3QgOSBjb252ZXlzIGEgZ3JlYXQgZGVhbCBvZiBpbmZvcm1hdGlvbiBjbGVhcmx5IGFuZCBlZmZpY2llbnRseSwgZXNwZWNpYWxseSBpZiBkaXNwbGF5ZWQgYWxvbmdzaWRlIHBsb3QgMiB0byBoaWdobGlnaHQgdGhlIGRpZmZlcmVuY2VzIGluIGRlYnQgY29tcG9zaXRpb24gYmV0d2VlbiBhbmQgYmFua3J1cHQtb25seSBob3VzZWhvbGRzIGFuZCBob3VzZWhvbGRzIGluIGdlbmVyYWwuIEhvd2V2ZXIsIGluIHRoZSBhYnNlbmNlIG9mIGEgZGVlcGVyIGRpc2N1c3Npb24gb24gYmFua3J1cHRjeSwgcGxvdCA4IHNob3VsZCBzdWZmaWNlLgoKCiMjIEludGVyYWN0aXZpdHkKCiMjIyA1LiBNYWtlIHR3byBwbG90cyBpbnRlcmFjdGl2ZQoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CmdncGxvdGx5KHAyaSkKYGBgCgpgYGB7ciwgd2FybmluZz1GQUxTRX0KZ2dwbG90bHkocDVpKQpgYGAKClBsb3RzIDIgYW5kIDUgd291bGQgYmVuZWZpdCBmcm9tIGludGVyYWN0aXZlIG9ubGluZSB2ZXJzaW9ucywgc2luY2Ugc3RhY2tlZCBwbG90cyBjYW4gYmUgZGlmZmljdWx0IHRvIGludGVycHJldC4gQmVpbmcgYWJsZSB0byBob3ZlciBvdmVyIGVhY2ggdHlwZSBvZiBkZWJ0IGZvciBhIGdpdmVuIHllYXIgb3IgY2F0ZWdvcnkgd291bGQgYWxsb3cgcmVhZGVycyB0byBmdXJ0aGVyIGV4cGxvcmUgdGhlIGRhdGEgYW5kIHJlbGlhYmx5IGNvbXBhcmUgdmFsdWVzIHRoYXQgZG8gbm90IGJlZ2luIGF0IHRoZSBzYW1lIHBvaW50IG9uIHRoZSB5LWF4aXMuCgojIyMgNi4gRGF0YSBUYWJsZQoKYGBge3J9CnNjZi4yMDE2LnN0YXRzLjkucCA8LSBzY2YuMjAxNiAlPiUKICBncm91cF9ieShZRUFSKSAlPiUKICBzdW1tYXJpc2VfYXQodmFycyhERUJULCBOSF9NT1JULCBDQ0JBTCwgRUROX0lOU1QsIFZFSF9JTlNULCBPVEhMT0MpLCBsaXN0KG1lYW4gPSBtZWFuKSkgJT4lCiAgcmVuYW1lKCJBbGwgZGVidCBtZWFuIiA9ICJERUJUX21lYW4iLAogICAgICAgICAiTW9ydGdhZ2UgbWVhbiIgPSAiTkhfTU9SVF9tZWFuIiwKICAgICAgICAgIkNyZWRpdCBjYXJkIG1lYW4iID0gIkNDQkFMX21lYW4iLAogICAgICAgICAiU3R1ZGVudCBsb2FuIG1lYW4iID0gIkVETl9JTlNUX21lYW4iLAogICAgICAgICAiQ2FyIHBheW1lbnQgbWVhbiIgPSAiVkVIX0lOU1RfbWVhbiIsCiAgICAgICAgICJPdGhlciBkZWJ0IG1lYW4iID0gIk9USExPQ19tZWFuIikKCmRhdGF0YWJsZShzY2YuMjAxNi5zdGF0cy45LnApCmBgYAoKVGhpcyB0YWJsZSBzaG93cyB0aGUgZGF0YSB1c2VkIGZvciBwbG90IDIsIHRoZSBtZWFuIHZhbHVlcyBvZiBhbGwgZGVidCB0eXBlcyBmb3IgZWFjaCB5ZWFyIG9mIHRoZSBzdXJ2ZXkuIFByZXNlbnRpbmcgdGhlIGRhdGEgaW4gdGhpcyB3YXkgd291bGQgYWxsb3cgcmVhZGVycyB0byBvcmRlciB0aGUgZGF0YSBieSBlYWNoIGRhdGEgdHlwZSwgdG8gc2VlIHdoaWNoIHllYXJzIGhhZCB0aGUgaGlnaGVzdCBhbmQgbG93ZXN0IGF2ZXJhZ2Ugc3R1ZGVudCBsb2FuIGRlYnQsIGZvciBpbnN0YW5jZSwgY29tcGFyZWQgdG8gb3RoZXIgdHlwZXMgb2YgZGVidC4K