The Data

For this homework we will be working with the data that were used in the lecture on ggplot from the 2011 The Economist article looking at the relationship between human development and perceived corruption.

Figure 1: The relationship between the perception of corruption and the human development index from 2011 for 174 nations states.

The data are located on the class GitHub site and can be accessed by the following URL, which is being presented as a CSV file.

# The URL for the data on GitHub
url <- "https://raw.githubusercontent.com/dyerlab/ENVS-Lectures/master/data/EconomistData.csv"

Use the URL above and load the data into R and present a summary. Name this data frame df because some code below that I give assumes that name.

## Load the data here.
library( readr )

df <- read_csv( url )
Parsed with column specification:
cols(
  Country = col_character(),
  HDI = col_double(),
  CPI = col_double(),
  Region = col_character()
)

As it stands, we are going to need to turn the Region column from a raw character type to a factor data type. To to this, we can use the function as.factor() and assign it back to the data.frame.

# Turn Region into factor

df$Region <- as.factor( df$Region  )

In all the plot on this homework, you must make an legend when appropriate and label the axes properly.

Univariate Data

For this section, focus on histograms and density plots. Create a historgram plot and a density plot, one for built-in graphics and the other using ggplot. Feel free to embellish them as you please but you must have properly labeled axes.

# Built-in hist for HDI
meanHDI <- by( df$HDI, df$Region, mean)
barplot( meanHDI )

# Density plot for HDI using built-in graphics

Now for CPI, do the same things using ggplot graphics. You must first load in the ggplot library.

# Load in GGPlot library
library( ggplot2 )

Then make the plots

# GGPlot histogram
# GGPlot density Plot
# Overlay density on top of histogram using ggplot

Categorical Data

For data that has both categorical data and continuous data, we can display the data in several different ways.

Bar Plots

For standard bar plots, we will create a new data.frame that has average values for the continuous variable across each of the levels of the categorical variable. You can do this manually or by using the by() function. If you use by() you’ll need to coerce it into a numeric data vector via as.numeric(). If you need a reminder of this, check out this slide.

# Create new data.frame with averages for HDI by Region

Create a barplot using built-in graphics.

# barplot

GGPlot has several ways to look at these kinds of data. There is a Cheat Sheet for a bunch of ggplot functions in Canvas (as well as GitHub from that link).

To create a bar plot in ggplot one can use the geom_col() geometric layer.

# geom_col plot

That plot looks great but the x-axis labels are all screwed up. To fix this you can add some customization to the theme by changing the text elements on the x axis. The code in the chunk below, when added to your plot code, will rotate the angle of the text by 45° and justified. Add your code to this chunk and see how this changes the axis labels (feel free to play around with them).

Note: You must change eval=FALSE to eval=TRUE to get this chunck to work. I had to set it to not run because the text {YOUR PLOT CODE HERE} will not compile.

# Fix the axes
{YOUR PLOT CODE HERE} + theme(axis.text.x = element_text(angle = 45, hjust=1))

Box plots & others

A Boxplot needs all the data to be able to display the distribution of values, so we’ll be using the whole data frame again.

# boxplot of HDI by Region using built-in graphics.

Now the same using ggplot.

# GGPlot geom_boxplot

The ggplot library has additional ways to visualize these kinds of data. Look at the CheatSheet if you need assistance or the built-in help file for geom_violin to make this plot.

# Look up geom_violin and use that for plotting

Adding Colors

Take the violin plot above and color each region in a different color.

# Colored violins

Continuous Bivariate Data

Using the built-in plot() function create the following scatter plots. The plot characters and other customization are found on this slide from the lecture on built-in graphics.

# HDI as a function of CPI with Regions defined by plot character  + legend

Use whatever color scheme you like.

# HDI as a function of CPI with Regions defined by color + legend

Now do the same with ggplot using regions as either plot character or color.

# HDI as function of CPI with Region differences.

Labels

OK, so the last thing we are going to do is define a separate data.frame that has just the labels so we can make it look a bit like the original plot. To do this, I define a new data.frame with just the countries that I’m interested in plotting.

