Questions
- Which project categories have viewers that give the highest average donation?
- Per category, what’s the success to failure rate/ratio of all projects?
- What Kickstarter categories have been most popular over time?
library(tidyverse)
library(lubridate)
library(scales)
library(MASS)
library(viridis)
# Use progress=FALSE to remove the progress bar!
ks2018 <- read_csv("./data/ks-2018.csv",col_names=TRUE, progress=FALSE)
Parsed with column specification:
cols(
ID = col_integer(),
name = col_character(),
category = col_character(),
main_category = col_character(),
currency = col_character(),
deadline = col_date(format = ""),
goal = col_double(),
launched = col_datetime(format = ""),
pledged = col_double(),
state = col_character(),
backers = col_integer(),
country = col_character(),
`usd pledged` = col_double(),
usd_pledged_real = col_double(),
usd_goal_real = col_double()
)
# Get rid of spaces in column names, replace with underscore
colnames(ks2018) <- gsub(" ", "_",colnames(ks2018))
Which project categories have viewers that give the highest average donation?
Technology
# Roll up dataset into mean pledge per backer per category
pledgeByCat <- ks2018 %>%
group_by(main_category) %>%
summarize(
pledged=sum(usd_pledged, na.rm = TRUE),
backers=sum(backers, na.rm = TRUE),
avg=pledged/backers) %>%
arrange(desc(avg))
# Change main_category into a factor so ggplot will honor the sort order
pledgeByCat$main_category <- factor(pledgeByCat$main_category, levels=pledgeByCat$main_category)
# Plot bar chart of mean pledges
pledgeByCatPlot <- ggplot(pledgeByCat, aes(x=main_category,y=avg,fill=avg)) + geom_col() + labs(title="Avg Pledge By Category Per Backer", x="Category",y="Avg Pledge Per Backer") + theme(axis.text.x=element_text(angle=90),legend.position = "null")
print(pledgeByCatPlot)

Per category, whats the success to failure rate/ratio of all projects?
Dance has the highest success rate, but a low number of projects overall
# Roll up dataset
successPerCat <- ks2018 %>%
group_by(main_category) %>%
summarize(
fails = sum(state == "failed", na.rm = TRUE),
success = sum(state == "successful", na.rm = TRUE),
success_rate = success / (success + fails) * 100
) %>%
arrange(desc(success_rate))
# Change main_category into a factor so ggplot will honor the sort order
successPerCat$main_category <- factor(successPerCat$main_category, levels=successPerCat$main_category)
# Plot bar chart
successPerCatPlot <- ggplot(successPerCat, aes(x=main_category,y=success_rate,fill=success_rate)) + geom_col() + labs(title="Percent Success Per Category", x="Category",y="Percentage Successes") + theme(axis.text.x=element_text(angle=90),legend.position = "null")
print(successPerCatPlot)
failTotals <- ggplot(successPerCat, aes(x=main_category,y=fails)) + geom_col()
successAndFails <- failTotals + geom_col(position="dodge", aes(y=success,fill=factor(success))) + theme(axis.text.x=element_text(angle=90),legend.position = "null")
print(successAndFails)
successPerCat <- ks2018 %>%
filter(state %in% c("successful", "failed")) %>%
group_by(main_category, state) %>%
summarize(category_count=n()) %>%
mutate(category_percent=category_count/sum(category_count)) %>%
arrange(desc(state), category_percent)
# Change main_category into a factor so ggplot will honor the sort order
successPerCat$main_category <- factor(successPerCat$main_category,
levels=unique(successPerCat$main_category))
print(successPerCat$main_category)
successTotals <- ggplot(successPerCat, aes(x=main_category, y=category_percent, fill=state)) + geom_col()
successAndFails <- successTotals +
geom_col(position="fill") +
scale_fill_discrete(breaks=c("successful", "failed")) +
scale_y_continuous(labels=scales::percent) +
theme(axis.text.x=element_text(angle=90),legend.position = "null")
print(successAndFails)
Trends in kickstarter categories over time
Hypothesis: kickstarter began with mainly tech projects and then expanded over time
# Roll up dataset to number of projects per category per year
catOverTime <- ks2018 %>%
mutate(year=year(deadline)) %>%
group_by(main_category,year) %>%
summarize(cat_total=n()) %>%
filter(year < 2018) %>%
arrange(cat_total)
# Line chart of projects per category per year
catOverTimePlot <- ggplot(
catOverTime,
aes(x=year,y=cat_total,colour=main_category)) + geom_line()
print(catOverTimePlot)

