Notebook description: Basic data wrangling and visualization practice
Data source: TidyTuesday Washington Hiking from Washington Trails Association
Load packages
library(rvest)
library(tidyverse)
library(here)
library(ggplot2)
library(plotly)
library(Hmisc)
library(ggsci)
Get data
scrape_trails <- function(start_int){
page_url <- paste0(
"https://www.wta.org/go-outside/hikes?b_start:int=",
start_int
)
page_html <- read_html(page_url)
page_html %>%
html_nodes(".search-result-item") %>%
map(
function(hike){
hike_name <- hike %>% html_nodes(".listitem-title") %>% html_nodes("span") %>% html_text()
hike_location <- hike %>% html_node("h3") %>% html_text()
hike_stats <- hike %>% html_node(".hike-stats")
hike_length <- hike_stats %>% html_nodes(".hike-length") %>%html_nodes("span") %>% html_text()
hike_gain <- hike_stats %>% html_nodes(".hike-gain") %>%html_nodes("span") %>% html_text()
hike_highpoint <- hike_stats %>% html_nodes(".hike-highpoint") %>%html_nodes("span") %>% html_text()
hike_rating <- hike_stats %>% html_nodes(".hike-rating") %>%html_nodes(".current-rating") %>% html_text()
hike_desc <- hike %>% html_nodes(".listing-summary") %>% html_text()
hike_features <- hike %>% html_nodes(".trip-features") %>% html_nodes("img") %>% html_attr("title") %>% list()
tibble(
name = hike_name,
location = hike_location,
length = hike_length,
gain = hike_gain,
highpoint = hike_highpoint,
rating = hike_rating,
features = hike_features,
description = hike_desc
)
}) %>%
bind_rows() %>%
mutate(description = str_remove(description, "\n") %>% str_squish())
}
start_int <- c(1, seq(30, 3840, by = 30))
hike_data <- start_int %>%
map_dfr(scrape_trails)
clean_hike_data <- hike_data %>%
mutate(
trip = case_when(
grepl("roundtrip",length) ~ "roundtrip",
grepl("one-way",length) ~ "one-way",
grepl("of trails",length) ~ "trails"),
length_total = as.numeric(gsub("(\\d+[.]\\d+).*","\\1", length)) * ((trip == "one-way") + 1),
gain = as.numeric(gain),
highpoint = as.numeric(highpoint),
location_general = gsub("(.*)\\s[-][-].*","\\1",location)
)
hike_plot <- ggplot(clean_hike_data) +
geom_rect(aes(
xmin = 0,
xmax = length_total,
ymin = 0,
ymax = gain,
label = name
),
alpha = .4,
fill = "#228B22",
color = "#765C48"
) +
facet_wrap(
~ location_general,
scales = "free_x"
) +
labs(
title = "Washington State Hikes",
x = "Hike Length (miles)",
y = "Hike Elevation Gain (ft)",
caption = "Data from Washingon Trails Association (wta.org) | Viz by @ellis_hughes"
)
ggplotly(hike_plot)
dim(clean_hike_data)
colnames(clean_hike_data)
Dog friendly trails
clean_hike_data$dogs = ifelse(grepl("leash", clean_hike_data$features), "Yes","No")
Hmisc::describe(clean_hike_data$dogs)
*1044 out of 1957 trails allow dogs on leash
clean_hike_data %>% group_by(location_general,dogs) %>% tally() %>% ggplot(aes(x=dogs, y=n, fill=dogs)) + geom_col() + facet_wrap(~location_general) + theme_minimal() + theme(
panel.grid.major.x = element_blank(),
panel.border = element_blank(),
axis.ticks.x = element_blank(),
axis.ticks.y = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(),
axis.text.x=element_blank(),
plot.title = element_text(size=12, face="bold"),
plot.subtitle = element_text(size=10, color="#343a40"),
legend.title=element_text(size=9),
legend.position = "top") + scale_fill_jama() +
labs(y="", x="", fill="Dogs allowed on leash", title = "Dog Friendly Trails In Washington", subtitle="1044 out of 1957 trails allow dogs on leash", caption="Data from Washingon Trails Association (wta.org)")

