INTRODUCTION

Vaccines have been hotly debated throughout the pandemic. There are different thoughts about each type and brand of vaccine, ranging from views about their effectiveness to side effects and duration of protection. One of the most successful vaccines to date is Pfizer-BioNTech, which has been part of the controversy as well. Encountering a database of tweets about Pfizer-BioNTech vaccines, I thought it would be interesting to analyze them through word networks to see which keywords/topics were most discussed and how they related to each other.

Set Up

First, we load libraries that we need in the following steps.

library(dplyr)
library(tidytext)
library(tidyverse)
library(tidyr)
library(ggplot2)
library(igraph)
## Warning: package 'igraph' was built under R version 4.1.3
library(ggraph)
## Warning: package 'ggraph' was built under R version 4.1.3

WRANGLE

Import Data

Now let’s read a dataset of the tweets about Pfizer or BioNTech. This dataset has many attributes, so I only select the column “text” which contains tweets and the column “user_name”.

vaccination <- read_csv("data/vaccination_tweets.csv")
## Rows: 11020 Columns: 16
## -- Column specification --------------------------------------------------------
## Delimiter: ","
## chr (8): user_name, user_location, user_description, user_created, date, tex...
## dbl (6): id, user_followers, user_friends, user_favourites, retweets, favorites
## lgl (2): user_verified, is_retweet
## 
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet this message.
vaccination <- select(vaccination,user_name,text)
 
# remove_words_from_text <- function(text) {
#   text <- unlist(strsplit(tolower(text), " "))
#   paste(text[!text %in% words_to_remove], collapse = " ")
# }
# 
# words_to_remove <- stop_words$word
# vaccination$text <- lapply(vaccination$text, remove_words_from_text)

Tokenizing text into bigrams

In this step, we will tokenize tweets into bigrams.

 ct_bigrams <- vaccination %>%
   unnest_tokens(bigram, text, token = "ngrams", n = 2)

There are 191753 bigrams. Now let’s do a quick count to see common bigrams:

ct_bigrams %>%
  count(bigram, sort = TRUE)
## # A tibble: 86,214 x 2
##    bigram                     n
##    <chr>                  <int>
##  1 of the                  1051
##  2 pfizerbiontech vaccine   981
##  3 covid 19                 976
##  4 the pfizerbiontech       945
##  5 dose of                  671
##  6 19 vaccine               512
##  7 of pfizerbiontech        446
##  8 pfizer biontech          439
##  9 first dose               422
## 10 covid19 vaccine          401
## # ... with 86,204 more rows

As we see, some stop words appeared in common bigrams, so we need to remove these words.

bigrams_separated <- ct_bigrams %>%
  separate(bigram, c("word1", "word2"), sep = " ")


bigrams_filtered <- bigrams_separated %>%
  filter(!word1 %in% stop_words$word) %>%
  filter(!word2 %in% stop_words$word) 

bigram_counts <- bigrams_filtered %>% 
  count(word1, word2, sort = TRUE)

bigram_counts
## # A tibble: 34,586 x 3
##    word1          word2              n
##    <chr>          <chr>          <int>
##  1 pfizerbiontech vaccine          981
##  2 covid          19               976
##  3 19             vaccine          512
##  4 pfizer         biontech         439
##  5 covid19        vaccine          401
##  6 covid          vaccine          325
##  7 pfizerbiontech covid19          251
##  8 pfizer         vaccine          236
##  9 2nd            dose             218
## 10 pfizer         pfizerbiontech   208
## # ... with 34,576 more rows

Now, in bigram_counts, all stop words are removed.

We can also combine the separated words with unite:

bigrams_united <- bigrams_filtered %>%
  unite(bigram, word1, word2, sep = " ")

