Student ID: 1A182901-2


  1. Set up
rm(list=ls(all=TRUE))
setwd("~/Desktop/R/polimetrics")
library(rtweet)
library(ggplot2)
library(dplyr)
library(quanteda)
library(rtweet)
library(ggplot2)
library(lattice)
library(syuzhet)
library(stm)
library(lubridate)

0.1. In the first time (Run in 11/14 evening)

token <- create_token(
  app = "yenchenghsuan",
  consumer_key = "VUk6UDizyDpi9xoUvcPqt2gFR", 
  consumer_secret = "e3X5JwD029oD8WymQgkVOwEdVK75EgrultGUOv2psyqBZcIxYL", 
  access_token = "1062396813330632704-DBt0K0EKo3BbJExDt2cIMgwELL8xso",
  access_secret = "lUrbH9KGsl8C2hi6UTPDAgymEt9o5je4MSHaso4EeLS8t")
#Run in 11/14 evening:
  #trumptweet <- get_timeline("realDonaldTrump", n = 3200)
  #trumptweet1 <- trumptweet[1:3000,]
  #write_as_csv(trumptweet1, "trumptweet.csv", prepend_ids = TRUE, na = "", fileEncoding = "UTF-8")
  1. Import data
trumptweet_n <- read.csv("trumptweet.csv",encoding = "UTF-8")
trumptweet_n$created_at_posixit <- as.POSIXct(trumptweet_n$created_at)
trumptweet_n$created_at <- as.numeric(as.Date(trumptweet_n$created_at))
since <- trumptweet_n$created_at_posixit[3000]
latest <- trumptweet_n$created_at_posixit[1]
trumptweet_n_f <- select(trumptweet_n,
                         status_id,
                         created_at,
                         created_at_posixit,
                         text)
trumptweet_n_f$text <- as.character(trumptweet_n_f$text)
mycorpus <- corpus(trumptweet_n_f)
cat("Twitter data","\n",paste("From:",since),"\n",paste("  To:",latest))
Twitter data 
 From: 2018-01-04 11:37:46 
   To: 2018-11-13 21:35:42

  1. Dictionaries
tweetdfm <- dfm(mycorpus ,
                remove = stopwords("english"),
                remove_punct = TRUE,
                remove_numbers=TRUE, 
                tolower = TRUE,
                stem = TRUE,
                remove_twitter = TRUE, 
                remove_url = TRUE)
sentiment1 <- dfm(mycorpus ,
                 remove = stopwords("english"),
                 remove_punct = TRUE,
                 remove_numbers=TRUE, 
                 tolower = TRUE,
                 stem = TRUE,
                 remove_twitter = TRUE, 
                 remove_url = TRUE, 
                 dictionary = data_dictionary_LSD2015[1:2])
dictfile <- tempfile()
download.file("https://provalisresearch.com/Download/LaverGarry.zip", dictfile, mode = "wb")
unzip(dictfile, exdir = (td <- tempdir()))
lgdict <- dictionary(file = paste(td, "LaverGarry.cat", sep = "/"))
sentiment2 <- dfm(mycorpus ,
                 remove = stopwords("english"),
                 remove_punct = TRUE,
                 remove_numbers=TRUE, 
                 tolower = TRUE,
                 remove_twitter = TRUE, 
                 remove_url = TRUE, 
                 dictionary = lgdict)
sentimentdf <- convert(sentiment1 , to="data.frame")
sentimentlg <- convert(sentiment2 , to="data.frame")
sentimentdf$value <- sentimentdf$posit-sentimentdf$negat
sentimentdf$Date <- as.Date(trumptweet_n_f$created_at_posixit)
sentimentdf$time <- trumptweet_n_f$created_at_posixit
sentimentdf$month <- month(sentimentdf$Date)
sentimentlg_s <- select(sentimentlg,VALUES.LIBERAL,VALUES.CONSERVATIVE)
sentimentlg_s$Date <- as.Date(trumptweet_n_f$created_at_posixit)
sentimentlg_s$time <- trumptweet_n_f$created_at_posixit
sentimentlg_s$month <- month(sentimentlg_s$Date)
lib <- aggregate(sentimentlg_s$VALUES.LIBERAL, by=list(Category=sentimentlg_s$month), FUN=sum)
con <- aggregate(sentimentlg_s$VALUES.CONSERVATIVE, by=list(Category=sentimentlg_s$month), FUN=sum)
libcon <- data.frame(month=lib$Category,
                     lib=lib$x,
                     con=con$x)

