Ở bài luyện tập này, mình sử dụng bộ dữ liệu kaggle_survey_2020_responses.csv được cung cấp bởi Kaggle năm 2020.

FACT 1

Từ hình ảnh, ta thấy khoảng chênh lệch giới tính trong ngành Data Science còn rất lớn. Mình đã lấy ra danh sách top 9 quốc gia có tỉ lệ lớn nhất và thêm Việt Nam để quan sát. Qua đó, có thể thấy rằng tỉ lệ nữ giới ở Việt Nam tham gia ngành này cũng ở mức triển vọng (14,3%), trong khi đó quốc gia lớn như Nhật Bản tỉ lệ này tương đối thấp (6,6%).

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

# Load package and data: 
library(tidyverse)

df_raw <- read_csv("D:\\R\\kaggle_survey_2020_responses.csv")

# Rename for all columns: 
df_raw %>% 
  slice(1) %>% 
  as.vector() -> df_a

str_replace_all(df_a, " ", "_") -> new_names

df_raw %>% slice(-1) -> df_raw

names(df_raw) <- new_names

# Select two columns: 
df_raw %>% 
  select(c(3, 4)) %>% 
  rename(gender = `What_is_your_gender?_-_Selected_Choice`, nation = `In_which_country_do_you_currently_reside?`) ->
  df_new

# Top 10 nations + Vietnam by nunber of DS/ML: 

df_new %>% 
  group_by(nation) %>% 
  count() %>% 
  arrange(-n) %>% 
  ungroup() %>% 
  slice(1:9) %>% 
  pull(nation) -> top9_nations

c(top9_nations, "Viet Nam") -> top10


# Relabel for some countries: 
df_new %>% 
  filter(nation %in% top10, gender %in% c("Man", "Woman")) %>% 
  mutate(nation = case_when(str_detect(nation, "United States") ~ "United States", 
                            str_detect(nation, "Kingdom") ~ "United Kingdom", 
                            TRUE ~ nation)) -> df_top10_nations

df_top10_nations %>% 
  group_by(gender, nation) %>% 
  count() %>% 
  ungroup() -> df_my

# Calculate female rate: 

df_my %>% 
  spread(key = "gender", value = "n") %>% 
  mutate(rate = Woman / (Woman + Man)) %>% 
  arrange(rate) %>% 
  mutate(label = round(100*rate, 1)) %>% 
  mutate(label = as.character(label)) %>% 
  mutate(label = case_when(!str_detect(label, "\\.") ~ paste0(label, ".0"), TRUE ~ label)) %>% 
  mutate(label = paste0(label, "%")) %>% 
  mutate(nation = factor(nation, levels = nation)) -> df_rate

# Re-arrange order by female rate: 

df_my %>% 
  mutate(nation = factor(nation, levels = df_rate$nation)) -> my_ord

# data visualization: 

library(extrafont)

my_colors <- c("#2E74C0", "#CB454A")  

my_font <- "Roboto Condensed"  

# Graph fact 1: 

my_ord %>% 
  full_join(df_rate, by = "nation") %>% 
  ggplot(aes(x = nation, y = n, fill = gender)) + 
  geom_col(position = "fill") + 
  coord_flip() +
  geom_text(aes(x = nation, y = 0.04, label = label), size = 3.8, color = "white", family = my_font) +
  scale_fill_manual(name = "", values = c(Man = my_colors[1], Woman = my_colors[2]), labels = c("Man", "Woman")) + 
  scale_y_continuous(labels = paste0(seq(0, 100, 25), "%"), expand = c(0, 0)) + 
  theme_minimal() + 
  theme(text = element_text(family = my_font)) + 
  theme(plot.margin = unit(rep(0.7, 4), "cm")) + 
  theme(plot.background = element_rect(fill = "#EFF2F4", color = NA)) + 
  theme(plot.title = element_text(size = 19)) + 
  theme(plot.caption = element_text(size = 10, color = "grey30")) + 
  theme(axis.text.x = element_text(size = 10.5, color = "grey20")) + 
  theme(axis.text.y = element_text(size = 10.5, color = "grey20")) +  
  theme(legend.position = "top") + 
  guides(fill = guide_legend(reverse = TRUE)) + 
  theme(panel.grid.major.y = element_blank(), panel.grid.minor.x = element_blank()) + 
  theme(legend.key.height = unit(0.15, "mm"), legend.key.width = unit(5, "mm")) + 
  labs(x = NULL, y = NULL, 
       title = "Fact 1: Women in Machine Learning and Data Science Community", 
       caption = "Source: 2020 Kaggle ML & DS Survey")

