Nhiệm vụ tuần 1

Tóm tắt Sách “Generalized Linear Models With Examples in R”

Giới thiệu Chung

Cuốn sách này trình bày về Các Mô hình Tuyến tính Tổng quát (Generalized Linear Models - GLM) với các ví dụ minh họa sử dụng ngôn ngữ lập trình R [1]. Sách được chuẩn bị bằng LATEX và R phiên bản 3.4.3, tích hợp sử dụng Sweave [2]. Cuốn sách này cung cấp dữ liệu qua gói R GLMsData [1, 2]. Các hàm trong R được hiển thị bằng phông chữ typewriter theo sau bởi dấu ngoặc đơn, ví dụ: glm() [1]. Các toán tử, data frame và biến trong R cũng được hiển thị bằng phông chữ typewriter, ví dụ: Smoke [1]. Các gói R được hiển thị bằng phông chữ in đậm sans serif, ví dụ: GLMsData [1].

Chương 1: Mô hình Thống kê (Statistical Models)

Chương này giới thiệu các khái niệm cơ bản về mô hình thống kê [3].

  • Quy ước mô tả dữ liệu: Giới thiệu cách mô tả dữ liệu, thường sử dụng ví dụ minh họa [4]. Ví dụ 1.1 sử dụng bộ dữ liệu lungcap từ gói GLMsData, nghiên cứu mối quan hệ giữa dung tích phổi (fev), tình trạng hút thuốc, tuổi, chiều cao và giới tính trên 654 thanh niên ở Đông Boston [4, 5]. Có thể nạp dữ liệu này vào R bằng cách tải gói GLMsData và sử dụng lệnh data(lungcap) [4]. Có thể xem các giá trị đầu tiên/cuối cùng của một biến bằng head()tail() [5].

  • Vẽ đồ thị dữ liệu: Trình bày cách vẽ đồ thị để khám phá dữ liệu [3, 6-11]. R có các cơ chế mạnh mẽ để tạo đồ thị [12]. Các đồ thị đơn giản có thể được tạo dễ dàng [12]. Có thể tùy chỉnh đồ thị bằng các tham số đồ họa của R như las, ylim, xlim, xlab, ylab, main, pch [13]. Có thể sử dụng lệnh plot(lungcap$FEV ~ lungcap$Age) để vẽ đồ thị FEV so với Tuổi [12].

  • Mô hình thống kê mô tả cả đặc điểm ngẫu nhiên và có hệ thống của dữ liệu [14].

  • Mô hình hồi quy (Regression Models) [14].

  • Giải thích mô hình hồi quy [14].

  • Tất cả mô hình đều sai, nhưng một số hữu ích [14].

  • Mục đích của mô hình thống kê ảnh hưởng đến cách phát triển nó [14].

  • Độ chính xác so với Tính tiết kiệm (Accuracy vs Parsimony) [14].

  • Thí nghiệm so với Nghiên cứu quan sát: Nguyên nhân so với Liên kết (Causality vs Association) [15].

  • Thu thập dữ liệu và Khả năng tổng quát hóa [15].

  • Sử dụng R cho mô hình thống kê [15].

Chương 2: Mô hình Hồi quy Tuyến tính (Linear Regression Models)

Chương này đi sâu vào mô hình hồi quy tuyến tính [16].

  • Định nghĩa mô hình hồi quy tuyến tính [16].

  • Hồi quy tuyến tính đơn giản [16]. Bao gồm Ước lượng Bình phương Tối thiểu (Least-Squares Estimation), Ước lượng Hệ số, Ước lượng Phương sai sigma^2, Sai số Chuẩn của Hệ số, Sai số Chuẩn của Giá trị Fitted [16].

  • Ước lượng cho hồi quy bội (Multiple Regression) [17]. Bao gồm Ước lượng Hệ số, Ước lượng Phương sai sigma^2, Sai số Chuẩn [17].

  • Công thức Ma trận của Mô hình Hồi quy Tuyến tính [17]. Bao gồm Ký hiệu Ma trận, Ước lượng Hệ số, Ước lượng Phương sai sigma^2, Ước lượng Phương sai của beta-hat, Ước lượng Phương sai của Giá trị Fitted [17]. Ví dụ 2.10 cho thấy cách sử dụng R để tạo ma trận thiết kế Xmat bằng model.matrix(), tính toán X^T XX^T y sử dụng t() (chuyển vị) và %*% (nhân ma trận), và tìm ước lượng hệ số beta bằng cách giải hệ phương trình sử dụng solve() (nghịch đảo ma trận) [18].

  • Phân tích Phương sai cho Mô hình Hồi quy [19].

  • So sánh các Mô hình Lồng nhau (Nested Models) [19]. Có thể sử dụng phân tích phương sai để so sánh hai mô hình lồng nhau [19]. R lệnh anova() có thể được sử dụng cho mục đích này [20, 21]. Bảng ANOVA bao gồm các cột Df (Bậc tự do), Sum Sq (Tổng bình phương), Mean Sq (Bình phương trung bình), F value (Giá trị F) và Pr(>F) (P-value) [21].

  • Chẩn đoán cho Mô hình Hồi quy Tuyến tính [22].

  • Xây dựng Mô hình Tuyến tính [22].

  • Sử dụng R cho Phân tích Chẩn đoán của Mô hình Hồi quy Tuyến tính [22].

  • Hệ số xác định R-squared (R^2): Tỷ lệ biến thiên tổng cộng được giải thích bởi hồi quy [20]. Có thể tính R^2 bằng công thức 1 - RSS/SST hoặc lấy trực tiếp từ summary(model)$r.squared [23]. R^2 hiệu chỉnh (adjusted R^2) cũng được báo cáo trong summary() [23].

  • So sánh các mô hình không lồng nhau có thể sử dụng Tiêu chí Thông tin Akaike (AIC) hoặc Tiêu chí Thông tin Bayes (BIC) [24]. AIC có thể được trích xuất bằng lệnh extractAIC() [25]. Đối với mô hình hồi quy tuyến tính, bậc tự do tương đương là số lượng tham số hồi quy được ước lượng [25]. BIC sử dụng cùng hàm extractAIC() nhưng với hình phạt (k) được điều chỉnh [25].

  • Problem 2.14 mô tả một nghiên cứu về huyết áp ở nam giới Ghana, sử dụng mô hình hồi quy tuyến tính với nhiều biến giải thích và yêu cầu so sánh các mô hình bằng ANOVA, AIC, BIC, R^2 và R^2 hiệu chỉnh [24].

Chương 3 & 4: Chẩn đoán và Xây dựng Mô hình Hồi quy Tuyến tính

Các chương này mở rộng về chẩn đoán và xây dựng mô hình [22, 26].

  • Chẩn đoán mô hình bao gồm kiểm tra các giả định [22, 27-29]. Các đồ thị chẩn đoán như phần dư chuẩn hóa (standardized residuals) so với giá trị fitted là hữu ích [27-29].

  • Biến đổi đơn giản các biến giải thích (Simple Transformations of Covariates) [30]. Có thể biến đổi biến giải thích, ví dụ sử dụng logarit (log(Ht)) [30].

  • Biến đổi biến phản hồi (Transformations of the Response) [27-29]. Có thể kiểm tra tác động của các biến đổi đối với biến phản hồi bằng cách xem xét các đồ thị phần dư [27-29].

  • Nguyên tắc biên (Marginality Principle) [19, 31].

  • Phân tích ảnh hưởng (Influence Analysis) [32]. Có thể sử dụng influence.measures()cooks.distance() trong R để xác định các quan sát có ảnh hưởng lớn [32, 33]. Quan sát có đòn bẩy (leverage) cao có thể không có ảnh hưởng nếu phần dư nhỏ, và ngược lại [33]. Có thể cập nhật mô hình bằng cách loại bỏ các quan sát có ảnh hưởng lớn bằng tùy chọn subset trong hàm mô hình [32].

  • Lựa chọn biến (Variable Selection) [19].

  • Problem 3.8 sử dụng dữ liệu lungcap để so sánh các mô hình hồi quy tuyến tính khác nhau [34].

  • Problem 3.23 sử dụng dữ liệu gopher để khám phá mối quan hệ giữa các biến, fit mô hình hồi quy tuyến tính có trọng số (weights), và thực hiện phân tích chẩn đoán [35].

  • Problem 3.25 sử dụng dữ liệu ratliver để khám phá dữ liệu, fit mô hình hồi quy tuyến tính, và kiểm tra các quan sát có ảnh hưởng [32].

Chương 5: Mô hình Tuyến tính Tổng quát: Cấu trúc (Generalized Linear Models: Structure)

