Introduction

There is a website which stores all of Donald Trumps Tweet created by Brendan Brown. The data for this analysis was obtained from the website with this link here.

library(tidyverse)
library(lubridate)
url <- 'http://www.trumptwitterarchive.com/data/realdonaldtrump/%s.json'
all_tweets <- map(2009:2017, ~sprintf(url, .x)) %>%
  #alternatively
  #paste0("http://www.trumptwitterarchive.com/data/realdonaldtrump/",2009:2017,".json")
  map_df(jsonlite::fromJSON, simplifyDataFrame = TRUE) %>%
  mutate(created_at = parse_date_time(created_at, "a b! d! H!:M!:S! z!* Y!")) %>%
  tbl_df()
all_tweets%>%head()

Devices over time

Trump’s tweets became and has being a subject of much public interest from the time he decided to contest the republican presidential nomination and subsequently the general election. Journalist particularly interested would want to distinguish between tweets by himself from those by his staff. The analysis starts with tweets since 2009.

library(forcats)
library(scales)
library(viridis)
# forcats::fct_lump()  lump source into 5 groups
theme_set(theme_bw())
all_tweets %>%
  mutate(source = forcats::fct_lump(source, 5)) %>%
  count(month = round_date(created_at, "month"), source) %>%
complete(month, source, fill = list(n = 0)) %>%  #fill missing n with 0 dplyr::complete
  mutate(source = reorder(source, -n, sum)) %>%
  group_by(month) %>%
  mutate(percent = n / sum(n),
         maximum = cumsum(percent),
         minimum = lag(maximum, 1, 0)) %>%
ggplot(aes(month, ymin = minimum, ymax = maximum, fill = source)) +
geom_ribbon()+
  scale_y_continuous(labels = percent_format()) +
  labs(x = "Time",
       y = "% of Trump's tweets",
       fill = "Source",
       title = "Source of @realDonaldTrump tweets over time",
       subtitle = "Summarized by month")+
  scale_fill_manual(values=viridis_pal(option = "A")(6))

#geom_area
library(forcats)
library(scales)
# forcats::fct_lump()  lump source into 5 groups
all_tweets %>%
  mutate(source = forcats::fct_lump(source, 5)) %>%
  count(month = round_date(created_at, "month"), source) %>%
complete(month, source, fill = list(n = 0)) %>%  #fill missing n with 0 dplyr::complete
  mutate(source = reorder(source, -n, sum)) %>%
  group_by(month) %>%
  mutate(percent = n / sum(n),
         maximum = cumsum(percent),
         minimum = lag(maximum, 1, 0)) %>%
  ggplot(aes(month, percent, fill = source)) +
 
  geom_area(position = "identity", alpha = 0.7)+
  scale_y_continuous(labels = percent_format()) +
  labs(x = "Time",
       y = "% of Trump's tweets",
       fill = "Source",
       title = "Source of @realDonaldTrump tweets over time",
       subtitle = "Summarized by month")+
  scale_fill_manual(values=viridis_pal(option = "B")(6))

Starting from 2009 to late 2011,all of Trump’s tweets came from the Web Client. In 2012 Trump mostly tweeted from TweetDeck , TwitLonger Beta and Twitter Wed client. The android tweets start in early 2013 and continued until he switched to an android at the end of the first quarter of 2017. An iphone was used in tweets afterwards.

library(stringr)
all_tweets %>%
  mutate(source = fct_lump(source, 5)) %>%
  filter(!str_detect(text, "^(\"|RT)")) %>% #remove  retweets
  group_by(source, year = year(created_at)) %>%
  summarize(tweets = n(),
            hashtag = sum(str_detect(str_to_lower(text), "#[a-z]|http"))) %>%
  ungroup() %>%
  mutate(source = reorder(source, -tweets, sum)) %>%
  filter(tweets >= 1) %>%
  ggplot(aes(year, hashtag / tweets, color = source)) +
  geom_line() +
  geom_point() +
  scale_x_continuous(breaks = seq(2009, 2017, 2)) +
  scale_y_continuous(labels = percent_format()) +
  facet_wrap(~ source) +
  scale_fill_manual(values=viridis_pal(option = "B")(6))+
  labs(x = "Time",
       y = "% of Trump's tweets with a hashtag, picture or link",
       title = "Tweets with a hashtag, picture or link by device",
       subtitle = "")

Trump Barack Obama Tweet

Trumps tweets about Obama spiked between 2011 and 2013.This can be attributed Obama’s roast of him at the 2011 white house correspondence dinner.

all_tweets %>%
  filter(!str_detect(text, "^(\"|RT)")) %>%
  group_by(month = round_date(created_at, "month")) %>%
  summarize(tweets = n(),
            hashtag = sum(str_detect(str_to_lower(text), "obama")),
            percent = hashtag / tweets) %>%
  ungroup() %>%
  filter(tweets >= 10) %>%
  ggplot(aes(as.Date(month), percent)) +
  geom_line() +
  geom_point() +
  geom_vline(xintercept = as.integer(as.Date("2011-04-30")), color = "#FDE725FF", lty = 2) +
  geom_vline(xintercept = as.integer(as.Date("2012-11-06")), color = "#440154FF", lty = 2) +
  scale_y_continuous(labels = percent_format()) +
  labs(x = "Time",
       y = "% of Trump's tweets that mention Obama",
       subtitle = paste0("Summarized by month; only months containing at least 10 tweets.\n",
                         "Yellow line is White House Correspondent's Dinner, purple is 2012 election."),
       title = "Trump's tweets mentioning Obama")

