Population Pyramids

R Codes for Collecting Data and Visualization

#==================================================================================
#   Scrapping population data with inputs are: 
#   1. Given year, 
#   2. Country code selected from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
#==================================================================================

# Clear workspace: 
rm(list = ls())

# Load some packages for scrapping data and data manipulation: 
library(rvest)
library(magrittr)
library(tidyverse)

# A function for collecting population data: 

get_population <- function(countryCode_selected, year_selected) {
  
  base_url <- "https://www.census.gov/data-tools/demo/idb/region.php?N=%20Results%20&T=10&A=separate&RT=0&Y="
  link <- paste0(paste0(paste0(base_url, year_selected), "&R=-1&C="), countryCode_selected)
  
  link %>% 
    read_html() -> html_content  
  
  html_content %>% 
    html_table(fill = TRUE) %>% 
    .[[1]] -> pop_df
  
  names(pop_df) <- str_replace_all(names(pop_df), " ", "_")
  
  country_name <- html_content %>% 
    html_nodes('.query_source a') %>% 
    html_text() 
  
  if (length(country_name) == 2) {
    country_name <- country_name[2]
  }
  
  
  final_df <- pop_df %>% 
    select(-Year, -Age, -contains("Percent"), -Sex_Ratio) %>% 
    mutate_all(function(x) {str_replace_all(x, "[^0-9]", "") %>% as.numeric()}) %>% 
    mutate(Year = pop_df$Year, Country = country_name[1], Age = pop_df$Age) %>% 
    select(Year, Country, Age, everything()) %>% 
    mutate(Percent_Both_Sexes = Both_Sexes_Population / Both_Sexes_Population[1], 
           Percent_Male = Male_Population / Male_Population[1], 
           Percent_Female = Female_Population / Female_Population[1], 
           Sex_Ratio = Male_Population / Female_Population, 
           Age = case_when(Age == "0-4" ~ "00-04", Age == "5-9" ~ "05-09", TRUE ~ Age))
  
  return(final_df)
  
}


# Function for getting population data for Vietnam by given year: 

pop_data_ByYear <- function(year_selected) {
  get_population("VM", year_selected) %>% 
    slice(-c(1, 20:22)) %>% 
    select(Year, Age, Male_Population, Female_Population) %>% 
    mutate(Female_Population = -1*Female_Population) %>% 
    gather(Gender, Value, -Age, -Year) %>% 
    return()
}


# Use the function for getting data: 
lapply(c(2018, 2005, 2000, 1995), pop_data_ByYear) -> total_list
total_df <- do.call("rbind", total_list)

#=========================
#  Data Visualization
#=========================

library(extrafont)

# Colors and font selected: 
my_colors <- c("#2E74C0", "#CB454A")
my_font <- "Roboto Condensed"


#---------------------------------
#   Version 1: Using geom_col()
#---------------------------------

total_df %>% 
  ggplot(aes(Age, Value, fill = Gender)) + 
  geom_col(position = "stack", width = 0.85) + 
  scale_y_continuous(expand = c(0, 0.5)) + 
  facet_wrap(~ Year) + 
  coord_flip() + 
  scale_y_continuous(breaks = seq(-5000000, 5000000, 1000000), 
                     limits = c(-5000000, 5000000), 
                     labels = c(paste0(seq(5, 0, -1), "M"), paste0(1:5, "M"))) + 
  theme_minimal() + 
  scale_fill_manual(values = my_colors, name = "", labels = c("Female", "Male")) + 
  # guides(fill = guide_legend(reverse = TRUE)) + 
  theme(panel.grid.major.x = element_line(linetype = "dotted", size = 0.2, color = "grey40")) + 
  theme(panel.grid.major.y = element_blank()) + 
  theme(panel.grid.minor.y = element_blank()) + 
  theme(panel.grid.minor.x = element_blank()) + 
  theme(legend.position = "top") + 
  theme(axis.text.y = element_text(size = 10, family = my_font)) + 
  theme(axis.text.x = element_text(size = 10, family = my_font)) + 
  theme(plot.title = element_text(family = my_font, size = 28)) + 
  theme(plot.subtitle = element_text(family = my_font, size = 13, color = "gray40")) + 
  theme(plot.caption = element_text(family = my_font, size = 12, colour = "grey40", face = "italic")) + 
  theme(plot.margin = unit(c(1.2, 1.2, 1.2, 1.2), "cm")) + 
  theme(legend.text = element_text(size = 12, face = "bold", color = "grey30", family = my_font)) + 
  theme(strip.text = element_text(color = "grey20", size = 13, face = "bold", family = my_font)) +  
  labs(x = NULL, y = NULL, 
       title = "Population Pyramids of Vietnam: 1995 - 2018",
       subtitle = "The age-sex structure of a country's population and may provide insights about political and social stability,\nas well as economic development. Countries with young populations need to invest more in schools,\nwhile countries with older populations need to invest more in the health sector.",
       caption = "Data Source: https://www.census.gov")


