Chapter 1: Getting Started

Install RStudio & Git

Chapter 2: Using the command line

Get comfortable using the terminal for navigation using commands like: ls, cd, mkdir Reference

Chapter 3: Version Control

A closer look at git/GitHub, make a repo, commit to it Here’s My Github

Chapter 4: Using Markdown for Documentation

All of the readmes for this project are made using markdown

Chapter 5: Introduction to R
print("Hello world!")
[1] "Hello world!"
Chapter 6: Functions
# Here's a function declaration
my_cool_function <- function(some_variable, another_variable){
  value_to_return <- some_variable + another_variable
  value_to_return # The value to be returned should be called as the last instruction
}

my_cool_function(10,5)
[1] 15
# Here is a function with a conditional statement
greet_user <- function(name){
  if (name == "Tom"){
    print("What is up, T-Dawg")
  } else {
    sprintf("Hello % s", name)
  }
}

greet_user("Tom")
[1] "What is up, T-Dawg"
greet_user("Joe Bloggs")
[1] "Hello Joe Bloggs"
Chapter 7: Vectors

A vector is a collection of data, like a list of numbers or names or dates of birth. R is a popular data science language as the majority of functions and tools are built to work with vectorised data.

cat("A vector    : ",a_vector, "\nA vector * 2: ", a_vector *2)
A vector    :  1 2 3 4 5 
A vector * 2:  2 4 6 8 10

This approach scales up very well for working with big databases! It’s both easier to follow logically and more efficient in terms of computer processing!

Chapter 8: Lists

Lists are essentially a vector that can hold multiple data types, useful for working with related data.

some_employee <- list(
  forename = "Joe",
  surname = "Bloggs",
  job = "CEO",
  salary = 999999,
  union_member = TRUE
)

some_employee$surname
[1] "Bloggs"
some_employee[2]
$surname
[1] "Bloggs"
some_employee[["surname"]]
[1] "Bloggs"
Chapter 9: Understanding Data

A more general topic about the world of data, covers topics such as:

Chapter 10: Data Frames

Data frames are one of the most common ways to work with data, any table is a data frame, an Excel spreadsheet is a data frame.

Chapter 11: Manipulating data with dplyr

dplyr is a very useful and popular package for wrangling data, it has a consistent “Grammar of data manipulation” * Select specific features * Filter out what you don’t want * Mutate a data set by creating new features * Arrange observations in some way * Summarize data in terms of aggregates (e.g. mean, median, range, max value) * Join data sets together

Chapter 12: Reshaping Data with tidyr

Tidy Data: 1. Each variable is in a column 2. Each observation is a row 3. Each value is a cell

gather() # To make your data long
spread() # To make your data wide
Chapter 13: Accessing Databases

A little intro into using SQL and some info about relational databases. Relational databases are pretty much a necessity for working with more complex data structures, requiring information to be stored in different places for different reasons. An example would be a music library, it is much more scalable to have a big database of artists and a separate big database of songs, pulling the necessary data as needed rather than having it all in one huge mess. R can be used to work with databases, like so:

Chapter 14: Accessing Web APIs

APIs are a very useful tool to access data, it allows companies to share data in a secure way and allows developers to make specific data requests instead of downloading entire databases systems to their local machine and processing it from there! API data can be a bit fiddly, as it may be in one of several different formats (commonly JSON or YAML) and will likely arrive as nested dataframes which can be difficult to keep track of.

```{r, echo=FALSE}
Error: attempt to use zero-length variable name

Once you have the data in a usable form, it’s business as usual.

Chapter 15: Designing Data Visualisations

“The purpose of visualisation is insight, not pictures” - Card, S.K., Mackinlay, J.D., & Shneiderman B. (1999)

As much as I like pretty graphs, they are in practice a means to an end, and that end is communicating insights in an efficient manner.

It is important to remember what you are trying to do with a graph, What is the specific question of interest you are attempting to answer? What layout of data is most suitable for this? What graphical encodings give the best perceptability to the data? (What colours show the best?) Would a preattentive attribute work best? (Colour one point, use a different shape, draw a box around an area etc.)

To make beautiful charts, remove clutter, don’t add design.

Chapter 16: Creating Visualisations with ggplot2

There a bunch of different plotting styles and colour palettes and co-ordinate systems, each graph will require consideration on how best to display the data, then ggplot can be given the data and instructions to produce that graph.

Chapter 17: Interactive Visualisation in R

There are a few packages that give you “interactive” graphs very easily! plotly, rbokeh and leaflet are covered in the book. In short: plotly and rbokeh are pretty similar, leaflet is good for maps.

Chapter 18: Dynamic Reports with R Markdown

This whole recap was written in R markdown! It can also do inline commands too, for example:` Code

