Seminar Learning Goals

  1. Analyse covid-19 data trends

  2. To run and extend some simple R code to compute book income

  3. Exercise answers

##0. Worksheet Introduction

Pre-requisites

You should:

  1. have completed the Week 1 Joining Seminar
  2. have (re-)acquainted yourself with Week 1 Seminar worksheet
  3. be familiar (listened to/read) the Week 2 Lecture “The Richness of Data”
  4. be able to write, edit, save and re-open your own RMarkdown files

If this is proving a challenge see “Prerequisites for Week 2 Seminars and Labs (CS5701/02)” for advice.

This seminar worksheet is organised as an RMarkdown file. You can read it. You can run the embedded R and you can add your own R. I suggest you save it as another file so, if necessary, you can revert to the original.

Whenever you click Preview in the RStudio menu it will render into nicely formatted html which you can look at it in the Viewing Window in RStudio or any web browser. You may find this easier to read, however, you must edit the .rmd file, i.e., the RMarkdown in the Edit Pane if you want to make any changes.

Remember, you are encouraged to explore and experiment. Change something and see what happens!

As per last week we will cover a lot of new ground but don’t be discouraged. We will revisit these concepts over the following weeks to help you consolidate your understanding.

1. Visualising covid-19 data trends

This example shows how we can fetch and visualise covid-19 data from John Hopkins University via GitHub.

Initialisation

We need some packages over and above base R. Since we may not be sure whether they are already installed we test for their presence. Most packages come from CRAN and are easy to install using install.packages() but the package {tidycovid19} is on GitHub (joachim-gassen) so we also need {devtools} in order to install packages that aren’t on CRAN.

This R code may appear daunting but don’t worry. We will revisit it in detail in Week 3. For the time being see it as a way to install and load necessary extra functionality beyond base ER.

# If a package is installed, it will be loaded and missing package(s) will be installed 
# from CRAN and then loaded.

# The packages we need are:
 
packages = c("tidyverse", "devtools")

# Load the package or install and load it
package.check <- lapply(
  packages,
  FUN = function(x) {
    if (!require(x, character.only = TRUE)) {
      install.packages(x, dependencies = TRUE)
      library(x, character.only = TRUE)
    }
  }
)

install_github("joachim-gassen/tidycovid19")
Skipping install of 'tidycovid19' from a github remote, the SHA1 (78254dca) has not changed since last install.
  Use `force = TRUE` to force installation
library(tidycovid19)

Download the data (cached on GitHub rather than directly from John Hopkins University). This is live data updated within the last 24 hours.

#Download the data into a data frame called cv.df using the 
#download_jhu_csse_covid19_data() function from the {tidycovid19} package.
#
cv.df <- download_jhu_csse_covid19_data(cached = TRUE)
Start downloading JHU CSSE Covid-19 data

Downloading cached version of JHU CSSE Covid 19 data...done. Timestamp is 2020-10-06 03:00:10

Data Info:

The COVID-19 Data Repository by the Johns Hopkins University Center for Systems
Science and Engineering (JHU CSSE) relies upon publicly available data from
multiple sources that do not always agree. It is updated daily. The data comes
in three data frames that you can select by the 'type' parameter. The 'country'
data frame contains the global country-level data reported by JHU CSSE by
aggregating over the regional data for countries that have regional data
available. The 'country_region' data frame provides regional data for the
countries that have regional data available (mosty Australia, Canada and China).
The 'us_county' data frame reports the data for the U.S. at the county level.
The column 'timestamp' reports the time the data was downloaded from its
authoritative source.

For further information refer to: https://github.com/CSSEGISandData/COVID-19.

Exercise 2.1: The dataframe which comprises all international covid-19 data recorded by John Hopkins since January 22, 2020 has 47545*7 observations (see the Environment Pane). Is this large? How much larger can R handle?

Explore the data

Let’s focus on the UK and then “eyeball” the data again.

# select only the UK data
cv.uk.df <- subset(cv.df, iso3c=="GBR")

head(cv.uk.df)
tail(cv.uk.df)

2. Exercise answers