2.1. Plot dictionaries’ result

2.1.A. Trump’s Tweets by month

par(mfrow=c(1,1),mar=c(5.1, 4.1, 4.1, 2.1))
g1 <- ggplot(sentimentdf, aes(month))+
  scale_x_continuous(breaks = 1:11)+
  geom_bar(width = 0.8,fill = "#99CC66")+
  theme_grey()+
  ggtitle("Trump's Tweets by month")+
  theme(plot.title = element_text(hjust = 0.5,size=20))
g1

2.1.B. Sentiment by month

g2 <- ggplot(sentimentdf,aes(x=reorder(month,Date),y=value,group=month))+
  geom_boxplot()+
  xlab("Month")+
  ylab("Value")+
  theme_grey()+
  ggtitle("Sentiment by month")+
  theme(plot.title = element_text(hjust = 0.5,size=20))
g2

2.1.C. Lib-con by month

g3 <- ggplot(libcon,aes(x=month,y=con,color="Conservative"))+
  geom_line()+
  geom_point()+
  geom_line(aes(y=lib,color="Liberal"))+
  geom_point(aes(y=lib,color="Liberal"))+
  scale_x_continuous(breaks = 1:11)+
  ylab("Frequency")+
  theme_grey()+
  ggtitle("Lib-con by month")+
  theme(plot.title = element_text(hjust = 0.5,size=18))+
  labs(color="") 
g3


  1. STM

3.1. SearchK at the fisrt time (NOT run it here)

#K <-c(4,5,6,7,8,9)
#storage  <- searchK(Dfm_stm$documents,
#                    Dfm_stm$vocab,
#                    K = K,
#                    max.em.its = 50,
#                    prevalence = ~ created_at,
#                    data = Dfm_stm$meta,
#                    init.type = "Spectral")
#plot(storage$results$semcoh,
#     storage$results$exclus,
#     xlab= "Semantic coherence",
#     ylab= "Exclusivity",
#     col= "blue",
#     pch = 19,
#     cex = 1,
#     lty = "solid",
#     lwd = 2)
#text(storage$results$semcoh,
#     storage$results$exclus,
#     labels=storage$results$K,
#     cex= 1,
#     pos=2)

3.2. STM

Dfm_stm <- convert(tweetdfm, to = "stm")
stmFitted1 <- stm(Dfm_stm$documents,
                  Dfm_stm$vocab,
                  K = 7,
                  max.em.its = 100,
                  prevalence = ~ created_at,
                  data = Dfm_stm$meta,
                  init.type = "Spectral")

3.3. Result of Topic Prevalence

3.3.A. Summary of topics

par(mfrow=c(1,1),mar=c(5.1, 4.1, 4.1, 2.1))
plot(stmFitted1, type = "summary", labeltype = c("frex"))

3.3.B. Wordcloud of Topic 4

par(mfrow=c(1,1))
cloud(stmFitted1, topic = 4)

3.3.C. Topic Prevalence across time

w <- labelTopics(stmFitted1, topics = 1, n = 3, frexweight = 0.5)
w_df <- as.data.frame(w$frex)
w_df$sum <- paste(w_df$V1,w_df$V2,w_df$V3,sep = " / ")
prep <- estimateEffect(1:7 ~ created_at, 
                       stmFitted1, 
                       meta = Dfm_stm$meta, 
                       uncertainty = "Global")
par(mfrow=c(2,2),mar=c(2,2,2,2))
for(i in c(1,4,5,6)){
  x <- w_df$sum[i]
  plot(prep, "created_at", method = "continuous", topics = i,
       model = stmFitted1, printlegend = FALSE, xaxt = "n", xlab = "Date",ylab = "")
  seq <- seq(from = min(Dfm_stm$meta$created_at), to = max(Dfm_stm$meta$created_at))
  axis(1, at = seq, labels = c(as.Date(seq,origin="1970/1/1")))
  title(paste("Topic",i,x))
  abline(h=0, col="#99CCFF")
  abline(h=0.1, col="#336699")
  abline(h=0.2, col="#003366")
}


