This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.
The Knowledge Exchange task and finish group defined a range of Twitter hashtags to be followed throughout the project Publishing reproducible research output. These hashtags were harvested via the rtweet libray and the Twitter API and then saved in csv format. Up to 7,500 tweets were allowed for each hashtag, and this number was never reached over the course of the monitoring period. The hashtags considered were:
- #Reproducibility
- #Replicability
- #ReproducibleScience
- #ResearchReproducibility
- #ReproducibleResearch
- #ResearchCredibility
- #GoodResearchPractices
- #RegisteredReports
- #GoodScience
- #ResearchCompendium (from 23/11 onwards)
- #ResearchCompendia (from 23/11 onwards)
- #ReproducibilityCrisis (from 23/11 onwards)
- #ReplicabilityCrisis (from 23/11 onwards)
- #ReplicationCrisis (from 23/11 onwards)
- #TuringWay (from 23/11 onwards)
Data was harvested on Mondays, starting from 09/11/2020. Please note that Twitter’s Terms of Service do not allow the sharing of full data, so only Tweet ids are available as part of this deposit.
Software environment
- R version 4.1.0 (2021-05-18)
- Platform: x86_64-w64-mingw32/x64 (64-bit)
- Running under: Windows 10 x64 (build 19042)
Library versions
- data.table 1.14.0
- dplyr 1.0.6
- ggplot2 3.3.4
- networkD3 0.4
- purrr 0.3.4
- RColorBrewer 1.1.2
- readr 1.4.0
- rmarkdown 2.11
- rtweet 0.7.0
- SnowballC 0.7.0
- stringr 1.4.0
- tidyverse 1.3.1
- tm 0.7.8
- wordcloud 2.6
Hardware
- Device: IdeaCentre A540-24ICB
- Processor: Intel(R) Core(TM) i5-9400T CPU @ 1.80GHz 1.80 GHz
- Installer RAM: 8.00 GB
- System type: 64-bit operating system, x64-based processor
Section 1 - Libraries
library(data.table)
library(dplyr)
options(dplyr.summarise.inform = FALSE)
library(ggplot2)
library(networkD3)
library(purrr)
library(RColorBrewer)
library(readr)
library(rmarkdown)
library(rtweet)
library(SnowballC)
library(stringr)
library(tidyverse)
library(tm)
library(wordcloud)
Section 2 - Data import
The csv data in different harvested files is imported into a single dataset and deduplicated by Tweet id.
# Clear the environment (RStudio)
rm(list = ls())
# This reads any number of Twitter .csv datasets harvested via rtweet.
tbl <-
list.files(pattern = "*.csv") %>%
map_df(~read_csv(., col_types = cols(.default = "c")))
# The tweets are de-duplicated by status id: the datasets downloaded may overlap, for example in cases where people used more than one of the hashtags monitored.
Twitter_data <- tbl[!duplicated(tbl$status_id),]
Section 3 - Relevance checks
Accounts that DO NOT include the words below in their description are likely to be irrelevant or invalid. They might have used the hashtags monitored in a different context that is not appropriate to this analysis. This approach is an approximation and will not be 100% accurate (e.g. if someone’s profile description is blank). However, without filtering we would be very likely to consider irrelevant accounts and tweets. The below list of words has been developed by reviewing a random set of twitter accounts gathered in the dataset and enriched via personal knowledge of the sector.
account_description_validation <- c('academia', 'academic', 'academics', 'analysis group', 'article', 'articles', 'assistant prof', 'assistant professor', 'associate prof', 'associate professor', 'associate director', 'biology', 'biomedical', 'book', 'ciencias', 'clinical trial', 'clinical trials', 'college', 'consortium', 'copyright', 'develop', 'digital object', 'director of', 'discover', 'doctoral', 'doi', 'editor', 'Editor-in-Chief', 'evidence', 'evidence base', 'evidencebased', 'head of', 'higher education', 'highered', 'humanities', 'information science', 'information sciences', 'institute', 'institutes', 'institution', 'institutions', 'interdisciplinary', 'journal', 'journals', 'learning', 'lecturer', 'librarian', 'librarians', 'libraries', 'library', 'licence', 'license', 'licensing', 'LIS', 'manuscript', 'manuscripts', 'medicine', 'metrics', 'modelling', 'museum', 'open access', 'open data', 'open knowledge', 'open research', 'open scholarship', 'paper', 'papers', 'peer review', 'peer reviewed', 'peer-review', 'peer-reviewed', 'ph.d. candidate', 'PhD', 'PhD candidate', 'postdoc', 'post-doc', 'preprint', 'pre-print', 'preprints', 'pre-prints', 'press', 'principal investigator', 'prof', 'prof.', 'professor', 'public domain', 'publication', 'publish', 'publisher', 'publishing', 'recherche', 'recherches', 'relationship between', 'research', 'research data', 'researcher', 'scholar', 'scholarly', 'scholarly communication', 'school', 'scicomm', 'science', 'sciences', 'scientific', 'scientist', 'scientists', 'society of', 'student', 'teacher', 'teaching', 'universities', 'university')
account_description_validation_string <- paste(account_description_validation, collapse="|")
# Accounts are marked as "Keep" or "Discard" based on the above list of words.
Twitter_data$relevance_check <- ifelse(grepl(account_description_validation_string, Twitter_data$description, ignore.case = TRUE), "Keep", "Discard")
# Only the accounts marked as "Keep" are taken forward.
Twitter_data <- Twitter_data[Twitter_data$relevance_check == 'Keep',]
Section 4 - Data cleaning
The text of the tweets is cleaned from odd characters and URLs using regex.
# Remove Unicode format and other textual oddities.
Twitter_data$text <- str_replace_all(Twitter_data$text,"\\<U[^\\>]*\\>"," ")
Twitter_data$text <- str_replace_all(Twitter_data$text,"\r\n"," ")
Twitter_data$text <- str_replace_all(Twitter_data$text,"&"," ")
# Create a new column to save the original text before any further cleaning - this is just a backup.
Twitter_data$Original_Tweet_Backup <- Twitter_data$text
# Continue cleaning, removing hashtags, mentions and "RT". Note that hashtags are saved in a dedicated column so this is just removing them from the body of the tweet.
Twitter_data$text <- str_replace_all(Twitter_data$text,"^RT:? "," ")
Twitter_data$text <- str_replace_all(Twitter_data$text,"@[[:alnum:]]+"," ")
Twitter_data$text <- str_replace_all(Twitter_data$text,"#[[:alnum:]]+"," ")
Twitter_data$text <- str_replace_all(Twitter_data$text,"http\\S+\\s*"," ")
Section 5 - Overview of posting times
A chart of tweets by date is created.
ts_plot(Twitter_data, "hours") +
labs(x = NULL, y = NULL,
title = "Frequency of tweets vs time",
subtitle = paste0(format(min(Twitter_data$created_at)), " to ", format(max(Twitter_data$created_at))),
caption = "Data collected from Twitter's API (rtweet)") +
theme_minimal()

Section 7 - Analysis of mentions
Mentions are analysed to identify the most mentioned accounts. Results are shown in a word cloud and a table.
# Exclude retweets, because they are considered as mentions in the data. If you retweet someone, the API considers that as you mentioning them.
Twitter_data_no_retweets <- Twitter_data[Twitter_data$is_retweet == 'FALSE',]
mentions_vector <- Twitter_data_no_retweets$mentions_screen_name
# Split the mentions column using the space separator. "100" allows room for 100 columns, just in case (note that this is not possible with Twitter's character limit!).
split_mentions <- str_split_fixed(mentions_vector, " ", 100)
split_mentions_single_column <- stack(data.frame(split_mentions))
split_mentions_single_column <- data.frame(split_mentions_single_column$values)
# Get rid of rows that are blank
split_mentions_single_column_clean <- split_mentions_single_column[split_mentions_single_column != "", ]
wordcloud(split_mentions_single_column_clean, min.freq=5, random.order=FALSE, colors=brewer.pal(9, 'Reds')[4:9])

