Economist-Style Plot using R

R Codes for Data Cleaning and Visualization
Above Economist-Style Plot can be created by using R as follows:
#==========================================
# Collect data from WHO and pre-process
#==========================================
# devtools::install_github("expersso/WHO")
library(WHO)
library(tidyverse)
# Government and total expenditure data:
expenditure_gov <- get_data("WHS7_108")
expenditure_total <- get_data("WHS7_105")
expenditure_gov %>%
filter(year == 2014, !is.na(country)) %>%
select(gov_exp = value, country) -> df_gov
expenditure_total %>%
filter(year == 2014, !is.na(country)) %>%
select(total_exp = value, country) -> df_total
nations <- intersect(df_gov$country, df_total$country)
full_join(df_total %>% filter(country %in% nations),
df_gov %>% filter(country %in% nations), by = "country") %>%
select(country, everything()) %>%
mutate(private_exp = total_exp - gov_exp) %>%
mutate(gov_rate = gov_exp / total_exp) %>%
arrange(gov_rate) %>%
mutate(rank = 1:nrow(.)) -> dfPlot
# Rename:
dfPlot %>%
mutate(country = case_when(country == "Brunei Darussalam" ~ "Brunei",
country == "Republic of Korea" ~ "South Korea",
country == "United Kingdom of Great Britain and Northern Ireland" ~ "United Kingdom",
country == "United States of America" ~ "United States",
country == "Russian Federation" ~ "Russia",
country == "Viet Nam" ~ "Vietnam",
TRUE ~ country)) -> dfPlot
# Some countries selected:
northernCon <- c("Denmark", "Finland", "Norway", "Sweden")
specialCon <- c("Qatar", "Brunei", "Cuba")
aseanCon <- c("Singapore", "Thailand", "Malaysia", "Vietnam")
others <- c("India", "China", "United States", "United Kingdom", "France",
"Germany", "Canada", "Japan", "South Korea")
dfPlot %>%
filter(country %in% c(northernCon, specialCon, aseanCon, others)) %>%
arrange(gov_rate) -> df
my_levels <- df %>% pull(country)
df %>%
mutate(country = factor(country, levels = my_levels)) %>%
select(country, private_exp, gov_exp) %>%
gather(type, value, -country) -> df1
# Colors and font selected: http://pattern-library.economist.com/color.html
# https://yutannihilation.github.io/allYourFigureAreBelongToUs/ggthemes/economist_pal/
my_colors <- c("#014d64", "#01a2d9")
my_font <- "Ubuntu Condensed"
colorLevels <- c("private_exp", "gov_exp")
#==================================
# Solution 1 (but i do not like)
#==================================
df1 %>%
mutate(type = factor(type, levels = colorLevels)) -> df1
df1 %>%
ggplot(aes(x = country, y = value, fill = type)) +
geom_col(position = "fill") +
coord_flip() +
scale_fill_manual(values = my_colors) +
theme_minimal(base_family = my_font)
#================
# Solution 2
#================
library(ggrepel)
df %>%
mutate(gov_rate = 100*gov_rate, total_rate = 100) %>%
mutate(country = factor(country, levels = country)) %>%
mutate(label = round(gov_rate, 1) %>% as.character()) %>%
mutate(label = case_when(!str_detect(label, "\\.") ~ paste0(label, ".0"), TRUE ~ label)) %>%
mutate(label = paste0(label, "%")) %>%
mutate(label_money = round(total_exp, 0) %>% scales::dollar()) -> dfSolution2
# Version 1:
ggplot() +
coord_flip() +
theme_minimal(base_family = my_font, base_size = 14) +
geom_col(data = dfSolution2, aes(x = country, y = total_rate, fill = "Government"), width = 0.9) +
geom_col(data = dfSolution2, aes(x = country, y = gov_rate, fill = "Private"), width = 0.9) +
scale_y_continuous(limits = c(0, 120)) +
geom_text(data = dfSolution2, aes(x = country, y = 5, label = label), color = "white", family = my_font, size = 4.5) +
scale_fill_manual(values = my_colors) +
geom_label_repel(data = dfSolution2, aes(x = country, y = 103, label = label_money), hjust = 0,
family = my_font, size = 4.3, direction = "x", nudge_y = 1, label.r = 0, box.padding = 0) +
theme(legend.position = "top")
# Version 2:
midd <- (102 + 110) / 2
dfSolution2 %>%
mutate(color_label_y = case_when(country == "Vietnam" ~ "#e5001c", TRUE ~ "grey20")) %>%
mutate(bold_y = case_when(country == "Vietnam" ~ "bold", TRUE ~ "plain")) -> dfSolution2
ggplot() +
coord_flip() +
theme_minimal(base_family = my_font, base_size = 14) +
geom_col(data = dfSolution2, aes(x = country, y = total_rate, fill = "Private"), width = 0.9) +
geom_col(data = dfSolution2, aes(x = country, y = gov_rate, fill = "Government"), width = 0.9) +
scale_y_continuous(limits = c(0, 110), expand = c(0, 0)) +
scale_x_discrete(expand = c(0.08, 0)) +
geom_text(data = dfSolution2, aes(x = country, y = 4, label = label), color = "white", family = my_font, size = 4.5) +
scale_fill_manual(values = my_colors) +
theme(legend.direction = "horizontal") +
theme(legend.position = c(0.5, 0.98)) +
theme(legend.title = element_blank()) +
theme(axis.title = element_blank()) +
theme(axis.text.x = element_blank()) +
theme(panel.grid = element_blank()) +
geom_rect(aes(xmin = 0.5, xmax = Inf, ymin = 102, ymax = 110), fill = "#efefe3") +
geom_text(data = dfSolution2 %>% filter(country == "Cuba"), aes(x = country, y = 106, label = "Total"),
vjust = -1.9, family = my_font, fontface = "bold", size = 4.5) +
geom_text(data = dfSolution2, aes(x = country, y = midd, label = scales::comma(round(total_exp, 0))),
family = my_font, size = 4.5, color = "grey30") +
theme(plot.margin = unit(rep(0.5, 4), "cm")) +
labs(x = NULL, y = NULL,
title = "Share of Vietnam government spending on health care, 2014",
subtitle = "Heath expenditure per capita in Vietnam was reported at $390 (PPP)\nand share of government spending on health care was 54.1%.",
caption = "Source: World Health Organization (WHO)") +
theme(plot.title = element_text(size = 23, colour = "grey20"),
plot.subtitle = element_text(color = "grey30", size = 15),
plot.caption = element_text(color = "grey30", face = "italic", size = 11)) +
theme(axis.text.y = element_text(color = dfSolution2$color_label_y, size = 12, face = dfSolution2$bold_y))
library(grid)
grid.rect(x = 0.015, y = 0.94, hjust = 1, vjust = 0, gp = gpar(fill = "#e5001c", lwd = 0))
grid.rect(x = 1, y = 1 - 0.005, hjust = 1, vjust = 0, gp = gpar(fill = "#e5001c", lwd = 0))
LS0tCnRpdGxlOiAiU2hhcmUgb2YgVmlldG5hbSBnb3Zlcm5tZW50IHNwZW5kaW5nIG9uIGhlYWx0aCBjYXJlLCAyMDE0ICIKYXV0aG9yOiAnTmd1eWVuIENoaSBEdW5nJwpzdWJ0aXRsZTogIkRhaWx5IEdyYXBoIFNlcmllcyIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6IAogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgIyAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuCiAgICAjIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogImZsYXRseSIKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCi0tLQoKYGBge3Igc2V0dXAsaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZmlnLndpZHRoID0gMTAsIGZpZy5oZWlnaHQgPSA2KQpgYGAKCiMgRWNvbm9taXN0LVN0eWxlIFBsb3QgdXNpbmcgUgogIAohW10oL2hvbWUva2hhbmhhbi9oZWF0aGNhcmUucG5nKQoKCiMgUiBDb2RlcyBmb3IgRGF0YSBDbGVhbmluZyBhbmQgVmlzdWFsaXphdGlvbgoKQWJvdmUgRWNvbm9taXN0LVN0eWxlIFBsb3QgY2FuIGJlIGNyZWF0ZWQgYnkgdXNpbmcgUiBhcyBmb2xsb3dzOiAKCmBgYHtyLCBldmFsPUZBTFNFfQoKCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyAgQ29sbGVjdCBkYXRhIGZyb20gV0hPIGFuZCBwcmUtcHJvY2VzcwojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgojIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiZXhwZXJzc28vV0hPIikKCmxpYnJhcnkoV0hPKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKCiMgR292ZXJubWVudCBhbmQgdG90YWwgZXhwZW5kaXR1cmUgZGF0YTogCgpleHBlbmRpdHVyZV9nb3YgPC0gZ2V0X2RhdGEoIldIUzdfMTA4IikKZXhwZW5kaXR1cmVfdG90YWwgPC0gZ2V0X2RhdGEoIldIUzdfMTA1IikKCmV4cGVuZGl0dXJlX2dvdiAlPiUgCiAgZmlsdGVyKHllYXIgPT0gMjAxNCwgIWlzLm5hKGNvdW50cnkpKSAlPiUgCiAgc2VsZWN0KGdvdl9leHAgPSB2YWx1ZSwgY291bnRyeSkgLT4gZGZfZ292CgpleHBlbmRpdHVyZV90b3RhbCAlPiUgCiAgZmlsdGVyKHllYXIgPT0gMjAxNCwgIWlzLm5hKGNvdW50cnkpKSAlPiUgCiAgc2VsZWN0KHRvdGFsX2V4cCA9IHZhbHVlLCBjb3VudHJ5KSAtPiBkZl90b3RhbAoKbmF0aW9ucyA8LSBpbnRlcnNlY3QoZGZfZ292JGNvdW50cnksIGRmX3RvdGFsJGNvdW50cnkpCgpmdWxsX2pvaW4oZGZfdG90YWwgJT4lIGZpbHRlcihjb3VudHJ5ICVpbiUgbmF0aW9ucyksIAogICAgICAgICAgZGZfZ292ICU+JSBmaWx0ZXIoY291bnRyeSAlaW4lIG5hdGlvbnMpLCBieSA9ICJjb3VudHJ5IikgJT4lIAogIHNlbGVjdChjb3VudHJ5LCBldmVyeXRoaW5nKCkpICU+JSAKICBtdXRhdGUocHJpdmF0ZV9leHAgPSB0b3RhbF9leHAgLSBnb3ZfZXhwKSAlPiUgCiAgbXV0YXRlKGdvdl9yYXRlID0gZ292X2V4cCAvIHRvdGFsX2V4cCkgJT4lIAogIGFycmFuZ2UoZ292X3JhdGUpICU+JSAKICBtdXRhdGUocmFuayA9IDE6bnJvdyguKSkgLT4gZGZQbG90CgojIFJlbmFtZTogCmRmUGxvdCAlPiUgCiAgbXV0YXRlKGNvdW50cnkgPSBjYXNlX3doZW4oY291bnRyeSA9PSAiQnJ1bmVpIERhcnVzc2FsYW0iIH4gIkJydW5laSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cnkgPT0gIlJlcHVibGljIG9mIEtvcmVhIiB+ICJTb3V0aCBLb3JlYSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50cnkgPT0gIlVuaXRlZCBLaW5nZG9tIG9mIEdyZWF0IEJyaXRhaW4gYW5kIE5vcnRoZXJuIElyZWxhbmQiIH4gIlVuaXRlZCBLaW5nZG9tIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIiB+ICJVbml0ZWQgU3RhdGVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRyeSA9PSAiUnVzc2lhbiBGZWRlcmF0aW9uIiB+ICJSdXNzaWEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudHJ5ID09ICJWaWV0IE5hbSIgfiAiVmlldG5hbSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBjb3VudHJ5KSkgLT4gZGZQbG90CgojIFNvbWUgY291bnRyaWVzIHNlbGVjdGVkOiAKCm5vcnRoZXJuQ29uIDwtIGMoIkRlbm1hcmsiLCAiRmlubGFuZCIsICJOb3J3YXkiLCAiU3dlZGVuIikKc3BlY2lhbENvbiA8LSBjKCJRYXRhciIsICJCcnVuZWkiLCAiQ3ViYSIpCmFzZWFuQ29uIDwtIGMoIlNpbmdhcG9yZSIsICJUaGFpbGFuZCIsICJNYWxheXNpYSIsICJWaWV0bmFtIikKb3RoZXJzIDwtIGMoIkluZGlhIiwgIkNoaW5hIiwgIlVuaXRlZCBTdGF0ZXMiLCAiVW5pdGVkIEtpbmdkb20iLCAiRnJhbmNlIiwgCiAgICAgICAgICAgIkdlcm1hbnkiLCAiQ2FuYWRhIiwgIkphcGFuIiwgIlNvdXRoIEtvcmVhIikKCmRmUGxvdCAlPiUgCiAgZmlsdGVyKGNvdW50cnkgJWluJSBjKG5vcnRoZXJuQ29uLCBzcGVjaWFsQ29uLCBhc2VhbkNvbiwgb3RoZXJzKSkgJT4lIAogIGFycmFuZ2UoZ292X3JhdGUpIC0+IGRmCgpteV9sZXZlbHMgPC0gZGYgJT4lIHB1bGwoY291bnRyeSkKCmRmICU+JSAKICBtdXRhdGUoY291bnRyeSA9IGZhY3Rvcihjb3VudHJ5LCBsZXZlbHMgPSBteV9sZXZlbHMpKSAlPiUKICBzZWxlY3QoY291bnRyeSwgcHJpdmF0ZV9leHAsIGdvdl9leHApICU+JSAKICBnYXRoZXIodHlwZSwgdmFsdWUsIC1jb3VudHJ5KSAtPiBkZjEKCiMgQ29sb3JzIGFuZCBmb250IHNlbGVjdGVkOiBodHRwOi8vcGF0dGVybi1saWJyYXJ5LmVjb25vbWlzdC5jb20vY29sb3IuaHRtbAojIGh0dHBzOi8veXV0YW5uaWhpbGF0aW9uLmdpdGh1Yi5pby9hbGxZb3VyRmlndXJlQXJlQmVsb25nVG9Vcy9nZ3RoZW1lcy9lY29ub21pc3RfcGFsLwoKbXlfY29sb3JzIDwtIGMoIiMwMTRkNjQiLCAiIzAxYTJkOSIpCm15X2ZvbnQgPC0gIlVidW50dSBDb25kZW5zZWQiCmNvbG9yTGV2ZWxzIDwtIGMoInByaXZhdGVfZXhwIiwgImdvdl9leHAiKQoKIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KIyAgU29sdXRpb24gMSAoYnV0IGkgZG8gbm90IGxpa2UpCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgpkZjEgJT4lIAogIG11dGF0ZSh0eXBlID0gZmFjdG9yKHR5cGUsIGxldmVscyA9IGNvbG9yTGV2ZWxzKSkgLT4gZGYxCgpkZjEgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvdW50cnksIHkgPSB2YWx1ZSwgZmlsbCA9IHR5cGUpKSArIAogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArIAogIGNvb3JkX2ZsaXAoKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG15X2NvbG9ycykgKyAKICB0aGVtZV9taW5pbWFsKGJhc2VfZmFtaWx5ID0gbXlfZm9udCkKCiM9PT09PT09PT09PT09PT09CiMgICBTb2x1dGlvbiAyCiM9PT09PT09PT09PT09PT09CgpsaWJyYXJ5KGdncmVwZWwpCgpkZiAlPiUgCiAgbXV0YXRlKGdvdl9yYXRlID0gMTAwKmdvdl9yYXRlLCB0b3RhbF9yYXRlID0gMTAwKSAlPiUgCiAgbXV0YXRlKGNvdW50cnkgPSBmYWN0b3IoY291bnRyeSwgbGV2ZWxzID0gY291bnRyeSkpICU+JSAKICBtdXRhdGUobGFiZWwgPSByb3VuZChnb3ZfcmF0ZSwgMSkgJT4lIGFzLmNoYXJhY3RlcigpKSAlPiUgCiAgbXV0YXRlKGxhYmVsID0gY2FzZV93aGVuKCFzdHJfZGV0ZWN0KGxhYmVsLCAiXFwuIikgfiBwYXN0ZTAobGFiZWwsICIuMCIpLCBUUlVFIH4gbGFiZWwpKSAlPiUgCiAgbXV0YXRlKGxhYmVsID0gcGFzdGUwKGxhYmVsLCAiJSIpKSAlPiUgCiAgbXV0YXRlKGxhYmVsX21vbmV5ID0gcm91bmQodG90YWxfZXhwLCAwKSAlPiUgc2NhbGVzOjpkb2xsYXIoKSkgLT4gZGZTb2x1dGlvbjIKCiMgVmVyc2lvbiAxOiAKCmdncGxvdCgpICsgCiAgY29vcmRfZmxpcCgpICsgCiAgdGhlbWVfbWluaW1hbChiYXNlX2ZhbWlseSA9IG15X2ZvbnQsIGJhc2Vfc2l6ZSA9IDE0KSArIAogIGdlb21fY29sKGRhdGEgPSBkZlNvbHV0aW9uMiwgYWVzKHggPSBjb3VudHJ5LCB5ID0gdG90YWxfcmF0ZSwgZmlsbCA9ICJHb3Zlcm5tZW50IiksIHdpZHRoID0gMC45KSArIAogIGdlb21fY29sKGRhdGEgPSBkZlNvbHV0aW9uMiwgYWVzKHggPSBjb3VudHJ5LCB5ID0gZ292X3JhdGUsIGZpbGwgPSAiUHJpdmF0ZSIpLCB3aWR0aCA9IDAuOSkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEyMCkpICsgCiAgZ2VvbV90ZXh0KGRhdGEgPSBkZlNvbHV0aW9uMiwgYWVzKHggPSBjb3VudHJ5LCB5ID0gNSwgbGFiZWwgPSBsYWJlbCksIGNvbG9yID0gIndoaXRlIiwgZmFtaWx5ID0gbXlfZm9udCwgc2l6ZSA9IDQuNSkgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBteV9jb2xvcnMpICsgCiAgZ2VvbV9sYWJlbF9yZXBlbChkYXRhID0gZGZTb2x1dGlvbjIsIGFlcyh4ID0gY291bnRyeSwgeSA9IDEwMywgbGFiZWwgPSBsYWJlbF9tb25leSksIGhqdXN0ID0gMCwgCiAgICAgICAgICAgICAgICAgICBmYW1pbHkgPSBteV9mb250LCBzaXplID0gNC4zLCBkaXJlY3Rpb24gPSAieCIsIG51ZGdlX3kgPSAxLCBsYWJlbC5yID0gMCwgYm94LnBhZGRpbmcgPSAwKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKCiMgVmVyc2lvbiAyOiAKCm1pZGQgPC0gKDEwMiArIDExMCkgLyAyCgpkZlNvbHV0aW9uMiAlPiUgCiAgbXV0YXRlKGNvbG9yX2xhYmVsX3kgPSBjYXNlX3doZW4oY291bnRyeSA9PSAiVmlldG5hbSIgfiAiI2U1MDAxYyIsIFRSVUUgfiAiZ3JleTIwIikpICU+JSAKICBtdXRhdGUoYm9sZF95ID0gY2FzZV93aGVuKGNvdW50cnkgPT0gIlZpZXRuYW0iIH4gImJvbGQiLCBUUlVFIH4gInBsYWluIikpIC0+IGRmU29sdXRpb24yCgoKZ2dwbG90KCkgKyAKICBjb29yZF9mbGlwKCkgKyAKICB0aGVtZV9taW5pbWFsKGJhc2VfZmFtaWx5ID0gbXlfZm9udCwgYmFzZV9zaXplID0gMTQpICsgCiAgZ2VvbV9jb2woZGF0YSA9IGRmU29sdXRpb24yLCBhZXMoeCA9IGNvdW50cnksIHkgPSB0b3RhbF9yYXRlLCBmaWxsID0gIlByaXZhdGUiKSwgd2lkdGggPSAwLjkpICsgCiAgZ2VvbV9jb2woZGF0YSA9IGRmU29sdXRpb24yLCBhZXMoeCA9IGNvdW50cnksIHkgPSBnb3ZfcmF0ZSwgZmlsbCA9ICJHb3Zlcm5tZW50IiksIHdpZHRoID0gMC45KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgMTEwKSwgZXhwYW5kID0gYygwLCAwKSkgKyAKICBzY2FsZV94X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMC4wOCwgMCkpICsgCiAgZ2VvbV90ZXh0KGRhdGEgPSBkZlNvbHV0aW9uMiwgYWVzKHggPSBjb3VudHJ5LCB5ID0gNCwgbGFiZWwgPSBsYWJlbCksIGNvbG9yID0gIndoaXRlIiwgZmFtaWx5ID0gbXlfZm9udCwgc2l6ZSA9IDQuNSkgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBteV9jb2xvcnMpICsgCiAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuNSwgMC45OCkpICsgCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSArIAogIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSkgKyAKICBnZW9tX3JlY3QoYWVzKHhtaW4gPSAwLjUsIHhtYXggPSBJbmYsIHltaW4gPSAxMDIsIHltYXggPSAxMTApLCBmaWxsID0gIiNlZmVmZTMiKSArIAogIGdlb21fdGV4dChkYXRhID0gZGZTb2x1dGlvbjIgJT4lIGZpbHRlcihjb3VudHJ5ID09ICJDdWJhIiksIGFlcyh4ID0gY291bnRyeSwgeSA9IDEwNiwgbGFiZWwgPSAiVG90YWwiKSwgCiAgICAgICAgICAgIHZqdXN0ID0gLTEuOSwgZmFtaWx5ID0gbXlfZm9udCwgZm9udGZhY2UgPSAiYm9sZCIsIHNpemUgPSA0LjUpICsgCiAgZ2VvbV90ZXh0KGRhdGEgPSBkZlNvbHV0aW9uMiwgYWVzKHggPSBjb3VudHJ5LCB5ID0gbWlkZCwgbGFiZWwgPSBzY2FsZXM6OmNvbW1hKHJvdW5kKHRvdGFsX2V4cCwgMCkpKSwgCiAgICAgICAgICAgIGZhbWlseSA9IG15X2ZvbnQsIHNpemUgPSA0LjUsIGNvbG9yID0gImdyZXkzMCIpICsgCiAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KHJlcCgwLjUsIDQpLCAiY20iKSkgKyAKICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgCiAgICAgICB0aXRsZSA9ICJTaGFyZSBvZiBWaWV0bmFtIGdvdmVybm1lbnQgc3BlbmRpbmcgb24gaGVhbHRoIGNhcmUsIDIwMTQiLCAKICAgICAgIHN1YnRpdGxlID0gIkhlYXRoIGV4cGVuZGl0dXJlIHBlciBjYXBpdGEgaW4gVmlldG5hbSB3YXMgcmVwb3J0ZWQgYXQgJDM5MCAoUFBQKVxuYW5kIHNoYXJlIG9mIGdvdmVybm1lbnQgc3BlbmRpbmcgb24gaGVhbHRoIGNhcmUgd2FzIDU0LjElLiIsIAogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IFdvcmxkIEhlYWx0aCBPcmdhbml6YXRpb24gKFdITykiKSArIAogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIzLCBjb2xvdXIgPSAiZ3JleTIwIiksIAogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiZ3JleTMwIiwgc2l6ZSA9IDE1KSwgCiAgICAgICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImdyZXkzMCIsIGZhY2UgPSAiaXRhbGljIiwgc2l6ZSA9IDExKSkgKyAKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9IGRmU29sdXRpb24yJGNvbG9yX2xhYmVsX3ksIHNpemUgPSAxMiwgZmFjZSA9IGRmU29sdXRpb24yJGJvbGRfeSkpIAoKbGlicmFyeShncmlkKQpncmlkLnJlY3QoeCA9IDAuMDE1LCB5ID0gMC45NCwgaGp1c3QgPSAxLCB2anVzdCA9IDAsIGdwID0gZ3BhcihmaWxsID0gIiNlNTAwMWMiLCBsd2QgPSAwKSkgIApncmlkLnJlY3QoeCA9IDEsIHkgPSAxIC0gMC4wMDUsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLCAgZ3AgPSBncGFyKGZpbGwgPSAiI2U1MDAxYyIsIGx3ZCA9IDApKSAgIAoKYGBgCgo=