https://www.kaggle.com/kemical/kickstarter-projects

Questions

  1. Which project categories have viewers that give the highest average donation?
  2. Per category, what’s the success to failure rate/ratio of all projects?
  3. 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)

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)

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

Has kickstarter peaked in its popularity as a crowdfunding platform?

There was a peak in Kickstarter popularity in 2015, and its popularity has declined since then

# Define density function
get_density <- function(x, y, n = 100) {
  dens <- MASS::kde2d(x = x, y = y, n = n)
  ix <- findInterval(x, dens$x)
  iy <- findInterval(y, dens$y)
  ii <- cbind(ix, iy)
  return(dens$z[ii])
}
# Frequency of projects y axis, x axis over time
popOverTime <- ks2018 %>%
    group_by(deadline) %>%
    summarize(count=n()) %>%
    mutate(density=get_density(as.integer(deadline), count))
# Scatterplot with a trend line
popOverTimePlot <- ggplot(popOverTime, aes(x=deadline,y=count,color=density)) +
    geom_point() +
    geom_smooth(method="loess", color="Dark Blue") +
    scale_y_continuous(limits=c(0, 400)) + # Remove values over 500
    scale_x_date(date_breaks = "1 year",
                 labels=date_format("%Y"),
                 limits = as.Date(c('2009-01-01','2018-01-01'))) +
    labs(title="Frequency of Kickstarter Projects over Time") +
    scale_color_viridis() +
    theme(legend.position="none")
print(popOverTimePlot)

