1 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.

1.1 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)

1.2 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.

gap_2018

1.2.1 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.

2 Exploring the 2018 Gapminder data

2.1 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()
continent n percent
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())

2.2 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()
pop life_exp fert gdp_percap continent
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

2.3 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)))

2.4 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)

2.5 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))

3 Analyses

3.1 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()
Parameter1 Parameter2 r CI CI_low CI_high t df_error p Method n_Obs
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)

3.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()
term estimate std.error statistic p.value
(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
glance(model)

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).

3.2.1 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=