Analysis of Comments from VK

Install packages

Prepare text for analysis

# Read the text file from local machine , choose file interactively
text <- readLines("vk_text_t.csv")
# Load the data as a corpus
TextDoc <- Corpus(VectorSource(text))
 #Replacing "/", "@" and "|" with space
toSpace <- content_transformer(function (x , pattern ) gsub(pattern, " ", x))
TextDoc <- tm_map(TextDoc, toSpace, "/")
TextDoc <- tm_map(TextDoc, toSpace, "@")
TextDoc <- tm_map(TextDoc, toSpace, "\\|")
# Convert the text to lower case
TextDoc <- tm_map(TextDoc, content_transformer(tolower))
# Remove numbers
TextDoc <- tm_map(TextDoc, removeNumbers)
# Remove english common stopwords
TextDoc <- tm_map(TextDoc, removeWords, stopwords("english"))
# Remove your own stop word
# specify your custom stopwords as a character vector
TextDoc <- tm_map(TextDoc, removeWords, c("s", "company", "team")) 
# Remove punctuation
TextDoc <- tm_map(TextDoc, removePunctuation)
# Eliminate extra white spaces
TextDoc <- tm_map(TextDoc, stripWhitespace)
# Text stemming - which reduces words to their root form
TextDoc <- tm_map(TextDoc, stemDocument)

Build a term document matrix

# Build a term-document matrix
TextDoc_dtm <- TermDocumentMatrix(TextDoc)
dtm_m <- as.matrix(TextDoc_dtm)

Identify most frequently used words

# Sort by descending value of frequency
dtm_v <- sort(rowSums(dtm_m),decreasing=TRUE)
dtm_d <- data.frame(word = names(dtm_v),freq=dtm_v)
# Plot the most frequent words
barplot(dtm_d[1:50,]$freq, las = 2, names.arg = dtm_d[1:50,]$word,
        col ="lightgreen", main ="Top 50 most frequent words",
        ylab = "Word frequencies")

Word cloud of top 150 words

#generate word cloud
set.seed(1234)
wordcloud(words = dtm_d$word, freq = dtm_d$freq, min.freq = 5,
          max.words=150, random.order=FALSE, rot.per=0.40, 
          colors=brewer.pal(8, "Dark2"))

Find associations between words

# Find associations 
findAssocs(TextDoc_dtm, terms = c("putin","ukraine","ukrainian","power","war","russia","russian","prigozhin","money","pay","work","job","food","children","death"), corlimit = 0.35)
[WARNING] This document format requires a nonempty <title> element.
  Defaulting to 'vk.knit' as the title.
  To specify a title, use 'title' in metadata or --metadata title="...".
$putin
   kalugin     kudrin   kussinen   liberman   ppoibwug   umohgsuu       gref      youtu nabiullina     chubai 
      0.38       0.38       0.38       0.38       0.38       0.38       0.37       0.37       0.37       0.36 
  yakovlev 
      0.36 

$ukraine
numeric(0)

$ukrainian
 ”kennedi dishonest 
     0.42      0.38 

$power
numeric(0)

$war
numeric(0)

$russia
numeric(0)

$russian
feder 
 0.46 

$prigozhin
yevgeni 
   0.41 

$money
numeric(0)

$pay
numeric(0)

$work
numeric(0)

$job
numeric(0)

$food
numeric(0)

$children
infant 
  0.36 

$death
numeric(0)
gc()
            used   (Mb) gc trigger   (Mb)  max used   (Mb)
Ncells   1769130   94.5    4543567  242.7   4543567  242.7
Vcells 385726429 2942.9 1107033624 8446.0 780303040 5953.3
# Find associations for words that occur at least 1480 times
findAssocs(TextDoc_dtm, terms = findFreqTerms(TextDoc_dtm, lowfreq = 1480), corlimit = 0.35)
[WARNING] This document format requires a nonempty <title> element.
  Defaulting to 'vk.knit' as the title.
  To specify a title, use 'title' in metadata or --metadata title="...".