Country <- c("Russia", "Venezuela", "Iraq", "Myanmar", "Sudan",
             "Afghanistan", "Congo", "Greece", "Argentina", "Brazil", 
             "India", "Italy", "China", "South Africa", "Spane", 
             "Botswana", "Cape Verde", "Bhutan", "Rwanda", "France", 
             "United States", "Germany", "Britain", "Barbados", "Norway", 
             "Japan","New Zealand", "Singapore")
df.labels <- data.frame( Country )

Next, I take this new data.frame and the original one and use the merge() function.

Figure 2: Help file for merge().

What this function requires is that the two data.frames must have a colum with the same name. In this case, both the original data.frame had one named Country as did the new one. I’m assuming that the original data was loaded in as the variable df as requested above—if you named it something else, then replace your variable name with the df in the first line of the code below.

df.labels <- merge( df.labels, df)
df.labels

Now, let’s load in the ggrepel library1 and use both of these data.frames to add labels to a scatter plot. To do this, you’ll have to use the full data frame to lay down a geom_point() layer and then add the geom_text_repel() layer using the other df.labels data.frame. To make it look right, you may need to futz around with the various data mappings in the aes functions. See this slide for a refresher on what ggrepel needs to do its job.

# GGRepel 
library( ggrepel )

  1. If you get an error when trying to load in the ggrepel library saying it could not find the library, then install it using install.packages("ggrepel").↩︎

