Preparation Instructions

EXERCISES

Examine the Data

For this Challenge Problem assignment, you are going to be using the 2015 census dataset.1 (Note: It is called census2015 in the set-up code chunk.) The data includes demographic and economic information for each county in the US [Note: States in the US are made up of counties, which are bigger than a city but smaller than a state]. The documentation for this dataset can be found on Kaggle.

  1. Examine the census2015 dataset. [Note: Feel free to use the eval=FALSE in the code chunk options so the output doesn’t get long.]
dim(census2015)

glimpse(census2015)
  1. Define what a case is (in the context of the dataset).
  • A case in this dataset is a single county in the United States
  1. How many cases are in the census2015 dataset? How many variables? [Note: You may have to use R code to figure this out if you didn’t obtain this information in a previous question.]
  • Cases: 3220
  • Variables: 37
  1. How many “cases” are there for each state? (Give answer as a table)
census2015 %>%
  group_by(State) %>%
  summarise(cases = n()) %>%
  arrange(desc(cases))

Practice Problems

Now let’s practice wrangling the data (if need be) and creating data visualizations to answer more in depth questions. Each question is supposed to be stand alone and not build from each other (unless specified).

  1. What is the general distribution of median household income for counties in the United States? Answer this question by creating a histogram, a boxplot, or a density plot of median household income. Feel free to customize the aesthetics of graph as you see fit.
ggplot(census2015, aes(x = Income)) + 
  geom_density(fill = "#7a0019", alpha = 0.6, na.rm = TRUE) +
  labs(title = "Density of Counties in the U.S. Median Household Income", 
       x = "Median Household Income", 
       y = "Density") +
         theme_bw()

  1. What is the relationship between median household income and mean commute time (in minutes) for counties in the United States? Answer this question by creating a scatterplot of mean commute time (in minutes) vs. median household income. Feel free to customize the aesthetics of graph as you see fit. [Note: When using the phrase of “vs.” to describe a scatterplot, it’s always of the form y vs. x. Also, if you don’t like the overplotting that you see, try using geom_hex instead. (you’ll need to make sure the “hexbin” package is installed)]
ggplot(census2015, aes(x = Income, y = MeanCommute)) + 
  geom_point(alpha = 0.4, color = "#7a0019", na.rm = TRUE) + 
  labs(title = "Mean Commute Time (in minutes) vs Median Household Income", 
       x = "Median Household Income", 
       y = "Mean Commute Time (minutes)") +
  theme_bw()

  1. What is the relationship between median household income and mean commute time (in minutes), while taking total population into account, for counties in the United States? Answer this question by creating a scatterplot of mean commute time (in minutes) vs. median household income but this time, color and size the points by the total population of the county. Feel free to customize the aesthetics of graph as you see fit. [Note: If you don’t like the overplotting that you see, try adjusting the transparency of the points.]
ggplot(census2015, aes(x = Income, y = MeanCommute, color = TotalPop, size = TotalPop)) + 
  geom_point(alpha = 0.6, color = "#7a0019", na.rm = TRUE) + 
  labs(title = "Mean Commute Time (in minutes) vs Median Household Income by Total Population", 
       x = "Median Household Income",
       y = "Mean Commute Time (minutes)",
       color = "Total Population", 
       size = "Total Population") + 
  scale_size_continuous(labels = comma) + 
  scale_color_continuous(labels = comma) +
  theme_bw()

  1. For each state, what is the relationship between median household income and mean commute time (in minutes) for their counties in the United States? Answer this question by creating a scatterplot of mean commute time (in minutes) vs. median household income and faceting by state. Feel free to customize the aesthetics of graph as you see fit. [Note: If you don’t like the overplotting that you see, try adjusting the transparency of the points.]
ggplot(census2015, aes(x = Income, y = MeanCommute)) + 
  geom_point(alpha = 0.6, color = "#7a0019", na.rm = TRUE) + 
  labs(title = "Mean Commute Time (in minutes) vs Median Household Income by State",
       x = "Median Household Income",
       y = "Mean Commute Time (minutes)") + 
  theme_bw() +
theme(
  axis.text.x = element_text(angle = 45, hjust = 1, size = 6),
  strip.text = element_text(size = 6.5),
  plot.title = element_text(size = 15)) +
  facet_wrap(~State)

  1. What is the relationship between median household income and mean commute time (in minutes), while taking total population into account, for states in the United States? Answer this question by first, wrangling the data so a case (row) is a state and the columns are (1) median of the counties’ median household income, (2) mean of the counties’ mean commute time, and (3) sum of counties’ total population. [Note: Be sure to examine the data frame from the data wrangling process to double-check that the results are what you expected.] Then, create a scatterplot of mean commute time (in minutes) vs. median household income, modifying the color and size the points by the total population of the state.
