南部アフリカ諸国の貧困と不平等の現状

1月9日(火)のジニ指数の演習ファイルをもとに、1月11日(木)の講義に関係したグラフをいくつか作成し、以下に提示します。基本的に、木曜日の講義を聴きながら作成したものです。

概要を把握するための作業

準備

library(tidyverse)
library(WDI)
library(DescTools)

データの読み込み

地域情報を利用するために、extra = TRUE を加えました。

df_gini_extra <- WDI(indicator = c(gini = "SI.POV.GINI",
                            `0-10` = "SI.DST.FRST.10",
                            `0-20` = "SI.DST.FRST.20",
                            `20-40` = "SI.DST.02ND.20",
                            `40-60` = "SI.DST.03RD.20",
                            `60-80` = "SI.DST.04TH.20",
                            `80-100` = "SI.DST.05TH.20",
                            `90-100` = "SI.DST.10TH.10"), extra = TRUE)

保存と読み込み

何度もダウンロードしなくて良いように、保存したものを読み込みます。

write_csv(df_gini_extra, "data/gini_extra.csv")
df_gini_extra <- read_csv("data/gini_extra.csv")
Rows: 16758 Columns: 20── Column specification ─────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr   (7): country, iso2c, iso3c, region, capital, income, lending
dbl  (11): year, gini, 0-10, 0-20, 20-40, 40-60, 60-80, 80-100, 90-100, longitude, latitude
lgl   (1): status
date  (1): lastupdated
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

データの確認

df_gini_extra

必要な変数のみ抽出

df_gini_extra <- df_gini_extra |> select(country, iso2c, year, gini:region)

gini が 欠損値(NA) ではない値のもののみ表示

df_gini_extra |> drop_na(gini)

gini の値の大きい順(降順)に並び替え

df_gini_extra |> drop_na(gini) |> 
  arrange(desc(gini)) |> distinct(country, year, gini, region)

それぞれの国の最も新しいデータだけを取り降順に並べます

df_gini_extra_recent <-df_gini_extra |> drop_na(gini) |> group_by(country) |> filter(year == max(year)) |>
  arrange(desc(gini))
df_gini_extra_recent

変形:各階級の値を縦に並べ、縦長形式の表にします。Long format

pivot_longer(cols, names_to = "", values_to = "") についてはいずれ説明します。ここでは、レベルに分けられたものを levels という名の列にレベルを、value という名の列に、その値を並べたものとします。

df_gini_extra_long <- df_gini_extra |> 
  pivot_longer(`0-10`:`90-100`, names_to = "levels", values_to = "value")
df_gini_extra_long

日本の情報の確認

df_gini_extra_long |> filter(country == "Japan") |> 
  drop_na(gini) |> distinct(country, year, gini, levels, value)
COUNTRIES_D <- c("Japan","United States", "South Africa")

国ごとの最近の GINI 指数(降順)

df_gini_extra |> select(country, year, gini:`90-100`) |> filter(country %in% COUNTRIES_D) |> 
  drop_na(gini) |> group_by(country) |> filter(year == max(year))

何種類かの棒グラフで表示

df_gini_extra_long |> filter(country %in% COUNTRIES_D) |>
  drop_na(gini) |> group_by(country) |> filter(year == max(year)) |> 
  ggplot(aes(factor(country, levels = COUNTRIES_D), value, fill = levels)) + geom_col(position = "dodge", col = "black", linewidth = 0.1) +
   geom_text(aes(group = levels, label = value), vjust = -0.2, position = position_dodge(width = 0.9)) + 
  labs(title = "Distribution of Wealth in Three Countries in Recent Year", x = "")

df_gini_extra_long |> filter(country %in% COUNTRIES_D) |>
  drop_na(gini) |> group_by(country) |> filter(year == max(year)) |>
  filter(!(levels %in% c('0-10','90-100'))) |> 
  ggplot(aes(factor(country, levels = COUNTRIES_D), value, fill = levels)) + geom_col(position = "dodge", col = "black", linewidth = 0.1) +
   geom_text(aes(group = levels, label = value), vjust = -0.2, position = position_dodge(width = 0.9)) + 
  labs(title = "Distribution of Wealth in Three Countries in Recent Year", x = "")

考察:0-10, 90-100 はなくても良いかもしれない。

df_gini_extra_long |> filter(country %in% COUNTRIES_D) |> filter(year == 2010) |>
  drop_na(gini) |> ggplot(aes(factor(country, levels = COUNTRIES_D), value, fill = levels)) + geom_col(position = "dodge", col = "black", linewidth = 0.1) +
   geom_text(aes(group = levels, label = value), vjust = -0.2, position = position_dodge(width = 0.9)) + 
  labs(title = "Distribution of Wealth in Three Countries in 2010", x = "")

考察:データが限られているので、年を揃えるのは難しい。最新のデータのみを使う

df_gini_extra_long |> filter(country %in% COUNTRIES_D) |>
  drop_na(gini) |> group_by(country) |> filter(year == max(year)) |>
  filter(!(levels %in% c('0-10','90-100'))) |> 
  ggplot(aes(factor(country, levels = COUNTRIES_D), value, fill = levels)) + geom_col(position = "dodge", col = "black", linewidth = 0.1) +
   geom_text(aes(group = levels, label = value), vjust = -0.2, position = position_dodge(width = 0.9)) + 
  labs(title = "Distribution of Wealth in Three Countries in Recent Year", x = "")

ローレンツ曲線を表示する準備

Derivation of the Lorenz curve and Gini coefficient for global income in 2011 [リンク]

df_gini_calc_recent <- df_gini_extra_recent |> 
  mutate(`0` = 0, `10` = `0-10`, `20` = `0-20`,
         `30` = `0-20`+`20-40`/2, `40` = `0-20` + `20-40`, 
         `50` = `0-20` + `20-40` + `40-60`/2, 
         `60` = `0-20` + `20-40` + `40-60`, 
         `70` = `0-20` + `20-40` + `40-60` + `60-80`/2,  
         `80` = `0-20` + `20-40` + `40-60` + `60-80`, 
         `90` = `0-20` + `20-40` + `40-60` + `60-80` + `80-100`-`90-100`,
         `100` = 100) |>
  select(-c(`0-10`:`90-100`)) # 不必要な部分を消去
df_gini_calc %>% drop_na() 

縦長の Long Table に変換

