library(treemap)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ──────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ──
✓ ggplot2 3.3.3     ✓ purrr   0.3.4
✓ tibble  3.1.0     ✓ dplyr   1.0.4
✓ tidyr   1.1.2     ✓ stringr 1.4.0
✓ readr   1.4.0     ✓ forcats 0.5.0
── Conflicts ─────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x tidyr::expand() masks reshape::expand()
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
x dplyr::rename() masks reshape::rename()
library(RColorBrewer)
data <- read.csv("http://datasets.flowingdata.com/post-data.txt")
head(data)

Create treemap

treemap(data, index="category", vSize="views", 
                vColor="comments", type="value", 
                palette="RdYlBu")

treemap(data, index="category", vSize="views", 
        vColor="comments", type="manual", 
        palette="RdYlBu")

Use RColorBrewer to change the palette to RdYlBu

treemap(data, index="category", vSize="views", 
        vColor="comments", type="manual", 
        palette="RdYlBu")

Heatmaps

Load nba data from Yau’s wbsite

Create a cool-color heatmap of the nba 2008 data

nba <- nba[order(nba$PTS),]
row.names(nba) <- nba$Name
nba <- nba[,2:19]
nba_matrix <- data.matrix(nba)
nba_heatmap <- heatmap(nba_matrix, Rowv=NA, Colv=NA, 
                       col = cm.colors(256), scale="column", margins=c(5,10),
                       xlab = "NBA Player Stats",
                       ylab = "NBA Players",
                       main = "NBA Payer Stats in 2008")

Change to heat colors

Use the viridis colors

library(viridis)
Loading required package: viridisLite
nba_heatmap <- heatmap(nba_matrix, Rowv=NA, col = viridis(25, direction = -1), 
                       scale="column", margins=c(5,10),
                        xlab = "NBA Player Stats",
                       ylab = "NBA Players",
                       main = "NBA Payer Stats in 2008")

Use the dataset NYCFlights13 to create a heatmap that explores Late Arrivals

library(nycflights13)
library(RColorBrewer)
#view(flights)
flights_nona <- na.omit (flights)      # remove observations with NA values
delays <- flights_nona %>%             # create a delays dataframe by:
  group_by (dest) %>%                  # grouping by point of destination
  summarize (count = n(),              # create these variables: number of flights to each destination,
             dist = mean (distance),   # mean distance flown to each destination,
             delay = mean (arr_delay), # mean delay of arrival to each destination,
             delaycost= mean(count*delay/distance)) # delay cost index defined as:
                     #  [(number of flights)*delay/distance] for a destination

top100 <- delays %>%                     # select the top 100 largest arrival delays
  arrange(desc(delaycost)) %>%                              
  head(100)
row.names(top100) <- top100$dest 
Setting row names on a tibble is deprecated.
delays_mat <- data.matrix(top100)     # convert delays dataframe to a matrix  (required by heatmap)
delays_matrix <- delays_mat[,2:5] # remove redundant column of destination airport codes
varcols = setNames(colorRampPalette(brewer.pal(nrow(delays_matrix), "YlGnBu"))(nrow(delays_matrix)), rownames(delays_matrix))   # parameter for RowSideColors
n too large, allowed maximum for palette YlGnBu is 9
Returning the palette you asked for with that many colors
heatmap(delays_matrix, Rowv = NA, 
        Colv = NA, 
        col= colorRampPalette(brewer.pal(nrow(delays_matrix), "YlGnBu"))(nrow(delays_matrix)), 
        s=0.6, v=1, scale="column", 
        margins=c(7,10), 
        main = "Cost of Late Arrivals", 
        xlab =" Flight Characteristics", 
        ylab="Arrival Airport", 
        labCol = c("Flights","Distance","Delay","Cost Index"), 
        cexCol=1, cexRow =1, RowSideColors = varcols)
layout: widths =  0.05 0.2 4 , heights =  0.25 4 ; lmat=
     [,1] [,2] [,3]
[1,]    0    0    4
[2,]    3    1    2

