
Motivations
Motivation 1. Mỗi tuần The Economist tạo ra chừng 40 graphs khác nhau cho các bài báo. Data visualization được sử dụng để đưa ra insight/fact tiềm ẩn trong dữ liệu. Bất cứ graph nào mà thất bại trong nhiệm vụ này như đưa ra các thông tin gây hiểu lầm, hiểu sai (misleading/confusing) thì coi như đó là một graph không đạt tiêu chuẩn. Sarah Leo - một visual data journalist tại The Economist đã chỉ ra và phân tích một số cases mà data visualization của chính tạp chí này thất bại trong việc truyền tải insight tiềm ẩn trong dữ liệu. Các cases này được phân tích chi tiết tại đây.
Một case về data visualization thất bại trong việc đưa ra insight của tạp chí này là sử dụng line graph. Khi khi nhìn vào plot (hình bên trái) chúng ta không thể nào nhận ra xu hướng rằng theo thời gian, càng nhiều người Anh cho rằng việc Anh rời bỏ EU là sai trái. Tuy nhiên nếu chúng ta sử dụng phương pháp hình ảnh hóa thích hợp thì chúng ta có thể đưa ra insight đúng cho người tiếp nhận thông tin (hình bên phải).
Một ví dụ khác về sự cẩu thả trong data visualization là các graphs của GSO - cơ quan thống kê quốc gia của Việt Nam. Ví dụ như graph dưới đây thì người tiếp nhận thông tin không tài nào (hoặc rất khó) nhận được một insight gì có ý nghĩa (chưa kể cả đơn giản và cũng là rất quan trọng là title cũng cẩu thả):