LS0tCnRpdGxlOiAiR3JhcGhpY3MgaW4gUiIKYXV0aG9yOiAiWW91ciBOYW1lIEhlcmUiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIGZpZ19jYXB0aW9uOiB5ZXMKLS0tCgojIFRoZSBEYXRhCgpGb3IgdGhpcyBob21ld29yayB3ZSB3aWxsIGJlIHdvcmtpbmcgd2l0aCB0aGUgZGF0YSB0aGF0IHdlcmUgdXNlZCBpbiB0aGUgbGVjdHVyZSBvbiBgZ2dwbG90YCBmcm9tIHRoZSAyMDExICpUaGUgRWNvbm9taXN0KiBhcnRpY2xlIGxvb2tpbmcgYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGh1bWFuIGRldmVsb3BtZW50IGFuZCBwZXJjZWl2ZWQgY29ycnVwdGlvbi4KCiFbKkZpZ3VyZSAxOiogVGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBwZXJjZXB0aW9uIG9mIGNvcnJ1cHRpb24gYW5kIHRoZSBodW1hbiBkZXZlbG9wbWVudCBpbmRleCBmcm9tIDIwMTEgZm9yIDE3NCBuYXRpb25zIHN0YXRlcy5dKGh0dHBzOi8vbGl2ZS5zdGF0aWNmbGlja3IuY29tLzY1NTM1LzUwMjk0NDEyNzEzXzI1YmJkNTIyMzBfY19kLmpwZykKClRoZSBkYXRhIGFyZSBsb2NhdGVkIG9uIHRoZSBbY2xhc3MgR2l0SHViIHNpdGVdKGh0dHBzOi8vZ2l0aHViLmNvbS9keWVybGFiL0VOVlMtTGVjdHVyZXMpIGFuZCBjYW4gYmUgYWNjZXNzZWQgYnkgdGhlIGZvbGxvd2luZyBVUkwsIHdoaWNoIGlzIGJlaW5nIHByZXNlbnRlZCBhcyBhIENTViBmaWxlLgoKYGBge3J9CiMgVGhlIFVSTCBmb3IgdGhlIGRhdGEgb24gR2l0SHViCnVybCA8LSAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2R5ZXJsYWIvRU5WUy1MZWN0dXJlcy9tYXN0ZXIvZGF0YS9FY29ub21pc3REYXRhLmNzdiIKYGBgCgpVc2UgdGhlIFVSTCBhYm92ZSBhbmQgbG9hZCB0aGUgZGF0YSBpbnRvIFIgYW5kIHByZXNlbnQgYSBzdW1tYXJ5LiAgTmFtZSB0aGlzIGRhdGEgZnJhbWUgYGRmYCBiZWNhdXNlIHNvbWUgY29kZSBiZWxvdyB0aGF0IEkgZ2l2ZSBhc3N1bWVzIHRoYXQgbmFtZS4KCmBgYHtyfQojIyBMb2FkIHRoZSBkYXRhIGhlcmUuCmxpYnJhcnkoIHJlYWRyICkKCmRmIDwtIHJlYWRfY3N2KCB1cmwgKQpgYGAKCkFzIGl0IHN0YW5kcywgd2UgYXJlIGdvaW5nIHRvIG5lZWQgdG8gdHVybiB0aGUgYFJlZ2lvbmAgY29sdW1uIGZyb20gYSByYXcgYGNoYXJhY3RlcmAgdHlwZSB0byBhIGBmYWN0b3JgIGRhdGEgdHlwZS4gIFRvIHRvIHRoaXMsIHdlIGNhbiB1c2UgdGhlIGZ1bmN0aW9uIGBhcy5mYWN0b3IoKWAgYW5kIGFzc2lnbiBpdCBiYWNrIHRvIHRoZSBgZGF0YS5mcmFtZWAuCgoKYGBge3J9CiMgVHVybiBSZWdpb24gaW50byBmYWN0b3IKCmRmJFJlZ2lvbiA8LSBhcy5mYWN0b3IoIGRmJFJlZ2lvbiAgKQpgYGAKCgoqSW4gYWxsIHRoZSBwbG90IG9uIHRoaXMgaG9tZXdvcmssIHlvdSBtdXN0IG1ha2UgYW4gbGVnZW5kIHdoZW4gYXBwcm9wcmlhdGUgYW5kIGxhYmVsIHRoZSBheGVzIHByb3Blcmx5LioKCgojIFVuaXZhcmlhdGUgRGF0YQoKRm9yIHRoaXMgc2VjdGlvbiwgZm9jdXMgb24gaGlzdG9ncmFtcyBhbmQgZGVuc2l0eSBwbG90cy4gIENyZWF0ZSBhIGhpc3RvcmdyYW0gcGxvdCBhbmQgYSBkZW5zaXR5IHBsb3QsIG9uZSBmb3IgYnVpbHQtaW4gZ3JhcGhpY3MgYW5kIHRoZSBvdGhlciB1c2luZyBgZ2dwbG90YC4gIEZlZWwgZnJlZSB0byBlbWJlbGxpc2ggdGhlbSBhcyB5b3UgcGxlYXNlIGJ1dCB5b3UgKiptdXN0KiogaGF2ZSBwcm9wZXJseSBsYWJlbGVkIGF4ZXMuCgpgYGB7cn0KIyBCdWlsdC1pbiBoaXN0IGZvciBIREkKbWVhbkhESSA8LSBieSggZGYkSERJLCBkZiRSZWdpb24sIG1lYW4pCmJhcnBsb3QoIG1lYW5IREkgKQoKCgpgYGAKCmBgYHtyfQojIERlbnNpdHkgcGxvdCBmb3IgSERJIHVzaW5nIGJ1aWx0LWluIGdyYXBoaWNzCgpgYGAKCk5vdyBmb3IgQ1BJLCBkbyB0aGUgc2FtZSB0aGluZ3MgdXNpbmcgYGdncGxvdGAgZ3JhcGhpY3MuICBZb3UgbXVzdCBmaXJzdCBsb2FkIGluIHRoZSBgZ2dwbG90YCBsaWJyYXJ5LgoKYGBge3J9CiMgTG9hZCBpbiBHR1Bsb3QgbGlicmFyeQpsaWJyYXJ5KCBnZ3Bsb3QyICkKYGBgCgpUaGVuIG1ha2UgdGhlIHBsb3RzCgpgYGB7cn0KIyBHR1Bsb3QgaGlzdG9ncmFtCmBgYAoKYGBge3J9CiMgR0dQbG90IGRlbnNpdHkgUGxvdApgYGAKCmBgYHtyfQojIE92ZXJsYXkgZGVuc2l0eSBvbiB0b3Agb2YgaGlzdG9ncmFtIHVzaW5nIGdncGxvdApgYGAKCgojIENhdGVnb3JpY2FsIERhdGEKCkZvciBkYXRhIHRoYXQgaGFzIGJvdGggY2F0ZWdvcmljYWwgZGF0YSBhbmQgY29udGludW91cyBkYXRhLCB3ZSBjYW4gZGlzcGxheSB0aGUgZGF0YSBpbiBzZXZlcmFsIGRpZmZlcmVudCB3YXlzLiAgCgojIyBCYXIgUGxvdHMgCgpGb3Igc3RhbmRhcmQgYmFyIHBsb3RzLCB3ZSB3aWxsIGNyZWF0ZSBhIG5ldyBgZGF0YS5mcmFtZWAgdGhhdCBoYXMgYXZlcmFnZSB2YWx1ZXMgZm9yIHRoZSBjb250aW51b3VzIHZhcmlhYmxlIGFjcm9zcyBlYWNoIG9mIHRoZSBsZXZlbHMgb2YgdGhlIGNhdGVnb3JpY2FsIHZhcmlhYmxlLiAgWW91IGNhbiBkbyB0aGlzIG1hbnVhbGx5IG9yIGJ5IHVzaW5nIHRoZSBgYnkoKWAgZnVuY3Rpb24uICBJZiB5b3UgdXNlIGBieSgpYCB5b3UnbGwgbmVlZCB0byBjb2VyY2UgaXQgaW50byBhIG51bWVyaWMgZGF0YSB2ZWN0b3IgdmlhIGBhcy5udW1lcmljKClgLiAgSWYgeW91IG5lZWQgYSByZW1pbmRlciBvZiB0aGlzLCBjaGVjayBvdXQgW3RoaXMgc2xpZGVdKGh0dHBzOi8vZHllcmxhYi5naXRodWIuaW8vRU5WUy1MZWN0dXJlcy92aXN1YWxpemF0aW9uL2Jhc2ljX3Zpc3VhbGl6YXRpb24vc2xpZGVzLmh0bWwjNTEpLgoKYGBge3J9CiMgQ3JlYXRlIG5ldyBkYXRhLmZyYW1lIHdpdGggYXZlcmFnZXMgZm9yIEhESSBieSBSZWdpb24KYGBgCgpDcmVhdGUgYSBiYXJwbG90IHVzaW5nIGJ1aWx0LWluIGdyYXBoaWNzLgoKYGBge3J9CiMgYmFycGxvdApgYGAKCkdHUGxvdCBoYXMgc2V2ZXJhbCB3YXlzIHRvIGxvb2sgYXQgdGhlc2Uga2luZHMgb2YgZGF0YS4gIFRoZXJlIGlzIGEgW0NoZWF0IFNoZWV0XShodHRwczovL2dpdGh1Yi5jb20vcnN0dWRpby9jaGVhdHNoZWV0cy9ibG9iL21hc3Rlci9kYXRhLXZpc3VhbGl6YXRpb24tMi4xLnBkZikgZm9yIGEgYnVuY2ggb2YgYGdncGxvdGAgZnVuY3Rpb25zIGluIENhbnZhcyAoYXMgd2VsbCBhcyBHaXRIdWIgZnJvbSB0aGF0IGxpbmspLiAgCgpUbyBjcmVhdGUgYSBiYXIgcGxvdCBpbiBgZ2dwbG90YCBvbmUgY2FuIHVzZSB0aGUgYGdlb21fY29sKClgIGdlb21ldHJpYyBsYXllci4gIAoKYGBge3J9CiMgZ2VvbV9jb2wgcGxvdApgYGAKClRoYXQgcGxvdCBsb29rcyBncmVhdCBidXQgdGhlIHgtYXhpcyBsYWJlbHMgYXJlIGFsbCBzY3Jld2VkIHVwLiAgVG8gZml4IHRoaXMgeW91IGNhbiBhZGQgc29tZSBjdXN0b21pemF0aW9uIHRvIHRoZSB0aGVtZSBieSBjaGFuZ2luZyB0aGUgdGV4dCBlbGVtZW50cyBvbiB0aGUgeCBheGlzLiAgVGhlIGNvZGUgaW4gdGhlIGNodW5rIGJlbG93LCB3aGVuIGFkZGVkIHRvIHlvdXIgcGxvdCBjb2RlLCB3aWxsIHJvdGF0ZSB0aGUgYW5nbGUgb2YgdGhlIHRleHQgYnkgNDXCsCBhbmQganVzdGlmaWVkLiAgQWRkIHlvdXIgY29kZSB0byB0aGlzIGNodW5rIGFuZCBzZWUgaG93IHRoaXMgY2hhbmdlcyB0aGUgYXhpcyBsYWJlbHMgKGZlZWwgZnJlZSB0byBwbGF5IGFyb3VuZCB3aXRoIHRoZW0pLiAgCgpOb3RlOiBZb3UgKm11c3QqIGNoYW5nZSBgZXZhbD1GQUxTRWAgdG8gYGV2YWw9VFJVRWAgdG8gZ2V0IHRoaXMgY2h1bmNrIHRvIHdvcmsuICBJIGhhZCB0byBzZXQgaXQgdG8gbm90IHJ1biBiZWNhdXNlIHRoZSB0ZXh0IGB7WU9VUiBQTE9UIENPREUgSEVSRX1gIHdpbGwgbm90IGNvbXBpbGUuCgpgYGB7ciBldmFsPUZBTFNFfQojIEZpeCB0aGUgYXhlcwp7WU9VUiBQTE9UIENPREUgSEVSRX0gKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xKSkKYGBgCgojIyBCb3ggcGxvdHMgJiBvdGhlcnMKCkEgQm94cGxvdCBuZWVkcyBhbGwgdGhlIGRhdGEgdG8gYmUgYWJsZSB0byBkaXNwbGF5IHRoZSBkaXN0cmlidXRpb24gb2YgdmFsdWVzLCBzbyB3ZSdsbCBiZSB1c2luZyB0aGUgd2hvbGUgZGF0YSBmcmFtZSBhZ2Fpbi4KCmBgYHtyfQojIGJveHBsb3Qgb2YgSERJIGJ5IFJlZ2lvbiB1c2luZyBidWlsdC1pbiBncmFwaGljcy4KYGBgCgpOb3cgdGhlIHNhbWUgdXNpbmcgYGdncGxvdGAuCgpgYGB7cn0KIyBHR1Bsb3QgZ2VvbV9ib3hwbG90CmBgYAoKVGhlIGBnZ3Bsb3RgIGxpYnJhcnkgaGFzIGFkZGl0aW9uYWwgd2F5cyB0byB2aXN1YWxpemUgdGhlc2Uga2luZHMgb2YgZGF0YS4gTG9vayBhdCB0aGUgQ2hlYXRTaGVldCBpZiB5b3UgbmVlZCBhc3Npc3RhbmNlIG9yIHRoZSBidWlsdC1pbiBoZWxwIGZpbGUgZm9yIGBnZW9tX3Zpb2xpbmAgdG8gbWFrZSB0aGlzIHBsb3QuCgoKCmBgYHtyfQojIExvb2sgdXAgZ2VvbV92aW9saW4gYW5kIHVzZSB0aGF0IGZvciBwbG90dGluZwpgYGAKCiMjIyBBZGRpbmcgQ29sb3JzCgpUYWtlIHRoZSB2aW9saW4gcGxvdCBhYm92ZSBhbmQgY29sb3IgZWFjaCByZWdpb24gaW4gYSBkaWZmZXJlbnQgY29sb3IuICAKCmBgYHtyfQojIENvbG9yZWQgdmlvbGlucwpgYGAKCgojIENvbnRpbnVvdXMgQml2YXJpYXRlIERhdGEKClVzaW5nIHRoZSBidWlsdC1pbiBgcGxvdCgpYCBmdW5jdGlvbiBjcmVhdGUgdGhlIGZvbGxvd2luZyBzY2F0dGVyIHBsb3RzLiBUaGUgcGxvdCBjaGFyYWN0ZXJzIGFuZCBvdGhlciBjdXN0b21pemF0aW9uIGFyZSBmb3VuZCBvbiBbdGhpcyBzbGlkZV0oaHR0cHM6Ly9keWVybGFiLmdpdGh1Yi5pby9FTlZTLUxlY3R1cmVzL3Zpc3VhbGl6YXRpb24vYmFzaWNfdmlzdWFsaXphdGlvbi9zbGlkZXMuaHRtbCMyOCkgZnJvbSB0aGUgbGVjdHVyZSBvbiBidWlsdC1pbiBncmFwaGljcy4KCgpgYGB7cn0KIyBIREkgYXMgYSBmdW5jdGlvbiBvZiBDUEkgd2l0aCBSZWdpb25zIGRlZmluZWQgYnkgcGxvdCBjaGFyYWN0ZXIgICsgbGVnZW5kCmBgYAoKVXNlIHdoYXRldmVyIGNvbG9yIHNjaGVtZSB5b3UgbGlrZS4KCmBgYHtyfQojIEhESSBhcyBhIGZ1bmN0aW9uIG9mIENQSSB3aXRoIFJlZ2lvbnMgZGVmaW5lZCBieSBjb2xvciArIGxlZ2VuZApgYGAKCk5vdyBkbyB0aGUgc2FtZSB3aXRoIGBnZ3Bsb3RgIHVzaW5nIHJlZ2lvbnMgYXMgZWl0aGVyIHBsb3QgY2hhcmFjdGVyIG9yIGNvbG9yLgoKYGBge3J9CiMgSERJIGFzIGZ1bmN0aW9uIG9mIENQSSB3aXRoIFJlZ2lvbiBkaWZmZXJlbmNlcy4KYGBgCgoKCiMgTGFiZWxzCgpPSywgc28gdGhlIGxhc3QgdGhpbmcgd2UgYXJlIGdvaW5nIHRvIGRvIGlzIGRlZmluZSBhIHNlcGFyYXRlIGBkYXRhLmZyYW1lYCB0aGF0IGhhcyBqdXN0IHRoZSBsYWJlbHMgc28gd2UgY2FuIG1ha2UgaXQgbG9vayBhIGJpdCBsaWtlIHRoZSBvcmlnaW5hbCBwbG90LiAgVG8gZG8gdGhpcywgSSBkZWZpbmUgYSBuZXcgZGF0YS5mcmFtZSB3aXRoIGp1c3QgdGhlIGNvdW50cmllcyB0aGF0IEknbSBpbnRlcmVzdGVkIGluIHBsb3R0aW5nLgoKYGBge3J9CkNvdW50cnkgPC0gYygiUnVzc2lhIiwgIlZlbmV6dWVsYSIsICJJcmFxIiwgIk15YW5tYXIiLCAiU3VkYW4iLAogICAgICAgICAgICAgIkFmZ2hhbmlzdGFuIiwgIkNvbmdvIiwgIkdyZWVjZSIsICJBcmdlbnRpbmEiLCAiQnJhemlsIiwgCiAgICAgICAgICAgICAiSW5kaWEiLCAiSXRhbHkiLCAiQ2hpbmEiLCAiU291dGggQWZyaWNhIiwgIlNwYW5lIiwgCiAgICAgICAgICAgICAiQm90c3dhbmEiLCAiQ2FwZSBWZXJkZSIsICJCaHV0YW4iLCAiUndhbmRhIiwgIkZyYW5jZSIsIAogICAgICAgICAgICAgIlVuaXRlZCBTdGF0ZXMiLCAiR2VybWFueSIsICJCcml0YWluIiwgIkJhcmJhZG9zIiwgIk5vcndheSIsIAogICAgICAgICAgICAgIkphcGFuIiwiTmV3IFplYWxhbmQiLCAiU2luZ2Fwb3JlIikKZGYubGFiZWxzIDwtIGRhdGEuZnJhbWUoIENvdW50cnkgKQpgYGAKCk5leHQsIEkgdGFrZSB0aGlzIG5ldyBkYXRhLmZyYW1lIGFuZCB0aGUgb3JpZ2luYWwgb25lIGFuZCB1c2UgdGhlIGBtZXJnZSgpYCBmdW5jdGlvbi4KCiFbKkZpZ3VyZSAyOiogSGVscCBmaWxlIGZvciBgbWVyZ2UoKWAuXShodHRwczovL2xpdmUuc3RhdGljZmxpY2tyLmNvbS82NTUzNS81MDM0ODcwMDU4Nl9jOWVlNjgxNDk0X2NfZC5qcGcpCgpXaGF0IHRoaXMgZnVuY3Rpb24gKnJlcXVpcmVzKiBpcyB0aGF0IHRoZSB0d28gZGF0YS5mcmFtZXMgKiptdXN0KiogaGF2ZSBhIGNvbHVtIHdpdGggdGhlIHNhbWUgbmFtZS4gIEluIHRoaXMgY2FzZSwgYm90aCB0aGUgb3JpZ2luYWwgZGF0YS5mcmFtZSBoYWQgb25lIG5hbWVkIGBDb3VudHJ5YCBhcyBkaWQgdGhlIG5ldyBvbmUuICBJJ20gYXNzdW1pbmcgdGhhdCB0aGUgb3JpZ2luYWwgZGF0YSB3YXMgbG9hZGVkIGluIGFzIHRoZSB2YXJpYWJsZSBgZGZgIGFzIHJlcXVlc3RlZCBhYm92ZeKAlGlmIHlvdSBuYW1lZCBpdCBzb21ldGhpbmcgZWxzZSwgdGhlbiByZXBsYWNlIHlvdXIgdmFyaWFibGUgbmFtZSB3aXRoIHRoZSBgZGZgIGluIHRoZSBmaXJzdCBsaW5lIG9mIHRoZSBjb2RlIGJlbG93LgoKYGBge3J9CmRmLmxhYmVscyA8LSBtZXJnZSggZGYubGFiZWxzLCBkZikKZGYubGFiZWxzCmBgYAoKCk5vdywgbGV0J3MgbG9hZCBpbiB0aGUgYGdncmVwZWxgIGxpYnJhcnlbXjFdIGFuZCB1c2UgYm90aCBvZiB0aGVzZSBkYXRhLmZyYW1lcyB0byBhZGQgbGFiZWxzIHRvIGEgc2NhdHRlciBwbG90LiAgVG8gZG8gdGhpcywgeW91J2xsIGhhdmUgdG8gdXNlIHRoZSBmdWxsIGRhdGEgZnJhbWUgdG8gbGF5IGRvd24gYSBgZ2VvbV9wb2ludCgpYCBsYXllciBhbmQgdGhlbiBhZGQgdGhlIGBnZW9tX3RleHRfcmVwZWwoKWAgbGF5ZXIgdXNpbmcgdGhlIG90aGVyIGBkZi5sYWJlbHNgIGRhdGEuZnJhbWUuIFRvIG1ha2UgaXQgbG9vayByaWdodCwgeW91IG1heSBuZWVkIHRvIGZ1dHogYXJvdW5kIHdpdGggdGhlIHZhcmlvdXMgZGF0YSBtYXBwaW5ncyBpbiB0aGUgYGFlc2AgZnVuY3Rpb25zLiAgU2VlIFt0aGlzIHNsaWRlXShodHRwczovL2R5ZXJsYWIuZ2l0aHViLmlvL0VOVlMtTGVjdHVyZXMvdmlzdWFsaXphdGlvbi9nZ3Bsb3RfZ3JhcGhpY3Mvc2xpZGVzLmh0bWwjNjIpIGZvciBhIHJlZnJlc2hlciBvbiB3aGF0IGBnZ3JlcGVsYCBuZWVkcyB0byBkbyBpdHMgam9iLgoKYGBge3J9CiMgR0dSZXBlbCAKbGlicmFyeSggZ2dyZXBlbCApCmBgYAoKCgoKCgoKClteMV06IElmIHlvdSBnZXQgYW4gZXJyb3Igd2hlbiB0cnlpbmcgdG8gbG9hZCBpbiB0aGUgZ2dyZXBlbCBsaWJyYXJ5IHNheWluZyBpdCBjb3VsZCBub3QgZmluZCB0aGUgbGlicmFyeSwgdGhlbiBpbnN0YWxsIGl0IHVzaW5nIGBpbnN0YWxsLnBhY2thZ2VzKCJnZ3JlcGVsIilgLgoKCg==