Cost index is a measure of how much the cost to fly to an airport increases due to frequent delays of arrival. It is roughly proportional to flights and inversely proportional to distance because delays affect shorter flights more than longer ones, and the profit per seat increases with distance. The variance in delays is due to airport congestion and regional weather.

Streamgraphs

Streamgraphs display the changes in data over time of different categories. The size of each individual stream shape is proportional to the values in each category. Colors can be used to distinguish streams or to represent an additional dimension in the data. They are well-suited to displaying high- volume datasets. The downside to streamgraphs is that they can be difficult to read, be cluttered, and the categories with smaller values may be drowned out. It is also not possible to read the exact values visualized from the plot.

devtools::install_github("hrbrmstr/streamgraph")
Skipping install of 'streamgraph' from a github remote, the SHA1 (76f7173e) has not changed since last install.
  Use `force = TRUE` to force installation
library(dplyr)
library(streamgraph)
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
library(babynames)

Trivial streamgraph using simulated names over time

# Create data:
year=rep(seq(1990,2016) , each=10)
name=rep(letters[1:10] , 27)
value=sample( seq(0,1,0.0001) , length(year))
data=data.frame(year, name, value)
# Basic stream graph: just give the 3 arguments
streamgraph(data, key="name", value="value", date="year")
streamgraph_html returned an object of class `list` instead of a `shiny.tag`.streamgraph_html returned an object of class `list` instead of a `shiny.tag`.

lets look at the babynames dataset:

ncol(babynames)
[1] 5
str(babynames)
tibble [1,924,665 × 5] (S3: tbl_df/tbl/data.frame)
 $ year: num [1:1924665] 1880 1880 1880 1880 1880 1880 1880 1880 1880 1880 ...
 $ sex : chr [1:1924665] "F" "F" "F" "F" ...
 $ name: chr [1:1924665] "Mary" "Anna" "Emma" "Elizabeth" ...
 $ n   : int [1:1924665] 7065 2604 2003 1939 1746 1578 1472 1414 1320 1288 ...
 $ prop: num [1:1924665] 0.0724 0.0267 0.0205 0.0199 0.0179 ...

Babynames streamgraph

babynames %>%
  filter(grepl("^Kr", name)) %>%
  group_by(year, name) %>%
  tally(wt=n) %>%
  streamgraph("name", "n", "year")
streamgraph_html returned an object of class `list` instead of a `shiny.tag`.streamgraph_html returned an object of class `list` instead of a `shiny.tag`.
# Streamgraphing Commercial Real Estate Transaction Volume by Asset Class Since 2001

dat <- read.csv("http://asbcllc.com/blog/2015/february/cre_stream_graph_test/data/cre_transaction-data.csv")

dat %>%
  streamgraph("asset_class", "volume_billions", "year", interpolate="cardinal") %>%
  sg_axis_x(1, "year", "%Y") %>%
  sg_fill_brewer("PuOr") 
streamgraph_html returned an object of class `list` instead of a `shiny.tag`.streamgraph_html returned an object of class `list` instead of a `shiny.tag`.

Alluvials

library(alluvial)

Examining data from the Refugees dataset

Create the alluvial to show UNHCR-recognised refugees in the top 10

countries from 2003 - 2013

set.seed(39) # for nice colours
cols <- hsv(h = sample(1:10/10), s = sample(3:12)/15, v = sample(3:12)/15) # creates the vector of 10 colors

