The R Environment consists of the language interpreter as well as packages and other software components that help you be more effective.

Getting R

To get R, go to the Comprehensive R Archive Network and download the installer for your particular platform. What this installs is the Base R set of software, with just enough that you could go from there. If you are on the Windows platform, please also install the optional Rtools software so you can get packages from GitHub and GitLab. If you are on Mac or Linux, you do not need this.

The base package installs the R.app (on mac, R.exe on Windows, and /bin/R on Linux). This is the base R program and provides a direct connection to the R interpreter through what we call the Console. When you start it up, it will give you message about the current version.

The Console is a direct interactive environment. In this context, you can type stuff into the console and R will return the answer, just like a normal calculator. This is excellent for quick interactions and iteratively creating more complext graphics. Don’t worry though, much of what we will be doing is a lot more complex than typing in a command and hitting return and getting an answer, that is where we use scripts and markdown documents.

The console is a great way to interact with R and has a lot of cool features. One of the most important ones is the “recall previous things I typed” feature that is engaged by using the up and down cursor keys. R keeps a ‘history’ of all the things that go through the terminal (and even saves them for you to a local file with your project). Being an error-prone typist, this is a very helpful feature.

R Packages

One of the most important components of the R ecosystem is that it is extensible by its users, like you and me. The base functionality of R is defined by a few packages that are installed along with the base system. To add functionality to R, we can install additional packages that offer special functionality.

At present, there are over 16,000 user contributed libraries available to install on your machine. Chances are you will only need a minor subset of them to complete your work. However, if you find that there is missing functionality for the kind of work you do, you too can contribute code to the package repository.

To install a package from within R, use the function install.functions() and pass it the name (or names) of the packages you want to install. R will go out and download the package and install it on your system. So for example, to install the tidyverse package we would use

install.packages( "tidyverse")

To update packages on your machine (the authors of the packages are continually working to fix bugs and add functionality), use the following command (n.b., I always add the ask=FALSE option to this one because if you do not it will ask you for each library if you want it updated—I always want all of the updated and not have to sit there and type “Y” “Y” “Y” …).

update.packages( ask=FALSE )

Updating R from Previous Version

If you already had a version of R and want to upgrade it you may want to read this section so you can minimized the amount of hassle you run into with your packages. When you update the base R system, the set of all the packages you have installed are not moved over en mass. You will have to actively install these packages again for the new version. Here is some code to use to make your life easier.

Before you upgrade base R, run the following code. This looks at the current installation and sees what packages you already have installed and saves a list of them to the Desktop.

pkgs <- installed.packages()
pkgs <- names( is.na(pkgs[,4]))
save(pkgs,file="~/Desktop/pkgs.rda")

Next, install your new version of R and start it up. In the new version, run the following code. It will read the data file from your Desktop and then look at what you now have installed and finds the difference between the two. Then it automatically install all the packages that you previously had into the new version of R.

new_pkgs <- installed.packages()
new_pkgs <- names( is.na(new_pkgs[,4]))
load("~/Desktop/pkgs.rda")
to_install <- setdiff( pkgs, new_pkgs )
install.packages( to_install )
update.packages( ask=FALSE )

RStudio

While you can interact with R using the standard console interface, it is frankly caught in the ’90’s with respect to user-interface and interactions. One of the best things you can do to increase your productivity in R is to install the RStudio integrated development environment (IDE).

Just like the base R, simply go to the website and download the Open Source version of RStudio. If you want to pay for a version, you are welcome to do so. However, the open source version is identical to the paid version and that is what I recommend you use. Select the appropriate version for your platform, and install it.

Setting Optional Startup Values

By far, one of the most annoying options that R has turned on by default is the stringsAsFactors=TRUE setting that is turned on for read.csv(). This means that every time you read in a file from your computer or from online, it turns every column that has non-numeric values in it into a factor. If you are new to R, just trust me, this is annoying.

Start up options for R are located in a text file in your home directory. This file is named .Rprofile and since it starts with a period, it is invisible to you in the file browser/finder. We can put options in this file that will be read each time R starts up. Here is a quick method to do it. In RStudio, open the Terminal Tab (usually next to the R Console tab).

The following code set the option of stringsAsFactors to FALSE and concatenates that onto the end of your .Rprofile text file (making it if it is missing). Make sure the double greater-than signs are there, that has the text concatenated onto the end of the file if it exists. If you only put one of them, it will overwrite the file and replace it with this one line.

