Hide all the warnings messages
knitr::opts_chunk$set(message = FALSE, warning = FALSE)
Packages
pacman::p_load(tidyverse, # for data science
janitor, # to clean names
visdat) # for NAs visualization
# uploaded the dataset to a google drive and published as csv file
happiness <- read_csv("https://docs.google.com/spreadsheets/d/e/2PACX-1vQQlW28r9deAndL9Jq0tBy93o3273SWFSR1Rrgtn2jS37rjfJALF5dlwATtqm7SPZYctV4hJxb34azG/pub?gid=684260656&single=true&output=csv")
head(happiness) # for data exploration
## # A tibble: 6 × 11
## `Country name` year `Life Ladder` `Log GDP per capita` `Social support`
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Afghanistan 2008 3.72 7.37 0.451
## 2 Afghanistan 2009 4.40 7.54 0.552
## 3 Afghanistan 2010 4.76 7.65 0.539
## 4 Afghanistan 2011 3.83 7.62 0.521
## 5 Afghanistan 2012 3.78 7.70 0.521
## 6 Afghanistan 2013 3.57 7.72 0.484
## # … with 6 more variables: Healthy life expectancy at birth <dbl>,
## # Freedom to make life choices <dbl>, Generosity <dbl>,
## # Perceptions of corruption <dbl>, Positive affect <dbl>,
## # Negative affect <dbl>
clean the names, removing the white spaces, etc. The manipulation of clean names is easier
happiness <- happiness %>%
janitor::clean_names()
check the variables
glimpse(happiness)
## Rows: 1,949
## Columns: 11
## $ country_name <chr> "Afghanistan", "Afghanistan", "Afghan…
## $ year <dbl> 2008, 2009, 2010, 2011, 2012, 2013, 2…
## $ life_ladder <dbl> 3.724, 4.402, 4.758, 3.832, 3.783, 3.…
## $ log_gdp_per_capita <dbl> 7.370, 7.540, 7.647, 7.620, 7.705, 7.…
## $ social_support <dbl> 0.451, 0.552, 0.539, 0.521, 0.521, 0.…
## $ healthy_life_expectancy_at_birth <dbl> 50.80, 51.20, 51.60, 51.92, 52.24, 52…
## $ freedom_to_make_life_choices <dbl> 0.718, 0.679, 0.600, 0.496, 0.531, 0.…
## $ generosity <dbl> 0.168, 0.190, 0.121, 0.162, 0.236, 0.…
## $ perceptions_of_corruption <dbl> 0.882, 0.850, 0.707, 0.731, 0.776, 0.…
## $ positive_affect <dbl> 0.518, 0.584, 0.618, 0.611, 0.710, 0.…
## $ negative_affect <dbl> 0.258, 0.237, 0.275, 0.267, 0.268, 0.…
check the completeness of the dataset
Check the completeness of the dataset. The grey spots are NAs values
visdat::vis_dat(happiness)

Data exploration
Baltics countries
happiness %>%
filter(country_name %in% c("Latvia", "Estonia", "Lithuania")) %>% # filter some countries
ggplot(aes(x = year,
y = life_ladder,
color = country_name)) +
geom_line() +
labs(title = "Happiness in Baltic by year",
y = "Happiness (0= worst, 10 = best)",
x = "Year",
color = "Country")

Group all the variables to make many plots at once
There are some absolute value variables and some related to a survey
log_gdp_per_capita
healthy_life_expectancy_at_birth
life_ladder: Happiness score or subjective well-being. 0 worst, 10 best
The ones from the survey can be collapsed into one column
happiness %>%
filter(country_name %in% c("Latvia", "Estonia", "Lithuania")) %>% # filter some countries
# relocate one column to make it easier the pivoting later
relocate(social_support, .after = healthy_life_expectancy_at_birth) %>%
# now reshape the dataset
pivot_longer(social_support:negative_affect,
names_to = "name_variable",
values_to = "name_value") %>%
# change the name of the levels of name_variable
mutate(name_variable = recode(name_variable, # change the variable, recoding the levels
freedom_to_make_life_choices = "Freedom", # old name = new name
generosity = "Generosity",
negative_affect = "Negative",
perceptions_of_corruption = "Corruption",
positive_affect = "Positive",
social_support = "Support")) %>%
# make the plot
ggplot(aes(x = year,
y = name_value,
color = country_name)) +
geom_line() +
facet_grid(. ~ name_variable ) +
labs(title = "Survey results in the Baltic countries",
y = "Survey results",
color = "Country",
x = "Year")

Join with another dataset
It would be interesting to group by continent. I could add by hand the continent for each country, but it is much simpler if I take another database where each country has the continent information.
Take this as an example in case you want to cross some happiness variable with another one, for example, from the world bank. The key is that both databases must have a column to fit. You can also match by two columns, for example, country and year.
Googling, I found this dataset with the required information of the countries and continents https://github.com/lukes/ISO-3166-Countries-with-Regional-Codes/blob/master/all/all.csv
countries <- read_csv("https://raw.githubusercontent.com/lukes/ISO-3166-Countries-with-Regional-Codes/master/all/all.csv")
head(countries)
## # A tibble: 6 × 11
## name `alpha-2` `alpha-3` `country-code` `iso_3166-2` region `sub-region`
## <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 Afghanis… AF AFG 004 ISO 3166-2:… Asia Southern Asia
## 2 Åland Is… AX ALA 248 ISO 3166-2:… Europe Northern Eur…
## 3 Albania AL ALB 008 ISO 3166-2:… Europe Southern Eur…
## 4 Algeria DZ DZA 012 ISO 3166-2:… Africa Northern Afr…
## 5 American… AS ASM 016 ISO 3166-2:… Ocean… Polynesia
## 6 Andorra AD AND 020 ISO 3166-2:… Europe Southern Eur…
## # … with 4 more variables: intermediate-region <chr>, region-code <chr>,
## # sub-region-code <chr>, intermediate-region-code <chr>
For how to join different datasets, see https://www.youtube.com/watch?v=Yg-pNqzDuN4 and this https://craig.rbind.io/post/2020-03-29-asgr-2-2-joining-data/
# overwrite the old dataset
happiness <-
# with a new one, where we will add the name dataset, matching by the columns "country_name" from the happiness data set and "name" from the countries data set
left_join(happiness, countries, by = c("country_name" = "name")) %>%
select(country_name:negative_affect, "alpha-3", "region", "sub-region")
Now I have the happiness dataset with the information of the continents (region)
summarize the life_ladder accross continents
happiness %>%
filter(region != "NA") %>% # remove the antartica, etc
# calculate the mean happines by continent and year
group_by(region, year) %>%
summarise(mean_happiness = mean(life_ladder)) %>%
# make the plot
ggplot(aes(x = year,
y = mean_happiness,
color = region)) +
geom_line() +
labs(title = "Happiness by continent and year",
y = "Happiness (0= worst, 10 = best)",
x = "Year",
color = "Continent")
## summary all continents at once And I can check all the variable sby continents at once
happiness %>%
# first relocate one column to make it easier
relocate(social_support, .after = healthy_life_expectancy_at_birth) %>%
# filter to exclude the NA continents
filter(region != "NA") %>%
# now reshape the dataset
pivot_longer(social_support:negative_affect,
names_to = "happiness_variable",
values_to = "happiness_value") %>%
# calculate the mean value per continent
group_by(happiness_variable, region, year) %>%
summarise(mean = mean(happiness_value, na.rm = T)) %>%
# change the name of the levels of name_variable
mutate(happiness_variable = recode(happiness_variable, # change the variable, recoding the levels
freedom_to_make_life_choices = "Freedom", # old name = new name
generosity = "Generosity",
negative_affect = "Negative",
perceptions_of_corruption = "Corruption",
positive_affect = "Positive",
social_support = "Support")) %>%
# and now plot
ggplot(aes(x = year,
y = mean,
color = region,
group = region)) +
geom_line() +
facet_grid(. ~ happiness_variable) +
labs(title = "Several variables in one plot",
y = "Mean value",
x = "Year",
color = "Continent")

