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