Motivations

Chức năng của Graph là truyền tải các insights cho người tiếp nhận thông tin. Khi nào chức năng này mà không làm được, hoặc gây hiểu lầm, hoặc não người mất quá nhiều thời gian để hiểu insight trong graph được trình bày, thì coi như graph chưa làm được chức năng của nó. Một Graph tốt thì nên là self-explanatory (tự cái hình đã giải thích mọi thứ). Một trong những ví dụ như vậy là hình số 2 của báo cáo có tên ĐÁNH GIÁ TÁC ĐỘNG CỦA COVID-19 ĐẾN NỀN KINH TẾ VÀ CÁC KHUYẾN NGHỊ CHÍNH SÁCH (có thể xem tại đây). Chúng ta có thể cải tiến lại như sau:

R codes

R codes để thực hiện hình này như sau:

# Load some packages: 
library(tidyverse)
library(lubridate)

# Data links (source: https://github.com/CSSEGISandData/COVID-19): 
rm(list = ls())
link1 <- "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv"
link2 <- "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv"
link3 <- "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_recovered_global.csv"

# Clean and prepare data: 

link1 %>% 
  read_csv() %>% 
  rename(Province = `Province/State`, Country = `Country/Region`) %>% 
  gather(Date, Confirmed, -Province, -Country, -Lat, -Long) %>% 
  mutate(Date = mdy(Date)) %>% 
  filter(Country == "Vietnam", Date <= ymd("2020-04-04")) -> df_confirmed

df_confirmed %>% 
  mutate(before = lag(Confirmed)) %>% 
  mutate(NewConfirmed = Confirmed - before) %>% 
  slice(-1) -> df_for_g1

end_stage1 <- dmy("13-02-2020")
start_stage2 <- dmy("06-03-2020")
end_stage2 <- dmy("21-03-2020")

df_for_g1 %>% 
  mutate(Stage = case_when(Date <= end_stage1 ~ "Stage 1", 
                           Date > end_stage1 & Date < start_stage2 ~ "Standby", 
                           Date >= start_stage2 & Date <= end_stage2 ~ "Stage 2", 
                           TRUE ~ "Stage 3")) -> df

df %>% 
  select(TotalConfirmed = Confirmed, NewConfirmed, Date) %>% 
  gather(Type, Value, -Date) -> df_plot

df_plot$Date %>% unique() -> my_date

df_labels <- data.frame(Date = my_date)

df_labels %>% 
  mutate(label_x = case_when(Date == min(Date) ~ as.character(Date), 
                             Date == end_stage1 ~ as.character(end_stage1), 
                             Date == start_stage2 ~ as.character(start_stage2), 
                             Date == end_stage2 ~ as.character(end_stage2), 
                             Date == max(Date) ~ as.character(Date), 
                             TRUE ~ "")) %>% 
  mutate(Stage = case_when(Date <= end_stage1 ~ "Stage 1", 
                           Date > end_stage1 & Date < start_stage2 ~ "Standby", 
                           Date >= start_stage2 & Date <= end_stage2 ~ "Stage 2", 
                           TRUE ~ "Stage 3")) %>% 
  mutate(label_x = case_when(label_x == "2020-01-23" ~ "23-01", 
                             label_x == "2020-02-13" ~ "13-02", 
                             label_x == "2020-03-06" ~ "06-03", 
                             label_x == "2020-03-21" ~ "21-03", 
                             label_x == "2020-04-04" ~ "04-04", 
                             TRUE ~ label_x)) -> df_labels



df_for_g1 %>% 
  filter(Date == max(Date)) %>% 
  mutate(Date = Date + 2) %>% 
  select(TotalConfirmed = Confirmed, NewConfirmed, Date) %>% 
  gather(Type, Value, -Date) %>% 
  mutate(label = case_when(Value == 4 ~ paste0(Value, "  "), 
                           TRUE ~ as.character(Value))) -> df_an 


fill_colors <- c("#fff5f0", "#fcbba1", "#fc9272", "#fb6a4a")
line_colors <- c("#e41a1c", "#1f78b4")
h <- 250
k <- -0.5
my_font <- "Ubuntu Condensed"

