Tidy Tuesday Week 22 Mario Kart 64 World Records, data from Mario Kart World Records
# Load libaries
library(tidyverse)
library(ggtext)
library(ggpubr)
library(ggstatsplot)
library(gt)
library(ggsci)
library(wesanderson)
theme_set(theme_minimal())
# Import data
records <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-05-25/records.csv')
── Column specification ──────────────────────────────────────────────────────────────────────────────────
cols(
track = col_character(),
type = col_character(),
shortcut = col_character(),
player = col_character(),
system_played = col_character(),
date = col_date(format = ""),
time_period = col_character(),
time = col_double(),
record_duration = col_double()
)
drivers <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-05-25/drivers.csv')
── Column specification ──────────────────────────────────────────────────────────────────────────────────
cols(
position = col_double(),
player = col_character(),
total = col_double(),
year = col_double(),
records = col_double(),
nation = col_character()
)
# Which Mario Kart Track Is The Fastest?
# shared on [Twitter](https://twitter.com/leeolney3/status/1396980461134614528/photo/1)
table1 = records %>%
group_by(track, type, shortcut) %>%
summarise(time_min=min(time)) %>%
ungroup() %>%
mutate(type_sc= ifelse(shortcut=="Yes", paste(type, "with","Shortcut"),type))
# dot plot
table1 %>%
ggplot(aes(x=fct_rev(fct_reorder(track, time_min, .fun='min')), y=time_min,
color=factor(type_sc, levels=c("Three Lap with Shortcut",
"Single Lap with Shortcut",
"Single Lap",
"Three Lap")))) +
geom_line(aes(group=track), color="grey",size=2,alpha=0.4) +
#geom_point(position=position_dodge(0.4),size=2.2) +
geom_point(position = position_jitterdodge(dodge.width = 0.5, jitter.height = 0.5),size=2.7) +
theme(legend.position="top",
legend.justification = "left",
plot.title.position = "plot",
plot.title=element_text(hjust=0.5, face="bold",size=18),
plot.margin=ggplot2::margin(1,1,0.5,1,"cm"),
axis.title.x=element_markdown(size=10.5),
axis.title.y=element_markdown(size=10.5)) +
labs(color="", x="**Track**",y="**Minimum Time** (in seconds)<br>",
title="Which Mario Kart Track Is The Fastest?",
caption="Tidy Tuesday Week 22 | Data from Mario Kart World Records") +
scale_color_manual(values=c("#f95738","#ffa62b","#0091ad","#43B047")) +
coord_flip()

# For how many tracks have shortcuts been discovered?
records %>%
count(track, shortcut) %>%
count(shortcut)
# For which track did the world record improve the most?
records %>%
group_by(track) %>%
summarise(min_time = min(time), max_time=max(time), improved=max_time-min_time) %>%
arrange(desc(improved)) %>%
mutate(improved_pct= round(improved/max_time*100,3)) %>%
arrange(desc(improved_pct)) %>% slice(1)
# On which track the shortcut saves the most time
table2 = records %>%
group_by(track, type, shortcut) %>%
summarise(time=mean(time)) %>%
pivot_wider(names_from = shortcut,values_from=time) %>%
filter(!is.na(Yes)) %>%
mutate(time_saved=No-Yes) %>%
arrange(desc(time_saved))
# time saved by race type
by(table2$time_saved, table2$type, summary) #no difference in Single lap with and without shortcut
table2$type: Single Lap
Min. 1st Qu. Median Mean 3rd Qu. Max.
0 0 0 0 0 0
-------------------------------------------------------------------------------
table2$type: Three Lap
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.516 38.977 59.911 78.928 102.340 242.578
# On which track the shortcut saves the most time
# dot plot: three lap
table4 = records %>%
group_by(track, type, shortcut) %>%
summarise(time=mean(time)) %>%
filter(type=="Three Lap") %>%
filter(track!="Banshee Boardwalk",track!="Bowser's Castle",
track!="Koopa Troopa Beach",track!="Moo Moo Farm") %>%
mutate(time_saved=lag(time)-time) %>%
mutate(pct = round(time_saved/lag(time),3))
table5 = table4 %>% filter(shortcut=="Yes")
table5 %>%
ggplot(aes(y=reorder(track,pct), x=time)) +
geom_text(aes(label=paste0("-",scales::percent(pct,accuracy=0.1L))),size=2.9, hjust=1.2, color="#3C5488FF") +
geom_point(data=table4, aes(color=shortcut),size=2,show.legend = F) +
geom_line(data=table4, aes(group=track), alpha=0.3,size=1) +
scale_x_continuous(limits=c(0,370)) +
theme(panel.grid.major.x=element_blank(),
panel.grid.minor.x=element_blank(),
axis.title.x=element_markdown(size=10),
axis.title.y=element_markdown(size=10),
plot.title.position = "plot",
plot.subtitle=element_markdown(size=10)) +
labs(x="**Average time** (in seconds)",
y="**Track**",
title="On which track the shortcut saves the most time for 3-lap?",
subtitle="Percentage is expressed as (<span style = 'color:#E64B35FF'>No Shortcut</span> - <span style = 'color:#3C5488FF'>With Shortcut</span>) / <span style = 'color:#E64B35FF'>No Shortcut</span><br>") +
scale_color_manual(values=c("#E64B35FF","#3C5488FF"))

