Data Science Module
Making memes in R
hagrid <- "https://i.imgflip.com/13wb2t.jpg"
meme(hagrid, "Yer a wizard", "with coding", font = "sans")

Note: Some warnings may appear in your R Console as this code is executing. Don’t worry about it, it is safe to ignore these warnings.
success_kid <- "http://i0.kym-cdn.com/entries/icons/mobile/000/000/745/success.jpg"
success <- meme(success_kid, "Using R", "to make memes", font = "sans")
success

An example command to save the success
object to the imaginary filepath "STM1001/Data Science/success_kid_R_meme.png"
is shown below.
meme_save(success, file="STM1001/Data Science/success_kid_R_meme.png")
Please refer to the previous steps of 1 for a guide on loading an image, adding text, and then saving your creation.
Customizing GIFs in R
Please note that for this question, while the code to present the gifs is included, the gifs themselves are not reproduced in the documentation below.
install.packages("magick")
library(magick)
Earth <- image_read("https://i.giphy.com/media/mf8UbIDew7e8g/giphy.gif")
Earth
rev(Earth) %>%
image_flip() %>%
image_annotate(" Meanwhile, in Australia", size = 40, color = "white")
Drawing a fish in R
install.packages("rfishdraw")
install.packages("patchwork")
install.packages("ggplot2")
library("rfishdraw")
library("patchwork")
library("ggplot2")
get_polylines(path = "inst/fishdraw.js",
format = "smil",
output = "animated.svg",
draw_type = "random")
windows()
fish_draw()
fish_draw(col = "blue")

As an example, you may have changed the fish colour to red, in which case your code would look like this:
fish_draw(col = "red")
Palmer Penguins Data Set
install.packages("palmerpenguins")
library(palmerpenguins)
# This code summarises the data in the `palmerpenguins` package.
summary(penguins)
## species island bill_length_mm bill_depth_mm
## Adelie :152 Biscoe :168 Min. :32.10 Min. :13.10
## Chinstrap: 68 Dream :124 1st Qu.:39.23 1st Qu.:15.60
## Gentoo :124 Torgersen: 52 Median :44.45 Median :17.30
## Mean :43.92 Mean :17.15
## 3rd Qu.:48.50 3rd Qu.:18.70
## Max. :59.60 Max. :21.50
## NA's :2 NA's :2
## flipper_length_mm body_mass_g sex year
## Min. :172.0 Min. :2700 female:165 Min. :2007
## 1st Qu.:190.0 1st Qu.:3550 male :168 1st Qu.:2007
## Median :197.0 Median :4050 NA's : 11 Median :2008
## Mean :200.9 Mean :4202 Mean :2008
## 3rd Qu.:213.0 3rd Qu.:4750 3rd Qu.:2009
## Max. :231.0 Max. :6300 Max. :2009
## NA's :2 NA's :2
Interactive Histograms
hist(penguins$body_mass_g, breaks = 19)

