世界開発指標(World Development Indicators)[Link]
貧困と不平等(Poverty and Inequality)
所得または消費の分配(Distribution of income or
consumption)
GINI 指数 (世界銀行推計):SI.POV.GINI [Link]
下位 10% が占める所得シェア:SI.DST.FRST.10 [Link]
下位 20% が占める所得シェア:SI.DST.FRST.20 [Link]
2番目の 20% が占める収入シェア:SI.DST.02ND.20 [Link]
3番目の 20% が占める収入シェア :SI.DST.03RD.20 [Link]
4番目の 20% が占める収入シェア:SI.DST.04TH.20 [Link]
上位 20% が占める収入シェア:SI.DST.05TH.20 [Link]
上位 10% が占める収入シェア:SI.DST.10TH.10 [Link]
前回(12月19日)の復習
パッケージ(Package)の利用:
データの取得:WDI(indicator = c(pop = "SP.POP.TOTL"))
特定の行の取得:filter(), drop_na(), distinct()
折れ線グラフ
ggplot(aes(x = year, y = pop) + geom_line()
ggplot(aes(x = year, y = pop, col = country) + geom_line()
今回の演習の内容
パッケージ(Package)インストール(コンピュータに入れておく):DescTools
パッケージのロード(すぐ使えるようにする):tidyverse
,
WDI
, DescTools
データの取得:WDI()
特定の条件にあった行を選択:filter()
新しい列を他の列から計算して加える:mutate()
順番に、変形、視覚化などをするためのパイプ:|>
(または、%>%
)
ヒストグラム(度数分布):ggplot(…) + geom_histogram()
棒グラフ:ggplot(…) + geom_col(), ggplot(…) + geom_bar()
指標について
何のデータか、変数はどのようなものか、定義は?など、確認。データのURL
を記録するのもたいせつ。
GINI index (World Bank estimate);SI.POV.GINI [Link]
Gini index measures the extent to which the distribution of
income (or, in some cases, consumption expenditure) among individuals or
households within an economy deviates from a perfectly equal
distribution. A Lorenz curve plots the cumulative percentages of total
income received against the cumulative number of recipients, starting
with the poorest individual or household. The Gini index measures the
area between the Lorenz curve and a hypothetical line of absolute
equality, expressed as a percentage of the maximum area under the line.
Thus a Gini index of 0 represents perfect equality, while an index of
100 implies perfect inequality.
ジニ指数は、経済内の個人または世帯間の所得(または場合によっては消費支出)の分布が、完全に平等な分布からどの程度逸脱しているかを測定する。ローレンツ曲線は、最も貧しい個人または世帯から始まり、受給者の累積数に対する総所得の累積割合をプロットしたものである。ジニ指数は、ローレンツ曲線と絶対的平等の仮想線との間の面積を測定するもので、線の下の最大面積の百分率で表される。したがって、ジニ指数0は完全な平等を表し、指数100は完全な不平等を意味する。
Income share held by lowest 10%:SI.DST.FRST.10 [Link]
Income share held by lowest 20%:SI.DST.FRST.20 [Link]
Percentage share of income or consumption is the share that
accrues to subgroups of population indicated by deciles or quintiles.
Percentage shares by quintile may not sum to 100 because of
rounding.
所得または消費の割合は、デシルまたは五分位数で示される人口のサブグループに発生する割合です。五分位数によるシェアの割合は、四捨五入のため100にならない場合があります。(Apple)
Income share held by second 20%:SI.DST.02ND.20 [Link]
Percentage share of income or consumption is the share that
accrues to subgroups of population indicated by deciles or quintiles.
Percentage shares by quintile may not sum to 100 because of
rounding.
所得または消費に占める割合は、10分位または5分位で示される人口のサブグループに帰属する割合である。四捨五入の関係上、五分位階級別の割合の合計が100にならない場合がある。(DeepL)
Income share held by third 20%:SI.DST.03RD.20 [Link]
Percentage share of income or consumption is the share that
accrues to subgroups of population indicated by deciles or quintiles.
Percentage shares by quintile may not sum to 100 because of
rounding.
所得または消費に占める割合は、10分位または5分位で示される人口のサブグループに帰属する割合である。四捨五入の関係上、五分位階級別の割合の合計が100にならない場合がある。(DeepL)
Income share held by fourth 20%:SI.DST.04TH.20 [Link]
Percentage share of income or consumption is the share that
accrues to subgroups of population indicated by deciles or quintiles.
Percentage shares by quintile may not sum to 100 because of
rounding.
所得または消費の割合は、十分位数または五分位数で示される人口のサブグループに生じる割合です。四捨五入のため、五分位別の割合の合計が
100 にならない場合があります。(Google)
Income share held by highest 20%:SI.DST.05TH.20 [Link]
Percentage share of income or consumption is the share that
accrues to subgroups of population indicated by deciles or quintiles.
Percentage shares by quintile may not sum to 100 because of
rounding.
所得または消費の割合は、十分位数または五分位数で示される人口のサブグループに生じる割合です。四捨五入のため、五分位別の割合の合計が
100 にならない場合があります。
Income share held by highest 10%:SI.DST.10TH.10 [Link]
準備
毎回 tidyverse
と WDI
と
DescTools
を使いますから、R Notebook
の最初には、次のコードチャンクを作成し、実行(Run)します。これらの(機能を拡張する)パッケージがインストールされていない場合は、インストールします。Tools>Install
Packages …
library(tidyverse)
library(WDI)
library(DescTools)
データの読み込み
df_gini <- 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"))
保存と読み込み
何度もダウンロードしなくて良いように、保存したものを読み込みます。
write_csv(df_gini, "data/gini.csv")
df_gini <- read_csv("data/gini.csv")
Rows: 16758 Columns: 12── Column specification ─────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): country, iso2c, iso3c
dbl (9): year, gini, 0-10, 0-20, 20-40, 40-60, 60-80, 80-100, 90-100
ℹ 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.
gini が NA ではない値のもののみ表示します
df_gini |> drop_na(gini)
整えられた(tidy)データ
階級(levels)を変数として扱うために、このように変形しました。
どのくらい GINI のデータがあるか確かめる
df_gini |> drop_na(gini) |>
ggplot(aes(year)) + geom_bar()
実際には、次のような計算をして、棒グラフで表示しています。
group_by(year)
年ごとにグループとする
summarize(n = n())
それぞれのグループごとのデータを数えます。直前に、drop_na(gini)
としてあるので、gini
が NA
ではないデータの数を数えています。
棒グラフ:ggplot(aes(year, n)) + geom_col()
すなわち、次のものと同じです。
df_gini |> group_by(year) |> drop_na(gini) |>
summarize(n = n()) |>
ggplot(aes(year, n)) + geom_col()
実際のデータの個数
df_gini_long |>
group_by(year, levels) |> drop_na(value) |>
summarize(num = n()) |> distinct(year, num) |> arrange(desc(year))
`summarise()` has grouped output by 'year'. You can override using the `.groups` argument.
2022年にデータが存在する7つの国名を表示
df_gini_long |> filter(year == 2022) |> drop_na(value) |>
distinct(country, gini) |> arrange(gini)
7カ国のいくつかについて調べる
x = levels
とし、y = value
とするところで、Long にした効果が出ています。
COUNTRY_GINI <- "Bhutan"
YEAR_GINI <- 2022
df_gini_long |> filter(levels != "gini") |>
filter(country == COUNTRY_GINI, year == YEAR_GINI) |>
ggplot(aes(levels, value)) + geom_col()
COUNTRY_GINI <- "Bangladesh"
YEAR_GINI <- 2022
df_gini_long |> filter(levels != "gini") |>
filter(country == COUNTRY_GINI, year == YEAR_GINI) |>
ggplot(aes(levels, value)) + geom_col()
COUNTRY_GINI <- "Costa Rica"
YEAR_GINI <- 2022
df_gini_long |> filter(levels != "gini") |>
filter(country == COUNTRY_GINI, year == YEAR_GINI) |>
ggplot(aes(levels, value)) + geom_col()
練習1. Indonesia, El Salvador, Paraguay, Ecuador
のいずれかについてグラフを描いてみましょう。
並べて描いてみましょう
ジニ指数は小さいほうから、Bhutan, Bangladesh, Indonesia, El Salvador,
Paraguay, Equador, Costa Rica でした。
df_gini_long |> filter(year == 2022) |>
filter(levels != "gini") |> drop_na(value) |>
ggplot(aes(levels, value)) + geom_col() + facet_wrap(~country)
考えてみよう
最後下がっているのは正常?
どのように表示するのがよいのだろうか。
これらの図をみて、ジニ指数の大きさについてわかりますか。
このデータから、ジニ指数を計算するには、どうしたら良いのだろうか。
ジニ指数の計算
Derivation of the Lorenz curve and Gini coefficient for global income
in 2011 [リンク]
ジニ指数を計算するために変換
df_gini_calc <- df_gini |>
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_long <- df_gini_calc |> 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_long |> filter(country == "Bangladesh") |>
filter(year == 2022) |> 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)
4カ国をジニ指数順にならべた棒グラフ
COUNTRIES_GINI <- c("Bhutan", "Bangladesh","Indonesia","Costa Rica")
YEAR_GINI <- 2022
df_gini_long |>
filter(country %in% COUNTRIES_GINI, year == YEAR_GINI) |>
ggplot(aes(levels, value, fill = factor(country, levels = COUNTRIES_GINI))) + geom_col(position = "dodge") + labs(fill = "")
練習2. 7カ国すべてについて、80-100 と、90-100
の部分だけ、表示できないでしょうか。(難:答えは一番下)
2000年のジニ指数と90%以上の割合の相関
df_gini |>
filter(year == 2000) |> drop_na(gini) |>
ggplot(aes(gini, `90-100`)) + geom_point() +
geom_smooth(formula = 'y ~ x', method = "lm")
練習3.
2000年(または他の年の)ジニ指数と80%以上の割合の相関
復習
パッケージ(Package)の利用:
データの取得:WDI(indicator = c(gini = "SI.POV.GINI",`0-10` = "SI.DST.FRST.10",...,`90-100` = "SI.DST.10TH.10"))
特定の行の取得:filter(), drop_na(), distinct()
棒グラフ
ggplot(aes(year)) + geom_bar()
ggplot(aes(levels, value)) + geom_col()
ggplot(aes(x = levels, y = value, fill = country)) + geom_col(position = "dodge")
ggplot(aes(x = gini, fill = region)) + geom_histogram()
散布図(+回帰直線)
ggplot(aes(gini, 90-100)) + geom_point()
ggplot(aes(gini, 80-100)) + geom_point() + geom_smooth(formula = 'y ~ x', method = "lm")
課題
練習1 から練習3.
提出はしなくて良いですが、ぜひ実際に手を動かして実行してください。
参考文献
「みんなのデータサイエンス - Data Science for All」[はじめてのデータサイエンス]
- 導入として、GDP(国内総生産)のデータを使って説明しています。
Posit Recipes(旧 Posit Primers): The Basics
対話型の演習サイトの最初 [Link]
Posit Cheat Sheet. 早見表です。印刷して使うために、PDF
も提供しています。[Site
Link]
DataCamp Cheat Sheet: Tidyverse for Biginners.
データサイエンスの教育をしている会社の早見表の一つです。基本が簡単にまとまっています。[Link]
参考1
階級を 10% 刻みに統一し、Long 形式に変換。
df_gini_rev <- df_gini |>
mutate(`0-10` = `0-10`, `10-20` = `0-20`-`0-10`,`20-30` = `20-40`/2, `30-40` = `20-40`/2, `40-50` = `40-60`/2, `50-60` = `40-60`/2, `60-70` = `60-80`/2, `70-80`=`60-80`/2, `80-90` = `80-100`-`90-100`, `90-100` = `90-100`) |>
select(-c(`0-20`, `20-40`,`40-60`,`60-80`, `80-100`)) |>
select(1:6, 8:15, 7)
df_gini_rev %>% drop_na()
df_gini_rev_long <- df_gini_rev |> pivot_longer(6:15, names_to = "levels", values_to = "value")
df_gini_rev_long
df_gini_rev_long |> filter(year == 2022) |> drop_na(gini) |>
ggplot(aes(levels, value)) + geom_col() +
facet_wrap(~country, ncol = 2)
参考2
曲線の下の面積を計算する AUC を利用して、ジニ係数を計算。
Area Under the Curve: [リンク]
https://rdrr.io/cran/DescTools/f/
df_gini_calc_long |> group_by(country, year) |>
drop_na(gini) |>
reframe(gini, gini_spline = round(100-AUC(classes, cumulative_share, method = "spline")/50, digits = 1), gini_trapezoid = round(100-AUC(classes, cumulative_share)/50, digits = 1)) |>
distinct(country, year, gini, gini_spline, gini_trapezoid)
練習2の答え
SEVEN_COUNTRIES <- c("Bhutan", "Bangladesh","Indonesia","El Salvador", "Paraguay", "Equador", "Costa Rica")
YEAR_GINI <- 2022
df_gini_long |>
filter(country %in% SEVEN_COUNTRIES, year == YEAR_GINI) |>
filter(levels %in% c('80-100','90-100')) |>
ggplot(aes(levels, value, fill = factor(country, levels = SEVEN_COUNTRIES))) + geom_col(position = "dodge", col = "black", linewidth = 0.2) + labs(fill = "")
LS0tCnRpdGxlOiAi44K444OL5oyH5pWw44Go5omA5b6X5YiG5biDIgphdXRob3I6ICJILiBTdXp1a2kiCmRhdGU6ICIyMDI05bm0MeaciDnml6UiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKIyMg5LiW55WM6ZaL55m65oyH5qiZ77yIV29ybGQgRGV2ZWxvcG1lbnQgSW5kaWNhdG9yc++8iVtbTGlua10oaHR0cHM6Ly9kYXRhdG9waWNzLndvcmxkYmFuay5vcmcvd29ybGQtZGV2ZWxvcG1lbnQtaW5kaWNhdG9ycy8pXQoKIyMjIyAqKuiyp+WbsOOBqOS4jeW5s+etie+8iFBvdmVydHkgYW5kIEluZXF1YWxpdHnvvIkqKgoKKirmiYDlvpfjgb7jgZ/jga/mtojosrvjga7liIbphY3vvIhEaXN0cmlidXRpb24gb2YgaW5jb21lIG9yIGNvbnN1bXB0aW9u77yJKioKCkdJTkkg5oyH5pWwICjkuJbnlYzpioDooYzmjqjoqIgp77yaU0kuUE9WLkdJTkkgW1tMaW5rXShodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy9pbmRpY2F0b3IvU0kuUE9WLkdJTkkpXQoK5LiL5L2NIDEwJSDjgYzljaDjgoHjgovmiYDlvpfjgrfjgqfjgqLvvJpTSS5EU1QuRlJTVC4xMCBbW0xpbmtdKGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9tZXRhZGF0YWdsb3NzYXJ5L3dvcmxkLWRldmVsb3BtZW50LWluZGljYXRvcnMvc2VyaWVzL1NJLkRTVC5GUlNULjEwKV0KCuS4i+S9jSAyMCUg44GM5Y2g44KB44KL5omA5b6X44K344Kn44Ki77yaU0kuRFNULkZSU1QuMjAgW1tMaW5rXShodHRwczovL2RhdGFiYW5rLndvcmxkYmFuay5vcmcvbWV0YWRhdGFnbG9zc2FyeS93b3JsZC1kZXZlbG9wbWVudC1pbmRpY2F0b3JzL3Nlcmllcy9TSS5EU1QuRlJTVC4yMCldCgoy55Wq55uu44GuIDIwJSDjgYzljaDjgoHjgovlj47lhaXjgrfjgqfjgqLvvJpTSS5EU1QuMDJORC4yMCBbW0xpbmtdKGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9tZXRhZGF0YWdsb3NzYXJ5L3dvcmxkLWRldmVsb3BtZW50LWluZGljYXRvcnMvc2VyaWVzL1NJLkRTVC4wMk5ELjIwKV0KCjPnlarnm67jga4gMjAlIOOBjOWNoOOCgeOCi+WPjuWFpeOCt+OCp+OCoiDvvJpTSS5EU1QuMDNSRC4yMCBbW0xpbmtdKGh0dHBzOi8vZGF0YS53b3JsZGJhbmsub3JnL2luZGljYXRvci9TSS5EU1QuMDNSRC4yMCldCgo055Wq55uu44GuIDIwJSDjgYzljaDjgoHjgovlj47lhaXjgrfjgqfjgqLvvJpTSS5EU1QuMDRUSC4yMCBbW0xpbmtdKGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9tZXRhZGF0YWdsb3NzYXJ5L3dvcmxkLWRldmVsb3BtZW50LWluZGljYXRvcnMvc2VyaWVzL1NJLkRTVC4wNFRILjIwKV0KCuS4iuS9jSAyMCUg44GM5Y2g44KB44KL5Y+O5YWl44K344Kn44Ki77yaU0kuRFNULjA1VEguMjAgW1tMaW5rXShodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy9pbmRpY2F0b3IvU0kuRFNULjA1VEguMjApXQoK5LiK5L2NIDEwJSDjgYzljaDjgoHjgovlj47lhaXjgrfjgqfjgqLvvJpTSS5EU1QuMTBUSC4xMCBbW0xpbmtdKGh0dHBzOi8vZGF0YS53b3JsZGJhbmsub3JnL2luZGljYXRvci9TSS5EU1QuMTBUSC4xMCldCgojIyDliY3lm57vvIgxMuaciDE55pel77yJ44Gu5b6p57+SCgotICAg44OR44OD44Kx44O844K477yIUGFja2FnZe+8ieOBruWIqeeUqO+8mgoKICAgIC0gICDjgqTjg7Pjgrnjg4jjg7zjg6vvvIhpbnN0YWxsYXRpb27vvInvvJpUb29scyBcPiBJbnN0YWxsIFBhY2thZ2VzCgogICAgLSAgIOODreODvOODie+8iGxvYWTvvIlgbGlicmFyeSh0aWR5dmVyc2UpOyBsaWJyYXJ5KFdESSk7IGxpYnJhcnkoc2hvd3RleHQpYAoKLSAgIOODh+ODvOOCv+OBruWPluW+l++8mmBXREkoaW5kaWNhdG9yID0gYyhwb3AgPSAiU1AuUE9QLlRPVEwiKSlgCgotICAg54m55a6a44Gu6KGM44Gu5Y+W5b6X77yaYGZpbHRlcigpLCBkcm9wX25hKCksIGRpc3RpbmN0KClgCgotICAg5oqY44KM57ea44Kw44Op44OVCgogICAgLSAgIGBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gcG9wKSArIGdlb21fbGluZSgpYAoKICAgIC0gICBgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHBvcCwgY29sID0gY291bnRyeSkgKyBnZW9tX2xpbmUoKWAKCiMjIOS7iuWbnuOBrua8lOe/kuOBruWGheWuuQoKLSAgIOODkeODg+OCseODvOOCuO+8iFBhY2thZ2XvvInjgqTjg7Pjgrnjg4jjg7zjg6vvvIjjgrPjg7Pjg5Tjg6Xjg7zjgr/jgavlhaXjgozjgabjgYrjgY/vvInvvJpgRGVzY1Rvb2xzYAoKLSAgIOODkeODg+OCseODvOOCuOOBruODreODvOODie+8iOOBmeOBkOS9v+OBiOOCi+OCiOOBhuOBq+OBmeOCi++8ie+8mmB0aWR5dmVyc2VgLCBgV0RJYCwgYERlc2NUb29sc2AKCi0gICDjg4fjg7zjgr/jga7lj5blvpfvvJpgV0RJKClgCgotICAg54m55a6a44Gu5p2h5Lu244Gr44GC44Gj44Gf6KGM44KS6YG45oqe77yaYGZpbHRlcigpYAoKLSAgIOaWsOOBl+OBhOWIl+OCkuS7luOBruWIl+OBi+OCieioiOeul+OBl+OBpuWKoOOBiOOCi++8mmBtdXRhdGUoKWAKCi0gICDpoIbnlarjgavjgIHlpInlvaLjgIHoppbopprljJbjgarjganjgpLjgZnjgovjgZ/jgoHjga7jg5HjgqTjg5fvvJpgfD5gIO+8iOOBvuOBn+OBr+OAgWAlPiVg77yJCgotICAg44OS44K544OI44Kw44Op44Og77yI5bqm5pWw5YiG5biD77yJ77yaZ2dwbG90KC4uLikgKyBnZW9tX2hpc3RvZ3JhbSgpCgotICAg5qOS44Kw44Op44OV77yaZ2dwbG90KC4uLikgKyBnZW9tX2NvbCgpLCBnZ3Bsb3QoLi4uKSArIGdlb21fYmFyKCkKCiMjIyDmjIfmqJnjgavjgaTjgYTjgaYKCuS9leOBruODh+ODvOOCv+OBi+OAgeWkieaVsOOBr+OBqeOBruOCiOOBhuOBquOCguOBruOBi+OAgeWumue+qeOBr++8n+OBquOBqeOAgeeiuuiqjeOAguODh+ODvOOCv+OBrlVSTCDjgpLoqJjpjLLjgZnjgovjga7jgoLjgZ/jgYTjgZvjgaTjgIIKCi0gICBHSU5JIGluZGV4IChXb3JsZCBCYW5rIGVzdGltYXRlKe+8m1NJLlBPVi5HSU5JIFtbTGlua10oaHR0cHM6Ly9kYXRhLndvcmxkYmFuay5vcmcvaW5kaWNhdG9yL1NJLlBPVi5HSU5JKV0KCiAgICAtICAgR2luaSBpbmRleCBtZWFzdXJlcyB0aGUgZXh0ZW50IHRvIHdoaWNoIHRoZSBkaXN0cmlidXRpb24gb2YgaW5jb21lIChvciwgaW4gc29tZSBjYXNlcywgY29uc3VtcHRpb24gZXhwZW5kaXR1cmUpIGFtb25nIGluZGl2aWR1YWxzIG9yIGhvdXNlaG9sZHMgd2l0aGluIGFuIGVjb25vbXkgZGV2aWF0ZXMgZnJvbSBhIHBlcmZlY3RseSBlcXVhbCBkaXN0cmlidXRpb24uIEEgTG9yZW56IGN1cnZlIHBsb3RzIHRoZSBjdW11bGF0aXZlIHBlcmNlbnRhZ2VzIG9mIHRvdGFsIGluY29tZSByZWNlaXZlZCBhZ2FpbnN0IHRoZSBjdW11bGF0aXZlIG51bWJlciBvZiByZWNpcGllbnRzLCBzdGFydGluZyB3aXRoIHRoZSBwb29yZXN0IGluZGl2aWR1YWwgb3IgaG91c2Vob2xkLiBUaGUgR2luaSBpbmRleCBtZWFzdXJlcyB0aGUgYXJlYSBiZXR3ZWVuIHRoZSBMb3JlbnogY3VydmUgYW5kIGEgaHlwb3RoZXRpY2FsIGxpbmUgb2YgYWJzb2x1dGUgZXF1YWxpdHksIGV4cHJlc3NlZCBhcyBhIHBlcmNlbnRhZ2Ugb2YgdGhlIG1heGltdW0gYXJlYSB1bmRlciB0aGUgbGluZS4gVGh1cyBhIEdpbmkgaW5kZXggb2YgMCByZXByZXNlbnRzIHBlcmZlY3QgZXF1YWxpdHksIHdoaWxlIGFuIGluZGV4IG9mIDEwMCBpbXBsaWVzIHBlcmZlY3QgaW5lcXVhbGl0eS4KCiAgICAtICAg44K444OL5oyH5pWw44Gv44CB57WM5riI5YaF44Gu5YCL5Lq644G+44Gf44Gv5LiW5biv6ZaT44Gu5omA5b6X77yI44G+44Gf44Gv5aC05ZCI44Gr44KI44Gj44Gm44Gv5raI6LK75pSv5Ye677yJ44Gu5YiG5biD44GM44CB5a6M5YWo44Gr5bmz562J44Gq5YiG5biD44GL44KJ44Gp44Gu56iL5bqm6YC46ISx44GX44Gm44GE44KL44GL44KS5ris5a6a44GZ44KL44CC44Ot44O844Os44Oz44OE5puy57ea44Gv44CB5pyA44KC6LKn44GX44GE5YCL5Lq644G+44Gf44Gv5LiW5biv44GL44KJ5aeL44G+44KK44CB5Y+X57Wm6ICF44Gu57Sv56mN5pWw44Gr5a++44GZ44KL57eP5omA5b6X44Gu57Sv56mN5Ymy5ZCI44KS44OX44Ot44OD44OI44GX44Gf44KC44Gu44Gn44GC44KL44CC44K444OL5oyH5pWw44Gv44CB44Ot44O844Os44Oz44OE5puy57ea44Go57W25a++55qE5bmz562J44Gu5Luu5oOz57ea44Go44Gu6ZaT44Gu6Z2i56mN44KS5ris5a6a44GZ44KL44KC44Gu44Gn44CB57ea44Gu5LiL44Gu5pyA5aSn6Z2i56mN44Gu55m+5YiG546H44Gn6KGo44GV44KM44KL44CC44GX44Gf44GM44Gj44Gm44CB44K444OL5oyH5pWwMOOBr+WujOWFqOOBquW5s+etieOCkuihqOOBl+OAgeaMh+aVsDEwMOOBr+WujOWFqOOBquS4jeW5s+etieOCkuaEj+WRs+OBmeOCi+OAggoKLSAgIEluY29tZSBzaGFyZSBoZWxkIGJ5IGxvd2VzdCAxMCXvvJpTSS5EU1QuRlJTVC4xMCBbW0xpbmtdKGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9tZXRhZGF0YWdsb3NzYXJ5L3dvcmxkLWRldmVsb3BtZW50LWluZGljYXRvcnMvc2VyaWVzL1NJLkRTVC5GUlNULjEwKV0KCiAgICAtICAgUGVyY2VudGFnZSBzaGFyZSBvZiBpbmNvbWUgb3IgY29uc3VtcHRpb24gaXMgdGhlIHNoYXJlIHRoYXQgYWNjcnVlcyB0byBzdWJncm91cHMgb2YgcG9wdWxhdGlvbiBpbmRpY2F0ZWQgYnkgZGVjaWxlcyBvciBxdWludGlsZXMuCgogICAgLSAgIOaJgOW+l+OBvuOBn+OBr+a2iOiyu+OBruWJsuWQiOOBr+OAgeODh+OCt+ODq+OBvuOBn+OBr+S6lOWIhuS9jeaVsOOBp+ekuuOBleOCjOOCi+S6uuWPo+OBruOCteODluOCsOODq+ODvOODl+OBq+eZuueUn+OBmeOCi+WJsuWQiOOBp+OBmeOAggoKLSAgIEluY29tZSBzaGFyZSBoZWxkIGJ5IGxvd2VzdCAyMCXvvJpTSS5EU1QuRlJTVC4yMCBbW0xpbmtdKGh0dHBzOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9tZXRhZGF0YWdsb3NzYXJ5L3dvcmxkLWRldmVsb3BtZW50LWluZGljYXRvcnMvc2VyaWVzL1NJLkRTVC5GUlNULjIwKV0KCiAgICAtICAgUGVyY2VudGFnZSBzaGFyZSBvZiBpbmNvbWUgb3IgY29uc3VtcHRpb24gaXMgdGhlIHNoYXJlIHRoYXQgYWNjcnVlcyB0byBzdWJncm91cHMgb2YgcG9wdWxhdGlvbiBpbmRpY2F0ZWQgYnkgZGVjaWxlcyBvciBxdWludGlsZXMuIFBlcmNlbnRhZ2Ugc2hhcmVzIGJ5IHF1aW50aWxlIG1heSBub3Qgc3VtIHRvIDEwMCBiZWNhdXNlIG9mIHJvdW5kaW5nLgoKICAgIC0gICDmiYDlvpfjgb7jgZ/jga/mtojosrvjga7libLlkIjjga/jgIHjg4fjgrfjg6vjgb7jgZ/jga/kupTliIbkvY3mlbDjgafnpLrjgZXjgozjgovkurrlj6Pjga7jgrXjg5bjgrDjg6vjg7zjg5fjgavnmbrnlJ/jgZnjgovlibLlkIjjgafjgZnjgILkupTliIbkvY3mlbDjgavjgojjgovjgrfjgqfjgqLjga7libLlkIjjga/jgIHlm5vmjajkupTlhaXjga7jgZ/jgoExMDDjgavjgarjgonjgarjgYTloLTlkIjjgYzjgYLjgorjgb7jgZnjgIIoQXBwbGUpCgotICAgSW5jb21lIHNoYXJlIGhlbGQgYnkgc2Vjb25kIDIwJe+8mlNJLkRTVC4wMk5ELjIwIFtbTGlua10oaHR0cHM6Ly9kYXRhYmFuay53b3JsZGJhbmsub3JnL21ldGFkYXRhZ2xvc3Nhcnkvd29ybGQtZGV2ZWxvcG1lbnQtaW5kaWNhdG9ycy9zZXJpZXMvU0kuRFNULjAyTkQuMjApXQoKICAgIC0gICBQZXJjZW50YWdlIHNoYXJlIG9mIGluY29tZSBvciBjb25zdW1wdGlvbiBpcyB0aGUgc2hhcmUgdGhhdCBhY2NydWVzIHRvIHN1Ymdyb3VwcyBvZiBwb3B1bGF0aW9uIGluZGljYXRlZCBieSBkZWNpbGVzIG9yIHF1aW50aWxlcy4gUGVyY2VudGFnZSBzaGFyZXMgYnkgcXVpbnRpbGUgbWF5IG5vdCBzdW0gdG8gMTAwIGJlY2F1c2Ugb2Ygcm91bmRpbmcuCgogICAgLSAgIOaJgOW+l+OBvuOBn+OBr+a2iOiyu+OBq+WNoOOCgeOCi+WJsuWQiOOBr+OAgTEw5YiG5L2N44G+44Gf44GvNeWIhuS9jeOBp+ekuuOBleOCjOOCi+S6uuWPo+OBruOCteODluOCsOODq+ODvOODl+OBq+W4sOWxnuOBmeOCi+WJsuWQiOOBp+OBguOCi+OAguWbm+aNqOS6lOWFpeOBrumWouS/guS4iuOAgeS6lOWIhuS9jemajue0muWIpeOBruWJsuWQiOOBruWQiOioiOOBjDEwMOOBq+OBquOCieOBquOBhOWgtOWQiOOBjOOBguOCi+OAgu+8iERlZXBM77yJCgotICAgSW5jb21lIHNoYXJlIGhlbGQgYnkgdGhpcmQgMjAl77yaU0kuRFNULjAzUkQuMjAgW1tMaW5rXShodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy9pbmRpY2F0b3IvU0kuRFNULjAzUkQuMjApXQoKICAgIC0gICBQZXJjZW50YWdlIHNoYXJlIG9mIGluY29tZSBvciBjb25zdW1wdGlvbiBpcyB0aGUgc2hhcmUgdGhhdCBhY2NydWVzIHRvIHN1Ymdyb3VwcyBvZiBwb3B1bGF0aW9uIGluZGljYXRlZCBieSBkZWNpbGVzIG9yIHF1aW50aWxlcy4gUGVyY2VudGFnZSBzaGFyZXMgYnkgcXVpbnRpbGUgbWF5IG5vdCBzdW0gdG8gMTAwIGJlY2F1c2Ugb2Ygcm91bmRpbmcuCgogICAgLSAgIOaJgOW+l+OBvuOBn+OBr+a2iOiyu+OBq+WNoOOCgeOCi+WJsuWQiOOBr+OAgTEw5YiG5L2N44G+44Gf44GvNeWIhuS9jeOBp+ekuuOBleOCjOOCi+S6uuWPo+OBruOCteODluOCsOODq+ODvOODl+OBq+W4sOWxnuOBmeOCi+WJsuWQiOOBp+OBguOCi+OAguWbm+aNqOS6lOWFpeOBrumWouS/guS4iuOAgeS6lOWIhuS9jemajue0muWIpeOBruWJsuWQiOOBruWQiOioiOOBjDEwMOOBq+OBquOCieOBquOBhOWgtOWQiOOBjOOBguOCi+OAgu+8iERlZXBM77yJCgotICAgSW5jb21lIHNoYXJlIGhlbGQgYnkgZm91cnRoIDIwJe+8mlNJLkRTVC4wNFRILjIwIFtbTGlua10oaHR0cHM6Ly9kYXRhYmFuay53b3JsZGJhbmsub3JnL21ldGFkYXRhZ2xvc3Nhcnkvd29ybGQtZGV2ZWxvcG1lbnQtaW5kaWNhdG9ycy9zZXJpZXMvU0kuRFNULjA0VEguMjApXQoKICAgIC0gICBQZXJjZW50YWdlIHNoYXJlIG9mIGluY29tZSBvciBjb25zdW1wdGlvbiBpcyB0aGUgc2hhcmUgdGhhdCBhY2NydWVzIHRvIHN1Ymdyb3VwcyBvZiBwb3B1bGF0aW9uIGluZGljYXRlZCBieSBkZWNpbGVzIG9yIHF1aW50aWxlcy4gUGVyY2VudGFnZSBzaGFyZXMgYnkgcXVpbnRpbGUgbWF5IG5vdCBzdW0gdG8gMTAwIGJlY2F1c2Ugb2Ygcm91bmRpbmcuCgogICAgLSAgIOaJgOW+l+OBvuOBn+OBr+a2iOiyu+OBruWJsuWQiOOBr+OAgeWNgeWIhuS9jeaVsOOBvuOBn+OBr+S6lOWIhuS9jeaVsOOBp+ekuuOBleOCjOOCi+S6uuWPo+OBruOCteODluOCsOODq+ODvOODl+OBq+eUn+OBmOOCi+WJsuWQiOOBp+OBmeOAguWbm+aNqOS6lOWFpeOBruOBn+OCgeOAgeS6lOWIhuS9jeWIpeOBruWJsuWQiOOBruWQiOioiOOBjCAxMDAg44Gr44Gq44KJ44Gq44GE5aC05ZCI44GM44GC44KK44G+44GZ44CCKEdvb2dsZSkKCi0gICBJbmNvbWUgc2hhcmUgaGVsZCBieSBoaWdoZXN0IDIwJe+8mlNJLkRTVC4wNVRILjIwIFtbTGlua10oaHR0cHM6Ly9kYXRhLndvcmxkYmFuay5vcmcvaW5kaWNhdG9yL1NJLkRTVC4wNVRILjIwKV0KCiAgICAtICAgUGVyY2VudGFnZSBzaGFyZSBvZiBpbmNvbWUgb3IgY29uc3VtcHRpb24gaXMgdGhlIHNoYXJlIHRoYXQgYWNjcnVlcyB0byBzdWJncm91cHMgb2YgcG9wdWxhdGlvbiBpbmRpY2F0ZWQgYnkgZGVjaWxlcyBvciBxdWludGlsZXMuIFBlcmNlbnRhZ2Ugc2hhcmVzIGJ5IHF1aW50aWxlIG1heSBub3Qgc3VtIHRvIDEwMCBiZWNhdXNlIG9mIHJvdW5kaW5nLgoKICAgIC0gICDmiYDlvpfjgb7jgZ/jga/mtojosrvjga7libLlkIjjga/jgIHljYHliIbkvY3mlbDjgb7jgZ/jga/kupTliIbkvY3mlbDjgafnpLrjgZXjgozjgovkurrlj6Pjga7jgrXjg5bjgrDjg6vjg7zjg5fjgavnlJ/jgZjjgovlibLlkIjjgafjgZnjgILlm5vmjajkupTlhaXjga7jgZ/jgoHjgIHkupTliIbkvY3liKXjga7libLlkIjjga7lkIjoqIjjgYwgMTAwIOOBq+OBquOCieOBquOBhOWgtOWQiOOBjOOBguOCiuOBvuOBmeOAggoKLSAgIEluY29tZSBzaGFyZSBoZWxkIGJ5IGhpZ2hlc3QgMTAl77yaU0kuRFNULjEwVEguMTAgW1tMaW5rXShodHRwczovL2RhdGEud29ybGRiYW5rLm9yZy9pbmRpY2F0b3IvU0kuRFNULjEwVEguMTApXQoKICAgIC0gICBQZXJjZW50YWdlIHNoYXJlIG9mIGluY29tZSBvciBjb25zdW1wdGlvbiBpcyB0aGUgc2hhcmUgdGhhdCBhY2NydWVzIHRvIHN1Ymdyb3VwcyBvZiBwb3B1bGF0aW9uIGluZGljYXRlZCBieSBkZWNpbGVzIG9yIHF1aW50aWxlcy4KCiAgICAtICAg5omA5b6X44G+44Gf44Gv5raI6LK744Gu5Ymy5ZCI44Gv44CB5Y2B5YiG5L2N5pWw44G+44Gf44Gv5LqU5YiG5L2N5pWw44Gn56S644GV44KM44KL5Lq65Y+j44Gu44K144OW44Kw44Or44O844OX44Gr55Sf44GY44KL5Ymy5ZCI44Gn44GZ44CCCgojIyDmupblgpkKCuavjuWbniBgdGlkeXZlcnNlYCDjgaggYFdESWAg44GoIGBEZXNjVG9vbHNgIOOCkuS9v+OBhOOBvuOBmeOBi+OCieOAgVIgTm90ZWJvb2sg44Gu5pyA5Yid44Gr44Gv44CB5qyh44Gu44Kz44O844OJ44OB44Oj44Oz44Kv44KS5L2c5oiQ44GX44CB5a6f6KGM77yIUnVu77yJ44GX44G+44GZ44CC44GT44KM44KJ44Gu77yI5qmf6IO944KS5ouh5by144GZ44KL77yJ44OR44OD44Kx44O844K444GM44Kk44Oz44K544OI44O844Or44GV44KM44Gm44GE44Gq44GE5aC05ZCI44Gv44CB44Kk44Oz44K544OI44O844Or44GX44G+44GZ44CCVG9vbHNcPkluc3RhbGwgUGFja2FnZXMgLi4uCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoV0RJKQpsaWJyYXJ5KERlc2NUb29scykKYGBgCgojIyDjg4fjg7zjgr/jga7oqq3jgb/ovrzjgb8KCmBgYHtyIGV2YWwgPSBGQUxTRX0KZGZfZ2luaSA8LSBXREkoaW5kaWNhdG9yID0gYyhnaW5pID0gIlNJLlBPVi5HSU5JIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGAwLTEwYCA9ICJTSS5EU1QuRlJTVC4xMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgMC0yMGAgPSAiU0kuRFNULkZSU1QuMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYDIwLTQwYCA9ICJTSS5EU1QuMDJORC4yMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgNDAtNjBgID0gIlNJLkRTVC4wM1JELjIwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGA2MC04MGAgPSAiU0kuRFNULjA0VEguMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYDgwLTEwMGAgPSAiU0kuRFNULjA1VEguMjAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYDkwLTEwMGAgPSAiU0kuRFNULjEwVEguMTAiKSkKYGBgCgoKCiMjIyDkv53lrZjjgajoqq3jgb/ovrzjgb8KCuS9leW6puOCguODgOOCpuODs+ODreODvOODieOBl+OBquOBj+OBpuiJr+OBhOOCiOOBhuOBq+OAgeS/neWtmOOBl+OBn+OCguOBruOCkuiqreOBv+i+vOOBv+OBvuOBmeOAggoKYGBge3IgZXZhbCA9IEZBTFNFfQp3cml0ZV9jc3YoZGZfZ2luaSwgImRhdGEvZ2luaS5jc3YiKQpgYGAKCmBgYHtyfQpkZl9naW5pIDwtIHJlYWRfY3N2KCJkYXRhL2dpbmkuY3N2IikKYGBgCiMjIyDjg4fjg7zjgr/jga7norroqo0KCmBgYHtyfQpkZl9naW5pCmBgYAoKIyMjIGdpbmkg44GMIE5BIOOBp+OBr+OBquOBhOWApOOBruOCguOBruOBruOBv+ihqOekuuOBl+OBvuOBmQoKYGBge3J9CmRmX2dpbmkgfD4gZHJvcF9uYShnaW5pKQpgYGAKCiMjIyDlpInlvaLvvJrlkITpmo7ntJrjga7lgKTjgpLnuKbjgavkuKbjgbnjgIHnuKbplbflvaLlvI/jga7ooajjgavjgZfjgb7jgZnjgIJMb25nIGZvcm1hdAoKYHBpdm90X2xvbmdlcihjb2xzLCBuYW1lc190byA9ICIiLCB2YWx1ZXNfdG8gPSAiIilgIOOBq+OBpOOBhOOBpuOBr+OBhOOBmuOCjOiqrOaYjuOBl+OBvuOBmeOAguOBk+OBk+OBp+OBr+OAgeODrOODmeODq+OBq+WIhuOBkeOCieOCjOOBn+OCguOBruOCkiBsZXZlbHMg44Go44GE44GG5ZCN44Gu5YiX44Gr44Os44OZ44Or44KS44CBdmFsdWUg44Go44GE44GG5ZCN44Gu5YiX44Gr44CB44Gd44Gu5YCk44KS5Lim44G544Gf44KC44Gu44Go44GX44G+44GZ44CCCgpgYGB7cn0KZGZfZ2luaV9sb25nIDwtIGRmX2dpbmkgfD4gCiAgcGl2b3RfbG9uZ2VyKGAwLTEwYDpgOTAtMTAwYCwgbmFtZXNfdG8gPSAibGV2ZWxzIiwgdmFsdWVzX3RvID0gInZhbHVlIikKZGZfZ2luaV9sb25nCmBgYAoKIyMjIOaVtOOBiOOCieOCjOOBn++8iHRpZHnvvInjg4fjg7zjgr8KCi0gICDlkITliJfjga/jgbLjgajjgaTjga7lpInmlbAKCi0gICDlkITooYzjga/jgbLjgajjgaTjga7oprPmuKzlgKQKCumajue0mu+8iGxldmVsc++8ieOCkuWkieaVsOOBqOOBl+OBpuaJseOBhuOBn+OCgeOBq+OAgeOBk+OBruOCiOOBhuOBq+WkieW9ouOBl+OBvuOBl+OBn+OAggoKIVtdKGh0dHBzOi8vaWN1LWhzdXp1a2kuZ2l0aHViLmlvL2RhNHIvZGF0YS90aWR5LTEucG5nKQoKIyMjIOOBqeOBruOBj+OCieOBhCBHSU5JIOOBruODh+ODvOOCv+OBjOOBguOCi+OBi+eiuuOBi+OCgeOCiwoKYGBge3J9CmRmX2dpbmkgfD4gZHJvcF9uYShnaW5pKSB8PiAKICBnZ3Bsb3QoYWVzKHllYXIpKSArIGdlb21fYmFyKCkKYGBgCgrlrp/pmpvjgavjga/jgIHmrKHjga7jgojjgYbjgaroqIjnrpfjgpLjgZfjgabjgIHmo5LjgrDjg6njg5XjgafooajnpLrjgZfjgabjgYTjgb7jgZnjgIIKCi0gICBgZ3JvdXBfYnkoeWVhcilgIOW5tOOBlOOBqOOBq+OCsOODq+ODvOODl+OBqOOBmeOCiwoKLSAgIGBzdW1tYXJpemUobiA9IG4oKSlgIOOBneOCjOOBnuOCjOOBruOCsOODq+ODvOODl+OBlOOBqOOBruODh+ODvOOCv+OCkuaVsOOBiOOBvuOBmeOAguebtOWJjeOBq+OAgWBkcm9wX25hKGdpbmkpYCDjgajjgZfjgabjgYLjgovjga7jgafjgIFgZ2luaWAg44GMIE5BIOOBp+OBr+OBquOBhOODh+ODvOOCv+OBruaVsOOCkuaVsOOBiOOBpuOBhOOBvuOBmeOAggoKLSAgIOajkuOCsOODqeODle+8mmBnZ3Bsb3QoYWVzKHllYXIsIG4pKSArIGdlb21fY29sKClgCgrjgZnjgarjgo/jgaHjgIHmrKHjga7jgoLjga7jgajlkIzjgZjjgafjgZnjgIIKCmBgYHtyfQpkZl9naW5pIHw+IGdyb3VwX2J5KHllYXIpIHw+IGRyb3BfbmEoZ2luaSkgfD4gCiAgc3VtbWFyaXplKG4gPSBuKCkpIHw+CiAgZ2dwbG90KGFlcyh5ZWFyLCBuKSkgKyBnZW9tX2NvbCgpCmBgYAoKIyMjIOWun+mam+OBruODh+ODvOOCv+OBruWAi+aVsAoKYGBge3J9CmRmX2dpbmlfbG9uZyB8PiAKICBncm91cF9ieSh5ZWFyLCBsZXZlbHMpIHw+IGRyb3BfbmEodmFsdWUpIHw+CiAgc3VtbWFyaXplKG51bSA9IG4oKSkgfD4gZGlzdGluY3QoeWVhciwgbnVtKSB8PiBhcnJhbmdlKGRlc2MoeWVhcikpCmBgYAoKIyMjIDIwMjLlubTjgavjg4fjg7zjgr/jgYzlrZjlnKjjgZnjgos344Gk44Gu5Zu95ZCN44KS6KGo56S6CgpgYGB7cn0KZGZfZ2luaV9sb25nIHw+IGZpbHRlcih5ZWFyID09IDIwMjIpIHw+IGRyb3BfbmEodmFsdWUpIHw+CiAgZGlzdGluY3QoY291bnRyeSwgZ2luaSkgfD4gYXJyYW5nZShnaW5pKQpgYGAKCiMjIyDvvJfjgqvlm73jga7jgYTjgY/jgaTjgYvjgavjgaTjgYTjgaboqr/jgbnjgosKCmB4ID0gbGV2ZWxzYCDjgajjgZfjgIFgeSA9IHZhbHVlYCDjgajjgZnjgovjgajjgZPjgo3jgafjgIFMb25nIOOBq+OBl+OBn+WKueaenOOBjOWHuuOBpuOBhOOBvuOBmeOAggoKYGBge3J9CkNPVU5UUllfR0lOSSA8LSAiQmh1dGFuIgpZRUFSX0dJTkkgPC0gMjAyMgpkZl9naW5pX2xvbmcgfD4gZmlsdGVyKGxldmVscyAhPSAiZ2luaSIpIHw+CiAgZmlsdGVyKGNvdW50cnkgPT0gQ09VTlRSWV9HSU5JLCB5ZWFyID09IFlFQVJfR0lOSSkgfD4KICBnZ3Bsb3QoYWVzKGxldmVscywgdmFsdWUpKSArIGdlb21fY29sKCkKYGBgCgpgYGB7cn0KQ09VTlRSWV9HSU5JIDwtICJCYW5nbGFkZXNoIgpZRUFSX0dJTkkgPC0gMjAyMgpkZl9naW5pX2xvbmcgfD4gZmlsdGVyKGxldmVscyAhPSAiZ2luaSIpIHw+CiAgZmlsdGVyKGNvdW50cnkgPT0gQ09VTlRSWV9HSU5JLCB5ZWFyID09IFlFQVJfR0lOSSkgfD4KICBnZ3Bsb3QoYWVzKGxldmVscywgdmFsdWUpKSArIGdlb21fY29sKCkKYGBgCgpgYGB7cn0KQ09VTlRSWV9HSU5JIDwtICJDb3N0YSBSaWNhIgpZRUFSX0dJTkkgPC0gMjAyMgpkZl9naW5pX2xvbmcgfD4gZmlsdGVyKGxldmVscyAhPSAiZ2luaSIpIHw+CiAgZmlsdGVyKGNvdW50cnkgPT0gQ09VTlRSWV9HSU5JLCB5ZWFyID09IFlFQVJfR0lOSSkgfD4KICBnZ3Bsb3QoYWVzKGxldmVscywgdmFsdWUpKSArIGdlb21fY29sKCkKYGBgCgoqKue3tOe/kjEu44CASW5kb25lc2lhLCBFbCBTYWx2YWRvciwgUGFyYWd1YXksIEVjdWFkb3Ig44Gu44GE44Ga44KM44GL44Gr44Gk44GE44Gm44Kw44Op44OV44KS5o+P44GE44Gm44G/44G+44GX44KH44GG44CCKioKCmBgYHtyfQoKYGBgCgojIyMg5Lim44G544Gm5o+P44GE44Gm44G/44G+44GX44KH44GGCgrjgrjjg4vmjIfmlbDjga/lsI/jgZXjgYTjgbvjgYbjgYvjgonjgIFCaHV0YW4sIEJhbmdsYWRlc2gsIEluZG9uZXNpYSwgRWwgU2FsdmFkb3IsIFBhcmFndWF5LCBFcXVhZG9yLCBDb3N0YSBSaWNhIOOBp+OBl+OBn+OAggoKYGBge3J9CmRmX2dpbmlfbG9uZyB8PiBmaWx0ZXIoeWVhciA9PSAyMDIyKSB8PiAKICBmaWx0ZXIobGV2ZWxzICE9ICJnaW5pIikgfD4gIGRyb3BfbmEodmFsdWUpIHw+CiAgZ2dwbG90KGFlcyhsZXZlbHMsIHZhbHVlKSkgKyBnZW9tX2NvbCgpICsgZmFjZXRfd3JhcCh+Y291bnRyeSkKYGBgCgojIyMg6ICD44GI44Gm44G/44KI44GGCgoxLiAg5pyA5b6M5LiL44GM44Gj44Gm44GE44KL44Gu44Gv5q2j5bi477yfCgoyLiAg44Gp44Gu44KI44GG44Gr6KGo56S644GZ44KL44Gu44GM44KI44GE44Gu44Gg44KN44GG44GL44CCCgozLiAg44GT44KM44KJ44Gu5Zuz44KS44G/44Gm44CB44K444OL5oyH5pWw44Gu5aSn44GN44GV44Gr44Gk44GE44Gm44KP44GL44KK44G+44GZ44GL44CCCgo0LiAg44GT44Gu44OH44O844K/44GL44KJ44CB44K444OL5oyH5pWw44KS6KiI566X44GZ44KL44Gr44Gv44CB44Gp44GG44GX44Gf44KJ6Imv44GE44Gu44Gg44KN44GG44GL44CCCgojIyDjgrjjg4vmjIfmlbDjga7oqIjnrpcKCkRlcml2YXRpb24gb2YgdGhlIExvcmVueiBjdXJ2ZSBhbmQgR2luaSBjb2VmZmljaWVudCBmb3IgZ2xvYmFsIGluY29tZSBpbiAyMDExIFtb44Oq44Oz44KvXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HaW5pX2NvZWZmaWNpZW50KV0KCiMjIyDjgrjjg4vmjIfmlbDjgpLoqIjnrpfjgZnjgovjgZ/jgoHjgavlpInmj5sKCmBgYHtyfQpkZl9naW5pX2NhbGMgPC0gZGZfZ2luaSB8PiAKICBtdXRhdGUoYDBgID0gMCwgYDEwYCA9IGAwLTEwYCwgYDIwYCA9IGAwLTIwYCwKICAgICAgICAgYDMwYCA9IGAwLTIwYCtgMjAtNDBgLzIsIGA0MGAgPSBgMC0yMGAgKyBgMjAtNDBgLCAKICAgICAgICAgYDUwYCA9IGAwLTIwYCArIGAyMC00MGAgKyBgNDAtNjBgLzIsIAogICAgICAgICBgNjBgID0gYDAtMjBgICsgYDIwLTQwYCArIGA0MC02MGAsIAogICAgICAgICBgNzBgID0gYDAtMjBgICsgYDIwLTQwYCArIGA0MC02MGAgKyBgNjAtODBgLzIsICAKICAgICAgICAgYDgwYCA9IGAwLTIwYCArIGAyMC00MGAgKyBgNDAtNjBgICsgYDYwLTgwYCwgCiAgICAgICAgIGA5MGAgPSBgMC0yMGAgKyBgMjAtNDBgICsgYDQwLTYwYCArIGA2MC04MGAgKyBgODAtMTAwYC1gOTAtMTAwYCwKICAgICAgICAgYDEwMGAgPSAxMDApIHw+CiAgc2VsZWN0KC1jKGAwLTEwYDpgOTAtMTAwYCkpICMg5LiN5b+F6KaB44Gq6YOo5YiG44KS5raI5Y67CmRmX2dpbmlfY2FsYyAlPiUgZHJvcF9uYSgpIApgYGAKCiMjIyDnuKbplbfjga4gTG9uZyBUYWJsZSDjgavlpInmj5sKCmBgYHtyfQpkZl9naW5pX2NhbGNfbG9uZyA8LSBkZl9naW5pX2NhbGMgfD4gIHBpdm90X2xvbmdlcihgMGA6YDEwMGAsIG5hbWVzX3RvID0gImNsYXNzZXMiLCB2YWx1ZXNfdG8gPSAiY3VtdWxhdGl2ZV9zaGFyZSIpIHw+IG11dGF0ZShjbGFzc2VzID0gYXMubnVtZXJpYyhjbGFzc2VzKSkKZGZfZ2luaV9jYWxjX2xvbmcgJT4lIGRyb3BfbmEoKSAKYGBgCgojIyMg56K66KqNCgpgYGB7cn0KZGZfZ2luaV9jYWxjX2xvbmcgfD4gZmlsdGVyKGNvdW50cnkgPT0gIkJhbmdsYWRlc2giKSB8PiAKICBmaWx0ZXIoeWVhciA9PSAyMDIyKSB8PiBnZ3Bsb3QoKSArIAogIGdlb21fbGluZShhZXMoY2xhc3NlcywgY3VtdWxhdGl2ZV9zaGFyZSkpICsgCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gMCwgeSA9IDAsIHhlbmQgPSAxMDAsIHllbmQgPSAxMDApLCBjb2xvciA9ICdyZWQnKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMDAsYnk9MjApKSArIAogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxMDAsYnk9MjApKSAjKwogICNhbm5vdGF0ZSgidGV4dCIsIHggPSAxMCwgeSA9IDgwLCBsYWJlbCA9IGdpbmkpCmBgYAoKIyMjIO+8lOOCq+WbveOCkuOCuOODi+aMh+aVsOmghuOBq+OBquOCieOBueOBn+ajkuOCsOODqeODlQoKYGBge3J9CkNPVU5UUklFU19HSU5JIDwtIGMoIkJodXRhbiIsICJCYW5nbGFkZXNoIiwiSW5kb25lc2lhIiwiQ29zdGEgUmljYSIpCllFQVJfR0lOSSA8LSAyMDIyCmRmX2dpbmlfbG9uZyB8PiAKICBmaWx0ZXIoY291bnRyeSAlaW4lIENPVU5UUklFU19HSU5JLCB5ZWFyID09IFlFQVJfR0lOSSkgfD4KICBnZ3Bsb3QoYWVzKGxldmVscywgdmFsdWUsIGZpbGwgPSBmYWN0b3IoY291bnRyeSwgbGV2ZWxzID0gQ09VTlRSSUVTX0dJTkkpKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsgbGFicyhmaWxsID0gIiIpCmBgYAoKKirnt7Tnv5IyLiDvvJfjgqvlm73jgZnjgbnjgabjgavjgaTjgYTjgabjgIE4MC0xMDAg44Go44CBOTAtMTAwIOOBrumDqOWIhuOBoOOBkeOAgeihqOekuuOBp+OBjeOBquOBhOOBp+OBl+OCh+OBhuOBi+OAgu+8iOmbo++8muetlOOBiOOBr+S4gOeVquS4i++8iSoqCgpgYGB7cn0KCmBgYAoKKioyMDAw5bm044Gu44K444OL5oyH5pWw44GoOTDvvIXku6XkuIrjga7libLlkIjjga7nm7jplqIqKgoKYGBge3J9CmRmX2dpbmkgfD4gCiAgZmlsdGVyKHllYXIgPT0gMjAwMCkgfD4gZHJvcF9uYShnaW5pKSB8PgogIGdncGxvdChhZXMoZ2luaSwgYDkwLTEwMGApKSArIGdlb21fcG9pbnQoKSArIAogIGdlb21fc21vb3RoKGZvcm11bGEgPSAneSB+IHgnLCBtZXRob2QgPSAibG0iKQpgYGAKCioq57e057+SMy4gMjAwMOW5tO+8iOOBvuOBn+OBr+S7luOBruW5tOOBru+8ieOCuOODi+aMh+aVsOOBqDgw77yF5Lul5LiK44Gu5Ymy5ZCI44Gu55u46ZaiKioKCmBgYHtyfQoKYGBgCgojIyDlvqnnv5IKCi0gICDjg5Hjg4PjgrHjg7zjgrjvvIhQYWNrYWdl77yJ44Gu5Yip55So77yaCgogICAgLSAgIOOCpOODs+OCueODiOODvOODq++8iGluc3RhbGxhdGlvbu+8ie+8mlRvb2xzIFw+IEluc3RhbGwgUGFja2FnZXMKCiAgICAtICAg44Ot44O844OJ77yIbG9hZO+8iWBsaWJyYXJ5KHRpZHl2ZXJzZSk7IGxpYnJhcnkoV0RJKTsgbGlicmFyeShEZXNjVG9vbHMpYAoKLSAgIOODh+ODvOOCv+OBruWPluW+l++8mmBgIFdESShpbmRpY2F0b3IgPSBjKGdpbmkgPSAiU0kuUE9WLkdJTkkiLGAwLTEwYCA9ICJTSS5EU1QuRlJTVC4xMCIsLi4uLGA5MC0xMDBgID0gIlNJLkRTVC4xMFRILjEwIikpIGBgCgotICAg54m55a6a44Gu6KGM44Gu5Y+W5b6X77yaYGZpbHRlcigpLCBkcm9wX25hKCksIGRpc3RpbmN0KClgCgotICAg5qOS44Kw44Op44OVCgogICAgLSAgIGBnZ3Bsb3QoYWVzKHllYXIpKSArIGdlb21fYmFyKClgCgogICAgLSAgIGBnZ3Bsb3QoYWVzKGxldmVscywgdmFsdWUpKSArIGdlb21fY29sKClgCgogICAgLSAgIGBnZ3Bsb3QoYWVzKHggPSBsZXZlbHMsIHkgPSB2YWx1ZSwgZmlsbCA9IGNvdW50cnkpKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIilgCgogICAgLSAgIGBnZ3Bsb3QoYWVzKHggPSBnaW5pLCBmaWxsID0gcmVnaW9uKSkgKyBnZW9tX2hpc3RvZ3JhbSgpYAoKLSAgIOaVo+W4g+Wbs++8iCvlm57luLDnm7Tnt5rvvIkKCiAgICAtICAgYGdncGxvdChhZXMoZ2luaSwgOTAtMTAwKSkgKyBnZW9tX3BvaW50KClgCgogICAgLSAgIGBnZ3Bsb3QoYWVzKGdpbmksIDgwLTEwMCkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9zbW9vdGgoZm9ybXVsYSA9ICd5IH4geCcsIG1ldGhvZCA9ICJsbSIpYAoKIyMg6Kqy6aGMCgoqKue3tOe/kjEg44GL44KJ57e057+SMy4qKgoK5o+Q5Ye644Gv44GX44Gq44GP44Gm6Imv44GE44Gn44GZ44GM44CB44Gc44Gy5a6f6Zqb44Gr5omL44KS5YuV44GL44GX44Gm5a6f6KGM44GX44Gm44GP44Gg44GV44GE44CCCgojIyDlj4LogIPmlofnjK4KCjEuICDjgIzjgb/jgpPjgarjga7jg4fjg7zjgr/jgrXjgqTjgqjjg7PjgrkgLSBEYXRhIFNjaWVuY2UgZm9yIEFsbOOAjVtb44Gv44GY44KB44Gm44Gu44OH44O844K/44K144Kk44Ko44Oz44K5XShodHRwczovL2ljdS1oc3V6dWtpLmdpdGh1Yi5pby9kczRhai9maXJzdC1leGFtcGxlLmh0bWwjZmlyc3QtZXhhbXBsZSldCgogICAgLSAgIOWwjuWFpeOBqOOBl+OBpuOAgUdEUO+8iOWbveWGhee3j+eUn+eUo++8ieOBruODh+ODvOOCv+OCkuS9v+OBo+OBpuiqrOaYjuOBl+OBpuOBhOOBvuOBmeOAggoKMi4gIFBvc2l0IFJlY2lwZXPvvIjml6cgUG9zaXQgUHJpbWVyc++8iTogVGhlIEJhc2ljcyDlr77oqbHlnovjga7mvJTnv5LjgrXjgqTjg4jjga7mnIDliJ0gW1tMaW5rXShodHRwczovL3Bvc2l0LmNsb3VkL2xlYXJuL3JlY2lwZXMpXQoKMy4gIFBvc2l0IENoZWF0IFNoZWV0LiDml6nopovooajjgafjgZnjgILljbDliLfjgZfjgabkvb/jgYbjgZ/jgoHjgavjgIFQREYg44KC5o+Q5L6b44GX44Gm44GE44G+44GZ44CCW1tTaXRlIExpbmtdKGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vY2hlYXRzaGVldHMvKV0KCjQuICBEYXRhQ2FtcCBDaGVhdCBTaGVldDogVGlkeXZlcnNlIGZvciBCaWdpbm5lcnMuIOODh+ODvOOCv+OCteOCpOOCqOODs+OCueOBruaVmeiCsuOCkuOBl+OBpuOBhOOCi+S8muekvuOBruaXqeimi+ihqOOBruS4gOOBpOOBp+OBmeOAguWfuuacrOOBjOewoeWNmOOBq+OBvuOBqOOBvuOBo+OBpuOBhOOBvuOBmeOAgltbTGlua10oaHR0cHM6Ly9pbWFnZXMuZGF0YWNhbXAuY29tL2ltYWdlL3VwbG9hZC92MTY3NjMwMjY5Ny9NYXJrZXRpbmcvQmxvZy9UaWR5dmVyc2VfQ2hlYXRfU2hlZXQucGRmKV0KCiMjIOWPguiAg++8kQoK6ZqO57Sa44KSIDEwJSDliLvjgb/jgavntbHkuIDjgZfjgIFMb25nIOW9ouW8j+OBq+WkieaPm+OAggoKYGBge3J9CmRmX2dpbmlfcmV2IDwtIGRmX2dpbmkgfD4gCiAgbXV0YXRlKGAwLTEwYCA9IGAwLTEwYCwgYDEwLTIwYCA9IGAwLTIwYC1gMC0xMGAsYDIwLTMwYCA9IGAyMC00MGAvMiwgYDMwLTQwYCA9IGAyMC00MGAvMiwgYDQwLTUwYCA9IGA0MC02MGAvMiwgYDUwLTYwYCA9IGA0MC02MGAvMiwgYDYwLTcwYCA9IGA2MC04MGAvMiwgYDcwLTgwYD1gNjAtODBgLzIsIGA4MC05MGAgPSBgODAtMTAwYC1gOTAtMTAwYCwgYDkwLTEwMGAgPSBgOTAtMTAwYCkgfD4gCiAgc2VsZWN0KC1jKGAwLTIwYCwgYDIwLTQwYCxgNDAtNjBgLGA2MC04MGAsIGA4MC0xMDBgKSkgfD4gCiAgc2VsZWN0KDE6NiwgODoxNSwgNykgCmRmX2dpbmlfcmV2ICU+JSBkcm9wX25hKCkKYGBgCgpgYGB7cn0KZGZfZ2luaV9yZXZfbG9uZyA8LSBkZl9naW5pX3JldiB8PiBwaXZvdF9sb25nZXIoNjoxNSwgbmFtZXNfdG8gPSAibGV2ZWxzIiwgdmFsdWVzX3RvID0gInZhbHVlIikKZGZfZ2luaV9yZXZfbG9uZwpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9OSwgZmlnLndpZHRoPTh9CmRmX2dpbmlfcmV2X2xvbmcgfD4gZmlsdGVyKHllYXIgPT0gMjAyMikgfD4gZHJvcF9uYShnaW5pKSB8PgogIGdncGxvdChhZXMobGV2ZWxzLCB2YWx1ZSkpICsgZ2VvbV9jb2woKSArIAogIGZhY2V0X3dyYXAofmNvdW50cnksIG5jb2wgPSAyKQpgYGAKCiMjIOWPguiAg++8kgoK5puy57ea44Gu5LiL44Gu6Z2i56mN44KS6KiI566X44GZ44KL44CAQVVDIOOCkuWIqeeUqOOBl+OBpuOAgeOCuOODi+S/guaVsOOCkuioiOeul+OAggoKQXJlYSBVbmRlciB0aGUgQ3VydmU6IFtb44Oq44Oz44KvXShodHRwczovL3NlYXJjaC5yLXByb2plY3Qub3JnL0NSQU4vcmVmbWFucy9EZXNjVG9vbHMvaHRtbC9BVUMuaHRtbCldCgo8aHR0cHM6Ly9yZHJyLmlvL2NyYW4vRGVzY1Rvb2xzL2YvPgoKYGBge3J9CmRmX2dpbmlfY2FsY19sb25nIHw+IGdyb3VwX2J5KGNvdW50cnksIHllYXIpIHw+IAogIGRyb3BfbmEoZ2luaSkgfD4KICByZWZyYW1lKGdpbmksIGdpbmlfc3BsaW5lID0gcm91bmQoMTAwLUFVQyhjbGFzc2VzLCBjdW11bGF0aXZlX3NoYXJlLCBtZXRob2QgPSAic3BsaW5lIikvNTAsIGRpZ2l0cyA9IDEpLCBnaW5pX3RyYXBlem9pZCA9IHJvdW5kKDEwMC1BVUMoY2xhc3NlcywgY3VtdWxhdGl2ZV9zaGFyZSkvNTAsIGRpZ2l0cyA9IDEpKSB8PiAKICBkaXN0aW5jdChjb3VudHJ5LCB5ZWFyLCBnaW5pLCBnaW5pX3NwbGluZSwgZ2luaV90cmFwZXpvaWQpCmBgYAoKIyMjIOe3tOe/kjLjga7nrZTjgYgKCmBgYHtyfQpTRVZFTl9DT1VOVFJJRVMgPC0gYygiQmh1dGFuIiwgIkJhbmdsYWRlc2giLCJJbmRvbmVzaWEiLCJFbCBTYWx2YWRvciIsICJQYXJhZ3VheSIsICJFcXVhZG9yIiwgIkNvc3RhIFJpY2EiKQpZRUFSX0dJTkkgPC0gMjAyMgpkZl9naW5pX2xvbmcgfD4gCiAgZmlsdGVyKGNvdW50cnkgJWluJSBTRVZFTl9DT1VOVFJJRVMsIHllYXIgPT0gWUVBUl9HSU5JKSB8PgogIGZpbHRlcihsZXZlbHMgJWluJSBjKCc4MC0xMDAnLCc5MC0xMDAnKSkgfD4KICBnZ3Bsb3QoYWVzKGxldmVscywgdmFsdWUsIGZpbGwgPSBmYWN0b3IoY291bnRyeSwgbGV2ZWxzID0gU0VWRU5fQ09VTlRSSUVTKSkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiLCBjb2wgPSAiYmxhY2siLCBsaW5ld2lkdGggPSAwLjIpICsgbGFicyhmaWxsID0gIiIpCmBgYAo=