# On which track the shortcut saves the most time
# highlighted slope chart: three lap
table2 %>%
filter(type=="Three Lap") %>%
pivot_longer(No:Yes) %>%
mutate(name=ifelse(name=="No","No Shortcut","With Shortcut")) %>%
mutate(value=round(value,1), time_saved=round(time_saved,1)) -> table3
table3 %>%
ggplot(aes(x=name, y=value, group=track)) +
geom_line(aes(color=I(ifelse(track=="Wario Stadium", '#E64B35FF', '#8491b4FF')))) +
geom_point(aes(color=I(ifelse(track=="Wario Stadium", '#E64B35FF', '#8491b4FF')))) +
theme(legend.position = "none") +
scale_x_discrete(position="top") +
geom_text(data= table3 %>% filter(track=="Wario Stadium") %>% filter(name=="No Shortcut"),
aes(label=paste0(value,"s")), size=3, color="#E64B35FF", hjust=1.2) +
geom_text(data= table3 %>% filter(track=="Wario Stadium") %>% filter(name=="With Shortcut"),
aes(label=paste0(value,"s")), size=3, color="#E64B35FF", hjust=-0.5) +
geom_text(aes(x="No Shortcut",y=265.2, label="Wario Stadium"),size=3, color="#E64B35FF",hjust=1.7) +
theme(axis.text.x=element_text(face="bold",size=10, color="black"),
axis.title.y=element_markdown(size=10),
plot.title.position = "plot") +
labs(x="",y="**Average time saved** (in seconds)",
title="On which track the shortcut saves the most time for 3-lap?")

# When were shortcuts discovered?
records %>% group_by(track, shortcut) %>%
summarise(sc_dis=min(date)) %>%
filter(shortcut=="Yes") %>%
mutate(shortcut=ifelse(shortcut=="Yes",1,"")) %>%
ggplot(aes(y=shortcut,x=sc_dis)) +
geom_segment(aes(x=min(sc_dis), xend=max(sc_dis), y=shortcut, yend=shortcut)) +
geom_point(aes(color=factor(sc_dis)),size=6,show.legend=F, shape=18) +
geom_text(aes(label=sc_dis), size=3, vjust=3, color="black") +
geom_text(aes(x=min(sc_dis),label="Luigi Raceway",y=1.03), size=3, color="#E64B35FF") +
geom_text(aes(x=as.Date(c("1997-03-07")),label="Rainbow Road\nYoshi Valley",y=1.048),
size=3, color="#00A087FF", hjust=0,nudge_x=-1.6) +
geom_text(aes(x=as.Date(c("1997-03-10")),label="Choco Mountain\nD.K.'s Jungle Parkway\nFrappe Snowland\nKalimari Desert\nMario Raceway\nRoyal Raceway\nSherbet Land\nToad's Turnpike\nWario Stadium",y=1.125), size=3,hjust=0,nudge_x=-1.1, color="#3C5488FF") +
scale_y_continuous(limits=c(0.85,1.35)) +
scale_x_date(labels=scales::date_format("%d-%m-%Y"), limits=as.Date(c('1997-02-13','1997-03-14')),
expand = c(0, 0), breaks = "1 week") +
theme(axis.text=element_blank(),
axis.title = element_blank(),
panel.grid.minor=element_blank(),
panel.grid.major.y=element_blank(),
panel.grid.major.x=element_line(size=0.35)) +
geom_bracket(xmin=as.Date(c("1997-02-16")), xmax=as.Date(c("1997-03-07")), y.position=1.1,
label="19 days", label.size=3) +
geom_bracket(xmin=as.Date(c("1997-03-07")), xmax=as.Date(c("1997-03-10")), y.position=1.25,
label="3 days", label.size=3) +
scale_color_manual(values=c("#E64B35FF","#00A087FF","#3C5488FF")) +
labs(title="When were shortcuts discovered?")

NA
# Which is the longest standing world record?
records %>% arrange(desc(record_duration)) %>% slice(1)
# Distribution of record duration across race types
ggbetweenstats(data=records, x=type, y=record_duration,
title="Distribution of record duration across race types",
type="np",
plotgrid.args=list(nrow=1),
messages=FALSE,
results.subtitle = FALSE,
xlab="Type",
ylab="Record duration",
point.args = list(position = ggplot2::position_jitterdodge(dodge.width = 0.6),
alpha= 0.4, size = 2, stroke = 0)) +
ggplot2::scale_color_manual(values=c("#4DBBD5FF","#00A087FF"))

# How did the world records develop over time?
# count of world records over time
#records %>%
#mutate(type_sc= ifelse(shortcut=="Yes", paste(type, "with","Shortcut"),type)) %>%
#group_by(date) %>% tally() %>% ggscatterhist(x="date",y="n", size=1, margin.plot="density")
# How did the world records develop over time?
# count of records over time by type and shortcut
records %>%
mutate(type_sc= ifelse(shortcut=="Yes", paste(type, "with","Shortcut"),type)) %>%
group_by(date) %>% count(type_sc) %>%
ggplot(aes(x=date, y=n, color=type_sc)) +
geom_point(size=1,show.legend=F, alpha=0.9) +
facet_wrap(~type_sc,ncol=2) +
scale_color_npg() +
theme(panel.grid.minor = element_blank(),
axis.title.x=element_markdown(size=10),
axis.title.y=element_markdown(size=10),
plot.title.position="plot",
strip.text = element_text(face="bold",color="#343a40")
) +
labs(x="**Date**",y="**Record count**", title="Records over time by lap type and shortcut")

# Which is the longest standing world record?
records %>% filter(record_duration==max(record_duration))
# Who is the player with the most world records?
drivers %>% distinct(player, total) %>% slice(1)
# Who are recent players? (players in 2021)
records %>% filter(date>"2020-12-31") %>%
group_by(player) %>%
summarise(latest_date=max(date), record_count=length(player))
# Unique and new player count across the years
# reference:https://jack-davison.github.io/posts/2021-05-25-exploring-fun-questions-tidytuesday-2021-week-22-mario-kart-64/
d1 = drivers %>% distinct(player, year, records) %>%
drop_na() %>% group_by(year) %>% summarise(unique_player=n_distinct(player))
d2 = drivers %>% distinct(player, year, records) %>%
drop_na() %>% group_by(player) %>%
filter(year==min(year)) %>%
ungroup() %>% count(year) %>% rename(new_player=n)
d1 %>% left_join(d2) %>% replace(is.na(.), 0) %>%
pivot_longer(unique_player:new_player) %>%
mutate(name=ifelse(name=="unique_player","Unique Player","New Player")) %>%
ggplot(aes(x=year, y=value, fill=value)) +
geom_col() +
facet_grid(~fct_rev(name)) +
scale_x_continuous(
breaks = seq(min(drivers$year), max(drivers$year), 4)) +
scale_fill_gradientn(colours = wes_palette("Zissou1", 25, type = "continuous")) +
theme(panel.grid.minor = element_blank(),
axis.title.x=element_markdown(size=10),
axis.title.y=element_markdown(size=10),
plot.title.position="plot",
legend.position="none",
strip.text=element_text(face="bold",size=10),
axis.text.x = element_text(vjust =5)) +
labs(x="**Year**",y="**Count**",
title="Unique and new player count across the years\n")

