Introduction

In this project, we look at the coverage of Coronavirus on mainstream news articles and Twitter in the USA. The main goal is to inspect the difference in the focus of each media outlet (topic modelling) and their expressed attitudes (sentiment analysis) on COVID-19.

The project is conducted with the following steps: Data collection, Data cleaning and Pre-processing, Topic modeling, and Sentiment analysis. The data was gathered using web-scraping technique with R and Python programming. After data cleaning, the Quanteda package in R was used to prepare for text analysis. Then, we applied topic modelling to identify distinct topics. In sentiment analysis, we chose a lexicon, calculated sentiments scores and looked at the shift in sentiments.

The result has revealed some disparities between the media sources. Social media, namely Twitter, are reflecting more on people´s sentiments and quick updates of the situation while news articles are more about macro problems. The two media’s sentiment remained negative throughout the observed period.

Data Collection and Cleaning

News Articles

Using the keyword coronavirus for querying, we collected news articles published on news websites in the United States from the beginning of 2020, where the first cases of coronavirus were reported, until April 19, 2020. For sources, we looked at the top 15 U.S news websites measured by unique monthly visitors (Statista, 2020), excluding the news aggregators (Yahoo News, Google News) and topic-specific newspapers (The Wall Street Journal). We used a third-party API called Currents API in R to get all the available URLs, then put them into the newspaper3k module in Python, which enabled scraping the entire articles. Furthermore, after checking the data quality from each source, we narrowed them down from 15 to 6 news outlets: CNN, The New York Times, Fox News, The Guardian, USA Today and The LA Times.

# Load the scraped data
news_data <- read_csv("news_coronavirus.csv")

# Add week and remove unnecessary column
news_data <- news_data %>% 
  mutate(week = isoweek(publish_date)) %>% 
  select(-title)

# Preview the data
glimpse(news_data)
Rows: 14,149
Columns: 4
$ publish_date <date> 2020-04-19, 2020-04-19, 2020-04-19, 2020-04-19, 202…
$ source       <chr> "CNN", "CNN", "CNN", "CNN", "CNN", "CNN", "CNN", "CN…
$ text         <chr> "(CNN) Nothing can bring back the months of wedding …
$ week         <dbl> 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, …

Twitter

Thanks to the support from the team at <crowdbreaks.org>, who is tracking Twitter trend on COVID-19 in real time, we managed to get all tweet IDs that they had collected since January 2020 in the US with the keywords of “wuhan”, “ncov”, “coronavirus”, “covid”, “sars-cov-2”. We decided to take stratified sampling of the data (50%) to keep the distribution of number of tweets per week and speed up data collection and obtain the data in time for the report. The Twitter data were collected until April 16, 2020.

# Load the scraped data
tweets_data <- read_csv("twitter_coronavirus.csv")

# Transform the date column
tweets_data <- tweets_data %>% 
  separate(created_at, c("wday", "month", "day", "time", "plus", "year"), 
           sep = " ") %>% 
  mutate(date = paste(month, day, year, sep = " ")) %>% 
  select(c("text", "date"))

tweets_data$date <- as.Date(tweets_data$date, format = "%b %d %Y")
tweets_data <- tweets_data %>% 
  mutate(week = isoweek(date)) %>% 
  filter(week > 2)

# Clean hashtags, links and special characters
tweets_data$text <- tweets_data$text %>% 
  str_replace_all("#", " ") %>%
  str_remove_all("(?<=^|\\s)http[^\\s]+") %>% 
  str_remove_all("[^a-zA-Z0-9 ]") %>% 
  trimws()

# Remove blank text after cleaning
tweets_data <- tweets_data %>% 
  filter(str_count(text, pattern = boundary("word")) > 1)

Data Overview

For further data cleaning, we removed duplicated data, texts that were too short and kept only texts written in English. We kept the time variable in week format and the full text of the document for analysis. Consequently, 14,149 news articles and 109,329 tweets were ready for analysis.

The data distribution can be seen below. The number of news reported on COVID-19 in the U.S were relatively low in the first 6 weeks (week 3 - week 8). However, there was a dramatic increase starting from week 9 and peaked in week 11 and 13 for Twitter and News respectively. This was the end of March when the number of infected cases in the country surged.

Pre-processing

For text data preparation, firstly, we created a corpus for the data set of each source. A corpus consists of a collection of documents (each document is an article or a tweet), and the document variables which describe the characteristics of the document, for instance published date and source. Subsequently, we tokenized each corpus, which separates the text into its single words (also called terms or tokens). A summary of the corpus for news articles can be seen below.

corpus_News_data <- corpus(news_data, text_field = c("text"), unique_docnames = F) %>%
  `docnames<-`(news_data$week) # update the name of document in the corpus
summary(corpus_News_data, 5)
Corpus consisting of 14149 documents, showing 5 documents:

 Text Types Tokens Sentences publish_date source week
 16.1   134    190         6   2020-04-19    CNN   16
 16.2    92    155         7   2020-04-19    CNN   16
 16.3   127    230         8   2020-04-19    CNN   16
 16.4   113    192         5   2020-04-19    CNN   16
 16.5   581   1509        54   2020-04-19    CNN   16
head(corpus_News_data, 5) # take a look at the corpus
Corpus consisting of 5 documents and 3 docvars.
16.1 :
"(CNN) Nothing can bring back the months of wedding planning ..."

16.2 :
"(CNN) Broadway actor Nick Cordero is recovering after having..."

16.3 :
"(CNN) A Louisiana pastor who defied state orders and repeate..."

16.4 :
"(CNN) More than 100,000 people defied Bangladesh lockdown or..."

16.5 :
"Hong Kong (CNN) Less than a month ago, Singapore was being h..."
corpus_Twitter_data <- corpus(tweets_data, text_field = c("text"), unique_docnames = F) %>%
  `docnames<-`(tweets_data$week)
stopwords_extended <- readLines("stopwords_en.txt", encoding = "UTF-8")
lemma_data <- read.csv("baseform_en.tsv", encoding = "UTF-8")

We pre-processed the data sets by lowering upper case letters and removing the numbers, punctuations, symbols, URLs and separators. The main idea is to reduce the final amount of terms extracted, which is important in order to improve the accuracy of both topic modeling and sentiment analysis. If two words are similar it is convenient to combine them as one unique word. Moreover, if a word is not relevant for the analysis, it can be removed. Hence, we implemented stop-words removal and lemmatization technique. Stopwords are words that appear in texts but do not give the text a substantial meaning (e.g., “the”, “a”, or “for”) and lemmatization deals with the inflected forms of words by replacing them with their base forms. The total number tokens and unique tokens in each source decreased by 40 – 70% after the above steps:

Token_news_data <- corpus_News_data %>% 
  tokens(remove_punct = TRUE, remove_numbers = TRUE, remove_symbols = TRUE, 
         remove_url = TRUE, remove_separators = TRUE) %>% 
  tokens_tolower(keep_acronyms = FALSE) %>%
  tokens_remove(pattern = c("amid", "updates", "live", "video", 
                            "didn", "briefing")) %>%
  tokens_replace(lemma_data$inflected_form, lemma_data$lemma, 
                 valuetype = "glob") %>%
  tokens_replace(pattern = c("covid-19", "ncov", "cov"), 
                 c("coronavirus", "coronavirus", "coronavirus"),
                 valuetype = "fixed") %>% 
  tokens_remove(pattern = stopwords_extended, padding = F)

Token_Twitter_data <- corpus_Twitter_data %>% 
  tokens(remove_punct = TRUE, remove_numbers = TRUE, remove_symbols = TRUE,
         remove_url = TRUE, remove_separators = TRUE) %>% 
  tokens_tolower(keep_acronyms = FALSE) %>%
  tokens_remove(pattern = c("people", "covid19", "covid", "rt", "dont")) %>%
  tokens_replace(lemma_data$inflected_form, lemma_data$lemma, 
                 valuetype = "glob") %>% 
  tokens_remove(pattern = stopwords_extended, padding = T)

In the next step, we generated a document-feature matrix (also known as document-term matrix) for each source. It represents how frequently terms (tokens) occur in the corpus (document) by counting single terms. We kept only the top 5% of the most frequent features (minimum term frequency set at 0.95) that present in less than 10% of all documents (maximum document frequency set at 0.1) to focus on common but distinctive features. We also dismissed the documents that had no tokens left after trimming. The dimensions of the two document-feature matrices are as follow:

News_DFM <- Token_news_data %>% 
  tokens_remove("") %>%
  dfm() %>% 
  dfm_trim(min_termfreq = 0.95, termfreq_type = "quantile",
           max_docfreq = 0.1, docfreq_type = "prop")
# We remove the token = 0
News_DFM <- News_DFM[ntoken(News_DFM) > 0, ]
#head(News_DFM, n = 5, nf = 8)

Twitter_DFM <- Token_Twitter_data %>% 
  tokens_remove("") %>%
  dfm() %>%
  dfm_trim(min_termfreq = 0.95, termfreq_type = "quantile", 
           max_docfreq = 0.1, docfreq_type = "prop")
# We remove the token = 0
Twitter_DFM <- Twitter_DFM[ntoken(Twitter_DFM) > 0,]

For better interpretation, the first 3 documents and 10 features of the document-feature matrix of news articles can be seen below.

News_DFM[1:3, 1:10]
Document-feature matrix of: 3 documents, 10 features (66.67% sparse) and 3 docvars.
      features
docs   wed waste alleviate engage couple stress beer chance hall postpone
  16.1   3     1         1      1      4      1    2      1    1        1
  16.2   0     0         0      0      0      0    0      0    0        0
  16.3   0     0         0      0      0      0    0      0    0        0

Topic Modelling

We discovered topics distributed in news articles and tweets on a weekly basis over the three-month period and compared the topics between the two media outlets. For topic modelling we used Structural Topic Modeling (STM), since it incorporates metadata (information about each document) into the topic modelling framework, so that we can discover topics and estimate their relationship to the documents’ metadata.

STM is an unsupervised machine learning model where we have to define the number of topic K in advance, similarly to k-means clustering we do not know ahead how many topics we should use for any given corpus. Therefore, we trained a group of topic models with different numbers of K (topics) and then evaluated how many topics are appropriate. Here we proceeded with K = 25 for each of the media forms. The evaluation method can be referred to in this post by Julia Silge.

News_stm <- convert(News_DFM, to = "stm")
Twitter_stm <- convert(Twitter_DFM, to = "stm")
News_topic_model <- stm(
  documents = News_stm$documents, 
  vocab = News_stm$vocab,
  K = 25,
  prevalence =~ s(week),
  data = News_stm$meta,
  init.type = "Spectral",
  seed = 123456)
Twitter_topic_model <- stm(
  documents = Twitter_stm$documents, 
  vocab = Twitter_stm$vocab,
  K = 25,
  prevalence =~ s(week),
  data = Twitter_stm$meta,
  init.type = "Spectral",
  seed = 123456)

The plots below show the top 10 topics in each corpus (News, Twitter), and top 7 words that have the highest probability to belong to that topic. A closer look into each source showed us some interesting patterns.

News_beta <- tidy(News_topic_model)
News_gamma <- tidy(News_topic_model, matrix = "gamma")

News_top_terms <- News_beta %>%
  arrange(beta) %>%
  group_by(topic) %>%
  top_n(7, beta) %>%
  arrange(-beta) %>%
  select(topic, term) %>%
  summarise(terms = list(term)) %>%
  mutate(terms = map(terms, paste, collapse = ", ")) %>% 
  unnest()

News_gamma_terms <- News_gamma %>%
  group_by(topic) %>%
  summarise(gamma = mean(gamma)) %>%
  arrange(desc(gamma)) %>%
  left_join(News_top_terms, by = "topic") %>%
  mutate(topic = paste0("Topic ", topic),
         topic = reorder(topic, gamma))

News_gamma_terms %>%
  top_n(10, gamma) %>%
  ggplot(aes(topic, gamma, label = terms, fill = topic)) +
  geom_col(show.legend = FALSE) +
  geom_text(hjust = 0.8, nudge_y = 0.0005, size = 3,
            family = "IBMPlexSans") +
  coord_flip() +
  scale_y_continuous(expand = c(0,0),
                     limits = c(0, 0.09),
                     labels = percent_format()) +
  theme_tufte(base_family = "IBMPlexSans", ticks = FALSE) +
  theme(plot.title = element_text(size = 16,
                                  family="IBMPlexSans-Bold"),
        plot.subtitle = element_text(size = 13)) +
  labs(x = NULL, y = expression(gamma),
       title = "Top 10 topics by popularity on News Articles",
       subtitle = "With the top words that contribute to each topic")

Twitter_beta <- tidy(Twitter_topic_model)
Twitter_gamma <- tidy(Twitter_topic_model, matrix = "gamma")

Twitter_top_terms <- Twitter_beta %>%
  arrange(beta) %>%
  group_by(topic) %>%
  top_n(7, beta) %>%
  arrange(-beta) %>%
  select(topic, term) %>%
  summarise(terms = list(term)) %>%
  mutate(terms = map(terms, paste, collapse = ", ")) %>% 
  unnest()

Twitter_gamma_terms <- Twitter_gamma %>%
  group_by(topic) %>%
  summarise(gamma = mean(gamma)) %>%
  arrange(desc(gamma)) %>%
  left_join(Twitter_top_terms, by = "topic") %>%
  mutate(topic = paste0("Topic ", topic),
         topic = reorder(topic, gamma))

