I ended up distributing my own pizza survey last week (since I was out of town and couldn’t contribute to the group effort as much as I should’ve). The data has a definite Californian skew, but there we are!
Packages and data I’ll be using:
library(tidyverse)
-- Attaching packages ---------------------------------------------------------------------------------- tidyverse 1.2.1 --
v ggplot2 3.0.0 v purrr 0.2.5
v tibble 1.4.2 v dplyr 0.7.6
v tidyr 0.8.1 v stringr 1.3.1
v readr 1.1.1 v forcats 0.3.0
-- Conflicts ------------------------------------------------------------------------------------- tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
library(ggrepel)
library(stringr)
setwd("C:/Users/monica/Documents/Courses/Q7_Fall2018/GEOG 208/week5_project")
column_names = c("submitted","name","age","gender","ethnicity","state","city","us_born","cntry_birth","pizza_freq","pizza_rating","pizza_1word","best_1","best_2","best_3","worst_1","worst_2","worst_3","add_ons","no_of_toppings","most_surprising","unacceptable","pineapple_q","diet","tacos","hamburgers","sushi","salad","bagels","steak","email")
untidy_pizza <- read_csv("the_pizza_survey.csv", skip = 1, col_names = column_names)
Parsed with column specification:
cols(
.default = col_character(),
age = col_integer(),
pizza_rating = col_integer(),
tacos = col_integer(),
hamburgers = col_integer(),
sushi = col_integer(),
salad = col_integer(),
bagels = col_integer(),
steak = col_integer()
)
See spec(...) for full column specifications.
head(untidy_pizza)
# A tibble: 6 x 31
submitted name age gender ethnicity state city us_born cntry_birth pizza_freq pizza_rating pizza_1word best_1 best_2
<chr> <chr> <int> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <int> <chr> <chr> <chr>
1 2018/10/~ <NA> 63 Male Asian Cali~ Sant~ No Philippines About onc~ 3 Acceptable Fresh~ Extra~
2 2018/10/~ Cass~ 20 Female White Cali~ San ~ Yes N/A About onc~ 4 Delicious Spina~ Garlic
3 2018/10/~ Moni~ 28 Female Asian Cali~ Los ~ Yes <NA> About onc~ 4 Delicious Mushr~ Peppe~
4 2018/10/~ Matt 25 Male Asian Cali~ Cost~ Yes <NA> Less than~ 4 Comfortabl~ Peppe~ Mushr~
5 2018/10/~ Soph~ 22 Female White;As~ Cali~ East~ Yes <NA> About onc~ 4 Delicious Mushr~ Pinea~
6 2018/10/~ ciro 29 Male Prefer n~ Cali~ Los ~ No Germany About onc~ 3 Delicious Sausa~ Mushr~
# ... with 17 more variables: best_3 <chr>, worst_1 <chr>, worst_2 <chr>, worst_3 <chr>, add_ons <chr>,
# no_of_toppings <chr>, most_surprising <chr>, unacceptable <chr>, pineapple_q <chr>, diet <chr>, tacos <int>,
# hamburgers <int>, sushi <int>, salad <int>, bagels <int>, steak <int>, email <chr>
Some preliminary cleaning: I know for certain that I don’t need the first or last columns, and I would like to add a unique ID (that may or may not end up being useful). Also, there was at least one prank entry, from a “Pete Za” who is 314 years old. Pete has to go.
pizza <- untidy_pizza[c(2:30)] %>%
mutate(participant_id = row_number()) %>%
filter(age <= 120)
Most of the survey participants live in the U.S., and most of them are in California, so instead of doing a geographic grouping by country or state, I’m going to go with the Census’ very basic regions.
census_region <- read_csv("census_state_regions.csv")
Parsed with column specification:
cols(
Region = col_integer(),
Region_name = col_character(),
Division = col_integer(),
State_FIPS = col_integer(),
State = col_character()
)
pizza_region <- pizza %>%
rename(State = state) %>%
left_join(census_region, by = "State")
pizza_region$Region_name[is.na(pizza_region$Region_name)] <- "Outside U.S."
pizza_region$Region_name <- ordered(pizza_region$Region_name, levels = c("Outside U.S.", "Midwest", "Northeast", "South", "West"))
table(pizza_region$Region_name)
Outside U.S. Midwest Northeast South West
3 5 21 23 93
1. Tippity Top Toppings
So, what does my population of 145 claim are the best toppings? I had participants choose their top 3 favorites from a pre-defined list, which I hoped would make the clean-up easier. To identify the top 10 toppings, we’ll attach a crude score to each topping (I asked participants to rank their top 3).
best_toppings <- pizza_region %>%
gather("best_rank", "best_toppings", 12:14) %>%
mutate(best_toppings = sub("Chicken \\(BBQ, buffalo, etc.\\)", "Chicken", best_toppings)) %>%
mutate(best_toppings = sub("Olives \\(black, green, kalamata, etc.\\)", "Olives", best_toppings)) %>%
mutate(best_toppings = sub("N/A - I don't eat pizza", "N/A", best_toppings)) %>%
mutate(best_rank = gsub("best_1", 1, best_rank)) %>%
mutate(best_rank = gsub("best_2", 2, best_rank)) %>%
mutate(best_rank = gsub("best_3", 3, best_rank))
best_toppings$score <- ifelse(
best_toppings$best_rank == 1, 3, (ifelse(
best_toppings$best_rank == 2, 2, ifelse(
best_toppings$best_rank == 3, 1, NA))))
best_sum <- best_toppings %>%
group_by(best_toppings) %>%
summarise(best_votes = n(),
best_score = sum(score)) %>%
rename(topping = best_toppings) %>%
arrange(desc(best_score))
top10_toppings <- best_sum$topping[1:10]
Let’s break down these top 10 by how frequently participants eat pizza:
ggplot(subset(best_toppings, best_toppings %in% top10_toppings), aes(x = best_toppings, fill = pizza_freq)) +
geom_bar(width = 0.75) +
coord_flip() +
theme_minimal() +
scale_fill_manual(values = c("#fdb87d", "#ff8364", "#ffe8d5", "#ff4d4d"), name = "How often do you \neat pizza?") +
labs(title = "Top 10 Pizza Toppings", y = "No. of Votes", x = "") +
theme(plot.title = element_text(vjust = 2, face = "bold"),
axis.title.x = element_text(vjust = -1, color = "gray60"))

