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=