Ansgar Wolsing’s contribution to 30 Day Chart Challenge, 2022 Edition.

Code on GitHub (very slightly modified).

## remotes::install_github("davidsjoberg/ggstream")
library(ggstream)
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✔ ggplot2 3.3.5     ✔ purrr   0.3.4
## ✔ tibble  3.1.6     ✔ dplyr   1.0.8
## ✔ tidyr   1.2.0     ✔ stringr 1.4.0
## ✔ readr   2.1.2     ✔ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library(tidytext)
library(ggtext)

## download text from Project Gutenberg
if (! file.exists("macbeth.txt")) {
    macbeth_url <- "https://www.gutenberg.org/cache/epub/1129/pg1129.txt"
    download.file(macbeth_url, "macbeth.txt")
}
macbeth_lines <- read_lines("macbeth.txt")

## Lines where the manuscript starts and ends
start_line <- 282
end_line <- 2899
exclude_lines <- 2358:2365

text_df <- tibble(line = macbeth_lines[start_line:end_line]) %>% 
    mutate(line = str_squish(line),
           line_id = row_number()) %>% 
    ## remove empty or irrelevant lines
    filter(line != "" | line_id %in% exclude_lines) %>% 
    filter(!str_detect(line, "SERVICE THAT CHARGES|WITH PERMISSION|COMMERCIALLY")) %>% 
    ## extract the act and scene
    mutate(act = str_extract(line, "^ACT\\b.+?\\."),
           scene = str_extract(line, "SCENE\\b.+?\\.")) %>% 
    fill(act, scene, .direction = "down") %>% 
    ## extract the character name who speaks
    mutate(speaker = str_extract(line, "^[A-Z\\s]+\\."),
           speaker = str_remove(speaker, "\\.$"),
           speaker = ifelse(str_detect(speaker, "^ACT|SCENE\\b"), 
                            NA_character_, speaker),
           speaker = str_to_title(speaker)) %>% 
    ## manage the switch of speakers from scene to scene
    group_by(act, scene) %>% 
    fill(speaker, .direction = "down") %>% 
    ungroup() %>% 
    ## remove lines without a speaker
    filter(!is.na(speaker)) %>%
    ## remove speaker names from the lines
    mutate(line = str_remove(line, paste0(speaker, ". "))) 

## count the number of words per speaker in each act and scene
word_count_speakers <- text_df %>% 
    ## recode the witches and murderers into one category
    mutate(speaker_grp = ifelse(str_detect(speaker, "Witch$"),
                                "Three Witches", speaker),
           speaker_grp = ifelse(str_detect(speaker_grp, "Mutherers?$"),
                                "Mutherers", speaker_grp)) %>% 
    unnest_tokens(word, line, token = "words", drop = TRUE) %>% 
    count(act, scene, speaker_grp, speaker, name = "word_count")

## identify character with only a few appearances
few_appearances_speakers <- word_count_speakers %>% 
    group_by(speaker_grp) %>% 
    summarize(scenes_count = n_distinct(act, scene),
              word_count_total = sum(word_count)) %>% 
    filter(scenes_count <= 3, word_count_total < 500) %>% 
    pull(speaker_grp)

## Custom color palette by character affiliation
speaker_grp_levels = c(
  "Macbeth", "Lady Macbeth", 
  "Duncan", "Malcolm", "Macduff", "Ross",
  "Banquo", "Lennox",
  "Three Witches",
  "Other")
color_palette <- paletteer::paletteer_d(
  "palettetown::pidgey")[c(9, 8,
                           2, 5, 4, 6,
                           12, 6,
                           3,
                           11 )]

## Annotations
plot_titles <- list(
    title = "Who speaks when in Shakespeare's MACBETH?",
    subtitle = "Distribution of speech share (number of words) per character in 
  each scene. Acts are separated with vertical lines.",
  caption = "Project Gutenberg. Visualization: Ansgar Wolsing"
)

## highlight key events - used for text and lines
story_annotations <- tibble(
    x    = c(13.5, 1.2, 7, 5, 14, 22),
    xend = c(19,   1.2, 7, 5, 14, 22),
    y    = c(-5000, -4200, -4500, 5000, 5000, 3000),
    yend = c(-5000,  -200,   400,  800, 1000,  500),
    vjust = c(   0,  0.25,   0.3,  0.85,  0.9,  0.8),
    label = c(
        "Macduff & Malcolm decide to go to war against Macbeth",
        "Three Witches<br>appear",
        "Macbeth kills King Duncan",
        "Lady Macbeth & Macbeth<br>plan the murder of King Duncan",
        "Murder of Banquo reported to Macbeth,<br>Ghost of Banquo appears",
        "Macduff<br>kills<br>Macbeth"))