Chương này giới thiệu cấu trúc của GLM [26].

  • Hai thành phần của Mô hình Tuyến tính Tổng quát: Thành phần ngẫu nhiên (Random Component) và thành phần có hệ thống (Systematic Component) liên kết thông qua hàm liên kết (link function) [26, 36].

  • Thành phần ngẫu nhiên: Mô hình Phân tán Hàm mũ (Exponential Dispersion Models - EDM) [26, 36]. Bảng 5.1 liệt kê các EDM phổ biến bao gồm Normal, Binomial, Negative Binomial, Poisson, Gamma, Inverse Gaussian và Tweedie, cùng với các thuộc tính của chúng như hàm phương sai V(μ), hàm tích lũy κ(θ), tham số chính tắc θ, tham số phân tán φ, độ lệch đơn vị d(y,μ), miền hỗ trợ S và miền cho μθ [36-38]. Phân phối Tweedie bao gồm các trường hợp đặc biệt như Gamma (ξ=2) và Poisson (ξ=1 với φ=1) [36].

Các Chương Khác về GLM Chuyên biệt

Cuốn sách tiếp tục khám phá các loại GLM cụ thể.

  • Chương 9: Models for Proportions: Binomial GLMs [37]. Sử dụng cho dữ liệu tỷ lệ [39]. Ví dụ sử dụng dữ liệu germ với mô hình Binomial GLM có trọng số (weights) [39].

  • Chương 10: Models for Counts: Poisson and Negative Binomial GLMs [38, 40]. Sử dụng cho dữ liệu đếm [40, 41].

    • Poisson GLM: Thích hợp cho dữ liệu đếm khi phương sai bằng trung bình [40]. Có thể bao gồm một offset trong mô hình, ví dụ:offset(log(Pop)) trong mô hình Poisson log μ = log T + ... nơi log T là một offset không cần ước lượng tham số [40]. Ví dụ sử dụng dữ liệu danishlc [40].

    • Negative Binomial GLM: Thích hợp cho dữ liệu đếm khi có hiện tượng overdispersion (phương sai lớn hơn trung bình) [42]. Có thể so sánh mô hình Quasi-poisson và Negative Binomial khi có overdispersion [42].

    • Quasi-poisson GLM: Cũng được sử dụng khi có overdispersion trong dữ liệu đếm [43]. anova() với test="F" thường được sử dụng cho mô hình Quasi-poisson [43]. Overdispersion có thể được xác nhận nếu độ lệch dư (residual deviance) hoặc Pearson Chi-squared lớn hơn đáng kể bậc tự do dư (residual degrees of freedom) [43]. Ví dụ sử dụng dữ liệu hcrabs [43].

    • Kiểm định độ khớp (Goodness-of-fit): Có thể sử dụng pchisq(deviance(model), df.residual(model), lower.tail=FALSE) để kiểm định giả thuyết rằng mô hình là phù hợp [41].

  • Chương 11: Positive Continuous Data: Gamma and Inverse Gaussian GLMs [38, 44]. Sử dụng cho dữ liệu liên tục dương [44]. Ví dụ sử dụng dữ liệu lime cho Gamma GLM [44, 45].

  • Chương 12: Tweedie GLMs [46]. Trình bày các Mô hình Phân tán Hàm mũ Tweedie (Tweedie EDMs) và cách fit Mô hình Tuyến tính Tổng quát Tweedie (Tweedie GLMs) [38, 46, 47]. Bao gồm ước lượng tham số chỉ số ξ [47]. Có thể sử dụng hàm tweedie()tweedie.profile() trong R [48]. summary() cho mô hình Tweedie sẽ hiển thị ước lượng, sai số chuẩn, giá trị t và P-value, cùng với ước lượng tham số phân tán [49].

Suy luận cho GLM (Inference for GLMs)

  • Kiểm định Tỷ số Độ Lệch (Deviance Ratio Test) hay Kiểm định Tỷ số Khả Năng (Likelihood Ratio Test) [50, 51]. Đối với các phân phối có φ = 1 (ví dụ: Poisson), sự khác biệt giữa độ lệch dư của hai mô hình lồng nhau theo phân phối chi-squared [50, 51]. Có thể tính toán sự khác biệt này và P-value bằng deviance()pchisq() [50]. Lệnh anova(model, test="Chisq") trong R thực hiện kiểm định này [51].

  • Kiểm định Wald (Wald Test): Sử dụng cho các tham số mô hình riêng lẻ hoặc các giả thuyết cụ thể [52, 53]. R summary() cho GLM thường thực hiện z-test (coi phân tán đã biết), điều này có thể phóng đại nhẹ ý nghĩa thống kê [52]. Có thể tính toán kiểm định Wald thủ công [52].

  • Kiểm định Score (Score Test): Một phương pháp kiểm định khác, có thể thực hiện trong R bằng hàm như glm.scoretest từ gói statmod [54].

Phụ lục A: Sử dụng R cho Phân tích Dữ liệu (Using R for Data Analysis)

Phụ lục này giới thiệu cách sử dụng R [55].

  • Chuẩn bị sử dụng R: Cách tải và cài đặt R và các gói R cần thiết (ví dụ: GLMsData) [4, 55, 56]. Các trang web R quan trọng bao gồm CRAN và R-project.org [56-58].

  • Giới thiệu cơ bản về sử dụng R: Sử dụng R như một máy tính nâng cao, thoát R (q()), nhận trợ giúp (help()), tên biến, làm việc với vector, nạp dữ liệu vào R [55, 59]. Có thể nạp dữ liệu có sẵn trong R bằng lệnh data() [60]. Có thể nạp dữ liệu từ file bằng read.table() [61].

  • Làm việc với data frame: Ví dụ lungcap là một data frame [4]. Có thể truy cập biến trong data frame bằng $, ví dụ lungcap$Age [12, 61]. Có thể sử dụng with() để truy cập biến dễ dàng hơn, nhưng attach()/detach() không được khuyến khích [61]. Có thể xem cấu trúc data frame bằng str(), tóm tắt bằng summary() [48].

  • Sử dụng hàm trong R: R chứa rất nhiều hàm và các gói bổ sung thêm nhiều hàm khác [59, 61]. Nhiều hàm đã được sử dụng trong sách như glm(), lm(), anova(), summary(), plot() [1, 20, 48].

  • Các hàm thống kê cơ bản trong R: mean(), sd(), var(), median(), IQR() [12, 59, 61].

  • Vẽ đồ thị cơ bản trong R [12, 13, 59, 62-64].

  • Viết hàm trong R: Hướng dẫn cách viết hàm tùy chỉnh, sử dụng đối số mặc định, lệnh signif(), paste(), return() [59, 65, 66].

Phụ lục B: Bộ dữ liệu (Data sets)

Liệt kê các bộ dữ liệu được sử dụng trong sách, bao gồm lungcap, hcrabs, lime, pock, gopher, ratliver, blocks, danishlc, cervical, turbines,… [67].

Chỉ mục (Index)

Bao gồm chỉ mục các bộ dữ liệu và các lệnh/hàm trong R được sử dụng trong sách, cung cấp tham chiếu trang [48, 68, 69].

Các Bài toán bổ sung (Extra Problems)

Cung cấp các bài toán thực hành bổ sung [70, 71].

Thực hiện thống kê mô tả cho các biến trong file: Supermarket Transactions.csv

if (!require("readxl")) install.packages("readxl")
## Loading required package: readxl
if (!require("dplyr")) install.packages("dplyr")
## Loading required package: dplyr
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
if (!require("psych")) install.packages("psych")
## Loading required package: psych
  library(readxl)
