1 DAY 1:2月20日

1.1 RStudio で Project の作成

1.1.1 確認

  1. R と R Studio のインストール
  2. RStudio: New Project 作成
  • R Studio の起動
  • New Project: eco232, eco232.Rproj
  1. Save して、終了
  2. プロジェクトを起動確認

1.2 基本コマンド - in Console

  • head(cars)
  • str(cars)
  • summary(cars)
  • df_cars <- cars
    • <-_%>% と ` back tick の確認
  • View(cars) または、右上の Environment から、df_cars をクリック
  • ?cars または Help 検索窓で cars, head など

おすすめ:Sys.setenv(LANG = "en")

1.3 Package の確認とインストール

R packages are extensions to the R statistical programming language containing code, data, and documentation in a standardised collection format that can be installed by users of R using Tool > Install Packages in the top menu bar of R Studio.

Rパッケージは、Rの拡張機能で、コード、データ、ドキュメントを標準化されたコレクション形式で含んでおり、標準的なものは、R Studio の Top Bar の Tool > Install Packages からインストールできます。

  • Minimum: tidyverse, rmarkdown, WDI

あとから使うので、ロードしておきます。最初に次のようなコードを実行します。右の三角を押します。

library(tidyverse)
library(WDI)

1.4 R Markdown 入門

1.4.1 R Notebook

R Markdownはデータサイエンスのためのオーサリングフレームワーク。

コード(プログラム)とその実行結果、を記録・表示し、高品質のレポートの作成を可能にします。

R Notebook は、独立してインタラクティブに実行できるチャンクを持つR Markdownドキュメントの一つの形式で、入力のすぐ下に出力が表示することができます。

  1. File > New File > R Notebook
  2. Save with a file name, say, test-notebook
  3. Preview by [Preview] button
  4. Run Code Chunk plot(cars) and then Preview again.

1.5 World Development Indicator (WDI)

WDI(country = "all", indicator = c(gdp = "NY.GDP.MKTP.CD"),
    extra=TRUE) %>% drop_na(gdp) %>%
  filter(year==max(year), income !="Aggregates") %>% 
  drop_na(region) %>% arrange(desc(gdp))
chosen_countries <- c("United States","China", "Japan", "Germany", "United Kingdom","India")
WDI(country = c("CN","GB","JP","IN","US","DE"), indicator = c(gdp = "NY.GDP.MKTP.CD"), extra=TRUE) %>% drop_na(gdp) %>% 
  ggplot(aes(year, gdp, col = country)) + geom_line() +
  labs(title = "WDI NY.GDP.MKTP.CD: gdp")

WDI(country = c("CN","IN","JP","US"), 
    indicator = c(gdp_growth_rate = "NY.GDP.MKTP.KD.ZG"), extra=TRUE) %>%
  drop_na(gdp_growth_rate) %>% 
  ggplot(aes(year, gdp_growth_rate, col = country)) + geom_line() +
  labs(title = paste("WDI NY.GDP.MKTP.KD.ZG: gdp growth rate"))

1.5.1 指標 Indicators (WDI)

  • NY.GDP.MKTP.CD: GDP (current US$)
  • NY.GDP.MKTP.KD.ZG: GDP growth (annual %)

1.5.2 指標 WDI を探してみよう

The World Development Indicators is a compilation of relevant, high-quality, and internationally comparable statistics about global development and the fight against poverty. The database contains 1,400 time series indicators for 217 economies and more than 40 country groups, with data for many indicators going back more than 50 years.

WDIは、世界の開発状況と、貧困との戦いに関する、適切で上質、かつ、国際的に比較可能な時系列の統計データを編纂したものです。このデータベースは、217の経済と40以上の国グループについて1,400の時系列指標を含み、指標のデータの多くは50年以上前に遡ることができます。

  • 世界銀行(World Bank):
  • World Bank Open Data:
    • Country / Indicator > Featured & All > Details
  • World Development Indicators (WDI) :
    • Themes: Poverty and Inequality, People, Environment, Economy, States and Markets, Global Links
    • Open Data & DataBank: Explore data, Query database

1.5.3 指標 WDIの例

  • NY.GDP.MKTP.CD: GDP (current US$)
  • NY.GDP.DEFL.KD.ZG: Inflation, GDP deflator (annual %)
  • SL.UEM.TOTL.NE.ZS: Unemployment, total (% of total labor force) (national estimate)
  • CPTOTNSXN: CPI Price, nominal
  • SL.TLF.CACT.MA.NE.ZS: Labor force participation rate, male (% of male population ages 15+) (national estimate)
  • SL.TLF.CACT.FE.NE.ZS: Labor force participation rate, female (% of male population ages 15+) (national estimate)

1.5.4 練習 1. - 調べてみたい WDI

いくつか、リストしてみましょう。

1.6 WDI パッケージ

WDI パッケージで、データをダウンロードしたり、探したり、詳細情報を得たりできます。

1.6.1 指標 WDI 検索

1.6.1.1 検索例 1(WDI名)

WDIsearch(string = "gdp", field = "name", short = TRUE, cache = NULL)

1.6.1.2 検索例 2(WDI)

WDIsearch(string = "NY.GDP.MKTP.CD", field = "indicator", short = TRUE, cache = NULL)

1.6.1.3 練習 2. - 検索(short)

名前で検索(“” の間に、(なるべく簡単な)検索文字列を入れてください。)

WDIsearch(string = "", field = "name", short = TRUE, cache = NULL)

Indicator で検索(“” の間に、調べたい indicator を入れてください。)

WDIsearch(string = "", field = "indicator", short = TRUE, cache = NULL)

1.6.1.4 詳しい情報を得るには

short = FALSE とします。時間がかかるので、検索は、Indicator と、名前などの情報をもったファイルを手元に持っておくことにします。

wdi_cache <- WDIcache()

右上の窓枠(pane)から、wdi_cache を探して、中身を見てみましょう。series と、country の二つのデータ・フレームからなっているリストです。三角印や、右から二番目の巻物のようなアイコンをクリックすると中身が見えます。

1.6.1.5 検索例 3(WDI名)

WDIsearch(string = "CPI Price", field = "name", short = FALSE, cache = wdi_cache)
  • CPTOTNSXN: CPI Price, nominal
    • The consumer price index reflects the change in prices for the average consumer of a constant basket of consumer goods. Data is not seasonally adjusted.

1.6.1.6 検索例 4(WDI)

WDIsearch(string = "NY.GDP.MKTP.KD.ZG", field = "indicator", short = FALSE, cache = wdi_cache)

1.6.1.7 練習 2 - 検索(long w/ cache)

string と、field を、ふたつとも入れてください。

WDIsearch(string = "", field = "", short = FALSE, cache = wdi_cache)

2 DAY 2:2月22日

2.1 (続)WDI パッケージ

2.1.1 指標 WDI データのダウンロード

Indicator が決まったら、ダウンロードします。

?WDI

2.1.1.1 ダウンロード例 1-1

df_gdp1 <- WDI(country = "all", indicator = "NY.GDP.MKTP.CD")
df_gdp1

2.1.1.2 ダウンロード例 1-2

df_gdp2 <- WDI(country = "all", indicator = c(gdp = "NY.GDP.MKTP.CD"))
df_gdp2

2.1.1.3 ダウンロード例 1-3

df_gdp3 <- WDI(country = "all", indicator = c(gdp = "NY.GDP.MKTP.CD"), extra=TRUE, cache=wdi_cache)
df_gdp3

2.1.1.4 ダウンロード例 1-4

df_gdp4 <- WDI(country = c("CN","GB","JP","IN","US","DE"), indicator = c(gdp = "NY.GDP.MKTP.CD"), extra=TRUE, cache=wdi_cache)
df_gdp4

2.1.1.5 ダウンロード例 2-1

  • NY.GDP.DEFL.KD.ZG: Inflation, GDP deflator (annual %)
  • CPTOTNSXN: CPI Price, nominal
df_gdp21 <- WDI(country = "all", 
                indicator = c(gdp_deflator = "NY.GDP.DEFL.KD.ZG", 
                              cpi_price = "CPTOTNSXN"), 
                extra=TRUE, cache=wdi_cache)
df_gdp21
str(df_gdp21)
'data.frame':   23972 obs. of  14 variables:
 $ country     : chr  "Advanced Economies" "Advanced Economies" "Advanced Economies" "Advanced Economies" ...
 $ iso2c       : chr  "AME" "AME" "AME" "AME" ...
 $ iso3c       : chr  "" "" "" "" ...
 $ year        : int  1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 ...
 $ status      : chr  "" "" "" "" ...
 $ lastupdated : chr  "2020-07-27" "2020-07-27" "2020-07-27" "2020-07-27" ...
 $ gdp_deflator: num  NA NA NA NA NA NA NA NA NA NA ...
  ..- attr(*, "label")= chr "Inflation, GDP deflator (annual %)"
 $ cpi_price   : num  58.7 60.5 63 66 69.1 ...
  ..- attr(*, "label")= chr "CPI Price,not seas.adj,,,"
 $ region      : chr  NA NA NA NA ...
 $ capital     : chr  NA NA NA NA ...
 $ longitude   : chr  NA NA NA NA ...
 $ latitude    : chr  NA NA NA NA ...
 $ income      : chr  NA NA NA NA ...
 $ lending     : chr  NA NA NA NA ...
summary(df_gdp21)
   country             iso2c              iso3c          
 Length:23972       Length:23972       Length:23972      
 Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character  
                                                         
                                                         
                                                         
                                                         
      year         status          lastupdated       
 Min.   :1960   Length:23972       Length:23972      
 1st Qu.:1982   Class :character   Class :character  
 Median :1996   Mode  :character   Mode  :character  
 Mean   :1995                                        
 3rd Qu.:2009                                        
 Max.   :2021                                        
                                                     
  gdp_deflator         cpi_price         region         
 Min.   :  -98.704   Min.   :  0.00   Length:23972      
 1st Qu.:    2.317   1st Qu.: 55.95   Class :character  
 Median :    5.273   Median : 83.28   Mode  :character  
 Mean   :   25.308   Mean   : 84.18                     
 3rd Qu.:   10.411   3rd Qu.:108.75                     
 Max.   :26765.858   Max.   :551.25                     
 NA's   :11616       NA's   :18410                      
   capital           longitude           latitude        
 Length:23972       Length:23972       Length:23972      
 Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character  
                                                         
                                                         
                                                         
                                                         
    income            lending         
 Length:23972       Length:23972      
 Class :character   Class :character  
 Mode  :character   Mode  :character  
                                      
                                      
                                      
                                      

右上の窓枠の、Environment も見てみましょう。

2.2 可視化 Visualization

グラフ(Chart)を描いて視覚化しよう

2.2.1 グラフ 1

df_gdp4 %>% ggplot(aes(year, gdp, col=country)) + geom_line()

2.2.2 グラフ 2

df_gdp4 %>% drop_na(gdp) %>% 
  ggplot(aes(year, gdp, col=country)) + geom_line() +
  labs(title = paste("WDI - NY.GDP.MKTP.CD: ", "gdp"))

2.2.3 テンプレート Templates

2.2.3.1 一つの国についての、一つの指標(WDI)と、その略称から、折線グラフを作成

Line Plot with one indicator with abbreviation and one country

chosen_indicator <- "SL.UEM.TOTL.NE.ZS"
short_name <- "unemployment"
chosen_country <- "United States"
WDI(country = "all", indicator = c(short_name = chosen_indicator), extra=TRUE, cache=wdi_cache) %>%
  filter(country == chosen_country) %>% 
  ggplot(aes(year, short_name)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator, ": ", short_name, " - ", chosen_country),
       y = short_name)

2.2.3.2 一つの国についての、一つの指標(WDI)から、折線グラフを作成

Line Plot with one indicator and one country

chosen_indicator <- "SL.UEM.TOTL.NE.ZS"
chosen_country <- "United States"
WDI(country = "all", indicator = c(chosen_indicator = chosen_indicator), 
    extra=TRUE, cache=wdi_cache) %>%
  filter(country == chosen_country) %>% 
  ggplot(aes(year, chosen_indicator)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator, " - ", chosen_country), 
       y = chosen_indicator)

2.2.3.3 いくつかの国についての、一つの指標(WDI)と、その略称から、折線グラフを作成

Line Plot with one indicator with abbreviation and several countries

chosen_indicator <- "SL.UEM.TOTL.NE.ZS"
short_name <- "unemployment"
chosen_countries <- c("United States","United Kingdom", "Japan")
WDI(country = "all", indicator = c(short_name = chosen_indicator), extra=TRUE, cache=wdi_cache) %>% drop_na(short_name) %>% 
  filter(country %in% chosen_countries) %>% 
  ggplot(aes(year, short_name, col = country)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator, ": ", short_name), y = short_name)

2.2.3.4 一つの国についての、二つの指標(WDI)と、その略称から、折線グラフを作成

Line Plot with two indicators with abbreviation and one country

chosen_indicator_1 <- "NY.GDP.DEFL.KD.ZG"
short_name_1 <- "gdp_deflator"
chosen_indicator_2 <- "CPTOTSAXNZGY"
short_name_2 <- "cpi_price"
chosen_country <- "United States"
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country == chosen_country) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, col = class)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2, " - ", chosen_country)) +
  scale_color_manual(labels = c(short_name_1, short_name_2), values = scales::hue_pal()(2))

chosen_indicator_1 <- "SL.TLF.CACT.MA.NE.ZS"
short_name_1 <- "male"
chosen_indicator_2 <- "SL.TLF.CACT.FE.NE.ZS"
short_name_2 <- "female"
chosen_country <- "United States"
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country == chosen_country) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, col = class)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2, " - ", chosen_country)) +
  scale_color_manual(labels = c(short_name_1, short_name_2), values = scales::hue_pal()(2))

2.2.3.5 いくつかの国についての、二つの指標(WDI)と、その略称から、折線グラフを作成

Line Plot with two indicators with abbreviation and several countries

chosen_indicator_1 <- "NY.GDP.DEFL.KD.ZG"
short_name_1 <- "gdp_deflator"
chosen_indicator_2 <- "CPTOTSAXNZGY"
short_name_2 <- "cpi_price"
chosen_countries <- c("United States", "France", "Japan")
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country %in% chosen_countries) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, linetype = class, col = country)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2)) +
  scale_linetype_manual(labels = c(short_name_1, short_name_2), values = c("solid", "dashed"))

chosen_indicator_1 <- "SL.TLF.CACT.MA.NE.ZS"
short_name_1 <- "male"
chosen_indicator_2 <- "SL.TLF.CACT.FE.NE.ZS"
short_name_2 <- "female"
chosen_countries <- c("United States", "France", "Japan")
WDI(country = "all", indicator = c(short_name_1 = chosen_indicator_1, short_name_2 = chosen_indicator_2), extra=TRUE, cache=wdi_cache) %>% 
  filter(country %in% chosen_countries) %>% 
  pivot_longer(c(short_name_1, short_name_2), names_to = "class", values_to = "value") %>% drop_na(value) %>%
  ggplot(aes(year, value, linetype = class, col = country)) + geom_line() +
  labs(title = paste("WDI ", chosen_indicator_1, ": ", short_name_1, "\n", chosen_indicator_2, ": ", short_name_2)) +
  scale_linetype_manual(labels = c(short_name_1, short_name_2), values = c("solid", "dashed"))

2.3 課題 Assignment

上のテンプレートをコピーして、下に貼り付け、指標 indicator と、略称 short_name と、いくつかの国名 chosen_countries を、入れ替えて、試してみてください。

2.4 探索的データ解析 Exploratory Data Analysis (EDA)

2.4.1 探索的データ解析とは? (Posit Primers)

  1. EDAは、データが何を語っているかを理解するための反復的なサイクルです。

  2. まず、データに関する問いを作成します。

  3. データの可視化、変換、モデリングを行い、答えを探します。

学習したことを活用して、問いを修正したり、新しい問いを考えたりします。そして、このサイクルを繰り返していきます。

EDAはデータ分析において重要な役割を果たします。また、データの品質を保証するために、データの質を確認するために使用することもできます。

R4DS からのイメージ

2.4.2 データの取得・読み込み - Importing Data

スタートは、本来は、データの作成・探索ですが、すでに、分析したいデータはすでにあるとして話を進めます。まずは、data フォルダ(directory)を作成しておくと良い。右下の窓枠の Files タブから、New Folder で作成してもよい。

dir.create("./data")

データの取得・読み込みを、四つの方法に分けて説明します。

  1. パッケージの利用
  • 例:WDI など。何度も、ダウンロードしなくて良いよいに、書き出しておき、2 を使うとよい。write(df_name, "./data/name.csv")
  1. コンピュータ上にある CSV などのテキストファイルを読み込む
  • 例:df_name <- read_csv("./data/file_name.csv")
  1. インターネット上のデータのアドレス(URL)を使って、CSV などのテキストファイルを読み込む。
  • 例:df_name <- read_csv(url_of_a_csv)
  1. コンピュータ上にある、Excel ファイルなどのデジタルファイルを読み込む。まず、library(readxl)
  • 例:df_name <- read_excel("./data/file_name.xlsx")
  1. サイトからダウンロードして、Project のデータフォルダに移す。または、データのアドレス(URL)がわかっていれば、直接ダウンロード。
  • 例:`download.file(url_of_a_data, destfile = “./data/data_name”)
  1. クリップボードにコピーして読み込む。
  • 例:df_name <- read_delim(clipboard())

2.4.3 WDIcache() の扱い

二つの、ファイルが一つになった、リストであるため、違って命令を使います。

wdi_cache <- WDIcache()
write_rds(wdi_cache, "./data/wdi_cache.RData")
wdi_cache <- read_rds("./data/wdi_cache.RData")

2.4.4 国際機関のデータ International Institutions’ Data

url_un_pop <- "https://data.un.org/_Docs/SYB/CSV/SYB65_1_202209_Population,%20Surface%20Area%20and%20Density.csv"
df_un_pop0 <- read_csv(url_un_pop)
New names:Rows: 7874 Columns: 7── Column specification ──────────────────────────────────────────────
Delimiter: ","
chr (7): T02, Population, density and surface area, ...3, ...4, .....
ℹ 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_un_pop0
url_un_pop <- "https://data.un.org/_Docs/SYB/CSV/SYB65_1_202209_Population,%20Surface%20Area%20and%20Density.csv"
df_un_pop <- read_csv(url_un_pop, skip=1)
New names:Rows: 7873 Columns: 7── Column specification ──────────────────────────────────────────────
Delimiter: ","
chr (4): ...2, Series, Footnotes, Source
dbl (2): Region/Country/Area, Year
num (1): Value
ℹ 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_un_pop
df_un_pop %>% distinct(`Region/Country/Area`, `...2`)
df_un_pop %>% filter(`Region/Country/Area` %in% c(2,19,142,150,9), Series == "Population mid-year estimates (millions)") %>%
  ggplot(aes(Year, Value, fill = `...2`)) + geom_area(col="black") +
  labs(title = "Population mid-year estimates (millions) of the World")