All the variables for just for the Baltic countries
happiness %>%
# first relocate one column to make it easier to manipulate the variables during the pivoting
relocate(social_support, .after = healthy_life_expectancy_at_birth) %>%
# filter to exclude the NA continents
filter(region != "NA") %>%
# now filter only european countries
filter(region == "Europe") %>% # comnent this line to check for all the world
# now reshape the dataset
pivot_longer(social_support:negative_affect,
names_to = "happiness_variable",
values_to = "happiness_value") %>%
# calculate the mean value per continent
group_by(happiness_variable, country_name, year) %>%
summarise(mean = mean(happiness_value, na.rm = T)) %>%
# change the name of the levels of name_variable
mutate(happiness_variable = recode(happiness_variable, # change the variable, recoding the levels
freedom_to_make_life_choices = "Freedom", # old name = new name
generosity = "Generosity",
negative_affect = "Negative",
perceptions_of_corruption = "Corruption",
positive_affect = "Positive",
social_support = "Support")) %>%
# and now plot
ggplot(aes(x = year,
y = mean,
color = (country_name == "Latvia"),
group = country_name)) +
geom_line(alpha = .5) +
# change the name of levels in the legend
scale_color_manual(values=c("Grey", "red"),
labels=c("Other", "Latvia")) +
# now generate several plots, each for one variable
facet_grid(. ~ happiness_variable) + # this means rows and columns, in this case, no variable ~ happiness
labs(title = "Several variables in one plot",
y = "Mean value",
x = "Year",
color = "Country")
# gghightlight
Check Latvia for all the countries. I will use the gghighlight package
see https://cran.r-project.org/web/packages/gghighlight/vignettes/gghighlight.html
pacman::p_load(gghighlight)
# copy and paste all the code
happiness %>%
# first relocate one column to make it easier
relocate(social_support, .after = healthy_life_expectancy_at_birth) %>%
# filter to exclude the NA continents
filter(region != "NA") %>%
# now filter only european countries
# filter(region == "Europe") %>%
ggplot(aes(x = year,
y = life_ladder,
color = region,
group = country_name)) +
geom_line() +
gghighlight(country_name == "Latvia") +
labs(title = "Life ladder, all the world",
y = "Life ladder",
x = "Year")

for the baltic countries
# copy and paste all the code
happiness %>%
# first relocate one column to make it easier
relocate(social_support, .after = healthy_life_expectancy_at_birth) %>%
# filter to exclude the NA continents
filter(region != "NA") %>%
# now filter only european countries
# uncomment next line to filter european countries only
# filter(region == "Europe") %>%
ggplot(aes(x = year,
y = life_ladder,
color = country_name,
group = country_name)) +
geom_line() +
gghighlight(country_name %in% c("Latvia", "Estonia", "Lithuania")) +
labs(title = "Life ladder, all the world",
y = "Life ladder",
x = "Year")
## check the happiest
# copy and paste all the code
happiness %>%
# first relocate one column to make it easier
relocate(social_support, .after = healthy_life_expectancy_at_birth) %>%
# filter to exclude the NA continents
filter(region != "NA") %>%
# now filter only european countries
# uncomment next line to filter european countries only
# filter(region == "Europe") %>%
ggplot(aes(x = year,
y = life_ladder,
color = country_name,
group = country_name)) +
geom_line() +
gghighlight(life_ladder > 7.6) + # select some arbitraty threshold
labs(title = "Life ladder, all the world",
y = "Life ladder",
x = "Year")
## and the lowest happiness score
# copy and paste all the code
happiness %>%
# first relocate one column to make it easier
relocate(social_support, .after = healthy_life_expectancy_at_birth) %>%
# filter to exclude the NA continents
filter(region != "NA") %>%
# now filter only european countries
# uncomment next line to filter european countries only
# filter(region == "Europe") %>%
ggplot(aes(x = year,
y = life_ladder,
color = country_name,
group = country_name)) +
geom_line() +
gghighlight(life_ladder < 3) +
labs(title = "Life ladder, all the world",
y = "Life ladder",
x = "Year")
## top three from Europe
# copy and paste all the code
happiness %>%
# first relocate one column to make it easier
relocate(social_support, .after = healthy_life_expectancy_at_birth) %>%
# filter to exclude the NA continents
filter(region == "Europe") %>%
# now filter only european countries
# uncomment next line to filter european countries only
# filter(region == "Europe") %>%
ggplot(aes(x = year,
y = life_ladder,
color = country_name,
group = country_name)) +
geom_line() +
gghighlight(max(life_ladder), max_highlight = 3L) # select the top 3

