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.
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.
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
library 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 )
LS0tCnRpdGxlOiAiR3JhcGhpY3MgaW4gUiIKYXV0aG9yOiAiWW91ciBOYW1lIEhlcmUiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIGZpZ19jYXB0aW9uOiB5ZXMKLS0tCgojIFRoZSBEYXRhCgpGb3IgdGhpcyBob21ld29yayB3ZSB3aWxsIGJlIHdvcmtpbmcgd2l0aCB0aGUgZGF0YSB0aGF0IHdlcmUgdXNlZCBpbiB0aGUgbGVjdHVyZSBvbiBgZ2dwbG90YCBmcm9tIHRoZSAyMDExICpUaGUgRWNvbm9taXN0KiBhcnRpY2xlIGxvb2tpbmcgYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGh1bWFuIGRldmVsb3BtZW50IGFuZCBwZXJjZWl2ZWQgY29ycnVwdGlvbi4KCiFbKkZpZ3VyZSAxOiogVGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBwZXJjZXB0aW9uIG9mIGNvcnJ1cHRpb24gYW5kIHRoZSBodW1hbiBkZXZlbG9wbWVudCBpbmRleCBmcm9tIDIwMTEgZm9yIDE3NCBuYXRpb25zIHN0YXRlcy5dKGh0dHBzOi8vbGl2ZS5zdGF0aWNmbGlja3IuY29tLzY1NTM1LzUwMjk0NDEyNzEzXzI1YmJkNTIyMzBfY19kLmpwZykKClRoZSBkYXRhIGFyZSBsb2NhdGVkIG9uIHRoZSBbY2xhc3MgR2l0SHViIHNpdGVdKGh0dHBzOi8vZ2l0aHViLmNvbS9keWVybGFiL0VOVlMtTGVjdHVyZXMpIGFuZCBjYW4gYmUgYWNjZXNzZWQgYnkgdGhlIGZvbGxvd2luZyBVUkwsIHdoaWNoIGlzIGJlaW5nIHByZXNlbnRlZCBhcyBhIENTViBmaWxlLgoKYGBge3J9CiMgVGhlIFVSTCBmb3IgdGhlIGRhdGEgb24gR2l0SHViCnVybCA8LSAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2R5ZXJsYWIvRU5WUy1MZWN0dXJlcy9tYXN0ZXIvZGF0YS9FY29ub21pc3REYXRhLmNzdiIKYGBgCgpVc2UgdGhlIFVSTCBhYm92ZSBhbmQgbG9hZCB0aGUgZGF0YSBpbnRvIFIgYW5kIHByZXNlbnQgYSBzdW1tYXJ5LiAgTmFtZSB0aGlzIGRhdGEgZnJhbWUgYGRmYCBiZWNhdXNlIHNvbWUgY29kZSBiZWxvdyB0aGF0IEkgZ2l2ZSBhc3N1bWVzIHRoYXQgbmFtZS4KCmBgYHtyfQojIyBMb2FkIHRoZSBkYXRhIGhlcmUuCmxpYnJhcnkoIHJlYWRyICkKCmRmIDwtIHJlYWRfY3N2KCB1cmwgKQpgYGAKCkFzIGl0IHN0YW5kcywgd2UgYXJlIGdvaW5nIHRvIG5lZWQgdG8gdHVybiB0aGUgYFJlZ2lvbmAgY29sdW1uIGZyb20gYSByYXcgYGNoYXJhY3RlcmAgdHlwZSB0byBhIGBmYWN0b3JgIGRhdGEgdHlwZS4gIFRvIHRvIHRoaXMsIHdlIGNhbiB1c2UgdGhlIGZ1bmN0aW9uIGBhcy5mYWN0b3IoKWAgYW5kIGFzc2lnbiBpdCBiYWNrIHRvIHRoZSBgZGF0YS5mcmFtZWAuCgoKYGBge3J9CiMgVHVybiBSZWdpb24gaW50byBmYWN0b3IKCmRmJFJlZ2lvbiA8LSBhcy5mYWN0b3IoIGRmJFJlZ2lvbiAgKQpgYGAKCgoqSW4gYWxsIHRoZSBwbG90IG9uIHRoaXMgaG9tZXdvcmssIHlvdSBtdXN0IG1ha2UgYW4gbGVnZW5kIHdoZW4gYXBwcm9wcmlhdGUgYW5kIGxhYmVsIHRoZSBheGVzIHByb3Blcmx5LioKCgojIFVuaXZhcmlhdGUgRGF0YQoKRm9yIHRoaXMgc2VjdGlvbiwgZm9jdXMgb24gaGlzdG9ncmFtcyBhbmQgZGVuc2l0eSBwbG90cy4gIENyZWF0ZSBhIGhpc3RvcmdyYW0gcGxvdCBhbmQgYSBkZW5zaXR5IHBsb3QsIG9uZSBmb3IgYnVpbHQtaW4gZ3JhcGhpY3MgYW5kIHRoZSBvdGhlciB1c2luZyBgZ2dwbG90YC4gIEZlZWwgZnJlZSB0byBlbWJlbGxpc2ggdGhlbSBhcyB5b3UgcGxlYXNlIGJ1dCB5b3UgKiptdXN0KiogaGF2ZSBwcm9wZXJseSBsYWJlbGVkIGF4ZXMuCgpgYGB7cn0KIyBCdWlsdC1pbiBoaXN0IGZvciBIREkKbWVhbkhESSA8LSBieSggZGYkSERJLCBkZiRSZWdpb24sIG1lYW4pCmJhcnBsb3QoIG1lYW5IREkgKQoKCgpgYGAKCmBgYHtyfQojIERlbnNpdHkgcGxvdCBmb3IgSERJIHVzaW5nIGJ1aWx0LWluIGdyYXBoaWNzCgpgYGAKCk5vdyBmb3IgQ1BJLCBkbyB0aGUgc2FtZSB0aGluZ3MgdXNpbmcgYGdncGxvdGAgZ3JhcGhpY3MuICBZb3UgbXVzdCBmaXJzdCBsb2FkIGluIHRoZSBgZ2dwbG90YCBsaWJyYXJ5LgoKYGBge3J9CiMgTG9hZCBpbiBHR1Bsb3QgbGlicmFyeQpsaWJyYXJ5KCBnZ3Bsb3QyICkKYGBgCgpUaGVuIG1ha2UgdGhlIHBsb3RzCgpgYGB7cn0KIyBHR1Bsb3QgaGlzdG9ncmFtCmBgYAoKYGBge3J9CiMgR0dQbG90IGRlbnNpdHkgUGxvdApgYGAKCmBgYHtyfQojIE92ZXJsYXkgZGVuc2l0eSBvbiB0b3Agb2YgaGlzdG9ncmFtIHVzaW5nIGdncGxvdApgYGAKCgojIENhdGVnb3JpY2FsIERhdGEKCkZvciBkYXRhIHRoYXQgaGFzIGJvdGggY2F0ZWdvcmljYWwgZGF0YSBhbmQgY29udGludW91cyBkYXRhLCB3ZSBjYW4gZGlzcGxheSB0aGUgZGF0YSBpbiBzZXZlcmFsIGRpZmZlcmVudCB3YXlzLiAgCgojIyBCYXIgUGxvdHMgCgpGb3Igc3RhbmRhcmQgYmFyIHBsb3RzLCB3ZSB3aWxsIGNyZWF0ZSBhIG5ldyBgZGF0YS5mcmFtZWAgdGhhdCBoYXMgYXZlcmFnZSB2YWx1ZXMgZm9yIHRoZSBjb250aW51b3VzIHZhcmlhYmxlIGFjcm9zcyBlYWNoIG9mIHRoZSBsZXZlbHMgb2YgdGhlIGNhdGVnb3JpY2FsIHZhcmlhYmxlLiAgWW91IGNhbiBkbyB0aGlzIG1hbnVhbGx5IG9yIGJ5IHVzaW5nIHRoZSBgYnkoKWAgZnVuY3Rpb24uICBJZiB5b3UgdXNlIGBieSgpYCB5b3UnbGwgbmVlZCB0byBjb2VyY2UgaXQgaW50byBhIG51bWVyaWMgZGF0YSB2ZWN0b3IgdmlhIGBhcy5udW1lcmljKClgLiAgSWYgeW91IG5lZWQgYSByZW1pbmRlciBvZiB0aGlzLCBjaGVjayBvdXQgW3RoaXMgc2xpZGVdKGh0dHBzOi8vZHllcmxhYi5naXRodWIuaW8vRU5WUy1MZWN0dXJlcy92aXN1YWxpemF0aW9uL2Jhc2ljX3Zpc3VhbGl6YXRpb24vc2xpZGVzLmh0bWwjNTEpLgoKYGBge3J9CiMgQ3JlYXRlIG5ldyBkYXRhLmZyYW1lIHdpdGggYXZlcmFnZXMgZm9yIEhESSBieSBSZWdpb24KYGBgCgpDcmVhdGUgYSBiYXJwbG90IHVzaW5nIGJ1aWx0LWluIGdyYXBoaWNzLgoKYGBge3J9CiMgYmFycGxvdApgYGAKCkdHUGxvdCBoYXMgc2V2ZXJhbCB3YXlzIHRvIGxvb2sgYXQgdGhlc2Uga2luZHMgb2YgZGF0YS4gIFRoZXJlIGlzIGEgW0NoZWF0IFNoZWV0XShodHRwczovL2dpdGh1Yi5jb20vcnN0dWRpby9jaGVhdHNoZWV0cy9ibG9iL21hc3Rlci9kYXRhLXZpc3VhbGl6YXRpb24tMi4xLnBkZikgZm9yIGEgYnVuY2ggb2YgYGdncGxvdGAgZnVuY3Rpb25zIGluIENhbnZhcyAoYXMgd2VsbCBhcyBHaXRIdWIgZnJvbSB0aGF0IGxpbmspLiAgCgpUbyBjcmVhdGUgYSBiYXIgcGxvdCBpbiBgZ2dwbG90YCBvbmUgY2FuIHVzZSB0aGUgYGdlb21fY29sKClgIGdlb21ldHJpYyBsYXllci4gIAoKYGBge3J9CiMgZ2VvbV9jb2wgcGxvdApgYGAKClRoYXQgcGxvdCBsb29rcyBncmVhdCBidXQgdGhlIHgtYXhpcyBsYWJlbHMgYXJlIGFsbCBzY3Jld2VkIHVwLiAgVG8gZml4IHRoaXMgeW91IGNhbiBhZGQgc29tZSBjdXN0b21pemF0aW9uIHRvIHRoZSB0aGVtZSBieSBjaGFuZ2luZyB0aGUgdGV4dCBlbGVtZW50cyBvbiB0aGUgeCBheGlzLiAgVGhlIGNvZGUgaW4gdGhlIGNodW5rIGJlbG93LCB3aGVuIGFkZGVkIHRvIHlvdXIgcGxvdCBjb2RlLCB3aWxsIHJvdGF0ZSB0aGUgYW5nbGUgb2YgdGhlIHRleHQgYnkgNDXCsCBhbmQganVzdGlmaWVkLiAgQWRkIHlvdXIgY29kZSB0byB0aGlzIGNodW5rIGFuZCBzZWUgaG93IHRoaXMgY2hhbmdlcyB0aGUgYXhpcyBsYWJlbHMgKGZlZWwgZnJlZSB0byBwbGF5IGFyb3VuZCB3aXRoIHRoZW0pLiAgCgpOb3RlOiBZb3UgKm11c3QqIGNoYW5nZSBgZXZhbD1GQUxTRWAgdG8gYGV2YWw9VFJVRWAgdG8gZ2V0IHRoaXMgY2h1bmNrIHRvIHdvcmsuICBJIGhhZCB0byBzZXQgaXQgdG8gbm90IHJ1biBiZWNhdXNlIHRoZSB0ZXh0IGB7WU9VUiBQTE9UIENPREUgSEVSRX1gIHdpbGwgbm90IGNvbXBpbGUuCgpgYGB7ciBldmFsPUZBTFNFfQojIEZpeCB0aGUgYXhlcwp7WU9VUiBQTE9UIENPREUgSEVSRX0gKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdD0xKSkKYGBgCgojIyBCb3ggcGxvdHMgJiBvdGhlcnMKCkEgQm94cGxvdCBuZWVkcyBhbGwgdGhlIGRhdGEgdG8gYmUgYWJsZSB0byBkaXNwbGF5IHRoZSBkaXN0cmlidXRpb24gb2YgdmFsdWVzLCBzbyB3ZSdsbCBiZSB1c2luZyB0aGUgd2hvbGUgZGF0YSBmcmFtZSBhZ2Fpbi4KCmBgYHtyfQojIGJveHBsb3Qgb2YgSERJIGJ5IFJlZ2lvbiB1c2luZyBidWlsdC1pbiBncmFwaGljcy4KYGBgCgpOb3cgdGhlIHNhbWUgdXNpbmcgYGdncGxvdGAuCgpgYGB7cn0KIyBHR1Bsb3QgZ2VvbV9ib3hwbG90CmBgYAoKVGhlIGBnZ3Bsb3RgIGxpYnJhcnkgaGFzIGFkZGl0aW9uYWwgd2F5cyB0byB2aXN1YWxpemUgdGhlc2Uga2luZHMgb2YgZGF0YS4gTG9vayBhdCB0aGUgQ2hlYXRTaGVldCBpZiB5b3UgbmVlZCBhc3Npc3RhbmNlIG9yIHRoZSBidWlsdC1pbiBoZWxwIGZpbGUgZm9yIGBnZW9tX3Zpb2xpbmAgdG8gbWFrZSB0aGlzIHBsb3QuCgoKCmBgYHtyfQojIExvb2sgdXAgZ2VvbV92aW9saW4gYW5kIHVzZSB0aGF0IGZvciBwbG90dGluZwpgYGAKCiMjIyBBZGRpbmcgQ29sb3JzCgpUYWtlIHRoZSB2aW9saW4gcGxvdCBhYm92ZSBhbmQgY29sb3IgZWFjaCByZWdpb24gaW4gYSBkaWZmZXJlbnQgY29sb3IuICAKCmBgYHtyfQojIENvbG9yZWQgdmlvbGlucwpgYGAKCgojIENvbnRpbnVvdXMgQml2YXJpYXRlIERhdGEKClVzaW5nIHRoZSBidWlsdC1pbiBgcGxvdCgpYCBmdW5jdGlvbiBjcmVhdGUgdGhlIGZvbGxvd2luZyBzY2F0dGVyIHBsb3RzLiBUaGUgcGxvdCBjaGFyYWN0ZXJzIGFuZCBvdGhlciBjdXN0b21pemF0aW9uIGFyZSBmb3VuZCBvbiBbdGhpcyBzbGlkZV0oaHR0cHM6Ly9keWVybGFiLmdpdGh1Yi5pby9FTlZTLUxlY3R1cmVzL3Zpc3VhbGl6YXRpb24vYmFzaWNfdmlzdWFsaXphdGlvbi9zbGlkZXMuaHRtbCMyOCkgZnJvbSB0aGUgbGVjdHVyZSBvbiBidWlsdC1pbiBncmFwaGljcy4KCgpgYGB7cn0KIyBIREkgYXMgYSBmdW5jdGlvbiBvZiBDUEkgd2l0aCBSZWdpb25zIGRlZmluZWQgYnkgcGxvdCBjaGFyYWN0ZXIgICsgbGVnZW5kCmBgYAoKVXNlIHdoYXRldmVyIGNvbG9yIHNjaGVtZSB5b3UgbGlrZS4KCmBgYHtyfQojIEhESSBhcyBhIGZ1bmN0aW9uIG9mIENQSSB3aXRoIFJlZ2lvbnMgZGVmaW5lZCBieSBjb2xvciArIGxlZ2VuZApgYGAKCk5vdyBkbyB0aGUgc2FtZSB3aXRoIGBnZ3Bsb3RgIHVzaW5nIHJlZ2lvbnMgYXMgZWl0aGVyIHBsb3QgY2hhcmFjdGVyIG9yIGNvbG9yLgoKYGBge3J9CiMgSERJIGFzIGZ1bmN0aW9uIG9mIENQSSB3aXRoIFJlZ2lvbiBkaWZmZXJlbmNlcy4KYGBgCgoKCiMgTGFiZWxzCgpPSywgc28gdGhlIGxhc3QgdGhpbmcgd2UgYXJlIGdvaW5nIHRvIGRvIGlzIGRlZmluZSBhIHNlcGFyYXRlIGBkYXRhLmZyYW1lYCB0aGF0IGhhcyBqdXN0IHRoZSBsYWJlbHMgc28gd2UgY2FuIG1ha2UgaXQgbG9vayBhIGJpdCBsaWtlIHRoZSBvcmlnaW5hbCBwbG90LiAgVG8gZG8gdGhpcywgSSBkZWZpbmUgYSBuZXcgZGF0YS5mcmFtZSB3aXRoIGp1c3QgdGhlIGNvdW50cmllcyB0aGF0IEknbSBpbnRlcmVzdGVkIGluIHBsb3R0aW5nLgoKYGBge3J9CkNvdW50cnkgPC0gYygiUnVzc2lhIiwgIlZlbmV6dWVsYSIsICJJcmFxIiwgIk15YW5tYXIiLCAiU3VkYW4iLAogICAgICAgICAgICAgIkFmZ2hhbmlzdGFuIiwgIkNvbmdvIiwgIkdyZWVjZSIsICJBcmdlbnRpbmEiLCAiQnJhemlsIiwgCiAgICAgICAgICAgICAiSW5kaWEiLCAiSXRhbHkiLCAiQ2hpbmEiLCAiU291dGggQWZyaWNhIiwgIlNwYW5lIiwgCiAgICAgICAgICAgICAiQm90c3dhbmEiLCAiQ2FwZSBWZXJkZSIsICJCaHV0YW4iLCAiUndhbmRhIiwgIkZyYW5jZSIsIAogICAgICAgICAgICAgIlVuaXRlZCBTdGF0ZXMiLCAiR2VybWFueSIsICJCcml0YWluIiwgIkJhcmJhZG9zIiwgIk5vcndheSIsIAogICAgICAgICAgICAgIkphcGFuIiwiTmV3IFplYWxhbmQiLCAiU2luZ2Fwb3JlIikKZGYubGFiZWxzIDwtIGRhdGEuZnJhbWUoIENvdW50cnkgKQpgYGAKCk5leHQsIEkgdGFrZSB0aGlzIG5ldyBkYXRhLmZyYW1lIGFuZCB0aGUgb3JpZ2luYWwgb25lIGFuZCB1c2UgdGhlIGBtZXJnZSgpYCBmdW5jdGlvbi4KCiFbKkZpZ3VyZSAyOiogSGVscCBmaWxlIGZvciBgbWVyZ2UoKWAuXShodHRwczovL2xpdmUuc3RhdGljZmxpY2tyLmNvbS82NTUzNS81MDM0ODcwMDU4Nl9jOWVlNjgxNDk0X2NfZC5qcGcpCgpXaGF0IHRoaXMgZnVuY3Rpb24gKnJlcXVpcmVzKiBpcyB0aGF0IHRoZSB0d28gZGF0YS5mcmFtZXMgKiptdXN0KiogaGF2ZSBhIGNvbHVtIHdpdGggdGhlIHNhbWUgbmFtZS4gIEluIHRoaXMgY2FzZSwgYm90aCB0aGUgb3JpZ2luYWwgZGF0YS5mcmFtZSBoYWQgb25lIG5hbWVkIGBDb3VudHJ5YCBhcyBkaWQgdGhlIG5ldyBvbmUuICBJJ20gYXNzdW1pbmcgdGhhdCB0aGUgb3JpZ2luYWwgZGF0YSB3YXMgbG9hZGVkIGluIGFzIHRoZSB2YXJpYWJsZSBgZGZgIGFzIHJlcXVlc3RlZCBhYm92ZeKAlGlmIHlvdSBuYW1lZCBpdCBzb21ldGhpbmcgZWxzZSwgdGhlbiByZXBsYWNlIHlvdXIgdmFyaWFibGUgbmFtZSB3aXRoIHRoZSBgZGZgIGluIHRoZSBmaXJzdCBsaW5lIG9mIHRoZSBjb2RlIGJlbG93LgoKYGBge3J9CmRmLmxhYmVscyA8LSBtZXJnZSggZGYubGFiZWxzLCBkZikKZGYubGFiZWxzCmBgYAoKCk5vdywgbGV0J3MgbG9hZCBpbiB0aGUgYGdncmVwZWxgIGxpYnJhcnlbXjFdIGFuZCB1c2UgYm90aCBvZiB0aGVzZSBkYXRhLmZyYW1lcyB0byBhZGQgbGFiZWxzIHRvIGEgc2NhdHRlciBwbG90LiAgVG8gZG8gdGhpcywgeW91J2xsIGhhdmUgdG8gdXNlIHRoZSBmdWxsIGRhdGEgZnJhbWUgdG8gbGF5IGRvd24gYSBgZ2VvbV9wb2ludCgpYCBsYXllciBhbmQgdGhlbiBhZGQgdGhlIGBnZW9tX3RleHRfcmVwZWwoKWAgbGF5ZXIgdXNpbmcgdGhlIG90aGVyIGBkZi5sYWJlbHNgIGRhdGEuZnJhbWUuIFRvIG1ha2UgaXQgbG9vayByaWdodCwgeW91IG1heSBuZWVkIHRvIGZ1dHogYXJvdW5kIHdpdGggdGhlIHZhcmlvdXMgZGF0YSBtYXBwaW5ncyBpbiB0aGUgYGFlc2AgZnVuY3Rpb25zLiAgU2VlIFt0aGlzIHNsaWRlXShodHRwczovL2R5ZXJsYWIuZ2l0aHViLmlvL0VOVlMtTGVjdHVyZXMvdmlzdWFsaXphdGlvbi9nZ3Bsb3RfZ3JhcGhpY3Mvc2xpZGVzLmh0bWwjNjIpIGZvciBhIHJlZnJlc2hlciBvbiB3aGF0IGBnZ3JlcGVsYCBuZWVkcyB0byBkbyBpdHMgam9iLgoKYGBge3J9CiMgR0dSZXBlbCAKbGlicmFyeSggZ2dyZXBlbCApCmBgYAoKCgoKCgoKClteMV06IElmIHlvdSBnZXQgYW4gZXJyb3Igd2hlbiB0cnlpbmcgdG8gbG9hZCBpbiB0aGUgZ2dyZXBlbCBsaWJyYXJ5IHNheWluZyBpdCBjb3VsZCBub3QgZmluZCB0aGUgbGlicmFyeSwgdGhlbiBpbnN0YWxsIGl0IHVzaW5nIGBpbnN0YWxsLnBhY2thZ2VzKCJnZ3JlcGVsIilgLgoKCg==