The data
The data we are using comes from Gapminder. We will use
data on population, life expectancy, fertility rate, and GDP per capita.
The full combined dataset contains data from 195 countries. As
Gapminder collects the data from different sources and there
are differences in the availability of different kinds of data, the
individual datasets (for life expectancy, GDP per capita, etc.) differ
regarding the number of countries and years they cover. Notably, all of
them except the one on GDP per capita also contain projected data until
the year 2100. The data on population, life expectancy, and fertility
rate also all go back to 1800. The data on GDP per capita, however, are
only available for the years from 1960 to 2018. Also, there is missing
data for many countries for different years.
Missing data
As we do not have data for all variables for all countries and years,
we want to know whether there are identifiable patterns of missingness
in our data.
library(visdat)
vis_miss(gap_full)

Data for 2018
Given that we only have data on GDP per capita from 1960 to 2018, we
will focus on data from the year 2018 in our analysis. The dataset for
2018 contains data for 195 countries from 6 continents. Let’s have a
look at this dataset.
Missing data in the
2018 dataset
The 2018 dataset still has some missing data.
library(naniar)
gg_miss_var(gap_2018)

We see that we have the most missing values for the
continent variable. The reason for this is that this
variable comes from a different source: the data included in the gapminder
package. For our analyses, we will only use the countries for which
we have complete data for 2018. This dataset includes data from 128
countries.
Exploring the 2018
Gapminder data
Countries per
continent
How many countries per continent are included in our complete 2018
dataset?
library(janitor)
gap_2018_complete %>%
tabyl(continent) %>%
adorn_totals("row") %>%
adorn_pct_formatting() %>%
knitr::kable()
| Asia |
25 |
19.5% |
| Europe |
30 |
23.4% |
| Africa |
48 |
37.5% |
| Americas |
23 |
18.0% |
| Oceania |
2 |
1.6% |
| Total |
128 |
100.0% |
top5_countries <- gap_full %>%
filter(year == 2018) %>%
arrange(-pop) %>%
select(country) %>%
head(5) %>%
pull()
gap_full %>%
filter(country %in% top5_countries) %>%
ggplot() +
geom_line(mapping = aes(x = year, y = pop, color = country))+
theme_bw()

gap_2018_complete %>%
ggplot(aes(x=continent, fill=continent)) +
geom_bar() +
scale_y_continuous(expand=expansion(mult=c(0,0.1))) +
labs(x = "",
y = "Number of countries") +
theme(legend.position="none",
panel.grid.major.x = element_blank())

Summary
statistics
The summary statistics for the numeric variables in the 2018
Gapminder dataset look as follows:
library(pander)
gap_2018_complete %>%
select(-country) %>%
summary() %>%
pander()
| Min. : 211000 |
Min. :52.40 |
Min. :1.240 |
Min. : 211 |
Asia :25 |
| 1st Qu.: 5315000 |
1st Qu.:66.53 |
1st Qu.:1.760 |
1st Qu.: 1408 |
Europe :30 |
| Median : 11950000 |
Median :74.85 |
Median :2.325 |
Median : 5440 |
Africa :48 |
| Mean : 54546391 |
Mean :73.13 |
Mean :2.852 |
Mean :14306 |
Americas:23 |
| 3rd Qu.: 38025000 |
3rd Qu.:79.35 |
3rd Qu.:4.110 |
3rd Qu.:16075 |
Oceania : 2 |
| Max. :1430000000 |
Max. :85.00 |
Max. :7.130 |
Max. :92100 |
NA |
Distribution of
variables
We want to explore how some of the numeric variables in our dataset
are distributed.
library(patchwork)
d1 <- gap_2018_complete %>%
ggplot(aes(x = life_exp)) +
geom_density(fill="#69b3a2",
color="#e9ecef") +
scale_y_continuous(expand=expansion(mult=c(0,0.1)))
d2 <- gap_2018_complete %>%
ggplot(aes(x = gdp_percap)) +
geom_density(fill="#69b3a2",
color="#e9ecef") +
scale_y_continuous(expand=expansion(mult=c(0,0.1)))
d1 + d2