labs(title = "Life ladder, all the world",
y = "Life ladder",
x = "Year")
## $y
## [1] "Life ladder"
##
## $x
## [1] "Year"
##
## $title
## [1] "Life ladder, all the world"
##
## attr(,"class")
## [1] "labels"
no gghighlight needed
Now with all variables and no gghighligth needed
happiness %>%
# first relocate one column to make it easier to manipulate the variables during the pivoting
relocate(social_support, .after = healthy_life_expectancy_at_birth) %>%
# filter to exclude the NA continents
filter(region != "NA") %>%
# now filter only european countries
filter(region == "Europe") %>% # comnent this line to check for all the world
# now reshape the dataset
pivot_longer(social_support:negative_affect,
names_to = "happiness_variable",
values_to = "happiness_value") %>%
# calculate the mean value per continent
group_by(happiness_variable, country_name, year) %>%
summarise(mean = mean(happiness_value, na.rm = T)) %>%
# change the name of the levels of name_variable
mutate(happiness_variable = recode(happiness_variable, # change the variable, recoding the levels
freedom_to_make_life_choices = "Freedom", # old name = new name
generosity = "Generosity",
negative_affect = "Negative",
perceptions_of_corruption = "Corruption",
positive_affect = "Positive",
social_support = "Support")) %>%
# and now plot
ggplot(aes(x = year,
y = mean,
color = (country_name == "Latvia"), # good trick! :D
group = country_name)) +
geom_line(alpha = .5) +
# change the name of levels in the legend
scale_color_manual(values=c("Grey", "red"),
labels=c("Other", "Latvia")) +
# now generate several plots, each for one variable
facet_grid(. ~ happiness_variable) + # this means rows and columns, in this case, no variable ~ happiness
labs(title = "Several variables in one plot",
y = "Mean value",
x = "Year",
color = "Country")