# If you want the word cloud in a table:
split_mentions_single_column_clean <- as.data.frame(split_mentions_single_column_clean)
names(split_mentions_single_column_clean)[1] <- 'account'
split_mentions_single_column_clean <- split_mentions_single_column_clean %>%
group_by(account) %>%
summarise(weight = n()) %>%
ungroup()
split_mentions_single_column_clean <- split_mentions_single_column_clean[order(-split_mentions_single_column_clean$weight), ]
paged_table(head(split_mentions_single_column_clean, 50))
Section 8 - Analysis of links shared
Links shared in the tweets harvested are shown as a table, to identify literature sources and any relevant events for inclusion in the study.
top_urls <- Twitter_data[, c("urls_expanded_url")]
top_urls <- top_urls[complete.cases(top_urls), ] # This gets rid of rows with missing values
top_urls <- top_urls %>%
group_by(urls_expanded_url) %>%
summarise(count = n()) %>%
ungroup()
top_urls <- top_urls[order(-top_urls$count),]
paged_table(head(top_urls, 50))
Section 11 - Identification of accounts with the most followers in the sample
The most popular individuals or organisations in the dataset are reviewed to understand the dynamics of social media discourse: who are the tweeters with the largest possible reach? The results are shown in a table.
# Select a list of unique accounts.
highestFollowers <- Twitter_data %>% select(screen_name, followers_count, friends_count, description, location)
highestFollowers_unique <- highestFollowers[!duplicated(highestFollowers$screen_name),]
# The data table is all characters, so relevant columns have to be converted into numbers.
highestFollowers_unique$followers_count <- as.numeric(as.character(highestFollowers_unique$followers_count))
highestFollowers_unique$friends_count <- as.numeric(as.character(highestFollowers_unique$friends_count))
# Sort the table of stakeholders by number of followers and number of friends.
stakeholder_highestFollowers <- highestFollowers_unique[order(-highestFollowers_unique$followers_count, -highestFollowers_unique$friends_count),]
stakeholder_highestFollowers_table <- select(stakeholder_highestFollowers, screen_name, followers_count, friends_count)
paged_table(head(stakeholder_highestFollowers_table,50))
Section 12 - Analysis of the most commonly used words in the dataset
Corpus analysis is used to analyse the words most commonly used in the dataset. The results are shown in a word cloud to gain an understanding of the language used when discussing reproducibility.
# The tweet's text is in the column called "text" in the data table called "Twitter_data".
data_for_corpus <- Twitter_data %>% select(screen_name, text)
# Build the corpus for analysis.
corpus <- Corpus(VectorSource(data_for_corpus$text))
# The corpus is cleaned and standardised.
corpus <- tm_map(corpus, content_transformer(tolower))
corpus <- tm_map(corpus, removeNumbers)
corpus <- tm_map(corpus, stripWhitespace)
corpus <- tm_map(corpus, removePunctuation)
# Remove stop words by using a pre-defined list for the English language and additional words in quotes.
mystopwords <- c(stopwords("english"),"rt","get","like","just","yes","know","will","good","day","people", "got", "can", "amp")
corpus <- tm_map(corpus,removeWords,mystopwords)
# Create a document term matrix.
myDtm <- DocumentTermMatrix(corpus)
sparse <- removeSparseTerms(myDtm, 0.97)
sparse <- as.data.frame(as.matrix(sparse))
# Calculate the frequency of each word from the data table created - colSums adds up the totals by column.
# freqWords is a row of numbers, which has the words as the column headers.
freqWords <- colSums(sparse)
freqWords <- freqWords[order(-freqWords)]
wordcloud(freq = as.vector(freqWords), words = names(freqWords),random.order = FALSE,
random.color = FALSE, colors = brewer.pal(9, 'Reds')[4:9])

