This notebook uses #TidyTuesday week 32 Paralympic Medals, data from International Paralympic Committee.
# Load libraries
library(tidyverse)
library(scales)
library(ggtext)
library(countrycode)
library(janitor)
library(ggmosaic)
library(gt)
library(kableExtra)
library(formattable)
library(colorspace)
library(wesanderson)
library(glue)
theme_set(theme_minimal(base_size = 10))
theme_update(panel.grid.minor = element_blank(),
plot.margin=unit(c(.5,1.5,.5,1),"cm"),
panel.grid=element_line(size=.3),
plot.title.position = "plot",
plot.title=element_text(face="bold",size=11.5),
plot.subtitle=element_text(size=10, margin=margin(b=10)),
plot.caption=element_text(hjust=-0.85, color="grey20"))
# Suppress summarise info
options(dplyr.summarise.inform = FALSE)
# Import data
athletes <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-08-03/athletes.csv')
── Column specification ─────────────────────────────────────────────────────────────────────────────
cols(
gender = col_character(),
event = col_character(),
medal = col_character(),
athlete = col_character(),
abb = col_character(),
country = col_character(),
grp_id = col_double(),
type = col_character(),
year = col_double(),
guide = col_logical()
)
53 parsing failures.
row col expected actual file
7548 guide 1/0/T/F/TRUE/FALSE AVERY Jerome 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-08-03/athletes.csv'
7549 guide 1/0/T/F/TRUE/FALSE SILVA Celio 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-08-03/athletes.csv'
7550 guide 1/0/T/F/TRUE/FALSE TJIVIJU Even 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-08-03/athletes.csv'
7595 guide 1/0/T/F/TRUE/FALSE TJIVIJU Even 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-08-03/athletes.csv'
7596 guide 1/0/T/F/TRUE/FALSE SILVA Jonas 'https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-08-03/athletes.csv'
.... ..... .................. ............ ........................................................................................................
See problems(...) for more details.
# rename country names
athletes = athletes %>% mutate(country=case_when(country=="United States of America"~"USA",
country=="Great Britain" ~"UK",
TRUE~country))
summary(athletes$year)
Min. 1st Qu. Median Mean 3rd Qu. Max.
1980 1988 1996 1997 2008 2016
Proportion of gender by type of sport
athletes %>% filter(!is.na(gender)) %>%
group_by(type, gender) %>%
tally() %>%
mutate(prop=n/sum(n)) %>%
ggplot(aes(y=type, x=prop, fill=gender)) +
geom_col(width=.6, alpha=0.85) +
coord_cartesian(expand=F, clip="off") +
scale_fill_manual(values=c("#5A9599FF","#C71000FF","#FF6F00FF")) +
scale_x_continuous(labels=scales::percent_format()) +
scale_y_discrete(expand=c(0,0)) +
theme(axis.text.y=element_text(size=9, face="bold", color="grey50", margin=margin(r=3)),
axis.ticks.x=element_line(color="grey"),
axis.title=element_blank(),
axis.ticks.length=unit(.25, "cm"),
legend.position = "top",
legend.justification = "left",
legend.margin = margin(l=-5),
legend.key.height =unit(.5,"cm"),
legend.key.width =unit(.25,"cm")
) +
guides(fill = guide_legend(reverse=T)) +
labs(subtitle="Proportion of gender by type of sport, from 1980 to 2016",fill="", title="Paralympics Sport and Gender", caption="\n#TidyTuesday Week 32 | Data from International Paralympic Committee ")

Paralympics medals by year and type of sport
athletes %>% count(year, type) %>%
group_by(type) %>%
mutate(col=if_else(n==max(n),"#ee9b00","#4f5d75")) %>%
ggplot(aes(x=factor(year), y=n)) +
geom_bar(stat="identity", aes(fill=col), width=0.7) +
facet_wrap(~type, scales="free_y") +
scale_fill_identity() +
theme(axis.text.x=element_text(angle=90),
panel.grid=element_blank(),
axis.text=element_text(size=7),
strip.text=element_text(size=9.5, face="bold", color="grey50"),
axis.title=element_blank()
) +
labs(title="Paralympics medals by year and sport\n")

Sport type: event, medal, year count
# sport type: event, medal, year count
athletes %>%
group_by(type) %>%
summarise(medal_count = n(),
event_count = n_distinct(event),
year_count = n_distinct(year),
earliest_year = min(year),
latest_year = max(year)
) %>%
#arrange(desc(medal_count)) %>%
DT::datatable(rownames=FALSE,options = list(order = list(list(1, 'desc')),pageLength = 11))
Countries with most Paralympic medals (type)
# sport type, medal, country
type_df = athletes %>% filter(!is.na(country)) %>%
group_by(type, medal, country) %>%
summarise(medal_count=n()) %>%
arrange(type, medal, desc(medal_count)) %>%
slice(1) %>%
arrange(type, desc(medal_count)) %>%
mutate(medal = fct_inorder(medal))
# kable tile function reference: https://github.com/moriahtaylor1/tidy-tuesday/blob/main/2021_Week31/TT_Olympics.R
gold_tile <- function() {
formatter("span",
style = style(
display = "block",
padding = "5 5px",
"border-radius" = "10px",
"color" = csscolor("black"),
"background-color" = "#be9625"
)
)
}
silver_tile <- function() {
formatter("span",
style = style(
display = "block",
padding = "5 5px",
"border-radius" = "10px",
"color" = csscolor("black"),
"background-color" = "#9F9F9F"
)
)
}
bronze_tile <- function() {
formatter("span",
style = style(
display = "block",
padding = "5 5px",
"border-radius" = "10px",
"color" = csscolor("black"),
"background-color" = "#cd7f32"
)
)
}
# kable
type_df %>% select(-medal_count) %>%
pivot_wider(names_from=medal, values_from=country) %>%
rename(Sport = type) %>%
mutate(Sport=cell_spec(Sport,"html", color="black", align="left",bold=F),
Gold=gold_tile()(Gold),
Silver=silver_tile()(Silver),
Bronze=bronze_tile()(Bronze)) %>%
select(Sport, Gold, Silver, Bronze) %>%
kable(
"html", escape = F,align=c("lcccc"),
) %>%
kable_minimal() %>%
column_spec(2:4,width_min='4cm') %>%
add_header_above(c("Countries with most Paralympic medals" = 4), color="black", font_size=18)
Countries with most Paralympic medals |
| Sport |
Gold |
Silver |
Bronze |
| Archery |
Korea |
Italy |
Korea |
| Athletics |
USA |
China |
USA |
| Basketball |
Canada |
Australia |
USA |
| Fencing |
France |
Germany |
Italy |
| Rugby |
Australia |
Canada |
USA |
| Swimming |
Australia |
UK |
Spain |
| Table Tennis |
China |
France |
France |
| Volleyball |
Iran |
Bosnia and Herzegovina |
Egypt |
| Wheelchair Tennis |
China |
France |
France |
NA
Medal/event/unique country count, by year
# year: medals, events, country
athletes %>% group_by(year) %>%
summarise(medal_count = n(),
event_count = n_distinct(event),
country_count=n_distinct(country))
Medal count by year
# medal count by year
medal_df = athletes %>% group_by(year) %>%
summarise(medal = n(),
event = n_distinct(event))
athletes %>% group_by(year) %>%
summarise(event = n_distinct(event)) %>%
ggplot(aes(x=factor(year), y=event, fill=event)) +
geom_col(width=0.7) +
geom_text(aes(label=event),size=3.3, vjust=2, color="white") +
#geom_text(aes(y=20, label=year),,size=3, color="white") +
scale_fill_gradientn(colours = wes_palette("Zissou1", 10, type = "continuous")) +
theme(legend.position = "none",
panel.grid.major.x=element_blank(),
axis.title=element_text(size=8.5)) +
scale_y_continuous(expand=c(0,0)) +
labs(x="Year", y="Event count", title="Paralympics event count by year", subtitle="(1980 to 2016)")