# Unfortunately this isn't super readable?
Retrying the above data with a modified dplyr filter and a density plot, to try and get a better visual of the data
Is there a way to reduce the number of distinct categories so we can only view the top 10% most popular categories?
# Roll up dataset to number of projects per category per year
# Remove summarize because that frontloads the process that the density plot wants to do
# which is counting the number of events
catOverTime2 <- ks2018 %>%
mutate(year=year(deadline)) %>%
group_by(main_category,deadline) %>%
filter(year < 2018) %>%
arrange(deadline)
# Density plot of projects
# histogram - plotting frequency of an event in the y axis, versus the scale/groups in the x axis
catDensity <- ggplot(
catOverTime2,
aes(x=deadline,fill=main_category,colour=main_category)) + geom_density(alpha = 0.1)
print(catDensity)

Trying a heatmap to visualize the trends in categories
According to our heat map, art projects like film/video and music were most popular. Games and technology did not become popular categories until later.
# Redo rolling up dataset to include deadline vector
catHeat <- ks2018 %>%
mutate(year=year(deadline)) %>%
group_by(main_category,year) %>%
summarize(
cat_total=n(),
deadline=deadline[1]) %>%
filter(year < 2018) %>%
arrange(year)
# Heatmap of categories over time
catHeatPlot <- ggplot(
catHeat,
aes(x=year,y=main_category)) +
geom_tile(aes(fill=cat_total)) +
scale_fill_gradient(low = 'white', high = 'red') +
scale_x_continuous(breaks = function(x) unique(floor(pretty(x)))) +
labs(title="Most Popular Kickstarter Categories Per Year", x="Year",y="Main Category")
print(catHeatPlot)

