Table of content


Importing the ggplot2 package -

> library(ggplot2)

Let’s use the built in Hair and Eye Color data set -

> HairEyeColor
, , Sex = Male

       Eye
Hair    Brown Blue Hazel Green
  Black    32   11    10     3
  Brown    53   50    25    15
  Red      10   10     7     7
  Blond     3   30     5     8

, , Sex = Female

       Eye
Hair    Brown Blue Hazel Green
  Black    36    9     5     2
  Brown    66   34    29    14
  Red      16    7     7     7
  Blond     4   64     5     8

This data set is not so suitable for visualization. So we need to do some manipulation before moving on.

Let’s import some necessary packages -

> library(dplyr)

The data set is then transformed into a form so that we can use it for plotting -

> df <- HairEyeColor %>%        
+   as_tibble() %>%             
+   tidyr::uncount(n) %>%              
+   mutate_all(as.factor)

More about uncount -

> tibble(a=c(2,1,4),
+        b=c('one','two','three')) %>% tidyr::uncount(a)
# A tibble: 7 x 1
  b    
  <chr>
1 one  
2 one  
3 two  
4 three
5 three
6 three
7 three

Uncount does the opposite work of count.

Let’s see the new data frame now-

> glimpse(df)
Rows: 592
Columns: 3
$ Hair <fct> Black, Black, Black, Black, Black, Black, Black, Black, Black, Bl~
$ Eye  <fct> Brown, Brown, Brown, Brown, Brown, Brown, Brown, Brown, Brown, Br~
$ Sex  <fct> Male, Male, Male, Male, Male, Male, Male, Male, Male, Male, Male,~

Now it can be used to create bar charts.


A Simple Barplot

> ggplot(data = df) +
+   geom_bar(mapping = aes(x = Hair))

The mapping can be done inside the ggplot() function -

> ggplot(data = df, mapping = aes(x=Hair))+
+   geom_bar(fill = "black") +  
+   labs(title = "Hair Color", 
+        subtitle = "592 Statistics Students",
+        caption = "(From R's built in HairEyeColor sample dataset)",
+        y = "Number of Students", x = NULL)

Horizontal Bar Chart

Using coord_flip() -

> ggplot(data = df, mapping = aes(x=Hair))+
+   geom_bar(fill = "black") +  
+   labs(title = "Hair Color", 
+        subtitle = "592 Statistics Students",
+        caption = "(From R's built in HairEyeColor sample dataset)",
+        y = "Number of Students", x = NULL) +
+   coord_flip()

Assigning variable to the y axis -

> ggplot(data = df, mapping = aes(y = Hair))+
+   geom_bar(fill = "black") +  
+   labs(title = "Hair Color", 
+        subtitle = "592 Statistics Students",
+        caption = "(From R's built in HairEyeColor sample dataset)",
+        y = "Number of Students", x = NULL)

Using Colors

fill = {the same variable as the x axis} so that for each variable different colors is shown -

> ggplot(data = df)+
+   geom_bar(mapping = aes(x = Hair, fill = Hair))+
+   theme(legend.position = "none")  # Don't show the legend

Using hue -

> ggplot(data = df)+
+   geom_bar(mapping = aes(x = Hair, fill = Hair))+
+   theme(legend.position = "none") +  # Don't show the legend
+   scale_fill_hue(c = 20) # Different values c gives different intensity of colors

Manually selecting colors

How to manually set colors in a bar chart?
Manually selecting colors -

> ggplot(data = df)+
+   geom_bar(mapping = aes(x = Hair, fill = Hair), 
+            col = "black",
+            fill = c("Black","beige","bisque3","red"))+
+   theme(legend.position = "none")

Another way to do that -

> ggplot(data = df)+
+   geom_bar(mapping = aes(x = Hair, fill = Hair), col = "black")+
+   theme(legend.position = "none") +
+   scale_fill_manual(values = c("Black","beige","bisque3","red"))

Modifying Axis Tickmarks

> ggplot(df, aes(x = Hair)) +
+   geom_bar() +
+   scale_y_continuous(breaks = seq(0, 300, by=50)) +
+   labs(x = "Colors", y = "Frequency",
+        title = "Bar Chart of Colors",
+        subtitle = "An observational study") +
+   theme(plot.title = element_text(hjust = 0.5),
+         plot.subtitle = element_text(hjust = 0.5)) # center the title and subtitle

