Overview
Using one or more TidyVerse packages, and any dataset from fivethirtyeight.com or Kaggle, create a programming sample “vignette” that demonstrates how to use one or more of the capabilities of the selected TidyVerse package with your selected dataset. In this case I selected Kaggle ‘COVID’ datset from Kaggle. The original dataset is from NY times.
Load required libraries
Step 1 is to install and load required libraries to extract data from NY times GIT library
The default packages loaded from the library ‘tidyverse’ are ggplot2, purrr,tibble,dplyr, tidyr, stringr,readr,forcats. My focus is on ggplot2 and dplyr
We will use read.csv() function from readr() package when we load the dataset.
Load the dataset
Raw data looks like this:
It contains time series data containing cumulative counts of coronavirus cases in the United States, at the state and county level, over time.
Data exploration using dplyr
- Filter function in dplyr()
Description Use filter() to choose rows/cases where conditions are true. Unlike base subsetting with [, rows where the condition evaluates to NA are dropped.
|
date
|
county
|
state
|
fips
|
cases
|
deaths
|
|
2020-10-24
|
Autauga
|
Alabama
|
1001
|
2048
|
31
|
|
2020-10-24
|
Baldwin
|
Alabama
|
1003
|
6637
|
69
|
|
2020-10-24
|
Barbour
|
Alabama
|
1005
|
1031
|
9
|
|
2020-10-24
|
Bibb
|
Alabama
|
1007
|
828
|
14
|
|
2020-10-24
|
Blount
|
Alabama
|
1009
|
1925
|
25
|
Now we have latest county level COVID data in the dataset covid_county_latest
- Arrange and group_by functions in dplyr()
Description Order tbl rows by an expression involving its variables.Most data operations are done on groups defined by variables. group_by() takes an existing tbl and converts it into a grouped tbl where operations are performed “by group”. ungroup() removes grouping.
|
date
|
county
|
state
|
fips
|
cases
|
deaths
|
|
2020-10-24
|
Jefferson
|
Alabama
|
1073
|
23129
|
377
|
|
2020-10-24
|
Mobile
|
Alabama
|
1097
|
16849
|
315
|
|
2020-10-24
|
Tuscaloosa
|
Alabama
|
1125
|
10296
|
140
|
|
2020-10-24
|
Montgomery
|
Alabama
|
1101
|
10197
|
197
|
|
2020-10-24
|
Madison
|
Alabama
|
1089
|
9280
|
96
|
We obtained COVID cases sorted by each state from highest to lowest in each of the counties.
- Select and rename functions in dplyr()
Description Choose or rename variables from a tbl. select() keeps only the variables you mention; rename() keeps all variables
|
county
|
state
|
covid_cases
|
covid_deaths
|
|
Jefferson
|
Alabama
|
23129
|
377
|
|
Mobile
|
Alabama
|
16849
|
315
|
|
Tuscaloosa
|
Alabama
|
10296
|
140
|
|
Montgomery
|
Alabama
|
10197
|
197
|
|
Madison
|
Alabama
|
9280
|
96
|
Selected only the required columns and renamed the columns so that it’s more intuitive to understand.
- Summarize function in dplyr()
Description Create one or more scalar variables summarizing the variables of an existing tbl. Tbls with groups created by group_by() will result in one row in the output for each group. Tbls with no groups will result in one row.
|
state
|
US_cases
|
US_deaths
|
|
California
|
906644
|
17345
|
|
Texas
|
906033
|
17998
|
|
Florida
|
776243
|
16416
|
|
New York
|
498568
|
33049
|
|
Illinois
|
376034
|
9765
|
Note that here, we obtained COVID cases by state by applying multiple functions such as arrange,group_by and summarise.
- Mutate function in dplyr()
Description mutate() adds new variables and preserves existing ones; transmute() adds new variables and drops existing ones. Both functions preserve the number of rows of the input. New variables overwrite existing variables of the same name.
|
state
|
US_cases
|
US_deaths
|
mortality_rate
|
cases_density
|
|
California
|
906644
|
17345
|
1.9
|
10.5
|
|
Texas
|
906033
|
17998
|
2.0
|
10.5
|
|
Florida
|
776243
|
16416
|
2.1
|
9.0
|
|
New York
|
498568
|
33049
|
6.6
|
5.8
|
|
Illinois
|
376034
|
9765
|
2.6
|
4.4
|
Mortality rate metric defined as deaths per cases is a better metric to understand the impact of COVID pandemic.
Visualization
- ggplot function in ggplot2 Description ggplot() initializes a ggplot object. It can be used to declare the input data frame for a graphic and to specify the set of plot aesthetics intended to be common throughout all subsequent layers unless specifically overridden.
covid_state %>% arrange(cases_density) %>% mutate(state = fct_reorder(state, cases_density)) %>%
ggplot(aes( x=state,y=cases_density)) +
geom_bar( stat="identity",color="black")+
geom_text(aes(label=paste0(cases_density,"%")),color = "orange",hjust=1,vjust=0.3,size = 3)+
theme( axis.line = element_line(colour = "black",
size = 1, linetype = "solid"))+
coord_flip()+
xlab("")+ ylab("")+
theme( axis.line = element_line(colour = "black",
size =1, linetype = "solid"))+
ggtitle("COVID Density Rate in the US States (as of Oct 24 '20)") +
theme(plot.title = element_text(lineheight=.8, face="bold"))

The graph shows COVID cases spread by states from highest to lowest order. Let’s now plot mortality rate to understand where the cases caused were more deadly.
covid_state %>% arrange(mortality_rate) %>% mutate(state = fct_reorder(state, mortality_rate)) %>%
ggplot(aes( x=state,y=mortality_rate)) +
geom_bar( stat="identity",color="black")+
geom_text(aes(label=paste0(mortality_rate,"%")),color = "orange",hjust=1,vjust=0.3,size = 3)+
theme( axis.line = element_line(colour = "black",
size = 1, linetype = "solid"))+
coord_flip()+
xlab("")+ ylab("")+
theme( axis.line = element_line(colour = "black",
size = 1, linetype = "solid"))+
ggtitle("COVID Mortality Rate in the US States (as of Oct 24 '20)") +
theme(plot.title = element_text(lineheight=.8, face="bold"))

- geom_smooth function in ggplot2 Description Aids the eye in seeing patterns in the presence of overplotting. geom_smooth() and stat_smooth() are effectively aliases: they both use the same arguments. Use stat_smooth() if you want to display the results with a non-standard geom.

Conclusion
There are three clear outliers which are possibly stopping us from understanding the clear relation between mortality rate and case density.
After removing the outliers, the distribution seems more linear where COVID mortality rate is higher in the states with higher COVID density.

LS0tDQp0aXRsZTogJ0Fzc2lnbm1lbnQ6IFRpZHlWZXJzZSBDUkVBVEUgYXNzaWdubWVudCcNCmF1dGhvcjogIkJoYXJhbmkgTml0dGFsYSINCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCINCm91dHB1dDoNCiAgb3BlbmludHJvOjpsYWJfcmVwb3J0OiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50Og0KICAgIGluY2x1ZGVzOg0KICAgICAgaW5faGVhZGVyOiBoZWFkZXIuaHRtbA0KICAgIGNzczogLi9sYWIuY3NzDQogICAgaGlnaGxpZ2h0OiBweWdtZW50cw0KICAgIHRoZW1lOiBjZXJ1bGVhbg0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KZWRpdG9yX29wdGlvbnM6DQogIGNodW5rX291dHB1dF90eXBlOiBjb25zb2xlDQotLS0NCg0KIyMjIE92ZXJ2aWV3DQoNClVzaW5nIG9uZSBvciBtb3JlIFRpZHlWZXJzZSBwYWNrYWdlcywgYW5kIGFueSBkYXRhc2V0IGZyb20gZml2ZXRoaXJ0eWVpZ2h0LmNvbSBvciBLYWdnbGUsIGNyZWF0ZSBhIHByb2dyYW1taW5nIHNhbXBsZSDigJx2aWduZXR0ZeKAnSB0aGF0IGRlbW9uc3RyYXRlcyBob3cgdG8gdXNlIG9uZSBvciBtb3JlIG9mIHRoZSBjYXBhYmlsaXRpZXMgb2YgdGhlIHNlbGVjdGVkIFRpZHlWZXJzZSBwYWNrYWdlIHdpdGggeW91ciBzZWxlY3RlZCBkYXRhc2V0LiBJbiB0aGlzIGNhc2UgSSBzZWxlY3RlZCBLYWdnbGUgJ0NPVklEJyBkYXRzZXQgZnJvbSBbS2FnZ2xlXShodHRwczovL3d3dy5rYWdnbGUuY29tL2ZpcmViYWxsYnllZGlteXJubW9tL3VzLWNvdW50aWVzLWNvdmlkLTE5LWRhdGFzZXQpLiBUaGUgb3JpZ2luYWwgZGF0YXNldCBpcyBmcm9tIE5ZIHRpbWVzLiAgICANCg0KDQojIyMgTG9hZCByZXF1aXJlZCBsaWJyYXJpZXMNCg0KU3RlcCAxIGlzIHRvIGluc3RhbGwgYW5kIGxvYWQgcmVxdWlyZWQgbGlicmFyaWVzIHRvIGV4dHJhY3QgZGF0YSBmcm9tIE5ZIHRpbWVzIEdJVCBsaWJyYXJ5DQoNCmBgYHtyIGxpYnJhcmllcywgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChldmFsID0gVFJVRSwgcmVzdWx0cyA9IEZBTFNFKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpsaWJyYXJ5KHJtYXJrZG93bikNCmxpYnJhcnkoUkN1cmwpDQoNCmBgYA0KDQojIyMjIFRoZSBkZWZhdWx0IHBhY2thZ2VzIGxvYWRlZCBmcm9tIHRoZSBsaWJyYXJ5ICd0aWR5dmVyc2UnIGFyZSAqZ2dwbG90MiosICpwdXJyciosKnRpYmJsZSosKmRwbHlyKiwgKnRpZHlyKiwgKnN0cmluZ3IqLCpyZWFkciosKmZvcmNhdHMqLiBNeSBmb2N1cyBpcyBvbiAqKmdncGxvdDIqKiBhbmQgKipkcGx5cioqDQoNCldlIHdpbGwgdXNlIHJlYWQuY3N2KCkgZnVuY3Rpb24gZnJvbSByZWFkcigpIHBhY2thZ2Ugd2hlbiB3ZSBsb2FkIHRoZSBkYXRhc2V0LiANCg0KDQojIyMgTG9hZCB0aGUgZGF0YXNldA0KDQpSYXcgZGF0YSBsb29rcyBsaWtlIHRoaXM6DQpgYGB7ciAsIG1lc3NhZ2U9RkFMU0UsZWNobz0gRkFMU0V9DQpjb3ZpZF9jb3VudHlfdXJsIDwtIGdldFVSTCgiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL255dGltZXMvY292aWQtMTktZGF0YS9tYXN0ZXIvdXMtY291bnRpZXMuY3N2IikgDQpjb3ZpZF9jb3VudHlfcmF3IDwtIHJlYWQuY3N2KHRleHQgPSBjb3ZpZF9jb3VudHlfdXJsKQ0KDQpoZWFkKGNvdmlkX2NvdW50eV9yYXcsNSkgJT4lIGthYmxlKCkgJT4lIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmaXhlZF90aGVhZCA9IFQpDQpgYGANCg0KSXQgY29udGFpbnMgdGltZSBzZXJpZXMgZGF0YSBjb250YWluaW5nIGN1bXVsYXRpdmUgY291bnRzIG9mIGNvcm9uYXZpcnVzIGNhc2VzIGluIHRoZSBVbml0ZWQgU3RhdGVzLCBhdCB0aGUgc3RhdGUgYW5kIGNvdW50eSBsZXZlbCwgb3ZlciB0aW1lLg0KDQoNCiMjIyBEYXRhIGV4cGxvcmF0aW9uIHVzaW5nIGRwbHlyDQoNClxuDQoxKSBGaWx0ZXIgZnVuY3Rpb24gaW4gZHBseXIoKQ0KIA0KKipEZXNjcmlwdGlvbioqDQpVc2UgZmlsdGVyKCkgdG8gY2hvb3NlIHJvd3MvY2FzZXMgd2hlcmUgY29uZGl0aW9ucyBhcmUgdHJ1ZS4gVW5saWtlIGJhc2Ugc3Vic2V0dGluZyB3aXRoIFssIHJvd3Mgd2hlcmUgdGhlIGNvbmRpdGlvbiBldmFsdWF0ZXMgdG8gTkEgYXJlIGRyb3BwZWQuDQpgYGB7ciAsIG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0iYXNpcyJ9DQpjb3ZpZF9jb3VudHlfbGF0ZXN0ID0gZmlsdGVyKGNvdmlkX2NvdW50eV9yYXcsZGF0ZSA9PSBtYXgoY292aWRfY291bnR5X3JhdyRkYXRlKSkNCmhlYWQoY292aWRfY291bnR5X2xhdGVzdCw1KSAlPiUga2FibGUoKSAlPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZpeGVkX3RoZWFkID0gVCkNCmBgYA0KDQpOb3cgd2UgaGF2ZSBsYXRlc3QgY291bnR5IGxldmVsIENPVklEIGRhdGEgaW4gdGhlIGRhdGFzZXQgY292aWRfY291bnR5X2xhdGVzdA0KDQoyKSBBcnJhbmdlIGFuZCBncm91cF9ieSBmdW5jdGlvbnMgaW4gZHBseXIoKQ0KXG4gDQoNCioqRGVzY3JpcHRpb24qKg0KT3JkZXIgdGJsIHJvd3MgYnkgYW4gZXhwcmVzc2lvbiBpbnZvbHZpbmcgaXRzIHZhcmlhYmxlcy5Nb3N0IGRhdGEgb3BlcmF0aW9ucyBhcmUgZG9uZSBvbiBncm91cHMgZGVmaW5lZCBieSB2YXJpYWJsZXMuIGdyb3VwX2J5KCkgdGFrZXMgYW4gZXhpc3RpbmcgdGJsIGFuZCBjb252ZXJ0cyBpdCBpbnRvIGEgZ3JvdXBlZCB0Ymwgd2hlcmUgb3BlcmF0aW9ucyBhcmUgcGVyZm9ybWVkICJieSBncm91cCIuIHVuZ3JvdXAoKSByZW1vdmVzIGdyb3VwaW5nLg0KYGBge3IgLCBtZXNzYWdlPUZBTFNFLHJlc3VsdHM9ImFzaXMifQ0KY292aWRfY291bnR5X2xhdGVzdCA8LSBjb3ZpZF9jb3VudHlfbGF0ZXN0ICU+JSBncm91cF9ieShzdGF0ZSkgICU+JSBhcnJhbmdlKGRlc2MoY2FzZXMpLCAuYnlfZ3JvdXAgPSBUUlVFKQ0KaGVhZChjb3ZpZF9jb3VudHlfbGF0ZXN0LDUpICU+JSBrYWJsZSgpICU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgZml4ZWRfdGhlYWQgPSBUKQ0KYGBgDQoNCldlIG9idGFpbmVkIENPVklEIGNhc2VzIHNvcnRlZCBieSBlYWNoIHN0YXRlIGZyb20gaGlnaGVzdCB0byBsb3dlc3QgaW4gZWFjaCBvZiB0aGUgY291bnRpZXMuIA0KDQpcbg0KMykgU2VsZWN0IGFuZCByZW5hbWUgZnVuY3Rpb25zIGluIGRwbHlyKCkNCg0KKipEZXNjcmlwdGlvbioqDQpDaG9vc2Ugb3IgcmVuYW1lIHZhcmlhYmxlcyBmcm9tIGEgdGJsLiBzZWxlY3QoKSBrZWVwcyBvbmx5IHRoZSB2YXJpYWJsZXMgeW91IG1lbnRpb247IHJlbmFtZSgpIGtlZXBzIGFsbCB2YXJpYWJsZXMNCmBgYHtyICwgbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSJhc2lzIn0NCmNvdmlkX2NvdW50eV9sYXRlc3QgPC0gY292aWRfY291bnR5X2xhdGVzdCU+JXNlbGVjdChjb3VudHksc3RhdGUsY2FzZXMsZGVhdGhzKQ0KY292aWRfY291bnR5X2xhdGVzdCA8LSByZW5hbWUoY292aWRfY291bnR5X2xhdGVzdCxjb3ZpZF9jYXNlcyA9IGNhc2VzLGNvdmlkX2RlYXRocyA9IGRlYXRocykNCmhlYWQoY292aWRfY291bnR5X2xhdGVzdCw1KSAlPiUga2FibGUoKSAlPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZpeGVkX3RoZWFkID0gVCkNCmBgYA0KDQpTZWxlY3RlZCBvbmx5IHRoZSByZXF1aXJlZCBjb2x1bW5zIGFuZCByZW5hbWVkIHRoZSBjb2x1bW5zIHNvIHRoYXQgaXQncyBtb3JlIGludHVpdGl2ZSB0byB1bmRlcnN0YW5kLg0KDQpcbg0KNCkgU3VtbWFyaXplIGZ1bmN0aW9uIGluIGRwbHlyKCkNCg0KKipEZXNjcmlwdGlvbioqDQpDcmVhdGUgb25lIG9yIG1vcmUgc2NhbGFyIHZhcmlhYmxlcyBzdW1tYXJpemluZyB0aGUgdmFyaWFibGVzIG9mIGFuIGV4aXN0aW5nIHRibC4gVGJscyB3aXRoIGdyb3VwcyBjcmVhdGVkIGJ5IGdyb3VwX2J5KCkgd2lsbCByZXN1bHQgaW4gb25lIHJvdyBpbiB0aGUgb3V0cHV0IGZvciBlYWNoIGdyb3VwLiBUYmxzIHdpdGggbm8gZ3JvdXBzIHdpbGwgcmVzdWx0IGluIG9uZSByb3cuDQpgYGB7ciAsIG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0iYXNpcyJ9DQoNCmNvdmlkX3N0YXRlIDwtIGNvdmlkX2NvdW50eV9sYXRlc3QgJT4lIGdyb3VwX2J5KHN0YXRlKSAlPiUgc3VtbWFyaXNlKFVTX2Nhc2VzID0gc3VtKGNvdmlkX2Nhc2VzKSxVU19kZWF0aHMgPSBzdW0oY292aWRfZGVhdGhzKSkgJT4lICBhcnJhbmdlKGRlc2MoVVNfY2FzZXMpLCAuYnlfZ3JvdXAgPSBUUlVFKQ0KaGVhZChjb3ZpZF9zdGF0ZSw1KSAlPiUga2FibGUoKSAlPiUga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZpeGVkX3RoZWFkID0gVCkNCg0KYGBgDQoNCk5vdGUgdGhhdCBoZXJlLCB3ZSBvYnRhaW5lZCBDT1ZJRCBjYXNlcyBieSBzdGF0ZSBieSBhcHBseWluZyBtdWx0aXBsZSBmdW5jdGlvbnMgc3VjaCBhcyBhcnJhbmdlLGdyb3VwX2J5IGFuZCBzdW1tYXJpc2UuIA0KDQo1KSBNdXRhdGUgZnVuY3Rpb24gaW4gZHBseXIoKQ0KDQoqKkRlc2NyaXB0aW9uKioNCm11dGF0ZSgpIGFkZHMgbmV3IHZhcmlhYmxlcyBhbmQgcHJlc2VydmVzIGV4aXN0aW5nIG9uZXM7IHRyYW5zbXV0ZSgpIGFkZHMgbmV3IHZhcmlhYmxlcyBhbmQgZHJvcHMgZXhpc3Rpbmcgb25lcy4gQm90aCBmdW5jdGlvbnMgcHJlc2VydmUgdGhlIG51bWJlciBvZiByb3dzIG9mIHRoZSBpbnB1dC4gTmV3IHZhcmlhYmxlcyBvdmVyd3JpdGUgZXhpc3RpbmcgdmFyaWFibGVzIG9mIHRoZSBzYW1lIG5hbWUuDQpgYGB7ciAsIG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0iYXNpcyJ9DQoNCmNvdmlkX3N0YXRlIDwtIGNvdmlkX3N0YXRlICU+JSBtdXRhdGUobW9ydGFsaXR5X3JhdGUgPSByb3VuZCgoVVNfZGVhdGhzKjEwMCkvVVNfY2FzZXMsMSksY2FzZXNfZGVuc2l0eSA9IHJvdW5kKFVTX2Nhc2VzKjEwMC9zdW0oVVNfY2FzZXMpLDEpKSANCmhlYWQoY292aWRfc3RhdGUsNSkgJT4lIGthYmxlKCkgJT4lIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCBmaXhlZF90aGVhZCA9IFQpDQoNCmBgYA0KDQoNCk1vcnRhbGl0eSByYXRlIG1ldHJpYyBkZWZpbmVkIGFzIGRlYXRocyBwZXIgY2FzZXMgaXMgYSBiZXR0ZXIgbWV0cmljIHRvIHVuZGVyc3RhbmQgdGhlIGltcGFjdCBvZiBDT1ZJRCBwYW5kZW1pYy4gDQoNCiMjIyBWaXN1YWxpemF0aW9uDQoNCjEpIGdncGxvdCBmdW5jdGlvbiBpbiBnZ3Bsb3QyDQpcbg0KKipEZXNjcmlwdGlvbioqDQpnZ3Bsb3QoKSBpbml0aWFsaXplcyBhIGdncGxvdCBvYmplY3QuIEl0IGNhbiBiZSB1c2VkIHRvIGRlY2xhcmUgdGhlIGlucHV0IGRhdGEgZnJhbWUgZm9yIGEgZ3JhcGhpYyBhbmQgdG8gc3BlY2lmeSB0aGUgc2V0IG9mIHBsb3QgYWVzdGhldGljcyBpbnRlbmRlZCB0byBiZSBjb21tb24gdGhyb3VnaG91dCBhbGwgc3Vic2VxdWVudCBsYXllcnMgdW5sZXNzIHNwZWNpZmljYWxseSBvdmVycmlkZGVuLg0KYGBge3IgLCBtZXNzYWdlPUZBTFNFLHJlc3VsdHM9ImFzaXMifQ0KDQpjb3ZpZF9zdGF0ZSAlPiUgYXJyYW5nZShjYXNlc19kZW5zaXR5KSAlPiUgIG11dGF0ZShzdGF0ZSA9IGZjdF9yZW9yZGVyKHN0YXRlLCBjYXNlc19kZW5zaXR5KSkgJT4lDQpnZ3Bsb3QoYWVzKCB4PXN0YXRlLHk9Y2FzZXNfZGVuc2l0eSkpICsgDQogICAgZ2VvbV9iYXIoIHN0YXQ9ImlkZW50aXR5Iixjb2xvcj0iYmxhY2siKSsNCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsPXBhc3RlMChjYXNlc19kZW5zaXR5LCIlIikpLGNvbG9yID0gIm9yYW5nZSIsaGp1c3Q9MSx2anVzdD0wLjMsc2l6ZSA9IDMpKw0KICB0aGVtZSggYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLCBsaW5ldHlwZSA9ICJzb2xpZCIpKSsNCiAgY29vcmRfZmxpcCgpKw0KICAgIHhsYWIoIiIpKyB5bGFiKCIiKSsNCiAgdGhlbWUoIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0xLCBsaW5ldHlwZSA9ICJzb2xpZCIpKSsNCiAgIGdndGl0bGUoIkNPVklEIERlbnNpdHkgUmF0ZSBpbiB0aGUgVVMgU3RhdGVzIChhcyBvZiBPY3QgMjQgJzIwKSIpICsgDQogICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIpKQ0KDQpgYGANCg0KVGhlIGdyYXBoIHNob3dzIENPVklEIGNhc2VzIHNwcmVhZCBieSBzdGF0ZXMgZnJvbSBoaWdoZXN0IHRvIGxvd2VzdCBvcmRlci4gTGV0J3Mgbm93IHBsb3QgbW9ydGFsaXR5IHJhdGUgdG8gdW5kZXJzdGFuZCB3aGVyZSB0aGUgY2FzZXMgY2F1c2VkIHdlcmUgbW9yZSBkZWFkbHkuIA0KDQpgYGB7ciAsIG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0iYXNpcyJ9DQoNCmNvdmlkX3N0YXRlICU+JSBhcnJhbmdlKG1vcnRhbGl0eV9yYXRlKSAlPiUgIG11dGF0ZShzdGF0ZSA9IGZjdF9yZW9yZGVyKHN0YXRlLCBtb3J0YWxpdHlfcmF0ZSkpICU+JQ0KZ2dwbG90KGFlcyggeD1zdGF0ZSx5PW1vcnRhbGl0eV9yYXRlKSkgKyANCiAgICBnZW9tX2Jhciggc3RhdD0iaWRlbnRpdHkiLGNvbG9yPSJibGFjayIpKw0KICAgIGdlb21fdGV4dChhZXMobGFiZWw9cGFzdGUwKG1vcnRhbGl0eV9yYXRlLCIlIikpLGNvbG9yID0gIm9yYW5nZSIsaGp1c3Q9MSx2anVzdD0wLjMsc2l6ZSA9IDMpKw0KICB0aGVtZSggYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIsIA0KICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLCBsaW5ldHlwZSA9ICJzb2xpZCIpKSsNCiAgY29vcmRfZmxpcCgpKw0KICAgIHhsYWIoIiIpKyB5bGFiKCIiKSsNCiAgdGhlbWUoIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siLCANCiAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMSwgbGluZXR5cGUgPSAic29saWQiKSkrDQogICBnZ3RpdGxlKCJDT1ZJRCBNb3J0YWxpdHkgUmF0ZSBpbiB0aGUgVVMgU3RhdGVzIChhcyBvZiBPY3QgMjQgJzIwKSIpICsgDQogICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIpKQ0KDQpgYGANCg0KMikgZ2VvbV9zbW9vdGggZnVuY3Rpb24gaW4gZ2dwbG90Mg0KXG4NCioqRGVzY3JpcHRpb24qKg0KQWlkcyB0aGUgZXllIGluIHNlZWluZyBwYXR0ZXJucyBpbiB0aGUgcHJlc2VuY2Ugb2Ygb3ZlcnBsb3R0aW5nLiBnZW9tX3Ntb290aCgpIGFuZCBzdGF0X3Ntb290aCgpIGFyZSBlZmZlY3RpdmVseSBhbGlhc2VzOiB0aGV5IGJvdGggdXNlIHRoZSBzYW1lIGFyZ3VtZW50cy4gVXNlIHN0YXRfc21vb3RoKCkgaWYgeW91IHdhbnQgdG8gZGlzcGxheSB0aGUgcmVzdWx0cyB3aXRoIGEgbm9uLXN0YW5kYXJkIGdlb20uDQpgYGB7ciAsIG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0iYXNpcyJ9DQoNCmdncGxvdChjb3ZpZF9zdGF0ZSwgYWVzKHggPSBtb3J0YWxpdHlfcmF0ZSAsIHk9IGNhc2VzX2RlbnNpdHkpKSArIGdlb21fcG9pbnQoKSArIGdlb21fc21vb3RoKG1ldGhvZD1sbSkrDQogICBnZ3RpdGxlKCJDT1ZJRCBNb3J0YWxpdHkgUmF0ZSB2cyBDT1ZJRCBDYXNlIERlbnNpdHkgaW4gdGhlIFVTIFN0YXRlcyIpICsgDQogICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQobGluZWhlaWdodD0uOCwgZmFjZT0iYm9sZCIpKQ0KDQpgYGANCg0KDQojIyMgQ29uY2x1c2lvbg0KDQpUaGVyZSBhcmUgdGhyZWUgY2xlYXIgb3V0bGllcnMgd2hpY2ggYXJlIHBvc3NpYmx5IHN0b3BwaW5nIHVzIGZyb20gdW5kZXJzdGFuZGluZyB0aGUgY2xlYXIgcmVsYXRpb24gYmV0d2VlbiBtb3J0YWxpdHkgcmF0ZSBhbmQgY2FzZSBkZW5zaXR5Lg0KDQpBZnRlciByZW1vdmluZyB0aGUgb3V0bGllcnMsIHRoZSBkaXN0cmlidXRpb24gc2VlbXMgbW9yZSBsaW5lYXIgd2hlcmUgQ09WSUQgbW9ydGFsaXR5IHJhdGUgaXMgaGlnaGVyIGluIHRoZSBzdGF0ZXMgd2l0aCBoaWdoZXIgQ09WSUQgZGVuc2l0eS4gDQpgYGB7ciAsIG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0iYXNpcyJ9DQoNCmdncGxvdChzdWJzZXQoY292aWRfc3RhdGUsY2FzZXNfZGVuc2l0eSA8NiksIGFlcyh4ID0gbW9ydGFsaXR5X3JhdGUgLCB5PSBjYXNlc19kZW5zaXR5KSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aChtZXRob2Q9IGxtKSsNCiAgIGdndGl0bGUoIkNPVklEIE1vcnRhbGl0eSBSYXRlIHZzIENPVklEIENhc2UgRGVuc2l0eSBpbiB0aGUgVVMgU3RhdGVzIikgKyANCiAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChsaW5laGVpZ2h0PS44LCBmYWNlPSJib2xkIikpDQoNCmBgYA0KDQoNCg==