Type the following into the Terminal and hit return.

echo "options( stringsAsFactors=FALSE )" >> ~/.Rprofile
LS0tCnRpdGxlOiAiVGhlIFIgRW52aXJvbm1lbnQiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIGNzczogImVudnM1NDMtc3R5bGVzLmNzcyIKLS0tCgo+IFRoZSBSIEVudmlyb25tZW50IGNvbnNpc3RzIG9mIHRoZSBsYW5ndWFnZSBpbnRlcnByZXRlciBhcyB3ZWxsIGFzIHBhY2thZ2VzIGFuZCBvdGhlciBzb2Z0d2FyZSBjb21wb25lbnRzIHRoYXQgaGVscCB5b3UgYmUgbW9yZSBlZmZlY3RpdmUuCgoKCiMjIEdldHRpbmcgUgoKVG8gZ2V0IFIsIGdvIHRvIHRoZSBbQ29tcHJlaGVuc2l2ZSBSIEFyY2hpdmUgTmV0d29ya10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcpIGFuZCBkb3dubG9hZCB0aGUgaW5zdGFsbGVyIGZvciB5b3VyIHBhcnRpY3VsYXIgcGxhdGZvcm0uICBXaGF0IHRoaXMgaW5zdGFsbHMgaXMgdGhlICpCYXNlIFIqIHNldCBvZiBzb2Z0d2FyZSwgd2l0aCBqdXN0IGVub3VnaCB0aGF0IHlvdSBjb3VsZCBnbyBmcm9tIHRoZXJlLiAgSWYgeW91IGFyZSBvbiB0aGUgV2luZG93cyBwbGF0Zm9ybSwgcGxlYXNlIGFsc28gaW5zdGFsbCB0aGUgb3B0aW9uYWwgW1J0b29sc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvYmluL3dpbmRvd3MvUnRvb2xzLykgc29mdHdhcmUgc28geW91IGNhbiBnZXQgcGFja2FnZXMgZnJvbSBHaXRIdWIgYW5kIEdpdExhYi4gIElmIHlvdSBhcmUgb24gTWFjIG9yIExpbnV4LCB5b3UgZG8gbm90IG5lZWQgdGhpcy4KClRoZSBiYXNlIHBhY2thZ2UgaW5zdGFsbHMgdGhlIFIuYXBwIChvbiBtYWMsIFIuZXhlIG9uIFdpbmRvd3MsIGFuZCAvYmluL1Igb24gTGludXgpLiAgVGhpcyBpcyB0aGUgYmFzZSBSIHByb2dyYW0gYW5kIHByb3ZpZGVzIGEgZGlyZWN0IGNvbm5lY3Rpb24gdG8gdGhlIFIgaW50ZXJwcmV0ZXIgdGhyb3VnaCB3aGF0IHdlIGNhbGwgdGhlIENvbnNvbGUuICBXaGVuIHlvdSBzdGFydCBpdCB1cCwgaXQgd2lsbCBnaXZlIHlvdSBtZXNzYWdlIGFib3V0IHRoZSBjdXJyZW50IHZlcnNpb24uCgo8IS0tIElOU0VSVCBJTUFHRSBIRVJFIC0tPgoKVGhlICpDb25zb2xlKiBpcyBhIGRpcmVjdCBpbnRlcmFjdGl2ZSBlbnZpcm9ubWVudC4gIEluIHRoaXMgY29udGV4dCwgeW91IGNhbiB0eXBlIHN0dWZmIGludG8gdGhlIGNvbnNvbGUgYW5kIGBSYCB3aWxsIHJldHVybiB0aGUgYW5zd2VyLCBqdXN0IGxpa2UgYSBub3JtYWwgY2FsY3VsYXRvci4gIFRoaXMgaXMgKmV4Y2VsbGVudCogZm9yIHF1aWNrIGludGVyYWN0aW9ucyBhbmQgaXRlcmF0aXZlbHkgY3JlYXRpbmcgbW9yZSBjb21wbGV4dCBncmFwaGljcy4gIERvbid0IHdvcnJ5IHRob3VnaCwgbXVjaCBvZiB3aGF0IHdlIHdpbGwgYmUgZG9pbmcgaXMgYSBsb3QgbW9yZSBjb21wbGV4IHRoYW4gdHlwaW5nIGluIGEgY29tbWFuZCBhbmQgaGl0dGluZyByZXR1cm4gYW5kIGdldHRpbmcgYW4gYW5zd2VyLCB0aGF0IGlzIHdoZXJlIHdlIHVzZSBzY3JpcHRzIGFuZCBtYXJrZG93biBkb2N1bWVudHMuCgo8ZGl2IGNsYXNzPSJib3gtZ3JlZW4iPlRoZSBjb25zb2xlIGlzIGEgZ3JlYXQgd2F5IHRvIGludGVyYWN0IHdpdGggUiBhbmQgaGFzIGEgbG90IG9mIGNvb2wgZmVhdHVyZXMuICBPbmUgb2YgdGhlIG1vc3QgaW1wb3J0YW50IG9uZXMgaXMgdGhlICJyZWNhbGwgcHJldmlvdXMgdGhpbmdzIEkgdHlwZWQiIGZlYXR1cmUgdGhhdCBpcyBlbmdhZ2VkIGJ5IHVzaW5nIHRoZSAqdXAgYW5kIGRvd24gY3Vyc29yKiBrZXlzLiAgYFJgIGtlZXBzIGEgJ2hpc3RvcnknIG9mIGFsbCB0aGUgdGhpbmdzIHRoYXQgZ28gdGhyb3VnaCB0aGUgdGVybWluYWwgKGFuZCBldmVuIHNhdmVzIHRoZW0gZm9yIHlvdSB0byBhIGxvY2FsIGZpbGUgd2l0aCB5b3VyIHByb2plY3QpLiAgQmVpbmcgYW4gZXJyb3ItcHJvbmUgdHlwaXN0LCB0aGlzIGlzIGEgdmVyeSBoZWxwZnVsIGZlYXR1cmUuPC9kaXY+CgojIyBSIFBhY2thZ2VzCgpPbmUgb2YgdGhlIG1vc3QgaW1wb3J0YW50IGNvbXBvbmVudHMgb2YgdGhlIGBSYCBlY29zeXN0ZW0gaXMgdGhhdCBpdCBpcyBleHRlbnNpYmxlIGJ5IGl0cyB1c2VycywgbGlrZSB5b3UgYW5kIG1lLiAgVGhlIGJhc2UgZnVuY3Rpb25hbGl0eSBvZiBgUmAgaXMgZGVmaW5lZCBieSBhIGZldyBwYWNrYWdlcyB0aGF0IGFyZSBpbnN0YWxsZWQgYWxvbmcgd2l0aCB0aGUgYmFzZSBzeXN0ZW0uICBUbyBhZGQgZnVuY3Rpb25hbGl0eSB0byBgUmAsIHdlIGNhbiBpbnN0YWxsIGFkZGl0aW9uYWwgcGFja2FnZXMgdGhhdCBvZmZlciBzcGVjaWFsIGZ1bmN0aW9uYWxpdHkuCgpBdCBwcmVzZW50LCB0aGVyZSBhcmUgb3ZlciAxNiwwMDAgdXNlciBjb250cmlidXRlZCBsaWJyYXJpZXMgYXZhaWxhYmxlIHRvIGluc3RhbGwgb24geW91ciBtYWNoaW5lLiAgQ2hhbmNlcyBhcmUgeW91IHdpbGwgb25seSBuZWVkIGEgbWlub3Igc3Vic2V0IG9mIHRoZW0gdG8gY29tcGxldGUgeW91ciB3b3JrLiBIb3dldmVyLCBpZiB5b3UgZmluZCB0aGF0IHRoZXJlIGlzIG1pc3NpbmcgZnVuY3Rpb25hbGl0eSBmb3IgdGhlIGtpbmQgb2Ygd29yayB5b3UgZG8sIHlvdSB0b28gY2FuIGNvbnRyaWJ1dGUgY29kZSB0byB0aGUgcGFja2FnZSByZXBvc2l0b3J5LgoKCjxpZnJhbWUgc3JjPSJodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvYXZhaWxhYmxlX3BhY2thZ2VzX2J5X25hbWUuaHRtbCIgd2lkdGg9IjYwMHB4IiBoZWlnaHQ9IjYwMHB4Ij48L2lmcmFtZT4KCgpUbyBpbnN0YWxsIGEgcGFja2FnZSBmcm9tIHdpdGhpbiBgUmAsIHVzZSB0aGUgZnVuY3Rpb24gYGluc3RhbGwuZnVuY3Rpb25zKClgIGFuZCBwYXNzIGl0IHRoZSBuYW1lIChvciBuYW1lcykgb2YgdGhlIHBhY2thZ2VzIHlvdSB3YW50IHRvIGluc3RhbGwuIGBSYCB3aWxsIGdvIG91dCBhbmQgZG93bmxvYWQgdGhlIHBhY2thZ2UgYW5kIGluc3RhbGwgaXQgb24geW91ciBzeXN0ZW0uICBTbyBmb3IgZXhhbXBsZSwgdG8gaW5zdGFsbCB0aGUgYHRpZHl2ZXJzZWAgcGFja2FnZSB3ZSB3b3VsZCB1c2UKCmBgYHtyIGV2YWw9RkFMU0UsIGVjaG89VFJVRX0KaW5zdGFsbC5wYWNrYWdlcyggInRpZHl2ZXJzZSIpCmBgYAoKClRvIHVwZGF0ZSBwYWNrYWdlcyBvbiB5b3VyIG1hY2hpbmUgKHRoZSBhdXRob3JzIG9mIHRoZSBwYWNrYWdlcyBhcmUgY29udGludWFsbHkgd29ya2luZyB0byBmaXggYnVncyBhbmQgYWRkIGZ1bmN0aW9uYWxpdHkpLCB1c2UgdGhlIGZvbGxvd2luZyBjb21tYW5kIChuLmIuLCBJIGFsd2F5cyBhZGQgdGhlIGBhc2s9RkFMU0VgIG9wdGlvbiB0byB0aGlzIG9uZSBiZWNhdXNlIGlmIHlvdSBkbyBub3QgaXQgd2lsbCBhc2sgeW91IGZvciBlYWNoIGxpYnJhcnkgaWYgeW91IHdhbnQgaXQgdXBkYXRlZOKAlEkgYWx3YXlzIHdhbnQgYWxsIG9mIHRoZSB1cGRhdGVkIGFuZCBub3QgaGF2ZSB0byBzaXQgdGhlcmUgYW5kIHR5cGUgIlkiICJZIiAiWSIgLi4uKS4KCmBgYHtyIGV2YWw9RkFMU0V9CnVwZGF0ZS5wYWNrYWdlcyggYXNrPUZBTFNFICkKYGBgCgoKCgoKIyMjIFVwZGF0aW5nIFIgZnJvbSBQcmV2aW91cyBWZXJzaW9uCgpJZiB5b3UgYWxyZWFkeSBoYWQgYSB2ZXJzaW9uIG9mIGBSYCBhbmQgd2FudCB0byB1cGdyYWRlIGl0IHlvdSBtYXkgd2FudCB0byByZWFkIHRoaXMgc2VjdGlvbiBzbyB5b3UgY2FuIG1pbmltaXplZCB0aGUgYW1vdW50IG9mIGhhc3NsZSB5b3UgcnVuIGludG8gd2l0aCB5b3VyIHBhY2thZ2VzLiAgV2hlbiB5b3UgdXBkYXRlIHRoZSBiYXNlIFIgc3lzdGVtLCB0aGUgc2V0IG9mIGFsbCB0aGUgcGFja2FnZXMgeW91IGhhdmUgaW5zdGFsbGVkIGFyZSBub3QgbW92ZWQgb3ZlciAqZW4gbWFzcyouIFlvdSB3aWxsIGhhdmUgdG8gYWN0aXZlbHkgaW5zdGFsbCB0aGVzZSBwYWNrYWdlcyBhZ2FpbiBmb3IgdGhlIG5ldyB2ZXJzaW9uLiAgSGVyZSBpcyBzb21lIGNvZGUgdG8gdXNlIHRvIG1ha2UgeW91ciBsaWZlIGVhc2llci4KCkJlZm9yZSB5b3UgdXBncmFkZSBiYXNlIGBSYCwgcnVuIHRoZSBmb2xsb3dpbmcgY29kZS4gIFRoaXMgbG9va3MgYXQgdGhlIGN1cnJlbnQgaW5zdGFsbGF0aW9uIGFuZCBzZWVzIHdoYXQgcGFja2FnZXMgeW91IGFscmVhZHkgaGF2ZSBpbnN0YWxsZWQgYW5kIHNhdmVzIGEgbGlzdCBvZiB0aGVtIHRvIHRoZSBEZXNrdG9wLgoKYGBge3IgZXZhbD1GQUxTRX0KcGtncyA8LSBpbnN0YWxsZWQucGFja2FnZXMoKQpwa2dzIDwtIG5hbWVzKCBpcy5uYShwa2dzWyw0XSkpCnNhdmUocGtncyxmaWxlPSJ+L0Rlc2t0b3AvcGtncy5yZGEiKQpgYGAKCk5leHQsIGluc3RhbGwgeW91ciBuZXcgdmVyc2lvbiBvZiBSIGFuZCBzdGFydCBpdCB1cC4gIEluIHRoZSBuZXcgdmVyc2lvbiwgcnVuIHRoZSBmb2xsb3dpbmcgY29kZS4gIEl0IHdpbGwgcmVhZCB0aGUgZGF0YSBmaWxlIGZyb20geW91ciBEZXNrdG9wIGFuZCB0aGVuIGxvb2sgYXQgd2hhdCB5b3Ugbm93IGhhdmUgaW5zdGFsbGVkIGFuZCBmaW5kcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB0d28uICBUaGVuIGl0IGF1dG9tYXRpY2FsbHkgaW5zdGFsbCBhbGwgdGhlIHBhY2thZ2VzIHRoYXQgeW91IHByZXZpb3VzbHkgaGFkIGludG8gdGhlIG5ldyB2ZXJzaW9uIG9mIGBSYC4KCmBgYHtyIGV2YWw9RkFMU0V9Cm5ld19wa2dzIDwtIGluc3RhbGxlZC5wYWNrYWdlcygpCm5ld19wa2dzIDwtIG5hbWVzKCBpcy5uYShuZXdfcGtnc1ssNF0pKQpsb2FkKCJ+L0Rlc2t0b3AvcGtncy5yZGEiKQp0b19pbnN0YWxsIDwtIHNldGRpZmYoIHBrZ3MsIG5ld19wa2dzICkKaW5zdGFsbC5wYWNrYWdlcyggdG9faW5zdGFsbCApCnVwZGF0ZS5wYWNrYWdlcyggYXNrPUZBTFNFICkKYGBgCgoKCiMjIFJTdHVkaW8KCldoaWxlIHlvdSBjYW4gaW50ZXJhY3Qgd2l0aCBSIHVzaW5nIHRoZSBzdGFuZGFyZCBjb25zb2xlIGludGVyZmFjZSwgaXQgaXMgZnJhbmtseSBjYXVnaHQgaW4gdGhlICc5MCdzIHdpdGggcmVzcGVjdCB0byB1c2VyLWludGVyZmFjZSBhbmQgaW50ZXJhY3Rpb25zLiAgT25lIG9mIHRoZSBiZXN0IHRoaW5ncyB5b3UgY2FuIGRvIHRvIGluY3JlYXNlIHlvdXIgcHJvZHVjdGl2aXR5IGluIGBSYCBpcyB0byBpbnN0YWxsIHRoZSBbUlN0dWRpb10oaHR0cHM6Ly9yc3R1ZGlvLmNvbSkgaW50ZWdyYXRlZCBkZXZlbG9wbWVudCBlbnZpcm9ubWVudCAoSURFKS4KCkp1c3QgbGlrZSB0aGUgYmFzZSBgUmAsIHNpbXBseSBnbyB0byB0aGUgd2Vic2l0ZSBhbmQgZG93bmxvYWQgdGhlIE9wZW4gU291cmNlIHZlcnNpb24gb2YgUlN0dWRpby4gIElmIHlvdSB3YW50IHRvIHBheSBmb3IgYSB2ZXJzaW9uLCB5b3UgYXJlIHdlbGNvbWUgdG8gZG8gc28uICBIb3dldmVyLCB0aGUgb3BlbiBzb3VyY2UgdmVyc2lvbiBpcyBpZGVudGljYWwgdG8gdGhlIHBhaWQgdmVyc2lvbiBhbmQgdGhhdCBpcyB3aGF0IEkgcmVjb21tZW5kIHlvdSB1c2UuICBTZWxlY3QgdGhlIGFwcHJvcHJpYXRlIHZlcnNpb24gZm9yIHlvdXIgcGxhdGZvcm0sIGFuZCBpbnN0YWxsIGl0LgoKCgoKIyMgU2V0dGluZyBPcHRpb25hbCBTdGFydHVwIFZhbHVlcwoKCkJ5IGZhciwgb25lIG9mIHRoZSBtb3N0IGFubm95aW5nIG9wdGlvbnMgdGhhdCBgUmAgaGFzIHR1cm5lZCBvbiBieSBkZWZhdWx0IGlzIHRoZSBgc3RyaW5nc0FzRmFjdG9ycz1UUlVFYCBzZXR0aW5nIHRoYXQgaXMgdHVybmVkIG9uIGZvciBgcmVhZC5jc3YoKWAuICBUaGlzIG1lYW5zIHRoYXQgZXZlcnkgdGltZSB5b3UgcmVhZCBpbiBhIGZpbGUgZnJvbSB5b3VyIGNvbXB1dGVyIG9yIGZyb20gb25saW5lLCBpdCB0dXJucyBldmVyeSBjb2x1bW4gdGhhdCBoYXMgbm9uLW51bWVyaWMgdmFsdWVzIGluIGl0IGludG8gYSBgZmFjdG9yYC4gIElmIHlvdSBhcmUgbmV3IHRvIGBSYCwganVzdCB0cnVzdCBtZSwgdGhpcyBpcyBhbm5veWluZy4KClN0YXJ0IHVwIG9wdGlvbnMgZm9yIFIgYXJlIGxvY2F0ZWQgaW4gYSB0ZXh0IGZpbGUgaW4geW91ciBob21lIGRpcmVjdG9yeS4gIFRoaXMgZmlsZSBpcyBuYW1lZCBgLlJwcm9maWxlYCBhbmQgc2luY2UgaXQgc3RhcnRzIHdpdGggYSBwZXJpb2QsIGl0IGlzIGludmlzaWJsZSB0byB5b3UgaW4gdGhlIGZpbGUgYnJvd3Nlci9maW5kZXIuICBXZSBjYW4gcHV0IG9wdGlvbnMgaW4gdGhpcyBmaWxlIHRoYXQgd2lsbCBiZSByZWFkIGVhY2ggdGltZSBSIHN0YXJ0cyB1cC4gIEhlcmUgaXMgYSBxdWljayBtZXRob2QgdG8gZG8gaXQuICBJbiBSU3R1ZGlvLCBvcGVuIHRoZSBUZXJtaW5hbCBUYWIgKHVzdWFsbHkgbmV4dCB0byB0aGUgUiBDb25zb2xlIHRhYikuCgpUaGUgZm9sbG93aW5nIGNvZGUgc2V0IHRoZSBvcHRpb24gb2YgYHN0cmluZ3NBc0ZhY3RvcnNgIHRvIGBGQUxTRWAgYW5kIGNvbmNhdGVuYXRlcyB0aGF0IG9udG8gdGhlIGVuZCBvZiB5b3VyIGAuUnByb2ZpbGVgIHRleHQgZmlsZSAobWFraW5nIGl0IGlmIGl0IGlzIG1pc3NpbmcpLiAgTWFrZSBzdXJlIHRoZSBkb3VibGUgZ3JlYXRlci10aGFuIHNpZ25zIGFyZSB0aGVyZSwgdGhhdCBoYXMgdGhlIHRleHQgY29uY2F0ZW5hdGVkIG9udG8gdGhlIGVuZCBvZiB0aGUgZmlsZSBpZiBpdCBleGlzdHMuICBJZiB5b3Ugb25seSBwdXQgb25lIG9mIHRoZW0sIGl0IHdpbGwgb3ZlcndyaXRlIHRoZSBmaWxlIGFuZCByZXBsYWNlIGl0IHdpdGggdGhpcyBvbmUgbGluZS4KClR5cGUgdGhlIGZvbGxvd2luZyBpbnRvIHRoZSBUZXJtaW5hbCBhbmQgaGl0IHJldHVybi4KCmBgYHtiYXNoIGV2YWw9RkFMU0V9CmVjaG8gIm9wdGlvbnMoIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UgKSIgPj4gfi8uUnByb2ZpbGUKYGBgCgoKCgo=