Ratings
summary(as.numeric(clean_hike_data$rating))
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.000 2.600 3.400 2.986 4.000 5.000
sum(is.na(clean_hike_data$rating))
[1] 0
median_values <- clean_hike_data %>%
group_by(location_general) %>%
summarise(
med = median(as.numeric(rating))) %>% ungroup()
ggplot(clean_hike_data, aes(x = reorder(location_general, rating, FUN = median), y = rating)) +
geom_boxplot(aes(color = location_general)) +
geom_point(data = median_values, aes(x = location_general, y = med, fill = location_general), shape = 23, size = 5, color = "grey") +
guides(fill = FALSE, color = FALSE) +
coord_flip() +
labs(y = "Rating", x = "General Location", title = "Washington Trail Ratings by General Location", caption = "Data from Washingon Trails Association (wta.org)") +
theme_light() +
scale_color_futurama() +
scale_fill_futurama() +
theme(
axis.ticks.x = element_blank(),
axis.ticks.y = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.x = element_blank(),
plot.title = element_text(size=12, face="bold"),
axis.title = element_text(size=10),
panel.border = element_blank(),
legend.position="none"
)

One-way vs Roundtrip trails
clean_hike_data %>% group_by(location_general,trip) %>% tally() %>% filter(trip !="trails") %>% ggplot(aes(x=location_general, y=n, fill=trip)) + geom_col(position="dodge") + coord_flip() + theme_light() + theme(
panel.grid.major.x = element_blank(),
panel.border = element_blank(),
axis.ticks.x = element_blank(),
axis.ticks.y = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(),
plot.title = element_text(size=12, face="bold"),
plot.subtitle = element_text(size=10, color="#343a40"),
legend.title=element_text(size=9),
legend.position = "right") +
labs(y="", x="", fill="", title = "One-way vs Roundtrip trails in Washington", caption="Data from Washingon Trails Association (wta.org)") +
scale_fill_jama()

Features
#cleaning script from @alexcookson
hike_data_raw <- read_rds(url('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-11-24/hike_data.rds'))
hike <- hike_data_raw %>%
distinct(name, location, .keep_all = TRUE) %>%
mutate(trail_id = row_number()) %>%
relocate(trail_id) %>%
mutate(across(.cols = c(length, gain, highpoint, rating), parse_number)) %>%
rename(length_miles = length,
gain_ft = gain,
highpoint_ft = highpoint) %>%
mutate(rating = ifelse(rating == 0, NA, rating))
features <- hike %>%
select(trail_id, features) %>%
unnest(features) %>%
rename(feature = features)
features %>% group_by(feature) %>% tally(sort=T) %>%
ggplot(aes(x=reorder(feature,n), y=n)) +
geom_segment(aes(x=reorder(feature,n), xend=feature, y=0, yend=n), color="#084c61") +
geom_point(color="#4f772d", size=3, alpha=0.9) + scale_color_viridis() +
theme_light() +
coord_flip() +
theme(
panel.border = element_blank(),
axis.ticks.x = element_blank(),
axis.ticks.y = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(),
plot.title = element_text(size=12, face="bold"),
axis.title= element_text(size=10),
legend.position = "right") +
labs(y="Number of Trails", x="Feature", fill="", title = "Washington Trails Features", caption="Data from Washingon Trails Association (wta.org)")