word_count_speakers %>% 
    mutate(speaker_grp =
               ifelse(speaker_grp %in% c("All", few_appearances_speakers),
                      "Other", speaker_grp),
           speaker_grp = factor(speaker_grp, levels = speaker_grp_levels)) %>% 
    count(act, scene, speaker_grp, wt = word_count, name = "word_count") %>% 
    ## increment counter across act and scene
    group_by(act, scene) %>% 
    mutate(act_scene_id = cur_group_id()) %>% 
    ungroup() %>% 
    ggplot(aes(act_scene_id, word_count, fill = speaker_grp)) +
    ## vertical lines for the acts
    geom_vline(
        data = . %>% filter(scene == "SCENE I."),
        aes(xintercept = act_scene_id), 
        color = "grey50", size = 0.2, lty = "dotted") +
    geom_stream(type = "mirror", bw = 0.5,  extra_span = 0.1) +
    ## annotations for key events (text + segment)
    geom_textbox(
        data = story_annotations,
        aes(x - 0.08, y, label = label, vjust = vjust),
        inherit.aes = FALSE,
        color = "grey90", family = "Forum", hjust = 0, fill = NA,
        box.size = 0,
        width = unit(3.5, "cm")) +
    geom_segment(
        data = story_annotations,
        aes(x = x, xend = xend, y = y, yend = yend), inherit.aes = FALSE,
        color = "grey90", size = 0.3) +
    ## text labels for the acts
    geom_text(
        data = . %>% group_by(act) %>%
            summarize(x = min(act_scene_id) + n_distinct(scene) / 2),
        aes(x, y = -Inf, label = act), inherit.aes = FALSE, 
        vjust = -1, hjust = 0.5, color = "grey60", family = "Forum") +
    scale_fill_manual(values = color_palette) +
    labs(
        title = plot_titles$title,
        subtitle = plot_titles$subtitle,
        caption = plot_titles$caption,
        fill = NULL) +
    theme_void(base_family = "Forum", base_size = 10) +
    theme(
        plot.background = element_rect(color = NA, fill = "grey8"),
        plot.margin = margin(10, 10, 10, 10),
        legend.position = "bottom", 
        legend.direction = "horizontal",
        legend.key.height = unit(3, "mm"),
        legend.spacing.y = unit(4, "cm"),
        legend.text = element_text(size = 9.5),
        text = element_text(color = "white"),
        plot.title = element_text(size = 24, family = "Forum"),
        plot.subtitle = element_markdown(),
        plot.caption = element_markdown(hjust = 1))