FACT 2

Phần tiếp theo, mình thực hiện minh họa các nhóm tuổi phân loại theo giới tính của tất cả các nước trên thế giới. Kết quả cho thấy rằng, nhóm Millennials (Gen Y) hiện đang thống trị ngành Data Science, trong đó độ tuổi phổ biến nhất từ 25-29 tuổi. Tuy nhiên, tỉ lệ cũng cho thấy nhóm Gen Z đang quan tâm rất lớn vào ngành này. Trong tương lai, Gen Z chắc chắn sẽ làm khuấy động ngành ML & DS.

df_raw %>% 
  group_by(`What_is_your_age_(#_years)?`, `What_is_your_gender?_-_Selected_Choice`) %>% 
  count() %>% 
  ungroup() -> age_gender
names(age_gender) <- c("Age", "Gender", "n")

age_gender %>% 
  filter(Gender %in% c("Man", "Woman")) -> age_gender

age_gender$Age %>% unique() -> age

age_gender %>% 
  mutate(Age = factor(Age, levels = age)) %>% 
  mutate(n = as.numeric(n)) %>% 
  mutate(c = case_when(Gender == "Man" ~ -1*n, TRUE ~ n)) -> age_gender

age_gender %>% 
  ggplot(aes(x = Age, y = c, fill = Gender)) +
  geom_col() +
  coord_flip() +
  theme_minimal() +
  theme(text = element_text(family = my_font)) +
  theme(plot.margin = unit(rep(0.7, 4), "cm")) +
  theme(plot.title = element_text(size = 19)) +
  theme(plot.caption = element_text(size = 10, color = "grey30")) +
  theme(plot.background = element_rect(fill = "#EFF2F4", color = NA)) +
  theme(axis.text.x = element_text(size = 10.5, color = "grey20")) +
  theme(axis.text.y = element_text(size = 10.5, color = "grey20")) +
  theme(legend.position = "top") +
  scale_fill_manual(name = "", values = c(Man = my_colors[1], Woman = my_colors[2]), labels = c("Man", "Woman")) +
  guides(fill = guide_legend(reverse = TRUE)) +
  theme(panel.grid.major.y = element_blank()) +
  theme(panel.grid.major.x = element_blank()) +
  theme(legend.key.height = unit(0.15, "mm"), legend.key.width = unit(5, "mm")) +
  scale_y_continuous(breaks = seq(-4000, 1000, 500), labels = c(seq(4000, 500, -500), seq(0, 1000, 500))) +
  theme(panel.grid.major.x = element_line(color = "grey60", linetype = "dotted")) +
  labs(x = NULL, y = NULL,
       title = "Fact 2: Age Distribution by Gender",
       caption = "Source: 2020 Kaggle ML & DS Survey")