Twitter_gamma_terms %>%
  top_n(10, gamma) %>%
  ggplot(aes(topic, gamma, label = terms, fill = topic)) +
  geom_col(show.legend = FALSE) +
  geom_text(hjust = 0.85, nudge_y = 0.0005, size = 3,
            family = "IBMPlexSans") +
  coord_flip() +
  scale_y_continuous(expand = c(0,0),
                     limits = c(0, 0.09),
                     labels = percent_format()) +
  theme_tufte(base_family = "IBMPlexSans", ticks = FALSE) +
  theme(plot.title = element_text(size = 16,
                                  family="IBMPlexSans-Bold"),
        plot.subtitle = element_text(size = 13)) +
  labs(x = NULL, y = expression(gamma),
       title = "Top 10 topics by popularity on Twitter",
       subtitle = "With the top words that contribute to each topic")

The key focuses on Twitter are about something like “the spread of virus (Topic 11)”, “negative reaction (Topic 7, 23)”, “update on the pandemic information (Topic 13, 4)”. On the contrary, when looking into News topics, we can see a relatively difference pattern, which is more related to “political matters – topic 22”, “situation in other country - topic 19”, “economy situation – topic 4”, “healthcare system situation (Topic 20, 21)”. The message about family is popular in both sources (News Topic 13, Twitter Topic 18). Furthermore, politicians are well-covered, with Trump on Twitter and Pence/ Cuomo on mainstream papers.

Sentiment Analysis

Corpus sentiment analysis

To investigate sentiments in news articles and tweets, tokens extracted from the documents are used to calculate sentiment scores with the AFINN lexicon developed by Finn Årup Nielsen, which is included in the tidytext package. The AFINN lexicon is a list of English terms manually rated for valence with an integer between -5 (negative) and +5 (positive). It comprises 878 positive terms and 1,598 negative terms. The sentiment score is the percentage of the difference between the absolute sum of positive terms and negative terms divided by the total sum of them.

# Make a dataframe with the AFINN dictionary
afinn <- get_sentiments("afinn")

News_ext <- convert(News_DFM, to = "tripletlist")
News_df <- data.frame(doc = News_ext$document,
                        word = News_ext$feature,
                        freq = News_ext$frequency)
News_df$word <- as.character(News_df$word)

News_afinn <- News_df %>% 
  inner_join(afinn, by = "word") %>% 
  mutate(score = freq * value) %>% 
  separate(doc, into = c("week", "no"), sep = "\\.") %>% 
  mutate(sentiment = ifelse(score > 0, "positive", "negative")) %>% 
  group_by(week, sentiment) %>% 
  summarise(sentiment_score = sum(score)) %>% 
  ungroup() %>% 
  mutate(source = "News")

Twitter_ext <- convert(Twitter_DFM, to = "tripletlist")
Twitter_df <- data.frame(doc = Twitter_ext$document,
                      word = Twitter_ext$feature,
                      freq = Twitter_ext$frequency)
Twitter_df$word <- as.character(Twitter_df$word)

Twitter_afinn <- Twitter_df %>% 
  inner_join(afinn, by = "word") %>% 
  mutate(score = freq * value) %>% 
  separate(doc, into = c("week", "no"), sep = "\\.") %>% 
  mutate(sentiment = ifelse(score > 0, "positive", "negative")) %>% 
  group_by(week, sentiment) %>% 
  summarise(sentiment_score = sum(score)) %>% 
  ungroup() %>% 
  mutate(source = "Twitter")

# Create a dataframe to plot sentiment
News_afinn_plot <- News_afinn %>% 
  pivot_wider(names_from = sentiment, values_from = sentiment_score) %>% 
  mutate(sum = positive + (-1)*negative, 
         pos_percent = positive/sum*100,
         neg_percent = (-1)*negative/sum*100, 
         polarity = round((pos_percent - neg_percent),3)) %>%
  select(week, polarity, source)

Twitter_afinn_plot <- Twitter_afinn %>% 
  pivot_wider(names_from = sentiment, values_from = sentiment_score) %>% 
  mutate(sum = positive + (-1)*negative, 
         pos_percent = positive/sum*100,
         neg_percent = (-1)*negative/sum*100, 
         polarity = round((pos_percent - neg_percent),3)) %>%
  select(week, polarity, source)

# Extract beta matrix to data frame format. Using AFINN lexicon, make a data frame with the sentiment for each word
News_beta <- tidy(News_topic_model, matrix = "beta")
News_topic_sc <- inner_join(News_beta, afinn, by = c("term" = "word")) %>% 
  mutate(score = beta * value) %>% 
  group_by(topic) %>% 
  summarise(sentiment_score = sum(score))
News_topic_sc$topic <- factor(News_topic_sc$topic, levels = c(1:25))

Twitter_beta <- tidy(Twitter_topic_model, matrix = "beta")
Twitter_topic_sc <- inner_join(Twitter_beta, afinn, by = c("term" = "word")) %>%  
  mutate(score = beta * value) %>% 
  group_by(topic) %>% 
  summarise(sentiment_score = sum(score))
Twitter_topic_sc$topic <- factor(Twitter_topic_sc$topic, levels = c(1:25))
afinn_chart_all <- rbind(News_afinn_plot, Twitter_afinn_plot)
afinn_chart_all$week <- as.numeric(as.character(afinn_chart_all$week))
afinn_chart_all %>% 
  arrange(week) %>% 
  ggplot(aes(x = week, y = polarity, color = source)) + 
  geom_point() +
  geom_path() +
  geom_hline(yintercept = 0, color = "gold3") +
  geom_vline(xintercept = 12, color = "coral2") +
  labs(x = "Week", y = "Sentiment Score") + 
  scale_x_continuous(  # This handles replacement of row 
    breaks = afinn_chart_all$week, # notice need to reuse data frame
    labels = afinn_chart_all$week) +
  scale_y_continuous(n.breaks = 10) +
  scale_colour_manual(values = c("#E3211C", "#1F78B4")) +
  theme(panel.grid = element_blank(),
        panel.background = NULL,
        axis.title = element_text(size = 16),
        axis.text = element_text(size = 16),
        legend.title = element_text(size = 16),
        legend.text = element_text(size = 16),
        legend.position = "bottom")

Overall, the opinion towards COVID-19 remained negative throughout the period. While news was a bit more positive than Twitter, there was a similar pattern as the sentiment scores were highly negative in week 3 but showed a positive trend in the subsequent weeks. At week 12 when the situation got worse in the US, the sentiment score of news articles went down then picked up again at week 15, whereas Twitter showed a consistent sentiment.

With the purpose of examining from several perspectives, we also made use of the NRC lexicon from Saif Mohammad and Peter Turney. The NRC lexicon categorizes words in a binary fashion (“yes”/ “no”) into categories of positive, negative, anger, anticipation, disgust, fear, joy, sadness, surprise, and trust. We filtered out the positive and negative categories which left us with 4,463 distinct words in the lexicon (Note: one word can be in multiple sentiment categories). We counted the number of words in each category and computed their percentage distribution in each of our sources. Applying NRC lexicon to inspect the data in different categorical sentiments, we presented the result in a radar chart:

nrc <- get_sentiments("nrc") %>% 
  filter(!sentiment %in%  c("positive", "negative"))

# News join and calculate score
News_nrc <- News_df %>% 
  inner_join(nrc) %>% 
  separate(doc, into = c("week", "no"), sep = "\\.") %>% 
  group_by(week, sentiment) %>% 
  summarise(count = sum(freq))
News_nrc_sum <- News_nrc %>% 
  group_by(sentiment) %>% 
  summarise(total_count = sum(count)) %>% 
  ungroup()
News_nrc_sum <- News_nrc_sum %>% 
  mutate(percent = total_count/ sum(News_nrc_sum$total_count),
         source = "News")

# Twitter join and calculate score
Twitter_nrc <- Twitter_df %>% 
  inner_join(nrc) %>% 
  separate(doc, into = c("week", "no"), sep = "\\.") %>% 
  group_by(week, sentiment) %>% 
  summarise(count = sum(freq))
Twitter_nrc_sum <- Twitter_nrc %>% 
  group_by(sentiment) %>% 
  summarise(total_count = sum(count)) %>% 
  ungroup()
Twitter_nrc_sum <- Twitter_nrc_sum %>% 
  mutate(percent = total_count/ sum(Twitter_nrc_sum$total_count),
         source = "Twitter")

# Combine data and plot radar chart
nrc_chart_all <- rbind(News_nrc_sum, Twitter_nrc_sum)
nrc_chart_all %>% 
  select(-total_count) %>% 
  pivot_wider(names_from = source, values_from = percent) %>% 
  chartJSRadar(width = 8,
               height = 5,
               showToolTipLabel = FALSE,
               colMatrix = grDevices::col2rgb(c("red", "blue", "green")),
               labelSize = 18)

Overall, news articles showed the most positivity by coming on top of “joy” and “trust”, but it also had more “anger” words. Reddit were dominant in most negative categories, such as “sadness”, “fear” and “anticipation”. Twitter’s posts were more negative, as they expressed “disgust”, “sadness”, and somehow “surprise”. This turned out to be a relevant interpretation of the outcome of the AFINN lexicon analysis above.

Topic-based sentiment analysis

On the topic-based level, we assigned the sentiment value for each topic word based on the lexicon and the probability of a word in a topic given by the STM topic model as the term weight of the word. As a result, topic sentiment score is calculated as

\[Sentiment\ Score\ of\ Topic\ A = \sum_{i=1}^{n} (prob(word_i|Topic_A)*sentiment\ value(word_i))\]

An overall topic sentiment score is computed by multiplying the sentiment value by the probability of words and summing the products in a chosen topic. Multiple topics could have the same words with different probability values. Therefore, the sentiment score of a topic would be distinguished from others even if the same set of words appear in different topics.


# News
News_topic_sc_plot <- News_topic_sc %>% 
  ggplot(aes(x = topic, y = sentiment_score)) + 
  geom_col(fill = "#E3211C") +
  geom_hline(yintercept = 0, color = "gold3") +
  labs(x = NULL, y = NULL, subtitle = "News") + 
  scale_y_continuous(limits = c(-1, 0.2), n.breaks = 8) +
  theme(panel.grid = element_blank(),
        panel.background = NULL,
        axis.title = element_text(size = 16),
        axis.text = element_text(size = 14),
        plot.subtitle = element_text(size = rel(1.5)))

# Twitter
Twitter_topic_sc_plot <- Twitter_topic_sc %>% 
  ggplot(aes(x = topic, y = sentiment_score)) + 
  geom_col(fill = "#1F78B4") +
  geom_hline(yintercept = 0, color = "gold3") +
  labs(x = "Topic", y = NULL, subtitle = "Twitter") + 
  scale_y_continuous(limits = c(-1, 0.2), n.breaks = 8) +
  theme(panel.grid = element_blank(),
        panel.background = NULL,
        axis.title = element_text(size = 16),
        axis.text = element_text(size = 14),
        plot.subtitle = element_text(size = rel(1.5)))

grid.arrange(News_topic_sc_plot, Twitter_topic_sc_plot)

Using STM model with the same number of topics of 25, we calculated the sentiment score of each topic. Again, the general opinions in most topics were negative. The sentiments were more significant in Twitter, while in news articles most topics had the scores closer to neutral. Topic 7 in Twitter was extremely negative, which mostly consist of sentimental words (hell, yall, shit…). This was one downside of unsupervised topic modelling, as it grouped these sentimental words together in one topic, but the interpretation was not useful for topic discovery. Excluding the topics above, news and Twitter had a few notable negativities, with topic 22 (political, pence, tweet, blame, party, attack…) and 23 (police, prison, court, law, jail…) in news and topic 12 (die, flu, trump…) in Twitter. Twitter users seemed to have the concerns centered around President Trump’s behaviors, while the news media gravitated towards the conflict of political parties and worries about social security.

Among the positive topics, there was a homogeneous them in all sources. Topic 13 in the news (love, church, moment, wife, mother…) and Topic 18 (family, friend, pray…) and 15 (protect, god, love, jesus…) in Twitter had the same theme of faith and belief, though the positive scores were mild.

Conclusion

This project studies the topic coverage and sentiment dynamics of the sensitive topic COVID-19 in News media and Twitter. Although the project has revealed different characteristics of news articles and Twitter, it only conducts analysis on the text property and the time variable. Many meta-data were removed from the raw data which might leave out some important aspects that could be elaborated further. Other choices that might lead to research bias were the data samples which just cover subsets of keywords and the dictionaries used for pre-processing and sentiment analysis. Lastly, the time frame of data collection is only three months, ending at the middle of April when the pandemic was still escalating in the US. It would be better If we collect the data and conduct the analysis after the pandemic is over, which would give a full overview of the situation.