bigrams_united
## # A tibble: 55,002 x 2
##    user_name                                               bigram               
##    <chr>                                                   <chr>                
##  1 "Rachel Roh"                                            daikon paste         
##  2 "Rachel Roh"                                            cytokine storm       
##  3 "Rachel Roh"                                            storm pfizerbiontech 
##  4 "Rachel Roh"                                            pfizerbiontech xehhi~
##  5 "Albert Fong"                                           biggest vaccination  
##  6 "Albert Fong"                                           vaccination effort   
##  7 "Albert Fong"                                           ev dlchrzjkhm        
##  8 "eli\U0001f1f1\U0001f1f9\U0001f1ea\U0001f1fa\U0001f44c" coronavirus sputnikv 
##  9 "eli\U0001f1f1\U0001f1f9\U0001f1ea\U0001f1fa\U0001f44c" sputnikv astrazeneca 
## 10 "eli\U0001f1f1\U0001f1f9\U0001f1ea\U0001f1fa\U0001f44c" astrazeneca pfizerbi~
## # ... with 54,992 more rows

VISUALIZE WORD NETWORK

We need to transform our dataset (bigram_counts) into these variables in the following way: from is the “word1”, to is the “word2”, and weight is “n”.

Let’s use graph_from_data_frame to make the transformation:

bigram_graph <- bigram_counts %>%
  graph_from_data_frame()

bigram_graph
## IGRAPH e50df3d DN-- 21259 34586 -- 
## + attr: name (v/c), n (e/n)
## + edges from e50df3d (vertex names):
##  [1] pfizerbiontech->vaccine        covid         ->19            
##  [3] 19            ->vaccine        pfizer        ->biontech      
##  [5] covid19       ->vaccine        covid         ->vaccine       
##  [7] pfizerbiontech->covid19        pfizer        ->vaccine       
##  [9] 2nd           ->dose           pfizer        ->pfizerbiontech
## [11] pfizerbiontech->covidvaccine   pfizervaccine ->pfizerbiontech
## [13] 1st           ->dose           pfizerbiontech->covid         
## [15] covidvaccine  ->pfizerbiontech vaccine       ->pfizerbiontech
## + ... omitted several edges

Based on the high number of bigrams, I decided to remove those with a nonsignificant number of occurrence. So I tried different numbers and found out that we would only need to keep those appearing more than 40 times.

bigram_graph_filtered <- bigram_counts %>%
  filter(n > 40) %>%
  graph_from_data_frame()

bigram_graph_filtered
## IGRAPH e51a83d DN-- 43 59 -- 
## + attr: name (v/c), n (e/n)
## + edges from e51a83d (vertex names):
##  [1] pfizerbiontech->vaccine        covid         ->19            
##  [3] 19            ->vaccine        pfizer        ->biontech      
##  [5] covid19       ->vaccine        covid         ->vaccine       
##  [7] pfizerbiontech->covid19        pfizer        ->vaccine       
##  [9] 2nd           ->dose           pfizer        ->pfizerbiontech
## [11] pfizerbiontech->covidvaccine   pfizervaccine ->pfizerbiontech
## [13] 1st           ->dose           pfizerbiontech->covid         
## [15] covidvaccine  ->pfizerbiontech vaccine       ->pfizerbiontech
## + ... omitted several edges
set.seed(100)

a <- grid::arrow(type = "closed", length = unit(.2, "inches"))

ggraph(bigram_graph_filtered, layout = "fr") +
  geom_edge_link(aes(edge_alpha = n), show.legend = FALSE,
                 arrow = a, end_cap = circle(.07, 'inches')) +
  geom_node_point(color = "yellow", size = 5) +
  geom_node_text(aes(label = name), vjust = 1, hjust = 1) +
  theme_void()

CONCLUSION

The result obtained using the word network have been way more interesting than I anticipated before conducting this study. In the middle cluster, which is comprised of the most repeated bigrams, the name of the main competitors of Pfizer can be seen: “Moderna Vaccine” and “AstraZeneca vaccine”. This shows that people use the name of these brands in their tweets about Pfizer, potentially for making comparisons or showing preference. The count of doses can be also seen by which we can see the number of doses people get or need to receive has been highly written in their tweets. Another interesting arrow is “vaccine approved” which again shows the public attention towards the approval of vaccines.

In other clusters, “soar arm” is so interesting which has been highly tweeted indicating the high focus on this side effect of Pfizer vaccines. Also “protective measures” including complementary tips about protecting against COVID and staying safe have been tweeted so many times. One another combination that I really liked is “remember 2021” which shows how the year 2021 will remain in the memory of people.