$creatur
numeric(0)

$even
numeric(0)

$know
numeric(0)

$like
numeric(0)

$live
numeric(0)

$peopl
numeric(0)

$putin
   kalugin     kudrin   kussinen   liberman   ppoibwug   umohgsuu       gref      youtu nabiullina     chubai 
      0.38       0.38       0.38       0.38       0.38       0.38       0.37       0.37       0.37       0.36 
  yakovlev 
      0.36 

$russian
feder 
 0.46 

$will
numeric(0)

$fool
numeric(0)

$russia
numeric(0)

$ukrain
 arm 
0.35 

$war
numeric(0)

$world
numeric(0)

$year
 old 
0.42 

$need
numeric(0)

$power
numeric(0)

$everyth
numeric(0)

$one
numeric(0)

$time
numeric(0)

$author
numeric(0)

$just
numeric(0)

$can
numeric(0)

$now
numeric(0)

$countri
numeric(0)

$want
numeric(0)

$well
numeric(0)

$idiot
numeric(0)

$fuck
numeric(0)

Evaluate sentiments

Evaluation emotion

# run nrc sentiment analysis to return data frame with each row classified as one of the following
# emotions, rather than a score: 
# anger, anticipation, disgust, fear, joy, sadness, surprise, trust 
# It also counts the number of positive and negative emotions found in each row
d<-get_nrc_sentiment(text)
# head(d,10) - to see top 10 lines of the get_nrc_sentiment dataframe
head (d,10)
#transpose
td<-data.frame(t(d))
#The function rowSums computes column sums across rows for each level of a grouping variable.
td_new <- data.frame(rowSums(td[2:14809]))
#Transformation and cleaning
names(td_new)[1] <- "count"
td_new <- cbind("sentiment" = rownames(td_new), td_new)
rownames(td_new) <- NULL
td_new2<-td_new[1:8,]
#Plot One - count of words associated with each sentiment
quickplot(sentiment, data=td_new2, weight=count, geom="bar", fill=sentiment, ylab="count")+ggtitle("Sentiments in Comments on VK")

#Plot two - count of words associated with each sentiment, expressed as a percentage
barplot(
  sort(colSums(prop.table(d[, 1:8]))), 
  horiz = TRUE, 
  cex.names = 0.7, 
  las = 1, 
  main = "Emotions in Text from VK Comments", xlab="Percentage"
)