LS0tCnRpdGxlOiAiSG9tZSBBc3NpZ25tZW50IDYiCm91dHB1dDogaHRtbF9ub3RlYm9vawphdXRob3I6IFllbiBDaGVuZyBIc3VhbgotLS0KIyMjI1N0dWRlbnQgSUQ6IDFBMTgyOTAxLTIKKioqCj4wLiBTZXQgdXAKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpybShsaXN0PWxzKGFsbD1UUlVFKSkKc2V0d2QoIn4vRGVza3RvcC9SL3BvbGltZXRyaWNzIikKbGlicmFyeShydHdlZXQpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeShxdWFudGVkYSkKbGlicmFyeShydHdlZXQpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShsYXR0aWNlKQpsaWJyYXJ5KHN5dXpoZXQpCmxpYnJhcnkoc3RtKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKYGBgCgo+MC4xLiBJbiB0aGUgZmlyc3QgdGltZSAoUnVuIGluIDExLzE0IGV2ZW5pbmcpCgpgYGB7ciwgIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnRva2VuIDwtIGNyZWF0ZV90b2tlbigKICBhcHAgPSAieWVuY2hlbmdoc3VhbiIsCiAgY29uc3VtZXJfa2V5ID0gIlZVazZVRGl6eURwaTl4b1V2Y1BxdDJnRlIiLCAKICBjb25zdW1lcl9zZWNyZXQgPSAiZTNYNUp3RDAyOW9EOFd5bVFna1ZPd0VkVks3NUVncnVsdEdVT3YycHN5cUJaY0l4WUwiLCAKICBhY2Nlc3NfdG9rZW4gPSAiMTA2MjM5NjgxMzMzMDYzMjcwNC1EQnQwSzBFS28zQmJKRXhEdDJjSU1nd0VMTDh4c28iLAogIGFjY2Vzc19zZWNyZXQgPSAibFVyYkg5S0dzbDhDMmhpNlVUUERBZ3ltRXQ5bzVqZTRNU0hhc280RWVMUzh0IikKCiNSdW4gaW4gMTEvMTQgZXZlbmluZzoKICAjdHJ1bXB0d2VldCA8LSBnZXRfdGltZWxpbmUoInJlYWxEb25hbGRUcnVtcCIsIG4gPSAzMjAwKQogICN0cnVtcHR3ZWV0MSA8LSB0cnVtcHR3ZWV0WzE6MzAwMCxdCiAgI3dyaXRlX2FzX2Nzdih0cnVtcHR3ZWV0MSwgInRydW1wdHdlZXQuY3N2IiwgcHJlcGVuZF9pZHMgPSBUUlVFLCBuYSA9ICIiLCBmaWxlRW5jb2RpbmcgPSAiVVRGLTgiKQpgYGAKCj4xLiBJbXBvcnQgZGF0YQoKYGBge3J9CnRydW1wdHdlZXRfbiA8LSByZWFkLmNzdigidHJ1bXB0d2VldC5jc3YiLGVuY29kaW5nID0gIlVURi04IikKdHJ1bXB0d2VldF9uJGNyZWF0ZWRfYXRfcG9zaXhpdCA8LSBhcy5QT1NJWGN0KHRydW1wdHdlZXRfbiRjcmVhdGVkX2F0KQp0cnVtcHR3ZWV0X24kY3JlYXRlZF9hdCA8LSBhcy5udW1lcmljKGFzLkRhdGUodHJ1bXB0d2VldF9uJGNyZWF0ZWRfYXQpKQpzaW5jZSA8LSB0cnVtcHR3ZWV0X24kY3JlYXRlZF9hdF9wb3NpeGl0WzMwMDBdCmxhdGVzdCA8LSB0cnVtcHR3ZWV0X24kY3JlYXRlZF9hdF9wb3NpeGl0WzFdCnRydW1wdHdlZXRfbl9mIDwtIHNlbGVjdCh0cnVtcHR3ZWV0X24sCiAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXNfaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVkX2F0LAogICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZF9hdF9wb3NpeGl0LAogICAgICAgICAgICAgICAgICAgICAgICAgdGV4dCkKdHJ1bXB0d2VldF9uX2YkdGV4dCA8LSBhcy5jaGFyYWN0ZXIodHJ1bXB0d2VldF9uX2YkdGV4dCkKbXljb3JwdXMgPC0gY29ycHVzKHRydW1wdHdlZXRfbl9mKQpgYGAKCmBgYHtyfQpjYXQoIlR3aXR0ZXIgZGF0YSIsIlxuIixwYXN0ZSgiRnJvbToiLHNpbmNlKSwiXG4iLHBhc3RlKCIgIFRvOiIsbGF0ZXN0KSkKYGBgCgoqKioKCj4yLiBEaWN0aW9uYXJpZXMKCmBgYHtyIHJlc3VsdHM9ImhpZGUiLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQp0d2VldGRmbSA8LSBkZm0obXljb3JwdXMgLAogICAgICAgICAgICAgICAgcmVtb3ZlID0gc3RvcHdvcmRzKCJlbmdsaXNoIiksCiAgICAgICAgICAgICAgICByZW1vdmVfcHVuY3QgPSBUUlVFLAogICAgICAgICAgICAgICAgcmVtb3ZlX251bWJlcnM9VFJVRSwgCiAgICAgICAgICAgICAgICB0b2xvd2VyID0gVFJVRSwKICAgICAgICAgICAgICAgIHN0ZW0gPSBUUlVFLAogICAgICAgICAgICAgICAgcmVtb3ZlX3R3aXR0ZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgIHJlbW92ZV91cmwgPSBUUlVFKQoKc2VudGltZW50MSA8LSBkZm0obXljb3JwdXMgLAogICAgICAgICAgICAgICAgIHJlbW92ZSA9IHN0b3B3b3JkcygiZW5nbGlzaCIpLAogICAgICAgICAgICAgICAgIHJlbW92ZV9wdW5jdCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgcmVtb3ZlX251bWJlcnM9VFJVRSwgCiAgICAgICAgICAgICAgICAgdG9sb3dlciA9IFRSVUUsCiAgICAgICAgICAgICAgICAgc3RlbSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgcmVtb3ZlX3R3aXR0ZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICByZW1vdmVfdXJsID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgZGljdGlvbmFyeSA9IGRhdGFfZGljdGlvbmFyeV9MU0QyMDE1WzE6Ml0pCgpkaWN0ZmlsZSA8LSB0ZW1wZmlsZSgpCmRvd25sb2FkLmZpbGUoImh0dHBzOi8vcHJvdmFsaXNyZXNlYXJjaC5jb20vRG93bmxvYWQvTGF2ZXJHYXJyeS56aXAiLCBkaWN0ZmlsZSwgbW9kZSA9ICJ3YiIpCnVuemlwKGRpY3RmaWxlLCBleGRpciA9ICh0ZCA8LSB0ZW1wZGlyKCkpKQpsZ2RpY3QgPC0gZGljdGlvbmFyeShmaWxlID0gcGFzdGUodGQsICJMYXZlckdhcnJ5LmNhdCIsIHNlcCA9ICIvIikpCnNlbnRpbWVudDIgPC0gZGZtKG15Y29ycHVzICwKICAgICAgICAgICAgICAgICByZW1vdmUgPSBzdG9wd29yZHMoImVuZ2xpc2giKSwKICAgICAgICAgICAgICAgICByZW1vdmVfcHVuY3QgPSBUUlVFLAogICAgICAgICAgICAgICAgIHJlbW92ZV9udW1iZXJzPVRSVUUsIAogICAgICAgICAgICAgICAgIHRvbG93ZXIgPSBUUlVFLAogICAgICAgICAgICAgICAgIHJlbW92ZV90d2l0dGVyID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgcmVtb3ZlX3VybCA9IFRSVUUsIAogICAgICAgICAgICAgICAgIGRpY3Rpb25hcnkgPSBsZ2RpY3QpCgpzZW50aW1lbnRkZiA8LSBjb252ZXJ0KHNlbnRpbWVudDEgLCB0bz0iZGF0YS5mcmFtZSIpCnNlbnRpbWVudGxnIDwtIGNvbnZlcnQoc2VudGltZW50MiAsIHRvPSJkYXRhLmZyYW1lIikKc2VudGltZW50ZGYkdmFsdWUgPC0gc2VudGltZW50ZGYkcG9zaXQtc2VudGltZW50ZGYkbmVnYXQKc2VudGltZW50ZGYkRGF0ZSA8LSBhcy5EYXRlKHRydW1wdHdlZXRfbl9mJGNyZWF0ZWRfYXRfcG9zaXhpdCkKc2VudGltZW50ZGYkdGltZSA8LSB0cnVtcHR3ZWV0X25fZiRjcmVhdGVkX2F0X3Bvc2l4aXQKc2VudGltZW50ZGYkbW9udGggPC0gbW9udGgoc2VudGltZW50ZGYkRGF0ZSkKCnNlbnRpbWVudGxnX3MgPC0gc2VsZWN0KHNlbnRpbWVudGxnLFZBTFVFUy5MSUJFUkFMLFZBTFVFUy5DT05TRVJWQVRJVkUpCnNlbnRpbWVudGxnX3MkRGF0ZSA8LSBhcy5EYXRlKHRydW1wdHdlZXRfbl9mJGNyZWF0ZWRfYXRfcG9zaXhpdCkKc2VudGltZW50bGdfcyR0aW1lIDwtIHRydW1wdHdlZXRfbl9mJGNyZWF0ZWRfYXRfcG9zaXhpdApzZW50aW1lbnRsZ19zJG1vbnRoIDwtIG1vbnRoKHNlbnRpbWVudGxnX3MkRGF0ZSkKCmxpYiA8LSBhZ2dyZWdhdGUoc2VudGltZW50bGdfcyRWQUxVRVMuTElCRVJBTCwgYnk9bGlzdChDYXRlZ29yeT1zZW50aW1lbnRsZ19zJG1vbnRoKSwgRlVOPXN1bSkKY29uIDwtIGFnZ3JlZ2F0ZShzZW50aW1lbnRsZ19zJFZBTFVFUy5DT05TRVJWQVRJVkUsIGJ5PWxpc3QoQ2F0ZWdvcnk9c2VudGltZW50bGdfcyRtb250aCksIEZVTj1zdW0pCmxpYmNvbiA8LSBkYXRhLmZyYW1lKG1vbnRoPWxpYiRDYXRlZ29yeSwKICAgICAgICAgICAgICAgICAgICAgbGliPWxpYiR4LAogICAgICAgICAgICAgICAgICAgICBjb249Y29uJHgpCmBgYAoKPjIuMS4gUGxvdCBkaWN0aW9uYXJpZXMnIHJlc3VsdAoKIyMjIzIuMS5BLiBUcnVtcCdzIFR3ZWV0cyBieSBtb250aApgYGB7cn0KcGFyKG1mcm93PWMoMSwxKSxtYXI9Yyg1LjEsIDQuMSwgNC4xLCAyLjEpKQpnMSA8LSBnZ3Bsb3Qoc2VudGltZW50ZGYsIGFlcyhtb250aCkpKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSAxOjExKSsKICBnZW9tX2Jhcih3aWR0aCA9IDAuOCxmaWxsID0gIiM5OUNDNjYiKSsKICB0aGVtZV9ncmV5KCkrCiAgZ2d0aXRsZSgiVHJ1bXAncyBUd2VldHMgYnkgbW9udGgiKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LHNpemU9MjApKQpnMQpgYGAKCiogVGhpcyBpcyB0aGUgdG90YWwgb2JzZXJ2YXRpb25zIG9mIHRoZSBmb2xsb3dpbmcgYW5hbHlzaXMsIERvbmFsZCBUcnVtcCBwZXJzb25hbCB0d2l0dGVyIGhhZCBwb3N0ZWQgb3ZlciAxMDAgdHdlZXRzIGV2ZXJ5IG1vbnRoLiBBZnRlciBBcHJpbCwgVHJ1bXAgcG9zdGVkIG1vcmUgdGhhbiAzMDAgdHdlZXRzIHBlciBtb250aC4KCiMjIyMyLjEuQi4gU2VudGltZW50IGJ5IG1vbnRoCmBgYHtyfQpnMiA8LSBnZ3Bsb3Qoc2VudGltZW50ZGYsYWVzKHg9cmVvcmRlcihtb250aCxEYXRlKSx5PXZhbHVlLGdyb3VwPW1vbnRoKSkrCiAgZ2VvbV9ib3hwbG90KCkrCiAgeGxhYigiTW9udGgiKSsKICB5bGFiKCJWYWx1ZSIpKwogIHRoZW1lX2dyZXkoKSsKICBnZ3RpdGxlKCJTZW50aW1lbnQgYnkgbW9udGgiKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LHNpemU9MjApKQpnMgpgYGAKCiogQnkgYXBwbHlpbmcgc2VudGltZW50IGRpY3Rpb25hcnkgaW4gcXVhbnRlZGEsIHRoaXMgYm94IHBsb3Qgc2hvd2VkIHRoZSBzZW50aW1lbnQgb2YgdHdlZXRzIGJ5IG1vbnRoCiAgICAxLiBPdmVyYWxsLCB0aGUgbWVkaWFuIG9mIHR3ZWV0cyB3YXMgcG9zaXRpdmUuCiAgICAyLiBFdmVuIHRob3VnaCB0aGUgaW1hZ2luYXRpb24gb2YgVHJ1bXAgd2FzIGhlIG9mdGVuIHVzZWQgdHdpdHRlciB0byB0aHJlYXRlbiBhbmQgYmxhbWUgaGlzIG9wcG9uZW50LCB0aGUgZ2VuZXJhbCByZXN1bHRzIHdlcmUgbW9yZSBwb3NpdGl2ZSB0d2VldHMgdGhhbiBuZWdhdGl2ZS4gVGhlIHBvc3NpYmxlIGV4cGxhbmF0aW9uIHdhcyBoZSBhbHNvIHVzZWQgYSBsb3Qgb2YgcG9zaXRpdmUgd29yZHMgdG8gc3RyZW5ndGhlbiBhbmQgZGVmZW5kIGhpcyBhY3Rpb25zLgoKIyMjIzIuMS5DLiBMaWItY29uIGJ5IG1vbnRoCmBgYHtyfQpnMyA8LSBnZ3Bsb3QobGliY29uLGFlcyh4PW1vbnRoLHk9Y29uLGNvbG9yPSJDb25zZXJ2YXRpdmUiKSkrCiAgZ2VvbV9saW5lKCkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fbGluZShhZXMoeT1saWIsY29sb3I9IkxpYmVyYWwiKSkrCiAgZ2VvbV9wb2ludChhZXMoeT1saWIsY29sb3I9IkxpYmVyYWwiKSkrCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IDE6MTEpKwogIHlsYWIoIkZyZXF1ZW5jeSIpKwogIHRoZW1lX2dyZXkoKSsKICBnZ3RpdGxlKCJMaWItY29uIGJ5IG1vbnRoIikrCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSxzaXplPTE4KSkrCiAgbGFicyhjb2xvcj0iIikgCmczCgpgYGAKCiogQnkgYXBwbHlpbmcgdGhlIExhdmVyIGFuZCBHYXJyeSBkaWN0aW9uYXJ5LCB0aGUgc3Ryb25nIHRlbmRlbmN5IHRoYXQgVHJ1bXAgd2FzIGEgc29saWQgcmVwdWJsaWNhbiBhbmQgY29uc2VydmF0aXZlIHBlcnNvbiB3YXMgc3RhYmxlIHRocm91Z2ggYWxtb3N0IHRoZSB3aG9sZSAyMDE4LgoqIChTaW5jZSBoZSB3YXMgZmlyc3QgVVMgbGVhZGVyIHdobyB1c2VkIHR3aXR0ZXIgYSBsb3QsIEkgaGFkIG5vIG90aGVyIHByZXNpZGVudHMgdG8gY29tcGFyZS4pCgoqKioKCj4zLiBTVE0KCj4zLjEuIFNlYXJjaEsgYXQgdGhlIGZpc3J0IHRpbWUgKE5PVCBydW4gaXQgaGVyZSkKYGBge3IsIGV2YWw9RiwgZWNobz1UfQojSyA8LWMoNCw1LDYsNyw4LDkpCiNzdG9yYWdlICA8LSBzZWFyY2hLKERmbV9zdG0kZG9jdW1lbnRzLAojICAgICAgICAgICAgICAgICAgICBEZm1fc3RtJHZvY2FiLAojICAgICAgICAgICAgICAgICAgICBLID0gSywKIyAgICAgICAgICAgICAgICAgICAgbWF4LmVtLml0cyA9IDUwLAojICAgICAgICAgICAgICAgICAgICBwcmV2YWxlbmNlID0gfiBjcmVhdGVkX2F0LAojICAgICAgICAgICAgICAgICAgICBkYXRhID0gRGZtX3N0bSRtZXRhLAojICAgICAgICAgICAgICAgICAgICBpbml0LnR5cGUgPSAiU3BlY3RyYWwiKQojcGxvdChzdG9yYWdlJHJlc3VsdHMkc2VtY29oLAojICAgICBzdG9yYWdlJHJlc3VsdHMkZXhjbHVzLAojICAgICB4bGFiPSAiU2VtYW50aWMgY29oZXJlbmNlIiwKIyAgICAgeWxhYj0gIkV4Y2x1c2l2aXR5IiwKIyAgICAgY29sPSAiYmx1ZSIsCiMgICAgIHBjaCA9IDE5LAojICAgICBjZXggPSAxLAojICAgICBsdHkgPSAic29saWQiLAojICAgICBsd2QgPSAyKQojdGV4dChzdG9yYWdlJHJlc3VsdHMkc2VtY29oLAojICAgICBzdG9yYWdlJHJlc3VsdHMkZXhjbHVzLAojICAgICBsYWJlbHM9c3RvcmFnZSRyZXN1bHRzJEssCiMgICAgIGNleD0gMSwKIyAgICAgcG9zPTIpCmBgYAoKKiBUaGUgc2VhcmNoSyBmdW5jdGlvbiBjb3VsZCBub3QgY29udmVyZ2UgaW4gdGhpcyBhbmFseXNpcy4gVW5kZXIgdGhpcyByZXN0aXJjdGlvbiwgdGhlIHJlc3VsdHMgc3VnZ2VzdGVkIHRoYXQgSz03IHdvdWxkIGJlIGEgYnd0dGVyIGNob2ljZS4KCj4zLjIuIFNUTQpgYGB7ciByZXN1bHRzPSJoaWRlIiwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KRGZtX3N0bSA8LSBjb252ZXJ0KHR3ZWV0ZGZtLCB0byA9ICJzdG0iKQpzdG1GaXR0ZWQxIDwtIHN0bShEZm1fc3RtJGRvY3VtZW50cywKICAgICAgICAgICAgICAgICAgRGZtX3N0bSR2b2NhYiwKICAgICAgICAgICAgICAgICAgSyA9IDcsCiAgICAgICAgICAgICAgICAgIG1heC5lbS5pdHMgPSAxMDAsCiAgICAgICAgICAgICAgICAgIHByZXZhbGVuY2UgPSB+IGNyZWF0ZWRfYXQsCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBEZm1fc3RtJG1ldGEsCiAgICAgICAgICAgICAgICAgIGluaXQudHlwZSA9ICJTcGVjdHJhbCIpCmBgYAoKPjMuMy4gUmVzdWx0IG9mIFRvcGljIFByZXZhbGVuY2UKCiMjIyMzLjMuQS4gU3VtbWFyeSBvZiB0b3BpY3MKYGBge3J9CnBhcihtZnJvdz1jKDEsMSksbWFyPWMoNS4xLCA0LjEsIDQuMSwgMi4xKSkKcGxvdChzdG1GaXR0ZWQxLCB0eXBlID0gInN1bW1hcnkiLCBsYWJlbHR5cGUgPSBjKCJmcmV4IikpCmBgYAoKKiBJIHdvdWxkIG5hbWUgdGhlIGZvbGxvd2luZyB0b3BpY3M6IAogICAgMS4gVG9waWMgMTogRWNvbm9taWMgaXNzdWUKICAgIDIuIFRvcGljIDQ6IFRyYWRlIHdhcgogICAgMy4gVG9waWMgNTogQ29uZmxpY3Qgd2l0aCBkZW1vY3JhdHMKICAgIDQuIFRvcGljIDY6IE1pZHRlcm0gZWxlY3Rpb24KCiMjIyMzLjMuQi4gV29yZGNsb3VkIG9mIFRvcGljIDQKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CnBhcihtZnJvdz1jKDEsMSkpCmNsb3VkKHN0bUZpdHRlZDEsIHRvcGljID0gNCkKYGBgCgoqIEZvY3VzaW5nIG9uIHRoZSB0b3BpYyA0LCB3ZSBjb3VsZCBzZWUgbW9yZSB0ZXJtcyBhYm91dCBwcm90ZWN0aXZlIHRyYWRlIHBvbGljeS4KCiMjIyMzLjMuQy4gVG9waWMgUHJldmFsZW5jZSBhY3Jvc3MgdGltZQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KdyA8LSBsYWJlbFRvcGljcyhzdG1GaXR0ZWQxLCB0b3BpY3MgPSAxLCBuID0gMywgZnJleHdlaWdodCA9IDAuNSkKd19kZiA8LSBhcy5kYXRhLmZyYW1lKHckZnJleCkKd19kZiRzdW0gPC0gcGFzdGUod19kZiRWMSx3X2RmJFYyLHdfZGYkVjMsc2VwID0gIiAvICIpCgpwcmVwIDwtIGVzdGltYXRlRWZmZWN0KDE6NyB+IGNyZWF0ZWRfYXQsIAogICAgICAgICAgICAgICAgICAgICAgIHN0bUZpdHRlZDEsIAogICAgICAgICAgICAgICAgICAgICAgIG1ldGEgPSBEZm1fc3RtJG1ldGEsIAogICAgICAgICAgICAgICAgICAgICAgIHVuY2VydGFpbnR5ID0gIkdsb2JhbCIpCnBhcihtZnJvdz1jKDIsMiksbWFyPWMoMiwyLDIsMikpCmZvcihpIGluIGMoMSw0LDUsNikpewogIHggPC0gd19kZiRzdW1baV0KICBwbG90KHByZXAsICJjcmVhdGVkX2F0IiwgbWV0aG9kID0gImNvbnRpbnVvdXMiLCB0b3BpY3MgPSBpLAogICAgICAgbW9kZWwgPSBzdG1GaXR0ZWQxLCBwcmludGxlZ2VuZCA9IEZBTFNFLCB4YXh0ID0gIm4iLCB4bGFiID0gIkRhdGUiLHlsYWIgPSAiIikKICBzZXEgPC0gc2VxKGZyb20gPSBtaW4oRGZtX3N0bSRtZXRhJGNyZWF0ZWRfYXQpLCB0byA9IG1heChEZm1fc3RtJG1ldGEkY3JlYXRlZF9hdCkpCiAgYXhpcygxLCBhdCA9IHNlcSwgbGFiZWxzID0gYyhhcy5EYXRlKHNlcSxvcmlnaW49IjE5NzAvMS8xIikpKQogIHRpdGxlKHBhc3RlKCJUb3BpYyIsaSx4KSkKICBhYmxpbmUoaD0wLCBjb2w9IiM5OUNDRkYiKQogIGFibGluZShoPTAuMSwgY29sPSIjMzM2Njk5IikKICBhYmxpbmUoaD0wLjIsIGNvbD0iIzAwMzM2NiIpCn0KYGBgCgoqIEFsbCA3IHRvcGljcyBoYWQgdGhlIGV4cGVjdGVkIHByb3BvdGlvbiBhYm92ZSB6ZXJvIHNpZ25pZmljYW50bHkgcmVnYXJsZXNzIG9mIHRoZSBkYXRlLgoqIFBsb3R0aW5nIHRob3NlIGZvdXIgdG9waWNzIEkgaGF2ZSBuYW1lZCwgdGhyZWUgb2YgdGhlbSBkZWNyZWFzZWQgYWNyb3NzIHRpbWUsIGV2ZW4gdGhlIHRyYWRlLXdhci1yZWxhdGVkIHRvcGljIGRlY3JlYXNlZCBncmFkdWFsbGx5LiBPbiB0aGUgb3RoZXIgaGFuZCwgZWxlY3Rpb24tcmVsYXRlZCB0b3BpYyBpbmNyZWFzZSBhIGxvdCBhcyB0aGUgbWlkLXRlcm0gZWxlY3Rpb24gY29taW5nICgxMS82KS4KCioqKg==