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() và
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 X và X^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() và
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 μ và θ [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() và
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() và
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].
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