Though they don’t make up the majority of participants, those who most frequently eat pizza (both more than once a week and about once a week) tend to stick to some of the most popular toppings, including pepperoni, sausage, and mushrooms.
2. The Rejects
And who are the least loved among toppings?
worst_toppings <- pizza_region %>%
gather("worst_rank", "worst_toppings", 15:17) %>%
mutate(worst_toppings = sub("Chicken \\(BBQ, buffalo, etc.\\)", "Chicken", worst_toppings)) %>%
mutate(worst_toppings = sub("Olives \\(black, green, kalamata, etc.\\)", "Olives", worst_toppings)) %>%
mutate(worst_toppings = sub("N/A - I like it all", "N/A", worst_toppings)) %>%
mutate(worst_toppings = sub("Excessive cheese", "Extra cheese", worst_toppings)) %>%
mutate(worst_rank = gsub("worst_1", 1, worst_rank)) %>%
mutate(worst_rank = gsub("worst_2", 2, worst_rank)) %>%
mutate(worst_rank = gsub("worst_3", 3, worst_rank))
worst_toppings$score <- ifelse(
worst_toppings$worst_rank == 1, 3, (ifelse(
worst_toppings$worst_rank == 2, 2, ifelse(
worst_toppings$worst_rank == 3, 1, NA))))
worst_sum <- worst_toppings %>%
group_by(worst_toppings) %>%
summarise(worst_votes = n(),
worst_score = sum(score)) %>%
rename(topping = worst_toppings) %>%
arrange(desc(worst_score))
worst_sum_noNA <- worst_sum %>%
filter(topping != "N/A")
bottom10_toppings <- worst_sum_noNA$topping[1:10]
This time we’ll break up the bottom 10 by how much the participants like pizza.
ggplot(subset(worst_toppings, worst_toppings %in% bottom10_toppings), aes(x = worst_toppings, fill = as.character(pizza_rating))) +
geom_bar(width = 0.7) +
coord_flip() +
theme_minimal() +
scale_fill_manual(values = c("#fefea4","#ffdc76", "#d3504a", "#4a2c2c"), name = "How much do \nyou like pizza?\n(1-5 scale)") +
labs(title = "10 Least Loved Pizza Toppings", y = "No. of Votes", x = "") +
theme(plot.title = element_text(vjust = 2, face = "bold"),
axis.title.x = element_text(vjust = -1, color = "gray60"))

Anchovies are a least favorite topping among even the most die-hard pizza lovers, followed by olives, pineapple, and eggplant. Participants who really like pizza but aren’t willing to call it their favorite food (rating = 4) follow a similar pattern.
3. Pizza Topping Agreement
Some toppings showed up on both lists - is everyone in agreement about these most loved and most loathed toppings? Let’s see! We’ll compare the number of “most favorite” votes each topping received to its “least favorite” votes. In this graph, points closer to the axes are more agreed-upon toppings.
best_no1 <- best_toppings %>%
filter(best_rank == 1) %>%
group_by(best_toppings) %>%
summarise(best_1 = n()) %>%
rename(topping = best_toppings)
topping_votes <- merge(best_no1, merge(best_sum, worst_sum, by = "topping", all.x = TRUE, all.y = TRUE), by = "topping", all.x = TRUE, all.y = TRUE)
topping_votes[is.na(topping_votes)] <- 0
rm(best_no1)
head(topping_votes)
topping best_1 best_votes best_score worst_votes worst_score
1 Anchovies 5 11 23 65 145
2 Artichokes 5 11 22 14 27
3 Bacon 8 25 47 10 20
4 Basil 4 17 30 2 2
5 Bell peppers 3 20 34 25 51
6 Chicken 7 16 36 22 43
ggplot(topping_votes, aes(x = best_votes, y = worst_votes)) +
geom_point(aes(size = best_1), shape = 21, stroke = 1.1, color = "#ff4d4d", fill = "#ff4d4d", alpha = 0.4) +
geom_text_repel(aes(label = topping), point.padding = 0.8) +
scale_size(name = "#1 Favorite \n Votes", range = c(2,14)) +
theme_minimal() +
labs(title = "Pizza Topping Agreement", subtitle = "Number of 'Favorite' vs. 'Least Favorite' votes received by topping", x = "Favorite Topping Votes", y = "Least Favorite Topping Votes") +
theme(plot.title = element_text(vjust = 2, face = "bold"),
plot.subtitle = element_text(color = "gray60"),
axis.title.x = element_text(vjust = -1),
axis.title.y = element_text(vjust = 2),
axis.text.y = element_text(hjust = 1.5))

Participants are mostly in agreement about the favorite (pepperoni, mushrooms, sausage) and least favorite (anchovies, eggplant) toppings, but there is more debate about toppings like pineapple (surprise, surprise), olives, and bell peppers.
4. A Regional Look at Pineapple
Pineapple appears to be one of the more divisive toppings. Is there a regional difference in its reception? …and can this chart be trusted when the responses from some of these regions was so teeny tiny…?
ggplot(pizza_region, aes(x = Region_name, fill = pineapple_q)) +
geom_bar(position = "fill", width = 0.25) +
geom_text(stat='count', aes(label=..count..), position = position_fill(vjust = 0.5)) +
scale_fill_manual(values = c("#ff7657", "#665c84", "#fbeed7", "#ffba5a"), name = "") +
coord_flip() +
labs(title = "Does pineapple belong on pizza?", subtitle = "Responses by U.S. region", x = "", y = "Percent of votes") +
theme_minimal() +
theme(plot.title = element_text(vjust = 2, face = "bold"),
plot.subtitle = element_text(color = "gray60"),
axis.title.x = element_text(vjust = -1, color = "gray60"))

