Data wrangling and visualization exercise

This notebook uses #TidyTuesday week 30 US Droughts, data from U.S. Drought Monitor

# Load libraries
library(tidyverse)
library(geofacet)
library(scales)
library(ggtext)
library(usmap)
library(urbnmapr)
library(patchwork)
# Import data
drought <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-07-20/drought.csv')

── Column specification ───────────────────────────────────────────────────────────────────────────────
cols(
  map_date = col_double(),
  state_abb = col_character(),
  valid_start = col_date(format = ""),
  valid_end = col_date(format = ""),
  stat_fmt = col_double(),
  drought_lvl = col_character(),
  area_pct = col_double(),
  area_total = col_double(),
  pop_pct = col_double(),
  pop_total = col_double()
)

Category D0, area_pct, pop_pct

df1 = drought %>% 
  filter(valid_end=="2021-07-19") %>%
  filter(drought_lvl=="D0") %>%
  select(state_abb,  area_pct,  pop_pct) %>%
  rename("land area"=area_pct, population=pop_pct) %>%
  pivot_longer(!state_abb) %>%
  mutate(value=value/100)
df1 
ggplot(df1, aes(fct_rev(name), value, fill = fct_rev(name))) +
  geom_col(width=0.8, alpha=0.9) +
  coord_flip() +
  facet_geo(~ state_abb, grid = "us_state_grid2") + 
  scale_y_continuous(breaks=c(0,0.5,1), labels=c(0,0.5,1), expand=c(0,0)) +
  scale_fill_manual(values=c("#f28f3b","#588b8b")) +
  theme(legend.position="none",
        panel.grid.major.y=element_blank(),
        panel.grid.minor=element_blank(),
        axis.text.x=element_text(size=8),
        axis.title=element_blank(),
        plot.margin=unit(c(0.5,0.5,0.5,0.5),"cm"),
        plot.title=element_markdown(size=18, margin=margin(b=10)),
        plot.subtitle=element_markdown(size=13, lineheight = 1.35),
        axis.ticks.y = element_blank()) + 
  labs(caption="#TidyTuesday week 30 | Data from U.S. Drought Monitor",
       title="<b>U.S. Drought Level D0</b> (July 13, 2021 to July 19, 2021)",
       subtitle="Proportion of <span style = 'color:#588b8b'><b>land area (sq miles)</b></span> and <span style = 'color:#f28f3b'><b>population</b></span> of state in drought level D0<br>(*Drought level D0 corresponds to short-term dryness that is typical with the onset of drought*)<br>")

Category D4, area_pct

df2 = drought %>% filter(drought_lvl=="D4") %>%
  select(state_abb, drought_lvl, valid_start, area_pct) %>%
  mutate(area_pct=area_pct/100)

summary(df2$valid_start)
        Min.      1st Qu.       Median         Mean      3rd Qu.         Max. 
"2001-07-17" "2006-07-16" "2011-07-15" "2011-07-15" "2016-07-13" "2021-07-13" 
ggplot(df2, aes(valid_start, area_pct)) + 
  geom_line(color="red",size=0.5) + 
  facet_geo(~ state_abb, grid = "us_state_grid2") + 
  theme_minimal() +
  scale_x_date(expand=c(0,0), breaks=c(min(df2$valid_start),max(df2$valid_start))) +
  scale_y_continuous(expand=c(0,0), breaks=seq(0,0.8,0.4)) +
  theme(legend.position="none",
        panel.grid=element_blank(),
        axis.text.x=element_text(angle=90,size=6),
        axis.text.y=element_text(size=7),
        plot.background=element_rect(fill="#f8f9fa", color=NA),
        panel.background = element_rect(fill="white", color=NA),
        strip.background=element_rect(fill="#eff1f3", color=NA),
        plot.margin=unit(c(0.5,0.5,0.5,0.5),"cm"),
        axis.title=element_blank(),
        plot.title=element_markdown(size=18, margin=margin(b=10)),
        plot.subtitle=element_markdown(size=10.3,lineheight = 1.35)) + 
  labs(title="<b>U.S. Drought Level D4 over 20 years</b>",
       subtitle="Proportion of land area (in sq miles) by state in drought category D4 from July 17, 2001 to July 19, 2021. Drought level D4 corresponds to<br>an area experiencing exceptional and widespread crop and pasture losses, fire risk, and water shortages that result in water emergencies. <br>")

All states, maximum drought level

df3 = drought %>% 
  filter(drought_lvl!="None") %>%
  filter(valid_end=="2021-07-19") %>%
  select(drought_lvl, state_abb, area_pct) %>%
  filter(area_pct!=0) %>%
  group_by(state_abb) %>%
  mutate(min_ap = min(area_pct)) %>%
  ungroup() %>%
  mutate(cond = ifelse(min_ap==area_pct,1,0)) %>%
  filter(cond!=0) %>%
  select(-min_ap,-cond) %>%
  rename(state_abbv=state_abb) %>%
  mutate(drought_lvl= recode(drought_lvl, 
                             D0="D0 (Abnormally Dry)",
                             D1="D1 (Moderate Drought)",
                             D2="D2 (Severe Drought)",
                             D3="D3 (Extreme Drought)",
                             D4="D4 (Exceptional Drought)")) 

states_sf = get_urbn_map("states",sf=TRUE)
df3b = states_sf %>% 
  left_join(df3, by="state_abbv") %>% 
  mutate(drought_lvl=replace_na(drought_lvl,"None"))
df3b %>%
  ggplot() + 
  geom_sf(aes(fill=drought_lvl),color="#ffffff",size=0.25) + 
  geom_sf_text(data = df3b %>% filter(state_abbv %in% df3$state_abbv), 
                aes(label = state_abbv), size = 2) + 
  coord_sf(datum = NA) + 
  #scale_fill_manual(values = wes_palette("Zissou1"), na.value="#e8e8e8") + 
  scale_fill_manual(values=c("#f1dca7","#ffcb69","#e8ac65","#d08c60","#997b66","#e9ecef")) +
  theme_void() + 
  theme(legend.text=element_text(size=7.5),
        legend.title=element_text(size=8.5),
        plot.subtitle=element_text(size=10, face="bold"),
        plot.margin=unit(c(0.5,1,0.5,1),"cm")) + 
  labs(fill="Drought Level", subtitle="U.S. States and their maximum drought level for the week July 13, 2021 to July 19, 2021\n") 

Nevada, area_pct

# tibble for x-axis text using with annotations()
x_axis = tibble(
  x = c(
        lubridate::ym("2002/07"),
        lubridate::ym("2006/07"),
        lubridate::ym("2010/07"),
        lubridate::ym("2014/07"),
        lubridate::ym("2018/07"),
        lubridate::ym("2021/01")),
  y = -7,
  label = c("2002", "06", "10", "14", "18", "21")
)
# tibble for xticks using with geom_linerange()
x_ticks = tibble(
            x = c(seq.Date(lubridate::ym("2002/01"), 
                           lubridate::ym("2021/01"), 
                                     by = "1 year"),
                            max(drought$valid_start)),
            ymax = 0,
            ymin = c(rep(c(4, 4, 2.3, 2.3), 4),  4, 4, 2.3, 4, 2.3) * -1)