LS0tDQp0aXRsZTogIktpY2tzdGFydGVyIERhdGEiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpodHRwczovL3d3dy5rYWdnbGUuY29tL2tlbWljYWwva2lja3N0YXJ0ZXItcHJvamVjdHMgDQoNCiMgUXVlc3Rpb25zDQoNCjEuIFdoaWNoIHByb2plY3QgY2F0ZWdvcmllcyBoYXZlIHZpZXdlcnMgdGhhdCBnaXZlIHRoZSBoaWdoZXN0IGF2ZXJhZ2UgZG9uYXRpb24/DQoyLiBQZXIgY2F0ZWdvcnksIHdoYXQncyB0aGUgc3VjY2VzcyB0byBmYWlsdXJlIHJhdGUvcmF0aW8gb2YgYWxsIHByb2plY3RzPw0KMy4gV2hhdCBLaWNrc3RhcnRlciBjYXRlZ29yaWVzIGhhdmUgYmVlbiBtb3N0IHBvcHVsYXIgb3ZlciB0aW1lPw0KDQpgYGB7ciBJbXBvcnQgTGlicmFyaWVzfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShNQVNTKQ0KbGlicmFyeSh2aXJpZGlzKQ0KYGBgDQoNCmBgYHtyIEltcG9ydCBEYXRhfQ0KDQojIFVzZSBwcm9ncmVzcz1GQUxTRSB0byByZW1vdmUgdGhlIHByb2dyZXNzIGJhciENCg0Ka3MyMDE4IDwtIHJlYWRfY3N2KCIuL2RhdGEva3MtMjAxOC5jc3YiLGNvbF9uYW1lcz1UUlVFLCBwcm9ncmVzcz1GQUxTRSkgDQpgYGANCg0KYGBge3IgRGF0YSBDbGVhbmluZ30NCiMgR2V0IHJpZCBvZiBzcGFjZXMgaW4gY29sdW1uIG5hbWVzLCByZXBsYWNlIHdpdGggdW5kZXJzY29yZQ0KY29sbmFtZXMoa3MyMDE4KSA8LSBnc3ViKCIgIiwgIl8iLGNvbG5hbWVzKGtzMjAxOCkpDQpgYGANCg0KIyMgV2hpY2ggcHJvamVjdCBjYXRlZ29yaWVzIGhhdmUgdmlld2VycyB0aGF0IGdpdmUgdGhlIGhpZ2hlc3QgYXZlcmFnZSBkb25hdGlvbj8NCj4gVGVjaG5vbG9neQ0KDQpgYGB7ciBIaWdoZXN0IEF2ZXJhZ2UgRG9uYXRpb24gUGVyIFByb2plY3QgQ2F0ZWdvcnl9DQoNCiMgUm9sbCB1cCBkYXRhc2V0IGludG8gbWVhbiBwbGVkZ2UgcGVyIGJhY2tlciBwZXIgY2F0ZWdvcnkNCnBsZWRnZUJ5Q2F0IDwtIGtzMjAxOCAlPiUNCiAgICBncm91cF9ieShtYWluX2NhdGVnb3J5KSAlPiUNCiAgICBzdW1tYXJpemUoDQogICAgICAgIHBsZWRnZWQ9c3VtKHVzZF9wbGVkZ2VkLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICBiYWNrZXJzPXN1bShiYWNrZXJzLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICBhdmc9cGxlZGdlZC9iYWNrZXJzKSAlPiUNCiAgICBhcnJhbmdlKGRlc2MoYXZnKSkNCg0KIyBDaGFuZ2UgbWFpbl9jYXRlZ29yeSBpbnRvIGEgZmFjdG9yIHNvIGdncGxvdCB3aWxsIGhvbm9yIHRoZSBzb3J0IG9yZGVyDQpwbGVkZ2VCeUNhdCRtYWluX2NhdGVnb3J5IDwtIGZhY3RvcihwbGVkZ2VCeUNhdCRtYWluX2NhdGVnb3J5LCBsZXZlbHM9cGxlZGdlQnlDYXQkbWFpbl9jYXRlZ29yeSkNCg0KIyBQbG90IGJhciBjaGFydCBvZiBtZWFuIHBsZWRnZXMNCnBsZWRnZUJ5Q2F0UGxvdCA8LSBnZ3Bsb3QocGxlZGdlQnlDYXQsIGFlcyh4PW1haW5fY2F0ZWdvcnkseT1hdmcsZmlsbD1hdmcpKSArIGdlb21fY29sKCkgKyBsYWJzKHRpdGxlPSJBdmcgUGxlZGdlIEJ5IENhdGVnb3J5IFBlciBCYWNrZXIiLCB4PSJDYXRlZ29yeSIseT0iQXZnIFBsZWRnZSBQZXIgQmFja2VyIikgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTApLGxlZ2VuZC5wb3NpdGlvbiA9ICJudWxsIikNCg0KcHJpbnQocGxlZGdlQnlDYXRQbG90KQ0KDQpgYGANCg0KIyMgUGVyIGNhdGVnb3J5LCB3aGF0cyB0aGUgc3VjY2VzcyB0byBmYWlsdXJlIHJhdGUvcmF0aW8gb2YgYWxsIHByb2plY3RzPw0KPiBEYW5jZSBoYXMgdGhlIGhpZ2hlc3Qgc3VjY2VzcyByYXRlLCBidXQgYSBsb3cgbnVtYmVyIG9mIHByb2plY3RzIG92ZXJhbGwNCg0KYGBge3IgU3VjY2Vzcy9GYWlsdXJlIFJhdGlvIG9mIEFsbCBQcm9qZWN0cywgUGVyIENhdGVnb3J5fQ0KDQojIFJvbGwgdXAgZGF0YXNldA0Kc3VjY2Vzc1BlckNhdCA8LSBrczIwMTggJT4lDQogICAgZ3JvdXBfYnkobWFpbl9jYXRlZ29yeSkgJT4lDQogICAgc3VtbWFyaXplKA0KICAgICAgICBmYWlscyA9IHN1bShzdGF0ZSA9PSAiZmFpbGVkIiwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgc3VjY2VzcyA9IHN1bShzdGF0ZSA9PSAic3VjY2Vzc2Z1bCIsIG5hLnJtID0gVFJVRSksDQogICAgICAgIHN1Y2Nlc3NfcmF0ZSA9IHN1Y2Nlc3MgLyAoc3VjY2VzcyArIGZhaWxzKSAqIDEwMA0KICAgICkgJT4lDQogICAgYXJyYW5nZShkZXNjKHN1Y2Nlc3NfcmF0ZSkpDQoNCiMgQ2hhbmdlIG1haW5fY2F0ZWdvcnkgaW50byBhIGZhY3RvciBzbyBnZ3Bsb3Qgd2lsbCBob25vciB0aGUgc29ydCBvcmRlcg0Kc3VjY2Vzc1BlckNhdCRtYWluX2NhdGVnb3J5IDwtIGZhY3RvcihzdWNjZXNzUGVyQ2F0JG1haW5fY2F0ZWdvcnksIGxldmVscz1zdWNjZXNzUGVyQ2F0JG1haW5fY2F0ZWdvcnkpDQoNCiMgUGxvdCBiYXIgY2hhcnQNCnN1Y2Nlc3NQZXJDYXRQbG90IDwtIGdncGxvdChzdWNjZXNzUGVyQ2F0LCBhZXMoeD1tYWluX2NhdGVnb3J5LHk9c3VjY2Vzc19yYXRlLGZpbGw9c3VjY2Vzc19yYXRlKSkgKyBnZW9tX2NvbCgpICsgbGFicyh0aXRsZT0iUGVyY2VudCBTdWNjZXNzIFBlciBDYXRlZ29yeSIsIHg9IkNhdGVnb3J5Iix5PSJQZXJjZW50YWdlIFN1Y2Nlc3NlcyIpICsgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwKSxsZWdlbmQucG9zaXRpb24gPSAibnVsbCIpDQoNCnByaW50KHN1Y2Nlc3NQZXJDYXRQbG90KQ0KDQpmYWlsVG90YWxzIDwtIGdncGxvdChzdWNjZXNzUGVyQ2F0LCBhZXMoeD1tYWluX2NhdGVnb3J5LHk9ZmFpbHMpKSArIGdlb21fY29sKCkNCg0Kc3VjY2Vzc0FuZEZhaWxzIDwtIGZhaWxUb3RhbHMgKyBnZW9tX2NvbChwb3NpdGlvbj0iZG9kZ2UiLCBhZXMoeT1zdWNjZXNzLGZpbGw9ZmFjdG9yKHN1Y2Nlc3MpKSkgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTApLGxlZ2VuZC5wb3NpdGlvbiA9ICJudWxsIikNCg0KcHJpbnQoc3VjY2Vzc0FuZEZhaWxzKQ0KDQpgYGANCg0KYGBge3IgU3VjY2Vzcy9GYWlsdXJlIFJhdGlvIG9mIEFsbCBQcm9qZWN0cywgUGVyIENhdGVnb3J5IC0gc2NhbGEgdmVyfQ0KDQpzdWNjZXNzUGVyQ2F0IDwtIGtzMjAxOCAlPiUNCiAgZmlsdGVyKHN0YXRlICVpbiUgYygic3VjY2Vzc2Z1bCIsICJmYWlsZWQiKSkgJT4lDQogIGdyb3VwX2J5KG1haW5fY2F0ZWdvcnksIHN0YXRlKSAlPiUNCiAgc3VtbWFyaXplKGNhdGVnb3J5X2NvdW50PW4oKSkgJT4lDQogIG11dGF0ZShjYXRlZ29yeV9wZXJjZW50PWNhdGVnb3J5X2NvdW50L3N1bShjYXRlZ29yeV9jb3VudCkpICU+JQ0KICBhcnJhbmdlKGRlc2Moc3RhdGUpLCBjYXRlZ29yeV9wZXJjZW50KQ0KDQojIENoYW5nZSBtYWluX2NhdGVnb3J5IGludG8gYSBmYWN0b3Igc28gZ2dwbG90IHdpbGwgaG9ub3IgdGhlIHNvcnQgb3JkZXINCnN1Y2Nlc3NQZXJDYXQkbWFpbl9jYXRlZ29yeSA8LSBmYWN0b3Ioc3VjY2Vzc1BlckNhdCRtYWluX2NhdGVnb3J5LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9dW5pcXVlKHN1Y2Nlc3NQZXJDYXQkbWFpbl9jYXRlZ29yeSkpDQoNCnByaW50KHN1Y2Nlc3NQZXJDYXQkbWFpbl9jYXRlZ29yeSkNCg0Kc3VjY2Vzc1RvdGFscyA8LSBnZ3Bsb3Qoc3VjY2Vzc1BlckNhdCwgYWVzKHg9bWFpbl9jYXRlZ29yeSwgeT1jYXRlZ29yeV9wZXJjZW50LCBmaWxsPXN0YXRlKSkgKyBnZW9tX2NvbCgpDQpzdWNjZXNzQW5kRmFpbHMgPC0gc3VjY2Vzc1RvdGFscyArIA0KICBnZW9tX2NvbChwb3NpdGlvbj0iZmlsbCIpICsgDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUoYnJlYWtzPWMoInN1Y2Nlc3NmdWwiLCAiZmFpbGVkIikpICsgDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpwZXJjZW50KSArDQogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT05MCksbGVnZW5kLnBvc2l0aW9uID0gIm51bGwiKQ0KDQpwcmludChzdWNjZXNzQW5kRmFpbHMpDQpgYGANCg0KIyMgVHJlbmRzIGluIGtpY2tzdGFydGVyIGNhdGVnb3JpZXMgb3ZlciB0aW1lDQoNCj4gSHlwb3RoZXNpczoga2lja3N0YXJ0ZXIgYmVnYW4gd2l0aCBtYWlubHkgdGVjaCBwcm9qZWN0cyBhbmQgdGhlbiBleHBhbmRlZCBvdmVyIHRpbWUNCg0KYGBge3IgTGluZSBQbG90fQ0KDQojIFJvbGwgdXAgZGF0YXNldCB0byBudW1iZXIgb2YgcHJvamVjdHMgcGVyIGNhdGVnb3J5IHBlciB5ZWFyDQpjYXRPdmVyVGltZSA8LSBrczIwMTggJT4lDQogICAgbXV0YXRlKHllYXI9eWVhcihkZWFkbGluZSkpICU+JQ0KICAgIGdyb3VwX2J5KG1haW5fY2F0ZWdvcnkseWVhcikgJT4lDQogICAgc3VtbWFyaXplKGNhdF90b3RhbD1uKCkpICU+JQ0KICAgIGZpbHRlcih5ZWFyIDwgMjAxOCkgJT4lDQogICAgYXJyYW5nZShjYXRfdG90YWwpDQoNCiMgTGluZSBjaGFydCBvZiBwcm9qZWN0cyBwZXIgY2F0ZWdvcnkgcGVyIHllYXINCmNhdE92ZXJUaW1lUGxvdCA8LSBnZ3Bsb3QoDQogICAgY2F0T3ZlclRpbWUsIA0KICAgIGFlcyh4PXllYXIseT1jYXRfdG90YWwsY29sb3VyPW1haW5fY2F0ZWdvcnkpKSArIGdlb21fbGluZSgpDQoNCnByaW50KGNhdE92ZXJUaW1lUGxvdCkNCg0KIyBVbmZvcnR1bmF0ZWx5IHRoaXMgaXNuJ3Qgc3VwZXIgcmVhZGFibGU/DQpgYGANCiMjIFJldHJ5aW5nIHRoZSBhYm92ZSBkYXRhIHdpdGggYSBtb2RpZmllZCBkcGx5ciBmaWx0ZXIgYW5kIGEgZGVuc2l0eSBwbG90LCB0byB0cnkgYW5kIGdldCBhIGJldHRlciB2aXN1YWwgb2YgdGhlIGRhdGENCg0KPiBJcyB0aGVyZSBhIHdheSB0byByZWR1Y2UgdGhlIG51bWJlciBvZiBkaXN0aW5jdCBjYXRlZ29yaWVzIHNvIHdlIGNhbiBvbmx5IHZpZXcgdGhlIHRvcCAxMCUgbW9zdCBwb3B1bGFyIGNhdGVnb3JpZXM/DQoNCmBgYHtyIERlbnNpdHkgTWFwfQ0KDQojIFJvbGwgdXAgZGF0YXNldCB0byBudW1iZXIgb2YgcHJvamVjdHMgcGVyIGNhdGVnb3J5IHBlciB5ZWFyDQojIFJlbW92ZSBzdW1tYXJpemUgYmVjYXVzZSB0aGF0IGZyb250bG9hZHMgdGhlIHByb2Nlc3MgdGhhdCB0aGUgZGVuc2l0eSBwbG90IHdhbnRzIHRvIGRvDQojIHdoaWNoIGlzIGNvdW50aW5nIHRoZSBudW1iZXIgb2YgZXZlbnRzDQpjYXRPdmVyVGltZTIgPC0ga3MyMDE4ICU+JQ0KICAgIG11dGF0ZSh5ZWFyPXllYXIoZGVhZGxpbmUpKSAlPiUNCiAgICBncm91cF9ieShtYWluX2NhdGVnb3J5LGRlYWRsaW5lKSAlPiUNCiAgICBmaWx0ZXIoeWVhciA8IDIwMTgpICU+JQ0KICAgIGFycmFuZ2UoZGVhZGxpbmUpDQoNCiMgRGVuc2l0eSBwbG90IG9mIHByb2plY3RzDQojIGhpc3RvZ3JhbSAtIHBsb3R0aW5nIGZyZXF1ZW5jeSBvZiBhbiBldmVudCBpbiB0aGUgeSBheGlzLCB2ZXJzdXMgdGhlIHNjYWxlL2dyb3VwcyBpbiB0aGUgeCBheGlzDQpjYXREZW5zaXR5IDwtIGdncGxvdCgNCiAgICBjYXRPdmVyVGltZTIsDQogICAgYWVzKHg9ZGVhZGxpbmUsZmlsbD1tYWluX2NhdGVnb3J5LGNvbG91cj1tYWluX2NhdGVnb3J5KSkgKyBnZW9tX2RlbnNpdHkoYWxwaGEgPSAwLjEpDQoNCnByaW50KGNhdERlbnNpdHkpDQpgYGANCg0KIyMgVHJ5aW5nIGEgaGVhdG1hcCB0byB2aXN1YWxpemUgdGhlIHRyZW5kcyBpbiBjYXRlZ29yaWVzDQoNCj4gQWNjb3JkaW5nIHRvIG91ciBoZWF0IG1hcCwgYXJ0IHByb2plY3RzIGxpa2UgZmlsbS92aWRlbyBhbmQgbXVzaWMgd2VyZSBtb3N0IHBvcHVsYXIuIEdhbWVzIGFuZCB0ZWNobm9sb2d5IGRpZCBub3QgYmVjb21lIHBvcHVsYXIgY2F0ZWdvcmllcyB1bnRpbCBsYXRlci4NCg0KYGBge3IgSGVhdG1hcH0NCg0KIyBSZWRvIHJvbGxpbmcgdXAgZGF0YXNldCB0byBpbmNsdWRlIGRlYWRsaW5lIHZlY3Rvcg0KY2F0SGVhdCA8LSBrczIwMTggJT4lDQogICAgbXV0YXRlKHllYXI9eWVhcihkZWFkbGluZSkpICU+JQ0KICAgIGdyb3VwX2J5KG1haW5fY2F0ZWdvcnkseWVhcikgJT4lDQogICAgc3VtbWFyaXplKA0KICAgICAgICBjYXRfdG90YWw9bigpLCANCiAgICAgICAgZGVhZGxpbmU9ZGVhZGxpbmVbMV0pICU+JQ0KICAgIGZpbHRlcih5ZWFyIDwgMjAxOCkgJT4lDQogICAgYXJyYW5nZSh5ZWFyKQ0KDQojIEhlYXRtYXAgb2YgY2F0ZWdvcmllcyBvdmVyIHRpbWUNCmNhdEhlYXRQbG90IDwtIGdncGxvdCgNCiAgICBjYXRIZWF0LCANCiAgICBhZXMoeD15ZWFyLHk9bWFpbl9jYXRlZ29yeSkpICsgDQogICAgZ2VvbV90aWxlKGFlcyhmaWxsPWNhdF90b3RhbCkpICsgDQogICAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAnd2hpdGUnLCBoaWdoID0gJ3JlZCcpICsNCiAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gZnVuY3Rpb24oeCkgdW5pcXVlKGZsb29yKHByZXR0eSh4KSkpKSArIA0KICAgIGxhYnModGl0bGU9Ik1vc3QgUG9wdWxhciBLaWNrc3RhcnRlciBDYXRlZ29yaWVzIFBlciBZZWFyIiwgeD0iWWVhciIseT0iTWFpbiBDYXRlZ29yeSIpDQoNCnByaW50KGNhdEhlYXRQbG90KQ0KDQpgYGANCg0KIyMgTm90ZXMNCj4gc3VtbWFyaXplIHdpbGwgc3RyaXAgb3V0IGFueXRoaW5nIHRoYXQgaXNudCBpbiB0aGUgZ3JvdXAgYnksIG11dGF0aW9uLCBvciBpbiB0aGUgc3VtbWFyaXplIGl0c2VsZg0KPiBzbyB5b3UgbmVlZCB0byByZWZlcmVuY2Ugcm93cyBpbiB0aGUgc3VtbWFyaXplIGlmIHlvdSB3YW50IHRvIGluY2x1ZGUgdGhlbSBidXQgdGhleSdyZSBub3QgaW4gZ3JvdXAgYnkgb3IgbXV0YXRlDQoNCg0KIyMgSGFzIGtpY2tzdGFydGVyIHBlYWtlZCBpbiBpdHMgcG9wdWxhcml0eSBhcyBhIGNyb3dkZnVuZGluZyBwbGF0Zm9ybT8gDQo+IFRoZXJlIHdhcyBhIHBlYWsgaW4gS2lja3N0YXJ0ZXIgcG9wdWxhcml0eSBpbiAyMDE1LCBhbmQgaXRzIHBvcHVsYXJpdHkgaGFzIGRlY2xpbmVkIHNpbmNlIHRoZW4NCg0KDQpgYGB7ciBTY2F0dGVycGxvdH0NCg0KIyBEZWZpbmUgZGVuc2l0eSBmdW5jdGlvbg0KZ2V0X2RlbnNpdHkgPC0gZnVuY3Rpb24oeCwgeSwgbiA9IDEwMCkgew0KICBkZW5zIDwtIE1BU1M6OmtkZTJkKHggPSB4LCB5ID0geSwgbiA9IG4pDQogIGl4IDwtIGZpbmRJbnRlcnZhbCh4LCBkZW5zJHgpDQogIGl5IDwtIGZpbmRJbnRlcnZhbCh5LCBkZW5zJHkpDQogIGlpIDwtIGNiaW5kKGl4LCBpeSkNCiAgcmV0dXJuKGRlbnMkeltpaV0pDQp9DQoNCiMgRnJlcXVlbmN5IG9mIHByb2plY3RzIHkgYXhpcywgeCBheGlzIG92ZXIgdGltZQ0KcG9wT3ZlclRpbWUgPC0ga3MyMDE4ICU+JQ0KICAgIGdyb3VwX2J5KGRlYWRsaW5lKSAlPiUNCiAgICBzdW1tYXJpemUoY291bnQ9bigpKSAlPiUNCiAgICBtdXRhdGUoZGVuc2l0eT1nZXRfZGVuc2l0eShhcy5pbnRlZ2VyKGRlYWRsaW5lKSwgY291bnQpKQ0KDQojIFNjYXR0ZXJwbG90IHdpdGggYSB0cmVuZCBsaW5lDQpwb3BPdmVyVGltZVBsb3QgPC0gZ2dwbG90KHBvcE92ZXJUaW1lLCBhZXMoeD1kZWFkbGluZSx5PWNvdW50LGNvbG9yPWRlbnNpdHkpKSArDQogICAgZ2VvbV9wb2ludCgpICsNCiAgICBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIiwgY29sb3I9IkRhcmsgQmx1ZSIpICsNCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwgNDAwKSkgKyAjIFJlbW92ZSB2YWx1ZXMgb3ZlciA1MDANCiAgICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMSB5ZWFyIiwNCiAgICAgICAgICAgICAgICAgbGFiZWxzPWRhdGVfZm9ybWF0KCIlWSIpLA0KICAgICAgICAgICAgICAgICBsaW1pdHMgPSBhcy5EYXRlKGMoJzIwMDktMDEtMDEnLCcyMDE4LTAxLTAxJykpKSArDQogICAgbGFicyh0aXRsZT0iRnJlcXVlbmN5IG9mIEtpY2tzdGFydGVyIFByb2plY3RzIG92ZXIgVGltZSIpICsNCiAgICBzY2FsZV9jb2xvcl92aXJpZGlzKCkgKw0KICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpDQoNCnByaW50KHBvcE92ZXJUaW1lUGxvdCkNCmBgYA0KDQo=