Stacked Bar Chart

Using fill argument stacked bar can be made -

> ggplot(data = df) + 
+   geom_bar(mapping = aes(Hair, fill = Sex))

100% Stacked Bar Chart

Using position = “fill” inside geom_bar -

> ggplot(df, aes(Hair, fill = Sex)) + 
+   geom_bar(position = "fill") +
+   labs(x="Hair Color", y=NULL) +
+   coord_flip()

Changing Order of Bars

> df$Hair <- factor(df$Hair, levels = c("Red", "Black", "Blond", "Brown"))
> ggplot(df, aes(y=Hair, fill = Sex)) + 
+   geom_bar(position = "fill") +
+   labs(x=NULL, y="Hair Color") 

Another way to do this using scale_y_discrete()-

> ggplot(df, aes(y = Hair, fill = Sex)) + 
+   geom_bar(position = "fill") +
+   labs(x=NULL, y="Hair Color") +
+   scale_y_discrete(limits = c("Black","Red","Brown","Blond"))

Changing Order in Legend’s Labels

Using scale_fill_discrete() -

> ggplot(df, aes(y = Hair, fill = Sex)) + 
+   geom_bar(position = "fill") +
+   labs(x=NULL, y="Hair Color") +
+   scale_y_discrete(limits = c("Black","Red","Brown","Blond")) +
+   scale_fill_discrete(breaks = c("Male","Female"))

Changing Order of Stacks

In the following stacked barplot, the left bar denotes female and the right bar denotes male -

> ggplot(df, aes(x = Hair, fill = Sex)) + 
+   geom_bar(position = "dodge") +
+   labs(x=NULL, y="Hair Color") +
+   scale_x_discrete(limits = c("Black","Red","Brown","Blond"))

If we check the order of levels of Sex we’ll see -

> levels(df$Sex)
[1] "Female" "Male"  

Now if the order is changed, the bar will also change its order -

> df %>% 
+   mutate(Sex = factor(Sex, levels = c("Male","Female"))) %>% 
+   ggplot(aes(x = Hair, fill = Sex)) + 
+   geom_bar(position = "dodge") +
+   labs(x=NULL, y="Hair Color") +
+   scale_x_discrete(limits = c("Black","Red","Brown","Blond"))

This is particularly useful when showing a 100% stacked barplot -

> df %>%
+   mutate(Hair = factor(Hair,
+                        levels = rev(c("Black","Brown","Red","Blond")))) %>%
+   ggplot(aes(y = Sex, fill = Hair)) + 
+   geom_bar(position = "fill") +
+   labs(x=NULL, y=NULL, fill = "Hair Colors") +
+   scale_fill_manual(values = c("black","#8B4513","#FF0000","#faf0be"),
+                       limits = c("Black","Brown","Red","Blond")) +
+   theme_bw() + theme(legend.position = "bottom")

Changing width of the bars

Width of the bars can be changed using the width argument from geom_bar(). It takes values from 0 to 1 -

> ggplot(df, aes(Hair, fill = Sex)) + 
+   geom_bar(position = "fill", 
+            width = 0.5) +
+   labs(x="Hair Color", y=NULL) +
+   coord_flip()

Side by Side Bar Chart

Using dodge -

> ggplot(df, aes(Hair, fill = Sex)) + 
+   geom_bar(position = "dodge") +
+   labs(x="Hair Color", y=NULL)

Using dodge2 -

> ggplot(df, aes(Hair, fill = Sex)) + 
+   geom_bar(position = "dodge2") +
+   labs(x="Hair Color", y=NULL)

In the following case we can see that there is no Male who has the hair color red. It fills the whole bar with Female bar -

> df %>% 
+   filter(!(Sex=="Male" & Hair=="Red")) %>% 
+   ggplot(aes(Hair, fill = Sex)) + 
+   geom_bar(position = "dodge2") +
+   labs(x="Hair Color", y=NULL)

To prevent it from happening use position_dodge2(preserve = “single”) in position argument -

> df %>% 
+   filter(!(Sex=="Male" & Hair=="Red")) %>% 
+   ggplot(aes(Hair, fill = Sex)) + 
+   geom_bar(position = position_dodge2(preserve = "single")) +
+   labs(x="Hair Color", y=NULL)

preserve = “total” will fill the whole place -

