Data Science Module

Topic 3B: Data Visualisation III


Example R code solutions for the Data Science Computer Lab 3B, which uses data from Horst, Hill, and Gorman (2020), and the plotly (Sievert 2020) R package, are presented below.


1 Preparation

1.1

library(palmerpenguins)
library(plotly)

2 Piping

2.1

penguins_scatter <- plot_ly(data = penguins, 
                            x = ~body_mass_g, y = ~flipper_length_mm, 
                            color = ~sex, colors = "Set1",
                            type = "scatter", mode = "markers")

2.2

penguins_scatter <- plot_ly(data = penguins, 
                            x = ~body_mass_g, y = ~flipper_length_mm, 
                            color = ~sex, colors = "Set1", text = ~species,
                            type = "scatter", mode = "markers")

2.3

penguins_scatter %>% layout(title = "Scatter Plot of Penguin Data")

2.4

No answer required.

2.5

# An example for the yaxis code is shown below
penguins_scatter %>% layout(xaxis = list(title = "Penguin Body Mass (grams)"),
                            yaxis = list(title = "Penguin Flipper Length (mm)")
                            )

2.6

No answer required.

2.7

No answer required.

3 Adding Range Sliders to Plotly plots

3.1

penguins_scatter %>% rangeslider()

3.2

No answer required.

3.3

No answer required.

4 Creating animated Plotly plots

4.1

penguins_scatter_anim <- plot_ly(data = penguins, 
                            x = ~body_mass_g, y = ~flipper_length_mm, 
                            color = ~sex, colors = "Set1", text = ~species,
                            frame = ~year, # Note we have used the frame argument here
                            type = "scatter", mode = "markers")
penguins_scatter_anim

4.2

No answer required.

4.3

We notice that the Gentoo penguins have much larger body masses and longer flipper lengths compared to Chinstrap or Adelie penguins.

5 Adding buttons to Plotly plots

Please note - it may also be helpful to refer to Section 5 of the Data Visualisation in R supplement while checking these solutions.

5.1

The R code below should be run, before creating the subsequent plots:

penguins_scatter <- plot_ly(data = penguins, 
                            x = ~body_mass_g, y = ~flipper_length_mm, 
                            color = ~sex, colors = "Set1",
                            type = "scatter", mode = "markers")

5.2

penguins_plots <- penguins_scatter %>% layout(

  updatemenus = list(
    list(y = 0.8, type = "buttons", 
         buttons = list(
           
          list(method = "restyle",
            args = list(
              list(type = list("scatter"), mode = list("markers"))),
              label = "Scatter Plot"),
      
          list(method = "restyle",
            args = list(
              list(type = list("histogram"))),
              label = "Histogram"))
    )))

penguins_plots

5.3

penguins_plots2 <- penguins_scatter %>% layout(

  updatemenus = list(
    list(y = 0.8, type = "dropdown", 
         buttons = list(
           
          list(method = "restyle",
            args = list(
              list(type = list("scatter"), mode = list("markers"))),
              label = "Scatter Plot"),
      
          list(method = "restyle",
            args = list(
              list(type = list("histogram"))),
              label = "Histogram"))
    )))

penguins_plots2

5.4

penguins_plots2 <- penguins_plots2 %>% layout(barmode ="overlay")

penguins_plots2

5.5

penguin_plots3 <- penguins_plots2 %>% 
                  layout(title = "Penguin Data - Select your plot")  %>% 
                  rangeslider()
penguin_plots3 


Great job! There was a lot of content for this lab.


References

Horst, Allison Marie, Alison Presmanes Hill, and Kristen B Gorman. 2020. Palmerpenguins: Palmer Archipelago (Antarctica) Penguin Data. https://doi.org/10.5281/zenodo.3960218.
Sievert, Carson. 2020. Interactive Web-Based Data Visualization with r, Plotly, and Shiny. Chapman; Hall/CRC. https://plotly-r.com.


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.

