library(tidyverse)
library(pageviews) # This package gets data on Wikipedia viewing
library(DT) # DT stands for datatable, and creates interactive tables
top_articles() from the pageviews package finds the most-read articles on the English-language wikipedia page. By default it gives Oct. 1 2015.
top_articles()
You can put a start date in the parentheses using as.Date() to find the top articles for a specific date. I’ll randomly pick August 13, 2016.
top_articles(start = as.Date("2016-8-13"))
It’s good practice when you get data from the internet like this to save the data first so you can manipulate it, rather than hitting their internet server over and over. Let’s save the top articles as ‘top.’ The little arrow <- is a ‘less than’ sign followed by a dash. A shortcut to make it in R Studio is alt- (the alt key and the dash key at the same time) or option-, and you need to be in a code chunk for that to work.
This will take all the data from the top_articles() command and put it into a data frame called top:
top <- top_articles(start = as.Date("2016-8-13"))
Nothing will appear on screen after you run the code above, because all you’re doing is saving it into ‘top.’
There are a lot of extra columns in there that we don’t need, like language and granularity. Let’s select just the ones we want.
top %>%
select(article, views)
Notice that there are some weird articles in there: Main_Page and Special:Search. Let’s get rid of those. The ! is a NOT, so this will keep the articles that are not Main_Page and not Special:Search.
top %>%
select(article, views) %>%
filter(!article == "Main_Page", !article == "Special:Search")
NA
datatable() from the DT package
The command datatable() comes from the DT package. It creates more flexible tables that work well when you publish on the web.
Copy-paste the above chunk, but put in a new line at the end with datatable(), and don’t forget the pipe on the previous line. See the difference you get in the table.
top %>%
select(article, views) %>%
filter(!article == "Main_Page", !article == "Special:Search") %>%
datatable()
NA
There are many customizations you can do on datatable(). See the package website for more details: https://rstudio.github.io/DT/
Here’s one small example: cell-border stripe. Copy-paste the chunk above and then in the parenteses of datatable() put class = “cell-border stripe”.
top %>%
select(article, views) %>%
filter(!article == "Main_Page", !article == "Special:Search") %>%
datatable(class = "cell-border stripe")
NA
Adding a formatStyle() line allows more changes. Here’s an example that takes the article column and changes its color:
top %>%
select(article, views) %>%
filter(!article == "Main_Page", !article == "Special:Search") %>%
datatable(class = 'cell-border stripe') %>%
formatStyle("article", backgroundColor = "lightgoldenrodyellow")
NA
Now copy-paste the above code, keep the articles column its color, but add another formatStyle line, this one changing the “views” column to another color of your choice. Here’s one source that has a list of the color names possible: https://www.rapidtables.com/web/css/css-color.html
top %>%
select(article, views) %>%
filter(!article == "Main_Page", !article == "Special:Search") %>%
datatable(class = 'cell-border stripe') %>%
formatStyle("article", backgroundColor = "lightgoldenrodyellow") %>%
formatStyle("views", backgroundColor = "lightcoral")
NA
Graphing the data
To narrow it down from almost a thousand rows to just the top 10, run the following code:
top %>%
select(article, views) %>%
filter(!article == "Main_Page", !article == "Special:Search") %>%
top_n(10, views)
NA
You can graph it by piping the above chunk into a ggplot(), like this:
top %>%
select(article, views) %>%
filter(!article == "Main_Page", !article == "Special:Search") %>%
top_n(10, views) %>%
ggplot(aes(x = article, y = views)) +
geom_col()

That’s ugly. Let’s fix it so it looks better. Copy-paste the above chunk and then:
1. use as_factor() to put the bars in order. Replace ‘ggplot(aes(x = article, y = views)) +’ with ‘ggplot(aes(x = as_factor(article), y = views)) +’
2. flip the x and y axes with coord_flip(). Put a + at the end of the last line and then on the next line put ‘coord_flip()’.
top %>%
select(article, views) %>%
filter(!article == "Main_Page", !article == "Special:Search") %>%
top_n(10, views) %>%
ggplot(aes(x = as_factor(article), y = views)) +
geom_col() +
coord_flip()

Now, 1. let’s make the numbers normal. Add a line: scale_y_continuous(labels = scales::comma),
2. reverse the order to put the longest bars at the top. Change ‘as_factor(article)’ to ‘fct_rev(as_factor(article))’. Be careful that your parentheses open and close correctly.
3. add some color. Change geom_col() to geom_col(fill = “blue”), or try another color.
top %>%
select(article, views) %>%
filter(!article == "Main_Page", !article == "Special:Search") %>%
top_n(10, views) %>%
ggplot(aes(x = fct_rev(as_factor(article)), y = views)) +
geom_col(fill = "green") +
coord_flip() +
scale_y_continuous(labels = scales::comma)

Now finish it by adding the following line:
labs(y = “Number of Views”, x = “Article”, title = “Top Wikipedia articles, Aug. 13, 2016”)
top %>%
select(article, views) %>%
filter(!article == "Main_Page", !article == "Special:Search") %>%
top_n(10, views) %>%
ggplot(aes(x = fct_rev(as_factor(article)), y = views)) +
geom_col(fill = "green") +
coord_flip() +
scale_y_continuous(labels = scales::comma) +
labs(y = "Number of Views", x = "Article", title = "Top Wikipedia articles, Aug. 13, 2016")