Motivation 2. Việc sử dụng màu sắc cũng không nên cẩu thả và tùy tiện. Graphs của các tạp chí như The Economist, Financial Times hay The Wall Street Journal đều sử dụng một style màu nhất quán và mang dấu ấn riêng của mỗi tạp chí mà không thể lẫn với bất kì tạp chí nào khác. Chúng ta có thể tham khảo tư vấn của Helen Atkinson - là một visual data journalist tại tạp chí The Economist tại đây về sử dụng màu sắc.
R Codes
R codes dưới đây mô phỏng lại phiên bản original của The Economist cũng như graph được hiệu chỉnh để insight đúng và không gây hiểu lầm cho người tiếp nhận thông tin:
#=====================================================================
# References:
# https://medium.economist.com/charting-new-territory-7f5afb293270
# https://medium.economist.com/mistakes-weve-drawn-a-few-8cdd8a42d368
#=====================================================================
# Clear R environment:
rm(list = ls())
# Load some packages:
library(tidyverse)
library(lubridate)
library(extrafont)
library(ggtext)
# Load data:
data <- read_csv("Economist_brexit.csv", skip = 3)
n_obs <- nrow(data)
# Rename for columns:
names(data) <- c("date", "Right", "Wrong")
# Convert to date time and long from:
data %>%
mutate(date = dmy(date), id = 1:n_obs) %>%
gather(response, percent, -date, -id) -> data
# Prepare for data visualization:
my_font <- "Roboto Condensed"
my_colors <- c("#00a4dc", "#f15a40")
bgr_color <- "#d9e9f0"
# Function create our theme:
our_theme <- function(...) {
theme(plot.background = element_rect(fill = bgr_color, color = NA)) +
theme(panel.background = element_rect(fill = "white")) +
theme(panel.grid.major.y = element_line(color = "grey85", size = 0.8)) +
theme(axis.title.y = element_blank()) +
theme(axis.text.y = element_blank()) +
theme(axis.ticks.y = element_blank()) +
theme(axis.title.x = element_blank()) +
theme(plot.margin = unit(c(0.3, 1, 0.5, 1), "cm")) +
theme(text = element_text(family = my_font))
}
# Simulate original version:
data %>%
ggplot(aes(date, percent, color = response)) +
geom_line(size = 1.3, show.legend = FALSE) +
scale_color_manual(values = my_colors) +
our_theme() +
scale_y_continuous(limits = c(38, 50.5), breaks = seq(38, 50, 2)) +
annotate("text", data$date %>% max() + 5, y = seq(38, 50, 2), label = seq(38, 50, 2),
hjust = -0.4, vjust = -0.5, size = 3.6, family = my_font, color = "grey40") +
labs(title = "Bremorse",
subtitle = "\"In hindsigh, do you think Britain was right or wrong\n to vote to leave the EU?\"",
caption = "Source: Natcen Social Research") +
theme(plot.title = element_text(size = 16)) +
theme(plot.subtitle = element_text(color = "grey30")) +
theme(plot.caption = element_text(color = "grey40", size = 10, vjust = -2)) +
annotate("text", data$date %>% max() - 250, y = 41, label = "Right", size = 4, family = my_font, color = "grey20") +
annotate("text", data$date %>% max() - 165, y = 48.5, label = "Wrong", size = 4, family = my_font, color = "grey20")
library(grid)
grid.rect(x = 0.015, y = 0.93, 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))
# Better version:
data %>%
ggplot(aes(date, percent, color = response)) +
geom_point(show.legend = FALSE, size = 2.5, alpha = 0.4) +
geom_smooth(show.legend = FALSE, size = 1.4, se = FALSE) +
scale_color_manual(values = my_colors) +
our_theme() +
scale_y_continuous(limits = c(38, 50.5), breaks = seq(38, 50, 2)) +
annotate("text", data$date %>% max() + 5, y = seq(38, 50, 2), label = seq(38, 50, 2),
hjust = -0.4, vjust = -0.5, size = 3.6, family = my_font, color = "grey40") +
labs(title = "Bremorse",
subtitle = "\"In hindsigh, do you think Britain was <b style='color:#00a4dc'>right</b> or <b style='color:#f15a40'>wrong</b> to vote to leave the EU?\"",
caption = "Source: Natcen Social Research") +
theme(plot.title = element_text(size = 16)) +
theme(plot.subtitle = element_markdown(color = "grey30")) +
theme(plot.caption = element_text(color = "grey40", size = 10, vjust = -2)) +
annotate("text", data$date %>% max() - 165, y = 41.5, label = "Right", size = 4, family = my_font, color = my_colors[1]) +
annotate("text", data$date %>% max() - 165, y = 46.6, label = "Wrong", size = 4, family = my_font, color = my_colors[2])
grid.rect(x = 0.015, y = 0.93, 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))
LS0tDQp0aXRsZTogJ01pc2xlYWRpbmcgQ2hhcnRzIGJ5IFRoZSBFY29ub21pc3QgYW5kIENvcnJlY3Rpb24nDQphdXRob3I6ICdBdXRob3I6IE5ndXllbiBDaGkgRHVuZycNCnN1YnRpdGxlOiAiRGFpbHkgR3JhcGggU2VyaWVzIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgIyBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBoaWdobGlnaHQ6IHplbmJ1cm4NCiAgICAjIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6ICJmbGF0bHkiDQogICAgdG9jOiBUUlVFDQogICAgdG9jX2Zsb2F0OiBUUlVFDQotLS0NCg0KYGBge3Igc2V0dXAsaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGNhY2hlID0gVFJVRSkNCg0KYGBgDQoNCg0KIVtdKEM6XFxVc2Vyc1xcQWRtaW5cXERvY3VtZW50c1xcYmV0dGVyMS5qcGcpDQoNCiMgTW90aXZhdGlvbnMNCg0KKipNb3RpdmF0aW9uIDEqKi4gTeG7l2kgdHXhuqduIFRoZSBFY29ub21pc3QgdOG6oW8gcmEgY2jhu6tuZyA0MCBncmFwaHMga2jDoWMgbmhhdSBjaG8gY8OhYyBiw6BpIGLDoW8uIERhdGEgdmlzdWFsaXphdGlvbiDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyDEkcawYSByYSBpbnNpZ2h0L2ZhY3QgdGnhu4FtIOG6qW4gdHJvbmcgZOG7ryBsaeG7h3UuIELhuqV0IGPhu6kgZ3JhcGggbsOgbyBtw6AgdGjhuqV0IGLhuqFpIHRyb25nIG5oaeG7h20gduG7pSBuw6B5IG5oxrAgxJHGsGEgcmEgY8OhYyB0aMO0bmcgdGluIGfDonkgaGnhu4N1IGzhuqdtLCBoaeG7g3Ugc2FpIChtaXNsZWFkaW5nL2NvbmZ1c2luZykgdGjDrCBjb2kgbmjGsCDEkcOzIGzDoCBt4buZdCBncmFwaCBraMO0bmcgxJHhuqF0IHRpw6p1IGNodeG6qW4uIFNhcmFoIExlbyAtIG3hu5l0IHZpc3VhbCBkYXRhIGpvdXJuYWxpc3QgdOG6oWkgVGhlIEVjb25vbWlzdCDEkcOjIGNo4buJIHJhIHbDoCBwaMOibiB0w61jaCBt4buZdCBz4buRIGNhc2VzIG3DoCBkYXRhIHZpc3VhbGl6YXRpb24gY+G7p2EgY2jDrW5oIHThuqFwIGNow60gbsOgeSB0aOG6pXQgYuG6oWkgdHJvbmcgdmnhu4djIHRydXnhu4FuIHThuqNpIGluc2lnaHQgdGnhu4FtIOG6qW4gdHJvbmcgZOG7ryBsaeG7h3UuIEPDoWMgY2FzZXMgbsOgeSDEkcaw4bujYyBwaMOibiB0w61jaCBjaGkgdGnhur90IFt04bqhaSDEkcOieV0oaHR0cHM6Ly9tZWRpdW0uZWNvbm9taXN0LmNvbS9taXN0YWtlcy13ZXZlLWRyYXduLWEtZmV3LThjZGQ4YTQyZDM2OCkuIA0KDQpN4buZdCBjYXNlIHbhu4EgZGF0YSB2aXN1YWxpemF0aW9uIHRo4bqldCBi4bqhaSB0cm9uZyB2aeG7h2MgxJHGsGEgcmEgaW5zaWdodCBj4bunYSB04bqhcCBjaMOtIG7DoHkgbMOgIHPhu60gZOG7pW5nIGxpbmUgZ3JhcGguIEtoaSBraGkgbmjDrG4gdsOgbyBwbG90IChow6xuaCBiw6puIHRyw6FpKSBjaMO6bmcgdGEga2jDtG5nIHRo4buDIG7DoG8gbmjhuq1uIHJhICp4dSBoxrDhu5tuZyogcuG6sW5nIHRoZW8gdGjhu51pIGdpYW4sIGPDoG5nIG5oaeG7gXUgbmfGsOG7nWkgQW5oIGNobyBy4bqxbmcgdmnhu4djIEFuaCBy4budaSBi4buPIEVVIGzDoCBzYWkgdHLDoWkuIFR1eSBuaGnDqm4gbuG6v3UgY2jDum5nIHRhIHPhu60gZOG7pW5nIHBoxrDGoW5nIHBow6FwIGjDrG5oIOG6o25oIGjDs2EgdGjDrWNoIGjhu6NwIHRow6wgY2jDum5nIHRhIGPDsyB0aOG7gyDEkcawYSByYSBpbnNpZ2h0IMSRw7puZyBjaG8gbmfGsOG7nWkgdGnhur9wIG5o4bqtbiB0aMO0bmcgdGluIChow6xuaCBiw6puIHBo4bqjaSkuIA0KDQpN4buZdCB2w60gZOG7pSBraMOhYyB24buBIHPhu7EgY+G6qXUgdGjhuqMgdHJvbmcgZGF0YSB2aXN1YWxpemF0aW9uIGzDoCBjw6FjIGdyYXBocyBj4bunYSBHU08gLSBjxqEgcXVhbiB0aOG7kW5nIGvDqiBxdeG7kWMgZ2lhIGPhu6dhIFZp4buHdCBOYW0uIFbDrSBk4bulIG5oxrAgZ3JhcGggZMaw4bubaSDEkcOieSB0aMOsIG5nxrDhu51pIHRp4bq/cCBuaOG6rW4gdGjDtG5nIHRpbiBraMO0bmcgdMOgaSBuw6BvIChob+G6t2MgcuG6pXQga2jDsykgbmjhuq1uIMSRxrDhu6NjIG3hu5l0IGluc2lnaHQgZ8OsIGPDsyDDvSBuZ2jEqWEgKGNoxrBhIGvhu4MgY+G6oyDEkcahbiBnaeG6o24gdsOgIGPFqW5nIGzDoCBy4bqldCBxdWFuIHRy4buNbmcgbMOgIHRpdGxlIGPFqW5nIGPhuql1IHRo4bqjKTogDQoNCiFbXShDOlxcVXNlcnNcXEFkbWluXFxEb2N1bWVudHNcXGdzbzEucG5nKQ0KDQoqKk1vdGl2YXRpb24gMioqLiBWaeG7h2Mgc+G7rSBk4bulbmcgbcOgdSBz4bqvYyBjxaluZyBraMO0bmcgbsOqbiBj4bqpdSB0aOG6oyB2w6AgdMO5eSB0aeG7h24uIEdyYXBocyBj4bunYSBjw6FjIHThuqFwIGNow60gbmjGsCBUaGUgRWNvbm9taXN0LCBGaW5hbmNpYWwgVGltZXMgaGF5IFRoZSBXYWxsIFN0cmVldCBKb3VybmFsIMSR4buBdSBz4butIGThu6VuZyBt4buZdCBzdHlsZSBtw6B1IG5o4bqldCBxdcOhbiB2w6AgbWFuZyBk4bqldSDhuqVuIHJpw6puZyBj4bunYSBt4buXaSB04bqhcCBjaMOtIG3DoCBraMO0bmcgdGjhu4MgbOG6q24gduG7m2kgYuG6pXQga8OsIHThuqFwIGNow60gbsOgbyBraMOhYy4gQ2jDum5nIHRhIGPDsyB0aOG7gyB0aGFtIGto4bqjbyB0xrAgduG6pW4gY+G7p2EgSGVsZW4gQXRraW5zb24gLSBsw6AgbeG7mXQgdmlzdWFsIGRhdGEgam91cm5hbGlzdCB04bqhaSB04bqhcCBjaMOtIFRoZSBFY29ub21pc3QgW3ThuqFpIMSRw6J5XShodHRwczovL21lZGl1bS5lY29ub21pc3QuY29tL2NoYXJ0aW5nLW5ldy10ZXJyaXRvcnktN2Y1YWZiMjkzMjcwKSB24buBIHPhu60gZOG7pW5nIG3DoHUgc+G6r2MuIA0KDQojIFIgQ29kZXMNCg0KUiBjb2RlcyBkxrDhu5tpIMSRw6J5IG3DtCBwaOG7j25nIGzhuqFpIHBoacOqbiBi4bqjbiBvcmlnaW5hbCBj4bunYSBUaGUgRWNvbm9taXN0IGPFqW5nIG5oxrAgZ3JhcGggxJHGsOG7o2MgaGnhu4d1IGNo4buJbmggxJHhu4MgaW5zaWdodCDEkcO6bmcgdsOgIGtow7RuZyBnw6J5IGhp4buDdSBs4bqnbSBjaG8gbmfGsOG7nWkgdGnhur9wIG5o4bqtbiB0aMO0bmcgdGluOiANCg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCg0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAgICAgICAgICAgICAgICAgICAgICAgUmVmZXJlbmNlczoNCiMgaHR0cHM6Ly9tZWRpdW0uZWNvbm9taXN0LmNvbS9jaGFydGluZy1uZXctdGVycml0b3J5LTdmNWFmYjI5MzI3MA0KIyBodHRwczovL21lZGl1bS5lY29ub21pc3QuY29tL21pc3Rha2VzLXdldmUtZHJhd24tYS1mZXctOGNkZDhhNDJkMzY4DQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCg0KIyBDbGVhciBSIGVudmlyb25tZW50OiANCnJtKGxpc3QgPSBscygpKQ0KDQojIExvYWQgc29tZSBwYWNrYWdlczogDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShleHRyYWZvbnQpDQpsaWJyYXJ5KGdndGV4dCkNCg0KIyBMb2FkIGRhdGE6IA0KZGF0YSA8LSByZWFkX2NzdigiRWNvbm9taXN0X2JyZXhpdC5jc3YiLCBza2lwID0gMykNCm5fb2JzIDwtIG5yb3coZGF0YSkNCg0KIyBSZW5hbWUgZm9yIGNvbHVtbnM6IA0KbmFtZXMoZGF0YSkgPC0gYygiZGF0ZSIsICJSaWdodCIsICJXcm9uZyIpDQoNCiMgQ29udmVydCB0byBkYXRlIHRpbWUgYW5kIGxvbmcgZnJvbTogDQpkYXRhICU+JSANCiAgbXV0YXRlKGRhdGUgPSBkbXkoZGF0ZSksIGlkID0gMTpuX29icykgJT4lIA0KICBnYXRoZXIocmVzcG9uc2UsIHBlcmNlbnQsIC1kYXRlLCAtaWQpIC0+IGRhdGEgDQoNCg0KIyBQcmVwYXJlIGZvciBkYXRhIHZpc3VhbGl6YXRpb246IA0KbXlfZm9udCA8LSAiUm9ib3RvIENvbmRlbnNlZCINCm15X2NvbG9ycyA8LSBjKCIjMDBhNGRjIiwgIiNmMTVhNDAiKQ0KYmdyX2NvbG9yIDwtICIjZDllOWYwIg0KDQojIEZ1bmN0aW9uIGNyZWF0ZSBvdXIgdGhlbWU6IA0KDQpvdXJfdGhlbWUgPC0gZnVuY3Rpb24oLi4uKSB7DQogIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gYmdyX2NvbG9yLCBjb2xvciA9IE5BKSkgKyANCiAgICB0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSkgKyANCiAgICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JleTg1Iiwgc2l6ZSA9IDAuOCkpICsgDQogICAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKSArIA0KICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpKSArIA0KICAgIHRoZW1lKGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSkgKyANCiAgICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsgDQogICAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMC4zLCAxLCAwLjUsIDEpLCAiY20iKSkgKyANCiAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9IG15X2ZvbnQpKSANCn0NCg0KIyBTaW11bGF0ZSBvcmlnaW5hbCB2ZXJzaW9uOiANCg0KZGF0YSAlPiUgDQogIGdncGxvdChhZXMoZGF0ZSwgcGVyY2VudCwgY29sb3IgPSByZXNwb25zZSkpICsgDQogIGdlb21fbGluZShzaXplID0gMS4zLCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArIA0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlfY29sb3JzKSArIA0KICBvdXJfdGhlbWUoKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygzOCwgNTAuNSksIGJyZWFrcyA9IHNlcSgzOCwgNTAsIDIpKSArIA0KICBhbm5vdGF0ZSgidGV4dCIsIGRhdGEkZGF0ZSAlPiUgbWF4KCkgKyA1LCB5ID0gc2VxKDM4LCA1MCwgMiksIGxhYmVsID0gc2VxKDM4LCA1MCwgMiksIA0KICAgICAgICAgICBoanVzdCA9IC0wLjQsIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDMuNiwgZmFtaWx5ID0gbXlfZm9udCwgY29sb3IgPSAiZ3JleTQwIikgKyANCiAgbGFicyh0aXRsZSA9ICJCcmVtb3JzZSIsIA0KICAgICAgIHN1YnRpdGxlID0gIlwiSW4gaGluZHNpZ2gsIGRvIHlvdSB0aGluayBCcml0YWluIHdhcyByaWdodCBvciB3cm9uZ1xuIHRvIHZvdGUgdG8gbGVhdmUgdGhlIEVVP1wiIiwgDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IE5hdGNlbiBTb2NpYWwgUmVzZWFyY2giKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNikpICsNCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmV5MzAiKSkgKyANCiAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImdyZXk0MCIsIHNpemUgPSAxMCwgdmp1c3QgPSAtMikpICsgDQogIGFubm90YXRlKCJ0ZXh0IiwgZGF0YSRkYXRlICU+JSBtYXgoKSAtIDI1MCwgeSA9IDQxLCBsYWJlbCA9ICJSaWdodCIsIHNpemUgPSA0LCBmYW1pbHkgPSBteV9mb250LCBjb2xvciA9ICJncmV5MjAiKSArIA0KICBhbm5vdGF0ZSgidGV4dCIsIGRhdGEkZGF0ZSAlPiUgbWF4KCkgLSAxNjUsIHkgPSA0OC41LCBsYWJlbCA9ICJXcm9uZyIsIHNpemUgPSA0LCBmYW1pbHkgPSBteV9mb250LCBjb2xvciA9ICJncmV5MjAiKQ0KDQoNCmxpYnJhcnkoZ3JpZCkNCmdyaWQucmVjdCh4ID0gMC4wMTUsIHkgPSAwLjkzLCBoanVzdCA9IDEsIHZqdXN0ID0gMCwgZ3AgPSBncGFyKGZpbGwgPSAiI2U1MDAxYyIsIGx3ZCA9IDApKSAgDQpncmlkLnJlY3QoeCA9IDEsIHkgPSAxIC0gMC4wMDUsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLCAgZ3AgPSBncGFyKGZpbGwgPSAiI2U1MDAxYyIsIGx3ZCA9IDApKQ0KDQoNCiMgQmV0dGVyIHZlcnNpb246IA0KDQpkYXRhICU+JSANCiAgZ2dwbG90KGFlcyhkYXRlLCBwZXJjZW50LCBjb2xvciA9IHJlc3BvbnNlKSkgKyANCiAgZ2VvbV9wb2ludChzaG93LmxlZ2VuZCA9IEZBTFNFLCBzaXplID0gMi41LCBhbHBoYSA9IDAuNCkgKyANCiAgZ2VvbV9zbW9vdGgoc2hvdy5sZWdlbmQgPSBGQUxTRSwgc2l6ZSA9IDEuNCwgc2UgPSBGQUxTRSkgKyANCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15X2NvbG9ycykgKyANCiAgb3VyX3RoZW1lKCkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMzgsIDUwLjUpLCBicmVha3MgPSBzZXEoMzgsIDUwLCAyKSkgKyANCiAgYW5ub3RhdGUoInRleHQiLCBkYXRhJGRhdGUgJT4lIG1heCgpICsgNSwgeSA9IHNlcSgzOCwgNTAsIDIpLCBsYWJlbCA9IHNlcSgzOCwgNTAsIDIpLCANCiAgICAgICAgICAgaGp1c3QgPSAtMC40LCB2anVzdCA9IC0wLjUsIHNpemUgPSAzLjYsIGZhbWlseSA9IG15X2ZvbnQsIGNvbG9yID0gImdyZXk0MCIpICsgDQogIGxhYnModGl0bGUgPSAiQnJlbW9yc2UiLCANCiAgICAgICBzdWJ0aXRsZSA9ICJcIkluIGhpbmRzaWdoLCBkbyB5b3UgdGhpbmsgQnJpdGFpbiB3YXMgPGIgc3R5bGU9J2NvbG9yOiMwMGE0ZGMnPnJpZ2h0PC9iPiBvciA8YiBzdHlsZT0nY29sb3I6I2YxNWE0MCc+d3Jvbmc8L2I+IHRvIHZvdGUgdG8gbGVhdmUgdGhlIEVVP1wiIiwgDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IE5hdGNlbiBTb2NpYWwgUmVzZWFyY2giKSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNikpICsNCiAgdGhlbWUocGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfbWFya2Rvd24oY29sb3IgPSAiZ3JleTMwIikpICsgDQogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmV5NDAiLCBzaXplID0gMTAsIHZqdXN0ID0gLTIpKSArIA0KICBhbm5vdGF0ZSgidGV4dCIsIGRhdGEkZGF0ZSAlPiUgbWF4KCkgLSAxNjUsIHkgPSA0MS41LCBsYWJlbCA9ICJSaWdodCIsIHNpemUgPSA0LCBmYW1pbHkgPSBteV9mb250LCBjb2xvciA9IG15X2NvbG9yc1sxXSkgKyANCiAgYW5ub3RhdGUoInRleHQiLCBkYXRhJGRhdGUgJT4lIG1heCgpIC0gMTY1LCB5ID0gNDYuNiwgbGFiZWwgPSAiV3JvbmciLCBzaXplID0gNCwgZmFtaWx5ID0gbXlfZm9udCwgY29sb3IgPSBteV9jb2xvcnNbMl0pDQogIA0KZ3JpZC5yZWN0KHggPSAwLjAxNSwgeSA9IDAuOTMsIGhqdXN0ID0gMSwgdmp1c3QgPSAwLCBncCA9IGdwYXIoZmlsbCA9ICIjZTUwMDFjIiwgbHdkID0gMCkpICANCmdyaWQucmVjdCh4ID0gMSwgeSA9IDEgLSAwLjAwNSwgaGp1c3QgPSAxLCB2anVzdCA9IDAsICBncCA9IGdwYXIoZmlsbCA9ICIjZTUwMDFjIiwgbHdkID0gMCkpDQoNCmBgYA0KDQo=