To conclude, word network seems to be able to derive meaningful relationships from a corpus which would be highly useful for getting insights into a large amount of text.

LS0tDQp0aXRsZTogIlVuaXQgNCBXYWxrdGhyb3VnaDogQmlncmFtcyAmIHdvcmQgbmV0d29yayINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiAzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFDQplZGl0b3Jfb3B0aW9uczogDQogIG1hcmtkb3duOiANCiAgICB3cmFwOiA3Mg0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCiMjIElOVFJPRFVDVElPTg0KDQpWYWNjaW5lcyBoYXZlIGJlZW4gaG90bHkgZGViYXRlZCB0aHJvdWdob3V0IHRoZSBwYW5kZW1pYy4gVGhlcmUgYXJlDQpkaWZmZXJlbnQgdGhvdWdodHMgYWJvdXQgZWFjaCB0eXBlIGFuZCBicmFuZCBvZiB2YWNjaW5lLCByYW5naW5nIGZyb20NCnZpZXdzIGFib3V0IHRoZWlyIGVmZmVjdGl2ZW5lc3MgdG8gc2lkZSBlZmZlY3RzIGFuZCBkdXJhdGlvbiBvZg0KcHJvdGVjdGlvbi4gT25lIG9mIHRoZSBtb3N0IHN1Y2Nlc3NmdWwgdmFjY2luZXMgdG8gZGF0ZSBpcw0KUGZpemVyLUJpb05UZWNoLCB3aGljaCBoYXMgYmVlbiBwYXJ0IG9mIHRoZSBjb250cm92ZXJzeSBhcyB3ZWxsLg0KRW5jb3VudGVyaW5nIGEgZGF0YWJhc2Ugb2YgdHdlZXRzIGFib3V0IFBmaXplci1CaW9OVGVjaCB2YWNjaW5lcywgSQ0KdGhvdWdodCBpdCB3b3VsZCBiZSBpbnRlcmVzdGluZyB0byBhbmFseXplIHRoZW0gdGhyb3VnaCB3b3JkIG5ldHdvcmtzIHRvDQpzZWUgd2hpY2gga2V5d29yZHMvdG9waWNzIHdlcmUgbW9zdCBkaXNjdXNzZWQgYW5kIGhvdyB0aGV5IHJlbGF0ZWQgdG8NCmVhY2ggb3RoZXIuDQoNCiMjIyBTZXQgVXANCg0KRmlyc3QsIHdlIGxvYWQgbGlicmFyaWVzIHRoYXQgd2UgbmVlZCBpbiB0aGUgZm9sbG93aW5nIHN0ZXBzLg0KDQpgYGB7ciBsb2FkLXBhY2thZ2VzLCBtZXNzYWdlPUZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXRleHQpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGlncmFwaCkNCmxpYnJhcnkoZ2dyYXBoKQ0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBXUkFOR0xFDQoNCiMjIEltcG9ydCBEYXRhDQoNCk5vdyBsZXQncyByZWFkIGEgZGF0YXNldCBvZiB0aGUgdHdlZXRzIGFib3V0IFBmaXplciBvciBCaW9OVGVjaC4gVGhpcw0KZGF0YXNldCBoYXMgbWFueSBhdHRyaWJ1dGVzLCBzbyBJIG9ubHkgc2VsZWN0IHRoZSBjb2x1bW4gInRleHQiIHdoaWNoDQpjb250YWlucyB0d2VldHMgYW5kIHRoZSBjb2x1bW4gInVzZXJfbmFtZSIuDQoNCmBgYHtyIHJlYWQtY3N2fQ0KdmFjY2luYXRpb24gPC0gcmVhZF9jc3YoImRhdGEvdmFjY2luYXRpb25fdHdlZXRzLmNzdiIpDQp2YWNjaW5hdGlvbiA8LSBzZWxlY3QodmFjY2luYXRpb24sdXNlcl9uYW1lLHRleHQpDQogDQojIHJlbW92ZV93b3Jkc19mcm9tX3RleHQgPC0gZnVuY3Rpb24odGV4dCkgew0KIyAgIHRleHQgPC0gdW5saXN0KHN0cnNwbGl0KHRvbG93ZXIodGV4dCksICIgIikpDQojICAgcGFzdGUodGV4dFshdGV4dCAlaW4lIHdvcmRzX3RvX3JlbW92ZV0sIGNvbGxhcHNlID0gIiAiKQ0KIyB9DQojIA0KIyB3b3Jkc190b19yZW1vdmUgPC0gc3RvcF93b3JkcyR3b3JkDQojIHZhY2NpbmF0aW9uJHRleHQgPC0gbGFwcGx5KHZhY2NpbmF0aW9uJHRleHQsIHJlbW92ZV93b3Jkc19mcm9tX3RleHQpDQoNCg0KYGBgDQoNCiMjIyBUb2tlbml6aW5nIHRleHQgaW50byBiaWdyYW1zDQoNCkluIHRoaXMgc3RlcCwgd2Ugd2lsbCB0b2tlbml6ZSB0d2VldHMgaW50byBiaWdyYW1zLg0KDQpgYGB7ciB0b2tlbml6ZX0NCg0KIGN0X2JpZ3JhbXMgPC0gdmFjY2luYXRpb24gJT4lDQogICB1bm5lc3RfdG9rZW5zKGJpZ3JhbSwgdGV4dCwgdG9rZW4gPSAibmdyYW1zIiwgbiA9IDIpDQoNCmBgYA0KDQpUaGVyZSBhcmUgMTkxNzUzIGJpZ3JhbXMuIE5vdyBsZXQncyBkbyBhIHF1aWNrIGNvdW50IHRvIHNlZSBjb21tb24NCmJpZ3JhbXM6DQoNCmBgYHtyIGNvdW50LWJpZ3JhbXN9DQoNCmN0X2JpZ3JhbXMgJT4lDQogIGNvdW50KGJpZ3JhbSwgc29ydCA9IFRSVUUpDQpgYGANCg0KQXMgd2Ugc2VlLCBzb21lIHN0b3Agd29yZHMgYXBwZWFyZWQgaW4gY29tbW9uIGJpZ3JhbXMsIHNvIHdlIG5lZWQgdG8NCnJlbW92ZSB0aGVzZSB3b3Jkcy4NCg0KYGBge3IgcmVtb3ZlIHN0b3Agd29yZHN9DQoNCg0KYmlncmFtc19zZXBhcmF0ZWQgPC0gY3RfYmlncmFtcyAlPiUNCiAgc2VwYXJhdGUoYmlncmFtLCBjKCJ3b3JkMSIsICJ3b3JkMiIpLCBzZXAgPSAiICIpDQoNCg0KYmlncmFtc19maWx0ZXJlZCA8LSBiaWdyYW1zX3NlcGFyYXRlZCAlPiUNCiAgZmlsdGVyKCF3b3JkMSAlaW4lIHN0b3Bfd29yZHMkd29yZCkgJT4lDQogIGZpbHRlcighd29yZDIgJWluJSBzdG9wX3dvcmRzJHdvcmQpIA0KDQpiaWdyYW1fY291bnRzIDwtIGJpZ3JhbXNfZmlsdGVyZWQgJT4lIA0KICBjb3VudCh3b3JkMSwgd29yZDIsIHNvcnQgPSBUUlVFKQ0KDQpiaWdyYW1fY291bnRzDQpgYGANCg0KTm93LCBpbiBiaWdyYW1fY291bnRzLCBhbGwgc3RvcCB3b3JkcyBhcmUgcmVtb3ZlZC4NCg0KV2UgY2FuIGFsc28gY29tYmluZSB0aGUgc2VwYXJhdGVkIHdvcmRzIHdpdGggYHVuaXRlYDoNCg0KYGBge3IgdW5pdGUgYmlncmFtc30NCmJpZ3JhbXNfdW5pdGVkIDwtIGJpZ3JhbXNfZmlsdGVyZWQgJT4lDQogIHVuaXRlKGJpZ3JhbSwgd29yZDEsIHdvcmQyLCBzZXAgPSAiICIpDQoNCmJpZ3JhbXNfdW5pdGVkDQpgYGANCg0KIyMgVklTVUFMSVpFIFdPUkQgTkVUV09SSw0KDQpXZSBuZWVkIHRvIHRyYW5zZm9ybSBvdXIgZGF0YXNldCAoYmlncmFtX2NvdW50cykgaW50byB0aGVzZSB2YXJpYWJsZXMgaW4NCnRoZSBmb2xsb3dpbmcgd2F5OiBgZnJvbWAgaXMgdGhlICJ3b3JkMSIsIGB0b2AgaXMgdGhlICJ3b3JkMiIsIGFuZA0KYHdlaWdodGAgaXMgIm4iLg0KDQpMZXQncyB1c2UgYGdyYXBoX2Zyb21fZGF0YV9mcmFtZWAgdG8gbWFrZSB0aGUgdHJhbnNmb3JtYXRpb246DQoNCmBgYHtyIHRyYW5mb3JtIGRhdGEgZm9yIHZpc3VhbGl6aW5nIHdvcmQgbmV0fQ0KYmlncmFtX2dyYXBoIDwtIGJpZ3JhbV9jb3VudHMgJT4lDQogIGdyYXBoX2Zyb21fZGF0YV9mcmFtZSgpDQoNCmJpZ3JhbV9ncmFwaA0KYGBgDQoNCkJhc2VkIG9uIHRoZSBoaWdoIG51bWJlciBvZiBiaWdyYW1zLCBJIGRlY2lkZWQgdG8gcmVtb3ZlIHRob3NlIHdpdGggYQ0Kbm9uc2lnbmlmaWNhbnQgbnVtYmVyIG9mIG9jY3VycmVuY2UuIFNvIEkgdHJpZWQgZGlmZmVyZW50IG51bWJlcnMgYW5kDQpmb3VuZCBvdXQgdGhhdCB3ZSB3b3VsZCBvbmx5IG5lZWQgdG8ga2VlcCB0aG9zZSBhcHBlYXJpbmcgbW9yZSB0aGFuIDQwDQp0aW1lcy4NCg0KYGBge3IgZmlsdGVyIGluZnJlcXVlbnQgYmlncmFtc30NCmJpZ3JhbV9ncmFwaF9maWx0ZXJlZCA8LSBiaWdyYW1fY291bnRzICU+JQ0KICBmaWx0ZXIobiA+IDQwKSAlPiUNCiAgZ3JhcGhfZnJvbV9kYXRhX2ZyYW1lKCkNCg0KYmlncmFtX2dyYXBoX2ZpbHRlcmVkDQpgYGANCg0KYGBge3IgdmlzdWFsaXplIGZpbHRlcmVkIG5ldH0NCnNldC5zZWVkKDEwMCkNCg0KYSA8LSBncmlkOjphcnJvdyh0eXBlID0gImNsb3NlZCIsIGxlbmd0aCA9IHVuaXQoLjIsICJpbmNoZXMiKSkNCg0KZ2dyYXBoKGJpZ3JhbV9ncmFwaF9maWx0ZXJlZCwgbGF5b3V0ID0gImZyIikgKw0KICBnZW9tX2VkZ2VfbGluayhhZXMoZWRnZV9hbHBoYSA9IG4pLCBzaG93LmxlZ2VuZCA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICBhcnJvdyA9IGEsIGVuZF9jYXAgPSBjaXJjbGUoLjA3LCAnaW5jaGVzJykpICsNCiAgZ2VvbV9ub2RlX3BvaW50KGNvbG9yID0gInllbGxvdyIsIHNpemUgPSA1KSArDQogIGdlb21fbm9kZV90ZXh0KGFlcyhsYWJlbCA9IG5hbWUpLCB2anVzdCA9IDEsIGhqdXN0ID0gMSkgKw0KICB0aGVtZV92b2lkKCkNCmBgYA0KDQojIyAqKkNPTkNMVVNJT04qKg0KDQpUaGUgcmVzdWx0IG9idGFpbmVkIHVzaW5nIHRoZSB3b3JkIG5ldHdvcmsgaGF2ZSBiZWVuIHdheSBtb3JlDQppbnRlcmVzdGluZyB0aGFuIEkgYW50aWNpcGF0ZWQgYmVmb3JlIGNvbmR1Y3RpbmcgdGhpcyBzdHVkeS4gSW4gdGhlDQptaWRkbGUgY2x1c3Rlciwgd2hpY2ggaXMgY29tcHJpc2VkIG9mIHRoZSBtb3N0IHJlcGVhdGVkIGJpZ3JhbXMsIHRoZQ0KbmFtZSBvZiB0aGUgbWFpbiBjb21wZXRpdG9ycyBvZiBQZml6ZXIgY2FuIGJlIHNlZW46ICJNb2Rlcm5hIFZhY2NpbmUiDQphbmQgIkFzdHJhWmVuZWNhIHZhY2NpbmUiLiBUaGlzIHNob3dzIHRoYXQgcGVvcGxlIHVzZSB0aGUgbmFtZSBvZiB0aGVzZQ0KYnJhbmRzIGluIHRoZWlyIHR3ZWV0cyBhYm91dCBQZml6ZXIsIHBvdGVudGlhbGx5IGZvciBtYWtpbmcgY29tcGFyaXNvbnMNCm9yIHNob3dpbmcgcHJlZmVyZW5jZS4gVGhlIGNvdW50IG9mIGRvc2VzIGNhbiBiZSBhbHNvIHNlZW4gYnkgd2hpY2ggd2UNCmNhbiBzZWUgdGhlIG51bWJlciBvZiBkb3NlcyBwZW9wbGUgZ2V0IG9yIG5lZWQgdG8gcmVjZWl2ZSBoYXMgYmVlbg0KaGlnaGx5IHdyaXR0ZW4gaW4gdGhlaXIgdHdlZXRzLiBBbm90aGVyIGludGVyZXN0aW5nIGFycm93IGlzICJ2YWNjaW5lDQphcHByb3ZlZCIgd2hpY2ggYWdhaW4gc2hvd3MgdGhlIHB1YmxpYyBhdHRlbnRpb24gdG93YXJkcyB0aGUgYXBwcm92YWwgb2YNCnZhY2NpbmVzLg0KDQpJbiBvdGhlciBjbHVzdGVycywgInNvYXIgYXJtIiBpcyBzbyBpbnRlcmVzdGluZyB3aGljaCBoYXMgYmVlbiBoaWdobHkNCnR3ZWV0ZWQgaW5kaWNhdGluZyB0aGUgaGlnaCBmb2N1cyBvbiB0aGlzIHNpZGUgZWZmZWN0IG9mIFBmaXplcg0KdmFjY2luZXMuIEFsc28gInByb3RlY3RpdmUgbWVhc3VyZXMiIGluY2x1ZGluZyBjb21wbGVtZW50YXJ5IHRpcHMgYWJvdXQNCnByb3RlY3RpbmcgYWdhaW5zdCBDT1ZJRCBhbmQgc3RheWluZyBzYWZlIGhhdmUgYmVlbiB0d2VldGVkIHNvIG1hbnkNCnRpbWVzLiBPbmUgYW5vdGhlciBjb21iaW5hdGlvbiB0aGF0IEkgcmVhbGx5IGxpa2VkIGlzICJyZW1lbWJlciAyMDIxIg0Kd2hpY2ggc2hvd3MgaG93IHRoZSB5ZWFyIDIwMjEgd2lsbCByZW1haW4gaW4gdGhlIG1lbW9yeSBvZiBwZW9wbGUuDQoNClRvIGNvbmNsdWRlLCB3b3JkIG5ldHdvcmsgc2VlbXMgdG8gYmUgYWJsZSB0byBkZXJpdmUgbWVhbmluZ2Z1bA0KcmVsYXRpb25zaGlwcyBmcm9tIGEgY29ycHVzIHdoaWNoIHdvdWxkIGJlIGhpZ2hseSB1c2VmdWwgZm9yIGdldHRpbmcNCmluc2lnaHRzIGludG8gYSBsYXJnZSBhbW91bnQgb2YgdGV4dC4NCg==