df_gini_calc_recent_long <- df_gini_calc_recent |>  pivot_longer(`0`:`100`, names_to = "classes", values_to = "cumulative_share") |> mutate(classes = as.numeric(classes))
df_gini_calc_long %>% drop_na() 

確認

df_gini_calc_recent_long |> filter(country == "Japan") |> 
  ggplot() + 
  geom_line(aes(classes, cumulative_share)) + 
  geom_segment(aes(x = 0, y = 0, xend = 100, yend = 100), color = 'red') + 
  scale_x_continuous(breaks = seq(0,100,by=20)) + 
  scale_y_continuous(breaks = seq(0,100,by=20)) #+
  #annotate("text", x = 10, y = 80, label = gini)

世界の状況

それぞれの国の最新のデータ

ジニ指数の降順

df_gini_extra_recent <-df_gini_extra |> drop_na(gini) |> group_by(country) |> filter(year == max(year)) |>
  arrange(desc(gini))
df_gini_extra_recent

ジニ指数の大きな30カ国を棒グラフにします

top30gini <- df_gini_extra_recent |>  
  arrange(desc(gini)) |> head(30) |> pull(country)
df_gini_extra_recent |> filter(country %in% top30gini) |> 
  ggplot(aes(factor(country, levels = top30gini), gini, fill = region)) + geom_col() + 
  theme(axis.text.x = element_text(angle = 90, vjust = 1, hjust=1), legend.position = "top") +
  labs(title = "Top 30 Countries of Recent Gini Index", x = "")

考察:二地域に限られています

分布を地域ごとの箱ひげ図で見てみます

箱ひげ図とは? [リンク]

df_gini_extra_recent |> drop_na(region) |> filter(region != "Aggregates") |>
  ggplot(aes(gini, region, fill = region)) + geom_boxplot() +
  theme(legend.position = "")

南アフリカ5カ国について

SOUTH_AFRICA_FIVE <- c("South Africa", "Namibia", "Eswatini", "Botswana", "Lesotho")

経年変化を表す折れ線グラフ

df_gini_extra |> filter(country %in% SOUTH_AFRICA_FIVE ) |>
  drop_na(gini) |>
  ggplot(aes(year, gini, col = factor(country, level = SOUTH_AFRICA_FIVE))) + 
  geom_line() + labs(title = "Gini Index of Five Countries", col = "From gini top")
df_gini_extra_long |> filter(country %in% SOUTH_AFRICA_FIVE ) |>
  drop_na(value) |>
  ggplot(aes(year, value, col = levels)) + geom_line() + facet_wrap(~factor(country, level = SOUTH_AFRICA_FIVE)) + labs(title = "Change of ratio of each level")

早くからデータがある国のジニ指数が低いように見える

最新のデータ

データの数も少ないので、最新のデータのみに限る

df_gini_extra_recent |> filter(country %in% SOUTH_AFRICA_FIVE)

SOUTH_AFRICA_FIVE の国の順番を、Gini 指数の大きい順に並べておく

ローレンツ曲線

df_gini_calc_recent_long |> filter(country %in% SOUTH_AFRICA_FIVE) |> 
  ggplot() + 
  geom_line(aes(classes, cumulative_share, col = factor(country, levels = SOUTH_AFRICA_FIVE))) + 
  geom_segment(aes(x = 0, y = 0, xend = 100, yend = 100, col = country), color = 'red') + 
  scale_x_continuous(breaks = seq(0,100,by=20)) + 
  scale_y_continuous(breaks = seq(0,100,by=20)) +
  labs(col = "From gini top")

所得の割合を表す棒グラフ

df_gini_extra_long |> filter(country %in% SOUTH_AFRICA_FIVE) |>
  drop_na(gini) |> group_by(country) |> filter(year == max(year)) |>
  filter(!(levels %in% c('0-10','90-100'))) |> 
  ggplot(aes(factor(country, levels = SOUTH_AFRICA_FIVE), value, fill = levels)) + geom_col(position = "dodge", col = "black", linewidth = 0.1) +
   geom_text(aes(group = levels, label = value), vjust = -0.2, position = position_dodge(width = 0.9)) + 
  labs(title = "Distribution of Wealth in Five Countries in Recent Year", x = "")

ジニ指数と Top 20% の値の相関

df_gini_extra_recent |> filter(region != "Aggregates") |> drop_na(`80-100`) |>
  ggplot(aes(gini, `80-100`)) + geom_point(aes(col = region)) + 
  geom_smooth(formula = 'y ~ x', method = "lm")

考察:かなり強い正の相関があり、回帰直線がかなり適合している。

練習: 国のリストを変えてみよう

国の選択

CHOSEN_GINI_COUNTRIES <- c("Suriname", "Belize", "Brazil", "Colombia")

経年変化を表す折れ線グラフ

df_gini_extra |> filter(country %in% CHOSEN_GINI_COUNTRIES) |>
  drop_na(gini) |>
  ggplot(aes(year, gini, col = factor(country, level = CHOSEN_GINI_COUNTRIES))) + 
  geom_line() + labs(title = "Gini Index of Chosen Countries", col = "From gini top")
df_gini_extra_long |> filter(country %in% CHOSEN_GINI_COUNTRIES) |>
  drop_na(value) |>
  ggplot(aes(year, value, col = levels)) + geom_line() + facet_wrap(~factor(country, level = CHOSEN_GINI_COUNTRIES)) + labs(title = "Change of ratio of each level")

考察:

最新のデータ

データの数も少ないので、最新のデータのみに限る

df_gini_extra_recent |> filter(country %in% CHOSEN_GINI_COUNTRIES)

考察:

CHOSEN_GINI_COUNTRIES の国の順番を、Gini 指数の大きい順に並べておく

ローレンツ曲線

df_gini_calc_recent_long |> filter(country %in% CHOSEN_GINI_COUNTRIES) |> 
  ggplot() + 
  geom_line(aes(classes, cumulative_share, col = factor(country, levels = CHOSEN_GINI_COUNTRIES))) + 
  geom_segment(aes(x = 0, y = 0, xend = 100, yend = 100, col = country), color = 'red') + 
  scale_x_continuous(breaks = seq(0,100,by=20)) + 
  scale_y_continuous(breaks = seq(0,100,by=20)) +
  labs(col = "From top gini")

考察:

所得の割合を表す棒グラフ