3 DAY 3:2月24日

3.1 OECD data

3.1.1 例:労働時間当たりGDP

Definition of GDP per hour worked

GDP per hour worked is a measure of labour productivity. It measures how efficiently labour input is combined with other factors of production and used in the production process. Labour input is defined as total hours worked of all persons engaged in production. Labour productivity only partially reflects the productivity of labour in terms of the personal capacities of workers or the intensity of their effort. The ratio between the output measure and the labour input depends to a large degree on the presence and/or use of other inputs (e.g. capital, intermediate inputs, technical, organisational and efficiency change, economies of scale). This indicator is measured in USD (constant prices 2010 and PPPs) and indices.

労働時間当たりGDPは、労働生産性の指標である。これは、労働投入量が他の生産要素と組み合わされ、生産プロセスでどれだけ効率的に利用されたかを測定するものである。労働投入量は、生産に従事するすべての人の総労働時間として定義される。労働生産性は、労働者の個人的能力や努力の強さといった労働の生産性を部分的にしか反映していない。アウトプット指標と労働投入量の比率は、他の投入物(資本、中間投入物、技術・組織・効率の変化、規模の経済など)の存在や利用に大きく左右される。この指標は、米ドル(2010年の恒常価格およびPPP)および指標で測定されています。

最初のステップ

  1. サイトから、CSV データをダウンロード。
  2. プロジェクト内のデータ格納フォルダに入れます。“./data/”
  3. 読み込みます。

上のサイトからデータ(Full indicator data)をダウンロードして、プロジェクトの data フォルダーに入れました。

df_oecd_productivity <- read_csv("./data/DP_LIVE_21022023111712065.csv")
Rows: 3894 Columns: 8── Column specification ──────────────────────────────────────────────
Delimiter: ","
chr (6): LOCATION, INDICATOR, SUBJECT, MEASURE, FREQUENCY, Flag Codes
dbl (2): TIME, Value
ℹ 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_oecd_productivity

データの確認

列名を確認し、列ごとに、データを確認

colnames(df_oecd_productivity)
[1] "LOCATION"   "INDICATOR"  "SUBJECT"    "MEASURE"    "FREQUENCY" 
[6] "TIME"       "Value"      "Flag Codes"

unique() のかっこの中に、df_oecd_productivity$LOCATION を入れたものと同じものを出力します。次々とつづけるときに便利なので、このパイプ %>% をわたしはよく使います。unique(df_oecd_productivity$LOCATION) も試してみてください。

df_oecd_productivity$LOCATION %>% unique()
 [1] "AUS"       "AUT"       "BEL"       "CAN"       "CZE"      
 [6] "DNK"       "FIN"       "FRA"       "DEU"       "GRC"      
[11] "HUN"       "ISL"       "IRL"       "ITA"       "JPN"      
[16] "KOR"       "LUX"       "MEX"       "NLD"       "NZL"      
[21] "NOR"       "POL"       "PRT"       "SVK"       "ESP"      
[26] "SWE"       "CHE"       "TUR"       "GBR"       "USA"      
[31] "CHL"       "EST"       "ISR"       "RUS"       "SVN"      
[36] "OECD"      "EU28"      "G-7"       "LVA"       "LTU"      
[41] "EA19"      "ZAF"       "CRI"       "BGR"       "HRV"      
[46] "ROU"       "EU27_2020" "COL"      
df_oecd_productivity$INDICATOR %>% unique()
[1] "GDPHRWKD"
df_oecd_productivity$SUBJECT %>% unique()
[1] "TOT"
df_oecd_productivity$MEASURE %>% unique()
[1] "USD"     "IDX2015"
df_oecd_productivity$FREQUENCY %>% unique()
[1] "A"
df_oecd_productivity$TIME %>% unique()
 [1] 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982
[14] 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995
[27] 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008
[40] 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021
df_oecd_productivity %>% 
  filter(MEASURE == "USD", TIME == 2021) %>% # filtering rows with conditions
  select(LOCATION, Value) %>% # selecting columns
  arrange(desc(Value)) # ordering the rows in the descenting order of the column Value

いくつかの地域を選んで、折線グラフを書いてみる。

3行目がないとどうなりますか。

df_oecd_productivity %>% 
  filter(LOCATION %in% c("JPN", "OECD", "G-7", "EU28")) %>%
  filter(MEASURE == "USD") %>% # same as above up to this line
  ggplot(aes(x = TIME, y = Value, col = LOCATION)) + geom_line() + 
  labs(title="GDP per hour worked", # adding the title and the subtitle
       subtitle="Total, 2015=100, 2021 or latest available")

3.1.2 練習:教育 Education

成人の教育レベルに関する、次のサイトからデータをとって、調べてみてください。

Adult education level: https://data.oecd.org/eduatt/adult-education-level.htm

ダウンロードしたファイルのファイル名が DP_LIVE_21022023120132654.csv と同じであることを確認してください。

df_oecd_education_level <- read_csv("./data/DP_LIVE_21022023120132654.csv")
df_oecd_education_level

上の労働時間当たりGDPの例に習って、データを調べてみてください。

colnames(df_oecd_education_level)
[1] "LOCATION"   "INDICATOR"  "SUBJECT"    "MEASURE"    "FREQUENCY" 
[6] "TIME"       "Value"      "Flag Codes"
df_oecd_education_level$SUBJECT %>% unique()
[1] "BUPPSRY"      "TRY"          "UPPSRY"       "TRY_MEN"     
[5] "TRY_WOMEN"    "UPPSRY_MEN"   "UPPSRY_WOMEN"

これらは、何を意味しているのでしょうか。サイトの Perspectives などをみてください。

他の列(変数)は、どうでしょうか。コードチャンクを挿入して、調べてみてください。

労働時間当たりGDPの例の真似をして、グラフを書いてみました。

df_oecd_education_level %>% 
  filter(LOCATION %in% c("JPN", "OECD", "G-7", "EU28")) %>%
  ggplot(aes(TIME, Value, linetype = SUBJECT, col = LOCATION)) + geom_line() + 
  labs(title="Adult education level")

なにか現れましたが、国も、SUBJECT も期待したものは現れていません。なにが問題なのでしょう。

気づいてたことを書き出してみましょう。

3.2 Excel Data の読み込み

readxl パッケージを使います。これは、tidyverse をインストールするときに、同時に、インストールされますから、インストールは必要ありませんが、tidyverse グループの主たるパッケージはないので、ロードはされていないので、使うときに、ロードする必要があります。

library(readxl) # need to load though readxl is a part of the tidyverse package and installed

実は、範囲を選択し、コピーをし、クリップボードから読む方法もありますが、二つの大きな理由から推奨しません。丁寧に、方法を記述しないと、再現性に問題があること、列のデータ・タイプなどが、適切に、読み込めない場合が多く、読み込んでからの作業が複雑になる。とっても、小さな、自分で作成したデータの場合には、有効かもしれません。

df_excel_clipboard <- read_delim(clipboard())

3.2.1 例: 世界の出生率(Fertility) UN Data

ホットなトピックですね。日本の問題、そして、自分ごととしてだけでなく、世界の状況を見る視点も持ちましょう。

UN data から、検索窓の上にある、Datamarts を選択し、下のほうにある、World Fertility Data United Nations Population Division (UNPD) の [+] 記号を開きます。右の [i] からは情報が得られます。三つのデータがあります。

まずは、“Age-specific fertility rates, Total fertility and Mean age at childbearing” データを使うことにします。

  1. サイトから、Excel データをダウンロード。
  2. プロジェクト内のデータ格納フォルダに入れます。“./data/”
  3. 試しに、読み込みます。
  4. Files から、Import Dataset を選択し、設定をして、もう一度、読み込む。
  5. 列名を修正
  6. 日本のデータを確認
  7. 年齢ごとの数を比較しやすいように、データを変形
  8. グラフを書いてみる。
  9. 出生平均年齢の表を降年齢順に見てみる。
  10. 密度分布グラフを書いてみる。
  11. 出生率の表を昇順に見てみる。
  12. 密度分布グラフを書いてみる。

Steps 1-3.

  1. サイトから、Excel データをダウンロード。
  2. プロジェクト内のデータ格納フォルダに入れます。“./data/” {-}
  3. 試しに、読み込みます。サイトから、Excel データをダウンロード。{-}

どんなシートがあるか見てみましょう。読み込みに問題があるときは、データ名からスペースを消し、下のコードも修正して読んでみてください。スペースなどがあると問題が起こる場合があります。

excel_sheets("./data/Age-specific fertility rates, Total fertility and .xls")
[1] "FERTILITY INDICATORS" "GENERAL NOTES"       
[3] "SOURCES"             

シートを指定するときは、sheet = 1 とか、sheet = "CHILDREN_EVER_BORN" とします。 指定がないときは、最初のシート。詳細は、Help で、read_excel として、確認してください。たくさんの、オプションがあります。

df_un_fertility <- read_excel("./data/Age-specific fertility rates, Total fertility and .xls")
New names:
df_un_fertility

構造が複雑そうです。

Step 4. Files から、Import Dataset を選択し、設定をして、もう一度、読み込む。

ファイル名も変更しておいが方がよい場合もあります。そのときは、変更記録を RNotebookに追記しておくと良いでしょう。下の例では、上の4行をスキップ。列が、text(文字) か、numeric(数値)かを選択。読み込まないときには、skip しています。

df_un_fertility <- read_excel("./data/Age-specific fertility rates, Total fertility and .xls", 
    col_types = c("text", "numeric", "text", 
        "numeric", "text", "numeric", "numeric", 
        "numeric", "numeric", "numeric", 
        "numeric", "numeric", "numeric", 
        "numeric", "skip", "text", "skip", 
        "skip", "skip", "skip", "skip", "skip"), 
    skip = 4)
df_un_fertility

Step 5. 列名を修正

修正したい列名をコピーしておく。

Country, ISO code, Period, Reference, NA, Total fertility

1列目から、6列目と、14列目と、15列目を、書き換えます。

colnames(df_un_fertility)[c(1:6,14:15)] <- c("country", "iso",  "period","year", "range",   "fertility_rate","mean_age","source")
df_un_fertility

Step 6. 日本のデータを確認

df_un_fertility_jp <- df_un_fertility %>% filter(country == "Japan")
df_un_fertility_jp

Step 7. 年齢ごとの数を比較しやすいように、データを変形

すこし、難しいですが、pivot_longer を Help で調べてください。

df_un_fertility_jp %>% pivot_longer(-c(1:6, 14:15), names_to = "age_range", values_to = "value")

Step 8. グラフを書いてみる。

df_un_fertility_jp %>% pivot_longer(-c(1:6, 14:15), names_to = "age_range", values_to = "value") %>%
  ggplot(aes(x=year, col=age_range, linetype = age_range)) + geom_line(aes(y=value)) 

いろいろなことがわかります。

Step 9. 出生平均年齢の表を降年齢順に見てみる。

df_un_fertility %>% 
  filter(year %in% c(2010)) %>% select(country, mean_age) %>% 
  drop_na(mean_age) %>%
  arrange(desc(mean_age))

Step 10. 密度分布グラフを書いてみる。

df_un_fertility %>% filter(year %in% c(1970, 1990, 2010)) %>% 
                                drop_na(mean_age) %>%
  ggplot(aes(mean_age, fill = factor(year))) + geom_density(alpha = 0.5) + 
#  scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
#  coord_cartesian(xlim=c(20,40)) + 
  labs(title="Mean age at childbearing", fill = "year")

df_un_fertility %>% drop_na(mean_age) %>% group_by(year) %>% summarise(n=n()) %>% arrange(desc(n))
df_un_fertility %>% filter(year %in% c(1970, 1985, 1995, 2005, 2010)) %>% 
                                drop_na(mean_age) %>%
  ggplot(aes(mean_age, fill = factor(year))) + geom_density(alpha = 0.3) + 
  labs(title="Mean age at childbearing", fill = "year")

df_un_fertility %>% filter(year %in% c(1970, 1985,1995, 2005,2010)) %>% 
                                drop_na(mean_age) %>%
  ggplot(aes(mean_age, fill = factor(year))) + geom_density(alpha = 0.5) + facet_wrap(~ factor(year)) +
  labs(title="Mean age at childbearing", fill = "year")

11. 出生率の表を昇順に見てみる。

df_un_fertility %>% 
  filter(year %in% c(2010)) %>% select(country, fertility_rate) %>% 
  drop_na(fertility_rate) %>%
  arrange(fertility_rate)

Step 12. 密度分布グラフを書いてみる。

df_un_fertility %>% filter(year %in% c(1970, 1990, 2010)) %>% 
                                drop_na(mean_age) %>%
  ggplot(aes(fertility_rate, fill = factor(year))) + geom_density(alpha = 0.5) + 
  labs(title="Total fertility", fill = "year")

df_un_fertility %>% drop_na(fertility_rate) %>% group_by(year) %>% summarise(n=n()) %>% arrange(desc(n))
df_un_fertility %>% filter(year %in% c(1970, 1985, 1995, 2005, 2010)) %>% 
                                drop_na(mean_age) %>%
  ggplot(aes(fertility_rate, fill = factor(year))) + geom_density(alpha = 0.5) + 
  labs(title="Total fertility", fill = "year")

df_un_fertility %>% filter(year %in% c(1970, 1985, 1995, 2005, 2010)) %>% 
                                drop_na(mean_age) %>%
  ggplot(aes(fertility_rate, fill = factor(year))) + geom_density(alpha = 0.5) + facet_wrap(~ factor(year)) +
  labs(title="Total fertility", fill = "year")

3.2.1.1 参考例1:World Inequality Report 2022

WIR2022: https://ds-sl.github.io/data-analysis/wir2022.nb.html

3.2.1.2 参考例2:学校種類別進学率の推移(日本語データ)

男女共同参画局の資料です。

学校種類別進学率の推移: https://empowerment.tsuda.ac.jp/detail/82584

url_school_jp <- "https://www.gender.go.jp/about_danjo/whitepaper/r02/zentai/html/honpen/csv/zuhyo01-04-01.csv"

エンコーディング(Encoding type)を推測することができます。

