In this R Notebook we will try out some interactive visualizations and some dynamic visualizations that are possible using R.

library(pacman)
p_load(tidyverse, purrr, gapminder, plotly, trelliscopejs, echarts4r, echarts4r.assets, gganimate)

Using the gapminder dataset.

gapminder

Plot by continent.

gapm <- gapminder %>% group_by(continent, country) %>%
  ggplot(aes(x = gdpPercap, y = lifeExp, 
             size = pop, colour = country )) +
  geom_point() +
  scale_x_log10() + 
  facet_wrap(~continent) +
  theme(legend.position = "none")
gapm

ggplotly(gapm)
`group_by_()` is deprecated as of dplyr 0.7.0.
Please use `group_by()` instead.
See vignette('programming') for more help
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.

Using facet_trelliscope can be used to create an interactive collection of plots. Can you image making a million plots?

gapminder %>% ggplot(aes(x = log10(gdpPercap), y = lifeExp, 
                         color = country, size = pop)) +  
  geom_point() + 
  theme_bw() +
  theme(legend.position = "none") +
  facet_trelliscope(~ continent, 
                    nrow = 2, ncol = 3)
using data from the first layer
gapm_trel <- gapminder %>% 
  ggplot(aes(x = log10(gdpPercap), y = lifeExp,
             color = country, size = pop)) +
  geom_point() +
  theme_bw() +
  theme(legend.position = "none") +
  facet_trelliscope(~ country + continent, 
                    nrow = 2, ncol = 3) 

gapm_trel
using data from the first layer

Try echarts.

titles <- map(unique(gapminder$year), function(x){
  list(
    text = "Gapminder",
    subtext = x,
    left = "center"
  )
})

gapminder %>% 
  group_by(year) %>% 
  e_charts(gdpPercap, timeline = TRUE) %>% 
  e_scatter(lifeExp, pop, country) %>% 
  e_y_axis(min = 20, max = 85) %>% 
  e_x_axis(type = "log", min = 100, max = 100000) %>% 
  e_timeline_serie(title = titles) %>% 
  e_tooltip() %>% 
  e_timeline_opts(
    show = TRUE,
    orient = "vertical",
    symbol = "none",
    right = 0,
    top = 20,
    bottom = 20,
    height = NULL,
    width = 45,
    inverse = TRUE,
    playInterval = 1000,
    autoPlay  = TRUE,
    controlStyle = list(
      showNextBtn = FALSE,
      showPrevBtn = FALSE
    ),
    label = list(
      fontSize = 8
    )
  ) %>% 
  e_theme("dark")