#-----------------------------------------
#   Version 2: Using geom_linerange()
#-----------------------------------------

total_df %>% 
  ggplot(aes(x = Age, color = Gender))+
  geom_linerange(data = total_df %>% filter(Gender == "Male_Population"),
                 aes(ymin = -0.3, ymax = -0.3 + Value), size = 3.5, alpha = 1) +
  geom_linerange(data = total_df %>% filter(Gender != "Male_Population"), 
                 aes(ymin = 0.3, ymax = 0.3 + Value), size = 3.5, alpha = 1) + 
  geom_label(aes(x = Age, y = 0, label = Age), inherit.aes = TRUE, family = my_font, 
             size = 3.5, label.padding = unit(0, "lines"), label.size = 0, 
             label.r = unit(0.0, "lines"), fill = "#f5f5f2", alpha = 1, color = "gray20") + 
  theme_minimal() + 
  coord_flip() + 
  facet_wrap( ~ Year) + 
  scale_y_continuous(breaks = seq(-5000000, 5000000, 1000000), 
                     limits = c(-5000000, 5000000), 
                     labels = c(paste0(seq(5, 0, -1), "M"), paste0(1:5, "M"))) + 
  scale_color_manual(name = "", values = c(Female_Population = "#3E606F", Male_Population = "#8C3F4D"), 
                     labels = c("Male", "Female")) + 
  theme(panel.grid.major.y = element_blank()) + 
  theme(plot.title = element_text(face = "bold", size = 28, family = my_font, margin = margin(b = 10), hjust = 0, color = "grey20")) + 
  theme(plot.subtitle = element_text(size = 14, margin = margin(b = 20), hjust = 0, family = my_font, color = "grey30")) + 
  theme(plot.caption = element_text(size = 13, color = "grey50", family = my_font)) + 
  theme(axis.text.y = element_blank()) + 
  theme(axis.text.x = element_text(size = 12, color = "grey20", family = my_font, face = "bold")) + 
  theme(plot.background = element_rect(fill = "#EFF2F4", color = NA)) + 
  theme(panel.grid.major.x = element_line(linetype = "dotted", size = 0.2, color = "grey40")) + 
  theme(plot.margin = unit(c(1.2, 1.2, 1.2, 1.2), "cm")) + 
  theme(legend.position = "top") + 
  theme(legend.text = element_text(size = 13, face = "bold", color = "grey30", family = my_font)) + 
  theme(legend.text.align = 1) + 
  theme(strip.text = element_text(color = "grey20", size = 14, face = "bold", family = my_font)) + 
  # theme(strip.text = element_text(color = "grey20", size = 14, face = "bold", hjust = 0.026) + 
  labs(x = NULL, y = NULL, 
       title = "Population Pyramids of Vietnam: 1995 - 2018",
       subtitle = "The age-sex structure of a country's population and may provide insights about political and social stability,\nas well as economic development. Countries with young populations need to invest more in schools,\nwhile countries with older populations need to invest more in the health sector.",
       caption = "Data Source: https://www.census.gov")