LS0tDQp0aXRsZTogIlNUTTEwMDE6IENvbXB1dGVyIExhYiAzQiBTb2x1dGlvbnMiDQpvdXRwdXQ6DQogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjogDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiByZWFkYWJsZQ0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KYmlibGlvZ3JhcGh5OiBTVE0xMDAxX0RTX0NMX3JlZmVyZW5jZXMuYmliIA0KbGluay1jaXRhdGlvbnM6IHllcw0KLS0tDQoNCjxzdHlsZT4NCiNUT0Mgew0KICBiYWNrZ3JvdW5kOiB1cmwoImh0dHBzOi8vd3d3LmxhdHJvYmUuZWR1LmF1L19tZWRpYS9sYS10cm9iZS1hcGkvdjUvaW1nL2xvZ28uc3ZnIik7DQogIGJhY2tncm91bmQtc2l6ZTogY29udGFpbjsNCiAgcGFkZGluZy10b3A6IDgwcHggIWltcG9ydGFudDsNCiAgYmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDsNCn0NCjwvc3R5bGU+DQoNCiMjIyBEYXRhIFNjaWVuY2UgTW9kdWxlIHstfQ0KDQojIyMgVG9waWMgM0I6IERhdGEgVmlzdWFsaXNhdGlvbiBJSUkgey19DQoNCjxicj4NCg0KRXhhbXBsZSBSIGNvZGUgc29sdXRpb25zIGZvciB0aGUgW0RhdGEgU2NpZW5jZSBDb21wdXRlciBMYWIgM0JdKGh0dHBzOi8vcnB1YnMuY29tL0xUVV9TVE0xMDAxL0RTTUNMM19TKSwgd2hpY2ggdXNlcyBkYXRhIGZyb20gQHBlbmd1aW5zLCBhbmQgdGhlIGBwbG90bHlgIFtAcGxvdGx5XSBSIHBhY2thZ2UsIGFyZSBwcmVzZW50ZWQgYmVsb3cuDQoNCjxicj4NCg0KIyBQcmVwYXJhdGlvbiB7I2xvYWRpbmd9DQoNCiMjDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IFR9DQpsaWJyYXJ5KHBhbG1lcnBlbmd1aW5zKQ0KbGlicmFyeShwbG90bHkpDQpgYGANCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBpbmNsdWRlID0gRn0NCmxpYnJhcnkocGFsbWVycGVuZ3VpbnMpDQpsaWJyYXJ5KHBsb3RseSkNCmBgYA0KDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgaW5jbHVkZSA9IEZ9DQpwZW5ndWlucyA8LSBuYS5vbWl0KHBlbmd1aW5zKQ0KYGBgDQoNCiMgUGlwaW5nDQoNCiMjIHsjc2ltcGxlc2NhdHRlcn0NCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVCwgZmlnLmRpbSA9IGMoOCwgNiksIGZpZy5hbGlnbiA9ICJjZW50ZXIifQ0KcGVuZ3VpbnNfc2NhdHRlciA8LSBwbG90X2x5KGRhdGEgPSBwZW5ndWlucywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IH5ib2R5X21hc3NfZywgeSA9IH5mbGlwcGVyX2xlbmd0aF9tbSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSB+c2V4LCBjb2xvcnMgPSAiU2V0MSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyIiwgbW9kZSA9ICJtYXJrZXJzIikNCmBgYA0KIyMgeyNzaW1wbGVzY2F0dGVyMn0NCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVCwgZmlnLmRpbSA9IGMoOCwgNiksIGZpZy5hbGlnbiA9ICJjZW50ZXIifQ0KcGVuZ3VpbnNfc2NhdHRlciA8LSBwbG90X2x5KGRhdGEgPSBwZW5ndWlucywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IH5ib2R5X21hc3NfZywgeSA9IH5mbGlwcGVyX2xlbmd0aF9tbSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSB+c2V4LCBjb2xvcnMgPSAiU2V0MSIsIHRleHQgPSB+c3BlY2llcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gInNjYXR0ZXIiLCBtb2RlID0gIm1hcmtlcnMiKQ0KYGBgDQoNCiMjIHsjdGl0bGV9DQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFQsIHdhcm5pbmcgPSBGLCBmaWcuZGltID0gYyg4LCA2KSwgZmlnLmFsaWduID0gImNlbnRlciJ9DQpwZW5ndWluc19zY2F0dGVyICU+JSBsYXlvdXQodGl0bGUgPSAiU2NhdHRlciBQbG90IG9mIFBlbmd1aW4gRGF0YSIpDQpgYGANCg0KIyMNCg0KTm8gYW5zd2VyIHJlcXVpcmVkLg0KDQojIw0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KIyBBbiBleGFtcGxlIGZvciB0aGUgeWF4aXMgY29kZSBpcyBzaG93biBiZWxvdw0KcGVuZ3VpbnNfc2NhdHRlciAlPiUgbGF5b3V0KHhheGlzID0gbGlzdCh0aXRsZSA9ICJQZW5ndWluIEJvZHkgTWFzcyAoZ3JhbXMpIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlBlbmd1aW4gRmxpcHBlciBMZW5ndGggKG1tKSIpDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KYGBgDQoNCiMjDQoNCk5vIGFuc3dlciByZXF1aXJlZC4NCg0KIyMNCg0KTm8gYW5zd2VyIHJlcXVpcmVkLg0KDQojIEFkZGluZyBSYW5nZSBTbGlkZXJzIHRvIFBsb3RseSBwbG90cyB7I3NsaWRlcn0gDQoNCiMjIHsjc2xpZGVyc3RhcnR9DQoNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVCwgd2FybmluZyA9IEZ9DQpwZW5ndWluc19zY2F0dGVyICU+JSByYW5nZXNsaWRlcigpDQpgYGANCg0KIyMNCg0KTm8gYW5zd2VyIHJlcXVpcmVkLg0KDQojIw0KDQpObyBhbnN3ZXIgcmVxdWlyZWQuDQoNCiMgQ3JlYXRpbmcgYW5pbWF0ZWQgUGxvdGx5IHBsb3RzIHsjYW5pbWF0aW9uc30NCg0KIyMNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVCwgd2FybmluZyA9IEYsIGZpZy5kaW0gPSBjKDgsIDYpLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCnBlbmd1aW5zX3NjYXR0ZXJfYW5pbSA8LSBwbG90X2x5KGRhdGEgPSBwZW5ndWlucywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IH5ib2R5X21hc3NfZywgeSA9IH5mbGlwcGVyX2xlbmd0aF9tbSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSB+c2V4LCBjb2xvcnMgPSAiU2V0MSIsIHRleHQgPSB+c3BlY2llcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcmFtZSA9IH55ZWFyLCAjIE5vdGUgd2UgaGF2ZSB1c2VkIHRoZSBmcmFtZSBhcmd1bWVudCBoZXJlDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyIiwgbW9kZSA9ICJtYXJrZXJzIikNCnBlbmd1aW5zX3NjYXR0ZXJfYW5pbQ0KYGBgDQoNCiMjDQoNCk5vIGFuc3dlciByZXF1aXJlZC4NCg0KIyMNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gRiwgd2FybmluZyA9IEYsIGZpZy5kaW0gPSBjKDgsIDYpLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCnBlbmd1aW5zX3NjYXR0ZXJfYW5pbV9zcGVjaWVzIDwtIHBsb3RfbHkoZGF0YSA9IHBlbmd1aW5zLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSB+Ym9keV9tYXNzX2csIHkgPSB+ZmxpcHBlcl9sZW5ndGhfbW0sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSB+c2V4LCBjb2xvcnMgPSAiU2V0MSIsIHRleHQgPSB+eWVhciwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyYW1lID0gfnNwZWNpZXMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyIiwgbW9kZSA9ICJtYXJrZXJzIikNCnBlbmd1aW5zX3NjYXR0ZXJfYW5pbV9zcGVjaWVzDQpgYGANCg0KV2Ugbm90aWNlIHRoYXQgdGhlIEdlbnRvbyBwZW5ndWlucyBoYXZlIG11Y2ggbGFyZ2VyIGJvZHkgbWFzc2VzIGFuZCBsb25nZXIgZmxpcHBlciBsZW5ndGhzIGNvbXBhcmVkIHRvIENoaW5zdHJhcCBvciBBZGVsaWUgcGVuZ3VpbnMuDQoNCiMgQWRkaW5nIGJ1dHRvbnMgdG8gUGxvdGx5IHBsb3RzIHsjYnV0dG9ufQ0KDQoqKlBsZWFzZSBub3RlIC0gaXQgbWF5IGFsc28gYmUgaGVscGZ1bCB0byByZWZlciB0byBbU2VjdGlvbiA1IG9mIHRoZSBEYXRhIFZpc3VhbGlzYXRpb24gaW4gUiBzdXBwbGVtZW50XShodHRwczovL2Jvb2tkb3duLm9yZy9yZWhrL3N0bTEwMDFfZHNtX3QxX2RhdGFfdmlzdWFsaXNhdGlvbl9pbl9yL2FkdmFuY2VkLXBsb3RseS1jb21wdXRlci1sYWItM2IuaHRtbCkgd2hpbGUgY2hlY2tpbmcgdGhlc2Ugc29sdXRpb25zLioqDQoNCiMjDQoNClRoZSBSIGNvZGUgYmVsb3cgc2hvdWxkIGJlIHJ1biwgYmVmb3JlIGNyZWF0aW5nIHRoZSBzdWJzZXF1ZW50IHBsb3RzOg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IFQsIGVjaG8gPSBUfQ0KcGVuZ3VpbnNfc2NhdHRlciA8LSBwbG90X2x5KGRhdGEgPSBwZW5ndWlucywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IH5ib2R5X21hc3NfZywgeSA9IH5mbGlwcGVyX2xlbmd0aF9tbSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSB+c2V4LCBjb2xvcnMgPSAiU2V0MSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICJzY2F0dGVyIiwgbW9kZSA9ICJtYXJrZXJzIikNCmBgYA0KDQojIyB7I2J1dHRvbnNwbG90fQ0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IFQsIGVjaG8gPSBULCB3YXJuaW5nID0gRiwgZmlnLmRpbSA9IGMoOCwgNiksIGZpZy5hbGlnbiA9ICJjZW50ZXIifQ0KcGVuZ3VpbnNfcGxvdHMgPC0gcGVuZ3VpbnNfc2NhdHRlciAlPiUgbGF5b3V0KA0KDQogIHVwZGF0ZW1lbnVzID0gbGlzdCgNCiAgICBsaXN0KHkgPSAwLjgsIHR5cGUgPSAiYnV0dG9ucyIsIA0KICAgICAgICAgYnV0dG9ucyA9IGxpc3QoDQogICAgICAgICAgIA0KICAgICAgICAgIGxpc3QobWV0aG9kID0gInJlc3R5bGUiLA0KICAgICAgICAgICAgYXJncyA9IGxpc3QoDQogICAgICAgICAgICAgIGxpc3QodHlwZSA9IGxpc3QoInNjYXR0ZXIiKSwgbW9kZSA9IGxpc3QoIm1hcmtlcnMiKSkpLA0KICAgICAgICAgICAgICBsYWJlbCA9ICJTY2F0dGVyIFBsb3QiKSwNCiAgICAgIA0KICAgICAgICAgIGxpc3QobWV0aG9kID0gInJlc3R5bGUiLA0KICAgICAgICAgICAgYXJncyA9IGxpc3QoDQogICAgICAgICAgICAgIGxpc3QodHlwZSA9IGxpc3QoImhpc3RvZ3JhbSIpKSksDQogICAgICAgICAgICAgIGxhYmVsID0gIkhpc3RvZ3JhbSIpKQ0KICAgICkpKQ0KDQpwZW5ndWluc19wbG90cw0KYGBgDQoNCiMjDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFQsIHdhcm5pbmcgPSBGLCBmaWcuZGltID0gYyg4LCA2KSwgZmlnLmFsaWduID0gImNlbnRlciJ9DQpwZW5ndWluc19wbG90czIgPC0gcGVuZ3VpbnNfc2NhdHRlciAlPiUgbGF5b3V0KA0KDQogIHVwZGF0ZW1lbnVzID0gbGlzdCgNCiAgICBsaXN0KHkgPSAwLjgsIHR5cGUgPSAiZHJvcGRvd24iLCANCiAgICAgICAgIGJ1dHRvbnMgPSBsaXN0KA0KICAgICAgICAgICANCiAgICAgICAgICBsaXN0KG1ldGhvZCA9ICJyZXN0eWxlIiwNCiAgICAgICAgICAgIGFyZ3MgPSBsaXN0KA0KICAgICAgICAgICAgICBsaXN0KHR5cGUgPSBsaXN0KCJzY2F0dGVyIiksIG1vZGUgPSBsaXN0KCJtYXJrZXJzIikpKSwNCiAgICAgICAgICAgICAgbGFiZWwgPSAiU2NhdHRlciBQbG90IiksDQogICAgICANCiAgICAgICAgICBsaXN0KG1ldGhvZCA9ICJyZXN0eWxlIiwNCiAgICAgICAgICAgIGFyZ3MgPSBsaXN0KA0KICAgICAgICAgICAgICBsaXN0KHR5cGUgPSBsaXN0KCJoaXN0b2dyYW0iKSkpLA0KICAgICAgICAgICAgICBsYWJlbCA9ICJIaXN0b2dyYW0iKSkNCiAgICApKSkNCg0KcGVuZ3VpbnNfcGxvdHMyDQpgYGANCg0KIyMNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVCwgd2FybmluZyA9IEYsIGZpZy5kaW0gPSBjKDgsIDYpLCBmaWcuYWxpZ24gPSAiY2VudGVyIn0NCnBlbmd1aW5zX3Bsb3RzMiA8LSBwZW5ndWluc19wbG90czIgJT4lIGxheW91dChiYXJtb2RlID0ib3ZlcmxheSIpDQoNCnBlbmd1aW5zX3Bsb3RzMg0KYGBgDQoNCiMjDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFQsIHdhcm5pbmcgPSBGLCBmaWcuZGltID0gYyg4LCA2KSwgZmlnLmFsaWduID0gImNlbnRlciJ9DQpwZW5ndWluX3Bsb3RzMyA8LSBwZW5ndWluc19wbG90czIgJT4lIA0KICAgICAgICAgICAgICAgICAgbGF5b3V0KHRpdGxlID0gIlBlbmd1aW4gRGF0YSAtIFNlbGVjdCB5b3VyIHBsb3QiKSAgJT4lIA0KICAgICAgICAgICAgICAgICAgcmFuZ2VzbGlkZXIoKQ0KcGVuZ3Vpbl9wbG90czMgDQpgYGANCg0KPGJyPg0KDQojIyMjIEdyZWF0IGpvYiEgVGhlcmUgd2FzIGEgbG90IG9mIGNvbnRlbnQgZm9yIHRoaXMgbGFiLiAjIyMjIHstfQ0KDQo8YnI+DQoNCiMgUmVmZXJlbmNlcyB7LSAjUmVmfQ0KPGRpdiBpZD0icmVmcyI+PC9kaXY+DQoNCjxicj4NCg0KPGZvbnQgY29sb3IgPSAiZ3JleSI+DQpUaGVzZSBub3RlcyBoYXZlIGJlZW4gcHJlcGFyZWQgYnkgUnVwZXJ0IEt1dmVrZS4gVGhlIGNvcHlyaWdodCBmb3IgdGhlIG1hdGVyaWFsIGluIHRoZXNlIG5vdGVzIHJlc2lkZXMgd2l0aCB0aGUgYXV0aG9yIG5hbWVkIGFib3ZlLCB3aXRoIHRoZSBEZXBhcnRtZW50IG9mIE1hdGhlbWF0aWNhbCBhbmQgUGh5c2ljYWwgU2NpZW5jZXMgYW5kIHdpdGggTGEgVHJvYmUgVW5pdmVyc2l0eS4gQ29weXJpZ2h0IGluIHRoaXMgd29yayBpcyB2ZXN0ZWQgaW4gTGEgVHJvYmUgVW5pdmVyc2l0eSBpbmNsdWRpbmcgYWxsIExhIFRyb2JlIFVuaXZlcnNpdHkgYnJhbmRpbmcgYW5kIG5hbWluZy4gVW5sZXNzIG90aGVyd2lzZSBzdGF0ZWQsIG1hdGVyaWFsIHdpdGhpbiB0aGlzIHdvcmsgaXMgbGljZW5zZWQgdW5kZXIgYSBDcmVhdGl2ZSBDb21tb25zIEF0dHJpYnV0aW9uLU5vbiBDb21tZXJjaWFsLU5vbiBEZXJpdmF0aXZlcyBMaWNlbnNlIA0KPGEgaHJlZiA9ICJodHRwczovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktbmMtbmQvNC4wL0NDIiB0YXJnZXQ9Il9ibGFuayI+IEJZLU5DLU5ELiA8L2E+DQo8L2ZvbnQ+