LS0tDQp0aXRsZTogIkthZ2dsZSBNYWNoaW5lIExlYXJuaW5nICYgRGF0YSBTY2llbmNlIFN1cnZleSINCmF1dGhvcjogIk5ndXllbiBUaGkgTmdvYyBIdXllbiINCmRhdGU6ICIzLzgvMjAyMSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGhpZ2hsaWdodDogemVuYnVybg0KICAgICMgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtZTogImZsYXRseSINCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGNhY2hlID0gVFJVRSkNCmBgYA0KDQrhu54gYsOgaSBsdXnhu4duIHThuq1wIG7DoHksIG3DrG5oIHPhu60gZOG7pW5nIGLhu5kgZOG7ryBsaeG7h3Uga2FnZ2xlX3N1cnZleV8yMDIwX3Jlc3BvbnNlcy5jc3YgxJHGsOG7o2MgY3VuZyBj4bqlcCBi4bufaSBLYWdnbGUgbsSDbSAyMDIwLg0KDQojIEZBQ1QgMQ0KDQpU4burIGjDrG5oIOG6o25oLCB0YSB0aOG6pXkga2hv4bqjbmcgY2jDqm5oIGzhu4djaCBnaeG7m2kgdMOtbmggdHJvbmcgbmfDoG5oIERhdGEgU2NpZW5jZSBjw7JuIHLhuqV0IGzhu5tuLiBNw6xuaCDEkcOjIGzhuqV5IHJhIGRhbmggc8OhY2ggdG9wIDkgcXXhu5FjIGdpYSBjw7MgdOG7iSBs4buHIGzhu5tuIG5o4bqldCB2w6AgdGjDqm0gVmnhu4d0IE5hbSDEkeG7gyBxdWFuIHPDoXQuIFF1YSDEkcOzLCBjw7MgdGjhu4MgdGjhuqV5IHLhurFuZyB04buJIGzhu4cgbuG7ryBnaeG7m2kg4bufIFZp4buHdCBOYW0gdGhhbSBnaWEgbmfDoG5oIG7DoHkgY8Wpbmcg4bufIG3hu6ljIHRyaeG7g24gduG7jW5nICgxNCwzJSksIHRyb25nIGtoaSDEkcOzIHF14buRYyBnaWEgbOG7m24gbmjGsCBOaOG6rXQgQuG6o24gdOG7iSBs4buHIG7DoHkgdMawxqFuZyDEkeG7kWkgdGjhuqVwICg2LDYlKS4NCg0KYGBge3IsIGV2YWw9RkFMU0V9DQojQ2xlYXIgd29ya3NwYWNlOiANCnJtKGxpc3QgPSBscygpKQ0KDQojIExvYWQgcGFja2FnZSBhbmQgZGF0YTogDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KZGZfcmF3IDwtIHJlYWRfY3N2KCJEOlxcUlxca2FnZ2xlX3N1cnZleV8yMDIwX3Jlc3BvbnNlcy5jc3YiKQ0KDQojIFJlbmFtZSBmb3IgYWxsIGNvbHVtbnM6IA0KZGZfcmF3ICU+JSANCiAgc2xpY2UoMSkgJT4lIA0KICBhcy52ZWN0b3IoKSAtPiBkZl9hDQoNCnN0cl9yZXBsYWNlX2FsbChkZl9hLCAiICIsICJfIikgLT4gbmV3X25hbWVzDQoNCmRmX3JhdyAlPiUgc2xpY2UoLTEpIC0+IGRmX3Jhdw0KDQpuYW1lcyhkZl9yYXcpIDwtIG5ld19uYW1lcw0KDQojIFNlbGVjdCB0d28gY29sdW1uczogDQpkZl9yYXcgJT4lIA0KICBzZWxlY3QoYygzLCA0KSkgJT4lIA0KICByZW5hbWUoZ2VuZGVyID0gYFdoYXRfaXNfeW91cl9nZW5kZXI/Xy1fU2VsZWN0ZWRfQ2hvaWNlYCwgbmF0aW9uID0gYEluX3doaWNoX2NvdW50cnlfZG9feW91X2N1cnJlbnRseV9yZXNpZGU/YCkgLT4NCiAgZGZfbmV3DQoNCiMgVG9wIDEwIG5hdGlvbnMgKyBWaWV0bmFtIGJ5IG51bmJlciBvZiBEUy9NTDogDQoNCmRmX25ldyAlPiUgDQogIGdyb3VwX2J5KG5hdGlvbikgJT4lIA0KICBjb3VudCgpICU+JSANCiAgYXJyYW5nZSgtbikgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBzbGljZSgxOjkpICU+JSANCiAgcHVsbChuYXRpb24pIC0+IHRvcDlfbmF0aW9ucw0KDQpjKHRvcDlfbmF0aW9ucywgIlZpZXQgTmFtIikgLT4gdG9wMTANCg0KDQojIFJlbGFiZWwgZm9yIHNvbWUgY291bnRyaWVzOiANCmRmX25ldyAlPiUgDQogIGZpbHRlcihuYXRpb24gJWluJSB0b3AxMCwgZ2VuZGVyICVpbiUgYygiTWFuIiwgIldvbWFuIikpICU+JSANCiAgbXV0YXRlKG5hdGlvbiA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KG5hdGlvbiwgIlVuaXRlZCBTdGF0ZXMiKSB+ICJVbml0ZWQgU3RhdGVzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChuYXRpb24sICJLaW5nZG9tIikgfiAiVW5pdGVkIEtpbmdkb20iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gbmF0aW9uKSkgLT4gZGZfdG9wMTBfbmF0aW9ucw0KDQpkZl90b3AxMF9uYXRpb25zICU+JSANCiAgZ3JvdXBfYnkoZ2VuZGVyLCBuYXRpb24pICU+JSANCiAgY291bnQoKSAlPiUgDQogIHVuZ3JvdXAoKSAtPiBkZl9teQ0KDQojIENhbGN1bGF0ZSBmZW1hbGUgcmF0ZTogDQoNCmRmX215ICU+JSANCiAgc3ByZWFkKGtleSA9ICJnZW5kZXIiLCB2YWx1ZSA9ICJuIikgJT4lIA0KICBtdXRhdGUocmF0ZSA9IFdvbWFuIC8gKFdvbWFuICsgTWFuKSkgJT4lIA0KICBhcnJhbmdlKHJhdGUpICU+JSANCiAgbXV0YXRlKGxhYmVsID0gcm91bmQoMTAwKnJhdGUsIDEpKSAlPiUgDQogIG11dGF0ZShsYWJlbCA9IGFzLmNoYXJhY3RlcihsYWJlbCkpICU+JSANCiAgbXV0YXRlKGxhYmVsID0gY2FzZV93aGVuKCFzdHJfZGV0ZWN0KGxhYmVsLCAiXFwuIikgfiBwYXN0ZTAobGFiZWwsICIuMCIpLCBUUlVFIH4gbGFiZWwpKSAlPiUgDQogIG11dGF0ZShsYWJlbCA9IHBhc3RlMChsYWJlbCwgIiUiKSkgJT4lIA0KICBtdXRhdGUobmF0aW9uID0gZmFjdG9yKG5hdGlvbiwgbGV2ZWxzID0gbmF0aW9uKSkgLT4gZGZfcmF0ZQ0KDQojIFJlLWFycmFuZ2Ugb3JkZXIgYnkgZmVtYWxlIHJhdGU6IA0KDQpkZl9teSAlPiUgDQogIG11dGF0ZShuYXRpb24gPSBmYWN0b3IobmF0aW9uLCBsZXZlbHMgPSBkZl9yYXRlJG5hdGlvbikpIC0+IG15X29yZA0KDQojIGRhdGEgdmlzdWFsaXphdGlvbjogDQoNCmxpYnJhcnkoZXh0cmFmb250KQ0KDQpteV9jb2xvcnMgPC0gYygiIzJFNzRDMCIsICIjQ0I0NTRBIikgIA0KDQpteV9mb250IDwtICJSb2JvdG8gQ29uZGVuc2VkIiAgDQoNCiMgR3JhcGggZmFjdCAxOiANCg0KbXlfb3JkICU+JSANCiAgZnVsbF9qb2luKGRmX3JhdGUsIGJ5ID0gIm5hdGlvbiIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gbmF0aW9uLCB5ID0gbiwgZmlsbCA9IGdlbmRlcikpICsgDQogIGdlb21fY29sKHBvc2l0aW9uID0gImZpbGwiKSArIA0KICBjb29yZF9mbGlwKCkgKw0KICBnZW9tX3RleHQoYWVzKHggPSBuYXRpb24sIHkgPSAwLjA0LCBsYWJlbCA9IGxhYmVsKSwgc2l6ZSA9IDMuOCwgY29sb3IgPSAid2hpdGUiLCBmYW1pbHkgPSBteV9mb250KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSAiIiwgdmFsdWVzID0gYyhNYW4gPSBteV9jb2xvcnNbMV0sIFdvbWFuID0gbXlfY29sb3JzWzJdKSwgbGFiZWxzID0gYygiTWFuIiwgIldvbWFuIikpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwYXN0ZTAoc2VxKDAsIDEwMCwgMjUpLCAiJSIpLCBleHBhbmQgPSBjKDAsIDApKSArIA0KICB0aGVtZV9taW5pbWFsKCkgKyANCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSBteV9mb250KSkgKyANCiAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KHJlcCgwLjcsIDQpLCAiY20iKSkgKyANCiAgdGhlbWUocGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAiI0VGRjJGNCIsIGNvbG9yID0gTkEpKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxOSkpICsgDQogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG9yID0gImdyZXkzMCIpKSArIA0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAuNSwgY29sb3IgPSAiZ3JleTIwIikpICsgDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMC41LCBjb2xvciA9ICJncmV5MjAiKSkgKyAgDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSArIA0KICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChyZXZlcnNlID0gVFJVRSkpICsgDQogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpKSArIA0KICB0aGVtZShsZWdlbmQua2V5LmhlaWdodCA9IHVuaXQoMC4xNSwgIm1tIiksIGxlZ2VuZC5rZXkud2lkdGggPSB1bml0KDUsICJtbSIpKSArIA0KICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwgDQogICAgICAgdGl0bGUgPSAiRmFjdCAxOiBXb21lbiBpbiBNYWNoaW5lIExlYXJuaW5nIGFuZCBEYXRhIFNjaWVuY2UgQ29tbXVuaXR5IiwgDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IDIwMjAgS2FnZ2xlIE1MICYgRFMgU3VydmV5IikNCg0KYGBgDQoNCiFbXShEOlxSXHdvbWFuIGthbmdnbGUucG5nKQ0KDQoNCiMgRkFDVCAyDQoNClBo4bqnbiB0aeG6v3AgdGhlbywgbcOsbmggdGjhu7FjIGhp4buHbiBtaW5oIGjhu41hIGPDoWMgbmjDs20gdHXhu5VpIHBow6JuIGxv4bqhaSB0aGVvIGdp4bubaSB0w61uaCBj4bunYSB04bqldCBj4bqjIGPDoWMgbsaw4bubYyB0csOqbiB0aOG6vyBnaeG7m2kuDQpL4bq/dCBxdeG6oyBjaG8gdGjhuqV5IHLhurFuZywgbmjDs20gTWlsbGVubmlhbHMgKEdlbiBZKSBoaeG7h24gxJFhbmcgdGjhu5FuZyB0cuG7iyBuZ8OgbmggRGF0YSBTY2llbmNlLCB0cm9uZyDEkcOzIMSR4buZIHR14buVaSBwaOG7lSBiaeG6v24gbmjhuqV0IA0KdOG7qyAyNS0yOSB0deG7lWkuDQpUdXkgbmhpw6puLCB04buJIGzhu4cgY8WpbmcgY2hvIHRo4bqleSBuaMOzbSBHZW4gWiDEkWFuZyBxdWFuIHTDom0gcuG6pXQgbOG7m24gdsOgbyBuZ8OgbmggbsOgeS4gVHJvbmcgdMawxqFuZyBsYWksIEdlbiBaIGNo4bqvYyBjaOG6r24gc+G6vSBsw6BtIGtodeG6pXkgxJHhu5luZyBuZ8OgbmggTUwgJiBEUy4NCg0KYGBge3IsIGV2YWw9RkFMU0V9DQoNCmRmX3JhdyAlPiUgDQogIGdyb3VwX2J5KGBXaGF0X2lzX3lvdXJfYWdlXygjX3llYXJzKT9gLCBgV2hhdF9pc195b3VyX2dlbmRlcj9fLV9TZWxlY3RlZF9DaG9pY2VgKSAlPiUgDQogIGNvdW50KCkgJT4lIA0KICB1bmdyb3VwKCkgLT4gYWdlX2dlbmRlcg0KbmFtZXMoYWdlX2dlbmRlcikgPC0gYygiQWdlIiwgIkdlbmRlciIsICJuIikNCg0KYWdlX2dlbmRlciAlPiUgDQogIGZpbHRlcihHZW5kZXIgJWluJSBjKCJNYW4iLCAiV29tYW4iKSkgLT4gYWdlX2dlbmRlcg0KDQphZ2VfZ2VuZGVyJEFnZSAlPiUgdW5pcXVlKCkgLT4gYWdlDQoNCmFnZV9nZW5kZXIgJT4lIA0KICBtdXRhdGUoQWdlID0gZmFjdG9yKEFnZSwgbGV2ZWxzID0gYWdlKSkgJT4lIA0KICBtdXRhdGUobiA9IGFzLm51bWVyaWMobikpICU+JSANCiAgbXV0YXRlKGMgPSBjYXNlX3doZW4oR2VuZGVyID09ICJNYW4iIH4gLTEqbiwgVFJVRSB+IG4pKSAtPiBhZ2VfZ2VuZGVyDQoNCmFnZV9nZW5kZXIgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBBZ2UsIHkgPSBjLCBmaWxsID0gR2VuZGVyKSkgKw0KICBnZW9tX2NvbCgpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSBteV9mb250KSkgKw0KICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQocmVwKDAuNywgNCksICJjbSIpKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE5KSkgKw0KICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvciA9ICJncmV5MzAiKSkgKw0KICB0aGVtZShwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICIjRUZGMkY0IiwgY29sb3IgPSBOQSkpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLjUsIGNvbG9yID0gImdyZXkyMCIpKSArDQogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMC41LCBjb2xvciA9ICJncmV5MjAiKSkgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKw0KICBzY2FsZV9maWxsX21hbnVhbChuYW1lID0gIiIsIHZhbHVlcyA9IGMoTWFuID0gbXlfY29sb3JzWzFdLCBXb21hbiA9IG15X2NvbG9yc1syXSksIGxhYmVscyA9IGMoIk1hbiIsICJXb21hbiIpKSArDQogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHJldmVyc2UgPSBUUlVFKSkgKw0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCkpICsNCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKSArDQogIHRoZW1lKGxlZ2VuZC5rZXkuaGVpZ2h0ID0gdW5pdCgwLjE1LCAibW0iKSwgbGVnZW5kLmtleS53aWR0aCA9IHVuaXQoNSwgIm1tIikpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtNDAwMCwgMTAwMCwgNTAwKSwgbGFiZWxzID0gYyhzZXEoNDAwMCwgNTAwLCAtNTAwKSwgc2VxKDAsIDEwMDAsIDUwMCkpKSArDQogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmV5NjAiLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSkgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gTlVMTCwNCiAgICAgICB0aXRsZSA9ICJGYWN0IDI6IEFnZSBEaXN0cmlidXRpb24gYnkgR2VuZGVyIiwNCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogMjAyMCBLYWdnbGUgTUwgJiBEUyBTdXJ2ZXkiKQ0KICANCmBgYA0KDQohW10oRDpcUlxhZ2UucG5nKQ==