state <- census2015 %>%
  group_by(State) %>%
  summarise(
    income_median = median(Income, na.rm = TRUE),
    mean_commute = mean(MeanCommute, na.rm = TRUE), 
    total = sum(TotalPop, na.rm = TRUE)
  )

ggplot(state, aes(x = income_median, y = mean_commute, color = total, size = total)) + 
  geom_point(na.rm = TRUE) + 
  geom_text_repel(aes(label = State), vjust = -0.5, size = 2.5, color = "#7a0019", max.overlaps = Inf) + 
  labs(title = "Mean Commute time (in minutes) vs Median Household Income by States Total Population",
       x = "Median Household Income", 
       y = "Mean Commute Time (minutes)",
       color = "Total Population",
       size = "Total Population") + 
  scale_size_continuous(labels = comma) + 
  scale_color_continuous(labels = comma) +
  theme_bw() +
theme(plot.title = element_text(size = 14))

Putting It All Together

Now let’s put the components of data visualization together to answer a question.

What is the distribution of median income by county for each state?

You are going to explore this in three different data visualizations (in questions 10 to 12). Feel free to customize the aesthetics of graph as you see fit.

  1. Data Visualization #1: Create a scatterplot of state vs. median income (Income) where the state is reordered by the median of the Income variable like the plot below: [Note: Be sure to examine the results from each step to make sure they reflect what you think they are!]

ggplot(census2015, aes(x = reorder(State, Income, FUN = median), y = Income)) + 
  geom_point(alpha = 0.5, color = "#7a0019", na.rm = TRUE) + 
  labs(title = "Distribution of Median Income by County for Each State",
       x = "State",
       y = "Median Household Income") + 
  theme_bw() + 
  theme(
    plot.title = element_text(size = 12, face = "bold", hjust = 0.5),
    axis.text.x = element_text(angle = 45, hjust = 1, size = 6.8)
  )

  1. Data Visualization #2: Create a plot (either a histogram, a boxplot, or a density plot) of median income (Income) where each state has their own panel.
ggplot(census2015, aes(x= Income)) + 
  geom_histogram(fill = "#7a0019", color = "white", bins = 20, na.rm = TRUE) + 
  labs(title = "Distribution of Median Household Income by State",
       x = "Median Household Income",
       y = "Count") + 
  theme_bw() + 
  theme(plot.title = element_text(size = 12, face = "bold", hjust = 0.5),
        strip.text = element_text(size = 6.5),
        axis.title.x = element_text(size = 10),
        axis.text.x = element_text(angle = 45, hjust = 1, size = 5)
        ) + 
  facet_wrap(~State)

  1. Data Visualization #3: Create a plot (either a histogram, a boxplot, or a density plot) of median income (Income) where each state is located approximately in their own region of the country. [Note: To do this, you will need the function facet_geo(~variable, scales="free") from the {geofacet} package2] An example of this with density plots is below:

library(geofacet) 
census <- census2015 %>%
  filter(!State %in% c("Puerto Rico", "District of Columbia"))
ggplot(census, aes(x = Income)) + 
  geom_histogram(fill = "#7a0019", color = "white", bins = 20, na.rm = TRUE) +
  labs(title = "Distribution of Median Household Income by State",
       x = "Median Household Income",
       y = "Count") + 
  theme_bw() + 
  theme(plot.title = element_text(size =24, face = "bold", hjust = 0.5),
        strip.text = element_text(size = 12),
        axis.title.x = element_text(size = 20), 
        axis.title.y = element_text(size = 6),
        axis.text.x = element_text(size = 9, angle = 45, hjust = 1)) +
  facet_geo(~State, scales = "free")


  1. Source: Tidy Tuesday dataset from April 30, 2018.↩︎

  2. Resource: Introduction to geofacet.↩︎