LS0tCnRpdGxlOiAiV29ybGQgSGFwcGluZXNzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDogCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IG5vCiAgICAgIHNtb290aF9zY3JvbGw6IG5vCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwotLS0KCkhpZGUgYWxsIHRoZSB3YXJuaW5ncyBtZXNzYWdlcwoKYGBge3J9CmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSkKYGBgCgojIFBhY2thZ2VzCgpgYGB7cn0KcGFjbWFuOjpwX2xvYWQodGlkeXZlcnNlLCAjIGZvciBkYXRhIHNjaWVuY2UKICAgICAgICAgICAgICAgamFuaXRvciwgICMgdG8gY2xlYW4gbmFtZXMKICAgICAgICAgICAgICAgdmlzZGF0KSAjIGZvciBOQXMgdmlzdWFsaXphdGlvbgpgYGAKCmBgYHtyfQojIHVwbG9hZGVkIHRoZSBkYXRhc2V0IHRvIGEgZ29vZ2xlIGRyaXZlIGFuZCBwdWJsaXNoZWQgYXMgY3N2IGZpbGUKaGFwcGluZXNzIDwtIHJlYWRfY3N2KCJodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9zcHJlYWRzaGVldHMvZC9lLzJQQUNYLTF2UVFsVzI4cjlkZUFuZEw5SnEwdEJ5OTNvMzI3M1NXRlNSMVJyZ3RuMmpTMzdyamZKQUxGNWRsd0FUdHFtN1NQWlljdFY0aEp4YjM0YXpHL3B1Yj9naWQ9Njg0MjYwNjU2JnNpbmdsZT10cnVlJm91dHB1dD1jc3YiKQpgYGAKCmBgYHtyfQpoZWFkKGhhcHBpbmVzcykgIyBmb3IgZGF0YSBleHBsb3JhdGlvbgpgYGAKCmNsZWFuIHRoZSBuYW1lcywgcmVtb3ZpbmcgdGhlIHdoaXRlIHNwYWNlcywgZXRjLiBUaGUgbWFuaXB1bGF0aW9uIG9mIGNsZWFuIG5hbWVzIGlzIGVhc2llcgoKYGBge3J9CmhhcHBpbmVzcyA8LSBoYXBwaW5lc3MgJT4lIAogIGphbml0b3I6OmNsZWFuX25hbWVzKCkKYGBgCgoKY2hlY2sgdGhlIHZhcmlhYmxlcwpgYGB7cn0KZ2xpbXBzZShoYXBwaW5lc3MpCmBgYAojIGNoZWNrIHRoZSBjb21wbGV0ZW5lc3Mgb2YgdGhlIGRhdGFzZXQKQ2hlY2sgdGhlIGNvbXBsZXRlbmVzcyBvZiB0aGUgZGF0YXNldC4gVGhlIGdyZXkgc3BvdHMgYXJlIE5BcyB2YWx1ZXMKCmBgYHtyfQp2aXNkYXQ6OnZpc19kYXQoaGFwcGluZXNzKQpgYGAKCgojIERhdGEgZXhwbG9yYXRpb24KCiMjIEJhbHRpY3MgY291bnRyaWVzCgpgYGB7cn0KaGFwcGluZXNzICU+JSAKICBmaWx0ZXIoY291bnRyeV9uYW1lICVpbiUgYygiTGF0dmlhIiwgIkVzdG9uaWEiLCAiTGl0aHVhbmlhIikpICU+JSAgIyBmaWx0ZXIgc29tZSBjb3VudHJpZXMKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCAKICAgICAgICAgICAgIHkgPSBsaWZlX2xhZGRlciwgCiAgICAgICAgICAgICBjb2xvciA9IGNvdW50cnlfbmFtZSkpICsgCiAgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiSGFwcGluZXNzIGluIEJhbHRpYyBieSB5ZWFyIiwgCiAgICAgICB5ID0gIkhhcHBpbmVzcyAoMD0gd29yc3QsIDEwID0gYmVzdCkiLCAKICAgICAgIHggPSAiWWVhciIsIAogICAgICAgY29sb3IgPSAiQ291bnRyeSIpIApgYGAKCgojIyBHcm91cCBhbGwgdGhlIHZhcmlhYmxlcyB0byBtYWtlIG1hbnkgcGxvdHMgYXQgb25jZQoKVGhlcmUgYXJlIHNvbWUgYWJzb2x1dGUgdmFsdWUgdmFyaWFibGVzIGFuZCBzb21lIHJlbGF0ZWQgdG8gYSBzdXJ2ZXkKCi0gICBsb2dfZ2RwX3Blcl9jYXBpdGEKCi0gICBoZWFsdGh5X2xpZmVfZXhwZWN0YW5jeV9hdF9iaXJ0aAoKLSAgIGxpZmVfbGFkZGVyOiBIYXBwaW5lc3Mgc2NvcmUgb3Igc3ViamVjdGl2ZSB3ZWxsLWJlaW5nLiAwIHdvcnN0LCAxMCBiZXN0CgpUaGUgb25lcyBmcm9tIHRoZSBzdXJ2ZXkgY2FuIGJlIGNvbGxhcHNlZCBpbnRvIG9uZSBjb2x1bW4KCi0gICBzb2NpYWxfc3VwcG9ydAoKLSAgIGZyZWVkb21fdG9fbWFrZV9saWZlX2Nob2ljZXMKCi0gICBwZXJjZXB0aW9uc19vZl9jb3JydXB0aW9uCgotICAgcG9zaXRpdmVfYWZmZWN0CgotICAgbmVnYXRpdmVfYWZmZWN0CgoKYGBge3J9CmhhcHBpbmVzcyAlPiUgCiAgZmlsdGVyKGNvdW50cnlfbmFtZSAlaW4lIGMoIkxhdHZpYSIsICJFc3RvbmlhIiwgIkxpdGh1YW5pYSIpKSAlPiUgICMgZmlsdGVyIHNvbWUgY291bnRyaWVzCiAgIyByZWxvY2F0ZSBvbmUgY29sdW1uIHRvIG1ha2UgaXQgZWFzaWVyIHRoZSBwaXZvdGluZyBsYXRlcgogIHJlbG9jYXRlKHNvY2lhbF9zdXBwb3J0LCAuYWZ0ZXIgPSBoZWFsdGh5X2xpZmVfZXhwZWN0YW5jeV9hdF9iaXJ0aCkgJT4lIAogICMgbm93IHJlc2hhcGUgdGhlIGRhdGFzZXQKICBwaXZvdF9sb25nZXIoc29jaWFsX3N1cHBvcnQ6bmVnYXRpdmVfYWZmZWN0LCAKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAibmFtZV92YXJpYWJsZSIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAibmFtZV92YWx1ZSIpICU+JSAKIyBjaGFuZ2UgdGhlIG5hbWUgb2YgdGhlIGxldmVscyBvZiBuYW1lX3ZhcmlhYmxlCiAgbXV0YXRlKG5hbWVfdmFyaWFibGUgPSByZWNvZGUobmFtZV92YXJpYWJsZSwgIyBjaGFuZ2UgdGhlIHZhcmlhYmxlLCByZWNvZGluZyB0aGUgbGV2ZWxzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJlZWRvbV90b19tYWtlX2xpZmVfY2hvaWNlcyA9ICJGcmVlZG9tIiwgICMgb2xkIG5hbWUgPSBuZXcgbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVyb3NpdHkgPSAiR2VuZXJvc2l0eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5lZ2F0aXZlX2FmZmVjdCA9ICJOZWdhdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcmNlcHRpb25zX29mX2NvcnJ1cHRpb24gPSAiQ29ycnVwdGlvbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aXZlX2FmZmVjdCA9ICJQb3NpdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvY2lhbF9zdXBwb3J0ID0gIlN1cHBvcnQiKSkgJT4lIAogICMgbWFrZSB0aGUgcGxvdAogIGdncGxvdChhZXMoeCA9IHllYXIsIAogICAgICAgICAgICAgeSA9IG5hbWVfdmFsdWUsIAogICAgICAgICAgICAgY29sb3IgPSBjb3VudHJ5X25hbWUpKSArIAogIGdlb21fbGluZSgpICsKICBmYWNldF9ncmlkKC4gfiBuYW1lX3ZhcmlhYmxlICkgKyAKICBsYWJzKHRpdGxlID0gIlN1cnZleSByZXN1bHRzIGluIHRoZSBCYWx0aWMgY291bnRyaWVzIiwgCiAgICAgICB5ID0gIlN1cnZleSByZXN1bHRzIiwgCiAgICAgICBjb2xvciA9ICJDb3VudHJ5IiwgCiAgICAgICB4ID0gIlllYXIiKQpgYGAKCgoKCgojIEpvaW4gd2l0aCBhbm90aGVyIGRhdGFzZXQKCkl0IHdvdWxkIGJlIGludGVyZXN0aW5nIHRvIGdyb3VwIGJ5IGNvbnRpbmVudC4gCkkgY291bGQgYWRkIGJ5IGhhbmQgdGhlIGNvbnRpbmVudCBmb3IgZWFjaCBjb3VudHJ5LCBidXQgaXQgaXMgbXVjaCBzaW1wbGVyIGlmIEkgdGFrZSBhbm90aGVyIGRhdGFiYXNlIHdoZXJlIGVhY2ggY291bnRyeSBoYXMgdGhlIGNvbnRpbmVudCBpbmZvcm1hdGlvbi4gCgpUYWtlIHRoaXMgYXMgYW4gZXhhbXBsZSBpbiBjYXNlIHlvdSB3YW50IHRvIGNyb3NzIHNvbWUgaGFwcGluZXNzIHZhcmlhYmxlIHdpdGggYW5vdGhlciBvbmUsIGZvciBleGFtcGxlLCBmcm9tIHRoZSB3b3JsZCBiYW5rLiBUaGUga2V5IGlzIHRoYXQgYm90aCBkYXRhYmFzZXMgbXVzdCBoYXZlIGEgY29sdW1uIHRvIGZpdC4gWW91IGNhbiBhbHNvIG1hdGNoIGJ5IHR3byBjb2x1bW5zLCBmb3IgZXhhbXBsZSwgY291bnRyeSBhbmQgeWVhci4KCgpHb29nbGluZywgSSBmb3VuZCB0aGlzIGRhdGFzZXQgd2l0aCB0aGUgcmVxdWlyZWQgaW5mb3JtYXRpb24gb2YgdGhlIGNvdW50cmllcyBhbmQgY29udGluZW50cyBodHRwczovL2dpdGh1Yi5jb20vbHVrZXMvSVNPLTMxNjYtQ291bnRyaWVzLXdpdGgtUmVnaW9uYWwtQ29kZXMvYmxvYi9tYXN0ZXIvYWxsL2FsbC5jc3YKCmBgYHtyfQpjb3VudHJpZXMgPC0gcmVhZF9jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9sdWtlcy9JU08tMzE2Ni1Db3VudHJpZXMtd2l0aC1SZWdpb25hbC1Db2Rlcy9tYXN0ZXIvYWxsL2FsbC5jc3YiKQpgYGAKCmBgYHtyfQpoZWFkKGNvdW50cmllcykKYGBgCgoKRm9yIGhvdyB0byBqb2luIGRpZmZlcmVudCBkYXRhc2V0cywgc2VlIGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9WWctcE5xekR1TjQgYW5kIHRoaXMgaHR0cHM6Ly9jcmFpZy5yYmluZC5pby9wb3N0LzIwMjAtMDMtMjktYXNnci0yLTItam9pbmluZy1kYXRhLyAKYGBge3J9CiMgb3ZlcndyaXRlIHRoZSBvbGQgZGF0YXNldApoYXBwaW5lc3MgPC0gCiAgIyB3aXRoIGEgbmV3IG9uZSwgd2hlcmUgd2Ugd2lsbCBhZGQgdGhlIG5hbWUgZGF0YXNldCwgbWF0Y2hpbmcgYnkgdGhlIGNvbHVtbnMgImNvdW50cnlfbmFtZSIgZnJvbSB0aGUgaGFwcGluZXNzIGRhdGEgc2V0IGFuZCAibmFtZSIgZnJvbSB0aGUgY291bnRyaWVzIGRhdGEgc2V0CiAgbGVmdF9qb2luKGhhcHBpbmVzcywgY291bnRyaWVzLCBieSA9IGMoImNvdW50cnlfbmFtZSIgPSAibmFtZSIpKSAlPiUgCiAgc2VsZWN0KGNvdW50cnlfbmFtZTpuZWdhdGl2ZV9hZmZlY3QsICJhbHBoYS0zIiwgInJlZ2lvbiIsICJzdWItcmVnaW9uIikKYGBgCgpOb3cgSSBoYXZlIHRoZSBoYXBwaW5lc3MgZGF0YXNldCB3aXRoIHRoZSBpbmZvcm1hdGlvbiBvZiB0aGUgY29udGluZW50cyAocmVnaW9uKQoKIyBzdW1tYXJpemUgdGhlIGxpZmVfbGFkZGVyIGFjY3Jvc3MgY29udGluZW50cwoKYGBge3J9CmhhcHBpbmVzcyAlPiUgCiAgZmlsdGVyKHJlZ2lvbiAhPSAiTkEiKSAlPiUgIyByZW1vdmUgdGhlIGFudGFydGljYSwgZXRjCiAgIyBjYWxjdWxhdGUgdGhlIG1lYW4gaGFwcGluZXMgYnkgY29udGluZW50IGFuZCB5ZWFyCiAgZ3JvdXBfYnkocmVnaW9uLCB5ZWFyKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5faGFwcGluZXNzID0gbWVhbihsaWZlX2xhZGRlcikpICU+JSAKICAjIG1ha2UgdGhlIHBsb3QKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCAKICAgICAgICAgICAgIHkgPSBtZWFuX2hhcHBpbmVzcywgCiAgICAgICAgICAgICBjb2xvciA9IHJlZ2lvbikpICsgCiAgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSAiSGFwcGluZXNzIGJ5IGNvbnRpbmVudCBhbmQgeWVhciIsIAogICAgICAgeSA9ICJIYXBwaW5lc3MgKDA9IHdvcnN0LCAxMCA9IGJlc3QpIiwgCiAgICAgICB4ID0gIlllYXIiLCAKICAgICAgIGNvbG9yID0gIkNvbnRpbmVudCIpIApgYGAKIyMgc3VtbWFyeSBhbGwgY29udGluZW50cyBhdCBvbmNlCkFuZCBJIGNhbiBjaGVjayBhbGwgdGhlIHZhcmlhYmxlIHNieSBjb250aW5lbnRzIGF0IG9uY2UKCmBgYHtyfQpoYXBwaW5lc3MgJT4lIAogICMgZmlyc3QgcmVsb2NhdGUgb25lIGNvbHVtbiB0byBtYWtlIGl0IGVhc2llcgogIHJlbG9jYXRlKHNvY2lhbF9zdXBwb3J0LCAuYWZ0ZXIgPSBoZWFsdGh5X2xpZmVfZXhwZWN0YW5jeV9hdF9iaXJ0aCkgJT4lIAogICMgZmlsdGVyIHRvIGV4Y2x1ZGUgdGhlIE5BIGNvbnRpbmVudHMKICBmaWx0ZXIocmVnaW9uICE9ICJOQSIpICU+JSAKICAjIG5vdyByZXNoYXBlIHRoZSBkYXRhc2V0CiAgcGl2b3RfbG9uZ2VyKHNvY2lhbF9zdXBwb3J0Om5lZ2F0aXZlX2FmZmVjdCwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gImhhcHBpbmVzc192YXJpYWJsZSIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiaGFwcGluZXNzX3ZhbHVlIikgJT4lIAogIAogICMgY2FsY3VsYXRlIHRoZSBtZWFuIHZhbHVlIHBlciBjb250aW5lbnQKICBncm91cF9ieShoYXBwaW5lc3NfdmFyaWFibGUsIHJlZ2lvbiwgeWVhcikgJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbihoYXBwaW5lc3NfdmFsdWUsIG5hLnJtID0gVCkpICU+JSAKICAKICAjIGNoYW5nZSB0aGUgbmFtZSBvZiB0aGUgbGV2ZWxzIG9mIG5hbWVfdmFyaWFibGUKICBtdXRhdGUoaGFwcGluZXNzX3ZhcmlhYmxlID0gcmVjb2RlKGhhcHBpbmVzc192YXJpYWJsZSwgIyBjaGFuZ2UgdGhlIHZhcmlhYmxlLCByZWNvZGluZyB0aGUgbGV2ZWxzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJlZWRvbV90b19tYWtlX2xpZmVfY2hvaWNlcyA9ICJGcmVlZG9tIiwgICMgb2xkIG5hbWUgPSBuZXcgbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVyb3NpdHkgPSAiR2VuZXJvc2l0eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5lZ2F0aXZlX2FmZmVjdCA9ICJOZWdhdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcmNlcHRpb25zX29mX2NvcnJ1cHRpb24gPSAiQ29ycnVwdGlvbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aXZlX2FmZmVjdCA9ICJQb3NpdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvY2lhbF9zdXBwb3J0ID0gIlN1cHBvcnQiKSkgJT4lIAogIAogICMgYW5kIG5vdyBwbG90CiAgZ2dwbG90KGFlcyh4ID0geWVhciwgCiAgICAgICAgICAgICB5ID0gbWVhbiwgCiAgICAgICAgICAgICBjb2xvciA9IHJlZ2lvbiwgCiAgICAgICAgICAgICBncm91cCA9IHJlZ2lvbikpICsgCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X2dyaWQoLiB+IGhhcHBpbmVzc192YXJpYWJsZSkgKyAKICBsYWJzKHRpdGxlID0gIlNldmVyYWwgdmFyaWFibGVzIGluIG9uZSBwbG90IiwgCiAgICAgICB5ID0gIk1lYW4gdmFsdWUiLCAKICAgICAgIHggPSAiWWVhciIsIAogICAgICAgY29sb3IgPSAiQ29udGluZW50IikKYGBgCgoKIyMgQWxsIHRoZSB2YXJpYWJsZXMgZm9yIGp1c3QgZm9yIHRoZSBCYWx0aWMgY291bnRyaWVzCgpgYGB7cn0KaGFwcGluZXNzICU+JSAKICAjIGZpcnN0IHJlbG9jYXRlIG9uZSBjb2x1bW4gdG8gbWFrZSBpdCBlYXNpZXIgdG8gbWFuaXB1bGF0ZSB0aGUgdmFyaWFibGVzIGR1cmluZyB0aGUgcGl2b3RpbmcKICByZWxvY2F0ZShzb2NpYWxfc3VwcG9ydCwgLmFmdGVyID0gaGVhbHRoeV9saWZlX2V4cGVjdGFuY3lfYXRfYmlydGgpICU+JSAKICAjIGZpbHRlciB0byBleGNsdWRlIHRoZSBOQSBjb250aW5lbnRzCiAgZmlsdGVyKHJlZ2lvbiAhPSAiTkEiKSAlPiUgCiAgIyBub3cgZmlsdGVyIG9ubHkgZXVyb3BlYW4gY291bnRyaWVzCiAgZmlsdGVyKHJlZ2lvbiA9PSAiRXVyb3BlIikgJT4lICAjIGNvbW5lbnQgdGhpcyBsaW5lIHRvIGNoZWNrIGZvciBhbGwgdGhlIHdvcmxkCiAgIyBub3cgcmVzaGFwZSB0aGUgZGF0YXNldAogIHBpdm90X2xvbmdlcihzb2NpYWxfc3VwcG9ydDpuZWdhdGl2ZV9hZmZlY3QsIAogICAgICAgICAgICAgICBuYW1lc190byA9ICJoYXBwaW5lc3NfdmFyaWFibGUiLCAKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gImhhcHBpbmVzc192YWx1ZSIpICU+JSAKICAKICAjIGNhbGN1bGF0ZSB0aGUgbWVhbiB2YWx1ZSBwZXIgY29udGluZW50CiAgZ3JvdXBfYnkoaGFwcGluZXNzX3ZhcmlhYmxlLCBjb3VudHJ5X25hbWUsIHllYXIpICU+JSAKICBzdW1tYXJpc2UobWVhbiA9IG1lYW4oaGFwcGluZXNzX3ZhbHVlLCBuYS5ybSA9IFQpKSAlPiUgCiAgCiAgIyBjaGFuZ2UgdGhlIG5hbWUgb2YgdGhlIGxldmVscyBvZiBuYW1lX3ZhcmlhYmxlCiAgbXV0YXRlKGhhcHBpbmVzc192YXJpYWJsZSA9IHJlY29kZShoYXBwaW5lc3NfdmFyaWFibGUsICMgY2hhbmdlIHRoZSB2YXJpYWJsZSwgcmVjb2RpbmcgdGhlIGxldmVscwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyZWVkb21fdG9fbWFrZV9saWZlX2Nob2ljZXMgPSAiRnJlZWRvbSIsICAjIG9sZCBuYW1lID0gbmV3IG5hbWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW5lcm9zaXR5ID0gIkdlbmVyb3NpdHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZWdhdGl2ZV9hZmZlY3QgPSAiTmVnYXRpdmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZXJjZXB0aW9uc19vZl9jb3JydXB0aW9uID0gIkNvcnJ1cHRpb24iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZV9hZmZlY3QgPSAiUG9zaXRpdmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb2NpYWxfc3VwcG9ydCA9ICJTdXBwb3J0IikpICU+JSAKICAKICAjIGFuZCBub3cgcGxvdAogIGdncGxvdChhZXMoeCA9IHllYXIsIAogICAgICAgICAgICAgeSA9IG1lYW4sIAogICAgICAgICAgICAgY29sb3IgPSAoY291bnRyeV9uYW1lID09ICJMYXR2aWEiKSwgCiAgICAgICAgICAgICBncm91cCA9IGNvdW50cnlfbmFtZSkpICsgCiAgZ2VvbV9saW5lKGFscGhhID0gLjUpICsKICAjIGNoYW5nZSB0aGUgbmFtZSBvZiBsZXZlbHMgaW4gdGhlIGxlZ2VuZAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiR3JleSIsICJyZWQiKSwgCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJPdGhlciIsICJMYXR2aWEiKSkgKwogICMgbm93IGdlbmVyYXRlIHNldmVyYWwgcGxvdHMsIGVhY2ggZm9yIG9uZSB2YXJpYWJsZQogIGZhY2V0X2dyaWQoLiB+IGhhcHBpbmVzc192YXJpYWJsZSkgKyAgIyB0aGlzIG1lYW5zIHJvd3MgYW5kIGNvbHVtbnMsIGluIHRoaXMgY2FzZSwgbm8gdmFyaWFibGUgfiBoYXBwaW5lc3MKICBsYWJzKHRpdGxlID0gIlNldmVyYWwgdmFyaWFibGVzIGluIG9uZSBwbG90IiwgCiAgICAgICB5ID0gIk1lYW4gdmFsdWUiLCAKICAgICAgIHggPSAiWWVhciIsIAogICAgICAgY29sb3IgPSAiQ291bnRyeSIpIApgYGAKIyBnZ2hpZ2h0bGlnaHQKCkNoZWNrIExhdHZpYSBmb3IgYWxsIHRoZSBjb3VudHJpZXMuICBJIHdpbGwgdXNlIHRoZSBnZ2hpZ2hsaWdodCBwYWNrYWdlCgpzZWUgaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dnaGlnaGxpZ2h0L3ZpZ25ldHRlcy9nZ2hpZ2hsaWdodC5odG1sCgpgYGB7cn0KcGFjbWFuOjpwX2xvYWQoZ2doaWdobGlnaHQpCmBgYAoKYGBge3J9CiMgY29weSBhbmQgcGFzdGUgYWxsIHRoZSBjb2RlCmhhcHBpbmVzcyAlPiUgCiAgIyBmaXJzdCByZWxvY2F0ZSBvbmUgY29sdW1uIHRvIG1ha2UgaXQgZWFzaWVyCiAgcmVsb2NhdGUoc29jaWFsX3N1cHBvcnQsIC5hZnRlciA9IGhlYWx0aHlfbGlmZV9leHBlY3RhbmN5X2F0X2JpcnRoKSAlPiUgCiAgIyBmaWx0ZXIgdG8gZXhjbHVkZSB0aGUgTkEgY29udGluZW50cwogIGZpbHRlcihyZWdpb24gIT0gIk5BIikgJT4lIAogICMgbm93IGZpbHRlciBvbmx5IGV1cm9wZWFuIGNvdW50cmllcwogICMgZmlsdGVyKHJlZ2lvbiA9PSAiRXVyb3BlIikgJT4lCiAgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgCiAgICAgICAgICAgICB5ID0gbGlmZV9sYWRkZXIsIAogICAgICAgICAgICAgY29sb3IgPSByZWdpb24sIAogICAgICAgICAgICAgZ3JvdXAgPSBjb3VudHJ5X25hbWUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdnaGlnaGxpZ2h0KGNvdW50cnlfbmFtZSA9PSAiTGF0dmlhIikgKwogIGxhYnModGl0bGUgPSAiTGlmZSBsYWRkZXIsIGFsbCB0aGUgd29ybGQiLCAKICAgICAgIHkgPSAiTGlmZSBsYWRkZXIiLCAKICAgICAgIHggPSAiWWVhciIpCmBgYAoKIyMgZm9yIHRoZSBiYWx0aWMgY291bnRyaWVzCgpgYGB7cn0KIyBjb3B5IGFuZCBwYXN0ZSBhbGwgdGhlIGNvZGUKaGFwcGluZXNzICU+JSAKICAjIGZpcnN0IHJlbG9jYXRlIG9uZSBjb2x1bW4gdG8gbWFrZSBpdCBlYXNpZXIKICByZWxvY2F0ZShzb2NpYWxfc3VwcG9ydCwgLmFmdGVyID0gaGVhbHRoeV9saWZlX2V4cGVjdGFuY3lfYXRfYmlydGgpICU+JSAKICAjIGZpbHRlciB0byBleGNsdWRlIHRoZSBOQSBjb250aW5lbnRzCiAgZmlsdGVyKHJlZ2lvbiAhPSAiTkEiKSAlPiUgCiAgIyBub3cgZmlsdGVyIG9ubHkgZXVyb3BlYW4gY291bnRyaWVzCiAgIyB1bmNvbW1lbnQgbmV4dCBsaW5lIHRvIGZpbHRlciBldXJvcGVhbiBjb3VudHJpZXMgb25seQogICMgZmlsdGVyKHJlZ2lvbiA9PSAiRXVyb3BlIikgJT4lCiAgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgCiAgICAgICAgICAgICB5ID0gbGlmZV9sYWRkZXIsIAogICAgICAgICAgICAgY29sb3IgPSBjb3VudHJ5X25hbWUsIAogICAgICAgICAgICAgZ3JvdXAgPSBjb3VudHJ5X25hbWUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdnaGlnaGxpZ2h0KGNvdW50cnlfbmFtZSAlaW4lIGMoIkxhdHZpYSIsICJFc3RvbmlhIiwgIkxpdGh1YW5pYSIpKSArCiAgbGFicyh0aXRsZSA9ICJMaWZlIGxhZGRlciwgYWxsIHRoZSB3b3JsZCIsIAogICAgICAgeSA9ICJMaWZlIGxhZGRlciIsIAogICAgICAgeCA9ICJZZWFyIikKYGBgCiMjIGNoZWNrIHRoZSBoYXBwaWVzdCAKCgpgYGB7cn0KIyBjb3B5IGFuZCBwYXN0ZSBhbGwgdGhlIGNvZGUKaGFwcGluZXNzICU+JSAKICAjIGZpcnN0IHJlbG9jYXRlIG9uZSBjb2x1bW4gdG8gbWFrZSBpdCBlYXNpZXIKICByZWxvY2F0ZShzb2NpYWxfc3VwcG9ydCwgLmFmdGVyID0gaGVhbHRoeV9saWZlX2V4cGVjdGFuY3lfYXRfYmlydGgpICU+JSAKICAjIGZpbHRlciB0byBleGNsdWRlIHRoZSBOQSBjb250aW5lbnRzCiAgZmlsdGVyKHJlZ2lvbiAhPSAiTkEiKSAlPiUgCiAgIyBub3cgZmlsdGVyIG9ubHkgZXVyb3BlYW4gY291bnRyaWVzCiAgIyB1bmNvbW1lbnQgbmV4dCBsaW5lIHRvIGZpbHRlciBldXJvcGVhbiBjb3VudHJpZXMgb25seQogICMgZmlsdGVyKHJlZ2lvbiA9PSAiRXVyb3BlIikgJT4lCiAgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgCiAgICAgICAgICAgICB5ID0gbGlmZV9sYWRkZXIsIAogICAgICAgICAgICAgY29sb3IgPSBjb3VudHJ5X25hbWUsIAogICAgICAgICAgICAgZ3JvdXAgPSBjb3VudHJ5X25hbWUpKSArCiAgZ2VvbV9saW5lKCkgKwogIGdnaGlnaGxpZ2h0KGxpZmVfbGFkZGVyID4gNy42KSArICMgc2VsZWN0IHNvbWUgYXJiaXRyYXR5IHRocmVzaG9sZAogIGxhYnModGl0bGUgPSAiTGlmZSBsYWRkZXIsIGFsbCB0aGUgd29ybGQiLCAKICAgICAgIHkgPSAiTGlmZSBsYWRkZXIiLCAKICAgICAgIHggPSAiWWVhciIpCmBgYAojIyBhbmQgdGhlIGxvd2VzdCBoYXBwaW5lc3Mgc2NvcmUKCmBgYHtyfQojIGNvcHkgYW5kIHBhc3RlIGFsbCB0aGUgY29kZQpoYXBwaW5lc3MgJT4lIAogICMgZmlyc3QgcmVsb2NhdGUgb25lIGNvbHVtbiB0byBtYWtlIGl0IGVhc2llcgogIHJlbG9jYXRlKHNvY2lhbF9zdXBwb3J0LCAuYWZ0ZXIgPSBoZWFsdGh5X2xpZmVfZXhwZWN0YW5jeV9hdF9iaXJ0aCkgJT4lIAogICMgZmlsdGVyIHRvIGV4Y2x1ZGUgdGhlIE5BIGNvbnRpbmVudHMKICBmaWx0ZXIocmVnaW9uICE9ICJOQSIpICU+JSAKICAjIG5vdyBmaWx0ZXIgb25seSBldXJvcGVhbiBjb3VudHJpZXMKICAjIHVuY29tbWVudCBuZXh0IGxpbmUgdG8gZmlsdGVyIGV1cm9wZWFuIGNvdW50cmllcyBvbmx5CiAgIyBmaWx0ZXIocmVnaW9uID09ICJFdXJvcGUiKSAlPiUKICAKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCAKICAgICAgICAgICAgIHkgPSBsaWZlX2xhZGRlciwgCiAgICAgICAgICAgICBjb2xvciA9IGNvdW50cnlfbmFtZSwgCiAgICAgICAgICAgICBncm91cCA9IGNvdW50cnlfbmFtZSkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2doaWdobGlnaHQobGlmZV9sYWRkZXIgPCAzKSArCiAgbGFicyh0aXRsZSA9ICJMaWZlIGxhZGRlciwgYWxsIHRoZSB3b3JsZCIsIAogICAgICAgeSA9ICJMaWZlIGxhZGRlciIsIAogICAgICAgeCA9ICJZZWFyIikKYGBgCiMjIHRvcCB0aHJlZSBmcm9tIEV1cm9wZQpgYGB7cn0KIyBjb3B5IGFuZCBwYXN0ZSBhbGwgdGhlIGNvZGUKaGFwcGluZXNzICU+JSAKICAjIGZpcnN0IHJlbG9jYXRlIG9uZSBjb2x1bW4gdG8gbWFrZSBpdCBlYXNpZXIKICByZWxvY2F0ZShzb2NpYWxfc3VwcG9ydCwgLmFmdGVyID0gaGVhbHRoeV9saWZlX2V4cGVjdGFuY3lfYXRfYmlydGgpICU+JSAKICAjIGZpbHRlciB0byBleGNsdWRlIHRoZSBOQSBjb250aW5lbnRzCiAgZmlsdGVyKHJlZ2lvbiA9PSAiRXVyb3BlIikgJT4lIAogICMgbm93IGZpbHRlciBvbmx5IGV1cm9wZWFuIGNvdW50cmllcwogICMgdW5jb21tZW50IG5leHQgbGluZSB0byBmaWx0ZXIgZXVyb3BlYW4gY291bnRyaWVzIG9ubHkKICAjIGZpbHRlcihyZWdpb24gPT0gIkV1cm9wZSIpICU+JQogIAogIGdncGxvdChhZXMoeCA9IHllYXIsIAogICAgICAgICAgICAgeSA9IGxpZmVfbGFkZGVyLCAKICAgICAgICAgICAgIGNvbG9yID0gY291bnRyeV9uYW1lLCAKICAgICAgICAgICAgIGdyb3VwID0gY291bnRyeV9uYW1lKSkgKwogIGdlb21fbGluZSgpICsKICBnZ2hpZ2hsaWdodChtYXgobGlmZV9sYWRkZXIpLCBtYXhfaGlnaGxpZ2h0ID0gM0wpICMgc2VsZWN0IHRoZSB0b3AgMwogIGxhYnModGl0bGUgPSAiTGlmZSBsYWRkZXIsIGFsbCB0aGUgd29ybGQiLCAKICAgICAgIHkgPSAiTGlmZSBsYWRkZXIiLCAKICAgICAgIHggPSAiWWVhciIpCmBgYAoKIyBubyBnZ2hpZ2hsaWdodCBuZWVkZWQKCk5vdyB3aXRoIGFsbCB2YXJpYWJsZXMgYW5kIG5vIGdnaGlnaGxpZ3RoIG5lZWRlZAoKCmBgYHtyfQpoYXBwaW5lc3MgJT4lIAogICMgZmlyc3QgcmVsb2NhdGUgb25lIGNvbHVtbiB0byBtYWtlIGl0IGVhc2llciB0byBtYW5pcHVsYXRlIHRoZSB2YXJpYWJsZXMgZHVyaW5nIHRoZSBwaXZvdGluZwogIHJlbG9jYXRlKHNvY2lhbF9zdXBwb3J0LCAuYWZ0ZXIgPSBoZWFsdGh5X2xpZmVfZXhwZWN0YW5jeV9hdF9iaXJ0aCkgJT4lIAogICMgZmlsdGVyIHRvIGV4Y2x1ZGUgdGhlIE5BIGNvbnRpbmVudHMKICBmaWx0ZXIocmVnaW9uICE9ICJOQSIpICU+JSAKICAjIG5vdyBmaWx0ZXIgb25seSBldXJvcGVhbiBjb3VudHJpZXMKICBmaWx0ZXIocmVnaW9uID09ICJFdXJvcGUiKSAlPiUgICMgY29tbmVudCB0aGlzIGxpbmUgdG8gY2hlY2sgZm9yIGFsbCB0aGUgd29ybGQKICAjIG5vdyByZXNoYXBlIHRoZSBkYXRhc2V0CiAgcGl2b3RfbG9uZ2VyKHNvY2lhbF9zdXBwb3J0Om5lZ2F0aXZlX2FmZmVjdCwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gImhhcHBpbmVzc192YXJpYWJsZSIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiaGFwcGluZXNzX3ZhbHVlIikgJT4lIAogIAogICMgY2FsY3VsYXRlIHRoZSBtZWFuIHZhbHVlIHBlciBjb250aW5lbnQKICBncm91cF9ieShoYXBwaW5lc3NfdmFyaWFibGUsIGNvdW50cnlfbmFtZSwgeWVhcikgJT4lIAogIHN1bW1hcmlzZShtZWFuID0gbWVhbihoYXBwaW5lc3NfdmFsdWUsIG5hLnJtID0gVCkpICU+JSAKICAKICAjIGNoYW5nZSB0aGUgbmFtZSBvZiB0aGUgbGV2ZWxzIG9mIG5hbWVfdmFyaWFibGUKICBtdXRhdGUoaGFwcGluZXNzX3ZhcmlhYmxlID0gcmVjb2RlKGhhcHBpbmVzc192YXJpYWJsZSwgIyBjaGFuZ2UgdGhlIHZhcmlhYmxlLCByZWNvZGluZyB0aGUgbGV2ZWxzCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnJlZWRvbV90b19tYWtlX2xpZmVfY2hvaWNlcyA9ICJGcmVlZG9tIiwgICMgb2xkIG5hbWUgPSBuZXcgbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVyb3NpdHkgPSAiR2VuZXJvc2l0eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5lZ2F0aXZlX2FmZmVjdCA9ICJOZWdhdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcmNlcHRpb25zX29mX2NvcnJ1cHRpb24gPSAiQ29ycnVwdGlvbiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aXZlX2FmZmVjdCA9ICJQb3NpdGl2ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvY2lhbF9zdXBwb3J0ID0gIlN1cHBvcnQiKSkgJT4lIAogIAogICMgYW5kIG5vdyBwbG90CiAgZ2dwbG90KGFlcyh4ID0geWVhciwgCiAgICAgICAgICAgICB5ID0gbWVhbiwgCiAgICAgICAgICAgICBjb2xvciA9IChjb3VudHJ5X25hbWUgPT0gIkxhdHZpYSIpLCAjIGdvb2QgdHJpY2shIDpECiAgICAgICAgICAgICBncm91cCA9IGNvdW50cnlfbmFtZSkpICsgCiAgZ2VvbV9saW5lKGFscGhhID0gLjUpICsKICAjIGNoYW5nZSB0aGUgbmFtZSBvZiBsZXZlbHMgaW4gdGhlIGxlZ2VuZAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiR3JleSIsICJyZWQiKSwgCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJPdGhlciIsICJMYXR2aWEiKSkgKwogICMgbm93IGdlbmVyYXRlIHNldmVyYWwgcGxvdHMsIGVhY2ggZm9yIG9uZSB2YXJpYWJsZQogIGZhY2V0X2dyaWQoLiB+IGhhcHBpbmVzc192YXJpYWJsZSkgKyAgIyB0aGlzIG1lYW5zIHJvd3MgYW5kIGNvbHVtbnMsIGluIHRoaXMgY2FzZSwgbm8gdmFyaWFibGUgfiBoYXBwaW5lc3MKICBsYWJzKHRpdGxlID0gIlNldmVyYWwgdmFyaWFibGVzIGluIG9uZSBwbG90IiwgCiAgICAgICB5ID0gIk1lYW4gdmFsdWUiLCAKICAgICAgIHggPSAiWWVhciIsIAogICAgICAgY29sb3IgPSAiQ291bnRyeSIpIApgYGAKCgo=