ggplot() + 
  theme_minimal() + 
  geom_rect(aes(xmin = min(my_date), xmax = end_stage1, ymin = -Inf, ymax = Inf, fill = "Stage 1"), fill = "#a1d99b", alpha = 0.3, show.legend = FALSE) + 
  geom_rect(aes(xmin = end_stage1, xmax = start_stage2, ymin = -Inf, ymax = Inf, fill = "Standby"), fill = fill_colors[2], alpha = 0.3, show.legend = FALSE) + 
  geom_rect(aes(xmin = start_stage2, xmax = end_stage2, ymin = -Inf, ymax = Inf, fill = "Stage 2"), fill = fill_colors[3], alpha = 0.3, show.legend = FALSE) + 
  geom_rect(aes(xmin = end_stage2, xmax = max(my_date), ymin = -Inf, ymax = Inf, fill = "Stage 3"), fill = fill_colors[4], alpha = 0.3, show.legend = FALSE) + 
  geom_line(data = df_plot, aes(Date, Value, color = Type), size = 1.5) + 
  scale_color_manual(values = line_colors, name = "", labels = c("New", "Total")) + 
  scale_y_continuous(breaks = seq(0, 250, 25), limits = c(0, 250)) + 
  theme(panel.grid.minor.y = element_blank()) + 
  theme(legend.position = "top") + 
  scale_x_date(limits = c(min(my_date), max(my_date) + 3), breaks = seq(min(my_date), max(my_date), 1), 
               labels = df_labels$label_x, position = "top", expand = c(0, 0)) + 
  theme(panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank()) + 
  geom_text(data = df_an, aes(Date, Value, label = label), show.legend = FALSE, color = line_colors[2:1], size = 4.5, 
            fontface = "bold", hjust = 0.6, family = my_font) +
  labs(x = NULL, y = NULL, 
       title = "Figure 1: Coronavirus cases in Vietnam, as of 04-04-2020", 
       caption = "Source: Ministry of Health of Vietnam") + 
  geom_text(data = data.frame(Date = ymd("2020-01-23") + 10, Value = h), aes(Date, Value), label = "Stage 1", size = 4, vjust = k, family = my_font) + 
  geom_text(data = data.frame(Date = ymd("2020-02-13") + 11, Value = h), aes(Date, Value), label = "Standby", size = 4, vjust = k, family = my_font) + 
  geom_text(data = data.frame(Date = ymd("2020-03-06") + 7, Value = h), aes(Date, Value), label = "Stage 2", size = 4, vjust = k, family = my_font) + 
  geom_text(data = data.frame(Date = ymd("2020-03-21") + 7, Value = h), aes(Date, Value), label = "Stage 3", size = 4, vjust = k, family = my_font) + 
  theme(axis.text.x = element_text(size = 10, family = my_font)) + 
  theme(axis.text.y = element_text(size = 13, family = my_font)) + 
  theme(plot.margin = unit(c(1, 1, 1, 1), "cm")) + 
  theme(plot.title = element_text(family = my_font, size = 20)) + 
  theme(plot.caption = element_text(family = my_font, size = 10, color = "grey30")) + 
  theme(legend.text = element_text(family = my_font, size = 10, face = "bold", color = "grey30"))
