Remember, before you can use the tidyverse, you need to load the package.
library(tidyverse)
First Steps
More plots with the mpg dataset
(Taken form R4DS)
- Run 
ggplot(data = mpg). What do you see? 
- How many rows are in mpg? How many columns?
 
- What does the 
drv variable describe? You may want to use ?mpg to find out 
- Make a scatter plot of 
hwy vs cyl 
- What happens if you make a scatter plot of 
class vs drv? Why is the plot not useful? 
 
Plots with other datasets
- Take a look at the 
iris dataset. What are its dimensions? What do its columns represent? 
- What are the ranges of each of the numeric columns. The 
summary() function might help you here 
- Make a plot of sepal width vs sepal length, and set all of the points to be green
 
- Repeat the previous plot but colour each point by the species of the flower
 
 
Remaking plots
- Take a look at the first and last few rows of the 
mtcars dataset 
- Access the 
cyl column of the dataset. Is this variable categorical, discrete, or continuous? 
- What steps would you go about to remake the following plot?
 

 
 
More Aesthetics
Size, Transparency, and Shape
- Using the 
mpg dataset, make a plot of city mileage vs highway mileage where the size of each point is determined by engine size (displ) 
- Plot sepal length vs sepal width using the 
iris dataset and control the transparency (alpha) of each point using the species variable. 
- Have a play with the 
Orange data set (note the capital ‘O’). Make a scatter plot of circumference against age where the shape of each point is determined by which tree the observation belongs to 
- Remake the standard 
hwy vs displ plot using the mpg data set but make all of the points hollow diamonds. How about solid triangles? 
 
Choosing Appropriate Aesthetics
(Q1/2 form R4DS)
- Which variables in 
mpg are categorical? Which are continuous/discrete? (The data set help file may be of use) 
- Map a continuous variable to colour, size, and shape. How does this differ from when you map a categorical variable?
 
- Plot the standard 
hwy vs displ graph using mpg and map the variable class to the size aesthetic. Was this a good idea? 
- Have a discussion with a partner or think for yourself: Which of the aesthetics you know are the clearest for displaying categorical data and which are best for continuous?
 
- In your own opinion, order the following aesthetics by how clear they are in representing a continuous variable: size, colour, transparency
 
 
Common Problems
- Using the 
mpg data set, make a plot of city milage against engine size. Map the variable class to the aesthetic shape. Is everything as you would expect? 
- Type the following code into the console. Why do you recieve an error message?
 
ggplot(iris) +
  geom_point(x = Sepal.Length, y = Petal.Length)
- Take a look at the 
airquality dataset. Type the following code into the console. Is the plot as you expected? 
ggplot(airquality) +
  geom_point(aes(x = Wind, y = Temp, col = Month))
- Why are the points in this plot not blue?
 
ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy, colour = 'blue'))

- What happens when you map a variable to multiple aesthetics (say colour and size)? (It’s okay to answer, “nothing”, to this question but make sure you verify that first!)
 
 
 
Facetting
Basic Faceting
(Taken form R4DS)
- What happens when you facet a continuous variable?
 
- What do the empty cells in a plot with 
facet_grid(drv ~ cyl) mean? How do they relate to this plot? 
ggplot(mpg) +
  geom_point(aes(x = drv, y = cyl))
- What plots does the following code make? What does the 
. do? 
ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy)) +
  facet_grid(drv ~ .)
ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy)) +
  facet_grid(. ~ cyl)
- Take the first faceted plot from the presentation:
 
ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy)) +
  facet_wrap(~ class, nrow = 2)
What are the advantages of faceting instead of the colour aesthetic? What are the disadvantages? How might the balance change if you had a larger data set?
- Read 
?facet_wrap. What does nrow do? What does ncol do? What other options control the layout of the individual panels? Why doesn’t facet_grid() have nrow and ncol parameters? 
- When using 
facet_grid() you should usually put the variable with more unique levels in the columns. Why? 
 
Combining Facets with Aesthetics
- Create a scatter plot of petal length vs petal width using the 
iris dataset and facet by species 
- Repeat the above plot whilst also colouring the species. Don’t forget to hide the colour legend
 
- Using the 
mpg dataset, plot hwy vs cty, map displ to the size aesthetic, map class to point colour, and facet columns by cyl and rows by drv. This plot is ridiculous but it does demonstrate the flexibilty of ggplot2 
 
 
Going Beyond
Labelling
- Run the following code. What does the extra 
labs(...) layer do? 
ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy, colour = class)) +
  labs(x = "Engine Displacment (litres)", y = "Highway Milage (miles/gallon)",
       colour = "Car Type",
       title = "A scatter plot of engine displacment vs highway milage",
       subtitle = "Coloured by car type",
       caption = "Source: EPA (http://fueleconomy.gov)")
