1 Introduction

In this note, we study how to construct, or recreate charts presented in World Inequality Report. We focus on the Executive Summary, however, we hope that you can study the report in more detail using the original data provided in the site.

1.1 WIR2022

There is an R package to make it easier to download the data.

2 Executive Summary

2.1 Setup

First, create a new project using R Studio and create a data folder in it by running the following code. It is better to set Lang = "en" as you can find a resolution easily by posting the error message.

Sys.setenv(LANG = "en")
dir.create("./data")
library(tidyverse)
library(readxl)
library(DT)
url_summary <- "https://wir2022.wid.world/www-site/uploads/2022/03/WIR2022TablesFigures-Summary.xlsx"
download.file(
  url = url_summary, 
  destfile = "./data/WIR2022TablesFigures-Summary.xlsx",
  mode = "wb") 

Note:

  • mode = "wb" is for binary files.
  • If you get an error, go to Methodology page and download Datasets 1. Open the file and save it in the data folder in your Project folder.

As Mac uses resource files, the following simple code works as well.

download.file(url = url_summary, 
destfile = "data/WIR2022TablesFigures-Summary.xlsx") 
summary_sheets <- excel_sheets("data/WIR2022TablesFigures-Summary.xlsx")
summary_sheets
 [1] "Index"     "F1"        "F2"        "F3"        "F4"       
 [6] "F5."       "F6"        "F7"        "F8"        "F9"       
[11] "F10"       "F11"       "F12"       "F13"       "F14"      
[16] "F15"       "T1"        "data-F1"   "data-F2"   "data-F3"  
[21] "data-F4"   "data-F5"   "data-F6"   "data-F7"   "data-F8"  
[26] "data-F9"   "data-F10"  "data-F11"  "data-F12"  "data-F13."
[31] "data-F14." "data-F15" 
  • You can check the sheet names if you open the Excel file. However, to import a sheet, it is convenient to have a list, as we can copy and paste the sheet name.
  • Note that some of the sheet names contain a period.
  • You can replace sheet = "Index" by sheet = 1. However, the sheet number stays the same if a sheet is deleted. So it is safer to use the sheet name.
df_index <- read_excel("data/WIR2022TablesFigures-Summary.xlsx", sheet = "Index")
df_index
  • The list of the titles of the tables and the figures.

2.2 Data and Charts

  • Data are in “data-F1” to “data-F15”.

2.2.1 F1: Global income and wealth inequality, 2021

df_f1 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F1")
New names:
  • Since the first column does not have a column name, R assigns ...1 to its name, and returns a message: New names:.
df_f1
df_f1 %>% select(cat = ...1, 2:4) %>%
  pivot_longer(2:4, names_to = "group", values_to = "value") %>%
  ggplot(aes(x = cat, y = value, fill = group)) +
  geom_col(position = "dodge") + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) + 
  geom_text(aes(x = cat, y = value, group = group, label = scales::label_percent(accuracy=1)(value)), vjust = -0.08,
            position = position_dodge(0.9)) + 
  labs(title = "Figure 1. Global income and wealth inequality, 2021",
       x = "", y = "Share of total income or wealth", fill = "")

Interpretation: The global bottom 50% captures 8.5% of total income measured at Purchasing Power Parity (PPP). The global bottom 50% owns 2% of wealth (at Purchasing Power Parity). The global top 10% owns 76% of total Household wealth and captures 52% of total income in 2021. Note that top wealth holders are not necessarily top income holders. Incomes are measured after the operation of pension and unemployment systems and before taxes and transfers.
Sources and series: wir2022.wid.world/methodology.

2.2.1.1 Explanation

2.2.1.1.1 Step 1.
  • The chart does not use Top 1% data.
  • There are two groups, Income and Wealth. We need to tidy the data using pivot_longer.
  • The basic format of pivot_longer is:
    • pivot_longer(cols, names_to = "group", values_to = "value"), and cols is the columns to pivot into a longer format. Hence, in this case, cols = 2:4 or cols = -1, i.e., except the first column.
df_f1 %>% select(cat = ...1, 2:4) %>%
  pivot_longer(2:4, names_to = "group", values_to = "value")
2.2.1.1.2 Step 2.
  • Now we use ggplot2 to draw a chart.
df_f1 %>% select(cat = ...1, 2:4) %>%
  pivot_longer(2:4, names_to = "level", values_to = "value") %>%
  ggplot(aes(x = cat, y = value, fill = level)) +
  geom_col()

2.2.1.1.3 Step 3.
  • In order to place columns side by side, we use the option position = dodge.
df_f1 %>% select(cat = ...1, 2:4) %>%
  pivot_longer(2:4, names_to = "group", values_to = "value") %>%
  ggplot(aes(x = cat, y = value, fill = group)) +
  geom_col(position = "dodge")

2.2.1.1.4 Step 4.
  • We use the percent scale on y-axis.
  • In this case, scale_y_continuous(labels = c("0%", "20%", "40%", "60%", "80%")) does the same.
df_f1 %>% select(cat = ...1, 2:4) %>%
  pivot_longer(2:4, names_to = "group", values_to = "value") %>%
  ggplot(aes(x = cat, y = value, fill = group)) +
  geom_col(position = "dodge") + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 1))

2.2.1.1.5 Step 5.
  • Add the title and the label of the y-axis, and erase the label of the x-axis and the legend.
df_f1 %>% select(cat = ...1, 2:4) %>%
  pivot_longer(2:4, names_to = "group", values_to = "value") %>%
  ggplot(aes(x = cat, y = value, fill = group)) +
  geom_col(position = "dodge") + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 1. Global income and wealth inequality, 2021",
       x = "", y = "Share of total income or wealth", fill = "")

2.2.1.1.6 Step 6.
  • Add the value in percent as the text to top of each column.
df_f1 %>% select(cat = ...1, 2:4) %>%
  pivot_longer(2:4, names_to = "group", values_to = "value") %>%
  ggplot(aes(x = cat, y = value, fill = group)) +
  geom_col(position = "dodge") + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  geom_text(aes(x = cat, y = value, group = group, label = scales::label_percent(accuracy=1)(value)), 
            position = position_dodge(0.9)) + 
  labs(title = "Figure 1. Global income and wealth inequality, 2021",
       x = "", y = "Share of total income or wealth", fill = "")

2.2.1.1.7 Step 7.
  • If we want to place the labels at the top of the columns, use vjust.
df_f1 %>% select(cat = ...1, 2:4) %>%
  pivot_longer(2:4, names_to = "group", values_to = "value") %>%
  ggplot(aes(x = cat, y = value, fill = group)) +
  geom_col(position = "dodge") + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  geom_text(aes(x = cat, y = value, group = group, label = scales::label_percent(accuracy=1)(value)), vjust = 0,
            position = position_dodge(width = 0.9)) + 
  labs(title = "Figure 1. Global income and wealth inequality, 2021",
       x = "", y = "Share of total income or wealth", fill = "")

2.2.2 F2: The poorest half lags behind: Bottom 50%, middle 40% and top 10% income shares across the world in 2021

df_f2 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F2")
df_f2
df_f2 %>% pivot_longer(3:5, names_to = "level", values_to = "value") %>%
  ggplot(aes(x = iso, y = value, fill = level)) +
  geom_col(position = "dodge") + 
  scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 8)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 2. The poorest half lags behind Bottom 50%, middle 40% \nand top 10% income shares across the world in 2021",
       x = "", y = "Share of national income (%)", fill = "")

Interpretation: In Latin America, the top 10% captures 55% of national income, compared to 36% in Europe. Income is measured after pension and unemployment contributions and benefits paid and received by individuals but before income taxes and other transfers.
Sources and series: www.wir2022.wid.world/methodology.

2.2.2.1 Explanation

2.2.2.1.1 Step 1.
  • Similar to F1.
df_f2 %>% pivot_longer(3:5, names_to = "level", values_to = "value")
2.2.2.1.2 Step 2.

*Since the title is very long, insert \n for a line break. If \n and, then it creates a space before and.

df_f2 %>% pivot_longer(3:5, names_to = "level", values_to = "value") %>%
  ggplot(aes(x = iso, y = value, fill = level)) +
  geom_col(position = "dodge") + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 2. The poorest half lags behind Bottom 50%, middle 40% \nand top 10% income shares across the world in 2021",
       x = "", y = "Share of national income (%)", fill = "")

2.2.2.1.3 Step 3.
  • The labels of the x-axis are overlapping. One way is to add angle. See below.
  • Another way is to use scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 8)) to wrap. Since label varies we use a function with a variable x. See above.
df_f2 %>% pivot_longer(3:5, names_to = "level", values_to = "value") %>%
  ggplot(aes(x = iso, y = value, fill = level)) +
  geom_col(position = "dodge") + 
  theme(axis.text.x = element_text(angle = 30, vjust = 1, hjust=1)) + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 2. The poorest half lags behind Bottom 50%, middle 40% \nand top 10% income shares across the world in 2021",
       x = "", y = "Share of national income (%)", fill = "")

df_f2 %>% pivot_longer(3:5, names_to = "level", values_to = "value") %>%
  ggplot(aes(x = iso, y = value, fill = level)) +
  geom_col(position = "dodge") + 
  scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 8)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 2. The poorest half lags behind Bottom 50%, middle 40% \nand top 10% income shares across the world in 2021",
       x = "", y = "Share of national income (%)", fill = "")

2.2.3 F3: Top 10/Bottom 50 income gaps across the world, 2021

df_f3 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F3")
df_f3
map0<-map_data("world")
map0$region[map0$region=="Democratic Republic of the Congo"]<-"DR Congo"
map0$region[map0$region=="Republic of Congo"]<-"Congo"
map0$region[map0$region=="Ivory Coast"]<-"Cote dIvoire"
map0$region[map0$region=="Vietnam"]<-"Viet Nam"
map0$region[map0$region=="Russia"]<-"Russian Federation"
map0$region[map0$region=="South Korea"]<-"Korea"
map0$region[map0$region=="UK"]<-"United Kingdom"
map0$region[map0$region=="Brunei"]<-"Brunei Darussalam"
map0$region[map0$region=="Laos"]<-"Lao PDR"
map0$region[map0$region=="Cote dIvoire"]<-"Cote d'Ivoire"
map0$region[map0$region=="Cape Verde"]<- "Cabo Verde"
map0$region[map0$region=="Syria"]<- "Syrian Arab Republic"
map0$region[map0$region=="Trinidad"]<- "Trinidad and Tobago"
map0$region[map0$region=="Tobago"]<- "Trinidad and Tobago"

df_f3 %>% 
  mutate(`Top 10 Bottom 50 Ratio` = cut(T10B50,breaks = c(5, 12, 13, 16, 19,140), include.lowest = FALSE)) %>%
  ggplot(aes(map_id = Country)) + geom_map(aes(fill = `Top 10 Bottom 50 Ratio`), map = map0) + expand_limits(x = world_map$long, y = world_map$lat) +
  labs(title = "Figure 3. Top 10/Bottom 50 income gaps across the world, 2021",
       x = "", y = "", fill = "Top 10/Bottom 50 ratio") +
  theme(legend.position="bottom", 
        axis.text.x=element_blank(), axis.ticks.x=element_blank(),
        axis.text.y=element_blank(), axis.ticks.y=element_blank()) + 
  scale_fill_brewer(palette='YlOrRd')

Interpretation: In Brazil, the bottom 50% earns 29 times less than the top 10%. The value is 7 in France. Income is measured after pension and unemployment payments and benefits received by individuals but before other taxes they pay and transfers they receive. Source and series: wir2022.wid.world/methodology.

2.2.3.1 Explanation

2.2.3.1.1 Step 1.
df_f3 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F3")
df_f3
  • We use map_data("world") data attached to the tidyverse package. Let us look at the data first.
world_map <- map_data("world")
datatable(world_map)
Warning: It seems your data is too big for client-side DataTables. You may consider server-side processing: https://rstudio.github.io/DT/server.htmlWarning: It seems your data is too big for client-side DataTables. You may consider server-side processing: https://rstudio.github.io/DT/server.html
  • Let us try using the standard template of ggplot. We use Country for map_id and T10B50 for numerical data. Since world_map data contains long and lat of each region, we assign them as expand_limit.
df_f3 %>% 
  ggplot(aes(map_id = Country)) + 
  geom_map(aes(fill = `T10B50`), map = world_map) +
  expand_limits(x = world_map$long, y = world_map$lat)

2.2.3.1.2 Step 2.
  • We observe a couple of issues by comparing them with the image of the original.
  1. Russia, Congo, and some other areas are void.
  2. Scale and the legend should be improved.
  3. It may be better to bring the legend at the bottom to provide more width to the world map.

F3_world_map

  • The region name and the country name may be different in two datasets world_map and df_f3. Let us take care of the first issue.

  • To search names, we use DT::datatable, i.e., datatable in the DT package.

datatable(df_f3)
  • Search for ‘russia’ and ‘congo’, we find that

    • Russian Federation = Russia in world_map
    • DR Congo = Democratic Republic of the Congo in world_map
    • Congo = Republic of Congo in world_map
  • There are at least three ways to change the entries.

    • The following is a method to use Base R.

      • df_f3_rev$Country[df_f3_rev$Country == "Russian Federation"] <- "Russia": If the entry of the columnCountryin the data framedf_f3_revmatches with "Russian Federation", then replace it with "Russia.
    • The second is to use mutate and case_when of tidyverse.

    • The third is to use left_join after making a comparison table.

df_f3_rev <- df_f3
df_f3_rev$Country[df_f3_rev$Country == "Russian Federation"] <- "Russia"
df_f3_rev$Country[df_f3_rev$Country == "DR Congo"] <- "Democratic Republic of the Congo"
df_f3_rev$Country[df_f3_rev$Country == "Congo"] <- "Republic of Congo"
  • Now check the country names again using anti_join. By the code below, we can create a new table such that there is no region in world_map corresponding to Country in df_f3_rev.
df_f3_rev %>% anti_join(world_map, by = c("Country" = "region"))

We can proceed one by one. However, WIR provides the code of this part in R. So let us use it. It is in Computer Codes at the Methodology site. Download ‘Full Datasets’ and ‘Computer Codes’. Then in WIR2022 - Computer codes, find Chapter1_Maps.R.

map<-map_data("world")
map$region[map$region=="Democratic Republic of the Congo"]<-"DR Congo"
map$region[map$region=="Republic of Congo"]<-"Congo"
map$region[map$region=="Ivory Coast"]<-"Cote dIvoire"
map$region[map$region=="Vietnam"]<-"Viet Nam"
# map$region[map$region=="United Arab Emirates"]<-"UAE"

The last one for UAE seems to be wrong, so deleted.

Since the data used in the next line was not find, let me use map now.

index_region2<-read_dta("index_region.dta")
map<-left_join(map,index_region2,by=c("region"="name_region"))
map$ISO[map$region=="Greenland"]<-"GL"
map$ISO[map$region=="UAE"]<-"AE"
map$ISO[map$region=="Brunei"]<-"BR" # done
map$ISO[map$region=="Antigua"]<-"AG"
map$ISO[map$region=="Cape Verde"]<-"CV"
map$ISO[map$region=="Cote dIvoire"]<-"CI"
map$ISO[map$region=="UK"]<-"GB" # done
map$ISO[map$region=="Canary Islands"]<-"ES"
map$ISO[map$region=="French Guiana"]<-"FR"
map$ISO[map$region=="Saint Kitts"]<-"KN"
map$ISO[map$region=="South Korea"]<-"KR"
map$ISO[map$region=="Saint Martin"]<-"MF"
map$ISO[map$region=="Macedonia"]<-"MK"
map$ISO[map$region=="Russia"]<-"RU" # done
map$ISO[map$region=="Bonaire"]<-"BQ"
map$ISO[map$region=="Sint Eustatius"]<-"BQ"
map$ISO[map$region=="Saba"]<-"BQ"
map$ISO[map$region=="Laos"]<-"LA"
map$ISO[map$region=="Sint Maarten"]<-"SX"
map$ISO[map$region=="Syria"]<-"SY"
map$ISO[map$region=="Trinidad"]<-"TT"
map$ISO[map$region=="Tobago"]<-"TT"
map$ISO[map$region=="Virgin Islands"]<-"VI"
map$ISO[map$region=="Saint Vincent"]<-"VC"
map$ISO[map$region=="Grenadines"]<-"VC"
map$ISO[map$region=="French Southern and Antarctic Lands"]<-"FR"
map$ISO[map$region=="Western Sahara"]<-"WS"
map$region[map$region=="Russia"]<-"Russian Federation"
map$region[map$region=="South Korea"]<-"Korea"
map$region[map$region=="UK"]<-"United Kingdom"
map$region[map$region=="Brunei"]<-"Brunei Darussalam"
map$region[map$region=="Laos"]<-"Lao PDR"
map$region[map$region=="Cote dIvoire"]<-"Cote d'Ivoire"
map$region[map$region=="Cape Verde"]<- "Cabo Verde"
map$region[map$region=="Syria"]<- "Syrian Arab Republic"
map$region[map$region=="Trinidad"]<- "Trinidad and Tobago"
map$region[map$region=="Tobago"]<- "Trinidad and Tobago"
df_f3 %>% anti_join(map, by = c("Country" = "region"))
  • Is Zanzibar a part of Tanzania?
df_f3 %>% 
  ggplot(aes(map_id = Country)) + 
  geom_map(aes(fill = `T10B50`), map = map) +
  expand_limits(x = map$long, y = map$lat)

2.2.3.1.3 Step 3.
  • Next we add a new column Top 10 Bottom 50 Ratio by setting new breaks of T10B50.
  • Place the legend at the bottom using theme(legend.position="bottom").
df_f3_rev %>% 
  mutate(`Top 10 Bottom 50 Ratio` = cut(T10B50, breaks = c(5, 12, 13, 16, 19, 140), include.lowest = FALSE)) %>%
  ggplot(aes(map_id = Country)) + geom_map(aes(fill = `Top 10 Bottom 50 Ratio`), map = world_map) + expand_limits(x = world_map$long, y = world_map$lat) +
  theme(legend.position="bottom")

2.2.3.1.4 Step 4.

Finally add the title, remove x and y labels, and change the legend name.

df_f3_rev %>% 
  mutate(`Top 10 Bottom 50 Ratio` = cut(T10B50, breaks = c(5, 12, 13, 16, 19, 140), include.lowest = FALSE)) %>%
  ggplot(aes(map_id = Country)) + geom_map(aes(fill = `Top 10 Bottom 50 Ratio`), map = world_map) + expand_limits(x = world_map$long, y = world_map$lat) +
  labs(title = "Figure 3. Top 10/Bottom 50 income gaps across the world, 2021",
       x = "", y = "", fill = "Top 10/Bottom 50 ratio") +
  theme(legend.position="bottom")

2.2.3.1.5 Step 5.

Remove x-axis, y-axis and ticks. If you want to change color palette, see:

df_f3_rev %>% 
  mutate(`Top 10 Bottom 50 Ratio` = cut(T10B50, breaks = c(5, 12, 13, 16, 19, 140), include.lowest = FALSE)) %>%
  ggplot(aes(map_id = Country)) + geom_map(aes(fill = `Top 10 Bottom 50 Ratio`), map = world_map) + expand_limits(x = world_map$long, y = world_map$lat) +
  labs(title = "Figure 3. Top 10/Bottom 50 income gaps across the world, 2021",
       x = "", y = "", fill = "Top 10/Bottom 50 ratio") +
  theme(legend.position="bottom", 
        axis.text.x=element_blank(), axis.ticks.x=element_blank(),
        axis.text.y=element_blank(), axis.ticks.y=element_blank()) +
  scale_fill_brewer(palette='YlOrRd')

2.2.4 F4: The extreme concentration of capital: wealth inequality across the world, 2021

df_f4 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F4")
df_f4
df_f4 %>% pivot_longer(3:5, names_to = "level", values_to = "value") %>%
  ggplot(aes(x = iso, y = value, fill = level)) +
  geom_col(position = "dodge") + 
  scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 10)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 4. The extreme concentration of capital: \nwealth inequality across the world, 2021",
       x = "", y = "Share of national wealth (%)", fill = "")

Interpretation: The Top 10% in Latin America captures 77% of total household wealth, versus 22% for the Middle 40% and 1% for the Bottom 50%. In Europe, the Top 10% owns 58% of total wealth, versus 38% for the Middle 40% and 4% for the Bottom 50%.
Sources and series: wir2022.wid.world/methodology.

2.2.4.1 Explanation

  • Almost the same as F1 and F2.

  • Wrap long label: scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 10))

  • Per Cent: scale_y_continuous(labels = scales::percent_format(accuracy = 1))

2.2.5 F5: Global income inequality: T10/B50 ratio, 1820-2020

df_f5 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F5")
df_f5
df_f5 %>% select(year = y, ratio = t10b50) %>%
  ggplot(aes(x = year, y = ratio)) + 
  lims(y = c(10,70)) + 
  geom_smooth(formula = y~x, method = "loess", span = 0.25, se = FALSE) + 
  scale_x_continuous(breaks = round(seq(1820, 2020, by = 20),1)) + 
  labs(title = "Figure 5. Global income inequality:T10/B50 ratio, 1820-2020", 
       x = "", y = stringr::str_wrap("Ratio of top 10% average income to bottom 50% average income", width = 35)) +
  annotate("text", x = 1840, y = 32, label = stringr::str_wrap("1820: average income of the global top 10% is 18x higher than average income of the bottom 50%", width = 20), size = 3) + 
  annotate("text", x = 1910, y = 49, label = stringr::str_wrap("1910: average income of the global top 10% is 41x higher than average income of the bottom 50%", width = 20), size = 3) +
    annotate("text", x = 1980, y = 60, label = stringr::str_wrap("1980: average income of the global top 10% is 53x higher than average income of the bottom 50%", width = 20), size = 3) +
    annotate("text", x = 2010, y = 32, label = stringr::str_wrap("2020: average income of the global top 10% is 38x higher than average income of the bottom 50%", width = 20), size = 3)

Interpretation. Global inequality, as measured by the ratio T10/B50 between the average income of the top 10% and the average income of the bottom 50%, more than doubled between between 1820 and 1910, from less than 20 to about 40, and stabilized around 40 between 1910 and 2020. It is too early to say whether the decline in global inequality observed since 2008 will continue. Income is measured per capita after pension and unemployement insurance transfers and before income and wealth taxes.
Sources and series: wir2022.wid.world/lmethodology and Chancel and Piketty (2021)..

2.2.5.1 Explanation

2.2.5.1.1 Step 1.
  • The following is enough. Here we applied str_wrap to the label of the y-axis as it is very long.
df_f5 %>% select(year = y, ratio = t10b50) %>%
  ggplot(aes(x = year, y = ratio)) + 
  geom_line() +
  labs(title = "Figure 5. Global income inequality:T10/B50 ratio, 1820-2020", 
       x = "", y = stringr::str_wrap("Ratio of top 10% average income to bottom 50% average income", width = 35))

2.2.5.1.2 Step 2.

There are many way of smoothing.