becomes: I love exponents, 1024 is a great one!

Chapter 19: Building Interactive Web Applications with Shiny

This was a fun chapter, shiny allows you to build simple websites with code. The layouts are created with different objects like titlePanel(), sidebarPanel() etc, then the content is rendered into a webpage!

It’s considered best practice to split the website into separate files, a UI file, a server file, and an app.R file that brings them together.

setwd("~/GitHub/R-Practice")
# app.R
source("shiny/my_ui_file.R") # Creates "my_ui"
source("shiny/my_server_file.R") # Creates "my_server"
shinyApp(ui = my_ui, server = my_server)

# This website may be ugly, but it does work!

Here’s a demo of the website: Website Demo

LS0tDQp0aXRsZTogIk5vdmVtYmVyIFJlY2FwIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMjIyMgKioqQ2hhcHRlciAxOiBHZXR0aW5nIFN0YXJ0ZWQqKioNCkluc3RhbGwgW1JTdHVkaW9dKGh0dHBzOi8vcG9zaXQuY28vZG93bmxvYWRzLykgJiBbR2l0XShodHRwczovL2dpdGZvcndpbmRvd3Mub3JnLykNCg0KIyMjIyMgKioqQ2hhcHRlciAyOiBVc2luZyB0aGUgY29tbWFuZCBsaW5lKioqDQpHZXQgY29tZm9ydGFibGUgdXNpbmcgdGhlIHRlcm1pbmFsIGZvciBuYXZpZ2F0aW9uIHVzaW5nIGNvbW1hbmRzIGxpa2U6IGxzLCBjZCwgbWtkaXINCltSZWZlcmVuY2VdKGh0dHBzOi8vcmlwdHV0b3JpYWwuY29tL3Rlcm1pbmFsL2V4YW1wbGUvMjYwMjMvYmFzaWMtbmF2aWdhdGlvbi1jb21tYW5kcykNCg0KIyMjIyMgKioqQ2hhcHRlciAzOiBWZXJzaW9uIENvbnRyb2wqKioNCkEgY2xvc2VyIGxvb2sgYXQgZ2l0L0dpdEh1YiwgbWFrZSBhIHJlcG8sIGNvbW1pdCB0byBpdA0KSGVyZSdzIFtNeSBHaXRodWJdKGh0dHBzOi8vZ2l0aHViLmNvbS9Ub21qb2huc29uZWxsaXMpDQoNCiMjIyMjICoqKkNoYXB0ZXIgNDogVXNpbmcgTWFya2Rvd24gZm9yIERvY3VtZW50YXRpb24qKioNCkFsbCBvZiB0aGUgcmVhZG1lcyBmb3IgdGhpcyBwcm9qZWN0IGFyZSBtYWRlIHVzaW5nIG1hcmtkb3duDQoNCiMjIyMjICoqKkNoYXB0ZXIgNTogSW50cm9kdWN0aW9uIHRvIFIqKioNCg0KYGBge3J9DQpwcmludCgiSGVsbG8gd29ybGQhIikNCg0KP2Z1bmN0aW9uICMgQnJpbmdzIHVwIGhlbHBmdWwgaW5mbw0KVFJVRSArIEZBTFNFICMgQm9vbGVhbnMNCmBgYA0KDQojIyMjIyAqKipDaGFwdGVyIDY6IEZ1bmN0aW9ucyoqKg0KYGBge3J9DQojIEhlcmUncyBhIGZ1bmN0aW9uIGRlY2xhcmF0aW9uDQpteV9jb29sX2Z1bmN0aW9uIDwtIGZ1bmN0aW9uKHNvbWVfdmFyaWFibGUsIGFub3RoZXJfdmFyaWFibGUpew0KICB2YWx1ZV90b19yZXR1cm4gPC0gc29tZV92YXJpYWJsZSArIGFub3RoZXJfdmFyaWFibGUNCiAgdmFsdWVfdG9fcmV0dXJuICMgVGhlIHZhbHVlIHRvIGJlIHJldHVybmVkIHNob3VsZCBiZSBjYWxsZWQgYXMgdGhlIGxhc3QgaW5zdHJ1Y3Rpb24NCn0NCg0KbXlfY29vbF9mdW5jdGlvbigxMCw1KQ0KDQojIEhlcmUgaXMgYSBmdW5jdGlvbiB3aXRoIGEgY29uZGl0aW9uYWwgc3RhdGVtZW50DQpncmVldF91c2VyIDwtIGZ1bmN0aW9uKG5hbWUpew0KICBpZiAobmFtZSA9PSAiVG9tIil7DQogICAgcHJpbnQoIldoYXQgaXMgdXAsIFQtRGF3ZyIpDQogIH0gZWxzZSB7DQogICAgc3ByaW50ZigiSGVsbG8gJSBzIiwgbmFtZSkNCiAgfQ0KfQ0KDQpncmVldF91c2VyKCJUb20iKQ0KZ3JlZXRfdXNlcigiSm9lIEJsb2dncyIpDQpgYGANCg0KIyMjIyMgKioqQ2hhcHRlciA3OiBWZWN0b3JzKioqDQpBIHZlY3RvciBpcyBhIGNvbGxlY3Rpb24gb2YgZGF0YSwgbGlrZSBhIGxpc3Qgb2YgbnVtYmVycyBvciBuYW1lcyBvciBkYXRlcyBvZiBiaXJ0aC4NClIgaXMgYSBwb3B1bGFyIGRhdGEgc2NpZW5jZSBsYW5ndWFnZSBhcyB0aGUgbWFqb3JpdHkgb2YgZnVuY3Rpb25zIGFuZCB0b29scyBhcmUgYnVpbHQgdG8gd29yayB3aXRoIHZlY3RvcmlzZWQgZGF0YS4NCmBgYHtyfQ0KYV92ZWN0b3IgPC0gYygxLDIsMyw0LDUpDQphX3ZlY3Rvcg0KYV92ZWN0b3IgKiAyDQpgYGANClRoaXMgYXBwcm9hY2ggc2NhbGVzIHVwIHZlcnkgd2VsbCBmb3Igd29ya2luZyB3aXRoIGJpZyBkYXRhYmFzZXMhIEl0J3MgYm90aCBlYXNpZXIgdG8gZm9sbG93IGxvZ2ljYWxseSBhbmQgbW9yZSBlZmZpY2llbnQgaW4gdGVybXMgb2YgY29tcHV0ZXIgcHJvY2Vzc2luZyENCg0KIyMjIyMgKioqQ2hhcHRlciA4OiBMaXN0cyoqKg0KTGlzdHMgYXJlIGVzc2VudGlhbGx5IGEgdmVjdG9yIHRoYXQgY2FuIGhvbGQgbXVsdGlwbGUgZGF0YSB0eXBlcywgdXNlZnVsIGZvciB3b3JraW5nIHdpdGggcmVsYXRlZCBkYXRhLg0KYGBge3J9DQpzb21lX2VtcGxveWVlIDwtIGxpc3QoDQogIGZvcmVuYW1lID0gIkpvZSIsDQogIHN1cm5hbWUgPSAiQmxvZ2dzIiwNCiAgam9iID0gIkNFTyIsDQogIHNhbGFyeSA9IDk5OTk5OSwNCiAgdW5pb25fbWVtYmVyID0gVFJVRQ0KKQ0KDQpzb21lX2VtcGxveWVlJHN1cm5hbWUNCnNvbWVfZW1wbG95ZWVbMl0NCnNvbWVfZW1wbG95ZWVbWyJzdXJuYW1lIl1dDQpgYGANCg0KIyMjIyMgKioqQ2hhcHRlciA5OiBVbmRlcnN0YW5kaW5nIERhdGEqKioNCkEgbW9yZSBnZW5lcmFsIHRvcGljIGFib3V0IHRoZSB3b3JsZCBvZiBkYXRhLCBjb3ZlcnMgdG9waWNzIHN1Y2ggYXM6DQoNCiogV2hlcmUgZGF0YSBjb21lcyBmcm9tOg0KICArIFNlbnNvcnMNCiAgKyBTdXJ2ZXlzDQogICsgUmVjb3JkIGtlZXBpbmcNCiogV2hlcmUgdG8gZmluZCBkYXRhOg0KICArIEdvdmVybm1lbnQgcHVibGljYXRpb25zIChCaWcgdXAgdGhlIE9OUykNCiAgKyBOZXdzcGFwZXJzL0pvdXJuYWxpc3RzDQogICsgU2NpZW50aWZpYyByZXNlYXJjaA0KICArIFNvY2lhbCBtZWRpYQ0KICArIE9ubGluZSBjb21tdW5pdGllcw0KKiBEaWZmZXJlbnQgdHlwZXMgb2YgZGF0YToNCiAgKyBOb21pbmFsIChhcHBsZXMgYW5kIG9yYW5nZXMpDQogICsgT3JkaW5hbCAoNSBzdGFyIHJhdGluZywgNCBzdGFyIHJhdGluZykNCiAgKyBSYXRpby9Db250aW51b3VzIChPcmRlcmVkIHdpdGggYSBmaXhlZCAwKQ0KICArIEludGVydmFsIChPcmRlcmVkIGJ1dCBubyBmaXhlZCAwKQ0KDQojIyMjIyAqKipDaGFwdGVyIDEwOiBEYXRhIEZyYW1lcyoqKg0KRGF0YSBmcmFtZXMgYXJlIG9uZSBvZiB0aGUgbW9zdCBjb21tb24gd2F5cyB0byB3b3JrIHdpdGggZGF0YSwgYW55IHRhYmxlIGlzIGEgZGF0YSBmcmFtZSwgYW4gRXhjZWwgc3ByZWFkc2hlZXQgaXMgYSBkYXRhIGZyYW1lLg0KYGBge3J9DQpuYW1lIDwtIGMoIkFsaWNlIiwiQm9iIiwiQ2h1Y2tpZSIsIkR5bGFuIikNCmhlaWdodCA8LSBjKDEwMCwxNTAsMTc1LDc1KQ0Kd2VpZ2h0IDwtIGMoNTAsNzUsMTAwLDIwMCkNCg0KbXlfZGF0YWZyYW1lIDwtIGRhdGEuZnJhbWUobmFtZSwgaGVpZ2h0LCB3ZWlnaHQpDQpteV9kYXRhZnJhbWUNCg0KYGBgDQoNCiMjIyMjICoqKkNoYXB0ZXIgMTE6IE1hbmlwdWxhdGluZyBkYXRhIHdpdGggZHBseXIqKioNCmRwbHlyIGlzIGEgdmVyeSB1c2VmdWwgYW5kIHBvcHVsYXIgcGFja2FnZSBmb3Igd3JhbmdsaW5nIGRhdGEsIGl0IGhhcyBhIGNvbnNpc3RlbnQgIkdyYW1tYXIgb2YgZGF0YSBtYW5pcHVsYXRpb24iDQoqICpTZWxlY3QqIHNwZWNpZmljIGZlYXR1cmVzDQoqICpGaWx0ZXIqIG91dCB3aGF0IHlvdSBkb24ndCB3YW50DQoqICpNdXRhdGUqIGEgZGF0YSBzZXQgYnkgY3JlYXRpbmcgbmV3IGZlYXR1cmVzDQoqICpBcnJhbmdlKiBvYnNlcnZhdGlvbnMgaW4gc29tZSB3YXkNCiogKlN1bW1hcml6ZSogZGF0YSBpbiB0ZXJtcyBvZiBhZ2dyZWdhdGVzIChlLmcuIG1lYW4sIG1lZGlhbiwgcmFuZ2UsIG1heCB2YWx1ZSkNCiogKkpvaW4qIGRhdGEgc2V0cyB0b2dldGhlcg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbXlfZGF0YWZyYW1lICU+JQ0KICBmaWx0ZXIod2VpZ2h0IDwgMjAwKSAlPiUNCiAgbXV0YXRlKCJCTUkiID0gd2VpZ2h0IC8gKGhlaWdodC8xMDApXjIpICU+JQ0KICBzZWxlY3QobmFtZSwgQk1JKQ0KDQpgYGANCg0KIyMjIyMgKioqQ2hhcHRlciAxMjogUmVzaGFwaW5nIERhdGEgd2l0aCB0aWR5cioqKg0KVGlkeSBEYXRhOg0KMS4gRWFjaCB2YXJpYWJsZSBpcyBpbiBhIGNvbHVtbg0KMi4gRWFjaCBvYnNlcnZhdGlvbiBpcyBhIHJvdw0KMy4gRWFjaCB2YWx1ZSBpcyBhIGNlbGwNCmBgYHtyfQ0KZ2F0aGVyKCkgIyBUbyBtYWtlIHlvdXIgZGF0YSBsb25nDQpzcHJlYWQoKSAjIFRvIG1ha2UgeW91ciBkYXRhIHdpZGUNCmBgYA0KDQojIyMjIyAqKipDaGFwdGVyIDEzOiBBY2Nlc3NpbmcgRGF0YWJhc2VzKioqDQpBIGxpdHRsZSBpbnRybyBpbnRvIHVzaW5nIFNRTCBhbmQgc29tZSBpbmZvIGFib3V0IHJlbGF0aW9uYWwgZGF0YWJhc2VzLg0KUmVsYXRpb25hbCBkYXRhYmFzZXMgYXJlIHByZXR0eSBtdWNoIGEgbmVjZXNzaXR5IGZvciB3b3JraW5nIHdpdGggbW9yZSBjb21wbGV4IGRhdGEgc3RydWN0dXJlcywgcmVxdWlyaW5nIGluZm9ybWF0aW9uIHRvIGJlIHN0b3JlZCBpbiBkaWZmZXJlbnQgcGxhY2VzIGZvciBkaWZmZXJlbnQgcmVhc29ucy4gQW4gZXhhbXBsZSB3b3VsZCBiZSBhIG11c2ljIGxpYnJhcnksIGl0IGlzIG11Y2ggbW9yZSBzY2FsYWJsZSB0byBoYXZlIGEgYmlnIGRhdGFiYXNlIG9mIGFydGlzdHMgYW5kIGEgc2VwYXJhdGUgYmlnIGRhdGFiYXNlIG9mIHNvbmdzLCBwdWxsaW5nIHRoZSBuZWNlc3NhcnkgZGF0YSBhcyBuZWVkZWQgcmF0aGVyIHRoYW4gaGF2aW5nIGl0IGFsbCBpbiBvbmUgaHVnZSBtZXNzLg0KUiBjYW4gYmUgdXNlZCB0byB3b3JrIHdpdGggZGF0YWJhc2VzLCBsaWtlIHNvOg0KYGBge3J9DQpsaWJyYXJ5KCJSU1FMaXRlIikgIyBBbiBTUUwgcGFja2FnZQ0KbGlicmFyeSgiZHBseXIiKSAjIEdvb2Qgb2wnIGRwbHlyDQoNCiMgQ29ubmVjdCB0byBhIGRhdGFiYXNlDQpkYXRhYmFzZV9jb25uZWN0aW9uIDwtIGRiQ29ubmVjdChTUUxpdGUoKSwgZGJuYW1lID0gIn4vR2l0SHViL1ItUHJhY3RpY2UvRXhlcmNpc2VzL2NoYXB0ZXItMTMvZGF0YS9DaGlub29rX1NxbGl0ZS5zcWxpdGUiKQ0KDQojIEhhdmUgYSBsb29rIGF0IHRoZSBhdmFpbGFibGUgdGFibGVzDQojIGRiTGlzdFRhYmxlcyhkYXRhYmFzZV9jb25uZWN0aW9uKQ0KDQojICJjb2xsZWN0IiB0aGUgaW5mbyBpbiBhIHRhYmxlIGFuZCBwdXQgaXQgaW50byBhIGRhdGFmcmFtZSwgb3VyIHByZWZlcnJlZCB0aGluZyB0byB1c2UNCnRyYWNrX2RmIDwtIGNvbGxlY3QodGJsKGRhdGFiYXNlX2Nvbm5lY3Rpb24sICJUcmFjayIpKQ0KDQojIEhhdmUgYSBsb29rIGxpa2Ugbm9ybWFsIQ0KI2RmJE5hbWVbMTo1XQ0KDQojIExldCdzIGZpbmQgYWxsIHRoZSBzb25ncyBvZiBhIHBhcnRpY3VsYXIgZ2VucmUNCmdlbnJlX2RmIDwtIGNvbGxlY3QodGJsKGRhdGFiYXNlX2Nvbm5lY3Rpb24sICJHZW5yZSIpKQ0KIyBnZW5yZV9kZiROYW1lICMgVGhlcmUncyAyNSwgSSdsbCBwaWNrICJFbGVjdHJvbmljYS9EYW5jZSINCiMgV2UgbmVlZCB0byB1c2UgdGhlICJBcnRpc3QgSUQiIG9mIHRoaXMgYXJ0aXN0IHRvIGZpbmQgdGhlIHNvbmdzIHRoZXkgYXJlIGNyZWRpdGVkIHdpdGgNCmlkX3RvX3VzZSA8LSBnZW5yZV9kZiAlPiUNCiAgZmlsdGVyKE5hbWUgPT0gIkVsZWN0cm9uaWNhL0RhbmNlIikgJT4lDQogIHNlbGVjdChHZW5yZUlkKQ0KDQpyZXN1bHRzIDwtIHRyYWNrX2RmICU+JQ0KICBmaWx0ZXIoR2VucmVJZCA9PSBpZF90b191c2UkR2VucmVJZCkgJT4lDQogIGFycmFuZ2UoLU1pbGxpc2Vjb25kcykgJT4lICMgTG9uZ2VzdCBzb25nIHRvIHNob3J0ZXN0IHNvbmcNCiAgc2VsZWN0KE5hbWUsIENvbXBvc2VyKQ0KDQojIEhlcmUncyB0aGUgNSBsb25nZXN0IEVsZWN0cm9uaWMgc29uZ3MgaW4gdGhlIGRhdGFiYXNlDQpoZWFkKHJlc3VsdHMsIDUpDQojIFRoZXkncmUgYWxyaWdodCwgSSBsaXN0ZW5lZCB0byB0aGVtIHdoaWxlIHdyaXRpbmcgdGhlIG5leHQgY2hhcHRlciBvZiB0aGlzIHJlY2FwIQ0KDQojIEZpbmFsbHksIGNsb3NlIHRoZSBjb25uZWN0aW9uDQpkYkRpc2Nvbm5lY3QoZGF0YWJhc2VfY29ubmVjdGlvbikNCg0KYGBgDQoNCiMjIyMjICoqKkNoYXB0ZXIgMTQ6IEFjY2Vzc2luZyBXZWIgQVBJcyoqKg0KQVBJcyBhcmUgYSB2ZXJ5IHVzZWZ1bCB0b29sIHRvIGFjY2VzcyBkYXRhLCBpdCBhbGxvd3MgY29tcGFuaWVzIHRvIHNoYXJlIGRhdGEgaW4gYSBzZWN1cmUgd2F5IGFuZCBhbGxvd3MgZGV2ZWxvcGVycyB0byBtYWtlIHNwZWNpZmljIGRhdGEgcmVxdWVzdHMgaW5zdGVhZCBvZiBkb3dubG9hZGluZyBlbnRpcmUgZGF0YWJhc2VzIHN5c3RlbXMgdG8gdGhlaXIgbG9jYWwgbWFjaGluZSBhbmQgcHJvY2Vzc2luZyBpdCBmcm9tIHRoZXJlIQ0KQVBJIGRhdGEgY2FuIGJlIGEgYml0IGZpZGRseSwgYXMgaXQgbWF5IGJlIGluIG9uZSBvZiBzZXZlcmFsIGRpZmZlcmVudCBmb3JtYXRzIChjb21tb25seSBKU09OIG9yIFlBTUwpIGFuZCB3aWxsIGxpa2VseSBhcnJpdmUgYXMgbmVzdGVkIGRhdGFmcmFtZXMgd2hpY2ggY2FuIGJlIGRpZmZpY3VsdCB0byBrZWVwIHRyYWNrIG9mLg0KYGBge3J9DQpsaWJyYXJ5KCJqc29ubGl0ZSIpDQojIEEgdHlwaWNhbCByZXF1ZXN0IHdvdWxkIGxvb2sgbGlrZSB0aGlzOg0KIyBHRVQgc29tZSBkYXRhDQpyZXNwb25zZSA8LSBHRVQodXJpX29mX3RoZV9kYXRhLCBxdWVyeSA9IG15X3F1ZXJ5X3BhcmFtZXRlcnMpDQojIEV4dHJhY3QgdGhlIENPTlRFTlQgb2YgdGhlIHJlc3BvbnNlIHlvdSBnZXQNCnJlc3BvbnNlX3RleHQgPC0gY29udGVudChyZXNwb25zZSwgInRleHQiKQ0KIyBUdXJuIHRoZSBKU09OIGRhdGEgaW50byBhIGxpc3QNCnJlc3BvbnNlX2RhdGEgPC0gZnJvbUpTT04ocmVzcG9uc2VfdGV4dCkNCiMgWW91J2xsIGxpa2VseSBlbmQgdXAgd2l0aCBhIGRhdGFmcmFtZSBvZiBjb2x1bW5zIHdoaWNoIGFyZSBhbHNvIGRhdGFmcmFtZXMsIG1lc3N5IQ0KIyBTbyBGTEFUVEVOIGl0IQ0KZmxhdHRlbihyZXNwb25zZV9kYXRhKQ0KYGBgDQpPbmNlIHlvdSBoYXZlIHRoZSBkYXRhIGluIGEgdXNhYmxlIGZvcm0sIGl0J3MgYnVzaW5lc3MgYXMgdXN1YWwuDQoNCiMjIyMjICoqKkNoYXB0ZXIgMTU6IERlc2lnbmluZyBEYXRhIFZpc3VhbGlzYXRpb25zKioqDQpfIlRoZSBwdXJwb3NlIG9mIHZpc3VhbGlzYXRpb24gaXMgaW5zaWdodCwgbm90IHBpY3R1cmVzIl8NCi0gQ2FyZCwgUy5LLiwgTWFja2lubGF5LCBKLkQuLCAmIFNobmVpZGVybWFuIEIuICgxOTk5KQ0KDQpBcyBtdWNoIGFzIEkgbGlrZSBwcmV0dHkgZ3JhcGhzLCB0aGV5IGFyZSBpbiBwcmFjdGljZSBhIG1lYW5zIHRvIGFuIGVuZCwgYW5kIHRoYXQgZW5kIGlzIGNvbW11bmljYXRpbmcgaW5zaWdodHMgaW4gYW4gZWZmaWNpZW50IG1hbm5lci4NCg0KSXQgaXMgaW1wb3J0YW50IHRvIHJlbWVtYmVyIHdoYXQgeW91IGFyZSB0cnlpbmcgdG8gZG8gd2l0aCBhIGdyYXBoLA0KV2hhdCBpcyB0aGUgX3NwZWNpZmljXyBxdWVzdGlvbiBvZiBpbnRlcmVzdCB5b3UgYXJlIGF0dGVtcHRpbmcgdG8gYW5zd2VyPw0KV2hhdCBsYXlvdXQgb2YgZGF0YSBpcyBtb3N0IHN1aXRhYmxlIGZvciB0aGlzPw0KV2hhdCBncmFwaGljYWwgZW5jb2RpbmdzIGdpdmUgdGhlIGJlc3QgcGVyY2VwdGFiaWxpdHkgdG8gdGhlIGRhdGE/IChXaGF0IGNvbG91cnMgc2hvdyB0aGUgYmVzdD8pDQpXb3VsZCBhIHByZWF0dGVudGl2ZSBhdHRyaWJ1dGUgd29yayBiZXN0PyAoQ29sb3VyIG9uZSBwb2ludCwgdXNlIGEgZGlmZmVyZW50IHNoYXBlLCBkcmF3IGEgYm94IGFyb3VuZCBhbiBhcmVhIGV0Yy4pDQoNClRvIG1ha2UgYmVhdXRpZnVsIGNoYXJ0cywgcmVtb3ZlIGNsdXR0ZXIsIGRvbid0IGFkZCBkZXNpZ24uDQoNCiMjIyMjICoqKkNoYXB0ZXIgMTY6IENyZWF0aW5nIFZpc3VhbGlzYXRpb25zIHdpdGggZ2dwbG90MioqKg0KYGBge3J9DQpsaWJyYXJ5KCJnZ3Bsb3QyIikNCnggPC0gYygxLDIsMyw0LDUsNiw3LDgsOSwxMCkNCnkgPC0gYygxLDQsOSwxNiwyNSwzNiw0OSw2NCw4MSwxMDApDQpkZiA8LSBkYXRhLmZyYW1lKHgseSkNCg0KZ2dwbG90KGRhdGEgPSBkZiwgYWVzKHgseSkpICsNCiAgZ2VvbV9saW5lKGNvbG9yID0gInB1cnBsZSIsIGxpbmV3aWR0aD0yKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDUsc2hhcGUgPSAxNikgKw0KICBnZ3RpdGxlKCJBbiB1Z2x5IGdyYXBoIG9mIHNxdWFyZSBudW1iZXJzIikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0geCkNCmBgYA0KDQpUaGVyZSBhIGJ1bmNoIG9mIGRpZmZlcmVudCBwbG90dGluZyBzdHlsZXMgYW5kIGNvbG91ciBwYWxldHRlcyBhbmQgY28tb3JkaW5hdGUgc3lzdGVtcywgZWFjaCBncmFwaCB3aWxsIHJlcXVpcmUgY29uc2lkZXJhdGlvbiBvbiBob3cgYmVzdCB0byBkaXNwbGF5IHRoZSBkYXRhLCB0aGVuIGdncGxvdCBjYW4gYmUgZ2l2ZW4gdGhlIGRhdGEgYW5kIGluc3RydWN0aW9ucyB0byBwcm9kdWNlIHRoYXQgZ3JhcGguDQoNCiMjIyMjICoqKkNoYXB0ZXIgMTc6IEludGVyYWN0aXZlIFZpc3VhbGlzYXRpb24gaW4gUioqKg0KVGhlcmUgYXJlIGEgZmV3IHBhY2thZ2VzIHRoYXQgZ2l2ZSB5b3UgImludGVyYWN0aXZlIiBncmFwaHMgdmVyeSBlYXNpbHkhDQpwbG90bHksIHJib2tlaCBhbmQgbGVhZmxldCBhcmUgY292ZXJlZCBpbiB0aGUgYm9vay4NCkluIHNob3J0OiBwbG90bHkgYW5kIHJib2tlaCBhcmUgcHJldHR5IHNpbWlsYXIsIGxlYWZsZXQgaXMgZ29vZCBmb3IgbWFwcy4NCg0KIyMjIyMgKioqQ2hhcHRlciAxODogRHluYW1pYyBSZXBvcnRzIHdpdGggUiBNYXJrZG93bioqKg0KVGhpcyB3aG9sZSByZWNhcCB3YXMgd3JpdHRlbiBpbiBSIG1hcmtkb3duIQ0KSXQgY2FuIGFsc28gZG8gaW5saW5lIGNvbW1hbmRzIHRvbywgZm9yIGV4YW1wbGU6YA0KIVtDb2RlXShpbWcvY29kZS5QTkcpDQoNCmJlY29tZXM6IEkgbG92ZSBleHBvbmVudHMsIGByIDJeMTBgIGlzIGEgZ3JlYXQgb25lIQ0KDQojIyMjIyAqKipDaGFwdGVyIDE5OiBCdWlsZGluZyBJbnRlcmFjdGl2ZSBXZWIgQXBwbGljYXRpb25zIHdpdGggU2hpbnkqKioNClRoaXMgd2FzIGEgZnVuIGNoYXB0ZXIsIHNoaW55IGFsbG93cyB5b3UgdG8gYnVpbGQgc2ltcGxlIHdlYnNpdGVzIHdpdGggY29kZS4NClRoZSBsYXlvdXRzIGFyZSBjcmVhdGVkIHdpdGggZGlmZmVyZW50IG9iamVjdHMgbGlrZSB0aXRsZVBhbmVsKCksIHNpZGViYXJQYW5lbCgpIGV0YywgdGhlbiB0aGUgY29udGVudCBpcyByZW5kZXJlZCBpbnRvIGEgd2VicGFnZSENCg0KSXQncyBjb25zaWRlcmVkIGJlc3QgcHJhY3RpY2UgdG8gc3BsaXQgdGhlIHdlYnNpdGUgaW50byBzZXBhcmF0ZSBmaWxlcywgYSBVSSBmaWxlLCBhIHNlcnZlciBmaWxlLCBhbmQgYW4gYXBwLlIgZmlsZSB0aGF0IGJyaW5ncyB0aGVtIHRvZ2V0aGVyLg0KDQpgYGB7cn0NCnNldHdkKCJ+L0dpdEh1Yi9SLVByYWN0aWNlIikNCiMgYXBwLlINCnNvdXJjZSgic2hpbnkvbXlfdWlfZmlsZS5SIikgIyBDcmVhdGVzICJteV91aSINCnNvdXJjZSgic2hpbnkvbXlfc2VydmVyX2ZpbGUuUiIpICMgQ3JlYXRlcyAibXlfc2VydmVyIg0Kc2hpbnlBcHAodWkgPSBteV91aSwgc2VydmVyID0gbXlfc2VydmVyKQ0KDQojIFRoaXMgd2Vic2l0ZSBtYXkgYmUgdWdseSwgYnV0IGl0IGRvZXMgd29yayENCg0KYGBgDQpIZXJlJ3MgYSBkZW1vIG9mIHRoZSB3ZWJzaXRlOg0KIVtXZWJzaXRlIERlbW9dKGltZy9zY3JlZW5ncmFiLmdpZikNCg==