library(DT)
library(readr)
vk_text_t <- read_csv("vk_text_t.csv", col_types = cols(...1 = col_skip()))
datatable(vk_text_t)
LS0tDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KLS0tDQoNCiMgQW5hbHlzaXMgb2YgQ29tbWVudHMgZnJvbSBWSyB7LnVubnVtYmVyZWR9DQoNCiMjIyBJbnN0YWxsIHBhY2thZ2VzDQoNCmBgYHtyIHBhY2thZ2VzLCBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KIyBJbnN0YWxsDQppbnN0YWxsLnBhY2thZ2VzKCJ0bSIpICAjIGZvciB0ZXh0IG1pbmluZw0KaW5zdGFsbC5wYWNrYWdlcygiU25vd2JhbGxDIikgIyBmb3IgdGV4dCBzdGVtbWluZw0KaW5zdGFsbC5wYWNrYWdlcygid29yZGNsb3VkIikgIyB3b3JkLWNsb3VkIGdlbmVyYXRvciANCmluc3RhbGwucGFja2FnZXMoIlJDb2xvckJyZXdlciIpICMgY29sb3IgcGFsZXR0ZXMNCmluc3RhbGwucGFja2FnZXMoInN5dXpoZXQiKSAjIGZvciBzZW50aW1lbnQgYW5hbHlzaXMNCmluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKSAjIGZvciBwbG90dGluZyBncmFwaHMNCmluc3RhbGwucGFja2FnZXMoIkRUIikgIyBmb3IgZGlzcGxheWluZyB0YWJsZQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIExvYWQNCmxpYnJhcnkoInRtIikNCmxpYnJhcnkoIlNub3diYWxsQyIpDQpsaWJyYXJ5KCJ3b3JkY2xvdWQiKQ0KbGlicmFyeSgiUkNvbG9yQnJld2VyIikNCmxpYnJhcnkoInN5dXpoZXQiKQ0KbGlicmFyeSgiZ2dwbG90MiIpDQpgYGANCg0KIyMjIFByZXBhcmUgdGV4dCBmb3IgYW5hbHlzaXMNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCiMgUmVhZCB0aGUgdGV4dCBmaWxlIGZyb20gbG9jYWwgbWFjaGluZSAsIGNob29zZSBmaWxlIGludGVyYWN0aXZlbHkNCnRleHQgPC0gcmVhZExpbmVzKCJ2a190ZXh0X3QuY3N2IikNCiMgTG9hZCB0aGUgZGF0YSBhcyBhIGNvcnB1cw0KVGV4dERvYyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRleHQpKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQogI1JlcGxhY2luZyAiLyIsICJAIiBhbmQgInwiIHdpdGggc3BhY2UNCnRvU3BhY2UgPC0gY29udGVudF90cmFuc2Zvcm1lcihmdW5jdGlvbiAoeCAsIHBhdHRlcm4gKSBnc3ViKHBhdHRlcm4sICIgIiwgeCkpDQpUZXh0RG9jIDwtIHRtX21hcChUZXh0RG9jLCB0b1NwYWNlLCAiLyIpDQpUZXh0RG9jIDwtIHRtX21hcChUZXh0RG9jLCB0b1NwYWNlLCAiQCIpDQpUZXh0RG9jIDwtIHRtX21hcChUZXh0RG9jLCB0b1NwYWNlLCAiXFx8IikNCiMgQ29udmVydCB0aGUgdGV4dCB0byBsb3dlciBjYXNlDQpUZXh0RG9jIDwtIHRtX21hcChUZXh0RG9jLCBjb250ZW50X3RyYW5zZm9ybWVyKHRvbG93ZXIpKQ0KIyBSZW1vdmUgbnVtYmVycw0KVGV4dERvYyA8LSB0bV9tYXAoVGV4dERvYywgcmVtb3ZlTnVtYmVycykNCiMgUmVtb3ZlIGVuZ2xpc2ggY29tbW9uIHN0b3B3b3Jkcw0KVGV4dERvYyA8LSB0bV9tYXAoVGV4dERvYywgcmVtb3ZlV29yZHMsIHN0b3B3b3JkcygiZW5nbGlzaCIpKQ0KIyBSZW1vdmUgeW91ciBvd24gc3RvcCB3b3JkDQojIHNwZWNpZnkgeW91ciBjdXN0b20gc3RvcHdvcmRzIGFzIGEgY2hhcmFjdGVyIHZlY3Rvcg0KVGV4dERvYyA8LSB0bV9tYXAoVGV4dERvYywgcmVtb3ZlV29yZHMsIGMoInMiLCAiY29tcGFueSIsICJ0ZWFtIikpIA0KIyBSZW1vdmUgcHVuY3R1YXRpb24NClRleHREb2MgPC0gdG1fbWFwKFRleHREb2MsIHJlbW92ZVB1bmN0dWF0aW9uKQ0KIyBFbGltaW5hdGUgZXh0cmEgd2hpdGUgc3BhY2VzDQpUZXh0RG9jIDwtIHRtX21hcChUZXh0RG9jLCBzdHJpcFdoaXRlc3BhY2UpDQojIFRleHQgc3RlbW1pbmcgLSB3aGljaCByZWR1Y2VzIHdvcmRzIHRvIHRoZWlyIHJvb3QgZm9ybQ0KVGV4dERvYyA8LSB0bV9tYXAoVGV4dERvYywgc3RlbURvY3VtZW50KQ0KYGBgDQoNCiMjIyBCdWlsZCBhIHRlcm0gZG9jdW1lbnQgbWF0cml4DQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojIEJ1aWxkIGEgdGVybS1kb2N1bWVudCBtYXRyaXgNClRleHREb2NfZHRtIDwtIFRlcm1Eb2N1bWVudE1hdHJpeChUZXh0RG9jKQ0KZHRtX20gPC0gYXMubWF0cml4KFRleHREb2NfZHRtKQ0KYGBgDQoNCiMjIyBJZGVudGlmeSBtb3N0IGZyZXF1ZW50bHkgdXNlZCB3b3Jkcw0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KIyBTb3J0IGJ5IGRlc2NlbmRpbmcgdmFsdWUgb2YgZnJlcXVlbmN5DQpkdG1fdiA8LSBzb3J0KHJvd1N1bXMoZHRtX20pLGRlY3JlYXNpbmc9VFJVRSkNCmR0bV9kIDwtIGRhdGEuZnJhbWUod29yZCA9IG5hbWVzKGR0bV92KSxmcmVxPWR0bV92KQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojIERpc3BsYXkgdGhlIHRvcCA1MDAgbW9zdCBmcmVxdWVudCB3b3Jkcw0KKGhlYWQoZHRtX2QsIDUwMCkpDQoNCiMgdmlldyB0b3AgNTAwDQpsaWJyYXJ5KERUKQ0KbGlicmFyeShyZWFkcikNCnZrX3RvcF81MDAgPC0gcmVhZF9jc3YoInZrX3RvcF81MDAuY3N2IiwgDQogICAgY29sX3R5cGVzID0gY29scyguLi4xID0gY29sX3NraXAoKSkpDQpkYXRhdGFibGUodmtfdG9wXzUwMCkNCmBgYA0KDQpgYGB7ciBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0NCiMgUGxvdCB0aGUgbW9zdCBmcmVxdWVudCB3b3Jkcw0KYmFycGxvdChkdG1fZFsxOjUwLF0kZnJlcSwgbGFzID0gMiwgbmFtZXMuYXJnID0gZHRtX2RbMTo1MCxdJHdvcmQsDQogICAgICAgIGNvbCA9ImxpZ2h0Z3JlZW4iLCBtYWluID0iVG9wIDUwIG1vc3QgZnJlcXVlbnQgd29yZHMiLA0KICAgICAgICB5bGFiID0gIldvcmQgZnJlcXVlbmNpZXMiKQ0KYGBgDQoNCiMjIyBXb3JkIGNsb3VkIG9mIHRvcCAxNTAgd29yZHMNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCiNnZW5lcmF0ZSB3b3JkIGNsb3VkDQpzZXQuc2VlZCgxMjM0KQ0Kd29yZGNsb3VkKHdvcmRzID0gZHRtX2Qkd29yZCwgZnJlcSA9IGR0bV9kJGZyZXEsIG1pbi5mcmVxID0gNSwNCiAgICAgICAgICBtYXgud29yZHM9MTUwLCByYW5kb20ub3JkZXI9RkFMU0UsIHJvdC5wZXI9MC40MCwgDQogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOCwgIkRhcmsyIikpDQpgYGANCg0KIyMjIEZpbmQgYXNzb2NpYXRpb25zIGJldHdlZW4gd29yZHMNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCiMgRmluZCBhc3NvY2lhdGlvbnMgDQpmaW5kQXNzb2NzKFRleHREb2NfZHRtLCB0ZXJtcyA9IGMoInB1dGluIiwidWtyYWluZSIsInVrcmFpbmlhbiIsInBvd2VyIiwid2FyIiwicnVzc2lhIiwicnVzc2lhbiIsInByaWdvemhpbiIsIm1vbmV5IiwicGF5Iiwid29yayIsImpvYiIsImZvb2QiLCJjaGlsZHJlbiIsImRlYXRoIiksIGNvcmxpbWl0ID0gMC4zNSkNCmBgYA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBGaW5kIGFzc29jaWF0aW9ucyBmb3Igd29yZHMgdGhhdCBvY2N1ciBhdCBsZWFzdCAxNDgwIHRpbWVzDQpmaW5kQXNzb2NzKFRleHREb2NfZHRtLCB0ZXJtcyA9IGZpbmRGcmVxVGVybXMoVGV4dERvY19kdG0sIGxvd2ZyZXEgPSAxNDgwKSwgY29ybGltaXQgPSAwLjM1KQ0KYGBgDQoNCiMjIyBFdmFsdWF0ZSBzZW50aW1lbnRzDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojIHJlZ3VsYXIgc2VudGltZW50IHNjb3JlIHVzaW5nIGdldF9zZW50aW1lbnQoKSBmdW5jdGlvbiBhbmQgbWV0aG9kIG9mIHlvdXIgY2hvaWNlDQojIHBsZWFzZSBub3RlIHRoYXQgZGlmZmVyZW50IG1ldGhvZHMgbWF5IGhhdmUgZGlmZmVyZW50IHNjYWxlcw0Kc3l1emhldF92ZWN0b3IgPC0gZ2V0X3NlbnRpbWVudCh0ZXh0LCBtZXRob2Q9InN5dXpoZXQiKQ0KIyBzZWUgdGhlIGZpcnN0IHJvdyBvZiB0aGUgdmVjdG9yDQpoZWFkKHN5dXpoZXRfdmVjdG9yKQ0KIyBzZWUgc3VtbWFyeSBzdGF0aXN0aWNzIG9mIHRoZSB2ZWN0b3INCnN1bW1hcnkoc3l1emhldF92ZWN0b3IpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCiMgYmluZw0KYmluZ192ZWN0b3IgPC0gZ2V0X3NlbnRpbWVudCh0ZXh0LCBtZXRob2Q9ImJpbmciKQ0KaGVhZChiaW5nX3ZlY3RvcikNCnN1bW1hcnkoYmluZ192ZWN0b3IpDQojYWZmaW4NCmFmaW5uX3ZlY3RvciA8LSBnZXRfc2VudGltZW50KHRleHQsIG1ldGhvZD0iYWZpbm4iKQ0KaGVhZChhZmlubl92ZWN0b3IpDQpzdW1tYXJ5KGFmaW5uX3ZlY3RvcikNCmBgYA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KI2NvbXBhcmUgdGhlIGZpcnN0IHJvdyBvZiBlYWNoIHZlY3RvciB1c2luZyBzaWduIGZ1bmN0aW9uDQpyYmluZCgNCiAgc2lnbihoZWFkKHN5dXpoZXRfdmVjdG9yKSksDQogIHNpZ24oaGVhZChiaW5nX3ZlY3RvcikpLA0KICBzaWduKGhlYWQoYWZpbm5fdmVjdG9yKSkNCikNCmBgYA0KDQojIyMgRXZhbHVhdGlvbiBlbW90aW9uDQoNCmBgYHtyIGVtb3Rpb24sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojIHJ1biBucmMgc2VudGltZW50IGFuYWx5c2lzIHRvIHJldHVybiBkYXRhIGZyYW1lIHdpdGggZWFjaCByb3cgY2xhc3NpZmllZCBhcyBvbmUgb2YgdGhlIGZvbGxvd2luZw0KIyBlbW90aW9ucywgcmF0aGVyIHRoYW4gYSBzY29yZTogDQojIGFuZ2VyLCBhbnRpY2lwYXRpb24sIGRpc2d1c3QsIGZlYXIsIGpveSwgc2FkbmVzcywgc3VycHJpc2UsIHRydXN0IA0KIyBJdCBhbHNvIGNvdW50cyB0aGUgbnVtYmVyIG9mIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSBlbW90aW9ucyBmb3VuZCBpbiBlYWNoIHJvdw0KZDwtZ2V0X25yY19zZW50aW1lbnQodGV4dCkNCiMgaGVhZChkLDEwKSAtIHRvIHNlZSB0b3AgMTAgbGluZXMgb2YgdGhlIGdldF9ucmNfc2VudGltZW50IGRhdGFmcmFtZQ0KaGVhZCAoZCwxMCkNCmBgYA0KDQpgYGB7ciBzZW50aW1lbnRzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1GQUxTRX0NCiN0cmFuc3Bvc2UNCnRkPC1kYXRhLmZyYW1lKHQoZCkpDQojVGhlIGZ1bmN0aW9uIHJvd1N1bXMgY29tcHV0ZXMgY29sdW1uIHN1bXMgYWNyb3NzIHJvd3MgZm9yIGVhY2ggbGV2ZWwgb2YgYSBncm91cGluZyB2YXJpYWJsZS4NCnRkX25ldyA8LSBkYXRhLmZyYW1lKHJvd1N1bXModGRbMjoxNDgwOV0pKQ0KI1RyYW5zZm9ybWF0aW9uIGFuZCBjbGVhbmluZw0KbmFtZXModGRfbmV3KVsxXSA8LSAiY291bnQiDQp0ZF9uZXcgPC0gY2JpbmQoInNlbnRpbWVudCIgPSByb3duYW1lcyh0ZF9uZXcpLCB0ZF9uZXcpDQpyb3duYW1lcyh0ZF9uZXcpIDwtIE5VTEwNCnRkX25ldzI8LXRkX25ld1sxOjgsXQ0KI1Bsb3QgT25lIC0gY291bnQgb2Ygd29yZHMgYXNzb2NpYXRlZCB3aXRoIGVhY2ggc2VudGltZW50DQpxdWlja3Bsb3Qoc2VudGltZW50LCBkYXRhPXRkX25ldzIsIHdlaWdodD1jb3VudCwgZ2VvbT0iYmFyIiwgZmlsbD1zZW50aW1lbnQsIHlsYWI9ImNvdW50IikrZ2d0aXRsZSgiU2VudGltZW50cyBpbiBDb21tZW50cyBvbiBWSyIpDQoNCmBgYA0KDQpgYGB7ciBzZW50aW1lbnRfdmssIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PVRSVUV9DQojUGxvdCB0d28gLSBjb3VudCBvZiB3b3JkcyBhc3NvY2lhdGVkIHdpdGggZWFjaCBzZW50aW1lbnQsIGV4cHJlc3NlZCBhcyBhIHBlcmNlbnRhZ2UNCmJhcnBsb3QoDQogIHNvcnQoY29sU3Vtcyhwcm9wLnRhYmxlKGRbLCAxOjhdKSkpLCANCiAgaG9yaXogPSBUUlVFLCANCiAgY2V4Lm5hbWVzID0gMC43LCANCiAgbGFzID0gMSwgDQogIG1haW4gPSAiRW1vdGlvbnMgaW4gVGV4dCBmcm9tIFZLIENvbW1lbnRzIiwgeGxhYj0iUGVyY2VudGFnZSINCikNCmBgYA0KDQpgYGB7ciB2aWV3LCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1UUlVFfQ0KbGlicmFyeShEVCkNCmxpYnJhcnkocmVhZHIpDQp2a190ZXh0X3QgPC0gcmVhZF9jc3YoInZrX3RleHRfdC5jc3YiLCBjb2xfdHlwZXMgPSBjb2xzKC4uLjEgPSBjb2xfc2tpcCgpKSkNCmRhdGF0YWJsZSh2a190ZXh0X3QpDQpgYGANCg==