> df %>% 
+   filter(!(Sex=="Male" & Hair=="Red")) %>% 
+   ggplot(aes(Hair, fill = Sex)) + 
+   geom_bar(position = position_dodge2(preserve = "total")) +
+   labs(x="Hair Color", y=NULL)

Column Chart

Column charts data looks like this - (after manipulation)

> hairdf <- df %>% 
+   filter(Sex == "Male") %>% 
+   group_by(Hair) %>% 
+   summarize(frequency = n()) 
> hairdf
# A tibble: 4 x 2
  Hair  frequency
  <fct>     <int>
1 Red          34
2 Black        56
3 Blond        46
4 Brown       143

This types of data frame can be graphed in column chart using the function geom_col(), not geom_bar(), here is the difference -

> hairdf %>% 
+   ggplot()+ 
+   geom_col(mapping = aes(x=Hair, y=frequency),
+            fill = c("Black","beige","bisque3","coral2")) +
+   labs(title="Hair Color in Column Chart")

This kind of data can also be graphed by defining stat = "identity" in the geom_bar() function -

> hairdf %>% 
+   ggplot() +
+   geom_bar(aes(x = Hair, y = frequency), 
+            stat = "identity")

Putting frequencies on each bars

> hairdf %>% 
+   ggplot(aes(x = Hair, y = frequency)) +
+   geom_col() +
+   scale_y_continuous(breaks = seq(0, 150, by=30)) +
+   labs(x = "Colors", y = "Frequency",
+        title = "Bar Chart of Colors",
+        subtitle = "An observational study") +
+   geom_text(aes(label= frequency), 
+             vjust=1.2, size=3,
+             col = "white")

To know more about ggplot2 visit here

To know more about colors visit here

Check out https://www.homeworkhelponline.net for R Studio Programming assignment help.

