My daughter has pointed out to me that I spend too much time on Twitter and to emphasize the point she bought me a Twitter addict mug. Rather than argue that she is unfairly characterizing the way I keep up with developments in the world of science and medicine, I decided that the best defense would be to turn to analyzing tweets and make my Twitter habit a programming project. As my timeline was filled up with tweets about COVID, I’ve decided to focus on tweets about the disease and virus.

I first had to find the tweets to analyse. I used two data sources, one for 2020 and the “ongoing” data set that continues to grow incrementally starting in mid December through a script that is scheduled to run weekly. For a first pass, I decided to explore how often the topics that I recalled from my own Twitter “explorations” within the tweets about COVID-19 occurred. For example, education (e.g. school closings, remote learning), vaccination, medical therapy (e.g. medications thought to work for COVID-19 treatment), and children (from neonates to teenagers)? What about masks? Also, how much did politics feature in the COVID-19 tweets? For each of those topics I crafted a simple filter for the context of each tweet (see the filters here). I also identified two groups of tweeters, those working for news organizations and those identifying as doctors or healthcare organizations (see Tweeter category definitons). Both the topics and the user groups were defined by iteration through different filters and then inspecting the tweets selected. This process has none of the rigor and validation of other efforts (including mine in applying natural language processing to electronic health records). That is, this project is really for my own entertainment and in the COVID-19-shrunken social sphere I’ve inhabited over the past year, the programming is a nerdy balm. I welcome suggestions, especially corrections (including typos), and comments. Also, this is just a first pass to familiarize myself with these data sets.

So let’s start with the big picture. What was the frequency of the topics mentioned within corpus of tweets pertaining to COVID-19 sampled across 2020?

The figure above shows the frequency of tweets across all tweeters in 2020 (corresponding figures for news organizations and medical organizations/doctors follow below). The legend in the figure identifies the 6 topics corresponding to the defined textual patterns (see Topic Filters). The Y axis is logarithmic so that tweet topics appearing towards the top of the graph are at least 100 times more frequent than those towards the bottom. It’s clear that these 6 themes of tweets still correspond to the minority of COVID-19 tweets as the large majorty of the topics are much less than 10% of all tweets that day. Tweets about the President and elections (recall all of the tweets analyzed here mention COVID-19 or the SARS-CoV2 virus) were consistently a higher fraction of tweets for each day than the other 5 topics.

Vaccines were a hot topic in February and March but dropped down by a factor of ten only to rise dramatically starting in October. Tweets about education, including remote schooling, and school closings were consistently higher than those about vaccines with peaks in March and August/September. Tweets about masks started lower but rose to compete with Pres./election by October. Tweets about pediatrics or children were about as frequent as those about vaccines.

Medical therapy tweets over a broad of therapies (from HCQ to Remesvedir to dexamethasone) were one to two orders of magntidue lower in frequency than other tweets for most of the year although there were some large spikes in March, May and June.?html_notebook_output.

In medical twitter (as defined here) education vied with masks in dominating the othervtopics except for immunization/vaccines at the beginning and end of the year. Tweets about the president (Trump or Biden) and elections (see Topic filters) within COVID-19 tweets are as frequent as the more popular tweet topics but not dominant as they are for the entire group of tweeters. Unlike the news tweeters (see below) and the overall group, medical therapies are not consistently the lowest frequency tweet. Interestingly, these 6 topics were an increasing fraction of daily tweets at the end of the year as evidenced by the overall rising trend of plotted points from the left to the right side of the plot.

For news-organization-associated tweeters, COVID-19 tweets were dominated by the president/elections topic (see filters) followed by education and then masks. Vaccines and medical therapy were less frequent than for the medical tweeters group except towards the end of the year.

Whereas the plots above capture some of the dynamics of tweet frequencies across the year, the diagram above summarizes these across the entire interval. Each bar represents the fraction of tweets with that topic and a particular group of users for the entire interval. Group comparisons are shown by adjacent bars. For example there are fewer tweets on average about children (red bars) by news-organizations-associated tweeters vs non-news-organization tweeters and more about children by medical tweeters than non-medical tweeters. Medical therapies were tweeted about far less often, even by the medical tweeters, although they did tweet more about medical therapy than the other groups. The error bars on each colored column represent a standard error.Tech note: Because the sampling strategy of the Twitter API accessed via rTweet is opaque, I’ve had to normalize per day (for the total number of tweets returned that day) because of variations in the sampling per day. That makes the standard error not a particularly robust measure for statistical comparison.

So much for the big picture. Let’s zoom in to the end of 2020 and the beginning of 2021 using the “ongoing” data set.

Unlike most of 2020, in these last few months of COVID-19 tweets, mentions of vaccines were more frequent than President/elections mentions. Also, although it might be too short an interval, there is little evidence of the steady rise of these 6 topics that characterized the bulk of 2020.

For this last interval starting in 2020-12-13 14:10:00 and ending 2021-01-22 05:00:01 there are 1502667 tweets in the “ongoing” database. For convenience (mine, so I don’t have to wait as long), so we are only sampling 1/10of the total.

Vaccine mentions in COVID-19 tweets are much more frequent among medical tweeters than the other 5 topic. Medical therapy appears to be a less frequent topic even among medical tweeters.

News organizations are much more like the vast majority of tweeters than medical tweeters with regard to the frequency of tweets about children and masks

Unlike for the overall year (i.e. just 2020), the news organizations (and those tweeting individually from news organizations) appear very similar to the medical professional tweeters perhaps with comparatively less focus on children.

What is immediately striking is the difference between this bar chart and the one from the prior year as illustrated below (where the two bar charts are shown side by side). Vaccines now dominate COVID-19 tweets whereas the President/Election topic is a distant second. Education features less prominently and medical therapy has decreased to well under 1%.

Data Sources and limitations

I used two data sources. For the full 2020 year view, I reached out to my friend and colleague, John Brownstein (a pioneer in digital epidemiology) and Jared Hawkins and asked them for all tweets that mention COVID-19 or SARS-CoV-2. The file they sent me was not all such tweets but regular sampling of such tweets totallng tweets. Also, around the beginning of December, I started running a cron job on my laptop every three days to get the last week of tweets (to ensure good overlap between each session) that included mention of covid19, I refer to the first data set as the “overall” data set and the second as the “ongoing” data set.

System Configuration

Configuration used to run this notebook: R version 4.0.2 (2020-06-22) included packages:kableExtra, gridExtra, broom, scales, forcats, stringr, dplyr, purrr, readr, tidyr, tibble, ggplot2, tidyverse, rtweet

Search strings

I did not use any NLP techniques but on simple regular expression patterns to identify strings related to the topic. I experimented with different regular expressions until the tweets matched seemd to correspond to the intended topic. I document those patterns below aligned with the Topic labels I used in the above graphs. By the way, if you want to read some of our publications that use more capable techniques for identifying and retrieving instances relevant to a topic, see here.

Filters for Topics and Tweeter Groups