LS0tCnRpdGxlOiAiV2VlayA2IENoYWxsZW5nZSBQcm9ibGVtIgphdXRob3I6ICJCaWxzdW1hIEFkZW1hIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KCiMjIyBQcmVwYXJhdGlvbiBJbnN0cnVjdGlvbnMKCi0gQmUgc3VyZSB0byBjaGFuZ2UgdGhlIGF1dGhvciBpbiB0aGUgWUFNTCB0byB5b3VyIG5hbWUuIFJlbWVtYmVyIHRvIGtlZXAgaXQgaW5zaWRlIHRoZSBxdW90ZXMuCgotIFF1ZXN0aW9ucyB0aGF0IHJlcXVpcmUgdGhlIHVzZSBvZiBSIHdpbGwgaGF2ZSBhbiBSIGNvZGUgY2h1bmsgYmVsb3cgaXQuIAoKLSBEb3dubG9hZCB0aGUgQ2Vuc3VzIDIwMTUgZGF0YXNldCAodGl0bGVkICpjZW5zdXMyMDE1LmNzdiopIGFzIHdlbGwgYXMgdGhlIHR3byBpbWFnZSBmaWxlcyBmcm9tIHRoZSBDYW52YXMgcGFnZSBmb3IgdGhpcyBhc3NpZ25tZW50IGFuZCBzYXZlIHRoZXNlIGZpbGVzIHRvIHRoZSBmb2xkZXIgd2hlcmUgdGhlIFJNRCBmaWxlIGlzIGxvY2F0ZWQuIAoKLSBSZW1lbWJlciB0byBjaGFuZ2UgdGhlIGZpbGVwYXRoIGxvY2F0aW9uIGluIHRoZSBgcmVhZC5jc3YoKWAgZnVuY3Rpb24gdG8gd2hlcmUgdGhlICouY3N2KiBkYXRhc2V0IGlzIGxvY2F0ZWQgb24geW91ciBjb21wdXRlci4gWW91IGNhbiBmaW5kIHRoZSBmaWxlcGF0aCBieSB1c2luZyB0aGUgYGZpbGUuY2hvb3NlKClgIGZ1bmN0aW9uLiBPbmNlIHRoaXMgaGFzIGJlZW4gY29tcGxldGVkLCB0aGVuIHlvdSBjYW4gZGVsZXRlIHRoZSBgI2AgYXQgdGhlIHN0YXJ0IG9mIGxpbmVzIDI0IGFuZCAyNS4KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZm9yY2F0cykKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoZ2dyZXBlbCkKY2Vuc3VzMjAxNTwtcmVhZC5jc3YoIi9Vc2Vycy9iaWxzdW1hYWRlbWEvRG9jdW1lbnRzL1IgQ291cnNlIENsYXNzIDIwMjUvY2Vuc3VzMjAxNS5jc3YiLCBoZWFkZXI9VFJVRSkKCmNlbnN1czIwMTU8LWFzX3RpYmJsZShjZW5zdXMyMDE1KQoKCgpgYGAKCiMjIyMgRVhFUkNJU0VTCgoqKkV4YW1pbmUgdGhlIERhdGEqKgoKRm9yIHRoaXMgQ2hhbGxlbmdlIFByb2JsZW0gYXNzaWdubWVudCwgeW91IGFyZSBnb2luZyB0byBiZSB1c2luZyB0aGUgMjAxNSBjZW5zdXMgZGF0YXNldC5eW1NvdXJjZTogWyoqVGlkeSBUdWVzZGF5IGRhdGFzZXQgZnJvbSBBcHJpbCAzMCwgMjAxOCoqXShodHRwczovL2dpdGh1Yi5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L3RyZWUvbWFzdGVyL2RhdGEvMjAxOCkuXSAoTm90ZTogSXQgaXMgY2FsbGVkIGBjZW5zdXMyMDE1YCBpbiB0aGUgc2V0LXVwIGNvZGUgY2h1bmsuKSBUaGUgZGF0YSBpbmNsdWRlcyBkZW1vZ3JhcGhpYyBhbmQgZWNvbm9taWMgaW5mb3JtYXRpb24gZm9yIGVhY2ggY291bnR5IGluIHRoZSBVUyBbTm90ZTogU3RhdGVzIGluIHRoZSBVUyBhcmUgbWFkZSB1cCBvZiBjb3VudGllcywgd2hpY2ggYXJlIGJpZ2dlciB0aGFuIGEgY2l0eSBidXQgc21hbGxlciB0aGFuIGEgc3RhdGVdLiBUaGUgZG9jdW1lbnRhdGlvbiBmb3IgdGhpcyBkYXRhc2V0IGNhbiBiZSBmb3VuZCBvbiBbS2FnZ2xlXShodHRwczovL3d3dy5rYWdnbGUuY29tL211b25uZXV0cmluby91cy1jZW5zdXMtZGVtb2dyYXBoaWMtZGF0YSkuCgooQCkgRXhhbWluZSB0aGUgYGNlbnN1czIwMTVgIGRhdGFzZXQuIFtOb3RlOiBGZWVsIGZyZWUgdG8gdXNlIHRoZSBgZXZhbD1GQUxTRWAgaW4gdGhlIGNvZGUgY2h1bmsgb3B0aW9ucyBzbyB0aGUgb3V0cHV0IGRvZXNuJ3QgZ2V0IGxvbmcuXQoKYGBge3IgZXZhbD1GQUxTRX0KZGltKGNlbnN1czIwMTUpCgpnbGltcHNlKGNlbnN1czIwMTUpCmBgYAoKKEApIERlZmluZSB3aGF0IGEgY2FzZSBpcyAoaW4gdGhlIGNvbnRleHQgb2YgdGhlIGRhdGFzZXQpLgoqIEEgY2FzZSBpbiB0aGlzIGRhdGFzZXQgaXMgYSBzaW5nbGUgY291bnR5IGluIHRoZSBVbml0ZWQgU3RhdGVzIAooQCkgSG93IG1hbnkgY2FzZXMgYXJlIGluIHRoZSBgY2Vuc3VzMjAxNWAgZGF0YXNldD8gSG93IG1hbnkgdmFyaWFibGVzPyBbTm90ZTogWW91IG1heSBoYXZlIHRvIHVzZSBSIGNvZGUgdG8gZmlndXJlIHRoaXMgb3V0IGlmIHlvdSBkaWRuJ3Qgb2J0YWluIHRoaXMgaW5mb3JtYXRpb24gaW4gYSBwcmV2aW91cyBxdWVzdGlvbi5dCiogQ2FzZXM6IDMyMjAKKiBWYXJpYWJsZXM6IDM3IAooQCkgSG93IG1hbnkgImNhc2VzIiBhcmUgdGhlcmUgZm9yIGVhY2ggc3RhdGU/IChHaXZlIGFuc3dlciBhcyBhIHRhYmxlKSAKCmBgYHtyfQpjZW5zdXMyMDE1ICU+JQogIGdyb3VwX2J5KFN0YXRlKSAlPiUKICBzdW1tYXJpc2UoY2FzZXMgPSBuKCkpICU+JQogIGFycmFuZ2UoZGVzYyhjYXNlcykpCmBgYAoKCioqUHJhY3RpY2UgUHJvYmxlbXMqKgoKTm93IGxldCdzIHByYWN0aWNlIHdyYW5nbGluZyB0aGUgZGF0YSAoaWYgbmVlZCBiZSkgYW5kIGNyZWF0aW5nIGRhdGEgdmlzdWFsaXphdGlvbnMgdG8gYW5zd2VyIG1vcmUgaW4gZGVwdGggcXVlc3Rpb25zLiBFYWNoIHF1ZXN0aW9uIGlzIHN1cHBvc2VkIHRvIGJlIHN0YW5kIGFsb25lIGFuZCBub3QgYnVpbGQgZnJvbSBlYWNoIG90aGVyICh1bmxlc3Mgc3BlY2lmaWVkKS4gCgooQCkgKipXaGF0IGlzIHRoZSBnZW5lcmFsIGRpc3RyaWJ1dGlvbiBvZiBtZWRpYW4gaG91c2Vob2xkIGluY29tZSBmb3IgY291bnRpZXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXM/KiogQW5zd2VyIHRoaXMgcXVlc3Rpb24gYnkgY3JlYXRpbmcgYSBoaXN0b2dyYW0sIGEgYm94cGxvdCwgb3IgYSBkZW5zaXR5IHBsb3Qgb2YgKm1lZGlhbiBob3VzZWhvbGQgaW5jb21lKi4gRmVlbCBmcmVlIHRvIGN1c3RvbWl6ZSB0aGUgYWVzdGhldGljcyBvZiBncmFwaCBhcyB5b3Ugc2VlIGZpdC4KCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTQuNX0KZ2dwbG90KGNlbnN1czIwMTUsIGFlcyh4ID0gSW5jb21lKSkgKyAKICBnZW9tX2RlbnNpdHkoZmlsbCA9ICIjN2EwMDE5IiwgYWxwaGEgPSAwLjYsIG5hLnJtID0gVFJVRSkgKwogIGxhYnModGl0bGUgPSAiRGVuc2l0eSBvZiBDb3VudGllcyBpbiB0aGUgVS5TLiBNZWRpYW4gSG91c2Vob2xkIEluY29tZSIsIAogICAgICAgeCA9ICJNZWRpYW4gSG91c2Vob2xkIEluY29tZSIsIAogICAgICAgeSA9ICJEZW5zaXR5IikgKwogICAgICAgICB0aGVtZV9idygpCmBgYAoKKEApICoqV2hhdCBpcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUgYW5kIG1lYW4gY29tbXV0ZSB0aW1lIChpbiBtaW51dGVzKSBmb3IgY291bnRpZXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXM/KiogQW5zd2VyIHRoaXMgcXVlc3Rpb24gYnkgY3JlYXRpbmcgYSBzY2F0dGVycGxvdCBvZiAqbWVhbiBjb21tdXRlIHRpbWUgKGluIG1pbnV0ZXMpKiB2cy4gKm1lZGlhbiBob3VzZWhvbGQgaW5jb21lKi4gRmVlbCBmcmVlIHRvIGN1c3RvbWl6ZSB0aGUgYWVzdGhldGljcyBvZiBncmFwaCBhcyB5b3Ugc2VlIGZpdC4gW05vdGU6IFdoZW4gdXNpbmcgdGhlIHBocmFzZSBvZiAidnMuIiB0byBkZXNjcmliZSBhIHNjYXR0ZXJwbG90LCBpdCdzIGFsd2F5cyBvZiB0aGUgZm9ybSB5IHZzLiB4LiBBbHNvLCBpZiB5b3UgZG9uJ3QgbGlrZSB0aGUgb3ZlcnBsb3R0aW5nIHRoYXQgeW91IHNlZSwgdHJ5IHVzaW5nIGBnZW9tX2hleGAgaW5zdGVhZC4gKHlvdSdsbCBuZWVkIHRvIG1ha2Ugc3VyZSB0aGUgImhleGJpbiIgcGFja2FnZSBpcyBpbnN0YWxsZWQpXSAKCmBgYHtyIGZpZy53aWR0aD02LCBmaWcuaGVpZ2h0PTQuNX0KZ2dwbG90KGNlbnN1czIwMTUsIGFlcyh4ID0gSW5jb21lLCB5ID0gTWVhbkNvbW11dGUpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjQsIGNvbG9yID0gIiM3YTAwMTkiLCBuYS5ybSA9IFRSVUUpICsgCiAgbGFicyh0aXRsZSA9ICJNZWFuIENvbW11dGUgVGltZSAoaW4gbWludXRlcykgdnMgTWVkaWFuIEhvdXNlaG9sZCBJbmNvbWUiLCAKICAgICAgIHggPSAiTWVkaWFuIEhvdXNlaG9sZCBJbmNvbWUiLCAKICAgICAgIHkgPSAiTWVhbiBDb21tdXRlIFRpbWUgKG1pbnV0ZXMpIikgKwogIHRoZW1lX2J3KCkKYGBgCgooQCkgKipXaGF0IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBtZWRpYW4gaG91c2Vob2xkIGluY29tZSBhbmQgbWVhbiBjb21tdXRlIHRpbWUgKGluIG1pbnV0ZXMpLCB3aGlsZSB0YWtpbmcgdG90YWwgcG9wdWxhdGlvbiBpbnRvIGFjY291bnQsIGZvciBjb3VudGllcyBpbiB0aGUgVW5pdGVkIFN0YXRlcz8qKiBBbnN3ZXIgdGhpcyBxdWVzdGlvbiBieSBjcmVhdGluZyBhIHNjYXR0ZXJwbG90IG9mICptZWFuIGNvbW11dGUgdGltZSAoaW4gbWludXRlcykqIHZzLiAqbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUqIGJ1dCB0aGlzIHRpbWUsIGNvbG9yIGFuZCBzaXplIHRoZSBwb2ludHMgYnkgdGhlICp0b3RhbCBwb3B1bGF0aW9uKiBvZiB0aGUgY291bnR5LiBGZWVsIGZyZWUgdG8gY3VzdG9taXplIHRoZSBhZXN0aGV0aWNzIG9mIGdyYXBoIGFzIHlvdSBzZWUgZml0LiBbTm90ZTogSWYgeW91IGRvbid0IGxpa2UgdGhlIG92ZXJwbG90dGluZyB0aGF0IHlvdSBzZWUsIHRyeSBhZGp1c3RpbmcgdGhlIHRyYW5zcGFyZW5jeSBvZiB0aGUgcG9pbnRzLl0gIAoKYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KZ2dwbG90KGNlbnN1czIwMTUsIGFlcyh4ID0gSW5jb21lLCB5ID0gTWVhbkNvbW11dGUsIGNvbG9yID0gVG90YWxQb3AsIHNpemUgPSBUb3RhbFBvcCkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNiwgY29sb3IgPSAiIzdhMDAxOSIsIG5hLnJtID0gVFJVRSkgKyAKICBsYWJzKHRpdGxlID0gIk1lYW4gQ29tbXV0ZSBUaW1lIChpbiBtaW51dGVzKSB2cyBNZWRpYW4gSG91c2Vob2xkIEluY29tZSBieSBUb3RhbCBQb3B1bGF0aW9uIiwgCiAgICAgICB4ID0gIk1lZGlhbiBIb3VzZWhvbGQgSW5jb21lIiwKICAgICAgIHkgPSAiTWVhbiBDb21tdXRlIFRpbWUgKG1pbnV0ZXMpIiwKICAgICAgIGNvbG9yID0gIlRvdGFsIFBvcHVsYXRpb24iLCAKICAgICAgIHNpemUgPSAiVG90YWwgUG9wdWxhdGlvbiIpICsgCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWEpICsKICB0aGVtZV9idygpCmBgYAoKCihAKSAqKkZvciBlYWNoIHN0YXRlLCB3aGF0IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBtZWRpYW4gaG91c2Vob2xkIGluY29tZSBhbmQgbWVhbiBjb21tdXRlIHRpbWUgKGluIG1pbnV0ZXMpIGZvciB0aGVpciBjb3VudGllcyBpbiB0aGUgVW5pdGVkIFN0YXRlcz8qKiBBbnN3ZXIgdGhpcyBxdWVzdGlvbiBieSBjcmVhdGluZyBhIHNjYXR0ZXJwbG90IG9mICptZWFuIGNvbW11dGUgdGltZSAoaW4gbWludXRlcykqIHZzLiAqbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUqIGFuZCBmYWNldGluZyBieSBzdGF0ZS4gRmVlbCBmcmVlIHRvIGN1c3RvbWl6ZSB0aGUgYWVzdGhldGljcyBvZiBncmFwaCBhcyB5b3Ugc2VlIGZpdC4gW05vdGU6IElmIHlvdSBkb24ndCBsaWtlIHRoZSBvdmVycGxvdHRpbmcgdGhhdCB5b3Ugc2VlLCB0cnkgYWRqdXN0aW5nIHRoZSB0cmFuc3BhcmVuY3kgb2YgdGhlIHBvaW50cy5dICAKCmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9CmdncGxvdChjZW5zdXMyMDE1LCBhZXMoeCA9IEluY29tZSwgeSA9IE1lYW5Db21tdXRlKSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gMC42LCBjb2xvciA9ICIjN2EwMDE5IiwgbmEucm0gPSBUUlVFKSArIAogIGxhYnModGl0bGUgPSAiTWVhbiBDb21tdXRlIFRpbWUgKGluIG1pbnV0ZXMpIHZzIE1lZGlhbiBIb3VzZWhvbGQgSW5jb21lIGJ5IFN0YXRlIiwKICAgICAgIHggPSAiTWVkaWFuIEhvdXNlaG9sZCBJbmNvbWUiLAogICAgICAgeSA9ICJNZWFuIENvbW11dGUgVGltZSAobWludXRlcykiKSArIAogIHRoZW1lX2J3KCkgKwp0aGVtZSgKICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEsIHNpemUgPSA2KSwKICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2LjUpLAogIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSkgKwogIGZhY2V0X3dyYXAoflN0YXRlKQpgYGAKCihAKSAqKldoYXQgaXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG1lZGlhbiBob3VzZWhvbGQgaW5jb21lIGFuZCBtZWFuIGNvbW11dGUgdGltZSAoaW4gbWludXRlcyksIHdoaWxlIHRha2luZyB0b3RhbCBwb3B1bGF0aW9uIGludG8gYWNjb3VudCwgZm9yIHN0YXRlcyBpbiB0aGUgVW5pdGVkIFN0YXRlcz8qKiBBbnN3ZXIgdGhpcyBxdWVzdGlvbiBieSBmaXJzdCwgd3JhbmdsaW5nIHRoZSBkYXRhIHNvIGEgY2FzZSAocm93KSBpcyBhIHN0YXRlIGFuZCB0aGUgY29sdW1ucyBhcmUgKDEpIG1lZGlhbiBvZiB0aGUgY291bnRpZXMnIG1lZGlhbiBob3VzZWhvbGQgaW5jb21lLCAoMikgbWVhbiBvZiB0aGUgY291bnRpZXMnIG1lYW4gY29tbXV0ZSB0aW1lLCBhbmQgKDMpIHN1bSBvZiBjb3VudGllcycgdG90YWwgcG9wdWxhdGlvbi4gW05vdGU6IEJlIHN1cmUgdG8gZXhhbWluZSB0aGUgZGF0YSBmcmFtZSBmcm9tIHRoZSBkYXRhIHdyYW5nbGluZyBwcm9jZXNzIHRvIGRvdWJsZS1jaGVjayB0aGF0IHRoZSByZXN1bHRzIGFyZSB3aGF0IHlvdSBleHBlY3RlZC5dIFRoZW4sIGNyZWF0ZSBhIHNjYXR0ZXJwbG90IG9mICptZWFuIGNvbW11dGUgdGltZSAoaW4gbWludXRlcykqIHZzLiAqbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUqLCBtb2RpZnlpbmcgdGhlIGNvbG9yIGFuZCBzaXplIHRoZSBwb2ludHMgYnkgdGhlICp0b3RhbCBwb3B1bGF0aW9uKiBvZiB0aGUgc3RhdGUuIAoKYGBge3IgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTh9CnN0YXRlIDwtIGNlbnN1czIwMTUgJT4lCiAgZ3JvdXBfYnkoU3RhdGUpICU+JQogIHN1bW1hcmlzZSgKICAgIGluY29tZV9tZWRpYW4gPSBtZWRpYW4oSW5jb21lLCBuYS5ybSA9IFRSVUUpLAogICAgbWVhbl9jb21tdXRlID0gbWVhbihNZWFuQ29tbXV0ZSwgbmEucm0gPSBUUlVFKSwgCiAgICB0b3RhbCA9IHN1bShUb3RhbFBvcCwgbmEucm0gPSBUUlVFKQogICkKCmdncGxvdChzdGF0ZSwgYWVzKHggPSBpbmNvbWVfbWVkaWFuLCB5ID0gbWVhbl9jb21tdXRlLCBjb2xvciA9IHRvdGFsLCBzaXplID0gdG90YWwpKSArIAogIGdlb21fcG9pbnQobmEucm0gPSBUUlVFKSArIAogIGdlb21fdGV4dF9yZXBlbChhZXMobGFiZWwgPSBTdGF0ZSksIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDIuNSwgY29sb3IgPSAiIzdhMDAxOSIsIG1heC5vdmVybGFwcyA9IEluZikgKyAKICBsYWJzKHRpdGxlID0gIk1lYW4gQ29tbXV0ZSB0aW1lIChpbiBtaW51dGVzKSB2cyBNZWRpYW4gSG91c2Vob2xkIEluY29tZSBieSBTdGF0ZXMgVG90YWwgUG9wdWxhdGlvbiIsCiAgICAgICB4ID0gIk1lZGlhbiBIb3VzZWhvbGQgSW5jb21lIiwgCiAgICAgICB5ID0gIk1lYW4gQ29tbXV0ZSBUaW1lIChtaW51dGVzKSIsCiAgICAgICBjb2xvciA9ICJUb3RhbCBQb3B1bGF0aW9uIiwKICAgICAgIHNpemUgPSAiVG90YWwgUG9wdWxhdGlvbiIpICsgCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKGxhYmVscyA9IGNvbW1hKSArIAogIHNjYWxlX2NvbG9yX2NvbnRpbnVvdXMobGFiZWxzID0gY29tbWEpICsKICB0aGVtZV9idygpICsKdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKQpgYGAKCioqUHV0dGluZyBJdCBBbGwgVG9nZXRoZXIqKgoKTm93IGxldCdzIHB1dCB0aGUgY29tcG9uZW50cyBvZiBkYXRhIHZpc3VhbGl6YXRpb24gdG9nZXRoZXIgdG8gYW5zd2VyIGEgcXVlc3Rpb24uCgo8cCBhbGlnbj0iY2VudGVyIj4KKipXaGF0IGlzIHRoZSBkaXN0cmlidXRpb24gb2YgbWVkaWFuIGluY29tZSBieSBjb3VudHkgZm9yIGVhY2ggc3RhdGU/KioKPC9wPgpZb3UgYXJlIGdvaW5nIHRvIGV4cGxvcmUgdGhpcyBpbiB0aHJlZSBkaWZmZXJlbnQgZGF0YSB2aXN1YWxpemF0aW9ucyAoaW4gcXVlc3Rpb25zIDEwIHRvIDEyKS4gRmVlbCBmcmVlIHRvIGN1c3RvbWl6ZSB0aGUgYWVzdGhldGljcyBvZiBncmFwaCBhcyB5b3Ugc2VlIGZpdC4KCihAKSAqKkRhdGEgVmlzdWFsaXphdGlvbiAjMSoqOiBDcmVhdGUgYSBzY2F0dGVycGxvdCBvZiBzdGF0ZSB2cy4gbWVkaWFuIGluY29tZSAoYEluY29tZWApIHdoZXJlIHRoZSBzdGF0ZSBpcyByZW9yZGVyZWQgYnkgdGhlIG1lZGlhbiBvZiB0aGUgYEluY29tZWAgdmFyaWFibGUgbGlrZSB0aGUgcGxvdCBiZWxvdzogW05vdGU6IEJlIHN1cmUgdG8gZXhhbWluZSB0aGUgcmVzdWx0cyBmcm9tIGVhY2ggc3RlcCB0byBtYWtlIHN1cmUgdGhleSByZWZsZWN0IHdoYXQgeW91IHRoaW5rIHRoZXkgYXJlIV0KCiFbXShJbmNvbWVieVN0YXRlX0NoYWxsZW5nZVByb2JsZW1XZWVrNi5wbmcpCgpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD02fQpnZ3Bsb3QoY2Vuc3VzMjAxNSwgYWVzKHggPSByZW9yZGVyKFN0YXRlLCBJbmNvbWUsIEZVTiA9IG1lZGlhbiksIHkgPSBJbmNvbWUpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUsIGNvbG9yID0gIiM3YTAwMTkiLCBuYS5ybSA9IFRSVUUpICsgCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgTWVkaWFuIEluY29tZSBieSBDb3VudHkgZm9yIEVhY2ggU3RhdGUiLAogICAgICAgeCA9ICJTdGF0ZSIsCiAgICAgICB5ID0gIk1lZGlhbiBIb3VzZWhvbGQgSW5jb21lIikgKyAKICB0aGVtZV9idygpICsgCiAgdGhlbWUoCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUpLAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxLCBzaXplID0gNi44KQogICkKYGBgCgooQCkgKipEYXRhIFZpc3VhbGl6YXRpb24gIzIqKjogQ3JlYXRlIGEgcGxvdCAoZWl0aGVyIGEgaGlzdG9ncmFtLCBhIGJveHBsb3QsIG9yIGEgZGVuc2l0eSBwbG90KSBvZiBtZWRpYW4gaW5jb21lIChgSW5jb21lYCkgd2hlcmUgZWFjaCBzdGF0ZSBoYXMgdGhlaXIgb3duIHBhbmVsLgoKYGBge3IgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KZ2dwbG90KGNlbnN1czIwMTUsIGFlcyh4PSBJbmNvbWUpKSArIAogIGdlb21faGlzdG9ncmFtKGZpbGwgPSAiIzdhMDAxOSIsIGNvbG9yID0gIndoaXRlIiwgYmlucyA9IDIwLCBuYS5ybSA9IFRSVUUpICsgCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgTWVkaWFuIEhvdXNlaG9sZCBJbmNvbWUgYnkgU3RhdGUiLAogICAgICAgeCA9ICJNZWRpYW4gSG91c2Vob2xkIEluY29tZSIsCiAgICAgICB5ID0gIkNvdW50IikgKyAKICB0aGVtZV9idygpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSwKICAgICAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2LjUpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDUpCiAgICAgICAgKSArIAogIGZhY2V0X3dyYXAoflN0YXRlKQpgYGAKCihAKSAqKkRhdGEgVmlzdWFsaXphdGlvbiAjMyoqOiBDcmVhdGUgYSBwbG90IChlaXRoZXIgYSBoaXN0b2dyYW0sIGEgYm94cGxvdCwgb3IgYSBkZW5zaXR5IHBsb3QpIG9mIG1lZGlhbiBpbmNvbWUgKGBJbmNvbWVgKSB3aGVyZSBlYWNoIHN0YXRlIGlzIGxvY2F0ZWQgYXBwcm94aW1hdGVseSBpbiB0aGVpciBvd24gcmVnaW9uIG9mIHRoZSBjb3VudHJ5LiBbTm90ZTogVG8gZG8gdGhpcywgeW91IHdpbGwgbmVlZCB0aGUgZnVuY3Rpb24gYGZhY2V0X2dlbyh+dmFyaWFibGUsIHNjYWxlcz0iZnJlZSIpYCBmcm9tIHRoZSBge2dlb2ZhY2V0fWAgcGFja2FnZV5bUmVzb3VyY2U6IFtJbnRyb2R1Y3Rpb24gdG8gZ2VvZmFjZXRdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nZW9mYWNldC92aWduZXR0ZXMvZ2VvZmFjZXQuaHRtbCkuXV0gQW4gZXhhbXBsZSBvZiB0aGlzIHdpdGggZGVuc2l0eSBwbG90cyBpcyBiZWxvdzogCgohW10oRmFjZXRHZW9fSW5jb21lRGVuc2l0eV9DaGFsbGVuZ2VQcm9ibGVtV2VlazYucG5nKQoKYGBge3IgZmlnLndpZHRoPTIwLCBmaWcuaGVpZ2h0PTE4fQpsaWJyYXJ5KGdlb2ZhY2V0KSAKY2Vuc3VzIDwtIGNlbnN1czIwMTUgJT4lCiAgZmlsdGVyKCFTdGF0ZSAlaW4lIGMoIlB1ZXJ0byBSaWNvIiwgIkRpc3RyaWN0IG9mIENvbHVtYmlhIikpCmdncGxvdChjZW5zdXMsIGFlcyh4ID0gSW5jb21lKSkgKyAKICBnZW9tX2hpc3RvZ3JhbShmaWxsID0gIiM3YTAwMTkiLCBjb2xvciA9ICJ3aGl0ZSIsIGJpbnMgPSAyMCwgbmEucm0gPSBUUlVFKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgTWVkaWFuIEhvdXNlaG9sZCBJbmNvbWUgYnkgU3RhdGUiLAogICAgICAgeCA9ICJNZWRpYW4gSG91c2Vob2xkIEluY29tZSIsCiAgICAgICB5ID0gIkNvdW50IikgKyAKICB0aGVtZV9idygpICsgCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0yNCwgZmFjZSA9ICJib2xkIiwgaGp1c3QgPSAwLjUpLAogICAgICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwgCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA2KSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIGZhY2V0X2dlbyh+U3RhdGUsIHNjYWxlcyA9ICJmcmVlIikKCgoKCmBgYAoK