LS0tDQp0aXRsZTogImdncGxvdDIgLSBCYXIgQ2hhcnQgYW5kIENvbHVtbiBDaGFydCINCmF1dGhvcjogJ01EIEFIU0FOVUwgSVNMQU0nDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCnRvYy10aXRsZTogIlRhYmxlIG9mIGNvbnRlbnQiDQotLS0NCg0KYGBge3IsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoDQogIGNvbW1lbnQgPSAiIiwgcHJvbXB0ID0gVFJVRSwgbWVzc2FnZT1GLCB3YXJuaW5nID0gRg0KKQ0KYGBgDQoNCi0tLQ0KDQpJbXBvcnRpbmcgdGhlIGdncGxvdDIgcGFja2FnZSAtIA0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KTGV0J3MgdXNlIHRoZSBidWlsdCBpbiBIYWlyIGFuZCBFeWUgQ29sb3IgZGF0YSBzZXQgLQ0KYGBge3J9DQpIYWlyRXllQ29sb3INCmBgYA0KVGhpcyBkYXRhIHNldCBpcyBub3Qgc28gc3VpdGFibGUgZm9yIHZpc3VhbGl6YXRpb24uIFNvIHdlIG5lZWQgdG8gZG8gc29tZSBtYW5pcHVsYXRpb24gYmVmb3JlIG1vdmluZyBvbi4gDQoNCkxldCdzIGltcG9ydCBzb21lIG5lY2Vzc2FyeSBwYWNrYWdlcyAtIA0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KYGBgDQoNClRoZSBkYXRhIHNldCBpcyB0aGVuIHRyYW5zZm9ybWVkIGludG8gYSBmb3JtIHNvIHRoYXQgd2UgY2FuIHVzZSBpdCBmb3IgcGxvdHRpbmcgLSANCmBgYHtyfQ0KZGYgPC0gSGFpckV5ZUNvbG9yICU+JSAgICAgICAgDQogIGFzX3RpYmJsZSgpICU+JSAgICAgICAgICAgICANCiAgdGlkeXI6OnVuY291bnQobikgJT4lICAgICAgICAgICAgICANCiAgbXV0YXRlX2FsbChhcy5mYWN0b3IpDQpgYGANCg0KTW9yZSBhYm91dCB1bmNvdW50IC0NCmBgYHtyfQ0KdGliYmxlKGE9YygyLDEsNCksDQogICAgICAgYj1jKCdvbmUnLCd0d28nLCd0aHJlZScpKSAlPiUgdGlkeXI6OnVuY291bnQoYSkNCmBgYA0KVW5jb3VudCBkb2VzIHRoZSBvcHBvc2l0ZSB3b3JrIG9mIGNvdW50Lg0KDQpMZXQncyBzZWUgdGhlIG5ldyBkYXRhIGZyYW1lIG5vdy0gDQpgYGB7cn0NCmdsaW1wc2UoZGYpDQpgYGANCg0KTm93IGl0IGNhbiBiZSB1c2VkIHRvIGNyZWF0ZSBiYXIgY2hhcnRzLg0KDQotLS0NCg0KIyMgQSBTaW1wbGUgQmFycGxvdA0KDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGYpICsNCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyh4ID0gSGFpcikpDQpgYGANCg0KVGhlIG1hcHBpbmcgY2FuIGJlIGRvbmUgaW5zaWRlIHRoZSBnZ3Bsb3QoKSBmdW5jdGlvbiAtIA0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRmLCBtYXBwaW5nID0gYWVzKHg9SGFpcikpKw0KICBnZW9tX2JhcihmaWxsID0gImJsYWNrIikgKyAgDQogIGxhYnModGl0bGUgPSAiSGFpciBDb2xvciIsIA0KICAgICAgIHN1YnRpdGxlID0gIjU5MiBTdGF0aXN0aWNzIFN0dWRlbnRzIiwNCiAgICAgICBjYXB0aW9uID0gIihGcm9tIFIncyBidWlsdCBpbiBIYWlyRXllQ29sb3Igc2FtcGxlIGRhdGFzZXQpIiwNCiAgICAgICB5ID0gIk51bWJlciBvZiBTdHVkZW50cyIsIHggPSBOVUxMKQ0KYGBgDQoNCiMjIEhvcml6b250YWwgQmFyIENoYXJ0DQoNClVzaW5nIGNvb3JkX2ZsaXAoKSAtDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGYsIG1hcHBpbmcgPSBhZXMoeD1IYWlyKSkrDQogIGdlb21fYmFyKGZpbGwgPSAiYmxhY2siKSArICANCiAgbGFicyh0aXRsZSA9ICJIYWlyIENvbG9yIiwgDQogICAgICAgc3VidGl0bGUgPSAiNTkyIFN0YXRpc3RpY3MgU3R1ZGVudHMiLA0KICAgICAgIGNhcHRpb24gPSAiKEZyb20gUidzIGJ1aWx0IGluIEhhaXJFeWVDb2xvciBzYW1wbGUgZGF0YXNldCkiLA0KICAgICAgIHkgPSAiTnVtYmVyIG9mIFN0dWRlbnRzIiwgeCA9IE5VTEwpICsNCiAgY29vcmRfZmxpcCgpDQpgYGANCg0KQXNzaWduaW5nIHZhcmlhYmxlIHRvIHRoZSB5IGF4aXMgLQ0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRmLCBtYXBwaW5nID0gYWVzKHkgPSBIYWlyKSkrDQogIGdlb21fYmFyKGZpbGwgPSAiYmxhY2siKSArICANCiAgbGFicyh0aXRsZSA9ICJIYWlyIENvbG9yIiwgDQogICAgICAgc3VidGl0bGUgPSAiNTkyIFN0YXRpc3RpY3MgU3R1ZGVudHMiLA0KICAgICAgIGNhcHRpb24gPSAiKEZyb20gUidzIGJ1aWx0IGluIEhhaXJFeWVDb2xvciBzYW1wbGUgZGF0YXNldCkiLA0KICAgICAgIHkgPSAiTnVtYmVyIG9mIFN0dWRlbnRzIiwgeCA9IE5VTEwpDQpgYGANCg0KIyMgVXNpbmcgQ29sb3JzDQoNCmZpbGwgPSB7dGhlIHNhbWUgdmFyaWFibGUgYXMgdGhlIHggYXhpc30gc28gdGhhdCBmb3IgZWFjaCB2YXJpYWJsZSBkaWZmZXJlbnQgY29sb3JzIGlzIHNob3duIC0gDQpgYGB7cn0NCmdncGxvdChkYXRhID0gZGYpKw0KICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKHggPSBIYWlyLCBmaWxsID0gSGFpcikpKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICAjIERvbid0IHNob3cgdGhlIGxlZ2VuZA0KYGBgDQoNClVzaW5nIGh1ZSAtIA0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRmKSsNCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyh4ID0gSGFpciwgZmlsbCA9IEhhaXIpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArICAjIERvbid0IHNob3cgdGhlIGxlZ2VuZA0KICBzY2FsZV9maWxsX2h1ZShjID0gMjApICMgRGlmZmVyZW50IHZhbHVlcyBjIGdpdmVzIGRpZmZlcmVudCBpbnRlbnNpdHkgb2YgY29sb3JzDQpgYGANCg0KIyMjIE1hbnVhbGx5IHNlbGVjdGluZyBjb2xvcnMNCg0KSG93IHRvIG1hbnVhbGx5IHNldCBjb2xvcnMgaW4gYSBiYXIgY2hhcnQ/ICAgDQpNYW51YWxseSBzZWxlY3RpbmcgY29sb3JzIC0gDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGEgPSBkZikrDQogIGdlb21fYmFyKG1hcHBpbmcgPSBhZXMoeCA9IEhhaXIsIGZpbGwgPSBIYWlyKSwgDQogICAgICAgICAgIGNvbCA9ICJibGFjayIsDQogICAgICAgICAgIGZpbGwgPSBjKCJCbGFjayIsImJlaWdlIiwiYmlzcXVlMyIsInJlZCIpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQ0KYGBgDQoNCkFub3RoZXIgd2F5IHRvIGRvIHRoYXQgLSANCg0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRmKSsNCiAgZ2VvbV9iYXIobWFwcGluZyA9IGFlcyh4ID0gSGFpciwgZmlsbCA9IEhhaXIpLCBjb2wgPSAiYmxhY2siKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkJsYWNrIiwiYmVpZ2UiLCJiaXNxdWUzIiwicmVkIikpDQpgYGANCg0KIyMgTW9kaWZ5aW5nIEF4aXMgVGlja21hcmtzDQoNCmBgYHtyfQ0KZ2dwbG90KGRmLCBhZXMoeCA9IEhhaXIpKSArDQogIGdlb21fYmFyKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDMwMCwgYnk9NTApKSArDQogIGxhYnMoeCA9ICJDb2xvcnMiLCB5ID0gIkZyZXF1ZW5jeSIsDQogICAgICAgdGl0bGUgPSAiQmFyIENoYXJ0IG9mIENvbG9ycyIsDQogICAgICAgc3VidGl0bGUgPSAiQW4gb2JzZXJ2YXRpb25hbCBzdHVkeSIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSAjIGNlbnRlciB0aGUgdGl0bGUgYW5kIHN1YnRpdGxlDQpgYGANCg0KIyMgU3RhY2tlZCBCYXIgQ2hhcnQNCg0KVXNpbmcgZmlsbCBhcmd1bWVudCBzdGFja2VkIGJhciBjYW4gYmUgbWFkZSAtIA0KYGBge3J9DQpnZ3Bsb3QoZGF0YSA9IGRmKSArIA0KICBnZW9tX2JhcihtYXBwaW5nID0gYWVzKEhhaXIsIGZpbGwgPSBTZXgpKQ0KYGBgDQoNCg0KIyMjIDEwMCUgU3RhY2tlZCBCYXIgQ2hhcnQNCg0KVXNpbmcgcG9zaXRpb24gPSAiZmlsbCIgaW5zaWRlIGdlb21fYmFyIC0gDQpgYGB7cn0NCmdncGxvdChkZiwgYWVzKEhhaXIsIGZpbGwgPSBTZXgpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICBsYWJzKHg9IkhhaXIgQ29sb3IiLCB5PU5VTEwpICsNCiAgY29vcmRfZmxpcCgpDQpgYGAgDQoNCiMjIENoYW5naW5nIE9yZGVyIG9mIEJhcnMNCg0KYGBge3J9DQpkZiRIYWlyIDwtIGZhY3RvcihkZiRIYWlyLCBsZXZlbHMgPSBjKCJSZWQiLCAiQmxhY2siLCAiQmxvbmQiLCAiQnJvd24iKSkNCmdncGxvdChkZiwgYWVzKHk9SGFpciwgZmlsbCA9IFNleCkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIGxhYnMoeD1OVUxMLCB5PSJIYWlyIENvbG9yIikgDQpgYGANCg0KQW5vdGhlciB3YXkgdG8gZG8gdGhpcyB1c2luZyBgc2NhbGVfeV9kaXNjcmV0ZSgpYC0gDQpgYGB7cn0NCmdncGxvdChkZiwgYWVzKHkgPSBIYWlyLCBmaWxsID0gU2V4KSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIpICsNCiAgbGFicyh4PU5VTEwsIHk9IkhhaXIgQ29sb3IiKSArDQogIHNjYWxlX3lfZGlzY3JldGUobGltaXRzID0gYygiQmxhY2siLCJSZWQiLCJCcm93biIsIkJsb25kIikpDQpgYGANCg0KIyMgQ2hhbmdpbmcgT3JkZXIgaW4gTGVnZW5kJ3MgTGFiZWxzDQoNClVzaW5nIGBzY2FsZV9maWxsX2Rpc2NyZXRlKClgIC0NCmBgYHtyfQ0KZ2dwbG90KGRmLCBhZXMoeSA9IEhhaXIsIGZpbGwgPSBTZXgpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICBsYWJzKHg9TlVMTCwgeT0iSGFpciBDb2xvciIpICsNCiAgc2NhbGVfeV9kaXNjcmV0ZShsaW1pdHMgPSBjKCJCbGFjayIsIlJlZCIsIkJyb3duIiwiQmxvbmQiKSkgKw0KICBzY2FsZV9maWxsX2Rpc2NyZXRlKGJyZWFrcyA9IGMoIk1hbGUiLCJGZW1hbGUiKSkNCmBgYA0KDQojIyBDaGFuZ2luZyBPcmRlciBvZiBTdGFja3MNCg0KSW4gdGhlIGZvbGxvd2luZyBzdGFja2VkIGJhcnBsb3QsIHRoZSBsZWZ0IGJhciBkZW5vdGVzIGZlbWFsZSBhbmQgdGhlIHJpZ2h0IGJhciBkZW5vdGVzIG1hbGUgLSANCmBgYHtyfQ0KZ2dwbG90KGRmLCBhZXMoeCA9IEhhaXIsIGZpbGwgPSBTZXgpKSArIA0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgbGFicyh4PU5VTEwsIHk9IkhhaXIgQ29sb3IiKSArDQogIHNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gYygiQmxhY2siLCJSZWQiLCJCcm93biIsIkJsb25kIikpDQpgYGANCg0KSWYgd2UgY2hlY2sgdGhlIG9yZGVyIG9mIGxldmVscyBvZiBTZXggd2UnbGwgc2VlIC0gDQpgYGB7cn0NCmxldmVscyhkZiRTZXgpDQpgYGANCg0KTm93IGlmIHRoZSBvcmRlciBpcyBjaGFuZ2VkLCB0aGUgYmFyIHdpbGwgYWxzbyBjaGFuZ2UgaXRzIG9yZGVyIC0gDQpgYGB7cn0NCmRmICU+JSANCiAgbXV0YXRlKFNleCA9IGZhY3RvcihTZXgsIGxldmVscyA9IGMoIk1hbGUiLCJGZW1hbGUiKSkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gSGFpciwgZmlsbCA9IFNleCkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIikgKw0KICBsYWJzKHg9TlVMTCwgeT0iSGFpciBDb2xvciIpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKCJCbGFjayIsIlJlZCIsIkJyb3duIiwiQmxvbmQiKSkNCmBgYA0KDQpUaGlzIGlzIHBhcnRpY3VsYXJseSB1c2VmdWwgd2hlbiBzaG93aW5nIGEgMTAwJSBzdGFja2VkIGJhcnBsb3QgLSANCmBgYHtyfQ0KZGYgJT4lDQogIG11dGF0ZShIYWlyID0gZmFjdG9yKEhhaXIsDQogICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHJldihjKCJCbGFjayIsIkJyb3duIiwiUmVkIiwiQmxvbmQiKSkpKSAlPiUNCiAgZ2dwbG90KGFlcyh5ID0gU2V4LCBmaWxsID0gSGFpcikpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArDQogIGxhYnMoeD1OVUxMLCB5PU5VTEwsIGZpbGwgPSAiSGFpciBDb2xvcnMiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImJsYWNrIiwiIzhCNDUxMyIsIiNGRjAwMDAiLCIjZmFmMGJlIiksDQogICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygiQmxhY2siLCJCcm93biIsIlJlZCIsIkJsb25kIikpICsNCiAgdGhlbWVfYncoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQ0KYGBgDQoNCg0KIyMgQ2hhbmdpbmcgd2lkdGggb2YgdGhlIGJhcnMNCg0KV2lkdGggb2YgdGhlIGJhcnMgY2FuIGJlIGNoYW5nZWQgdXNpbmcgdGhlIGB3aWR0aGAgYXJndW1lbnQgZnJvbSBnZW9tX2JhcigpLiBJdCB0YWtlcyB2YWx1ZXMgZnJvbSAwIHRvIDEgLSANCmBgYHtyfQ0KZ2dwbG90KGRmLCBhZXMoSGFpciwgZmlsbCA9IFNleCkpICsgDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLCANCiAgICAgICAgICAgd2lkdGggPSAwLjUpICsNCiAgbGFicyh4PSJIYWlyIENvbG9yIiwgeT1OVUxMKSArDQogIGNvb3JkX2ZsaXAoKQ0KYGBgDQoNCiMjIFNpZGUgYnkgU2lkZSBCYXIgQ2hhcnQNCg0KVXNpbmcgZG9kZ2UgLQ0KYGBge3J9DQpnZ3Bsb3QoZGYsIGFlcyhIYWlyLCBmaWxsID0gU2V4KSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIGxhYnMoeD0iSGFpciBDb2xvciIsIHk9TlVMTCkNCmBgYA0KDQpVc2luZyBkb2RnZTIgLQ0KYGBge3J9DQpnZ3Bsb3QoZGYsIGFlcyhIYWlyLCBmaWxsID0gU2V4KSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UyIikgKw0KICBsYWJzKHg9IkhhaXIgQ29sb3IiLCB5PU5VTEwpDQpgYGANCg0KSW4gdGhlIGZvbGxvd2luZyBjYXNlIHdlIGNhbiBzZWUgdGhhdCB0aGVyZSBpcyBubyBNYWxlIHdobyBoYXMgdGhlIGhhaXIgY29sb3IgcmVkLiBJdCBmaWxscyB0aGUgd2hvbGUgYmFyIHdpdGggRmVtYWxlIGJhciAtDQpgYGB7cn0NCmRmICU+JSANCiAgZmlsdGVyKCEoU2V4PT0iTWFsZSIgJiBIYWlyPT0iUmVkIikpICU+JSANCiAgZ2dwbG90KGFlcyhIYWlyLCBmaWxsID0gU2V4KSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UyIikgKw0KICBsYWJzKHg9IkhhaXIgQ29sb3IiLCB5PU5VTEwpDQpgYGANCg0KVG8gcHJldmVudCBpdCBmcm9tIGhhcHBlbmluZyB1c2UgcG9zaXRpb25fZG9kZ2UyKHByZXNlcnZlID0gInNpbmdsZSIpIGluIHBvc2l0aW9uIGFyZ3VtZW50IC0gDQpgYGB7cn0NCmRmICU+JSANCiAgZmlsdGVyKCEoU2V4PT0iTWFsZSIgJiBIYWlyPT0iUmVkIikpICU+JSANCiAgZ2dwbG90KGFlcyhIYWlyLCBmaWxsID0gU2V4KSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZTIocHJlc2VydmUgPSAic2luZ2xlIikpICsNCiAgbGFicyh4PSJIYWlyIENvbG9yIiwgeT1OVUxMKQ0KYGBgDQoNCnByZXNlcnZlID0gInRvdGFsIiB3aWxsIGZpbGwgdGhlIHdob2xlIHBsYWNlIC0gDQpgYGB7cn0NCmRmICU+JSANCiAgZmlsdGVyKCEoU2V4PT0iTWFsZSIgJiBIYWlyPT0iUmVkIikpICU+JSANCiAgZ2dwbG90KGFlcyhIYWlyLCBmaWxsID0gU2V4KSkgKyANCiAgZ2VvbV9iYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZTIocHJlc2VydmUgPSAidG90YWwiKSkgKw0KICBsYWJzKHg9IkhhaXIgQ29sb3IiLCB5PU5VTEwpDQpgYGANCg0KIyMgQ29sdW1uIENoYXJ0DQoNCkNvbHVtbiBjaGFydHMgZGF0YSBsb29rcyBsaWtlIHRoaXMgLSAoYWZ0ZXIgbWFuaXB1bGF0aW9uKQ0KYGBge3IgbWVzc2FnZT1GfQ0KaGFpcmRmIDwtIGRmICU+JSANCiAgZmlsdGVyKFNleCA9PSAiTWFsZSIpICU+JSANCiAgZ3JvdXBfYnkoSGFpcikgJT4lIA0KICBzdW1tYXJpemUoZnJlcXVlbmN5ID0gbigpKSANCmhhaXJkZg0KYGBgDQoNClRoaXMgdHlwZXMgb2YgZGF0YSBmcmFtZSBjYW4gYmUgZ3JhcGhlZCBpbiBjb2x1bW4gY2hhcnQgdXNpbmcgdGhlIGZ1bmN0aW9uIGdlb21fY29sKCksIG5vdCBnZW9tX2JhcigpLCBoZXJlIGlzIHRoZSBkaWZmZXJlbmNlIC0gDQpgYGB7cn0NCmhhaXJkZiAlPiUgDQogIGdncGxvdCgpKyANCiAgZ2VvbV9jb2wobWFwcGluZyA9IGFlcyh4PUhhaXIsIHk9ZnJlcXVlbmN5KSwNCiAgICAgICAgICAgZmlsbCA9IGMoIkJsYWNrIiwiYmVpZ2UiLCJiaXNxdWUzIiwiY29yYWwyIikpICsNCiAgbGFicyh0aXRsZT0iSGFpciBDb2xvciBpbiBDb2x1bW4gQ2hhcnQiKQ0KYGBgDQoNClRoaXMga2luZCBvZiBkYXRhIGNhbiBhbHNvIGJlIGdyYXBoZWQgYnkgZGVmaW5pbmcgYHN0YXQgPSAiaWRlbnRpdHkiYCBpbiB0aGUgYGdlb21fYmFyKClgIGZ1bmN0aW9uIC0gDQpgYGB7cn0NCmhhaXJkZiAlPiUgDQogIGdncGxvdCgpICsNCiAgZ2VvbV9iYXIoYWVzKHggPSBIYWlyLCB5ID0gZnJlcXVlbmN5KSwgDQogICAgICAgICAgIHN0YXQgPSAiaWRlbnRpdHkiKQ0KYGBgDQoNCg0KDQojIyBQdXR0aW5nIGZyZXF1ZW5jaWVzIG9uIGVhY2ggYmFycw0KDQpgYGB7cn0NCmhhaXJkZiAlPiUgDQogIGdncGxvdChhZXMoeCA9IEhhaXIsIHkgPSBmcmVxdWVuY3kpKSArDQogIGdlb21fY29sKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDE1MCwgYnk9MzApKSArDQogIGxhYnMoeCA9ICJDb2xvcnMiLCB5ID0gIkZyZXF1ZW5jeSIsDQogICAgICAgdGl0bGUgPSAiQmFyIENoYXJ0IG9mIENvbG9ycyIsDQogICAgICAgc3VidGl0bGUgPSAiQW4gb2JzZXJ2YXRpb25hbCBzdHVkeSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD0gZnJlcXVlbmN5KSwgDQogICAgICAgICAgICB2anVzdD0xLjIsIHNpemU9MywNCiAgICAgICAgICAgIGNvbCA9ICJ3aGl0ZSIpDQpgYGANCg0KDQoNClRvIGtub3cgbW9yZSBhYm91dCBnZ3Bsb3QyIHZpc2l0IFtoZXJlXShodHRwczovL3JwdWJzLmNvbS9NZEFoc2FudWwvZ2dwbG90Ml9zY2F0dGVycGxvdCkNCg0KVG8ga25vdyBtb3JlIGFib3V0IGNvbG9ycyB2aXNpdCBbaGVyZV0oaHR0cHM6Ly9ycHVicy5jb20vTWRBaHNhbnVsL2NvbG9yc19wYWxldHRlcykNCg0KQ2hlY2sgb3V0IFtodHRwczovL3d3dy5ob21ld29ya2hlbHBvbmxpbmUubmV0XShodHRwczovL3d3dy5ob21ld29ya2hlbHBvbmxpbmUubmV0L3Byb2dyYW1taW5nL3ItcHJvZ3JhbW1pbmcgIlIgaGVscCIpIGZvciBSIFN0dWRpbyBQcm9ncmFtbWluZyBhc3NpZ25tZW50IGhlbHAuDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==