- Use this to take the plot from the ‘Remaking plots’ section and beautify it
 
- Pick any plot of your choosing an give it appropriate axis labels, a title, and - if possible - a data source
 
 
Diamonds and Overplotting
- Have a look at the 
diamonds dataset 
- Make a scatter plot of 
price against caret (this may take a long time to run). Is this plot easy to read? 
- How could you fix this problem? (perhaps you could manually set a certain aesthetic)
 
 
Explanatory and Response variables
- How do you decide which variable to map to the x-axis and which to plot to the y-axis?
 
- If you are unsure, web-search for the phrase “explanatory and response variables”
 
 
Positional Arguments
Begin with the following code
ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy, colour = factor(class)))

- Try removing 
x = and y = from your geom_point call. Does everything still work? 
- Try removing 
colour = from your geom_point call. Does everything still work? 
- Take the original plot and specify the aesthetics in a different order, say 
y then colour then x. Does everything still work? 
 
 
LS0tCnRpdGxlOiAiSW50byB0aGUgVGlkeXZlcnNlIgpzdWJ0aXRsZTogIlNlc3Npb24gT25lIEV4ZXJjaXNlcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKUmVtZW1iZXIsIGJlZm9yZSB5b3UgY2FuIHVzZSB0aGUgdGlkeXZlcnNlLCB5b3UgbmVlZCB0byBsb2FkIHRoZSBwYWNrYWdlLgoKYGBge3IgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKIyMgRmlyc3QgU3RlcHMKCiMjIyBNb3JlIHBsb3RzIHdpdGggdGhlIG1wZyBkYXRhc2V0CgooKipUYWtlbiBmb3JtIFI0RFMqKikKCjEuIFJ1biBgZ2dwbG90KGRhdGEgPSBtcGcpYC4gV2hhdCBkbyB5b3Ugc2VlPwoyLiBIb3cgbWFueSByb3dzIGFyZSBpbiBtcGc/IEhvdyBtYW55IGNvbHVtbnM/CjMuIFdoYXQgZG9lcyB0aGUgYGRydmAgdmFyaWFibGUgZGVzY3JpYmU/IFlvdSBtYXkgd2FudCB0byB1c2UgYD9tcGdgIHRvIGZpbmQgb3V0CjQuIE1ha2UgYSBzY2F0dGVyIHBsb3Qgb2YgYGh3eWAgdnMgYGN5bGAKNS4gV2hhdCBoYXBwZW5zIGlmIHlvdSBtYWtlIGEgc2NhdHRlciBwbG90IG9mIGBjbGFzc2AgdnMgYGRydmA/IFdoeSBpcyB0aGUgcGxvdCBub3QgdXNlZnVsPwoKIyMjIFBsb3RzIHdpdGggb3RoZXIgZGF0YXNldHMKCjEuIFRha2UgYSBsb29rIGF0IHRoZSBgaXJpc2AgZGF0YXNldC4gV2hhdCBhcmUgaXRzIGRpbWVuc2lvbnM/IFdoYXQgZG8gaXRzIGNvbHVtbnMgcmVwcmVzZW50PwoyLiBXaGF0IGFyZSB0aGUgcmFuZ2VzIG9mIGVhY2ggb2YgdGhlIG51bWVyaWMgY29sdW1ucy4gVGhlIGBzdW1tYXJ5KClgIGZ1bmN0aW9uIG1pZ2h0IGhlbHAgeW91IGhlcmUKMy4gTWFrZSBhIHBsb3Qgb2Ygc2VwYWwgd2lkdGggdnMgc2VwYWwgbGVuZ3RoLCBhbmQgc2V0IGFsbCBvZiB0aGUgcG9pbnRzIHRvIGJlIGdyZWVuCjQuIFJlcGVhdCB0aGUgcHJldmlvdXMgcGxvdCBidXQgY29sb3VyIGVhY2ggcG9pbnQgYnkgdGhlIHNwZWNpZXMgb2YgdGhlIGZsb3dlcgoKIyMjIFJlbWFraW5nIHBsb3RzCgoxLiBUYWtlIGEgbG9vayBhdCB0aGUgZmlyc3QgYW5kIGxhc3QgZmV3IHJvd3Mgb2YgdGhlIGBtdGNhcnNgIGRhdGFzZXQKMi4gQWNjZXNzIHRoZSBgY3lsYCBjb2x1bW4gb2YgdGhlIGRhdGFzZXQuIElzIHRoaXMgdmFyaWFibGUgY2F0ZWdvcmljYWwsIGRpc2NyZXRlLCBvciBjb250aW51b3VzPwozLiBXaGF0IHN0ZXBzIHdvdWxkIHlvdSBnbyBhYm91dCB0byByZW1ha2UgdGhlIGZvbGxvd2luZyBwbG90PwoKYGBge3IgZWNobz1GQUxTRX0KZ2dwbG90KG10Y2FycykgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkaXNwLCB5ID0gaHAsIGNvbG91ciA9IGZhY3RvcihjeWwpKSkKYGBgCgojIyBNb3JlIEFlc3RoZXRpY3MgCgojIyMgU2l6ZSwgVHJhbnNwYXJlbmN5LCBhbmQgU2hhcGUKCjEuIFVzaW5nIHRoZSBgbXBnYCBkYXRhc2V0LCBtYWtlIGEgcGxvdCBvZiBjaXR5IG1pbGVhZ2UgdnMgaGlnaHdheSBtaWxlYWdlIHdoZXJlIHRoZSBzaXplIG9mIGVhY2ggcG9pbnQgaXMgZGV0ZXJtaW5lZCBieSBlbmdpbmUgc2l6ZSAoYGRpc3BsYCkKMi4gUGxvdCBzZXBhbCBsZW5ndGggdnMgc2VwYWwgd2lkdGggdXNpbmcgdGhlIGBpcmlzYCBkYXRhc2V0IGFuZCBjb250cm9sIHRoZSB0cmFuc3BhcmVuY3kgKGBhbHBoYWApIG9mIGVhY2ggcG9pbnQgdXNpbmcgdGhlIGBzcGVjaWVzYCB2YXJpYWJsZS4KMy4gSGF2ZSBhIHBsYXkgd2l0aCB0aGUgYE9yYW5nZWAgZGF0YSBzZXQgKG5vdGUgdGhlIGNhcGl0YWwgJ08nKS4gTWFrZSBhIHNjYXR0ZXIgcGxvdCBvZiBjaXJjdW1mZXJlbmNlIGFnYWluc3QgYWdlIHdoZXJlIHRoZSBzaGFwZSBvZiBlYWNoIHBvaW50IGlzIGRldGVybWluZWQgYnkgd2hpY2ggdHJlZSB0aGUgb2JzZXJ2YXRpb24gYmVsb25ncyB0bwo0LiBSZW1ha2UgdGhlIHN0YW5kYXJkIGBod3lgIHZzIGBkaXNwbGAgcGxvdCB1c2luZyB0aGUgYG1wZ2AgZGF0YSBzZXQgYnV0IG1ha2UgYWxsIG9mIHRoZSBwb2ludHMgaG9sbG93IGRpYW1vbmRzLiBIb3cgYWJvdXQgc29saWQgdHJpYW5nbGVzPwoKIyMjIENob29zaW5nIEFwcHJvcHJpYXRlIEFlc3RoZXRpY3MKCigqKlExLzIgZm9ybSBSNERTKiopCgoxLiBXaGljaCB2YXJpYWJsZXMgaW4gYG1wZ2AgYXJlIGNhdGVnb3JpY2FsPyBXaGljaCBhcmUgY29udGludW91cy9kaXNjcmV0ZT8gKFRoZSBkYXRhIHNldCBoZWxwIGZpbGUgbWF5IGJlIG9mIHVzZSkKMi4gTWFwIGEgY29udGludW91cyB2YXJpYWJsZSB0byBjb2xvdXIsIHNpemUsIGFuZCBzaGFwZS4gSG93IGRvZXMgdGhpcyBkaWZmZXIgZnJvbSB3aGVuIHlvdSBtYXAgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZT8KMy4gUGxvdCB0aGUgc3RhbmRhcmQgYGh3eWAgdnMgYGRpc3BsYCBncmFwaCB1c2luZyBgbXBnYCBhbmQgbWFwIHRoZSB2YXJpYWJsZSBgY2xhc3NgIHRvIHRoZSBgc2l6ZWAgYWVzdGhldGljLiBXYXMgdGhpcyBhIGdvb2QgaWRlYT8KNC4gSGF2ZSBhIGRpc2N1c3Npb24gd2l0aCBhIHBhcnRuZXIgb3IgdGhpbmsgZm9yIHlvdXJzZWxmOiBXaGljaCBvZiB0aGUgYWVzdGhldGljcyB5b3Uga25vdyBhcmUgdGhlIGNsZWFyZXN0IGZvciBkaXNwbGF5aW5nIGNhdGVnb3JpY2FsIGRhdGEgYW5kIHdoaWNoIGFyZSBiZXN0IGZvciBjb250aW51b3VzPyAKNS4gSW4geW91ciBvd24gb3Bpbmlvbiwgb3JkZXIgdGhlIGZvbGxvd2luZyBhZXN0aGV0aWNzIGJ5IGhvdyBjbGVhciB0aGV5IGFyZSBpbiByZXByZXNlbnRpbmcgYSBjb250aW51b3VzIHZhcmlhYmxlOiBzaXplLCBjb2xvdXIsIHRyYW5zcGFyZW5jeQoKIyMjIENvbW1vbiBQcm9ibGVtcwoKMS4gVXNpbmcgdGhlIGBtcGdgIGRhdGEgc2V0LCBtYWtlIGEgcGxvdCBvZiBjaXR5IG1pbGFnZSBhZ2FpbnN0IGVuZ2luZSBzaXplLiBNYXAgdGhlIHZhcmlhYmxlIGBjbGFzc2AgdG8gdGhlIGFlc3RoZXRpYyBgc2hhcGVgLiBJcyBldmVyeXRoaW5nIGFzIHlvdSB3b3VsZCBleHBlY3Q/CjIuIFR5cGUgdGhlIGZvbGxvd2luZyBjb2RlIGludG8gdGhlIGNvbnNvbGUuIFdoeSBkbyB5b3UgcmVjaWV2ZSBhbiBlcnJvciBtZXNzYWdlPwoKYGBge3IgZXZhbCA9IEZBTFNFfQpnZ3Bsb3QoaXJpcykgKwogIGdlb21fcG9pbnQoeCA9IFNlcGFsLkxlbmd0aCwgeSA9IFBldGFsLkxlbmd0aCkKYGBgCgozLiBUYWtlIGEgbG9vayBhdCB0aGUgYGFpcnF1YWxpdHlgIGRhdGFzZXQuIFR5cGUgdGhlIGZvbGxvd2luZyBjb2RlIGludG8gdGhlIGNvbnNvbGUuIElzIHRoZSBwbG90IGFzIHlvdSBleHBlY3RlZD8KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZ2dwbG90KGFpcnF1YWxpdHkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gV2luZCwgeSA9IFRlbXAsIGNvbCA9IE1vbnRoKSkKYGBgCgo0LiBXaHkgYXJlIHRoZSBwb2ludHMgaW4gdGhpcyBwbG90IG5vdCBibHVlPwoKYGBge3IgbWVzc2FnZSA9IEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvdXIgPSAnYmx1ZScpKQpgYGAKCjUuIFdoYXQgaGFwcGVucyB3aGVuIHlvdSBtYXAgYSB2YXJpYWJsZSB0byBtdWx0aXBsZSBhZXN0aGV0aWNzIChzYXkgY29sb3VyIGFuZCBzaXplKT8gKEl0J3Mgb2theSB0byBhbnN3ZXIsICJub3RoaW5nIiwgdG8gdGhpcyBxdWVzdGlvbiBidXQgbWFrZSBzdXJlIHlvdSB2ZXJpZnkgdGhhdCBmaXJzdCEpCgojIyBGYWNldHRpbmcKCiMjIyBCYXNpYyBGYWNldGluZwoKKCoqVGFrZW4gZm9ybSBSNERTKiopCgoxLiBXaGF0IGhhcHBlbnMgd2hlbiB5b3UgZmFjZXQgYSBjb250aW51b3VzIHZhcmlhYmxlPwoyLiBXaGF0IGRvIHRoZSBlbXB0eSBjZWxscyBpbiBhIHBsb3Qgd2l0aCBgZmFjZXRfZ3JpZChkcnYgfiBjeWwpYCBtZWFuPyBIb3cgZG8gdGhleSByZWxhdGUgdG8gdGhpcyBwbG90PwoKYGBge3IgZXZhbCA9IEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRydiwgeSA9IGN5bCkpCmBgYAoKMy4gV2hhdCBwbG90cyBkb2VzIHRoZSBmb2xsb3dpbmcgY29kZSBtYWtlPyBXaGF0IGRvZXMgdGhlIGAuYCBkbz8KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZ2dwbG90KG1wZykgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkaXNwbCwgeSA9IGh3eSkpICsKICBmYWNldF9ncmlkKGRydiB+IC4pCgpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkgKwogIGZhY2V0X2dyaWQoLiB+IGN5bCkKYGBgCgo0LiBUYWtlIHRoZSBmaXJzdCBmYWNldGVkIHBsb3QgZnJvbSB0aGUgcHJlc2VudGF0aW9uOgoKYGBge3IgZXZhbCA9IEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5KSkgKwogIGZhY2V0X3dyYXAofiBjbGFzcywgbnJvdyA9IDIpCmBgYAoKV2hhdCBhcmUgdGhlIGFkdmFudGFnZXMgb2YgZmFjZXRpbmcgaW5zdGVhZCBvZiB0aGUgY29sb3VyIGFlc3RoZXRpYz8gV2hhdCBhcmUgdGhlIGRpc2FkdmFudGFnZXM/IEhvdyBtaWdodCB0aGUgYmFsYW5jZSBjaGFuZ2UgaWYgeW91IGhhZCBhIGxhcmdlciBkYXRhIHNldD8KCjUuIFJlYWQgYD9mYWNldF93cmFwYC4gV2hhdCBkb2VzIGBucm93YCBkbz8gV2hhdCBkb2VzIGBuY29sYCBkbz8gV2hhdCBvdGhlciBvcHRpb25zIGNvbnRyb2wgdGhlIGxheW91dCBvZiB0aGUgaW5kaXZpZHVhbCBwYW5lbHM/IFdoeSBkb2Vzbid0IGBmYWNldF9ncmlkKClgIGhhdmUgYG5yb3dgIGFuZCBgbmNvbGAgcGFyYW1ldGVycz8KNi4gV2hlbiB1c2luZyBgZmFjZXRfZ3JpZCgpYCB5b3Ugc2hvdWxkIHVzdWFsbHkgcHV0IHRoZSB2YXJpYWJsZSB3aXRoIG1vcmUgdW5pcXVlIGxldmVscyBpbiB0aGUgY29sdW1ucy4gV2h5PwoKCiMjIyBDb21iaW5pbmcgRmFjZXRzIHdpdGggQWVzdGhldGljcwoKMS4gQ3JlYXRlIGEgc2NhdHRlciBwbG90IG9mIHBldGFsIGxlbmd0aCB2cyBwZXRhbCB3aWR0aCB1c2luZyB0aGUgYGlyaXNgIGRhdGFzZXQgYW5kIGZhY2V0IGJ5IHNwZWNpZXMKMi4gUmVwZWF0IHRoZSBhYm92ZSBwbG90IHdoaWxzdCBhbHNvIGNvbG91cmluZyB0aGUgc3BlY2llcy4gRG9uJ3QgZm9yZ2V0IHRvIGhpZGUgdGhlIGNvbG91ciBsZWdlbmQKMy4gVXNpbmcgdGhlIGBtcGdgIGRhdGFzZXQsIHBsb3QgYGh3eWAgdnMgYGN0eWAsIG1hcCBgZGlzcGxgIHRvIHRoZSBgc2l6ZWAgYWVzdGhldGljLCBtYXAgYGNsYXNzYCB0byBwb2ludCBjb2xvdXIsIGFuZCBmYWNldCBjb2x1bW5zIGJ5IGBjeWxgIGFuZCByb3dzIGJ5IGBkcnZgLiBUaGlzIHBsb3QgaXMgcmlkaWN1bG91cyBidXQgaXQgZG9lcyBkZW1vbnN0cmF0ZSB0aGUgZmxleGliaWx0eSBvZiBgZ2dwbG90MmAKCiMjIEdvaW5nIEJleW9uZAoKIyMjIExhYmVsbGluZwoKMS4gUnVuIHRoZSBmb2xsb3dpbmcgY29kZS4gV2hhdCBkb2VzIHRoZSBleHRyYSBgbGFicyguLi4pYCBsYXllciBkbz8KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZ2dwbG90KG1wZykgKwogIGdlb21fcG9pbnQoYWVzKHggPSBkaXNwbCwgeSA9IGh3eSwgY29sb3VyID0gY2xhc3MpKSArCiAgbGFicyh4ID0gIkVuZ2luZSBEaXNwbGFjbWVudCAobGl0cmVzKSIsIHkgPSAiSGlnaHdheSBNaWxhZ2UgKG1pbGVzL2dhbGxvbikiLAogICAgICAgY29sb3VyID0gIkNhciBUeXBlIiwKICAgICAgIHRpdGxlID0gIkEgc2NhdHRlciBwbG90IG9mIGVuZ2luZSBkaXNwbGFjbWVudCB2cyBoaWdod2F5IG1pbGFnZSIsCiAgICAgICBzdWJ0aXRsZSA9ICJDb2xvdXJlZCBieSBjYXIgdHlwZSIsCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogRVBBIChodHRwOi8vZnVlbGVjb25vbXkuZ292KSIpCmBgYAoKMi4gVXNlIHRoaXMgdG8gdGFrZSB0aGUgcGxvdCBmcm9tIHRoZSAnUmVtYWtpbmcgcGxvdHMnIHNlY3Rpb24gYW5kIGJlYXV0aWZ5IGl0CjMuIFBpY2sgYW55IHBsb3Qgb2YgeW91ciBjaG9vc2luZyBhbiBnaXZlIGl0IGFwcHJvcHJpYXRlIGF4aXMgbGFiZWxzLCBhIHRpdGxlLCBhbmQgLSBpZiBwb3NzaWJsZSAtIGEgZGF0YSBzb3VyY2UKCiMjIyBEaWFtb25kcyBhbmQgT3ZlcnBsb3R0aW5nCgoxLiBIYXZlIGEgbG9vayBhdCB0aGUgYGRpYW1vbmRzYCBkYXRhc2V0CjIuIE1ha2UgYSBzY2F0dGVyIHBsb3Qgb2YgYHByaWNlYCBhZ2FpbnN0IGBjYXJldGAgKHRoaXMgbWF5IHRha2UgYSBsb25nIHRpbWUgdG8gcnVuKS4gSXMgdGhpcyBwbG90IGVhc3kgdG8gcmVhZD8KMy4gSG93IGNvdWxkIHlvdSBmaXggdGhpcyBwcm9ibGVtPyAocGVyaGFwcyB5b3UgY291bGQgbWFudWFsbHkgc2V0IGEgY2VydGFpbiBhZXN0aGV0aWMpCgojIyMgRXhwbGFuYXRvcnkgYW5kIFJlc3BvbnNlIHZhcmlhYmxlcwoKMS4gSG93IGRvIHlvdSBkZWNpZGUgd2hpY2ggdmFyaWFibGUgdG8gbWFwIHRvIHRoZSB4LWF4aXMgYW5kIHdoaWNoIHRvIHBsb3QgdG8gdGhlIHktYXhpcz8KMi4gSWYgeW91IGFyZSB1bnN1cmUsIHdlYi1zZWFyY2ggZm9yIHRoZSBwaHJhc2UgImV4cGxhbmF0b3J5IGFuZCByZXNwb25zZSB2YXJpYWJsZXMiCgojIyMgUG9zaXRpb25hbCBBcmd1bWVudHMKCkJlZ2luIHdpdGggdGhlIGZvbGxvd2luZyBjb2RlCgpgYGB7ciBldmFsIEZBTFNFfQpnZ3Bsb3QobXBnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGRpc3BsLCB5ID0gaHd5LCBjb2xvdXIgPSBmYWN0b3IoY2xhc3MpKSkKYGBgCgoxLiBUcnkgcmVtb3ZpbmcgYHggPSBgIGFuZCBgeSA9IGAgZnJvbSB5b3VyIGBnZW9tX3BvaW50YCBjYWxsLiBEb2VzIGV2ZXJ5dGhpbmcgc3RpbGwgd29yaz8KMi4gVHJ5IHJlbW92aW5nIGBjb2xvdXIgPSBgIGZyb20geW91ciBgZ2VvbV9wb2ludGAgY2FsbC4gRG9lcyBldmVyeXRoaW5nIHN0aWxsIHdvcms/CjMuIFRha2UgdGhlIG9yaWdpbmFsIHBsb3QgYW5kIHNwZWNpZnkgdGhlIGFlc3RoZXRpY3MgaW4gYSBkaWZmZXJlbnQgb3JkZXIsIHNheSBgeWAgdGhlbiBgY29sb3VyYCB0aGVuIGB4YC4gRG9lcyBldmVyeXRoaW5nIHN0aWxsIHdvcms/Cg==