# Which is the fastest track?
records %>% group_by(type,track) %>% summarise(min_time=min(time)) %>%
pivot_wider(names_from=type, values_from=min_time) %>%
rename(Track=track) %>%
ungroup() %>%
DT::datatable(rownames=FALSE,options = list(order = list(list(1, 'asc'))))
# Maximum Record by track and lap type
# reference: https://twitter.com/Juanma_MN/status/1397249648931360768/photo/1
records %>% group_by(track, type) %>% summarise(max_duration=max(record_duration)) %>%
ggplot(aes(y=reorder(track,max_duration, max), x=max_duration, color=type)) +
geom_point(size=2) +
geom_line(aes(group=track), color="grey") +
scale_color_manual(values=c("#E64B35FF","#3C5488FF")) +
theme(axis.title.x=element_markdown(size=10),
axis.title.y=element_markdown(size=10),
plot.title = element_markdown(),
plot.title.position="plot",
legend.position="none") +
labs(y="**Track**",x="**Maximum record duration** (in days)",
title="Maximum record duration of <span style = 'color:#E64B35FF'>Single Lap</span> and <span style = 'color:#3C5488FF'>Three Lap</span> races, by Track",
subtitle="")

LS0tCnRpdGxlOiAiVGlkeSBUdWVzZGF5IDIyLzIwMjEiCm91dHB1dDogaHRtbF9ub3RlYm9vawpkYXRlOiAiMjAyMS8wNS8yNiIKLS0tCgpbVGlkeSBUdWVzZGF5XShodHRwczovL2dpdGh1Yi5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5KSBXZWVrIDIyIFtNYXJpbyBLYXJ0IDY0IFdvcmxkIFJlY29yZHNdKGh0dHBzOi8vZ2l0aHViLmNvbS9yZm9yZGF0YXNjaWVuY2UvdGlkeXR1ZXNkYXkvYmxvYi9tYXN0ZXIvZGF0YS8yMDIxLzIwMjEtMDUtMjUvcmVhZG1lLm1kKSwgZGF0YSBmcm9tIFtNYXJpbyBLYXJ0IFdvcmxkIFJlY29yZHNdKGh0dHBzOi8vbWt3cnMuY29tLykgCgoKYGBge3J9CiMgTG9hZCBsaWJyYXJpZXMgCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGdndGV4dCkKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkoZ2dzdGF0c3Bsb3QpCmxpYnJhcnkoZ3QpCmxpYnJhcnkoZ2dzY2kpCmxpYnJhcnkod2VzYW5kZXJzb24pCgp0aGVtZV9zZXQodGhlbWVfbWluaW1hbCgpKQpgYGAKCmBgYHtyfQojIEltcG9ydCBkYXRhCnJlY29yZHMgPC0gcmVhZHI6OnJlYWRfY3N2KCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L21hc3Rlci9kYXRhLzIwMjEvMjAyMS0wNS0yNS9yZWNvcmRzLmNzdicpCmRyaXZlcnMgPC0gcmVhZHI6OnJlYWRfY3N2KCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L21hc3Rlci9kYXRhLzIwMjEvMjAyMS0wNS0yNS9kcml2ZXJzLmNzdicpCmBgYAoKCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9RiwgZmlnLmhlaWdodD0zLjUsIGZpZy53aWR0aD00LjV9CiMgV2hpY2ggTWFyaW8gS2FydCBUcmFjayBJcyBUaGUgRmFzdGVzdD8KIyBzaGFyZWQgb24gW1R3aXR0ZXJdKGh0dHBzOi8vdHdpdHRlci5jb20vbGVlb2xuZXkzL3N0YXR1cy8xMzk2OTgwNDYxMTM0NjE0NTI4L3Bob3RvLzEpCgp0YWJsZTEgPSByZWNvcmRzICU+JSAKICBncm91cF9ieSh0cmFjaywgdHlwZSwgc2hvcnRjdXQpICU+JQogIHN1bW1hcmlzZSh0aW1lX21pbj1taW4odGltZSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUodHlwZV9zYz0gaWZlbHNlKHNob3J0Y3V0PT0iWWVzIiwgcGFzdGUodHlwZSwgIndpdGgiLCJTaG9ydGN1dCIpLHR5cGUpKQoKIyBkb3QgcGxvdAp0YWJsZTEgJT4lIAogIGdncGxvdChhZXMoeD1mY3RfcmV2KGZjdF9yZW9yZGVyKHRyYWNrLCB0aW1lX21pbiwgLmZ1bj0nbWluJykpLCB5PXRpbWVfbWluLCAKICAgICAgICAgICAgIGNvbG9yPWZhY3Rvcih0eXBlX3NjLCBsZXZlbHM9YygiVGhyZWUgTGFwIHdpdGggU2hvcnRjdXQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTaW5nbGUgTGFwIHdpdGggU2hvcnRjdXQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTaW5nbGUgTGFwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGhyZWUgTGFwIikpKSkgKwogIGdlb21fbGluZShhZXMoZ3JvdXA9dHJhY2spLCBjb2xvcj0iZ3JleSIsc2l6ZT0yLGFscGhhPTAuNCkgKwogICNnZW9tX3BvaW50KHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKDAuNCksc2l6ZT0yLjIpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyZG9kZ2UoZG9kZ2Uud2lkdGggPSAwLjUsIGppdHRlci5oZWlnaHQgPSAwLjUpLHNpemU9Mi43KSAgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIiwKICAgICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9ICJsZWZ0IiwKICAgICAgICBwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiLAogICAgICAgIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KGhqdXN0PTAuNSwgZmFjZT0iYm9sZCIsc2l6ZT0xOCksCiAgICAgICAgcGxvdC5tYXJnaW49Z2dwbG90Mjo6bWFyZ2luKDEsMSwwLjUsMSwiY20iKSwKICAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9tYXJrZG93bihzaXplPTEwLjUpLAogICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X21hcmtkb3duKHNpemU9MTAuNSkpICsgCiAgbGFicyhjb2xvcj0iIiwgeD0iKipUcmFjayoqIix5PSIqKk1pbmltdW0gVGltZSoqIChpbiBzZWNvbmRzKTxicj4iLAogICAgICAgdGl0bGU9IldoaWNoIE1hcmlvIEthcnQgVHJhY2sgSXMgVGhlIEZhc3Rlc3Q/IiwKICAgICAgIGNhcHRpb249IlRpZHkgVHVlc2RheSBXZWVrIDIyIHwgRGF0YSBmcm9tIE1hcmlvIEthcnQgV29ybGQgUmVjb3JkcyIpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjZjk1NzM4IiwiI2ZmYTYyYiIsIiMwMDkxYWQiLCIjNDNCMDQ3IikpICsgCiAgY29vcmRfZmxpcCgpIApgYGAKCmBgYHtyfQojIEZvciBob3cgbWFueSB0cmFja3MgaGF2ZSBzaG9ydGN1dHMgYmVlbiBkaXNjb3ZlcmVkPwpyZWNvcmRzICU+JSAKICBjb3VudCh0cmFjaywgc2hvcnRjdXQpICU+JQogIGNvdW50KHNob3J0Y3V0KQpgYGAKCmBgYHtyfQojIEZvciB3aGljaCB0cmFjayBkaWQgdGhlIHdvcmxkIHJlY29yZCBpbXByb3ZlIHRoZSBtb3N0PwpyZWNvcmRzICU+JSAKIGdyb3VwX2J5KHRyYWNrKSAlPiUgCiAgc3VtbWFyaXNlKG1pbl90aW1lID0gbWluKHRpbWUpLCBtYXhfdGltZT1tYXgodGltZSksIGltcHJvdmVkPW1heF90aW1lLW1pbl90aW1lKSAlPiUKICBhcnJhbmdlKGRlc2MoaW1wcm92ZWQpKSAlPiUKICBtdXRhdGUoaW1wcm92ZWRfcGN0PSByb3VuZChpbXByb3ZlZC9tYXhfdGltZSoxMDAsMykpICU+JQogIGFycmFuZ2UoZGVzYyhpbXByb3ZlZF9wY3QpKSAlPiUgc2xpY2UoMSkKYGBgCgoKYGBge3IsIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQojIE9uIHdoaWNoIHRyYWNrIHRoZSBzaG9ydGN1dCBzYXZlcyB0aGUgbW9zdCB0aW1lIAp0YWJsZTIgPSByZWNvcmRzICU+JSAKICBncm91cF9ieSh0cmFjaywgdHlwZSwgc2hvcnRjdXQpICU+JQogIHN1bW1hcmlzZSh0aW1lPW1lYW4odGltZSkpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzaG9ydGN1dCx2YWx1ZXNfZnJvbT10aW1lKSAlPiUKICBmaWx0ZXIoIWlzLm5hKFllcykpICU+JQogIG11dGF0ZSh0aW1lX3NhdmVkPU5vLVllcykgJT4lIAogIGFycmFuZ2UoZGVzYyh0aW1lX3NhdmVkKSkKCiMgdGltZSBzYXZlZCBieSByYWNlIHR5cGUKYnkodGFibGUyJHRpbWVfc2F2ZWQsIHRhYmxlMiR0eXBlLCBzdW1tYXJ5KSAjbm8gZGlmZmVyZW5jZSBpbiBTaW5nbGUgbGFwIHdpdGggYW5kIHdpdGhvdXQgc2hvcnRjdXQKYGBgCgoKYGBge3Isd2FybmluZz1GLCBtZXNzYWdlPUYsIGZpZy53aWR0aD0zLjc1LCBmaWcuaGVpZ2h0PTIuNzV9CiMgT24gd2hpY2ggdHJhY2sgdGhlIHNob3J0Y3V0IHNhdmVzIHRoZSBtb3N0IHRpbWUgCiMgZG90IHBsb3Q6IHRocmVlIGxhcAp0YWJsZTQgPSByZWNvcmRzICU+JSAKICBncm91cF9ieSh0cmFjaywgdHlwZSwgc2hvcnRjdXQpICU+JQogIHN1bW1hcmlzZSh0aW1lPW1lYW4odGltZSkpICU+JSAKICBmaWx0ZXIodHlwZT09IlRocmVlIExhcCIpICU+JQogIGZpbHRlcih0cmFjayE9IkJhbnNoZWUgQm9hcmR3YWxrIix0cmFjayE9IkJvd3NlcidzIENhc3RsZSIsCiAgICAgICAgIHRyYWNrIT0iS29vcGEgVHJvb3BhIEJlYWNoIix0cmFjayE9Ik1vbyBNb28gRmFybSIpICU+JQogIG11dGF0ZSh0aW1lX3NhdmVkPWxhZyh0aW1lKS10aW1lKSAlPiUKICBtdXRhdGUocGN0ID0gcm91bmQodGltZV9zYXZlZC9sYWcodGltZSksMykpIAoKdGFibGU1ID0gdGFibGU0ICU+JSBmaWx0ZXIoc2hvcnRjdXQ9PSJZZXMiKQoKdGFibGU1ICU+JQogIGdncGxvdChhZXMoeT1yZW9yZGVyKHRyYWNrLHBjdCksIHg9dGltZSkpICsgCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1wYXN0ZTAoIi0iLHNjYWxlczo6cGVyY2VudChwY3QsYWNjdXJhY3k9MC4xTCkpKSxzaXplPTIuOSwgaGp1c3Q9MS4yLCBjb2xvcj0iIzNDNTQ4OEZGIikgKwogIGdlb21fcG9pbnQoZGF0YT10YWJsZTQsIGFlcyhjb2xvcj1zaG9ydGN1dCksc2l6ZT0yLHNob3cubGVnZW5kID0gRikgKyAKICBnZW9tX2xpbmUoZGF0YT10YWJsZTQsIGFlcyhncm91cD10cmFjayksIGFscGhhPTAuMyxzaXplPTEpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsMzcwKSkgKyAKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgcGFuZWwuZ3JpZC5taW5vci54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X21hcmtkb3duKHNpemU9MTApLAogICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfbWFya2Rvd24oc2l6ZT0xMCksCiAgICAgICBwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiLAogICAgICAgcGxvdC5zdWJ0aXRsZT1lbGVtZW50X21hcmtkb3duKHNpemU9MTApKSArIAogIGxhYnMoeD0iKipBdmVyYWdlIHRpbWUqKiAoaW4gc2Vjb25kcykiLAogICAgICAgeT0iKipUcmFjayoqIiwKICAgICAgIHRpdGxlPSJPbiB3aGljaCB0cmFjayB0aGUgc2hvcnRjdXQgc2F2ZXMgdGhlIG1vc3QgdGltZSBmb3IgMy1sYXA/IiwKICAgICAgIHN1YnRpdGxlPSJQZXJjZW50YWdlIGlzIGV4cHJlc3NlZCBhcyAoPHNwYW4gc3R5bGUgPSAnY29sb3I6I0U2NEIzNUZGJz5ObyBTaG9ydGN1dDwvc3Bhbj4gLSA8c3BhbiBzdHlsZSA9ICdjb2xvcjojM0M1NDg4RkYnPldpdGggU2hvcnRjdXQ8L3NwYW4+KSAvIDxzcGFuIHN0eWxlID0gJ2NvbG9yOiNFNjRCMzVGRic+Tm8gU2hvcnRjdXQ8L3NwYW4+PGJyPiIpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjRTY0QjM1RkYiLCIjM0M1NDg4RkYiKSkKYGBgIAoKCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0KIyBPbiB3aGljaCB0cmFjayB0aGUgc2hvcnRjdXQgc2F2ZXMgdGhlIG1vc3QgdGltZSAKIyBoaWdobGlnaHRlZCBzbG9wZSBjaGFydDogdGhyZWUgbGFwCnRhYmxlMiAlPiUKICBmaWx0ZXIodHlwZT09IlRocmVlIExhcCIpICU+JQogIHBpdm90X2xvbmdlcihObzpZZXMpICU+JQogIG11dGF0ZShuYW1lPWlmZWxzZShuYW1lPT0iTm8iLCJObyBTaG9ydGN1dCIsIldpdGggU2hvcnRjdXQiKSkgJT4lCiAgbXV0YXRlKHZhbHVlPXJvdW5kKHZhbHVlLDEpLCB0aW1lX3NhdmVkPXJvdW5kKHRpbWVfc2F2ZWQsMSkpIC0+IHRhYmxlMwoKdGFibGUzICU+JQogIGdncGxvdChhZXMoeD1uYW1lLCB5PXZhbHVlLCBncm91cD10cmFjaykpICsgCiAgZ2VvbV9saW5lKGFlcyhjb2xvcj1JKGlmZWxzZSh0cmFjaz09IldhcmlvIFN0YWRpdW0iLCAnI0U2NEIzNUZGJywgJyM4NDkxYjRGRicpKSkpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3I9SShpZmVsc2UodHJhY2s9PSJXYXJpbyBTdGFkaXVtIiwgJyNFNjRCMzVGRicsICcjODQ5MWI0RkYnKSkpKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKyAKICBzY2FsZV94X2Rpc2NyZXRlKHBvc2l0aW9uPSJ0b3AiKSArCiAgZ2VvbV90ZXh0KGRhdGE9IHRhYmxlMyAlPiUgZmlsdGVyKHRyYWNrPT0iV2FyaW8gU3RhZGl1bSIpICU+JSBmaWx0ZXIobmFtZT09Ik5vIFNob3J0Y3V0IiksIAogICAgICAgICAgICBhZXMobGFiZWw9cGFzdGUwKHZhbHVlLCJzIikpLCBzaXplPTMsIGNvbG9yPSIjRTY0QjM1RkYiLCBoanVzdD0xLjIpICsKICBnZW9tX3RleHQoZGF0YT0gdGFibGUzICU+JSBmaWx0ZXIodHJhY2s9PSJXYXJpbyBTdGFkaXVtIikgJT4lIGZpbHRlcihuYW1lPT0iV2l0aCBTaG9ydGN1dCIpLCAKICAgICAgICAgICAgYWVzKGxhYmVsPXBhc3RlMCh2YWx1ZSwicyIpKSwgc2l6ZT0zLCBjb2xvcj0iI0U2NEIzNUZGIiwgaGp1c3Q9LTAuNSkgKyAKICBnZW9tX3RleHQoYWVzKHg9Ik5vIFNob3J0Y3V0Iix5PTI2NS4yLCBsYWJlbD0iV2FyaW8gU3RhZGl1bSIpLHNpemU9MywgY29sb3I9IiNFNjRCMzVGRiIsaGp1c3Q9MS43KSArIAogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChmYWNlPSJib2xkIixzaXplPTEwLCBjb2xvcj0iYmxhY2siKSwKICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF9tYXJrZG93bihzaXplPTEwKSwKICAgICAgICBwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiKSArCiAgbGFicyh4PSIiLHk9IioqQXZlcmFnZSB0aW1lIHNhdmVkKiogKGluIHNlY29uZHMpIiwKICAgICAgIHRpdGxlPSJPbiB3aGljaCB0cmFjayB0aGUgc2hvcnRjdXQgc2F2ZXMgdGhlIG1vc3QgdGltZSBmb3IgMy1sYXA/IikKYGBgCgoKYGBge3IsIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQojIFdoZW4gd2VyZSBzaG9ydGN1dHMgZGlzY292ZXJlZD8KcmVjb3JkcyAlPiUgZ3JvdXBfYnkodHJhY2ssIHNob3J0Y3V0KSAlPiUKICBzdW1tYXJpc2Uoc2NfZGlzPW1pbihkYXRlKSkgJT4lCiAgZmlsdGVyKHNob3J0Y3V0PT0iWWVzIikgJT4lCiAgbXV0YXRlKHNob3J0Y3V0PWlmZWxzZShzaG9ydGN1dD09IlllcyIsMSwiIikpICU+JQogIGdncGxvdChhZXMoeT1zaG9ydGN1dCx4PXNjX2RpcykpICsgCiAgZ2VvbV9zZWdtZW50KGFlcyh4PW1pbihzY19kaXMpLCB4ZW5kPW1heChzY19kaXMpLCB5PXNob3J0Y3V0LCB5ZW5kPXNob3J0Y3V0KSkgKwogIGdlb21fcG9pbnQoYWVzKGNvbG9yPWZhY3RvcihzY19kaXMpKSxzaXplPTYsc2hvdy5sZWdlbmQ9Riwgc2hhcGU9MTgpICsgCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1zY19kaXMpLCBzaXplPTMsIHZqdXN0PTMsIGNvbG9yPSJibGFjayIpICsgCiAgZ2VvbV90ZXh0KGFlcyh4PW1pbihzY19kaXMpLGxhYmVsPSJMdWlnaSBSYWNld2F5Iix5PTEuMDMpLCBzaXplPTMsIGNvbG9yPSIjRTY0QjM1RkYiKSArIAogIGdlb21fdGV4dChhZXMoeD1hcy5EYXRlKGMoIjE5OTctMDMtMDciKSksbGFiZWw9IlJhaW5ib3cgUm9hZFxuWW9zaGkgVmFsbGV5Iix5PTEuMDQ4KSwgCiAgICAgICAgICAgIHNpemU9MywgY29sb3I9IiMwMEEwODdGRiIsIGhqdXN0PTAsbnVkZ2VfeD0tMS42KSArCiAgZ2VvbV90ZXh0KGFlcyh4PWFzLkRhdGUoYygiMTk5Ny0wMy0xMCIpKSxsYWJlbD0iQ2hvY28gTW91bnRhaW5cbkQuSy4ncyBKdW5nbGUgUGFya3dheVxuRnJhcHBlIFNub3dsYW5kXG5LYWxpbWFyaSBEZXNlcnRcbk1hcmlvIFJhY2V3YXlcblJveWFsIFJhY2V3YXlcblNoZXJiZXQgTGFuZFxuVG9hZCdzIFR1cm5waWtlXG5XYXJpbyBTdGFkaXVtIix5PTEuMTI1KSwgc2l6ZT0zLGhqdXN0PTAsbnVkZ2VfeD0tMS4xLCBjb2xvcj0iIzNDNTQ4OEZGIikgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLjg1LDEuMzUpKSArCiAgc2NhbGVfeF9kYXRlKGxhYmVscz1zY2FsZXM6OmRhdGVfZm9ybWF0KCIlZC0lbS0lWSIpLCBsaW1pdHM9YXMuRGF0ZShjKCcxOTk3LTAyLTEzJywnMTk5Ny0wMy0xNCcpKSwKICAgICAgICAgICAgICAgZXhwYW5kID0gYygwLCAwKSwgYnJlYWtzID0gIjEgd2VlayIpICsKICB0aGVtZShheGlzLnRleHQ9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vcj1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLng9ZWxlbWVudF9saW5lKHNpemU9MC4zNSkpICsgCiAgZ2VvbV9icmFja2V0KHhtaW49YXMuRGF0ZShjKCIxOTk3LTAyLTE2IikpLCB4bWF4PWFzLkRhdGUoYygiMTk5Ny0wMy0wNyIpKSwgeS5wb3NpdGlvbj0xLjEsIAogICAgICAgICAgICAgICBsYWJlbD0iMTkgZGF5cyIsIGxhYmVsLnNpemU9MykgKwogIGdlb21fYnJhY2tldCh4bWluPWFzLkRhdGUoYygiMTk5Ny0wMy0wNyIpKSwgeG1heD1hcy5EYXRlKGMoIjE5OTctMDMtMTAiKSksIHkucG9zaXRpb249MS4yNSwgCiAgICAgICAgICAgICAgIGxhYmVsPSIzIGRheXMiLCBsYWJlbC5zaXplPTMpICsgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjRTY0QjM1RkYiLCIjMDBBMDg3RkYiLCIjM0M1NDg4RkYiKSkgKyAKICBsYWJzKHRpdGxlPSJXaGVuIHdlcmUgc2hvcnRjdXRzIGRpc2NvdmVyZWQ/IikKICAKYGBgCgoKYGBge3J9CiMgV2hpY2ggaXMgdGhlIGxvbmdlc3Qgc3RhbmRpbmcgd29ybGQgcmVjb3JkPwpyZWNvcmRzICU+JSBhcnJhbmdlKGRlc2MocmVjb3JkX2R1cmF0aW9uKSkgJT4lIHNsaWNlKDEpCmBgYAoKYGBge3IsIG1lc3NhZ2U9Rn0KIyBEaXN0cmlidXRpb24gb2YgcmVjb3JkIGR1cmF0aW9uIGFjcm9zcyByYWNlIHR5cGVzCmdnYmV0d2VlbnN0YXRzKGRhdGE9cmVjb3JkcywgeD10eXBlLCB5PXJlY29yZF9kdXJhdGlvbiwKICAgICAgICAgICAgICAgdGl0bGU9IkRpc3RyaWJ1dGlvbiBvZiByZWNvcmQgZHVyYXRpb24gYWNyb3NzIHJhY2UgdHlwZXMiLAogICAgICAgICAgICAgICB0eXBlPSJucCIsCiAgICAgICAgICAgICAgIHBsb3RncmlkLmFyZ3M9bGlzdChucm93PTEpLAogICAgICAgICAgICAgICBtZXNzYWdlcz1GQUxTRSwKICAgICAgICAgICAgICAgcmVzdWx0cy5zdWJ0aXRsZSA9IEZBTFNFLAogICAgICAgICAgICAgICB4bGFiPSJUeXBlIiwKICAgICAgICAgICAgICAgeWxhYj0iUmVjb3JkIGR1cmF0aW9uIiwKICAgICAgICAgICAgICAgcG9pbnQuYXJncyA9IGxpc3QocG9zaXRpb24gPSBnZ3Bsb3QyOjpwb3NpdGlvbl9qaXR0ZXJkb2RnZShkb2RnZS53aWR0aCA9IDAuNiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHBoYT0gMC40LCBzaXplID0gMiwgc3Ryb2tlID0gMCkpICsgCiAgZ2dwbG90Mjo6c2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcz1jKCIjNERCQkQ1RkYiLCIjMDBBMDg3RkYiKSkKYGBgCgpgYGB7cn0KIyBIb3cgZGlkIHRoZSB3b3JsZCByZWNvcmRzIGRldmVsb3Agb3ZlciB0aW1lPwojIGNvdW50IG9mIHdvcmxkIHJlY29yZHMgb3ZlciB0aW1lCiNyZWNvcmRzICU+JSAKICAjbXV0YXRlKHR5cGVfc2M9IGlmZWxzZShzaG9ydGN1dD09IlllcyIsIHBhc3RlKHR5cGUsICJ3aXRoIiwiU2hvcnRjdXQiKSx0eXBlKSkgJT4lCiAgI2dyb3VwX2J5KGRhdGUpICU+JSB0YWxseSgpICU+JSBnZ3NjYXR0ZXJoaXN0KHg9ImRhdGUiLHk9Im4iLCBzaXplPTEsIG1hcmdpbi5wbG90PSJkZW5zaXR5IikKCgojIEhvdyBkaWQgdGhlIHdvcmxkIHJlY29yZHMgZGV2ZWxvcCBvdmVyIHRpbWU/CiMgY291bnQgb2YgcmVjb3JkcyBvdmVyIHRpbWUgYnkgdHlwZSBhbmQgc2hvcnRjdXQgCnJlY29yZHMgJT4lIAogIG11dGF0ZSh0eXBlX3NjPSBpZmVsc2Uoc2hvcnRjdXQ9PSJZZXMiLCBwYXN0ZSh0eXBlLCAid2l0aCIsIlNob3J0Y3V0IiksdHlwZSkpICU+JQogIGdyb3VwX2J5KGRhdGUpICU+JSBjb3VudCh0eXBlX3NjKSAlPiUKICBnZ3Bsb3QoYWVzKHg9ZGF0ZSwgeT1uLCBjb2xvcj10eXBlX3NjKSkgKyAKICBnZW9tX3BvaW50KHNpemU9MSxzaG93LmxlZ2VuZD1GLCBhbHBoYT0wLjkpICsgCiAgZmFjZXRfd3JhcCh+dHlwZV9zYyxuY29sPTIpICsgCiAgc2NhbGVfY29sb3JfbnBnKCkgKyAKICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X21hcmtkb3duKHNpemU9MTApLAogICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X21hcmtkb3duKHNpemU9MTApLAogICAgICAgIHBsb3QudGl0bGUucG9zaXRpb249InBsb3QiLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZT0iYm9sZCIsY29sb3I9IiMzNDNhNDAiKQogICAgICAgICkgKyAKICBsYWJzKHg9IioqRGF0ZSoqIix5PSIqKlJlY29yZCBjb3VudCoqIiwgdGl0bGU9IlJlY29yZHMgb3ZlciB0aW1lIGJ5IGxhcCB0eXBlIGFuZCBzaG9ydGN1dCIpCmBgYAoKCmBgYHtyfQojIFdoaWNoIGlzIHRoZSBsb25nZXN0IHN0YW5kaW5nIHdvcmxkIHJlY29yZD8KcmVjb3JkcyAlPiUgZmlsdGVyKHJlY29yZF9kdXJhdGlvbj09bWF4KHJlY29yZF9kdXJhdGlvbikpCiMgV2hvIGlzIHRoZSBwbGF5ZXIgd2l0aCB0aGUgbW9zdCB3b3JsZCByZWNvcmRzPwpkcml2ZXJzICU+JSBkaXN0aW5jdChwbGF5ZXIsIHRvdGFsKSAlPiUgc2xpY2UoMSkKIyBXaG8gYXJlIHJlY2VudCBwbGF5ZXJzPyAocGxheWVycyBpbiAyMDIxKQpyZWNvcmRzICU+JSBmaWx0ZXIoZGF0ZT4iMjAyMC0xMi0zMSIpICU+JSAKICBncm91cF9ieShwbGF5ZXIpICU+JSAKICBzdW1tYXJpc2UobGF0ZXN0X2RhdGU9bWF4KGRhdGUpLCByZWNvcmRfY291bnQ9bGVuZ3RoKHBsYXllcikpIApgYGAKCgoKCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0KIyBVbmlxdWUgYW5kIG5ldyBwbGF5ZXIgY291bnQgYWNyb3NzIHRoZSB5ZWFycwojIHJlZmVyZW5jZTpodHRwczovL2phY2stZGF2aXNvbi5naXRodWIuaW8vcG9zdHMvMjAyMS0wNS0yNS1leHBsb3JpbmctZnVuLXF1ZXN0aW9ucy10aWR5dHVlc2RheS0yMDIxLXdlZWstMjItbWFyaW8ta2FydC02NC8KCmQxID0gZHJpdmVycyAlPiUgZGlzdGluY3QocGxheWVyLCB5ZWFyLCByZWNvcmRzKSAlPiUKICBkcm9wX25hKCkgJT4lIGdyb3VwX2J5KHllYXIpICU+JSBzdW1tYXJpc2UodW5pcXVlX3BsYXllcj1uX2Rpc3RpbmN0KHBsYXllcikpCgpkMiA9IGRyaXZlcnMgJT4lIGRpc3RpbmN0KHBsYXllciwgeWVhciwgcmVjb3JkcykgJT4lCiAgZHJvcF9uYSgpICU+JSBncm91cF9ieShwbGF5ZXIpICU+JQogIGZpbHRlcih5ZWFyPT1taW4oeWVhcikpICU+JSAKICB1bmdyb3VwKCkgJT4lIGNvdW50KHllYXIpICU+JSByZW5hbWUobmV3X3BsYXllcj1uKQoKZDEgJT4lIGxlZnRfam9pbihkMikgJT4lIHJlcGxhY2UoaXMubmEoLiksIDApICU+JQogIHBpdm90X2xvbmdlcih1bmlxdWVfcGxheWVyOm5ld19wbGF5ZXIpICU+JQogIG11dGF0ZShuYW1lPWlmZWxzZShuYW1lPT0idW5pcXVlX3BsYXllciIsIlVuaXF1ZSBQbGF5ZXIiLCJOZXcgUGxheWVyIikpICU+JQogIGdncGxvdChhZXMoeD15ZWFyLCB5PXZhbHVlLCBmaWxsPXZhbHVlKSkgKyAKICBnZW9tX2NvbCgpICsgCiAgZmFjZXRfZ3JpZCh+ZmN0X3JldihuYW1lKSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICBicmVha3MgPSBzZXEobWluKGRyaXZlcnMkeWVhciksIG1heChkcml2ZXJzJHllYXIpLCA0KSkgKyAKICBzY2FsZV9maWxsX2dyYWRpZW50bihjb2xvdXJzID0gd2VzX3BhbGV0dGUoIlppc3NvdTEiLCAyNSwgdHlwZSA9ICJjb250aW51b3VzIikpICsgCiAgdGhlbWUocGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9tYXJrZG93bihzaXplPTEwKSwKICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF9tYXJrZG93bihzaXplPTEwKSwKICAgICAgICBwbG90LnRpdGxlLnBvc2l0aW9uPSJwbG90IiwKICAgICAgICBsZWdlbmQucG9zaXRpb249Im5vbmUiLAogICAgICAgIHN0cmlwLnRleHQ9ZWxlbWVudF90ZXh0KGZhY2U9ImJvbGQiLHNpemU9MTApLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHZqdXN0ID01KSkgKyAKICBsYWJzKHg9IioqWWVhcioqIix5PSIqKkNvdW50KioiLAogICAgICAgdGl0bGU9IlVuaXF1ZSBhbmQgbmV3IHBsYXllciBjb3VudCBhY3Jvc3MgdGhlIHllYXJzXG4iKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0KIyBXaGljaCBpcyB0aGUgZmFzdGVzdCB0cmFjaz8KcmVjb3JkcyAlPiUgZ3JvdXBfYnkodHlwZSx0cmFjaykgJT4lIHN1bW1hcmlzZShtaW5fdGltZT1taW4odGltZSkpICU+JSAKICBwaXZvdF93aWRlcihuYW1lc19mcm9tPXR5cGUsIHZhbHVlc19mcm9tPW1pbl90aW1lKSAlPiUgCiAgcmVuYW1lKFRyYWNrPXRyYWNrKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBEVDo6ZGF0YXRhYmxlKHJvd25hbWVzPUZBTFNFLG9wdGlvbnMgPSBsaXN0KG9yZGVyID0gbGlzdChsaXN0KDEsICdhc2MnKSkpKQpgYGAKCmBgYHtyLCBtZXNzYWdlPUZ9CiMgTWF4aW11bSBSZWNvcmQgYnkgdHJhY2sgYW5kIGxhcCB0eXBlICAKIyByZWZlcmVuY2U6IGh0dHBzOi8vdHdpdHRlci5jb20vSnVhbm1hX01OL3N0YXR1cy8xMzk3MjQ5NjQ4OTMxMzYwNzY4L3Bob3RvLzEKcmVjb3JkcyAlPiUgZ3JvdXBfYnkodHJhY2ssIHR5cGUpICU+JSBzdW1tYXJpc2UobWF4X2R1cmF0aW9uPW1heChyZWNvcmRfZHVyYXRpb24pKSAlPiUKICBnZ3Bsb3QoYWVzKHk9cmVvcmRlcih0cmFjayxtYXhfZHVyYXRpb24sIG1heCksIHg9bWF4X2R1cmF0aW9uLCBjb2xvcj10eXBlKSkgKyAKICBnZW9tX3BvaW50KHNpemU9MikgKyAKICBnZW9tX2xpbmUoYWVzKGdyb3VwPXRyYWNrKSwgY29sb3I9ImdyZXkiKSArIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiI0U2NEIzNUZGIiwiIzNDNTQ4OEZGIikpICsgCiAgdGhlbWUoYXhpcy50aXRsZS54PWVsZW1lbnRfbWFya2Rvd24oc2l6ZT0xMCksCiAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfbWFya2Rvd24oc2l6ZT0xMCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfbWFya2Rvd24oKSwKICAgICAgICBwbG90LnRpdGxlLnBvc2l0aW9uPSJwbG90IiwKICAgICAgICBsZWdlbmQucG9zaXRpb249Im5vbmUiKSArIAogIGxhYnMoeT0iKipUcmFjayoqIix4PSIqKk1heGltdW0gcmVjb3JkIGR1cmF0aW9uKiogKGluIGRheXMpIiwKICAgICAgIHRpdGxlPSJNYXhpbXVtIHJlY29yZCBkdXJhdGlvbiBvZiA8c3BhbiBzdHlsZSA9ICdjb2xvcjojRTY0QjM1RkYnPlNpbmdsZSBMYXA8L3NwYW4+IGFuZCA8c3BhbiBzdHlsZSA9ICdjb2xvcjojM0M1NDg4RkYnPlRocmVlIExhcDwvc3Bhbj4gcmFjZXMsIGJ5IFRyYWNrIiwKICAgICAgIHN1YnRpdGxlPSIiKQpgYGAKCgoK