df_gini_extra_long |> filter(country %in% CHOSEN_GINI_COUNTRIES) |>
  drop_na(gini) |> group_by(country) |> filter(year == max(year)) |>
  filter(!(levels %in% c('0-10','90-100'))) |> drop_na(value) |>
  ggplot(aes(factor(country, levels = CHOSEN_GINI_COUNTRIES), value, fill = levels)) + geom_col(position = "dodge", col = "black", linewidth = 0.1) +
   geom_text(aes(group = levels, label = value), vjust = -0.2, position = position_dodge(width = 0.9)) + 
  labs(title = "Distribution of Wealth in Chosen Countries in Recent Year", x = "")

考察:

LS0tCnRpdGxlOiAi44K444OL5oyH5pWw44Go5omA5b6X5YiG5biDIC0g57aa57eoIgphdXRob3I6ICJILiBTdXp1a2kiCmRhdGU6ICIyMDI05bm0MeaciDEx5pelIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKLS0tCgojIOWNl+mDqOOCouODleODquOCq+iruOWbveOBruiyp+WbsOOBqOS4jeW5s+etieOBruePvueKtgoKPiAx5pyIOeaXpe+8iOeBq++8ieOBruOCuOODi+aMh+aVsOOBrua8lOe/kuODleOCoeOCpOODq+OCkuOCguOBqOOBq+OAgTHmnIgxMeaXpe+8iOacqO+8ieOBruism+e+qeOBq+mWouS/guOBl+OBn+OCsOODqeODleOCkuOBhOOBj+OBpOOBi+S9nOaIkOOBl+OAgeS7peS4i+OBq+aPkOekuuOBl+OBvuOBmeOAguWfuuacrOeahOOBq+OAgeacqOabnOaXpeOBruism+e+qeOCkuiBtOOBjeOBquOBjOOCieS9nOaIkOOBl+OBn+OCguOBruOBp+OBmeOAggoKIyMg5LiW55WM6ZaL55m65oyH5qiZ77yIV29ybGQgRGV2ZWxvcG1lbnQgSW5kaWNhdG9yc++8iVtbTGlua10oaHR0cHM6Ly9kYXRhdG9waWNzLndvcmxkYmFuay5vcmcvd29ybGQtZGV2ZWxvcG1lbnQtaW5kaWNhdG9ycy8pXQoKIyMjIyAqKuiyp+WbsOOBqOS4jeW5s+etie+8iFBvdmVydHkgYW5kIEluZXF1YWxpdHnvvIkqKgoKKirmiYDlvpfjgb7jgZ/jga/mtojosrvjga7liIbphY3vvIhEaXN0cmlidXRpb24gb2YgaW5jb21lIG9yIGNvbnN1bXB0aW9u77yJKioKCkdJTkkg5oyH5pWwICjkuJbnlYzpioDooYzmjqjoqIgp77yaU0kuUE9WLkdJTkkgW1tMaW5rXShodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy9pbmRpY2F0b3IvU0kuUE9WLkdJTkkpXQoK5LiL5L2NIDEwJSDjgYzljaDjgoHjgovmiYDlvpfjgrfjgqfjgqLvvJpTSS5EU1QuRlJTVC4xMCBbW0xpbmtdKGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9tZXRhZGF0YWdsb3NzYXJ5L3dvcmxkLWRldmVsb3BtZW50LWluZGljYXRvcnMvc2VyaWVzL1NJLkRTVC5GUlNULjEwKV0KCuS4i+S9jSAyMCUg44GM5Y2g44KB44KL5omA5b6X44K344Kn44Ki77yaU0kuRFNULkZSU1QuMjAgW1tMaW5rXShodHRwczovL2RhdGFiYW5rLndvcmxkYmFuay5vcmcvbWV0YWRhdGFnbG9zc2FyeS93b3JsZC1kZXZlbG9wbWVudC1pbmRpY2F0b3JzL3Nlcmllcy9TSS5EU1QuRlJTVC4yMCldCgoy55Wq55uu44GuIDIwJSDjgYzljaDjgoHjgovlj47lhaXjgrfjgqfjgqLvvJpTSS5EU1QuMDJORC4yMCBbW0xpbmtdKGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9tZXRhZGF0YWdsb3NzYXJ5L3dvcmxkLWRldmVsb3BtZW50LWluZGljYXRvcnMvc2VyaWVzL1NJLkRTVC4wMk5ELjIwKV0KCjPnlarnm67jga4gMjAlIOOBjOWNoOOCgeOCi+WPjuWFpeOCt+OCp+OCoiDvvJpTSS5EU1QuMDNSRC4yMCBbW0xpbmtdKGh0dHBzOi8vZGF0YS53b3JsZGJhbmsub3JnL2luZGljYXRvci9TSS5EU1QuMDNSRC4yMCldCgo055Wq55uu44GuIDIwJSDjgYzljaDjgoHjgovlj47lhaXjgrfjgqfjgqLvvJpTSS5EU1QuMDRUSC4yMCBbW0xpbmtdKGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9tZXRhZGF0YWdsb3NzYXJ5L3dvcmxkLWRldmVsb3BtZW50LWluZGljYXRvcnMvc2VyaWVzL1NJLkRTVC4wNFRILjIwKV0KCuS4iuS9jSAyMCUg44GM5Y2g44KB44KL5Y+O5YWl44K344Kn44Ki77yaU0kuRFNULjA1VEguMjAgW1tMaW5rXShodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy9pbmRpY2F0b3IvU0kuRFNULjA1VEguMjApXQoK5LiK5L2NIDEwJSDjgYzljaDjgoHjgovlj47lhaXjgrfjgqfjgqLvvJpTSS5EU1QuMTBUSC4xMCBbW0xpbmtdKGh0dHBzOi8vZGF0YS53b3JsZGJhbmsub3JnL2luZGljYXRvci9TSS5EU1QuMTBUSC4xMCldCgojIyDmpoLopoHjgpLmiormj6HjgZnjgovjgZ/jgoHjga7kvZzmpa0KCiMjIyDmupblgpkKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShXREkpCmxpYnJhcnkoRGVzY1Rvb2xzKQpgYGAKCiMjIyDjg4fjg7zjgr/jga7oqq3jgb/ovrzjgb8KCuWcsOWfn+aDheWgseOCkuWIqeeUqOOBmeOCi+OBn+OCgeOBq+OAgWBleHRyYSA9IFRSVUVgIOOCkuWKoOOBiOOBvuOBl+OBn+OAggoKYGBge3IgZXZhbCA9IEZBTFNFfQpkZl9naW5pX2V4dHJhIDwtIFdESShpbmRpY2F0b3IgPSBjKGdpbmkgPSAiU0kuUE9WLkdJTkkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYDAtMTBgID0gIlNJLkRTVC5GUlNULjEwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGAwLTIwYCA9ICJTSS5EU1QuRlJTVC4yMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgMjAtNDBgID0gIlNJLkRTVC4wMk5ELjIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGA0MC02MGAgPSAiU0kuRFNULjAzUkQuMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYDYwLTgwYCA9ICJTSS5EU1QuMDRUSC4yMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgODAtMTAwYCA9ICJTSS5EU1QuMDVUSC4yMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgOTAtMTAwYCA9ICJTSS5EU1QuMTBUSC4xMCIpLCBleHRyYSA9IFRSVUUpCmBgYAoKIyMjIOS/neWtmOOBqOiqreOBv+i+vOOBvwoK5L2V5bqm44KC44OA44Km44Oz44Ot44O844OJ44GX44Gq44GP44Gm6Imv44GE44KI44GG44Gr44CB5L+d5a2Y44GX44Gf44KC44Gu44KS6Kqt44G/6L6844G/44G+44GZ44CCCgpgYGB7ciBldmFsID0gRkFMU0V9CndyaXRlX2NzdihkZl9naW5pX2V4dHJhLCAiZGF0YS9naW5pX2V4dHJhLmNzdiIpCmBgYAoKYGBge3J9CmRmX2dpbmlfZXh0cmEgPC0gcmVhZF9jc3YoImRhdGEvZ2luaV9leHRyYS5jc3YiKQpgYGAKCiMjIyDjg4fjg7zjgr/jga7norroqo0KCmBgYHtyfQpkZl9naW5pX2V4dHJhCmBgYAoKIyMjIOW/heimgeOBquWkieaVsOOBruOBv+aKveWHugoKYGBge3J9CmRmX2dpbmlfZXh0cmEgPC0gZGZfZ2luaV9leHRyYSB8PiBzZWxlY3QoY291bnRyeSwgaXNvMmMsIHllYXIsIGdpbmk6cmVnaW9uKQpgYGAKCiMjIyBnaW5pIOOBjCDmrKDmkI3lgKTvvIhOQe+8iSDjgafjga/jgarjgYTlgKTjga7jgoLjga7jga7jgb/ooajnpLoKCmBgYHtyfQpkZl9naW5pX2V4dHJhIHw+IGRyb3BfbmEoZ2luaSkKYGBgCgojIyMgZ2luaSDjga7lgKTjga7lpKfjgY3jgYTpoIbvvIjpmY3poIbvvInjgavkuKbjgbPmm7/jgYgKCmBgYHtyfQpkZl9naW5pX2V4dHJhIHw+IGRyb3BfbmEoZ2luaSkgfD4gCiAgYXJyYW5nZShkZXNjKGdpbmkpKSB8PiBkaXN0aW5jdChjb3VudHJ5LCB5ZWFyLCBnaW5pLCByZWdpb24pCmBgYAoKIyMjIOOBneOCjOOBnuOCjOOBruWbveOBruacgOOCguaWsOOBl+OBhOODh+ODvOOCv+OBoOOBkeOCkuWPluOCiumZjemghuOBq+S4puOBueOBvuOBmQoKYGBge3J9CmRmX2dpbmlfZXh0cmFfcmVjZW50IDwtZGZfZ2luaV9leHRyYSB8PiBkcm9wX25hKGdpbmkpIHw+IGdyb3VwX2J5KGNvdW50cnkpIHw+IGZpbHRlcih5ZWFyID09IG1heCh5ZWFyKSkgfD4KICBhcnJhbmdlKGRlc2MoZ2luaSkpCmRmX2dpbmlfZXh0cmFfcmVjZW50CmBgYAoKIyMjIOWkieW9ou+8muWQhOmajue0muOBruWApOOCkue4puOBq+S4puOBueOAgee4pumVt+W9ouW8j+OBruihqOOBq+OBl+OBvuOBmeOAgkxvbmcgZm9ybWF0CgpgcGl2b3RfbG9uZ2VyKGNvbHMsIG5hbWVzX3RvID0gIiIsIHZhbHVlc190byA9ICIiKWAg44Gr44Gk44GE44Gm44Gv44GE44Ga44KM6Kqs5piO44GX44G+44GZ44CC44GT44GT44Gn44Gv44CB44Os44OZ44Or44Gr5YiG44GR44KJ44KM44Gf44KC44Gu44KSIGxldmVscyDjgajjgYTjgYblkI3jga7liJfjgavjg6zjg5njg6vjgpLjgIF2YWx1ZSDjgajjgYTjgYblkI3jga7liJfjgavjgIHjgZ3jga7lgKTjgpLkuKbjgbnjgZ/jgoLjga7jgajjgZfjgb7jgZnjgIIKCmBgYHtyfQpkZl9naW5pX2V4dHJhX2xvbmcgPC0gZGZfZ2luaV9leHRyYSB8PiAKICBwaXZvdF9sb25nZXIoYDAtMTBgOmA5MC0xMDBgLCBuYW1lc190byA9ICJsZXZlbHMiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKQpkZl9naW5pX2V4dHJhX2xvbmcKYGBgCgojIyMg5pel5pys44Gu5oOF5aCx44Gu56K66KqNCgpgYGB7cn0KZGZfZ2luaV9leHRyYV9sb25nIHw+IGZpbHRlcihjb3VudHJ5ID09ICJKYXBhbiIpIHw+IAogIGRyb3BfbmEoZ2luaSkgfD4gZGlzdGluY3QoY291bnRyeSwgeWVhciwgZ2luaSwgbGV2ZWxzLCB2YWx1ZSkKYGBgCgpgYGB7cn0KQ09VTlRSSUVTX0QgPC0gYygiSmFwYW4iLCJVbml0ZWQgU3RhdGVzIiwgIlNvdXRoIEFmcmljYSIpCmBgYAoKIyMjIOWbveOBlOOBqOOBruacgOi/keOBriBHSU5JIOaMh+aVsO+8iOmZjemghu+8iQoKYGBge3J9CmRmX2dpbmlfZXh0cmEgfD4gc2VsZWN0KGNvdW50cnksIHllYXIsIGdpbmk6YDkwLTEwMGApIHw+IGZpbHRlcihjb3VudHJ5ICVpbiUgQ09VTlRSSUVTX0QpIHw+IAogIGRyb3BfbmEoZ2luaSkgfD4gZ3JvdXBfYnkoY291bnRyeSkgfD4gZmlsdGVyKHllYXIgPT0gbWF4KHllYXIpKQpgYGAKCiMjIyDkvZXnqK7poZ7jgYvjga7mo5LjgrDjg6njg5XjgafooajnpLoKCmBgYHtyfQpkZl9naW5pX2V4dHJhX2xvbmcgfD4gZmlsdGVyKGNvdW50cnkgJWluJSBDT1VOVFJJRVNfRCkgfD4KICBkcm9wX25hKGdpbmkpIHw+IGdyb3VwX2J5KGNvdW50cnkpIHw+IGZpbHRlcih5ZWFyID09IG1heCh5ZWFyKSkgfD4gCiAgZ2dwbG90KGFlcyhmYWN0b3IoY291bnRyeSwgbGV2ZWxzID0gQ09VTlRSSUVTX0QpLCB2YWx1ZSwgZmlsbCA9IGxldmVscykpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiLCBjb2wgPSAiYmxhY2siLCBsaW5ld2lkdGggPSAwLjEpICsKICAgZ2VvbV90ZXh0KGFlcyhncm91cCA9IGxldmVscywgbGFiZWwgPSB2YWx1ZSksIHZqdXN0ID0gLTAuMiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSkpICsgCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgV2VhbHRoIGluIFRocmVlIENvdW50cmllcyBpbiBSZWNlbnQgWWVhciIsIHggPSAiIikKYGBgCgpgYGB7cn0KZGZfZ2luaV9leHRyYV9sb25nIHw+IGZpbHRlcihjb3VudHJ5ICVpbiUgQ09VTlRSSUVTX0QpIHw+CiAgZHJvcF9uYShnaW5pKSB8PiBncm91cF9ieShjb3VudHJ5KSB8PiBmaWx0ZXIoeWVhciA9PSBtYXgoeWVhcikpIHw+CiAgZmlsdGVyKCEobGV2ZWxzICVpbiUgYygnMC0xMCcsJzkwLTEwMCcpKSkgfD4gCiAgZ2dwbG90KGFlcyhmYWN0b3IoY291bnRyeSwgbGV2ZWxzID0gQ09VTlRSSUVTX0QpLCB2YWx1ZSwgZmlsbCA9IGxldmVscykpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiLCBjb2wgPSAiYmxhY2siLCBsaW5ld2lkdGggPSAwLjEpICsKICAgZ2VvbV90ZXh0KGFlcyhncm91cCA9IGxldmVscywgbGFiZWwgPSB2YWx1ZSksIHZqdXN0ID0gLTAuMiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSkpICsgCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgV2VhbHRoIGluIFRocmVlIENvdW50cmllcyBpbiBSZWNlbnQgWWVhciIsIHggPSAiIikKYGBgCgoqKuiAg+Wvn++8mjAtMTAsIDkwLTEwMCDjga/jgarjgY/jgabjgoLoia/jgYTjgYvjgoLjgZfjgozjgarjgYTjgIIqKgoKYGBge3J9CmRmX2dpbmlfZXh0cmFfbG9uZyB8PiBmaWx0ZXIoY291bnRyeSAlaW4lIENPVU5UUklFU19EKSB8PiBmaWx0ZXIoeWVhciA9PSAyMDEwKSB8PgogIGRyb3BfbmEoZ2luaSkgfD4gZ2dwbG90KGFlcyhmYWN0b3IoY291bnRyeSwgbGV2ZWxzID0gQ09VTlRSSUVTX0QpLCB2YWx1ZSwgZmlsbCA9IGxldmVscykpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiLCBjb2wgPSAiYmxhY2siLCBsaW5ld2lkdGggPSAwLjEpICsKICAgZ2VvbV90ZXh0KGFlcyhncm91cCA9IGxldmVscywgbGFiZWwgPSB2YWx1ZSksIHZqdXN0ID0gLTAuMiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSkpICsgCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgV2VhbHRoIGluIFRocmVlIENvdW50cmllcyBpbiAyMDEwIiwgeCA9ICIiKQpgYGAKCioq6ICD5a+f77ya44OH44O844K/44GM6ZmQ44KJ44KM44Gm44GE44KL44Gu44Gn44CB5bm044KS5o+D44GI44KL44Gu44Gv6Zuj44GX44GE44CC5pyA5paw44Gu44OH44O844K/44Gu44G/44KS5L2/44GGKioKCmBgYHtyfQpkZl9naW5pX2V4dHJhX2xvbmcgfD4gZmlsdGVyKGNvdW50cnkgJWluJSBDT1VOVFJJRVNfRCkgfD4KICBkcm9wX25hKGdpbmkpIHw+IGdyb3VwX2J5KGNvdW50cnkpIHw+IGZpbHRlcih5ZWFyID09IG1heCh5ZWFyKSkgfD4KICBmaWx0ZXIoIShsZXZlbHMgJWluJSBjKCcwLTEwJywnOTAtMTAwJykpKSB8PiAKICBnZ3Bsb3QoYWVzKGZhY3Rvcihjb3VudHJ5LCBsZXZlbHMgPSBDT1VOVFJJRVNfRCksIHZhbHVlLCBmaWxsID0gbGV2ZWxzKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIsIGNvbCA9ICJibGFjayIsIGxpbmV3aWR0aCA9IDAuMSkgKwogICBnZW9tX3RleHQoYWVzKGdyb3VwID0gbGV2ZWxzLCBsYWJlbCA9IHZhbHVlKSwgdmp1c3QgPSAtMC4yLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSkgKyAKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBXZWFsdGggaW4gVGhyZWUgQ291bnRyaWVzIGluIFJlY2VudCBZZWFyIiwgeCA9ICIiKQpgYGAKCiMjIyDjg63jg7zjg6zjg7Pjg4Tmm7Lnt5rjgpLooajnpLrjgZnjgovmupblgpkKCkRlcml2YXRpb24gb2YgdGhlIExvcmVueiBjdXJ2ZSBhbmQgR2luaSBjb2VmZmljaWVudCBmb3IgZ2xvYmFsIGluY29tZSBpbiAyMDExIFtb44Oq44Oz44KvXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HaW5pX2NvZWZmaWNpZW50KV0KCmBgYHtyfQpkZl9naW5pX2NhbGNfcmVjZW50IDwtIGRmX2dpbmlfZXh0cmFfcmVjZW50IHw+IAogIG11dGF0ZShgMGAgPSAwLCBgMTBgID0gYDAtMTBgLCBgMjBgID0gYDAtMjBgLAogICAgICAgICBgMzBgID0gYDAtMjBgK2AyMC00MGAvMiwgYDQwYCA9IGAwLTIwYCArIGAyMC00MGAsIAogICAgICAgICBgNTBgID0gYDAtMjBgICsgYDIwLTQwYCArIGA0MC02MGAvMiwgCiAgICAgICAgIGA2MGAgPSBgMC0yMGAgKyBgMjAtNDBgICsgYDQwLTYwYCwgCiAgICAgICAgIGA3MGAgPSBgMC0yMGAgKyBgMjAtNDBgICsgYDQwLTYwYCArIGA2MC04MGAvMiwgIAogICAgICAgICBgODBgID0gYDAtMjBgICsgYDIwLTQwYCArIGA0MC02MGAgKyBgNjAtODBgLCAKICAgICAgICAgYDkwYCA9IGAwLTIwYCArIGAyMC00MGAgKyBgNDAtNjBgICsgYDYwLTgwYCArIGA4MC0xMDBgLWA5MC0xMDBgLAogICAgICAgICBgMTAwYCA9IDEwMCkgfD4KICBzZWxlY3QoLWMoYDAtMTBgOmA5MC0xMDBgKSkgIyDkuI3lv4XopoHjgarpg6jliIbjgpLmtojljrsKZGZfZ2luaV9jYWxjICU+JSBkcm9wX25hKCkgCmBgYAoKIyMjIOe4pumVt+OBriBMb25nIFRhYmxlIOOBq+WkieaPmwoKYGBge3J9CmRmX2dpbmlfY2FsY19yZWNlbnRfbG9uZyA8LSBkZl9naW5pX2NhbGNfcmVjZW50IHw+ICBwaXZvdF9sb25nZXIoYDBgOmAxMDBgLCBuYW1lc190byA9ICJjbGFzc2VzIiwgdmFsdWVzX3RvID0gImN1bXVsYXRpdmVfc2hhcmUiKSB8PiBtdXRhdGUoY2xhc3NlcyA9IGFzLm51bWVyaWMoY2xhc3NlcykpCmRmX2dpbmlfY2FsY19sb25nICU+JSBkcm9wX25hKCkgCmBgYAoKIyMjIOeiuuiqjQoKYGBge3J9CmRmX2dpbmlfY2FsY19yZWNlbnRfbG9uZyB8PiBmaWx0ZXIoY291bnRyeSA9PSAiSmFwYW4iKSB8PiAKICBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoY2xhc3NlcywgY3VtdWxhdGl2ZV9zaGFyZSkpICsgCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwgeSA9IDAsIHhlbmQgPSAxMDAsIHllbmQgPSAxMDApLCBjb2xvciA9ICdyZWQnKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMDAsYnk9MjApKSArIAogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMDAsYnk9MjApKSAjKwogICNhbm5vdGF0ZSgidGV4dCIsIHggPSAxMCwgeSA9IDgwLCBsYWJlbCA9IGdpbmkpCmBgYAoKIyMg5LiW55WM44Gu54q25rOBCgojIyMg44Gd44KM44Ge44KM44Gu5Zu944Gu5pyA5paw44Gu44OH44O844K/Cgrjgrjjg4vmjIfmlbDjga7pmY3poIYKCmBgYHtyfQpkZl9naW5pX2V4dHJhX3JlY2VudCA8LWRmX2dpbmlfZXh0cmEgfD4gZHJvcF9uYShnaW5pKSB8PiBncm91cF9ieShjb3VudHJ5KSB8PiBmaWx0ZXIoeWVhciA9PSBtYXgoeWVhcikpIHw+CiAgYXJyYW5nZShkZXNjKGdpbmkpKQpkZl9naW5pX2V4dHJhX3JlY2VudApgYGAKCiMjIyDjgrjjg4vmjIfmlbDjga7lpKfjgY3jgaozMOOCq+WbveOCkuajkuOCsOODqeODleOBq+OBl+OBvuOBmQoKYGBge3J9CnRvcDMwZ2luaSA8LSBkZl9naW5pX2V4dHJhX3JlY2VudCB8PiAgCiAgYXJyYW5nZShkZXNjKGdpbmkpKSB8PiBoZWFkKDMwKSB8PiBwdWxsKGNvdW50cnkpCmRmX2dpbmlfZXh0cmFfcmVjZW50IHw+IGZpbHRlcihjb3VudHJ5ICVpbiUgdG9wMzBnaW5pKSB8PiAKICBnZ3Bsb3QoYWVzKGZhY3Rvcihjb3VudHJ5LCBsZXZlbHMgPSB0b3AzMGdpbmkpLCBnaW5pLCBmaWxsID0gcmVnaW9uKSkgKyBnZW9tX2NvbCgpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAxLCBoanVzdD0xKSwgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsKICBsYWJzKHRpdGxlID0gIlRvcCAzMCBDb3VudHJpZXMgb2YgUmVjZW50IEdpbmkgSW5kZXgiLCB4ID0gIiIpCmBgYAoKKirogIPlr5/vvJrkuozlnLDln5/jgavpmZDjgonjgozjgabjgYTjgb7jgZkqKgoKIyMjIOWIhuW4g+OCkuWcsOWfn+OBlOOBqOOBrueuseOBsuOBkuWbs+OBp+imi+OBpuOBv+OBvuOBmQoK566x44Gy44GS5Zuz44Go44Gv77yfIFtb44Oq44Oz44KvXShodHRwczovL2JlbGxjdXJ2ZS5qcC9zdGF0aXN0aWNzL2NvdXJzZS81MjE5Lmh0bWwpXQoKYGBge3J9CmRmX2dpbmlfZXh0cmFfcmVjZW50IHw+IGRyb3BfbmEocmVnaW9uKSB8PiBmaWx0ZXIocmVnaW9uICE9ICJBZ2dyZWdhdGVzIikgfD4KICBnZ3Bsb3QoYWVzKGdpbmksIHJlZ2lvbiwgZmlsbCA9IHJlZ2lvbikpICsgZ2VvbV9ib3hwbG90KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICIiKQpgYGAKCiMjIOWNl+OCouODleODquOCq++8leOCq+WbveOBq+OBpOOBhOOBpgoKYGBge3J9ClNPVVRIX0FGUklDQV9GSVZFIDwtIGMoIlNvdXRoIEFmcmljYSIsICJOYW1pYmlhIiwgIkVzd2F0aW5pIiwgIkJvdHN3YW5hIiwgIkxlc290aG8iKQpgYGAKCiMjIyDntYzlubTlpInljJbjgpLooajjgZnmipjjgoznt5rjgrDjg6njg5UKCmBgYHtyfQpkZl9naW5pX2V4dHJhIHw+IGZpbHRlcihjb3VudHJ5ICVpbiUgU09VVEhfQUZSSUNBX0ZJVkUgKSB8PgogIGRyb3BfbmEoZ2luaSkgfD4KICBnZ3Bsb3QoYWVzKHllYXIsIGdpbmksIGNvbCA9IGZhY3Rvcihjb3VudHJ5LCBsZXZlbCA9IFNPVVRIX0FGUklDQV9GSVZFKSkpICsgCiAgZ2VvbV9saW5lKCkgKyBsYWJzKHRpdGxlID0gIkdpbmkgSW5kZXggb2YgRml2ZSBDb3VudHJpZXMiLCBjb2wgPSAiRnJvbSBnaW5pIHRvcCIpCmBgYAoKYGBge3J9CmRmX2dpbmlfZXh0cmFfbG9uZyB8PiBmaWx0ZXIoY291bnRyeSAlaW4lIFNPVVRIX0FGUklDQV9GSVZFICkgfD4KICBkcm9wX25hKHZhbHVlKSB8PgogIGdncGxvdChhZXMoeWVhciwgdmFsdWUsIGNvbCA9IGxldmVscykpICsgZ2VvbV9saW5lKCkgKyBmYWNldF93cmFwKH5mYWN0b3IoY291bnRyeSwgbGV2ZWwgPSBTT1VUSF9BRlJJQ0FfRklWRSkpICsgbGFicyh0aXRsZSA9ICJDaGFuZ2Ugb2YgcmF0aW8gb2YgZWFjaCBsZXZlbCIpCmBgYAoK5pep44GP44GL44KJ44OH44O844K/44GM44GC44KL5Zu944Gu44K444OL5oyH5pWw44GM5L2O44GE44KI44GG44Gr6KaL44GI44KLCgojIyMg5pyA5paw44Gu44OH44O844K/Cgrjg4fjg7zjgr/jga7mlbDjgoLlsJHjgarjgYTjga7jgafjgIHmnIDmlrDjga7jg4fjg7zjgr/jga7jgb/jgavpmZDjgosKCmBgYHtyfQpkZl9naW5pX2V4dHJhX3JlY2VudCB8PiBmaWx0ZXIoY291bnRyeSAlaW4lIFNPVVRIX0FGUklDQV9GSVZFKQpgYGAKCmBTT1VUSF9BRlJJQ0FfRklWRWAg44Gu5Zu944Gu6aCG55Wq44KS44CBR2luaSDmjIfmlbDjga7lpKfjgY3jgYTpoIbjgavkuKbjgbnjgabjgYrjgY8KCiMjIyDjg63jg7zjg6zjg7Pjg4Tmm7Lnt5oKCmBgYHtyfQpkZl9naW5pX2NhbGNfcmVjZW50X2xvbmcgfD4gZmlsdGVyKGNvdW50cnkgJWluJSBTT1VUSF9BRlJJQ0FfRklWRSkgfD4gCiAgZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoYWVzKGNsYXNzZXMsIGN1bXVsYXRpdmVfc2hhcmUsIGNvbCA9IGZhY3Rvcihjb3VudHJ5LCBsZXZlbHMgPSBTT1VUSF9BRlJJQ0FfRklWRSkpKSArIAogIGdlb21fc2VnbWVudChhZXMoeCA9IDAsIHkgPSAwLCB4ZW5kID0gMTAwLCB5ZW5kID0gMTAwLCBjb2wgPSBjb3VudHJ5KSwgY29sb3IgPSAncmVkJykgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsMTAwLGJ5PTIwKSkgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsMTAwLGJ5PTIwKSkgKwogIGxhYnMoY29sID0gIkZyb20gZ2luaSB0b3AiKQpgYGAKCiMjIyDmiYDlvpfjga7libLlkIjjgpLooajjgZnmo5LjgrDjg6njg5UKCmBgYHtyfQpkZl9naW5pX2V4dHJhX2xvbmcgfD4gZmlsdGVyKGNvdW50cnkgJWluJSBTT1VUSF9BRlJJQ0FfRklWRSkgfD4KICBkcm9wX25hKGdpbmkpIHw+IGdyb3VwX2J5KGNvdW50cnkpIHw+IGZpbHRlcih5ZWFyID09IG1heCh5ZWFyKSkgfD4KICBmaWx0ZXIoIShsZXZlbHMgJWluJSBjKCcwLTEwJywnOTAtMTAwJykpKSB8PiAKICBnZ3Bsb3QoYWVzKGZhY3Rvcihjb3VudHJ5LCBsZXZlbHMgPSBTT1VUSF9BRlJJQ0FfRklWRSksIHZhbHVlLCBmaWxsID0gbGV2ZWxzKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIsIGNvbCA9ICJibGFjayIsIGxpbmV3aWR0aCA9IDAuMSkgKwogICBnZW9tX3RleHQoYWVzKGdyb3VwID0gbGV2ZWxzLCBsYWJlbCA9IHZhbHVlKSwgdmp1c3QgPSAtMC4yLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSkgKyAKICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBXZWFsdGggaW4gRml2ZSBDb3VudHJpZXMgaW4gUmVjZW50IFllYXIiLCB4ID0gIiIpCmBgYAoKIyMjIOOCuOODi+aMh+aVsOOBqCBUb3AgMjAlIOOBruWApOOBruebuOmWogoKYGBge3J9CmRmX2dpbmlfZXh0cmFfcmVjZW50IHw+IGZpbHRlcihyZWdpb24gIT0gIkFnZ3JlZ2F0ZXMiKSB8PiBkcm9wX25hKGA4MC0xMDBgKSB8PgogIGdncGxvdChhZXMoZ2luaSwgYDgwLTEwMGApKSArIGdlb21fcG9pbnQoYWVzKGNvbCA9IHJlZ2lvbikpICsgCiAgZ2VvbV9zbW9vdGgoZm9ybXVsYSA9ICd5IH4geCcsIG1ldGhvZCA9ICJsbSIpCmBgYAoKKirogIPlr58qKu+8muOBi+OBquOCiuW8t+OBhOato+OBruebuOmWouOBjOOBguOCiuOAgeWbnuW4sOebtOe3muOBjOOBi+OBquOCiumBqeWQiOOBl+OBpuOBhOOCi+OAggoKIyMg57e057+S77yaIOWbveOBruODquOCueODiOOCkuWkieOBiOOBpuOBv+OCiOOBhgoKIyMjIOWbveOBrumBuOaKngoKYGBge3J9CkNIT1NFTl9HSU5JX0NPVU5UUklFUyA8LSBjKCJTdXJpbmFtZSIsICJCZWxpemUiLCAiQnJhemlsIiwgIkNvbG9tYmlhIikKYGBgCgojIyMg57WM5bm05aSJ5YyW44KS6KGo44GZ5oqY44KM57ea44Kw44Op44OVCgpgYGB7cn0KZGZfZ2luaV9leHRyYSB8PiBmaWx0ZXIoY291bnRyeSAlaW4lIENIT1NFTl9HSU5JX0NPVU5UUklFUykgfD4KICBkcm9wX25hKGdpbmkpIHw+CiAgZ2dwbG90KGFlcyh5ZWFyLCBnaW5pLCBjb2wgPSBmYWN0b3IoY291bnRyeSwgbGV2ZWwgPSBDSE9TRU5fR0lOSV9DT1VOVFJJRVMpKSkgKyAKICBnZW9tX2xpbmUoKSArIGxhYnModGl0bGUgPSAiR2luaSBJbmRleCBvZiBDaG9zZW4gQ291bnRyaWVzIiwgY29sID0gIkZyb20gZ2luaSB0b3AiKQpgYGAKCmBgYHtyfQpkZl9naW5pX2V4dHJhX2xvbmcgfD4gZmlsdGVyKGNvdW50cnkgJWluJSBDSE9TRU5fR0lOSV9DT1VOVFJJRVMpIHw+CiAgZHJvcF9uYSh2YWx1ZSkgfD4KICBnZ3Bsb3QoYWVzKHllYXIsIHZhbHVlLCBjb2wgPSBsZXZlbHMpKSArIGdlb21fbGluZSgpICsgZmFjZXRfd3JhcCh+ZmFjdG9yKGNvdW50cnksIGxldmVsID0gQ0hPU0VOX0dJTklfQ09VTlRSSUVTKSkgKyBsYWJzKHRpdGxlID0gIkNoYW5nZSBvZiByYXRpbyBvZiBlYWNoIGxldmVsIikKYGBgCgoqKuiAg+Wvn++8mioqCgojIyMg5pyA5paw44Gu44OH44O844K/Cgrjg4fjg7zjgr/jga7mlbDjgoLlsJHjgarjgYTjga7jgafjgIHmnIDmlrDjga7jg4fjg7zjgr/jga7jgb/jgavpmZDjgosKCmBgYHtyfQpkZl9naW5pX2V4dHJhX3JlY2VudCB8PiBmaWx0ZXIoY291bnRyeSAlaW4lIENIT1NFTl9HSU5JX0NPVU5UUklFUykKYGBgCgoqKuiAg+Wvn++8mioqCgpgQ0hPU0VOX0dJTklfQ09VTlRSSUVTYCDjga7lm73jga7poIbnlarjgpLjgIFHaW5pIOaMh+aVsOOBruWkp+OBjeOBhOmghuOBq+S4puOBueOBpuOBiuOBjwoKIyMjIOODreODvOODrOODs+ODhOabsue3mgoKYGBge3J9CmRmX2dpbmlfY2FsY19yZWNlbnRfbG9uZyB8PiBmaWx0ZXIoY291bnRyeSAlaW4lIENIT1NFTl9HSU5JX0NPVU5UUklFUykgfD4gCiAgZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoYWVzKGNsYXNzZXMsIGN1bXVsYXRpdmVfc2hhcmUsIGNvbCA9IGZhY3Rvcihjb3VudHJ5LCBsZXZlbHMgPSBDSE9TRU5fR0lOSV9DT1VOVFJJRVMpKSkgKyAKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLCB5ID0gMCwgeGVuZCA9IDEwMCwgeWVuZCA9IDEwMCwgY29sID0gY291bnRyeSksIGNvbG9yID0gJ3JlZCcpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDEwMCxieT0yMCkpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDEwMCxieT0yMCkpICsKICBsYWJzKGNvbCA9ICJGcm9tIHRvcCBnaW5pIikKYGBgCgoqKuiAg+Wvn++8mioqCgojIyMg5omA5b6X44Gu5Ymy5ZCI44KS6KGo44GZ5qOS44Kw44Op44OVCgpgYGB7cn0KZGZfZ2luaV9leHRyYV9sb25nIHw+IGZpbHRlcihjb3VudHJ5ICVpbiUgQ0hPU0VOX0dJTklfQ09VTlRSSUVTKSB8PgogIGRyb3BfbmEoZ2luaSkgfD4gZ3JvdXBfYnkoY291bnRyeSkgfD4gZmlsdGVyKHllYXIgPT0gbWF4KHllYXIpKSB8PgogIGZpbHRlcighKGxldmVscyAlaW4lIGMoJzAtMTAnLCc5MC0xMDAnKSkpIHw+IGRyb3BfbmEodmFsdWUpIHw+CiAgZ2dwbG90KGFlcyhmYWN0b3IoY291bnRyeSwgbGV2ZWxzID0gQ0hPU0VOX0dJTklfQ09VTlRSSUVTKSwgdmFsdWUsIGZpbGwgPSBsZXZlbHMpKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIiwgY29sID0gImJsYWNrIiwgbGluZXdpZHRoID0gMC4xKSArCiAgIGdlb21fdGV4dChhZXMoZ3JvdXAgPSBsZXZlbHMsIGxhYmVsID0gdmFsdWUpLCB2anVzdCA9IC0wLjIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpKSArIAogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFdlYWx0aCBpbiBDaG9zZW4gQ291bnRyaWVzIGluIFJlY2VudCBZZWFyIiwgeCA9ICIiKQpgYGAKCioq6ICD5a+f77yaKioK