この文書は、 Rao & Molina (2015) “Small Area Estimation”, 2nd Ed. (以下RM本)を読みながら、小地域推定の具体的な手続きについて、 Rで実習してみた記録である。

いうまでもなく、私による私のための私のノートであり、すべての誤りは私に帰属いたします。

なお、RM本の読書ノートは理論編として別途まとめてある。

更新履歴:

  • 2018/06/25 理論編から分離。Fay-Herriotモデルの説明を追加。 まだまだこれからだ…
  • 2018/06/27 Fay-Herriotモデル(milkデータ)を, BayesSAEパッケージ, nlmeパッケージでも試した。
  • 2018/06/28 ちょっとだけ更新。空間FHモデルに進む勇気がまだ出ない…
  • 2018/06/29 Fay-Herriotモデルのシミュレーションを追加。いろいろと 発見がありました。
  • 2018/07/01 空間Fay-Herriotモデルの実習を追加。
  • 2018/07/02 空間Fay-Herriotモデルの実習に、BayesSAEパッケージとspdepパッケージを 追加。RM本のささやかな誤りのせいで、えらい目に…
  • 2018/07/05 誤字などの修正。
  • 2018/07/08 ようやく空間Fay-Herriotモデルの実習を終了。長かった。
  • 2018/07/09 Fay-Herriotモデルの実習にrstanを追加。
  • 2018/07/10 空間Fay-Herriotモデルの実習にrstanを追加。
  • 2018/07/12 誤字など訂正。いったんこれで終了とします。
  • 2018/07/18 誤字など訂正。
  • 2018/07/19 誤字など訂正。

1. 小地域推定とは

なにかの事柄について標本調査をやったとき、標本サイズは全体としては十分に大きいんだけど、 標本がなんらかのたくさんのドメイン(たとえば地域とか)に分かれていて、 ドメイン別にみると標本サイズが足りない、 困ったな、ということがある。

標本サイズが足りないんなら、いさぎよく推定をあきらめればいいと 思うんだけど、なかなかそうもいっていられない。 標本サイズが小さいドメインについても、なんとかしてそれらしい推定値を求めたい。 こういう問題を小地域推定という。

小地域推定は主に公的統計の分野で発展してきたんだけど、標本調査を利用する他の分野 (たとえば市場調査)の関係者にとっても、学ぶ価値があるように思う。

というわけで、以下ではRを使い、小地域推定の実習をいたします。

1.1 小地域モデルによる推定

小地域推定の歴史は長く、いろんなアプローチがあるが、それらは以下の3つに分類できる。

  • 直接推定 … ある小地域の特性について、 その小地域についてのデータだけをつかって推定する。 RM本の2章。
  • 間接推定 … ある小地域の特性について、他の小地域のデータも使いながら推定する。
    • デザイン・ベース … 調査デザインについての情報に基づいて推定する。RM本の3章。
    • モデル・ベース … データの背後に統計的モデル(小地域モデル)を想定し、 このモデルを使って推定する。RM本の4章-10章。

本稿ではモデル・ベース間接推定、つまり、小地域モデルによる小地域推定を扱う。

1.2. 推定方法

先に述べたように、 地域モデルによる小地域推定では、 (1)データの背後になんらかの小地域モデルを想定し、 (2)そのモデルをデータにあてはめて、モデルのパラメータを推定し、 (3)それを通じて、小地域の特性について推定しようとするわけである。

(1)の小地域モデルにはいろいろあるが、いずれの場合にも、 (2)(3)における推定方法(推定量のタイプ)は、大きく分けて次の3種類である。

  • 経験的最良線形不偏予測推定(EBLUP推定)。RM本5章-8章。
  • 経験ベイズ推定(EB推定)。9章。
  • 階層ベイズ推定(HB推定)。10章。

以下ではEBLUP推定とHB推定を試す。

EBLUP推定では、モデルのパラメータを次の2段階にわけて推定する。

  • Step 1. 分散成分と呼ばれるパラメータを推定する。その方法として、 ML推定量, REML推定量, モーメント推定量などがある。
  • Step 2. 他のパラメータを推定する。

HB推定では、データとモデルに基づき、小地域の特性がどうなっているかを 確率分布の形で推定する(これを「事後分布」という)。事後分布を求める方法には、 大きく分けて次の2つがある。

  • 数値積分による方法。
  • MCMCによる方法。

2. パッケージと汎用関数

以下の実習では次のパッケージを使用する。

### x <- Sys.setlocale("LC_ALL","English")
### 
library(dplyr)
library(tidyr)
library(ggplot2)
library(gridExtra)  ### grid.arrange()
library(R.utils)    ### witTimeout()
library(GGally)     ### ggpairs()
library(igraph)     ### plot network graph
library(tagcloud)   ### smoothPalette()
library(raster)     ### required by {rstan}
# library(RColorBrewer)
# library(scales)
# library(coda)
###
### for small area estimation
library(sae)
library(hbsae)
library(BayesSAE)
library(nlme)
library(spdep)
library(rstan)
###
### for rstan
rstan_options(auto_write = TRUE)
options(mc.cores=parallel::detectCores())
sessionInfo() 
R version 3.5.1 (2018-07-02)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

Matrix products: default

locale:
[1] LC_COLLATE=Japanese_Japan.932  LC_CTYPE=Japanese_Japan.932   
[3] LC_MONETARY=Japanese_Japan.932 LC_NUMERIC=C                  
[5] LC_TIME=Japanese_Japan.932    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] rstan_2.17.3       StanHeaders_2.17.2 spdep_0.7-7       
 [4] spData_0.2.9.0     nlme_3.1-137       BayesSAE_1.0-2    
 [7] lattice_0.20-35    coda_0.19-1        Formula_1.2-3     
[10] hbsae_1.0          sae_1.2            lme4_1.1-17       
[13] Matrix_1.2-14      MASS_7.3-50        raster_2.6-7      
[16] sp_1.3-1           tagcloud_0.6       Rcpp_0.12.17      
[19] igraph_1.2.1       GGally_1.4.0       R.utils_2.6.0     
[22] R.oo_1.22.0        R.methodsS3_1.7.1  gridExtra_2.3     
[25] ggplot2_3.0.0      tidyr_0.8.1        dplyr_0.7.6       

loaded via a namespace (and not attached):
 [1] deldir_0.1-15      gtools_3.8.1       assertthat_0.2.0  
 [4] rprojroot_1.3-2    digest_0.6.15      R6_2.2.2          
 [7] plyr_1.8.4         backports_1.1.2    stats4_3.5.1      
[10] evaluate_0.11      pillar_1.3.0       rlang_0.2.1       
[13] lazyeval_0.2.1     gdata_2.18.0       rstudioapi_0.7    
[16] minqa_1.2.4        nloptr_1.0.4       gmodels_2.18.1    
[19] rmarkdown_1.10     splines_3.5.1      stringr_1.3.1     
[22] munsell_0.5.0      compiler_3.5.1     pkgconfig_2.0.1   
[25] base64enc_0.1-3    htmltools_0.3.6    tidyselect_0.2.4  
[28] expm_0.999-2       tibble_1.4.2       reshape_0.8.7     
[31] crayon_1.3.4       withr_2.1.2        grid_3.5.1        
[34] jsonlite_1.5       arm_1.10-1         gtable_0.2.0      
[37] magrittr_1.5       scales_0.5.0       stringi_1.2.3     
[40] LearnBayes_2.15.1  bindrcpp_0.2.2     boot_1.3-20       
[43] RColorBrewer_1.1-2 tools_3.5.1        glue_1.3.0        
[46] purrr_0.2.5        abind_1.4-5        parallel_3.5.1    
[49] yaml_2.1.19        inline_0.3.15      colorspace_1.3-2  
[52] knitr_1.20         bindr_0.1.1       

また、チャート作成のために、あらかじめ以下の汎用的な関数を定義しておく。

sub_PlotTwoEstimate.1 <- function(
  agEst1, agMSE1=NULL, agEst2, agMSE2=NULL, asLabel, sVarLabel1, sVarLabel2
){
  # purpose: plot scatter plots to compare two type of estimation 
  # arg:
  #   agEst1: estimates of type 1
  #   agMSE1: MSEs of agEst1 (or NULL)
  #   agEst2: estimates of type 2  
  #   agMSE2: MSE2 of agEst2 (or NULL)
  #   asLabel: labels 
  #   sVarLabel1: a label of estimation type 1
  #   sVarLable1: a label of estimation type 2
  
  bPlotMSE <- !is.null(agMSE1)
  
  # traps
  stopifnot(length(agEst1) == length(agEst2))
  stopifnot(length(agEst1) == length(asLabel))
  if (bPlotMSE){
    stopifnot(length(agEst1) == length(agMSE1))
    stopifnot(length(agEst1) == length(agMSE2))
  }
  
  # plot of estimates
  dfPlotEst <- data.frame(
    gEst1  = agEst1, 
    gEst2  = agEst2, 
    sLabel = asLabel
  )
  g1 <- ggplot(data=dfPlotEst, aes(x = gEst1, y = gEst2, label=sLabel))
  g1 <- g1 + geom_text(size=3)
  g1 <- g1 + labs(
    title = expression("Estimate"), 
    x     = sVarLabel1,
    y     = sVarLabel2
  )
  g1 <- g1 + geom_abline(intercept = 0, slope = 1)
  g1 <- g1 + theme_bw()
# print(g1)
  
  # plot of MSEs
  if (bPlotMSE){
    dfPlotMSE <- data.frame(
      gMSE1 = agMSE1, 
      gMSE2 = agMSE2, 
      sLabel = asLabel
    )
    g2 <- ggplot(data=dfPlotMSE, aes(x = gMSE1, y = gMSE2, label=sLabel))
    g2 <- g2 + geom_text(size=3)
    g2 <- g2 + labs(
      title = expression("MSE"), 
      x     = sVarLabel1,
      y     = sVarLabel2
    )
    g2 <- g2 + geom_abline(intercept = 0, slope = 1)
    g2 <- g2 + theme_bw()
    
  }
  
  # plot
  if (bPlotMSE){
    grid.arrange(g1, g2, ncol = 2) 
  } else {
    plot(g1)
  }
}
gg_color_hue <- function(n) {
  # purpose: Emulate ggplot2 default color palette
  # arg:
  #   n: number of colors
  # return: 
  #   a vector of colors
  # notes;
  #   see https://stackoverflow.com/questions/8197559/emulate-ggplot2-default-color-palette
  
  hues = seq(15, 375, length = n + 1)
  hcl(h = hues, l = 65, c = 100)[1:n]
  
}

以下では、小地域推定に用いるパッケージをご紹介します。

2.1 saeパッケージ

RM本の著者のひとりMolinaさんが開発に関わっているパッケージ。

このパッケージが提供する関数は以下の通り。

  • 小地域モデルによる推定
    • Fay-Herriotモデル … eblupFH(), mseFH()
    • 空間Fay-Herriotモデル … eblupSFH(), mseSFH(), pbmseSFH(), npbmseSFH()
    • 時空間Fay-Herriotモデル … eblupSTFH(), pbmseSTFH()
    • ユニットレベルモデル … eblupBHF(), pbmseBHF(), pbmseebBHF(), ebBHF()
  • 直接推定・デザインベース推定 … direct(), pssynt(), ssd()
  • ツール… bxcx(), diagonalizematrix()

saeパッケージで小地域モデルを推定する場合、推定量はEBLUPである。分散成分の 推定量はいくつかの選択肢から選ぶことができる。

2.2 hbsaeパッケージ

小地域推定のパッケージとしては古株。 開発者の方のプレゼン資料によれば、この方はオランダ統計局にお勤めで、このパッケージはオランダの労働力調査で実際に使われているんだそうです。そういわれるとぐっと信頼感が増しますね。

このパッケージが提供する関数は以下の通り。

  • 小地域モデルによる推定 … fSAE(), fSAE.Area(), fSAE.Unit()
  • 直接推定 … fSurvReg()
  • ツール … aggr(), bench(), CVarea(), generateFakeData(), uweights()

小地域モデルを推定する場合、推定量としてEBLUPとHBが用意されている。EBLUP推定の場合、 分散成分の推定量はいくつかの選択肢から選ぶことができる。 HB推定は数値積分を使用する。

2.3 BayesSAEパッケージ

Fay-Herriotモデル(後述する)のHB推定に特化したパッケージ。

このパッケージが提供する関数は BayesSAE()である。シンプルでよろしい。

推定量はHBのみ。MCMCを使用する。

2.4 nlmeパッケージ

小地域推定に限らず、線形・非線形の混合モデルのためのパッケージ。 Rのコアパッケージである。

小地域モデルは基本的には一種の混合モデルなので、 こういう汎用的なパッケージでも推定できる…はずである。

推定量はEBLUP。分散成分の推定量はいくつかの選択肢から選べる。

2.5 spdepパッケージ

小地域推定というより、空間データ分析の基本パッケージ。多種多様な機能を 提供している。

空間Fay-Harrietモデルは要するにSAR(同時自己回帰)モデルなので、 こういう汎用的なパッケージでも推定できるはずだ…と思ったんです。

小地域の特性を推測する場合、推定量はEBLUPだということになると 思うのですが… すいません、よくわからないっす。

2.6 rstanパッケージ

泣く子も黙る、ベイジアン・モデリングのための 汎用パッケージ。なるべくなら触りたくないのですが、このたびは仕方なく…。

推定量はHB。MCMCを利用する。

3. 地域レベルモデル

3.1 Fay-Herriotモデルとは

(本節はRM本4.2節, 6.1節, 10.3節のまとめである。)

Fay-Herriotモデルとは、小地域レベルのデータを使って 小地域特性を推定するためのモデルである。

地域\(i\)(\(=1,\ldots,m\))における、なにかの変数の平均(たとえば一人当たり所得)を\(\bar{Y}_i\)とする。

\(\bar{Y}_i\)そのものについてはわからないが、 その地域の標本から、直接推定量\(\hat{\bar{Y}}_i\)(典型的には標本平均) が手に入っているとしよう。ただし、標本サイズが十分でないので、 この値があてにならない… というのが問題の発端である。

なんらかの関数\(g(\cdot)\)があって、\(\theta_i = g(\bar{Y}_i)\)であるとする。 典型的には\(\theta_i = \bar{Y}_i\)である。 同様に、\(\hat{\theta}_i = g(\hat{\bar{Y}}_i)\)とする。

以上のデータとともに、 地域の補足データ\(\mathbf{z}_i\)(長さ\(p\)のベクトル)も手に入っているとする。 つまり、その地域の\(\theta_i\)を予測するのに役立つような、なんらかの変数群についての 値である。

さて、各地域の\(\bar{Y}_i\)について推測したい。 そこで以下のように想定する。なお以下では、変数\(x\)が平均0, 分散\(\sigma^2\)のなんらかの分布に 従うということを、\(x \sim (0, \sigma^2)\)と略記する。

まず、 \[ \theta_i = \mathbf{z}_i^T \mathbf{\beta} + v_i, \ \ v_i \sim (0, \sigma_v^2)\]

と考える。 つまり、関心の対象である地域特性(\(\theta_i\))は、その地域の補足データ\(\mathbf{z}_i\) で決まっている部分と、それ以外の部分(いわば「地域効果」)\(v_i\)の和だと考えるわけである。 さらに、地域効果はランダムに決まり、その平均は0で、分散は\(\sigma_v^2\)だと考える。

次に、 \[\hat{\theta}_i = \theta_i + e_i, \ \ e_i|\theta_i \sim (0, \psi_i)\]

と考える。つまり、手元にある直接推定量\(\hat{\theta}_i\)は、地域特性の真の値 (\(\theta_i\))を反映してはいるが、標本調査につきものである標本抽出誤差\(e_i\)も 含んでしまっている、と考えるわけである。さらに、各地域の標本抽出誤差は ランダムに決まり、その平均は0で、分散は\(\psi_i\)だと考える。 \(\psi_i\)については既知とする。

このモデルに基づき、\(\theta_i\)について推定することができる。 これがFay-Herriotモデルである。

では、Fay-Herriotモデルのパラメータ (\(\mathbf{\beta}\), \(\sigma_v^2\))をどうやって推定するか。

EBLUP推定の場合は、まず\(\sigma_v^2\)を推定し、次に\(\mathbf{\beta}\)\(\theta_i\)を推定する。

HB推定の場合は、Fay-Herriotモデルを次の階層ベイズモデルに書き換える。

\[ \begin{aligned} {\rm (i)} \ \ & \hat{\theta}_i | \theta_i, \mathbf{\beta}, \sigma^2_v \mathop{\sim}^{iid} N(\theta_i, \psi_i), \ \ i = 1, \ldots, m \\ {\rm (ii)} \ \ & \theta_i | \mathbf{\beta}, \sigma^2_v \mathop{\sim}^{iid} N(\mathbf{z}_i^T, \sigma_v^2), \ \ i = 1, \ldots, m \\ {\rm (iii)} \ \ & f(\mathbf{\beta}, \sigma^2_v) = f(\mathbf{\beta}) f(\sigma^2_v) \propto f(\sigma^2_v) \end{aligned} \] このモデルを推定するためには、\(\sigma^2_v\)の事前分布\(f(\sigma^2_v)\)を指定する必要がある。

代表的な推定方法として、次の2つがある。

  • \(f(\sigma^2_v) \propto 1\) と指定し、\(\theta_i\)を数値積分により推定する。
  • \(\sigma_v^{-2} \sim G(a,b)\)と指定し、\(\theta_i\)をMCMCにより推定する。

3.2 実習: milk

まずはかんたんなデータについて、基本的なFay-Herriotモデルを推定してみよう。

3.2.1 データ

saeパッケージについているサンプルデータ milk を使う。 このデータは、43地域について以下の変数を持っている。

  • SmallArea: 地域番号
  • ni: 標本サイズ
  • yi: 生乳の年間支出の標本平均
  • SD: 生乳の年間支出の標本平均のSDの推定値。つまりSE。
  • CV: 変動係数(CV)
  • MajorArea: 上位地域番号

データの出典となっている論文 Arora & Lahiri (1997) をあたってみたところ、これは1989年のデータで、地域は “publication area”だそうである(恥ずかしながら意味がわかりません)。 なお、MajorAreaは現論文にはない。あとから付けたものらしい。

### a.dfMilk: dataset
data(milk, package="sae")
a.dfMilk <- milk %>%
  mutate(
    SmallArea = as.factor(SmallArea),
    MajorArea = as.factor(MajorArea), 
    var = SD^2
  )
rm(milk)
print(a.dfMilk %>% dplyr::select(-var))

各地域の標本サイズは95から633。小地域じゃないじゃん!これで十分じゃん! と私なんかは思うわけですが、そのへんは分野によるんでしょうね。

各地域の支出をチャートにしてみよう。

g <- ggplot(
  data = a.dfMilk, 
  aes(
    x     = SmallArea, 
    y     = yi, 
    ymin  = yi - SD, 
    ymax  = yi + SD, 
    color = MajorArea
  )
)
g <- g + geom_pointrange()
g <- g + labs(
  x     = "Small Area", 
  y     = expression(mean %+-% SE), 
  color = "Major Area"
)
g <- g + theme_bw()
print(g)

上位地域番号によって支出が異なることがわかる。共変量にするとよさそうだ。

3.2.2 saeパッケージによる推定

(本節はRM本6.5節の再現である。)

まずはsaeパッケージで推定してみよう。

saeパッケージでは、 基本的なFay-Herriotモデルの関数として、 eblupFH()とmseFH()が用意されている。eblupFH()は推定値しか返さないが、 mseFH()は推定量のMSEの推定値も返す、という 違いがあるらしい。 以下ではmseFH()を使うことにする。

まず、共変量なしで。

### a.oModel_saeREML_nox: saeREML model with no covariate
a.oModel_saeREML_nox <- mseFH(
  formula = a.dfMilk$yi ~ 1, 
  vardir  = a.dfMilk$SD ^ 2, 
  method  = "REML"
)
  • method=オプションは、 \(\sigma_u^2\)の推定量の指定。 REML(デフォルト), ML, FHを選べる。FHというのは RM本6.1.2節でいうところの方法1のことであろう。
  • formula=オプションで共変量を指定する。ここでは切片項のみ指定している。
  • vardir=オプションで、標本抽出分散\(\psi_i\)を指定する。 ここでは\(\psi_i\)の代用として、各地域における標本平均の分散の推定値 (つまり標本平均の標準誤差の二乗)を使用している。
cat("refvar:", a.oModel_saeREML_nox$est$fit$refvar, "\n")
refvar: 0.05431129 

\(\sigma_v^2\)は0.05431と推定された。

では、共変量として上位地域番号をいれてみよう。

### a.oModel_saeREML: saeREML model
a.oModel_saeREML <- mseFH(
  formula = a.dfMilk$yi ~ a.dfMilk$MajorArea, 
  vardir  = a.dfMilk$SD ^ 2, 
  method  = "REML"
)
cat("refvar:", a.oModel_saeREML$est$fit$refvar, "\n")
refvar: 0.01855022 

\(\sigma_v^2\)は0.01855と推定された。ぐっと下がっている。

\(\mathbf{\beta}\)は…

print(a.oModel_saeREML$est$fit$estcoef)

試みに、地域効果\(v_i\)を無視した回帰モデルを推定してみよう。

print(summary(lm(yi ~ MajorArea, data = a.dfMilk))$coefficients)
              Estimate Std. Error   t value     Pr(>|t|)
(Intercept)  0.9854286 0.06937886 14.203585 5.314727e-17
MajorArea2   0.1750000 0.09811653  1.783593 8.227312e-02
MajorArea3   0.2175714 0.08874974  2.451516 1.880886e-02
MajorArea4  -0.2390952 0.08176377 -2.924220 5.725864e-03

固定効果の係数の推定値が異なる。つまり、直接推定量\(\hat{\theta}_i\) を目的変数として、 Fay-Herriotモデル \[\hat{\theta}_i = \mathbf{z}_i^T \mathbf{\beta} + v_i + e_i\] を推定した場合と、 地域効果を無視した回帰モデル \[\hat{\theta_i} = \mathbf{z}^T_i \mathbf{\beta}' + e'_i \] を推定した場合、 \(\mathbf{\beta}\)の推定値と\(\mathbf{\beta}'\)の推定値は異なるのだ。このことは、 RM本6.1.1節の\(\hat{\mathbf{\beta}}\)の式をみてもわかる。 ここ、わたしずーっと誤解してました…反省…

本題に戻って、\(\theta_i\)のEBLUP推定値を見比べてみる。

### a.dfResult_saeREML: result from models by saeREML
a.dfResult_saeREML <- a.dfMilk %>%
  mutate(
    gEBLUP1 = as.vector(a.oModel_saeREML_nox$est$eblup), 
    gEBLUP2 = as.vector(a.oModel_saeREML$est$eblup), 
    gMSE1   = a.oModel_saeREML_nox$mse, 
    gMSE2   = a.oModel_saeREML$mse,
    gCV_0   = CV,
    gCV_1   = sqrt(gMSE1)/gEBLUP1,
    gCV_2   = sqrt(gMSE2)/gEBLUP2
  )
g <- ggplot(
  data = a.dfResult_saeREML,
  aes(
    x    = SmallArea,
    y    = yi,
    ymin = yi - SD ,
    ymax = yi + SD 
  )
)
g <- g + geom_pointrange(aes(color = MajorArea))
g <- g + geom_path(aes(y = gEBLUP1, group = 0))
g <- g + geom_path(aes(y = gEBLUP2, group = 0, color = MajorArea))
g <- g + labs(
  x     = "Small Area", 
  y     = expression(mean %+-% SE), 
  color = "Major Area"
)
g <- g + theme_bw()
print(g)

折れ線のうち、黒いのは共変量を使わなかった場合、色がついているのは 使った場合。前者は全体平均に、後者はMajor rea別の 平均に値が寄っている。

今度はMSEの推定値を比べてみよう。

平均が大きいとそのMSEも大きくなりそうなので、 変動係数で比較する。

dfPlot <- a.dfResult_saeREML %>%
  arrange(-ni) %>% 
  mutate(
    fSmallArea = factor(
      seq_along(SmallArea), 
      labels = as.character(SmallArea)
    )
  ) %>%
  dplyr::select(fSmallArea, MajorArea, ni, starts_with("gCV_")) %>%
  gather(sVar, gValue, starts_with("gCV_")) %>%
  separate(sVar, c("sVar1", "sVar2")) %>%
  mutate(
    fMethod = factor(
      as.integer(sVar2), 
      levels = 0:2, 
      labels = c("Direct", "EBLUP(w/o covariate)", "EBLUP(w/ covariate)")
    )
  )
g <- ggplot(
  data = dfPlot,
  aes(
    x     = fSmallArea,
    y     = gValue,
    group = fMethod, 
    color = fMethod
  )
)
g <- g + geom_path()
g <- g + labs(
  x     = "Small Area (sorted by decreasing sample size)", 
  y     = "Coef.Variation", 
  color = "Method"
)
g <- g + theme_bw()
print(g)

今度は横軸を標本サイズ順に並べている。

直接推定量、共変量なしのEBLUP, 共変量をいれたEBLUPと進むにつれて 変動係数が小さくなっている。 また、標本サイズが大きい地域では、変動係数があまり減っていない。なるほどね。

なお、以上は\(\sigma_v^2\)をREML推定した場合であった。 後述する理由により、ここでML推定も試しておく。

### a.oModel_saeML: model by saeML
a.oModel_saeML <- mseFH(
  formula = a.dfMilk$yi ~ a.dfMilk$MajorArea, 
  vardir  = a.dfMilk$SD ^ 2, 
  method  = "ML"
)
print(a.oModel_saeML$est$fit$refvar)
[1] 0.01551755

\(\sigma_v^2\)は0.01552と推定された。ちょっぴり低めですね。

sub_PlotTwoEstimate.1(
  agEst1     = as.vector(a.oModel_saeREML$est$eblup), 
  agMSE1     = a.oModel_saeREML$mse, 
  agEst2     = as.vector(a.oModel_saeML$est$eblup), 
  agMSE2     = a.oModel_saeML$mse, 
  asLabel    = a.dfMilk$SmallArea, 
  sVarLabel1 = "sae (REML)", 
  sVarLabel2 = "sae (ML)"
)

\(\theta_i\)の推定値も、推定量のMSEの推定値も、ほとんどかわらない。

3.2.3 hbsaeパッケージによる推定

共変量をいれたモデルの推定を、今度はhbsaeパッケージで試してみる。

hbsaeパッケージは推定量として以下を御用意している。

  • survreg … 察するに直接推定であろう。
  • synthetic … デザインベース間接推定であろう。
  • hybrid … EBLUP推定, \(\sigma_u^2\)をHB推定する。
  • REML … EBLUP推定, \(\sigma_u^2\)ををREML推定する。
  • BLUP … EBLUP推定, \(\sigma_u^2\)をを別途指定する。
  • HB … 階層ベイズ推定。

まずはEBLUP推定を試してみよう。saeパッケージの出力と揃えるため、REMLを選ぶ。

### a.oModel_hbsaeREML: model by hbsaeREML
a.oModel_hbsaeREML <- fSAE.Area(
  a.dfMilk$yi, 
  a.dfMilk$SD^2, 
  model.matrix(yi ~ MajorArea, data=a.dfMilk), 
  method = "REML"
)
REML estimate of variance ratio: 0.01855
sub_PlotTwoEstimate.1(
  agEst1     = as.vector(a.oModel_saeREML$est$eblup), 
  agMSE1     = a.oModel_saeREML$mse, 
  agEst2     = EST(a.oModel_hbsaeREML), 
  agMSE2     = SE(a.oModel_hbsaeREML)^2, 
  asLabel    = a.dfMilk$SmallArea, 
  sVarLabel1 = "sae (REML)", 
  sVarLabel2 = "hbsae (REML)"
)

\(\sigma_v^2\)は, hbsaeのfSAE.Area()ではvariance ratioと呼ばれるらしい。 なんだか変な呼び方だが、 きっとfSAE.Area()の内側でユニットレベルモデルの関数をコールしている から、ユニットレベルモデルの用語がそのまま残っているのだろう。 推定値は0.01855、saeパッケージの推定値とほぼ同じだ。

\(\theta_i\)の推定値もほぼ同じ。しかし、推定量のMSEの推定値は hbsaeのほうが少し低めになっている。なぜかわからない。

こんどは階層ベイズ推定。 hbsaeパッケージにおけるHB推定は、MCMCではなく数値積分を使っている。

### a.oModel_hbsaeHB: model by hbsaeHB
set.seed(12345)
a.oModel_hbsaeHB <- fSAE.Area(
  a.dfMilk$yi, 
  a.dfMilk$SD^2, 
  model.matrix(yi ~ MajorArea, data=a.dfMilk)
)
REML estimate of variance ratio: 0.01855
numerical integration of f(x) (normalization constant): 2.231 with absolute error < 5.1e-10
numerical integration of x*f(x): 0.05055 with absolute error < 6.6e-11
posterior mean for variance ratio: 0.02266

sub_PlotTwoEstimate.1(
  agEst1     = as.vector(a.oModel_saeREML$est$eblup), 
  agMSE1     = a.oModel_saeREML$mse, 
  agEst2     = EST(a.oModel_hbsaeHB), 
  agMSE2     = SE(a.oModel_hbsaeHB)^2, 
  asLabel    = a.dfMilk$SmallArea, 
  sVarLabel1 = "sae (REML)", 
  sVarLabel2 = "hbsae (HB)"
)

\(\sigma_v^2\)の推定値(事後平均)は0.02266。少し高くなった。 \(\theta_i\)の推定値は、saeパッケージとほぼ同じだが、MSEの推定値はちょっとずれている。

3.2.4 BayesSAEパッケージによる推定

こんどはBayesSAEパッケージで試してみよう。 MCMCによるHB推定である。

事前分布の指定がデフォルトでどうなっているのか、 マニュアルを読んでもよくわからなかったので、 ソースコードを調べて突き止めた。以下のコードでprior=に与えている リスト これがデフォルトである(従ってprior=オプションを消しても 結果は同じ)。\(\beta\)は無情報事前分布, \(\sigma_v^2\)\((0, 100)\)の一様分布。

set.seed(123)
a.oModel_BayesSAE <- BayesSAE::BayesSAE(
  yi ~ MajorArea|var, 
  data=a.dfMilk, 
  mcmc=20000,
  prior=list(
    beta.type  = "non_in",
    beta.prior = 0,
    sigv.type  = "unif",
    sigv.prior = list(eps2=1e-02)
  )
)
print(summary(a.oModel_BayesSAE))

Call:
BayesSAE::BayesSAE(formula = yi ~ MajorArea | var, prior = list(beta.type = "non_in", 
    beta.prior = 0, sigv.type = "unif", sigv.prior = list(eps2 = 0.01)), 
    mcmc = 20000, data = a.dfMilk)

Basic Fay-Herriort Model 
Sampling model: yi ~ theta
Linking model: theta ~ MajorArea + var + NA

Rao-Blackwellization of theta's based on the simulation:
     1      2      3      4      5      6      7      8      9     10 
1.0257 1.0489 1.0698 0.7530 0.8406 0.9745 1.0672 1.0983 1.2321 1.2044 
    11     12     13     14     15     16     17     18     19     20 
0.7759 1.2266 1.2175 0.9772 1.1861 1.1535 1.2282 1.2932 1.2388 1.2382 
    21     22     23     24     25     26     27     28     29     30 
1.0854 1.1923 1.1175 1.2255 1.1939 0.7646 0.7669 0.7356 0.7716 0.6108 
    31     32     33     34     35     36     37     38     39     40 
0.7751 0.8035 0.7745 0.6088 0.6994 0.7611 0.5250 0.7446 0.7559 0.7721 
    41     42     43 
0.7486 0.8078 0.6790 

Coefficients in the linking model:
           Mean       SD     2.5%  97.5%
beta.1  0.97049  0.07142  0.82950  1.110
beta.2  0.13513  0.10713 -0.06956  0.351
beta.3  0.22345  0.09577  0.03532  0.416
beta.4 -0.24317  0.08397 -0.40953 -0.076

Variance of residual in the linking model:
         Mean       SD     2.5%  97.5
[1,] 0.022241 0.009261 0.008402 0.044

DIC: -28.35111 

\(\sigma_v^2\)の推定値(事後平均)は0.022241。hbsaeのHB推定に近い。

sub_PlotTwoEstimate.1(
  agEst1     = as.vector(a.oModel_saeREML$est$eblup), 
  agMSE1     = a.oModel_saeREML$mse, 
  agEst2     = a.oModel_BayesSAE$HB, 
  agMSE2     = summary(MCMC(a.oModel_BayesSAE))$statistics[1:43,2]^2, 
  asLabel    = a.dfMilk$SmallArea, 
  sVarLabel1 = "sae (REML)", 
  sVarLabel2 = "BayesSAE"
)

\(\theta_i\)の推定値、ならびにMSEの推定値も、hbsaeのHB推定に近いようだ。

3.2.5 nlmeパッケージによる推定

混合モデルの汎用パッケージであるnlmeパッケージで試してみよう。 正規混合モデルの関数lme()を使う。\(\theta_i\)の推定量はEBLUP。 \(\sigma^2_v\)の推定量はデフォルトではREMLになる。

a.oModel_lmeREML <- lme(
  fixed   = yi ~ MajorArea,
  random  = ~ 1 | SmallArea,
  control = lmeControl(sigma = 1, apVar = T),
  weights = varFixed(~var),
  data    = a.dfMilk
)
print(a.oModel_lmeREML)
Linear mixed-effects model fit by REML
  Data: a.dfMilk 
  Log-restricted-likelihood: 10.34588
  Fixed: yi ~ MajorArea 
(Intercept)  MajorArea2  MajorArea3  MajorArea4 
  0.9680768   0.1316132   0.2269008  -0.2415905 

Random effects:
 Formula: ~1 | SmallArea
        (Intercept) Residual
StdDev:   0.1332918        1

Variance function:
 Structure: fixed weights
 Formula: ~var 
Number of Observations: 43
Number of Groups: 43 

lme()関数のweights=varFixed(~ var)で、「グループ内の分散は変数varである」 と指定していることになるのだそうだ(ここでグループとは小地域のことであろう)。 また、control=オプションのうち、sigma=1とは「残差分散を1に固定する」という意味、 apVar = Tとは「分散共分散行列を求める」という意味らしい。 こうすると残差分散は var*1 になる、ということなのかな。

へーこうやって書くのか、勉強になるなあ、と思ったのだが、 よくよくみると、結果がちょっぴりsaeパッケージと異なる。 ここでは\(\sigma_v\)の推定値が 0.1332918 となっている。二乗すると0.0177667。 saeパッケージでは0.01855であった。あれ?ちょっと低いぞ?

実はこの話、nlmeパッケージのバグとして報告されている。 saeパッケージとぴったり合わないのはおかしいのだそうで、これはどうやら nlme側のバグらしい。うわー。まさかそんなことがー。

なお、ML推定を指定した場合の出力は正しいそうだ。

a.oModel_lmeML <- lme(
  fixed   = yi ~ MajorArea,
  random  = ~ 1 | SmallArea,
  control = lmeControl(sigma = 1, apVar = T),
  weights = varFixed(~var),
  method  = "ML",
  data    = a.dfMilk
)
print(a.oModel_lmeML)
Linear mixed-effects model fit by maximum likelihood
  Data: a.dfMilk 
  Log-likelihood: 12.77117
  Fixed: yi ~ MajorArea 
(Intercept)  MajorArea2  MajorArea3  MajorArea4 
  0.9677986   0.1278755   0.2266909  -0.2425804 

Random effects:
 Formula: ~1 | SmallArea
        (Intercept) Residual
StdDev:   0.1245693        1

Variance function:
 Structure: fixed weights
 Formula: ~var 
Number of Observations: 43
Number of Groups: 43 

0.1245693^2 = 0.01551751, saeパッケージでのML推定とほぼ一致する。

sub_PlotTwoEstimate.1(
  agEst1     = as.vector(a.oModel_saeREML$est$eblup), 
  agMSE1     = NULL, 
  agEst2     = predict(a.oModel_lmeML), 
  agMSE2     = NULL, 
  asLabel    = a.dfMilk$SmallArea, 
  sVarLabel1 = "sae (REML)", 
  sVarLabel2 = "nlme (ML)"
)

推定値はsaeパッケージとたいして変わらない。なお、推定量のMSEの推定値のほうは、 nlmeパッケージだけでは出力できず、なにか工夫しないといけない模様である。

3.2.6 rstanパッケージによる推定

最後に、ベイジアン・モデリングのための汎用パッケージrstanで試してみよう。

stanコードはこちら。 わたくし、普段はほぼ使わないので、正直なところ全然自信がないんですが…

// Fay-Herriot model
// cf. https://rdrr.io/github/ssoro411/bayesae/src/R/Models_fast.R

data {
    int<lower=0>        M;      
    int<lower=0>        P;      
    vector[M]           Y;   
    vector<lower=0>[M]  SD;  
    matrix[M,P]         X;   
}

parameters {
    real<lower=0>     sigma;    
    vector[P]         beta;        
    vector[M]         theta;       
}

transformed parameters {
    vector[M] mu;
    mu = X*beta;
}

model {
    theta ~ normal(mu, sigma);
    Y     ~ normal(theta, SD);
}

では実行します…

# a.oStanModel <- stan_model(file="./FH1_vectorized.stan")
# save(a.oStanModel, file="./a.oStanModel.RData")
# 
# load(file = "./a.oStanModel.RData")
# 
# mnModelMatrix <- model.matrix(~ MajorArea, data=a.dfMilk)
# lData <- list(
#   M  = nrow(a.dfMilk),
#   P  = ncol(mnModelMatrix),
#   Y  = a.dfMilk$yi,
#   SD = a.dfMilk$SD,
#   X  = mnModelMatrix
# )
# a.oStanFit   <- sampling(
#   a.oStanModel,
#   data   = lData,
#   seed   = 1234,
#   control = list(adapt_delta = 0.95)
# )
# save(a.oStanFit, file="./a.oStanFit.RData")
load(file = "./a.oStanFit.RData")
stan_trace(a.oStanFit, c("sigma", "theta[28]"), inc_warmup = T)

stan_rhat((a.oStanFit))

\(\sigma_v\)\(\theta_{28}\)のトレースプロット(地域28は推定値のSEがいちばん大きい地域)、 ならびに\(\hat{R}\)のヒストグラムを示す。 余裕で収束している模様。

地域効果の推定値ならびにMSEの推定と、saeパッケージと比較してみると…

lResult <- rstan::extract(a.oStanFit)
agEst <- colMeans(lResult$theta)
agMSE <- apply(lResult$theta, 2, var)
sub_PlotTwoEstimate.1(
  agEst1     = as.vector(a.oModel_saeREML$est$eblup), 
  agMSE1     = a.oModel_saeREML$mse, 
  agEst2     = agEst, 
  agMSE2     = agMSE, 
  asLabel    = a.dfMilk$SmallArea, 
  sVarLabel1 = "sae (REML)", 
  sVarLabel2 = "rstan"
)

推定値のほうはほぼ同じ。MSEは少しずれていて、hbsaeパッケージ(HB推定)や、 BayesSAEパッケージと似ている。

rm(list=grep("^a\\.", ls(), value=T))

3.3 シミュレーション

こうしてみてみると、いろいろ疑問が湧いてくる。わたくしと致しましては、 特に次の3点に関心がある。

  • EBLUPとHBでは地域特性のMSEの推定値が異なる。 同じEBLUPでも、saeパッケージとhbsaeパッケージでは やはり異なる。良いのはどれか。
  • これってスケールするのか。たとえば小地域が10万個あってもちゃんと推定できるのか。
  • 無駄な共変量を投入したらなにが起きるのか。それは推定量によって異なるか。

そこでシミュレーションしてみることにしました。

3.3.1 問題

いま、地域\(i\)(\(=1,\ldots,m\))のひとりひとりの住民\(j\)(\(=1,\ldots,N_i\))が、 量的な反応変数\(y_{ij}\)を持っている。えーっと、幸福度ってことにしましょうか。

地域の母集団サイズ\(N_i\)はいずれも十分に大きい。 各地域の幸福度の母平均\(\bar{Y}_i = \frac{1}{N_i} \sum_j y_{ij}\)について推測したい。 そこで、各地域\(i\)からサイズ\(n_i\)の標本を単純無作為抽出し、 標本平均\(\hat{\bar{Y}}_i = \frac{1}{n_i} \sum_j y_{ij}\), ならびにその分散の推定値 \(\hat{Var}(\hat{\bar{Y}})_i = \frac{1}{n_i(n_i-1)} \sum_j (y_{ij} - \hat{\bar{Y}}_i)\) を求めた。

ところが、地域ごとの標本サイズ\(n_i\)は必ずしも十分でない。 標本平均\(\hat{\bar{Y}}_i\)\(\bar{Y}_i\)の推定量とするのは、いささか心許ない。 さらに、各地域は\(p+1\)個のブロックに分類されており、 ブロックによって幸福度平均\(\bar{Y}_i\)の高さが異なる、 と私は信じている。

そこで私はこう考える。幸福度の標本平均\(\hat{\bar{Y}}_i\)だけでなく、 その地域がどのブロックに属するかという情報もつかって、 各地域の幸福度の母平均\(\bar{Y}_i\)を 推測しよう!

というわけで、Fay-Erriotモデルの登場である。

以下、記号が煩雑になるので、 RM本にあわせて\(\theta_i = \bar{Y}_i\), \(\hat{\theta}_i = \hat{\bar{Y}}_i\)と書く。 また、\(\hat{\psi}_i = \hat{Var}(\hat{\bar{Y}}_i)\)と書く。さらに、 ある地域がどこに分類されるかを、長さ\(p\)の二値ベクトル\(\mathbf{z}_i\)で表す。

おさらいすると、Fay-Herriotモデルは以下の通り。 \[ \hat{\theta}_i = \mathbf{z}^T_i \mathbf{\beta} + v_i + e_i, \ \ v_i \sim (0, \sigma^2_v), \ \ e_i \sim (0, \psi_i) \]

以下では\(v_i\)を地域効果、\(e_i\)を標本抽出誤差と呼ぼう。

3.3.2 データ生成モデル

さて、これから分析用のデータを生成します。

データ生成モデルは次のとおり。\(i=1,\ldots,m\)について、 \[ y_{ij} = 50 + \mathbf{z}^T_i \mathbf{0} + v_i + \epsilon_{ij}, \ \ v_i \mathop{\sim}^{iid} N(0, \sigma^2_v), \ \ \epsilon_{ij} \mathop{\sim}^{iid} N(0,100) \]

つまり、私は知らないのだが、実は

  • (幸福度)=50+(地域効果)+(個人差) である。
  • 地域間で幸福度にばらつきがあり、そのばらつきは正規分布に従っている。
  • 幸福度は地域が属するブロックとは関係がない(\(\mathbf{\beta} = \mathbf{0}\))。
  • 地域内の個人差も正規分布に従っている。どのくらいばらついているかというと、よく学校の成績とかを偏差値で表すけれど(分散は100)、幸福度もまたそのくらいばらついている(分散は100)。

母集団サイズは大きく、\(\epsilon_{ij}\)の母集団平均は 0とみなせるので、結局、知りたい特性\(\theta_i\)はここでは\(v_i\)に等しい。

地域の標本サイズ\(n_i\)は、地域1から地域10まで順に\(10, 20, ..., 100\)とし、 地域11以降もこれを繰り返す。

共変量\(\mathbf{z}_i\)(長さ\(p\))は、地域のブロック(\(p+1\)水準)を表すものとする。 ブロック番号は、地域1から地域\(p+1\)までは順に \(1,...,p+1\)とし、 残りの地域については等確率でランダムに決める。

3.3.3 シミュレーション用の関数

…というデータを生成し分析する、一連の関数を作りました。

### for rstan ...
# b.oStanModel <- stan_model(file="./FH1_vectorized.stan")
# save(b.oStanModel, file="./b.oStanModel.RData")
load(file = "./b.oStanModel.RData")
b.sub_GenerateDataset1.1 <- function(
  nNumArea, nNumGroup, gVarV, gVarE=100, anPossibleN=seq(10, 100, by = 10)
){
  ## purpose: generate a dataset for FH model
  ## arg:
  ##   nNumArea:         number of areas
  ##   nNumGroup:        number of levels of a categorical covariate
  ##   gVarV:            variance of area effects
  ##   anPossibleN:      vector of possible sample size
  ## return:
  ##   a data frame, area level data
  ##   $nArea:       Area ID
  ##   $nSize:       sample size
  ##   $fGroup:      categorical covariate with (nNumGroup) levels
  ##   $gEst_Direct: sample means of a response variable
  ##   $gMSE_Direct: sample est. of variance of sample means
  ##   $gV:          area effect
  
  out <- data.frame(
    nArea      = 1:nNumArea,
    nSize      = rep(anPossibleN, nNumArea %/% length(anPossibleN) + 1)[1:nNumArea],
    fGroup     = factor(
      c(1:nNumGroup, sample(1:nNumGroup, nNumArea - nNumGroup, replace = T)), 
      levels = 1:nNumGroup
    ),
    gV         = 50 + rnorm(n = nNumArea, mean = 0, sd = sqrt(gVarV))
  )
  lError <- lapply(
    out$nSize,
    function(nSize){
      rnorm(n = nSize, mean = 0, sd = sqrt(gVarE))
    }
  )
  out$gEst_Direct  <- out$gV + sapply(lError, mean)
  out$gMSE_Direct  <- sapply(lError, function(x){ var(x) / length(x) })
  out$nTotalSize   <- sum(out$nSize)
  
  return(out)
}
b.sub_GenerateMultiDataset1.1 <- function(nNumDataset=1, ...){
  ## purpose: generate multiple datasets for FH model
  ## arg:
  ##   nNumDataset:      number of data sets
  ##   ...:              pass to sub_GenerateDataset1.1()
  ## return:
  ##   a data frame, area level data
  ##   $nDataset:  Dataset ID
  ##   $...        return from sub_GenerateDataset1.1()
  out <- data.frame(nDataset = 1:nNumDataset) %>%
    group_by(nDataset) %>%
    dplyr::do(b.sub_GenerateDataset1.1(...)) %>%
    ungroup()
  return(out)
}
b.sub_EstimateDatasetByMethod1.1 <- function(
  dfData, sMethod, nTimeOut = 1800, bVerbose=FALSE
){
  ## purpose: estimate FH model for a dataset by a method
  ## arg:
  ##   dfData:   a data set
  ##   sMethod:  {"saeREML", "saeREMLNOMSE", "hbsaeREML", "hbsaeHB", 
  ##              "bayessae", "nlme", "rstan"}
  ##   nTimeOut: time limit
  ##   bVerbose: verbose flag (logical)
  ## return:
  ##   a list
  ## notes:
  ##   - nTimeOut is effective only for hbsaeREML and hbsaeHB
  ##   - rstan requires b.oStanModel in the environment
  ## trap: check sMethod
  stopifnot(
    sMethod %in% c(
      "saeREML", "saeREMLNOMSE", "hbsaeREML", "hbsaeHB", 
      "bayessae", "nlme", "rstan"
    )
  )
  if (bVerbose) cat("[sub_EstimateDataset1.1]", sMethod, "... \n")
  t <- proc.time()
  if (sMethod == "saeREML") {
    oModel <- try(
      mseFH(
        formula = dfData$gEst_Direct ~ dfData$fGroup,
        vardir  = dfData$gMSE_Direct,
        method  = "REML"
      )
    )
    if (!inherits(oModel, "try-error")) {
      agEst <- as.vector(oModel$est$eblup)
      agMSE <- oModel$mse
    }
  }
  if (sMethod == "saeREMLNOMSE") {
    oModel <- try(
      eblupFH(
        formula = dfData$gEst_Direct ~ dfData$fGroup,
        vardir  = dfData$gMSE_Direct,
        method  = "REML"
      )
    )
    if (!inherits(oModel, "try-error")) {
      agEst <- as.vector(oModel$eblup)
      agMSE <- rep(NA, nrow(dfData))
    }
  }
  if (sMethod == "hbsaeREML") {
    oModel <- withTimeout(
      try(
        fSAE.Area(
          dfData$gEst_Direct,
          dfData$gMSE_Direct,
          model.matrix(gEst_Direct ~ fGroup, data = dfData),
          method = "REML",
          silent =  TRUE
        )
      ),
      timeout = nTimeOut
    )
    if (!inherits(oModel, "try-error")) {
      agEst <- EST(oModel)
      agMSE <- SE(oModel)^2
    }
  }
  if (sMethod == "hbsaeHB") {
    oModel <- withTimeout(
      try(
        fSAE.Area(
          dfData$gEst_Direct,
          dfData$gMSE_Direct,
          model.matrix(gEst_Direct ~ fGroup, data = dfData),
          method = "HB",
          silent =  TRUE
        )
      ),
      timeout = nTimeOut
    )
    if (!inherits(oModel, "try-error")) {
      agEst <- EST(oModel)
      agMSE <- SE(oModel)^2
    }
  }
  if (sMethod == "bayessae") {
    oModel <- try(
      BayesSAE(
        gEst_Direct ~ fGroup | gMSE_Direct,
        data = dfData,
        mcmc = 5000
      )
    )
    if (!inherits(oModel, "try-error")) {
      agEst <- oModel$HB
      agMSE <- summary(MCMC(oModel))$statistics[seq_along(dfData$nArea),2]^2
    }
  }
  if (sMethod == "nlme") {
    oModel <- try(
      lme(
        fixed   = gEst_Direct ~ fGroup,
        random  = ~ 1 | nArea,
        control = lmeControl(sigma = 1, apVar = T),
        weights = varFixed(~gMSE_Direct),
        method  = "ML",
        data    = dfData
      )
    )
    if (!inherits(oModel, "try-error")) {
      agEst <- fitted(oModel)
      agMSE <- rep(NA, nrow(dfData))
    }
  }
  if (sMethod == "rstan") {
    ## trap: b.oStanModel is found in the enviroment
    stopifnot(exists("b.oStanModel"))
    mnModelMatrix <- model.matrix(~ fGroup, data = dfData)
    lData <- list(
      M  = nrow(dfData),
      P  = ncol(mnModelMatrix),
      Y  = dfData$gEst_Direct,
      SD = sqrt(dfData$gMSE_Direct),
      X  = mnModelMatrix
    )
    oModel <- try(
      sampling(
        b.oStanModel,
        data   = lData,
        seed   = 1234,
        iter   = 400,
        control = list(adapt_delta = 0.95), 
        open_progress = FALSE, 
        show_messages = FALSE
      )
    )
    if ( !inherits(oModel, "try-error") ) {
       if ( any(summary(oModel)$summary[,"Rhat"] > 1.1) ) {
         oModel <- try(stop("not converged!"))
       }
    }
    if ( !inherits(oModel, "try-error") ) {
      lResult <- rstan::extract(oModel)
      agEst <- colMeans(lResult$theta)
      agMSE <- apply(lResult$theta, 2, var)
    }
  }
  ## common process ...
  if (!inherits(oModel, "try-error")) {
    out <- list(
      sMethod = sMethod,
      bStatus = TRUE,
      agEst   = agEst,
      agMSE   = agMSE,
      gTime   = (proc.time() - t)[3]
    )
    if (bVerbose) cat("[sub_EstimateDataset1.1] Success.", out$gTime, "sec.\n")
  } else {
    out <- list(
      sMethod = sMethod,
      bStatus = FALSE,
      agEst   = rep(NA, nrow(dfData)),
      agMSE   = rep(NA, nrow(dfData)),
      gTime   = (proc.time() - t)[3]
    )
    if (bVerbose) cat("[sub_EstimateDataset1.1] Fail.", out$gTime, "sec.\n")
  }
  return(out)
}
b.sub_EstimateDataset1.1 <- function(
  dfData,
  asMethod=c("saeREML", "hbsaeREML", "hbsaeHB", "bayessae", "nlme", "rstan"), 
  ...
){
  ## purpose: estimate FH model for a dataset by multiple methods
  ## arg:
  ##   dfData:    a dataset
  ##   asMethod
  ##   ...
  ## return:
  ##   a data frame
  lOut <- lapply(
    asMethod,
    function(sMethod){
      lResult <- b.sub_EstimateDatasetByMethod1.1(dfData, sMethod = sMethod, ...)
      out <- data.frame(
        nArea   = dfData$nArea,
        sMethod = rep(lResult$sMethod, nrow(dfData)),
        bStatus = rep(lResult$bStatus, nrow(dfData)),
        gEst    = lResult$agEst,
        gMSE    = lResult$agMSE,
        gTime   = rep(lResult$gTime, nrow(dfData)),
        stringsAsFactors = FALSE
      )
      return(out)
    }
  )
  out <- bind_rows(lOut) %>%
    gather(sVar, gValue, c(bStatus, gEst, gMSE, gTime)) %>%
    mutate(sVar = paste0(sVar, "_", sMethod)) %>%
    dplyr::select(nArea, sVar, gValue) %>%
    spread(sVar, gValue)
  out <- full_join(dfData, out, by = "nArea")
  return(out)
}
b.sub_EstimateMultiDataset1.1 <- function(dfData, ...){
  ## purpose: estimate FH models for multiple datasets by multiple methods
  ## arg:
  ##   dfData:    multiple datasets
  ## return:
  ##   a data frame of multiple results
  out <- dfData %>%
    group_by(nDataset) %>%
    dplyr::do(b.sub_EstimateDataset1.1(., ...)) %>%
    ungroup()
  return(out)
}
b.sub_EstimatorAsFactor.1 <- function(asEstimator){
  ## purpose: convert estimator names into factor
  ## args:
  ##   asEstimator: a character vector of estimator names
  ## return: 
  ##   a factor vector
  
  factor(
    asEstimator, 
    levels = c(
      "True", "Direct", "saeREML", "saeREMLNOMSE", 
      "hbsaeREML", "hbsaeHB", "bayessae", "nlme", "rstan"
    ), 
    labels = c(
      "True", "Direct", "sae(REML)", "sae(REML,noMSE)", 
      "hbsae(REML)", "hbsae(HB)", "BayesSAE", "nlme", "rstan"
    ) 
  )
}
b.sub_EstimatorPalette.1 <- function(afEstimator){
  ## purpose: get consisntent color pallette for estimators
  ## args:
  ##   afEstimator: a factor vector of estimator 
  ## return:
  ##   a vector of color palette
  
  gg_color_hue(9)[sort(unique(as.integer(afEstimator)))]
  
}

3.3.3 データ分析例

ためしに、上記のデータ生成関数とデータ分析関数を使ってみよう。

まずデータ生成。10地域、4ブロック、地域効果の分散は50とする。 地域効果の分散は、地域内の個人差の半分の大きさだ。 結構大きな地域差があるんですね。

## b.dfDemoData: data for demo
set.seed(100)
b.dfDemoData <- b.sub_GenerateDataset1.1(nNumArea=10L, nNumGroup=4L, gVarV=50)
print(b.dfDemoData)

では、このデータについて推定し、次の8個を比較する。

  • True: 真値\(\theta_i\)
  • Direct: 標本平均\(\hat{\theta}_i\)
  • sae(REML): saeパッケージ, EBLUP推定量, \(\sigma_v^2\)をREML推定。
  • hbsae(REML): hbsaeパッケージ, EBLUP推定量, \(\sigma_v^2\)をREML推定。
  • hbsae(HB): hbsaeパッケージ, HB推定量, 数値積分による。
  • BayesSAE: BayesSAEパッケージ, HB推定量, MCMCによる。 なお、mcmcのドロー数は、ちょっと多めに5000にしておいた。
  • nlme: nlmeパッケージのlme関数, EBLUP推定量, \(\sigma_v^2\)をML推定。
  • rstan: rstanパッケージ, HB推定量, MCMCによる。ドロー数400, 全パラメータの \(\hat{R}\)が1.1以下であることを確認する。
dfResult <- b.sub_EstimateDataset1.1(b.dfDemoData) %>%
  dplyr::select(nArea, nSize, gV, starts_with("gEst_"))
dfPlot <- dfResult %>%
  dplyr::select(nArea, gV, starts_with("gEst_")) %>%
  rename(gEst_True = gV) %>%
  gather(sVar, gValue , starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sVar2")) %>%
  mutate(fEstimator = b.sub_EstimatorAsFactor.1(sVar2))
g <- ggplot(
  data=dfPlot,
  aes(x=as.factor(nArea), y=gValue, group=fEstimator, color=fEstimator)
)
g <- g + geom_path(size=1)
g <- g + labs(
  x     = "area",
  y     = expression(paste(theta, " or ", hat(theta))),
  color = "Estimator"
)
g <- g + scale_color_manual(values = b.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

縦軸は真値ないし推定値である。

たとえば地域1の正解は56.3点。標本平均は59.2点, 正解よりもかなり高めになってしまった (地域1の標本サイズは10しかない)。 しかるに、saeパッケージの推定値は57.5点。標本平均よりも正解に近くなっている。

もっとも、この結果はたまたまかもしれない。 同じことを何度も繰り返してみないと、なんともいえない。

3.3.4 標本サイズ vs. 推定の精度

おまたせしました。なんども繰り返してみます。

先程と同じく、10地域、4ブロック、地域効果の分散は50とする。 500回繰り返してみた。40分ほどかかりました。

# set.seed(123456)
# dfData <- b.sub_GenerateMultiDataset1.1(
#   nNumDataset = 500, nNumArea = 10L, nNumGroup = 4L, gVarV = 50
# )
# b.dfSimulation1 <- b.sub_EstimateMultiDataset1.1(dfData)
# save(b.dfSimulation1, file="./b_dfSimulation1.RData")
load("./b_dfSimulation1.RData")

500回中1回、rstanが収束しなかった試行 (いずれかのパラメータの\(\hat{R}\)が1.10を上回わった試行)があった。 これは反復数が足りなかったせいだと思うので、 公平を期するため、以下では1試行まるごと除外する。つまり、他の推定量による 推定結果も除外する。

1) 推定値

推定値はどのくらいあてになるか、調べてみよう。 おそらく、地域の標本サイズ\(n_i\)が小さいとき、推定値は正解からずれてしまうだろうから、 \(n_i\)別に見る必要がありそうだ。

dfPlot <- b.dfSimulation1 %>%
  filter(!is.na(gEst_rstan)) %>%
  dplyr::select(nSize, gV, starts_with("gEst_")) %>%
  gather(sVar, gEst, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  mutate(
    gDiff      = gEst - gV, 
    fEstimator = b.sub_EstimatorAsFactor.1(sEstimator)
  ) 
g <- ggplot(data=dfPlot, aes(x = nSize, y=gDiff, color=fEstimator))
g <- g + geom_point(alpha=1/5)
g <- g + labs(
  x     = "Sample Size",
  y     = expression(hat(theta)-theta),
  color = "Estimator"
)
g <- g + geom_hline(yintercept = 0)
g <- g + scale_x_continuous(breaks=seq(10, 100, by = 20))
g <- g + scale_color_manual(
  guide=FALSE, 
  values = b.sub_EstimatorPalette.1(dfPlot$fEstimator)
)
g <- g + facet_grid(~ fEstimator)
g <- g + theme_bw()
print(g)

縦軸は、推定値と正解との差を表している。 やはり、標本サイズが小さいときに、正解からのずれが大きくなる。

推定方法 x 標本サイズ別に、推定値と正解との差を集計してみよう。

dfPlot <- b.dfSimulation1 %>%
  filter(!is.na(gEst_rstan)) %>%
  dplyr::select(nSize, gV, starts_with("gEst_")) %>%
  gather(sVar, gEst, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  group_by(sEstimator, nSize) %>%
  summarize(
    nFreq = n(),
    gRMSE = sqrt(mean((gEst - gV)^2))
  ) %>%
  ungroup() %>%
  mutate(fEstimator = b.sub_EstimatorAsFactor.1(sEstimator)) 
g <- ggplot(data=dfPlot, aes(x = nSize, y=gRMSE, group=fEstimator, color=fEstimator)) 
g <- g + geom_path(size=1)
g <- g + labs(x = "Sample Size", y = "observed RMSE", color="Estimator")
g <- g + scale_x_continuous(breaks=seq(10, 100, by = 10))
g <- g + scale_color_manual(values = b.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

縦軸は「推定値と正解との差の二乗の平均の平方根」(RMSE)を示す。平たく言っちゃうと、 推定した地域平均は、真の地域平均からだいたい何点くらいずれるか、を示している。

標本サイズが10のときには、だいたい3点くらいずれてしまう。 標本サイズが大きくなると、ずれは小さくなる。

ここで関心があるのは推定方法の間の差だ。 上のチャートだと差を読み取れないので描き直そう。

### observed RMSE / theoretical RMSE of Direct
dfPlot <- b.dfSimulation1 %>%
  filter(!is.na(gEst_rstan)) %>%
  dplyr::select(nSize, gV, starts_with("gEst_")) %>%
  gather(sVar, gEst, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  group_by(sEstimator, nSize) %>%
  summarize(
    gRMSE = sqrt(mean((gEst - gV)^2))
  ) %>%
  ungroup() %>%
  mutate(
    gRatio     = gRMSE / sqrt(100/nSize),
    fEstimator = b.sub_EstimatorAsFactor.1(sEstimator)
  )
g1 <- ggplot(data=dfPlot, aes(x = nSize, y=gRatio, group=fEstimator, color=fEstimator))
g1 <- g1 + geom_path(size=1)
g1 <- g1 + geom_hline(yintercept = 1)
g1 <- g1 + labs(
  x     = "Sample Size",
  y     = "(observed RMSE)/(theoretical RMSE of Direct)",
  color = "Estimator"
)
g1 <- g1 + scale_color_manual(values = b.sub_EstimatorPalette.1(dfPlot$fEstimator))
g1 <- g1 + scale_x_continuous(breaks=seq(10, 100, by = 10))
g1 <- g1 + theme_bw()
print(g1)

### (observed RMSE) / (observed RMSE of Direct)
# dfTemp <- b.dfSimulation1 %>%
#   filter(!is.na(gEst_rstan)) %>%
#   dplyr::select(nSize, gV, starts_with("gEst_")) %>%
#   gather(sVar, gEst, starts_with("gEst_")) %>%
#   separate(sVar, c("sVar1", "sEstimator")) %>%
#   group_by(sEstimator, nSize) %>%
#   summarize(
#     gRMSE = sqrt(mean((gEst - gV)^2))
#   ) %>%
#   ungroup() 
# dfTemp.1 <- dfTemp %>% filter(sEstimator != "Direct")
# dfTemp.2 <- dfTemp %>% 
#   filter(sEstimator == "Direct") %>% 
#   rename(gRMSE_Direct = gRMSE) %>%
#   dplyr::select(-sEstimator)
# dfPlot <- full_join(dfTemp.1, dfTemp.2, by = "nSize") %>%
#   mutate(
#     gRatio     = gRMSE / gRMSE_Direct,
#     fEstimator = b.sub_EstimatorAsFactor.1(sEstimator)
#   )
# g1 <- ggplot(data=dfPlot, aes(x = nSize, y=gRatio, group=fEstimator, color=fEstimator))
# g1 <- g1 + geom_path(size=1)
# g1 <- g1 + geom_hline(yintercept = 1)
# g1 <- g1 + labs(
#   x     = "Sample Size",
#   y     = "(RMSE)/(RMSE of Direct)",
#   color = "Estimator"
# )
# g1 <- g1 + scale_x_continuous(breaks=seq(10, 100, by = 10))
# g1 <- g1 + scale_color_manual(values = b.sub_EstimatorPalette.1(dfPlot$fEstimator))
# g1 <- g1 + theme_bw()
# print(g1)
g2 <- ggplot(
  data=dfPlot %>% filter(nSize == 10),
  aes(x = fEstimator, y = gRatio, color=fEstimator)
)
g2 <- g2 + geom_point(size=5)
g2 <- g2 + geom_hline(yintercept = 1)
g2 <- g2 + labs(
  x     = "Estimator",
  y     = "(observed RMSE)/(theoretical RMSE of Direct), size=10"
)
g2 <- g2 + scale_color_manual(
  guide = FALSE, 
  values = b.sub_EstimatorPalette.1(dfPlot$fEstimator)
)
g2 <- g2 + theme_bw()
print(g2)

# grid.arrange(g1, g2, ncol = 2)

さきほど求めたRMSEはデータから得たものだが、 標本抽出誤差は実は100なので、これを既知とするならば、 標本平均のRMSEは\(\sqrt{100/n_i}\)である。 上の2枚の図の縦軸は、この理屈上の値を基準に、それぞれの推定方法による推定値の RMSEを比で表している(つまり、長い目でみれば標本平均(Direct)の折れ線は 縦軸1の位置の水平線になるはずで、そうなっていないのは運の問題である)。 下にいくほど、推定値と真の値のずれが小さい。

上の図は全地域。下の図は標本サイズ10の地域のみ拡大している。

以下の点がみてとれる。

  • nlmeパッケージの推定値は真値とのずれが大きい。 RMSEが標本平均より大きいわけで、 「小地域モデルを使った推定なんてしなきゃよかった」という事態である。 理由はよくわからない…
  • nlmeを別にすれば、HB推定, EBLUP推定, 標本平均の順にずれが小さい。 標本サイズが大きくなると、HBとEBLUPの差は縮まり、さらに標本平均との差も縮まる。

2) MSEの推定値

こんどはMSEの推定値について調べてみよう。

推定量のMSEとは、「仮にある推定値を得て、その値を真の値と比べることができるなら、 差の二乗の期待値がどうなるか」という値である。 この実験では真の値が分かっているのだから、 推定値と真値の差の二乗そのものが手に入る。この実績を、 推定されたMSEと比べてみようではないか。

dfPlot <- b.dfSimulation1 %>%
  filter(!is.na(gEst_rstan)) %>%
  dplyr::select(nDataset, nArea, nSize, gV, starts_with("gEst_"), starts_with("gMSE_")) %>% 
  gather(sVar, gValue, c(starts_with("gEst_"), starts_with("gMSE_"))) %>%
  separate(sVar, c("sVar", "sEstimator")) %>%
  spread(sVar, gValue) %>%
  filter(sEstimator != "nlme") %>%
  mutate(
    gDiff      = gMSE - (gEst - gV)^2,
    fEstimator = b.sub_EstimatorAsFactor.1(sEstimator)
  )
g <- ggplot(data=dfPlot, aes(x = nSize, y = gDiff, color = fEstimator)) 
g <- g + geom_point(alpha=1/5)
g <- g + labs(
  x = "Sample Size", 
  y = "(Estimated MSE)-(Actual Sq.Err)"
)
g <- g + geom_hline(yintercept = 0)
g <- g + scale_x_continuous(breaks=seq(10, 100, by = 20))
g <- g + facet_grid(~ fEstimator)
g <- g + scale_color_manual(values = b.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

縦軸は、「推定されたMSEから、推定値と正解との差の二乗を引いた値」である。 縦軸が0だということは、 推定値と正解との間にはずれがあったかもしれないが、そのずれの大きさは予想通りだった、 ということを表している。正の値は「思ったよりずれなかった」つまり MSEが過大に推定されていたことを表し、 負の値は「思ったよりずれた」つまりMSEが過小に推定されていたことを表す。 なお、nlmeパッケージがないのは、すでに述べたように、 nlmeパッケージがEBLUP推定量のMSEの推定を提供していないからである。

標本サイズが小さい時、MSEの推定は 過小だったり過大だったりしやすくなることが見て取れる。

では、推定方法 x 標本サイズ別に、MSEが過小・過大だった程度について調べてみよう。

dfPlot <- b.dfSimulation1 %>%
  filter(!is.na(gEst_rstan)) %>%
  dplyr::select(nSize, gV, starts_with("gEst_"), starts_with("gMSE_")) %>%
  gather(sVar, gValue, c(starts_with("gEst_"), starts_with("gMSE_"))) %>%
  separate(sVar, c("sVar", "sEstimator")) %>%
  spread(sVar, gValue) %>%
  filter(sEstimator != "nlme") %>%
  mutate(
    gDiff    = gMSE - (gEst - gV)^2
  ) %>% 
  group_by(sEstimator, nSize) %>%
  summarize( gMeanDiff = mean(gDiff) ) %>%
  ungroup() %>%
  mutate( fEstimator = b.sub_EstimatorAsFactor.1(sEstimator) ) 
g <- ggplot(data=dfPlot, aes(x = nSize, y=gMeanDiff, group=fEstimator, color=fEstimator)) 
g <- g + geom_path(size=1)
g <- g + scale_x_continuous(breaks=seq(10, 100, by = 10))
g <- g + geom_hline(yintercept = 0)
g <- g + labs(
  x     = "Sample Size", 
  y     = "mean( (Estimated MSE)-(Actual Sq.Err) )",
  color = "Estimator"
)
g <- g + scale_color_manual(values = b.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

縦軸は、「推定されたMSEから、推定値と正解との差の二乗を引いた値」の平均である。 正の値はMSEの推定が概して過大であること、負の値は概して過小であることを表す。

全体的なでこぼこは運の問題として、 ここで注目したいのは推定方法間の差である。よくみると、標本サイズが10のとき、 EBLUP推定のMSEの推定が過小であることが見て取れる。 とくにhbsaeパッケージのEBLUP推定は過小となる程度が大きく、標本サイズが20, 30のときにも やや過小になっている。

EBLUP推定のMSEの推定が過小になるのは、 EBLUP推定では(1)いったん\(\hat{\sigma^2_v}\)の点推定値を求め、 (2)これを使って\(\theta_i\)を推定する、という方法を取っているからだと思う。 つまり、本当は\(\hat{\sigma^2_v}\)にも分散があるのだが、それを無視しているわけで、 その分MSEが過小評価されるのだ… という理解で、あってますかね?

3.3.4 地域数 vs. 推定の精度

さきほどは地域の数を10に固定していた。これが多くなったらどうなるか?

さきほどと同じく、4ブロック、地域効果の分散は50とし、 地域の数を10, 100, 200, 300と動かしながら、 500回づつ繰り返してみよう。

なお、このシミュレーションはすごく時間がかかるので、nlmeパッケージと rstanパッケージは省略した。

# set.seed(123)
# lOut <- lapply(
#   c(10, 100, 200, 300),
#   function(nNumArea){
#     cat("nNumArea = ", nNumArea, "...\n")
#     dfData   <- b.sub_GenerateMultiDataset1.1(
#       nNumDataset = 500, nNumArea = nNumArea, nNumGroup = 4L, gVarV = 50
#     )
#     dfResult <- b.sub_EstimateMultiDataset1.1(
#       dfData, 
#       asMethod = c("saeREML", "hbsaeREML", "hbsaeHB", "bayessae")      
#     )
#     dfResult$nNumArea <- nNumArea
#     cat("\n")
#     return(dfResult)
#   }
# )
# b.dfSimulation2 <- bind_rows(lOut) %>%
#   filter(nArea == 1)
# save(b.dfSimulation2, file="./b_dfSimulation2.RData")
load("./b_dfSimulation2.RData")

なお、以下では標本サイズが10である地域だけに注目する。 また、条件間で分析件数を揃えるために、地域番号1だけに限定して分析する。 各条件において500件の推定結果が使えるわけである。

1) 推定値

地域数 x 推定方法別に、推定値と正解とのずれを集計してみよう。

dfPlot <- b.dfSimulation2 %>%
  dplyr::select(nNumArea, gV, starts_with("gEst_")) %>%
  gather(sVar, gEst, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  group_by(sEstimator, nNumArea) %>%
  summarize(
    nFreq = n(),
    gRMSE = sqrt(mean((gEst - gV)^2))
  ) %>%
  ungroup() %>%
  mutate(
    fEstimator = b.sub_EstimatorAsFactor.1(sEstimator) # ,
    # fNumArea = factor(nNumArea, levels=c(10, 100, 200, 300))
  )
g <- ggplot(data=dfPlot, aes(x = nNumArea, y=gRMSE, group=fEstimator, color=fEstimator))
g <- g + geom_path(size=1)
g <- g + scale_x_continuous(breaks = c(0, 10, 100, 200, 300))
g <- g + labs(x = "Num. Area", y = "observed RMSE", color="Estimator")
g <- g + scale_color_manual(values = b.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

さきほど同様、縦軸は「推定値と正解との差の二乗の平均の平方根」(RMSE)を示している。 さきほど確認したように、地域数10の場合には、だいたい3点くらいずれる。 そのずれは、HB推定, EBLUP推定, 標本平均の順に小さい。

さて、上の図からは、地域数が増えるとHB推定とEBLUP推定におけるずれがさらに小さくなる ことがわかる。また、 HB推定とEBLUP推定の間の差は消失し、標本平均との差が広がる。

なるほど、小地域モデルによる推定は、いわば他の地域から 情報を借りてくるようなものだから、他の地域の数が大きいほうがより有利になるのだろう。

2) MSEの推定値

こんどは、地域数 x 推定方法別に、MSEの推定が 過小・過大だった程度について調べてみよう。

dfPlot <- b.dfSimulation2 %>%
  dplyr::select(nNumArea, gV, starts_with("gEst_"), starts_with("gMSE_")) %>%
  gather(sVar, gValue, c(starts_with("gEst_"), starts_with("gMSE_"))) %>%
  separate(sVar, c("sVar", "sEstimator")) %>%
  spread(sVar, gValue) %>%
  mutate(
    gTrueSE = (gEst - gV)^2, 
    gDiff   = gMSE - gTrueSE 
  ) %>% 
  group_by(sEstimator, nNumArea) %>%
  summarize(
    gMeanDiff = mean(gDiff)
  ) %>%
  ungroup() %>%
  mutate(
    fEstimator = b.sub_EstimatorAsFactor.1(sEstimator) #,
    # fNumArea = factor(nNumArea, levels=c(10, 100, 200, 300))
  ) 
g <- ggplot(
  data=dfPlot, 
  aes(x = nNumArea, y=gMeanDiff, group=fEstimator, color=fEstimator)
)
g <- g + geom_path(size = 1)
g <- g + geom_hline(yintercept = 0)
g <- g + scale_x_continuous(breaks = c(0, 10, 100, 200, 300))
g <- g + labs(
  x     = "Num. Area", 
  y     = "mean ((Estimated MSE) - (Actual Sq.Err))",
  color = "Estimator"
)
g <- g + scale_color_manual(values = b.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

例によって、縦軸は「推定されたMSEから推定値と正解との差の二乗を引いた値」の平均である。 正の値はMSEの推定が概して過大であること、負の値は概して過小であることを表す。

すでに、地域数10で標本サイズが10のとき、EBLUP推定(特にhbsaeパッケージ)で MSEが過小評価されるということがわかった。 しかし上の図からは、それは地域数が少ないときの話であって、 地域数が多ければ気にしなくてよいということがわかる。

3.3.4 共変量の数 vs. 推定の精度

ここでちょっと変な実験を試してみる。

ここまでは、地域レベルの共変量として、地域のブロック(4水準のカテゴリ変数)を投入していた。 いいかえると、3つの二値変数を共変量として投入していた。

実は、地域のブロックは幸福度と無関係である。つまり、 真の係数\(\mathbf{\beta}\)\(\mathbf{0}\)である。でも分析者は そのことに気づいていないわけである。

この共変量の数が減ったら、また増えたら、何が起きるだろうか。

変なことに関心を持つと思われるかもしれないけれど、個人的には ちょっと切実な疑問なんです。だって、共変量というものは、往々にして 意味があるのかないのかわからないものじゃないですか。

  • 係数の推定値が0に近い共変量であっても、ぴったり0ってことは ないですよね? その真値は0ではないかもしれない。 それを投入することには実はわずかな意味があるのかもしれない。 そう考えると、いっけん意味がなさそうな共変量であっても、 取り除くのにはなかなか勇気がいる。
  • いっぽうで、もし意味のない共変量を入れてしまったら、無駄なパラメータを推測する羽目になり、 そのせいで地域特性の推定値の分散は大きくなるかもしれない。 そう考えると、やはり係数の推定値が0に近い共変量は、 勇気をもって取り除くべきなのかもしれない。うーむ、悩む…

というわけで、意味のない共変量をうっかり投入したときの弊害というのはどんなものなのか、 それは推定量によって違うのか、ひとつ調べてみたいものだと思ったわけです。

地域数は10とし、ブロックの数を2から5まで動かしながら、 500回繰り返す。 nlmeパッケージとrstanパッケージは省略した。

# set.seed(123)
# lOut <- lapply(
#   c(2, 3, 4, 5),
#   function(nNumGroup){
#     cat("nNumGroup = ", nNumGroup, "...\n")
#     dfData   <- b.sub_GenerateMultiDataset1.1(
#       nNumDataset = 500, nNumArea = 10, nNumGroup = nNumGroup, gVarV = 50
#     )
#     dfResult <- b.sub_EstimateMultiDataset1.1(
#        dfData,
#        asMethod = c("saeREML", "hbsaeREML", "hbsaeHB", "bayessae")      
#     )
#     dfResult$nNumGroup <- nNumGroup
#     cat("\n")
#     return(dfResult)
#   }
# )
# lOut <- lapply(
#   lOut,
#   function(dfIn){
#     dfIn$fGroup <- as.integer(dfIn$fGroup)
#     return(dfIn)
#   }
# )
# b.dfSimulation3 <- bind_rows(lOut) %>%
#   filter(nSize == 10)
# save(b.dfSimulation3, file="./b_dfSimulation3.RData")
load("./b_dfSimulation3.RData")

ここでも、標本サイズが10である地域だけに注目する。 各条件において500件の推定結果が使える。

1) 推定値

ブロックの数 x 推定方法別に、推定値と正解とのずれを集計してみよう。

dfPlot <- b.dfSimulation3 %>%
  dplyr::select(nNumGroup, gV, starts_with("gEst_")) %>%
  gather(sVar, gEst, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  group_by(sEstimator, nNumGroup) %>%
  summarize(
    nFreq = n(),
    gRMSE = sqrt(mean((gEst - gV)^2))
  ) %>%
  ungroup() %>%
  mutate(
    fEstimator = b.sub_EstimatorAsFactor.1(sEstimator),
    fNumGroup  = factor(nNumGroup, levels=2:5)
  )
g <- ggplot(
  data=dfPlot, 
  aes(x = fNumGroup, y=gRMSE, group=fEstimator, color=fEstimator)
)
g <- g + geom_path(size=1)
g <- g + labs(
  x = "Num. Blocks", 
  y = "observed RMSE", 
  color = "Estimator"
)
g <- g + scale_color_manual(values = b.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

ブロックの数が少ない、つまり共変量が少ないほうが、 推定値は真値に近づく。えっ、こんなに違うの…

2) MSEの推定値

ブロックの数 x 推定方法別に、MSEの推定が過小・過大だった程度について調べてみる。

dfPlot <- b.dfSimulation3 %>%
  dplyr::select(nNumGroup, gV, starts_with("gEst_"), starts_with("gMSE_")) %>%
  gather(sVar, gValue, c(starts_with("gEst_"), starts_with("gMSE_"))) %>%
  separate(sVar, c("sVar", "sEstimator")) %>%
  spread(sVar, gValue) %>%
  mutate(
    gTrueSE = (gEst - gV)^2, 
    gDiff   = gMSE - gTrueSE 
  ) %>% 
  group_by(sEstimator, nNumGroup) %>%
  summarize(
    gMeanDiff = mean(gDiff)
  ) %>%
  ungroup() %>%
  mutate(
    fEstimator = b.sub_EstimatorAsFactor.1(sEstimator),
    fNumGroup  = factor(nNumGroup, levels=2:5)
  ) 
g <- ggplot(data=dfPlot, aes(x = fNumGroup, y=gMeanDiff, group=fEstimator, color=fEstimator))
g <- g + geom_path(size=1)
g <- g + geom_hline(yintercept = 0)
g <- g + labs(
  x     = "Num. Blocks", 
  y     = "mean ((Estimated MSE) - (Actual Sq.Err))", 
  color = "Estimator"
)
g <- g + scale_color_manual(values = b.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

ブロック数5のときにちょっと高くなっている理由がよくわかんないんだけど、 ブロック数を2から3に増やすと、MSEが過小評価されていることがわかる。 無駄な共変量は、MSEの過小評価にもつながるようだ…

3.3.5 地域数 vs. 計算時間

最後に、地域数と計算にかかる時間との関連について調べてみる。

100地域, 1,000地域, 10,000地域, 100,000地域の5通りについて、 5回ずつためしてみた。

ここでは、以下の推定方法を試す。

  • sae(REML): saeパッケージ, EBLUP推定量, \(\sigma_v^2\)をREML推定。
  • sae(REML,noMSE): saeパッケージ, EBLUP推定量, \(\sigma_v^2\)をREML推定, MSEを算出しない。
  • hbsae(REML): hbsaeパッケージ, EBLUP推定量, \(\sigma_v^2\)をREML推定。
  • hbsae(HB): hbsaeパッケージ, HB推定量, 数値積分による。
  • BayesSAE: BayesSAEパッケージ, HB推定量, MCMCによる。 mcmcのドロー数は10000。
  • nlme: nlmeパッケージ, EBLUP推定量, \(\sigma_v^2\)をML推定。

なお、

  • rstanは法外に時間がかかることがわかっているので、省略した。
  • 10,000地域以上の場合は、saeパッケージは省略した。すごく時間がかかるため。 いちど10,000地域で試したら、MSEを算出してもしなくても1800秒くらいかかった。
  • 100,000地域の場合は、BayesSAEパッケージは省略した。 何度か試したところ、そのたびにメモリが足りないというエラーが出たから。
  • 100,000地域の場合、hbsaeパッケージはエラーになることが多い。 下の実験の場合は5回中5回エラーとなった。
# set.seed(12345)
# lOut <- lapply(
#   c(100,1000,10000,100000),
#   function(nNumArea){
#     cat("nNumArea = ", nNumArea, "...\n")
# 
#     cat("generate data ...\n")
#     dfData   <- b.sub_GenerateMultiDataset1.1(
#       nNumDataset = 5, nNumArea = nNumArea, nNumGroup = 4L, gVarV = 50
#     )
# 
#     asMethod <- c(
#       "saeREML", "saeREMLNOMSE", "hbsaeREML", "hbsaeHB", "bayessae", "nlme"
#     )
#     ## sae takes too long with nNumArea >= 10000
#     if (nNumArea >= 10000){
#        asMethod <- asMethod[!(asMethod %in% c("saeREML", "saeREMLNOMSE"))]
#     }
#     ## BayesSAE raises out-of-memory error with nNumArea >= 100000
#     if (nNumArea >= 100000){
#        asMethod <- asMethod[asMethod != "bayessae"]
#     }
# 
#     dfResult <- b.sub_EstimateMultiDataset1.1(
#       dfData, asMethod = asMethod, bVerbose = TRUE
#     ) %>%
#       filter(nArea == 1) %>%
#       mutate(nNumArea = nNumArea)
#     cat("\n")
#     return(dfResult)
#   }
# )
# b.dfSimulation4 <- bind_rows(lOut)
# save(b.dfSimulation4, file="./b_dfSimulation4.RData")
load(file="./b_dfSimulation4.RData")
 

一回あたりの計算時間は下図となった。

dfPlot1 <- b.dfSimulation4 %>%
  dplyr::select(nNumArea, nDataset, starts_with("gTime_"), starts_with("bStatus_")) %>%
  gather(sVar, gValue, c(starts_with("gTime_"), starts_with("bStatus_"))) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  spread(sVar1, gValue) %>%
  filter(bStatus == 1) %>%
  mutate(
    fEstimator = b.sub_EstimatorAsFactor.1(sEstimator),
    fNumArea = factor(
      nNumArea,
      levels = c(100,1000,10000,100000),
      labels = c("100","1000","10000","100000")
    )
  )
dfPlot2 <- dfPlot1 %>%
  group_by(fNumArea, fNumArea, fEstimator) %>%
  summarize(gTime = mean(gTime)) %>%
  ungroup() 
g <- ggplot(data=dfPlot2, aes(x = fNumArea, y=gTime, fill=fEstimator))
g <- g + geom_col()
g <- g + geom_point(data=dfPlot1, aes(x = fNumArea, y = gTime), size=1, alpha=1/10)
g <- g + labs(y = "Mean time (sec)", x = "Num.Area", fill="Estimator")
g <- g + scale_fill_manual(guide=FALSE, values = b.sub_EstimatorPalette.1(dfPlot1$fEstimator))
g <- g + facet_grid(~ fEstimator)
g <- g + theme_bw()
g <- g + theme(axis.text.x = element_text(angle = -90, hjust = 0, vjust = 0.3)) 
print(g)

MCMCで推定しているBayesSAEパッケージが遅くなるのは わかるんだけど、不思議なのはsaeパッケージである。 MSEを算出してもしなくても、 地域数がある程度大きくなると急激に時間を食うようになる。

地域数が10万を超えるようなケースでは、hbsaeパッケージでEBLUP推定するか、 MSEは出せないけどnlmeパッケージのlme()を使うのが速そうだ。 lme()の推定精度が悪かった(3.3.4)ことを考えると、 hbsaeパッケージによるEBLUP推定が最善手であろう。

ここだけの話、このシミュレーションが今回の最大の発見でありました。 これまでsaeパッケージだけで悪戦苦闘していたのはなんだったのか…

3.3.6 まとめ

このシミュレーションでわかったことをまとめておく。

  • 標本サイズが小さい時、地域特性の推定値は、HB推定、EBLUP推定, 標本平均の順に真値に近い。 ただし、地域数が多いときは、HB推定、EBLUP推定が標本平均を引き離し、より有利、 かつ同程度に有利になる。 なお、標本サイズが大きければ、いずれも真値に近くなる。
  • 標本サイズが小さく地域数が小さいとき、 地域特性の推定値のMSEの推定は、EBLUP推定において過小になる。 特に、hbsaeパッケージのEBLUP推定で過小になる。
  • 意味のない共変量は取り除いたほうがよい。
  • 地域数がすごく多いときは、hbsaeパッケージのEBLUP推定を使うとよい
rm(list=grep("^b\\.", ls(), value=T))

4. 地域レベル空間モデル

4.1 空間Fay-Herriotモデルとは

(この項はRM本4.4.4節, 8.4節に基づく。)

おさらいすると、Fay-Herriotモデルは以下の通りであった。 \[ \hat{\theta}_i = \mathbf{z}^T_i \mathbf{\beta} + v_i + e_i, \ \ v_i \sim (0, \sigma^2_v), \ \ e_i \sim (0, \psi_i) \] ところで、上の\(v_i\)の式はこう書き換えることができる。 \(\mathbf{v} = (v_1, \ldots, v_m)^T\)として、 \[ \mathbf{v} \sim (0, \mathbf{\Gamma}), \ \ \mathbf{\Gamma} = \sigma_v^2 \mathbf{I} \]

\(\mathbf{\Gamma}\)\(m \times m\)の行列で、\(i\)\(j\)列目の要素が、 地域\(i\)\(j\)の共分散を表す。Fay-Herriotモデルの 場合は、すべての対角成分に\(\sigma_v^2\) が入っており、すべての非対角成分に\(0\)がはいる(地域効果\(v_i\)は地域間で 独立だと考えているから)。

このように、Fay-Herriotモデルでは、 地域効果\(v_i\)は地域間で独立だと考えていた。 でも実際には、 地域の間には隣接関係があり、隣り合う地域のあいだでは地域効果が似ている ことが多い。こうした空間相関を考慮すれば、 地域特性をもっと正確に推測できるかもしれない。

そこで、\(\mathbf{\Gamma}\)の非対角成分が0でないと考える。 地域効果\(\mathbf{v}\)が、地域間の空間的な隣接関係とどのように関連しているかを モデル化し、このモデルに基づいて、\(\mathbf{\Gamma}\)がどういう形式になっている かを規定する。これが空間Fay-Herriotモデルである。

推定の方法には、Fay-Herriotモデルと同様、EBLUP推定, HB推定などがある。

では、共分散行列\(\mathbf{\Gamma}\)をどのように規定するか。 代表的なアプローチが2つある。

4.1.1 SAR (同時自己回帰) モデル

いきなり\(\mathbf{v}\)の同時分布をモデル化するアプローチ。

次のように考える。 \[ \mathbf{v} = \phi \mathbf{W} \mathbf{v} + \mathbf{u}, \ \ \mathbf{u} \sim N(\mathbf{0}, \sigma_u^2 \mathbf{I}) \] つまりこういうことだ。オリジナルのFay-Herriotモデルでは、 地域\(i\)の地域効果\(v\)は、平均0, 分散\(\sigma_v^2\)のなんらかの分布に従う ランダムな効果だと想定していた。 いっぽうこのモデルでは、地域\(i\)の地域効果\(v_i\)は次のふたつの要素の 和だと想定する。

  • その地域自体のランダムな効果。平均0, 分散\(\sigma_v^2\)の正規分布に従う。
  • 他の地域から受ける効果の合計。地域\(j\)からは効果\(\phi w_{ij} v_j\)を受ける。

この\(w_{ij}\)を行列の形に並べたのが\(\mathbf{W}\)である。この\(\mathbf{W}\)は 地域間の隣接関係を表現している行列で、分析者が指定する。

以上の想定はこういう風に書き換えることができる。 \[ \mathbf{v} = (\mathbf{I}-\phi \mathbf{W})^{-1} \mathbf{u}, \ \ \mathbf{u} \sim N(\mathbf{0}, \sigma_u^2 \mathbf{I}) \] ここから、\(\mathbf{v}\)の分布は \[ \mathbf{v} \sim N(0, \mathbf{\Gamma}), \ \ \mathbf{\Gamma} = \sigma_v^2[(\mathbf{I}-\phi \mathbf{W})(\mathbf{I}-\phi \mathbf{W})^T]^{-1} \] となる。空間相関を考慮しないFay-Herriotモデルでは\(\sigma_v^2\)を推定する必要があったが、 ここではそのかわりに\(\sigma_u^2\)\(\phi\)を推定する必要がある。

ここで鍵になるのは、隣接行列\(\mathbf{W}\)の定義である。 通常は次のように定義する。

  1. まず、地域\(i\), \(j\)が隣接しているときに\(w_{ij}=1\)、 そうでないときに\(w_{ij}=0\)とする。
  2. こうしてできた\(\mathbf{W}\)を各行について合計し、 その行の値を合計で割る(つまり、各行の合計が1になるようにする)。

このとき、\(\phi \in (0,1)\)となる。このときの\(\phi\)空間自己相関パラメータという。

4.1.2 CAR (条件付き自己回帰) モデル

\(\mathbf{v}\)の同時分布ではなく、 他のエリア\(\{v_l: l \neq i\}\)の下での、\(v_i\)の条件つき分布を モデル化する、というアプローチである。

各地域\(i\)は既知の定数\(b_i\)を持っているとする(典型的には1とする)。 次のように考える。地域\(i\)の「近接」地域の集合を\(A_i\)として \[ b_i v_i | \{v_l: l \neq i\} \sim N \left( \rho \sum_{l \in A_l} q_{il} b_l v_l, b_i^2 \sigma_v^2 \right) \] ここで\(\{q_{il}\}\)は既知の定数で、\(q_{il}b_l^2 = q_{li} b_i^2\)を満たす。 典型的には、\(l \in A_i\)のとき\(q_{il} = q_{li} = 1\)とする。

つまりこういうことだ。オリジナルのFay-Herriotモデルでは、 地域\(i\)の地域効果\(v_i\)は、平均0, 分散\(\sigma_v^2\)のなんらかの分布に従う ランダムな効果だと想定していた。 いっぽうこのモデルでは、なぜだか知らないが、\(v_i\)は隣接地域の 地域効果が固定されたときに、次のように正規分布する、と想定する。

  • その平均は、隣接する他の地域\(l\)の地域効果\(b_l v_l\)を、重み\(q_{il}\)を つけて足し上げ, \(\rho\)倍した値である。
  • その分散は\(b_i^2 \sigma_v^2\)である。

ここから、\(\mathbf{\Gamma}\)を規定する次式が得られる。 \(b_1^2, \ldots, b_m^2\)を持つ対角行列を\(\mathbf{B}\)とし、 すべての\(q_{il}\)を持つ\(m \times m\)行列(近接じゃないところと対角は0にする)を \(\mathbf{Q}\)として \[ \mathbf{B}^{1/2} \mathbf{v} \sim N_m(\mathbf{0}, \mathbf{\Gamma}) \] \[ \Gamma = \sigma^2_v(\mathbf{I} - \rho \mathbf{Q})^{-1} \mathbf{B} \] 空間相関を考慮しないFay-Herriotモデルでは\(\sigma_v^2\)を推定する必要があったが、 ここでは\(\sigma_v^2\)\(\rho\)を推定する必要がある。

4.1.3 SARモデルとCARモデルの比較

前項まででは、空間Fay-Herriotモデルにおいて空間相関を規定するための2つの モデル(SARモデルとCARモデル)を取り上げた。

なんだか難しいので、すごく単純な具体例で考えてみよう。

いま地域が4つあり、地域1と2, 2と3, 3と4が隣接しているとする。 SARモデルとCARモデルでは、空間相関はどのように規定されるか。

まず隣接行列について。 SARモデルの場合、隣接行列\(\mathbf{W}\)は次のように定義されることが多い。 各行の和が1になっている点に注意。

  e.mgProx_unstd <- matrix(0, nrow=4, ncol=4)
  e.mgProx_unstd[1,2] <- 1
  e.mgProx_unstd[2,3] <- 1
  e.mgProx_unstd[3,4] <- 1
  e.mgProx_unstd[2,1] <- 1
  e.mgProx_unstd[3,2] <- 1
  e.mgProx_unstd[4,3] <- 1
  e.mgProx_std <- sweep(e.mgProx_unstd, 1, rowSums(e.mgProx_unstd), "/")
  print(e.mgProx_std)
     [,1] [,2] [,3] [,4]
[1,]  0.0  1.0  0.0  0.0
[2,]  0.5  0.0  0.5  0.0
[3,]  0.0  0.5  0.0  0.5
[4,]  0.0  0.0  1.0  0.0

いっぽうCARモデルの場合、隣接行列\(\mathbf{Q}\)は次のように定義されることが多い。 隣接する地域間のみ1, ほかを0として

  print(e.mgProx_unstd)
     [,1] [,2] [,3] [,4]
[1,]    0    1    0    0
[2,]    1    0    1    0
[3,]    0    1    0    1
[4,]    0    0    1    0

次に地域効果の定義について。

SARモデルの場合は下式のように定義される。

\[ v_1 = \phi v_2 + u_1, \ \ u_1 \sim N(0, \sigma_u^2) \] \[ v_2 = \phi (0.5 v_1 + 0.5v_3) + u_2, \ \ u_2 \sim N(0, \sigma_u^2) \] \[ v_3 = \phi (0.5v_2 + 0.5v_4) + u_3, \ \ u_3 \sim N(0, \sigma_u^2) \] \[ v_4 = \phi v_3 + u_4, \ \ u_4 \sim N(0, \sigma_u^2) \]

ここから、\(\mathbf{v}\)の分布は \[ \mathbf{v} \sim N(0, \mathbf{\Gamma}), \ \ \mathbf{\Gamma} = \sigma_v^2[(\mathbf{I}-\phi \mathbf{W})(\mathbf{I}-\phi \mathbf{W})^T]^{-1} \]

となる。

いっぽうCARモデルの場合は、すべての\(b_i\)を1とすれば

\[ v_1 | v_2 \sim N(\rho v_2, \sigma_v^2) \] \[ v_2 | \{ v_1, v_3\} \sim N(\rho (v_1+v_3), \sigma_v^2) \] \[ v_3 | \{ v_2, v_4\} \sim N(\rho (v_2+v_4), \sigma_v^2) \] \[ v_4 | v_3 \sim N(\rho v_3, \sigma_v^2) \]

これを同時分布に書き直すと \[ \mathbf{v} \sim N(\mathbf{0}, \mathbf{\Gamma}), \ \ \mathbf{\Gamma} = \sigma^2_v(\mathbf{I} - \rho \mathbf{Q})^{-1} \]

となる。

では、共分散行列\(\mathbf{\Gamma}\)をくらべてみよう。 SARモデルの場合、\(\sigma_u^2=1, \phi=0.5\)のとき

  mbUnit <- diag(rep(1,4))
  e.mgCov2 <- solve( (mbUnit - 0.5 * e.mgProx_std) %*% t(mbUnit - 0.5 * e.mgProx_std) )
  print(e.mgCov2)
          [,1]     [,2]     [,3]      [,4]
[1,] 1.4419753 1.145679 0.454321 0.1580247
[2,] 1.1456790 2.093827 1.106173 0.4543210
[3,] 0.4543210 1.106173 2.093827 1.1456790
[4,] 0.1580247 0.454321 1.145679 1.4419753

CARモデルの場合、\(\sigma_v^2=1, \rho=0.5\)のとき

  e.mgCov1 <- solve(diag(rep(1,4)) - 0.5 * e.mgProx_unstd)
  print(e.mgCov1)
     [,1] [,2] [,3] [,4]
[1,]  1.6  1.2  0.8  0.4
[2,]  1.2  2.4  1.6  0.8
[3,]  0.8  1.6  2.4  1.2
[4,]  0.4  0.8  1.2  1.6

となる。

相関行列に直してみると, SARモデルは

  mgCor <- sweep(e.mgCov2, 1, sqrt(diag(e.mgCov2)), "/")
  mgCor <- sweep(mgCor, 2, sqrt(diag(e.mgCov2)), "/")
  print(mgCor)
          [,1]      [,2]      [,3]      [,4]
[1,] 1.0000000 0.6593464 0.2614649 0.1095890
[2,] 0.6593464 1.0000000 0.5283019 0.2614649
[3,] 0.2614649 0.5283019 1.0000000 0.6593464
[4,] 0.1095890 0.2614649 0.6593464 1.0000000

CARモデルは

  mgCor <- sweep(e.mgCov1, 1, sqrt(diag(e.mgCov1)), "/")
  mgCor <- sweep(mgCor, 2, sqrt(diag(e.mgCov1)), "/")
  print(mgCor)
          [,1]      [,2]      [,3]      [,4]
[1,] 1.0000000 0.6123724 0.4082483 0.2500000
[2,] 0.6123724 1.0000000 0.6666667 0.4082483
[3,] 0.4082483 0.6666667 1.0000000 0.6123724
[4,] 0.2500000 0.4082483 0.6123724 1.0000000

このように、SARモデルとCARモデルは、定式化は全く異なるものの、 空間相関についての規定は、結局それほど変わらない。 いずれのモデルでも、

  • 地域効果の分散は、隣接地域が多い地域で高いと規定される。上の 例では、地域1,2,3,4の分散は、SARモデルでは1.44, 2.09, 2.09, 1.44であり、 CARモデルでは1.60, 2.40, 2.40, 1.60である。
  • モデルのうえでは隣接地域との関係しか定式化されていないにも関わらず、 結局は、離れた地域の間にも弱い相関があると規定される。 たとえば上の例で、地域1と4の間の相関は、 SARモデルは0.11, CARモデルでは0.25である。
rm(list=grep("^e\\.", ls(), value=T))

4.2 実習: grapes

かんたんなデータについて、空間Fay-Herriotモデルを推定してみよう。

4.2.1 データ

saeパッケージについているサンプルデータ grapes を使う。 イタリアはトスカーナ地方の224自治体についてのデータで、以下の変数を 持っている。

  • grapehect: ブドウ畑の平均面積(ヘクタール)の直接推定値。
  • area: ブドウ畑の総面積(ヘクタール)。
  • workdays: 「2000年の平均労働日数(average number of working days)」。 えええ? 言ってる意味がわかんないんだけど… 最小で22.15, 最大で497.68である。
  • var: 標本抽出分散の直接推定値。
### c.dfGrapes
data(grapes)
c.dfGrapes <- grapes %>%
  mutate(
    nAreaID = seq_along(grapehect),
    SE = sqrt(var)
  )
rm(grapes)
### c.mgProx_std: row-standardized neighbor matrix
data(grapesprox)
c.mgProx_std <- as.matrix(grapesprox)
rm(grapesprox)
colnames(c.mgProx_std) <- as.character(1:ncol(c.mgProx_std))
rownames(c.mgProx_std) <- as.character(1:nrow(c.mgProx_std))
## print(c.mgProx_std)
### c.mbProx_unstd: unstandardized neighbor matrix
c.mbProx_unstd <- c.mgProx_std
c.mbProx_unstd[c.mbProx_unstd > 0] <- 1
## print(c.mbProx_unstd)
summary(c.dfGrapes %>% dplyr::select(-c(nAreaID, SE)))
   grapehect             area            workdays     
 Min.   :  0.2478   Min.   :  35.81   Min.   : 22.15  
 1st Qu.: 38.9887   1st Qu.: 205.24   1st Qu.:104.94  
 Median : 60.3268   Median : 443.42   Median :138.25  
 Mean   : 69.5096   Mean   : 639.16   Mean   :149.61  
 3rd Qu.: 85.7415   3rd Qu.: 830.28   3rd Qu.:178.59  
 Max.   :342.9919   Max.   :2890.13   Max.   :497.68  
      var           
 Min.   :     0.00  
 1st Qu.:    25.97  
 Median :   211.52  
 Mean   :  2588.58  
 3rd Qu.:  1105.37  
 Max.   :102745.66  

データを散布図行列で観察してみよう。 なお、varはみにくいので平方根をとって標準誤差(SE)にする。

ggpairs(
  c.dfGrapes %>% dplyr::select(grapehect, area, workdays, SE), 
  progress = FALSE, 
  aes(alpha = 1/10)
)

平均面積の直接推定量grapehectは、総面積areaと弱い相関があり、 謎の地域特性workdaysと比較的強い相関がある。 またSEとも正の相関がある(それはそうなるだろう。広い畑が多い自治体の ほうが、面積のばらつきも大きくなるだろうから)。

このデータに付随して、地域間隣接行列grapesproxも提供されている。 左上の8行8列だけ、ちらっとみてみると…

print(c.mgProx_std[1:8,1:8])
     1         2         3         4         5         6         7
1 0.00 0.3333333 0.3333333 0.0000000 0.0000000 0.0000000 0.0000000
2 0.25 0.0000000 0.0000000 0.2500000 0.0000000 0.0000000 0.2500000
3 0.50 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000 0.0000000
4 0.00 0.3333333 0.0000000 0.0000000 0.3333333 0.0000000 0.3333333
5 0.00 0.0000000 0.0000000 0.1428571 0.0000000 0.1428571 0.1428571
6 0.00 0.0000000 0.0000000 0.0000000 0.5000000 0.0000000 0.0000000
7 0.00 0.2000000 0.0000000 0.2000000 0.2000000 0.0000000 0.0000000
8 0.20 0.2000000 0.2000000 0.0000000 0.0000000 0.0000000 0.2000000
          8
1 0.3333333
2 0.2500000
3 0.5000000
4 0.0000000
5 0.0000000
6 0.0000000
7 0.2000000
8 0.0000000

こんな感じ。各行の合計が1になっている。

隣接行列を眺めていても全然面白くない。地図をみたいんだけど、あいにく 提供されていない。仕方がないので、地域をノード、隣接をリンクにした グラフを描いてみた。

sub_ShowAreaGraph1.1 <- function(
  mgProx, agSizeVar, agColorVar, sPal="OrRd"
){
  g <- graph.adjacency(mgProx, mode="undirected")
  V(g)$size  <- agSizeVar
  V(g)$color <- smoothPalette(agColorVar, pal=sPal)
  set.seed(122)
  par(mar=c(0,0,0,0))
  plot(
    g, 
    vertex.label.color  = "black", 
    vertex.label.family = "mono", 
    vertex.label.cex    = 0.5, 
    margin = -0.15
  )
}
sub_ShowAreaGraph1.1(
  c.mbProx_unstd, c.dfGrapes$area/120, c.dfGrapes$grapehect
)

円の大きさはブドウ畑総面積、 色の濃さはブドウ畑平均面積(色が濃い地域は平均面積が広い)。 なお、位置はソフトが適当に決めており、あまり意味がない。

グラフの左側に孤立した地域群があるけど、これは 島かなにかかなあ、とイタリアの地図を調べてみた。

グラフと見比べてみると、グラフ左側の孤立した地域群は、ポルト・フェライロという 島なんじゃないかと思うが、他の箇所については全く対応がわからない。うーむ、残念。 でもまあ、 色の濃い地域が隣接しているということがわかったのでよしとしよう。

地理には全く疎く、海外旅行もしないつまらない男なので、全然見当がつかないんですけど、 トスカーナ地方というのは、北はこの地図の左上のラ・スペツィアというあたりから、 南は地図の下側のオルベテッロというあたりまで、イタリア半島の西側の一帯を占める 州なのだそうだ。

イタリア政府観光局様によれば、 「糸杉が連なる美しい丘陵地帯は、世界遺産のヴァル・ドルチャをはじめ、 世界的に有名な大変美しいトスカーナの自然景観で、 街々を移動する間も旅行者の目を楽しませてくれ」るのだそうである。 州都はフィレンツェ。あ、それ知ってる!須賀敦子の本に出てくるよね!

写真を眺めていたら、人生どこで間違えたんだろうかと、 だんだん辛くなってきたので、話をもとに戻して…

4.2.2 空間自己相関指標

さきほどのグラフによれば、ブドウ畑の平均面積は、どうやら隣接している 地域間で似ているようであった。 こういう性質を空間自己相関という。

空間自己相関の強さはどのくらいだろうか。 RM本の内容からは離れるが、いくつか指標を求めてみよう。

空間自己相関の指標には大きく分けて2種類ある。

その1、グローバルな指標。つまり、全ての地域を通じた空間自己相関の 指標。その代表選手が、MoranのI統計量である。 地域\(i\)の値を\(x_i\), 地域\(i\)\(j\)のあいだの 隣接関係を表す重みを\(w_{ij}\)として、 \[ I = \frac{m}{\sum_i \sum_k w_{ij}} \frac{ \sum_i \sum_j w_{ij} (x_i-\bar{x})(x_j - \bar{x}) }{ \sum_i (x_i - \bar{x})^2 } \] この指標は、空間自己相関がないときに\(-1/(m-1)\)に近づく。

計算してみよう。\(w_{ij}\)を4.1で述べた重みとすると、

moran.test(c.dfGrapes$grapehect, mat2listw(c.mgProx_std, style="W"))

    Moran I test under randomisation

data:  c.dfGrapes$grapehect  
weights: mat2listw(c.mgProx_std, style = "W")    

Moran I statistic standard deviate = 6.2334, p-value = 2.282e-10
alternative hypothesis: greater
sample estimates:
Moran I statistic       Expectation          Variance 
      0.233579488      -0.003663004       0.001448550 

I=0.23、弱い正の空間自己相関がある。

その2, ローカルな指標。隣接地域と似ているのはどの地域かを調べる ために使う。その代表選手はMoranのローカルI統計量で、 これはグローバルな\(I\)を各地域に分解する。つまり、 各地域について値が得られ、その合計はグローバルな\(I\)に一致する。 \[ I_i = \frac{m}{\sum_i \sum_k w_{ij}} \frac{ (x_i-\bar{x})\sum_j w_{ij} (x_j - \bar{x}) }{ \sum_i (x_i - \bar{x})^2 } \] 計算してみよう。

mgLocalMoran <- localmoran(
  c.dfGrapes$grapehect, 
  mat2listw(c.mgProx_std, style="W")
)
sub_ShowAreaGraph1.1(
  c.mbProx_unstd, c.dfGrapes$area/120, mgLocalMoran[,1], sPal = "Blues"
)

隣接地域との空間相関が高い地域を濃い青にしてみた。中央に、 青色が濃い地域が固まっている。さっきの図に戻ってみると、 これらはブドウ畑平均面積が広い地域である。

4.2.3 saeパッケージによる推定

(本節はRM本8.11節の再現である。)

ブドウ畑平均面積をsaeパッケージで推定してみよう。

saeパッケージでは、SARモデルに基づく 空間Fay-Herriotモデルを推定できる。 地域特性はEBLUP推定。 \(\sigma_u^2\)\(\phi\)の推定量はデフォルトではREMLとなる。

saeパッケージは空間Fay-Herriotモデルの関数として次の4つの関数を提供している。 いずれも地域特性の推定は同じで、MSEの扱いが異なる。

  • eblupSFH(): 推定量のMSEを推定しない。
  • mseSFH(): 推定量のMSEを解析的に推定する。
  • pbmseSFH(); 推定量のMSEをパラメトリック・ブートストラップ法で推定する。
  • npbmseSFH(): 推定量のMSEをノンパラメトリック・ブートストラップ法で推定する。

ここではmseSFH()を使うことにする。

まず、切片項を抜いたモデルを推定する。 ブドウ畑総面積areaとブドウ畑平均面積の散布図をみてみると、 回帰直線は原点を通りそうだから、という理由であろう。 RM本のモデルもそうなってますし(p.266), saeパッケージのmseSFH()のマニュアルのコード例でもそうなってます。

oModel <- mseSFH(
  formula = grapehect ~ area + workdays - 1 , 
  vardir  = var, 
  proxmat = c.mgProx_std, 
  data    = c.dfGrapes
)
cat(
  "refvar:",      oModel$'est'$fit$refvar,       
  "\nspatialcorr:", oModel$'est'$fit$spatialcorr, "\n"
)
refvar: 69.74899 
spatialcorr: 0.6142697 

\(\sigma_u^2\)は69.7, \(\phi\)は0.61と推定された。 … あれ? RM本p.266とまったく同じコードなのに、値がかなりちがう (RM本では71.189, 0.583)。なぜだ???

これは私のパソコンがおかしいわけではなくて、 FAO統計部の傘下にあるらしき組織による テクニカル・レポート での解説でも、私の出力と同じ値になっている(p.41)。うーむ…

とかなり思い悩んだんだけど、途中で気が付きました。切片項を抜くのをやめてみると

### c.oModel_saeREML
c.oModel_saeREML <- mseSFH(
  formula = grapehect ~ area + workdays , 
  vardir  = var, 
  proxmat = c.mgProx_std, 
  data    = c.dfGrapes
)
cat(
  "refvar:",      c.oModel_saeREML$'est'$fit$refvar,       
  "\nspatialcorr:", c.oModel_saeREML$'est'$fit$spatialcorr, "\n"
)
refvar: 71.1893 
spatialcorr: 0.5826043 
print(c.oModel_saeREML$'est'$fit$estcoef)

\(\sigma_u^2\)は71.189, \(\phi\)は0.583。 RM本の出力と一致しました。やれやれ。

このように、RM本はコード例と出力が矛盾しているわけだ。 では、どっちを採用するべきか。ここでは切片項を入れるほうを採用する。 「平均面積は総面積とworkdaysの線形和になる」というのは なんだか変なモデルだと思うので。

さて、グラフの色を、このモデルによる推定値に描き変えると…

sub_ShowAreaGraph1.1(c.mbProx_unstd, c.dfGrapes$area/120, c.oModel_saeREML$'est'$eblup)

色の濃さがちょっと変わった。たとえば、中心の色の濃いノード(地域173)の左上にある、 地域187の色がちょっと薄くなっている。

さて、地域特性の推定値は、空間相関を考慮するかどうかによっても変わるし、 どんな共変量を使うかによって変わる。次の5種類を比べてみよう。

  • direct: 直接推定(おそらくは標本平均)。
  • none: Fay-Herriotモデルによる推定(EBLUP), 共変量なし。
  • area: Fay-Herriotモデルによる推定(EBLUP), 共変量は総面積。
  • area+workdays: Fay-Herriotモデルによる推定(EBLUP), 共変量は総面積とworkdays。
  • area+workdays+spatialcoor: 空間Fay-Herriotモデルによる推定(EBLUP), 共変量は総面積とworkdays。
### c.oModel_saeREML_{nox, area, areaworkday}
c.oModel_saeREML_nox <- mseFH(
  formula = grapehect ~ 1, 
  vardir  = var, 
  data    = c.dfGrapes
)
c.oModel_saeREML_area <- mseFH(
  formula = grapehect ~  area , 
  vardir  = var, 
  data    = c.dfGrapes
)
c.oModel_saeREML_areaworkday <- mseFH(
  formula = grapehect ~  area + workdays, 
  vardir  = var, 
  data    = c.dfGrapes
)

モデルの適合度を調べてみると…

lModel <- list(
  c.oModel_saeREML_nox, 
  c.oModel_saeREML_area, 
  c.oModel_saeREML_areaworkday, 
  c.oModel_saeREML
)
dfTemp <- data.frame(
  Estimator = c("none", "area", "area+workdays", "area+workdays+spatialcorr"), 
  AIC       = sapply(lModel, function(oModel) oModel$est$fit$goodness[2]), 
  BIC       = sapply(lModel, function(oModel) oModel$est$fit$goodness[3]), 
  stringsAsFactors = FALSE
)
print(dfTemp)

AIC, BICいずれも、空間Fay-Herriotモデルが最小となった。

推定結果は下図の通り。

c.dfResult_saeREML <- c.dfGrapes %>%
  mutate(
    gEst_1 = as.vector(c.oModel_saeREML_nox$est$eblup),
    gEst_2 = as.vector(c.oModel_saeREML_area$est$eblup),
    gEst_3 = as.vector(c.oModel_saeREML_areaworkday$est$eblup),
    gEst_4 = as.vector(c.oModel_saeREML$est$eblup),
    gMSE_3 = c.oModel_saeREML_areaworkday$mse,
    gMSE_4 = c.oModel_saeREML$mse
  ) %>%
  mutate(nArea = seq_along(grapehect)) 
dfPlot <- c.dfResult_saeREML %>%
  arrange(-var) %>%
  top_n(30, var) %>%  # attention!!!!
  mutate(
    fArea = factor(seq_along(nArea), labels = as.character(nArea))
  ) %>%
  rename(gEst_0 = grapehect) %>%
  gather(sVar, gValue, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sVar2")) %>%
  mutate(
    fModel = factor(
      as.integer(sVar2),
      levels=0:4,
      labels=c("direct", "none", "area", "area+workdays", "area+workdays+spatialcorr")
    )
  )
g <- ggplot(data=dfPlot, aes(x=fArea, y=gValue, group=fModel, color=fModel))
g <- g + geom_path(size=1)
g <- g + labs(x = "AreaID", y = expression(hat(theta)), color="Model")
g <- g + theme_bw()
print(g)

標本抽出分散が大きい地域(つまり、おそらくは標本サイズが小さかった地域) を30個選んで示す。 横軸は地域で、標本抽出分散の大きさで並べている。地域187は左から4番目にある。

推定値は、共変量としてworkdaysを投入したことによって 大きく変わり、空間相関を考慮してもしなくてもあまり変わっていない。 これはこの30地域に限ったことではなくて…

sub_PlotTwoEstimate.1(
  agEst1     = as.vector(c.dfResult_saeREML$gEst_3), 
  agMSE1     = as.vector(c.dfResult_saeREML$gMSE_3), 
  agEst2     = as.vector(c.dfResult_saeREML$gEst_4), 
  agMSE2     = as.vector(c.dfResult_saeREML$gMSE_4), 
  asLabel    = c.dfResult_saeREML$nArea, 
  sVarLabel1 = "area+workdays", 
  sVarLabel2 = "area+workdays+spatialcoor"
)

左側のパネルは各地域の推定値を表している。 横軸は空間相関を考慮していない場合、縦軸は考慮した場合。たいして変わっていない。

では、わざわざ空間Fay-Herriotモデルなんて使わなくてよかったんじゃないか? というと、これがそうでもない。右側は各地域の推定値のMSEの推定値を表している。 空間相関を考慮した場合のほうがMSEの推定値が下がっている。つまり、 もともとブドウ畑平均面積は隣接する自治体で似ているという傾向があるので、 それを考慮することで、推定値の精度を高めに見積もることができたわけだ。

4.2.4 BayesSAEパッケージによる推定

こんどはBayesSAEパッケージ。

BayesSAEパッケージはCARモデルによる空間Fay-Herriotモデルを推定できる… はずである。推定量はHB。推定方法はMCMC。

では推定してみよう…と試みたところで、 ドツボにはまりました。

延々時間をかけた末、以下のことがわかった。

  • BayesSAEパッケージの場合、formulaで切片項を除外することができない。 下のコード例で、grapehect ~ 0 + area + workdays | var と書こうものなら、 mcmc=の値をどんなに小さくしても、処理が終わらない。
  • set.seed()しても結果は再現されない。つまり、set.seed()であるシード値を与え、 その直後に実行する、というのを繰り返したとしても、 実行するたびに結果が変わってしまう。想像するに、内部でCのライブラリを呼んでいて、 そこでの乱数のシードはR上のシードとは別なのではなかろうか。
  • 固まる。実に頻繁に固まる。エラーメッセージのひとつもないまま、いつまで待っても処理が 終わらなくなってしまう。mcmc=の値を大きくすると確実に固まるし、小さくしても かなりの確率で固まる。で、Rを強制終了し、全く同じコード(set.seed()も同じ)を もう一度実行すると、今度はしれっと動いたりする。ぶひー。

Rの再起動を繰り返しながら何度も試したなかで、運よく結果が得られたケースを 示す。mcmc=500。

# dfTemp <- expand.grid(
#   nRow = 1:nrow(c.mbProx_unstd),
#   nCol = 1:ncol(c.mbProx_unstd)
# ) 
# dfTemp$gValue <- c.mbProx_unstd[as.matrix(dfTemp)]
# mbTemp <- dfTemp %>%
#    filter(gValue > 0, nRow < nCol) %>%
#    dplyr::select(nRow, nCol) %>%
#    as.matrix(.)
# 
# set.seed(13)
# c.oModel_BayesSAE <- BayesSAE(
#   grapehect ~ area + workdays | var,
#   data    = c.dfGrapes,
#   spatial = TRUE,
#   prox    = mbTemp,
#   mcmc    = 500,
#   burnin  = 250
# )
# save(c.oModel_BayesSAE, file="./c_oModel_BayesSAE.RData")
load(file="./c_oModel_BayesSAE.RData")
summary(c.oModel_BayesSAE)

Call:
BayesSAE(formula = grapehect ~ area + workdays | var, spatial = TRUE, 
    prox = mbTemp, mcmc = 500, burnin = 250, data = c.dfGrapes)

CAR Area-Level Fay-Herriot Model 
Sampling model: grapehect ~ theta
Linking model: theta ~ area + workdays with spatial random effect

Rao-Blackwellization of theta's based on the simulation:
       1        2        3        4        5        6        7        8 
 31.1089  69.6696  73.8351  63.1305  38.9171  78.5383  49.6683  41.2826 
       9       10       11       12       13       14       15       16 
111.1351  10.2331  79.9256  78.4572  60.6078  52.3993  59.1869  69.0589 
      17       18       19       20       21       22       23       24 
103.4756  42.1818  34.9507  73.1143  71.6234  82.8210  60.2036  65.6269 
      25       26       27       28       29       30       31       32 
 69.5191  59.0232  76.5645  15.8110   2.0183 130.3570  34.4952  21.6494 
      33       34       35       36       37       38       39       40 
 15.0136  63.6233  60.2669  91.5382  54.9043  41.7187  82.4428  57.9240 
      41       42       43       44       45       46       47       48 
  0.6297  97.5886  77.6175  38.9341  16.9809 139.6731  48.8367  52.5079 
      49       50       51       52       53       54       55       56 
 29.1266  78.4874  65.3626  37.9817  59.7702  39.2380  19.6406  95.0978 
      57       58       59       60       61       62       63       64 
 74.3208  58.6386  57.5934  41.4696  96.3495  66.7592  80.4993  52.3589 
      65       66       67       68       69       70       71       72 
 38.8288  62.9432  45.9401  42.2684  43.9611  49.1812  77.7751  62.4326 
      73       74       75       76       77       78       79       80 
 35.1562  74.2700  53.7352  86.4640 101.7038  52.5921  44.5070  32.9756 
      81       82       83       84       85       86       87       88 
144.3330  77.3188  88.7806  73.9564  52.1338  51.2183  24.3714  57.3625 
      89       90       91       92       93       94       95       96 
 36.2671  26.7954  29.0365  38.4890 162.4122  31.4012  48.4079  95.9136 
      97       98       99      100      101      102      103      104 
 46.4321  46.8414  68.3132  71.2937  70.9937  50.5978 106.7134  59.2189 
     105      106      107      108      109      110      111      112 
 37.9505  54.3702  29.9997  45.5565  48.4020  83.2776  29.5474  98.5622 
     113      114      115      116      117      118      119      120 
 94.9086  75.5132  80.4144  63.5484  63.1694  60.2385  51.2838  66.7885 
     121      122      123      124      125      126      127      128 
 39.0232  35.9737  72.3765  60.0282  52.7013  44.1830  26.9104  63.9960 
     129      130      131      132      133      134      135      136 
115.4749  56.6792 118.7125  55.8009  61.2699 127.7067  38.8180  44.6875 
     137      138      139      140      141      142      143      144 
 55.9713  51.1405  63.5967  54.4470 151.9690  66.3482  70.7935  44.9629 
     145      146      147      148      149      150      151      152 
 67.6876  19.3465  73.1860  34.1474  81.6416  25.1924  54.2336  73.8958 
     153      154      155      156      157      158      159      160 
 71.9959  77.8823  39.0749  72.3258  33.4203 111.5003  43.4258  78.4384 
     161      162      163      164      165      166      167      168 
 58.2105  69.9291  89.3437 144.1329 141.5826  59.0028  32.9067  55.4793 
     169      170      171      172      173      174      175      176 
 74.1697 108.5298  76.2338  69.2812 218.3891 121.7793  19.9590  51.8617 
     177      178      179      180      181      182      183      184 
 62.9212  34.1808  33.3153  51.0139  52.6428  52.4443  88.4668  60.0182 
     185      186      187      188      189      190      191      192 
 72.9722  67.1534 168.9997  78.2465  87.9143 107.0522  86.4187  22.8224 
     193      194      195      196      197      198      199      200 
 28.5026  48.0452  68.5629  66.8568  18.0972  53.7315  84.2729 102.6104 
     201      202      203      204      205      206      207      208 
 36.2346  26.8451  52.4201  88.5696  55.4012  25.8781  50.3355  43.7183 
     209      210      211      212      213      214      215      216 
 97.2438  60.0605  76.1216  51.1254  68.3506 119.0295  51.7719  29.9704 
     217      218      219      220      221      222      223      224 
 37.8990  52.2895  96.8565  99.2800  49.6618  54.4060  39.7284  96.7855 
     225      226      227      228      229      230      231      232 
 75.5608 118.1376  57.9896 225.7792  81.1546  89.0848  91.3760  60.7030 
     233      234      235      236      237      238      239      240 
 47.3624  67.2553  42.3490 108.5470  55.3341  50.5188  85.9824  75.5469 
     241      242      243      244      245      246      247      248 
 49.0319  57.2949  34.9818  29.5782  32.9417  54.5701  32.2340  63.4536 
     249      250      251      252      253      254      255      256 
 16.0221  43.8043  40.6643  87.8827  46.4739  61.5904 114.4208 168.8226 
     257      258      259      260      261      262      263      264 
 58.3548 107.0767  89.7515  43.8791  93.2973  67.8464  80.2149  42.8581 
     265      266      267      268      269      270      271      272 
 53.6011 157.5936 119.6216 124.7967 111.2727  46.2415  52.2796  85.2828 
     273      274 
 88.1354  25.7205 

Coefficients in the linking model:
            Mean        SD      2.5%  97.5%
beta.1 -3.947019  3.551080 -8.655680  2.854
beta.2 -0.011854  0.002403 -0.016726 -0.007
beta.3  0.516320  0.021010  0.478431  0.557

Variance of residual in the linking model:
      Mean    SD  2.5% 97.5
[1,] 404.3 654.7 156.7 2092

DIC: 2231.764 
sub_PlotTwoEstimate.1(
  agEst1     = as.vector(c.oModel_saeREML$est$eblup),
  agMSE1     = c.oModel_saeREML$mse,
  agEst2     = c.oModel_BayesSAE$HB,
  agMSE2     = summary(MCMC(c.oModel_BayesSAE))$statistics[1:nrow(c.dfGrapes),2]^2,
  asLabel    = c.dfGrapes$nAreaID,
  sVarLabel1 = "sae (REML)",
  sVarLabel2 = "BayesSAE"
)

… まあとにかく、パッケージを世に送り出す開発者の方には感謝しておりますが、 BayesSAEパッケージで空間Fay-Herriotモデルを推定するのは、現状かなり怖いな、 と思う次第である。

4.2.5 rstanによる推定

SARモデルについて、今度はrstanでやってみよう。 SARモデルはベイズ推定との相性があまりよくないようなのだが、 推定できないわけじゃないらしい。

まずstanコード。以下ではテキストとして示すが、 本物はファイルになっている。 正直、全然自信がないのですが…

// Spatial Fay-Herriot model (SAR)
// cf. https://rdrr.io/github/ssoro411/bayesae/src/R/Models_fast.R

data {
  int<lower=1>                  M;
  int<lower=0>                  P;
  vector[M]                     Y; 
  vector<lower=0>[M]            SD;
  matrix<lower=0, upper=1>[M,M] W;
  matrix[M,P]                   X;
}

transformed data {
  matrix[M,M] unit;
  unit = diag_matrix(rep_vector(1,M));
}

parameters {
  real<lower=-0.99999, upper=0.99999> rho;   
  real<lower=0>  sigma_sq;                   
  vector[P]      beta;                       
  vector[M]      theta;                      
}

model {
  theta ~ multi_normal_prec(X*beta, (1/sigma_sq)*((unit-rho*(W))*(unit-rho*(W'))) );
  // slower
  // theta ~ multi_normal_prec( X*beta, (1/sigma_sq)*crossprod(unit-rho*(W)) ) ; 
  Y ~ normal(theta, SD);
}

Rコードは以下。ふだんはMplusの忠実な信者で、stanにあまり慣れてないもので、 これが速いのか遅いのかわからないのだが、PCを6時間くらい 唸らせる羽目になった。

# c.oStanModel <- stan_model(file="./SFH1.stan")
# save(c.oStanModel, file="./c.oStanModel.RData")
# load(file = "./c.oStanModel.RData")
 
# mgModelMatrix <- model.matrix(~ area + workdays, data=c.dfGrapes)
# lData <- list(
#   M  = nrow(c.dfGrapes),
#   P  = ncol(mgModelMatrix),
#   Y  = c.dfGrapes$grapehect,
#   SD = c.dfGrapes$SE,
#   W  = c.mgProx_std,
#   X  = mgModelMatrix
# )
# 
# c.oStanFit   <- sampling(
#   oStanModel_vec,
#   data    = lData,
#   seed    = 1234,
#   iter    = 500,
#   verbose = TRUE,
#   control = list(adapt_delta = 0.95),
#   refresh = 10
# )
# save(c.oStanFit, file="./c.oStanFit.RData")
load(file="./c.oStanFit.RData")
stan_trace(c.oStanFit, c("rho", "sigma_sq", "theta[116]"), inc_warmup = T)

stan_rhat(c.oStanFit)

\(\rho, \sigma_u^2, \theta_{116},\)のトレースプロットと、 \(\hat{R}\)のヒストグラムを描いてみた。 なお、地域116は直接推定量の分散が最も高い。MCMCにおいてパラメータの\(\hat{R}\)が 一番高いのも\(\theta_{116}\)である(1.099)。

まあ… ぎりぎり収束しているということにしたいが、 warmup(現状ではデフォルトの250)がちょっと足りないような気がするので、 以下ではさらに50反復を捨て、最後の200反復だけ使うことにする。

地域特性の推定値をsaeパッケージと比較してみると…

mgResult <- rstan::extract(c.oStanFit, permuted = FALSE) # 3 dims
mgTheta <- mgResult[51:250, , grepl("^theta", dimnames(mgResult)$parameters)]
mgTheta <- do.call(rbind, lapply(1:4, function(nID) mgTheta[,nID,]))
agEst <- colMeans(mgTheta)
agMSE <- apply(mgTheta, 2, var)
sub_PlotTwoEstimate.1(
  agEst1     = as.vector(c.oModel_saeREML$est$eblup),
  agMSE1     = c.oModel_saeREML$mse,
  agEst2     = agEst,
  agMSE2     = agMSE,
  asLabel    = c.dfGrapes$nAreaID,
  sVarLabel1 = "sae (REML)",
  sVarLabel2 = "rstan"
)

推定値はほぼ同じ、MSEは高めに推定されている。

4.2.6 spdepパッケージによる推定

saeパッケージで推定した空間Fay-Herriotモデルとは、要は 各地域の標本抽出誤差分散\(\psi_i\)が既知なSARモデルかCARモデルなのだから、 汎用的なパッケージで推定できるはずだ。

…と考え、SARモデルのほうについて、 果敢にもspdepパッケージでの推定にチャレンジしてみた。 正直、正しいコードなのか全く自信がない。

特に自信がないのが、標本抽出誤差分散\(\psi_i\)の指定の仕方である。 errorsarlm()にはweights=という引数がある。マニュアルにいわく、 「オプション。フィッティングの過程で用いられるウェイトのベクトル。 非NULLのウェイトを指定することで、観察によって分散が異なることを 指示することができる。この場合、ウェイトの値は分散と反比例する値とする」 とある。それで、きっとweightsには\(1/\psi_i\)を指定するんだろうと 思ったわけなのですが…

c.oModel_spdep <- errorsarlm(
  grapehect ~ area + workdays , 
  data    = c.dfGrapes, 
  listw   = mat2listw(c.mgProx_std, style="W"), 
  weights = 1/var
)
print(summary(c.oModel_spdep))

Call:
errorsarlm(formula = grapehect ~ area + workdays, data = c.dfGrapes, 
    listw = mat2listw(c.mgProx_std, style = "W"), weights = 1/var)

Residuals:
     Min       1Q   Median       3Q      Max 
-84.0203  -2.6305  11.4841  24.5922 225.4653 

Type: error 
Coefficients: (asymptotic standard errors) 
               Estimate  Std. Error z value Pr(>|z|)
(Intercept) -25.3884753   1.0907410 -23.276   <2e-16
area          0.0015826   0.0015890   0.996   0.3192
workdays      0.4030366   0.0151736  26.562   <2e-16

Lambda: 0.58134, LR test value: 257.4, p-value: < 2.22e-16
Asymptotic standard error: 0.061051
    z-value: 9.5223, p-value: < 2.22e-16
Wald statistic: 90.673, p-value: < 2.22e-16

Log likelihood: -1640.073 for error model
ML residual variance (sigma squared): 56.904, (sigma: 7.5435)
Number of observations: 274 
Number of parameters estimated: 5 
AIC: 3290.1, (AIC for lm: 3545.5)

\(\sigma_u^2\)は56.904(seaパッケージでは71.189), \(\phi\)は0.581(saeパッケージでは0.583)と推定された。

\(\sigma_u^2\)の推定値が全然ちがう。\(\mathbf{\beta}\)の推定値も かなり違う。暗雲垂れ込めてきたけれど、\(\theta_i\)の推定値を比べてみると…

sub_PlotTwoEstimate.1(
  agEst1     = as.vector(c.oModel_saeREML$est$eblup), 
  agEst2     = as.vector(predict(c.oModel_spdep, pred.type="TS")), 
  asLabel    = c.dfGrapes$nAreaID, 
  sVarLabel1 = "sae (REML)", 
  sVarLabel2 = "spdep"
)

案の定、かなり違う。なぜだ??

二つの可能性が考えられる。

  • 私がspdepパッケージの使い方をよく理解できておらず、 書き方を間違えている。
  • そもそもspdepパッケージのerrorsarlm()では、ここでいう 空間Fay-Herriotモデルを推定できない。

あれこれ考えていて、実は後者なのかも、という気がしてきた。 その理由は次の通り。

空間Fay-Herriotモデルは、 \(\hat{\mathbf{\theta}} = (\theta_1, \ldots, \theta_m)^T\)とし、 \(\psi_1, \ldots, \psi_m\)を持つ対角行列を\(\mathbf{\Psi}\)と書くとして \[ \hat{\mathbf{\theta}} = \mathbf{Z} \mathbf{\beta} + \mathbf{v} + \mathbf{e}, \ \ \mathbf{e} \sim (0, \mathbf{\Psi}) \] \[ \mathbf{v} = \phi \mathbf{W} \mathbf{v} + \mathbf{u}, \ \ \mathbf{u} \sim N(\mathbf{0}, \sigma_u^2 \mathbf{I}) \] となると思う。いっぽうerrorsarlm()のモデルは、マニュアルによれば

y = X beta + u, u = lambda W u + e

である。記法を揃えると、これは \[ \hat{\mathbf{\theta}} = \mathbf{Z} \mathbf{\beta} + \mathbf{v} \] \[ \mathbf{v} = \phi \mathbf{W} \mathbf{v} + \mathbf{u}, \ \ \mathbf{u} \sim N(\mathbf{0}, \sigma_u^2 \mathbf{I}) \] ではないかと思うのである。weights=引数は 推定の際になんらか使われる重みづけに過ぎず、モデルには標本抽出誤差が含まれて いないのではなかろうか?

うーむ。残念ながら、よくわからない。 どなたか教えてくださらないでしょうか。

rm(list=grep("^c\\.", ls(), value=T))

4.3 シミュレーション

こうしてみてみると、いろいろ疑問が湧いてくる。わたくしと致しましては、 特に次の3点に関心がある。

  • spdepパッケージによる推定は、saeパッケージによる推定と 著しく異なる。これは私の使い方が悪いか、ないし モデルが異なるからだと思う。では、真値を正しく推定しているのは どちらか。saeパッケージのほうが正しい、ということを確かめたい。
  • grapesデータの場合、空間相関を考慮してもしなくても、 推定値はたいして変わらなかったが、MSEの推定値は下がった。 では、真のMSEを正しく推定しているのはどちらか。
  • 真の空間相関が高ければ、空間相関の考慮によって推定の精度は 上がるだろう。では、真の空間相関がどのくらい高かったら、 空間相関を考慮すべきなのか。

こんばんは、シミュレーションの時間です。

4.3.1 問題

\(c\)\(c\)列のグリッドで区切られた\(m=c*c\)個の地域があるとする。 いま、地域\(i\)(\(=1,\ldots,m\))のひとりひとりの住民\(j\)(\(=1,\ldots,N_i\))が、 量的な反応変数\(y_{ij}\)を持っている。えーっと、幸福度ってことにしましょうか。

地域の母集団サイズ\(N_i\)はいずれも十分に大きい。 各地域の幸福度の母平均\(\bar{Y}_i = (1/N_i) \sum_j y_{ij}\)について推測したい。

そこで、各地域\(i\)からサイズ\(n_i\)の標本を単純無作為抽出し、 標本平均\(\hat{\bar{Y}}_i = \frac{\sum_j y_{ij}}{n_i}\), ならびにその分散の推定値 \(\hat{Var}(\hat{\bar{Y}}_i) = \frac{\sum_j (y_{ij} - \hat{\bar{Y}}_i)}{n_i(n_i-1)}\) を求めた。

ところが、地域ごとの標本サイズ\(n_i\)は必ずしも十分でない。 また、辺を接する地域間では、幸福度平均\(\bar{Y}_i\)が似ている、 と私は信じている(なんかその、境界を超えて漂ってくるんじゃないですかね、 幸せのオーラみたいなものが)。 だから、幸福度の標本平均\(\hat{\bar{Y}}_i\)だけでなく、 その地域が他のどの地域と接しているかという情報もつかって、 各地域の幸福度の母平均\(\bar{Y}_i\)を 推測できるはずである。

そこで空間Fay-Erriotモデルの登場である。

以下、記号が煩雑になるので、 RM本にあわせて\(\theta_i = \bar{Y}_i\), \(\hat{\theta}_i = \hat{\bar{Y}}_i\) と書く。 また、 \(\psi_i = Var(\hat{\bar{Y}}_i)\)と書く。

おさらいすると、空間Fay-Herriotモデル(SARモデル)は以下の通り。 上の問題設定にあわせ、共変量を省いて書く。 \(\hat{\mathbf{\theta}} = (\theta_1, \ldots, \theta_m)^T\)とし、 \(\psi_1, \ldots, \psi_m\)を持つ対角行列を\(\mathbf{\Psi}\)と書く。

\[ \hat{\mathbf{\theta}} = \mathbf{v} + \mathbf{e}, \ \ \mathbf{e} \sim (\mathbf{0}, \mathbf{\Psi}) \] \[ \mathbf{v} = (\mathbf{I}-\phi \mathbf{W})^{-1} \mathbf{u}, \ \ \mathbf{u} \sim N(\mathbf{0}, \sigma_u^2 \mathbf{I}) \]

4.3.2 データ生成モデル

データ生成モデルは次のとおり。SARモデルに基づく。

地域 \(i=1,\ldots,m\) のユニット \(j=1,\ldots,n_j\) について、 \[ y_{ij} = 50 + v_i + \epsilon_{ij}, \ \ \epsilon_{ij} \mathop{\sim}^{iid} N(0,100) \] \(\mathbf{v} = (v_1, \ldots, v_m)^T\)について、 \[ \mathbf{v} = (\mathbf{I} - \phi \mathbf{W})^{-1} \mathbf{u}, \ \ \mathbf{u} \sim N(\mathbf{0}, \sigma_u^2 \mathbf{I}) \] \(\mathbf{W}\)は、辺を接する地域を1とした隣接行列を行標準化したものとする。

つまり、私は知らないのだが、実は

  • (幸福度)=50+(地域効果)+(個人差) である。
  • 地域間で幸福度にばらつきがあり、そのばらつきは多変量正規分布に従っている。 隣接している地域間では幸福度が似ている。
  • 地域内の個人差も正規分布に従っている。

母集団サイズは大きく、\(\epsilon_{ij}\)の母集団平均は 0とみなせるので、結局、知りたい特性\(\theta_i\)はここでは\(v_i\)に等しい。

地域の標本サイズ\(n_i\)は、\(10, 20, \ldots, 100\)を長さ\(m\)に達するまで繰り返し、 これをランダムに並び替えたものとする。

4.3.3 シミュレーション用の関数

…というデータを生成するための、一連の関数を作ってみました。

d.sub_MakeNeighborMatrix.1 <- function(nNumGridRow, nNumGridCol){
  # purpose: make a neighbor matrix of meshes in specified grid
  # args: 
  #   nNumGridRow, nNumGridCol: size of grid
  # return: 
  #   a neighbor matrix (row-standardized)
  # notes: 
  #   e.g. nNumGridRow=2, nNumGridCol=3
  #     meshID in grid:
  #        1, 2, 3
  #        4, 5, 6
  #     neighbor matrix (unstandardized): 
  #        (meshID=1) 0, 1, 0, 1, 0, 0
  #        (meshID=2) 1, 0, 1, 0, 1, 0 
  #        (meshID=3) 0, 1, 0, 0, 0, 1
  #        (meshID=4) 1, 0, 0, 0, 1, 0
  #        (meshID=5) 0, 1, 0, 1, 0, 1
  #        (meshID=6) 0, 0, 1, 0, 1, 0
  
  dfValue <- expand.grid(
    # nGridRow1, nGridCol1: location of mesh1 in the grid 
    # nGridRow2, nGridCol2: location of mesh2 in the grid 
    nGridRow1 = 1:nNumGridRow,
    nGridCol1 = 1:nNumGridCol,
    nGridRow2 = 1:nNumGridRow,
    nGridCol2 = 1:nNumGridCol
  ) %>%
    mutate(
      # nLoc1: meshID of mesh1
      # nLoc2: meshID of mesh2
      nLoc1 = (nGridRow1-1)*nNumGridCol + nGridCol1,
      nLoc2 = (nGridRow2-1)*nNumGridCol + nGridCol2,
      # bValue: neighbor or not
      bValue = if_else(
        (
          (nGridRow1 == nGridRow2)
          & (abs(nGridCol1 - nGridCol2) == 1)
        )|(
          (abs(nGridRow1 - nGridRow2)==1)
          & (nGridCol1 == nGridCol2)
        ),
        1, 0
      )
    )
  
  dfName <- dfValue %>%
    dplyr::select(nGridRow1, nGridCol1, nLoc1) %>%
    distinct() %>%
    mutate(sName = paste0("r", nGridRow1, "c", nGridCol1)) %>%
    arrange(nLoc1) 
  ## print(dfName)
  
  out <- matrix(0, nrow=nNumGridRow*nNumGridCol, ncol=nNumGridRow*nNumGridCol)
  out[as.matrix(dfValue[c("nLoc1", "nLoc2")])] <- dfValue$bValue
  out <- sweep(out, MARGIN = 1, FUN = "/", STATS = rowSums(out))
  rownames(out) <- dfName$sName
  colnames(out) <- dfName$sName
  
  # print(out)
  return(out)
}
d.sub_GenerateDataset2.1 <- function(
  mgNB, gVarU, gPhi, gVarE=100, anPossibleN=seq(10, 100, by = 10)
){
  ## purpose: generate a dataset for spatial FH model
  ## arg:
  ##   mgNB:        neighbor matrix
  ##   gVarU:       variance of area effects
  ##   gPhi:        spatial correlation
  ##   gVarE:       variance in each area
  ##   anPossibleN: vector of possible sample size
  ## return:
  ##   a data frame, area level data
  ##   $nArea:       Area ID
  ##   $sName:       Grid Location (e.g. "r2c3" means row2-col3)
  ##   $nSize:       sample size
  ##   $gU:          area effect without spatial correlation
  ##   $gV:          area effect with spatial correlation
  ##   $gTrue:       true value
  ##   $gEst_Direct: sample means of a response variable
  ##   $gMSE_Direct: sample est. of variance of sample means
  
  nNumArea <- nrow(mgNB)
  
  # anSize: sample size 
  anSize <- rep(anPossibleN, nNumArea %/% length(anPossibleN) + 1)[1:nNumArea]
  anSize <- sample(anSize, nNumArea, replace=FALSE)
  ## print(anSize)
  
  # agU: \sim N(\mathbf{0}, \sigma_u^2 \mathbf{I})
  agU <- rnorm(n = nNumArea, mean = 0, sd = sqrt(gVarU))
  # agV: (\mathbf{I} - \phi \mathbf{W})^{-1} \mathbf{u}
  mgCoef <- solve(diag(x=1, nrow=nNumArea) - gPhi * mgNB)
  agV <- as.vector(mgCoef %*% agU)
  
  asName <- rownames(mgNB)
  
  out <- data.frame(
    nArea      = 1:nNumArea,
    sName      = asName,
    nGridRow   = as.integer(sub("^r([0-9]+)c([0-9]+)$", "\\1", asName)),
    nGridCol   = as.integer(sub("^r([0-9]+)c([0-9]+)$", "\\2", asName)),
    nSize      = anSize,
    gU         = agU,
    gV         = agV,
    gTrue      = 50 + agV,
    stringsAsFactors = FALSE
  )
  lError <- lapply(
    out$nSize,
    function(nSize){
      rnorm(n = nSize, mean = 0, sd = sqrt(gVarE))
    }
  )
  out$gEst_Direct  <- out$gTrue + sapply(lError, mean)
  out$gMSE_Direct  <- sapply(lError, function(x){ var(x) / length(x) })
  
  ## print(out)
  return(out)
}
d.sub_GenerateMultiDataset2.1 <- function(nNumDataset=1, mgNB, gVarU, gPhi, ...){
  ## purpose: generate multiple datasets for FH model
  ## arg:
  ##   nNumDataset:   number of data sets
  ##   mgNB:          neighbor matrix
  ##   gVarU:         variance of area effects
  ##   gPhi:          spatial correlation, 
  ##   ...:           pass to sub_GenerateDataset2.1() (gVarE, anPossibleN)
  ##                     
  ## return:
  ##   a dataset
  ##   $nDataset:  Dataset ID
  ##   $...        generated by sub_GenerateDataset2.1()
  
  out <- data.frame(nDataset = 1:nNumDataset) %>%
    group_by(nDataset) %>%
    dplyr::do(d.sub_GenerateDataset2.1(mgNB = mgNB, gVarU = gVarU, gPhi = gPhi)) %>%
    ungroup()
  return(out)
}
d.sub_EstimateDatasetByMethod2.1 <- function(
  dfData, mgNB, sMethod, bVerbose=FALSE
){
  ## purpose: estimate spatial FH model for a dataset by a method
  ## arg:
  ##   dfData:  a data set
  ##   mgNB:    neighbor matrix
  ##   sMethod: {"saeFH", "saeSFH", "spdepWGT", "spdepNOWGT"}
  ##   bVerbose
  ## return:
  ##   a list
  ## trap: check sMethod
  stopifnot(sMethod %in% c("saeFH", "saeSFH", "spdepWGT", "spdepNOWGT"))
  if (bVerbose) cat("[sub_EstimateDataset2.1]", sMethod, "... \n")
  t <- proc.time()
  if (sMethod == "saeFH") {
    oModel <- try(
      mseFH(
        formula = dfData$gEst_Direct ~ 1,
        vardir  = dfData$gMSE_Direct,
        method  = "REML"
      )
    )
    if (!inherits(oModel, "try-error")) {
      agEst  <- as.vector(oModel$est$eblup)
      agMSE  <- oModel$mse
      gSCorr <- NA
      gAIC   <- oModel$est$fit$goodness[2]
      gBIC   <- oModel$est$fit$goodness[3] 
    }
  }
  if (sMethod == "saeSFH") {
    oModel <- try(
      mseSFH(
        formula = dfData$gEst_Direct ~ 1,
        vardir  = dfData$gMSE_Direct,
        proxmat = mgNB,
        method  = "REML"
      )
    )
    if (!inherits(oModel, "try-error")) {
      agEst <- as.vector(oModel$est$eblup)
      agMSE <- oModel$mse
      gSCorr <- oModel$est$fit$spatialcorr
      gAIC   <- oModel$est$fit$goodness[2]
      gBIC   <- oModel$est$fit$goodness[3] 
    }
  }
  if (sMethod == "spdepWGT") {
    oModel <- try(
      errorsarlm(
        gEst_Direct ~ 1 ,
        data    = dfData,
        listw   = mat2listw(mgNB, style="W"),
        weights = 1/gMSE_Direct
      )
    )
    ## print(oModel)
    if (!inherits(oModel, "try-error")) {
      agEst  <- as.vector(predict(oModel, pred.type="TS"))
      agMSE  <- rep(NA, nrow(dfData))
      gSCorr <- oModel$lambda
      gAIC   <- NA
      gBIC   <- NA
    }
  }
  if (sMethod == "spdepNOWGT") {
    oModel <- try(
      errorsarlm(
        gEst_Direct ~ 1 ,
        data    = dfData,
        listw   = mat2listw(mgNB, style="W")
      )
    )
    ## print(oModel)
    if (!inherits(oModel, "try-error")) {
      agEst <- as.vector(predict(oModel, pred.type="TS"))
      agMSE <- rep(NA, nrow(dfData))
      gSCorr <- oModel$lambda
      gAIC   <- NA
      gBIC   <- NA
    }
  }
  ## common process ...
  if (!inherits(oModel, "try-error")) {
    out <- list(
      sMethod = sMethod,
      bStatus = TRUE,
      agEst   = agEst,
      agMSE   = agMSE,
      gSCorr  = gSCorr,
      gAIC    = gAIC,
      gBIC    = gBIC,
      gTime   = (proc.time() - t)[3]
    )
    if (bVerbose) cat("[sub_EstimateDataset2.1] Success.", out$gTime, "sec.\n")
  } else {
    out <- list(
      sMethod = sMethod,
      bStatus = FALSE,
      agEst   = rep(NA, nrow(dfData)),
      agMSE   = rep(NA, nrow(dfData)),
      gSCorr  = NA, 
      gAIC    = NA, 
      gBIC    = NA,
      gTime   = (proc.time() - t)[3]
    )
    if (bVerbose) cat("[sub_EstimateDataset2.1] Fail.", out$gTime, "sec.\n")
  }
  return(out)
}
d.sub_EstimateDataset2.1 <- function(
  dfData, mgNB, asMethod=c("saeFH", "saeSFH", "spdepWGT", "spdepNOWGT"), ...
){
  ## purpose: estimate spatial FH model for a dataset by multiple methods
  ## arg:
  ##   dfData:   a data set
  ##   mgNB:     neighbor matrix
  ##   asMethod: {"saeFH", "saeSFH", "spdepWGT", "spdepNOWGT"}
  ##   ...:      pass to sub_EstimateDatasetByMethod2.1() (bVerbose)
  ## return:
  ##   a data frame
  lOut <- lapply(
    asMethod,
    function(sMethod){
      lResult <- d.sub_EstimateDatasetByMethod2.1(dfData, mgNB, sMethod, ...)
      out <- data.frame(
        nArea   = dfData$nArea,
        sName   = dfData$sName,
        sMethod = rep(lResult$sMethod, nrow(dfData)),
        bStatus = rep(lResult$bStatus, nrow(dfData)),
        gEst    = lResult$agEst,
        gMSE    = lResult$agMSE,
        gSCorr  = rep(lResult$gSCorr, nrow(dfData)),
        gAIC    = rep(lResult$gAIC,   nrow(dfData)),
        gBIC    = rep(lResult$gBIC,   nrow(dfData)),
        gTime   = rep(lResult$gTime,  nrow(dfData)),
        stringsAsFactors = FALSE
      )
      return(out)
    }
  )
  out <- bind_rows(lOut) %>%
    gather(sVar, gValue, c(bStatus, gEst, gMSE, gSCorr, gAIC, gBIC, gTime)) %>%
    mutate(sVar = paste0(sVar, "_", sMethod)) %>%
    dplyr::select(nArea, sVar, gValue) %>%
    spread(sVar, gValue)
  out <- full_join(dfData, out, by = "nArea")
  return(out)
}
d.sub_EstimateMultiDataset2.1 <- function(dfMultiData, mgNB, ...){
  ## purpose: estimate FH models for multiple datasets by multiple methods
  ## arg:
  ##   dfMultiData: multiple data
  ##   mgNB:        neighbor matrix
  ##   ...:         pass to sub_EstimateDataset2.1() (asMethod, bVerbose)
  ## return:
  ##   a data frame of multiple results
  out <- dfMultiData %>%
    group_by(nDataset) %>%
    dplyr::do(d.sub_EstimateDataset2.1(., mgNB = mgNB, ...)) %>%
    ungroup()
  return(out)
}
d.sub_EstimatorAsFactor.1 <- function(asEstimator){
  ## purpose: convert estimator names into factor
  ## args:
  ##   asEstimator: a character vector of estimator names
  ## return:
  ##   a factor vector
  factor(
    asEstimator,
    levels = c(
      "True", "Direct", "saeFH", "saeSFH", 
      "spdepWGT", "spdepNOWGT"
    ),
    labels = c(
      "True", "Direct", "sae(w/o sc)", "sae(w/ sc)", 
      "spdep(wgt)", "spdep(unwgt)"
    )
  )
}
d.sub_EstimatorPalette.1 <- function(afEstimator){
  ## purpose: get consisntent color pallette for estimators
  ## args:
  ##   afEstimator: a factor vector of estimator
  ## return:
  ##   a vector of color palette
  gg_color_hue(6)[sort(unique(as.integer(afEstimator)))]
}

4.3.3 データ分析例

ためしに、上記のデータ生成関数とデータ分析関数を使ってみよう。

地域数を\(10 \times 10 = 100\), 地域効果の分散\(\sigma_u^2\)を50, 空間自己相関パラメータ\(\phi\)を0.7とする。

set.seed(100)
d.mgNeighbor <- d.sub_MakeNeighborMatrix.1(10, 10)
d.dfDemoData <- d.sub_GenerateDataset2.1(mgNB = d.mgNeighbor, gVarU=50, gPhi=0.7)

各地域の標本サイズと、幸福度の標本平均を描いてみよう。

dfPlot <- d.dfDemoData %>%
  dplyr::select(nArea, nGridRow, nGridCol, nSize, gEst_Direct) 
g <- ggplot(data=dfPlot, aes(x=nGridCol, y=-nGridRow, size = nSize, label=nArea))
g <- g + geom_count(aes(color=gEst_Direct), shape=15)
g <- g + geom_text(size=4)
g <- g + scale_size_area(max_size = 12)
g <- g + scale_x_discrete()
g <- g + scale_y_discrete()
g <- g + scale_color_gradient(low="yellow", high="red")
g <- g + labs(x=NULL, y=NULL, size="SampleSize", color="Direct")
g <- g + theme_bw()
print(g)

正方形は各地域、数字は地域番号, サイズは標本サイズ、色の濃さは標本平均の高さを表す。 心なしか、隣接している地域の色は似ているような気がしませんか?

MorranのIを求めてみると…

moran.test(d.dfDemoData$gEst_Direct, mat2listw(d.mgNeighbor, style="W"))

    Moran I test under randomisation

data:  d.dfDemoData$gEst_Direct  
weights: mat2listw(d.mgNeighbor, style = "W")    

Moran I statistic standard deviate = 4.5121, p-value = 3.209e-06
alternative hypothesis: greater
sample estimates:
Moran I statistic       Expectation          Variance 
      0.323555742      -0.010101010       0.005468176 

I=0.32。有意ではあるが、そんなに大きくない。これは標本平均に標本抽出誤差が 載っているからだろうと思い、ためしに真値\(v_i\)について MorranのIを求めてみたら…

moran.test(d.dfDemoData$gTrue, mat2listw(d.mgNeighbor, style="W"))

    Moran I test under randomisation

data:  d.dfDemoData$gTrue  
weights: mat2listw(d.mgNeighbor, style = "W")    

Moran I statistic standard deviate = 4.864, p-value = 5.753e-07
alternative hypothesis: greater
sample estimates:
Moran I statistic       Expectation          Variance 
       0.35029214       -0.01010101        0.00548998 

I=0.35, たいしてかわらない。そんなもんなのか…

では、推定してみましょう。 次の6個を比較する。

  • True: 真値\(\theta_i\)
  • Direct: 標本平均_i。
  • sae(w/o sc): saeパッケージ, 空間相関を考慮しない。 EBLUP推定量, \(\sigma_v^2\)をREML推定。
  • hbsae(w/ sc): saeパッケージ, 空間相関を考慮する(SARモデル)。 EBLUP推定量, \(\sigma_v^2\)をREML推定。
  • spde(wgt): spdepパッケージ(SARモデル)。標本抽出誤差分散によって重みづけする。
  • spde(unwgt): spdepパッケージ(SARモデル)。標本抽出誤差分散によって重みづけしない。

rstanも試したいところだが、計算時間が長すぎるので断念した。

dfResult <- d.sub_EstimateDataset2.1(d.dfDemoData, d.mgNeighbor, bVerbose=F)
dfPlot <- dfResult %>%
  filter(nSize == 10) %>%
  dplyr::select(nArea, nSize, gTrue, starts_with("gEst_")) %>%
  arrange(-gTrue) %>%
  mutate(fArea = factor(nArea, levels=nArea, labels=as.character(nArea))) %>%
  rename(gEst_True = gTrue) %>%
  gather(sVar, gValue, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  mutate(fEstimator = d.sub_EstimatorAsFactor.1(sEstimator))
g <- ggplot(data=dfPlot, aes(x=fArea, y=gValue, group=fEstimator, color=fEstimator))
g <- g + geom_path(size=1)
g <- g + labs(
  x     = "area (of sample size == 10)", 
  y     = expression(paste(theta, " or ", hat(theta))), 
  color = "Estimator"
)
g <- g + scale_color_manual(values = d.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

上の図は、標本サイズ10の地域のみについて、真値\(\theta_i = v_i\)ならびにその推定値を 示したものである。真値が高い順に並べてある。

spdepによる推定値は、真値よりもずっと全体平均に近い推定値となっている。 はっきりいってぼろ負けである。

saeによる推定値は直接推定(標本平均)に近い。また、空間相関を考慮しようがしまいが、 結果はたいして変わらない。

… もっとも、この結果はたまたまかもしれない。 同じことを何度も繰り返してみないと、なんともいえない。

4.3.4 標本サイズ vs. 推定の精度

お待たせしました。繰り返します。

さきほどと同じく、 地域数を\(10 \times 10 = 100\), 地域効果の分散\(\sigma_u^2\)を50, 地域効果の分散\(\sigma_u^2\)を50, 空間自己相関パラメータ\(\phi\)を0.7とする。 500回繰り返す。

# set.seed(100)
# d.dfSimData1 <- d.sub_GenerateMultiDataset2.1(
#     nNumDataset = 500,
#     mgNB        = d.mgNeighbor,
#     gVarU       = 50,
#     gPhi        = 0.7
#   )
# d.dfSimulation1 <- d.sub_EstimateMultiDataset2.1(
#   dfMultiData = d.dfSimData1,
#   mgNB        = d.mgNeighbor
# )
# save(d.dfSimulation1, file="./d_dfSimulation1.RData")
load("./d_dfSimulation1.RData")

推定値はどのくらいあてになるか。

dfPlot <- d.dfSimulation1 %>%
  dplyr::select(nSize, gTrue, starts_with("gEst_")) %>%
  gather(sVar, gEst, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  mutate(
    gDiff      = gEst - gTrue, 
    fEstimator = d.sub_EstimatorAsFactor.1(sEstimator)
  ) 
g <- ggplot(data=dfPlot, aes(x = nSize, y=gDiff, color=fEstimator)) 
g <- g + geom_point(alpha=1/5)
g <- g + labs(
  x     = "Sample Size", 
  y     = expression(hat(theta)-theta), 
  color = "Estimator"
)
g <- g + geom_hline(yintercept = 0)
g <- g + scale_x_continuous(breaks = seq(10, 100, by = 20))
g <- g + scale_color_manual(
  guide = FALSE, 
  values = d.sub_EstimatorPalette.1(dfPlot$fEstimator)
)
g <- g + facet_grid(~ fEstimator)
g <- g + theme_bw()
print(g)

縦軸は、推定値と真値との差を表している。

まずみてとれるのは、次の点である: spdep!! おまえはダメな子!!

ま、spdepのerrorsarlm()というのは空間Fay-Herriotモデルとは違うのだろう。 ないし、私の使い方が間違っているのだろう。 ともあれ、以下ではspdepの結果は省略する。

推定値と正解との差を集計すると、

dfPlot <- d.dfSimulation1 %>%
  dplyr::select(nSize, gTrue, gEst_Direct, gEst_saeFH, gEst_saeSFH) %>%
  gather(sVar, gEst, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  group_by(sEstimator, nSize) %>%
  summarize(
    nFreq = n(),
    gRMSE = sqrt(mean((gEst - gTrue)^2))
  ) %>%
  ungroup() %>%
  mutate(
    fEstimator = d.sub_EstimatorAsFactor.1(sEstimator)
  ) 
g <- ggplot(data=dfPlot, aes(x = nSize, y=gRMSE, group=fEstimator, color=fEstimator)) 
g <- g + geom_path(size=1)
g <- g + scale_x_continuous(breaks = seq(10, 100, by = 10))
g <- g + labs(x = "Sample Size", y = "observed RMSE", color="Estimator")
g <- g + scale_color_manual(values = d.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

縦軸は「推定値と正解との差の二乗の平均の平方根」(RMSE)を示す。平たく言っちゃうと、 推定した地域平均は、真の地域平均からだいたい何点くらいずれるか、を示している。

標本サイズが10のときには、だいたい3点くらいずれてしまう。 標本サイズが大きくなると、ずれは小さくなる。

ここで関心があるのは推定量の間の差だ。拡大します。

dfPlot <- d.dfSimulation1 %>%
  dplyr::select(nSize, gTrue, gEst_Direct, gEst_saeFH, gEst_saeSFH) %>%
  gather(sVar, gEst, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  group_by(sEstimator, nSize) %>%
  summarize(
    gRMSE = sqrt(mean((gEst - gTrue)^2))
  ) %>%
  ungroup() %>%
  mutate(
    gRatio = gRMSE / sqrt(100/nSize),
    fEstimator = d.sub_EstimatorAsFactor.1(sEstimator)
  ) 
g <- ggplot(data=dfPlot, aes(x = nSize, y=gRatio, group=fEstimator, color=fEstimator)) 
g <- g + geom_path(size=1)
g <- g + geom_hline(yintercept = 1)
g <- g + scale_x_continuous(breaks = seq(10, 100, by = 10))
g <- g + labs(
  x = "Sample Size",
  y = "(observed RMSE)/(theoretical RMSE of Direct)", 
  color = "Estimator"
)
g <- g + scale_color_manual(values = d.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

標本抽出誤差は実は100なので、 標本平均の真のRMSEは\(\sqrt{100/n_i}\)である。 これを基準に、それぞれのパッケージによる推定値の RMSEを比で表している。下にいくほど、推定値と真の値のずれが小さい。

このように、空間相関を考慮することで、推定値と真の値のずれが小さくなる ことがわかる。標本サイズが小さいときに効果が大きい。

MSEについてもみておこう。

dfPlot <- d.dfSimulation1 %>%
  dplyr::select(
    nSize, gTrue, 
    gEst_Direct, gEst_saeFH, gEst_saeSFH, 
    gMSE_Direct, gMSE_saeFH, gMSE_saeSFH
  ) %>%
  gather(sVar, gValue, c(starts_with("gEst_"), starts_with("gMSE_"))) %>%
  separate(sVar, c("sVar", "sEstimator")) %>%
  spread(sVar, gValue) %>%
  mutate(
    gTrueSE = (gEst - gTrue)^2, 
    gDiff   = gMSE - gTrueSE 
  ) %>% 
  group_by(sEstimator, nSize) %>%
  summarize(
    gMeanDiff = mean(gDiff)
  ) %>%
  ungroup() %>%
  mutate(
    fEstimator = d.sub_EstimatorAsFactor.1(sEstimator)
  ) 
g <- ggplot(data=dfPlot, aes(x = nSize, y=gMeanDiff, group=fEstimator, color=fEstimator)) 
g <- g + geom_path(size=1)
g <- g + geom_hline(yintercept = 0)
g <- g + scale_x_continuous(breaks = seq(10, 100, by = 10))
g <- g + labs(
  x = "Sample Size", 
  y = "mean ((Estimated MSE)-(Actual Sq.Err))", 
  color = "Estimator"
)
g <- g + scale_color_manual(values = d.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

縦軸は、「推定されたMSEから、推定値と正解との差の二乗を引いた値」の平均である。 つまり、正の値はMSEの推定が概して過大であること、 負の値は概して過小であることを表す。

3.3.4で確認したように、 標本サイズが小さい時、BLUP推定のMSEの推定は過小になる。 ここでわかるのは、空間相関を考慮するとさらに過小になるということである。

つまりこういうことだ。 標本サイズが小さいとき、空間相関を正しく考慮することで、真値と推定値との ずれは小さくなる(推定量の真のMSEは下がる)。いっぽう、真値と推定値との ずれに対する推定(推定量のMSEの推定)は、もともと過度に楽観的だったのが、 さらに楽観的になってしまうわけだ。へー!

4.3.5 空間相関の強さ vs. 推定の精度

今度は、空間相関の強さと推定の精度の関係について調べてみたい。

地域効果の分散\(\sigma_u^2\)を50, 空間自己相関パラメータ\(\phi\)を0.7とする。 空間自己相関パラメータ\(\phi\)を0, 0.1, 0.2, …, 0.8と変えながら、 データ生成と分析を500試行繰り返した。 推定方法はsaeパッケージのみ、2種類とする。

# set.seed(123)
# lOut <- lapply(
#   seq(from=0, to=0.8, by = 0.1),
#   function(gPhi){
#     cat("gPhi = ", gPhi, "...")
#     out <- d.sub_GenerateMultiDataset2.1(
#       nNumDataset = 500,
#       mgNB        = d.mgNeighbor,
#       gVarU       = 50,
#       gPhi        = gPhi
#     )
#     out$gPhi <- gPhi
#     cat("\n")
#     return(out)
#   }
# )
# d.dfSimData2 <- bind_rows(lOut)
# 
# d.dfSimulation2 <- d.dfSimData2 %>%
#   group_by(gPhi) %>%
#   dplyr::do(
#     d.sub_EstimateMultiDataset2.1(
#       dfMultiData = .,
#       mgNB     = d.mgNeighbor,
#       asMethod = c("saeFH", "saeSFH")
#     )
#   ) %>%
#   ungroup()
# save(d.dfSimulation2, file="./d_dfSimulation2.RData")
load("./d_dfSimulation2.RData")

まずは推定の精度から。ここでは、 標本サイズ10の地域のみに注目する。各試行について10地域を利用できる。

dfPlot <- d.dfSimulation2 %>%
  filter(nSize == 10) %>%
  dplyr::select(gPhi, gTrue, starts_with("gEst_")) %>%
  gather(sVar, gEst, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  group_by(gPhi, sEstimator) %>%
  summarize(
    gRMSE = mean((gTrue-gEst)^2)
  ) %>%
  ungroup() %>% 
  mutate(
    fEstimator = d.sub_EstimatorAsFactor.1(sEstimator)
  ) 
## print(dfPlot)
g <- ggplot(data=dfPlot, aes(x=gPhi, y = gRMSE, color=fEstimator, group=fEstimator))
g <- g + geom_path(size=1)
g <- g + labs(x = expression(phi), y = "observed RMSE", color="Estimator")
g <- g + scale_color_manual(values = d.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + theme_bw()
print(g)

縦軸は「推定値と正解との差の二乗の平均の平方根」(RMSE)を示す。平たく言っちゃうと、 推定した地域平均は、真の地域平均からだいたい何点くらいずれるか、を示している。

空間自己相関パラメータ\(\phi\)が0.2以下のときは、 空間相関を考慮しないほうが、推定値と真値のずれがわずかに小さい。 いっぽう0.3以上になると、空間相関を考慮することによって、推定値の精度が高くなる。

では、\(\phi\)の大きさを知ることはできるのか。 こんどは\(\phi\)の推定値について調べてみよう。

dfPlot1 <- d.dfSimulation2 %>%
  filter(nArea == 1) %>%
  dplyr::select(gPhi, gSCorr_saeSFH) 
dfPlot2 <- dfPlot1 %>%
  group_by(gPhi) %>%
  summarize(gMean = mean(gSCorr_saeSFH)) %>%
  ungroup()
g <- ggplot(data=dfPlot2, aes(x = gPhi, y = gMean))
g <- g + geom_abline(intercept = 0, slope = 1)
g <- g + geom_violin(data=dfPlot1, aes(y=gSCorr_saeSFH, group = gPhi))
# g <- g + geom_point(data=dfPlot1, aes(y=gSCorr_saeSFH), size=1, alpha=1/10)
g <- g + geom_point(size=5)
g <- g + labs(x = expression(phi), y = expression(paste("estimated ", phi)))
g <- g + theme_bw()
print(g)

横軸は空間自己相関パラメータの真値\(\phi\)、縦軸はsaeパッケージ(空間Fay-Herriotモデル)に よるその推定値。 分布(バイオリンプロット)と平均(黒丸)を示している。

\(\phi\)の推定は、平均すると正しいが、かなりばらつきが大きい。\(\phi\)が低い場合には、 さらにばらつきが大きくなる。 つまり、標本から\(\phi\)を知るのは難しいわけだ。

具体的な分析の場面で、空間相関を考慮するかどうかを検討する際には、 空間Fay-Herriotモデルを推定して\(\phi\)の推定値を調べるよりも、 空間相関を考慮するモデルと考慮しないモデルのAICを比較することが 多いのではないかと思う。試してみよう。

dfPlot <- d.dfSimulation2 %>%
  filter(nArea == 1) %>%
  mutate(bWin = if_else(gAIC_saeSFH < gAIC_saeFH, 1, 0)) %>%
  group_by(gPhi) %>%
  summarize(gWin = mean(bWin)) %>%
  ungroup()
g <- ggplot(data=dfPlot, aes(x = gPhi, y = gWin))
g <- g + geom_col()
g <- g + labs(x = expression(phi), y = "Ratio of selecting spatial model")
g <- g + theme_bw()
print(g)

縦軸は、空間相関を考慮しないFay-Herriotモデルと空間Fay-Herriotモデルを比較したとき、 後者のほうがAICが小さくなった試行の割合である。

この図からわかるように、真の空間相関がゼロでも、 空間Fay-HerriotモデルのAICのほうが低くなってしまうことも ある。また、真の空間相関が小さいとき、空間Fay-HerriotモデルのAICのほうが 必ず低くなるとも限らない。 要するに、空間相関がない、ないし小さいとき、そのことを正しく知るのは 結構難しい。

ついでに、空間相関の有無についての判断を誤り、うっかり変なモデルを採用しちゃったら なにが起きるか試してみよう。

dfPlot <- d.dfSimulation2 %>%
  filter(nSize == 10, gPhi < 0.4 ) %>%
  mutate(bWin = if_else(gAIC_saeSFH < gAIC_saeFH, 1, 0)) %>%
  dplyr::select(gPhi, gTrue, bWin, starts_with("gEst_")) %>%
  gather(sVar, gEst, starts_with("gEst_")) %>%
  separate(sVar, c("sVar1", "sEstimator")) %>%
  group_by(gPhi, sEstimator, bWin) %>%
  summarize(
    gRMSE = mean((gTrue-gEst)^2)
  ) %>%
  ungroup() %>% 
  mutate(
    fWin       = factor(bWin, levels=c(0,1), labels=c("w/o sc", "w/ sc")),
    fEstimator = d.sub_EstimatorAsFactor.1(sEstimator)
  ) 
# print(dfPlot)
g <- ggplot(data=dfPlot, aes(x=fWin, y = gRMSE, color=fEstimator, group=fEstimator))
g <- g + geom_path(size=1)
g <- g + labs(x = "selected model", y = "observed RMSE", color="Estimator")
g <- g + scale_color_manual(values = d.sub_EstimatorPalette.1(dfPlot$fEstimator))
g <- g + facet_grid(~gPhi)
g <- g + theme_bw()
print(g)

パネルは真の空間自己相関パラメータ。パネル内の左側は、 AICによって空間相関を考慮しないモデルが支持された試行、 右側は、AICによって空間相関を考慮するモデルが支持された試行。縦軸は 「推定値と正解との差の二乗の平均の平方根」(RMSE)で、小さいほうが 推定値の精度が高い。

さきほどの分析では、 真の空間自己相関パラメータが0.2までであれば空間相関を考慮しないほうが いいし、それより大きければ空間相関を考慮したほうがいい、ということが わかった。この図からは、手元のデータから得られたAICがどうであれ (つまり、パネル内の左側の状況であれ右側の状況であれ)、 同じことがいえるのだ、と確認できる。

このシミュレーションの状況に関する限り、 空間相関が弱い(\(\phi\)が0.2以下だ)という確信があるならば、 たとえAICによって空間Fay-Herriotモデルが支持されようが、 断固として、ただのFay-Herriotモデルを使うべきなのである。

4.3.6 まとめ

このシミュレーションでわかったことをまとめておく。

  • Fay-HerriotモデルのEBLUP推定で、地域特性の推定量のMSEを解析的に求めたとき、 MSEは標本サイズが小さい地域において過小である。この傾向は、 空間Fay-Herriotモデルではさらに強くなる
  • 空間相関が存在しない場合、ないしある程度小さい場合には (このシミュレーションの状況では\(\phi<0.2\)のとき)、 空間Fay-Herriotモデル(SARモデル)を使うより、空間相関を考慮しない Fay-Herriotモデルを使うほうが、地域特性の推定量の精度は高くなる
  • 空間Fay-Herriotモデル(SARモデル)をspdepパッケージで推定する方法については、 結局よくわからなかった。どなたか、ビールでもなんでもお好きなものを 奢りますので、教えてくださらないでしょうか。
rm(list=grep("^d\\.", ls(), value=T))

いったんこれで終了とします。続きはまた後日…

LS0tDQp0aXRsZTogIuWwj+WcsOWfn+aOqOWumuOBruOBn+OCgeOBruODjuODvOODiCBb5a6f57+S57eoXSINCmF1dGhvcjogIlNoaWdlcnUgT05PIg0Kb3V0cHV0Og0KICBodG1sX25vdGVib29rOg0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNzczogc2FlLmNzcw0KICAgIGhpZ2hsaWdodDogaGFkZG9jaw0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0aGVtZTogY29zbW8NCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogMw0KICAgIHRvY19mbG9hdDogeWVzDQotLS0gDQo+IOOBk+OBruaWh+abuOOBr+OAgQ0KPiBSYW8gJmFtcDsgTW9saW5hICgyMDE1KSAiW1NtYWxsIEFyZWEgRXN0aW1hdGlvbl0oaHR0cHM6Ly9hbXpuLnRvLzJLNFRlczApIiwgDQo+IDJuZCBFZC4gKOS7peS4iyoqUk3mnKwqKinjgpLoqq3jgb/jgarjgYzjgonjgIHlsI/lnLDln5/mjqjlrprjga7lhbfkvZPnmoTjgarmiYvntprjgY3jgavjgaTjgYTjgabjgIENCj4gUuOBp+Wun+e/kuOBl+OBpuOBv+OBn+iomOmMsuOBp+OBguOCi+OAgg0KPg0KPiDjgYTjgYbjgb7jgafjgoLjgarjgY/jgIHnp4Hjgavjgojjgovnp4Hjga7jgZ/jgoHjga7np4Hjga7jg47jg7zjg4jjgafjgYLjgorjgIHjgZnjgbnjgabjga7oqqTjgorjga/np4HjgavluLDlsZ7jgYTjgZ/jgZfjgb7jgZnjgIINCj4NCj4g44Gq44GK44CBUk3mnKzjga7oqq3mm7jjg47jg7zjg4jjga9b55CG6KuW57eoXSguL3NhZS5uYi5odG1sKeOBqOOBl+OBpuWIpemAlOOBvuOBqOOCgeOBpuOBguOCi+OAgg0KPg0KPiDmm7TmlrDlsaXmrbQ6DQo+DQo+IC0gMjAxOC8wNi8yNSBb55CG6KuW57eoXSguL3NhZS5uYi5odG1sKeOBi+OCieWIhumbouOAgkZheS1IZXJyaW9044Oi44OH44Or44Gu6Kqs5piO44KS6L+95Yqg44CCDQo+ICAgICAgICAgICAgICDjgb7jgaDjgb7jgaDjgZPjgozjgYvjgonjgaAuLi4NCj4gLSAyMDE4LzA2LzI3IEZheS1IZXJyaW9044Oi44OH44OrKG1pbGvjg4fjg7zjgr8p44KSLCBCYXllc1NBReODkeODg+OCseODvOOCuCwNCj4gICAgICAgICAgICAgIG5sbWXjg5Hjg4PjgrHjg7zjgrjjgafjgoLoqabjgZfjgZ/jgIINCj4gLSAyMDE4LzA2LzI4IOOBoeOCh+OBo+OBqOOBoOOBkeabtOaWsOOAguepuumWk0ZI44Oi44OH44Or44Gr6YCy44KA5YuH5rCX44GM44G+44Gg5Ye644Gq44GELi4uDQo+IC0gMjAxOC8wNi8yOSBGYXktSGVycmlvdOODouODh+ODq+OBruOCt+ODn+ODpeODrOODvOOCt+ODp+ODs+OCkui/veWKoOOAguOBhOOCjeOBhOOCjeOBqA0KPiAgICAgICAgICAgICAg55m66KaL44GM44GC44KK44G+44GX44Gf44CCDQo+IC0gMjAxOC8wNy8wMSDnqbrplpNGYXktSGVycmlvdOODouODh+ODq+OBruWun+e/kuOCkui/veWKoOOAgg0KPiAtIDIwMTgvMDcvMDIg56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjga7lrp/nv5LjgavjgIFCYXllc1NBReODkeODg+OCseODvOOCuOOBqHNwZGVw44OR44OD44Kx44O844K444KSDQo+ICAgICAgICAgICAgICDov73liqDjgIJSTeacrOOBruOBleOBleOChOOBi+OBquiqpOOCiuOBruOBm+OBhOOBp+OAgeOBiOOCieOBhOebruOBqy4uLg0KPiAtIDIwMTgvMDcvMDUg6Kqk5a2X44Gq44Gp44Gu5L+u5q2j44CCDQo+IC0gMjAxOC8wNy8wOCDjgojjgYbjgoTjgY/nqbrplpNGYXktSGVycmlvdOODouODh+ODq+OBruWun+e/kuOCkue1guS6huOAgumVt+OBi+OBo+OBn+OAgg0KPiAtIDIwMTgvMDcvMDkgRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjga7lrp/nv5Ljgatyc3RhbuOCkui/veWKoOOAgg0KPiAtIDIwMTgvMDcvMTAg56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjga7lrp/nv5Ljgatyc3RhbuOCkui/veWKoOOAgg0KPiAtIDIwMTgvMDcvMTIg6Kqk5a2X44Gq44Gp6KiC5q2j44CC44GE44Gj44Gf44KT44GT44KM44Gn57WC5LqG44Go44GX44G+44GZ44CCDQo+IC0gMjAxOC8wNy8xOCDoqqTlrZfjgarjganoqILmraPjgIINCj4gLSAyMDE4LzA3LzE5IOiqpOWtl+OBquOBqeioguato+OAgg0KDQojIDEuIOWwj+WcsOWfn+aOqOWumuOBqOOBrw0KDQrjgarjgavjgYvjga7kuovmn4TjgavjgaTjgYTjgabmqJnmnKzoqr/mn7vjgpLjgoTjgaPjgZ/jgajjgY3jgIHmqJnmnKzjgrXjgqTjgrrjga/lhajkvZPjgajjgZfjgabjga/ljYHliIbjgavlpKfjgY3jgYTjgpPjgaDjgZHjganjgIENCuaomeacrOOBjOOBquOCk+OCieOBi+OBruOBn+OBj+OBleOCk+OBruODieODoeOCpOODsyjjgZ/jgajjgYjjgbDlnLDln5/jgajjgYsp44Gr5YiG44GL44KM44Gm44GE44Gm44CBDQrjg4njg6HjgqTjg7PliKXjgavjgb/jgovjgajmqJnmnKzjgrXjgqTjgrrjgYzotrPjgorjgarjgYTjgIENCuWbsOOBo+OBn+OBquOAgeOBqOOBhOOBhuOBk+OBqOOBjOOBguOCi+OAgg0KDQrmqJnmnKzjgrXjgqTjgrrjgYzotrPjgorjgarjgYTjgpPjgarjgonjgIHjgYTjgZXjgY7jgojjgY/mjqjlrprjgpLjgYLjgY3jgonjgoHjgozjgbDjgYTjgYTjgagNCuaAneOBhuOCk+OBoOOBkeOBqeOAgeOBquOBi+OBquOBi+OBneOBhuOCguOBhOOBo+OBpuOBhOOCieOCjOOBquOBhOOAgg0K5qiZ5pys44K144Kk44K644GM5bCP44GV44GE44OJ44Oh44Kk44Oz44Gr44Gk44GE44Gm44KC44CB44Gq44KT44Go44GL44GX44Gm44Gd44KM44KJ44GX44GE5o6o5a6a5YCk44KS5rGC44KB44Gf44GE44CCDQrjgZPjgYbjgYTjgYbllY/poYzjgpIqKuWwj+WcsOWfn+aOqOWumioq44Go44GE44GG44CCDQoNCuWwj+WcsOWfn+aOqOWumuOBr+S4u+OBq+WFrOeahOe1seioiOOBruWIhumHjuOBp+eZuuWxleOBl+OBpuOBjeOBn+OCk+OBoOOBkeOBqeOAgeaomeacrOiqv+afu+OCkuWIqeeUqOOBmeOCi+S7luOBruWIhumHjg0KKOOBn+OBqOOBiOOBsOW4guWgtOiqv+afuynjga7plqLkv4LogIXjgavjgajjgaPjgabjgoLjgIHlrabjgbbkvqHlgKTjgYzjgYLjgovjgojjgYbjgavmgJ3jgYbjgIINCg0K44Go44GE44GG44KP44GR44Gn44CB5Lul5LiL44Gn44GvUuOCkuS9v+OBhOOAgeWwj+WcsOWfn+aOqOWumuOBruWun+e/kuOCkuOBhOOBn+OBl+OBvuOBmeOAgg0KDQojIyAxLjEg5bCP5Zyw5Z+f44Oi44OH44Or44Gr44KI44KL5o6o5a6aDQoNCuWwj+WcsOWfn+aOqOWumuOBruattOWPsuOBr+mVt+OBj+OAgeOBhOOCjeOCk+OBquOCouODl+ODreODvOODgeOBjOOBguOCi+OBjOOAgeOBneOCjOOCieOBr+S7peS4i+OBrjPjgaTjgavliIbpoZ7jgafjgY3jgovjgIINCg0KLSDnm7TmjqXmjqjlrpogLi4uIOOBguOCi+Wwj+WcsOWfn+OBrueJueaAp+OBq+OBpOOBhOOBpuOAgQ0KICAgICAgICAgICAgICAg44Gd44Gu5bCP5Zyw5Z+f44Gr44Gk44GE44Gm44Gu44OH44O844K/44Gg44GR44KS44Gk44GL44Gj44Gm5o6o5a6a44GZ44KL44CCDQogICAgICAgICAgICAgICBSTeacrOOBrjLnq6DjgIINCi0g6ZaT5o6l5o6o5a6aIC4uLiDjgYLjgovlsI/lnLDln5/jga7nibnmgKfjgavjgaTjgYTjgabjgIHku5bjga7lsI/lnLDln5/jga7jg4fjg7zjgr/jgoLkvb/jgYTjgarjgYzjgonmjqjlrprjgZnjgovjgIINCiAgICAtIOODh+OCtuOCpOODs+ODu+ODmeODvOOCuSAuLi4g6Kq/5p+744OH44K244Kk44Oz44Gr44Gk44GE44Gm44Gu5oOF5aCx44Gr5Z+644Gl44GE44Gm5o6o5a6a44GZ44KL44CCUk3mnKzjga4z56ug44CCDQogICAgLSDjg6Ljg4fjg6vjg7vjg5njg7zjgrkgLi4uIOODh+ODvOOCv+OBruiDjOW+jOOBq+e1seioiOeahOODouODh+ODqygqKuWwj+WcsOWfn+ODouODh+ODqyoqKeOCkuaDs+WumuOBl+OAgQ0KICAgICAgICAgICAgICAgICAgICAgICAgIOOBk+OBruODouODh+ODq+OCkuS9v+OBo+OBpuaOqOWumuOBmeOCi+OAglJN5pys44GuNOeroC0xMOeroOOAgg0KDQrmnKznqL/jgafjga/jg6Ljg4fjg6vjg7vjg5njg7zjgrnplpPmjqXmjqjlrprjgIHjgaTjgb7jgorjgIHlsI/lnLDln5/jg6Ljg4fjg6vjgavjgojjgovlsI/lnLDln5/mjqjlrprjgpLmibHjgYbjgIINCg0KIyMgMS4yLiDmjqjlrprmlrnms5UNCg0K5YWI44Gr6L+w44G544Gf44KI44GG44Gr44CBDQrlnLDln5/jg6Ljg4fjg6vjgavjgojjgovlsI/lnLDln5/mjqjlrprjgafjga/jgIENCigxKeODh+ODvOOCv+OBruiDjOW+jOOBq+OBquOCk+OCieOBi+OBruWwj+WcsOWfn+ODouODh+ODq+OCkuaDs+WumuOBl+OAgQ0KKDIp44Gd44Gu44Oi44OH44Or44KS44OH44O844K/44Gr44GC44Gm44Gv44KB44Gm44CB44Oi44OH44Or44Gu44OR44Op44Oh44O844K/44KS5o6o5a6a44GX44CBDQooMynjgZ3jgozjgpLpgJrjgZjjgabjgIHlsI/lnLDln5/jga7nibnmgKfjgavjgaTjgYTjgabmjqjlrprjgZfjgojjgYbjgajjgZnjgovjgo/jgZHjgafjgYLjgovjgIINCg0KKDEp44Gu5bCP5Zyw5Z+f44Oi44OH44Or44Gr44Gv44GE44KN44GE44KN44GC44KL44GM44CB44GE44Ga44KM44Gu5aC05ZCI44Gr44KC44CBDQooMikoMynjgavjgYrjgZHjgovmjqjlrprmlrnms5Uo5o6o5a6a6YeP44Gu44K/44Kk44OXKeOBr+OAgeWkp+OBjeOBj+WIhuOBkeOBpuasoeOBrjPnqK7poZ7jgafjgYLjgovjgIINCg0KLSDntYzpqJPnmoTmnIDoia/nt5rlvaLkuI3lgY/kuojmuKzmjqjlrpooKipFQkxVUOaOqOWumioqKeOAglJN5pysNeeroC0456ug44CCDQotIOe1jOmok+ODmeOCpOOCuuaOqOWumigqKkVC5o6o5a6aKiop44CCOeeroOOAgg0KLSDpmo7lsaTjg5njgqTjgrrmjqjlrpooKipIQuaOqOWumioqKeOAgjEw56ug44CCDQoNCuS7peS4i+OBp+OBr0VCTFVQ5o6o5a6a44GoSELmjqjlrprjgpLoqabjgZnjgIINCg0KRUJMVVDmjqjlrprjgafjga/jgIHjg6Ljg4fjg6vjga7jg5Hjg6njg6Hjg7zjgr/jgpLmrKHjga4y5q616ZqO44Gr44KP44GR44Gm5o6o5a6a44GZ44KL44CCDQoNCi0gU3RlcCAxLiDliIbmlaPmiJDliIbjgajlkbzjgbDjgozjgovjg5Hjg6njg6Hjg7zjgr/jgpLmjqjlrprjgZnjgovjgILjgZ3jga7mlrnms5XjgajjgZfjgabjgIENCiAgICAgICAgICAqKk1M5o6o5a6a6YePKiosICoqUkVNTOaOqOWumumHjyoqLCDjg6Ljg7zjg6Hjg7Pjg4jmjqjlrprph4/jgarjganjgYzjgYLjgovjgIINCi0gU3RlcCAyLiDku5bjga7jg5Hjg6njg6Hjg7zjgr/jgpLmjqjlrprjgZnjgovjgIINCg0KSELmjqjlrprjgafjga/jgIHjg4fjg7zjgr/jgajjg6Ljg4fjg6vjgavln7rjgaXjgY3jgIHlsI/lnLDln5/jga7nibnmgKfjgYzjganjgYbjgarjgaPjgabjgYTjgovjgYvjgpINCueiuueOh+WIhuW4g+OBruW9ouOBp+aOqOWumuOBmeOCiyjjgZPjgozjgpLjgIzkuovlvozliIbluIPjgI3jgajjgYTjgYYp44CC5LqL5b6M5YiG5biD44KS5rGC44KB44KL5pa55rOV44Gr44Gv44CBDQrlpKfjgY3jgY/liIbjgZHjgabmrKHjga4y44Gk44GM44GC44KL44CCDQoNCi0gKirmlbDlgKTnqY3liIYqKuOBq+OCiOOCi+aWueazleOAgg0KLSAqKk1DTUMqKuOBq+OCiOOCi+aWueazleOAgg0KDQojIDIuIOODkeODg+OCseODvOOCuOOBqOaxjueUqOmWouaVsA0KDQrku6XkuIvjga7lrp/nv5Ljgafjga/mrKHjga7jg5Hjg4PjgrHjg7zjgrjjgpLkvb/nlKjjgZnjgovjgIINCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCByZXN1bHRzPSJoaWRlIn0NCiMjIyB4IDwtIFN5cy5zZXRsb2NhbGUoIkxDX0FMTCIsIkVuZ2xpc2giKQ0KIyMjIA0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdyaWRFeHRyYSkgICMjIyBncmlkLmFycmFuZ2UoKQ0KbGlicmFyeShSLnV0aWxzKSAgICAjIyMgd2l0VGltZW91dCgpDQpsaWJyYXJ5KEdHYWxseSkgICAgICMjIyBnZ3BhaXJzKCkNCmxpYnJhcnkoaWdyYXBoKSAgICAgIyMjIHBsb3QgbmV0d29yayBncmFwaA0KbGlicmFyeSh0YWdjbG91ZCkgICAjIyMgc21vb3RoUGFsZXR0ZSgpDQpsaWJyYXJ5KHJhc3RlcikgICAgICMjIyByZXF1aXJlZCBieSB7cnN0YW59DQojIGxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KIyBsaWJyYXJ5KHNjYWxlcykNCiMgbGlicmFyeShjb2RhKQ0KIyMjDQojIyMgZm9yIHNtYWxsIGFyZWEgZXN0aW1hdGlvbg0KbGlicmFyeShzYWUpDQpsaWJyYXJ5KGhic2FlKQ0KbGlicmFyeShCYXllc1NBRSkNCmxpYnJhcnkobmxtZSkNCmxpYnJhcnkoc3BkZXApDQpsaWJyYXJ5KHJzdGFuKQ0KIyMjDQojIyMgZm9yIHJzdGFuDQpyc3Rhbl9vcHRpb25zKGF1dG9fd3JpdGUgPSBUUlVFKQ0Kb3B0aW9ucyhtYy5jb3Jlcz1wYXJhbGxlbDo6ZGV0ZWN0Q29yZXMoKSkNCg0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0V9DQpzZXNzaW9uSW5mbygpIA0KYGBgDQoNCuOBvuOBn+OAgeODgeODo+ODvOODiOS9nOaIkOOBruOBn+OCgeOBq+OAgeOBguOCieOBi+OBmOOCgeS7peS4i+OBruaxjueUqOeahOOBqumWouaVsOOCkuWumue+qeOBl+OBpuOBiuOBj+OAgg0KYGBge3J9DQoNCnN1Yl9QbG90VHdvRXN0aW1hdGUuMSA8LSBmdW5jdGlvbigNCiAgYWdFc3QxLCBhZ01TRTE9TlVMTCwgYWdFc3QyLCBhZ01TRTI9TlVMTCwgYXNMYWJlbCwgc1ZhckxhYmVsMSwgc1ZhckxhYmVsMg0KKXsNCiAgIyBwdXJwb3NlOiBwbG90IHNjYXR0ZXIgcGxvdHMgdG8gY29tcGFyZSB0d28gdHlwZSBvZiBlc3RpbWF0aW9uIA0KICAjIGFyZzoNCiAgIyAgIGFnRXN0MTogZXN0aW1hdGVzIG9mIHR5cGUgMQ0KICAjICAgYWdNU0UxOiBNU0VzIG9mIGFnRXN0MSAob3IgTlVMTCkNCiAgIyAgIGFnRXN0MjogZXN0aW1hdGVzIG9mIHR5cGUgMiAgDQogICMgICBhZ01TRTI6IE1TRTIgb2YgYWdFc3QyIChvciBOVUxMKQ0KICAjICAgYXNMYWJlbDogbGFiZWxzIA0KICAjICAgc1ZhckxhYmVsMTogYSBsYWJlbCBvZiBlc3RpbWF0aW9uIHR5cGUgMQ0KICAjICAgc1ZhckxhYmxlMTogYSBsYWJlbCBvZiBlc3RpbWF0aW9uIHR5cGUgMg0KICANCiAgYlBsb3RNU0UgPC0gIWlzLm51bGwoYWdNU0UxKQ0KICANCiAgIyB0cmFwcw0KICBzdG9waWZub3QobGVuZ3RoKGFnRXN0MSkgPT0gbGVuZ3RoKGFnRXN0MikpDQogIHN0b3BpZm5vdChsZW5ndGgoYWdFc3QxKSA9PSBsZW5ndGgoYXNMYWJlbCkpDQogIGlmIChiUGxvdE1TRSl7DQogICAgc3RvcGlmbm90KGxlbmd0aChhZ0VzdDEpID09IGxlbmd0aChhZ01TRTEpKQ0KICAgIHN0b3BpZm5vdChsZW5ndGgoYWdFc3QxKSA9PSBsZW5ndGgoYWdNU0UyKSkNCiAgfQ0KICANCiAgIyBwbG90IG9mIGVzdGltYXRlcw0KICBkZlBsb3RFc3QgPC0gZGF0YS5mcmFtZSgNCiAgICBnRXN0MSAgPSBhZ0VzdDEsIA0KICAgIGdFc3QyICA9IGFnRXN0MiwgDQogICAgc0xhYmVsID0gYXNMYWJlbA0KICApDQogIGcxIDwtIGdncGxvdChkYXRhPWRmUGxvdEVzdCwgYWVzKHggPSBnRXN0MSwgeSA9IGdFc3QyLCBsYWJlbD1zTGFiZWwpKQ0KICBnMSA8LSBnMSArIGdlb21fdGV4dChzaXplPTMpDQogIGcxIDwtIGcxICsgbGFicygNCiAgICB0aXRsZSA9IGV4cHJlc3Npb24oIkVzdGltYXRlIiksIA0KICAgIHggICAgID0gc1ZhckxhYmVsMSwNCiAgICB5ICAgICA9IHNWYXJMYWJlbDINCiAgKQ0KICBnMSA8LSBnMSArIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkNCiAgZzEgPC0gZzEgKyB0aGVtZV9idygpDQojIHByaW50KGcxKQ0KICANCiAgIyBwbG90IG9mIE1TRXMNCiAgaWYgKGJQbG90TVNFKXsNCiAgICBkZlBsb3RNU0UgPC0gZGF0YS5mcmFtZSgNCiAgICAgIGdNU0UxID0gYWdNU0UxLCANCiAgICAgIGdNU0UyID0gYWdNU0UyLCANCiAgICAgIHNMYWJlbCA9IGFzTGFiZWwNCiAgICApDQogICAgZzIgPC0gZ2dwbG90KGRhdGE9ZGZQbG90TVNFLCBhZXMoeCA9IGdNU0UxLCB5ID0gZ01TRTIsIGxhYmVsPXNMYWJlbCkpDQogICAgZzIgPC0gZzIgKyBnZW9tX3RleHQoc2l6ZT0zKQ0KICAgIGcyIDwtIGcyICsgbGFicygNCiAgICAgIHRpdGxlID0gZXhwcmVzc2lvbigiTVNFIiksIA0KICAgICAgeCAgICAgPSBzVmFyTGFiZWwxLA0KICAgICAgeSAgICAgPSBzVmFyTGFiZWwyDQogICAgKQ0KICAgIGcyIDwtIGcyICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKQ0KICAgIGcyIDwtIGcyICsgdGhlbWVfYncoKQ0KICAgIA0KICB9DQogIA0KICAjIHBsb3QNCiAgaWYgKGJQbG90TVNFKXsNCiAgICBncmlkLmFycmFuZ2UoZzEsIGcyLCBuY29sID0gMikgDQogIH0gZWxzZSB7DQogICAgcGxvdChnMSkNCiAgfQ0KfQ0KZ2dfY29sb3JfaHVlIDwtIGZ1bmN0aW9uKG4pIHsNCiAgIyBwdXJwb3NlOiBFbXVsYXRlIGdncGxvdDIgZGVmYXVsdCBjb2xvciBwYWxldHRlDQogICMgYXJnOg0KICAjICAgbjogbnVtYmVyIG9mIGNvbG9ycw0KICAjIHJldHVybjogDQogICMgICBhIHZlY3RvciBvZiBjb2xvcnMNCiAgIyBub3RlczsNCiAgIyAgIHNlZSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy84MTk3NTU5L2VtdWxhdGUtZ2dwbG90Mi1kZWZhdWx0LWNvbG9yLXBhbGV0dGUNCiAgDQogIGh1ZXMgPSBzZXEoMTUsIDM3NSwgbGVuZ3RoID0gbiArIDEpDQogIGhjbChoID0gaHVlcywgbCA9IDY1LCBjID0gMTAwKVsxOm5dDQogIA0KfQ0KDQpgYGANCg0K5Lul5LiL44Gn44Gv44CB5bCP5Zyw5Z+f5o6o5a6a44Gr55So44GE44KL44OR44OD44Kx44O844K444KS44GU57S55LuL44GX44G+44GZ44CCDQoNCiMjIDIuMSBbc2Fl44OR44OD44Kx44O844K4XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2FlL2luZGV4Lmh0bWwpDQoNClJN5pys44Gu6JGX6ICF44Gu44Gy44Go44KKTW9saW5h44GV44KT44GM6ZaL55m644Gr6Zai44KP44Gj44Gm44GE44KL44OR44OD44Kx44O844K444CCDQoNCuOBk+OBruODkeODg+OCseODvOOCuOOBjOaPkOS+m+OBmeOCi+mWouaVsOOBr+S7peS4i+OBrumAmuOCiuOAgg0KDQotIOWwj+WcsOWfn+ODouODh+ODq+OBq+OCiOOCi+aOqOWumg0KICAgIC0gRmF5LUhlcnJpb3Tjg6Ljg4fjg6sgLi4uIGVibHVwRkgoKSwgbXNlRkgoKQ0KICAgIC0g56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6sgLi4uIGVibHVwU0ZIKCksIG1zZVNGSCgpLCBwYm1zZVNGSCgpLCBucGJtc2VTRkgoKQ0KICAgIC0g5pmC56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6sgLi4uIGVibHVwU1RGSCgpLCBwYm1zZVNURkgoKQ0KICAgIC0g44Om44OL44OD44OI44Os44OZ44Or44Oi44OH44OrIC4uLiBlYmx1cEJIRigpLCBwYm1zZUJIRigpLCBwYm1zZWViQkhGKCksIGViQkhGKCkNCi0g55u05o6l5o6o5a6a44O744OH44K244Kk44Oz44OZ44O844K55o6o5a6aIC4uLiBkaXJlY3QoKSwgcHNzeW50KCksIHNzZCgpDQotIOODhOODvOODqy4uLiBieGN4KCksIGRpYWdvbmFsaXplbWF0cml4KCkNCg0Kc2Fl44OR44OD44Kx44O844K444Gn5bCP5Zyw5Z+f44Oi44OH44Or44KS5o6o5a6a44GZ44KL5aC05ZCI44CB5o6o5a6a6YeP44GvRUJMVVDjgafjgYLjgovjgILliIbmlaPmiJDliIbjga4NCuaOqOWumumHj+OBr+OBhOOBj+OBpOOBi+OBrumBuOaKnuiCouOBi+OCiemBuOOBtuOBk+OBqOOBjOOBp+OBjeOCi+OAgg0KDQojIyAyLjIgW2hic2Fl44OR44OD44Kx44O844K4XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvaGJzYWUvaW5kZXguaHRtbCkNCg0K5bCP5Zyw5Z+f5o6o5a6a44Gu44OR44OD44Kx44O844K444Go44GX44Gm44Gv5Y+k5qCq44CCDQrplovnmbrogIXjga7mlrnjga5b44OX44Os44K844Oz6LOH5paZXShodHRwOi8vc2FlMjAxNC51ZS5wb3puYW4ucGwvcHJlc2VudGF0aW9ucy9TQUUyMDE0X0hhcm1fSmFuX0Jvb25zdHJhXzdjNTk4MzViM2UucGRmKeOBq+OCiOOCjOOBsOOAgeOBk+OBruaWueOBr+OCquODqeODs+ODgOe1seioiOWxgOOBq+OBiuWLpOOCgeOBp+OAgeOBk+OBruODkeODg+OCseODvOOCuOOBr+OCquODqeODs+ODgOOBruWKtOWDjeWKm+iqv+afu+OBp+Wun+mam+OBq+S9v+OCj+OCjOOBpuOBhOOCi+OCk+OBoOOBneOBhuOBp+OBmeOAguOBneOBhuOBhOOCj+OCjOOCi+OBqOOBkOOBo+OBqOS/oemgvOaEn+OBjOWil+OBl+OBvuOBmeOBreOAgg0KDQrjgZPjga7jg5Hjg4PjgrHjg7zjgrjjgYzmj5DkvpvjgZnjgovplqLmlbDjga/ku6XkuIvjga7pgJrjgorjgIINCg0KLSDlsI/lnLDln5/jg6Ljg4fjg6vjgavjgojjgovmjqjlrpogLi4uIGZTQUUoKSwgZlNBRS5BcmVhKCksIGZTQUUuVW5pdCgpDQotIOebtOaOpeaOqOWumiAuLi4gZlN1cnZSZWcoKQ0KLSDjg4Tjg7zjg6sgLi4uIGFnZ3IoKSwgYmVuY2goKSwgQ1ZhcmVhKCksIGdlbmVyYXRlRmFrZURhdGEoKSwgdXdlaWdodHMoKQ0KDQrlsI/lnLDln5/jg6Ljg4fjg6vjgpLmjqjlrprjgZnjgovloLTlkIjjgIHmjqjlrprph4/jgajjgZfjgaZFQkxVUOOBqEhC44GM55So5oSP44GV44KM44Gm44GE44KL44CCRUJMVVDmjqjlrprjga7loLTlkIjjgIENCuWIhuaVo+aIkOWIhuOBruaOqOWumumHj+OBr+OBhOOBj+OBpOOBi+OBrumBuOaKnuiCouOBi+OCiemBuOOBtuOBk+OBqOOBjOOBp+OBjeOCi+OAgg0KSELmjqjlrprjga/mlbDlgKTnqY3liIbjgpLkvb/nlKjjgZnjgovjgIINCg0KIyMgMi4zIFtCYXllc1NBReODkeODg+OCseODvOOCuF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL0JheWVzU0FFL2luZGV4Lmh0bWwpDQoNCkZheS1IZXJyaW9044Oi44OH44OrKOW+jOi/sOOBmeOCiynjga5IQuaOqOWumuOBq+eJueWMluOBl+OBn+ODkeODg+OCseODvOOCuOOAgg0KDQrjgZPjga7jg5Hjg4PjgrHjg7zjgrjjgYzmj5DkvpvjgZnjgovplqLmlbDjga8gQmF5ZXNTQUUoKeOBp+OBguOCi+OAguOCt+ODs+ODl+ODq+OBp+OCiOOCjeOBl+OBhOOAgg0KDQrmjqjlrprph4/jga9IQuOBruOBv+OAgk1DTUPjgpLkvb/nlKjjgZnjgovjgIINCg0KIyMgMi40IFtubG1l44OR44OD44Kx44O844K4XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbmxtZS9pbmRleC5odG1sKQ0KDQrlsI/lnLDln5/mjqjlrprjgavpmZDjgonjgZrjgIHnt5rlvaLjg7vpnZ7nt5rlvaLjga7mt7flkIjjg6Ljg4fjg6vjga7jgZ/jgoHjga7jg5Hjg4PjgrHjg7zjgrjjgIINClLjga7jgrPjgqLjg5Hjg4PjgrHjg7zjgrjjgafjgYLjgovjgIINCg0K5bCP5Zyw5Z+f44Oi44OH44Or44Gv5Z+65pys55qE44Gr44Gv5LiA56iu44Gu5re35ZCI44Oi44OH44Or44Gq44Gu44Gn44CBDQrjgZPjgYbjgYTjgYbmsY7nlKjnmoTjgarjg5Hjg4PjgrHjg7zjgrjjgafjgoLmjqjlrprjgafjgY3jgosuLi7jga/jgZrjgafjgYLjgovjgIINCg0K5o6o5a6a6YeP44GvRUJMVVDjgILliIbmlaPmiJDliIbjga7mjqjlrprph4/jga/jgYTjgY/jgaTjgYvjga7pgbjmip7ogqLjgYvjgonpgbjjgbnjgovjgIINCg0KIyMgMi41IFtzcGRlcOODkeODg+OCseODvOOCuF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NwZGVwL2luZGV4Lmh0bWwpDQoNCuWwj+WcsOWfn+aOqOWumuOBqOOBhOOBhuOCiOOCiuOAgeepuumWk+ODh+ODvOOCv+WIhuaekOOBruWfuuacrOODkeODg+OCseODvOOCuOOAguWkmueoruWkmuanmOOBquapn+iDveOCkg0K5o+Q5L6b44GX44Gm44GE44KL44CCDQoNCuepuumWk0ZheS1IYXJyaWV044Oi44OH44Or44Gv6KaB44GZ44KL44GrU0FSKOWQjOaZguiHquW3seWbnuW4sCnjg6Ljg4fjg6vjgarjga7jgafjgIENCuOBk+OBhuOBhOOBhuaxjueUqOeahOOBquODkeODg+OCseODvOOCuOOBp+OCguaOqOWumuOBp+OBjeOCi+OBr+OBmuOBoC4uLuOBqOaAneOBo+OBn+OCk+OBp+OBmeOAgg0KDQrlsI/lnLDln5/jga7nibnmgKfjgpLmjqjmuKzjgZnjgovloLTlkIjjgIHmjqjlrprph4/jga9FQkxVUOOBoOOBqOOBhOOBhuOBk+OBqOOBq+OBquOCi+OBqA0K5oCd44GG44Gu44Gn44GZ44GMLi4uIOOBmeOBhOOBvuOBm+OCk+OAgeOCiOOBj+OCj+OBi+OCieOBquOBhOOBo+OBmeOAgg0KDQojIyAyLjYgW3JzdGFu44OR44OD44Kx44O844K4XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcnN0YW4vaW5kZXguaHRtbCkNCg0K5rOj44GP5a2Q44KC6buZ44KL44CB44OZ44Kk44K444Ki44Oz44O744Oi44OH44Oq44Oz44Kw44Gu44Gf44KB44GuDQrmsY7nlKjjg5Hjg4PjgrHjg7zjgrjjgILjgarjgovjgbnjgY/jgarjgonop6bjgorjgZ/jgY/jgarjgYTjga7jgafjgZnjgYzjgIHjgZPjga7jgZ/jgbPjga/ku5XmlrnjgarjgY8uLi7jgIINCg0K5o6o5a6a6YeP44GvSELjgIJNQ01D44KS5Yip55So44GZ44KL44CCDQoNCiMgMy4g5Zyw5Z+f44Os44OZ44Or44Oi44OH44OrDQoNCiMjIDMuMSBGYXktSGVycmlvdOODouODh+ODq+OBqOOBrw0KDQoo5pys56+A44GvUk3mnKw0LjLnr4AsIDYuMeevgCwgMTAuM+evgOOBruOBvuOBqOOCgeOBp+OBguOCi+OAgikNCg0KRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgajjga/jgIHlsI/lnLDln5/jg6zjg5njg6vjga7jg4fjg7zjgr/jgpLkvb/jgaPjgaYNCuWwj+WcsOWfn+eJueaAp+OCkuaOqOWumuOBmeOCi+OBn+OCgeOBruODouODh+ODq+OBp+OBguOCi+OAgg0KDQrlnLDln58kaSQoJD0xLFxsZG90cyxtJCnjgavjgYrjgZHjgovjgIHjgarjgavjgYvjga7lpInmlbDjga7lubPlnYco44Gf44Go44GI44Gw5LiA5Lq65b2T44Gf44KK5omA5b6XKeOCkiRcYmFye1l9X2kk44Go44GZ44KL44CCDQoNCiRcYmFye1l9X2kk44Gd44Gu44KC44Gu44Gr44Gk44GE44Gm44Gv44KP44GL44KJ44Gq44GE44GM44CBDQrjgZ3jga7lnLDln5/jga7mqJnmnKzjgYvjgonjgIHnm7TmjqXmjqjlrprph48kXGhhdHtcYmFye1l9fV9pJCjlhbjlnovnmoTjgavjga/mqJnmnKzlubPlnYcpDQrjgYzmiYvjgavlhaXjgaPjgabjgYTjgovjgajjgZfjgojjgYbjgILjgZ/jgaDjgZfjgIHmqJnmnKzjgrXjgqTjgrrjgYzljYHliIbjgafjgarjgYTjga7jgafjgIENCuOBk+OBruWApOOBjOOBguOBpuOBq+OBquOCieOBquOBhC4uLuOAgOOBqOOBhOOBhuOBruOBjOWVj+mhjOOBrueZuuerr+OBp+OBguOCi+OAgg0KDQrjgarjgpPjgonjgYvjga7plqLmlbAkZyhcY2RvdCkk44GM44GC44Gj44Gm44CBJFx0aGV0YV9pID0gZyhcYmFye1l9X2kpJOOBp+OBguOCi+OBqOOBmeOCi+OAgg0K5YW45Z6L55qE44Gr44GvJFx0aGV0YV9pID0gXGJhcntZfV9pJOOBp+OBguOCi+OAgg0K5ZCM5qeY44Gr44CBJFxoYXR7XHRoZXRhfV9pID0gZyhcaGF0e1xiYXJ7WX19X2kpJOOBqOOBmeOCi+OAgg0KDQrku6XkuIrjga7jg4fjg7zjgr/jgajjgajjgoLjgavjgIENCuWcsOWfn+OBruijnOi2s+ODh+ODvOOCvyRcbWF0aGJme3p9X2kkKOmVt+OBlSRwJOOBruODmeOCr+ODiOODqynjgoLmiYvjgavlhaXjgaPjgabjgYTjgovjgajjgZnjgovjgIINCuOBpOOBvuOCiuOAgeOBneOBruWcsOWfn+OBriRcdGhldGFfaSTjgpLkuojmuKzjgZnjgovjga7jgavlvbnnq4vjgaTjgojjgYbjgarjgIHjgarjgpPjgonjgYvjga7lpInmlbDnvqTjgavjgaTjgYTjgabjga4NCuWApOOBp+OBguOCi+OAgg0KDQrjgZXjgabjgIHlkITlnLDln5/jga4kXGJhcntZfV9pJOOBq+OBpOOBhOOBpuaOqOa4rOOBl+OBn+OBhOOAgg0K44Gd44GT44Gn5Lul5LiL44Gu44KI44GG44Gr5oOz5a6a44GZ44KL44CC44Gq44GK5Lul5LiL44Gn44Gv44CB5aSJ5pWwJHgk44GM5bmz5Z2HMCwg5YiG5pWjJFxzaWdtYV4yJOOBruOBquOCk+OCieOBi+OBruWIhuW4g+OBqw0K5b6T44GG44Go44GE44GG44GT44Go44KS44CBJHggXHNpbSAoMCwgXHNpZ21hXjIpJOOBqOeVpeiomOOBmeOCi+OAgg0KDQrjgb7jgZrjgIENCiQkIFx0aGV0YV9pID0gXG1hdGhiZnt6fV9pXlQgXG1hdGhiZntcYmV0YX0gKyB2X2ksIFwgXCB2X2kgXHNpbSAoMCwgXHNpZ21hX3ZeMikkJA0KDQoNCuOBqOiAg+OBiOOCi+OAgg0K44Gk44G+44KK44CB6Zai5b+D44Gu5a++6LGh44Gn44GC44KL5Zyw5Z+f54m55oCnKCRcdGhldGFfaSQp44Gv44CB44Gd44Gu5Zyw5Z+f44Gu6KOc6Laz44OH44O844K/JFxtYXRoYmZ7en1faSQNCuOBp+axuuOBvuOBo+OBpuOBhOOCi+mDqOWIhuOBqOOAgeOBneOCjOS7peWkluOBrumDqOWIhijjgYTjgo/jgbDjgIzlnLDln5/lirnmnpzjgI0pJHZfaSTjga7lkozjgaDjgajogIPjgYjjgovjgo/jgZHjgafjgYLjgovjgIINCuOBleOCieOBq+OAgeWcsOWfn+WKueaenOOBr+ODqeODs+ODgOODoOOBq+axuuOBvuOCiuOAgeOBneOBruW5s+Wdh+OBrzDjgafjgIHliIbmlaPjga8kXHNpZ21hX3ZeMiTjgaDjgajogIPjgYjjgovjgIINCg0K5qyh44Gr44CBDQokJFxoYXR7XHRoZXRhfV9pID0gXHRoZXRhX2kgKyBlX2ksIFwgXCBlX2l8XHRoZXRhX2kgXHNpbSAoMCwgXHBzaV9pKSQkDQoNCg0K44Go6ICD44GI44KL44CC44Gk44G+44KK44CB5omL5YWD44Gr44GC44KL55u05o6l5o6o5a6a6YePJFxoYXR7XHRoZXRhfV9pJOOBr+OAgeWcsOWfn+eJueaAp+OBruecn+OBruWApA0KKCRcdGhldGFfaSQp44KS5Y+N5pig44GX44Gm44Gv44GE44KL44GM44CB5qiZ5pys6Kq/5p+744Gr44Gk44GN44KC44Gu44Gn44GC44KL5qiZ5pys5oq95Ye66Kqk5beuJGVfaSTjgoINCuWQq+OCk+OBp+OBl+OBvuOBo+OBpuOBhOOCi+OAgeOBqOiAg+OBiOOCi+OCj+OBkeOBp+OBguOCi+OAguOBleOCieOBq+OAgeWQhOWcsOWfn+OBruaomeacrOaKveWHuuiqpOW3ruOBrw0K44Op44Oz44OA44Og44Gr5rG644G+44KK44CB44Gd44Gu5bmz5Z2H44GvMOOBp+OAgeWIhuaVo+OBryRccHNpX2kk44Gg44Go6ICD44GI44KL44CCDQokXHBzaV9pJOOBq+OBpOOBhOOBpuOBr+aXouefpeOBqOOBmeOCi+OAgg0KDQrjgZPjga7jg6Ljg4fjg6vjgavln7rjgaXjgY3jgIEkXHRoZXRhX2kk44Gr44Gk44GE44Gm5o6o5a6a44GZ44KL44GT44Go44GM44Gn44GN44KL44CCDQrjgZPjgozjgYxGYXktSGVycmlvdOODouODh+ODq+OBp+OBguOCi+OAgg0KDQrjgafjga/jgIFGYXktSGVycmlvdOODouODh+ODq+OBruODkeODqeODoeODvOOCvw0KKCRcbWF0aGJme1xiZXRhfSQsICRcc2lnbWFfdl4yJCnjgpLjganjgYbjgoTjgaPjgabmjqjlrprjgZnjgovjgYvjgIINCg0KRUJMVVDmjqjlrprjga7loLTlkIjjga/jgIHjgb7jgZokXHNpZ21hX3ZeMiTjgpLmjqjlrprjgZfjgIHmrKHjgaskXG1hdGhiZntcYmV0YX0k44KEDQokXHRoZXRhX2kk44KS5o6o5a6a44GZ44KL44CCDQoNCkhC5o6o5a6a44Gu5aC05ZCI44Gv44CBRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgpLmrKHjga7pmo7lsaTjg5njgqTjgrrjg6Ljg4fjg6vjgavmm7jjgY3mj5vjgYjjgovjgIINCg0KJCQNClxiZWdpbnthbGlnbmVkfQ0KICB7XHJtIChpKX0gXCBcICYgDQogIFxoYXR7XHRoZXRhfV9pIHwgXHRoZXRhX2ksIFxtYXRoYmZ7XGJldGF9LCBcc2lnbWFeMl92DQogIFxtYXRob3B7XHNpbX1ee2lpZH0gTihcdGhldGFfaSwgXHBzaV9pKSwgXCBcICBpID0gMSwgXGxkb3RzLCBtIFxcDQogIHtccm0gKGlpKX0gIFwgXCAmDQogIFx0aGV0YV9pIHwgXG1hdGhiZntcYmV0YX0sIFxzaWdtYV4yX3YgDQogIFxtYXRob3B7XHNpbX1ee2lpZH0gTihcbWF0aGJme3p9X2leVCwgXHNpZ21hX3ZeMiksIFwgXCANCiAgaSA9IDEsIFxsZG90cywgbSBcXA0KICB7XHJtIChpaWkpfSAgXCBcICYNCiAgZihcbWF0aGJme1xiZXRhfSwgXHNpZ21hXjJfdikgDQogID0gZihcbWF0aGJme1xiZXRhfSkgZihcc2lnbWFeMl92KSBccHJvcHRvIGYoXHNpZ21hXjJfdikNClxlbmR7YWxpZ25lZH0NCiQkDQrjgZPjga7jg6Ljg4fjg6vjgpLmjqjlrprjgZnjgovjgZ/jgoHjgavjga/jgIEkXHNpZ21hXjJfdiTjga7kuovliY3liIbluIMkZihcc2lnbWFeMl92KSTjgpLmjIflrprjgZnjgovlv4XopoHjgYzjgYLjgovjgIINCg0K5Luj6KGo55qE44Gq5o6o5a6a5pa55rOV44Go44GX44Gm44CB5qyh44GuMuOBpOOBjOOBguOCi+OAgg0KDQotICRmKFxzaWdtYV4yX3YpIFxwcm9wdG8gMSQg44Go5oyH5a6a44GX44CBJFx0aGV0YV9pJOOCkuaVsOWApOepjeWIhuOBq+OCiOOCiuaOqOWumuOBmeOCi+OAgg0KLSAkXHNpZ21hX3Zeey0yfSBcc2ltIEcoYSxiKSTjgajmjIflrprjgZfjgIEkXHRoZXRhX2kk44KSTUNNQ+OBq+OCiOOCiuaOqOWumuOBmeOCi+OAgg0KDQojIyAzLjIg5a6f57+SOiBtaWxrDQo8IS0tIGNodW5r44KS6LaF44GI44KL44Kq44OW44K444Kn44Kv44OI44GvYS7jgYvjgonlp4vjgoHjgosgLS0+DQoNCuOBvuOBmuOBr+OBi+OCk+OBn+OCk+OBquODh+ODvOOCv+OBq+OBpOOBhOOBpuOAgeWfuuacrOeahOOBqkZheS1IZXJyaW9044Oi44OH44Or44KS5o6o5a6a44GX44Gm44G/44KI44GG44CCDQoNCiMjIyAzLjIuMSDjg4fjg7zjgr8NCg0Kc2Fl44OR44OD44Kx44O844K444Gr44Gk44GE44Gm44GE44KL44K144Oz44OX44Or44OH44O844K/IG1pbGsg44KS5L2/44GG44CCDQrjgZPjga7jg4fjg7zjgr/jga/jgIE0M+WcsOWfn+OBq+OBpOOBhOOBpuS7peS4i+OBruWkieaVsOOCkuaMgeOBo+OBpuOBhOOCi+OAgg0KDQotIFNtYWxsQXJlYTog5Zyw5Z+f55Wq5Y+3DQotIG5pOiDmqJnmnKzjgrXjgqTjgroNCi0geWk6IOeUn+S5s+OBruW5tOmWk+aUr+WHuuOBruaomeacrOW5s+Wdhw0KLSBTRDog55Sf5Lmz44Gu5bm06ZaT5pSv5Ye644Gu5qiZ5pys5bmz5Z2H44GuU0Tjga7mjqjlrprlgKTjgILjgaTjgb7jgopTReOAgg0KLSBDVjog5aSJ5YuV5L+C5pWwKENWKQ0KLSBNYWpvckFyZWE6IOS4iuS9jeWcsOWfn+eVquWPtw0KDQrjg4fjg7zjgr/jga7lh7rlhbjjgajjgarjgaPjgabjgYTjgovoq5bmlocgQXJvcmEgJiBMYWhpcmkgKDE5OTcpIOOCkuOBguOBn+OBo+OBpuOBv+OBn+OBqOOBk+OCjeOAgeOBk+OCjOOBrzE5ODnlubTjga7jg4fjg7zjgr/jgafjgIHlnLDln5/jga8NCiJwdWJsaWNhdGlvbiBhcmVhIuOBoOOBneOBhuOBp+OBguOCiyjmgaXjgZrjgYvjgZfjgarjgYzjgonmhI/lkbPjgYzjgo/jgYvjgorjgb7jgZvjgpMp44CCDQrjgarjgYrjgIFNYWpvckFyZWHjga/nj77oq5bmlofjgavjga/jgarjgYTjgILjgYLjgajjgYvjgonku5jjgZHjgZ/jgoLjga7jgonjgZfjgYTjgIINCg0KYGBge3J9DQojIyMgYS5kZk1pbGs6IGRhdGFzZXQNCmRhdGEobWlsaywgcGFja2FnZT0ic2FlIikNCmEuZGZNaWxrIDwtIG1pbGsgJT4lDQogIG11dGF0ZSgNCiAgICBTbWFsbEFyZWEgPSBhcy5mYWN0b3IoU21hbGxBcmVhKSwNCiAgICBNYWpvckFyZWEgPSBhcy5mYWN0b3IoTWFqb3JBcmVhKSwgDQogICAgdmFyID0gU0ReMg0KICApDQpybShtaWxrKQ0KcHJpbnQoYS5kZk1pbGsgJT4lIGRwbHlyOjpzZWxlY3QoLXZhcikpDQpgYGANCuWQhOWcsOWfn+OBruaomeacrOOCteOCpOOCuuOBrzk144GL44KJNjMz44CC5bCP5Zyw5Z+f44GY44KD44Gq44GE44GY44KD44KT77yB44GT44KM44Gn5Y2B5YiG44GY44KD44KT77yBDQrjgajnp4HjgarjgpPjgYvjga/mgJ3jgYbjgo/jgZHjgafjgZnjgYzjgIHjgZ3jga7jgbjjgpPjga/liIbph47jgavjgojjgovjgpPjgafjgZfjgofjgYbjga3jgIINCg0K5ZCE5Zyw5Z+f44Gu5pSv5Ye644KS44OB44Oj44O844OI44Gr44GX44Gm44G/44KI44GG44CCDQpgYGB7cn0NCmcgPC0gZ2dwbG90KA0KICBkYXRhID0gYS5kZk1pbGssIA0KICBhZXMoDQogICAgeCAgICAgPSBTbWFsbEFyZWEsIA0KICAgIHkgICAgID0geWksIA0KICAgIHltaW4gID0geWkgLSBTRCwgDQogICAgeW1heCAgPSB5aSArIFNELCANCiAgICBjb2xvciA9IE1ham9yQXJlYQ0KICApDQopDQpnIDwtIGcgKyBnZW9tX3BvaW50cmFuZ2UoKQ0KZyA8LSBnICsgbGFicygNCiAgeCAgICAgPSAiU21hbGwgQXJlYSIsIA0KICB5ICAgICA9IGV4cHJlc3Npb24obWVhbiAlKy0lIFNFKSwgDQogIGNvbG9yID0gIk1ham9yIEFyZWEiDQopDQpnIDwtIGcgKyB0aGVtZV9idygpDQpwcmludChnKQ0KYGBgDQrkuIrkvY3lnLDln5/nlarlj7fjgavjgojjgaPjgabmlK/lh7rjgYznlbDjgarjgovjgZPjgajjgYzjgo/jgYvjgovjgILlhbHlpInph4/jgavjgZnjgovjgajjgojjgZXjgZ3jgYbjgaDjgIINCg0KIyMjIDMuMi4yIHNhZeODkeODg+OCseODvOOCuOOBq+OCiOOCi+aOqOWumg0KDQoo5pys56+A44GvUk3mnKw2LjXnr4Djga7lho3nj77jgafjgYLjgovjgIIpDQoNCuOBvuOBmuOBr3NhZeODkeODg+OCseODvOOCuOOBp+aOqOWumuOBl+OBpuOBv+OCiOOBhuOAgg0KDQpzYWXjg5Hjg4PjgrHjg7zjgrjjgafjga/jgIENCuWfuuacrOeahOOBqkZheS1IZXJyaW9044Oi44OH44Or44Gu6Zai5pWw44Go44GX44Gm44CBDQplYmx1cEZIKCnjgahtc2VGSCgp44GM55So5oSP44GV44KM44Gm44GE44KL44CCZWJsdXBGSCgp44Gv5o6o5a6a5YCk44GX44GL6L+U44GV44Gq44GE44GM44CBDQptc2VGSCgp44Gv5o6o5a6a6YeP44GuTVNF44Gu5o6o5a6a5YCk44KC6L+U44GZ44CB44Go44GE44GGDQrpgZXjgYTjgYzjgYLjgovjgonjgZfjgYTjgIINCuS7peS4i+OBp+OBr21zZUZIKCnjgpLkvb/jgYbjgZPjgajjgavjgZnjgovjgIINCg0K44G+44Ga44CB5YWx5aSJ6YeP44Gq44GX44Gn44CCDQo8IS0tIOOBquOBnOOBi+OCj+OBi+OCieOBquOBhOOCk+OBoOOBkeOBqSwgZGF0YT3jgpLjgaTjgZHjgablpInmlbDlkI3jgpLjgZjjgYvjgavmm7jjgY/jgajjgYbjgb7jgY/li5XjgYvjgarjgYTjga7jgafjgIEgLS0+DQo8IS0tIOODh+ODvOOCv+OCu+ODg+ODiOWQjeOCkuOBhOOBoeOBhOOBoeabuOOBhOOBpuOBhOOCi+OAgiAtLT4NCmBgYHtyfQ0KIyMjIGEub01vZGVsX3NhZVJFTUxfbm94OiBzYWVSRU1MIG1vZGVsIHdpdGggbm8gY292YXJpYXRlDQphLm9Nb2RlbF9zYWVSRU1MX25veCA8LSBtc2VGSCgNCiAgZm9ybXVsYSA9IGEuZGZNaWxrJHlpIH4gMSwgDQogIHZhcmRpciAgPSBhLmRmTWlsayRTRCBeIDIsIA0KICBtZXRob2QgID0gIlJFTUwiDQopDQpgYGANCg0KLSBtZXRob2Q944Kq44OX44K344On44Oz44Gv44CBDQogICRcc2lnbWFfdV4yJOOBruaOqOWumumHj+OBruaMh+WumuOAgg0KICBSRU1MKOODh+ODleOCqeODq+ODiCksIE1MLCBGSOOCkumBuOOBueOCi+OAgkZI44Go44GE44GG44Gu44GvDQogIFJN5pysNi4xLjLnr4DjgafjgYTjgYbjgajjgZPjgo3jga7mlrnms5Ux44Gu44GT44Go44Gn44GC44KN44GG44CCDQotIGZvcm11bGE944Kq44OX44K344On44Oz44Gn5YWx5aSJ6YeP44KS5oyH5a6a44GZ44KL44CC44GT44GT44Gn44Gv5YiH54mH6aCF44Gu44G/5oyH5a6a44GX44Gm44GE44KL44CCDQotIHZhcmRpcj3jgqrjg5fjgrfjg6fjg7PjgafjgIHmqJnmnKzmir3lh7rliIbmlaMkXHBzaV9pJOOCkuaMh+WumuOBmeOCi+OAgg0KICDjgZPjgZPjgafjga8kXHBzaV9pJOOBruS7o+eUqOOBqOOBl+OBpuOAgeWQhOWcsOWfn+OBq+OBiuOBkeOCi+aomeacrOW5s+Wdh+OBruWIhuaVo+OBruaOqOWumuWApA0KICAo44Gk44G+44KK5qiZ5pys5bmz5Z2H44Gu5qiZ5rqW6Kqk5beu44Gu5LqM5LmXKeOCkuS9v+eUqOOBl+OBpuOBhOOCi+OAgg0KDQpgYGB7cn0NCmNhdCgicmVmdmFyOiIsIGEub01vZGVsX3NhZVJFTUxfbm94JGVzdCRmaXQkcmVmdmFyLCAiXG4iKQ0KYGBgDQokXHNpZ21hX3ZeMiTjga8wLjA1NDMx44Go5o6o5a6a44GV44KM44Gf44CCDQoNCuOBp+OBr+OAgeWFseWkiemHj+OBqOOBl+OBpuS4iuS9jeWcsOWfn+eVquWPt+OCkuOBhOOCjOOBpuOBv+OCiOOBhuOAgg0KYGBge3J9DQojIyMgYS5vTW9kZWxfc2FlUkVNTDogc2FlUkVNTCBtb2RlbA0KYS5vTW9kZWxfc2FlUkVNTCA8LSBtc2VGSCgNCiAgZm9ybXVsYSA9IGEuZGZNaWxrJHlpIH4gYS5kZk1pbGskTWFqb3JBcmVhLCANCiAgdmFyZGlyICA9IGEuZGZNaWxrJFNEIF4gMiwgDQogIG1ldGhvZCAgPSAiUkVNTCINCikNCmNhdCgicmVmdmFyOiIsIGEub01vZGVsX3NhZVJFTUwkZXN0JGZpdCRyZWZ2YXIsICJcbiIpDQpgYGANCiRcc2lnbWFfdl4yJOOBrzAuMDE4NTXjgajmjqjlrprjgZXjgozjgZ/jgILjgZDjgaPjgajkuIvjgYzjgaPjgabjgYTjgovjgIINCg0KJFxtYXRoYmZ7XGJldGF9JOOBry4uLg0KYGBge3J9DQpwcmludChhLm9Nb2RlbF9zYWVSRU1MJGVzdCRmaXQkZXN0Y29lZikNCmBgYA0KDQroqabjgb/jgavjgIHlnLDln5/lirnmnpwkdl9pJOOCkueEoeimluOBl+OBn+WbnuW4sOODouODh+ODq+OCkuaOqOWumuOBl+OBpuOBv+OCiOOBhuOAgg0KYGBge3J9DQpwcmludChzdW1tYXJ5KGxtKHlpIH4gTWFqb3JBcmVhLCBkYXRhID0gYS5kZk1pbGspKSRjb2VmZmljaWVudHMpDQoNCmBgYA0K5Zu65a6a5Yq55p6c44Gu5L+C5pWw44Gu5o6o5a6a5YCk44GM55Ww44Gq44KL44CC44Gk44G+44KK44CB55u05o6l5o6o5a6a6YePJFxoYXR7XHRoZXRhfV9pJA0K44KS55uu55qE5aSJ5pWw44Go44GX44Gm44CBDQpGYXktSGVycmlvdOODouODh+ODqw0KJCRcaGF0e1x0aGV0YX1faSA9IFxtYXRoYmZ7en1faV5UIFxtYXRoYmZ7XGJldGF9ICsgdl9pICsgZV9pJCQNCuOCkuaOqOWumuOBl+OBn+WgtOWQiOOBqOOAgQ0K5Zyw5Z+f5Yq55p6c44KS54Sh6KaW44GX44Gf5Zue5biw44Oi44OH44OrDQokJFxoYXR7XHRoZXRhX2l9ID0gXG1hdGhiZnt6fV5UX2kgXG1hdGhiZntcYmV0YX0nICsgZSdfaSAkJA0K44KS5o6o5a6a44GX44Gf5aC05ZCI44CBDQokXG1hdGhiZntcYmV0YX0k44Gu5o6o5a6a5YCk44GoJFxtYXRoYmZ7XGJldGF9JyTjga7mjqjlrprlgKTjga/nlbDjgarjgovjga7jgaDjgILjgZPjga7jgZPjgajjga/jgIENClJN5pysNi4xLjHnr4Djga4kXGhhdHtcbWF0aGJme1xiZXRhfX0k44Gu5byP44KS44G/44Gm44KC44KP44GL44KL44CCDQrjgZPjgZPjgIHjgo/jgZ/jgZfjgZrjg7zjgaPjgajoqqTop6PjgZfjgabjgb7jgZfjgZ8uLi7lj43nnIEuLi4NCg0K5pys6aGM44Gr5oi744Gj44Gm44CBJFx0aGV0YV9pJOOBrkVCTFVQ5o6o5a6a5YCk44KS6KaL5q+U44G544Gm44G/44KL44CCIA0KYGBge3J9DQojIyMgYS5kZlJlc3VsdF9zYWVSRU1MOiByZXN1bHQgZnJvbSBtb2RlbHMgYnkgc2FlUkVNTA0KYS5kZlJlc3VsdF9zYWVSRU1MIDwtIGEuZGZNaWxrICU+JQ0KICBtdXRhdGUoDQogICAgZ0VCTFVQMSA9IGFzLnZlY3RvcihhLm9Nb2RlbF9zYWVSRU1MX25veCRlc3QkZWJsdXApLCANCiAgICBnRUJMVVAyID0gYXMudmVjdG9yKGEub01vZGVsX3NhZVJFTUwkZXN0JGVibHVwKSwgDQogICAgZ01TRTEgICA9IGEub01vZGVsX3NhZVJFTUxfbm94JG1zZSwgDQogICAgZ01TRTIgICA9IGEub01vZGVsX3NhZVJFTUwkbXNlLA0KICAgIGdDVl8wICAgPSBDViwNCiAgICBnQ1ZfMSAgID0gc3FydChnTVNFMSkvZ0VCTFVQMSwNCiAgICBnQ1ZfMiAgID0gc3FydChnTVNFMikvZ0VCTFVQMg0KICApDQoNCmcgPC0gZ2dwbG90KA0KICBkYXRhID0gYS5kZlJlc3VsdF9zYWVSRU1MLA0KICBhZXMoDQogICAgeCAgICA9IFNtYWxsQXJlYSwNCiAgICB5ICAgID0geWksDQogICAgeW1pbiA9IHlpIC0gU0QgLA0KICAgIHltYXggPSB5aSArIFNEIA0KICApDQopDQpnIDwtIGcgKyBnZW9tX3BvaW50cmFuZ2UoYWVzKGNvbG9yID0gTWFqb3JBcmVhKSkNCmcgPC0gZyArIGdlb21fcGF0aChhZXMoeSA9IGdFQkxVUDEsIGdyb3VwID0gMCkpDQpnIDwtIGcgKyBnZW9tX3BhdGgoYWVzKHkgPSBnRUJMVVAyLCBncm91cCA9IDAsIGNvbG9yID0gTWFqb3JBcmVhKSkNCmcgPC0gZyArIGxhYnMoDQogIHggICAgID0gIlNtYWxsIEFyZWEiLCANCiAgeSAgICAgPSBleHByZXNzaW9uKG1lYW4gJSstJSBTRSksIA0KICBjb2xvciA9ICJNYWpvciBBcmVhIg0KKQ0KZyA8LSBnICsgdGhlbWVfYncoKQ0KcHJpbnQoZykNCmBgYA0K5oqY44KM57ea44Gu44GG44Gh44CB6buS44GE44Gu44Gv5YWx5aSJ6YeP44KS5L2/44KP44Gq44GL44Gj44Gf5aC05ZCI44CB6Imy44GM44Gk44GE44Gm44GE44KL44Gu44GvDQrkvb/jgaPjgZ/loLTlkIjjgILliY3ogIXjga/lhajkvZPlubPlnYfjgavjgIHlvozogIXjga9NYWpvciByZWHliKXjga4NCuW5s+Wdh+OBq+WApOOBjOWvhOOBo+OBpuOBhOOCi+OAgiANCg0K5LuK5bqm44GvTVNF44Gu5o6o5a6a5YCk44KS5q+U44G544Gm44G/44KI44GG44CCDQoNCuW5s+Wdh+OBjOWkp+OBjeOBhOOBqOOBneOBrk1TReOCguWkp+OBjeOBj+OBquOCiuOBneOBhuOBquOBruOBp+OAgQ0K5aSJ5YuV5L+C5pWw44Gn5q+U6LyD44GZ44KL44CCDQpgYGB7cn0NCmRmUGxvdCA8LSBhLmRmUmVzdWx0X3NhZVJFTUwgJT4lDQogIGFycmFuZ2UoLW5pKSAlPiUgDQogIG11dGF0ZSgNCiAgICBmU21hbGxBcmVhID0gZmFjdG9yKA0KICAgICAgc2VxX2Fsb25nKFNtYWxsQXJlYSksIA0KICAgICAgbGFiZWxzID0gYXMuY2hhcmFjdGVyKFNtYWxsQXJlYSkNCiAgICApDQogICkgJT4lDQogIGRwbHlyOjpzZWxlY3QoZlNtYWxsQXJlYSwgTWFqb3JBcmVhLCBuaSwgc3RhcnRzX3dpdGgoImdDVl8iKSkgJT4lDQogIGdhdGhlcihzVmFyLCBnVmFsdWUsIHN0YXJ0c193aXRoKCJnQ1ZfIikpICU+JQ0KICBzZXBhcmF0ZShzVmFyLCBjKCJzVmFyMSIsICJzVmFyMiIpKSAlPiUNCiAgbXV0YXRlKA0KICAgIGZNZXRob2QgPSBmYWN0b3IoDQogICAgICBhcy5pbnRlZ2VyKHNWYXIyKSwgDQogICAgICBsZXZlbHMgPSAwOjIsIA0KICAgICAgbGFiZWxzID0gYygiRGlyZWN0IiwgIkVCTFVQKHcvbyBjb3ZhcmlhdGUpIiwgIkVCTFVQKHcvIGNvdmFyaWF0ZSkiKQ0KICAgICkNCiAgKQ0KZyA8LSBnZ3Bsb3QoDQogIGRhdGEgPSBkZlBsb3QsDQogIGFlcygNCiAgICB4ICAgICA9IGZTbWFsbEFyZWEsDQogICAgeSAgICAgPSBnVmFsdWUsDQogICAgZ3JvdXAgPSBmTWV0aG9kLCANCiAgICBjb2xvciA9IGZNZXRob2QNCiAgKQ0KKQ0KZyA8LSBnICsgZ2VvbV9wYXRoKCkNCmcgPC0gZyArIGxhYnMoDQogIHggICAgID0gIlNtYWxsIEFyZWEgKHNvcnRlZCBieSBkZWNyZWFzaW5nIHNhbXBsZSBzaXplKSIsIA0KICB5ICAgICA9ICJDb2VmLlZhcmlhdGlvbiIsIA0KICBjb2xvciA9ICJNZXRob2QiDQopDQpnIDwtIGcgKyB0aGVtZV9idygpDQpwcmludChnKQ0KYGBgDQrku4rluqbjga/mqKrou7jjgpLmqJnmnKzjgrXjgqTjgrrpoIbjgavkuKbjgbnjgabjgYTjgovjgIINCg0K55u05o6l5o6o5a6a6YeP44CB5YWx5aSJ6YeP44Gq44GX44GuRUJMVVAsIOWFseWkiemHj+OCkuOBhOOCjOOBn0VCTFVQ44Go6YCy44KA44Gr44Gk44KM44GmDQrlpInli5Xkv4LmlbDjgYzlsI/jgZXjgY/jgarjgaPjgabjgYTjgovjgIINCuOBvuOBn+OAgeaomeacrOOCteOCpOOCuuOBjOWkp+OBjeOBhOWcsOWfn+OBp+OBr+OAgeWkieWLleS/guaVsOOBjOOBguOBvuOCiua4m+OBo+OBpuOBhOOBquOBhOOAguOBquOCi+OBu+OBqeOBreOAgg0KDQrjgarjgYrjgIHku6XkuIrjga8kXHNpZ21hX3ZeMiTjgpJSRU1M5o6o5a6a44GX44Gf5aC05ZCI44Gn44GC44Gj44Gf44CCDQrlvozov7DjgZnjgovnkIbnlLHjgavjgojjgorjgIHjgZPjgZPjgadNTOaOqOWumuOCguippuOBl+OBpuOBiuOBj+OAgg0KYGBge3J9DQojIyMgYS5vTW9kZWxfc2FlTUw6IG1vZGVsIGJ5IHNhZU1MDQphLm9Nb2RlbF9zYWVNTCA8LSBtc2VGSCgNCiAgZm9ybXVsYSA9IGEuZGZNaWxrJHlpIH4gYS5kZk1pbGskTWFqb3JBcmVhLCANCiAgdmFyZGlyICA9IGEuZGZNaWxrJFNEIF4gMiwgDQogIG1ldGhvZCAgPSAiTUwiDQopDQpwcmludChhLm9Nb2RlbF9zYWVNTCRlc3QkZml0JHJlZnZhcikNCmBgYA0KJFxzaWdtYV92XjIk44GvMC4wMTU1MuOBqOaOqOWumuOBleOCjOOBn+OAguOBoeOCh+OBo+OBtOOCiuS9juOCgeOBp+OBmeOBreOAgg0KDQpgYGB7cn0NCnN1Yl9QbG90VHdvRXN0aW1hdGUuMSgNCiAgYWdFc3QxICAgICA9IGFzLnZlY3RvcihhLm9Nb2RlbF9zYWVSRU1MJGVzdCRlYmx1cCksIA0KICBhZ01TRTEgICAgID0gYS5vTW9kZWxfc2FlUkVNTCRtc2UsIA0KICBhZ0VzdDIgICAgID0gYXMudmVjdG9yKGEub01vZGVsX3NhZU1MJGVzdCRlYmx1cCksIA0KICBhZ01TRTIgICAgID0gYS5vTW9kZWxfc2FlTUwkbXNlLCANCiAgYXNMYWJlbCAgICA9IGEuZGZNaWxrJFNtYWxsQXJlYSwgDQogIHNWYXJMYWJlbDEgPSAic2FlIChSRU1MKSIsIA0KICBzVmFyTGFiZWwyID0gInNhZSAoTUwpIg0KKQ0KYGBgDQokXHRoZXRhX2kk44Gu5o6o5a6a5YCk44KC44CB5o6o5a6a6YeP44GuTVNF44Gu5o6o5a6a5YCk44KC44CB44G744Go44KT44Gp44GL44KP44KJ44Gq44GE44CCDQoNCiMjIyAzLjIuMyBoYnNhZeODkeODg+OCseODvOOCuOOBq+OCiOOCi+aOqOWumg0KDQrlhbHlpInph4/jgpLjgYTjgozjgZ/jg6Ljg4fjg6vjga7mjqjlrprjgpLjgIHku4rluqbjga9oYnNhZeODkeODg+OCseODvOOCuOOBp+ippuOBl+OBpuOBv+OCi+OAgg0KDQpoYnNhZeODkeODg+OCseODvOOCuOOBr+aOqOWumumHj+OBqOOBl+OBpuS7peS4i+OCkuW+oeeUqOaEj+OBl+OBpuOBhOOCi+OAgg0KDQotIHN1cnZyZWcgLi4uIOWvn+OBmeOCi+OBq+ebtOaOpeaOqOWumuOBp+OBguOCjeOBhuOAgg0KLSBzeW50aGV0aWMgLi4uIOODh+OCtuOCpOODs+ODmeODvOOCuemWk+aOpeaOqOWumuOBp+OBguOCjeOBhuOAgg0KLSBoeWJyaWQgLi4uIEVCTFVQ5o6o5a6aLCAkXHNpZ21hX3VeMiTjgpJIQuaOqOWumuOBmeOCi+OAgg0KLSBSRU1MIC4uLiBFQkxVUOaOqOWumiwgJFxzaWdtYV91XjIk44KS44KSUkVNTOaOqOWumuOBmeOCi+OAgg0KLSBCTFVQIC4uLiBFQkxVUOaOqOWumiwgJFxzaWdtYV91XjIk44KS44KS5Yil6YCU5oyH5a6a44GZ44KL44CCDQotIEhCIC4uLiDpmo7lsaTjg5njgqTjgrrmjqjlrprjgIINCg0K44G+44Ga44GvRUJMVVDmjqjlrprjgpLoqabjgZfjgabjgb/jgojjgYbjgIJzYWXjg5Hjg4PjgrHjg7zjgrjjga7lh7rlipvjgajmj4PjgYjjgovjgZ/jgoHjgIFSRU1M44KS6YG444G244CCDQpgYGB7cn0NCiMjIyBhLm9Nb2RlbF9oYnNhZVJFTUw6IG1vZGVsIGJ5IGhic2FlUkVNTA0KYS5vTW9kZWxfaGJzYWVSRU1MIDwtIGZTQUUuQXJlYSgNCiAgYS5kZk1pbGskeWksIA0KICBhLmRmTWlsayRTRF4yLCANCiAgbW9kZWwubWF0cml4KHlpIH4gTWFqb3JBcmVhLCBkYXRhPWEuZGZNaWxrKSwgDQogIG1ldGhvZCA9ICJSRU1MIg0KKQ0Kc3ViX1Bsb3RUd29Fc3RpbWF0ZS4xKA0KICBhZ0VzdDEgICAgID0gYXMudmVjdG9yKGEub01vZGVsX3NhZVJFTUwkZXN0JGVibHVwKSwgDQogIGFnTVNFMSAgICAgPSBhLm9Nb2RlbF9zYWVSRU1MJG1zZSwgDQogIGFnRXN0MiAgICAgPSBFU1QoYS5vTW9kZWxfaGJzYWVSRU1MKSwgDQogIGFnTVNFMiAgICAgPSBTRShhLm9Nb2RlbF9oYnNhZVJFTUwpXjIsIA0KICBhc0xhYmVsICAgID0gYS5kZk1pbGskU21hbGxBcmVhLCANCiAgc1ZhckxhYmVsMSA9ICJzYWUgKFJFTUwpIiwgDQogIHNWYXJMYWJlbDIgPSAiaGJzYWUgKFJFTUwpIg0KKQ0KDQpgYGANCiRcc2lnbWFfdl4yJOOBrywgDQpoYnNhZeOBrmZTQUUuQXJlYSgp44Gn44GvdmFyaWFuY2UgcmF0aW/jgajlkbzjgbDjgozjgovjgonjgZfjgYTjgIINCuOBquOCk+OBoOOBi+WkieOBquWRvOOBs+aWueOBoOOBjOOAgQ0K44GN44Gj44GoZlNBRS5BcmVhKCnjga7lhoXlgbTjgafjg6bjg4vjg4Pjg4jjg6zjg5njg6vjg6Ljg4fjg6vjga7plqLmlbDjgpLjgrPjg7zjg6vjgZfjgabjgYTjgosNCuOBi+OCieOAgeODpuODi+ODg+ODiOODrOODmeODq+ODouODh+ODq+OBrueUqOiqnuOBjOOBneOBruOBvuOBvuaui+OBo+OBpuOBhOOCi+OBruOBoOOCjeOBhuOAgg0K5o6o5a6a5YCk44GvMC4wMTg1NeOAgXNhZeODkeODg+OCseODvOOCuOOBruaOqOWumuWApOOBqOOBu+OBvOWQjOOBmOOBoOOAgg0KDQokXHRoZXRhX2kk44Gu5o6o5a6a5YCk44KC44G744G85ZCM44GY44CC44GX44GL44GX44CB5o6o5a6a6YeP44GuTVNF44Gu5o6o5a6a5YCk44GvDQpoYnNhZeOBruOBu+OBhuOBjOWwkeOBl+S9juOCgeOBq+OBquOBo+OBpuOBhOOCi+OAguOBquOBnOOBi+OCj+OBi+OCieOBquOBhOOAgg0KDQrjgZPjgpPjganjga/pmo7lsaTjg5njgqTjgrrmjqjlrprjgIINCmhic2Fl44OR44OD44Kx44O844K444Gr44GK44GR44KLSELmjqjlrprjga/jgIFNQ01D44Gn44Gv44Gq44GP5pWw5YCk56mN5YiG44KS5L2/44Gj44Gm44GE44KL44CCDQoNCmBgYHtyfQ0KIyMjIGEub01vZGVsX2hic2FlSEI6IG1vZGVsIGJ5IGhic2FlSEINCnNldC5zZWVkKDEyMzQ1KQ0KYS5vTW9kZWxfaGJzYWVIQiA8LSBmU0FFLkFyZWEoDQogIGEuZGZNaWxrJHlpLCANCiAgYS5kZk1pbGskU0ReMiwgDQogIG1vZGVsLm1hdHJpeCh5aSB+IE1ham9yQXJlYSwgZGF0YT1hLmRmTWlsaykNCikNCnN1Yl9QbG90VHdvRXN0aW1hdGUuMSgNCiAgYWdFc3QxICAgICA9IGFzLnZlY3RvcihhLm9Nb2RlbF9zYWVSRU1MJGVzdCRlYmx1cCksIA0KICBhZ01TRTEgICAgID0gYS5vTW9kZWxfc2FlUkVNTCRtc2UsIA0KICBhZ0VzdDIgICAgID0gRVNUKGEub01vZGVsX2hic2FlSEIpLCANCiAgYWdNU0UyICAgICA9IFNFKGEub01vZGVsX2hic2FlSEIpXjIsIA0KICBhc0xhYmVsICAgID0gYS5kZk1pbGskU21hbGxBcmVhLCANCiAgc1ZhckxhYmVsMSA9ICJzYWUgKFJFTUwpIiwgDQogIHNWYXJMYWJlbDIgPSAiaGJzYWUgKEhCKSINCikNCmBgYA0KJFxzaWdtYV92XjIk44Gu5o6o5a6a5YCkKOS6i+W+jOW5s+Wdhynjga8wLjAyMjY244CC5bCR44GX6auY44GP44Gq44Gj44Gf44CCDQokXHRoZXRhX2kk44Gu5o6o5a6a5YCk44Gv44CBc2Fl44OR44OD44Kx44O844K444Go44G744G85ZCM44GY44Gg44GM44CBTVNF44Gu5o6o5a6a5YCk44Gv44Gh44KH44Gj44Go44Ga44KM44Gm44GE44KL44CCDQoNCiMjIyAzLjIuNCBCYXllc1NBReODkeODg+OCseODvOOCuOOBq+OCiOOCi+aOqOWumg0KDQrjgZPjgpPjganjga9CYXllc1NBReODkeODg+OCseODvOOCuOOBp+ippuOBl+OBpuOBv+OCiOOBhuOAgg0KTUNNQ+OBq+OCiOOCi0hC5o6o5a6a44Gn44GC44KL44CCDQoNCuS6i+WJjeWIhuW4g+OBruaMh+WumuOBjOODh+ODleOCqeODq+ODiOOBp+OBqeOBhuOBquOBo+OBpuOBhOOCi+OBruOBi+OAgQ0K44Oe44OL44Ol44Ki44Or44KS6Kqt44KT44Gn44KC44KI44GP44KP44GL44KJ44Gq44GL44Gj44Gf44Gu44Gn44CBDQrjgr3jg7zjgrnjgrPjg7zjg4njgpLoqr/jgbnjgabnqoHjgY3mraLjgoHjgZ/jgILku6XkuIvjga7jgrPjg7zjg4njgadwcmlvcj3jgavkuI7jgYjjgabjgYTjgosNCuODquOCueODiCDjgZPjgozjgYzjg4fjg5Xjgqnjg6vjg4jjgafjgYLjgoso5b6T44Gj44GmcHJpb3I944Kq44OX44K344On44Oz44KS5raI44GX44Gm44KCDQrntZDmnpzjga/lkIzjgZgp44CCJFxiZXRhJOOBr+eEoeaDheWgseS6i+WJjeWIhuW4gywgJFxzaWdtYV92XjIk44GvDQokKDAsIDEwMCkk44Gu5LiA5qeY5YiG5biD44CCDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKQ0KYS5vTW9kZWxfQmF5ZXNTQUUgPC0gQmF5ZXNTQUU6OkJheWVzU0FFKA0KICB5aSB+IE1ham9yQXJlYXx2YXIsIA0KICBkYXRhPWEuZGZNaWxrLCANCiAgbWNtYz0yMDAwMCwNCiAgcHJpb3I9bGlzdCgNCiAgICBiZXRhLnR5cGUgID0gIm5vbl9pbiIsDQogICAgYmV0YS5wcmlvciA9IDAsDQogICAgc2lndi50eXBlICA9ICJ1bmlmIiwNCiAgICBzaWd2LnByaW9yID0gbGlzdChlcHMyPTFlLTAyKQ0KICApDQopDQpwcmludChzdW1tYXJ5KGEub01vZGVsX0JheWVzU0FFKSkNCmBgYA0KJFxzaWdtYV92XjIk44Gu5o6o5a6a5YCkKOS6i+W+jOW5s+Wdhynjga8wLjAyMjI0MeOAgmhic2Fl44GuSELmjqjlrprjgavov5HjgYTjgIINCg0KYGBge3J9DQpzdWJfUGxvdFR3b0VzdGltYXRlLjEoDQogIGFnRXN0MSAgICAgPSBhcy52ZWN0b3IoYS5vTW9kZWxfc2FlUkVNTCRlc3QkZWJsdXApLCANCiAgYWdNU0UxICAgICA9IGEub01vZGVsX3NhZVJFTUwkbXNlLCANCiAgYWdFc3QyICAgICA9IGEub01vZGVsX0JheWVzU0FFJEhCLCANCiAgYWdNU0UyICAgICA9IHN1bW1hcnkoTUNNQyhhLm9Nb2RlbF9CYXllc1NBRSkpJHN0YXRpc3RpY3NbMTo0MywyXV4yLCANCiAgYXNMYWJlbCAgICA9IGEuZGZNaWxrJFNtYWxsQXJlYSwgDQogIHNWYXJMYWJlbDEgPSAic2FlIChSRU1MKSIsIA0KICBzVmFyTGFiZWwyID0gIkJheWVzU0FFIg0KKQ0KYGBgDQokXHRoZXRhX2kk44Gu5o6o5a6a5YCk44CB44Gq44KJ44Gz44GrTVNF44Gu5o6o5a6a5YCk44KC44CBaGJzYWXjga5IQuaOqOWumuOBq+i/keOBhOOCiOOBhuOBoOOAgg0KDQojIyMgMy4yLjUgbmxtZeODkeODg+OCseODvOOCuOOBq+OCiOOCi+aOqOWumg0KDQrmt7flkIjjg6Ljg4fjg6vjga7msY7nlKjjg5Hjg4PjgrHjg7zjgrjjgafjgYLjgotubG1l44OR44OD44Kx44O844K444Gn6Kmm44GX44Gm44G/44KI44GG44CCDQrmraPopo/mt7flkIjjg6Ljg4fjg6vjga7plqLmlbBsbWUoKeOCkuS9v+OBhuOAgiRcdGhldGFfaSTjga7mjqjlrprph4/jga9FQkxVUOOAgg0KJFxzaWdtYV4yX3Yk44Gu5o6o5a6a6YeP44Gv44OH44OV44Kp44Or44OI44Gn44GvUkVNTOOBq+OBquOCi+OAgg0KDQpgYGB7cn0NCmEub01vZGVsX2xtZVJFTUwgPC0gbG1lKA0KICBmaXhlZCAgID0geWkgfiBNYWpvckFyZWEsDQogIHJhbmRvbSAgPSB+IDEgfCBTbWFsbEFyZWEsDQogIGNvbnRyb2wgPSBsbWVDb250cm9sKHNpZ21hID0gMSwgYXBWYXIgPSBUKSwNCiAgd2VpZ2h0cyA9IHZhckZpeGVkKH52YXIpLA0KICBkYXRhICAgID0gYS5kZk1pbGsNCikNCnByaW50KGEub01vZGVsX2xtZVJFTUwpDQpgYGANCmxtZSgp6Zai5pWw44Gud2VpZ2h0cz12YXJGaXhlZCh+IHZhcinjgafjgIHjgIzjgrDjg6vjg7zjg5flhoXjga7liIbmlaPjga/lpInmlbB2YXLjgafjgYLjgovjgI0NCuOBqOaMh+WumuOBl+OBpuOBhOOCi+OBk+OBqOOBq+OBquOCi+OBruOBoOOBneOBhuOBoCjjgZPjgZPjgafjgrDjg6vjg7zjg5fjgajjga/lsI/lnLDln5/jga7jgZPjgajjgafjgYLjgo3jgYYp44CCDQrjgb7jgZ/jgIFjb250cm9sPeOCquODl+OCt+ODp+ODs+OBruOBhuOBoeOAgXNpZ21hPTHjgajjga/jgIzmrovlt67liIbmlaPjgpIx44Gr5Zu65a6a44GZ44KL44CN44Go44GE44GG5oSP5ZGz44CBDQphcFZhciA9IFTjgajjga/jgIzliIbmlaPlhbHliIbmlaPooYzliJfjgpLmsYLjgoHjgovjgI3jgajjgYTjgYbmhI/lkbPjgonjgZfjgYTjgIINCuOBk+OBhuOBmeOCi+OBqOaui+W3ruWIhuaVo+OBryB2YXIqMSDjgavjgarjgovjgIHjgajjgYTjgYbjgZPjgajjgarjga7jgYvjgarjgIINCg0K44G444O844GT44GG44KE44Gj44Gm5pu444GP44Gu44GL44CB5YuJ5by344Gr44Gq44KL44Gq44GC44CB44Go5oCd44Gj44Gf44Gu44Gg44GM44CBDQrjgojjgY/jgojjgY/jgb/jgovjgajjgIHntZDmnpzjgYzjgaHjgofjgaPjgbTjgopzYWXjg5Hjg4PjgrHjg7zjgrjjgajnlbDjgarjgovjgIINCuOBk+OBk+OBp+OBryRcc2lnbWFfdiTjga7mjqjlrprlgKTjgYwgMC4xMzMyOTE4IOOBqOOBquOBo+OBpuOBhOOCi+OAguS6jOS5l+OBmeOCi+OBqDAuMDE3NzY2N+OAgg0Kc2Fl44OR44OD44Kx44O844K444Gn44GvMC4wMTg1NeOBp+OBguOBo+OBn+OAguOBguOCjO+8n+OBoeOCh+OBo+OBqOS9juOBhOOBnu+8nw0KDQrlrp/jga/jgZPjga7oqbHjgIFubG1l44OR44OD44Kx44O844K444GuPGEgaHJlZj0iaHR0cHM6Ly9idWdzLnItcHJvamVjdC5vcmcvYnVnemlsbGEvc2hvd19idWcuY2dpP2lkPTE2OTc1Ij7jg5DjgrA8L2E+44Go44GX44Gm5aCx5ZGK44GV44KM44Gm44GE44KL44CCDQpzYWXjg5Hjg4PjgrHjg7zjgrjjgajjgbTjgaPjgZ/jgorlkIjjgo/jgarjgYTjga7jga/jgYrjgYvjgZfjgYTjga7jgaDjgZ3jgYbjgafjgIHjgZPjgozjga/jganjgYbjgoTjgokNCm5sbWXlgbTjga7jg5DjgrDjgonjgZfjgYTjgILjgYbjgo/jg7zjgILjgb7jgZXjgYvjgZ3jgpPjgarjgZPjgajjgYzjg7zjgIINCg0K44Gq44GK44CBTUzmjqjlrprjgpLmjIflrprjgZfjgZ/loLTlkIjjga7lh7rlipvjga/mraPjgZfjgYTjgZ3jgYbjgaDjgIINCmBgYHtyfQ0KYS5vTW9kZWxfbG1lTUwgPC0gbG1lKA0KICBmaXhlZCAgID0geWkgfiBNYWpvckFyZWEsDQogIHJhbmRvbSAgPSB+IDEgfCBTbWFsbEFyZWEsDQogIGNvbnRyb2wgPSBsbWVDb250cm9sKHNpZ21hID0gMSwgYXBWYXIgPSBUKSwNCiAgd2VpZ2h0cyA9IHZhckZpeGVkKH52YXIpLA0KICBtZXRob2QgID0gIk1MIiwNCiAgZGF0YSAgICA9IGEuZGZNaWxrDQopDQpwcmludChhLm9Nb2RlbF9sbWVNTCkNCmBgYA0KDQowLjEyNDU2OTNeMiA9IDAuMDE1NTE3NTEsIHNhZeODkeODg+OCseODvOOCuOOBp+OBrk1M5o6o5a6a44Go44G744G85LiA6Ie044GZ44KL44CCDQoNCmBgYHtyfQ0Kc3ViX1Bsb3RUd29Fc3RpbWF0ZS4xKA0KICBhZ0VzdDEgICAgID0gYXMudmVjdG9yKGEub01vZGVsX3NhZVJFTUwkZXN0JGVibHVwKSwgDQogIGFnTVNFMSAgICAgPSBOVUxMLCANCiAgYWdFc3QyICAgICA9IHByZWRpY3QoYS5vTW9kZWxfbG1lTUwpLCANCiAgYWdNU0UyICAgICA9IE5VTEwsIA0KICBhc0xhYmVsICAgID0gYS5kZk1pbGskU21hbGxBcmVhLCANCiAgc1ZhckxhYmVsMSA9ICJzYWUgKFJFTUwpIiwgDQogIHNWYXJMYWJlbDIgPSAibmxtZSAoTUwpIg0KKQ0KYGBgDQrmjqjlrprlgKTjga9zYWXjg5Hjg4PjgrHjg7zjgrjjgajjgZ/jgYTjgZfjgablpInjgo/jgonjgarjgYTjgILjgarjgYrjgIHmjqjlrprph4/jga5NU0Xjga7mjqjlrprlgKTjga7jgbvjgYbjga/jgIENCm5sbWXjg5Hjg4PjgrHjg7zjgrjjgaDjgZHjgafjga/lh7rlipvjgafjgY3jgZrjgIHjgarjgavjgYvlt6XlpKvjgZfjgarjgYTjgajjgYTjgZHjgarjgYTmqKHmp5jjgafjgYLjgovjgIINCg0KIyMjIDMuMi42IHJzdGFu44OR44OD44Kx44O844K444Gr44KI44KL5o6o5a6aDQoNCuacgOW+jOOBq+OAgeODmeOCpOOCuOOCouODs+ODu+ODouODh+ODquODs+OCsOOBruOBn+OCgeOBruaxjueUqOODkeODg+OCseODvOOCuHJzdGFu44Gn6Kmm44GX44Gm44G/44KI44GG44CCDQoNCnN0YW7jgrPjg7zjg4njga/jgZPjgaHjgonjgIINCuOCj+OBn+OBj+OBl+OAgeaZruauteOBr+OBu+OBvOS9v+OCj+OBquOBhOOBruOBp+OAgeato+ebtOOBquOBqOOBk+OCjeWFqOeEtuiHquS/oeOBjOOBquOBhOOCk+OBp+OBmeOBjC4uLiANCmBgYHtyIGVuZ2luZT0nY2F0JywgcmVzdWx0cz0iaGlkZSJ9DQovLyBGYXktSGVycmlvdCBtb2RlbA0KLy8gY2YuIGh0dHBzOi8vcmRyci5pby9naXRodWIvc3Nvcm80MTEvYmF5ZXNhZS9zcmMvUi9Nb2RlbHNfZmFzdC5SDQoNCmRhdGEgew0KICAgIGludDxsb3dlcj0wPiAgICAgICAgTTsgICAgICANCiAgICBpbnQ8bG93ZXI9MD4gICAgICAgIFA7ICAgICAgDQogICAgdmVjdG9yW01dICAgICAgICAgICBZOyAgIA0KICAgIHZlY3Rvcjxsb3dlcj0wPltNXSAgU0Q7ICANCiAgICBtYXRyaXhbTSxQXSAgICAgICAgIFg7ICAgDQp9DQoNCnBhcmFtZXRlcnMgew0KICAgIHJlYWw8bG93ZXI9MD4gICAgIHNpZ21hOyAgICANCiAgICB2ZWN0b3JbUF0gICAgICAgICBiZXRhOyAgICAgICAgDQogICAgdmVjdG9yW01dICAgICAgICAgdGhldGE7ICAgICAgIA0KfQ0KDQp0cmFuc2Zvcm1lZCBwYXJhbWV0ZXJzIHsNCiAgICB2ZWN0b3JbTV0gbXU7DQogICAgbXUgPSBYKmJldGE7DQp9DQoNCm1vZGVsIHsNCiAgICB0aGV0YSB+IG5vcm1hbChtdSwgc2lnbWEpOw0KICAgIFkgICAgIH4gbm9ybWFsKHRoZXRhLCBTRCk7DQp9DQpgYGANCg0K44Gn44Gv5a6f6KGM44GX44G+44GZLi4uDQoNCmBgYHtyfQ0KDQojIGEub1N0YW5Nb2RlbCA8LSBzdGFuX21vZGVsKGZpbGU9Ii4vRkgxX3ZlY3Rvcml6ZWQuc3RhbiIpDQojIHNhdmUoYS5vU3Rhbk1vZGVsLCBmaWxlPSIuL2Eub1N0YW5Nb2RlbC5SRGF0YSIpDQojIA0KIyBsb2FkKGZpbGUgPSAiLi9hLm9TdGFuTW9kZWwuUkRhdGEiKQ0KIyANCiMgbW5Nb2RlbE1hdHJpeCA8LSBtb2RlbC5tYXRyaXgofiBNYWpvckFyZWEsIGRhdGE9YS5kZk1pbGspDQojIGxEYXRhIDwtIGxpc3QoDQojICAgTSAgPSBucm93KGEuZGZNaWxrKSwNCiMgICBQICA9IG5jb2wobW5Nb2RlbE1hdHJpeCksDQojICAgWSAgPSBhLmRmTWlsayR5aSwNCiMgICBTRCA9IGEuZGZNaWxrJFNELA0KIyAgIFggID0gbW5Nb2RlbE1hdHJpeA0KIyApDQojIGEub1N0YW5GaXQgICA8LSBzYW1wbGluZygNCiMgICBhLm9TdGFuTW9kZWwsDQojICAgZGF0YSAgID0gbERhdGEsDQojICAgc2VlZCAgID0gMTIzNCwNCiMgICBjb250cm9sID0gbGlzdChhZGFwdF9kZWx0YSA9IDAuOTUpDQojICkNCiMgc2F2ZShhLm9TdGFuRml0LCBmaWxlPSIuL2Eub1N0YW5GaXQuUkRhdGEiKQ0KDQpsb2FkKGZpbGUgPSAiLi9hLm9TdGFuRml0LlJEYXRhIikNCnN0YW5fdHJhY2UoYS5vU3RhbkZpdCwgYygic2lnbWEiLCAidGhldGFbMjhdIiksIGluY193YXJtdXAgPSBUKQ0Kc3Rhbl9yaGF0KChhLm9TdGFuRml0KSkNCmBgYA0KDQokXHNpZ21hX3Yk44GoJFx0aGV0YV97Mjh9JOOBruODiOODrOODvOOCueODl+ODreODg+ODiCjlnLDln58yOOOBr+aOqOWumuWApOOBrlNF44GM44GE44Gh44Gw44KT5aSn44GN44GE5Zyw5Z+fKeOAgQ0K44Gq44KJ44Gz44GrJFxoYXR7Un0k44Gu44OS44K544OI44Kw44Op44Og44KS56S644GZ44CCDQrkvZnoo5Xjgaflj47mnZ/jgZfjgabjgYTjgovmqKHmp5jjgIINCg0K5Zyw5Z+f5Yq55p6c44Gu5o6o5a6a5YCk44Gq44KJ44Gz44GrTVNF44Gu5o6o5a6a44Go44CBc2Fl44OR44OD44Kx44O844K444Go5q+U6LyD44GX44Gm44G/44KL44GoLi4uDQoNCmBgYHtyfQ0KbFJlc3VsdCA8LSByc3Rhbjo6ZXh0cmFjdChhLm9TdGFuRml0KQ0KYWdFc3QgPC0gY29sTWVhbnMobFJlc3VsdCR0aGV0YSkNCmFnTVNFIDwtIGFwcGx5KGxSZXN1bHQkdGhldGEsIDIsIHZhcikNCg0Kc3ViX1Bsb3RUd29Fc3RpbWF0ZS4xKA0KICBhZ0VzdDEgICAgID0gYXMudmVjdG9yKGEub01vZGVsX3NhZVJFTUwkZXN0JGVibHVwKSwgDQogIGFnTVNFMSAgICAgPSBhLm9Nb2RlbF9zYWVSRU1MJG1zZSwgDQogIGFnRXN0MiAgICAgPSBhZ0VzdCwgDQogIGFnTVNFMiAgICAgPSBhZ01TRSwgDQogIGFzTGFiZWwgICAgPSBhLmRmTWlsayRTbWFsbEFyZWEsIA0KICBzVmFyTGFiZWwxID0gInNhZSAoUkVNTCkiLCANCiAgc1ZhckxhYmVsMiA9ICJyc3RhbiINCikNCg0KYGBgDQoNCuaOqOWumuWApOOBruOBu+OBhuOBr+OBu+OBvOWQjOOBmOOAgk1TReOBr+WwkeOBl+OBmuOCjOOBpuOBhOOBpuOAgWhic2Fl44OR44OD44Kx44O844K4KEhC5o6o5a6aKeOChOOAgQ0KQmF5ZXNTQUXjg5Hjg4PjgrHjg7zjgrjjgajkvLzjgabjgYTjgovjgIINCg0KYGBge3IsIHJlc3VsdHM9ImhpZGUifQ0Kcm0obGlzdD1ncmVwKCJeYVxcLiIsIGxzKCksIHZhbHVlPVQpKQ0KYGBgDQoNCiMjIDMuMyDjgrfjg5/jg6Xjg6zjg7zjgrfjg6fjg7MNCjwhLS0gY2h1bmvjgpLotoXjgYjjgovjgqrjg5bjgrjjgqfjgq/jg4jjga9iLuOBi+OCieWni+OCgeOCiyAtLT4NCg0K44GT44GG44GX44Gm44G/44Gm44G/44KL44Go44CB44GE44KN44GE44KN55aR5ZWP44GM5rmn44GE44Gm44GP44KL44CC44KP44Gf44GP44GX44Go6Ie044GX44G+44GX44Gm44Gv44CBDQrnibnjgavmrKHjga4z54K544Gr6Zai5b+D44GM44GC44KL44CCDQoNCi0gRUJMVVDjgahIQuOBp+OBr+WcsOWfn+eJueaAp+OBrk1TReOBruaOqOWumuWApOOBjOeVsOOBquOCi+OAgg0KICDlkIzjgZhFQkxVUOOBp+OCguOAgXNhZeODkeODg+OCseODvOOCuOOBqGhic2Fl44OR44OD44Kx44O844K444Gn44GvDQogIOOChOOBr+OCiueVsOOBquOCi+OAguiJr+OBhOOBruOBr+OBqeOCjOOBi+OAgg0KLSDjgZPjgozjgaPjgabjgrnjgrHjg7zjg6vjgZnjgovjga7jgYvjgILjgZ/jgajjgYjjgbDlsI/lnLDln5/jgYwxMOS4h+WAi+OBguOBo+OBpuOCguOBoeOCg+OCk+OBqOaOqOWumuOBp+OBjeOCi+OBruOBi+OAgg0KLSDnhKHpp4TjgarlhbHlpInph4/jgpLmipXlhaXjgZfjgZ/jgonjgarjgavjgYzotbfjgY3jgovjga7jgYvjgILjgZ3jgozjga/mjqjlrprph4/jgavjgojjgaPjgabnlbDjgarjgovjgYvjgIINCg0K44Gd44GT44Gn44K344Of44Ol44Os44O844K344On44Oz44GX44Gm44G/44KL44GT44Go44Gr44GX44G+44GX44Gf44CCDQoNCiMjIyAzLjMuMSDllY/poYwNCg0K44GE44G+44CB5Zyw5Z+fJGkkKCQ9MSxcbGRvdHMsbSQp44Gu44Gy44Go44KK44Gy44Go44KK44Gu5L2P5rCRJGokKCQ9MSxcbGRvdHMsTl9pJCnjgYzjgIENCumHj+eahOOBquWPjeW/nOWkieaVsCR5X3tpan0k44KS5oyB44Gj44Gm44GE44KL44CC44GI44O844Gj44Go44CB5bm456aP5bqm44Gj44Gm44GT44Go44Gr44GX44G+44GX44KH44GG44GL44CCDQoNCuWcsOWfn+OBruavjembhuWbo+OCteOCpOOCuiROX2kk44Gv44GE44Ga44KM44KC5Y2B5YiG44Gr5aSn44GN44GE44CCDQrlkITlnLDln5/jga7lubjnpo/luqbjga7mr43lubPlnYckXGJhcntZfV9pID0gXGZyYWN7MX17Tl9pfSBcc3VtX2ogeV97aWp9JOOBq+OBpOOBhOOBpuaOqOa4rOOBl+OBn+OBhOOAgg0K44Gd44GT44Gn44CB5ZCE5Zyw5Z+fJGkk44GL44KJ44K144Kk44K6JG5faSTjga7mqJnmnKzjgpLljZjntJTnhKHkvZzngrrmir3lh7rjgZfjgIENCuaomeacrOW5s+WdhyRcaGF0e1xiYXJ7WX19X2kgPSBcZnJhY3sxfXtuX2l9IFxzdW1faiB5X3tpan0kLA0K44Gq44KJ44Gz44Gr44Gd44Gu5YiG5pWj44Gu5o6o5a6a5YCkDQokXGhhdHtWYXJ9KFxoYXR7XGJhcntZfX0pX2kgPSBcZnJhY3sxfXtuX2kobl9pLTEpfSBcc3VtX2ogKHlfe2lqfSAtIFxoYXR7XGJhcntZfX1faSkkDQrjgpLmsYLjgoHjgZ/jgIINCg0K44Go44GT44KN44GM44CB5Zyw5Z+f44GU44Go44Gu5qiZ5pys44K144Kk44K6JG5faSTjga/lv4XjgZrjgZfjgoLljYHliIbjgafjgarjgYTjgIINCuaomeacrOW5s+WdhyRcaGF0e1xiYXJ7WX19X2kk44KSJFxiYXJ7WX1faSTjga7mjqjlrprph4/jgajjgZnjgovjga7jga/jgIHjgYTjgZXjgZXjgYvlv4PoqLHjgarjgYTjgIINCuOBleOCieOBq+OAgeWQhOWcsOWfn+OBryRwKzEk5YCL44Gu44OW44Ot44OD44Kv44Gr5YiG6aGe44GV44KM44Gm44GK44KK44CBDQrjg5bjg63jg4Pjgq/jgavjgojjgaPjgablubjnpo/luqblubPlnYckXGJhcntZfV9pJOOBrumrmOOBleOBjOeVsOOBquOCi+OAgQ0K44Go56eB44Gv5L+h44GY44Gm44GE44KL44CCIA0KDQrjgZ3jgZPjgafnp4Hjga/jgZPjgYbogIPjgYjjgovjgILlubjnpo/luqbjga7mqJnmnKzlubPlnYckXGhhdHtcYmFye1l9fV9pJOOBoOOBkeOBp+OBquOBj+OAgQ0K44Gd44Gu5Zyw5Z+f44GM44Gp44Gu44OW44Ot44OD44Kv44Gr5bGe44GZ44KL44GL44Go44GE44GG5oOF5aCx44KC44Gk44GL44Gj44Gm44CBDQrlkITlnLDln5/jga7lubjnpo/luqbjga7mr43lubPlnYckXGJhcntZfV9pJOOCkg0K5o6o5ris44GX44KI44GG77yBDQoNCuOBqOOBhOOBhuOCj+OBkeOBp+OAgUZheS1FcnJpb3Tjg6Ljg4fjg6vjga7nmbvloLTjgafjgYLjgovjgIINCg0K5Lul5LiL44CB6KiY5Y+344GM54Wp6ZuR44Gr44Gq44KL44Gu44Gn44CBDQpSTeacrOOBq+OBguOCj+OBm+OBpiRcdGhldGFfaSA9IFxiYXJ7WX1faSQsICRcaGF0e1x0aGV0YX1faSA9IFxoYXR7XGJhcntZfX1faSTjgajmm7jjgY/jgIINCuOBvuOBn+OAgSRcaGF0e1xwc2l9X2kgPSBcaGF0e1Zhcn0oXGhhdHtcYmFye1l9fV9pKSTjgajmm7jjgY/jgILjgZXjgonjgavjgIENCuOBguOCi+WcsOWfn+OBjOOBqeOBk+OBq+WIhumhnuOBleOCjOOCi+OBi+OCkuOAgemVt+OBlSRwJOOBruS6jOWApOODmeOCr+ODiOODqyRcbWF0aGJme3p9X2kk44Gn6KGo44GZ44CCDQoNCuOBiuOBleOCieOBhOOBmeOCi+OBqOOAgUZheS1IZXJyaW9044Oi44OH44Or44Gv5Lul5LiL44Gu6YCa44KK44CCDQokJCANCiAgXGhhdHtcdGhldGF9X2kgPSBcbWF0aGJme3p9XlRfaSBcbWF0aGJme1xiZXRhfSArIHZfaSArIGVfaSwgXCBcDQogIHZfaSBcc2ltICgwLCBcc2lnbWFeMl92KSwgXCBcIA0KICBlX2kgXHNpbSAoMCwgXHBzaV9pKQ0KJCQNCg0K5Lul5LiL44Gn44GvJHZfaSTjgpLlnLDln5/lirnmnpzjgIEkZV9pJOOCkuaomeacrOaKveWHuuiqpOW3ruOBqOWRvOOBvOOBhuOAgg0KDQojIyMgMy4zLjIg44OH44O844K/55Sf5oiQ44Oi44OH44OrDQoNCuOBleOBpuOAgeOBk+OCjOOBi+OCieWIhuaekOeUqOOBruODh+ODvOOCv+OCkueUn+aIkOOBl+OBvuOBmeOAgg0KDQrjg4fjg7zjgr/nlJ/miJDjg6Ljg4fjg6vjga/mrKHjga7jgajjgYrjgorjgIIkaT0xLFxsZG90cyxtJOOBq+OBpOOBhOOBpuOAgQ0KJCQgDQogIHlfe2lqfSA9IDUwICsgXG1hdGhiZnt6fV5UX2kgXG1hdGhiZnswfSArIHZfaSArIFxlcHNpbG9uX3tpan0sIFwgXCANCiAgdl9pIFxtYXRob3B7XHNpbX1ee2lpZH0gTigwLCBcc2lnbWFeMl92KSwgXCBcDQogIFxlcHNpbG9uX3tpan0gXG1hdGhvcHtcc2ltfV57aWlkfSBOKDAsMTAwKQ0KJCQNCg0K44Gk44G+44KK44CB56eB44Gv55+l44KJ44Gq44GE44Gu44Gg44GM44CB5a6f44GvDQoNCi0gKOW5uOemj+W6pik9NTArKOWcsOWfn+WKueaenCkrKOWAi+S6uuW3rikg44Gn44GC44KL44CCDQotIOWcsOWfn+mWk+OBp+W5uOemj+W6puOBq+OBsOOCieOBpOOBjeOBjOOBguOCiuOAgeOBneOBruOBsOOCieOBpOOBjeOBr+ato+imj+WIhuW4g+OBq+W+k+OBo+OBpuOBhOOCi+OAgg0KLSDlubjnpo/luqbjga/lnLDln5/jgYzlsZ7jgZnjgovjg5bjg63jg4Pjgq/jgajjga/plqLkv4LjgYzjgarjgYQoJFxtYXRoYmZ7XGJldGF9ID0gXG1hdGhiZnswfSQp44CCDQotIOWcsOWfn+WGheOBruWAi+S6uuW3ruOCguato+imj+WIhuW4g+OBq+W+k+OBo+OBpuOBhOOCi+OAguOBqeOBruOBj+OCieOBhOOBsOOCieOBpOOBhOOBpuOBhOOCi+OBi+OBqOOBhOOBhuOBqOOAgeOCiOOBj+WtpuagoeOBruaIkOe4vuOBqOOBi+OCkuWBj+W3ruWApOOBp+ihqOOBmeOBkeOCjOOBqSjliIbmlaPjga8xMDAp44CB5bm456aP5bqm44KC44G+44Gf44Gd44Gu44GP44KJ44GE44Gw44KJ44Gk44GE44Gm44GE44KLKOWIhuaVo+OBrzEwMCnjgIINCg0K5q+N6ZuG5Zuj44K144Kk44K644Gv5aSn44GN44GP44CBJFxlcHNpbG9uX3tpan0k44Gu5q+N6ZuG5Zuj5bmz5Z2H44GvDQow44Go44G/44Gq44Gb44KL44Gu44Gn44CB57WQ5bGA44CB55+l44KK44Gf44GE54m55oCnJFx0aGV0YV9pJOOBr+OBk+OBk+OBp+OBryR2X2kk44Gr562J44GX44GE44CCDQoNCuWcsOWfn+OBruaomeacrOOCteOCpOOCuiRuX2kk44Gv44CB5Zyw5Z+fMeOBi+OCieWcsOWfnzEw44G+44Gn6aCG44GrJDEwLCAyMCwgLi4uLCAxMDAk44Go44GX44CBDQrlnLDln58xMeS7pemZjeOCguOBk+OCjOOCkue5sOOCiui/lOOBmeOAgg0KDQrlhbHlpInph48kXG1hdGhiZnt6fV9pJCjplbfjgZUkcCQp44Gv44CB5Zyw5Z+f44Gu44OW44Ot44OD44KvKCRwKzEk5rC05rqWKeOCkuihqOOBmeOCguOBruOBqOOBmeOCi+OAgg0K44OW44Ot44OD44Kv55Wq5Y+344Gv44CB5Zyw5Z+fMeOBi+OCieWcsOWfnyRwKzEk44G+44Gn44Gv6aCG44GrICQxLC4uLixwKzEk44Go44GX44CBDQrmrovjgorjga7lnLDln5/jgavjgaTjgYTjgabjga/nrYnnorrnjofjgafjg6njg7Pjg4Djg6DjgavmsbrjgoHjgovjgIINCg0KIyMjIDMuMy4zIOOCt+ODn+ODpeODrOODvOOCt+ODp+ODs+eUqOOBrumWouaVsA0KDQouLi7jgajjgYTjgYbjg4fjg7zjgr/jgpLnlJ/miJDjgZfliIbmnpDjgZnjgovjgIHkuIDpgKPjga7plqLmlbDjgpLkvZzjgorjgb7jgZfjgZ/jgIINCg0KYGBge3J9DQoNCiMjIyBmb3IgcnN0YW4gLi4uDQojIGIub1N0YW5Nb2RlbCA8LSBzdGFuX21vZGVsKGZpbGU9Ii4vRkgxX3ZlY3Rvcml6ZWQuc3RhbiIpDQojIHNhdmUoYi5vU3Rhbk1vZGVsLCBmaWxlPSIuL2Iub1N0YW5Nb2RlbC5SRGF0YSIpDQpsb2FkKGZpbGUgPSAiLi9iLm9TdGFuTW9kZWwuUkRhdGEiKQ0KDQpiLnN1Yl9HZW5lcmF0ZURhdGFzZXQxLjEgPC0gZnVuY3Rpb24oDQogIG5OdW1BcmVhLCBuTnVtR3JvdXAsIGdWYXJWLCBnVmFyRT0xMDAsIGFuUG9zc2libGVOPXNlcSgxMCwgMTAwLCBieSA9IDEwKQ0KKXsNCiAgIyMgcHVycG9zZTogZ2VuZXJhdGUgYSBkYXRhc2V0IGZvciBGSCBtb2RlbA0KICAjIyBhcmc6DQogICMjICAgbk51bUFyZWE6ICAgICAgICAgbnVtYmVyIG9mIGFyZWFzDQogICMjICAgbk51bUdyb3VwOiAgICAgICAgbnVtYmVyIG9mIGxldmVscyBvZiBhIGNhdGVnb3JpY2FsIGNvdmFyaWF0ZQ0KICAjIyAgIGdWYXJWOiAgICAgICAgICAgIHZhcmlhbmNlIG9mIGFyZWEgZWZmZWN0cw0KICAjIyAgIGFuUG9zc2libGVOOiAgICAgIHZlY3RvciBvZiBwb3NzaWJsZSBzYW1wbGUgc2l6ZQ0KICAjIyByZXR1cm46DQogICMjICAgYSBkYXRhIGZyYW1lLCBhcmVhIGxldmVsIGRhdGENCiAgIyMgICAkbkFyZWE6ICAgICAgIEFyZWEgSUQNCiAgIyMgICAkblNpemU6ICAgICAgIHNhbXBsZSBzaXplDQogICMjICAgJGZHcm91cDogICAgICBjYXRlZ29yaWNhbCBjb3ZhcmlhdGUgd2l0aCAobk51bUdyb3VwKSBsZXZlbHMNCiAgIyMgICAkZ0VzdF9EaXJlY3Q6IHNhbXBsZSBtZWFucyBvZiBhIHJlc3BvbnNlIHZhcmlhYmxlDQogICMjICAgJGdNU0VfRGlyZWN0OiBzYW1wbGUgZXN0LiBvZiB2YXJpYW5jZSBvZiBzYW1wbGUgbWVhbnMNCiAgIyMgICAkZ1Y6ICAgICAgICAgIGFyZWEgZWZmZWN0DQogIA0KICBvdXQgPC0gZGF0YS5mcmFtZSgNCiAgICBuQXJlYSAgICAgID0gMTpuTnVtQXJlYSwNCiAgICBuU2l6ZSAgICAgID0gcmVwKGFuUG9zc2libGVOLCBuTnVtQXJlYSAlLyUgbGVuZ3RoKGFuUG9zc2libGVOKSArIDEpWzE6bk51bUFyZWFdLA0KICAgIGZHcm91cCAgICAgPSBmYWN0b3IoDQogICAgICBjKDE6bk51bUdyb3VwLCBzYW1wbGUoMTpuTnVtR3JvdXAsIG5OdW1BcmVhIC0gbk51bUdyb3VwLCByZXBsYWNlID0gVCkpLCANCiAgICAgIGxldmVscyA9IDE6bk51bUdyb3VwDQogICAgKSwNCiAgICBnViAgICAgICAgID0gNTAgKyBybm9ybShuID0gbk51bUFyZWEsIG1lYW4gPSAwLCBzZCA9IHNxcnQoZ1ZhclYpKQ0KICApDQogIGxFcnJvciA8LSBsYXBwbHkoDQogICAgb3V0JG5TaXplLA0KICAgIGZ1bmN0aW9uKG5TaXplKXsNCiAgICAgIHJub3JtKG4gPSBuU2l6ZSwgbWVhbiA9IDAsIHNkID0gc3FydChnVmFyRSkpDQogICAgfQ0KICApDQogIG91dCRnRXN0X0RpcmVjdCAgPC0gb3V0JGdWICsgc2FwcGx5KGxFcnJvciwgbWVhbikNCiAgb3V0JGdNU0VfRGlyZWN0ICA8LSBzYXBwbHkobEVycm9yLCBmdW5jdGlvbih4KXsgdmFyKHgpIC8gbGVuZ3RoKHgpIH0pDQogIG91dCRuVG90YWxTaXplICAgPC0gc3VtKG91dCRuU2l6ZSkNCiAgDQogIHJldHVybihvdXQpDQp9DQpiLnN1Yl9HZW5lcmF0ZU11bHRpRGF0YXNldDEuMSA8LSBmdW5jdGlvbihuTnVtRGF0YXNldD0xLCAuLi4pew0KICAjIyBwdXJwb3NlOiBnZW5lcmF0ZSBtdWx0aXBsZSBkYXRhc2V0cyBmb3IgRkggbW9kZWwNCiAgIyMgYXJnOg0KICAjIyAgIG5OdW1EYXRhc2V0OiAgICAgIG51bWJlciBvZiBkYXRhIHNldHMNCiAgIyMgICAuLi46ICAgICAgICAgICAgICBwYXNzIHRvIHN1Yl9HZW5lcmF0ZURhdGFzZXQxLjEoKQ0KICAjIyByZXR1cm46DQogICMjICAgYSBkYXRhIGZyYW1lLCBhcmVhIGxldmVsIGRhdGENCiAgIyMgICAkbkRhdGFzZXQ6ICBEYXRhc2V0IElEDQogICMjICAgJC4uLiAgICAgICAgcmV0dXJuIGZyb20gc3ViX0dlbmVyYXRlRGF0YXNldDEuMSgpDQoNCiAgb3V0IDwtIGRhdGEuZnJhbWUobkRhdGFzZXQgPSAxOm5OdW1EYXRhc2V0KSAlPiUNCiAgICBncm91cF9ieShuRGF0YXNldCkgJT4lDQogICAgZHBseXI6OmRvKGIuc3ViX0dlbmVyYXRlRGF0YXNldDEuMSguLi4pKSAlPiUNCiAgICB1bmdyb3VwKCkNCiAgcmV0dXJuKG91dCkNCn0NCg0KYi5zdWJfRXN0aW1hdGVEYXRhc2V0QnlNZXRob2QxLjEgPC0gZnVuY3Rpb24oDQogIGRmRGF0YSwgc01ldGhvZCwgblRpbWVPdXQgPSAxODAwLCBiVmVyYm9zZT1GQUxTRQ0KKXsNCiAgIyMgcHVycG9zZTogZXN0aW1hdGUgRkggbW9kZWwgZm9yIGEgZGF0YXNldCBieSBhIG1ldGhvZA0KICAjIyBhcmc6DQogICMjICAgZGZEYXRhOiAgIGEgZGF0YSBzZXQNCiAgIyMgICBzTWV0aG9kOiAgeyJzYWVSRU1MIiwgInNhZVJFTUxOT01TRSIsICJoYnNhZVJFTUwiLCAiaGJzYWVIQiIsIA0KICAjIyAgICAgICAgICAgICAgImJheWVzc2FlIiwgIm5sbWUiLCAicnN0YW4ifQ0KICAjIyAgIG5UaW1lT3V0OiB0aW1lIGxpbWl0DQogICMjICAgYlZlcmJvc2U6IHZlcmJvc2UgZmxhZyAobG9naWNhbCkNCiAgIyMgcmV0dXJuOg0KICAjIyAgIGEgbGlzdA0KICAjIyBub3RlczoNCiAgIyMgICAtIG5UaW1lT3V0IGlzIGVmZmVjdGl2ZSBvbmx5IGZvciBoYnNhZVJFTUwgYW5kIGhic2FlSEINCiAgIyMgICAtIHJzdGFuIHJlcXVpcmVzIGIub1N0YW5Nb2RlbCBpbiB0aGUgZW52aXJvbm1lbnQNCg0KICAjIyB0cmFwOiBjaGVjayBzTWV0aG9kDQogIHN0b3BpZm5vdCgNCiAgICBzTWV0aG9kICVpbiUgYygNCiAgICAgICJzYWVSRU1MIiwgInNhZVJFTUxOT01TRSIsICJoYnNhZVJFTUwiLCAiaGJzYWVIQiIsIA0KICAgICAgImJheWVzc2FlIiwgIm5sbWUiLCAicnN0YW4iDQogICAgKQ0KICApDQoNCiAgaWYgKGJWZXJib3NlKSBjYXQoIltzdWJfRXN0aW1hdGVEYXRhc2V0MS4xXSIsIHNNZXRob2QsICIuLi4gXG4iKQ0KDQogIHQgPC0gcHJvYy50aW1lKCkNCg0KICBpZiAoc01ldGhvZCA9PSAic2FlUkVNTCIpIHsNCiAgICBvTW9kZWwgPC0gdHJ5KA0KICAgICAgbXNlRkgoDQogICAgICAgIGZvcm11bGEgPSBkZkRhdGEkZ0VzdF9EaXJlY3QgfiBkZkRhdGEkZkdyb3VwLA0KICAgICAgICB2YXJkaXIgID0gZGZEYXRhJGdNU0VfRGlyZWN0LA0KICAgICAgICBtZXRob2QgID0gIlJFTUwiDQogICAgICApDQogICAgKQ0KICAgIGlmICghaW5oZXJpdHMob01vZGVsLCAidHJ5LWVycm9yIikpIHsNCiAgICAgIGFnRXN0IDwtIGFzLnZlY3RvcihvTW9kZWwkZXN0JGVibHVwKQ0KICAgICAgYWdNU0UgPC0gb01vZGVsJG1zZQ0KICAgIH0NCiAgfQ0KDQogIGlmIChzTWV0aG9kID09ICJzYWVSRU1MTk9NU0UiKSB7DQogICAgb01vZGVsIDwtIHRyeSgNCiAgICAgIGVibHVwRkgoDQogICAgICAgIGZvcm11bGEgPSBkZkRhdGEkZ0VzdF9EaXJlY3QgfiBkZkRhdGEkZkdyb3VwLA0KICAgICAgICB2YXJkaXIgID0gZGZEYXRhJGdNU0VfRGlyZWN0LA0KICAgICAgICBtZXRob2QgID0gIlJFTUwiDQogICAgICApDQogICAgKQ0KICAgIGlmICghaW5oZXJpdHMob01vZGVsLCAidHJ5LWVycm9yIikpIHsNCiAgICAgIGFnRXN0IDwtIGFzLnZlY3RvcihvTW9kZWwkZWJsdXApDQogICAgICBhZ01TRSA8LSByZXAoTkEsIG5yb3coZGZEYXRhKSkNCiAgICB9DQogIH0NCg0KICBpZiAoc01ldGhvZCA9PSAiaGJzYWVSRU1MIikgew0KICAgIG9Nb2RlbCA8LSB3aXRoVGltZW91dCgNCiAgICAgIHRyeSgNCiAgICAgICAgZlNBRS5BcmVhKA0KICAgICAgICAgIGRmRGF0YSRnRXN0X0RpcmVjdCwNCiAgICAgICAgICBkZkRhdGEkZ01TRV9EaXJlY3QsDQogICAgICAgICAgbW9kZWwubWF0cml4KGdFc3RfRGlyZWN0IH4gZkdyb3VwLCBkYXRhID0gZGZEYXRhKSwNCiAgICAgICAgICBtZXRob2QgPSAiUkVNTCIsDQogICAgICAgICAgc2lsZW50ID0gIFRSVUUNCiAgICAgICAgKQ0KICAgICAgKSwNCiAgICAgIHRpbWVvdXQgPSBuVGltZU91dA0KICAgICkNCiAgICBpZiAoIWluaGVyaXRzKG9Nb2RlbCwgInRyeS1lcnJvciIpKSB7DQogICAgICBhZ0VzdCA8LSBFU1Qob01vZGVsKQ0KICAgICAgYWdNU0UgPC0gU0Uob01vZGVsKV4yDQogICAgfQ0KICB9DQoNCiAgaWYgKHNNZXRob2QgPT0gImhic2FlSEIiKSB7DQogICAgb01vZGVsIDwtIHdpdGhUaW1lb3V0KA0KICAgICAgdHJ5KA0KICAgICAgICBmU0FFLkFyZWEoDQogICAgICAgICAgZGZEYXRhJGdFc3RfRGlyZWN0LA0KICAgICAgICAgIGRmRGF0YSRnTVNFX0RpcmVjdCwNCiAgICAgICAgICBtb2RlbC5tYXRyaXgoZ0VzdF9EaXJlY3QgfiBmR3JvdXAsIGRhdGEgPSBkZkRhdGEpLA0KICAgICAgICAgIG1ldGhvZCA9ICJIQiIsDQogICAgICAgICAgc2lsZW50ID0gIFRSVUUNCiAgICAgICAgKQ0KICAgICAgKSwNCiAgICAgIHRpbWVvdXQgPSBuVGltZU91dA0KICAgICkNCiAgICBpZiAoIWluaGVyaXRzKG9Nb2RlbCwgInRyeS1lcnJvciIpKSB7DQogICAgICBhZ0VzdCA8LSBFU1Qob01vZGVsKQ0KICAgICAgYWdNU0UgPC0gU0Uob01vZGVsKV4yDQogICAgfQ0KICB9DQoNCiAgaWYgKHNNZXRob2QgPT0gImJheWVzc2FlIikgew0KICAgIG9Nb2RlbCA8LSB0cnkoDQogICAgICBCYXllc1NBRSgNCiAgICAgICAgZ0VzdF9EaXJlY3QgfiBmR3JvdXAgfCBnTVNFX0RpcmVjdCwNCiAgICAgICAgZGF0YSA9IGRmRGF0YSwNCiAgICAgICAgbWNtYyA9IDUwMDANCiAgICAgICkNCiAgICApDQogICAgaWYgKCFpbmhlcml0cyhvTW9kZWwsICJ0cnktZXJyb3IiKSkgew0KICAgICAgYWdFc3QgPC0gb01vZGVsJEhCDQogICAgICBhZ01TRSA8LSBzdW1tYXJ5KE1DTUMob01vZGVsKSkkc3RhdGlzdGljc1tzZXFfYWxvbmcoZGZEYXRhJG5BcmVhKSwyXV4yDQogICAgfQ0KICB9DQoNCiAgaWYgKHNNZXRob2QgPT0gIm5sbWUiKSB7DQogICAgb01vZGVsIDwtIHRyeSgNCiAgICAgIGxtZSgNCiAgICAgICAgZml4ZWQgICA9IGdFc3RfRGlyZWN0IH4gZkdyb3VwLA0KICAgICAgICByYW5kb20gID0gfiAxIHwgbkFyZWEsDQogICAgICAgIGNvbnRyb2wgPSBsbWVDb250cm9sKHNpZ21hID0gMSwgYXBWYXIgPSBUKSwNCiAgICAgICAgd2VpZ2h0cyA9IHZhckZpeGVkKH5nTVNFX0RpcmVjdCksDQogICAgICAgIG1ldGhvZCAgPSAiTUwiLA0KICAgICAgICBkYXRhICAgID0gZGZEYXRhDQogICAgICApDQogICAgKQ0KICAgIGlmICghaW5oZXJpdHMob01vZGVsLCAidHJ5LWVycm9yIikpIHsNCiAgICAgIGFnRXN0IDwtIGZpdHRlZChvTW9kZWwpDQogICAgICBhZ01TRSA8LSByZXAoTkEsIG5yb3coZGZEYXRhKSkNCiAgICB9DQogIH0NCg0KICBpZiAoc01ldGhvZCA9PSAicnN0YW4iKSB7DQogICAgIyMgdHJhcDogYi5vU3Rhbk1vZGVsIGlzIGZvdW5kIGluIHRoZSBlbnZpcm9tZW50DQogICAgc3RvcGlmbm90KGV4aXN0cygiYi5vU3Rhbk1vZGVsIikpDQogICAgbW5Nb2RlbE1hdHJpeCA8LSBtb2RlbC5tYXRyaXgofiBmR3JvdXAsIGRhdGEgPSBkZkRhdGEpDQogICAgbERhdGEgPC0gbGlzdCgNCiAgICAgIE0gID0gbnJvdyhkZkRhdGEpLA0KICAgICAgUCAgPSBuY29sKG1uTW9kZWxNYXRyaXgpLA0KICAgICAgWSAgPSBkZkRhdGEkZ0VzdF9EaXJlY3QsDQogICAgICBTRCA9IHNxcnQoZGZEYXRhJGdNU0VfRGlyZWN0KSwNCiAgICAgIFggID0gbW5Nb2RlbE1hdHJpeA0KICAgICkNCiAgICBvTW9kZWwgPC0gdHJ5KA0KICAgICAgc2FtcGxpbmcoDQogICAgICAgIGIub1N0YW5Nb2RlbCwNCiAgICAgICAgZGF0YSAgID0gbERhdGEsDQogICAgICAgIHNlZWQgICA9IDEyMzQsDQogICAgICAgIGl0ZXIgICA9IDQwMCwNCiAgICAgICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk1KSwgDQogICAgICAgIG9wZW5fcHJvZ3Jlc3MgPSBGQUxTRSwgDQogICAgICAgIHNob3dfbWVzc2FnZXMgPSBGQUxTRQ0KICAgICAgKQ0KICAgICkNCiAgICBpZiAoICFpbmhlcml0cyhvTW9kZWwsICJ0cnktZXJyb3IiKSApIHsNCiAgICAgICBpZiAoIGFueShzdW1tYXJ5KG9Nb2RlbCkkc3VtbWFyeVssIlJoYXQiXSA+IDEuMSkgKSB7DQogICAgICAgICBvTW9kZWwgPC0gdHJ5KHN0b3AoIm5vdCBjb252ZXJnZWQhIikpDQogICAgICAgfQ0KICAgIH0NCiAgICBpZiAoICFpbmhlcml0cyhvTW9kZWwsICJ0cnktZXJyb3IiKSApIHsNCiAgICAgIGxSZXN1bHQgPC0gcnN0YW46OmV4dHJhY3Qob01vZGVsKQ0KICAgICAgYWdFc3QgPC0gY29sTWVhbnMobFJlc3VsdCR0aGV0YSkNCiAgICAgIGFnTVNFIDwtIGFwcGx5KGxSZXN1bHQkdGhldGEsIDIsIHZhcikNCiAgICB9DQogIH0NCg0KICAjIyBjb21tb24gcHJvY2VzcyAuLi4NCiAgaWYgKCFpbmhlcml0cyhvTW9kZWwsICJ0cnktZXJyb3IiKSkgew0KICAgIG91dCA8LSBsaXN0KA0KICAgICAgc01ldGhvZCA9IHNNZXRob2QsDQogICAgICBiU3RhdHVzID0gVFJVRSwNCiAgICAgIGFnRXN0ICAgPSBhZ0VzdCwNCiAgICAgIGFnTVNFICAgPSBhZ01TRSwNCiAgICAgIGdUaW1lICAgPSAocHJvYy50aW1lKCkgLSB0KVszXQ0KICAgICkNCiAgICBpZiAoYlZlcmJvc2UpIGNhdCgiW3N1Yl9Fc3RpbWF0ZURhdGFzZXQxLjFdIFN1Y2Nlc3MuIiwgb3V0JGdUaW1lLCAic2VjLlxuIikNCiAgfSBlbHNlIHsNCiAgICBvdXQgPC0gbGlzdCgNCiAgICAgIHNNZXRob2QgPSBzTWV0aG9kLA0KICAgICAgYlN0YXR1cyA9IEZBTFNFLA0KICAgICAgYWdFc3QgICA9IHJlcChOQSwgbnJvdyhkZkRhdGEpKSwNCiAgICAgIGFnTVNFICAgPSByZXAoTkEsIG5yb3coZGZEYXRhKSksDQogICAgICBnVGltZSAgID0gKHByb2MudGltZSgpIC0gdClbM10NCiAgICApDQogICAgaWYgKGJWZXJib3NlKSBjYXQoIltzdWJfRXN0aW1hdGVEYXRhc2V0MS4xXSBGYWlsLiIsIG91dCRnVGltZSwgInNlYy5cbiIpDQogIH0NCiAgcmV0dXJuKG91dCkNCn0NCmIuc3ViX0VzdGltYXRlRGF0YXNldDEuMSA8LSBmdW5jdGlvbigNCiAgZGZEYXRhLA0KICBhc01ldGhvZD1jKCJzYWVSRU1MIiwgImhic2FlUkVNTCIsICJoYnNhZUhCIiwgImJheWVzc2FlIiwgIm5sbWUiLCAicnN0YW4iKSwgDQogIC4uLg0KKXsNCiAgIyMgcHVycG9zZTogZXN0aW1hdGUgRkggbW9kZWwgZm9yIGEgZGF0YXNldCBieSBtdWx0aXBsZSBtZXRob2RzDQogICMjIGFyZzoNCiAgIyMgICBkZkRhdGE6ICAgIGEgZGF0YXNldA0KICAjIyAgIGFzTWV0aG9kDQogICMjICAgLi4uDQogICMjIHJldHVybjoNCiAgIyMgICBhIGRhdGEgZnJhbWUNCg0KICBsT3V0IDwtIGxhcHBseSgNCiAgICBhc01ldGhvZCwNCiAgICBmdW5jdGlvbihzTWV0aG9kKXsNCiAgICAgIGxSZXN1bHQgPC0gYi5zdWJfRXN0aW1hdGVEYXRhc2V0QnlNZXRob2QxLjEoZGZEYXRhLCBzTWV0aG9kID0gc01ldGhvZCwgLi4uKQ0KICAgICAgb3V0IDwtIGRhdGEuZnJhbWUoDQogICAgICAgIG5BcmVhICAgPSBkZkRhdGEkbkFyZWEsDQogICAgICAgIHNNZXRob2QgPSByZXAobFJlc3VsdCRzTWV0aG9kLCBucm93KGRmRGF0YSkpLA0KICAgICAgICBiU3RhdHVzID0gcmVwKGxSZXN1bHQkYlN0YXR1cywgbnJvdyhkZkRhdGEpKSwNCiAgICAgICAgZ0VzdCAgICA9IGxSZXN1bHQkYWdFc3QsDQogICAgICAgIGdNU0UgICAgPSBsUmVzdWx0JGFnTVNFLA0KICAgICAgICBnVGltZSAgID0gcmVwKGxSZXN1bHQkZ1RpbWUsIG5yb3coZGZEYXRhKSksDQogICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KICAgICAgKQ0KICAgICAgcmV0dXJuKG91dCkNCiAgICB9DQogICkNCiAgb3V0IDwtIGJpbmRfcm93cyhsT3V0KSAlPiUNCiAgICBnYXRoZXIoc1ZhciwgZ1ZhbHVlLCBjKGJTdGF0dXMsIGdFc3QsIGdNU0UsIGdUaW1lKSkgJT4lDQogICAgbXV0YXRlKHNWYXIgPSBwYXN0ZTAoc1ZhciwgIl8iLCBzTWV0aG9kKSkgJT4lDQogICAgZHBseXI6OnNlbGVjdChuQXJlYSwgc1ZhciwgZ1ZhbHVlKSAlPiUNCiAgICBzcHJlYWQoc1ZhciwgZ1ZhbHVlKQ0KDQogIG91dCA8LSBmdWxsX2pvaW4oZGZEYXRhLCBvdXQsIGJ5ID0gIm5BcmVhIikNCg0KICByZXR1cm4ob3V0KQ0KfQ0KYi5zdWJfRXN0aW1hdGVNdWx0aURhdGFzZXQxLjEgPC0gZnVuY3Rpb24oZGZEYXRhLCAuLi4pew0KICAjIyBwdXJwb3NlOiBlc3RpbWF0ZSBGSCBtb2RlbHMgZm9yIG11bHRpcGxlIGRhdGFzZXRzIGJ5IG11bHRpcGxlIG1ldGhvZHMNCiAgIyMgYXJnOg0KICAjIyAgIGRmRGF0YTogICAgbXVsdGlwbGUgZGF0YXNldHMNCiAgIyMgcmV0dXJuOg0KICAjIyAgIGEgZGF0YSBmcmFtZSBvZiBtdWx0aXBsZSByZXN1bHRzDQoNCiAgb3V0IDwtIGRmRGF0YSAlPiUNCiAgICBncm91cF9ieShuRGF0YXNldCkgJT4lDQogICAgZHBseXI6OmRvKGIuc3ViX0VzdGltYXRlRGF0YXNldDEuMSguLCAuLi4pKSAlPiUNCiAgICB1bmdyb3VwKCkNCg0KICByZXR1cm4ob3V0KQ0KfQ0KYi5zdWJfRXN0aW1hdG9yQXNGYWN0b3IuMSA8LSBmdW5jdGlvbihhc0VzdGltYXRvcil7DQogICMjIHB1cnBvc2U6IGNvbnZlcnQgZXN0aW1hdG9yIG5hbWVzIGludG8gZmFjdG9yDQogICMjIGFyZ3M6DQogICMjICAgYXNFc3RpbWF0b3I6IGEgY2hhcmFjdGVyIHZlY3RvciBvZiBlc3RpbWF0b3IgbmFtZXMNCiAgIyMgcmV0dXJuOiANCiAgIyMgICBhIGZhY3RvciB2ZWN0b3INCiAgDQogIGZhY3RvcigNCiAgICBhc0VzdGltYXRvciwgDQogICAgbGV2ZWxzID0gYygNCiAgICAgICJUcnVlIiwgIkRpcmVjdCIsICJzYWVSRU1MIiwgInNhZVJFTUxOT01TRSIsIA0KICAgICAgImhic2FlUkVNTCIsICJoYnNhZUhCIiwgImJheWVzc2FlIiwgIm5sbWUiLCAicnN0YW4iDQogICAgKSwgDQogICAgbGFiZWxzID0gYygNCiAgICAgICJUcnVlIiwgIkRpcmVjdCIsICJzYWUoUkVNTCkiLCAic2FlKFJFTUwsbm9NU0UpIiwgDQogICAgICAiaGJzYWUoUkVNTCkiLCAiaGJzYWUoSEIpIiwgIkJheWVzU0FFIiwgIm5sbWUiLCAicnN0YW4iDQogICAgKSANCiAgKQ0KfQ0KYi5zdWJfRXN0aW1hdG9yUGFsZXR0ZS4xIDwtIGZ1bmN0aW9uKGFmRXN0aW1hdG9yKXsNCiAgIyMgcHVycG9zZTogZ2V0IGNvbnNpc250ZW50IGNvbG9yIHBhbGxldHRlIGZvciBlc3RpbWF0b3JzDQogICMjIGFyZ3M6DQogICMjICAgYWZFc3RpbWF0b3I6IGEgZmFjdG9yIHZlY3RvciBvZiBlc3RpbWF0b3IgDQogICMjIHJldHVybjoNCiAgIyMgICBhIHZlY3RvciBvZiBjb2xvciBwYWxldHRlDQogIA0KICBnZ19jb2xvcl9odWUoOSlbc29ydCh1bmlxdWUoYXMuaW50ZWdlcihhZkVzdGltYXRvcikpKV0NCiAgDQp9DQpgYGANCg0KIyMjIDMuMy4zIOODh+ODvOOCv+WIhuaekOS+iw0KDQrjgZ/jgoHjgZfjgavjgIHkuIroqJjjga7jg4fjg7zjgr/nlJ/miJDplqLmlbDjgajjg4fjg7zjgr/liIbmnpDplqLmlbDjgpLkvb/jgaPjgabjgb/jgojjgYbjgIINCg0K44G+44Ga44OH44O844K/55Sf5oiQ44CCMTDlnLDln5/jgIE044OW44Ot44OD44Kv44CB5Zyw5Z+f5Yq55p6c44Gu5YiG5pWj44GvNTDjgajjgZnjgovjgIINCuWcsOWfn+WKueaenOOBruWIhuaVo+OBr+OAgeWcsOWfn+WGheOBruWAi+S6uuW3ruOBruWNiuWIhuOBruWkp+OBjeOBleOBoOOAgg0K57WQ5qeL5aSn44GN44Gq5Zyw5Z+f5beu44GM44GC44KL44KT44Gn44GZ44Gt44CCDQoNCmBgYHtyfQ0KIyMgYi5kZkRlbW9EYXRhOiBkYXRhIGZvciBkZW1vDQpzZXQuc2VlZCgxMDApDQpiLmRmRGVtb0RhdGEgPC0gYi5zdWJfR2VuZXJhdGVEYXRhc2V0MS4xKG5OdW1BcmVhPTEwTCwgbk51bUdyb3VwPTRMLCBnVmFyVj01MCkNCnByaW50KGIuZGZEZW1vRGF0YSkNCmBgYA0KDQrjgafjga/jgIHjgZPjga7jg4fjg7zjgr/jgavjgaTjgYTjgabmjqjlrprjgZfjgIHmrKHjga445YCL44KS5q+U6LyD44GZ44KL44CCDQoNCi0gKipUcnVlKio6IOecn+WApCRcdGhldGFfaSTjgIINCi0gKipEaXJlY3QqKjog5qiZ5pys5bmz5Z2HJFxoYXR7XHRoZXRhfV9pJOOAgg0KLSAqKnNhZShSRU1MKSoqOiBzYWXjg5Hjg4PjgrHjg7zjgrgsIEVCTFVQ5o6o5a6a6YePLCAkXHNpZ21hX3ZeMiTjgpJSRU1M5o6o5a6a44CCDQotICoqaGJzYWUoUkVNTCkqKjogaGJzYWXjg5Hjg4PjgrHjg7zjgrgsIEVCTFVQ5o6o5a6a6YePLCAkXHNpZ21hX3ZeMiTjgpJSRU1M5o6o5a6a44CCDQotICoqaGJzYWUoSEIpKio6ICAgaGJzYWXjg5Hjg4PjgrHjg7zjgrgsIEhC5o6o5a6a6YePLCDmlbDlgKTnqY3liIbjgavjgojjgovjgIINCi0gKipCYXllc1NBRSoqOiAgQmF5ZXNTQUXjg5Hjg4PjgrHjg7zjgrgsIEhC5o6o5a6a6YePLCBNQ01D44Gr44KI44KL44CCDQogICAgICAgICAgICAgICAgIOOBquOBiuOAgW1jbWPjga7jg4njg63jg7zmlbDjga/jgIHjgaHjgofjgaPjgajlpJrjgoHjgas1MDAw44Gr44GX44Gm44GK44GE44Gf44CCDQotICoqbmxtZSoqOiAgICAgIG5sbWXjg5Hjg4PjgrHjg7zjgrjjga5sbWXplqLmlbAsIEVCTFVQ5o6o5a6a6YePLCAkXHNpZ21hX3ZeMiTjgpJNTOaOqOWumuOAgg0KLSAqKnJzdGFuKio6ICAgICByc3RhbuODkeODg+OCseODvOOCuCwgSELmjqjlrprph48sIE1DTUPjgavjgojjgovjgILjg4njg63jg7zmlbA0MDAsIOWFqOODkeODqeODoeODvOOCv+OBrg0KICAgICAgICAgICAgICAgICAkXGhhdHtSfSTjgYwxLjHku6XkuIvjgafjgYLjgovjgZPjgajjgpLnorroqo3jgZnjgovjgIINCg0KYGBge3J9DQpkZlJlc3VsdCA8LSBiLnN1Yl9Fc3RpbWF0ZURhdGFzZXQxLjEoYi5kZkRlbW9EYXRhKSAlPiUNCiAgZHBseXI6OnNlbGVjdChuQXJlYSwgblNpemUsIGdWLCBzdGFydHNfd2l0aCgiZ0VzdF8iKSkNCg0KZGZQbG90IDwtIGRmUmVzdWx0ICU+JQ0KICBkcGx5cjo6c2VsZWN0KG5BcmVhLCBnViwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICByZW5hbWUoZ0VzdF9UcnVlID0gZ1YpICU+JQ0KICBnYXRoZXIoc1ZhciwgZ1ZhbHVlICwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBzZXBhcmF0ZShzVmFyLCBjKCJzVmFyMSIsICJzVmFyMiIpKSAlPiUNCiAgbXV0YXRlKGZFc3RpbWF0b3IgPSBiLnN1Yl9Fc3RpbWF0b3JBc0ZhY3Rvci4xKHNWYXIyKSkNCg0KZyA8LSBnZ3Bsb3QoDQogIGRhdGE9ZGZQbG90LA0KICBhZXMoeD1hcy5mYWN0b3IobkFyZWEpLCB5PWdWYWx1ZSwgZ3JvdXA9ZkVzdGltYXRvciwgY29sb3I9ZkVzdGltYXRvcikNCikNCmcgPC0gZyArIGdlb21fcGF0aChzaXplPTEpDQpnIDwtIGcgKyBsYWJzKA0KICB4ICAgICA9ICJhcmVhIiwNCiAgeSAgICAgPSBleHByZXNzaW9uKHBhc3RlKHRoZXRhLCAiIG9yICIsIGhhdCh0aGV0YSkpKSwNCiAgY29sb3IgPSAiRXN0aW1hdG9yIg0KKQ0KZyA8LSBnICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGIuc3ViX0VzdGltYXRvclBhbGV0dGUuMShkZlBsb3QkZkVzdGltYXRvcikpDQpnIDwtIGcgKyB0aGVtZV9idygpDQpwcmludChnKQ0KDQpgYGANCue4pui7uOOBr+ecn+WApOOBquOBhOOBl+aOqOWumuWApOOBp+OBguOCi+OAgg0KDQrjgZ/jgajjgYjjgbDlnLDln58x44Gu5q2j6Kej44GvNTYuM+eCueOAguaomeacrOW5s+Wdh+OBrzU5LjLngrksIOato+ino+OCiOOCiuOCguOBi+OBquOCiumrmOOCgeOBq+OBquOBo+OBpuOBl+OBvuOBo+OBnw0KKOWcsOWfnzHjga7mqJnmnKzjgrXjgqTjgrrjga8xMOOBl+OBi+OBquOBhCnjgIINCuOBl+OBi+OCi+OBq+OAgXNhZeODkeODg+OCseODvOOCuOOBruaOqOWumuWApOOBrzU3LjXngrnjgILmqJnmnKzlubPlnYfjgojjgorjgoLmraPop6Pjgavov5HjgY/jgarjgaPjgabjgYTjgovjgIINCg0K44KC44Gj44Go44KC44CB44GT44Gu57WQ5p6c44Gv44Gf44G+44Gf44G+44GL44KC44GX44KM44Gq44GE44CCDQrlkIzjgZjjgZPjgajjgpLkvZXluqbjgoLnubDjgorov5TjgZfjgabjgb/jgarjgYTjgajjgIHjgarjgpPjgajjgoLjgYTjgYjjgarjgYTjgIINCg0KIyMjIDMuMy40IOaomeacrOOCteOCpOOCuiB2cy4g5o6o5a6a44Gu57K+5bqmDQoNCuOBiuOBvuOBn+OBm+OBl+OBvuOBl+OBn+OAguOBquOCk+OBqeOCgue5sOOCiui/lOOBl+OBpuOBv+OBvuOBmeOAgg0KDQrlhYjnqIvjgajlkIzjgZjjgY/jgIExMOWcsOWfn+OAgTTjg5bjg63jg4Pjgq/jgIHlnLDln5/lirnmnpzjga7liIbmlaPjga81MOOBqOOBmeOCi+OAgg0KNTAw5Zue57mw44KK6L+U44GX44Gm44G/44Gf44CCNDDliIbjgbvjganjgYvjgYvjgorjgb7jgZfjgZ/jgIINCmBgYHtyIHJlc3VsdHM9ImhpZGUifQ0KDQojIHNldC5zZWVkKDEyMzQ1NikNCiMgZGZEYXRhIDwtIGIuc3ViX0dlbmVyYXRlTXVsdGlEYXRhc2V0MS4xKA0KIyAgIG5OdW1EYXRhc2V0ID0gNTAwLCBuTnVtQXJlYSA9IDEwTCwgbk51bUdyb3VwID0gNEwsIGdWYXJWID0gNTANCiMgKQ0KIyBiLmRmU2ltdWxhdGlvbjEgPC0gYi5zdWJfRXN0aW1hdGVNdWx0aURhdGFzZXQxLjEoZGZEYXRhKQ0KIyBzYXZlKGIuZGZTaW11bGF0aW9uMSwgZmlsZT0iLi9iX2RmU2ltdWxhdGlvbjEuUkRhdGEiKQ0KDQpsb2FkKCIuL2JfZGZTaW11bGF0aW9uMS5SRGF0YSIpDQoNCmBgYA0KDQoNCjUwMOWbnuS4rTHlm57jgIFyc3RhbuOBjOWPjuadn+OBl+OBquOBi+OBo+OBn+ippuihjA0KKOOBhOOBmuOCjOOBi+OBruODkeODqeODoeODvOOCv+OBriRcaGF0e1J9JOOBjDEuMTDjgpLkuIrlm57jgo/jgaPjgZ/oqabooYwp44GM44GC44Gj44Gf44CCDQrjgZPjgozjga/lj43lvqnmlbDjgYzotrPjgorjgarjgYvjgaPjgZ/jgZvjgYTjgaDjgajmgJ3jgYbjga7jgafjgIENCuWFrOW5s+OCkuacn+OBmeOCi+OBn+OCgeOAgeS7peS4i+OBp+OBrzHoqabooYzjgb7jgovjgZTjgajpmaTlpJbjgZnjgovjgILjgaTjgb7jgorjgIHku5bjga7mjqjlrprph4/jgavjgojjgosNCuaOqOWumue1kOaenOOCgumZpOWkluOBmeOCi+OAgg0KDQojIyMjIDEpIOaOqOWumuWApA0KDQrmjqjlrprlgKTjga/jganjga7jgY/jgonjgYTjgYLjgabjgavjgarjgovjgYvjgIHoqr/jgbnjgabjgb/jgojjgYbjgIINCuOBiuOBneOCieOBj+OAgeWcsOWfn+OBruaomeacrOOCteOCpOOCuiRuX2kk44GM5bCP44GV44GE44Go44GN44CB5o6o5a6a5YCk44Gv5q2j6Kej44GL44KJ44Ga44KM44Gm44GX44G+44GG44Gg44KN44GG44GL44KJ44CBDQokbl9pJOWIpeOBq+imi+OCi+W/heimgeOBjOOBguOCiuOBneOBhuOBoOOAgg0KDQpgYGB7cn0NCmRmUGxvdCA8LSBiLmRmU2ltdWxhdGlvbjEgJT4lDQogIGZpbHRlcighaXMubmEoZ0VzdF9yc3RhbikpICU+JQ0KICBkcGx5cjo6c2VsZWN0KG5TaXplLCBnViwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBnYXRoZXIoc1ZhciwgZ0VzdCwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBzZXBhcmF0ZShzVmFyLCBjKCJzVmFyMSIsICJzRXN0aW1hdG9yIikpICU+JQ0KICBtdXRhdGUoDQogICAgZ0RpZmYgICAgICA9IGdFc3QgLSBnViwgDQogICAgZkVzdGltYXRvciA9IGIuc3ViX0VzdGltYXRvckFzRmFjdG9yLjEoc0VzdGltYXRvcikNCiAgKSANCg0KZyA8LSBnZ3Bsb3QoZGF0YT1kZlBsb3QsIGFlcyh4ID0gblNpemUsIHk9Z0RpZmYsIGNvbG9yPWZFc3RpbWF0b3IpKQ0KZyA8LSBnICsgZ2VvbV9wb2ludChhbHBoYT0xLzUpDQpnIDwtIGcgKyBsYWJzKA0KICB4ICAgICA9ICJTYW1wbGUgU2l6ZSIsDQogIHkgICAgID0gZXhwcmVzc2lvbihoYXQodGhldGEpLXRoZXRhKSwNCiAgY29sb3IgPSAiRXN0aW1hdG9yIg0KKQ0KZyA8LSBnICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkNCmcgPC0gZyArIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDEwLCAxMDAsIGJ5ID0gMjApKQ0KZyA8LSBnICsgc2NhbGVfY29sb3JfbWFudWFsKA0KICBndWlkZT1GQUxTRSwgDQogIHZhbHVlcyA9IGIuc3ViX0VzdGltYXRvclBhbGV0dGUuMShkZlBsb3QkZkVzdGltYXRvcikNCikNCmcgPC0gZyArIGZhY2V0X2dyaWQofiBmRXN0aW1hdG9yKQ0KZyA8LSBnICsgdGhlbWVfYncoKQ0KDQpwcmludChnKQ0KDQpgYGANCue4pui7uOOBr+OAgeaOqOWumuWApOOBqOato+ino+OBqOOBruW3ruOCkuihqOOBl+OBpuOBhOOCi+OAgg0K44KE44Gv44KK44CB5qiZ5pys44K144Kk44K644GM5bCP44GV44GE44Go44GN44Gr44CB5q2j6Kej44GL44KJ44Gu44Ga44KM44GM5aSn44GN44GP44Gq44KL44CCDQoNCuaOqOWumuaWueazlSB4IOaomeacrOOCteOCpOOCuuWIpeOBq+OAgeaOqOWumuWApOOBqOato+ino+OBqOOBruW3ruOCkumbhuioiOOBl+OBpuOBv+OCiOOBhuOAgg0KYGBge3J9DQoNCmRmUGxvdCA8LSBiLmRmU2ltdWxhdGlvbjEgJT4lDQogIGZpbHRlcighaXMubmEoZ0VzdF9yc3RhbikpICU+JQ0KICBkcGx5cjo6c2VsZWN0KG5TaXplLCBnViwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBnYXRoZXIoc1ZhciwgZ0VzdCwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBzZXBhcmF0ZShzVmFyLCBjKCJzVmFyMSIsICJzRXN0aW1hdG9yIikpICU+JQ0KICBncm91cF9ieShzRXN0aW1hdG9yLCBuU2l6ZSkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBuRnJlcSA9IG4oKSwNCiAgICBnUk1TRSA9IHNxcnQobWVhbigoZ0VzdCAtIGdWKV4yKSkNCiAgKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBtdXRhdGUoZkVzdGltYXRvciA9IGIuc3ViX0VzdGltYXRvckFzRmFjdG9yLjEoc0VzdGltYXRvcikpIA0KDQpnIDwtIGdncGxvdChkYXRhPWRmUGxvdCwgYWVzKHggPSBuU2l6ZSwgeT1nUk1TRSwgZ3JvdXA9ZkVzdGltYXRvciwgY29sb3I9ZkVzdGltYXRvcikpIA0KZyA8LSBnICsgZ2VvbV9wYXRoKHNpemU9MSkNCmcgPC0gZyArIGxhYnMoeCA9ICJTYW1wbGUgU2l6ZSIsIHkgPSAib2JzZXJ2ZWQgUk1TRSIsIGNvbG9yPSJFc3RpbWF0b3IiKQ0KZyA8LSBnICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMTAsIDEwMCwgYnkgPSAxMCkpDQpnIDwtIGcgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYi5zdWJfRXN0aW1hdG9yUGFsZXR0ZS4xKGRmUGxvdCRmRXN0aW1hdG9yKSkNCmcgPC0gZyArIHRoZW1lX2J3KCkNCnByaW50KGcpDQoNCmBgYA0K57im6Lu444Gv44CM5o6o5a6a5YCk44Go5q2j6Kej44Go44Gu5beu44Gu5LqM5LmX44Gu5bmz5Z2H44Gu5bmz5pa55qC544CNKFJNU0Up44KS56S644GZ44CC5bmz44Gf44GP6KiA44Gj44Gh44KD44GG44Go44CBDQrmjqjlrprjgZfjgZ/lnLDln5/lubPlnYfjga/jgIHnnJ/jga7lnLDln5/lubPlnYfjgYvjgonjgaDjgYTjgZ/jgYTkvZXngrnjgY/jgonjgYTjgZrjgozjgovjgYvjgIHjgpLnpLrjgZfjgabjgYTjgovjgIINCg0K5qiZ5pys44K144Kk44K644GMMTDjga7jgajjgY3jgavjga/jgIHjgaDjgYTjgZ/jgYQz54K544GP44KJ44GE44Ga44KM44Gm44GX44G+44GG44CCDQrmqJnmnKzjgrXjgqTjgrrjgYzlpKfjgY3jgY/jgarjgovjgajjgIHjgZrjgozjga/lsI/jgZXjgY/jgarjgovjgIINCg0K44GT44GT44Gn6Zai5b+D44GM44GC44KL44Gu44Gv5o6o5a6a5pa55rOV44Gu6ZaT44Gu5beu44Gg44CCDQrkuIrjga7jg4Hjg6Pjg7zjg4jjgaDjgajlt67jgpLoqq3jgb/lj5bjgozjgarjgYTjga7jgafmj4/jgY3nm7TjgZ3jgYbjgIINCg0KYGBge3J9DQojIyMgb2JzZXJ2ZWQgUk1TRSAvIHRoZW9yZXRpY2FsIFJNU0Ugb2YgRGlyZWN0DQpkZlBsb3QgPC0gYi5kZlNpbXVsYXRpb24xICU+JQ0KICBmaWx0ZXIoIWlzLm5hKGdFc3RfcnN0YW4pKSAlPiUNCiAgZHBseXI6OnNlbGVjdChuU2l6ZSwgZ1YsIHN0YXJ0c193aXRoKCJnRXN0XyIpKSAlPiUNCiAgZ2F0aGVyKHNWYXIsIGdFc3QsIHN0YXJ0c193aXRoKCJnRXN0XyIpKSAlPiUNCiAgc2VwYXJhdGUoc1ZhciwgYygic1ZhcjEiLCAic0VzdGltYXRvciIpKSAlPiUNCiAgZ3JvdXBfYnkoc0VzdGltYXRvciwgblNpemUpICU+JQ0KICBzdW1tYXJpemUoDQogICAgZ1JNU0UgPSBzcXJ0KG1lYW4oKGdFc3QgLSBnVileMikpDQogICkgJT4lDQogIHVuZ3JvdXAoKSAlPiUNCiAgbXV0YXRlKA0KICAgIGdSYXRpbyAgICAgPSBnUk1TRSAvIHNxcnQoMTAwL25TaXplKSwNCiAgICBmRXN0aW1hdG9yID0gYi5zdWJfRXN0aW1hdG9yQXNGYWN0b3IuMShzRXN0aW1hdG9yKQ0KICApDQpnMSA8LSBnZ3Bsb3QoZGF0YT1kZlBsb3QsIGFlcyh4ID0gblNpemUsIHk9Z1JhdGlvLCBncm91cD1mRXN0aW1hdG9yLCBjb2xvcj1mRXN0aW1hdG9yKSkNCmcxIDwtIGcxICsgZ2VvbV9wYXRoKHNpemU9MSkNCmcxIDwtIGcxICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSkNCmcxIDwtIGcxICsgbGFicygNCiAgeCAgICAgPSAiU2FtcGxlIFNpemUiLA0KICB5ICAgICA9ICIob2JzZXJ2ZWQgUk1TRSkvKHRoZW9yZXRpY2FsIFJNU0Ugb2YgRGlyZWN0KSIsDQogIGNvbG9yID0gIkVzdGltYXRvciINCikNCmcxIDwtIGcxICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGIuc3ViX0VzdGltYXRvclBhbGV0dGUuMShkZlBsb3QkZkVzdGltYXRvcikpDQpnMSA8LSBnMSArIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDEwLCAxMDAsIGJ5ID0gMTApKQ0KZzEgPC0gZzEgKyB0aGVtZV9idygpDQpwcmludChnMSkNCg0KIyMjIChvYnNlcnZlZCBSTVNFKSAvIChvYnNlcnZlZCBSTVNFIG9mIERpcmVjdCkNCiMgZGZUZW1wIDwtIGIuZGZTaW11bGF0aW9uMSAlPiUNCiMgICBmaWx0ZXIoIWlzLm5hKGdFc3RfcnN0YW4pKSAlPiUNCiMgICBkcGx5cjo6c2VsZWN0KG5TaXplLCBnViwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KIyAgIGdhdGhlcihzVmFyLCBnRXN0LCBzdGFydHNfd2l0aCgiZ0VzdF8iKSkgJT4lDQojICAgc2VwYXJhdGUoc1ZhciwgYygic1ZhcjEiLCAic0VzdGltYXRvciIpKSAlPiUNCiMgICBncm91cF9ieShzRXN0aW1hdG9yLCBuU2l6ZSkgJT4lDQojICAgc3VtbWFyaXplKA0KIyAgICAgZ1JNU0UgPSBzcXJ0KG1lYW4oKGdFc3QgLSBnVileMikpDQojICAgKSAlPiUNCiMgICB1bmdyb3VwKCkgDQojIGRmVGVtcC4xIDwtIGRmVGVtcCAlPiUgZmlsdGVyKHNFc3RpbWF0b3IgIT0gIkRpcmVjdCIpDQojIGRmVGVtcC4yIDwtIGRmVGVtcCAlPiUgDQojICAgZmlsdGVyKHNFc3RpbWF0b3IgPT0gIkRpcmVjdCIpICU+JSANCiMgICByZW5hbWUoZ1JNU0VfRGlyZWN0ID0gZ1JNU0UpICU+JQ0KIyAgIGRwbHlyOjpzZWxlY3QoLXNFc3RpbWF0b3IpDQojIGRmUGxvdCA8LSBmdWxsX2pvaW4oZGZUZW1wLjEsIGRmVGVtcC4yLCBieSA9ICJuU2l6ZSIpICU+JQ0KIyAgIG11dGF0ZSgNCiMgICAgIGdSYXRpbyAgICAgPSBnUk1TRSAvIGdSTVNFX0RpcmVjdCwNCiMgICAgIGZFc3RpbWF0b3IgPSBiLnN1Yl9Fc3RpbWF0b3JBc0ZhY3Rvci4xKHNFc3RpbWF0b3IpDQojICAgKQ0KIyBnMSA8LSBnZ3Bsb3QoZGF0YT1kZlBsb3QsIGFlcyh4ID0gblNpemUsIHk9Z1JhdGlvLCBncm91cD1mRXN0aW1hdG9yLCBjb2xvcj1mRXN0aW1hdG9yKSkNCiMgZzEgPC0gZzEgKyBnZW9tX3BhdGgoc2l6ZT0xKQ0KIyBnMSA8LSBnMSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEpDQojIGcxIDwtIGcxICsgbGFicygNCiMgICB4ICAgICA9ICJTYW1wbGUgU2l6ZSIsDQojICAgeSAgICAgPSAiKFJNU0UpLyhSTVNFIG9mIERpcmVjdCkiLA0KIyAgIGNvbG9yID0gIkVzdGltYXRvciINCiMgKQ0KIyBnMSA8LSBnMSArIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDEwLCAxMDAsIGJ5ID0gMTApKQ0KIyBnMSA8LSBnMSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBiLnN1Yl9Fc3RpbWF0b3JQYWxldHRlLjEoZGZQbG90JGZFc3RpbWF0b3IpKQ0KIyBnMSA8LSBnMSArIHRoZW1lX2J3KCkNCiMgcHJpbnQoZzEpDQoNCmcyIDwtIGdncGxvdCgNCiAgZGF0YT1kZlBsb3QgJT4lIGZpbHRlcihuU2l6ZSA9PSAxMCksDQogIGFlcyh4ID0gZkVzdGltYXRvciwgeSA9IGdSYXRpbywgY29sb3I9ZkVzdGltYXRvcikNCikNCmcyIDwtIGcyICsgZ2VvbV9wb2ludChzaXplPTUpDQpnMiA8LSBnMiArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEpDQpnMiA8LSBnMiArIGxhYnMoDQogIHggICAgID0gIkVzdGltYXRvciIsDQogIHkgICAgID0gIihvYnNlcnZlZCBSTVNFKS8odGhlb3JldGljYWwgUk1TRSBvZiBEaXJlY3QpLCBzaXplPTEwIg0KKQ0KZzIgPC0gZzIgKyBzY2FsZV9jb2xvcl9tYW51YWwoDQogIGd1aWRlID0gRkFMU0UsIA0KICB2YWx1ZXMgPSBiLnN1Yl9Fc3RpbWF0b3JQYWxldHRlLjEoZGZQbG90JGZFc3RpbWF0b3IpDQopDQpnMiA8LSBnMiArIHRoZW1lX2J3KCkNCnByaW50KGcyKQ0KIyBncmlkLmFycmFuZ2UoZzEsIGcyLCBuY29sID0gMikNCg0KYGBgDQoNCuOBleOBjeOBu+OBqeaxguOCgeOBn1JNU0Xjga/jg4fjg7zjgr/jgYvjgonlvpfjgZ/jgoLjga7jgaDjgYzjgIENCuaomeacrOaKveWHuuiqpOW3ruOBr+Wun+OBrzEwMOOBquOBruOBp+OAgeOBk+OCjOOCkuaXouefpeOBqOOBmeOCi+OBquOCieOBsOOAgQ0K5qiZ5pys5bmz5Z2H44GuUk1TReOBryRcc3FydHsxMDAvbl9pfSTjgafjgYLjgovjgIINCuS4iuOBrjLmnprjga7lm7Pjga7nuKbou7jjga/jgIHjgZPjga7nkIblsYjkuIrjga7lgKTjgpLln7rmupbjgavjgIHjgZ3jgozjgZ7jgozjga7mjqjlrprmlrnms5XjgavjgojjgovmjqjlrprlgKTjga4NClJNU0XjgpLmr5TjgafooajjgZfjgabjgYTjgoso44Gk44G+44KK44CB6ZW344GE55uu44Gn44G/44KM44Gw5qiZ5pys5bmz5Z2HKERpcmVjdCnjga7mipjjgoznt5rjga8NCue4pui7uDHjga7kvY3nva7jga7msLTlubPnt5rjgavjgarjgovjga/jgZrjgafjgIHjgZ3jgYbjgarjgaPjgabjgYTjgarjgYTjga7jga/pgYvjga7llY/poYzjgafjgYLjgosp44CCDQrkuIvjgavjgYTjgY/jgbvjganjgIHmjqjlrprlgKTjgajnnJ/jga7lgKTjga7jgZrjgozjgYzlsI/jgZXjgYTjgIINCg0K5LiK44Gu5Zuz44Gv5YWo5Zyw5Z+f44CC5LiL44Gu5Zuz44Gv5qiZ5pys44K144Kk44K6MTDjga7lnLDln5/jga7jgb/mi6HlpKfjgZfjgabjgYTjgovjgIINCg0K5Lul5LiL44Gu54K544GM44G/44Gm44Go44KM44KL44CCDQoNCi0gbmxtZeODkeODg+OCseODvOOCuOOBruaOqOWumuWApOOBr+ecn+WApOOBqOOBruOBmuOCjOOBjOWkp+OBjeOBhOOAgg0KICBSTVNF44GM5qiZ5pys5bmz5Z2H44KI44KK5aSn44GN44GE44KP44GR44Gn44CBDQogIOOAjOWwj+WcsOWfn+ODouODh+ODq+OCkuS9v+OBo+OBn+aOqOWumuOBquOCk+OBpuOBl+OBquOBjeOCg+OCiOOBi+OBo+OBn+OAjeOBqOOBhOOBhuS6i+aFi+OBp+OBguOCi+OAgg0KICDnkIbnlLHjga/jgojjgY/jgo/jgYvjgonjgarjgYQuLi4NCi0gbmxtZeOCkuWIpeOBq+OBmeOCjOOBsOOAgSoqSELmjqjlrposIEVCTFVQ5o6o5a6aLCDmqJnmnKzlubPlnYfjga7poIbjgavjgZrjgozjgYzlsI/jgZXjgYQqKuOAgg0KICDmqJnmnKzjgrXjgqTjgrrjgYzlpKfjgY3jgY/jgarjgovjgajjgIFIQuOBqEVCTFVQ44Gu5beu44Gv57iu44G+44KK44CB44GV44KJ44Gr5qiZ5pys5bmz5Z2H44Go44Gu5beu44KC57iu44G+44KL44CCDQoNCiMjIyMgMikgTVNF44Gu5o6o5a6a5YCkDQoNCuOBk+OCk+OBqeOBr01TReOBruaOqOWumuWApOOBq+OBpOOBhOOBpuiqv+OBueOBpuOBv+OCiOOBhuOAgg0KDQrmjqjlrprph4/jga5NU0Xjgajjga/jgIHjgIzku67jgavjgYLjgovmjqjlrprlgKTjgpLlvpfjgabjgIHjgZ3jga7lgKTjgpLnnJ/jga7lgKTjgajmr5TjgbnjgovjgZPjgajjgYzjgafjgY3jgovjgarjgonjgIENCuW3ruOBruS6jOS5l+OBruacn+W+heWApOOBjOOBqeOBhuOBquOCi+OBi+OAjeOBqOOBhOOBhuWApOOBp+OBguOCi+OAgg0K44GT44Gu5a6f6aiT44Gn44Gv55yf44Gu5YCk44GM5YiG44GL44Gj44Gm44GE44KL44Gu44Gg44GL44KJ44CBDQrmjqjlrprlgKTjgajnnJ/lgKTjga7lt67jga7kuozkuZfjgZ3jga7jgoLjga7jgYzmiYvjgavlhaXjgovjgILjgZPjga7lrp/nuL7jgpLjgIENCuaOqOWumuOBleOCjOOBn01TReOBqOavlOOBueOBpuOBv+OCiOOBhuOBp+OBr+OBquOBhOOBi+OAgg0KDQpgYGB7cn0NCg0KZGZQbG90IDwtIGIuZGZTaW11bGF0aW9uMSAlPiUNCiAgZmlsdGVyKCFpcy5uYShnRXN0X3JzdGFuKSkgJT4lDQogIGRwbHlyOjpzZWxlY3QobkRhdGFzZXQsIG5BcmVhLCBuU2l6ZSwgZ1YsIHN0YXJ0c193aXRoKCJnRXN0XyIpLCBzdGFydHNfd2l0aCgiZ01TRV8iKSkgJT4lIA0KICBnYXRoZXIoc1ZhciwgZ1ZhbHVlLCBjKHN0YXJ0c193aXRoKCJnRXN0XyIpLCBzdGFydHNfd2l0aCgiZ01TRV8iKSkpICU+JQ0KICBzZXBhcmF0ZShzVmFyLCBjKCJzVmFyIiwgInNFc3RpbWF0b3IiKSkgJT4lDQogIHNwcmVhZChzVmFyLCBnVmFsdWUpICU+JQ0KICBmaWx0ZXIoc0VzdGltYXRvciAhPSAibmxtZSIpICU+JQ0KICBtdXRhdGUoDQogICAgZ0RpZmYgICAgICA9IGdNU0UgLSAoZ0VzdCAtIGdWKV4yLA0KICAgIGZFc3RpbWF0b3IgPSBiLnN1Yl9Fc3RpbWF0b3JBc0ZhY3Rvci4xKHNFc3RpbWF0b3IpDQogICkNCmcgPC0gZ2dwbG90KGRhdGE9ZGZQbG90LCBhZXMoeCA9IG5TaXplLCB5ID0gZ0RpZmYsIGNvbG9yID0gZkVzdGltYXRvcikpIA0KZyA8LSBnICsgZ2VvbV9wb2ludChhbHBoYT0xLzUpDQpnIDwtIGcgKyBsYWJzKA0KICB4ID0gIlNhbXBsZSBTaXplIiwgDQogIHkgPSAiKEVzdGltYXRlZCBNU0UpLShBY3R1YWwgU3EuRXJyKSINCikNCmcgPC0gZyArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApDQpnIDwtIGcgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgxMCwgMTAwLCBieSA9IDIwKSkNCmcgPC0gZyArIGZhY2V0X2dyaWQofiBmRXN0aW1hdG9yKQ0KZyA8LSBnICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGIuc3ViX0VzdGltYXRvclBhbGV0dGUuMShkZlBsb3QkZkVzdGltYXRvcikpDQpnIDwtIGcgKyB0aGVtZV9idygpDQpwcmludChnKQ0KDQpgYGANCg0K57im6Lu444Gv44CB44CM5o6o5a6a44GV44KM44GfTVNF44GL44KJ44CB5o6o5a6a5YCk44Go5q2j6Kej44Go44Gu5beu44Gu5LqM5LmX44KS5byV44GE44Gf5YCk44CN44Gn44GC44KL44CCDQrnuKbou7jjgYww44Gg44Go44GE44GG44GT44Go44Gv44CBDQrmjqjlrprlgKTjgajmraPop6Pjgajjga7plpPjgavjga/jgZrjgozjgYzjgYLjgaPjgZ/jgYvjgoLjgZfjgozjgarjgYTjgYzjgIHjgZ3jga7jgZrjgozjga7lpKfjgY3jgZXjga/kuojmg7PpgJrjgorjgaDjgaPjgZ/jgIENCuOBqOOBhOOBhuOBk+OBqOOCkuihqOOBl+OBpuOBhOOCi+OAguato+OBruWApOOBr+OAjOaAneOBo+OBn+OCiOOCiuOBmuOCjOOBquOBi+OBo+OBn+OAjeOBpOOBvuOCig0KTVNF44GM6YGO5aSn44Gr5o6o5a6a44GV44KM44Gm44GE44Gf44GT44Go44KS6KGo44GX44CBDQrosqDjga7lgKTjga/jgIzmgJ3jgaPjgZ/jgojjgorjgZrjgozjgZ/jgI3jgaTjgb7jgopNU0XjgYzpgY7lsI/jgavmjqjlrprjgZXjgozjgabjgYTjgZ/jgZPjgajjgpLooajjgZnjgIINCuOBquOBiuOAgW5sbWXjg5Hjg4PjgrHjg7zjgrjjgYzjgarjgYTjga7jga/jgIHjgZnjgafjgavov7DjgbnjgZ/jgojjgYbjgavjgIENCm5sbWXjg5Hjg4PjgrHjg7zjgrjjgYxFQkxVUOaOqOWumumHj+OBrk1TReOBruaOqOWumuOCkuaPkOS+m+OBl+OBpuOBhOOBquOBhOOBi+OCieOBp+OBguOCi+OAgg0KDQrmqJnmnKzjgrXjgqTjgrrjgYzlsI/jgZXjgYTmmYLjgIFNU0Xjga7mjqjlrprjga8NCumBjuWwj+OBoOOBo+OBn+OCiumBjuWkp+OBoOOBo+OBn+OCiuOBl+OChOOBmeOBj+OBquOCi+OBk+OBqOOBjOimi+OBpuWPluOCjOOCi+OAgg0KDQrjgafjga/jgIHmjqjlrprmlrnms5UgeCDmqJnmnKzjgrXjgqTjgrrliKXjgavjgIFNU0XjgYzpgY7lsI/jg7vpgY7lpKfjgaDjgaPjgZ/nqIvluqbjgavjgaTjgYTjgaboqr/jgbnjgabjgb/jgojjgYbjgIINCg0KYGBge3J9DQpkZlBsb3QgPC0gYi5kZlNpbXVsYXRpb24xICU+JQ0KICBmaWx0ZXIoIWlzLm5hKGdFc3RfcnN0YW4pKSAlPiUNCiAgZHBseXI6OnNlbGVjdChuU2l6ZSwgZ1YsIHN0YXJ0c193aXRoKCJnRXN0XyIpLCBzdGFydHNfd2l0aCgiZ01TRV8iKSkgJT4lDQogIGdhdGhlcihzVmFyLCBnVmFsdWUsIGMoc3RhcnRzX3dpdGgoImdFc3RfIiksIHN0YXJ0c193aXRoKCJnTVNFXyIpKSkgJT4lDQogIHNlcGFyYXRlKHNWYXIsIGMoInNWYXIiLCAic0VzdGltYXRvciIpKSAlPiUNCiAgc3ByZWFkKHNWYXIsIGdWYWx1ZSkgJT4lDQogIGZpbHRlcihzRXN0aW1hdG9yICE9ICJubG1lIikgJT4lDQogIG11dGF0ZSgNCiAgICBnRGlmZiAgICA9IGdNU0UgLSAoZ0VzdCAtIGdWKV4yDQogICkgJT4lIA0KICBncm91cF9ieShzRXN0aW1hdG9yLCBuU2l6ZSkgJT4lDQogIHN1bW1hcml6ZSggZ01lYW5EaWZmID0gbWVhbihnRGlmZikgKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBtdXRhdGUoIGZFc3RpbWF0b3IgPSBiLnN1Yl9Fc3RpbWF0b3JBc0ZhY3Rvci4xKHNFc3RpbWF0b3IpICkgDQoNCmcgPC0gZ2dwbG90KGRhdGE9ZGZQbG90LCBhZXMoeCA9IG5TaXplLCB5PWdNZWFuRGlmZiwgZ3JvdXA9ZkVzdGltYXRvciwgY29sb3I9ZkVzdGltYXRvcikpIA0KZyA8LSBnICsgZ2VvbV9wYXRoKHNpemU9MSkNCmcgPC0gZyArIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDEwLCAxMDAsIGJ5ID0gMTApKQ0KZyA8LSBnICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkNCmcgPC0gZyArIGxhYnMoDQogIHggICAgID0gIlNhbXBsZSBTaXplIiwgDQogIHkgICAgID0gIm1lYW4oIChFc3RpbWF0ZWQgTVNFKS0oQWN0dWFsIFNxLkVycikgKSIsDQogIGNvbG9yID0gIkVzdGltYXRvciINCikNCmcgPC0gZyArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBiLnN1Yl9Fc3RpbWF0b3JQYWxldHRlLjEoZGZQbG90JGZFc3RpbWF0b3IpKQ0KZyA8LSBnICsgdGhlbWVfYncoKQ0KcHJpbnQoZykNCmBgYA0KDQrnuKbou7jjga/jgIHjgIzmjqjlrprjgZXjgozjgZ9NU0XjgYvjgonjgIHmjqjlrprlgKTjgajmraPop6Pjgajjga7lt67jga7kuozkuZfjgpLlvJXjgYTjgZ/lgKTjgI3jga7lubPlnYfjgafjgYLjgovjgIINCuato+OBruWApOOBr01TReOBruaOqOWumuOBjOamguOBl+OBpumBjuWkp+OBp+OBguOCi+OBk+OBqOOAgeiyoOOBruWApOOBr+amguOBl+OBpumBjuWwj+OBp+OBguOCi+OBk+OBqOOCkuihqOOBmeOAgg0KDQrlhajkvZPnmoTjgarjgafjgZPjgbzjgZPjga/pgYvjga7llY/poYzjgajjgZfjgabjgIENCuOBk+OBk+OBp+azqOebruOBl+OBn+OBhOOBruOBr+aOqOWumuaWueazlemWk+OBruW3ruOBp+OBguOCi+OAguOCiOOBj+OBv+OCi+OBqOOAgeaomeacrOOCteOCpOOCuuOBjDEw44Gu44Go44GN44CBDQoqKkVCTFVQ5o6o5a6a44GuTVNF44Gu5o6o5a6a44GM6YGO5bCPKirjgafjgYLjgovjgZPjgajjgYzopovjgablj5bjgozjgovjgIINCuOBqOOBj+OBq2hic2Fl44OR44OD44Kx44O844K444GuRUJMVVDmjqjlrprjga/pgY7lsI/jgajjgarjgovnqIvluqbjgYzlpKfjgY3jgY/jgIHmqJnmnKzjgrXjgqTjgrrjgYwyMCwgMzDjga7jgajjgY3jgavjgoINCuOChOOChOmBjuWwj+OBq+OBquOBo+OBpuOBhOOCi+OAgg0KDQpFQkxVUOaOqOWumuOBrk1TReOBruaOqOWumuOBjOmBjuWwj+OBq+OBquOCi+OBruOBr+OAgQ0KRUJMVVDmjqjlrprjgafjga8oMSnjgYTjgaPjgZ/jgpMkXGhhdHtcc2lnbWFeMl92fSTjga7ngrnmjqjlrprlgKTjgpLmsYLjgoHjgIENCigyKeOBk+OCjOOCkuS9v+OBo+OBpiRcdGhldGFfaSTjgpLmjqjlrprjgZnjgovjgIHjgajjgYTjgYbmlrnms5XjgpLlj5bjgaPjgabjgYTjgovjgYvjgonjgaDjgajmgJ3jgYbjgIINCuOBpOOBvuOCiuOAgeacrOW9k+OBryRcaGF0e1xzaWdtYV4yX3Z9JOOBq+OCguWIhuaVo+OBjOOBguOCi+OBruOBoOOBjOOAgeOBneOCjOOCkueEoeimluOBl+OBpuOBhOOCi+OCj+OBkeOBp+OAgQ0K44Gd44Gu5YiGTVNF44GM6YGO5bCP6KmV5L6h44GV44KM44KL44Gu44GgLi4uIOOBqOOBhOOBhueQhuino+OBp+OAgeOBguOBo+OBpuOBvuOBmeOBi+OBre+8nw0KDQojIyMgMy4zLjQgIOWcsOWfn+aVsCB2cy4g5o6o5a6a44Gu57K+5bqmDQoNCuOBleOBjeOBu+OBqeOBr+WcsOWfn+OBruaVsOOCkjEw44Gr5Zu65a6a44GX44Gm44GE44Gf44CC44GT44KM44GM5aSa44GP44Gq44Gj44Gf44KJ44Gp44GG44Gq44KL44GL77yfDQoNCuOBleOBjeOBu+OBqeOBqOWQjOOBmOOBj+OAgTTjg5bjg63jg4Pjgq/jgIHlnLDln5/lirnmnpzjga7liIbmlaPjga81MOOBqOOBl+OAgQ0K5Zyw5Z+f44Gu5pWw44KSMTAsIDEwMCwgMjAwLCAzMDDjgajli5XjgYvjgZfjgarjgYzjgonjgIENCjUwMOWbnuOBpeOBpOe5sOOCiui/lOOBl+OBpuOBv+OCiOOBhuOAgg0KDQrjgarjgYrjgIHjgZPjga7jgrfjg5/jg6Xjg6zjg7zjgrfjg6fjg7Pjga/jgZnjgZTjgY/mmYLplpPjgYzjgYvjgYvjgovjga7jgafjgIFubG1l44OR44OD44Kx44O844K444GoDQpyc3RhbuODkeODg+OCseODvOOCuOOBr+ecgeeVpeOBl+OBn+OAgg0KDQpgYGB7ciByZXN1bHRzPSJoaWRlIn0NCg0KIyBzZXQuc2VlZCgxMjMpDQojIGxPdXQgPC0gbGFwcGx5KA0KIyAgIGMoMTAsIDEwMCwgMjAwLCAzMDApLA0KIyAgIGZ1bmN0aW9uKG5OdW1BcmVhKXsNCiMgICAgIGNhdCgibk51bUFyZWEgPSAiLCBuTnVtQXJlYSwgIi4uLlxuIikNCiMgICAgIGRmRGF0YSAgIDwtIGIuc3ViX0dlbmVyYXRlTXVsdGlEYXRhc2V0MS4xKA0KIyAgICAgICBuTnVtRGF0YXNldCA9IDUwMCwgbk51bUFyZWEgPSBuTnVtQXJlYSwgbk51bUdyb3VwID0gNEwsIGdWYXJWID0gNTANCiMgICAgICkNCiMgICAgIGRmUmVzdWx0IDwtIGIuc3ViX0VzdGltYXRlTXVsdGlEYXRhc2V0MS4xKA0KIyAgICAgICBkZkRhdGEsIA0KIyAgICAgICBhc01ldGhvZCA9IGMoInNhZVJFTUwiLCAiaGJzYWVSRU1MIiwgImhic2FlSEIiLCAiYmF5ZXNzYWUiKSAgICAgIA0KIyAgICAgKQ0KIyAgICAgZGZSZXN1bHQkbk51bUFyZWEgPC0gbk51bUFyZWENCiMgICAgIGNhdCgiXG4iKQ0KIyAgICAgcmV0dXJuKGRmUmVzdWx0KQ0KIyAgIH0NCiMgKQ0KIyBiLmRmU2ltdWxhdGlvbjIgPC0gYmluZF9yb3dzKGxPdXQpICU+JQ0KIyAgIGZpbHRlcihuQXJlYSA9PSAxKQ0KIyBzYXZlKGIuZGZTaW11bGF0aW9uMiwgZmlsZT0iLi9iX2RmU2ltdWxhdGlvbjIuUkRhdGEiKQ0KDQpsb2FkKCIuL2JfZGZTaW11bGF0aW9uMi5SRGF0YSIpDQoNCmBgYA0KDQrjgarjgYrjgIHku6XkuIvjgafjga8qKuaomeacrOOCteOCpOOCuuOBjDEw44Gn44GC44KL5Zyw5Z+f44Gg44GR44Gr5rOo55uu44GZ44KLKirjgIINCuOBvuOBn+OAgeadoeS7tumWk+OBp+WIhuaekOS7tuaVsOOCkuaPg+OBiOOCi+OBn+OCgeOBq+OAgeWcsOWfn+eVquWPtzHjgaDjgZHjgavpmZDlrprjgZfjgabliIbmnpDjgZnjgovjgIINCuWQhOadoeS7tuOBq+OBiuOBhOOBpjUwMOS7tuOBruaOqOWumue1kOaenOOBjOS9v+OBiOOCi+OCj+OBkeOBp+OBguOCi+OAgg0KDQojIyMjIDEpIOaOqOWumuWApA0KDQrlnLDln5/mlbAgeCDmjqjlrprmlrnms5XliKXjgavjgIHmjqjlrprlgKTjgajmraPop6Pjgajjga7jgZrjgozjgpLpm4boqIjjgZfjgabjgb/jgojjgYbjgIINCmBgYHtyfQ0KDQpkZlBsb3QgPC0gYi5kZlNpbXVsYXRpb24yICU+JQ0KICBkcGx5cjo6c2VsZWN0KG5OdW1BcmVhLCBnViwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBnYXRoZXIoc1ZhciwgZ0VzdCwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBzZXBhcmF0ZShzVmFyLCBjKCJzVmFyMSIsICJzRXN0aW1hdG9yIikpICU+JQ0KICBncm91cF9ieShzRXN0aW1hdG9yLCBuTnVtQXJlYSkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBuRnJlcSA9IG4oKSwNCiAgICBnUk1TRSA9IHNxcnQobWVhbigoZ0VzdCAtIGdWKV4yKSkNCiAgKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBtdXRhdGUoDQogICAgZkVzdGltYXRvciA9IGIuc3ViX0VzdGltYXRvckFzRmFjdG9yLjEoc0VzdGltYXRvcikgIyAsDQogICAgIyBmTnVtQXJlYSA9IGZhY3RvcihuTnVtQXJlYSwgbGV2ZWxzPWMoMTAsIDEwMCwgMjAwLCAzMDApKQ0KICApDQoNCmcgPC0gZ2dwbG90KGRhdGE9ZGZQbG90LCBhZXMoeCA9IG5OdW1BcmVhLCB5PWdSTVNFLCBncm91cD1mRXN0aW1hdG9yLCBjb2xvcj1mRXN0aW1hdG9yKSkNCmcgPC0gZyArIGdlb21fcGF0aChzaXplPTEpDQpnIDwtIGcgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLCAxMCwgMTAwLCAyMDAsIDMwMCkpDQpnIDwtIGcgKyBsYWJzKHggPSAiTnVtLiBBcmVhIiwgeSA9ICJvYnNlcnZlZCBSTVNFIiwgY29sb3I9IkVzdGltYXRvciIpDQpnIDwtIGcgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYi5zdWJfRXN0aW1hdG9yUGFsZXR0ZS4xKGRmUGxvdCRmRXN0aW1hdG9yKSkNCmcgPC0gZyArIHRoZW1lX2J3KCkNCnByaW50KGcpDQoNCmBgYA0KDQrjgZXjgY3jgbvjganlkIzmp5jjgIHnuKbou7jjga/jgIzmjqjlrprlgKTjgajmraPop6Pjgajjga7lt67jga7kuozkuZfjga7lubPlnYfjga7lubPmlrnmoLnjgI0oUk1TRSnjgpLnpLrjgZfjgabjgYTjgovjgIINCuOBleOBjeOBu+OBqeeiuuiqjeOBl+OBn+OCiOOBhuOBq+OAgeWcsOWfn+aVsDEw44Gu5aC05ZCI44Gr44Gv44CB44Gg44GE44Gf44GEM+eCueOBj+OCieOBhOOBmuOCjOOCi+OAgg0K44Gd44Gu44Ga44KM44Gv44CBSELmjqjlrposIEVCTFVQ5o6o5a6aLCDmqJnmnKzlubPlnYfjga7poIbjgavlsI/jgZXjgYTjgIINCg0K44GV44Gm44CB5LiK44Gu5Zuz44GL44KJ44Gv44CB5Zyw5Z+f5pWw44GM5aKX44GI44KL44GoSELmjqjlrprjgahFQkxVUOaOqOWumuOBq+OBiuOBkeOCi+OBmuOCjOOBjOOBleOCieOBq+Wwj+OBleOBj+OBquOCiw0K44GT44Go44GM44KP44GL44KL44CC44G+44Gf44CBDQpIQuaOqOWumuOBqEVCTFVQ5o6o5a6a44Gu6ZaT44Gu5beu44Gv5raI5aSx44GX44CB5qiZ5pys5bmz5Z2H44Go44Gu5beu44GM5bqD44GM44KL44CCDQoNCuOBquOCi+OBu+OBqeOAgeWwj+WcsOWfn+ODouODh+ODq+OBq+OCiOOCi+aOqOWumuOBr+OAgeOBhOOCj+OBsOS7luOBruWcsOWfn+OBi+OCiQ0K5oOF5aCx44KS5YCf44KK44Gm44GP44KL44KI44GG44Gq44KC44Gu44Gg44GL44KJ44CB5LuW44Gu5Zyw5Z+f44Gu5pWw44GM5aSn44GN44GE44G744GG44GM44KI44KK5pyJ5Yip44Gr44Gq44KL44Gu44Gg44KN44GG44CCDQoNCiMjIyMgMikgTVNF44Gu5o6o5a6a5YCkDQoNCuOBk+OCk+OBqeOBr+OAgeWcsOWfn+aVsCB4IOaOqOWumuaWueazleWIpeOBq+OAgU1TReOBruaOqOWumuOBjA0K6YGO5bCP44O76YGO5aSn44Gg44Gj44Gf56iL5bqm44Gr44Gk44GE44Gm6Kq/44G544Gm44G/44KI44GG44CCDQpgYGB7cn0NCg0KZGZQbG90IDwtIGIuZGZTaW11bGF0aW9uMiAlPiUNCiAgZHBseXI6OnNlbGVjdChuTnVtQXJlYSwgZ1YsIHN0YXJ0c193aXRoKCJnRXN0XyIpLCBzdGFydHNfd2l0aCgiZ01TRV8iKSkgJT4lDQogIGdhdGhlcihzVmFyLCBnVmFsdWUsIGMoc3RhcnRzX3dpdGgoImdFc3RfIiksIHN0YXJ0c193aXRoKCJnTVNFXyIpKSkgJT4lDQogIHNlcGFyYXRlKHNWYXIsIGMoInNWYXIiLCAic0VzdGltYXRvciIpKSAlPiUNCiAgc3ByZWFkKHNWYXIsIGdWYWx1ZSkgJT4lDQogIG11dGF0ZSgNCiAgICBnVHJ1ZVNFID0gKGdFc3QgLSBnVileMiwgDQogICAgZ0RpZmYgICA9IGdNU0UgLSBnVHJ1ZVNFIA0KICApICU+JSANCiAgZ3JvdXBfYnkoc0VzdGltYXRvciwgbk51bUFyZWEpICU+JQ0KICBzdW1tYXJpemUoDQogICAgZ01lYW5EaWZmID0gbWVhbihnRGlmZikNCiAgKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBtdXRhdGUoDQogICAgZkVzdGltYXRvciA9IGIuc3ViX0VzdGltYXRvckFzRmFjdG9yLjEoc0VzdGltYXRvcikgIywNCiAgICAjIGZOdW1BcmVhID0gZmFjdG9yKG5OdW1BcmVhLCBsZXZlbHM9YygxMCwgMTAwLCAyMDAsIDMwMCkpDQogICkgDQoNCmcgPC0gZ2dwbG90KA0KICBkYXRhPWRmUGxvdCwgDQogIGFlcyh4ID0gbk51bUFyZWEsIHk9Z01lYW5EaWZmLCBncm91cD1mRXN0aW1hdG9yLCBjb2xvcj1mRXN0aW1hdG9yKQ0KKQ0KZyA8LSBnICsgZ2VvbV9wYXRoKHNpemUgPSAxKQ0KZyA8LSBnICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkNCmcgPC0gZyArIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDAsIDEwLCAxMDAsIDIwMCwgMzAwKSkNCmcgPC0gZyArIGxhYnMoDQogIHggICAgID0gIk51bS4gQXJlYSIsIA0KICB5ICAgICA9ICJtZWFuICgoRXN0aW1hdGVkIE1TRSkgLSAoQWN0dWFsIFNxLkVycikpIiwNCiAgY29sb3IgPSAiRXN0aW1hdG9yIg0KKQ0KZyA8LSBnICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGIuc3ViX0VzdGltYXRvclBhbGV0dGUuMShkZlBsb3QkZkVzdGltYXRvcikpDQpnIDwtIGcgKyB0aGVtZV9idygpDQoNCnByaW50KGcpDQoNCmBgYA0KDQrkvovjgavjgojjgaPjgabjgIHnuKbou7jjga/jgIzmjqjlrprjgZXjgozjgZ9NU0XjgYvjgonmjqjlrprlgKTjgajmraPop6Pjgajjga7lt67jga7kuozkuZfjgpLlvJXjgYTjgZ/lgKTjgI3jga7lubPlnYfjgafjgYLjgovjgIINCuato+OBruWApOOBr01TReOBruaOqOWumuOBjOamguOBl+OBpumBjuWkp+OBp+OBguOCi+OBk+OBqOOAgeiyoOOBruWApOOBr+amguOBl+OBpumBjuWwj+OBp+OBguOCi+OBk+OBqOOCkuihqOOBmeOAgg0KDQrjgZnjgafjgavjgIHlnLDln5/mlbAxMOOBp+aomeacrOOCteOCpOOCuuOBjDEw44Gu44Go44GN44CBRUJMVVDmjqjlrpoo54m544GraGJzYWXjg5Hjg4PjgrHjg7zjgrgp44GnDQpNU0XjgYzpgY7lsI/oqZXkvqHjgZXjgozjgovjgajjgYTjgYbjgZPjgajjgYzjgo/jgYvjgaPjgZ/jgIINCuOBl+OBi+OBl+S4iuOBruWbs+OBi+OCieOBr+OAgeOBneOCjOOBr+WcsOWfn+aVsOOBjOWwkeOBquOBhOOBqOOBjeOBruipseOBp+OBguOBo+OBpuOAgQ0K5Zyw5Z+f5pWw44GM5aSa44GR44KM44Gw5rCX44Gr44GX44Gq44GP44Gm44KI44GE44Go44GE44GG44GT44Go44GM44KP44GL44KL44CCDQoNCiMjIyAzLjMuNCAg5YWx5aSJ6YeP44Gu5pWwIHZzLiDmjqjlrprjga7nsr7luqYNCg0K44GT44GT44Gn44Gh44KH44Gj44Go5aSJ44Gq5a6f6aiT44KS6Kmm44GX44Gm44G/44KL44CCDQoNCuOBk+OBk+OBvuOBp+OBr+OAgeWcsOWfn+ODrOODmeODq+OBruWFseWkiemHj+OBqOOBl+OBpuOAgeWcsOWfn+OBruODluODreODg+OCryg05rC05rqW44Gu44Kr44OG44K044Oq5aSJ5pWwKeOCkuaKleWFpeOBl+OBpuOBhOOBn+OAgg0K44GE44GE44GL44GI44KL44Go44CBM+OBpOOBruS6jOWApOWkieaVsOOCkuWFseWkiemHj+OBqOOBl+OBpuaKleWFpeOBl+OBpuOBhOOBn+OAgg0KDQrlrp/jga/jgIHlnLDln5/jga7jg5bjg63jg4Pjgq/jga/lubjnpo/luqbjgajnhKHplqLkv4LjgafjgYLjgovjgILjgaTjgb7jgorjgIENCuecn+OBruS/guaVsCRcbWF0aGJme1xiZXRhfSTjga8kXG1hdGhiZnswfSTjgafjgYLjgovjgILjgafjgoLliIbmnpDogIXjga8NCuOBneOBruOBk+OBqOOBq+awl+OBpeOBhOOBpuOBhOOBquOBhOOCj+OBkeOBp+OBguOCi+OAgg0KDQrjgZPjga7lhbHlpInph4/jga7mlbDjgYzmuJvjgaPjgZ/jgonjgIHjgb7jgZ/lopfjgYjjgZ/jgonjgIHkvZXjgYzotbfjgY3jgovjgaDjgo3jgYbjgYvjgIINCg0K5aSJ44Gq44GT44Go44Gr6Zai5b+D44KS5oyB44Gk44Go5oCd44KP44KM44KL44GL44KC44GX44KM44Gq44GE44GR44KM44Gp44CB5YCL5Lq655qE44Gr44GvDQrjgaHjgofjgaPjgajliIflrp/jgarnlpHllY/jgarjgpPjgafjgZnjgILjgaDjgaPjgabjgIHlhbHlpInph4/jgajjgYTjgYbjgoLjga7jga/jgIHlvoDjgIXjgavjgZfjgaYNCuaEj+WRs+OBjOOBguOCi+OBruOBi+OBquOBhOOBruOBi+OCj+OBi+OCieOBquOBhOOCguOBruOBmOOCg+OBquOBhOOBp+OBmeOBi+OAgg0KDQotIOS/guaVsOOBruaOqOWumuWApOOBjDDjgavov5HjgYTlhbHlpInph4/jgafjgYLjgaPjgabjgoLjgIHjgbTjgaPjgZ/jgoow44Gj44Gm44GT44Go44GvDQogIOOBquOBhOOBp+OBmeOCiOOBre+8nyDjgZ3jga7nnJ/lgKTjga8w44Gn44Gv44Gq44GE44GL44KC44GX44KM44Gq44GE44CCDQogIOOBneOCjOOCkuaKleWFpeOBmeOCi+OBk+OBqOOBq+OBr+Wun+OBr+OCj+OBmuOBi+OBquaEj+WRs+OBjOOBguOCi+OBruOBi+OCguOBl+OCjOOBquOBhOOAgg0KICDjgZ3jgYbogIPjgYjjgovjgajjgIHjgYTjgaPjgZHjgpPmhI/lkbPjgYzjgarjgZXjgZ3jgYbjgarlhbHlpInph4/jgafjgYLjgaPjgabjgoLjgIENCiAg5Y+W44KK6Zmk44GP44Gu44Gr44Gv44Gq44GL44Gq44GL5YuH5rCX44GM44GE44KL44CCDQotIOOBhOOBo+OBveOBhuOBp+OAgeOCguOBl+aEj+WRs+OBruOBquOBhOWFseWkiemHj+OCkuWFpeOCjOOBpuOBl+OBvuOBo+OBn+OCieOAgeeEoemnhOOBquODkeODqeODoeODvOOCv+OCkuaOqOa4rOOBmeOCi+e+veebruOBq+OBquOCiuOAgQ0KICDjgZ3jga7jgZvjgYTjgaflnLDln5/nibnmgKfjga7mjqjlrprlgKTjga7liIbmlaPjga/lpKfjgY3jgY/jgarjgovjgYvjgoLjgZfjgozjgarjgYTjgIINCiAg44Gd44GG6ICD44GI44KL44Go44CB44KE44Gv44KK5L+C5pWw44Gu5o6o5a6a5YCk44GMMOOBq+i/keOBhOWFseWkiemHj+OBr+OAgQ0KICDli4fmsJfjgpLjgoLjgaPjgablj5bjgorpmaTjgY/jgbnjgY3jgarjga7jgYvjgoLjgZfjgozjgarjgYTjgILjgYbjg7zjgoDjgIHmgqnjgoAuLi4gDQoNCuOBqOOBhOOBhuOCj+OBkeOBp+OAgeaEj+WRs+OBruOBquOBhOWFseWkiemHj+OCkuOBhuOBo+OBi+OCiuaKleWFpeOBl+OBn+OBqOOBjeOBruW8iuWus+OBqOOBhOOBhuOBruOBr+OBqeOCk+OBquOCguOBruOBquOBruOBi+OAgQ0K44Gd44KM44Gv5o6o5a6a6YeP44Gr44KI44Gj44Gm6YGV44GG44Gu44GL44CB44Gy44Go44Gk6Kq/44G544Gm44G/44Gf44GE44KC44Gu44Gg44Go5oCd44Gj44Gf44KP44GR44Gn44GZ44CCDQoNCuWcsOWfn+aVsOOBrzEw44Go44GX44CB44OW44Ot44OD44Kv44Gu5pWw44KSMuOBi+OCiTXjgb7jgafli5XjgYvjgZfjgarjgYzjgonjgIENCjUwMOWbnue5sOOCiui/lOOBmeOAgg0KbmxtZeODkeODg+OCseODvOOCuOOBqHJzdGFu44OR44OD44Kx44O844K444Gv55yB55Wl44GX44Gf44CCDQoNCmBgYHtyIHJlc3VsdHM9ImhpZGUifQ0KDQojIHNldC5zZWVkKDEyMykNCiMgbE91dCA8LSBsYXBwbHkoDQojICAgYygyLCAzLCA0LCA1KSwNCiMgICBmdW5jdGlvbihuTnVtR3JvdXApew0KIyAgICAgY2F0KCJuTnVtR3JvdXAgPSAiLCBuTnVtR3JvdXAsICIuLi5cbiIpDQojICAgICBkZkRhdGEgICA8LSBiLnN1Yl9HZW5lcmF0ZU11bHRpRGF0YXNldDEuMSgNCiMgICAgICAgbk51bURhdGFzZXQgPSA1MDAsIG5OdW1BcmVhID0gMTAsIG5OdW1Hcm91cCA9IG5OdW1Hcm91cCwgZ1ZhclYgPSA1MA0KIyAgICAgKQ0KIyAgICAgZGZSZXN1bHQgPC0gYi5zdWJfRXN0aW1hdGVNdWx0aURhdGFzZXQxLjEoDQojICAgICAgICBkZkRhdGEsDQojICAgICAgICBhc01ldGhvZCA9IGMoInNhZVJFTUwiLCAiaGJzYWVSRU1MIiwgImhic2FlSEIiLCAiYmF5ZXNzYWUiKSAgICAgIA0KIyAgICAgKQ0KIyAgICAgZGZSZXN1bHQkbk51bUdyb3VwIDwtIG5OdW1Hcm91cA0KIyAgICAgY2F0KCJcbiIpDQojICAgICByZXR1cm4oZGZSZXN1bHQpDQojICAgfQ0KIyApDQojIGxPdXQgPC0gbGFwcGx5KA0KIyAgIGxPdXQsDQojICAgZnVuY3Rpb24oZGZJbil7DQojICAgICBkZkluJGZHcm91cCA8LSBhcy5pbnRlZ2VyKGRmSW4kZkdyb3VwKQ0KIyAgICAgcmV0dXJuKGRmSW4pDQojICAgfQ0KIyApDQojIGIuZGZTaW11bGF0aW9uMyA8LSBiaW5kX3Jvd3MobE91dCkgJT4lDQojICAgZmlsdGVyKG5TaXplID09IDEwKQ0KIyBzYXZlKGIuZGZTaW11bGF0aW9uMywgZmlsZT0iLi9iX2RmU2ltdWxhdGlvbjMuUkRhdGEiKQ0KDQpsb2FkKCIuL2JfZGZTaW11bGF0aW9uMy5SRGF0YSIpDQoNCmBgYA0K44GT44GT44Gn44KC44CBKirmqJnmnKzjgrXjgqTjgrrjgYwxMOOBp+OBguOCi+WcsOWfn+OBoOOBkeOBq+azqOebruOBmeOCiyoq44CCDQrlkITmnaHku7bjgavjgYrjgYTjgaY1MDDku7bjga7mjqjlrprntZDmnpzjgYzkvb/jgYjjgovjgIINCg0KIyMjIyAxKSDmjqjlrprlgKQNCg0K44OW44Ot44OD44Kv44Gu5pWwIHgg5o6o5a6a5pa55rOV5Yil44Gr44CB5o6o5a6a5YCk44Go5q2j6Kej44Go44Gu44Ga44KM44KS6ZuG6KiI44GX44Gm44G/44KI44GG44CCDQoNCmBgYHtyfQ0KDQpkZlBsb3QgPC0gYi5kZlNpbXVsYXRpb24zICU+JQ0KICBkcGx5cjo6c2VsZWN0KG5OdW1Hcm91cCwgZ1YsIHN0YXJ0c193aXRoKCJnRXN0XyIpKSAlPiUNCiAgZ2F0aGVyKHNWYXIsIGdFc3QsIHN0YXJ0c193aXRoKCJnRXN0XyIpKSAlPiUNCiAgc2VwYXJhdGUoc1ZhciwgYygic1ZhcjEiLCAic0VzdGltYXRvciIpKSAlPiUNCiAgZ3JvdXBfYnkoc0VzdGltYXRvciwgbk51bUdyb3VwKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG5GcmVxID0gbigpLA0KICAgIGdSTVNFID0gc3FydChtZWFuKChnRXN0IC0gZ1YpXjIpKQ0KICApICU+JQ0KICB1bmdyb3VwKCkgJT4lDQogIG11dGF0ZSgNCiAgICBmRXN0aW1hdG9yID0gYi5zdWJfRXN0aW1hdG9yQXNGYWN0b3IuMShzRXN0aW1hdG9yKSwNCiAgICBmTnVtR3JvdXAgID0gZmFjdG9yKG5OdW1Hcm91cCwgbGV2ZWxzPTI6NSkNCiAgKQ0KDQpnIDwtIGdncGxvdCgNCiAgZGF0YT1kZlBsb3QsIA0KICBhZXMoeCA9IGZOdW1Hcm91cCwgeT1nUk1TRSwgZ3JvdXA9ZkVzdGltYXRvciwgY29sb3I9ZkVzdGltYXRvcikNCikNCmcgPC0gZyArIGdlb21fcGF0aChzaXplPTEpDQpnIDwtIGcgKyBsYWJzKA0KICB4ID0gIk51bS4gQmxvY2tzIiwgDQogIHkgPSAib2JzZXJ2ZWQgUk1TRSIsIA0KICBjb2xvciA9ICJFc3RpbWF0b3IiDQopDQpnIDwtIGcgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYi5zdWJfRXN0aW1hdG9yUGFsZXR0ZS4xKGRmUGxvdCRmRXN0aW1hdG9yKSkNCmcgPC0gZyArIHRoZW1lX2J3KCkNCnByaW50KGcpDQoNCmBgYA0K44OW44Ot44OD44Kv44Gu5pWw44GM5bCR44Gq44GE44CB44Gk44G+44KK5YWx5aSJ6YeP44GM5bCR44Gq44GE44G744GG44GM44CBDQrmjqjlrprlgKTjga/nnJ/lgKTjgavov5HjgaXjgY/jgILjgYjjgaPjgIHjgZPjgpPjgarjgavpgZXjgYbjga4uLi4gDQoNCiMjIyMgMikgTVNF44Gu5o6o5a6a5YCkDQoNCuODluODreODg+OCr+OBruaVsCB4IOaOqOWumuaWueazleWIpeOBq+OAgU1TReOBruaOqOWumuOBjOmBjuWwj+ODu+mBjuWkp+OBoOOBo+OBn+eoi+W6puOBq+OBpOOBhOOBpuiqv+OBueOBpuOBv+OCi+OAgg0KYGBge3J9DQoNCmRmUGxvdCA8LSBiLmRmU2ltdWxhdGlvbjMgJT4lDQogIGRwbHlyOjpzZWxlY3Qobk51bUdyb3VwLCBnViwgc3RhcnRzX3dpdGgoImdFc3RfIiksIHN0YXJ0c193aXRoKCJnTVNFXyIpKSAlPiUNCiAgZ2F0aGVyKHNWYXIsIGdWYWx1ZSwgYyhzdGFydHNfd2l0aCgiZ0VzdF8iKSwgc3RhcnRzX3dpdGgoImdNU0VfIikpKSAlPiUNCiAgc2VwYXJhdGUoc1ZhciwgYygic1ZhciIsICJzRXN0aW1hdG9yIikpICU+JQ0KICBzcHJlYWQoc1ZhciwgZ1ZhbHVlKSAlPiUNCiAgbXV0YXRlKA0KICAgIGdUcnVlU0UgPSAoZ0VzdCAtIGdWKV4yLCANCiAgICBnRGlmZiAgID0gZ01TRSAtIGdUcnVlU0UgDQogICkgJT4lIA0KICBncm91cF9ieShzRXN0aW1hdG9yLCBuTnVtR3JvdXApICU+JQ0KICBzdW1tYXJpemUoDQogICAgZ01lYW5EaWZmID0gbWVhbihnRGlmZikNCiAgKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBtdXRhdGUoDQogICAgZkVzdGltYXRvciA9IGIuc3ViX0VzdGltYXRvckFzRmFjdG9yLjEoc0VzdGltYXRvciksDQogICAgZk51bUdyb3VwICA9IGZhY3RvcihuTnVtR3JvdXAsIGxldmVscz0yOjUpDQogICkgDQoNCmcgPC0gZ2dwbG90KGRhdGE9ZGZQbG90LCBhZXMoeCA9IGZOdW1Hcm91cCwgeT1nTWVhbkRpZmYsIGdyb3VwPWZFc3RpbWF0b3IsIGNvbG9yPWZFc3RpbWF0b3IpKQ0KZyA8LSBnICsgZ2VvbV9wYXRoKHNpemU9MSkNCmcgPC0gZyArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApDQpnIDwtIGcgKyBsYWJzKA0KICB4ICAgICA9ICJOdW0uIEJsb2NrcyIsIA0KICB5ICAgICA9ICJtZWFuICgoRXN0aW1hdGVkIE1TRSkgLSAoQWN0dWFsIFNxLkVycikpIiwgDQogIGNvbG9yID0gIkVzdGltYXRvciINCikNCmcgPC0gZyArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBiLnN1Yl9Fc3RpbWF0b3JQYWxldHRlLjEoZGZQbG90JGZFc3RpbWF0b3IpKQ0KZyA8LSBnICsgdGhlbWVfYncoKQ0KcHJpbnQoZykNCg0KYGBgDQoNCuODluODreODg+OCr+aVsDXjga7jgajjgY3jgavjgaHjgofjgaPjgajpq5jjgY/jgarjgaPjgabjgYTjgovnkIbnlLHjgYzjgojjgY/jgo/jgYvjgpPjgarjgYTjgpPjgaDjgZHjganjgIENCuODluODreODg+OCr+aVsOOCkjLjgYvjgokz44Gr5aKX44KE44GZ44Go44CBTVNF44GM6YGO5bCP6KmV5L6h44GV44KM44Gm44GE44KL44GT44Go44GM44KP44GL44KL44CCDQrnhKHpp4TjgarlhbHlpInph4/jga/jgIFNU0Xjga7pgY7lsI/oqZXkvqHjgavjgoLjgaTjgarjgYzjgovjgojjgYbjgaAuLi4NCg0KIyMjMy4zLjUg5Zyw5Z+f5pWwIHZzLiDoqIjnrpfmmYLplpMgDQoNCuacgOW+jOOBq+OAgeWcsOWfn+aVsOOBqOioiOeul+OBq+OBi+OBi+OCi+aZgumWk+OBqOOBrumWoumAo+OBq+OBpOOBhOOBpuiqv+OBueOBpuOBv+OCi+OAgg0KDQoxMDDlnLDln58sIDEsMDAw5Zyw5Z+fLCAxMCwwMDDlnLDln58sIDEwMCwwMDDlnLDln5/jga416YCa44KK44Gr44Gk44GE44Gm44CBDQo15Zue44Ga44Gk44Gf44KB44GX44Gm44G/44Gf44CCDQoNCuOBk+OBk+OBp+OBr+OAgeS7peS4i+OBruaOqOWumuaWueazleOCkuippuOBmeOAgg0KDQotICoqc2FlKFJFTUwpKio6IHNhZeODkeODg+OCseODvOOCuCwgRUJMVVDmjqjlrprph48sICRcc2lnbWFfdl4yJOOCklJFTUzmjqjlrprjgIINCi0gKipzYWUoUkVNTCxub01TRSkqKjogc2Fl44OR44OD44Kx44O844K4LCBFQkxVUOaOqOWumumHjywgJFxzaWdtYV92XjIk44KSUkVNTOaOqOWumiwgDQogICAgICAgICAgICAgICAgICAgTVNF44KS566X5Ye644GX44Gq44GE44CCDQotICoqaGJzYWUoUkVNTCkqKjogaGJzYWXjg5Hjg4PjgrHjg7zjgrgsIEVCTFVQ5o6o5a6a6YePLCAkXHNpZ21hX3ZeMiTjgpJSRU1M5o6o5a6a44CCDQotICoqaGJzYWUoSEIpKio6ICAgaGJzYWXjg5Hjg4PjgrHjg7zjgrgsIEhC5o6o5a6a6YePLCDmlbDlgKTnqY3liIbjgavjgojjgovjgIINCi0gKipCYXllc1NBRSoqOiAgQmF5ZXNTQUXjg5Hjg4PjgrHjg7zjgrgsIEhC5o6o5a6a6YePLCBNQ01D44Gr44KI44KL44CCDQogICAgICAgICAgICAgICAgIG1jbWPjga7jg4njg63jg7zmlbDjga8xMDAwMOOAgg0KLSAqKm5sbWUqKjogbmxtZeODkeODg+OCseODvOOCuCwgRUJMVVDmjqjlrprph48sICRcc2lnbWFfdl4yJOOCkk1M5o6o5a6a44CCDQoNCuOBquOBiuOAgQ0KDQotIHJzdGFu44Gv5rOV5aSW44Gr5pmC6ZaT44GM44GL44GL44KL44GT44Go44GM44KP44GL44Gj44Gm44GE44KL44Gu44Gn44CB55yB55Wl44GX44Gf44CCDQotIDEwLDAwMOWcsOWfn+S7peS4iuOBruWgtOWQiOOBr+OAgXNhZeODkeODg+OCseODvOOCuOOBr+ecgeeVpeOBl+OBn+OAguOBmeOBlOOBj+aZgumWk+OBjOOBi+OBi+OCi+OBn+OCgeOAgg0KICDjgYTjgaHjgakxMCwwMDDlnLDln5/jgafoqabjgZfjgZ/jgonjgIFNU0XjgpLnrpflh7rjgZfjgabjgoLjgZfjgarjgY/jgabjgoIxODAw56eS44GP44KJ44GE44GL44GL44Gj44Gf44CCDQotIDEwMCwwMDDlnLDln5/jga7loLTlkIjjga/jgIFCYXllc1NBReODkeODg+OCseODvOOCuOOBr+ecgeeVpeOBl+OBn+OAgg0KICDkvZXluqbjgYvoqabjgZfjgZ/jgajjgZPjgo3jgIHjgZ3jga7jgZ/jgbPjgavjg6Hjg6Ljg6rjgYzotrPjgorjgarjgYTjgajjgYTjgYbjgqjjg6njg7zjgYzlh7rjgZ/jgYvjgonjgIINCi0gMTAwLDAwMOWcsOWfn+OBruWgtOWQiOOAgWhic2Fl44OR44OD44Kx44O844K444Gv44Ko44Op44O844Gr44Gq44KL44GT44Go44GM5aSa44GE44CCDQogIOS4i+OBruWun+mok+OBruWgtOWQiOOBrzXlm57kuK015Zue44Ko44Op44O844Go44Gq44Gj44Gf44CCDQoNCmBgYHtyfSANCg0KIyBzZXQuc2VlZCgxMjM0NSkNCiMgbE91dCA8LSBsYXBwbHkoDQojICAgYygxMDAsMTAwMCwxMDAwMCwxMDAwMDApLA0KIyAgIGZ1bmN0aW9uKG5OdW1BcmVhKXsNCiMgICAgIGNhdCgibk51bUFyZWEgPSAiLCBuTnVtQXJlYSwgIi4uLlxuIikNCiMgDQojICAgICBjYXQoImdlbmVyYXRlIGRhdGEgLi4uXG4iKQ0KIyAgICAgZGZEYXRhICAgPC0gYi5zdWJfR2VuZXJhdGVNdWx0aURhdGFzZXQxLjEoDQojICAgICAgIG5OdW1EYXRhc2V0ID0gNSwgbk51bUFyZWEgPSBuTnVtQXJlYSwgbk51bUdyb3VwID0gNEwsIGdWYXJWID0gNTANCiMgICAgICkNCiMgDQojICAgICBhc01ldGhvZCA8LSBjKA0KIyAgICAgICAic2FlUkVNTCIsICJzYWVSRU1MTk9NU0UiLCAiaGJzYWVSRU1MIiwgImhic2FlSEIiLCAiYmF5ZXNzYWUiLCAibmxtZSINCiMgICAgICkNCiMgICAgICMjIHNhZSB0YWtlcyB0b28gbG9uZyB3aXRoIG5OdW1BcmVhID49IDEwMDAwDQojICAgICBpZiAobk51bUFyZWEgPj0gMTAwMDApew0KIyAgICAgICAgYXNNZXRob2QgPC0gYXNNZXRob2RbIShhc01ldGhvZCAlaW4lIGMoInNhZVJFTUwiLCAic2FlUkVNTE5PTVNFIikpXQ0KIyAgICAgfQ0KIyAgICAgIyMgQmF5ZXNTQUUgcmFpc2VzIG91dC1vZi1tZW1vcnkgZXJyb3Igd2l0aCBuTnVtQXJlYSA+PSAxMDAwMDANCiMgICAgIGlmIChuTnVtQXJlYSA+PSAxMDAwMDApew0KIyAgICAgICAgYXNNZXRob2QgPC0gYXNNZXRob2RbYXNNZXRob2QgIT0gImJheWVzc2FlIl0NCiMgICAgIH0NCiMgDQojICAgICBkZlJlc3VsdCA8LSBiLnN1Yl9Fc3RpbWF0ZU11bHRpRGF0YXNldDEuMSgNCiMgICAgICAgZGZEYXRhLCBhc01ldGhvZCA9IGFzTWV0aG9kLCBiVmVyYm9zZSA9IFRSVUUNCiMgICAgICkgJT4lDQojICAgICAgIGZpbHRlcihuQXJlYSA9PSAxKSAlPiUNCiMgICAgICAgbXV0YXRlKG5OdW1BcmVhID0gbk51bUFyZWEpDQojICAgICBjYXQoIlxuIikNCiMgICAgIHJldHVybihkZlJlc3VsdCkNCiMgICB9DQojICkNCiMgYi5kZlNpbXVsYXRpb240IDwtIGJpbmRfcm93cyhsT3V0KQ0KIyBzYXZlKGIuZGZTaW11bGF0aW9uNCwgZmlsZT0iLi9iX2RmU2ltdWxhdGlvbjQuUkRhdGEiKQ0KbG9hZChmaWxlPSIuL2JfZGZTaW11bGF0aW9uNC5SRGF0YSIpDQogDQpgYGANCg0KDQrkuIDlm57jgYLjgZ/jgorjga7oqIjnrpfmmYLplpPjga/kuIvlm7PjgajjgarjgaPjgZ/jgIINCg0KYGBge3J9DQoNCmRmUGxvdDEgPC0gYi5kZlNpbXVsYXRpb240ICU+JQ0KICBkcGx5cjo6c2VsZWN0KG5OdW1BcmVhLCBuRGF0YXNldCwgc3RhcnRzX3dpdGgoImdUaW1lXyIpLCBzdGFydHNfd2l0aCgiYlN0YXR1c18iKSkgJT4lDQogIGdhdGhlcihzVmFyLCBnVmFsdWUsIGMoc3RhcnRzX3dpdGgoImdUaW1lXyIpLCBzdGFydHNfd2l0aCgiYlN0YXR1c18iKSkpICU+JQ0KICBzZXBhcmF0ZShzVmFyLCBjKCJzVmFyMSIsICJzRXN0aW1hdG9yIikpICU+JQ0KICBzcHJlYWQoc1ZhcjEsIGdWYWx1ZSkgJT4lDQogIGZpbHRlcihiU3RhdHVzID09IDEpICU+JQ0KICBtdXRhdGUoDQogICAgZkVzdGltYXRvciA9IGIuc3ViX0VzdGltYXRvckFzRmFjdG9yLjEoc0VzdGltYXRvciksDQogICAgZk51bUFyZWEgPSBmYWN0b3IoDQogICAgICBuTnVtQXJlYSwNCiAgICAgIGxldmVscyA9IGMoMTAwLDEwMDAsMTAwMDAsMTAwMDAwKSwNCiAgICAgIGxhYmVscyA9IGMoIjEwMCIsIjEwMDAiLCIxMDAwMCIsIjEwMDAwMCIpDQogICAgKQ0KICApDQoNCmRmUGxvdDIgPC0gZGZQbG90MSAlPiUNCiAgZ3JvdXBfYnkoZk51bUFyZWEsIGZOdW1BcmVhLCBmRXN0aW1hdG9yKSAlPiUNCiAgc3VtbWFyaXplKGdUaW1lID0gbWVhbihnVGltZSkpICU+JQ0KICB1bmdyb3VwKCkgDQoNCmcgPC0gZ2dwbG90KGRhdGE9ZGZQbG90MiwgYWVzKHggPSBmTnVtQXJlYSwgeT1nVGltZSwgZmlsbD1mRXN0aW1hdG9yKSkNCmcgPC0gZyArIGdlb21fY29sKCkNCmcgPC0gZyArIGdlb21fcG9pbnQoZGF0YT1kZlBsb3QxLCBhZXMoeCA9IGZOdW1BcmVhLCB5ID0gZ1RpbWUpLCBzaXplPTEsIGFscGhhPTEvMTApDQpnIDwtIGcgKyBsYWJzKHkgPSAiTWVhbiB0aW1lIChzZWMpIiwgeCA9ICJOdW0uQXJlYSIsIGZpbGw9IkVzdGltYXRvciIpDQpnIDwtIGcgKyBzY2FsZV9maWxsX21hbnVhbChndWlkZT1GQUxTRSwgdmFsdWVzID0gYi5zdWJfRXN0aW1hdG9yUGFsZXR0ZS4xKGRmUGxvdDEkZkVzdGltYXRvcikpDQpnIDwtIGcgKyBmYWNldF9ncmlkKH4gZkVzdGltYXRvcikNCmcgPC0gZyArIHRoZW1lX2J3KCkNCmcgPC0gZyArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gLTkwLCBoanVzdCA9IDAsIHZqdXN0ID0gMC4zKSkgDQpwcmludChnKQ0KDQpgYGANCg0KTUNNQ+OBp+aOqOWumuOBl+OBpuOBhOOCi0JheWVzU0FF44OR44OD44Kx44O844K444GM6YGF44GP44Gq44KL44Gu44GvDQrjgo/jgYvjgovjgpPjgaDjgZHjganjgIHkuI3mgJ3orbDjgarjga7jga9zYWXjg5Hjg4PjgrHjg7zjgrjjgafjgYLjgovjgIINCk1TReOCkueul+WHuuOBl+OBpuOCguOBl+OBquOBj+OBpuOCguOAgQ0K5Zyw5Z+f5pWw44GM44GC44KL56iL5bqm5aSn44GN44GP44Gq44KL44Go5oCl5r+A44Gr5pmC6ZaT44KS6aOf44GG44KI44GG44Gr44Gq44KL44CCDQoNCuWcsOWfn+aVsOOBjDEw5LiH44KS6LaF44GI44KL44KI44GG44Gq44Kx44O844K544Gn44Gv44CBaGJzYWXjg5Hjg4PjgrHjg7zjgrjjgadFQkxVUOaOqOWumuOBmeOCi+OBi+OAgQ0KTVNF44Gv5Ye644Gb44Gq44GE44GR44GpbmxtZeODkeODg+OCseODvOOCuOOBrmxtZSgp44KS5L2/44GG44Gu44GM6YCf44Gd44GG44Gg44CCDQpsbWUoKeOBruaOqOWumueyvuW6puOBjOaCquOBi+OBo+OBnygzLjMuNCnjgZPjgajjgpLogIPjgYjjgovjgajjgIENCmhic2Fl44OR44OD44Kx44O844K444Gr44KI44KLRUJMVVDmjqjlrprjgYzmnIDlloTmiYvjgafjgYLjgo3jgYbjgIINCg0K44GT44GT44Gg44GR44Gu6Kmx44CB44GT44Gu44K344Of44Ol44Os44O844K344On44Oz44GM5LuK5Zue44Gu5pyA5aSn44Gu55m66KaL44Gn44GC44KK44G+44GX44Gf44CCDQrjgZPjgozjgb7jgadzYWXjg5Hjg4PjgrHjg7zjgrjjgaDjgZHjgafmgqrmiKboi6bpl5jjgZfjgabjgYTjgZ/jga7jga/jgarjgpPjgaDjgaPjgZ/jga7jgYsuLi4NCg0KIyMjIDMuMy42IOOBvuOBqOOCgQ0KDQrjgZPjga7jgrfjg5/jg6Xjg6zjg7zjgrfjg6fjg7Pjgafjgo/jgYvjgaPjgZ/jgZPjgajjgpLjgb7jgajjgoHjgabjgYrjgY/jgIINCg0KLSDmqJnmnKzjgrXjgqTjgrrjgYzlsI/jgZXjgYTmmYLjgIEqKuWcsOWfn+eJueaAp+OBruaOqOWumuWApOOBr+OAgUhC5o6o5a6a44CBRUJMVVDmjqjlrposIOaomeacrOW5s+Wdh+OBrumghuOBq+ecn+WApOOBq+i/keOBhCoq44CCDQogIOOBn+OBoOOBl+OAgeWcsOWfn+aVsOOBjOWkmuOBhOOBqOOBjeOBr+OAgUhC5o6o5a6a44CBRUJMVVDmjqjlrprjgYzmqJnmnKzlubPlnYfjgpLlvJXjgY3pm6LjgZfjgIHjgojjgormnInliKnjgIENCiAg44GL44Gk5ZCM56iL5bqm44Gr5pyJ5Yip44Gr44Gq44KL44CCDQogIOOBquOBiuOAgeaomeacrOOCteOCpOOCuuOBjOWkp+OBjeOBkeOCjOOBsOOAgeOBhOOBmuOCjOOCguecn+WApOOBq+i/keOBj+OBquOCi+OAgg0KLSDmqJnmnKzjgrXjgqTjgrrjgYzlsI/jgZXjgY/lnLDln5/mlbDjgYzlsI/jgZXjgYTjgajjgY3jgIENCiAgKirlnLDln5/nibnmgKfjga7mjqjlrprlgKTjga5NU0Xjga7mjqjlrprjga/jgIFFQkxVUOaOqOWumuOBq+OBiuOBhOOBpumBjuWwj+OBq+OBquOCiyoq44CCDQogIOeJueOBq+OAgWhic2Fl44OR44OD44Kx44O844K444GuRUJMVVDmjqjlrprjgafpgY7lsI/jgavjgarjgovjgIINCi0g5oSP5ZGz44Gu44Gq44GE5YWx5aSJ6YeP44Gv5Y+W44KK6Zmk44GE44Gf44G744GG44GM44KI44GE44CCDQotICoq5Zyw5Z+f5pWw44GM44GZ44GU44GP5aSa44GE44Go44GN44Gv44CBaGJzYWXjg5Hjg4PjgrHjg7zjgrjjga5FQkxVUOaOqOWumuOCkuS9v+OBhuOBqOOCiOOBhCoq44CCIA0KDQpgYGB7ciwgcmVzdWx0cz0iaGlkZSJ9DQpybShsaXN0PWdyZXAoIl5iXFwuIiwgbHMoKSwgdmFsdWU9VCkpDQpgYGANCg0KIyA0LiDlnLDln5/jg6zjg5njg6vnqbrplpPjg6Ljg4fjg6sNCg0KIyMgNC4xIOepuumWk0ZheS1IZXJyaW9044Oi44OH44Or44Go44GvDQo8IS0tIGNodW5r44KS6LaF44GI44KL44Kq44OW44K444Kn44Kv44OI44GvZS7jgYvjgonlp4vjgoHjgosgLS0+DQoNCijjgZPjga7poIXjga9STeacrDQuNC4056+ALCA4LjTnr4Djgavln7rjgaXjgY/jgIIpDQoNCuOBiuOBleOCieOBhOOBmeOCi+OBqOOAgUZheS1IZXJyaW9044Oi44OH44Or44Gv5Lul5LiL44Gu6YCa44KK44Gn44GC44Gj44Gf44CCDQokJCANCiAgXGhhdHtcdGhldGF9X2kgPSBcbWF0aGJme3p9XlRfaSBcbWF0aGJme1xiZXRhfSArIHZfaSArIGVfaSwgXCBcIA0KICB2X2kgXHNpbSAoMCwgXHNpZ21hXjJfdiksIFwgXCAgDQogIGVfaSBcc2ltICgwLCBccHNpX2kpDQokJA0K44Go44GT44KN44Gn44CB5LiK44GuJHZfaSTjga7lvI/jga/jgZPjgYbmm7jjgY3mj5vjgYjjgovjgZPjgajjgYzjgafjgY3jgovjgIINCiRcbWF0aGJme3Z9ID0gKHZfMSwgXGxkb3RzLCB2X20pXlQk44Go44GX44Gm44CBDQokJA0KICBcbWF0aGJme3Z9IFxzaW0gKDAsIFxtYXRoYmZ7XEdhbW1hfSksIFwgXCAgDQogIFxtYXRoYmZ7XEdhbW1hfSA9IFxzaWdtYV92XjIgXG1hdGhiZntJfQ0KJCQNCg0KJFxtYXRoYmZ7XEdhbW1hfSTjga8kbSBcdGltZXMgbSTjga7ooYzliJfjgafjgIEkaSTooYwkaiTliJfnm67jga7opoHntKDjgYzjgIENCuWcsOWfnyRpJOOBqCRqJOOBruWFseWIhuaVo+OCkuihqOOBmeOAgkZheS1IZXJyaW9044Oi44OH44Or44GuDQrloLTlkIjjga/jgIHjgZnjgbnjgabjga7lr77op5LmiJDliIbjgaskXHNpZ21hX3ZeMiQNCuOBjOWFpeOBo+OBpuOBiuOCiuOAgeOBmeOBueOBpuOBrumdnuWvvuinkuaIkOWIhuOBqyQwJOOBjOOBr+OBhOOCiyjlnLDln5/lirnmnpwkdl9pJOOBr+WcsOWfn+mWk+OBpw0K54us56uL44Gg44Go6ICD44GI44Gm44GE44KL44GL44KJKeOAgg0KDQrjgZPjga7jgojjgYbjgavjgIFGYXktSGVycmlvdOODouODh+ODq+OBp+OBr+OAgQ0K5Zyw5Z+f5Yq55p6cJHZfaSTjga/lnLDln5/plpPjgafni6znq4vjgaDjgajogIPjgYjjgabjgYTjgZ/jgIINCuOBp+OCguWun+mam+OBq+OBr+OAgQ0K5Zyw5Z+f44Gu6ZaT44Gr44Gv6Zqj5o6l6Zai5L+C44GM44GC44KK44CB6Zqj44KK5ZCI44GG5Zyw5Z+f44Gu44GC44GE44Gg44Gn44Gv5Zyw5Z+f5Yq55p6c44GM5Ly844Gm44GE44KLDQrjgZPjgajjgYzlpJrjgYTjgILjgZPjgYbjgZfjgZ8qKuepuumWk+ebuOmWoioq44KS6ICD5oWu44GZ44KM44Gw44CBDQrlnLDln5/nibnmgKfjgpLjgoLjgaPjgajmraPnorrjgavmjqjmuKzjgafjgY3jgovjgYvjgoLjgZfjgozjgarjgYTjgIINCg0K44Gd44GT44Gn44CBJFxtYXRoYmZ7XEdhbW1hfSTjga7pnZ7lr77op5LmiJDliIbjgYww44Gn44Gq44GE44Go6ICD44GI44KL44CCDQrlnLDln5/lirnmnpwkXG1hdGhiZnt2fSTjgYzjgIHlnLDln5/plpPjga7nqbrplpPnmoTjgarpmqPmjqXplqLkv4Ljgajjganjga7jgojjgYbjgavplqLpgKPjgZfjgabjgYTjgovjgYvjgpINCuODouODh+ODq+WMluOBl+OAgeOBk+OBruODouODh+ODq+OBq+WfuuOBpeOBhOOBpuOAgSRcbWF0aGJme1xHYW1tYX0k44GM44Gp44GG44GE44GG5b2i5byP44Gr44Gq44Gj44Gm44GE44KLDQrjgYvjgpLopo/lrprjgZnjgovjgILjgZPjgozjgYwqKuepuumWk0ZheS1IZXJyaW9044Oi44OH44OrKirjgafjgYLjgovjgIINCg0K5o6o5a6a44Gu5pa55rOV44Gr44Gv44CBRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgajlkIzmp5jjgIFFQkxVUOaOqOWumiwgSELmjqjlrprjgarjganjgYzjgYLjgovjgIINCg0K44Gn44Gv44CB5YWx5YiG5pWj6KGM5YiXJFxtYXRoYmZ7XEdhbW1hfSTjgpLjganjga7jgojjgYbjgavopo/lrprjgZnjgovjgYvjgIINCuS7o+ihqOeahOOBquOCouODl+ODreODvOODgeOBjDLjgaTjgYLjgovjgIINCg0KIyMjIDQuMS4xICoqU0FSICjlkIzmmYLoh6rlt7Hlm57luLApIOODouODh+ODqyoqDQoNCuOBhOOBjeOBquOCiiRcbWF0aGJme3Z9JOOBruWQjOaZguWIhuW4g+OCkuODouODh+ODq+WMluOBmeOCi+OCouODl+ODreODvOODgeOAgg0KDQrmrKHjga7jgojjgYbjgavogIPjgYjjgovjgIINCiQkDQogIFxtYXRoYmZ7dn0gPSBccGhpIFxtYXRoYmZ7V30gXG1hdGhiZnt2fSArIFxtYXRoYmZ7dX0sIFwgXCANCiAgXG1hdGhiZnt1fSBcc2ltIE4oXG1hdGhiZnswfSwgXHNpZ21hX3VeMiBcbWF0aGJme0l9KQ0KJCQgDQrjgaTjgb7jgorjgZPjgYbjgYTjgYbjgZPjgajjgaDjgILjgqrjg6rjgrjjg4rjg6vjga5GYXktSGVycmlvdOODouODh+ODq+OBp+OBr+OAgQ0K5Zyw5Z+fJGkk44Gu5Zyw5Z+f5Yq55p6cJHYk44Gv44CB5bmz5Z2HMCwg5YiG5pWjJFxzaWdtYV92XjIk44Gu44Gq44KT44KJ44GL44Gu5YiG5biD44Gr5b6T44GGDQrjg6njg7Pjg4Djg6DjgarlirnmnpzjgaDjgajmg7PlrprjgZfjgabjgYTjgZ/jgIINCuOBhOOBo+OBveOBhuOBk+OBruODouODh+ODq+OBp+OBr+OAgeWcsOWfnyRpJOOBruWcsOWfn+WKueaenCR2X2kk44Gv5qyh44Gu44G144Gf44Gk44Gu6KaB57Sg44GuDQrlkozjgaDjgajmg7PlrprjgZnjgovjgIINCg0KLSDjgZ3jga7lnLDln5/oh6rkvZPjga7jg6njg7Pjg4Djg6DjgarlirnmnpzjgILlubPlnYcwLCDliIbmlaMkXHNpZ21hX3ZeMiTjga7mraPopo/liIbluIPjgavlvpPjgYbjgIINCi0g5LuW44Gu5Zyw5Z+f44GL44KJ5Y+X44GR44KL5Yq55p6c44Gu5ZCI6KiI44CC5Zyw5Z+fJGok44GL44KJ44Gv5Yq55p6cJFxwaGkgd197aWp9IHZfaiTjgpLlj5fjgZHjgovjgIINCg0K44GT44GuJHdfe2lqfSTjgpLooYzliJfjga7lvaLjgavkuKbjgbnjgZ/jga7jgYwkXG1hdGhiZntXfSTjgafjgYLjgovjgILjgZPjga4kXG1hdGhiZntXfSTjga8NCuWcsOWfn+mWk+OBrumao+aOpemWouS/guOCkuihqOePvuOBl+OBpuOBhOOCi+ihjOWIl+OBp+OAgeWIhuaekOiAheOBjOaMh+WumuOBmeOCi+OAgg0KDQrku6XkuIrjga7mg7Plrprjga/jgZPjgYbjgYTjgYbpoqjjgavmm7jjgY3mj5vjgYjjgovjgZPjgajjgYzjgafjgY3jgovjgIINCiQkDQogIFxtYXRoYmZ7dn0gPSAoXG1hdGhiZntJfS1ccGhpIFxtYXRoYmZ7V30pXnstMX0gXG1hdGhiZnt1fSwgXCBcIA0KICBcbWF0aGJme3V9IFxzaW0gTihcbWF0aGJmezB9LCBcc2lnbWFfdV4yIFxtYXRoYmZ7SX0pDQokJA0K44GT44GT44GL44KJ44CBJFxtYXRoYmZ7dn0k44Gu5YiG5biD44GvDQokJA0KICBcbWF0aGJme3Z9IFxzaW0gTigwLCBcbWF0aGJme1xHYW1tYX0pLCBcIFwgDQogIFxtYXRoYmZ7XEdhbW1hfSA9IFxzaWdtYV92XjJbKFxtYXRoYmZ7SX0tXHBoaSBcbWF0aGJme1d9KShcbWF0aGJme0l9LVxwaGkgXG1hdGhiZntXfSleVF1eey0xfQ0KJCQNCuOBqOOBquOCi+OAguepuumWk+ebuOmWouOCkuiAg+aFruOBl+OBquOBhEZheS1IZXJyaW9044Oi44OH44Or44Gn44GvJFxzaWdtYV92XjIk44KS5o6o5a6a44GZ44KL5b+F6KaB44GM44GC44Gj44Gf44GM44CBDQrjgZPjgZPjgafjga/jgZ3jga7jgYvjgo/jgorjgaskXHNpZ21hX3VeMiTjgagkXHBoaSTjgpLmjqjlrprjgZnjgovlv4XopoHjgYzjgYLjgovjgIINCg0K44GT44GT44Gn6Y2144Gr44Gq44KL44Gu44Gv44CB6Zqj5o6l6KGM5YiXJFxtYXRoYmZ7V30k44Gu5a6a576p44Gn44GC44KL44CCDQrpgJrluLjjga/mrKHjga7jgojjgYbjgavlrprnvqnjgZnjgovjgIINCg0KMS4g44G+44Ga44CB5Zyw5Z+fJGkkLCAkaiTjgYzpmqPmjqXjgZfjgabjgYTjgovjgajjgY3jgaskd197aWp9PTEk44CBDQogICDjgZ3jgYbjgafjgarjgYTjgajjgY3jgaskd197aWp9PTAk44Go44GZ44KL44CCDQoyLiDjgZPjgYbjgZfjgabjgafjgY3jgZ8kXG1hdGhiZntXfSTjgpLlkITooYzjgavjgaTjgYTjgablkIjoqIjjgZfjgIENCiAgIOOBneOBruihjOOBruWApOOCkuWQiOioiOOBp+WJsuOCiyjjgaTjgb7jgorjgIHlkITooYzjga7lkIjoqIjjgYwx44Gr44Gq44KL44KI44GG44Gr44GZ44KLKeOAgg0KDQrjgZPjga7jgajjgY3jgIEkXHBoaSBcaW4gKDAsMSkk44Go44Gq44KL44CC44GT44Gu44Go44GN44GuJFxwaGkk44KSDQoqKuepuumWk+iHquW3seebuOmWouODkeODqeODoeODvOOCvyoq44Go44GE44GG44CCDQoNCiMjIyA0LjEuMiAqKkNBUiAo5p2h5Lu25LuY44GN6Ieq5bex5Zue5biwKSDjg6Ljg4fjg6sqKg0KDQokXG1hdGhiZnt2fSTjga7lkIzmmYLliIbluIPjgafjga/jgarjgY/jgIENCuS7luOBruOCqOODquOCoiRce3ZfbDogbCBcbmVxIGlcfSTjga7kuIvjgafjga7jgIEkdl9pJOOBruadoeS7tuOBpOOBjeWIhuW4g+OCkg0K44Oi44OH44Or5YyW44GZ44KL44CB44Go44GE44GG44Ki44OX44Ot44O844OB44Gn44GC44KL44CCDQoNCuWQhOWcsOWfnyRpJOOBr+aXouefpeOBruWumuaVsCRiX2kk44KS5oyB44Gj44Gm44GE44KL44Go44GZ44KLKOWFuOWei+eahOOBq+OBrzHjgajjgZnjgosp44CCDQrmrKHjga7jgojjgYbjgavogIPjgYjjgovjgILlnLDln58kaSTjga7jgIzov5HmjqXjgI3lnLDln5/jga7pm4blkIjjgpIkQV9pJOOBqOOBl+OBpg0KJCQNCiAgYl9pIHZfaSB8IFx7dl9sOiBsIFxuZXEgaVx9IA0KICBcc2ltIE4gXGxlZnQoIFxyaG8gXHN1bV97bCBcaW4gQV9sfSBxX3tpbH0gYl9sIHZfbCwgYl9pXjIgXHNpZ21hX3ZeMiBccmlnaHQpDQokJA0K44GT44GT44GnJFx7cV97aWx9XH0k44Gv5pei55+l44Gu5a6a5pWw44Gn44CBJHFfe2lsfWJfbF4yID0gcV97bGl9IGJfaV4yJOOCkua6gOOBn+OBmeOAgg0K5YW45Z6L55qE44Gr44Gv44CBJGwgXGluIEFfaSTjga7jgajjgY0kcV97aWx9ID0gcV97bGl9ID0gMSTjgajjgZnjgovjgIINCg0K44Gk44G+44KK44GT44GG44GE44GG44GT44Go44Gg44CC44Kq44Oq44K444OK44Or44GuRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgafjga/jgIENCuWcsOWfnyRpJOOBruWcsOWfn+WKueaenCR2X2kk44Gv44CB5bmz5Z2HMCwg5YiG5pWjJFxzaWdtYV92XjIk44Gu44Gq44KT44KJ44GL44Gu5YiG5biD44Gr5b6T44GGDQrjg6njg7Pjg4Djg6DjgarlirnmnpzjgaDjgajmg7PlrprjgZfjgabjgYTjgZ/jgIINCuOBhOOBo+OBveOBhuOBk+OBruODouODh+ODq+OBp+OBr+OAgeOBquOBnOOBoOOBi+efpeOCieOBquOBhOOBjOOAgSR2X2kk44Gv6Zqj5o6l5Zyw5Z+f44GuDQrlnLDln5/lirnmnpzjgYzlm7rlrprjgZXjgozjgZ/jgajjgY3jgavjgIHmrKHjga7jgojjgYbjgavmraPopo/liIbluIPjgZnjgovjgIHjgajmg7PlrprjgZnjgovjgIINCg0KLSDjgZ3jga7lubPlnYfjga/jgIHpmqPmjqXjgZnjgovku5bjga7lnLDln58kbCTjga7lnLDln5/lirnmnpwkYl9sIHZfbCTjgpLjgIHph43jgb8kcV97aWx9JOOCkg0KICDjgaTjgZHjgabotrPjgZfkuIrjgZIsICRccmhvJOWAjeOBl+OBn+WApOOBp+OBguOCi+OAgg0KLSDjgZ3jga7liIbmlaPjga8kYl9pXjIgXHNpZ21hX3ZeMiTjgafjgYLjgovjgIINCg0K44GT44GT44GL44KJ44CBJFxtYXRoYmZ7XEdhbW1hfSTjgpLopo/lrprjgZnjgovmrKHlvI/jgYzlvpfjgonjgozjgovjgIINCiRiXzFeMiwgXGxkb3RzLCBiX21eMiTjgpLmjIHjgaTlr77op5LooYzliJfjgpIkXG1hdGhiZntCfSTjgajjgZfjgIENCuOBmeOBueOBpuOBriRxX3tpbH0k44KS5oyB44GkJG0gXHRpbWVzIG0k6KGM5YiXKOi/keaOpeOBmOOCg+OBquOBhOOBqOOBk+OCjeOBqOWvvuinkuOBrzDjgavjgZnjgosp44KSDQokXG1hdGhiZntRfSTjgajjgZfjgaYNCiQkDQogIFxtYXRoYmZ7Qn1eezEvMn0gXG1hdGhiZnt2fSBcc2ltIE5fbShcbWF0aGJmezB9LCBcbWF0aGJme1xHYW1tYX0pDQokJA0KJCQNCiAgXEdhbW1hID0gXHNpZ21hXjJfdihcbWF0aGJme0l9IC0gXHJobyBcbWF0aGJme1F9KV57LTF9IFxtYXRoYmZ7Qn0NCiQkDQrnqbrplpPnm7jplqLjgpLogIPmha7jgZfjgarjgYRGYXktSGVycmlvdOODouODh+ODq+OBp+OBryRcc2lnbWFfdl4yJOOCkuaOqOWumuOBmeOCi+W/heimgeOBjOOBguOBo+OBn+OBjOOAgQ0K44GT44GT44Gn44GvJFxzaWdtYV92XjIk44GoJFxyaG8k44KS5o6o5a6a44GZ44KL5b+F6KaB44GM44GC44KL44CCDQoNCiMjIyA0LjEuMyBTQVLjg6Ljg4fjg6vjgahDQVLjg6Ljg4fjg6vjga7mr5TovIMNCg0K5YmN6aCF44G+44Gn44Gn44Gv44CB56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgavjgYrjgYTjgabnqbrplpPnm7jplqLjgpLopo/lrprjgZnjgovjgZ/jgoHjga4y44Gk44GuDQrjg6Ljg4fjg6soU0FS44Oi44OH44Or44GoQ0FS44Oi44OH44OrKeOCkuWPluOCiuS4iuOBkuOBn+OAgg0KDQrjgarjgpPjgaDjgYvpm6PjgZfjgYTjga7jgafjgIHjgZnjgZTjgY/ljZjntJTjgarlhbfkvZPkvovjgafogIPjgYjjgabjgb/jgojjgYbjgIINCg0K44GE44G+5Zyw5Z+f44GMNOOBpOOBguOCiuOAgeWcsOWfnzHjgagyLCAy44GoMywgM+OBqDTjgYzpmqPmjqXjgZfjgabjgYTjgovjgajjgZnjgovjgIINClNBUuODouODh+ODq+OBqENBUuODouODh+ODq+OBp+OBr+OAgeepuumWk+ebuOmWouOBr+OBqeOBruOCiOOBhuOBq+imj+WumuOBleOCjOOCi+OBi+OAgg0KDQrjgb7jgZoqKumao+aOpeihjOWIlyoq44Gr44Gk44GE44Gm44CCDQpTQVLjg6Ljg4fjg6vjga7loLTlkIjjgIHpmqPmjqXooYzliJckXG1hdGhiZntXfSTjga/mrKHjga7jgojjgYbjgavlrprnvqnjgZXjgozjgovjgZPjgajjgYzlpJrjgYTjgIINCuWQhOihjOOBruWSjOOBjDHjgavjgarjgaPjgabjgYTjgovngrnjgavms6jmhI/jgIINCg0KYGBge3J9DQogIGUubWdQcm94X3Vuc3RkIDwtIG1hdHJpeCgwLCBucm93PTQsIG5jb2w9NCkNCiAgZS5tZ1Byb3hfdW5zdGRbMSwyXSA8LSAxDQogIGUubWdQcm94X3Vuc3RkWzIsM10gPC0gMQ0KICBlLm1nUHJveF91bnN0ZFszLDRdIDwtIDENCiAgZS5tZ1Byb3hfdW5zdGRbMiwxXSA8LSAxDQogIGUubWdQcm94X3Vuc3RkWzMsMl0gPC0gMQ0KICBlLm1nUHJveF91bnN0ZFs0LDNdIDwtIDENCiAgZS5tZ1Byb3hfc3RkIDwtIHN3ZWVwKGUubWdQcm94X3Vuc3RkLCAxLCByb3dTdW1zKGUubWdQcm94X3Vuc3RkKSwgIi8iKQ0KICBwcmludChlLm1nUHJveF9zdGQpDQoNCmBgYA0KDQrjgYTjgaPjgb3jgYZDQVLjg6Ljg4fjg6vjga7loLTlkIjjgIHpmqPmjqXooYzliJckXG1hdGhiZntRfSTjga/mrKHjga7jgojjgYbjgavlrprnvqnjgZXjgozjgovjgZPjgajjgYzlpJrjgYTjgIINCumao+aOpeOBmeOCi+WcsOWfn+mWk+OBruOBvzEsIOOBu+OBi+OCkjDjgajjgZfjgaYNCg0KYGBge3J9DQogIHByaW50KGUubWdQcm94X3Vuc3RkKQ0KYGBgDQoNCuasoeOBqyoq5Zyw5Z+f5Yq55p6c44Gu5a6a576pKirjgavjgaTjgYTjgabjgIINCg0KU0FS44Oi44OH44Or44Gu5aC05ZCI44Gv5LiL5byP44Gu44KI44GG44Gr5a6a576p44GV44KM44KL44CCDQoNCiQkIHZfMSA9IFxwaGkgdl8yICsgdV8xLCBcIFwgdV8xIFxzaW0gTigwLCBcc2lnbWFfdV4yKSAkJA0KJCQgdl8yID0gXHBoaSAoMC41IHZfMSArIDAuNXZfMykgKyB1XzIsIFwgXCB1XzIgXHNpbSBOKDAsIFxzaWdtYV91XjIpICQkDQokJCB2XzMgPSBccGhpICgwLjV2XzIgKyAwLjV2XzQpICsgdV8zLCBcIFwgdV8zIFxzaW0gTigwLCBcc2lnbWFfdV4yKSAkJA0KJCQgdl80ID0gXHBoaSB2XzMgKyB1XzQsIFwgXCB1XzQgXHNpbSBOKDAsIFxzaWdtYV91XjIpICQkDQoNCuOBk+OBk+OBi+OCieOAgSRcbWF0aGJme3Z9JOOBruWIhuW4g+OBrw0KJCQNCiAgXG1hdGhiZnt2fSBcc2ltIE4oMCwgXG1hdGhiZntcR2FtbWF9KSwgXCBcIA0KICBcbWF0aGJme1xHYW1tYX0gPSBcc2lnbWFfdl4yWyhcbWF0aGJme0l9LVxwaGkgXG1hdGhiZntXfSkoXG1hdGhiZntJfS1ccGhpIFxtYXRoYmZ7V30pXlRdXnstMX0NCiQkDQoNCuOBqOOBquOCi+OAgg0KDQrjgYTjgaPjgb3jgYZDQVLjg6Ljg4fjg6vjga7loLTlkIjjga/jgIHjgZnjgbnjgabjga4kYl9pJOOCkjHjgajjgZnjgozjgbANCg0KJCQgdl8xIHwgdl8yICBcc2ltIE4oXHJobyB2XzIsIFxzaWdtYV92XjIpICQkDQokJCB2XzIgfCBceyB2XzEsIHZfM1x9IFxzaW0gTihccmhvICh2XzErdl8zKSwgXHNpZ21hX3ZeMikgJCQNCiQkIHZfMyB8IFx7IHZfMiwgdl80XH0gXHNpbSBOKFxyaG8gKHZfMit2XzQpLCBcc2lnbWFfdl4yKSAkJA0KJCQgdl80IHwgdl8zIFxzaW0gTihccmhvIHZfMywgXHNpZ21hX3ZeMikgJCQNCg0K44GT44KM44KS5ZCM5pmC5YiG5biD44Gr5pu444GN55u044GZ44GoDQokJA0KICBcbWF0aGJme3Z9IFxzaW0gTihcbWF0aGJmezB9LCBcbWF0aGJme1xHYW1tYX0pLCBcIFwgDQogIFxtYXRoYmZ7XEdhbW1hfSA9IFxzaWdtYV4yX3YoXG1hdGhiZntJfSAtIFxyaG8gXG1hdGhiZntRfSleey0xfQ0KJCQNCg0KDQrjgajjgarjgovjgIINCg0K44Gn44Gv44CBKirlhbHliIbmlaPooYzliJcqKiRcbWF0aGJme1xHYW1tYX0k44KS44GP44KJ44G544Gm44G/44KI44GG44CCDQpTQVLjg6Ljg4fjg6vjga7loLTlkIjjgIEkXHNpZ21hX3VeMj0xLCBccGhpPTAuNSTjga7jgajjgY0NCmBgYHtyfQ0KICBtYlVuaXQgPC0gZGlhZyhyZXAoMSw0KSkNCiAgZS5tZ0NvdjIgPC0gc29sdmUoIChtYlVuaXQgLSAwLjUgKiBlLm1nUHJveF9zdGQpICUqJSB0KG1iVW5pdCAtIDAuNSAqIGUubWdQcm94X3N0ZCkgKQ0KICBwcmludChlLm1nQ292MikNCg0KYGBgDQoNCkNBUuODouODh+ODq+OBruWgtOWQiOOAgSRcc2lnbWFfdl4yPTEsIFxyaG89MC41JOOBruOBqOOBjQ0KDQpgYGB7cn0NCg0KICBlLm1nQ292MSA8LSBzb2x2ZShkaWFnKHJlcCgxLDQpKSAtIDAuNSAqIGUubWdQcm94X3Vuc3RkKQ0KICBwcmludChlLm1nQ292MSkNCg0KYGBgDQoNCuOBqOOBquOCi+OAgg0KDQoqKuebuOmWouihjOWIlyoq44Gr55u044GX44Gm44G/44KL44GoLCBTQVLjg6Ljg4fjg6vjga8NCg0KYGBge3J9DQoNCiAgbWdDb3IgPC0gc3dlZXAoZS5tZ0NvdjIsIDEsIHNxcnQoZGlhZyhlLm1nQ292MikpLCAiLyIpDQogIG1nQ29yIDwtIHN3ZWVwKG1nQ29yLCAyLCBzcXJ0KGRpYWcoZS5tZ0NvdjIpKSwgIi8iKQ0KICBwcmludChtZ0NvcikNCg0KYGBgDQoNCkNBUuODouODh+ODq+OBrw0KDQpgYGB7cn0NCg0KICBtZ0NvciA8LSBzd2VlcChlLm1nQ292MSwgMSwgc3FydChkaWFnKGUubWdDb3YxKSksICIvIikNCiAgbWdDb3IgPC0gc3dlZXAobWdDb3IsIDIsIHNxcnQoZGlhZyhlLm1nQ292MSkpLCAiLyIpDQogIHByaW50KG1nQ29yKQ0KDQpgYGANCg0K44GT44Gu44KI44GG44Gr44CBU0FS44Oi44OH44Or44GoQ0FS44Oi44OH44Or44Gv44CB5a6a5byP5YyW44Gv5YWo44GP55Ww44Gq44KL44KC44Gu44Gu44CBDQrnqbrplpPnm7jplqLjgavjgaTjgYTjgabjga7opo/lrprjga/jgIHntZDlsYDjgZ3jgozjgbvjganlpInjgo/jgonjgarjgYTjgIINCuOBhOOBmuOCjOOBruODouODh+ODq+OBp+OCguOAgQ0KDQotIOWcsOWfn+WKueaenOOBruWIhuaVo+OBr+OAgemao+aOpeWcsOWfn+OBjOWkmuOBhOWcsOWfn+OBp+mrmOOBhOOBqOimj+WumuOBleOCjOOCi+OAguS4iuOBrg0KICDkvovjgafjga/jgIHlnLDln58xLDIsMyw044Gu5YiG5pWj44Gv44CBU0FS44Oi44OH44Or44Gn44GvMS40NCwgMi4wOSwgMi4wOSwgMS40NOOBp+OBguOCiuOAgQ0KICBDQVLjg6Ljg4fjg6vjgafjga8xLjYwLCAyLjQwLCAyLjQwLCAxLjYw44Gn44GC44KL44CCDQotIOODouODh+ODq+OBruOBhuOBiOOBp+OBr+mao+aOpeWcsOWfn+OBqOOBrumWouS/guOBl+OBi+WumuW8j+WMluOBleOCjOOBpuOBhOOBquOBhOOBq+OCgumWouOCj+OCieOBmuOAgQ0KICDntZDlsYDjga/jgIHpm6LjgozjgZ/lnLDln5/jga7plpPjgavjgoLlvLHjgYTnm7jplqLjgYzjgYLjgovjgajopo/lrprjgZXjgozjgovjgIINCiAg44Gf44Go44GI44Gw5LiK44Gu5L6L44Gn44CB5Zyw5Z+fMeOBqDTjga7plpPjga7nm7jplqLjga/jgIENCiAgU0FS44Oi44OH44Or44GvMC4xMSwgQ0FS44Oi44OH44Or44Gn44GvMC4yNeOBp+OBguOCi+OAgg0KDQpgYGB7ciwgcmVzdWx0cz0iaGlkZSJ9DQpybShsaXN0PWdyZXAoIl5lXFwuIiwgbHMoKSwgdmFsdWU9VCkpDQpgYGANCg0KIyMgNC4yIOWun+e/kjogZ3JhcGVzDQo8IS0tIGNodW5r44KS6LaF44GI44KL44Kq44OW44K444Kn44Kv44OI44GvYy7jgYvjgonlp4vjgoHjgosgLS0+DQoNCuOBi+OCk+OBn+OCk+OBquODh+ODvOOCv+OBq+OBpOOBhOOBpuOAgeepuumWk0ZheS1IZXJyaW9044Oi44OH44Or44KS5o6o5a6a44GX44Gm44G/44KI44GG44CCDQoNCiMjIyA0LjIuMSDjg4fjg7zjgr8NCg0Kc2Fl44OR44OD44Kx44O844K444Gr44Gk44GE44Gm44GE44KL44K144Oz44OX44Or44OH44O844K/IGdyYXBlcyDjgpLkvb/jgYbjgIINCuOCpOOCv+ODquOCouOBr+ODiOOCueOCq+ODvOODiuWcsOaWueOBrjIyNOiHquayu+S9k+OBq+OBpOOBhOOBpuOBruODh+ODvOOCv+OBp+OAgeS7peS4i+OBruWkieaVsOOCkg0K5oyB44Gj44Gm44GE44KL44CCDQoNCi0gZ3JhcGVoZWN0OiDjg5bjg4njgqbnlZHjga7lubPlnYfpnaLnqY0o44OY44Kv44K/44O844OrKeOBruebtOaOpeaOqOWumuWApOOAgg0KLSBhcmVhOiDjg5bjg4njgqbnlZHjga7nt4/pnaLnqY0o44OY44Kv44K/44O844OrKeOAgg0KLSB3b3JrZGF5czog44CMMjAwMOW5tOOBruW5s+Wdh+WKtOWDjeaXpeaVsChhdmVyYWdlIG51bWJlciBvZiB3b3JraW5nIGRheXMp44CN44CCDQogICAgICAgICAg44GI44GI44GI77yfIOiogOOBo+OBpuOCi+aEj+WRs+OBjOOCj+OBi+OCk+OBquOBhOOCk+OBoOOBkeOBqS4uLg0KICAgICAgICAgIOacgOWwj+OBpzIyLjE1LCDmnIDlpKfjgac0OTcuNjjjgafjgYLjgovjgIINCi0gdmFyOiDmqJnmnKzmir3lh7rliIbmlaPjga7nm7TmjqXmjqjlrprlgKTjgIINCg0KYGBge3J9DQoNCiMjIyBjLmRmR3JhcGVzDQpkYXRhKGdyYXBlcykNCmMuZGZHcmFwZXMgPC0gZ3JhcGVzICU+JQ0KICBtdXRhdGUoDQogICAgbkFyZWFJRCA9IHNlcV9hbG9uZyhncmFwZWhlY3QpLA0KICAgIFNFID0gc3FydCh2YXIpDQogICkNCnJtKGdyYXBlcykNCg0KIyMjIGMubWdQcm94X3N0ZDogcm93LXN0YW5kYXJkaXplZCBuZWlnaGJvciBtYXRyaXgNCmRhdGEoZ3JhcGVzcHJveCkNCmMubWdQcm94X3N0ZCA8LSBhcy5tYXRyaXgoZ3JhcGVzcHJveCkNCnJtKGdyYXBlc3Byb3gpDQpjb2xuYW1lcyhjLm1nUHJveF9zdGQpIDwtIGFzLmNoYXJhY3RlcigxOm5jb2woYy5tZ1Byb3hfc3RkKSkNCnJvd25hbWVzKGMubWdQcm94X3N0ZCkgPC0gYXMuY2hhcmFjdGVyKDE6bnJvdyhjLm1nUHJveF9zdGQpKQ0KIyMgcHJpbnQoYy5tZ1Byb3hfc3RkKQ0KDQojIyMgYy5tYlByb3hfdW5zdGQ6IHVuc3RhbmRhcmRpemVkIG5laWdoYm9yIG1hdHJpeA0KYy5tYlByb3hfdW5zdGQgPC0gYy5tZ1Byb3hfc3RkDQpjLm1iUHJveF91bnN0ZFtjLm1iUHJveF91bnN0ZCA+IDBdIDwtIDENCiMjIHByaW50KGMubWJQcm94X3Vuc3RkKQ0KDQpzdW1tYXJ5KGMuZGZHcmFwZXMgJT4lIGRwbHlyOjpzZWxlY3QoLWMobkFyZWFJRCwgU0UpKSkNCmBgYA0KDQrjg4fjg7zjgr/jgpLmlaPluIPlm7PooYzliJfjgafoprPlr5/jgZfjgabjgb/jgojjgYbjgIINCuOBquOBiuOAgXZhcuOBr+OBv+OBq+OBj+OBhOOBruOBp+W5s+aWueagueOCkuOBqOOBo+OBpuaomea6luiqpOW3rihTRSnjgavjgZnjgovjgIINCg0KYGBge3J9DQpnZ3BhaXJzKA0KICBjLmRmR3JhcGVzICU+JSBkcGx5cjo6c2VsZWN0KGdyYXBlaGVjdCwgYXJlYSwgd29ya2RheXMsIFNFKSwgDQogIHByb2dyZXNzID0gRkFMU0UsIA0KICBhZXMoYWxwaGEgPSAxLzEwKQ0KKQ0KYGBgDQoNCuW5s+Wdh+mdouepjeOBruebtOaOpeaOqOWumumHj2dyYXBlaGVjdOOBr+OAgee3j+mdouepjWFyZWHjgajlvLHjgYTnm7jplqLjgYzjgYLjgorjgIENCuisjuOBruWcsOWfn+eJueaAp3dvcmtkYXlz44Go5q+U6LyD55qE5by344GE55u46Zai44GM44GC44KL44CCDQrjgb7jgZ9TReOBqOOCguato+OBruebuOmWouOBjOOBguOCiyjjgZ3jgozjga/jgZ3jgYbjgarjgovjgaDjgo3jgYbjgILluoPjgYTnlZHjgYzlpJrjgYToh6rmsrvkvZPjga4NCuOBu+OBhuOBjOOAgemdouepjeOBruOBsOOCieOBpOOBjeOCguWkp+OBjeOBj+OBquOCi+OBoOOCjeOBhuOBi+OCiSnjgIINCg0K44GT44Gu44OH44O844K/44Gr5LuY6ZqP44GX44Gm44CB5Zyw5Z+f6ZaT6Zqj5o6l6KGM5YiXZ3JhcGVzcHJveOOCguaPkOS+m+OBleOCjOOBpuOBhOOCi+OAgg0K5bem5LiK44GuOOihjDjliJfjgaDjgZHjgIHjgaHjgonjgaPjgajjgb/jgabjgb/jgovjgaguLi4NCg0KYGBge3J9DQpwcmludChjLm1nUHJveF9zdGRbMTo4LDE6OF0pDQpgYGANCg0K44GT44KT44Gq5oSf44GY44CC5ZCE6KGM44Gu5ZCI6KiI44GMMeOBq+OBquOBo+OBpuOBhOOCi+OAgg0KDQrpmqPmjqXooYzliJfjgpLnnLrjgoHjgabjgYTjgabjgoLlhajnhLbpnaLnmb3jgY/jgarjgYTjgILlnLDlm7PjgpLjgb/jgZ/jgYTjgpPjgaDjgZHjganjgIHjgYLjgYTjgavjgY8NCuaPkOS+m+OBleOCjOOBpuOBhOOBquOBhOOAguS7leaWueOBjOOBquOBhOOBruOBp+OAgeWcsOWfn+OCkuODjuODvOODieOAgemao+aOpeOCkuODquODs+OCr+OBq+OBl+OBnw0K44Kw44Op44OV44KS5o+P44GE44Gm44G/44Gf44CCDQoNCmBgYHtyfQ0KDQpzdWJfU2hvd0FyZWFHcmFwaDEuMSA8LSBmdW5jdGlvbigNCiAgbWdQcm94LCBhZ1NpemVWYXIsIGFnQ29sb3JWYXIsIHNQYWw9Ik9yUmQiDQopew0KICBnIDwtIGdyYXBoLmFkamFjZW5jeShtZ1Byb3gsIG1vZGU9InVuZGlyZWN0ZWQiKQ0KICBWKGcpJHNpemUgIDwtIGFnU2l6ZVZhcg0KICBWKGcpJGNvbG9yIDwtIHNtb290aFBhbGV0dGUoYWdDb2xvclZhciwgcGFsPXNQYWwpDQogIHNldC5zZWVkKDEyMikNCiAgcGFyKG1hcj1jKDAsMCwwLDApKQ0KICBwbG90KA0KICAgIGcsIA0KICAgIHZlcnRleC5sYWJlbC5jb2xvciAgPSAiYmxhY2siLCANCiAgICB2ZXJ0ZXgubGFiZWwuZmFtaWx5ID0gIm1vbm8iLCANCiAgICB2ZXJ0ZXgubGFiZWwuY2V4ICAgID0gMC41LCANCiAgICBtYXJnaW4gPSAtMC4xNQ0KICApDQp9DQoNCnN1Yl9TaG93QXJlYUdyYXBoMS4xKA0KICBjLm1iUHJveF91bnN0ZCwgYy5kZkdyYXBlcyRhcmVhLzEyMCwgYy5kZkdyYXBlcyRncmFwZWhlY3QNCikNCg0KYGBgDQrlhobjga7lpKfjgY3jgZXjga/jg5bjg4njgqbnlZHnt4/pnaLnqY3jgIENCuiJsuOBrua/g+OBleOBr+ODluODieOCpueVkeW5s+Wdh+mdouepjSjoibLjgYzmv4PjgYTlnLDln5/jga/lubPlnYfpnaLnqY3jgYzluoPjgYQp44CCDQrjgarjgYrjgIHkvY3nva7jga/jgr3jg5Xjg4jjgYzpganlvZPjgavmsbrjgoHjgabjgYrjgorjgIHjgYLjgb7jgormhI/lkbPjgYzjgarjgYTjgIINCg0K44Kw44Op44OV44Gu5bem5YG044Gr5a2k56uL44GX44Gf5Zyw5Z+f576k44GM44GC44KL44GR44Gp44CB44GT44KM44GvDQrls7bjgYvjgarjgavjgYvjgYvjgarjgYLjgIHjgajjgqTjgr/jg6rjgqLjga7lnLDlm7PjgpLoqr/jgbnjgabjgb/jgZ/jgIINCg0KPGlmcmFtZSBzcmM9Imh0dHBzOi8vd3d3Lmdvb2dsZS5jb20vbWFwcy9lbWJlZD9wYj0hMW0xNCExbTEyITFtMyExZDEwNDkzNjUuOTAwMzczMTkwMiEyZDExLjU1MDA3NzAyMTEzNzUzNiEzZDQzLjQwODU2MzIyMzQ4NDk1ITJtMyExZjAhMmYwITNmMCEzbTIhMWkxMDI0ITJpNzY4ITRmMTMuMSE1ZTAhM20yITFzamEhMnNqcCE0djE1MzAzODg4NjA2NzAiIHdpZHRoPSI2MDAiIGhlaWdodD0iNDUwIiBmcmFtZWJvcmRlcj0iMCIgc3R5bGU9ImJvcmRlcjowIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+DQoNCuOCsOODqeODleOBqOimi+avlOOBueOBpuOBv+OCi+OBqOOAgeOCsOODqeODleW3puWBtOOBruWtpOeri+OBl+OBn+WcsOWfn+e+pOOBr+OAgeODneODq+ODiOODu+ODleOCp+ODqeOCpOODreOBqOOBhOOBhg0K5bO244Gq44KT44GY44KD44Gq44GE44GL44Go5oCd44GG44GM44CB5LuW44Gu566H5omA44Gr44Gk44GE44Gm44Gv5YWo44GP5a++5b+c44GM44KP44GL44KJ44Gq44GE44CC44GG44O844KA44CB5q6L5b+144CCDQrjgafjgoLjgb7jgYLjgIENCuiJsuOBrua/g+OBhOWcsOWfn+OBjOmao+aOpeOBl+OBpuOBhOOCi+OBqOOBhOOBhuOBk+OBqOOBjOOCj+OBi+OBo+OBn+OBruOBp+OCiOOBl+OBqOOBl+OCiOOBhuOAgg0KDQrlnLDnkIbjgavjga/lhajjgY/nlo7jgY/jgIHmtbflpJbml4XooYzjgoLjgZfjgarjgYTjgaTjgb7jgonjgarjgYTnlLfjgarjga7jgafjgIHlhajnhLbopovlvZPjgYzjgaTjgYvjgarjgYTjgpPjgafjgZnjgZHjganjgIENCuODiOOCueOCq+ODvOODiuWcsOaWueOBqOOBhOOBhuOBruOBr+OAgeWMl+OBr+OBk+OBruWcsOWbs+OBruW3puS4iuOBruODqeODu+OCueODmuODhOOCo+OCouOBqOOBhOOBhuOBguOBn+OCiuOBi+OCieOAgQ0K5Y2X44Gv5Zyw5Zuz44Gu5LiL5YG044Gu44Kq44Or44OZ44OG44OD44Ot44Go44GE44GG44GC44Gf44KK44G+44Gn44CB44Kk44K/44Oq44Ki5Y2K5bO244Gu6KW/5YG044Gu5LiA5biv44KS5Y2g44KB44KLDQrlt57jgarjga7jgaDjgZ3jgYbjgaDjgIINCg0KW+OCpOOCv+ODquOCouaUv+W6nOims+WFieWxgF0oaHR0cDovL3Zpc2l0YWx5LmpwL3RyYXZlbC90b3NjYW5hKeanmOOBq+OCiOOCjOOBsOOAgQ0K44CM57O45p2J44GM6YCj44Gq44KL576O44GX44GE5LiY6Zm15Zyw5biv44Gv44CB5LiW55WM6YG655Sj44Gu44O044Kh44Or44O744OJ44Or44OB44Oj44KS44Gv44GY44KB44CBDQrkuJbnlYznmoTjgavmnInlkI3jgarlpKflpInnvo7jgZfjgYTjg4jjgrnjgqvjg7zjg4rjga7oh6rnhLbmma/oprPjgafjgIENCuihl+OAheOCkuenu+WLleOBmeOCi+mWk+OCguaXheihjOiAheOBruebruOCkualveOBl+OBvuOBm+OBpuOBj+OCjOOAjeOCi+OBruOBoOOBneOBhuOBp+OBguOCi+OAgg0K5bee6YO944Gv44OV44Kj44Os44Oz44OE44Kn44CC44GC44CB44Gd44KM55+l44Gj44Gm44KL77yB6aCI6LOA5pWm5a2Q44Gu5pys44Gr5Ye644Gm44GP44KL44KI44Gt77yBDQoNCjxpbWFnZSBzcmM9Ii4vbW9udGVwdWxjaWFuby0xNjM5NDUxXzY0MC5qcGciPg0KDQrlhpnnnJ/jgpLnnLrjgoHjgabjgYTjgZ/jgonjgIHkurrnlJ/jganjgZPjgafplpPpgZXjgYjjgZ/jgpPjgaDjgo3jgYbjgYvjgajjgIENCuOBoOOCk+OBoOOCk+i+m+OBj+OBquOBo+OBpuOBjeOBn+OBruOBp+OAgeipseOCkuOCguOBqOOBq+aIu+OBl+OBpi4uLg0KDQojIyMgNC4yLjIg56m66ZaT6Ieq5bex55u46Zai5oyH5qiZDQoNCuOBleOBjeOBu+OBqeOBruOCsOODqeODleOBq+OCiOOCjOOBsOOAgeODluODieOCpueVkeOBruW5s+Wdh+mdouepjeOBr+OAgeOBqeOBhuOChOOCiemao+aOpeOBl+OBpuOBhOOCiw0K5Zyw5Z+f6ZaT44Gn5Ly844Gm44GE44KL44KI44GG44Gn44GC44Gj44Gf44CCDQrjgZPjgYbjgYTjgYbmgKfos6rjgpIqKuepuumWk+iHquW3seebuOmWoioq44Go44GE44GG44CCDQoNCuepuumWk+iHquW3seebuOmWouOBruW8t+OBleOBr+OBqeOBruOBj+OCieOBhOOBoOOCjeOBhuOBi+OAgg0KUk3mnKzjga7lhoXlrrnjgYvjgonjga/pm6LjgozjgovjgYzjgIHjgYTjgY/jgaTjgYvmjIfmqJnjgpLmsYLjgoHjgabjgb/jgojjgYbjgIINCg0K56m66ZaT6Ieq5bex55u46Zai44Gu5oyH5qiZ44Gr44Gv5aSn44GN44GP5YiG44GR44GmMueorumhnuOBguOCi+OAgg0KDQrjgZ3jga4x44CB44Kw44Ot44O844OQ44Or44Gq5oyH5qiZ44CC44Gk44G+44KK44CB5YWo44Gm44Gu5Zyw5Z+f44KS6YCa44GY44Gf56m66ZaT6Ieq5bex55u46Zai44GuDQrmjIfmqJnjgILjgZ3jga7ku6PooajpgbjmiYvjgYzjgIFNb3JhbuOBrknntbHoqIjph4/jgafjgYLjgovjgIINCuWcsOWfnyRpJOOBruWApOOCkiR4X2kkLCDlnLDln58kaSTjgagkaiTjga7jgYLjgYTjgaDjga4NCumao+aOpemWouS/guOCkuihqOOBmemHjeOBv+OCkiR3X3tpan0k44Go44GX44Gm44CBDQokJA0KICBJID0gXGZyYWN7bX17XHN1bV9pIFxzdW1fayB3X3tpan19IA0KICAgICAgXGZyYWN7DQogICAgICAgIFxzdW1faSBcc3VtX2ogd197aWp9ICh4X2ktXGJhcnt4fSkoeF9qIC0gXGJhcnt4fSkNCiAgICAgIH17DQogICAgICAgIFxzdW1faSAoeF9pIC0gXGJhcnt4fSleMg0KICAgICAgfQ0KJCQNCuOBk+OBruaMh+aomeOBr+OAgeepuumWk+iHquW3seebuOmWouOBjOOBquOBhOOBqOOBjeOBqyQtMS8obS0xKSTjgavov5HjgaXjgY/jgIINCg0K6KiI566X44GX44Gm44G/44KI44GG44CCJHdfe2lqfSTjgpI0LjHjgafov7DjgbnjgZ/ph43jgb/jgajjgZnjgovjgajjgIENCg0KYGBge3J9DQptb3Jhbi50ZXN0KGMuZGZHcmFwZXMkZ3JhcGVoZWN0LCBtYXQybGlzdHcoYy5tZ1Byb3hfc3RkLCBzdHlsZT0iVyIpKQ0KYGBgDQpJPTAuMjPjgIHlvLHjgYTmraPjga7nqbrplpPoh6rlt7Hnm7jplqLjgYzjgYLjgovjgIINCg0K44Gd44GuMiwg44Ot44O844Kr44Or44Gq5oyH5qiZ44CC6Zqj5o6l5Zyw5Z+f44Go5Ly844Gm44GE44KL44Gu44Gv44Gp44Gu5Zyw5Z+f44GL44KS6Kq/44G544KLDQrjgZ/jgoHjgavkvb/jgYbjgILjgZ3jga7ku6PooajpgbjmiYvjga9Nb3JhbuOBruODreODvOOCq+ODq0nntbHoqIjph4/jgafjgIENCuOBk+OCjOOBr+OCsOODreODvOODkOODq+OBqiRJJOOCkuWQhOWcsOWfn+OBq+WIhuino+OBmeOCi+OAguOBpOOBvuOCiuOAgQ0K5ZCE5Zyw5Z+f44Gr44Gk44GE44Gm5YCk44GM5b6X44KJ44KM44CB44Gd44Gu5ZCI6KiI44Gv44Kw44Ot44O844OQ44Or44GqJEkk44Gr5LiA6Ie044GZ44KL44CCDQokJA0KICBJX2kgPSBcZnJhY3ttfXtcc3VtX2kgXHN1bV9rIHdfe2lqfX0gDQogICAgICBcZnJhY3sNCiAgICAgICAgKHhfaS1cYmFye3h9KVxzdW1faiB3X3tpan0gKHhfaiAtIFxiYXJ7eH0pDQogICAgICB9ew0KICAgICAgICBcc3VtX2kgKHhfaSAtIFxiYXJ7eH0pXjINCiAgICAgIH0NCiQkDQroqIjnrpfjgZfjgabjgb/jgojjgYbjgIINCg0KYGBge3J9DQptZ0xvY2FsTW9yYW4gPC0gbG9jYWxtb3JhbigNCiAgYy5kZkdyYXBlcyRncmFwZWhlY3QsIA0KICBtYXQybGlzdHcoYy5tZ1Byb3hfc3RkLCBzdHlsZT0iVyIpDQopDQpzdWJfU2hvd0FyZWFHcmFwaDEuMSgNCiAgYy5tYlByb3hfdW5zdGQsIGMuZGZHcmFwZXMkYXJlYS8xMjAsIG1nTG9jYWxNb3JhblssMV0sIHNQYWwgPSAiQmx1ZXMiDQopDQoNCmBgYA0K6Zqj5o6l5Zyw5Z+f44Go44Gu56m66ZaT55u46Zai44GM6auY44GE5Zyw5Z+f44KS5r+D44GE6Z2S44Gr44GX44Gm44G/44Gf44CC5Lit5aSu44Gr44CBDQrpnZLoibLjgYzmv4PjgYTlnLDln5/jgYzlm7rjgb7jgaPjgabjgYTjgovjgILjgZXjgaPjgY3jga7lm7PjgavmiLvjgaPjgabjgb/jgovjgajjgIENCuOBk+OCjOOCieOBr+ODluODieOCpueVkeW5s+Wdh+mdouepjeOBjOW6g+OBhOWcsOWfn+OBp+OBguOCi+OAgg0KDQojIyMgNC4yLjMgc2Fl44OR44OD44Kx44O844K444Gr44KI44KL5o6o5a6aDQoNCijmnKznr4Djga9STeacrDguMTHnr4Djga7lho3nj77jgafjgYLjgovjgIIpDQoNCuODluODieOCpueVkeW5s+Wdh+mdouepjeOCknNhZeODkeODg+OCseODvOOCuOOBp+aOqOWumuOBl+OBpuOBv+OCiOOBhuOAgg0KDQpzYWXjg5Hjg4PjgrHjg7zjgrjjgafjga/jgIFTQVLjg6Ljg4fjg6vjgavln7rjgaXjgY8NCuepuumWk0ZheS1IZXJyaW9044Oi44OH44Or44KS5o6o5a6a44Gn44GN44KL44CCDQrlnLDln5/nibnmgKfjga9FQkxVUOaOqOWumuOAgg0KJFxzaWdtYV91XjIk44GoJFxwaGkk44Gu5o6o5a6a6YeP44Gv44OH44OV44Kp44Or44OI44Gn44GvUkVNTOOBqOOBquOCi+OAgg0KDQpzYWXjg5Hjg4PjgrHjg7zjgrjjga/nqbrplpNGYXktSGVycmlvdOODouODh+ODq+OBrumWouaVsOOBqOOBl+OBpuasoeOBrjTjgaTjga7plqLmlbDjgpLmj5DkvpvjgZfjgabjgYTjgovjgIINCuOBhOOBmuOCjOOCguWcsOWfn+eJueaAp+OBruaOqOWumuOBr+WQjOOBmOOBp+OAgU1TReOBruaJseOBhOOBjOeVsOOBquOCi+OAgg0KDQotIGVibHVwU0ZIKCk6IOaOqOWumumHj+OBrk1TReOCkuaOqOWumuOBl+OBquOBhOOAgg0KLSBtc2VTRkgoKTog5o6o5a6a6YeP44GuTVNF44KS6Kej5p6Q55qE44Gr5o6o5a6a44GZ44KL44CCDQotIHBibXNlU0ZIKCk7IOaOqOWumumHj+OBrk1TReOCkuODkeODqeODoeODiOODquODg+OCr+ODu+ODluODvOODiOOCueODiOODqeODg+ODl+azleOBp+aOqOWumuOBmeOCi+OAgg0KLSBucGJtc2VTRkgoKTog5o6o5a6a6YeP44GuTVNF44KS44OO44Oz44OR44Op44Oh44OI44Oq44OD44Kv44O744OW44O844OI44K544OI44Op44OD44OX5rOV44Gn5o6o5a6a44GZ44KL44CCDQoNCuOBk+OBk+OBp+OBr21zZVNGSCgp44KS5L2/44GG44GT44Go44Gr44GZ44KL44CCDQoNCuOBvuOBmuOAgeWIh+eJh+mgheOCkuaKnOOBhOOBn+ODouODh+ODq+OCkuaOqOWumuOBmeOCi+OAgg0K44OW44OJ44Km55WR57eP6Z2i56mNYXJlYeOBqOODluODieOCpueVkeW5s+Wdh+mdouepjeOBruaVo+W4g+Wbs+OCkuOBv+OBpuOBv+OCi+OBqOOAgQ0K5Zue5biw55u057ea44Gv5Y6f54K544KS6YCa44KK44Gd44GG44Gg44GL44KJ44CB44Go44GE44GG55CG55Sx44Gn44GC44KN44GG44CCDQpSTeacrOOBruODouODh+ODq+OCguOBneOBhuOBquOBo+OBpuOBvuOBmeOBlyhwLjI2NiksIA0Kc2Fl44OR44OD44Kx44O844K444GubXNlU0ZIKCnjga7jg57jg4vjg6XjgqLjg6vjga7jgrPjg7zjg4nkvovjgafjgoLjgZ3jgYbjgarjgaPjgabjgb7jgZnjgIINCg0KYGBge3J9DQpvTW9kZWwgPC0gbXNlU0ZIKA0KICBmb3JtdWxhID0gZ3JhcGVoZWN0IH4gYXJlYSArIHdvcmtkYXlzIC0gMSAsIA0KICB2YXJkaXIgID0gdmFyLCANCiAgcHJveG1hdCA9IGMubWdQcm94X3N0ZCwgDQogIGRhdGEgICAgPSBjLmRmR3JhcGVzDQopDQpjYXQoDQogICJyZWZ2YXI6IiwgICAgICBvTW9kZWwkJ2VzdCckZml0JHJlZnZhciwgICAgICAgDQogICJcbnNwYXRpYWxjb3JyOiIsIG9Nb2RlbCQnZXN0JyRmaXQkc3BhdGlhbGNvcnIsICJcbiINCikNCmBgYA0KDQokXHNpZ21hX3VeMiTjga82OS43LCAkXHBoaSTjga8wLjYx44Go5o6o5a6a44GV44KM44Gf44CCDQouLi4g44GC44KM77yfIFJN5pyscC4yNjbjgajjgb7jgaPjgZ/jgY/lkIzjgZjjgrPjg7zjg4njgarjga7jgavjgIHlgKTjgYzjgYvjgarjgorjgaHjgYzjgYYNCihSTeacrOOBp+OBrzcxLjE4OSwgMC41ODMp44CC44Gq44Gc44Gg77yf77yf77yfDQoNCuOBk+OCjOOBr+engeOBruODkeOCveOCs+ODs+OBjOOBiuOBi+OBl+OBhOOCj+OBkeOBp+OBr+OBquOBj+OBpuOAgQ0KRkFP57Wx6KiI6YOo44Gu5YKY5LiL44Gr44GC44KL44KJ44GX44GN57WE57mU44Gr44KI44KLDQpb44OG44Kv44OL44Kr44Or44O744Os44Od44O844OIXShodHRwOi8vZ3NhcnMub3JnL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDE1LzA5L1RSLVNwYXRpYWwtRGlzYWdncmVnYXRpb24tYW5kLVNtYWxsLUFyZWEtRXN0aW1hdGlvbi0yMTA5MTUucGRmKQ0K44Gn44Gu6Kej6Kqs44Gn44KC44CB56eB44Gu5Ye65Yqb44Go5ZCM44GY5YCk44Gr44Gq44Gj44Gm44GE44KLKHAuNDEp44CC44GG44O844KALi4uDQoNCuOBqOOBi+OBquOCiuaAneOBhOaCqeOCk+OBoOOCk+OBoOOBkeOBqeOAgemAlOS4reOBp+awl+OBjOS7mOOBjeOBvuOBl+OBn+OAguWIh+eJh+mgheOCkuaKnOOBj+OBruOCkuOChOOCgeOBpuOBv+OCi+OBqA0KYGBge3J9DQojIyMgYy5vTW9kZWxfc2FlUkVNTA0KYy5vTW9kZWxfc2FlUkVNTCA8LSBtc2VTRkgoDQogIGZvcm11bGEgPSBncmFwZWhlY3QgfiBhcmVhICsgd29ya2RheXMgLCANCiAgdmFyZGlyICA9IHZhciwgDQogIHByb3htYXQgPSBjLm1nUHJveF9zdGQsIA0KICBkYXRhICAgID0gYy5kZkdyYXBlcw0KKQ0KY2F0KA0KICAicmVmdmFyOiIsICAgICAgYy5vTW9kZWxfc2FlUkVNTCQnZXN0JyRmaXQkcmVmdmFyLCAgICAgICANCiAgIlxuc3BhdGlhbGNvcnI6IiwgYy5vTW9kZWxfc2FlUkVNTCQnZXN0JyRmaXQkc3BhdGlhbGNvcnIsICJcbiINCikNCnByaW50KGMub01vZGVsX3NhZVJFTUwkJ2VzdCckZml0JGVzdGNvZWYpDQpgYGANCg0KJFxzaWdtYV91XjIk44GvNzEuMTg5LCAkXHBoaSTjga8wLjU4M+OAgg0KUk3mnKzjga7lh7rlipvjgajkuIDoh7TjgZfjgb7jgZfjgZ/jgILjgoTjgozjgoTjgozjgIINCg0K44GT44Gu44KI44GG44Gr44CBUk3mnKzjga/jgrPjg7zjg4nkvovjgajlh7rlipvjgYznn5vnm77jgZfjgabjgYTjgovjgo/jgZHjgaDjgIINCuOBp+OBr+OAgeOBqeOBo+OBoeOCkuaOoeeUqOOBmeOCi+OBueOBjeOBi+OAguOBk+OBk+OBp+OBr+WIh+eJh+mgheOCkuWFpeOCjOOCi+OBu+OBhuOCkuaOoeeUqOOBmeOCi+OAgg0KIOOAjOW5s+Wdh+mdouepjeOBr+e3j+mdouepjeOBqHdvcmtkYXlz44Gu57ea5b2i5ZKM44Gr44Gq44KL44CN44Go44GE44GG44Gu44GvDQrjgarjgpPjgaDjgYvlpInjgarjg6Ljg4fjg6vjgaDjgajmgJ3jgYbjga7jgafjgIINCg0K44GV44Gm44CB44Kw44Op44OV44Gu6Imy44KS44CB44GT44Gu44Oi44OH44Or44Gr44KI44KL5o6o5a6a5YCk44Gr5o+P44GN5aSJ44GI44KL44GoLi4uDQoNCmBgYHtyfQ0Kc3ViX1Nob3dBcmVhR3JhcGgxLjEoYy5tYlByb3hfdW5zdGQsIGMuZGZHcmFwZXMkYXJlYS8xMjAsIGMub01vZGVsX3NhZVJFTUwkJ2VzdCckZWJsdXApDQpgYGANCg0K6Imy44Gu5r+D44GV44GM44Gh44KH44Gj44Go5aSJ44KP44Gj44Gf44CC44Gf44Go44GI44Gw44CB5Lit5b+D44Gu6Imy44Gu5r+D44GE44OO44O844OJKOWcsOWfnzE3Mynjga7lt6bkuIrjgavjgYLjgovjgIENCuWcsOWfnzE4N+OBruiJsuOBjOOBoeOCh+OBo+OBqOiWhOOBj+OBquOBo+OBpuOBhOOCi+OAgg0KDQrjgZXjgabjgIHlnLDln5/nibnmgKfjga7mjqjlrprlgKTjga/jgIHnqbrplpPnm7jplqLjgpLogIPmha7jgZnjgovjgYvjganjgYbjgYvjgavjgojjgaPjgabjgoLlpInjgo/jgovjgZfjgIENCuOBqeOCk+OBquWFseWkiemHj+OCkuS9v+OBhuOBi+OBq+OCiOOBo+OBpuWkieOCj+OCi+OAguasoeOBrjXnqK7poZ7jgpLmr5Tjgbnjgabjgb/jgojjgYbjgIINCg0KLSAqKmRpcmVjdCoqOiDnm7TmjqXmjqjlrpoo44GK44Gd44KJ44GP44Gv5qiZ5pys5bmz5Z2HKeOAgg0KLSAqKm5vbmUqKjogICBGYXktSGVycmlvdOODouODh+ODq+OBq+OCiOOCi+aOqOWumihFQkxVUCksIOWFseWkiemHj+OBquOBl+OAgg0KLSAqKmFyZWEqKjogICBGYXktSGVycmlvdOODouODh+ODq+OBq+OCiOOCi+aOqOWumihFQkxVUCksIOWFseWkiemHj+OBr+e3j+mdouepjeOAgg0KLSAqKmFyZWErd29ya2RheXMqKjogICBGYXktSGVycmlvdOODouODh+ODq+OBq+OCiOOCi+aOqOWumihFQkxVUCksIOWFseWkiemHj+OBr+e3j+mdouepjeOBqHdvcmtkYXlz44CCDQotICoqYXJlYSt3b3JrZGF5cytzcGF0aWFsY29vcioqOg0KICDnqbrplpNGYXktSGVycmlvdOODouODh+ODq+OBq+OCiOOCi+aOqOWumihFQkxVUCksIOWFseWkiemHj+OBr+e3j+mdouepjeOBqHdvcmtkYXlz44CCDQoNCmBgYHtyfQ0KIyMjIGMub01vZGVsX3NhZVJFTUxfe25veCwgYXJlYSwgYXJlYXdvcmtkYXl9DQpjLm9Nb2RlbF9zYWVSRU1MX25veCA8LSBtc2VGSCgNCiAgZm9ybXVsYSA9IGdyYXBlaGVjdCB+IDEsIA0KICB2YXJkaXIgID0gdmFyLCANCiAgZGF0YSAgICA9IGMuZGZHcmFwZXMNCikNCmMub01vZGVsX3NhZVJFTUxfYXJlYSA8LSBtc2VGSCgNCiAgZm9ybXVsYSA9IGdyYXBlaGVjdCB+ICBhcmVhICwgDQogIHZhcmRpciAgPSB2YXIsIA0KICBkYXRhICAgID0gYy5kZkdyYXBlcw0KKQ0KYy5vTW9kZWxfc2FlUkVNTF9hcmVhd29ya2RheSA8LSBtc2VGSCgNCiAgZm9ybXVsYSA9IGdyYXBlaGVjdCB+ICBhcmVhICsgd29ya2RheXMsIA0KICB2YXJkaXIgID0gdmFyLCANCiAgZGF0YSAgICA9IGMuZGZHcmFwZXMNCikNCmBgYA0KDQrjg6Ljg4fjg6vjga7pganlkIjluqbjgpLoqr/jgbnjgabjgb/jgovjgaguLi4NCmBgYHtyfQ0KbE1vZGVsIDwtIGxpc3QoDQogIGMub01vZGVsX3NhZVJFTUxfbm94LCANCiAgYy5vTW9kZWxfc2FlUkVNTF9hcmVhLCANCiAgYy5vTW9kZWxfc2FlUkVNTF9hcmVhd29ya2RheSwgDQogIGMub01vZGVsX3NhZVJFTUwNCikNCmRmVGVtcCA8LSBkYXRhLmZyYW1lKA0KICBFc3RpbWF0b3IgPSBjKCJub25lIiwgImFyZWEiLCAiYXJlYSt3b3JrZGF5cyIsICJhcmVhK3dvcmtkYXlzK3NwYXRpYWxjb3JyIiksIA0KICBBSUMgICAgICAgPSBzYXBwbHkobE1vZGVsLCBmdW5jdGlvbihvTW9kZWwpIG9Nb2RlbCRlc3QkZml0JGdvb2RuZXNzWzJdKSwgDQogIEJJQyAgICAgICA9IHNhcHBseShsTW9kZWwsIGZ1bmN0aW9uKG9Nb2RlbCkgb01vZGVsJGVzdCRmaXQkZ29vZG5lc3NbM10pLCANCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQpwcmludChkZlRlbXApDQpgYGANCkFJQywgQklD44GE44Ga44KM44KC44CB56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgYzmnIDlsI/jgajjgarjgaPjgZ/jgIINCg0K5o6o5a6a57WQ5p6c44Gv5LiL5Zuz44Gu6YCa44KK44CCDQoNCmBgYHtyfQ0KYy5kZlJlc3VsdF9zYWVSRU1MIDwtIGMuZGZHcmFwZXMgJT4lDQogIG11dGF0ZSgNCiAgICBnRXN0XzEgPSBhcy52ZWN0b3IoYy5vTW9kZWxfc2FlUkVNTF9ub3gkZXN0JGVibHVwKSwNCiAgICBnRXN0XzIgPSBhcy52ZWN0b3IoYy5vTW9kZWxfc2FlUkVNTF9hcmVhJGVzdCRlYmx1cCksDQogICAgZ0VzdF8zID0gYXMudmVjdG9yKGMub01vZGVsX3NhZVJFTUxfYXJlYXdvcmtkYXkkZXN0JGVibHVwKSwNCiAgICBnRXN0XzQgPSBhcy52ZWN0b3IoYy5vTW9kZWxfc2FlUkVNTCRlc3QkZWJsdXApLA0KICAgIGdNU0VfMyA9IGMub01vZGVsX3NhZVJFTUxfYXJlYXdvcmtkYXkkbXNlLA0KICAgIGdNU0VfNCA9IGMub01vZGVsX3NhZVJFTUwkbXNlDQogICkgJT4lDQogIG11dGF0ZShuQXJlYSA9IHNlcV9hbG9uZyhncmFwZWhlY3QpKSANCg0KZGZQbG90IDwtIGMuZGZSZXN1bHRfc2FlUkVNTCAlPiUNCiAgYXJyYW5nZSgtdmFyKSAlPiUNCiAgdG9wX24oMzAsIHZhcikgJT4lICAjIGF0dGVudGlvbiEhISENCiAgbXV0YXRlKA0KICAgIGZBcmVhID0gZmFjdG9yKHNlcV9hbG9uZyhuQXJlYSksIGxhYmVscyA9IGFzLmNoYXJhY3RlcihuQXJlYSkpDQogICkgJT4lDQogIHJlbmFtZShnRXN0XzAgPSBncmFwZWhlY3QpICU+JQ0KICBnYXRoZXIoc1ZhciwgZ1ZhbHVlLCBzdGFydHNfd2l0aCgiZ0VzdF8iKSkgJT4lDQogIHNlcGFyYXRlKHNWYXIsIGMoInNWYXIxIiwgInNWYXIyIikpICU+JQ0KICBtdXRhdGUoDQogICAgZk1vZGVsID0gZmFjdG9yKA0KICAgICAgYXMuaW50ZWdlcihzVmFyMiksDQogICAgICBsZXZlbHM9MDo0LA0KICAgICAgbGFiZWxzPWMoImRpcmVjdCIsICJub25lIiwgImFyZWEiLCAiYXJlYSt3b3JrZGF5cyIsICJhcmVhK3dvcmtkYXlzK3NwYXRpYWxjb3JyIikNCiAgICApDQogICkNCg0KZyA8LSBnZ3Bsb3QoZGF0YT1kZlBsb3QsIGFlcyh4PWZBcmVhLCB5PWdWYWx1ZSwgZ3JvdXA9Zk1vZGVsLCBjb2xvcj1mTW9kZWwpKQ0KZyA8LSBnICsgZ2VvbV9wYXRoKHNpemU9MSkNCmcgPC0gZyArIGxhYnMoeCA9ICJBcmVhSUQiLCB5ID0gZXhwcmVzc2lvbihoYXQodGhldGEpKSwgY29sb3I9Ik1vZGVsIikNCmcgPC0gZyArIHRoZW1lX2J3KCkNCnByaW50KGcpDQoNCmBgYA0KDQrmqJnmnKzmir3lh7rliIbmlaPjgYzlpKfjgY3jgYTlnLDln58o44Gk44G+44KK44CB44GK44Gd44KJ44GP44Gv5qiZ5pys44K144Kk44K644GM5bCP44GV44GL44Gj44Gf5Zyw5Z+fKQ0K44KSMzDlgIvpgbjjgpPjgafnpLrjgZnjgIINCuaoqui7uOOBr+WcsOWfn+OBp+OAgeaomeacrOaKveWHuuWIhuaVo+OBruWkp+OBjeOBleOBp+S4puOBueOBpuOBhOOCi+OAguWcsOWfnzE4N+OBr+W3puOBi+OCiTTnlarnm67jgavjgYLjgovjgIINCg0K5o6o5a6a5YCk44Gv44CB5YWx5aSJ6YeP44Go44GX44Gmd29ya2RheXPjgpLmipXlhaXjgZfjgZ/jgZPjgajjgavjgojjgaPjgaYNCuWkp+OBjeOBj+WkieOCj+OCiuOAgeepuumWk+ebuOmWouOCkuiAg+aFruOBl+OBpuOCguOBl+OBquOBj+OBpuOCguOBguOBvuOCiuWkieOCj+OBo+OBpuOBhOOBquOBhOOAgg0K44GT44KM44Gv44GT44GuMzDlnLDln5/jgavpmZDjgaPjgZ/jgZPjgajjgafjga/jgarjgY/jgaYuLi4NCg0KYGBge3J9DQpzdWJfUGxvdFR3b0VzdGltYXRlLjEoDQogIGFnRXN0MSAgICAgPSBhcy52ZWN0b3IoYy5kZlJlc3VsdF9zYWVSRU1MJGdFc3RfMyksIA0KICBhZ01TRTEgICAgID0gYXMudmVjdG9yKGMuZGZSZXN1bHRfc2FlUkVNTCRnTVNFXzMpLCANCiAgYWdFc3QyICAgICA9IGFzLnZlY3RvcihjLmRmUmVzdWx0X3NhZVJFTUwkZ0VzdF80KSwgDQogIGFnTVNFMiAgICAgPSBhcy52ZWN0b3IoYy5kZlJlc3VsdF9zYWVSRU1MJGdNU0VfNCksIA0KICBhc0xhYmVsICAgID0gYy5kZlJlc3VsdF9zYWVSRU1MJG5BcmVhLCANCiAgc1ZhckxhYmVsMSA9ICJhcmVhK3dvcmtkYXlzIiwgDQogIHNWYXJMYWJlbDIgPSAiYXJlYSt3b3JrZGF5cytzcGF0aWFsY29vciINCikNCmBgYA0KDQrlt6blgbTjga7jg5Hjg43jg6vjga/lkITlnLDln5/jga7mjqjlrprlgKTjgpLooajjgZfjgabjgYTjgovjgIINCuaoqui7uOOBr+epuumWk+ebuOmWouOCkuiAg+aFruOBl+OBpuOBhOOBquOBhOWgtOWQiOOAgee4pui7uOOBr+iAg+aFruOBl+OBn+WgtOWQiOOAguOBn+OBhOOBl+OBpuWkieOCj+OBo+OBpuOBhOOBquOBhOOAgg0KDQrjgafjga/jgIHjgo/jgZbjgo/jgZbnqbrplpNGYXktSGVycmlvdOODouODh+ODq+OBquOCk+OBpuS9v+OCj+OBquOBj+OBpuOCiOOBi+OBo+OBn+OCk+OBmOOCg+OBquOBhOOBi++8nw0K44Go44GE44GG44Go44CB44GT44KM44GM44Gd44GG44Gn44KC44Gq44GE44CC5Y+z5YG044Gv5ZCE5Zyw5Z+f44Gu5o6o5a6a5YCk44GuTVNF44Gu5o6o5a6a5YCk44KS6KGo44GX44Gm44GE44KL44CCDQrnqbrplpPnm7jplqLjgpLogIPmha7jgZfjgZ/loLTlkIjjga7jgbvjgYbjgYxNU0Xjga7mjqjlrprlgKTjgYzkuIvjgYzjgaPjgabjgYTjgovjgILjgaTjgb7jgorjgIENCuOCguOBqOOCguOBqOODluODieOCpueVkeW5s+Wdh+mdouepjeOBr+mao+aOpeOBmeOCi+iHquayu+S9k+OBp+S8vOOBpuOBhOOCi+OBqOOBhOOBhuWCvuWQkeOBjOOBguOCi+OBruOBp+OAgQ0K44Gd44KM44KS6ICD5oWu44GZ44KL44GT44Go44Gn44CB5o6o5a6a5YCk44Gu57K+5bqm44KS6auY44KB44Gr6KaL56mN44KC44KL44GT44Go44GM44Gn44GN44Gf44KP44GR44Gg44CCDQoNCiMjIyA0LjIuNCBCYXllc1NBReODkeODg+OCseODvOOCuOOBq+OCiOOCi+aOqOWumg0KDQrjgZPjgpPjganjga9CYXllc1NBReODkeODg+OCseODvOOCuOOAgg0KDQpCYXllc1NBReODkeODg+OCseODvOOCuOOBr0NBUuODouODh+ODq+OBq+OCiOOCi+epuumWk0ZheS1IZXJyaW9044Oi44OH44Or44KS5o6o5a6a44Gn44GN44KLLi4uDQrjga/jgZrjgafjgYLjgovjgILmjqjlrprph4/jga9IQuOAguaOqOWumuaWueazleOBr01DTUPjgIINCg0K44Gn44Gv5o6o5a6a44GX44Gm44G/44KI44GGLi4u44Go6Kmm44G/44Gf44Go44GT44KN44Gn44CBDQrjg4njg4Tjg5zjgavjga/jgb7jgorjgb7jgZfjgZ/jgIINCg0K5bu244CF5pmC6ZaT44KS44GL44GR44Gf5pyr44CB5Lul5LiL44Gu44GT44Go44GM44KP44GL44Gj44Gf44CCDQoNCi0gQmF5ZXNTQUXjg5Hjg4PjgrHjg7zjgrjjga7loLTlkIjjgIFmb3JtdWxh44Gn5YiH54mH6aCF44KS6Zmk5aSW44GZ44KL44GT44Go44GM44Gn44GN44Gq44GE44CCDQogIOS4i+OBruOCs+ODvOODieS+i+OBp+OAgWdyYXBlaGVjdCB+IDAgKyBhcmVhICsgd29ya2RheXMgfCB2YXIg44Go5pu444GT44GG44KC44Gu44Gq44KJ44CBDQogIG1jbWM944Gu5YCk44KS44Gp44KT44Gq44Gr5bCP44GV44GP44GX44Gm44KC44CB5Yem55CG44GM57WC44KP44KJ44Gq44GE44CCDQotIHNldC5zZWVkKCnjgZfjgabjgoLntZDmnpzjga/lho3nj77jgZXjgozjgarjgYTjgILjgaTjgb7jgorjgIFzZXQuc2VlZCgp44Gn44GC44KL44K344O844OJ5YCk44KS5LiO44GI44CBDQogIOOBneOBruebtOW+jOOBq+Wun+ihjOOBmeOCi+OAgeOBqOOBhOOBhuOBruOCkue5sOOCiui/lOOBl+OBn+OBqOOBl+OBpuOCguOAgQ0KICDlrp/ooYzjgZnjgovjgZ/jgbPjgavntZDmnpzjgYzlpInjgo/jgaPjgabjgZfjgb7jgYbjgILmg7Plg4/jgZnjgovjgavjgIHlhoXpg6jjgadD44Gu44Op44Kk44OW44Op44Oq44KS5ZG844KT44Gn44GE44Gm44CBDQogIOOBneOBk+OBp+OBruS5seaVsOOBruOCt+ODvOODieOBr1LkuIrjga7jgrfjg7zjg4njgajjga/liKXjgarjga7jgafjga/jgarjgYvjgo3jgYbjgYvjgIINCi0g5Zu644G+44KL44CC5a6f44Gr6aC757mB44Gr5Zu644G+44KL44CC44Ko44Op44O844Oh44OD44K744O844K444Gu44Gy44Go44Gk44KC44Gq44GE44G+44G+44CB44GE44Gk44G+44Gn5b6F44Gj44Gm44KC5Yem55CG44GMDQogIOe1guOCj+OCieOBquOBj+OBquOBo+OBpuOBl+OBvuOBhuOAgm1jbWM944Gu5YCk44KS5aSn44GN44GP44GZ44KL44Go56K65a6f44Gr5Zu644G+44KL44GX44CB5bCP44GV44GP44GX44Gm44KCDQogIOOBi+OBquOCiuOBrueiuueOh+OBp+WbuuOBvuOCi+OAguOBp+OAgVLjgpLlvLfliLbntYLkuobjgZfjgIHlhajjgY/lkIzjgZjjgrPjg7zjg4koc2V0LnNlZWQoKeOCguWQjOOBmCnjgpINCiAg44KC44GG5LiA5bqm5a6f6KGM44GZ44KL44Go44CB5LuK5bqm44Gv44GX44KM44Gj44Go5YuV44GE44Gf44KK44GZ44KL44CC44G244Gy44O844CCDQogIA0KUuOBruWGjei1t+WLleOCkue5sOOCiui/lOOBl+OBquOBjOOCieS9leW6puOCguippuOBl+OBn+OBquOBi+OBp+OAgemBi+OCiOOBj+e1kOaenOOBjOW+l+OCieOCjOOBn+OCseODvOOCueOCkg0K56S644GZ44CCbWNtYz01MDDjgIINCg0KYGBge3J9DQojIGRmVGVtcCA8LSBleHBhbmQuZ3JpZCgNCiMgICBuUm93ID0gMTpucm93KGMubWJQcm94X3Vuc3RkKSwNCiMgICBuQ29sID0gMTpuY29sKGMubWJQcm94X3Vuc3RkKQ0KIyApIA0KIyBkZlRlbXAkZ1ZhbHVlIDwtIGMubWJQcm94X3Vuc3RkW2FzLm1hdHJpeChkZlRlbXApXQ0KIyBtYlRlbXAgPC0gZGZUZW1wICU+JQ0KIyAgICBmaWx0ZXIoZ1ZhbHVlID4gMCwgblJvdyA8IG5Db2wpICU+JQ0KIyAgICBkcGx5cjo6c2VsZWN0KG5Sb3csIG5Db2wpICU+JQ0KIyAgICBhcy5tYXRyaXgoLikNCiMgDQojIHNldC5zZWVkKDEzKQ0KIyBjLm9Nb2RlbF9CYXllc1NBRSA8LSBCYXllc1NBRSgNCiMgICBncmFwZWhlY3QgfiBhcmVhICsgd29ya2RheXMgfCB2YXIsDQojICAgZGF0YSAgICA9IGMuZGZHcmFwZXMsDQojICAgc3BhdGlhbCA9IFRSVUUsDQojICAgcHJveCAgICA9IG1iVGVtcCwNCiMgICBtY21jICAgID0gNTAwLA0KIyAgIGJ1cm5pbiAgPSAyNTANCiMgKQ0KIyBzYXZlKGMub01vZGVsX0JheWVzU0FFLCBmaWxlPSIuL2Nfb01vZGVsX0JheWVzU0FFLlJEYXRhIikNCg0KbG9hZChmaWxlPSIuL2Nfb01vZGVsX0JheWVzU0FFLlJEYXRhIikNCnN1bW1hcnkoYy5vTW9kZWxfQmF5ZXNTQUUpDQoNCnN1Yl9QbG90VHdvRXN0aW1hdGUuMSgNCiAgYWdFc3QxICAgICA9IGFzLnZlY3RvcihjLm9Nb2RlbF9zYWVSRU1MJGVzdCRlYmx1cCksDQogIGFnTVNFMSAgICAgPSBjLm9Nb2RlbF9zYWVSRU1MJG1zZSwNCiAgYWdFc3QyICAgICA9IGMub01vZGVsX0JheWVzU0FFJEhCLA0KICBhZ01TRTIgICAgID0gc3VtbWFyeShNQ01DKGMub01vZGVsX0JheWVzU0FFKSkkc3RhdGlzdGljc1sxOm5yb3coYy5kZkdyYXBlcyksMl1eMiwNCiAgYXNMYWJlbCAgICA9IGMuZGZHcmFwZXMkbkFyZWFJRCwNCiAgc1ZhckxhYmVsMSA9ICJzYWUgKFJFTUwpIiwNCiAgc1ZhckxhYmVsMiA9ICJCYXllc1NBRSINCikNCg0KYGBgDQoNCi4uLiDjgb7jgYLjgajjgavjgYvjgY/jgIHjg5Hjg4PjgrHjg7zjgrjjgpLkuJbjgavpgIHjgorlh7rjgZnplovnmbrogIXjga7mlrnjgavjga/mhJ/orJ3jgZfjgabjgYrjgorjgb7jgZnjgYzjgIENCkJheWVzU0FF44OR44OD44Kx44O844K444Gn56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgpLmjqjlrprjgZnjgovjga7jga/jgIHnj77nirbjgYvjgarjgormgJbjgYTjgarjgIENCuOBqOaAneOBhuasoeesrOOBp+OBguOCi+OAgg0KDQojIyMgNC4yLjUgcnN0YW7jgavjgojjgovmjqjlrpoNCg0KU0FS44Oi44OH44Or44Gr44Gk44GE44Gm44CB5LuK5bqm44GvcnN0YW7jgafjgoTjgaPjgabjgb/jgojjgYbjgIINClNBUuODouODh+ODq+OBr+ODmeOCpOOCuuaOqOWumuOBqOOBruebuOaAp+OBjOOBguOBvuOCiuOCiOOBj+OBquOBhOOCiOOBhuOBquOBruOBoOOBjOOAgQ0K5o6o5a6a44Gn44GN44Gq44GE44KP44GR44GY44KD44Gq44GE44KJ44GX44GE44CCDQoNCuOBvuOBmnN0YW7jgrPjg7zjg4njgILku6XkuIvjgafjga/jg4bjgq3jgrnjg4jjgajjgZfjgabnpLrjgZnjgYzjgIENCuacrOeJqeOBr+ODleOCoeOCpOODq+OBq+OBquOBo+OBpuOBhOOCi+OAgg0K5q2j55u044CB5YWo54S26Ieq5L+h44GM44Gq44GE44Gu44Gn44GZ44GMLi4uDQoNCmBgYHtyIGVuZ2luZT0nY2F0JywgcmVzdWx0cz0iaGlkZSJ9DQovLyBTcGF0aWFsIEZheS1IZXJyaW90IG1vZGVsIChTQVIpDQovLyBjZi4gaHR0cHM6Ly9yZHJyLmlvL2dpdGh1Yi9zc29ybzQxMS9iYXllc2FlL3NyYy9SL01vZGVsc19mYXN0LlINCg0KZGF0YSB7DQogIGludDxsb3dlcj0xPiAgICAgICAgICAgICAgICAgIE07DQogIGludDxsb3dlcj0wPiAgICAgICAgICAgICAgICAgIFA7DQogIHZlY3RvcltNXSAgICAgICAgICAgICAgICAgICAgIFk7IA0KICB2ZWN0b3I8bG93ZXI9MD5bTV0gICAgICAgICAgICBTRDsNCiAgbWF0cml4PGxvd2VyPTAsIHVwcGVyPTE+W00sTV0gVzsNCiAgbWF0cml4W00sUF0gICAgICAgICAgICAgICAgICAgWDsNCn0NCg0KdHJhbnNmb3JtZWQgZGF0YSB7DQogIG1hdHJpeFtNLE1dIHVuaXQ7DQogIHVuaXQgPSBkaWFnX21hdHJpeChyZXBfdmVjdG9yKDEsTSkpOw0KfQ0KDQpwYXJhbWV0ZXJzIHsNCiAgcmVhbDxsb3dlcj0tMC45OTk5OSwgdXBwZXI9MC45OTk5OT4gcmhvOyAgIA0KICByZWFsPGxvd2VyPTA+ICBzaWdtYV9zcTsgICAgICAgICAgICAgICAgICAgDQogIHZlY3RvcltQXSAgICAgIGJldGE7ICAgICAgICAgICAgICAgICAgICAgICANCiAgdmVjdG9yW01dICAgICAgdGhldGE7ICAgICAgICAgICAgICAgICAgICAgIA0KfQ0KDQptb2RlbCB7DQogIHRoZXRhIH4gbXVsdGlfbm9ybWFsX3ByZWMoWCpiZXRhLCAoMS9zaWdtYV9zcSkqKCh1bml0LXJobyooVykpKih1bml0LXJobyooVycpKSkgKTsNCiAgLy8gc2xvd2VyDQogIC8vIHRoZXRhIH4gbXVsdGlfbm9ybWFsX3ByZWMoIFgqYmV0YSwgKDEvc2lnbWFfc3EpKmNyb3NzcHJvZCh1bml0LXJobyooVykpICkgOyANCiAgWSB+IG5vcm1hbCh0aGV0YSwgU0QpOw0KfQ0KYGBgDQoNClLjgrPjg7zjg4njga/ku6XkuIvjgILjgbXjgaDjgpPjga9NcGx1c+OBruW/oOWun+OBquS/oeiAheOBp+OAgXN0YW7jgavjgYLjgb7jgormhaPjgozjgabjgarjgYTjgoLjga7jgafjgIENCuOBk+OCjOOBjOmAn+OBhOOBruOBi+mBheOBhOOBruOBi+OCj+OBi+OCieOBquOBhOOBruOBoOOBjOOAgVBD44KSNuaZgumWk+OBj+OCieOBhA0K5ZS444KJ44Gb44KL576955uu44Gr44Gq44Gj44Gf44CCDQoNCmBgYHtyfQ0KDQojIGMub1N0YW5Nb2RlbCA8LSBzdGFuX21vZGVsKGZpbGU9Ii4vU0ZIMS5zdGFuIikNCiMgc2F2ZShjLm9TdGFuTW9kZWwsIGZpbGU9Ii4vYy5vU3Rhbk1vZGVsLlJEYXRhIikNCiMgbG9hZChmaWxlID0gIi4vYy5vU3Rhbk1vZGVsLlJEYXRhIikNCiANCiMgbWdNb2RlbE1hdHJpeCA8LSBtb2RlbC5tYXRyaXgofiBhcmVhICsgd29ya2RheXMsIGRhdGE9Yy5kZkdyYXBlcykNCiMgbERhdGEgPC0gbGlzdCgNCiMgICBNICA9IG5yb3coYy5kZkdyYXBlcyksDQojICAgUCAgPSBuY29sKG1nTW9kZWxNYXRyaXgpLA0KIyAgIFkgID0gYy5kZkdyYXBlcyRncmFwZWhlY3QsDQojICAgU0QgPSBjLmRmR3JhcGVzJFNFLA0KIyAgIFcgID0gYy5tZ1Byb3hfc3RkLA0KIyAgIFggID0gbWdNb2RlbE1hdHJpeA0KIyApDQojIA0KIyBjLm9TdGFuRml0ICAgPC0gc2FtcGxpbmcoDQojICAgb1N0YW5Nb2RlbF92ZWMsDQojICAgZGF0YSAgICA9IGxEYXRhLA0KIyAgIHNlZWQgICAgPSAxMjM0LA0KIyAgIGl0ZXIgICAgPSA1MDAsDQojICAgdmVyYm9zZSA9IFRSVUUsDQojICAgY29udHJvbCA9IGxpc3QoYWRhcHRfZGVsdGEgPSAwLjk1KSwNCiMgICByZWZyZXNoID0gMTANCiMgKQ0KIyBzYXZlKGMub1N0YW5GaXQsIGZpbGU9Ii4vYy5vU3RhbkZpdC5SRGF0YSIpDQpsb2FkKGZpbGU9Ii4vYy5vU3RhbkZpdC5SRGF0YSIpDQpzdGFuX3RyYWNlKGMub1N0YW5GaXQsIGMoInJobyIsICJzaWdtYV9zcSIsICJ0aGV0YVsxMTZdIiksIGluY193YXJtdXAgPSBUKQ0Kc3Rhbl9yaGF0KGMub1N0YW5GaXQpDQpgYGANCg0KJFxyaG8sIFxzaWdtYV91XjIsIFx0aGV0YV97MTE2fSwk44Gu44OI44Os44O844K544OX44Ot44OD44OI44Go44CBDQokXGhhdHtSfSTjga7jg5Ljgrnjg4jjgrDjg6njg6DjgpLmj4/jgYTjgabjgb/jgZ/jgIINCuOBquOBiuOAgeWcsOWfnzExNuOBr+ebtOaOpeaOqOWumumHj+OBruWIhuaVo+OBjOacgOOCgumrmOOBhOOAgk1DTUPjgavjgYrjgYTjgabjg5Hjg6njg6Hjg7zjgr/jga4kXGhhdHtSfSTjgYwNCuS4gOeVqumrmOOBhOOBruOCgiRcdGhldGFfezExNn0k44Gn44GC44KLKDEuMDk5KeOAgg0KDQrjgb7jgYIuLi4g44GO44KK44GO44KK5Y+O5p2f44GX44Gm44GE44KL44Go44GE44GG44GT44Go44Gr44GX44Gf44GE44GM44CBDQp3YXJtdXAo54++54q244Gn44Gv44OH44OV44Kp44Or44OI44GuMjUwKeOBjOOBoeOCh+OBo+OBqOi2s+OCiuOBquOBhOOCiOOBhuOBquawl+OBjOOBmeOCi+OBruOBp+OAgQ0K5Lul5LiL44Gn44Gv44GV44KJ44GrNTDlj43lvqnjgpLmjajjgabjgIHmnIDlvozjga4yMDDlj43lvqnjgaDjgZHkvb/jgYbjgZPjgajjgavjgZnjgovjgIINCg0K5Zyw5Z+f54m55oCn44Gu5o6o5a6a5YCk44KSc2Fl44OR44OD44Kx44O844K444Go5q+U6LyD44GX44Gm44G/44KL44GoLi4uDQoNCmBgYHtyfQ0KbWdSZXN1bHQgPC0gcnN0YW46OmV4dHJhY3QoYy5vU3RhbkZpdCwgcGVybXV0ZWQgPSBGQUxTRSkgIyAzIGRpbXMNCm1nVGhldGEgPC0gbWdSZXN1bHRbNTE6MjUwLCAsIGdyZXBsKCJedGhldGEiLCBkaW1uYW1lcyhtZ1Jlc3VsdCkkcGFyYW1ldGVycyldDQptZ1RoZXRhIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseSgxOjQsIGZ1bmN0aW9uKG5JRCkgbWdUaGV0YVssbklELF0pKQ0KYWdFc3QgPC0gY29sTWVhbnMobWdUaGV0YSkNCmFnTVNFIDwtIGFwcGx5KG1nVGhldGEsIDIsIHZhcikNCg0Kc3ViX1Bsb3RUd29Fc3RpbWF0ZS4xKA0KICBhZ0VzdDEgICAgID0gYXMudmVjdG9yKGMub01vZGVsX3NhZVJFTUwkZXN0JGVibHVwKSwNCiAgYWdNU0UxICAgICA9IGMub01vZGVsX3NhZVJFTUwkbXNlLA0KICBhZ0VzdDIgICAgID0gYWdFc3QsDQogIGFnTVNFMiAgICAgPSBhZ01TRSwNCiAgYXNMYWJlbCAgICA9IGMuZGZHcmFwZXMkbkFyZWFJRCwNCiAgc1ZhckxhYmVsMSA9ICJzYWUgKFJFTUwpIiwNCiAgc1ZhckxhYmVsMiA9ICJyc3RhbiINCikNCg0KYGBgDQoNCuaOqOWumuWApOOBr+OBu+OBvOWQjOOBmOOAgU1TReOBr+mrmOOCgeOBq+aOqOWumuOBleOCjOOBpuOBhOOCi+OAgg0KDQojIyMgNC4yLjYgc3BkZXDjg5Hjg4PjgrHjg7zjgrjjgavjgojjgovmjqjlrpoNCg0Kc2Fl44OR44OD44Kx44O844K444Gn5o6o5a6a44GX44Gf56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgajjga/jgIHopoHjga8NCuWQhOWcsOWfn+OBruaomeacrOaKveWHuuiqpOW3ruWIhuaVoyRccHNpX2kk44GM5pei55+l44GqU0FS44Oi44OH44Or44GLQ0FS44Oi44OH44Or44Gq44Gu44Gg44GL44KJ44CBDQrmsY7nlKjnmoTjgarjg5Hjg4PjgrHjg7zjgrjjgafmjqjlrprjgafjgY3jgovjga/jgZrjgaDjgIINCg0KLi4u44Go6ICD44GI44CBU0FS44Oi44OH44Or44Gu44G744GG44Gr44Gk44GE44Gm44CBDQrmnpzmlaLjgavjgoJzcGRlcOODkeODg+OCseODvOOCuOOBp+OBruaOqOWumuOBq+ODgeODo+ODrOODs+OCuOOBl+OBpuOBv+OBn+OAgg0K5q2j55u044CB5q2j44GX44GE44Kz44O844OJ44Gq44Gu44GL5YWo44GP6Ieq5L+h44GM44Gq44GE44CCDQoNCueJueOBq+iHquS/oeOBjOOBquOBhOOBruOBjOOAgeaomeacrOaKveWHuuiqpOW3ruWIhuaVoyRccHNpX2kk44Gu5oyH5a6a44Gu5LuV5pa544Gn44GC44KL44CCDQplcnJvcnNhcmxtKCnjgavjga93ZWlnaHRzPeOBqOOBhOOBhuW8leaVsOOBjOOBguOCi+OAguODnuODi+ODpeOCouODq+OBq+OBhOOCj+OBj+OAgQ0K44CM44Kq44OX44K344On44Oz44CC44OV44Kj44OD44OG44Kj44Oz44Kw44Gu6YGO56iL44Gn55So44GE44KJ44KM44KL44Km44Kn44Kk44OI44Gu44OZ44Kv44OI44Or44CCDQrpnZ5OVUxM44Gu44Km44Kn44Kk44OI44KS5oyH5a6a44GZ44KL44GT44Go44Gn44CB6Kaz5a+f44Gr44KI44Gj44Gm5YiG5pWj44GM55Ww44Gq44KL44GT44Go44KSDQrmjIfnpLrjgZnjgovjgZPjgajjgYzjgafjgY3jgovjgILjgZPjga7loLTlkIjjgIHjgqbjgqfjgqTjg4jjga7lgKTjga/liIbmlaPjgajlj43mr5TkvovjgZnjgovlgKTjgajjgZnjgovjgI0NCjwhLS0g44Gq44GE44GX44CB44GT44KM44Go5ZCM44GY44GT44Go44Gr44Gq44KL44GM44CBIC0tPg0KPCEtLSDjgqbjgqfjgqTjg4jjgajjgZfjgabmraPjga7mlbTmlbB3XzHjgpLmjIflrprjgZnjgovjgZPjgajjgafjgIEgLS0+DQo8IS0tIOOBneOCjOOBnuOCjOOBruWPjeW/nHlfaeOBjOOAgeWNmOS9jeOCpuOCp+OCpOODiOOCkuaMgeOBpHdfaeWAi+OBruims+Wvn+OBruW5s+Wdh+OBp+OBguOCi+OBk+OBqOOCkiAtLT4NCjwhLS0g5oyH56S644GZ44KL44GT44Go44GM44Gn44GN44KLIC0tPg0K44Go44GC44KL44CC44Gd44KM44Gn44CB44GN44Gj44God2VpZ2h0c+OBq+OBryQxL1xwc2lfaSTjgpLmjIflrprjgZnjgovjgpPjgaDjgo3jgYbjgagNCuaAneOBo+OBn+OCj+OBkeOBquOBruOBp+OBmeOBjC4uLiANCg0KYGBge3J9DQpjLm9Nb2RlbF9zcGRlcCA8LSBlcnJvcnNhcmxtKA0KICBncmFwZWhlY3QgfiBhcmVhICsgd29ya2RheXMgLCANCiAgZGF0YSAgICA9IGMuZGZHcmFwZXMsIA0KICBsaXN0dyAgID0gbWF0Mmxpc3R3KGMubWdQcm94X3N0ZCwgc3R5bGU9IlciKSwgDQogIHdlaWdodHMgPSAxL3Zhcg0KKQ0KcHJpbnQoc3VtbWFyeShjLm9Nb2RlbF9zcGRlcCkpDQpgYGANCiRcc2lnbWFfdV4yJOOBrzU2LjkwNChzZWHjg5Hjg4PjgrHjg7zjgrjjgafjga83MS4xODkpLCANCiRccGhpJOOBrzAuNTgxKHNhZeODkeODg+OCseODvOOCuOOBp+OBrzAuNTgzKeOBqOaOqOWumuOBleOCjOOBn+OAgg0KDQokXHNpZ21hX3VeMiTjga7mjqjlrprlgKTjgYzlhajnhLbjgaHjgYzjgYbjgIIkXG1hdGhiZntcYmV0YX0k44Gu5o6o5a6a5YCk44KCDQrjgYvjgarjgorpgZXjgYbjgILmmpfpm7LlnoLjgozovrzjgoHjgabjgY3jgZ/jgZHjgozjganjgIEkXHRoZXRhX2kk44Gu5o6o5a6a5YCk44KS5q+U44G544Gm44G/44KL44GoLi4uDQoNCmBgYHtyfQ0Kc3ViX1Bsb3RUd29Fc3RpbWF0ZS4xKA0KICBhZ0VzdDEgICAgID0gYXMudmVjdG9yKGMub01vZGVsX3NhZVJFTUwkZXN0JGVibHVwKSwgDQogIGFnRXN0MiAgICAgPSBhcy52ZWN0b3IocHJlZGljdChjLm9Nb2RlbF9zcGRlcCwgcHJlZC50eXBlPSJUUyIpKSwgDQogIGFzTGFiZWwgICAgPSBjLmRmR3JhcGVzJG5BcmVhSUQsIA0KICBzVmFyTGFiZWwxID0gInNhZSAoUkVNTCkiLCANCiAgc1ZhckxhYmVsMiA9ICJzcGRlcCINCikNCmBgYA0KDQrmoYjjga7lrprjgIHjgYvjgarjgorpgZXjgYbjgILjgarjgZzjgaDvvJ/vvJ8NCg0K5LqM44Gk44Gu5Y+v6IO95oCn44GM6ICD44GI44KJ44KM44KL44CCDQoNCi0g56eB44GMc3BkZXDjg5Hjg4PjgrHjg7zjgrjjga7kvb/jgYTmlrnjgpLjgojjgY/nkIbop6PjgafjgY3jgabjgYrjgonjgZrjgIENCiAg5pu444GN5pa544KS6ZaT6YGV44GI44Gm44GE44KL44CCDQotIOOBneOCguOBneOCgnNwZGVw44OR44OD44Kx44O844K444GuZXJyb3JzYXJsbSgp44Gn44Gv44CB44GT44GT44Gn44GE44GGDQogIOepuumWk0ZheS1IZXJyaW9044Oi44OH44Or44KS5o6o5a6a44Gn44GN44Gq44GE44CCDQogIA0K44GC44KM44GT44KM6ICD44GI44Gm44GE44Gm44CB5a6f44Gv5b6M6ICF44Gq44Gu44GL44KC44CB44Go44GE44GG5rCX44GM44GX44Gm44GN44Gf44CCDQrjgZ3jga7nkIbnlLHjga/mrKHjga7pgJrjgorjgIINCg0K56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjga/jgIENCiRcaGF0e1xtYXRoYmZ7XHRoZXRhfX0gPSAoXHRoZXRhXzEsIFxsZG90cywgXHRoZXRhX20pXlQk44Go44GX44CBDQokXHBzaV8xLCBcbGRvdHMsIFxwc2lfbSTjgpLmjIHjgaTlr77op5LooYzliJfjgpIkXG1hdGhiZntcUHNpfSTjgajmm7jjgY/jgajjgZfjgaYNCiQkDQogIFxoYXR7XG1hdGhiZntcdGhldGF9fSANCiAgPSBcbWF0aGJme1p9IFxtYXRoYmZ7XGJldGF9ICsgXG1hdGhiZnt2fSArIFxtYXRoYmZ7ZX0sIFwgXCANCiAgXG1hdGhiZntlfSBcc2ltICgwLCBcbWF0aGJme1xQc2l9KQ0KJCQNCiQkDQogIFxtYXRoYmZ7dn0gPSBccGhpIFxtYXRoYmZ7V30gXG1hdGhiZnt2fSArIFxtYXRoYmZ7dX0sIFwgXCANCiAgXG1hdGhiZnt1fSBcc2ltIE4oXG1hdGhiZnswfSwgXHNpZ21hX3VeMiBcbWF0aGJme0l9KQ0KJCQNCuOBqOOBquOCi+OBqOaAneOBhuOAguOBhOOBo+OBveOBhmVycm9yc2FybG0oKeOBruODouODh+ODq+OBr+OAgeODnuODi+ODpeOCouODq+OBq+OCiOOCjOOBsA0KDQp5ID0gWCBiZXRhICsgdSwgdSA9IGxhbWJkYSBXIHUgKyBlDQoNCuOBp+OBguOCi+OAguiomOazleOCkuaPg+OBiOOCi+OBqOOAgeOBk+OCjOOBrw0KJCQNCiAgXGhhdHtcbWF0aGJme1x0aGV0YX19IA0KICA9IFxtYXRoYmZ7Wn0gXG1hdGhiZntcYmV0YX0gKyBcbWF0aGJme3Z9IA0KJCQNCiQkDQogIFxtYXRoYmZ7dn0gPSBccGhpIFxtYXRoYmZ7V30gXG1hdGhiZnt2fSArIFxtYXRoYmZ7dX0sIFwgXCANCiAgXG1hdGhiZnt1fSBcc2ltIE4oXG1hdGhiZnswfSwgXHNpZ21hX3VeMiBcbWF0aGJme0l9KQ0KJCQNCuOBp+OBr+OBquOBhOOBi+OBqOaAneOBhuOBruOBp+OBguOCi+OAgndlaWdodHM95byV5pWw44GvDQrmjqjlrprjga7pmpvjgavjgarjgpPjgonjgYvkvb/jgo/jgozjgovph43jgb/jgaXjgZHjgavpgY7jgY7jgZrjgIHjg6Ljg4fjg6vjgavjga/mqJnmnKzmir3lh7roqqTlt67jgYzlkKvjgb7jgozjgaYNCuOBhOOBquOBhOOBruOBp+OBr+OBquOBi+OCjeOBhuOBi++8nw0KDQrjgYbjg7zjgoDjgILmrovlv7XjgarjgYzjgonjgIHjgojjgY/jgo/jgYvjgonjgarjgYTjgIINCuOBqeOBquOBn+OBi+aVmeOBiOOBpuOBj+OBoOOBleOCieOBquOBhOOBp+OBl+OCh+OBhuOBi+OAgg0KDQpgYGB7ciwgcmVzdWx0cz0iaGlkZSJ9DQpybShsaXN0PWdyZXAoIl5jXFwuIiwgbHMoKSwgdmFsdWU9VCkpDQpgYGANCg0KIyMgNC4zIOOCt+ODn+ODpeODrOODvOOCt+ODp+ODsw0KPCEtLSBjaHVua+OCkui2heOBiOOCi+OCquODluOCuOOCp+OCr+ODiOOBr2Qu44GL44KJ5aeL44KB44KLIC0tPg0KDQrjgZPjgYbjgZfjgabjgb/jgabjgb/jgovjgajjgIHjgYTjgo3jgYTjgo3nlpHllY/jgYzmuafjgYTjgabjgY/jgovjgILjgo/jgZ/jgY/jgZfjgajoh7TjgZfjgb7jgZfjgabjga/jgIENCueJueOBq+asoeOBrjPngrnjgavplqLlv4PjgYzjgYLjgovjgIINCg0KLSBzcGRlcOODkeODg+OCseODvOOCuOOBq+OCiOOCi+aOqOWumuOBr+OAgXNhZeODkeODg+OCseODvOOCuOOBq+OCiOOCi+aOqOWumuOBqA0KICDokZfjgZfjgY/nlbDjgarjgovjgILjgZPjgozjga/np4Hjga7kvb/jgYTmlrnjgYzmgqrjgYTjgYvjgIHjgarjgYTjgZcNCiAg44Oi44OH44Or44GM55Ww44Gq44KL44GL44KJ44Gg44Go5oCd44GG44CC44Gn44Gv44CB55yf5YCk44KS5q2j44GX44GP5o6o5a6a44GX44Gm44GE44KL44Gu44GvDQogIOOBqeOBoeOCieOBi+OAgnNhZeODkeODg+OCseODvOOCuOOBruOBu+OBhuOBjOato+OBl+OBhOOAgeOBqOOBhOOBhuOBk+OBqOOCkueiuuOBi+OCgeOBn+OBhOOAgg0KLSBncmFwZXPjg4fjg7zjgr/jga7loLTlkIjjgIHnqbrplpPnm7jplqLjgpLogIPmha7jgZfjgabjgoLjgZfjgarjgY/jgabjgoLjgIENCiAg5o6o5a6a5YCk44Gv44Gf44GE44GX44Gm5aSJ44KP44KJ44Gq44GL44Gj44Gf44GM44CBTVNF44Gu5o6o5a6a5YCk44Gv5LiL44GM44Gj44Gf44CCDQogIOOBp+OBr+OAgeecn+OBrk1TReOCkuato+OBl+OBj+aOqOWumuOBl+OBpuOBhOOCi+OBruOBr+OBqeOBoeOCieOBi+OAgg0KLSDnnJ/jga7nqbrplpPnm7jplqLjgYzpq5jjgZHjgozjgbDjgIHnqbrplpPnm7jplqLjga7ogIPmha7jgavjgojjgaPjgabmjqjlrprjga7nsr7luqbjga8NCiAg5LiK44GM44KL44Gg44KN44GG44CC44Gn44Gv44CB55yf44Gu56m66ZaT55u46Zai44GM44Gp44Gu44GP44KJ44GE6auY44GL44Gj44Gf44KJ44CBDQogIOepuumWk+ebuOmWouOCkuiAg+aFruOBmeOBueOBjeOBquOBruOBi+OAgg0KDQrjgZPjgpPjgbDjgpPjga/jgIHjgrfjg5/jg6Xjg6zjg7zjgrfjg6fjg7Pjga7mmYLplpPjgafjgZnjgIINCg0KIyMjIDQuMy4xIOWVj+mhjA0KDQokYyTooYwkYyTliJfjga7jgrDjg6rjg4Pjg4njgafljLrliIfjgonjgozjgZ8kbT1jKmMk5YCL44Gu5Zyw5Z+f44GM44GC44KL44Go44GZ44KL44CCDQrjgYTjgb7jgIHlnLDln58kaSQoJD0xLFxsZG90cyxtJCnjga7jgbLjgajjgorjgbLjgajjgorjga7kvY/msJEkaiQoJD0xLFxsZG90cyxOX2kkKeOBjOOAgQ0K6YeP55qE44Gq5Y+N5b+c5aSJ5pWwJHlfe2lqfSTjgpLmjIHjgaPjgabjgYTjgovjgILjgYjjg7zjgaPjgajjgIHlubjnpo/luqbjgaPjgabjgZPjgajjgavjgZfjgb7jgZfjgofjgYbjgYvjgIINCg0K5Zyw5Z+f44Gu5q+N6ZuG5Zuj44K144Kk44K6JE5faSTjga/jgYTjgZrjgozjgoLljYHliIbjgavlpKfjgY3jgYTjgIINCuWQhOWcsOWfn+OBruW5uOemj+W6puOBruavjeW5s+WdhyRcYmFye1l9X2kgPSAoMS9OX2kpIFxzdW1faiB5X3tpan0k44Gr44Gk44GE44Gm5o6o5ris44GX44Gf44GE44CCDQoNCuOBneOBk+OBp+OAgeWQhOWcsOWfnyRpJOOBi+OCieOCteOCpOOCuiRuX2kk44Gu5qiZ5pys44KS5Y2Y57SU54Sh5L2c54K65oq95Ye644GX44CBDQrmqJnmnKzlubPlnYckXGhhdHtcYmFye1l9fV9pID0gXGZyYWN7XHN1bV9qIHlfe2lqfX17bl9pfSQsDQrjgarjgonjgbPjgavjgZ3jga7liIbmlaPjga7mjqjlrprlgKQNCiRcaGF0e1Zhcn0oXGhhdHtcYmFye1l9fV9pKSA9IFxmcmFje1xzdW1faiAoeV97aWp9IC0gXGhhdHtcYmFye1l9fV9pKX17bl9pKG5faS0xKX0kDQrjgpLmsYLjgoHjgZ/jgIINCg0K44Go44GT44KN44GM44CB5Zyw5Z+f44GU44Go44Gu5qiZ5pys44K144Kk44K6JG5faSTjga/lv4XjgZrjgZfjgoLljYHliIbjgafjgarjgYTjgIINCuOBvuOBn+OAgei+uuOCkuaOpeOBmeOCi+WcsOWfn+mWk+OBp+OBr+OAgeW5uOemj+W6puW5s+WdhyRcYmFye1l9X2kk44GM5Ly844Gm44GE44KL44CBDQrjgajnp4Hjga/kv6HjgZjjgabjgYTjgoso44Gq44KT44GL44Gd44Gu44CB5aKD55WM44KS6LaF44GI44Gm5ryC44Gj44Gm44GP44KL44KT44GY44KD44Gq44GE44Gn44GZ44GL44Gt44CBDQrlubjjgZvjga7jgqrjg7zjg6njgb/jgZ/jgYTjgarjgoLjga7jgYwp44CCIA0K44Gg44GL44KJ44CB5bm456aP5bqm44Gu5qiZ5pys5bmz5Z2HJFxoYXR7XGJhcntZfX1faSTjgaDjgZHjgafjgarjgY/jgIENCuOBneOBruWcsOWfn+OBjOS7luOBruOBqeOBruWcsOWfn+OBqOaOpeOBl+OBpuOBhOOCi+OBi+OBqOOBhOOBhuaDheWgseOCguOBpOOBi+OBo+OBpuOAgQ0K5ZCE5Zyw5Z+f44Gu5bm456aP5bqm44Gu5q+N5bmz5Z2HJFxiYXJ7WX1faSTjgpINCuaOqOa4rOOBp+OBjeOCi+OBr+OBmuOBp+OBguOCi+OAgg0KDQrjgZ3jgZPjgafnqbrplpNGYXktRXJyaW9044Oi44OH44Or44Gu55m75aC044Gn44GC44KL44CCDQoNCuS7peS4i+OAgeiomOWPt+OBjOeFqembkeOBq+OBquOCi+OBruOBp+OAgQ0KUk3mnKzjgavjgYLjgo/jgZvjgaYkXHRoZXRhX2kgPSBcYmFye1l9X2kkLCAkXGhhdHtcdGhldGF9X2kgPSBcaGF0e1xiYXJ7WX19X2kkDQrjgajmm7jjgY/jgIINCuOBvuOBn+OAgQ0KJFxwc2lfaSA9IFZhcihcaGF0e1xiYXJ7WX19X2kpJOOBqOabuOOBj+OAgg0KDQrjgYrjgZXjgonjgYTjgZnjgovjgajjgIHnqbrplpNGYXktSGVycmlvdOODouODh+ODqyhTQVLjg6Ljg4fjg6sp44Gv5Lul5LiL44Gu6YCa44KK44CCDQrkuIrjga7llY/poYzoqK3lrprjgavjgYLjgo/jgZvjgIHlhbHlpInph4/jgpLnnIHjgYTjgabmm7jjgY/jgIINCiRcaGF0e1xtYXRoYmZ7XHRoZXRhfX0gPSAoXHRoZXRhXzEsIFxsZG90cywgXHRoZXRhX20pXlQk44Go44GX44CBDQokXHBzaV8xLCBcbGRvdHMsIFxwc2lfbSTjgpLmjIHjgaTlr77op5LooYzliJfjgpIkXG1hdGhiZntcUHNpfSTjgajmm7jjgY/jgIINCg0KJCQgDQogIFxoYXR7XG1hdGhiZntcdGhldGF9fSA9IFxtYXRoYmZ7dn0gKyBcbWF0aGJme2V9LCBcIFwNCiAgXG1hdGhiZntlfSBcc2ltIChcbWF0aGJmezB9LCBcbWF0aGJme1xQc2l9KQ0KJCQNCiQkDQogIFxtYXRoYmZ7dn0gPSAoXG1hdGhiZntJfS1ccGhpIFxtYXRoYmZ7V30pXnstMX0gXG1hdGhiZnt1fSwgXCBcIA0KICBcbWF0aGJme3V9IFxzaW0gTihcbWF0aGJmezB9LCBcc2lnbWFfdV4yIFxtYXRoYmZ7SX0pDQokJA0KDQojIyMgNC4zLjIg44OH44O844K/55Sf5oiQ44Oi44OH44OrDQoNCuODh+ODvOOCv+eUn+aIkOODouODh+ODq+OBr+asoeOBruOBqOOBiuOCiuOAglNBUuODouODh+ODq+OBq+WfuuOBpeOBj+OAgg0KDQrlnLDln58gJGk9MSxcbGRvdHMsbSQg44Gu44Om44OL44OD44OIICRqPTEsXGxkb3RzLG5faiQg44Gr44Gk44GE44Gm44CBDQokJCANCiAgeV97aWp9ID0gNTAgKyB2X2kgKyBcZXBzaWxvbl97aWp9LCBcIFwgDQogIFxlcHNpbG9uX3tpan0gXG1hdGhvcHtcc2ltfV57aWlkfSBOKDAsMTAwKQ0KJCQNCiRcbWF0aGJme3Z9ID0gKHZfMSwgXGxkb3RzLCB2X20pXlQk44Gr44Gk44GE44Gm44CBDQokJA0KICBcbWF0aGJme3Z9ID0gKFxtYXRoYmZ7SX0gLSBccGhpIFxtYXRoYmZ7V30pXnstMX0gXG1hdGhiZnt1fSwgXCBcIA0KICBcbWF0aGJme3V9IFxzaW0gTihcbWF0aGJmezB9LCBcc2lnbWFfdV4yIFxtYXRoYmZ7SX0pDQokJCANCiRcbWF0aGJme1d9JOOBr+OAgei+uuOCkuaOpeOBmeOCi+WcsOWfn+OCkjHjgajjgZfjgZ/pmqPmjqXooYzliJfjgpLooYzmqJnmupbljJbjgZfjgZ/jgoLjga7jgajjgZnjgovjgIINCg0K44Gk44G+44KK44CB56eB44Gv55+l44KJ44Gq44GE44Gu44Gg44GM44CB5a6f44GvDQoNCi0gKOW5uOemj+W6pik9NTArKOWcsOWfn+WKueaenCkrKOWAi+S6uuW3rikg44Gn44GC44KL44CCDQotIOWcsOWfn+mWk+OBp+W5uOemj+W6puOBq+OBsOOCieOBpOOBjeOBjOOBguOCiuOAgeOBneOBruOBsOOCieOBpOOBjeOBr+WkmuWkiemHj+ato+imj+WIhuW4g+OBq+W+k+OBo+OBpuOBhOOCi+OAgg0KICDpmqPmjqXjgZfjgabjgYTjgovlnLDln5/plpPjgafjga/lubjnpo/luqbjgYzkvLzjgabjgYTjgovjgIINCi0g5Zyw5Z+f5YaF44Gu5YCL5Lq65beu44KC5q2j6KaP5YiG5biD44Gr5b6T44Gj44Gm44GE44KL44CCDQoNCuavjembhuWbo+OCteOCpOOCuuOBr+Wkp+OBjeOBj+OAgSRcZXBzaWxvbl97aWp9JOOBruavjembhuWbo+W5s+Wdh+OBrw0KMOOBqOOBv+OBquOBm+OCi+OBruOBp+OAgee1kOWxgOOAgeefpeOCiuOBn+OBhOeJueaApyRcdGhldGFfaSTjga/jgZPjgZPjgafjga8kdl9pJOOBq+etieOBl+OBhOOAgg0KDQrlnLDln5/jga7mqJnmnKzjgrXjgqTjgrokbl9pJOOBr+OAgSQxMCwgMjAsIFxsZG90cywgMTAwJOOCkumVt+OBlSRtJOOBq+mBlOOBmeOCi+OBvuOBp+e5sOOCiui/lOOBl+OAgQ0K44GT44KM44KS44Op44Oz44OA44Og44Gr5Lim44Gz5pu/44GI44Gf44KC44Gu44Go44GZ44KL44CCDQoNCiMjIyA0LjMuMyDjgrfjg5/jg6Xjg6zjg7zjgrfjg6fjg7PnlKjjga7plqLmlbANCg0KLi4u44Go44GE44GG44OH44O844K/44KS55Sf5oiQ44GZ44KL44Gf44KB44Gu44CB5LiA6YCj44Gu6Zai5pWw44KS5L2c44Gj44Gm44G/44G+44GX44Gf44CCDQoNCmBgYHtyfQ0KZC5zdWJfTWFrZU5laWdoYm9yTWF0cml4LjEgPC0gZnVuY3Rpb24obk51bUdyaWRSb3csIG5OdW1HcmlkQ29sKXsNCiAgIyBwdXJwb3NlOiBtYWtlIGEgbmVpZ2hib3IgbWF0cml4IG9mIG1lc2hlcyBpbiBzcGVjaWZpZWQgZ3JpZA0KICAjIGFyZ3M6IA0KICAjICAgbk51bUdyaWRSb3csIG5OdW1HcmlkQ29sOiBzaXplIG9mIGdyaWQNCiAgIyByZXR1cm46IA0KICAjICAgYSBuZWlnaGJvciBtYXRyaXggKHJvdy1zdGFuZGFyZGl6ZWQpDQogICMgbm90ZXM6IA0KICAjICAgZS5nLiBuTnVtR3JpZFJvdz0yLCBuTnVtR3JpZENvbD0zDQogICMgICAgIG1lc2hJRCBpbiBncmlkOg0KICAjICAgICAgICAxLCAyLCAzDQogICMgICAgICAgIDQsIDUsIDYNCiAgIyAgICAgbmVpZ2hib3IgbWF0cml4ICh1bnN0YW5kYXJkaXplZCk6IA0KICAjICAgICAgICAobWVzaElEPTEpIDAsIDEsIDAsIDEsIDAsIDANCiAgIyAgICAgICAgKG1lc2hJRD0yKSAxLCAwLCAxLCAwLCAxLCAwIA0KICAjICAgICAgICAobWVzaElEPTMpIDAsIDEsIDAsIDAsIDAsIDENCiAgIyAgICAgICAgKG1lc2hJRD00KSAxLCAwLCAwLCAwLCAxLCAwDQogICMgICAgICAgIChtZXNoSUQ9NSkgMCwgMSwgMCwgMSwgMCwgMQ0KICAjICAgICAgICAobWVzaElEPTYpIDAsIDAsIDEsIDAsIDEsIDANCiAgDQogIGRmVmFsdWUgPC0gZXhwYW5kLmdyaWQoDQogICAgIyBuR3JpZFJvdzEsIG5HcmlkQ29sMTogbG9jYXRpb24gb2YgbWVzaDEgaW4gdGhlIGdyaWQgDQogICAgIyBuR3JpZFJvdzIsIG5HcmlkQ29sMjogbG9jYXRpb24gb2YgbWVzaDIgaW4gdGhlIGdyaWQgDQogICAgbkdyaWRSb3cxID0gMTpuTnVtR3JpZFJvdywNCiAgICBuR3JpZENvbDEgPSAxOm5OdW1HcmlkQ29sLA0KICAgIG5HcmlkUm93MiA9IDE6bk51bUdyaWRSb3csDQogICAgbkdyaWRDb2wyID0gMTpuTnVtR3JpZENvbA0KICApICU+JQ0KICAgIG11dGF0ZSgNCiAgICAgICMgbkxvYzE6IG1lc2hJRCBvZiBtZXNoMQ0KICAgICAgIyBuTG9jMjogbWVzaElEIG9mIG1lc2gyDQogICAgICBuTG9jMSA9IChuR3JpZFJvdzEtMSkqbk51bUdyaWRDb2wgKyBuR3JpZENvbDEsDQogICAgICBuTG9jMiA9IChuR3JpZFJvdzItMSkqbk51bUdyaWRDb2wgKyBuR3JpZENvbDIsDQogICAgICAjIGJWYWx1ZTogbmVpZ2hib3Igb3Igbm90DQogICAgICBiVmFsdWUgPSBpZl9lbHNlKA0KICAgICAgICAoDQogICAgICAgICAgKG5HcmlkUm93MSA9PSBuR3JpZFJvdzIpDQogICAgICAgICAgJiAoYWJzKG5HcmlkQ29sMSAtIG5HcmlkQ29sMikgPT0gMSkNCiAgICAgICAgKXwoDQogICAgICAgICAgKGFicyhuR3JpZFJvdzEgLSBuR3JpZFJvdzIpPT0xKQ0KICAgICAgICAgICYgKG5HcmlkQ29sMSA9PSBuR3JpZENvbDIpDQogICAgICAgICksDQogICAgICAgIDEsIDANCiAgICAgICkNCiAgICApDQogIA0KICBkZk5hbWUgPC0gZGZWYWx1ZSAlPiUNCiAgICBkcGx5cjo6c2VsZWN0KG5HcmlkUm93MSwgbkdyaWRDb2wxLCBuTG9jMSkgJT4lDQogICAgZGlzdGluY3QoKSAlPiUNCiAgICBtdXRhdGUoc05hbWUgPSBwYXN0ZTAoInIiLCBuR3JpZFJvdzEsICJjIiwgbkdyaWRDb2wxKSkgJT4lDQogICAgYXJyYW5nZShuTG9jMSkgDQogICMjIHByaW50KGRmTmFtZSkNCiAgDQogIG91dCA8LSBtYXRyaXgoMCwgbnJvdz1uTnVtR3JpZFJvdypuTnVtR3JpZENvbCwgbmNvbD1uTnVtR3JpZFJvdypuTnVtR3JpZENvbCkNCiAgb3V0W2FzLm1hdHJpeChkZlZhbHVlW2MoIm5Mb2MxIiwgIm5Mb2MyIildKV0gPC0gZGZWYWx1ZSRiVmFsdWUNCiAgb3V0IDwtIHN3ZWVwKG91dCwgTUFSR0lOID0gMSwgRlVOID0gIi8iLCBTVEFUUyA9IHJvd1N1bXMob3V0KSkNCiAgcm93bmFtZXMob3V0KSA8LSBkZk5hbWUkc05hbWUNCiAgY29sbmFtZXMob3V0KSA8LSBkZk5hbWUkc05hbWUNCiAgDQogICMgcHJpbnQob3V0KQ0KICByZXR1cm4ob3V0KQ0KfQ0KZC5zdWJfR2VuZXJhdGVEYXRhc2V0Mi4xIDwtIGZ1bmN0aW9uKA0KICBtZ05CLCBnVmFyVSwgZ1BoaSwgZ1ZhckU9MTAwLCBhblBvc3NpYmxlTj1zZXEoMTAsIDEwMCwgYnkgPSAxMCkNCil7DQogICMjIHB1cnBvc2U6IGdlbmVyYXRlIGEgZGF0YXNldCBmb3Igc3BhdGlhbCBGSCBtb2RlbA0KICAjIyBhcmc6DQogICMjICAgbWdOQjogICAgICAgIG5laWdoYm9yIG1hdHJpeA0KICAjIyAgIGdWYXJVOiAgICAgICB2YXJpYW5jZSBvZiBhcmVhIGVmZmVjdHMNCiAgIyMgICBnUGhpOiAgICAgICAgc3BhdGlhbCBjb3JyZWxhdGlvbg0KICAjIyAgIGdWYXJFOiAgICAgICB2YXJpYW5jZSBpbiBlYWNoIGFyZWENCiAgIyMgICBhblBvc3NpYmxlTjogdmVjdG9yIG9mIHBvc3NpYmxlIHNhbXBsZSBzaXplDQogICMjIHJldHVybjoNCiAgIyMgICBhIGRhdGEgZnJhbWUsIGFyZWEgbGV2ZWwgZGF0YQ0KICAjIyAgICRuQXJlYTogICAgICAgQXJlYSBJRA0KICAjIyAgICRzTmFtZTogICAgICAgR3JpZCBMb2NhdGlvbiAoZS5nLiAicjJjMyIgbWVhbnMgcm93Mi1jb2wzKQ0KICAjIyAgICRuU2l6ZTogICAgICAgc2FtcGxlIHNpemUNCiAgIyMgICAkZ1U6ICAgICAgICAgIGFyZWEgZWZmZWN0IHdpdGhvdXQgc3BhdGlhbCBjb3JyZWxhdGlvbg0KICAjIyAgICRnVjogICAgICAgICAgYXJlYSBlZmZlY3Qgd2l0aCBzcGF0aWFsIGNvcnJlbGF0aW9uDQogICMjICAgJGdUcnVlOiAgICAgICB0cnVlIHZhbHVlDQogICMjICAgJGdFc3RfRGlyZWN0OiBzYW1wbGUgbWVhbnMgb2YgYSByZXNwb25zZSB2YXJpYWJsZQ0KICAjIyAgICRnTVNFX0RpcmVjdDogc2FtcGxlIGVzdC4gb2YgdmFyaWFuY2Ugb2Ygc2FtcGxlIG1lYW5zDQogIA0KICBuTnVtQXJlYSA8LSBucm93KG1nTkIpDQogIA0KICAjIGFuU2l6ZTogc2FtcGxlIHNpemUgDQogIGFuU2l6ZSA8LSByZXAoYW5Qb3NzaWJsZU4sIG5OdW1BcmVhICUvJSBsZW5ndGgoYW5Qb3NzaWJsZU4pICsgMSlbMTpuTnVtQXJlYV0NCiAgYW5TaXplIDwtIHNhbXBsZShhblNpemUsIG5OdW1BcmVhLCByZXBsYWNlPUZBTFNFKQ0KICAjIyBwcmludChhblNpemUpDQogIA0KICAjIGFnVTogXHNpbSBOKFxtYXRoYmZ7MH0sIFxzaWdtYV91XjIgXG1hdGhiZntJfSkNCiAgYWdVIDwtIHJub3JtKG4gPSBuTnVtQXJlYSwgbWVhbiA9IDAsIHNkID0gc3FydChnVmFyVSkpDQogICMgYWdWOiAoXG1hdGhiZntJfSAtIFxwaGkgXG1hdGhiZntXfSleey0xfSBcbWF0aGJme3V9DQogIG1nQ29lZiA8LSBzb2x2ZShkaWFnKHg9MSwgbnJvdz1uTnVtQXJlYSkgLSBnUGhpICogbWdOQikNCiAgYWdWIDwtIGFzLnZlY3RvcihtZ0NvZWYgJSolIGFnVSkNCiAgDQogIGFzTmFtZSA8LSByb3duYW1lcyhtZ05CKQ0KICANCiAgb3V0IDwtIGRhdGEuZnJhbWUoDQogICAgbkFyZWEgICAgICA9IDE6bk51bUFyZWEsDQogICAgc05hbWUgICAgICA9IGFzTmFtZSwNCiAgICBuR3JpZFJvdyAgID0gYXMuaW50ZWdlcihzdWIoIl5yKFswLTldKyljKFswLTldKykkIiwgIlxcMSIsIGFzTmFtZSkpLA0KICAgIG5HcmlkQ29sICAgPSBhcy5pbnRlZ2VyKHN1YigiXnIoWzAtOV0rKWMoWzAtOV0rKSQiLCAiXFwyIiwgYXNOYW1lKSksDQogICAgblNpemUgICAgICA9IGFuU2l6ZSwNCiAgICBnVSAgICAgICAgID0gYWdVLA0KICAgIGdWICAgICAgICAgPSBhZ1YsDQogICAgZ1RydWUgICAgICA9IDUwICsgYWdWLA0KICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KICApDQogIGxFcnJvciA8LSBsYXBwbHkoDQogICAgb3V0JG5TaXplLA0KICAgIGZ1bmN0aW9uKG5TaXplKXsNCiAgICAgIHJub3JtKG4gPSBuU2l6ZSwgbWVhbiA9IDAsIHNkID0gc3FydChnVmFyRSkpDQogICAgfQ0KICApDQogIG91dCRnRXN0X0RpcmVjdCAgPC0gb3V0JGdUcnVlICsgc2FwcGx5KGxFcnJvciwgbWVhbikNCiAgb3V0JGdNU0VfRGlyZWN0ICA8LSBzYXBwbHkobEVycm9yLCBmdW5jdGlvbih4KXsgdmFyKHgpIC8gbGVuZ3RoKHgpIH0pDQogIA0KICAjIyBwcmludChvdXQpDQogIHJldHVybihvdXQpDQp9DQpkLnN1Yl9HZW5lcmF0ZU11bHRpRGF0YXNldDIuMSA8LSBmdW5jdGlvbihuTnVtRGF0YXNldD0xLCBtZ05CLCBnVmFyVSwgZ1BoaSwgLi4uKXsNCiAgIyMgcHVycG9zZTogZ2VuZXJhdGUgbXVsdGlwbGUgZGF0YXNldHMgZm9yIEZIIG1vZGVsDQogICMjIGFyZzoNCiAgIyMgICBuTnVtRGF0YXNldDogICBudW1iZXIgb2YgZGF0YSBzZXRzDQogICMjICAgbWdOQjogICAgICAgICAgbmVpZ2hib3IgbWF0cml4DQogICMjICAgZ1ZhclU6ICAgICAgICAgdmFyaWFuY2Ugb2YgYXJlYSBlZmZlY3RzDQogICMjICAgZ1BoaTogICAgICAgICAgc3BhdGlhbCBjb3JyZWxhdGlvbiwgDQogICMjICAgLi4uOiAgICAgICAgICAgcGFzcyB0byBzdWJfR2VuZXJhdGVEYXRhc2V0Mi4xKCkgKGdWYXJFLCBhblBvc3NpYmxlTikNCiAgIyMgICAgICAgICAgICAgICAgICAgICANCiAgIyMgcmV0dXJuOg0KICAjIyAgIGEgZGF0YXNldA0KICAjIyAgICRuRGF0YXNldDogIERhdGFzZXQgSUQNCiAgIyMgICAkLi4uICAgICAgICBnZW5lcmF0ZWQgYnkgc3ViX0dlbmVyYXRlRGF0YXNldDIuMSgpDQogIA0KICBvdXQgPC0gZGF0YS5mcmFtZShuRGF0YXNldCA9IDE6bk51bURhdGFzZXQpICU+JQ0KICAgIGdyb3VwX2J5KG5EYXRhc2V0KSAlPiUNCiAgICBkcGx5cjo6ZG8oZC5zdWJfR2VuZXJhdGVEYXRhc2V0Mi4xKG1nTkIgPSBtZ05CLCBnVmFyVSA9IGdWYXJVLCBnUGhpID0gZ1BoaSkpICU+JQ0KICAgIHVuZ3JvdXAoKQ0KICByZXR1cm4ob3V0KQ0KfQ0KZC5zdWJfRXN0aW1hdGVEYXRhc2V0QnlNZXRob2QyLjEgPC0gZnVuY3Rpb24oDQogIGRmRGF0YSwgbWdOQiwgc01ldGhvZCwgYlZlcmJvc2U9RkFMU0UNCil7DQogICMjIHB1cnBvc2U6IGVzdGltYXRlIHNwYXRpYWwgRkggbW9kZWwgZm9yIGEgZGF0YXNldCBieSBhIG1ldGhvZA0KICAjIyBhcmc6DQogICMjICAgZGZEYXRhOiAgYSBkYXRhIHNldA0KICAjIyAgIG1nTkI6ICAgIG5laWdoYm9yIG1hdHJpeA0KICAjIyAgIHNNZXRob2Q6IHsic2FlRkgiLCAic2FlU0ZIIiwgInNwZGVwV0dUIiwgInNwZGVwTk9XR1QifQ0KICAjIyAgIGJWZXJib3NlDQogICMjIHJldHVybjoNCiAgIyMgICBhIGxpc3QNCg0KICAjIyB0cmFwOiBjaGVjayBzTWV0aG9kDQogIHN0b3BpZm5vdChzTWV0aG9kICVpbiUgYygic2FlRkgiLCAic2FlU0ZIIiwgInNwZGVwV0dUIiwgInNwZGVwTk9XR1QiKSkNCg0KICBpZiAoYlZlcmJvc2UpIGNhdCgiW3N1Yl9Fc3RpbWF0ZURhdGFzZXQyLjFdIiwgc01ldGhvZCwgIi4uLiBcbiIpDQoNCiAgdCA8LSBwcm9jLnRpbWUoKQ0KDQogIGlmIChzTWV0aG9kID09ICJzYWVGSCIpIHsNCiAgICBvTW9kZWwgPC0gdHJ5KA0KICAgICAgbXNlRkgoDQogICAgICAgIGZvcm11bGEgPSBkZkRhdGEkZ0VzdF9EaXJlY3QgfiAxLA0KICAgICAgICB2YXJkaXIgID0gZGZEYXRhJGdNU0VfRGlyZWN0LA0KICAgICAgICBtZXRob2QgID0gIlJFTUwiDQogICAgICApDQogICAgKQ0KICAgIGlmICghaW5oZXJpdHMob01vZGVsLCAidHJ5LWVycm9yIikpIHsNCiAgICAgIGFnRXN0ICA8LSBhcy52ZWN0b3Iob01vZGVsJGVzdCRlYmx1cCkNCiAgICAgIGFnTVNFICA8LSBvTW9kZWwkbXNlDQogICAgICBnU0NvcnIgPC0gTkENCiAgICAgIGdBSUMgICA8LSBvTW9kZWwkZXN0JGZpdCRnb29kbmVzc1syXQ0KICAgICAgZ0JJQyAgIDwtIG9Nb2RlbCRlc3QkZml0JGdvb2RuZXNzWzNdIA0KICAgIH0NCiAgfQ0KICBpZiAoc01ldGhvZCA9PSAic2FlU0ZIIikgew0KICAgIG9Nb2RlbCA8LSB0cnkoDQogICAgICBtc2VTRkgoDQogICAgICAgIGZvcm11bGEgPSBkZkRhdGEkZ0VzdF9EaXJlY3QgfiAxLA0KICAgICAgICB2YXJkaXIgID0gZGZEYXRhJGdNU0VfRGlyZWN0LA0KICAgICAgICBwcm94bWF0ID0gbWdOQiwNCiAgICAgICAgbWV0aG9kICA9ICJSRU1MIg0KICAgICAgKQ0KICAgICkNCiAgICBpZiAoIWluaGVyaXRzKG9Nb2RlbCwgInRyeS1lcnJvciIpKSB7DQogICAgICBhZ0VzdCA8LSBhcy52ZWN0b3Iob01vZGVsJGVzdCRlYmx1cCkNCiAgICAgIGFnTVNFIDwtIG9Nb2RlbCRtc2UNCiAgICAgIGdTQ29yciA8LSBvTW9kZWwkZXN0JGZpdCRzcGF0aWFsY29ycg0KICAgICAgZ0FJQyAgIDwtIG9Nb2RlbCRlc3QkZml0JGdvb2RuZXNzWzJdDQogICAgICBnQklDICAgPC0gb01vZGVsJGVzdCRmaXQkZ29vZG5lc3NbM10gDQogICAgfQ0KICB9DQogIGlmIChzTWV0aG9kID09ICJzcGRlcFdHVCIpIHsNCiAgICBvTW9kZWwgPC0gdHJ5KA0KICAgICAgZXJyb3JzYXJsbSgNCiAgICAgICAgZ0VzdF9EaXJlY3QgfiAxICwNCiAgICAgICAgZGF0YSAgICA9IGRmRGF0YSwNCiAgICAgICAgbGlzdHcgICA9IG1hdDJsaXN0dyhtZ05CLCBzdHlsZT0iVyIpLA0KICAgICAgICB3ZWlnaHRzID0gMS9nTVNFX0RpcmVjdA0KICAgICAgKQ0KICAgICkNCiAgICAjIyBwcmludChvTW9kZWwpDQogICAgaWYgKCFpbmhlcml0cyhvTW9kZWwsICJ0cnktZXJyb3IiKSkgew0KICAgICAgYWdFc3QgIDwtIGFzLnZlY3RvcihwcmVkaWN0KG9Nb2RlbCwgcHJlZC50eXBlPSJUUyIpKQ0KICAgICAgYWdNU0UgIDwtIHJlcChOQSwgbnJvdyhkZkRhdGEpKQ0KICAgICAgZ1NDb3JyIDwtIG9Nb2RlbCRsYW1iZGENCiAgICAgIGdBSUMgICA8LSBOQQ0KICAgICAgZ0JJQyAgIDwtIE5BDQogICAgfQ0KICB9DQogIGlmIChzTWV0aG9kID09ICJzcGRlcE5PV0dUIikgew0KICAgIG9Nb2RlbCA8LSB0cnkoDQogICAgICBlcnJvcnNhcmxtKA0KICAgICAgICBnRXN0X0RpcmVjdCB+IDEgLA0KICAgICAgICBkYXRhICAgID0gZGZEYXRhLA0KICAgICAgICBsaXN0dyAgID0gbWF0Mmxpc3R3KG1nTkIsIHN0eWxlPSJXIikNCiAgICAgICkNCiAgICApDQogICAgIyMgcHJpbnQob01vZGVsKQ0KICAgIGlmICghaW5oZXJpdHMob01vZGVsLCAidHJ5LWVycm9yIikpIHsNCiAgICAgIGFnRXN0IDwtIGFzLnZlY3RvcihwcmVkaWN0KG9Nb2RlbCwgcHJlZC50eXBlPSJUUyIpKQ0KICAgICAgYWdNU0UgPC0gcmVwKE5BLCBucm93KGRmRGF0YSkpDQogICAgICBnU0NvcnIgPC0gb01vZGVsJGxhbWJkYQ0KICAgICAgZ0FJQyAgIDwtIE5BDQogICAgICBnQklDICAgPC0gTkENCiAgICB9DQogIH0NCg0KICAjIyBjb21tb24gcHJvY2VzcyAuLi4NCiAgaWYgKCFpbmhlcml0cyhvTW9kZWwsICJ0cnktZXJyb3IiKSkgew0KICAgIG91dCA8LSBsaXN0KA0KICAgICAgc01ldGhvZCA9IHNNZXRob2QsDQogICAgICBiU3RhdHVzID0gVFJVRSwNCiAgICAgIGFnRXN0ICAgPSBhZ0VzdCwNCiAgICAgIGFnTVNFICAgPSBhZ01TRSwNCiAgICAgIGdTQ29yciAgPSBnU0NvcnIsDQogICAgICBnQUlDICAgID0gZ0FJQywNCiAgICAgIGdCSUMgICAgPSBnQklDLA0KICAgICAgZ1RpbWUgICA9IChwcm9jLnRpbWUoKSAtIHQpWzNdDQogICAgKQ0KICAgIGlmIChiVmVyYm9zZSkgY2F0KCJbc3ViX0VzdGltYXRlRGF0YXNldDIuMV0gU3VjY2Vzcy4iLCBvdXQkZ1RpbWUsICJzZWMuXG4iKQ0KICB9IGVsc2Ugew0KICAgIG91dCA8LSBsaXN0KA0KICAgICAgc01ldGhvZCA9IHNNZXRob2QsDQogICAgICBiU3RhdHVzID0gRkFMU0UsDQogICAgICBhZ0VzdCAgID0gcmVwKE5BLCBucm93KGRmRGF0YSkpLA0KICAgICAgYWdNU0UgICA9IHJlcChOQSwgbnJvdyhkZkRhdGEpKSwNCiAgICAgIGdTQ29yciAgPSBOQSwgDQogICAgICBnQUlDICAgID0gTkEsIA0KICAgICAgZ0JJQyAgICA9IE5BLA0KICAgICAgZ1RpbWUgICA9IChwcm9jLnRpbWUoKSAtIHQpWzNdDQogICAgKQ0KICAgIGlmIChiVmVyYm9zZSkgY2F0KCJbc3ViX0VzdGltYXRlRGF0YXNldDIuMV0gRmFpbC4iLCBvdXQkZ1RpbWUsICJzZWMuXG4iKQ0KICB9DQogIHJldHVybihvdXQpDQp9DQpkLnN1Yl9Fc3RpbWF0ZURhdGFzZXQyLjEgPC0gZnVuY3Rpb24oDQogIGRmRGF0YSwgbWdOQiwgYXNNZXRob2Q9Yygic2FlRkgiLCAic2FlU0ZIIiwgInNwZGVwV0dUIiwgInNwZGVwTk9XR1QiKSwgLi4uDQopew0KICAjIyBwdXJwb3NlOiBlc3RpbWF0ZSBzcGF0aWFsIEZIIG1vZGVsIGZvciBhIGRhdGFzZXQgYnkgbXVsdGlwbGUgbWV0aG9kcw0KICAjIyBhcmc6DQogICMjICAgZGZEYXRhOiAgIGEgZGF0YSBzZXQNCiAgIyMgICBtZ05COiAgICAgbmVpZ2hib3IgbWF0cml4DQogICMjICAgYXNNZXRob2Q6IHsic2FlRkgiLCAic2FlU0ZIIiwgInNwZGVwV0dUIiwgInNwZGVwTk9XR1QifQ0KICAjIyAgIC4uLjogICAgICBwYXNzIHRvIHN1Yl9Fc3RpbWF0ZURhdGFzZXRCeU1ldGhvZDIuMSgpIChiVmVyYm9zZSkNCiAgIyMgcmV0dXJuOg0KICAjIyAgIGEgZGF0YSBmcmFtZQ0KDQogIGxPdXQgPC0gbGFwcGx5KA0KICAgIGFzTWV0aG9kLA0KICAgIGZ1bmN0aW9uKHNNZXRob2Qpew0KICAgICAgbFJlc3VsdCA8LSBkLnN1Yl9Fc3RpbWF0ZURhdGFzZXRCeU1ldGhvZDIuMShkZkRhdGEsIG1nTkIsIHNNZXRob2QsIC4uLikNCiAgICAgIG91dCA8LSBkYXRhLmZyYW1lKA0KICAgICAgICBuQXJlYSAgID0gZGZEYXRhJG5BcmVhLA0KICAgICAgICBzTmFtZSAgID0gZGZEYXRhJHNOYW1lLA0KICAgICAgICBzTWV0aG9kID0gcmVwKGxSZXN1bHQkc01ldGhvZCwgbnJvdyhkZkRhdGEpKSwNCiAgICAgICAgYlN0YXR1cyA9IHJlcChsUmVzdWx0JGJTdGF0dXMsIG5yb3coZGZEYXRhKSksDQogICAgICAgIGdFc3QgICAgPSBsUmVzdWx0JGFnRXN0LA0KICAgICAgICBnTVNFICAgID0gbFJlc3VsdCRhZ01TRSwNCiAgICAgICAgZ1NDb3JyICA9IHJlcChsUmVzdWx0JGdTQ29yciwgbnJvdyhkZkRhdGEpKSwNCiAgICAgICAgZ0FJQyAgICA9IHJlcChsUmVzdWx0JGdBSUMsICAgbnJvdyhkZkRhdGEpKSwNCiAgICAgICAgZ0JJQyAgICA9IHJlcChsUmVzdWx0JGdCSUMsICAgbnJvdyhkZkRhdGEpKSwNCiAgICAgICAgZ1RpbWUgICA9IHJlcChsUmVzdWx0JGdUaW1lLCAgbnJvdyhkZkRhdGEpKSwNCiAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQogICAgICApDQogICAgICByZXR1cm4ob3V0KQ0KICAgIH0NCiAgKQ0KICBvdXQgPC0gYmluZF9yb3dzKGxPdXQpICU+JQ0KICAgIGdhdGhlcihzVmFyLCBnVmFsdWUsIGMoYlN0YXR1cywgZ0VzdCwgZ01TRSwgZ1NDb3JyLCBnQUlDLCBnQklDLCBnVGltZSkpICU+JQ0KICAgIG11dGF0ZShzVmFyID0gcGFzdGUwKHNWYXIsICJfIiwgc01ldGhvZCkpICU+JQ0KICAgIGRwbHlyOjpzZWxlY3QobkFyZWEsIHNWYXIsIGdWYWx1ZSkgJT4lDQogICAgc3ByZWFkKHNWYXIsIGdWYWx1ZSkNCg0KICBvdXQgPC0gZnVsbF9qb2luKGRmRGF0YSwgb3V0LCBieSA9ICJuQXJlYSIpDQoNCiAgcmV0dXJuKG91dCkNCn0NCmQuc3ViX0VzdGltYXRlTXVsdGlEYXRhc2V0Mi4xIDwtIGZ1bmN0aW9uKGRmTXVsdGlEYXRhLCBtZ05CLCAuLi4pew0KICAjIyBwdXJwb3NlOiBlc3RpbWF0ZSBGSCBtb2RlbHMgZm9yIG11bHRpcGxlIGRhdGFzZXRzIGJ5IG11bHRpcGxlIG1ldGhvZHMNCiAgIyMgYXJnOg0KICAjIyAgIGRmTXVsdGlEYXRhOiBtdWx0aXBsZSBkYXRhDQogICMjICAgbWdOQjogICAgICAgIG5laWdoYm9yIG1hdHJpeA0KICAjIyAgIC4uLjogICAgICAgICBwYXNzIHRvIHN1Yl9Fc3RpbWF0ZURhdGFzZXQyLjEoKSAoYXNNZXRob2QsIGJWZXJib3NlKQ0KICAjIyByZXR1cm46DQogICMjICAgYSBkYXRhIGZyYW1lIG9mIG11bHRpcGxlIHJlc3VsdHMNCg0KICBvdXQgPC0gZGZNdWx0aURhdGEgJT4lDQogICAgZ3JvdXBfYnkobkRhdGFzZXQpICU+JQ0KICAgIGRwbHlyOjpkbyhkLnN1Yl9Fc3RpbWF0ZURhdGFzZXQyLjEoLiwgbWdOQiA9IG1nTkIsIC4uLikpICU+JQ0KICAgIHVuZ3JvdXAoKQ0KDQogIHJldHVybihvdXQpDQp9DQpkLnN1Yl9Fc3RpbWF0b3JBc0ZhY3Rvci4xIDwtIGZ1bmN0aW9uKGFzRXN0aW1hdG9yKXsNCiAgIyMgcHVycG9zZTogY29udmVydCBlc3RpbWF0b3IgbmFtZXMgaW50byBmYWN0b3INCiAgIyMgYXJnczoNCiAgIyMgICBhc0VzdGltYXRvcjogYSBjaGFyYWN0ZXIgdmVjdG9yIG9mIGVzdGltYXRvciBuYW1lcw0KICAjIyByZXR1cm46DQogICMjICAgYSBmYWN0b3IgdmVjdG9yDQoNCiAgZmFjdG9yKA0KICAgIGFzRXN0aW1hdG9yLA0KICAgIGxldmVscyA9IGMoDQogICAgICAiVHJ1ZSIsICJEaXJlY3QiLCAic2FlRkgiLCAic2FlU0ZIIiwgDQogICAgICAic3BkZXBXR1QiLCAic3BkZXBOT1dHVCINCiAgICApLA0KICAgIGxhYmVscyA9IGMoDQogICAgICAiVHJ1ZSIsICJEaXJlY3QiLCAic2FlKHcvbyBzYykiLCAic2FlKHcvIHNjKSIsIA0KICAgICAgInNwZGVwKHdndCkiLCAic3BkZXAodW53Z3QpIg0KICAgICkNCiAgKQ0KfQ0KZC5zdWJfRXN0aW1hdG9yUGFsZXR0ZS4xIDwtIGZ1bmN0aW9uKGFmRXN0aW1hdG9yKXsNCiAgIyMgcHVycG9zZTogZ2V0IGNvbnNpc250ZW50IGNvbG9yIHBhbGxldHRlIGZvciBlc3RpbWF0b3JzDQogICMjIGFyZ3M6DQogICMjICAgYWZFc3RpbWF0b3I6IGEgZmFjdG9yIHZlY3RvciBvZiBlc3RpbWF0b3INCiAgIyMgcmV0dXJuOg0KICAjIyAgIGEgdmVjdG9yIG9mIGNvbG9yIHBhbGV0dGUNCg0KICBnZ19jb2xvcl9odWUoNilbc29ydCh1bmlxdWUoYXMuaW50ZWdlcihhZkVzdGltYXRvcikpKV0NCg0KfQ0KDQpgYGANCg0KIyMjIDQuMy4zIOODh+ODvOOCv+WIhuaekOS+iw0KDQrjgZ/jgoHjgZfjgavjgIHkuIroqJjjga7jg4fjg7zjgr/nlJ/miJDplqLmlbDjgajjg4fjg7zjgr/liIbmnpDplqLmlbDjgpLkvb/jgaPjgabjgb/jgojjgYbjgIINCg0K5Zyw5Z+f5pWw44KSJDEwIFx0aW1lcyAxMCA9IDEwMCQsIOWcsOWfn+WKueaenOOBruWIhuaVoyRcc2lnbWFfdV4yJOOCkjUwLCANCuepuumWk+iHquW3seebuOmWouODkeODqeODoeODvOOCvyRccGhpJOOCkjAuN+OBqOOBmeOCi+OAgg0KDQpgYGB7cn0NCnNldC5zZWVkKDEwMCkNCmQubWdOZWlnaGJvciA8LSBkLnN1Yl9NYWtlTmVpZ2hib3JNYXRyaXguMSgxMCwgMTApDQpkLmRmRGVtb0RhdGEgPC0gZC5zdWJfR2VuZXJhdGVEYXRhc2V0Mi4xKG1nTkIgPSBkLm1nTmVpZ2hib3IsIGdWYXJVPTUwLCBnUGhpPTAuNykNCmBgYA0KDQrlkITlnLDln5/jga7mqJnmnKzjgrXjgqTjgrrjgajjgIHlubjnpo/luqbjga7mqJnmnKzlubPlnYfjgpLmj4/jgYTjgabjgb/jgojjgYbjgIINCg0KYGBge3J9DQpkZlBsb3QgPC0gZC5kZkRlbW9EYXRhICU+JQ0KICBkcGx5cjo6c2VsZWN0KG5BcmVhLCBuR3JpZFJvdywgbkdyaWRDb2wsIG5TaXplLCBnRXN0X0RpcmVjdCkgDQpnIDwtIGdncGxvdChkYXRhPWRmUGxvdCwgYWVzKHg9bkdyaWRDb2wsIHk9LW5HcmlkUm93LCBzaXplID0gblNpemUsIGxhYmVsPW5BcmVhKSkNCmcgPC0gZyArIGdlb21fY291bnQoYWVzKGNvbG9yPWdFc3RfRGlyZWN0KSwgc2hhcGU9MTUpDQpnIDwtIGcgKyBnZW9tX3RleHQoc2l6ZT00KQ0KZyA8LSBnICsgc2NhbGVfc2l6ZV9hcmVhKG1heF9zaXplID0gMTIpDQpnIDwtIGcgKyBzY2FsZV94X2Rpc2NyZXRlKCkNCmcgPC0gZyArIHNjYWxlX3lfZGlzY3JldGUoKQ0KZyA8LSBnICsgc2NhbGVfY29sb3JfZ3JhZGllbnQobG93PSJ5ZWxsb3ciLCBoaWdoPSJyZWQiKQ0KZyA8LSBnICsgbGFicyh4PU5VTEwsIHk9TlVMTCwgc2l6ZT0iU2FtcGxlU2l6ZSIsIGNvbG9yPSJEaXJlY3QiKQ0KZyA8LSBnICsgdGhlbWVfYncoKQ0KcHJpbnQoZykNCmBgYA0KDQrmraPmlrnlvaLjga/lkITlnLDln5/jgIHmlbDlrZfjga/lnLDln5/nlarlj7csIOOCteOCpOOCuuOBr+aomeacrOOCteOCpOOCuuOAgeiJsuOBrua/g+OBleOBr+aomeacrOW5s+Wdh+OBrumrmOOBleOCkuihqOOBmeOAgg0K5b+D44Gq44GX44GL44CB6Zqj5o6l44GX44Gm44GE44KL5Zyw5Z+f44Gu6Imy44Gv5Ly844Gm44GE44KL44KI44GG44Gq5rCX44GM44GX44G+44Gb44KT44GL77yfDQoNCk1vcnJhbuOBrknjgpLmsYLjgoHjgabjgb/jgovjgaguLi4NCmBgYHtyfQ0KbW9yYW4udGVzdChkLmRmRGVtb0RhdGEkZ0VzdF9EaXJlY3QsIG1hdDJsaXN0dyhkLm1nTmVpZ2hib3IsIHN0eWxlPSJXIikpDQpgYGANCg0KST0wLjMy44CC5pyJ5oSP44Gn44Gv44GC44KL44GM44CB44Gd44KT44Gq44Gr5aSn44GN44GP44Gq44GE44CC44GT44KM44Gv5qiZ5pys5bmz5Z2H44Gr5qiZ5pys5oq95Ye66Kqk5beu44GMDQrovInjgaPjgabjgYTjgovjgYvjgonjgaDjgo3jgYbjgajmgJ3jgYTjgIHjgZ/jgoHjgZfjgavnnJ/lgKQkdl9pJOOBq+OBpOOBhOOBpg0KTW9ycmFu44GuSeOCkuaxguOCgeOBpuOBv+OBn+OCiS4uLg0KDQpgYGB7cn0NCm1vcmFuLnRlc3QoZC5kZkRlbW9EYXRhJGdUcnVlLCBtYXQybGlzdHcoZC5tZ05laWdoYm9yLCBzdHlsZT0iVyIpKQ0KYGBgDQoNCkk9MC4zNSwg44Gf44GE44GX44Gm44GL44KP44KJ44Gq44GE44CC44Gd44KT44Gq44KC44KT44Gq44Gu44GLLi4uDQoNCuOBp+OBr+OAgeaOqOWumuOBl+OBpuOBv+OBvuOBl+OCh+OBhuOAgg0K5qyh44GuNuWAi+OCkuavlOi8g+OBmeOCi+OAgg0KDQotICoqVHJ1ZSoqOiDnnJ/lgKQkXHRoZXRhX2kk44CCDQotICoqRGlyZWN0Kio6IOaomeacrOW5s+Wdh1xoYXR7XHRoZXRhfV9p44CCDQotICoqc2FlKHcvbyBzYykqKjogc2Fl44OR44OD44Kx44O844K4LCDnqbrplpPnm7jplqLjgpLogIPmha7jgZfjgarjgYTjgIINCiAgICAgICAgICAgICAgICAgICBFQkxVUOaOqOWumumHjywgJFxzaWdtYV92XjIk44KSUkVNTOaOqOWumuOAgg0KLSAqKmhic2FlKHcvIHNjKSoqOiBzYWXjg5Hjg4PjgrHjg7zjgrgsIOepuumWk+ebuOmWouOCkuiAg+aFruOBmeOCiyhTQVLjg6Ljg4fjg6sp44CCDQogICAgICAgICAgICAgICAgICBFQkxVUOaOqOWumumHjywgJFxzaWdtYV92XjIk44KSUkVNTOaOqOWumuOAgg0KLSAqKnNwZGUod2d0KSoqOiAgIHNwZGVw44OR44OD44Kx44O844K4KFNBUuODouODh+ODqynjgILmqJnmnKzmir3lh7roqqTlt67liIbmlaPjgavjgojjgaPjgabph43jgb/jgaXjgZHjgZnjgovjgIINCi0gKipzcGRlKHVud2d0KSoqOiAgIHNwZGVw44OR44OD44Kx44O844K4KFNBUuODouODh+ODqynjgILmqJnmnKzmir3lh7roqqTlt67liIbmlaPjgavjgojjgaPjgabph43jgb/jgaXjgZHjgZfjgarjgYTjgIINCg0KcnN0YW7jgoLoqabjgZfjgZ/jgYTjgajjgZPjgo3jgaDjgYzjgIHoqIjnrpfmmYLplpPjgYzplbfjgZnjgY7jgovjga7jgafmlq3lv7XjgZfjgZ/jgIINCg0KYGBge3J9DQoNCmRmUmVzdWx0IDwtIGQuc3ViX0VzdGltYXRlRGF0YXNldDIuMShkLmRmRGVtb0RhdGEsIGQubWdOZWlnaGJvciwgYlZlcmJvc2U9RikNCg0KZGZQbG90IDwtIGRmUmVzdWx0ICU+JQ0KICBmaWx0ZXIoblNpemUgPT0gMTApICU+JQ0KICBkcGx5cjo6c2VsZWN0KG5BcmVhLCBuU2l6ZSwgZ1RydWUsIHN0YXJ0c193aXRoKCJnRXN0XyIpKSAlPiUNCiAgYXJyYW5nZSgtZ1RydWUpICU+JQ0KICBtdXRhdGUoZkFyZWEgPSBmYWN0b3IobkFyZWEsIGxldmVscz1uQXJlYSwgbGFiZWxzPWFzLmNoYXJhY3RlcihuQXJlYSkpKSAlPiUNCiAgcmVuYW1lKGdFc3RfVHJ1ZSA9IGdUcnVlKSAlPiUNCiAgZ2F0aGVyKHNWYXIsIGdWYWx1ZSwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBzZXBhcmF0ZShzVmFyLCBjKCJzVmFyMSIsICJzRXN0aW1hdG9yIikpICU+JQ0KICBtdXRhdGUoZkVzdGltYXRvciA9IGQuc3ViX0VzdGltYXRvckFzRmFjdG9yLjEoc0VzdGltYXRvcikpDQoNCmcgPC0gZ2dwbG90KGRhdGE9ZGZQbG90LCBhZXMoeD1mQXJlYSwgeT1nVmFsdWUsIGdyb3VwPWZFc3RpbWF0b3IsIGNvbG9yPWZFc3RpbWF0b3IpKQ0KZyA8LSBnICsgZ2VvbV9wYXRoKHNpemU9MSkNCmcgPC0gZyArIGxhYnMoDQogIHggICAgID0gImFyZWEgKG9mIHNhbXBsZSBzaXplID09IDEwKSIsIA0KICB5ICAgICA9IGV4cHJlc3Npb24ocGFzdGUodGhldGEsICIgb3IgIiwgaGF0KHRoZXRhKSkpLCANCiAgY29sb3IgPSAiRXN0aW1hdG9yIg0KKQ0KZyA8LSBnICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGQuc3ViX0VzdGltYXRvclBhbGV0dGUuMShkZlBsb3QkZkVzdGltYXRvcikpDQpnIDwtIGcgKyB0aGVtZV9idygpDQpwcmludChnKQ0KDQpgYGANCg0K5LiK44Gu5Zuz44Gv44CB5qiZ5pys44K144Kk44K6MTDjga7lnLDln5/jga7jgb/jgavjgaTjgYTjgabjgIHnnJ/lgKQkXHRoZXRhX2kgPSB2X2kk44Gq44KJ44Gz44Gr44Gd44Gu5o6o5a6a5YCk44KSDQrnpLrjgZfjgZ/jgoLjga7jgafjgYLjgovjgILnnJ/lgKTjgYzpq5jjgYTpoIbjgavkuKbjgbnjgabjgYLjgovjgIINCg0Kc3BkZXDjgavjgojjgovmjqjlrprlgKTjga/jgIHnnJ/lgKTjgojjgorjgoLjgZrjgaPjgajlhajkvZPlubPlnYfjgavov5HjgYTmjqjlrprlgKTjgajjgarjgaPjgabjgYTjgovjgIINCuOBr+OBo+OBjeOCiuOBhOOBo+OBpuOBvOOCjeiyoOOBkeOBp+OBguOCi+OAgg0KDQpzYWXjgavjgojjgovmjqjlrprlgKTjga/nm7TmjqXmjqjlrpoo5qiZ5pys5bmz5Z2HKeOBq+i/keOBhOOAguOBvuOBn+OAgeepuumWk+ebuOmWouOCkuiAg+aFruOBl+OCiOOBhuOBjOOBl+OBvuOBhOOBjOOAgQ0K57WQ5p6c44Gv44Gf44GE44GX44Gm5aSJ44KP44KJ44Gq44GE44CCDQoNCi4uLiDjgoLjgaPjgajjgoLjgIHjgZPjga7ntZDmnpzjga/jgZ/jgb7jgZ/jgb7jgYvjgoLjgZfjgozjgarjgYTjgIIgDQrlkIzjgZjjgZPjgajjgpLkvZXluqbjgoLnubDjgorov5TjgZfjgabjgb/jgarjgYTjgajjgIHjgarjgpPjgajjgoLjgYTjgYjjgarjgYTjgIINCg0KIyMjIDQuMy40IOaomeacrOOCteOCpOOCuiB2cy4g5o6o5a6a44Gu57K+5bqmDQoNCuOBiuW+heOBn+OBm+OBl+OBvuOBl+OBn+OAgue5sOOCiui/lOOBl+OBvuOBmeOAgg0KDQrjgZXjgY3jgbvjganjgajlkIzjgZjjgY/jgIENCuWcsOWfn+aVsOOCkiQxMCBcdGltZXMgMTAgPSAxMDAkLCDlnLDln5/lirnmnpzjga7liIbmlaMkXHNpZ21hX3VeMiTjgpI1MCwgDQrlnLDln5/lirnmnpzjga7liIbmlaMkXHNpZ21hX3VeMiTjgpI1MCwgDQrnqbrplpPoh6rlt7Hnm7jplqLjg5Hjg6njg6Hjg7zjgr8kXHBoaSTjgpIwLjfjgajjgZnjgovjgIINCjUwMOWbnue5sOOCiui/lOOBmeOAgg0KDQpgYGB7cn0NCg0KIyBzZXQuc2VlZCgxMDApDQojIGQuZGZTaW1EYXRhMSA8LSBkLnN1Yl9HZW5lcmF0ZU11bHRpRGF0YXNldDIuMSgNCiMgICAgIG5OdW1EYXRhc2V0ID0gNTAwLA0KIyAgICAgbWdOQiAgICAgICAgPSBkLm1nTmVpZ2hib3IsDQojICAgICBnVmFyVSAgICAgICA9IDUwLA0KIyAgICAgZ1BoaSAgICAgICAgPSAwLjcNCiMgICApDQojIGQuZGZTaW11bGF0aW9uMSA8LSBkLnN1Yl9Fc3RpbWF0ZU11bHRpRGF0YXNldDIuMSgNCiMgICBkZk11bHRpRGF0YSA9IGQuZGZTaW1EYXRhMSwNCiMgICBtZ05CICAgICAgICA9IGQubWdOZWlnaGJvcg0KIyApDQojIHNhdmUoZC5kZlNpbXVsYXRpb24xLCBmaWxlPSIuL2RfZGZTaW11bGF0aW9uMS5SRGF0YSIpDQpsb2FkKCIuL2RfZGZTaW11bGF0aW9uMS5SRGF0YSIpDQoNCmBgYA0KDQoNCuaOqOWumuWApOOBr+OBqeOBruOBj+OCieOBhOOBguOBpuOBq+OBquOCi+OBi+OAgg0KYGBge3J9DQpkZlBsb3QgPC0gZC5kZlNpbXVsYXRpb24xICU+JQ0KICBkcGx5cjo6c2VsZWN0KG5TaXplLCBnVHJ1ZSwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBnYXRoZXIoc1ZhciwgZ0VzdCwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBzZXBhcmF0ZShzVmFyLCBjKCJzVmFyMSIsICJzRXN0aW1hdG9yIikpICU+JQ0KICBtdXRhdGUoDQogICAgZ0RpZmYgICAgICA9IGdFc3QgLSBnVHJ1ZSwgDQogICAgZkVzdGltYXRvciA9IGQuc3ViX0VzdGltYXRvckFzRmFjdG9yLjEoc0VzdGltYXRvcikNCiAgKSANCmcgPC0gZ2dwbG90KGRhdGE9ZGZQbG90LCBhZXMoeCA9IG5TaXplLCB5PWdEaWZmLCBjb2xvcj1mRXN0aW1hdG9yKSkgDQpnIDwtIGcgKyBnZW9tX3BvaW50KGFscGhhPTEvNSkNCmcgPC0gZyArIGxhYnMoDQogIHggICAgID0gIlNhbXBsZSBTaXplIiwgDQogIHkgICAgID0gZXhwcmVzc2lvbihoYXQodGhldGEpLXRoZXRhKSwgDQogIGNvbG9yID0gIkVzdGltYXRvciINCikNCmcgPC0gZyArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApDQpnIDwtIGcgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwLCAxMDAsIGJ5ID0gMjApKQ0KZyA8LSBnICsgc2NhbGVfY29sb3JfbWFudWFsKA0KICBndWlkZSA9IEZBTFNFLCANCiAgdmFsdWVzID0gZC5zdWJfRXN0aW1hdG9yUGFsZXR0ZS4xKGRmUGxvdCRmRXN0aW1hdG9yKQ0KKQ0KZyA8LSBnICsgZmFjZXRfZ3JpZCh+IGZFc3RpbWF0b3IpDQpnIDwtIGcgKyB0aGVtZV9idygpDQpwcmludChnKQ0KYGBgDQoNCue4pui7uOOBr+OAgeaOqOWumuWApOOBqOecn+WApOOBqOOBruW3ruOCkuihqOOBl+OBpuOBhOOCi+OAgg0KDQrjgb7jgZrjgb/jgabjgajjgozjgovjga7jga/jgIHmrKHjga7ngrnjgafjgYLjgovvvJoNCioqc3BkZXAhISDjgYrjgb7jgYjjga/jg4Djg6HjgarlrZAhISoqDQoNCuOBvuOAgXNwZGVw44GuZXJyb3JzYXJsbSgp44Go44GE44GG44Gu44Gv56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgajjga/pgZXjgYbjga7jgaDjgo3jgYbjgIINCuOBquOBhOOBl+OAgeengeOBruS9v+OBhOaWueOBjOmWk+mBleOBo+OBpuOBhOOCi+OBruOBoOOCjeOBhuOAgg0K44Go44KC44GC44KM44CB5Lul5LiL44Gn44Gvc3BkZXDjga7ntZDmnpzjga/nnIHnlaXjgZnjgovjgIINCg0K5o6o5a6a5YCk44Go5q2j6Kej44Go44Gu5beu44KS6ZuG6KiI44GZ44KL44Go44CBDQoNCmBgYHtyfQ0KZGZQbG90IDwtIGQuZGZTaW11bGF0aW9uMSAlPiUNCiAgZHBseXI6OnNlbGVjdChuU2l6ZSwgZ1RydWUsIGdFc3RfRGlyZWN0LCBnRXN0X3NhZUZILCBnRXN0X3NhZVNGSCkgJT4lDQogIGdhdGhlcihzVmFyLCBnRXN0LCBzdGFydHNfd2l0aCgiZ0VzdF8iKSkgJT4lDQogIHNlcGFyYXRlKHNWYXIsIGMoInNWYXIxIiwgInNFc3RpbWF0b3IiKSkgJT4lDQogIGdyb3VwX2J5KHNFc3RpbWF0b3IsIG5TaXplKSAlPiUNCiAgc3VtbWFyaXplKA0KICAgIG5GcmVxID0gbigpLA0KICAgIGdSTVNFID0gc3FydChtZWFuKChnRXN0IC0gZ1RydWUpXjIpKQ0KICApICU+JQ0KICB1bmdyb3VwKCkgJT4lDQogIG11dGF0ZSgNCiAgICBmRXN0aW1hdG9yID0gZC5zdWJfRXN0aW1hdG9yQXNGYWN0b3IuMShzRXN0aW1hdG9yKQ0KICApIA0KZyA8LSBnZ3Bsb3QoZGF0YT1kZlBsb3QsIGFlcyh4ID0gblNpemUsIHk9Z1JNU0UsIGdyb3VwPWZFc3RpbWF0b3IsIGNvbG9yPWZFc3RpbWF0b3IpKSANCmcgPC0gZyArIGdlb21fcGF0aChzaXplPTEpDQpnIDwtIGcgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwLCAxMDAsIGJ5ID0gMTApKQ0KZyA8LSBnICsgbGFicyh4ID0gIlNhbXBsZSBTaXplIiwgeSA9ICJvYnNlcnZlZCBSTVNFIiwgY29sb3I9IkVzdGltYXRvciIpDQpnIDwtIGcgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gZC5zdWJfRXN0aW1hdG9yUGFsZXR0ZS4xKGRmUGxvdCRmRXN0aW1hdG9yKSkNCmcgPC0gZyArIHRoZW1lX2J3KCkNCnByaW50KGcpDQpgYGANCue4pui7uOOBr+OAjOaOqOWumuWApOOBqOato+ino+OBqOOBruW3ruOBruS6jOS5l+OBruW5s+Wdh+OBruW5s+aWueagueOAjShSTVNFKeOCkuekuuOBmeOAguW5s+OBn+OBj+iogOOBo+OBoeOCg+OBhuOBqOOAgSDmjqjlrprjgZfjgZ/lnLDln5/lubPlnYfjga/jgIHnnJ/jga7lnLDln5/lubPlnYfjgYvjgonjgaDjgYTjgZ/jgYTkvZXngrnjgY/jgonjgYTjgZrjgozjgovjgYvjgIHjgpLnpLrjgZfjgabjgYTjgovjgIINCg0K5qiZ5pys44K144Kk44K644GMMTDjga7jgajjgY3jgavjga/jgIHjgaDjgYTjgZ/jgYQz54K544GP44KJ44GE44Ga44KM44Gm44GX44G+44GG44CCIA0K5qiZ5pys44K144Kk44K644GM5aSn44GN44GP44Gq44KL44Go44CB44Ga44KM44Gv5bCP44GV44GP44Gq44KL44CCDQoNCuOBk+OBk+OBp+mWouW/g+OBjOOBguOCi+OBruOBr+aOqOWumumHj+OBrumWk+OBruW3ruOBoOOAguaLoeWkp+OBl+OBvuOBmeOAgg0KDQpgYGB7cn0NCmRmUGxvdCA8LSBkLmRmU2ltdWxhdGlvbjEgJT4lDQogIGRwbHlyOjpzZWxlY3QoblNpemUsIGdUcnVlLCBnRXN0X0RpcmVjdCwgZ0VzdF9zYWVGSCwgZ0VzdF9zYWVTRkgpICU+JQ0KICBnYXRoZXIoc1ZhciwgZ0VzdCwgc3RhcnRzX3dpdGgoImdFc3RfIikpICU+JQ0KICBzZXBhcmF0ZShzVmFyLCBjKCJzVmFyMSIsICJzRXN0aW1hdG9yIikpICU+JQ0KICBncm91cF9ieShzRXN0aW1hdG9yLCBuU2l6ZSkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBnUk1TRSA9IHNxcnQobWVhbigoZ0VzdCAtIGdUcnVlKV4yKSkNCiAgKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBtdXRhdGUoDQogICAgZ1JhdGlvID0gZ1JNU0UgLyBzcXJ0KDEwMC9uU2l6ZSksDQogICAgZkVzdGltYXRvciA9IGQuc3ViX0VzdGltYXRvckFzRmFjdG9yLjEoc0VzdGltYXRvcikNCiAgKSANCmcgPC0gZ2dwbG90KGRhdGE9ZGZQbG90LCBhZXMoeCA9IG5TaXplLCB5PWdSYXRpbywgZ3JvdXA9ZkVzdGltYXRvciwgY29sb3I9ZkVzdGltYXRvcikpIA0KZyA8LSBnICsgZ2VvbV9wYXRoKHNpemU9MSkNCmcgPC0gZyArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEpDQpnIDwtIGcgKyBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwLCAxMDAsIGJ5ID0gMTApKQ0KZyA8LSBnICsgbGFicygNCiAgeCA9ICJTYW1wbGUgU2l6ZSIsDQogIHkgPSAiKG9ic2VydmVkIFJNU0UpLyh0aGVvcmV0aWNhbCBSTVNFIG9mIERpcmVjdCkiLCANCiAgY29sb3IgPSAiRXN0aW1hdG9yIg0KKQ0KZyA8LSBnICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGQuc3ViX0VzdGltYXRvclBhbGV0dGUuMShkZlBsb3QkZkVzdGltYXRvcikpDQpnIDwtIGcgKyB0aGVtZV9idygpDQpwcmludChnKQ0KYGBgDQrmqJnmnKzmir3lh7roqqTlt67jga/lrp/jga8xMDDjgarjga7jgafjgIEg5qiZ5pys5bmz5Z2H44Gu55yf44GuUk1TReOBryRcc3FydHsxMDAvbl9pfSTjgafjgYLjgovjgIIg44GT44KM44KS5Z+65rqW44Gr44CB44Gd44KM44Ge44KM44Gu44OR44OD44Kx44O844K444Gr44KI44KL5o6o5a6a5YCk44GuIFJNU0XjgpLmr5TjgafooajjgZfjgabjgYTjgovjgILkuIvjgavjgYTjgY/jgbvjganjgIHmjqjlrprlgKTjgajnnJ/jga7lgKTjga7jgZrjgozjgYzlsI/jgZXjgYTjgIINCg0K44GT44Gu44KI44GG44Gr44CBKirnqbrplpPnm7jplqLjgpLogIPmha7jgZnjgovjgZPjgajjgafjgIHmjqjlrprlgKTjgajnnJ/jga7lgKTjga7jgZrjgozjgYzlsI/jgZXjgY/jgarjgosqKg0K44GT44Go44GM44KP44GL44KL44CC5qiZ5pys44K144Kk44K644GM5bCP44GV44GE44Go44GN44Gr5Yq55p6c44GM5aSn44GN44GE44CCDQoNCk1TReOBq+OBpOOBhOOBpuOCguOBv+OBpuOBiuOBk+OBhuOAgg0KYGBge3J9DQpkZlBsb3QgPC0gZC5kZlNpbXVsYXRpb24xICU+JQ0KICBkcGx5cjo6c2VsZWN0KA0KICAgIG5TaXplLCBnVHJ1ZSwgDQogICAgZ0VzdF9EaXJlY3QsIGdFc3Rfc2FlRkgsIGdFc3Rfc2FlU0ZILCANCiAgICBnTVNFX0RpcmVjdCwgZ01TRV9zYWVGSCwgZ01TRV9zYWVTRkgNCiAgKSAlPiUNCiAgZ2F0aGVyKHNWYXIsIGdWYWx1ZSwgYyhzdGFydHNfd2l0aCgiZ0VzdF8iKSwgc3RhcnRzX3dpdGgoImdNU0VfIikpKSAlPiUNCiAgc2VwYXJhdGUoc1ZhciwgYygic1ZhciIsICJzRXN0aW1hdG9yIikpICU+JQ0KICBzcHJlYWQoc1ZhciwgZ1ZhbHVlKSAlPiUNCiAgbXV0YXRlKA0KICAgIGdUcnVlU0UgPSAoZ0VzdCAtIGdUcnVlKV4yLCANCiAgICBnRGlmZiAgID0gZ01TRSAtIGdUcnVlU0UgDQogICkgJT4lIA0KICBncm91cF9ieShzRXN0aW1hdG9yLCBuU2l6ZSkgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBnTWVhbkRpZmYgPSBtZWFuKGdEaWZmKQ0KICApICU+JQ0KICB1bmdyb3VwKCkgJT4lDQogIG11dGF0ZSgNCiAgICBmRXN0aW1hdG9yID0gZC5zdWJfRXN0aW1hdG9yQXNGYWN0b3IuMShzRXN0aW1hdG9yKQ0KICApIA0KDQpnIDwtIGdncGxvdChkYXRhPWRmUGxvdCwgYWVzKHggPSBuU2l6ZSwgeT1nTWVhbkRpZmYsIGdyb3VwPWZFc3RpbWF0b3IsIGNvbG9yPWZFc3RpbWF0b3IpKSANCmcgPC0gZyArIGdlb21fcGF0aChzaXplPTEpDQpnIDwtIGcgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKQ0KZyA8LSBnICsgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgxMCwgMTAwLCBieSA9IDEwKSkNCmcgPC0gZyArIGxhYnMoDQogIHggPSAiU2FtcGxlIFNpemUiLCANCiAgeSA9ICJtZWFuICgoRXN0aW1hdGVkIE1TRSktKEFjdHVhbCBTcS5FcnIpKSIsIA0KICBjb2xvciA9ICJFc3RpbWF0b3IiDQopDQpnIDwtIGcgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gZC5zdWJfRXN0aW1hdG9yUGFsZXR0ZS4xKGRmUGxvdCRmRXN0aW1hdG9yKSkNCmcgPC0gZyArIHRoZW1lX2J3KCkNCnByaW50KGcpDQpgYGANCg0K57im6Lu444Gv44CB44CM5o6o5a6a44GV44KM44GfTVNF44GL44KJ44CB5o6o5a6a5YCk44Go5q2j6Kej44Go44Gu5beu44Gu5LqM5LmX44KS5byV44GE44Gf5YCk44CN44Gu5bmz5Z2H44Gn44GC44KL44CCIOOBpOOBvuOCiuOAgeato+OBruWApOOBr01TReOBruaOqOWumuOBjOamguOBl+OBpumBjuWkp+OBp+OBguOCi+OBk+OBqOOAgSDosqDjga7lgKTjga/mpoLjgZfjgabpgY7lsI/jgafjgYLjgovjgZPjgajjgpLooajjgZnjgIINCg0KMy4zLjTjgafnorroqo3jgZfjgZ/jgojjgYbjgavjgIENCuaomeacrOOCteOCpOOCuuOBjOWwj+OBleOBhOaZguOAgUJMVVDmjqjlrprjga5NU0Xjga7mjqjlrprjga/pgY7lsI/jgavjgarjgovjgIINCuOBk+OBk+OBp+OCj+OBi+OCi+OBruOBr+OAgSoq56m66ZaT55u46Zai44KS6ICD5oWu44GZ44KL44Go44GV44KJ44Gr6YGO5bCP44Gr44Gq44KLKirjgajjgYTjgYbjgZPjgajjgafjgYLjgovjgIINCg0K44Gk44G+44KK44GT44GG44GE44GG44GT44Go44Gg44CCDQrmqJnmnKzjgrXjgqTjgrrjgYzlsI/jgZXjgYTjgajjgY3jgIHnqbrplpPnm7jplqLjgpLmraPjgZfjgY/ogIPmha7jgZnjgovjgZPjgajjgafjgIHnnJ/lgKTjgajmjqjlrprlgKTjgajjga4NCuOBmuOCjOOBr+Wwj+OBleOBj+OBquOCiyjmjqjlrprph4/jga7nnJ/jga5NU0Xjga/kuIvjgYzjgosp44CC44GE44Gj44G944GG44CB55yf5YCk44Go5o6o5a6a5YCk44Go44GuDQrjgZrjgozjgavlr77jgZnjgovmjqjlrpoo5o6o5a6a6YeP44GuTVNF44Gu5o6o5a6aKeOBr+OAgeOCguOBqOOCguOBqOmBjuW6puOBq+alveims+eahOOBoOOBo+OBn+OBruOBjOOAgQ0K44GV44KJ44Gr5qW96Kaz55qE44Gr44Gq44Gj44Gm44GX44G+44GG44KP44GR44Gg44CC44G444O877yBDQoNCiMjIyA0LjMuNSDnqbrplpPnm7jplqLjga7lvLfjgZUgdnMuIOaOqOWumuOBrueyvuW6pg0KDQrku4rluqbjga/jgIHnqbrplpPnm7jplqLjga7lvLfjgZXjgajmjqjlrprjga7nsr7luqbjga7plqLkv4LjgavjgaTjgYTjgaboqr/jgbnjgabjgb/jgZ/jgYTjgIINCg0K5Zyw5Z+f5Yq55p6c44Gu5YiG5pWjJFxzaWdtYV91XjIk44KSNTAsIA0K56m66ZaT6Ieq5bex55u46Zai44OR44Op44Oh44O844K/JFxwaGkk44KSMC4344Go44GZ44KL44CCDQrnqbrplpPoh6rlt7Hnm7jplqLjg5Hjg6njg6Hjg7zjgr8kXHBoaSTjgpIwLCAwLjEsIDAuMiwgLi4uLCAwLjjjgajlpInjgYjjgarjgYzjgonjgIENCuODh+ODvOOCv+eUn+aIkOOBqOWIhuaekOOCkjUwMOippuihjOe5sOOCiui/lOOBl+OBn+OAgg0K5o6o5a6a5pa55rOV44Gvc2Fl44OR44OD44Kx44O844K444Gu44G/44CBMueorumhnuOBqOOBmeOCi+OAgg0KDQpgYGB7cn0NCg0KIyBzZXQuc2VlZCgxMjMpDQojIGxPdXQgPC0gbGFwcGx5KA0KIyAgIHNlcShmcm9tPTAsIHRvPTAuOCwgYnkgPSAwLjEpLA0KIyAgIGZ1bmN0aW9uKGdQaGkpew0KIyAgICAgY2F0KCJnUGhpID0gIiwgZ1BoaSwgIi4uLiIpDQojICAgICBvdXQgPC0gZC5zdWJfR2VuZXJhdGVNdWx0aURhdGFzZXQyLjEoDQojICAgICAgIG5OdW1EYXRhc2V0ID0gNTAwLA0KIyAgICAgICBtZ05CICAgICAgICA9IGQubWdOZWlnaGJvciwNCiMgICAgICAgZ1ZhclUgICAgICAgPSA1MCwNCiMgICAgICAgZ1BoaSAgICAgICAgPSBnUGhpDQojICAgICApDQojICAgICBvdXQkZ1BoaSA8LSBnUGhpDQojICAgICBjYXQoIlxuIikNCiMgICAgIHJldHVybihvdXQpDQojICAgfQ0KIyApDQojIGQuZGZTaW1EYXRhMiA8LSBiaW5kX3Jvd3MobE91dCkNCiMgDQojIGQuZGZTaW11bGF0aW9uMiA8LSBkLmRmU2ltRGF0YTIgJT4lDQojICAgZ3JvdXBfYnkoZ1BoaSkgJT4lDQojICAgZHBseXI6OmRvKA0KIyAgICAgZC5zdWJfRXN0aW1hdGVNdWx0aURhdGFzZXQyLjEoDQojICAgICAgIGRmTXVsdGlEYXRhID0gLiwNCiMgICAgICAgbWdOQiAgICAgPSBkLm1nTmVpZ2hib3IsDQojICAgICAgIGFzTWV0aG9kID0gYygic2FlRkgiLCAic2FlU0ZIIikNCiMgICAgICkNCiMgICApICU+JQ0KIyAgIHVuZ3JvdXAoKQ0KIyBzYXZlKGQuZGZTaW11bGF0aW9uMiwgZmlsZT0iLi9kX2RmU2ltdWxhdGlvbjIuUkRhdGEiKQ0KbG9hZCgiLi9kX2RmU2ltdWxhdGlvbjIuUkRhdGEiKQ0KDQpgYGANCg0K44G+44Ga44Gv5o6o5a6a44Gu57K+5bqm44GL44KJ44CC44GT44GT44Gn44Gv44CBDQoqKuaomeacrOOCteOCpOOCujEw44Gu5Zyw5Z+f44Gu44G/44Gr5rOo55uu44GZ44KLKirjgILlkIToqabooYzjgavjgaTjgYTjgaYxMOWcsOWfn+OCkuWIqeeUqOOBp+OBjeOCi+OAgg0KDQpgYGB7cn0NCmRmUGxvdCA8LSBkLmRmU2ltdWxhdGlvbjIgJT4lDQogIGZpbHRlcihuU2l6ZSA9PSAxMCkgJT4lDQogIGRwbHlyOjpzZWxlY3QoZ1BoaSwgZ1RydWUsIHN0YXJ0c193aXRoKCJnRXN0XyIpKSAlPiUNCiAgZ2F0aGVyKHNWYXIsIGdFc3QsIHN0YXJ0c193aXRoKCJnRXN0XyIpKSAlPiUNCiAgc2VwYXJhdGUoc1ZhciwgYygic1ZhcjEiLCAic0VzdGltYXRvciIpKSAlPiUNCiAgZ3JvdXBfYnkoZ1BoaSwgc0VzdGltYXRvcikgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBnUk1TRSA9IG1lYW4oKGdUcnVlLWdFc3QpXjIpDQogICkgJT4lDQogIHVuZ3JvdXAoKSAlPiUgDQogIG11dGF0ZSgNCiAgICBmRXN0aW1hdG9yID0gZC5zdWJfRXN0aW1hdG9yQXNGYWN0b3IuMShzRXN0aW1hdG9yKQ0KICApIA0KIyMgcHJpbnQoZGZQbG90KQ0KDQpnIDwtIGdncGxvdChkYXRhPWRmUGxvdCwgYWVzKHg9Z1BoaSwgeSA9IGdSTVNFLCBjb2xvcj1mRXN0aW1hdG9yLCBncm91cD1mRXN0aW1hdG9yKSkNCmcgPC0gZyArIGdlb21fcGF0aChzaXplPTEpDQpnIDwtIGcgKyBsYWJzKHggPSBleHByZXNzaW9uKHBoaSksIHkgPSAib2JzZXJ2ZWQgUk1TRSIsIGNvbG9yPSJFc3RpbWF0b3IiKQ0KZyA8LSBnICsgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGQuc3ViX0VzdGltYXRvclBhbGV0dGUuMShkZlBsb3QkZkVzdGltYXRvcikpDQpnIDwtIGcgKyB0aGVtZV9idygpDQpwcmludChnKQ0KDQoNCmBgYA0K57im6Lu444Gv44CM5o6o5a6a5YCk44Go5q2j6Kej44Go44Gu5beu44Gu5LqM5LmX44Gu5bmz5Z2H44Gu5bmz5pa55qC544CNKFJNU0Up44KS56S644GZ44CC5bmz44Gf44GP6KiA44Gj44Gh44KD44GG44Go44CBIOaOqOWumuOBl+OBn+WcsOWfn+W5s+Wdh+OBr+OAgeecn+OBruWcsOWfn+W5s+Wdh+OBi+OCieOBoOOBhOOBn+OBhOS9leeCueOBj+OCieOBhOOBmuOCjOOCi+OBi+OAgeOCkuekuuOBl+OBpuOBhOOCi+OAgg0KDQrnqbrplpPoh6rlt7Hnm7jplqLjg5Hjg6njg6Hjg7zjgr8kXHBoaSTjgYwwLjLku6XkuIvjga7jgajjgY3jga/jgIENCuepuumWk+ebuOmWouOCkuiAg+aFruOBl+OBquOBhOOBu+OBhuOBjOOAgeaOqOWumuWApOOBqOecn+WApOOBruOBmuOCjOOBjOOCj+OBmuOBi+OBq+Wwj+OBleOBhOOAgg0K44GE44Gj44G944GGMC4z5Lul5LiK44Gr44Gq44KL44Go44CB56m66ZaT55u46Zai44KS6ICD5oWu44GZ44KL44GT44Go44Gr44KI44Gj44Gm44CB5o6o5a6a5YCk44Gu57K+5bqm44GM6auY44GP44Gq44KL44CCDQoNCuOBp+OBr+OAgSRccGhpJOOBruWkp+OBjeOBleOCkuefpeOCi+OBk+OBqOOBr+OBp+OBjeOCi+OBruOBi+OAgg0K44GT44KT44Gp44GvJFxwaGkk44Gu5o6o5a6a5YCk44Gr44Gk44GE44Gm6Kq/44G544Gm44G/44KI44GG44CCDQpgYGB7cn0NCmRmUGxvdDEgPC0gZC5kZlNpbXVsYXRpb24yICU+JQ0KICBmaWx0ZXIobkFyZWEgPT0gMSkgJT4lDQogIGRwbHlyOjpzZWxlY3QoZ1BoaSwgZ1NDb3JyX3NhZVNGSCkgDQpkZlBsb3QyIDwtIGRmUGxvdDEgJT4lDQogIGdyb3VwX2J5KGdQaGkpICU+JQ0KICBzdW1tYXJpemUoZ01lYW4gPSBtZWFuKGdTQ29ycl9zYWVTRkgpKSAlPiUNCiAgdW5ncm91cCgpDQoNCmcgPC0gZ2dwbG90KGRhdGE9ZGZQbG90MiwgYWVzKHggPSBnUGhpLCB5ID0gZ01lYW4pKQ0KZyA8LSBnICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKQ0KZyA8LSBnICsgZ2VvbV92aW9saW4oZGF0YT1kZlBsb3QxLCBhZXMoeT1nU0NvcnJfc2FlU0ZILCBncm91cCA9IGdQaGkpKQ0KIyBnIDwtIGcgKyBnZW9tX3BvaW50KGRhdGE9ZGZQbG90MSwgYWVzKHk9Z1NDb3JyX3NhZVNGSCksIHNpemU9MSwgYWxwaGE9MS8xMCkNCmcgPC0gZyArIGdlb21fcG9pbnQoc2l6ZT01KQ0KZyA8LSBnICsgbGFicyh4ID0gZXhwcmVzc2lvbihwaGkpLCB5ID0gZXhwcmVzc2lvbihwYXN0ZSgiZXN0aW1hdGVkICIsIHBoaSkpKQ0KZyA8LSBnICsgdGhlbWVfYncoKQ0KcHJpbnQoZykNCmBgYA0K5qiq6Lu444Gv56m66ZaT6Ieq5bex55u46Zai44OR44Op44Oh44O844K/44Gu55yf5YCkJFxwaGkk44CB57im6Lu444Gvc2Fl44OR44OD44Kx44O844K4KOepuumWk0ZheS1IZXJyaW9044Oi44OH44OrKeOBqw0K44KI44KL44Gd44Gu5o6o5a6a5YCk44CCDQrliIbluIMo44OQ44Kk44Kq44Oq44Oz44OX44Ot44OD44OIKeOBqOW5s+Wdhyjpu5LkuLgp44KS56S644GX44Gm44GE44KL44CCDQoNCiRccGhpJOOBruaOqOWumuOBr+OAgeW5s+Wdh+OBmeOCi+OBqOato+OBl+OBhOOBjOOAgeOBi+OBquOCiuOBsOOCieOBpOOBjeOBjOWkp+OBjeOBhOOAgiRccGhpJOOBjOS9juOBhOWgtOWQiOOBq+OBr+OAgQ0K44GV44KJ44Gr44Gw44KJ44Gk44GN44GM5aSn44GN44GP44Gq44KL44CCDQrjgaTjgb7jgorjgIHmqJnmnKzjgYvjgokkXHBoaSTjgpLnn6Xjgovjga7jga/pm6PjgZfjgYTjgo/jgZHjgaDjgIINCg0K5YW35L2T55qE44Gq5YiG5p6Q44Gu5aC06Z2i44Gn44CB56m66ZaT55u46Zai44KS6ICD5oWu44GZ44KL44GL44Gp44GG44GL44KS5qSc6KiO44GZ44KL6Zqb44Gr44Gv44CBDQrnqbrplpNGYXktSGVycmlvdOODouODh+ODq+OCkuaOqOWumuOBl+OBpiRccGhpJOOBruaOqOWumuWApOOCkuiqv+OBueOCi+OCiOOCiuOCguOAgQ0K56m66ZaT55u46Zai44KS6ICD5oWu44GZ44KL44Oi44OH44Or44Go6ICD5oWu44GX44Gq44GE44Oi44OH44Or44GuQUlD44KS5q+U6LyD44GZ44KL44GT44Go44GMDQrlpJrjgYTjga7jgafjga/jgarjgYTjgYvjgajmgJ3jgYbjgILoqabjgZfjgabjgb/jgojjgYbjgIINCg0KYGBge3J9DQpkZlBsb3QgPC0gZC5kZlNpbXVsYXRpb24yICU+JQ0KICBmaWx0ZXIobkFyZWEgPT0gMSkgJT4lDQogIG11dGF0ZShiV2luID0gaWZfZWxzZShnQUlDX3NhZVNGSCA8IGdBSUNfc2FlRkgsIDEsIDApKSAlPiUNCiAgZ3JvdXBfYnkoZ1BoaSkgJT4lDQogIHN1bW1hcml6ZShnV2luID0gbWVhbihiV2luKSkgJT4lDQogIHVuZ3JvdXAoKQ0KDQpnIDwtIGdncGxvdChkYXRhPWRmUGxvdCwgYWVzKHggPSBnUGhpLCB5ID0gZ1dpbikpDQpnIDwtIGcgKyBnZW9tX2NvbCgpDQpnIDwtIGcgKyBsYWJzKHggPSBleHByZXNzaW9uKHBoaSksIHkgPSAiUmF0aW8gb2Ygc2VsZWN0aW5nIHNwYXRpYWwgbW9kZWwiKQ0KZyA8LSBnICsgdGhlbWVfYncoKQ0KDQpwcmludChnKQ0KYGBgDQoNCue4pui7uOOBr+OAgeepuumWk+ebuOmWouOCkuiAg+aFruOBl+OBquOBhEZheS1IZXJyaW9044Oi44OH44Or44Go56m66ZaTRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgpLmr5TovIPjgZfjgZ/jgajjgY3jgIENCuW+jOiAheOBruOBu+OBhuOBjEFJQ+OBjOWwj+OBleOBj+OBquOBo+OBn+ippuihjOOBruWJsuWQiOOBp+OBguOCi+OAgg0KDQrjgZPjga7lm7PjgYvjgonjgo/jgYvjgovjgojjgYbjgavjgIHnnJ/jga7nqbrplpPnm7jplqLjgYzjgrzjg63jgafjgoLjgIENCuepuumWk0ZheS1IZXJyaW9044Oi44OH44Or44GuQUlD44Gu44G744GG44GM5L2O44GP44Gq44Gj44Gm44GX44G+44GG44GT44Go44KCDQrjgYLjgovjgILjgb7jgZ/jgIHnnJ/jga7nqbrplpPnm7jplqLjgYzlsI/jgZXjgYTjgajjgY3jgIHnqbrplpNGYXktSGVycmlvdOODouODh+ODq+OBrkFJQ+OBruOBu+OBhuOBjA0K5b+F44Ga5L2O44GP44Gq44KL44Go44KC6ZmQ44KJ44Gq44GE44CCDQropoHjgZnjgovjgavjgIHnqbrplpPnm7jplqLjgYzjgarjgYTjgIHjgarjgYTjgZflsI/jgZXjgYTjgajjgY3jgIHjgZ3jga7jgZPjgajjgpLmraPjgZfjgY/nn6Xjgovjga7jga8NCue1kOani+mbo+OBl+OBhOOAgg0KDQrjgaTjgYTjgafjgavjgIHnqbrplpPnm7jplqLjga7mnInnhKHjgavjgaTjgYTjgabjga7liKTmlq3jgpLoqqTjgorjgIHjgYbjgaPjgYvjgorlpInjgarjg6Ljg4fjg6vjgpLmjqHnlKjjgZfjgaHjgoPjgaPjgZ/jgokNCuOBquOBq+OBjOi1t+OBjeOCi+OBi+ippuOBl+OBpuOBv+OCiOOBhuOAgg0KDQpgYGB7cn0NCmRmUGxvdCA8LSBkLmRmU2ltdWxhdGlvbjIgJT4lDQogIGZpbHRlcihuU2l6ZSA9PSAxMCwgZ1BoaSA8IDAuNCApICU+JQ0KICBtdXRhdGUoYldpbiA9IGlmX2Vsc2UoZ0FJQ19zYWVTRkggPCBnQUlDX3NhZUZILCAxLCAwKSkgJT4lDQogIGRwbHlyOjpzZWxlY3QoZ1BoaSwgZ1RydWUsIGJXaW4sIHN0YXJ0c193aXRoKCJnRXN0XyIpKSAlPiUNCiAgZ2F0aGVyKHNWYXIsIGdFc3QsIHN0YXJ0c193aXRoKCJnRXN0XyIpKSAlPiUNCiAgc2VwYXJhdGUoc1ZhciwgYygic1ZhcjEiLCAic0VzdGltYXRvciIpKSAlPiUNCiAgZ3JvdXBfYnkoZ1BoaSwgc0VzdGltYXRvciwgYldpbikgJT4lDQogIHN1bW1hcml6ZSgNCiAgICBnUk1TRSA9IG1lYW4oKGdUcnVlLWdFc3QpXjIpDQogICkgJT4lDQogIHVuZ3JvdXAoKSAlPiUgDQogIG11dGF0ZSgNCiAgICBmV2luICAgICAgID0gZmFjdG9yKGJXaW4sIGxldmVscz1jKDAsMSksIGxhYmVscz1jKCJ3L28gc2MiLCAidy8gc2MiKSksDQogICAgZkVzdGltYXRvciA9IGQuc3ViX0VzdGltYXRvckFzRmFjdG9yLjEoc0VzdGltYXRvcikNCiAgKSANCiMgcHJpbnQoZGZQbG90KQ0KDQpnIDwtIGdncGxvdChkYXRhPWRmUGxvdCwgYWVzKHg9ZldpbiwgeSA9IGdSTVNFLCBjb2xvcj1mRXN0aW1hdG9yLCBncm91cD1mRXN0aW1hdG9yKSkNCmcgPC0gZyArIGdlb21fcGF0aChzaXplPTEpDQpnIDwtIGcgKyBsYWJzKHggPSAic2VsZWN0ZWQgbW9kZWwiLCB5ID0gIm9ic2VydmVkIFJNU0UiLCBjb2xvcj0iRXN0aW1hdG9yIikNCmcgPC0gZyArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBkLnN1Yl9Fc3RpbWF0b3JQYWxldHRlLjEoZGZQbG90JGZFc3RpbWF0b3IpKQ0KZyA8LSBnICsgZmFjZXRfZ3JpZCh+Z1BoaSkNCmcgPC0gZyArIHRoZW1lX2J3KCkNCnByaW50KGcpDQoNCg0KYGBgDQoNCuODkeODjeODq+OBr+ecn+OBruepuumWk+iHquW3seebuOmWouODkeODqeODoeODvOOCv+OAguODkeODjeODq+WGheOBruW3puWBtOOBr+OAgQ0KQUlD44Gr44KI44Gj44Gm56m66ZaT55u46Zai44KS6ICD5oWu44GX44Gq44GE44Oi44OH44Or44GM5pSv5oyB44GV44KM44Gf6Kmm6KGM44CBDQrlj7PlgbTjga/jgIFBSUPjgavjgojjgaPjgabnqbrplpPnm7jplqLjgpLogIPmha7jgZnjgovjg6Ljg4fjg6vjgYzmlK/mjIHjgZXjgozjgZ/oqabooYzjgILnuKbou7jjga8NCuOAjOaOqOWumuWApOOBqOato+ino+OBqOOBruW3ruOBruS6jOS5l+OBruW5s+Wdh+OBruW5s+aWueagueOAjShSTVNFKeOBp+OAgeWwj+OBleOBhOOBu+OBhuOBjA0K5o6o5a6a5YCk44Gu57K+5bqm44GM6auY44GE44CCDQoNCuOBleOBjeOBu+OBqeOBruWIhuaekOOBp+OBr+OAgQ0K55yf44Gu56m66ZaT6Ieq5bex55u46Zai44OR44Op44Oh44O844K/44GMMC4y44G+44Gn44Gn44GC44KM44Gw56m66ZaT55u46Zai44KS6ICD5oWu44GX44Gq44GE44G744GG44GMDQrjgYTjgYTjgZfjgIHjgZ3jgozjgojjgorlpKfjgY3jgZHjgozjgbDnqbrplpPnm7jplqLjgpLogIPmha7jgZfjgZ/jgbvjgYbjgYzjgYTjgYTjgIHjgajjgYTjgYbjgZPjgajjgYwNCuOCj+OBi+OBo+OBn+OAguOBk+OBruWbs+OBi+OCieOBr+OAgeaJi+WFg+OBruODh+ODvOOCv+OBi+OCieW+l+OCieOCjOOBn0FJQ+OBjOOBqeOBhuOBp+OBguOCjA0KKOOBpOOBvuOCiuOAgeODkeODjeODq+WGheOBruW3puWBtOOBrueKtuazgeOBp+OBguOCjOWPs+WBtOOBrueKtuazgeOBp+OBguOCjCnjgIENCuWQjOOBmOOBk+OBqOOBjOOBhOOBiOOCi+OBruOBoOOAgeOBqOeiuuiqjeOBp+OBjeOCi+OAgg0KDQrjgZPjga7jgrfjg5/jg6Xjg6zjg7zjgrfjg6fjg7Pjga7nirbms4HjgavplqLjgZnjgovpmZDjgorjgIENCuepuumWk+ebuOmWouOBjOW8seOBhCgkXHBoaSTjgYwwLjLku6XkuIvjgaAp44Go44GE44GG56K65L+h44GM44GC44KL44Gq44KJ44Gw44CBDQrjgZ/jgajjgYhBSUPjgavjgojjgaPjgabnqbrplpNGYXktSGVycmlvdOODouODh+ODq+OBjOaUr+aMgeOBleOCjOOCiOOBhuOBjOOAgQ0K5pat5Zu644Go44GX44Gm44CB44Gf44Gg44GuRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgpLkvb/jgYbjgbnjgY3jgarjga7jgafjgYLjgovjgIINCg0KIyMjIDQuMy42IOOBvuOBqOOCgQ0KDQrjgZPjga7jgrfjg5/jg6Xjg6zjg7zjgrfjg6fjg7Pjgafjgo/jgYvjgaPjgZ/jgZPjgajjgpLjgb7jgajjgoHjgabjgYrjgY/jgIINCg0KLSBGYXktSGVycmlvdOODouODh+ODq+OBrkVCTFVQ5o6o5a6a44Gn44CB5Zyw5Z+f54m55oCn44Gu5o6o5a6a6YeP44GuTVNF44KS6Kej5p6Q55qE44Gr5rGC44KB44Gf44Go44GN44CBDQogICoqTVNF44Gv5qiZ5pys44K144Kk44K644GM5bCP44GV44GE5Zyw5Z+f44Gr44GK44GE44Gm6YGO5bCPKirjgafjgYLjgovjgILjgZPjga7lgr7lkJHjga/jgIENCiAgKirnqbrplpNGYXktSGVycmlvdOODouODh+ODq+OBp+OBr+OBleOCieOBq+W8t+OBj+OBquOCiyoq44CCDQotICoq56m66ZaT55u46Zai44GM5a2Y5Zyo44GX44Gq44GE5aC05ZCI44CB44Gq44GE44GX44GC44KL56iL5bqm5bCP44GV44GE5aC05ZCIKirjgavjga8NCiAgKOOBk+OBruOCt+ODn+ODpeODrOODvOOCt+ODp+ODs+OBrueKtuazgeOBp+OBryRccGhpPDAuMiTjga7jgajjgY0p44CBDQogIOepuumWk0ZheS1IZXJyaW9044Oi44OH44OrKFNBUuODouODh+ODqynjgpLkvb/jgYbjgojjgorjgIEqKuepuumWk+ebuOmWouOCkuiAg+aFruOBl+OBquOBhCoqDQogICoqRmF5LUhlcnJpb3Tjg6Ljg4fjg6vjgpLkvb/jgYbjgbvjgYbjgYzjgIHlnLDln5/nibnmgKfjga7mjqjlrprph4/jga7nsr7luqbjga/pq5jjgY/jgarjgosqKuOAgg0KLSDnqbrplpNGYXktSGVycmlvdOODouODh+ODqyhTQVLjg6Ljg4fjg6sp44KSc3BkZXDjg5Hjg4PjgrHjg7zjgrjjgafmjqjlrprjgZnjgovmlrnms5XjgavjgaTjgYTjgabjga/jgIENCiAg57WQ5bGA44KI44GP44KP44GL44KJ44Gq44GL44Gj44Gf44CC44Gp44Gq44Gf44GL44CB44OT44O844Or44Gn44KC44Gq44KT44Gn44KC44GK5aW944GN44Gq44KC44Gu44KSDQogIOWlouOCiuOBvuOBmeOBruOBp+OAgeaVmeOBiOOBpuOBj+OBoOOBleOCieOBquOBhOOBp+OBl+OCh+OBhuOBi+OAgg0KICANCmBgYHtyLCByZXN1bHRzPSJoaWRlIn0NCnJtKGxpc3Q9Z3JlcCgiXmRcXC4iLCBscygpLCB2YWx1ZT1UKSkNCmBgYA0KDQoNCjwhLS0g44OR44OD44Kx44O844K45re75LuY44Gu44K144Oz44OX44Or44OH44O844K/44Gw44GL44KK44Gn44Gv44Gp44GG44KC5a6f5oSf44GM44KP44GL44Gq44GE44Gu44Gn44CBIC0tPg0KPCEtLSDmgJ3jgYTkvZnjgaPjgaboh6rliIbjgafliIbmnpDnlKjjg4fjg7zjgr/jgpLkvZzjgaPjgabjgb/jgZ/jgILmnbHkuqzpg73nibnliKXljLrjga7nlJ/mtLvkv53orbfkuJbluK/mlbDjga7jg4fjg7zjgr/jgafjgYLjgovjgIIgLS0+DQo8IS0tIHNm44Kq44OW44K444Kn44Kv44OI44Gr44GX44Gm44GC44KL44CCUkRhdGHlvaLlvI/jgavjgZfjgZ/jgoLjga7jgpJ3ZWLjgavnva7jgYTjgabjgYrjgY3jgb7jgZko5LiL6KiY44Kz44O844OJ44KS5Y+C54WnKeOAgiAtLT4NCg0KPCEtLSDlkITlpInmlbDjgajjgZ3jga7lh7rlhbjjga/ku6XkuIvjga7pgJrjgorjgIIgLS0+DQoNCjwhLS0gLSBuSG91c2Vob2xkOiDkuJbluK/mlbDjgILmnbHkuqzpg73nt4/li5nlsYDntbHoqIjpg6jjgIxb5L2P5rCR5Z+65pys5Y+w5biz44Gr44KI44KL5p2x5Lqs6YO944Gu5LiW5biv44Go5Lq65Y+jXShodHRwOi8vd3d3LnRvdWtlaS5tZXRyby50b2t5by5qcC9qdXVraXkvanktaW5kZXguaHRtKeOAjeOAgeesrDHooajjgIzljLrluILnlLrmnZHliKXkuJbluK/mlbDjgI0sIOW5s+aIkDI45bm0LCDnt4/kuJbluK/mlbDjgIIgLS0+DQo8IS0tIC0gZ0VsZGVybHlSYXRpbzog6ICB5bm05Lq65Y+j5Ymy5ZCI44CC5ZCM5LiK44CB56ysOeihqOOAjOWMuuW4gueUuuadkeWIpeW5tOm9ou+8k+WMuuWIhuWIpeS6uuWPo+WPiuOBs+ani+aIkOavlOOAjSwg5ZCE5Yy65biC55S65p2R5Yil57eP5Lq65Y+j44Gr5Y2g44KB44KL6ICB5bm05Lq65Y+j77yI77yW77yV5q2z5Lul5LiK77yJ44Gu5Ymy5ZCIKO+8hSksIOW5s+aIkDI45bm0LCDkurrlj6Pnt4/mlbDjgavljaDjgoHjgovogIHlubTkurrlj6PlibLlkIgsIOe3j+aVsOOAgiAtLT4NCjwhLS0gLSBuV2FsZmFyZTog6KKr5L+d6K235LiW5biv5pWw44CC5p2x5Lqs6YO957eP5YuZ6YOo57Wx6KiI5bGA44CM5p2x5Lqs6YO957Wx6KiI5bm06ZGRIOW5s+aIkDI45bm044CNLCBbMTgg56S+5Lya5L+d6ZqcXShodHRwOi8vd3d3LnRvdWtlaS5tZXRyby50b2t5by5qcC90bmVua2FuLzIwMTYvdG4xNnEzaTAxOC5odG0pLCAxOC0yIOWcsOWfn+WIpeiiq+S/neitt+S4luW4r+aVsCwg6KKr5L+d6K235LiW5biv5pWw44CCIC0tPg0KPCEtLSAtIGdlb21ldHJ5OiDlooPnlYzmg4XloLEo44Od44Oq44K044Oz44OH44O844K/KeOAguOBquOBnOOBi+OBr+ioiuOBi+OBquOBhOOBp+OBu+OBl+OBhOOBruOBoOOBjOOAgeengeOBrlBD44Gr44Gv44CBIC0tPg0KPCEtLSAgIOaXpeacrOOBruWFqOOBpuOBruW4guWMuueUuuadkeOBruOAgeeUuuS4geebruODrOODmeODq+OBruWig+eVjOODh+ODvOOCv+OBjOOBr+OBhOOBo+OBpuOBhOOCiyjlubPmiJAyN+W5tOW6puWbveWLouiqv+afuyAtLT4NCjwhLS0gICDlsI/lnLDln5/looPnlYzmg4XloLHjgavjgojjgosp44CC44GT44GT44GL44KJ5p2x5Lqs6YO954m55Yil5Yy644Gu5aKD55WM44KS5YiH44KK5Ye644GX44Gf44KC44Gu44CCIC0tPg0KDQo+IOOBhOOBo+OBn+OCk+OBk+OCjOOBp+e1guS6huOBqOOBl+OBvuOBmeOAgue2muOBjeOBr+OBvuOBn+W+jOaXpS4uLg0K