As we can see, GDP per capita is heavily right-skewed.
We also want to know how the variables are distributed for the
individual continents.
gap_2018_complete %>%
ggplot(aes(x = life_exp, group = continent, fill = continent)) +
geom_density(alpha = .4) +
scale_y_continuous(expand=expansion(mult=c(0,0.1)))

gap_2018_complete %>%
ggplot(aes(x = gdp_percap, group = continent, fill = continent)) +
geom_density(alpha = .4) +
scale_y_continuous(expand=expansion(mult=c(0,0.1)))

Comparisons between
continents
How do life expectancy, fertility rate, and GPD per capita differ
between continents?
gap_2018_complete %>%
ggplot(aes(x = continent, y = life_exp)) +
geom_boxplot(outlier.colour = "hotpink") +
geom_jitter(position = position_jitter(width = 0.1, height = 0),
alpha = 0.25)

gap_2018_complete %>%
ggplot(aes(x = continent, y = fert)) +
geom_boxplot(outlier.colour = "hotpink") +
geom_jitter(position = position_jitter(width = 0.1, height = 0),
alpha = 0.25)

gap_2018_complete %>%
ggplot(aes(x = continent, y = gdp_percap)) +
geom_boxplot(outlier.colour = "hotpink") +
geom_jitter(position = position_jitter(width = 0.1, height = 0),
alpha = 0.25)

Visualizing
relationships between continent, population, GDP per capita, and life
expectancy
To visualize relationships between continent, population, GDP per
capita, and life expectancy we use a bubble plot as made popular by the
TED
talk by Hans Rosling. Note that, due to the heavily skewed
distribution of GDP per capita, the X-axis in the plot uses a
log-scale.
gap_2018_complete %>%
ggplot(aes(x = gdp_percap, y = life_exp)) +
geom_point(aes(size = pop, color = continent), alpha = .5) +
scale_x_log10(breaks = c(500, 1000, 2000, 4000,
8000, 16000, 32000, 64000)) +
scale_y_continuous(breaks = seq(0, 90, by = 10))

Analyses
Correlations
We first want to look at the correlations between the numeric
variables in our dataset.
library(correlation)
library(GGally)
gap_2018_complete %>%
select(-c(country, continent)) %>%
correlation %>%
knitr::kable()
| pop |
life_exp |
0.0081307 |
0.95 |
-0.1656335 |
0.1814053 |
0.0912699 |
126 |
1.00000 |
Pearson correlation |
128 |
| pop |
fert |
-0.0878368 |
0.95 |
-0.2574432 |
0.0870201 |
-0.9897908 |
126 |
0.97252 |
Pearson correlation |
128 |
| pop |
gdp_percap |
-0.0536373 |
0.95 |
-0.2250729 |
0.1210196 |
-0.6029451 |
126 |
1.00000 |
Pearson correlation |
128 |
| life_exp |
fert |
-0.8188908 |
0.95 |
-0.8689424 |
-0.7522581 |
-16.0153991 |
126 |
0.00000 |
Pearson correlation |
128 |
| life_exp |
gdp_percap |
0.6791337 |
0.95 |
0.5731490 |
0.7627713 |
10.3857012 |
126 |
0.00000 |
Pearson correlation |
128 |
| fert |
gdp_percap |
-0.5068098 |
0.95 |
-0.6253433 |
-0.3654166 |
-6.5992393 |
126 |
0.00000 |
Pearson correlation |
128 |
gap_2018_complete %>%
select(-c(country, continent)) %>%
ggcorr(label = TRUE,
label_round = 2)

Regression
analysis
We use a linear OLS regression model to explore how life expectancy
is predicted by fertility rate and GPD per capita.
library(broom)
model <- lm(life_exp ~ fert + gdp_percap, data = gap_2018_complete)
tidy_model <- model %>%
tidy()
tidy_model %>%
knitr::kable()
| (Intercept) |
81.2050435 |
1.0124840 |
80.203782 |
0 |
| fert |
-3.5122524 |
0.2768809 |
-12.685067 |
0 |
| gdp_percap |
0.0001356 |
0.0000192 |
7.057679 |
0 |
The unstandardized regression coefficient for fertility rate is
b = -3.51 (p<0.001), while the coefficient for GDP per
capita is b = 0 (p<0.001).
Regression
plots
library(sjPlot)
plot_model(model,
type = "std")

