Motivations

John Burn-Murdoch của tạp chí Financial Times (FT) trong một bài viết trên Twitter có trích dẫn lại plot sau:

Plot này từng được đăng trên FT tại đây. Plot này có thể được tái tạo lại bằng cách sử dụng R như sau:

R Codes

Dưới đây là R codes để tái tạo plot trên

# Clear work space: 
rm(list = ls())

# Load R packages: 
library(tidyverse)
library(lubridate)
library(ggtext)
library(glue)
library(zoo)

#----------------------------
#  Prepare data for ploting
#----------------------------

# Load data: 

owid_new_deaths_per_million_url <- "https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/jhu/new_deaths_per_million.csv"

covid_deaths <- read_csv(owid_new_deaths_per_million_url)

owid_new_cases_per_million_url <- "https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/jhu/new_cases_per_million.csv"

covid_cases <- read_csv(owid_new_cases_per_million_url)

# Set reporting period: 

start_date <- ymd("2022-02-01")

end_date <- ymd("2022-03-11")

nations_included <- c("New Zealand", "Hong Kong")

# Lag to shift cases: 

lag_cases_deaths <- duration("14 days") 

covid_deaths %>%
  mutate(metric = "deaths") %>%
  bind_rows(covid_cases %>% mutate(metric = "cases")) %>%
  pivot_longer(cols = -c("date", "metric"), names_to = "region", values_to = "new_per_million") %>%
  filter(region %in% nations_included) %>%
  group_by(region) %>%
  mutate(new_per_million = replace_na(new_per_million, 0),new_per_100k = new_per_million / 10) %>%
  mutate(new_per_100k_7drollmean = rollmean(new_per_100k, 7, fill = NA, align = "right"),
         new_per_million_7drollmean = rollmean(new_per_million, 7, fill = NA, align = "right")) %>%
  arrange(region) %>%
  mutate(date2 = case_when(metric == "cases" ~ date + lag_cases_deaths, TRUE ~ date)) %>%
  filter(date2 >= start_date, date2 <= end_date) -> covid_df_long
  
# Colors for our plot: 

color_cases_text <- "#258BC3"

color_cases <- "#71C8E4"
color_deaths <- "#CE3240" 

bgr_color <- "#FFF1E5"

library(showtext) # -> Package for using extra fonts. 

my_font <- "Outfit"  # -> Set Outfit font for our plot. 

font_add_google(name = my_font, family = my_font) # -> Load font for using. 

# Automatically render text: 

showtext_auto()

scales_on_y <- seq(-80, 120, 20)

y_text_label <- as.character(scales_on_y) %>% str_replace_all("-", "")

y_text_color <- case_when(scales_on_y > 0 ~ color_cases, 
                          scales_on_y < 0 ~ color_deaths, 
                          TRUE ~ "grey30")

p_title <- "Cases are translating into deaths at much higher rates in Hong Kong than\nin New Zealand, where elderly vaccination rates are much higher"

p_subtitle <- "Daily <b style='color:#71C8E4'>cases</b> per 100,000 people, and daily <b style='color:#CE3240'>deaths </b>per 2 million"

p_caption <- "Source: FT analysis of data from Johns Hopkins CSSE. Cases shifted forward to account for lag between infection and death"


