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=