It is disappointing to find that nearly 50% of participants from most U.S. regions have such silly taste in pizza. The Midwest appears to have its values in the right place (though there were very few responses from the region [n = 5]).
5. Pizza, and…
I collected some very important data regarding participants’ taste for other popular foods. How does their apapreciation for pizza compare to these other eats?
other_eats <- pizza_region %>%
select(participant_id, Region_name, pizza_rating, tacos:steak) %>%
group_by(Region_name) %>%
gather("eats", "rating", tacos:steak)
other_eats$eats <- str_to_title(other_eats$eats)
I had grand visions for the visualization of this data, but they have been reduced to this jitter plot:
ggplot(other_eats, aes(x = rating, y = pizza_rating, color = Region_name, fill = Region_name)) +
facet_wrap(. ~ eats) +
geom_jitter(width = 0.3, height = 0.3, seed = NULL, size = 1.5, shape = 21, alpha = 0.75) +
scale_color_manual(values = c("#182C61","#1B9CFC","#55E6C1","#FC427B","#EAB543"), name = "Region") +
scale_fill_manual(values = c("#182C61","#1B9CFC","#55E6C1","#FC427B","#EAB543"), name = "Region") +
theme_minimal() +
labs(title = "How much do you like _____?", subtitle = "Participants' ratings of pizza vs. ratings of other eats", x = "(1 = low rating, 5 = high rating)", y = "Pizza Rating") +
theme(plot.title = element_text(vjust = 2, face = "bold"),
plot.subtitle = element_text(color = "gray60"),
axis.text.y = element_text(hjust = 1.5),
axis.title.y = element_text(vjust = 3),
axis.title.x = element_text(vjust = -2, color = "gray60"),
strip.text.x = element_text(face = "bold"),
panel.margin = unit(1.5, "lines"))
Ignoring unknown parameters: seed`panel.margin` is deprecated. Please use `panel.spacing` property instead