LS0tDQp0aXRsZTogIlBvcHVsYXRpb24gU3RydWN0dXJlIG9mIFZpZXRuYW06IDE5OTUgLSAyMDE4Ig0KYXV0aG9yOiAiTmd1eWVuIENoaSBEdW5nIg0Kc3VidGl0bGU6ICJEYWlseSBHcmFwaCBTZXJpZXMiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgIyBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBoaWdobGlnaHQ6IHplbmJ1cm4NCiAgICB0aGVtZTogZmxhdGx5DQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQotLS0NCg0KYGBge3Igc2V0dXAsaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZpZy5yZXRpbmE9MikNCmBgYA0KDQojIFBvcHVsYXRpb24gUHlyYW1pZHMNCg0KIVtdKEM6XFxVc2Vyc1xcWmJvb2tcXERlc2t0b3BcXHBpY1xccGlkMS5qcGcpDQoNCiFbXShDOlxcVXNlcnNcXFpib29rXFxEZXNrdG9wXFxwaWNcXHBpZDIuanBnKQ0KDQojIFIgQ29kZXMgZm9yIENvbGxlY3RpbmcgRGF0YSBhbmQgVmlzdWFsaXphdGlvbg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCg0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgICBTY3JhcHBpbmcgcG9wdWxhdGlvbiBkYXRhIHdpdGggaW5wdXRzIGFyZTogDQojICAgMS4gR2l2ZW4geWVhciwgDQojICAgMi4gQ291bnRyeSBjb2RlIHNlbGVjdGVkIGZyb20gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPXzMxNjYtMV9hbHBoYS0yDQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojIENsZWFyIHdvcmtzcGFjZTogDQpybShsaXN0ID0gbHMoKSkNCg0KIyBMb2FkIHNvbWUgcGFja2FnZXMgZm9yIHNjcmFwcGluZyBkYXRhIGFuZCBkYXRhIG1hbmlwdWxhdGlvbjogDQpsaWJyYXJ5KHJ2ZXN0KQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQojIEEgZnVuY3Rpb24gZm9yIGNvbGxlY3RpbmcgcG9wdWxhdGlvbiBkYXRhOiANCg0KZ2V0X3BvcHVsYXRpb24gPC0gZnVuY3Rpb24oY291bnRyeUNvZGVfc2VsZWN0ZWQsIHllYXJfc2VsZWN0ZWQpIHsNCiAgDQogIGJhc2VfdXJsIDwtICJodHRwczovL3d3dy5jZW5zdXMuZ292L2RhdGEtdG9vbHMvZGVtby9pZGIvcmVnaW9uLnBocD9OPSUyMFJlc3VsdHMlMjAmVD0xMCZBPXNlcGFyYXRlJlJUPTAmWT0iDQogIGxpbmsgPC0gcGFzdGUwKHBhc3RlMChwYXN0ZTAoYmFzZV91cmwsIHllYXJfc2VsZWN0ZWQpLCAiJlI9LTEmQz0iKSwgY291bnRyeUNvZGVfc2VsZWN0ZWQpDQogIA0KICBsaW5rICU+JSANCiAgICByZWFkX2h0bWwoKSAtPiBodG1sX2NvbnRlbnQgIA0KICANCiAgaHRtbF9jb250ZW50ICU+JSANCiAgICBodG1sX3RhYmxlKGZpbGwgPSBUUlVFKSAlPiUgDQogICAgLltbMV1dIC0+IHBvcF9kZg0KICANCiAgbmFtZXMocG9wX2RmKSA8LSBzdHJfcmVwbGFjZV9hbGwobmFtZXMocG9wX2RmKSwgIiAiLCAiXyIpDQogIA0KICBjb3VudHJ5X25hbWUgPC0gaHRtbF9jb250ZW50ICU+JSANCiAgICBodG1sX25vZGVzKCcucXVlcnlfc291cmNlIGEnKSAlPiUgDQogICAgaHRtbF90ZXh0KCkgDQogIA0KICBpZiAobGVuZ3RoKGNvdW50cnlfbmFtZSkgPT0gMikgew0KICAgIGNvdW50cnlfbmFtZSA8LSBjb3VudHJ5X25hbWVbMl0NCiAgfQ0KICANCiAgDQogIGZpbmFsX2RmIDwtIHBvcF9kZiAlPiUgDQogICAgc2VsZWN0KC1ZZWFyLCAtQWdlLCAtY29udGFpbnMoIlBlcmNlbnQiKSwgLVNleF9SYXRpbykgJT4lIA0KICAgIG11dGF0ZV9hbGwoZnVuY3Rpb24oeCkge3N0cl9yZXBsYWNlX2FsbCh4LCAiW14wLTldIiwgIiIpICU+JSBhcy5udW1lcmljKCl9KSAlPiUgDQogICAgbXV0YXRlKFllYXIgPSBwb3BfZGYkWWVhciwgQ291bnRyeSA9IGNvdW50cnlfbmFtZVsxXSwgQWdlID0gcG9wX2RmJEFnZSkgJT4lIA0KICAgIHNlbGVjdChZZWFyLCBDb3VudHJ5LCBBZ2UsIGV2ZXJ5dGhpbmcoKSkgJT4lIA0KICAgIG11dGF0ZShQZXJjZW50X0JvdGhfU2V4ZXMgPSBCb3RoX1NleGVzX1BvcHVsYXRpb24gLyBCb3RoX1NleGVzX1BvcHVsYXRpb25bMV0sIA0KICAgICAgICAgICBQZXJjZW50X01hbGUgPSBNYWxlX1BvcHVsYXRpb24gLyBNYWxlX1BvcHVsYXRpb25bMV0sIA0KICAgICAgICAgICBQZXJjZW50X0ZlbWFsZSA9IEZlbWFsZV9Qb3B1bGF0aW9uIC8gRmVtYWxlX1BvcHVsYXRpb25bMV0sIA0KICAgICAgICAgICBTZXhfUmF0aW8gPSBNYWxlX1BvcHVsYXRpb24gLyBGZW1hbGVfUG9wdWxhdGlvbiwgDQogICAgICAgICAgIEFnZSA9IGNhc2Vfd2hlbihBZ2UgPT0gIjAtNCIgfiAiMDAtMDQiLCBBZ2UgPT0gIjUtOSIgfiAiMDUtMDkiLCBUUlVFIH4gQWdlKSkNCiAgDQogIHJldHVybihmaW5hbF9kZikNCiAgDQp9DQoNCg0KIyBGdW5jdGlvbiBmb3IgZ2V0dGluZyBwb3B1bGF0aW9uIGRhdGEgZm9yIFZpZXRuYW0gYnkgZ2l2ZW4geWVhcjogDQoNCnBvcF9kYXRhX0J5WWVhciA8LSBmdW5jdGlvbih5ZWFyX3NlbGVjdGVkKSB7DQogIGdldF9wb3B1bGF0aW9uKCJWTSIsIHllYXJfc2VsZWN0ZWQpICU+JSANCiAgICBzbGljZSgtYygxLCAyMDoyMikpICU+JSANCiAgICBzZWxlY3QoWWVhciwgQWdlLCBNYWxlX1BvcHVsYXRpb24sIEZlbWFsZV9Qb3B1bGF0aW9uKSAlPiUgDQogICAgbXV0YXRlKEZlbWFsZV9Qb3B1bGF0aW9uID0gLTEqRmVtYWxlX1BvcHVsYXRpb24pICU+JSANCiAgICBnYXRoZXIoR2VuZGVyLCBWYWx1ZSwgLUFnZSwgLVllYXIpICU+JSANCiAgICByZXR1cm4oKQ0KfQ0KDQoNCiMgVXNlIHRoZSBmdW5jdGlvbiBmb3IgZ2V0dGluZyBkYXRhOiANCmxhcHBseShjKDIwMTgsIDIwMDUsIDIwMDAsIDE5OTUpLCBwb3BfZGF0YV9CeVllYXIpIC0+IHRvdGFsX2xpc3QNCnRvdGFsX2RmIDwtIGRvLmNhbGwoInJiaW5kIiwgdG90YWxfbGlzdCkNCg0KIz09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgIERhdGEgVmlzdWFsaXphdGlvbg0KIz09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KbGlicmFyeShleHRyYWZvbnQpDQoNCiMgQ29sb3JzIGFuZCBmb250IHNlbGVjdGVkOiANCm15X2NvbG9ycyA8LSBjKCIjMkU3NEMwIiwgIiNDQjQ1NEEiKQ0KbXlfZm9udCA8LSAiUm9ib3RvIENvbmRlbnNlZCINCg0KDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICAgVmVyc2lvbiAxOiBVc2luZyBnZW9tX2NvbCgpDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCnRvdGFsX2RmICU+JSANCiAgZ2dwbG90KGFlcyhBZ2UsIFZhbHVlLCBmaWxsID0gR2VuZGVyKSkgKyANCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAic3RhY2siLCB3aWR0aCA9IDAuODUpICsgDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsIDAuNSkpICsgDQogIGZhY2V0X3dyYXAofiBZZWFyKSArIA0KICBjb29yZF9mbGlwKCkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtNTAwMDAwMCwgNTAwMDAwMCwgMTAwMDAwMCksIA0KICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygtNTAwMDAwMCwgNTAwMDAwMCksIA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYyhwYXN0ZTAoc2VxKDUsIDAsIC0xKSwgIk0iKSwgcGFzdGUwKDE6NSwgIk0iKSkpICsgDQogIHRoZW1lX21pbmltYWwoKSArIA0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBteV9jb2xvcnMsIG5hbWUgPSAiIiwgbGFiZWxzID0gYygiRmVtYWxlIiwgIk1hbGUiKSkgKyANCiAgIyBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlID0gVFJVRSkpICsgDQogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShsaW5ldHlwZSA9ICJkb3R0ZWQiLCBzaXplID0gMC4yLCBjb2xvciA9ICJncmV5NDAiKSkgKyANCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKSArIA0KICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgDQogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsgDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFtaWx5ID0gbXlfZm9udCkpICsgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgZmFtaWx5ID0gbXlfZm9udCkpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gbXlfZm9udCwgc2l6ZSA9IDI4KSkgKyANCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSBteV9mb250LCBzaXplID0gMTMsIGNvbG9yID0gImdyYXk0MCIpKSArIA0KICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gbXlfZm9udCwgc2l6ZSA9IDEyLCBjb2xvdXIgPSAiZ3JleTQwIiwgZmFjZSA9ICJpdGFsaWMiKSkgKyANCiAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMS4yLCAxLjIsIDEuMiwgMS4yKSwgImNtIikpICsgDQogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiZ3JleTMwIiwgZmFtaWx5ID0gbXlfZm9udCkpICsgDQogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiZ3JleTIwIiwgc2l6ZSA9IDEzLCBmYWNlID0gImJvbGQiLCBmYW1pbHkgPSBteV9mb250KSkgKyAgDQogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLCANCiAgICAgICB0aXRsZSA9ICJQb3B1bGF0aW9uIFB5cmFtaWRzIG9mIFZpZXRuYW06IDE5OTUgLSAyMDE4IiwNCiAgICAgICBzdWJ0aXRsZSA9ICJUaGUgYWdlLXNleCBzdHJ1Y3R1cmUgb2YgYSBjb3VudHJ5J3MgcG9wdWxhdGlvbiBhbmQgbWF5IHByb3ZpZGUgaW5zaWdodHMgYWJvdXQgcG9saXRpY2FsIGFuZCBzb2NpYWwgc3RhYmlsaXR5LFxuYXMgd2VsbCBhcyBlY29ub21pYyBkZXZlbG9wbWVudC4gQ291bnRyaWVzIHdpdGggeW91bmcgcG9wdWxhdGlvbnMgbmVlZCB0byBpbnZlc3QgbW9yZSBpbiBzY2hvb2xzLFxud2hpbGUgY291bnRyaWVzIHdpdGggb2xkZXIgcG9wdWxhdGlvbnMgbmVlZCB0byBpbnZlc3QgbW9yZSBpbiB0aGUgaGVhbHRoIHNlY3Rvci4iLA0KICAgICAgIGNhcHRpb24gPSAiRGF0YSBTb3VyY2U6IGh0dHBzOi8vd3d3LmNlbnN1cy5nb3YiKQ0KDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgIFZlcnNpb24gMjogVXNpbmcgZ2VvbV9saW5lcmFuZ2UoKQ0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCnRvdGFsX2RmICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gQWdlLCBjb2xvciA9IEdlbmRlcikpKw0KICBnZW9tX2xpbmVyYW5nZShkYXRhID0gdG90YWxfZGYgJT4lIGZpbHRlcihHZW5kZXIgPT0gIk1hbGVfUG9wdWxhdGlvbiIpLA0KICAgICAgICAgICAgICAgICBhZXMoeW1pbiA9IC0wLjMsIHltYXggPSAtMC4zICsgVmFsdWUpLCBzaXplID0gMy41LCBhbHBoYSA9IDEpICsNCiAgZ2VvbV9saW5lcmFuZ2UoZGF0YSA9IHRvdGFsX2RmICU+JSBmaWx0ZXIoR2VuZGVyICE9ICJNYWxlX1BvcHVsYXRpb24iKSwgDQogICAgICAgICAgICAgICAgIGFlcyh5bWluID0gMC4zLCB5bWF4ID0gMC4zICsgVmFsdWUpLCBzaXplID0gMy41LCBhbHBoYSA9IDEpICsgDQogIGdlb21fbGFiZWwoYWVzKHggPSBBZ2UsIHkgPSAwLCBsYWJlbCA9IEFnZSksIGluaGVyaXQuYWVzID0gVFJVRSwgZmFtaWx5ID0gbXlfZm9udCwgDQogICAgICAgICAgICAgc2l6ZSA9IDMuNSwgbGFiZWwucGFkZGluZyA9IHVuaXQoMCwgImxpbmVzIiksIGxhYmVsLnNpemUgPSAwLCANCiAgICAgICAgICAgICBsYWJlbC5yID0gdW5pdCgwLjAsICJsaW5lcyIpLCBmaWxsID0gIiNmNWY1ZjIiLCBhbHBoYSA9IDEsIGNvbG9yID0gImdyYXkyMCIpICsgDQogIHRoZW1lX21pbmltYWwoKSArIA0KICBjb29yZF9mbGlwKCkgKyANCiAgZmFjZXRfd3JhcCggfiBZZWFyKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC01MDAwMDAwLCA1MDAwMDAwLCAxMDAwMDAwKSwgDQogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKC01MDAwMDAwLCA1MDAwMDAwKSwgDQogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKHBhc3RlMChzZXEoNSwgMCwgLTEpLCAiTSIpLCBwYXN0ZTAoMTo1LCAiTSIpKSkgKyANCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWUgPSAiIiwgdmFsdWVzID0gYyhGZW1hbGVfUG9wdWxhdGlvbiA9ICIjM0U2MDZGIiwgTWFsZV9Qb3B1bGF0aW9uID0gIiM4QzNGNEQiKSwgDQogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNYWxlIiwgIkZlbWFsZSIpKSArIA0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiwgc2l6ZSA9IDI4LCBmYW1pbHkgPSBteV9mb250LCBtYXJnaW4gPSBtYXJnaW4oYiA9IDEwKSwgaGp1c3QgPSAwLCBjb2xvciA9ICJncmV5MjAiKSkgKyANCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIG1hcmdpbiA9IG1hcmdpbihiID0gMjApLCBoanVzdCA9IDAsIGZhbWlseSA9IG15X2ZvbnQsIGNvbG9yID0gImdyZXkzMCIpKSArIA0KICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzLCBjb2xvciA9ICJncmV5NTAiLCBmYW1pbHkgPSBteV9mb250KSkgKyANCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpICsgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiZ3JleTIwIiwgZmFtaWx5ID0gbXlfZm9udCwgZmFjZSA9ICJib2xkIikpICsgDQogIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIiNFRkYyRjQiLCBjb2xvciA9IE5BKSkgKyANCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9saW5lKGxpbmV0eXBlID0gImRvdHRlZCIsIHNpemUgPSAwLjIsIGNvbG9yID0gImdyZXk0MCIpKSArIA0KICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygxLjIsIDEuMiwgMS4yLCAxLjIpLCAiY20iKSkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsgDQogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMywgZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiZ3JleTMwIiwgZmFtaWx5ID0gbXlfZm9udCkpICsgDQogIHRoZW1lKGxlZ2VuZC50ZXh0LmFsaWduID0gMSkgKyANCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmV5MjAiLCBzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIsIGZhbWlseSA9IG15X2ZvbnQpKSArIA0KICAjIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiZ3JleTIwIiwgc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiLCBoanVzdCA9IDAuMDI2KSArIA0KICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgDQogICAgICAgdGl0bGUgPSAiUG9wdWxhdGlvbiBQeXJhbWlkcyBvZiBWaWV0bmFtOiAxOTk1IC0gMjAxOCIsDQogICAgICAgc3VidGl0bGUgPSAiVGhlIGFnZS1zZXggc3RydWN0dXJlIG9mIGEgY291bnRyeSdzIHBvcHVsYXRpb24gYW5kIG1heSBwcm92aWRlIGluc2lnaHRzIGFib3V0IHBvbGl0aWNhbCBhbmQgc29jaWFsIHN0YWJpbGl0eSxcbmFzIHdlbGwgYXMgZWNvbm9taWMgZGV2ZWxvcG1lbnQuIENvdW50cmllcyB3aXRoIHlvdW5nIHBvcHVsYXRpb25zIG5lZWQgdG8gaW52ZXN0IG1vcmUgaW4gc2Nob29scyxcbndoaWxlIGNvdW50cmllcyB3aXRoIG9sZGVyIHBvcHVsYXRpb25zIG5lZWQgdG8gaW52ZXN0IG1vcmUgaW4gdGhlIGhlYWx0aCBzZWN0b3IuIiwNCiAgICAgICBjYXB0aW9uID0gIkRhdGEgU291cmNlOiBodHRwczovL3d3dy5jZW5zdXMuZ292IikNCiAgDQoNCg0KYGBgDQoNCg==