LS0tCnRpdGxlOiAiV2hvIFNwZWFrcyBXaGVuIGluIFNoYWtlc3BlYXJlJ3MgTUFDQkVUSD8iCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVkgJUg6JU0nKWAiCi0tLQoKYGBge3IgZ2xvYmFsX29wdGlvbnMsIGluY2x1ZGUgPSBGQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNvbGxhcHNlID0gVFJVRSwgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSIsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuYWxpZ24gPSAiY2VudGVyIikKYGBgCkFuc2dhciBXb2xzaW5nJ3MKW2NvbnRyaWJ1dGlvbl0oaHR0cHM6Ly90d2l0dGVyLmNvbS9fYW5zZ2FyL3N0YXR1cy8xNTEzMDg0NjU5MDEzNTA1MDI4KSB0bwpbMzAgRGF5IENoYXJ0IENoYWxsZW5nZSwgMjAyMiBFZGl0aW9uXShodHRwczovL3R3aXR0ZXIuY29tLzMwRGF5Q2hhcnRDaGFsbCkuCgpbQ29kZSBvbiBHaXRIdWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9ieWRhdGEvMzBEYXlDaGFydENoYWxsZW5nZS9ibG9iL21haW4vMjAyMi8xMC8xMC1leHBlcmltZW50YWwtbWFjYmV0aC5SKSAodmVyeSBzbGlnaHRseSBtb2RpZmllZCkuCgpgYGB7ciwgZmlnLndpZHRoID0gMTAsIGZpZy5oZWlnaHQgPSA4fQojIyByZW1vdGVzOjppbnN0YWxsX2dpdGh1YigiZGF2aWRzam9iZXJnL2dnc3RyZWFtIikKbGlicmFyeShnZ3N0cmVhbSkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkodGlkeXRleHQpCmxpYnJhcnkoZ2d0ZXh0KQoKIyMgZG93bmxvYWQgdGV4dCBmcm9tIFByb2plY3QgR3V0ZW5iZXJnCmlmICghIGZpbGUuZXhpc3RzKCJtYWNiZXRoLnR4dCIpKSB7CiAgICBtYWNiZXRoX3VybCA8LSAiaHR0cHM6Ly93d3cuZ3V0ZW5iZXJnLm9yZy9jYWNoZS9lcHViLzExMjkvcGcxMTI5LnR4dCIKICAgIGRvd25sb2FkLmZpbGUobWFjYmV0aF91cmwsICJtYWNiZXRoLnR4dCIpCn0KbWFjYmV0aF9saW5lcyA8LSByZWFkX2xpbmVzKCJtYWNiZXRoLnR4dCIpCgojIyBMaW5lcyB3aGVyZSB0aGUgbWFudXNjcmlwdCBzdGFydHMgYW5kIGVuZHMKc3RhcnRfbGluZSA8LSAyODIKZW5kX2xpbmUgPC0gMjg5OQpleGNsdWRlX2xpbmVzIDwtIDIzNTg6MjM2NQoKdGV4dF9kZiA8LSB0aWJibGUobGluZSA9IG1hY2JldGhfbGluZXNbc3RhcnRfbGluZTplbmRfbGluZV0pICU+JSAKICAgIG11dGF0ZShsaW5lID0gc3RyX3NxdWlzaChsaW5lKSwKICAgICAgICAgICBsaW5lX2lkID0gcm93X251bWJlcigpKSAlPiUgCiAgICAjIyByZW1vdmUgZW1wdHkgb3IgaXJyZWxldmFudCBsaW5lcwogICAgZmlsdGVyKGxpbmUgIT0gIiIgfCBsaW5lX2lkICVpbiUgZXhjbHVkZV9saW5lcykgJT4lIAogICAgZmlsdGVyKCFzdHJfZGV0ZWN0KGxpbmUsICJTRVJWSUNFIFRIQVQgQ0hBUkdFU3xXSVRIIFBFUk1JU1NJT058Q09NTUVSQ0lBTExZIikpICU+JSAKICAgICMjIGV4dHJhY3QgdGhlIGFjdCBhbmQgc2NlbmUKICAgIG11dGF0ZShhY3QgPSBzdHJfZXh0cmFjdChsaW5lLCAiXkFDVFxcYi4rP1xcLiIpLAogICAgICAgICAgIHNjZW5lID0gc3RyX2V4dHJhY3QobGluZSwgIlNDRU5FXFxiLis/XFwuIikpICU+JSAKICAgIGZpbGwoYWN0LCBzY2VuZSwgLmRpcmVjdGlvbiA9ICJkb3duIikgJT4lIAogICAgIyMgZXh0cmFjdCB0aGUgY2hhcmFjdGVyIG5hbWUgd2hvIHNwZWFrcwogICAgbXV0YXRlKHNwZWFrZXIgPSBzdHJfZXh0cmFjdChsaW5lLCAiXltBLVpcXHNdK1xcLiIpLAogICAgICAgICAgIHNwZWFrZXIgPSBzdHJfcmVtb3ZlKHNwZWFrZXIsICJcXC4kIiksCiAgICAgICAgICAgc3BlYWtlciA9IGlmZWxzZShzdHJfZGV0ZWN0KHNwZWFrZXIsICJeQUNUfFNDRU5FXFxiIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgTkFfY2hhcmFjdGVyXywgc3BlYWtlciksCiAgICAgICAgICAgc3BlYWtlciA9IHN0cl90b190aXRsZShzcGVha2VyKSkgJT4lIAogICAgIyMgbWFuYWdlIHRoZSBzd2l0Y2ggb2Ygc3BlYWtlcnMgZnJvbSBzY2VuZSB0byBzY2VuZQogICAgZ3JvdXBfYnkoYWN0LCBzY2VuZSkgJT4lIAogICAgZmlsbChzcGVha2VyLCAuZGlyZWN0aW9uID0gImRvd24iKSAlPiUgCiAgICB1bmdyb3VwKCkgJT4lIAogICAgIyMgcmVtb3ZlIGxpbmVzIHdpdGhvdXQgYSBzcGVha2VyCiAgICBmaWx0ZXIoIWlzLm5hKHNwZWFrZXIpKSAlPiUKICAgICMjIHJlbW92ZSBzcGVha2VyIG5hbWVzIGZyb20gdGhlIGxpbmVzCiAgICBtdXRhdGUobGluZSA9IHN0cl9yZW1vdmUobGluZSwgcGFzdGUwKHNwZWFrZXIsICIuICIpKSkgCgojIyBjb3VudCB0aGUgbnVtYmVyIG9mIHdvcmRzIHBlciBzcGVha2VyIGluIGVhY2ggYWN0IGFuZCBzY2VuZQp3b3JkX2NvdW50X3NwZWFrZXJzIDwtIHRleHRfZGYgJT4lIAogICAgIyMgcmVjb2RlIHRoZSB3aXRjaGVzIGFuZCBtdXJkZXJlcnMgaW50byBvbmUgY2F0ZWdvcnkKICAgIG11dGF0ZShzcGVha2VyX2dycCA9IGlmZWxzZShzdHJfZGV0ZWN0KHNwZWFrZXIsICJXaXRjaCQiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGhyZWUgV2l0Y2hlcyIsIHNwZWFrZXIpLAogICAgICAgICAgIHNwZWFrZXJfZ3JwID0gaWZlbHNlKHN0cl9kZXRlY3Qoc3BlYWtlcl9ncnAsICJNdXRoZXJlcnM/JCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNdXRoZXJlcnMiLCBzcGVha2VyX2dycCkpICU+JSAKICAgIHVubmVzdF90b2tlbnMod29yZCwgbGluZSwgdG9rZW4gPSAid29yZHMiLCBkcm9wID0gVFJVRSkgJT4lIAogICAgY291bnQoYWN0LCBzY2VuZSwgc3BlYWtlcl9ncnAsIHNwZWFrZXIsIG5hbWUgPSAid29yZF9jb3VudCIpCgojIyBpZGVudGlmeSBjaGFyYWN0ZXIgd2l0aCBvbmx5IGEgZmV3IGFwcGVhcmFuY2VzCmZld19hcHBlYXJhbmNlc19zcGVha2VycyA8LSB3b3JkX2NvdW50X3NwZWFrZXJzICU+JSAKICAgIGdyb3VwX2J5KHNwZWFrZXJfZ3JwKSAlPiUgCiAgICBzdW1tYXJpemUoc2NlbmVzX2NvdW50ID0gbl9kaXN0aW5jdChhY3QsIHNjZW5lKSwKICAgICAgICAgICAgICB3b3JkX2NvdW50X3RvdGFsID0gc3VtKHdvcmRfY291bnQpKSAlPiUgCiAgICBmaWx0ZXIoc2NlbmVzX2NvdW50IDw9IDMsIHdvcmRfY291bnRfdG90YWwgPCA1MDApICU+JSAKICAgIHB1bGwoc3BlYWtlcl9ncnApCgojIyBDdXN0b20gY29sb3IgcGFsZXR0ZSBieSBjaGFyYWN0ZXIgYWZmaWxpYXRpb24Kc3BlYWtlcl9ncnBfbGV2ZWxzID0gYygKICAiTWFjYmV0aCIsICJMYWR5IE1hY2JldGgiLCAKICAiRHVuY2FuIiwgIk1hbGNvbG0iLCAiTWFjZHVmZiIsICJSb3NzIiwKICAiQmFucXVvIiwgIkxlbm5veCIsCiAgIlRocmVlIFdpdGNoZXMiLAogICJPdGhlciIpCmNvbG9yX3BhbGV0dGUgPC0gcGFsZXR0ZWVyOjpwYWxldHRlZXJfZCgKICAicGFsZXR0ZXRvd246OnBpZGdleSIpW2MoOSwgOCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgMiwgNSwgNCwgNiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgMTIsIDYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIDExICldCgojIyBBbm5vdGF0aW9ucwpwbG90X3RpdGxlcyA8LSBsaXN0KAogICAgdGl0bGUgPSAiV2hvIHNwZWFrcyB3aGVuIGluIFNoYWtlc3BlYXJlJ3MgTUFDQkVUSD8iLAogICAgc3VidGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIHNwZWVjaCBzaGFyZSAobnVtYmVyIG9mIHdvcmRzKSBwZXIgY2hhcmFjdGVyIGluIAogIGVhY2ggc2NlbmUuIEFjdHMgYXJlIHNlcGFyYXRlZCB3aXRoIHZlcnRpY2FsIGxpbmVzLiIsCiAgY2FwdGlvbiA9ICJQcm9qZWN0IEd1dGVuYmVyZy4gVmlzdWFsaXphdGlvbjogQW5zZ2FyIFdvbHNpbmciCikKCiMjIGhpZ2hsaWdodCBrZXkgZXZlbnRzIC0gdXNlZCBmb3IgdGV4dCBhbmQgbGluZXMKc3RvcnlfYW5ub3RhdGlvbnMgPC0gdGliYmxlKAogICAgeCAgICA9IGMoMTMuNSwgMS4yLCA3LCA1LCAxNCwgMjIpLAogICAgeGVuZCA9IGMoMTksICAgMS4yLCA3LCA1LCAxNCwgMjIpLAogICAgeSAgICA9IGMoLTUwMDAsIC00MjAwLCAtNDUwMCwgNTAwMCwgNTAwMCwgMzAwMCksCiAgICB5ZW5kID0gYygtNTAwMCwgIC0yMDAsICAgNDAwLCAgODAwLCAxMDAwLCAgNTAwKSwKICAgIHZqdXN0ID0gYyggICAwLCAgMC4yNSwgICAwLjMsICAwLjg1LCAgMC45LCAgMC44KSwKICAgIGxhYmVsID0gYygKICAgICAgICAiTWFjZHVmZiAmIE1hbGNvbG0gZGVjaWRlIHRvIGdvIHRvIHdhciBhZ2FpbnN0IE1hY2JldGgiLAogICAgICAgICJUaHJlZSBXaXRjaGVzPGJyPmFwcGVhciIsCiAgICAgICAgIk1hY2JldGgga2lsbHMgS2luZyBEdW5jYW4iLAogICAgICAgICJMYWR5IE1hY2JldGggJiBNYWNiZXRoPGJyPnBsYW4gdGhlIG11cmRlciBvZiBLaW5nIER1bmNhbiIsCiAgICAgICAgIk11cmRlciBvZiBCYW5xdW8gcmVwb3J0ZWQgdG8gTWFjYmV0aCw8YnI+R2hvc3Qgb2YgQmFucXVvIGFwcGVhcnMiLAogICAgICAgICJNYWNkdWZmPGJyPmtpbGxzPGJyPk1hY2JldGgiKSkKCndvcmRfY291bnRfc3BlYWtlcnMgJT4lIAogICAgbXV0YXRlKHNwZWFrZXJfZ3JwID0KICAgICAgICAgICAgICAgaWZlbHNlKHNwZWFrZXJfZ3JwICVpbiUgYygiQWxsIiwgZmV3X2FwcGVhcmFuY2VzX3NwZWFrZXJzKSwKICAgICAgICAgICAgICAgICAgICAgICJPdGhlciIsIHNwZWFrZXJfZ3JwKSwKICAgICAgICAgICBzcGVha2VyX2dycCA9IGZhY3RvcihzcGVha2VyX2dycCwgbGV2ZWxzID0gc3BlYWtlcl9ncnBfbGV2ZWxzKSkgJT4lIAogICAgY291bnQoYWN0LCBzY2VuZSwgc3BlYWtlcl9ncnAsIHd0ID0gd29yZF9jb3VudCwgbmFtZSA9ICJ3b3JkX2NvdW50IikgJT4lIAogICAgIyMgaW5jcmVtZW50IGNvdW50ZXIgYWNyb3NzIGFjdCBhbmQgc2NlbmUKICAgIGdyb3VwX2J5KGFjdCwgc2NlbmUpICU+JSAKICAgIG11dGF0ZShhY3Rfc2NlbmVfaWQgPSBjdXJfZ3JvdXBfaWQoKSkgJT4lIAogICAgdW5ncm91cCgpICU+JSAKICAgIGdncGxvdChhZXMoYWN0X3NjZW5lX2lkLCB3b3JkX2NvdW50LCBmaWxsID0gc3BlYWtlcl9ncnApKSArCiAgICAjIyB2ZXJ0aWNhbCBsaW5lcyBmb3IgdGhlIGFjdHMKICAgIGdlb21fdmxpbmUoCiAgICAgICAgZGF0YSA9IC4gJT4lIGZpbHRlcihzY2VuZSA9PSAiU0NFTkUgSS4iKSwKICAgICAgICBhZXMoeGludGVyY2VwdCA9IGFjdF9zY2VuZV9pZCksIAogICAgICAgIGNvbG9yID0gImdyZXk1MCIsIHNpemUgPSAwLjIsIGx0eSA9ICJkb3R0ZWQiKSArCiAgICBnZW9tX3N0cmVhbSh0eXBlID0gIm1pcnJvciIsIGJ3ID0gMC41LCAgZXh0cmFfc3BhbiA9IDAuMSkgKwogICAgIyMgYW5ub3RhdGlvbnMgZm9yIGtleSBldmVudHMgKHRleHQgKyBzZWdtZW50KQogICAgZ2VvbV90ZXh0Ym94KAogICAgICAgIGRhdGEgPSBzdG9yeV9hbm5vdGF0aW9ucywKICAgICAgICBhZXMoeCAtIDAuMDgsIHksIGxhYmVsID0gbGFiZWwsIHZqdXN0ID0gdmp1c3QpLAogICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgY29sb3IgPSAiZ3JleTkwIiwgZmFtaWx5ID0gIkZvcnVtIiwgaGp1c3QgPSAwLCBmaWxsID0gTkEsCiAgICAgICAgYm94LnNpemUgPSAwLAogICAgICAgIHdpZHRoID0gdW5pdCgzLjUsICJjbSIpKSArCiAgICBnZW9tX3NlZ21lbnQoCiAgICAgICAgZGF0YSA9IHN0b3J5X2Fubm90YXRpb25zLAogICAgICAgIGFlcyh4ID0geCwgeGVuZCA9IHhlbmQsIHkgPSB5LCB5ZW5kID0geWVuZCksIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgY29sb3IgPSAiZ3JleTkwIiwgc2l6ZSA9IDAuMykgKwogICAgIyMgdGV4dCBsYWJlbHMgZm9yIHRoZSBhY3RzCiAgICBnZW9tX3RleHQoCiAgICAgICAgZGF0YSA9IC4gJT4lIGdyb3VwX2J5KGFjdCkgJT4lCiAgICAgICAgICAgIHN1bW1hcml6ZSh4ID0gbWluKGFjdF9zY2VuZV9pZCkgKyBuX2Rpc3RpbmN0KHNjZW5lKSAvIDIpLAogICAgICAgIGFlcyh4LCB5ID0gLUluZiwgbGFiZWwgPSBhY3QpLCBpbmhlcml0LmFlcyA9IEZBTFNFLCAKICAgICAgICB2anVzdCA9IC0xLCBoanVzdCA9IDAuNSwgY29sb3IgPSAiZ3JleTYwIiwgZmFtaWx5ID0gIkZvcnVtIikgKwogICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JfcGFsZXR0ZSkgKwogICAgbGFicygKICAgICAgICB0aXRsZSA9IHBsb3RfdGl0bGVzJHRpdGxlLAogICAgICAgIHN1YnRpdGxlID0gcGxvdF90aXRsZXMkc3VidGl0bGUsCiAgICAgICAgY2FwdGlvbiA9IHBsb3RfdGl0bGVzJGNhcHRpb24sCiAgICAgICAgZmlsbCA9IE5VTEwpICsKICAgIHRoZW1lX3ZvaWQoYmFzZV9mYW1pbHkgPSAiRm9ydW0iLCBiYXNlX3NpemUgPSAxMCkgKwogICAgdGhlbWUoCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gTkEsIGZpbGwgPSAiZ3JleTgiKSwKICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigxMCwgMTAsIDEwLCAxMCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIAogICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAgbGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDMsICJtbSIpLAogICAgICAgIGxlZ2VuZC5zcGFjaW5nLnkgPSB1bml0KDQsICJjbSIpLAogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LjUpLAogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAid2hpdGUiKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyNCwgZmFtaWx5ID0gIkZvcnVtIiksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfbWFya2Rvd24oKSwKICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X21hcmtkb3duKGhqdXN0ID0gMSkpCmBgYAo=