Medals by country and year
# 10 countries with most medals
df10 = athletes %>% filter(!is.na(country)) %>% group_by(country) %>% tally(sort=T) %>% slice(1:10) %>%
mutate(labs=glue::glue("<b>{country}</b> ({n})")) %>%
mutate(labs=fct_inorder(labs))
# plot
athletes %>% filter(!is.na(country)) %>%
mutate(country=ifelse(country=="United States of America","USA",country)) %>%
filter(country %in% df10$country) %>%
mutate(country=fct_rev(fct_infreq(country))) %>%
group_by(year, country) %>% tally() %>%
mutate(col = if_else(n>50,"black","white")) %>%
ggplot(aes(x=factor(year), y=country, fill=n)) +
geom_tile(size=2, color="white") +
geom_text(aes(label=n, color=col), size=2.85) +
scale_color_identity() +
scale_fill_gradientn(colours = wes_palette("Zissou1", 10, type = "continuous")) +
#scale_fill_continuous_sequential(pal="BluYl") +
scale_y_discrete(labels=rev(df10$labs)) +
theme(axis.text.y=element_markdown(size=9, color="grey30"),
axis.text.x=element_text(size=8.5, color="grey30"),
panel.grid.major.x=element_blank(),
legend.position = "none",
axis.title=element_blank()
) +
labs(title= "Paralympics medals by country and year",
subtitle = "10 countries with the most medals from 1980 to 2016")

NA
Event and sport
# top 10 event/sport by count of medals
athletes %>% count(type, event, sort=T) %>% slice(1:10)
# event with highest medal from each sport
athletes %>%
count(type, event) %>%
group_by(type) %>%
arrange(type, desc(n)) %>%
slice(1)
Swimming medals
# countries with most swimming medals
df_swim = athletes %>%
filter(type=="Swimming", !is.na(country), country!="-") %>%
count(country, sort=T) %>%
slice(1:10)
# gender of swimming medalists from 10 countries with most swimming medals
athletes %>% filter(type=="Swimming", !is.na(country), country!="-") %>%
filter(country %in% df_swim$country) %>%
group_by(country, gender) %>% tally() %>%
ggplot(aes(y=reorder(country,n), x=n, fill=gender)) +
geom_col(alpha=0.95,width=.6)+
scale_fill_manual(values=c("#288994","#083346","#77C4D1")) +
scale_x_continuous(breaks=seq(0,150,25)) +
coord_cartesian(expand=F, clip="off") +
theme(axis.text.y=element_text(margin=margin(r=4)),
axis.title=element_blank(),
legend.position = "top",
legend.justification = "left",
legend.margin = margin(l=-5),
legend.key.height =unit(.5,"cm"),
legend.key.width =unit(.25,"cm"),
plot.subtitle=element_text(size=9.5, lineheight = 1.2),
panel.grid.major.y=element_blank(),
plot.background = element_rect(fill="#fdfff7",color=NA)
) +
guides(fill = guide_legend(reverse=T)) +
labs(fill="", title="Paralympics Swimming Medals", subtitle = "1980 to 2016\nTen countries with the most swimming medals")

NA
Rank plot
# top 10 countries with most medals
athletes1 <- athletes %>%
mutate(abb = case_when(abb == "URS" ~ "RUS",
abb == "FRG" ~ "GER",
TRUE ~ abb))
top_10 = athletes1 %>% count(abb,sort=T) %>% slice(1:10)
ranking = athletes1 %>%
filter(abb %in% top_10$abb) %>%
group_by(year, abb) %>% tally() %>%
arrange(year, -n) %>%
mutate(rank = dense_rank(desc(n)),
col= case_when(abb=="USA"~ "#ae2012",
abb=="GER" ~ "#0077b6",
abb=="AUS" ~ "#588157",
abb=="CHN" ~ "#f3722c",
TRUE ~ "grey")
)
# x axis labels
# reference: https://github.com/AbdoulMa/TidyTuesday/tree/main/2021_w32
olympics <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-07-27/olympics.csv')
── Column specification ─────────────────────────────────────────────────────────────────────────────
cols(
id = col_double(),
name = col_character(),
sex = col_character(),
age = col_double(),
height = col_double(),
weight = col_double(),
team = col_character(),
noc = col_character(),
games = col_character(),
year = col_double(),
season = col_character(),
city = col_character(),
sport = col_character(),
event = col_character(),
medal = col_character()
)
summer <- olympics %>%
filter(season == "Summer") %>%
distinct(year, city) %>%
mutate(edition = glue::glue('<span style = "color: grey35;">{year}</span> <br> <span style = "color: grey35;">{city}</span>')) %>%
filter(between(year, 1980,2016)) %>%
arrange(year)
ggplot(data = (ranking %>% filter(col=="grey")), aes(year, rank, fill=abb)) +
geom_line(alpha=.7, color="grey50") +
geom_point(aes(year, rank, fill=abb),shape=21, fill="white",size=6, color="grey50") +
geom_text(aes(year, rank, label=abb),size=1.7, color="grey30") +
# add highlights
geom_line(data = (ranking %>% filter(col!="grey")), aes(year, rank, color=col),size=0.8) +
geom_point(data = (ranking %>% filter(col!="grey")),aes(year, rank, color=col), size=6.5, show.legend=F) +
geom_text(data = (ranking %>% filter(col!="grey")),aes(label=abb), size=1.9, color="white") +
coord_cartesian(clip="off") +
scale_color_identity() +
scale_y_reverse(breaks=seq(1,10,1)) +
geom_richtext(data = summer, aes(x = year, y = 10.75, group = seq_along(year), label = edition),
fill = NA, label.color = NA, size = 2.4, lineheight = .9) +
theme(axis.text.x=element_blank(),
axis.title.x=element_text(size=8, face="bold", margin=margin(t=-4)),
axis.title.y=element_text(size=8, face="bold"),
panel.grid.major.x=element_blank(),
plot.subtitle=element_text(hjust=0.5, face="bold")) +
labs(y="Rank", x="Year and Host City",
subtitle="Which country won the most Paralympic medals? ")