LS0tDQp0aXRsZTogVGV4dCBtaW5pbmcgb2YgbWFpbnN0cmVhbSBuZXdzIGFuZCBUd2l0dGVyIGFib3V0IENvcm9uYXZpcnVzIG91dGJyZWFrIGluIHRoZSBVU0EuDQphdXRob3I6IFBob25nIFZpZXQgTmd1eWVuDQpkYXRlOiAiMjAyMC0xMi0wNSINCm91dHB1dDogDQogICAgaHRtbF9ub3RlYm9vazoNCiAgICAgIHRvYzogdHJ1ZQ0KLS0tDQoNCiMgSW50cm9kdWN0aW9uDQoNCkluIHRoaXMgcHJvamVjdCwgd2UgbG9vayBhdCB0aGUgY292ZXJhZ2Ugb2YgQ29yb25hdmlydXMgb24gbWFpbnN0cmVhbSBuZXdzIGFydGljbGVzIGFuZCBUd2l0dGVyIGluIHRoZSBVU0EuIFRoZSBtYWluIGdvYWwgaXMgdG8gaW5zcGVjdCB0aGUgZGlmZmVyZW5jZSBpbiB0aGUgZm9jdXMgb2YgZWFjaCBtZWRpYSBvdXRsZXQgKHRvcGljIG1vZGVsbGluZykgYW5kIHRoZWlyIGV4cHJlc3NlZCBhdHRpdHVkZXMgKHNlbnRpbWVudCBhbmFseXNpcykgb24gQ09WSUQtMTkuDQoNClRoZSBwcm9qZWN0IGlzIGNvbmR1Y3RlZCB3aXRoIHRoZSBmb2xsb3dpbmcgc3RlcHM6IERhdGEgY29sbGVjdGlvbiwgRGF0YSBjbGVhbmluZyBhbmQgUHJlLXByb2Nlc3NpbmcsIFRvcGljIG1vZGVsaW5nLCBhbmQgU2VudGltZW50IGFuYWx5c2lzLiBUaGUgZGF0YSB3YXMgZ2F0aGVyZWQgdXNpbmcgd2ViLXNjcmFwaW5nIHRlY2huaXF1ZSB3aXRoIFIgYW5kIFB5dGhvbiBwcm9ncmFtbWluZy4gQWZ0ZXIgZGF0YSBjbGVhbmluZywgdGhlICpRdWFudGVkYSogcGFja2FnZSBpbiBSIHdhcyB1c2VkIHRvIHByZXBhcmUgZm9yIHRleHQgYW5hbHlzaXMuIFRoZW4sIHdlIGFwcGxpZWQgdG9waWMgbW9kZWxsaW5nIHRvIGlkZW50aWZ5IGRpc3RpbmN0IHRvcGljcy4gSW4gc2VudGltZW50IGFuYWx5c2lzLCB3ZSBjaG9zZSBhIGxleGljb24sIGNhbGN1bGF0ZWQgc2VudGltZW50cyBzY29yZXMgYW5kIGxvb2tlZCBhdCB0aGUgc2hpZnQgaW4gc2VudGltZW50cy4NCg0KVGhlIHJlc3VsdCBoYXMgcmV2ZWFsZWQgc29tZSBkaXNwYXJpdGllcyBiZXR3ZWVuIHRoZSBtZWRpYSBzb3VyY2VzLiBTb2NpYWwgbWVkaWEsIG5hbWVseSBUd2l0dGVyLCBhcmUgcmVmbGVjdGluZyBtb3JlIG9uIHBlb3BsZcK0cyBzZW50aW1lbnRzIGFuZCBxdWljayB1cGRhdGVzIG9mIHRoZSBzaXR1YXRpb24gd2hpbGUgbmV3cyBhcnRpY2xlcyBhcmUgbW9yZSBhYm91dCBtYWNybyBwcm9ibGVtcy4gVGhlIHR3byBtZWRpYSdzIHNlbnRpbWVudCByZW1haW5lZCBuZWdhdGl2ZSB0aHJvdWdob3V0IHRoZSBvYnNlcnZlZCBwZXJpb2QuDQoNCmBgYHtyIFBhY2thZ2VzLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpICMgZGF0YSBtYW5pcHVsYXRpb24NCmxpYnJhcnkocXVhbnRlZGEpICMgdGV4dCBwcmUtcHJvY2Vzc2luZw0KbGlicmFyeShxdWFudGVkYS5kaWN0aW9uYXJpZXMpDQpsaWJyYXJ5KHRpZHl0ZXh0KSAjIHRleHQgYW5hbHlzaXMNCmxpYnJhcnkobHVicmlkYXRlKSAjIGRhdGUgZnVuY3Rpb24NCmxpYnJhcnkoZ3JpZEV4dHJhKSAjIG11bHRpcGxlIGdyYXBocw0KbGlicmFyeShzdG0pICMgdG9waWMgbW9kZWxsaW5nDQpsaWJyYXJ5KHN0bUNvcnJWaXopDQpsaWJyYXJ5KGZ1cnJyKQ0KbGlicmFyeSh0bSkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShnZ3RoZW1lcykNCmxpYnJhcnkocmFkYXJjaGFydCkNCmBgYA0KDQojIERhdGEgQ29sbGVjdGlvbiBhbmQgQ2xlYW5pbmcNCg0KIyMgTmV3cyBBcnRpY2xlcw0KDQpVc2luZyB0aGUga2V5d29yZCAqY29yb25hdmlydXMqIGZvciBxdWVyeWluZywgd2UgY29sbGVjdGVkIG5ld3MgYXJ0aWNsZXMgcHVibGlzaGVkIG9uIG5ld3Mgd2Vic2l0ZXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMgZnJvbSB0aGUgYmVnaW5uaW5nIG9mIDIwMjAsIHdoZXJlIHRoZSBmaXJzdCBjYXNlcyBvZiBjb3JvbmF2aXJ1cyB3ZXJlIHJlcG9ydGVkLCB1bnRpbCBBcHJpbCAxOSwgMjAyMC4gRm9yIHNvdXJjZXMsIHdlIGxvb2tlZCBhdCB0aGUgdG9wIDE1IFUuUyBuZXdzIHdlYnNpdGVzIG1lYXN1cmVkIGJ5IHVuaXF1ZSBtb250aGx5IHZpc2l0b3JzIChTdGF0aXN0YSwgMjAyMCksIGV4Y2x1ZGluZyB0aGUgbmV3cyBhZ2dyZWdhdG9ycyAoWWFob28gTmV3cywgR29vZ2xlIE5ld3MpIGFuZCB0b3BpYy1zcGVjaWZpYyBuZXdzcGFwZXJzIChUaGUgV2FsbCBTdHJlZXQgSm91cm5hbCkuIFdlIHVzZWQgYSB0aGlyZC1wYXJ0eSBBUEkgY2FsbGVkICpDdXJyZW50cyBBUEkqIGluIFIgdG8gZ2V0IGFsbCB0aGUgYXZhaWxhYmxlIFVSTHMsIHRoZW4gcHV0IHRoZW0gaW50byB0aGUgbmV3c3BhcGVyM2sgbW9kdWxlIGluIFB5dGhvbiwgd2hpY2ggZW5hYmxlZCBzY3JhcGluZyB0aGUgZW50aXJlIGFydGljbGVzLiBGdXJ0aGVybW9yZSwgYWZ0ZXIgY2hlY2tpbmcgdGhlIGRhdGEgcXVhbGl0eSBmcm9tIGVhY2ggc291cmNlLCB3ZSBuYXJyb3dlZCB0aGVtIGRvd24gZnJvbSAxNSB0byA2IG5ld3Mgb3V0bGV0czogQ05OLCBUaGUgTmV3IFlvcmsgVGltZXMsIEZveCBOZXdzLCBUaGUgR3VhcmRpYW4sIFVTQSBUb2RheSBhbmQgVGhlIExBIFRpbWVzLg0KDQpgYGB7ciwgbWVzc2FnZT1GQUxTRX0NCiMgTG9hZCB0aGUgc2NyYXBlZCBkYXRhDQpuZXdzX2RhdGEgPC0gcmVhZF9jc3YoIm5ld3NfY29yb25hdmlydXMuY3N2IikNCg0KIyBBZGQgd2VlayBhbmQgcmVtb3ZlIHVubmVjZXNzYXJ5IGNvbHVtbg0KbmV3c19kYXRhIDwtIG5ld3NfZGF0YSAlPiUgDQogIG11dGF0ZSh3ZWVrID0gaXNvd2VlayhwdWJsaXNoX2RhdGUpKSAlPiUgDQogIHNlbGVjdCgtdGl0bGUpDQoNCiMgUHJldmlldyB0aGUgZGF0YQ0KZ2xpbXBzZShuZXdzX2RhdGEpDQpgYGANCg0KIyMgVHdpdHRlcg0KDQpUaGFua3MgdG8gdGhlIHN1cHBvcnQgZnJvbSB0aGUgdGVhbSBhdCA8Y3Jvd2RicmVha3Mub3JnPiwgd2hvIGlzIHRyYWNraW5nIFR3aXR0ZXIgdHJlbmQgb24gQ09WSUQtMTkgaW4gcmVhbCB0aW1lLCB3ZSBtYW5hZ2VkIHRvIGdldCBhbGwgdHdlZXQgSURzIHRoYXQgdGhleSBoYWQgY29sbGVjdGVkIHNpbmNlIEphbnVhcnkgMjAyMCBpbiB0aGUgVVMgd2l0aCB0aGUga2V5d29yZHMgb2Yg4oCcd3VoYW7igJ0sIOKAnG5jb3bigJ0sIOKAnGNvcm9uYXZpcnVz4oCdLCDigJxjb3ZpZOKAnSwg4oCcc2Fycy1jb3YtMuKAnS4gV2UgZGVjaWRlZCB0byB0YWtlIHN0cmF0aWZpZWQgc2FtcGxpbmcgb2YgdGhlIGRhdGEgKDUwJSkgdG8ga2VlcCB0aGUgZGlzdHJpYnV0aW9uIG9mIG51bWJlciBvZiB0d2VldHMgcGVyIHdlZWsgYW5kIHNwZWVkIHVwIGRhdGEgY29sbGVjdGlvbiBhbmQgb2J0YWluIHRoZSBkYXRhIGluIHRpbWUgZm9yIHRoZSByZXBvcnQuIFRoZSBUd2l0dGVyIGRhdGEgd2VyZSBjb2xsZWN0ZWQgdW50aWwgQXByaWwgMTYsIDIwMjAuDQoNCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQ0KIyBMb2FkIHRoZSBzY3JhcGVkIGRhdGENCnR3ZWV0c19kYXRhIDwtIHJlYWRfY3N2KCJ0d2l0dGVyX2Nvcm9uYXZpcnVzLmNzdiIpDQoNCiMgVHJhbnNmb3JtIHRoZSBkYXRlIGNvbHVtbg0KdHdlZXRzX2RhdGEgPC0gdHdlZXRzX2RhdGEgJT4lIA0KICBzZXBhcmF0ZShjcmVhdGVkX2F0LCBjKCJ3ZGF5IiwgIm1vbnRoIiwgImRheSIsICJ0aW1lIiwgInBsdXMiLCAieWVhciIpLCANCiAgICAgICAgICAgc2VwID0gIiAiKSAlPiUgDQogIG11dGF0ZShkYXRlID0gcGFzdGUobW9udGgsIGRheSwgeWVhciwgc2VwID0gIiAiKSkgJT4lIA0KICBzZWxlY3QoYygidGV4dCIsICJkYXRlIikpDQoNCnR3ZWV0c19kYXRhJGRhdGUgPC0gYXMuRGF0ZSh0d2VldHNfZGF0YSRkYXRlLCBmb3JtYXQgPSAiJWIgJWQgJVkiKQ0KdHdlZXRzX2RhdGEgPC0gdHdlZXRzX2RhdGEgJT4lIA0KICBtdXRhdGUod2VlayA9IGlzb3dlZWsoZGF0ZSkpICU+JSANCiAgZmlsdGVyKHdlZWsgPiAyKQ0KDQojIENsZWFuIGhhc2h0YWdzLCBsaW5rcyBhbmQgc3BlY2lhbCBjaGFyYWN0ZXJzDQp0d2VldHNfZGF0YSR0ZXh0IDwtIHR3ZWV0c19kYXRhJHRleHQgJT4lIA0KICBzdHJfcmVwbGFjZV9hbGwoIiMiLCAiICIpICU+JQ0KICBzdHJfcmVtb3ZlX2FsbCgiKD88PV58XFxzKWh0dHBbXlxcc10rIikgJT4lIA0KICBzdHJfcmVtb3ZlX2FsbCgiW15hLXpBLVowLTkgXSIpICU+JSANCiAgdHJpbXdzKCkNCg0KIyBSZW1vdmUgYmxhbmsgdGV4dCBhZnRlciBjbGVhbmluZw0KdHdlZXRzX2RhdGEgPC0gdHdlZXRzX2RhdGEgJT4lIA0KICBmaWx0ZXIoc3RyX2NvdW50KHRleHQsIHBhdHRlcm4gPSBib3VuZGFyeSgid29yZCIpKSA+IDEpDQpgYGANCg0KIyMgRGF0YSBPdmVydmlldw0KDQpGb3IgZnVydGhlciBkYXRhIGNsZWFuaW5nLCB3ZSByZW1vdmVkIGR1cGxpY2F0ZWQgZGF0YSwgdGV4dHMgdGhhdCB3ZXJlIHRvbyBzaG9ydCBhbmQga2VwdCBvbmx5IHRleHRzIHdyaXR0ZW4gaW4gRW5nbGlzaC4gV2Uga2VwdCB0aGUgdGltZSB2YXJpYWJsZSBpbiB3ZWVrIGZvcm1hdCBhbmQgdGhlIGZ1bGwgdGV4dCBvZiB0aGUgZG9jdW1lbnQgZm9yIGFuYWx5c2lzLiBDb25zZXF1ZW50bHksIDE0LDE0OSBuZXdzIGFydGljbGVzIGFuZCAxMDksMzI5IHR3ZWV0cyB3ZXJlIHJlYWR5IGZvciBhbmFseXNpcy4NCg0KVGhlIGRhdGEgZGlzdHJpYnV0aW9uIGNhbiBiZSBzZWVuIGJlbG93LiBUaGUgbnVtYmVyIG9mIG5ld3MgcmVwb3J0ZWQgb24gQ09WSUQtMTkgaW4gdGhlIFUuUyB3ZXJlIHJlbGF0aXZlbHkgbG93IGluIHRoZSBmaXJzdCA2IHdlZWtzICh3ZWVrIDMgLSB3ZWVrIDgpLiBIb3dldmVyLCB0aGVyZSB3YXMgYSBkcmFtYXRpYyBpbmNyZWFzZSBzdGFydGluZyBmcm9tIHdlZWsgOSBhbmQgcGVha2VkIGluIHdlZWsgMTEgYW5kIDEzIGZvciBUd2l0dGVyIGFuZCBOZXdzIHJlc3BlY3RpdmVseS4gVGhpcyB3YXMgdGhlIGVuZCBvZiBNYXJjaCB3aGVuIHRoZSBudW1iZXIgb2YgaW5mZWN0ZWQgY2FzZXMgaW4gdGhlIGNvdW50cnkgc3VyZ2VkLiANCg0KYGBge3IgRGF0YSBDb3VudCwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCnBsb3RfbmV3cyA8LSBuZXdzX2RhdGEgJT4lDQogIGdyb3VwX2J5KHdlZWspICU+JQ0KICBzdW1tYXJpc2UobiA9IG4oKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBtdXRhdGUoc291cmNlID0gIk5ld3MiKQ0KDQpwbG90X3R3ZWV0cyA8LSB0d2VldHNfZGF0YSAlPiUNCiAgZ3JvdXBfYnkod2VlaykgJT4lDQogIHN1bW1hcmlzZShuID0gbigpKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIG11dGF0ZShzb3VyY2UgPSAiVHdpdHRlciIpDQpgYGANCg0KYGBge3IgRGF0YSBEaXN0cmlidXRpb24sIGVjaG89RkFMU0V9DQoNCm5ld3NfZGlzdHJpYnV0aW9uIDwtIHBsb3RfbmV3cyAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gd2VlaykpICsgDQogIGdlb21fY29sKGFlcyh5ID0gbiwgZmlsbCA9IC1uKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobi5icmVha3MgPSAxMCkgKw0KICBsYWJzKHggPSAid2VlayIsIHkgPSAibnVtYmVyIG9mIGRvY3VtZW50cyIsIHN1YnRpdGxlID0gIk5ld3MiKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGhqdXN0ID0gLjUsIHZqdXN0ID0gLjUpLA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksDQogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9yZWN0KCJsaWdodGdyYXkiLCBmaWxsID0gTkEpLA0KICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIHNpemUgPSByZWwoMS44KSkpDQoNCnR3ZWV0c19kaXN0cmlidXRpb24gPC0gcGxvdF90d2VldHMgJT4lDQogIGdncGxvdChhZXMoeCA9IHdlZWspKSArIA0KICBnZW9tX2NvbChhZXMoeSA9IG4sIGZpbGwgPSAtbiksIHNob3cubGVnZW5kID0gRkFMU0UpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKG4uYnJlYWtzID0gMTApICsNCiAgbGFicyh4ID0gIndlZWsiLCB5ID0gTlVMTCwgc3VidGl0bGUgPSAiVHdpdHRlciIpICsNCiAgdGhlbWUoDQogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgaGp1c3QgPSAuNSwgdmp1c3QgPSAuNSksDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoImxpZ2h0Z3JheSIsIGZpbGwgPSBOQSksDQogICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgc2l6ZSA9IHJlbCgxLjgpKSkNCg0KZ3JpZC5hcnJhbmdlKG5ld3NfZGlzdHJpYnV0aW9uLCB0d2VldHNfZGlzdHJpYnV0aW9uLCBuY29sID0gMikNCmBgYA0KDQojIFByZS1wcm9jZXNzaW5nDQoNCkZvciB0ZXh0IGRhdGEgcHJlcGFyYXRpb24sIGZpcnN0bHksIHdlIGNyZWF0ZWQgYSBjb3JwdXMgZm9yIHRoZSBkYXRhIHNldCBvZiBlYWNoIHNvdXJjZS4gQSBjb3JwdXMgY29uc2lzdHMgb2YgYSBjb2xsZWN0aW9uIG9mIGRvY3VtZW50cyAoZWFjaCBkb2N1bWVudCBpcyBhbiBhcnRpY2xlIG9yIGEgdHdlZXQpLCBhbmQgdGhlIGRvY3VtZW50IHZhcmlhYmxlcyB3aGljaCBkZXNjcmliZSB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSBkb2N1bWVudCwgZm9yIGluc3RhbmNlIHB1Ymxpc2hlZCBkYXRlIGFuZCBzb3VyY2UuIFN1YnNlcXVlbnRseSwgd2UgdG9rZW5pemVkIGVhY2ggY29ycHVzLCB3aGljaCBzZXBhcmF0ZXMgdGhlIHRleHQgaW50byBpdHMgc2luZ2xlIHdvcmRzIChhbHNvIGNhbGxlZCB0ZXJtcyBvciB0b2tlbnMpLiBBIHN1bW1hcnkgb2YgdGhlIGNvcnB1cyBmb3IgbmV3cyBhcnRpY2xlcyBjYW4gYmUgc2VlbiBiZWxvdy4NCg0KYGBge3IgQ3JlYXRlIGEgY29ycHVzfQ0KY29ycHVzX05ld3NfZGF0YSA8LSBjb3JwdXMobmV3c19kYXRhLCB0ZXh0X2ZpZWxkID0gYygidGV4dCIpLCB1bmlxdWVfZG9jbmFtZXMgPSBGKSAlPiUNCiAgYGRvY25hbWVzPC1gKG5ld3NfZGF0YSR3ZWVrKSAjIHVwZGF0ZSB0aGUgbmFtZSBvZiBkb2N1bWVudCBpbiB0aGUgY29ycHVzDQpzdW1tYXJ5KGNvcnB1c19OZXdzX2RhdGEsIDUpDQpoZWFkKGNvcnB1c19OZXdzX2RhdGEsIDUpICMgdGFrZSBhIGxvb2sgYXQgdGhlIGNvcnB1cw0KDQpjb3JwdXNfVHdpdHRlcl9kYXRhIDwtIGNvcnB1cyh0d2VldHNfZGF0YSwgdGV4dF9maWVsZCA9IGMoInRleHQiKSwgdW5pcXVlX2RvY25hbWVzID0gRikgJT4lDQogIGBkb2NuYW1lczwtYCh0d2VldHNfZGF0YSR3ZWVrKQ0KYGBgDQoNCmBgYHtyIFN0b3Atd29yZHMgYW5kIEJhc2UtZm9ybWVkIHdvcmRzfQ0Kc3RvcHdvcmRzX2V4dGVuZGVkIDwtIHJlYWRMaW5lcygic3RvcHdvcmRzX2VuLnR4dCIsIGVuY29kaW5nID0gIlVURi04IikNCmxlbW1hX2RhdGEgPC0gcmVhZC5jc3YoImJhc2Vmb3JtX2VuLnRzdiIsIGVuY29kaW5nID0gIlVURi04IikNCmBgYA0KDQpXZSBwcmUtcHJvY2Vzc2VkIHRoZSBkYXRhIHNldHMgYnkgbG93ZXJpbmcgdXBwZXIgY2FzZSBsZXR0ZXJzIGFuZCByZW1vdmluZyB0aGUgbnVtYmVycywgcHVuY3R1YXRpb25zLCBzeW1ib2xzLCBVUkxzIGFuZCBzZXBhcmF0b3JzLiBUaGUgbWFpbiBpZGVhIGlzIHRvIHJlZHVjZSB0aGUgZmluYWwgYW1vdW50IG9mIHRlcm1zIGV4dHJhY3RlZCwgd2hpY2ggaXMgaW1wb3J0YW50IGluIG9yZGVyIHRvIGltcHJvdmUgdGhlIGFjY3VyYWN5IG9mIGJvdGggdG9waWMgbW9kZWxpbmcgYW5kIHNlbnRpbWVudCBhbmFseXNpcy4gSWYgdHdvIHdvcmRzIGFyZSBzaW1pbGFyIGl0IGlzIGNvbnZlbmllbnQgdG8gY29tYmluZSB0aGVtIGFzIG9uZSB1bmlxdWUgd29yZC4gTW9yZW92ZXIsIGlmIGEgd29yZCBpcyBub3QgcmVsZXZhbnQgZm9yIHRoZSBhbmFseXNpcywgaXQgY2FuIGJlIHJlbW92ZWQuIEhlbmNlLCB3ZSBpbXBsZW1lbnRlZCBzdG9wLXdvcmRzIHJlbW92YWwgYW5kIGxlbW1hdGl6YXRpb24gdGVjaG5pcXVlLiBTdG9wd29yZHMgYXJlIHdvcmRzIHRoYXQgYXBwZWFyIGluIHRleHRzIGJ1dCBkbyBub3QgZ2l2ZSB0aGUgdGV4dCBhIHN1YnN0YW50aWFsIG1lYW5pbmcgKGUuZy4sICJ0aGUiLCAiYSIsIG9yICJmb3IiKSBhbmQgbGVtbWF0aXphdGlvbiBkZWFscyB3aXRoIHRoZSBpbmZsZWN0ZWQgZm9ybXMgb2Ygd29yZHMgYnkgcmVwbGFjaW5nIHRoZW0gd2l0aCB0aGVpciBiYXNlIGZvcm1zLiBUaGUgdG90YWwgbnVtYmVyIHRva2VucyBhbmQgdW5pcXVlIHRva2VucyBpbiBlYWNoIHNvdXJjZSBkZWNyZWFzZWQgYnkgNDAg4oCTIDcwJSBhZnRlciB0aGUgYWJvdmUgc3RlcHM6DQoNCmBgYHtyIENyZWF0ZSB0b2tlbnN9DQpUb2tlbl9uZXdzX2RhdGEgPC0gY29ycHVzX05ld3NfZGF0YSAlPiUgDQogIHRva2VucyhyZW1vdmVfcHVuY3QgPSBUUlVFLCByZW1vdmVfbnVtYmVycyA9IFRSVUUsIHJlbW92ZV9zeW1ib2xzID0gVFJVRSwgDQogICAgICAgICByZW1vdmVfdXJsID0gVFJVRSwgcmVtb3ZlX3NlcGFyYXRvcnMgPSBUUlVFKSAlPiUgDQogIHRva2Vuc190b2xvd2VyKGtlZXBfYWNyb255bXMgPSBGQUxTRSkgJT4lDQogIHRva2Vuc19yZW1vdmUocGF0dGVybiA9IGMoImFtaWQiLCAidXBkYXRlcyIsICJsaXZlIiwgInZpZGVvIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgImRpZG4iLCAiYnJpZWZpbmciKSkgJT4lDQogIHRva2Vuc19yZXBsYWNlKGxlbW1hX2RhdGEkaW5mbGVjdGVkX2Zvcm0sIGxlbW1hX2RhdGEkbGVtbWEsIA0KICAgICAgICAgICAgICAgICB2YWx1ZXR5cGUgPSAiZ2xvYiIpICU+JQ0KICB0b2tlbnNfcmVwbGFjZShwYXR0ZXJuID0gYygiY292aWQtMTkiLCAibmNvdiIsICJjb3YiKSwgDQogICAgICAgICAgICAgICAgIGMoImNvcm9uYXZpcnVzIiwgImNvcm9uYXZpcnVzIiwgImNvcm9uYXZpcnVzIiksDQogICAgICAgICAgICAgICAgIHZhbHVldHlwZSA9ICJmaXhlZCIpICU+JSANCiAgdG9rZW5zX3JlbW92ZShwYXR0ZXJuID0gc3RvcHdvcmRzX2V4dGVuZGVkLCBwYWRkaW5nID0gRikNCg0KVG9rZW5fVHdpdHRlcl9kYXRhIDwtIGNvcnB1c19Ud2l0dGVyX2RhdGEgJT4lIA0KICB0b2tlbnMocmVtb3ZlX3B1bmN0ID0gVFJVRSwgcmVtb3ZlX251bWJlcnMgPSBUUlVFLCByZW1vdmVfc3ltYm9scyA9IFRSVUUsDQogICAgICAgICByZW1vdmVfdXJsID0gVFJVRSwgcmVtb3ZlX3NlcGFyYXRvcnMgPSBUUlVFKSAlPiUgDQogIHRva2Vuc190b2xvd2VyKGtlZXBfYWNyb255bXMgPSBGQUxTRSkgJT4lDQogIHRva2Vuc19yZW1vdmUocGF0dGVybiA9IGMoInBlb3BsZSIsICJjb3ZpZDE5IiwgImNvdmlkIiwgInJ0IiwgImRvbnQiKSkgJT4lDQogIHRva2Vuc19yZXBsYWNlKGxlbW1hX2RhdGEkaW5mbGVjdGVkX2Zvcm0sIGxlbW1hX2RhdGEkbGVtbWEsIA0KICAgICAgICAgICAgICAgICB2YWx1ZXR5cGUgPSAiZ2xvYiIpICU+JSANCiAgdG9rZW5zX3JlbW92ZShwYXR0ZXJuID0gc3RvcHdvcmRzX2V4dGVuZGVkLCBwYWRkaW5nID0gVCkNCmBgYA0KDQoNCmBgYHtyIE51bWJlciBvZiB0b2tlbnMsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQp0aWJibGUoDQogIFNvdXJjZSA9IGMoIk5ld3MiLCAiVHdpdHRlciIpLCANCiAgQ29ycHVzID0gYygxNDE0OSwgMzUyODQyKSwgDQogIE51bWJlcl9vZl90b2tlbnMgPSBjKCIzOTM4NjM5ICgtNTkuNiUpIiwgIjU3MjkzNjAgKC02OC43JSkiKSwNCiAgVW5pcXVlX3Rva2VucyA9IGMoIjI1MzQ1MTggKC00Mi41JSkiLCAiNTA2NTEzNiAoLTYyLjklKSIpDQopDQpgYGANCg0KSW4gdGhlIG5leHQgc3RlcCwgd2UgZ2VuZXJhdGVkIGEgZG9jdW1lbnQtZmVhdHVyZSBtYXRyaXggKGFsc28ga25vd24gYXMgZG9jdW1lbnQtdGVybSBtYXRyaXgpIGZvciBlYWNoIHNvdXJjZS4gSXQgcmVwcmVzZW50cyBob3cgZnJlcXVlbnRseSB0ZXJtcyAodG9rZW5zKSBvY2N1ciBpbiB0aGUgY29ycHVzIChkb2N1bWVudCkgYnkgY291bnRpbmcgc2luZ2xlIHRlcm1zLiBXZSBrZXB0IG9ubHkgdGhlIHRvcCA1JSBvZiB0aGUgbW9zdCBmcmVxdWVudCBmZWF0dXJlcyAobWluaW11bSB0ZXJtIGZyZXF1ZW5jeSBzZXQgYXQgMC45NSkgdGhhdCBwcmVzZW50IGluIGxlc3MgdGhhbiAxMCUgb2YgYWxsIGRvY3VtZW50cyAobWF4aW11bSBkb2N1bWVudCBmcmVxdWVuY3kgc2V0IGF0IDAuMSkgdG8gZm9jdXMgb24gY29tbW9uIGJ1dCBkaXN0aW5jdGl2ZSBmZWF0dXJlcy4gV2UgYWxzbyBkaXNtaXNzZWQgdGhlIGRvY3VtZW50cyB0aGF0IGhhZCBubyB0b2tlbnMgbGVmdCBhZnRlciB0cmltbWluZy4gVGhlIGRpbWVuc2lvbnMgb2YgdGhlIHR3byBkb2N1bWVudC1mZWF0dXJlIG1hdHJpY2VzIGFyZSBhcyBmb2xsb3c6DQoNCmBgYHtyIEtlZXAgdG9wIGZlYXR1cmVzfQ0KTmV3c19ERk0gPC0gVG9rZW5fbmV3c19kYXRhICU+JSANCiAgdG9rZW5zX3JlbW92ZSgiIikgJT4lDQogIGRmbSgpICU+JSANCiAgZGZtX3RyaW0obWluX3Rlcm1mcmVxID0gMC45NSwgdGVybWZyZXFfdHlwZSA9ICJxdWFudGlsZSIsDQogICAgICAgICAgIG1heF9kb2NmcmVxID0gMC4xLCBkb2NmcmVxX3R5cGUgPSAicHJvcCIpDQojIFdlIHJlbW92ZSB0aGUgdG9rZW4gPSAwDQpOZXdzX0RGTSA8LSBOZXdzX0RGTVtudG9rZW4oTmV3c19ERk0pID4gMCwgXQ0KI2hlYWQoTmV3c19ERk0sIG4gPSA1LCBuZiA9IDgpDQoNClR3aXR0ZXJfREZNIDwtIFRva2VuX1R3aXR0ZXJfZGF0YSAlPiUgDQogIHRva2Vuc19yZW1vdmUoIiIpICU+JQ0KICBkZm0oKSAlPiUNCiAgZGZtX3RyaW0obWluX3Rlcm1mcmVxID0gMC45NSwgdGVybWZyZXFfdHlwZSA9ICJxdWFudGlsZSIsIA0KICAgICAgICAgICBtYXhfZG9jZnJlcSA9IDAuMSwgZG9jZnJlcV90eXBlID0gInByb3AiKQ0KIyBXZSByZW1vdmUgdGhlIHRva2VuID0gMA0KVHdpdHRlcl9ERk0gPC0gVHdpdHRlcl9ERk1bbnRva2VuKFR3aXR0ZXJfREZNKSA+IDAsXQ0KYGBgDQoNCmBgYHtyIERvY3VtZW50LWZlYXR1cmUgbWF0cml4IGRpbWVuc2lvbiwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCnRpYmJsZSgNCiAgU291cmNlID0gYygiTmV3cyIsICJUd2l0dGVyIiksIA0KICAiTnVtYmVyX29mX2RvY3VtZW50cyAocm93cykiID0gYygxNDE0OSwgMzUxNjAzKSwNCiAgIk51bWJlcl9vZl9mZWF0dXJlcyAoY29sdW1ucykiID0gYygzNDkyLCAyODQ2KQ0KKQ0KYGBgDQoNCkZvciBiZXR0ZXIgaW50ZXJwcmV0YXRpb24sIHRoZSBmaXJzdCAzIGRvY3VtZW50cyBhbmQgMTAgZmVhdHVyZXMgb2YgdGhlIGRvY3VtZW50LWZlYXR1cmUgbWF0cml4IG9mIG5ld3MgYXJ0aWNsZXMgY2FuIGJlIHNlZW4gYmVsb3cuDQoNCmBgYHtyIERGTSBwcmV2aWV3fQ0KTmV3c19ERk1bMTozLCAxOjEwXQ0KYGBgDQoNCiMgVG9waWMgTW9kZWxsaW5nDQoNCldlIGRpc2NvdmVyZWQgdG9waWNzIGRpc3RyaWJ1dGVkIGluIG5ld3MgYXJ0aWNsZXMgYW5kIHR3ZWV0cyBvbiBhIHdlZWtseSBiYXNpcyBvdmVyIHRoZSB0aHJlZS1tb250aCBwZXJpb2QgYW5kIGNvbXBhcmVkIHRoZSB0b3BpY3MgYmV0d2VlbiB0aGUgdHdvIG1lZGlhIG91dGxldHMuIEZvciB0b3BpYyBtb2RlbGxpbmcgd2UgdXNlZCBTdHJ1Y3R1cmFsIFRvcGljIE1vZGVsaW5nIChTVE0pLCBzaW5jZSBpdCBpbmNvcnBvcmF0ZXMgbWV0YWRhdGEgKGluZm9ybWF0aW9uIGFib3V0IGVhY2ggZG9jdW1lbnQpIGludG8gdGhlIHRvcGljIG1vZGVsbGluZyBmcmFtZXdvcmssIHNvIHRoYXQgd2UgY2FuIGRpc2NvdmVyIHRvcGljcyBhbmQgZXN0aW1hdGUgdGhlaXIgcmVsYXRpb25zaGlwIHRvIHRoZSBkb2N1bWVudHMnIG1ldGFkYXRhLg0KDQpTVE0gaXMgYW4gdW5zdXBlcnZpc2VkIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWwgd2hlcmUgd2UgaGF2ZSB0byBkZWZpbmUgdGhlIG51bWJlciBvZiB0b3BpYyBLIGluIGFkdmFuY2UsIHNpbWlsYXJseSB0byBrLW1lYW5zIGNsdXN0ZXJpbmcgd2UgZG8gbm90IGtub3cgYWhlYWQgaG93IG1hbnkgdG9waWNzIHdlIHNob3VsZCB1c2UgZm9yIGFueSBnaXZlbiBjb3JwdXMuIFRoZXJlZm9yZSwgd2UgdHJhaW5lZCBhIGdyb3VwIG9mIHRvcGljIG1vZGVscyB3aXRoIGRpZmZlcmVudCBudW1iZXJzIG9mIEsgKHRvcGljcykgYW5kIHRoZW4gZXZhbHVhdGVkIGhvdyBtYW55IHRvcGljcyBhcmUgYXBwcm9wcmlhdGUuIEhlcmUgd2UgcHJvY2VlZGVkIHdpdGggKipLID0gMjUqKiBmb3IgZWFjaCBvZiB0aGUgbWVkaWEgZm9ybXMuIFRoZSBldmFsdWF0aW9uIG1ldGhvZCBjYW4gYmUgcmVmZXJyZWQgdG8gaW4gW3RoaXMgcG9zdF0oaHR0cHM6Ly9qdWxpYXNpbGdlLmNvbS9ibG9nL2V2YWx1YXRpbmctc3RtLykgYnkgKkp1bGlhIFNpbGdlKi4NCg0KYGBge3IgQ29udmVydCBkZm0gdG8gc3RtIG1vZGVsfQ0KTmV3c19zdG0gPC0gY29udmVydChOZXdzX0RGTSwgdG8gPSAic3RtIikNClR3aXR0ZXJfc3RtIDwtIGNvbnZlcnQoVHdpdHRlcl9ERk0sIHRvID0gInN0bSIpDQpgYGANCg0KYGBge3IgUnVuIHRvcGljIG1vZGVsbGluZywgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9DQpOZXdzX3RvcGljX21vZGVsIDwtIHN0bSgNCiAgZG9jdW1lbnRzID0gTmV3c19zdG0kZG9jdW1lbnRzLCANCiAgdm9jYWIgPSBOZXdzX3N0bSR2b2NhYiwNCiAgSyA9IDI1LA0KICBwcmV2YWxlbmNlID1+IHMod2VlayksDQogIGRhdGEgPSBOZXdzX3N0bSRtZXRhLA0KICBpbml0LnR5cGUgPSAiU3BlY3RyYWwiLA0KICBzZWVkID0gMTIzNDU2KQ0KDQpUd2l0dGVyX3RvcGljX21vZGVsIDwtIHN0bSgNCiAgZG9jdW1lbnRzID0gVHdpdHRlcl9zdG0kZG9jdW1lbnRzLCANCiAgdm9jYWIgPSBUd2l0dGVyX3N0bSR2b2NhYiwNCiAgSyA9IDI1LA0KICBwcmV2YWxlbmNlID1+IHMod2VlayksDQogIGRhdGEgPSBUd2l0dGVyX3N0bSRtZXRhLA0KICBpbml0LnR5cGUgPSAiU3BlY3RyYWwiLA0KICBzZWVkID0gMTIzNDU2KQ0KYGBgDQoNClRoZSBwbG90cyBiZWxvdyBzaG93IHRoZSB0b3AgMTAgdG9waWNzIGluIGVhY2ggY29ycHVzIChOZXdzLCBUd2l0dGVyKSwgYW5kIHRvcCA3IHdvcmRzIHRoYXQgaGF2ZSB0aGUgaGlnaGVzdCBwcm9iYWJpbGl0eSB0byBiZWxvbmcgdG8gdGhhdCB0b3BpYy4gQSBjbG9zZXIgbG9vayBpbnRvIGVhY2ggc291cmNlIHNob3dlZCB1cyBzb21lIGludGVyZXN0aW5nIHBhdHRlcm5zLiANCg0KYGBge3IgUGxvdCBuZXdzIHRvcGljLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KTmV3c19iZXRhIDwtIHRpZHkoTmV3c190b3BpY19tb2RlbCkNCk5ld3NfZ2FtbWEgPC0gdGlkeShOZXdzX3RvcGljX21vZGVsLCBtYXRyaXggPSAiZ2FtbWEiKQ0KDQpOZXdzX3RvcF90ZXJtcyA8LSBOZXdzX2JldGEgJT4lDQogIGFycmFuZ2UoYmV0YSkgJT4lDQogIGdyb3VwX2J5KHRvcGljKSAlPiUNCiAgdG9wX24oNywgYmV0YSkgJT4lDQogIGFycmFuZ2UoLWJldGEpICU+JQ0KICBzZWxlY3QodG9waWMsIHRlcm0pICU+JQ0KICBzdW1tYXJpc2UodGVybXMgPSBsaXN0KHRlcm0pKSAlPiUNCiAgbXV0YXRlKHRlcm1zID0gbWFwKHRlcm1zLCBwYXN0ZSwgY29sbGFwc2UgPSAiLCAiKSkgJT4lIA0KICB1bm5lc3QoKQ0KDQpOZXdzX2dhbW1hX3Rlcm1zIDwtIE5ld3NfZ2FtbWEgJT4lDQogIGdyb3VwX2J5KHRvcGljKSAlPiUNCiAgc3VtbWFyaXNlKGdhbW1hID0gbWVhbihnYW1tYSkpICU+JQ0KICBhcnJhbmdlKGRlc2MoZ2FtbWEpKSAlPiUNCiAgbGVmdF9qb2luKE5ld3NfdG9wX3Rlcm1zLCBieSA9ICJ0b3BpYyIpICU+JQ0KICBtdXRhdGUodG9waWMgPSBwYXN0ZTAoIlRvcGljICIsIHRvcGljKSwNCiAgICAgICAgIHRvcGljID0gcmVvcmRlcih0b3BpYywgZ2FtbWEpKQ0KDQpOZXdzX2dhbW1hX3Rlcm1zICU+JQ0KICB0b3BfbigxMCwgZ2FtbWEpICU+JQ0KICBnZ3Bsb3QoYWVzKHRvcGljLCBnYW1tYSwgbGFiZWwgPSB0ZXJtcywgZmlsbCA9IHRvcGljKSkgKw0KICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGdlb21fdGV4dChoanVzdCA9IDAuOCwgbnVkZ2VfeSA9IDAuMDAwNSwgc2l6ZSA9IDMsDQogICAgICAgICAgICBmYW1pbHkgPSAiSUJNUGxleFNhbnMiKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQgPSBjKDAsMCksDQogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsIDAuMDkpLA0KICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gcGVyY2VudF9mb3JtYXQoKSkgKw0KICB0aGVtZV90dWZ0ZShiYXNlX2ZhbWlseSA9ICJJQk1QbGV4U2FucyIsIHRpY2tzID0gRkFMU0UpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFtaWx5PSJJQk1QbGV4U2Fucy1Cb2xkIiksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEzKSkgKw0KICBsYWJzKHggPSBOVUxMLCB5ID0gZXhwcmVzc2lvbihnYW1tYSksDQogICAgICAgdGl0bGUgPSAiVG9wIDEwIHRvcGljcyBieSBwb3B1bGFyaXR5IG9uIE5ld3MgQXJ0aWNsZXMiLA0KICAgICAgIHN1YnRpdGxlID0gIldpdGggdGhlIHRvcCB3b3JkcyB0aGF0IGNvbnRyaWJ1dGUgdG8gZWFjaCB0b3BpYyIpDQpgYGANCg0KYGBge3IgUGxvdCB0d2l0dGVyIHRvcGljLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KVHdpdHRlcl9iZXRhIDwtIHRpZHkoVHdpdHRlcl90b3BpY19tb2RlbCkNClR3aXR0ZXJfZ2FtbWEgPC0gdGlkeShUd2l0dGVyX3RvcGljX21vZGVsLCBtYXRyaXggPSAiZ2FtbWEiKQ0KDQpUd2l0dGVyX3RvcF90ZXJtcyA8LSBUd2l0dGVyX2JldGEgJT4lDQogIGFycmFuZ2UoYmV0YSkgJT4lDQogIGdyb3VwX2J5KHRvcGljKSAlPiUNCiAgdG9wX24oNywgYmV0YSkgJT4lDQogIGFycmFuZ2UoLWJldGEpICU+JQ0KICBzZWxlY3QodG9waWMsIHRlcm0pICU+JQ0KICBzdW1tYXJpc2UodGVybXMgPSBsaXN0KHRlcm0pKSAlPiUNCiAgbXV0YXRlKHRlcm1zID0gbWFwKHRlcm1zLCBwYXN0ZSwgY29sbGFwc2UgPSAiLCAiKSkgJT4lIA0KICB1bm5lc3QoKQ0KDQpUd2l0dGVyX2dhbW1hX3Rlcm1zIDwtIFR3aXR0ZXJfZ2FtbWEgJT4lDQogIGdyb3VwX2J5KHRvcGljKSAlPiUNCiAgc3VtbWFyaXNlKGdhbW1hID0gbWVhbihnYW1tYSkpICU+JQ0KICBhcnJhbmdlKGRlc2MoZ2FtbWEpKSAlPiUNCiAgbGVmdF9qb2luKFR3aXR0ZXJfdG9wX3Rlcm1zLCBieSA9ICJ0b3BpYyIpICU+JQ0KICBtdXRhdGUodG9waWMgPSBwYXN0ZTAoIlRvcGljICIsIHRvcGljKSwNCiAgICAgICAgIHRvcGljID0gcmVvcmRlcih0b3BpYywgZ2FtbWEpKQ0KDQpUd2l0dGVyX2dhbW1hX3Rlcm1zICU+JQ0KICB0b3BfbigxMCwgZ2FtbWEpICU+JQ0KICBnZ3Bsb3QoYWVzKHRvcGljLCBnYW1tYSwgbGFiZWwgPSB0ZXJtcywgZmlsbCA9IHRvcGljKSkgKw0KICBnZW9tX2NvbChzaG93LmxlZ2VuZCA9IEZBTFNFKSArDQogIGdlb21fdGV4dChoanVzdCA9IDAuODUsIG51ZGdlX3kgPSAwLjAwMDUsIHNpemUgPSAzLA0KICAgICAgICAgICAgZmFtaWx5ID0gIklCTVBsZXhTYW5zIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLDApLA0KICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLCAwLjA5KSwNCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHBlcmNlbnRfZm9ybWF0KCkpICsNCiAgdGhlbWVfdHVmdGUoYmFzZV9mYW1pbHkgPSAiSUJNUGxleFNhbnMiLCB0aWNrcyA9IEZBTFNFKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbWlseT0iSUJNUGxleFNhbnMtQm9sZCIpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMykpICsNCiAgbGFicyh4ID0gTlVMTCwgeSA9IGV4cHJlc3Npb24oZ2FtbWEpLA0KICAgICAgIHRpdGxlID0gIlRvcCAxMCB0b3BpY3MgYnkgcG9wdWxhcml0eSBvbiBUd2l0dGVyIiwNCiAgICAgICBzdWJ0aXRsZSA9ICJXaXRoIHRoZSB0b3Agd29yZHMgdGhhdCBjb250cmlidXRlIHRvIGVhY2ggdG9waWMiKQ0KYGBgDQoNClRoZSBrZXkgZm9jdXNlcyBvbiBUd2l0dGVyIGFyZSBhYm91dCBzb21ldGhpbmcgbGlrZSDigJx0aGUgc3ByZWFkIG9mIHZpcnVzIChUb3BpYyAxMSkiLCAg4oCcbmVnYXRpdmUgcmVhY3Rpb24gKFRvcGljIDcsIDIzKeKAnSwg4oCcdXBkYXRlIG9uIHRoZSBwYW5kZW1pYyBpbmZvcm1hdGlvbiAoVG9waWMgMTMsIDQpIi4gT24gdGhlIGNvbnRyYXJ5LCB3aGVuIGxvb2tpbmcgaW50byBOZXdzIHRvcGljcywgd2UgY2FuIHNlZSBhIHJlbGF0aXZlbHkgZGlmZmVyZW5jZSBwYXR0ZXJuLCB3aGljaCBpcyBtb3JlIHJlbGF0ZWQgdG8g4oCccG9saXRpY2FsIG1hdHRlcnMg4oCTIHRvcGljIDIy4oCdLCDigJxzaXR1YXRpb24gaW4gb3RoZXIgY291bnRyeSAtIHRvcGljIDE54oCdLCDigJxlY29ub215IHNpdHVhdGlvbiDigJMgdG9waWMgNOKAnSwgImhlYWx0aGNhcmUgc3lzdGVtIHNpdHVhdGlvbiAoVG9waWMgMjAsIDIxKSIuIFRoZSBtZXNzYWdlIGFib3V0IGZhbWlseSBpcyBwb3B1bGFyIGluIGJvdGggc291cmNlcyAoTmV3cyBUb3BpYyAxMywgVHdpdHRlciBUb3BpYyAxOCkuIEZ1cnRoZXJtb3JlLCBwb2xpdGljaWFucyBhcmUgd2VsbC1jb3ZlcmVkLCB3aXRoIFRydW1wIG9uIFR3aXR0ZXIgYW5kIFBlbmNlLyBDdW9tbyBvbiBtYWluc3RyZWFtIHBhcGVycy4NCg0KIyBTZW50aW1lbnQgQW5hbHlzaXMNCg0KIyMgQ29ycHVzIHNlbnRpbWVudCBhbmFseXNpcw0KDQpUbyBpbnZlc3RpZ2F0ZSBzZW50aW1lbnRzIGluIG5ld3MgYXJ0aWNsZXMgYW5kIHR3ZWV0cywgdG9rZW5zIGV4dHJhY3RlZCBmcm9tIHRoZSBkb2N1bWVudHMgYXJlIHVzZWQgdG8gY2FsY3VsYXRlIHNlbnRpbWVudCBzY29yZXMgd2l0aCB0aGUgQUZJTk4gbGV4aWNvbiBkZXZlbG9wZWQgYnkgRmlubiDDhXJ1cCBOaWVsc2VuLCB3aGljaCBpcyBpbmNsdWRlZCBpbiB0aGUgdGlkeXRleHQgcGFja2FnZS4gVGhlIEFGSU5OIGxleGljb24gaXMgYSBsaXN0IG9mIEVuZ2xpc2ggdGVybXMgbWFudWFsbHkgcmF0ZWQgZm9yIHZhbGVuY2Ugd2l0aCBhbiBpbnRlZ2VyIGJldHdlZW4gLTUgKG5lZ2F0aXZlKSBhbmQgKzUgKHBvc2l0aXZlKS4gSXQgY29tcHJpc2VzIDg3OCBwb3NpdGl2ZSB0ZXJtcyBhbmQgMSw1OTggbmVnYXRpdmUgdGVybXMuIFRoZSBzZW50aW1lbnQgc2NvcmUgaXMgdGhlIHBlcmNlbnRhZ2Ugb2YgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgYWJzb2x1dGUgc3VtIG9mIHBvc2l0aXZlIHRlcm1zIGFuZCBuZWdhdGl2ZSB0ZXJtcyBkaXZpZGVkIGJ5IHRoZSB0b3RhbCBzdW0gb2YgdGhlbS4NCg0KYGBge3IgUHJlcGFyYXRpb24sIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQojIE1ha2UgYSBkYXRhZnJhbWUgd2l0aCB0aGUgQUZJTk4gZGljdGlvbmFyeQ0KYWZpbm4gPC0gZ2V0X3NlbnRpbWVudHMoImFmaW5uIikNCg0KTmV3c19leHQgPC0gY29udmVydChOZXdzX0RGTSwgdG8gPSAidHJpcGxldGxpc3QiKQ0KTmV3c19kZiA8LSBkYXRhLmZyYW1lKGRvYyA9IE5ld3NfZXh0JGRvY3VtZW50LA0KICAgICAgICAgICAgICAgICAgICAgICAgd29yZCA9IE5ld3NfZXh0JGZlYXR1cmUsDQogICAgICAgICAgICAgICAgICAgICAgICBmcmVxID0gTmV3c19leHQkZnJlcXVlbmN5KQ0KTmV3c19kZiR3b3JkIDwtIGFzLmNoYXJhY3RlcihOZXdzX2RmJHdvcmQpDQoNCk5ld3NfYWZpbm4gPC0gTmV3c19kZiAlPiUgDQogIGlubmVyX2pvaW4oYWZpbm4sIGJ5ID0gIndvcmQiKSAlPiUgDQogIG11dGF0ZShzY29yZSA9IGZyZXEgKiB2YWx1ZSkgJT4lIA0KICBzZXBhcmF0ZShkb2MsIGludG8gPSBjKCJ3ZWVrIiwgIm5vIiksIHNlcCA9ICJcXC4iKSAlPiUgDQogIG11dGF0ZShzZW50aW1lbnQgPSBpZmVsc2Uoc2NvcmUgPiAwLCAicG9zaXRpdmUiLCAibmVnYXRpdmUiKSkgJT4lIA0KICBncm91cF9ieSh3ZWVrLCBzZW50aW1lbnQpICU+JSANCiAgc3VtbWFyaXNlKHNlbnRpbWVudF9zY29yZSA9IHN1bShzY29yZSkpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgbXV0YXRlKHNvdXJjZSA9ICJOZXdzIikNCg0KVHdpdHRlcl9leHQgPC0gY29udmVydChUd2l0dGVyX0RGTSwgdG8gPSAidHJpcGxldGxpc3QiKQ0KVHdpdHRlcl9kZiA8LSBkYXRhLmZyYW1lKGRvYyA9IFR3aXR0ZXJfZXh0JGRvY3VtZW50LA0KICAgICAgICAgICAgICAgICAgICAgIHdvcmQgPSBUd2l0dGVyX2V4dCRmZWF0dXJlLA0KICAgICAgICAgICAgICAgICAgICAgIGZyZXEgPSBUd2l0dGVyX2V4dCRmcmVxdWVuY3kpDQpUd2l0dGVyX2RmJHdvcmQgPC0gYXMuY2hhcmFjdGVyKFR3aXR0ZXJfZGYkd29yZCkNCg0KVHdpdHRlcl9hZmlubiA8LSBUd2l0dGVyX2RmICU+JSANCiAgaW5uZXJfam9pbihhZmlubiwgYnkgPSAid29yZCIpICU+JSANCiAgbXV0YXRlKHNjb3JlID0gZnJlcSAqIHZhbHVlKSAlPiUgDQogIHNlcGFyYXRlKGRvYywgaW50byA9IGMoIndlZWsiLCAibm8iKSwgc2VwID0gIlxcLiIpICU+JSANCiAgbXV0YXRlKHNlbnRpbWVudCA9IGlmZWxzZShzY29yZSA+IDAsICJwb3NpdGl2ZSIsICJuZWdhdGl2ZSIpKSAlPiUgDQogIGdyb3VwX2J5KHdlZWssIHNlbnRpbWVudCkgJT4lIA0KICBzdW1tYXJpc2Uoc2VudGltZW50X3Njb3JlID0gc3VtKHNjb3JlKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBtdXRhdGUoc291cmNlID0gIlR3aXR0ZXIiKQ0KDQojIENyZWF0ZSBhIGRhdGFmcmFtZSB0byBwbG90IHNlbnRpbWVudA0KTmV3c19hZmlubl9wbG90IDwtIE5ld3NfYWZpbm4gJT4lIA0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc2VudGltZW50LCB2YWx1ZXNfZnJvbSA9IHNlbnRpbWVudF9zY29yZSkgJT4lIA0KICBtdXRhdGUoc3VtID0gcG9zaXRpdmUgKyAoLTEpKm5lZ2F0aXZlLCANCiAgICAgICAgIHBvc19wZXJjZW50ID0gcG9zaXRpdmUvc3VtKjEwMCwNCiAgICAgICAgIG5lZ19wZXJjZW50ID0gKC0xKSpuZWdhdGl2ZS9zdW0qMTAwLCANCiAgICAgICAgIHBvbGFyaXR5ID0gcm91bmQoKHBvc19wZXJjZW50IC0gbmVnX3BlcmNlbnQpLDMpKSAlPiUNCiAgc2VsZWN0KHdlZWssIHBvbGFyaXR5LCBzb3VyY2UpDQoNClR3aXR0ZXJfYWZpbm5fcGxvdCA8LSBUd2l0dGVyX2FmaW5uICU+JSANCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHNlbnRpbWVudCwgdmFsdWVzX2Zyb20gPSBzZW50aW1lbnRfc2NvcmUpICU+JSANCiAgbXV0YXRlKHN1bSA9IHBvc2l0aXZlICsgKC0xKSpuZWdhdGl2ZSwgDQogICAgICAgICBwb3NfcGVyY2VudCA9IHBvc2l0aXZlL3N1bSoxMDAsDQogICAgICAgICBuZWdfcGVyY2VudCA9ICgtMSkqbmVnYXRpdmUvc3VtKjEwMCwgDQogICAgICAgICBwb2xhcml0eSA9IHJvdW5kKChwb3NfcGVyY2VudCAtIG5lZ19wZXJjZW50KSwzKSkgJT4lDQogIHNlbGVjdCh3ZWVrLCBwb2xhcml0eSwgc291cmNlKQ0KDQojIEV4dHJhY3QgYmV0YSBtYXRyaXggdG8gZGF0YSBmcmFtZSBmb3JtYXQuIFVzaW5nIEFGSU5OIGxleGljb24sIG1ha2UgYSBkYXRhIGZyYW1lIHdpdGggdGhlIHNlbnRpbWVudCBmb3IgZWFjaCB3b3JkDQpOZXdzX2JldGEgPC0gdGlkeShOZXdzX3RvcGljX21vZGVsLCBtYXRyaXggPSAiYmV0YSIpDQpOZXdzX3RvcGljX3NjIDwtIGlubmVyX2pvaW4oTmV3c19iZXRhLCBhZmlubiwgYnkgPSBjKCJ0ZXJtIiA9ICJ3b3JkIikpICU+JSANCiAgbXV0YXRlKHNjb3JlID0gYmV0YSAqIHZhbHVlKSAlPiUgDQogIGdyb3VwX2J5KHRvcGljKSAlPiUgDQogIHN1bW1hcmlzZShzZW50aW1lbnRfc2NvcmUgPSBzdW0oc2NvcmUpKQ0KTmV3c190b3BpY19zYyR0b3BpYyA8LSBmYWN0b3IoTmV3c190b3BpY19zYyR0b3BpYywgbGV2ZWxzID0gYygxOjI1KSkNCg0KVHdpdHRlcl9iZXRhIDwtIHRpZHkoVHdpdHRlcl90b3BpY19tb2RlbCwgbWF0cml4ID0gImJldGEiKQ0KVHdpdHRlcl90b3BpY19zYyA8LSBpbm5lcl9qb2luKFR3aXR0ZXJfYmV0YSwgYWZpbm4sIGJ5ID0gYygidGVybSIgPSAid29yZCIpKSAlPiUgIA0KICBtdXRhdGUoc2NvcmUgPSBiZXRhICogdmFsdWUpICU+JSANCiAgZ3JvdXBfYnkodG9waWMpICU+JSANCiAgc3VtbWFyaXNlKHNlbnRpbWVudF9zY29yZSA9IHN1bShzY29yZSkpDQpUd2l0dGVyX3RvcGljX3NjJHRvcGljIDwtIGZhY3RvcihUd2l0dGVyX3RvcGljX3NjJHRvcGljLCBsZXZlbHMgPSBjKDE6MjUpKQ0KYGBgDQoNCmBgYHtyIFBsb3QgQUZJTk4gc2VudGltZW50IGFuYWx5c2lzLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KYWZpbm5fY2hhcnRfYWxsIDwtIHJiaW5kKE5ld3NfYWZpbm5fcGxvdCwgVHdpdHRlcl9hZmlubl9wbG90KQ0KYWZpbm5fY2hhcnRfYWxsJHdlZWsgPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoYWZpbm5fY2hhcnRfYWxsJHdlZWspKQ0KYWZpbm5fY2hhcnRfYWxsICU+JSANCiAgYXJyYW5nZSh3ZWVrKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IHdlZWssIHkgPSBwb2xhcml0eSwgY29sb3IgPSBzb3VyY2UpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBnZW9tX3BhdGgoKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gImdvbGQzIikgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAxMiwgY29sb3IgPSAiY29yYWwyIikgKw0KICBsYWJzKHggPSAiV2VlayIsIHkgPSAiU2VudGltZW50IFNjb3JlIikgKyANCiAgc2NhbGVfeF9jb250aW51b3VzKCAgIyBUaGlzIGhhbmRsZXMgcmVwbGFjZW1lbnQgb2Ygcm93IA0KICAgIGJyZWFrcyA9IGFmaW5uX2NoYXJ0X2FsbCR3ZWVrLCAjIG5vdGljZSBuZWVkIHRvIHJldXNlIGRhdGEgZnJhbWUNCiAgICBsYWJlbHMgPSBhZmlubl9jaGFydF9hbGwkd2VlaykgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobi5icmVha3MgPSAxMCkgKw0KICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoIiNFMzIxMUMiLCAiIzFGNzhCNCIpKSArDQogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBOVUxMLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSwNCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpDQoNCmBgYA0KDQpPdmVyYWxsLCB0aGUgb3BpbmlvbiB0b3dhcmRzIENPVklELTE5IHJlbWFpbmVkIG5lZ2F0aXZlIHRocm91Z2hvdXQgdGhlIHBlcmlvZC4gV2hpbGUgbmV3cyB3YXMgYSBiaXQgbW9yZSBwb3NpdGl2ZSB0aGFuIFR3aXR0ZXIsIHRoZXJlIHdhcyBhIHNpbWlsYXIgcGF0dGVybiBhcyB0aGUgc2VudGltZW50IHNjb3JlcyB3ZXJlIGhpZ2hseSBuZWdhdGl2ZSBpbiB3ZWVrIDMgYnV0IHNob3dlZCBhIHBvc2l0aXZlIHRyZW5kIGluIHRoZSBzdWJzZXF1ZW50IHdlZWtzLiBBdCB3ZWVrIDEyIHdoZW4gdGhlIHNpdHVhdGlvbiBnb3Qgd29yc2UgaW4gdGhlIFVTLCB0aGUgc2VudGltZW50IHNjb3JlIG9mIG5ld3MgYXJ0aWNsZXMgd2VudCBkb3duIHRoZW4gcGlja2VkIHVwIGFnYWluIGF0IHdlZWsgMTUsIHdoZXJlYXMgVHdpdHRlciBzaG93ZWQgYSBjb25zaXN0ZW50IHNlbnRpbWVudC4NCg0KV2l0aCB0aGUgcHVycG9zZSBvZiBleGFtaW5pbmcgZnJvbSBzZXZlcmFsIHBlcnNwZWN0aXZlcywgd2UgYWxzbyBtYWRlIHVzZSBvZiB0aGUgTlJDIGxleGljb24gZnJvbSBTYWlmIE1vaGFtbWFkIGFuZCBQZXRlciBUdXJuZXkuIFRoZSBOUkMgbGV4aWNvbiBjYXRlZ29yaXplcyB3b3JkcyBpbiBhIGJpbmFyeSBmYXNoaW9uICjigJx5ZXPigJ0vIOKAnG5v4oCdKSBpbnRvIGNhdGVnb3JpZXMgb2YgcG9zaXRpdmUsIG5lZ2F0aXZlLCBhbmdlciwgYW50aWNpcGF0aW9uLCBkaXNndXN0LCBmZWFyLCBqb3ksIHNhZG5lc3MsIHN1cnByaXNlLCBhbmQgdHJ1c3QuIFdlIGZpbHRlcmVkIG91dCB0aGUgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIGNhdGVnb3JpZXMgd2hpY2ggbGVmdCB1cyB3aXRoIDQsNDYzIGRpc3RpbmN0IHdvcmRzIGluIHRoZSBsZXhpY29uIChOb3RlOiBvbmUgd29yZCBjYW4gYmUgaW4gbXVsdGlwbGUgc2VudGltZW50IGNhdGVnb3JpZXMpLiBXZSBjb3VudGVkIHRoZSBudW1iZXIgb2Ygd29yZHMgaW4gZWFjaCBjYXRlZ29yeSBhbmQgY29tcHV0ZWQgdGhlaXIgcGVyY2VudGFnZSBkaXN0cmlidXRpb24gaW4gZWFjaCBvZiBvdXIgc291cmNlcy4gQXBwbHlpbmcgTlJDIGxleGljb24gdG8gaW5zcGVjdCB0aGUgZGF0YSBpbiBkaWZmZXJlbnQgY2F0ZWdvcmljYWwgc2VudGltZW50cywgd2UgcHJlc2VudGVkIHRoZSByZXN1bHQgaW4gYSByYWRhciBjaGFydDoNCg0KYGBge3IgUGxvdCBOUkMgc2VudGltZW50IGFuYWx5c2lzLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQ0KbnJjIDwtIGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgDQogIGZpbHRlcighc2VudGltZW50ICVpbiUgIGMoInBvc2l0aXZlIiwgIm5lZ2F0aXZlIikpDQoNCiMgTmV3cyBqb2luIGFuZCBjYWxjdWxhdGUgc2NvcmUNCk5ld3NfbnJjIDwtIE5ld3NfZGYgJT4lIA0KICBpbm5lcl9qb2luKG5yYykgJT4lIA0KICBzZXBhcmF0ZShkb2MsIGludG8gPSBjKCJ3ZWVrIiwgIm5vIiksIHNlcCA9ICJcXC4iKSAlPiUgDQogIGdyb3VwX2J5KHdlZWssIHNlbnRpbWVudCkgJT4lIA0KICBzdW1tYXJpc2UoY291bnQgPSBzdW0oZnJlcSkpDQpOZXdzX25yY19zdW0gPC0gTmV3c19ucmMgJT4lIA0KICBncm91cF9ieShzZW50aW1lbnQpICU+JSANCiAgc3VtbWFyaXNlKHRvdGFsX2NvdW50ID0gc3VtKGNvdW50KSkgJT4lIA0KICB1bmdyb3VwKCkNCk5ld3NfbnJjX3N1bSA8LSBOZXdzX25yY19zdW0gJT4lIA0KICBtdXRhdGUocGVyY2VudCA9IHRvdGFsX2NvdW50LyBzdW0oTmV3c19ucmNfc3VtJHRvdGFsX2NvdW50KSwNCiAgICAgICAgIHNvdXJjZSA9ICJOZXdzIikNCg0KIyBUd2l0dGVyIGpvaW4gYW5kIGNhbGN1bGF0ZSBzY29yZQ0KVHdpdHRlcl9ucmMgPC0gVHdpdHRlcl9kZiAlPiUgDQogIGlubmVyX2pvaW4obnJjKSAlPiUgDQogIHNlcGFyYXRlKGRvYywgaW50byA9IGMoIndlZWsiLCAibm8iKSwgc2VwID0gIlxcLiIpICU+JSANCiAgZ3JvdXBfYnkod2Vlaywgc2VudGltZW50KSAlPiUgDQogIHN1bW1hcmlzZShjb3VudCA9IHN1bShmcmVxKSkNClR3aXR0ZXJfbnJjX3N1bSA8LSBUd2l0dGVyX25yYyAlPiUgDQogIGdyb3VwX2J5KHNlbnRpbWVudCkgJT4lIA0KICBzdW1tYXJpc2UodG90YWxfY291bnQgPSBzdW0oY291bnQpKSAlPiUgDQogIHVuZ3JvdXAoKQ0KVHdpdHRlcl9ucmNfc3VtIDwtIFR3aXR0ZXJfbnJjX3N1bSAlPiUgDQogIG11dGF0ZShwZXJjZW50ID0gdG90YWxfY291bnQvIHN1bShUd2l0dGVyX25yY19zdW0kdG90YWxfY291bnQpLA0KICAgICAgICAgc291cmNlID0gIlR3aXR0ZXIiKQ0KDQojIENvbWJpbmUgZGF0YSBhbmQgcGxvdCByYWRhciBjaGFydA0KbnJjX2NoYXJ0X2FsbCA8LSByYmluZChOZXdzX25yY19zdW0sIFR3aXR0ZXJfbnJjX3N1bSkNCm5yY19jaGFydF9hbGwgJT4lIA0KICBzZWxlY3QoLXRvdGFsX2NvdW50KSAlPiUgDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzb3VyY2UsIHZhbHVlc19mcm9tID0gcGVyY2VudCkgJT4lIA0KICBjaGFydEpTUmFkYXIod2lkdGggPSA4LA0KICAgICAgICAgICAgICAgaGVpZ2h0ID0gNSwNCiAgICAgICAgICAgICAgIHNob3dUb29sVGlwTGFiZWwgPSBGQUxTRSwNCiAgICAgICAgICAgICAgIGNvbE1hdHJpeCA9IGdyRGV2aWNlczo6Y29sMnJnYihjKCJyZWQiLCAiYmx1ZSIsICJncmVlbiIpKSwNCiAgICAgICAgICAgICAgIGxhYmVsU2l6ZSA9IDE4KQ0KYGBgDQoNCk92ZXJhbGwsIG5ld3MgYXJ0aWNsZXMgc2hvd2VkIHRoZSBtb3N0IHBvc2l0aXZpdHkgYnkgY29taW5nIG9uIHRvcCBvZiDigJxqb3nigJ0gYW5kIOKAnHRydXN04oCdLCBidXQgaXQgYWxzbyBoYWQgbW9yZSDigJxhbmdlcuKAnSB3b3Jkcy4gUmVkZGl0IHdlcmUgZG9taW5hbnQgaW4gbW9zdCBuZWdhdGl2ZSBjYXRlZ29yaWVzLCBzdWNoIGFzIOKAnHNhZG5lc3PigJ0sIOKAnGZlYXLigJ0gYW5kIOKAnGFudGljaXBhdGlvbuKAnS4gVHdpdHRlcuKAmXMgcG9zdHMgd2VyZSBtb3JlIG5lZ2F0aXZlLCBhcyB0aGV5IGV4cHJlc3NlZCDigJxkaXNndXN04oCdLCAic2FkbmVzcyIsIGFuZCBzb21laG93ICJzdXJwcmlzZSIuIFRoaXMgdHVybmVkIG91dCB0byBiZSBhIHJlbGV2YW50IGludGVycHJldGF0aW9uIG9mIHRoZSBvdXRjb21lIG9mIHRoZSBBRklOTiBsZXhpY29uIGFuYWx5c2lzIGFib3ZlLiANCg0KIyMgVG9waWMtYmFzZWQgc2VudGltZW50IGFuYWx5c2lzDQoNCk9uIHRoZSB0b3BpYy1iYXNlZCBsZXZlbCwgd2UgYXNzaWduZWQgdGhlIHNlbnRpbWVudCB2YWx1ZSBmb3IgZWFjaCB0b3BpYyB3b3JkIGJhc2VkIG9uIHRoZSBsZXhpY29uIGFuZCB0aGUgcHJvYmFiaWxpdHkgb2YgYSB3b3JkIGluIGEgdG9waWMgZ2l2ZW4gYnkgdGhlIFNUTSB0b3BpYyBtb2RlbCBhcyB0aGUgdGVybSB3ZWlnaHQgb2YgdGhlIHdvcmQuIEFzIGEgcmVzdWx0LCB0b3BpYyBzZW50aW1lbnQgc2NvcmUgaXMgY2FsY3VsYXRlZCBhcw0KDQokJFNlbnRpbWVudFwgU2NvcmVcIG9mXCBUb3BpY1wgQSA9IFxzdW1fe2k9MX1ee259IChwcm9iKHdvcmRfaXxUb3BpY19BKSpzZW50aW1lbnRcIHZhbHVlKHdvcmRfaSkpJCQNCg0KQW4gb3ZlcmFsbCB0b3BpYyBzZW50aW1lbnQgc2NvcmUgaXMgY29tcHV0ZWQgYnkgbXVsdGlwbHlpbmcgdGhlIHNlbnRpbWVudCB2YWx1ZSBieSB0aGUgcHJvYmFiaWxpdHkgb2Ygd29yZHMgYW5kIHN1bW1pbmcgdGhlIHByb2R1Y3RzIGluIGEgY2hvc2VuIHRvcGljLiBNdWx0aXBsZSB0b3BpY3MgY291bGQgaGF2ZSB0aGUgc2FtZSB3b3JkcyB3aXRoIGRpZmZlcmVudCBwcm9iYWJpbGl0eSB2YWx1ZXMuIFRoZXJlZm9yZSwgdGhlIHNlbnRpbWVudCBzY29yZSBvZiBhIHRvcGljIHdvdWxkIGJlIGRpc3Rpbmd1aXNoZWQgZnJvbSBvdGhlcnMgZXZlbiBpZiB0aGUgc2FtZSBzZXQgb2Ygd29yZHMgYXBwZWFyIGluIGRpZmZlcmVudCB0b3BpY3MuDQoNCmBgYHtyIFRvcGljLWJhc2VkIHNlbnRpbWVudCBhbmFseXNpcywgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCg0KIyBOZXdzDQpOZXdzX3RvcGljX3NjX3Bsb3QgPC0gTmV3c190b3BpY19zYyAlPiUgDQogIGdncGxvdChhZXMoeCA9IHRvcGljLCB5ID0gc2VudGltZW50X3Njb3JlKSkgKyANCiAgZ2VvbV9jb2woZmlsbCA9ICIjRTMyMTFDIikgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICJnb2xkMyIpICsNCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIHN1YnRpdGxlID0gIk5ld3MiKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygtMSwgMC4yKSwgbi5icmVha3MgPSA4KSArDQogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBOVUxMLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNiksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLA0KICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMS41KSkpDQoNCiMgVHdpdHRlcg0KVHdpdHRlcl90b3BpY19zY19wbG90IDwtIFR3aXR0ZXJfdG9waWNfc2MgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB0b3BpYywgeSA9IHNlbnRpbWVudF9zY29yZSkpICsgDQogIGdlb21fY29sKGZpbGwgPSAiIzFGNzhCNCIpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3IgPSAiZ29sZDMiKSArDQogIGxhYnMoeCA9ICJUb3BpYyIsIHkgPSBOVUxMLCBzdWJ0aXRsZSA9ICJUd2l0dGVyIikgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoLTEsIDAuMiksIG4uYnJlYWtzID0gOCkgKw0KICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gTlVMTCwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwNCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEuNSkpKQ0KDQpncmlkLmFycmFuZ2UoTmV3c190b3BpY19zY19wbG90LCBUd2l0dGVyX3RvcGljX3NjX3Bsb3QpDQpgYGANCg0KVXNpbmcgU1RNIG1vZGVsIHdpdGggdGhlIHNhbWUgbnVtYmVyIG9mIHRvcGljcyBvZiAyNSwgd2UgY2FsY3VsYXRlZCB0aGUgc2VudGltZW50IHNjb3JlIG9mIGVhY2ggdG9waWMuIEFnYWluLCB0aGUgZ2VuZXJhbCBvcGluaW9ucyBpbiBtb3N0IHRvcGljcyB3ZXJlIG5lZ2F0aXZlLiBUaGUgc2VudGltZW50cyB3ZXJlIG1vcmUgc2lnbmlmaWNhbnQgaW4gVHdpdHRlciwgd2hpbGUgaW4gbmV3cyBhcnRpY2xlcyBtb3N0IHRvcGljcyBoYWQgdGhlIHNjb3JlcyBjbG9zZXIgdG8gbmV1dHJhbC4gVG9waWMgNyBpbiBUd2l0dGVyIHdhcyBleHRyZW1lbHkgbmVnYXRpdmUsIHdoaWNoIG1vc3RseSBjb25zaXN0IG9mIHNlbnRpbWVudGFsIHdvcmRzIChoZWxsLCB5YWxsLCBzaGl04oCmKS4gVGhpcyB3YXMgb25lIGRvd25zaWRlIG9mIHVuc3VwZXJ2aXNlZCB0b3BpYyBtb2RlbGxpbmcsIGFzIGl0IGdyb3VwZWQgdGhlc2Ugc2VudGltZW50YWwgd29yZHMgdG9nZXRoZXIgaW4gb25lIHRvcGljLCBidXQgdGhlIGludGVycHJldGF0aW9uIHdhcyBub3QgdXNlZnVsIGZvciB0b3BpYyBkaXNjb3ZlcnkuIEV4Y2x1ZGluZyB0aGUgdG9waWNzIGFib3ZlLCBuZXdzIGFuZCBUd2l0dGVyIGhhZCBhIGZldyBub3RhYmxlIG5lZ2F0aXZpdGllcywgd2l0aCB0b3BpYyAyMiAocG9saXRpY2FsLCBwZW5jZSwgdHdlZXQsIGJsYW1lLCBwYXJ0eSwgYXR0YWNr4oCmKSBhbmQgMjMgKHBvbGljZSwgcHJpc29uLCBjb3VydCwgbGF3LCBqYWls4oCmKSBpbiBuZXdzIGFuZCB0b3BpYyAxMiAoZGllLCBmbHUsIHRydW1w4oCmKSBpbiBUd2l0dGVyLiBUd2l0dGVyIHVzZXJzIHNlZW1lZCB0byBoYXZlIHRoZSBjb25jZXJucyBjZW50ZXJlZCBhcm91bmQgUHJlc2lkZW50IFRydW1w4oCZcyBiZWhhdmlvcnMsIHdoaWxlIHRoZSBuZXdzIG1lZGlhIGdyYXZpdGF0ZWQgdG93YXJkcyB0aGUgY29uZmxpY3Qgb2YgcG9saXRpY2FsIHBhcnRpZXMgYW5kIHdvcnJpZXMgYWJvdXQgc29jaWFsIHNlY3VyaXR5Lg0KDQpBbW9uZyB0aGUgcG9zaXRpdmUgdG9waWNzLCB0aGVyZSB3YXMgYSBob21vZ2VuZW91cyB0aGVtIGluIGFsbCBzb3VyY2VzLiBUb3BpYyAxMyBpbiB0aGUgbmV3cyAobG92ZSwgY2h1cmNoLCBtb21lbnQsIHdpZmUsIG1vdGhlcuKApikgYW5kIFRvcGljIDE4IChmYW1pbHksIGZyaWVuZCwgcHJheeKApikgYW5kIDE1IChwcm90ZWN0LCBnb2QsIGxvdmUsIGplc3VzLi4uKSBpbiBUd2l0dGVyIGhhZCB0aGUgc2FtZSB0aGVtZSBvZiBmYWl0aCBhbmQgYmVsaWVmLCB0aG91Z2ggdGhlIHBvc2l0aXZlIHNjb3JlcyB3ZXJlIG1pbGQuDQoNCiMgQ29uY2x1c2lvbg0KDQpUaGlzIHByb2plY3Qgc3R1ZGllcyB0aGUgdG9waWMgY292ZXJhZ2UgYW5kIHNlbnRpbWVudCBkeW5hbWljcyBvZiB0aGUgc2Vuc2l0aXZlIHRvcGljIENPVklELTE5IGluIE5ld3MgbWVkaWEgYW5kIFR3aXR0ZXIuIEFsdGhvdWdoIHRoZSBwcm9qZWN0IGhhcyByZXZlYWxlZCBkaWZmZXJlbnQgY2hhcmFjdGVyaXN0aWNzIG9mIG5ld3MgYXJ0aWNsZXMgYW5kIFR3aXR0ZXIsIGl0IG9ubHkgY29uZHVjdHMgYW5hbHlzaXMgb24gdGhlIHRleHQgcHJvcGVydHkgYW5kIHRoZSB0aW1lIHZhcmlhYmxlLiBNYW55IG1ldGEtZGF0YSB3ZXJlIHJlbW92ZWQgZnJvbSB0aGUgcmF3IGRhdGEgd2hpY2ggbWlnaHQgbGVhdmUgb3V0IHNvbWUgaW1wb3J0YW50IGFzcGVjdHMgdGhhdCBjb3VsZCBiZSBlbGFib3JhdGVkIGZ1cnRoZXIuIE90aGVyIGNob2ljZXMgdGhhdCBtaWdodCBsZWFkIHRvIHJlc2VhcmNoIGJpYXMgd2VyZSB0aGUgZGF0YSBzYW1wbGVzIHdoaWNoIGp1c3QgY292ZXIgc3Vic2V0cyBvZiBrZXl3b3JkcyBhbmQgdGhlIGRpY3Rpb25hcmllcyB1c2VkIGZvciBwcmUtcHJvY2Vzc2luZyBhbmQgc2VudGltZW50IGFuYWx5c2lzLiBMYXN0bHksIHRoZSB0aW1lIGZyYW1lIG9mIGRhdGEgY29sbGVjdGlvbiBpcyBvbmx5IHRocmVlIG1vbnRocywgZW5kaW5nIGF0IHRoZSBtaWRkbGUgb2YgQXByaWwgd2hlbiB0aGUgcGFuZGVtaWMgd2FzIHN0aWxsIGVzY2FsYXRpbmcgaW4gdGhlIFVTLiBJdCB3b3VsZCBiZSBiZXR0ZXIgSWYgd2UgY29sbGVjdCB0aGUgZGF0YSBhbmQgY29uZHVjdCB0aGUgYW5hbHlzaXMgYWZ0ZXIgdGhlIHBhbmRlbWljIGlzIG92ZXIsIHdoaWNoIHdvdWxkIGdpdmUgYSBmdWxsIG92ZXJ2aWV3IG9mIHRoZSBzaXR1YXRpb24u