guess_encoding(url_school_jp, n_max = 10000, threshold = 0.2)
df_school_jp <- read_csv(url_school_jp, locale = locale(encoding = "Shift_JIS"), skip=2)
Rows: 70 Columns: 10── Column specification ──────────────────────────────────────────────
Delimiter: ","
chr (1): 年度
dbl (9): 高等学校等(男子), 高等学校等(女子), 専修学校(専門課程,男子), 専修学校(専門課程,女子), 大学(学部...
ℹ 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_school_jp 
df_edu0 <- df_school_jp 
colnames(df_edu0) <- c("year", "highschool_m", "highschool_f", "vocational_m", "vocational_f", "university_m", "university_f", "juniorcollege_f", "gradschool_m", "gradschool_f")
df_edu00 <- df_edu0 %>% mutate(year = 1950:2019, 
                   highschool = (highschool_m + highschool_f)/2,
                   vocational = (vocational_m + vocational_f)/2,
                   university = (university_m + university_f)/2, 
                   juniorcollege = juniorcollege_f,
                   gradschool = (gradschool_m + gradschool_f)/2) 
df_edu00 %>% filter(year >= 1954) %>% select(-(2:10)) %>% 
  pivot_longer(3:5, names_to = "schools", values_to = "percentage") %>%
  mutate(types = factor(schools, levels = c("vocational", "juniorcollege", "university"))) %>%
  pivot_longer(c(highschool, gradschool), names_to = "highgrad", values_to ="value") %>%
  mutate(high_grad = factor(highgrad, levels = c("highschool", "gradschool"))) %>%
  ggplot() +
  geom_area(aes(x = year, y = percentage, fill = types)) +
  geom_line(aes(x = year, y = value, linetype = high_grad)) + 
  scale_x_continuous(breaks = round(seq(1960, 2020, by =10),1)) + 
  scale_y_continuous(breaks = round(seq(0, 100, by =10),1)) + 
  labs(title = "Tertially Education After Highschool", 
       subtitle = "with Highschool Graduates and Graduate School", 
       fill = "", linetype = "")

3.3 (続)探索的データ解析 (EDA) 

image from r4ds

NY.GDP.PCAP.CD: GDP per capita (current US$)

df_wdi_gdppcap <- WDI(country = "all", indicator = c(gdp_pcap = "NY.GDP.PCAP.CD"))
write_csv(df_wdi_gdppcap, "./data/df_wdi_gdppcap.csv")
df_wdi_gdppcap <- read_csv("./data/df_wdi_gdppcap.csv")
Rows: 16492 Columns: 5── Column specification ──────────────────────────────────────────────
Delimiter: ","
chr (3): country, iso2c, iso3c
dbl (2): year, gdp_pcap
ℹ 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_wdi_gdppcap

3.3.1 Data Transformation

3.3.1.1 列を select

df_wdi_gdppcap_small <- df_wdi_gdppcap %>% 
  select(country, year, gdp_pcap)
df_wdi_gdppcap_small

3.3.1.2 行を filter

df_wdi_gdppcap_short <- df_wdi_gdppcap %>% 
  filter(country %in% c("Japan", "Germany", "United States"))
df_wdi_gdppcap_short
df_wdi_gdppcap_small_short <- df_wdi_gdppcap %>% select(country, year, gdp_pcap) %>%
  filter(country %in% c("Japan", "Germany", "United States"))
df_wdi_gdppcap_small_short

次は、よく生じる、誤りの例で、ノコギリの歯(sawtoothed)のようなギザギザ・グラフと呼ばれます。なぜこのようなことが起きているかわかりますか。

df_wdi_gdppcap_small_short %>%
  ggplot(aes(x = year, y = gdp_pcap)) + geom_line()

df_wdi_gdppcap_small_short %>% filter(country %in% c("Japan")) %>%
  ggplot(aes(x = year, y = gdp_pcap)) + geom_line()

df_wdi_gdppcap_small_short %>%
  ggplot(aes(x = year, y = gdp_pcap)) + geom_point()

df_wdi_gdppcap_small_short %>% drop_na(gdp_pcap) %>%
  ggplot(aes(x = year, y = gdp_pcap, col = country)) + geom_line()

df_wdi_gdppcap_small_short %>% drop_na(gdp_pcap) %>%
  ggplot(aes(x = year, y = gdp_pcap, col = country)) + geom_line() +
  geom_point()

df_wdi_gdppcap_small_short %>% drop_na(gdp_pcap) %>%
  ggplot(aes(x = year, y = gdp_pcap)) + 
  geom_point(aes(color = country)) + 
  geom_smooth(method = 'loess', formula = 'y ~ x')

4 参考 - 今後の学習のために

4.1 RNotebook の活用

下のリンクを開き、右上の Code ボタンから、Download Rmd を選択すると、ダウンロードできますから、ダインロードしたものを、プロジェクト・フォールダーに移動またはコピーしてください。ダウンロードできないときは、Ctrl を押しながら、Download Rmd をクリックすると、Save As で保存できると思います。ブラウザーによって仕様が異なりますから、適切な方法を選んでください。

Windows でも、Mac でも提供されている、Google Chrome の場合には、Code ボタンから、ダンロードされるはずです。

4.2 クラウド - Posit Cloud

RStudio Cloudは、誰でもオンラインでデータサイエンスを行い、共有し、教え、学ぶことができる、軽量でクラウドベースのソリューションです。月25時間の制限がありますが、内容を共有して、他のアカウントから利用することも可能です。

クラウドサービス How to Start Posit Cloud

  1. Go to https://posit.cloud/
  2. Sign Up: top right
  3. Email address or Google account
  4. New Project: Project Name

4.3 練習問題 Posit Primers

Posit Primers https://posit.cloud/learn/primers

最初の演習

Moodle(2月22日)にリンクをつけてあります。

LS0tCnRpdGxlOiAiRUNPMjMyIFLjgafjga/jgZjjgoHjgovjg4fjg7zjgr/jg7vjgrXjgqTjgqjjg7PjgrkiCmF1dGhvcjogIuOCsuOCueODiOism+W4q++8mumItOacqOWvm++8iEhpcm9zaGkgU3V6dWtp77yJIgpkYXRlOiAiTGFzdCBVcGRhdGVkOiBgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIHRoZW1lOiBjZXJ1bGVhbgogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICBpb3NsaWRlc19wcmVzZW50YXRpb246CiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICB3aWRlc2NyZWVuOiB5ZXMKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRSwgZXZhbD1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSkKYGBgCgojIERBWSAx77yaMuaciDIw5pelCgojIyBSU3R1ZGlvIOOBpyBQcm9qZWN0IOOBruS9nOaIkAoKIyMjIOeiuuiqjQoKMS4gIFIg44GoIFIgU3R1ZGlvIOOBruOCpOODs+OCueODiOODvOODqwoyLiAgUlN0dWRpbzogTmV3IFByb2plY3Qg5L2c5oiQCgotICAgUiBTdHVkaW8g44Gu6LW35YuVCi0gICBOZXcgUHJvamVjdDogZWNvMjMyLCBlY28yMzIuUnByb2oKCjMuICBTYXZlIOOBl+OBpuOAgee1guS6hgo0LiAg44OX44Ot44K444Kn44Kv44OI44KS6LW35YuV56K66KqNCgojIyDln7rmnKzjgrPjg57jg7Pjg4kgLSBpbiBDb25zb2xlCgotICAgYGhlYWQoY2FycylgCi0gICBgc3RyKGNhcnMpYAotICAgYHN1bW1hcnkoY2FycylgCi0gICBgZGZfY2FycyA8LSBjYXJzYAogICAgLSAgIGA8LWAg44GoIGBfYCDjgaggYCU+JWAg44GoIFxgIGJhY2sgdGljayDjga7norroqo0KLSAgIGBWaWV3KGNhcnMpYCDjgb7jgZ/jga/jgIHlj7PkuIrjga4gRW52aXJvbm1lbnQg44GL44KJ44CBYGRmX2NhcnNgIOOCkuOCr+ODquODg+OCrwotICAgYD9jYXJzYCDjgb7jgZ/jga8gSGVscCDmpJzntKLnqpPjgacgYGNhcnNgLCBgaGVhZGAg44Gq44GpCgrjgYrjgZnjgZnjgoHvvJpgU3lzLnNldGVudihMQU5HID0gImVuIilgCgojIyBQYWNrYWdlIOOBrueiuuiqjeOBqOOCpOODs+OCueODiOODvOODqwoKUiBwYWNrYWdlcyBhcmUgZXh0ZW5zaW9ucyB0byB0aGUgUiBzdGF0aXN0aWNhbCBwcm9ncmFtbWluZyBsYW5ndWFnZSBjb250YWluaW5nIGNvZGUsIGRhdGEsIGFuZCBkb2N1bWVudGF0aW9uIGluIGEgc3RhbmRhcmRpc2VkIGNvbGxlY3Rpb24gZm9ybWF0IHRoYXQgY2FuIGJlIGluc3RhbGxlZCBieSB1c2VycyBvZiBSIHVzaW5nIFRvb2wgXD4gSW5zdGFsbCBQYWNrYWdlcyBpbiB0aGUgdG9wIG1lbnUgYmFyIG9mIFIgU3R1ZGlvLgoKUuODkeODg+OCseODvOOCuOOBr+OAgVLjga7mi6HlvLXmqZ/og73jgafjgIHjgrPjg7zjg4njgIHjg4fjg7zjgr/jgIHjg4njgq3jg6Xjg6Hjg7Pjg4jjgpLmqJnmupbljJbjgZXjgozjgZ/jgrPjg6zjgq/jgrfjg6fjg7PlvaLlvI/jgaflkKvjgpPjgafjgYrjgorjgIHmqJnmupbnmoTjgarjgoLjga7jga/jgIFSIFN0dWRpbyDjga4gVG9wIEJhciDjga4gVG9vbCBcPiBJbnN0YWxsIFBhY2thZ2VzIOOBi+OCieOCpOODs+OCueODiOODvOODq+OBp+OBjeOBvuOBmeOAggoKLSAgIE1pbmltdW06IGB0aWR5dmVyc2VgLCBgcm1hcmtkb3duYCwgYFdESWAKCuOBguOBqOOBi+OCieS9v+OBhuOBruOBp+OAgeODreODvOODieOBl+OBpuOBiuOBjeOBvuOBmeOAguacgOWIneOBq+asoeOBruOCiOOBhuOBquOCs+ODvOODieOCkuWun+ihjOOBl+OBvuOBmeOAguWPs+OBruS4ieinkuOCkuaKvOOBl+OBvuOBmeOAggoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KFdESSkKYGBgCgojIyBSIE1hcmtkb3duIOWFpemWgAoKIyMjIFIgTm90ZWJvb2sKClIgTWFya2Rvd27jga/jg4fjg7zjgr/jgrXjgqTjgqjjg7Pjgrnjga7jgZ/jgoHjga7jgqrjg7zjgrXjg6rjg7PjgrDjg5Xjg6zjg7zjg6Djg6/jg7zjgq/jgIIKCuOCs+ODvOODie+8iOODl+ODreOCsOODqeODoO+8ieOBqOOBneOBruWun+ihjOe1kOaenOOAgeOCkuiomOmMsuODu+ihqOekuuOBl+OAgemrmOWTgeizquOBruODrOODneODvOODiOOBruS9nOaIkOOCkuWPr+iDveOBq+OBl+OBvuOBmeOAggoKUiBOb3RlYm9vayDjga/jgIHni6znq4vjgZfjgabjgqTjg7Pjgr/jg6njgq/jg4bjgqPjg5bjgavlrp/ooYzjgafjgY3jgovjg4Hjg6Pjg7Pjgq/jgpLmjIHjgaRSIE1hcmtkb3du44OJ44Kt44Ol44Oh44Oz44OI44Gu5LiA44Gk44Gu5b2i5byP44Gn44CB5YWl5Yqb44Gu44GZ44GQ5LiL44Gr5Ye65Yqb44GM6KGo56S644GZ44KL44GT44Go44GM44Gn44GN44G+44GZ44CCCgoxLiAgRmlsZSBcPiBOZXcgRmlsZSBcPiBSIE5vdGVib29rCjIuICBTYXZlIHdpdGggYSBmaWxlIG5hbWUsIHNheSwgdGVzdC1ub3RlYm9vawozLiAgUHJldmlldyBieSBbUHJldmlld10gYnV0dG9uCjQuICBSdW4gQ29kZSBDaHVuayBwbG90KGNhcnMpIGFuZCB0aGVuIFByZXZpZXcgYWdhaW4uCgojIyBXb3JsZCBEZXZlbG9wbWVudCBJbmRpY2F0b3IgKFdESSkKCmBgYHtyIGNhY2hlPVRSVUV9CldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoZ2RwID0gIk5ZLkdEUC5NS1RQLkNEIiksCiAgICBleHRyYT1UUlVFKSAlPiUgZHJvcF9uYShnZHApICU+JQogIGZpbHRlcih5ZWFyPT1tYXgoeWVhciksIGluY29tZSAhPSJBZ2dyZWdhdGVzIikgJT4lIAogIGRyb3BfbmEocmVnaW9uKSAlPiUgYXJyYW5nZShkZXNjKGdkcCkpCmBgYAoKYGBge3IgY2FjaGU9VFJVRX0KY2hvc2VuX2NvdW50cmllcyA8LSBjKCJVbml0ZWQgU3RhdGVzIiwiQ2hpbmEiLCAiSmFwYW4iLCAiR2VybWFueSIsICJVbml0ZWQgS2luZ2RvbSIsIkluZGlhIikKV0RJKGNvdW50cnkgPSBjKCJDTiIsIkdCIiwiSlAiLCJJTiIsIlVTIiwiREUiKSwgaW5kaWNhdG9yID0gYyhnZHAgPSAiTlkuR0RQLk1LVFAuQ0QiKSwgZXh0cmE9VFJVRSkgJT4lIGRyb3BfbmEoZ2RwKSAlPiUgCiAgZ2dwbG90KGFlcyh5ZWFyLCBnZHAsIGNvbCA9IGNvdW50cnkpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gIldESSBOWS5HRFAuTUtUUC5DRDogZ2RwIikKYGBgCgpgYGB7ciBjYWNoZT1UUlVFfQpXREkoY291bnRyeSA9IGMoIkNOIiwiSU4iLCJKUCIsIlVTIiksIAogICAgaW5kaWNhdG9yID0gYyhnZHBfZ3Jvd3RoX3JhdGUgPSAiTlkuR0RQLk1LVFAuS0QuWkciKSwgZXh0cmE9VFJVRSkgJT4lCiAgZHJvcF9uYShnZHBfZ3Jvd3RoX3JhdGUpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIGdkcF9ncm93dGhfcmF0ZSwgY29sID0gY291bnRyeSkpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiV0RJIE5ZLkdEUC5NS1RQLktELlpHOiBnZHAgZ3Jvd3RoIHJhdGUiKSkKYGBgCgojIyMg5oyH5qiZIEluZGljYXRvcnMgKFdESSkKCi0gICBOWS5HRFAuTUtUUC5DRDogR0RQIChjdXJyZW50IFVTXCQpCi0gICBOWS5HRFAuTUtUUC5LRC5aRzogR0RQIGdyb3d0aCAoYW5udWFsICUpCgojIyMg5oyH5qiZIFdESSDjgpLmjqLjgZfjgabjgb/jgojjgYYKCj4gVGhlIFdvcmxkIERldmVsb3BtZW50IEluZGljYXRvcnMgaXMgYSBjb21waWxhdGlvbiBvZiByZWxldmFudCwgaGlnaC1xdWFsaXR5LCBhbmQgaW50ZXJuYXRpb25hbGx5IGNvbXBhcmFibGUgc3RhdGlzdGljcyBhYm91dCBnbG9iYWwgZGV2ZWxvcG1lbnQgYW5kIHRoZSBmaWdodCBhZ2FpbnN0IHBvdmVydHkuIFRoZSBkYXRhYmFzZSBjb250YWlucyAxLDQwMCB0aW1lIHNlcmllcyBpbmRpY2F0b3JzIGZvciAyMTcgZWNvbm9taWVzIGFuZCBtb3JlIHRoYW4gNDAgY291bnRyeSBncm91cHMsIHdpdGggZGF0YSBmb3IgbWFueSBpbmRpY2F0b3JzIGdvaW5nIGJhY2sgbW9yZSB0aGFuIDUwIHllYXJzLgoKPiBXREnjga/jgIHkuJbnlYzjga7plovnmbrnirbms4HjgajjgIHosqflm7Djgajjga7miKbjgYTjgavplqLjgZnjgovjgIHpganliIfjgafkuIros6rjgIHjgYvjgaTjgIHlm73pmpvnmoTjgavmr5TovIPlj6/og73jgarmmYLns7vliJfjga7ntbHoqIjjg4fjg7zjgr/jgpLnt6jnuoLjgZfjgZ/jgoLjga7jgafjgZnjgILjgZPjga7jg4fjg7zjgr/jg5njg7zjgrnjga/jgIEyMTfjga7ntYzmuIjjgag0MOS7peS4iuOBruWbveOCsOODq+ODvOODl+OBq+OBpOOBhOOBpjEsNDAw44Gu5pmC57O75YiX5oyH5qiZ44KS5ZCr44G/44CB5oyH5qiZ44Gu44OH44O844K/44Gu5aSa44GP44GvNTDlubTku6XkuIrliY3jgavpgaHjgovjgZPjgajjgYzjgafjgY3jgb7jgZnjgIIKCi0gICDkuJbnlYzpioDooYzvvIhXb3JsZCBCYW5r77yJOiAKLSAgIFdvcmxkIEJhbmsgT3BlbiBEYXRhOiAKICAgIC0gICBDb3VudHJ5IC8gSW5kaWNhdG9yIFw+IEZlYXR1cmVkICYgQWxsIFw+IERldGFpbHMKLSAgIFtXb3JsZCBEZXZlbG9wbWVudCBJbmRpY2F0b3JzIChXREkpXShodHRwczovL2RhdGF0b3BpY3Mud29ybGRiYW5rLm9yZy93b3JsZC1kZXZlbG9wbWVudC1pbmRpY2F0b3JzLykgOgogICAgLSAgIFRoZW1lczogUG92ZXJ0eSBhbmQgSW5lcXVhbGl0eSwgUGVvcGxlLCBFbnZpcm9ubWVudCwgRWNvbm9teSwgU3RhdGVzIGFuZCBNYXJrZXRzLCBHbG9iYWwgTGlua3MKICAgIC0gICBPcGVuIERhdGEgJiBEYXRhQmFuazogRXhwbG9yZSBkYXRhLCBRdWVyeSBkYXRhYmFzZQoKIyMjIOaMh+aomSBXREnjga7kvosKCiogTlkuR0RQLk1LVFAuQ0Q6IEdEUCAoY3VycmVudCBVUyQpCiogTlkuR0RQLkRFRkwuS0QuWkc6IEluZmxhdGlvbiwgR0RQIGRlZmxhdG9yIChhbm51YWwgJSkKKiBTTC5VRU0uVE9UTC5ORS5aUzogVW5lbXBsb3ltZW50LCB0b3RhbCAoJSBvZiB0b3RhbCBsYWJvciBmb3JjZSkgKG5hdGlvbmFsIGVzdGltYXRlKQoqIENQVE9UTlNYTjogQ1BJIFByaWNlLCBub21pbmFsCiogU0wuVExGLkNBQ1QuTUEuTkUuWlM6IExhYm9yIGZvcmNlIHBhcnRpY2lwYXRpb24gcmF0ZSwgbWFsZSAoJSBvZiBtYWxlIHBvcHVsYXRpb24gYWdlcyAxNSspIChuYXRpb25hbCBlc3RpbWF0ZSkKKiBTTC5UTEYuQ0FDVC5GRS5ORS5aUzogTGFib3IgZm9yY2UgcGFydGljaXBhdGlvbiByYXRlLCBmZW1hbGUgKCUgb2YgbWFsZSBwb3B1bGF0aW9uIGFnZXMgMTUrKSAobmF0aW9uYWwgZXN0aW1hdGUpCgojIyMg57e057+SIDEuIC0g6Kq/44G544Gm44G/44Gf44GEIFdESQoK44GE44GP44Gk44GL44CB44Oq44K544OI44GX44Gm44G/44G+44GX44KH44GG44CCCgojIyBXREkg44OR44OD44Kx44O844K4CgpgV0RJYCDjg5Hjg4PjgrHjg7zjgrjjgafjgIHjg4fjg7zjgr/jgpLjg4Djgqbjg7Pjg63jg7zjg4njgZfjgZ/jgorjgIHmjqLjgZfjgZ/jgorjgIHoqbPntLDmg4XloLHjgpLlvpfjgZ/jgorjgafjgY3jgb7jgZnjgIIKCiMjIyDmjIfmqJkgV0RJIOaknOe0ogoKIyMjIyDmpJzntKLkvosgMe+8iFdESeWQje+8iQoKYGBge3IgY2FjaGU9VFJVRX0KV0RJc2VhcmNoKHN0cmluZyA9ICJnZHAiLCBmaWVsZCA9ICJuYW1lIiwgc2hvcnQgPSBUUlVFLCBjYWNoZSA9IE5VTEwpCmBgYAoKICAKIyMjIyDmpJzntKLkvosgMu+8iFdESe+8iQoKYGBge3IgY2FjaGU9VFJVRX0KV0RJc2VhcmNoKHN0cmluZyA9ICJOWS5HRFAuTUtUUC5DRCIsIGZpZWxkID0gImluZGljYXRvciIsIHNob3J0ID0gVFJVRSwgY2FjaGUgPSBOVUxMKQpgYGAKCiAgCiMjIyMg57e057+SIDIuIC0g5qSc57Si77yIc2hvcnTvvIkKCuWQjeWJjeOBp+aknOe0ou+8iCIiIOOBrumWk+OBq+OAge+8iOOBquOCi+OBueOBj+ewoeWNmOOBqu+8ieaknOe0ouaWh+Wtl+WIl+OCkuWFpeOCjOOBpuOBj+OBoOOBleOBhOOAgu+8iQoKYGBge3IgY2FjaGU9VFJVRX0KV0RJc2VhcmNoKHN0cmluZyA9ICIiLCBmaWVsZCA9ICJuYW1lIiwgc2hvcnQgPSBUUlVFLCBjYWNoZSA9IE5VTEwpCmBgYAoKSW5kaWNhdG9yIOOBp+aknOe0ou+8iCIiIOOBrumWk+OBq+OAgeiqv+OBueOBn+OBhCBpbmRpY2F0b3Ig44KS5YWl44KM44Gm44GP44Gg44GV44GE44CC77yJCgpgYGB7ciBjYWNoZT1UUlVFfQpXRElzZWFyY2goc3RyaW5nID0gIiIsIGZpZWxkID0gImluZGljYXRvciIsIHNob3J0ID0gVFJVRSwgY2FjaGUgPSBOVUxMKQpgYGAKCiMjIyMg6Kmz44GX44GE5oOF5aCx44KS5b6X44KL44Gr44GvCgpgc2hvcnQgPSBGQUxTRWAg44Go44GX44G+44GZ44CC5pmC6ZaT44GM44GL44GL44KL44Gu44Gn44CB5qSc57Si44Gv44CBSW5kaWNhdG9yIOOBqOOAgeWQjeWJjeOBquOBqeOBruaDheWgseOCkuOCguOBo+OBn+ODleOCoeOCpOODq+OCkuaJi+WFg+OBq+aMgeOBo+OBpuOBiuOBj+OBk+OBqOOBq+OBl+OBvuOBmeOAggoKYGBge3IgY2FjaGU9VFJVRX0Kd2RpX2NhY2hlIDwtIFdESWNhY2hlKCkKYGBgCgrlj7PkuIrjga7nqpPmnqDvvIhwYW5l77yJ44GL44KJ44CBYHdkaV9jYWNoZWAg44KS5o6i44GX44Gm44CB5Lit6Lqr44KS6KaL44Gm44G/44G+44GX44KH44GG44CCc2VyaWVzIOOBqOOAgWNvdW50cnkg44Gu5LqM44Gk44Gu44OH44O844K/44O744OV44Os44O844Og44GL44KJ44Gq44Gj44Gm44GE44KL44Oq44K544OI44Gn44GZ44CC5LiJ6KeS5Y2w44KE44CB5Y+z44GL44KJ5LqM55Wq55uu44Gu5be754mp44Gu44KI44GG44Gq44Ki44Kk44Kz44Oz44KS44Kv44Oq44OD44Kv44GZ44KL44Go5Lit6Lqr44GM6KaL44GI44G+44GZ44CCCiAgCiMjIyMg5qSc57Si5L6LIDPvvIhXREnlkI3vvIkKCmBgYHtyfQpXRElzZWFyY2goc3RyaW5nID0gIkNQSSBQcmljZSIsIGZpZWxkID0gIm5hbWUiLCBzaG9ydCA9IEZBTFNFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgotIENQVE9UTlNYTjogQ1BJIFByaWNlLCBub21pbmFsCiAgLSBUaGUgY29uc3VtZXIgcHJpY2UgaW5kZXggcmVmbGVjdHMgdGhlIGNoYW5nZSBpbiBwcmljZXMgZm9yIHRoZSBhdmVyYWdlIGNvbnN1bWVyIG9mIGEgY29uc3RhbnQgYmFza2V0IG9mIGNvbnN1bWVyIGdvb2RzLiBEYXRhIGlzIG5vdCBzZWFzb25hbGx5IGFkanVzdGVkLgoKIyMjIyDmpJzntKLkvosgNO+8iFdESe+8iQoKYGBge3J9CldESXNlYXJjaChzdHJpbmcgPSAiTlkuR0RQLk1LVFAuS0QuWkciLCBmaWVsZCA9ICJpbmRpY2F0b3IiLCBzaG9ydCA9IEZBTFNFLCBjYWNoZSA9IHdkaV9jYWNoZSkKYGBgCgogIAojIyMjIOe3tOe/kiAyIC0g5qSc57Si77yIbG9uZyB3LyBjYWNoZe+8iQoKYHN0cmluZ2Ag44Go44CBYGZpZWxkYCDjgpLjgIHjgbXjgZ/jgaTjgajjgoLlhaXjgozjgabjgY/jgaDjgZXjgYTjgIIKCmBgYHtyIGV2YWw9RkFMU0V9CldESXNlYXJjaChzdHJpbmcgPSAiIiwgZmllbGQgPSAiIiwgc2hvcnQgPSBGQUxTRSwgY2FjaGUgPSB3ZGlfY2FjaGUpCmBgYAoKCiMgREFZIDLvvJoy5pyIMjLml6UKCiMjIO+8iOe2mu+8iVdESSDjg5Hjg4PjgrHjg7zjgrgKCiMjIyDmjIfmqJkgV0RJIOODh+ODvOOCv+OBruODgOOCpuODs+ODreODvOODiQoKSW5kaWNhdG9yIOOBjOaxuuOBvuOBo+OBn+OCieOAgeODgOOCpuODs+ODreODvOODieOBl+OBvuOBmeOAggoKYGBge3IgZXZhbD1GQUxTRX0KP1dESQpgYGAKCiAgCiMjIyMg44OA44Km44Oz44Ot44O844OJ5L6LIDEtMQoKYGBge3IgY2FjaGU9VFJVRX0KZGZfZ2RwMSA8LSBXREkoY291bnRyeSA9ICJhbGwiLCBpbmRpY2F0b3IgPSAiTlkuR0RQLk1LVFAuQ0QiKQpkZl9nZHAxCmBgYAoKICAKIyMjIyDjg4Djgqbjg7Pjg63jg7zjg4nkvosgMS0yCgpgYGB7ciBjYWNoZT1UUlVFfQpkZl9nZHAyIDwtIFdESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoZ2RwID0gIk5ZLkdEUC5NS1RQLkNEIikpCmRmX2dkcDIKYGBgCgogIAojIyMjIOODgOOCpuODs+ODreODvOODieS+iyAxLTMKCmBgYHtyIGNhY2hlPVRSVUV9CmRmX2dkcDMgPC0gV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0gYyhnZHAgPSAiTlkuR0RQLk1LVFAuQ0QiKSwgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKQpkZl9nZHAzCmBgYAoKICAKIyMjIyDjg4Djgqbjg7Pjg63jg7zjg4nkvosgMS00CgpgYGB7ciBjYWNoZT1UUlVFfQpkZl9nZHA0IDwtIFdESShjb3VudHJ5ID0gYygiQ04iLCJHQiIsIkpQIiwiSU4iLCJVUyIsIkRFIiksIGluZGljYXRvciA9IGMoZ2RwID0gIk5ZLkdEUC5NS1RQLkNEIiksIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkKZGZfZ2RwNApgYGAKCiMjIyMg44OA44Km44Oz44Ot44O844OJ5L6LIDItMQoKKiBOWS5HRFAuREVGTC5LRC5aRzogSW5mbGF0aW9uLCBHRFAgZGVmbGF0b3IgKGFubnVhbCAlKQoqIENQVE9UTlNYTjogQ1BJIFByaWNlLCBub21pbmFsCgpgYGB7ciBjYWNoZT1UUlVFfQpkZl9nZHAyMSA8LSBXREkoY291bnRyeSA9ICJhbGwiLCAKICAgICAgICAgICAgICAgIGluZGljYXRvciA9IGMoZ2RwX2RlZmxhdG9yID0gIk5ZLkdEUC5ERUZMLktELlpHIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNwaV9wcmljZSA9ICJDUFRPVE5TWE4iKSwgCiAgICAgICAgICAgICAgICBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpCmRmX2dkcDIxCmBgYAoKYGBge3J9CnN0cihkZl9nZHAyMSkKYGBgCgpgYGB7cn0Kc3VtbWFyeShkZl9nZHAyMSkKYGBgCgrlj7PkuIrjga7nqpPmnqDjga7jgIFFbnZpcm9ubWVudCDjgoLopovjgabjgb/jgb7jgZfjgofjgYbjgIIKCiMjIOWPr+imluWMliBWaXN1YWxpemF0aW9uCgrjgrDjg6njg5XvvIhDaGFydO+8ieOCkuaPj+OBhOOBpuimluimmuWMluOBl+OCiOOBhgoKIyMjIOOCsOODqeODlSAxCgpgYGB7cn0KZGZfZ2RwNCAlPiUgZ2dwbG90KGFlcyh5ZWFyLCBnZHAsIGNvbD1jb3VudHJ5KSkgKyBnZW9tX2xpbmUoKQpgYGAKCiMjIyDjgrDjg6njg5UgMgoKYGBge3J9CmRmX2dkcDQgJT4lIGRyb3BfbmEoZ2RwKSAlPiUgCiAgZ2dwbG90KGFlcyh5ZWFyLCBnZHAsIGNvbD1jb3VudHJ5KSkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJXREkgLSBOWS5HRFAuTUtUUC5DRDogIiwgImdkcCIpKQpgYGAKCiMjIyDjg4bjg7Pjg5fjg6zjg7zjg4ggVGVtcGxhdGVzCgojIyMjIOS4gOOBpOOBruWbveOBq+OBpOOBhOOBpuOBruOAgeS4gOOBpOOBruaMh+aome+8iFdESe+8ieOBqOOAgeOBneOBrueVpeensOOBi+OCieOAgeaKmOe3muOCsOODqeODleOCkuS9nOaIkAoKTGluZSBQbG90IHdpdGggb25lIGluZGljYXRvciB3aXRoIGFiYnJldmlhdGlvbiBhbmQgb25lIGNvdW50cnkKCmBgYHtyIGNhY2hlPVRSVUV9CmNob3Nlbl9pbmRpY2F0b3IgPC0gIlNMLlVFTS5UT1RMLk5FLlpTIgpzaG9ydF9uYW1lIDwtICJ1bmVtcGxveW1lbnQiCmNob3Nlbl9jb3VudHJ5IDwtICJVbml0ZWQgU3RhdGVzIgpXREkoY291bnRyeSA9ICJhbGwiLCBpbmRpY2F0b3IgPSBjKHNob3J0X25hbWUgPSBjaG9zZW5faW5kaWNhdG9yKSwgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKSAlPiUKICBmaWx0ZXIoY291bnRyeSA9PSBjaG9zZW5fY291bnRyeSkgJT4lIAogIGdncGxvdChhZXMoeWVhciwgc2hvcnRfbmFtZSkpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiV0RJICIsIGNob3Nlbl9pbmRpY2F0b3IsICI6ICIsIHNob3J0X25hbWUsICIgLSAiLCBjaG9zZW5fY291bnRyeSksCiAgICAgICB5ID0gc2hvcnRfbmFtZSkKYGBgCgojIyMjIOS4gOOBpOOBruWbveOBq+OBpOOBhOOBpuOBruOAgeS4gOOBpOOBruaMh+aome+8iFdESe+8ieOBi+OCieOAgeaKmOe3muOCsOODqeODleOCkuS9nOaIkAoKTGluZSBQbG90IHdpdGggb25lIGluZGljYXRvciBhbmQgb25lIGNvdW50cnkKCmBgYHtyIGNhY2hlPVRSVUV9CmNob3Nlbl9pbmRpY2F0b3IgPC0gIlNMLlVFTS5UT1RMLk5FLlpTIgpjaG9zZW5fY291bnRyeSA8LSAiVW5pdGVkIFN0YXRlcyIKV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0gYyhjaG9zZW5faW5kaWNhdG9yID0gY2hvc2VuX2luZGljYXRvciksIAogICAgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKSAlPiUKICBmaWx0ZXIoY291bnRyeSA9PSBjaG9zZW5fY291bnRyeSkgJT4lIAogIGdncGxvdChhZXMoeWVhciwgY2hvc2VuX2luZGljYXRvcikpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiV0RJICIsIGNob3Nlbl9pbmRpY2F0b3IsICIgLSAiLCBjaG9zZW5fY291bnRyeSksIAogICAgICAgeSA9IGNob3Nlbl9pbmRpY2F0b3IpCmBgYAoKIyMjIyDjgYTjgY/jgaTjgYvjga7lm73jgavjgaTjgYTjgabjga7jgIHkuIDjgaTjga7mjIfmqJnvvIhXREnvvInjgajjgIHjgZ3jga7nlaXnp7DjgYvjgonjgIHmipjnt5rjgrDjg6njg5XjgpLkvZzmiJAKCkxpbmUgUGxvdCB3aXRoIG9uZSBpbmRpY2F0b3Igd2l0aCBhYmJyZXZpYXRpb24gYW5kIHNldmVyYWwgY291bnRyaWVzCgpgYGB7ciBjYWNoZT1UUlVFfQpjaG9zZW5faW5kaWNhdG9yIDwtICJTTC5VRU0uVE9UTC5ORS5aUyIKc2hvcnRfbmFtZSA8LSAidW5lbXBsb3ltZW50IgpjaG9zZW5fY291bnRyaWVzIDwtIGMoIlVuaXRlZCBTdGF0ZXMiLCJVbml0ZWQgS2luZ2RvbSIsICJKYXBhbiIpCldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoc2hvcnRfbmFtZSA9IGNob3Nlbl9pbmRpY2F0b3IpLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpICU+JSBkcm9wX25hKHNob3J0X25hbWUpICU+JSAKICBmaWx0ZXIoY291bnRyeSAlaW4lIGNob3Nlbl9jb3VudHJpZXMpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIHNob3J0X25hbWUsIGNvbCA9IGNvdW50cnkpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIldESSAiLCBjaG9zZW5faW5kaWNhdG9yLCAiOiAiLCBzaG9ydF9uYW1lKSwgeSA9IHNob3J0X25hbWUpCmBgYAoKCiMjIyMg5LiA44Gk44Gu5Zu944Gr44Gk44GE44Gm44Gu44CB5LqM44Gk44Gu5oyH5qiZ77yIV0RJ77yJ44Go44CB44Gd44Gu55Wl56ew44GL44KJ44CB5oqY57ea44Kw44Op44OV44KS5L2c5oiQCgpMaW5lIFBsb3Qgd2l0aCB0d28gaW5kaWNhdG9ycyB3aXRoIGFiYnJldmlhdGlvbiBhbmQgb25lIGNvdW50cnkKCmBgYHtyIGNhY2hlPVRSVUV9CmNob3Nlbl9pbmRpY2F0b3JfMSA8LSAiTlkuR0RQLkRFRkwuS0QuWkciCnNob3J0X25hbWVfMSA8LSAiZ2RwX2RlZmxhdG9yIgpjaG9zZW5faW5kaWNhdG9yXzIgPC0gIkNQVE9UU0FYTlpHWSIKc2hvcnRfbmFtZV8yIDwtICJjcGlfcHJpY2UiCmNob3Nlbl9jb3VudHJ5IDwtICJVbml0ZWQgU3RhdGVzIgpXREkoY291bnRyeSA9ICJhbGwiLCBpbmRpY2F0b3IgPSBjKHNob3J0X25hbWVfMSA9IGNob3Nlbl9pbmRpY2F0b3JfMSwgc2hvcnRfbmFtZV8yID0gY2hvc2VuX2luZGljYXRvcl8yKSwgZXh0cmE9VFJVRSwgY2FjaGU9d2RpX2NhY2hlKSAlPiUgCiAgZmlsdGVyKGNvdW50cnkgPT0gY2hvc2VuX2NvdW50cnkpICU+JSAKICBwaXZvdF9sb25nZXIoYyhzaG9ydF9uYW1lXzEsIHNob3J0X25hbWVfMiksIG5hbWVzX3RvID0gImNsYXNzIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lIGRyb3BfbmEodmFsdWUpICU+JQogIGdncGxvdChhZXMoeWVhciwgdmFsdWUsIGNvbCA9IGNsYXNzKSkgKyBnZW9tX2xpbmUoKSArCiAgbGFicyh0aXRsZSA9IHBhc3RlKCJXREkgIiwgY2hvc2VuX2luZGljYXRvcl8xLCAiOiAiLCBzaG9ydF9uYW1lXzEsICJcbiIsIGNob3Nlbl9pbmRpY2F0b3JfMiwgIjogIiwgc2hvcnRfbmFtZV8yLCAiIC0gIiwgY2hvc2VuX2NvdW50cnkpKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKGxhYmVscyA9IGMoc2hvcnRfbmFtZV8xLCBzaG9ydF9uYW1lXzIpLCB2YWx1ZXMgPSBzY2FsZXM6Omh1ZV9wYWwoKSgyKSkKYGBgCgpgYGB7ciBjYWNoZT1UUlVFfQpjaG9zZW5faW5kaWNhdG9yXzEgPC0gIlNMLlRMRi5DQUNULk1BLk5FLlpTIgpzaG9ydF9uYW1lXzEgPC0gIm1hbGUiCmNob3Nlbl9pbmRpY2F0b3JfMiA8LSAiU0wuVExGLkNBQ1QuRkUuTkUuWlMiCnNob3J0X25hbWVfMiA8LSAiZmVtYWxlIgpjaG9zZW5fY291bnRyeSA8LSAiVW5pdGVkIFN0YXRlcyIKV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0gYyhzaG9ydF9uYW1lXzEgPSBjaG9zZW5faW5kaWNhdG9yXzEsIHNob3J0X25hbWVfMiA9IGNob3Nlbl9pbmRpY2F0b3JfMiksIGV4dHJhPVRSVUUsIGNhY2hlPXdkaV9jYWNoZSkgJT4lIAogIGZpbHRlcihjb3VudHJ5ID09IGNob3Nlbl9jb3VudHJ5KSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGMoc2hvcnRfbmFtZV8xLCBzaG9ydF9uYW1lXzIpLCBuYW1lc190byA9ICJjbGFzcyIsIHZhbHVlc190byA9ICJ2YWx1ZSIpICU+JSBkcm9wX25hKHZhbHVlKSAlPiUKICBnZ3Bsb3QoYWVzKHllYXIsIHZhbHVlLCBjb2wgPSBjbGFzcykpICsgZ2VvbV9saW5lKCkgKwogIGxhYnModGl0bGUgPSBwYXN0ZSgiV0RJICIsIGNob3Nlbl9pbmRpY2F0b3JfMSwgIjogIiwgc2hvcnRfbmFtZV8xLCAiXG4iLCBjaG9zZW5faW5kaWNhdG9yXzIsICI6ICIsIHNob3J0X25hbWVfMiwgIiAtICIsIGNob3Nlbl9jb3VudHJ5KSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbChsYWJlbHMgPSBjKHNob3J0X25hbWVfMSwgc2hvcnRfbmFtZV8yKSwgdmFsdWVzID0gc2NhbGVzOjpodWVfcGFsKCkoMikpCmBgYAoKIyMjIyDjgYTjgY/jgaTjgYvjga7lm73jgavjgaTjgYTjgabjga7jgIHkuozjgaTjga7mjIfmqJnvvIhXREnvvInjgajjgIHjgZ3jga7nlaXnp7DjgYvjgonjgIHmipjnt5rjgrDjg6njg5XjgpLkvZzmiJAKCkxpbmUgUGxvdCB3aXRoIHR3byBpbmRpY2F0b3JzIHdpdGggYWJicmV2aWF0aW9uIGFuZCBzZXZlcmFsIGNvdW50cmllcwoKYGBge3IgY2FjaGU9VFJVRX0KY2hvc2VuX2luZGljYXRvcl8xIDwtICJOWS5HRFAuREVGTC5LRC5aRyIKc2hvcnRfbmFtZV8xIDwtICJnZHBfZGVmbGF0b3IiCmNob3Nlbl9pbmRpY2F0b3JfMiA8LSAiQ1BUT1RTQVhOWkdZIgpzaG9ydF9uYW1lXzIgPC0gImNwaV9wcmljZSIKY2hvc2VuX2NvdW50cmllcyA8LSBjKCJVbml0ZWQgU3RhdGVzIiwgIkZyYW5jZSIsICJKYXBhbiIpCldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoc2hvcnRfbmFtZV8xID0gY2hvc2VuX2luZGljYXRvcl8xLCBzaG9ydF9uYW1lXzIgPSBjaG9zZW5faW5kaWNhdG9yXzIpLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpICU+JSAKICBmaWx0ZXIoY291bnRyeSAlaW4lIGNob3Nlbl9jb3VudHJpZXMpICU+JSAKICBwaXZvdF9sb25nZXIoYyhzaG9ydF9uYW1lXzEsIHNob3J0X25hbWVfMiksIG5hbWVzX3RvID0gImNsYXNzIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lIGRyb3BfbmEodmFsdWUpICU+JQogIGdncGxvdChhZXMoeWVhciwgdmFsdWUsIGxpbmV0eXBlID0gY2xhc3MsIGNvbCA9IGNvdW50cnkpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIldESSAiLCBjaG9zZW5faW5kaWNhdG9yXzEsICI6ICIsIHNob3J0X25hbWVfMSwgIlxuIiwgY2hvc2VuX2luZGljYXRvcl8yLCAiOiAiLCBzaG9ydF9uYW1lXzIpKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKGxhYmVscyA9IGMoc2hvcnRfbmFtZV8xLCBzaG9ydF9uYW1lXzIpLCB2YWx1ZXMgPSBjKCJzb2xpZCIsICJkYXNoZWQiKSkKYGBgCgoKYGBge3IgY2FjaGU9VFJVRX0KY2hvc2VuX2luZGljYXRvcl8xIDwtICJTTC5UTEYuQ0FDVC5NQS5ORS5aUyIKc2hvcnRfbmFtZV8xIDwtICJtYWxlIgpjaG9zZW5faW5kaWNhdG9yXzIgPC0gIlNMLlRMRi5DQUNULkZFLk5FLlpTIgpzaG9ydF9uYW1lXzIgPC0gImZlbWFsZSIKY2hvc2VuX2NvdW50cmllcyA8LSBjKCJVbml0ZWQgU3RhdGVzIiwgIkZyYW5jZSIsICJKYXBhbiIpCldESShjb3VudHJ5ID0gImFsbCIsIGluZGljYXRvciA9IGMoc2hvcnRfbmFtZV8xID0gY2hvc2VuX2luZGljYXRvcl8xLCBzaG9ydF9uYW1lXzIgPSBjaG9zZW5faW5kaWNhdG9yXzIpLCBleHRyYT1UUlVFLCBjYWNoZT13ZGlfY2FjaGUpICU+JSAKICBmaWx0ZXIoY291bnRyeSAlaW4lIGNob3Nlbl9jb3VudHJpZXMpICU+JSAKICBwaXZvdF9sb25nZXIoYyhzaG9ydF9uYW1lXzEsIHNob3J0X25hbWVfMiksIG5hbWVzX3RvID0gImNsYXNzIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lIGRyb3BfbmEodmFsdWUpICU+JQogIGdncGxvdChhZXMoeWVhciwgdmFsdWUsIGxpbmV0eXBlID0gY2xhc3MsIGNvbCA9IGNvdW50cnkpKSArIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gcGFzdGUoIldESSAiLCBjaG9zZW5faW5kaWNhdG9yXzEsICI6ICIsIHNob3J0X25hbWVfMSwgIlxuIiwgY2hvc2VuX2luZGljYXRvcl8yLCAiOiAiLCBzaG9ydF9uYW1lXzIpKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKGxhYmVscyA9IGMoc2hvcnRfbmFtZV8xLCBzaG9ydF9uYW1lXzIpLCB2YWx1ZXMgPSBjKCJzb2xpZCIsICJkYXNoZWQiKSkKYGBgCgoKIyMg6Kqy6aGM44CAQXNzaWdubWVudAoK5LiK44Gu44OG44Oz44OX44Os44O844OI44KS44Kz44OU44O844GX44Gm44CB5LiL44Gr6LK844KK5LuY44GR44CB5oyH5qiZIGBpbmRpY2F0b3JgIOOBqOOAgeeVpeensCBgc2hvcnRfbmFtZWAg44Go44CB44GE44GP44Gk44GL44Gu5Zu95ZCNIGBjaG9zZW5fY291bnRyaWVzYCDjgpLjgIHlhaXjgozmm7/jgYjjgabjgIHoqabjgZfjgabjgb/jgabjgY/jgaDjgZXjgYTjgIIKCiMjIOaOoue0oueahOODh+ODvOOCv+ino+aekOOAgEV4cGxvcmF0b3J5IERhdGEgQW5hbHlzaXMgKEVEQSkKCiMjIyDmjqLntKLnmoTjg4fjg7zjgr/op6PmnpDjgajjga/vvJ8gKFtQb3NpdCBQcmltZXJzXShodHRwczovL3Bvc2l0LmNsb3VkL2xlYXJuL3ByaW1lcnMvMy4xKSkKCjEuIEVEQeOBr+OAgeODh+ODvOOCv+OBjOS9leOCkuiqnuOBo+OBpuOBhOOCi+OBi+OCkueQhuino+OBmeOCi+OBn+OCgeOBruWPjeW+qeeahOOBquOCteOCpOOCr+ODq+OBp+OBmeOAggoKMi4g44G+44Ga44CB44OH44O844K/44Gr6Zai44GZ44KL5ZWP44GE44KS5L2c5oiQ44GX44G+44GZ44CCCgozLiDjg4fjg7zjgr/jga7lj6/oppbljJbjgIHlpInmj5vjgIHjg6Ljg4fjg6rjg7PjgrDjgpLooYzjgYTjgIHnrZTjgYjjgpLmjqLjgZfjgb7jgZnjgIIKCuWtpue/kuOBl+OBn+OBk+OBqOOCkua0u+eUqOOBl+OBpuOAgeWVj+OBhOOCkuS/ruato+OBl+OBn+OCiuOAgeaWsOOBl+OBhOWVj+OBhOOCkuiAg+OBiOOBn+OCiuOBl+OBvuOBmeOAguOBneOBl+OBpuOAgeOBk+OBruOCteOCpOOCr+ODq+OCkue5sOOCiui/lOOBl+OBpuOBhOOBjeOBvuOBmeOAggoKRURB44Gv44OH44O844K/5YiG5p6Q44Gr44GK44GE44Gm6YeN6KaB44Gq5b255Ymy44KS5p6c44Gf44GX44G+44GZ44CC44G+44Gf44CB44OH44O844K/44Gu5ZOB6LOq44KS5L+d6Ki844GZ44KL44Gf44KB44Gr44CB44OH44O844K/44Gu6LOq44KS56K66KqN44GZ44KL44Gf44KB44Gr5L2/55So44GZ44KL44GT44Go44KC44Gn44GN44G+44GZ44CCCgohW1I0RFMg44GL44KJ44Gu44Kk44Oh44O844K4XShkYXRhL2RhdGEtc2NpZW5jZS5wbmcpCgojIyMg44OH44O844K/44Gu5Y+W5b6X44O76Kqt44G/6L6844G/IC0gSW1wb3J0aW5nIERhdGEKCuOCueOCv+ODvOODiOOBr+OAgeacrOadpeOBr+OAgeODh+ODvOOCv+OBruS9nOaIkOODu+aOoue0ouOBp+OBmeOBjOOAgeOBmeOBp+OBq+OAgeWIhuaekOOBl+OBn+OBhOODh+ODvOOCv+OBr+OBmeOBp+OBq+OBguOCi+OBqOOBl+OBpuipseOCkumAsuOCgeOBvuOBmeOAguOBvuOBmuOBr+OAgWBkYXRhYCDjg5Xjgqnjg6vjg4DvvIhkaXJlY3RvcnnvvInjgpLkvZzmiJDjgZfjgabjgYrjgY/jgajoia/jgYTjgILlj7PkuIvjga7nqpPmnqDjga4gRmlsZXMg44K/44OW44GL44KJ44CBTmV3IEZvbGRlciDjgafkvZzmiJDjgZfjgabjgoLjgojjgYTjgIIKCmBgYHtyIGV2YWw9RkFMU0V9CmRpci5jcmVhdGUoIi4vZGF0YSIpCmBgYAoKCuODh+ODvOOCv+OBruWPluW+l+ODu+iqreOBv+i+vOOBv+OCkuOAgeWbm+OBpOOBruaWueazleOBq+WIhuOBkeOBpuiqrOaYjuOBl+OBvuOBmeOAggoKMS4g44OR44OD44Kx44O844K444Gu5Yip55SoCiAgLSDkvovvvJpXREkg44Gq44Gp44CC5L2V5bqm44KC44CB44OA44Km44Oz44Ot44O844OJ44GX44Gq44GP44Gm6Imv44GE44KI44GE44Gr44CB5pu444GN5Ye644GX44Gm44GK44GN44CBMiDjgpLkvb/jgYbjgajjgojjgYTjgIJgd3JpdGUoZGZfbmFtZSwgIi4vZGF0YS9uYW1lLmNzdiIpYAoyLiDjgrPjg7Pjg5Tjg6Xjg7zjgr/kuIrjgavjgYLjgosgQ1NWIOOBquOBqeOBruODhuOCreOCueODiOODleOCoeOCpOODq+OCkuiqreOBv+i+vOOCgAogIC0g5L6L77yaYGRmX25hbWUgPC0gcmVhZF9jc3YoIi4vZGF0YS9maWxlX25hbWUuY3N2IilgCjMuIOOCpOODs+OCv+ODvOODjeODg+ODiOS4iuOBruODh+ODvOOCv+OBruOCouODieODrOOCue+8iFVSTO+8ieOCkuS9v+OBo+OBpuOAgUNTViDjgarjganjga7jg4bjgq3jgrnjg4jjg5XjgqHjgqTjg6vjgpLoqq3jgb/ovrzjgoDjgIIKICAtIOS+i++8mmBkZl9uYW1lIDwtIHJlYWRfY3N2KHVybF9vZl9hX2NzdilgCjQuIOOCs+ODs+ODlOODpeODvOOCv+S4iuOBq+OBguOCi+OAgUV4Y2VsIOODleOCoeOCpOODq+OBquOBqeOBruODh+OCuOOCv+ODq+ODleOCoeOCpOODq+OCkuiqreOBv+i+vOOCgOOAguOBvuOBmuOAgWBsaWJyYXJ5KHJlYWR4bClg44CCCiAgLSDkvovvvJpgZGZfbmFtZSA8LSByZWFkX2V4Y2VsKCIuL2RhdGEvZmlsZV9uYW1lLnhsc3giKWAKNS4g44K144Kk44OI44GL44KJ44OA44Km44Oz44Ot44O844OJ44GX44Gm44CBUHJvamVjdCDjga7jg4fjg7zjgr/jg5Xjgqnjg6vjg4Djgavnp7vjgZnjgILjgb7jgZ/jga/jgIHjg4fjg7zjgr/jga7jgqLjg4njg6zjgrnvvIhVUkzvvInjgYzjgo/jgYvjgaPjgabjgYTjgozjgbDjgIHnm7TmjqXjg4Djgqbjg7Pjg63jg7zjg4njgIIKICAtIOS+i++8mmBkb3dubG9hZC5maWxlKHVybF9vZl9hX2RhdGEsIGRlc3RmaWxlID0gIi4vZGF0YS9kYXRhX25hbWUiKQo2LiDjgq/jg6rjg4Pjg5fjg5zjg7zjg4njgavjgrPjg5Tjg7zjgZfjgaboqq3jgb/ovrzjgoDjgIIKICAtIOS+i++8mmBkZl9uYW1lIDwtIHJlYWRfZGVsaW0oY2xpcGJvYXJkKCkpYAoKIyMjIGBXREljYWNoZSgpYCDjga7mibHjgYQKCuS6jOOBpOOBruOAgeODleOCoeOCpOODq+OBjOS4gOOBpOOBq+OBquOBo+OBn+OAgeODquOCueODiOOBp+OBguOCi+OBn+OCgeOAgemBleOBo+OBpuWRveS7pOOCkuS9v+OBhOOBvuOBmeOAggoKYGBge3J9CndkaV9jYWNoZSA8LSBXREljYWNoZSgpCndyaXRlX3Jkcyh3ZGlfY2FjaGUsICIuL2RhdGEvd2RpX2NhY2hlLlJEYXRhIikKYGBgCgpgYGB7cn0Kd2RpX2NhY2hlIDwtIHJlYWRfcmRzKCIuL2RhdGEvd2RpX2NhY2hlLlJEYXRhIikKYGBgCgojIyMg5Zu96Zqb5qmf6Zai44Gu44OH44O844K/IEludGVybmF0aW9uYWwgSW5zdGl0dXRpb25zJyBEYXRhCgotIFdvcmxkIEJhbms6IGh0dHBzOi8vZGF0YS53b3JsZGJhbmsub3JnCi0gVU4gRGF0YTogaHR0cHM6Ly9kYXRhLnVuLm9yZwotIE9FQ0Q6IGh0dHBzOi8vZGF0YS5vZWNkLm9yZy8KCmBgYHtyfQp1cmxfdW5fcG9wIDwtICJodHRwczovL2RhdGEudW4ub3JnL19Eb2NzL1NZQi9DU1YvU1lCNjVfMV8yMDIyMDlfUG9wdWxhdGlvbiwlMjBTdXJmYWNlJTIwQXJlYSUyMGFuZCUyMERlbnNpdHkuY3N2IgpkZl91bl9wb3AwIDwtIHJlYWRfY3N2KHVybF91bl9wb3ApCmRmX3VuX3BvcDAKYGBgCgpgYGB7cn0KdXJsX3VuX3BvcCA8LSAiaHR0cHM6Ly9kYXRhLnVuLm9yZy9fRG9jcy9TWUIvQ1NWL1NZQjY1XzFfMjAyMjA5X1BvcHVsYXRpb24sJTIwU3VyZmFjZSUyMEFyZWElMjBhbmQlMjBEZW5zaXR5LmNzdiIKZGZfdW5fcG9wIDwtIHJlYWRfY3N2KHVybF91bl9wb3AsIHNraXA9MSkKZGZfdW5fcG9wCmBgYAoKYGBge3J9CmRmX3VuX3BvcCAlPiUgZGlzdGluY3QoYFJlZ2lvbi9Db3VudHJ5L0FyZWFgLCBgLi4uMmApCmBgYAoKCmBgYHtyfQpkZl91bl9wb3AgJT4lIGZpbHRlcihgUmVnaW9uL0NvdW50cnkvQXJlYWAgJWluJSBjKDIsMTksMTQyLDE1MCw5KSwgU2VyaWVzID09ICJQb3B1bGF0aW9uIG1pZC15ZWFyIGVzdGltYXRlcyAobWlsbGlvbnMpIikgJT4lCiAgZ2dwbG90KGFlcyhZZWFyLCBWYWx1ZSwgZmlsbCA9IGAuLi4yYCkpICsgZ2VvbV9hcmVhKGNvbD0iYmxhY2siKSArCiAgbGFicyh0aXRsZSA9ICJQb3B1bGF0aW9uIG1pZC15ZWFyIGVzdGltYXRlcyAobWlsbGlvbnMpIG9mIHRoZSBXb3JsZCIpCmBgYAoKCgojIERBWSAz77yaMuaciDI05pelCgojIyBPRUNEIGRhdGEKCi0gaHR0cHM6Ly9kYXRhLm9lY2Qub3JnLwoKIyMjIOS+i++8muWKtOWDjeaZgumWk+W9k+OBn+OCikdEUAoKLSBb5pel5pys44Gu5pmC6ZaT5b2T44Gf44KK55Sf55Sj5oCn44GvT0VDRDM444Kr5Zu95LitMjfkvY3vvIjml6XmnKznlJ/nlKPmgKfmnKzpg6jjgIzlirTlg43nlJ/nlKPmgKfjga7lm73pmpvmr5TovIPjgI3vvIldKGh0dHBzOi8vd3d3LmpjY2kub3IuanAvbmV3cy90cmVuZC1ib3gvMjAyMi8xMjE5MTU0NzEzLmh0bWwpCiAgLSBb5Yq05YON55Sf55Sj5oCn44Gu5Zu96Zqb5q+U6LyDMjAyMl0oaHR0cHM6Ly93d3cuanBjLW5ldC5qcC9yZXNlYXJjaC9kZXRhaWwvMDA2MTc0Lmh0bWwpCi0gW1Byb2R1Y3Rpdml0eSBzdGF0aXN0aWNzXShodHRwczovL3d3dy5vZWNkLm9yZy9zZGQvcHJvZHVjdGl2aXR5LXN0YXRzLykKICAtIFtSZWFkIE1vcmU6IEltcHJvdmluZyBQcm9kdWN0aXZpdHkgTWVhc3VyZW1lbnQgUHJhY3RpY2VzXShodHRwczovL3d3dy5vZWNkLm9yZy9zZGQvcHJvZHVjdGl2aXR5LXN0YXRzL2ltcHJvdmluZy1wcm9kdWN0aXZpdHktbWVhc3VyZW1lbnQtcHJhY3RpY2VzLmh0bSkKICAgIC0gW0xldmVsIG9mIEdEUCBwZXIgY2FwaXRhIGFuZCBwcm9kdWN0aXZpdHldKGh0dHBzOi8vc3RhdHMub2VjZC5vcmcvSW5kZXguYXNweD9EYXRhU2V0Q29kZT1QREJfTFYpCiAgICAtIFtHRFAgcGVyIGhvdXIgd29ya2VkXShodHRwczovL2RhdGEub2VjZC5vcmcvbHByZHR5L2dkcC1wZXItaG91ci13b3JrZWQuaHRtI2luZGljYXRvci1jaGFydCkKICAgIAoKKipEZWZpbml0aW9uIG9mIEdEUCBwZXIgaG91ciB3b3JrZWQqKgoKR0RQIHBlciBob3VyIHdvcmtlZCBpcyBhIG1lYXN1cmUgb2YgbGFib3VyIHByb2R1Y3Rpdml0eS4gSXQgbWVhc3VyZXMgaG93IGVmZmljaWVudGx5IGxhYm91ciBpbnB1dCBpcyBjb21iaW5lZCB3aXRoIG90aGVyIGZhY3RvcnMgb2YgcHJvZHVjdGlvbiBhbmQgdXNlZCBpbiB0aGUgcHJvZHVjdGlvbiBwcm9jZXNzLiBMYWJvdXIgaW5wdXQgaXMgZGVmaW5lZCBhcyB0b3RhbCBob3VycyB3b3JrZWQgb2YgYWxsIHBlcnNvbnMgZW5nYWdlZCBpbiBwcm9kdWN0aW9uLiBMYWJvdXIgcHJvZHVjdGl2aXR5IG9ubHkgcGFydGlhbGx5IHJlZmxlY3RzIHRoZSBwcm9kdWN0aXZpdHkgb2YgbGFib3VyIGluIHRlcm1zIG9mIHRoZSBwZXJzb25hbCBjYXBhY2l0aWVzIG9mIHdvcmtlcnMgb3IgdGhlIGludGVuc2l0eSBvZiB0aGVpciBlZmZvcnQuIFRoZSByYXRpbyBiZXR3ZWVuIHRoZSBvdXRwdXQgbWVhc3VyZSBhbmQgdGhlIGxhYm91ciBpbnB1dCBkZXBlbmRzIHRvIGEgbGFyZ2UgZGVncmVlIG9uIHRoZSBwcmVzZW5jZSBhbmQvb3IgdXNlIG9mIG90aGVyIGlucHV0cyAoZS5nLiBjYXBpdGFsLCBpbnRlcm1lZGlhdGUgaW5wdXRzLCB0ZWNobmljYWwsIG9yZ2FuaXNhdGlvbmFsIGFuZCBlZmZpY2llbmN5IGNoYW5nZSwgZWNvbm9taWVzIG9mIHNjYWxlKS4gVGhpcyBpbmRpY2F0b3IgaXMgbWVhc3VyZWQgaW4gVVNEIChjb25zdGFudCBwcmljZXMgMjAxMCBhbmQgUFBQcykgYW5kIGluZGljZXMuCgrlirTlg43mmYLplpPlvZPjgZ/jgopHRFDjga/jgIHlirTlg43nlJ/nlKPmgKfjga7mjIfmqJnjgafjgYLjgovjgILjgZPjgozjga/jgIHlirTlg43mipXlhaXph4/jgYzku5bjga7nlJ/nlKPopoHntKDjgajntYTjgb/lkIjjgo/jgZXjgozjgIHnlJ/nlKPjg5fjg63jgrvjgrnjgafjganjgozjgaDjgZHlirnnjofnmoTjgavliKnnlKjjgZXjgozjgZ/jgYvjgpLmuKzlrprjgZnjgovjgoLjga7jgafjgYLjgovjgILlirTlg43mipXlhaXph4/jga/jgIHnlJ/nlKPjgavlvpPkuovjgZnjgovjgZnjgbnjgabjga7kurrjga7nt4/lirTlg43mmYLplpPjgajjgZfjgablrprnvqnjgZXjgozjgovjgILlirTlg43nlJ/nlKPmgKfjga/jgIHlirTlg43ogIXjga7lgIvkurrnmoTog73lipvjgoTliqrlipvjga7lvLfjgZXjgajjgYTjgaPjgZ/lirTlg43jga7nlJ/nlKPmgKfjgpLpg6jliIbnmoTjgavjgZfjgYvlj43mmKDjgZfjgabjgYTjgarjgYTjgILjgqLjgqbjg4jjg5fjg4Pjg4jmjIfmqJnjgajlirTlg43mipXlhaXph4/jga7mr5Tnjofjga/jgIHku5bjga7mipXlhaXnianvvIjos4fmnKzjgIHkuK3plpPmipXlhaXnianjgIHmioDooZPjg7vntYTnuZTjg7vlirnnjofjga7lpInljJbjgIHopo/mqKHjga7ntYzmuIjjgarjganvvInjga7lrZjlnKjjgoTliKnnlKjjgavlpKfjgY3jgY/lt6blj7PjgZXjgozjgovjgILjgZPjga7mjIfmqJnjga/jgIHnsbPjg4njg6vvvIgyMDEw5bm044Gu5oGS5bi45L6h5qC844GK44KI44GzUFBQ77yJ44GK44KI44Gz5oyH5qiZ44Gn5ris5a6a44GV44KM44Gm44GE44G+44GZ44CCCgojIyMjIOacgOWIneOBruOCueODhuODg+ODlyB7LX0KCjEuIFvjgrXjgqTjg4hdKGh0dHBzOi8vZGF0YS5vZWNkLm9yZy9scHJkdHkvZ2RwLXBlci1ob3VyLXdvcmtlZC5odG0jaW5kaWNhdG9yLWNoYXJ0KeOBi+OCieOAgUNTViDjg4fjg7zjgr/jgpLjg4Djgqbjg7Pjg63jg7zjg4njgIIKMi4g44OX44Ot44K444Kn44Kv44OI5YaF44Gu44OH44O844K/5qC857SN44OV44Kp44Or44OA44Gr5YWl44KM44G+44GZ44CCIi4vZGF0YS8iCjMuIOiqreOBv+i+vOOBv+OBvuOBmeOAggoK5LiK44GuW+OCteOCpOODiF0oaHR0cHM6Ly9kYXRhLm9lY2Qub3JnL2xwcmR0eS9nZHAtcGVyLWhvdXItd29ya2VkLmh0bSNpbmRpY2F0b3ItY2hhcnQp44GL44KJ44OH44O844K/77yIRnVsbCBpbmRpY2F0b3IgZGF0Ye+8ieOCkuODgOOCpuODs+ODreODvOODieOBl+OBpuOAgeODl+ODreOCuOOCp+OCr+ODiOOBriBkYXRhIOODleOCqeODq+ODgOODvOOBq+WFpeOCjOOBvuOBl+OBn+OAggoKYGBge3J9CmRmX29lY2RfcHJvZHVjdGl2aXR5IDwtIHJlYWRfY3N2KCIuL2RhdGEvRFBfTElWRV8yMTAyMjAyMzExMTcxMjA2NS5jc3YiKQpkZl9vZWNkX3Byb2R1Y3Rpdml0eQpgYGAKCiMjIyDjg4fjg7zjgr/jga7norroqo0gey19CgrliJflkI3jgpLnorroqo3jgZfjgIHliJfjgZTjgajjgavjgIHjg4fjg7zjgr/jgpLnorroqo0KCmBgYHtyfQpjb2xuYW1lcyhkZl9vZWNkX3Byb2R1Y3Rpdml0eSkKYGBgCgpgdW5pcXVlKClgIOOBruOBi+OBo+OBk+OBruS4reOBq+OAgWBkZl9vZWNkX3Byb2R1Y3Rpdml0eSRMT0NBVElPTmAg44KS5YWl44KM44Gf44KC44Gu44Go5ZCM44GY44KC44Gu44KS5Ye65Yqb44GX44G+44GZ44CC5qyh44CF44Go44Gk44Gl44GR44KL44Go44GN44Gr5L6/5Yip44Gq44Gu44Gn44CB44GT44Gu44OR44Kk44OXIGAlPiVgIOOCkuOCj+OBn+OBl+OBr+OCiOOBj+S9v+OBhOOBvuOBmeOAgmB1bmlxdWUoZGZfb2VjZF9wcm9kdWN0aXZpdHkkTE9DQVRJT04pYCDjgoLoqabjgZfjgabjgb/jgabjgY/jgaDjgZXjgYTjgIIKCgpgYGB7cn0KZGZfb2VjZF9wcm9kdWN0aXZpdHkkTE9DQVRJT04gJT4lIHVuaXF1ZSgpCmBgYApgYGB7cn0KZGZfb2VjZF9wcm9kdWN0aXZpdHkkSU5ESUNBVE9SICU+JSB1bmlxdWUoKQpgYGAKCmBgYHtyfQpkZl9vZWNkX3Byb2R1Y3Rpdml0eSRTVUJKRUNUICU+JSB1bmlxdWUoKQpgYGAKCmBgYHtyfQpkZl9vZWNkX3Byb2R1Y3Rpdml0eSRNRUFTVVJFICU+JSB1bmlxdWUoKQpgYGAKCmBgYHtyfQpkZl9vZWNkX3Byb2R1Y3Rpdml0eSRGUkVRVUVOQ1kgJT4lIHVuaXF1ZSgpCmBgYAoKYGBge3J9CmRmX29lY2RfcHJvZHVjdGl2aXR5JFRJTUUgJT4lIHVuaXF1ZSgpCmBgYAoKYGBge3J9CmRmX29lY2RfcHJvZHVjdGl2aXR5ICU+JSAKICBmaWx0ZXIoTUVBU1VSRSA9PSAiVVNEIiwgVElNRSA9PSAyMDIxKSAlPiUgIyBmaWx0ZXJpbmcgcm93cyB3aXRoIGNvbmRpdGlvbnMKICBzZWxlY3QoTE9DQVRJT04sIFZhbHVlKSAlPiUgIyBzZWxlY3RpbmcgY29sdW1ucwogIGFycmFuZ2UoZGVzYyhWYWx1ZSkpICMgb3JkZXJpbmcgdGhlIHJvd3MgaW4gdGhlIGRlc2NlbnRpbmcgb3JkZXIgb2YgdGhlIGNvbHVtbiBWYWx1ZQpgYGAKCiMjIyMg44GE44GP44Gk44GL44Gu5Zyw5Z+f44KS6YG444KT44Gn44CB5oqY57ea44Kw44Op44OV44KS5pu444GE44Gm44G/44KL44CCey19CgrvvJPooYznm67jgYzjgarjgYTjgajjganjgYbjgarjgorjgb7jgZnjgYvjgIIKCmBgYHtyfQpkZl9vZWNkX3Byb2R1Y3Rpdml0eSAlPiUgCiAgZmlsdGVyKExPQ0FUSU9OICVpbiUgYygiSlBOIiwgIk9FQ0QiLCAiRy03IiwgIkVVMjgiKSkgJT4lCiAgZmlsdGVyKE1FQVNVUkUgPT0gIlVTRCIpICU+JSAjIHNhbWUgYXMgYWJvdmUgdXAgdG8gdGhpcyBsaW5lCiAgZ2dwbG90KGFlcyh4ID0gVElNRSwgeSA9IFZhbHVlLCBjb2wgPSBMT0NBVElPTikpICsgZ2VvbV9saW5lKCkgKyAKICBsYWJzKHRpdGxlPSJHRFAgcGVyIGhvdXIgd29ya2VkIiwgIyBhZGRpbmcgdGhlIHRpdGxlIGFuZCB0aGUgc3VidGl0bGUKICAgICAgIHN1YnRpdGxlPSJUb3RhbCwgMjAxNT0xMDAsIDIwMjEgb3IgbGF0ZXN0IGF2YWlsYWJsZSIpCmBgYAoKCiMjIyDnt7Tnv5LvvJrmlZnogrIgRWR1Y2F0aW9uCgrmiJDkurrjga7mlZnogrLjg6zjg5njg6vjgavplqLjgZnjgovjgIHmrKHjga7jgrXjgqTjg4jjgYvjgonjg4fjg7zjgr/jgpLjgajjgaPjgabjgIHoqr/jgbnjgabjgb/jgabjgY/jgaDjgZXjgYTjgIIKCkFkdWx0IGVkdWNhdGlvbiBsZXZlbDogaHR0cHM6Ly9kYXRhLm9lY2Qub3JnL2VkdWF0dC9hZHVsdC1lZHVjYXRpb24tbGV2ZWwuaHRtCgrjg4Djgqbjg7Pjg63jg7zjg4njgZfjgZ/jg5XjgqHjgqTjg6vjga7jg5XjgqHjgqTjg6vlkI3jgYwgYERQX0xJVkVfMjEwMjIwMjMxMjAxMzI2NTQuY3N2YCDjgajlkIzjgZjjgafjgYLjgovjgZPjgajjgpLnorroqo3jgZfjgabjgY/jgaDjgZXjgYTjgIIKCmBgYHtyIGV2YWw9RkFMU0V9CmRmX29lY2RfZWR1Y2F0aW9uX2xldmVsIDwtIHJlYWRfY3N2KCIuL2RhdGEvRFBfTElWRV8yMTAyMjAyMzEyMDEzMjY1NC5jc3YiKQpkZl9vZWNkX2VkdWNhdGlvbl9sZXZlbApgYGAKCuS4iuOBruWKtOWDjeaZgumWk+W9k+OBn+OCikdEUOOBruS+i+OBq+e/kuOBo+OBpuOAgeODh+ODvOOCv+OCkuiqv+OBueOBpuOBv+OBpuOBj+OBoOOBleOBhOOAggoKYGBge3J9CmNvbG5hbWVzKGRmX29lY2RfZWR1Y2F0aW9uX2xldmVsKQpgYGAKCgpgYGB7cn0KZGZfb2VjZF9lZHVjYXRpb25fbGV2ZWwkU1VCSkVDVCAlPiUgdW5pcXVlKCkKYGBgCgrjgZPjgozjgonjga/jgIHkvZXjgpLmhI/lkbPjgZfjgabjgYTjgovjga7jgafjgZfjgofjgYbjgYvjgILjgrXjgqTjg4jjga4gUGVyc3BlY3RpdmVzIOOBquOBqeOCkuOBv+OBpuOBj+OBoOOBleOBhOOAggoK5LuW44Gu5YiX77yI5aSJ5pWw77yJ44Gv44CB44Gp44GG44Gn44GX44KH44GG44GL44CC44Kz44O844OJ44OB44Oj44Oz44Kv44KS5oy/5YWl44GX44Gm44CB6Kq/44G544Gm44G/44Gm44GP44Gg44GV44GE44CCCgrlirTlg43mmYLplpPlvZPjgZ/jgopHRFDjga7kvovjga7nnJ/kvLzjgpLjgZfjgabjgIHjgrDjg6njg5XjgpLmm7jjgYTjgabjgb/jgb7jgZfjgZ/jgIIKCmBgYHtyfQpkZl9vZWNkX2VkdWNhdGlvbl9sZXZlbCAlPiUgCiAgZmlsdGVyKExPQ0FUSU9OICVpbiUgYygiSlBOIiwgIk9FQ0QiLCAiRy03IiwgIkVVMjgiKSkgJT4lCiAgZ2dwbG90KGFlcyhUSU1FLCBWYWx1ZSwgbGluZXR5cGUgPSBTVUJKRUNULCBjb2wgPSBMT0NBVElPTikpICsgZ2VvbV9saW5lKCkgKyAKICBsYWJzKHRpdGxlPSJBZHVsdCBlZHVjYXRpb24gbGV2ZWwiKQpgYGAKCuOBquOBq+OBi+ePvuOCjOOBvuOBl+OBn+OBjOOAgeWbveOCguOAgVNVQkpFQ1Qg44KC5pyf5b6F44GX44Gf44KC44Gu44Gv54++44KM44Gm44GE44G+44Gb44KT44CC44Gq44Gr44GM5ZWP6aGM44Gq44Gu44Gn44GX44KH44GG44CCCgrmsJfjgaXjgYTjgabjgZ/jgZPjgajjgpLmm7jjgY3lh7rjgZfjgabjgb/jgb7jgZfjgofjgYbjgIIKCiMjIEV4Y2VsIERhdGEg44Gu6Kqt44G/6L6844G/CgpgcmVhZHhsYCDjg5Hjg4PjgrHjg7zjgrjjgpLkvb/jgYTjgb7jgZnjgILjgZPjgozjga/jgIFgdGlkeXZlcnNlYCDjgpLjgqTjg7Pjgrnjg4jjg7zjg6vjgZnjgovjgajjgY3jgavjgIHlkIzmmYLjgavjgIHjgqTjg7Pjgrnjg4jjg7zjg6vjgZXjgozjgb7jgZnjgYvjgonjgIHjgqTjg7Pjgrnjg4jjg7zjg6vjga/lv4XopoHjgYLjgorjgb7jgZvjgpPjgYzjgIFgdGlkeXZlcnNlYCDjgrDjg6vjg7zjg5fjga7kuLvjgZ/jgovjg5Hjg4PjgrHjg7zjgrjjga/jgarjgYTjga7jgafjgIHjg63jg7zjg4njga/jgZXjgozjgabjgYTjgarjgYTjga7jgafjgIHkvb/jgYbjgajjgY3jgavjgIHjg63jg7zjg4njgZnjgovlv4XopoHjgYzjgYLjgorjgb7jgZnjgIIKCmBgYHtyfQpsaWJyYXJ5KHJlYWR4bCkgIyBuZWVkIHRvIGxvYWQgdGhvdWdoIHJlYWR4bCBpcyBhIHBhcnQgb2YgdGhlIHRpZHl2ZXJzZSBwYWNrYWdlIGFuZCBpbnN0YWxsZWQKYGBgCgrlrp/jga/jgIHnr4Tlm7LjgpLpgbjmip7jgZfjgIHjgrPjg5Tjg7zjgpLjgZfjgIHjgq/jg6rjg4Pjg5fjg5zjg7zjg4njgYvjgonoqq3jgoDmlrnms5XjgoLjgYLjgorjgb7jgZnjgYzjgIHkuozjgaTjga7lpKfjgY3jgarnkIbnlLHjgYvjgonmjqjlpajjgZfjgb7jgZvjgpPjgILkuIHlr6fjgavjgIHmlrnms5XjgpLoqJjov7DjgZfjgarjgYTjgajjgIHlho3nj77mgKfjgavllY/poYzjgYzjgYLjgovjgZPjgajjgIHliJfjga7jg4fjg7zjgr/jg7vjgr/jgqTjg5fjgarjganjgYzjgIHpganliIfjgavjgIHoqq3jgb/ovrzjgoHjgarjgYTloLTlkIjjgYzlpJrjgY/jgIHoqq3jgb/ovrzjgpPjgafjgYvjgonjga7kvZzmpa3jgYzopIfpm5HjgavjgarjgovjgILjgajjgaPjgabjgoLjgIHlsI/jgZXjgarjgIHoh6rliIbjgafkvZzmiJDjgZfjgZ/jg4fjg7zjgr/jga7loLTlkIjjgavjga/jgIHmnInlirnjgYvjgoLjgZfjgozjgb7jgZvjgpPjgIIKCmBgYHtyIGV2YWw9RkFMU0V9CmRmX2V4Y2VsX2NsaXBib2FyZCA8LSByZWFkX2RlbGltKGNsaXBib2FyZCgpKQpgYGAKCgojIyMg5L6LOiDkuJbnlYzjga7lh7rnlJ/njofvvIhGZXJ0aWxpdHnvvIkgVU4gRGF0YQoK44Ob44OD44OI44Gq44OI44OU44OD44Kv44Gn44GZ44Gt44CC5pel5pys44Gu5ZWP6aGM44CB44Gd44GX44Gm44CB6Ieq5YiG44GU44Go44Go44GX44Gm44Gg44GR44Gn44Gq44GP44CB5LiW55WM44Gu54q25rOB44KS6KaL44KL6KaW54K544KC5oyB44Gh44G+44GX44KH44GG44CCCgpbVU4gZGF0YV0oaHR0cHM6Ly9kYXRhLnVuLm9yZy8pIOOBi+OCieOAgeaknOe0oueqk+OBruS4iuOBq+OBguOCi+OAgVtEYXRhbWFydHNdKGh0dHA6Ly9kYXRhLnVuLm9yZy9FeHBsb3Jlci5hc3B4KSDjgpLpgbjmip7jgZfjgIHkuIvjga7jgbvjgYbjgavjgYLjgovjgIFXb3JsZCBGZXJ0aWxpdHkgRGF0YSBVbml0ZWQgTmF0aW9ucyBQb3B1bGF0aW9uIERpdmlzaW9uIChVTlBEKSDjga4gWytdIOiomOWPt+OCkumWi+OBjeOBvuOBmeOAguWPs+OBriBbaV0g44GL44KJ44Gv5oOF5aCx44GM5b6X44KJ44KM44G+44GZ44CC5LiJ44Gk44Gu44OH44O844K/44GM44GC44KK44G+44GZ44CCCgoqIFtBZ2Utc3BlY2lmaWMgZmVydGlsaXR5IHJhdGVzLCBUb3RhbCBmZXJ0aWxpdHkgYW5kIE1lYW4gYWdlIGF0IGNoaWxkYmVhcmluZ10oaHR0cDovL2RhdGEudW4ub3JnL0RvY3VtZW50RGF0YS5hc3B4P2lkPTMxOSkKKiBbQW5udWFsIG51bWJlciBvZiBsaXZlIGJpcnRocyBhbmQgQ3J1ZGUgYmlydGggcmF0ZV0oaHR0cDovL2RhdGEudW4ub3JnL0RvY3VtZW50RGF0YS5hc3B4P2lkPTMxNikKKiBbQ2hpbGRyZW4gZXZlciBib3JuXShodHRwOi8vZGF0YS51bi5vcmcvRG9jdW1lbnREYXRhLmFzcHg/aWQ9MzE4KQoK44G+44Ga44Gv44CBIkFnZS1zcGVjaWZpYyBmZXJ0aWxpdHkgcmF0ZXMsIFRvdGFsIGZlcnRpbGl0eSBhbmQgTWVhbiBhZ2UgYXQgY2hpbGRiZWFyaW5nIiDjg4fjg7zjgr/jgpLkvb/jgYbjgZPjgajjgavjgZfjgb7jgZnjgIIKCjEuIOOCteOCpOODiOOBi+OCieOAgUV4Y2VsIOODh+ODvOOCv+OCkuODgOOCpuODs+ODreODvOODieOAggoyLiDjg5fjg63jgrjjgqfjgq/jg4jlhoXjga7jg4fjg7zjgr/moLzntI3jg5Xjgqnjg6vjg4DjgavlhaXjgozjgb7jgZnjgIIiLi9kYXRhLyIKMy4g6Kmm44GX44Gr44CB6Kqt44G/6L6844G/44G+44GZ44CCCjQuIEZpbGVzIOOBi+OCieOAgUltcG9ydCBEYXRhc2V0IOOCkumBuOaKnuOBl+OAgeioreWumuOCkuOBl+OBpuOAgeOCguOBhuS4gOW6puOAgeiqreOBv+i+vOOCgOOAggo1LiDliJflkI3jgpLkv67mraMKNi4g5pel5pys44Gu44OH44O844K/44KS56K66KqNCjcuIOW5tOm9ouOBlOOBqOOBruaVsOOCkuavlOi8g+OBl+OChOOBmeOBhOOCiOOBhuOBq+OAgeODh+ODvOOCv+OCkuWkieW9ogo4LiDjgrDjg6njg5XjgpLmm7jjgYTjgabjgb/jgovjgIIKOS4g5Ye655Sf5bmz5Z2H5bm06b2i44Gu6KGo44KS6ZmN5bm06b2i6aCG44Gr6KaL44Gm44G/44KL44CCCjEwLiDlr4bluqbliIbluIPjgrDjg6njg5XjgpLmm7jjgYTjgabjgb/jgovjgIIKMTEuIOWHuueUn+eOh+OBruihqOOCkuaYh+mghuOBq+imi+OBpuOBv+OCi+OAggoxMi4g5a+G5bqm5YiG5biD44Kw44Op44OV44KS5pu444GE44Gm44G/44KL44CCCgojIyMjIFN0ZXBzIDEtMy4gey19CgoxLiDjgrXjgqTjg4jjgYvjgonjgIFFeGNlbCDjg4fjg7zjgr/jgpLjg4Djgqbjg7Pjg63jg7zjg4njgIIKMi4g44OX44Ot44K444Kn44Kv44OI5YaF44Gu44OH44O844K/5qC857SN44OV44Kp44Or44OA44Gr5YWl44KM44G+44GZ44CCIi4vZGF0YS8iIHstfQozLiDoqabjgZfjgavjgIHoqq3jgb/ovrzjgb/jgb7jgZnjgILjgrXjgqTjg4jjgYvjgonjgIFFeGNlbCDjg4fjg7zjgr/jgpLjg4Djgqbjg7Pjg63jg7zjg4njgIJ7LX0KCuOBqeOCk+OBquOCt+ODvOODiOOBjOOBguOCi+OBi+imi+OBpuOBv+OBvuOBl+OCh+OBhuOAguiqreOBv+i+vOOBv+OBq+WVj+mhjOOBjOOBguOCi+OBqOOBjeOBr+OAgeODh+ODvOOCv+WQjeOBi+OCieOCueODmuODvOOCueOCkua2iOOBl+OAgeS4i+OBruOCs+ODvOODieOCguS/ruato+OBl+OBpuiqreOCk+OBp+OBv+OBpuOBj+OBoOOBleOBhOOAguOCueODmuODvOOCueOBquOBqeOBjOOBguOCi+OBqOWVj+mhjOOBjOi1t+OBk+OCi+WgtOWQiOOBjOOBguOCiuOBvuOBmeOAggoKYGBge3J9CmV4Y2VsX3NoZWV0cygiLi9kYXRhL0FnZS1zcGVjaWZpYyBmZXJ0aWxpdHkgcmF0ZXMsIFRvdGFsIGZlcnRpbGl0eSBhbmQgLnhscyIpCmBgYAoK44K344O844OI44KS5oyH5a6a44GZ44KL44Go44GN44Gv44CBYHNoZWV0ID0gMWAg44Go44GL44CBYHNoZWV0ID0gIkNISUxEUkVOX0VWRVJfQk9STiJgIOOBqOOBl+OBvuOBmeOAggrmjIflrprjgYzjgarjgYTjgajjgY3jga/jgIHmnIDliJ3jga7jgrfjg7zjg4jjgILoqbPntLDjga/jgIFIZWxwIOOBp+OAgWByZWFkX2V4Y2VsYCDjgajjgZfjgabjgIHnorroqo3jgZfjgabjgY/jgaDjgZXjgYTjgILjgZ/jgY/jgZXjgpPjga7jgIHjgqrjg5fjgrfjg6fjg7PjgYzjgYLjgorjgb7jgZnjgIIKCmBgYHtyfQpkZl91bl9mZXJ0aWxpdHkgPC0gcmVhZF9leGNlbCgiLi9kYXRhL0FnZS1zcGVjaWZpYyBmZXJ0aWxpdHkgcmF0ZXMsIFRvdGFsIGZlcnRpbGl0eSBhbmQgLnhscyIpCmRmX3VuX2ZlcnRpbGl0eQpgYGAKCuani+mAoOOBjOikh+mbkeOBneOBhuOBp+OBmeOAggoKIyMjIyBTdGVwIDQuIEZpbGVzIOOBi+OCieOAgUltcG9ydCBEYXRhc2V0IOOCkumBuOaKnuOBl+OAgeioreWumuOCkuOBl+OBpuOAgeOCguOBhuS4gOW6puOAgeiqreOBv+i+vOOCgOOAgnstfQoK44OV44Kh44Kk44Or5ZCN44KC5aSJ5pu044GX44Gm44GK44GE44GM5pa544GM44KI44GE5aC05ZCI44KC44GC44KK44G+44GZ44CC44Gd44Gu44Go44GN44Gv44CB5aSJ5pu06KiY6Yyy44KSIFJOb3RlYm9va+OBq+i/veiomOOBl+OBpuOBiuOBj+OBqOiJr+OBhOOBp+OBl+OCh+OBhuOAguS4i+OBruS+i+OBp+OBr+OAgeS4iuOBru+8lOihjOOCkuOCueOCreODg+ODl+OAguWIl+OBjOOAgXRleHTvvIjmloflrZfvvIkg44GL44CBbnVtZXJpY++8iOaVsOWApO+8ieOBi+OCkumBuOaKnuOAguiqreOBv+i+vOOBvuOBquOBhOOBqOOBjeOBq+OBr+OAgXNraXAg44GX44Gm44GE44G+44GZ44CCCgkJCQpgYGB7ciB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpkZl91bl9mZXJ0aWxpdHkgPC0gcmVhZF9leGNlbCgiLi9kYXRhL0FnZS1zcGVjaWZpYyBmZXJ0aWxpdHkgcmF0ZXMsIFRvdGFsIGZlcnRpbGl0eSBhbmQgLnhscyIsIAogICAgY29sX3R5cGVzID0gYygidGV4dCIsICJudW1lcmljIiwgInRleHQiLCAKICAgICAgICAibnVtZXJpYyIsICJ0ZXh0IiwgIm51bWVyaWMiLCAibnVtZXJpYyIsIAogICAgICAgICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsIAogICAgICAgICJudW1lcmljIiwgIm51bWVyaWMiLCAibnVtZXJpYyIsIAogICAgICAgICJudW1lcmljIiwgInNraXAiLCAidGV4dCIsICJza2lwIiwgCiAgICAgICAgInNraXAiLCAic2tpcCIsICJza2lwIiwgInNraXAiLCAic2tpcCIpLCAKICAgIHNraXAgPSA0KQpgYGAKCgpgYGB7cn0KZGZfdW5fZmVydGlsaXR5CmBgYAoKIyMjIyBTdGVwIDUuIOWIl+WQjeOCkuS/ruatoyB7LX0KCuS/ruato+OBl+OBn+OBhOWIl+WQjeOCkuOCs+ODlOODvOOBl+OBpuOBiuOBj+OAggoKQ291bnRyeSwgSVNPIGNvZGUsIFBlcmlvZCwgUmVmZXJlbmNlLCBOQSwgVG90YWwgZmVydGlsaXR5Cgox5YiX55uu44GL44KJ44CBNuWIl+ebruOBqOOAgTE05YiX55uu44Go44CBMTXliJfnm67jgpLjgIHmm7jjgY3mj5vjgYjjgb7jgZnjgIIKCmBgYHtyfQpjb2xuYW1lcyhkZl91bl9mZXJ0aWxpdHkpW2MoMTo2LDE0OjE1KV0gPC0gYygiY291bnRyeSIsCSJpc28iLAkicGVyaW9kIiwieWVhciIsICJyYW5nZSIsCSJmZXJ0aWxpdHlfcmF0ZSIsIm1lYW5fYWdlIiwic291cmNlIikKZGZfdW5fZmVydGlsaXR5CmBgYAoKIyMjIyBTdGVwIDYuIOaXpeacrOOBruODh+ODvOOCv+OCkueiuuiqjSB7LX0KCgpgYGB7cn0KZGZfdW5fZmVydGlsaXR5X2pwIDwtIGRmX3VuX2ZlcnRpbGl0eSAlPiUgZmlsdGVyKGNvdW50cnkgPT0gIkphcGFuIikKZGZfdW5fZmVydGlsaXR5X2pwCmBgYAoKIyMjIyBTdGVwIDcuIOW5tOm9ouOBlOOBqOOBruaVsOOCkuavlOi8g+OBl+OChOOBmeOBhOOCiOOBhuOBq+OAgeODh+ODvOOCv+OCkuWkieW9oiB7LX0KCuOBmeOBk+OBl+OAgembo+OBl+OBhOOBp+OBmeOBjOOAgWBwaXZvdF9sb25nZXJgIOOCkiBIZWxwIOOBp+iqv+OBueOBpuOBj+OBoOOBleOBhOOAggoKYGBge3J9CmRmX3VuX2ZlcnRpbGl0eV9qcCAlPiUgcGl2b3RfbG9uZ2VyKC1jKDE6NiwgMTQ6MTUpLCBuYW1lc190byA9ICJhZ2VfcmFuZ2UiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKQpgYGAKCiMjIyMgU3RlcCA4LiDjgrDjg6njg5XjgpLmm7jjgYTjgabjgb/jgovjgIJ7LX0KCmBgYHtyfQpkZl91bl9mZXJ0aWxpdHlfanAgJT4lIHBpdm90X2xvbmdlcigtYygxOjYsIDE0OjE1KSwgbmFtZXNfdG8gPSAiYWdlX3JhbmdlIiwgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXIsIGNvbD1hZ2VfcmFuZ2UsIGxpbmV0eXBlID0gYWdlX3JhbmdlKSkgKyBnZW9tX2xpbmUoYWVzKHk9dmFsdWUpKSAKYGBgCgrjgYTjgo3jgYTjgo3jgarjgZPjgajjgYzjgo/jgYvjgorjgb7jgZnjgIIKCiMjIyMgU3RlcCA5LiDlh7rnlJ/lubPlnYflubTpvaLjga7ooajjgpLpmY3lubTpvaLpoIbjgavopovjgabjgb/jgovjgIJ7LX0KCmBgYHtyfQpkZl91bl9mZXJ0aWxpdHkgJT4lIAogIGZpbHRlcih5ZWFyICVpbiUgYygyMDEwKSkgJT4lIHNlbGVjdChjb3VudHJ5LCBtZWFuX2FnZSkgJT4lIAogIGRyb3BfbmEobWVhbl9hZ2UpICU+JQogIGFycmFuZ2UoZGVzYyhtZWFuX2FnZSkpCmBgYAoKIyMjIyBTdGVwIDEwLiDlr4bluqbliIbluIPjgrDjg6njg5XjgpLmm7jjgYTjgabjgb/jgovjgIJ7LX0KCmBgYHtyfQpkZl91bl9mZXJ0aWxpdHkgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygxOTcwLCAxOTkwLCAyMDEwKSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3BfbmEobWVhbl9hZ2UpICU+JQogIGdncGxvdChhZXMobWVhbl9hZ2UsIGZpbGwgPSBmYWN0b3IoeWVhcikpKSArIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSkgKyAKIyAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwojICBjb29yZF9jYXJ0ZXNpYW4oeGxpbT1jKDIwLDQwKSkgKyAKICBsYWJzKHRpdGxlPSJNZWFuIGFnZSBhdCBjaGlsZGJlYXJpbmciLCBmaWxsID0gInllYXIiKQpgYGAKYGBge3J9CmRmX3VuX2ZlcnRpbGl0eSAlPiUgZHJvcF9uYShtZWFuX2FnZSkgJT4lIGdyb3VwX2J5KHllYXIpICU+JSBzdW1tYXJpc2Uobj1uKCkpICU+JSBhcnJhbmdlKGRlc2MobikpCmBgYAoKCmBgYHtyfQpkZl91bl9mZXJ0aWxpdHkgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygxOTcwLCAxOTg1LCAxOTk1LCAyMDA1LCAyMDEwKSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3BfbmEobWVhbl9hZ2UpICU+JQogIGdncGxvdChhZXMobWVhbl9hZ2UsIGZpbGwgPSBmYWN0b3IoeWVhcikpKSArIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuMykgKyAKICBsYWJzKHRpdGxlPSJNZWFuIGFnZSBhdCBjaGlsZGJlYXJpbmciLCBmaWxsID0gInllYXIiKQpgYGAKYGBge3J9CmRmX3VuX2ZlcnRpbGl0eSAlPiUgZmlsdGVyKHllYXIgJWluJSBjKDE5NzAsIDE5ODUsMTk5NSwgMjAwNSwyMDEwKSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3BfbmEobWVhbl9hZ2UpICU+JQogIGdncGxvdChhZXMobWVhbl9hZ2UsIGZpbGwgPSBmYWN0b3IoeWVhcikpKSArIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSkgKyBmYWNldF93cmFwKH4gZmFjdG9yKHllYXIpKSArCiAgbGFicyh0aXRsZT0iTWVhbiBhZ2UgYXQgY2hpbGRiZWFyaW5nIiwgZmlsbCA9ICJ5ZWFyIikKYGBgCgojIyMjIDExLiDlh7rnlJ/njofjga7ooajjgpLmmIfpoIbjgavopovjgabjgb/jgovjgIJ7LX0KCmBgYHtyfQpkZl91bl9mZXJ0aWxpdHkgJT4lIAogIGZpbHRlcih5ZWFyICVpbiUgYygyMDEwKSkgJT4lIHNlbGVjdChjb3VudHJ5LCBmZXJ0aWxpdHlfcmF0ZSkgJT4lIAogIGRyb3BfbmEoZmVydGlsaXR5X3JhdGUpICU+JQogIGFycmFuZ2UoZmVydGlsaXR5X3JhdGUpCmBgYAoKIyMjIyBTdGVwIDEyLiDlr4bluqbliIbluIPjgrDjg6njg5XjgpLmm7jjgYTjgabjgb/jgovjgIJ7LX0KCmBgYHtyfQpkZl91bl9mZXJ0aWxpdHkgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygxOTcwLCAxOTkwLCAyMDEwKSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3BfbmEobWVhbl9hZ2UpICU+JQogIGdncGxvdChhZXMoZmVydGlsaXR5X3JhdGUsIGZpbGwgPSBmYWN0b3IoeWVhcikpKSArIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSkgKyAKICBsYWJzKHRpdGxlPSJUb3RhbCBmZXJ0aWxpdHkiLCBmaWxsID0gInllYXIiKQpgYGAKCmBgYHtyfQpkZl91bl9mZXJ0aWxpdHkgJT4lIGRyb3BfbmEoZmVydGlsaXR5X3JhdGUpICU+JSBncm91cF9ieSh5ZWFyKSAlPiUgc3VtbWFyaXNlKG49bigpKSAlPiUgYXJyYW5nZShkZXNjKG4pKQpgYGAKCmBgYHtyfQpkZl91bl9mZXJ0aWxpdHkgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygxOTcwLCAxOTg1LCAxOTk1LCAyMDA1LCAyMDEwKSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3BfbmEobWVhbl9hZ2UpICU+JQogIGdncGxvdChhZXMoZmVydGlsaXR5X3JhdGUsIGZpbGwgPSBmYWN0b3IoeWVhcikpKSArIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSkgKyAKICBsYWJzKHRpdGxlPSJUb3RhbCBmZXJ0aWxpdHkiLCBmaWxsID0gInllYXIiKQpgYGAKCmBgYHtyfQpkZl91bl9mZXJ0aWxpdHkgJT4lIGZpbHRlcih5ZWFyICVpbiUgYygxOTcwLCAxOTg1LCAxOTk1LCAyMDA1LCAyMDEwKSkgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyb3BfbmEobWVhbl9hZ2UpICU+JQogIGdncGxvdChhZXMoZmVydGlsaXR5X3JhdGUsIGZpbGwgPSBmYWN0b3IoeWVhcikpKSArIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSkgKyBmYWNldF93cmFwKH4gZmFjdG9yKHllYXIpKSArCiAgbGFicyh0aXRsZT0iVG90YWwgZmVydGlsaXR5IiwgZmlsbCA9ICJ5ZWFyIikKYGBgCgojIyMjIOWPguiAg+S+i++8ke+8mldvcmxkIEluZXF1YWxpdHkgUmVwb3J0IDIwMjIKCldJUjIwMjI6IGh0dHBzOi8vZHMtc2wuZ2l0aHViLmlvL2RhdGEtYW5hbHlzaXMvd2lyMjAyMi5uYi5odG1sCgojIyMjIOWPguiAg+S+i++8kjrlrabmoKHnqK7poZ7liKXpgLLlrabnjofjga7mjqjnp7so5pel5pys6Kqe44OH44O844K/KQoKW+eUt+Wls+WFseWQjOWPgueUu+WxgF0oaHR0cHM6Ly93d3cuZ2VuZGVyLmdvLmpwKeOBruizh+aWmeOBp+OBmeOAggoK5a2m5qCh56iu6aGe5Yil6YCy5a2m546H44Gu5o6o56e7OiBodHRwczovL2VtcG93ZXJtZW50LnRzdWRhLmFjLmpwL2RldGFpbC84MjU4NAoKYGBge3J9CnVybF9zY2hvb2xfanAgPC0gImh0dHBzOi8vd3d3LmdlbmRlci5nby5qcC9hYm91dF9kYW5qby93aGl0ZXBhcGVyL3IwMi96ZW50YWkvaHRtbC9ob25wZW4vY3N2L3p1aHlvMDEtMDQtMDEuY3N2IgpgYGAKCuOCqOODs+OCs+ODvOODh+OCo+ODs+OCsO+8iEVuY29kaW5nIHR5cGXvvInjgpLmjqjmuKzjgZnjgovjgZPjgajjgYzjgafjgY3jgb7jgZnjgIIKCmBgYHtyfQpndWVzc19lbmNvZGluZyh1cmxfc2Nob29sX2pwLCBuX21heCA9IDEwMDAwLCB0aHJlc2hvbGQgPSAwLjIpCmBgYAoKCmBgYHtyfQpkZl9zY2hvb2xfanAgPC0gcmVhZF9jc3YodXJsX3NjaG9vbF9qcCwgbG9jYWxlID0gbG9jYWxlKGVuY29kaW5nID0gIlNoaWZ0X0pJUyIpLCBza2lwPTIpCmRmX3NjaG9vbF9qcCAKYGBgCgpgYGB7ciB3YXJuaW5nPUZBTFNFfQpkZl9lZHUwIDwtIGRmX3NjaG9vbF9qcCAKY29sbmFtZXMoZGZfZWR1MCkgPC0gYygieWVhciIsICJoaWdoc2Nob29sX20iLCAiaGlnaHNjaG9vbF9mIiwgInZvY2F0aW9uYWxfbSIsICJ2b2NhdGlvbmFsX2YiLCAidW5pdmVyc2l0eV9tIiwgInVuaXZlcnNpdHlfZiIsICJqdW5pb3Jjb2xsZWdlX2YiLCAiZ3JhZHNjaG9vbF9tIiwgImdyYWRzY2hvb2xfZiIpCmRmX2VkdTAwIDwtIGRmX2VkdTAgJT4lIG11dGF0ZSh5ZWFyID0gMTk1MDoyMDE5LCAKICAgICAgICAgICAgICAgICAgIGhpZ2hzY2hvb2wgPSAoaGlnaHNjaG9vbF9tICsgaGlnaHNjaG9vbF9mKS8yLAogICAgICAgICAgICAgICAgICAgdm9jYXRpb25hbCA9ICh2b2NhdGlvbmFsX20gKyB2b2NhdGlvbmFsX2YpLzIsCiAgICAgICAgICAgICAgICAgICB1bml2ZXJzaXR5ID0gKHVuaXZlcnNpdHlfbSArIHVuaXZlcnNpdHlfZikvMiwgCiAgICAgICAgICAgICAgICAgICBqdW5pb3Jjb2xsZWdlID0ganVuaW9yY29sbGVnZV9mLAogICAgICAgICAgICAgICAgICAgZ3JhZHNjaG9vbCA9IChncmFkc2Nob29sX20gKyBncmFkc2Nob29sX2YpLzIpIApkZl9lZHUwMCAlPiUgZmlsdGVyKHllYXIgPj0gMTk1NCkgJT4lIHNlbGVjdCgtKDI6MTApKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKDM6NSwgbmFtZXNfdG8gPSAic2Nob29scyIsIHZhbHVlc190byA9ICJwZXJjZW50YWdlIikgJT4lCiAgbXV0YXRlKHR5cGVzID0gZmFjdG9yKHNjaG9vbHMsIGxldmVscyA9IGMoInZvY2F0aW9uYWwiLCAianVuaW9yY29sbGVnZSIsICJ1bml2ZXJzaXR5IikpKSAlPiUKICBwaXZvdF9sb25nZXIoYyhoaWdoc2Nob29sLCBncmFkc2Nob29sKSwgbmFtZXNfdG8gPSAiaGlnaGdyYWQiLCB2YWx1ZXNfdG8gPSJ2YWx1ZSIpICU+JQogIG11dGF0ZShoaWdoX2dyYWQgPSBmYWN0b3IoaGlnaGdyYWQsIGxldmVscyA9IGMoImhpZ2hzY2hvb2wiLCAiZ3JhZHNjaG9vbCIpKSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fYXJlYShhZXMoeCA9IHllYXIsIHkgPSBwZXJjZW50YWdlLCBmaWxsID0gdHlwZXMpKSArCiAgZ2VvbV9saW5lKGFlcyh4ID0geWVhciwgeSA9IHZhbHVlLCBsaW5ldHlwZSA9IGhpZ2hfZ3JhZCkpICsgCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHJvdW5kKHNlcSgxOTYwLCAyMDIwLCBieSA9MTApLDEpKSArIAogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSByb3VuZChzZXEoMCwgMTAwLCBieSA9MTApLDEpKSArIAogIGxhYnModGl0bGUgPSAiVGVydGlhbGx5IEVkdWNhdGlvbiBBZnRlciBIaWdoc2Nob29sIiwgCiAgICAgICBzdWJ0aXRsZSA9ICJ3aXRoIEhpZ2hzY2hvb2wgR3JhZHVhdGVzIGFuZCBHcmFkdWF0ZSBTY2hvb2wiLCAKICAgICAgIGZpbGwgPSAiIiwgbGluZXR5cGUgPSAiIikKYGBgCgoKIyMg77yI57aa77yJ5o6i57Si55qE44OH44O844K/6Kej5p6QIChFREEp44CACgohW2ltYWdlIGZyb20gcjRkc10oaHR0cHM6Ly9kMzN3dWJyZmtpMGw2OC5jbG91ZGZyb250Lm5ldC81NzFiMDU2NzU3ZDY4ZTZkZjgxYTNlMzg1M2Y1NGQzYzc2YWQ2ZWZjLzMyZDM3L2RpYWdyYW1zL2RhdGEtc2NpZW5jZS5wbmcpCgpOWS5HRFAuUENBUC5DRDogR0RQIHBlciBjYXBpdGEgKGN1cnJlbnQgVVMkKQoKYGBge3IgZXZhbD1GQUxTRX0KZGZfd2RpX2dkcHBjYXAgPC0gV0RJKGNvdW50cnkgPSAiYWxsIiwgaW5kaWNhdG9yID0gYyhnZHBfcGNhcCA9ICJOWS5HRFAuUENBUC5DRCIpKQp3cml0ZV9jc3YoZGZfd2RpX2dkcHBjYXAsICIuL2RhdGEvZGZfd2RpX2dkcHBjYXAuY3N2IikKYGBgCgpgYGB7cn0KZGZfd2RpX2dkcHBjYXAgPC0gcmVhZF9jc3YoIi4vZGF0YS9kZl93ZGlfZ2RwcGNhcC5jc3YiKQpgYGAKCmBgYHtyfQpkZl93ZGlfZ2RwcGNhcApgYGAKCiMjIyBEYXRhIFRyYW5zZm9ybWF0aW9uCgojIyMjIOWIl+OCkiBgc2VsZWN0YAoKYGBge3J9CmRmX3dkaV9nZHBwY2FwX3NtYWxsIDwtIGRmX3dkaV9nZHBwY2FwICU+JSAKICBzZWxlY3QoY291bnRyeSwgeWVhciwgZ2RwX3BjYXApCmRmX3dkaV9nZHBwY2FwX3NtYWxsCmBgYAoKIyMjIyDooYzjgpIgYGZpbHRlcmAKCmBgYHtyfQpkZl93ZGlfZ2RwcGNhcF9zaG9ydCA8LSBkZl93ZGlfZ2RwcGNhcCAlPiUgCiAgZmlsdGVyKGNvdW50cnkgJWluJSBjKCJKYXBhbiIsICJHZXJtYW55IiwgIlVuaXRlZCBTdGF0ZXMiKSkKZGZfd2RpX2dkcHBjYXBfc2hvcnQKYGBgCgpgYGB7cn0KZGZfd2RpX2dkcHBjYXBfc21hbGxfc2hvcnQgPC0gZGZfd2RpX2dkcHBjYXAgJT4lIHNlbGVjdChjb3VudHJ5LCB5ZWFyLCBnZHBfcGNhcCkgJT4lCiAgZmlsdGVyKGNvdW50cnkgJWluJSBjKCJKYXBhbiIsICJHZXJtYW55IiwgIlVuaXRlZCBTdGF0ZXMiKSkKZGZfd2RpX2dkcHBjYXBfc21hbGxfc2hvcnQKYGBgCgrmrKHjga/jgIHjgojjgY/nlJ/jgZjjgovjgIHoqqTjgorjga7kvovjgafjgIHjg47jgrPjgq7jg6rjga7mra/vvIhzYXd0b290aGVk77yJ44Gu44KI44GG44Gq44Ku44K244Ku44K244O744Kw44Op44OV44Go5ZG844Gw44KM44G+44GZ44CC44Gq44Gc44GT44Gu44KI44GG44Gq44GT44Go44GM6LW344GN44Gm44GE44KL44GL44KP44GL44KK44G+44GZ44GL44CCCgpgYGB7cn0KZGZfd2RpX2dkcHBjYXBfc21hbGxfc2hvcnQgJT4lCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IGdkcF9wY2FwKSkgKyBnZW9tX2xpbmUoKQpgYGAKCmBgYHtyfQpkZl93ZGlfZ2RwcGNhcF9zbWFsbF9zaG9ydCAlPiUgZmlsdGVyKGNvdW50cnkgJWluJSBjKCJKYXBhbiIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gZ2RwX3BjYXApKSArIGdlb21fbGluZSgpCmBgYAoKYGBge3J9CmRmX3dkaV9nZHBwY2FwX3NtYWxsX3Nob3J0ICU+JQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBnZHBfcGNhcCkpICsgZ2VvbV9wb2ludCgpCmBgYAoKYGBge3J9CmRmX3dkaV9nZHBwY2FwX3NtYWxsX3Nob3J0ICU+JSBkcm9wX25hKGdkcF9wY2FwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gZ2RwX3BjYXAsIGNvbCA9IGNvdW50cnkpKSArIGdlb21fbGluZSgpCmBgYAoKYGBge3J9CmRmX3dkaV9nZHBwY2FwX3NtYWxsX3Nob3J0ICU+JSBkcm9wX25hKGdkcF9wY2FwKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gZ2RwX3BjYXAsIGNvbCA9IGNvdW50cnkpKSArIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KCkKYGBgCgpgYGB7cn0KZGZfd2RpX2dkcHBjYXBfc21hbGxfc2hvcnQgJT4lIGRyb3BfbmEoZ2RwX3BjYXApICU+JQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBnZHBfcGNhcCkpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBjb3VudHJ5KSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG9lc3MnLCBmb3JtdWxhID0gJ3kgfiB4JykKYGBgCgojIOWPguiAgyAtIOS7iuW+jOOBruWtpue/kuOBruOBn+OCgeOBqwoKIyMgUk5vdGVib29rIOOBrua0u+eUqAoK5LiL44Gu44Oq44Oz44Kv44KS6ZaL44GN44CB5Y+z5LiK44GuIENvZGUg44Oc44K/44Oz44GL44KJ44CBRG93bmxvYWQgUm1kIOOCkumBuOaKnuOBmeOCi+OBqOOAgeODgOOCpuODs+ODreODvOODieOBp+OBjeOBvuOBmeOBi+OCieOAgeODgOOCpOODs+ODreODvOODieOBl+OBn+OCguOBruOCkuOAgeODl+ODreOCuOOCp+OCr+ODiOODu+ODleOCqeODvOODq+ODgOODvOOBq+enu+WLleOBvuOBn+OBr+OCs+ODlOODvOOBl+OBpuOBj+OBoOOBleOBhOOAguODgOOCpuODs+ODreODvOODieOBp+OBjeOBquOBhOOBqOOBjeOBr+OAgUN0cmwg44KS5oq844GX44Gq44GM44KJ44CBRG93bmxvYWQgUm1kIOOCkuOCr+ODquODg+OCr+OBmeOCi+OBqOOAgVNhdmUgQXMg44Gn5L+d5a2Y44Gn44GN44KL44Go5oCd44GE44G+44GZ44CC44OW44Op44Km44K244O844Gr44KI44Gj44Gm5LuV5qeY44GM55Ww44Gq44KK44G+44GZ44GL44KJ44CB6YGp5YiH44Gq5pa55rOV44KS6YG444KT44Gn44GP44Gg44GV44GE44CCCgotICAgPGh0dHBzOi8vZHMtc2wuZ2l0aHViLmlvL2ludHJvMnIvUk5vdGVib29rLUoubmIuaHRtbD4KLSAgIDxodHRwczovL2RzLXNsLmdpdGh1Yi5pby9pbnRybzJyL1JtYXJrZG93bi1KLm5iLmh0bWw+CgpXaW5kb3dzIOOBp+OCguOAgU1hYyDjgafjgoLmj5DkvpvjgZXjgozjgabjgYTjgovjgIFHb29nbGUgQ2hyb21lIOOBruWgtOWQiOOBq+OBr+OAgUNvZGUg44Oc44K/44Oz44GL44KJ44CB44OA44Oz44Ot44O844OJ44GV44KM44KL44Gv44Ga44Gn44GZ44CCCgojIyDjgq/jg6njgqbjg4kgLSBQb3NpdCBDbG91ZAoKUlN0dWRpbyBDbG91ZOOBr+OAgeiqsOOBp+OCguOCquODs+ODqeOCpOODs+OBp+ODh+ODvOOCv+OCteOCpOOCqOODs+OCueOCkuihjOOBhOOAgeWFseacieOBl+OAgeaVmeOBiOOAgeWtpuOBtuOBk+OBqOOBjOOBp+OBjeOCi+OAgei7vemHj+OBp+OCr+ODqeOCpuODieODmeODvOOCueOBruOCveODquODpeODvOOCt+ODp+ODs+OBp+OBmeOAguaciDI15pmC6ZaT44Gu5Yi26ZmQ44GM44GC44KK44G+44GZ44GM44CB5YaF5a6544KS5YWx5pyJ44GX44Gm44CB5LuW44Gu44Ki44Kr44Km44Oz44OI44GL44KJ5Yip55So44GZ44KL44GT44Go44KC5Y+v6IO944Gn44GZ44CCCgojIyMg44Kv44Op44Km44OJ44K144O844OT44K544CASG93IHRvIFN0YXJ0IFBvc2l0IENsb3VkIHstfQoKMS4gIEdvIHRvIDxodHRwczovL3Bvc2l0LmNsb3VkLz4KMi4gIFNpZ24gVXA6IHRvcCByaWdodAozLiAgRW1haWwgYWRkcmVzcyBvciBHb29nbGUgYWNjb3VudAo0LiAgTmV3IFByb2plY3Q6IFByb2plY3QgTmFtZQoKIyMg57e057+S5ZWP6aGMIFBvc2l0IFByaW1lcnMKClBvc2l0IFByaW1lcnMgPGh0dHBzOi8vcG9zaXQuY2xvdWQvbGVhcm4vcHJpbWVycz4KCiMjIyDmnIDliJ3jga7mvJTnv5Igey19CgpNb29kbGXvvIgy5pyIMjLml6XvvInjgavjg6rjg7Pjgq/jgpLjgaTjgZHjgabjgYLjgorjgb7jgZnjgIIKCi0gICBbVmlzdWFsaXphdGlvbiBCYXNpY3NdKGh0dHBzOi8vcnN0dWRpby5jbG91ZC9sZWFybi9wcmltZXJzLzEuMSkKLSAgIFtQcm9ncmFtbWluZyBCYXNpY3NdKGh0dHBzOi8vcnN0dWRpby5jbG91ZC9sZWFybi9wcmltZXJzLzEuMikKCiMjIOWPguiAg+aWh+eMriBSZWZlcmVuY2VzCgotICAgUiBGb3IgRGF0YSBTY2llbmNlLCBieSBILiBXaWNraGFtOiA8aHR0cHM6Ly9yNGRzLmhhZC5jby5uej4KCiAgICAtICAgSW50cm9kdWN0aW9uOiA8aHR0cHM6Ly9yNGRzLmhhZC5jby5uei9leHBsb3JlLWludHJvLmh0bWwjZXhwbG9yZS1pbnRybz4KCi0gICBCb29rZG93bjogPGh0dHBzOi8vYm9va2Rvd24ub3JnPiwgW0FyY2hpdmVdKGh0dHBzOi8vYm9va2Rvd24ub3JnL2hvbWUvYXJjaGl2ZS8pCgotICAgW0dldCBTdGFydGVkOiBSIFN0dWRpbyDjgacgUiDjgpLjga/jgZjjgoHjgojjgYbjgIFSIE1hcmtkb3duXShodHRwczovL2RzLXNsLmdpdGh1Yi5pby9pbnRybzJyL2dldHN0YXJ0ZWQuaHRtbCkKCi0gICBbSW50cm9kdWN0b24gdG8gUl0oaHR0cHM6Ly9kcy1zbC5naXRodWIuaW8vaW50cm8yci9pbnRybzJyLm5iLmh0bWwjM19EYXRhX0FuYWx5c2lzX1VzaW5nX1JTdHVkaW8pCgotICAgW0RhdGEgQW5hbHlzaXMgZm9yIFJlc2VhcmNoZXJzIDIwMjJdKGh0dHBzOi8vaWN1LWhzdXp1a2kuZ2l0aHViLmlvL2RhNHIyMDIyLykKCi0gICBb44OH44O844K/44O744K144Kk44Ko44Oz44K544KS5aeL44KB44G+44GX44KH44GGIC0gRGF0YSBTY2llbmNlIGZvciBBbGxdKGh0dHBzOi8vaWN1LWhzdXp1a2kuZ2l0aHViLmlvL2RzNGFqLykKCgo=