install.packages("plotly")
library(plotly)
penguin_hist_base <- plot_ly(data = penguins,
x = ~body_mass_g,
type = "histogram")
penguin_hist_base <- penguin_hist_base %>% layout(yaxis = list(title = 'count'))
A brief explanation of the code is provided in the Code
chunk below.
# Here, we are creating a plotly object called "penguin_hist_base"
penguin_hist_base <- plot_ly(data = penguins, # We are using the penguins data
x = ~body_mass_g, # and modelling the body_mass_g data
type = "histogram") # in a histogram format
# The code below is used to modify the layout of the histogram
# to include a label for the y-axis
penguin_hist_base <- penguin_hist_base %>% layout(yaxis = list(title = 'count'))
penguin_hist <- plot_ly(data = penguins,
x = ~body_mass_g,
color = ~island,
type = "histogram", alpha = 0.6)
penguin_hist <- penguin_hist %>% layout(yaxis = list(title = 'count'),
barmode ="overlay")
A brief explanation of the code is provided in the Code
chunk below.
# Here, we are creating a plotly object called "penguin_hist"
penguin_hist <- plot_ly(data = penguins, # We are using the penguins data
x = ~body_mass_g, # and modelling the body_mass_g data
color = ~island, type = "histogram", alpha = 0.6)
# We are producing a histogram for this data, with points coloured differently,
# depending on the island on which the penguin is located
# The code below is used to modify the layout of the histogram
# This includes adding a label to the y-axis
# and setting the histograms to be layered over each other
# (hence the alpha = 0.6 above to change the opacity)
penguin_hist <- penguin_hist %>% layout(yaxis = list(title = 'count'),
barmode ="overlay")
No answer required.
Well done, that’s everything covered.
References
Ding, Liuyong. 2021.
rfishdraw: Automatically Generated Fish Drawings via JavaScript.
https://github.com/Otoliths/rfishdraw.
Horst, Allison Marie, Alison Presmanes Hill, and Kristen B Gorman. 2020.
Palmerpenguins: Palmer Archipelago (Antarctica) Penguin Data.
https://doi.org/10.5281/zenodo.3960218.
Ooms, Jeroen. 2021.
magick: advanced graphics and image-processing in R.
https://docs.ropensci.org/magick/.
Sievert, Carson. 2020.
Interactive Web-Based Data Visualization with r, Plotly, and Shiny. Chapman; Hall/CRC.
https://plotly-r.com.
Yu, Guangchuang. 2021.
meme: create memes in R.
https://github.com/GuangchuangYu/meme/.
These notes have been prepared by Rupert Kuveke. The copyright for the material in these notes resides with the author named above, with the Department of Mathematical and Physical Sciences and with La Trobe University. Copyright in this work is vested in La Trobe University including all La Trobe University branding and naming. Unless otherwise stated, material within this work is licensed under a Creative Commons Attribution-Non Commercial-Non Derivatives License
BY-NC-ND.
LS0tDQp0aXRsZTogIlNUTTEwMDE6IENvbXB1dGVyIExhYiAxQiBTb2x1dGlvbnMiDQpvdXRwdXQ6DQogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjogDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KYmlibGlvZ3JhcGh5OiBTVE0xMDAxX0RTX0NMX3JlZmVyZW5jZXMuYmliIA0KbGluay1jaXRhdGlvbnM6IHllcw0KLS0tDQoNCjxzdHlsZT4NCiNUT0Mgew0KICBiYWNrZ3JvdW5kOiB1cmwoImh0dHBzOi8vd3d3LmxhdHJvYmUuZWR1LmF1L19tZWRpYS9sYS10cm9iZS1hcGkvdjUvaW1nL2xvZ28uc3ZnIik7DQogIGJhY2tncm91bmQtc2l6ZTogY29udGFpbjsNCiAgcGFkZGluZy10b3A6IDgwcHggIWltcG9ydGFudDsNCiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsNCn0NCjwvc3R5bGU+DQoNCiMjIyBEYXRhIFNjaWVuY2UgTW9kdWxlIHstfQ0KDQojIyMgVG9waWMgMUI6IERhdGEgVmlzdWFsaXNhdGlvbiBJIHstfQ0KDQo8YnI+DQoNCkV4YW1wbGUgUiBjb2RlIHNvbHV0aW9ucyBmb3IgdGhlIFtEYXRhIFNjaWVuY2UgQ29tcHV0ZXIgTGFiIDFdKGh0dHBzOi8vcnB1YnMuY29tL0xUVV9TVE0xMDAxL0RTTUNMMV9TKSwgd2hpY2ggdXNlcyB0aGUgcGFja2FnZXMgYG1lbWVgIFtAbWVtZXNdLCBgbWFnaWNrYCBbQG1hZ2lja10sIGByZmlzaGRyYXdgIFtAcmZpc2hkcmF3XSwgYHBsb3RseWAgW0BwbG90bHldLCBhbmQgYHBhbG1lcnBlbmd1aW5zYCBbQHBlbmd1aW5zXSwgYXJlIHByZXNlbnRlZCBiZWxvdy4NCg0KPGJyPg0KDQojIE1ha2luZyBtZW1lcyBpbiBSIHsjbWVtZXN9DQoNCiMjIA0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBULCBpbmNsdWRlID0gRn0NCmluc3RhbGwucGFja2FnZXMoIm1lbWUiLCByZXBvcyA9ICJodHRwOi8vY3Jhbi51cy5yLXByb2plY3Qub3JnIikNCmBgYA0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KaW5zdGFsbC5wYWNrYWdlcygibWVtZSIpDQpgYGANCg0KIyMNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gRiwgaW5jbHVkZSA9IEZ9DQpsaWJyYXJ5KG1lbWUpDQpgYGANCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVH0NCmxpYnJhcnkobWVtZSkNCmBgYA0KDQojIw0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IFQsIGVjaG8gPSBUfQ0KaGFncmlkIDwtICJodHRwczovL2kuaW1nZmxpcC5jb20vMTN3YjJ0LmpwZyINCmBgYA0KDQojIw0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCm1lbWUoaGFncmlkLCAiWWVyIGEgd2l6YXJkIiwgIndpdGggY29kaW5nIiwgZm9udCA9ICJzYW5zIikNCmBgYA0KDQoqTm90ZTogU29tZSB3YXJuaW5ncyBtYXkgYXBwZWFyIGluIHlvdXIgUiBDb25zb2xlIGFzIHRoaXMgY29kZSBpcyBleGVjdXRpbmcuIERvbid0IHdvcnJ5IGFib3V0IGl0LCBpdCBpcyBzYWZlIHRvIGlnbm9yZSB0aGVzZSB3YXJuaW5ncy4qIA0KDQojIw0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IFQsIGVjaG8gPSBULCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCnN1Y2Nlc3Nfa2lkIDwtICJodHRwOi8vaTAua3ltLWNkbi5jb20vZW50cmllcy9pY29ucy9tb2JpbGUvMDAwLzAwMC83NDUvc3VjY2Vzcy5qcGciDQpzdWNjZXNzIDwtIG1lbWUoc3VjY2Vzc19raWQsICJVc2luZyBSIiwgInRvIG1ha2UgbWVtZXMiLCBmb250ID0gInNhbnMiKQ0Kc3VjY2Vzcw0KYGBgDQoNCiMjIA0KDQpBbiBleGFtcGxlIGNvbW1hbmQgdG8gc2F2ZSB0aGUgYHN1Y2Nlc3NgIG9iamVjdCB0byB0aGUgaW1hZ2luYXJ5IGZpbGVwYXRoIGAiU1RNMTAwMS9EYXRhIFNjaWVuY2Uvc3VjY2Vzc19raWRfUl9tZW1lLnBuZyJgIGlzIHNob3duIGJlbG93Lg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KbWVtZV9zYXZlKHN1Y2Nlc3MsIGZpbGU9IlNUTTEwMDEvRGF0YSBTY2llbmNlL3N1Y2Nlc3Nfa2lkX1JfbWVtZS5wbmciKSANCmBgYA0KDQojIw0KDQpQbGVhc2UgcmVmZXIgdG8gdGhlIHByZXZpb3VzIHN0ZXBzIG9mIFxAcmVmKG1lbWVzKSBmb3IgYSBndWlkZSBvbiBsb2FkaW5nIGFuIGltYWdlLCBhZGRpbmcgdGV4dCwgYW5kIHRoZW4gc2F2aW5nIHlvdXIgY3JlYXRpb24uDQoNCiMgQ3VzdG9taXppbmcgR0lGcyBpbiBSDQoNCipQbGVhc2Ugbm90ZSB0aGF0IGZvciB0aGlzIHF1ZXN0aW9uLCB3aGlsZSB0aGUgY29kZSB0byBwcmVzZW50IHRoZSBnaWZzIGlzIGluY2x1ZGVkLCB0aGUgZ2lmcyB0aGVtc2VsdmVzIGFyZSBub3QgcmVwcm9kdWNlZCBpbiB0aGUgZG9jdW1lbnRhdGlvbiBiZWxvdy4qDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IFQsIGluY2x1ZGUgPSBGfQ0KaW5zdGFsbC5wYWNrYWdlcygibWFnaWNrIiwgcmVwb3MgPSAiaHR0cDovL2NyYW4udXMuci1wcm9qZWN0Lm9yZyIpDQpgYGANCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVH0NCmluc3RhbGwucGFja2FnZXMoIm1hZ2ljayIpDQpgYGANCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gRiwgaW5jbHVkZSA9IEZ9DQpsaWJyYXJ5KG1hZ2ljaykNCmBgYA0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KbGlicmFyeShtYWdpY2spDQpgYGANCg0KIyMNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVCwgZmlnLmFsaWduID0gImNlbnRlciJ9DQpFYXJ0aCA8LSBpbWFnZV9yZWFkKCJodHRwczovL2kuZ2lwaHkuY29tL21lZGlhL21mOFViSURldzdlOGcvZ2lwaHkuZ2lmIikNCkVhcnRoDQpgYGANCg0KIyMNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVCwgZmlnLmFsaWduID0gImNlbnRlciJ9DQpyZXYoRWFydGgpICU+JSANCiAgICAgICAgICAgaW1hZ2VfZmxpcCgpICU+JSANCiAgICAgICAgICAgaW1hZ2VfYW5ub3RhdGUoIiAgICAgIE1lYW53aGlsZSwgaW4gQXVzdHJhbGlhIiwgc2l6ZSA9IDQwLCBjb2xvciA9ICJ3aGl0ZSIpDQpgYGANCg0KIyMNCg0KTm8gYW5zd2VyIHJlcXVpcmVkLg0KDQojIERyYXdpbmcgYSBmaXNoIGluIFINCg0KIyMNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVCwgaW5jbHVkZSA9IEZ9DQppbnN0YWxsLnBhY2thZ2VzKCJyZmlzaGRyYXciLCByZXBvcyA9ICJodHRwOi8vY3Jhbi51cy5yLXByb2plY3Qub3JnIikNCmluc3RhbGwucGFja2FnZXMoInBhdGNod29yayIsIHJlcG9zID0gImh0dHA6Ly9jcmFuLnVzLnItcHJvamVjdC5vcmciKQ0KaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIsIHJlcG9zID0gImh0dHA6Ly9jcmFuLnVzLnItcHJvamVjdC5vcmciKQ0KYGBgDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IFR9DQppbnN0YWxsLnBhY2thZ2VzKCJyZmlzaGRyYXciKQ0KaW5zdGFsbC5wYWNrYWdlcygicGF0Y2h3b3JrIikNCmluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KYGBgDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IEYsIGluY2x1ZGUgPSBGfQ0KbGlicmFyeSgicmZpc2hkcmF3IikNCmxpYnJhcnkoInBhdGNod29yayIpDQpsaWJyYXJ5KCJnZ3Bsb3QyIikNCmBgYA0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KbGlicmFyeSgicmZpc2hkcmF3IikNCmxpYnJhcnkoInBhdGNod29yayIpDQpsaWJyYXJ5KCJnZ3Bsb3QyIikNCmBgYA0KDQojIw0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBULCBtZXNzYWdlID0gRn0NCmdldF9wb2x5bGluZXMocGF0aCA9ICJpbnN0L2Zpc2hkcmF3LmpzIiwNCiAgICAgICAgICAgICAgZm9ybWF0ID0gInNtaWwiLA0KICAgICAgICAgICAgICBvdXRwdXQgPSAiYW5pbWF0ZWQuc3ZnIiwNCiAgICAgICAgICAgICAgZHJhd190eXBlID0gInJhbmRvbSIpDQoNCndpbmRvd3MoKQ0KDQpmaXNoX2RyYXcoKQ0KYGBgDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IEYsIHdhcm5pbmcgPSBGLCBpbmNsdWRlID0gRn0NCmdldF9wb2x5bGluZXMocGF0aCA9ICJpbnN0L2Zpc2hkcmF3LmpzIiwNCiAgICAgICAgICAgICAgZm9ybWF0ID0gInNtaWwiLA0KICAgICAgICAgICAgICBvdXRwdXQgPSAiYW5pbWF0ZWQuc3ZnIiwNCiAgICAgICAgICAgICAgZHJhd190eXBlID0gInJhbmRvbSIpDQoNCndpbmRvd3MoKQ0KDQpmaXNoX2RyYXcoKQ0KYGBgDQoNCiMjDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFR9DQpmaXNoX2RyYXcoY29sID0gImJsdWUiKQ0KYGBgDQoNCkFzIGFuIGV4YW1wbGUsIHlvdSBtYXkgaGF2ZSBjaGFuZ2VkIHRoZSBmaXNoIGNvbG91ciB0byByZWQsIGluIHdoaWNoIGNhc2UgeW91ciBjb2RlIHdvdWxkIGxvb2sgbGlrZSB0aGlzOg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVH0NCmZpc2hfZHJhdyhjb2wgPSAicmVkIikNCmBgYA0KDQojIFBhbG1lciBQZW5ndWlucyBEYXRhIFNldCB7I3Blbmd1aW5zfQ0KDQojIw0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBGLCBpbmNsdWRlID0gRn0NCmluc3RhbGwucGFja2FnZXMoInBhbG1lcnBlbmd1aW5zIiwgcmVwb3MgPSAiaHR0cDovL2NyYW4udXMuci1wcm9qZWN0Lm9yZyIpDQpgYGANCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVH0NCmluc3RhbGwucGFja2FnZXMoInBhbG1lcnBlbmd1aW5zIikNCmBgYA0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IFQsIGVjaG8gPSBUfQ0KbGlicmFyeShwYWxtZXJwZW5ndWlucykNCmBgYA0KDQojIw0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IFQsIGVjaG8gPSBUfQ0KIyBUaGlzIGNvZGUgc3VtbWFyaXNlcyB0aGUgZGF0YSBpbiB0aGUgYHBhbG1lcnBlbmd1aW5zYCBwYWNrYWdlLg0Kc3VtbWFyeShwZW5ndWlucykNCmBgYA0KDQojIEludGVyYWN0aXZlIEhpc3RvZ3JhbXMNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVH0NCmhpc3QocGVuZ3VpbnMkYm9keV9tYXNzX2csIGJyZWFrcyA9IDE5KQ0KYGBgDQoNCiMjDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IEYsIGluY2x1ZGUgPSBGfQ0KaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IiwgcmVwb3MgPSAiaHR0cDovL2NyYW4udXMuci1wcm9qZWN0Lm9yZyIpDQpgYGANCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVH0NCmluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQpgYGANCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGfQ0KbGlicmFyeShwbG90bHkpDQpgYGANCg0KIyMNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVCwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGfQ0KcGVuZ3Vpbl9oaXN0X2Jhc2UgPC0gcGxvdF9seShkYXRhID0gcGVuZ3VpbnMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gfmJvZHlfbWFzc19nLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJoaXN0b2dyYW0iKQ0KDQpwZW5ndWluX2hpc3RfYmFzZSA8LSBwZW5ndWluX2hpc3RfYmFzZSAlPiUgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9ICdjb3VudCcpKQ0KYGBgDQoNCkEgYnJpZWYgZXhwbGFuYXRpb24gb2YgdGhlIGNvZGUgaXMgcHJvdmlkZWQgaW4gdGhlIGBDb2RlYCBjaHVuayBiZWxvdy4NCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtaGlkZSIsIGV2YWwgPSBGLCBlY2hvID0gVH0NCiMgSGVyZSwgd2UgYXJlIGNyZWF0aW5nIGEgcGxvdGx5IG9iamVjdCBjYWxsZWQgInBlbmd1aW5faGlzdF9iYXNlIg0KcGVuZ3Vpbl9oaXN0X2Jhc2UgPC0gcGxvdF9seShkYXRhID0gcGVuZ3VpbnMsICMgV2UgYXJlIHVzaW5nIHRoZSBwZW5ndWlucyBkYXRhDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSB+Ym9keV9tYXNzX2csICMgYW5kIG1vZGVsbGluZyB0aGUgYm9keV9tYXNzX2cgZGF0YQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gImhpc3RvZ3JhbSIpICMgaW4gYSBoaXN0b2dyYW0gZm9ybWF0DQoNCiMgVGhlIGNvZGUgYmVsb3cgaXMgdXNlZCB0byBtb2RpZnkgdGhlIGxheW91dCBvZiB0aGUgaGlzdG9ncmFtDQojIHRvIGluY2x1ZGUgYSBsYWJlbCBmb3IgdGhlIHktYXhpcw0KcGVuZ3Vpbl9oaXN0X2Jhc2UgPC0gcGVuZ3Vpbl9oaXN0X2Jhc2UgJT4lIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSAnY291bnQnKSkNCmBgYA0KDQojIyB7I2Jhc2VoaXN0fQ0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IFQsIGVjaG8gPSBULCB3YXJuaW5nID0gRiwgbWVzc2FnZSA9IEYsIGZpZy5hbGlnbiA9ICJjZW50ZXIifQ0KcGVuZ3Vpbl9oaXN0X2Jhc2UNCmBgYA0KDQojIw0KDQpObyBhbnN3ZXIgcmVxdWlyZWQuDQoNCiMjDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFQsIHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRn0NCnBlbmd1aW5faGlzdCA8LSBwbG90X2x5KGRhdGEgPSBwZW5ndWlucywgDQogICAgICAgICAgICAgICAgICAgICAgICB4ID0gfmJvZHlfbWFzc19nLCANCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gfmlzbGFuZCwgDQogICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gImhpc3RvZ3JhbSIsIGFscGhhID0gMC42KQ0KDQpwZW5ndWluX2hpc3QgPC0gcGVuZ3Vpbl9oaXN0ICU+JSBsYXlvdXQoeWF4aXMgPSBsaXN0KHRpdGxlID0gJ2NvdW50JyksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhcm1vZGUgPSJvdmVybGF5IikNCmBgYA0KDQpBIGJyaWVmIGV4cGxhbmF0aW9uIG9mIHRoZSBjb2RlIGlzIHByb3ZpZGVkIGluIHRoZSBgQ29kZWAgY2h1bmsgYmVsb3cuDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLWhpZGUiLCBldmFsID0gRiwgZWNobyA9IFR9DQojIEhlcmUsIHdlIGFyZSBjcmVhdGluZyBhIHBsb3RseSBvYmplY3QgY2FsbGVkICJwZW5ndWluX2hpc3QiDQpwZW5ndWluX2hpc3QgPC0gcGxvdF9seShkYXRhID0gcGVuZ3VpbnMsICMgV2UgYXJlIHVzaW5nIHRoZSBwZW5ndWlucyBkYXRhDQogICAgICAgICAgICAgICAgICAgICAgICB4ID0gfmJvZHlfbWFzc19nLCAjIGFuZCBtb2RlbGxpbmcgdGhlIGJvZHlfbWFzc19nIGRhdGENCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gfmlzbGFuZCwgdHlwZSA9ICJoaXN0b2dyYW0iLCBhbHBoYSA9IDAuNikNCiMgV2UgYXJlIHByb2R1Y2luZyBhIGhpc3RvZ3JhbSBmb3IgdGhpcyBkYXRhLCB3aXRoIHBvaW50cyBjb2xvdXJlZCBkaWZmZXJlbnRseSwgDQojIGRlcGVuZGluZyBvbiB0aGUgaXNsYW5kIG9uIHdoaWNoIHRoZSBwZW5ndWluIGlzIGxvY2F0ZWQNCg0KIyBUaGUgY29kZSBiZWxvdyBpcyB1c2VkIHRvIG1vZGlmeSB0aGUgbGF5b3V0IG9mIHRoZSBoaXN0b2dyYW0NCiMgVGhpcyBpbmNsdWRlcyBhZGRpbmcgYSBsYWJlbCB0byB0aGUgeS1heGlzDQojIGFuZCBzZXR0aW5nIHRoZSBoaXN0b2dyYW1zIHRvIGJlIGxheWVyZWQgb3ZlciBlYWNoIG90aGVyDQojIChoZW5jZSB0aGUgYWxwaGEgPSAwLjYgYWJvdmUgdG8gY2hhbmdlIHRoZSBvcGFjaXR5KQ0KcGVuZ3Vpbl9oaXN0IDwtIHBlbmd1aW5faGlzdCAlPiUgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9ICdjb3VudCcpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXJtb2RlID0ib3ZlcmxheSIpDQpgYGANCg0KIyMgeyNpc2xhbmRzaGlzdH0NCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVCwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCnBlbmd1aW5faGlzdA0KYGBgDQoNCiMjDQoNCk5vIGFuc3dlciByZXF1aXJlZC4NCg0KPGJyPg0KDQojIyMjIFdlbGwgZG9uZSwgdGhhdCdzIGV2ZXJ5dGhpbmcgY292ZXJlZC4gIyMjIyB7LX0NCg0KPGJyPg0KDQojIFJlZmVyZW5jZXMgey0gI1JlZn0NCjxkaXYgaWQ9InJlZnMiPjwvZGl2Pg0KDQo8YnI+DQoNCjxmb250IGNvbG9yID0gImdyZXkiPg0KVGhlc2Ugbm90ZXMgaGF2ZSBiZWVuIHByZXBhcmVkIGJ5IFJ1cGVydCBLdXZla2UuIFRoZSBjb3B5cmlnaHQgZm9yIHRoZSBtYXRlcmlhbCBpbiB0aGVzZSBub3RlcyByZXNpZGVzIHdpdGggdGhlIGF1dGhvciBuYW1lZCBhYm92ZSwgd2l0aCB0aGUgRGVwYXJ0bWVudCBvZiBNYXRoZW1hdGljYWwgYW5kIFBoeXNpY2FsIFNjaWVuY2VzIGFuZCB3aXRoIExhIFRyb2JlIFVuaXZlcnNpdHkuIENvcHlyaWdodCBpbiB0aGlzIHdvcmsgaXMgdmVzdGVkIGluIExhIFRyb2JlIFVuaXZlcnNpdHkgaW5jbHVkaW5nIGFsbCBMYSBUcm9iZSBVbml2ZXJzaXR5IGJyYW5kaW5nIGFuZCBuYW1pbmcuIFVubGVzcyBvdGhlcndpc2Ugc3RhdGVkLCBtYXRlcmlhbCB3aXRoaW4gdGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVyIGEgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob24gQ29tbWVyY2lhbC1Ob24gRGVyaXZhdGl2ZXMgTGljZW5zZSANCjxhIGhyZWYgPSAiaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLW5kLzQuMC9DQyIgdGFyZ2V0PSJfYmxhbmsiPiBCWS1OQy1ORC4gPC9hPg0KPC9mb250Pg==