alluvial_ts(Refugees, wave = .3, ygap = 5, col = cols, plotdir = 'centred', alpha=.9,
            grid = TRUE, grid.lwd = 5, xmargin = 0.2, lab.cex = .7, xlab = '',
            ylab = '', border = NA, axis.cex = .8, leg.cex = .7,
            leg.col='white', 
            title = "UNHCR-recognised refugees\nTop 10 countries (2003-2013)\n")

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkodHJlZW1hcCkKbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKYGBge3J9CmxpYnJhcnkoUkNvbG9yQnJld2VyKQpkYXRhIDwtIHJlYWQuY3N2KCJodHRwOi8vZGF0YXNldHMuZmxvd2luZ2RhdGEuY29tL3Bvc3QtZGF0YS50eHQiKQpoZWFkKGRhdGEpCmBgYAoKIyBDcmVhdGUgdHJlZW1hcAoKYGBge3J9CnRyZWVtYXAoZGF0YSwgaW5kZXg9ImNhdGVnb3J5IiwgdlNpemU9InZpZXdzIiwgCiAgICAgICAgICAgICAgICB2Q29sb3I9ImNvbW1lbnRzIiwgdHlwZT0idmFsdWUiLCAKICAgICAgICAgICAgICAgIHBhbGV0dGU9IlJkWWxCdSIpCmBgYAoKCmBgYHtyfQp0cmVlbWFwKGRhdGEsIGluZGV4PSJjYXRlZ29yeSIsIHZTaXplPSJ2aWV3cyIsIAogICAgICAgIHZDb2xvcj0iY29tbWVudHMiLCB0eXBlPSJtYW51YWwiLCAKICAgICAgICBwYWxldHRlPSJSZFlsQnUiKQpgYGAKCiMgVXNlIFJDb2xvckJyZXdlciB0byBjaGFuZ2UgdGhlIHBhbGV0dGUgdG8gUmRZbEJ1CgpgYGB7cn0KdHJlZW1hcChkYXRhLCBpbmRleD0iY2F0ZWdvcnkiLCB2U2l6ZT0idmlld3MiLCAKICAgICAgICB2Q29sb3I9ImNvbW1lbnRzIiwgdHlwZT0ibWFudWFsIiwgCiAgICAgICAgcGFsZXR0ZT0iUmRZbEJ1IikKYGBgCgojIEhlYXRtYXBzCgojIExvYWQgbmJhIGRhdGEgZnJvbSBZYXUncyB3YnNpdGUKCmBgYHtyfQojIEhvdyB0byBtYWtlIGEgaGVhdG1hcApuYmEgPC0gcmVhZC5jc3YoImh0dHA6Ly9kYXRhc2V0cy5mbG93aW5nZGF0YS5jb20vcHBnMjAwOC5jc3YiKQpuYmEKYGBgCgojIENyZWF0ZSBhIGNvb2wtY29sb3IgaGVhdG1hcCBvZiB0aGUgbmJhIDIwMDggZGF0YQoKYGBge3J9Cm5iYSA8LSBuYmFbb3JkZXIobmJhJFBUUyksXQpyb3cubmFtZXMobmJhKSA8LSBuYmEkTmFtZQpuYmEgPC0gbmJhWywyOjE5XQpuYmFfbWF0cml4IDwtIGRhdGEubWF0cml4KG5iYSkKbmJhX2hlYXRtYXAgPC0gaGVhdG1hcChuYmFfbWF0cml4LCBSb3d2PU5BLCBDb2x2PU5BLCAKICAgICAgICAgICAgICAgICAgICAgICBjb2wgPSBjbS5jb2xvcnMoMjU2KSwgc2NhbGU9ImNvbHVtbiIsIG1hcmdpbnM9Yyg1LDEwKSwKICAgICAgICAgICAgICAgICAgICAgICB4bGFiID0gIk5CQSBQbGF5ZXIgU3RhdHMiLAogICAgICAgICAgICAgICAgICAgICAgIHlsYWIgPSAiTkJBIFBsYXllcnMiLAogICAgICAgICAgICAgICAgICAgICAgIG1haW4gPSAiTkJBIFBheWVyIFN0YXRzIGluIDIwMDgiKQpgYGAKCiMjIENoYW5nZSB0byBoZWF0IGNvbG9ycwoKYGBge3J9Cm5iYV9oZWF0bWFwIDwtIGhlYXRtYXAobmJhX21hdHJpeCwgUm93dj1OQSwgQ29sdj1OQSwgY29sID0gaGVhdC5jb2xvcnMoMjU2KSwgCiAgICAgICAgICAgICAgICAgICAgICAgc2NhbGU9ImNvbHVtbiIsIG1hcmdpbnM9Yyg1LDEwKSwKICAgICAgICAgICAgICAgICAgICAgICAgeGxhYiA9ICJOQkEgUGxheWVyIFN0YXRzIiwKICAgICAgICAgICAgICAgICAgICAgICB5bGFiID0gIk5CQSBQbGF5ZXJzIiwKICAgICAgICAgICAgICAgICAgICAgICBtYWluID0gIk5CQSBQYXllciBTdGF0cyBpbiAyMDA4IikKYGBgCgojIyBVc2UgdGhlIHZpcmlkaXMgY29sb3JzCgpgYGB7cn0KbGlicmFyeSh2aXJpZGlzKQpgYGAKCmBgYHtyfQpuYmFfaGVhdG1hcCA8LSBoZWF0bWFwKG5iYV9tYXRyaXgsIFJvd3Y9TkEsIGNvbCA9IHZpcmlkaXMoMjUsIGRpcmVjdGlvbiA9IC0xKSwgCiAgICAgICAgICAgICAgICAgICAgICAgc2NhbGU9ImNvbHVtbiIsIG1hcmdpbnM9Yyg1LDEwKSwKICAgICAgICAgICAgICAgICAgICAgICAgeGxhYiA9ICJOQkEgUGxheWVyIFN0YXRzIiwKICAgICAgICAgICAgICAgICAgICAgICB5bGFiID0gIk5CQSBQbGF5ZXJzIiwKICAgICAgICAgICAgICAgICAgICAgICBtYWluID0gIk5CQSBQYXllciBTdGF0cyBpbiAyMDA4IikKYGBgCiMjIFVzZSB0aGUgZGF0YXNldCBOWUNGbGlnaHRzMTMgdG8gY3JlYXRlIGEgaGVhdG1hcCB0aGF0IGV4cGxvcmVzIExhdGUgQXJyaXZhbHMKCmBgYHtyfQpsaWJyYXJ5KG55Y2ZsaWdodHMxMykKbGlicmFyeShSQ29sb3JCcmV3ZXIpCiN2aWV3KGZsaWdodHMpCmBgYAoKYGBge3J9CmZsaWdodHNfbm9uYSA8LSBuYS5vbWl0IChmbGlnaHRzKSAgICAgICMgcmVtb3ZlIG9ic2VydmF0aW9ucyB3aXRoIE5BIHZhbHVlcwpkZWxheXMgPC0gZmxpZ2h0c19ub25hICU+JSAgICAgICAgICAgICAjIGNyZWF0ZSBhIGRlbGF5cyBkYXRhZnJhbWUgYnk6CiAgZ3JvdXBfYnkgKGRlc3QpICU+JSAgICAgICAgICAgICAgICAgICMgZ3JvdXBpbmcgYnkgcG9pbnQgb2YgZGVzdGluYXRpb24KICBzdW1tYXJpemUgKGNvdW50ID0gbigpLCAgICAgICAgICAgICAgIyBjcmVhdGUgdGhlc2UgdmFyaWFibGVzOiBudW1iZXIgb2YgZmxpZ2h0cyB0byBlYWNoIGRlc3RpbmF0aW9uLAogICAgICAgICAgICAgZGlzdCA9IG1lYW4gKGRpc3RhbmNlKSwgICAjIG1lYW4gZGlzdGFuY2UgZmxvd24gdG8gZWFjaCBkZXN0aW5hdGlvbiwKICAgICAgICAgICAgIGRlbGF5ID0gbWVhbiAoYXJyX2RlbGF5KSwgIyBtZWFuIGRlbGF5IG9mIGFycml2YWwgdG8gZWFjaCBkZXN0aW5hdGlvbiwKICAgICAgICAgICAgIGRlbGF5Y29zdD0gbWVhbihjb3VudCpkZWxheS9kaXN0YW5jZSkpICMgZGVsYXkgY29zdCBpbmRleCBkZWZpbmVkIGFzOgogICAgICAgICAgICAgICAgICAgICAjICBbKG51bWJlciBvZiBmbGlnaHRzKSpkZWxheS9kaXN0YW5jZV0gZm9yIGEgZGVzdGluYXRpb24KCnRvcDEwMCA8LSBkZWxheXMgJT4lICAgICAgICAgICAgICAgICAgICAgIyBzZWxlY3QgdGhlIHRvcCAxMDAgbGFyZ2VzdCBhcnJpdmFsIGRlbGF5cwogIGFycmFuZ2UoZGVzYyhkZWxheWNvc3QpKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICBoZWFkKDEwMCkKYGBgCgpgYGB7cn0Kcm93Lm5hbWVzKHRvcDEwMCkgPC0gdG9wMTAwJGRlc3QgCmBgYAoKYGBge3J9CmRlbGF5c19tYXQgPC0gZGF0YS5tYXRyaXgodG9wMTAwKSAgICAgIyBjb252ZXJ0IGRlbGF5cyBkYXRhZnJhbWUgdG8gYSBtYXRyaXggIChyZXF1aXJlZCBieSBoZWF0bWFwKQpkZWxheXNfbWF0cml4IDwtIGRlbGF5c19tYXRbLDI6NV0gIyByZW1vdmUgcmVkdW5kYW50IGNvbHVtbiBvZiBkZXN0aW5hdGlvbiBhaXJwb3J0IGNvZGVzCmBgYAoKYGBge3J9CnZhcmNvbHMgPSBzZXROYW1lcyhjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwobnJvdyhkZWxheXNfbWF0cml4KSwgIllsR25CdSIpKShucm93KGRlbGF5c19tYXRyaXgpKSwgcm93bmFtZXMoZGVsYXlzX21hdHJpeCkpICAgIyBwYXJhbWV0ZXIgZm9yIFJvd1NpZGVDb2xvcnMKYGBgCgpgYGB7cn0KaGVhdG1hcChkZWxheXNfbWF0cml4LCBSb3d2ID0gTkEsIAogICAgICAgIENvbHYgPSBOQSwgCiAgICAgICAgY29sPSBjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwobnJvdyhkZWxheXNfbWF0cml4KSwgIllsR25CdSIpKShucm93KGRlbGF5c19tYXRyaXgpKSwgCiAgICAgICAgcz0wLjYsIHY9MSwgc2NhbGU9ImNvbHVtbiIsIAogICAgICAgIG1hcmdpbnM9Yyg3LDEwKSwgCiAgICAgICAgbWFpbiA9ICJDb3N0IG9mIExhdGUgQXJyaXZhbHMiLCAKICAgICAgICB4bGFiID0iIEZsaWdodCBDaGFyYWN0ZXJpc3RpY3MiLCAKICAgICAgICB5bGFiPSJBcnJpdmFsIEFpcnBvcnQiLCAKICAgICAgICBsYWJDb2wgPSBjKCJGbGlnaHRzIiwiRGlzdGFuY2UiLCJEZWxheSIsIkNvc3QgSW5kZXgiKSwgCiAgICAgICAgY2V4Q29sPTEsIGNleFJvdyA9MSwgUm93U2lkZUNvbG9ycyA9IHZhcmNvbHMpCmBgYAoKQ29zdCBpbmRleCBpcyBhIG1lYXN1cmUgb2YgaG93IG11Y2ggdGhlIGNvc3QgdG8gZmx5IHRvIGFuIGFpcnBvcnQgaW5jcmVhc2VzIApkdWUgdG8gZnJlcXVlbnQgZGVsYXlzIG9mIGFycml2YWwuIEl0IGlzIHJvdWdobHkgcHJvcG9ydGlvbmFsIHRvIGZsaWdodHMgYW5kIAppbnZlcnNlbHkgcHJvcG9ydGlvbmFsIHRvIGRpc3RhbmNlIApiZWNhdXNlIGRlbGF5cyBhZmZlY3Qgc2hvcnRlciBmbGlnaHRzIG1vcmUgdGhhbiBsb25nZXIgb25lcywgYW5kIHRoZSBwcm9maXQKcGVyIHNlYXQgaW5jcmVhc2VzIHdpdGggZGlzdGFuY2UuIFRoZSB2YXJpYW5jZSBpbiBkZWxheXMgaXMgZHVlIHRvIGFpcnBvcnQgCmNvbmdlc3Rpb24gYW5kIHJlZ2lvbmFsIHdlYXRoZXIuCgojIyBTdHJlYW1ncmFwaHMKClN0cmVhbWdyYXBocyBkaXNwbGF5IHRoZSBjaGFuZ2VzIGluIGRhdGEgb3ZlciB0aW1lIG9mIGRpZmZlcmVudCBjYXRlZ29yaWVzLiBUaGUKc2l6ZSBvZiBlYWNoIGluZGl2aWR1YWwgc3RyZWFtIHNoYXBlIGlzIHByb3BvcnRpb25hbCB0byB0aGUgdmFsdWVzIGluIGVhY2gKY2F0ZWdvcnkuIENvbG9ycyBjYW4gYmUgdXNlZCB0byBkaXN0aW5ndWlzaCBzdHJlYW1zIG9yIHRvIHJlcHJlc2VudCBhbgphZGRpdGlvbmFsIGRpbWVuc2lvbiBpbiB0aGUgZGF0YS4gVGhleSBhcmUgd2VsbC1zdWl0ZWQgdG8gZGlzcGxheWluZyBoaWdoLQp2b2x1bWUgZGF0YXNldHMuIFRoZSBkb3duc2lkZSB0byBzdHJlYW1ncmFwaHMgaXMgdGhhdCB0aGV5IGNhbiBiZSBkaWZmaWN1bHQgdG8KcmVhZCwgYmUgY2x1dHRlcmVkLCBhbmQgdGhlIGNhdGVnb3JpZXMgd2l0aCBzbWFsbGVyIHZhbHVlcyBtYXkgYmUgZHJvd25lZCBvdXQuIApJdCBpcyBhbHNvIG5vdCBwb3NzaWJsZSB0byByZWFkIHRoZSBleGFjdCB2YWx1ZXMgdmlzdWFsaXplZCBmcm9tIHRoZSBwbG90LgoKYGBge3J9CmRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiaHJicm1zdHIvc3RyZWFtZ3JhcGgiKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHN0cmVhbWdyYXBoKQpsaWJyYXJ5KGJhYnluYW1lcykKYGBgCgojIyBUcml2aWFsIHN0cmVhbWdyYXBoIHVzaW5nIHNpbXVsYXRlZCBuYW1lcyBvdmVyIHRpbWUKCmBgYHtyfQojIENyZWF0ZSBkYXRhOgp5ZWFyPXJlcChzZXEoMTk5MCwyMDE2KSAsIGVhY2g9MTApCm5hbWU9cmVwKGxldHRlcnNbMToxMF0gLCAyNykKdmFsdWU9c2FtcGxlKCBzZXEoMCwxLDAuMDAwMSkgLCBsZW5ndGgoeWVhcikpCmRhdGE9ZGF0YS5mcmFtZSh5ZWFyLCBuYW1lLCB2YWx1ZSkKIyBCYXNpYyBzdHJlYW0gZ3JhcGg6IGp1c3QgZ2l2ZSB0aGUgMyBhcmd1bWVudHMKc3RyZWFtZ3JhcGgoZGF0YSwga2V5PSJuYW1lIiwgdmFsdWU9InZhbHVlIiwgZGF0ZT0ieWVhciIpCmBgYAoKbGV0cyBsb29rIGF0IHRoZSBiYWJ5bmFtZXMgZGF0YXNldDoKYGBge3J9Cm5jb2woYmFieW5hbWVzKQpgYGAKCmBgYHtyfQpoZWFkKGJhYnluYW1lcykKYGBgCgpgYGB7cn0Kc3RyKGJhYnluYW1lcykKYGBgCgojIyBCYWJ5bmFtZXMgc3RyZWFtZ3JhcGgKCmBgYHtyfQpiYWJ5bmFtZXMgJT4lCiAgZmlsdGVyKGdyZXBsKCJeS3IiLCBuYW1lKSkgJT4lCiAgZ3JvdXBfYnkoeWVhciwgbmFtZSkgJT4lCiAgdGFsbHkod3Q9bikgJT4lCiAgc3RyZWFtZ3JhcGgoIm5hbWUiLCAibiIsICJ5ZWFyIikKYGBgCgpgYGB7cn0KIyBTdHJlYW1ncmFwaGluZyBDb21tZXJjaWFsIFJlYWwgRXN0YXRlIFRyYW5zYWN0aW9uIFZvbHVtZSBieSBBc3NldCBDbGFzcyBTaW5jZSAyMDAxCgpkYXQgPC0gcmVhZC5jc3YoImh0dHA6Ly9hc2JjbGxjLmNvbS9ibG9nLzIwMTUvZmVicnVhcnkvY3JlX3N0cmVhbV9ncmFwaF90ZXN0L2RhdGEvY3JlX3RyYW5zYWN0aW9uLWRhdGEuY3N2IikKCmRhdCAlPiUKICBzdHJlYW1ncmFwaCgiYXNzZXRfY2xhc3MiLCAidm9sdW1lX2JpbGxpb25zIiwgInllYXIiLCBpbnRlcnBvbGF0ZT0iY2FyZGluYWwiKSAlPiUKICBzZ19heGlzX3goMSwgInllYXIiLCAiJVkiKSAlPiUKICBzZ19maWxsX2JyZXdlcigiUHVPciIpIApgYGAKCiMjIEFsbHV2aWFscwoKYGBge3J9CmxpYnJhcnkoYWxsdXZpYWwpCmBgYAoKIyMgRXhhbWluaW5nIGRhdGEgZnJvbSB0aGUgUmVmdWdlZXMgZGF0YXNldAoKYGBge3J9CmFsbHV2aWFsOjpSZWZ1Z2VlcwpgYGAKCmBgYHtyfQpSZWZ1Z2VlcyA8LSBSZWZ1Z2VlcyAjLi4uV2h5Pwp3cml0ZV9jc3YoUmVmdWdlZXMsICJyZWZ1Z2Vlcy5jc3YiKQpgYGAKCiMjIENyZWF0ZSB0aGUgYWxsdXZpYWwgdG8gc2hvdyBVTkhDUi1yZWNvZ25pc2VkIHJlZnVnZWVzIGluIHRoZSB0b3AgMTAKIyMgY291bnRyaWVzIGZyb20gMjAwMyAtIDIwMTMKCmBgYHtyfQpzZXQuc2VlZCgzOSkgIyBmb3IgbmljZSBjb2xvdXJzCmNvbHMgPC0gaHN2KGggPSBzYW1wbGUoMToxMC8xMCksIHMgPSBzYW1wbGUoMzoxMikvMTUsIHYgPSBzYW1wbGUoMzoxMikvMTUpICMgY3JlYXRlcyB0aGUgdmVjdG9yIG9mIDEwIGNvbG9ycwoKYWxsdXZpYWxfdHMoUmVmdWdlZXMsIHdhdmUgPSAuMywgeWdhcCA9IDUsIGNvbCA9IGNvbHMsIHBsb3RkaXIgPSAnY2VudHJlZCcsIGFscGhhPS45LAogICAgICAgICAgICBncmlkID0gVFJVRSwgZ3JpZC5sd2QgPSA1LCB4bWFyZ2luID0gMC4yLCBsYWIuY2V4ID0gLjcsIHhsYWIgPSAnJywKICAgICAgICAgICAgeWxhYiA9ICcnLCBib3JkZXIgPSBOQSwgYXhpcy5jZXggPSAuOCwgbGVnLmNleCA9IC43LAogICAgICAgICAgICBsZWcuY29sPSd3aGl0ZScsIAogICAgICAgICAgICB0aXRsZSA9ICJVTkhDUi1yZWNvZ25pc2VkIHJlZnVnZWVzXG5Ub3AgMTAgY291bnRyaWVzICgyMDAzLTIwMTMpXG4iKQpgYGAKCg==