LS0tDQp0aXRsZTogJ0Nvcm9uYXZpcnVzIGNhc2VzIGluIFZpZXRuYW0nDQphdXRob3I6ICdBdXRob3I6IE5ndXllbiBDaGkgRHVuZycNCnN1YnRpdGxlOiAiRGFpbHkgR3JhcGggU2VyaWVzIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgIyBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBoaWdobGlnaHQ6IHplbmJ1cm4NCiAgICAjIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6ICJmbGF0bHkiDQogICAgdG9jOiBUUlVFDQogICAgdG9jX2Zsb2F0OiBUUlVFDQotLS0NCg0KYGBge3Igc2V0dXAsaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGZpZy53aWR0aCA9IDEwLCBmaWcuaGVpZ2h0ID0gNikNCmBgYA0KDQoNCiMgTW90aXZhdGlvbnMNCg0KQ2jhu6ljIG7Eg25nIGPhu6dhIEdyYXBoIGzDoCB0cnV54buBbiB04bqjaSBjw6FjIGluc2lnaHRzIGNobyBuZ8aw4budaSB0aeG6v3Agbmjhuq1uIHRow7RuZyB0aW4uIEtoaSBuw6BvIGNo4bupYyBuxINuZyBuw6B5IG3DoCBraMO0bmcgbMOgbSDEkcaw4bujYywgaG/hurdjIGfDonkgaGnhu4N1IGzhuqdtLCBob+G6t2MgbsOjbyBuZ8aw4budaSBt4bqldCBxdcOhIG5oaeG7gXUgdGjhu51pIGdpYW4gxJHhu4MgaGnhu4N1IGluc2lnaHQgdHJvbmcgZ3JhcGggxJHGsOG7o2MgdHLDrG5oIGLDoHksIHRow6wgY29pIG5oxrAgZ3JhcGggY2jGsGEgbMOgbSDEkcaw4bujYyBjaOG7qWMgbsSDbmcgY+G7p2EgbsOzLiBN4buZdCBHcmFwaCB04buRdCB0aMOsIG7Dqm4gbMOgIHNlbGYtZXhwbGFuYXRvcnkgKHThu7EgY8OhaSBow6xuaCDEkcOjIGdp4bqjaSB0aMOtY2ggbeG7jWkgdGjhu6kpLiBN4buZdCB0cm9uZyBuaOG7r25nIHbDrSBk4bulIG5oxrAgduG6rXkgbMOgIGjDrG5oIHPhu5EgMiBj4bunYSBiw6FvIGPDoW8gY8OzIHTDqm4gKsSQw4FOSCBHScOBIFTDgUMgxJDhu5hORyBD4bumQSBDT1ZJRC0xOSDEkOG6vk4gTuG7gE4gS0lOSCBU4bq+IFbDgCBDw4FDIEtIVVnhur5OIE5HSOG7iiBDSMONTkggU8OBQ0gqIChjw7MgdGjhu4MgeGVtIFt04bqhaSDEkcOieV0oaHR0cHM6Ly9uZXUuZWR1LnZuL1Jlc291cmNlcy9Eb2NzL1N1YkRvbWFpbi9Ib21lUGFnZS9UaG9uZ0Jhby8yMDIwLzIwMjBfNC9Gb3JtYXRGYWN0b3J5JTIwUERGJTIwSm9pbmVyJTIwQklBJTIwMSUyMGJhbyUyMGNhb18xLnBkZj9mYmNsaWQ9SXdBUjFmNll6ZGZTYURINjlsZmEwNUhuQ3dwQXVFRjI1SFNEMHFraG5HSm1TVE14LUxaMmVBREZxeVd4cykpLiBDaMO6bmcgdGEgY8OzIHRo4buDIGPhuqNpIHRp4bq/biBs4bqhaSBuaMawIHNhdTogDQoNCiFbXShDOlxcVXNlcnNcXEFETUlOXFxEZXNrdG9wXFxjb3JvbmEuanBnKQ0KDQojIFIgY29kZXMgDQoNClIgY29kZXMgxJHhu4MgdGjhu7FjIGhp4buHbiBow6xuaCBuw6B5IG5oxrAgc2F1OiANCg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCiMgTG9hZCBzb21lIHBhY2thZ2VzOiANCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShsdWJyaWRhdGUpDQoNCiMgRGF0YSBsaW5rcyAoc291cmNlOiBodHRwczovL2dpdGh1Yi5jb20vQ1NTRUdJU2FuZERhdGEvQ09WSUQtMTkpOiANCnJtKGxpc3QgPSBscygpKQ0KbGluazEgPC0gImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9DU1NFR0lTYW5kRGF0YS9DT1ZJRC0xOS9tYXN0ZXIvY3NzZV9jb3ZpZF8xOV9kYXRhL2Nzc2VfY292aWRfMTlfdGltZV9zZXJpZXMvdGltZV9zZXJpZXNfY292aWQxOV9jb25maXJtZWRfZ2xvYmFsLmNzdiINCmxpbmsyIDwtICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vQ1NTRUdJU2FuZERhdGEvQ09WSUQtMTkvbWFzdGVyL2Nzc2VfY292aWRfMTlfZGF0YS9jc3NlX2NvdmlkXzE5X3RpbWVfc2VyaWVzL3RpbWVfc2VyaWVzX2NvdmlkMTlfcmVjb3ZlcmVkX2dsb2JhbC5jc3YiDQpsaW5rMyA8LSAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0NTU0VHSVNhbmREYXRhL0NPVklELTE5L21hc3Rlci9jc3NlX2NvdmlkXzE5X2RhdGEvY3NzZV9jb3ZpZF8xOV90aW1lX3Nlcmllcy90aW1lX3Nlcmllc19jb3ZpZDE5X3JlY292ZXJlZF9nbG9iYWwuY3N2Ig0KDQojIENsZWFuIGFuZCBwcmVwYXJlIGRhdGE6IA0KDQpsaW5rMSAlPiUgDQogIHJlYWRfY3N2KCkgJT4lIA0KICByZW5hbWUoUHJvdmluY2UgPSBgUHJvdmluY2UvU3RhdGVgLCBDb3VudHJ5ID0gYENvdW50cnkvUmVnaW9uYCkgJT4lIA0KICBnYXRoZXIoRGF0ZSwgQ29uZmlybWVkLCAtUHJvdmluY2UsIC1Db3VudHJ5LCAtTGF0LCAtTG9uZykgJT4lIA0KICBtdXRhdGUoRGF0ZSA9IG1keShEYXRlKSkgJT4lIA0KICBmaWx0ZXIoQ291bnRyeSA9PSAiVmlldG5hbSIsIERhdGUgPD0geW1kKCIyMDIwLTA0LTA0IikpIC0+IGRmX2NvbmZpcm1lZA0KDQpkZl9jb25maXJtZWQgJT4lIA0KICBtdXRhdGUoYmVmb3JlID0gbGFnKENvbmZpcm1lZCkpICU+JSANCiAgbXV0YXRlKE5ld0NvbmZpcm1lZCA9IENvbmZpcm1lZCAtIGJlZm9yZSkgJT4lIA0KICBzbGljZSgtMSkgLT4gZGZfZm9yX2cxDQoNCmVuZF9zdGFnZTEgPC0gZG15KCIxMy0wMi0yMDIwIikNCnN0YXJ0X3N0YWdlMiA8LSBkbXkoIjA2LTAzLTIwMjAiKQ0KZW5kX3N0YWdlMiA8LSBkbXkoIjIxLTAzLTIwMjAiKQ0KDQpkZl9mb3JfZzEgJT4lIA0KICBtdXRhdGUoU3RhZ2UgPSBjYXNlX3doZW4oRGF0ZSA8PSBlbmRfc3RhZ2UxIH4gIlN0YWdlIDEiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIERhdGUgPiBlbmRfc3RhZ2UxICYgRGF0ZSA8IHN0YXJ0X3N0YWdlMiB+ICJTdGFuZGJ5IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBEYXRlID49IHN0YXJ0X3N0YWdlMiAmIERhdGUgPD0gZW5kX3N0YWdlMiB+ICJTdGFnZSAyIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIlN0YWdlIDMiKSkgLT4gZGYNCg0KZGYgJT4lIA0KICBzZWxlY3QoVG90YWxDb25maXJtZWQgPSBDb25maXJtZWQsIE5ld0NvbmZpcm1lZCwgRGF0ZSkgJT4lIA0KICBnYXRoZXIoVHlwZSwgVmFsdWUsIC1EYXRlKSAtPiBkZl9wbG90DQoNCmRmX3Bsb3QkRGF0ZSAlPiUgdW5pcXVlKCkgLT4gbXlfZGF0ZQ0KDQpkZl9sYWJlbHMgPC0gZGF0YS5mcmFtZShEYXRlID0gbXlfZGF0ZSkNCg0KZGZfbGFiZWxzICU+JSANCiAgbXV0YXRlKGxhYmVsX3ggPSBjYXNlX3doZW4oRGF0ZSA9PSBtaW4oRGF0ZSkgfiBhcy5jaGFyYWN0ZXIoRGF0ZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEYXRlID09IGVuZF9zdGFnZTEgfiBhcy5jaGFyYWN0ZXIoZW5kX3N0YWdlMSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEYXRlID09IHN0YXJ0X3N0YWdlMiB+IGFzLmNoYXJhY3RlcihzdGFydF9zdGFnZTIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGF0ZSA9PSBlbmRfc3RhZ2UyIH4gYXMuY2hhcmFjdGVyKGVuZF9zdGFnZTIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGF0ZSA9PSBtYXgoRGF0ZSkgfiBhcy5jaGFyYWN0ZXIoRGF0ZSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIiIpKSAlPiUgDQogIG11dGF0ZShTdGFnZSA9IGNhc2Vfd2hlbihEYXRlIDw9IGVuZF9zdGFnZTEgfiAiU3RhZ2UgMSIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgRGF0ZSA+IGVuZF9zdGFnZTEgJiBEYXRlIDwgc3RhcnRfc3RhZ2UyIH4gIlN0YW5kYnkiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIERhdGUgPj0gc3RhcnRfc3RhZ2UyICYgRGF0ZSA8PSBlbmRfc3RhZ2UyIH4gIlN0YWdlIDIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiU3RhZ2UgMyIpKSAlPiUgDQogIG11dGF0ZShsYWJlbF94ID0gY2FzZV93aGVuKGxhYmVsX3ggPT0gIjIwMjAtMDEtMjMiIH4gIjIzLTAxIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsX3ggPT0gIjIwMjAtMDItMTMiIH4gIjEzLTAyIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsX3ggPT0gIjIwMjAtMDMtMDYiIH4gIjA2LTAzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsX3ggPT0gIjIwMjAtMDMtMjEiIH4gIjIxLTAzIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsX3ggPT0gIjIwMjAtMDQtMDQiIH4gIjA0LTA0IiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBsYWJlbF94KSkgLT4gZGZfbGFiZWxzDQoNCg0KDQpkZl9mb3JfZzEgJT4lIA0KICBmaWx0ZXIoRGF0ZSA9PSBtYXgoRGF0ZSkpICU+JSANCiAgbXV0YXRlKERhdGUgPSBEYXRlICsgMikgJT4lIA0KICBzZWxlY3QoVG90YWxDb25maXJtZWQgPSBDb25maXJtZWQsIE5ld0NvbmZpcm1lZCwgRGF0ZSkgJT4lIA0KICBnYXRoZXIoVHlwZSwgVmFsdWUsIC1EYXRlKSAlPiUgDQogIG11dGF0ZShsYWJlbCA9IGNhc2Vfd2hlbihWYWx1ZSA9PSA0IH4gcGFzdGUwKFZhbHVlLCAiICAiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gYXMuY2hhcmFjdGVyKFZhbHVlKSkpIC0+IGRmX2FuIA0KDQoNCmZpbGxfY29sb3JzIDwtIGMoIiNmZmY1ZjAiLCAiI2ZjYmJhMSIsICIjZmM5MjcyIiwgIiNmYjZhNGEiKQ0KbGluZV9jb2xvcnMgPC0gYygiI2U0MWExYyIsICIjMWY3OGI0IikNCmggPC0gMjUwDQprIDwtIC0wLjUNCm15X2ZvbnQgPC0gIlVidW50dSBDb25kZW5zZWQiDQoNCmdncGxvdCgpICsgDQogIHRoZW1lX21pbmltYWwoKSArIA0KICBnZW9tX3JlY3QoYWVzKHhtaW4gPSBtaW4obXlfZGF0ZSksIHhtYXggPSBlbmRfc3RhZ2UxLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJTdGFnZSAxIiksIGZpbGwgPSAiI2ExZDk5YiIsIGFscGhhID0gMC4zLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArIA0KICBnZW9tX3JlY3QoYWVzKHhtaW4gPSBlbmRfc3RhZ2UxLCB4bWF4ID0gc3RhcnRfc3RhZ2UyLCB5bWluID0gLUluZiwgeW1heCA9IEluZiwgZmlsbCA9ICJTdGFuZGJ5IiksIGZpbGwgPSBmaWxsX2NvbG9yc1syXSwgYWxwaGEgPSAwLjMsIHNob3cubGVnZW5kID0gRkFMU0UpICsgDQogIGdlb21fcmVjdChhZXMoeG1pbiA9IHN0YXJ0X3N0YWdlMiwgeG1heCA9IGVuZF9zdGFnZTIsIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCBmaWxsID0gIlN0YWdlIDIiKSwgZmlsbCA9IGZpbGxfY29sb3JzWzNdLCBhbHBoYSA9IDAuMywgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKyANCiAgZ2VvbV9yZWN0KGFlcyh4bWluID0gZW5kX3N0YWdlMiwgeG1heCA9IG1heChteV9kYXRlKSwgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsIGZpbGwgPSAiU3RhZ2UgMyIpLCBmaWxsID0gZmlsbF9jb2xvcnNbNF0sIGFscGhhID0gMC4zLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArIA0KICBnZW9tX2xpbmUoZGF0YSA9IGRmX3Bsb3QsIGFlcyhEYXRlLCBWYWx1ZSwgY29sb3IgPSBUeXBlKSwgc2l6ZSA9IDEuNSkgKyANCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGxpbmVfY29sb3JzLCBuYW1lID0gIiIsIGxhYmVscyA9IGMoIk5ldyIsICJUb3RhbCIpKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDI1MCwgMjUpLCBsaW1pdHMgPSBjKDAsIDI1MCkpICsgDQogIHRoZW1lKHBhbmVsLmdyaWQubWlub3IueSA9IGVsZW1lbnRfYmxhbmsoKSkgKyANCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsgDQogIHNjYWxlX3hfZGF0ZShsaW1pdHMgPSBjKG1pbihteV9kYXRlKSwgbWF4KG15X2RhdGUpICsgMyksIGJyZWFrcyA9IHNlcShtaW4obXlfZGF0ZSksIG1heChteV9kYXRlKSwgMSksIA0KICAgICAgICAgICAgICAgbGFiZWxzID0gZGZfbGFiZWxzJGxhYmVsX3gsIHBvc2l0aW9uID0gInRvcCIsIGV4cGFuZCA9IGMoMCwgMCkpICsgDQogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpKSArIA0KICBnZW9tX3RleHQoZGF0YSA9IGRmX2FuLCBhZXMoRGF0ZSwgVmFsdWUsIGxhYmVsID0gbGFiZWwpLCBzaG93LmxlZ2VuZCA9IEZBTFNFLCBjb2xvciA9IGxpbmVfY29sb3JzWzI6MV0sIHNpemUgPSA0LjUsIA0KICAgICAgICAgICAgZm9udGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC42LCBmYW1pbHkgPSBteV9mb250KSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLCANCiAgICAgICB0aXRsZSA9ICJGaWd1cmUgMTogQ29yb25hdmlydXMgY2FzZXMgaW4gVmlldG5hbSwgYXMgb2YgMDQtMDQtMjAyMCIsIA0KICAgICAgIGNhcHRpb24gPSAiU291cmNlOiBNaW5pc3RyeSBvZiBIZWFsdGggb2YgVmlldG5hbSIpICsgDQogIGdlb21fdGV4dChkYXRhID0gZGF0YS5mcmFtZShEYXRlID0geW1kKCIyMDIwLTAxLTIzIikgKyAxMCwgVmFsdWUgPSBoKSwgYWVzKERhdGUsIFZhbHVlKSwgbGFiZWwgPSAiU3RhZ2UgMSIsIHNpemUgPSA0LCB2anVzdCA9IGssIGZhbWlseSA9IG15X2ZvbnQpICsgDQogIGdlb21fdGV4dChkYXRhID0gZGF0YS5mcmFtZShEYXRlID0geW1kKCIyMDIwLTAyLTEzIikgKyAxMSwgVmFsdWUgPSBoKSwgYWVzKERhdGUsIFZhbHVlKSwgbGFiZWwgPSAiU3RhbmRieSIsIHNpemUgPSA0LCB2anVzdCA9IGssIGZhbWlseSA9IG15X2ZvbnQpICsgDQogIGdlb21fdGV4dChkYXRhID0gZGF0YS5mcmFtZShEYXRlID0geW1kKCIyMDIwLTAzLTA2IikgKyA3LCBWYWx1ZSA9IGgpLCBhZXMoRGF0ZSwgVmFsdWUpLCBsYWJlbCA9ICJTdGFnZSAyIiwgc2l6ZSA9IDQsIHZqdXN0ID0gaywgZmFtaWx5ID0gbXlfZm9udCkgKyANCiAgZ2VvbV90ZXh0KGRhdGEgPSBkYXRhLmZyYW1lKERhdGUgPSB5bWQoIjIwMjAtMDMtMjEiKSArIDcsIFZhbHVlID0gaCksIGFlcyhEYXRlLCBWYWx1ZSksIGxhYmVsID0gIlN0YWdlIDMiLCBzaXplID0gNCwgdmp1c3QgPSBrLCBmYW1pbHkgPSBteV9mb250KSArIA0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGZhbWlseSA9IG15X2ZvbnQpKSArIA0KICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTMsIGZhbWlseSA9IG15X2ZvbnQpKSArIA0KICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygxLCAxLCAxLCAxKSwgImNtIikpICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gbXlfZm9udCwgc2l6ZSA9IDIwKSkgKyANCiAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGZhbWlseSA9IG15X2ZvbnQsIHNpemUgPSAxMCwgY29sb3IgPSAiZ3JleTMwIikpICsgDQogIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9IG15X2ZvbnQsIHNpemUgPSAxMCwgZmFjZSA9ICJib2xkIiwgY29sb3IgPSAiZ3JleTMwIikpDQoNCmBgYA0KDQoNCg0KDQoNCg==