Download Data Files
In these exercises we will see the power of the libraries
ggplot2
and plotly
to make sense of
statistical data. The goal is to reproduce the moving chart that you can
see in this video from Hans Rosling – I invite you to watch his other
videos, they are quite enlightening and inspiring:
For this, we will need to gather the data:
Data handling
The first thing to do is to load and regroup all these datasets into
a single one.
Load the tidyverse
library and, using
read_csv()
, load the 4 datasets in 4 separate tibbles
called children
, income
, pop
and
religion
.
To reproduce the chart on the video, we need to determine the
dominant religion in each country. In the religion
dataset,
add a column Religion
that will give the name of the
dominant religion for each country. For this, you need to make the table
contain just the Country
and all religions, make the table
tidy, and then select the religion with the highest proportion for each
country. We will filter the data to get only the year 2020.
Using pivot_longer()
, make all datasets
tidy.
children
should now contain 3 columns:
Country
, Year
and Fertility
.
income
should now contain 3 columns:
Country
, Year
and Income
.
pop
should now contain 3 columns: Country
,
Year
and Population
.
We will only consider data from 1900 to 2018. Example of syntax using
the pipe operator |>
:
DF <- read_table ("name 2010 2011 2012 2014
Kevin 10 11 12 123
Jane 122 56 23 4
"
)
DF
## # A tibble: 2 Ă— 5
## name `2010` `2011` `2012` `2014`
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Kevin 10 11 12 123
## 2 Jane 122 56 23 4
DF |>
select (name, '2010' : '2012' ) |>
pivot_longer (col= - name,
names_to= "Year" ,
values_to= "Score" ,
names_transform= list (Year = as.numeric))
## # A tibble: 6 Ă— 3
## name Year Score
## <chr> <dbl> <dbl>
## 1 Kevin 2010 10
## 2 Kevin 2011 11
## 3 Kevin 2012 12
## 4 Jane 2010 122
## 5 Jane 2011 56
## 6 Jane 2012 23
The line names_transform=list(Year = as.numeric)
is here
to convert the character year values to numerical values.
Now we want to combine all these datasets into a single one called
dat
, containing the columns Country
,
Year
, Population
, Religion
,
Fertility
and Income
. Look into the
inner_join()
function of the dplyr
library
(which is part of the tidyverse
library).
You should end up with a dataset like this one:
## # A tibble: 20,587 Ă— 6
## Country Year Fertility Income Population Religion
## <chr> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 Afghanistan 1900 7 793 5020000 Muslims
## 2 Afghanistan 1901 7 796 5050000 Muslims
## 3 Afghanistan 1902 7 798 5090000 Muslims
## 4 Afghanistan 1903 7 801 5120000 Muslims
## 5 Afghanistan 1904 7 804 5150000 Muslims
## 6 Afghanistan 1905 7 807 5180000 Muslims
## 7 Afghanistan 1906 7 809 5220000 Muslims
## 8 Afghanistan 1907 7 812 5250000 Muslims
## 9 Afghanistan 1908 7 815 5280000 Muslims
## 10 Afghanistan 1909 7 818 5320000 Muslims
## # ℹ 20,577 more rows
In case you struggled to get there, download the archive with the
button at the top and get the dat
tibble with dat <- read_csv ("Data/dat.csv" )
.
Now our dataset is ready, let’s plot it.
Plotting
Load the library ggplot2
and set the global theme to
theme_bw()
using theme_set()
Create a subset of dat
concerning your origin
country. For me it will be dat_france
Plot the evolution of the income per capita and the number of
children per woman as a function of the years, and make it look like
that (notice the kinks during the two world wars):
Create a subset of dat
containing the data for your
country plus all the neighbor countries (if you come from an island, the
nearest countries…). For me, dat_france_region
will contain
data from France, Spain, Italy, Switzerland, Germany, Luxembourg and
Belgium.
Plot again income and fertility as a function of the years, but
add a color corresponding to the country and a point size to its
population:
Load the library plotly
and make the previous graphs
interactive. You can make an interactive graph by calling
ggplotly()
, like that:
library (plotly)
P <- ggplot (data = dat_france, aes (x= Population, y= Income))+
geom_point ()
ggplotly (P) # add dynamicTicks=TRUE allows redrawing ticks when zooming in
Finally, you can add a slider to the interactive graph allowing
selecting a value for another variable (just like in the video) by
adding the keyword frame =
in the chart’s aesthetics. So
now, make the graph of the video ! (you can also add the aesthetics
id=Country
to show the country name in the popup when
hovering on a point).
LS0tCnRpdGxlIDogIlIgRXhlcmNpc2VzIC0gUmVsaWdpb24gYW5kIGJhYmllcyIKZGF0ZSAgOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogCiAgICBodG1sX2RvY3VtZW50OgogICAgICAgIHRvYyAgICAgICAgICAgIDogdHJ1ZQogICAgICAgIHRvY19mbG9hdCAgICAgIDogdHJ1ZQogICAgICAgIHRvY19kZXB0aCAgICAgIDogNAogICAgICAgIGhpZ2hsaWdodCAgICAgIDogdGFuZ28KICAgICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgICAgICBjb2RlX2Rvd25sb2FkICA6IHRydWUKcGFyYW1zOiAKICAgIHNvbHV0aW9uOgogICAgICAgIHZhbHVlOiBmYWxzZQotLS0KCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5hbGlnbj0iY2VudGVyIn0KbGlicmFyeShkb3dubG9hZHRoaXMpCmRvd25sb2FkX2xpbmsoCiAgbGluayA9ICIuL0FyY2hpdmUuemlwIiwKICBvdXRwdXRfbmFtZSA9ICJEYXRhIEZpbGVzIiwKICBidXR0b25fbGFiZWwgPSAiRG93bmxvYWQgRGF0YSBGaWxlcyIsCiAgYnV0dG9uX3R5cGUgPSAiZGVmYXVsdCIsCiAgaGFzX2ljb24gPSBUUlVFLAogIGljb24gPSAiZmEgZmEtc2F2ZSIsCiAgc2VsZl9jb250YWluZWQgPSBGQUxTRQopCmBgYAo8YnI+CgotLS0tCgpJbiB0aGVzZSBleGVyY2lzZXMgd2Ugd2lsbCBzZWUgdGhlIHBvd2VyIG9mIHRoZSBsaWJyYXJpZXMgYGdncGxvdDJgIGFuZCBgcGxvdGx5YCB0byBtYWtlIHNlbnNlIG9mIHN0YXRpc3RpY2FsIGRhdGEuIFRoZSBnb2FsIGlzIHRvIHJlcHJvZHVjZSB0aGUgbW92aW5nIGNoYXJ0IHRoYXQgeW91IGNhbiBzZWUgaW4gdGhpcyB2aWRlbyBmcm9tIEhhbnMgUm9zbGluZyAtLSBJIGludml0ZSB5b3UgdG8gd2F0Y2ggaGlzIG90aGVyIHZpZGVvcywgdGhleSBhcmUgcXVpdGUgZW5saWdodGVuaW5nIGFuZCBpbnNwaXJpbmc6Cgo8ZGl2IHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij4KPGEgaHJlZj0iaHR0cHM6Ly93d3cudGVkLmNvbS90YWxrcy9oYW5zX3Jvc2xpbmdfcmVsaWdpb25zX2FuZF9iYWJpZXM/bGFuZ3VhZ2U9ZW4iIHRhcmdldD0iX2JsYW5rIj4KPGkgY2xhc3M9ImZhYiBmYS15b3V0dWJlIGZhLTV4Ij48L2k+CjwvYT4KPC9kaXY+Cgo8YnI+Cjxicj4KCkZvciB0aGlzLCB3ZSB3aWxsIG5lZWQgdG8gZ2F0aGVyIHRoZSBkYXRhOgoKLSBGcm9tIFtHYXBtaW5kZXJdKGh0dHBzOi8vd3d3LmdhcG1pbmRlci5vcmcvZGF0YS8pLCBkYXRhIHBlciBjb3VudHJ5IGFuZCBwZXIgeWVhciBmcm9tIDE4MDAgdG8gMjAxODoKICAgIC0gW1RoZSBjaGlsZHJlbiBwZXIgd29tYW4gdG90YWwgZmVydGlsaXR5XShEYXRhL2NoaWxkcmVuX3Blcl93b21hbl90b3RhbF9mZXJ0aWxpdHkuY3N2KQogICAgLSBbVGhlIGluY29tZSBwZXIgY2FwaXRhXShEYXRhL2luY29tZV9wZXJfcGVyc29uX2dkcHBlcmNhcGl0YV9wcHBfaW5mbGF0aW9uX2FkanVzdGVkLmNzdikKICAgIC0gW1RoZSB0b3RhbCBwb3B1bGF0aW9uXShEYXRhL3BvcHVsYXRpb25fdG90YWwuY3N2KQotIEZyb20gdGhlIFtQRVcgcmVzZWFyY2ggY2VudGVyXShodHRwczovL3d3dy5wZXdmb3J1bS5vcmcvMjAxNS8wNC8wMi9yZWxpZ2lvdXMtcHJvamVjdGlvbi10YWJsZS8yMDEwL3BlcmNlbnQvYWxsLyksIGRhdGEgcGVyIGNvdW50cnk6CiAgICArIFtUaGUgcmVsaWdpb3VzIGNvbXBvc2l0aW9uXShEYXRhL3JlbGlnaW9uLmNzdikKCi0tLS0tLS0gCgojIERhdGEgaGFuZGxpbmcKClRoZSBmaXJzdCB0aGluZyB0byBkbyBpcyB0byBsb2FkIGFuZCByZWdyb3VwIGFsbCB0aGVzZSBkYXRhc2V0cyBpbnRvIGEgc2luZ2xlIG9uZS4KCjEuIExvYWQgdGhlIGB0aWR5dmVyc2VgIGxpYnJhcnkgYW5kLCB1c2luZyBgcmVhZF9jc3YoKWAsIGxvYWQgdGhlIDQgZGF0YXNldHMgaW4gNCBzZXBhcmF0ZSB0aWJibGVzIGNhbGxlZCBgY2hpbGRyZW5gLCBgaW5jb21lYCwgYHBvcGAgYW5kIGByZWxpZ2lvbmAuCgpgYGB7ciBpbmNsdWRlPXBhcmFtcyRzb2x1dGlvbiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocmVhZHhsKQpjaGlsZHJlbiA8LSByZWFkX2NzdigiRGF0YS9jaGlsZHJlbl9wZXJfd29tYW5fdG90YWxfZmVydGlsaXR5LmNzdiIpCmluY29tZSAgIDwtIHJlYWRfY3N2KCJEYXRhL2luY29tZV9wZXJfcGVyc29uX2dkcHBlcmNhcGl0YV9wcHBfaW5mbGF0aW9uX2FkanVzdGVkLmNzdiIpCnBvcCAgICAgIDwtIHJlYWRfY3N2KCJEYXRhL3BvcHVsYXRpb25fdG90YWwuY3N2IikKcmVsaWdpb24gPC0gcmVhZF9jc3YoIkRhdGEvcmVsaWdpb24uY3N2IikKYGBgCgoyLiBUbyByZXByb2R1Y2UgdGhlIGNoYXJ0IG9uIHRoZSB2aWRlbywgd2UgbmVlZCB0byBkZXRlcm1pbmUgdGhlIGRvbWluYW50IHJlbGlnaW9uIGluIGVhY2ggY291bnRyeS4gSW4gdGhlIGByZWxpZ2lvbmAgZGF0YXNldCwgYWRkIGEgY29sdW1uIGBSZWxpZ2lvbmAgdGhhdCB3aWxsIGdpdmUgdGhlIG5hbWUgb2YgdGhlIGRvbWluYW50IHJlbGlnaW9uIGZvciBlYWNoIGNvdW50cnkuIEZvciB0aGlzLCB5b3UgbmVlZCB0byBtYWtlIHRoZSB0YWJsZSBjb250YWluIGp1c3QgdGhlIGBDb3VudHJ5YCBhbmQgYWxsIHJlbGlnaW9ucywgbWFrZSB0aGUgdGFibGUgdGlkeSwgYW5kIHRoZW4gc2VsZWN0IHRoZSByZWxpZ2lvbiB3aXRoIHRoZSBoaWdoZXN0IHByb3BvcnRpb24gZm9yIGVhY2ggY291bnRyeS4gV2Ugd2lsbCBmaWx0ZXIgdGhlIGRhdGEgdG8gZ2V0IG9ubHkgdGhlIHllYXIgMjAyMC4KCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPUZBTFNFfQpyZWxpZ2lvbiA8LSByZWxpZ2lvbiB8PgogICAgICAgIGZpbHRlcihZZWFyPT0yMDIwKSB8PgogICAgICAgIHNlbGVjdChDb3VudHJ5LCBCdWRkaGlzdHM6VW5hZmZpbGlhdGVkKSB8PiAKICAgICAgICBwaXZvdF9sb25nZXIoY29scz0tQ291bnRyeSwgCiAgICAgICAgICAgICAgICAgICAgIG5hbWVzX3RvPSJSZWxpZ2lvbiIsIAogICAgICAgICAgICAgICAgICAgICB2YWx1ZXNfdG89IlByb3BvcnRpb24iKSB8PgogICAgICAgIGZpbHRlciguYnkgPSBDb3VudHJ5LAogICAgICAgICAgICAgICBQcm9wb3J0aW9uPT1tYXgoUHJvcG9ydGlvbikpIHw+CiAgICAgICAgc2VsZWN0KC1Qcm9wb3J0aW9uKQpgYGAKCjMuIFVzaW5nIGBwaXZvdF9sb25nZXIoKWAsIG1ha2UgYWxsIGRhdGFzZXRzIHRpZHkuIAoKLSBgY2hpbGRyZW5gIHNob3VsZCBub3cgY29udGFpbiAzIGNvbHVtbnM6IGBDb3VudHJ5YCwgYFllYXJgIGFuZCBgRmVydGlsaXR5YC4gCi0gYGluY29tZWAgc2hvdWxkIG5vdyBjb250YWluIDMgY29sdW1uczogYENvdW50cnlgLCBgWWVhcmAgYW5kIGBJbmNvbWVgLiAKLSBgcG9wYCBzaG91bGQgbm93IGNvbnRhaW4gMyBjb2x1bW5zOiBgQ291bnRyeWAsIGBZZWFyYCBhbmQgYFBvcHVsYXRpb25gLiAKCldlIHdpbGwgb25seSBjb25zaWRlciBkYXRhIGZyb20gMTkwMCB0byAyMDE4LiBFeGFtcGxlIG9mIHN5bnRheCB1c2luZyB0aGUgcGlwZSBvcGVyYXRvciBgfD5gOgoKYGBge3J9CkRGIDwtIHJlYWRfdGFibGUoIm5hbWUgIDIwMTAgIDIwMTEgIDIwMTIgIDIwMTQKS2V2aW4gIDEwICAgIDExICAgMTIgICAxMjMKSmFuZSAgIDEyMiAgIDU2ICAgMjMgICA0CiIKKQpERgpERiB8PiAKICAgIHNlbGVjdChuYW1lLCAnMjAxMCc6JzIwMTInKSB8PiAKICAgIHBpdm90X2xvbmdlcihjb2w9LW5hbWUsCiAgICAgICAgICAgICAgICAgbmFtZXNfdG89IlllYXIiLCAKICAgICAgICAgICAgICAgICB2YWx1ZXNfdG89IlNjb3JlIiwKICAgICAgICAgICAgICAgICBuYW1lc190cmFuc2Zvcm09bGlzdChZZWFyID0gYXMubnVtZXJpYykpCmBgYApUaGUgbGluZSBgbmFtZXNfdHJhbnNmb3JtPWxpc3QoWWVhciA9IGFzLm51bWVyaWMpYCBpcyBoZXJlIHRvIGNvbnZlcnQgdGhlIGNoYXJhY3RlciB5ZWFyIHZhbHVlcyB0byBudW1lcmljYWwgdmFsdWVzLgoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmNoaWxkcmVuIDwtIGNoaWxkcmVuIHw+IAogICAgICAgICAgICAgICAgc2VsZWN0KENvdW50cnksICcxOTAwJzonMjAxOCcpIHw+IAogICAgICAgICAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbD0tQ291bnRyeSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNfdG89IlllYXIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXNfdG89IkZlcnRpbGl0eSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNfdHJhbnNmb3JtPWxpc3QoWWVhciA9IGFzLm51bWVyaWMpKQppbmNvbWUgICA8LSBpbmNvbWUgfD4gCiAgICAgICAgICAgICAgICBzZWxlY3QoQ291bnRyeSwgJzE5MDAnOicyMDE4JykgfD4gCiAgICAgICAgICAgICAgICBwaXZvdF9sb25nZXIoY29sPS1Db3VudHJ5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lc190bz0iWWVhciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190bz0iSW5jb21lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lc190cmFuc2Zvcm09bGlzdChZZWFyID0gYXMubnVtZXJpYykpCnBvcCAgICAgIDwtIHBvcCB8PiAKICAgICAgICAgICAgICAgIHNlbGVjdChDb3VudHJ5LCAnMTkwMCc6JzIwMTgnKSB8PiAKICAgICAgICAgICAgICAgIHBpdm90X2xvbmdlcihjb2w9LUNvdW50cnksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzX3RvPSJZZWFyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzX3RvPSJQb3B1bGF0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lc190cmFuc2Zvcm09bGlzdChZZWFyID0gYXMubnVtZXJpYykpCmBgYAoKNC4gTm93IHdlIHdhbnQgdG8gY29tYmluZSBhbGwgdGhlc2UgZGF0YXNldHMgaW50byBhIHNpbmdsZSBvbmUgY2FsbGVkIGBkYXRgLCBjb250YWluaW5nIHRoZSBjb2x1bW5zIGBDb3VudHJ5YCwgYFllYXJgLCBgUG9wdWxhdGlvbmAsIGBSZWxpZ2lvbmAsIGBGZXJ0aWxpdHlgIGFuZCBgSW5jb21lYC4gTG9vayBpbnRvIHRoZSBgaW5uZXJfam9pbigpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBsaWJyYXJ5ICh3aGljaCBpcyBwYXJ0IG9mIHRoZSBgdGlkeXZlcnNlYCBsaWJyYXJ5KS4gCgpgYGB7ciBpbmNsdWRlPXBhcmFtcyRzb2x1dGlvbiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1GQUxTRX0KZGF0IDwtIGlubmVyX2pvaW4oY2hpbGRyZW4sIGluY29tZSkgfD4KICAgICAgICBpbm5lcl9qb2luKHBvcCkgfD4KICAgICAgICBpbm5lcl9qb2luKHJlbGlnaW9uKQojIHdyaXRlX2NzdihkYXQsICJEYXRhL2RhdC5jc3YiKQpgYGAKCllvdSBzaG91bGQgZW5kIHVwIHdpdGggYSBkYXRhc2V0IGxpa2UgdGhpcyBvbmU6CgpgYGB7ciBlY2hvPUZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPUZBTFNFfQpkYXQKYGBgCgpJbiBjYXNlIHlvdSBzdHJ1Z2dsZWQgdG8gZ2V0IHRoZXJlLCBkb3dubG9hZCB0aGUgYXJjaGl2ZSB3aXRoIHRoZSBidXR0b24gYXQgdGhlIHRvcCBhbmQgZ2V0IHRoZSBgZGF0YCB0aWJibGUgd2l0aCBgZGF0IDwtIHJlYWRfY3N2KCJEYXRhL2RhdC5jc3YiKWB7LlJ9LgoKTm93IG91ciBkYXRhc2V0IGlzIHJlYWR5LCBsZXQncyBwbG90IGl0LgoKIyBQbG90dGluZwoKMS4gTG9hZCB0aGUgbGlicmFyeSBgZ2dwbG90MmAgYW5kIHNldCB0aGUgZ2xvYmFsIHRoZW1lIHRvIGB0aGVtZV9idygpYCB1c2luZyBgdGhlbWVfc2V0KClgCgpgYGB7ciBpbmNsdWRlPXBhcmFtcyRzb2x1dGlvbiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1GQUxTRX0KbGlicmFyeShnZ3Bsb3QyKQp0aGVtZV9zZXQodGhlbWVfYncoKSkKYGBgCgoyLiBDcmVhdGUgYSBzdWJzZXQgb2YgYGRhdGAgY29uY2VybmluZyB5b3VyIG9yaWdpbiBjb3VudHJ5LiBGb3IgbWUgaXQgd2lsbCBiZSBgZGF0X2ZyYW5jZWAKCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPUZBTFNFfQpkYXRfZnJhbmNlIDwtIGRhdCB8PiBmaWx0ZXIoQ291bnRyeT09IkZyYW5jZSIpCmBgYAoKMy4gUGxvdCB0aGUgZXZvbHV0aW9uIG9mIHRoZSBpbmNvbWUgcGVyIGNhcGl0YSBhbmQgdGhlIG51bWJlciBvZiBjaGlsZHJlbiBwZXIgd29tYW4gYXMgYSBmdW5jdGlvbiBvZiB0aGUgeWVhcnMsIGFuZCBtYWtlIGl0IGxvb2sgbGlrZSB0aGF0IChub3RpY2UgdGhlIGtpbmtzIGR1cmluZyB0aGUgdHdvIHdvcmxkIHdhcnMpOgoKYGBge3IgZWNobz1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmdncGxvdChkYXRhPWRhdF9mcmFuY2UsIGFlcyh4PVllYXIsIHk9SW5jb21lKSkrCiAgICBnZ3RpdGxlKCJIb3VzZWhvbGQgaW5jb21lIGluIEZyYW5jZSIpKwogICAgeGxhYigiWWVhciIpKwogICAgeWxhYigiSG91c2Vob2xkIGluY29tZSBwZXIgY2FwaXRhIHBlciB5ZWFyIFtjb25zdGFudCAkXSIpKwogICAgYW5ub3RhdGUoInJlY3QiLCB4bWluPTE5MTQsIHhtYXg9MTkxOCwgeW1pbj0tSW5mLCB5bWF4PUluZiwgYWxwaGE9LjMpKwogICAgYW5ub3RhdGUoInJlY3QiLCB4bWluPTE5MzksIHhtYXg9MTk0NSwgeW1pbj0tSW5mLCB5bWF4PUluZiwgYWxwaGE9LjMpKwogICAgZ2VvbV9wb2ludChhbHBoYT0wLjIsIHNpemU9NSkrCiAgICBnZW9tX3Ntb290aCgpCmdncGxvdChkYXRhPWRhdF9mcmFuY2UsIGFlcyh4PVllYXIsIHk9RmVydGlsaXR5KSkrCiAgICBnZ3RpdGxlKCJGZXJ0aWxpdHkgaW4gRnJhbmNlIikrCiAgICB4bGFiKCJZZWFyIikrCiAgICBsaW1zKHk9YygwLDUpKSsKICAgIHlsYWIoIkNoaWxkcmVuIHBlciB3b21hbiIpKwogICAgYW5ub3RhdGUoInJlY3QiLCB4bWluPTE5MTQsIHhtYXg9MTkxOCwgeW1pbj0tSW5mLCB5bWF4PUluZiwgYWxwaGE9LjMpKwogICAgYW5ub3RhdGUoInJlY3QiLCB4bWluPTE5MzksIHhtYXg9MTk0NSwgeW1pbj0tSW5mLCB5bWF4PUluZiwgYWxwaGE9LjMpKwogICAgZ2VvbV9saW5lKHNpemU9MiwgY29sb3I9InJlZCIpCmBgYAoKNC4gQ3JlYXRlIGEgc3Vic2V0IG9mIGBkYXRgIGNvbnRhaW5pbmcgdGhlIGRhdGEgZm9yIHlvdXIgY291bnRyeSBwbHVzIGFsbCB0aGUgbmVpZ2hib3IgY291bnRyaWVzIChpZiB5b3UgY29tZSBmcm9tIGFuIGlzbGFuZCwgdGhlIG5lYXJlc3QgY291bnRyaWVzLi4uKS4gRm9yIG1lLCBgZGF0X2ZyYW5jZV9yZWdpb25gIHdpbGwgY29udGFpbiBkYXRhIGZyb20gRnJhbmNlLCBTcGFpbiwgSXRhbHksIFN3aXR6ZXJsYW5kLCBHZXJtYW55LCBMdXhlbWJvdXJnIGFuZCBCZWxnaXVtLgoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmRhdF9mcmFuY2VfcmVnaW9uIDwtIGRhdCB8PgogICAgICAgIGZpbHRlcihDb3VudHJ5ICVpbiUgYygiRnJhbmNlIiwgIlNwYWluIiwgIkl0YWx5IiwgIlN3aXR6ZXJsYW5kIiwgIkdlcm1hbnkiLCAiTHV4ZW1ib3VyZyIsICJCZWxnaXVtIikpCmBgYAoKNS4gUGxvdCBhZ2FpbiBpbmNvbWUgYW5kIGZlcnRpbGl0eSBhcyBhIGZ1bmN0aW9uIG9mIHRoZSB5ZWFycywgYnV0IGFkZCBhIGNvbG9yIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGNvdW50cnkgYW5kIGEgcG9pbnQgc2l6ZSB0byBpdHMgcG9wdWxhdGlvbjoKCmBgYHtyIGVjaG89cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPUZBTFNFfQpnZ3Bsb3QoZGF0YT1kYXRfZnJhbmNlX3JlZ2lvbiwgYWVzKHg9WWVhciwgeT1JbmNvbWUsIGNvbD1Db3VudHJ5LCBzaXplPVBvcHVsYXRpb24pKSsKICAgIGdndGl0bGUoIkhvdXNlaG9sZCBpbmNvbWUgaW4gRnJhbmNlIGFuZCBpdHMgcmVnaW9uIikrCiAgICB4bGFiKCJZZWFyIikrCiAgICB5bGFiKCJIb3VzZWhvbGQgaW5jb21lIHBlciBjYXBpdGEgcGVyIHllYXIgW2NvbnN0YW50ICRdIikrCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTkxNCwgeG1heD0xOTE4LCB5bWluPS1JbmYsIHltYXg9SW5mLCBhbHBoYT0uMykrCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTkzOSwgeG1heD0xOTQ1LCB5bWluPS1JbmYsIHltYXg9SW5mLCBhbHBoYT0uMykrCiAgICBnZW9tX3BvaW50KGFscGhhPTAuNSkKZ2dwbG90KGRhdGE9ZGF0X2ZyYW5jZV9yZWdpb24sIGFlcyh4PVllYXIsIHk9RmVydGlsaXR5LCBjb2w9Q291bnRyeSwgc2l6ZT1Qb3B1bGF0aW9uKSkrCiAgICBnZ3RpdGxlKCJGZXJ0aWxpdHkgaW4gRnJhbmNlIGFuZCBpdHMgcmVnaW9uIikrCiAgICB4bGFiKCJZZWFyIikrCiAgICBsaW1zKHk9YygwLDUpKSsKICAgIHlsYWIoIkNoaWxkcmVuIHBlciB3b21hbiIpKwogICAgYW5ub3RhdGUoInJlY3QiLCB4bWluPTE5MTQsIHhtYXg9MTkxOCwgeW1pbj0tSW5mLCB5bWF4PUluZiwgYWxwaGE9LjMpKwogICAgYW5ub3RhdGUoInJlY3QiLCB4bWluPTE5MzksIHhtYXg9MTk0NSwgeW1pbj0tSW5mLCB5bWF4PUluZiwgYWxwaGE9LjMpKwogICAgZ2VvbV9wb2ludChhbHBoYT0uNSkKYGBgCgo2LiBMb2FkIHRoZSBsaWJyYXJ5IGBwbG90bHlgIGFuZCBtYWtlIHRoZSBwcmV2aW91cyBncmFwaHMgaW50ZXJhY3RpdmUuIFlvdSBjYW4gbWFrZSBhbiBpbnRlcmFjdGl2ZSBncmFwaCBieSBjYWxsaW5nIGBnZ3Bsb3RseSgpYCwgbGlrZSB0aGF0OgoKYGBge3IgaW5jbHVkZT1UUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPUZBTFNFfQpsaWJyYXJ5KHBsb3RseSkKUCA8LSBnZ3Bsb3QoZGF0YSA9IGRhdF9mcmFuY2UsIGFlcyh4PVBvcHVsYXRpb24sIHk9SW5jb21lKSkrCiAgICAgICAgZ2VvbV9wb2ludCgpCmdncGxvdGx5KFApICMgYWRkIGR5bmFtaWNUaWNrcz1UUlVFIGFsbG93cyByZWRyYXdpbmcgdGlja3Mgd2hlbiB6b29taW5nIGluCmBgYAoKCjcuIEZpbmFsbHksIHlvdSBjYW4gYWRkIGEgc2xpZGVyIHRvIHRoZSBpbnRlcmFjdGl2ZSBncmFwaCBhbGxvd2luZyBzZWxlY3RpbmcgYSB2YWx1ZSBmb3IgYW5vdGhlciB2YXJpYWJsZSAoanVzdCBsaWtlIGluIHRoZSB2aWRlbykgYnkgYWRkaW5nIHRoZSBrZXl3b3JkIGBmcmFtZSA9YCBpbiB0aGUgY2hhcnQncyBhZXN0aGV0aWNzLiBTbyBub3csIG1ha2UgdGhlIGdyYXBoIG9mIHRoZSB2aWRlbyAhICh5b3UgY2FuIGFsc28gYWRkIHRoZSBhZXN0aGV0aWNzIGBpZD1Db3VudHJ5YCB0byBzaG93IHRoZSBjb3VudHJ5IG5hbWUgaW4gdGhlIHBvcHVwIHdoZW4gaG92ZXJpbmcgb24gYSBwb2ludCkuCgoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmxpYnJhcnkocGxvdGx5KQpQIDwtIGdncGxvdChkYXRhPWRhdCwgYWVzKHg9SW5jb21lLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB5PUZlcnRpbGl0eSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgZnJhbWU9WWVhciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgY29sPVJlbGlnaW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPVBvcHVsYXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ9Q291bnRyeSkpKwogICAgZ2VvbV9wb2ludChhbHBoYT0wLjUpKwogICAgZ2d0aXRsZSgiRmVydGlsaXR5IHZzLiBJbmNvbWUgaW4gdGhlIFdvcmxkIikrCiAgICB4bGFiKCJIb3VzZWhvbGQgaW5jb21lIHBlciBjYXBpdGEgcGVyIHllYXIgW2NvbnN0YW50ICRdIikrCiAgICBsaW1zKHk9YygwLDgpKSsKICAgIHNjYWxlX3NpemUocmFuZ2U9YygxLCAxNSkpKwogICAgeWxhYigiQ2hpbGRyZW4gcGVyIHdvbWFuIikKZ2dwbG90bHkoUCwgZHluYW1pY1RpY2tzID0gVFJVRSkgfD4gCiAgbGF5b3V0KHlheGlzID0gbGlzdChhdXRvcmFuZ2UgPSBGQUxTRSksIAogICAgICAgICB4YXhpcyA9IGxpc3QoYXV0b3JhbmdlID0gRkFMU0UsIHR5cGUgPSAnbG9nJywgcmFuZ2U9bGlzdCgyLCA1LjUpKSkKYGBgCg==