Data Science Module

Topic 1B: Data Visualisation I


Example R code solutions for the Data Science Computer Lab 1, which uses the packages meme (Yu 2021), magick (Ooms 2021), rfishdraw (Ding 2021), plotly (Sievert 2020), and palmerpenguins (Horst, Hill, and Gorman 2020), are presented below.


1 Making memes in R

1.1

install.packages("meme")

1.2

library(meme)

1.3

hagrid <- "https://i.imgflip.com/13wb2t.jpg"

1.4

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.

1.5

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

1.6

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") 

1.7

Please refer to the previous steps of 1 for a guide on loading an image, adding text, and then saving your creation.

2 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)

2.1

Earth <- image_read("https://i.giphy.com/media/mf8UbIDew7e8g/giphy.gif")
Earth

2.2

rev(Earth) %>% 
           image_flip() %>% 
           image_annotate("      Meanwhile, in Australia", size = 40, color = "white")

2.3

No answer required.

3 Drawing a fish in R

3.1

install.packages("rfishdraw")
install.packages("patchwork")
install.packages("ggplot2")
library("rfishdraw")
library("patchwork")
library("ggplot2")

3.2

get_polylines(path = "inst/fishdraw.js",
              format = "smil",
              output = "animated.svg",
              draw_type = "random")

windows()

fish_draw()

3.3

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")

4 Palmer Penguins Data Set

4.1

install.packages("palmerpenguins")
library(palmerpenguins)

4.2

# 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

5 Interactive Histograms

hist(penguins$body_mass_g, breaks = 19)

5.1

install.packages("plotly")
library(plotly)

5.2

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'))

5.3

penguin_hist_base

5.4

No answer required.

5.5

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")

5.6

penguin_hist

5.7

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==