all_tweets %>%
  filter(!str_detect(text, "^(\"|RT)")) %>%
  group_by(month = round_date(created_at, "month")) %>%
  summarize(tweets = n(),
            hashtag = sum(str_detect(str_to_lower(text), "radical islamic terrorism")),
            percent = hashtag / tweets) %>%
  ungroup() %>%
  filter(tweets >= 10) %>%
  ggplot(aes(as.Date(month), percent)) +
  geom_line() +
  geom_point() +
  geom_vline(xintercept = as.integer(as.Date("2011-04-30")), color = "#FDE725FF", lty = 2) +
  geom_vline(xintercept = as.integer(as.Date("2012-11-06")), color = "#440154FF", lty = 2) +
  scale_y_continuous(labels = percent_format()) +
  labs(x = "Time",
       y = "% of Trump's tweets that mention Islam",
       subtitle = paste0("Summarized by month; only months containing at least 10 tweets.\n",
                         " "),
       title = "Trump's tweets mentioning radical islamic terrorism")

all_tweets %>%
  filter(!str_detect(text, "^(\"|RT)")) %>%
  group_by(month = round_date(created_at, "month")) %>%
  summarize(tweets = n(),
            hashtag = sum(str_detect(str_to_lower(text), " terrorist")),
            percent = hashtag / tweets) %>%
  ungroup() %>%
  #filter(tweets >= 1) %>%
  ggplot(aes(as.Date(month), percent)) +
  geom_line() +
  geom_point() +
  geom_vline(xintercept = as.integer(as.Date("2011-04-30")), color = "#FDE725FF", lty = 2) +
  geom_vline(xintercept = as.integer(as.Date("2012-11-06")), color = "#440154FF", lty = 2) +
  scale_y_continuous(labels = percent_format()) +
  labs(x = "Time",
       y = "% of Trump's tweets that mention Islam",
       subtitle = paste0("Summarized by month; only months containing at least 10 tweets.\n",
                         " "),
       title = "Trump's tweets mentioning  terrorism")

between <- all_tweets %>%
  filter(created_at >= "2011-04-30", created_at < "2012-11-07") %>%
  mutate(obama = str_detect(str_to_lower(text), "obama"))
percent_mentioned <- mean(between$obama)
percent_mentioned
[1] 0.3232209

Between July 2011 and November 2012 (Obama’s re-election), a full 32.3%% of Trump’s tweets mentioned Obama by name.

Examining Trumps Sentiment over Time

library(tidytext)
all_tweet_words <- all_tweets %>%
  mutate(text = str_replace_all(text, "https?://t.co/[A-Za-z\\d]+|&amp;", "")) %>%
  filter(!str_detect(text, "^(\"|RT)")) %>%
  unnest_tokens(word, text, token = "regex") %>%
  filter(!word %in% stop_words$word, str_detect(word, "[a-z]"))
all_tweet_words %>%
  inner_join(get_sentiments("afinn")) %>%
  group_by(month = round_date(created_at, "month")) %>%
  summarize(average_sentiment = mean(score), words = n()) %>%
  filter(words >= 10) %>%
  ggplot(aes(month, average_sentiment)) +
  geom_line() +
  geom_hline(color = "red", lty = 2, yintercept = 0) +
  labs(x = "Time",
       y = "Average AFINN sentiment score",
       title = "@realDonaldTrump sentiment over time",
       subtitle = "Dashed line represents a 'neutral' sentiment average. Only months with at least 10 words present in the AFINN lexicon")

Trumps tweets about Obama were largely positive before 2011. After 2011, his tweets oscillated between negatives and positives.

library(stringr)
campaign_tweets <- all_tweets %>%
  filter(created_at >= "2015-06-16") %>%
  mutate(source = str_replace(source, "Twitter for ", "")) %>%
  filter(!str_detect(text, "^(\"|RT)")) #remove retweets
tweet_words <- all_tweet_words %>%
    filter(created_at >= "2015-06-16")

Frequency of Words before and After 2016 Election

ratios <- tweet_words %>%
  mutate(phase = ifelse(created_at >= "2016-12-07", "after", "before")) %>%
  count(word, phase) %>%
  spread(phase, n, fill = 0) %>%
  mutate(total = before + after) %>%
  mutate_at(vars(before, after), funs((. + 1) / sum(. + 1))) %>%
  mutate(ratio = after / before) %>%
  arrange(desc(ratio))
ratios%>%head()

Some of the words used mostly before the election included “fake” and “cuts”. Trumps attack on the media as fake news is well documented.

Most Retweeted Words

word_summary <- tweet_words %>%
  group_by(word)%>%
  summarize(total = n(),
            median_retweets = median(retweet_count)) 
word_summary%>%head() 
word_summary %>%
  filter(total >= 25) %>%
  arrange(desc(median_retweets)) %>%
  slice(c(1:20, seq(n() - 19, n()))) %>% #get the first 20 and last 20
  mutate(type = rep(c("Most retweets", "Fewest retweets"), each = 20)) %>%
  mutate(word = reorder(word, median_retweets)) %>%
  ggplot(aes(word, median_retweets,fill=type)) +
  scale_fill_manual(values=viridis_pal(option = "D")(2))+
  geom_col() +
  labs(x = "",
       y = "Median # of retweets for tweets containing this word",
       title = "Words that led to many or few retweets") +
  coord_flip() +
  facet_wrap(~ type, ncol = 1, scales = "free_y")