2.1: Although ~47.5K observations might seem large in reality this only occopies 2.6Mb which is <0.1% of the capacity of R on a fairly standard laptop or PC.

2.2: Given the wide range of values for daily infections a log10 scale makes the plot easier to view, particularly for the smaller values.

2.3: There is a clear weekly cycle (or we can say the periodicity is 7-days). This is true of many countries. Why do you think this might be?

2.4: This shows the 95% confidence limit since there is an element of uncertainty as to exactly where the trend line should be. The broader the confidence limit band (shaded pale orange) the less confident we are about the exact location of the trend. Where the confidence limit potentially goes negative (which would be meaningless) we do not plot it. This principally occurs for the daily new death rate trend since many values are (mercifully) close to zero.

2.5: max(cv.uk.df$new.i)

2.6: Good luck!

2.7: new.i is not an integer? One way to find out is to use the built in function is.integer().

is.integer(cv.uk.df$new.i)
[1] FALSE

If you wanted new.i to be an integer you could need to code something like

cv.uk.df$new.i <- as.integer(cv.uk.df$new.i)

or make an assignment like cv.uk.df$new.i <- 10L where L is short for Long which is a long story!

2.8: cv.uk.df$recovered[236] Remember you need to use the $ operator to reference a particular vector (variable) in the dataframe cv.uk.df.

Exercise 2.9:

cv.uk.df$recovered[236] <- 0
LS0tCiMgVGhpcyBpcyB0aGUgWUFNTCBoZWFkZXIKdGl0bGU6ICJDUzU3MDIgVzIgU2VtaW5hciBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjogTWFydGluIFNoZXBwZXJkCmRhdGU6IDA2LzEwLzIwMjAKIyBUaGlzIGlzIHRoZSBlbmQgb2YgdGhlIFlBTUwgaGVhZGVyIAojICh1c2UgaXQgYXMgYSB0ZW1wbGF0ZSBmb3IgeW91ciBybWFya2Rvd24gZmlsZXMpCi0tLQoKIyMgU2VtaW5hciBMZWFybmluZyBHb2FscwoKMS4gW0FuYWx5c2UgY292aWQtMTkgZGF0YSB0cmVuZHNdKCNXMlMxKSAgCjIuIFtUbyBydW4gYW5kIGV4dGVuZCBzb21lIHNpbXBsZSBSIGNvZGUgdG8gY29tcHV0ZSBib29rIGluY29tZV0oI1cyUzIpICAKCjMuIFtFeGVyY2lzZSBhbnN3ZXJzXSgjVzJBKSAKCgojIzAuIFdvcmtzaGVldCBJbnRyb2R1Y3Rpb24KCjxzcGFuIHN0eWxlPSJjb2xvcjogZGFya29yYW5nZTsiPioqUHJlLXJlcXVpc2l0ZXMqKjwvc3Bhbj4KCllvdSBzaG91bGQ6ICAKCjEuIGhhdmUgY29tcGxldGVkIHRoZSBXZWVrIDEgSm9pbmluZyBTZW1pbmFyICAKMi4gaGF2ZSAocmUtKWFjcXVhaW50ZWQgeW91cnNlbGYgd2l0aCBXZWVrIDEgU2VtaW5hciB3b3Jrc2hlZXQgIAozLiBiZSBmYW1pbGlhciAobGlzdGVuZWQgdG8vcmVhZCkgdGhlIFdlZWsgMiBMZWN0dXJlICJUaGUgUmljaG5lc3Mgb2YgRGF0YSIgIAo0LiBiZSBhYmxlIHRvIHdyaXRlLCBlZGl0LCBzYXZlIGFuZCByZS1vcGVuIHlvdXIgb3duIFJNYXJrZG93biBmaWxlcwoKSWYgdGhpcyBpcyBwcm92aW5nIGEgPHNwYW4gc3R5bGU9ImNvbG9yOiBkYXJrb3JhbmdlOyI+KipjaGFsbGVuZ2UqKjwvc3Bhbj4gc2VlIFsiUHJlcmVxdWlzaXRlcyBmb3IgV2VlayAyIFNlbWluYXJzIGFuZCBMYWJzIChDUzU3MDEvMDIpIl0oaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL21qc2hlcHBlcmQvQ1M1NzAyLURhdGEvbWFzdGVyL0NTNTcwMl9XMl9TZW1fUHJlUmVxcy5wZGYpIGZvciBhZHZpY2UuCgpUaGlzIHNlbWluYXIgd29ya3NoZWV0IGlzIG9yZ2FuaXNlZCBhcyBhbiBSTWFya2Rvd24gZmlsZS4gIFlvdSBjYW4gKipyZWFkKiogaXQuICBZb3UgY2FuICoqcnVuKiogdGhlIGVtYmVkZGVkIFIgYW5kIHlvdSBjYW4gKiphZGQqKiB5b3VyIG93biBSLiAgSSBzdWdnZXN0IHlvdSBzYXZlIGl0IGFzIGFub3RoZXIgZmlsZSBzbywgaWYgbmVjZXNzYXJ5LCB5b3UgY2FuIHJldmVydCB0byB0aGUgb3JpZ2luYWwuICAKCldoZW5ldmVyIHlvdSBjbGljayAqKlByZXZpZXcqKiBpbiB0aGUgUlN0dWRpbyBtZW51IGl0IHdpbGwgcmVuZGVyIGludG8gbmljZWx5IGZvcm1hdHRlZCBodG1sIHdoaWNoIHlvdSBjYW4gbG9vayBhdCBpdCBpbiB0aGUgVmlld2luZyBXaW5kb3cgaW4gUlN0dWRpbyBvciBhbnkgd2ViIGJyb3dzZXIuICBZb3UgbWF5IGZpbmQgdGhpcyBlYXNpZXIgdG8gcmVhZCwgaG93ZXZlciwgeW91IG11c3QgZWRpdCB0aGUgLnJtZCBmaWxlLCBpLmUuLCB0aGUgUk1hcmtkb3duIGluIHRoZSBFZGl0IFBhbmUgaWYgeW91IHdhbnQgdG8gbWFrZSBhbnkgY2hhbmdlcy4gCgpSZW1lbWJlciwgeW91IGFyZSBlbmNvdXJhZ2VkIHRvIGV4cGxvcmUgYW5kIGV4cGVyaW1lbnQuICBDaGFuZ2Ugc29tZXRoaW5nIGFuZCBzZWUgd2hhdCBoYXBwZW5zIQoKQXMgcGVyIGxhc3Qgd2VlayB3ZSB3aWxsIGNvdmVyIGEgbG90IG9mIG5ldyBncm91bmQgYnV0IGRvbid0IGJlIGRpc2NvdXJhZ2VkLiAgV2Ugd2lsbCByZXZpc2l0IHRoZXNlIGNvbmNlcHRzIG92ZXIgdGhlIGZvbGxvd2luZyB3ZWVrcyB0byBoZWxwIHlvdSBjb25zb2xpZGF0ZSB5b3VyIHVuZGVyc3RhbmRpbmcuIAoKCiMjIDEuIFZpc3VhbGlzaW5nIGNvdmlkLTE5IGRhdGEgdHJlbmRzIHsjVzJTMX0KClRoaXMgZXhhbXBsZSBzaG93cyBob3cgd2UgY2FuIGZldGNoIGFuZCB2aXN1YWxpc2UgY292aWQtMTkgZGF0YSBmcm9tIEpvaG4gSG9wa2lucyBVbml2ZXJzaXR5IHZpYSBHaXRIdWIuCgojIyMgSW5pdGlhbGlzYXRpb24KCldlIG5lZWQgc29tZSBwYWNrYWdlcyBvdmVyIGFuZCBhYm92ZSBiYXNlIFIuICBTaW5jZSB3ZSBtYXkgbm90IGJlIHN1cmUgd2hldGhlciB0aGV5IGFyZSBhbHJlYWR5IGluc3RhbGxlZCB3ZSB0ZXN0IGZvciB0aGVpciBwcmVzZW5jZS4gIE1vc3QgcGFja2FnZXMgY29tZSBmcm9tIENSQU4gYW5kIGFyZSBlYXN5IHRvIGluc3RhbGwgdXNpbmcgYGluc3RhbGwucGFja2FnZXMoKWAgYnV0IHRoZSBwYWNrYWdlIGB7dGlkeWNvdmlkMTl9YCBpcyBvbiBHaXRIdWIgKGpvYWNoaW0tZ2Fzc2VuKSBzbyB3ZSBhbHNvIG5lZWQgYHtkZXZ0b29sc31gIGluIG9yZGVyIHRvIGluc3RhbGwgcGFja2FnZXMgdGhhdCBhcmVuJ3Qgb24gQ1JBTi4KClRoaXMgUiBjb2RlIG1heSBhcHBlYXIgZGF1bnRpbmcgYnV0IGRvbid0IHdvcnJ5LiAgV2Ugd2lsbCByZXZpc2l0IGl0IGluIGRldGFpbCBpbiBXZWVrIDMuICBGb3IgdGhlIHRpbWUgYmVpbmcgc2VlIGl0IGFzIGEgd2F5IHRvIGluc3RhbGwgYW5kIGxvYWQgbmVjZXNzYXJ5IGV4dHJhIGZ1bmN0aW9uYWxpdHkgYmV5b25kIGJhc2UgRVIuCgpgYGB7ciBtZXNzYWdlcz1GfQojIElmIGEgcGFja2FnZSBpcyBpbnN0YWxsZWQsIGl0IHdpbGwgYmUgbG9hZGVkIGFuZCBtaXNzaW5nIHBhY2thZ2Uocykgd2lsbCBiZSBpbnN0YWxsZWQgCiMgZnJvbSBDUkFOIGFuZCB0aGVuIGxvYWRlZC4KCiMgVGhlIHBhY2thZ2VzIHdlIG5lZWQgYXJlOgogCnBhY2thZ2VzID0gYygidGlkeXZlcnNlIiwgImRldnRvb2xzIikKCiMgTG9hZCB0aGUgcGFja2FnZSBvciBpbnN0YWxsIGFuZCBsb2FkIGl0CnBhY2thZ2UuY2hlY2sgPC0gbGFwcGx5KAogIHBhY2thZ2VzLAogIEZVTiA9IGZ1bmN0aW9uKHgpIHsKICAgIGlmICghcmVxdWlyZSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKSB7CiAgICAgIGluc3RhbGwucGFja2FnZXMoeCwgZGVwZW5kZW5jaWVzID0gVFJVRSkKICAgICAgbGlicmFyeSh4LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpCiAgICB9CiAgfQopCgppbnN0YWxsX2dpdGh1Yigiam9hY2hpbS1nYXNzZW4vdGlkeWNvdmlkMTkiKQpsaWJyYXJ5KHRpZHljb3ZpZDE5KQpgYGAKCkRvd25sb2FkIHRoZSBkYXRhIChjYWNoZWQgb24gR2l0SHViIHJhdGhlciB0aGFuIGRpcmVjdGx5IGZyb20gSm9obiBIb3BraW5zIFVuaXZlcnNpdHkpLiAgVGhpcyBpcyBsaXZlIGRhdGEgdXBkYXRlZCB3aXRoaW4gdGhlIGxhc3QgMjQgaG91cnMuICAKCmBgYHtyfQojRG93bmxvYWQgdGhlIGRhdGEgaW50byBhIGRhdGEgZnJhbWUgY2FsbGVkIGN2LmRmIHVzaW5nIHRoZSAKI2Rvd25sb2FkX2podV9jc3NlX2NvdmlkMTlfZGF0YSgpIGZ1bmN0aW9uIGZyb20gdGhlIHt0aWR5Y292aWQxOX0gcGFja2FnZS4KIwpjdi5kZiA8LSBkb3dubG9hZF9qaHVfY3NzZV9jb3ZpZDE5X2RhdGEoY2FjaGVkID0gVFJVRSkKYGBgCgoqKkV4ZXJjaXNlIDIuMToqKiBUaGUgZGF0YWZyYW1lIHdoaWNoIGNvbXByaXNlcyBhbGwgaW50ZXJuYXRpb25hbCBjb3ZpZC0xOSBkYXRhIHJlY29yZGVkIGJ5IEpvaG4gSG9wa2lucyBzaW5jZSBKYW51YXJ5IDIyLCAyMDIwIGhhcyA0NzU0NSo3IG9ic2VydmF0aW9ucyAoc2VlIHRoZSBFbnZpcm9ubWVudCBQYW5lKS4gIElzIHRoaXMgbGFyZ2U/ICBIb3cgbXVjaCBsYXJnZXIgY2FuIFIgaGFuZGxlPwoKIyMjIEV4cGxvcmUgdGhlIGRhdGEKCkxldCdzIGZvY3VzIG9uIHRoZSBVSyAgYW5kIHRoZW4gImV5ZWJhbGwiIHRoZSBkYXRhIGFnYWluLgoKYGBge3J9CiMgc2VsZWN0IG9ubHkgdGhlIFVLIGRhdGEKY3YudWsuZGYgPC0gc3Vic2V0KGN2LmRmLCBpc28zYz09IkdCUiIpCgpoZWFkKGN2LnVrLmRmKQp0YWlsKGN2LnVrLmRmKQpgYGAKCiMjIFNob3cgdHJlbmRzCgojIyMgTW9ydGFsaXR5IHJhdGUKCmBgYHtyfQojIENvbXB1dGUgbmV3IGRlYXRocyBhcyB0aGUgZGF0YSBzaG93cyBjdW11bGF0aXZlIGRlYXRocwpjdi51ay5kZiRuZXcuZFsyOm5yb3coY3YudWsuZGYpXSA8LSB0YWlsKGN2LnVrLmRmJGRlYXRocywgLTEpIC0gaGVhZChjdi51ay5kZiRkZWF0aHMsIC0xKQpjdi51ay5kZiRuZXcuZFsxXSA8LSAwICAgICAjIEFkZCB6ZXJvIGZvciBmaXJzdCByb3cgCgojIENvbXB1dGUgbmV3IGluZmVjdGlvbnMKY3YudWsuZGYkbmV3LmlbMjpucm93KGN2LnVrLmRmKV0gPC0gdGFpbChjdi51ay5kZiRjb25maXJtZWQsIC0xKSAtIGhlYWQoY3YudWsuZGYkY29uZmlybWVkLCAtMSkKY3YudWsuZGYkbmV3LmlbMV0gPC0gMCAgICAgIyBBZGQgemVybyBmb3IgZmlyc3Qgcm93IApgYGAKCldlIGNhbiBwcm9kdWNlIGEgcGxvdCBvZiBkYWlseSBhZGRpdGlvbmFsIGRlYXRocyB1c2luZyB0aGUge2dncGxvdH0gcGFja2FnZSB3aGljaCBpcyBhbiBleHRyZW1lbHkgcG93ZXJmdWwgYW5kIGZsZXhpYmxlIHNldCBvZiBmdW5jdGlvbnMgZm9yIHByb2R1Y2luZyBleHRyZW1lbHkgaGlnaCBxdWFsaXR5IGdyYXBoaWNzIGUuZy4gTllULCBHdWFyZGlhbiBhbmQgdGhlIEJCQy4gIFdlIGFsc28gc2F2ZSB0aGUgcGxvdHMgdXNpbmcgdGhlIGBnZ3NhdmUoKWAgZnVuY3Rpb24gd2hpY2ggaXMgYWxzbyBwYXJ0IG9mIHRoZSB7Z2dwbG90fSBwYWNrYWdlLgoKYGBge3J9CiMgTkIgYSBzbWFsbCBzcGFuIHZhbHVlICg8MSkgbWFrZXMgdGhlIGxvZXNzIHNtb290aGVyIG1vcmUgd2lnZ2x5IQpnZ3Bsb3QoZGF0YSA9IGN2LnVrLmRmLCBhZXMoeCA9IGRhdGUsIHkgPSBuZXcuZCkpICsKICBnZW9tX2xpbmUoY29sb3IgPSAic2t5Ymx1ZSIsIHNpemUgPSAwLjYpICsKICB5bGltKDAsMTIwMCkgKwogIHN0YXRfc21vb3RoKGNvbG9yID0gImRhcmtvcmFuZ2UiLCBmaWxsID0gImRhcmtvcmFuZ2UiLCBtZXRob2QgPSAibG9lc3MiLCBzcGFuID0gMC4yKSArCiAgZ2d0aXRsZSgiRGFpbHkgYWRkaXRpb25hbCBkZWF0aHMgaW4gdGhlIFVLIGR1ZSB0byBjb3ZpZC0xOSIpICsKICB4bGFiKCJEYXRlIikgKyB5bGFiKCJEYWlseSBuZXcgZGVhdGhzIikKZ2dzYXZlKCJjdjE5X1VLX2RlYXRocmF0ZS5wbmciKQpgYGAKCiMjIyBJbmZlY3Rpb24gcmF0ZQoKTm90ZSB0aGF0IHdlIHVzZSBhIGxvZyBzY2FsZSBmb3IgdGhlIHktYXhpcyBpZSBkYWlseSBuZXcgaW5mZWN0aW9uIHJhdGUuCgoqKkV4ZXJjaXNlIDIuMjoqKiBXaHkgZGlkIEkgY2hvb3NlIHRvIHVzZSBhIGxvZyBzY2FsZSBmb3IgZGFpbHkgbmV3IGluZmVjdGlvbiByYXRlPwoKYGBge3J9CmdncGxvdChkYXRhID0gY3YudWsuZGYsIGFlcyh4ID0gZGF0ZSwgeSA9IG5ldy5pKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJza3libHVlIiwgc2l6ZSA9IDAuNikgKwogIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpICsKICBzdGF0X3Ntb290aChjb2xvciA9ICJkYXJrb3JhbmdlIiwgZmlsbCA9ICJkYXJrb3JhbmdlIiwgbWV0aG9kID0gImxvZXNzIikgKwogIGdndGl0bGUoIkRhaWx5IG5ldyBpbmZlY3Rpb25zIGluIHRoZSBVSyBmcm9tIGNvdmlkLTE5IikgKwogIHhsYWIoIkRhdGUiKSArIHlsYWIoIkRhaWx5IG5ldyBpbmZlY3Rpb25zIikgCmdnc2F2ZSgiY3YxOV9VS19pbmZlY3Rpb25yYXRlLnBuZyIpCmBgYAoKVG8gYmV0dGVyIHZpc3VhbGlzZSB0aGUgdHJlbmRzIChpLmUuLCBvdmVyIHRpbWUpIHdlIHVzZSB0aGUgKipsb2VzcyoqIChsb2NhbGx5IGVzdGltYXRlZCBzY2F0dGVycGxvdCBzbW9vdGhpbmcpIHNtb290aGVyLiAgSXQgaXMgZGVzaWduZWQgdG8gZGV0ZWN0IHRyZW5kcyBpbiB0aGUgcHJlc2VuY2Ugb2Ygbm9pc3kgZGF0YSB3aGVuIHRoZSBzaGFwZSBvZiB0aGUgdHJlbmQgaXMgdW5rbm93biB0aHVzIGl0IGlzIGEgcm9idXN0IChub24tcGFyYW1ldHJpYykgbWV0aG9kLiAgCgoqKkV4ZXJjaXNlIDIuMzoqKiBJZiB5b3UgbG9vayBjYXJlZnVsbHkgYXQgdGhlIGRhdGEgdGhlcmUgaXMgYSBjbGVhciBjeWNsZSB3aXRoaW4gdGhlIG92ZXJhbGwgdHJlbmQuICBXaGF0IGlzIGl0IGFuZCB3aHk/ICBIb3cgc2hvdWxkIHdlIGRlYWwgd2l0aCBpdD8KCioqRXhlcmNpc2UgMi40OioqIFdoYXQgZG9lcyB0aGUgbGlnaHQgb3JhbmdlIHNoYWRlZCByZWdpb24gYXJvdW5kIHRoZSBzbW9vdGhlZCB0cmVuZCBsaW5lIG1lYW4/ICBXaHkgZG9lcyBpdCB2YXJ5IGluIGJyZWFkdGg/CgoqKkV4ZXJjaXNlIDIuNToqKiBXaGF0IHdhcyB0aGUgZ3JlYXRlc3QgbnVtYmVyIG9mIG5ldyBpbmZlY3Rpb25zIGluIG9uZSBkYXkgaW4gdGhlIFVLPyAgSElOVCB0aGVyZSBpcyBhIGJ1aWx0IGluIGZ1bmN0aW9uIGBtYXgoKWAgYW5kIHRoZSB5b3Ugd2lsbCBuZWVkIHRvIGV4YW1pbmUgdGhlIHZlY3RvciBgbmV3LmlgIHdoaWNoIGlzIHBhcnQgb2YgdGhlIGBjdi51ay5kZmAgZGF0YWZyYW1lIHNvIHlvdSB3aWxsIG5lZWQgdGhlIGAkYCBvcGVyYXRvci4gIAoKKipFeHRlbnNpb24gRXhlcmNpc2UgMi42OioqIEVkaXQgdGhlIFIgY29kZSB0byBwcm9kdWNlIGEgc2ltaWxhciB0cmVuZCBhbmFseXNpcyBmb3IgYW5vdGhlciBjb3VudHJ5IG9mIHlvdXIgY2hvaWNlLiAgTm90ZSB0aGF0IHRoZSBkYXRhIHNldCB1c2VzIDMgY2hhcmFjdGVyIGNvdW50cnkgY29kZXMgZS5nLiwgU1dFLCBVU0Egc2VlIFt3aWtpcGVkaWFdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lTT18zMTY2LTFfYWxwaGEtMykgZm9yIGEgY29tcGxldGUgbGlzdC4gIEhJTlQ6IHlvdSB3aWxsIG5lZWQgdG8gY2hhbmdlIHRoZSBzdWJzZXQgY29tbWFuZCBhbmQgcGVyaGFwcyBzYXZlIHRvIGEgbmV3IGRhdGFmcmFtZSBhbmQgdGhlbiBtYWtlIHN1cmUgeW91IHR1cm4gdGhlIGN1bW11bGF0aXZlIGNvdW50cyBpbnRvIG5ldyBjb3VudHMuCgoqKkV4ZXJjaXNlIDIuNzoqKiBJcyBgbmV3LmlgIGluIHRoZSBjdi51ay5kZiBkYXRhZnJhbWUgYW4gaW50ZWdlcj8gIAoKKipFeGVyY2lzZSAyLjg6KiogSG93IG1hbnkgcGVvcGxlIHJlY292ZXJlZCBpbiB0aGUgVUsgb24gdGhlIDIzNnRoIGRheSBvZiBkYXRhIGNvbGxlY3Rpb24uICBXcml0ZSBhbiBSIHN0YXRlbWVudCB0byBhbnN3ZXIuICAKCioqRXhlcmNpc2UgMi45OioqIFVwZGF0ZSB0aGUgbnVtYmVyIG9mIG5ldyBkZWF0aHMgb24gdGhlIDIzNnRoIGRheSB0byB6ZXJvLiAgCgohW0Fuc3dlcnM/XShodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vbWpzaGVwcGVyZC9DUzU3MDItRGF0YS9tYXN0ZXIvQW5zd2Vycy5wbmcpCgojIyAyLiBFeGVyY2lzZSBhbnN3ZXJzeyNXMkF9CgoyLjE6IEFsdGhvdWdoIH40Ny41SyBvYnNlcnZhdGlvbnMgbWlnaHQgc2VlbSBsYXJnZSBpbiByZWFsaXR5IHRoaXMgb25seSBvY2NvcGllcyAyLjZNYiB3aGljaCBpcyA8MC4xJSBvZiB0aGUgY2FwYWNpdHkgb2YgUiBvbiBhIGZhaXJseSBzdGFuZGFyZCBsYXB0b3Agb3IgUEMuCgoyLjI6IEdpdmVuIHRoZSB3aWRlIHJhbmdlIG9mIHZhbHVlcyBmb3IgZGFpbHkgaW5mZWN0aW9ucyBhIGxvZzEwIHNjYWxlIG1ha2VzIHRoZSBwbG90IGVhc2llciB0byB2aWV3LCBwYXJ0aWN1bGFybHkgZm9yIHRoZSBzbWFsbGVyIHZhbHVlcy4gCgoyLjM6IFRoZXJlIGlzIGEgY2xlYXIgd2Vla2x5IGN5Y2xlIChvciB3ZSBjYW4gc2F5IHRoZSBwZXJpb2RpY2l0eSBpcyA3LWRheXMpLiAgVGhpcyBpcyB0cnVlIG9mIG1hbnkgY291bnRyaWVzLiAgV2h5IGRvIHlvdSB0aGluayB0aGlzIG1pZ2h0IGJlPyAgCgoyLjQ6IFRoaXMgc2hvd3MgdGhlIDk1JSBjb25maWRlbmNlIGxpbWl0IHNpbmNlIHRoZXJlIGlzIGFuIGVsZW1lbnQgb2YgdW5jZXJ0YWludHkgYXMgdG8gZXhhY3RseSB3aGVyZSB0aGUgdHJlbmQgbGluZSBzaG91bGQgYmUuICBUaGUgYnJvYWRlciB0aGUgY29uZmlkZW5jZSBsaW1pdCBiYW5kIChzaGFkZWQgcGFsZSBvcmFuZ2UpIHRoZSBsZXNzIGNvbmZpZGVudCB3ZSBhcmUgYWJvdXQgdGhlIGV4YWN0IGxvY2F0aW9uIG9mIHRoZSB0cmVuZC4gIFdoZXJlIHRoZSBjb25maWRlbmNlIGxpbWl0IHBvdGVudGlhbGx5IGdvZXMgbmVnYXRpdmUgKHdoaWNoIHdvdWxkIGJlIG1lYW5pbmdsZXNzKSB3ZSBkbyBub3QgcGxvdCBpdC4gIFRoaXMgcHJpbmNpcGFsbHkgb2NjdXJzIGZvciB0aGUgZGFpbHkgbmV3IGRlYXRoIHJhdGUgdHJlbmQgc2luY2UgbWFueSB2YWx1ZXMgYXJlIChtZXJjaWZ1bGx5KSBjbG9zZSB0byB6ZXJvLiAgCgoyLjU6IGBtYXgoY3YudWsuZGYkbmV3LmkpYCAgCgoyLjY6IEdvb2QgbHVjayEgIAoKMi43OiBgbmV3LmlgIGlzIG5vdCBhbiBpbnRlZ2VyPyAgT25lIHdheSB0byBmaW5kIG91dCBpcyB0byB1c2UgdGhlIGJ1aWx0IGluIGZ1bmN0aW9uIGBpcy5pbnRlZ2VyKClgLgpgYGB7cn0KaXMuaW50ZWdlcihjdi51ay5kZiRuZXcuaSkKYGBgCgpJZiB5b3Ugd2FudGVkIGBuZXcuaWAgdG8gYmUgYW4gaW50ZWdlciB5b3UgY291bGQgbmVlZCB0byBjb2RlIHNvbWV0aGluZyBsaWtlCmBgYHtyfQpjdi51ay5kZiRuZXcuaSA8LSBhcy5pbnRlZ2VyKGN2LnVrLmRmJG5ldy5pKQpgYGAKb3IgbWFrZSBhbiBhc3NpZ25tZW50IGxpa2UgYGN2LnVrLmRmJG5ldy5pIDwtIDEwTGAgd2hlcmUgTCBpcyBzaG9ydCBmb3IgTG9uZyB3aGljaCBpcyBhIGxvbmcgc3RvcnkhICAKCjIuODogYGN2LnVrLmRmJHJlY292ZXJlZFsyMzZdYCAgUmVtZW1iZXIgeW91IG5lZWQgdG8gdXNlIHRoZSAkIG9wZXJhdG9yIHRvIHJlZmVyZW5jZSBhIHBhcnRpY3VsYXIgdmVjdG9yICh2YXJpYWJsZSkgaW4gdGhlIGRhdGFmcmFtZSBjdi51ay5kZi4KCkV4ZXJjaXNlIDIuOTogCgpgYGB7cn0KY3YudWsuZGYkcmVjb3ZlcmVkWzIzNl0gPC0gMApgYGAKCg==