Article views over a time period
See how often an article was accessed during a specific time period. Go to Wikipedia first to be sure you have the correct spelling and format of the article title. You can use R’s as.Date() to put in a date of this form: “2015-7-1”, which is the earliest it seems to go back.
I want to find the number of pageviews for flu over several years. Going to Wikipedia, the article name is Influenza. Here’s how to get the data, call it flu, and then use glimpse() to get an overview of the data:
flu <- article_pageviews(article = "Influenza", start = as.Date("2015-7-1"), end = as.Date("2018-7-1"))
glimpse(flu)
Observations: 1,097
Variables: 8
$ project [3m[90m<chr>[39m[23m "wikipedia", "wikipedia", "wikipedia", "wikipedia", "wikipedia", "wikipedia", "wikipedia", "wikipedia", "…
$ language [3m[90m<chr>[39m[23m "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en…
$ article [3m[90m<chr>[39m[23m "Influenza", "Influenza", "Influenza", "Influenza", "Influenza", "Influenza", "Influenza", "Influenza", "…
$ access [3m[90m<chr>[39m[23m "all-access", "all-access", "all-access", "all-access", "all-access", "all-access", "all-access", "all-ac…
$ agent [3m[90m<chr>[39m[23m "all-agents", "all-agents", "all-agents", "all-agents", "all-agents", "all-agents", "all-agents", "all-ag…
$ granularity [3m[90m<chr>[39m[23m "daily", "daily", "daily", "daily", "daily", "daily", "daily", "daily", "daily", "daily", "daily", "daily…
$ date [3m[90m<dttm>[39m[23m 2015-07-01, 2015-07-02, 2015-07-03, 2015-07-04, 2015-07-05, 2015-07-06, 2015-07-07, 2015-07-08, 2015-07-…
$ views [3m[90m<dbl>[39m[23m 2693, 3025, 2185, 1944, 2609, 2893, 3288, 2762, 2753, 2336, 1931, 2119, 2635, 2639, 2677, 2348, 2112, 178…
This uses ggplot to make a line graph:
flu %>%
ggplot(aes(x = date, y = views)) +
geom_line()

Modify the graph above by 1. Put color = “red” inside the parentheses of geom_line(), 2. add the following line: labs(x = “Date”, y = “Wikipedia Views”, title = “Views of Wikipedia’s Influenza Article”). Don’t forget the + to connect lines.
flu %>%
ggplot(aes(x = date, y = views)) +
geom_line(color = "red") +
labs(x = "Date", y = "Wikipedia Views", title = "Views of Wikipedia's Influenza Article")

Notice the big jump in late 2017. We can find the exact date by using arrange() to sort the data. We need to put the minus sign in front of views so the highest number of views is on top.
flu %>%
arrange(-views)
Combining data
Now look at another illness. Copy-paste the chunk above where you used article_pageviews to find Influenza searches, but change it so you find Diabetes searches. The Wikipedia article is called “Diabetes mellitus” (it is case sensitive). Call the data ‘diabetes’ instead of flu.
diabetes <- article_pageviews(article = "Diabetes mellitus",
start = as.Date("2015-7-1"),
end = as.Date("2018-7-1"))
Now graph it like above.
diabetes %>%
ggplot(aes(x = date, y = views)) +
geom_line()

Now we want to combine the two datasets so we can view them together. This uses bind_rows() to stack the flu data on top of the diabetes data. View the data by clicking on it in the Environment tab.
illness <- bind_rows(flu, diabetes)
Now create a plot of illness by piping it to ggplot just as above, but adding color = article inside the parentheses of aes().
illness %>%
ggplot(aes(x = date, y = views, color = article)) +
geom_line()

Views of Influenza are a bit lower overall than Diabetes, but Influenza views are highly seasonal, peaking in the winter flu months every year.
Gun control and mass shootings
This analysis looks at pageviews of “Gun control” on Wikipedia immediately before and after two mass shootings: One at a high school in Santa Fe TX on May 18, 2018, and another at a bar in California on Nov. 7, 2018.
I counted 7 days back (making the day of the shooting day 0) and then 14 days forward to get the start and end dates.
texas <- article_pageviews(article = "Gun_control",
start = as.Date("2018-5-11"),
end = as.Date("2018-6-1"))
The next code chunk does two things:
1. It labels each day from 7 days prior to 14 days after. A handy R trick is that the colon will fill in the numbers, so 1:5 creates 1, 2, 3, 4, 5.
2. It labels the event Texas so when I compare it to the other shooting I will know which one it is.
There will be no output from this because it just creates the two new columns in the texas data frame, but look at the data by clicking on it in the Environment tab.
texas <- texas %>%
mutate(day = -7:14) %>%
mutate(event = "Texas")
This gets a quick look at a graph of it.
texas %>%
ggplot(aes(x = day, y = views)) +
geom_line()

This next code chunk does all of the previous three but in one chunk: It finds views of the Gun control article 7 days before and 14 days after the Nov. 7, 2018 California shooting, creates the new columns with the days and the event, and creates the graph.
california <- article_pageviews(article = "Gun_control",
start = as.Date("2018-10-31"),
end = as.Date("2018-11-21"))
california <- california %>%
mutate(day = -7:14) %>%
mutate(event = "California")
california %>%
ggplot(aes(x = day, y = views)) +
geom_line()

Next, we want to combine them so we can see both graphs in one. The command to use is bind_rows(). It takes the texas data and puts its rows right on top of the rows from the california data.
Then it creates a graph with the minimal theme and proper titles:
shootings <- bind_rows(texas, california)
shootings %>%
ggplot(aes(x = day, y = views, color = event)) +
geom_line() +
theme_minimal() +
labs(x = "Days before/after Shooting",
y = "Wikipedia Views",
color = "Event",
title = "Views of the Wikipedia Gun Control Article before and after Two Mass Shootings")

LS0tCnRpdGxlOiAiV2lraXBlZGlhIEFQSSByYW5kYWxsIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGFnZXZpZXdzKSAgICAgICAgIyBUaGlzIHBhY2thZ2UgZ2V0cyBkYXRhIG9uIFdpa2lwZWRpYSB2aWV3aW5nCmxpYnJhcnkoRFQpICAgICAgICAgICAgICAgIyBEVCBzdGFuZHMgZm9yIGRhdGF0YWJsZSwgYW5kIGNyZWF0ZXMgaW50ZXJhY3RpdmUgdGFibGVzCmBgYAoKdG9wX2FydGljbGVzKCkgZnJvbSB0aGUgcGFnZXZpZXdzIHBhY2thZ2UgZmluZHMgdGhlIG1vc3QtcmVhZCBhcnRpY2xlcyBvbiB0aGUgRW5nbGlzaC1sYW5ndWFnZSB3aWtpcGVkaWEgcGFnZS4gQnkgZGVmYXVsdCBpdCBnaXZlcyBPY3QuIDEgMjAxNS4KYGBge3J9CnRvcF9hcnRpY2xlcygpCmBgYAoKWW91IGNhbiBwdXQgYSBzdGFydCBkYXRlIGluIHRoZSBwYXJlbnRoZXNlcyB1c2luZyBhcy5EYXRlKCkgdG8gZmluZCB0aGUgdG9wIGFydGljbGVzIGZvciBhIHNwZWNpZmljIGRhdGUuIEknbGwgcmFuZG9tbHkgcGljayBBdWd1c3QgMTMsIDIwMTYuCmBgYHtyfQp0b3BfYXJ0aWNsZXMoc3RhcnQgPSBhcy5EYXRlKCIyMDE2LTgtMTMiKSkKYGBgCgoKSXQncyBnb29kIHByYWN0aWNlIHdoZW4geW91IGdldCBkYXRhIGZyb20gdGhlIGludGVybmV0IGxpa2UgdGhpcyB0byBzYXZlIHRoZSBkYXRhIGZpcnN0IHNvIHlvdSBjYW4gbWFuaXB1bGF0ZSBpdCwgcmF0aGVyIHRoYW4gaGl0dGluZyB0aGVpciBpbnRlcm5ldCBzZXJ2ZXIgb3ZlciBhbmQgb3Zlci4gTGV0J3Mgc2F2ZSB0aGUgdG9wIGFydGljbGVzIGFzICd0b3AuJyBUaGUgbGl0dGxlIGFycm93IDwtIGlzIGEgJ2xlc3MgdGhhbicgc2lnbiBmb2xsb3dlZCBieSBhIGRhc2guIEEgc2hvcnRjdXQgdG8gbWFrZSBpdCBpbiBSIFN0dWRpbyBpcyBhbHQtICh0aGUgYWx0IGtleSBhbmQgdGhlIGRhc2gga2V5IGF0IHRoZSBzYW1lIHRpbWUpIG9yIG9wdGlvbi0sIGFuZCB5b3UgbmVlZCB0byBiZSBpbiBhIGNvZGUgY2h1bmsgZm9yIHRoYXQgdG8gd29yay4gCgpUaGlzIHdpbGwgdGFrZSBhbGwgdGhlIGRhdGEgZnJvbSB0aGUgdG9wX2FydGljbGVzKCkgY29tbWFuZCBhbmQgcHV0IGl0IGludG8gYSBkYXRhIGZyYW1lIGNhbGxlZCB0b3A6CgpgYGB7cn0KdG9wIDwtIHRvcF9hcnRpY2xlcyhzdGFydCA9IGFzLkRhdGUoIjIwMTYtOC0xMyIpKSAKYGBgCgpOb3RoaW5nIHdpbGwgYXBwZWFyIG9uIHNjcmVlbiBhZnRlciB5b3UgcnVuIHRoZSBjb2RlIGFib3ZlLCBiZWNhdXNlIGFsbCB5b3UncmUgZG9pbmcgaXMgc2F2aW5nIGl0IGludG8gJ3RvcC4nCgoKVGhlcmUgYXJlIGEgbG90IG9mIGV4dHJhIGNvbHVtbnMgaW4gdGhlcmUgdGhhdCB3ZSBkb24ndCBuZWVkLCBsaWtlIGxhbmd1YWdlIGFuZCBncmFudWxhcml0eS4gTGV0J3Mgc2VsZWN0IGp1c3QgdGhlIG9uZXMgd2Ugd2FudC4KYGBge3J9CnRvcCAlPiUKICBzZWxlY3QoYXJ0aWNsZSwgdmlld3MpCmBgYAoKTm90aWNlIHRoYXQgdGhlcmUgYXJlIHNvbWUgd2VpcmQgYXJ0aWNsZXMgaW4gdGhlcmU6IE1haW5fUGFnZSBhbmQgU3BlY2lhbDpTZWFyY2guIExldCdzIGdldCByaWQgb2YgdGhvc2UuIFRoZSAhIGlzIGEgTk9ULCBzbyB0aGlzIHdpbGwga2VlcCB0aGUgYXJ0aWNsZXMgdGhhdCBhcmUgbm90IE1haW5fUGFnZSBhbmQgbm90IFNwZWNpYWw6U2VhcmNoLiAKYGBge3J9CnRvcCAlPiUgCiAgc2VsZWN0KGFydGljbGUsIHZpZXdzKSAlPiUKICBmaWx0ZXIoIWFydGljbGUgPT0gIk1haW5fUGFnZSIsICFhcnRpY2xlID09ICJTcGVjaWFsOlNlYXJjaCIpCgpgYGAKCgojIyMgZGF0YXRhYmxlKCkgZnJvbSB0aGUgRFQgcGFja2FnZQoKVGhlIGNvbW1hbmQgZGF0YXRhYmxlKCkgY29tZXMgZnJvbSB0aGUgRFQgcGFja2FnZS4gSXQgY3JlYXRlcyBtb3JlIGZsZXhpYmxlIHRhYmxlcyB0aGF0IHdvcmsgd2VsbCB3aGVuIHlvdSBwdWJsaXNoIG9uIHRoZSB3ZWIuICAKCkNvcHktcGFzdGUgdGhlIGFib3ZlIGNodW5rLCBidXQgcHV0IGluIGEgbmV3IGxpbmUgYXQgdGhlIGVuZCB3aXRoIGRhdGF0YWJsZSgpLCBhbmQgZG9uJ3QgZm9yZ2V0IHRoZSBwaXBlIG9uIHRoZSBwcmV2aW91cyBsaW5lLiBTZWUgdGhlIGRpZmZlcmVuY2UgeW91IGdldCBpbiB0aGUgdGFibGUuICAKCgpgYGB7cn0KdG9wICU+JSAKICBzZWxlY3QoYXJ0aWNsZSwgdmlld3MpICU+JQogIGZpbHRlcighYXJ0aWNsZSA9PSAiTWFpbl9QYWdlIiwgIWFydGljbGUgPT0gIlNwZWNpYWw6U2VhcmNoIikgJT4lCiAgZGF0YXRhYmxlKCkKCmBgYAoKCgoKCgoKClRoZXJlIGFyZSBtYW55IGN1c3RvbWl6YXRpb25zIHlvdSBjYW4gZG8gb24gZGF0YXRhYmxlKCkuIFNlZSB0aGUgcGFja2FnZSB3ZWJzaXRlIGZvciBtb3JlIGRldGFpbHM6IGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vRFQvCgpIZXJlJ3Mgb25lIHNtYWxsIGV4YW1wbGU6IGNlbGwtYm9yZGVyIHN0cmlwZS4gIENvcHktcGFzdGUgdGhlIGNodW5rIGFib3ZlIGFuZCB0aGVuIGluIHRoZSBwYXJlbnRlc2VzIG9mIGRhdGF0YWJsZSgpIHB1dCBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLgoKCmBgYHtyfQp0b3AgJT4lIAogIHNlbGVjdChhcnRpY2xlLCB2aWV3cykgJT4lCiAgZmlsdGVyKCFhcnRpY2xlID09ICJNYWluX1BhZ2UiLCAhYXJ0aWNsZSA9PSAiU3BlY2lhbDpTZWFyY2giKSAlPiUKICBkYXRhdGFibGUoY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIikKCmBgYAoKCgoKCgpBZGRpbmcgYSBmb3JtYXRTdHlsZSgpIGxpbmUgYWxsb3dzIG1vcmUgY2hhbmdlcy4gSGVyZSdzIGFuIGV4YW1wbGUgdGhhdCB0YWtlcyB0aGUgYXJ0aWNsZSBjb2x1bW4gYW5kIGNoYW5nZXMgaXRzIGNvbG9yOgoKYGBge3J9CnRvcCAlPiUgCiAgc2VsZWN0KGFydGljbGUsIHZpZXdzKSAlPiUKICBmaWx0ZXIoIWFydGljbGUgPT0gIk1haW5fUGFnZSIsICFhcnRpY2xlID09ICJTcGVjaWFsOlNlYXJjaCIpICU+JSAKICBkYXRhdGFibGUoY2xhc3MgPSAnY2VsbC1ib3JkZXIgc3RyaXBlJykgJT4lIAogIGZvcm1hdFN0eWxlKCJhcnRpY2xlIiwgYmFja2dyb3VuZENvbG9yID0gImxpZ2h0Z29sZGVucm9keWVsbG93IikKCmBgYAoKCk5vdyBjb3B5LXBhc3RlIHRoZSBhYm92ZSBjb2RlLCBrZWVwIHRoZSBhcnRpY2xlcyBjb2x1bW4gaXRzIGNvbG9yLCBidXQgYWRkIGFub3RoZXIgZm9ybWF0U3R5bGUgbGluZSwgdGhpcyBvbmUgY2hhbmdpbmcgdGhlICJ2aWV3cyIgY29sdW1uIHRvIGFub3RoZXIgY29sb3Igb2YgeW91ciBjaG9pY2UuIEhlcmUncyBvbmUgc291cmNlIHRoYXQgaGFzIGEgbGlzdCBvZiB0aGUgY29sb3IgbmFtZXMgcG9zc2libGU6IGh0dHBzOi8vd3d3LnJhcGlkdGFibGVzLmNvbS93ZWIvY3NzL2Nzcy1jb2xvci5odG1sCgoKCmBgYHtyfQp0b3AgJT4lIAogIHNlbGVjdChhcnRpY2xlLCB2aWV3cykgJT4lCiAgZmlsdGVyKCFhcnRpY2xlID09ICJNYWluX1BhZ2UiLCAhYXJ0aWNsZSA9PSAiU3BlY2lhbDpTZWFyY2giKSAlPiUgCiAgZGF0YXRhYmxlKGNsYXNzID0gJ2NlbGwtYm9yZGVyIHN0cmlwZScpICU+JSAKICBmb3JtYXRTdHlsZSgiYXJ0aWNsZSIsIGJhY2tncm91bmRDb2xvciA9ICJsaWdodGdvbGRlbnJvZHllbGxvdyIpICU+JSAKICBmb3JtYXRTdHlsZSgidmlld3MiLCBiYWNrZ3JvdW5kQ29sb3IgPSAibGlnaHRjb3JhbCIpCgpgYGAKCgoKCgoKCgoKCgoKIyMjIEdyYXBoaW5nIHRoZSBkYXRhCgpUbyBuYXJyb3cgaXQgZG93biBmcm9tIGFsbW9zdCBhIHRob3VzYW5kIHJvd3MgdG8ganVzdCB0aGUgdG9wIDEwLCBydW4gdGhlIGZvbGxvd2luZyBjb2RlOgoKYGBge3J9CnRvcCAlPiUgCiAgc2VsZWN0KGFydGljbGUsIHZpZXdzKSAlPiUKICBmaWx0ZXIoIWFydGljbGUgPT0gIk1haW5fUGFnZSIsICFhcnRpY2xlID09ICJTcGVjaWFsOlNlYXJjaCIpICU+JSAKICB0b3BfbigxMCwgdmlld3MpCgpgYGAKCllvdSBjYW4gZ3JhcGggaXQgYnkgcGlwaW5nIHRoZSBhYm92ZSBjaHVuayBpbnRvIGEgZ2dwbG90KCksIGxpa2UgdGhpczoKCmBgYHtyfQp0b3AgJT4lIAogIHNlbGVjdChhcnRpY2xlLCB2aWV3cykgJT4lCiAgZmlsdGVyKCFhcnRpY2xlID09ICJNYWluX1BhZ2UiLCAhYXJ0aWNsZSA9PSAiU3BlY2lhbDpTZWFyY2giKSAlPiUgCiAgdG9wX24oMTAsIHZpZXdzKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gYXJ0aWNsZSwgeSA9IHZpZXdzKSkgKwogIGdlb21fY29sKCkKYGBgCgpUaGF0J3MgdWdseS4gTGV0J3MgZml4IGl0IHNvIGl0IGxvb2tzIGJldHRlci4gQ29weS1wYXN0ZSB0aGUgYWJvdmUgY2h1bmsgYW5kIHRoZW46ICAgIAoxLiB1c2UgYXNfZmFjdG9yKCkgdG8gcHV0IHRoZSBiYXJzIGluIG9yZGVyLiBSZXBsYWNlICdnZ3Bsb3QoYWVzKHggPSBhcnRpY2xlLCB5ID0gdmlld3MpKSArJyB3aXRoICdnZ3Bsb3QoYWVzKHggPSBhc19mYWN0b3IoYXJ0aWNsZSksIHkgPSB2aWV3cykpICsnICAgCjIuIGZsaXAgdGhlIHggYW5kIHkgYXhlcyB3aXRoIGNvb3JkX2ZsaXAoKS4gUHV0IGEgKyBhdCB0aGUgZW5kIG9mIHRoZSBsYXN0IGxpbmUgYW5kIHRoZW4gb24gdGhlIG5leHQgbGluZSBwdXQgJ2Nvb3JkX2ZsaXAoKScuCgoKYGBge3J9CnRvcCAlPiUgCiAgc2VsZWN0KGFydGljbGUsIHZpZXdzKSAlPiUKICBmaWx0ZXIoIWFydGljbGUgPT0gIk1haW5fUGFnZSIsICFhcnRpY2xlID09ICJTcGVjaWFsOlNlYXJjaCIpICU+JSAKICB0b3BfbigxMCwgdmlld3MpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhc19mYWN0b3IoYXJ0aWNsZSksIHkgPSB2aWV3cykpICsKICBnZW9tX2NvbCgpICsKICBjb29yZF9mbGlwKCkKYGBgCgoKCgoKCgoKCgoKTm93LCAxLiBsZXQncyBtYWtlIHRoZSBudW1iZXJzIG5vcm1hbC4gQWRkIGEgbGluZTogc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpLCAgCjIuIHJldmVyc2UgdGhlIG9yZGVyIHRvIHB1dCB0aGUgbG9uZ2VzdCBiYXJzIGF0IHRoZSB0b3AuIENoYW5nZSAnYXNfZmFjdG9yKGFydGljbGUpJyB0byAnZmN0X3Jldihhc19mYWN0b3IoYXJ0aWNsZSkpJy4gQmUgY2FyZWZ1bCB0aGF0IHlvdXIgcGFyZW50aGVzZXMgb3BlbiBhbmQgY2xvc2UgY29ycmVjdGx5LiAgICAKMy4gYWRkIHNvbWUgY29sb3IuIENoYW5nZSBnZW9tX2NvbCgpIHRvIGdlb21fY29sKGZpbGwgPSAiYmx1ZSIpLCBvciB0cnkgYW5vdGhlciBjb2xvci4gIAoKCmBgYHtyfQp0b3AgJT4lIAogIHNlbGVjdChhcnRpY2xlLCB2aWV3cykgJT4lCiAgZmlsdGVyKCFhcnRpY2xlID09ICJNYWluX1BhZ2UiLCAhYXJ0aWNsZSA9PSAiU3BlY2lhbDpTZWFyY2giKSAlPiUgCiAgdG9wX24oMTAsIHZpZXdzKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZmN0X3Jldihhc19mYWN0b3IoYXJ0aWNsZSkpLCB5ID0gdmlld3MpKSArCiAgZ2VvbV9jb2woZmlsbCA9ICJncmVlbiIpICsKICBjb29yZF9mbGlwKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKQpgYGAKCgoKCgoKCgoKCk5vdyBmaW5pc2ggaXQgYnkgYWRkaW5nIHRoZSBmb2xsb3dpbmcgbGluZToKCmxhYnMoeSA9ICJOdW1iZXIgb2YgVmlld3MiLCB4ID0gIkFydGljbGUiLCB0aXRsZSA9ICJUb3AgV2lraXBlZGlhIGFydGljbGVzLCBBdWcuIDEzLCAyMDE2IikKCgpgYGB7cn0KdG9wICU+JSAKICBzZWxlY3QoYXJ0aWNsZSwgdmlld3MpICU+JQogIGZpbHRlcighYXJ0aWNsZSA9PSAiTWFpbl9QYWdlIiwgIWFydGljbGUgPT0gIlNwZWNpYWw6U2VhcmNoIikgJT4lIAogIHRvcF9uKDEwLCB2aWV3cykgJT4lIAogIGdncGxvdChhZXMoeCA9IGZjdF9yZXYoYXNfZmFjdG9yKGFydGljbGUpKSwgeSA9IHZpZXdzKSkgKwogIGdlb21fY29sKGZpbGwgPSAiZ3JlZW4iKSArCiAgY29vcmRfZmxpcCgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKwogIGxhYnMoeSA9ICJOdW1iZXIgb2YgVmlld3MiLCB4ID0gIkFydGljbGUiLCB0aXRsZSA9ICJUb3AgV2lraXBlZGlhIGFydGljbGVzLCBBdWcuIDEzLCAyMDE2IikKYGBgCgoKCgoKCgoKCgoKCgojIyMgQXJ0aWNsZSB2aWV3cyBvdmVyIGEgdGltZSBwZXJpb2QKClNlZSBob3cgb2Z0ZW4gYW4gYXJ0aWNsZSB3YXMgYWNjZXNzZWQgZHVyaW5nIGEgc3BlY2lmaWMgdGltZSBwZXJpb2QuIEdvIHRvIFdpa2lwZWRpYSBmaXJzdCB0byBiZSBzdXJlIHlvdSBoYXZlIHRoZSBjb3JyZWN0IHNwZWxsaW5nIGFuZCBmb3JtYXQgb2YgdGhlIGFydGljbGUgdGl0bGUuIFlvdSBjYW4gdXNlIFIncyBhcy5EYXRlKCkgdG8gcHV0IGluIGEgZGF0ZSBvZiB0aGlzIGZvcm06ICIyMDE1LTctMSIsIHdoaWNoIGlzIHRoZSBlYXJsaWVzdCBpdCBzZWVtcyB0byBnbyBiYWNrLgoKSSB3YW50IHRvIGZpbmQgdGhlIG51bWJlciBvZiBwYWdldmlld3MgZm9yIGZsdSBvdmVyIHNldmVyYWwgeWVhcnMuIEdvaW5nIHRvIFdpa2lwZWRpYSwgdGhlIGFydGljbGUgbmFtZSBpcyAqSW5mbHVlbnphKi4gSGVyZSdzIGhvdyB0byBnZXQgdGhlIGRhdGEsIGNhbGwgaXQgZmx1LCBhbmQgdGhlbiB1c2UgZ2xpbXBzZSgpIHRvIGdldCBhbiBvdmVydmlldyBvZiB0aGUgZGF0YToKCmBgYHtyfQpmbHUgPC0gYXJ0aWNsZV9wYWdldmlld3MoYXJ0aWNsZSA9ICJJbmZsdWVuemEiLCBzdGFydCA9IGFzLkRhdGUoIjIwMTUtNy0xIiksIGVuZCA9IGFzLkRhdGUoIjIwMTgtNy0xIikpCgpnbGltcHNlKGZsdSkKYGBgCgoKClRoaXMgdXNlcyBnZ3Bsb3QgdG8gbWFrZSBhIGxpbmUgZ3JhcGg6CgpgYGB7cn0KZmx1ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gdmlld3MpKSArCiAgZ2VvbV9saW5lKCkKYGBgCgoKTW9kaWZ5IHRoZSBncmFwaCBhYm92ZSBieSAKMS4gUHV0IGNvbG9yID0gInJlZCIgaW5zaWRlIHRoZSBwYXJlbnRoZXNlcyBvZiBnZW9tX2xpbmUoKSwKMi4gYWRkIHRoZSBmb2xsb3dpbmcgbGluZTogbGFicyh4ID0gIkRhdGUiLCB5ID0gIldpa2lwZWRpYSBWaWV3cyIsIHRpdGxlID0gIlZpZXdzIG9mIFdpa2lwZWRpYSdzIEluZmx1ZW56YSBBcnRpY2xlIikuIERvbid0IGZvcmdldCB0aGUgKyB0byBjb25uZWN0IGxpbmVzLgoKCgoKYGBge3J9CmZsdSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHZpZXdzKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJyZWQiKSArCiAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIldpa2lwZWRpYSBWaWV3cyIsIHRpdGxlID0gIlZpZXdzIG9mIFdpa2lwZWRpYSdzIEluZmx1ZW56YSBBcnRpY2xlIikKYGBgCgoKCgoKCgoKCgoKTm90aWNlIHRoZSBiaWcganVtcCBpbiBsYXRlIDIwMTcuIFdlIGNhbiBmaW5kIHRoZSBleGFjdCBkYXRlIGJ5IHVzaW5nIGFycmFuZ2UoKSB0byBzb3J0IHRoZSBkYXRhLiBXZSBuZWVkIHRvIHB1dCB0aGUgbWludXMgc2lnbiBpbiBmcm9udCBvZiB2aWV3cyBzbyB0aGUgaGlnaGVzdCBudW1iZXIgb2Ygdmlld3MgaXMgb24gdG9wLgpgYGB7cn0KZmx1ICU+JQogIGFycmFuZ2UoLXZpZXdzKQpgYGAKCgoKIyMjIENvbWJpbmluZyBkYXRhCgpOb3cgbG9vayBhdCBhbm90aGVyIGlsbG5lc3MuIENvcHktcGFzdGUgdGhlIGNodW5rIGFib3ZlIHdoZXJlIHlvdSB1c2VkIGFydGljbGVfcGFnZXZpZXdzIHRvIGZpbmQgSW5mbHVlbnphIHNlYXJjaGVzLCBidXQgY2hhbmdlIGl0IHNvIHlvdSBmaW5kIERpYWJldGVzIHNlYXJjaGVzLiBUaGUgV2lraXBlZGlhIGFydGljbGUgaXMgY2FsbGVkICJEaWFiZXRlcyBtZWxsaXR1cyIgKGl0IGlzIGNhc2Ugc2Vuc2l0aXZlKS4gQ2FsbCB0aGUgZGF0YSAnZGlhYmV0ZXMnIGluc3RlYWQgb2YgZmx1LgoKYGBge3J9CmRpYWJldGVzIDwtIGFydGljbGVfcGFnZXZpZXdzKGFydGljbGUgPSAiRGlhYmV0ZXMgbWVsbGl0dXMiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQgPSBhcy5EYXRlKCIyMDE1LTctMSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kID0gYXMuRGF0ZSgiMjAxOC03LTEiKSkKYGBgCgoKCk5vdyBncmFwaCBpdCBsaWtlIGFib3ZlLgoKCmBgYHtyfQpkaWFiZXRlcyAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHZpZXdzKSkgKwogIGdlb21fbGluZSgpCmBgYAoKCgoKCk5vdyB3ZSB3YW50IHRvIGNvbWJpbmUgdGhlIHR3byBkYXRhc2V0cyBzbyB3ZSBjYW4gdmlldyB0aGVtIHRvZ2V0aGVyLiBUaGlzIHVzZXMgYmluZF9yb3dzKCkgdG8gc3RhY2sgdGhlIGZsdSBkYXRhIG9uIHRvcCBvZiB0aGUgZGlhYmV0ZXMgZGF0YS4gVmlldyB0aGUgZGF0YSBieSBjbGlja2luZyBvbiBpdCBpbiB0aGUgRW52aXJvbm1lbnQgdGFiLgoKCmBgYHtyfQppbGxuZXNzIDwtIGJpbmRfcm93cyhmbHUsIGRpYWJldGVzKSAKCmBgYAoKCgpOb3cgY3JlYXRlIGEgcGxvdCBvZiBpbGxuZXNzIGJ5IHBpcGluZyBpdCB0byBnZ3Bsb3QganVzdCBhcyBhYm92ZSwgYnV0IGFkZGluZyBjb2xvciA9IGFydGljbGUgaW5zaWRlIHRoZSBwYXJlbnRoZXNlcyBvZiBhZXMoKS4KCgoKYGBge3J9CmlsbG5lc3MgJT4lIAogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSB2aWV3cywgY29sb3IgPSBhcnRpY2xlKSkgKwogIGdlb21fbGluZSgpCmBgYAoKCgoKCgoKVmlld3Mgb2YgSW5mbHVlbnphIGFyZSBhIGJpdCBsb3dlciBvdmVyYWxsIHRoYW4gRGlhYmV0ZXMsIGJ1dCBJbmZsdWVuemEgdmlld3MgYXJlIGhpZ2hseSBzZWFzb25hbCwgcGVha2luZyBpbiB0aGUgd2ludGVyIGZsdSBtb250aHMgZXZlcnkgeWVhci4KCgoKIyMjIEd1biBjb250cm9sIGFuZCBtYXNzIHNob290aW5ncwoKClRoaXMgYW5hbHlzaXMgbG9va3MgYXQgcGFnZXZpZXdzIG9mICJHdW4gY29udHJvbCIgb24gV2lraXBlZGlhIGltbWVkaWF0ZWx5IGJlZm9yZSBhbmQgYWZ0ZXIgdHdvIG1hc3Mgc2hvb3RpbmdzOiBPbmUgYXQgYSBoaWdoIHNjaG9vbCBpbiBTYW50YSBGZSBUWCBvbiBNYXkgMTgsIDIwMTgsIGFuZCBhbm90aGVyIGF0IGEgYmFyIGluIENhbGlmb3JuaWEgb24gTm92LiA3LCAyMDE4LgoKSSBjb3VudGVkIDcgZGF5cyBiYWNrIChtYWtpbmcgdGhlIGRheSBvZiB0aGUgc2hvb3RpbmcgZGF5IDApIGFuZCB0aGVuIDE0IGRheXMgZm9yd2FyZCB0byBnZXQgdGhlIHN0YXJ0IGFuZCBlbmQgZGF0ZXMuIAoKYGBge3J9CnRleGFzIDwtIGFydGljbGVfcGFnZXZpZXdzKGFydGljbGUgPSAiR3VuX2NvbnRyb2wiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydCA9IGFzLkRhdGUoIjIwMTgtNS0xMSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSBhcy5EYXRlKCIyMDE4LTYtMSIpKQoKYGBgCgoKVGhlIG5leHQgY29kZSBjaHVuayBkb2VzIHR3byB0aGluZ3M6ICAKMS4gSXQgbGFiZWxzIGVhY2ggZGF5IGZyb20gNyBkYXlzIHByaW9yIHRvIDE0IGRheXMgYWZ0ZXIuIEEgaGFuZHkgUiB0cmljayBpcyB0aGF0IHRoZSBjb2xvbiB3aWxsIGZpbGwgaW4gdGhlIG51bWJlcnMsIHNvIDE6NSBjcmVhdGVzIDEsIDIsIDMsIDQsIDUuICAKMi4gSXQgbGFiZWxzIHRoZSBldmVudCBUZXhhcyBzbyB3aGVuIEkgY29tcGFyZSBpdCB0byB0aGUgb3RoZXIgc2hvb3RpbmcgSSB3aWxsIGtub3cgd2hpY2ggb25lIGl0IGlzLiAgCgpUaGVyZSB3aWxsIGJlIG5vIG91dHB1dCBmcm9tIHRoaXMgYmVjYXVzZSBpdCBqdXN0IGNyZWF0ZXMgdGhlIHR3byBuZXcgY29sdW1ucyBpbiB0aGUgdGV4YXMgZGF0YSBmcmFtZSwgYnV0IGxvb2sgYXQgdGhlIGRhdGEgYnkgY2xpY2tpbmcgb24gaXQgaW4gdGhlIEVudmlyb25tZW50IHRhYi4KCgoKYGBge3J9CnRleGFzIDwtIHRleGFzICU+JSAKICBtdXRhdGUoZGF5ID0gLTc6MTQpICU+JSAKICBtdXRhdGUoZXZlbnQgPSAiVGV4YXMiKQoKYGBgCgpUaGlzIGdldHMgYSBxdWljayBsb29rIGF0IGEgZ3JhcGggb2YgaXQuCgpgYGB7cn0KdGV4YXMgJT4lIAogIGdncGxvdChhZXMoeCA9IGRheSwgeSA9IHZpZXdzKSkgKwogIGdlb21fbGluZSgpCmBgYAoKVGhpcyBuZXh0IGNvZGUgY2h1bmsgZG9lcyBhbGwgb2YgdGhlIHByZXZpb3VzIHRocmVlIGJ1dCBpbiBvbmUgY2h1bms6IEl0IGZpbmRzIHZpZXdzIG9mIHRoZSBHdW4gY29udHJvbCBhcnRpY2xlIDcgZGF5cyBiZWZvcmUgYW5kIDE0IGRheXMgYWZ0ZXIgdGhlIE5vdi4gNywgMjAxOCBDYWxpZm9ybmlhIHNob290aW5nLCBjcmVhdGVzIHRoZSBuZXcgY29sdW1ucyB3aXRoIHRoZSBkYXlzIGFuZCB0aGUgZXZlbnQsIGFuZCBjcmVhdGVzIHRoZSBncmFwaC4KCmBgYHtyfQpjYWxpZm9ybmlhIDwtIGFydGljbGVfcGFnZXZpZXdzKGFydGljbGUgPSAiR3VuX2NvbnRyb2wiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydCA9IGFzLkRhdGUoIjIwMTgtMTAtMzEiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kID0gYXMuRGF0ZSgiMjAxOC0xMS0yMSIpKQoKY2FsaWZvcm5pYSA8LSBjYWxpZm9ybmlhICU+JSAKICBtdXRhdGUoZGF5ID0gLTc6MTQpICU+JSAKICBtdXRhdGUoZXZlbnQgPSAiQ2FsaWZvcm5pYSIpCgpjYWxpZm9ybmlhICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXksIHkgPSB2aWV3cykpICsKICBnZW9tX2xpbmUoKQoKYGBgCgoKTmV4dCwgd2Ugd2FudCB0byBjb21iaW5lIHRoZW0gc28gd2UgY2FuIHNlZSBib3RoIGdyYXBocyBpbiBvbmUuIFRoZSBjb21tYW5kIHRvIHVzZSBpcyBiaW5kX3Jvd3MoKS4gSXQgdGFrZXMgdGhlIHRleGFzIGRhdGEgYW5kIHB1dHMgaXRzIHJvd3MgcmlnaHQgb24gdG9wIG9mIHRoZSByb3dzIGZyb20gdGhlIGNhbGlmb3JuaWEgZGF0YS4KClRoZW4gaXQgY3JlYXRlcyBhIGdyYXBoIHdpdGggdGhlIG1pbmltYWwgdGhlbWUgYW5kIHByb3BlciB0aXRsZXM6CgpgYGB7cn0Kc2hvb3RpbmdzIDwtIGJpbmRfcm93cyh0ZXhhcywgY2FsaWZvcm5pYSkKCnNob290aW5ncyAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF5LCB5ID0gdmlld3MsIGNvbG9yID0gZXZlbnQpKSArCiAgZ2VvbV9saW5lKCkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh4ID0gIkRheXMgYmVmb3JlL2FmdGVyIFNob290aW5nIiwgCiAgICAgICB5ID0gIldpa2lwZWRpYSBWaWV3cyIsIAogICAgICAgY29sb3IgPSAiRXZlbnQiLCAKICAgICAgIHRpdGxlID0gIlZpZXdzIG9mIHRoZSBXaWtpcGVkaWEgR3VuIENvbnRyb2wgQXJ0aWNsZSBiZWZvcmUgYW5kIGFmdGVyIFR3byBNYXNzIFNob290aW5ncyIpCmBgYA==