Some of Trump’s most retweeted topics include hillary clinton, obama, country and crooked.His fewest tweets included meeting,obamacare and puerto rico.

all_tweets %>%
  group_by(month = round_date(created_at, "month")) %>%
  summarize(median_retweets = median(retweet_count), number = n()) %>%
  filter(number >= 10) %>%
  ggplot(aes(month, median_retweets)) +
  geom_line() +
  scale_y_continuous(labels = comma_format()) +
  labs(x = "Time",
       y = "Median # of retweets")

Trumps retweets skyrocketed after the elections in rowards the end of 2016.

LS0tCnRpdGxlOiAiU2VudGltZW50ICBBbmFseXNpcyBvZiBUcnVtcCdzIFR3ZWV0cyIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjogTmFuYSBCb2F0ZW5nCmRmX3ByaW50OiBwYWdlZApUaW1lOiAnYHIgU3lzLnRpbWUoKWAnCmRhdGU6ICJgciBmb3JtYXQoU3lzLnRpbWUoKSwgJyVCICVkLCAlWScpYCIKLS0tCgoKCiMjIyMgSW50cm9kdWN0aW9uClRoZXJlIGlzIGEgd2Vic2l0ZSB3aGljaCBzdG9yZXMgYWxsIG9mIERvbmFsZCBUcnVtcHMgVHdlZXQgY3JlYXRlZCBieSBCcmVuZGFuIEJyb3duLiBUaGUgZGF0YSBmb3IgdGhpcyBhbmFseXNpcyB3YXMgb2J0YWluZWQgZnJvbSB0aGUgd2Vic2l0ZSB3aXRoIHRoaXMgbGluayBbaGVyZV0oaHR0cDovL3d3dy50cnVtcHR3aXR0ZXJhcmNoaXZlLmNvbS9kYXRhL3JlYWxkb25hbGR0cnVtcC8pLgoKYGBge3Igc2V0dXAsaW5jbHVkZT1GQUxTRX0KCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIG91dC53aWR0aCA9IjEwMCUiLAogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gJ2RlZmF1bHQnLCAKICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICBmaWcuY2FwID0iRmlnLiAzMCIsIAogICAgICAgICAgICAgICAgICAgICAgb3V0LndpZHRoPSIxMDAlIikKCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCgp1cmwgPC0gJ2h0dHA6Ly93d3cudHJ1bXB0d2l0dGVyYXJjaGl2ZS5jb20vZGF0YS9yZWFsZG9uYWxkdHJ1bXAvJXMuanNvbicKYWxsX3R3ZWV0cyA8LSBtYXAoMjAwOToyMDE3LCB+c3ByaW50Zih1cmwsIC54KSkgJT4lCiAgI2FsdGVybmF0aXZlbHkKICAjcGFzdGUwKCJodHRwOi8vd3d3LnRydW1wdHdpdHRlcmFyY2hpdmUuY29tL2RhdGEvcmVhbGRvbmFsZHRydW1wLyIsMjAwOToyMDE3LCIuanNvbiIpCiAgbWFwX2RmKGpzb25saXRlOjpmcm9tSlNPTiwgc2ltcGxpZnlEYXRhRnJhbWUgPSBUUlVFKSAlPiUKICBtdXRhdGUoY3JlYXRlZF9hdCA9IHBhcnNlX2RhdGVfdGltZShjcmVhdGVkX2F0LCAiYSBiISBkISBIITpNITpTISB6ISogWSEiKSkgJT4lCiAgdGJsX2RmKCkKCmFsbF90d2VldHMlPiVoZWFkKCkKYGBgCgoKIyMjIyBEZXZpY2VzIG92ZXIgdGltZQoKVHJ1bXAncyB0d2VldHMgYmVjYW1lIGFuZCBoYXMgYmVpbmcgYSBzdWJqZWN0IG9mIG11Y2ggcHVibGljIGludGVyZXN0IGZyb20gdGhlIHRpbWUgIGhlIGRlY2lkZWQgdG8gY29udGVzdCB0aGUgcmVwdWJsaWNhbiBwcmVzaWRlbnRpYWwgbm9taW5hdGlvbiBhbmQgc3Vic2VxdWVudGx5IHRoZSBnZW5lcmFsIGVsZWN0aW9uLiBKb3VybmFsaXN0ICBwYXJ0aWN1bGFybHkgaW50ZXJlc3RlZCB3b3VsZCB3YW50IHRvIGRpc3Rpbmd1aXNoIGJldHdlZW4gIHR3ZWV0cyBieSBoaW1zZWxmIGZyb20gdGhvc2UgYnkgaGlzIHN0YWZmLiBUaGUgYW5hbHlzaXMgc3RhcnRzIHdpdGggdHdlZXRzIHNpbmNlIDIwMDkuCgpgYGB7cn0KbGlicmFyeShmb3JjYXRzKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeSh2aXJpZGlzKQojIGZvcmNhdHM6OmZjdF9sdW1wKCkgIGx1bXAgc291cmNlIGludG8gNSBncm91cHMKdGhlbWVfc2V0KHRoZW1lX2J3KCkpCmFsbF90d2VldHMgJT4lCiAgbXV0YXRlKHNvdXJjZSA9IGZvcmNhdHM6OmZjdF9sdW1wKHNvdXJjZSwgNSkpICU+JQogIGNvdW50KG1vbnRoID0gcm91bmRfZGF0ZShjcmVhdGVkX2F0LCAibW9udGgiKSwgc291cmNlKSAlPiUKY29tcGxldGUobW9udGgsIHNvdXJjZSwgZmlsbCA9IGxpc3QobiA9IDApKSAlPiUgICNmaWxsIG1pc3NpbmcgbiB3aXRoIDAgZHBseXI6OmNvbXBsZXRlCiAgbXV0YXRlKHNvdXJjZSA9IHJlb3JkZXIoc291cmNlLCAtbiwgc3VtKSkgJT4lCiAgZ3JvdXBfYnkobW9udGgpICU+JQogIG11dGF0ZShwZXJjZW50ID0gbiAvIHN1bShuKSwKICAgICAgICAgbWF4aW11bSA9IGN1bXN1bShwZXJjZW50KSwKICAgICAgICAgbWluaW11bSA9IGxhZyhtYXhpbXVtLCAxLCAwKSkgJT4lCmdncGxvdChhZXMobW9udGgsIHltaW4gPSBtaW5pbXVtLCB5bWF4ID0gbWF4aW11bSwgZmlsbCA9IHNvdXJjZSkpICsKZ2VvbV9yaWJib24oKSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoKSkgKwogIGxhYnMoeCA9ICJUaW1lIiwKICAgICAgIHkgPSAiJSBvZiBUcnVtcCdzIHR3ZWV0cyIsCiAgICAgICBmaWxsID0gIlNvdXJjZSIsCiAgICAgICB0aXRsZSA9ICJTb3VyY2Ugb2YgQHJlYWxEb25hbGRUcnVtcCB0d2VldHMgb3ZlciB0aW1lIiwKICAgICAgIHN1YnRpdGxlID0gIlN1bW1hcml6ZWQgYnkgbW9udGgiKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9dmlyaWRpc19wYWwob3B0aW9uID0gIkEiKSg2KSkKCgojZ2VvbV9hcmVhCgpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkoc2NhbGVzKQojIGZvcmNhdHM6OmZjdF9sdW1wKCkgIGx1bXAgc291cmNlIGludG8gNSBncm91cHMKYWxsX3R3ZWV0cyAlPiUKICBtdXRhdGUoc291cmNlID0gZm9yY2F0czo6ZmN0X2x1bXAoc291cmNlLCA1KSkgJT4lCiAgY291bnQobW9udGggPSByb3VuZF9kYXRlKGNyZWF0ZWRfYXQsICJtb250aCIpLCBzb3VyY2UpICU+JQpjb21wbGV0ZShtb250aCwgc291cmNlLCBmaWxsID0gbGlzdChuID0gMCkpICU+JSAgI2ZpbGwgbWlzc2luZyBuIHdpdGggMCBkcGx5cjo6Y29tcGxldGUKICBtdXRhdGUoc291cmNlID0gcmVvcmRlcihzb3VyY2UsIC1uLCBzdW0pKSAlPiUKICBncm91cF9ieShtb250aCkgJT4lCiAgbXV0YXRlKHBlcmNlbnQgPSBuIC8gc3VtKG4pLAogICAgICAgICBtYXhpbXVtID0gY3Vtc3VtKHBlcmNlbnQpLAogICAgICAgICBtaW5pbXVtID0gbGFnKG1heGltdW0sIDEsIDApKSAlPiUKCiAgZ2dwbG90KGFlcyhtb250aCwgcGVyY2VudCwgZmlsbCA9IHNvdXJjZSkpICsKIAogIGdlb21fYXJlYShwb3NpdGlvbiA9ICJpZGVudGl0eSIsIGFscGhhID0gMC43KSsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoKSkgKwogIGxhYnMoeCA9ICJUaW1lIiwKICAgICAgIHkgPSAiJSBvZiBUcnVtcCdzIHR3ZWV0cyIsCiAgICAgICBmaWxsID0gIlNvdXJjZSIsCiAgICAgICB0aXRsZSA9ICJTb3VyY2Ugb2YgQHJlYWxEb25hbGRUcnVtcCB0d2VldHMgb3ZlciB0aW1lIiwKICAgICAgIHN1YnRpdGxlID0gIlN1bW1hcml6ZWQgYnkgbW9udGgiKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9dmlyaWRpc19wYWwob3B0aW9uID0gIkIiKSg2KSkKYGBgCgoKCgoKU3RhcnRpbmcgZnJvbSAyMDA5IHRvIGxhdGUgMjAxMSxhbGwgIG9mIFRydW1w4oCZcyB0d2VldHMgIGNhbWUgZnJvbSB0aGUgV2ViIENsaWVudC4gSW4gMjAxMiBUcnVtcCBtb3N0bHkgdHdlZXRlZCBmcm9tIFR3ZWV0RGVjayAsIFR3aXRMb25nZXIgQmV0YSBhbmQgVHdpdHRlciBXZWQgY2xpZW50LiBUaGUgYW5kcm9pZCB0d2VldHMgc3RhcnQgaW4gZWFybHkgMjAxMyBhbmQgY29udGludWVkIHVudGlsIGhlIHN3aXRjaGVkIHRvIGFuIGFuZHJvaWQgIGF0IHRoZSBlbmQgb2YgdGhlIGZpcnN0IHF1YXJ0ZXIgb2YgMjAxNy4gQW4gaXBob25lIHdhcyB1c2VkIGluIHR3ZWV0cyBhZnRlcndhcmRzLgoKCgpgYGB7cn0KbGlicmFyeShzdHJpbmdyKQoKYWxsX3R3ZWV0cyAlPiUKICBtdXRhdGUoc291cmNlID0gZmN0X2x1bXAoc291cmNlLCA1KSkgJT4lCiAgZmlsdGVyKCFzdHJfZGV0ZWN0KHRleHQsICJeKFwifFJUKSIpKSAlPiUgI3JlbW92ZSAgcmV0d2VldHMKICBncm91cF9ieShzb3VyY2UsIHllYXIgPSB5ZWFyKGNyZWF0ZWRfYXQpKSAlPiUKICBzdW1tYXJpemUodHdlZXRzID0gbigpLAogICAgICAgICAgICBoYXNodGFnID0gc3VtKHN0cl9kZXRlY3Qoc3RyX3RvX2xvd2VyKHRleHQpLCAiI1thLXpdfGh0dHAiKSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoc291cmNlID0gcmVvcmRlcihzb3VyY2UsIC10d2VldHMsIHN1bSkpICU+JQogIGZpbHRlcih0d2VldHMgPj0gMSkgJT4lCiAgZ2dwbG90KGFlcyh5ZWFyLCBoYXNodGFnIC8gdHdlZXRzLCBjb2xvciA9IHNvdXJjZSkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDksIDIwMTcsIDIpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCkpICsKICBmYWNldF93cmFwKH4gc291cmNlKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPXZpcmlkaXNfcGFsKG9wdGlvbiA9ICJCIikoNikpKwogIGxhYnMoeCA9ICJUaW1lIiwKICAgICAgIHkgPSAiJSBvZiBUcnVtcCdzIHR3ZWV0cyB3aXRoIGEgaGFzaHRhZywgcGljdHVyZSBvciBsaW5rIiwKICAgICAgIHRpdGxlID0gIlR3ZWV0cyB3aXRoIGEgaGFzaHRhZywgcGljdHVyZSBvciBsaW5rIGJ5IGRldmljZSIsCiAgICAgICBzdWJ0aXRsZSA9ICIiKQpgYGAKCgoKCgojIyMjIFRydW1wICBCYXJhY2sgT2JhbWEgVHdlZXQKClRydW1wcyB0d2VldHMgYWJvdXQgT2JhbWEgc3Bpa2VkIGJldHdlZW4gMjAxMSBhbmQgMjAxMy5UaGlzIGNhbiBiZSBhdHRyaWJ1dGVkIE9iYW1hJ3Mgcm9hc3Qgb2YgaGltIGF0IHRoZSAyMDExIHdoaXRlIGhvdXNlIGNvcnJlc3BvbmRlbmNlIGRpbm5lci4KCmBgYHtyfQphbGxfdHdlZXRzICU+JQogIGZpbHRlcighc3RyX2RldGVjdCh0ZXh0LCAiXihcInxSVCkiKSkgJT4lCiAgZ3JvdXBfYnkobW9udGggPSByb3VuZF9kYXRlKGNyZWF0ZWRfYXQsICJtb250aCIpKSAlPiUKICBzdW1tYXJpemUodHdlZXRzID0gbigpLAogICAgICAgICAgICBoYXNodGFnID0gc3VtKHN0cl9kZXRlY3Qoc3RyX3RvX2xvd2VyKHRleHQpLCAib2JhbWEiKSksCiAgICAgICAgICAgIHBlcmNlbnQgPSBoYXNodGFnIC8gdHdlZXRzKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZmlsdGVyKHR3ZWV0cyA+PSAxMCkgJT4lCiAgZ2dwbG90KGFlcyhhcy5EYXRlKG1vbnRoKSwgcGVyY2VudCkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBhcy5pbnRlZ2VyKGFzLkRhdGUoIjIwMTEtMDQtMzAiKSksIGNvbG9yID0gIiNGREU3MjVGRiIsIGx0eSA9IDIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBhcy5pbnRlZ2VyKGFzLkRhdGUoIjIwMTItMTEtMDYiKSksIGNvbG9yID0gIiM0NDAxNTRGRiIsIGx0eSA9IDIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gcGVyY2VudF9mb3JtYXQoKSkgKwogIGxhYnMoeCA9ICJUaW1lIiwKICAgICAgIHkgPSAiJSBvZiBUcnVtcCdzIHR3ZWV0cyB0aGF0IG1lbnRpb24gT2JhbWEiLAogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoIlN1bW1hcml6ZWQgYnkgbW9udGg7IG9ubHkgbW9udGhzIGNvbnRhaW5pbmcgYXQgbGVhc3QgMTAgdHdlZXRzLlxuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJZZWxsb3cgbGluZSBpcyBXaGl0ZSBIb3VzZSBDb3JyZXNwb25kZW50J3MgRGlubmVyLCBwdXJwbGUgaXMgMjAxMiBlbGVjdGlvbi4iKSwKICAgICAgIHRpdGxlID0gIlRydW1wJ3MgdHdlZXRzIG1lbnRpb25pbmcgT2JhbWEiKQpgYGAKCgoKYGBge3J9CmFsbF90d2VldHMgJT4lCiAgZmlsdGVyKCFzdHJfZGV0ZWN0KHRleHQsICJeKFwifFJUKSIpKSAlPiUKICBncm91cF9ieShtb250aCA9IHJvdW5kX2RhdGUoY3JlYXRlZF9hdCwgIm1vbnRoIikpICU+JQogIHN1bW1hcml6ZSh0d2VldHMgPSBuKCksCiAgICAgICAgICAgIGhhc2h0YWcgPSBzdW0oc3RyX2RldGVjdChzdHJfdG9fbG93ZXIodGV4dCksICJyYWRpY2FsIGlzbGFtaWMgdGVycm9yaXNtIikpLAogICAgICAgICAgICBwZXJjZW50ID0gaGFzaHRhZyAvIHR3ZWV0cykgJT4lCiAgdW5ncm91cCgpICU+JQogIGZpbHRlcih0d2VldHMgPj0gMTApICU+JQogIGdncGxvdChhZXMoYXMuRGF0ZShtb250aCksIHBlcmNlbnQpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYXMuaW50ZWdlcihhcy5EYXRlKCIyMDExLTA0LTMwIikpLCBjb2xvciA9ICIjRkRFNzI1RkYiLCBsdHkgPSAyKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYXMuaW50ZWdlcihhcy5EYXRlKCIyMDEyLTExLTA2IikpLCBjb2xvciA9ICIjNDQwMTU0RkYiLCBsdHkgPSAyKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCkpICsKICBsYWJzKHggPSAiVGltZSIsCiAgICAgICB5ID0gIiUgb2YgVHJ1bXAncyB0d2VldHMgdGhhdCBtZW50aW9uIElzbGFtIiwKICAgICAgIHN1YnRpdGxlID0gcGFzdGUwKCJTdW1tYXJpemVkIGJ5IG1vbnRoOyBvbmx5IG1vbnRocyBjb250YWluaW5nIGF0IGxlYXN0IDEwIHR3ZWV0cy5cbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiICIpLAogICAgICAgdGl0bGUgPSAiVHJ1bXAncyB0d2VldHMgbWVudGlvbmluZyByYWRpY2FsIGlzbGFtaWMgdGVycm9yaXNtIikKYGBgCgoKCmBgYHtyfQphbGxfdHdlZXRzICU+JQogIGZpbHRlcighc3RyX2RldGVjdCh0ZXh0LCAiXihcInxSVCkiKSkgJT4lCiAgZ3JvdXBfYnkobW9udGggPSByb3VuZF9kYXRlKGNyZWF0ZWRfYXQsICJtb250aCIpKSAlPiUKICBzdW1tYXJpemUodHdlZXRzID0gbigpLAogICAgICAgICAgICBoYXNodGFnID0gc3VtKHN0cl9kZXRlY3Qoc3RyX3RvX2xvd2VyKHRleHQpLCAiIHRlcnJvcmlzdCIpKSwKICAgICAgICAgICAgcGVyY2VudCA9IGhhc2h0YWcgLyB0d2VldHMpICU+JQogIHVuZ3JvdXAoKSAlPiUKICAjZmlsdGVyKHR3ZWV0cyA+PSAxKSAlPiUKICBnZ3Bsb3QoYWVzKGFzLkRhdGUobW9udGgpLCBwZXJjZW50KSkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGFzLmludGVnZXIoYXMuRGF0ZSgiMjAxMS0wNC0zMCIpKSwgY29sb3IgPSAiI0ZERTcyNUZGIiwgbHR5ID0gMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IGFzLmludGVnZXIoYXMuRGF0ZSgiMjAxMi0xMS0wNiIpKSwgY29sb3IgPSAiIzQ0MDE1NEZGIiwgbHR5ID0gMikgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBwZXJjZW50X2Zvcm1hdCgpKSArCiAgbGFicyh4ID0gIlRpbWUiLAogICAgICAgeSA9ICIlIG9mIFRydW1wJ3MgdHdlZXRzIHRoYXQgbWVudGlvbiBJc2xhbSIsCiAgICAgICBzdWJ0aXRsZSA9IHBhc3RlMCgiU3VtbWFyaXplZCBieSBtb250aDsgb25seSBtb250aHMgY29udGFpbmluZyBhdCBsZWFzdCAxMCB0d2VldHMuXG4iLAogICAgICAgICAgICAgICAgICAgICAgICAgIiAiKSwKICAgICAgIHRpdGxlID0gIlRydW1wJ3MgdHdlZXRzIG1lbnRpb25pbmcgIHRlcnJvcmlzbSIpCmBgYAoKCgoKYGBge3J9CmJldHdlZW4gPC0gYWxsX3R3ZWV0cyAlPiUKICBmaWx0ZXIoY3JlYXRlZF9hdCA+PSAiMjAxMS0wNC0zMCIsIGNyZWF0ZWRfYXQgPCAiMjAxMi0xMS0wNyIpICU+JQogIG11dGF0ZShvYmFtYSA9IHN0cl9kZXRlY3Qoc3RyX3RvX2xvd2VyKHRleHQpLCAib2JhbWEiKSkKCnBlcmNlbnRfbWVudGlvbmVkIDwtIG1lYW4oYmV0d2VlbiRvYmFtYSkKcGVyY2VudF9tZW50aW9uZWQKYGBgCgpCZXR3ZWVuIEp1bHkgMjAxMSBhbmQgTm92ZW1iZXIgMjAxMiAoT2JhbWHigJlzIHJlLWVsZWN0aW9uKSwgYSBmdWxsIDMyLjMlJSBvZiBUcnVtcOKAmXMgdHdlZXRzIG1lbnRpb25lZCBPYmFtYSBieSBuYW1lLgoKIyMjIyBFeGFtaW5pbmcgVHJ1bXBzIFNlbnRpbWVudCBvdmVyIFRpbWUKCmBgYHtyfQpsaWJyYXJ5KHRpZHl0ZXh0KQoKYWxsX3R3ZWV0X3dvcmRzIDwtIGFsbF90d2VldHMgJT4lCiAgbXV0YXRlKHRleHQgPSBzdHJfcmVwbGFjZV9hbGwodGV4dCwgImh0dHBzPzovL3QuY28vW0EtWmEtelxcZF0rfCZhbXA7IiwgIiIpKSAlPiUKICBmaWx0ZXIoIXN0cl9kZXRlY3QodGV4dCwgIl4oXCJ8UlQpIikpICU+JQogIHVubmVzdF90b2tlbnMod29yZCwgdGV4dCwgdG9rZW4gPSAicmVnZXgiKSAlPiUKICBmaWx0ZXIoIXdvcmQgJWluJSBzdG9wX3dvcmRzJHdvcmQsIHN0cl9kZXRlY3Qod29yZCwgIlthLXpdIikpCmBgYAoKCgoKYGBge3J9CmFsbF90d2VldF93b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJhZmlubiIpKSAlPiUKICBncm91cF9ieShtb250aCA9IHJvdW5kX2RhdGUoY3JlYXRlZF9hdCwgIm1vbnRoIikpICU+JQogIHN1bW1hcml6ZShhdmVyYWdlX3NlbnRpbWVudCA9IG1lYW4oc2NvcmUpLCB3b3JkcyA9IG4oKSkgJT4lCiAgZmlsdGVyKHdvcmRzID49IDEwKSAlPiUKICBnZ3Bsb3QoYWVzKG1vbnRoLCBhdmVyYWdlX3NlbnRpbWVudCkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9obGluZShjb2xvciA9ICJyZWQiLCBsdHkgPSAyLCB5aW50ZXJjZXB0ID0gMCkgKwogIGxhYnMoeCA9ICJUaW1lIiwKICAgICAgIHkgPSAiQXZlcmFnZSBBRklOTiBzZW50aW1lbnQgc2NvcmUiLAogICAgICAgdGl0bGUgPSAiQHJlYWxEb25hbGRUcnVtcCBzZW50aW1lbnQgb3ZlciB0aW1lIiwKICAgICAgIHN1YnRpdGxlID0gIkRhc2hlZCBsaW5lIHJlcHJlc2VudHMgYSAnbmV1dHJhbCcgc2VudGltZW50IGF2ZXJhZ2UuIE9ubHkgbW9udGhzIHdpdGggYXQgbGVhc3QgMTAgd29yZHMgcHJlc2VudCBpbiB0aGUgQUZJTk4gbGV4aWNvbiIpCgpgYGAKClRydW1wcyB0d2VldHMgYWJvdXQgT2JhbWEgd2VyZSBsYXJnZWx5IHBvc2l0aXZlIGJlZm9yZSAyMDExLiBBZnRlciAyMDExLCBoaXMgdHdlZXRzIG9zY2lsbGF0ZWQgYmV0d2VlbiBuZWdhdGl2ZXMgYW5kIHBvc2l0aXZlcy4KCmBgYHtyfQpsaWJyYXJ5KHN0cmluZ3IpCgpjYW1wYWlnbl90d2VldHMgPC0gYWxsX3R3ZWV0cyAlPiUKICBmaWx0ZXIoY3JlYXRlZF9hdCA+PSAiMjAxNS0wNi0xNiIpICU+JQogIG11dGF0ZShzb3VyY2UgPSBzdHJfcmVwbGFjZShzb3VyY2UsICJUd2l0dGVyIGZvciAiLCAiIikpICU+JQogIGZpbHRlcighc3RyX2RldGVjdCh0ZXh0LCAiXihcInxSVCkiKSkgI3JlbW92ZSByZXR3ZWV0cwoKdHdlZXRfd29yZHMgPC0gYWxsX3R3ZWV0X3dvcmRzICU+JQogICAgZmlsdGVyKGNyZWF0ZWRfYXQgPj0gIjIwMTUtMDYtMTYiKQoKYGBgCgoKIyMjIyBGcmVxdWVuY3kgb2YgV29yZHMgYmVmb3JlIGFuZCBBZnRlciAyMDE2IEVsZWN0aW9uCgpgYGB7cn0KcmF0aW9zIDwtIHR3ZWV0X3dvcmRzICU+JQogIG11dGF0ZShwaGFzZSA9IGlmZWxzZShjcmVhdGVkX2F0ID49ICIyMDE2LTEyLTA3IiwgImFmdGVyIiwgImJlZm9yZSIpKSAlPiUKICBjb3VudCh3b3JkLCBwaGFzZSkgJT4lCiAgc3ByZWFkKHBoYXNlLCBuLCBmaWxsID0gMCkgJT4lCiAgbXV0YXRlKHRvdGFsID0gYmVmb3JlICsgYWZ0ZXIpICU+JQogIG11dGF0ZV9hdCh2YXJzKGJlZm9yZSwgYWZ0ZXIpLCBmdW5zKCguICsgMSkgLyBzdW0oLiArIDEpKSkgJT4lCiAgbXV0YXRlKHJhdGlvID0gYWZ0ZXIgLyBiZWZvcmUpICU+JQogIGFycmFuZ2UoZGVzYyhyYXRpbykpCgpyYXRpb3MlPiVoZWFkKCkKCmBgYAoKU29tZSBvZiB0aGUgd29yZHMgdXNlZCBtb3N0bHkgYmVmb3JlIHRoZSBlbGVjdGlvbiBpbmNsdWRlZCDigJxmYWtlIOKAnSBhbmQg4oCcY3V0c+KAnS4gVHJ1bXBzIGF0dGFjayBvbiB0aGUgbWVkaWEgYXMgZmFrZSBuZXdzIGlzIHdlbGwgZG9jdW1lbnRlZC4KCgojIyMjIE1vc3QgUmV0d2VldGVkIFdvcmRzCgpgYGB7cn0Kd29yZF9zdW1tYXJ5IDwtIHR3ZWV0X3dvcmRzICU+JQogIGdyb3VwX2J5KHdvcmQpJT4lCiAgc3VtbWFyaXplKHRvdGFsID0gbigpLAogICAgICAgICAgICBtZWRpYW5fcmV0d2VldHMgPSBtZWRpYW4ocmV0d2VldF9jb3VudCkpIAoKd29yZF9zdW1tYXJ5JT4laGVhZCgpIAoKCmBgYAoKCgoKYGBge3J9CndvcmRfc3VtbWFyeSAlPiUKICBmaWx0ZXIodG90YWwgPj0gMjUpICU+JQogIGFycmFuZ2UoZGVzYyhtZWRpYW5fcmV0d2VldHMpKSAlPiUKICBzbGljZShjKDE6MjAsIHNlcShuKCkgLSAxOSwgbigpKSkpICU+JSAjZ2V0IHRoZSBmaXJzdCAyMCBhbmQgbGFzdCAyMAogIG11dGF0ZSh0eXBlID0gcmVwKGMoIk1vc3QgcmV0d2VldHMiLCAiRmV3ZXN0IHJldHdlZXRzIiksIGVhY2ggPSAyMCkpICU+JQogIG11dGF0ZSh3b3JkID0gcmVvcmRlcih3b3JkLCBtZWRpYW5fcmV0d2VldHMpKSAlPiUKICBnZ3Bsb3QoYWVzKHdvcmQsIG1lZGlhbl9yZXR3ZWV0cyxmaWxsPXR5cGUpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPXZpcmlkaXNfcGFsKG9wdGlvbiA9ICJEIikoMikpKwogIGdlb21fY29sKCkgKwogIGxhYnMoeCA9ICIiLAogICAgICAgeSA9ICJNZWRpYW4gIyBvZiByZXR3ZWV0cyBmb3IgdHdlZXRzIGNvbnRhaW5pbmcgdGhpcyB3b3JkIiwKICAgICAgIHRpdGxlID0gIldvcmRzIHRoYXQgbGVkIHRvIG1hbnkgb3IgZmV3IHJldHdlZXRzIikgKwogIGNvb3JkX2ZsaXAoKSArCiAgZmFjZXRfd3JhcCh+IHR5cGUsIG5jb2wgPSAxLCBzY2FsZXMgPSAiZnJlZV95IikKYGBgCgpTb21lIG9mIFRydW1w4oCZcyBtb3N0IHJldHdlZXRlZCB0b3BpY3MgaW5jbHVkZSBoaWxsYXJ5IGNsaW50b24sIG9iYW1hLCBjb3VudHJ5IGFuZCBjcm9va2VkLkhpcyBmZXdlc3QgdHdlZXRzIGluY2x1ZGVkIG1lZXRpbmcsb2JhbWFjYXJlIGFuZCBwdWVydG8gcmljby4KCgoKYGBge3J9CmFsbF90d2VldHMgJT4lCiAgZ3JvdXBfYnkobW9udGggPSByb3VuZF9kYXRlKGNyZWF0ZWRfYXQsICJtb250aCIpKSAlPiUKICBzdW1tYXJpemUobWVkaWFuX3JldHdlZXRzID0gbWVkaWFuKHJldHdlZXRfY291bnQpLCBudW1iZXIgPSBuKCkpICU+JQogIGZpbHRlcihudW1iZXIgPj0gMTApICU+JQogIGdncGxvdChhZXMobW9udGgsIG1lZGlhbl9yZXR3ZWV0cykpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hX2Zvcm1hdCgpKSArCiAgbGFicyh4ID0gIlRpbWUiLAogICAgICAgeSA9ICJNZWRpYW4gIyBvZiByZXR3ZWV0cyIpCmBgYAoKVHJ1bXBzIHJldHdlZXRzIHNreXJvY2tldGVkIGFmdGVyIHRoZSBlbGVjdGlvbnMgaW4gcm93YXJkcyB0aGUgZW5kIG9mIDIwMTYuCgoKCgoKCgo=