country_annotations <- data.frame(
  region = c("Hong Kong", "New Zealand"),
  label = c(
    glue("<span style='color: black; font-size: 14pt; font-family: \"Outfit\"'>
    Hong Kong</span><br>
    66% of over-80s unvaccinated<br>when Omicron took off<br>
    <span style='color: {color_deaths}; font-family: \"Outfit\"'>Case fatality
         <br>rate: 4.7%</span>"),
    glue("<span style='color: black; font-size: 14pt; font-family: \"Outfit\"'>
    New Zealand</span><br>
    2% unvaccinated<br>
    <span style='color: {color_deaths}; font-family: \"Outfit\"'>CFR: 0.1%</span>")))

# Replicate area plot originated by John Burn-Murdoch: 

ggplot() + 
  geom_area(data = covid_df_long %>% filter(metric == "cases"), aes(date2, new_per_100k_7drollmean), fill = color_cases) + 
  geom_area(data = covid_df_long %>% filter(metric != "cases"), aes(date2, -2*new_per_million_7drollmean), fill = color_deaths) + 
  facet_wrap(~ region) + 
  scale_y_continuous(breaks = scales_on_y, labels = y_text_label, sec.axis = dup_axis()) + 
  scale_x_date(breaks = ymd(c("2022-02-01", "2022-03-01")), date_labels = "%b") + 
  theme(axis.title = element_blank()) + 
  theme(panel.grid.minor = element_blank()) + 
  theme(panel.grid.major.x = element_blank()) + 
  theme(plot.margin = unit(rep(1, 4), "cm")) + 
  theme(axis.text.y = element_text(color = y_text_color, family = my_font, size = 12)) + 
  theme(axis.text.x = element_text(family = my_font, size = 12, hjust = -0.05)) + 
  theme(plot.background = element_rect(color = NA, fill = bgr_color)) + 
  theme(panel.background = element_rect(color = NA, fill = NA)) + 
  theme(strip.text = element_blank()) + 
  theme(axis.ticks.y = element_blank()) + 
  theme(axis.ticks.length.x = unit(0.2, "cm")) + 
  theme(axis.ticks.x = element_line(color = "grey60", size = 0.8)) + 
  theme(panel.grid.major.y = element_line(size = 0.8, color = "grey90")) + 
  labs(title = p_title, subtitle = p_subtitle, caption = p_caption) + 
  theme(plot.title = element_text(family = my_font, size = 19, vjust = 2, hjust = 0)) + 
  theme(plot.subtitle = element_markdown(color = "grey30", family = my_font, size = 16)) + 
  theme(plot.caption = element_text(color = "grey30", family = my_font, size = 12, hjust = 0, vjust = -1.5)) + 
  geom_richtext(data = country_annotations, 
                aes(x = start_date, y = 115, label = label),
                size = 4.8, 
                label.size = NA, 
                fill = NA,
                family = my_font,
                color = "grey30", 
                hjust = 0, 
                vjust = 1)

# Make FT icon: 

library(grid)

grid.rect(x = 0, y = 1, width = 0.07, height = 0.01, just = c("left", "top"), gp = gpar(fill = "black", col = "black"))

Notes

  1. Font chữ Outfit được sử dụng trong plot trên chưa phải là font chữ mà FT sử dụng. Để giống hơn có thể tham khảo các loại font chữ mà tạp chí này sử dụng tại đây hoặc font chữ do Kris Sowersby thiết kế mà tạp chí này sử dụng từ năm 2016.

  2. Style màu sắc của tạp chí FT có thể được tham khảo tại đây.

  3. Cách thiết kế các plot của FT có thể đọc tại đây, tại đây.

  4. Annotations có thể tham khảo bài giảng của CÉDRIC SCHERER từ khóa học Hands-On Data Visualization with ggplot2.

  5. Một hướng dẫn khác tạo ra các graph của FT bằng R/ggplot2 tại đây.

  6. Có thể sử dụng ftplottools - một package của R để tái lập lại các graphs của FT.

LS0tDQp0aXRsZTogJ1IgZm9yIERhdGEgVmlzdWFsaXphdGlvbjogUmVwbGljYXRpbmcgRmluYW5jaWFsIFRpbWVzIEdyYXBoJw0KYXV0aG9yOiAnQXV0aG9yOiBOZ3V5ZW4gQ2hpIER1bmcnDQpzdWJ0aXRsZTogIkRhaWx5IEdyYXBoIFNlcmllcyINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgICMgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuDQogICAgIyBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRoZW1lOiAiZmxhdGx5Ig0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KLS0tDQoNCmBgYHtyIHNldHVwLGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCBjYWNoZSA9IFRSVUUsIGZpZy5zaG93dGV4dCA9IFRSVUUpDQoNCmBgYA0KDQojIE1vdGl2YXRpb25zDQoNCltKb2huIEJ1cm4tTXVyZG9jaF0oaHR0cHM6Ly93d3cuZnQuY29tL3N0cmVhbS9lMTkxNjU4ZS1jNjZhLTQ1YmMtOWJhZC0zNDNiZGM0MjEwYjMpIGPhu6dhIHThuqFwIGNow60gRmluYW5jaWFsIFRpbWVzIChGVCkgdHJvbmcgbeG7mXQgYsOgaSB2aeG6v3QgdHLDqm4gW1R3aXR0ZXJdKGh0dHBzOi8vbW9iaWxlLnR3aXR0ZXIuY29tL2pidXJubXVyZG9jaC9zdGF0dXMvMTUwMzQyMDY2MDg2OTIxNDIxMykgY8OzIHRyw61jaCBk4bqrbiBs4bqhaSBwbG90IHNhdTogDQoNCiFbXShDOi9Vc2Vycy9BZG1pbi9Eb2N1bWVudHMvb3JpZ2luYWxfcGxvdC5qcGcpDQoNClBsb3QgbsOgeSB04burbmcgxJHGsOG7o2MgxJHEg25nIHRyw6puIEZUIFt04bqhaSDEkcOieV0oaHR0cHM6Ly93d3cuZnQuY29tL2NvbnRlbnQvNmU2MTBjYWMtNDAwYi00ODQzLWEwN2ItN2Q4NzBlODYzNWEpLiBQbG90IG7DoHkgY8OzIHRo4buDIMSRxrDhu6NjIHTDoWkgdOG6oW8gbOG6oWkgYuG6sW5nIGPDoWNoIHPhu60gZOG7pW5nIFIgbmjGsCBzYXU6DQoNCiFbXShDOi9Vc2Vycy9BZG1pbi9Eb2N1bWVudHMvcGljX25ldy5qcGcpDQoNCiMgUiBDb2Rlcw0KDQpExrDhu5tpIMSRw6J5IGzDoCBSIGNvZGVzIMSR4buDIHTDoWkgdOG6oW8gcGxvdCB0csOqbg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCg0KIyBDbGVhciB3b3JrIHNwYWNlOiANCnJtKGxpc3QgPSBscygpKQ0KDQojIExvYWQgUiBwYWNrYWdlczogDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShnZ3RleHQpDQpsaWJyYXJ5KGdsdWUpDQpsaWJyYXJ5KHpvbykNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgIFByZXBhcmUgZGF0YSBmb3IgcGxvdGluZw0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyBMb2FkIGRhdGE6IA0KDQpvd2lkX25ld19kZWF0aHNfcGVyX21pbGxpb25fdXJsIDwtICJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vb3dpZC9jb3ZpZC0xOS1kYXRhL21hc3Rlci9wdWJsaWMvZGF0YS9qaHUvbmV3X2RlYXRoc19wZXJfbWlsbGlvbi5jc3YiDQoNCmNvdmlkX2RlYXRocyA8LSByZWFkX2Nzdihvd2lkX25ld19kZWF0aHNfcGVyX21pbGxpb25fdXJsKQ0KDQpvd2lkX25ld19jYXNlc19wZXJfbWlsbGlvbl91cmwgPC0gImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9vd2lkL2NvdmlkLTE5LWRhdGEvbWFzdGVyL3B1YmxpYy9kYXRhL2podS9uZXdfY2FzZXNfcGVyX21pbGxpb24uY3N2Ig0KDQpjb3ZpZF9jYXNlcyA8LSByZWFkX2Nzdihvd2lkX25ld19jYXNlc19wZXJfbWlsbGlvbl91cmwpDQoNCiMgU2V0IHJlcG9ydGluZyBwZXJpb2Q6IA0KDQpzdGFydF9kYXRlIDwtIHltZCgiMjAyMi0wMi0wMSIpDQoNCmVuZF9kYXRlIDwtIHltZCgiMjAyMi0wMy0xMSIpDQoNCm5hdGlvbnNfaW5jbHVkZWQgPC0gYygiTmV3IFplYWxhbmQiLCAiSG9uZyBLb25nIikNCg0KIyBMYWcgdG8gc2hpZnQgY2FzZXM6IA0KDQpsYWdfY2FzZXNfZGVhdGhzIDwtIGR1cmF0aW9uKCIxNCBkYXlzIikgDQoNCmNvdmlkX2RlYXRocyAlPiUNCiAgbXV0YXRlKG1ldHJpYyA9ICJkZWF0aHMiKSAlPiUNCiAgYmluZF9yb3dzKGNvdmlkX2Nhc2VzICU+JSBtdXRhdGUobWV0cmljID0gImNhc2VzIikpICU+JQ0KICBwaXZvdF9sb25nZXIoY29scyA9IC1jKCJkYXRlIiwgIm1ldHJpYyIpLCBuYW1lc190byA9ICJyZWdpb24iLCB2YWx1ZXNfdG8gPSAibmV3X3Blcl9taWxsaW9uIikgJT4lDQogIGZpbHRlcihyZWdpb24gJWluJSBuYXRpb25zX2luY2x1ZGVkKSAlPiUNCiAgZ3JvdXBfYnkocmVnaW9uKSAlPiUNCiAgbXV0YXRlKG5ld19wZXJfbWlsbGlvbiA9IHJlcGxhY2VfbmEobmV3X3Blcl9taWxsaW9uLCAwKSxuZXdfcGVyXzEwMGsgPSBuZXdfcGVyX21pbGxpb24gLyAxMCkgJT4lDQogIG11dGF0ZShuZXdfcGVyXzEwMGtfN2Ryb2xsbWVhbiA9IHJvbGxtZWFuKG5ld19wZXJfMTAwaywgNywgZmlsbCA9IE5BLCBhbGlnbiA9ICJyaWdodCIpLA0KICAgICAgICAgbmV3X3Blcl9taWxsaW9uXzdkcm9sbG1lYW4gPSByb2xsbWVhbihuZXdfcGVyX21pbGxpb24sIDcsIGZpbGwgPSBOQSwgYWxpZ24gPSAicmlnaHQiKSkgJT4lDQogIGFycmFuZ2UocmVnaW9uKSAlPiUNCiAgbXV0YXRlKGRhdGUyID0gY2FzZV93aGVuKG1ldHJpYyA9PSAiY2FzZXMiIH4gZGF0ZSArIGxhZ19jYXNlc19kZWF0aHMsIFRSVUUgfiBkYXRlKSkgJT4lDQogIGZpbHRlcihkYXRlMiA+PSBzdGFydF9kYXRlLCBkYXRlMiA8PSBlbmRfZGF0ZSkgLT4gY292aWRfZGZfbG9uZw0KICANCiMgQ29sb3JzIGZvciBvdXIgcGxvdDogDQoNCmNvbG9yX2Nhc2VzX3RleHQgPC0gIiMyNThCQzMiDQoNCmNvbG9yX2Nhc2VzIDwtICIjNzFDOEU0Ig0KY29sb3JfZGVhdGhzIDwtICIjQ0UzMjQwIiANCg0KYmdyX2NvbG9yIDwtICIjRkZGMUU1Ig0KDQpsaWJyYXJ5KHNob3d0ZXh0KSAjIC0+IFBhY2thZ2UgZm9yIHVzaW5nIGV4dHJhIGZvbnRzLiANCg0KbXlfZm9udCA8LSAiT3V0Zml0IiAgIyAtPiBTZXQgT3V0Zml0IGZvbnQgZm9yIG91ciBwbG90LiANCg0KZm9udF9hZGRfZ29vZ2xlKG5hbWUgPSBteV9mb250LCBmYW1pbHkgPSBteV9mb250KSAjIC0+IExvYWQgZm9udCBmb3IgdXNpbmcuIA0KDQojIEF1dG9tYXRpY2FsbHkgcmVuZGVyIHRleHQ6IA0KDQpzaG93dGV4dF9hdXRvKCkNCg0Kc2NhbGVzX29uX3kgPC0gc2VxKC04MCwgMTIwLCAyMCkNCg0KeV90ZXh0X2xhYmVsIDwtIGFzLmNoYXJhY3RlcihzY2FsZXNfb25feSkgJT4lIHN0cl9yZXBsYWNlX2FsbCgiLSIsICIiKQ0KDQp5X3RleHRfY29sb3IgPC0gY2FzZV93aGVuKHNjYWxlc19vbl95ID4gMCB+IGNvbG9yX2Nhc2VzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVzX29uX3kgPCAwIH4gY29sb3JfZGVhdGhzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJncmV5MzAiKQ0KDQpwX3RpdGxlIDwtICJDYXNlcyBhcmUgdHJhbnNsYXRpbmcgaW50byBkZWF0aHMgYXQgbXVjaCBoaWdoZXIgcmF0ZXMgaW4gSG9uZyBLb25nIHRoYW5cbmluIE5ldyBaZWFsYW5kLCB3aGVyZSBlbGRlcmx5IHZhY2NpbmF0aW9uIHJhdGVzIGFyZSBtdWNoIGhpZ2hlciINCg0KcF9zdWJ0aXRsZSA8LSAiRGFpbHkgPGIgc3R5bGU9J2NvbG9yOiM3MUM4RTQnPmNhc2VzPC9iPiBwZXIgMTAwLDAwMCBwZW9wbGUsIGFuZCBkYWlseSA8YiBzdHlsZT0nY29sb3I6I0NFMzI0MCc+ZGVhdGhzIDwvYj5wZXIgMiBtaWxsaW9uIg0KDQpwX2NhcHRpb24gPC0gIlNvdXJjZTogRlQgYW5hbHlzaXMgb2YgZGF0YSBmcm9tIEpvaG5zIEhvcGtpbnMgQ1NTRS4gQ2FzZXMgc2hpZnRlZCBmb3J3YXJkIHRvIGFjY291bnQgZm9yIGxhZyBiZXR3ZWVuIGluZmVjdGlvbiBhbmQgZGVhdGgiDQoNCg0KY291bnRyeV9hbm5vdGF0aW9ucyA8LSBkYXRhLmZyYW1lKA0KICByZWdpb24gPSBjKCJIb25nIEtvbmciLCAiTmV3IFplYWxhbmQiKSwNCiAgbGFiZWwgPSBjKA0KICAgIGdsdWUoIjxzcGFuIHN0eWxlPSdjb2xvcjogYmxhY2s7IGZvbnQtc2l6ZTogMTRwdDsgZm9udC1mYW1pbHk6IFwiT3V0Zml0XCInPg0KICAgIEhvbmcgS29uZzwvc3Bhbj48YnI+DQogICAgNjYlIG9mIG92ZXItODBzIHVudmFjY2luYXRlZDxicj53aGVuIE9taWNyb24gdG9vayBvZmY8YnI+DQogICAgPHNwYW4gc3R5bGU9J2NvbG9yOiB7Y29sb3JfZGVhdGhzfTsgZm9udC1mYW1pbHk6IFwiT3V0Zml0XCInPkNhc2UgZmF0YWxpdHkNCiAgICAgICAgIDxicj5yYXRlOiA0LjclPC9zcGFuPiIpLA0KICAgIGdsdWUoIjxzcGFuIHN0eWxlPSdjb2xvcjogYmxhY2s7IGZvbnQtc2l6ZTogMTRwdDsgZm9udC1mYW1pbHk6IFwiT3V0Zml0XCInPg0KICAgIE5ldyBaZWFsYW5kPC9zcGFuPjxicj4NCiAgICAyJSB1bnZhY2NpbmF0ZWQ8YnI+DQogICAgPHNwYW4gc3R5bGU9J2NvbG9yOiB7Y29sb3JfZGVhdGhzfTsgZm9udC1mYW1pbHk6IFwiT3V0Zml0XCInPkNGUjogMC4xJTwvc3Bhbj4iKSkpDQoNCiMgUmVwbGljYXRlIGFyZWEgcGxvdCBvcmlnaW5hdGVkIGJ5IEpvaG4gQnVybi1NdXJkb2NoOiANCg0KZ2dwbG90KCkgKyANCiAgZ2VvbV9hcmVhKGRhdGEgPSBjb3ZpZF9kZl9sb25nICU+JSBmaWx0ZXIobWV0cmljID09ICJjYXNlcyIpLCBhZXMoZGF0ZTIsIG5ld19wZXJfMTAwa183ZHJvbGxtZWFuKSwgZmlsbCA9IGNvbG9yX2Nhc2VzKSArIA0KICBnZW9tX2FyZWEoZGF0YSA9IGNvdmlkX2RmX2xvbmcgJT4lIGZpbHRlcihtZXRyaWMgIT0gImNhc2VzIiksIGFlcyhkYXRlMiwgLTIqbmV3X3Blcl9taWxsaW9uXzdkcm9sbG1lYW4pLCBmaWxsID0gY29sb3JfZGVhdGhzKSArIA0KICBmYWNldF93cmFwKH4gcmVnaW9uKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2NhbGVzX29uX3ksIGxhYmVscyA9IHlfdGV4dF9sYWJlbCwgc2VjLmF4aXMgPSBkdXBfYXhpcygpKSArIA0KICBzY2FsZV94X2RhdGUoYnJlYWtzID0geW1kKGMoIjIwMjItMDItMDEiLCAiMjAyMi0wMy0wMSIpKSwgZGF0ZV9sYWJlbHMgPSAiJWIiKSArIA0KICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSArIA0KICB0aGVtZShwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpKSArIA0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCkpICsgDQogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChyZXAoMSwgNCksICJjbSIpKSArIA0KICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9IHlfdGV4dF9jb2xvciwgZmFtaWx5ID0gbXlfZm9udCwgc2l6ZSA9IDEyKSkgKyANCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gbXlfZm9udCwgc2l6ZSA9IDEyLCBoanVzdCA9IC0wLjA1KSkgKyANCiAgdGhlbWUocGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gTkEsIGZpbGwgPSBiZ3JfY29sb3IpKSArIA0KICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gTkEsIGZpbGwgPSBOQSkpICsgDQogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X2JsYW5rKCkpICsgDQogIHRoZW1lKGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSkgKyANCiAgdGhlbWUoYXhpcy50aWNrcy5sZW5ndGgueCA9IHVuaXQoMC4yLCAiY20iKSkgKyANCiAgdGhlbWUoYXhpcy50aWNrcy54ID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyZXk2MCIsIHNpemUgPSAwLjgpKSArIA0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuOCwgY29sb3IgPSAiZ3JleTkwIikpICsgDQogIGxhYnModGl0bGUgPSBwX3RpdGxlLCBzdWJ0aXRsZSA9IHBfc3VidGl0bGUsIGNhcHRpb24gPSBwX2NhcHRpb24pICsgDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gbXlfZm9udCwgc2l6ZSA9IDE5LCB2anVzdCA9IDIsIGhqdXN0ID0gMCkpICsgDQogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X21hcmtkb3duKGNvbG9yID0gImdyZXkzMCIsIGZhbWlseSA9IG15X2ZvbnQsIHNpemUgPSAxNikpICsgDQogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmV5MzAiLCBmYW1pbHkgPSBteV9mb250LCBzaXplID0gMTIsIGhqdXN0ID0gMCwgdmp1c3QgPSAtMS41KSkgKyANCiAgZ2VvbV9yaWNodGV4dChkYXRhID0gY291bnRyeV9hbm5vdGF0aW9ucywgDQogICAgICAgICAgICAgICAgYWVzKHggPSBzdGFydF9kYXRlLCB5ID0gMTE1LCBsYWJlbCA9IGxhYmVsKSwNCiAgICAgICAgICAgICAgICBzaXplID0gNC44LCANCiAgICAgICAgICAgICAgICBsYWJlbC5zaXplID0gTkEsIA0KICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwNCiAgICAgICAgICAgICAgICBmYW1pbHkgPSBteV9mb250LA0KICAgICAgICAgICAgICAgIGNvbG9yID0gImdyZXkzMCIsIA0KICAgICAgICAgICAgICAgIGhqdXN0ID0gMCwgDQogICAgICAgICAgICAgICAgdmp1c3QgPSAxKQ0KDQojIE1ha2UgRlQgaWNvbjogDQoNCmxpYnJhcnkoZ3JpZCkNCg0KZ3JpZC5yZWN0KHggPSAwLCB5ID0gMSwgd2lkdGggPSAwLjA3LCBoZWlnaHQgPSAwLjAxLCBqdXN0ID0gYygibGVmdCIsICJ0b3AiKSwgZ3AgPSBncGFyKGZpbGwgPSAiYmxhY2siLCBjb2wgPSAiYmxhY2siKSkNCmBgYA0KDQojIE5vdGVzDQoNCjEuIEZvbnQgY2jhu68gT3V0Zml0IMSRxrDhu6NjIHPhu60gZOG7pW5nIHRyb25nIHBsb3QgdHLDqm4gY2jGsGEgcGjhuqNpIGzDoCBmb250IGNo4buvIG3DoCBGVCBz4butIGThu6VuZy4gxJDhu4MgZ2nhu5FuZyBoxqFuIGPDsyB0aOG7gyB0aGFtIGto4bqjbyBjw6FjIGxv4bqhaSBmb250IGNo4buvIG3DoCB04bqhcCBjaMOtIG7DoHkgc+G7rSBk4bulbmcgW3ThuqFpIMSRw6J5XShodHRwczovL2ZvbnRzaW51c2UuY29tL3RhZ3MvNjA2Ni9maW5hbmNpYWwtdGltZXMpIGhv4bq3YyBmb250IGNo4buvIGRvIFtLcmlzIFNvd2Vyc2J5XShodHRwczovL2tsaW0uY28ubnovaW4tdXNlL2ZpbmFuY2lhbC10aW1lcy8pIHRoaeG6v3Qga+G6vyBtw6AgdOG6oXAgY2jDrSBuw6B5IHPhu60gZOG7pW5nIHThu6sgbsSDbSAyMDE2LiANCg0KMi4gU3R5bGUgbcOgdSBz4bqvYyBj4bunYSB04bqhcCBjaMOtIEZUIGPDsyB0aOG7gyDEkcaw4bujYyB0aGFtIGto4bqjbyBbdOG6oWkgxJHDonldKGh0dHBzOi8vd3d3LnNjaGVtZWNvbG9yLmNvbS9maW5hbmNpYWwtdGltZXMtd2ViLXNpdGUucGhwKS4gDQoNCjMuIEPDoWNoIHRoaeG6v3Qga+G6vyBjw6FjIHBsb3QgY+G7p2EgRlQgY8OzIHRo4buDIMSR4buNYyBbdOG6oWkgxJHDonldKGh0dHBzOi8vd3d3LmZ0LmNvbS9jb250ZW50LzQ3NDNjZTk2LWU0YmYtMTFlNy05N2UyLTkxNmQ0ZmJhYzBkYSksIFt04bqhaSDEkcOieV0oaHR0cHM6Ly93d3cuZnQuY29tL2NvbnRlbnQvYzRiN2Q4YmUtMmViMC0xMWU4LTliNGItYmM0YjlmMDhmMzgxKS4gDQoNCjQuIEFubm90YXRpb25zIGPDsyB0aOG7gyB0aGFtIGto4bqjbyBiw6BpIGdp4bqjbmcgY+G7p2EgW0PDiURSSUMgU0NIRVJFUl0oaHR0cHM6Ly93d3cuY2Vkcmljc2NoZXJlci5jb20vKSB04burIGtow7NhIGjhu41jIFtIYW5kcy1PbiBEYXRhIFZpc3VhbGl6YXRpb24gd2l0aCBnZ3Bsb3QyXShodHRwczovL3d3dy5vcmVpbGx5LmNvbS9saXZlLWV2ZW50cy9oYW5kcy1vbi1kYXRhLXZpc3VhbGl6YXRpb24td2l0aC1nZ3Bsb3QyLzA2MzY5MjAwNjA5MjEvMDYzNjkyMDA2NDg1OC8pLiANCg0KNS4gTeG7mXQgaMaw4bubbmcgZOG6q24ga2jDoWMgdOG6oW8gcmEgY8OhYyBncmFwaCBj4bunYSBGVCBi4bqxbmcgUi9nZ3Bsb3QyIFt04bqhaSDEkcOieV0oaHR0cHM6Ly9wZXltYW5rb3IubmV0bGlmeS5hcHAvcG9zdC9mdC8pLiANCg0KNi4gQ8OzIHRo4buDIHPhu60gZOG7pW5nIFtmdHBsb3R0b29sc10oaHR0cHM6Ly9yZHJyLmlvL2dpdGh1Yi9GaW5hbmNpYWwtVGltZXMvZnRwbG90dG9vbHMvKSAtIG3hu5l0IHBhY2thZ2UgY+G7p2EgUiDEkeG7gyB0w6FpIGzhuq1wIGzhuqFpIGPDoWMgZ3JhcGhzIGPhu6dhIEZULiANCg0KDQo=