Proportion of Paralympics medals by sport
athletes %>%
group_by(year, type) %>%
tally() %>%
mutate(prop=n/sum(n)) %>%
ggplot(aes(x=year, y=n, fill=fct_rev(type), label=fct_rev(type))) +
geom_stream(type="proportional") +
scale_fill_futurama() +
scale_x_continuous(limits=c(1980,2023), breaks=c(1980,1990, 2000, 2010, 2016)) +
theme(legend.position="none",
axis.title=element_blank(),
axis.text.x=element_text(margin=margin(t=-8)),
axis.text.y=element_text(margin=margin(r=-8)),
plot.title.position = "plot") +
annotate(geom= "text",x=2017, y=0.01, label="Archery",size=2.7, hjust=0,
color="#1A5354FF",fontface="bold") +
annotate(geom= "text",x=2017, y=0.15, label="Athletics",size=2.7,hjust=0,
color="#87d5ba",fontface="bold") +
annotate(geom= "text",x=2017, y=0.325, label="Basketball",size=2.7,hjust=0,
color="#3D3B25FF",fontface="bold") +
annotate(geom= "text",x=2017, y=0.365, label="Fencing",size=2.7,hjust=0,
color="#FF95A8FF",fontface="bold") +
annotate(geom= "text",x=2017, y=0.4, label="Powerlifting",size=2.7,hjust=0,
color="#84D7E1FF",fontface="bold") +
annotate(geom= "text",x=2017, y=0.435, label="Rugby",size=2.7,hjust=0,
color="#FF6348FF",fontface="bold") +
annotate(geom= "text",x=2017, y=0.6, label="Swimming",size=2.7,hjust=0,
color="#5A9599FF",fontface="bold") +
annotate(geom= "text",x=2017, y=0.75, label="Table Tennis",size=2.7,hjust=0,
color="#8A4198FF",fontface="bold") +
annotate(geom= "text",x=2017, y=0.84, label="Triathlon",size=2.7,hjust=0,
color="#008EA0FF",fontface="bold") +
annotate(geom= "text",x=2017, y=0.915, label="Volleyball",size=2.7,hjust=0,
color="#C71000FF",fontface="bold") +
annotate(geom= "text",x=2017, y=0.965, label="Wheelchair Tennis",size=2.7,hjust=0,
color="#FF6F00FF",fontface="bold") +
labs(subtitle = "Proportion of Paralympics medals by sport (1980-2016)")