Regular expression strings used for each topic
Topic Regular Expression
Vaccine (V|v)accin|Pfizer-BioNTech|(M|m)oderna|Novavax|Sinovax|(I|i)mmuniz
Education (E|e)ducat|(.*(S|s)chool|(C|c)ollege|(U|u)niversity.*clos|remot|Zoom.*)|(.*clos|remot|Zoom.*(S|s)chool|(C|c)ollege|(U|u)niversity.*)|(.*student|learning|class.*virtual|remote.*)|(.*virtual|remote.*student|learning|class.*)
Medical Therapy (T|t)herap(y|eu)|(R|r)emdesivir|VEKLURY|(A|a)zithromycin|Z-pac|(Z|z)ithromax|Zmax|(C|c)onvalescent (plasma|serum)|hyperimmune (plasma|serum)|(D|d)examethasone|(D|d)ecadron|(D|d)exasone|(S|s)olurex|(B|b)aycadron|(I|i)ntensol
Pres./election (T|t)rump|(P|p)resident|(B|b)iden|election|polls|ballot|vote
Children (C|c)hild|(P|p)ediat|neonat|kids|toddle
Mask (M|m)ask|PPE|N95

Tweeter Categories

Here are the regular expressions used to define the groups of Tweeters that we wish to study more closely.

Regular expression strings used for each group/nMissing nonMD medical personnel
Group Regular Expression
Medical personnel MD|M\.D\.|(D|d)octor|internist|surgeon|physician|Dr\.|Dr\ |Dra(\ |\.) , (P|p)ediatric|(I|i)nternist|(S|s)urgeon|(P|p)hysician|(P|p)sychia|(D|d)octor|(M|m)edical.*(S|s)pecialist
News reporters/organizations (N|n)(ews|EWS)|\W*K[:upper:]+.*|The|\W*W[:upper:]+.*|.*CBS.*|.*F(OX|ox).*|.*CNN.*|.*ABC.*|.*NBC.*|Herald|Tribune|TV|(N|n)oticias|(N|n)oticiero[s]*|Post|Times|CBC|.+S(ol|OL).*|.+Sun.*|Magazine|.+(M|m)ag.*|24h|.*/d/d\./d.*|Telemundo|World|P(olitico|OLITICO)|Wire|(P|p)rensa|Globe|MSN|P(olitica|OLITICA)|Hill|Canal|Media|BNN|Bloomberg|Journal|Intelligencer|Ledger|Clarion|Register|Press|Chronicle|Telegram|Pulse|Pulso|Informativo|Enquirer|Six|Page|Financiero|Financial|Jornada|.*\.com|visión|Daily|Diario|Político|Yahoo|Google|Bing|Microsoft|.*Review.*|.*Examiner.*|Star|CSPAN|InStyle

Feedback

Comments and particularly suggested improvements are welcome.