data <- read_excel("C:/Users/Nep/Downloads/Supermarket Transactions.xlsx")
## New names:
## • `` -> `...1`
str(data)
## tibble [14,059 × 16] (S3: tbl_df/tbl/data.frame)
##  $ ...1             : num [1:14059] 1 2 3 4 5 6 7 8 9 10 ...
##  $ PurchaseDate     : POSIXct[1:14059], format: "2007-12-18" "2007-12-20" ...
##  $ CustomerID       : num [1:14059] 7223 7841 8374 9619 1900 ...
##  $ Gender           : chr [1:14059] "F" "M" "F" "M" ...
##  $ MaritalStatus    : chr [1:14059] "S" "M" "M" "M" ...
##  $ Homeowner        : chr [1:14059] "Y" "Y" "N" "Y" ...
##  $ Children         : num [1:14059] 2 5 2 3 3 3 2 2 3 1 ...
##  $ AnnualIncome     : chr [1:14059] "$30K - $50K" "$70K - $90K" "$50K - $70K" "$30K - $50K" ...
##  $ City             : chr [1:14059] "Los Angeles" "Los Angeles" "Bremerton" "Portland" ...
##  $ StateorProvince  : chr [1:14059] "CA" "CA" "WA" "OR" ...
##  $ Country          : chr [1:14059] "USA" "USA" "USA" "USA" ...
##  $ ProductFamily    : chr [1:14059] "Food" "Food" "Food" "Food" ...
##  $ ProductDepartment: chr [1:14059] "Snack Foods" "Produce" "Snack Foods" "Snacks" ...
##  $ ProductCategory  : chr [1:14059] "Snack Foods" "Vegetables" "Snack Foods" "Candy" ...
##  $ UnitsSold        : num [1:14059] 5 5 3 4 4 3 4 6 1 2 ...
##  $ Revenue          : num [1:14059] 27.38 14.9 5.52 4.44 14 ...
head(data)
numeric_vars <- data[, sapply(data, is.numeric)]
summary(numeric_vars)
##       ...1         CustomerID       Children      UnitsSold        Revenue     
##  Min.   :    1   Min.   :    3   Min.   :0.00   Min.   :1.000   Min.   : 0.53  
##  1st Qu.: 3516   1st Qu.: 2549   1st Qu.:1.00   1st Qu.:3.000   1st Qu.: 6.84  
##  Median : 7030   Median : 5060   Median :3.00   Median :4.000   Median :11.25  
##  Mean   : 7030   Mean   : 5117   Mean   :2.53   Mean   :4.081   Mean   :13.00  
##  3rd Qu.:10544   3rd Qu.: 7633   3rd Qu.:4.00   3rd Qu.:5.000   3rd Qu.:17.37  
##  Max.   :14059   Max.   :10280   Max.   :5.00   Max.   :8.000   Max.   :56.70
library(psych)
describe(numeric_vars)
categorical_vars <- data[, sapply(data, is.character) | sapply(data, is.factor)]
lapply(categorical_vars, table)
## $Gender
## 
##    F    M 
## 7170 6889 
## 
## $MaritalStatus
## 
##    M    S 
## 6866 7193 
## 
## $Homeowner
## 
##    N    Y 
## 5615 8444 
## 
## $AnnualIncome
## 
##   $10K - $30K $110K - $130K $130K - $150K       $150K +   $30K - $50K 
##          3090           643           760           273          4601 
##   $50K - $70K   $70K - $90K  $90K - $110K 
##          2370          1709           613 
## 
## $City
## 
##      Acapulco    Bellingham Beverly Hills     Bremerton       Camacho 
##           383           143           811           834           452 
##   Guadalajara       Hidalgo   Los Angeles        Merida   Mexico City 
##            75           845           926           654           194 
##       Orizaba      Portland         Salem    San Andres     San Diego 
##           464           876          1386           621           866 
## San Francisco       Seattle       Spokane        Tacoma     Vancouver 
##           130           922           875          1257           633 
##      Victoria   Walla Walla        Yakima 
##           176           160           376 
## 
## $StateorProvince
## 
##        BC        CA        DF  Guerrero   Jalisco        OR  Veracruz        WA 
##       809      2733       815       383        75      2262       464      4567 
##   Yucatan Zacatecas 
##       654      1297 
## 
## $Country
## 
## Canada Mexico    USA 
##    809   3688   9562 
## 
## $ProductFamily
## 
##          Drink           Food Non-Consumable 
##           1250          10153           2656 
## 
## $ProductDepartment
## 
## Alcoholic Beverages         Baked Goods        Baking Goods           Beverages 
##                 356                 425                1072                 680 
##     Breakfast Foods        Canned Foods     Canned Products            Carousel 
##                 188                 977                 109                  59 
##            Checkout               Dairy                Deli                Eggs 
##                  82                 903                 699                 198 
##        Frozen Foods  Health and Hygiene           Household                Meat 
##                1382                 893                1420                  89 
##         Periodicals             Produce             Seafood         Snack Foods 
##                 202                1994                 102                1600 
##              Snacks       Starchy Foods 
##                 352                 277 
## 
## $ProductCategory
## 
##         Baking Goods    Bathroom Products        Beer and Wine 
##                  484                  365                  356 
##                Bread      Breakfast Foods              Candles 
##                  425                  417                   45 
##                Candy     Canned Anchovies         Canned Clams 
##                  352                   44                   53 
##       Canned Oysters      Canned Sardines        Canned Shrimp 
##                   35                   40                   38 
##          Canned Soup          Canned Tuna Carbonated Beverages 
##                  404                   87                  154 
##    Cleaning Supplies        Cold Remedies                Dairy 
##                  189                   93                  903 
##        Decongestants               Drinks                 Eggs 
##                   85                  135                  198 
##           Electrical      Frozen Desserts       Frozen Entrees 
##                  355                  323                  118 
##                Fruit             Hardware        Hot Beverages 
##                  765                  129                  226 
##              Hygiene     Jams and Jellies     Kitchen Products 
##                  197                  588                  217 
##            Magazines                 Meat        Miscellaneous 
##                  202                  761                   42 
##  Packaged Vegetables       Pain Relievers       Paper Products 
##                   48                  192                  345 
##                Pizza     Plastic Products Pure Juice Beverages 
##                  194                  141                  165 
##              Seafood          Side Dishes          Snack Foods 
##                  102                  153                 1600 
##            Specialty        Starchy Foods           Vegetables 
##                  289                  277                 1728
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSB0deG6p24gMSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogIHBkZl9kb2N1bWVudDoNCiAgICBleHRyYV9kZXBlbmRlbmNpZXM6DQogICAgICB2aWV0bmFtOiB1dGY4DQogICAgdG9jOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCmdlb21ldHJ5Og0KICAgICAgLSBpbm5lcj0zY20NCiAgICAgIC0gb3V0ZXI9NGNtDQogICAgICAtIHRvcD0zY20NCiAgICAgIC0gYm90dG9tPTRjbQ0KICAgICAgLSBoZWFkc2VwPTIycHQNCiAgICAgIC0gaGVhZGhlaWdodD0xMXB0DQogICAgICAtIGZvb3Rza2lwPTMzcHQNCiAgICAgIC0gaWdub3JlaGVhZA0KICAgICAgLSBpZ25vcmVmb290DQogICAgICAtIGhlaWdodHJvdW5kZWQNCi0tLQ0KKipOaGnhu4dtIHbhu6UgdHXhuqduIDEqKg0KDQojIFTDs20gdOG6r3QgU8OhY2ggIkdlbmVyYWxpemVkIExpbmVhciBNb2RlbHMgV2l0aCBFeGFtcGxlcyBpbiBSIiANCg0KIyBHaeG7m2kgdGhp4buHdSBDaHVuZw0KDQpDdeG7kW4gc8OhY2ggbsOgeSB0csOsbmggYsOgeSB24buBIEPDoWMgTcO0IGjDrG5oIFR1eeG6v24gdMOtbmggVOG7lW5nIHF1w6F0IChHZW5lcmFsaXplZCBMaW5lYXIgTW9kZWxzIC0gR0xNKSB24bubaSBjw6FjIHbDrSBk4bulIG1pbmggaOG7jWEgc+G7rSBk4bulbmcgbmfDtG4gbmfhu68gbOG6rXAgdHLDrG5oIFIgWzFdLiBTw6FjaCDEkcaw4bujYyBjaHXhuqluIGLhu4sgYuG6sW5nIExBVEVYIHbDoCBSIHBoacOqbiBi4bqjbiAzLjQuMywgdMOtY2ggaOG7o3Agc+G7rSBk4bulbmcgU3dlYXZlIFsyXS4gQ3Xhu5FuIHPDoWNoIG7DoHkgY3VuZyBj4bqlcCBk4buvIGxp4buHdSBxdWEgZ8OzaSBSICoqR0xNc0RhdGEqKiBbMSwgMl0uIEPDoWMgaMOgbSB0cm9uZyBSIMSRxrDhu6NjIGhp4buDbiB0aOG7iyBi4bqxbmcgcGjDtG5nIGNo4buvIHR5cGV3cml0ZXIgdGhlbyBzYXUgYuG7n2kgZOG6pXUgbmdv4bq3YyDEkcahbiwgdsOtIGThu6U6IGBnbG0oKWAgWzFdLiBDw6FjIHRvw6FuIHThu60sIGRhdGEgZnJhbWUgdsOgIGJp4bq/biB0cm9uZyBSIGPFqW5nIMSRxrDhu6NjIGhp4buDbiB0aOG7iyBi4bqxbmcgcGjDtG5nIGNo4buvIHR5cGV3cml0ZXIsIHbDrSBk4bulOiBgU21va2VgIFsxXS4gQ8OhYyBnw7NpIFIgxJHGsOG7o2MgaGnhu4NuIHRo4buLIGLhurFuZyBwaMO0bmcgY2jhu68gaW4gxJHhuq1tIHNhbnMgc2VyaWYsIHbDrSBk4bulOiAqKkdMTXNEYXRhKiogWzFdLg0KDQojIENoxrDGoW5nIDE6IE3DtCBow6xuaCBUaOG7kW5nIGvDqiAoU3RhdGlzdGljYWwgTW9kZWxzKQ0KDQpDaMawxqFuZyBuw6B5IGdp4bubaSB0aGnhu4d1IGPDoWMga2jDoWkgbmnhu4dtIGPGoSBi4bqjbiB24buBIG3DtCBow6xuaCB0aOG7kW5nIGvDqiBbM10uDQoNCiogICAqKlF1eSDGsOG7m2MgbcO0IHThuqMgZOG7ryBsaeG7h3UqKjogR2nhu5tpIHRoaeG7h3UgY8OhY2ggbcO0IHThuqMgZOG7ryBsaeG7h3UsIHRoxrDhu51uZyBz4butIGThu6VuZyB2w60gZOG7pSBtaW5oIGjhu41hIFs0XS4gVsOtIGThu6UgMS4xIHPhu60gZOG7pW5nIGLhu5kgZOG7ryBsaeG7h3UgYGx1bmdjYXBgIHThu6sgZ8OzaSAqKkdMTXNEYXRhKiosIG5naGnDqm4gY+G7qXUgbeG7kWkgcXVhbiBo4buHIGdp4buvYSBkdW5nIHTDrWNoIHBo4buVaSAoZmV2KSwgdMOsbmggdHLhuqFuZyBow7p0IHRodeG7kWMsIHR14buVaSwgY2hp4buBdSBjYW8gdsOgIGdp4bubaSB0w61uaCB0csOqbiA2NTQgdGhhbmggbmnDqm4g4bufIMSQw7RuZyBCb3N0b24gWzQsIDVdLiBDw7MgdGjhu4MgbuG6oXAgZOG7ryBsaeG7h3UgbsOgeSB2w6BvIFIgYuG6sW5nIGPDoWNoIHThuqNpIGfDs2kgKipHTE1zRGF0YSoqIHbDoCBz4butIGThu6VuZyBs4buHbmggYGRhdGEobHVuZ2NhcClgIFs0XS4gQ8OzIHRo4buDIHhlbSBjw6FjIGdpw6EgdHLhu4sgxJHhuqd1IHRpw6puL2N14buRaSBjw7luZyBj4bunYSBt4buZdCBiaeG6v24gYuG6sW5nIGBoZWFkKClgIHbDoCBgdGFpbCgpYCBbNV0uDQoNCiogICAqKlbhur0gxJHhu5MgdGjhu4sgZOG7ryBsaeG7h3UqKjogVHLDrG5oIGLDoHkgY8OhY2ggduG6vSDEkeG7kyB0aOG7iyDEkeG7gyBraMOhbSBwaMOhIGThu68gbGnhu4d1IFszLCA2LTExXS4gUiBjw7MgY8OhYyBjxqEgY2jhur8gbeG6oW5oIG3hur0gxJHhu4MgdOG6oW8gxJHhu5MgdGjhu4sgWzEyXS4gQ8OhYyDEkeG7kyB0aOG7iyDEkcahbiBnaeG6o24gY8OzIHRo4buDIMSRxrDhu6NjIHThuqFvIGThu4UgZMOgbmcgWzEyXS4gQ8OzIHRo4buDIHTDuXkgY2jhu4luaCDEkeG7kyB0aOG7iyBi4bqxbmcgY8OhYyB0aGFtIHPhu5EgxJHhu5MgaOG7jWEgY+G7p2EgUiBuaMawIGBsYXNgLCBgeWxpbWAsIGB4bGltYCwgYHhsYWJgLCBgeWxhYmAsIGBtYWluYCwgYHBjaGAgWzEzXS4gQ8OzIHRo4buDIHPhu60gZOG7pW5nIGzhu4duaCBgcGxvdChsdW5nY2FwJEZFViB+IGx1bmdjYXAkQWdlKWAgxJHhu4MgduG6vSDEkeG7kyB0aOG7iyBGRVYgc28gduG7m2kgVHXhu5VpIFsxMl0uDQoNCiogICAqKk3DtCBow6xuaCB0aOG7kW5nIGvDqiBtw7QgdOG6oyBj4bqjIMSR4bq3YyDEkWnhu4NtIG5n4bqrdSBuaGnDqm4gdsOgIGPDsyBo4buHIHRo4buRbmcgY+G7p2EgZOG7ryBsaeG7h3UqKiBbMTRdLg0KDQoqICAgKipNw7QgaMOsbmggaOG7k2kgcXV5IChSZWdyZXNzaW9uIE1vZGVscykqKiBbMTRdLg0KDQoqICAgKipHaeG6o2kgdGjDrWNoIG3DtCBow6xuaCBo4buTaSBxdXkqKiBbMTRdLg0KDQoqICAgKipU4bqldCBj4bqjIG3DtCBow6xuaCDEkeG7gXUgc2FpLCBuaMawbmcgbeG7mXQgc+G7kSBo4buvdSDDrWNoKiogWzE0XS4NCg0KKiAgICoqTeG7pWMgxJHDrWNoIGPhu6dhIG3DtCBow6xuaCB0aOG7kW5nIGvDqiDhuqNuaCBoxrDhu59uZyDEkeG6v24gY8OhY2ggcGjDoXQgdHJp4buDbiBuw7MqKiBbMTRdLg0KDQoqICAgKirEkOG7mSBjaMOtbmggeMOhYyBzbyB24bubaSBUw61uaCB0aeG6v3Qga2nhu4dtIChBY2N1cmFjeSB2cyBQYXJzaW1vbnkpKiogWzE0XS4NCg0KKiAgICoqVGjDrSBuZ2hp4buHbSBzbyB24bubaSBOZ2hpw6puIGPhu6l1IHF1YW4gc8OhdDogTmd1ecOqbiBuaMOibiBzbyB24bubaSBMacOqbiBr4bq/dCAoQ2F1c2FsaXR5IHZzIEFzc29jaWF0aW9uKSoqIFsxNV0uDQoNCiogICAqKlRodSB0aOG6rXAgZOG7ryBsaeG7h3UgdsOgIEto4bqjIG7Eg25nIHThu5VuZyBxdcOhdCBow7NhKiogWzE1XS4NCg0KKiAgICoqU+G7rSBk4bulbmcgUiBjaG8gbcO0IGjDrG5oIHRo4buRbmcga8OqKiogWzE1XS4NCg0KIyBDaMawxqFuZyAyOiBNw7QgaMOsbmggSOG7k2kgcXV5IFR1eeG6v24gdMOtbmggKExpbmVhciBSZWdyZXNzaW9uIE1vZGVscykNCg0KQ2jGsMahbmcgbsOgeSDEkWkgc8OidSB2w6BvIG3DtCBow6xuaCBo4buTaSBxdXkgdHV54bq/biB0w61uaCBbMTZdLg0KDQoqICAgKirEkOG7i25oIG5naMSpYSBtw7QgaMOsbmggaOG7k2kgcXV5IHR1eeG6v24gdMOtbmgqKiBbMTZdLg0KDQoqICAgKipI4buTaSBxdXkgdHV54bq/biB0w61uaCDEkcahbiBnaeG6o24qKiBbMTZdLiBCYW8gZ+G7k20gxq/hu5tjIGzGsOG7o25nIELDrG5oIHBoxrDGoW5nIFThu5FpIHRoaeG7g3UgKExlYXN0LVNxdWFyZXMgRXN0aW1hdGlvbiksIMav4bubYyBsxrDhu6NuZyBI4buHIHPhu5EsIMav4bubYyBsxrDhu6NuZyBQaMawxqFuZyBzYWkgc2lnbWFeMiwgU2FpIHPhu5EgQ2h14bqpbiBj4bunYSBI4buHIHPhu5EsIFNhaSBz4buRIENodeG6qW4gY+G7p2EgR2nDoSB0cuG7iyBGaXR0ZWQgWzE2XS4NCg0KKiAgICoqxq/hu5tjIGzGsOG7o25nIGNobyBo4buTaSBxdXkgYuG7mWkgKE11bHRpcGxlIFJlZ3Jlc3Npb24pKiogWzE3XS4gQmFvIGfhu5NtIMav4bubYyBsxrDhu6NuZyBI4buHIHPhu5EsIMav4bubYyBsxrDhu6NuZyBQaMawxqFuZyBzYWkgc2lnbWFeMiwgU2FpIHPhu5EgQ2h14bqpbiBbMTddLg0KDQoqICAgKipDw7RuZyB0aOG7qWMgTWEgdHLhuq1uIGPhu6dhIE3DtCBow6xuaCBI4buTaSBxdXkgVHV54bq/biB0w61uaCoqIFsxN10uIEJhbyBn4buTbSBLw70gaGnhu4d1IE1hIHRy4bqtbiwgxq/hu5tjIGzGsOG7o25nIEjhu4cgc+G7kSwgxq/hu5tjIGzGsOG7o25nIFBoxrDGoW5nIHNhaSBzaWdtYV4yLCDGr+G7m2MgbMaw4bujbmcgUGjGsMahbmcgc2FpIGPhu6dhIGJldGEtaGF0LCDGr+G7m2MgbMaw4bujbmcgUGjGsMahbmcgc2FpIGPhu6dhIEdpw6EgdHLhu4sgRml0dGVkIFsxN10uIFbDrSBk4bulIDIuMTAgY2hvIHRo4bqleSBjw6FjaCBz4butIGThu6VuZyBSIMSR4buDIHThuqFvIG1hIHRy4bqtbiB0aGnhur90IGvhur8gYFhtYXRgIGLhurFuZyBgbW9kZWwubWF0cml4KClgLCB0w61uaCB0b8OhbiBgWF5UIFhgIHbDoCBgWF5UIHlgIHPhu60gZOG7pW5nIGB0KClgIChjaHV54buDbiB24buLKSB2w6AgYCUqJWAgKG5ow6JuIG1hIHRy4bqtbiksIHbDoCB0w6xtIMaw4bubYyBsxrDhu6NuZyBo4buHIHPhu5EgYmV0YSBi4bqxbmcgY8OhY2ggZ2nhuqNpIGjhu4cgcGjGsMahbmcgdHLDrG5oIHPhu60gZOG7pW5nIGBzb2x2ZSgpYCAobmdo4buLY2ggxJHhuqNvIG1hIHRy4bqtbikgWzE4XS4NCg0KKiAgICoqUGjDom4gdMOtY2ggUGjGsMahbmcgc2FpIGNobyBNw7QgaMOsbmggSOG7k2kgcXV5KiogWzE5XS4NCg0KKiAgICoqU28gc8OhbmggY8OhYyBNw7QgaMOsbmggTOG7k25nIG5oYXUgKE5lc3RlZCBNb2RlbHMpKiogWzE5XS4gQ8OzIHRo4buDIHPhu60gZOG7pW5nIHBow6JuIHTDrWNoIHBoxrDGoW5nIHNhaSDEkeG7gyBzbyBzw6FuaCBoYWkgbcO0IGjDrG5oIGzhu5NuZyBuaGF1IFsxOV0uIFIgbOG7h25oIGBhbm92YSgpYCBjw7MgdGjhu4MgxJHGsOG7o2Mgc+G7rSBk4bulbmcgY2hvIG3hu6VjIMSRw61jaCBuw6B5IFsyMCwgMjFdLiBC4bqjbmcgQU5PVkEgYmFvIGfhu5NtIGPDoWMgY+G7mXQgRGYgKELhuq1jIHThu7EgZG8pLCBTdW0gU3EgKFThu5VuZyBiw6xuaCBwaMawxqFuZyksIE1lYW4gU3EgKELDrG5oIHBoxrDGoW5nIHRydW5nIGLDrG5oKSwgRiB2YWx1ZSAoR2nDoSB0cuG7iyBGKSB2w6AgUHIoPkYpIChQLXZhbHVlKSBbMjFdLg0KDQoqICAgKipDaOG6qW4gxJFvw6FuIGNobyBNw7QgaMOsbmggSOG7k2kgcXV5IFR1eeG6v24gdMOtbmgqKiBbMjJdLg0KDQoqICAgKipYw6J5IGThu7FuZyBNw7QgaMOsbmggVHV54bq/biB0w61uaCoqIFsyMl0uDQoNCiogICAqKlPhu60gZOG7pW5nIFIgY2hvIFBow6JuIHTDrWNoIENo4bqpbiDEkW/DoW4gY+G7p2EgTcO0IGjDrG5oIEjhu5NpIHF1eSBUdXnhur9uIHTDrW5oKiogWzIyXS4NCg0KKiAgICoqSOG7hyBz4buRIHjDoWMgxJHhu4tuaCBSLXNxdWFyZWQgKFJeMikqKjogVOG7tyBs4buHIGJp4bq/biB0aGnDqm4gdOG7lW5nIGPhu5luZyDEkcaw4bujYyBnaeG6o2kgdGjDrWNoIGLhu59pIGjhu5NpIHF1eSBbMjBdLiBDw7MgdGjhu4MgdMOtbmggUl4yIGLhurFuZyBjw7RuZyB0aOG7qWMgYDEgLSBSU1MvU1NUYCBob+G6t2MgbOG6pXkgdHLhu7FjIHRp4bq/cCB04burIGBzdW1tYXJ5KG1vZGVsKSRyLnNxdWFyZWRgIFsyM10uIFJeMiBoaeG7h3UgY2jhu4luaCAoYWRqdXN0ZWQgUl4yKSBjxaluZyDEkcaw4bujYyBiw6FvIGPDoW8gdHJvbmcgYHN1bW1hcnkoKWAgWzIzXS4NCg0KKiAgICoqU28gc8OhbmggY8OhYyBtw7QgaMOsbmgga2jDtG5nIGzhu5NuZyBuaGF1KiogY8OzIHRo4buDIHPhu60gZOG7pW5nIFRpw6p1IGNow60gVGjDtG5nIHRpbiBBa2Fpa2UgKEFJQykgaG/hurdjIFRpw6p1IGNow60gVGjDtG5nIHRpbiBCYXllcyAoQklDKSBbMjRdLiBBSUMgY8OzIHRo4buDIMSRxrDhu6NjIHRyw61jaCB4deG6pXQgYuG6sW5nIGzhu4duaCBgZXh0cmFjdEFJQygpYCBbMjVdLiDEkOG7kWkgduG7m2kgbcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oLCBi4bqtYyB04buxIGRvIHTGsMahbmcgxJHGsMahbmcgbMOgIHPhu5EgbMaw4bujbmcgdGhhbSBz4buRIGjhu5NpIHF1eSDEkcaw4bujYyDGsOG7m2MgbMaw4bujbmcgWzI1XS4gQklDIHPhu60gZOG7pW5nIGPDuW5nIGjDoG0gYGV4dHJhY3RBSUMoKWAgbmjGsG5nIHbhu5tpIGjDrG5oIHBo4bqhdCAoYGtgKSDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmggWzI1XS4NCg0KKiAgICoqUHJvYmxlbSAyLjE0KiogbcO0IHThuqMgbeG7mXQgbmdoacOqbiBj4bupdSB24buBIGh1eeG6v3Qgw6FwIOG7nyBuYW0gZ2nhu5tpIEdoYW5hLCBz4butIGThu6VuZyBtw7QgaMOsbmggaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggduG7m2kgbmhp4buBdSBiaeG6v24gZ2nhuqNpIHRow61jaCB2w6AgecOqdSBj4bqndSBzbyBzw6FuaCBjw6FjIG3DtCBow6xuaCBi4bqxbmcgQU5PVkEsIEFJQywgQklDLCBSXjIgdsOgIFJeMiBoaeG7h3UgY2jhu4luaCBbMjRdLg0KDQojIENoxrDGoW5nIDMgJiA0OiBDaOG6qW4gxJFvw6FuIHbDoCBYw6J5IGThu7FuZyBNw7QgaMOsbmggSOG7k2kgcXV5IFR1eeG6v24gdMOtbmgNCg0KQ8OhYyBjaMawxqFuZyBuw6B5IG3hu58gcuG7mW5nIHbhu4EgY2jhuqluIMSRb8OhbiB2w6AgeMOieSBk4buxbmcgbcO0IGjDrG5oIFsyMiwgMjZdLg0KDQoqICAgKipDaOG6qW4gxJFvw6FuIG3DtCBow6xuaCoqIGJhbyBn4buTbSBraeG7g20gdHJhIGPDoWMgZ2nhuqMgxJHhu4tuaCBbMjIsIDI3LTI5XS4gQ8OhYyDEkeG7kyB0aOG7iyBjaOG6qW4gxJFvw6FuIG5oxrAgcGjhuqduIGTGsCBjaHXhuqluIGjDs2EgKHN0YW5kYXJkaXplZCByZXNpZHVhbHMpIHNvIHbhu5tpIGdpw6EgdHLhu4sgZml0dGVkIGzDoCBo4buvdSDDrWNoIFsyNy0yOV0uDQoNCiogICAqKkJp4bq/biDEkeG7lWkgxJHGoW4gZ2nhuqNuIGPDoWMgYmnhur9uIGdp4bqjaSB0aMOtY2ggKFNpbXBsZSBUcmFuc2Zvcm1hdGlvbnMgb2YgQ292YXJpYXRlcykqKiBbMzBdLiBDw7MgdGjhu4MgYmnhur9uIMSR4buVaSBiaeG6v24gZ2nhuqNpIHRow61jaCwgdsOtIGThu6Ugc+G7rSBk4bulbmcgbG9nYXJpdCAoYGxvZyhIdClgKSBbMzBdLg0KDQoqICAgKipCaeG6v24gxJHhu5VpIGJp4bq/biBwaOG6o24gaOG7k2kgKFRyYW5zZm9ybWF0aW9ucyBvZiB0aGUgUmVzcG9uc2UpKiogWzI3LTI5XS4gQ8OzIHRo4buDIGtp4buDbSB0cmEgdMOhYyDEkeG7mW5nIGPhu6dhIGPDoWMgYmnhur9uIMSR4buVaSDEkeG7kWkgduG7m2kgYmnhur9uIHBo4bqjbiBo4buTaSBi4bqxbmcgY8OhY2ggeGVtIHjDqXQgY8OhYyDEkeG7kyB0aOG7iyBwaOG6p24gZMawIFsyNy0yOV0uDQoNCiogICAqKk5ndXnDqm4gdOG6r2MgYmnDqm4gKE1hcmdpbmFsaXR5IFByaW5jaXBsZSkqKiBbMTksIDMxXS4NCg0KKiAgICoqUGjDom4gdMOtY2gg4bqjbmggaMaw4bufbmcgKEluZmx1ZW5jZSBBbmFseXNpcykqKiBbMzJdLiBDw7MgdGjhu4Mgc+G7rSBk4bulbmcgYGluZmx1ZW5jZS5tZWFzdXJlcygpYCB2w6AgYGNvb2tzLmRpc3RhbmNlKClgIHRyb25nIFIgxJHhu4MgeMOhYyDEkeG7i25oIGPDoWMgcXVhbiBzw6F0IGPDsyDhuqNuaCBoxrDhu59uZyBs4bubbiBbMzIsIDMzXS4gUXVhbiBzw6F0IGPDsyDEkcOybiBi4bqpeSAobGV2ZXJhZ2UpIGNhbyBjw7MgdGjhu4Mga2jDtG5nIGPDsyDhuqNuaCBoxrDhu59uZyBu4bq/dSBwaOG6p24gZMawIG5o4buPLCB2w6AgbmfGsOG7o2MgbOG6oWkgWzMzXS4gQ8OzIHRo4buDIGPhuq1wIG5o4bqtdCBtw7QgaMOsbmggYuG6sW5nIGPDoWNoIGxv4bqhaSBi4buPIGPDoWMgcXVhbiBzw6F0IGPDsyDhuqNuaCBoxrDhu59uZyBs4bubbiBi4bqxbmcgdMO5eSBjaOG7jW4gYHN1YnNldGAgdHJvbmcgaMOgbSBtw7QgaMOsbmggWzMyXS4NCg0KKiAgICoqTOG7sWEgY2jhu41uIGJp4bq/biAoVmFyaWFibGUgU2VsZWN0aW9uKSoqIFsxOV0uDQoNCiogICAqKlByb2JsZW0gMy44Kiogc+G7rSBk4bulbmcgZOG7ryBsaeG7h3UgYGx1bmdjYXBgIMSR4buDIHNvIHPDoW5oIGPDoWMgbcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIGtow6FjIG5oYXUgWzM0XS4NCg0KKiAgICoqUHJvYmxlbSAzLjIzKiogc+G7rSBk4bulbmcgZOG7ryBsaeG7h3UgYGdvcGhlcmAgxJHhu4Mga2jDoW0gcGjDoSBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIGPDoWMgYmnhur9uLCBmaXQgbcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIGPDsyB0cuG7jW5nIHPhu5EgKGB3ZWlnaHRzYCksIHbDoCB0aOG7sWMgaGnhu4duIHBow6JuIHTDrWNoIGNo4bqpbiDEkW/DoW4gWzM1XS4NCg0KKiAgICoqUHJvYmxlbSAzLjI1Kiogc+G7rSBk4bulbmcgZOG7ryBsaeG7h3UgYHJhdGxpdmVyYCDEkeG7gyBraMOhbSBwaMOhIGThu68gbGnhu4d1LCBmaXQgbcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oLCB2w6Aga2nhu4NtIHRyYSBjw6FjIHF1YW4gc8OhdCBjw7Mg4bqjbmggaMaw4bufbmcgWzMyXS4NCg0KIyBDaMawxqFuZyA1OiBNw7QgaMOsbmggVHV54bq/biB0w61uaCBU4buVbmcgcXXDoXQ6IEPhuqV1IHRyw7pjIChHZW5lcmFsaXplZCBMaW5lYXIgTW9kZWxzOiBTdHJ1Y3R1cmUpDQoNCkNoxrDGoW5nIG7DoHkgZ2nhu5tpIHRoaeG7h3UgY+G6pXUgdHLDumMgY+G7p2EgR0xNIFsyNl0uDQoNCiogICAqKkhhaSB0aMOgbmggcGjhuqduIGPhu6dhIE3DtCBow6xuaCBUdXnhur9uIHTDrW5oIFThu5VuZyBxdcOhdCoqOiBUaMOgbmggcGjhuqduIG5n4bqrdSBuaGnDqm4gKFJhbmRvbSBDb21wb25lbnQpIHbDoCB0aMOgbmggcGjhuqduIGPDsyBo4buHIHRo4buRbmcgKFN5c3RlbWF0aWMgQ29tcG9uZW50KSBsacOqbiBr4bq/dCB0aMO0bmcgcXVhIGjDoG0gbGnDqm4ga+G6v3QgKGxpbmsgZnVuY3Rpb24pIFsyNiwgMzZdLg0KDQoqICAgKipUaMOgbmggcGjhuqduIG5n4bqrdSBuaGnDqm46IE3DtCBow6xuaCBQaMOibiB0w6FuIEjDoG0gbcWpIChFeHBvbmVudGlhbCBEaXNwZXJzaW9uIE1vZGVscyAtIEVETSkqKiBbMjYsIDM2XS4gQuG6o25nIDUuMSBsaeG7h3Qga8OqIGPDoWMgRURNIHBo4buVIGJp4bq/biBiYW8gZ+G7k20gTm9ybWFsLCBCaW5vbWlhbCwgTmVnYXRpdmUgQmlub21pYWwsIFBvaXNzb24sIEdhbW1hLCBJbnZlcnNlIEdhdXNzaWFuIHbDoCBUd2VlZGllLCBjw7luZyB24bubaSBjw6FjIHRodeG7mWMgdMOtbmggY+G7p2EgY2jDum5nIG5oxrAgaMOgbSBwaMawxqFuZyBzYWkgYFYozrwpYCwgaMOgbSB0w61jaCBsxal5IGDOuijOuClgLCB0aGFtIHPhu5EgY2jDrW5oIHThuq9jIGDOuGAsIHRoYW0gc+G7kSBwaMOibiB0w6FuIGDPhmAsIMSR4buZIGzhu4djaCDEkcahbiB24buLIGBkKHkszrwpYCwgbWnhu4FuIGjhu5cgdHLhu6MgYFNgIHbDoCBtaeG7gW4gY2hvIGDOvGAgdsOgIGDOuGAgWzM2LTM4XS4gUGjDom4gcGjhu5FpIFR3ZWVkaWUgYmFvIGfhu5NtIGPDoWMgdHLGsOG7nW5nIGjhu6NwIMSR4bq3YyBiaeG7h3QgbmjGsCBHYW1tYSAozr49MikgdsOgIFBvaXNzb24gKM6+PTEgduG7m2kgz4Y9MSkgWzM2XS4NCg0KIyBDw6FjIENoxrDGoW5nIEtow6FjIHbhu4EgR0xNIENodXnDqm4gYmnhu4d0DQoNCkN14buRbiBzw6FjaCB0aeG6v3AgdOG7pWMga2jDoW0gcGjDoSBjw6FjIGxv4bqhaSBHTE0gY+G7pSB0aOG7gy4NCg0KKiAgICoqQ2jGsMahbmcgOTogTW9kZWxzIGZvciBQcm9wb3J0aW9uczogQmlub21pYWwgR0xNcyoqIFszN10uIFPhu60gZOG7pW5nIGNobyBk4buvIGxp4buHdSB04bu3IGzhu4cgWzM5XS4gVsOtIGThu6Ugc+G7rSBk4bulbmcgZOG7ryBsaeG7h3UgYGdlcm1gIHbhu5tpIG3DtCBow6xuaCBCaW5vbWlhbCBHTE0gY8OzIHRy4buNbmcgc+G7kSAoYHdlaWdodHNgKSBbMzldLg0KDQoqICAgKipDaMawxqFuZyAxMDogTW9kZWxzIGZvciBDb3VudHM6IFBvaXNzb24gYW5kIE5lZ2F0aXZlIEJpbm9taWFsIEdMTXMqKiBbMzgsIDQwXS4gU+G7rSBk4bulbmcgY2hvIGThu68gbGnhu4d1IMSR4bq/bSBbNDAsIDQxXS4NCg0KICAgICogICAqKlBvaXNzb24gR0xNKio6IFRow61jaCBo4bujcCBjaG8gZOG7ryBsaeG7h3UgxJHhur9tIGtoaSBwaMawxqFuZyBzYWkgYuG6sW5nIHRydW5nIGLDrG5oIFs0MF0uIEPDsyB0aOG7gyBiYW8gZ+G7k20gbeG7mXQgYG9mZnNldGAgdHJvbmcgbcO0IGjDrG5oLCB2w60gZOG7pTpgb2Zmc2V0KGxvZyhQb3ApKWAgdHJvbmcgbcO0IGjDrG5oIFBvaXNzb24gYGxvZyDOvCA9IGxvZyBUICsgLi4uYCBuxqFpIGBsb2cgVGAgbMOgIG3hu5l0IG9mZnNldCBraMO0bmcgY+G6p24gxrDhu5tjIGzGsOG7o25nIHRoYW0gc+G7kSBbNDBdLiBWw60gZOG7pSBz4butIGThu6VuZyBk4buvIGxp4buHdSBgZGFuaXNobGNgIFs0MF0uDQogICAgDQogICAgKiAgICoqTmVnYXRpdmUgQmlub21pYWwgR0xNKio6IFRow61jaCBo4bujcCBjaG8gZOG7ryBsaeG7h3UgxJHhur9tIGtoaSBjw7MgaGnhu4duIHTGsOG7o25nIG92ZXJkaXNwZXJzaW9uIChwaMawxqFuZyBzYWkgbOG7m24gaMahbiB0cnVuZyBiw6xuaCkgWzQyXS4gQ8OzIHRo4buDIHNvIHPDoW5oIG3DtCBow6xuaCBRdWFzaS1wb2lzc29uIHbDoCBOZWdhdGl2ZSBCaW5vbWlhbCBraGkgY8OzIG92ZXJkaXNwZXJzaW9uIFs0Ml0uDQogICAgDQogICAgKiAgICoqUXVhc2ktcG9pc3NvbiBHTE0qKjogQ8WpbmcgxJHGsOG7o2Mgc+G7rSBk4bulbmcga2hpIGPDsyBvdmVyZGlzcGVyc2lvbiB0cm9uZyBk4buvIGxp4buHdSDEkeG6v20gWzQzXS4gYGFub3ZhKClgIHbhu5tpIGB0ZXN0PSJGImAgdGjGsOG7nW5nIMSRxrDhu6NjIHPhu60gZOG7pW5nIGNobyBtw7QgaMOsbmggUXVhc2ktcG9pc3NvbiBbNDNdLiBPdmVyZGlzcGVyc2lvbiBjw7MgdGjhu4MgxJHGsOG7o2MgeMOhYyBuaOG6rW4gbuG6v3UgxJHhu5kgbOG7h2NoIGTGsCAocmVzaWR1YWwgZGV2aWFuY2UpIGhv4bq3YyBQZWFyc29uIENoaS1zcXVhcmVkIGzhu5tuIGjGoW4gxJHDoW5nIGvhu4MgYuG6rWMgdOG7sSBkbyBkxrAgKHJlc2lkdWFsIGRlZ3JlZXMgb2YgZnJlZWRvbSkgWzQzXS4gVsOtIGThu6Ugc+G7rSBk4bulbmcgZOG7ryBsaeG7h3UgYGhjcmFic2AgWzQzXS4NCiAgICANCiAgICAqICAgKipLaeG7g20gxJHhu4tuaCDEkeG7mSBraOG7m3AgKEdvb2RuZXNzLW9mLWZpdCkqKjogQ8OzIHRo4buDIHPhu60gZOG7pW5nIGBwY2hpc3EoZGV2aWFuY2UobW9kZWwpLCBkZi5yZXNpZHVhbChtb2RlbCksIGxvd2VyLnRhaWw9RkFMU0UpYCDEkeG7gyBraeG7g20gxJHhu4tuaCBnaeG6oyB0aHV54bq/dCBy4bqxbmcgbcO0IGjDrG5oIGzDoCBwaMO5IGjhu6NwIFs0MV0uDQogICAgDQoqICAgKipDaMawxqFuZyAxMTogUG9zaXRpdmUgQ29udGludW91cyBEYXRhOiBHYW1tYSBhbmQgSW52ZXJzZSBHYXVzc2lhbiBHTE1zKiogWzM4LCA0NF0uIFPhu60gZOG7pW5nIGNobyBk4buvIGxp4buHdSBsacOqbiB04bulYyBkxrDGoW5nIFs0NF0uIFbDrSBk4bulIHPhu60gZOG7pW5nIGThu68gbGnhu4d1IGBsaW1lYCBjaG8gR2FtbWEgR0xNIFs0NCwgNDVdLg0KDQoqICAgKipDaMawxqFuZyAxMjogVHdlZWRpZSBHTE1zKiogWzQ2XS4gVHLDrG5oIGLDoHkgY8OhYyBNw7QgaMOsbmggUGjDom4gdMOhbiBIw6BtIG3FqSBUd2VlZGllIChUd2VlZGllIEVETXMpIHbDoCBjw6FjaCBmaXQgTcO0IGjDrG5oIFR1eeG6v24gdMOtbmggVOG7lW5nIHF1w6F0IFR3ZWVkaWUgKFR3ZWVkaWUgR0xNcykgWzM4LCA0NiwgNDddLiBCYW8gZ+G7k20gxrDhu5tjIGzGsOG7o25nIHRoYW0gc+G7kSBjaOG7iSBz4buRIM6+IFs0N10uIEPDsyB0aOG7gyBz4butIGThu6VuZyBow6BtIGB0d2VlZGllKClgIHbDoCBgdHdlZWRpZS5wcm9maWxlKClgIHRyb25nIFIgWzQ4XS4gYHN1bW1hcnkoKWAgY2hvIG3DtCBow6xuaCBUd2VlZGllIHPhur0gaGnhu4NuIHRo4buLIMaw4bubYyBsxrDhu6NuZywgc2FpIHPhu5EgY2h14bqpbiwgZ2nDoSB0cuG7iyB0IHbDoCBQLXZhbHVlLCBjw7luZyB24bubaSDGsOG7m2MgbMaw4bujbmcgdGhhbSBz4buRIHBow6JuIHTDoW4gWzQ5XS4NCg0KIyBTdXkgbHXhuq1uIGNobyBHTE0gKEluZmVyZW5jZSBmb3IgR0xNcykNCg0KKiAgICoqS2nhu4NtIMSR4buLbmggVOG7tyBz4buRIMSQ4buZIEzhu4djaCAoRGV2aWFuY2UgUmF0aW8gVGVzdCkqKiBoYXkgS2nhu4NtIMSR4buLbmggVOG7tyBz4buRIEto4bqjIE7Eg25nIChMaWtlbGlob29kIFJhdGlvIFRlc3QpIFs1MCwgNTFdLiDEkOG7kWkgduG7m2kgY8OhYyBwaMOibiBwaOG7kWkgY8OzIM+GID0gMSAodsOtIGThu6U6IFBvaXNzb24pLCBz4buxIGtow6FjIGJp4buHdCBnaeG7r2EgxJHhu5kgbOG7h2NoIGTGsCBj4bunYSBoYWkgbcO0IGjDrG5oIGzhu5NuZyBuaGF1IHRoZW8gcGjDom4gcGjhu5FpIGNoaS1zcXVhcmVkIFs1MCwgNTFdLiBDw7MgdGjhu4MgdMOtbmggdG/DoW4gc+G7sSBraMOhYyBiaeG7h3QgbsOgeSB2w6AgUC12YWx1ZSBi4bqxbmcgYGRldmlhbmNlKClgIHbDoCBgcGNoaXNxKClgIFs1MF0uIEzhu4duaCBgYW5vdmEobW9kZWwsIHRlc3Q9IkNoaXNxIilgIHRyb25nIFIgdGjhu7FjIGhp4buHbiBraeG7g20gxJHhu4tuaCBuw6B5IFs1MV0uDQoNCiogICAqKktp4buDbSDEkeG7i25oIFdhbGQgKFdhbGQgVGVzdCkqKjogU+G7rSBk4bulbmcgY2hvIGPDoWMgdGhhbSBz4buRIG3DtCBow6xuaCByacOqbmcgbOG6uyBob+G6t2MgY8OhYyBnaeG6oyB0aHV54bq/dCBj4bulIHRo4buDIFs1MiwgNTNdLiBSIGBzdW1tYXJ5KClgIGNobyBHTE0gdGjGsOG7nW5nIHRo4buxYyBoaeG7h24gei10ZXN0IChjb2kgcGjDom4gdMOhbiDEkcOjIGJp4bq/dCksIMSRaeG7gXUgbsOgeSBjw7MgdGjhu4MgcGjDs25nIMSR4bqhaSBuaOG6uSDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogWzUyXS4gQ8OzIHRo4buDIHTDrW5oIHRvw6FuIGtp4buDbSDEkeG7i25oIFdhbGQgdGjhu6cgY8O0bmcgWzUyXS4NCiogICAqKktp4buDbSDEkeG7i25oIFNjb3JlIChTY29yZSBUZXN0KSoqOiBN4buZdCBwaMawxqFuZyBwaMOhcCBraeG7g20gxJHhu4tuaCBraMOhYywgY8OzIHRo4buDIHRo4buxYyBoaeG7h24gdHJvbmcgUiBi4bqxbmcgaMOgbSBuaMawIGBnbG0uc2NvcmV0ZXN0YCB04burIGfDs2kgKipzdGF0bW9kKiogWzU0XS4NCg0KIyBQaOG7pSBs4bulYyBBOiBT4butIGThu6VuZyBSIGNobyBQaMOibiB0w61jaCBE4buvIGxp4buHdSAoVXNpbmcgUiBmb3IgRGF0YSBBbmFseXNpcykNClBo4bulIGzhu6VjIG7DoHkgZ2nhu5tpIHRoaeG7h3UgY8OhY2ggc+G7rSBk4bulbmcgUiBbNTVdLg0KDQoqICAgKipDaHXhuqluIGLhu4sgc+G7rSBk4bulbmcgUioqOiBDw6FjaCB04bqjaSB2w6AgY8OgaSDEkeG6t3QgUiB2w6AgY8OhYyBnw7NpIFIgY+G6p24gdGhp4bq/dCAodsOtIGThu6U6ICoqR0xNc0RhdGEqKikgWzQsIDU1LCA1Nl0uIEPDoWMgdHJhbmcgd2ViIFIgcXVhbiB0cuG7jW5nIGJhbyBn4buTbSBDUkFOIHbDoCBSLXByb2plY3Qub3JnIFs1Ni01OF0uDQoNCiogICAqKkdp4bubaSB0aGnhu4d1IGPGoSBi4bqjbiB24buBIHPhu60gZOG7pW5nIFIqKjogU+G7rSBk4bulbmcgUiBuaMawIG3hu5l0IG3DoXkgdMOtbmggbsOibmcgY2FvLCB0aG/DoXQgUiAoYHEoKWApLCBuaOG6rW4gdHLhu6MgZ2nDunAgKGBoZWxwKClgKSwgdMOqbiBiaeG6v24sIGzDoG0gdmnhu4djIHbhu5tpIHZlY3RvciwgbuG6oXAgZOG7ryBsaeG7h3UgdsOgbyBSIFs1NSwgNTldLiBDw7MgdGjhu4MgbuG6oXAgZOG7ryBsaeG7h3UgY8OzIHPhurVuIHRyb25nIFIgYuG6sW5nIGzhu4duaCBgZGF0YSgpYCBbNjBdLiBDw7MgdGjhu4MgbuG6oXAgZOG7ryBsaeG7h3UgdOG7qyBmaWxlIGLhurFuZyBgcmVhZC50YWJsZSgpYCBbNjFdLg0KDQoqICAgKipMw6BtIHZp4buHYyB24bubaSBkYXRhIGZyYW1lKio6IFbDrSBk4bulIGBsdW5nY2FwYCBsw6AgbeG7mXQgZGF0YSBmcmFtZSBbNF0uIEPDsyB0aOG7gyB0cnV5IGPhuq1wIGJp4bq/biB0cm9uZyBkYXRhIGZyYW1lIGLhurFuZyBgJGAsIHbDrSBk4bulIGBsdW5nY2FwJEFnZWAgWzEyLCA2MV0uIEPDsyB0aOG7gyBz4butIGThu6VuZyBgd2l0aCgpYCDEkeG7gyB0cnV5IGPhuq1wIGJp4bq/biBk4buFIGTDoG5nIGjGoW4sIG5oxrBuZyBgYXR0YWNoKClgL2BkZXRhY2goKWAga2jDtG5nIMSRxrDhu6NjIGtodXnhur9uIGtow61jaCBbNjFdLiBDw7MgdGjhu4MgeGVtIGPhuqV1IHRyw7pjIGRhdGEgZnJhbWUgYuG6sW5nIGBzdHIoKWAsIHTDs20gdOG6r3QgYuG6sW5nIGBzdW1tYXJ5KClgIFs0OF0uDQoNCiogICAqKlPhu60gZOG7pW5nIGjDoG0gdHJvbmcgUioqOiBSIGNo4bupYSBy4bqldCBuaGnhu4F1IGjDoG0gdsOgIGPDoWMgZ8OzaSBi4buVIHN1bmcgdGjDqm0gbmhp4buBdSBow6BtIGtow6FjIFs1OSwgNjFdLiBOaGnhu4F1IGjDoG0gxJHDoyDEkcaw4bujYyBz4butIGThu6VuZyB0cm9uZyBzw6FjaCBuaMawIGBnbG0oKWAsIGBsbSgpYCwgYGFub3ZhKClgLCBgc3VtbWFyeSgpYCwgYHBsb3QoKWAgWzEsIDIwLCA0OF0uDQoNCiogICAqKkPDoWMgaMOgbSB0aOG7kW5nIGvDqiBjxqEgYuG6o24gdHJvbmcgUioqOiBgbWVhbigpYCwgYHNkKClgLCBgdmFyKClgLCBgbWVkaWFuKClgLCBgSVFSKClgIFsxMiwgNTksIDYxXS4NCg0KKiAgICoqVuG6vSDEkeG7kyB0aOG7iyBjxqEgYuG6o24gdHJvbmcgUioqIFsxMiwgMTMsIDU5LCA2Mi02NF0uDQoNCiogICAqKlZp4bq/dCBow6BtIHRyb25nIFIqKjogSMaw4bubbmcgZOG6q24gY8OhY2ggdmnhur90IGjDoG0gdMO5eSBjaOG7iW5oLCBz4butIGThu6VuZyDEkeG7kWkgc+G7kSBt4bq3YyDEkeG7i25oLCBs4buHbmggYHNpZ25pZigpYCwgYHBhc3RlKClgLCBgcmV0dXJuKClgIFs1OSwgNjUsIDY2XS4NCg0KIyBQaOG7pSBs4bulYyBCOiBC4buZIGThu68gbGnhu4d1IChEYXRhIHNldHMpDQpMaeG7h3Qga8OqIGPDoWMgYuG7mSBk4buvIGxp4buHdSDEkcaw4bujYyBz4butIGThu6VuZyB0cm9uZyBzw6FjaCwgYmFvIGfhu5NtIGBsdW5nY2FwYCwgYGhjcmFic2AsIGBsaW1lYCwgYHBvY2tgLCBgZ29waGVyYCwgYHJhdGxpdmVyYCwgYGJsb2Nrc2AsIGBkYW5pc2hsY2AsIGBjZXJ2aWNhbGAsIGB0dXJiaW5lc2AsLi4uIFs2N10uDQoNCiMgQ2jhu4kgbeG7pWMgKEluZGV4KQ0KQmFvIGfhu5NtIGNo4buJIG3hu6VjIGPDoWMgYuG7mSBk4buvIGxp4buHdSB2w6AgY8OhYyBs4buHbmgvaMOgbSB0cm9uZyBSIMSRxrDhu6NjIHPhu60gZOG7pW5nIHRyb25nIHPDoWNoLCBjdW5nIGPhuqVwIHRoYW0gY2hp4bq/dSB0cmFuZyBbNDgsIDY4LCA2OV0uDQoNCiMgQ8OhYyBCw6BpIHRvw6FuIGLhu5Ugc3VuZyAoRXh0cmEgUHJvYmxlbXMpDQpDdW5nIGPhuqVwIGPDoWMgYsOgaSB0b8OhbiB0aOG7sWMgaMOgbmggYuG7lSBzdW5nIFs3MCwgNzFdLg0KDQojIFRo4buxYyBoaeG7h24gdGjhu5FuZyBrw6ogbcO0IHThuqMgY2hvIGPDoWMgYmnhur9uIHRyb25nIGZpbGU6IFN1cGVybWFya2V0IFRyYW5zYWN0aW9ucy5jc3YNCg0KYGBge3J9DQppZiAoIXJlcXVpcmUoInJlYWR4bCIpKSBpbnN0YWxsLnBhY2thZ2VzKCJyZWFkeGwiKQ0KaWYgKCFyZXF1aXJlKCJkcGx5ciIpKSBpbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpDQppZiAoIXJlcXVpcmUoInBzeWNoIikpIGluc3RhbGwucGFja2FnZXMoInBzeWNoIikNCiAgbGlicmFyeShyZWFkeGwpDQpkYXRhIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL05lcC9Eb3dubG9hZHMvU3VwZXJtYXJrZXQgVHJhbnNhY3Rpb25zLnhsc3giKQ0Kc3RyKGRhdGEpDQpoZWFkKGRhdGEpDQpudW1lcmljX3ZhcnMgPC0gZGF0YVssIHNhcHBseShkYXRhLCBpcy5udW1lcmljKV0NCnN1bW1hcnkobnVtZXJpY192YXJzKQ0KbGlicmFyeShwc3ljaCkNCmRlc2NyaWJlKG51bWVyaWNfdmFycykNCmNhdGVnb3JpY2FsX3ZhcnMgPC0gZGF0YVssIHNhcHBseShkYXRhLCBpcy5jaGFyYWN0ZXIpIHwgc2FwcGx5KGRhdGEsIGlzLmZhY3RvcildDQpsYXBwbHkoY2F0ZWdvcmljYWxfdmFycywgdGFibGUpDQpgYGANCg0K