Line Plot and LOESS

  • The default is “loess”, and se = TRUE which include the standard error.
  • Unless you clearly understand them, it is better to use formula = y~x, method = "loess", andse = FALSE`.
  • We try other methods below.
df_f5 %>% select(year = y, ratio = t10b50) %>%
  ggplot(aes(x = year, y = ratio)) +
  geom_line() +
  geom_smooth(formula = y~x, method = "loess", se = FALSE) + 
  labs(title = "Figure 5. Global income inequality:", 
       subtitle = "T10/B50 ratio, 1820-2020",
       x = "", y = "Ratio of top 10% average income to bottom 50% average income")

GAM Smoothing with 24 Points

df_f5 %>% select(year = y, ratio = t10b50) %>%
  ggplot(aes(x = year, y = ratio)) +
  stat_smooth(method = "gam", formula = y ~ s(x, k = 24), se = FALSE) + 
  scale_x_continuous(breaks = round(seq(min(df_f5$y), max(df_f5$y), by = 20),1)) + 
  labs(title = "Figure 5. Global income inequality:T10/B50 ratio, 1820-2020", 
       x = "", y = stringr::str_wrap("Ratio of top 10% average income to bottom 50% average income", width = 35))

Polynomial Approximation of Degree 6

df_f5 %>% select(year = y, ratio = t10b50) %>%
  ggplot(aes(x = year, y = ratio)) +
  geom_point() +
  geom_smooth(method = "lm", formula = y ~ poly(x, 6), se = FALSE) + 
  labs(title = "Figure 5. Global income inequality:", 
       subtitle = "T10/B50 ratio, 1820-2020",
       x = "", y = stringr::str_wrap("Ratio of top 10% average income to bottom 50% average income", width = 35))

2.2.5.1.3 Step 3.
  • In the main chart for F5, we applied geom_smooth(formula = y~x, method = "loess", span = 0.25, se = FALSE) as it is easy. You can adjust smoothness by changing the value for span.

  • For the y-axis, following the output provided, lims(y = c(10,70)) is added and annotation.

  • For a long text use: stringr::str_wrap("long text", width = size) and annotate with size = fontsize.

  • ggforce::geom_mark_rect will add annotation in a box.

df_f5 %>% select(year = y, ratio = t10b50) %>%
  ggplot(aes(x = year, y = ratio)) + 
  lims(y = c(10,70)) + 
  geom_smooth(formula = y~x, method = "loess", span = 0.25, se = FALSE) + 
  scale_x_continuous(breaks = round(seq(1820, 2020, by = 20),1)) + 
  labs(title = "Figure 5. Global income inequality:T10/B50 ratio, 1820-2020", 
       x = "", y = stringr::str_wrap("Ratio of top 10% average income to bottom 50% average income", width = 35)) +
  annotate("text", x = 1840, y = 32, label = stringr::str_wrap("1820: average income of the global top 10% is 18x higher than average income of the bottom 50%", width = 20), size = 3) + 
  annotate("text", x = 1910, y = 49, label = stringr::str_wrap("1910: average income of the global top 10% is 41x higher than average income of the bottom 50%", width = 20), size = 3) +
    annotate("text", x = 1980, y = 60, label = stringr::str_wrap("1980: average income of the global top 10% is 53x higher than average income of the bottom 50%", width = 20), size = 3) +
    annotate("text", x = 2010, y = 32, label = stringr::str_wrap("2020: average income of the global top 10% is 38x higher than average income of the bottom 50%", width = 20), size = 3)

2.2.6 F6: Global income inequality: Between vs. Within country inequality (Theil index), 1820-2020

df_f6 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F6")
New names:
df_f6
df_f6 %>% select(year = "...1", 2:3) %>%
  pivot_longer(cols = 2:3, names_to = "type", values_to = "value") %>%
  mutate(types = factor(type, levels = c("Within-country inequality", "Between-country inequality"))) %>%
  ggplot(aes(x = year, y = value, fill = types)) +
  geom_area() +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_x_continuous(breaks = round(seq(1820, 2020, by = 20),1)) + 
  scale_fill_manual(values=rev(scales::hue_pal()(2)), labels = function(x) str_wrap(x, width = 15)) +
  labs(title = "Figure 6. Global income inequality: \nBetween vs. within country inequality (Theil index), 1820-2020",
       x = "", y = "Share of global inequality (% of total Theil index)", fill = "") + 
  annotate("text", x = 1850, y = 0.28, label = stringr::str_wrap("1820: Between country inequality represents 11% of global inequality", width = 20), size = 3) + 
  annotate("text", x = 1980, y = 0.70, label = stringr::str_wrap("1980: Between country inequality represents 57% of global inequality", width = 20), size = 3) +
  annotate("text", x = 1990, y = 0.30, label = stringr::str_wrap("2020: Between country inequality represents 32% of global inequality", width = 20), size = 3)

  • Legend can be placed at the bottom: theme(legend.position="bottom")
df_f6 %>% select(year = "...1", 2:3) %>%
  pivot_longer(cols = 2:3, names_to = "type", values_to = "value") %>%
  mutate(types = factor(type, levels = c("Within-country inequality", "Between-country inequality"))) %>%
  ggplot(aes(x = year, y = value, fill = types)) +
  geom_area() +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_x_continuous(breaks = round(seq(1820, 2020, by = 20),1)) + 
  scale_fill_manual(values=rev(scales::hue_pal()(2))) +
  labs(title = "Figure 6. Global income inequality: \nBetween vs. within country inequality (Theil index), 1820-2020",
       x = "", y = "Share of global inequality (% of total Theil index)", fill = "") + 
  annotate("text", x = 1850, y = 0.28, label = stringr::str_wrap("1820: Between country inequality represents 11% of global inequality", width = 20), size = 3) + 
  annotate("text", x = 1980, y = 0.70, label = stringr::str_wrap("1980: Between country inequality represents 57% of global inequality", width = 20), size = 3) +
    annotate("text", x = 1990, y = 0.30, label = stringr::str_wrap("2020: Between country inequality represents 32% of global inequality", width = 20), size = 3) +
  theme(legend.position="bottom")

Interpretation. The importance of between-country inequality in overall global inequality, as measured by the Theil index, rose between 1820 and 1980 and strongly declined since then. In 2020, between-country inequality makes-up about a third of global inequality between individuals. The rest is due to inequality within countries. Income is measured per capita after pension and unemployement insurance transfers and before income and wealth taxes.
Sources and series: wir2022.wid.world/methodology and Chancel and Piketty (2021).

2.2.6.1 Explanation

2.2.6.1.1 Step 1.
  • We use geom_area after tidying the data with pilot_longer.
df_f6 %>% select(year = "...1", 2:3) %>%
  pivot_longer(cols = 2:3, names_to = "type", values_to = "value") %>%
  ggplot(aes(x = year, y = value, fill = type)) +
  geom_area() +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 6. Global income inequality: \nBetween vs. within country inequality (Theil index), 1820-2020",
       x = "", y = "Share of global inequality (% of total Theil index)")

2.2.6.1.2 Step 2.
  • Since the order of the two groups are different, the following linw is added.
scale_fill_manual(values=rev(scales::hue_pal()(2)), labels = function(x) str_wrap(x, width = 15))
  • The second option is to control the legend to wrap.

  • Annotation can be omitted if we use RMarkdown to explain the charts clearly.

  • Add a line break in the y-axis label.

df_f6 %>% select(year = "...1", 2:3) %>%
  pivot_longer(cols = 2:3, names_to = "type", values_to = "value") %>%
  mutate(types = factor(type, levels = c("Within-country inequality", "Between-country inequality"))) %>%
  ggplot(aes(x = year, y = value, fill = types)) +
  geom_area() +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_x_continuous(breaks = round(seq(1820, 2020, by = 20),1)) + 
  scale_fill_manual(values=rev(scales::hue_pal()(2)), labels = function(x) str_wrap(x, width = 15)) +
  labs(title = "Figure 6. Global income inequality: \nBetween vs. within country inequality (Theil index), 1820-2020",
       x = "", y = "Share of global inequality \n(% of total Theil index)", fill = "")

2.2.7 F7: Global income inequality, 1820-2020

df_f7 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F7")
df_f7
df_f7 %>% select(year = y, 2:4) %>%
  pivot_longer(cols = 2:4, names_to = "type", values_to = "value") %>%
  ggplot(aes(x = year, y = value, color = type)) +
  geom_smooth(formula = y~x, method = "loess", span = 0.25, se = FALSE) +
  scale_x_continuous(breaks = round(seq(1820, 2020, by = 20),1)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 7. Global income inequality, 1820-2020", 
       x = "", y = " Share of total world income (%)", color = "") +
  annotate("text", x = 1980, y = 0.20, label = stringr::str_wrap("The global bottom 50% income share remains historically low despite growth in the emerging world in the past decades.", width = 30), size = 3)

Interpretation. The share of global income going to top 10% highest incomes at the world level has fluctuated around 50-60% between 1820 and 2020 (50% in 1820, 60% in 1910, 56% in 1980, 61% in 2000, 55% in 2020), while the share going to the bottom 50% lowest incomes has generally been around or below 10% (14% in 1820, 7% in 1910, 5% in 1980, 6% in 2000, 7% in 2020). Global inequality has always been very large. It rose between 1820 and 1910 and shows little long-run trend between 1910 and 2020. Distribution of per capita incomes. Sources and series: see wir2022.wid.world/methodology and Chancel and Piketty (2021).

2.2.7.1 Explanation

2.2.7.1.1 Step 1.
  • Use pivot_longer to tidy the data.
df_f7 %>% select(year = y, 2:4) %>%
  pivot_longer(cols = 2:4, names_to = "type", values_to = "value") 
2.2.7.1.2 Step 2.

*Use geom_smooth with span, and change the scale of x-axis and y-axis.

df_f7 %>% select(year = y, 2:4) %>%
  pivot_longer(cols = 2:4, names_to = "type", values_to = "value") %>%
  ggplot(aes(x = year, y = value, color = type)) +
  geom_smooth(formula = y~x, method = "loess", span = 0.25, se = FALSE) +
  scale_x_continuous(breaks = round(seq(1820, 2020, by = 20),1)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 7. Global income inequality, 1820-2020", 
       x = "", y = " Share of total world income (%)", color = "")

  • Finally, add the annotation to obtain the figure above.

2.2.8 F8: The rise of private versus the decline of public wealth in rich countries, 1970-2020

df_f8 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F8")
df_f8
df_f8 %>% drop_na() %>%
  select(year, Germany_public = Germany, Germany_private = 'Germany (private)', 
         Spain_public = Spain, Spain_private = 'Spain (private)', 
         France_public = France, France_private = 'France (private)', 
         UK_public  = UK, UK_private = 'UK (private)', 
         Japan_public = Japan, Japan_private = 'Japan (private)', 
         Norway_public = Norway, Norway_private = 'Norway (private)',
         USA_public = USA, USA_private = 'USA (private)') %>%
  pivot_longer(!year, names_to = c("country",".value"), names_sep = "_") %>%
  pivot_longer(3:4, names_to = "type", values_to = "value") %>%
  ggplot() +
  stat_smooth(aes(x = year, y = value, color = country, linetype = type), 
              formula = y~x, method = "loess", 
              span = 0.25, se = FALSE, size=0.75) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 8. The rise of private versus the decline of \npublic wealth in rich countries, 1970-2020", 
       x = "", y = "wealth as % of national income", color = "", type = "")

Interpretation: Public wealth is the sum of all financial and non-financial assets, net of debts, held by governments. Public wealth dropped from 60% of national income in 1970 to -106% in 2020 in the UK.
Sources and series: wir2022.wid.world/methodology, Bauluz et al. (2021) and updates.

2.2.8.1 Explanation

2.2.8.1.1 Step 1.
  • There are two types of groups, countries and public vs private. So we change the column names first to identify that classification easily. We delete the last two columns “gwealAVGRICH” and “pwealAVGRICH” as they will not appear in the chart.
df_f8 %>% 
  select(year, Germany_public = Germany, Germany_private = 'Germany (private)', 
         Spain_public = Spain, Spain_private = 'Spain (private)', 
         France_public = France, France_private = 'France (private)', 
         UK_public  = UK, UK_private = 'UK (private)', 
         Japan_public = Japan, Japan_private = 'Japan (private)', 
         Norway_public = Norway, Norway_private = 'Norway (private)',
         USA_public = USA, USA_private = 'USA (private)') 
2.2.8.1.2 Step 2.
  • First separate the countries into a new column.
  • Here, we used an option names_sep = "_".
df_f8 %>% 
  select(year, Germany_public = Germany, Germany_private = 'Germany (private)', 
         Spain_public = Spain, Spain_private = 'Spain (private)', 
         France_public = France, France_private = 'France (private)', 
         UK_public  = UK, UK_private = 'UK (private)', 
         Japan_public = Japan, Japan_private = 'Japan (private)', 
         Norway_public = Norway, Norway_private = 'Norway (private)',
         USA_public = USA, USA_private = 'USA (private)') %>%
  pivot_longer(!year, names_to = c("country",".value"), names_sep = "_") 
2.2.8.1.3 Step 3.
  • Next apply pivot_longer again to form the second group.
df_f8 %>% 
  select(year, Germany_public = Germany, Germany_private = 'Germany (private)', 
         Spain_public = Spain, Spain_private = 'Spain (private)', 
         France_public = France, France_private = 'France (private)', 
         UK_public  = UK, UK_private = 'UK (private)', 
         Japan_public = Japan, Japan_private = 'Japan (private)', 
         Norway_public = Norway, Norway_private = 'Norway (private)',
         USA_public = USA, USA_private = 'USA (private)') %>%
  pivot_longer(!year, names_to = c("country",".value"), names_sep = "_") %>%
  pivot_longer(3:4, names_to = "type", values_to = "value")
2.2.8.1.4 Step 4.
  • Assign colors to countries and distinguish types by linetype.
df_f8 %>% 
  select(year, Germany_public = Germany, Germany_private = 'Germany (private)', 
         Spain_public = Spain, Spain_private = 'Spain (private)', 
         France_public = France, France_private = 'France (private)', 
         UK_public  = UK, UK_private = 'UK (private)', 
         Japan_public = Japan, Japan_private = 'Japan (private)', 
         Norway_public = Norway, Norway_private = 'Norway (private)',
         USA_public = USA, USA_private = 'USA (private)') %>%
  pivot_longer(!year, names_to = c("country",".value"), names_sep = "_") %>%
  pivot_longer(3:4, names_to = "type", values_to = "value") %>%
  ggplot() +
  geom_smooth(aes(x = year, y = value, color = country, linetype = type),
              formula = y~x, method = "loess", span = 0.25, se = FALSE)

2.2.8.1.5 Step 5.
  • Since there are a lot of NA’s, removed using drop_na()
  • Change the line width by size, change the y-axis to percents and add the .title.
df_f8 %>% drop_na() %>%
  select(year, Germany_public = Germany, Germany_private = 'Germany (private)', 
         Spain_public = Spain, Spain_private = 'Spain (private)', 
         France_public = France, France_private = 'France (private)', 
         UK_public  = UK, UK_private = 'UK (private)', 
         Japan_public = Japan, Japan_private = 'Japan (private)', 
         Norway_public = Norway, Norway_private = 'Norway (private)',
         USA_public = USA, USA_private = 'USA (private)') %>%
  pivot_longer(!year, names_to = c("country",".value"), names_sep = "_") %>%
  pivot_longer(3:4, names_to = "type", values_to = "value") %>%
  ggplot() +
  geom_smooth(aes(x = year, y = value, color = country, linetype = type),
              formula = y~x, method = "loess", 
              span = 0.25, se = FALSE, size=0.75) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 8. The rise of private versus the decline of \npublic wealth in rich countries, 1970-2020", 
       x = "", y = "wealth as % of national income", color = "", type = "")

2.2.8.1.6 Step 6.
  • Let us check if we use only color for each group representing columns. This is not the chart we wanted to obtain.
df_f8 %>% drop_na() %>% 
  pivot_longer(!year, names_to = "group", values_to = "value") %>%
  ggplot() +
  geom_smooth(aes(x = year, y = value, color = group), 
            formula = y~x, method = "loess", 
            span = 0.25, se = FALSE, size=0.75) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 8. The rise of private versus \nthe decline of public wealth in rich countries, \n1970-2020", 
       x = "", y = "wealth as % of national income", color = "")

2.2.9 F9: Average annual wealth growth rate, 1995-2021

df_f9 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F9")
df_f9
brks <- c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 99, 99.9, 99.99, 99.999)
df_f9 %>% 
  mutate(level = cut(p, breaks = c(brks,100), labels = as.character(brks), include.lowest = TRUE)) %>% 
  mutate(xlabel = as.numeric(level)+0.8) %>%
  ggplot(aes(x = xlabel, y = `Wealth growth 1995-2021`)) + geom_smooth(method = "loess", formula = y~x, se = FALSE, span = 0.5) + 
  scale_x_discrete(limits=as.character(brks)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 0.1)) +
  labs(title = "Figure 9. Average annual wealth growth rate, 1995-2021", 
       x = "←1% poorest Global wealth group              0.001% richest→", 
       y = "Per adult annual growth rate in wealth, \nnet of inflation (%)")

Interpretation: Growth rates among the poorest half of the population were between 3% and 4% per year, between 1995 and 2021. Since this group started from very low wealth levels, its absolute levels of growth remained very low. The poorest half of the world population only captured 2.3% of overall wealth growth since 1995. The top 1% benefited from high growth rates (3% to 9% per year). This group captured 38% of total wealth growth between 1995 and 2021. Net household wealth is equal to the sum of financial assets (e.g. equity or bonds) and non-financial assets (e.g. housing or land) owned by individuals, net of their debts.
Sources and series: wir2022.wid.world/methodology.

2.2.9.1 Explanation

2.2.9.1.1 Step 1.
  • Let’s look at the original chart

F9_world_map{width = 100%}

  • The scale of the x-axis is not evenly partitioned. It is (0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 99, 99.9, 99.99, 99.999).
  • Look at the column p of the data.
df_f9 %>% distinct(p) %>% pull()
  [1]  0.000  1.000  2.000  3.000  4.000  5.000  6.000  7.000  8.000
 [10]  9.000 10.000 11.000 12.000 13.000 14.000 15.000 16.000 17.000
 [19] 18.000 19.000 20.000 21.000 22.000 23.000 24.000 25.000 26.000
 [28] 27.000 28.000 29.000 30.000 31.000 32.000 33.000 34.000 35.000
 [37] 36.000 37.000 38.000 39.000 40.000 41.000 42.000 43.000 44.000
 [46] 45.000 46.000 47.000 48.000 49.000 50.000 51.000 52.000 53.000
 [55] 54.000 55.000 56.000 57.000 58.000 59.000 60.000 61.000 62.000
 [64] 63.000 64.000 65.000 66.000 67.000 68.000 69.000 70.000 71.000
 [73] 72.000 73.000 74.000 75.000 76.000 77.000 78.000 79.000 80.000
 [82] 81.000 82.000 83.000 84.000 85.000 86.000 87.000 88.000 89.000
 [91] 90.000 91.000 92.000 93.000 94.000 95.000 96.000 97.000 98.000
[100] 99.000 99.900 99.990 99.999
  • Use cut to break in levels.
brks <- c(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 99, 99.9, 99.99, 99.999)
df_f9 %>% mutate(level = cut(p, breaks = c(brks,100), labels = as.character(brks), include.lowest = TRUE))
2.2.9.1.2 Step 2.
  • Add xlabel in numeric.
df_f9 %>% mutate(level = cut(p, breaks = c(brks,100), labels = as.character(brks), include.lowest = TRUE)) %>% 
  mutate(xlabel = as.numeric(level))
2.2.9.1.3 Step 3.
  • Draw a curve using geom_smooth.
  • Added 0.5 to represent the mean value in each interval.
df_f9 %>% mutate(level = cut(p, breaks = c(brks,100), labels = as.character(brks), include.lowest = TRUE)) %>% 
  mutate(xlabel = as.numeric(level)+0.5) %>%
  ggplot(aes(x = xlabel, y = `Wealth growth 1995-2021`)) + geom_smooth(method = "loess", formula = y~x, se = FALSE, span = 0.5)

2.2.9.1.4 Step 4.
  • Use scale_x_discrete(limits=as.character(brks)) to change the label of the x-axis.
  • Use scale_y_continuous(labels = scales::percent_format(accuracy = 0.1)).
df_f9 %>% mutate(level = cut(p, breaks = c(brks,100), labels = as.character(brks), include.lowest = TRUE)) %>% 
  mutate(xlabel = as.numeric(level)+ 0.8) %>%
  ggplot(aes(x = xlabel, y = `Wealth growth 1995-2021`)) + geom_smooth(method = "loess", formula = y~x, se = FALSE, span = 0.5) + 
  scale_x_discrete(limits=as.character(brks)) + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 0.1))

2.2.10 F10: The share of wealth owned by the global 0.1% and billionaires, 2021

df_f10 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F10")
New names:
df_f10
df_f10 %>% 
  select(year, "Global Billionaire Wealth" = bn_hhweal, "Top 0.01%" = top0.1_hhweal) %>%
  pivot_longer(!year, names_to = "group",".value", values_to = "value") %>%
  ggplot() +
  geom_smooth(aes(x = year, y = value, color = group), 
              formula = y~x, method = "loess", 
              span = 0.25, se = FALSE) +
  scale_x_continuous(breaks = round(seq(1995, 2020, by = 5),1)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_color_manual(values=rev(scales::hue_pal()(2))) +
  labs(title = "Figure 10. Extreme wealth inequality: \nthe rise of global billionaires and top 0.01%, 1995-2021", 
       x = "", y = "Share of total household wealth (%)", color = "")

Interpretation: The share of wealth detained by the world’s billionaires rose from 1% of total household wealth in 1995 to nearly 3.5% today. The threshold of top 0.01%, composed of 520 000 adults, grew from €693,000 (PPP) in 1995 to €16,666,000 today. The net household wealth is equal to the sum of financial assets (e.g. equity or bonds) and non-financial assets (e.g. housing or land) owned by individuals, net of their debts.
Sources and series: wir2022.wid.world/methodology, Bauluz et al. (2021) and updates.

2.2.10.1 Explanation

2.2.10.1.1 Step 1.
  • Use descriptive column names and use pivot_longer to make it tidy.
df_f10 %>% 
  select(year, "Global Billionaire Wealth" = bn_hhweal, "Top 0.01%" = top0.1_hhweal) %>%
  pivot_longer(!year, names_to = "group",".value", values_to = "value")
2.2.10.1.2 Step 2.
  • Use geom_smooth with span = 0.25 and change the breaks of x-labels.
df_f10 %>% 
  select(year, "Global Billionaire Wealth" = bn_hhweal, "Top 0.01%" = top0.1_hhweal) %>%
  pivot_longer(!year, names_to = "group",".value", values_to = "value") %>%
  ggplot() +
  geom_smooth(aes(x = year, y = value, color = group), 
              formula = y~x, method = "loess", span = 0.25, se = FALSE) +
  scale_x_continuous(breaks = round(seq(1995, 2020, by = 5),1)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 10. Extreme wealth inequality: \nthe rise of global billionaires and top 0.01%, 1995-2021", 
       x = "", y = "Share of total household wealth (%)", color = "")

2.2.10.1.3 Step 3.
df_f10 %>% 
  select(year, "Global Billionaire Wealth" = bn_hhweal, "Top 0.01%" = top0.1_hhweal) %>%
  pivot_longer(!year, names_to = "group",".value", values_to = "value") %>%
  ggplot() +
  geom_smooth(aes(x = year, y = value, color = group), 
              formula = y~x, method = "loess", span = 0.25, se = FALSE) +
  scale_x_continuous(breaks = round(seq(1995, 2020, by = 5),1)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  scale_color_manual(values=rev(scales::hue_pal()(2))) +
  labs(title = "Figure 10. Extreme wealth inequality: \nthe rise of global billionaires and top 0.01%, 1995-2021", 
       x = "", y = "Share of total household wealth (%)", color = "")

2.2.11 F11: Top 1% vs bottom 50% wealth shares in Western Europe and the US, 1910-2020

df_f11 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F11")
df_f11
df_f11 %>%
  rename(!year, US_bot50 = USbot50, US_top1 = UStop1, EU_bot50 = EUbot50, EU_top1 = EUtop1) %>%
  pivot_longer(!year, names_to = c("group",".value"), names_sep = "_") %>%
  pivot_longer(3:4, names_to = "type", values_to = "value") %>%
  ggplot() +
  geom_smooth(aes(x = year, y = value, color = group, linetype = type), 
              formula = y~x, method = "loess", span = 0.5, se = FALSE) +
  scale_x_continuous(breaks = round(seq(1910, 2020, by = 10),1)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 11. Top 1% vs bottom 50% wealth shares \n in Western Europe and the US, 1910-2020", 
       x = "", y = "Share of total personal wealth (%)", color = "", linetype = "") +
  scale_linetype_manual(values = c("dotted","solid")) +
  annotate("text", x = 2000, y = 0.50, label = stringr::str_wrap("Wealth inequality has been rising at different speeds after a historical decline. The bottom 50% has always been extremely low.", width = 30), size = 3)

Interpretation: The graph presents decennal averages of top 1% personal wealth shares in Western Europe and the US. Between 1910 and 2020, the top 1% was 55% on average in Europe vs. 43% in the US. A century later, the US is almost back to its early 20th century level. Sources and series: wir2022.wid.world/methodology.

2.2.11.1 Explanation

2.2.11.1.1 Step 1.
  • There are two groups: US vs. EU and bot50 and top1. We use the same technique as in F8.
df_f11 %>% 
  rename(!year, US_bot50 = USbot50, US_top1 = UStop1, EU_bot50 = EUbot50, EU_top1 = EUtop1) %>%
  pivot_longer(!year, names_to = c("group",".value"), names_sep = "_")
2.2.11.1.2 Step 2.
  • Here, we try another way. Here we use two geom_smooth with different aes().
  • Can you see the difference of the chart above?
df_f11 %>% 
  rename(!year, US_bot50 = USbot50, US_top1 = UStop1, EU_bot50 = EUbot50, EU_top1 = EUtop1) %>%
  pivot_longer(!year, names_to = c("group",".value"), names_sep = "_") %>%
  ggplot() +
  geom_smooth(aes(x = year, y = top1, color = group), 
              formula = y~x, method = "loess", span = 0.5, se = FALSE) +
  geom_smooth(aes(x = year, y = bot50, color = group), 
              formula = y~x, method = "loess", span = 0.5, se = FALSE, linetype = 2) +
  scale_x_continuous(breaks = round(seq(1910, 2020, by = 10),1)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 11. Top 1% vs bottom 50% wealth shares \n in Western Europe and the US, 1910-2020", 
       x = "", y = "Share of total personal wealth (%)", color = "") +
  annotate("text", x = 2000, y = 0.50, label = stringr::str_wrap("Wealth inequality has been rising at different speeds after a historical decline. The bottom 50% has always been extremely low.", width = 30), size = 3)

2.2.11.1.3 Step 3.

Use pivot_longer the second time.

df_f11 %>% 
  rename(!year, US_bot50 = USbot50, US_top1 = UStop1, EU_bot50 = EUbot50, EU_top1 = EUtop1) %>%
  pivot_longer(!year, names_to = c("group",".value"), names_sep = "_") %>%
  pivot_longer(3:4, names_to = "type", values_to = "value") %>%
  ggplot() +
  geom_smooth(aes(x = year, y = value, color = group, linetype = type), 
              formula = y~x, method = "loess", span = 0.5, se = FALSE) +
  scale_x_continuous(breaks = round(seq(1910, 2020, by = 10),1)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 11. Top 1% vs bottom 50% wealth shares \n in Western Europe and the US, 1910-2020", 
       x = "", y = "Share of total personal wealth (%)", color = "", linetype = "") +
  annotate("text", x = 2000, y = 0.50, label = stringr::str_wrap("Wealth inequality has been rising at different speeds after a historical decline. The bottom 50% has always been extremely low.", width = 30), size = 3)

2.2.11.1.4 Step 4.

Change the order of linetypes manually.

df_f11 %>% 
  rename(!year, US_bot50 = USbot50, US_top1 = UStop1, EU_bot50 = EUbot50, EU_top1 = EUtop1) %>%
  pivot_longer(!year, names_to = c("group",".value"), names_sep = "_") %>%
  pivot_longer(3:4, names_to = "type", values_to = "value") %>%
  ggplot() +
  geom_smooth(aes(x = year, y = value, color = group, linetype = type), 
              formula = y~x, method = "loess",
              span = 0.5, se = FALSE) +
  scale_x_continuous(breaks = round(seq(1910, 2020, by = 10),1)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 11. Top 1% vs bottom 50% wealth shares \n in Western Europe and the US, 1910-2020", 
       x = "", y = "Share of total personal wealth (%)", color = "", linetype = "") +
  scale_linetype_manual(values = c("dotted","solid")) +
  annotate("text", x = 2000, y = 0.50, label = stringr::str_wrap("Wealth inequality has been rising at different speeds after a historical decline. The bottom 50% has always been extremely low.", width = 30), size = 3)

2.2.12 F12: Female share in global labor incomes, 1990-2020

df_f12 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F12")
New names:
df_f12
df_f12 %>% 
  select(year = "Data needs to be updated", value = ...2) %>%
  filter(!is.na(year)) %>%
  ggplot(aes(x = year, y = value)) +
  geom_col(width = 0.5, fill = scales::hue_pal()(2)[2]) +
  geom_hline(yintercept = 0.5, linetype = 2, colour = scales::hue_pal()(2)[1]) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 12. Female share in global labor incomes, 1990-2020", 
        x = "", y = "") +
  annotate("text", x = 1, y = 0.48, label = "Gender parity", size = 3) +
  annotate("text", x = 5.2, y = 0.47, label = stringr::str_wrap("Women make only 35% of global labor incomes, men make the remaining  65%.", width = 40), size = 3)

Interpretation: The share of female incomes in global labour incomes was 31% in 1990 and nears 35% in 2015-2020. Today, males make up 65% of total labor incomes. Sources and series: wir2022.wid.world/methodology and Neef and Robilliard (2021).

2.2.12.1 Explanation

2.2.12.1.1 Step 1.

Change the column names and delete the rows with NAs.

df_f12 %>% 
  select(year = "Data needs to be updated", value = ...2) %>%
  filter(!is.na(year))
2.2.12.1.2 Step 2.

Add geom_col and geom_hline with colors scales::hue_pal()(2)[2] and scales::hue_pal()(2)[1].

df_f12 %>% 
  select(year = "Data needs to be updated", value = ...2) %>%
  filter(!is.na(year)) %>%
  ggplot(aes(x = year, y = value)) +
  geom_col(width = 0.5, fill = scales::hue_pal()(2)[2]) +
  geom_hline(yintercept = 0.5, linetype = 2, colour = scales::hue_pal()(2)[1]) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 12. Female share in global labor incomes, 1990-2020", 
        x = "", y = "") +
  annotate("text", x = 1, y = 0.48, label = "Gender parity", size = 3) +
  annotate("text", x = 5.2, y = 0.47, label = stringr::str_wrap("Women make only 35% of global labor incomes, men make the remaining  65%.", width = 40), size = 3)

2.2.13 F13: Female labor income share across the world, 1990-2020

Note that the sheet name of F13 has period at the end. Note that summary_sheets[30] =data-F13. with a period.

df_f13 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F13.")
New names:
df_f13
df_f13 %>% pivot_longer(2:9, names_to = "region", values_to = "value") %>%
  ggplot(aes(x = region, y = value, fill = ...1)) +
  geom_col(position = "dodge") + 
  geom_hline(yintercept = 0.5, linetype = 2, colour = "red") +
  scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 12)) +
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 13. Female labor income share across the world, 1990-2020", 
        x = "", y = "", fill = "") +
  annotate("text", x = 1.2, y = 0.48, label = "Gender parity", size = 3)

Interpretation: The female labour income share rose from 34% to 38% in North America between 1990 and 2020. Sources and series: wir2022.wid.world/methodology and Neef and Robilliard (2021).

2.2.13.1 Explanation

Not so difficult.

2.2.14 F14: Global carbon inequality, 2019. Group contribution to world emissions (%)

Note that the sheet name of F14 has period at the end. Note that summary_sheets[31] =data-F14. with a period.

df_f14 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F14.")
df_f14
  • \n for line break in the title.
df_f14 %>% 
  ggplot(aes(x = Group, y = Share)) +
  geom_col(width = 0.5, fill = scales::hue_pal()(1)[1]) + 
  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
  labs(title = "Figure 14. Global carbon inequality, \n2019 Group contribution to world emissions (%)", 
       x = "", y = "Share of world emissions (%)")

Interpretation: Personal carbon footprints include emissions from domestic consumption, public and private investments as well as imports and exports of carbon embedded in goods and services traded with the rest of the world. Modeled estimates based on the systematic combination of tax data, household surveys and input-output tables. Emissions split equally within households. Sources and series: wir2022.wid.world/methodology and Chancel (2021).

2.2.14.1 Explanation

Not so difficult. You can assign color name. See http://www.cookbook-r.com/Graphs/Colors_(ggplot2)/.

2.2.15 F15: Per capita emissions acriss the world, 2019

df_f15 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", sheet = "data-F15")
df_f15
df_f15 %>% mutate(region = rep(regionWID[!is.na(regionWID)], each = 3)) %>%
  select(region, group, tcap) %>%
  ggplot(aes(x = region, y = tcap, fill = group)) +
  geom_col(position = "dodge") + 
  scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 10)) +
  labs(title = "Figure 15 Per capita emissions across the world, 2019", 
       x = "", y = "tonnes of CO2e per person per year", fill = "")

Interpretation: Personal carbon footprints include emissions from domestic consumption, public and private investments as well as imports and exports of carbon embedded in goods and services traded with the rest of the world. Modeled estimates based on the systematic combination of tax data, household surveys and input-output tables. Emissions split equally within households. Sources and series: wir2022.wid.world/methodology and Chancel (2021).

2.2.15.1 Explanation

2.2.15.1.1 Step 1.

It is in Excel stype and there are missing values in the first column. In order to add a new column, let us check the following.

region_test <- rep(df_f15$regionWID[!is.na(df_f15$regionWID)], each = 3)
region_test
 [1] "East Asia"               "East Asia"              
 [3] "East Asia"               "Europe"                 
 [5] "Europe"                  "Europe"                 
 [7] "North America"           "North America"          
 [9] "North America"           "South & South-East Asia"
[11] "South & South-East Asia" "South & South-East Asia"
[13] "Russia & Central Asia"   "Russia & Central Asia"  
[15] "Russia & Central Asia"   "MENA"                   
[17] "MENA"                    "MENA"                   
[19] "Latin America"           "Latin America"          
[21] "Latin America"           "Sub-Saharan Africa"     
[23] "Sub-Saharan Africa"      "Sub-Saharan Africa"     
2.2.15.1.2 Step 2.

Add the names of the region in the last column by mutate and choose columns by select.

df_f15 %>% mutate(region = rep(regionWID[!is.na(regionWID)], each = 3))
df_f15 %>% mutate(region = rep(regionWID[!is.na(regionWID)], each = 3)) %>%
  select(region, group, tcap)
2.2.15.1.3 Step 3.

Now it is not difficult to draw a chart.

df_f15 %>% mutate(region = rep(regionWID[!is.na(regionWID)], each = 3)) %>%
  select(region, group, tcap) %>%
  ggplot(aes(x = region, y = tcap, fill = group)) +
  geom_col(position = "dodge") + 
  scale_x_discrete(labels = function(x) stringr::str_wrap(x, width = 10)) +
  labs(title = "Figure 15 Per capita emissions across the world, 2019", 
       x = "", y = "tonnes of CO2e per person per year", fill = "")

2.2.16 T1 Global millionaires and billionaires, 2021

Check the format of the sheet and add skip=4, n_max=7.

df_t1 <- read_excel("./data/WIR2022TablesFigures-Summary.xlsx", 
                    sheet = "T1", skip = 4, n_max = 7)
df_t1

Interpretation: In 2021, there were 62.2 million people in the world owning more than $1 million (measured at Market Exchange Rates). Their average wealth was $ 2.8 million, representing a total of $174 trillion. In our Tax scenario 2, a global progressive wealth tax would yield 2.1% of global income, taking into account capital depreciation and evasion. Sources and series: wir2022.wid.world/methodology.

3 Other Data of WIR2022

3.1 Data Used in Chapter 1 to Chapter 10

There are three ways to import data used in Chapter 1 to Chapter 10.

3.1.2 Download the zip file and move to you data folder

  1. Go to the Methodology site: https://wir2022.wid.world/methodology/

  2. Double click the download link under Dataset 2, i.e., the datasets of chapters 1 to 10 to dounload the zip file.

  3. Unzip the file using the helper application of your PC. In most cases, if you double click the zip file, you can get a folder containing Excel files.

  4. Move to your data folder and follow the line above of the previous method.

3.1.3 Use copying and pasting

Since the table structure of Excel is complicated, it may be much easier to copy and paste the range you want to use. In this case keep the record of the data so that the method is reproducible.

# Copy the range of an Excel sheet into your clipboard
wir_F1.0c <- read_delim(clipboard())

3.2 Package: wid to Download Data

In the following, we explain how to download data by an R package wid-r-tool. First, you need to install the package. The wid-r-tool is a package in the development stage; it is not an official R package yet; you need to use the package devtools to install it.

To install, run the following code or in Console. If you are recommended to update, select one by choosing ‘All’.

install.packages("devtools")
devtools::install_github("WIDworld/wid-r-tool")

For references use ‘?download_wid’ or put ‘download_wid’ in the search box under Help.

It is similar to WDI. For more detail and examples, see vignettes.

For indicators of WIR, see codebook.

library("wid")

3.2.1 Examples

3.2.1.1 Evolution of national income over long period

This example is essentially the same as in the vignettes.

  • We now plot the evolution of average net national income per adult in Japan, France, Germany, the United Kingdom and the United States.
# Average national income data
data <- download_wid(
    indicators = "anninc", # Average net national income
    areas = c("JP", "FR", "US", "DE", "GB"),
    ages = 992 # Adults
) %>% rename(value_lcu = value)
# Purchasing power parities with US dollar
ppp <- download_wid(
    indicators = "xlcusp", # US PPP
    areas = c("JP", "FR", "US", "DE", "GB"), # France, China and United States
    year = 2016 # Reference year only
) %>% rename(ppp = value) %>% select(-year, -percentile)
# Convert from local currency to PPP US dollar
data <- merge(data, ppp, by = "country") %>%
    mutate(value_ppp = value_lcu/ppp) %>%
    filter(year %in% 1950:2021)
ggplot(data) +
    geom_line(aes(x = year, y = value_ppp, color = country, linetype=country)) +
    scale_y_log10(breaks = c(2e3, 5e3, 1e4, 2e4, 5e4)) +
    ylab("2016 $ PPP") +
    scale_color_discrete(
        labels = c("JP" = "Japan", "US" = "USA", "FR" = "France", "DE" = "Germany", "GB" = "UK")
    ) + 
    scale_linetype_discrete(
        labels = c("JP" = "Japan", "US" = "USA", "FR" = "France", "DE" = "Germany", "GB" = "UK")
    ) + 
    ggtitle("Average net national income per adult")

3.2.1.2 wealg and wealp

  • After installing the package, check the codebook of the indicators.
  • The wir indicator is a combination of one alphabet and five alphabets. See the codebook above.

We use the folowing two indicators.

  • w wealth-to-income ratio or labor/capital share fraction of national income
  • wealg: net public wealth to net national income ratio
  • wealp: net private wealth to net national income ratio
3.2.1.2.1 Step 1.
  • Importing the data using download_wid.
library(wid)
wwealg <- download_wid(indicators = "wwealg", areas = "all", years = "all")
wwealp <- download_wid(indicators = "wwealp", areas = "all", years = "all")
public <- wwealg %>% select(country, year, public = value)
public
private <- wwealp %>% select(country, year, private = value)
private
3.2.1.2.2 Step 2.

*Combine two tables.

public_vs_private <- public %>% left_join(private)
Joining, by = c("country", "year")
public_vs_private
3.2.1.2.3 Step 3.
  • To add country names, use the WDI data.

  • We use a package WDI to use WDIcache() as a reference.

wdi_cache <- WDI::WDIcache()
3.2.1.2.4 Step 4.
  • Use left_join to add country names
df_pub_priv <- public_vs_private %>% pivot_longer(cols = c(3,4), names_to = "category", values_to = "value") %>% left_join(wdi_cache$country, by = c("country"="iso2c")) %>%
  select(country = country.y, iso2c = country, year, category, value, region, income, lending)
df_pub_priv
  • Check if the country name is missing.
df_pub_priv %>% filter(is.na(country)) %>% 
  filter(nchar(iso2c)==2) %>%
  distinct(iso2c) %>% pull(iso2c)
 [1] "AI" "MS" "OA" "OB" "OC" "OD" "OH" "OI" "OJ" "QB" "QC" "QD" "QE"
[14] "QF" "QG" "QH" "QI" "QJ" "QK" "QL" "QM" "QN" "QO" "QP" "QQ" "QR"
[27] "QS" "QT" "QU" "QV" "QW" "QX" "QY" "WO" "XA" "XB" "XR" "XS"

3.2.1.3 Step 5.

  • Select countries
unique(df_pub_priv$country)
  [1] "Andorra"                                     
  [2] "United Arab Emirates"                        
  [3] "Afghanistan"                                 
  [4] "Antigua and Barbuda"                         
  [5] NA                                            
  [6] "Albania"                                     
  [7] "Armenia"                                     
  [8] "Angola"                                      
  [9] "Argentina"                                   
 [10] "American Samoa"                              
 [11] "Austria"                                     
 [12] "Australia"                                   
 [13] "Aruba"                                       
 [14] "Azerbaijan"                                  
 [15] "Bosnia and Herzegovina"                      
 [16] "Barbados"                                    
 [17] "Bangladesh"                                  
 [18] "Belgium"                                     
 [19] "Burkina Faso"                                
 [20] "Bulgaria"                                    
 [21] "Bahrain"                                     
 [22] "Burundi"                                     
 [23] "Benin"                                       
 [24] "Bermuda"                                     
 [25] "Brunei Darussalam"                           
 [26] "Bolivia"                                     
 [27] "Brazil"                                      
 [28] "Bahamas, The"                                
 [29] "Bhutan"                                      
 [30] "Botswana"                                    
 [31] "Belize"                                      
 [32] "Canada"                                      
 [33] "Congo, Dem. Rep."                            
 [34] "Central African Republic"                    
 [35] "Congo, Rep."                                 
 [36] "Switzerland"                                 
 [37] "Cote d'Ivoire"                               
 [38] "Chile"                                       
 [39] "Cameroon"                                    
 [40] "China"                                       
 [41] "Colombia"                                    
 [42] "Costa Rica"                                  
 [43] "Cuba"                                        
 [44] "Cabo Verde"                                  
 [45] "Curacao"                                     
 [46] "Cyprus"                                      
 [47] "Czechia"                                     
 [48] "Germany"                                     
 [49] "Djibouti"                                    
 [50] "Denmark"                                     
 [51] "Dominica"                                    
 [52] "Dominican Republic"                          
 [53] "Algeria"                                     
 [54] "Ecuador"                                     
 [55] "Estonia"                                     
 [56] "Egypt, Arab Rep."                            
 [57] "Eritrea"                                     
 [58] "Spain"                                       
 [59] "Ethiopia"                                    
 [60] "Finland"                                     
 [61] "Fiji"                                        
 [62] "Micronesia, Fed. Sts."                       
 [63] "France"                                      
 [64] "Gabon"                                       
 [65] "United Kingdom"                              
 [66] "Grenada"                                     
 [67] "Georgia"                                     
 [68] "Ghana"                                       
 [69] "Greenland"                                   
 [70] "Gambia, The"                                 
 [71] "Guinea"                                      
 [72] "Equatorial Guinea"                           
 [73] "Greece"                                      
 [74] "Guatemala"                                   
 [75] "Guam"                                        
 [76] "Guinea-Bissau"                               
 [77] "Guyana"                                      
 [78] "Hong Kong SAR, China"                        
 [79] "Honduras"                                    
 [80] "Croatia"                                     
 [81] "Haiti"                                       
 [82] "Hungary"                                     
 [83] "Indonesia"                                   
 [84] "Ireland"                                     
 [85] "Israel"                                      
 [86] "Isle of Man"                                 
 [87] "India"                                       
 [88] "Iraq"                                        
 [89] "Iran, Islamic Rep."                          
 [90] "Iceland"                                     
 [91] "Italy"                                       
 [92] "Jamaica"                                     
 [93] "Jordan"                                      
 [94] "Japan"                                       
 [95] "Kenya"                                       
 [96] "Kyrgyz Republic"                             
 [97] "Cambodia"                                    
 [98] "Kiribati"                                    
 [99] "Comoros"                                     
[100] "St. Kitts and Nevis"                         
[101] "Korea, Dem. People's Rep."                   
[102] "Korea, Rep."                                 
[103] "Kuwait"                                      
[104] "Cayman Islands"                              
[105] "Kazakhstan"                                  
[106] "Lao PDR"                                     
[107] "Lebanon"                                     
[108] "St. Lucia"                                   
[109] "Liechtenstein"                               
[110] "Sri Lanka"                                   
[111] "Liberia"                                     
[112] "Lesotho"                                     
[113] "Lithuania"                                   
[114] "Luxembourg"                                  
[115] "Latvia"                                      
[116] "Libya"                                       
[117] "Morocco"                                     
[118] "Monaco"                                      
[119] "Moldova"                                     
[120] "Montenegro"                                  
[121] "Madagascar"                                  
[122] "Marshall Islands"                            
[123] "North Macedonia"                             
[124] "Mali"                                        
[125] "Myanmar"                                     
[126] "Mongolia"                                    
[127] "Macao SAR, China"                            
[128] "Northern Mariana Islands"                    
[129] "Mauritania"                                  
[130] "Malta"                                       
[131] "Mauritius"                                   
[132] "Maldives"                                    
[133] "Malawi"                                      
[134] "Mexico"                                      
[135] "Malaysia"                                    
[136] "Mozambique"                                  
[137] "Namibia"                                     
[138] "New Caledonia"                               
[139] "Niger"                                       
[140] "Nigeria"                                     
[141] "Nicaragua"                                   
[142] "Netherlands"                                 
[143] "Norway"                                      
[144] "Nepal"                                       
[145] "Nauru"                                       
[146] "New Zealand"                                 
[147] "OECD members"                                
[148] "Oman"                                        
[149] "Panama"                                      
[150] "Peru"                                        
[151] "French Polynesia"                            
[152] "Papua New Guinea"                            
[153] "Philippines"                                 
[154] "Pakistan"                                    
[155] "Poland"                                      
[156] "Puerto Rico"                                 
[157] "West Bank and Gaza"                          
[158] "Portugal"                                    
[159] "Palau"                                       
[160] "Paraguay"                                    
[161] "Qatar"                                       
[162] "Romania"                                     
[163] "Serbia"                                      
[164] "Russian Federation"                          
[165] "Rwanda"                                      
[166] "Saudi Arabia"                                
[167] "Solomon Islands"                             
[168] "Seychelles"                                  
[169] "Sudan"                                       
[170] "Sweden"                                      
[171] "Singapore"                                   
[172] "Slovenia"                                    
[173] "Slovak Republic"                             
[174] "Sierra Leone"                                
[175] "San Marino"                                  
[176] "Senegal"                                     
[177] "Somalia"                                     
[178] "Suriname"                                    
[179] "South Sudan"                                 
[180] "Sao Tome and Principe"                       
[181] "El Salvador"                                 
[182] "Sint Maarten (Dutch part)"                   
[183] "Syrian Arab Republic"                        
[184] "Eswatini"                                    
[185] "Turks and Caicos Islands"                    
[186] "Chad"                                        
[187] "Togo"                                        
[188] "Thailand"                                    
[189] "Tajikistan"                                  
[190] "Timor-Leste"                                 
[191] "Turkmenistan"                                
[192] "Tunisia"                                     
[193] "Tonga"                                       
[194] "Turkiye"                                     
[195] "Trinidad and Tobago"                         
[196] "Tuvalu"                                      
[197] "Taiwan, China"                               
[198] "Tanzania"                                    
[199] "Ukraine"                                     
[200] "Uganda"                                      
[201] "United States"                               
[202] "Uruguay"                                     
[203] "Uzbekistan"                                  
[204] "St. Vincent and the Grenadines"              
[205] "Venezuela, RB"                               
[206] "British Virgin Islands"                      
[207] "Virgin Islands (U.S.)"                       
[208] "Vietnam"                                     
[209] "Vanuatu"                                     
[210] "Samoa"                                       
[211] "IBRD only"                                   
[212] "IDA only"                                    
[213] "Least developed countries: UN classification"
[214] "Low income"                                  
[215] "Lower middle income"                         
[216] "Yemen, Rep."                                 
[217] "South Africa"                                
[218] "Zambia"                                      
[219] "Zimbabwe"                                    
3.2.1.3.1 Step 6.

Draw a chart.

df_pub_priv %>% 
  filter(country %in% c("Japan", "Norway", "Sweden", "Denmark", "Finland"), year %in% 1970:2020) %>%
  ggplot(aes(year, value, color = country, linetype = category)) + geom_line()

We choose two indicators: ‘wealg’ and ‘wealp’. WIR2022 indicators consists of 6 characters; 1 letter code plus 5 letter code. You can find the list in the codebook.

If you want to study WIR2022, please study the report, the codebook, and wir vignette together with the R Notebook.

LS0tCnRpdGxlOiAiV29ybGQgSW5lcXVhbGl0eSBSZXBvcnQgMjAyMiIKYXV0aG9yOiAiRFMtU0wiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIgCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQotLS0KCiMgSW50cm9kdWN0aW9uCgpJbiB0aGlzIG5vdGUsIHdlIHN0dWR5IGhvdyB0byBjb25zdHJ1Y3QsIG9yIHJlY3JlYXRlIGNoYXJ0cyBwcmVzZW50ZWQgaW4gV29ybGQgSW5lcXVhbGl0eSBSZXBvcnQuIFdlIGZvY3VzIG9uIHRoZSBFeGVjdXRpdmUgU3VtbWFyeSwgaG93ZXZlciwgd2UgaG9wZSB0aGF0IHlvdSBjYW4gc3R1ZHkgdGhlIHJlcG9ydCBpbiBtb3JlIGRldGFpbCB1c2luZyB0aGUgb3JpZ2luYWwgZGF0YSBwcm92aWRlZCBpbiB0aGUgc2l0ZS4KCiMjIFdJUjIwMjIKCiogV29ybGQgSW5lcXVhbGl0eSBSZXBvcnQ6IGh0dHBzOi8vd2lyMjAyMi53aWQud29ybGQvCiogRXhlY3V0aXZlIFN1bW1hcnk6IGh0dHBzOi8vd2lyMjAyMi53aWQud29ybGQvZXhlY3V0aXZlLXN1bW1hcnkvCiogTWV0aG9kb2xvZ3k6IGh0dHBzOi8vd2lyMjAyMi53aWQud29ybGQvbWV0aG9kb2xvZ3kvCgpUaGVyZSBpcyBhbiBSIHBhY2thZ2UgdG8gbWFrZSBpdCBlYXNpZXIgdG8gZG93bmxvYWQgdGhlIGRhdGEuCgoqIFtSIHBhY2thZ2UgdG8gZG93bmxvYWQgZGF0YSBmcm9tIHRoZSBXSUQud29ybGQgZGF0YWJhc2VdKGh0dHBzOi8vZ2l0aHViLmNvbS90aG9tYXNibGFuY2hldC93aWQtci10b29sKQogIC0gU2VlIFtgZG93bmxvYWRfd2lkYF0oI3dpci1kLXRvb2wpCgojIEV4ZWN1dGl2ZSBTdW1tYXJ5CgojIyBTZXR1cAoKRmlyc3QsIGNyZWF0ZSBhIG5ldyBwcm9qZWN0IHVzaW5nIFIgU3R1ZGlvIGFuZCBjcmVhdGUgYSBgZGF0YWAgZm9sZGVyIGluIGl0IGJ5IHJ1bm5pbmcgdGhlIGZvbGxvd2luZyBjb2RlLiBJdCBpcyBiZXR0ZXIgdG8gc2V0IGBMYW5nID0gImVuImAgYXMgeW91IGNhbiBmaW5kIGEgcmVzb2x1dGlvbiBlYXNpbHkgYnkgcG9zdGluZyB0aGUgZXJyb3IgbWVzc2FnZS4KCmBgYHtyIHNldHVwLCBldmFsPUZBTFNFfQpTeXMuc2V0ZW52KExBTkcgPSAiZW4iKQpkaXIuY3JlYXRlKCIuL2RhdGEiKQpgYGAKCgoqIERhdGE6IGh0dHBzOi8vd2lyMjAyMi53aWQud29ybGQvd3d3LXNpdGUvdXBsb2Fkcy8yMDIyLzAzL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeAoqIERhdGEgYXJlIGluIEV4Y2VsIGZvcm1hdCBhbmQgY2hhcnRzIGFyZSBhbHNvIGNyZWF0ZWQgaW4gRXhjZWwuCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KERUKQpgYGAKCmBgYHtyIHN1bW1hcnktZGF0YSwgY2FzaCA9IFRSVUUsIGV2YWwgPSBGQUxTRX0KdXJsX3N1bW1hcnkgPC0gImh0dHBzOi8vd2lyMjAyMi53aWQud29ybGQvd3d3LXNpdGUvdXBsb2Fkcy8yMDIyLzAzL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeCIKZG93bmxvYWQuZmlsZSgKICB1cmwgPSB1cmxfc3VtbWFyeSwgCiAgZGVzdGZpbGUgPSAiLi9kYXRhL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeCIsCiAgbW9kZSA9ICJ3YiIpIApgYGAKCioqTm90ZToqKiAKCiogYG1vZGUgPSAid2IiYCBpcyBmb3IgYmluYXJ5IGZpbGVzLiAKKiBJZiB5b3UgZ2V0IGFuIGVycm9yLCBnbyB0byBbTWV0aG9kb2xvZ3kgcGFnZV0oaHR0cHM6Ly93aXIyMDIyLndpZC53b3JsZC9tZXRob2RvbG9neS8pIGFuZCBkb3dubG9hZCBEYXRhc2V0cyAxLiBPcGVuIHRoZSBmaWxlIGFuZCBzYXZlIGl0IGluIHRoZSBgZGF0YWAgZm9sZGVyIGluIHlvdXIgUHJvamVjdCBmb2xkZXIuCgpBcyBNYWMgdXNlcyByZXNvdXJjZSBmaWxlcywgdGhlIGZvbGxvd2luZyBzaW1wbGUgY29kZSB3b3JrcyBhcyB3ZWxsLiAKCmBgYApkb3dubG9hZC5maWxlKHVybCA9IHVybF9zdW1tYXJ5LCAKZGVzdGZpbGUgPSAiZGF0YS9XSVIyMDIyVGFibGVzRmlndXJlcy1TdW1tYXJ5Lnhsc3giKSAKYGBgCgpgYGB7ciBzdW1tYXJ5LWRhdGEtc2hlZXQsIGNhc2ggPSBUUlVFfQpzdW1tYXJ5X3NoZWV0cyA8LSBleGNlbF9zaGVldHMoImRhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtU3VtbWFyeS54bHN4IikKc3VtbWFyeV9zaGVldHMKYGBgCgoqIFlvdSBjYW4gY2hlY2sgdGhlIHNoZWV0IG5hbWVzIGlmIHlvdSBvcGVuIHRoZSBFeGNlbCBmaWxlLiBIb3dldmVyLCB0byBpbXBvcnQgYSBzaGVldCwgaXQgaXMgY29udmVuaWVudCB0byBoYXZlIGEgbGlzdCwgYXMgd2UgY2FuIGNvcHkgYW5kIHBhc3RlIHRoZSBzaGVldCBuYW1lLgoqIE5vdGUgdGhhdCBzb21lIG9mIHRoZSBzaGVldCBuYW1lcyBjb250YWluIGEgcGVyaW9kLgoqIFlvdSBjYW4gcmVwbGFjZSBgc2hlZXQgPSAiSW5kZXgiYCBieSBgc2hlZXQgPSAxYC4gSG93ZXZlciwgdGhlIHNoZWV0IG51bWJlciBzdGF5cyB0aGUgc2FtZSBpZiBhIHNoZWV0IGlzIGRlbGV0ZWQuIFNvIGl0IGlzIHNhZmVyIHRvIHVzZSB0aGUgc2hlZXQgbmFtZS4KCmBgYHtyfQpkZl9pbmRleCA8LSByZWFkX2V4Y2VsKCJkYXRhL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeCIsIHNoZWV0ID0gIkluZGV4IikKZGZfaW5kZXgKYGBgCiogVGhlIGxpc3Qgb2YgdGhlIHRpdGxlcyBvZiB0aGUgdGFibGVzIGFuZCB0aGUgZmlndXJlcy4KCiMjIERhdGEgYW5kIENoYXJ0cwoKKiBEYXRhIGFyZSBpbiAiZGF0YS1GMSIgdG8gImRhdGEtRjE1Ii4KCiMjIyBGMTogR2xvYmFsIGluY29tZSBhbmQgd2VhbHRoIGluZXF1YWxpdHksIDIwMjEKCmBgYHtyIGRhdGEtZjEsIGNhc2ggPSBUUlVFfQpkZl9mMSA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtU3VtbWFyeS54bHN4Iiwgc2hlZXQgPSAiZGF0YS1GMSIpCmBgYAoKKiBTaW5jZSB0aGUgZmlyc3QgY29sdW1uIGRvZXMgbm90IGhhdmUgYSBjb2x1bW4gbmFtZSwgUiBhc3NpZ25zIGAuLi4xYCB0byBpdHMgbmFtZSwgYW5kIHJldHVybnMgYSBtZXNzYWdlOiBgTmV3IG5hbWVzOi5gCgpgYGB7cn0KZGZfZjEKYGBgCgpgYGB7cn0KZGZfZjEgJT4lIHNlbGVjdChjYXQgPSAuLi4xLCAyOjQpICU+JQogIHBpdm90X2xvbmdlcigyOjQsIG5hbWVzX3RvID0gImdyb3VwIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gY2F0LCB5ID0gdmFsdWUsIGZpbGwgPSBncm91cCkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKyAKICBnZW9tX3RleHQoYWVzKHggPSBjYXQsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBncm91cCwgbGFiZWwgPSBzY2FsZXM6OmxhYmVsX3BlcmNlbnQoYWNjdXJhY3k9MSkodmFsdWUpKSwgdmp1c3QgPSAtMC4wOCwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjkpKSArIAogIGxhYnModGl0bGUgPSAiRmlndXJlIDEuIEdsb2JhbCBpbmNvbWUgYW5kIHdlYWx0aCBpbmVxdWFsaXR5LCAyMDIxIiwKICAgICAgIHggPSAiIiwgeSA9ICJTaGFyZSBvZiB0b3RhbCBpbmNvbWUgb3Igd2VhbHRoIiwgZmlsbCA9ICIiKQpgYGAKCioqSW50ZXJwcmV0YXRpb24qKjogVGhlIGdsb2JhbCBib3R0b20gNTAlIGNhcHR1cmVzIDguNSUgb2YgdG90YWwgaW5jb21lIG1lYXN1cmVkIGF0IFB1cmNoYXNpbmcgUG93ZXIgUGFyaXR5IChQUFApLiBUaGUgZ2xvYmFsIGJvdHRvbSA1MCUgb3ducyAyJSBvZiB3ZWFsdGggKGF0IFB1cmNoYXNpbmcgUG93ZXIgUGFyaXR5KS4gVGhlIGdsb2JhbCB0b3AgMTAlIG93bnMgNzYlIG9mIHRvdGFsIEhvdXNlaG9sZCB3ZWFsdGggYW5kIGNhcHR1cmVzIDUyJSBvZiB0b3RhbCBpbmNvbWUgaW4gMjAyMS4gTm90ZSB0aGF0IHRvcCB3ZWFsdGggaG9sZGVycyBhcmUgbm90IG5lY2Vzc2FyaWx5IHRvcCBpbmNvbWUgaG9sZGVycy4gSW5jb21lcyBhcmUgbWVhc3VyZWQgYWZ0ZXIgdGhlIG9wZXJhdGlvbiBvZiBwZW5zaW9uIGFuZCB1bmVtcGxveW1lbnQgc3lzdGVtcyBhbmQgYmVmb3JlIHRheGVzIGFuZCB0cmFuc2ZlcnMuICAgCioqU291cmNlcyBhbmQgc2VyaWVzKio6IHdpcjIwMjIud2lkLndvcmxkL21ldGhvZG9sb2d5LgoKIyMjIyBFeHBsYW5hdGlvbgojIyMjIyBTdGVwIDEuCgoqIFRoZSBjaGFydCBkb2VzIG5vdCB1c2UgVG9wIDElIGRhdGEuCiogVGhlcmUgYXJlIHR3byBncm91cHMsIEluY29tZSBhbmQgV2VhbHRoLiBXZSBuZWVkIHRvIHRpZHkgdGhlIGRhdGEgdXNpbmcgYHBpdm90X2xvbmdlcmAuCiogVGhlIGJhc2ljIGZvcm1hdCBvZiBgcGl2b3RfbG9uZ2VyYCBpczoKICAtIGBwaXZvdF9sb25nZXIoY29scywgbmFtZXNfdG8gPSAiZ3JvdXAiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKWAsIGFuZCBgY29sc2AgaXMgdGhlIGNvbHVtbnMgdG8gcGl2b3QgaW50byBhIGxvbmdlciBmb3JtYXQuIEhlbmNlLCBpbiB0aGlzIGNhc2UsIGBjb2xzID0gMjo0YCBvciBgY29scyA9IC0xYCwgaS5lLiwgZXhjZXB0IHRoZSBmaXJzdCBjb2x1bW4uCgpgYGB7cn0KZGZfZjEgJT4lIHNlbGVjdChjYXQgPSAuLi4xLCAyOjQpICU+JQogIHBpdm90X2xvbmdlcigyOjQsIG5hbWVzX3RvID0gImdyb3VwIiwgdmFsdWVzX3RvID0gInZhbHVlIikKYGBgCgojIyMjIyBTdGVwIDIuCgoqIE5vdyB3ZSB1c2UgYGdncGxvdDJgIHRvIGRyYXcgYSBjaGFydC4KCmBgYHtyfQpkZl9mMSAlPiUgc2VsZWN0KGNhdCA9IC4uLjEsIDI6NCkgJT4lCiAgcGl2b3RfbG9uZ2VyKDI6NCwgbmFtZXNfdG8gPSAibGV2ZWwiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBjYXQsIHkgPSB2YWx1ZSwgZmlsbCA9IGxldmVsKSkgKwogIGdlb21fY29sKCkKYGBgCgojIyMjIyBTdGVwIDMuCgoqIEluIG9yZGVyIHRvIHBsYWNlIGNvbHVtbnMgc2lkZSBieSBzaWRlLCB3ZSB1c2UgdGhlIG9wdGlvbiBgcG9zaXRpb24gPSBkb2RnZWAuCgpgYGB7cn0KZGZfZjEgJT4lIHNlbGVjdChjYXQgPSAuLi4xLCAyOjQpICU+JQogIHBpdm90X2xvbmdlcigyOjQsIG5hbWVzX3RvID0gImdyb3VwIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gY2F0LCB5ID0gdmFsdWUsIGZpbGwgPSBncm91cCkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpCmBgYAojIyMjIyBTdGVwIDQuCgoqIFdlIHVzZSB0aGUgcGVyY2VudCBzY2FsZSBvbiB5LWF4aXMuCiogSW4gdGhpcyBjYXNlLCBgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGMoIjAlIiwgIjIwJSIsICI0MCUiLCAiNjAlIiwgIjgwJSIpKWAgZG9lcyB0aGUgc2FtZS4KCmBgYHtyfQpkZl9mMSAlPiUgc2VsZWN0KGNhdCA9IC4uLjEsIDI6NCkgJT4lCiAgcGl2b3RfbG9uZ2VyKDI6NCwgbmFtZXNfdG8gPSAiZ3JvdXAiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBjYXQsIHkgPSB2YWx1ZSwgZmlsbCA9IGdyb3VwKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKQpgYGAKCiMjIyMjIFN0ZXAgNS4KCiogQWRkIHRoZSB0aXRsZSBhbmQgdGhlIGxhYmVsIG9mIHRoZSB5LWF4aXMsIGFuZCBlcmFzZSB0aGUgbGFiZWwgb2YgdGhlIHgtYXhpcyBhbmQgdGhlIGxlZ2VuZC4KCmBgYHtyfQpkZl9mMSAlPiUgc2VsZWN0KGNhdCA9IC4uLjEsIDI6NCkgJT4lCiAgcGl2b3RfbG9uZ2VyKDI6NCwgbmFtZXNfdG8gPSAiZ3JvdXAiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBjYXQsIHkgPSB2YWx1ZSwgZmlsbCA9IGdyb3VwKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMS4gR2xvYmFsIGluY29tZSBhbmQgd2VhbHRoIGluZXF1YWxpdHksIDIwMjEiLAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIHRvdGFsIGluY29tZSBvciB3ZWFsdGgiLCBmaWxsID0gIiIpCmBgYAoKIyMjIyMgU3RlcCA2LgoKKiBBZGQgdGhlIHZhbHVlIGluIHBlcmNlbnQgYXMgdGhlIHRleHQgdG8gdG9wIG9mIGVhY2ggY29sdW1uLgoKYGBge3J9CmRmX2YxICU+JSBzZWxlY3QoY2F0ID0gLi4uMSwgMjo0KSAlPiUKICBwaXZvdF9sb25nZXIoMjo0LCBuYW1lc190byA9ICJncm91cCIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIGdncGxvdChhZXMoeCA9IGNhdCwgeSA9IHZhbHVlLCBmaWxsID0gZ3JvdXApKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArIAogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBnZW9tX3RleHQoYWVzKHggPSBjYXQsIHkgPSB2YWx1ZSwgZ3JvdXAgPSBncm91cCwgbGFiZWwgPSBzY2FsZXM6OmxhYmVsX3BlcmNlbnQoYWNjdXJhY3k9MSkodmFsdWUpKSwgCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC45KSkgKyAKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSAxLiBHbG9iYWwgaW5jb21lIGFuZCB3ZWFsdGggaW5lcXVhbGl0eSwgMjAyMSIsCiAgICAgICB4ID0gIiIsIHkgPSAiU2hhcmUgb2YgdG90YWwgaW5jb21lIG9yIHdlYWx0aCIsIGZpbGwgPSAiIikKYGBgCgojIyMjIyBTdGVwIDcuCgoqIElmIHdlIHdhbnQgdG8gcGxhY2UgdGhlIGxhYmVscyBhdCB0aGUgdG9wIG9mIHRoZSBjb2x1bW5zLCB1c2UgYHZqdXN0YC4KCmBgYHtyfQpkZl9mMSAlPiUgc2VsZWN0KGNhdCA9IC4uLjEsIDI6NCkgJT4lCiAgcGl2b3RfbG9uZ2VyKDI6NCwgbmFtZXNfdG8gPSAiZ3JvdXAiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBjYXQsIHkgPSB2YWx1ZSwgZmlsbCA9IGdyb3VwKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gY2F0LCB5ID0gdmFsdWUsIGdyb3VwID0gZ3JvdXAsIGxhYmVsID0gc2NhbGVzOjpsYWJlbF9wZXJjZW50KGFjY3VyYWN5PTEpKHZhbHVlKSksIHZqdXN0ID0gMCwKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSkpICsgCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMS4gR2xvYmFsIGluY29tZSBhbmQgd2VhbHRoIGluZXF1YWxpdHksIDIwMjEiLAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIHRvdGFsIGluY29tZSBvciB3ZWFsdGgiLCBmaWxsID0gIiIpCmBgYAoKIyMjIEYyOiBUaGUgcG9vcmVzdCBoYWxmIGxhZ3MgYmVoaW5kOiBCb3R0b20gNTAlLCBtaWRkbGUgNDAlIGFuZCB0b3AgMTAlIGluY29tZSBzaGFyZXMgYWNyb3NzIHRoZSB3b3JsZCBpbiAyMDIxCgpgYGB7ciBkYXRhLWYyLCBjYXNoID0gVFJVRX0KZGZfZjIgPC0gcmVhZF9leGNlbCgiLi9kYXRhL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeCIsIHNoZWV0ID0gImRhdGEtRjIiKQpkZl9mMgpgYGAKCmBgYHtyfQpkZl9mMiAlPiUgcGl2b3RfbG9uZ2VyKDM6NSwgbmFtZXNfdG8gPSAibGV2ZWwiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBpc28sIHkgPSB2YWx1ZSwgZmlsbCA9IGxldmVsKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyAKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cmluZ3I6OnN0cl93cmFwKHgsIHdpZHRoID0gOCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMi4gVGhlIHBvb3Jlc3QgaGFsZiBsYWdzIGJlaGluZCBCb3R0b20gNTAlLCBtaWRkbGUgNDAlIFxuYW5kIHRvcCAxMCUgaW5jb21lIHNoYXJlcyBhY3Jvc3MgdGhlIHdvcmxkIGluIDIwMjEiLAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIG5hdGlvbmFsIGluY29tZSAoJSkiLCBmaWxsID0gIiIpCmBgYAoqKkludGVycHJldGF0aW9uKio6IEluIExhdGluIEFtZXJpY2EsIHRoZSB0b3AgMTAlIGNhcHR1cmVzIDU1JSBvZiBuYXRpb25hbCBpbmNvbWUsIGNvbXBhcmVkIHRvIDM2JSBpbiBFdXJvcGUuIEluY29tZSBpcyBtZWFzdXJlZCBhZnRlciBwZW5zaW9uIGFuZCB1bmVtcGxveW1lbnQgY29udHJpYnV0aW9ucyBhbmQgYmVuZWZpdHMgcGFpZCBhbmQgcmVjZWl2ZWQgYnkgaW5kaXZpZHVhbHMgYnV0IGJlZm9yZSBpbmNvbWUgdGF4ZXMgYW5kIG90aGVyIHRyYW5zZmVycy4gICAKKipTb3VyY2VzIGFuZCBzZXJpZXMqKjogd3d3LndpcjIwMjIud2lkLndvcmxkL21ldGhvZG9sb2d5LgoKIyMjIyBFeHBsYW5hdGlvbgojIyMjIyBTdGVwIDEuCgoqIFNpbWlsYXIgdG8gRjEuCgpgYGB7cn0KZGZfZjIgJT4lIHBpdm90X2xvbmdlcigzOjUsIG5hbWVzX3RvID0gImxldmVsIiwgdmFsdWVzX3RvID0gInZhbHVlIikKYGBgCgojIyMjIyBTdGVwIDIuCgoqU2luY2UgdGhlIHRpdGxlIGlzIHZlcnkgbG9uZywgaW5zZXJ0IGBcbmAgZm9yIGEgbGluZSBicmVhay4gSWYgYFxuIGFuZGAsIHRoZW4gaXQgY3JlYXRlcyBhIHNwYWNlIGJlZm9yZSBgYW5kYC4KCmBgYHtyfQpkZl9mMiAlPiUgcGl2b3RfbG9uZ2VyKDM6NSwgbmFtZXNfdG8gPSAibGV2ZWwiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBpc28sIHkgPSB2YWx1ZSwgZmlsbCA9IGxldmVsKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMi4gVGhlIHBvb3Jlc3QgaGFsZiBsYWdzIGJlaGluZCBCb3R0b20gNTAlLCBtaWRkbGUgNDAlIFxuYW5kIHRvcCAxMCUgaW5jb21lIHNoYXJlcyBhY3Jvc3MgdGhlIHdvcmxkIGluIDIwMjEiLAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIG5hdGlvbmFsIGluY29tZSAoJSkiLCBmaWxsID0gIiIpCmBgYAoKIyMjIyMgU3RlcCAzLgoKKiBUaGUgbGFiZWxzIG9mIHRoZSB4LWF4aXMgYXJlIG92ZXJsYXBwaW5nLiBPbmUgd2F5IGlzIHRvIGFkZCBgYW5nbGVgLiBTZWUgYmVsb3cuIAoqIEFub3RoZXIgd2F5IGlzIHRvIHVzZSAKYHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgc3RyaW5ncjo6c3RyX3dyYXAoeCwgd2lkdGggPSA4KSlgIHRvIHdyYXAuIFNpbmNlIGxhYmVsIHZhcmllcyB3ZSB1c2UgYSBmdW5jdGlvbiB3aXRoIGEgdmFyaWFibGUgeC4gU2VlIGFib3ZlLgoKYGBge3J9CmRmX2YyICU+JSBwaXZvdF9sb25nZXIoMzo1LCBuYW1lc190byA9ICJsZXZlbCIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIGdncGxvdChhZXMoeCA9IGlzbywgeSA9IHZhbHVlLCBmaWxsID0gbGV2ZWwpKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAsIHZqdXN0ID0gMSwgaGp1c3Q9MSkpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDIuIFRoZSBwb29yZXN0IGhhbGYgbGFncyBiZWhpbmQgQm90dG9tIDUwJSwgbWlkZGxlIDQwJSBcbmFuZCB0b3AgMTAlIGluY29tZSBzaGFyZXMgYWNyb3NzIHRoZSB3b3JsZCBpbiAyMDIxIiwKICAgICAgIHggPSAiIiwgeSA9ICJTaGFyZSBvZiBuYXRpb25hbCBpbmNvbWUgKCUpIiwgZmlsbCA9ICIiKQpgYGAKCmBgYHtyfQpkZl9mMiAlPiUgcGl2b3RfbG9uZ2VyKDM6NSwgbmFtZXNfdG8gPSAibGV2ZWwiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBpc28sIHkgPSB2YWx1ZSwgZmlsbCA9IGxldmVsKSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyAKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cmluZ3I6OnN0cl93cmFwKHgsIHdpZHRoID0gOCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMi4gVGhlIHBvb3Jlc3QgaGFsZiBsYWdzIGJlaGluZCBCb3R0b20gNTAlLCBtaWRkbGUgNDAlIFxuYW5kIHRvcCAxMCUgaW5jb21lIHNoYXJlcyBhY3Jvc3MgdGhlIHdvcmxkIGluIDIwMjEiLAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIG5hdGlvbmFsIGluY29tZSAoJSkiLCBmaWxsID0gIiIpCmBgYAoKIyMjIEYzOiBUb3AgMTAvQm90dG9tIDUwIGluY29tZSBnYXBzIGFjcm9zcyB0aGUgd29ybGQsIDIwMjEKCgpgYGB7ciBkYXRhLWYzLCBjYXNoID0gVFJVRX0KZGZfZjMgPC0gcmVhZF9leGNlbCgiLi9kYXRhL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeCIsIHNoZWV0ID0gImRhdGEtRjMiKQpkZl9mMwpgYGAKCgpgYGB7cn0KbWFwMDwtbWFwX2RhdGEoIndvcmxkIikKbWFwMCRyZWdpb25bbWFwMCRyZWdpb249PSJEZW1vY3JhdGljIFJlcHVibGljIG9mIHRoZSBDb25nbyJdPC0iRFIgQ29uZ28iCm1hcDAkcmVnaW9uW21hcDAkcmVnaW9uPT0iUmVwdWJsaWMgb2YgQ29uZ28iXTwtIkNvbmdvIgptYXAwJHJlZ2lvblttYXAwJHJlZ2lvbj09Ikl2b3J5IENvYXN0Il08LSJDb3RlIGRJdm9pcmUiCm1hcDAkcmVnaW9uW21hcDAkcmVnaW9uPT0iVmlldG5hbSJdPC0iVmlldCBOYW0iCm1hcDAkcmVnaW9uW21hcDAkcmVnaW9uPT0iUnVzc2lhIl08LSJSdXNzaWFuIEZlZGVyYXRpb24iCm1hcDAkcmVnaW9uW21hcDAkcmVnaW9uPT0iU291dGggS29yZWEiXTwtIktvcmVhIgptYXAwJHJlZ2lvblttYXAwJHJlZ2lvbj09IlVLIl08LSJVbml0ZWQgS2luZ2RvbSIKbWFwMCRyZWdpb25bbWFwMCRyZWdpb249PSJCcnVuZWkiXTwtIkJydW5laSBEYXJ1c3NhbGFtIgptYXAwJHJlZ2lvblttYXAwJHJlZ2lvbj09Ikxhb3MiXTwtIkxhbyBQRFIiCm1hcDAkcmVnaW9uW21hcDAkcmVnaW9uPT0iQ290ZSBkSXZvaXJlIl08LSJDb3RlIGQnSXZvaXJlIgptYXAwJHJlZ2lvblttYXAwJHJlZ2lvbj09IkNhcGUgVmVyZGUiXTwtICJDYWJvIFZlcmRlIgptYXAwJHJlZ2lvblttYXAwJHJlZ2lvbj09IlN5cmlhIl08LSAiU3lyaWFuIEFyYWIgUmVwdWJsaWMiCm1hcDAkcmVnaW9uW21hcDAkcmVnaW9uPT0iVHJpbmlkYWQiXTwtICJUcmluaWRhZCBhbmQgVG9iYWdvIgptYXAwJHJlZ2lvblttYXAwJHJlZ2lvbj09IlRvYmFnbyJdPC0gIlRyaW5pZGFkIGFuZCBUb2JhZ28iCgpkZl9mMyAlPiUgCiAgbXV0YXRlKGBUb3AgMTAgQm90dG9tIDUwIFJhdGlvYCA9IGN1dChUMTBCNTAsYnJlYWtzID0gYyg1LCAxMiwgMTMsIDE2LCAxOSwxNDApLCBpbmNsdWRlLmxvd2VzdCA9IEZBTFNFKSkgJT4lCiAgZ2dwbG90KGFlcyhtYXBfaWQgPSBDb3VudHJ5KSkgKyBnZW9tX21hcChhZXMoZmlsbCA9IGBUb3AgMTAgQm90dG9tIDUwIFJhdGlvYCksIG1hcCA9IG1hcDApICsgZXhwYW5kX2xpbWl0cyh4ID0gd29ybGRfbWFwJGxvbmcsIHkgPSB3b3JsZF9tYXAkbGF0KSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMy4gVG9wIDEwL0JvdHRvbSA1MCBpbmNvbWUgZ2FwcyBhY3Jvc3MgdGhlIHdvcmxkLCAyMDIxIiwKICAgICAgIHggPSAiIiwgeSA9ICIiLCBmaWxsID0gIlRvcCAxMC9Cb3R0b20gNTAgcmF0aW8iKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKSArIAogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9J1lsT3JSZCcpCmBgYAoqKkludGVycHJldGF0aW9uKio6IEluIEJyYXppbCwgdGhlIGJvdHRvbSA1MCUgZWFybnMgMjkgdGltZXMgbGVzcyB0aGFuIHRoZSB0b3AgMTAlLiBUaGUgdmFsdWUgaXMgNyBpbiBGcmFuY2UuIEluY29tZSBpcyBtZWFzdXJlZCBhZnRlciBwZW5zaW9uIGFuZCB1bmVtcGxveW1lbnQgcGF5bWVudHMgYW5kIGJlbmVmaXRzIHJlY2VpdmVkIGJ5IGluZGl2aWR1YWxzIGJ1dCBiZWZvcmUgb3RoZXIgdGF4ZXMgdGhleSBwYXkgYW5kIHRyYW5zZmVycyB0aGV5IHJlY2VpdmUuIFNvdXJjZSBhbmQgc2VyaWVzOiB3aXIyMDIyLndpZC53b3JsZC9tZXRob2RvbG9neS4KCgojIyMjIEV4cGxhbmF0aW9uCiMjIyMjIFN0ZXAgMS4KCmBgYHtyIGRhdGEtZjMtMiwgY2FzaD1UUlVFfQpkZl9mMyA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtU3VtbWFyeS54bHN4Iiwgc2hlZXQgPSAiZGF0YS1GMyIpCmRmX2YzCmBgYAoKKiBXZSB1c2UgYG1hcF9kYXRhKCJ3b3JsZCIpYCBkYXRhIGF0dGFjaGVkIHRvIHRoZSBgdGlkeXZlcnNlYCBwYWNrYWdlLiBMZXQgdXMgbG9vayBhdCB0aGUgZGF0YSBmaXJzdC4KCmBgYHtyfQp3b3JsZF9tYXAgPC0gbWFwX2RhdGEoIndvcmxkIikKZGF0YXRhYmxlKHdvcmxkX21hcCkKYGBgCgoqIExldCB1cyB0cnkgdXNpbmcgdGhlIHN0YW5kYXJkIHRlbXBsYXRlIG9mIGBnZ3Bsb3RgLiBXZSB1c2UgYENvdW50cnlgIGZvciBgbWFwX2lkYCBhbmQgYFQxMEI1MGAgZm9yIG51bWVyaWNhbCBkYXRhLiBTaW5jZSBgd29ybGRfbWFwYCBkYXRhIGNvbnRhaW5zIGBsb25nYCBhbmQgYGxhdGAgb2YgZWFjaCByZWdpb24sIHdlIGFzc2lnbiB0aGVtIGFzIGBleHBhbmRfbGltaXRgLgoKYGBge3J9CmRmX2YzICU+JSAKICBnZ3Bsb3QoYWVzKG1hcF9pZCA9IENvdW50cnkpKSArIAogIGdlb21fbWFwKGFlcyhmaWxsID0gYFQxMEI1MGApLCBtYXAgPSB3b3JsZF9tYXApICsKICBleHBhbmRfbGltaXRzKHggPSB3b3JsZF9tYXAkbG9uZywgeSA9IHdvcmxkX21hcCRsYXQpCmBgYAoKIyMjIyMgU3RlcCAyLgoKKiBXZSBvYnNlcnZlIGEgY291cGxlIG9mIGlzc3VlcyBieSBjb21wYXJpbmcgdGhlbSB3aXRoIHRoZSBpbWFnZSBvZiB0aGUgb3JpZ2luYWwuCgoxLiBSdXNzaWEsIENvbmdvLCBhbmQgc29tZSBvdGhlciBhcmVhcyBhcmUgdm9pZC4KMi4gU2NhbGUgYW5kIHRoZSBsZWdlbmQgc2hvdWxkIGJlIGltcHJvdmVkLgozLiBJdCBtYXkgYmUgYmV0dGVyIHRvIGJyaW5nIHRoZSBsZWdlbmQgYXQgdGhlIGJvdHRvbSB0byBwcm92aWRlIG1vcmUgd2lkdGggdG8gdGhlIHdvcmxkIG1hcC4KCgohW0YzX3dvcmxkX21hcF0oZmlncy9GMy5wbmcpCgoKKiBUaGUgcmVnaW9uIG5hbWUgYW5kIHRoZSBjb3VudHJ5IG5hbWUgbWF5IGJlIGRpZmZlcmVudCBpbiB0d28gZGF0YXNldHMgYHdvcmxkX21hcGAgYW5kIGBkZl9mM2AuIExldCB1cyB0YWtlIGNhcmUgb2YgdGhlIGZpcnN0IGlzc3VlLgoKKiBUbyBzZWFyY2ggbmFtZXMsIHdlIHVzZSBgRFQ6OmRhdGF0YWJsZWAsIGkuZS4sIGBkYXRhdGFibGVgIGluIHRoZSBgRFRgIHBhY2thZ2UuIAoKYGBge3J9CmRhdGF0YWJsZShkZl9mMykKYGBgCgoqIFNlYXJjaCBmb3IgJ3J1c3NpYScgYW5kICdjb25nbycsIHdlIGZpbmQgdGhhdCAKCiAgLSBSdXNzaWFuIEZlZGVyYXRpb24gPSBSdXNzaWEgaW4gYHdvcmxkX21hcGAKICAtIERSIENvbmdvID0gRGVtb2NyYXRpYyBSZXB1YmxpYyBvZiB0aGUgQ29uZ28gaW4gYHdvcmxkX21hcGAKICAtIENvbmdvID0gUmVwdWJsaWMgb2YgQ29uZ28gaW4gYHdvcmxkX21hcGAKICAKKiBUaGVyZSBhcmUgYXQgbGVhc3QgdGhyZWUgd2F5cyB0byBjaGFuZ2UgdGhlIGVudHJpZXMuCgogIC0gVGhlIGZvbGxvd2luZyBpcyBhIG1ldGhvZCB0byB1c2UgQmFzZSBSLiAKCiAgICArIGBkZl9mM19yZXYkQ291bnRyeVtkZl9mM19yZXYkQ291bnRyeSA9PSAiUnVzc2lhbiBGZWRlcmF0aW9uIl0gPC0gIlJ1c3NpYSI6IElmIHRoZSBlbnRyeSBvZiB0aGUgY29sdW1uIGBDb3VudHJ5YCBpbiB0aGUgZGF0YSBmcmFtZSBgZGZfZjNfcmV2YCBtYXRjaGVzIHdpdGggIlJ1c3NpYW4gRmVkZXJhdGlvbiIsIHRoZW4gcmVwbGFjZSBpdCB3aXRoICJSdXNzaWFgLgogICAgCiAgLSBUaGUgc2Vjb25kIGlzIHRvIHVzZSBgbXV0YXRlYCBhbmQgYGNhc2Vfd2hlbmAgb2YgYHRpZHl2ZXJzZWAuCiAgCiAgLSBUaGUgdGhpcmQgaXMgdG8gdXNlIGBsZWZ0X2pvaW5gIGFmdGVyIG1ha2luZyBhIGNvbXBhcmlzb24gdGFibGUuIAoKYGBge3J9CmRmX2YzX3JldiA8LSBkZl9mMwpkZl9mM19yZXYkQ291bnRyeVtkZl9mM19yZXYkQ291bnRyeSA9PSAiUnVzc2lhbiBGZWRlcmF0aW9uIl0gPC0gIlJ1c3NpYSIKZGZfZjNfcmV2JENvdW50cnlbZGZfZjNfcmV2JENvdW50cnkgPT0gIkRSIENvbmdvIl0gPC0gIkRlbW9jcmF0aWMgUmVwdWJsaWMgb2YgdGhlIENvbmdvIgpkZl9mM19yZXYkQ291bnRyeVtkZl9mM19yZXYkQ291bnRyeSA9PSAiQ29uZ28iXSA8LSAiUmVwdWJsaWMgb2YgQ29uZ28iCmBgYAoKKiBOb3cgY2hlY2sgdGhlIGNvdW50cnkgbmFtZXMgYWdhaW4gdXNpbmcgYGFudGlfam9pbmAuIEJ5IHRoZSBjb2RlIGJlbG93LCB3ZSBjYW4gY3JlYXRlIGEgbmV3IHRhYmxlIHN1Y2ggdGhhdCB0aGVyZSBpcyBubyByZWdpb24gaW4gYHdvcmxkX21hcGAgY29ycmVzcG9uZGluZyB0byBDb3VudHJ5IGluIGBkZl9mM19yZXZgLgoKYGBge3J9CmRmX2YzX3JldiAlPiUgYW50aV9qb2luKHdvcmxkX21hcCwgYnkgPSBjKCJDb3VudHJ5IiA9ICJyZWdpb24iKSkKYGBgCgpXZSBjYW4gcHJvY2VlZCBvbmUgYnkgb25lLiBIb3dldmVyLCBXSVIgcHJvdmlkZXMgdGhlIGNvZGUgb2YgdGhpcyBwYXJ0IGluIFIuIFNvIGxldCB1cyB1c2UgaXQuIEl0IGlzIGluIENvbXB1dGVyIENvZGVzIGF0IHRoZSBNZXRob2RvbG9neSBbc2l0ZV0oaHR0cHM6Ly93aXIyMDIyLndpZC53b3JsZC9tZXRob2RvbG9neS8pLiBEb3dubG9hZCAnRnVsbCBEYXRhc2V0cycgYW5kICdDb21wdXRlciBDb2RlcycuIFRoZW4gaW4gV0lSMjAyMiAtIENvbXB1dGVyIGNvZGVzLCBmaW5kIGBDaGFwdGVyMV9NYXBzLlJgLiAKCmBgYHtyfQptYXA8LW1hcF9kYXRhKCJ3b3JsZCIpCm1hcCRyZWdpb25bbWFwJHJlZ2lvbj09IkRlbW9jcmF0aWMgUmVwdWJsaWMgb2YgdGhlIENvbmdvIl08LSJEUiBDb25nbyIKbWFwJHJlZ2lvblttYXAkcmVnaW9uPT0iUmVwdWJsaWMgb2YgQ29uZ28iXTwtIkNvbmdvIgptYXAkcmVnaW9uW21hcCRyZWdpb249PSJJdm9yeSBDb2FzdCJdPC0iQ290ZSBkSXZvaXJlIgptYXAkcmVnaW9uW21hcCRyZWdpb249PSJWaWV0bmFtIl08LSJWaWV0IE5hbSIKIyBtYXAkcmVnaW9uW21hcCRyZWdpb249PSJVbml0ZWQgQXJhYiBFbWlyYXRlcyJdPC0iVUFFIgpgYGAKClRoZSBsYXN0IG9uZSBmb3IgVUFFIHNlZW1zIHRvIGJlIHdyb25nLCBzbyBkZWxldGVkLgoKU2luY2UgdGhlIGRhdGEgdXNlZCBpbiB0aGUgbmV4dCBsaW5lIHdhcyBub3QgZmluZCwgbGV0IG1lIHVzZSBgbWFwYCBub3cuCgpgYGAKaW5kZXhfcmVnaW9uMjwtcmVhZF9kdGEoImluZGV4X3JlZ2lvbi5kdGEiKQptYXA8LWxlZnRfam9pbihtYXAsaW5kZXhfcmVnaW9uMixieT1jKCJyZWdpb24iPSJuYW1lX3JlZ2lvbiIpKQptYXAkSVNPW21hcCRyZWdpb249PSJHcmVlbmxhbmQiXTwtIkdMIgptYXAkSVNPW21hcCRyZWdpb249PSJVQUUiXTwtIkFFIgptYXAkSVNPW21hcCRyZWdpb249PSJCcnVuZWkiXTwtIkJSIiAjIGRvbmUKbWFwJElTT1ttYXAkcmVnaW9uPT0iQW50aWd1YSJdPC0iQUciCm1hcCRJU09bbWFwJHJlZ2lvbj09IkNhcGUgVmVyZGUiXTwtIkNWIgptYXAkSVNPW21hcCRyZWdpb249PSJDb3RlIGRJdm9pcmUiXTwtIkNJIgptYXAkSVNPW21hcCRyZWdpb249PSJVSyJdPC0iR0IiICMgZG9uZQptYXAkSVNPW21hcCRyZWdpb249PSJDYW5hcnkgSXNsYW5kcyJdPC0iRVMiCm1hcCRJU09bbWFwJHJlZ2lvbj09IkZyZW5jaCBHdWlhbmEiXTwtIkZSIgptYXAkSVNPW21hcCRyZWdpb249PSJTYWludCBLaXR0cyJdPC0iS04iCm1hcCRJU09bbWFwJHJlZ2lvbj09IlNvdXRoIEtvcmVhIl08LSJLUiIKbWFwJElTT1ttYXAkcmVnaW9uPT0iU2FpbnQgTWFydGluIl08LSJNRiIKbWFwJElTT1ttYXAkcmVnaW9uPT0iTWFjZWRvbmlhIl08LSJNSyIKbWFwJElTT1ttYXAkcmVnaW9uPT0iUnVzc2lhIl08LSJSVSIgIyBkb25lCm1hcCRJU09bbWFwJHJlZ2lvbj09IkJvbmFpcmUiXTwtIkJRIgptYXAkSVNPW21hcCRyZWdpb249PSJTaW50IEV1c3RhdGl1cyJdPC0iQlEiCm1hcCRJU09bbWFwJHJlZ2lvbj09IlNhYmEiXTwtIkJRIgptYXAkSVNPW21hcCRyZWdpb249PSJMYW9zIl08LSJMQSIKbWFwJElTT1ttYXAkcmVnaW9uPT0iU2ludCBNYWFydGVuIl08LSJTWCIKbWFwJElTT1ttYXAkcmVnaW9uPT0iU3lyaWEiXTwtIlNZIgptYXAkSVNPW21hcCRyZWdpb249PSJUcmluaWRhZCJdPC0iVFQiCm1hcCRJU09bbWFwJHJlZ2lvbj09IlRvYmFnbyJdPC0iVFQiCm1hcCRJU09bbWFwJHJlZ2lvbj09IlZpcmdpbiBJc2xhbmRzIl08LSJWSSIKbWFwJElTT1ttYXAkcmVnaW9uPT0iU2FpbnQgVmluY2VudCJdPC0iVkMiCm1hcCRJU09bbWFwJHJlZ2lvbj09IkdyZW5hZGluZXMiXTwtIlZDIgptYXAkSVNPW21hcCRyZWdpb249PSJGcmVuY2ggU291dGhlcm4gYW5kIEFudGFyY3RpYyBMYW5kcyJdPC0iRlIiCm1hcCRJU09bbWFwJHJlZ2lvbj09Ildlc3Rlcm4gU2FoYXJhIl08LSJXUyIKYGBgCmBgYHtyfQptYXAkcmVnaW9uW21hcCRyZWdpb249PSJSdXNzaWEiXTwtIlJ1c3NpYW4gRmVkZXJhdGlvbiIKbWFwJHJlZ2lvblttYXAkcmVnaW9uPT0iU291dGggS29yZWEiXTwtIktvcmVhIgptYXAkcmVnaW9uW21hcCRyZWdpb249PSJVSyJdPC0iVW5pdGVkIEtpbmdkb20iCm1hcCRyZWdpb25bbWFwJHJlZ2lvbj09IkJydW5laSJdPC0iQnJ1bmVpIERhcnVzc2FsYW0iCm1hcCRyZWdpb25bbWFwJHJlZ2lvbj09Ikxhb3MiXTwtIkxhbyBQRFIiCm1hcCRyZWdpb25bbWFwJHJlZ2lvbj09IkNvdGUgZEl2b2lyZSJdPC0iQ290ZSBkJ0l2b2lyZSIKbWFwJHJlZ2lvblttYXAkcmVnaW9uPT0iQ2FwZSBWZXJkZSJdPC0gIkNhYm8gVmVyZGUiCm1hcCRyZWdpb25bbWFwJHJlZ2lvbj09IlN5cmlhIl08LSAiU3lyaWFuIEFyYWIgUmVwdWJsaWMiCm1hcCRyZWdpb25bbWFwJHJlZ2lvbj09IlRyaW5pZGFkIl08LSAiVHJpbmlkYWQgYW5kIFRvYmFnbyIKbWFwJHJlZ2lvblttYXAkcmVnaW9uPT0iVG9iYWdvIl08LSAiVHJpbmlkYWQgYW5kIFRvYmFnbyIKYGBgCgpgYGB7cn0KZGZfZjMgJT4lIGFudGlfam9pbihtYXAsIGJ5ID0gYygiQ291bnRyeSIgPSAicmVnaW9uIikpCmBgYAoKKiBJcyBaYW56aWJhciBhIHBhcnQgb2YgVGFuemFuaWE/CgpgYGB7cn0KZGZfZjMgJT4lIAogIGdncGxvdChhZXMobWFwX2lkID0gQ291bnRyeSkpICsgCiAgZ2VvbV9tYXAoYWVzKGZpbGwgPSBgVDEwQjUwYCksIG1hcCA9IG1hcCkgKwogIGV4cGFuZF9saW1pdHMoeCA9IG1hcCRsb25nLCB5ID0gbWFwJGxhdCkKYGBgCgoKIyMjIyMgU3RlcCAzLgoKKiBOZXh0IHdlIGFkZCBhIG5ldyBjb2x1bW4gYFRvcCAxMCBCb3R0b20gNTAgUmF0aW9gIGJ5IHNldHRpbmcgbmV3IGJyZWFrcyBvZiBgVDEwQjUwYC4KKiBQbGFjZSB0aGUgbGVnZW5kIGF0IHRoZSBib3R0b20gdXNpbmcgYHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIilgLgoKYGBge3J9CmRmX2YzX3JldiAlPiUgCiAgbXV0YXRlKGBUb3AgMTAgQm90dG9tIDUwIFJhdGlvYCA9IGN1dChUMTBCNTAsIGJyZWFrcyA9IGMoNSwgMTIsIDEzLCAxNiwgMTksIDE0MCksIGluY2x1ZGUubG93ZXN0ID0gRkFMU0UpKSAlPiUKICBnZ3Bsb3QoYWVzKG1hcF9pZCA9IENvdW50cnkpKSArIGdlb21fbWFwKGFlcyhmaWxsID0gYFRvcCAxMCBCb3R0b20gNTAgUmF0aW9gKSwgbWFwID0gd29ybGRfbWFwKSArIGV4cGFuZF9saW1pdHMoeCA9IHdvcmxkX21hcCRsb25nLCB5ID0gd29ybGRfbWFwJGxhdCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0iYm90dG9tIikKYGBgCgojIyMjIyBTdGVwIDQuCgpGaW5hbGx5IGFkZCB0aGUgdGl0bGUsIHJlbW92ZSB4IGFuZCB5IGxhYmVscywgYW5kIGNoYW5nZSB0aGUgbGVnZW5kIG5hbWUuCgpgYGB7cn0KZGZfZjNfcmV2ICU+JSAKICBtdXRhdGUoYFRvcCAxMCBCb3R0b20gNTAgUmF0aW9gID0gY3V0KFQxMEI1MCwgYnJlYWtzID0gYyg1LCAxMiwgMTMsIDE2LCAxOSwgMTQwKSwgaW5jbHVkZS5sb3dlc3QgPSBGQUxTRSkpICU+JQogIGdncGxvdChhZXMobWFwX2lkID0gQ291bnRyeSkpICsgZ2VvbV9tYXAoYWVzKGZpbGwgPSBgVG9wIDEwIEJvdHRvbSA1MCBSYXRpb2ApLCBtYXAgPSB3b3JsZF9tYXApICsgZXhwYW5kX2xpbWl0cyh4ID0gd29ybGRfbWFwJGxvbmcsIHkgPSB3b3JsZF9tYXAkbGF0KSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMy4gVG9wIDEwL0JvdHRvbSA1MCBpbmNvbWUgZ2FwcyBhY3Jvc3MgdGhlIHdvcmxkLCAyMDIxIiwKICAgICAgIHggPSAiIiwgeSA9ICIiLCBmaWxsID0gIlRvcCAxMC9Cb3R0b20gNTAgcmF0aW8iKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKQpgYGAKCiMjIyMjIFN0ZXAgNS4KClJlbW92ZSB4LWF4aXMsIHktYXhpcyBhbmQgdGlja3MuIElmIHlvdSB3YW50IHRvIGNoYW5nZSBjb2xvciBwYWxldHRlLCBzZWU6CgoqIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9zY2FsZV9icmV3ZXIuaHRtbAoqIGh0dHA6Ly93d3cuY29va2Jvb2stci5jb20vR3JhcGhzL0NvbG9yc18oZ2dwbG90MikvCgpgYGB7cn0KZGZfZjNfcmV2ICU+JSAKICBtdXRhdGUoYFRvcCAxMCBCb3R0b20gNTAgUmF0aW9gID0gY3V0KFQxMEI1MCwgYnJlYWtzID0gYyg1LCAxMiwgMTMsIDE2LCAxOSwgMTQwKSwgaW5jbHVkZS5sb3dlc3QgPSBGQUxTRSkpICU+JQogIGdncGxvdChhZXMobWFwX2lkID0gQ291bnRyeSkpICsgZ2VvbV9tYXAoYWVzKGZpbGwgPSBgVG9wIDEwIEJvdHRvbSA1MCBSYXRpb2ApLCBtYXAgPSB3b3JsZF9tYXApICsgZXhwYW5kX2xpbWl0cyh4ID0gd29ybGRfbWFwJGxvbmcsIHkgPSB3b3JsZF9tYXAkbGF0KSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMy4gVG9wIDEwL0JvdHRvbSA1MCBpbmNvbWUgZ2FwcyBhY3Jvc3MgdGhlIHdvcmxkLCAyMDIxIiwKICAgICAgIHggPSAiIiwgeSA9ICIiLCBmaWxsID0gIlRvcCAxMC9Cb3R0b20gNTAgcmF0aW8iKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iLCAKICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpY2tzLnk9ZWxlbWVudF9ibGFuaygpKSArCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZT0nWWxPclJkJykKYGBgCgoKCgoKCiMjIyBGNDogVGhlIGV4dHJlbWUgY29uY2VudHJhdGlvbiBvZiBjYXBpdGFsOiB3ZWFsdGggaW5lcXVhbGl0eSBhY3Jvc3MgdGhlIHdvcmxkLCAyMDIxCgpgYGB7ciBkYXRhLWY0LCBjYXNoID0gVFJVRX0KZGZfZjQgPC0gcmVhZF9leGNlbCgiLi9kYXRhL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeCIsIHNoZWV0ID0gImRhdGEtRjQiKQpkZl9mNApgYGAKCgpgYGB7cn0KZGZfZjQgJT4lIHBpdm90X2xvbmdlcigzOjUsIG5hbWVzX3RvID0gImxldmVsIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gaXNvLCB5ID0gdmFsdWUsIGZpbGwgPSBsZXZlbCkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBmdW5jdGlvbih4KSBzdHJpbmdyOjpzdHJfd3JhcCh4LCB3aWR0aCA9IDEwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSA0LiBUaGUgZXh0cmVtZSBjb25jZW50cmF0aW9uIG9mIGNhcGl0YWw6IFxud2VhbHRoIGluZXF1YWxpdHkgYWNyb3NzIHRoZSB3b3JsZCwgMjAyMSIsCiAgICAgICB4ID0gIiIsIHkgPSAiU2hhcmUgb2YgbmF0aW9uYWwgd2VhbHRoICglKSIsIGZpbGwgPSAiIikKYGBgCioqSW50ZXJwcmV0YXRpb24qKjogIFRoZSBUb3AgMTAlIGluIExhdGluIEFtZXJpY2EgY2FwdHVyZXMgNzclIG9mIHRvdGFsIGhvdXNlaG9sZCB3ZWFsdGgsIHZlcnN1cyAyMiUgZm9yIHRoZSBNaWRkbGUgNDAlIGFuZCAxJSBmb3IgdGhlIEJvdHRvbSA1MCUuIEluIEV1cm9wZSwgdGhlIFRvcCAxMCUgb3ducyA1OCUgb2YgdG90YWwgd2VhbHRoLCB2ZXJzdXMgMzglIGZvciB0aGUgTWlkZGxlIDQwJSBhbmQgNCUgZm9yIHRoZSBCb3R0b20gNTAlLiAgIAoqKlNvdXJjZXMgYW5kIHNlcmllcyoqOiB3aXIyMDIyLndpZC53b3JsZC9tZXRob2RvbG9neS4KCiMjIyMgRXhwbGFuYXRpb24KCiogQWxtb3N0IHRoZSBzYW1lIGFzIEYxIGFuZCBGMi4KCiogV3JhcCBsb25nIGxhYmVsOiBgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBmdW5jdGlvbih4KSBzdHJpbmdyOjpzdHJfd3JhcCh4LCB3aWR0aCA9IDEwKSlgCiogUGVyIENlbnQ6IGBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKWAKCiMjIyBGNTogR2xvYmFsIGluY29tZSBpbmVxdWFsaXR5OiBUMTAvQjUwIHJhdGlvLCAxODIwLTIwMjAKCmBgYHtyIGRhdGEtZjUsIGNhc2ggPSBUUlVFfQpkZl9mNSA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtU3VtbWFyeS54bHN4Iiwgc2hlZXQgPSAiZGF0YS1GNSIpCmRmX2Y1CmBgYAoKYGBge3J9CmRmX2Y1ICU+JSBzZWxlY3QoeWVhciA9IHksIHJhdGlvID0gdDEwYjUwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gcmF0aW8pKSArIAogIGxpbXMoeSA9IGMoMTAsNzApKSArIAogIGdlb21fc21vb3RoKGZvcm11bGEgPSB5fngsIG1ldGhvZCA9ICJsb2VzcyIsIHNwYW4gPSAwLjI1LCBzZSA9IEZBTFNFKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSByb3VuZChzZXEoMTgyMCwgMjAyMCwgYnkgPSAyMCksMSkpICsgCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgNS4gR2xvYmFsIGluY29tZSBpbmVxdWFsaXR5OlQxMC9CNTAgcmF0aW8sIDE4MjAtMjAyMCIsIAogICAgICAgeCA9ICIiLCB5ID0gc3RyaW5ncjo6c3RyX3dyYXAoIlJhdGlvIG9mIHRvcCAxMCUgYXZlcmFnZSBpbmNvbWUgdG8gYm90dG9tIDUwJSBhdmVyYWdlIGluY29tZSIsIHdpZHRoID0gMzUpKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTg0MCwgeSA9IDMyLCBsYWJlbCA9IHN0cmluZ3I6OnN0cl93cmFwKCIxODIwOiBhdmVyYWdlIGluY29tZSBvZiB0aGUgZ2xvYmFsIHRvcCAxMCUgaXMgMTh4IGhpZ2hlciB0aGFuIGF2ZXJhZ2UgaW5jb21lIG9mIHRoZSBib3R0b20gNTAlIiwgd2lkdGggPSAyMCksIHNpemUgPSAzKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE5MTAsIHkgPSA0OSwgbGFiZWwgPSBzdHJpbmdyOjpzdHJfd3JhcCgiMTkxMDogYXZlcmFnZSBpbmNvbWUgb2YgdGhlIGdsb2JhbCB0b3AgMTAlIGlzIDQxeCBoaWdoZXIgdGhhbiBhdmVyYWdlIGluY29tZSBvZiB0aGUgYm90dG9tIDUwJSIsIHdpZHRoID0gMjApLCBzaXplID0gMykgKwogICAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTk4MCwgeSA9IDYwLCBsYWJlbCA9IHN0cmluZ3I6OnN0cl93cmFwKCIxOTgwOiBhdmVyYWdlIGluY29tZSBvZiB0aGUgZ2xvYmFsIHRvcCAxMCUgaXMgNTN4IGhpZ2hlciB0aGFuIGF2ZXJhZ2UgaW5jb21lIG9mIHRoZSBib3R0b20gNTAlIiwgd2lkdGggPSAyMCksIHNpemUgPSAzKSArCiAgICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyMDEwLCB5ID0gMzIsIGxhYmVsID0gc3RyaW5ncjo6c3RyX3dyYXAoIjIwMjA6IGF2ZXJhZ2UgaW5jb21lIG9mIHRoZSBnbG9iYWwgdG9wIDEwJSBpcyAzOHggaGlnaGVyIHRoYW4gYXZlcmFnZSBpbmNvbWUgb2YgdGhlIGJvdHRvbSA1MCUiLCB3aWR0aCA9IDIwKSwgc2l6ZSA9IDMpCmBgYAoqKkludGVycHJldGF0aW9uKiouIEdsb2JhbCBpbmVxdWFsaXR5LCBhcyBtZWFzdXJlZCBieSB0aGUgcmF0aW8gVDEwL0I1MCBiZXR3ZWVuIHRoZSBhdmVyYWdlIGluY29tZSBvZiB0aGUgdG9wIDEwJSBhbmQgdGhlIGF2ZXJhZ2UgaW5jb21lIG9mIHRoZSBib3R0b20gNTAlLCBtb3JlIHRoYW4gZG91YmxlZCBiZXR3ZWVuIGJldHdlZW4gMTgyMCBhbmQgMTkxMCwgZnJvbSBsZXNzIHRoYW4gMjAgdG8gYWJvdXQgNDAsIGFuZCBzdGFiaWxpemVkIGFyb3VuZCA0MCBiZXR3ZWVuIDE5MTAgYW5kIDIwMjAuIEl0IGlzIHRvbyBlYXJseSB0byBzYXkgd2hldGhlciB0aGUgZGVjbGluZSBpbiBnbG9iYWwgaW5lcXVhbGl0eSBvYnNlcnZlZCBzaW5jZSAyMDA4IHdpbGwgY29udGludWUuIEluY29tZSBpcyBtZWFzdXJlZCBwZXIgY2FwaXRhIGFmdGVyIHBlbnNpb24gYW5kIHVuZW1wbG95ZW1lbnQgaW5zdXJhbmNlIHRyYW5zZmVycyBhbmQgYmVmb3JlIGluY29tZSBhbmQgd2VhbHRoIHRheGVzLiAgIAoqKlNvdXJjZXMgYW5kIHNlcmllcyoqOiB3aXIyMDIyLndpZC53b3JsZC9sbWV0aG9kb2xvZ3kgYW5kIENoYW5jZWwgYW5kIFBpa2V0dHkgKDIwMjEpLi4KCiMjIyMgRXhwbGFuYXRpb24KCiMjIyMjIFN0ZXAgMS4KCiogVGhlIGZvbGxvd2luZyBpcyBlbm91Z2guIEhlcmUgd2UgYXBwbGllZCBgc3RyX3dyYXBgIHRvIHRoZSBsYWJlbCBvZiB0aGUgeS1heGlzIGFzIGl0IGlzIHZlcnkgbG9uZy4KCmBgYHtyfQpkZl9mNSAlPiUgc2VsZWN0KHllYXIgPSB5LCByYXRpbyA9IHQxMGI1MCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHJhdGlvKSkgKyAKICBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgNS4gR2xvYmFsIGluY29tZSBpbmVxdWFsaXR5OlQxMC9CNTAgcmF0aW8sIDE4MjAtMjAyMCIsIAogICAgICAgeCA9ICIiLCB5ID0gc3RyaW5ncjo6c3RyX3dyYXAoIlJhdGlvIG9mIHRvcCAxMCUgYXZlcmFnZSBpbmNvbWUgdG8gYm90dG9tIDUwJSBhdmVyYWdlIGluY29tZSIsIHdpZHRoID0gMzUpKQpgYGAKCiMjIyMjIFN0ZXAgMi4KClRoZXJlIGFyZSBtYW55IHdheSBvZiBzbW9vdGhpbmcuCgoKKipMaW5lIFBsb3QgYW5kIExPRVNTKioKCiogVGhlIGRlZmF1bHQgaXMgImxvZXNzIiwgYW5kIGBzZSA9IFRSVUVgIHdoaWNoIGluY2x1ZGUgdGhlIHN0YW5kYXJkIGVycm9yLgoqIFVubGVzcyB5b3UgY2xlYXJseSB1bmRlcnN0YW5kIHRoZW0sIGl0IGlzIGJldHRlciB0byB1c2UgYGZvcm11bGEgPSB5fnhgLCBgbWV0aG9kID0gImxvZXNzIiwgIGFuZCBgc2UgPSBGQUxTRWAuCiogV2UgdHJ5IG90aGVyIG1ldGhvZHMgYmVsb3cuCgpgYGB7cn0KZGZfZjUgJT4lIHNlbGVjdCh5ZWFyID0geSwgcmF0aW8gPSB0MTBiNTApICU+JQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSByYXRpbykpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9zbW9vdGgoZm9ybXVsYSA9IHl+eCwgbWV0aG9kID0gImxvZXNzIiwgc2UgPSBGQUxTRSkgKyAKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSA1LiBHbG9iYWwgaW5jb21lIGluZXF1YWxpdHk6IiwgCiAgICAgICBzdWJ0aXRsZSA9ICJUMTAvQjUwIHJhdGlvLCAxODIwLTIwMjAiLAogICAgICAgeCA9ICIiLCB5ID0gIlJhdGlvIG9mIHRvcCAxMCUgYXZlcmFnZSBpbmNvbWUgdG8gYm90dG9tIDUwJSBhdmVyYWdlIGluY29tZSIpCmBgYAoKKipHQU0gU21vb3RoaW5nIHdpdGggMjQgUG9pbnRzKioKCmBgYHtyfQpkZl9mNSAlPiUgc2VsZWN0KHllYXIgPSB5LCByYXRpbyA9IHQxMGI1MCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHJhdGlvKSkgKwogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJnYW0iLCBmb3JtdWxhID0geSB+IHMoeCwgayA9IDI0KSwgc2UgPSBGQUxTRSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcm91bmQoc2VxKG1pbihkZl9mNSR5KSwgbWF4KGRmX2Y1JHkpLCBieSA9IDIwKSwxKSkgKyAKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSA1LiBHbG9iYWwgaW5jb21lIGluZXF1YWxpdHk6VDEwL0I1MCByYXRpbywgMTgyMC0yMDIwIiwgCiAgICAgICB4ID0gIiIsIHkgPSBzdHJpbmdyOjpzdHJfd3JhcCgiUmF0aW8gb2YgdG9wIDEwJSBhdmVyYWdlIGluY29tZSB0byBib3R0b20gNTAlIGF2ZXJhZ2UgaW5jb21lIiwgd2lkdGggPSAzNSkpCmBgYAoKKipQb2x5bm9taWFsIEFwcHJveGltYXRpb24gb2YgRGVncmVlIDYqKgoKYGBge3J9CmRmX2Y1ICU+JSBzZWxlY3QoeWVhciA9IHksIHJhdGlvID0gdDEwYjUwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gcmF0aW8pKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBmb3JtdWxhID0geSB+IHBvbHkoeCwgNiksIHNlID0gRkFMU0UpICsgCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgNS4gR2xvYmFsIGluY29tZSBpbmVxdWFsaXR5OiIsIAogICAgICAgc3VidGl0bGUgPSAiVDEwL0I1MCByYXRpbywgMTgyMC0yMDIwIiwKICAgICAgIHggPSAiIiwgeSA9IHN0cmluZ3I6OnN0cl93cmFwKCJSYXRpbyBvZiB0b3AgMTAlIGF2ZXJhZ2UgaW5jb21lIHRvIGJvdHRvbSA1MCUgYXZlcmFnZSBpbmNvbWUiLCB3aWR0aCA9IDM1KSkKYGBgCgojIyMjIyBTdGVwIDMuCgoqIEluIHRoZSBtYWluIGNoYXJ0IGZvciBGNSwgd2UgYXBwbGllZCBgZ2VvbV9zbW9vdGgoZm9ybXVsYSA9IHl+eCwgbWV0aG9kID0gImxvZXNzIiwgc3BhbiA9IDAuMjUsIHNlID0gRkFMU0UpYCBhcyBpdCBpcyBlYXN5LiBZb3UgY2FuIGFkanVzdCBzbW9vdGhuZXNzIGJ5IGNoYW5naW5nIHRoZSB2YWx1ZSBmb3IgYHNwYW5gLgoKKiBGb3IgdGhlIHktYXhpcywgZm9sbG93aW5nIHRoZSBvdXRwdXQgcHJvdmlkZWQsIGBsaW1zKHkgPSBjKDEwLDcwKSlgIGlzIGFkZGVkIGFuZCBhbm5vdGF0aW9uLgoKKiBGb3IgYSBsb25nIHRleHQgdXNlOiBgc3RyaW5ncjo6c3RyX3dyYXAoImxvbmcgdGV4dCIsIHdpZHRoID0gc2l6ZSlgIGFuZCBgYW5ub3RhdGVgIHdpdGggYHNpemUgPSBmb250c2l6ZWAuCgoqIGBnZ2ZvcmNlOjpnZW9tX21hcmtfcmVjdGAgd2lsbCBhZGQgYW5ub3RhdGlvbiBpbiBhIGJveC4KCmBgYHtyfQpkZl9mNSAlPiUgc2VsZWN0KHllYXIgPSB5LCByYXRpbyA9IHQxMGI1MCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHJhdGlvKSkgKyAKICBsaW1zKHkgPSBjKDEwLDcwKSkgKyAKICBnZW9tX3Ntb290aChmb3JtdWxhID0geX54LCBtZXRob2QgPSAibG9lc3MiLCBzcGFuID0gMC4yNSwgc2UgPSBGQUxTRSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcm91bmQoc2VxKDE4MjAsIDIwMjAsIGJ5ID0gMjApLDEpKSArIAogIGxhYnModGl0bGUgPSAiRmlndXJlIDUuIEdsb2JhbCBpbmNvbWUgaW5lcXVhbGl0eTpUMTAvQjUwIHJhdGlvLCAxODIwLTIwMjAiLCAKICAgICAgIHggPSAiIiwgeSA9IHN0cmluZ3I6OnN0cl93cmFwKCJSYXRpbyBvZiB0b3AgMTAlIGF2ZXJhZ2UgaW5jb21lIHRvIGJvdHRvbSA1MCUgYXZlcmFnZSBpbmNvbWUiLCB3aWR0aCA9IDM1KSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE4NDAsIHkgPSAzMiwgbGFiZWwgPSBzdHJpbmdyOjpzdHJfd3JhcCgiMTgyMDogYXZlcmFnZSBpbmNvbWUgb2YgdGhlIGdsb2JhbCB0b3AgMTAlIGlzIDE4eCBoaWdoZXIgdGhhbiBhdmVyYWdlIGluY29tZSBvZiB0aGUgYm90dG9tIDUwJSIsIHdpZHRoID0gMjApLCBzaXplID0gMykgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxOTEwLCB5ID0gNDksIGxhYmVsID0gc3RyaW5ncjo6c3RyX3dyYXAoIjE5MTA6IGF2ZXJhZ2UgaW5jb21lIG9mIHRoZSBnbG9iYWwgdG9wIDEwJSBpcyA0MXggaGlnaGVyIHRoYW4gYXZlcmFnZSBpbmNvbWUgb2YgdGhlIGJvdHRvbSA1MCUiLCB3aWR0aCA9IDIwKSwgc2l6ZSA9IDMpICsKICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE5ODAsIHkgPSA2MCwgbGFiZWwgPSBzdHJpbmdyOjpzdHJfd3JhcCgiMTk4MDogYXZlcmFnZSBpbmNvbWUgb2YgdGhlIGdsb2JhbCB0b3AgMTAlIGlzIDUzeCBoaWdoZXIgdGhhbiBhdmVyYWdlIGluY29tZSBvZiB0aGUgYm90dG9tIDUwJSIsIHdpZHRoID0gMjApLCBzaXplID0gMykgKwogICAgYW5ub3RhdGUoInRleHQiLCB4ID0gMjAxMCwgeSA9IDMyLCBsYWJlbCA9IHN0cmluZ3I6OnN0cl93cmFwKCIyMDIwOiBhdmVyYWdlIGluY29tZSBvZiB0aGUgZ2xvYmFsIHRvcCAxMCUgaXMgMzh4IGhpZ2hlciB0aGFuIGF2ZXJhZ2UgaW5jb21lIG9mIHRoZSBib3R0b20gNTAlIiwgd2lkdGggPSAyMCksIHNpemUgPSAzKQpgYGAKCiMjIyBGNjogR2xvYmFsIGluY29tZSBpbmVxdWFsaXR5OiBCZXR3ZWVuIHZzLiBXaXRoaW4gY291bnRyeSBpbmVxdWFsaXR5IChUaGVpbCBpbmRleCksIDE4MjAtMjAyMAoKYGBge3IgZGF0YS1mNiwgY2FzaCA9IFRSVUV9CmRmX2Y2IDwtIHJlYWRfZXhjZWwoIi4vZGF0YS9XSVIyMDIyVGFibGVzRmlndXJlcy1TdW1tYXJ5Lnhsc3giLCBzaGVldCA9ICJkYXRhLUY2IikKZGZfZjYKYGBgCgoKYGBge3J9CmRmX2Y2ICU+JSBzZWxlY3QoeWVhciA9ICIuLi4xIiwgMjozKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IDI6MywgbmFtZXNfdG8gPSAidHlwZSIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIG11dGF0ZSh0eXBlcyA9IGZhY3Rvcih0eXBlLCBsZXZlbHMgPSBjKCJXaXRoaW4tY291bnRyeSBpbmVxdWFsaXR5IiwgIkJldHdlZW4tY291bnRyeSBpbmVxdWFsaXR5IikpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUsIGZpbGwgPSB0eXBlcykpICsKICBnZW9tX2FyZWEoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSByb3VuZChzZXEoMTgyMCwgMjAyMCwgYnkgPSAyMCksMSkpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPXJldihzY2FsZXM6Omh1ZV9wYWwoKSgyKSksIGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cl93cmFwKHgsIHdpZHRoID0gMTUpKSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgNi4gR2xvYmFsIGluY29tZSBpbmVxdWFsaXR5OiBcbkJldHdlZW4gdnMuIHdpdGhpbiBjb3VudHJ5IGluZXF1YWxpdHkgKFRoZWlsIGluZGV4KSwgMTgyMC0yMDIwIiwKICAgICAgIHggPSAiIiwgeSA9ICJTaGFyZSBvZiBnbG9iYWwgaW5lcXVhbGl0eSAoJSBvZiB0b3RhbCBUaGVpbCBpbmRleCkiLCBmaWxsID0gIiIpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTg1MCwgeSA9IDAuMjgsIGxhYmVsID0gc3RyaW5ncjo6c3RyX3dyYXAoIjE4MjA6IEJldHdlZW4gY291bnRyeSBpbmVxdWFsaXR5IHJlcHJlc2VudHMgMTElIG9mIGdsb2JhbCBpbmVxdWFsaXR5Iiwgd2lkdGggPSAyMCksIHNpemUgPSAzKSArIAogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE5ODAsIHkgPSAwLjcwLCBsYWJlbCA9IHN0cmluZ3I6OnN0cl93cmFwKCIxOTgwOiBCZXR3ZWVuIGNvdW50cnkgaW5lcXVhbGl0eSByZXByZXNlbnRzIDU3JSBvZiBnbG9iYWwgaW5lcXVhbGl0eSIsIHdpZHRoID0gMjApLCBzaXplID0gMykgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE5OTAsIHkgPSAwLjMwLCBsYWJlbCA9IHN0cmluZ3I6OnN0cl93cmFwKCIyMDIwOiBCZXR3ZWVuIGNvdW50cnkgaW5lcXVhbGl0eSByZXByZXNlbnRzIDMyJSBvZiBnbG9iYWwgaW5lcXVhbGl0eSIsIHdpZHRoID0gMjApLCBzaXplID0gMykKYGBgCgoqIExlZ2VuZCBjYW4gYmUgcGxhY2VkIGF0IHRoZSBib3R0b206IGB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpYAoKYGBge3J9CmRmX2Y2ICU+JSBzZWxlY3QoeWVhciA9ICIuLi4xIiwgMjozKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IDI6MywgbmFtZXNfdG8gPSAidHlwZSIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIG11dGF0ZSh0eXBlcyA9IGZhY3Rvcih0eXBlLCBsZXZlbHMgPSBjKCJXaXRoaW4tY291bnRyeSBpbmVxdWFsaXR5IiwgIkJldHdlZW4tY291bnRyeSBpbmVxdWFsaXR5IikpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUsIGZpbGwgPSB0eXBlcykpICsKICBnZW9tX2FyZWEoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSByb3VuZChzZXEoMTgyMCwgMjAyMCwgYnkgPSAyMCksMSkpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPXJldihzY2FsZXM6Omh1ZV9wYWwoKSgyKSkpICsKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSA2LiBHbG9iYWwgaW5jb21lIGluZXF1YWxpdHk6IFxuQmV0d2VlbiB2cy4gd2l0aGluIGNvdW50cnkgaW5lcXVhbGl0eSAoVGhlaWwgaW5kZXgpLCAxODIwLTIwMjAiLAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIGdsb2JhbCBpbmVxdWFsaXR5ICglIG9mIHRvdGFsIFRoZWlsIGluZGV4KSIsIGZpbGwgPSAiIikgKyAKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxODUwLCB5ID0gMC4yOCwgbGFiZWwgPSBzdHJpbmdyOjpzdHJfd3JhcCgiMTgyMDogQmV0d2VlbiBjb3VudHJ5IGluZXF1YWxpdHkgcmVwcmVzZW50cyAxMSUgb2YgZ2xvYmFsIGluZXF1YWxpdHkiLCB3aWR0aCA9IDIwKSwgc2l6ZSA9IDMpICsgCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMTk4MCwgeSA9IDAuNzAsIGxhYmVsID0gc3RyaW5ncjo6c3RyX3dyYXAoIjE5ODA6IEJldHdlZW4gY291bnRyeSBpbmVxdWFsaXR5IHJlcHJlc2VudHMgNTclIG9mIGdsb2JhbCBpbmVxdWFsaXR5Iiwgd2lkdGggPSAyMCksIHNpemUgPSAzKSArCiAgICBhbm5vdGF0ZSgidGV4dCIsIHggPSAxOTkwLCB5ID0gMC4zMCwgbGFiZWwgPSBzdHJpbmdyOjpzdHJfd3JhcCgiMjAyMDogQmV0d2VlbiBjb3VudHJ5IGluZXF1YWxpdHkgcmVwcmVzZW50cyAzMiUgb2YgZ2xvYmFsIGluZXF1YWxpdHkiLCB3aWR0aCA9IDIwKSwgc2l6ZSA9IDMpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpCmBgYAoqKkludGVycHJldGF0aW9uKiouIFRoZSBpbXBvcnRhbmNlIG9mIGJldHdlZW4tY291bnRyeSBpbmVxdWFsaXR5IGluIG92ZXJhbGwgZ2xvYmFsIGluZXF1YWxpdHksIGFzIG1lYXN1cmVkIGJ5IHRoZSBUaGVpbCBpbmRleCwgcm9zZSBiZXR3ZWVuIDE4MjAgYW5kIDE5ODAgYW5kIHN0cm9uZ2x5IGRlY2xpbmVkIHNpbmNlIHRoZW4uIEluIDIwMjAsIGJldHdlZW4tY291bnRyeSBpbmVxdWFsaXR5IG1ha2VzLXVwIGFib3V0IGEgdGhpcmQgb2YgZ2xvYmFsIGluZXF1YWxpdHkgYmV0d2VlbiBpbmRpdmlkdWFscy4gVGhlIHJlc3QgaXMgZHVlIHRvIGluZXF1YWxpdHkgd2l0aGluIGNvdW50cmllcy4gSW5jb21lIGlzIG1lYXN1cmVkIHBlciBjYXBpdGEgYWZ0ZXIgcGVuc2lvbiBhbmQgdW5lbXBsb3llbWVudCBpbnN1cmFuY2UgdHJhbnNmZXJzIGFuZCBiZWZvcmUgaW5jb21lIGFuZCB3ZWFsdGggdGF4ZXMuICAgCioqU291cmNlcyBhbmQgc2VyaWVzKio6IHdpcjIwMjIud2lkLndvcmxkL21ldGhvZG9sb2d5IGFuZCBDaGFuY2VsIGFuZCBQaWtldHR5ICgyMDIxKS4KCiMjIyMgRXhwbGFuYXRpb24KCiMjIyMjIFN0ZXAgMS4KCiogV2UgdXNlIGBnZW9tX2FyZWFgIGFmdGVyIHRpZHlpbmcgdGhlIGRhdGEgd2l0aCBgcGlsb3RfbG9uZ2VyYC4KCmBgYHtyfQpkZl9mNiAlPiUgc2VsZWN0KHllYXIgPSAiLi4uMSIsIDI6MykgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAyOjMsIG5hbWVzX3RvID0gInR5cGUiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUsIGZpbGwgPSB0eXBlKSkgKwogIGdlb21fYXJlYSgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgNi4gR2xvYmFsIGluY29tZSBpbmVxdWFsaXR5OiBcbkJldHdlZW4gdnMuIHdpdGhpbiBjb3VudHJ5IGluZXF1YWxpdHkgKFRoZWlsIGluZGV4KSwgMTgyMC0yMDIwIiwKICAgICAgIHggPSAiIiwgeSA9ICJTaGFyZSBvZiBnbG9iYWwgaW5lcXVhbGl0eSAoJSBvZiB0b3RhbCBUaGVpbCBpbmRleCkiKQpgYGAKCiMjIyMjIFN0ZXAgMi4KCiogU2luY2UgdGhlIG9yZGVyIG9mIHRoZSB0d28gZ3JvdXBzIGFyZSBkaWZmZXJlbnQsIHRoZSBmb2xsb3dpbmcgbGludyBpcyBhZGRlZC4KYGBgCnNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1yZXYoc2NhbGVzOjpodWVfcGFsKCkoMikpLCBsYWJlbHMgPSBmdW5jdGlvbih4KSBzdHJfd3JhcCh4LCB3aWR0aCA9IDE1KSkKYGBgCgoqIFRoZSBzZWNvbmQgb3B0aW9uIGlzIHRvIGNvbnRyb2wgdGhlIGxlZ2VuZCB0byB3cmFwLgoKKiBBbm5vdGF0aW9uIGNhbiBiZSBvbWl0dGVkIGlmIHdlIHVzZSBSTWFya2Rvd24gdG8gZXhwbGFpbiB0aGUgY2hhcnRzIGNsZWFybHkuCgoqIEFkZCBhIGxpbmUgYnJlYWsgaW4gdGhlIHktYXhpcyBsYWJlbC4KCmBgYHtyfQpkZl9mNiAlPiUgc2VsZWN0KHllYXIgPSAiLi4uMSIsIDI6MykgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAyOjMsIG5hbWVzX3RvID0gInR5cGUiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBtdXRhdGUodHlwZXMgPSBmYWN0b3IodHlwZSwgbGV2ZWxzID0gYygiV2l0aGluLWNvdW50cnkgaW5lcXVhbGl0eSIsICJCZXR3ZWVuLWNvdW50cnkgaW5lcXVhbGl0eSIpKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHZhbHVlLCBmaWxsID0gdHlwZXMpKSArCiAgZ2VvbV9hcmVhKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcm91bmQoc2VxKDE4MjAsIDIwMjAsIGJ5ID0gMjApLDEpKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1yZXYoc2NhbGVzOjpodWVfcGFsKCkoMikpLCBsYWJlbHMgPSBmdW5jdGlvbih4KSBzdHJfd3JhcCh4LCB3aWR0aCA9IDE1KSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDYuIEdsb2JhbCBpbmNvbWUgaW5lcXVhbGl0eTogXG5CZXR3ZWVuIHZzLiB3aXRoaW4gY291bnRyeSBpbmVxdWFsaXR5IChUaGVpbCBpbmRleCksIDE4MjAtMjAyMCIsCiAgICAgICB4ID0gIiIsIHkgPSAiU2hhcmUgb2YgZ2xvYmFsIGluZXF1YWxpdHkgXG4oJSBvZiB0b3RhbCBUaGVpbCBpbmRleCkiLCBmaWxsID0gIiIpCmBgYAoKIyMjIEY3OiBHbG9iYWwgaW5jb21lIGluZXF1YWxpdHksIDE4MjAtMjAyMAoKYGBge3IgZGF0YS1mNywgY2FzaCA9IFRSVUV9CmRmX2Y3IDwtIHJlYWRfZXhjZWwoIi4vZGF0YS9XSVIyMDIyVGFibGVzRmlndXJlcy1TdW1tYXJ5Lnhsc3giLCBzaGVldCA9ICJkYXRhLUY3IikKZGZfZjcKYGBgCgpgYGB7cn0KZGZfZjcgJT4lIHNlbGVjdCh5ZWFyID0geSwgMjo0KSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IDI6NCwgbmFtZXNfdG8gPSAidHlwZSIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSB2YWx1ZSwgY29sb3IgPSB0eXBlKSkgKwogIGdlb21fc21vb3RoKGZvcm11bGEgPSB5fngsIG1ldGhvZCA9ICJsb2VzcyIsIHNwYW4gPSAwLjI1LCBzZSA9IEZBTFNFKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHJvdW5kKHNlcSgxODIwLCAyMDIwLCBieSA9IDIwKSwxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSA3LiBHbG9iYWwgaW5jb21lIGluZXF1YWxpdHksIDE4MjAtMjAyMCIsIAogICAgICAgeCA9ICIiLCB5ID0gIiBTaGFyZSBvZiB0b3RhbCB3b3JsZCBpbmNvbWUgKCUpIiwgY29sb3IgPSAiIikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDE5ODAsIHkgPSAwLjIwLCBsYWJlbCA9IHN0cmluZ3I6OnN0cl93cmFwKCJUaGUgZ2xvYmFsIGJvdHRvbSA1MCUgaW5jb21lIHNoYXJlIHJlbWFpbnMgaGlzdG9yaWNhbGx5IGxvdyBkZXNwaXRlIGdyb3d0aCBpbiB0aGUgZW1lcmdpbmcgd29ybGQgaW4gdGhlIHBhc3QgZGVjYWRlcy4iLCB3aWR0aCA9IDMwKSwgc2l6ZSA9IDMpCmBgYAoqKkludGVycHJldGF0aW9uKiouIFRoZSBzaGFyZSBvZiBnbG9iYWwgaW5jb21lIGdvaW5nIHRvIHRvcCAxMCUgaGlnaGVzdCBpbmNvbWVzIGF0IHRoZSB3b3JsZCBsZXZlbCBoYXMgZmx1Y3R1YXRlZCBhcm91bmQgNTAtNjAlIGJldHdlZW4gMTgyMCBhbmQgMjAyMCAoNTAlIGluIDE4MjAsIDYwJSBpbiAxOTEwLCA1NiUgaW4gMTk4MCwgNjElIGluIDIwMDAsIDU1JSBpbiAyMDIwKSwgd2hpbGUgdGhlIHNoYXJlIGdvaW5nIHRvIHRoZSBib3R0b20gNTAlIGxvd2VzdCBpbmNvbWVzIGhhcyBnZW5lcmFsbHkgYmVlbiBhcm91bmQgb3IgYmVsb3cgMTAlICgxNCUgaW4gMTgyMCwgNyUgaW4gMTkxMCwgNSUgaW4gMTk4MCwgNiUgaW4gMjAwMCwgNyUgaW4gMjAyMCkuIEdsb2JhbCBpbmVxdWFsaXR5IGhhcyBhbHdheXMgYmVlbiB2ZXJ5IGxhcmdlLiBJdCByb3NlIGJldHdlZW4gMTgyMCBhbmQgMTkxMCBhbmQgc2hvd3MgbGl0dGxlIGxvbmctcnVuIHRyZW5kIGJldHdlZW4gMTkxMCBhbmQgMjAyMC4gRGlzdHJpYnV0aW9uIG9mIHBlciBjYXBpdGEgaW5jb21lcy4gU291cmNlcyBhbmQgc2VyaWVzOiBzZWUgd2lyMjAyMi53aWQud29ybGQvbWV0aG9kb2xvZ3kgYW5kIENoYW5jZWwgYW5kIFBpa2V0dHkgKDIwMjEpLgoKIyMjIyBFeHBsYW5hdGlvbgoKIyMjIyMgU3RlcCAxLgoKKiBVc2UgYHBpdm90X2xvbmdlcmAgdG8gdGlkeSB0aGUgZGF0YS4KCmBgYHtyfQpkZl9mNyAlPiUgc2VsZWN0KHllYXIgPSB5LCAyOjQpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gMjo0LCBuYW1lc190byA9ICJ0eXBlIiwgdmFsdWVzX3RvID0gInZhbHVlIikgCmBgYAoKIyMjIyMgU3RlcCAyLgoKKlVzZSBgZ2VvbV9zbW9vdGhgIHdpdGggYHNwYW5gLCBhbmQgY2hhbmdlIHRoZSBzY2FsZSBvZiB4LWF4aXMgYW5kIHktYXhpcy4KCmBgYHtyfQpkZl9mNyAlPiUgc2VsZWN0KHllYXIgPSB5LCAyOjQpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gMjo0LCBuYW1lc190byA9ICJ0eXBlIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHZhbHVlLCBjb2xvciA9IHR5cGUpKSArCiAgZ2VvbV9zbW9vdGgoZm9ybXVsYSA9IHl+eCwgbWV0aG9kID0gImxvZXNzIiwgc3BhbiA9IDAuMjUsIHNlID0gRkFMU0UpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcm91bmQoc2VxKDE4MjAsIDIwMjAsIGJ5ID0gMjApLDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDcuIEdsb2JhbCBpbmNvbWUgaW5lcXVhbGl0eSwgMTgyMC0yMDIwIiwgCiAgICAgICB4ID0gIiIsIHkgPSAiIFNoYXJlIG9mIHRvdGFsIHdvcmxkIGluY29tZSAoJSkiLCBjb2xvciA9ICIiKQpgYGAKCiogRmluYWxseSwgYWRkIHRoZSBhbm5vdGF0aW9uIHRvIG9idGFpbiB0aGUgZmlndXJlIGFib3ZlLgoKIyMjIEY4OiBUaGUgcmlzZSBvZiBwcml2YXRlIHZlcnN1cyB0aGUgZGVjbGluZSBvZiBwdWJsaWMgd2VhbHRoIGluIHJpY2ggY291bnRyaWVzLCAxOTcwLTIwMjAKCmBgYHtyIGRhdGEtZjgsIGNhc2ggPSBUUlVFfQpkZl9mOCA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtU3VtbWFyeS54bHN4Iiwgc2hlZXQgPSAiZGF0YS1GOCIpCmRmX2Y4CmBgYApgYGB7cn0KZGZfZjggJT4lIGRyb3BfbmEoKSAlPiUKICBzZWxlY3QoeWVhciwgR2VybWFueV9wdWJsaWMgPSBHZXJtYW55LCBHZXJtYW55X3ByaXZhdGUgPSAnR2VybWFueSAocHJpdmF0ZSknLCAKICAgICAgICAgU3BhaW5fcHVibGljID0gU3BhaW4sIFNwYWluX3ByaXZhdGUgPSAnU3BhaW4gKHByaXZhdGUpJywgCiAgICAgICAgIEZyYW5jZV9wdWJsaWMgPSBGcmFuY2UsIEZyYW5jZV9wcml2YXRlID0gJ0ZyYW5jZSAocHJpdmF0ZSknLCAKICAgICAgICAgVUtfcHVibGljICA9IFVLLCBVS19wcml2YXRlID0gJ1VLIChwcml2YXRlKScsIAogICAgICAgICBKYXBhbl9wdWJsaWMgPSBKYXBhbiwgSmFwYW5fcHJpdmF0ZSA9ICdKYXBhbiAocHJpdmF0ZSknLCAKICAgICAgICAgTm9yd2F5X3B1YmxpYyA9IE5vcndheSwgTm9yd2F5X3ByaXZhdGUgPSAnTm9yd2F5IChwcml2YXRlKScsCiAgICAgICAgIFVTQV9wdWJsaWMgPSBVU0EsIFVTQV9wcml2YXRlID0gJ1VTQSAocHJpdmF0ZSknKSAlPiUKICBwaXZvdF9sb25nZXIoIXllYXIsIG5hbWVzX3RvID0gYygiY291bnRyeSIsIi52YWx1ZSIpLCBuYW1lc19zZXAgPSAiXyIpICU+JQogIHBpdm90X2xvbmdlcigzOjQsIG5hbWVzX3RvID0gInR5cGUiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoKSArCiAgc3RhdF9zbW9vdGgoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUsIGNvbG9yID0gY291bnRyeSwgbGluZXR5cGUgPSB0eXBlKSwgCiAgICAgICAgICAgICAgZm9ybXVsYSA9IHl+eCwgbWV0aG9kID0gImxvZXNzIiwgCiAgICAgICAgICAgICAgc3BhbiA9IDAuMjUsIHNlID0gRkFMU0UsIHNpemU9MC43NSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSA4LiBUaGUgcmlzZSBvZiBwcml2YXRlIHZlcnN1cyB0aGUgZGVjbGluZSBvZiBcbnB1YmxpYyB3ZWFsdGggaW4gcmljaCBjb3VudHJpZXMsIDE5NzAtMjAyMCIsIAogICAgICAgeCA9ICIiLCB5ID0gIndlYWx0aCBhcyAlIG9mIG5hdGlvbmFsIGluY29tZSIsIGNvbG9yID0gIiIsIHR5cGUgPSAiIikKYGBgCioqSW50ZXJwcmV0YXRpb24qKjogUHVibGljIHdlYWx0aCBpcyB0aGUgc3VtIG9mIGFsbCBmaW5hbmNpYWwgYW5kIG5vbi1maW5hbmNpYWwgYXNzZXRzLCBuZXQgb2YgZGVidHMsIGhlbGQgYnkgZ292ZXJubWVudHMuIFB1YmxpYyB3ZWFsdGggZHJvcHBlZCBmcm9tIDYwJSBvZiBuYXRpb25hbCBpbmNvbWUgaW4gMTk3MCB0byAtMTA2JSBpbiAyMDIwIGluIHRoZSBVSy4gICAKKipTb3VyY2VzIGFuZCBzZXJpZXMqKjogd2lyMjAyMi53aWQud29ybGQvbWV0aG9kb2xvZ3ksIEJhdWx1eiBldCBhbC4gKDIwMjEpIGFuZCB1cGRhdGVzLgoKIyMjIyBFeHBsYW5hdGlvbgoKIyMjIyMgU3RlcCAxLgoKKiBUaGVyZSBhcmUgdHdvIHR5cGVzIG9mIGdyb3VwcywgY291bnRyaWVzIGFuZCBwdWJsaWMgdnMgcHJpdmF0ZS4gU28gd2UgY2hhbmdlIHRoZSBjb2x1bW4gbmFtZXMgZmlyc3QgdG8gaWRlbnRpZnkgdGhhdCBjbGFzc2lmaWNhdGlvbiBlYXNpbHkuIFdlIGRlbGV0ZSB0aGUgbGFzdCB0d28gY29sdW1ucyAiZ3dlYWxBVkdSSUNIIiBhbmQgICJwd2VhbEFWR1JJQ0giIGFzIHRoZXkgd2lsbCBub3QgYXBwZWFyIGluIHRoZSBjaGFydC4KCmBgYHtyfQpkZl9mOCAlPiUgCiAgc2VsZWN0KHllYXIsIEdlcm1hbnlfcHVibGljID0gR2VybWFueSwgR2VybWFueV9wcml2YXRlID0gJ0dlcm1hbnkgKHByaXZhdGUpJywgCiAgICAgICAgIFNwYWluX3B1YmxpYyA9IFNwYWluLCBTcGFpbl9wcml2YXRlID0gJ1NwYWluIChwcml2YXRlKScsIAogICAgICAgICBGcmFuY2VfcHVibGljID0gRnJhbmNlLCBGcmFuY2VfcHJpdmF0ZSA9ICdGcmFuY2UgKHByaXZhdGUpJywgCiAgICAgICAgIFVLX3B1YmxpYyAgPSBVSywgVUtfcHJpdmF0ZSA9ICdVSyAocHJpdmF0ZSknLCAKICAgICAgICAgSmFwYW5fcHVibGljID0gSmFwYW4sIEphcGFuX3ByaXZhdGUgPSAnSmFwYW4gKHByaXZhdGUpJywgCiAgICAgICAgIE5vcndheV9wdWJsaWMgPSBOb3J3YXksIE5vcndheV9wcml2YXRlID0gJ05vcndheSAocHJpdmF0ZSknLAogICAgICAgICBVU0FfcHVibGljID0gVVNBLCBVU0FfcHJpdmF0ZSA9ICdVU0EgKHByaXZhdGUpJykgCmBgYAoKIyMjIyMgU3RlcCAyLiAKCiogRmlyc3Qgc2VwYXJhdGUgdGhlIGNvdW50cmllcyBpbnRvIGEgbmV3IGNvbHVtbi4KKiBIZXJlLCB3ZSB1c2VkIGFuIG9wdGlvbiBgbmFtZXNfc2VwID0gIl8iYC4gCgpgYGB7cn0KZGZfZjggJT4lIAogIHNlbGVjdCh5ZWFyLCBHZXJtYW55X3B1YmxpYyA9IEdlcm1hbnksIEdlcm1hbnlfcHJpdmF0ZSA9ICdHZXJtYW55IChwcml2YXRlKScsIAogICAgICAgICBTcGFpbl9wdWJsaWMgPSBTcGFpbiwgU3BhaW5fcHJpdmF0ZSA9ICdTcGFpbiAocHJpdmF0ZSknLCAKICAgICAgICAgRnJhbmNlX3B1YmxpYyA9IEZyYW5jZSwgRnJhbmNlX3ByaXZhdGUgPSAnRnJhbmNlIChwcml2YXRlKScsIAogICAgICAgICBVS19wdWJsaWMgID0gVUssIFVLX3ByaXZhdGUgPSAnVUsgKHByaXZhdGUpJywgCiAgICAgICAgIEphcGFuX3B1YmxpYyA9IEphcGFuLCBKYXBhbl9wcml2YXRlID0gJ0phcGFuIChwcml2YXRlKScsIAogICAgICAgICBOb3J3YXlfcHVibGljID0gTm9yd2F5LCBOb3J3YXlfcHJpdmF0ZSA9ICdOb3J3YXkgKHByaXZhdGUpJywKICAgICAgICAgVVNBX3B1YmxpYyA9IFVTQSwgVVNBX3ByaXZhdGUgPSAnVVNBIChwcml2YXRlKScpICU+JQogIHBpdm90X2xvbmdlcigheWVhciwgbmFtZXNfdG8gPSBjKCJjb3VudHJ5IiwiLnZhbHVlIiksIG5hbWVzX3NlcCA9ICJfIikgCmBgYAoKIyMjIyMgU3RlcCAzLgoKKiBOZXh0IGFwcGx5IGBwaXZvdF9sb25nZXJgICBhZ2FpbiB0byBmb3JtIHRoZSBzZWNvbmQgZ3JvdXAuCgpgYGB7cn0KZGZfZjggJT4lIAogIHNlbGVjdCh5ZWFyLCBHZXJtYW55X3B1YmxpYyA9IEdlcm1hbnksIEdlcm1hbnlfcHJpdmF0ZSA9ICdHZXJtYW55IChwcml2YXRlKScsIAogICAgICAgICBTcGFpbl9wdWJsaWMgPSBTcGFpbiwgU3BhaW5fcHJpdmF0ZSA9ICdTcGFpbiAocHJpdmF0ZSknLCAKICAgICAgICAgRnJhbmNlX3B1YmxpYyA9IEZyYW5jZSwgRnJhbmNlX3ByaXZhdGUgPSAnRnJhbmNlIChwcml2YXRlKScsIAogICAgICAgICBVS19wdWJsaWMgID0gVUssIFVLX3ByaXZhdGUgPSAnVUsgKHByaXZhdGUpJywgCiAgICAgICAgIEphcGFuX3B1YmxpYyA9IEphcGFuLCBKYXBhbl9wcml2YXRlID0gJ0phcGFuIChwcml2YXRlKScsIAogICAgICAgICBOb3J3YXlfcHVibGljID0gTm9yd2F5LCBOb3J3YXlfcHJpdmF0ZSA9ICdOb3J3YXkgKHByaXZhdGUpJywKICAgICAgICAgVVNBX3B1YmxpYyA9IFVTQSwgVVNBX3ByaXZhdGUgPSAnVVNBIChwcml2YXRlKScpICU+JQogIHBpdm90X2xvbmdlcigheWVhciwgbmFtZXNfdG8gPSBjKCJjb3VudHJ5IiwiLnZhbHVlIiksIG5hbWVzX3NlcCA9ICJfIikgJT4lCiAgcGl2b3RfbG9uZ2VyKDM6NCwgbmFtZXNfdG8gPSAidHlwZSIsIHZhbHVlc190byA9ICJ2YWx1ZSIpCmBgYAoKIyMjIyMgU3RlcCA0LgoKKiBBc3NpZ24gY29sb3JzIHRvIGNvdW50cmllcyBhbmQgZGlzdGluZ3Vpc2ggdHlwZXMgYnkgYGxpbmV0eXBlYC4KCmBgYHtyfQpkZl9mOCAlPiUgCiAgc2VsZWN0KHllYXIsIEdlcm1hbnlfcHVibGljID0gR2VybWFueSwgR2VybWFueV9wcml2YXRlID0gJ0dlcm1hbnkgKHByaXZhdGUpJywgCiAgICAgICAgIFNwYWluX3B1YmxpYyA9IFNwYWluLCBTcGFpbl9wcml2YXRlID0gJ1NwYWluIChwcml2YXRlKScsIAogICAgICAgICBGcmFuY2VfcHVibGljID0gRnJhbmNlLCBGcmFuY2VfcHJpdmF0ZSA9ICdGcmFuY2UgKHByaXZhdGUpJywgCiAgICAgICAgIFVLX3B1YmxpYyAgPSBVSywgVUtfcHJpdmF0ZSA9ICdVSyAocHJpdmF0ZSknLCAKICAgICAgICAgSmFwYW5fcHVibGljID0gSmFwYW4sIEphcGFuX3ByaXZhdGUgPSAnSmFwYW4gKHByaXZhdGUpJywgCiAgICAgICAgIE5vcndheV9wdWJsaWMgPSBOb3J3YXksIE5vcndheV9wcml2YXRlID0gJ05vcndheSAocHJpdmF0ZSknLAogICAgICAgICBVU0FfcHVibGljID0gVVNBLCBVU0FfcHJpdmF0ZSA9ICdVU0EgKHByaXZhdGUpJykgJT4lCiAgcGl2b3RfbG9uZ2VyKCF5ZWFyLCBuYW1lc190byA9IGMoImNvdW50cnkiLCIudmFsdWUiKSwgbmFtZXNfc2VwID0gIl8iKSAlPiUKICBwaXZvdF9sb25nZXIoMzo0LCBuYW1lc190byA9ICJ0eXBlIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc21vb3RoKGFlcyh4ID0geWVhciwgeSA9IHZhbHVlLCBjb2xvciA9IGNvdW50cnksIGxpbmV0eXBlID0gdHlwZSksCiAgICAgICAgICAgICAgZm9ybXVsYSA9IHl+eCwgbWV0aG9kID0gImxvZXNzIiwgc3BhbiA9IDAuMjUsIHNlID0gRkFMU0UpCmBgYAoKIyMjIyMgU3RlcCA1LgoKKiBTaW5jZSB0aGVyZSBhcmUgYSBsb3Qgb2YgTkEncywgcmVtb3ZlZCB1c2luZyBgZHJvcF9uYSgpYAoqIENoYW5nZSB0aGUgbGluZSB3aWR0aCBieSBgc2l6ZWAsIGNoYW5nZSB0aGUgeS1heGlzIHRvIHBlcmNlbnRzIGFuZCBhZGQgdGhlIC50aXRsZS4KCmBgYHtyfQpkZl9mOCAlPiUgZHJvcF9uYSgpICU+JQogIHNlbGVjdCh5ZWFyLCBHZXJtYW55X3B1YmxpYyA9IEdlcm1hbnksIEdlcm1hbnlfcHJpdmF0ZSA9ICdHZXJtYW55IChwcml2YXRlKScsIAogICAgICAgICBTcGFpbl9wdWJsaWMgPSBTcGFpbiwgU3BhaW5fcHJpdmF0ZSA9ICdTcGFpbiAocHJpdmF0ZSknLCAKICAgICAgICAgRnJhbmNlX3B1YmxpYyA9IEZyYW5jZSwgRnJhbmNlX3ByaXZhdGUgPSAnRnJhbmNlIChwcml2YXRlKScsIAogICAgICAgICBVS19wdWJsaWMgID0gVUssIFVLX3ByaXZhdGUgPSAnVUsgKHByaXZhdGUpJywgCiAgICAgICAgIEphcGFuX3B1YmxpYyA9IEphcGFuLCBKYXBhbl9wcml2YXRlID0gJ0phcGFuIChwcml2YXRlKScsIAogICAgICAgICBOb3J3YXlfcHVibGljID0gTm9yd2F5LCBOb3J3YXlfcHJpdmF0ZSA9ICdOb3J3YXkgKHByaXZhdGUpJywKICAgICAgICAgVVNBX3B1YmxpYyA9IFVTQSwgVVNBX3ByaXZhdGUgPSAnVVNBIChwcml2YXRlKScpICU+JQogIHBpdm90X2xvbmdlcigheWVhciwgbmFtZXNfdG8gPSBjKCJjb3VudHJ5IiwiLnZhbHVlIiksIG5hbWVzX3NlcCA9ICJfIikgJT4lCiAgcGl2b3RfbG9uZ2VyKDM6NCwgbmFtZXNfdG8gPSAidHlwZSIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Ntb290aChhZXMoeCA9IHllYXIsIHkgPSB2YWx1ZSwgY29sb3IgPSBjb3VudHJ5LCBsaW5ldHlwZSA9IHR5cGUpLAogICAgICAgICAgICAgIGZvcm11bGEgPSB5fngsIG1ldGhvZCA9ICJsb2VzcyIsIAogICAgICAgICAgICAgIHNwYW4gPSAwLjI1LCBzZSA9IEZBTFNFLCBzaXplPTAuNzUpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgOC4gVGhlIHJpc2Ugb2YgcHJpdmF0ZSB2ZXJzdXMgdGhlIGRlY2xpbmUgb2YgXG5wdWJsaWMgd2VhbHRoIGluIHJpY2ggY291bnRyaWVzLCAxOTcwLTIwMjAiLCAKICAgICAgIHggPSAiIiwgeSA9ICJ3ZWFsdGggYXMgJSBvZiBuYXRpb25hbCBpbmNvbWUiLCBjb2xvciA9ICIiLCB0eXBlID0gIiIpCmBgYAoKIyMjIyMgU3RlcCA2LgoKKiBMZXQgdXMgY2hlY2sgaWYgd2UgdXNlIG9ubHkgY29sb3IgZm9yIGVhY2ggZ3JvdXAgcmVwcmVzZW50aW5nIGNvbHVtbnMuIFRoaXMgaXMgbm90IHRoZSBjaGFydCB3ZSB3YW50ZWQgdG8gb2J0YWluLgoKYGBge3J9CmRmX2Y4ICU+JSBkcm9wX25hKCkgJT4lIAogIHBpdm90X2xvbmdlcigheWVhciwgbmFtZXNfdG8gPSAiZ3JvdXAiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUsIGNvbG9yID0gZ3JvdXApLCAKICAgICAgICAgICAgZm9ybXVsYSA9IHl+eCwgbWV0aG9kID0gImxvZXNzIiwgCiAgICAgICAgICAgIHNwYW4gPSAwLjI1LCBzZSA9IEZBTFNFLCBzaXplPTAuNzUpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgOC4gVGhlIHJpc2Ugb2YgcHJpdmF0ZSB2ZXJzdXMgXG50aGUgZGVjbGluZSBvZiBwdWJsaWMgd2VhbHRoIGluIHJpY2ggY291bnRyaWVzLCBcbjE5NzAtMjAyMCIsIAogICAgICAgeCA9ICIiLCB5ID0gIndlYWx0aCBhcyAlIG9mIG5hdGlvbmFsIGluY29tZSIsIGNvbG9yID0gIiIpCmBgYAoKIyMjIEY5OiBBdmVyYWdlIGFubnVhbCB3ZWFsdGggZ3Jvd3RoIHJhdGUsIDE5OTUtMjAyMQoKYGBge3IgZGF0YS1mOSwgY2FzaCA9IFRSVUV9CmRmX2Y5IDwtIHJlYWRfZXhjZWwoIi4vZGF0YS9XSVIyMDIyVGFibGVzRmlndXJlcy1TdW1tYXJ5Lnhsc3giLCBzaGVldCA9ICJkYXRhLUY5IikKZGZfZjkKYGBgCgpgYGB7cn0KYnJrcyA8LSBjKDAsIDEwLCAyMCwgMzAsIDQwLCA1MCwgNjAsIDcwLCA4MCwgOTAsIDk5LCA5OS45LCA5OS45OSwgOTkuOTk5KQpkZl9mOSAlPiUgCiAgbXV0YXRlKGxldmVsID0gY3V0KHAsIGJyZWFrcyA9IGMoYnJrcywxMDApLCBsYWJlbHMgPSBhcy5jaGFyYWN0ZXIoYnJrcyksIGluY2x1ZGUubG93ZXN0ID0gVFJVRSkpICU+JSAKICBtdXRhdGUoeGxhYmVsID0gYXMubnVtZXJpYyhsZXZlbCkrMC44KSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB4bGFiZWwsIHkgPSBgV2VhbHRoIGdyb3d0aCAxOTk1LTIwMjFgKSkgKyBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBmb3JtdWxhID0geX54LCBzZSA9IEZBTFNFLCBzcGFuID0gMC41KSArIAogIHNjYWxlX3hfZGlzY3JldGUobGltaXRzPWFzLmNoYXJhY3RlcihicmtzKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDkuIEF2ZXJhZ2UgYW5udWFsIHdlYWx0aCBncm93dGggcmF0ZSwgMTk5NS0yMDIxIiwgCiAgICAgICB4ID0gIuKGkDElIHBvb3Jlc3QgR2xvYmFsIHdlYWx0aCBncm91cCAgICAgICAgICAgICAgMC4wMDElIHJpY2hlc3TihpIiLCAKICAgICAgIHkgPSAiUGVyIGFkdWx0IGFubnVhbCBncm93dGggcmF0ZSBpbiB3ZWFsdGgsIFxubmV0IG9mIGluZmxhdGlvbiAoJSkiKQpgYGAKKipJbnRlcnByZXRhdGlvbioqOiBHcm93dGggcmF0ZXMgYW1vbmcgdGhlIHBvb3Jlc3QgaGFsZiBvZiB0aGUgcG9wdWxhdGlvbiB3ZXJlIGJldHdlZW4gMyUgYW5kIDQlIHBlciB5ZWFyLCBiZXR3ZWVuIDE5OTUgYW5kIDIwMjEuIFNpbmNlIHRoaXMgZ3JvdXAgc3RhcnRlZCBmcm9tIHZlcnkgbG93IHdlYWx0aCBsZXZlbHMsIGl0cyBhYnNvbHV0ZSBsZXZlbHMgb2YgZ3Jvd3RoIHJlbWFpbmVkIHZlcnkgbG93LiBUaGUgcG9vcmVzdCBoYWxmIG9mIHRoZSB3b3JsZCBwb3B1bGF0aW9uIG9ubHkgY2FwdHVyZWQgMi4zJSBvZiBvdmVyYWxsIHdlYWx0aCBncm93dGggc2luY2UgMTk5NS4gVGhlIHRvcCAxJSAgYmVuZWZpdGVkIGZyb20gaGlnaCBncm93dGggcmF0ZXMgKDMlIHRvIDklIHBlciB5ZWFyKS4gVGhpcyBncm91cCBjYXB0dXJlZCAzOCUgb2YgdG90YWwgd2VhbHRoIGdyb3d0aCBiZXR3ZWVuIDE5OTUgYW5kIDIwMjEuIE5ldCBob3VzZWhvbGQgd2VhbHRoIGlzIGVxdWFsIHRvIHRoZSBzdW0gb2YgZmluYW5jaWFsIGFzc2V0cyAoZS5nLiBlcXVpdHkgb3IgYm9uZHMpIGFuZCBub24tZmluYW5jaWFsIGFzc2V0cyAoZS5nLiBob3VzaW5nIG9yIGxhbmQpIG93bmVkIGJ5IGluZGl2aWR1YWxzLCBuZXQgb2YgdGhlaXIgZGVidHMuICAgCioqU291cmNlcyBhbmQgc2VyaWVzKio6IHdpcjIwMjIud2lkLndvcmxkL21ldGhvZG9sb2d5LgoKIyMjIyBFeHBsYW5hdGlvbgoKIyMjIyMgU3RlcCAxLgoKKiBMZXQncyBsb29rIGF0IHRoZSBvcmlnaW5hbCBjaGFydAoKIVtGOV93b3JsZF9tYXBdKGZpZ3MvRjkucG5nKXt3aWR0aCA9IDEwMCV9CgoqIFRoZSBzY2FsZSBvZiB0aGUgeC1heGlzIGlzIG5vdCBldmVubHkgcGFydGl0aW9uZWQuIEl0IGlzICgwLCAxMCwgMjAsIDMwLCA0MCwgNTAsIDYwLCA3MCwgODAsIDkwLCA5OSwgOTkuOSwgOTkuOTksIDk5Ljk5OSkuCiogTG9vayBhdCB0aGUgY29sdW1uIHAgb2YgdGhlIGRhdGEuCgpgYGB7cn0KZGZfZjkgJT4lIGRpc3RpbmN0KHApICU+JSBwdWxsKCkKYGBgCiogVXNlIGN1dCB0byBicmVhayBpbiBsZXZlbHMuCgpgYGB7cn0KYnJrcyA8LSBjKDAsIDEwLCAyMCwgMzAsIDQwLCA1MCwgNjAsIDcwLCA4MCwgOTAsIDk5LCA5OS45LCA5OS45OSwgOTkuOTk5KQpkZl9mOSAlPiUgbXV0YXRlKGxldmVsID0gY3V0KHAsIGJyZWFrcyA9IGMoYnJrcywxMDApLCBsYWJlbHMgPSBhcy5jaGFyYWN0ZXIoYnJrcyksIGluY2x1ZGUubG93ZXN0ID0gVFJVRSkpCmBgYAoKIyMjIyMgU3RlcCAyLgoKKiBBZGQgYHhsYWJlbGAgaW4gbnVtZXJpYy4KCmBgYHtyfQpkZl9mOSAlPiUgbXV0YXRlKGxldmVsID0gY3V0KHAsIGJyZWFrcyA9IGMoYnJrcywxMDApLCBsYWJlbHMgPSBhcy5jaGFyYWN0ZXIoYnJrcyksIGluY2x1ZGUubG93ZXN0ID0gVFJVRSkpICU+JSAKICBtdXRhdGUoeGxhYmVsID0gYXMubnVtZXJpYyhsZXZlbCkpCmBgYAoKIyMjIyMgU3RlcCAzLgoKKiBEcmF3IGEgY3VydmUgdXNpbmcgYGdlb21fc21vb3RoYC4KKiBBZGRlZCAwLjUgdG8gcmVwcmVzZW50IHRoZSBtZWFuIHZhbHVlIGluIGVhY2ggaW50ZXJ2YWwuCgpgYGB7cn0KZGZfZjkgJT4lIG11dGF0ZShsZXZlbCA9IGN1dChwLCBicmVha3MgPSBjKGJya3MsMTAwKSwgbGFiZWxzID0gYXMuY2hhcmFjdGVyKGJya3MpLCBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpKSAlPiUgCiAgbXV0YXRlKHhsYWJlbCA9IGFzLm51bWVyaWMobGV2ZWwpKzAuNSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0geGxhYmVsLCB5ID0gYFdlYWx0aCBncm93dGggMTk5NS0yMDIxYCkpICsgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgZm9ybXVsYSA9IHl+eCwgc2UgPSBGQUxTRSwgc3BhbiA9IDAuNSkKYGBgCgojIyMjIyBTdGVwIDQuCgoqIFVzZSBgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHM9YXMuY2hhcmFjdGVyKGJya3MpKWAgdG8gY2hhbmdlIHRoZSBsYWJlbCBvZiB0aGUgeC1heGlzLgoqIFVzZSBgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKWAuCgpgYGB7cn0KZGZfZjkgJT4lIG11dGF0ZShsZXZlbCA9IGN1dChwLCBicmVha3MgPSBjKGJya3MsMTAwKSwgbGFiZWxzID0gYXMuY2hhcmFjdGVyKGJya3MpLCBpbmNsdWRlLmxvd2VzdCA9IFRSVUUpKSAlPiUgCiAgbXV0YXRlKHhsYWJlbCA9IGFzLm51bWVyaWMobGV2ZWwpKyAwLjgpICU+JQogIGdncGxvdChhZXMoeCA9IHhsYWJlbCwgeSA9IGBXZWFsdGggZ3Jvd3RoIDE5OTUtMjAyMWApKSArIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIGZvcm11bGEgPSB5fngsIHNlID0gRkFMU0UsIHNwYW4gPSAwLjUpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHM9YXMuY2hhcmFjdGVyKGJya3MpKSArIAogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkKYGBgCgojIyMgRjEwOiBUaGUgc2hhcmUgb2Ygd2VhbHRoIG93bmVkIGJ5IHRoZSBnbG9iYWwgMC4xJSBhbmQgYmlsbGlvbmFpcmVzLCAyMDIxCgpgYGB7ciBkYXRhLWYxMCwgY2FzaCA9IFRSVUV9CmRmX2YxMCA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtU3VtbWFyeS54bHN4Iiwgc2hlZXQgPSAiZGF0YS1GMTAiKQpkZl9mMTAKYGBgCgpgYGB7cn0KZGZfZjEwICU+JSAKICBzZWxlY3QoeWVhciwgIkdsb2JhbCBCaWxsaW9uYWlyZSBXZWFsdGgiID0gYm5faGh3ZWFsLCAiVG9wIDAuMDElIiA9IHRvcDAuMV9oaHdlYWwpICU+JQogIHBpdm90X2xvbmdlcigheWVhciwgbmFtZXNfdG8gPSAiZ3JvdXAiLCIudmFsdWUiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUsIGNvbG9yID0gZ3JvdXApLCAKICAgICAgICAgICAgICBmb3JtdWxhID0geX54LCBtZXRob2QgPSAibG9lc3MiLCAKICAgICAgICAgICAgICBzcGFuID0gMC4yNSwgc2UgPSBGQUxTRSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSByb3VuZChzZXEoMTk5NSwgMjAyMCwgYnkgPSA1KSwxKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPXJldihzY2FsZXM6Omh1ZV9wYWwoKSgyKSkpICsKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSAxMC4gRXh0cmVtZSB3ZWFsdGggaW5lcXVhbGl0eTogXG50aGUgcmlzZSBvZiBnbG9iYWwgYmlsbGlvbmFpcmVzIGFuZCB0b3AgMC4wMSUsIDE5OTUtMjAyMSIsIAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIHRvdGFsIGhvdXNlaG9sZCB3ZWFsdGggKCUpIiwgY29sb3IgPSAiIikKYGBgCioqSW50ZXJwcmV0YXRpb24qKjogVGhlIHNoYXJlIG9mIHdlYWx0aCBkZXRhaW5lZCBieSB0aGUgd29ybGQncyBiaWxsaW9uYWlyZXMgcm9zZSBmcm9tIDElIG9mIHRvdGFsIGhvdXNlaG9sZCB3ZWFsdGggaW4gMTk5NSB0byBuZWFybHkgMy41JSB0b2RheS4gVGhlIHRocmVzaG9sZCBvZiB0b3AgMC4wMSUsIGNvbXBvc2VkIG9mIDUyMCAwMDAgYWR1bHRzLCBncmV3IGZyb20g4oKsNjkzLDAwMCAoUFBQKSBpbiAxOTk1IHRvIOKCrDE2LDY2NiwwMDAgdG9kYXkuIFRoZSBuZXQgaG91c2Vob2xkIHdlYWx0aCBpcyBlcXVhbCB0byB0aGUgc3VtIG9mIGZpbmFuY2lhbCBhc3NldHMgKGUuZy4gZXF1aXR5IG9yIGJvbmRzKSBhbmQgbm9uLWZpbmFuY2lhbCBhc3NldHMgKGUuZy4gaG91c2luZyBvciBsYW5kKSBvd25lZCBieSBpbmRpdmlkdWFscywgbmV0IG9mIHRoZWlyIGRlYnRzLiAgIAoqKlNvdXJjZXMgYW5kIHNlcmllcyoqOiB3aXIyMDIyLndpZC53b3JsZC9tZXRob2RvbG9neSwgQmF1bHV6IGV0IGFsLiAoMjAyMSkgYW5kIHVwZGF0ZXMuCgojIyMjIEV4cGxhbmF0aW9uCgojIyMjIyBTdGVwIDEuCgoqIFVzZSBkZXNjcmlwdGl2ZSBjb2x1bW4gbmFtZXMgYW5kIHVzZSBgcGl2b3RfbG9uZ2VyYCB0byBtYWtlIGl0IHRpZHkuCgpgYGB7cn0KZGZfZjEwICU+JSAKICBzZWxlY3QoeWVhciwgIkdsb2JhbCBCaWxsaW9uYWlyZSBXZWFsdGgiID0gYm5faGh3ZWFsLCAiVG9wIDAuMDElIiA9IHRvcDAuMV9oaHdlYWwpICU+JQogIHBpdm90X2xvbmdlcigheWVhciwgbmFtZXNfdG8gPSAiZ3JvdXAiLCIudmFsdWUiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKQpgYGAKCiMjIyMjIFN0ZXAgMi4KCiogVXNlIGBnZW9tX3Ntb290aGAgd2l0aCBgc3BhbiA9IDAuMjVgIGFuZCBjaGFuZ2UgdGhlIGJyZWFrcyBvZiB4LWxhYmVscy4KCmBgYHtyfQpkZl9mMTAgJT4lIAogIHNlbGVjdCh5ZWFyLCAiR2xvYmFsIEJpbGxpb25haXJlIFdlYWx0aCIgPSBibl9oaHdlYWwsICJUb3AgMC4wMSUiID0gdG9wMC4xX2hod2VhbCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF5ZWFyLCBuYW1lc190byA9ICJncm91cCIsIi52YWx1ZSIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Ntb290aChhZXMoeCA9IHllYXIsIHkgPSB2YWx1ZSwgY29sb3IgPSBncm91cCksIAogICAgICAgICAgICAgIGZvcm11bGEgPSB5fngsIG1ldGhvZCA9ICJsb2VzcyIsIHNwYW4gPSAwLjI1LCBzZSA9IEZBTFNFKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHJvdW5kKHNlcSgxOTk1LCAyMDIwLCBieSA9IDUpLDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDEwLiBFeHRyZW1lIHdlYWx0aCBpbmVxdWFsaXR5OiBcbnRoZSByaXNlIG9mIGdsb2JhbCBiaWxsaW9uYWlyZXMgYW5kIHRvcCAwLjAxJSwgMTk5NS0yMDIxIiwgCiAgICAgICB4ID0gIiIsIHkgPSAiU2hhcmUgb2YgdG90YWwgaG91c2Vob2xkIHdlYWx0aCAoJSkiLCBjb2xvciA9ICIiKQpgYGAKCiMjIyMjIFN0ZXAgMy4KCiogU3dhcCB0aGUgY29sb3JzIGJ5IGBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPXJldihzY2FsZXM6Omh1ZV9wYWwoKSgyKSkpYC4gSWYgYG5gIGlzIHRoZSBudW1iZXIgb2YgY29sb3JzIHVzZWQgYHNjYWxlczo6aHVlX3BhbCgpKG4pYCByZXR1cm5zIHRoZSBSR0IgY29sb3IgY29kZXMgdXNlZC4gQnkgYHJldmAsIHRoZSBvcmRlciBpcyByZXZlcnNlZC4gU2VlIGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9zY2FsZV9odWUuaHRtbC4KCmBgYHtyfQpkZl9mMTAgJT4lIAogIHNlbGVjdCh5ZWFyLCAiR2xvYmFsIEJpbGxpb25haXJlIFdlYWx0aCIgPSBibl9oaHdlYWwsICJUb3AgMC4wMSUiID0gdG9wMC4xX2hod2VhbCkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF5ZWFyLCBuYW1lc190byA9ICJncm91cCIsIi52YWx1ZSIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3Ntb290aChhZXMoeCA9IHllYXIsIHkgPSB2YWx1ZSwgY29sb3IgPSBncm91cCksIAogICAgICAgICAgICAgIGZvcm11bGEgPSB5fngsIG1ldGhvZCA9ICJsb2VzcyIsIHNwYW4gPSAwLjI1LCBzZSA9IEZBTFNFKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHJvdW5kKHNlcSgxOTk1LCAyMDIwLCBieSA9IDUpLDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9cmV2KHNjYWxlczo6aHVlX3BhbCgpKDIpKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDEwLiBFeHRyZW1lIHdlYWx0aCBpbmVxdWFsaXR5OiBcbnRoZSByaXNlIG9mIGdsb2JhbCBiaWxsaW9uYWlyZXMgYW5kIHRvcCAwLjAxJSwgMTk5NS0yMDIxIiwgCiAgICAgICB4ID0gIiIsIHkgPSAiU2hhcmUgb2YgdG90YWwgaG91c2Vob2xkIHdlYWx0aCAoJSkiLCBjb2xvciA9ICIiKQpgYGAKCiMjIyBGMTE6IFRvcCAxJSB2cyBib3R0b20gNTAlIHdlYWx0aCBzaGFyZXMgaW4gV2VzdGVybiBFdXJvcGUgYW5kIHRoZSBVUywgMTkxMC0yMDIwCgpgYGB7ciBkYXRhLWYxMSwgY2FzaCA9IFRSVUV9CmRmX2YxMSA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtU3VtbWFyeS54bHN4Iiwgc2hlZXQgPSAiZGF0YS1GMTEiKQpkZl9mMTEKYGBgCgpgYGB7cn0KZGZfZjExICU+JQogIHJlbmFtZSgheWVhciwgVVNfYm90NTAgPSBVU2JvdDUwLCBVU190b3AxID0gVVN0b3AxLCBFVV9ib3Q1MCA9IEVVYm90NTAsIEVVX3RvcDEgPSBFVXRvcDEpICU+JQogIHBpdm90X2xvbmdlcigheWVhciwgbmFtZXNfdG8gPSBjKCJncm91cCIsIi52YWx1ZSIpLCBuYW1lc19zZXAgPSAiXyIpICU+JQogIHBpdm90X2xvbmdlcigzOjQsIG5hbWVzX3RvID0gInR5cGUiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUsIGNvbG9yID0gZ3JvdXAsIGxpbmV0eXBlID0gdHlwZSksIAogICAgICAgICAgICAgIGZvcm11bGEgPSB5fngsIG1ldGhvZCA9ICJsb2VzcyIsIHNwYW4gPSAwLjUsIHNlID0gRkFMU0UpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcm91bmQoc2VxKDE5MTAsIDIwMjAsIGJ5ID0gMTApLDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDExLiBUb3AgMSUgdnMgYm90dG9tIDUwJSB3ZWFsdGggc2hhcmVzIFxuIGluIFdlc3Rlcm4gRXVyb3BlIGFuZCB0aGUgVVMsIDE5MTAtMjAyMCIsIAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIHRvdGFsIHBlcnNvbmFsIHdlYWx0aCAoJSkiLCBjb2xvciA9ICIiLCBsaW5ldHlwZSA9ICIiKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoImRvdHRlZCIsInNvbGlkIikpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyMDAwLCB5ID0gMC41MCwgbGFiZWwgPSBzdHJpbmdyOjpzdHJfd3JhcCgiV2VhbHRoIGluZXF1YWxpdHkgaGFzIGJlZW4gcmlzaW5nIGF0IGRpZmZlcmVudCBzcGVlZHMgYWZ0ZXIgYSBoaXN0b3JpY2FsIGRlY2xpbmUuIFRoZSBib3R0b20gNTAlIGhhcyBhbHdheXMgYmVlbiBleHRyZW1lbHkgbG93LiIsIHdpZHRoID0gMzApLCBzaXplID0gMykKYGBgCioqSW50ZXJwcmV0YXRpb24qKjogVGhlIGdyYXBoIHByZXNlbnRzIGRlY2VubmFsIGF2ZXJhZ2VzIG9mIHRvcCAxJSBwZXJzb25hbCB3ZWFsdGggc2hhcmVzIGluIFdlc3Rlcm4gRXVyb3BlIGFuZCB0aGUgVVMuIEJldHdlZW4gMTkxMCBhbmQgMjAyMCwgdGhlIHRvcCAxJSB3YXMgNTUlIG9uIGF2ZXJhZ2UgaW4gRXVyb3BlIHZzLiA0MyUgaW4gdGhlIFVTLiBBIGNlbnR1cnkgbGF0ZXIsIHRoZSBVUyBpcyBhbG1vc3QgYmFjayB0byBpdHMgZWFybHkgMjB0aCBjZW50dXJ5IGxldmVsLiBTb3VyY2VzIGFuZCBzZXJpZXM6IHdpcjIwMjIud2lkLndvcmxkL21ldGhvZG9sb2d5LgoKIyMjIyBFeHBsYW5hdGlvbgoKIyMjIyMgU3RlcCAxLgoKKiBUaGVyZSBhcmUgdHdvIGdyb3VwczogVVMgdnMuIEVVIGFuZCBib3Q1MCBhbmQgdG9wMS4gV2UgdXNlIHRoZSBzYW1lIHRlY2huaXF1ZSBhcyBpbiBGOC4KCmBgYHtyfQpkZl9mMTEgJT4lIAogIHJlbmFtZSgheWVhciwgVVNfYm90NTAgPSBVU2JvdDUwLCBVU190b3AxID0gVVN0b3AxLCBFVV9ib3Q1MCA9IEVVYm90NTAsIEVVX3RvcDEgPSBFVXRvcDEpICU+JQogIHBpdm90X2xvbmdlcigheWVhciwgbmFtZXNfdG8gPSBjKCJncm91cCIsIi52YWx1ZSIpLCBuYW1lc19zZXAgPSAiXyIpCmBgYAoKIyMjIyMgU3RlcCAyLgoKKiBIZXJlLCB3ZSB0cnkgYW5vdGhlciB3YXkuIEhlcmUgd2UgdXNlIHR3byBgZ2VvbV9zbW9vdGhgIHdpdGggZGlmZmVyZW50IGBhZXMoKWAuCiogQ2FuIHlvdSBzZWUgdGhlIGRpZmZlcmVuY2Ugb2YgdGhlIGNoYXJ0IGFib3ZlPwoKYGBge3J9CmRmX2YxMSAlPiUgCiAgcmVuYW1lKCF5ZWFyLCBVU19ib3Q1MCA9IFVTYm90NTAsIFVTX3RvcDEgPSBVU3RvcDEsIEVVX2JvdDUwID0gRVVib3Q1MCwgRVVfdG9wMSA9IEVVdG9wMSkgJT4lCiAgcGl2b3RfbG9uZ2VyKCF5ZWFyLCBuYW1lc190byA9IGMoImdyb3VwIiwiLnZhbHVlIiksIG5hbWVzX3NlcCA9ICJfIikgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc21vb3RoKGFlcyh4ID0geWVhciwgeSA9IHRvcDEsIGNvbG9yID0gZ3JvdXApLCAKICAgICAgICAgICAgICBmb3JtdWxhID0geX54LCBtZXRob2QgPSAibG9lc3MiLCBzcGFuID0gMC41LCBzZSA9IEZBTFNFKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSB5ZWFyLCB5ID0gYm90NTAsIGNvbG9yID0gZ3JvdXApLCAKICAgICAgICAgICAgICBmb3JtdWxhID0geX54LCBtZXRob2QgPSAibG9lc3MiLCBzcGFuID0gMC41LCBzZSA9IEZBTFNFLCBsaW5ldHlwZSA9IDIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcm91bmQoc2VxKDE5MTAsIDIwMjAsIGJ5ID0gMTApLDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDExLiBUb3AgMSUgdnMgYm90dG9tIDUwJSB3ZWFsdGggc2hhcmVzIFxuIGluIFdlc3Rlcm4gRXVyb3BlIGFuZCB0aGUgVVMsIDE5MTAtMjAyMCIsIAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIHRvdGFsIHBlcnNvbmFsIHdlYWx0aCAoJSkiLCBjb2xvciA9ICIiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMjAwMCwgeSA9IDAuNTAsIGxhYmVsID0gc3RyaW5ncjo6c3RyX3dyYXAoIldlYWx0aCBpbmVxdWFsaXR5IGhhcyBiZWVuIHJpc2luZyBhdCBkaWZmZXJlbnQgc3BlZWRzIGFmdGVyIGEgaGlzdG9yaWNhbCBkZWNsaW5lLiBUaGUgYm90dG9tIDUwJSBoYXMgYWx3YXlzIGJlZW4gZXh0cmVtZWx5IGxvdy4iLCB3aWR0aCA9IDMwKSwgc2l6ZSA9IDMpCmBgYAoKIyMjIyMgU3RlcCAzLgoKVXNlIGBwaXZvdF9sb25nZXJgIHRoZSBzZWNvbmQgdGltZS4KCmBgYHtyfQpkZl9mMTEgJT4lIAogIHJlbmFtZSgheWVhciwgVVNfYm90NTAgPSBVU2JvdDUwLCBVU190b3AxID0gVVN0b3AxLCBFVV9ib3Q1MCA9IEVVYm90NTAsIEVVX3RvcDEgPSBFVXRvcDEpICU+JQogIHBpdm90X2xvbmdlcigheWVhciwgbmFtZXNfdG8gPSBjKCJncm91cCIsIi52YWx1ZSIpLCBuYW1lc19zZXAgPSAiXyIpICU+JQogIHBpdm90X2xvbmdlcigzOjQsIG5hbWVzX3RvID0gInR5cGUiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUsIGNvbG9yID0gZ3JvdXAsIGxpbmV0eXBlID0gdHlwZSksIAogICAgICAgICAgICAgIGZvcm11bGEgPSB5fngsIG1ldGhvZCA9ICJsb2VzcyIsIHNwYW4gPSAwLjUsIHNlID0gRkFMU0UpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcm91bmQoc2VxKDE5MTAsIDIwMjAsIGJ5ID0gMTApLDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDExLiBUb3AgMSUgdnMgYm90dG9tIDUwJSB3ZWFsdGggc2hhcmVzIFxuIGluIFdlc3Rlcm4gRXVyb3BlIGFuZCB0aGUgVVMsIDE5MTAtMjAyMCIsIAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIHRvdGFsIHBlcnNvbmFsIHdlYWx0aCAoJSkiLCBjb2xvciA9ICIiLCBsaW5ldHlwZSA9ICIiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMjAwMCwgeSA9IDAuNTAsIGxhYmVsID0gc3RyaW5ncjo6c3RyX3dyYXAoIldlYWx0aCBpbmVxdWFsaXR5IGhhcyBiZWVuIHJpc2luZyBhdCBkaWZmZXJlbnQgc3BlZWRzIGFmdGVyIGEgaGlzdG9yaWNhbCBkZWNsaW5lLiBUaGUgYm90dG9tIDUwJSBoYXMgYWx3YXlzIGJlZW4gZXh0cmVtZWx5IGxvdy4iLCB3aWR0aCA9IDMwKSwgc2l6ZSA9IDMpCmBgYAojIyMjIyBTdGVwIDQuIAoKQ2hhbmdlIHRoZSBvcmRlciBvZiBsaW5ldHlwZXMgbWFudWFsbHkuCgpgYGB7cn0KZGZfZjExICU+JSAKICByZW5hbWUoIXllYXIsIFVTX2JvdDUwID0gVVNib3Q1MCwgVVNfdG9wMSA9IFVTdG9wMSwgRVVfYm90NTAgPSBFVWJvdDUwLCBFVV90b3AxID0gRVV0b3AxKSAlPiUKICBwaXZvdF9sb25nZXIoIXllYXIsIG5hbWVzX3RvID0gYygiZ3JvdXAiLCIudmFsdWUiKSwgbmFtZXNfc2VwID0gIl8iKSAlPiUKICBwaXZvdF9sb25nZXIoMzo0LCBuYW1lc190byA9ICJ0eXBlIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc21vb3RoKGFlcyh4ID0geWVhciwgeSA9IHZhbHVlLCBjb2xvciA9IGdyb3VwLCBsaW5ldHlwZSA9IHR5cGUpLCAKICAgICAgICAgICAgICBmb3JtdWxhID0geX54LCBtZXRob2QgPSAibG9lc3MiLAogICAgICAgICAgICAgIHNwYW4gPSAwLjUsIHNlID0gRkFMU0UpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gcm91bmQoc2VxKDE5MTAsIDIwMjAsIGJ5ID0gMTApLDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDExLiBUb3AgMSUgdnMgYm90dG9tIDUwJSB3ZWFsdGggc2hhcmVzIFxuIGluIFdlc3Rlcm4gRXVyb3BlIGFuZCB0aGUgVVMsIDE5MTAtMjAyMCIsIAogICAgICAgeCA9ICIiLCB5ID0gIlNoYXJlIG9mIHRvdGFsIHBlcnNvbmFsIHdlYWx0aCAoJSkiLCBjb2xvciA9ICIiLCBsaW5ldHlwZSA9ICIiKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoImRvdHRlZCIsInNvbGlkIikpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSAyMDAwLCB5ID0gMC41MCwgbGFiZWwgPSBzdHJpbmdyOjpzdHJfd3JhcCgiV2VhbHRoIGluZXF1YWxpdHkgaGFzIGJlZW4gcmlzaW5nIGF0IGRpZmZlcmVudCBzcGVlZHMgYWZ0ZXIgYSBoaXN0b3JpY2FsIGRlY2xpbmUuIFRoZSBib3R0b20gNTAlIGhhcyBhbHdheXMgYmVlbiBleHRyZW1lbHkgbG93LiIsIHdpZHRoID0gMzApLCBzaXplID0gMykKYGBgCgojIyMgRjEyOiBGZW1hbGUgc2hhcmUgaW4gZ2xvYmFsIGxhYm9yIGluY29tZXMsIDE5OTAtMjAyMAoKYGBge3IgZGF0YS1mMTIsIGNhc2ggPSBUUlVFfQpkZl9mMTIgPC0gcmVhZF9leGNlbCgiLi9kYXRhL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeCIsIHNoZWV0ID0gImRhdGEtRjEyIikKZGZfZjEyCmBgYAoKYGBge3J9CmRmX2YxMiAlPiUgCiAgc2VsZWN0KHllYXIgPSAiRGF0YSBuZWVkcyB0byBiZSB1cGRhdGVkIiwgdmFsdWUgPSAuLi4yKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHllYXIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUpKSArCiAgZ2VvbV9jb2wod2lkdGggPSAwLjUsIGZpbGwgPSBzY2FsZXM6Omh1ZV9wYWwoKSgyKVsyXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAuNSwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSBzY2FsZXM6Omh1ZV9wYWwoKSgyKVsxXSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSAxMi4gRmVtYWxlIHNoYXJlIGluIGdsb2JhbCBsYWJvciBpbmNvbWVzLCAxOTkwLTIwMjAiLCAKICAgICAgICB4ID0gIiIsIHkgPSAiIikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDEsIHkgPSAwLjQ4LCBsYWJlbCA9ICJHZW5kZXIgcGFyaXR5Iiwgc2l6ZSA9IDMpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSA1LjIsIHkgPSAwLjQ3LCBsYWJlbCA9IHN0cmluZ3I6OnN0cl93cmFwKCJXb21lbiBtYWtlIG9ubHkgMzUlIG9mIGdsb2JhbCBsYWJvciBpbmNvbWVzLCBtZW4gbWFrZSB0aGUgcmVtYWluaW5nICA2NSUuIiwgd2lkdGggPSA0MCksIHNpemUgPSAzKQpgYGAKKipJbnRlcnByZXRhdGlvbioqOiBUaGUgc2hhcmUgb2YgZmVtYWxlIGluY29tZXMgaW4gZ2xvYmFsIGxhYm91ciBpbmNvbWVzIHdhcyAzMSUgaW4gMTk5MCBhbmQgbmVhcnMgMzUlIGluIDIwMTUtMjAyMC4gVG9kYXksIG1hbGVzIG1ha2UgdXAgNjUlIG9mIHRvdGFsIGxhYm9yIGluY29tZXMuIFNvdXJjZXMgYW5kIHNlcmllczogd2lyMjAyMi53aWQud29ybGQvbWV0aG9kb2xvZ3kgYW5kIE5lZWYgYW5kIFJvYmlsbGlhcmQgKDIwMjEpLgoKIyMjIyBFeHBsYW5hdGlvbgoKIyMjIyMgU3RlcCAxLgoKQ2hhbmdlIHRoZSBjb2x1bW4gbmFtZXMgYW5kIGRlbGV0ZSB0aGUgcm93cyB3aXRoIE5Bcy4KCmBgYHtyfQpkZl9mMTIgJT4lIAogIHNlbGVjdCh5ZWFyID0gIkRhdGEgbmVlZHMgdG8gYmUgdXBkYXRlZCIsIHZhbHVlID0gLi4uMikgJT4lCiAgZmlsdGVyKCFpcy5uYSh5ZWFyKSkKYGBgCgojIyMjIyBTdGVwIDIuCgpBZGQgYGdlb21fY29sYCBhbmQgIGBnZW9tX2hsaW5lYCB3aXRoIGNvbG9ycyBgc2NhbGVzOjpodWVfcGFsKCkoMilbMl1gIGFuZCBgc2NhbGVzOjpodWVfcGFsKCkoMilbMV1gLgoKYGBge3J9CmRmX2YxMiAlPiUgCiAgc2VsZWN0KHllYXIgPSAiRGF0YSBuZWVkcyB0byBiZSB1cGRhdGVkIiwgdmFsdWUgPSAuLi4yKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHllYXIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUpKSArCiAgZ2VvbV9jb2wod2lkdGggPSAwLjUsIGZpbGwgPSBzY2FsZXM6Omh1ZV9wYWwoKSgyKVsyXSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAuNSwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSBzY2FsZXM6Omh1ZV9wYWwoKSgyKVsxXSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSAxMi4gRmVtYWxlIHNoYXJlIGluIGdsb2JhbCBsYWJvciBpbmNvbWVzLCAxOTkwLTIwMjAiLCAKICAgICAgICB4ID0gIiIsIHkgPSAiIikgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDEsIHkgPSAwLjQ4LCBsYWJlbCA9ICJHZW5kZXIgcGFyaXR5Iiwgc2l6ZSA9IDMpICsKICBhbm5vdGF0ZSgidGV4dCIsIHggPSA1LjIsIHkgPSAwLjQ3LCBsYWJlbCA9IHN0cmluZ3I6OnN0cl93cmFwKCJXb21lbiBtYWtlIG9ubHkgMzUlIG9mIGdsb2JhbCBsYWJvciBpbmNvbWVzLCBtZW4gbWFrZSB0aGUgcmVtYWluaW5nICA2NSUuIiwgd2lkdGggPSA0MCksIHNpemUgPSAzKQpgYGAKCiMjIyBGMTM6IEZlbWFsZSBsYWJvciBpbmNvbWUgc2hhcmUgYWNyb3NzIHRoZSB3b3JsZCwgMTk5MC0yMDIwCgpOb3RlIHRoYXQgdGhlIHNoZWV0IG5hbWUgb2YgRjEzIGhhcyBwZXJpb2QgYXQgdGhlIGVuZC4gTm90ZSB0aGF0IGBzdW1tYXJ5X3NoZWV0c1szMF0gPSBgYHIgc3VtbWFyeV9zaGVldHNbMzBdYCB3aXRoIGEgcGVyaW9kLgoKYGBge3IgZGF0YS1mMTMsIGNhc2ggPSBUUlVFfQpkZl9mMTMgPC0gcmVhZF9leGNlbCgiLi9kYXRhL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeCIsIHNoZWV0ID0gImRhdGEtRjEzLiIpCmRmX2YxMwpgYGAKCmBgYHtyfQpkZl9mMTMgJT4lIHBpdm90X2xvbmdlcigyOjksIG5hbWVzX3RvID0gInJlZ2lvbiIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JQogIGdncGxvdChhZXMoeCA9IHJlZ2lvbiwgeSA9IHZhbHVlLCBmaWxsID0gLi4uMSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC41LCBsaW5ldHlwZSA9IDIsIGNvbG91ciA9ICJyZWQiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBmdW5jdGlvbih4KSBzdHJpbmdyOjpzdHJfd3JhcCh4LCB3aWR0aCA9IDEyKSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSAxMy4gRmVtYWxlIGxhYm9yIGluY29tZSBzaGFyZSBhY3Jvc3MgdGhlIHdvcmxkLCAxOTkwLTIwMjAiLCAKICAgICAgICB4ID0gIiIsIHkgPSAiIiwgZmlsbCA9ICIiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMS4yLCB5ID0gMC40OCwgbGFiZWwgPSAiR2VuZGVyIHBhcml0eSIsIHNpemUgPSAzKQpgYGAKKipJbnRlcnByZXRhdGlvbioqOiBUaGUgZmVtYWxlIGxhYm91ciBpbmNvbWUgc2hhcmUgcm9zZSBmcm9tIDM0JSB0byAzOCUgaW4gTm9ydGggQW1lcmljYSBiZXR3ZWVuIDE5OTAgYW5kIDIwMjAuIFNvdXJjZXMgYW5kIHNlcmllczogd2lyMjAyMi53aWQud29ybGQvbWV0aG9kb2xvZ3kgYW5kIE5lZWYgYW5kIFJvYmlsbGlhcmQgKDIwMjEpLgoKIyMjIyBFeHBsYW5hdGlvbgoKTm90IHNvIGRpZmZpY3VsdC4KCiMjIyBGMTQ6IEdsb2JhbCBjYXJib24gaW5lcXVhbGl0eSwgMjAxOS4gR3JvdXAgY29udHJpYnV0aW9uIHRvIHdvcmxkIGVtaXNzaW9ucyAoJSkKCk5vdGUgdGhhdCB0aGUgc2hlZXQgbmFtZSBvZiBGMTQgaGFzIHBlcmlvZCBhdCB0aGUgZW5kLiBOb3RlIHRoYXQgYHN1bW1hcnlfc2hlZXRzWzMxXSA9IGBgciBzdW1tYXJ5X3NoZWV0c1szMV1gIHdpdGggYSBwZXJpb2QuCgpgYGB7ciBkYXRhLWYxNCwgY2FzaCA9IFRSVUV9CmRmX2YxNCA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtU3VtbWFyeS54bHN4Iiwgc2hlZXQgPSAiZGF0YS1GMTQuIikKZGZfZjE0CmBgYAoKKiBgXG5gIGZvciBsaW5lIGJyZWFrIGluIHRoZSB0aXRsZS4KCmBgYHtyfQpkZl9mMTQgJT4lIAogIGdncGxvdChhZXMoeCA9IEdyb3VwLCB5ID0gU2hhcmUpKSArCiAgZ2VvbV9jb2wod2lkdGggPSAwLjUsIGZpbGwgPSBzY2FsZXM6Omh1ZV9wYWwoKSgxKVsxXSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMTQuIEdsb2JhbCBjYXJib24gaW5lcXVhbGl0eSwgXG4yMDE5IEdyb3VwIGNvbnRyaWJ1dGlvbiB0byB3b3JsZCBlbWlzc2lvbnMgKCUpIiwgCiAgICAgICB4ID0gIiIsIHkgPSAiU2hhcmUgb2Ygd29ybGQgZW1pc3Npb25zICglKSIpCmBgYAoKKipJbnRlcnByZXRhdGlvbioqOiBQZXJzb25hbCBjYXJib24gZm9vdHByaW50cyBpbmNsdWRlIGVtaXNzaW9ucyBmcm9tIGRvbWVzdGljIGNvbnN1bXB0aW9uLCBwdWJsaWMgYW5kIHByaXZhdGUgaW52ZXN0bWVudHMgYXMgd2VsbCBhcyBpbXBvcnRzIGFuZCBleHBvcnRzIG9mIGNhcmJvbiBlbWJlZGRlZCBpbiBnb29kcyBhbmQgc2VydmljZXMgdHJhZGVkIHdpdGggdGhlIHJlc3Qgb2YgdGhlIHdvcmxkLiBNb2RlbGVkIGVzdGltYXRlcyBiYXNlZCBvbiB0aGUgc3lzdGVtYXRpYyBjb21iaW5hdGlvbiBvZiB0YXggZGF0YSwgaG91c2Vob2xkIHN1cnZleXMgYW5kIGlucHV0LW91dHB1dCB0YWJsZXMuIEVtaXNzaW9ucyBzcGxpdCBlcXVhbGx5IHdpdGhpbiBob3VzZWhvbGRzLiBTb3VyY2VzIGFuZCBzZXJpZXM6IHdpcjIwMjIud2lkLndvcmxkL21ldGhvZG9sb2d5IGFuZCBDaGFuY2VsICgyMDIxKS4KCiMjIyMgRXhwbGFuYXRpb24KCk5vdCBzbyBkaWZmaWN1bHQuIFlvdSBjYW4gYXNzaWduIGNvbG9yIG5hbWUuIFNlZSBodHRwOi8vd3d3LmNvb2tib29rLXIuY29tL0dyYXBocy9Db2xvcnNfKGdncGxvdDIpLy4KCiMjIyBGMTU6IFBlciBjYXBpdGEgZW1pc3Npb25zIGFjcmlzcyB0aGUgd29ybGQsIDIwMTkKCmBgYHtyIGRhdGEtZjE1LCBjYXNoID0gVFJVRX0KZGZfZjE1IDwtIHJlYWRfZXhjZWwoIi4vZGF0YS9XSVIyMDIyVGFibGVzRmlndXJlcy1TdW1tYXJ5Lnhsc3giLCBzaGVldCA9ICJkYXRhLUYxNSIpCmRmX2YxNQpgYGAKYGBge3J9CmRmX2YxNSAlPiUgbXV0YXRlKHJlZ2lvbiA9IHJlcChyZWdpb25XSURbIWlzLm5hKHJlZ2lvbldJRCldLCBlYWNoID0gMykpICU+JQogIHNlbGVjdChyZWdpb24sIGdyb3VwLCB0Y2FwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSByZWdpb24sIHkgPSB0Y2FwLCBmaWxsID0gZ3JvdXApKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArIAogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgc3RyaW5ncjo6c3RyX3dyYXAoeCwgd2lkdGggPSAxMCkpICsKICBsYWJzKHRpdGxlID0gIkZpZ3VyZSAxNSBQZXIgY2FwaXRhIGVtaXNzaW9ucyBhY3Jvc3MgdGhlIHdvcmxkLCAyMDE5IiwgCiAgICAgICB4ID0gIiIsIHkgPSAidG9ubmVzIG9mIENPMmUgcGVyIHBlcnNvbiBwZXIgeWVhciIsIGZpbGwgPSAiIikKYGBgCioqSW50ZXJwcmV0YXRpb24qKjogUGVyc29uYWwgY2FyYm9uIGZvb3RwcmludHMgaW5jbHVkZSBlbWlzc2lvbnMgZnJvbSBkb21lc3RpYyBjb25zdW1wdGlvbiwgcHVibGljIGFuZCBwcml2YXRlIGludmVzdG1lbnRzIGFzIHdlbGwgYXMgaW1wb3J0cyBhbmQgZXhwb3J0cyBvZiBjYXJib24gZW1iZWRkZWQgaW4gZ29vZHMgYW5kIHNlcnZpY2VzIHRyYWRlZCB3aXRoIHRoZSByZXN0IG9mIHRoZSB3b3JsZC4gTW9kZWxlZCBlc3RpbWF0ZXMgYmFzZWQgb24gdGhlIHN5c3RlbWF0aWMgY29tYmluYXRpb24gb2YgdGF4IGRhdGEsIGhvdXNlaG9sZCBzdXJ2ZXlzIGFuZCBpbnB1dC1vdXRwdXQgdGFibGVzLiBFbWlzc2lvbnMgc3BsaXQgZXF1YWxseSB3aXRoaW4gaG91c2Vob2xkcy4gU291cmNlcyBhbmQgc2VyaWVzOiB3aXIyMDIyLndpZC53b3JsZC9tZXRob2RvbG9neSBhbmQgQ2hhbmNlbCAoMjAyMSkuCgojIyMjIEV4cGxhbmF0aW9uCgojIyMjIyBTdGVwIDEuIAoKSXQgaXMgaW4gRXhjZWwgc3R5cGUgYW5kIHRoZXJlIGFyZSBtaXNzaW5nIHZhbHVlcyBpbiB0aGUgZmlyc3QgY29sdW1uLiBJbiBvcmRlciB0byBhZGQgYSBuZXcgY29sdW1uLCBsZXQgdXMgY2hlY2sgdGhlIGZvbGxvd2luZy4KCmBgYHtyfQpyZWdpb25fdGVzdCA8LSByZXAoZGZfZjE1JHJlZ2lvbldJRFshaXMubmEoZGZfZjE1JHJlZ2lvbldJRCldLCBlYWNoID0gMykKcmVnaW9uX3Rlc3QKYGBgCgojIyMjIyBTdGVwIDIuCgpBZGQgdGhlIG5hbWVzIG9mIHRoZSByZWdpb24gaW4gdGhlIGxhc3QgY29sdW1uIGJ5IGBtdXRhdGVgIGFuZCBjaG9vc2UgY29sdW1ucyBieSBgc2VsZWN0YC4KCmBgYHtyfQpkZl9mMTUgJT4lIG11dGF0ZShyZWdpb24gPSByZXAocmVnaW9uV0lEWyFpcy5uYShyZWdpb25XSUQpXSwgZWFjaCA9IDMpKQpgYGAKCmBgYHtyfQpkZl9mMTUgJT4lIG11dGF0ZShyZWdpb24gPSByZXAocmVnaW9uV0lEWyFpcy5uYShyZWdpb25XSUQpXSwgZWFjaCA9IDMpKSAlPiUKICBzZWxlY3QocmVnaW9uLCBncm91cCwgdGNhcCkKYGBgCgojIyMjIyBTdGVwIDMuCgpOb3cgaXQgaXMgbm90IGRpZmZpY3VsdCB0byBkcmF3IGEgY2hhcnQuCgpgYGB7cn0KZGZfZjE1ICU+JSBtdXRhdGUocmVnaW9uID0gcmVwKHJlZ2lvbldJRFshaXMubmEocmVnaW9uV0lEKV0sIGVhY2ggPSAzKSkgJT4lCiAgc2VsZWN0KHJlZ2lvbiwgZ3JvdXAsIHRjYXApICU+JQogIGdncGxvdChhZXMoeCA9IHJlZ2lvbiwgeSA9IHRjYXAsIGZpbGwgPSBncm91cCkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsgCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBmdW5jdGlvbih4KSBzdHJpbmdyOjpzdHJfd3JhcCh4LCB3aWR0aCA9IDEwKSkgKwogIGxhYnModGl0bGUgPSAiRmlndXJlIDE1IFBlciBjYXBpdGEgZW1pc3Npb25zIGFjcm9zcyB0aGUgd29ybGQsIDIwMTkiLCAKICAgICAgIHggPSAiIiwgeSA9ICJ0b25uZXMgb2YgQ08yZSBwZXIgcGVyc29uIHBlciB5ZWFyIiwgZmlsbCA9ICIiKQpgYGAKCiMjIyBUMSBHbG9iYWwgbWlsbGlvbmFpcmVzIGFuZCBiaWxsaW9uYWlyZXMsIDIwMjEKCkNoZWNrIHRoZSBmb3JtYXQgb2YgdGhlIHNoZWV0IGFuZCBhZGQgYHNraXA9NCwgbl9tYXg9N2AuCgpgYGB7ciBUMX0KZGZfdDEgPC0gcmVhZF9leGNlbCgiLi9kYXRhL1dJUjIwMjJUYWJsZXNGaWd1cmVzLVN1bW1hcnkueGxzeCIsIAogICAgICAgICAgICAgICAgICAgIHNoZWV0ID0gIlQxIiwgc2tpcCA9IDQsIG5fbWF4ID0gNykKZGZfdDEKYGBgCioqSW50ZXJwcmV0YXRpb24qKjogSW4gMjAyMSwgdGhlcmUgd2VyZSA2Mi4yIG1pbGxpb24gcGVvcGxlIGluIHRoZSB3b3JsZCBvd25pbmcgbW9yZSB0aGFuICQxIG1pbGxpb24gKG1lYXN1cmVkIGF0IE1hcmtldCBFeGNoYW5nZSBSYXRlcykuIFRoZWlyIGF2ZXJhZ2Ugd2VhbHRoIHdhcyAkIDIuOCBtaWxsaW9uLCByZXByZXNlbnRpbmcgYSB0b3RhbCBvZiAgJDE3NCB0cmlsbGlvbi4gSW4gb3VyIFRheCBzY2VuYXJpbyAyLCBhIGdsb2JhbCBwcm9ncmVzc2l2ZSB3ZWFsdGggdGF4IHdvdWxkIHlpZWxkIDIuMSUgb2YgZ2xvYmFsIGluY29tZSwgdGFraW5nIGludG8gYWNjb3VudCBjYXBpdGFsIGRlcHJlY2lhdGlvbiBhbmQgZXZhc2lvbi4gU291cmNlcyBhbmQgc2VyaWVzOiB3aXIyMDIyLndpZC53b3JsZC9tZXRob2RvbG9neS4KCiMgT3RoZXIgRGF0YSBvZiBXSVIyMDIyCgojIyBEYXRhIFVzZWQgaW4gQ2hhcHRlciAxIHRvIENoYXB0ZXIgMTAKClRoZXJlIGFyZSB0aHJlZSB3YXlzIHRvIGltcG9ydCBkYXRhIHVzZWQgaW4gQ2hhcHRlciAxIHRvIENoYXB0ZXIgMTAuCgojIyMgVXNlIHRoZSBsaW5rIHRvIGRvd25sb2FkIHRoZSBkYXRhLgoKMS4gR28gdG8gdGhlIE1ldGhvZG9sb2d5IHNpdGU6IGh0dHBzOi8vd2lyMjAyMi53aWQud29ybGQvbWV0aG9kb2xvZ3kvCgoyLiBDb3B5IHRoZSBsaW5rIHRvIERhdGFzZXQgMiwgaS5lLiwgdGhlIGRhdGFzZXRzIG9mIGNoYXB0ZXJzIDEgdG8gMTAuCgpgYGB7ciBldmFsID0gRkFMU0V9CnVybF93aXIxdG8xMCA8LSAiaHR0cHM6Ly93aXIyMDIyLndpZC53b3JsZC93d3ctc2l0ZS91cGxvYWRzLzIwMjIvMDMvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtQ2hhcHRlci56aXAiCmBgYAoKMy4gRG93bmxvYWQgdGhlIGRhdGEgaW4geW91ciBkYXRhIGZvbGRlci4KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZG93bmxvYWQuZmlsZSh1cmxfd2lyMXRvMTAsIGRlc3RmaWxlID0gIi4vZGF0YS93aXIxdG8xMC56aXAiLCBtb2RlID0gIndiIikKYGBgCjMuIFVuemlwIHRoZSBmaWxlLgoKYGBge3IgZXZhbCA9IEZBTFNFfQp1bnppcCgiLi9kYXRhL3dpcjF0bzEwLnppcCIsIGV4ZGlyID0gIi4vZGF0YSIpCmBgYAoKCiogRG93bmxvYWQgdGhlIGRhdGEgZnJvbSB0aGUgZm9sbG93aW5nIHNpdGUuCiAgLSBNZXRob2RvbG9neTogaHR0cHM6Ly93aXIyMDIyLndpZC53b3JsZC9tZXRob2RvbG9neS8KICAKNC4gQ2hlY2sgdGhlIGZpbGUgbmFtZXMgYW5kIGNoZWNrIHRoZSBzaGVldCBuYW1lcy4KCmBgYHtyIGV2YWwgPSBGQUxTRX0KbGlzdC5maWxlcygiLi9kYXRhL1dJUjIwMjJUYWJsZXNGaWd1cmVzLUNoYXB0ZXIiKQpgYGAKCmBgYHtyIGV2YWwgPSBGQUxTRX0KZXhjZWxfc2hlZXRzKCIuL2RhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtQ2hhcHRlci9XSVIyMDIyVGFibGVzRmlndXJlcy1DaGFwdGVyMS54bHN4IikKYGBgCgo1LiBJbXBvcnQgdGhlIGRhdGEgdGFibGUuCgpgYGB7ciBldmFsID0gRkFMU0V9Cndpcl9GMS4wIDwtIHJlYWRfZXhjZWwoIi4vZGF0YS9XSVIyMDIyVGFibGVzRmlndXJlcy1DaGFwdGVyL1dJUjIwMjJUYWJsZXNGaWd1cmVzLUNoYXB0ZXIxLnhsc3giLCBzaGVldCA9ICJkYXRhLUYxLjAiKQp3aXJfRjEuMApgYGAKCjYuIFNlbGVjdCB0aGUgcmFuZ2UgYnkgc2xpY2Ugb3IgdXNlIHJhbmdlIG9wdGlvbi4KCmBgYHtyIGV2YWwgPSBGQUxTRX0Kd2lyX0YxLjAgPC0gd2lyX0YxLjAgJT4lIHNsaWNlKDE6MikKd2lyX0YxLjAKYGBgCgpgYGB7ciBldmFsID0gRkFMU0V9Cndpcl9GMS4wYSA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtQ2hhcHRlci9XSVIyMDIyVGFibGVzRmlndXJlcy1DaGFwdGVyMS54bHN4Iiwgc2hlZXQgPSAiZGF0YS1GMS4wIiwgcmFuZ2UgPSAiQTI6RTQiKQp3aXJfRjEuMGEKYGBgCgpgYGB7ciBldmFsID0gRkFMU0V9Cndpcl9GMS4wYiA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvV0lSMjAyMlRhYmxlc0ZpZ3VyZXMtQ2hhcHRlci9XSVIyMDIyVGFibGVzRmlndXJlcy1DaGFwdGVyMS54bHN4Iiwgc2hlZXQgPSAiZGF0YS1GMS4wIiwgcmFuZ2UgPSAiQTc6RTkiKQp3aXJfRjEuMGIKYGBgCiMjIyBEb3dubG9hZCB0aGUgemlwIGZpbGUgYW5kIG1vdmUgdG8geW91IGRhdGEgZm9sZGVyCgoxLiBHbyB0byB0aGUgTWV0aG9kb2xvZ3kgc2l0ZTogaHR0cHM6Ly93aXIyMDIyLndpZC53b3JsZC9tZXRob2RvbG9neS8KCjIuIERvdWJsZSBjbGljayB0aGUgZG93bmxvYWQgbGluayB1bmRlciBEYXRhc2V0IDIsIGkuZS4sIHRoZSBkYXRhc2V0cyBvZiBjaGFwdGVycyAxIHRvIDEwIHRvIGRvdW5sb2FkIHRoZSB6aXAgZmlsZS4KCjMuIFVuemlwIHRoZSBmaWxlIHVzaW5nIHRoZSBoZWxwZXIgYXBwbGljYXRpb24gb2YgeW91ciBQQy4gSW4gbW9zdCBjYXNlcywgaWYgeW91IGRvdWJsZSBjbGljayB0aGUgemlwIGZpbGUsIHlvdSBjYW4gZ2V0IGEgZm9sZGVyIGNvbnRhaW5pbmcgRXhjZWwgZmlsZXMuCgo0LiBNb3ZlIHRvIHlvdXIgZGF0YSBmb2xkZXIgYW5kIGZvbGxvdyB0aGUgbGluZSBhYm92ZSBvZiB0aGUgcHJldmlvdXMgbWV0aG9kLgoKIyMjIFVzZSBjb3B5aW5nIGFuZCBwYXN0aW5nCgpTaW5jZSB0aGUgdGFibGUgc3RydWN0dXJlIG9mIEV4Y2VsIGlzIGNvbXBsaWNhdGVkLCBpdCBtYXkgYmUgbXVjaCBlYXNpZXIgdG8gY29weSBhbmQgcGFzdGUgdGhlIHJhbmdlIHlvdSB3YW50IHRvIHVzZS4gSW4gdGhpcyBjYXNlIGtlZXAgdGhlIHJlY29yZCBvZiB0aGUgZGF0YSBzbyB0aGF0IHRoZSBtZXRob2QgaXMgcmVwcm9kdWNpYmxlLiAKCmBgYHtyIGV2YWw9RkFMU0V9CiMgQ29weSB0aGUgcmFuZ2Ugb2YgYW4gRXhjZWwgc2hlZXQgaW50byB5b3VyIGNsaXBib2FyZAp3aXJfRjEuMGMgPC0gcmVhZF9kZWxpbShjbGlwYm9hcmQoKSkKYGBgCgoKCiMjIFBhY2thZ2U6IGB3aWRgIHRvIERvd25sb2FkIERhdGEgeyN3aXItZC10b29sfQoKSW4gdGhlIGZvbGxvd2luZywgd2UgZXhwbGFpbiBob3cgdG8gZG93bmxvYWQgZGF0YSBieSBhbiBSIHBhY2thZ2UgYHdpZC1yLXRvb2xgLiBGaXJzdCwgeW91IG5lZWQgdG8gaW5zdGFsbCB0aGUgcGFja2FnZS4gVGhlIGB3aWQtci10b29sYCBpcyBhIHBhY2thZ2UgaW4gdGhlIGRldmVsb3BtZW50IHN0YWdlOyBpdCBpcyBub3QgYW4gb2ZmaWNpYWwgUiBwYWNrYWdlIHlldDsgeW91IG5lZWQgdG8gdXNlIHRoZSBwYWNrYWdlIGBkZXZ0b29sc2AgdG8gaW5zdGFsbCBpdC4KClRvIGluc3RhbGwsIHJ1biB0aGUgZm9sbG93aW5nIGNvZGUgb3IgaW4gQ29uc29sZS4gSWYgeW91IGFyZSByZWNvbW1lbmRlZCB0byB1cGRhdGUsIHNlbGVjdCBvbmUgYnkgY2hvb3NpbmcgJ0FsbCcuCgpgYGB7ciBldmFsPUZBTFNFfQppbnN0YWxsLnBhY2thZ2VzKCJkZXZ0b29scyIpCmRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiV0lEd29ybGQvd2lkLXItdG9vbCIpCmBgYAoKRm9yIHJlZmVyZW5jZXMgdXNlICc/ZG93bmxvYWRfd2lkJyBvciBwdXQgJ2Rvd25sb2FkX3dpZCcgaW4gdGhlIHNlYXJjaCBib3ggdW5kZXIgSGVscC4KCkl0IGlzIHNpbWlsYXIgdG8gYFdESWAuIEZvciBtb3JlIGRldGFpbCBhbmQgZXhhbXBsZXMsIHNlZSBbdmlnbmV0dGVzXShodHRwczovL2RzLXNsLmdpdGh1Yi5pby9kYXRhLWFuYWx5c2lzL3dpcl9kb3dubG9hZC5wZGYpLgoKRm9yIGluZGljYXRvcnMgb2YgV0lSLCBzZWUgW2NvZGVib29rXShodHRwczovL3dpZC53b3JsZC9jb2Rlcy1kaWN0aW9uYXJ5KS4KCgpgYGB7cn0KbGlicmFyeSgid2lkIikKYGBgCgojIyMgRXhhbXBsZXMKCiMjIyMgRXZvbHV0aW9uIG9mIG5hdGlvbmFsIGluY29tZSBvdmVyIGxvbmcgcGVyaW9kCgpUaGlzIGV4YW1wbGUgaXMgZXNzZW50aWFsbHkgdGhlIHNhbWUgYXMgaW4gdGhlIHZpZ25ldHRlcy4KCiogV2Ugbm93IHBsb3QgdGhlIGV2b2x1dGlvbiBvZiBhdmVyYWdlIG5ldCBuYXRpb25hbCBpbmNvbWUgcGVyIGFkdWx0IGluIEphcGFuLCBGcmFuY2UsIEdlcm1hbnksIHRoZSBVbml0ZWQgS2luZ2RvbSBhbmQgdGhlIFVuaXRlZCBTdGF0ZXMuCgpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcuaGVpZ2h0PTQsIGNhY2hlPVRSVUV9CiMgQXZlcmFnZSBuYXRpb25hbCBpbmNvbWUgZGF0YQpkYXRhIDwtIGRvd25sb2FkX3dpZCgKICAgIGluZGljYXRvcnMgPSAiYW5uaW5jIiwgIyBBdmVyYWdlIG5ldCBuYXRpb25hbCBpbmNvbWUKICAgIGFyZWFzID0gYygiSlAiLCAiRlIiLCAiVVMiLCAiREUiLCAiR0IiKSwKICAgIGFnZXMgPSA5OTIgIyBBZHVsdHMKKSAlPiUgcmVuYW1lKHZhbHVlX2xjdSA9IHZhbHVlKQojIFB1cmNoYXNpbmcgcG93ZXIgcGFyaXRpZXMgd2l0aCBVUyBkb2xsYXIKcHBwIDwtIGRvd25sb2FkX3dpZCgKICAgIGluZGljYXRvcnMgPSAieGxjdXNwIiwgIyBVUyBQUFAKICAgIGFyZWFzID0gYygiSlAiLCAiRlIiLCAiVVMiLCAiREUiLCAiR0IiKSwgIyBGcmFuY2UsIENoaW5hIGFuZCBVbml0ZWQgU3RhdGVzCiAgICB5ZWFyID0gMjAxNiAjIFJlZmVyZW5jZSB5ZWFyIG9ubHkKKSAlPiUgcmVuYW1lKHBwcCA9IHZhbHVlKSAlPiUgc2VsZWN0KC15ZWFyLCAtcGVyY2VudGlsZSkKIyBDb252ZXJ0IGZyb20gbG9jYWwgY3VycmVuY3kgdG8gUFBQIFVTIGRvbGxhcgpkYXRhIDwtIG1lcmdlKGRhdGEsIHBwcCwgYnkgPSAiY291bnRyeSIpICU+JQogICAgbXV0YXRlKHZhbHVlX3BwcCA9IHZhbHVlX2xjdS9wcHApICU+JQogICAgZmlsdGVyKHllYXIgJWluJSAxOTUwOjIwMjEpCmdncGxvdChkYXRhKSArCiAgICBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWVfcHBwLCBjb2xvciA9IGNvdW50cnksIGxpbmV0eXBlPWNvdW50cnkpKSArCiAgICBzY2FsZV95X2xvZzEwKGJyZWFrcyA9IGMoMmUzLCA1ZTMsIDFlNCwgMmU0LCA1ZTQpKSArCiAgICB5bGFiKCIyMDE2ICQgUFBQIikgKwogICAgc2NhbGVfY29sb3JfZGlzY3JldGUoCiAgICAgICAgbGFiZWxzID0gYygiSlAiID0gIkphcGFuIiwgIlVTIiA9ICJVU0EiLCAiRlIiID0gIkZyYW5jZSIsICJERSIgPSAiR2VybWFueSIsICJHQiIgPSAiVUsiKQogICAgKSArIAogICAgc2NhbGVfbGluZXR5cGVfZGlzY3JldGUoCiAgICAgICAgbGFiZWxzID0gYygiSlAiID0gIkphcGFuIiwgIlVTIiA9ICJVU0EiLCAiRlIiID0gIkZyYW5jZSIsICJERSIgPSAiR2VybWFueSIsICJHQiIgPSAiVUsiKQogICAgKSArIAogICAgZ2d0aXRsZSgiQXZlcmFnZSBuZXQgbmF0aW9uYWwgaW5jb21lIHBlciBhZHVsdCIpCmBgYAoKIyMjIyBgd2VhbGdgIGFuZCBgd2VhbHBgCgoqIEFmdGVyIGluc3RhbGxpbmcgdGhlIHBhY2thZ2UsIGNoZWNrIHRoZSBbY29kZWJvb2tdKGh0dHBzOi8vd2lkLndvcmxkL2NvZGVzLWRpY3Rpb25hcnkpIG9mIHRoZSBpbmRpY2F0b3JzLgoqIFRoZSB3aXIgaW5kaWNhdG9yIGlzIGEgY29tYmluYXRpb24gb2Ygb25lIGFscGhhYmV0IGFuZCBmaXZlIGFscGhhYmV0cy4gU2VlIHRoZSBjb2RlYm9vayBhYm92ZS4KCldlIHVzZSB0aGUgZm9sb3dpbmcgdHdvIGluZGljYXRvcnMuCgoqIHcJd2VhbHRoLXRvLWluY29tZSByYXRpbyBvciBsYWJvci9jYXBpdGFsIHNoYXJlCWZyYWN0aW9uIG9mIG5hdGlvbmFsIGluY29tZQoqIHdlYWxnOiBuZXQgcHVibGljIHdlYWx0aCB0byBuZXQgbmF0aW9uYWwgaW5jb21lIHJhdGlvCiogd2VhbHA6IG5ldCBwcml2YXRlIHdlYWx0aCB0byBuZXQgbmF0aW9uYWwgaW5jb21lIHJhdGlvCgojIyMjIyBTdGVwIDEuIAoKKiBJbXBvcnRpbmcgdGhlIGRhdGEgdXNpbmcgYGRvd25sb2FkX3dpZGAuCgpgYGB7cn0KbGlicmFyeSh3aWQpCnd3ZWFsZyA8LSBkb3dubG9hZF93aWQoaW5kaWNhdG9ycyA9ICJ3d2VhbGciLCBhcmVhcyA9ICJhbGwiLCB5ZWFycyA9ICJhbGwiKQp3d2VhbHAgPC0gZG93bmxvYWRfd2lkKGluZGljYXRvcnMgPSAid3dlYWxwIiwgYXJlYXMgPSAiYWxsIiwgeWVhcnMgPSAiYWxsIikKYGBgCgpgYGB7cn0KcHVibGljIDwtIHd3ZWFsZyAlPiUgc2VsZWN0KGNvdW50cnksIHllYXIsIHB1YmxpYyA9IHZhbHVlKQpwdWJsaWMKYGBgCgpgYGB7cn0KcHJpdmF0ZSA8LSB3d2VhbHAgJT4lIHNlbGVjdChjb3VudHJ5LCB5ZWFyLCBwcml2YXRlID0gdmFsdWUpCnByaXZhdGUKYGBgCgojIyMjIyBTdGVwIDIuCgoqQ29tYmluZSB0d28gdGFibGVzLiAKCgpgYGB7cn0KcHVibGljX3ZzX3ByaXZhdGUgPC0gcHVibGljICU+JSBsZWZ0X2pvaW4ocHJpdmF0ZSkKcHVibGljX3ZzX3ByaXZhdGUKYGBgCgojIyMjIyBTdGVwIDMuCgoqIFRvIGFkZCBjb3VudHJ5IG5hbWVzLCB1c2UgdGhlIFdESSBkYXRhLgoKKiBXZSB1c2UgYSBwYWNrYWdlIGBXRElgIHRvIHVzZSBgV0RJY2FjaGUoKWAgYXMgYSByZWZlcmVuY2UuCgpgYGB7ciBldmFsPSBGQUxTRSwgY2FzaD1UUlVFfQp3ZGlfY2FjaGUgPC0gV0RJOjpXREljYWNoZSgpCmBgYAoKIyMjIyMgU3RlcCA0LgoKKiBVc2UgYGxlZnRfam9pbmAgdG8gYWRkIGNvdW50cnkgbmFtZXMKCmBgYHtyfQpkZl9wdWJfcHJpdiA8LSBwdWJsaWNfdnNfcHJpdmF0ZSAlPiUgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDMsNCksIG5hbWVzX3RvID0gImNhdGVnb3J5IiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lIGxlZnRfam9pbih3ZGlfY2FjaGUkY291bnRyeSwgYnkgPSBjKCJjb3VudHJ5Ij0iaXNvMmMiKSkgJT4lCiAgc2VsZWN0KGNvdW50cnkgPSBjb3VudHJ5LnksIGlzbzJjID0gY291bnRyeSwgeWVhciwgY2F0ZWdvcnksIHZhbHVlLCByZWdpb24sIGluY29tZSwgbGVuZGluZykKZGZfcHViX3ByaXYKYGBgCgoqIENoZWNrIGlmIHRoZSBjb3VudHJ5IG5hbWUgaXMgbWlzc2luZy4KCmBgYHtyfSAKZGZfcHViX3ByaXYgJT4lIGZpbHRlcihpcy5uYShjb3VudHJ5KSkgJT4lIAogIGZpbHRlcihuY2hhcihpc28yYyk9PTIpICU+JQogIGRpc3RpbmN0KGlzbzJjKSAlPiUgcHVsbChpc28yYykKYGBgCgoKIyMjIyBTdGVwIDUuCgoqIFNlbGVjdCBjb3VudHJpZXMgCgpgYGB7cn0KdW5pcXVlKGRmX3B1Yl9wcml2JGNvdW50cnkpCmBgYAojIyMjIyBTdGVwIDYuCgpEcmF3IGEgY2hhcnQuCgpgYGB7cn0KZGZfcHViX3ByaXYgJT4lIAogIGZpbHRlcihjb3VudHJ5ICVpbiUgYygiSmFwYW4iLCAiTm9yd2F5IiwgIlN3ZWRlbiIsICJEZW5tYXJrIiwgIkZpbmxhbmQiKSwgeWVhciAlaW4lIDE5NzA6MjAyMCkgJT4lCiAgZ2dwbG90KGFlcyh5ZWFyLCB2YWx1ZSwgY29sb3IgPSBjb3VudHJ5LCBsaW5ldHlwZSA9IGNhdGVnb3J5KSkgKyBnZW9tX2xpbmUoKQpgYGAKCldlIGNob29zZSB0d28gaW5kaWNhdG9yczogJ3dlYWxnJyBhbmQgJ3dlYWxwJy4gV0lSMjAyMiBpbmRpY2F0b3JzIGNvbnNpc3RzIG9mIDYgY2hhcmFjdGVyczsgMSBsZXR0ZXIgY29kZSBwbHVzIDUgbGV0dGVyIGNvZGUuIFlvdSBjYW4gZmluZCB0aGUgbGlzdCBpbiB0aGUgY29kZWJvb2suCgpJZiB5b3Ugd2FudCB0byBzdHVkeSBXSVIyMDIyLCBwbGVhc2Ugc3R1ZHkgdGhlIFtyZXBvcnRdKGh0dHBzOi8vd2lyMjAyMi53aWQud29ybGQvKSwgdGhlIFtjb2RlYm9va10oaHR0cHM6Ly93aWQud29ybGQvY29kZXMtZGljdGlvbmFyeSksIGFuZCB3aXIgW3ZpZ25ldHRlXShodHRwczovL2RzLXNsLmdpdGh1Yi5pby9kYXRhLWFuYWx5c2lzL3dpcl9kb3dubG9hZC5wZGYpIHRvZ2V0aGVyIHdpdGggdGhlIFtSIE5vdGVib29rXShodHRwczovL2RzLXNsLmdpdGh1Yi5pby9kYXRhLWFuYWx5c2lzL3dpcjIwMjIubmIuaHRtbCkuIAoKCg==