LS0tCnRpdGxlOiAiRXhwbG9yYXRpb24gb2YgVHdlZXRzIGFib3V0IENPVklEOiBQYXJ0IEkiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KCmBgYHtyIGluY2x1ZGUgPSBGQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG89RkFMU0UpCmBgYApNeSBkYXVnaHRlciBoYXMgcG9pbnRlZCBvdXQgdG8gbWUgdGhhdCBJIHNwZW5kIHRvbyBtdWNoIHRpbWUgb24gVHdpdHRlciBhbmQgdG8gZW1waGFzaXplIHRoZSBwb2ludCBzaGUgYm91Z2h0IG1lIGEgVHdpdHRlciBhZGRpY3QgbXVnLiBSYXRoZXIgdGhhbiBhcmd1ZSB0aGF0IHNoZSBpcyB1bmZhaXJseSBjaGFyYWN0ZXJpemluZyB0aGUgd2F5IEkga2VlcCB1cCB3aXRoIGRldmVsb3BtZW50cyBpbiB0aGUgd29ybGQgb2Ygc2NpZW5jZSBhbmQgbWVkaWNpbmUsIEkgZGVjaWRlZCB0aGF0IHRoZSBiZXN0IGRlZmVuc2Ugd291bGQgYmUgdG8gdHVybiB0byBhbmFseXppbmcgdHdlZXRzIGFuZCBtYWtlIG15IFR3aXR0ZXIgaGFiaXQgYSBwcm9ncmFtbWluZyBwcm9qZWN0LiBBcyBteSB0aW1lbGluZSB3YXMgZmlsbGVkIHVwIHdpdGggdHdlZXRzIGFib3V0IENPVklELCBJJ3ZlIGRlY2lkZWQgdG8gZm9jdXMgb24gdHdlZXRzIGFib3V0IHRoZSBkaXNlYXNlIGFuZCB2aXJ1cy4gCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLGluY2x1ZGUgPSBGQUxTRX0KbGlicmFyeShydHdlZXQpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShicm9vbSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShrYWJsZUV4dHJhKQoKc291cmNlKCJ0d2VldEFuYWx5c2lzLlIiKQpgYGAKCmBgYHtyIFNldCBnbG9iYWxzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFfQppIDwtc2Vzc2lvbkluZm8oKQpjb3VudHMgPC0gYygpCnN0YXJ0cyA8LSBjKCkKZW5kcyA8LSBjKCkKdG9waWNOdW0gPC0gbGVuZ3RoKGNvbExhYmVsczYpCmBgYAoKYGBge3IgTG9hZCBIYXdraW5zIEZpbGVzLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpsb2FkKGZpbGU9Imh1QWNjdW0iKQpsb2FkKGZpbGU9Imh0QWNjdW0iKQphY2N1bUhhd2tpbnMyMDIwIDwtICBpbnRlcnZhbERlc2NyaXB0aW9uKGh0QWNjdW0saHVBY2N1bSkKCmBgYApgYGB7ciBDbGVhbiB1cCxlY2hvPUZBTFNFfQoKcm0oaHVBY2N1bSkKcm0oaHRBY2N1bSkKCgpgYGAKCmBgYHtyIFByb2Nlc3MgdGhlIGludGVydmFsLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KY291bnRzJGhhd2tpbnNUd2VldHMgPC0gZGltKGFjY3VtSGF3a2luczIwMjApWzFdCiMjIyBIZXJlIGlzIHdoZXJlIEkgc3BlY2lmeSB0aGUgZmlsdGVycwpoYXdraW5zMjAyMCA8LSBwcm9jZXNzQW5kUGxvdEludGVydmFsKGFjY3VtSGF3a2luczIwMjAscmVnZXhWZWN0b3IgPSBzdHJpbmdWZWM2LGNvbExhYmVscyA9IGNvbExhYmVsczYsIG5vcm1hbGl6aW5nID0gVFJVRSx0aXRsZT0iMjAyMCIpCnJtKGFjY3VtSGF3a2luczIwMjApICAKCmBgYApJIGZpcnN0IGhhZCB0byBmaW5kIHRoZSB0d2VldHMgdG8gYW5hbHlzZS4gSSB1c2VkIHR3byBbZGF0YSBzb3VyY2VzXSgjc291cmNlcyksIG9uZSBmb3IgMjAyMCBhbmQgdGhlICJvbmdvaW5nIiBkYXRhIHNldCB0aGF0IGNvbnRpbnVlcyB0byBncm93IGluY3JlbWVudGFsbHkgc3RhcnRpbmcgaW4gbWlkIERlY2VtYmVyIHRocm91Z2ggYSBzY3JpcHQgdGhhdCBpcyBzY2hlZHVsZWQgdG8gcnVuIHdlZWtseS4gRm9yIGEgZmlyc3QgcGFzcywgSSBkZWNpZGVkIHRvIGV4cGxvcmUgaG93IG9mdGVuIHRoZSAgdG9waWNzIHRoYXQgSSByZWNhbGxlZCBmcm9tIG15IG93biBUd2l0dGVyICJleHBsb3JhdGlvbnMiICB3aXRoaW4gdGhlIHR3ZWV0cyBhYm91dCBDT1ZJRC0xOSBvY2N1cnJlZC4gIEZvciBleGFtcGxlLCAgZWR1Y2F0aW9uIChlLmcuIHNjaG9vbCBjbG9zaW5ncywgcmVtb3RlIGxlYXJuaW5nKSwgdmFjY2luYXRpb24sIG1lZGljYWwgdGhlcmFweSAoZS5nLiBtZWRpY2F0aW9ucyB0aG91Z2h0IHRvIHdvcmsgZm9yIENPVklELTE5IHRyZWF0bWVudCksIGFuZCBjaGlsZHJlbiAoZnJvbSBuZW9uYXRlcyB0byB0ZWVuYWdlcnMpPyBXaGF0IGFib3V0IG1hc2tzPyBBbHNvLCBob3cgbXVjaCBkaWQgcG9saXRpY3MgZmVhdHVyZSBpbiB0aGUgQ09WSUQtMTkgdHdlZXRzPyBGb3IgZWFjaCBvZiB0aG9zZSB0b3BpY3MgSSBjcmFmdGVkIGEgc2ltcGxlIGZpbHRlciBmb3IgdGhlIGNvbnRleHQgb2YgZWFjaCB0d2VldCAoc2VlICBbdGhlIGZpbHRlcnMgaGVyZV0oI3RvcGljZmlsdGVycykpLiBJIGFsc28gaWRlbnRpZmllZCB0d28gZ3JvdXBzIG9mIHR3ZWV0ZXJzLCB0aG9zZSB3b3JraW5nIGZvciBuZXdzIG9yZ2FuaXphdGlvbnMgYW5kIHRob3NlIGlkZW50aWZ5aW5nIGFzIGRvY3RvcnMgb3IgaGVhbHRoY2FyZSBvcmdhbml6YXRpb25zIChzZWUgW1R3ZWV0ZXIgY2F0ZWdvcnkgZGVmaW5pdG9uc10oI1R3ZWV0ZXJDYXRlZ29yaWVzKSkuIEJvdGggdGhlIHRvcGljcyBhbmQgdGhlIHVzZXIgZ3JvdXBzIHdlcmUgZGVmaW5lZCBieSBpdGVyYXRpb24gdGhyb3VnaCBkaWZmZXJlbnQgZmlsdGVycyBhbmQgdGhlbiBpbnNwZWN0aW5nIHRoZSB0d2VldHMgc2VsZWN0ZWQuIFRoaXMgcHJvY2VzcyBoYXMgbm9uZSBvZiB0aGUgcmlnb3IgYW5kIHZhbGlkYXRpb24gb2Ygb3RoZXIgZWZmb3J0cyAoaW5jbHVkaW5nIG1pbmUgaW4gYXBwbHlpbmcgW25hdHVyYWwgbGFuZ3VhZ2UgcHJvY2Vzc2luZyB0byBlbGVjdHJvbmljIGhlYWx0aCByZWNvcmRzXShodHRwczovL3d3dy5uYXR1cmUuY29tL2FydGljbGVzL25yZzI5OTkpKS4gVGhhdCBpcywgdGhpcyBwcm9qZWN0IGlzIHJlYWxseSBmb3IgbXkgb3duIGVudGVydGFpbm1lbnQgYW5kIGluIHRoZSBDT1ZJRC0xOS1zaHJ1bmtlbiBzb2NpYWwgc3BoZXJlIEkndmUgaW5oYWJpdGVkIG92ZXIgdGhlIHBhc3QgeWVhciwgdGhlIHByb2dyYW1taW5nIGlzIGEgbmVyZHkgYmFsbS4gSSB3ZWxjb21lIHN1Z2dlc3Rpb25zLCBlc3BlY2lhbGx5IGNvcnJlY3Rpb25zIChpbmNsdWRpbmcgdHlwb3MpLCBhbmQgY29tbWVudHMuIEFsc28sIHRoaXMgaXMganVzdCBhIGZpcnN0IHBhc3MgdG8gZmFtaWxpYXJpemUgbXlzZWxmIHdpdGggdGhlc2UgZGF0YSBzZXRzLiAKYGBge3IgR0MgYW5kIGV4dHJhY3QgcGxvdHMsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFLGluY2x1ZGU9RkFMU0V9CiMgc3QocHJvZmlsZT1wcm9maWxlMSRoaXN0LG5vTmV3cz1ub05ld3MxJGhpc3QsbmV3cz1uZXdzMSRoaXN0LG1lZD1tZWQxJGhpc3Qsbm9NZWQ9bm9NZWQxJGhpc3QsIHByb2ZpbGVQPXByb2ZpbGUxJHBsb3Qsbm9OZXdzUD1ub05ld3MxJHBsb3QsbmV3c1A9bmV3czEkcGxvdCxtZWRQPW1lZDEkcGxvdCxub01lZFA9bm9NZWQxJHBsb3QpCm92ZXJhbGxQbG90IDwtIGhhd2tpbnMyMDIwJHByb2ZpbGVQCm1lZFBsb3QgPC0gaGF3a2luczIwMjAkbWVkUApuZXdzUGxvdCA8LSBoYXdraW5zMjAyMCRuZXdzUAoKYGBgClNvIGxldCdzIHN0YXJ0IHdpdGggdGhlIGJpZyBwaWN0dXJlLiBXaGF0IHdhcyB0aGUgZnJlcXVlbmN5IG9mIHRoZSB0b3BpY3MgbWVudGlvbmVkIHdpdGhpbiBjb3JwdXMgb2YgIHR3ZWV0cyBwZXJ0YWluaW5nIHRvIENPVklELTE5IHNhbXBsZWQgYWNyb3NzIDIwMjA/PGEgaWQ9Im92ZXJhbGxmaWcxIj48L2E+CmBgYHtyICAsbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFfQoKICBnZ3Bsb3Qob3ZlcmFsbFBsb3QkZGF0YSwgYWVzKHg9dGltZSx5PW4sY29sb3I9VHdlZXQpKSArCiAgICBnZW9tX3BvaW50KGFlcyhzaGFwZT1Ud2VldCkpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHRpdGxlPScyMDIwIE92ZXJhbGwgQ09WSUQtMTkgVHdlZXRzIEZyZXF1ZW5jeSBmb3IgU2VsZWN0ZWQgVG9waWNzJykgKwogICAgeGxhYigiRGF0ZSIpICsKICAgIHlsYWIoIkZyYWN0aW9uIG9mIFR3ZWV0cyB0aGF0IGRheSAobG9nMTApIikgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSkKCmBgYApUaGUgZmlndXJlIGFib3ZlIHNob3dzIHRoZSBmcmVxdWVuY3kgb2YgdHdlZXRzIGFjcm9zcyBhbGwgdHdlZXRlcnMgaW4gMjAyMCAoY29ycmVzcG9uZGluZyBmaWd1cmVzIGZvciBuZXdzIG9yZ2FuaXphdGlvbnMgYW5kIG1lZGljYWwgb3JnYW5pemF0aW9ucy9kb2N0b3JzIGZvbGxvdyBiZWxvdykuICBUaGUgbGVnZW5kIGluIHRoZSBmaWd1cmUgIGlkZW50aWZpZXMgdGhlIGByIHRvcGljTnVtYCB0b3BpY3MgY29ycmVzcG9uZGluZyB0byB0aGUgZGVmaW5lZCB0ZXh0dWFsIHBhdHRlcm5zIChzZWUgW1RvcGljIEZpbHRlcnNdKCN0b3BpY2ZpbHRlcnMpKS4gVGhlIFkgYXhpcyBpcyBsb2dhcml0aG1pYyBzbyB0aGF0IHR3ZWV0IHRvcGljcyBhcHBlYXJpbmcgdG93YXJkcyB0aGUgdG9wIG9mIHRoZSBncmFwaCBhcmUgYXQgbGVhc3QgMTAwIHRpbWVzIG1vcmUgZnJlcXVlbnQgdGhhbiB0aG9zZSB0b3dhcmRzIHRoZSBib3R0b20uIEl0J3MgY2xlYXIgdGhhdCB0aGVzZSBgciB0b3BpY051bWAgdGhlbWVzIG9mIHR3ZWV0cyBzdGlsbCBjb3JyZXNwb25kIHRvIHRoZSBtaW5vcml0eSBvZiBDT1ZJRC0xOSB0d2VldHMgYXMgdGhlIGxhcmdlIG1ham9ydHkgb2YgdGhlIHRvcGljcyBhcmUgbXVjaCBsZXNzIHRoYW4gMTAlIG9mIGFsbCB0d2VldHMgdGhhdCBkYXkuIFR3ZWV0cyBhYm91dCB0aGUgUHJlc2lkZW50IGFuZCBlbGVjdGlvbnMgKHJlY2FsbCBhbGwgb2YgdGhlIHR3ZWV0cyBhbmFseXplZCBoZXJlIG1lbnRpb24gQ09WSUQtMTkgb3IgdGhlIFNBUlMtQ29WMiB2aXJ1cykgd2VyZSBjb25zaXN0ZW50bHkgYSBoaWdoZXIgZnJhY3Rpb24gb2YgdHdlZXRzIGZvciBlYWNoIGRheSB0aGFuIHRoZSBvdGhlciBgciB0b3BpY051bSAtMWAgdG9waWNzLiAKClZhY2NpbmVzIHdlcmUgYSBob3QgdG9waWMgaW4gRmVicnVhcnkgYW5kIE1hcmNoIGJ1dCBkcm9wcGVkIGRvd24gYnkgYSBmYWN0b3Igb2YgdGVuIG9ubHkgdG8gcmlzZSBkcmFtYXRpY2FsbHkgc3RhcnRpbmcgaW4gT2N0b2Jlci4gVHdlZXRzIGFib3V0IGVkdWNhdGlvbiwgaW5jbHVkaW5nIHJlbW90ZSBzY2hvb2xpbmcsIGFuZCBzY2hvb2wgY2xvc2luZ3Mgd2VyZSBjb25zaXN0ZW50bHkgaGlnaGVyIHRoYW4gdGhvc2UgYWJvdXQgdmFjY2luZXMgd2l0aCBwZWFrcyBpbiBNYXJjaCBhbmQgQXVndXN0L1NlcHRlbWJlci4gVHdlZXRzIGFib3V0IG1hc2tzIHN0YXJ0ZWQgbG93ZXIgYnV0IHJvc2UgdG8gY29tcGV0ZSB3aXRoIFByZXMuL2VsZWN0aW9uIGJ5IE9jdG9iZXIuIFR3ZWV0cyBhYm91dCBwZWRpYXRyaWNzIG9yIGNoaWxkcmVuIHdlcmUgYWJvdXQgYXMgZnJlcXVlbnQgYXMgdGhvc2UgYWJvdXQgdmFjY2luZXMuIAoKTWVkaWNhbCB0aGVyYXB5IHR3ZWV0cyBvdmVyIGEgYnJvYWQgb2YgdGhlcmFwaWVzIChmcm9tIEhDUSB0byBSZW1lc3ZlZGlyIHRvIGRleGFtZXRoYXNvbmUpIHdlcmUgb25lIHRvIHR3byBvcmRlcnMgb2YgbWFnbnRpZHVlIGxvd2VyIGluIGZyZXF1ZW5jeSB0aGFuIG90aGVyIHR3ZWV0cyBmb3IgbW9zdCBvZiB0aGUgeWVhciBhbHRob3VnaCB0aGVyZSB3ZXJlIHNvbWUgbGFyZ2Ugc3Bpa2VzIGluIE1hcmNoLCBNYXkgYW5kIEp1bmUuP2h0bWxfbm90ZWJvb2tfb3V0cHV0LgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsZmlnLndpZHRoPTYuNX0gCgogZ2dwbG90KG1lZFBsb3QkZGF0YSwgYWVzKHg9dGltZSx5PW4sY29sb3I9VHdlZXQpKSArCiAgICBnZW9tX3BvaW50KGFlcyhzaGFwZT1Ud2VldCkpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHRpdGxlPScyMDIwIE1lZGljYWwgVHdlZXRlcnMgQ09WSUQtMTkgVHdlZXRzIGZvciA2IFRvcGljcycpICsKICAgIHhsYWIoIkRhdGUiKSArCiAgICB5bGFiKCJGcmFjdGlvbiBvZiBUd2VldHMgdGhhdCBkYXkgKGxvZzEwKSIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkpCgpgYGAKSW4gbWVkaWNhbCB0d2l0dGVyIChhcyBkZWZpbmVkIFtoZXJlXSgjVHdlZXRlckNhdGVnb3JpZXMpKSBlZHVjYXRpb24gdmllZCB3aXRoIG1hc2tzIGluIGRvbWluYXRpbmcgdGhlIG90aGVydnRvcGljcyBleGNlcHQgZm9yIGltbXVuaXphdGlvbi92YWNjaW5lcyBhdCB0aGUgYmVnaW5uaW5nIGFuZCBlbmQgb2YgdGhlIHllYXIuIFR3ZWV0cyBhYm91dCB0aGUgcHJlc2lkZW50IChUcnVtcCBvciBCaWRlbikgYW5kIGVsZWN0aW9ucyAoc2VlIFtUb3BpYyBmaWx0ZXJzXXsjdG9waWNmaWx0ZXJzfSkgd2l0aGluIENPVklELTE5IHR3ZWV0cyBhcmUgYXMgZnJlcXVlbnQgYXMgdGhlIG1vcmUgcG9wdWxhciB0d2VldCB0b3BpY3MgYnV0IG5vdCBkb21pbmFudCBhcyB0aGV5IGFyZSBmb3IgdGhlIFtlbnRpcmUgZ3JvdXAgb2YgdHdlZXRlcnNdKCNvdmVyYWxsZmlnMSkuIFVubGlrZSB0aGUgbmV3cyB0d2VldGVycyAoc2VlIGJlbG93KSBhbmQgdGhlIG92ZXJhbGwgZ3JvdXAsIG1lZGljYWwgdGhlcmFwaWVzIGFyZSBub3QgY29uc2lzdGVudGx5IHRoZSBsb3dlc3QgZnJlcXVlbmN5IHR3ZWV0LiBJbnRlcmVzdGluZ2x5LCB0aGVzZSBgciB0b3BpY051bWAgdG9waWNzIHdlcmUgYW4gaW5jcmVhc2luZyBmcmFjdGlvbiBvZiBkYWlseSB0d2VldHMgYXQgdGhlIGVuZCBvZiB0aGUgeWVhciBhcyBldmlkZW5jZWQgYnkgdGhlIG92ZXJhbGwgcmlzaW5nIHRyZW5kIG9mIHBsb3R0ZWQgcG9pbnRzIGZyb20gdGhlIGxlZnQgdG8gdGhlIHJpZ2h0IHNpZGUgb2YgdGhlIHBsb3QuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KIGdncGxvdChuZXdzUGxvdCRkYXRhLCBhZXMoeD10aW1lLHk9bixjb2xvcj1Ud2VldCkpICsKICAgIGdlb21fcG9pbnQoYWVzKHNoYXBlPVR3ZWV0KSkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGxhYnModGl0bGU9JzIwMjAgTmV3cyBmb2xrIENPVklELTE5IFR3ZWV0cyBmb3IgNiBUb3BpY3MnKSArCiAgICB4bGFiKCJEYXRlIikgKwogICAgeWxhYigiRnJhY3Rpb24gb2YgVHdlZXRzIHRoYXQgZGF5IChsb2cxMCkiKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTQpKQpgYGAKRm9yIG5ld3Mtb3JnYW5pemF0aW9uLWFzc29jaWF0ZWQgdHdlZXRlcnMsIENPVklELTE5IHR3ZWV0cyB3ZXJlIGRvbWluYXRlZCBieSB0aGUgcHJlc2lkZW50L2VsZWN0aW9ucyB0b3BpYyAoc2VlIFtmaWx0ZXJzXSgjdG9waWNmaWx0ZXJzKSkgZm9sbG93ZWQgYnkgZWR1Y2F0aW9uIGFuZCB0aGVuIG1hc2tzLiBWYWNjaW5lcyBhbmQgbWVkaWNhbCB0aGVyYXB5IHdlcmUgbGVzcyBmcmVxdWVudCB0aGFuIGZvciB0aGUgbWVkaWNhbCB0d2VldGVycyBncm91cCBleGNlcHQgdG93YXJkcyB0aGUgZW5kIG9mIHRoZSB5ZWFyLgpgYGB7ciAsZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSxpbmNsdWRlPUZBTFNFfQojIyBTdGF0aXN0aWNhbCB0ZXN0Cgpsc3VtbWFyeSA8LSBzaW5nbGVJbnRTdGF0cyhoYXdraW5zMjAyMCkKYGBgCgpgYGB7ciBTdGF0aXN0aWNhbCB0ZXN0MSxlY2hvPUZBTFNFfQpzaW5nbGVJbnRCYXJQbG90MSA8LSBiYXJwbG90SW50ZXJ2YWxDb21wYXJlKGxzdW1tYXJ5KSArCiAgIGdndGl0bGUoIkNvbXBhcmlzb24gb2YgdHdlZXRlciBncm91cHMsIFxuRmVicnVhcnkgMjAyMCB0aHJvdWdoIGJlZ2lubmluZyBEZWNlbWJlciIpCnByaW50KHNpbmdsZUludEJhclBsb3QxKQpgYGAKV2hlcmVhcyB0aGUgcGxvdHMgYWJvdmUgY2FwdHVyZSBzb21lIG9mIHRoZSBkeW5hbWljcyBvZiB0d2VldCBmcmVxdWVuY2llcyBhY3Jvc3MgdGhlIHllYXIsIHRoZSBkaWFncmFtIGFib3ZlIHN1bW1hcml6ZXMgdGhlc2UgYWNyb3NzIHRoZSBlbnRpcmUgaW50ZXJ2YWwuIEVhY2ggYmFyIHJlcHJlc2VudHMgdGhlIGZyYWN0aW9uIG9mIHR3ZWV0cyB3aXRoIHRoYXQgdG9waWMgYW5kIGEgcGFydGljdWxhciBncm91cCBvZiB1c2VycyBmb3IgdGhlICplbnRpcmUqIGludGVydmFsLiBHcm91cCBjb21wYXJpc29ucyBhcmUgc2hvd24gYnkgYWRqYWNlbnQgYmFycy4gRm9yIGV4YW1wbGUgdGhlcmUgYXJlIGZld2VyIHR3ZWV0cyBvbiBhdmVyYWdlIGFib3V0IGNoaWxkcmVuIChyZWQgYmFycykgYnkgbmV3cy1vcmdhbml6YXRpb25zLWFzc29jaWF0ZWQgdHdlZXRlcnMgdnMgbm9uLW5ld3Mtb3JnYW5pemF0aW9uIHR3ZWV0ZXJzIGFuZCBtb3JlIGFib3V0IGNoaWxkcmVuIGJ5IG1lZGljYWwgdHdlZXRlcnMgdGhhbiBub24tbWVkaWNhbCB0d2VldGVycy4gTWVkaWNhbCB0aGVyYXBpZXMgd2VyZSB0d2VldGVkIGFib3V0IGZhciBsZXNzIG9mdGVuLCBldmVuIGJ5IHRoZSBtZWRpY2FsIHR3ZWV0ZXJzLCBhbHRob3VnaCB0aGV5IGRpZCB0d2VldCBtb3JlIGFib3V0IG1lZGljYWwgdGhlcmFweSB0aGFuIHRoZSBvdGhlciBncm91cHMuIFRoZSBlcnJvciBiYXJzIG9uIGVhY2ggY29sb3JlZCBjb2x1bW4gcmVwcmVzZW50IGEgW3N0YW5kYXJkIGVycm9yXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TdGFuZGFyZF9lcnJvcikuVGVjaCBub3RlOiBCZWNhdXNlIHRoZSBzYW1wbGluZyBzdHJhdGVneSBvZiB0aGUgVHdpdHRlciBBUEkgYWNjZXNzZWQgdmlhIFtyVHdlZXRdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9ydHdlZXQvcnR3ZWV0LnBkZikgaXMgb3BhcXVlLCBJJ3ZlIGhhZCB0byBub3JtYWxpemUgcGVyIGRheSAoZm9yIHRoZSB0b3RhbCBudW1iZXIgb2YgdHdlZXRzIHJldHVybmVkIHRoYXQgZGF5KSBiZWNhdXNlIG9mIHZhcmlhdGlvbnMgaW4gdGhlIHNhbXBsaW5nIHBlciBkYXkuIFRoYXQgbWFrZXMgdGhlIHN0YW5kYXJkIGVycm9yIG5vdCBhIHBhcnRpY3VsYXJseSAgcm9idXN0IG1lYXN1cmUgZm9yIHN0YXRpc3RpY2FsIGNvbXBhcmlzb24uCgpgYGB7ciwgZWNobz1GQUxTRX0Kc2hyaW5rRmFjdG9yIDwtIDEwCmBgYAoKU28gbXVjaCBmb3IgdGhlIGJpZyBwaWN0dXJlLiBMZXQncyB6b29tIGluIHRvIHRoZSBlbmQgb2YgMjAyMCBhbmQgdGhlIGJlZ2lubmluZyBvZiAyMDIxIHVzaW5nIHRoZSAib25nb2luZyIgZGF0YSBzZXQuCgoKYGBge3IgLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFLCBlY2hvPUZBTFNFfQojIENsZWFuIHVwCnJtKGFjY3VtSGF3a2luczIwMjApICMgUmVtb3ZlIGZvciBkZWJ1Z2dpbmcuCnJtKGhhd2tpbnMyMDIwKQpybShvdmVyYWxsUGxvdCxtZWRQbG90LG5ld3NQbG90KQpgYGAKCmBgYHtyIE1lcmdpbmcgTXVsdGlwbGUgVHdlZXQgU3RyZWFtcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRSxpbmNsdWRlPUZBTFNFfQpzZXR3ZCgnL1VzZXJzL3pha2kgMS9Ecm9wYm94L1JfQ29kZS90d2VldHMvdHdlZXRhcmNoaXZlJykKIyBmaWxlTGlzdFJUIDwtIGMoInJ0MSIsInJ0MiIsInJ0MyIsInJ0NCIpCiMgRmlyc3QgbGlzdCBpcyBkaXNjb250aW51b3VzIHdpdGggdGhlIHJlc3QKZmlsZUxpc3QxIDwtIGMoIlN1bl9EZWNfMjBfMTVfMThfNTRfMjAyMCIsIlN1bl9EZWNfMjBfMDBfMDBfMDJfMjAyMCIsIk1vbl9EZWNfMjFfMDlfMjNfNDRfMjAyMCIpCmZpbGVMaXN0MiA8LSBjKCJNb25fRGVjXzIxXzAwXzAwXzAyXzIwMjAiLCJUdWVfRGVjXzIyXzAwXzAwXzAyXzIwMjAiLCJXZWRfRGVjXzIzXzAwXzAwXzAzXzIwMjAiLAogICAgICAgICAgICAgICAiVGh1X0RlY18yNF8wMF8wMF8wM18yMDIwIiwiRnJpX0RlY18yNV8wMF8wMF8wM18yMDIwIiwiTW9uX0RlY18yOF8wMF8wMF8wMl8yMDIwIiwgCiAgICAgICAgICAgICAgICJUaHVfRGVjXzMxXzAwXzAwXzAzXzIwMjAiKQpmaWxlTGlzdDMgPC0gYygiRnJpX0phbl9fMV8wMF8wMF8wMl8yMDIxIiwiTW9uX0phbl9fNF8wMF8wMF8wMl8yMDIxIiwiVGh1X0phbl9fN18wMF8wMF8wM18yMDIxIiwiU3VuX0phbl8xMF8wMF8wMF8wMl8yMDIxIiwiV2VkX0phbl8xM18wMF8wMF8wMl8yMDIxIiwgIlR1ZV9KYW5fMTlfMDBfMDBfMDNfMjAyMSIsIkZyaV9KYW5fMjJfMDBfMDBfMDNfMjAyMSIpCgojIGYxIDwtIG1lcmdlVHdlZXRTdHJlYW1zKGZpbGVMaXN0UlQpCiMgZjEgPC0gZG93bnNhbXBsZShmMSwxMCkKZjIgPC0gbWVyZ2VUd2VldFN0cmVhbXMoZmlsZUxpc3QxKQpmMiA8LSBkb3duc2FtcGxlKGYyLDEwKQpmMyA8LSBtZXJnZVR3ZWV0U3RyZWFtcyhmaWxlTGlzdDIpCmYzIDwtIGRvd25zYW1wbGUoZjMsMTApCmY0IDwtIG1lcmdlVHdlZXRTdHJlYW1zKGZpbGVMaXN0MykKZjQgPC0gZG93bnNhbXBsZShmNCwxMCkKYGBgCgoKYGBge3IgLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFfQpvbmdvaW5nIDwtIHVuaW9uKGYyLHVuaW9uKGYzLGY0KSkKY291bnRzJG9uZ29pbmcgPC0gZGltKG9uZ29pbmcpWzFdCnN0YXJ0cyRvbmdvaW5nIDwtIG1pbihvbmdvaW5nJGNyZWF0ZWRfYXQpCmVuZHMkb25nb2luZyA8LSBtYXgob25nb2luZyRjcmVhdGVkX2F0KQpybShmMixmMyxmNCkKCgpgYGAKCgpgYGB7ciAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0V9Cm9uZ29pbmdJbnQgPC0gaW50ZXJ2YWxEZXNjcmlwdGlvbihvbmdvaW5nKQpgYGAKCgpgYGB7ciAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0V9IAoKb25nb2luZ0FuYWx5c2lzIDwtIHByb2Nlc3NBbmRQbG90SW50ZXJ2YWwob25nb2luZ0ludCxzdHJpbmdWZWM2LGNvbExhYmVsczYsdGl0bGU9Ik9uZ29pbmcgZGF0YSBzZXQiKQoKYGBgCgpgYGB7ciAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGluY2x1ZGU9RkFMU0UsIGVjaG89RkFMU0V9Cm92ZXJhbGxQbG90MiA8LSBvbmdvaW5nQW5hbHlzaXMkcHJvZmlsZVAKbWVkUGxvdDIgPC0gb25nb2luZ0FuYWx5c2lzJG1lZFAKbmV3c1Bsb3QyIDwtIG9uZ29pbmdBbmFseXNpcyRuZXdzUAoKYGBgCmBgYHtyICBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0V9CnJtKG9uZ29pbmcpCiAgZ2dwbG90KG92ZXJhbGxQbG90MiRkYXRhLCBhZXMoeD10aW1lLHk9bixjb2xvcj1Ud2VldCkpICsKICAgIGdlb21fcG9pbnQoYWVzKHNoYXBlPVR3ZWV0KSkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGxhYnModGl0bGU9IkVuZCAyMDIwIEJlZ2lubmluZyAyMDIxIE92ZXJhbGwgQ09WSUQtMTkgVHdlZXRzIGZvciA2IFRvcGljcyIpICsKICAgIHhsYWIoIkRhdGUiKSArCiAgICB5bGFiKCJGcmFjdGlvbiBvZiBUd2VldHMgdGhhdCBkYXkgKGxvZzEwKSIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkpCgpgYGAKVW5saWtlIG1vc3Qgb2YgMjAyMCwgaW4gdGhlc2UgbGFzdCBmZXcgbW9udGhzIG9mIENPVklELTE5IHR3ZWV0cywgbWVudGlvbnMgb2YgdmFjY2luZXMgd2VyZSBtb3JlIGZyZXF1ZW50IHRoYW4gUHJlc2lkZW50L2VsZWN0aW9ucyBtZW50aW9ucy4gQWxzbywgYWx0aG91Z2ggaXQgbWlnaHQgYmUgdG9vIHNob3J0IGFuIGludGVydmFsLCB0aGVyZSBpcyBsaXR0bGUgZXZpZGVuY2Ugb2YgdGhlIHN0ZWFkeSByaXNlIG9mIHRoZXNlIGByIHRvcGljTnVtYCB0b3BpY3MgdGhhdCBjaGFyYWN0ZXJpemVkIHRoZSBidWxrIG9mIDIwMjAuIAoKRm9yIHRoaXMgbGFzdCBpbnRlcnZhbCBzdGFydGluZyBpbiBgciBzdGFydHMkb25nb2luZ2AgYW5kIGVuZGluZyBgciBlbmRzJG9uZ29pbmdgIHRoZXJlIGFyZSBgciBjb3VudHMkb25nb2luZ2AgdHdlZXRzIGluIHRoZSAib25nb2luZyIgZGF0YWJhc2UuIEZvciBjb252ZW5pZW5jZSAobWluZSwgc28gSSBkb24ndCBoYXZlIHRvIHdhaXQgYXMgbG9uZyksIHNvIHdlIGFyZSBvbmx5IHNhbXBsaW5nIDEvYHIgc2hyaW5rRmFjdG9yYG9mIHRoZSB0b3RhbC4KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFfQogZ2dwbG90KG1lZFBsb3QyJGRhdGEsIGFlcyh4PXRpbWUseT1uLGNvbG9yPVR3ZWV0KSkgKwogICAgZ2VvbV9wb2ludChhZXMoc2hhcGU9VHdlZXQpKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgbGFicyh0aXRsZT0iTWVkaWNhbCBUd2VldGVycyBDT1ZJRC0xOSBUd2VldHNcbmR1cmluZyB0aGUgYG9uZ29pbmcnIGludGVydmFsIGZvciA2IFRvcGljcyIpICsKICAgIHhsYWIoIkRhdGUiKSArCiAgICB5bGFiKCJGcmFjdGlvbiBvZiBUd2VldHMgdGhhdCBkYXkgKGxvZzEwKSIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkpCmBgYApWYWNjaW5lIG1lbnRpb25zIGluIENPVklELTE5IHR3ZWV0cyBhcmUgbXVjaCBtb3JlIGZyZXF1ZW50IGFtb25nICBtZWRpY2FsIHR3ZWV0ZXJzIHRoYW4gdGhlIG90aGVyIGByIHRvcGljTnVtIC0xYCB0b3BpYy4gTWVkaWNhbCB0aGVyYXB5IGFwcGVhcnMgdG8gYmUgYSBsZXNzIGZyZXF1ZW50IHRvcGljIGV2ZW4gYW1vbmcgbWVkaWNhbCB0d2VldGVycy4KCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRX0KIGdncGxvdChuZXdzUGxvdDIkZGF0YSwgYWVzKHg9dGltZSx5PW4sY29sb3I9VHdlZXQpKSArCiAgICBnZW9tX3BvaW50KGFlcyhzaGFwZT1Ud2VldCkpICsKICAgIHNjYWxlX3lfbG9nMTAoKSArCiAgICBsYWJzKHRpdGxlPSJOZXdzIGZvbGsgQ09WSUQtMTkgVHdlZXRzIGZvciA2IFRvcGljc1xuT25nb2luZyBpbnRlcnZhbCIpICsKICAgIHhsYWIoIkRhdGUiKSArCiAgICB5bGFiKCJGcmFjdGlvbiBvZiBUd2VldHMgdGhhdCBkYXkgKGxvZzEwKSIpICsKICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkpCmBgYApOZXdzIG9yZ2FuaXphdGlvbnMgYXJlIG11Y2ggbW9yZSBsaWtlIHRoZSB2YXN0IG1ham9yaXR5IG9mIHR3ZWV0ZXJzIHRoYW4gbWVkaWNhbCB0d2VldGVycyB3aXRoIHJlZ2FyZCB0byB0aGUgZnJlcXVlbmN5IG9mIHR3ZWV0cyBhYm91dCBjaGlsZHJlbiBhbmQgbWFza3MKCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLGZpZy53aWR0aD02LGZpZy5oZWlnaHQ9NH0KbHN1bW1hcnkyIDwtIHNpbmdsZUludFN0YXRzKG9uZ29pbmdBbmFseXNpcykKc2luZ2xlSW50QmFyUGxvdDIgPC0gYmFycGxvdEludGVydmFsQ29tcGFyZShsc3VtbWFyeTIpICsKICBnZ3RpdGxlKCJDb21wYXJpc29uIG9mIHR3ZWV0ZXIgZ3JvdXBzLCBcbkRlY2VtYmVyIDIwMjAgdGhyb3VnaCBiZWdpbm5pbmcgMjAyMSIpCnNpbmdsZUludEJhclBsb3QyIApybShtZWRQbG90MixuZXdzUGxvdDIsb25nb2luZ0FuYWx5c2lzKQpgYGAKVW5saWtlIGZvciB0aGUgb3ZlcmFsbCB5ZWFyIChpLmUuIGp1c3QgMjAyMCksIHRoZSBuZXdzIG9yZ2FuaXphdGlvbnMgKGFuZCB0aG9zZSB0d2VldGluZyBpbmRpdmlkdWFsbHkgZnJvbSBuZXdzIG9yZ2FuaXphdGlvbnMpIGFwcGVhciB2ZXJ5IHNpbWlsYXIgdG8gdGhlIG1lZGljYWwgcHJvZmVzc2lvbmFsIHR3ZWV0ZXJzIHBlcmhhcHMgd2l0aCBjb21wYXJhdGl2ZWx5IGxlc3MgZm9jdXMgb24gY2hpbGRyZW4uIAoKV2hhdCBpcyBpbW1lZGlhdGVseSBzdHJpa2luZyBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoaXMgYmFyIGNoYXJ0IGFuZCB0aGUgb25lIGZyb20gdGhlIHByaW9yIHllYXIgYXMgaWxsdXN0cmF0ZWQgYmVsb3cgKHdoZXJlIHRoZSB0d28gYmFyIGNoYXJ0cyBhcmUgc2hvd24gc2lkZSBieSBzaWRlKS4gVmFjY2luZXMgbm93IGRvbWluYXRlIENPVklELTE5IHR3ZWV0cyB3aGVyZWFzIHRoZSBQcmVzaWRlbnQvRWxlY3Rpb24gdG9waWMgaXMgYSBkaXN0YW50IHNlY29uZC4gRWR1Y2F0aW9uIGZlYXR1cmVzIGxlc3MgcHJvbWluZW50bHkgYW5kIG1lZGljYWwgdGhlcmFweSBoYXMgZGVjcmVhc2VkIHRvIHdlbGwgdW5kZXIgMSUuCgpgYGB7ciBUd2luIGJhcmNoYXJ0LCBlY2hvPUZBTFNFLGZpZy53aWR0aD04LGZpZy5oZWlnaHQ9M30KZ3JpZC5hcnJhbmdlKHNpbmdsZUludEJhclBsb3QxLCBzaW5nbGVJbnRCYXJQbG90MiwgbmNvbD0yKQpgYGAKCiMjIyBEYXRhIFNvdXJjZXMgYW5kIGxpbWl0YXRpb25zCjxhIGlkPSJzb3VyY2VzIj48L2E+CkkgdXNlZCB0d28gZGF0YSBzb3VyY2VzLiBGb3IgdGhlIGZ1bGwgMjAyMCB5ZWFyIHZpZXcsIEkgcmVhY2hlZCBvdXQgdG8gbXkgZnJpZW5kIGFuZCBjb2xsZWFndWUsIEpvaG4gQnJvd25zdGVpbiAoW2EgcGlvbmVlciBpbiBkaWdpdGFsIGVwaWRlbWlvbG9neV0oaHR0cHM6Ly9zY2hvbGFyLmdvb2dsZS5jb20vY2l0YXRpb25zP3VzZXI9d1RIMlpvb0FBQUFKJmhsPWVuJm9pPWFvKSkgYW5kIEphcmVkIEhhd2tpbnMgYW5kIGFza2VkIHRoZW0gZm9yICphbGwqIHR3ZWV0cyB0aGF0IG1lbnRpb24gQ09WSUQtMTkgb3IgU0FSUy1Db1YtMi4gVGhlIGZpbGUgdGhleSBzZW50IG1lIHdhcyBub3QgYWxsIHN1Y2ggdHdlZXRzIGJ1dCByZWd1bGFyIHNhbXBsaW5nIG9mIHN1Y2ggdHdlZXRzIHRvdGFsbG5nIGByIHBhc3RlKGNvdW50cyRoYXdraW5zVHdlZXRzKWAgdHdlZXRzLiBBbHNvLCBhcm91bmQgdGhlIGJlZ2lubmluZyBvZiBEZWNlbWJlciwgSSBzdGFydGVkIHJ1bm5pbmcgYSBjcm9uIGpvYiBvbiBteSBsYXB0b3AgZXZlcnkgdGhyZWUgZGF5cyB0byBnZXQgdGhlIGxhc3Qgd2VlayBvZiB0d2VldHMgKHRvIGVuc3VyZSBnb29kIG92ZXJsYXAgYmV0d2VlbiBlYWNoIHNlc3Npb24pIHRoYXQgaW5jbHVkZWQgbWVudGlvbiBvZiBjb3ZpZDE5LCAgSSByZWZlciB0byB0aGUgZmlyc3QgZGF0YSBzZXQgYXMgdGhlICJvdmVyYWxsIiBkYXRhIHNldCBhbmQgdGhlIHNlY29uZCBhcyB0aGUgIm9uZ29pbmciIGRhdGEgc2V0LgoKIyMjIFN5c3RlbSBDb25maWd1cmF0aW9uCgpDb25maWd1cmF0aW9uIHVzZWQgdG8gcnVuIHRoaXMgbm90ZWJvb2s6IGByIGkkUi52ZXJzaW9uJHZlcnNpb24uc3RyaW5nYCBpbmNsdWRlZCBwYWNrYWdlczpgciBuYW1lcyhpJG90aGVyUGtncylgCgojIyMgU2VhcmNoIHN0cmluZ3MKCkkgZGlkIG5vdCB1c2UgYW55IE5MUCB0ZWNobmlxdWVzIGJ1dCBvbiBzaW1wbGUgcmVndWxhciBleHByZXNzaW9uIHBhdHRlcm5zIHRvIGlkZW50aWZ5IHN0cmluZ3MgcmVsYXRlZCB0byB0aGUgdG9waWMuIEkgZXhwZXJpbWVudGVkIHdpdGggZGlmZmVyZW50IHJlZ3VsYXIgZXhwcmVzc2lvbnMgdW50aWwgdGhlIHR3ZWV0cyBtYXRjaGVkIHNlZW1kIHRvIGNvcnJlc3BvbmQgdG8gdGhlIGludGVuZGVkIHRvcGljLiAgSSBkb2N1bWVudCB0aG9zZSBwYXR0ZXJucyBiZWxvdyBhbGlnbmVkIHdpdGggdGhlIFRvcGljIGxhYmVscyBJIHVzZWQgaW4gdGhlIGFib3ZlIGdyYXBocy4gQnkgdGhlIHdheSwgaWYgeW91IHdhbnQgdG8gcmVhZCBzb21lIG9mIG91ciBwdWJsaWNhdGlvbnMgdGhhdCB1c2UgbW9yZSBjYXBhYmxlIHRlY2huaXF1ZXMgZm9yIGlkZW50aWZ5aW5nIGFuZCByZXRyaWV2aW5nIGluc3RhbmNlcyByZWxldmFudCB0byBhIHRvcGljLCBzZWUgW2hlcmVdKGh0dHBzOi8vcGFwZXJwaWxlLmNvbS9zaGFyZWQvNDNWVkw2KS4KCiMjIyBGaWx0ZXJzIGZvciBUb3BpY3MgYW5kIFR3ZWV0ZXIgR3JvdXBzCjxhIGlkPSJ0b3BpY2ZpbHRlcnMiPjwvYT4KYGBge3IgVG9waWMgRmlsdGVycywgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShrbml0cikKZmlsdGVyVGFibGUxIDwtIGJpbmRfY29scyhjb2xMYWJlbHM2LHN0cmluZ1ZlYzYpICU+JSAgYGNvbG5hbWVzPC1gKGMoIlRvcGljIiwgIlJlZ3VsYXIgRXhwcmVzc2lvbiIpKQoKa2JsKGZpbHRlclRhYmxlMSxjYXB0aW9uPSJSZWd1bGFyIGV4cHJlc3Npb24gc3RyaW5ncyB1c2VkIGZvciBlYWNoIHRvcGljIikgJT4lCiAga2FibGVfcGFwZXIoZnVsbF93aWR0aCA9IFQpICU+JQogIGNvbHVtbl9zcGVjKDEsIGJvbGQgPSBULCBib3JkZXJfcmlnaHQgPSBUKSAlPiUKICBjb2x1bW5fc3BlYygyLCB3aWR0aCA9ICI1MGVtIiwgYmFja2dyb3VuZCA9ICJncmF5MTAiKQpgYGAKPGEgaWQ9IlR3ZWV0ZXJDYXRlZ29yaWVzIj48L2E+CgojIyMgVHdlZXRlciBDYXRlZ29yaWVzCkhlcmUgYXJlIHRoZSByZWd1bGFyIGV4cHJlc3Npb25zIHVzZWQgdG8gZGVmaW5lIHRoZSBncm91cHMgb2YgVHdlZXRlcnMgdGhhdCB3ZSB3aXNoIHRvIHN0dWR5IG1vcmUgY2xvc2VseS4KYGBge3IgVHdlZXRlciBncm91cCBkZWZpbml0aW9ucywgZWNobz1GQUxTRSwgbWVzc2FnZT1UUlVFfQpncm91cE5hbWVzIDwtIGxpc3QoIk1lZGljYWwgcGVyc29ubmVsIiwiTmV3cyByZXBvcnRlcnMvb3JnYW5pemF0aW9ucyIpCmdyb3VwRmlsdGVycyA8LSBsaXN0KGMobWVkUmVnRXhwLG1lZFJlZ0V4cDIpLE5ld3NSZWdFeHApCmZpbHRlclRhYmxlMiA8LSB0aWJibGUoZ3JvdXBOYW1lcz1ncm91cE5hbWVzLGdyb3VwRmlsdGVycz1ncm91cEZpbHRlcnMpCmZpbHRlclRhYmxlMiA8LSBmaWx0ZXJUYWJsZTIgJT4lICBgY29sbmFtZXM8LWAoYygiR3JvdXAiLCAiUmVndWxhciBFeHByZXNzaW9uIikpCgprYmwoZmlsdGVyVGFibGUyLGNhcHRpb249IlJlZ3VsYXIgZXhwcmVzc2lvbiBzdHJpbmdzIHVzZWQgZm9yIGVhY2ggZ3JvdXAvbk1pc3Npbmcgbm9uTUQgbWVkaWNhbCBwZXJzb25uZWwiKSAlPiUKICBrYWJsZV9wYXBlcihmdWxsX3dpZHRoID0gVCkgJT4lCiAgY29sdW1uX3NwZWMoMSwgYm9sZCA9IFQsIGJvcmRlcl9yaWdodCA9IFQpICU+JQogIGNvbHVtbl9zcGVjKDIsIHdpZHRoID0gIjUwZW0iLCBiYWNrZ3JvdW5kID0gImdyYXkxMCIpCmBgYAoKIyMjIEZlZWRiYWNrCgpDb21tZW50cyBhbmQgcGFydGljdWxhcmx5IHN1Z2dlc3RlZCBpbXByb3ZlbWVudHMgYXJlIHdlbGNvbWUuCgoK