Notes
summarize will strip out anything that isnt in the group by, mutation, or in the summarize itself so you need to reference rows in the summarize if you want to include them but they’re not in group by or mutate
LS0tDQp0aXRsZTogIktpY2tzdGFydGVyIERhdGEiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpodHRwczovL3d3dy5rYWdnbGUuY29tL2tlbWljYWwva2lja3N0YXJ0ZXItcHJvamVjdHMgDQoNCiMgUXVlc3Rpb25zDQoNCjEuIFdoaWNoIHByb2plY3QgY2F0ZWdvcmllcyBoYXZlIHZpZXdlcnMgdGhhdCBnaXZlIHRoZSBoaWdoZXN0IGF2ZXJhZ2UgZG9uYXRpb24/DQoyLiBQZXIgY2F0ZWdvcnksIHdoYXQncyB0aGUgc3VjY2VzcyB0byBmYWlsdXJlIHJhdGUvcmF0aW8gb2YgYWxsIHByb2plY3RzPw0KMy4gV2hhdCBLaWNrc3RhcnRlciBjYXRlZ29yaWVzIGhhdmUgYmVlbiBtb3N0IHBvcHVsYXIgb3ZlciB0aW1lPw0KDQpgYGB7ciBJbXBvcnQgTGlicmFyaWVzfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShNQVNTKQ0KbGlicmFyeSh2aXJpZGlzKQ0KYGBgDQoNCmBgYHtyIEltcG9ydCBEYXRhfQ0KDQojIFVzZSBwcm9ncmVzcz1GQUxTRSB0byByZW1vdmUgdGhlIHByb2dyZXNzIGJhciENCg0Ka3MyMDE4IDwtIHJlYWRfY3N2KCIuL2RhdGEva3MtMjAxOC5jc3YiLGNvbF9uYW1lcz1UUlVFLCBwcm9ncmVzcz1GQUxTRSkgDQpgYGANCg0KYGBge3IgRGF0YSBDbGVhbmluZ30NCiMgR2V0IHJpZCBvZiBzcGFjZXMgaW4gY29sdW1uIG5hbWVzLCByZXBsYWNlIHdpdGggdW5kZXJzY29yZQ0KY29sbmFtZXMoa3MyMDE4KSA8LSBnc3ViKCIgIiwgIl8iLGNvbG5hbWVzKGtzMjAxOCkpDQpgYGANCg0KIyMgV2hpY2ggcHJvamVjdCBjYXRlZ29yaWVzIGhhdmUgdmlld2VycyB0aGF0IGdpdmUgdGhlIGhpZ2hlc3QgYXZlcmFnZSBkb25hdGlvbj8NCj4gVGVjaG5vbG9neQ0KDQpgYGB7ciBIaWdoZXN0IEF2ZXJhZ2UgRG9uYXRpb24gUGVyIFByb2plY3QgQ2F0ZWdvcnl9DQoNCiMgUm9sbCB1cCBkYXRhc2V0IGludG8gbWVhbiBwbGVkZ2UgcGVyIGJhY2tlciBwZXIgY2F0ZWdvcnkNCnBsZWRnZUJ5Q2F0IDwtIGtzMjAxOCAlPiUNCiAgICBncm91cF9ieShtYWluX2NhdGVnb3J5KSAlPiUNCiAgICBzdW1tYXJpemUoDQogICAgICAgIHBsZWRnZWQ9c3VtKHVzZF9wbGVkZ2VkLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICBiYWNrZXJzPXN1bShiYWNrZXJzLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICBhdmc9cGxlZGdlZC9iYWNrZXJzKSAlPiUNCiAgICBhcnJhbmdlKGRlc2MoYXZnKSkNCg0KIyBDaGFuZ2UgbWFpbl9jYXRlZ29yeSBpbnRvIGEgZmFjdG9yIHNvIGdncGxvdCB3aWxsIGhvbm9yIHRoZSBzb3J0IG9yZGVyDQpwbGVkZ2VCeUNhdCRtYWluX2NhdGVnb3J5IDwtIGZhY3RvcihwbGVkZ2VCeUNhdCRtYWluX2NhdGVnb3J5LCBsZXZlbHM9cGxlZGdlQnlDYXQkbWFpbl9jYXRlZ29yeSkNCg0KIyBQbG90IGJhciBjaGFydCBvZiBtZWFuIHBsZWRnZXMNCnBsZWRnZUJ5Q2F0UGxvdCA8LSBnZ3Bsb3QocGxlZGdlQnlDYXQsIGFlcyh4PW1haW5fY2F0ZWdvcnkseT1hdmcsZmlsbD1hdmcpKSArIGdlb21fY29sKCkgKyBsYWJzKHRpdGxlPSJBdmcgUGxlZGdlIEJ5IENhdGVnb3J5IFBlciBCYWNrZXIiLCB4PSJDYXRlZ29yeSIseT0iQXZnIFBsZWRnZSBQZXIgQmFja2VyIikgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTApLGxlZ2VuZC5wb3NpdGlvbiA9ICJudWxsIikNCg0KcHJpbnQocGxlZGdlQnlDYXRQbG90KQ0KDQpgYGANCg0KIyMgUGVyIGNhdGVnb3J5LCB3aGF0cyB0aGUgc3VjY2VzcyB0byBmYWlsdXJlIHJhdGUvcmF0aW8gb2YgYWxsIHByb2plY3RzPw0KPiBEYW5jZSBoYXMgdGhlIGhpZ2hlc3Qgc3VjY2VzcyByYXRlLCBidXQgYSBsb3cgbnVtYmVyIG9mIHByb2plY3RzIG92ZXJhbGwNCg0KYGBge3IgU3VjY2Vzcy9GYWlsdXJlIFJhdGlvIG9mIEFsbCBQcm9qZWN0cywgUGVyIENhdGVnb3J5fQ0KDQojIFJvbGwgdXAgZGF0YXNldA0Kc3VjY2Vzc1BlckNhdCA8LSBrczIwMTggJT4lDQogICAgZ3JvdXBfYnkobWFpbl9jYXRlZ29yeSkgJT4lDQogICAgc3VtbWFyaXplKA0KICAgICAgICBmYWlscyA9IHN1bShzdGF0ZSA9PSAiZmFpbGVkIiwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgc3VjY2VzcyA9IHN1bShzdGF0ZSA9PSAic3VjY2Vzc2Z1bCIsIG5hLnJtID0gVFJVRSksDQogICAgICAgIHN1Y2Nlc3NfcmF0ZSA9IHN1Y2Nlc3MgLyAoc3VjY2VzcyArIGZhaWxzKSAqIDEwMA0KICAgICkgJT4lDQogICAgYXJyYW5nZShkZXNjKHN1Y2Nlc3NfcmF0ZSkpDQoNCiMgQ2hhbmdlIG1haW5fY2F0ZWdvcnkgaW50byBhIGZhY3RvciBzbyBnZ3Bsb3Qgd2lsbCBob25vciB0aGUgc29ydCBvcmRlcg0Kc3VjY2Vzc1BlckNhdCRtYWluX2NhdGVnb3J5IDwtIGZhY3RvcihzdWNjZXNzUGVyQ2F0JG1haW5fY2F0ZWdvcnksIGxldmVscz1zdWNjZXNzUGVyQ2F0JG1haW5fY2F0ZWdvcnkpDQoNCiMgUGxvdCBiYXIgY2hhcnQNCnN1Y2Nlc3NQZXJDYXRQbG90IDwtIGdncGxvdChzdWNjZXNzUGVyQ2F0LCBhZXMoeD1tYWluX2NhdGVnb3J5LHk9c3VjY2Vzc19yYXRlLGZpbGw9c3VjY2Vzc19yYXRlKSkgKyBnZW9tX2NvbCgpICsgbGFicyh0aXRsZT0iUGVyY2VudCBTdWNjZXNzIFBlciBDYXRlZ29yeSIsIHg9IkNhdGVnb3J5Iix5PSJQZXJjZW50YWdlIFN1Y2Nlc3NlcyIpICsgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwKSxsZWdlbmQucG9zaXRpb24gPSAibnVsbCIpDQoNCnByaW50KHN1Y2Nlc3NQZXJDYXRQbG90KQ0KDQpmYWlsVG90YWxzIDwtIGdncGxvdChzdWNjZXNzUGVyQ2F0LCBhZXMoeD1tYWluX2NhdGVnb3J5LHk9ZmFpbHMpKSArIGdlb21fY29sKCkNCg0Kc3VjY2Vzc0FuZEZhaWxzIDwtIGZhaWxUb3RhbHMgKyBnZW9tX2NvbChwb3NpdGlvbj0iZG9kZ2UiLCBhZXMoeT1zdWNjZXNzLGZpbGw9ZmFjdG9yKHN1Y2Nlc3MpKSkgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTApLGxlZ2VuZC5wb3NpdGlvbiA9ICJudWxsIikNCg0KcHJpbnQoc3VjY2Vzc0FuZEZhaWxzKQ0KDQpgYGANCg0KYGBge3IgU3VjY2Vzcy9GYWlsdXJlIFJhdGlvIG9mIEFsbCBQcm9qZWN0cywgUGVyIENhdGVnb3J5IC0gc2NhbGEgdmVyfQ0KDQpzdWNjZXNzUGVyQ2F0IDwtIGtzMjAxOCAlPiUNCiAgZmlsdGVyKHN0YXRlICVpbiUgYygic3VjY2Vzc2Z1bCIsICJmYWlsZWQiKSkgJT4lDQogIGdyb3VwX2J5KG1haW5fY2F0ZWdvcnksIHN0YXRlKSAlPiUNCiAgc3VtbWFyaXplKGNhdGVnb3J5X2NvdW50PW4oKSkgJT4lDQogIG11dGF0ZShjYXRlZ29yeV9wZXJjZW50PWNhdGVnb3J5X2NvdW50L3N1bShjYXRlZ29yeV9jb3VudCkpICU+JQ0KICBhcnJhbmdlKGRlc2Moc3RhdGUpLCBjYXRlZ29yeV9wZXJjZW50KQ0KDQojIENoYW5nZSBtYWluX2NhdGVnb3J5IGludG8gYSBmYWN0b3Igc28gZ2dwbG90IHdpbGwgaG9ub3IgdGhlIHNvcnQgb3JkZXINCnN1Y2Nlc3NQZXJDYXQkbWFpbl9jYXRlZ29yeSA8LSBmYWN0b3Ioc3VjY2Vzc1BlckNhdCRtYWluX2NhdGVnb3J5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9dW5pcXVlKHN1Y2Nlc3NQZXJDYXQkbWFpbl9jYXRlZ29yeSkpDQoNCnByaW50KHN1Y2Nlc3NQZXJDYXQkbWFpbl9jYXRlZ29yeSkNCg0Kc3VjY2Vzc1RvdGFscyA8LSBnZ3Bsb3Qoc3VjY2Vzc1BlckNhdCwgYWVzKHg9bWFpbl9jYXRlZ29yeSwgeT1jYXRlZ29yeV9wZXJjZW50LCBmaWxsPXN0YXRlKSkgKyBnZW9tX2NvbCgpDQpzdWNjZXNzQW5kRmFpbHMgPC0gc3VjY2Vzc1RvdGFscyArIA0KICBnZW9tX2NvbChwb3NpdGlvbj0iZmlsbCIpICsgDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUoYnJlYWtzPWMoInN1Y2Nlc3NmdWwiLCAiZmFpbGVkIikpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArDQogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT05MCksbGVnZW5kLnBvc2l0aW9uID0gIm51bGwiKQ0KDQpwcmludChzdWNjZXNzQW5kRmFpbHMpDQpgYGANCg0KIyMgVHJlbmRzIGluIGtpY2tzdGFydGVyIGNhdGVnb3JpZXMgb3ZlciB0aW1lDQoNCj4gSHlwb3RoZXNpczoga2lja3N0YXJ0ZXIgYmVnYW4gd2l0aCBtYWlubHkgdGVjaCBwcm9qZWN0cyBhbmQgdGhlbiBleHBhbmRlZCBvdmVyIHRpbWUNCg0KYGBge3IgTGluZSBQbG90fQ0KDQojIFJvbGwgdXAgZGF0YXNldCB0byBudW1iZXIgb2YgcHJvamVjdHMgcGVyIGNhdGVnb3J5IHBlciB5ZWFyDQpjYXRPdmVyVGltZSA8LSBrczIwMTggJT4lDQogICAgbXV0YXRlKHllYXI9eWVhcihkZWFkbGluZSkpICU+JQ0KICAgIGdyb3VwX2J5KG1haW5fY2F0ZWdvcnkseWVhcikgJT4lDQogICAgc3VtbWFyaXplKGNhdF90b3RhbD1uKCkpICU+JQ0KICAgIGZpbHRlcih5ZWFyIDwgMjAxOCkgJT4lDQogICAgYXJyYW5nZShjYXRfdG90YWwpDQoNCiMgTGluZSBjaGFydCBvZiBwcm9qZWN0cyBwZXIgY2F0ZWdvcnkgcGVyIHllYXINCmNhdE92ZXJUaW1lUGxvdCA8LSBnZ3Bsb3QoDQogICAgY2F0T3ZlclRpbWUsIA0KICAgIGFlcyh4PXllYXIseT1jYXRfdG90YWwsY29sb3VyPW1haW5fY2F0ZWdvcnkpKSArIGdlb21fbGluZSgpDQoNCnByaW50KGNhdE92ZXJUaW1lUGxvdCkNCg0KIyBVbmZvcnR1bmF0ZWx5IHRoaXMgaXNuJ3Qgc3VwZXIgcmVhZGFibGU/DQpgYGANCiMjIFJldHJ5aW5nIHRoZSBhYm92ZSBkYXRhIHdpdGggYSBtb2RpZmllZCBkcGx5ciBmaWx0ZXIgYW5kIGEgZGVuc2l0eSBwbG90LCB0byB0cnkgYW5kIGdldCBhIGJldHRlciB2aXN1YWwgb2YgdGhlIGRhdGENCg0KPiBJcyB0aGVyZSBhIHdheSB0byByZWR1Y2UgdGhlIG51bWJlciBvZiBkaXN0aW5jdCBjYXRlZ29yaWVzIHNvIHdlIGNhbiBvbmx5IHZpZXcgdGhlIHRvcCAxMCUgbW9zdCBwb3B1bGFyIGNhdGVnb3JpZXM/DQoNCmBgYHtyIERlbnNpdHkgTWFwfQ0KDQojIFJvbGwgdXAgZGF0YXNldCB0byBudW1iZXIgb2YgcHJvamVjdHMgcGVyIGNhdGVnb3J5IHBlciB5ZWFyDQojIFJlbW92ZSBzdW1tYXJpemUgYmVjYXVzZSB0aGF0IGZyb250bG9hZHMgdGhlIHByb2Nlc3MgdGhhdCB0aGUgZGVuc2l0eSBwbG90IHdhbnRzIHRvIGRvDQojIHdoaWNoIGlzIGNvdW50aW5nIHRoZSBudW1iZXIgb2YgZXZlbnRzDQpjYXRPdmVyVGltZTIgPC0ga3MyMDE4ICU+JQ0KICAgIG11dGF0ZSh5ZWFyPXllYXIoZGVhZGxpbmUpKSAlPiUNCiAgICBncm91cF9ieShtYWluX2NhdGVnb3J5LGRlYWRsaW5lKSAlPiUNCiAgICBmaWx0ZXIoeWVhciA8IDIwMTgpICU+JQ0KICAgIGFycmFuZ2UoZGVhZGxpbmUpDQoNCiMgRGVuc2l0eSBwbG90IG9mIHByb2plY3RzDQojIGhpc3RvZ3JhbSAtIHBsb3R0aW5nIGZyZXF1ZW5jeSBvZiBhbiBldmVudCBpbiB0aGUgeSBheGlzLCB2ZXJzdXMgdGhlIHNjYWxlL2dyb3VwcyBpbiB0aGUgeCBheGlzDQpjYXREZW5zaXR5IDwtIGdncGxvdCgNCiAgICBjYXRPdmVyVGltZTIsDQogICAgYWVzKHg9ZGVhZGxpbmUsZmlsbD1tYWluX2NhdGVnb3J5LGNvbG91cj1tYWluX2NhdGVnb3J5KSkgKyBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjEpDQoNCnByaW50KGNhdERlbnNpdHkpDQpgYGANCg0KIyMgVHJ5aW5nIGEgaGVhdG1hcCB0byB2aXN1YWxpemUgdGhlIHRyZW5kcyBpbiBjYXRlZ29yaWVzDQoNCj4gQWNjb3JkaW5nIHRvIG91ciBoZWF0IG1hcCwgYXJ0IHByb2plY3RzIGxpa2UgZmlsbS92aWRlbyBhbmQgbXVzaWMgd2VyZSBtb3N0IHBvcHVsYXIuIEdhbWVzIGFuZCB0ZWNobm9sb2d5IGRpZCBub3QgYmVjb21lIHBvcHVsYXIgY2F0ZWdvcmllcyB1bnRpbCBsYXRlci4NCg0KYGBge3IgSGVhdG1hcH0NCg0KIyBSZWRvIHJvbGxpbmcgdXAgZGF0YXNldCB0byBpbmNsdWRlIGRlYWRsaW5lIHZlY3Rvcg0KY2F0SGVhdCA8LSBrczIwMTggJT4lDQogICAgbXV0YXRlKHllYXI9eWVhcihkZWFkbGluZSkpICU+JQ0KICAgIGdyb3VwX2J5KG1haW5fY2F0ZWdvcnkseWVhcikgJT4lDQogICAgc3VtbWFyaXplKA0KICAgICAgICBjYXRfdG90YWw9bigpLCANCiAgICAgICAgZGVhZGxpbmU9ZGVhZGxpbmVbMV0pICU+JQ0KICAgIGZpbHRlcih5ZWFyIDwgMjAxOCkgJT4lDQogICAgYXJyYW5nZSh5ZWFyKQ0KDQojIEhlYXRtYXAgb2YgY2F0ZWdvcmllcyBvdmVyIHRpbWUNCmNhdEhlYXRQbG90IDwtIGdncGxvdCgNCiAgICBjYXRIZWF0LCANCiAgICBhZXMoeD15ZWFyLHk9bWFpbl9jYXRlZ29yeSkpICsgDQogICAgZ2VvbV90aWxlKGFlcyhmaWxsPWNhdF90b3RhbCkpICsgDQogICAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAnd2hpdGUnLCBoaWdoID0gJ3JlZCcpICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gZnVuY3Rpb24oeCkgdW5pcXVlKGZsb29yKHByZXR0eSh4KSkpKSArIA0KICAgIGxhYnModGl0bGU9Ik1vc3QgUG9wdWxhciBLaWNrc3RhcnRlciBDYXRlZ29yaWVzIFBlciBZZWFyIiwgeD0iWWVhciIseT0iTWFpbiBDYXRlZ29yeSIpDQoNCnByaW50KGNhdEhlYXRQbG90KQ0KDQpgYGANCg0KIyMgTm90ZXMNCj4gc3VtbWFyaXplIHdpbGwgc3RyaXAgb3V0IGFueXRoaW5nIHRoYXQgaXNudCBpbiB0aGUgZ3JvdXAgYnksIG11dGF0aW9uLCBvciBpbiB0aGUgc3VtbWFyaXplIGl0c2VsZg0KPiBzbyB5b3UgbmVlZCB0byByZWZlcmVuY2Ugcm93cyBpbiB0aGUgc3VtbWFyaXplIGlmIHlvdSB3YW50IHRvIGluY2x1ZGUgdGhlbSBidXQgdGhleSdyZSBub3QgaW4gZ3JvdXAgYnkgb3IgbXV0YXRlDQoNCg0KIyMgSGFzIGtpY2tzdGFydGVyIHBlYWtlZCBpbiBpdHMgcG9wdWxhcml0eSBhcyBhIGNyb3dkZnVuZGluZyBwbGF0Zm9ybT8gDQo+IFRoZXJlIHdhcyBhIHBlYWsgaW4gS2lja3N0YXJ0ZXIgcG9wdWxhcml0eSBpbiAyMDE1LCBhbmQgaXRzIHBvcHVsYXJpdHkgaGFzIGRlY2xpbmVkIHNpbmNlIHRoZW4NCg0KDQpgYGB7ciBTY2F0dGVycGxvdH0NCg0KIyBEZWZpbmUgZGVuc2l0eSBmdW5jdGlvbg0KZ2V0X2RlbnNpdHkgPC0gZnVuY3Rpb24oeCwgeSwgbiA9IDEwMCkgew0KICBkZW5zIDwtIE1BU1M6OmtkZTJkKHggPSB4LCB5ID0geSwgbiA9IG4pDQogIGl4IDwtIGZpbmRJbnRlcnZhbCh4LCBkZW5zJHgpDQogIGl5IDwtIGZpbmRJbnRlcnZhbCh5LCBkZW5zJHkpDQogIGlpIDwtIGNiaW5kKGl4LCBpeSkNCiAgcmV0dXJuKGRlbnMkeltpaV0pDQp9DQoNCiMgRnJlcXVlbmN5IG9mIHByb2plY3RzIHkgYXhpcywgeCBheGlzIG92ZXIgdGltZQ0KcG9wT3ZlclRpbWUgPC0ga3MyMDE4ICU+JQ0KICAgIGdyb3VwX2J5KGRlYWRsaW5lKSAlPiUNCiAgICBzdW1tYXJpemUoY291bnQ9bigpKSAlPiUNCiAgICBtdXRhdGUoZGVuc2l0eT1nZXRfZGVuc2l0eShhcy5pbnRlZ2VyKGRlYWRsaW5lKSwgY291bnQpKQ0KDQojIFNjYXR0ZXJwbG90IHdpdGggYSB0cmVuZCBsaW5lDQpwb3BPdmVyVGltZVBsb3QgPC0gZ2dwbG90KHBvcE92ZXJUaW1lLCBhZXMoeD1kZWFkbGluZSx5PWNvdW50LGNvbG9yPWRlbnNpdHkpKSArDQogICAgZ2VvbV9wb2ludCgpICsNCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgY29sb3I9IkRhcmsgQmx1ZSIpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwgNDAwKSkgKyAjIFJlbW92ZSB2YWx1ZXMgb3ZlciA1MDANCiAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwNCiAgICAgICAgICAgICAgICAgbGFiZWxzPWRhdGVfZm9ybWF0KCIlWSIpLA0KICAgICAgICAgICAgICAgICBsaW1pdHMgPSBhcy5EYXRlKGMoJzIwMDktMDEtMDEnLCcyMDE4LTAxLTAxJykpKSArDQogICAgbGFicyh0aXRsZT0iRnJlcXVlbmN5IG9mIEtpY2tzdGFydGVyIFByb2plY3RzIG92ZXIgVGltZSIpICsNCiAgICBzY2FsZV9jb2xvcl92aXJpZGlzKCkgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpDQoNCnByaW50KHBvcE92ZXJUaW1lUGxvdCkNCmBgYA0KDQo=