LS0tCnRpdGxlOiAiV2FzaGluZ3RvbiBUcmFpbHMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCioqTm90ZWJvb2sgZGVzY3JpcHRpb24qKjogQmFzaWMgZGF0YSB3cmFuZ2xpbmcgYW5kIHZpc3VhbGl6YXRpb24gcHJhY3RpY2UgCgoqKkRhdGEgc291cmNlKio6IFRpZHlUdWVzZGF5IFtXYXNoaW5ndG9uIEhpa2luZ10oaHR0cHM6Ly9naXRodWIuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9ibG9iL21hc3Rlci9kYXRhLzIwMjAvMjAyMC0xMS0yNC9yZWFkbWUubWQpIGZyb20gW1dhc2hpbmd0b24gVHJhaWxzIEFzc29jaWF0aW9uXShodHRwczovL3d3dy53dGEub3JnL2dvLW91dHNpZGUvaGlrZXM/Yl9zdGFydDppbnQ9MSkKCiMjIyBMb2FkIHBhY2thZ2VzCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KbGlicmFyeShydmVzdCkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoaGVyZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShIbWlzYykKbGlicmFyeShnZ3NjaSkKYGBgCgojIyMgR2V0IGRhdGEKYGBge3J9CnNjcmFwZV90cmFpbHMgPC0gZnVuY3Rpb24oc3RhcnRfaW50KXsKICBwYWdlX3VybCA8LSBwYXN0ZTAoCiAgICAiaHR0cHM6Ly93d3cud3RhLm9yZy9nby1vdXRzaWRlL2hpa2VzP2Jfc3RhcnQ6aW50PSIsCiAgICBzdGFydF9pbnQKICApCiAgCiAgcGFnZV9odG1sIDwtIHJlYWRfaHRtbChwYWdlX3VybCkKICAKICBwYWdlX2h0bWwgJT4lIAogICAgCiAgICBodG1sX25vZGVzKCIuc2VhcmNoLXJlc3VsdC1pdGVtIikgJT4lIAogICAgCiAgICBtYXAoCiAgICAgIGZ1bmN0aW9uKGhpa2UpewogICAgICAgIAogICAgICAgIGhpa2VfbmFtZSA8LSBoaWtlICU+JSBodG1sX25vZGVzKCIubGlzdGl0ZW0tdGl0bGUiKSAlPiUgaHRtbF9ub2Rlcygic3BhbiIpICU+JSAgaHRtbF90ZXh0KCkKICAgICAgICBoaWtlX2xvY2F0aW9uIDwtIGhpa2UgJT4lIGh0bWxfbm9kZSgiaDMiKSAlPiUgaHRtbF90ZXh0KCkKICAgICAgICAKICAgICAgICBoaWtlX3N0YXRzIDwtIGhpa2UgJT4lIGh0bWxfbm9kZSgiLmhpa2Utc3RhdHMiKQogICAgICAgIAogICAgICAgIGhpa2VfbGVuZ3RoIDwtIGhpa2Vfc3RhdHMgJT4lIGh0bWxfbm9kZXMoIi5oaWtlLWxlbmd0aCIpICU+JWh0bWxfbm9kZXMoInNwYW4iKSAlPiUgIGh0bWxfdGV4dCgpCiAgICAgICAgaGlrZV9nYWluIDwtIGhpa2Vfc3RhdHMgJT4lIGh0bWxfbm9kZXMoIi5oaWtlLWdhaW4iKSAlPiVodG1sX25vZGVzKCJzcGFuIikgJT4lICBodG1sX3RleHQoKQogICAgICAgIGhpa2VfaGlnaHBvaW50IDwtIGhpa2Vfc3RhdHMgJT4lIGh0bWxfbm9kZXMoIi5oaWtlLWhpZ2hwb2ludCIpICU+JWh0bWxfbm9kZXMoInNwYW4iKSAlPiUgIGh0bWxfdGV4dCgpCiAgICAgICAgaGlrZV9yYXRpbmcgPC0gaGlrZV9zdGF0cyAlPiUgaHRtbF9ub2RlcygiLmhpa2UtcmF0aW5nIikgJT4laHRtbF9ub2RlcygiLmN1cnJlbnQtcmF0aW5nIikgJT4lICBodG1sX3RleHQoKQogICAgICAgIAogICAgICAgIGhpa2VfZGVzYyA8LSBoaWtlICU+JSBodG1sX25vZGVzKCIubGlzdGluZy1zdW1tYXJ5IikgJT4lIGh0bWxfdGV4dCgpCiAgICAgICAgCiAgICAgICAgaGlrZV9mZWF0dXJlcyA8LSBoaWtlICU+JSBodG1sX25vZGVzKCIudHJpcC1mZWF0dXJlcyIpICU+JSBodG1sX25vZGVzKCJpbWciKSAlPiUgaHRtbF9hdHRyKCJ0aXRsZSIpICU+JSBsaXN0KCkKICAgICAgICAKICAgICAgICB0aWJibGUoCiAgICAgICAgICBuYW1lID0gaGlrZV9uYW1lLAogICAgICAgICAgbG9jYXRpb24gPSBoaWtlX2xvY2F0aW9uLAogICAgICAgICAgbGVuZ3RoID0gaGlrZV9sZW5ndGgsCiAgICAgICAgICBnYWluID0gaGlrZV9nYWluLAogICAgICAgICAgaGlnaHBvaW50ID0gaGlrZV9oaWdocG9pbnQsCiAgICAgICAgICByYXRpbmcgPSBoaWtlX3JhdGluZywKICAgICAgICAgIGZlYXR1cmVzID0gaGlrZV9mZWF0dXJlcywKICAgICAgICAgIGRlc2NyaXB0aW9uID0gaGlrZV9kZXNjCiAgICAgICAgKQogICAgICB9KSAlPiUgCiAgICBiaW5kX3Jvd3MoKSAlPiUgCiAgICBtdXRhdGUoZGVzY3JpcHRpb24gPSBzdHJfcmVtb3ZlKGRlc2NyaXB0aW9uLCAiXG4iKSAlPiUgc3RyX3NxdWlzaCgpKQp9CgpzdGFydF9pbnQgPC0gYygxLCBzZXEoMzAsIDM4NDAsIGJ5ID0gMzApKQoKaGlrZV9kYXRhIDwtIHN0YXJ0X2ludCAlPiUgCiAgbWFwX2RmcihzY3JhcGVfdHJhaWxzKQoKc2F2ZVJEUyhoaWtlX2RhdGEsZmlsZSA9ICIvaGlrZV9kYXRhLnJkcyIpCmBgYAoKCmBgYHtyfQpjbGVhbl9oaWtlX2RhdGEgPC0gaGlrZV9kYXRhICU+JSAKICBtdXRhdGUoCiAgICB0cmlwID0gY2FzZV93aGVuKAogICAgICBncmVwbCgicm91bmR0cmlwIixsZW5ndGgpIH4gInJvdW5kdHJpcCIsCiAgICAgIGdyZXBsKCJvbmUtd2F5IixsZW5ndGgpIH4gIm9uZS13YXkiLAogICAgICBncmVwbCgib2YgdHJhaWxzIixsZW5ndGgpIH4gInRyYWlscyIpLAogICAgCiAgICBsZW5ndGhfdG90YWwgPSBhcy5udW1lcmljKGdzdWIoIihcXGQrWy5dXFxkKykuKiIsIlxcMSIsIGxlbmd0aCkpICogKCh0cmlwID09ICJvbmUtd2F5IikgKyAxKSwKICAgIAogICAgZ2FpbiA9IGFzLm51bWVyaWMoZ2FpbiksCiAgICBoaWdocG9pbnQgPSBhcy5udW1lcmljKGhpZ2hwb2ludCksCiAgICAKICAgIGxvY2F0aW9uX2dlbmVyYWwgPSBnc3ViKCIoLiopXFxzWy1dWy1dLioiLCJcXDEiLGxvY2F0aW9uKQogICkKCmBgYAoKYGBge3IsIGZpZy5zaG93PSdoaWRlJywgbWVzc2FnZT1GQUxTRX0KaGlrZV9wbG90IDwtIGdncGxvdChjbGVhbl9oaWtlX2RhdGEpICsgCiAgZ2VvbV9yZWN0KGFlcygKICAgIHhtaW4gPSAwLAogICAgeG1heCA9IGxlbmd0aF90b3RhbCwKICAgIHltaW4gPSAwLAogICAgeW1heCA9IGdhaW4sCiAgICBsYWJlbCA9IG5hbWUKICApLAogIGFscGhhID0gLjQsCiAgZmlsbCA9ICIjMjI4QjIyIiwKICBjb2xvciA9ICIjNzY1QzQ4IgogICkgKyAKICBmYWNldF93cmFwKAogICAgfiBsb2NhdGlvbl9nZW5lcmFsLAogICAgc2NhbGVzID0gImZyZWVfeCIKICApICsKICBsYWJzKAogICAgdGl0bGUgPSAiV2FzaGluZ3RvbiBTdGF0ZSBIaWtlcyIsCiAgICB4ID0gIkhpa2UgTGVuZ3RoIChtaWxlcykiLAogICAgeSA9ICJIaWtlIEVsZXZhdGlvbiBHYWluIChmdCkiLAogICAgY2FwdGlvbiA9ICJEYXRhIGZyb20gV2FzaGluZ29uIFRyYWlscyBBc3NvY2lhdGlvbiAod3RhLm9yZykgfCBWaXogYnkgQGVsbGlzX2h1Z2hlcyIKICApCgpnZ3Bsb3RseShoaWtlX3Bsb3QpCmBgYAoKCmBgYHtyfQpkaW0oY2xlYW5faGlrZV9kYXRhKQpjb2xuYW1lcyhjbGVhbl9oaWtlX2RhdGEpCmBgYAoKIyMjIERvZyBmcmllbmRseSB0cmFpbHMgCgpgYGB7cn0KY2xlYW5faGlrZV9kYXRhJGRvZ3MgPSBpZmVsc2UoZ3JlcGwoImxlYXNoIiwgY2xlYW5faGlrZV9kYXRhJGZlYXR1cmVzKSwgIlllcyIsIk5vIikKSG1pc2M6OmRlc2NyaWJlKGNsZWFuX2hpa2VfZGF0YSRkb2dzKQpgYGAKKjEwNDQgb3V0IG9mIDE5NTcgdHJhaWxzIGFsbG93IGRvZ3Mgb24gbGVhc2ggCgpgYGB7cn0KY2xlYW5faGlrZV9kYXRhICU+JSBncm91cF9ieShsb2NhdGlvbl9nZW5lcmFsLGRvZ3MpICU+JSB0YWxseSgpICU+JSBnZ3Bsb3QoYWVzKHg9ZG9ncywgeT1uLCBmaWxsPWRvZ3MpKSArIGdlb21fY29sKCkgKyBmYWNldF93cmFwKH5sb2NhdGlvbl9nZW5lcmFsKSArIHRoZW1lX21pbmltYWwoKSArIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBmYWNlPSJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTAsIGNvbG9yPSIjMzQzYTQwIiksCiAgICBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OSksCiAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKyBzY2FsZV9maWxsX2phbWEoKSArIAogICAgbGFicyh5PSIiLCB4PSIiLCBmaWxsPSJEb2dzIGFsbG93ZWQgb24gbGVhc2giLCB0aXRsZSA9ICJEb2cgRnJpZW5kbHkgVHJhaWxzIEluIFdhc2hpbmd0b24iLCBzdWJ0aXRsZT0iMTA0NCBvdXQgb2YgMTk1NyB0cmFpbHMgYWxsb3cgZG9ncyBvbiBsZWFzaCIsIGNhcHRpb249IkRhdGEgZnJvbSBXYXNoaW5nb24gVHJhaWxzIEFzc29jaWF0aW9uICh3dGEub3JnKSIpCmBgYAoKIyMjIFJhdGluZ3MKYGBge3J9CnN1bW1hcnkoYXMubnVtZXJpYyhjbGVhbl9oaWtlX2RhdGEkcmF0aW5nKSkKc3VtKGlzLm5hKGNsZWFuX2hpa2VfZGF0YSRyYXRpbmcpKQpgYGAKCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0KbWVkaWFuX3ZhbHVlcyA8LSBjbGVhbl9oaWtlX2RhdGEgJT4lCiAgZ3JvdXBfYnkobG9jYXRpb25fZ2VuZXJhbCkgJT4lCiAgc3VtbWFyaXNlKAogICAgbWVkID0gbWVkaWFuKGFzLm51bWVyaWMocmF0aW5nKSkpICU+JSB1bmdyb3VwKCkKCmdncGxvdChjbGVhbl9oaWtlX2RhdGEsIGFlcyh4ID0gcmVvcmRlcihsb2NhdGlvbl9nZW5lcmFsLCByYXRpbmcsIEZVTiA9IG1lZGlhbiksIHkgPSByYXRpbmcpKSArCiAgZ2VvbV9ib3hwbG90KGFlcyhjb2xvciA9IGxvY2F0aW9uX2dlbmVyYWwpKSArCiAgZ2VvbV9wb2ludChkYXRhID0gbWVkaWFuX3ZhbHVlcywgYWVzKHggPSBsb2NhdGlvbl9nZW5lcmFsLCB5ID0gbWVkLCBmaWxsID0gbG9jYXRpb25fZ2VuZXJhbCksIHNoYXBlID0gMjMsIHNpemUgPSA1LCBjb2xvciA9ICJncmV5IikgKwogIGd1aWRlcyhmaWxsID0gRkFMU0UsIGNvbG9yID0gRkFMU0UpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoeSA9ICJSYXRpbmciLCB4ID0gIkdlbmVyYWwgTG9jYXRpb24iLCB0aXRsZSA9ICJXYXNoaW5ndG9uIFRyYWlsIFJhdGluZ3MgYnkgR2VuZXJhbCBMb2NhdGlvbiIsIGNhcHRpb24gPSAiRGF0YSBmcm9tIFdhc2hpbmdvbiBUcmFpbHMgQXNzb2NpYXRpb24gKHd0YS5vcmcpIikgKwogIHRoZW1lX2xpZ2h0KCkgKwogIHNjYWxlX2NvbG9yX2Z1dHVyYW1hKCkgKwogIHNjYWxlX2ZpbGxfZnV0dXJhbWEoKSArCiB0aGVtZSgKICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMiwgZmFjZT0iYm9sZCIpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwKICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIKICApIApgYGAKCiMjIyBPbmUtd2F5IHZzIFJvdW5kdHJpcCB0cmFpbHMgCmBgYHtyfQpjbGVhbl9oaWtlX2RhdGEgJT4lIGdyb3VwX2J5KGxvY2F0aW9uX2dlbmVyYWwsdHJpcCkgJT4lIHRhbGx5KCkgJT4lIGZpbHRlcih0cmlwICE9InRyYWlscyIpICU+JSBnZ3Bsb3QoYWVzKHg9bG9jYXRpb25fZ2VuZXJhbCwgeT1uLCBmaWxsPXRyaXApKSArIGdlb21fY29sKHBvc2l0aW9uPSJkb2RnZSIpICsgY29vcmRfZmxpcCgpICsgdGhlbWVfbGlnaHQoKSArIHRoZW1lKAogICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBmYWNlPSJib2xkIiksCiAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTAsIGNvbG9yPSIjMzQzYTQwIiksCiAgICBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OSksCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKSArCiAgICBsYWJzKHk9IiIsIHg9IiIsIGZpbGw9IiIsIHRpdGxlID0gIk9uZS13YXkgdnMgUm91bmR0cmlwIHRyYWlscyBpbiBXYXNoaW5ndG9uIiwgY2FwdGlvbj0iRGF0YSBmcm9tIFdhc2hpbmdvbiBUcmFpbHMgQXNzb2NpYXRpb24gKHd0YS5vcmcpIikgKwogICAgc2NhbGVfZmlsbF9qYW1hKCkKYGBgCgojIyMgRmVhdHVyZXMgCmBgYHtyfQojY2xlYW5pbmcgc2NyaXB0IGZyb20gQGFsZXhjb29rc29uCmhpa2VfZGF0YV9yYXcgPC0gcmVhZF9yZHModXJsKCdodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L21hc3Rlci9kYXRhLzIwMjAvMjAyMC0xMS0yNC9oaWtlX2RhdGEucmRzJykpCgpoaWtlIDwtIGhpa2VfZGF0YV9yYXcgJT4lCiAgZGlzdGluY3QobmFtZSwgbG9jYXRpb24sIC5rZWVwX2FsbCA9IFRSVUUpICU+JQogIG11dGF0ZSh0cmFpbF9pZCA9IHJvd19udW1iZXIoKSkgJT4lCiAgcmVsb2NhdGUodHJhaWxfaWQpICU+JQogIG11dGF0ZShhY3Jvc3MoLmNvbHMgPSBjKGxlbmd0aCwgZ2FpbiwgaGlnaHBvaW50LCByYXRpbmcpLCBwYXJzZV9udW1iZXIpKSAlPiUKICByZW5hbWUobGVuZ3RoX21pbGVzID0gbGVuZ3RoLAogICAgICAgICBnYWluX2Z0ID0gZ2FpbiwKICAgICAgICAgaGlnaHBvaW50X2Z0ID0gaGlnaHBvaW50KSAlPiUKICBtdXRhdGUocmF0aW5nID0gaWZlbHNlKHJhdGluZyA9PSAwLCBOQSwgcmF0aW5nKSkKCmZlYXR1cmVzIDwtIGhpa2UgJT4lCiAgc2VsZWN0KHRyYWlsX2lkLCBmZWF0dXJlcykgJT4lCiAgdW5uZXN0KGZlYXR1cmVzKSAlPiUKICByZW5hbWUoZmVhdHVyZSA9IGZlYXR1cmVzKQpgYGAKCmBgYHtyfQpmZWF0dXJlcyAlPiUgZ3JvdXBfYnkoZmVhdHVyZSkgJT4lIHRhbGx5KHNvcnQ9VCkgJT4lIAogIGdncGxvdChhZXMoeD1yZW9yZGVyKGZlYXR1cmUsbiksIHk9bikpICsKICBnZW9tX3NlZ21lbnQoYWVzKHg9cmVvcmRlcihmZWF0dXJlLG4pLCB4ZW5kPWZlYXR1cmUsIHk9MCwgeWVuZD1uKSwgY29sb3I9IiMwODRjNjEiKSArCiAgZ2VvbV9wb2ludChjb2xvcj0iIzRmNzcyZCIsIHNpemU9MywgYWxwaGE9MC45KSArIHNjYWxlX2NvbG9yX3ZpcmlkaXMoKSArCiAgdGhlbWVfbGlnaHQoKSArCiAgY29vcmRfZmxpcCgpICsgCiAgdGhlbWUoCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIsIGZhY2U9ImJvbGQiKSwKICAgIGF4aXMudGl0bGU9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpICsKICAgIGxhYnMoeT0iTnVtYmVyIG9mIFRyYWlscyIsIHg9IkZlYXR1cmUiLCBmaWxsPSIiLCB0aXRsZSA9ICJXYXNoaW5ndG9uIFRyYWlscyBGZWF0dXJlcyIsIGNhcHRpb249IkRhdGEgZnJvbSBXYXNoaW5nb24gVHJhaWxzIEFzc29jaWF0aW9uICh3dGEub3JnKSIpCmBgYAoK