LS0tCnRpdGxlOiAiRXhwbG9yaW5nIGRhdGEgZnJvbSBHYXBtaW5kZXIiCmF1dGhvcjogIlIgVXNlciIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0aGVtZTogZmxhdGx5CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBkZl9wcmludDogcGFnZWQKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFKQoKb3B0aW9ucyhzY2lwZW4gPSAxNSkKCmBgYAoKYGBge3IgbG9hZC13cmFuZ2xlLWRhdGEsIGVjaG8gPSBGQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCgpnYXBfY29udCA8LSByZWFkX2NzdigiLi4vZGF0YS9jb3VudHJpZXNfY29udGluZW50LmNzdiIpCgpnYXBfbGlmZSA8LSByZWFkX2NzdigiLi4vZGF0YS9saWZlX2V4cGVjdGFuY3lfeWVhcnMuY3N2IikKCmdhcF9wb3AgPC0gcmVhZF9jc3YoIi4uL2RhdGEvcG9wdWxhdGlvbl90b3RhbC5jc3YiKQoKZ2FwX2dkcCA8LSByZWFkX2NzdigiLi4vZGF0YS9nZHBwZXJjYXBpdGFfdXNfaW5mbGF0aW9uX2FkanVzdGVkLmNzdiIpCgpnYXBfZmVydCA8LSByZWFkX2NzdigiLi4vZGF0YS9jaGlsZHJlbl9wZXJfd29tYW5fdG90YWxfZmVydGlsaXR5LmNzdiIpCgpnYXBfY29udCA8LSBnYXBfY29udCAlPiUgCiAgbXV0YXRlKGNvbnRpbmVudCA9IGFzX2ZhY3Rvcihjb250aW5lbnQpKQoKZ2FwX2xpZmUgPC0gZ2FwX2xpZmUgJT4lIAogIHBpdm90X2xvbmdlcigtY291bnRyeSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAieWVhciIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJsaWZlX2V4cCIpICU+JSAKICBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoeWVhcikpCgpnYXBfcG9wIDwtIGdhcF9wb3AgJT4lIAogIHBpdm90X2xvbmdlcigtY291bnRyeSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAieWVhciIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJwb3AiKSAlPiUgCiAgbXV0YXRlKHllYXIgPSBhcy5udW1lcmljKHllYXIpKQoKZ2FwX2dkcCA8LSBnYXBfZ2RwICU+JSAKICBwaXZvdF9sb25nZXIoLWNvdW50cnksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInllYXIiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiZ2RwX3BlcmNhcCIpICU+JSAKICBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoeWVhcikpCgpnYXBfZmVydCA8LSBnYXBfZmVydCAlPiUgCiAgcGl2b3RfbG9uZ2VyKC1jb3VudHJ5LAogICAgICAgICAgICAgICBuYW1lc190byA9ICJ5ZWFyIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImZlcnQiKSAlPiUgCiAgbXV0YXRlKHllYXIgPSBhcy5udW1lcmljKHllYXIpKQoKZ2FwX2Z1bGwgPC0gZ2FwX3BvcCAlPiUgCiAgZnVsbF9qb2luKGdhcF9saWZlLCBieSA9IGMoImNvdW50cnkiLCAieWVhciIpKSAlPiUgCiAgZnVsbF9qb2luKGdhcF9mZXJ0LCBieSA9IGMoImNvdW50cnkiLCAieWVhciIpKSAlPiUgCiAgZnVsbF9qb2luKGdhcF9nZHAsIGJ5ID0gYygiY291bnRyeSIsICJ5ZWFyIikpICU+JQogIGxlZnRfam9pbihnYXBfY29udCwgYnkgPSAiY291bnRyeSIpIAoKbWF4X3llYXIgPC0gbWF4KGdhcF9nZHAkeWVhcikKCmdhcF8yMDE4IDwtIGdhcF9mdWxsICU+JSAKICBmaWx0ZXIoeWVhciA9PSBtYXhfeWVhcikgJT4lIAogIHNlbGVjdCgteWVhcikKCmdhcF8yMDE4X2NvbXBsZXRlIDwtIGdhcF8yMDE4ICU+JSAKICBkcm9wX25hKCkKYGBgCgojIFRoZSBkYXRhCgpUaGUgZGF0YSB3ZSBhcmUgdXNpbmcgY29tZXMgZnJvbSBbKkdhcG1pbmRlcipdKGh0dHBzOi8vd3d3LmdhcG1pbmRlci5vcmcvKS4gV2Ugd2lsbCB1c2UgZGF0YSBvbiBwb3B1bGF0aW9uLCBsaWZlIGV4cGVjdGFuY3ksIGZlcnRpbGl0eSByYXRlLCBhbmQgR0RQIHBlciBjYXBpdGEuIFRoZSBmdWxsIGNvbWJpbmVkIGRhdGFzZXQgY29udGFpbnMgZGF0YSBmcm9tIGByIG5fZGlzdGluY3QoZ2FwX2Z1bGwkY291bnRyeSlgIGNvdW50cmllcy4gQXMgKkdhcG1pbmRlciogY29sbGVjdHMgdGhlIGRhdGEgZnJvbSBkaWZmZXJlbnQgc291cmNlcyBhbmQgdGhlcmUgYXJlIGRpZmZlcmVuY2VzIGluIHRoZSBhdmFpbGFiaWxpdHkgb2YgZGlmZmVyZW50IGtpbmRzIG9mIGRhdGEsIHRoZSBpbmRpdmlkdWFsIGRhdGFzZXRzIChmb3IgbGlmZSBleHBlY3RhbmN5LCBHRFAgcGVyIGNhcGl0YSwgZXRjLikgZGlmZmVyIHJlZ2FyZGluZyB0aGUgbnVtYmVyIG9mIGNvdW50cmllcyBhbmQgeWVhcnMgdGhleSBjb3Zlci4gTm90YWJseSwgYWxsIG9mIHRoZW0gZXhjZXB0IHRoZSBvbmUgb24gR0RQIHBlciBjYXBpdGEgYWxzbyBjb250YWluIHByb2plY3RlZCBkYXRhIHVudGlsIHRoZSB5ZWFyIGByIG1heChnYXBfcG9wJHllYXIpYC4gVGhlIGRhdGEgb24gcG9wdWxhdGlvbiwgbGlmZSBleHBlY3RhbmN5LCBhbmQgZmVydGlsaXR5IHJhdGUgYWxzbyBhbGwgZ28gYmFjayB0byBgciBtaW4oZ2FwX3BvcCR5ZWFyKWAuIFRoZSBkYXRhIG9uIEdEUCBwZXIgY2FwaXRhLCBob3dldmVyLCBhcmUgb25seSBhdmFpbGFibGUgZm9yIHRoZSB5ZWFycyBmcm9tIGByIG1pbihnYXBfZ2RwJHllYXIpYCB0byBgciBtYXgoZ2FwX2dkcCR5ZWFyKWAuIEFsc28sIHRoZXJlIGlzIG1pc3NpbmcgZGF0YSBmb3IgbWFueSBjb3VudHJpZXMgZm9yIGRpZmZlcmVudCB5ZWFycy4KCiMjIE1pc3NpbmcgZGF0YQoKQXMgd2UgZG8gbm90IGhhdmUgZGF0YSBmb3IgYWxsIHZhcmlhYmxlcyBmb3IgYWxsIGNvdW50cmllcyBhbmQgeWVhcnMsIHdlIHdhbnQgdG8ga25vdyB3aGV0aGVyIHRoZXJlIGFyZSBpZGVudGlmaWFibGUgcGF0dGVybnMgb2YgbWlzc2luZ25lc3MgaW4gb3VyIGRhdGEuCgpgYGB7ciB2aXMtbWlzc30KbGlicmFyeSh2aXNkYXQpCgp2aXNfbWlzcyhnYXBfZnVsbCkKYGBgCgojIyBEYXRhIGZvciAyMDE4CgpHaXZlbiB0aGF0IHdlIG9ubHkgaGF2ZSBkYXRhIG9uIEdEUCBwZXIgY2FwaXRhIGZyb20gYHIgbWluKGdhcF9nZHAkeWVhcilgIHRvIGByIG1heChnYXBfZ2RwJHllYXIpYCwgd2Ugd2lsbCBmb2N1cyBvbiBkYXRhIGZyb20gdGhlIHllYXIgYHIgbWF4KGdhcF9nZHAkeWVhcilgIGluIG91ciBhbmFseXNpcy4gVGhlIGRhdGFzZXQgZm9yIGByIG1heChnYXBfZ2RwJHllYXIpYCBjb250YWlucyBkYXRhIGZvciBgciBucm93KGdhcF8yMDE4KWAgY291bnRyaWVzIGZyb20gYHIgbl9kaXN0aW5jdChnYXBfMjAxOCRjb250aW5lbnQpYCBjb250aW5lbnRzLiBMZXQncyBoYXZlIGEgbG9vayBhdCB0aGlzIGRhdGFzZXQuCgpgYGB7ciBmdWxsLXRhYmxlfQpnYXBfMjAxOApgYGAKCiMjIyBNaXNzaW5nIGRhdGEgaW4gdGhlIDIwMTggZGF0YXNldAoKVGhlIDIwMTggZGF0YXNldCBzdGlsbCBoYXMgc29tZSBtaXNzaW5nIGRhdGEuCgpgYGB7ciBtaXNzLTIwMTh9CmxpYnJhcnkobmFuaWFyKQoKZ2dfbWlzc192YXIoZ2FwXzIwMTgpCmBgYAoKV2Ugc2VlIHRoYXQgd2UgaGF2ZSB0aGUgbW9zdCBtaXNzaW5nIHZhbHVlcyBmb3IgdGhlIGBjb250aW5lbnRgIHZhcmlhYmxlLiBUaGUgcmVhc29uIGZvciB0aGlzIGlzIHRoYXQgdGhpcyB2YXJpYWJsZSBjb21lcyBmcm9tIGEgZGlmZmVyZW50IHNvdXJjZTogdGhlIGRhdGEgaW5jbHVkZWQgaW4gdGhlIFtgZ2FwbWluZGVyYCBwYWNrYWdlXShodHRwczovL2dpdGh1Yi5jb20vamVubnliYy9nYXBtaW5kZXIpLiBGb3Igb3VyIGFuYWx5c2VzLCB3ZSB3aWxsIG9ubHkgdXNlIHRoZSBjb3VudHJpZXMgZm9yIHdoaWNoIHdlIGhhdmUgY29tcGxldGUgZGF0YSBmb3IgMjAxOC4gVGhpcyBkYXRhc2V0IGluY2x1ZGVzIGRhdGEgZnJvbSBgciBucm93KGdhcF8yMDE4X2NvbXBsZXRlKWAgY291bnRyaWVzLgoKIyBFeHBsb3JpbmcgdGhlIDIwMTggKkdhcG1pbmRlciogZGF0YQoKIyMgQ291bnRyaWVzIHBlciBjb250aW5lbnQKCkhvdyBtYW55IGNvdW50cmllcyBwZXIgY29udGluZW50IGFyZSBpbmNsdWRlZCBpbiBvdXIgY29tcGxldGUgMjAxOCBkYXRhc2V0PwoKYGBge3IgY29udGluZW50cyx9CmxpYnJhcnkoamFuaXRvcikKCmdhcF8yMDE4X2NvbXBsZXRlICU+JSAKICB0YWJ5bChjb250aW5lbnQpICU+JSAKICBhZG9ybl90b3RhbHMoInJvdyIpICU+JQogIGFkb3JuX3BjdF9mb3JtYXR0aW5nKCkgJT4lIAogIGtuaXRyOjprYWJsZSgpCmBgYAoKYGBge3J9CnRvcDVfY291bnRyaWVzIDwtIGdhcF9mdWxsICU+JQogICAgIGZpbHRlcih5ZWFyID09IDIwMTgpICU+JSAKICAgICBhcnJhbmdlKC1wb3ApICU+JSAKICAgICBzZWxlY3QoY291bnRyeSkgJT4lIAogICAgIGhlYWQoNSkgJT4lIAogICAgIHB1bGwoKQoKZ2FwX2Z1bGwgJT4lIAogIGZpbHRlcihjb3VudHJ5ICVpbiUgdG9wNV9jb3VudHJpZXMpICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKG1hcHBpbmcgPSBhZXMoeCA9IHllYXIsIHkgPSBwb3AsIGNvbG9yID0gY291bnRyeSkpKwogIHRoZW1lX2J3KCkKYGBgCgpgYGB7ciBjb3VudHJpZXMtY29udH0KZ2FwXzIwMThfY29tcGxldGUgJT4lIAogIGdncGxvdChhZXMoeD1jb250aW5lbnQsIGZpbGw9Y29udGluZW50KSkgKyAKICBnZW9tX2JhcigpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kPWV4cGFuc2lvbihtdWx0PWMoMCwwLjEpKSkgKwogIGxhYnMoeCA9ICIiLAogICAgICAgeSA9ICJOdW1iZXIgb2YgY291bnRyaWVzIikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci54ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIFN1bW1hcnkgc3RhdGlzdGljcwoKVGhlIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgdGhlIG51bWVyaWMgdmFyaWFibGVzIGluIHRoZSAyMDE4ICpHYXBtaW5kZXIqIGRhdGFzZXQgbG9vayBhcyBmb2xsb3dzOgoKYGBge3Igc3VtbWFyeXN0YXRzfQpsaWJyYXJ5KHBhbmRlcikKCmdhcF8yMDE4X2NvbXBsZXRlICU+JSAKICBzZWxlY3QoLWNvdW50cnkpICU+JSAKICBzdW1tYXJ5KCkgJT4lIAogIHBhbmRlcigpCmBgYAoKIyMgRGlzdHJpYnV0aW9uIG9mIHZhcmlhYmxlcwoKV2Ugd2FudCB0byBleHBsb3JlIGhvdyBzb21lIG9mIHRoZSBudW1lcmljIHZhcmlhYmxlcyBpbiBvdXIgZGF0YXNldCBhcmUgZGlzdHJpYnV0ZWQuCgpgYGB7ciBkZW5zaXR5fQpsaWJyYXJ5KHBhdGNod29yaykKCmQxIDwtIGdhcF8yMDE4X2NvbXBsZXRlICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsaWZlX2V4cCkpICsKICBnZW9tX2RlbnNpdHkoZmlsbD0iIzY5YjNhMiIsCiAgICAgICAgICAgICAgIGNvbG9yPSIjZTllY2VmIikgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQ9ZXhwYW5zaW9uKG11bHQ9YygwLDAuMSkpKQoKZDIgPC0gZ2FwXzIwMThfY29tcGxldGUgJT4lIAogIGdncGxvdChhZXMoeCA9IGdkcF9wZXJjYXApKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGw9IiM2OWIzYTIiLAogICAgICAgICAgICAgICBjb2xvcj0iI2U5ZWNlZiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kPWV4cGFuc2lvbihtdWx0PWMoMCwwLjEpKSkKCmQxICsgZDIKYGBgCgpBcyB3ZSBjYW4gc2VlLCBHRFAgcGVyIGNhcGl0YSBpcyBoZWF2aWx5IHJpZ2h0LXNrZXdlZC4KCldlIGFsc28gd2FudCB0byBrbm93IGhvdyB0aGUgdmFyaWFibGVzIGFyZSBkaXN0cmlidXRlZCBmb3IgdGhlIGluZGl2aWR1YWwgY29udGluZW50cy4KCmBgYHtyIGxpZmVleHAtY29udH0KZ2FwXzIwMThfY29tcGxldGUgJT4lIAogIGdncGxvdChhZXMoeCA9IGxpZmVfZXhwLCBncm91cCA9IGNvbnRpbmVudCwgZmlsbCA9IGNvbnRpbmVudCkpICsKICBnZW9tX2RlbnNpdHkoYWxwaGEgPSAuNCkgKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQ9ZXhwYW5zaW9uKG11bHQ9YygwLDAuMSkpKQpgYGAKCmBgYHtyIGdkcC1jb250fQpnYXBfMjAxOF9jb21wbGV0ZSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZ2RwX3BlcmNhcCwgZ3JvdXAgPSBjb250aW5lbnQsIGZpbGwgPSBjb250aW5lbnQpKSArCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gLjQpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kPWV4cGFuc2lvbihtdWx0PWMoMCwwLjEpKSkKYGBgCgojIyBDb21wYXJpc29ucyBiZXR3ZWVuIGNvbnRpbmVudHMKCkhvdyBkbyBsaWZlIGV4cGVjdGFuY3ksIGZlcnRpbGl0eSByYXRlLCBhbmQgR1BEIHBlciBjYXBpdGEgZGlmZmVyIGJldHdlZW4gY29udGluZW50cz8KCmBgYHtyIGJveC1saWZlZXhwfQpnYXBfMjAxOF9jb21wbGV0ZSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29udGluZW50LCB5ID0gbGlmZV9leHApKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gImhvdHBpbmsiKSArCiAgZ2VvbV9qaXR0ZXIocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjEsIGhlaWdodCA9IDApLAogICAgICAgICAgICAgIGFscGhhID0gMC4yNSkKYGBgCgpgYGB7ciBib3gtZmVydH0KZ2FwXzIwMThfY29tcGxldGUgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvbnRpbmVudCwgeSA9IGZlcnQpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gImhvdHBpbmsiKSArCiAgZ2VvbV9qaXR0ZXIocG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjEsIGhlaWdodCA9IDApLAogICAgICAgICAgICAgIGFscGhhID0gMC4yNSkKYGBgCgpgYGB7ciBib3gtZ2RwfQpnYXBfMjAxOF9jb21wbGV0ZSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29udGluZW50LCB5ID0gZ2RwX3BlcmNhcCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXIgPSAiaG90cGluayIpICsKICBnZW9tX2ppdHRlcihwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcih3aWR0aCA9IDAuMSwgaGVpZ2h0ID0gMCksCiAgICAgICAgICAgICAgYWxwaGEgPSAwLjI1KQpgYGAKCiMjIFZpc3VhbGl6aW5nIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBjb250aW5lbnQsIHBvcHVsYXRpb24sIEdEUCBwZXIgY2FwaXRhLCBhbmQgbGlmZSBleHBlY3RhbmN5CgpUbyB2aXN1YWxpemUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIGNvbnRpbmVudCwgcG9wdWxhdGlvbiwgR0RQIHBlciBjYXBpdGEsIGFuZCBsaWZlIGV4cGVjdGFuY3kgd2UgdXNlIGEgYnViYmxlIHBsb3QgYXMgbWFkZSBwb3B1bGFyIGJ5IHRoZSBbVEVEIHRhbGsgYnkgSGFucyBSb3NsaW5nXShodHRwczovL3d3dy50ZWQuY29tL3RhbGtzL2hhbnNfcm9zbGluZ190aGVfYmVzdF9zdGF0c195b3VfdmVfZXZlcl9zZWVuKS4gTm90ZSB0aGF0LCBkdWUgdG8gdGhlIGhlYXZpbHkgc2tld2VkIGRpc3RyaWJ1dGlvbiBvZiBHRFAgcGVyIGNhcGl0YSwgdGhlIFgtYXhpcyBpbiB0aGUgcGxvdCB1c2VzIGEgbG9nLXNjYWxlLgoKYGBge3IgYnViYmxlfQpnYXBfMjAxOF9jb21wbGV0ZSAlPiUgCmdncGxvdChhZXMoeCA9IGdkcF9wZXJjYXAsIHkgPSBsaWZlX2V4cCkpICsKICBnZW9tX3BvaW50KGFlcyhzaXplID0gcG9wLCBjb2xvciA9IGNvbnRpbmVudCksIGFscGhhID0gLjUpICsKICBzY2FsZV94X2xvZzEwKGJyZWFrcyA9IGMoNTAwLCAxMDAwLCAyMDAwLCA0MDAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICA4MDAwLCAxNjAwMCwgMzIwMDAsIDY0MDAwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgOTAsIGJ5ID0gMTApKQpgYGAKCiMgQW5hbHlzZXMKCiMjIENvcnJlbGF0aW9ucwoKV2UgZmlyc3Qgd2FudCB0byBsb29rIGF0IHRoZSBjb3JyZWxhdGlvbnMgYmV0d2VlbiB0aGUgbnVtZXJpYyB2YXJpYWJsZXMgaW4gb3VyIGRhdGFzZXQuCgpgYGB7ciBjb3JyZWxhdGlvbnN9CmxpYnJhcnkoY29ycmVsYXRpb24pCmxpYnJhcnkoR0dhbGx5KQoKZ2FwXzIwMThfY29tcGxldGUgJT4lIAogIHNlbGVjdCgtYyhjb3VudHJ5LCBjb250aW5lbnQpKSAlPiUgCiAgY29ycmVsYXRpb24gJT4lIAogIGtuaXRyOjprYWJsZSgpCgpnYXBfMjAxOF9jb21wbGV0ZSAlPiUgCiAgc2VsZWN0KC1jKGNvdW50cnksIGNvbnRpbmVudCkpICU+JSAKICBnZ2NvcnIobGFiZWwgPSBUUlVFLAogICAgICAgICBsYWJlbF9yb3VuZCA9IDIpCmBgYAoKIyMgUmVncmVzc2lvbiBhbmFseXNpcwoKV2UgdXNlIGEgbGluZWFyIE9MUyByZWdyZXNzaW9uIG1vZGVsIHRvIGV4cGxvcmUgaG93IGxpZmUgZXhwZWN0YW5jeSBpcyBwcmVkaWN0ZWQgYnkgZmVydGlsaXR5IHJhdGUgYW5kIEdQRCBwZXIgY2FwaXRhLgoKYGBge3IgcmVncmVzc2lvbn0KbGlicmFyeShicm9vbSkKCm1vZGVsIDwtIGxtKGxpZmVfZXhwIH4gZmVydCArIGdkcF9wZXJjYXAsIGRhdGEgPSBnYXBfMjAxOF9jb21wbGV0ZSkKCnRpZHlfbW9kZWwgPC0gbW9kZWwgJT4lIAogIHRpZHkoKQoKdGlkeV9tb2RlbCAlPiUgCiAga25pdHI6OmthYmxlKCkKCmdsYW5jZShtb2RlbCkKYGBgCgpUaGUgdW5zdGFuZGFyZGl6ZWQgcmVncmVzc2lvbiBjb2VmZmljaWVudCBmb3IgZmVydGlsaXR5IHJhdGUgaXMgKmIqID0gYHIgcm91bmQodGlkeV9tb2RlbCRlc3RpbWF0ZVsyXSwgMilgIChgciBzY2FsZXM6OnB2YWx1ZSh0aWR5X21vZGVsJHAudmFsdWVbMl0sIGFjY3VyYWN5ID0gMC4wMDEsIGFkZF9wID0gVFJVRSlgKSwgd2hpbGUgdGhlIGNvZWZmaWNpZW50IGZvciBHRFAgcGVyIGNhcGl0YSBpcyAqYiogPSBgciByb3VuZCh0aWR5X21vZGVsJGVzdGltYXRlWzNdLCAyKWAgKGByIHNjYWxlczo6cHZhbHVlKHRpZHlfbW9kZWwkcC52YWx1ZVszXSwgYWNjdXJhY3kgPSAwLjAwMSwgYWRkX3AgPSBUUlVFKWApLgoKIyMjIFJlZ3Jlc3Npb24gcGxvdHMKCmBgYHtyIHJlZ3Jlc3Npb24tcGxvdHN9CmxpYnJhcnkoc2pQbG90KQoKcGxvdF9tb2RlbChtb2RlbCwKICAgICAgICAgICB0eXBlID0gInN0ZCIpCgpgYGAKCgo=