A few observations can be drawn from this confetti here:
-
Tacos are the most beloved of these foods, far more participants gave tacos a 5 than they did pizza, and no one dares say they hate tacos (rating = 1).
-
Sushi is the most polarizing among the other eats, with a lot of pizza lovers (rating = 5) giving it a 1!
-
People aren’t as wild about steak as I thought. That’s kind of nice!
-
People aren’t as wild about bagels as I thought. I’m kind of bothered?
-
There are zero regional patterns that I can make out from this mess.
LS0tDQp0aXRsZTogIlRoZSBQaXp6YSBTdXJ2ZXkiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpJIGVuZGVkIHVwIGRpc3RyaWJ1dGluZyBteSBvd24gcGl6emEgc3VydmV5IGxhc3Qgd2VlayAoc2luY2UgSSB3YXMgb3V0IG9mIHRvd24gYW5kIGNvdWxkbid0IGNvbnRyaWJ1dGUgdG8gdGhlIGdyb3VwIGVmZm9ydCBhcyBtdWNoIGFzIEkgc2hvdWxkJ3ZlKS4gVGhlIGRhdGEgaGFzIGEgZGVmaW5pdGUgQ2FsaWZvcm5pYW4gc2tldywgYnV0IHRoZXJlIHdlIGFyZSEgIA0KDQpQYWNrYWdlcyBhbmQgZGF0YSBJJ2xsIGJlIHVzaW5nOiANCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoZ2dyZXBlbCkNCmxpYnJhcnkoc3RyaW5ncikNCg0Kc2V0d2QoIkM6L1VzZXJzL21vbmljYS9Eb2N1bWVudHMvQ291cnNlcy9RN19GYWxsMjAxOC9HRU9HIDIwOC93ZWVrNV9wcm9qZWN0IikNCmNvbHVtbl9uYW1lcyA9IGMoInN1Ym1pdHRlZCIsIm5hbWUiLCJhZ2UiLCJnZW5kZXIiLCJldGhuaWNpdHkiLCJzdGF0ZSIsImNpdHkiLCJ1c19ib3JuIiwiY250cnlfYmlydGgiLCJwaXp6YV9mcmVxIiwicGl6emFfcmF0aW5nIiwicGl6emFfMXdvcmQiLCJiZXN0XzEiLCJiZXN0XzIiLCJiZXN0XzMiLCJ3b3JzdF8xIiwid29yc3RfMiIsIndvcnN0XzMiLCJhZGRfb25zIiwibm9fb2ZfdG9wcGluZ3MiLCJtb3N0X3N1cnByaXNpbmciLCJ1bmFjY2VwdGFibGUiLCJwaW5lYXBwbGVfcSIsImRpZXQiLCJ0YWNvcyIsImhhbWJ1cmdlcnMiLCJzdXNoaSIsInNhbGFkIiwiYmFnZWxzIiwic3RlYWsiLCJlbWFpbCIpDQp1bnRpZHlfcGl6emEgPC0gcmVhZF9jc3YoInRoZV9waXp6YV9zdXJ2ZXkuY3N2Iiwgc2tpcCA9IDEsIGNvbF9uYW1lcyA9IGNvbHVtbl9uYW1lcykNCg0KaGVhZCh1bnRpZHlfcGl6emEpDQpgYGANCg0KU29tZSBwcmVsaW1pbmFyeSBjbGVhbmluZzogSSBrbm93IGZvciBjZXJ0YWluIHRoYXQgSSBkb24ndCBuZWVkIHRoZSBmaXJzdCBvciBsYXN0IGNvbHVtbnMsIGFuZCBJIHdvdWxkIGxpa2UgdG8gYWRkIGEgdW5pcXVlIElEICh0aGF0IG1heSBvciBtYXkgbm90IGVuZCB1cCBiZWluZyB1c2VmdWwpLiBBbHNvLCB0aGVyZSB3YXMgYXQgbGVhc3Qgb25lIHByYW5rIGVudHJ5LCBmcm9tIGEgIlBldGUgWmEiIHdobyBpcyAzMTQgeWVhcnMgb2xkLiBQZXRlIGhhcyB0byBnby4NCg0KYGBge3J9DQpwaXp6YSA8LSB1bnRpZHlfcGl6emFbYygyOjMwKV0gJT4lDQogIG11dGF0ZShwYXJ0aWNpcGFudF9pZCA9IHJvd19udW1iZXIoKSkgJT4lDQogIGZpbHRlcihhZ2UgPD0gMTIwKQ0KYGBgDQoNCk1vc3Qgb2YgdGhlIHN1cnZleSBwYXJ0aWNpcGFudHMgbGl2ZSBpbiB0aGUgVS5TLiwgYW5kIG1vc3Qgb2YgdGhlbSBhcmUgaW4gQ2FsaWZvcm5pYSwgc28gaW5zdGVhZCBvZiBkb2luZyBhIGdlb2dyYXBoaWMgZ3JvdXBpbmcgYnkgY291bnRyeSBvciBzdGF0ZSwgSSdtIGdvaW5nIHRvIGdvIHdpdGggdGhlIENlbnN1cycgdmVyeSBiYXNpYyByZWdpb25zLg0KDQpgYGB7cn0NCmNlbnN1c19yZWdpb24gPC0gcmVhZF9jc3YoImNlbnN1c19zdGF0ZV9yZWdpb25zLmNzdiIpDQoNCnBpenphX3JlZ2lvbiA8LSBwaXp6YSAlPiUNCiAgcmVuYW1lKFN0YXRlID0gc3RhdGUpICU+JQ0KICBsZWZ0X2pvaW4oY2Vuc3VzX3JlZ2lvbiwgYnkgPSAiU3RhdGUiKQ0KDQpwaXp6YV9yZWdpb24kUmVnaW9uX25hbWVbaXMubmEocGl6emFfcmVnaW9uJFJlZ2lvbl9uYW1lKV0gPC0gIk91dHNpZGUgVS5TLiINCnBpenphX3JlZ2lvbiRSZWdpb25fbmFtZSA8LSBvcmRlcmVkKHBpenphX3JlZ2lvbiRSZWdpb25fbmFtZSwgbGV2ZWxzID0gYygiT3V0c2lkZSBVLlMuIiwgIk1pZHdlc3QiLCAiTm9ydGhlYXN0IiwgIlNvdXRoIiwgIldlc3QiKSkNCg0KdGFibGUocGl6emFfcmVnaW9uJFJlZ2lvbl9uYW1lKQ0KYGBgDQoNCjxocj4NCjxiPjEuIFRpcHBpdHkgVG9wIFRvcHBpbmdzPC9iPg0KDQpTbywgd2hhdCBkb2VzIG15IHBvcHVsYXRpb24gb2YgMTQ1IGNsYWltIGFyZSB0aGUgYmVzdCB0b3BwaW5ncz8gSSBoYWQgcGFydGljaXBhbnRzIGNob29zZSB0aGVpciB0b3AgMyBmYXZvcml0ZXMgZnJvbSBhIHByZS1kZWZpbmVkIGxpc3QsIHdoaWNoIEkgaG9wZWQgd291bGQgbWFrZSB0aGUgY2xlYW4tdXAgZWFzaWVyLiBUbyBpZGVudGlmeSB0aGUgdG9wIDEwIHRvcHBpbmdzLCB3ZSdsbCBhdHRhY2ggYSBjcnVkZSBzY29yZSB0byBlYWNoIHRvcHBpbmcgKEkgYXNrZWQgcGFydGljaXBhbnRzIHRvIHJhbmsgdGhlaXIgdG9wIDMpLg0KDQpgYGB7cn0NCmJlc3RfdG9wcGluZ3MgPC0gcGl6emFfcmVnaW9uICU+JQ0KICBnYXRoZXIoImJlc3RfcmFuayIsICJiZXN0X3RvcHBpbmdzIiwgMTI6MTQpICU+JQ0KICBtdXRhdGUoYmVzdF90b3BwaW5ncyA9IHN1YigiQ2hpY2tlbiBcXChCQlEsIGJ1ZmZhbG8sIGV0Yy5cXCkiLCAiQ2hpY2tlbiIsIGJlc3RfdG9wcGluZ3MpKSAlPiUNCiAgbXV0YXRlKGJlc3RfdG9wcGluZ3MgPSBzdWIoIk9saXZlcyBcXChibGFjaywgZ3JlZW4sIGthbGFtYXRhLCBldGMuXFwpIiwgIk9saXZlcyIsIGJlc3RfdG9wcGluZ3MpKSAlPiUNCiAgbXV0YXRlKGJlc3RfdG9wcGluZ3MgPSBzdWIoIk4vQSAtIEkgZG9uJ3QgZWF0IHBpenphIiwgIk4vQSIsIGJlc3RfdG9wcGluZ3MpKSAlPiUNCiAgbXV0YXRlKGJlc3RfcmFuayA9IGdzdWIoImJlc3RfMSIsIDEsIGJlc3RfcmFuaykpICU+JQ0KICBtdXRhdGUoYmVzdF9yYW5rID0gZ3N1YigiYmVzdF8yIiwgMiwgYmVzdF9yYW5rKSkgJT4lDQogIG11dGF0ZShiZXN0X3JhbmsgPSBnc3ViKCJiZXN0XzMiLCAzLCBiZXN0X3JhbmspKQ0KDQpiZXN0X3RvcHBpbmdzJHNjb3JlIDwtIGlmZWxzZSgNCiAgYmVzdF90b3BwaW5ncyRiZXN0X3JhbmsgPT0gMSwgMywgKGlmZWxzZSgNCiAgICBiZXN0X3RvcHBpbmdzJGJlc3RfcmFuayA9PSAyLCAyLCBpZmVsc2UoDQogICAgICBiZXN0X3RvcHBpbmdzJGJlc3RfcmFuayA9PSAzLCAxLCBOQSkpKSkNCg0KYmVzdF9zdW0gPC0gYmVzdF90b3BwaW5ncyAlPiUNCiAgZ3JvdXBfYnkoYmVzdF90b3BwaW5ncykgJT4lDQogIHN1bW1hcmlzZShiZXN0X3ZvdGVzID0gbigpLA0KICAgICAgICAgICAgYmVzdF9zY29yZSA9IHN1bShzY29yZSkpICU+JQ0KICByZW5hbWUodG9wcGluZyA9IGJlc3RfdG9wcGluZ3MpICU+JQ0KICBhcnJhbmdlKGRlc2MoYmVzdF9zY29yZSkpDQoNCnRvcDEwX3RvcHBpbmdzIDwtIGJlc3Rfc3VtJHRvcHBpbmdbMToxMF0NCmBgYA0KDQpMZXQncyBicmVhayBkb3duIHRoZXNlIHRvcCAxMCBieSBob3cgZnJlcXVlbnRseSBwYXJ0aWNpcGFudHMgZWF0IHBpenphOg0KDQpgYGB7cn0NCmdncGxvdChzdWJzZXQoYmVzdF90b3BwaW5ncywgYmVzdF90b3BwaW5ncyAlaW4lIHRvcDEwX3RvcHBpbmdzKSwgYWVzKHggPSBiZXN0X3RvcHBpbmdzLCBmaWxsID0gcGl6emFfZnJlcSkpICsNCiAgZ2VvbV9iYXIod2lkdGggPSAwLjc1KSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNmZGI4N2QiLCAiI2ZmODM2NCIsICIjZmZlOGQ1IiwgIiNmZjRkNGQiKSwgbmFtZSA9ICJIb3cgb2Z0ZW4gZG8geW91IFxuZWF0IHBpenphPyIpICsNCiAgbGFicyh0aXRsZSA9ICJUb3AgMTAgUGl6emEgVG9wcGluZ3MiLCB5ID0gIk5vLiBvZiBWb3RlcyIsIHggPSAiIikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHZqdXN0ID0gMiwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IC0xLCBjb2xvciA9ICJncmF5NjAiKSkNCmBgYA0KDQpUaG91Z2ggdGhleSBkb24ndCBtYWtlIHVwIHRoZSBtYWpvcml0eSBvZiBwYXJ0aWNpcGFudHMsIHRob3NlIHdobyBtb3N0IGZyZXF1ZW50bHkgZWF0IHBpenphIChib3RoIG1vcmUgdGhhbiBvbmNlIGEgd2VlayBhbmQgYWJvdXQgb25jZSBhIHdlZWspIHRlbmQgdG8gc3RpY2sgdG8gc29tZSBvZiB0aGUgbW9zdCBwb3B1bGFyIHRvcHBpbmdzLCBpbmNsdWRpbmcgcGVwcGVyb25pLCBzYXVzYWdlLCBhbmQgbXVzaHJvb21zLg0KDQo8aHI+DQo8Yj4yLiBUaGUgUmVqZWN0cyA8L2I+DQoNCkFuZCB3aG8gYXJlIHRoZSBsZWFzdCBsb3ZlZCBhbW9uZyB0b3BwaW5ncz8gDQoNCmBgYHtyfQ0Kd29yc3RfdG9wcGluZ3MgPC0gcGl6emFfcmVnaW9uICU+JQ0KICBnYXRoZXIoIndvcnN0X3JhbmsiLCAid29yc3RfdG9wcGluZ3MiLCAxNToxNykgJT4lDQogIG11dGF0ZSh3b3JzdF90b3BwaW5ncyA9IHN1YigiQ2hpY2tlbiBcXChCQlEsIGJ1ZmZhbG8sIGV0Yy5cXCkiLCAiQ2hpY2tlbiIsIHdvcnN0X3RvcHBpbmdzKSkgJT4lDQogIG11dGF0ZSh3b3JzdF90b3BwaW5ncyA9IHN1YigiT2xpdmVzIFxcKGJsYWNrLCBncmVlbiwga2FsYW1hdGEsIGV0Yy5cXCkiLCAiT2xpdmVzIiwgd29yc3RfdG9wcGluZ3MpKSAlPiUNCiAgbXV0YXRlKHdvcnN0X3RvcHBpbmdzID0gc3ViKCJOL0EgLSBJIGxpa2UgaXQgYWxsIiwgIk4vQSIsIHdvcnN0X3RvcHBpbmdzKSkgJT4lDQogIG11dGF0ZSh3b3JzdF90b3BwaW5ncyA9IHN1YigiRXhjZXNzaXZlIGNoZWVzZSIsICJFeHRyYSBjaGVlc2UiLCB3b3JzdF90b3BwaW5ncykpICU+JQ0KICBtdXRhdGUod29yc3RfcmFuayA9IGdzdWIoIndvcnN0XzEiLCAxLCB3b3JzdF9yYW5rKSkgJT4lDQogIG11dGF0ZSh3b3JzdF9yYW5rID0gZ3N1Yigid29yc3RfMiIsIDIsIHdvcnN0X3JhbmspKSAlPiUNCiAgbXV0YXRlKHdvcnN0X3JhbmsgPSBnc3ViKCJ3b3JzdF8zIiwgMywgd29yc3RfcmFuaykpDQoNCndvcnN0X3RvcHBpbmdzJHNjb3JlIDwtIGlmZWxzZSgNCiAgd29yc3RfdG9wcGluZ3Mkd29yc3RfcmFuayA9PSAxLCAzLCAoaWZlbHNlKA0KICAgIHdvcnN0X3RvcHBpbmdzJHdvcnN0X3JhbmsgPT0gMiwgMiwgaWZlbHNlKA0KICAgICAgd29yc3RfdG9wcGluZ3Mkd29yc3RfcmFuayA9PSAzLCAxLCBOQSkpKSkNCg0Kd29yc3Rfc3VtIDwtIHdvcnN0X3RvcHBpbmdzICU+JQ0KICBncm91cF9ieSh3b3JzdF90b3BwaW5ncykgJT4lDQogIHN1bW1hcmlzZSh3b3JzdF92b3RlcyA9IG4oKSwNCiAgICAgICAgICAgIHdvcnN0X3Njb3JlID0gc3VtKHNjb3JlKSkgJT4lDQogIHJlbmFtZSh0b3BwaW5nID0gd29yc3RfdG9wcGluZ3MpICU+JQ0KICBhcnJhbmdlKGRlc2Mod29yc3Rfc2NvcmUpKQ0KDQp3b3JzdF9zdW1fbm9OQSA8LSB3b3JzdF9zdW0gJT4lDQogIGZpbHRlcih0b3BwaW5nICE9ICJOL0EiKQ0KDQpib3R0b20xMF90b3BwaW5ncyA8LSB3b3JzdF9zdW1fbm9OQSR0b3BwaW5nWzE6MTBdDQpgYGANCg0KVGhpcyB0aW1lIHdlJ2xsIGJyZWFrIHVwIHRoZSBib3R0b20gMTAgYnkgaG93IG11Y2ggdGhlIHBhcnRpY2lwYW50cyAqbGlrZSogcGl6emEuDQoNCmBgYHtyfQ0KZ2dwbG90KHN1YnNldCh3b3JzdF90b3BwaW5ncywgd29yc3RfdG9wcGluZ3MgJWluJSBib3R0b20xMF90b3BwaW5ncyksIGFlcyh4ID0gd29yc3RfdG9wcGluZ3MsIGZpbGwgPSBhcy5jaGFyYWN0ZXIocGl6emFfcmF0aW5nKSkpICsNCiAgZ2VvbV9iYXIod2lkdGggPSAwLjcpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2ZlZmVhNCIsIiNmZmRjNzYiLCAiI2QzNTA0YSIsICIjNGEyYzJjIiksIG5hbWUgPSAiSG93IG11Y2ggZG8gXG55b3UgbGlrZSBwaXp6YT9cbigxLTUgc2NhbGUpIikgKw0KICBsYWJzKHRpdGxlID0gIjEwIExlYXN0IExvdmVkIFBpenphIFRvcHBpbmdzIiwgeSA9ICJOby4gb2YgVm90ZXMiLCB4ID0gIiIpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IDIsIGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQodmp1c3QgPSAtMSwgY29sb3IgPSAiZ3JheTYwIikpDQpgYGANCg0KQW5jaG92aWVzIGFyZSBhIGxlYXN0IGZhdm9yaXRlIHRvcHBpbmcgYW1vbmcgZXZlbiB0aGUgbW9zdCBkaWUtaGFyZCBwaXp6YSBsb3ZlcnMsIGZvbGxvd2VkIGJ5IG9saXZlcywgcGluZWFwcGxlLCBhbmQgZWdncGxhbnQuIFBhcnRpY2lwYW50cyB3aG8gcmVhbGx5IGxpa2UgcGl6emEgYnV0IGFyZW4ndCB3aWxsaW5nIHRvIGNhbGwgaXQgdGhlaXIgZmF2b3JpdGUgZm9vZCAocmF0aW5nID0gNCkgZm9sbG93IGEgc2ltaWxhciBwYXR0ZXJuLg0KDQo8aHI+DQo8Yj4zLiBQaXp6YSBUb3BwaW5nIEFncmVlbWVudDwvYj4NCg0KU29tZSB0b3BwaW5ncyBzaG93ZWQgdXAgb24gYm90aCBsaXN0cyAtIGlzIGV2ZXJ5b25lIGluIGFncmVlbWVudCBhYm91dCB0aGVzZSBtb3N0IGxvdmVkIGFuZCBtb3N0IGxvYXRoZWQgdG9wcGluZ3M/IExldCdzIHNlZSEgV2UnbGwgY29tcGFyZSB0aGUgbnVtYmVyIG9mICJtb3N0IGZhdm9yaXRlIiB2b3RlcyBlYWNoIHRvcHBpbmcgcmVjZWl2ZWQgdG8gaXRzICJsZWFzdCBmYXZvcml0ZSIgdm90ZXMuIEluIHRoaXMgZ3JhcGgsIHBvaW50cyBjbG9zZXIgdG8gdGhlIGF4ZXMgYXJlIG1vcmUgYWdyZWVkLXVwb24gdG9wcGluZ3MuDQoNCmBgYHtyfQ0KYmVzdF9ubzEgPC0gYmVzdF90b3BwaW5ncyAlPiUNCiAgZmlsdGVyKGJlc3RfcmFuayA9PSAxKSAlPiUNCiAgZ3JvdXBfYnkoYmVzdF90b3BwaW5ncykgJT4lDQogIHN1bW1hcmlzZShiZXN0XzEgPSBuKCkpICU+JQ0KICByZW5hbWUodG9wcGluZyA9IGJlc3RfdG9wcGluZ3MpDQoNCnRvcHBpbmdfdm90ZXMgPC0gbWVyZ2UoYmVzdF9ubzEsIG1lcmdlKGJlc3Rfc3VtLCB3b3JzdF9zdW0sIGJ5ID0gInRvcHBpbmciLCBhbGwueCA9IFRSVUUsIGFsbC55ID0gVFJVRSksIGJ5ID0gInRvcHBpbmciLCBhbGwueCA9IFRSVUUsIGFsbC55ID0gVFJVRSkNCnRvcHBpbmdfdm90ZXNbaXMubmEodG9wcGluZ192b3RlcyldIDwtIDANCg0Kcm0oYmVzdF9ubzEpDQoNCmhlYWQodG9wcGluZ192b3RlcykNCg0KZ2dwbG90KHRvcHBpbmdfdm90ZXMsIGFlcyh4ID0gYmVzdF92b3RlcywgeSA9IHdvcnN0X3ZvdGVzKSkgKyANCiAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IGJlc3RfMSksIHNoYXBlID0gMjEsIHN0cm9rZSA9IDEuMSwgY29sb3IgPSAiI2ZmNGQ0ZCIsIGZpbGwgPSAiI2ZmNGQ0ZCIsIGFscGhhID0gMC40KSArIA0KICBnZW9tX3RleHRfcmVwZWwoYWVzKGxhYmVsID0gdG9wcGluZyksIHBvaW50LnBhZGRpbmcgPSAwLjgpICsNCiAgc2NhbGVfc2l6ZShuYW1lID0gIiMxIEZhdm9yaXRlIFxuIFZvdGVzIiwgcmFuZ2UgPSBjKDIsMTQpKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiUGl6emEgVG9wcGluZyBBZ3JlZW1lbnQiLCBzdWJ0aXRsZSA9ICJOdW1iZXIgb2YgJ0Zhdm9yaXRlJyB2cy4gJ0xlYXN0IEZhdm9yaXRlJyB2b3RlcyByZWNlaXZlZCBieSB0b3BwaW5nIiwgeCA9ICJGYXZvcml0ZSBUb3BwaW5nIFZvdGVzIiwgeSA9ICJMZWFzdCBGYXZvcml0ZSBUb3BwaW5nIFZvdGVzIikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHZqdXN0ID0gMiwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiZ3JheTYwIiksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IC0xKSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHZqdXN0ID0gMiksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMS41KSkNCmBgYA0KDQpQYXJ0aWNpcGFudHMgYXJlIG1vc3RseSBpbiBhZ3JlZW1lbnQgYWJvdXQgdGhlIGZhdm9yaXRlIChwZXBwZXJvbmksIG11c2hyb29tcywgc2F1c2FnZSkgYW5kIGxlYXN0IGZhdm9yaXRlIChhbmNob3ZpZXMsIGVnZ3BsYW50KSB0b3BwaW5ncywgYnV0IHRoZXJlIGlzIG1vcmUgZGViYXRlIGFib3V0IHRvcHBpbmdzIGxpa2UgcGluZWFwcGxlIChzdXJwcmlzZSwgc3VycHJpc2UpLCBvbGl2ZXMsIGFuZCBiZWxsIHBlcHBlcnMuDQoNCjxocj4NCjxiPjQuIEEgUmVnaW9uYWwgTG9vayBhdCBQaW5lYXBwbGU8L2I+DQoNClBpbmVhcHBsZSBhcHBlYXJzIHRvIGJlIG9uZSBvZiB0aGUgbW9yZSBkaXZpc2l2ZSB0b3BwaW5ncy4gSXMgdGhlcmUgYSByZWdpb25hbCBkaWZmZXJlbmNlIGluIGl0cyByZWNlcHRpb24/IC4uLmFuZCBjYW4gdGhpcyBjaGFydCBiZSB0cnVzdGVkIHdoZW4gdGhlIHJlc3BvbnNlcyBmcm9tIHNvbWUgb2YgdGhlc2UgcmVnaW9ucyB3YXMgc28gdGVlbnkgdGlueS4uLj8NCg0KYGBge3J9DQpnZ3Bsb3QocGl6emFfcmVnaW9uLCBhZXMoeCA9IFJlZ2lvbl9uYW1lLCBmaWxsID0gcGluZWFwcGxlX3EpKSArDQogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiLCB3aWR0aCA9IDAuMjUpICsNCiAgZ2VvbV90ZXh0KHN0YXQ9J2NvdW50JywgYWVzKGxhYmVsPS4uY291bnQuLiksIHBvc2l0aW9uID0gcG9zaXRpb25fZmlsbCh2anVzdCA9IDAuNSkpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI2ZmNzY1NyIsICIjNjY1Yzg0IiwgIiNmYmVlZDciLCAiI2ZmYmE1YSIpLCBuYW1lID0gIiIpICsNCiAgY29vcmRfZmxpcCgpICsNCiAgbGFicyh0aXRsZSA9ICJEb2VzIHBpbmVhcHBsZSBiZWxvbmcgb24gcGl6emE/Iiwgc3VidGl0bGUgPSAiUmVzcG9uc2VzIGJ5IFUuUy4gcmVnaW9uIiwgeCA9ICIiLCB5ID0gIlBlcmNlbnQgb2Ygdm90ZXMiKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQodmp1c3QgPSAyLCBmYWNlID0gImJvbGQiKSwNCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmF5NjAiKSwNCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHZqdXN0ID0gLTEsIGNvbG9yID0gImdyYXk2MCIpKQ0KYGBgDQoNCkl0IGlzIGRpc2FwcG9pbnRpbmcgdG8gZmluZCB0aGF0IG5lYXJseSA1MCUgb2YgcGFydGljaXBhbnRzIGZyb20gbW9zdCBVLlMuIHJlZ2lvbnMgaGF2ZSBzdWNoIHNpbGx5IHRhc3RlIGluIHBpenphLiBUaGUgTWlkd2VzdCBhcHBlYXJzIHRvIGhhdmUgaXRzIHZhbHVlcyBpbiB0aGUgcmlnaHQgcGxhY2UgKHRob3VnaCB0aGVyZSB3ZXJlIHZlcnkgZmV3IHJlc3BvbnNlcyBmcm9tIHRoZSByZWdpb24gW24gPSA1XSkuDQoNCjxocj4NCjxiPjUuIFBpenphLCBhbmQuLi48L2I+DQoNCkkgY29sbGVjdGVkIHNvbWUgdmVyeSBpbXBvcnRhbnQgZGF0YSByZWdhcmRpbmcgcGFydGljaXBhbnRzJyB0YXN0ZSBmb3Igb3RoZXIgcG9wdWxhciBmb29kcy4gSG93IGRvZXMgdGhlaXIgYXBhcHJlY2lhdGlvbiBmb3IgcGl6emEgY29tcGFyZSB0byB0aGVzZSBvdGhlciBlYXRzPw0KDQpgYGB7cn0NCm90aGVyX2VhdHMgPC0gcGl6emFfcmVnaW9uICU+JQ0KICBzZWxlY3QocGFydGljaXBhbnRfaWQsIFJlZ2lvbl9uYW1lLCBwaXp6YV9yYXRpbmcsIHRhY29zOnN0ZWFrKSAlPiUNCiAgZ3JvdXBfYnkoUmVnaW9uX25hbWUpICU+JQ0KICBnYXRoZXIoImVhdHMiLCAicmF0aW5nIiwgdGFjb3M6c3RlYWspDQoNCm90aGVyX2VhdHMkZWF0cyA8LSBzdHJfdG9fdGl0bGUob3RoZXJfZWF0cyRlYXRzKQ0KYGBgDQoNCkkgaGFkIGdyYW5kIHZpc2lvbnMgZm9yIHRoZSB2aXN1YWxpemF0aW9uIG9mIHRoaXMgZGF0YSwgYnV0IHRoZXkgaGF2ZSBiZWVuIHJlZHVjZWQgdG8gdGhpcyBqaXR0ZXIgcGxvdDoNCg0KYGBge3J9DQpnZ3Bsb3Qob3RoZXJfZWF0cywgYWVzKHggPSByYXRpbmcsIHkgPSBwaXp6YV9yYXRpbmcsIGNvbG9yID0gUmVnaW9uX25hbWUsIGZpbGwgPSBSZWdpb25fbmFtZSkpICsNCiAgZmFjZXRfd3JhcCguIH4gZWF0cykgKw0KICBnZW9tX2ppdHRlcih3aWR0aCA9IDAuMywgaGVpZ2h0ID0gMC4zLCBzZWVkID0gTlVMTCwgc2l6ZSA9IDEuNSwgc2hhcGUgPSAyMSwgYWxwaGEgPSAwLjc1KSArDQogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCIjMTgyQzYxIiwiIzFCOUNGQyIsIiM1NUU2QzEiLCIjRkM0MjdCIiwiI0VBQjU0MyIpLCBuYW1lID0gIlJlZ2lvbiIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzE4MkM2MSIsIiMxQjlDRkMiLCIjNTVFNkMxIiwiI0ZDNDI3QiIsIiNFQUI1NDMiKSwgbmFtZSA9ICJSZWdpb24iKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnModGl0bGUgPSAiSG93IG11Y2ggZG8geW91IGxpa2UgX19fX18/Iiwgc3VidGl0bGUgPSAiUGFydGljaXBhbnRzJyByYXRpbmdzIG9mIHBpenphIHZzLiByYXRpbmdzIG9mIG90aGVyIGVhdHMiLCB4ID0gIigxID0gbG93IHJhdGluZywgNSA9IGhpZ2ggcmF0aW5nKSIsIHkgPSAiUGl6emEgUmF0aW5nIikgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHZqdXN0ID0gMiwgZmFjZSA9ICJib2xkIiksDQogICAgICAgIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiZ3JheTYwIiksDQogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMS41KSwNCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHZqdXN0ID0gMyksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IC0yLCBjb2xvciA9ICJncmF5NjAiKSwNCiAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgICAgICBwYW5lbC5tYXJnaW4gPSB1bml0KDEuNSwgImxpbmVzIikpDQpgYGANCg0KQSBmZXcgb2JzZXJ2YXRpb25zIGNhbiBiZSBkcmF3biBmcm9tIHRoaXMgY29uZmV0dGkgaGVyZToNCjx1bD4NCjxsaT5UYWNvcyBhcmUgdGhlIG1vc3QgYmVsb3ZlZCBvZiB0aGVzZSBmb29kcywgZmFyIG1vcmUgcGFydGljaXBhbnRzIGdhdmUgdGFjb3MgYSA1IHRoYW4gdGhleSBkaWQgcGl6emEsIGFuZCBubyBvbmUgZGFyZXMgc2F5IHRoZXkgaGF0ZSB0YWNvcyAocmF0aW5nID0gMSkuPC9saT4NCjxsaT5TdXNoaSBpcyB0aGUgbW9zdCBwb2xhcml6aW5nIGFtb25nIHRoZSBvdGhlciBlYXRzLCB3aXRoIGEgbG90IG9mIHBpenphIGxvdmVycyAocmF0aW5nID0gNSkgZ2l2aW5nIGl0IGEgMSE8L2xpPg0KPGxpPlBlb3BsZSBhcmVuJ3QgYXMgd2lsZCBhYm91dCBzdGVhayBhcyBJIHRob3VnaHQuIFRoYXQncyBraW5kIG9mIG5pY2UhPC9saT4NCjxsaT5QZW9wbGUgYXJlbid0IGFzIHdpbGQgYWJvdXQgYmFnZWxzIGFzIEkgdGhvdWdodC4gSSdtIGtpbmQgb2YgYm90aGVyZWQ/PC9saT4NCjxsaT5UaGVyZSBhcmUgemVybyByZWdpb25hbCBwYXR0ZXJucyB0aGF0IEkgY2FuIG1ha2Ugb3V0IGZyb20gdGhpcyBtZXNzLjwvbGk+DQo8L3VsPiANCjxicj4NCjxicj4=