T test x trung bình trừ nhau ra âm

Thân chào các bạn, đây là bài thực hành thứ 5 trong dự án Bayes for Vietnam. Mục tiêu của chúng tôi là phổ cập về phương pháp thống kê theo trường phái Bayes nhằm thay thế hoàn toàn những công cụ truyền thống. Đối tượng của chúng tôi là các bạn bác sĩ và sinh viên y khoa.

Đây cũng là lần đầu tiên một bài giảng có sự góp sức của tất cả 4 thành viên trong Core team của project. Trong những bài đi trước, Bs. Khả Nhi đã cùng các bạn đi qua 4 chặng đường, dùng Bayes thay thế cho Pearson’s r, Student t-test, Chisquared test và phân loại bằng hồi quy Logistic. Các bạn đã bắt đầu quen với cấu trúc ngôn ngữ STAN, quy trình chuyển giả thuyết nghiên cứu thành mô hình Bayes, khai thác phân phố hậu định.

Trong bài hôm nay chúng ta sẽ thay thế phân tích phương sai 1 yếu tố (One-way ANOVA) bằng phương pháp hồi quy Bayes.

Qua 2 bài gần đây nhất, ta thấy rằng:

  1. Phân tích và suy diễn thống kê theo trường phái Bayes có nguyên tắc như nhau trong mọi bài toán:

\[p(\theta |outcome, data)\propto p(outcome|\theta) p(\theta ,data)\]

theo đó, phân phối hậu định của một tham số Theta (xác suất điều kiện của theta khi có thông tin về biến kết quả outcome và matrix/vector dữ liệu) tỉ lệ với tích của hàm likelihood (xác suất có điều kiện cho phép ước tính kết quả khi có theta và dữ liệu) với phân phối tiền định (prior= một giả thuyết về phân phối của theta trước khi ta nhìn thấy dữ liệu và kết quả).

  1. Vấn đề là ta phải chuyển câu hỏi nghiên cứu và dữ liệu thành mô hình Bayes, trong đó theta là mục tiêu cần tìm phân phối hậu định, ta phải mô tả được quy luật của hàm likelihood cho phép ước lượng outcome, và phải chọn prior. Khi đã phác thảo được mô hình trên giấy thì việc viết code chỉ còn là vấn đề kỹ thuật.
  2. Theo nguyên tắc này, ta có thể thay thế tất cả những công cụ thống kê truyền thống dùng null hypothesis testing và p_value bằng phân tích Bayes.
  3. Sự thay thế có thể thực hiện ở 2 cấp độ (theo 2 cách): hoặc chọn trị số thống kê (thí dụ F cho Fisher’s F test và các effect-size trong ANOVA) làm mục tiêu để tìm phân phối hậu định, tức là vẫn bám sát vào truyền thống; hoặc chỉ giữ lại tinh thần của giải pháp mà không chấp chước vào các trị số quy ước, thí dụ thay vì dựng bảng ANOVA và F test thì ta khảo sát trực tiếp phân phối hậu định của trung bình khác biệt giữa các phân nhóm, tức là ta bỏ hẳn công cụ đi và chỉ dùng mô hình.

Như thường lệ, bài giảng sẽ đi theo 3 bước như sau:

Trước hết, chúng tôi sẽ ôn lại lý thuyết về ANOVA đơn biến, đưa ra 1 bài toán tiêu biểu và minh họa quy trình ANOVA cổ điển theo phái frequentist.

Sau đó chúng tôi sẽ chuyển bài toán này thành mô hình Bayes, và hướng dẫn các bạn viết STAN code cho mô hình.

Cuối cùng, chúng ta sẽ khai thác phân phối hậu định cho các tham số cần quan tâm, và suy diễn Bayes.

Ôn tập về ANOVA 1 yếu tố

Bài toán minh họa

Bộ số liệu minh họa trong bài thực hành này có nguồn gốc từ một thử nghiệm lâm sàng đối chứng song song của AstraZeneca. 606 bệnh nhân có chức năng gan ở thời điểm ban đầu tương đương nhau, được phân chia ngẫu nhiên vào 4 phân nhóm điều trị A,B,C và D. Mỗi phân nhóm được điều trị bằng một loại thuốc X với liều khác nhau (A= liều thấp nhất, D= cao nhất) trong một thời gian dài như nhau. Biến số kết quả là nồng độ bilirubin (TBL : total bilirubin level) cuối cùng sau khi điều trị. Câu hỏi nghiên cứu đặt ra là liệu liều thuốc có ảnh hưởng đến giá trị TBL hay không ?

library(tidyverse)
dat0 <- read.csv("http://vincentarelbundock.github.io/Rdatasets/csv/texmex/liver.csv")%>%as_tibble()

Bảng thống kê mô tả:

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

n mean sd median trimmed mad min max range skew kurtosis se A 152 9.57 3.56 8.46 9.16 2.79 3.25 23.09 19.84 1.27 2.07 0.29 B 148 10.55 4.17 9.49 10.13 3.42 3.42 25.99 22.57 1.16 1.65 0.34 C 148 10.75 5.24 9.40 10.02 3.42 4.28 42.75 38.48 2.90 12.87 0.43 D 158 11.85 5.27 10.60 11.22 4.31 3.93 39.84 35.91 2.01 6.77 0.42

library(ggjoy)
## Warning: package 'ggjoy' was built under R version 3.4.1
mycol4=c("
# fcb614","
# f2600c","
# f20c23","
# 98039e")
dat0%>%ggplot(aes(x=TBL.M,y=dose,fill=dose,col=dose))+  
  geom_joy(alpha=0.5,size=1,scale=1)+  
  geom_rug(alpha=0.1)+  
  scale_x_continuous("Total bilirubin after treatment")+  
  theme_bw()+  
  geom_vline(xintercept=mean(dat0$TBL.M),linetype=2,col="blue",size=1)+  
  coord_flip()+  
  scale_fill_manual(values=mycol4)+ scale_color_manual(values=mycol4)
## Picking joint bandwidth of 1.29

Bây giờ chúng ta sẽ phân tích bài toán này. Có 2 biến số:

  1. kết quả Y (TBL) là một biến định lượng, liên tục
  2. yếu tố phân nhóm (X) là một biến phân loại có ý nghĩa thứ bậc, vì nó biểu thị cho liều thuốc tăng dần.

Có hai điểm chú ý quan trọng mà chúng tôi muốn nhấn mạnh :

Đầu tiên, mục tiêu nghiên cứu có thể được phát biểu theo 2 cách:

  1. So sánh giá trị Y (TBL) giữa 4 phân nhóm A,B,C,D (đây là cách hiểu thông dụng ; có hàm ý so sánh)
  2. Khảo sát tác động của liều thuốc (X) lên sự thay đổi của Y (TBL) (Đây là cách phát biểu theo trường phái mô hình hồi quy)

Cả 2 cách tư duy kể trên đều đúng, và hiểu theo cách nào, thì các bạn cũng nhận ra giải pháp mình cần sử dụng chính là phân tích phương sai 1 yếu tố (gọi tắt là ANOVA đơn biến). Tuy nhiên, ở trường đại học các sinh viên Y khoa thường được dạy nhìn vấn đề theo cách thứ nhất (so sánh giá trị trung bình Yj giữa các phân nhóm Xj), do đó hầu hết bác sĩ và sinh viên tiếp cận ANOVA như một (bộ) công cụ gồm F-test, post-hoc test… ,không khác với những kiểm định rời rạc như Student-t test.

Khi chúng ta tiếp cận theo hướng mô hình, ta sẽ nhận ra bài toán ANOVA chính là một mô hình hồi quy tuyến tính có dạng Y = f(X), và thay vì dùng thuật ngữ «So sánh giữa 4 phân nhóm», ta sẽ nghĩ về « 4 bậc Hiệu ứng » mà yếu tố X đã gây ra cho kết quả Y.

Các phần mềm thống kê thương mại thường che dấu bản chất mô hình GLM của ANOVA, chúng chỉ dẫn dắt người dùng triển khai ANOVA như một gói công cụ dưới hình thức menu và nút bấm. Chỉ có R yêu cầu người dùng làm test F ANOVA qua một mô hình tuyến tính với hàm anova(), song R cũng có hàm aov() cho phép dựng bảng ANOVA mà không qua trung gian lm().

Chúng tôi khuyến khích các bạn suy nghĩ theo cách thứ hai (mô hình GLM), bởi vì nó cho phép các bạn quan sát thế giới sinh lý bệnh như những mô hình, bạn có thể nhìn ra bản chất của hiện tượng và tương tác giữa các yếu tố, hình dung về thiết kế phân nhóm ngay từ khi việc phân nhóm chưa được thực hiện. Mặt khác, khi đã nhìn ra bản chất của ANOVA chính là mô hình hồi quy tuyến tính, bạn sẽ nắm được dễ dàng MANOVA, ANOVA lặp lại, ANCOVA, MANCOVA, Mixed ANOVA… chứ không còn lẫn lộn giữa chúng như từng công cụ rời rạc nữa.

Thứ hai : ANOVA theo trường phái frequentist là một quy trình nhiều bước, chứ không phải là 1 kiểm định duy nhất. Những bước bắt buộc gồm có

  1. Kiểm tra các giả định, trong đó quan trọng nhất là giả định vê quan sát độc lập, giả định phương sai đồng nhất, giả định phân phối chuẩn ở mỗi phân nhóm
  2. Fisher’s F test
  3. hậu kiểm (posthoc) hay phân tích tương phản (contrast analysis), với mục tiêu so sánh bắt cặp tuần tự ;
  4. Tính effect-size.

Đa số các bạn sinh viên chỉ làm bước 2,3 nhưng bỏ qua bước 1 và 4.

Thí dụ: Dữ liệu này đã vi phạm giả định về phân phối chuẩn, dựa theo kết quả D’Agostino test.

dat0%>%  
  split(.$dose)%>%  
  map(~fBasics::dagoTest(.$TBL.M))
## $A  
##   
## Title:  
##  D'Agostino Normality Test  
##   
## Test Results:  
##   STATISTIC:  
##     Chi2 | Omnibus: 40.5507  
##     Z3  | Skewness: 5.4139  
##     Z4  | Kurtosis: 3.3526  
##   P VALUE:  
##     Omnibus  Test: 1.565e-09   
##     Skewness Test: 6.166e-08   
##     Kurtosis Test: 0.0008005   
##   
## Description:  
##  Fri Oct 13 13:04:19 2017 by user: Admin  
##   
##   
## $B  
##   
## Title:  
##  D'Agostino Normality Test  
##   
## Test Results:  
##   STATISTIC:  
##     Chi2 | Omnibus: 33.8696  
##     Z3  | Skewness: 5.0183  
##     Z4  | Kurtosis: 2.9473  
##   P VALUE:  
##     Omnibus  Test: 4.419e-08   
##     Skewness Test: 5.214e-07   
##     Kurtosis Test: 0.003206   
##   
## Description:  
##  Fri Oct 13 13:04:20 2017 by user: Admin  
##   
##   
## $C  
##   
## Title:  
##  D'Agostino Normality Test  
##   
## Test Results:  
##   STATISTIC:  
##     Chi2 | Omnibus: 120.8591  
##     Z3  | Skewness: 8.7442  
##     Z4  | Kurtosis: 6.6632  
##   P VALUE:  
##     Omnibus  Test: < 2.2e-16   
##     Skewness Test: < 2.2e-16   
##     Kurtosis Test: 2.679e-11   
##   
## Description:  
##  Fri Oct 13 13:04:20 2017 by user: Admin  
##   
##   
## $D  
##   
## Title:  
##  D'Agostino Normality Test  
##   
## Test Results:  
##   STATISTIC:  
##     Chi2 | Omnibus: 86.4629  
##     Z3  | Skewness: 7.3941  
##     Z4  | Kurtosis: 5.6383  
##   P VALUE:  
##     Omnibus  Test: < 2.2e-16   
##     Skewness Test: 1.423e-13   
##     Kurtosis Test: 1.717e-08   
##   
## Description:  
##  Fri Oct 13 13:04:20 2017 by user: Admin

Sự vi phạm giả định về phân phối chuẩn của Y tại các phân nhóm, thông thường không cho phép chúng ta dùng ANOVA. Một giải pháp thay thế phi tham số (Kruskal-Wallis test) hoặc hoán chuyển dữ liệu có thể áp dụng. Tuy nhiên với mục đích minh họa, chúng ta tạm chấp nhận bỏ qua vi phạm này, và thực ra khi quan sát 4 density plot của Y, ta thấy chúng có phân phối đồng dạng.

Bây giờ ta thực hiện ANOVA:

Một quy trình ANOVA hoàn chỉnh phải trả lời được 2 câu hỏi :

Câu hỏi 1) X có thật sự gây ra hiệu ứng ý nghĩa làm thay đổi Y hay không ? (Nói cách khác : Mô hình tuyến tính Y=f(X) có cho phép giải thích được phần lớn sai biệt của Y hay không ?), hiệu ứng của X lớn đến mức nào ?

Câu hỏi thứ nhất này được giải quyết bằng F test như sau :

Đầu tiên ta dựng một mô hình tuyến tính M có dạng Y = f(X) (chúng ta sẽ tìm hiểu rõ hơn về nội dung hàm f trong đoạn sau). Áp dụng model M này, ta có thể ước lượng giá trị trung bình Yj của Y tại mỗi cấp bậc j của yếu tố X. Yj được giả định có phân phối chuẩn (Muj, sigmaj), trong đó Muj là giá trị trung bình dự báo, còn sigmaj cho biết sai biệt mang tính nội tại (trong từng phân nhóm) và ngẫu nhiên so với giá trị có thực quan sát được (có thể xem như residual error của model M hay residual sum of squares = SSR).

SSR = Residual sum of squares

\[SSR=\sum_{i=1}^{n}(y_i-\hat{y}_i)^2\]

Ta lại có thể tính được khoảng cách sai biệt giữa Muj và giá trị trung bình của Y cho toàn quần thể (tất cả phân nhóm gộp lại), đây là phần sai biệt do sự phân nhóm gây ra (hay phần biến thiên của Y mà mô hình M có thể giải thích được):

SSM = Model sum of squares

\[SSM=\sum_{i=1}^{n}(\hat{y}_i-\bar{y})^2\] Từ đó ta có:

Trung bình bình phương mô hình: Mean model sum of squares: MSM

\[MSM=\frac{SSR}{k-1}\] Với k = số bậc của yếu tố X

Trung bình bình phương nội tại ngẫu nhiên : Mean residual sum of squares

\[MSR=\frac{SSE}{n-k}\]

Tỉ số F được xác định như sau:

\[F=\frac{MSM}{MSR}\]

Tỉ số F có thể được định nghĩa theo nhiều cách, thí dụ : F= tỉ số giữa hiệu ứng chính giữa các phân nhóm Xj và hiệu ứng nội tại trong từng phân nhóm Xj, hoặc F=tỉ số giữa phương sai do yếu tố X và phương sai do ngẫu nhiên, hoặc : F = tỉ số giữa phần phương sai mà mô hình cho phép giải thích và phần phương sai còn lại mà mô hình không thể giải thích.

Kiểm định F được Giáo sư Ronald A. Fisher (1890-1962), một nhà di truyền và thống kê học người Anh thiết kế ra năm 1920. Bản chất của F test là một phản nghiệm với lý luận như sau:

Nếu X thực sự gây hiệu ứng quan trọng đối với Y (tức là gây ra thay đổi lớn hơn sự biến thiên ngẫu nhiên của chính Y), một mô hình M ước lượng Y theo X hẳn phải rất phù hợp với dữ liệu, các điểm giá trị Yij sẽ nằm rất gần đường thẳng hồi quy M=f(X). M sẽ cho phép giải thích hầu hết phương sai của Y và chỉ để lại phần sai số dư nhỏ như vậy, như vậy MSM chắc chắn là lớn hơn so với MSR.

Nếu ta dùng 1 giá trị F đại diện cho tỉ lệ MSM/MSR, hiệu ứng của X càng quan trọng thì F càng lớn.

Bước tiếp theo của phản nghiệm (như mọi Null hypothesis testing khác), ta sẽ dùng F đại diện cho hiệu ứng của X: Ta muốn chứng minh là F đủ lớn để có thể gọi là có ý nghĩa.

Giả thuyết 0 do đó sẽ là: Có 1 giá trị F’ còn lớn hơn F nữa ! (H0: F’ > F) Giả thuyết H1 sẽ là : F’ không lớn hơn F.

Xác suất tìm ra F’ được xác định từ hàm pdf của một phân phối “F”, với 2 tham số độ tự do tương ứng với (k-1) : số phân nhóm hay bậc của X trừ 1, và (N-k) với N=cỡ mẫu. Mật độ xác suất (giá trị p) so với ngưỡng ý nghĩa thống kê được chọn, thí dụ alpha = 0.05 sẽ cho biết khả năng H0 đúng là thấp hơn hay cao hơn 0.05.

Nếu p<0.05 thì ta có thể loại bỏ giả thuyết H0. Kết quả này tương đương với việc khẳng định: F đủ lớn để cho phép suy diễn rằng hiệu ứng của X có ý nghĩa thống kê.

Sau đây là F test và bảng ANOVA cổ điển trong R:

Đầu tiên, Levene test cho phép khẳng định thỏa mãn giả định phương sai đồng nhất,sau đó là kết quả của hàm aov() cung cấp SSM, SSR,MSM,MSR và df của chúng.

Ta có F(3,602) = 6.318, có ý nghĩa thống kê với p=0.0003

aov(TBL.M ~ dose, dat0)%>%car::leveneTest()
## Levene's Test for Homogeneity of Variance (center = median)  
##        Df F value  Pr(>F)    
## group   3  2.2155 0.08521 .  
##       602                    
## ---  
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

0

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

1

Ngoài F test, ta còn có thể tính những Effect-sizes (kích thước hiệu ứng), thí dụ: Etasquared, r và Omegasquared

\[\eta ^{2} = \frac{SSM}{SST}\]

\[\omega ^{2} = \frac{SSM-dfmodel*MSR}{SST+MSR}\]

\[r = \sqrt{\frac{SSM}{SST}}\]

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

2

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

3

Giá trị omegaSqr hay Etasqr thường được diễn giải ở 3 mức: hiệu ứng nhỏ nếu < 0.05 trung bình : từ 0.01-0.05 và lớn nếu > 0.15, r được so sánh với ngưỡng 0.5, càng gần 1 thì hiệu ứng càng cao

Câu hỏi 2) Sự khác biệt giữa các phân nhóm với nhau là bao nhiêu ? Có ý nghĩa hay không ? (Mục tiêu so sánh bắt cặp giữa các phân nhóm, hay định vị sự khác biệt giữa các thứ bậc của X).

Câu hỏi thứ 2 này có hàm ý so sánh trung bình giữa các phân nhóm. Có hai cách giải quyết câu hỏi này, đó là post-hoc test (có hàng chục loại,như Tukey, Bonferroni, Sidak, Scheffe, Hochberg, Gabriel, Waller-Duncan, Dunett, Newman Keuls, LSD, Tamhane, Ryan-Einot-Gabriel Welsch) hay phân tích Contrast.

Post-hoc test được dùng khi ta không có giả thuyết nào cụ thể; phổ biến nhất là Bonferroni hay Tukey; trong khi contrast là một thí nghiệm mang tính chủ quan, trong đó ta dựng mô hình có áp dụng trọng số để tạo ra tương phản trên model matrix.

Sau đây là thí dụ với Bonferroni post-hoc test:

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

4

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

5

VÀ Tukey post-hoc test

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

6

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

7

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

8

Còn đây là thí dụ minh họa về 1 phân tích contrast:

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

9

library(ggjoy)

0

Phái Frequentist và vấn đề cỡ mẫu

Sau khi tìm hiểu về nội dung của ANOVA cổ điển, chắc các bạn đã có thể hình dung về một số đặc tính của những công cụ thống kê cổ điển, đó là :

Các nhà thống kê cổ điển thường không giải quyết trực tiếp câu hỏi (giả thuyết) nghiên cứu từ dữ liệu ; nhưng họ đặt ra một trị số thống kê mang tính đại diện, thí dụ t trong Student t test, Chi2 trong Pearson’s Chisquared test, F trong Fisher’s F test ; sau đó họ dùng phương pháp Phản nghiệm, để chuyển giả thuyết nghiên cứu thành một giả thuyết H1 đối lập với 1 giả thuyết H0. Họ cho rằng nếu bác bỏ được H0 thì xem như H1 đúng. Cách làm này là không hoàn hảo trên thực tế. Đầu tiên, giả thuyết H0 được kiểm chứng duy nhất bằng trị số thống kê trung gian và đại diện mà ta vừa nói, và dựa vào một phân phối mang tính chất « tưởng tượng, giả định » của trị số này, thí dụ Chisquared, t, F. Sau nữa là cách phát biểu giả thuyết H0, H1. Ngay cả khi bác bỏ được H0, không đồng nghĩa với việc H1 là đúng (có thể còn nhiều giả thuyết thay thế khác như H2, H3 ?). Sau nữa, việc đặt ra ngưỡng ý nghĩa 0.05 cho trị số p vô tình đã khiến người nghiên cứu nhìn thế giới chỉ bằng 2 màu Trắng hoặc Đen, trong khi sự thật lại là màu xám.

Một nhược điểm khác của phái Frequentist, đó là mọi thứ đều phụ thuộc vào cỡ mẫu. Chúng ta có thể minh họa cho vấn đề này qua thí nghiệm nhỏ sau đây : Tưởng tượng cùng nghiên cứu này, chúng ta thực hiện ANOVA cho 17 mẫu khác nhau có kích thước N tăng dần từ 60 (10%) đến 606 (100%).

library(ggjoy)

1

Kết quả mô phỏng cho thấy : giá trị của F, p_value của F_test, và các effect size đều phụ thuộc vào cỡ mẫu. Chúng chỉ trở nên ổn định và đáng tin cậy với ít nhất N>200 N càng cao thì F càng cao; p_value không có ý nghĩa nếu N quá thấp, và effect-size chỉ ổn định với N đủ lớn.

Đó là nguyên nhân khiến nhóm BAV quyết định phát động dự án Bayes For Vietnam, nhằm giới thiệu một hướng đi khác so với trường phái Frequentist cổ điển và Null hypothesis testing. Trường phái Bayes cho phép các bạn định vị, xác lập trạng thái của H1, hay nói cách khác, là mức độ khả tín, niềm tin của các bạn vào H1 dựa vào dữ liệu thực tế, hiện tại mà bạn đang có (Chúng ta không cần đến p_value nữa). Bayes còn cho phép hòa hợp được thông tin, giả thuyết tiền định và likelihood để tìm ra phân phối hậu định

Đến đây, ta tạm dừng phần ANOVA cổ điển và chuyển sang phần chính của bài, đó là ANOVA theo Bayes:

Giải pháp Bayes cho ANOVA 1 yếu tố

Có nhiều cách để biểu diễn hàm f(X) trong mô hình y~f(X), thí dụ :