NA
NA
LS0tCnRpdGxlOiAiVGlkeSBUdWVzZGF5IFdlZWsgMzIvMjAyMSIKZGF0ZTogIjIwMjEvMDgvMDMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClRoaXMgbm90ZWJvb2sgdXNlcyBbI1RpZHlUdWVzZGF5XShodHRwczovL2dpdGh1Yi5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5KSB3ZWVrIDMyIFtQYXJhbHltcGljIE1lZGFsc10oaHR0cHM6Ly9naXRodWIuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9ibG9iL21hc3Rlci9kYXRhLzIwMjEvMjAyMS0wOC0wMy9yZWFkbWUubWQpLApkYXRhIGZyb20gW0ludGVybmF0aW9uYWwgUGFyYWx5bXBpYyBDb21taXR0ZWVdKGh0dHBzOi8vZGIuaXBjLXNlcnZpY2VzLm9yZy9zZG1zL2hpcmEvd2ViL2luZGV4KS4KCmBgYHtyfQojIExvYWQgbGlicmFyaWVzIApsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoZ2d0ZXh0KQpsaWJyYXJ5KGNvdW50cnljb2RlKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoZ2dtb3NhaWMpCmxpYnJhcnkoZ3QpCmxpYnJhcnkoa2FibGVFeHRyYSkgCmxpYnJhcnkoZm9ybWF0dGFibGUpIApsaWJyYXJ5KGNvbG9yc3BhY2UpCmxpYnJhcnkod2VzYW5kZXJzb24pCmxpYnJhcnkoZ2x1ZSkKCnRoZW1lX3NldCh0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwKSkKdGhlbWVfdXBkYXRlKHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICBwbG90Lm1hcmdpbj11bml0KGMoLjUsMS41LC41LDEpLCJjbSIpLAogICAgICAgICAgICAgcGFuZWwuZ3JpZD1lbGVtZW50X2xpbmUoc2l6ZT0uMyksCiAgICAgICAgICAgICBwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiLAogICAgICAgICAgICAgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsc2l6ZT0xMS41KSwKICAgICAgICAgICAgIHBsb3Quc3VidGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTAsIG1hcmdpbj1tYXJnaW4oYj0xMCkpLAogICAgICAgICAgICAgcGxvdC5jYXB0aW9uPWVsZW1lbnRfdGV4dChoanVzdD0tMC44NSwgY29sb3I9ImdyZXkyMCIpKQoKIyBTdXBwcmVzcyBzdW1tYXJpc2UgaW5mbwpvcHRpb25zKGRwbHlyLnN1bW1hcmlzZS5pbmZvcm0gPSBGQUxTRSkKYGBgCgpgYGB7cn0KIyBJbXBvcnQgZGF0YQphdGhsZXRlcyA8LSByZWFkcjo6cmVhZF9jc3YoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9yZm9yZGF0YXNjaWVuY2UvdGlkeXR1ZXNkYXkvbWFzdGVyL2RhdGEvMjAyMS8yMDIxLTA4LTAzL2F0aGxldGVzLmNzdicpCmBgYApgYGB7cn0KIyByZW5hbWUgY291bnRyeSBuYW1lcwphdGhsZXRlcyA9IGF0aGxldGVzICU+JSBtdXRhdGUoY291bnRyeT1jYXNlX3doZW4oY291bnRyeT09IlVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSJ+IlVTQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cnk9PSJHcmVhdCBCcml0YWluIiB+IlVLIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRX5jb3VudHJ5KSkKYGBgCgpgYGB7cn0Kc3VtbWFyeShhdGhsZXRlcyR5ZWFyKQpgYGAKCiMjIyMgUHJvcG9ydGlvbiBvZiBnZW5kZXIgYnkgdHlwZSBvZiBzcG9ydAoqIHNoYXJlZCBvbiBbVHdpdHRlcl0oaHR0cHM6Ly90d2l0dGVyLmNvbS9sZWVvbG5leTMvc3RhdHVzLzE0MjIzOTkwNjkwMTY3OTcxODQpCgpgYGB7cn0KYXRobGV0ZXMgJT4lIGZpbHRlcighaXMubmEoZ2VuZGVyKSkgJT4lCiAgZ3JvdXBfYnkodHlwZSwgZ2VuZGVyKSAlPiUKICB0YWxseSgpICU+JSAKICBtdXRhdGUocHJvcD1uL3N1bShuKSkgJT4lCiAgZ2dwbG90KGFlcyh5PXR5cGUsIHg9cHJvcCwgZmlsbD1nZW5kZXIpKSArIAogIGdlb21fY29sKHdpZHRoPS42LCBhbHBoYT0wLjg1KSArIAogIGNvb3JkX2NhcnRlc2lhbihleHBhbmQ9RiwgY2xpcD0ib2ZmIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjNUE5NTk5RkYiLCIjQzcxMDAwRkYiLCIjRkY2RjAwRkYiKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50X2Zvcm1hdCgpKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShleHBhbmQ9YygwLDApKSArCiAgdGhlbWUoYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9OSwgZmFjZT0iYm9sZCIsIGNvbG9yPSJncmV5NTAiLCBtYXJnaW49bWFyZ2luKHI9MykpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2xpbmUoY29sb3I9ImdyZXkiKSwKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLmxlbmd0aD11bml0KC4yNSwgImNtIiksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAibGVmdCIsCiAgICAgICAgbGVnZW5kLm1hcmdpbiA9IG1hcmdpbihsPS01KSwKICAgICAgICBsZWdlbmQua2V5LmhlaWdodCA9dW5pdCguNSwiY20iKSwKICAgICAgICBsZWdlbmQua2V5LndpZHRoID11bml0KC4yNSwiY20iKQogICAgICAgICkgKyAKICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlPVQpKSArCiAgbGFicyhzdWJ0aXRsZT0iUHJvcG9ydGlvbiBvZiBnZW5kZXIgYnkgdHlwZSBvZiBzcG9ydCwgZnJvbSAxOTgwIHRvIDIwMTYiLGZpbGw9IiIsIHRpdGxlPSJQYXJhbHltcGljcyBTcG9ydCBhbmQgR2VuZGVyIiwgY2FwdGlvbj0iXG4jVGlkeVR1ZXNkYXkgV2VlayAzMiB8IERhdGEgZnJvbSBJbnRlcm5hdGlvbmFsIFBhcmFseW1waWMgQ29tbWl0dGVlICIpCmBgYAoKIyMjIyBQYXJhbHltcGljcyBtZWRhbHMgYnkgeWVhciBhbmQgdHlwZSBvZiBzcG9ydApgYGB7cn0KYXRobGV0ZXMgJT4lIGNvdW50KHllYXIsIHR5cGUpICU+JQogIGdyb3VwX2J5KHR5cGUpICU+JSAKICBtdXRhdGUoY29sPWlmX2Vsc2Uobj09bWF4KG4pLCIjZWU5YjAwIiwiIzRmNWQ3NSIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZmFjdG9yKHllYXIpLCB5PW4pKSArIAogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgYWVzKGZpbGw9Y29sKSwgd2lkdGg9MC43KSArCiAgZmFjZXRfd3JhcCh+dHlwZSwgc2NhbGVzPSJmcmVlX3kiKSArIAogIHNjYWxlX2ZpbGxfaWRlbnRpdHkoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwKSwKICAgICAgICBwYW5lbC5ncmlkPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9NyksCiAgICAgICAgc3RyaXAudGV4dD1lbGVtZW50X3RleHQoc2l6ZT05LjUsIGZhY2U9ImJvbGQiLCBjb2xvcj0iZ3JleTUwIiksCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCkKICAgICAgICApICsgCiAgbGFicyh0aXRsZT0iUGFyYWx5bXBpY3MgbWVkYWxzIGJ5IHllYXIgYW5kIHNwb3J0XG4iKQpgYGAKCiMjIyMgU3BvcnQgdHlwZTogZXZlbnQsIG1lZGFsLCB5ZWFyIGNvdW50CmBgYHtyfQojIHNwb3J0IHR5cGU6IGV2ZW50LCBtZWRhbCwgeWVhciBjb3VudAphdGhsZXRlcyAlPiUgCiAgZ3JvdXBfYnkodHlwZSkgJT4lIAogIHN1bW1hcmlzZShtZWRhbF9jb3VudCA9IG4oKSwKICAgICAgICAgICAgZXZlbnRfY291bnQgPSBuX2Rpc3RpbmN0KGV2ZW50KSwgCiAgICAgICAgICAgIHllYXJfY291bnQgPSBuX2Rpc3RpbmN0KHllYXIpLAogICAgICAgICAgICBlYXJsaWVzdF95ZWFyID0gbWluKHllYXIpLAogICAgICAgICAgICBsYXRlc3RfeWVhciA9IG1heCh5ZWFyKQogICAgICAgICAgICApICU+JQogICNhcnJhbmdlKGRlc2MobWVkYWxfY291bnQpKSAlPiUKICBEVDo6ZGF0YXRhYmxlKHJvd25hbWVzPUZBTFNFLG9wdGlvbnMgPSBsaXN0KG9yZGVyID0gbGlzdChsaXN0KDEsICdkZXNjJykpLHBhZ2VMZW5ndGggPSAxMSkpIApgYGAKCiMjIyMgQ291bnRyaWVzIHdpdGggbW9zdCBQYXJhbHltcGljIG1lZGFscyAodHlwZSkKYGBge3J9CiMgc3BvcnQgdHlwZSwgbWVkYWwsIGNvdW50cnkKdHlwZV9kZiA9IGF0aGxldGVzICU+JSBmaWx0ZXIoIWlzLm5hKGNvdW50cnkpKSAlPiUKICBncm91cF9ieSh0eXBlLCBtZWRhbCwgY291bnRyeSkgJT4lIAogIHN1bW1hcmlzZShtZWRhbF9jb3VudD1uKCkpICU+JQogIGFycmFuZ2UodHlwZSwgbWVkYWwsIGRlc2MobWVkYWxfY291bnQpKSAlPiUKICBzbGljZSgxKSAlPiUKICBhcnJhbmdlKHR5cGUsIGRlc2MobWVkYWxfY291bnQpKSAlPiUKICBtdXRhdGUobWVkYWwgPSBmY3RfaW5vcmRlcihtZWRhbCkpCgojIGthYmxlIHRpbGUgZnVuY3Rpb24gcmVmZXJlbmNlOiBodHRwczovL2dpdGh1Yi5jb20vbW9yaWFodGF5bG9yMS90aWR5LXR1ZXNkYXkvYmxvYi9tYWluLzIwMjFfV2VlazMxL1RUX09seW1waWNzLlIKZ29sZF90aWxlIDwtIGZ1bmN0aW9uKCkgewogIGZvcm1hdHRlcigic3BhbiIsIAogICAgICAgICAgICBzdHlsZSA9IHN0eWxlKAogICAgICAgICAgICAgIGRpc3BsYXkgPSAiYmxvY2siLAogICAgICAgICAgICAgIHBhZGRpbmcgPSAiNSA1cHgiLAogICAgICAgICAgICAgICJib3JkZXItcmFkaXVzIiA9ICIxMHB4IiwKICAgICAgICAgICAgICAiY29sb3IiID0gY3NzY29sb3IoImJsYWNrIiksCiAgICAgICAgICAgICAgImJhY2tncm91bmQtY29sb3IiID0gIiNiZTk2MjUiCiAgICAgICAgICAgICkKICApCn0KCnNpbHZlcl90aWxlIDwtIGZ1bmN0aW9uKCkgewogICAgZm9ybWF0dGVyKCJzcGFuIiwgCiAgICAgICAgICAgIHN0eWxlID0gc3R5bGUoCiAgICAgICAgICAgICAgZGlzcGxheSA9ICJibG9jayIsCiAgICAgICAgICAgICAgcGFkZGluZyA9ICI1IDVweCIsCiAgICAgICAgICAgICAgImJvcmRlci1yYWRpdXMiID0gIjEwcHgiLAogICAgICAgICAgICAgICJjb2xvciIgPSBjc3Njb2xvcigiYmxhY2siKSwKICAgICAgICAgICAgICAiYmFja2dyb3VuZC1jb2xvciIgPSAiIzlGOUY5RiIKICAgICAgICAgICAgKQogICkKfQoKYnJvbnplX3RpbGUgPC0gZnVuY3Rpb24oKSB7CiAgZm9ybWF0dGVyKCJzcGFuIiwgCiAgICAgICAgICAgIHN0eWxlID0gc3R5bGUoCiAgICAgICAgICAgICAgZGlzcGxheSA9ICJibG9jayIsCiAgICAgICAgICAgICAgcGFkZGluZyA9ICI1IDVweCIsCiAgICAgICAgICAgICAgImJvcmRlci1yYWRpdXMiID0gIjEwcHgiLAogICAgICAgICAgICAgICJjb2xvciIgPSBjc3Njb2xvcigiYmxhY2siKSwKICAgICAgICAgICAgICAiYmFja2dyb3VuZC1jb2xvciIgPSAiI2NkN2YzMiIKICAgICAgICAgICAgKQogICkKfQoKIyBrYWJsZSAKdHlwZV9kZiAlPiUgc2VsZWN0KC1tZWRhbF9jb3VudCkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbT1tZWRhbCwgdmFsdWVzX2Zyb209Y291bnRyeSkgJT4lCiAgcmVuYW1lKFNwb3J0ID0gdHlwZSkgJT4lCiAgbXV0YXRlKFNwb3J0PWNlbGxfc3BlYyhTcG9ydCwiaHRtbCIsIGNvbG9yPSJibGFjayIsIGFsaWduPSJsZWZ0Iixib2xkPUYpLAogICAgICAgICBHb2xkPWdvbGRfdGlsZSgpKEdvbGQpLAogICAgICAgICBTaWx2ZXI9c2lsdmVyX3RpbGUoKShTaWx2ZXIpLAogICAgICAgICBCcm9uemU9YnJvbnplX3RpbGUoKShCcm9uemUpKSAlPiUKICBzZWxlY3QoU3BvcnQsIEdvbGQsIFNpbHZlciwgQnJvbnplKSAlPiUKICBrYWJsZSgKICAgICJodG1sIiwgZXNjYXBlID0gRixhbGlnbj1jKCJsY2NjYyIpLAogICkgJT4lCiAga2FibGVfbWluaW1hbCgpICU+JQogIGNvbHVtbl9zcGVjKDI6NCx3aWR0aF9taW49JzRjbScpICU+JQogIGFkZF9oZWFkZXJfYWJvdmUoYygiQ291bnRyaWVzIHdpdGggbW9zdCBQYXJhbHltcGljIG1lZGFscyIgPSA0KSwgY29sb3I9ImJsYWNrIiwgZm9udF9zaXplPTE4KQoKYGBgCgojIyMjIE1lZGFsL2V2ZW50L3VuaXF1ZSBjb3VudHJ5IGNvdW50LCBieSB5ZWFyCmBgYHtyfQojIHllYXI6IG1lZGFscywgZXZlbnRzLCBjb3VudHJ5IAphdGhsZXRlcyAlPiUgZ3JvdXBfYnkoeWVhcikgJT4lIAogIHN1bW1hcmlzZShtZWRhbF9jb3VudCA9IG4oKSwKICAgICAgICAgICAgZXZlbnRfY291bnQgPSBuX2Rpc3RpbmN0KGV2ZW50KSwKICAgICAgICAgICAgY291bnRyeV9jb3VudD1uX2Rpc3RpbmN0KGNvdW50cnkpKQpgYGAKIyMjIyBNZWRhbCBjb3VudCBieSB5ZWFyCmBgYHtyfQojIG1lZGFsIGNvdW50IGJ5IHllYXIgCm1lZGFsX2RmID0gYXRobGV0ZXMgJT4lIGdyb3VwX2J5KHllYXIpICU+JSAKICBzdW1tYXJpc2UobWVkYWwgPSBuKCksCiAgICAgICAgICAgIGV2ZW50ID0gbl9kaXN0aW5jdChldmVudCkpIAoKYXRobGV0ZXMgJT4lIGdyb3VwX2J5KHllYXIpICU+JSAKICBzdW1tYXJpc2UoZXZlbnQgPSBuX2Rpc3RpbmN0KGV2ZW50KSkgJT4lCiAgZ2dwbG90KGFlcyh4PWZhY3Rvcih5ZWFyKSwgeT1ldmVudCwgZmlsbD1ldmVudCkpICsgCiAgZ2VvbV9jb2wod2lkdGg9MC43KSArIAogIGdlb21fdGV4dChhZXMobGFiZWw9ZXZlbnQpLHNpemU9My4zLCB2anVzdD0yLCBjb2xvcj0id2hpdGUiKSArIAogICNnZW9tX3RleHQoYWVzKHk9MjAsIGxhYmVsPXllYXIpLCxzaXplPTMsIGNvbG9yPSJ3aGl0ZSIpICsgCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3VycyA9IHdlc19wYWxldHRlKCJaaXNzb3UxIiwgMTAsIHR5cGUgPSAiY29udGludW91cyIpKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OC41KSkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQ9YygwLDApKSArIAogIGxhYnMoeD0iWWVhciIsIHk9IkV2ZW50IGNvdW50IiwgdGl0bGU9IlBhcmFseW1waWNzIGV2ZW50IGNvdW50IGJ5IHllYXIiLCBzdWJ0aXRsZT0iKDE5ODAgdG8gMjAxNikiKQpgYGAKCgoKCiMjIyMgTWVkYWxzIGJ5IGNvdW50cnkgYW5kIHllYXIKYGBge3J9CiMgMTAgY291bnRyaWVzIHdpdGggbW9zdCBtZWRhbHMgCmRmMTAgPSBhdGhsZXRlcyAlPiUgZmlsdGVyKCFpcy5uYShjb3VudHJ5KSkgJT4lIGdyb3VwX2J5KGNvdW50cnkpICU+JSB0YWxseShzb3J0PVQpICU+JSBzbGljZSgxOjEwKSAlPiUKICBtdXRhdGUobGFicz1nbHVlOjpnbHVlKCI8Yj57Y291bnRyeX08L2I+ICh7bn0pIikpICU+JQogIG11dGF0ZShsYWJzPWZjdF9pbm9yZGVyKGxhYnMpKQoKIyBwbG90CmF0aGxldGVzICU+JSBmaWx0ZXIoIWlzLm5hKGNvdW50cnkpKSAlPiUKICBtdXRhdGUoY291bnRyeT1pZmVsc2UoY291bnRyeT09IlVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSIsIlVTQSIsY291bnRyeSkpICU+JQogIGZpbHRlcihjb3VudHJ5ICVpbiUgZGYxMCRjb3VudHJ5KSAlPiUgCiAgbXV0YXRlKGNvdW50cnk9ZmN0X3JldihmY3RfaW5mcmVxKGNvdW50cnkpKSkgJT4lCiAgZ3JvdXBfYnkoeWVhciwgY291bnRyeSkgJT4lIHRhbGx5KCkgJT4lCiAgbXV0YXRlKGNvbCA9IGlmX2Vsc2Uobj41MCwiYmxhY2siLCJ3aGl0ZSIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZmFjdG9yKHllYXIpLCB5PWNvdW50cnksIGZpbGw9bikpICsgCiAgZ2VvbV90aWxlKHNpemU9MiwgY29sb3I9IndoaXRlIikgKwogIGdlb21fdGV4dChhZXMobGFiZWw9biwgY29sb3I9Y29sKSwgc2l6ZT0yLjg1KSArCiAgc2NhbGVfY29sb3JfaWRlbnRpdHkoKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudG4oY29sb3VycyA9IHdlc19wYWxldHRlKCJaaXNzb3UxIiwgMTAsIHR5cGUgPSAiY29udGludW91cyIpKSArCiAgI3NjYWxlX2ZpbGxfY29udGludW91c19zZXF1ZW50aWFsKHBhbD0iQmx1WWwiKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShsYWJlbHM9cmV2KGRmMTAkbGFicykpICsgCiAgdGhlbWUoYXhpcy50ZXh0Lnk9ZWxlbWVudF9tYXJrZG93bihzaXplPTksIGNvbG9yPSJncmV5MzAiKSwKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQoc2l6ZT04LjUsIGNvbG9yPSJncmV5MzAiKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKQogICAgICAgICkgKyAKICBsYWJzKHRpdGxlPSAiUGFyYWx5bXBpY3MgbWVkYWxzIGJ5IGNvdW50cnkgYW5kIHllYXIiLAogICAgICAgc3VidGl0bGUgPSAiMTAgY291bnRyaWVzIHdpdGggdGhlIG1vc3QgbWVkYWxzIGZyb20gMTk4MCB0byAyMDE2IikKICAKYGBgCgojIyMjIEV2ZW50IGFuZCBzcG9ydApgYGB7cn0KIyB0b3AgMTAgZXZlbnQvc3BvcnQgYnkgY291bnQgb2YgbWVkYWxzCmF0aGxldGVzICU+JSBjb3VudCh0eXBlLCBldmVudCwgc29ydD1UKSAlPiUgc2xpY2UoMToxMCkKYGBgCmBgYHtyfQojIGV2ZW50IHdpdGggaGlnaGVzdCBtZWRhbCBmcm9tIGVhY2ggc3BvcnQKYXRobGV0ZXMgJT4lIAogIGNvdW50KHR5cGUsIGV2ZW50KSAlPiUKICBncm91cF9ieSh0eXBlKSAlPiUKICBhcnJhbmdlKHR5cGUsIGRlc2MobikpICU+JQogIHNsaWNlKDEpCmBgYAoKIyMjIyBTd2ltbWluZyBtZWRhbHMgCmBgYHtyfQojIGNvdW50cmllcyB3aXRoIG1vc3Qgc3dpbW1pbmcgbWVkYWxzIApkZl9zd2ltID0gYXRobGV0ZXMgJT4lIAogIGZpbHRlcih0eXBlPT0iU3dpbW1pbmciLCAhaXMubmEoY291bnRyeSksIGNvdW50cnkhPSItIikgJT4lCiAgY291bnQoY291bnRyeSwgc29ydD1UKSAlPiUgCiAgc2xpY2UoMToxMCkKCiMgZ2VuZGVyIG9mIHN3aW1taW5nIG1lZGFsaXN0cyBmcm9tIDEwIGNvdW50cmllcyB3aXRoIG1vc3Qgc3dpbW1pbmcgbWVkYWxzCmF0aGxldGVzICU+JSBmaWx0ZXIodHlwZT09IlN3aW1taW5nIiwgIWlzLm5hKGNvdW50cnkpLCBjb3VudHJ5IT0iLSIpICU+JQogIGZpbHRlcihjb3VudHJ5ICVpbiUgZGZfc3dpbSRjb3VudHJ5KSAlPiUKICBncm91cF9ieShjb3VudHJ5LCBnZW5kZXIpICU+JSB0YWxseSgpICU+JQogIGdncGxvdChhZXMoeT1yZW9yZGVyKGNvdW50cnksbiksIHg9biwgZmlsbD1nZW5kZXIpKSArIAogIGdlb21fY29sKGFscGhhPTAuOTUsd2lkdGg9LjYpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjMjg4OTk0IiwiIzA4MzM0NiIsIiM3N0M0RDEiKSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDE1MCwyNSkpICsKICBjb29yZF9jYXJ0ZXNpYW4oZXhwYW5kPUYsIGNsaXA9Im9mZiIpICsKICB0aGVtZShheGlzLnRleHQueT1lbGVtZW50X3RleHQobWFyZ2luPW1hcmdpbihyPTQpKSwKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwKICAgICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9ICJsZWZ0IiwKICAgICAgICBsZWdlbmQubWFyZ2luID0gbWFyZ2luKGw9LTUpLAogICAgICAgIGxlZ2VuZC5rZXkuaGVpZ2h0ID11bml0KC41LCJjbSIpLAogICAgICAgIGxlZ2VuZC5rZXkud2lkdGggPXVuaXQoLjI1LCJjbSIpLAogICAgICAgIHBsb3Quc3VidGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OS41LCBsaW5laGVpZ2h0ID0gMS4yKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSIjZmRmZmY3Iixjb2xvcj1OQSkKICAgICAgICApICsgCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZT1UKSkgKyAKICBsYWJzKGZpbGw9IiIsIHRpdGxlPSJQYXJhbHltcGljcyBTd2ltbWluZyBNZWRhbHMiLCBzdWJ0aXRsZSA9ICIxOTgwIHRvIDIwMTZcblRlbiBjb3VudHJpZXMgd2l0aCB0aGUgbW9zdCBzd2ltbWluZyBtZWRhbHMiKQogIApgYGAKCgoKIyMjIFJhbmsgcGxvdAoqIHRvcCAxMCBjb3VudHJpZXMgd2l0aCBtb3N0IG1lZGFscwoqIHJlZmVyZW5jZTogaHR0cHM6Ly90d2l0dGVyLmNvbS9pc3NhX21hZGppZC9zdGF0dXMvMTQyMjYzNTIzMjk5NDQ2Mzc0NgoKYGBge3J9CiMgdG9wIDEwIGNvdW50cmllcyB3aXRoIG1vc3QgbWVkYWxzCmF0aGxldGVzMSA8LSBhdGhsZXRlcyAlPiUgCiAgbXV0YXRlKGFiYiA9IGNhc2Vfd2hlbihhYmIgPT0gIlVSUyIgfiAiUlVTIiwKICAgICAgICAgICAgICAgICAgICAgICAgIGFiYiA9PSAiRlJHIiB+ICJHRVIiLAogICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IGFiYikpCnRvcF8xMCA9IGF0aGxldGVzMSAlPiUgY291bnQoYWJiLHNvcnQ9VCkgJT4lIHNsaWNlKDE6MTApCgpyYW5raW5nID0gYXRobGV0ZXMxICU+JSAKICBmaWx0ZXIoYWJiICVpbiUgdG9wXzEwJGFiYikgJT4lCiAgZ3JvdXBfYnkoeWVhciwgYWJiKSAlPiUgdGFsbHkoKSAlPiUKICBhcnJhbmdlKHllYXIsIC1uKSAlPiUKICBtdXRhdGUocmFuayA9IGRlbnNlX3JhbmsoZGVzYyhuKSksCiAgICAgICAgIGNvbD0gY2FzZV93aGVuKGFiYj09IlVTQSJ+ICIjYWUyMDEyIiwKICAgICAgICAgICAgICAgICAgICAgICAgYWJiPT0iR0VSIiB+ICIjMDA3N2I2IiwKICAgICAgICAgICAgICAgICAgICAgICAgYWJiPT0iQVVTIiB+ICIjNTg4MTU3IiwKICAgICAgICAgICAgICAgICAgICAgICAgYWJiPT0iQ0hOIiB+ICIjZjM3MjJjIiwKICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJncmV5IikKICAgICAgICAgKQoKIyB4IGF4aXMgbGFiZWxzCiMgcmVmZXJlbmNlOiBodHRwczovL2dpdGh1Yi5jb20vQWJkb3VsTWEvVGlkeVR1ZXNkYXkvdHJlZS9tYWluLzIwMjFfdzMyCm9seW1waWNzIDwtIHJlYWRyOjpyZWFkX2NzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9tYXN0ZXIvZGF0YS8yMDIxLzIwMjEtMDctMjcvb2x5bXBpY3MuY3N2JykKc3VtbWVyIDwtIG9seW1waWNzICU+JSAKICBmaWx0ZXIoc2Vhc29uID09ICJTdW1tZXIiKSAlPiUgCiAgZGlzdGluY3QoeWVhciwgY2l0eSkgJT4lIAogIG11dGF0ZShlZGl0aW9uID0gZ2x1ZTo6Z2x1ZSgnPHNwYW4gc3R5bGUgPSAiY29sb3I6IGdyZXkzNTsiPnt5ZWFyfTwvc3Bhbj4gPGJyPiA8c3BhbiBzdHlsZSA9ICJjb2xvcjogZ3JleTM1OyI+e2NpdHl9PC9zcGFuPicpKSAlPiUgCiAgZmlsdGVyKGJldHdlZW4oeWVhciwgMTk4MCwyMDE2KSkgJT4lIAogIGFycmFuZ2UoeWVhcikKYGBgCgoKYGBge3J9CmdncGxvdChkYXRhID0gKHJhbmtpbmcgJT4lIGZpbHRlcihjb2w9PSJncmV5IikpLCBhZXMoeWVhciwgcmFuaywgZmlsbD1hYmIpKSArCiAgZ2VvbV9saW5lKGFscGhhPS43LCBjb2xvcj0iZ3JleTUwIikgKyAKICBnZW9tX3BvaW50KGFlcyh5ZWFyLCByYW5rLCBmaWxsPWFiYiksc2hhcGU9MjEsIGZpbGw9IndoaXRlIixzaXplPTYsIGNvbG9yPSJncmV5NTAiKSArIAogIGdlb21fdGV4dChhZXMoeWVhciwgcmFuaywgbGFiZWw9YWJiKSxzaXplPTEuNywgY29sb3I9ImdyZXkzMCIpICsgCiAgIyBhZGQgaGlnaGxpZ2h0cwogIGdlb21fbGluZShkYXRhID0gKHJhbmtpbmcgJT4lIGZpbHRlcihjb2whPSJncmV5IikpLCBhZXMoeWVhciwgcmFuaywgY29sb3I9Y29sKSxzaXplPTAuOCkgKyAKICBnZW9tX3BvaW50KGRhdGEgPSAocmFua2luZyAlPiUgZmlsdGVyKGNvbCE9ImdyZXkiKSksYWVzKHllYXIsIHJhbmssIGNvbG9yPWNvbCksIHNpemU9Ni41LCBzaG93LmxlZ2VuZD1GKSArCiAgZ2VvbV90ZXh0KGRhdGEgPSAocmFua2luZyAlPiUgZmlsdGVyKGNvbCE9ImdyZXkiKSksYWVzKGxhYmVsPWFiYiksIHNpemU9MS45LCBjb2xvcj0id2hpdGUiKSArCiAgY29vcmRfY2FydGVzaWFuKGNsaXA9Im9mZiIpICsKICBzY2FsZV9jb2xvcl9pZGVudGl0eSgpICsKICBzY2FsZV95X3JldmVyc2UoYnJlYWtzPXNlcSgxLDEwLDEpKSArIAogIGdlb21fcmljaHRleHQoZGF0YSA9IHN1bW1lciwgYWVzKHggPSB5ZWFyLCB5ID0gMTAuNzUsIGdyb3VwID0gc2VxX2Fsb25nKHllYXIpLCBsYWJlbCA9IGVkaXRpb24pLAogICAgICAgICAgICAgICAgZmlsbCA9IE5BLCBsYWJlbC5jb2xvciA9IE5BLCBzaXplID0gMi40LCBsaW5laGVpZ2h0ID0gLjkpICsgCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoc2l6ZT04LCBmYWNlPSJib2xkIiwgbWFyZ2luPW1hcmdpbih0PS00KSksCiAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfdGV4dChzaXplPTgsIGZhY2U9ImJvbGQiKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3Quc3VidGl0bGU9ZWxlbWVudF90ZXh0KGhqdXN0PTAuNSwgZmFjZT0iYm9sZCIpKSArIAogIGxhYnMoeT0iUmFuayIsIHg9IlllYXIgYW5kIEhvc3QgQ2l0eSIsIAogICAgICAgc3VidGl0bGU9IldoaWNoIGNvdW50cnkgd29uIHRoZSBtb3N0IFBhcmFseW1waWMgbWVkYWxzPyAiKQpgYGAKCiMjIyMgUHJvcG9ydGlvbiBvZiBQYXJhbHltcGljcyBtZWRhbHMgYnkgc3BvcnQKYGBge3J9CmF0aGxldGVzICU+JSAKICBncm91cF9ieSh5ZWFyLCB0eXBlKSAlPiUgCiAgdGFsbHkoKSAlPiUKICBtdXRhdGUocHJvcD1uL3N1bShuKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXIsIHk9biwgZmlsbD1mY3RfcmV2KHR5cGUpLCBsYWJlbD1mY3RfcmV2KHR5cGUpKSkgKyAKICBnZW9tX3N0cmVhbSh0eXBlPSJwcm9wb3J0aW9uYWwiKSArIAogIHNjYWxlX2ZpbGxfZnV0dXJhbWEoKSArIAogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygxOTgwLDIwMjMpLCBicmVha3M9YygxOTgwLDE5OTAsIDIwMDAsIDIwMTAsIDIwMTYpKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiwKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X3RleHQobWFyZ2luPW1hcmdpbih0PS04KSksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KG1hcmdpbj1tYXJnaW4ocj0tOCkpLAogICAgICAgIHBsb3QudGl0bGUucG9zaXRpb24gPSAicGxvdCIpICsgCiAgYW5ub3RhdGUoZ2VvbT0gInRleHQiLHg9MjAxNywgeT0wLjAxLCBsYWJlbD0iQXJjaGVyeSIsc2l6ZT0yLjcsIGhqdXN0PTAsCiAgICAgICAgICAgY29sb3I9IiMxQTUzNTRGRiIsZm9udGZhY2U9ImJvbGQiKSArIAogIGFubm90YXRlKGdlb209ICJ0ZXh0Iix4PTIwMTcsIHk9MC4xNSwgbGFiZWw9IkF0aGxldGljcyIsc2l6ZT0yLjcsaGp1c3Q9MCwKICAgICAgICAgICBjb2xvcj0iIzg3ZDViYSIsZm9udGZhY2U9ImJvbGQiKSArCiAgYW5ub3RhdGUoZ2VvbT0gInRleHQiLHg9MjAxNywgeT0wLjMyNSwgbGFiZWw9IkJhc2tldGJhbGwiLHNpemU9Mi43LGhqdXN0PTAsCiAgICAgICAgICAgY29sb3I9IiMzRDNCMjVGRiIsZm9udGZhY2U9ImJvbGQiKSArIAogIGFubm90YXRlKGdlb209ICJ0ZXh0Iix4PTIwMTcsIHk9MC4zNjUsIGxhYmVsPSJGZW5jaW5nIixzaXplPTIuNyxoanVzdD0wLAogICAgICAgICAgIGNvbG9yPSIjRkY5NUE4RkYiLGZvbnRmYWNlPSJib2xkIikgKwogIGFubm90YXRlKGdlb209ICJ0ZXh0Iix4PTIwMTcsIHk9MC40LCBsYWJlbD0iUG93ZXJsaWZ0aW5nIixzaXplPTIuNyxoanVzdD0wLAogICAgICAgICAgIGNvbG9yPSIjODREN0UxRkYiLGZvbnRmYWNlPSJib2xkIikgKwogIGFubm90YXRlKGdlb209ICJ0ZXh0Iix4PTIwMTcsIHk9MC40MzUsIGxhYmVsPSJSdWdieSIsc2l6ZT0yLjcsaGp1c3Q9MCwKICAgICAgICAgICBjb2xvcj0iI0ZGNjM0OEZGIixmb250ZmFjZT0iYm9sZCIpICsKICBhbm5vdGF0ZShnZW9tPSAidGV4dCIseD0yMDE3LCB5PTAuNiwgbGFiZWw9IlN3aW1taW5nIixzaXplPTIuNyxoanVzdD0wLAogICAgICAgICAgIGNvbG9yPSIjNUE5NTk5RkYiLGZvbnRmYWNlPSJib2xkIikgKwogIGFubm90YXRlKGdlb209ICJ0ZXh0Iix4PTIwMTcsIHk9MC43NSwgbGFiZWw9IlRhYmxlIFRlbm5pcyIsc2l6ZT0yLjcsaGp1c3Q9MCwKICAgICAgICAgICBjb2xvcj0iIzhBNDE5OEZGIixmb250ZmFjZT0iYm9sZCIpICsKICBhbm5vdGF0ZShnZW9tPSAidGV4dCIseD0yMDE3LCB5PTAuODQsIGxhYmVsPSJUcmlhdGhsb24iLHNpemU9Mi43LGhqdXN0PTAsCiAgICAgICAgICAgY29sb3I9IiMwMDhFQTBGRiIsZm9udGZhY2U9ImJvbGQiKSArCiAgYW5ub3RhdGUoZ2VvbT0gInRleHQiLHg9MjAxNywgeT0wLjkxNSwgbGFiZWw9IlZvbGxleWJhbGwiLHNpemU9Mi43LGhqdXN0PTAsIAogICAgICAgICAgIGNvbG9yPSIjQzcxMDAwRkYiLGZvbnRmYWNlPSJib2xkIikgKwogIGFubm90YXRlKGdlb209ICJ0ZXh0Iix4PTIwMTcsIHk9MC45NjUsIGxhYmVsPSJXaGVlbGNoYWlyIFRlbm5pcyIsc2l6ZT0yLjcsaGp1c3Q9MCwgCiAgICAgICAgICAgY29sb3I9IiNGRjZGMDBGRiIsZm9udGZhY2U9ImJvbGQiKSArIAogIGxhYnMoc3VidGl0bGUgPSAiUHJvcG9ydGlvbiBvZiBQYXJhbHltcGljcyBtZWRhbHMgYnkgc3BvcnQgKDE5ODAtMjAxNikiKQogIAogIApgYGAKCgoK