pal = c("#ffebc6","#ffb100","#f194b4","#d90368","#003844")

plotdata = drought %>% 
  filter(drought_lvl!="None",
         area_pct!=0, 
         state_abb=="NV",
         lubridate::year(valid_start) > 2001) %>%
  mutate(drought_lvl= recode(drought_lvl, 
                             D0="D0 Abnormally Dry",
                             D1="D1 Moderate Drought",
                             D2="D2 Severe Drought",
                             D3="D3 Extreme Drought",
                             D4="D4 Exceptional Drought"))  %>%
  mutate(date = lubridate::ym(
                            paste(lubridate::year(valid_start),
                                  lubridate::month(valid_start),
                                                   sep = "/"))) 
# main plot
p4 = plotdata %>%
  ggplot() + 
  geom_col(aes(x=valid_start, y=area_pct, color=drought_lvl, fill=drought_lvl), position = "dodge") + 
  geom_hline(color="black", yintercept=0, size=0.3) +
  coord_cartesian(clip = "off") +
  # x-axis
  annotate(geom = "text", x = x_axis$x, y = x_axis$y,
           label = x_axis$label, size = 2.7, color="grey30") +
  geom_linerange(data = x_ticks,
                 aes(x = x, ymin = ymin, ymax = ymax),color="grey30") +
  # annotate
  #geom_curve(aes(x = lubridate::ym("2015/01"), y = 85,
                 #xend = lubridate::ym("2020/11"), yend = 20),
             #curvature = 0.20,
            # arrow = arrow(length = unit(0.03, "npc"))) +
  #geom_text(aes(x = lubridate::ym("2015/01"), y = 95,
                #label = "The effect of\nrecord-low precipitation and higher temperatures"),
            #fontface="italic", size = 2.5) +
  # customize 
  scale_fill_manual(values=pal, guide='none')+
  scale_color_manual(values=pal)+
  scale_y_continuous(limits = c(-10, 100), expand = c(0, 0),
                     position = "right") + 
  theme_minimal(base_size=10) +
  theme(legend.position = "top",
        panel.grid.minor=element_blank(),
        panel.grid.major.x=element_blank(),
        axis.title=element_blank(),
        axis.text.x = element_blank(),
        axis.text.y.right =element_text(color="grey20", margin=margin(l=-15),size=8,vjust=-.7),
        plot.title=element_text(face="bold", size=11),
        plot.subtitle=element_markdown(color="grey20",lineheight = 1.3),
        legend.margin=margin(5, .2, .2,-5),
        legend.key.width = unit(0.3, "cm"),
        legend.key.height = unit(0.18, "cm"),
        legend.text = element_text(size=7.5),
        legend.justification = "left",
        legend.spacing.x = unit(0.2, "cm"),
        panel.grid.major=element_line(size=.5),
        plot.margin=unit(c(0.5,1.5,0.5,1),"cm")) + 
  guides(fill=guide_legend(ncol=3, byrow=T)) + 
  labs(color="", fill="",
       title="Proportion of Nevada in drought", 
       subtitle="<span style = 'font-size:10pt'>By intensity category, % of total area</span><br>
    <span style = 'font-size:9pt'>July 17, 2001 to July 19, 2021</span>")
# map insert 
state_nv = statepop %>% mutate(col=ifelse(abbr=="NV","1","0"))

map_nv = plot_usmap(data = state_nv, values = "col", color = "#495057",size=0.3) + 
  theme(legend.position="none",plot.margin=unit(c(0.5,0.5,0.5,0.5),"cm")) + 
  scale_fill_manual(values=c("white","#2ec4b6"))
p4 |inset_element(map_nv,
                    align_to = "full",
                    clip = FALSE,
                    on_top = TRUE,
                    ignore_tag = TRUE,
                    left = 0.55, 
                    bottom = 0.7, 
                    right = 1, 
                    top = 1)

Pacific division, area_pct

# states in pacific division
.pacific
[1] "AK" "CA" "HI" "OR" "WA"
# pacific division
p5 = drought %>% 
  filter(state_abb %in% .pacific) %>%
  filter(lubridate::year(valid_start) == 2021) %>% 
  mutate(drought_lvl = fct_relevel(drought_lvl, 
                                   levels = c("D4","D3","D2","D1","D0","None"))) %>% 
  group_by(map_date, valid_start, drought_lvl) %>%
  summarise(area_pct=mean(area_pct)) %>%
  ungroup() %>%
  arrange(map_date, drought_lvl) %>% 
  mutate(test = lag(area_pct),
         value = ifelse(drought_lvl %in% c("D4","None"), 
                        area_pct, area_pct - test)) %>% 
  ggplot(aes(x = valid_start, y = value, fill = drought_lvl)) +
  geom_area(color = "white") +
  scale_fill_viridis_d(option = "A") +
  scale_y_continuous(labels = label_number(suffix = "%"),
                     expand = expansion(mult = c(0, 0))) +
  scale_x_date(date_labels = '%b',
               breaks = as.Date(c('2021/1/10','2021/2/10','2021/3/10',
                                  '2021/4/10', '2021/5/10','2021/6/10','2021/7/10')),
               expand = expansion(mult = c(0, 0))) +
  scale_fill_manual(values=c("#540804", "#81171b", "#ad2e24", "#c75146","#ea8c55","#ccd7e4")) +
  labs(x = NULL,
       y = "Percent of state (by area)",
       title = "\nUS, proportion of Pacific division in drought",
       subtitle = "By intensity category, % of total area, 2021-01-05 to 2021-07-13\n\n") +
  annotate("text", x = as.Date('2021/6/20'), y = 96.5, label = "Exceptional drought", 
           size = 3, color="white") +
  annotate("text", x = as.Date('2021/6/20'), y = 85, label = "Extreme drought",
           size = 3, color="white") +
  annotate("text", x = as.Date('2021/6/20'), y = 62, label = "Severe drought",
           size = 3, color="white") +
  annotate("text", x = as.Date('2021/6/20'), y = 48, label = "Moderate drought",
           size = 3, color="white") +
  annotate("text", x = as.Date('2021/6/20'), y = 31, label = "Abnormally dry",
           size = 3,color="white") +
  annotate("text", x = as.Date('2021/6/20'), y = 12, label = "None",
           size = 3) +
  theme(panel.grid.major = element_blank(),
        legend.position = "none",
        plot.title=element_text(face="bold",size=14),
        plot.subtitle=element_text(size=10, color="grey30"),
        axis.title=element_blank(),
        plot.margin=unit(c(0.5,1.5,0.5,1),"cm"))

map_pacific= usmap::plot_usmap(include = .pacific)
p5 |inset_element(map_pacific,
                    align_to = "full",
                    clip = FALSE,
                    on_top = TRUE,
                    ignore_tag = TRUE,
                    left = 0.67, 
                    bottom = 0.72, 
                    right = 1, 
                    top = 1)

Western US, pop_pct

drought1 <- drought %>% 
  mutate(pop_pct= ifelse(pop_pct>100,100,pop_pct)) %>%
  group_by(state_abb, valid_start) %>% 
  arrange(desc(drought_lvl)) %>% 
  # decumulate pop_pct and area_pct 
  mutate(area_pct1 = case_when(drought_lvl == "D4" ~ area_pct,
                                  drought_lvl != "None" ~ 
                                             area_pct - lag(area_pct),
                                  TRUE ~ area_pct),
         pop_pct1 = case_when(drought_lvl == "D4" ~ pop_pct,
                                  drought_lvl != "None" ~ 
                                             pop_pct - lag(pop_pct),
                                  TRUE ~ pop_pct),
         ) %>% 
  ungroup() %>%
  mutate(state_name = abbr2state(state_abb))
p6 = drought1 %>% filter(valid_end=="2021-07-19") %>%
  mutate(drought_lvl=factor(drought_lvl, levels=c("None","D0","D1","D2","D3","D4"))) %>%
  mutate(drought_lvl= recode(drought_lvl, 
                             D0="D0\nAbnormally Dry",
                             D1="D1\nModerate Drought",
                             D2="D2\nSevere Drought",
                             D3="D3\nExtreme Drought",
                             D4="D4\nExceptional Drought")) %>%
  filter(state_abb %in% .west_region) %>%
  filter(area_pct1>0) %>%
  ggplot(aes(y=fct_rev(state_name), x=pop_pct1, fill=fct_rev(drought_lvl))) + 
  geom_col(width=0.8) + 
  scale_fill_manual(values=c("#332a24","#997b66","#d08c60","#ffcb69","#f1dca7","grey")) + 
  scale_x_continuous(expand=c(0,0)) +
  theme(axis.text.y=element_text(margin=margin(r=10)),
        plot.margin=unit(c(0.5,1,0.5,1),"cm"),
        axis.title=element_blank(),
        legend.position="top",
        legend.title=element_blank(),
        legend.justification = "left",
        legend.margin=margin(5, .2, .2,-60),
        legend.key.width = unit(0.3, "cm"),
        legend.text=element_text(size=7),
        legend.spacing = unit(0.2, "cm"),
        plot.title.position = "plot",
        plot.title=element_markdown(lineheight = 1.3)) +
  guides(fill=guide_legend(ncol=6, byrow=T, reverse=T)) + 
  labs(title="<span style = 'font-size:11pt'><b>Western US, Proportion of population affected by drought<b></span><br><span style = 'font-size:10pt'>By intensity category, % of total population</span><br>
    <span style = 'font-size:9pt'>(July 13, 2021 to July 19, 2021)</span>")
  
map_west = plot_usmap(include = .west_region, size=0.3) 
p6 |inset_element(map_west ,
                    align_to = "full",
                    clip = FALSE,
                    on_top = TRUE,
                    ignore_tag = TRUE,
                    left = 0.75, 
                    bottom = 0.7, 
                    right = 1, 
                    top = 1)

LS0tCnRpdGxlOiAiVGlkeSBUdWVzZGF5IFdlZWsgMzAvMjAyMSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKKipEYXRhIHdyYW5nbGluZyBhbmQgdmlzdWFsaXphdGlvbiBleGVyY2lzZSoqCgpUaGlzIG5vdGVib29rIHVzZXMgWyNUaWR5VHVlc2RheV0oaHR0cHM6Ly9naXRodWIuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheSkgd2VlayAzMCBbVVMgRHJvdWdodHNdKGh0dHBzOi8vZ2l0aHViLmNvbS9yZm9yZGF0YXNjaWVuY2UvdGlkeXR1ZXNkYXkvYmxvYi9tYXN0ZXIvZGF0YS8yMDIxLzIwMjEtMDctMjAvcmVhZG1lLm1kKSwgZGF0YSBmcm9tIFtVLlMuIERyb3VnaHQgTW9uaXRvcl0oaHR0cHM6Ly9kcm91Z2h0bW9uaXRvci51bmwuZWR1L0RtRGF0YS9EYXRhRG93bmxvYWQuYXNweCkKCgpgYGB7cn0KIyBMb2FkIGxpYnJhcmllcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZW9mYWNldCkKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoZ2d0ZXh0KQpsaWJyYXJ5KHVzbWFwKQpsaWJyYXJ5KHVyYm5tYXByKQpsaWJyYXJ5KHBhdGNod29yaykKYGBgCgpgYGB7cn0KIyBJbXBvcnQgZGF0YQpkcm91Z2h0IDwtIHJlYWRyOjpyZWFkX2NzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9tYXN0ZXIvZGF0YS8yMDIxLzIwMjEtMDctMjAvZHJvdWdodC5jc3YnKQpgYGAKCiMjIyBDYXRlZ29yeSBEMCwgYXJlYV9wY3QsIHBvcF9wY3QKKiBzaGFyZWQgb24gW1R3aXR0ZXJdKGh0dHBzOi8vdHdpdHRlci5jb20vbGVlb2xuZXkzL3N0YXR1cy8xNDE3MzQ1MjgwOTA3OTExMTY4KQoKYGBge3J9CmRmMSA9IGRyb3VnaHQgJT4lIAogIGZpbHRlcih2YWxpZF9lbmQ9PSIyMDIxLTA3LTE5IikgJT4lCiAgZmlsdGVyKGRyb3VnaHRfbHZsPT0iRDAiKSAlPiUKICBzZWxlY3Qoc3RhdGVfYWJiLCAgYXJlYV9wY3QsICBwb3BfcGN0KSAlPiUKICByZW5hbWUoImxhbmQgYXJlYSI9YXJlYV9wY3QsIHBvcHVsYXRpb249cG9wX3BjdCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCFzdGF0ZV9hYmIpICU+JQogIG11dGF0ZSh2YWx1ZT12YWx1ZS8xMDApCmRmMSAKYGBgCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9RiwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9My43NX0KZ2dwbG90KGRmMSwgYWVzKGZjdF9yZXYobmFtZSksIHZhbHVlLCBmaWxsID0gZmN0X3JldihuYW1lKSkpICsKICBnZW9tX2NvbCh3aWR0aD0wLjgsIGFscGhhPTAuOSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgZmFjZXRfZ2VvKH4gc3RhdGVfYWJiLCBncmlkID0gInVzX3N0YXRlX2dyaWQyIikgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPWMoMCwwLjUsMSksIGxhYmVscz1jKDAsMC41LDEpLCBleHBhbmQ9YygwLDApKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiNmMjhmM2IiLCIjNTg4YjhiIikpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vcj1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9OCksCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5tYXJnaW49dW5pdChjKDAuNSwwLjUsMC41LDAuNSksImNtIiksCiAgICAgICAgcGxvdC50aXRsZT1lbGVtZW50X21hcmtkb3duKHNpemU9MTgsIG1hcmdpbj1tYXJnaW4oYj0xMCkpLAogICAgICAgIHBsb3Quc3VidGl0bGU9ZWxlbWVudF9tYXJrZG93bihzaXplPTEzLCBsaW5laGVpZ2h0ID0gMS4zNSksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpKSArIAogIGxhYnMoY2FwdGlvbj0iI1RpZHlUdWVzZGF5IHdlZWsgMzAgfCBEYXRhIGZyb20gVS5TLiBEcm91Z2h0IE1vbml0b3IiLAogICAgICAgdGl0bGU9IjxiPlUuUy4gRHJvdWdodCBMZXZlbCBEMDwvYj4gKEp1bHkgMTMsIDIwMjEgdG8gSnVseSAxOSwgMjAyMSkiLAogICAgICAgc3VidGl0bGU9IlByb3BvcnRpb24gb2YgPHNwYW4gc3R5bGUgPSAnY29sb3I6IzU4OGI4Yic+PGI+bGFuZCBhcmVhIChzcSBtaWxlcyk8L2I+PC9zcGFuPiBhbmQgPHNwYW4gc3R5bGUgPSAnY29sb3I6I2YyOGYzYic+PGI+cG9wdWxhdGlvbjwvYj48L3NwYW4+IG9mIHN0YXRlIGluIGRyb3VnaHQgbGV2ZWwgRDA8YnI+KCpEcm91Z2h0IGxldmVsIEQwIGNvcnJlc3BvbmRzIHRvIHNob3J0LXRlcm0gZHJ5bmVzcyB0aGF0IGlzIHR5cGljYWwgd2l0aCB0aGUgb25zZXQgb2YgZHJvdWdodCopPGJyPiIpCmBgYAoKIyMjIENhdGVnb3J5IEQ0LCBhcmVhX3BjdAoKYGBge3J9CmRmMiA9IGRyb3VnaHQgJT4lIGZpbHRlcihkcm91Z2h0X2x2bD09IkQ0IikgJT4lCiAgc2VsZWN0KHN0YXRlX2FiYiwgZHJvdWdodF9sdmwsIHZhbGlkX3N0YXJ0LCBhcmVhX3BjdCkgJT4lCiAgbXV0YXRlKGFyZWFfcGN0PWFyZWFfcGN0LzEwMCkKCnN1bW1hcnkoZGYyJHZhbGlkX3N0YXJ0KQpgYGAKCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9RiwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9My43NX0KZ2dwbG90KGRmMiwgYWVzKHZhbGlkX3N0YXJ0LCBhcmVhX3BjdCkpICsgCiAgZ2VvbV9saW5lKGNvbG9yPSJyZWQiLHNpemU9MC41KSArIAogIGZhY2V0X2dlbyh+IHN0YXRlX2FiYiwgZ3JpZCA9ICJ1c19zdGF0ZV9ncmlkMiIpICsgCiAgdGhlbWVfbWluaW1hbCgpICsKICBzY2FsZV94X2RhdGUoZXhwYW5kPWMoMCwwKSwgYnJlYWtzPWMobWluKGRmMiR2YWxpZF9zdGFydCksbWF4KGRmMiR2YWxpZF9zdGFydCkpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZD1jKDAsMCksIGJyZWFrcz1zZXEoMCwwLjgsMC40KSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsCiAgICAgICAgcGFuZWwuZ3JpZD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwLHNpemU9NiksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9NyksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kPWVsZW1lbnRfcmVjdChmaWxsPSIjZjhmOWZhIiwgY29sb3I9TkEpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0id2hpdGUiLCBjb2xvcj1OQSksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZD1lbGVtZW50X3JlY3QoZmlsbD0iI2VmZjFmMyIsIGNvbG9yPU5BKSwKICAgICAgICBwbG90Lm1hcmdpbj11bml0KGMoMC41LDAuNSwwLjUsMC41KSwiY20iKSwKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlPWVsZW1lbnRfbWFya2Rvd24oc2l6ZT0xOCwgbWFyZ2luPW1hcmdpbihiPTEwKSksCiAgICAgICAgcGxvdC5zdWJ0aXRsZT1lbGVtZW50X21hcmtkb3duKHNpemU9MTAuMyxsaW5laGVpZ2h0ID0gMS4zNSkpICsgCiAgbGFicyh0aXRsZT0iPGI+VS5TLiBEcm91Z2h0IExldmVsIEQ0IG92ZXIgMjAgeWVhcnM8L2I+IiwKICAgICAgIHN1YnRpdGxlPSJQcm9wb3J0aW9uIG9mIGxhbmQgYXJlYSAoaW4gc3EgbWlsZXMpIGJ5IHN0YXRlIGluIGRyb3VnaHQgY2F0ZWdvcnkgRDQgZnJvbSBKdWx5IDE3LCAyMDAxIHRvIEp1bHkgMTksIDIwMjEuIERyb3VnaHQgbGV2ZWwgRDQgY29ycmVzcG9uZHMgdG88YnI+YW4gYXJlYSBleHBlcmllbmNpbmcgZXhjZXB0aW9uYWwgYW5kIHdpZGVzcHJlYWQgY3JvcCBhbmQgcGFzdHVyZSBsb3NzZXMsIGZpcmUgcmlzaywgYW5kIHdhdGVyIHNob3J0YWdlcyB0aGF0IHJlc3VsdCBpbiB3YXRlciBlbWVyZ2VuY2llcy4gPGJyPiIpCmBgYAoKCiMjIyBBbGwgc3RhdGVzLCBtYXhpbXVtIGRyb3VnaHQgbGV2ZWwKCmBgYHtyfQpkZjMgPSBkcm91Z2h0ICU+JSAKICBmaWx0ZXIoZHJvdWdodF9sdmwhPSJOb25lIikgJT4lCiAgZmlsdGVyKHZhbGlkX2VuZD09IjIwMjEtMDctMTkiKSAlPiUKICBzZWxlY3QoZHJvdWdodF9sdmwsIHN0YXRlX2FiYiwgYXJlYV9wY3QpICU+JQogIGZpbHRlcihhcmVhX3BjdCE9MCkgJT4lCiAgZ3JvdXBfYnkoc3RhdGVfYWJiKSAlPiUKICBtdXRhdGUobWluX2FwID0gbWluKGFyZWFfcGN0KSkgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShjb25kID0gaWZlbHNlKG1pbl9hcD09YXJlYV9wY3QsMSwwKSkgJT4lCiAgZmlsdGVyKGNvbmQhPTApICU+JQogIHNlbGVjdCgtbWluX2FwLC1jb25kKSAlPiUKICByZW5hbWUoc3RhdGVfYWJidj1zdGF0ZV9hYmIpICU+JQogIG11dGF0ZShkcm91Z2h0X2x2bD0gcmVjb2RlKGRyb3VnaHRfbHZsLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEMD0iRDAgKEFibm9ybWFsbHkgRHJ5KSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRDE9IkQxIChNb2RlcmF0ZSBEcm91Z2h0KSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRDI9IkQyIChTZXZlcmUgRHJvdWdodCkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEQzPSJEMyAoRXh0cmVtZSBEcm91Z2h0KSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRDQ9IkQ0IChFeGNlcHRpb25hbCBEcm91Z2h0KSIpKSAKCnN0YXRlc19zZiA9IGdldF91cmJuX21hcCgic3RhdGVzIixzZj1UUlVFKQpkZjNiID0gc3RhdGVzX3NmICU+JSAKICBsZWZ0X2pvaW4oZGYzLCBieT0ic3RhdGVfYWJidiIpICU+JSAKICBtdXRhdGUoZHJvdWdodF9sdmw9cmVwbGFjZV9uYShkcm91Z2h0X2x2bCwiTm9uZSIpKQpgYGAKCgpgYGB7cn0KZGYzYiAlPiUKICBnZ3Bsb3QoKSArIAogIGdlb21fc2YoYWVzKGZpbGw9ZHJvdWdodF9sdmwpLGNvbG9yPSIjZmZmZmZmIixzaXplPTAuMjUpICsgCiAgZ2VvbV9zZl90ZXh0KGRhdGEgPSBkZjNiICU+JSBmaWx0ZXIoc3RhdGVfYWJidiAlaW4lIGRmMyRzdGF0ZV9hYmJ2KSwgCiAgICAgICAgICAgICAgICBhZXMobGFiZWwgPSBzdGF0ZV9hYmJ2KSwgc2l6ZSA9IDIpICsgCiAgY29vcmRfc2YoZGF0dW0gPSBOQSkgKyAKICAjc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gd2VzX3BhbGV0dGUoIlppc3NvdTEiKSwgbmEudmFsdWU9IiNlOGU4ZTgiKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjZjFkY2E3IiwiI2ZmY2I2OSIsIiNlOGFjNjUiLCIjZDA4YzYwIiwiIzk5N2I2NiIsIiNlOWVjZWYiKSkgKwogIHRoZW1lX3ZvaWQoKSArIAogIHRoZW1lKGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTcuNSksCiAgICAgICAgbGVnZW5kLnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTguNSksCiAgICAgICAgcGxvdC5zdWJ0aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMCwgZmFjZT0iYm9sZCIpLAogICAgICAgIHBsb3QubWFyZ2luPXVuaXQoYygwLjUsMSwwLjUsMSksImNtIikpICsgCiAgbGFicyhmaWxsPSJEcm91Z2h0IExldmVsIiwgc3VidGl0bGU9IlUuUy4gU3RhdGVzIGFuZCB0aGVpciBtYXhpbXVtIGRyb3VnaHQgbGV2ZWwgZm9yIHRoZSB3ZWVrIEp1bHkgMTMsIDIwMjEgdG8gSnVseSAxOSwgMjAyMVxuIikgCmBgYAoKCgojIyMgTmV2YWRhLCBhcmVhX3BjdAoqIHgtYXhpcyBsYWJlbHMgYW5kIHRpY2tzIHJlZmVyZW5jZTogW0B2YW1vc19hbGNhemFyXShodHRwczovL3R3aXR0ZXIuY29tL3ZhbW9zX2FsY2F6YXIvc3RhdHVzLzE0MTc1MzA0NjExMDcyMzY4NjYpICAKKiBpbnNldF9lbGVtZW50IHJlZmVyZW5jZTogW0BtYXh3ZWxjb10oaHR0cHM6Ly90d2l0dGVyLmNvbS9tYXh3ZWxjby9zdGF0dXMvMTQxNzQ1NDU1MTQyMzE5MzA5MSkKCmBgYHtyfQojIHRpYmJsZSBmb3IgeC1heGlzIHRleHQgdXNpbmcgd2l0aCBhbm5vdGF0aW9ucygpCnhfYXhpcyA9IHRpYmJsZSgKICB4ID0gYygKICAgICAgICBsdWJyaWRhdGU6OnltKCIyMDAyLzA3IiksCiAgICAgICAgbHVicmlkYXRlOjp5bSgiMjAwNi8wNyIpLAogICAgICAgIGx1YnJpZGF0ZTo6eW0oIjIwMTAvMDciKSwKICAgICAgICBsdWJyaWRhdGU6OnltKCIyMDE0LzA3IiksCiAgICAgICAgbHVicmlkYXRlOjp5bSgiMjAxOC8wNyIpLAogICAgICAgIGx1YnJpZGF0ZTo6eW0oIjIwMjEvMDEiKSksCiAgeSA9IC03LAogIGxhYmVsID0gYygiMjAwMiIsICIwNiIsICIxMCIsICIxNCIsICIxOCIsICIyMSIpCikKIyB0aWJibGUgZm9yIHh0aWNrcyB1c2luZyB3aXRoIGdlb21fbGluZXJhbmdlKCkKeF90aWNrcyA9IHRpYmJsZSgKICAgICAgICAgICAgeCA9IGMoc2VxLkRhdGUobHVicmlkYXRlOjp5bSgiMjAwMi8wMSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbHVicmlkYXRlOjp5bSgiMjAyMS8wMSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gIjEgeWVhciIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KGRyb3VnaHQkdmFsaWRfc3RhcnQpKSwKICAgICAgICAgICAgeW1heCA9IDAsCiAgICAgICAgICAgIHltaW4gPSBjKHJlcChjKDQsIDQsIDIuMywgMi4zKSwgNCksICA0LCA0LCAyLjMsIDQsIDIuMykgKiAtMSkKYGBgCgpgYGB7cn0KcGFsID0gYygiI2ZmZWJjNiIsIiNmZmIxMDAiLCIjZjE5NGI0IiwiI2Q5MDM2OCIsIiMwMDM4NDQiKQoKcGxvdGRhdGEgPSBkcm91Z2h0ICU+JSAKICBmaWx0ZXIoZHJvdWdodF9sdmwhPSJOb25lIiwKICAgICAgICAgYXJlYV9wY3QhPTAsIAogICAgICAgICBzdGF0ZV9hYmI9PSJOViIsCiAgICAgICAgIGx1YnJpZGF0ZTo6eWVhcih2YWxpZF9zdGFydCkgPiAyMDAxKSAlPiUKICBtdXRhdGUoZHJvdWdodF9sdmw9IHJlY29kZShkcm91Z2h0X2x2bCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRDA9IkQwIEFibm9ybWFsbHkgRHJ5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEMT0iRDEgTW9kZXJhdGUgRHJvdWdodCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRDI9IkQyIFNldmVyZSBEcm91Z2h0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEMz0iRDMgRXh0cmVtZSBEcm91Z2h0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEND0iRDQgRXhjZXB0aW9uYWwgRHJvdWdodCIpKSAgJT4lCiAgbXV0YXRlKGRhdGUgPSBsdWJyaWRhdGU6OnltKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUobHVicmlkYXRlOjp5ZWFyKHZhbGlkX3N0YXJ0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGx1YnJpZGF0ZTo6bW9udGgodmFsaWRfc3RhcnQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXAgPSAiLyIpKSkgCmBgYAoKYGBge3J9CiMgbWFpbiBwbG90CnA0ID0gcGxvdGRhdGEgJT4lCiAgZ2dwbG90KCkgKyAKICBnZW9tX2NvbChhZXMoeD12YWxpZF9zdGFydCwgeT1hcmVhX3BjdCwgY29sb3I9ZHJvdWdodF9sdmwsIGZpbGw9ZHJvdWdodF9sdmwpLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsgCiAgZ2VvbV9obGluZShjb2xvcj0iYmxhY2siLCB5aW50ZXJjZXB0PTAsIHNpemU9MC4zKSArCiAgY29vcmRfY2FydGVzaWFuKGNsaXAgPSAib2ZmIikgKwogICMgeC1heGlzCiAgYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwgeCA9IHhfYXhpcyR4LCB5ID0geF9heGlzJHksCiAgICAgICAgICAgbGFiZWwgPSB4X2F4aXMkbGFiZWwsIHNpemUgPSAyLjcsIGNvbG9yPSJncmV5MzAiKSArCiAgZ2VvbV9saW5lcmFuZ2UoZGF0YSA9IHhfdGlja3MsCiAgICAgICAgICAgICAgICAgYWVzKHggPSB4LCB5bWluID0geW1pbiwgeW1heCA9IHltYXgpLGNvbG9yPSJncmV5MzAiKSArCiAgIyBhbm5vdGF0ZQogICNnZW9tX2N1cnZlKGFlcyh4ID0gbHVicmlkYXRlOjp5bSgiMjAxNS8wMSIpLCB5ID0gODUsCiAgICAgICAgICAgICAgICAgI3hlbmQgPSBsdWJyaWRhdGU6OnltKCIyMDIwLzExIiksIHllbmQgPSAyMCksCiAgICAgICAgICAgICAjY3VydmF0dXJlID0gMC4yMCwKICAgICAgICAgICAgIyBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMC4wMywgIm5wYyIpKSkgKwogICNnZW9tX3RleHQoYWVzKHggPSBsdWJyaWRhdGU6OnltKCIyMDE1LzAxIiksIHkgPSA5NSwKICAgICAgICAgICAgICAgICNsYWJlbCA9ICJUaGUgZWZmZWN0IG9mXG5yZWNvcmQtbG93IHByZWNpcGl0YXRpb24gYW5kIGhpZ2hlciB0ZW1wZXJhdHVyZXMiKSwKICAgICAgICAgICAgI2ZvbnRmYWNlPSJpdGFsaWMiLCBzaXplID0gMi41KSArCiAgIyBjdXN0b21pemUgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPXBhbCwgZ3VpZGU9J25vbmUnKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPXBhbCkrCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTEwLCAxMDApLCBleHBhbmQgPSBjKDAsIDApLAogICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9ICJyaWdodCIpICsgCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemU9MTApICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55LnJpZ2h0ID1lbGVtZW50X3RleHQoY29sb3I9ImdyZXkyMCIsIG1hcmdpbj1tYXJnaW4obD0tMTUpLHNpemU9OCx2anVzdD0tLjcpLAogICAgICAgIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLCBzaXplPTExKSwKICAgICAgICBwbG90LnN1YnRpdGxlPWVsZW1lbnRfbWFya2Rvd24oY29sb3I9ImdyZXkyMCIsbGluZWhlaWdodCA9IDEuMyksCiAgICAgICAgbGVnZW5kLm1hcmdpbj1tYXJnaW4oNSwgLjIsIC4yLC01KSwKICAgICAgICBsZWdlbmQua2V5LndpZHRoID0gdW5pdCgwLjMsICJjbSIpLAogICAgICAgIGxlZ2VuZC5rZXkuaGVpZ2h0ID0gdW5pdCgwLjE4LCAiY20iKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTcuNSksCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAibGVmdCIsCiAgICAgICAgbGVnZW5kLnNwYWNpbmcueCA9IHVuaXQoMC4yLCAiY20iKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yPWVsZW1lbnRfbGluZShzaXplPS41KSwKICAgICAgICBwbG90Lm1hcmdpbj11bml0KGMoMC41LDEuNSwwLjUsMSksImNtIikpICsgCiAgZ3VpZGVzKGZpbGw9Z3VpZGVfbGVnZW5kKG5jb2w9MywgYnlyb3c9VCkpICsgCiAgbGFicyhjb2xvcj0iIiwgZmlsbD0iIiwKICAgICAgIHRpdGxlPSJQcm9wb3J0aW9uIG9mIE5ldmFkYSBpbiBkcm91Z2h0IiwgCiAgICAgICBzdWJ0aXRsZT0iPHNwYW4gc3R5bGUgPSAnZm9udC1zaXplOjEwcHQnPkJ5IGludGVuc2l0eSBjYXRlZ29yeSwgJSBvZiB0b3RhbCBhcmVhPC9zcGFuPjxicj4KICAgIDxzcGFuIHN0eWxlID0gJ2ZvbnQtc2l6ZTo5cHQnPkp1bHkgMTcsIDIwMDEgdG8gSnVseSAxOSwgMjAyMTwvc3Bhbj4iKQpgYGAKCgpgYGB7cn0KIyBtYXAgaW5zZXJ0IApzdGF0ZV9udiA9IHN0YXRlcG9wICU+JSBtdXRhdGUoY29sPWlmZWxzZShhYmJyPT0iTlYiLCIxIiwiMCIpKQoKbWFwX252ID0gcGxvdF91c21hcChkYXRhID0gc3RhdGVfbnYsIHZhbHVlcyA9ICJjb2wiLCBjb2xvciA9ICIjNDk1MDU3IixzaXplPTAuMykgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiLHBsb3QubWFyZ2luPXVuaXQoYygwLjUsMC41LDAuNSwwLjUpLCJjbSIpKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJ3aGl0ZSIsIiMyZWM0YjYiKSkKYGBgCgoKYGBge3J9CnA0IHxpbnNldF9lbGVtZW50KG1hcF9udiwKICAgICAgICAgICAgICAgICAgICBhbGlnbl90byA9ICJmdWxsIiwKICAgICAgICAgICAgICAgICAgICBjbGlwID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgb25fdG9wID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICBpZ25vcmVfdGFnID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gMC41NSwgCiAgICAgICAgICAgICAgICAgICAgYm90dG9tID0gMC43LCAKICAgICAgICAgICAgICAgICAgICByaWdodCA9IDEsIAogICAgICAgICAgICAgICAgICAgIHRvcCA9IDEpCmBgYAoKIyMjIFBhY2lmaWMgZGl2aXNpb24sIGFyZWFfcGN0CgoqIGFyZWEgcGxvdCBhbm5vdGF0aW9uIHJlZmVyZW5jZTogW0BNZWdoYW5NaGFsbF0oaHR0cHM6Ly90d2l0dGVyLmNvbS9NZWdoYW5NSGFsbC9zdGF0dXMvMTQxNzU1MzY2ODUzNTEwNzU4NykgCgpgYGB7cn0KIyBzdGF0ZXMgaW4gcGFjaWZpYyBkaXZpc2lvbgoucGFjaWZpYwpgYGAKCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0KIyBwYWNpZmljIGRpdmlzaW9uCnA1ID0gZHJvdWdodCAlPiUgCiAgZmlsdGVyKHN0YXRlX2FiYiAlaW4lIC5wYWNpZmljKSAlPiUKICBmaWx0ZXIobHVicmlkYXRlOjp5ZWFyKHZhbGlkX3N0YXJ0KSA9PSAyMDIxKSAlPiUgCiAgbXV0YXRlKGRyb3VnaHRfbHZsID0gZmN0X3JlbGV2ZWwoZHJvdWdodF9sdmwsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkQ0IiwiRDMiLCJEMiIsIkQxIiwiRDAiLCJOb25lIikpKSAlPiUgCiAgZ3JvdXBfYnkobWFwX2RhdGUsIHZhbGlkX3N0YXJ0LCBkcm91Z2h0X2x2bCkgJT4lCiAgc3VtbWFyaXNlKGFyZWFfcGN0PW1lYW4oYXJlYV9wY3QpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZShtYXBfZGF0ZSwgZHJvdWdodF9sdmwpICU+JSAKICBtdXRhdGUodGVzdCA9IGxhZyhhcmVhX3BjdCksCiAgICAgICAgIHZhbHVlID0gaWZlbHNlKGRyb3VnaHRfbHZsICVpbiUgYygiRDQiLCJOb25lIiksIAogICAgICAgICAgICAgICAgICAgICAgICBhcmVhX3BjdCwgYXJlYV9wY3QgLSB0ZXN0KSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHZhbGlkX3N0YXJ0LCB5ID0gdmFsdWUsIGZpbGwgPSBkcm91Z2h0X2x2bCkpICsKICBnZW9tX2FyZWEoY29sb3IgPSAid2hpdGUiKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Qob3B0aW9uID0gIkEiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGxhYmVsX251bWJlcihzdWZmaXggPSAiJSIpLAogICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24obXVsdCA9IGMoMCwgMCkpKSArCiAgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gJyViJywKICAgICAgICAgICAgICAgYnJlYWtzID0gYXMuRGF0ZShjKCcyMDIxLzEvMTAnLCcyMDIxLzIvMTAnLCcyMDIxLzMvMTAnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJzIwMjEvNC8xMCcsICcyMDIxLzUvMTAnLCcyMDIxLzYvMTAnLCcyMDIxLzcvMTAnKSksCiAgICAgICAgICAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLCAwKSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiIzU0MDgwNCIsICIjODExNzFiIiwgIiNhZDJlMjQiLCAiI2M3NTE0NiIsIiNlYThjNTUiLCIjY2NkN2U0IikpICsKICBsYWJzKHggPSBOVUxMLAogICAgICAgeSA9ICJQZXJjZW50IG9mIHN0YXRlIChieSBhcmVhKSIsCiAgICAgICB0aXRsZSA9ICJcblVTLCBwcm9wb3J0aW9uIG9mIFBhY2lmaWMgZGl2aXNpb24gaW4gZHJvdWdodCIsCiAgICAgICBzdWJ0aXRsZSA9ICJCeSBpbnRlbnNpdHkgY2F0ZWdvcnksICUgb2YgdG90YWwgYXJlYSwgMjAyMS0wMS0wNSB0byAyMDIxLTA3LTEzXG5cbiIpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSBhcy5EYXRlKCcyMDIxLzYvMjAnKSwgeSA9IDk2LjUsIGxhYmVsID0gIkV4Y2VwdGlvbmFsIGRyb3VnaHQiLCAKICAgICAgICAgICBzaXplID0gMywgY29sb3I9IndoaXRlIikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IGFzLkRhdGUoJzIwMjEvNi8yMCcpLCB5ID0gODUsIGxhYmVsID0gIkV4dHJlbWUgZHJvdWdodCIsCiAgICAgICAgICAgc2l6ZSA9IDMsIGNvbG9yPSJ3aGl0ZSIpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSBhcy5EYXRlKCcyMDIxLzYvMjAnKSwgeSA9IDYyLCBsYWJlbCA9ICJTZXZlcmUgZHJvdWdodCIsCiAgICAgICAgICAgc2l6ZSA9IDMsIGNvbG9yPSJ3aGl0ZSIpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSBhcy5EYXRlKCcyMDIxLzYvMjAnKSwgeSA9IDQ4LCBsYWJlbCA9ICJNb2RlcmF0ZSBkcm91Z2h0IiwKICAgICAgICAgICBzaXplID0gMywgY29sb3I9IndoaXRlIikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IGFzLkRhdGUoJzIwMjEvNi8yMCcpLCB5ID0gMzEsIGxhYmVsID0gIkFibm9ybWFsbHkgZHJ5IiwKICAgICAgICAgICBzaXplID0gMyxjb2xvcj0id2hpdGUiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gYXMuRGF0ZSgnMjAyMS82LzIwJyksIHkgPSAxMiwgbGFiZWwgPSAiTm9uZSIsCiAgICAgICAgICAgc2l6ZSA9IDMpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixzaXplPTE0KSwKICAgICAgICBwbG90LnN1YnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEwLCBjb2xvcj0iZ3JleTMwIiksCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5tYXJnaW49dW5pdChjKDAuNSwxLjUsMC41LDEpLCJjbSIpKQoKbWFwX3BhY2lmaWM9IHVzbWFwOjpwbG90X3VzbWFwKGluY2x1ZGUgPSAucGFjaWZpYykKYGBgCgpgYGB7cn0KcDUgfGluc2V0X2VsZW1lbnQobWFwX3BhY2lmaWMsCiAgICAgICAgICAgICAgICAgICAgYWxpZ25fdG8gPSAiZnVsbCIsCiAgICAgICAgICAgICAgICAgICAgY2xpcCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgIG9uX3RvcCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgaWdub3JlX3RhZyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgbGVmdCA9IDAuNjcsIAogICAgICAgICAgICAgICAgICAgIGJvdHRvbSA9IDAuNzIsIAogICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gMSwgCiAgICAgICAgICAgICAgICAgICAgdG9wID0gMSkKYGBgCgojIyMgV2VzdGVybiBVUywgcG9wX3BjdAoKYGBge3J9CmRyb3VnaHQxIDwtIGRyb3VnaHQgJT4lIAogIG11dGF0ZShwb3BfcGN0PSBpZmVsc2UocG9wX3BjdD4xMDAsMTAwLHBvcF9wY3QpKSAlPiUKICBncm91cF9ieShzdGF0ZV9hYmIsIHZhbGlkX3N0YXJ0KSAlPiUgCiAgYXJyYW5nZShkZXNjKGRyb3VnaHRfbHZsKSkgJT4lIAogICMgZGVjdW11bGF0ZSBwb3BfcGN0IGFuZCBhcmVhX3BjdCAKICBtdXRhdGUoYXJlYV9wY3QxID0gY2FzZV93aGVuKGRyb3VnaHRfbHZsID09ICJENCIgfiBhcmVhX3BjdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3VnaHRfbHZsICE9ICJOb25lIiB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmVhX3BjdCAtIGxhZyhhcmVhX3BjdCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gYXJlYV9wY3QpLAogICAgICAgICBwb3BfcGN0MSA9IGNhc2Vfd2hlbihkcm91Z2h0X2x2bCA9PSAiRDQiIH4gcG9wX3BjdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3VnaHRfbHZsICE9ICJOb25lIiB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3BfcGN0IC0gbGFnKHBvcF9wY3QpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IHBvcF9wY3QpLAogICAgICAgICApICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKHN0YXRlX25hbWUgPSBhYmJyMnN0YXRlKHN0YXRlX2FiYikpCmBgYAoKCmBgYHtyfQpwNiA9IGRyb3VnaHQxICU+JSBmaWx0ZXIodmFsaWRfZW5kPT0iMjAyMS0wNy0xOSIpICU+JQogIG11dGF0ZShkcm91Z2h0X2x2bD1mYWN0b3IoZHJvdWdodF9sdmwsIGxldmVscz1jKCJOb25lIiwiRDAiLCJEMSIsIkQyIiwiRDMiLCJENCIpKSkgJT4lCiAgbXV0YXRlKGRyb3VnaHRfbHZsPSByZWNvZGUoZHJvdWdodF9sdmwsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEQwPSJEMFxuQWJub3JtYWxseSBEcnkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEQxPSJEMVxuTW9kZXJhdGUgRHJvdWdodCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRDI9IkQyXG5TZXZlcmUgRHJvdWdodCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRDM9IkQzXG5FeHRyZW1lIERyb3VnaHQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIEQ0PSJENFxuRXhjZXB0aW9uYWwgRHJvdWdodCIpKSAlPiUKICBmaWx0ZXIoc3RhdGVfYWJiICVpbiUgLndlc3RfcmVnaW9uKSAlPiUKICBmaWx0ZXIoYXJlYV9wY3QxPjApICU+JQogIGdncGxvdChhZXMoeT1mY3RfcmV2KHN0YXRlX25hbWUpLCB4PXBvcF9wY3QxLCBmaWxsPWZjdF9yZXYoZHJvdWdodF9sdmwpKSkgKyAKICBnZW9tX2NvbCh3aWR0aD0wLjgpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiMzMzJhMjQiLCIjOTk3YjY2IiwiI2QwOGM2MCIsIiNmZmNiNjkiLCIjZjFkY2E3IiwiZ3JleSIpKSArIAogIHNjYWxlX3hfY29udGludW91cyhleHBhbmQ9YygwLDApKSArCiAgdGhlbWUoYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KG1hcmdpbj1tYXJnaW4ocj0xMCkpLAogICAgICAgIHBsb3QubWFyZ2luPXVuaXQoYygwLjUsMSwwLjUsMSksImNtIiksCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJ0b3AiLAogICAgICAgIGxlZ2VuZC50aXRsZT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAibGVmdCIsCiAgICAgICAgbGVnZW5kLm1hcmdpbj1tYXJnaW4oNSwgLjIsIC4yLC02MCksCiAgICAgICAgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQoMC4zLCAiY20iKSwKICAgICAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT03KSwKICAgICAgICBsZWdlbmQuc3BhY2luZyA9IHVuaXQoMC4yLCAiY20iKSwKICAgICAgICBwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiLAogICAgICAgIHBsb3QudGl0bGU9ZWxlbWVudF9tYXJrZG93bihsaW5laGVpZ2h0ID0gMS4zKSkgKwogIGd1aWRlcyhmaWxsPWd1aWRlX2xlZ2VuZChuY29sPTYsIGJ5cm93PVQsIHJldmVyc2U9VCkpICsgCiAgbGFicyh0aXRsZT0iPHNwYW4gc3R5bGUgPSAnZm9udC1zaXplOjExcHQnPjxiPldlc3Rlcm4gVVMsIFByb3BvcnRpb24gb2YgcG9wdWxhdGlvbiBhZmZlY3RlZCBieSBkcm91Z2h0PGI+PC9zcGFuPjxicj48c3BhbiBzdHlsZSA9ICdmb250LXNpemU6MTBwdCc+QnkgaW50ZW5zaXR5IGNhdGVnb3J5LCAlIG9mIHRvdGFsIHBvcHVsYXRpb248L3NwYW4+PGJyPgogICAgPHNwYW4gc3R5bGUgPSAnZm9udC1zaXplOjlwdCc+KEp1bHkgMTMsIDIwMjEgdG8gSnVseSAxOSwgMjAyMSk8L3NwYW4+IikKICAKbWFwX3dlc3QgPSBwbG90X3VzbWFwKGluY2x1ZGUgPSAud2VzdF9yZWdpb24sIHNpemU9MC4zKSAKYGBgCgpgYGB7cn0KcDYgfGluc2V0X2VsZW1lbnQobWFwX3dlc3QgLAogICAgICAgICAgICAgICAgICAgIGFsaWduX3RvID0gImZ1bGwiLAogICAgICAgICAgICAgICAgICAgIGNsaXAgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICBvbl90b3AgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgIGlnbm9yZV90YWcgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgIGxlZnQgPSAwLjc1LCAKICAgICAgICAgICAgICAgICAgICBib3R0b20gPSAwLjcsIAogICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gMSwgCiAgICAgICAgICAgICAgICAgICAgdG9wID0gMSkKYGBgCgo=