Y ~ 1 + (1|Xj) : Mô hình này tương đương với một hàm xác suất có điều kiện, cho phép tính trung bình Mu của Y tại mỗi phân nhóm Xj

Y~X, mô hình này có matrix bao gồm 4 biến : Intercept (tham số beta1) đại diện cho cấp bậc thứ nhất của X (thí dụ phân nhóm A), và 3 biến giả (dummy var) đại diện cho 3 phân nhóm B,C,D). Như vậy

Y ~ beta1 + beta2.(X=B)+beta3.(X=C) + beta4*(X=D).

Tuy nhiên, tham số hồi quy beta2, beta3, beta4 chỉ cho biết khác biệt trung bình của Y tại B,C,D so với A

Y ~ X – 1 ; mô hình này tương đương với mô hình 1 nhưng không chứa Intercept (-1), khi đó matrix của mô hình sẽ là 4 dummy variables (A,B,C,D) tương ứng với 4 tham số hồi quy beta1, beta2, beta3, beta4 – lần lượt chính là trung bình của Y tại mỗi phân nhóm.

Dù là mô hình nào, ta đều có thể trả lời câu thứ 1, vì F test dựa vào việc tính sum of squares, nhưng chúng ta phải chọn cách nào cho phép giải đáp cả câu thứ 2 thì mới là tối ưu. Do đó hàm f(X) của mô hình thứ 3 (không chứa intercept) được chọn để dựng mô hình Bayes.

Mô hình Bayes trong STAN

Như vậy trong bài này, chúng ta sẽ chuyển giá trị trung bình Y tại mỗi phân nhóm A,B,C,D thành 4 tham số beta1, beta2, beta3 và beta4. Mô hình có dạng:

\[y_{ij} = \beta _{1i}+\beta _{2i}+\beta _{3i} + \beta _{4i} + \epsilon _{ij}\]

Trong đó, yij là giá trị của biến kết quả Y tại trường hợp thứ i và phân nhóm j; betaji là giá trị trung bình dự báo của phân nhóm j, và eij là sai số tồn lưu của mô hình.

Trước hết ta viết mô hình trong STAN với cấu trúc như sau:

STAN code được lưu dưới dạng chuỗi kí tự (string),

model.text <- “…..”

một chương trình STAN có nhiều block và mỗi block có vai trò khác nhau:

  1. Block data: Tên gọi, loại và phạm vi của từng yếu tố trong dữ liệu đầu vào phải được khai báo trong block này

N là một số nguyên dương chỉ cỡ mẫu

J là 1 số nguyên dương, chỉ số bậc của yếu tố X (số phân nhóm)

y là 1 vector số thực có độ dài = N

x là 1 vector số nguyên dương, dao động từ 1 đến J và có độ dài N

  1. Block parameter:

Như tên gọi của nó, đây là nơi khai báo về các tham số mà ta cần trong mô hình. Như đã trình bày, ta có 2 loại tham số: beta (trung bình mỗi phân nhóm, hay tham số hồi quy trong mô hình), là một vector số thực có kích thước J (J=1,2,3,4) và sigma là SD của residual, là 1 số thực

  1. Block Transformed parameters:

Block này không bắt buộc phải có cho mọi mô hình vì nó tùy thuộc vào mục đích của người viết code và độ phức tạp của mô hình. Cần chú ý là mọi tham số tạo ra trong block này cũn sẽ được lấy mẫu cho chuỗi MCMC và xuất ra kết quả mô hình như các tham số trong block parameter.

Trong block này, ta khai báo tham số Mu là trung bình dự báo của Y, với likelihood là Y được mô tả bằng phân phối chuẩn có trung bình Mu và SD=sigma; sau đó ta viết 1 vòng lặp để liên kết Mu và Beta cho mỗi case i

  1. Block Model: Trong block này ta sẽ khai báo về thành phần likelihood và priors (giả thuyết tiền định về phân phối của từng tham số).

Trong mô hình này, likelihood là y ~ normal (Mu, sigma); Ta có 2 tham số là beta và Sigma. Nếu ta không khai báo prior, STAN sẽ mặc định dùng prior Uniform cho tham số đó. Ở đây ta dùng prior “non informative” là half-Cauchy cho sigma, và 1 giả thuyết tiền định rằng beta có phân phối chuẩn, dao động quanh trung bình = 10 và sd=100.

Ngoài ra, ta còn có thể dùng thêm block thứ 5 để lấy mẫu cho các tham số phụ hay phái sinh từ các parameter có sẵn trong mô hình; tuy nhiên việc này không thực sự quan trọng, nhất là việc tính toán nhiều tham số bằng cách lấy mẫu sẽ làm quy trình tạo MCMC quá tải một cách không cần thiết.

library(ggjoy)

2

Sau khi code mô hình, ta sẽ tạo ra dữ liệu đầu vào cho phân tích Bayes, dưới dạng 1 list, trong đó ta khai báo các thành phần mà block data đã mô tả, gồm vector y, x, 2 số nguyên N và J

library(ggjoy)

3

Ta đưa data vào mô hình và kích hoạt quy trình lấy mẫu MCMC với các tùy chỉnh Ta sẽ chạy 2 chuỗi song song: Trước hết sampler sẽ chạy 500 lượt khởi động, khi ổn định thì kết quả MCMC bắt đầu được ghi lại 2500 lượt cho mỗi chuỗi, và chạy song song trên tối đa 4 cores của máy tính.

library(ggjoy)

4

library(ggjoy)

5

Quy trình converged khá nhanh sau vài phút. Bây giờ ta có 1 object khá lớn, chứa 2 chuỗi MCMCx2500 lượt cho 4 tham số beta, cho sigma, và 606 tham số Mu. Tuy nhiên ta chỉ cần khảo sát 4 tham số beta.

Phân phối hậu định của 4 tham số beta1,2,3,4 (chính là trung bình của TBL cho 4 phân nhóm) có thể được khảo sát như sau :

library(ggjoy)

6

library(ggjoy)

7

library(ggjoy)

8

library(ggjoy)

9

Trước hết, ta thấy rằng mô hình Bayes không thể ước lượng chính xác phân phối thực tế của TBL, nó chỉ cho phép ước lượng giá trị trung bình (Muj) tại mỗi phân nhóm thông qua các tham số beta.

Tuy nhiên bản thân tham số beta chưa cho phép ta trả lời 2 câu hỏi ở trên. Do đó ta phải làm tiếp bước 2 : Dựng bảng ANOVA từ mô hình BAYES

Bảng ANOVA từ mô hình BAYES

Nội dung của bước này là tương tự như cách ta làm để dựng bảng ANOVA cổ điển, chỉ khác đó là MSM và MSR và các sum of squares không được xác định từ mô hình tuyến tính dùng algorithm Least square hay REML, mà dùng chính mô hình Bayes với 4 tham số Beta. Để đơn giản, ta lấy Trung vị của phân phối hậu định của mỗi Beta để tạo ra 1 mô hình đại diện :

Sau đó, từ mô hình đại diện Bayes này, ta tính các SS, MSM, MSR, F values cũng như các effect-sizes

## Warning: package 'ggjoy' was built under R version 3.4.1

0

## Warning: package 'ggjoy' was built under R version 3.4.1

1

Như vậy, đây là một giải pháp “lai” giữa hồi quy Bayes và null hypothesis testing. Thậm chí ta có cả p values.

Kết quả trên đây có thể xem như tương đương với kết quả của hàm aov(), trường phái Frequentist.Giá trị p 1 sided là như nhau. Một kết quả không tệ ?

## Warning: package 'ggjoy' was built under R version 3.4.1

2

## Warning: package 'ggjoy' was built under R version 3.4.1

3

Đến đây, ta đã trả lời xong câu hỏi thứ 1, tiếp theo sẽ là việc so sánh bắt cặp tuần tự giữa 4 phân nhóm để trả lời câu hỏi thứ 2

Post-hoc test theo BAYES

Quy trình này thực sự thay thế post-hoc test theo phái frequentist bằng phương pháp Bayes. Nội dung của post hoc test theo Bayes rất đơn giản: Ta sẽ tạo ra 6 chuỗi MCMC chứa phân phối hậu định của “khác biệt trung bình” giữa 2 phân nhóm được bắt cặp tuần tự (Ta có 4 phân nhóm, nên có 6 cặp so sánh ). Suy diễn Bayes sẽ được thực hiện trực tiếp trên mỗi chuỗi MCMC, không cần dùng p_value hay hiệu chỉnh.

## Warning: package 'ggjoy' was built under R version 3.4.1

4

## Warning: package 'ggjoy' was built under R version 3.4.1

5

Suy diễn Bayes được thực hiện bằng cả 2 phương pháp : ROPE (Kruschke) và Bayes Factor. Chú ý rằng chúng ta lấy MuA-MuB, nên khác biệt trung bình <0 cho cặp so sánh AB có nghĩa là MuB lớn hơn MuA

Trước hết, ta hãy xem qua phân tích ROPE phân phối hậu định của 6 khác biệt trung bình :

Nhắc lại, ROPE là một khoảng vô nghĩa thực dụng, thí dụ ta giả địng rằng nếu khác biệt trung bình nằm trong khoảng +/- 0.5 xem như vô nghĩa.

## Warning: package 'ggjoy' was built under R version 3.4.1

6

## Warning: package 'ggjoy' was built under R version 3.4.1

7

Kết quả: Ngoại trừ cặp BC, 5 cặp còn lại đều cho thấy một sự tương phản khá rõ, vì mật độ phân phối hậu định của khác biệt trung bình nằm trong ROPE thấp nhất là 6.5% (cặp BD) , cao nhất chỉ có 18.6% (cặp AB), sự khác biệt này theo hướng : Liều thuốc cao hơn tương ứng với giá trị TLB cao hơn (khác biệt càng âm), vì mật độ phân phối hậu định nằm dưới ROPE dao động từ 81% cho cặp AB đến 90% cho cặp AC, 93.4% cho cặp BD, 87.8% cho cặp CD và cao nhất là 99.9% cho cặp AD.

## Warning: package 'ggjoy' was built under R version 3.4.1

8

Kết quả này hoàn toàn tương đồng với kết quả của Bootstrap 1000 lần post-hoc test Tukey:

## Warning: package 'ggjoy' was built under R version 3.4.1

9

Như vậy chúng ta có thể an tâm rằng Bayesian post hoc test có thể thay thế cho Tukey post hoc test, nhưng còn về ý nghĩa thống kê thì sao ? Ta thử đối chiếu phân tích ROPE và p value của Tukey test cũng như của Bonferroni test:

mycol4=c("
# fcb614","
# f2600c","
# f20c23","
# 98039e")
dat0%>%ggplot(aes(x=TBL.M,y=dose,fill=dose,col=dose))+  
  geom_joy(alpha=0.5,size=1,scale=1)+  
  geom_rug(alpha=0.1)+  
  scale_x_continuous("Total bilirubin after treatment")+  
  theme_bw()+  
  geom_vline(xintercept=mean(dat0$TBL.M),linetype=2,col="blue",size=1)+  
  coord_flip()+  
  scale_fill_manual(values=mycol4)+ scale_color_manual(values=mycol4)

0

mycol4=c("
# fcb614","
# f2600c","
# f20c23","
# 98039e")
dat0%>%ggplot(aes(x=TBL.M,y=dose,fill=dose,col=dose))+  
  geom_joy(alpha=0.5,size=1,scale=1)+  
  geom_rug(alpha=0.1)+  
  scale_x_continuous("Total bilirubin after treatment")+  
  theme_bw()+  
  geom_vline(xintercept=mean(dat0$TBL.M),linetype=2,col="blue",size=1)+  
  coord_flip()+  
  scale_fill_manual(values=mycol4)+ scale_color_manual(values=mycol4)

1

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

4

d=psych::describeBy(dat0$TBL.M,dat0$dose)
t1=rbind(d$A[,c(2:13)],   
         d$B[,c(2:13)],   
         d$C[,c(2:13)],   
         d$D[,c(2:13)])%>%as.data.frame()%>%round(.,2)  
row.names(t1)=c("A","B","C","D")  
knitr::kable(t1)

5

Kết quả đối chiếu cho thấy: Vì Bonferroni là 1 test rất bảo thủ, nó phủ nhận toàn bộ ý nghĩa của khác biệt trung bình giữa các cặp AB,BC,AC,CD và BD, chỉ duy nhất cặp AD với tương phản mạnh nhất là nhận p_value < 0.05

Khi không hiệu chỉnh bằng Bonferroni, 1 test Tukey thông thường chỉ bác bỏ ý nghĩa của khác biệt giữa 2 cặp AB và BC, nhưng các cặp còn lại đều nhận p<0.05;

Chúng tôi không muốn áp đặt ý kiến riêng nào cả về kết quả này. Các bạn có toàn quyền Tin hoặc không Tin về khác biệt có ý nghĩa cho cặp AB ngay cả khi post-hoc test đã phủ nhận giả thuyết này, biết rằng có đến 81% mật độ phân phối hậu định của khác biệt A-B nằm dưới -0.5; tương tự, bạn có quyền tin hay không tin rằng TBL ở liều thuốc D so với C là khác nhau, dù p_value =0.23, biết rằng 87.8% mật độ phân phối của khác biệt < -0.5

Có một cách khác nếu bạn muốn phân định Trắng/Đen: đó là dùng Bayes Factor, với ngưỡng so sánh là zero (không có khác biệt), tỉ trọng chứng cứ ủng hộ cho giả thuyết H1 (khác biệt < 0):

mycol4=c("
# fcb614","
# f2600c","
# f20c23","
# 98039e")
dat0%>%ggplot(aes(x=TBL.M,y=dose,fill=dose,col=dose))+  
  geom_joy(alpha=0.5,size=1,scale=1)+  
  geom_rug(alpha=0.1)+  
  scale_x_continuous("Total bilirubin after treatment")+  
  theme_bw()+  
  geom_vline(xintercept=mean(dat0$TBL.M),linetype=2,col="blue",size=1)+  
  coord_flip()+  
  scale_fill_manual(values=mycol4)+ scale_color_manual(values=mycol4)

4

mycol4=c("
# fcb614","
# f2600c","
# f20c23","
# 98039e")
dat0%>%ggplot(aes(x=TBL.M,y=dose,fill=dose,col=dose))+  
  geom_joy(alpha=0.5,size=1,scale=1)+  
  geom_rug(alpha=0.1)+  
  scale_x_continuous("Total bilirubin after treatment")+  
  theme_bw()+  
  geom_vline(xintercept=mean(dat0$TBL.M),linetype=2,col="blue",size=1)+  
  coord_flip()+  
  scale_fill_manual(values=mycol4)+ scale_color_manual(values=mycol4)

5

Ta khảo sát BF cho 10 ngưỡng H0 từ 0 đến -3, tuy nhiên ta quan tâm đến ngưỡng 0, để đối chiếu với p_values:

Nếu ta lấy tiêu chí: BF > 30 là đủ cao cho một suy diễn ý nghĩa thống kê, và BF>100 là rất cao, cho phép xác tín về ý nghĩa này; thì kết qủa của 6 phân phối hậu định của ta cho thấy:

Tỉ trọng chứng cứ ủng hộ cho giả thuyết H1: khác biệt trung bình < 0 thấp hơn 30 ở 2 cặp AB và BC, nhưng cao hơn 30 cho 4 cặp còn lại, thậm chí > 100 cho 2 cặp AD và BD.

Như vậy, Suy diễn Bayes có tính linh hoạt rất cao so với post-hoc test theo frequentist; không còn khái niệm test bảo thủ hay quá nhạy,không có ngưỡng nguy cơ sai lầm alpha = 0.05, v.v. Chính người thầy thuốc có quyền tự chủ trong suy luận của mình khi đọc kết quả mà phân tích Bayes đưa ra.

mycol4=c("
# fcb614","
# f2600c","
# f20c23","
# 98039e")
dat0%>%ggplot(aes(x=TBL.M,y=dose,fill=dose,col=dose))+  
  geom_joy(alpha=0.5,size=1,scale=1)+  
  geom_rug(alpha=0.1)+  
  scale_x_continuous("Total bilirubin after treatment")+  
  theme_bw()+  
  geom_vline(xintercept=mean(dat0$TBL.M),linetype=2,col="blue",size=1)+  
  coord_flip()+  
  scale_fill_manual(values=mycol4)+ scale_color_manual(values=mycol4)

6

Diễn đạt văn bản khoa học

Phương pháp thống kê:

Hiệu ứng của liều thuốc tăng dần đối với giá trị nồng độ bilirubin được khảo sát bằng một mô hình ANOVA theo phương pháp Bayes. Mô hình này cho phép ước lượng phân phối hậu định của giá trị TBL trung bình cho mỗi phân nhóm. Dựa vào kết quả này, chúng tôi có thể kiểm tra ý nghĩa và kích thước của hiệu ứng bằng F test theo Fisher, cũng như suy diễn về sự tương phản giữa 4 phân nhóm dựa vào phân phối hậu định của khác biệt trung bình, sử dụng Bayes Factor và ROPE (theo J. Kruschke).

Kết quả:

Liều thuốc tăng dần đã gây ra một hiệu ứng yếu nhưng có ý nghĩa thống kê làm thay đổi giá trị TBL giữa 4 phân nhóm (F(3,602)=6.27 ; p_value = 0.0003 ; etasquared = 0.03). Cụ thể, nồng độ Bilirubin có khuynh hướng tăng dần từ liều thấp nhất đến liều cao nhất. Tuy nhiên, sự khác biệt chỉ thực sự có ý nghĩa khi so sánh liều cơ bản (A) với liều cao (C) và rất cao (D) ; cũng như có sự tương phản ý nghĩa giữa liều cao nhất (D) và 2 liều thấp hơn là B và C. Việc tăng liều từ A sang B và từ B sang C không gây ra sự thay đổi đáng kể về TBL.

Tổng kết

Bài thực hành đến đây là hết. Các bạn đã khám phá lại ANOVA theo một cách làm hoàn toàn khác, với nhiều ưu điểm hơn so với phương pháp truyền thống. ANOVA là một chủ đề rất thú vị, vì nó kết hợp hầu hết những yếu tố đặc trưng của môn Thống Kê học, bao gồm phân tích hồi quy, phân phối và xác suất, phản nghiệm null hypothesis testing và effect-size, tương quan và so sánh…

Như chúng tôi từng nói, việc thực hành Bayes giúp (bắt buộc) người học xây dựng một kiến thức về xác suất, thống kê vững chắc hơn nhiều so với cách học truyền thống. Thực hành Bayes cũng tạo cho các bạn một kỹ năng viết R codes phong phú hơn nhiều so với việc sử dụng package từ ngày này qua ngày khác ; vì khi phải làm thủ công mọi việc, bạn sẽ học được nhiều hơn về cú pháp. Những thông điệp quan trọng sau đây đã được truyền tải trong bài :

  1. Bản chất ANOVA chính là Generalized linear model
  2. Quy trình ANOVA 1 yếu tố có mục tiêu trả lời 2 câu hỏi về kích thước/ý nghĩa của hiệu ứng, và khác biệt giữa các phân nhóm
  3. Có thể thay thế hoàn toàn quy trình ANOVA cổ điển bằng phương pháp Hồi quy Bayes.
  4. Phương pháp suy diễn Bayes linh hoạt và có nhiều ưu thế hơn so với Null hypothesis testing và P_value

Nhóm BAV xin chân thành cảm ơn sự ủng hộ của các bạn. Chúng tôi sẽ gặp lại các bạn trong một bài khác.

LS0tDQp0aXRsZTogIkJBWUVTOiBBTk9WQSAxIHnhur91IHThu5EiDQpzdWJ0aXRsZTogIlPhu60gZOG7pW5nIG5nw7RuIG5n4buvIFNUQU4iDQphdXRob3I6ICJOaMOzbSB0w6FjIGdp4bqjIEJBViINCmRhdGU6ICIxMiBUaMOhbmcgMTAgMjAxNyINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6ICJkZWZhdWx0Ig0KICAgIHRvYzogVFJVRQ0KICAgIHRvY19mbG9hdDogVFJVRQ0KLS0tDQoNCmBgYHtyIHNldHVwLGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkocnN0YW4pDQpsaWJyYXJ5KGJybXMpDQpgYGANCg0KIVtdKGJheWVzYW5vdmExLnBuZykNCg0KKlTDoWMgZ2nhuqM6KiANCg0KKkzDqiBOZ+G7jWMgS2jhuqMgTmhpICgyLDQsNSkqDQoqxJBpbmggVGnhur9uIFTDoGkgKDMsMikqIA0KKlRy4bqnbiBUcnVuZyBExaluZyAoMykqDQoqTMOqIMSQw7RuZyBOaOG6rXQgTmFtICgxLDIsMyw0LDUpKg0KDQpHaGkgY2jDujogxJDDs25nIGfDs3AgY+G7p2EgY8OhYyB0aMOgbmggdmnDqm46DQoNCigxKSBRdXkgdHLDrG5oIEFOT1ZBIGPhu5UgxJFp4buDbg0KKDIpIFZp4bq/dCBiw6BpIGdp4bqjbmcgbMO9IHRodXnhur90IA0KKDMpIFNv4bqhbiB2w6AgaG/DoG4gdGhp4buHbiBTVEFOIGNvZGVzIGNobyBtw7QgaMOsbmggQmF5ZXMNCig0KSDEkOG7kyBo4buNYQ0KKDUpIFN1eSBkaeG7hW4gQmF5ZXMNCg0KIyBHaeG7m2kgdGhp4buHdQ0KDQpUaMOibiBjaMOgbyBjw6FjIGLhuqFuLCDEkcOieSBsw6AgYsOgaSB0aOG7sWMgaMOgbmggdGjhu6kgNSB0cm9uZyBk4buxIMOhbiBCYXllcyBmb3IgVmlldG5hbS4gTeG7pWMgdGnDqnUgY+G7p2EgY2jDum5nIHTDtGkgbMOgIHBo4buVIGPhuq1wIHbhu4EgcGjGsMahbmcgcGjDoXAgdGjhu5FuZyBrw6ogdGhlbyB0csaw4budbmcgcGjDoWkgQmF5ZXMgbmjhurFtIHRoYXkgdGjhur8gaG/DoG4gdG/DoG4gbmjhu69uZyBjw7RuZyBj4bulIHRydXnhu4FuIHRo4buRbmcuIMSQ4buRaSB0xrDhu6NuZyBj4bunYSBjaMO6bmcgdMO0aSBsw6AgY8OhYyBi4bqhbiBiw6FjIHPEqSB2w6Agc2luaCB2acOqbiB5IGtob2EuIA0KDQrEkMOieSBjxaluZyBsw6AgbOG6p24gxJHhuqd1IHRpw6puIG3hu5l0IGLDoGkgZ2nhuqNuZyBjw7Mgc+G7sSBnw7NwIHPhu6ljIGPhu6dhIHThuqV0IGPhuqMgNCB0aMOgbmggdmnDqm4gdHJvbmcgQ29yZSB0ZWFtIGPhu6dhIHByb2plY3QuIFRyb25nIG5o4buvbmcgYsOgaSDEkWkgdHLGsOG7m2MsIEJzLiBLaOG6oyBOaGkgxJHDoyBjw7luZyBjw6FjIGLhuqFuIMSRaSBxdWEgNCBjaOG6t25nIMSRxrDhu51uZywgZMO5bmcgQmF5ZXMgdGhheSB0aOG6vyBjaG8gUGVhcnNvbuKAmXMgciwgU3R1ZGVudCB0LXRlc3QsIENoaXNxdWFyZWQgdGVzdCB2w6AgcGjDom4gbG/huqFpIGLhurFuZyBo4buTaSBxdXkgTG9naXN0aWMuIEPDoWMgYuG6oW4gxJHDoyBi4bqvdCDEkeG6p3UgcXVlbiB24bubaSBj4bqldSB0csO6YyBuZ8O0biBuZ+G7ryBTVEFOLCBxdXkgdHLDrG5oIGNodXnhu4NuIGdp4bqjIHRodXnhur90IG5naGnDqm4gY+G7qXUgdGjDoG5oIG3DtCBow6xuaCBCYXllcywga2hhaSB0aMOhYyBwaMOibiBwaOG7kSBo4bqtdSDEkeG7i25oLg0KDQpUcm9uZyBiw6BpIGjDtG0gbmF5IGNow7puZyB0YSBz4bq9IHRoYXkgdGjhur8gcGjDom4gdMOtY2ggcGjGsMahbmcgc2FpIDEgeeG6v3UgdOG7kSAoT25lLXdheSBBTk9WQSkgYuG6sW5nIHBoxrDGoW5nIHBow6FwIGjhu5NpIHF1eSBCYXllcy4gDQoNClF1YSAyIGLDoGkgZ+G6p24gxJHDonkgbmjhuqV0LCB0YSB0aOG6pXkgcuG6sW5nOg0KDQoxKQlQaMOibiB0w61jaCB2w6Agc3V5IGRp4buFbiB0aOG7kW5nIGvDqiB0aGVvIHRyxrDhu51uZyBwaMOhaSBCYXllcyBjw7Mgbmd1ecOqbiB04bqvYyBuaMawIG5oYXUgdHJvbmcgbeG7jWkgYsOgaSB0b8OhbjoNCg0KJCRwKFx0aGV0YSB8b3V0Y29tZSwgZGF0YSlccHJvcHRvIHAob3V0Y29tZXxcdGhldGEpIHAoXHRoZXRhICxkYXRhKSQkDQoNCnRoZW8gxJHDsywgcGjDom4gcGjhu5FpIGjhuq11IMSR4buLbmggY+G7p2EgbeG7mXQgdGhhbSBz4buRIFRoZXRhICh4w6FjIHN14bqldCDEkWnhu4F1IGtp4buHbiBj4bunYSB0aGV0YSBraGkgY8OzIHRow7RuZyB0aW4gduG7gSBiaeG6v24ga+G6v3QgcXXhuqMgb3V0Y29tZSB2w6AgbWF0cml4L3ZlY3RvciBk4buvIGxp4buHdSkgdOG7iSBs4buHIHbhu5tpIHTDrWNoIGPhu6dhIGjDoG0gbGlrZWxpaG9vZCAoeMOhYyBzdeG6pXQgY8OzIMSRaeG7gXUga2nhu4duIGNobyBwaMOpcCDGsOG7m2MgdMOtbmgga+G6v3QgcXXhuqMga2hpIGPDsyB0aGV0YSB2w6AgZOG7ryBsaeG7h3UpIHbhu5tpIHBow6JuIHBo4buRaSB0aeG7gW4gxJHhu4tuaCAocHJpb3I9IG3hu5l0IGdp4bqjIHRodXnhur90IHbhu4EgcGjDom4gcGjhu5FpIGPhu6dhIHRoZXRhIHRyxrDhu5tjIGtoaSB0YSBuaMOsbiB0aOG6pXkgZOG7ryBsaeG7h3UgdsOgIGvhur90IHF14bqjKS4NCg0KMikJVuG6pW4gxJHhu4EgbMOgIHRhIHBo4bqjaSBjaHV54buDbiBjw6J1IGjhu49pIG5naGnDqm4gY+G7qXUgdsOgIGThu68gbGnhu4d1IHRow6BuaCBtw7QgaMOsbmggQmF5ZXMsIHRyb25nIMSRw7MgdGhldGEgbMOgIG3hu6VjIHRpw6p1IGPhuqduIHTDrG0gcGjDom4gcGjhu5FpIGjhuq11IMSR4buLbmgsIHRhIHBo4bqjaSBtw7QgdOG6oyDEkcaw4bujYyBxdXkgbHXhuq10IGPhu6dhIGjDoG0gbGlrZWxpaG9vZCBjaG8gcGjDqXAgxrDhu5tjIGzGsOG7o25nIG91dGNvbWUsIHbDoCBwaOG6o2kgY2jhu41uIHByaW9yLiBLaGkgxJHDoyBwaMOhYyB0aOG6o28gxJHGsOG7o2MgbcO0IGjDrG5oIHRyw6puIGdp4bqleSB0aMOsIHZp4buHYyB2aeG6v3QgY29kZSBjaOG7iSBjw7JuIGzDoCB24bqlbiDEkeG7gSBr4bu5IHRodeG6rXQuDQoNCjMpCVRoZW8gbmd1ecOqbiB04bqvYyBuw6B5LCB0YSBjw7MgdGjhu4MgdGhheSB0aOG6vyB04bqldCBj4bqjIG5o4buvbmcgY8O0bmcgY+G7pSB0aOG7kW5nIGvDqiB0cnV54buBbiB0aOG7kW5nIGTDuW5nIG51bGwgaHlwb3RoZXNpcyB0ZXN0aW5nIHbDoCBwX3ZhbHVlIGLhurFuZyBwaMOibiB0w61jaCBCYXllcy4gDQoNCjQpCVPhu7EgdGhheSB0aOG6vyBjw7MgdGjhu4MgdGjhu7FjIGhp4buHbiDhu58gMiBj4bqlcCDEkeG7mSAodGhlbyAyIGPDoWNoKTogaG/hurdjIGNo4buNbiB0cuG7iyBz4buRIHRo4buRbmcga8OqICh0aMOtIGThu6UgRiBjaG8gRmlzaGVyJ3MgRiB0ZXN0IHbDoCBjw6FjIGVmZmVjdC1zaXplIHRyb25nIEFOT1ZBKSBsw6BtIG3hu6VjIHRpw6p1IMSR4buDIHTDrG0gcGjDom4gcGjhu5FpIGjhuq11IMSR4buLbmgsIHThu6ljIGzDoCB24bqrbiBiw6FtIHPDoXQgdsOgbyB0cnV54buBbiB0aOG7kW5nOyBob+G6t2MgY2jhu4kgZ2nhu68gbOG6oWkgdGluaCB0aOG6p24gY+G7p2EgZ2nhuqNpIHBow6FwIG3DoCBraMO0bmcgY2jhuqVwIGNoxrDhu5tjIHbDoG8gY8OhYyB0cuG7iyBz4buRIHF1eSDGsOG7m2MsIHRow60gZOG7pSB0aGF5IHbDrCBk4buxbmcgYuG6o25nIEFOT1ZBIHbDoCBGIHRlc3QgdGjDrCB0YSBraOG6o28gc8OhdCB0cuG7sWMgdGnhur9wIHBow6JuIHBo4buRaSBo4bqtdSDEkeG7i25oIGPhu6dhIHRydW5nIGLDrG5oIGtow6FjIGJp4buHdCBnaeG7r2EgY8OhYyBwaMOibiBuaMOzbSwgdOG7qWMgbMOgIHRhIGLhu48gaOG6s24gY8O0bmcgY+G7pSDEkWkgdsOgIGNo4buJIGTDuW5nIG3DtCBow6xuaC4gDQoNCk5oxrAgdGjGsOG7nW5nIGzhu4csIGLDoGkgZ2nhuqNuZyBz4bq9IMSRaSB0aGVvIDMgYsaw4bubYyBuaMawIHNhdTogDQoNClRyxrDhu5tjIGjhur90LCBjaMO6bmcgdMO0aSBz4bq9IMO0biBs4bqhaSBsw70gdGh1eeG6v3QgduG7gSBBTk9WQSDEkcahbiBiaeG6v24sIMSRxrBhIHJhIDEgYsOgaSB0b8OhbiB0acOqdSBiaeG7g3UgdsOgIG1pbmggaOG7jWEgcXV5IHRyw6xuaCBBTk9WQSBj4buVIMSRaeG7g24gdGhlbyBwaMOhaSBmcmVxdWVudGlzdC4gDQoNClNhdSDEkcOzIGNow7puZyB0w7RpIHPhur0gY2h1eeG7g24gYsOgaSB0b8OhbiBuw6B5IHRow6BuaCBtw7QgaMOsbmggQmF5ZXMsIHbDoCBoxrDhu5tuZyBk4bqrbiBjw6FjIGLhuqFuIHZp4bq/dCBTVEFOIGNvZGUgY2hvIG3DtCBow6xuaC4NCg0KQ3Xhu5FpIGPDuW5nLCBjaMO6bmcgdGEgc+G6vSBraGFpIHRow6FjIHBow6JuIHBo4buRaSBo4bqtdSDEkeG7i25oIGNobyBjw6FjIHRoYW0gc+G7kSBj4bqnbiBxdWFuIHTDom0sIHbDoCBzdXkgZGnhu4VuIEJheWVzLg0KDQojIMOUbiB04bqtcCB24buBIEFOT1ZBIDEgeeG6v3UgdOG7kQ0KDQoqQsOgaSB0b8OhbiBtaW5oIGjhu41hKg0KDQpC4buZIHPhu5EgbGnhu4d1IG1pbmggaOG7jWEgdHJvbmcgYsOgaSB0aOG7sWMgaMOgbmggbsOgeSBjw7Mgbmd14buTbiBn4buRYyB04burIG3hu5l0IHRo4butIG5naGnhu4dtIGzDom0gc8OgbmcgxJHhu5FpIGNo4bupbmcgc29uZyBzb25nIGPhu6dhIEFzdHJhWmVuZWNhLiA2MDYgYuG7h25oIG5ow6JuIGPDsyBjaOG7qWMgbsSDbmcgZ2FuIOG7nyB0aOG7nWkgxJFp4buDbSBiYW4gxJHhuqd1IHTGsMahbmcgxJHGsMahbmcgbmhhdSwgxJHGsOG7o2MgcGjDom4gY2hpYSBuZ+G6q3Ugbmhpw6puIHbDoG8gNCBwaMOibiBuaMOzbSDEkWnhu4F1IHRy4buLIEEsQixDIHbDoCBELiBN4buXaSBwaMOibiBuaMOzbSDEkcaw4bujYyDEkWnhu4F1IHRy4buLIGLhurFuZyBt4buZdCBsb+G6oWkgdGh14buRYyBYIHbhu5tpIGxp4buBdSBraMOhYyBuaGF1IChBPSBsaeG7gXUgdGjhuqVwIG5o4bqldCwgRD0gY2FvIG5o4bqldCkgdHJvbmcgbeG7mXQgdGjhu51pIGdpYW4gZMOgaSBuaMawIG5oYXUuIEJp4bq/biBz4buRIGvhur90IHF14bqjIGzDoCBu4buTbmcgxJHhu5kgYmlsaXJ1YmluIChUQkwgOiB0b3RhbCBiaWxpcnViaW4gbGV2ZWwpIGN14buRaSBjw7luZyBzYXUga2hpIMSRaeG7gXUgdHLhu4suIEPDonUgaOG7j2kgbmdoacOqbiBj4bupdSDEkeG6t3QgcmEgbMOgIGxp4buHdSBsaeG7gXUgdGh14buRYyBjw7Mg4bqjbmggaMaw4bufbmcgxJHhur9uIGdpw6EgdHLhu4sgVEJMIGhheSBraMO0bmcgPw0KDQpgYGB7cixtZXNzYWdlID0gRkFMU0Usd2FybmluZz1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQpkYXQwIDwtIHJlYWQuY3N2KCJodHRwOi8vdmluY2VudGFyZWxidW5kb2NrLmdpdGh1Yi5pby9SZGF0YXNldHMvY3N2L3RleG1leC9saXZlci5jc3YiKSU+JWFzX3RpYmJsZSgpDQoNCmBgYA0KDQpC4bqjbmcgdGjhu5FuZyBrw6ogbcO0IHThuqM6IA0KDQpgYGB7cixtZXNzYWdlID0gRkFMU0Usd2FybmluZz1GQUxTRX0NCmQ9cHN5Y2g6OmRlc2NyaWJlQnkoZGF0MCRUQkwuTSxkYXQwJGRvc2UpDQoNCnQxPXJiaW5kKGQkQVssYygyOjEzKV0sIA0KICAgICAgICAgZCRCWyxjKDI6MTMpXSwgDQogICAgICAgICBkJENbLGMoMjoxMyldLCANCiAgICAgICAgIGQkRFssYygyOjEzKV0pJT4lYXMuZGF0YS5mcmFtZSgpJT4lcm91bmQoLiwyKQ0Kcm93Lm5hbWVzKHQxKT1jKCJBIiwiQiIsIkMiLCJEIikNCmtuaXRyOjprYWJsZSh0MSkNCmBgYA0KDQoNCmBgYHtyfQ0KbGlicmFyeShnZ2pveSkNCg0KbXljb2w0PWMoIiNmY2I2MTQiLCIjZjI2MDBjIiwiI2YyMGMyMyIsIiM5ODAzOWUiKQ0KDQpkYXQwJT4lZ2dwbG90KGFlcyh4PVRCTC5NLHk9ZG9zZSxmaWxsPWRvc2UsY29sPWRvc2UpKSsNCiAgZ2VvbV9qb3koYWxwaGE9MC41LHNpemU9MSxzY2FsZT0xKSsNCiAgZ2VvbV9ydWcoYWxwaGE9MC4xKSsNCiAgc2NhbGVfeF9jb250aW51b3VzKCJUb3RhbCBiaWxpcnViaW4gYWZ0ZXIgdHJlYXRtZW50IikrDQogIHRoZW1lX2J3KCkrDQogIGdlb21fdmxpbmUoeGludGVyY2VwdD1tZWFuKGRhdDAkVEJMLk0pLGxpbmV0eXBlPTIsY29sPSJibHVlIixzaXplPTEpKw0KICBjb29yZF9mbGlwKCkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1teWNvbDQpKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPW15Y29sNCkNCmBgYA0KDQoNCkLDonkgZ2nhu50gY2jDum5nIHRhIHPhur0gcGjDom4gdMOtY2ggYsOgaSB0b8OhbiBuw6B5LiBDw7MgMiBiaeG6v24gc+G7kTogDQoNCjEpIGvhur90IHF14bqjIFkgKFRCTCkgbMOgIG3hu5l0IGJp4bq/biDEkeG7i25oIGzGsOG7o25nLCBsacOqbiB04bulYw0KDQoyKSB54bq/dSB04buRIHBow6JuIG5ow7NtIChYKSBsw6AgbeG7mXQgYmnhur9uIHBow6JuIGxv4bqhaSBjw7Mgw70gbmdoxKlhIHRo4bupIGLhuq1jLCB2w6wgbsOzIGJp4buDdSB0aOG7iyBjaG8gbGnhu4F1IHRodeG7kWMgdMSDbmcgZOG6p24uIA0KDQpDw7MgaGFpIMSRaeG7g20gY2jDuiDDvSBxdWFuIHRy4buNbmcgbcOgIGNow7puZyB0w7RpIG114buRbiBuaOG6pW4gbeG6oW5oIDoNCg0KxJDhuqd1IHRpw6puLCBt4bulYyB0acOqdSBuZ2hpw6puIGPhu6l1IGPDsyB0aOG7gyDEkcaw4bujYyBwaMOhdCBiaeG7g3UgdGhlbyAyIGPDoWNoOg0KDQpJKSBTbyBzw6FuaCBnacOhIHRy4buLIFkgKFRCTCkgZ2nhu69hIDQgcGjDom4gbmjDs20gQSxCLEMsRCANCijEkcOieSBsw6AgY8OhY2ggaGnhu4N1IHRow7RuZyBk4bulbmcgOyBjw7MgaMOgbSDDvSBzbyBzw6FuaCkNCg0KSUkpIEto4bqjbyBzw6F0IHTDoWMgxJHhu5luZyBj4bunYSBsaeG7gXUgdGh14buRYyAoWCkgbMOqbiBz4buxIHRoYXkgxJHhu5VpIGPhu6dhIFkgKFRCTCkNCijEkMOieSBsw6AgY8OhY2ggcGjDoXQgYmnhu4N1IHRoZW8gdHLGsOG7nW5nIHBow6FpIG3DtCBow6xuaCBo4buTaSBxdXkpDQoNCkPhuqMgMiBjw6FjaCB0xrAgZHV5IGvhu4MgdHLDqm4gxJHhu4F1IMSRw7puZywgdsOgIGhp4buDdSB0aGVvIGPDoWNoIG7DoG8sIHRow6wgY8OhYyBi4bqhbiBjxaluZyBuaOG6rW4gcmEgZ2nhuqNpIHBow6FwIG3DrG5oIGPhuqduIHPhu60gZOG7pW5nIGNow61uaCBsw6AgcGjDom4gdMOtY2ggcGjGsMahbmcgc2FpIDEgeeG6v3UgdOG7kSAoZ+G7jWkgdOG6r3QgbMOgIEFOT1ZBIMSRxqFuIGJp4bq/bikuIFR1eSBuaGnDqm4sIOG7nyB0csaw4budbmcgxJHhuqFpIGjhu41jIGPDoWMgc2luaCB2acOqbiBZIGtob2EgdGjGsOG7nW5nIMSRxrDhu6NjIGThuqF5IG5ow6xuIHbhuqVuIMSR4buBIHRoZW8gY8OhY2ggdGjhu6kgbmjhuqV0IChzbyBzw6FuaCBnacOhIHRy4buLIHRydW5nIGLDrG5oIFlqIGdp4buvYSBjw6FjIHBow6JuIG5ow7NtIFhqKSwgZG8gxJHDsyBo4bqndSBo4bq/dCBiw6FjIHPEqSB2w6Agc2luaCB2acOqbiB0aeG6v3AgY+G6rW4gQU5PVkEgbmjGsCBt4buZdCAoYuG7mSkgY8O0bmcgY+G7pSBn4buTbSBGLXRlc3QsIHBvc3QtaG9jIHRlc3TigKYgLGtow7RuZyBraMOhYyB24bubaSBuaOG7r25nIGtp4buDbSDEkeG7i25oIHLhu51pIHLhuqFjIG5oxrAgU3R1ZGVudC10IHRlc3QuDQoNCktoaSBjaMO6bmcgdGEgdGnhur9wIGPhuq1uIHRoZW8gaMaw4bubbmcgbcO0IGjDrG5oLCB0YSBz4bq9IG5o4bqtbiByYSBiw6BpIHRvw6FuIEFOT1ZBIGNow61uaCBsw6AgbeG7mXQgbcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIGPDsyBk4bqhbmcgWSA9IGYoWCksIHbDoCB0aGF5IHbDrCBkw7luZyB0aHXhuq10IG5n4buvIMKrU28gc8OhbmggZ2nhu69hIDQgcGjDom4gbmjDs23CuywgdGEgc+G6vSBuZ2jEqSB24buBIMKrIDQgYuG6rWMgSGnhu4d1IOG7qW5nIMK7IG3DoCB54bq/dSB04buRIFggxJHDoyBnw6J5IHJhIGNobyBr4bq/dCBxdeG6oyBZLiANCg0KQ8OhYyBwaOG6p24gbeG7gW0gdGjhu5FuZyBrw6ogdGjGsMahbmcgbeG6oWkgdGjGsOG7nW5nIGNoZSBk4bqldSBi4bqjbiBjaOG6pXQgbcO0IGjDrG5oIEdMTSBj4bunYSBBTk9WQSwgY2jDum5nIGNo4buJIGThuqtuIGThuq90IG5nxrDhu51pIGTDuW5nIHRyaeG7g24ga2hhaSBBTk9WQSBuaMawIG3hu5l0IGfDs2kgY8O0bmcgY+G7pSBkxrDhu5tpIGjDrG5oIHRo4bupYyBtZW51IHbDoCBuw7p0IGLhuqVtLiBDaOG7iSBjw7MgUiB5w6p1IGPhuqd1IG5nxrDhu51pIGTDuW5nIGzDoG0gdGVzdCBGIEFOT1ZBIHF1YSBt4buZdCBtw7QgaMOsbmggdHV54bq/biB0w61uaCB24bubaSBow6BtIGFub3ZhKCksIHNvbmcgUiBjxaluZyBjw7MgaMOgbSBhb3YoKSBjaG8gcGjDqXAgZOG7sW5nIGLhuqNuZyBBTk9WQSBtw6Aga2jDtG5nIHF1YSB0cnVuZyBnaWFuIGxtKCkuDQoNCkNow7puZyB0w7RpIGtodXnhur9uIGtow61jaCBjw6FjIGLhuqFuIHN1eSBuZ2jEqSB0aGVvIGPDoWNoIHRo4bupIGhhaSAobcO0IGjDrG5oIEdMTSksIGLhu59pIHbDrCBuw7MgY2hvIHBow6lwIGPDoWMgYuG6oW4gcXVhbiBzw6F0IHRo4bq/IGdp4bubaSBzaW5oIGzDvSBi4buHbmggbmjGsCBuaOG7r25nIG3DtCBow6xuaCwgYuG6oW4gY8OzIHRo4buDIG5ow6xuIHJhIGLhuqNuIGNo4bqldCBj4bunYSBoaeG7h24gdMaw4bujbmcgdsOgIHTGsMahbmcgdMOhYyBnaeG7r2EgY8OhYyB54bq/dSB04buRLCBow6xuaCBkdW5nIHbhu4EgdGhp4bq/dCBr4bq/IHBow6JuIG5ow7NtIG5nYXkgdOG7qyBraGkgdmnhu4djIHBow6JuIG5ow7NtIGNoxrBhIMSRxrDhu6NjIHRo4buxYyBoaeG7h24uIE3hurd0IGtow6FjLCBraGkgxJHDoyBuaMOsbiByYSBi4bqjbiBjaOG6pXQgY+G7p2EgQU5PVkEgY2jDrW5oIGzDoCBtw7QgaMOsbmggaOG7k2kgcXV5IHR1eeG6v24gdMOtbmgsIGLhuqFuIHPhur0gbuG6r20gxJHGsOG7o2MgZOG7hSBkw6BuZyBNQU5PVkEsIEFOT1ZBIGzhurdwIGzhuqFpLCBBTkNPVkEsIE1BTkNPVkEsIE1peGVkIEFOT1ZB4oCmIGNo4bupIGtow7RuZyBjw7JuIGzhuqtuIGzhu5luIGdp4buvYSBjaMO6bmcgbmjGsCB04burbmcgY8O0bmcgY+G7pSBy4budaSBy4bqhYyBu4buvYS4NCg0KVGjhu6kgaGFpIDogQU5PVkEgdGhlbyB0csaw4budbmcgcGjDoWkgZnJlcXVlbnRpc3QgbMOgIG3hu5l0IHF1eSB0csOsbmggbmhp4buBdSBixrDhu5tjLCBjaOG7qSBraMO0bmcgcGjhuqNpIGzDoCAxIGtp4buDbSDEkeG7i25oIGR1eSBuaOG6pXQuIE5o4buvbmcgYsaw4bubYyBi4bqvdCBideG7mWMgZ+G7k20gY8OzIA0KDQoxKSBLaeG7g20gdHJhIGPDoWMgZ2nhuqMgxJHhu4tuaCwgdHJvbmcgxJHDsyBxdWFuIHRy4buNbmcgbmjhuqV0IGzDoCBnaeG6oyDEkeG7i25oIHbDqiBxdWFuIHPDoXQgxJHhu5ljIGzhuq1wLCBnaeG6oyDEkeG7i25oIHBoxrDGoW5nIHNhaSDEkeG7k25nIG5o4bqldCwgZ2nhuqMgxJHhu4tuaCBwaMOibiBwaOG7kWkgY2h14bqpbiDhu58gbeG7l2kgcGjDom4gbmjDs20gDQoNCjIpIEZpc2hlcuKAmXMgRiB0ZXN0IA0KDQozKSBo4bqtdSBraeG7g20gKHBvc3Rob2MpIGhheSBwaMOibiB0w61jaCB0xrDGoW5nIHBo4bqjbiAoY29udHJhc3QgYW5hbHlzaXMpLCB24bubaSBt4bulYyB0acOqdSBzbyBzw6FuaCBi4bqvdCBj4bq3cCB0deG6p24gdOG7sSA7IA0KDQo0KSBUw61uaCBlZmZlY3Qtc2l6ZS4gDQoNCsSQYSBz4buRIGPDoWMgYuG6oW4gc2luaCB2acOqbiBjaOG7iSBsw6BtIGLGsOG7m2MgMiwzIG5oxrBuZyBi4buPIHF1YSBixrDhu5tjIDEgdsOgIDQuIA0KDQpUaMOtIGThu6U6IEThu68gbGnhu4d1IG7DoHkgxJHDoyB2aSBwaOG6oW0gZ2nhuqMgxJHhu4tuaCB24buBIHBow6JuIHBo4buRaSBjaHXhuqluLCBk4buxYSB0aGVvIGvhur90IHF14bqjIEQnQWdvc3Rpbm8gdGVzdC4NCg0KYGBge3J9DQpkYXQwJT4lDQogIHNwbGl0KC4kZG9zZSklPiUNCiAgbWFwKH5mQmFzaWNzOjpkYWdvVGVzdCguJFRCTC5NKSkNCmBgYA0KDQpT4buxIHZpIHBo4bqhbSBnaeG6oyDEkeG7i25oIHbhu4EgcGjDom4gcGjhu5FpIGNodeG6qW4gY+G7p2EgWSB04bqhaSBjw6FjIHBow6JuIG5ow7NtLCB0aMO0bmcgdGjGsOG7nW5nIGtow7RuZyBjaG8gcGjDqXAgY2jDum5nIHRhIGTDuW5nIEFOT1ZBLiBN4buZdCBnaeG6o2kgcGjDoXAgdGhheSB0aOG6vyBwaGkgdGhhbSBz4buRIChLcnVza2FsLVdhbGxpcyB0ZXN0KSBob+G6t2MgaG/DoW4gY2h1eeG7g24gZOG7ryBsaeG7h3UgY8OzIHRo4buDIMOhcCBk4bulbmcuIFR1eSBuaGnDqm4gduG7m2kgbeG7pWMgxJHDrWNoIG1pbmggaOG7jWEsIGNow7puZyB0YSB04bqhbSBjaOG6pXAgbmjhuq1uIGLhu48gcXVhIHZpIHBo4bqhbSBuw6B5LCB2w6AgdGjhu7FjIHJhIGtoaSBxdWFuIHPDoXQgNCBkZW5zaXR5IHBsb3QgY+G7p2EgWSwgdGEgdGjhuqV5IGNow7puZyBjw7MgcGjDom4gcGjhu5FpIMSR4buTbmcgZOG6oW5nLg0KDQpCw6J5IGdp4budIHRhIHRo4buxYyBoaeG7h24gQU5PVkE6IA0KDQpN4buZdCBxdXkgdHLDrG5oIEFOT1ZBIGhvw6BuIGNo4buJbmggcGjhuqNpIHRy4bqjIGzhu51pIMSRxrDhu6NjIDIgY8OidSBo4buPaSA6DQoNCkPDonUgaOG7j2kgMSkJWCBjw7MgdGjhuq10IHPhu7EgZ8OieSByYSBoaeG7h3Ug4bupbmcgw70gbmdoxKlhIGzDoG0gdGhheSDEkeG7lWkgWSBoYXkga2jDtG5nID8gKE7Ds2kgY8OhY2gga2jDoWMgOiBNw7QgaMOsbmggdHV54bq/biB0w61uaCBZPWYoWCkgY8OzIGNobyBwaMOpcCBnaeG6o2kgdGjDrWNoIMSRxrDhu6NjIHBo4bqnbiBs4bubbiBzYWkgYmnhu4d0IGPhu6dhIFkgaGF5IGtow7RuZyA/KSwgaGnhu4d1IOG7qW5nIGPhu6dhIFggbOG7m24gxJHhur9uIG3hu6ljIG7DoG8gPw0KDQpDw6J1IGjhu49pIHRo4bupIG5o4bqldCBuw6B5IMSRxrDhu6NjIGdp4bqjaSBxdXnhur90IGLhurFuZyBGIHRlc3QgbmjGsCBzYXUgOiANCg0KIVtdKGJheWVzYW5vdmEyLnBuZykNCg0KxJDhuqd1IHRpw6puIHRhIGThu7FuZyBt4buZdCBtw7QgaMOsbmggdHV54bq/biB0w61uaCBNIGPDsyBk4bqhbmcgWSA9IGYoWCkgKGNow7puZyB0YSBz4bq9IHTDrG0gaGnhu4N1IHLDtSBoxqFuIHbhu4EgbuG7mWkgZHVuZyBow6BtIGYgdHJvbmcgxJFv4bqhbiBzYXUpLiDDgXAgZOG7pW5nIG1vZGVsIE0gbsOgeSwgdGEgY8OzIHRo4buDIMaw4bubYyBsxrDhu6NuZyBnacOhIHRy4buLIHRydW5nIGLDrG5oIFlqIGPhu6dhIFkgdOG6oWkgbeG7l2kgY+G6pXAgYuG6rWMgaiBj4bunYSB54bq/dSB04buRIFguIFlqIMSRxrDhu6NjIGdp4bqjIMSR4buLbmggY8OzICBwaMOibiBwaOG7kWkgY2h14bqpbiAoTXVqLCBzaWdtYWopLCB0cm9uZyDEkcOzIE11aiBsw6AgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBk4buxIGLDoW8sIGPDsm4gc2lnbWFqIGNobyBiaeG6v3Qgc2FpIGJp4buHdCBtYW5nIHTDrW5oIG7hu5lpIHThuqFpICh0cm9uZyB04burbmcgcGjDom4gbmjDs20pIHbDoCBuZ+G6q3Ugbmhpw6puIHNvIHbhu5tpIGdpw6EgdHLhu4sgY8OzIHRo4buxYyBxdWFuIHPDoXQgxJHGsOG7o2MgKGPDsyB0aOG7gyB4ZW0gbmjGsCByZXNpZHVhbCBlcnJvciBj4bunYSBtb2RlbCBNIGhheSByZXNpZHVhbCBzdW0gb2Ygc3F1YXJlcyA9IFNTUikuDQoNClNTUiA9IFJlc2lkdWFsIHN1bSBvZiBzcXVhcmVzIA0KDQokJFNTUj1cc3VtX3tpPTF9XntufSh5X2ktXGhhdHt5fV9pKV4yJCQNCg0KVGEgbOG6oWkgY8OzIHRo4buDIHTDrW5oIMSRxrDhu6NjIGtob+G6o25nIGPDoWNoIHNhaSBiaeG7h3QgZ2nhu69hIE11aiB2w6AgZ2nDoSB0cuG7iyB0cnVuZyBiw6xuaCBj4bunYSBZIGNobyB0b8OgbiBxdeG6p24gdGjhu4MgKHThuqV0IGPhuqMgcGjDom4gbmjDs20gZ+G7mXAgbOG6oWkpLCDEkcOieSBsw6AgcGjhuqduIHNhaSBiaeG7h3QgZG8gc+G7sSBwaMOibiBuaMOzbSBnw6J5IHJhIChoYXkgcGjhuqduIGJp4bq/biB0aGnDqm4gY+G7p2EgWSBtw6AgbcO0IGjDrG5oIE0gY8OzIHRo4buDIGdp4bqjaSB0aMOtY2ggxJHGsOG7o2MpOg0KDQpTU00gPSBNb2RlbCBzdW0gb2Ygc3F1YXJlcw0KDQokJFNTTT1cc3VtX3tpPTF9XntufShcaGF0e3l9X2ktXGJhcnt5fSleMiQkDQpU4burIMSRw7MgdGEgY8OzOg0KDQpUcnVuZyBiw6xuaCBiw6xuaCBwaMawxqFuZyBtw7QgaMOsbmg6IE1lYW4gbW9kZWwgc3VtIG9mIHNxdWFyZXM6IE1TTQ0KDQokJE1TTT1cZnJhY3tTU1J9e2stMX0kJA0KVuG7m2kgayA9IHPhu5EgYuG6rWMgY+G7p2EgeeG6v3UgdOG7kSBYDQoNClRydW5nIGLDrG5oIGLDrG5oIHBoxrDGoW5nIG7hu5lpIHThuqFpIG5n4bqrdSBuaGnDqm4gOiBNZWFuIHJlc2lkdWFsIHN1bSBvZiBzcXVhcmVzDQoNCiQkTVNSPVxmcmFje1NTRX17bi1rfSQkDQoNClThu4kgc+G7kSBGIMSRxrDhu6NjIHjDoWMgxJHhu4tuaCBuaMawIHNhdToNCg0KJCRGPVxmcmFje01TTX17TVNSfSQkDQoNClThu4kgc+G7kSBGIGPDsyB0aOG7gyDEkcaw4bujYyDEkeG7i25oIG5naMSpYSB0aGVvIG5oaeG7gXUgY8OhY2gsIHRow60gZOG7pSA6IEY9IHThu4kgc+G7kSBnaeG7r2EgaGnhu4d1IOG7qW5nIGNow61uaCBnaeG7r2EgY8OhYyBwaMOibiBuaMOzbSBYaiB2w6AgaGnhu4d1IOG7qW5nIG7hu5lpIHThuqFpIHRyb25nIHThu6tuZyBwaMOibiBuaMOzbSBYaiwgaG/hurdjIEY9dOG7iSBz4buRIGdp4buvYSBwaMawxqFuZyBzYWkgZG8geeG6v3UgdOG7kSBYIHbDoCBwaMawxqFuZyBzYWkgZG8gbmfhuqt1IG5oacOqbiwgaG/hurdjIDogRiA9IHThu4kgc+G7kSBnaeG7r2EgcGjhuqduIHBoxrDGoW5nIHNhaSBtw6AgbcO0IGjDrG5oIGNobyBwaMOpcCBnaeG6o2kgdGjDrWNoIHbDoCBwaOG6p24gcGjGsMahbmcgc2FpIGPDsm4gbOG6oWkgbcOgIG3DtCBow6xuaCBraMO0bmcgdGjhu4MgZ2nhuqNpIHRow61jaC4NCg0KS2nhu4NtIMSR4buLbmggRiDEkcaw4bujYyBHacOhbyBzxrAgUm9uYWxkIEEuIEZpc2hlciAoMTg5MC0xOTYyKSwgbeG7mXQgbmjDoCBkaSB0cnV54buBbiB2w6AgdGjhu5FuZyBrw6ogaOG7jWMgbmfGsOG7nWkgQW5oIHRoaeG6v3Qga+G6vyByYSBuxINtIDE5MjAuIELhuqNuIGNo4bqldCBj4bunYSBGIHRlc3QgbMOgIG3hu5l0IHBo4bqjbiBuZ2hp4buHbSB24bubaSBsw70gbHXhuq1uIG5oxrAgc2F1Og0KDQpO4bq/dSBYIHRo4buxYyBz4buxIGfDonkgaGnhu4d1IOG7qW5nIHF1YW4gdHLhu41uZyDEkeG7kWkgduG7m2kgWSAodOG7qWMgbMOgIGfDonkgcmEgdGhheSDEkeG7lWkgbOG7m24gaMahbiBz4buxIGJp4bq/biB0aGnDqm4gbmfhuqt1IG5oacOqbiBj4bunYSBjaMOtbmggWSksIG3hu5l0IG3DtCBow6xuaCBNIMaw4bubYyBsxrDhu6NuZyBZIHRoZW8gWCBo4bqzbiBwaOG6o2kgcuG6pXQgcGjDuSBo4bujcCB24bubaSBk4buvIGxp4buHdSwgY8OhYyDEkWnhu4NtIGdpw6EgdHLhu4sgWWlqIHPhur0gbuG6sW0gcuG6pXQgZ+G6p24gxJHGsOG7nW5nIHRo4bqzbmcgaOG7k2kgcXV5IE09ZihYKS4gTSBz4bq9IGNobyBwaMOpcCBnaeG6o2kgdGjDrWNoIGjhuqd1IGjhur90IHBoxrDGoW5nIHNhaSBj4bunYSBZIHbDoCBjaOG7iSDEkeG7gyBs4bqhaSBwaOG6p24gc2FpIHPhu5EgZMawIG5o4buPIG5oxrAgduG6rXksIG5oxrAgduG6rXkgTVNNIGNo4bqvYyBjaOG6r24gbMOgIGzhu5tuIGjGoW4gc28gduG7m2kgTVNSLg0KDQpO4bq/dSB0YSBkw7luZyAxIGdpw6EgdHLhu4sgRiDEkeG6oWkgZGnhu4duIGNobyB04buJIGzhu4cgTVNNL01TUiwgaGnhu4d1IOG7qW5nIGPhu6dhIFggY8OgbmcgcXVhbiB0cuG7jW5nIHRow6wgRiBjw6BuZyBs4bubbi4NCg0KQsaw4bubYyB0aeG6v3AgdGhlbyBj4bunYSBwaOG6o24gbmdoaeG7h20gKG5oxrAgbeG7jWkgTnVsbCBoeXBvdGhlc2lzIHRlc3Rpbmcga2jDoWMpLCB0YSBz4bq9IGTDuW5nIEYgxJHhuqFpIGRp4buHbiBjaG8gaGnhu4d1IOG7qW5nIGPhu6dhIFg6IFRhIG114buRbiBjaOG7qW5nIG1pbmggbMOgIEYgxJHhu6cgbOG7m24gxJHhu4MgY8OzIHRo4buDIGfhu41pIGzDoCBjw7Mgw70gbmdoxKlhLiANCg0KR2nhuqMgdGh1eeG6v3QgMCBkbyDEkcOzIHPhur0gbMOgOiBDw7MgMSBnacOhIHRy4buLIEYnIGPDsm4gbOG7m24gaMahbiBGIG7hu69hICEgKEgwOiBGJyA+IEYpDQpHaeG6oyB0aHV54bq/dCBIMSBz4bq9IGzDoCA6IEYnIGtow7RuZyBs4bubbiBoxqFuIEYuDQoNCljDoWMgc3XhuqV0IHTDrG0gcmEgRicgxJHGsOG7o2MgeMOhYyDEkeG7i25oIHThu6sgaMOgbSBwZGYgY+G7p2EgbeG7mXQgcGjDom4gcGjhu5FpIOKAnEbigJ0sIHbhu5tpIDIgdGhhbSBz4buRIMSR4buZIHThu7EgZG8gdMawxqFuZyDhu6luZyB24bubaSAoay0xKSA6IHPhu5EgcGjDom4gbmjDs20gaGF5IGLhuq1jIGPhu6dhIFggdHLhu6sgMSwgdsOgIChOLWspIHbhu5tpIE49Y+G7oSBt4bqrdS4gTeG6rXQgxJHhu5kgeMOhYyBzdeG6pXQgKGdpw6EgdHLhu4sgcCkgc28gduG7m2kgbmfGsOG7oW5nIMO9IG5naMSpYSB0aOG7kW5nIGvDqiDEkcaw4bujYyBjaOG7jW4sIHRow60gZOG7pSBhbHBoYSA9IDAuMDUgc+G6vSBjaG8gYmnhur90IGto4bqjIG7Eg25nIEgwIMSRw7puZyBsw6AgdGjhuqVwIGjGoW4gaGF5IGNhbyBoxqFuIDAuMDUuDQoNCk7hur91IHA8MC4wNSB0aMOsIHRhIGPDsyB0aOG7gyBsb+G6oWkgYuG7jyBnaeG6oyB0aHV54bq/dCBIMC4gS+G6v3QgcXXhuqMgbsOgeSB0xrDGoW5nIMSRxrDGoW5nIHbhu5tpIHZp4buHYyBraOG6s25nIMSR4buLbmg6IEYgxJHhu6cgbOG7m24gxJHhu4MgY2hvIHBow6lwIHN1eSBkaeG7hW4gcuG6sW5nIGhp4buHdSDhu6luZyBj4bunYSBYIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouDQoNClNhdSDEkcOieSBsw6AgRiB0ZXN0IHbDoCBi4bqjbmcgQU5PVkEgY+G7lSDEkWnhu4NuIHRyb25nIFI6DQoNCsSQ4bqndSB0acOqbiwgTGV2ZW5lIHRlc3QgY2hvIHBow6lwIGto4bqzbmcgxJHhu4tuaCB0aOG7j2EgbcOjbiBnaeG6oyDEkeG7i25oIHBoxrDGoW5nIHNhaSDEkeG7k25nIG5o4bqldCxzYXUgxJHDsyBsw6Aga+G6v3QgcXXhuqMgY+G7p2EgaMOgbSBhb3YoKSBjdW5nIGPhuqVwIFNTTSwgU1NSLE1TTSxNU1IgdsOgIGRmIGPhu6dhIGNow7puZy4NCg0KVGEgY8OzIEYoMyw2MDIpID0gNi4zMTgsIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogduG7m2kgcD0wLjAwMDMNCg0KYGBge3IsbWVzc2FnZSA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9DQoNCmFvdihUQkwuTSB+IGRvc2UsIGRhdDApJT4lY2FyOjpsZXZlbmVUZXN0KCkNCg0KYW92KFRCTC5NIH4gZG9zZSwgZGF0MCklPiVzdW1tYXJ5KCkNCmBgYA0KDQpOZ2/DoGkgRiB0ZXN0LCB0YSBjw7JuIGPDsyB0aOG7gyB0w61uaCBuaOG7r25nIEVmZmVjdC1zaXplcyAoa8OtY2ggdGjGsOG7m2MgaGnhu4d1IOG7qW5nKSwgdGjDrSBk4bulOiBFdGFzcXVhcmVkLCByIHbDoCBPbWVnYXNxdWFyZWQNCg0KJCRcZXRhIF57Mn0gPSBcZnJhY3tTU019e1NTVH0kJA0KDQokJFxvbWVnYSBeezJ9ID0gXGZyYWN7U1NNLWRmbW9kZWwqTVNSfXtTU1QrTVNSfSQkDQoNCiQkciA9IFxzcXJ0e1xmcmFje1NTTX17U1NUfX0kJA0KDQpgYGB7cixtZXNzYWdlID0gRkFMU0Usd2FybmluZz1GQUxTRX0NCmFub3ZhZnVuYz1mdW5jdGlvbihvdXRwdXQpew0KICBvdXQ9b3V0cHV0JT4lc3VtbWFyeSgpDQogIGRmTT1vdXRbWzFdXSREZlsxXQ0KICBkZlI9b3V0W1sxXV0kRGZbMl0NCiAgRnZhbD1vdXRbWzFdXSRgRiB2YWx1ZWBbMV0NCiAgcDFzaWRlPSgxLShwZihGdmFsLGRmTSxkZlIsRikpKQ0KICBwMnNpZGVzPTIqcDFzaWRlDQogIFNTPW91dFtbMV1dJGBTdW0gU3FgWzFdDQogIE1TPW91dFtbMV1dJGBNZWFuIFNxYFsxXQ0KICBTU1I9b3V0W1sxXV0kYFN1bSBTcWBbMl0gICANCiAgTVNSPW91dFtbMV1dJGBNZWFuIFNxYFsyXQ0KICBldGEyPVNTLyhTUytTU1IpDQogIG9tZWdhMjwtIGRmTSooTVMtTVNSKSAvIChTUyArIFNTUiArIE1TUikNCiAgcjwtc3FydChldGEyKQ0KICByZXR1cm4oY2JpbmQoRnZhbCxkZk0sZGZSLHAxc2lkZSxwMnNpZGVzLGV0YTIsb21lZ2EyLHIpKQ0KfQ0KDQphb3YoVEJMLk0gfiBkb3NlLCBkYXQwKSU+JWFub3ZhZnVuYygpDQpgYGANCg0KR2nDoSB0cuG7iyBvbWVnYVNxciBoYXkgRXRhc3FyIHRoxrDhu51uZyDEkcaw4bujYyBkaeG7hW4gZ2nhuqNpIOG7nyAzIG3hu6ljOiBoaeG7h3Ug4bupbmcgbmjhu48gbuG6v3UgPCAwLjA1IHRydW5nIGLDrG5oIDogdOG7qyAwLjAxLTAuMDUgdsOgIGzhu5tuIG7hur91ID4gMC4xNSwgciDEkcaw4bujYyBzbyBzw6FuaCB24bubaSBuZ8aw4buhbmcgMC41LCBjw6BuZyBn4bqnbiAxIHRow6wgaGnhu4d1IOG7qW5nIGPDoG5nIGNhbw0KDQpDw6J1IGjhu49pIDIpCVPhu7Ega2jDoWMgYmnhu4d0IGdp4buvYSBjw6FjIHBow6JuIG5ow7NtIHbhu5tpIG5oYXUgbMOgIGJhbyBuaGnDqnUgPyBDw7Mgw70gbmdoxKlhIGhheSBraMO0bmcgPyAoTeG7pWMgdGnDqnUgc28gc8OhbmggYuG6r3QgY+G6t3AgZ2nhu69hIGPDoWMgcGjDom4gbmjDs20sIGhheSDEkeG7i25oIHbhu4sgc+G7sSBraMOhYyBiaeG7h3QgZ2nhu69hIGPDoWMgdGjhu6kgYuG6rWMgY+G7p2EgWCkuDQoNCkPDonUgaOG7j2kgdGjhu6kgMiBuw6B5IGPDsyBow6BtIMO9IHNvIHPDoW5oIHRydW5nIGLDrG5oIGdp4buvYSBjw6FjIHBow6JuIG5ow7NtLiBDw7MgaGFpIGPDoWNoIGdp4bqjaSBxdXnhur90IGPDonUgaOG7j2kgbsOgeSwgxJHDsyBsw6AgcG9zdC1ob2MgdGVzdCAoY8OzIGjDoG5nIGNo4bulYyBsb+G6oWksbmjGsCBUdWtleSwgQm9uZmVycm9uaSwgU2lkYWssIFNjaGVmZmUsIEhvY2hiZXJnLCBHYWJyaWVsLCBXYWxsZXItRHVuY2FuLCBEdW5ldHQsIE5ld21hbiBLZXVscywgTFNELCBUYW1oYW5lLCBSeWFuLUVpbm90LUdhYnJpZWwgV2Vsc2NoKSBoYXkgcGjDom4gdMOtY2ggQ29udHJhc3QuIA0KDQpQb3N0LWhvYyB0ZXN0IMSRxrDhu6NjIGTDuW5nIGtoaSB0YSBraMO0bmcgY8OzIGdp4bqjIHRodXnhur90IG7DoG8gY+G7pSB0aOG7gzsgcGjhu5UgYmnhur9uIG5o4bqldCBsw6AgQm9uZmVycm9uaSBoYXkgVHVrZXk7IHRyb25nIGtoaSBjb250cmFzdCBsw6AgbeG7mXQgdGjDrSBuZ2hp4buHbSBtYW5nIHTDrW5oIGNo4bunIHF1YW4sIHRyb25nIMSRw7MgdGEgZOG7sW5nIG3DtCBow6xuaCBjw7Mgw6FwIGThu6VuZyB0cuG7jW5nIHPhu5EgxJHhu4MgdOG6oW8gcmEgdMawxqFuZyBwaOG6o24gdHLDqm4gbW9kZWwgbWF0cml4LiANCg0KU2F1IMSRw6J5IGzDoCB0aMOtIGThu6UgduG7m2kgQm9uZmVycm9uaSBwb3N0LWhvYyB0ZXN0Og0KDQpgYGB7cixtZXNzYWdlID0gRkFMU0Usd2FybmluZz1GQUxTRX0NCnBhaXJ3aXNlLnQudGVzdChkYXQwJFRCTC5NLCBkYXQwJGRvc2UscC5hZGp1c3QubWV0aG9kPSJib25mZXJyb25pIikNCmBgYA0KDQpWw4AgVHVrZXkgcG9zdC1ob2MgdGVzdA0KDQpgYGB7cixtZXNzYWdlID0gRkFMU0Usd2FybmluZz1GQUxTRX0NCmFvdihUQkwuTSB+IGRvc2UsIGRhdGE9ZGF0MCklPiVUdWtleUhTRCgpDQoNCmFvdihUQkwuTSB+IGRvc2UsIGRhdGE9ZGF0MCklPiVUdWtleUhTRCgpJT4lcGxvdCgpDQoNCmBgYA0KDQpDw7JuIMSRw6J5IGzDoCB0aMOtIGThu6UgbWluaCBo4buNYSB24buBIDEgcGjDom4gdMOtY2ggY29udHJhc3Q6DQoNCmBgYHtyLG1lc3NhZ2UgPSBGQUxTRSx3YXJuaW5nPUZBTFNFfQ0KY250ck1hdCA8LSByYmluZCgiRCB2cyBBIj1jKCAtMSwgICAwLCAgIDAsICAxKSwNCiAgICAgICAgICAgICAgICAgIkQgdnMgQiI9YyggMCwgICAtMSwgICAwLCAgMSksDQogICAgICAgICAgICAgICAgICJEIHZzIEMiPWMoIDAsICAgMCwgICAtMSwgIDEpLA0KICAgICAgICAgICAgICAgICAiKEJDRCkgdnMgQSI9YyggLTEsICAgMS8zLCAgIDEvMywgIDEvMyksDQogICAgICAgICAgICAgICAgICIoKENEKSB2cyAoQUIpKSIgICA9YyggLTEvMiwgICAtMS8yLCAgIDEvMiwgIDEvMiksDQogICAgICAgICAgICAgICAgICJEIHZzIChBQkMpIiAgICA9YyggLTEvMywgICAtMS8zLCAgIC0xLzMsICAxKSwNCiAgICAgICAgICAgICAgICAgIihDRCkgdnMgQSIgICAgPWMoIC0xLCAgMCwgICAxLzIsICAxLzIpLA0KICAgICAgICAgICAgICAgICAiKENEKSB2cyBCIiAgICA9YyggMCwgIC0xLCAgIDEvMiwgIDEvMikNCiAgICAgICAgICAgICAgICAgKQ0KDQpsaWJyYXJ5KG11bHRjb21wKSAgICAgICAgICAgICAgICAgDQpvdXQ9YW92KFRCTC5NIH4gZG9zZSwgZGF0YT1kYXQwKQ0KDQpzdW1tYXJ5KGdsaHQob3V0LGxpbmZjdD1tY3AoZG9zZT1jbnRyTWF0KSxhbHRlcm5hdGl2ZT0idHdvLnNpZGVkIiksDQogICAgICAgIHRlc3Q9YWRqdXN0ZWQoImJvbmZlcnJvbmkiKSkNCmBgYA0KDQojIFBow6FpIEZyZXF1ZW50aXN0IHbDoCB24bqlbiDEkeG7gSBj4buhIG3huqt1DQoNClNhdSBraGkgdMOsbSBoaeG7g3UgduG7gSBu4buZaSBkdW5nIGPhu6dhIEFOT1ZBIGPhu5UgxJFp4buDbiwgY2jhuq9jIGPDoWMgYuG6oW4gxJHDoyBjw7MgdGjhu4MgaMOsbmggZHVuZyB24buBIG3hu5l0IHPhu5EgxJHhurdjIHTDrW5oIGPhu6dhIG5o4buvbmcgY8O0bmcgY+G7pSB0aOG7kW5nIGvDqiBj4buVIMSRaeG7g24sIMSRw7MgbMOgIDoNCg0KQ8OhYyBuaMOgIHRo4buRbmcga8OqIGPhu5UgxJFp4buDbiB0aMaw4budbmcga2jDtG5nIGdp4bqjaSBxdXnhur90IHRy4buxYyB0aeG6v3AgY8OidSBo4buPaSAoZ2nhuqMgdGh1eeG6v3QpIG5naGnDqm4gY+G7qXUgdOG7qyBk4buvIGxp4buHdSA7IG5oxrBuZyBo4buNIMSR4bq3dCByYSBt4buZdCB0cuG7iyBz4buRIHRo4buRbmcga8OqIG1hbmcgdMOtbmggxJHhuqFpIGRp4buHbiwgdGjDrSBk4bulIHQgdHJvbmcgU3R1ZGVudCB0IHRlc3QsIENoaTIgdHJvbmcgUGVhcnNvbuKAmXMgQ2hpc3F1YXJlZCB0ZXN0LCBGIHRyb25nIEZpc2hlcuKAmXMgRiB0ZXN0IDsgc2F1IMSRw7MgaOG7jSBkw7luZyBwaMawxqFuZyBwaMOhcCBQaOG6o24gbmdoaeG7h20sIMSR4buDIGNodXnhu4NuIGdp4bqjIHRodXnhur90IG5naGnDqm4gY+G7qXUgdGjDoG5oIG3hu5l0IGdp4bqjIHRodXnhur90IEgxIMSR4buRaSBs4bqtcCB24bubaSAxIGdp4bqjIHRodXnhur90IEgwLiBI4buNIGNobyBy4bqxbmcgbuG6v3UgYsOhYyBi4buPIMSRxrDhu6NjIEgwIHRow6wgeGVtIG5oxrAgSDEgxJHDum5nLiBDw6FjaCBsw6BtIG7DoHkgbMOgIGtow7RuZyBob8OgbiBo4bqjbyB0csOqbiB0aOG7sWMgdOG6vy4gxJDhuqd1IHRpw6puLCBnaeG6oyB0aHV54bq/dCBIMCDEkcaw4bujYyBraeG7g20gY2jhu6luZyBkdXkgbmjhuqV0IGLhurFuZyB0cuG7iyBz4buRIHRo4buRbmcga8OqIHRydW5nIGdpYW4gdsOgIMSR4bqhaSBkaeG7h24gbcOgIHRhIHbhu6thIG7Ds2ksIHbDoCBk4buxYSB2w6BvIG3hu5l0IHBow6JuIHBo4buRaSBtYW5nIHTDrW5oIGNo4bqldCDCqyB0xrDhu59uZyB0xrDhu6NuZywgZ2nhuqMgxJHhu4tuaCDCuyBj4bunYSB0cuG7iyBz4buRIG7DoHksIHRow60gZOG7pSBDaGlzcXVhcmVkLCB0LCBGLiBTYXUgbuG7r2EgbMOgIGPDoWNoIHBow6F0IGJp4buDdSBnaeG6oyB0aHV54bq/dCBIMCwgSDEuIE5nYXkgY+G6oyBraGkgYsOhYyBi4buPIMSRxrDhu6NjIEgwLCBraMO0bmcgxJHhu5NuZyBuZ2jEqWEgduG7m2kgdmnhu4djIEgxIGzDoCDEkcO6bmcgKGPDsyB0aOG7gyBjw7JuIG5oaeG7gXUgZ2nhuqMgdGh1eeG6v3QgdGhheSB0aOG6vyBraMOhYyBuaMawIEgyLCBIMyA/KS4gU2F1IG7hu69hLCB2aeG7h2MgxJHhurd0IHJhIG5nxrDhu6FuZyDDvSBuZ2jEqWEgMC4wNSBjaG8gdHLhu4sgc+G7kSBwIHbDtCB0w6xuaCDEkcOjIGtoaeG6v24gbmfGsOG7nWkgbmdoacOqbiBj4bupdSBuaMOsbiB0aOG6vyBnaeG7m2kgY2jhu4kgYuG6sW5nIDIgbcOgdSBUcuG6r25nIGhv4bq3YyDEkGVuLCB0cm9uZyBraGkgc+G7sSB0aOG6rXQgbOG6oWkgbMOgIG3DoHUgeMOhbS4gDQoNCk3hu5l0IG5oxrDhu6NjIMSRaeG7g20ga2jDoWMgY+G7p2EgcGjDoWkgRnJlcXVlbnRpc3QsIMSRw7MgbMOgIG3hu41pIHRo4bupIMSR4buBdSBwaOG7pSB0aHXhu5ljIHbDoG8gY+G7oSBt4bqrdS4gQ2jDum5nIHRhIGPDsyB0aOG7gyBtaW5oIGjhu41hIGNobyB24bqlbiDEkeG7gSBuw6B5IHF1YSB0aMOtIG5naGnhu4dtIG5o4buPIHNhdSDEkcOieSA6IFTGsOG7n25nIHTGsOG7o25nIGPDuW5nIG5naGnDqm4gY+G7qXUgbsOgeSwgY2jDum5nIHRhIHRo4buxYyBoaeG7h24gQU5PVkEgY2hvIDE3IG3huqt1IGtow6FjIG5oYXUgY8OzIGvDrWNoIHRoxrDhu5tjIE4gdMSDbmcgZOG6p24gdOG7qyA2MCAoMTAlKSDEkeG6v24gNjA2ICgxMDAlKS4gDQoNCmBgYHtyfQ0KDQpzaW1BTk9WQWRmPWRhdGEuZnJhbWUoDQogc2FtcGxlPXJlcChOQSwxNyksDQogZGZSPXJlcChOQSwxNyksDQogRnZhbD1yZXAoTkEsMTcpLA0KIHAxc2lkZT1yZXAoTkEsMTcpLA0KIHAyc2lkZXM9cmVwKE5BLDE3KSwNCiBvbWVnYTI9cmVwKE5BLDE3KSwNCiBldGEyPXJlcChOQSwxNykNCikNCg0KcmF0aW89YygxMDAsOTAsODAsNzAsNjAsNTAsNDAsMzAsMjgsMjUsMjIsMjAsMTgsMTYsMTQsMTIsMTApDQoNCmZvciAoaSBpbiAxOjE3KXsNCiAgc2V0LnNlZWQoMTIzKQ0KICBzcGxpdHJhdGlvPXJhdGlvW2ldDQogIGlkc3BsaXQ9Y2FyZXQ6OmNyZWF0ZURhdGFQYXJ0aXRpb24oeT1kYXQwJGRvc2UsIHA9c3BsaXRyYXRpby8xMDAsbGlzdD1GQUxTRSkNCiAgdGVtcHN1YnNldD1kYXQwW2lkc3BsaXQsXQ0KICBvdXRwdXQ9YW92KFRCTC5NIH4gZG9zZSx0ZW1wc3Vic2V0KQ0KICByZXM9YW5vdmFmdW5jKG91dHB1dCkNCiAgc2ltQU5PVkFkZiRGdmFsW2ldPXJlc1tbMV1dDQogIHNpbUFOT1ZBZGYkZGZSW2ldPXJlc1tbM11dDQogIHNpbUFOT1ZBZGYkc2FtcGxlW2ldPW5yb3codGVtcHN1YnNldCkNCiAgc2ltQU5PVkFkZiRwMXNpZGVbaV09cmVzW1s0XV0NCiAgc2ltQU5PVkFkZiRwMnNpZGVzW2ldPXJlc1tbNV1dDQogIHNpbUFOT1ZBZGYkb21lZ2EyW2ldPXJlc1tbN11dDQogIHNpbUFOT1ZBZGYkZXRhMltpXT1yZXNbWzZdXQ0KfQ0KDQpzaW1BTk9WQWRmPXNpbUFOT1ZBZGYlPiVhc190aWJibGUoKQ0KDQpzaW1BTk9WQWRmJT4lZ2F0aGVyKGRmUjpldGEyLGtleT0iUGFyYSIsdmFsdWU9IkVzdGltYXRlZCIpJT4lDQogIGdncGxvdChhZXMoeD1zYW1wbGUseT1Fc3RpbWF0ZWQpKSsNCiAgZ2VvbV9wYXRoKGFlcyhjb2w9UGFyYSksc2hvdy5sZWdlbmQgPSBGLHNpemU9MSkrDQogIGdlb21fcG9pbnQoc2hhcGU9MjEsYWVzKGZpbGw9UGFyYSksY29sPSJibGFjayIsc2hvdy5sZWdlbmQgPSBGLHNpemU9MykrDQogIHRoZW1lX2J3KCkrDQogIGZhY2V0X3dyYXAoflBhcmEsc2NhbGVzPSJmcmVlX3kiLG5jb2w9MikNCg0KYGBgDQoNCkvhur90IHF14bqjIG3DtCBwaOG7j25nIGNobyB0aOG6pXkgOiBnacOhIHRy4buLIGPhu6dhIEYsIHBfdmFsdWUgY+G7p2EgRl90ZXN0LCB2w6AgY8OhYyBlZmZlY3Qgc2l6ZSDEkeG7gXUgcGjhu6UgdGh14buZYyB2w6BvIGPhu6EgbeG6q3UuIENow7puZyBjaOG7iSB0cuG7nyBuw6puIOG7lW4gxJHhu4tuaCB2w6AgxJHDoW5nIHRpbiBj4bqteSB24bubaSDDrXQgbmjhuqV0IE4+MjAwIE4gY8OgbmcgY2FvIHRow6wgRiBjw6BuZyBjYW87IHBfdmFsdWUga2jDtG5nIGPDsyDDvSBuZ2jEqWEgbuG6v3UgTiBxdcOhIHRo4bqlcCwgdsOgIGVmZmVjdC1zaXplIGNo4buJIOG7lW4gxJHhu4tuaCB24bubaSBOIMSR4bunIGzhu5tuLiANCg0KxJDDsyBsw6Agbmd1ecOqbiBuaMOibiBraGnhur9uIG5ow7NtIEJBViBxdXnhur90IMSR4buLbmggcGjDoXQgxJHhu5luZyBk4buxIMOhbiBCYXllcyBGb3IgVmlldG5hbSwgbmjhurFtIGdp4bubaSB0aGnhu4d1IG3hu5l0IGjGsOG7m25nIMSRaSBraMOhYyBzbyB24bubaSB0csaw4budbmcgcGjDoWkgRnJlcXVlbnRpc3QgY+G7lSDEkWnhu4NuIHbDoCBOdWxsIGh5cG90aGVzaXMgdGVzdGluZy4gVHLGsOG7nW5nIHBow6FpIEJheWVzIGNobyBwaMOpcCBjw6FjIGLhuqFuIMSR4buLbmggduG7iywgeMOhYyBs4bqtcCB0cuG6oW5nIHRow6FpIGPhu6dhIEgxLCBoYXkgbsOzaSBjw6FjaCBraMOhYywgbMOgIG3hu6ljIMSR4buZIGto4bqjIHTDrW4sIG5p4buBbSB0aW4gY+G7p2EgY8OhYyBi4bqhbiB2w6BvIEgxIGThu7FhIHbDoG8gZOG7ryBsaeG7h3UgdGjhu7FjIHThur8sIGhp4buHbiB04bqhaSBtw6AgYuG6oW4gxJFhbmcgY8OzIChDaMO6bmcgdGEga2jDtG5nIGPhuqduIMSR4bq/biBwX3ZhbHVlIG7hu69hKS4gQmF5ZXMgY8OybiBjaG8gcGjDqXAgIGjDsmEgaOG7o3AgxJHGsOG7o2MgdGjDtG5nIHRpbiwgZ2nhuqMgdGh1eeG6v3QgdGnhu4FuIMSR4buLbmggdsOgIGxpa2VsaWhvb2QgxJHhu4MgdMOsbSByYSBwaMOibiBwaOG7kWkgaOG6rXUgxJHhu4tuaA0KDQrEkOG6v24gxJHDonksIHRhIHThuqFtIGThu6tuZyBwaOG6p24gQU5PVkEgY+G7lSDEkWnhu4NuIHbDoCBjaHV54buDbiBzYW5nIHBo4bqnbiBjaMOtbmggY+G7p2EgYsOgaSwgxJHDsyBsw6AgQU5PVkEgdGhlbyBCYXllczoNCg0KIyBHaeG6o2kgcGjDoXAgQmF5ZXMgY2hvIEFOT1ZBIDEgeeG6v3UgdOG7kQ0KDQpDw7Mgbmhp4buBdSBjw6FjaCDEkeG7gyBiaeG7g3UgZGnhu4VuIGjDoG0gZihYKSB0cm9uZyBtw7QgaMOsbmggeX5mKFgpLCB0aMOtIGThu6UgOg0KDQoqWSB+IDEgKyAoMXxYaikqIDogTcO0IGjDrG5oIG7DoHkgdMawxqFuZyDEkcawxqFuZyB24bubaSBt4buZdCBow6BtIHjDoWMgc3XhuqV0IGPDsyDEkWnhu4F1IGtp4buHbiwgY2hvIHBow6lwIHTDrW5oIHRydW5nIGLDrG5oIE11IGPhu6dhIFkgdOG6oWkgbeG7l2kgcGjDom4gbmjDs20gWGoNCg0KKll+WCosIG3DtCBow6xuaCBuw6B5IGPDsyBtYXRyaXggYmFvIGfhu5NtIDQgYmnhur9uIDogSW50ZXJjZXB0ICh0aGFtIHPhu5EgYmV0YTEpICDEkeG6oWkgZGnhu4duIGNobyBj4bqlcCBi4bqtYyB0aOG7qSBuaOG6pXQgY+G7p2EgWCAodGjDrSBk4bulIHBow6JuIG5ow7NtIEEpLCB2w6AgIDMgYmnhur9uIGdp4bqjIChkdW1teSB2YXIpIMSR4bqhaSBkaeG7h24gY2hvIDMgcGjDom4gbmjDs20gQixDLEQpLiBOaMawIHbhuq15IA0KDQpZIH4gYmV0YTEgKyBiZXRhMi4oWD1CKStiZXRhMy4oWD1DKSArIGJldGE0KihYPUQpLiANCg0KVHV5IG5oacOqbiwgdGhhbSBz4buRIGjhu5NpIHF1eSBiZXRhMiwgYmV0YTMsIGJldGE0IGNo4buJIGNobyBiaeG6v3Qga2jDoWMgYmnhu4d0IHRydW5nIGLDrG5oIGPhu6dhIFkgdOG6oWkgQixDLEQgc28gduG7m2kgQQ0KDQoqWSB+IFgg4oCTIDEqIDsgbcO0IGjDrG5oIG7DoHkgdMawxqFuZyDEkcawxqFuZyB24bubaSBtw7QgaMOsbmggMSBuaMawbmcga2jDtG5nIGNo4bupYSBJbnRlcmNlcHQgKC0xKSwga2hpIMSRw7MgbWF0cml4IGPhu6dhIG3DtCBow6xuaCBz4bq9IGzDoCA0IGR1bW15IHZhcmlhYmxlcyAoQSxCLEMsRCkgdMawxqFuZyDhu6luZyB24bubaSA0IHRoYW0gc+G7kSBo4buTaSBxdXkgYmV0YTEsIGJldGEyLCBiZXRhMywgYmV0YTQg4oCTIGzhuqduIGzGsOG7o3QgY2jDrW5oIGzDoCB0cnVuZyBiw6xuaCBj4bunYSBZIHThuqFpIG3hu5dpIHBow6JuIG5ow7NtLg0KDQpEw7kgbMOgIG3DtCBow6xuaCBuw6BvLCB0YSDEkeG7gXUgY8OzIHRo4buDIHRy4bqjIGzhu51pIGPDonUgdGjhu6kgMSwgdsOsIEYgdGVzdCBk4buxYSB2w6BvIHZp4buHYyB0w61uaCBzdW0gb2Ygc3F1YXJlcywgbmjGsG5nIGNow7puZyB0YSBwaOG6o2kgY2jhu41uIGPDoWNoIG7DoG8gY2hvIHBow6lwIGdp4bqjaSDEkcOhcCBj4bqjIGPDonUgdGjhu6kgMiB0aMOsIG3hu5tpIGzDoCB04buRaSDGsHUuIERvIMSRw7MgaMOgbSBmKFgpIGPhu6dhIG3DtCBow6xuaCB0aOG7qSAzIChraMO0bmcgY2jhu6lhIGludGVyY2VwdCkgxJHGsOG7o2MgY2jhu41uIMSR4buDIGThu7FuZyBtw7QgaMOsbmggQmF5ZXMuDQoNCiMgTcO0IGjDrG5oIEJheWVzIHRyb25nIFNUQU4NCg0KIVtdKGJheWVzYW5vdmEzLnBuZykNCg0KTmjGsCB24bqteSB0cm9uZyBiw6BpIG7DoHksIGNow7puZyB0YSBz4bq9IGNodXnhu4NuIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggWSB04bqhaSBt4buXaSBwaMOibiBuaMOzbSBBLEIsQyxEIHRow6BuaCA0IHRoYW0gc+G7kSBiZXRhMSwgYmV0YTIsIGJldGEzIHbDoCBiZXRhNC4gTcO0IGjDrG5oIGPDsyBk4bqhbmc6DQoNCiQkeV97aWp9ID0gXGJldGEgX3sxaX0rXGJldGEgX3syaX0rXGJldGEgX3szaX0gKyBcYmV0YSBfezRpfSArIFxlcHNpbG9uIF97aWp9JCQNCg0KVHJvbmcgxJHDsywgeWlqIGzDoCBnacOhIHRy4buLIGPhu6dhIGJp4bq/biBr4bq/dCBxdeG6oyBZIHThuqFpIHRyxrDhu51uZyBo4bujcCB0aOG7qSBpIHbDoCBwaMOibiBuaMOzbSBqOyBiZXRhamkgbMOgIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggZOG7sSBiw6FvIGPhu6dhIHBow6JuIG5ow7NtIGosIHbDoCBlaWogbMOgIHNhaSBz4buRIHThu5NuIGzGsHUgY+G7p2EgbcO0IGjDrG5oLg0KDQpUcsaw4bubYyBo4bq/dCB0YSB2aeG6v3QgbcO0IGjDrG5oIHRyb25nIFNUQU4gduG7m2kgY+G6pXUgdHLDumMgbmjGsCBzYXU6DQoNClNUQU4gY29kZSDEkcaw4bujYyBsxrB1IGTGsOG7m2kgZOG6oW5nIGNodeG7l2kga8OtIHThu7EgKHN0cmluZyksDQoNCm1vZGVsLnRleHQgPC0gICIuLi4uLiINCg0KbeG7mXQgY2jGsMahbmcgdHLDrG5oIFNUQU4gY8OzIG5oaeG7gXUgYmxvY2sgdsOgIG3hu5dpIGJsb2NrIGPDsyB2YWkgdHLDsiBraMOhYyBuaGF1Og0KDQoxKSBCbG9jayBkYXRhOiBUw6puIGfhu41pLCBsb+G6oWkgdsOgIHBo4bqhbSB2aSBj4bunYSB04burbmcgeeG6v3UgdOG7kSB0cm9uZyBk4buvIGxp4buHdSDEkeG6p3UgdsOgbyBwaOG6o2kgxJHGsOG7o2Mga2hhaSBiw6FvIHRyb25nIGJsb2NrIG7DoHkNCg0KTiBsw6AgbeG7mXQgc+G7kSBuZ3V5w6puIGTGsMahbmcgY2jhu4kgY+G7oSBt4bqrdQ0KDQpKIGzDoCAxIHPhu5Egbmd1ecOqbiBkxrDGoW5nLCBjaOG7iSBz4buRIGLhuq1jIGPhu6dhIHnhur91IHThu5EgWCAoc+G7kSBwaMOibiBuaMOzbSkNCg0KeSBsw6AgMSB2ZWN0b3Igc+G7kSB0aOG7sWMgY8OzIMSR4buZIGTDoGkgPSBODQoNCnggbMOgIDEgdmVjdG9yIHPhu5Egbmd1ecOqbiBkxrDGoW5nLCBkYW8gxJHhu5luZyB04burIDEgxJHhur9uIEogdsOgIGPDsyDEkeG7mSBkw6BpIE4NCg0KDQoyKSBCbG9jayBwYXJhbWV0ZXI6DQoNCk5oxrAgdMOqbiBn4buNaSBj4bunYSBuw7MsIMSRw6J5IGzDoCBuxqFpIGtoYWkgYsOhbyB24buBIGPDoWMgdGhhbSBz4buRIG3DoCB0YSBj4bqnbiB0cm9uZyBtw7QgaMOsbmguIE5oxrAgxJHDoyB0csOsbmggYsOgeSwgdGEgY8OzIDIgbG/huqFpIHRoYW0gc+G7kTogYmV0YSAodHJ1bmcgYsOsbmggbeG7l2kgcGjDom4gbmjDs20sIGhheSB0aGFtIHPhu5EgaOG7k2kgcXV5IHRyb25nIG3DtCBow6xuaCksIGzDoCBt4buZdCB2ZWN0b3Igc+G7kSB0aOG7sWMgY8OzIGvDrWNoIHRoxrDhu5tjIEogKEo9MSwyLDMsNCkgdsOgIHNpZ21hIGzDoCBTRCBj4bunYSByZXNpZHVhbCwgbMOgIDEgc+G7kSB0aOG7sWMgDQoNCjMpIEJsb2NrIFRyYW5zZm9ybWVkIHBhcmFtZXRlcnM6DQoNCkJsb2NrIG7DoHkga2jDtG5nIGLhuq90IGJ14buZYyBwaOG6o2kgY8OzIGNobyBt4buNaSBtw7QgaMOsbmggdsOsIG7DsyB0w7l5IHRodeG7mWMgdsOgbyBt4bulYyDEkcOtY2ggY+G7p2EgbmfGsOG7nWkgdmnhur90IGNvZGUgdsOgIMSR4buZIHBo4bupYyB04bqhcCBj4bunYSBtw7QgaMOsbmguIEPhuqduIGNow7ogw70gbMOgIG3hu41pIHRoYW0gc+G7kSB04bqhbyByYSB0cm9uZyBibG9jayBuw6B5IGPFqW4gc+G6vSDEkcaw4bujYyBs4bqleSBt4bqrdSBjaG8gY2h14buXaSBNQ01DIHbDoCB4deG6pXQgcmEga+G6v3QgcXXhuqMgbcO0IGjDrG5oIG5oxrAgY8OhYyB0aGFtIHPhu5EgdHJvbmcgYmxvY2sgcGFyYW1ldGVyLg0KDQpUcm9uZyBibG9jayBuw6B5LCB0YSBraGFpIGLDoW8gdGhhbSBz4buRIE11IGzDoCB0cnVuZyBiw6xuaCBk4buxIGLDoW8gY+G7p2EgWSwgduG7m2kgbGlrZWxpaG9vZCBsw6AgWSDEkcaw4bujYyBtw7QgdOG6oyBi4bqxbmcgcGjDom4gcGjhu5FpIGNodeG6qW4gY8OzIHRydW5nIGLDrG5oIE11IHbDoCBTRD1zaWdtYTsgc2F1IMSRw7MgdGEgdmnhur90IDEgdsOybmcgbOG6t3AgxJHhu4MgbGnDqm4ga+G6v3QgTXUgdsOgIEJldGEgY2hvIG3hu5dpIGNhc2UgaQ0KDQo0KSBCbG9jayBNb2RlbDogVHJvbmcgYmxvY2sgbsOgeSB0YSBz4bq9IGtoYWkgYsOhbyB24buBIHRow6BuaCBwaOG6p24gbGlrZWxpaG9vZCB2w6AgcHJpb3JzIChnaeG6oyB0aHV54bq/dCB0aeG7gW4gxJHhu4tuaCB24buBIHBow6JuIHBo4buRaSBj4bunYSB04burbmcgdGhhbSBz4buRKS4NCg0KVHJvbmcgbcO0IGjDrG5oIG7DoHksIGxpa2VsaWhvb2QgbMOgIHkgfiBub3JtYWwgKE11LCBzaWdtYSk7IFRhIGPDsyAyIHRoYW0gc+G7kSBsw6AgYmV0YSB2w6AgU2lnbWEuIE7hur91IHRhIGtow7RuZyBraGFpIGLDoW8gcHJpb3IsIFNUQU4gc+G6vSBt4bq3YyDEkeG7i25oIGTDuW5nIHByaW9yIFVuaWZvcm0gY2hvIHRoYW0gc+G7kSDEkcOzLiDhu54gxJHDonkgdGEgZMO5bmcgcHJpb3IgIm5vbiBpbmZvcm1hdGl2ZSIgbMOgIGhhbGYtQ2F1Y2h5IGNobyBzaWdtYSwgdsOgIDEgZ2nhuqMgdGh1eeG6v3QgdGnhu4FuIMSR4buLbmggcuG6sW5nIGJldGEgY8OzIHBow6JuIHBo4buRaSBjaHXhuqluLCBkYW8gxJHhu5luZyBxdWFuaCB0cnVuZyBiw6xuaCA9IDEwIHbDoCBzZD0xMDAuDQoNCk5nb8OgaSByYSwgdGEgY8OybiBjw7MgdGjhu4MgZMO5bmcgdGjDqm0gYmxvY2sgdGjhu6kgNSDEkeG7gyBs4bqleSBt4bqrdSBjaG8gY8OhYyB0aGFtIHPhu5EgcGjhu6UgaGF5IHBow6FpIHNpbmggdOG7qyBjw6FjIHBhcmFtZXRlciBjw7Mgc+G6tW4gdHJvbmcgbcO0IGjDrG5oOyB0dXkgbmhpw6puIHZp4buHYyBuw6B5IGtow7RuZyB0aOG7sWMgc+G7sSBxdWFuIHRy4buNbmcsIG5o4bqldCBsw6Agdmnhu4djIHTDrW5oIHRvw6FuIG5oaeG7gXUgdGhhbSBz4buRIGLhurFuZyBjw6FjaCBs4bqleSBt4bqrdSBz4bq9IGzDoG0gcXV5IHRyw6xuaCB04bqhbyBNQ01DIHF1w6EgdOG6o2kgbeG7mXQgY8OhY2gga2jDtG5nIGPhuqduIHRoaeG6v3QuIA0KDQpgYGB7cixtZXNzYWdlID0gRkFMU0Usd2FybmluZz1GQUxTRX0NCmxpYnJhcnkocnN0YW4pDQoNCm1vZGVsLnRleHQgPC0gICJkYXRhIHsNCmludDxsb3dlcj0wPiBOOyAgICAgICAgICAgICAgIC8vbm8gb2Ygb2JzDQppbnQ8bG93ZXI9Mj4gSjsgICAgICAgICAgICAgICAvL25vIG9mIGdyb3VwDQpyZWFsIHlbTl07ICAgICAgICAgICAgICAgICAgICAvL2RlcGVuZGVudCB2YXJpYWJsZQ0KaW50PGxvd2VyPTAsdXBwZXI9Sj4geFtOXTsgICAgLy9wcmVkaWN0b3INCg0KfQ0KcGFyYW1ldGVycyB7DQp2ZWN0b3JbSl0gYmV0YTsgICAgICAgICAgICAgICAgIC8vbWVhbiBvZiBlYWNoIGdyb3VwIA0KcmVhbCBzaWdtYTsgICAgICAgICAvL1NEIHJlc2lkdWFscw0KfQ0KDQp0cmFuc2Zvcm1lZCBwYXJhbWV0ZXJzIHsNCnZlY3RvcltOXSBNdTsgICAgICAgLy9wcmVkaWN0ZWQgbWVhbiBvZiBlYWNoIGVhY2ggb2JzDQpmb3IgKGkgaW4gMTpOKSB7DQogICAgTXVbaV0gPSBiZXRhW3hbaV1dOw0KfQ0KfQ0KDQptb2RlbCB7IA0KDQovL0xpa2VsaWhvb2QNCnkgfiBub3JtYWwoTXUsIHNpZ21hKTsNCg0KLy9QcmlvcnMNCmJldGEgfiBub3JtYWwoMTAsMTAwKTsNCnNpZ21hfmNhdWNoeSgwLDUpOw0KfQ0KIg0KYGBgDQoNClNhdSBraGkgY29kZSBtw7QgaMOsbmgsIHRhIHPhur0gdOG6oW8gcmEgZOG7ryBsaeG7h3UgxJHhuqd1IHbDoG8gY2hvIHBow6JuIHTDrWNoIEJheWVzLCBkxrDhu5tpIGThuqFuZyAxIGxpc3QsIHRyb25nIMSRw7MgdGEga2hhaSBiw6FvIGPDoWMgdGjDoG5oIHBo4bqnbiBtw6AgYmxvY2sgZGF0YSDEkcOjIG3DtCB04bqjLCBn4buTbSB2ZWN0b3IgeSwgeCwgMiBz4buRIG5ndXnDqm4gTiB2w6AgSg0KDQpgYGB7cn0NCmRhdCA8LSBsaXN0KHkgPSBkYXQwJFRCTC5NLA0KICAgICAgICAgICAgeCA9IGRhdDAkZG9zZSAlPiUgYXMuaW50ZWdlcigpLA0KICAgICAgICAgICAgTiA9IG5yb3coZGF0MCksDQogICAgICAgICAgICBKID0gbmxldmVscyhkYXQwJGRvc2UpKQ0KYGBgDQoNClRhIMSRxrBhIGRhdGEgdsOgbyBtw7QgaMOsbmggdsOgIGvDrWNoIGhv4bqhdCBxdXkgdHLDrG5oIGzhuqV5IG3huqt1IE1DTUMgduG7m2kgY8OhYyB0w7l5IGNo4buJbmggVGEgc+G6vSBjaOG6oXkgMiBjaHXhu5dpIHNvbmcgc29uZzogVHLGsOG7m2MgaOG6v3Qgc2FtcGxlciBz4bq9IGNo4bqheSA1MDAgbMaw4bujdCBraOG7n2kgxJHhu5luZywga2hpIOG7lW4gxJHhu4tuaCB0aMOsIGvhur90IHF14bqjIE1DTUMgYuG6r3QgxJHhuqd1IMSRxrDhu6NjIGdoaSBs4bqhaSAyNTAwIGzGsOG7o3QgY2hvIG3hu5dpIGNodeG7l2ksIHbDoCBjaOG6oXkgc29uZyBzb25nIHRyw6puIHThu5FpIMSRYSA0IGNvcmVzIGPhu6dhIG3DoXkgdMOtbmguDQoNCmBgYHtyLG1lc3NhZ2UgPSBGQUxTRSx3YXJuaW5nPUZBTFNFfQ0Kc2V0LnNlZWQoMTIzNDUpDQoNCmZtLnN0YW4gPSBzdGFuKG1vZGVsX2NvZGUgPSBtb2RlbC50ZXh0LCANCiAgICAgICAgICAgICAgICBkYXRhID0gZGF0LCANCiAgICAgICAgICAgICAgICBpdGVyID0gMzAwMCwNCiAgICAgICAgICAgICAgICB3YXJtdXAgPSA1MDAsIA0KICAgICAgICAgICAgICAgIHRoaW4gPSAxLA0KICAgICAgICAgICAgICAgIGNoYWlucyA9IDIsIA0KICAgICAgICAgICAgICAgIGNvcmVzID0gcGFyYWxsZWw6OmRldGVjdENvcmVzKCkpDQpgYGANCg0KUXV5IHRyw6xuaCBjb252ZXJnZWQga2jDoSBuaGFuaCBzYXUgdsOgaSBwaMO6dC4gQsOieSBnaeG7nSB0YSBjw7MgMSBvYmplY3Qga2jDoSBs4bubbiwgY2jhu6lhIDIgY2h14buXaSBNQ01DeDI1MDAgbMaw4bujdCBjaG8gNCB0aGFtIHPhu5EgYmV0YSwgY2hvIHNpZ21hLCB2w6AgNjA2IHRoYW0gc+G7kSBNdS4gVHV5IG5oacOqbiB0YSBjaOG7iSBj4bqnbiBraOG6o28gc8OhdCA0IHRoYW0gc+G7kSBiZXRhLg0KDQpQaMOibiBwaOG7kWkgaOG6rXUgxJHhu4tuaCBj4bunYSA0IHRoYW0gc+G7kSBiZXRhMSwyLDMsNCAoY2jDrW5oIGzDoCB0cnVuZyBiw6xuaCBj4bunYSBUQkwgY2hvIDQgcGjDom4gbmjDs20pIGPDsyB0aOG7gyDEkcaw4bujYyBraOG6o28gc8OhdCBuaMawIHNhdSA6DQoNCmBgYHtyLG1lc3NhZ2UgPSBGQUxTRSx3YXJuaW5nPUZBTFNFfQ0KcHJpbnQoZm0uc3RhbiwgcGFycyA9IGMoImJldGEiLCJzaWdtYSIpKQ0KYGBgDQoNCmBgYHtyLG1lc3NhZ2UgPSBGQUxTRSx3YXJuaW5nPUZBTFNFfQ0KcG9zdGRmPWFzLmRhdGEuZnJhbWUoZm0uc3RhbiklPiVhc190aWJibGUoKSU+JS5bLGMoMTo0KV0lPiVtdXRhdGUoLixJdGVyYXRpb249YXMubnVtZXJpYyhyZXAoYygxOjI1MDApLDIpKSxDaGFpbj1hcy5mYWN0b3IocmVwKGMoMToyKSxlYWNoPTI1MDApKSkNCg0KY29sbmFtZXMocG9zdGRmKT1jKCJEb3NlQSIsIkRvc2VCIiwiRG9zZUMiLCJEb3NlRCIsIkl0ZXJhdGlvbiIsIkNoYWluIikNCg0KcEExPXBvc3RkZiU+JQ0KICBnZ3Bsb3QoYWVzKHg9SXRlcmF0aW9uLHk9RG9zZUEsY29sPUNoYWluKSkrDQogIGdlb21fcGF0aChhbHBoYT0wLjUsc2hvdy5sZWdlbmQgPSBGKSsNCiAgdGhlbWVfYncoKQ0KDQpwQTI9cG9zdGRmJT4lDQogIGdncGxvdChhZXMoeD1Eb3NlQSxmaWxsPUNoYWluKSkrDQogIGdlb21fZGVuc2l0eShhbHBoYT0wLjMpKw0KICB0aGVtZV9idygpDQoNCnBCMT1wb3N0ZGYlPiUNCiAgZ2dwbG90KGFlcyh4PUl0ZXJhdGlvbix5PURvc2VCLGNvbD1DaGFpbikpKw0KICBnZW9tX3BhdGgoYWxwaGE9MC41LHNob3cubGVnZW5kID0gRikrDQogIHRoZW1lX2J3KCkNCg0KcEIyPXBvc3RkZiU+JQ0KICBnZ3Bsb3QoYWVzKHg9RG9zZUIsZmlsbD1DaGFpbikpKw0KICBnZW9tX2RlbnNpdHkoYWxwaGE9MC4zKSsNCiAgdGhlbWVfYncoKQ0KDQpwQzE9cG9zdGRmJT4lDQogIGdncGxvdChhZXMoeD1JdGVyYXRpb24seT1Eb3NlQyxjb2w9Q2hhaW4pKSsNCiAgZ2VvbV9wYXRoKGFscGhhPTAuNSxzaG93LmxlZ2VuZCA9IEYpKw0KICB0aGVtZV9idygpDQoNCnBDMj1wb3N0ZGYlPiUNCiAgZ2dwbG90KGFlcyh4PURvc2VDLGZpbGw9Q2hhaW4pKSsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhPTAuMykrDQogIHRoZW1lX2J3KCkNCg0KcEQxPXBvc3RkZiU+JQ0KICBnZ3Bsb3QoYWVzKHg9SXRlcmF0aW9uLHk9RG9zZUQsY29sPUNoYWluKSkrDQogIGdlb21fcGF0aChhbHBoYT0wLjUsc2hvdy5sZWdlbmQgPSBGKSsNCiAgdGhlbWVfYncoKQ0KDQpwRDI9cG9zdGRmJT4lDQogIGdncGxvdChhZXMoeD1Eb3NlRCxmaWxsPUNoYWluKSkrDQogIGdlb21fZGVuc2l0eShhbHBoYT0wLjMpKw0KICB0aGVtZV9idygpDQoNCg0KZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UocEExLHBBMixwQjEscEIyLHBDMSxwQzIscEQxLHBEMixuY29sPTIpDQoNCmBgYA0KDQoNCmBgYHtyLG1lc3NhZ2UgPSBGQUxTRSx3YXJuaW5nPUZBTFNFfQ0KDQpwb3N0ZGYkcHNldWRvR3JvdXA9ZmFjdG9yKHJlcChjKDE6MjUpLGU9bnJvdyhwb3N0ZGYpLzI1KSkNCg0KdGVtcD1wb3N0ZGYlPiVnYXRoZXIoRG9zZUE6RG9zZUQsa2V5PSJGYWN0b3JfbGV2ZWwiLHZhbHVlPSJNZWFuIikNCg0KICBnZ3Bsb3QoKSsNCiAgZ2VvbV9qb3koZGF0YT10ZW1wLGFlcyh5PUZhY3Rvcl9sZXZlbCwNCiAgICAgICAgICAgICAgIHg9TWVhbixjb2w9cHNldWRvR3JvdXApLGZpbGw9InJlZCIsYWxwaGE9MC4wMixzaG93LmxlZ2VuZCA9IEYsc2NhbGU9MSkrDQogIGdlb21fdmxpbmUoeGludGVyY2VwdD0xMCxjb2w9InJlZDQiLGxpbmV0eXBlPTIpKw0KICBjb29yZF9mbGlwKCkrDQogIHNjYWxlX2NvbG91cl9icmV3ZXIocGFsZXR0ZSA9ICJSZWRzIikrDQogIHRoZW1lX2J3KCkNCmBgYA0KDQpUcsaw4bubYyBo4bq/dCwgdGEgdGjhuqV5IHLhurFuZyBtw7QgaMOsbmggQmF5ZXMga2jDtG5nIHRo4buDIMaw4bubYyBsxrDhu6NuZyBjaMOtbmggeMOhYyBwaMOibiBwaOG7kWkgdGjhu7FjIHThur8gY+G7p2EgVEJMLCBuw7MgY2jhu4kgY2hvIHBow6lwIMaw4bubYyBsxrDhu6NuZyBnacOhIHRy4buLIHRydW5nIGLDrG5oIChNdWopIHThuqFpIG3hu5dpIHBow6JuIG5ow7NtIHRow7RuZyBxdWEgY8OhYyB0aGFtIHPhu5EgYmV0YS4NCg0KVHV5IG5oacOqbiBi4bqjbiB0aMOibiB0aGFtIHPhu5EgYmV0YSBjaMawYSBjaG8gcGjDqXAgdGEgdHLhuqMgbOG7nWkgMiBjw6J1IGjhu49pIOG7nyB0csOqbi4gRG8gxJHDsyB0YSBwaOG6o2kgbMOgbSB0aeG6v3AgYsaw4bubYyAyIDogROG7sW5nIGLhuqNuZyBBTk9WQSB04burIG3DtCBow6xuaCBCQVlFUw0KDQojIELhuqNuZyBBTk9WQSB04burIG3DtCBow6xuaCBCQVlFUw0KDQpO4buZaSBkdW5nIGPhu6dhIGLGsOG7m2MgbsOgeSBsw6AgdMawxqFuZyB04buxIG5oxrAgY8OhY2ggdGEgbMOgbSDEkeG7gyBk4buxbmcgYuG6o25nIEFOT1ZBIGPhu5UgxJFp4buDbiwgY2jhu4kga2jDoWMgxJHDsyBsw6AgTVNNIHbDoCBNU1IgdsOgIGPDoWMgc3VtIG9mIHNxdWFyZXMga2jDtG5nIMSRxrDhu6NjIHjDoWMgxJHhu4tuaCB04burIG3DtCBow6xuaCB0dXnhur9uIHTDrW5oIGTDuW5nIGFsZ29yaXRobSBMZWFzdCBzcXVhcmUgaGF5IFJFTUwsIG3DoCBkw7luZyBjaMOtbmggbcO0IGjDrG5oIEJheWVzIHbhu5tpIDQgdGhhbSBz4buRIEJldGEuIMSQ4buDIMSRxqFuIGdp4bqjbiwgdGEgbOG6pXkgVHJ1bmcgduG7iyBj4bunYSBwaMOibiBwaOG7kWkgaOG6rXUgxJHhu4tuaCBj4bunYSBt4buXaSBCZXRhIMSR4buDIHThuqFvIHJhIDEgbcO0IGjDrG5oIMSR4bqhaSBkaeG7h24gOg0KDQpTYXUgxJHDsywgdOG7qyBtw7QgaMOsbmggxJHhuqFpIGRp4buHbiBCYXllcyBuw6B5LCB0YSB0w61uaCBjw6FjIFNTLCBNU00sIE1TUiwgRiB2YWx1ZXMgY8WpbmcgbmjGsCBjw6FjIGVmZmVjdC1zaXplcw0KDQpgYGB7cixtZXNzYWdlID0gRkFMU0Usd2FybmluZz1GQUxTRX0NCmNvZWZzPWFzLm1hdHJpeChmbS5zdGFuKSU+JS5bLGMoMTo0KV0lPiVhcHBseSguLDIsIG1lZGlhbikNCg0KcHJlZERGPWRhdGEuZnJhbWUoeD1kYXQwJGRvc2UsdHJ1dGg9ZGF0MCRUQkwuTSkNCg0KWWhhdD0oY29lZnMgJSolIHQobW9kZWwubWF0cml4KH5wcmVkREYkeC0xKSkpJT4lYXMudmVjdG9yKCkNCg0KZGYxPWRhdCRKLTENCmRmMj0oZGF0JE4tZGF0JEopDQoNCnNzbT1zdW0oIChZaGF0LW1lYW4ocHJlZERGJHRydXRoKSleMiApDQpzc3I9c3VtKCAocHJlZERGJHRydXRoLVloYXQpXjIgKQ0Kc3N0PXN1bSggKHByZWRERiR0cnV0aC1tZWFuKHByZWRERiR0cnV0aCkpXjIgKQ0KbXNtPXNzbS9kZjENCm1zcj1zc3IvZGYyDQpmPW1zbS9tc3INCiNFZmZlY3Qgc2l6ZXMNCmV0YTI9c3NtL3NzdA0Kcj1zcXJ0KHNzbS9zc3QpDQpSMj1yXjINCm9tZWdhMj0oc3NtLWRmMSptc3IpLyhzc3QrbXNyKQ0KIzItc2lkZXMgRiB0ZXN0DQpwMnNpZGVzPTIqKDEtKHBmKGYsZGYxLGRmMixGKSkpDQojMS1zaWRlIEYgdGVzdA0KcDFzaWRlPSgxLShwZihmLGRmMSxkZjIsRikpKQ0KDQpyYmluZChzc20sc3NyLHNzdCxtc20sbXNyLGYsZGYxLGRmMixwMXNpZGUscDJzaWRlcyxldGEyLG9tZWdhMixyLFIyKSU+JXJvdW5kKC4sNSklPiVhcy5tYXRyaXgoKSU+JS5bLDFdDQoNCmBgYA0KDQpOaMawIHbhuq15LCDEkcOieSBsw6AgbeG7mXQgZ2nhuqNpIHBow6FwICJsYWkiIGdp4buvYSBo4buTaSBxdXkgQmF5ZXMgdsOgIG51bGwgaHlwb3RoZXNpcyB0ZXN0aW5nLiBUaOG6rW0gY2jDrSB0YSBjw7MgY+G6oyBwIHZhbHVlcy4NCg0KS+G6v3QgcXXhuqMgdHLDqm4gxJHDonkgY8OzIHRo4buDIHhlbSBuaMawIHTGsMahbmcgxJHGsMahbmcgduG7m2kga+G6v3QgcXXhuqMgY+G7p2EgaMOgbSBhb3YoKSwgdHLGsOG7nW5nIHBow6FpIEZyZXF1ZW50aXN0Lkdpw6EgdHLhu4sgcCAxIHNpZGVkIGzDoCBuaMawIG5oYXUuIE3hu5l0IGvhur90IHF14bqjIGtow7RuZyB04buHID8NCg0KYGBge3IsbWVzc2FnZSA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9DQphb3YoVEJMLk0gfiBkb3NlLCBkYXQwKSU+JWFub3ZhZnVuYygpJT4lcm91bmQoLiw1KQ0KYGBgDQoNCsSQ4bq/biDEkcOieSwgdGEgxJHDoyB0cuG6oyBs4budaSB4b25nIGPDonUgaOG7j2kgdGjhu6kgMSwgdGnhur9wIHRoZW8gc+G6vSBsw6Agdmnhu4djIHNvIHPDoW5oIGLhuq90IGPhurdwIHR14bqnbiB04buxIGdp4buvYSA0IHBow6JuIG5ow7NtIMSR4buDIHRy4bqjIGzhu51pIGPDonUgaOG7j2kgdGjhu6kgMg0KDQojIFBvc3QtaG9jIHRlc3QgdGhlbyBCQVlFUw0KDQpRdXkgdHLDrG5oIG7DoHkgdGjhu7FjIHPhu7EgdGhheSB0aOG6vyBwb3N0LWhvYyB0ZXN0IHRoZW8gcGjDoWkgZnJlcXVlbnRpc3QgYuG6sW5nIHBoxrDGoW5nIHBow6FwIEJheWVzLiBO4buZaSBkdW5nIGPhu6dhIHBvc3QgaG9jIHRlc3QgdGhlbyBCYXllcyBy4bqldCDEkcahbiBnaeG6o246IFRhIHPhur0gdOG6oW8gcmEgNiBjaHXhu5dpIE1DTUMgY2jhu6lhIHBow6JuIHBo4buRaSBo4bqtdSDEkeG7i25oIGPhu6dhIOKAnGtow6FjIGJp4buHdCB0cnVuZyBiw6xuaOKAnSBnaeG7r2EgMiBwaMOibiBuaMOzbSDEkcaw4bujYyBi4bqvdCBj4bq3cCB0deG6p24gdOG7sSAoVGEgY8OzIDQgcGjDom4gbmjDs20sIG7Dqm4gY8OzIDYgY+G6t3Agc28gc8OhbmggKS4gU3V5IGRp4buFbiBCYXllcyBz4bq9IMSRxrDhu6NjIHRo4buxYyBoaeG7h24gdHLhu7FjIHRp4bq/cCB0csOqbiBt4buXaSBjaHXhu5dpIE1DTUMsIGtow7RuZyBj4bqnbiBkw7luZyBwX3ZhbHVlIGhheSBoaeG7h3UgY2jhu4luaC4NCg0KYGBge3IsbWVzc2FnZSA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9DQpwb3N0aG9jZGY9ZGF0YS5mcmFtZSgNCiAgICAgICAgICAgICAgIEFCPXJlcChOQSw1MDAwKSwNCiAgICAgICAgICAgICAgIEFDPXJlcChOQSw1MDAwKSwNCiAgICAgICAgICAgICAgIEFEPXJlcChOQSw1MDAwKSwNCiAgICAgICAgICAgICAgIEJDPXJlcChOQSw1MDAwKSwNCiAgICAgICAgICAgICAgIEJEPXJlcChOQSw1MDAwKSwNCiAgICAgICAgICAgICAgIENEPXJlcChOQSw1MDAwKQ0KICAgICAgICAgICAgICAgKQ0KDQpmb3IgKGkgaW4gMTo1MDAwKXsNCiAgcG9zdGhvY2RmJEFCW2ldPXBvc3RkZiREb3NlQVtpXS1wb3N0ZGYkRG9zZUJbaV0NCiAgcG9zdGhvY2RmJEFDW2ldPXBvc3RkZiREb3NlQVtpXS1wb3N0ZGYkRG9zZUNbaV0NCiAgcG9zdGhvY2RmJEFEW2ldPXBvc3RkZiREb3NlQVtpXS1wb3N0ZGYkRG9zZURbaV0NCiAgcG9zdGhvY2RmJEJDW2ldPXBvc3RkZiREb3NlQltpXS1wb3N0ZGYkRG9zZUNbaV0NCiAgcG9zdGhvY2RmJEJEW2ldPXBvc3RkZiREb3NlQltpXS1wb3N0ZGYkRG9zZURbaV0NCiAgcG9zdGhvY2RmJENEW2ldPXBvc3RkZiREb3NlQ1tpXS1wb3N0ZGYkRG9zZURbaV0NCn0NCg0KYGBgDQoNCg0KYGBge3IsbWVzc2FnZSA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9DQpIRElGPSBmdW5jdGlvbiggc2FtcGxlVmVjLGNyZWRNYXNzPTAuOTc1ICkgew0KICBzb3J0ZWRQdHMgPSBzb3J0KCBzYW1wbGVWZWMgKQ0KICBjaUlkeEluYyA9IGNlaWxpbmcoIGNyZWRNYXNzICogbGVuZ3RoKCBzb3J0ZWRQdHMgKSApDQogIG5DSXMgPSBsZW5ndGgoIHNvcnRlZFB0cyApIC0gY2lJZHhJbmMNCiAgY2lXaWR0aCA9IHJlcCggMCAsIG5DSXMgKQ0KICBmb3IgKCBpIGluIDE6bkNJcyApIHsNCiAgICBjaVdpZHRoWyBpIF0gPSBzb3J0ZWRQdHNbIGkgKyBjaUlkeEluYyBdIC0gc29ydGVkUHRzWyBpIF0NCiAgfQ0KICBIREltaW4gPSBzb3J0ZWRQdHNbIHdoaWNoLm1pbiggY2lXaWR0aCApIF0NCiAgSERJbWF4ID0gc29ydGVkUHRzWyB3aGljaC5taW4oIGNpV2lkdGggKSArIGNpSWR4SW5jIF0NCiAgSERJbGltID0gYyggSERJbWluICwgSERJbWF4ICkNCiAgcmV0dXJuKCBIRElsaW0gKQ0KfQ0KDQpTVU1LPWZ1bmN0aW9uKHBhcmFtU2FtcGxlVmVjLGNvbXBWYWw9TlVMTCAsIFJPUEU9TlVMTCAsIGNyZWRNYXNzPTAuOTc1KSB7DQogIG1lYW5QYXJhbSA9IG1lYW4oIHBhcmFtU2FtcGxlVmVjICkNCiAgbWVkaWFuUGFyYW0gPSBtZWRpYW4oIHBhcmFtU2FtcGxlVmVjICkNCiAgZHJlcyA9IGRlbnNpdHkoIHBhcmFtU2FtcGxlVmVjICkNCiAgbW9kZVBhcmFtID0gZHJlcyR4W3doaWNoLm1heChkcmVzJHkpXQ0KICBoZGlMaW0gPSBIRElGKCBwYXJhbVNhbXBsZVZlYyAsIGNyZWRNYXNzPWNyZWRNYXNzICkNCiAgaWYgKCAhaXMubnVsbChjb21wVmFsKSApIHsNCiAgICBwY2d0Q29tcFZhbCA9ICggMTAwICogc3VtKCBwYXJhbVNhbXBsZVZlYyA+IGNvbXBWYWwgKSANCiAgICAgICAgICAgICAgICAgICAgLyBsZW5ndGgoIHBhcmFtU2FtcGxlVmVjICkgKQ0KICB9IGVsc2Ugew0KICAgIGNvbXBWYWw9TkENCiAgICBwY2d0Q29tcFZhbD1OQQ0KICB9DQogIGlmICggIWlzLm51bGwoUk9QRSkgKSB7DQogICAgcGNsdFJvcGUgPSAoIDEwMCAqIHN1bSggcGFyYW1TYW1wbGVWZWMgPCBST1BFWzFdICkgDQogICAgICAgICAgICAgICAgIC8gbGVuZ3RoKCBwYXJhbVNhbXBsZVZlYyApICkNCiAgICBwY2d0Um9wZSA9ICggMTAwICogc3VtKCBwYXJhbVNhbXBsZVZlYyA+IFJPUEVbMl0gKSANCiAgICAgICAgICAgICAgICAgLyBsZW5ndGgoIHBhcmFtU2FtcGxlVmVjICkgKQ0KICAgIHBjaW5Sb3BlID0gMTAwLShwY2x0Um9wZStwY2d0Um9wZSkNCiAgfSBlbHNlIHsgDQogICAgUk9QRSA9IGMoTkEsTkEpDQogICAgcGNsdFJvcGU9TkEgDQogICAgcGNndFJvcGU9TkEgDQogICAgcGNpblJvcGU9TkEgDQogIH0gIA0KICByZXR1cm4oIGMoIE1lYW49bWVhblBhcmFtICwgTWVkaWFuPW1lZGlhblBhcmFtICwgTW9kZT1tb2RlUGFyYW0gLCANCiAgICAgICAgICAgICBIRElsZXZlbD1jcmVkTWFzcyAsIExMPWhkaUxpbVsxXSAsIFVMPWhkaUxpbVsyXSAsIA0KICAgICAgICAgICAgIENvbXBWYWw9Y29tcFZhbCAsIFBjbnRHdENvbXBWYWw9cGNndENvbXBWYWwgLCANCiAgICAgICAgICAgICBST1BFbG93PVJPUEVbMV0gLCBST1BFaGlnaD1ST1BFWzJdICwNCiAgICAgICAgICAgICBQY250THRST1BFPXBjbHRSb3BlICwgUGNudEluUk9QRT1wY2luUm9wZSAsIFBjbnRHdFJPUEU9cGNndFJvcGUgKSApDQp9DQoNCnN1bW1hcnlLcnVzY2hrZT1mdW5jdGlvbihNQ01DLGNvbXBWYWw9TlVMTCwgcm9wZT1OVUxMLGNyZWRNYXNzPU5VTEwpew0KICBzdW1tYXJ5SW5mbyA9IE5VTEwNCiAgc3VtbWFyeUluZm8gPSBjYmluZChzdW1tYXJ5SW5mbywgIkVzdGltYXRlZCI9IFNVTUsoTUNNQywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcFZhbD1jb21wVmFsLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBST1BFPXJvcGUsY3JlZE1hc3M9Y3JlZE1hc3MpKQ0KICByZXR1cm4oc3VtbWFyeUluZm8pDQp9DQoNCg0KcG9zdGhvY2RmJHBzZXVkb0dyb3VwPWZhY3RvcihyZXAoYygxOjI1KSxlPW5yb3cocG9zdGhvY2RmKS8yNSkpDQoNCnBvc3Rob2NkZj1wb3N0aG9jZGYlPiVnYXRoZXIoQUI6Q0Qsa2V5PSJQYWlycyIsdmFsdWU9IkRpZmZlcmVuY2UiKQ0KDQpgYGANCg0KU3V5IGRp4buFbiBCYXllcyDEkcaw4bujYyB0aOG7sWMgaGnhu4duIGLhurFuZyBj4bqjIDIgcGjGsMahbmcgcGjDoXAgOiBST1BFIChLcnVzY2hrZSkgdsOgIEJheWVzIEZhY3Rvci4gQ2jDuiDDvSBy4bqxbmcgY2jDum5nIHRhIGzhuqV5IE11QS1NdUIsIG7Dqm4ga2jDoWMgYmnhu4d0IHRydW5nIGLDrG5oIDwwICBjaG8gY+G6t3Agc28gc8OhbmggQUIgY8OzIG5naMSpYSBsw6AgTXVCIGzhu5tuIGjGoW4gTXVBDQoNClRyxrDhu5tjIGjhur90LCB0YSBow6N5IHhlbSBxdWEgcGjDom4gdMOtY2ggUk9QRSBwaMOibiBwaOG7kWkgaOG6rXUgxJHhu4tuaCBj4bunYSA2IGtow6FjIGJp4buHdCB0cnVuZyBiw6xuaCA6DQoNCk5o4bqvYyBs4bqhaSwgUk9QRSBsw6AgbeG7mXQga2hv4bqjbmcgdsO0IG5naMSpYSB0aOG7sWMgZOG7pW5nLCB0aMOtIGThu6UgdGEgZ2nhuqMgxJHhu4tuZyBy4bqxbmcgbuG6v3Uga2jDoWMgYmnhu4d0IHRydW5nIGLDrG5oIG7hurFtIHRyb25nIGtob+G6o25nICsvLSAwLjUgeGVtIG5oxrAgdsO0IG5naMSpYS4NCg0KYGBge3IsbWVzc2FnZSA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9DQoNCnBvc3Rob2NkZiU+JQ0KICBzcGxpdCguJFBhaXJzKSU+JQ0KICBtYXAofnN1bW1hcnlLcnVzY2hrZShNQ01DID0gLiREaWZmZXJlbmNlLA0KICAgICAgICAgICAgICAgICAgICAgICBjb21wVmFsPTAuMCwNCiAgICAgICAgICAgICAgICAgICAgICAgcm9wZT1jKC0wLjUsMC41KSwNCiAgICAgICAgICAgICAgICAgICAgICAgY3JlZE1hc3M9MC45NzUpDQogICAgICApJT4lYXMuZGF0YS5mcmFtZSgpLT5rcnVzY2hrZQ0KDQpjb2xuYW1lcyhrcnVzY2hrZSk9YygiQUIiLCJBQyIsIkFEIiwiQkMiLCJCRCIsIkNEIikNCg0Ka3J1c2Noa2UlPiVyb3VuZCguLDMpDQpgYGANCg0KS+G6v3QgcXXhuqM6IE5nb+G6oWkgdHLhu6sgY+G6t3AgQkMsIDUgY+G6t3AgY8OybiBs4bqhaSDEkeG7gXUgY2hvIHRo4bqleSBt4buZdCBz4buxIHTGsMahbmcgcGjhuqNuIGtow6EgcsO1LCB2w6wgbeG6rXQgxJHhu5kgcGjDom4gcGjhu5FpIGjhuq11IMSR4buLbmggY+G7p2Ega2jDoWMgYmnhu4d0IHRydW5nIGLDrG5oIG7hurFtIHRyb25nIFJPUEUgIHRo4bqlcCBuaOG6pXQgbMOgIDYuNSUgKGPhurdwIEJEKSAsIGNhbyBuaOG6pXQgY2jhu4kgY8OzIDE4LjYlIChj4bq3cCBBQiksIHPhu7Ega2jDoWMgYmnhu4d0IG7DoHkgdGhlbyBoxrDhu5tuZyA6IExp4buBdSB0aHXhu5FjIGNhbyBoxqFuIHTGsMahbmcg4bupbmcgduG7m2kgZ2nDoSB0cuG7iyBUTEIgY2FvIGjGoW4gKGtow6FjIGJp4buHdCBjw6BuZyDDom0pLCB2w6wgbeG6rXQgxJHhu5kgcGjDom4gcGjhu5FpIGjhuq11IMSR4buLbmggbuG6sW0gZMaw4bubaSBST1BFIGRhbyDEkeG7mW5nIHThu6sgODElIGNobyBj4bq3cCBBQiDEkeG6v24gOTAlIGNobyBj4bq3cCBBQywgOTMuNCUgY2hvIGPhurdwIEJELCA4Ny44JSBjaG8gY+G6t3AgQ0QgdsOgIGNhbyBuaOG6pXQgbMOgIDk5LjklIGNobyBj4bq3cCBBRC4NCg0KYGBge3IsbWVzc2FnZSA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9DQoNCnBvc3Rob2NkZiU+JWdncGxvdCgpKw0KICBnZW9tX2pveShhZXMoeT1yZW9yZGVyKFBhaXJzLERpZmZlcmVuY2UpLA0KICAgICAgICAgICAgICAgeD1EaWZmZXJlbmNlLA0KICAgICAgICAgICAgICAgY29sPXJlb3JkZXIocHNldWRvR3JvdXAsRGlmZmVyZW5jZSkpLA0KICAgICAgICAgICBmaWxsPSJyZWQiLA0KICAgICAgICAgICBhbHBoYT0wLjAxLA0KICAgICAgICAgICBzaG93LmxlZ2VuZCA9IEYsDQogICAgICAgICAgIHNjYWxlPTEpKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9YygtMSwwLjAsMSksY29sPSJyZWQ0IixsaW5ldHlwZT0yKSsNCiAgeGxpbSgtNC41LDMpK3lsYWIoIlBhaXJzIikrDQogIGNvb3JkX2ZsaXAoKSsNCiAgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIlJlZHMiKSsNCiAgdGhlbWVfYncoKStnZ3RpdGxlKCJCYXllc2lhbiBQYWlyd2lzZSBjb21wYXJpc29uIikNCg0KYGBgDQoNCkvhur90IHF14bqjIG7DoHkgaG/DoG4gdG/DoG4gdMawxqFuZyDEkeG7k25nIHbhu5tpIGvhur90IHF14bqjIGPhu6dhIEJvb3RzdHJhcCAxMDAwIGzhuqduIHBvc3QtaG9jIHRlc3QgVHVrZXk6DQoNCmBgYHtyLG1lc3NhZ2UgPSBGQUxTRSx3YXJuaW5nPUZBTFNFfQ0KDQpsaWJyYXJ5KGJvb3QpDQoNCnR1a2V5Ym9vdD1mdW5jdGlvbihmb3JtdWxhLGRhdGEsaSl7DQogIGRycz0gZGF0YVtpLF0NCiAgb3V0PWFvdihsbShmb3JtdWxhPWZvcm11bGEsZGF0YT1kcnMpKQ0KICB0az1UdWtleUhTRChvdXQpDQogIHJldHVybj1jYmluZChkMT10ayRkb3NlWzEsMV0sDQogICAgICAgICAgICAgICBkMj10ayRkb3NlWzIsMV0sDQogICAgICAgICAgICAgICBkMz10ayRkb3NlWzMsMV0sDQogICAgICAgICAgICAgICBkND10ayRkb3NlWzQsMV0sDQogICAgICAgICAgICAgICBkNT10ayRkb3NlWzUsMV0sDQogICAgICAgICAgICAgICBkNj10ayRkb3NlWzYsMV0pDQp9DQoNCnJlc3RrPWJvb3Qoc3RhdGlzdGljPXR1a2V5Ym9vdCxmb3JtdWxhPSJUQkwuTX5kb3NlIixkYXQwLFI9MTAwMCklPiUuJHQlPiVhc190aWJibGUoKQ0KDQpyZXN0a2RpZj1yZXN0a1ssYygxOjYpXSU+JW11dGF0ZSguLHBzZXVkb0dyb3VwPXJlcChjKDE6NTApLDIwKSkNCm5hbWVzKHJlc3RrZGlmKT1jKCJBQiIsIkFDIiwiQUQiLCJCQyIsIkJEIiwiQ0QiLCJwc2V1ZG9Hcm91cCIpDQpyZXN0a2RpZj1yZXN0a2RpZiU+JWdhdGhlcihBQjpDRCxrZXk9IlBhaXIiLHZhbHVlPSJNZWFuRGlmIikNCg0KcmVzdGtkaWYlPiVnZ3Bsb3QoKSsNCiAgZ2VvbV9qb3koYWVzKHg9LU1lYW5EaWYseT1yZW9yZGVyKFBhaXIsLU1lYW5EaWYpLGNvbD1hcy5mYWN0b3IocHNldWRvR3JvdXApKSxzaG93LmxlZ2VuZCA9IEYsZmlsbD0ic2t5Ymx1ZSIsYWxwaGE9MC4wMixzY2FsZT0xKSsNCiAgY29vcmRfZmxpcCgpKw0KICBzY2FsZV9jb2xvcl9icmV3ZXIocGFsZXR0ZT0iQmx1ZXMiKSsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PWMoLTEsMC4wLDEpLGNvbD0iYmx1ZTQiLGxpbmV0eXBlPTIpKw0KICB4bGltKC00LjUsMykreWxhYigiUGFpcnMiKSt4bGFiKCJNZWFuIGRpZmZlcmVuY2VzIikrDQogIHRoZW1lX2J3KCkrZ2d0aXRsZSgiQm9vdHN0cmFwcGVkIFR1a2V5IFBvc3RfaG9jIHRlc3QiKQ0KYGBgDQoNCk5oxrAgduG6rXkgY2jDum5nIHRhIGPDsyB0aOG7gyBhbiB0w6JtIHLhurFuZyBCYXllc2lhbiBwb3N0IGhvYyB0ZXN0IGPDsyB0aOG7gyB0aGF5IHRo4bq/IGNobyBUdWtleSBwb3N0IGhvYyB0ZXN0LCBuaMawbmcgY8OybiB24buBIMO9IG5naMSpYSB0aOG7kW5nIGvDqiB0aMOsIHNhbyA/IFRhIHRo4butIMSR4buRaSBjaGnhur91IHBow6JuIHTDrWNoIFJPUEUgdsOgIHAgdmFsdWUgY+G7p2EgVHVrZXkgdGVzdCBjxaluZyBuaMawIGPhu6dhIEJvbmZlcnJvbmkgdGVzdDoNCg0KYGBge3J9DQpwYWlyd2lzZS50LnRlc3QoZGF0MCRUQkwuTSwgZGF0MCRkb3NlLHAuYWRqdXN0Lm1ldGhvZD0ibm9uZSIpDQoNCnBhaXJ3aXNlLnQudGVzdChkYXQwJFRCTC5NLCBkYXQwJGRvc2UscC5hZGp1c3QubWV0aG9kPSJib25mZXJyb25pIikNCg0KYGBgDQoNCkvhur90IHF14bqjIMSR4buRaSBjaGnhur91IGNobyB0aOG6pXk6IFbDrCBCb25mZXJyb25pIGzDoCAxIHRlc3QgcuG6pXQgYuG6o28gdGjhu6csIG7DsyBwaOG7pyBuaOG6rW4gdG/DoG4gYuG7mSDDvSBuZ2jEqWEgY+G7p2Ega2jDoWMgYmnhu4d0IHRydW5nIGLDrG5oIGdp4buvYSBjw6FjIGPhurdwIEFCLEJDLEFDLENEIHbDoCBCRCwgY2jhu4kgZHV5IG5o4bqldCBj4bq3cCBBRCB24bubaSB0xrDGoW5nIHBo4bqjbiBt4bqhbmggbmjhuqV0IGzDoCBuaOG6rW4gcF92YWx1ZSA8IDAuMDUNCg0KS2hpIGtow7RuZyBoaeG7h3UgY2jhu4luaCBi4bqxbmcgQm9uZmVycm9uaSwgMSB0ZXN0IFR1a2V5IHRow7RuZyB0aMaw4budbmcgY2jhu4kgYsOhYyBi4buPIMO9IG5naMSpYSBj4bunYSBraMOhYyBiaeG7h3QgZ2nhu69hIDIgY+G6t3AgQUIgdsOgIEJDLCBuaMawbmcgY8OhYyBj4bq3cCBjw7JuIGzhuqFpIMSR4buBdSBuaOG6rW4gcDwwLjA1Ow0KDQpDaMO6bmcgdMO0aSBraMO0bmcgbXXhu5FuIMOhcCDEkeG6t3Qgw70ga2nhur9uIHJpw6puZyBuw6BvIGPhuqMgduG7gSBr4bq/dCBxdeG6oyBuw6B5LiBDw6FjIGLhuqFuIGPDsyB0b8OgbiBxdXnhu4FuIFRpbiBob+G6t2Mga2jDtG5nIFRpbiB24buBIGtow6FjIGJp4buHdCBjw7Mgw70gbmdoxKlhIGNobyBj4bq3cCBBQiBuZ2F5IGPhuqMga2hpIHBvc3QtaG9jIHRlc3QgxJHDoyBwaOG7pyBuaOG6rW4gZ2nhuqMgdGh1eeG6v3QgbsOgeSwgYmnhur90IHLhurFuZyBjw7MgxJHhur9uIDgxJSBt4bqtdCDEkeG7mSBwaMOibiBwaOG7kWkgaOG6rXUgxJHhu4tuaCBj4bunYSBraMOhYyBiaeG7h3QgQS1CIG7hurFtIGTGsOG7m2kgLTAuNTsgdMawxqFuZyB04buxLCBi4bqhbiBjw7MgcXV54buBbiB0aW4gaGF5IGtow7RuZyB0aW4gcuG6sW5nIFRCTCDhu58gbGnhu4F1IHRodeG7kWMgRCBzbyB24bubaSBDIGzDoCBraMOhYyBuaGF1LCBkw7kgcF92YWx1ZSA9MC4yMywgYmnhur90IHLhurFuZyA4Ny44JSBt4bqtdCDEkeG7mSBwaMOibiBwaOG7kWkgY+G7p2Ega2jDoWMgYmnhu4d0IDwgLTAuNQ0KDQpDw7MgbeG7mXQgY8OhY2gga2jDoWMgbuG6v3UgYuG6oW4gbXXhu5FuIHBow6JuIMSR4buLbmggVHLhuq9uZy/EkGVuOiDEkcOzIGzDoCBkw7luZyBCYXllcyBGYWN0b3IsIHbhu5tpIG5nxrDhu6FuZyBzbyBzw6FuaCBsw6AgemVybyAoa2jDtG5nIGPDsyBraMOhYyBiaeG7h3QpLCB04buJIHRy4buNbmcgY2jhu6luZyBj4bupIOG7p25nIGjhu5kgY2hvIGdp4bqjIHRodXnhur90IEgxIChraMOhYyBiaeG7h3QgPCAwKToNCg0KYGBge3IsbWVzc2FnZSA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9DQoNCnRocmVzaG9sZD1yZXAoTkEsNjApDQpCYXllc0ZhY3Rvcj1yZXAoTkEsNjApDQpQYWlyPXJlcChOQSw2MCkNCg0KdGhyZXM9YygtMywtMi41LC0yLjI1LC0yLC0xLjUsLTEuMjUsLTEsLTAuNSwtMC4yNSwwKQ0KDQpwYWlybGV2PXVuaXF1ZShwb3N0aG9jZGYkUGFpcnMpDQoNCm49MA0KDQpmb3IoaSBpbiAoMTo2KSl7DQogIGZvciAoaiBpbiAoMToxMCkpew0KICAgIHRlbXBkZj1zdWJzZXQocG9zdGhvY2RmLFBhaXJzPT1wYWlybGV2W2ldKQ0KICAgIFBhaXJbbitqXT1wYWlybGV2W2ldDQogIHRocj10aHJlc1tqXQ0KICB0aHJlc2hvbGRbbitqXT10aHINCiAgaHlwPXBhc3RlKCJEaWZmZXJlbmNlPCIsdGhyLHNlcD0iIikNCiAgYmY9YnJtczo6aHlwb3RoZXNpcyh0ZW1wZGYsaHlwLGFscGhhPTAuMDUpDQogIEJheWVzRmFjdG9yW24ral09YmYkaHlwb3RoZXNpcyRFdmlkLlJhdGlvDQogIH0NCiAgbj1uKzEwDQp9DQoNCnRlbXBiZmRmPWNiaW5kKFBhaXIsdGhyZXNob2xkLEJheWVzRmFjdG9yKSU+JWFzX3RpYmJsZSgpDQp0ZW1wYmZkZiR0aHJlc2hvbGQ9YXMubnVtZXJpYyh0ZW1wYmZkZiR0aHJlc2hvbGQpDQp0ZW1wYmZkZiRCYXllc0ZhY3Rvcj1hcy5udW1lcmljKHRlbXBiZmRmJEJheWVzRmFjdG9yKQ0KDQp0ZW1wYmZkZiU+JXNwbGl0KC4kUGFpciklPiVtYXAofnJiaW5kKFRocmVzaG9sZD1tYXgoLiR0aHJlc2hvbGQpLEJGPW1heCguJEJheWVzRmFjdG9yKSkpJT4lYXMuZGF0YS5mcmFtZSgpDQpgYGANCg0KVGEga2jhuqNvIHPDoXQgQkYgY2hvIDEwIG5nxrDhu6FuZyBIMCB04burIDAgxJHhur9uIC0zLCB0dXkgbmhpw6puIHRhIHF1YW4gdMOibSDEkeG6v24gbmfGsOG7oW5nIDAsIMSR4buDIMSR4buRaSBjaGnhur91IHbhu5tpIHBfdmFsdWVzOg0KDQpO4bq/dSB0YSBs4bqleSB0acOqdSBjaMOtOiBCRiA+IDMwIGzDoCDEkeG7pyBjYW8gY2hvIG3hu5l0IHN1eSBkaeG7hW4gIMO9IG5naMSpYSB0aOG7kW5nIGvDqiwgdsOgIEJGPjEwMCBsw6AgcuG6pXQgY2FvLCBjaG8gcGjDqXAgeMOhYyB0w61uIHbhu4Egw70gbmdoxKlhIG7DoHk7IHRow6wga+G6v3QgceG7p2EgY+G7p2EgNiBwaMOibiBwaOG7kWkgaOG6rXUgxJHhu4tuaCBj4bunYSB0YSBjaG8gdGjhuqV5Og0KDQpU4buJIHRy4buNbmcgY2jhu6luZyBj4bupIOG7p25nIGjhu5kgY2hvIGdp4bqjIHRodXnhur90IEgxOiBraMOhYyBiaeG7h3QgdHJ1bmcgYsOsbmggPCAwIHRo4bqlcCBoxqFuIDMwIOG7nyAyIGPhurdwIEFCIHbDoCBCQywgbmjGsG5nIGNhbyBoxqFuIDMwIGNobyA0IGPhurdwIGPDsm4gbOG6oWksIHRo4bqtbSBjaMOtID4gMTAwIGNobyAyIGPhurdwIEFEIHbDoCBCRC4NCg0KTmjGsCB24bqteSwgU3V5IGRp4buFbiBCYXllcyBjw7MgdMOtbmggbGluaCBob+G6oXQgcuG6pXQgY2FvIHNvIHbhu5tpIHBvc3QtaG9jIHRlc3QgdGhlbyBmcmVxdWVudGlzdDsga2jDtG5nIGPDsm4ga2jDoWkgbmnhu4dtIHRlc3QgYuG6o28gdGjhu6cgaGF5IHF1w6EgbmjhuqF5LGtow7RuZyBjw7MgbmfGsOG7oW5nIG5ndXkgY8ahIHNhaSBs4bqnbSBhbHBoYSA9IDAuMDUsIHYudi4gQ2jDrW5oIG5nxrDhu51pIHRo4bqneSB0aHXhu5FjIGPDsyBxdXnhu4FuIHThu7EgY2jhu6cgdHJvbmcgc3V5IGx14bqtbiBj4bunYSBtw6xuaCBraGkgxJHhu41jIGvhur90IHF14bqjIG3DoCBwaMOibiB0w61jaCBCYXllcyDEkcawYSByYS4NCg0KYGBge3IsbWVzc2FnZSA9IEZBTFNFLHdhcm5pbmc9RkFMU0V9DQp0ZW1wYmZkZiU+JWdncGxvdChhZXMoeD10aHJlc2hvbGQseT1CYXllc0ZhY3RvcixmaWxsPUJheWVzRmFjdG9yKSkrDQogIGdlb21fcGF0aCgpKw0KICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRixzaXplPTMsc2hhcGU9MjEsY29sPSJibGFjayIpKw0KICBzY2FsZV9maWxsX2dyYWRpZW50KGxvdz0iZ29sZCIsaGlnaD0icmVkIikrDQogIHRoZW1lX2J3KDEwKSsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbD1yb3VuZCh0ZW1wYmZkZiRCYXllc0ZhY3RvciwyKSksY29sPSJibGFjayIsc2hvdy5sZWdlbmQgPSBGLGFuZ2xlID0gNTAsbnVkZ2VfeT1CYXllc0ZhY3RvcisyMCxudWRnZV94PTAsc2l6ZT0yKSsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gYygzMCwxMDApLGxpbmV0eXBlPTIsY29sPSJibHVlIikrDQogIGZhY2V0X3dyYXAoflBhaXIsbmNvbD0zLHNjYWxlcyA9ICJmcmVlIikNCmBgYA0KDQojIERp4buFbiDEkeG6oXQgdsSDbiBi4bqjbiBraG9hIGjhu41jDQoNClBoxrDGoW5nIHBow6FwIHRo4buRbmcga8OqOg0KDQpIaeG7h3Ug4bupbmcgY+G7p2EgbGnhu4F1IHRodeG7kWMgdMSDbmcgZOG6p24gxJHhu5FpIHbhu5tpIGdpw6EgdHLhu4sgbuG7k25nIMSR4buZIGJpbGlydWJpbiDEkcaw4bujYyBraOG6o28gc8OhdCBi4bqxbmcgbeG7mXQgbcO0IGjDrG5oIEFOT1ZBIHRoZW8gcGjGsMahbmcgcGjDoXAgQmF5ZXMuIE3DtCBow6xuaCBuw6B5IGNobyBwaMOpcCDGsOG7m2MgbMaw4bujbmcgcGjDom4gcGjhu5FpIGjhuq11IMSR4buLbmggY+G7p2EgZ2nDoSB0cuG7iyBUQkwgdHJ1bmcgYsOsbmggY2hvIG3hu5dpIHBow6JuIG5ow7NtLiBE4buxYSB2w6BvIGvhur90IHF14bqjIG7DoHksIGNow7puZyB0w7RpIGPDsyB0aOG7gyBraeG7g20gdHJhIMO9IG5naMSpYSB2w6Aga8OtY2ggdGjGsOG7m2MgY+G7p2EgaGnhu4d1IOG7qW5nIGLhurFuZyBGIHRlc3QgdGhlbyBGaXNoZXIsIGPFqW5nIG5oxrAgc3V5IGRp4buFbiB24buBIHPhu7EgdMawxqFuZyBwaOG6o24gZ2nhu69hIDQgcGjDom4gbmjDs20gZOG7sWEgdsOgbyBwaMOibiBwaOG7kWkgaOG6rXUgxJHhu4tuaCBj4bunYSBraMOhYyBiaeG7h3QgdHJ1bmcgYsOsbmgsIHPhu60gZOG7pW5nIEJheWVzIEZhY3RvciB2w6AgUk9QRSAodGhlbyBKLiBLcnVzY2hrZSkuDQoNCkvhur90IHF14bqjOg0KDQpMaeG7gXUgdGh14buRYyB0xINuZyBk4bqnbiDEkcOjIGfDonkgcmEgbeG7mXQgaGnhu4d1IOG7qW5nIHnhur91IG5oxrBuZyBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIGzDoG0gdGhheSDEkeG7lWkgZ2nDoSB0cuG7iyBUQkwgZ2nhu69hIDQgcGjDom4gbmjDs20gKEYoMyw2MDIpPTYuMjcgOyBwX3ZhbHVlID0gMC4wMDAzIDsgZXRhc3F1YXJlZCA9IDAuMDMpLiBD4bulIHRo4buDLCBu4buTbmcgxJHhu5kgQmlsaXJ1YmluIGPDsyBraHV5bmggaMaw4bubbmcgdMSDbmcgZOG6p24gdOG7qyBsaeG7gXUgdGjhuqVwIG5o4bqldCDEkeG6v24gbGnhu4F1IGNhbyBuaOG6pXQuIFR1eSBuaGnDqm4sIHPhu7Ega2jDoWMgYmnhu4d0IGNo4buJIHRo4buxYyBz4buxIGPDsyDDvSBuZ2jEqWEga2hpIHNvIHPDoW5oIGxp4buBdSBjxqEgYuG6o24gKEEpIHbhu5tpIGxp4buBdSBjYW8gKEMpIHbDoCBy4bqldCBjYW8gKEQpIDsgY8WpbmcgbmjGsCBjw7Mgc+G7sSB0xrDGoW5nIHBo4bqjbiDDvSBuZ2jEqWEgZ2nhu69hIGxp4buBdSBjYW8gbmjhuqV0IChEKSB2w6AgMiBsaeG7gXUgdGjhuqVwIGjGoW4gbMOgIEIgdsOgIEMuIFZp4buHYyB0xINuZyBsaeG7gXUgdOG7qyBBIHNhbmcgQiB2w6AgdOG7qyBCIHNhbmcgQyBraMO0bmcgZ8OieSByYSBz4buxIHRoYXkgxJHhu5VpIMSRw6FuZyBr4buDIHbhu4EgVEJMLg0KDQojIFThu5VuZyBr4bq/dA0KDQpCw6BpIHRo4buxYyBow6BuaCDEkeG6v24gxJHDonkgbMOgIGjhur90LiBDw6FjIGLhuqFuIMSRw6Mga2jDoW0gcGjDoSBs4bqhaSBBTk9WQSB0aGVvIG3hu5l0IGPDoWNoIGzDoG0gaG/DoG4gdG/DoG4ga2jDoWMsIHbhu5tpIG5oaeG7gXUgxrB1IMSRaeG7g20gaMahbiBzbyB24bubaSBwaMawxqFuZyBwaMOhcCB0cnV54buBbiB0aOG7kW5nLiBBTk9WQSBsw6AgbeG7mXQgY2jhu6cgxJHhu4EgcuG6pXQgdGjDuiB24buLLCB2w6wgbsOzIGvhur90IGjhu6NwIGjhuqd1IGjhur90IG5o4buvbmcgeeG6v3UgdOG7kSDEkeG6t2MgdHLGsG5nIGPhu6dhIG3DtG4gVGjhu5FuZyBLw6ogaOG7jWMsIGJhbyBn4buTbSBwaMOibiB0w61jaCBo4buTaSBxdXksIHBow6JuIHBo4buRaSB2w6AgeMOhYyBzdeG6pXQsIHBo4bqjbiBuZ2hp4buHbSBudWxsIGh5cG90aGVzaXMgdGVzdGluZyB2w6AgZWZmZWN0LXNpemUsIHTGsMahbmcgcXVhbiB2w6Agc28gc8OhbmjigKYgDQoNCk5oxrAgY2jDum5nIHTDtGkgdOG7q25nIG7Ds2ksIHZp4buHYyB0aOG7sWMgaMOgbmggQmF5ZXMgZ2nDunAgKGLhuq90IGJ14buZYykgbmfGsOG7nWkgaOG7jWMgeMOieSBk4buxbmcgbeG7mXQga2nhur9uIHRo4bupYyB24buBIHjDoWMgc3XhuqV0LCB0aOG7kW5nIGvDqiB24buvbmcgY2jhuq9jIGjGoW4gbmhp4buBdSBzbyB24bubaSBjw6FjaCBo4buNYyB0cnV54buBbiB0aOG7kW5nLiBUaOG7sWMgaMOgbmggQmF5ZXMgY8WpbmcgdOG6oW8gY2hvIGPDoWMgYuG6oW4gbeG7mXQga+G7uSBuxINuZyB2aeG6v3QgUiBjb2RlcyBwaG9uZyBwaMO6IGjGoW4gbmhp4buBdSBzbyB24bubaSB2aeG7h2Mgc+G7rSBk4bulbmcgcGFja2FnZSB04burIG5nw6B5IG7DoHkgcXVhIG5nw6B5IGtow6FjIDsgdsOsIGtoaSBwaOG6o2kgbMOgbSB0aOG7pyBjw7RuZyBt4buNaSB2aeG7h2MsIGLhuqFuIHPhur0gaOG7jWMgxJHGsOG7o2Mgbmhp4buBdSBoxqFuIHbhu4EgY8O6IHBow6FwLg0KTmjhu69uZyB0aMO0bmcgxJFp4buHcCBxdWFuIHRy4buNbmcgc2F1IMSRw6J5IMSRw6MgxJHGsOG7o2MgdHJ1eeG7gW4gdOG6o2kgdHJvbmcgYsOgaSA6DQoNCjEpCULhuqNuIGNo4bqldCBBTk9WQSBjaMOtbmggbMOgIEdlbmVyYWxpemVkIGxpbmVhciBtb2RlbA0KMikJUXV5IHRyw6xuaCBBTk9WQSAxIHnhur91IHThu5EgY8OzIG3hu6VjIHRpw6p1IHRy4bqjIGzhu51pIDIgY8OidSBo4buPaSB24buBIGvDrWNoIHRoxrDhu5tjL8O9IG5naMSpYSBj4bunYSBoaeG7h3Ug4bupbmcsIHbDoCBraMOhYyBiaeG7h3QgZ2nhu69hIGPDoWMgcGjDom4gbmjDs20NCjMpCUPDsyB0aOG7gyB0aGF5IHRo4bq/IGhvw6BuIHRvw6BuIHF1eSB0csOsbmggQU5PVkEgY+G7lSDEkWnhu4NuIGLhurFuZyBwaMawxqFuZyBwaMOhcCBI4buTaSBxdXkgQmF5ZXMuDQo0KQlQaMawxqFuZyBwaMOhcCBzdXkgZGnhu4VuIEJheWVzIGxpbmggaG/huqF0IHbDoCBjw7Mgbmhp4buBdSDGsHUgdGjhur8gaMahbiBzbyB24bubaSBOdWxsIGh5cG90aGVzaXMgdGVzdGluZyB2w6AgUF92YWx1ZQ0KDQpOaMOzbSBCQVYgeGluIGNow6JuIHRow6BuaCBj4bqjbSDGoW4gc+G7sSDhu6duZyBo4buZIGPhu6dhIGPDoWMgYuG6oW4uIENow7puZyB0w7RpIHPhur0gZ+G6t3AgbOG6oWkgY8OhYyBi4bqhbiB0cm9uZyBt4buZdCBiw6BpIGtow6FjLg==