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
.
library(tidyverse)
library(readxl)
children <- read_csv("Data/children_per_woman_total_fertility.csv")
income <- read_csv("Data/income_per_person_gdppercapita_ppp_inflation_adjusted.csv")
pop <- read_csv("Data/population_total.csv")
religion <- read_csv("Data/religion.csv")
- 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.
religion <- religion |>
filter(Year==2020) |>
select(Country, Buddhists:Unaffiliated) |>
pivot_longer(cols=-Country,
names_to="Religion",
values_to="Proportion") |>
filter(.by = Country,
Proportion==max(Proportion)) |>
select(-Proportion)
- 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.
children <- children |>
select(Country, '1900':'2018') |>
pivot_longer(col=-Country,
names_to="Year",
values_to="Fertility",
names_transform=list(Year = as.numeric))
income <- income |>
select(Country, '1900':'2018') |>
pivot_longer(col=-Country,
names_to="Year",
values_to="Income",
names_transform=list(Year = as.numeric))
pop <- pop |>
select(Country, '1900':'2018') |>
pivot_longer(col=-Country,
names_to="Year",
values_to="Population",
names_transform=list(Year = as.numeric))
- 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).
dat <- inner_join(children, income) |>
inner_join(pop) |>
inner_join(religion)
# write_csv(dat, "Data/dat.csv")
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()
library(ggplot2)
theme_set(theme_bw())
- Create a subset of
dat
concerning your origin country.
For me it will be dat_france
dat_france <- dat |> filter(Country=="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):
ggplot(data=dat_france, aes(x=Year, y=Income))+
ggtitle("Household income in France")+
xlab("Year")+
ylab("Household income per capita per year [constant $]")+
annotate("rect", xmin=1914, xmax=1918, ymin=-Inf, ymax=Inf, alpha=.3)+
annotate("rect", xmin=1939, xmax=1945, ymin=-Inf, ymax=Inf, alpha=.3)+
geom_point(alpha=0.2, size=5)+
geom_smooth()
ggplot(data=dat_france, aes(x=Year, y=Fertility))+
ggtitle("Fertility in France")+
xlab("Year")+
lims(y=c(0,5))+
ylab("Children per woman")+
annotate("rect", xmin=1914, xmax=1918, ymin=-Inf, ymax=Inf, alpha=.3)+
annotate("rect", xmin=1939, xmax=1945, ymin=-Inf, ymax=Inf, alpha=.3)+
geom_line(size=2, color="red")
- 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.
dat_france_region <- dat |>
filter(Country %in% c("France", "Spain", "Italy", "Switzerland", "Germany", "Luxembourg", "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:
ggplot(data=dat_france_region, aes(x=Year, y=Income, col=Country, size=Population))+
ggtitle("Household income in France and its region")+
xlab("Year")+
ylab("Household income per capita per year [constant $]")+
annotate("rect", xmin=1914, xmax=1918, ymin=-Inf, ymax=Inf, alpha=.3)+
annotate("rect", xmin=1939, xmax=1945, ymin=-Inf, ymax=Inf, alpha=.3)+
geom_point(alpha=0.5)
ggplot(data=dat_france_region, aes(x=Year, y=Fertility, col=Country, size=Population))+
ggtitle("Fertility in France and its region")+
xlab("Year")+
lims(y=c(0,5))+
ylab("Children per woman")+
annotate("rect", xmin=1914, xmax=1918, ymin=-Inf, ymax=Inf, alpha=.3)+
annotate("rect", xmin=1939, xmax=1945, ymin=-Inf, ymax=Inf, alpha=.3)+
geom_point(alpha=.5)
- 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).
library(plotly)
P <- ggplot(data=dat, aes(x=Income,
y=Fertility,
frame=Year,
col=Religion,
size=Population,
id=Country))+
geom_point(alpha=0.5)+
ggtitle("Fertility vs. Income in the World")+
xlab("Household income per capita per year [constant $]")+
lims(y=c(0,8))+
scale_size(range=c(1, 15))+
ylab("Children per woman")
ggplotly(P, dynamicTicks = TRUE) |>
layout(yaxis = list(autorange = FALSE),
xaxis = list(autorange = FALSE, type = 'log', range=list(2, 5.5)))
LS0tCnRpdGxlIDogIlIgRXhlcmNpc2VzIC0gUmVsaWdpb24gYW5kIGJhYmllcyIKZGF0ZSAgOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogCiAgICBodG1sX2RvY3VtZW50OgogICAgICAgIHRvYyAgICAgICAgICAgIDogdHJ1ZQogICAgICAgIHRvY19mbG9hdCAgICAgIDogdHJ1ZQogICAgICAgIHRvY19kZXB0aCAgICAgIDogNAogICAgICAgIGhpZ2hsaWdodCAgICAgIDogdGFuZ28KICAgICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgICAgICBjb2RlX2Rvd25sb2FkICA6IHRydWUKcGFyYW1zOiAKICAgIHNvbHV0aW9uOgogICAgICAgIHZhbHVlOiB0cnVlCi0tLQoKYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZmlnLmFsaWduPSJjZW50ZXIifQpsaWJyYXJ5KGRvd25sb2FkdGhpcykKZG93bmxvYWRfbGluaygKICBsaW5rID0gIi4vQXJjaGl2ZS56aXAiLAogIG91dHB1dF9uYW1lID0gIkRhdGEgRmlsZXMiLAogIGJ1dHRvbl9sYWJlbCA9ICJEb3dubG9hZCBEYXRhIEZpbGVzIiwKICBidXR0b25fdHlwZSA9ICJkZWZhdWx0IiwKICBoYXNfaWNvbiA9IFRSVUUsCiAgaWNvbiA9ICJmYSBmYS1zYXZlIiwKICBzZWxmX2NvbnRhaW5lZCA9IEZBTFNFCikKYGBgCjxicj4KCi0tLS0KCkluIHRoZXNlIGV4ZXJjaXNlcyB3ZSB3aWxsIHNlZSB0aGUgcG93ZXIgb2YgdGhlIGxpYnJhcmllcyBgZ2dwbG90MmAgYW5kIGBwbG90bHlgIHRvIG1ha2Ugc2Vuc2Ugb2Ygc3RhdGlzdGljYWwgZGF0YS4gVGhlIGdvYWwgaXMgdG8gcmVwcm9kdWNlIHRoZSBtb3ZpbmcgY2hhcnQgdGhhdCB5b3UgY2FuIHNlZSBpbiB0aGlzIHZpZGVvIGZyb20gSGFucyBSb3NsaW5nIC0tIEkgaW52aXRlIHlvdSB0byB3YXRjaCBoaXMgb3RoZXIgdmlkZW9zLCB0aGV5IGFyZSBxdWl0ZSBlbmxpZ2h0ZW5pbmcgYW5kIGluc3BpcmluZzoKCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPgo8YSBocmVmPSJodHRwczovL3d3dy50ZWQuY29tL3RhbGtzL2hhbnNfcm9zbGluZ19yZWxpZ2lvbnNfYW5kX2JhYmllcz9sYW5ndWFnZT1lbiIgdGFyZ2V0PSJfYmxhbmsiPgo8aSBjbGFzcz0iZmFiIGZhLXlvdXR1YmUgZmEtNXgiPjwvaT4KPC9hPgo8L2Rpdj4KCjxicj4KPGJyPgoKRm9yIHRoaXMsIHdlIHdpbGwgbmVlZCB0byBnYXRoZXIgdGhlIGRhdGE6CgotIEZyb20gW0dhcG1pbmRlcl0oaHR0cHM6Ly93d3cuZ2FwbWluZGVyLm9yZy9kYXRhLyksIGRhdGEgcGVyIGNvdW50cnkgYW5kIHBlciB5ZWFyIGZyb20gMTgwMCB0byAyMDE4OgogICAgLSBbVGhlIGNoaWxkcmVuIHBlciB3b21hbiB0b3RhbCBmZXJ0aWxpdHldKERhdGEvY2hpbGRyZW5fcGVyX3dvbWFuX3RvdGFsX2ZlcnRpbGl0eS5jc3YpCiAgICAtIFtUaGUgaW5jb21lIHBlciBjYXBpdGFdKERhdGEvaW5jb21lX3Blcl9wZXJzb25fZ2RwcGVyY2FwaXRhX3BwcF9pbmZsYXRpb25fYWRqdXN0ZWQuY3N2KQogICAgLSBbVGhlIHRvdGFsIHBvcHVsYXRpb25dKERhdGEvcG9wdWxhdGlvbl90b3RhbC5jc3YpCi0gRnJvbSB0aGUgW1BFVyByZXNlYXJjaCBjZW50ZXJdKGh0dHBzOi8vd3d3LnBld2ZvcnVtLm9yZy8yMDE1LzA0LzAyL3JlbGlnaW91cy1wcm9qZWN0aW9uLXRhYmxlLzIwMTAvcGVyY2VudC9hbGwvKSwgZGF0YSBwZXIgY291bnRyeToKICAgICsgW1RoZSByZWxpZ2lvdXMgY29tcG9zaXRpb25dKERhdGEvcmVsaWdpb24uY3N2KQoKLS0tLS0tLSAKCiMgRGF0YSBoYW5kbGluZwoKVGhlIGZpcnN0IHRoaW5nIHRvIGRvIGlzIHRvIGxvYWQgYW5kIHJlZ3JvdXAgYWxsIHRoZXNlIGRhdGFzZXRzIGludG8gYSBzaW5nbGUgb25lLgoKMS4gTG9hZCB0aGUgYHRpZHl2ZXJzZWAgbGlicmFyeSBhbmQsIHVzaW5nIGByZWFkX2NzdigpYCwgbG9hZCB0aGUgNCBkYXRhc2V0cyBpbiA0IHNlcGFyYXRlIHRpYmJsZXMgY2FsbGVkIGBjaGlsZHJlbmAsIGBpbmNvbWVgLCBgcG9wYCBhbmQgYHJlbGlnaW9uYC4KCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyZWFkeGwpCmNoaWxkcmVuIDwtIHJlYWRfY3N2KCJEYXRhL2NoaWxkcmVuX3Blcl93b21hbl90b3RhbF9mZXJ0aWxpdHkuY3N2IikKaW5jb21lICAgPC0gcmVhZF9jc3YoIkRhdGEvaW5jb21lX3Blcl9wZXJzb25fZ2RwcGVyY2FwaXRhX3BwcF9pbmZsYXRpb25fYWRqdXN0ZWQuY3N2IikKcG9wICAgICAgPC0gcmVhZF9jc3YoIkRhdGEvcG9wdWxhdGlvbl90b3RhbC5jc3YiKQpyZWxpZ2lvbiA8LSByZWFkX2NzdigiRGF0YS9yZWxpZ2lvbi5jc3YiKQpgYGAKCjIuIFRvIHJlcHJvZHVjZSB0aGUgY2hhcnQgb24gdGhlIHZpZGVvLCB3ZSBuZWVkIHRvIGRldGVybWluZSB0aGUgZG9taW5hbnQgcmVsaWdpb24gaW4gZWFjaCBjb3VudHJ5LiBJbiB0aGUgYHJlbGlnaW9uYCBkYXRhc2V0LCBhZGQgYSBjb2x1bW4gYFJlbGlnaW9uYCB0aGF0IHdpbGwgZ2l2ZSB0aGUgbmFtZSBvZiB0aGUgZG9taW5hbnQgcmVsaWdpb24gZm9yIGVhY2ggY291bnRyeS4gRm9yIHRoaXMsIHlvdSBuZWVkIHRvIG1ha2UgdGhlIHRhYmxlIGNvbnRhaW4ganVzdCB0aGUgYENvdW50cnlgIGFuZCBhbGwgcmVsaWdpb25zLCBtYWtlIHRoZSB0YWJsZSB0aWR5LCBhbmQgdGhlbiBzZWxlY3QgdGhlIHJlbGlnaW9uIHdpdGggdGhlIGhpZ2hlc3QgcHJvcG9ydGlvbiBmb3IgZWFjaCBjb3VudHJ5LiBXZSB3aWxsIGZpbHRlciB0aGUgZGF0YSB0byBnZXQgb25seSB0aGUgeWVhciAyMDIwLgoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CnJlbGlnaW9uIDwtIHJlbGlnaW9uIHw+CiAgICAgICAgZmlsdGVyKFllYXI9PTIwMjApIHw+CiAgICAgICAgc2VsZWN0KENvdW50cnksIEJ1ZGRoaXN0czpVbmFmZmlsaWF0ZWQpIHw+IAogICAgICAgIHBpdm90X2xvbmdlcihjb2xzPS1Db3VudHJ5LCAKICAgICAgICAgICAgICAgICAgICAgbmFtZXNfdG89IlJlbGlnaW9uIiwgCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190bz0iUHJvcG9ydGlvbiIpIHw+CiAgICAgICAgZmlsdGVyKC5ieSA9IENvdW50cnksCiAgICAgICAgICAgICAgIFByb3BvcnRpb249PW1heChQcm9wb3J0aW9uKSkgfD4KICAgICAgICBzZWxlY3QoLVByb3BvcnRpb24pCmBgYAoKMy4gVXNpbmcgYHBpdm90X2xvbmdlcigpYCwgbWFrZSBhbGwgZGF0YXNldHMgdGlkeS4gCgotIGBjaGlsZHJlbmAgc2hvdWxkIG5vdyBjb250YWluIDMgY29sdW1uczogYENvdW50cnlgLCBgWWVhcmAgYW5kIGBGZXJ0aWxpdHlgLiAKLSBgaW5jb21lYCBzaG91bGQgbm93IGNvbnRhaW4gMyBjb2x1bW5zOiBgQ291bnRyeWAsIGBZZWFyYCBhbmQgYEluY29tZWAuIAotIGBwb3BgIHNob3VsZCBub3cgY29udGFpbiAzIGNvbHVtbnM6IGBDb3VudHJ5YCwgYFllYXJgIGFuZCBgUG9wdWxhdGlvbmAuIAoKV2Ugd2lsbCBvbmx5IGNvbnNpZGVyIGRhdGEgZnJvbSAxOTAwIHRvIDIwMTguIEV4YW1wbGUgb2Ygc3ludGF4IHVzaW5nIHRoZSBwaXBlIG9wZXJhdG9yIGB8PmA6CgpgYGB7cn0KREYgPC0gcmVhZF90YWJsZSgibmFtZSAgMjAxMCAgMjAxMSAgMjAxMiAgMjAxNApLZXZpbiAgMTAgICAgMTEgICAxMiAgIDEyMwpKYW5lICAgMTIyICAgNTYgICAyMyAgIDQKIgopCkRGCkRGIHw+IAogICAgc2VsZWN0KG5hbWUsICcyMDEwJzonMjAxMicpIHw+IAogICAgcGl2b3RfbG9uZ2VyKGNvbD0tbmFtZSwKICAgICAgICAgICAgICAgICBuYW1lc190bz0iWWVhciIsIAogICAgICAgICAgICAgICAgIHZhbHVlc190bz0iU2NvcmUiLAogICAgICAgICAgICAgICAgIG5hbWVzX3RyYW5zZm9ybT1saXN0KFllYXIgPSBhcy5udW1lcmljKSkKYGBgClRoZSBsaW5lIGBuYW1lc190cmFuc2Zvcm09bGlzdChZZWFyID0gYXMubnVtZXJpYylgIGlzIGhlcmUgdG8gY29udmVydCB0aGUgY2hhcmFjdGVyIHllYXIgdmFsdWVzIHRvIG51bWVyaWNhbCB2YWx1ZXMuCgpgYGB7ciBpbmNsdWRlPXBhcmFtcyRzb2x1dGlvbiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1GQUxTRX0KY2hpbGRyZW4gPC0gY2hpbGRyZW4gfD4gCiAgICAgICAgICAgICAgICBzZWxlY3QoQ291bnRyeSwgJzE5MDAnOicyMDE4JykgfD4gCiAgICAgICAgICAgICAgICBwaXZvdF9sb25nZXIoY29sPS1Db3VudHJ5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lc190bz0iWWVhciIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190bz0iRmVydGlsaXR5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lc190cmFuc2Zvcm09bGlzdChZZWFyID0gYXMubnVtZXJpYykpCmluY29tZSAgIDwtIGluY29tZSB8PiAKICAgICAgICAgICAgICAgIHNlbGVjdChDb3VudHJ5LCAnMTkwMCc6JzIwMTgnKSB8PiAKICAgICAgICAgICAgICAgIHBpdm90X2xvbmdlcihjb2w9LUNvdW50cnksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzX3RvPSJZZWFyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzX3RvPSJJbmNvbWUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzX3RyYW5zZm9ybT1saXN0KFllYXIgPSBhcy5udW1lcmljKSkKcG9wICAgICAgPC0gcG9wIHw+IAogICAgICAgICAgICAgICAgc2VsZWN0KENvdW50cnksICcxOTAwJzonMjAxOCcpIHw+IAogICAgICAgICAgICAgICAgcGl2b3RfbG9uZ2VyKGNvbD0tQ291bnRyeSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNfdG89IlllYXIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXNfdG89IlBvcHVsYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzX3RyYW5zZm9ybT1saXN0KFllYXIgPSBhcy5udW1lcmljKSkKYGBgCgo0LiBOb3cgd2Ugd2FudCB0byBjb21iaW5lIGFsbCB0aGVzZSBkYXRhc2V0cyBpbnRvIGEgc2luZ2xlIG9uZSBjYWxsZWQgYGRhdGAsIGNvbnRhaW5pbmcgdGhlIGNvbHVtbnMgYENvdW50cnlgLCBgWWVhcmAsIGBQb3B1bGF0aW9uYCwgYFJlbGlnaW9uYCwgYEZlcnRpbGl0eWAgYW5kIGBJbmNvbWVgLiBMb29rIGludG8gdGhlIGBpbm5lcl9qb2luKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIGxpYnJhcnkgKHdoaWNoIGlzIHBhcnQgb2YgdGhlIGB0aWR5dmVyc2VgIGxpYnJhcnkpLiAKCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPUZBTFNFfQpkYXQgPC0gaW5uZXJfam9pbihjaGlsZHJlbiwgaW5jb21lKSB8PgogICAgICAgIGlubmVyX2pvaW4ocG9wKSB8PgogICAgICAgIGlubmVyX2pvaW4ocmVsaWdpb24pCiMgd3JpdGVfY3N2KGRhdCwgIkRhdGEvZGF0LmNzdiIpCmBgYAoKWW91IHNob3VsZCBlbmQgdXAgd2l0aCBhIGRhdGFzZXQgbGlrZSB0aGlzIG9uZToKCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmRhdApgYGAKCkluIGNhc2UgeW91IHN0cnVnZ2xlZCB0byBnZXQgdGhlcmUsIGRvd25sb2FkIHRoZSBhcmNoaXZlIHdpdGggdGhlIGJ1dHRvbiBhdCB0aGUgdG9wIGFuZCBnZXQgdGhlIGBkYXRgIHRpYmJsZSB3aXRoIGBkYXQgPC0gcmVhZF9jc3YoIkRhdGEvZGF0LmNzdiIpYHsuUn0uCgpOb3cgb3VyIGRhdGFzZXQgaXMgcmVhZHksIGxldCdzIHBsb3QgaXQuCgojIFBsb3R0aW5nCgoxLiBMb2FkIHRoZSBsaWJyYXJ5IGBnZ3Bsb3QyYCBhbmQgc2V0IHRoZSBnbG9iYWwgdGhlbWUgdG8gYHRoZW1lX2J3KClgIHVzaW5nIGB0aGVtZV9zZXQoKWAKCmBgYHtyIGluY2x1ZGU9cGFyYW1zJHNvbHV0aW9uLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGNhY2hlPUZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCnRoZW1lX3NldCh0aGVtZV9idygpKQpgYGAKCjIuIENyZWF0ZSBhIHN1YnNldCBvZiBgZGF0YCBjb25jZXJuaW5nIHlvdXIgb3JpZ2luIGNvdW50cnkuIEZvciBtZSBpdCB3aWxsIGJlIGBkYXRfZnJhbmNlYAoKYGBge3IgaW5jbHVkZT1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmRhdF9mcmFuY2UgPC0gZGF0IHw+IGZpbHRlcihDb3VudHJ5PT0iRnJhbmNlIikKYGBgCgozLiBQbG90IHRoZSBldm9sdXRpb24gb2YgdGhlIGluY29tZSBwZXIgY2FwaXRhIGFuZCB0aGUgbnVtYmVyIG9mIGNoaWxkcmVuIHBlciB3b21hbiBhcyBhIGZ1bmN0aW9uIG9mIHRoZSB5ZWFycywgYW5kIG1ha2UgaXQgbG9vayBsaWtlIHRoYXQgKG5vdGljZSB0aGUga2lua3MgZHVyaW5nIHRoZSB0d28gd29ybGQgd2Fycyk6CgpgYGB7ciBlY2hvPXBhcmFtcyRzb2x1dGlvbiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1GQUxTRX0KZ2dwbG90KGRhdGE9ZGF0X2ZyYW5jZSwgYWVzKHg9WWVhciwgeT1JbmNvbWUpKSsKICAgIGdndGl0bGUoIkhvdXNlaG9sZCBpbmNvbWUgaW4gRnJhbmNlIikrCiAgICB4bGFiKCJZZWFyIikrCiAgICB5bGFiKCJIb3VzZWhvbGQgaW5jb21lIHBlciBjYXBpdGEgcGVyIHllYXIgW2NvbnN0YW50ICRdIikrCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTkxNCwgeG1heD0xOTE4LCB5bWluPS1JbmYsIHltYXg9SW5mLCBhbHBoYT0uMykrCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTkzOSwgeG1heD0xOTQ1LCB5bWluPS1JbmYsIHltYXg9SW5mLCBhbHBoYT0uMykrCiAgICBnZW9tX3BvaW50KGFscGhhPTAuMiwgc2l6ZT01KSsKICAgIGdlb21fc21vb3RoKCkKZ2dwbG90KGRhdGE9ZGF0X2ZyYW5jZSwgYWVzKHg9WWVhciwgeT1GZXJ0aWxpdHkpKSsKICAgIGdndGl0bGUoIkZlcnRpbGl0eSBpbiBGcmFuY2UiKSsKICAgIHhsYWIoIlllYXIiKSsKICAgIGxpbXMoeT1jKDAsNSkpKwogICAgeWxhYigiQ2hpbGRyZW4gcGVyIHdvbWFuIikrCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTkxNCwgeG1heD0xOTE4LCB5bWluPS1JbmYsIHltYXg9SW5mLCBhbHBoYT0uMykrCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTkzOSwgeG1heD0xOTQ1LCB5bWluPS1JbmYsIHltYXg9SW5mLCBhbHBoYT0uMykrCiAgICBnZW9tX2xpbmUoc2l6ZT0yLCBjb2xvcj0icmVkIikKYGBgCgo0LiBDcmVhdGUgYSBzdWJzZXQgb2YgYGRhdGAgY29udGFpbmluZyB0aGUgZGF0YSBmb3IgeW91ciBjb3VudHJ5IHBsdXMgYWxsIHRoZSBuZWlnaGJvciBjb3VudHJpZXMgKGlmIHlvdSBjb21lIGZyb20gYW4gaXNsYW5kLCB0aGUgbmVhcmVzdCBjb3VudHJpZXMuLi4pLiBGb3IgbWUsIGBkYXRfZnJhbmNlX3JlZ2lvbmAgd2lsbCBjb250YWluIGRhdGEgZnJvbSBGcmFuY2UsIFNwYWluLCBJdGFseSwgU3dpdHplcmxhbmQsIEdlcm1hbnksIEx1eGVtYm91cmcgYW5kIEJlbGdpdW0uCgpgYGB7ciBpbmNsdWRlPXBhcmFtcyRzb2x1dGlvbiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1GQUxTRX0KZGF0X2ZyYW5jZV9yZWdpb24gPC0gZGF0IHw+CiAgICAgICAgZmlsdGVyKENvdW50cnkgJWluJSBjKCJGcmFuY2UiLCAiU3BhaW4iLCAiSXRhbHkiLCAiU3dpdHplcmxhbmQiLCAiR2VybWFueSIsICJMdXhlbWJvdXJnIiwgIkJlbGdpdW0iKSkKYGBgCgo1LiBQbG90IGFnYWluIGluY29tZSBhbmQgZmVydGlsaXR5IGFzIGEgZnVuY3Rpb24gb2YgdGhlIHllYXJzLCBidXQgYWRkIGEgY29sb3IgY29ycmVzcG9uZGluZyB0byB0aGUgY291bnRyeSBhbmQgYSBwb2ludCBzaXplIHRvIGl0cyBwb3B1bGF0aW9uOgoKYGBge3IgZWNobz1wYXJhbXMkc29sdXRpb24sIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmdncGxvdChkYXRhPWRhdF9mcmFuY2VfcmVnaW9uLCBhZXMoeD1ZZWFyLCB5PUluY29tZSwgY29sPUNvdW50cnksIHNpemU9UG9wdWxhdGlvbikpKwogICAgZ2d0aXRsZSgiSG91c2Vob2xkIGluY29tZSBpbiBGcmFuY2UgYW5kIGl0cyByZWdpb24iKSsKICAgIHhsYWIoIlllYXIiKSsKICAgIHlsYWIoIkhvdXNlaG9sZCBpbmNvbWUgcGVyIGNhcGl0YSBwZXIgeWVhciBbY29uc3RhbnQgJF0iKSsKICAgIGFubm90YXRlKCJyZWN0IiwgeG1pbj0xOTE0LCB4bWF4PTE5MTgsIHltaW49LUluZiwgeW1heD1JbmYsIGFscGhhPS4zKSsKICAgIGFubm90YXRlKCJyZWN0IiwgeG1pbj0xOTM5LCB4bWF4PTE5NDUsIHltaW49LUluZiwgeW1heD1JbmYsIGFscGhhPS4zKSsKICAgIGdlb21fcG9pbnQoYWxwaGE9MC41KQpnZ3Bsb3QoZGF0YT1kYXRfZnJhbmNlX3JlZ2lvbiwgYWVzKHg9WWVhciwgeT1GZXJ0aWxpdHksIGNvbD1Db3VudHJ5LCBzaXplPVBvcHVsYXRpb24pKSsKICAgIGdndGl0bGUoIkZlcnRpbGl0eSBpbiBGcmFuY2UgYW5kIGl0cyByZWdpb24iKSsKICAgIHhsYWIoIlllYXIiKSsKICAgIGxpbXMoeT1jKDAsNSkpKwogICAgeWxhYigiQ2hpbGRyZW4gcGVyIHdvbWFuIikrCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTkxNCwgeG1heD0xOTE4LCB5bWluPS1JbmYsIHltYXg9SW5mLCBhbHBoYT0uMykrCiAgICBhbm5vdGF0ZSgicmVjdCIsIHhtaW49MTkzOSwgeG1heD0xOTQ1LCB5bWluPS1JbmYsIHltYXg9SW5mLCBhbHBoYT0uMykrCiAgICBnZW9tX3BvaW50KGFscGhhPS41KQpgYGAKCjYuIExvYWQgdGhlIGxpYnJhcnkgYHBsb3RseWAgYW5kIG1ha2UgdGhlIHByZXZpb3VzIGdyYXBocyBpbnRlcmFjdGl2ZS4gWW91IGNhbiBtYWtlIGFuIGludGVyYWN0aXZlIGdyYXBoIGJ5IGNhbGxpbmcgYGdncGxvdGx5KClgLCBsaWtlIHRoYXQ6CgpgYGB7ciBpbmNsdWRlPVRSVUUsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZT1GQUxTRSwgY2FjaGU9RkFMU0V9CmxpYnJhcnkocGxvdGx5KQpQIDwtIGdncGxvdChkYXRhID0gZGF0X2ZyYW5jZSwgYWVzKHg9UG9wdWxhdGlvbiwgeT1JbmNvbWUpKSsKICAgICAgICBnZW9tX3BvaW50KCkKZ2dwbG90bHkoUCkgIyBhZGQgZHluYW1pY1RpY2tzPVRSVUUgYWxsb3dzIHJlZHJhd2luZyB0aWNrcyB3aGVuIHpvb21pbmcgaW4KYGBgCgoKNy4gRmluYWxseSwgeW91IGNhbiBhZGQgYSBzbGlkZXIgdG8gdGhlIGludGVyYWN0aXZlIGdyYXBoIGFsbG93aW5nIHNlbGVjdGluZyBhIHZhbHVlIGZvciBhbm90aGVyIHZhcmlhYmxlIChqdXN0IGxpa2UgaW4gdGhlIHZpZGVvKSBieSBhZGRpbmcgdGhlIGtleXdvcmQgYGZyYW1lID1gIGluIHRoZSBjaGFydCdzIGFlc3RoZXRpY3MuIFNvIG5vdywgbWFrZSB0aGUgZ3JhcGggb2YgdGhlIHZpZGVvICEgKHlvdSBjYW4gYWxzbyBhZGQgdGhlIGFlc3RoZXRpY3MgYGlkPUNvdW50cnlgIHRvIHNob3cgdGhlIGNvdW50cnkgbmFtZSBpbiB0aGUgcG9wdXAgd2hlbiBob3ZlcmluZyBvbiBhIHBvaW50KS4KCgpgYGB7ciBpbmNsdWRlPXBhcmFtcyRzb2x1dGlvbiwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjYWNoZT1GQUxTRX0KbGlicmFyeShwbG90bHkpClAgPC0gZ2dwbG90KGRhdGE9ZGF0LCBhZXMoeD1JbmNvbWUsIAogICAgICAgICAgICAgICAgICAgICAgICAgIHk9RmVydGlsaXR5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBmcmFtZT1ZZWFyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBjb2w9UmVsaWdpb24sIAogICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9UG9wdWxhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICBpZD1Db3VudHJ5KSkrCiAgICBnZW9tX3BvaW50KGFscGhhPTAuNSkrCiAgICBnZ3RpdGxlKCJGZXJ0aWxpdHkgdnMuIEluY29tZSBpbiB0aGUgV29ybGQiKSsKICAgIHhsYWIoIkhvdXNlaG9sZCBpbmNvbWUgcGVyIGNhcGl0YSBwZXIgeWVhciBbY29uc3RhbnQgJF0iKSsKICAgIGxpbXMoeT1jKDAsOCkpKwogICAgc2NhbGVfc2l6ZShyYW5nZT1jKDEsIDE1KSkrCiAgICB5bGFiKCJDaGlsZHJlbiBwZXIgd29tYW4iKQpnZ3Bsb3RseShQLCBkeW5hbWljVGlja3MgPSBUUlVFKSB8PiAKICBsYXlvdXQoeWF4aXMgPSBsaXN0KGF1dG9yYW5nZSA9IEZBTFNFKSwgCiAgICAgICAgIHhheGlzID0gbGlzdChhdXRvcmFuZ2UgPSBGQUxTRSwgdHlwZSA9ICdsb2cnLCByYW5nZT1saXN0KDIsIDUuNSkpKQpgYGAK