paged_table(head(as.data.frame(freqWords), 50))
LS0tDQp0aXRsZTogIktFIFBSUk8gLSBTb2NpYWwgbWVkaWEgYW5hbHlzaXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KVGhlIEtub3dsZWRnZSBFeGNoYW5nZSB0YXNrIGFuZCBmaW5pc2ggZ3JvdXAgZGVmaW5lZCBhIHJhbmdlIG9mIFR3aXR0ZXIgaGFzaHRhZ3MgdG8gYmUgZm9sbG93ZWQgdGhyb3VnaG91dCB0aGUgcHJvamVjdCBbUHVibGlzaGluZyByZXByb2R1Y2libGUgcmVzZWFyY2ggb3V0cHV0XShodHRwczovL3d3dy5rbm93bGVkZ2UtZXhjaGFuZ2UuaW5mby9ldmVudC9wdWJsaXNoaW5nLXJlcHJvZHVjaWJsZS1yZXNlYXJjaC1vdXRwdXQpLiBUaGVzZSBoYXNodGFncyB3ZXJlIGhhcnZlc3RlZCB2aWEgdGhlIHJ0d2VldCBsaWJyYXkgYW5kIHRoZSBUd2l0dGVyIEFQSSBhbmQgdGhlbiBzYXZlZCBpbiBjc3YgZm9ybWF0LiBVcCB0byA3LDUwMCB0d2VldHMgd2VyZSBhbGxvd2VkIGZvciBlYWNoIGhhc2h0YWcsIGFuZCB0aGlzIG51bWJlciB3YXMgbmV2ZXIgcmVhY2hlZCBvdmVyIHRoZSBjb3Vyc2Ugb2YgdGhlIG1vbml0b3JpbmcgcGVyaW9kLiBUaGUgaGFzaHRhZ3MgY29uc2lkZXJlZCB3ZXJlOg0KDQoqICNSZXByb2R1Y2liaWxpdHkNCiogI1JlcGxpY2FiaWxpdHkNCiogI1JlcHJvZHVjaWJsZVNjaWVuY2UNCiogI1Jlc2VhcmNoUmVwcm9kdWNpYmlsaXR5DQoqICNSZXByb2R1Y2libGVSZXNlYXJjaA0KKiAjUmVzZWFyY2hDcmVkaWJpbGl0eQ0KKiAjR29vZFJlc2VhcmNoUHJhY3RpY2VzDQoqICNSZWdpc3RlcmVkUmVwb3J0cw0KKiAjR29vZFNjaWVuY2UNCiogI1Jlc2VhcmNoQ29tcGVuZGl1bSAoZnJvbSAyMy8xMSBvbndhcmRzKQ0KKiAjUmVzZWFyY2hDb21wZW5kaWEgKGZyb20gMjMvMTEgb253YXJkcykNCiogI1JlcHJvZHVjaWJpbGl0eUNyaXNpcyAoZnJvbSAyMy8xMSBvbndhcmRzKQ0KKiAjUmVwbGljYWJpbGl0eUNyaXNpcyAoZnJvbSAyMy8xMSBvbndhcmRzKQ0KKiAjUmVwbGljYXRpb25DcmlzaXMgKGZyb20gMjMvMTEgb253YXJkcykNCiogI1R1cmluZ1dheSAoZnJvbSAyMy8xMSBvbndhcmRzKQ0KDQpEYXRhIHdhcyBoYXJ2ZXN0ZWQgb24gTW9uZGF5cywgc3RhcnRpbmcgZnJvbSAwOS8xMS8yMDIwLiBQbGVhc2Ugbm90ZSB0aGF0IFR3aXR0ZXIncyBUZXJtcyBvZiBTZXJ2aWNlIGRvIG5vdCBhbGxvdyB0aGUgc2hhcmluZyBvZiBmdWxsIGRhdGEsIHNvIG9ubHkgVHdlZXQgaWRzIGFyZSBhdmFpbGFibGUgYXMgcGFydCBvZiB0aGlzIGRlcG9zaXQuDQoNCiMgU29mdHdhcmUgZW52aXJvbm1lbnQNCg0KKiBSIHZlcnNpb24gNC4xLjAgKDIwMjEtMDUtMTgpDQoqIFBsYXRmb3JtOiB4ODZfNjQtdzY0LW1pbmd3MzIveDY0ICg2NC1iaXQpDQoqIFJ1bm5pbmcgdW5kZXI6IFdpbmRvd3MgMTAgeDY0IChidWlsZCAxOTA0MikNCg0KIyBMaWJyYXJ5IHZlcnNpb25zDQoqIGRhdGEudGFibGUgMS4xNC4wDQoqIGRwbHlyIDEuMC42DQoqIGdncGxvdDIgMy4zLjQNCiogbmV0d29ya0QzIDAuNA0KKiBwdXJyciAwLjMuNA0KKiBSQ29sb3JCcmV3ZXIgMS4xLjINCiogcmVhZHIgMS40LjANCiogcm1hcmtkb3duIDIuMTENCiogcnR3ZWV0IDAuNy4wDQoqIFNub3diYWxsQyAwLjcuMA0KKiBzdHJpbmdyIDEuNC4wDQoqIHRpZHl2ZXJzZSAxLjMuMQ0KKiB0bSAwLjcuOA0KKiB3b3JkY2xvdWQgMi42DQoNCiMgSGFyZHdhcmUNCg0KKiBEZXZpY2U6IElkZWFDZW50cmUgQTU0MC0yNElDQg0KKiBQcm9jZXNzb3I6IEludGVsKFIpIENvcmUoVE0pIGk1LTk0MDBUIENQVSBAIDEuODBHSHogICAxLjgwIEdIeg0KKiBJbnN0YWxsZXIgUkFNOiA4LjAwIEdCDQoqIFN5c3RlbSB0eXBlOiA2NC1iaXQgb3BlcmF0aW5nIHN5c3RlbSwgeDY0LWJhc2VkIHByb2Nlc3Nvcg0KDQojIFNlY3Rpb24gMSAtIExpYnJhcmllcw0KDQpgYGB7ciByZXN1bHRzID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeShkcGx5cikNCm9wdGlvbnMoZHBseXIuc3VtbWFyaXNlLmluZm9ybSA9IEZBTFNFKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShuZXR3b3JrRDMpDQpsaWJyYXJ5KHB1cnJyKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShybWFya2Rvd24pDQpsaWJyYXJ5KHJ0d2VldCkNCmxpYnJhcnkoU25vd2JhbGxDKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHRtKQ0KbGlicmFyeSh3b3JkY2xvdWQpDQpgYGANCg0KIyBTZWN0aW9uIDIgLSBEYXRhIGltcG9ydA0KDQpUaGUgY3N2IGRhdGEgaW4gZGlmZmVyZW50IGhhcnZlc3RlZCBmaWxlcyBpcyBpbXBvcnRlZCBpbnRvIGEgc2luZ2xlIGRhdGFzZXQgYW5kIGRlZHVwbGljYXRlZCBieSBUd2VldCBpZC4NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0V9DQpyZXF1aXJlKCJrbml0ciIpDQpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gIkM6XFxVc2Vyc1xcQW5kcmVhIENoaWFyZWxsaVxcUmVzZWFyY2ggQ29uc3VsdGluZ1xcUm9iIEpvaG5zb24gLSBUZWFtIEZvbGRlclxcUHJvamVjdHNcXDIwMjAgLSBLRSBSZXByb2R1Y2libGUgUmVzZWFyY2hcXDA2IE91dHB1dHNcXDUuIFNvY2lhbCBtZWRpYSBhbmFseXNpcyAoR0RQUilcXERhdGEiKQ0KYGBgDQoNCg0KYGBge3IgcmVzdWx0cz0naGlkZSd9DQoNCiMgQ2xlYXIgdGhlIGVudmlyb25tZW50IChSU3R1ZGlvKQ0Kcm0obGlzdCA9IGxzKCkpDQoNCiMgVGhpcyByZWFkcyBhbnkgbnVtYmVyIG9mIFR3aXR0ZXIgLmNzdiBkYXRhc2V0cyBoYXJ2ZXN0ZWQgdmlhIHJ0d2VldC4NCnRibCA8LQ0KICBsaXN0LmZpbGVzKHBhdHRlcm4gPSAiKi5jc3YiKSAlPiUgDQogIG1hcF9kZih+cmVhZF9jc3YoLiwgY29sX3R5cGVzID0gY29scyguZGVmYXVsdCA9ICJjIikpKQ0KDQojIFRoZSB0d2VldHMgYXJlIGRlLWR1cGxpY2F0ZWQgYnkgc3RhdHVzIGlkOiB0aGUgZGF0YXNldHMgZG93bmxvYWRlZCBtYXkgb3ZlcmxhcCwgZm9yIGV4YW1wbGUgaW4gY2FzZXMgd2hlcmUgcGVvcGxlIHVzZWQgbW9yZSB0aGFuIG9uZSBvZiB0aGUgaGFzaHRhZ3MgbW9uaXRvcmVkLg0KVHdpdHRlcl9kYXRhIDwtIHRibFshZHVwbGljYXRlZCh0Ymwkc3RhdHVzX2lkKSxdIA0KYGBgDQoNCiMgU2VjdGlvbiAzIC0gUmVsZXZhbmNlIGNoZWNrcw0KDQpBY2NvdW50cyB0aGF0IERPIE5PVCBpbmNsdWRlIHRoZSB3b3JkcyBiZWxvdyBpbiB0aGVpciBkZXNjcmlwdGlvbiBhcmUgbGlrZWx5IHRvIGJlIGlycmVsZXZhbnQgb3IgaW52YWxpZC4gVGhleSBtaWdodCBoYXZlIHVzZWQgdGhlIGhhc2h0YWdzIG1vbml0b3JlZCBpbiBhIGRpZmZlcmVudCBjb250ZXh0IHRoYXQgaXMgbm90IGFwcHJvcHJpYXRlIHRvIHRoaXMgYW5hbHlzaXMuIFRoaXMgYXBwcm9hY2ggaXMgYW4gYXBwcm94aW1hdGlvbiBhbmQgd2lsbCBub3QgYmUgMTAwJSBhY2N1cmF0ZSAoZS5nLiBpZiBzb21lb25lJ3MgcHJvZmlsZSBkZXNjcmlwdGlvbiBpcyBibGFuaykuIEhvd2V2ZXIsIHdpdGhvdXQgZmlsdGVyaW5nIHdlIHdvdWxkIGJlIHZlcnkgbGlrZWx5IHRvIGNvbnNpZGVyIGlycmVsZXZhbnQgYWNjb3VudHMgYW5kIHR3ZWV0cy4gVGhlIGJlbG93IGxpc3Qgb2Ygd29yZHMgaGFzIGJlZW4gZGV2ZWxvcGVkIGJ5IHJldmlld2luZyBhIHJhbmRvbSBzZXQgb2YgdHdpdHRlciBhY2NvdW50cyBnYXRoZXJlZCBpbiB0aGUgZGF0YXNldCBhbmQgZW5yaWNoZWQgdmlhIHBlcnNvbmFsIGtub3dsZWRnZSBvZiB0aGUgc2VjdG9yLg0KDQpgYGB7ciByZXN1bHRzID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRX0NCg0KYWNjb3VudF9kZXNjcmlwdGlvbl92YWxpZGF0aW9uIDwtIGMoJ2FjYWRlbWlhJywgJ2FjYWRlbWljJywgJ2FjYWRlbWljcycsICdhbmFseXNpcyBncm91cCcsICdhcnRpY2xlJywgJ2FydGljbGVzJywgJ2Fzc2lzdGFudCBwcm9mJywgJ2Fzc2lzdGFudCBwcm9mZXNzb3InLCAnYXNzb2NpYXRlIHByb2YnLCAnYXNzb2NpYXRlIHByb2Zlc3NvcicsICdhc3NvY2lhdGUgZGlyZWN0b3InLCAnYmlvbG9neScsICdiaW9tZWRpY2FsJywgJ2Jvb2snLCAnY2llbmNpYXMnLCAnY2xpbmljYWwgdHJpYWwnLCAnY2xpbmljYWwgdHJpYWxzJywgJ2NvbGxlZ2UnLCAnY29uc29ydGl1bScsICdjb3B5cmlnaHQnLCAnZGV2ZWxvcCcsICdkaWdpdGFsIG9iamVjdCcsICdkaXJlY3RvciBvZicsICdkaXNjb3ZlcicsICdkb2N0b3JhbCcsICdkb2knLCAnZWRpdG9yJywgJ0VkaXRvci1pbi1DaGllZicsICdldmlkZW5jZScsICdldmlkZW5jZSBiYXNlJywgJ2V2aWRlbmNlYmFzZWQnLCAnaGVhZCBvZicsICdoaWdoZXIgZWR1Y2F0aW9uJywgJ2hpZ2hlcmVkJywgJ2h1bWFuaXRpZXMnLCAnaW5mb3JtYXRpb24gc2NpZW5jZScsICdpbmZvcm1hdGlvbiBzY2llbmNlcycsICdpbnN0aXR1dGUnLCAnaW5zdGl0dXRlcycsICdpbnN0aXR1dGlvbicsICdpbnN0aXR1dGlvbnMnLCAnaW50ZXJkaXNjaXBsaW5hcnknLCAnam91cm5hbCcsICdqb3VybmFscycsICdsZWFybmluZycsICdsZWN0dXJlcicsICdsaWJyYXJpYW4nLCAnbGlicmFyaWFucycsICdsaWJyYXJpZXMnLCAnbGlicmFyeScsICdsaWNlbmNlJywgJ2xpY2Vuc2UnLCAnbGljZW5zaW5nJywgJ0xJUycsICdtYW51c2NyaXB0JywgJ21hbnVzY3JpcHRzJywgJ21lZGljaW5lJywgJ21ldHJpY3MnLCAnbW9kZWxsaW5nJywgJ211c2V1bScsICdvcGVuIGFjY2VzcycsICdvcGVuIGRhdGEnLCAnb3BlbiBrbm93bGVkZ2UnLCAnb3BlbiByZXNlYXJjaCcsICdvcGVuIHNjaG9sYXJzaGlwJywgJ3BhcGVyJywgJ3BhcGVycycsICdwZWVyIHJldmlldycsICdwZWVyIHJldmlld2VkJywgJ3BlZXItcmV2aWV3JywgJ3BlZXItcmV2aWV3ZWQnLCAncGguZC4gY2FuZGlkYXRlJywgJ1BoRCcsICdQaEQgY2FuZGlkYXRlJywgJ3Bvc3Rkb2MnLCAncG9zdC1kb2MnLCAncHJlcHJpbnQnLCAncHJlLXByaW50JywgJ3ByZXByaW50cycsICdwcmUtcHJpbnRzJywgJ3ByZXNzJywgJ3ByaW5jaXBhbCBpbnZlc3RpZ2F0b3InLCAncHJvZicsICdwcm9mLicsICdwcm9mZXNzb3InLCAncHVibGljIGRvbWFpbicsICdwdWJsaWNhdGlvbicsICdwdWJsaXNoJywgJ3B1Ymxpc2hlcicsICdwdWJsaXNoaW5nJywgJ3JlY2hlcmNoZScsICdyZWNoZXJjaGVzJywgJ3JlbGF0aW9uc2hpcCBiZXR3ZWVuJywgJ3Jlc2VhcmNoJywgJ3Jlc2VhcmNoIGRhdGEnLCAncmVzZWFyY2hlcicsICdzY2hvbGFyJywgJ3NjaG9sYXJseScsICdzY2hvbGFybHkgY29tbXVuaWNhdGlvbicsICdzY2hvb2wnLCAnc2NpY29tbScsICdzY2llbmNlJywgJ3NjaWVuY2VzJywgJ3NjaWVudGlmaWMnLCAnc2NpZW50aXN0JywgJ3NjaWVudGlzdHMnLCAnc29jaWV0eSBvZicsICdzdHVkZW50JywgJ3RlYWNoZXInLCAndGVhY2hpbmcnLCAndW5pdmVyc2l0aWVzJywgJ3VuaXZlcnNpdHknKQ0KYWNjb3VudF9kZXNjcmlwdGlvbl92YWxpZGF0aW9uX3N0cmluZyA8LSBwYXN0ZShhY2NvdW50X2Rlc2NyaXB0aW9uX3ZhbGlkYXRpb24sIGNvbGxhcHNlPSJ8IikNCg0KIyBBY2NvdW50cyBhcmUgbWFya2VkIGFzICJLZWVwIiBvciAiRGlzY2FyZCIgYmFzZWQgb24gdGhlIGFib3ZlIGxpc3Qgb2Ygd29yZHMuDQpUd2l0dGVyX2RhdGEkcmVsZXZhbmNlX2NoZWNrIDwtIGlmZWxzZShncmVwbChhY2NvdW50X2Rlc2NyaXB0aW9uX3ZhbGlkYXRpb25fc3RyaW5nLCBUd2l0dGVyX2RhdGEkZGVzY3JpcHRpb24sIGlnbm9yZS5jYXNlID0gVFJVRSksICJLZWVwIiwgIkRpc2NhcmQiKQ0KDQojIE9ubHkgdGhlIGFjY291bnRzIG1hcmtlZCBhcyAiS2VlcCIgYXJlIHRha2VuIGZvcndhcmQuDQpUd2l0dGVyX2RhdGEgPC0gVHdpdHRlcl9kYXRhW1R3aXR0ZXJfZGF0YSRyZWxldmFuY2VfY2hlY2sgPT0gJ0tlZXAnLF0gDQpgYGANCg0KIyBTZWN0aW9uIDQgLSBEYXRhIGNsZWFuaW5nDQoNClRoZSB0ZXh0IG9mIHRoZSB0d2VldHMgaXMgY2xlYW5lZCBmcm9tIG9kZCBjaGFyYWN0ZXJzIGFuZCBVUkxzIHVzaW5nIHJlZ2V4Lg0KDQpgYGB7ciB3YXJuaW5nID0gRkFMU0V9DQoNCiMgUmVtb3ZlIFVuaWNvZGUgZm9ybWF0IGFuZCBvdGhlciB0ZXh0dWFsIG9kZGl0aWVzLg0KVHdpdHRlcl9kYXRhJHRleHQgPC0gc3RyX3JlcGxhY2VfYWxsKFR3aXR0ZXJfZGF0YSR0ZXh0LCJcXDxVW15cXD5dKlxcPiIsIiAiKQ0KVHdpdHRlcl9kYXRhJHRleHQgPC0gc3RyX3JlcGxhY2VfYWxsKFR3aXR0ZXJfZGF0YSR0ZXh0LCJcclxuIiwiICIpDQpUd2l0dGVyX2RhdGEkdGV4dCA8LSBzdHJfcmVwbGFjZV9hbGwoVHdpdHRlcl9kYXRhJHRleHQsIiZhbXA7IiwiICIpDQoNCiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiB0byBzYXZlIHRoZSBvcmlnaW5hbCB0ZXh0IGJlZm9yZSBhbnkgZnVydGhlciBjbGVhbmluZyAtIHRoaXMgaXMganVzdCBhIGJhY2t1cC4NClR3aXR0ZXJfZGF0YSRPcmlnaW5hbF9Ud2VldF9CYWNrdXAgPC0gVHdpdHRlcl9kYXRhJHRleHQNCg0KIyBDb250aW51ZSBjbGVhbmluZywgcmVtb3ZpbmcgaGFzaHRhZ3MsIG1lbnRpb25zIGFuZCAiUlQiLiBOb3RlIHRoYXQgaGFzaHRhZ3MgYXJlIHNhdmVkIGluIGEgZGVkaWNhdGVkIGNvbHVtbiBzbyB0aGlzIGlzIGp1c3QgcmVtb3ZpbmcgdGhlbSBmcm9tIHRoZSBib2R5IG9mIHRoZSB0d2VldC4NClR3aXR0ZXJfZGF0YSR0ZXh0IDwtIHN0cl9yZXBsYWNlX2FsbChUd2l0dGVyX2RhdGEkdGV4dCwiXlJUOj8gIiwiICIpDQpUd2l0dGVyX2RhdGEkdGV4dCA8LSBzdHJfcmVwbGFjZV9hbGwoVHdpdHRlcl9kYXRhJHRleHQsIkBbWzphbG51bTpdXSsiLCIgIikNClR3aXR0ZXJfZGF0YSR0ZXh0IDwtIHN0cl9yZXBsYWNlX2FsbChUd2l0dGVyX2RhdGEkdGV4dCwiI1tbOmFsbnVtOl1dKyIsIiAiKQ0KVHdpdHRlcl9kYXRhJHRleHQgPC0gc3RyX3JlcGxhY2VfYWxsKFR3aXR0ZXJfZGF0YSR0ZXh0LCJodHRwXFxTK1xccyoiLCIgIikNCmBgYA0KDQojIFNlY3Rpb24gNSAtIE92ZXJ2aWV3IG9mIHBvc3RpbmcgdGltZXMNCg0KQSBjaGFydCBvZiB0d2VldHMgYnkgZGF0ZSBpcyBjcmVhdGVkLg0KDQpgYGB7ciB3YXJuaW5nID0gRkFMU0V9DQoNCnRzX3Bsb3QoVHdpdHRlcl9kYXRhLCAiaG91cnMiKSArDQogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLA0KICAgICAgIHRpdGxlID0gIkZyZXF1ZW5jeSBvZiB0d2VldHMgdnMgdGltZSIsDQogICAgICAgc3VidGl0bGUgPSBwYXN0ZTAoZm9ybWF0KG1pbihUd2l0dGVyX2RhdGEkY3JlYXRlZF9hdCkpLCAiIHRvICIsIGZvcm1hdChtYXgoVHdpdHRlcl9kYXRhJGNyZWF0ZWRfYXQpKSksDQogICAgICAgY2FwdGlvbiA9ICJEYXRhIGNvbGxlY3RlZCBmcm9tIFR3aXR0ZXIncyBBUEkgKHJ0d2VldCkiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCiMgU2VjdGlvbiA2IC0gQW5hbHlzaXMgb2YgaGFzaHRhZ3MNCg0KVGhlIGhhc2h0YWdzIGhhcnZlc3RlZCBhcmUgYW5hbHlzZWQgYW5kIHNob3duIGFzIGEgd29yZCBjbG91ZCBhbmQgYXMgYSB0YWJsZS4NCg0KTm90ZTogU29tZSBvZiB0aGUgdHdlZXRzLCBldmVuIGlmIHRoZXkgaW5jbHVkZSB0aGUgaGFzaHRhZ3MgY29uc2lkZXJlZCBhbmQgd2VyZSBoYXJ2ZXN0ZWQgYXMgYSByZXN1bHQsIGRvIG5vdCBpbmNsdWRlIHRoZSBoYXNodGFncyBpbiB0aGUgZGVkaWNhdGVkICJoYXNodGFncyIgY29sdW1uIG9mIFR3aXR0ZXJfZGF0YS4gYXMgYSByZXN1bHQsIHNvbWUgb2YgdGhlIHR3ZWV0cyBpbiB0aGUgZGF0YXNldCBkbyBub3QgY29udHJpYnV0ZSB0byB0aGUgYmVsb3cgY2FsY3VsYXRpb25zLg0KDQpgYGB7ciB3YXJuaW5nID0gRkFMU0V9DQoNCmhhc2h0YWdzX3ZlY3RvciA8LSBUd2l0dGVyX2RhdGEkaGFzaHRhZ3MgDQoNCnNwbGl0X2hhc2h0YWdzIDwtIHN0cl9zcGxpdF9maXhlZChoYXNodGFnc192ZWN0b3IsICIgIiwgMTAwKSAjIFRoaXMgc3BsaXRzIHRoZSBoYXNodGFncyBjb2x1bW4gdXNpbmcgdGhlIHNwYWNlIHNlcGFyYXRvci4gIjEwMCIgYWxsb3dzIHJvb20gZm9yIDEwMCBjb2x1bW5zLCBqdXN0IGluIGNhc2UuDQpzcGxpdF9oYXNodGFnc19zaW5nbGVfY29sdW1uIDwtIHN0YWNrKGRhdGEuZnJhbWUoc3BsaXRfaGFzaHRhZ3MpKQ0Kc3BsaXRfaGFzaHRhZ3Nfc2luZ2xlX2NvbHVtbiA8LSBkYXRhLmZyYW1lKHNwbGl0X2hhc2h0YWdzX3NpbmdsZV9jb2x1bW4kdmFsdWVzKQ0KDQpzcGxpdF9oYXNodGFnc19zaW5nbGVfY29sdW1uIDwtIG11dGF0ZV9hbGwoc3BsaXRfaGFzaHRhZ3Nfc2luZ2xlX2NvbHVtbiwgbGlzdCh0b2xvd2VyKSkgIyBDb252ZXJ0aW5nIHRvIGxvd2VyY2FzZSBpcyB1c2VmdWwgYmVjYXVzZSBwZW9wbGUgbWlnaHQgdXNlICJPcGVuQWNjZXNzIiwgIm9wZW5hY2Nlc3MiLCAiT3BlbmFjY2VzcyIsIGV0Yy4NCg0KIyBUaGUgbGluZSBiZWxvdyBnZXRzIHJpZCBvZiByb3dzIHRoYXQgYXJlIGVxdWFsIHRvICNvcGVuYWNjZXNzLCBhcyB0aGlzIHdpbGwgc2ltcGx5IGJlIGEgaHVnZSB3b3JkIGluIHRoZSBtaWRkbGUgb2YgYSB3b3JkIGNsb3VkLg0KIyBZb3Ugc2hvdWxkIHJlcGxhY2UgIm9wZW5hY2Nlc3MiIHdpdGggYW55IG90aGVyIHdvcmRzIHJlbGV2YW50IHRvIHlvdSwgb3Igc2ltcGx5IGNvbW1lbnQgdGhlIG5leHQgbGluZS4NCnNwbGl0X2hhc2h0YWdzX3NpbmdsZV9jb2x1bW4gPC0gc3BsaXRfaGFzaHRhZ3Nfc2luZ2xlX2NvbHVtbltzcGxpdF9oYXNodGFnc19zaW5nbGVfY29sdW1uICE9ICJvcGVuYWNjZXNzIiwgXSANCg0Kc3BsaXRfaGFzaHRhZ3Nfc2luZ2xlX2NvbHVtbiA8LSBkYXRhLmZyYW1lKHNwbGl0X2hhc2h0YWdzX3NpbmdsZV9jb2x1bW4pDQpzcGxpdF9oYXNodGFnc19zaW5nbGVfY29sdW1uX2NsZWFuIDwtIHNwbGl0X2hhc2h0YWdzX3NpbmdsZV9jb2x1bW5bc3BsaXRfaGFzaHRhZ3Nfc2luZ2xlX2NvbHVtbiAhPSAiIiwgXSAjIFRoaXMgZ2V0cyByaWQgb2Ygcm93cyB0aGF0IGFyZSBibGFuaw0KDQp3b3JkY2xvdWQoc3BsaXRfaGFzaHRhZ3Nfc2luZ2xlX2NvbHVtbl9jbGVhbiwgbWluLmZyZXE9MzAsIHJhbmRvbS5vcmRlcj1GQUxTRSwgY29sb3JzPWJyZXdlci5wYWwoOSwgJ1JlZHMnKVs0OjldKQ0KDQojIElmIHlvdSB3YW50IHRoZSB3b3JkIGNsb3VkIGluIGEgdGFibGU6DQpzcGxpdF9oYXNodGFnc19zaW5nbGVfY29sdW1uX2NsZWFuIDwtIGFzLmRhdGEuZnJhbWUoc3BsaXRfaGFzaHRhZ3Nfc2luZ2xlX2NvbHVtbl9jbGVhbikNCm5hbWVzKHNwbGl0X2hhc2h0YWdzX3NpbmdsZV9jb2x1bW5fY2xlYW4pWzFdIDwtICdoYXNodGFnJw0KDQpzcGxpdF9oYXNodGFnc19zaW5nbGVfY29sdW1uX2NsZWFuIDwtIHNwbGl0X2hhc2h0YWdzX3NpbmdsZV9jb2x1bW5fY2xlYW4gJT4lICANCiAgZ3JvdXBfYnkoaGFzaHRhZykgJT4lDQogIHN1bW1hcmlzZSh3ZWlnaHQgPSBuKCkpICU+JSANCiAgdW5ncm91cCgpDQoNCnNwbGl0X2hhc2h0YWdzX3NpbmdsZV9jb2x1bW5fY2xlYW4gPC0gc3BsaXRfaGFzaHRhZ3Nfc2luZ2xlX2NvbHVtbl9jbGVhbltvcmRlcigtc3BsaXRfaGFzaHRhZ3Nfc2luZ2xlX2NvbHVtbl9jbGVhbiR3ZWlnaHQpLCBdDQoNCnBhZ2VkX3RhYmxlKGhlYWQoc3BsaXRfaGFzaHRhZ3Nfc2luZ2xlX2NvbHVtbl9jbGVhbiwgNTApKQ0KYGBgDQoNCiMgU2VjdGlvbiA3IC0gQW5hbHlzaXMgb2YgbWVudGlvbnMNCg0KTWVudGlvbnMgYXJlIGFuYWx5c2VkIHRvIGlkZW50aWZ5IHRoZSBtb3N0IG1lbnRpb25lZCBhY2NvdW50cy4gUmVzdWx0cyBhcmUgc2hvd24gaW4gYSB3b3JkIGNsb3VkIGFuZCBhIHRhYmxlLg0KDQpgYGB7ciB3YXJuaW5nID0gRkFMU0V9DQoNCiMgRXhjbHVkZSByZXR3ZWV0cywgYmVjYXVzZSB0aGV5IGFyZSBjb25zaWRlcmVkIGFzIG1lbnRpb25zIGluIHRoZSBkYXRhLiBJZiB5b3UgcmV0d2VldCBzb21lb25lLCB0aGUgQVBJIGNvbnNpZGVycyB0aGF0IGFzIHlvdSBtZW50aW9uaW5nIHRoZW0uDQpUd2l0dGVyX2RhdGFfbm9fcmV0d2VldHMgPC0gVHdpdHRlcl9kYXRhW1R3aXR0ZXJfZGF0YSRpc19yZXR3ZWV0ID09ICdGQUxTRScsXQ0KbWVudGlvbnNfdmVjdG9yIDwtIFR3aXR0ZXJfZGF0YV9ub19yZXR3ZWV0cyRtZW50aW9uc19zY3JlZW5fbmFtZSANCg0KIyBTcGxpdCB0aGUgbWVudGlvbnMgY29sdW1uIHVzaW5nIHRoZSBzcGFjZSBzZXBhcmF0b3IuICIxMDAiIGFsbG93cyByb29tIGZvciAxMDAgY29sdW1ucywganVzdCBpbiBjYXNlIChub3RlIHRoYXQgdGhpcyBpcyBub3QgcG9zc2libGUgd2l0aCBUd2l0dGVyJ3MgY2hhcmFjdGVyIGxpbWl0ISkuDQpzcGxpdF9tZW50aW9ucyA8LSBzdHJfc3BsaXRfZml4ZWQobWVudGlvbnNfdmVjdG9yLCAiICIsIDEwMCkgDQpzcGxpdF9tZW50aW9uc19zaW5nbGVfY29sdW1uIDwtIHN0YWNrKGRhdGEuZnJhbWUoc3BsaXRfbWVudGlvbnMpKQ0Kc3BsaXRfbWVudGlvbnNfc2luZ2xlX2NvbHVtbiA8LSBkYXRhLmZyYW1lKHNwbGl0X21lbnRpb25zX3NpbmdsZV9jb2x1bW4kdmFsdWVzKQ0KDQojIEdldCByaWQgb2Ygcm93cyB0aGF0IGFyZSBibGFuaw0Kc3BsaXRfbWVudGlvbnNfc2luZ2xlX2NvbHVtbl9jbGVhbiA8LSBzcGxpdF9tZW50aW9uc19zaW5nbGVfY29sdW1uW3NwbGl0X21lbnRpb25zX3NpbmdsZV9jb2x1bW4gIT0gIiIsIF0gDQoNCndvcmRjbG91ZChzcGxpdF9tZW50aW9uc19zaW5nbGVfY29sdW1uX2NsZWFuLCBtaW4uZnJlcT01LCByYW5kb20ub3JkZXI9RkFMU0UsIGNvbG9ycz1icmV3ZXIucGFsKDksICdSZWRzJylbNDo5XSkNCg0KIyBJZiB5b3Ugd2FudCB0aGUgd29yZCBjbG91ZCBpbiBhIHRhYmxlOg0Kc3BsaXRfbWVudGlvbnNfc2luZ2xlX2NvbHVtbl9jbGVhbiA8LSBhcy5kYXRhLmZyYW1lKHNwbGl0X21lbnRpb25zX3NpbmdsZV9jb2x1bW5fY2xlYW4pDQpuYW1lcyhzcGxpdF9tZW50aW9uc19zaW5nbGVfY29sdW1uX2NsZWFuKVsxXSA8LSAnYWNjb3VudCcNCg0Kc3BsaXRfbWVudGlvbnNfc2luZ2xlX2NvbHVtbl9jbGVhbiA8LSBzcGxpdF9tZW50aW9uc19zaW5nbGVfY29sdW1uX2NsZWFuICU+JSAgDQogIGdyb3VwX2J5KGFjY291bnQpICU+JQ0KICBzdW1tYXJpc2Uod2VpZ2h0ID0gbigpKSAlPiUgDQogIHVuZ3JvdXAoKQ0KDQpzcGxpdF9tZW50aW9uc19zaW5nbGVfY29sdW1uX2NsZWFuIDwtIHNwbGl0X21lbnRpb25zX3NpbmdsZV9jb2x1bW5fY2xlYW5bb3JkZXIoLXNwbGl0X21lbnRpb25zX3NpbmdsZV9jb2x1bW5fY2xlYW4kd2VpZ2h0KSwgXQ0KDQpwYWdlZF90YWJsZShoZWFkKHNwbGl0X21lbnRpb25zX3NpbmdsZV9jb2x1bW5fY2xlYW4sIDUwKSkNCmBgYA0KDQojIFNlY3Rpb24gOCAtIEFuYWx5c2lzIG9mIGxpbmtzIHNoYXJlZA0KDQpMaW5rcyBzaGFyZWQgaW4gdGhlIHR3ZWV0cyBoYXJ2ZXN0ZWQgYXJlIHNob3duIGFzIGEgdGFibGUsIHRvIGlkZW50aWZ5IGxpdGVyYXR1cmUgc291cmNlcyBhbmQgYW55IHJlbGV2YW50IGV2ZW50cyBmb3IgaW5jbHVzaW9uIGluIHRoZSBzdHVkeS4NCg0KYGBge3Igd2FybmluZyA9IEZBTFNFfQ0KDQp0b3BfdXJscyA8LSBUd2l0dGVyX2RhdGFbLCBjKCJ1cmxzX2V4cGFuZGVkX3VybCIpXQ0KdG9wX3VybHMgPC0gdG9wX3VybHNbY29tcGxldGUuY2FzZXModG9wX3VybHMpLCBdICMgVGhpcyBnZXRzIHJpZCBvZiByb3dzIHdpdGggbWlzc2luZyB2YWx1ZXMNCg0KdG9wX3VybHMgPC0gdG9wX3VybHMgJT4lICANCiAgZ3JvdXBfYnkodXJsc19leHBhbmRlZF91cmwpICU+JQ0KICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JSANCiAgdW5ncm91cCgpDQoNCnRvcF91cmxzIDwtIHRvcF91cmxzW29yZGVyKC10b3BfdXJscyRjb3VudCksXQ0KDQpwYWdlZF90YWJsZShoZWFkKHRvcF91cmxzLCA1MCkpDQpgYGANCg0KIyBTZWN0aW9uIDkgLSBBbmFseXNpcyBvZiBtb3N0IHJldHdlZXRlZCB0d2VldHMNCg0KVGhlIG1vc3QgcmV0d2VldGVkIHR3ZWV0cyBhcmUgcmV2aWV3ZWQgdG8gc2VlIGlmIGFueSBrZXkgZXZlbnRzIG9yIGRpc2N1c3Npb25zIHNob3VsZCBiZSByZWZsZWN0ZWQgaW4gdGhlIHN0dWR5LiBUaGUgcmVzdWx0cyBjYW4gYmUgc2hvd24gaW4gYSB0YWJsZSAtIG5vIG91dHB1dCBpcyBzaG93biBoZXJlIGR1ZSB0byBkYXRhIHByaXZhY3kgY29uc2lkZXJhdGlvbnMuDQoNCmBgYHtyIHdhcm5pbmcgPSBGQUxTRX0NCg0KIyBJIHVzZWQgdGhlIE9yaWdpbmFsX1R3ZWV0X0JhY2t1cCBjb2x1bW4gSSd2ZSBkZWZpbmVkIGFib3ZlLiANCiMgVGhpcyBpcyBiZWNhdXNlIHRoZSBvcmlnaW5hbCAidGV4dCIgY29sdW1uIGhhcyBiZWVuIHN0cmlwcGVkIG9mIGhhc2h0YWdzLCBtZW50aW9ucywgbGlua3MsIGV0Yy4NCnRvcF90d2VldHMgPC0gVHdpdHRlcl9kYXRhWywgYygic2NyZWVuX25hbWUiLCAiT3JpZ2luYWxfVHdlZXRfQmFja3VwIiwgInJldHdlZXRfY291bnQiLCAic3RhdHVzX3VybCIpXQ0KDQojIFRoaXMgZGVkdXBsaWNhdGVzIHRoZSBkYXRhc2V0IGJ5IHR3ZWV0IHRleHQuIEkgZG8gdGhpcyBhcyBvdGhlcndpc2UgSSdkIGdldCANCiMgbG90cyBvZiBkdXBsaWNhdGVkIG9jY3VycmVuY2VzIChpLmUuIHBlb3BsZSByZXR3ZWV0aW5nIHRoZSBzYW1lIHBvcHVsYXIgdHdlZXQpDQp0b3BfdHdlZXRzIDwtIHRvcF90d2VldHNbIWR1cGxpY2F0ZWQodG9wX3R3ZWV0cyRPcmlnaW5hbF9Ud2VldF9CYWNrdXApLF0gDQoNCnRvcF90d2VldHMkcmV0d2VldF9jb3VudCA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih0b3BfdHdlZXRzJHJldHdlZXRfY291bnQpKSAjIFRoZSBkYXRhIHRhYmxlIGlzIGFsbCBjaGFyYWN0ZXJzLCBzbyBJIG5lZWQgdG8gY29udmVydCB0aGUgcmV0d2VldCBjb3VudCBjb2x1bW4gaW50byBudW1iZXJzDQp0b3BfdHdlZXRzIDwtIHRvcF90d2VldHNbb3JkZXIoLXRvcF90d2VldHMkcmV0d2VldF9jb3VudCksXQ0KDQpgYGANCg0KIyBTZWN0aW9uIDEwIC0gQW5hbHlzaXMgb2YgdG9wIHR3ZWV0ZXJzDQoNClRvcCB0d2VldGVycyBhcmUgcmV2aWV3ZWQgdG8gZ2FpbiBhbiB1bmRlcnN0YW5kaW5nIG9mIHRoZSBpbmRpdmlkdWFscyBvciBvcmdhbmlzYXRpb25zIHRoYXQgbW9zdCBjb250cmlidXRlIHRvIHRoZSByZXNlYXJjaCByZXByb2R1Y2liaWxpdHkgZGlzY291cnNlLiBUaGUgcmVzdWx0cyBhcmUgc2hvd24gaW4gYSB0YWJsZS4NCg0KYGBge3Igd2FybmluZyA9IEZBTFNFfQ0KDQojIFRoZSB0b3AgdHdlZXRlcnMgZGF0YSB0YWJsZSBpcyBleHRyYWN0ZWQgZnJvbSB0aGUgZnVsbCBkYXRhc2V0DQp0b3BUd2VldGVycyA8LSBUd2l0dGVyX2RhdGEgJT4lIHNlbGVjdChzY3JlZW5fbmFtZSkgDQoNCiMgVGhlIG51bWJlciBvZiBvY2N1cnJlbmNlcyBvZiBlYWNoIHRvcCB0d2VldGVycyBpcyBjb3VudGVkDQp0b3BUd2VldGVycyA8LSB0b3BUd2VldGVycyAlPiUgZ3JvdXBfYnkoc2NyZWVuX25hbWUpICU+JSBzdW1tYXJpc2UoY291bnQ9bigpKSANCg0KIyBUaGUgdGFibGUgaXMgc29ydGVkDQp0b3BUd2VldGVycyA8LSB0b3BUd2VldGVyc1tvcmRlcigtdG9wVHdlZXRlcnMkY291bnQpLF0gDQoNCnBhZ2VkX3RhYmxlKGhlYWQodG9wVHdlZXRlcnMsIDUwKSkNCmBgYA0KDQojIFNlY3Rpb24gMTEgLSBJZGVudGlmaWNhdGlvbiBvZiBhY2NvdW50cyB3aXRoIHRoZSBtb3N0IGZvbGxvd2VycyBpbiB0aGUgc2FtcGxlDQoNClRoZSBtb3N0IHBvcHVsYXIgaW5kaXZpZHVhbHMgb3Igb3JnYW5pc2F0aW9ucyBpbiB0aGUgZGF0YXNldCBhcmUgcmV2aWV3ZWQgdG8gdW5kZXJzdGFuZCB0aGUgZHluYW1pY3Mgb2Ygc29jaWFsIG1lZGlhIGRpc2NvdXJzZTogd2hvIGFyZSB0aGUgdHdlZXRlcnMgd2l0aCB0aGUgbGFyZ2VzdCBwb3NzaWJsZSByZWFjaD8gVGhlIHJlc3VsdHMgYXJlIHNob3duIGluIGEgdGFibGUuDQoNCmBgYHtyIHdhcm5pbmcgPSBGQUxTRX0NCg0KIyBTZWxlY3QgYSBsaXN0IG9mIHVuaXF1ZSBhY2NvdW50cy4NCmhpZ2hlc3RGb2xsb3dlcnMgPC0gVHdpdHRlcl9kYXRhICU+JSBzZWxlY3Qoc2NyZWVuX25hbWUsIGZvbGxvd2Vyc19jb3VudCwgZnJpZW5kc19jb3VudCwgZGVzY3JpcHRpb24sIGxvY2F0aW9uKQ0KaGlnaGVzdEZvbGxvd2Vyc191bmlxdWUgPC0gaGlnaGVzdEZvbGxvd2Vyc1shZHVwbGljYXRlZChoaWdoZXN0Rm9sbG93ZXJzJHNjcmVlbl9uYW1lKSxdIA0KDQojIFRoZSBkYXRhIHRhYmxlIGlzIGFsbCBjaGFyYWN0ZXJzLCBzbyByZWxldmFudCBjb2x1bW5zIGhhdmUgdG8gYmUgY29udmVydGVkIGludG8gbnVtYmVycy4NCmhpZ2hlc3RGb2xsb3dlcnNfdW5pcXVlJGZvbGxvd2Vyc19jb3VudCA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihoaWdoZXN0Rm9sbG93ZXJzX3VuaXF1ZSRmb2xsb3dlcnNfY291bnQpKQ0KaGlnaGVzdEZvbGxvd2Vyc191bmlxdWUkZnJpZW5kc19jb3VudCA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihoaWdoZXN0Rm9sbG93ZXJzX3VuaXF1ZSRmcmllbmRzX2NvdW50KSkNCg0KIyBTb3J0IHRoZSB0YWJsZSBvZiBzdGFrZWhvbGRlcnMgYnkgbnVtYmVyIG9mIGZvbGxvd2VycyBhbmQgbnVtYmVyIG9mIGZyaWVuZHMuDQpzdGFrZWhvbGRlcl9oaWdoZXN0Rm9sbG93ZXJzIDwtIGhpZ2hlc3RGb2xsb3dlcnNfdW5pcXVlW29yZGVyKC1oaWdoZXN0Rm9sbG93ZXJzX3VuaXF1ZSRmb2xsb3dlcnNfY291bnQsIC1oaWdoZXN0Rm9sbG93ZXJzX3VuaXF1ZSRmcmllbmRzX2NvdW50KSxdDQoNCnN0YWtlaG9sZGVyX2hpZ2hlc3RGb2xsb3dlcnNfdGFibGUgPC0gc2VsZWN0KHN0YWtlaG9sZGVyX2hpZ2hlc3RGb2xsb3dlcnMsIHNjcmVlbl9uYW1lLCBmb2xsb3dlcnNfY291bnQsIGZyaWVuZHNfY291bnQpDQoNCnBhZ2VkX3RhYmxlKGhlYWQoc3Rha2Vob2xkZXJfaGlnaGVzdEZvbGxvd2Vyc190YWJsZSw1MCkpDQpgYGANCg0KIyBTZWN0aW9uIDEyIC0gQW5hbHlzaXMgb2YgdGhlIG1vc3QgY29tbW9ubHkgdXNlZCB3b3JkcyBpbiB0aGUgZGF0YXNldA0KDQpDb3JwdXMgYW5hbHlzaXMgaXMgdXNlZCB0byBhbmFseXNlIHRoZSB3b3JkcyBtb3N0IGNvbW1vbmx5IHVzZWQgaW4gdGhlIGRhdGFzZXQuIFRoZSByZXN1bHRzIGFyZSBzaG93biBpbiBhIHdvcmQgY2xvdWQgdG8gZ2FpbiBhbiB1bmRlcnN0YW5kaW5nIG9mIHRoZSBsYW5ndWFnZSB1c2VkIHdoZW4gZGlzY3Vzc2luZyByZXByb2R1Y2liaWxpdHkuDQoNCmBgYHtyIHdhcm5pbmcgPSBGQUxTRX0NCg0KIyBUaGUgdHdlZXQncyB0ZXh0IGlzIGluIHRoZSBjb2x1bW4gY2FsbGVkICJ0ZXh0IiBpbiB0aGUgZGF0YSB0YWJsZSBjYWxsZWQgIlR3aXR0ZXJfZGF0YSIuDQpkYXRhX2Zvcl9jb3JwdXMgPC0gVHdpdHRlcl9kYXRhICU+JSBzZWxlY3Qoc2NyZWVuX25hbWUsIHRleHQpDQoNCiMgQnVpbGQgdGhlIGNvcnB1cyBmb3IgYW5hbHlzaXMuDQpjb3JwdXMgPC0gQ29ycHVzKFZlY3RvclNvdXJjZShkYXRhX2Zvcl9jb3JwdXMkdGV4dCkpIA0KDQojIFRoZSBjb3JwdXMgaXMgY2xlYW5lZCBhbmQgc3RhbmRhcmRpc2VkLg0KY29ycHVzIDwtIHRtX21hcChjb3JwdXMsIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpDQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgcmVtb3ZlTnVtYmVycykNCmNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLCBzdHJpcFdoaXRlc3BhY2UpDQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgcmVtb3ZlUHVuY3R1YXRpb24pDQoNCiMgUmVtb3ZlIHN0b3Agd29yZHMgYnkgdXNpbmcgYSBwcmUtZGVmaW5lZCBsaXN0IGZvciB0aGUgRW5nbGlzaCBsYW5ndWFnZSBhbmQgYWRkaXRpb25hbCB3b3JkcyBpbiBxdW90ZXMuDQpteXN0b3B3b3JkcyA8LSBjKHN0b3B3b3JkcygiZW5nbGlzaCIpLCJydCIsImdldCIsImxpa2UiLCJqdXN0IiwieWVzIiwia25vdyIsIndpbGwiLCJnb29kIiwiZGF5IiwicGVvcGxlIiwgImdvdCIsICJjYW4iLCAiYW1wIikNCmNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLHJlbW92ZVdvcmRzLG15c3RvcHdvcmRzKQ0KDQojIENyZWF0ZSBhIGRvY3VtZW50IHRlcm0gbWF0cml4Lg0KbXlEdG0gPC0gRG9jdW1lbnRUZXJtTWF0cml4KGNvcnB1cykgDQpzcGFyc2UgPC0gcmVtb3ZlU3BhcnNlVGVybXMobXlEdG0sIDAuOTcpDQpzcGFyc2UgPC0gYXMuZGF0YS5mcmFtZShhcy5tYXRyaXgoc3BhcnNlKSkNCg0KIyBDYWxjdWxhdGUgdGhlIGZyZXF1ZW5jeSBvZiBlYWNoIHdvcmQgZnJvbSB0aGUgZGF0YSB0YWJsZSBjcmVhdGVkIC0gY29sU3VtcyBhZGRzIHVwIHRoZSB0b3RhbHMgYnkgY29sdW1uLg0KIyBmcmVxV29yZHMgaXMgYSByb3cgb2YgbnVtYmVycywgd2hpY2ggaGFzIHRoZSAgd29yZHMgYXMgdGhlIGNvbHVtbiBoZWFkZXJzLg0KZnJlcVdvcmRzIDwtIGNvbFN1bXMoc3BhcnNlKQ0KZnJlcVdvcmRzIDwtIGZyZXFXb3Jkc1tvcmRlcigtZnJlcVdvcmRzKV0NCg0Kd29yZGNsb3VkKGZyZXEgPSBhcy52ZWN0b3IoZnJlcVdvcmRzKSwgd29yZHMgPSBuYW1lcyhmcmVxV29yZHMpLHJhbmRvbS5vcmRlciA9IEZBTFNFLA0KICAgICAgICAgIHJhbmRvbS5jb2xvciA9IEZBTFNFLCBjb2xvcnMgPSBicmV3ZXIucGFsKDksICdSZWRzJylbNDo5XSkNCg0KcGFnZWRfdGFibGUoaGVhZChhcy5kYXRhLmZyYW1lKGZyZXFXb3JkcyksIDUwKSkNCmBgYA0KDQojIFNlY3Rpb24gMTMgLSBSZXR3ZWV0IG5ldHdvcmsgYW5hbHlzaXMgKGZ1bGwgbmV0d29yaykNCg0KQSBncmFwaGljIG9mIHRoZSByZXR3ZWV0IG5ldHdvcmtzIGlzIGNyZWF0ZWQgYXMgYW4gaHRtbCBmaWxlLiBUaGlzIHNob3dzIHJlbGF0aW9uc2hpcHMgc3VjaCBhcyAid2hvIHJldHdlZXRlZCB3aG9tPyIuIFRoZSBhbmFseXNpcyBpcyBwcmVzZW50ZWQgYXMgYW4gaW50ZXJhY3RpdmUgSFRNTCBmaWxlIGFuZCBpbmNsdWRlcyBhbGwgdHdlZXRzIGluIHRoZSBkYXRhc2V0Lg0KDQpgYGB7ciB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQoNCiMgU2VsZWN0IHRoZSBhcHByb3ByaWF0ZSBjb2x1bW5zLg0KZGF0YV9mb3JfbmV0d29yayA8LSBUd2l0dGVyX2RhdGFbLCBjKCJzY3JlZW5fbmFtZSIsICJyZXR3ZWV0X3NjcmVlbl9uYW1lIiwgInRleHQiLCAiZm9sbG93ZXJzX2NvdW50IildDQpkYXRhX2Zvcl9uZXR3b3JrJGZvbGxvd2Vyc19jb3VudCA8LSBhcy5udW1lcmljKGRhdGFfZm9yX25ldHdvcmskZm9sbG93ZXJzX2NvdW50KQ0KDQojIFBvdGVudGlhbGx5IGZpbHRlciBhY2NvdW50cyB0aGF0IGhhdmUgYSBjZXJ0YWluIGZvbGxvd2VyIGNvdW50LCBhcyB0aGUgbmV0d29yayBpcyBwb3RlbnRpYWxseSB2ZXJ5IGxhcmdlLiBDb21tZW50IHRoZSBsaW5lIGJlbG93IG9yIGRlbGV0ZSBpdCB0byBzaG93IGFsbCBhY2NvdW50cyBpbiB5b3VyIHNhbXBsZS4NCiMgZGF0YV9mb3JfbmV0d29yayA8LSBkYXRhX2Zvcl9uZXR3b3JrW2RhdGFfZm9yX25ldHdvcmskZm9sbG93ZXJzX2NvdW50PjQ5OSwgXSAgDQoNCiMgR2V0IHJpZCBvZiByb3dzIHdpdGggbWlzc2luZyB2YWx1ZXMuDQpkYXRhX2Zvcl9uZXR3b3JrX25vdEJsYW5rIDwtIGRhdGFfZm9yX25ldHdvcmtbY29tcGxldGUuY2FzZXMoZGF0YV9mb3JfbmV0d29yayksIF0gDQoNCiMgQnVpbGQgYSBsaXN0IG9mIG5vZGVzLg0Kd2hvVHdlZXRlZCA8LSBkYXRhX2Zvcl9uZXR3b3JrX25vdEJsYW5rJHNjcmVlbl9uYW1lDQpvcmlnaW5hbFNvdXJjZSA8LSBkYXRhX2Zvcl9uZXR3b3JrX25vdEJsYW5rJHJldHdlZXRfc2NyZWVuX25hbWUNCm5vZGVzIDwtIGMod2hvVHdlZXRlZCwgb3JpZ2luYWxTb3VyY2UpDQoNCm5vZGVzIDwtIGFzLmRhdGEuZnJhbWUodW5pcXVlKG5vZGVzKSkNCm5vZGVzIDwtIG5vZGVzICU+JSByb3dpZF90b19jb2x1bW4oImlkIikNCm5hbWVzKG5vZGVzKVsyXSA8LSAibGFiZWwiDQoNCiMgQnVpbGQgYSBsaXN0IG9mIGVkZ2VzLg0KcmV0d2VldF9uZXR3b3JrIDwtIGRhdGFfZm9yX25ldHdvcmtfbm90QmxhbmsgJT4lICANCiAgZ3JvdXBfYnkoc2NyZWVuX25hbWUsIHJldHdlZXRfc2NyZWVuX25hbWUpICU+JQ0KICBzdW1tYXJpc2Uod2VpZ2h0ID0gbigpKSAlPiUgDQogIHVuZ3JvdXAoKQ0KDQpuYW1lcyhyZXR3ZWV0X25ldHdvcmspWzFdIDwtICJXaG8gcmV0d2VldGVkIg0KbmFtZXMocmV0d2VldF9uZXR3b3JrKVsyXSA8LSAiT3JpZ2luYWwgc291cmNlIg0KDQplZGdlcyA8LSByZXR3ZWV0X25ldHdvcmsgJT4lIA0KICBsZWZ0X2pvaW4obm9kZXMsIGJ5ID0gYygiT3JpZ2luYWwgc291cmNlIiA9ICJsYWJlbCIpKSAlPiUgDQogIHJlbmFtZShmcm9tID0gaWQpDQoNCmVkZ2VzIDwtIGVkZ2VzICU+JSANCiAgbGVmdF9qb2luKG5vZGVzLCBieSA9IGMoIldobyByZXR3ZWV0ZWQiID0gImxhYmVsIikpICU+JSANCiAgcmVuYW1lKHRvID0gaWQpDQoNCiMgQ3JlYXRlIHRoZSBuZXR3b3JrLg0Kbm9kZXNfZDMgPC0gbXV0YXRlKG5vZGVzLCBpZCA9IGlkIC0gMSkNCmVkZ2VzX2QzIDwtIG11dGF0ZShlZGdlcywgZnJvbSA9IGZyb20gLSAxLCB0byA9IHRvIC0gMSkNCm5vZGVzX2QzIDwtIGFzLmRhdGEuZnJhbWUobm9kZXNfZDMpICMgVGhpcyBpcyBuZWVkZWQgdG8gYXZvaWQgdGhlIHdhcm5pbmcgIkxpbmtzIGlzIGEgdGJsX2RmLiBDb252ZXJ0aW5nIHRvIGEgcGxhaW4gZGF0YSBmcmFtZS4iDQplZGdlc19kMyA8LSBhcy5kYXRhLmZyYW1lKGVkZ2VzX2QzKSANCg0KZm9yY2VOZXR3b3JrKExpbmtzID0gZWRnZXNfZDMsIE5vZGVzID0gbm9kZXNfZDMsIFNvdXJjZSA9ICJmcm9tIiwgVGFyZ2V0ID0gInRvIiwgDQogICAgICAgICAgICAgTm9kZUlEID0gImxhYmVsIiwgR3JvdXAgPSAiaWQiLCBWYWx1ZSA9ICJ3ZWlnaHQiLCANCiAgICAgICAgICAgICBvcGFjaXR5ID0gMSwgZm9udFNpemUgPSAxNiwgem9vbSA9IFRSVUUsIGFycm93cz1UUlVFKSU+JSANCiAgaHRtbHdpZGdldHM6OnByZXBlbmRDb250ZW50KGh0bWx0b29sczo6dGFncyRoMygiRnVsbCByZXR3ZWV0IG5ldHdvcmsiKSkgDQpgYGANCg0KIyBTZWN0aW9uIDE0IC0gUmV0d2VldCBuZXR3b3JrIGFuYWx5c2lzIChtb3N0IG1lbnRpb25lZCBhY2NvdW50cykNCg0KQSBncmFwaGljIG9mIHRoZSByZXR3ZWV0IG5ldHdvcmtzIGlzIGNyZWF0ZWQgYXMgYW4gaHRtbCBmaWxlLiBUaGlzIHNob3dzIHJlbGF0aW9uc2hpcHMgc3VjaCBhcyAid2hvIHJldHdlZXRlZCB3aG9tPyIuIFRoZSBhbmFseXNpcyBpcyBwcmVzZW50ZWQgYXMgYW4gaW50ZXJhY3RpdmUgSFRNTCBmaWxlIGFuZCBpbmNsdWRlcyB0d2VldHMgaW4gdGhlIHRvcCAyNCBtb3N0IG1lbnRpb25lZCBhY2NvdW50cy4gVGhpcyBpcyBhcmJpdHJhcnkgLSB0aGUgY3V0dGluZyBwb2ludCBpcyBhY2NvdW50cyB0aGF0IGhhdmUgYmVlbiBtZW50aW9uZWQgYXQgbGVhc3QgMTAgdGltZXMgaW4gdGhlIGRhdGFzZXQuDQoNCmBgYHtyIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRX0NCg0KdG9wX2FjY291bnRzIDwtIHNwbGl0X21lbnRpb25zX3NpbmdsZV9jb2x1bW5fY2xlYW5bMToyNCwgMV0gDQpjb3VudGVyIDwtIDE6YXMubnVtZXJpYyhjb3VudCh0b3BfYWNjb3VudHMpKQ0KDQpmb3IgKGkgaW4gY291bnRlcil7DQogIFR3aXR0ZXJfZGF0YV9jb3VudGVyIDwtIFR3aXR0ZXJfZGF0YVtUd2l0dGVyX2RhdGEkcmV0d2VldF9zY3JlZW5fbmFtZSA9PSBhcy5jaGFyYWN0ZXIodG9wX2FjY291bnRzW2ksXSksXQ0KICANCiAgaWYgKGkgPT0xKXsNCiAgICB0YmxfY2hhcnQgPC0gVHdpdHRlcl9kYXRhX2NvdW50ZXINCiAgfQ0KICBpZiAoaT4xKXsNCiAgICB0YmxfY2hhcnQgPC0gcmJpbmQodGJsX2NoYXJ0LCBUd2l0dGVyX2RhdGFfY291bnRlcikNCiAgfQ0KfQ0KDQojIEFyZSBhbnkgb2YgdGhlIHRvcCBtZW50aW9uZWQgYWNjb3VudHMgbWlzc2luZyBmcm9tIHRibF9jaGFydD8gVGhhdCdzIGJlY2F1c2UgdGhleSBoYXZlbid0IGJlZW4gcmV0d2VldGVkIQ0KZGF0YV9mb3JfbmV0d29yayA8LSB0YmxfY2hhcnRbLCBjKCJzY3JlZW5fbmFtZSIsICJyZXR3ZWV0X3NjcmVlbl9uYW1lIiwgInRleHQiLCAiZm9sbG93ZXJzX2NvdW50IildDQpkYXRhX2Zvcl9uZXR3b3JrJGZvbGxvd2Vyc19jb3VudCA8LSBhcy5udW1lcmljKGRhdGFfZm9yX25ldHdvcmskZm9sbG93ZXJzX2NvdW50KQ0KDQojIEdldCByaWQgb2Ygcm93cyB3aXRoIG1pc3NpbmcgdmFsdWVzLg0KZGF0YV9mb3JfbmV0d29ya19ub3RCbGFuayA8LSBkYXRhX2Zvcl9uZXR3b3JrW2NvbXBsZXRlLmNhc2VzKGRhdGFfZm9yX25ldHdvcmspLCBdIA0KDQojIEJ1aWxkIGEgbGlzdCBvZiBub2Rlcy4NCndob1R3ZWV0ZWQgPC0gZGF0YV9mb3JfbmV0d29ya19ub3RCbGFuayRzY3JlZW5fbmFtZQ0Kb3JpZ2luYWxTb3VyY2UgPC0gZGF0YV9mb3JfbmV0d29ya19ub3RCbGFuayRyZXR3ZWV0X3NjcmVlbl9uYW1lDQpub2RlcyA8LSBjKHdob1R3ZWV0ZWQsIG9yaWdpbmFsU291cmNlKQ0KDQpub2RlcyA8LSBhcy5kYXRhLmZyYW1lKHVuaXF1ZShub2RlcykpDQpub2RlcyA8LSBub2RlcyAlPiUgcm93aWRfdG9fY29sdW1uKCJpZCIpDQpuYW1lcyhub2RlcylbMl0gPC0gImxhYmVsIg0KDQojIEJ1aWxkIGEgbGlzdCBvZiBlZGdlcy4NCnJldHdlZXRfbmV0d29yayA8LSBkYXRhX2Zvcl9uZXR3b3JrX25vdEJsYW5rICU+JSAgDQogIGdyb3VwX2J5KHNjcmVlbl9uYW1lLCByZXR3ZWV0X3NjcmVlbl9uYW1lKSAlPiUNCiAgc3VtbWFyaXNlKHdlaWdodCA9IG4oKSkgJT4lIA0KICB1bmdyb3VwKCkNCg0KbmFtZXMocmV0d2VldF9uZXR3b3JrKVsxXSA8LSAiV2hvIHJldHdlZXRlZCINCm5hbWVzKHJldHdlZXRfbmV0d29yaylbMl0gPC0gIk9yaWdpbmFsIHNvdXJjZSINCg0KZWRnZXMgPC0gcmV0d2VldF9uZXR3b3JrICU+JSANCiAgbGVmdF9qb2luKG5vZGVzLCBieSA9IGMoIk9yaWdpbmFsIHNvdXJjZSIgPSAibGFiZWwiKSkgJT4lIA0KICByZW5hbWUoZnJvbSA9IGlkKQ0KDQplZGdlcyA8LSBlZGdlcyAlPiUgDQogIGxlZnRfam9pbihub2RlcywgYnkgPSBjKCJXaG8gcmV0d2VldGVkIiA9ICJsYWJlbCIpKSAlPiUgDQogIHJlbmFtZSh0byA9IGlkKQ0KDQojIENyZWF0ZSB0aGUgbmV0d29yay4NCm5vZGVzX2QzIDwtIG11dGF0ZShub2RlcywgaWQgPSBpZCAtIDEpDQplZGdlc19kMyA8LSBtdXRhdGUoZWRnZXMsIGZyb20gPSBmcm9tIC0gMSwgdG8gPSB0byAtIDEpDQpub2Rlc19kMyA8LSBhcy5kYXRhLmZyYW1lKG5vZGVzX2QzKSAjIFRoaXMgaXMgbmVlZGVkIHRvIGF2b2lkIHRoZSB3YXJuaW5nICJMaW5rcyBpcyBhIHRibF9kZi4gQ29udmVydGluZyB0byBhIHBsYWluIGRhdGEgZnJhbWUuIg0KZWRnZXNfZDMgPC0gYXMuZGF0YS5mcmFtZShlZGdlc19kMykgDQoNCmZvcmNlTmV0d29yayhMaW5rcyA9IGVkZ2VzX2QzLCBOb2RlcyA9IG5vZGVzX2QzLCBTb3VyY2UgPSAiZnJvbSIsIFRhcmdldCA9ICJ0byIsIA0KICAgICAgICAgICAgIE5vZGVJRCA9ICJsYWJlbCIsIEdyb3VwID0gImlkIiwgVmFsdWUgPSAid2VpZ2h0IiwgDQogICAgICAgICAgICAgb3BhY2l0eSA9IDEsIGZvbnRTaXplID0gMTYsIHpvb20gPSBUUlVFLCBhcnJvd3M9VFJVRSklPiUgDQogIGh0bWx3aWRnZXRzOjpwcmVwZW5kQ29udGVudChodG1sdG9vbHM6OnRhZ3MkaDMoIkZpbHRlcmVkIHJldHdlZXQgbmV0d29yayIpKSANCmBgYA0K