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