Exercise 1
Why are our best and most experienced employees leaving prematurely?
The data available here includes information on several current and former employees of an anonymous organization.** Fields in the data-set include:
- satisfaction_level = Level of satisfaction (numeric; 0-1)
- last_evaluation = Evaluation score of the employee (numeric; 0-1)
- number_project = Number of projects completed while at work (numeric)
- average_monthly_hours = Average monthly hours spent at the workplace (numeric)
- time_spend_company = Number of years spent in the company (numeric)
- Work_accident = Whether the employee had a workplace accident (categorical; 1 = yes or 0 = no)
- left = Whether the employee left the workplace or not (categorical; 1 = left or 0 = stayed)
- promotion_last_5years = Whether the employee was promoted in the last five years (categorical; 1 = yes or 0 = no)
- sales = Department in which they work (categorical)
- salary = Relative level of salary (categorical; low, med, and high)
- Read in the csv-format data-set, naming it
hrdata
and save it in RData format as hrdata.RData
- Create new variables that add labels to Work_accident, left, promotion_last_5years, and create a new variable that orders salary from low to high, and add these to
hrdata
.
hrdata %>%
mutate(
had_accident = case_when(
Work_accident == 0 ~ "No",
Work_accident == 1 ~ "Yes"),
left_company = case_when(
left == 0 ~ "No",
left == 1 ~ "Yes"),
recently_promoted = case_when(
promotion_last_5years == 0 ~ "No",
promotion_last_5years == 1 ~ "Yes"),
salary_group = ordered(
salary,
levels = c("low", "medium", "high"),
labels = c("Low", "Medium", "High"))
) -> hrdata
- Convert satisfaction_level from a 0-1 scale to a 0-100 scale, making sure to create a new variable of course.
- Now retain only employees who left the company, and had not been promoted in the last five years. Save this result as
hr01
- In this
hr01
data-set, how many employees do you have per sales department? What sales department has the most number of employees?
## # A tibble: 10 x 2
## sales n
## <chr> <int>
## 1 sales 1007
## 2 technical 694
## 3 support 552
## 4 IT 270
## 5 hr 215
## 6 accounting 204
## 7 marketing 203
## 8 product_mng 198
## 9 RandD 121
## 10 management 88
- By sales department, calculate mean and standard deviation of (i) satisfaction_level, and (ii) last_evaluation.
## # A tibble: 10 x 5
## sales mean.satisfaction sd.satisfaction mean.evaluation sd.evaluation
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 accounting 0.403 0.257 0.695 0.199
## 2 hr 0.433 0.243 0.680 0.197
## 3 IT 0.411 0.273 0.733 0.193
## 4 management 0.410 0.266 0.732 0.204
## 5 marketing 0.453 0.249 0.692 0.200
## 6 product_mng 0.482 0.264 0.727 0.203
## 7 RandD 0.433 0.282 0.745 0.194
## 8 sales 0.447 0.259 0.712 0.198
## 9 support 0.451 0.264 0.728 0.192
## 10 technical 0.434 0.276 0.734 0.198
- What department has the lowest mean satisfaction? How much difference is there in mean satisfaction between departments?
## # A tibble: 10 x 2
## sales mean.satisfaction
## <chr> <dbl>
## 1 accounting 0.403
## 2 management 0.410
## 3 IT 0.411
## 4 RandD 0.433
## 5 hr 0.433
## 6 technical 0.434
## 7 sales 0.447
## 8 support 0.451
## 9 marketing 0.453
## 10 product_mng 0.482
Accounting has the lowest mean satisfaction level. All departments have mean satisfaction in the 0.403 to 0.482 range, so some difference but a huge one.
- Create a new variable that groups average monthly hours into 4 groups. You can let the group cut-points be chosen automatically with
chop_evenly()
. Then show the frequencies of each group.
## # A tibble: 4 x 2
## grouped_hours n
## <fct> <int>
## 1 [126, 172) 1594
## 2 [172, 218) 88
## 3 [218, 264) 1037
## 4 [264, 310] 833
Exercise 2
Thanks to the frenetic work of many individuals, the global spread of the Novel Coronavirus (COVID-19) has been tracked and the data made available for analysis. Yanchang Zhao is one such individual and for this exercise we will use a spcific version of his data that I have named cvdata.RData
and made available via Slack. Make sure to upload that data-set to your RStudio Cloud data
folder, and then to read it in via the load()
command. We can then answer a few questions. Note the contents:
country =
name of the country
date =
date of indidents as recorded
confirmed =
cumulative count of the number of people who tested positive
deaths =
cumulative count of the number of people lost to Covid-19
deaths =
cumulative count of the number of people recovered
- Filter the data-set so that we have only one row per country, the data from March 10, 2020 and call it
cv0310
.
- How many countries have lost
at least one
person to this tragedy? “Others” should not show up as one of the countries.
## # A tibble: 1 x 2
## ncountries n
## <int> <int>
## 1 24 24
- What 10 countries have had the most number of confirmed cases? “Others” should not show up as one of the countries. Also ensure the result is organized in descending order of the number of confirmed cases.
## # A tibble: 10 x 2
## country confirmed
## <fct> <int>
## 1 Mainland China 80757
## 2 Italy 10149
## 3 Iran (Islamic Republic of) 8042
## 4 Republic of Korea 7513
## 5 France 1784
## 6 Spain 1695
## 7 US 1670
## 8 Germany 1457
## 9 Japan 581
## 10 Switzerland 491
- Calculate the
fatality_rate
, defined for our purposes as the percent of deaths. excluding “Others”, and only keeping countried that have had at least 10
confirmed cases, arrange the result to show the top-10 countries in descending order of fatality_rate
.
## # A tibble: 10 x 2
## country fatality_rate
## <fct> <dbl>
## 1 Iraq 9.86
## 2 Italy 6.22
## 3 Argentina 5.88
## 4 San Marino 3.92
## 5 Mainland China 3.88
## 6 Iran (Islamic Republic of) 3.62
## 7 US 3.35
## 8 Philippines 3.03
## 9 Australia 2.80
## 10 Hong Kong SAR 2.5
Say we only want to focus on the Baltic countries (Estonia, Latvia, and Lithuania) as a unified group and compare this group to the ASEAN nations (Brunei, Cambodia, Indonesia, Laos, Malaysia, Myanmar, Philippines, Singapore, Thailand, and Vietnam). Use cv0310
to complete the followng tasks:
- Create a new variable called
region
that only takes on two values – “Baltic” if the country is a Baltic country and “Asean” if the country is an ASEAN country.
- Use this variable to calculate the total number of confirmed cases in each region.
cv0310 %>%
mutate(
region = case_when(
country %in% c("Estonia", "Latvia", "Lithuania") ~ "Baltic",
country %in% c("Brunei", "Cambodia", "Indonesia", "Laos",
"Malaysia", "Myanmar", "Philippines", "Singapore",
"Thailand", "Vietnam") ~ "ASEAN")
) %>%
group_by(region) %>%
summarise(total.confirmed = sum(confirmed))
## # A tibble: 3 x 2
## region total.confirmed
## <chr> <int>
## 1 ASEAN 405
## 2 Baltic 21
## 3 <NA> 118877
LS0tCnRpdGxlOiAiTVBBIDU4MzAgLSBNb2R1bGUgMDIgRXhlcmNpc2VzIgpzdWJ0aXRsZTogIlNwcmluZyAyMDIwIgphdXRob3I6ICJQcm9mZXNzb3IgUnVoaWwiCmRhdGU6ICJVcGRhdGVkIG9uIGByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6IAogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGhpZ2hsaWdodDogemVuYnVybgogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRoZW1lOiBmbGF0bHkKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoKYm9keXsgLyogTm9ybWFsICAqLwovKiAgICBmb250LWZhbWlseTogTGF0bywgc2Fucy1zZXJpZjsgIAogICAgICBmb250LWZhbWlseTogTXVrdGEsIHNhbnMtc2VyaWY7IAogICAgICBmb250LWZhbWlseTogJ051bml0byBTYW5zJywgc2Fucy1zZXJpZjsKICAgICAgZm9udC1mYW1pbHk6IEthcmxhLCBzYW5zLXNlcmlmOyAgKi8KICAgICAgZm9udC1mYW1pbHk6ICdNZXJyaXdlYXRoZXIgU2FucycsIHNhbnMtc2VyaWY7IAogICAgICBmb250LXNpemU6IDE4cHg7CiAgfQoKaDEudGl0bGUgewogIGZvbnQtc2l6ZTogMzhweDsKICBjb2xvcjogRGFya1JlZDsKfQoKaDEgeyAvKiBIZWFkZXIgMSAqLwogIGZvbnQtc2l6ZTogMjhweDsKICBjb2xvcjogRGFya0JsdWU7Cn0KCmgyIHsgLyogSGVhZGVyIDIgKi8KICAgIGZvbnQtc2l6ZTogMjJweDsKICBjb2xvcjogRGFya0JsdWU7Cn0KCmgzIHsgLyogSGVhZGVyIDMgKi8KICBmb250LXNpemU6IDE4cHg7CiAgY29sb3I6IERhcmtCbHVlOwp9Cgpjb2RlLnJ7IC8qIENvZGUgYmxvY2sgKi8KICAgIGZvbnQtZmFtaWx5OiBNdWt0YSwgc2Fucy1zZXJpZjsgCiAgICBmb250LXdlaWdodDogNjAwOyAgCiAgICBmb250LXNpemU6IDE4cHg7Cn0KCi8qIHByZSB7IC8qIENvZGUgYmxvY2sgLSBkZXRlcm1pbmVzIGNvZGUgc3BhY2luZyBiZXR3ZWVuIGxpbmVzICovCiAgICBmb250LXNpemU6IDE2cHg7Cn0gKi8KPC9zdHlsZT4KCgpgYGB7ciBrbGlwcHksIGVjaG8gPSBGQUxTRSwgaW5jbHVkZSA9IFRSVUV9CmtsaXBweTo6a2xpcHB5KHRvb2x0aXBfbWVzc2FnZSA9ICdDbGljayB0byBjb3B5JywgdG9vbHRpcF9zdWNjZXNzID0gJ0RvbmUnLCBjb2xvciA9ICdjb3JuZmxvd2VyYmx1ZScsIHBvc2l0aW9uID0gYygndG9wJywgJ3JpZ2h0JykpCmBgYAoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGRwaSA9IDMwMCwgY2FjaGUgPSBUUlVFLCBmaWcuYWxpZ24gPSAiY2VudGVyIiwgZmlnLndpZHRoID0gMTAsIGZpZy5oZWlnaHQgPSA4LCBvdXQud2lkdGggPSAiMTAwJSIsIGhpZ2hsaWdodCA9IFRSVUUpIApgYGAKCiMgRXhlcmNpc2UgMQpXaHkgYXJlIG91ciBiZXN0IGFuZCBtb3N0IGV4cGVyaWVuY2VkIGVtcGxveWVlcyBsZWF2aW5nIHByZW1hdHVyZWx5PyAKClRoZSBkYXRhIFthdmFpbGFibGUgaGVyZV0oaHR0cHM6Ly9hbmlydWhpbC5naXRodWIuaW8vYXZzci90ZWFjaGluZy9kYXRhdml6L0hSX2NvbW1hX3NlcC5jc3YpIGluY2x1ZGVzIGluZm9ybWF0aW9uIG9uIHNldmVyYWwgY3VycmVudCBhbmQgZm9ybWVyIGVtcGxveWVlcyBvZiBhbiBhbm9ueW1vdXMgb3JnYW5pemF0aW9uLioqIEZpZWxkcyBpbiB0aGUgZGF0YS1zZXQgaW5jbHVkZTogCgorIHNhdGlzZmFjdGlvbl9sZXZlbCA9IExldmVsIG9mIHNhdGlzZmFjdGlvbiAobnVtZXJpYzsgMC0xKSAKKyBsYXN0X2V2YWx1YXRpb24gPSBFdmFsdWF0aW9uIHNjb3JlIG9mIHRoZSBlbXBsb3llZSAobnVtZXJpYzsgMC0xKSAKKyBudW1iZXJfcHJvamVjdCA9IE51bWJlciBvZiBwcm9qZWN0cyBjb21wbGV0ZWQgd2hpbGUgYXQgd29yayAobnVtZXJpYykgCisgYXZlcmFnZV9tb250aGx5X2hvdXJzID0gQXZlcmFnZSBtb250aGx5IGhvdXJzIHNwZW50IGF0IHRoZSB3b3JrcGxhY2UgKG51bWVyaWMpICAKKyB0aW1lX3NwZW5kX2NvbXBhbnkgPSBOdW1iZXIgb2YgeWVhcnMgc3BlbnQgaW4gdGhlIGNvbXBhbnkgKG51bWVyaWMpIAorIFdvcmtfYWNjaWRlbnQgPSBXaGV0aGVyIHRoZSBlbXBsb3llZSBoYWQgYSB3b3JrcGxhY2UgYWNjaWRlbnQgKGNhdGVnb3JpY2FsOyAxID0geWVzIG9yIDAgPSBubykgCisgbGVmdCA9IFdoZXRoZXIgdGhlIGVtcGxveWVlIGxlZnQgdGhlIHdvcmtwbGFjZSBvciBub3QgKGNhdGVnb3JpY2FsOyAxID0gbGVmdCBvciAwID0gc3RheWVkKSAgCisgcHJvbW90aW9uX2xhc3RfNXllYXJzID0gV2hldGhlciB0aGUgZW1wbG95ZWUgd2FzIHByb21vdGVkIGluIHRoZSBsYXN0IGZpdmUgeWVhcnMgKGNhdGVnb3JpY2FsOyAxID0geWVzIG9yIDAgPSBubykgCisgc2FsZXMgPSBEZXBhcnRtZW50IGluIHdoaWNoIHRoZXkgd29yayAoY2F0ZWdvcmljYWwpIAorIHNhbGFyeSA9IFJlbGF0aXZlIGxldmVsIG9mIHNhbGFyeSAoY2F0ZWdvcmljYWw7IGxvdywgbWVkLCBhbmQgaGlnaCkgCgooYSkgUmVhZCBpbiB0aGUgY3N2LWZvcm1hdCBkYXRhLXNldCwgbmFtaW5nIGl0IGBocmRhdGFgIGFuZCBzYXZlIGl0IGluIFJEYXRhIGZvcm1hdCBhcyBgaHJkYXRhLlJEYXRhYCAKCmBgYHtyIGhyZGF0YS1pbn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkodGlkeWxvZykKbGlicmFyeShoZXJlKQpyZWFkX2NzdigKICAiaHR0cHM6Ly9hbmlydWhpbC5naXRodWIuaW8vYXZzci90ZWFjaGluZy9kYXRhdml6L0hSX2NvbW1hX3NlcC5jc3YiCiAgKSAtPiBocmRhdGEKYGBgCgooYikgQ3JlYXRlIG5ldyB2YXJpYWJsZXMgdGhhdCBhZGQgbGFiZWxzIHRvIFdvcmtfYWNjaWRlbnQsIGxlZnQsIHByb21vdGlvbl9sYXN0XzV5ZWFycywgYW5kIGNyZWF0ZSBhIG5ldyB2YXJpYWJsZSB0aGF0IG9yZGVycyBzYWxhcnkgZnJvbSBsb3cgdG8gaGlnaCwgYW5kIGFkZCB0aGVzZSB0byBgaHJkYXRhYC4gIAoKYGBge3IgbXV0MDF9CmhyZGF0YSAlPiUKICBtdXRhdGUoCiAgICBoYWRfYWNjaWRlbnQgPSBjYXNlX3doZW4oCiAgICAgIFdvcmtfYWNjaWRlbnQgPT0gMCB+ICJObyIsCiAgICAgIFdvcmtfYWNjaWRlbnQgPT0gMSB+ICJZZXMiKSwKICAgIGxlZnRfY29tcGFueSA9IGNhc2Vfd2hlbigKICAgICAgbGVmdCA9PSAwIH4gIk5vIiwKICAgICAgbGVmdCA9PSAxIH4gIlllcyIpLAogICAgcmVjZW50bHlfcHJvbW90ZWQgPSBjYXNlX3doZW4oCiAgICAgIHByb21vdGlvbl9sYXN0XzV5ZWFycyA9PSAwIH4gIk5vIiwKICAgICAgcHJvbW90aW9uX2xhc3RfNXllYXJzID09IDEgfiAiWWVzIiksCiAgICBzYWxhcnlfZ3JvdXAgPSBvcmRlcmVkKAogICAgICBzYWxhcnksIAogICAgICBsZXZlbHMgPSBjKCJsb3ciLCAibWVkaXVtIiwgImhpZ2giKSwKICAgICAgbGFiZWxzID0gYygiTG93IiwgIk1lZGl1bSIsICJIaWdoIikpCiAgICApIC0+IGhyZGF0YSAKYGBgCgooYykgQ29udmVydCBzYXRpc2ZhY3Rpb25fbGV2ZWwgZnJvbSBhIDAtMSBzY2FsZSB0byBhIDAtMTAwIHNjYWxlLCBtYWtpbmcgc3VyZSB0byBjcmVhdGUgYSBuZXcgdmFyaWFibGUgb2YgY291cnNlLiAgCgpgYGB7ciBtdXQwMn0KaHJkYXRhICU+JQogIG11dGF0ZSgKICAgIHNhdGxldmVsID0gc2F0aXNmYWN0aW9uX2xldmVsICogMTAwCiAgICApIC0+IGhyZGF0YQpgYGAKCihkKSBOb3cgcmV0YWluIG9ubHkgZW1wbG95ZWVzIHdobyBsZWZ0IHRoZSBjb21wYW55LCBhbmQgaGFkIG5vdCBiZWVuIHByb21vdGVkIGluIHRoZSBsYXN0IGZpdmUgeWVhcnMuIFNhdmUgdGhpcyByZXN1bHQgYXMgYGhyMDFgCgpgYGB7ciBtdXQwM30KaHJkYXRhICU+JQogIGZpbHRlcigKICAgIGxlZnRfY29tcGFueSA9PSAiWWVzIiwKICAgIHJlY2VudGx5X3Byb21vdGVkID09ICJObyIKICAgICkgLT4gaHIwMQpgYGAKCihlKSBJbiB0aGlzIGBocjAxYCBkYXRhLXNldCwgaG93IG1hbnkgZW1wbG95ZWVzIGRvIHlvdSBoYXZlIHBlciBzYWxlcyBkZXBhcnRtZW50PyBXaGF0IHNhbGVzIGRlcGFydG1lbnQgaGFzIHRoZSBtb3N0IG51bWJlciBvZiBlbXBsb3llZXM/IAoKYGBge3IgbXV0MDR9CmhyMDEgJT4lCiAgZ3JvdXBfYnkoc2FsZXMpICU+JQogIHRhbGx5KCkgJT4lCiAgYXJyYW5nZSgtbikKYGBgCgooZikgQnkgc2FsZXMgZGVwYXJ0bWVudCwgY2FsY3VsYXRlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAoaSkgc2F0aXNmYWN0aW9uX2xldmVsLCBhbmQgKGlpKSBsYXN0X2V2YWx1YXRpb24uIAoKYGBge3IgbXV0MDV9CmhyMDEgJT4lCiAgZ3JvdXBfYnkoc2FsZXMpICU+JQogIHN1bW1hcmlzZSgKICAgIG1lYW4uc2F0aXNmYWN0aW9uID0gbWVhbihzYXRpc2ZhY3Rpb25fbGV2ZWwsIG5hLnJtID0gVFJVRSksCiAgICBzZC5zYXRpc2ZhY3Rpb24gPSBzZChzYXRpc2ZhY3Rpb25fbGV2ZWwsIG5hLnJtID0gVFJVRSksCiAgICBtZWFuLmV2YWx1YXRpb24gPSBtZWFuKGxhc3RfZXZhbHVhdGlvbiwgbmEucm0gPSBUUlVFKSwKICAgIHNkLmV2YWx1YXRpb24gPSBzZChsYXN0X2V2YWx1YXRpb24sIG5hLnJtID0gVFJVRSkKICApCmBgYAoKKGcpIFdoYXQgZGVwYXJ0bWVudCBoYXMgdGhlIGxvd2VzdCBtZWFuIHNhdGlzZmFjdGlvbj8gSG93IG11Y2ggZGlmZmVyZW5jZSBpcyB0aGVyZSBpbiBtZWFuIHNhdGlzZmFjdGlvbiBiZXR3ZWVuIGRlcGFydG1lbnRzPyAgCgpgYGB7ciBtdXQwNn0KaHIwMSAlPiUKICBncm91cF9ieShzYWxlcykgJT4lCiAgc3VtbWFyaXNlKG1lYW4uc2F0aXNmYWN0aW9uID0gbWVhbihzYXRpc2ZhY3Rpb25fbGV2ZWwsIG5hLnJtID0gVFJVRSkpICU+JQogIGFycmFuZ2UobWVhbi5zYXRpc2ZhY3Rpb24pCmBgYAoKQWNjb3VudGluZyBoYXMgdGhlIGxvd2VzdCBtZWFuIHNhdGlzZmFjdGlvbiBsZXZlbC4gQWxsIGRlcGFydG1lbnRzIGhhdmUgbWVhbiBzYXRpc2ZhY3Rpb24gaW4gdGhlIDAuNDAzIHRvIDAuNDgyIHJhbmdlLCBzbyBzb21lIGRpZmZlcmVuY2UgYnV0IGEgaHVnZSBvbmUuIAoKKGgpIENyZWF0ZSBhIG5ldyB2YXJpYWJsZSB0aGF0IGdyb3VwcyBhdmVyYWdlIG1vbnRobHkgaG91cnMgaW50byA0IGdyb3Vwcy4gWW91IGNhbiBsZXQgdGhlIGdyb3VwIGN1dC1wb2ludHMgYmUgY2hvc2VuIGF1dG9tYXRpY2FsbHkgd2l0aCBgY2hvcF9ldmVubHkoKWAuIFRoZW4gc2hvdyB0aGUgZnJlcXVlbmNpZXMgb2YgZWFjaCBncm91cC4KCmBgYHtyIGNob3B9CmxpYnJhcnkoc2FudG9rdSkKaHIwMSAlPiUKICBtdXRhdGUoCiAgICBncm91cGVkX2hvdXJzID0gY2hvcF9ldmVubHkoYXZlcmFnZV9tb250bHlfaG91cnMsIGdyb3VwcyA9IDQpCiAgICApIC0+IGhyMDEKCmhyMDEgJT4lCiAgZ3JvdXBfYnkoZ3JvdXBlZF9ob3VycykgJT4lCiAgdGFsbHkoKQpgYGAKCiMgRXhlcmNpc2UgMgpUaGFua3MgdG8gdGhlIGZyZW5ldGljIHdvcmsgb2YgbWFueSBpbmRpdmlkdWFscywgdGhlIGdsb2JhbCBzcHJlYWQgb2YgdGhlIE5vdmVsIENvcm9uYXZpcnVzIChDT1ZJRC0xOSkgaGFzIGJlZW4gdHJhY2tlZCBhbmQgdGhlIGRhdGEgbWFkZSBhdmFpbGFibGUgZm9yIGFuYWx5c2lzLiBbWWFuY2hhbmcgWmhhb10oaHR0cHM6Ly9yZGF0YW1pbmluZy53b3JkcHJlc3MuY29tLzIwMjAvMDMvMTAvY29yb25hdmlydXMtZGF0YS1hbmFseXNpcy13aXRoLXItdGlkeXZlcnNlLWFuZC1nZ3Bsb3QyLykgaXMgb25lIHN1Y2ggaW5kaXZpZHVhbCBhbmQgZm9yIHRoaXMgZXhlcmNpc2Ugd2Ugd2lsbCB1c2UgYSBzcGNpZmljIHZlcnNpb24gb2YgaGlzIGRhdGEgdGhhdCBJIGhhdmUgbmFtZWQgYGN2ZGF0YS5SRGF0YWAgYW5kIG1hZGUgYXZhaWxhYmxlIHZpYSBTbGFjay4gTWFrZSBzdXJlIHRvIHVwbG9hZCB0aGF0IGRhdGEtc2V0IHRvIHlvdXIgUlN0dWRpbyBDbG91ZCBgZGF0YWAgZm9sZGVyLCBhbmQgdGhlbiB0byByZWFkIGl0IGluIHZpYSB0aGUgYGxvYWQoKWAgY29tbWFuZC4gV2UgY2FuIHRoZW4gYW5zd2VyIGEgZmV3IHF1ZXN0aW9ucy4gTm90ZSB0aGUgY29udGVudHM6IAoKKyBgY291bnRyeSA9YCBuYW1lIG9mIHRoZSBjb3VudHJ5IAorIGBkYXRlID1gIGRhdGUgb2YgaW5kaWRlbnRzIGFzIHJlY29yZGVkIAorIGBjb25maXJtZWQgPWAgY3VtdWxhdGl2ZSBjb3VudCBvZiB0aGUgbnVtYmVyIG9mIHBlb3BsZSB3aG8gdGVzdGVkIHBvc2l0aXZlICAKKyBgZGVhdGhzID1gIGN1bXVsYXRpdmUgY291bnQgb2YgdGhlIG51bWJlciBvZiBwZW9wbGUgbG9zdCB0byBDb3ZpZC0xOSAKKyBgZGVhdGhzID1gIGN1bXVsYXRpdmUgY291bnQgb2YgdGhlIG51bWJlciBvZiBwZW9wbGUgcmVjb3ZlcmVkICAKCmBgYHtyIGN2MDF9CmxvYWQoaGVyZSgiZGF0YSIsICJjdmRhdGEuUkRhdGEiKSkKYGBgCgooYSkgRmlsdGVyIHRoZSBkYXRhLXNldCBzbyB0aGF0IHdlIGhhdmUgb25seSBvbmUgcm93IHBlciBjb3VudHJ5LCB0aGUgZGF0YSBmcm9tIE1hcmNoIDEwLCAyMDIwIGFuZCBjYWxsIGl0IGBjdjAzMTBgLiAKCmBgYHtyIGN2MDJ9CmN2ZGF0YSAlPiUKICBmaWx0ZXIoZGF0ZSA9PSAiMjAyMC0wMy0xMCIpIC0+IGN2MDMxMApgYGAKCihiKSBIb3cgbWFueSBjb3VudHJpZXMgaGF2ZSBsb3N0IGBhdCBsZWFzdCBvbmVgIHBlcnNvbiB0byB0aGlzIHRyYWdlZHk/ICJPdGhlcnMiIHNob3VsZCBub3Qgc2hvdyB1cCBhcyBvbmUgb2YgdGhlIGNvdW50cmllcy4gIAoKYGBge3IgY3YwM30KY3YwMzEwICU+JQogIGZpbHRlcihkZWF0aHMgPj0gMSwgY291bnRyeSAhPSAiT3RoZXJzIikgJT4lCiAgY291bnQobmNvdW50cmllcyA9IG5fZGlzdGluY3QoY291bnRyeSkpCmBgYAoKKGMpIFdoYXQgMTAgY291bnRyaWVzIGhhdmUgaGFkIHRoZSBtb3N0IG51bWJlciBvZiBjb25maXJtZWQgY2FzZXM/ICJPdGhlcnMiIHNob3VsZCBub3Qgc2hvdyB1cCBhcyBvbmUgb2YgdGhlIGNvdW50cmllcy4gQWxzbyBlbnN1cmUgdGhlIHJlc3VsdCBpcyBvcmdhbml6ZWQgaW4gZGVzY2VuZGluZyBvcmRlciBvZiB0aGUgbnVtYmVyIG9mIGNvbmZpcm1lZCBjYXNlcy4gCgpgYGB7ciBjdjA0fQpjdjAzMTAgJT4lCiAgZmlsdGVyKGRlYXRocyA+PSAxLCBjb3VudHJ5ICE9ICJPdGhlcnMiKSAlPiUKICBncm91cF9ieShjb3VudHJ5KSAlPiUKICBhcnJhbmdlKC1jb25maXJtZWQpICU+JQogIHNlbGVjdChjb3VudHJ5LCBjb25maXJtZWQpICU+JQogIHVuZ3JvdXAoKSAlPiUKICB0b3BfbigxMCkKYGBgCgooZCkgQ2FsY3VsYXRlIHRoZSBgZmF0YWxpdHlfcmF0ZWAsIGRlZmluZWQgZm9yIG91ciBwdXJwb3NlcyBhcyB0aGUgcGVyY2VudCBvZiBkZWF0aHMuIGV4Y2x1ZGluZyAiT3RoZXJzIiwgYW5kIG9ubHkga2VlcGluZyBjb3VudHJpZWQgdGhhdCBoYXZlIGhhZCBgYXQgbGVhc3QgMTBgIGNvbmZpcm1lZCBjYXNlcywgYXJyYW5nZSB0aGUgcmVzdWx0IHRvIHNob3cgdGhlIHRvcC0xMCBjb3VudHJpZXMgaW4gZGVzY2VuZGluZyBvcmRlciBvZiBgZmF0YWxpdHlfcmF0ZWAuICAKCmBgYHtyIGN2MDV9CmN2MDMxMCAlPiUKICBmaWx0ZXIoY291bnRyeSAhPSAiT3RoZXJzIiwgY29uZmlybWVkID49IDEwKSAlPiUKICBtdXRhdGUoZmF0YWxpdHlfcmF0ZSA9IChkZWF0aHMgLyBjb25maXJtZWQpKjEwMCkgJT4lCiAgZ3JvdXBfYnkoY291bnRyeSkgJT4lCiAgYXJyYW5nZSgtZmF0YWxpdHlfcmF0ZSkgJT4lCiAgc2VsZWN0KGNvdW50cnksIGZhdGFsaXR5X3JhdGUpICU+JQogIHVuZ3JvdXAoKSAlPiUKICB0b3BfbigxMCkKYGBgCgooZSkgU2F5IHdlIG9ubHkgd2FudCB0byBmb2N1cyBvbiB0aGUgQmFsdGljIGNvdW50cmllcyAoRXN0b25pYSwgTGF0dmlhLCBhbmQgTGl0aHVhbmlhKSBhcyBhIHVuaWZpZWQgZ3JvdXAgYW5kIGNvbXBhcmUgdGhpcyBncm91cCB0byB0aGUgQVNFQU4gbmF0aW9ucyAoQnJ1bmVpLCBDYW1ib2RpYSwgSW5kb25lc2lhLCBMYW9zLCBNYWxheXNpYSwgTXlhbm1hciwgUGhpbGlwcGluZXMsIFNpbmdhcG9yZSwgVGhhaWxhbmQsIGFuZCBWaWV0bmFtKS4gVXNlIGBjdjAzMTBgIHRvIGNvbXBsZXRlIHRoZSBmb2xsb3duZyB0YXNrczogCgooaSkgQ3JlYXRlIGEgbmV3IHZhcmlhYmxlIGNhbGxlZCBgcmVnaW9uYCB0aGF0IG9ubHkgdGFrZXMgb24gdHdvIHZhbHVlcyAtLSAiQmFsdGljIiBpZiB0aGUgY291bnRyeSBpcyBhIEJhbHRpYyBjb3VudHJ5IGFuZCAiQXNlYW4iIGlmIHRoZSBjb3VudHJ5IGlzIGFuIEFTRUFOIGNvdW50cnkuIAooaWkpIFVzZSB0aGlzIHZhcmlhYmxlIHRvIGNhbGN1bGF0ZSB0aGUgdG90YWwgbnVtYmVyIG9mIGNvbmZpcm1lZCBjYXNlcyBpbiBlYWNoIHJlZ2lvbi4gCgpgYGB7ciBjdjA2fQpjdjAzMTAgJT4lCiAgbXV0YXRlKAogICAgcmVnaW9uID0gY2FzZV93aGVuKAogICAgICBjb3VudHJ5ICVpbiUgYygiRXN0b25pYSIsICJMYXR2aWEiLCAiTGl0aHVhbmlhIikgfiAiQmFsdGljIiwKICAgICAgY291bnRyeSAlaW4lIGMoIkJydW5laSIsICJDYW1ib2RpYSIsICJJbmRvbmVzaWEiLCAiTGFvcyIsCiAgICAgICAgICAgICAgICAgICAiTWFsYXlzaWEiLCAiTXlhbm1hciIsICJQaGlsaXBwaW5lcyIsICJTaW5nYXBvcmUiLAogICAgICAgICAgICAgICAgICAgIlRoYWlsYW5kIiwgIlZpZXRuYW0iKSB+ICJBU0VBTiIpCiAgICApICU+JQogIGdyb3VwX2J5KHJlZ2lvbikgJT4lCiAgc3VtbWFyaXNlKHRvdGFsLmNvbmZpcm1lZCA9IHN1bShjb25maXJtZWQpKQpgYGAK