gapminder %>% ggplot(aes(x = gdpPercap, y = lifeExp, 
                         size = pop, colour = country)) +
  geom_point(alpha = 0.7, show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  scale_x_log10() +
  facet_wrap(~ continent)

Try gganimate.

gapminder %>% ggplot(aes(x = gdpPercap, y = lifeExp, 
                         size = pop, colour = country)) +
  geom_point(alpha = 0.7, show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  scale_x_log10() +
  facet_wrap(~ continent) +
  # Here comes the gganimate specific bits
  labs(title = 'Year: {frame_time}', 
       x = 'GDP per capita', y = 'life expectancy') +
  transition_time(year) +
  ease_aes('cubic-in-out')
goo <- gapminder %>% ggplot(aes(x = gdpPercap, y = lifeExp, 
                         size = pop, colour = country)) +
  geom_point(alpha = 0.7, show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  scale_x_log10() +
  facet_wrap(~continent) +
  # Here comes the gganimate specific bits
  labs(title = 'Year: {frame_time}', 
       x = 'GDP per capita', y = 'life expectancy') +
  transition_time(year) +
  ease_aes('cubic-in-out')

anim_save("goo.gif", goo)

Try echarts.

airports <- read.csv(
  paste0("https://raw.githubusercontent.com/plotly/datasets/",
         "master/2011_february_us_airport_traffic.csv")
)

airports %>% 
  e_charts(long) %>% 
  e_globe(
    environment = ea_asset("starfield"),
    base_texture = ea_asset("world"), 
    globeOuterRadius = 100
  ) %>% 
  e_scatter_3d(lat, cnt, coord_system = "globe", blendMode = 'lighter') %>% 
  e_visual_map(inRange = list(symbolSize = c(1, 10)))
# download
flights <- jsonlite::fromJSON("https://raw.githubusercontent.com/apache/incubator-echarts/master/test/data/flight.json")



# airports
airports <- as.data.frame(flights$airports)
names(airports) <- flights$airportsFields

airports <- airports %>% 
  select(name, longitude, latitude) %>% 
  tibble::rownames_to_column("ID") %>% 
  mutate(ID = as.integer(paste0(ID)))

# routes
routes <- as.data.frame(flights$routes)
names(routes) <- c("ID", "from", "to")

# airlines
airlines <- as.data.frame(flights$airlines) %>% 
  tibble::rownames_to_column("ID") %>% 
  mutate(ID = as.integer(paste(ID))) %>% 
  select(ID, airline = V1, country = V2) %>%
  filter(country == "United States")

# bind
data <- routes %>% 
  inner_join(airports, by = c("from" = "ID")) %>% 
  inner_join(airports, by = c("to" = "ID"), suffix = c(".start", ".end")) %>%
  inner_join(airlines, by = "ID") %>% 
  select(airline, longitude.start, latitude.start, longitude.end, latitude.end) 

# initialise plot  
data %>%
  group_by(airline) %>% 
  e_charts() %>% 
  e_globe(
    base_texture = ea_asset("world dark"),
    environment = ea_asset("starfield"),
    displacementScale = 0.1,
    displacementQuality = "high",
    shading = "realistic",
    realisticMaterial = list(
      roughness = .2,
      metalness = 0
    ),
    postEffect = list(
      enable = TRUE,
      depthOfField = list(
        enable = FALSE
      )
    ),
    temporalSuperSampling = list(
      enable = TRUE
    ),
    light = list(
      ambient = list(
        intensity = 1
      ),
      main = list(
        intensity = .1,
        shadow = FALSE
      )
    ),
    viewControl = list(autoRotate = FALSE)
  ) %>% 
  e_legend(
    selectedMode = "single", 
    left = "left",
    textStyle = list(color = "#fff"),
    orient = "vertical"
  ) %>% 
  e_lines_3d(
    longitude.start, latitude.start, longitude.end, latitude.end, 
    coord_system = "globe", 
    effect = list(
      show = TRUE,
      trailWidth = 2,
      trailLength = 0.15,
      trailOpacity = 1,
      trailColor = 'rgb(30, 30, 60)'
    ),
    lineStyle = list(opacity = 0.1, widh = 0.5, color = 'rgb(50, 50, 150)')
  )

NA
LS0tCnRpdGxlOiAiSW50ZXJhY3RpdmUgYW5kIER5bmFtaWMgQW5pbWF0aW9uIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpJbiB0aGlzIFIgTm90ZWJvb2sgd2Ugd2lsbCB0cnkgb3V0IHNvbWUgaW50ZXJhY3RpdmUgdmlzdWFsaXphdGlvbnMgYW5kIHNvbWUgZHluYW1pYyB2aXN1YWxpemF0aW9ucyB0aGF0IGFyZSBwb3NzaWJsZSB1c2luZyBSLgoKYGBge3J9CmxpYnJhcnkocGFjbWFuKQpwX2xvYWQodGlkeXZlcnNlLCBwdXJyciwgZ2FwbWluZGVyLCBwbG90bHksIHRyZWxsaXNjb3BlanMsIGVjaGFydHM0ciwgZWNoYXJ0czRyLmFzc2V0cywgZ2dhbmltYXRlKQpgYGAKClVzaW5nIHRoZSBnYXBtaW5kZXIgZGF0YXNldC4KCmBgYHtyfQpnYXBtaW5kZXIKYGBgCgpQbG90IGJ5IGNvbnRpbmVudC4KCmBgYHtyfQpnYXBtIDwtIGdhcG1pbmRlciAlPiUgZ3JvdXBfYnkoY29udGluZW50LCBjb3VudHJ5KSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBnZHBQZXJjYXAsIHkgPSBsaWZlRXhwLCAKICAgICAgICAgICAgIHNpemUgPSBwb3AsIGNvbG91ciA9IGNvdW50cnkgKSkgKwogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfeF9sb2cxMCgpICsgCiAgZmFjZXRfd3JhcCh+Y29udGluZW50KSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpnYXBtCmBgYApgYGB7cn0KZ2dwbG90bHkoZ2FwbSkKYGBgCgpVc2luZyBmYWNldF90cmVsbGlzY29wZSBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYW4gaW50ZXJhY3RpdmUgY29sbGVjdGlvbiBvZiBwbG90cy4gIENhbiB5b3UgaW1hZ2UgbWFraW5nIGEgbWlsbGlvbiBwbG90cz8KCmBgYHtyfQpnYXBtaW5kZXIgJT4lIGdncGxvdChhZXMoeCA9IGxvZzEwKGdkcFBlcmNhcCksIHkgPSBsaWZlRXhwLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gY291bnRyeSwgc2l6ZSA9IHBvcCkpICsgIAogIGdlb21fcG9pbnQoKSArIAogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGZhY2V0X3RyZWxsaXNjb3BlKH4gY29udGluZW50LCAKICAgICAgICAgICAgICAgICAgICBucm93ID0gMiwgbmNvbCA9IDMpCmBgYAoKYGBge3J9CmdhcG1fdHJlbCA8LSBnYXBtaW5kZXIgJT4lIAogIGdncGxvdChhZXMoeCA9IGxvZzEwKGdkcFBlcmNhcCksIHkgPSBsaWZlRXhwLAogICAgICAgICAgICAgY29sb3IgPSBjb3VudHJ5LCBzaXplID0gcG9wKSkgKwogIGdlb21fcG9pbnQoKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgZmFjZXRfdHJlbGxpc2NvcGUofiBjb3VudHJ5ICsgY29udGluZW50LCAKICAgICAgICAgICAgICAgICAgICBucm93ID0gMiwgbmNvbCA9IDMpIAoKZ2FwbV90cmVsCmBgYAoKVHJ5IGVjaGFydHMuCgpgYGB7cn0KdGl0bGVzIDwtIG1hcCh1bmlxdWUoZ2FwbWluZGVyJHllYXIpLCBmdW5jdGlvbih4KXsKICBsaXN0KAogICAgdGV4dCA9ICJHYXBtaW5kZXIiLAogICAgc3VidGV4dCA9IHgsCiAgICBsZWZ0ID0gImNlbnRlciIKICApCn0pCgpnYXBtaW5kZXIgJT4lIAogIGdyb3VwX2J5KHllYXIpICU+JSAKICBlX2NoYXJ0cyhnZHBQZXJjYXAsIHRpbWVsaW5lID0gVFJVRSkgJT4lIAogIGVfc2NhdHRlcihsaWZlRXhwLCBwb3AsIGNvdW50cnkpICU+JSAKICBlX3lfYXhpcyhtaW4gPSAyMCwgbWF4ID0gODUpICU+JSAKICBlX3hfYXhpcyh0eXBlID0gImxvZyIsIG1pbiA9IDEwMCwgbWF4ID0gMTAwMDAwKSAlPiUgCiAgZV90aW1lbGluZV9zZXJpZSh0aXRsZSA9IHRpdGxlcykgJT4lIAogIGVfdG9vbHRpcCgpICU+JSAKICBlX3RpbWVsaW5lX29wdHMoCiAgICBzaG93ID0gVFJVRSwKICAgIG9yaWVudCA9ICJ2ZXJ0aWNhbCIsCiAgICBzeW1ib2wgPSAibm9uZSIsCiAgICByaWdodCA9IDAsCiAgICB0b3AgPSAyMCwKICAgIGJvdHRvbSA9IDIwLAogICAgaGVpZ2h0ID0gTlVMTCwKICAgIHdpZHRoID0gNDUsCiAgICBpbnZlcnNlID0gVFJVRSwKICAgIHBsYXlJbnRlcnZhbCA9IDEwMDAsCiAgICBhdXRvUGxheSAgPSBUUlVFLAogICAgY29udHJvbFN0eWxlID0gbGlzdCgKICAgICAgc2hvd05leHRCdG4gPSBGQUxTRSwKICAgICAgc2hvd1ByZXZCdG4gPSBGQUxTRQogICAgKSwKICAgIGxhYmVsID0gbGlzdCgKICAgICAgZm9udFNpemUgPSA4CiAgICApCiAgKSAlPiUgCiAgZV90aGVtZSgiZGFyayIpCmBgYAoKCgpgYGB7cn0KZ2FwbWluZGVyICU+JSBnZ3Bsb3QoYWVzKHggPSBnZHBQZXJjYXAsIHkgPSBsaWZlRXhwLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSBwb3AsIGNvbG91ciA9IGNvdW50cnkpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNywgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gY291bnRyeV9jb2xvcnMpICsKICBzY2FsZV9zaXplKHJhbmdlID0gYygyLCAxMikpICsKICBzY2FsZV94X2xvZzEwKCkgKwogIGZhY2V0X3dyYXAofiBjb250aW5lbnQpCmBgYAoKVHJ5IGdnYW5pbWF0ZS4KCmBgYHtyfQpnYXBtaW5kZXIgJT4lIGdncGxvdChhZXMoeCA9IGdkcFBlcmNhcCwgeSA9IGxpZmVFeHAsIAogICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IHBvcCwgY29sb3VyID0gY291bnRyeSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC43LCBzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjb3VudHJ5X2NvbG9ycykgKwogIHNjYWxlX3NpemUocmFuZ2UgPSBjKDIsIDEyKSkgKwogIHNjYWxlX3hfbG9nMTAoKSArCiAgZmFjZXRfd3JhcCh+IGNvbnRpbmVudCkgKwogICMgSGVyZSBjb21lcyB0aGUgZ2dhbmltYXRlIHNwZWNpZmljIGJpdHMKICBsYWJzKHRpdGxlID0gJ1llYXI6IHtmcmFtZV90aW1lfScsIAogICAgICAgeCA9ICdHRFAgcGVyIGNhcGl0YScsIHkgPSAnbGlmZSBleHBlY3RhbmN5JykgKwogIHRyYW5zaXRpb25fdGltZSh5ZWFyKSArCiAgZWFzZV9hZXMoJ2N1YmljLWluLW91dCcpCmBgYAoKCgoKYGBge3IgZXZhbD1GQUxTRX0KZ29vIDwtIGdhcG1pbmRlciAlPiUgZ2dwbG90KGFlcyh4ID0gZ2RwUGVyY2FwLCB5ID0gbGlmZUV4cCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gcG9wLCBjb2xvdXIgPSBjb3VudHJ5KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjcsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGNvdW50cnlfY29sb3JzKSArCiAgc2NhbGVfc2l6ZShyYW5nZSA9IGMoMiwgMTIpKSArCiAgc2NhbGVfeF9sb2cxMCgpICsKICBmYWNldF93cmFwKH5jb250aW5lbnQpICsKICAjIEhlcmUgY29tZXMgdGhlIGdnYW5pbWF0ZSBzcGVjaWZpYyBiaXRzCiAgbGFicyh0aXRsZSA9ICdZZWFyOiB7ZnJhbWVfdGltZX0nLCAKICAgICAgIHggPSAnR0RQIHBlciBjYXBpdGEnLCB5ID0gJ2xpZmUgZXhwZWN0YW5jeScpICsKICB0cmFuc2l0aW9uX3RpbWUoeWVhcikgKwogIGVhc2VfYWVzKCdjdWJpYy1pbi1vdXQnKQoKYW5pbV9zYXZlKCJnb28uZ2lmIiwgZ29vKQpgYGAKCiFbXShnb28uZ2lmKQoKVHJ5IGVjaGFydHMuCgpgYGB7cn0KYWlycG9ydHMgPC0gcmVhZC5jc3YoCiAgcGFzdGUwKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcGxvdGx5L2RhdGFzZXRzLyIsCiAgICAgICAgICJtYXN0ZXIvMjAxMV9mZWJydWFyeV91c19haXJwb3J0X3RyYWZmaWMuY3N2IikKKQoKYWlycG9ydHMgJT4lIAogIGVfY2hhcnRzKGxvbmcpICU+JSAKICBlX2dsb2JlKAogICAgZW52aXJvbm1lbnQgPSBlYV9hc3NldCgic3RhcmZpZWxkIiksCiAgICBiYXNlX3RleHR1cmUgPSBlYV9hc3NldCgid29ybGQiKSwgCiAgICBnbG9iZU91dGVyUmFkaXVzID0gMTAwCiAgKSAlPiUgCiAgZV9zY2F0dGVyXzNkKGxhdCwgY250LCBjb29yZF9zeXN0ZW0gPSAiZ2xvYmUiLCBibGVuZE1vZGUgPSAnbGlnaHRlcicpICU+JSAKICBlX3Zpc3VhbF9tYXAoaW5SYW5nZSA9IGxpc3Qoc3ltYm9sU2l6ZSA9IGMoMSwgMTApKSkKYGBgCgoKYGBge3J9CiMgZG93bmxvYWQKZmxpZ2h0cyA8LSBqc29ubGl0ZTo6ZnJvbUpTT04oImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9hcGFjaGUvaW5jdWJhdG9yLWVjaGFydHMvbWFzdGVyL3Rlc3QvZGF0YS9mbGlnaHQuanNvbiIpCgoKCiMgYWlycG9ydHMKYWlycG9ydHMgPC0gYXMuZGF0YS5mcmFtZShmbGlnaHRzJGFpcnBvcnRzKQpuYW1lcyhhaXJwb3J0cykgPC0gZmxpZ2h0cyRhaXJwb3J0c0ZpZWxkcwoKYWlycG9ydHMgPC0gYWlycG9ydHMgJT4lIAogIHNlbGVjdChuYW1lLCBsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUgCiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIklEIikgJT4lIAogIG11dGF0ZShJRCA9IGFzLmludGVnZXIocGFzdGUwKElEKSkpCgojIHJvdXRlcwpyb3V0ZXMgPC0gYXMuZGF0YS5mcmFtZShmbGlnaHRzJHJvdXRlcykKbmFtZXMocm91dGVzKSA8LSBjKCJJRCIsICJmcm9tIiwgInRvIikKCiMgYWlybGluZXMKYWlybGluZXMgPC0gYXMuZGF0YS5mcmFtZShmbGlnaHRzJGFpcmxpbmVzKSAlPiUgCiAgdGliYmxlOjpyb3duYW1lc190b19jb2x1bW4oIklEIikgJT4lIAogIG11dGF0ZShJRCA9IGFzLmludGVnZXIocGFzdGUoSUQpKSkgJT4lIAogIHNlbGVjdChJRCwgYWlybGluZSA9IFYxLCBjb3VudHJ5ID0gVjIpICU+JQogIGZpbHRlcihjb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIikKCiMgYmluZApkYXRhIDwtIHJvdXRlcyAlPiUgCiAgaW5uZXJfam9pbihhaXJwb3J0cywgYnkgPSBjKCJmcm9tIiA9ICJJRCIpKSAlPiUgCiAgaW5uZXJfam9pbihhaXJwb3J0cywgYnkgPSBjKCJ0byIgPSAiSUQiKSwgc3VmZml4ID0gYygiLnN0YXJ0IiwgIi5lbmQiKSkgJT4lCiAgaW5uZXJfam9pbihhaXJsaW5lcywgYnkgPSAiSUQiKSAlPiUgCiAgc2VsZWN0KGFpcmxpbmUsIGxvbmdpdHVkZS5zdGFydCwgbGF0aXR1ZGUuc3RhcnQsIGxvbmdpdHVkZS5lbmQsIGxhdGl0dWRlLmVuZCkgCgojIGluaXRpYWxpc2UgcGxvdCAgCmRhdGEgJT4lCiAgZ3JvdXBfYnkoYWlybGluZSkgJT4lIAogIGVfY2hhcnRzKCkgJT4lIAogIGVfZ2xvYmUoCiAgICBiYXNlX3RleHR1cmUgPSBlYV9hc3NldCgid29ybGQgZGFyayIpLAogICAgZW52aXJvbm1lbnQgPSBlYV9hc3NldCgic3RhcmZpZWxkIiksCiAgICBkaXNwbGFjZW1lbnRTY2FsZSA9IDAuMSwKICAgIGRpc3BsYWNlbWVudFF1YWxpdHkgPSAiaGlnaCIsCiAgICBzaGFkaW5nID0gInJlYWxpc3RpYyIsCiAgICByZWFsaXN0aWNNYXRlcmlhbCA9IGxpc3QoCiAgICAgIHJvdWdobmVzcyA9IC4yLAogICAgICBtZXRhbG5lc3MgPSAwCiAgICApLAogICAgcG9zdEVmZmVjdCA9IGxpc3QoCiAgICAgIGVuYWJsZSA9IFRSVUUsCiAgICAgIGRlcHRoT2ZGaWVsZCA9IGxpc3QoCiAgICAgICAgZW5hYmxlID0gRkFMU0UKICAgICAgKQogICAgKSwKICAgIHRlbXBvcmFsU3VwZXJTYW1wbGluZyA9IGxpc3QoCiAgICAgIGVuYWJsZSA9IFRSVUUKICAgICksCiAgICBsaWdodCA9IGxpc3QoCiAgICAgIGFtYmllbnQgPSBsaXN0KAogICAgICAgIGludGVuc2l0eSA9IDEKICAgICAgKSwKICAgICAgbWFpbiA9IGxpc3QoCiAgICAgICAgaW50ZW5zaXR5ID0gLjEsCiAgICAgICAgc2hhZG93ID0gRkFMU0UKICAgICAgKQogICAgKSwKICAgIHZpZXdDb250cm9sID0gbGlzdChhdXRvUm90YXRlID0gRkFMU0UpCiAgKSAlPiUgCiAgZV9sZWdlbmQoCiAgICBzZWxlY3RlZE1vZGUgPSAic2luZ2xlIiwgCiAgICBsZWZ0ID0gImxlZnQiLAogICAgdGV4dFN0eWxlID0gbGlzdChjb2xvciA9ICIjZmZmIiksCiAgICBvcmllbnQgPSAidmVydGljYWwiCiAgKSAlPiUgCiAgZV9saW5lc18zZCgKICAgIGxvbmdpdHVkZS5zdGFydCwgbGF0aXR1ZGUuc3RhcnQsIGxvbmdpdHVkZS5lbmQsIGxhdGl0dWRlLmVuZCwgCiAgICBjb29yZF9zeXN0ZW0gPSAiZ2xvYmUiLCAKICAgIGVmZmVjdCA9IGxpc3QoCiAgICAgIHNob3cgPSBUUlVFLAogICAgICB0cmFpbFdpZHRoID0gMiwKICAgICAgdHJhaWxMZW5ndGggPSAwLjE1LAogICAgICB0cmFpbE9wYWNpdHkgPSAxLAogICAgICB0cmFpbENvbG9yID0gJ3JnYigzMCwgMzAsIDYwKScKICAgICksCiAgICBsaW5lU3R5bGUgPSBsaXN0KG9wYWNpdHkgPSAwLjEsIHdpZGggPSAwLjUsIGNvbG9yID0gJ3JnYig1MCwgNTAsIDE1MCknKQogICkKCmBgYAoK