BÀI TẬP 1

TÓM TẮT CUỐN SÁCH: 2019_Generalized Linear Models With Examples in R_9781441901170.pdf

MỤC TIÊU: Tài liệu này tóm tắt các chủ đề chính và các ý tưởng quan trọng được trình bày trong các chương đầu tiên và các phần được trích dẫn của cuốn sách “Generalized Linear Models With Examples in R”, tập trung vào các khái niệm về mô hình thống kê, hồi quy tuyến tính và các mô hình tuyến tính tổng quát, cũng như các phương pháp chẩn đoán và ước lượng liên quan.

Các nội dung liên quan đến từng chương:

CHƯƠNG 1: MÔ HÌNH THỐNG KÊ (Statistical Models)

1.1. Giới thiệu

Chương này giới thiệu khái niệm cơ bản về mô hình thống kê như một cách để mô tả cả các đặc điểm ngẫu nhiên và có hệ thống của dữ liệu. Nó nhấn mạnh tầm quan trọng của việc sử dụng các mô hình để phân tích dữ liệu (“Data analysis: The need for models?” - Reese, 1986).

1.2. Cách biểu diễn dữ liệu

Dữ liệu được trình bày thông qua các ví dụ (như dữ liệu FEV – dung tích phổi):

  • Age: tuổi (số)

  • FEV: dung tích thở ra (lít)

  • Ht: chiều cao (cm)

  • Gender: giới tính (F/M)

  • Smoke: hút thuốc (0/1)

Biến số được chia thành:

  • Biến liên tục (quantitative) → covariates.

  • Biến phân loại (qualitative) → factors.

1.3. Biểu đồ và trực quan hóa

Plotting là bước đầu để hiểu dữ liệu, phát hiện xu hướng và mối quan hệ.

1.4. Mã hóa biến phân loại

Biến phân loại phải được mã hóa thành số để sử dụng trong mô hình thống kê.

Dùng biến giả (dummy variables):

  • Với biến có k mức → cần k−1 biến giả.

1.5. Mô hình thống kê gồm 2 thành phần

Hệ thống: mô tả mối quan hệ giữa kỳ vọng các biến giải thích:

\[ \mu_i = \mathbb{E}[y_i] = f(\beta_0 + \beta_1 x_{1i} + \cdots + \beta_p x_{pi}) \]

1.7. Diễn giải mô hình

Hệ số hồi quy \(\beta_j\): thay đổi trung bình của \(y\) khi \(x_j\) tăng 1 đơn vị (giữ các biến khác cố định).

1.8. All Models Are Wrong, but Some Are Useful

Một ý tưởng quan trọng được trích dẫn từ một nguồn khác (không được cung cấp đầy đủ trong trích đoạn) là các mô hình là sự đơn giản hóa thực tế và do đó không bao giờ hoàn toàn chính xác, nhưng chúng có thể là công cụ có giá trị để hiểu dữ liệu.

1.9. Mục đích của mô hình thống kê

Mục đích của một mô hình ảnh hưởng đến cách nó được phát triển. Các mục đích có thể bao gồm mô tả, dự đoán và hiểu mối quan hệ giữa các biến.

1.10. Độ chính xác so với sự đơn giản

Có sự đánh đổi giữa độ chính xác của một mô hình (khả năng phù hợp chặt chẽ với dữ liệu) và sự đơn giản của nó (số lượng tham số). Việc lựa chọn mô hình thường liên quan đến việc cân bằng hai yếu tố này.

1.11. Thực nghiệm so với nghiên cứu quan sát

Cuốn sách phân biệt giữa thực nghiệm (nơi có thể suy luận nguyên nhân - kết quả) và nghiên cứu quan sát (nơi chỉ có thể thiết lập mối liên hệ)

1.12. Thu thập dữ liệu và khả năng khái quát hóa

  • Kết quả mô hình chỉ áp dụng cho quần thể mà dữ liệu được thu thập từ đó.

  • Không nên ngoại suy kết quả ngoài phạm vi giá trị đã quan sát.


CHƯƠNG 2: MÔ HÌNH HỒI QUY TUYẾN TÍNH (Linear Regression Models)

2.1. Giới thiệu và tổng quan

Mô hình hồi quy tuyến tính là loại phổ biến nhất trong tất cả các mô hình hồi quy.

Đây là một trường hợp đặc biệt của mô hình tuyến tính tổng quát (GLM).

Chương này giới thiệu:

  • Khái niệm và ký hiệu của mô hình.

  • Ước lượng bình phương tối thiểu (OLS).

  • Hồi quy đơn và hồi quy bội.

  • Diễn giải hệ số hồi quy.

  • Suy luận thống kê.

  • Phân tích phương sai (ANOVA).

  • So sánh mô hình lồng và không lồng.

  • Chọn mô hình tốt nhất

2.2 Định nghĩa mô hình hồi quy tuyến tính

Định nghĩa: Mô hình hồi quy tuyến tính mô tả mối quan hệ giữa biến phản hồi \(y\) và các biến giải thích \(x_1, x_2, \ldots, x_p\) thông qua một biểu thức tuyến tính, cùng với một giả định về phân phối và phương sai của phần dư.

Biểu diễn mô hình:

\[ y_i = \beta_0 + \beta_1 x_{1i} + \beta_2 x_{2i} + \cdots + \beta_p x_{pi} + \varepsilon_i \]

Với giả định:

  • \(\varepsilon_i \sim \mathcal{N}(0, \sigma^2)\)

  • Các phần dư \(\varepsilon_i\) là độc lập và có phương sai không đổi.


Cấu trúc mô hình:

Mô hình gồm 2 thành phần:

1. Ngẫu nhiên (random component):

Phương sai của \(y_i\) được giả định là:

\[ \text{Var}[y_i] = \frac{\sigma^2}{w_i} \]

Trong đó:

  • \(\sigma^2\) là phương sai chưa biết.

  • \(w_i\) là trọng số (prior weight), thường là \(1\) với mọi \(i\) trong mô hình hồi quy thông thường.


2. Hệ thống (systematic component):

\[ \mu_i = \mathbb{E}[y_i] = \beta_0 + \sum_{j=1}^{p} \beta_j x_{ji} \]


Các loại mô hình hồi quy đặc biệt:

  • Simple Linear Regression: \(p = 1\), mô hình chỉ có một biến giải thích.

  • Ordinary Linear Regression: tất cả các trọng số \(w_i = 1\), tức là phương sai đồng nhất.

  • Multiple Linear Regression: \(p > 1\), có nhiều biến giải thích trong mô hình.

  • Normal Linear Regression: giả định phân phối chuẩn cho \(y_i\):

    \[ y_i \sim \mathcal{N}\left(\mu_i, \frac{\sigma^2}{w_i}\right) \]

2.3 Ước lượng bình phương tối thiểu (Least Squares Estimation)

Mục tiêu:

ìm các \(\hat{\beta}_j\) sao cho hàm mục tiêu là tổng bình phương phần dư có trọng số (RSS) được tối thiểu hóa:

\[ RSS = \sum_{i=1}^{n} w_i \left(y_i - \mu_i\right)^2 \]

Trong đó:

  • \(w_i\) là trọng số quan sát thứ \(i\)
  • \(y_i\) là giá trị thực tế
  • \(\mu_i = \mathbb{E}[y_i] = \beta_0 + \sum_{j=1}^{p} \beta_j x_{ji}\)

Trong hồi quy đơn (p = 1):

Ước lượng hệ số hồi quy được tính như sau:

\[ \hat{\beta}_1 = \frac{\sum (x_i - \bar{x})(y_i - \bar{y})}{\sum (x_i - \bar{x})^2} \]

\[ \hat{\beta}_0 = \bar{y} - \hat{\beta}_1 \bar{x} \]


2.4 Ước lượng trong hồi quy bội (nhiều biến)

Dạng ma trận của mô hình:

Mô hình hồi quy tuyến tính có thể được viết dưới dạng ma trận:

\[ y = X\beta + \varepsilon \]

Trong đó:

  • \(y\): vector phản hồi (cỡ \(n \times 1\))
  • \(X\): ma trận thiết kế (design matrix) kích thước \(n \times (p+1)\), với cột đầu tiên toàn số 1 (ứng với hệ số chặn \(\beta_0\)), các cột còn lại là giá trị của các biến giải thích \(x_j\)
  • \(\beta\): vector hệ số hồi quy (cỡ \((p+1) \times 1\))
  • \(\varepsilon \sim \mathcal{N}(0, \sigma^2 I)\): vector nhiễu có phân phối chuẩn đa biến với trung bình 0 và phương sai \(\sigma^2 I\)

Ước lượng OLS:

\[ \hat{\beta} = (X^T W X)^{-1} X^T W y \]

Phần dư và phương sai ước lượng:

Giá trị dự đoán (fitted values):

\[ \hat{\mu}_i = \hat{y}_i = \hat{\beta}_0 + \sum_{j=1}^{p} \hat{\beta}_j x_{ji} \]


Ước lượng phương sai phần dư:

\[ s^2 = \frac{RSS}{n - p'} \]

2.5 Sai số chuẩn và khoảng tin cậy

Sai số chuẩn của \(\hat{\beta}_j\):

\[ SE(\hat{\beta}_j) = \sqrt{s^{2} \cdot \bigl( X^{T} X \bigr)^{-1}_{jj}} \]

Khoảng tin cậy cho \(\hat{\beta}_j\):

\[ \hat{\beta}_j \pm t_{\alpha/2, \, n - p} \times SE(\hat{\beta}_j) \]

2.6 Sử dụng R để hồi quy

Mô hình hóa: model <- lm(y ~ x1 + x2, data = dataset)

Kết quả mô hình:

summary(model)

confint(model)

anova(model)

2.7 Diễn giải hệ số hồi quy

  • \(\beta_0\): giá trị trung bình của \(y\) khi tất cả các biến \(x_j = 0\).

  • \(\beta_j\): mức thay đổi kỳ vọng của \(y\) khi \(x_j\) tăng 1 đơn vị, giữ các biến khác không đổi.

2.8 Suy luận thống kê

Giả sử kiểm định với

\[ H_0: \beta_j = 0 \]

và thống kê kiểm định

\[ t = \frac{\hat{\beta}_j}{SE(\hat{\beta}_j)} \sim t_{n-p} \]

Trong đó:

  • \(\hat{\beta}_j\) là hệ số ước lượng của biến \(j\),

  • \(SE(\hat{\beta}_j)\) là sai số chuẩn của \(\hat{\beta}_j\),

  • \(t_{n-p}\) là phân phối t với \(n-p\) bậc tự do.

2.9 Phân tích phương sai (ANOVA)

Giá trị tổng phương sai \(TSS\) được tính theo công thức:

\[ TSS = \sum_{i=1}^{n} (y_i - \bar{y})^2 \]

Tổng phương sai được phân tích thành hai phần:

\[ TSS = SSR + RSS \]

Trong đó:

  • \(SSR\) là tổng bình phương phần giải thích (Explained Sum of Squares), được tính bằng:

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

  • \(RSS\) là tổng bình phương phần dư (Residual Sum of Squares), được tính bằng:

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

Hệ số xác định \(R^2\) được định nghĩa là:

\[ R^2 = \frac{SSR}{TSS} = 1 - \frac{RSS}{TSS} \]

2.10 So sánh mô hình lồng (Nested Models)

Định nghĩa: Hai mô hình được gọi là lồng nhau (nested models) khi mô hình đơn giản hơn (reduced model) là một trường hợp đặc biệt của mô hình phức tạp hơn (full model), tức là nó được tạo ra bằng cách loại bỏ một hay nhiều biến khỏi mô hình đầy đủ.

Kiểm định F:

\[ F = \frac{(RSS_{\text{reduced}} - RSS_{\text{full}}) / (p_{\text{full}} - p_{\text{reduced}})}{s^2_{\text{full}}} \]

Trong đó:

  • \(RSS_{\text{reduced}}\) là tổng bình phương phần dư của mô hình rút gọn,

  • \(RSS_{\text{full}}\) là tổng bình phương phần dư của mô hình đầy đủ,

  • \(p_{\text{full}}\)\(p_{\text{reduced}}\) lần lượt là số tham số của mô hình đầy đủ và mô hình rút gọn,

  • \(s^2_{\text{full}}\) là ước lượng phương sai phần dư của mô hình đầy đủ, được tính bằng:

\[ s^2_{\text{full}} = \frac{RSS_{\text{full}}}{n - p_{\text{full}}} \]

với \(n\) là số quan sát.

2.11 So sánh mô hình không lồng (Non-Nested Models)

Định nghĩa: Hai mô hình được gọi là không lồng (non-nested) nếu không có mô hình nào là một trường hợp đặc biệt (submodel) của mô hình còn lại.

AIC (Akaike Information Criterion) là chỉ số dùng để đánh giá độ phù hợp của mô hình, đồng thời phạt mức độ phức tạp của mô hình:

\[ AIC = -2 \cdot \ell(\hat{\theta}) + 2k \]

trong đó:

  • \(\ell(\hat{\theta})\) là log-likelihood tại ước lượng MLE \(\hat{\theta}\),

  • \(k\) là số tham số trong mô hình (bao gồm cả hệ số hằng số \(\beta_0\)).


BIC (Bayesian Information Criterion) tương tự AIC nhưng mức phạt độ phức tạp mạnh hơn, được tính bằng:

\[ BIC = -2 \cdot \ell(\hat{\theta}) + \log(n) \cdot k \]

trong đó:

  • \(n\) là kích thước mẫu,

  • \(k\)\(\ell(\hat{\theta})\) như trên.

Nguyên tắc chọn mô hình:

  • AIC/BIC càng nhỏ càng tốt.

  • Nếu AIC của mô hình A < mô hình B khoảng 2 điểm trở lên, mô hình A được ưu tiên hơn đáng kể.

2.12 Lựa chọn mô hình tự động (Automated Model Selection)

Định nghĩa:Lựa chọn mô hình là quá trình tìm ra tập hợp biến giải thích tốt nhất (phù hợp, đơn giản) để mô hình hóa biến phản hồi.

Có nhiều chiến lược lựa chọn mô hình:

  • Forward selection: bắt đầu từ mô hình rỗng, thêm biến từng bước.

  • Backward elimination: bắt đầu từ mô hình đầy đủ, loại bỏ từng biến.

  • Stepwise selection: kết hợp cả thêm và bớt biến ở mỗi bước.

Một số hàm sử dụng:

  • step(): chọn mô hình theo hướng forward/backward/stepwise.

  • drop1(), add1(): thêm hoặc bớt biến với kiểm định F.

  • extractAIC(): trả về AIC và số tham số.


CHƯƠNG 3: CHẨN ĐOÁN MÔ HÌNH HỒI QUY TUYẾN TÍNH (Linear Regression Models: Diagnostics and Model-Building)

3.1. Giới thiệu và tổng quan

Sau khi xây dựng một mô hình hồi quy tuyến tính, công việc không kết thúc ở việc ước lượng các hệ số hồi quy và kiểm định ý nghĩa thống kê. Một bước quan trọng không thể thiếu là chẩn đoán mô hình – tức là đánh giá xem mô hình đã được xây dựng có thực sự phù hợp với dữ liệu hay không.

Chẩn đoán mô hình hồi quy là một phần thiết yếu trong phân tích dữ liệu vì nó giúp ta:

  • Xác minh các giả định cơ bản của mô hình hồi quy tuyến tính có được thỏa mãn hay không (ví dụ như quan hệ tuyến tính, phương sai không đổi, phân phối chuẩn…).

  • Phát hiện những quan sát bất thường như điểm ngoại lai (outliers) hoặc điểm có ảnh hưởng lớn (influential observations) – những điểm có thể bóp méo kết quả ước lượng hoặc kiểm định.

  • Đánh giá độ tin cậy của các hệ số ước lượng.

Đề xuất cách cải thiện mô hình, ví dụ: biến đổi biến, thêm hoặc bớt biến giải thích, sử dụng mô hình phi tuyến hoặc tổng quát (GLM) thay thế.

Nếu bỏ qua bước này, người phân tích dễ rơi vào bẫy của việc “phù hợp quá mức” (overfitting), hiểu sai mối quan hệ giữa các biến, hoặc dự đoán sai lệch trong thực tế. Do đó, chẩn đoán mô hình không phải là tùy chọn – mà là một phần bắt buộc trong phân tích hồi quy nghiêm túc.

Trong chương này, chúng ta sẽ học cách:

  • Kiểm tra các giả định của mô hình hồi quy.

  • Sử dụng phần dư (residuals) để kiểm tra độ phù hợp.

  • Phát hiện và xử lý các điểm ảnh hưởng lớn.

  • Đo lường hiện tượng đa cộng tuyến và cách giảm thiểu.

3.2 Giả định trong mô hình hồi quy tuyến tính

Một mô hình hồi quy tuyến tính tiêu chuẩn đòi hỏi phải thỏa mãn 4 giả định cơ bản:

1. Giả định 1: Quan hệ tuyến tính

  • Mô hình giả định rằng trung bình của biến phản hồi \(y\) là hàm tuyến tính của các biến giải thích \(x_1, x_2, \ldots, x_p\).

  • Nếu quan hệ thật sự là phi tuyến mà ta vẫn dùng mô hình tuyến tính, kết quả ước lượng có thể bị thiên lệch và dự đoán sai.

\(\Rightarrow\) Cách kiểm tra: vẽ biểu đồ phần dư so với giá trị dự đoán, nếu thấy xu hướng cong (parabola, S-shape…) thì có thể là mô hình sai dạng.

2. Giả định 2: Phương sai không đổi (Homoscedasticity)

  • Phương sai của sai số \(\varepsilon_i\) là như nhau ở mọi mức giá trị của \(x\):

\[ \text{Var}(y_i) = \sigma^2 \]

  • Nếu phương sai thay đổi theo \(x\), ta có hiện tượng phương sai thay đổi (heteroscedasticity), dẫn đến ước lượng không hiệu quả và sai lệch trong kiểm định.

\(\Rightarrow\) Cách kiểm tra: vẽ đồ thị phần dư. Nếu phần dư có dạng hình nón (rộng dần hoặc hẹp lại) thì có thể bị heteroscedasticity.

3. Giả định 3: Độc lập

  • Các quan sát \((x_i, y_i)\) phải độc lập nhau.

  • Nếu dữ liệu có tính chuỗi thời gian, dữ liệu lồng ghép (nested data) hoặc phân nhóm (clustered), thì mô hình tuyến tính cơ bản không còn phù hợp.

\(\Rightarrow\) Cách kiểm tra: nếu dữ liệu theo thời gian, nên kiểm tra phần dư có xu hướng (autocorrelation) hay không.

4. Giả định 4: Phân phối chuẩn của sai số

  • Mặc dù không bắt buộc để ước lượng OLS, giả định này rất quan trọng để kiểm định giả thuyết và tính khoảng tin cậy: \[ \varepsilon_i \sim \mathcal{N}(0, \sigma^2) \]

\(\Rightarrow\) Cách kiểm tra: dùng biểu đồ Q-Q plot (quantile-quantile) để so sánh phần dư với phân phối chuẩn.

3.3 Các loại phần dư (Residuals)

Phần dư là công cụ trung tâm để chẩn đoán mô hình. Có nhiều cách tính phần dư:

1. Raw residual (Phần dư thô):

\[ e_i = y_i - \hat{y}_i \] Đơn giản là hiệu giữa giá trị thực tế và giá trị dự đoán.

2. Standardized residual (Phần dư chuẩn hóa):

\[ r_i = \frac{e_i}{\hat{\sigma} \sqrt{1 - h_{ii}}} \]

  • Giúp so sánh phần dư giữa các điểm có leverage khác nhau.

  • \(h_{ii}\): leverage – mức ảnh hưởng của điểm \(i\) lên dự đoán \(\hat{y}_i\).

3. Studentized residual:

\[ t_i = \frac{e_i}{\hat{\sigma}_{(i)} \sqrt{1 - h_{ii}}} \]

  • Giống standardized residual nhưng dùng \(\hat{\sigma}_{(i)}\) – phương sai ước lượng không dùng quan sát \(i\) \(\rightarrow\) chính xác hơn.

  • Dùng để phát hiện ngoại lai vì nó gần với phân phối t.

3.4 Biểu đồ phần dư (Residual Plots)

Một số biểu đồ quan trọng:

  • Residual vs Fitted Plot: kiểm tra tuyến tính và phương sai không đổi.

  • Normal Q-Q Plot: kiểm tra phân phối chuẩn của phần dư.

  • Scale-Location Plot: chuẩn hóa phần dư để dễ phát hiện heteroscedasticity.

  • Residuals vs Leverage Plot: xác định điểm ảnh hưởng lớn.

3.5 Ngoại lai (Outliers)

Định nghĩa: Là các điểm dữ liệu mà giá trị phản hồi \(y_i\) khác biệt lớn so với dự đoán từ mô hình, dù biến \(x_i\) không bất thường.

Dùng studentized residual để kiểm tra.

Quy tắc ngưỡng:

  • \(|t_i| > 2\): nghi ngờ.

  • \(|t_i| > 3\): có thể là ngoại lai đáng kể.

\(\Rightarrow\) Ngoại lai không nhất thiết có ảnh hưởng lớn, nhưng cần kiểm tra kỹ.

3.6 Điểm ảnh hưởng (Influential Points)

Định nghĩa: Là những điểm dữ liệu mà nếu bị loại bỏ, mô hình sẽ thay đổi đáng kể.

Các chỉ số phổ biến để đo ảnh hưởng:

1. Leverage (Hệ số đòn bẩy):

\[ h_{ii} = x_i^T (X^T X)^{-1} x_i \]

  • Đo khoảng cách của \(x_i\) đến trung tâm của các điểm \(x\).

  • Nếu \(h_{ii} > \frac{2p}{n}\): điểm có leverage cao.

2. Cook’s Distance (Khoảng cách Cook):

\[ D_i = \frac{p \hat{\sigma}^2 e_i^2}{(1 - h_{ii})^2 h_{ii}} \]

Kết hợp giữa độ lệch (residual) và leverage.

  • Nếu \(D_i > 0.5\): có thể có ảnh hưởng.

  • Nếu \(D_i > 1\): ảnh hưởng lớn cần xem xét kỹ.

3. DFBETAS:

\[ \text{DFBETAS}_{ij} = \frac{\hat{\beta}_j - \hat{\beta}_{j(i)}}{\text{SE}(\hat{\beta}_{j(i)})} \]

  • Mức thay đổi của hệ số \(\beta_j\) khi loại bỏ quan sát \(i\).

  • Dùng để kiểm tra ảnh hưởng của từng điểm lên từng hệ số cụ thể.

3.7 Đa cộng tuyến (Multicollinearity)

Định nghĩa: Xảy ra khi hai hay nhiều biến giải thích có tương quan cao, khiến cho ước lượng \(\beta_j\) không ổn định (nhỏ thay đổi dữ liệu \(\rightarrow\) lớn thay đổi hệ số).

Variance Inflation Factor (VIF):

\[ \mathrm{VIF}_j = \frac{1}{1 - R_j^2} \]

  • \(R_j^2\) : hệ số xác định khi hồi quy \(x_j\) lên tất cả các biến còn lại.

  • Nếu \(\mathrm{VIF}_j > 5\) hoặc \(> 10\): có vấn đề cần xử lý.

3.8 Sửa chữa mô hình sai

Khi mô hình vi phạm giả định:

  • Dùng biến đổi (log, sqrt, Box-Cox…).

  • Dùng mô hình phi tuyến hoặc mô hình GLM.

  • Loại bỏ hoặc thay thế điểm ảnh hưởng quá lớn.

  • Thêm biến bị thiếu hoặc loại bớt biến gây nhiễu.


CHƯƠNG 4: ƯỚC LƯỢNG HỢP LÝ TỐI ĐA (MAXIMUM LIKELIHOOD ESTIMATION – MLE)

4.1 Giới thiệu

Phương pháp bình phương tối thiểu (OLS) chỉ hoạt động hiệu quả khi dữ liệu thỏa mãn các giả định như phân phối chuẩn, phương sai không đổi, và biến phản hồi liên tục. Tuy nhiên, nhiều loại dữ liệu thực tế không tuân theo những điều kiện đó – ví dụ: dữ liệu nhị phân, đếm, hoặc dương liên tục. Khi đó, Maximum Likelihood Estimation (MLE) là phương pháp mạnh mẽ hơn, dùng để ước lượng các tham số trong mô hình tổng quát.

MLE là nền tảng cho mô hình tuyến tính tổng quát (GLM), vốn là trung tâm của phần còn lại trong sách.

4.2 Hàm hợp lý (Likelihood Function)

Định nghĩa: Hàm hợp lý là một hàm xác suất của toàn bộ dữ liệu đã quan sát, biểu diễn như một hàm của tham số \(\theta\).

Giả sử ta có một mẫu gồm \(n\) quan sát độc lập \(y_1, y_2, \ldots, y_n\), với mỗi \(y_i\) có phân phối xác suất \(f(y_i; \theta)\), thì:

Hàm hợp lý:

\[ L(\theta) = \prod_{i=1}^{n} f(y_i; \theta) \]

  • \(L(\theta)\): hàm hợp lý

  • \(\theta\): vector các tham số cần ước lượng

  • \(f(y_i; \theta)\): mật độ xác suất (hoặc khối xác suất) của \(y_i\)

Log-hợp lý (log-likelihood):

\[ \ell(\theta) = \log L(\theta) = \sum_{i=1}^{n} \log f(y_i; \theta) \]

  • Dễ đạo hàm hơn vì tích thành tổng.

  • Giá trị cực đại của \(\ell(\theta)\) trùng với \(L(\theta)\).

4.3 Ước lượng hợp lý tối đa (Maximum Likelihood Estimation – MLE)

Định nghĩa: MLE là giá trị \(\hat{\theta}\) của tham số \(\theta\) sao cho log-likelihood đạt cực đại.

\[ \hat{\theta} = \arg\max_{\theta} \, \ell(\theta) \] Để tìm \(\hat{\theta}\), ta giải:

\[ \frac{d\ell(\theta)}{d\theta} = 0 \]

\(\Rightarrow\) Đây gọi là phương trình điểm (score equation).

4.4 Ma trận thông tin Fisher và phương sai

1. Hàm điểm (Score Function):

\[ U(\theta) = \frac{d\ell(\theta)}{d\theta} \]

  • \(U(\theta)\): độ dốc của log-likelihood theo \(\theta\)

2. Ma trận thông tin Fisher:

\[ I(\theta) = -\mathbb{E} \left[ \frac{d^2 \ell(\theta)}{d\theta^2} \right] \]

  • \(I(\theta)\): kỳ vọng âm của đạo hàm bậc hai log-likelihood → đo độ cong.

  • Là xấp xỉ ngược lại của phương sai: \[ \mathrm{Var}(\hat{\theta}) \approx \frac{1}{I(\theta)} \]

4.5 Các tính chất của MLE

MLE có nhiều tính chất tốt về mặt lý thuyết, đặc biệt khi kích thước mẫu n lớn:

Tính chất Giải thích
Nhất quán \(\hat{\theta} \to \theta\) khi \(n \to \infty\)
Không chệch tiệm cận Độ lệch giữa \(\hat{\theta}\)\(\theta\) tiến về 0
Hiệu quả MLE đạt giới hạn Cramér–Rao, là ước lượng “tốt nhất”
Tiệm cận chuẩn Khi \(n\) lớn, phân phối của \(\hat{\theta}\) gần chuẩn: \(\hat{\theta} \sim \mathcal{N}(\theta, I(\theta)^{-1})\)

4.6 Kiểm định giả thuyết với MLE

Muốn kiểm tra giả thuyết:

\[ H_0: \theta = \theta_0 \]

ta có ba cách phổ biến:

1. Wald Test:

\[ Z = \frac{\hat{\theta} - \theta_0}{SE(\hat{\theta})}, \quad Z \sim N(0,1) \]

  • Dùng để kiểm định nếu \(SE(\hat{\theta})\) đã có.

2. Likelihood Ratio Test (LRT):

\[ LR = 2 \left[ \ell(\hat{\theta}) - \ell(\theta_0) \right] \sim \chi^2_{df} \]

  • So sánh log-likelihood của mô hình đầy đủ và mô hình rút gọn.

  • \(df\): số tham số bị ràng buộc trong \(H_0\).


3. Score Test (Lagrange Multiplier Test):

\[ S = \frac{U(\theta_0)^2}{I(\theta_0)} \sim \chi^2_1 \]

Không cần ước lượng mô hình đầy đủ.

4.7 So sánh mô hình bằng AIC và BIC

Khi không thể dùng kiểm định LRT (do mô hình không lồng), ta dùng:

1. AIC – Akaike Information Criterion:

\[ \text{AIC} = -2\ell + 2k \]

  • \(k\): số tham số trong mô hình

  • \(\ell\): log-likelihood tại MLE


2. BIC – Bayesian Information Criterion:

\[ \text{BIC} = -2\ell + \log(n) \cdot k \]

  • \(n\): số quan sát

→ Chọn mô hình có AIC/BIC thấp hơn.

4.8 MLE trong mô hình không tuyến tính chuẩn

Hồi quy logistic (nhị phân):

\[ y_i \sim \text{Bernoulli}(\pi_i), \quad \log\left(\frac{\pi_i}{1 - \pi_i}\right) = x_i^T \beta \]


Hồi quy Poisson (đếm):

\[ y_i \sim \text{Poisson}(\mu_i), \quad \log(\mu_i) = x_i^T \beta \]


Hồi quy Gamma (dương liên tục):

\[ y_i \sim \text{Gamma}(\alpha, \mu_i), \quad \log(\mu_i) = x_i^T \beta \]


→ Cả ba đều dùng MLE để ước lượng \(\beta\), chứ không dùng OLS.

CHƯƠNG 5: CẤU TRÚC CỦA MÔ HÌNH TUYẾN TÍNH TỔNG QUÁT (GLM STRUCTURE)

5.1 Giới thiệu

Mô hình tuyến tính tổng quát (GLM) là một khuôn khổ mạnh mẽ cho việc mô hình hóa các loại dữ liệu khác nhau – không chỉ dữ liệu liên tục có phân phối chuẩn như trong hồi quy tuyến tính. GLM bao gồm hồi quy logistic, hồi quy Poisson, hồi quy Gamma… và mở rộng khả năng phân tích đến dữ liệu nhị phân, đếm, tỷ lệ và dương liên tục.

Mỗi GLM được xây dựng trên cùng một nguyên lý chung gồm ba thành phần chính: phân phối xác suất, hàm liên kết, và thành phần tuyến tính.

5.2 Cấu trúc 3 phần của GLM

1. Thành phần ngẫu nhiên (Random component)

Biến phản hồi \(y_i\) được giả định phân phối theo một phân phối thuộc họ hàm mũ một tham số (One-Parameter Exponential Family):

\[ f(y_i; \theta_i, \phi) = \exp \left\{ \frac{y_i \theta_i - b(\theta_i)}{\phi} + c(y_i, \phi) \right\} \]

Ý nghĩa các ký hiệu:

  • \(\theta_i\): tham số tự nhiên (natural parameter)
  • \(\phi\): tham số phân tán (dispersion parameter), không phải lúc nào cũng có (ví dụ Poisson thì \(\phi = 1\))
  • \(b(\theta_i)\): hàm log partition
  • \(c(y_i, \phi)\): hàm chuẩn hóa để bảo toàn tích phân bằng 1

→ Họ hàm mũ bao gồm Normal, Poisson, Binomial, Gamma,…


2. Thành phần hệ thống (Systematic component)

Giống như hồi quy tuyến tính, GLM vẫn dùng một predictor tuyến tính:

\[ \eta_i = x_i^T \beta = \beta_0 + \beta_1 x_{i1} + \cdots + \beta_p x_{ip} \]

Ý nghĩa:

  • \(\eta_i\): predictor tuyến tính
  • \(x_i\): vector hàng gồm các biến giải thích của quan sát \(i\)
  • \(\beta\): vector hệ số hồi quy

Đây là thành phần chứa ảnh hưởng của các biến độc lập lên mô hình.


3. Hàm liên kết (Link function)

GLM dùng một hàm liên kết \(g(\cdot)\) để kết nối trung bình \(\mu_i = E[y_i]\) với predictor tuyến tính \(\eta_i\):

\[ g(\mu_i) = \eta_i \quad \text{hay} \quad \mu_i = g^{-1}(\eta_i) \]

→ Cho phép mô hình hóa các biến phản hồi có đặc tính phi tuyến, không âm, giới hạn trong khoảng (0,1),…

Hàm liên kết thường dùng:

Phân phối \(\mu_i = E[y_i]\) Link function \(g(\mu)\) Ghi chú
Normal \(\mu \in \mathbb{R}\) \(g(\mu) = \mu\) (identity) Hồi quy tuyến tính chuẩn
Binomial \(\mu \in (0,1)\) \(g(\mu) = \log \frac{\mu}{1-\mu}\) Logistic regression
Poisson \(\mu > 0\) \(g(\mu) = \log(\mu)\) Hồi quy đếm
Gamma \(\mu > 0\) \(g(\mu) = \log(\mu)\) hoặc \(g(\mu) = \frac{1}{\mu}\) Mô hình dữ liệu dương

5.3 Ví dụ mô hình hóa trong GLM

1. Hồi quy Logistic (nhị phân)

\[ y_i \sim \text{Bernoulli}(\pi_i) \]

\[ g(\pi_i) = \log \left(\frac{\pi_i}{1-\pi_i}\right) = \eta_i \]

\[ \pi_i = P(y_i = 1 \mid x_i) \]

  • Dùng cho dữ liệu như: sống/chết, mua/không mua, đúng/sai…

2. Hồi quy Poisson (đếm)

\[ y_i \sim \text{Poisson}(\mu_i) \]

\[ \log(\mu_i) = x_i^T \beta \]

  • \(\mu_i\): số sự kiện kỳ vọng xảy ra.

  • Dùng cho dữ liệu: số ca bệnh, số lần vi phạm, số giao dịch…


3. Hồi quy Gamma (dương liên tục)

\[ y_i \sim \text{Gamma}(\alpha, \mu_i) \]

Hàm liên kết:

\[ g(\mu_i) = \log(\mu_i) \quad \text{hoặc} \quad g(\mu_i) = \frac{1}{\mu_i} \]

  • Dùng cho dữ liệu chi phí, độ dài, thời gian

5.4 Hàm phương sai (Variance Function)

Trong GLM, phương sai của \(y_i\) không cần bằng nhau mà được mô hình hóa như hàm của \(\mu_i\):

\[ \text{Var}(y_i) = \phi \cdot V(\mu_i) \]

Trong đó:

  • \(\phi\): tham số phân tán (dispersion parameter)
  • \(V(\mu)\): hàm phương sai phụ thuộc vào trung bình \(\mu\)

Hàm \(V(\mu)\) tùy theo phân phối như sau:

Phân phối \(V(\mu)\)
Normal 1
Binomial \(\mu (1 - \mu)\)
Poisson \(\mu\)
Gamma \(\mu^2\)

Việc mô hình hóa phương sai như trên giúp xử lý được hiện tượng phương sai thay đổi (heteroscedasticity), vốn là một giả định bị vi phạm trong phương pháp OLS (Hồi quy tuyến tính thông thường).

5.5 Các khái niệm mở rộng

Canonical Link Function là hàm liên kết sao cho predictor tuyến tính chính là tham số tự nhiên \(\theta\) trong phân phối họ hàm mũ:

\[ \theta_i = \eta_i = x_i^T \beta \]

Ví dụ về hàm liên kết chuẩn (canonical link):

Phân phối Hàm liên kết (Link function)
Binomial logit: \(\log\frac{\mu}{1-\mu}\)
Poisson log: \(\log(\mu)\)
Normal identity: \(\mu\)

Lưu ý: Dù GLM gọi là “tuyến tính”, nhưng mối quan hệ giữa \(y\)\(x\) có thể phi tuyến do sử dụng hàm liên kết (link function).

CHƯƠNG 6: ƯỚC LƯỢNG TRONG MÔ HÌNH TUYẾN TÍNH TỔNG QUÁT (GLMs)

6.1 Giới thiệu

Sau khi xác định được cấu trúc của một GLM (gồm phân phối xác suất, hàm liên kết và thành phần tuyến tính), bước tiếp theo là ước lượng các hệ số hồi quy \(\beta\) trong mô hình.

Khác với hồi quy tuyến tính cổ điển – nơi ta dùng phương pháp bình phương tối thiểu (OLS) – trong GLM, các hệ số được ước lượng bằng phương pháp hợp lý tối đa (Maximum Likelihood Estimation - MLE) thông qua một thuật toán gọi là Iteratively Reweighted Least Squares (IRLS).

Phương pháp IRLS thực hiện việc cập nhật các ước lượng \(\beta\) lặp đi lặp lại, mỗi lần dựa trên trọng số được điều chỉnh sao cho phù hợp với phân phối của dữ liệu và hàm liên kết được chọn.

6.2 Tổng quan về ước lượng hợp lý tối đa (MLE) trong GLM

Cho dữ liệu gồm:

  • Biến phản hồi: \(y_1, y_2, \ldots, y_n\) có thể là biến đếm, nhị phân hoặc liên tục dương…

  • Biến giải thích: \(x_{i1}, \ldots, x_{ip}\) với \(i=1, \ldots, n\).

Mô hình GLM được biểu diễn như sau:

\[ g(\mu_i) = \eta_i = \mathbf{x}_i^T \boldsymbol{\beta} \]

với

\[ \mu_i = E[y_i] = g^{-1}(\mathbf{x}_i^T \boldsymbol{\beta}) \]

Mục tiêu là tìm ước lượng \(\hat{\boldsymbol{\beta}}\) sao cho hàm log-likelihood đạt cực đại:

\[ \ell(\boldsymbol{\beta}) = \sum_{i=1}^n \log f(y_i; \theta_i) \]

trong đó:

  • \(f(y_i; \theta_i)\) là hàm mật độ xác suất (hoặc hàm khối xác suất) của biến \(y_i\),

  • \(\theta_i\) là tham số tự nhiên trong phân phối thuộc họ hàm mũ,

  • \(\theta_i\) có quan hệ với \(\mu_i\), từ đó liên hệ với \(\boldsymbol{\beta}\).

Việc ước lượng này thường được thực hiện bằng phương pháp hợp lý tối đa (MLE), sử dụng thuật toán Iteratively Reweighted Least Squares (IRLS).

6.3 Phương pháp IRLS (Iteratively Reweighted Least Squares)

1. Thuật toán IRLS (Iteratively Reweighted Least Squares):

GLM sử dụng thuật toán IRLS để tìm ước lượng \(\hat{\boldsymbol{\beta}}\). Thuật toán dựa trên việc lặp lại các bước hồi quy tuyến tính có trọng số.

2. Ý tưởng cơ bản:

  • Ở mỗi vòng lặp, mô hình GLM được xấp xỉ bằng một hồi quy tuyến tính với trọng số.

  • Biến giả (working response) \(\mathbf{z}\)ma trận trọng số \(\mathbf{W}\) được cập nhật liên tục ở mỗi bước.

3. Hệ phương trình IRLS:

\[ \mathbf{X}^T \mathbf{W} \mathbf{X} \hat{\boldsymbol{\beta}} = \mathbf{X}^T \mathbf{W} \mathbf{z} \]

Trong đó:

  • \(\mathbf{X}\) là ma trận thiết kế,

  • \(\mathbf{W}\) là ma trận trọng số kích thước \(n \times n\),

  • \(\mathbf{z}\) là vector biến giả \(n \times 1\), tính theo công thức:

\[ z_i = \eta_i + \frac{y_i - \mu_i}{\frac{d \mu_i}{d \eta_i}} \]

  • Trọng số \(W_i\) được tính theo:

\[ W_i = \left(\frac{d \mu_i}{d \eta_i}\right)^2 \Big/ \mathrm{Var}(y_i) \]

Quá trình này được lặp lại cho đến khi các ước lượng \(\boldsymbol{\beta}\) hội tụ.

6.4 Hàm điểm, ma trận Fisher và phương sai của ước lượng

Hàm điểm (Score Function)

Hàm điểm là đạo hàm của log-likelihood theo vector hệ số \(\boldsymbol{\beta}\):

\[ U(\boldsymbol{\beta}) = \frac{\partial \ell(\boldsymbol{\beta})}{\partial \boldsymbol{\beta}} \]

Đây là hệ phương trình mà khi giải \(U(\boldsymbol{\beta}) = 0\), ta thu được ước lượng cực đại \(\hat{\boldsymbol{\beta}}\).


Ma trận thông tin Fisher

Ma trận thông tin Fisher là kỳ vọng âm của đạo hàm bậc hai của log-likelihood:

\[ \mathcal{I}(\boldsymbol{\beta}) = - \mathbb{E} \left[ \frac{\partial^2 \ell(\boldsymbol{\beta})}{\partial \boldsymbol{\beta} \, \partial \boldsymbol{\beta}^T} \right] \]

Ma trận này đóng vai trò như một thước đo độ “sắc nét” của log-likelihood tại điểm cực đại và được dùng để đánh giá độ chính xác của ước lượng.


Phương sai của \(\hat{\boldsymbol{\beta}}\)

Khi đã có ma trận thông tin Fisher, phương sai hiệp phương sai của vector hệ số ước lượng được tính là:

\[ \mathrm{Var}(\hat{\boldsymbol{\beta}}) = \mathcal{I}(\hat{\boldsymbol{\beta}})^{-1} \]

Nếu sử dụng thuật toán IRLS, ma trận thông tin Fisher được xấp xỉ bởi:

\[ \mathrm{Var}(\hat{\boldsymbol{\beta}}) = (\mathbf{X}^T \mathbf{W} \mathbf{X})^{-1} \]

Trong đó:

  • \(\mathbf{X}\): ma trận thiết kế,

  • \(\mathbf{W}\): ma trận trọng số tại nghiệm hội tụ,

  • Công thức này xuất hiện tự nhiên từ bước giải hệ phương trình IRLS.


Ghi chú

  • Công thức phương sai trên rất quan trọng để tính khoảng tin cậy và kiểm định giả thuyết trong GLM.

  • Với các mô hình lớn, ma trận \((\mathbf{X}^T \mathbf{W} \mathbf{X})^{-1}\) thường được tính thông qua giải hệ phương trình thay vì đảo trực tiếp để tránh sai số số học.

6.5 Sai số chuẩn và khoảng tin cậy

Sai số chuẩn (Standard Error)

Sau khi có được ước lượng \(\hat{\boldsymbol{\beta}}\) và ma trận phương sai hiệp phương sai \(\mathrm{Var}(\hat{\boldsymbol{\beta}})\), ta tính sai số chuẩn cho từng hệ số \(\hat{\beta}_j\) như sau:

\[ \mathrm{SE}(\hat{\beta}_j) = \sqrt{[\mathrm{Var}(\hat{\boldsymbol{\beta}})]_{jj}} \]

Trong đó, \([\cdot]_{jj}\) là phần tử hàng \(j\), cột \(j\) trong ma trận phương sai.


Khoảng tin cậy \(100(1 - \alpha)\%\)

Khoảng tin cậy cho hệ số \(\hat{\beta}_j\) được tính bằng công thức:

\[ \hat{\beta}_j \pm z_{\alpha/2} \cdot \mathrm{SE}(\hat{\beta}_j) \]

Trong đó:

  • \(z_{\alpha/2}\) là bách phân vị \(1 - \alpha/2\) của phân phối chuẩn chuẩn hóa (thường tra từ bảng Z),

  • Ví dụ: với \(\alpha = 0.05\), \(z_{0.025} \approx 1.96\) (tương ứng khoảng tin cậy 95%).


Kiểm định Wald

Kiểm định Wald giúp đánh giá giả thuyết:

\[ H_0: \beta_j = 0 \quad \text{vs} \quad H_1: \beta_j \neq 0 \]

Thống kê kiểm định:

\[ Z = \frac{\hat{\beta}_j}{\mathrm{SE}(\hat{\beta}_j)} \sim \mathcal{N}(0, 1) \]

Dựa vào giá trị \(Z\), ta có thể tính p-value và đưa ra kết luận thống kê.


Ghi chú

  • Kiểm định Wald được dùng phổ biến do tính đơn giản và có thể thực hiện ngay sau khi có ước lượng và phương sai.

  • Nếu \(|Z| > z_{\alpha/2}\), bác bỏ \(H_0\), tức là hệ số \(\beta_j\) có ý nghĩa thống kê.

6.6 Ước lượng tham số phân tán

Trong một số mô hình GLM, đặc biệt là khi phân phối thuộc họ phân phối mũ (exponential family) không chuẩn hóa, ta cần ước lượng tham số phân tán \(\phi\).

Công thức ước lượng:

\[ \hat{\phi} = \frac{1}{n - p} \sum_{i=1}^{n} \frac{(y_i - \hat{\mu}_i)^2}{V(\hat{\mu}_i)} \]

Trong đó:

  • \(n\): số quan sát

  • \(p\): số tham số trong mô hình (bao gồm hệ số chặn nếu có)

  • \(\hat{\mu}_i = \mathbb{E}[y_i] = g^{-1}(\eta_i)\): giá trị kỳ vọng được ước lượng

  • \(V(\hat{\mu}_i)\): hàm phương sai, phụ thuộc vào phân phối:

Phân phối Hàm phương sai \(V(\mu)\)
Gaussian \(1\)
Poisson \(\mu\)
Binomial (logit) \(\mu(1 - \mu)\)

CHƯƠNG 7: ĐÁNH GIÁ MỨC ĐỘ PHÙ HỢP VÀ LỰA CHỌN MÔ HÌNH TRONG GLM

7.1 Giới thiệu

Sau khi ước lượng các tham số \(\beta\) trong GLM, bước tiếp theo là đánh giá xem mô hình có phù hợp với dữ liệu không, và nếu có nhiều mô hình cạnh tranh, thì nên chọn mô hình nào là tốt nhất.

Các công cụ đánh giá bao gồm:

  • Deviance (độ lệch)

  • Kiểm định \(\chi^2\)

  • AIC, BIC

  • So sánh mô hình lồng và không lồng

  • Đồ thị phần dư và điểm ảnh hưởng

7.2 Deviance – đo lường mức độ phù hợp của mô hình

Định nghĩa:

Deviance là đại lượng đo sự khác biệt giữa mô hình hiện tại và mô hình đầy đủ (saturated model) – tức mô hình khớp hoàn toàn với dữ liệu.

\[ D(y; \hat{\mu}) = 2 \left[ \ell(y; y) - \ell(\hat{\mu}; y) \right] \]

Giải thích ký hiệu:

  • \(\ell(y; y)\): log-likelihood của mô hình bão hòa (saturated model)

  • \(\ell(\hat{\mu}; y)\): log-likelihood của mô hình đang xét

\(\Rightarrow\) Deviance càng nhỏ → mô hình càng gần với mô hình bão hòa → phù hợp hơn.

7.3 So sánh mô hình bằng kiểm định deviance

Khi hai mô hình lồng nhau, ta có thể so sánh bằng kiểm định sai biệt deviance:

Công thức kiểm định:

\[ \Delta D = D_{\text{reduced}} - D_{\text{full}} \sim \chi^2_{df} \]

Trong đó:

  • \(df\): số tham số bị ràng buộc trong mô hình nhỏ hơn

\(\Rightarrow\) Nếu \(\Delta D\) lớn và p-value nhỏ → mô hình đầy đủ tốt hơn.

7.4 AIC và BIC – lựa chọn giữa các mô hình không lồng

Khi các mô hình không lồng nhau, ta dùng tiêu chí thông tin để so sánh:

AIC (Akaike Information Criterion):

\[ AIC = -2\ell + 2k \]

  • \(\ell\): log-likelihood

  • \(k\): số tham số trong mô hình

BIC (Bayesian Information Criterion):

\[ BIC = -2\ell + \log(n) \cdot k \]

  • \(n\): số quan sát

\(\Rightarrow\) Chọn mô hình có AIC/BIC thấp hơn.

\(\Rightarrow\) BIC phạt các mô hình phức tạp nhiều hơn so với AIC.


7.5 Đồ thị chẩn đoán và phần dư

Phần dư (residuals):

  • Phần dư thô (raw residual):

\[ e_i = y_i - \hat{\mu}_i \]

  • Phần dư Pearson:

\[ r_i = \frac{y_i - \hat{\mu}_i}{\sqrt{V(\hat{\mu}_i)}} \]

  • Phần dư deviance:

\[ d_i = \text{sign}(y_i - \hat{\mu}_i) \cdot \sqrt{2\left[\ell(y_i; y_i) - \ell(\hat{\mu}_i; y_i)\right]} \]

Biểu đồ kiểm tra mô hình (Diagnostic plots):

  • Residuals vs Fitted

  • Normal Q-Q (nếu mô hình gần phân phối chuẩn)

  • Scale-Location plot

  • Cook’s distance vs Leverage

Các biểu đồ này giúp phát hiện điểm ngoại laiđiểm ảnh hưởng mạnh đến mô hình.


7.6 Kiểm định Pearson Chi-square

Phép kiểm định Pearson đo sự khác biệt giữa dữ liệu quan sát và giá trị kỳ vọng từ mô hình:

\[ X^2 = \sum_{i=1}^n \frac{(y_i - \hat{\mu}_i)^2}{V(\hat{\mu}_i)} \]

Nếu \(X^2\) lớn hơn mức kỳ vọng theo phân phối \(\chi^2_{df}\) → mô hình có thể không phù hợp với dữ liệu.

7.7 Độ phân tán và vấn đề overdispersion

Một số mô hình GLM như Poisson hoặc Binomial giả định hệ số phân tán là:

\[ \phi = 1 \]

Tuy nhiên, trong thực tế, nếu phương sai quan sát lớn hơn phương sai lý thuyết, ta gọi là overdispersion (quá phân tán).

Kiểm tra overdispersion:

Hệ số phân tán ước lượng được tính theo công thức:

\[ \hat{\phi} = \frac{\text{Deviance}}{n - p} \]

  • \(n\): số quan sát

  • \(p\): số tham số trong mô hình

\(\Rightarrow\) Nếu:

\[ \hat{\phi} > 1.5 \]

→ Mô hình có thể bị overdispersed (quá phân tán)

\(\Rightarrow\) Trong trường hợp này, cần điều chỉnh mô hình, ví dụ:

  • Sử dụng quasi-Poisson

  • Hoặc Negative Binomial

CHƯƠNG 8: HỒI QUY LOGISTIC (LOGISTIC REGRESSION)

8.1 Giới thiệu

Hồi quy logistic là một trong những mô hình phổ biến nhất thuộc họ GLM, được dùng để mô hình hóa dữ liệu nhị phân (binary), tức khi biến phản hồi

\[ y \in \{0,1\} \]

Ví dụ: bệnh/không bệnh, mua/không mua, đạt/không đạt.

Đặc điểm:
\[ \mu_i = E[y_i] = P(y_i=1) \in (0,1) \]

Sử dụng hàm liên kết logit:
\[ g(\mu_i) = \log\left(\frac{\mu_i}{1-\mu_i}\right) = \eta_i = x_i^T \beta \]


8.2 Phân phối Bernoulli và hàm log-likelihood

Biến phản hồi

\[ y_i \in \{0,1\} \]
phân phối theo:

\[ y_i \sim \text{Bernoulli}(\pi_i) \]

Trong đó:

\[ \pi_i = P(y_i=1) \]
và:
\[ \log\left(\frac{\pi_i}{1-\pi_i}\right) = x_i^T \beta \]

Log-likelihood cho toàn bộ mẫu:
\[ \ell(\beta) = \sum_{i=1}^n \left[ y_i \log(\pi_i) + (1 - y_i) \log(1-\pi_i) \right] \]

Không có nghiệm giải tường minh → dùng IRLS để tìm \(\hat{\beta}\).


8.3 Diễn giải hệ số hồi quy trong logistic regression

Khi dùng logit link:
\[ \eta_i = \log\left(\frac{\pi_i}{1-\pi_i}\right) = x_i^T \beta \]

\(\beta_j\) đại diện cho log odds ratio:
\[ \text{Odds ratio} = \exp(\beta_j) \]

  • Nếu \(\beta_j > 0\): biến \(x_j\) làm tăng khả năng \(y=1\)

  • Nếu \(\beta_j < 0\): biến \(x_j\) làm giảm khả năng \(y=1\)


8.4 Khoảng tin cậy và kiểm định

Sau khi ước lượng \(\hat{\beta}\), ta kiểm định từng hệ số:

Kiểm định Wald:
\[ Z_j = \frac{\hat{\beta}_j}{SE(\hat{\beta}_j)} \sim N(0,1) \]

Khoảng tin cậy 95%:
\[ \hat{\beta}_j \pm z_{0.975} \cdot SE(\hat{\beta}_j) \]

Chuyển sang odds ratio bằng
\[ \exp(\hat{\beta}_j) \]


8.5 Đánh giá mô hình

Deviance:
\[ D = -2 \left[ \ell(\hat{\beta}) - \ell_{\text{saturated}} \right] \]

Kiểm định deviance giữa mô hình đầy đủ và mô hình rút gọn.

Pseudo-\(R^2\):
\[ R^2 = 1 - \frac{D_{\text{model}}}{D_{\text{null}}} \]


8.6 Mô hình hóa với nhiều biến (multiple predictors)

Có thể mở rộng logistic regression để bao gồm nhiều biến giải thích:

\[ \log\left(\frac{\pi_i}{1-\pi_i}\right) = \beta_0 + \beta_1 x_{i1} + \cdots + \beta_p x_{ip} \]

→ Mô hình đa biến logistic.


8.7 Mô hình hóa tỷ lệ (Grouped binomial model)

Khi dữ liệu không phải từng quan sát riêng lẻ, mà là tổng hợp
\[ \frac{y_i}{n_i} \]
ta dùng:
\[ y_i \sim \text{Binomial}(n_i, \pi_i) \]

Log-likelihood:
\[ \ell(\beta) = \sum_{i=1}^n \left[ y_i \log(\pi_i) + (n_i - y_i) \log(1-\pi_i) \right] \]

CHƯƠNG 9: HỒI QUY POISSON (POISSON REGRESSION)

9.1 Giới thiệu và ứng dụng thực tế

Hồi quy Poisson là một mô hình thuộc họ GLM, được sử dụng để mô hình hóa các biến phản hồi là số lượng sự kiện đếm được trên một đơn vị quan sát, chẳng hạn như:

  • Số lần nhập viện

  • Số vụ tai nạn giao thông

  • Số lỗi phần mềm phát sinh

Đặc biệt phù hợp khi:

  • Biến phản hồi \(y \in \{0, 1, 2, \ldots \}\)

  • Dữ liệu không âm, rời rạc

  • Mục tiêu là ước lượng số sự kiện trung bình theo các đặc tính \(x\)


9.2 Phân phối Poisson và liên kết log

Hàm xác suất:
\[ P(y_i) = \frac{e^{-\mu_i} \mu_i^{y_i}}{y_i!}, \quad y_i = 0, 1, 2, \ldots \]

Trong đó:

\[ \mu_i = E[y_i] : \text{số sự kiện kỳ vọng của quan sát thứ } i \]

\[ \text{Var}(y_i) = \mu_i \quad : \text{đặc điểm then chốt} \]

Hàm liên kết (canonical):

\[ \eta_i = \log(\mu_i) = x_i^T \beta \implies \mu_i = e^{x_i^T \beta} \]

Hàm log đảm bảo:

\[ \mu_i > 0 \]

Mối quan hệ tuyến tính trên log-scale.


9.3 Hàm log-likelihood và phương trình điểm

Log-likelihood của mô hình:

\[ \ell(\beta) = \sum_{i=1}^n \left[ y_i \log(\mu_i) - \mu_i - \log(y_i!) \right] \]

Thay \(\mu_i = e^{x_i^T \beta}\), ta được:

\[ \ell(\beta) = \sum_{i=1}^n \left[ y_i x_i^T \beta - e^{x_i^T \beta} - \log(y_i!) \right] \]

Score function (đạo hàm log-likelihood):

\[ U(\beta) = \sum_{i=1}^n x_i (y_i - \mu_i) \]

Giải phương trình \(U(\beta) = 0\) → tìm \(\hat{\beta}\) bằng IRLS.

9.4 Diễn giải hệ số hồi quy

Trong hồi quy Poisson:

  • Mỗi \(\beta_j\) là tác động log tuyến tính đến số sự kiện trung bình.

  • \(e^{\beta_j}\) là tỷ lệ thay đổi kỳ vọng \(\mu\) khi \(x_j\) tăng 1 đơn vị, giữ các biến khác không đổi.

Ví dụ:

  • \(\beta_j = 0.693 \Rightarrow e^{0.693} = 2\): số sự kiện kỳ vọng gấp đôi khi \(x_j\) tăng 1 đơn vị.

  • \(\beta_j = -0.223\) → giảm khoảng 20%.


9.5 Tỷ lệ xảy ra & offset

Offset là gì?
Khi quan sát không đồng nhất về thời gian/phạm vi, cần điều chỉnh bằng offset.

Ví dụ:

  • Quan sát 1: 5 tai nạn trong 10 ngày

  • Quan sát 2: 2 tai nạn trong 2 ngày

Không thể so sánh số tuyệt đối → dùng tỷ lệ:
\[ \frac{\mu_i}{t_i} \implies \log(\mu_i) = \log(t_i) + x_i^T \beta \]

Trong đó \(\log(t_i)\)offset – không có hệ số, nhưng được đưa vào mô hình.


9.6 Overdispersion (phân tán quá mức)

Trong lý thuyết:

\[ \mathrm{Var}(y_i) = \mu_i \]

Nhưng thực tế thường thấy:

\[ \mathrm{Var}(y_i) > \mu_i \quad \Rightarrow \quad \text{overdispersion} \]

Nguyên nhân do bỏ sót biến quan trọng, quá nhiều giá trị 0, hoặc biến động ngẫu nhiên vượt mức.

Hệ số phân tán:

\[ \hat{\phi} = \frac{\text{Deviance}}{n - p} \]

Nếu \(\hat{\phi} > 1.5\) thì đáng lo ngại.

Cách xử lý:

  • Sử dụng quasi-Poisson: điều chỉnh phương sai mà không thay đổi kỳ vọng.

  • Dùng Negative Binomial: thêm tham số \(\alpha\) để điều chỉnh phương sai.


9.7 Đánh giá mô hình

  • Deviance: kiểm tra mức độ phù hợp của mô hình.

  • AIC: chọn mô hình tốt nhất.

  • Kiểm định deviance: so sánh hai mô hình lồng nhau.

  • Biểu đồ phần dư:

    • Residuals vs fitted

    • Deviance residuals

    • Cook’s distance

Kiểm định Pearson chi-square:

\[ X^2 = \sum_{i=1}^n \frac{(y_i - \mu_i)^2}{\mu_i} \quad \Rightarrow \quad X^2 \sim \chi^2_{n-p} \]

9.8 So sánh với các mô hình khác

Mô hình Khi nào dùng
Poisson Dữ liệu đếm, phương sai gần bằng kỳ vọng (\(\mathrm{Var}(y) \approx E(y)\))
Quasi-Poisson Khi có overdispersion nhẹ, giữ cùng hàm liên kết (link function)
Negative Binomial Khi overdispersion nặng hoặc dữ liệu có quá nhiều giá trị 0

CHƯƠNG 10: HỒI QUY GAMMA (GAMMA REGRESSION)

10.1 Giới thiệu

Hồi quy Gamma là một mô hình thuộc họ GLM dùng để mô hình hóa các biến phản hồi dương liên tục có phương sai tăng theo giá trị trung bình.

Ví dụ ứng dụng:

  • Chi phí y tế

  • Thời gian sống (survival time)

  • Lượng tiêu thụ năng lượng

10.2 Phân phối Gamma

Giả định biến ngẫu nhiên \(y_i\) phân phối Gamma với tham số:

\[ y_i \sim Gamma(\alpha, \mu_i) \]

Trong đó:

  • \(\mu_i = E[y_i]\) là kỳ vọng.

  • Phương sai:
    \[ Var(y_i) = \frac{\mu_i^2}{\alpha} = \phi \mu_i^2 \]

Phương sai tỷ lệ với bình phương kỳ vọng, phù hợp khi biến thiên tỷ lệ không đổi.

10.3 Hàm mật độ xác suất Gamma (dạng GLM)

Hàm mật độ xác suất:

\[ f(y; \mu, \phi) = \frac{1}{\Gamma(1/\phi)} \left(\frac{1}{\phi \mu}\right)^{1/\phi} y^{\frac{1}{\phi}-1} \exp\left(-\frac{y}{\phi \mu}\right) \]

Hàm này thuộc họ hàm mũ (exponential family), với:

\[ \theta = -\frac{1}{\mu} \]

\[ b(\theta) = -\log(-\theta) \]

Hàm phương sai:

\[ V(\mu) = \mu^2 \]

\(\phi\) là tham số phân tán.

10.5 Ước lượng trong hồi quy Gamma

Ước lượng tham số \(\beta\) bằng phương pháp hợp lý tối đa (MLE) qua thuật toán IRLS.

Hàm log-likelihood:

\[ \ell(\beta) = \sum_{i=1}^n \left[-\log(\mu_i) - \frac{y_i}{\mu_i} \right] + \text{hằng số} \]

với:

\[ \mu_i = e^{x_i^T \beta} \]

Phương trình điểm:

\[ \frac{\partial \ell}{\partial \beta} = \sum_{i=1}^n x_i \left( y_i - \frac{\mu_i}{\mu_i^2} \cdot \frac{d\mu_i}{d\eta_i} \right) = 0 \]

Dùng IRLS để giải phương trình và tìm nghiệm \(\hat{\beta}\).

10.6 Diễn giải hệ số

Với link log:

\[ \log(\mu_i) = \beta_0 + \beta_1 x_{i1} + \cdots + \beta_p x_{ip} \implies \mu_i = e^{x_i^T \beta} \]

Mỗi hệ số \(\beta_j\) được hiểu là tác động trên log-scale, nghĩa là ảnh hưởng đến log của kỳ vọng trung bình.

  • Khi \(x_j\) tăng 1 đơn vị, trung bình \(\mu\) thay đổi theo tỷ lệ:

\[ e^{\beta_j} \]

tức là hệ số tỷ lệ thay đổi của \(\mu\).

10.7 Kiểm định và khoảng tin cậy

  • Wald test để kiểm định:

\[ Z_j = \frac{\hat{\beta}_j}{SE(\hat{\beta}_j)} \sim \mathcal{N}(0,1) \]

  • Khoảng tin cậy cho \(\beta_j\):

\[ \hat{\beta}_j \pm z_{\alpha/2} \cdot SE(\hat{\beta}_j) \]

  • Chuyển sang khoảng tin cậy tỷ lệ thay đổi trung bình:

\[ \left(e^{\hat{\beta}_j - z_{\alpha/2} SE(\hat{\beta}_j)}, \quad e^{\hat{\beta}_j + z_{\alpha/2} SE(\hat{\beta}_j)} \right) \]

10.8 Kiểm tra độ phù hợp (Goodness-of-fit)

  • Deviance:

\[ D = 2 \sum_{i=1}^n \left[ \frac{y_i - \mu_i}{\mu_i} - \log\left(\frac{y_i}{\mu_i}\right) \right] \]

  • Pearson chi-square:

\[ X^2 = \sum_{i=1}^n \left( \frac{y_i - \mu_i}{\mu_i} \right)^2 \]

Hai chỉ số này dùng để đánh giá độ phù hợp của mô hình và phát hiện hiện tượng overdispersion nếu có.

10.9 So sánh với mô hình khác

Mô hình Khi dùng
Hồi quy tuyến tính Khi dữ liệu phân phối chuẩn, phương sai không đổi
Hồi quy Gamma Khi dữ liệu dương, phương sai tỷ lệ với bình phương trung bình
Hồi quy log-normal Khi \(\log(y)\) phân phối chuẩn (sau biến đổi log)

CHƯƠNG 11: DỮ LIỆU NHÓM HOẶC TỶ LỆ (GROUPED DATA OR PROPORTIONS)

11.1 Giới thiệu

Dữ liệu nhị phân dạng 0/1 được mô hình hóa bằng hồi quy logistic. Tuy nhiên, nếu dữ liệu có dạng tổng hợp (grouped) hoặc thể hiện dưới dạng tỷ lệ, ví dụ:

20 thành công trong 30 thử nghiệm → \(y = 20, n = 30\)

  • Tỷ lệ mắc bệnh ở mỗi quận

  • Tỷ lệ sinh viên đậu trong từng lớp

→ Cần dùng GLM dạng nhị thức tổng quát (binomial GLM), áp dụng cho số lần thành công trên số lần thử.

11.2 Mô hình hóa số thành công trong nhóm

Với \(y_i \sim \text{Binomial}(n_i, \pi_i)\), ta mô hình hóa:

\[ \log \left(\frac{\pi_i}{1 - \pi_i}\right) = \eta_i = x_i^T \beta \implies \pi_i = \frac{e^{x_i^T \beta}}{1 + e^{x_i^T \beta}} \]

Trong đó:

  • \(y_i\): số thành công trong nhóm \(i\)

  • \(n_i\): tổng số thử nghiệm trong nhóm \(i\)

  • \(\pi_i\): xác suất thành công

  • \(\mu_i = E[y_i] = n_i \pi_i\)

  • \(\text{Var}(y_i) = n_i \pi_i (1 - \pi_i)\)

→ Phù hợp cho dữ liệu dạng “n trials, k successes”.

11.3 Log-likelihood và IRLS

Hàm log-likelihood:

\[ \ell(\beta) = \sum_{i=1}^n \left[ y_i \log(\pi_i) + (n_i - y_i) \log(1 - \pi_i) \right] \]

Tối đa hóa log-likelihood bằng IRLS (như logistic), nhưng có thêm yếu tố \(n_i\).

Biến giả và trọng số:

\[ w_i = n_i \pi_i (1 - \pi_i) \]

\[ z_i = \eta_i + \frac{y_i - n_i \pi_i}{n_i \pi_i (1 - \pi_i)} \]

11.4 Ưu điểm so với mô hình nhị phân

Dạng dữ liệu Mô hình tương ứng Ghi chú
0/1 từng cá nhân Hồi quy logistic \(y_i \sim \text{Bernoulli}(\pi_i)\)
Nhóm nhiều cá nhân Binomial GLM với \(y_i / n_i\) \(y_i \sim \text{Binomial}(n_i, \pi_i)\)

→ Mô hình nhóm cho kết quả ước lượng chính xác hơn vì dùng nhiều thông tin hơn trên mỗi quan sát.

11.5 Dữ liệu tỷ lệ (proportions)

Nếu \(y_i / n_i\) được ghi dưới dạng tỷ lệ (0 < tỷ lệ < 1), ta vẫn dùng mô hình:

\[ \log \left(\frac{y_i / n_i}{1 - y_i / n_i}\right) = x_i^T \beta \]

→ Nhưng phải chỉ rõ số lần thử \(n_i\) để tính đúng phương sai.

11.6 Kiểm định mô hình

  • Wald test cho các hệ số

  • Kiểm định deviance giữa mô hình đầy đủ và rút gọn

  • AIC/BIC để chọn mô hình

  • Phần dư Pearson / deviance để phát hiện điểm bất thường

11.7 Kiểm tra overdispersion

Giống hồi quy logistic, mô hình binomial giả định:

\[ \text{Var}(y_i) = n_i \pi_i (1 - \pi_i) \]

Nếu thấy phương sai quan sát lớn hơn → overdispersion.

Kiểm tra:

\[ \hat{\phi} = \frac{\text{Deviance}}{n - p} \]

→ Nếu \(\hat{\phi} > 1.5\): cần chuyển sang mô hình quasi-binomial

CHƯƠNG 12: MÔ HÌNH TUYẾN TÍNH TỔNG QUÁT TWEEDEE (TWEEDIE GLMs)

12.1 Giới thiệu

Mô hình Tweedie GLM mở rộng họ hàm mũ bằng cách cho phép phân phối có đặc điểm trung gian giữa các phân phối quen thuộc như:

  • Gaussian

  • Poisson

  • Gamma

  • Inverse Gaussian

Mô hình Tweedie phù hợp với các loại dữ liệu có đặc điểm:

  • Liên tục dương + rất nhiều giá trị 0
    (ví dụ: dữ liệu chi phí, có người không tiêu dùng)

  • Phân tán quá mức (overdispersion)

  • Có cả phần rời rạc (0, 1, 2, …) lẫn liên tục dương

→ Ứng dụng rộng rãi trong bảo hiểm, tài chính, y tế, và các bài toán zero-inflated data.


12.2 Định nghĩa và tính chất

Tweedie là một lớp phân phối thuộc họ hàm mũ (exponential family), với hàm phương sai có dạng:

\[ \text{Var}(Y) = \phi \mu^p \]

Trong đó:

  • \(\mu = \mathbb{E}[Y]\): kỳ vọng

  • \(\phi > 0\): hệ số phân tán

  • \(p\): chỉ số sức mạnh (power index)


12.3 Giá trị đặc biệt của chỉ số \(p\)

\(p\) Phân phối tương ứng
0 Gaussian (Normal)
1 Poisson
\((1, 2)\) Tweedie hỗn hợp (0 + dương liên tục)
2 Gamma
3 Inverse Gaussian

→ Với \(1 < p < 2\), mô hình Tweedie hỗn hợp có thể:

  • Tái hiện được số lượng lớn giá trị 0

  • Mô hình hóa được giá trị dương liên tục

Rất phù hợp cho các bài toán như chi phí bảo hiểm, tổn thất, dữ liệu có số 0 và giá trị tiền tệ.

BÀI TẬP 2

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

library(readr)
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
library(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
library(skimr)
## Warning: package 'skimr' was built under R version 4.3.3
library(psych)
## Warning: package 'psych' was built under R version 4.3.3
## 
## Attaching package: 'psych'
## The following objects are masked from 'package:ggplot2':
## 
##     %+%, alpha
library(csv)
## Warning: package 'csv' was built under R version 4.3.3

1. Đọc file CSV

  • Tệp Supermarket Transactions được lưu dưới định dạng CSV, vì vậy ta sẽ đọc dữ liệu từ tệp này.

  • Sau khi đọc, bộ dữ liệu được gán vào biến data để thuận tiện cho việc xử lý và phân tích sau này.

data <- read.csv("D:/PTDLDT/Supermarket Transactions.csv", header = T)

2. Tổng quan bộ số liệu

2.1 Nội dung bộ dữ liệu

  • Bộ dữ liệu Supermarket Transactions ghi lại thông tin về các giao dịch mua hàng tại một hệ thống siêu thị, bao gồm thông tin khách hàng, vị trí địa lý, và chi tiết các sản phẩm được mua.

  • Dữ liệu này có thể được sử dụng để phân tích hành vi mua sắm của khách hàng, phân khúc thị trường, hoặc đánh giá hiệu quả kinh doanh theo từng sản phẩm, khu vực và nhóm nhân khẩu học.

2.2 Danh sách các biến và mô tả

Tên của các biến trong bộ dữ liệu sẽ bao gồm:

names(data)
##  [1] "X"                 "PurchaseDate"      "CustomerID"       
##  [4] "Gender"            "MaritalStatus"     "Homeowner"        
##  [7] "Children"          "AnnualIncome"      "City"             
## [10] "StateorProvince"   "Country"           "ProductFamily"    
## [13] "ProductDepartment" "ProductCategory"   "UnitsSold"        
## [16] "Revenue"

Cụ thể từng các biến và quan sát có ý nghĩa:

variable_description <- data.frame(
  Variable = c(
    "Unnamed: 0", "PurchaseDate", "CustomerID", "Gender", "MaritalStatus",
    "Homeowner", "Children", "AnnualIncome", "City", "StateorProvince",
    "Country", "ProductFamily", "ProductDepartment", "ProductCategory",
    "UnitsSold", "Revenue"
  ),
  Description = c(
    "Ma dong (co the bo qua)",
    "Ngay mua hang",
    "ID khach hang",
    "Gioi tinh (F: nu, M: nam)",
    "Tinh trang hon nhan (S: doc than, M: da ket hon)",
    "So huu nha (Y: co, N: khong)",
    "So con trong gia dinh",
    "Thu nhap hang nam (theo nhom)",
    "Thanh pho sinh song",
    "Bang / tinh",
    "Quoc gia",
    "Nhom san pham chinh (Food, Drink, ...)",
    "Phong ban san pham (Snacks, Produce, ...)",
    "Danh muc san pham cu the",
    "So luong san pham da ban",
    "Doanh thu tu giao dich (USD)"
  ),
  stringsAsFactors = FALSE
)

library(knitr)
kable(variable_description, col.names = c("Bien", "Mo ta"))
Bien Mo ta
Unnamed: 0 Ma dong (co the bo qua)
PurchaseDate Ngay mua hang
CustomerID ID khach hang
Gender Gioi tinh (F: nu, M: nam)
MaritalStatus Tinh trang hon nhan (S: doc than, M: da ket hon)
Homeowner So huu nha (Y: co, N: khong)
Children So con trong gia dinh
AnnualIncome Thu nhap hang nam (theo nhom)
City Thanh pho sinh song
StateorProvince Bang / tinh
Country Quoc gia
ProductFamily Nhom san pham chinh (Food, Drink, …)
ProductDepartment Phong ban san pham (Snacks, Produce, …)
ProductCategory Danh muc san pham cu the
UnitsSold So luong san pham da ban
Revenue Doanh thu tu giao dich (USD)

3 Thống kê mô tả cho các biến

3.1 Số biến và số quan sát

dim(data)
## [1] 14059    16
  • Bộ dữ liệu data chứa tổng cộng 14.059 bản ghi với 16 biến đặc trưng.

  • Mỗi bản ghi tương ứng với một giao dịch mua hàng tại siêu thị, mô tả chi tiết về lần mua đó thông qua 16 thuộc tính khác nhau.

3.2 Kiểm tra cấu trúc tổng quát

Để hiểu rõ hơn về cấu trúc tổng thể của bộ dữ liệu, ta có thể thực hiện việc kiểm tra các thành phần cơ bản như số lượng biến, kiểu dữ liệu của từng biến, cũng như một số thông tin tổng quan khác. Việc này giúp chúng ta có cái nhìn bao quát trước khi tiến hành các bước phân tích chuyên sâu hơn.

str(data)
## 'data.frame':    14059 obs. of  16 variables:
##  $ X                : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ PurchaseDate     : chr  "2007-12-18" "2007-12-20" "2007-12-21" "2007-12-21" ...
##  $ CustomerID       : int  7223 7841 8374 9619 1900 6696 9673 354 1293 7938 ...
##  $ Gender           : chr  "F" "M" "F" "M" ...
##  $ MaritalStatus    : chr  "S" "M" "M" "M" ...
##  $ Homeowner        : chr  "Y" "Y" "N" "Y" ...
##  $ Children         : int  2 5 2 3 3 3 2 2 3 1 ...
##  $ AnnualIncome     : chr  "$30K - $50K" "$70K - $90K" "$50K - $70K" "$30K - $50K" ...
##  $ City             : chr  "Los Angeles" "Los Angeles" "Bremerton" "Portland" ...
##  $ StateorProvince  : chr  "CA" "CA" "WA" "OR" ...
##  $ Country          : chr  "USA" "USA" "USA" "USA" ...
##  $ ProductFamily    : chr  "Food" "Food" "Food" "Food" ...
##  $ ProductDepartment: chr  "Snack Foods" "Produce" "Snack Foods" "Snacks" ...
##  $ ProductCategory  : chr  "Snack Foods" "Vegetables" "Snack Foods" "Candy" ...
##  $ UnitsSold        : int  5 5 3 4 4 3 4 6 1 2 ...
##  $ Revenue          : num  27.38 14.9 5.52 4.44 14 ...

Các biến trong bộ dữ liệu bao gồm:

  • X: biến số nguyên, có thể là chỉ số thứ tự của bản ghi.

  • PurchaseDate: ngày mua hàng, được lưu dưới dạng chuỗi ký tự với định dạng “YYYY-MM-DD”.

  • CustomerID: mã định danh khách hàng dưới dạng số nguyên.

  • Gender: giới tính khách hàng, ký hiệu bằng ký tự (F: nữ, M: nam).

  • MaritalStatus: tình trạng hôn nhân (S: độc thân, M: đã kết hôn).

  • Homeowner: trạng thái sở hữu nhà (Y: có nhà, N: không có nhà).

  • Children: số lượng con trong gia đình, kiểu số nguyên.

  • AnnualIncome: nhóm thu nhập hàng năm, được ghi dưới dạng chuỗi ký tự (ví dụ: “$30K - $50K”).

  • City: tên thành phố nơi khách hàng sinh sống.

  • StateorProvince: bang hoặc tỉnh, được lưu dưới dạng chuỗi ký tự.

  • Country: quốc gia, dưới dạng chuỗi ký tự.

  • ProductFamily: nhóm sản phẩm chính, ví dụ như Food, Drink,…

  • ProductDepartment: phòng ban sản phẩm, ví dụ như Snack Foods, Produce,…

  • ProductCategory: danh mục sản phẩm cụ thể.

  • UnitsSold: số lượng sản phẩm đã bán, kiểu số nguyên.

  • Revenue: doanh thu thu được từ giao dịch, kiểu số thực (đơn vị USD).

Việc hiểu rõ cấu trúc và kiểu dữ liệu của các biến sẽ hỗ trợ rất nhiều trong việc phân tích và xử lý dữ liệu tiếp theo.

Vì bộ dữ liệu bao gồm cả các biến định tính như thông tin nhận dạng hay các phân loại liên quan đến khách hàng, những biến này không thể trực tiếp dùng cho các phép tính số học như các biến định lượng (ví dụ: doanh thu, số lượng sản phẩm bán ra). Do đó, trong quá trình thống kê mô tả, ta cần phân biệt rõ giữa hai nhóm biến này để lựa chọn phương pháp xử lý phù hợp.

3.3 Thống kê mô tả biến định lượng

library(psych)

describe(select(data, UnitsSold, Revenue, Children))
##           vars     n  mean   sd median trimmed  mad  min  max range  skew
## UnitsSold    1 14059  4.08 1.17   4.00    4.08 1.48 1.00  8.0  7.00  0.01
## Revenue      2 14059 13.00 8.22  11.25   12.05 7.40 0.53 56.7 56.17  1.13
## Children     3 14059  2.53 1.49   3.00    2.53 1.48 0.00  5.0  5.00 -0.02
##           kurtosis   se
## UnitsSold    -0.44 0.01
## Revenue       1.39 0.07
## Children     -1.03 0.01

1. UnitsSold

(Số lượng sản phẩm được bán trong mỗi giao dịch)

Thống kê Giá trị
Trung bình 4.08
Trung vị 4.00
Min – Max 1 – 8
Độ lệch chuẩn (sd) 1.17
Skew (độ lệch) 0.01 → Gần đối xứng
Kurtosis -0.44 → Gần chuẩn

Nhận xét: Hầu hết các giao dịch bán khoảng 4 sản phẩm. Phân phối gần với phân phối chuẩn.


2. Revenue

(Doanh thu mỗi giao dịch, đơn vị USD)

Thống kê Giá trị
Trung bình 13.00 USD
Trung vị 11.25 USD
Min – Max 0.53 – 56.70 USD
Độ lệch chuẩn (sd) 8.22
Skew (độ lệch) 1.13 → Phân phối lệch phải
Kurtosis 1.39 → Phân phối nhọn hơn chuẩn

Nhận xét: Doanh thu giao dịch có xu hướng lệch phải, nghĩa là phần lớn các giao dịch có doanh thu thấp và chỉ một số ít mang lại giá trị cao.

3. Children (Số con của khách hàng)

  • Phân bố khá đối xứng

    Độ lệch (skew) gần bằng 0, cho thấy phân bố không lệch đáng kể sang trái hay phải.
    Giá trị trung bình (2,53) gần bằng trung vị (3), xác nhận tính đối xứng này.

  • Độ phân tán vừa phải

    Độ lệch chuẩn khoảng 1,5, nghĩa là đa số khách hàng có từ 1 đến 4 con.
    Khoảng 68% các quan sát nằm trong khoảng 1,0 đến 4,0 con (ước lượng bằng mean ± SD).

  • Giá trị cực trị hợp lý

    Số con thấp nhất là 0 và cao nhất là 5, không có giá trị ngoại lệ bất thường (ví dụ như > 10).

  • Độ nhọn âm

    Kurtosis < 0 cho thấy phân bố hơi “phẳng”, tức đỉnh thấp hơn phân phối chuẩn,
    với tần suất ở trung tâm ít cô đặc hơn, hai đuôi phân bố hơi dày hơn nhưng vẫn nằm trong tầm kiểm soát.

Hàm ý

  • Có thể phân nhóm khách hàng dựa trên số con thành:

    • Không con (0)

    • Gia đình nhỏ (1–2)

    • Gia đình trung bình (3–4)

    • Gia đình lớn (5)

  • Về tiếp thị sản phẩm:

    • Nhóm 0–1 con có thể quan tâm đến sản phẩm cá nhân hoặc dành cho đôi.

    • Nhóm có từ 3 con trở lên ưu tiên gói sản phẩm gia đình và các chương trình chiết khấu theo số lượng.

  • Trong mô hình dự đoán, do phân bố tương đối đối xứng và không có ngoại lệ nghiêm trọng, biến Children có thể được sử dụng trực tiếp mà không cần biến đổi như log hay winsorize.

3.4 Biến định tính

# Lấy tên các biến định tính
categorical_vars <- c(
  "Gender", "MaritalStatus", "Homeowner", "AnnualIncome",
  "City", "StateorProvince", "Country",
  "ProductFamily", "ProductDepartment", "ProductCategory"
)

# Tạo bảng tần số cho từng biến
for (var in categorical_vars) {
  cat("\n###", var, "\n")
  print(table(data[[var]]))
  cat("\n")
}
## 
## ### 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

3.4.1. Gender (Giới tính)

gender_table <- table(data$Gender)
gender_prop <- prop.table(gender_table)
kable(
  cbind(So_luong = gender_table, Ty_le = round(gender_prop * 100, 2)),
  col.names = c("So luong", "Ty le (%)")
)
So luong Ty le (%)
F 7170 51
M 6889 49
gender_df <- as.data.frame(gender_prop) |>
  mutate(
    Gender  = names(gender_prop),
    Percent = round(Freq * 100, 2)
  )

ggplot(gender_df, aes(x = "", y = Percent, fill = Gender)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  geom_text(aes(label = paste0(Percent, "%")),
            position = position_stack(vjust = 0.5), size = 5) +
  labs(title = "Tỷ lệ giới tính", x = NULL, y = NULL) +
  theme_void() +
  scale_fill_manual(values = c("#4E79A7", "#F28E2B"))

  • Tỷ lệ khách hàng theo giới tính khá cân bằng giữa nam (M) và nữ (F).

  • Nữ chiếm 51%, nhỉnh hơn một chút so với nam là 49%.

  • Điều này cho thấy không có sự chênh lệch lớn về giới tính trong mẫu dữ liệu này.

  • Cửa hàng/công ty có thể thiết kế chiến lược marketing không cần phân biệt giới tính mạnh, vì cả hai nhóm khách hàng đều tương đương về tỷ lệ.

3.4.2. MaritalStatus (Tình trạng hôn nhân)

marital_table <- table(data$MaritalStatus)
marital_prop <- prop.table(marital_table)
kable(
  cbind(So_luong = marital_table, Ty_le = round(marital_prop * 100, 2)),
  col.names = c("So luong", "Ty le (%)")
)
So luong Ty le (%)
M 6866 48.84
S 7193 51.16
# Đưa về data‑frame
marital_df <- data.frame(
  Status  = names(marital_prop),
  Percent = round(as.vector(marital_prop) * 100, 2)
)

# Biểu đồ tròn
ggplot(marital_df, aes(x = "", y = Percent, fill = Status)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  geom_text(aes(label = paste0(Percent, "%")),
            position = position_stack(vjust = 0.5), size = 5) +
  labs(title = "Tỷ lệ tình trạng hôn nhân", x = NULL, y = NULL) +
  theme_void() +
  scale_fill_manual(values = c("#59A14F", "#EDC948"))  # tuỳ chọn màu

  • Tình trạng hôn nhân của khách hàng khá cân bằng giữa hai nhóm. Trong đó, khách hàng độc thân chiếm tỷ lệ nhỉnh hơn một chút (51.16%) so với nhóm đã kết hôn (48.84%). Điều này cho thấy siêu thị có tệp khách hàng đa dạng về tình trạng hôn nhân, không nghiêng hẳn về nhóm nào.

3.4.3. Homeowner (Sở hữu nhà)

homeowner_table <- table(data$Homeowner)
homeowner_prop <- prop.table(homeowner_table)
kable(
  cbind(So_luong = homeowner_table, Ty_le = round(homeowner_prop * 100, 2)),
  col.names = c("So luong", "Ty le (%)")
)
So luong Ty le (%)
N 5615 39.94
Y 8444 60.06
# Đưa về data‑frame
homeowner_df <- data.frame(
  Owner   = names(homeowner_prop),                    # ví dụ: "Yes" / "No"
  Percent = round(as.vector(homeowner_prop) * 100, 2) # chuyển sang %
)

# Biểu đồ tròn
ggplot(homeowner_df, aes(x = "", y = Percent, fill = Owner)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  geom_text(aes(label = paste0(Percent, "%")),
            position = position_stack(vjust = 0.5), size = 5) +
  labs(title = "Tỷ lệ chủ sở hữu nhà", x = NULL, y = NULL) +
  theme_void() +
  scale_fill_manual(values = c("#E15759", "#76B7B2"))   # tuỳ chọn màu

  • Khoảng 60% khách hàng trong dữ liệu là người sở hữu nhà, trong khi gần 40% không sở hữu nhà. Điều này phản ánh rằng phần lớn khách hàng của siêu thị thuộc nhóm đã có điều kiện kinh tế ổn định hơn. Tuy nhiên, nhóm không sở hữu nhà vẫn chiếm tỷ lệ đáng kể, cho thấy siêu thị cũng tiếp cận được nhóm khách hàng thuê nhà hoặc chưa có nhà riêng.

3.4.4. AnnualIncome (Thu nhập hàng năm – theo nhóm)

# Làm sạch biến AnnualIncome nếu cần
data$AnnualIncome <- gsub("\\$", "", data$AnnualIncome)
data$AnnualIncome <- gsub("\u2013", "-", data$AnnualIncome)
data$AnnualIncome <- trimws(data$AnnualIncome)
data$AnnualIncome <- as.factor(data$AnnualIncome)

# Tính tần suất và tỷ lệ phần trăm
income_table <- table(data$AnnualIncome)
income_prop  <- prop.table(income_table)

# Kết hợp thành bảng
income_df <- data.frame(
  Muc      = names(income_table),
  So_luong = as.vector(income_table),
  Ty_le    = round(100 * as.vector(income_prop), 2)
)

# Hiển thị bảng đẹp
kable(income_df, col.names = c("Mức thu nhập", "Số lượng", "Tỷ lệ (%)"))
Mức thu nhập Số lượng Tỷ lệ (%)
10K - 30K 3090 21.98
110K - 130K 643 4.57
130K - 150K 760 5.41
150K + 273 1.94
30K - 50K 4601 32.73
50K - 70K 2370 16.86
70K - 90K 1709 12.16
90K - 110K 613 4.36
ggplot(income_df, aes(x = Muc, y = So_luong)) +
  geom_col(fill = "#4E79A7") +
  geom_text(aes(label = paste0(Ty_le, "%")),
            vjust = -0.3, size = 4) +
  labs(title = "Phân bố mức thu nhập",
       x = "Mức thu nhập",
       y = "Số lượng") +
  theme_minimal(base_size = 13) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

Điểm nổi bật:

  • Tập trung vào thu nhập tầm trung: Nhóm có thu nhập trong khoảng 30K – 70K chiếm khoảng 50% tổng số khách hàng. Đây chính là thị trường mục tiêu chính.

  • Thu nhập thấp - trung (10K – 30K) vẫn chiếm gần 22%, cho thấy sự hiện diện rõ rệt của phân khúc tiết kiệm. Nếu sản phẩm hoặc dịch vụ cần định giá, nên cân nhắc gói giá phù hợp nhóm này.

  • Nhóm có thu nhập cao (> 90K) chỉ chiếm khoảng 16%. Riêng nhóm rất cao > 150Krất nhỏ. Do đó, các chiến dịch sản phẩm/dịch vụ cao cấp cần nhắm đúng đối tượng, tránh lan rộng thiếu hiệu quả.

  • Phân bố thu nhập bị lệch trái (left-skewed): Phần lớn khách hàng thuộc nhóm thu nhập thấp - trung. Đỉnh phân bố rơi vào nhóm 30K–50K, càng về mức cao thì số lượng càng giảm.

Hàm ý

  • Chiến lược giá & khuyến mãi: Ưu tiên xây dựng các gói giá trung bình (30K–70K) đi kèm các lựa chọn tiết kiệm cho nhóm thu nhập thấp (10K–30K).

  • Sản phẩm cao cấp / Upsell: Tập trung vào việc xây dựng đề nghị giá trị cao rõ nét, vì nhóm thu nhập cao tuy nhỏ nhưng vẫn có gần 2.000 khách hàng tiềm năng (thu nhập > 90K).

  • Phân khúc tiếp thị: Cần chia ít nhất 3 tầng thu nhập:

    • Thấp (<30K)

    • Trung (30K–70K)

    • Cao (>70K) để cá nhân hóa nội dung và thông điệp tiếp thị phù hợp từng nhóm.

3.4.5. City (Thành phố)

# Nếu muốn, có thể bỏ khoảng trắng dư và ép factor
data$City <- trimws(data$City)
data$City <- as.factor(data$City)

# Tính tần suất & tỷ lệ phần trăm
city_table <- table(data$City)
city_prop  <- prop.table(city_table)

# Ghép thành data‑frame
city_df <- data.frame(
  City     = names(city_table),
  So_luong = as.vector(city_table),
  Ty_le    = round(100 * as.vector(city_prop), 2),
  row.names = NULL
)

# Hiển thị bảng đẹp
kable(city_df,
      col.names = c("Thành phố", "Số lượng", "Tỷ lệ (%)"))
Thành phố Số lượng Tỷ lệ (%)
Acapulco 383 2.72
Bellingham 143 1.02
Beverly Hills 811 5.77
Bremerton 834 5.93
Camacho 452 3.22
Guadalajara 75 0.53
Hidalgo 845 6.01
Los Angeles 926 6.59
Merida 654 4.65
Mexico City 194 1.38
Orizaba 464 3.30
Portland 876 6.23
Salem 1386 9.86
San Andres 621 4.42
San Diego 866 6.16
San Francisco 130 0.92
Seattle 922 6.56
Spokane 875 6.22
Tacoma 1257 8.94
Vancouver 633 4.50
Victoria 176 1.25
Walla Walla 160 1.14
Yakima 376 2.67
ggplot(city_df, aes(x = reorder(City, So_luong), y = So_luong)) +
  geom_col(fill = "#59A14F") +
  geom_text(aes(label = paste0(Ty_le, "%")),
            hjust = -0.1, size = 3.5) +
  coord_flip() +                              # xoay trục -> cột nằm ngang
  labs(title = "Phân bố khách hàng theo thành phố",
       x = "Thành phố",
       y = "Số lượng") +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(face = "bold"),
    axis.title.y = element_blank(),           # trục y là tên thành phố, không cần tiêu đề
    axis.text.y = element_text(size = 10)
  )

Nhận xét tổng quan:

  • Tập trung tại một số thành phố lớn:

    Những thành phố có tỷ lệ khách hàng cao nhất bao gồm:

    • Salem (9.86%)

    • Tacoma (8.94%)

    • Los Angeles (6.59%)

    • Seattle (6.56%)

    • Portland (6.23%)

    • San Diego (6.16%)

    → Đây là những khu vực tập trung đông khách hàng nhất, nên ưu tiên trong các chiến dịch marketing, phân phối hoặc dịch vụ khách hàng.

  • Phân bố tương đối trải đều ở nhóm giữa:

    Một số thành phố như Bremerton, Hidalgo, Spokane, Vancouver,… có tỷ lệ khách hàng ở mức trung bình từ 3% đến 6%, đóng vai trò bổ trợ quan trọng.

  • Nhóm có tỷ lệ thấp (dưới 2%):

    Các thành phố như Guadalajara, Walla Walla, Victoria, San Francisco, Bellingham,… có số lượng khách hàng thấp hơn, có thể không phải là thị trường chính, nhưng có thể khai thác thêm nếu muốn mở rộng.

Hàm ý triển khai:

  • Ưu tiên nguồn lực: Tập trung nguồn lực vào top 5–6 thành phố đầu bảng để tối ưu hiệu quả tiếp cận và chăm sóc khách hàng.

  • Chiến dịch địa phương hóa (localization): Với mỗi cụm thành phố có tỷ lệ cao, nên cân nhắc tùy chỉnh thông điệp quảng bá, chương trình khuyến mãi phù hợp vùng miền.

  • Định hướng mở rộng: Những thành phố có tỷ lệ trung bình có thể là thị trường tiềm năng để mở rộng trong giai đoạn tiếp theo.

3.4.6. StateorProvince (Bang hoặc tỉnh)

# Làm sạch nhẹ (bỏ khoảng trắng thừa) rồi ép factor
data$StateorProvince <- trimws(data$StateorProvince)
data$StateorProvince <- as.factor(data$StateorProvince)

# Tần suất & tỷ lệ
state_tab  <- table(data$StateorProvince)
state_prop <- prop.table(state_tab)

# Kết hợp thành bảng
state_df <- data.frame(
  Bang_Tinh = names(state_tab),
  So_luong  = as.vector(state_tab),
  Ty_le     = round(100 * as.vector(state_prop), 2),
  row.names = NULL
)

# Hiển thị
kable(state_df,
      col.names = c("Bang/Tỉnh", "Số lượng", "Tỷ lệ (%)"))
Bang/Tỉnh Số lượng Tỷ lệ (%)
BC 809 5.75
CA 2733 19.44
DF 815 5.80
Guerrero 383 2.72
Jalisco 75 0.53
OR 2262 16.09
Veracruz 464 3.30
WA 4567 32.48
Yucatan 654 4.65
Zacatecas 1297 9.23
ggplot(state_df, aes(x = reorder(Bang_Tinh, So_luong), y = So_luong)) +
  geom_col(fill = "#EDC948") +
  geom_text(aes(label = paste0(Ty_le, "%")),
            hjust = -0.1, size = 3.5) +
  coord_flip() +
  labs(title = "Phân bố khách hàng theo bang/tỉnh",
       x = "Bang/Tỉnh",
       y = "Số lượng") +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(face = "bold"),
    axis.title.y = element_blank()
  )

Nhận xét tổng quan:

  • Tập trung mạnh tại bang WA (Washington):

    Với 32.48% tổng số khách hàng (tương đương 4,567 khách), bang WA là thị trường trọng điểm, cần được ưu tiên cao nhất trong các chiến lược kinh doanh và tiếp thị.

  • Nhóm quan trọng thứ hai:

    • CA (California) chiếm 19.44%

    • OR (Oregon) chiếm 16.09%

    → Tổng cộng ba bang WA, CA, OR đã chiếm đến gần 70% tổng số khách hàng.

    Đây là vùng thị trường cốt lõi, nên đầu tư mạnh về nhân lực, quảng bá, dịch vụ hậu mãi tại khu vực này.

  • Bang có mức độ khách hàng trung bình:

    • Zacatecas (9.23%)

    • DF (5.80%)

    • BC (5.75%)

    → Đây là những khu vực phụ trợ đáng chú ý, có thể cân nhắc triển khai các chương trình marketing khu vực nhỏ (regional marketing).

  • Bang có tỷ lệ thấp (<5%):

    Guerrero, Jalisco, Veracruz, Yucatan — tuy có số lượng khách ít hơn, vẫn có thể cân nhắc tăng nhận diện thương hiệu, đặc biệt nếu muốn mở rộng thị trường về phía Mexico.

Hàm ý triển khai:

  • Tập trung nguồn lực vào top 3 bang chính (WA, CA, OR) để tối ưu hiệu quả kinh doanh.

  • Phát triển chiến lược tiếp thị vùng miền cụ thể, tùy theo quy mô khách hàng ở từng bang.

  • Khám phá thêm tiềm năng từ các bang có mức trung bình (Zacatecas, DF, BC) nếu mở rộng quy mô.

  • Thí điểm sản phẩm/dịch vụ mới ở thị trường nhỏ như Yucatan hoặc Veracruz để kiểm tra phản ứng thị trường trước khi mở rộng.

3.4.7. Country (Quốc gia)

# Làm sạch nếu cần (loại khoảng trắng thừa)
data$Country <- trimws(data$Country)
data$Country <- as.factor(data$Country)

# Tính tần suất và tỷ lệ phần trăm
country_table <- table(data$Country)
country_prop  <- prop.table(country_table)

# Kết hợp thành bảng
country_df <- data.frame(
  Quoc_gia = names(country_table),
  So_luong = as.vector(country_table),
  Ty_le    = round(100 * as.vector(country_prop), 2),
  row.names = NULL
)

# Hiển thị bảng đẹp
kable(country_df,
      col.names = c("Quốc gia", "Số lượng", "Tỷ lệ (%)"))
Quốc gia Số lượng Tỷ lệ (%)
Canada 809 5.75
Mexico 3688 26.23
USA 9562 68.01
ggplot(country_df, aes(x = "", y = So_luong, fill = Quoc_gia)) +
  geom_col(width = 1, color = "white") +       # lát bánh
  coord_polar(theta = "y") +                   # chuyển thành pie
  geom_text(
    aes(label = paste0(Quoc_gia, ": ", Ty_le, "%")),
    position = position_stack(vjust = 0.5),
    size = 3
  ) +
  labs(title = "Tỷ lệ khách hàng theo quốc gia",
       x = NULL, y = NULL, fill = "Quốc gia") +
  theme_void() +
  guides(fill = guide_legend(override.aes = list(size = 4)))

Nhận xét tổng quan:

  • Mỹ (USA) chiếm 68.01% tổng số khách hàng – đây là thị trường chính yếu và áp đảo tuyệt đối.

    → Các chiến lược kinh doanh, marketing, sản phẩm cần ưu tiên tối đa cho khách hàng Hoa Kỳ.

  • Mexico chiếm 26.23% – là thị trường phụ nhưng rất đáng chú ý với gần 1/4 tổng khách hàng.

    → Có thể cân nhắc bản địa hoá thông điệp, ưu đãi hoặc sản phẩm dành riêng cho khu vực này.

  • Canada chỉ chiếm 5.75% – số lượng tương đối nhỏ.

    → Không phải thị trường trọng tâm hiện tại, nhưng vẫn có thể được duy trì như một khu vực vệ tinh hỗ trợ hoặc để thử nghiệm sản phẩm mới.

Hàm ý triển khai:

  • Tập trung phát triển thị trường Mỹ: đầu tư về dịch vụ khách hàng, chiến dịch quảng cáo, mạng lưới phân phối tại Hoa Kỳ.

  • Phân khúc và bản địa hóa chiến dịch tại Mexico: dùng tiếng Tây Ban Nha, điều chỉnh chính sách giá, vận chuyển phù hợp với khu vực.

  • Giữ sự hiện diện tại Canada, nhưng chưa cần đầu tư mạnh — có thể khai thác dần khi các thị trường lớn đã ổn định.

3.4.8. ProductFamily (Nhóm sản phẩm lớn)

# Làm sạch biến ProductFamily (nếu cần)
data$ProductFamily <- trimws(data$ProductFamily)
data$ProductFamily <- as.factor(data$ProductFamily)

# Tính tần suất và tỷ lệ phần trăm
pf_table <- table(data$ProductFamily)
pf_prop  <- prop.table(pf_table)

# Kết hợp thành bảng
pf_df <- data.frame(
  ProductFamily = names(pf_table),
  So_luong     = as.vector(pf_table),
  Ty_le        = round(100 * as.vector(pf_prop), 2),
  row.names    = NULL
)

# Hiển thị bảng đẹp
kable(pf_df,
      col.names = c("Nhóm sản phẩm", "Số lượng", "Tỷ lệ (%)"))
Nhóm sản phẩm Số lượng Tỷ lệ (%)
Drink 1250 8.89
Food 10153 72.22
Non-Consumable 2656 18.89
ggplot(pf_df, aes(x = "", y = So_luong, fill = ProductFamily)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  geom_text(aes(label = paste0(Ty_le, "%")),
            position = position_stack(vjust = 0.5),
            size = 4) +
  labs(title = "Tỷ lệ theo nhóm sản phẩm",
       x = NULL, y = NULL, fill = "Nhóm sản phẩm") +
  theme_void() +
  guides(fill = guide_legend(override.aes = list(size = 5)))

Nhận xét:

  • Nhóm Food (thực phẩm) chiếm trên 72% tổng giao dịch, là mảng sản phẩm cốt lõi và chủ đạo.

    → Các quyết định về danh mục, chất lượng, giá, khuyến mãi… nên ưu tiên nhóm này.

  • Non-Consumable (phi tiêu dùng, như đồ gia dụng, điện tử…) chiếm gần 19% – là mảng phụ nhưng tiềm năng.

    → Có thể khai thác thêm về upsell hoặc cross-sell với nhóm khách hàng mua Food.

  • Drink (thức uống) chỉ chiếm gần 9% – là mảng nhỏ, nên cân nhắc tập trung vào các sản phẩm có biên lợi nhuận cao hoặc liên kết combo với Food.

Hàm ý triển khai:

  • Đầu tư tối ưu dòng sản phẩm Food: nghiên cứu hành vi mua, xu hướng ẩm thực, cải tiến bao bì, vị, giá.

  • Khai thác combo Food + Drink hoặc Food + Non-Consumable để tăng giá trị đơn hàng.

  • Định vị rõ Non-Consumable: dùng như sản phẩm quà tặng, khách hàng thân thiết hoặc nhắm vào nhóm có mức chi tiêu cao.

3.4.9. ProductDepartment (Phòng ban sản phẩm)

# Làm sạch biến ProductDepartment nếu cần
data$ProductDepartment <- trimws(data$ProductDepartment)
data$ProductDepartment <- as.factor(data$ProductDepartment)

# Tính tần suất và tỷ lệ phần trăm
pd_table <- table(data$ProductDepartment)
pd_prop  <- prop.table(pd_table)

# Kết hợp thành bảng
pd_df <- data.frame(
  ProductDepartment = names(pd_table),
  So_luong          = as.vector(pd_table),
  Ty_le             = round(100 * as.vector(pd_prop), 2),
  row.names         = NULL
)

# Hiển thị bảng đẹp
kable(pd_df,
      col.names = c("Phòng ban sản phẩm", "Số lượng", "Tỷ lệ (%)"))
Phòng ban sản phẩm Số lượng Tỷ lệ (%)
Alcoholic Beverages 356 2.53
Baked Goods 425 3.02
Baking Goods 1072 7.63
Beverages 680 4.84
Breakfast Foods 188 1.34
Canned Foods 977 6.95
Canned Products 109 0.78
Carousel 59 0.42
Checkout 82 0.58
Dairy 903 6.42
Deli 699 4.97
Eggs 198 1.41
Frozen Foods 1382 9.83
Health and Hygiene 893 6.35
Household 1420 10.10
Meat 89 0.63
Periodicals 202 1.44
Produce 1994 14.18
Seafood 102 0.73
Snack Foods 1600 11.38
Snacks 352 2.50
Starchy Foods 277 1.97
ggplot(pd_df, aes(x = reorder(ProductDepartment, So_luong), y = So_luong)) +
  geom_col(fill = "#76B7B2") +
  geom_text(aes(label = paste0(Ty_le, "%")),
            vjust = -0.5, size = 4) +
  labs(title = "Phân bố số lượng theo phòng ban sản phẩm",
       x = "Phòng ban sản phẩm",
       y = "Số lượng") +
  theme_minimal(base_size = 13) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

Nhận xét:

  • Produce (Rau quả tươi) là phòng ban chiếm tỷ trọng lớn nhất (14.18%), thể hiện xu hướng tiêu dùng thực phẩm tươi sống cao.

  • Snack Foods và Frozen Foods chiếm tỷ trọng lớn thứ 2 và 3 → cho thấy nhu cầu cao với đồ ăn nhanh, tiện lợi, thích hợp cho khách bận rộn hoặc gia đình.

  • Household (Đồ gia dụng) cũng chiếm hơn 10%, là sản phẩm thiết yếu trong đời sống → có thể kết hợp bán chéo.

  • Các nhóm như Meat, Seafood, Periodicals, Checkout, Carousel… chiếm tỷ trọng rất nhỏ → không phải trọng tâm hiện tại.

Hàm ý triển khai:

  • Tối ưu danh mục và khuyến mãi cho nhóm: Produce, Snack Foods, Frozen Foods → đây là các phòng ban tạo doanh số chủ lực.

  • Nhóm Household có thể tích hợp trong các chiến lược upsell hoặc combo cho khách hàng thường xuyên.

  • Các phòng ban nhỏ nên:

    • Được xem xét điều chỉnh vị trí/quy mô trưng bày.

    • Chỉ giữ lại những sản phẩm có biên lợi nhuận cao hoặc giá trị thương hiệu rõ nét.

3.4.10. ProductCategory (Danh mục sản phẩm cụ thể)

# Làm sạch biến ProductCategory nếu cần
data$ProductCategory <- trimws(data$ProductCategory)
data$ProductCategory <- as.factor(data$ProductCategory)

# Tính tần suất và tỷ lệ phần trăm
pc_table <- table(data$ProductCategory)
pc_prop  <- prop.table(pc_table)

# Kết hợp thành bảng
pc_df <- data.frame(
  ProductCategory = names(pc_table),
  So_luong       = as.vector(pc_table),
  Ty_le          = round(100 * as.vector(pc_prop), 2),
  row.names      = NULL
)

# Hiển thị bảng đẹp
kable(pc_df,
      col.names = c("Danh mục sản phẩm", "Số lượng", "Tỷ lệ (%)"))
Danh mục sản phẩm Số lượng Tỷ lệ (%)
Baking Goods 484 3.44
Bathroom Products 365 2.60
Beer and Wine 356 2.53
Bread 425 3.02
Breakfast Foods 417 2.97
Candles 45 0.32
Candy 352 2.50
Canned Anchovies 44 0.31
Canned Clams 53 0.38
Canned Oysters 35 0.25
Canned Sardines 40 0.28
Canned Shrimp 38 0.27
Canned Soup 404 2.87
Canned Tuna 87 0.62
Carbonated Beverages 154 1.10
Cleaning Supplies 189 1.34
Cold Remedies 93 0.66
Dairy 903 6.42
Decongestants 85 0.60
Drinks 135 0.96
Eggs 198 1.41
Electrical 355 2.53
Frozen Desserts 323 2.30
Frozen Entrees 118 0.84
Fruit 765 5.44
Hardware 129 0.92
Hot Beverages 226 1.61
Hygiene 197 1.40
Jams and Jellies 588 4.18
Kitchen Products 217 1.54
Magazines 202 1.44
Meat 761 5.41
Miscellaneous 42 0.30
Packaged Vegetables 48 0.34
Pain Relievers 192 1.37
Paper Products 345 2.45
Pizza 194 1.38
Plastic Products 141 1.00
Pure Juice Beverages 165 1.17
Seafood 102 0.73
Side Dishes 153 1.09
Snack Foods 1600 11.38
Specialty 289 2.06
Starchy Foods 277 1.97
Vegetables 1728 12.29
ggplot(pc_df, aes(x = reorder(ProductCategory, So_luong), y = So_luong)) +
  geom_col(fill = "#B07AA1") +
  labs(title = "Phân bố số lượng theo danh mục sản phẩm",
       x = "Danh mục sản phẩm",
       y = "Số lượng") +
  theme_minimal(base_size = 13) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

Nhận xét:

  • Vegetables là danh mục chiếm tỷ lệ cao nhất (12.29%) → cho thấy ưu tiên hàng đầu với nhóm thực phẩm tươi sống.

  • Snack Foods tiếp tục là danh mục chủ lực (11.38%) → xu hướng tiêu dùng đồ ăn nhanh, tiện dụng rất rõ ràng.

  • Dairy, Fruit và Meat đều nằm trong nhóm top 5 → đây là những sản phẩm thiết yếu, tiêu dùng hàng ngày.

  • Các danh mục như Canned Seafood (Canned Sardines, Tuna, Shrimp…) có tỷ trọng thấp (~0.3–0.6%) → ít được quan tâm, có thể là do khẩu vị, thói quen tiêu dùng.

Các danh mục có tỷ trọng rất thấp (<1%):

  • Candles, Canned Clams, Miscellaneous, Electrical… có lượng mua cực kỳ thấp → không phải ưu tiên chính trong chiến lược kinh doanh.

Hàm ý chiến lược:

  • Tập trung marketing và trưng bày nổi bật cho các nhóm: Vegetables, Snack Foods, Dairy, Fruit và Meat.

  • Gộp nhóm sản phẩm ít phổ biến vào các combo/khuyến mãi kèm → giúp tăng doanh số và giải phóng tồn kho.

  • Xem xét định vị lại hoặc thay thế danh mục dưới 0.5% nếu không mang lại lợi nhuận tốt hoặc không phục vụ mục tiêu thương hiệu.


3.5 Kết quả thống kê mô tả của các biến định tính

# Danh sách các biến định tính
cat_vars <- c("Gender", "MaritalStatus", "Homeowner", "AnnualIncome",
              "City", "StateorProvince", "Country",
              "ProductFamily", "ProductDepartment", "ProductCategory")

# Hàm xử lý từng biến
cat_summary <- function(df, var) {
  v <- trimws(df[[var]])         # loại bỏ khoảng trắng
  v <- as.factor(v)              # ép kiểu factor nếu chưa
  tbl  <- table(v, useNA = "ifany")
  prop <- prop.table(tbl)

  data.frame(
    Bien     = var,
    Muc      = names(tbl),
    So_luong = as.vector(tbl),
    Ty_le    = round(100 * as.vector(prop), 2),
    row.names = NULL,
    stringsAsFactors = FALSE
  )
}

# Áp dụng cho tất cả biến và nối thành 1 bảng lớn
big_tbl <- bind_rows(lapply(cat_vars, function(x) cat_summary(data, x)))

# (Tùy chọn) Sắp xếp theo biến rồi giảm dần số lượng
big_tbl <- big_tbl %>%
  arrange(Bien, desc(So_luong))

# Hiển thị bảng thống kê
kable(big_tbl,
      col.names = c("Biến", "Mức", "Số lượng", "Tỷ lệ (%)"),
      caption = "Bảng thống kê mô tả cho tất cả biến định tính")
Bảng thống kê mô tả cho tất cả biến định tính
Biến Mức Số lượng Tỷ lệ (%)
AnnualIncome 30K - 50K 4601 32.73
AnnualIncome 10K - 30K 3090 21.98
AnnualIncome 50K - 70K 2370 16.86
AnnualIncome 70K - 90K 1709 12.16
AnnualIncome 130K - 150K 760 5.41
AnnualIncome 110K - 130K 643 4.57
AnnualIncome 90K - 110K 613 4.36
AnnualIncome 150K + 273 1.94
City Salem 1386 9.86
City Tacoma 1257 8.94
City Los Angeles 926 6.59
City Seattle 922 6.56
City Portland 876 6.23
City Spokane 875 6.22
City San Diego 866 6.16
City Hidalgo 845 6.01
City Bremerton 834 5.93
City Beverly Hills 811 5.77
City Merida 654 4.65
City Vancouver 633 4.50
City San Andres 621 4.42
City Orizaba 464 3.30
City Camacho 452 3.22
City Acapulco 383 2.72
City Yakima 376 2.67
City Mexico City 194 1.38
City Victoria 176 1.25
City Walla Walla 160 1.14
City Bellingham 143 1.02
City San Francisco 130 0.92
City Guadalajara 75 0.53
Country USA 9562 68.01
Country Mexico 3688 26.23
Country Canada 809 5.75
Gender F 7170 51.00
Gender M 6889 49.00
Homeowner Y 8444 60.06
Homeowner N 5615 39.94
MaritalStatus S 7193 51.16
MaritalStatus M 6866 48.84
ProductCategory Vegetables 1728 12.29
ProductCategory Snack Foods 1600 11.38
ProductCategory Dairy 903 6.42
ProductCategory Fruit 765 5.44
ProductCategory Meat 761 5.41
ProductCategory Jams and Jellies 588 4.18
ProductCategory Baking Goods 484 3.44
ProductCategory Bread 425 3.02
ProductCategory Breakfast Foods 417 2.97
ProductCategory Canned Soup 404 2.87
ProductCategory Bathroom Products 365 2.60
ProductCategory Beer and Wine 356 2.53
ProductCategory Electrical 355 2.53
ProductCategory Candy 352 2.50
ProductCategory Paper Products 345 2.45
ProductCategory Frozen Desserts 323 2.30
ProductCategory Specialty 289 2.06
ProductCategory Starchy Foods 277 1.97
ProductCategory Hot Beverages 226 1.61
ProductCategory Kitchen Products 217 1.54
ProductCategory Magazines 202 1.44
ProductCategory Eggs 198 1.41
ProductCategory Hygiene 197 1.40
ProductCategory Pizza 194 1.38
ProductCategory Pain Relievers 192 1.37
ProductCategory Cleaning Supplies 189 1.34
ProductCategory Pure Juice Beverages 165 1.17
ProductCategory Carbonated Beverages 154 1.10
ProductCategory Side Dishes 153 1.09
ProductCategory Plastic Products 141 1.00
ProductCategory Drinks 135 0.96
ProductCategory Hardware 129 0.92
ProductCategory Frozen Entrees 118 0.84
ProductCategory Seafood 102 0.73
ProductCategory Cold Remedies 93 0.66
ProductCategory Canned Tuna 87 0.62
ProductCategory Decongestants 85 0.60
ProductCategory Canned Clams 53 0.38
ProductCategory Packaged Vegetables 48 0.34
ProductCategory Candles 45 0.32
ProductCategory Canned Anchovies 44 0.31
ProductCategory Miscellaneous 42 0.30
ProductCategory Canned Sardines 40 0.28
ProductCategory Canned Shrimp 38 0.27
ProductCategory Canned Oysters 35 0.25
ProductDepartment Produce 1994 14.18
ProductDepartment Snack Foods 1600 11.38
ProductDepartment Household 1420 10.10
ProductDepartment Frozen Foods 1382 9.83
ProductDepartment Baking Goods 1072 7.63
ProductDepartment Canned Foods 977 6.95
ProductDepartment Dairy 903 6.42
ProductDepartment Health and Hygiene 893 6.35
ProductDepartment Deli 699 4.97
ProductDepartment Beverages 680 4.84
ProductDepartment Baked Goods 425 3.02
ProductDepartment Alcoholic Beverages 356 2.53
ProductDepartment Snacks 352 2.50
ProductDepartment Starchy Foods 277 1.97
ProductDepartment Periodicals 202 1.44
ProductDepartment Eggs 198 1.41
ProductDepartment Breakfast Foods 188 1.34
ProductDepartment Canned Products 109 0.78
ProductDepartment Seafood 102 0.73
ProductDepartment Meat 89 0.63
ProductDepartment Checkout 82 0.58
ProductDepartment Carousel 59 0.42
ProductFamily Food 10153 72.22
ProductFamily Non-Consumable 2656 18.89
ProductFamily Drink 1250 8.89
StateorProvince WA 4567 32.48
StateorProvince CA 2733 19.44
StateorProvince OR 2262 16.09
StateorProvince Zacatecas 1297 9.23
StateorProvince DF 815 5.80
StateorProvince BC 809 5.75
StateorProvince Yucatan 654 4.65
StateorProvince Veracruz 464 3.30
StateorProvince Guerrero 383 2.72
StateorProvince Jalisco 75 0.53
# Tính thống kê mô tả đầy đủ theo từng biến định tính
descriptive_stats_full <- big_tbl %>%
  group_by(Bien) %>%
  summarise(
    Mean    = mean(So_luong, na.rm = TRUE),
    StdDev  = sd(So_luong, na.rm = TRUE),
    Min     = min(So_luong, na.rm = TRUE),
    Q1      = quantile(So_luong, 0.25, na.rm = TRUE),
    Median  = quantile(So_luong, 0.5, na.rm = TRUE),
    Q3      = quantile(So_luong, 0.75, na.rm = TRUE),
    Max     = max(So_luong, na.rm = TRUE)
  )

# Hiển thị bảng đẹp
kable(descriptive_stats_full,
      digits = 2,
      col.names = c("Biến", "Trung bình", "Độ lệch chuẩn", "Min", "Q1", "Trung vị", "Q3", "Max"),
      caption = "Thống kê mô tả đầy đủ số lượng các mức theo từng biến định tính")
Thống kê mô tả đầy đủ số lượng các mức theo từng biến định tính
Biến Trung bình Độ lệch chuẩn Min Q1 Trung vị Q3 Max
AnnualIncome 1757.38 1511.35 273 635.50 1234.5 2550.00 4601
City 611.26 370.75 75 285.00 633.0 870.50 1386
Country 4686.33 4461.08 809 2248.50 3688.0 6625.00 9562
Gender 7029.50 198.70 6889 6959.25 7029.5 7099.75 7170
Homeowner 7029.50 2000.41 5615 6322.25 7029.5 7736.75 8444
MaritalStatus 7029.50 231.22 6866 6947.75 7029.5 7111.25 7193
ProductCategory 312.42 358.15 35 102.00 197.0 356.00 1728
ProductDepartment 639.05 569.43 59 190.50 390.5 958.50 1994
ProductFamily 4686.33 4786.18 1250 1953.00 2656.0 6404.50 10153
StateorProvince 1405.90 1393.40 75 511.50 812.0 2020.75 4567

Nhận xét thống kê mô tả các biến định lượng:

  • AnnualIncome (Thu nhập hàng năm): Trung bình khoảng 1,757, với độ lệch chuẩn lớn (1,511), cho thấy sự chênh lệch thu nhập đáng kể trong tập khách hàng. Phân phối thu nhập có xu hướng lệch phải, với phần lớn khách có thu nhập thấp đến trung bình (Q1 = 635.5, Q3 = 2,550), trong khi một nhóm nhỏ có thu nhập rất cao (max = 4,601).

  • City (Số lượng khách theo thành phố): Trung bình là 611, dao động từ 75 đến 1,386. Điều này cho thấy số lượng khách phân bố không đồng đều giữa các thành phố, có nơi tập trung rất cao, nơi thì rất ít.

  • Country (Phân bổ theo quốc gia): Trung bình 4,686 với độ lệch chuẩn lớn (4,461), phản ánh sự mất cân đối mạnh giữa các quốc gia. Phần lớn khách hàng tập trung tại một vài quốc gia chính (như USA), các quốc gia khác chiếm tỷ trọng nhỏ.

  • Gender, Homeowner, MaritalStatus: Các biến dạng phân loại (được mã hóa số) có trung bình và trung vị gần nhau (~7,029), cho thấy phân phối khá đồng đều giữa các nhóm (giới tính, tình trạng hôn nhân, sở hữu nhà).

  • ProductCategory: Trung bình 312 với độ lệch chuẩn 358, cho thấy mức độ đa dạng cao giữa các danh mục sản phẩm.

  • ProductDepartment: Có độ phân tán lớn (std = 569), giá trị lớn nhất lên tới 1,994 sản phẩm, cho thấy một số phòng ban có rất nhiều sản phẩm, trong khi các phòng ban khác có số lượng ít.

  • ProductFamily: Trung bình 4,686 và độ lệch chuẩn cao (4,786), dao động từ 1,250 đến 10,153. Sự chênh lệch này cho thấy sự khác biệt rõ rệt về số lượng giữa các nhóm sản phẩm tiêu dùng.

  • StateorProvince: Trung bình 1,405 và độ lệch chuẩn cao (1,393), với min = 75 và max = 4,567. Điều này cho thấy sự phân bố khách hàng không đồng đều giữa các bang hoặc tỉnh, phản ánh thị trường tập trung ở một số khu vực nhất định.

LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSB0deG6p24gMSINCmF1dGhvcjogIkzDqiBUaOG7iyBOZ+G7jWMgw4FuaCINCmRhdGU6ICIyMDI1LTA1LTE2Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jOiB0cnVlDQogIHBkZl9kb2N1bWVudDoNCiAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXgNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQo8c3R5bGU+DQpib2R5IHsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBzYW5zLXNlcmlmOw0KICBmb250LXNpemU6IDE2cHg7DQogIHRleHQtYWxpZ246IGp1c3RpZnk7DQogIGxpbmUtaGVpZ2h0OiAxLjU7DQp9DQpoMiB7DQogIGNvbG9yOiByZWQ7DQp9DQpoMyB7DQogIGNvbG9yOiBkYXJrYmx1ZTsNCn0NCjwvc3R5bGU+DQoNCiMgKipCw4BJIFThuqxQIDEqKg0KDQoqKlTDk00gVOG6rlQgQ1Xhu5BOIFPDgUNIOiAyMDE5X0dlbmVyYWxpemVkIExpbmVhciBNb2RlbHMgV2l0aCBFeGFtcGxlcyBpbiBSXzk3ODE0NDE5MDExNzAucGRmKioNCg0KKipN4bukQyBUScOKVToqKiBUw6BpIGxp4buHdSBuw6B5IHTDs20gdOG6r3QgY8OhYyBjaOG7pyDEkeG7gSBjaMOtbmggdsOgIGPDoWMgw70gdMaw4bufbmcgcXVhbiB0cuG7jW5nIMSRxrDhu6NjIHRyw6xuaCBiw6B5IHRyb25nIGPDoWMgY2jGsMahbmcgxJHhuqd1IHRpw6puIHbDoCBjw6FjIHBo4bqnbiDEkcaw4bujYyB0csOtY2ggZOG6q24gY+G7p2EgY3Xhu5FuIHPDoWNoICJHZW5lcmFsaXplZCBMaW5lYXIgTW9kZWxzIFdpdGggRXhhbXBsZXMgaW4gUiIsIHThuq1wIHRydW5nIHbDoG8gY8OhYyBraMOhaSBuaeG7h20gduG7gSBtw7QgaMOsbmggdGjhu5FuZyBrw6osIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIHbDoCBjw6FjIG3DtCBow6xuaCB0dXnhur9uIHTDrW5oIHThu5VuZyBxdcOhdCwgY8WpbmcgbmjGsCBjw6FjIHBoxrDGoW5nIHBow6FwIGNo4bqpbiDEkW/DoW4gdsOgIMaw4bubYyBsxrDhu6NuZyBsacOqbiBxdWFuLg0KDQoqKkPDoWMgbuG7mWkgZHVuZyBsacOqbiBxdWFuIMSR4bq/biB04burbmcgY2jGsMahbmc6KioNCg0KIyMgKipDSMavxqBORyAxOiBNw5QgSMOMTkggVEjhu5BORyBLw4ogKFN0YXRpc3RpY2FsIE1vZGVscykqKg0KDQojIyMgKioxLjEuIEdp4bubaSB0aGnhu4d1KioNCiAgICANCiAgQ2jGsMahbmcgbsOgeSBnaeG7m2kgdGhp4buHdSBraMOhaSBuaeG7h20gY8ahIGLhuqNuIHbhu4EgbcO0IGjDrG5oIHRo4buRbmcga8OqIG5oxrAgbeG7mXQgY8OhY2ggxJHhu4MgbcO0IHThuqMgY+G6oyBjw6FjIMSR4bq3YyDEkWnhu4NtIG5n4bqrdSBuaGnDqm4gdsOgIGPDsyBo4buHIHRo4buRbmcgY+G7p2EgZOG7ryBsaeG7h3UuIE7DsyBuaOG6pW4gbeG6oW5oIHThuqdtIHF1YW4gdHLhu41uZyBj4bunYSB2aeG7h2Mgc+G7rSBk4bulbmcgY8OhYyBtw7QgaMOsbmggxJHhu4MgcGjDom4gdMOtY2ggZOG7ryBsaeG7h3UgKCJEYXRhIGFuYWx5c2lzOiBUaGUgbmVlZCBmb3IgbW9kZWxzPyIgLSBSZWVzZSwgMTk4NikuDQogIA0KIyMjICoqMS4yLiBDw6FjaCBiaeG7g3UgZGnhu4VuIGThu68gbGnhu4d1KioNCg0KICBE4buvIGxp4buHdSDEkcaw4bujYyB0csOsbmggYsOgeSB0aMO0bmcgcXVhIGPDoWMgdsOtIGThu6UgKG5oxrAgZOG7ryBsaeG7h3UgRkVWIOKAkyBkdW5nIHTDrWNoIHBo4buVaSk6DQoNCi0gICBBZ2U6IHR14buVaSAoc+G7kSkNCg0KLSAgIEZFVjogZHVuZyB0w61jaCB0aOG7nyByYSAobMOtdCkNCg0KLSAgIEh0OiBjaGnhu4F1IGNhbyAoY20pDQoNCi0gICBHZW5kZXI6IGdp4bubaSB0w61uaCAoRi9NKQ0KDQotICAgU21va2U6IGjDunQgdGh14buRYyAoMC8xKQ0KDQogIEJp4bq/biBz4buRIMSRxrDhu6NjIGNoaWEgdGjDoG5oOg0KDQotICAgKipCaeG6v24gbGnDqm4gdOG7pWMqKiAocXVhbnRpdGF0aXZlKSDihpIgY292YXJpYXRlcy4NCg0KLSAgICoqQmnhur9uIHBow6JuIGxv4bqhaSoqIChxdWFsaXRhdGl2ZSkg4oaSIGZhY3RvcnMuDQoNCiMjIyAqKjEuMy4gQmnhu4N1IMSR4buTIHbDoCB0cuG7sWMgcXVhbiBow7NhKioNCg0KICAqKlBsb3R0aW5nKiogbMOgIGLGsOG7m2MgxJHhuqd1IMSR4buDIGhp4buDdSBk4buvIGxp4buHdSwgcGjDoXQgaGnhu4duIHh1IGjGsOG7m25nIHbDoCBt4buRaSBxdWFuIGjhu4cuDQoNCiMjIyAqKjEuNC4gTcOjIGjDs2EgYmnhur9uIHBow6JuIGxv4bqhaSoqDQoNCiAgQmnhur9uIHBow6JuIGxv4bqhaSBwaOG6o2kgxJHGsOG7o2MgbcOjIGjDs2EgdGjDoG5oIHPhu5EgxJHhu4Mgc+G7rSBk4bulbmcgdHJvbmcgbcO0IGjDrG5oIHRo4buRbmcga8OqLg0KDQogIETDuW5nIGJp4bq/biBnaeG6oyAoZHVtbXkgdmFyaWFibGVzKToNCg0KLSAgIFbhu5tpIGJp4bq/biBjw7MgayBt4bupYyDihpIgY+G6p24ga+KIkjEgYmnhur9uIGdp4bqjLg0KDQojIyMgKioxLjUuIE3DtCBow6xuaCB0aOG7kW5nIGvDqiBn4buTbSAyIHRow6BuaCBwaOG6p24qKg0KDQogIEjhu4cgdGjhu5FuZzogbcO0IHThuqMgbeG7kWkgcXVhbiBo4buHIGdp4buvYSBr4buzIHbhu41uZyBjw6FjIGJp4bq/biBnaeG6o2kgdGjDrWNoOg0KDQokJA0KXG11X2kgPSBcbWF0aGJie0V9W3lfaV0gPSBmKFxiZXRhXzAgKyBcYmV0YV8xIHhfezFpfSArIFxjZG90cyArIFxiZXRhX3AgeF97cGl9KQ0KJCQNCg0KIyMjICoqMS43LiBEaeG7hW4gZ2nhuqNpIG3DtCBow6xuaCoqDQoNCiAgSOG7hyBz4buRIGjhu5NpIHF1eSBcKFxiZXRhX2pcKTogdGhheSDEkeG7lWkgdHJ1bmcgYsOsbmggY+G7p2EgXCh5XCkga2hpIFwoeF9qXCkgdMSDbmcgMSDEkcahbiB24buLIChnaeG7ryBjw6FjIGJp4bq/biBraMOhYyBj4buRIMSR4buLbmgpLg0KDQojIyMgKioxLjguIEFsbCBNb2RlbHMgQXJlIFdyb25nLCBidXQgU29tZSBBcmUgVXNlZnVsKioNCg0KICBN4buZdCDDvSB0xrDhu59uZyBxdWFuIHRy4buNbmcgxJHGsOG7o2MgdHLDrWNoIGThuqtuIHThu6sgbeG7mXQgbmd14buTbiBraMOhYyAoa2jDtG5nIMSRxrDhu6NjIGN1bmcgY+G6pXAgxJHhuqd5IMSR4bunIHRyb25nIHRyw61jaCDEkW/huqFuKSBsw6AgY8OhYyBtw7QgaMOsbmggbMOgIHPhu7EgxJHGoW4gZ2nhuqNuIGjDs2EgdGjhu7FjIHThur8gdsOgIGRvIMSRw7Mga2jDtG5nIGJhbyBnaeG7nSBob8OgbiB0b8OgbiBjaMOtbmggeMOhYywgbmjGsG5nIGNow7puZyBjw7MgdGjhu4MgbMOgIGPDtG5nIGPhu6UgY8OzIGdpw6EgdHLhu4sgxJHhu4MgaGnhu4N1IGThu68gbGnhu4d1Lg0KDQojIyMgKioxLjkuIE3hu6VjIMSRw61jaCBj4bunYSBtw7QgaMOsbmggdGjhu5FuZyBrw6oqKg0KDQogIE3hu6VjIMSRw61jaCBj4bunYSBt4buZdCBtw7QgaMOsbmgg4bqjbmggaMaw4bufbmcgxJHhur9uIGPDoWNoIG7DsyDEkcaw4bujYyBwaMOhdCB0cmnhu4NuLiBDw6FjIG3hu6VjIMSRw61jaCBjw7MgdGjhu4MgYmFvIGfhu5NtIG3DtCB04bqjLCBk4buxIMSRb8OhbiB2w6AgaGnhu4N1IG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgY8OhYyBiaeG6v24uDQoNCiMjIyAqKjEuMTAuIMSQ4buZIGNow61uaCB4w6FjIHNvIHbhu5tpIHPhu7EgxJHGoW4gZ2nhuqNuKioNCg0KICBDw7Mgc+G7sSDEkcOhbmggxJHhu5VpIGdp4buvYSDEkeG7mSBjaMOtbmggeMOhYyBj4bunYSBt4buZdCBtw7QgaMOsbmggKGto4bqjIG7Eg25nIHBow7kgaOG7o3AgY2jhurd0IGNo4bq9IHbhu5tpIGThu68gbGnhu4d1KSB2w6Agc+G7sSDEkcahbiBnaeG6o24gY+G7p2EgbsOzIChz4buRIGzGsOG7o25nIHRoYW0gc+G7kSkuIFZp4buHYyBs4buxYSBjaOG7jW4gbcO0IGjDrG5oIHRoxrDhu51uZyBsacOqbiBxdWFuIMSR4bq/biB2aeG7h2MgY8OibiBi4bqxbmcgaGFpIHnhur91IHThu5EgbsOgeS4NCiAgDQojIyMgKioxLjExLiBUaOG7sWMgbmdoaeG7h20gc28gduG7m2kgbmdoacOqbiBj4bupdSBxdWFuIHPDoXQqKg0KDQogIEN14buRbiBzw6FjaCBwaMOibiBiaeG7h3QgZ2nhu69hIHRo4buxYyBuZ2hp4buHbSAobsahaSBjw7MgdGjhu4Mgc3V5IGx14bqtbiBuZ3V5w6puIG5ow6JuIC0ga+G6v3QgcXXhuqMpIHbDoCBuZ2hpw6puIGPhu6l1IHF1YW4gc8OhdCAobsahaSBjaOG7iSBjw7MgdGjhu4MgdGhp4bq/dCBs4bqtcCBt4buRaSBsacOqbiBo4buHKSANCg0KIyMjICoqMS4xMi4gVGh1IHRo4bqtcCBk4buvIGxp4buHdSB2w6Aga2jhuqMgbsSDbmcga2jDoWkgcXXDoXQgaMOzYSoqDQoNCi0gICBL4bq/dCBxdeG6oyBtw7QgaMOsbmggY2jhu4kgw6FwIGThu6VuZyBjaG8gcXXhuqduIHRo4buDIG3DoCBk4buvIGxp4buHdSDEkcaw4bujYyB0aHUgdGjhuq1wIHThu6sgxJHDsy4NCg0KLSAgIEtow7RuZyBuw6puIG5nb+G6oWkgc3V5IGvhur90IHF14bqjIG5nb8OgaSBwaOG6oW0gdmkgZ2nDoSB0cuG7iyDEkcOjIHF1YW4gc8OhdC4NCg0KLS0tDQoNCiMjICoqQ0jGr8agTkcgMjogTcOUIEjDjE5IIEjhu5JJIFFVWSBUVVnhur5OIFTDjU5IIChMaW5lYXIgUmVncmVzc2lvbiBNb2RlbHMpKioNCg0KIyMjICoqMi4xLiBHaeG7m2kgdGhp4buHdSB2w6AgdOG7lW5nIHF1YW4qKg0KDQpNw7QgaMOsbmggaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggbMOgIGxv4bqhaSBwaOG7lSBiaeG6v24gbmjhuqV0IHRyb25nIHThuqV0IGPhuqMgY8OhYyBtw7QgaMOsbmggaOG7k2kgcXV5Lg0KDQrEkMOieSBsw6AgbeG7mXQgdHLGsOG7nW5nIGjhu6NwIMSR4bq3YyBiaeG7h3QgY+G7p2EgbcO0IGjDrG5oIHR1eeG6v24gdMOtbmggdOG7lW5nIHF1w6F0IChHTE0pLg0KDQpDaMawxqFuZyBuw6B5IGdp4bubaSB0aGnhu4d1Og0KDQotICAgS2jDoWkgbmnhu4dtIHbDoCBrw70gaGnhu4d1IGPhu6dhIG3DtCBow6xuaC4NCg0KLSAgIMav4bubYyBsxrDhu6NuZyBiw6xuaCBwaMawxqFuZyB04buRaSB0aGnhu4N1IChPTFMpLg0KDQotICAgSOG7k2kgcXV5IMSRxqFuIHbDoCBo4buTaSBxdXkgYuG7mWkuDQoNCi0gICBEaeG7hW4gZ2nhuqNpIGjhu4cgc+G7kSBo4buTaSBxdXkuDQoNCi0gICBTdXkgbHXhuq1uIHRo4buRbmcga8OqLg0KDQotICAgUGjDom4gdMOtY2ggcGjGsMahbmcgc2FpIChBTk9WQSkuDQoNCi0gICBTbyBzw6FuaCBtw7QgaMOsbmggbOG7k25nIHbDoCBraMO0bmcgbOG7k25nLg0KDQotICAgQ2jhu41uIG3DtCBow6xuaCB04buRdCBuaOG6pXQNCg0KIyMjICoqMi4yIMSQ4buLbmggbmdoxKlhIG3DtCBow6xuaCBo4buTaSBxdXkgdHV54bq/biB0w61uaCoqDQoNCioqKsSQ4buLbmggbmdoxKlhOioqKiBNw7QgaMOsbmggaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggbcO0IHThuqMgbeG7kWkgcXVhbiBo4buHIGdp4buvYSBiaeG6v24gcGjhuqNuIGjhu5NpIFwoeVwpIHbDoCBjw6FjIGJp4bq/biBnaeG6o2kgdGjDrWNoIFwoeF8xLCB4XzIsIFxsZG90cywgeF9wXCkgdGjDtG5nIHF1YSBt4buZdCBiaeG7g3UgdGjhu6ljIHR1eeG6v24gdMOtbmgsIGPDuW5nIHbhu5tpIG3hu5l0IGdp4bqjIMSR4buLbmggduG7gSBwaMOibiBwaOG7kWkgdsOgIHBoxrDGoW5nIHNhaSBj4bunYSBwaOG6p24gZMawLg0KDQpCaeG7g3UgZGnhu4VuIG3DtCBow6xuaDoNCg0KJCQNCnlfaSA9IFxiZXRhXzAgKyBcYmV0YV8xIHhfezFpfSArIFxiZXRhXzIgeF97Mml9ICsgXGNkb3RzICsgXGJldGFfcCB4X3twaX0gKyBcdmFyZXBzaWxvbl9pDQokJA0KDQpW4bubaSBnaeG6oyDEkeG7i25oOg0KDQotIFwoXHZhcmVwc2lsb25faSBcc2ltIFxtYXRoY2Fse059KDAsIFxzaWdtYV4yKVwpDQoNCi0gQ8OhYyBwaOG6p24gZMawIFwoXHZhcmVwc2lsb25faVwpIGzDoCDEkeG7mWMgbOG6rXAgdsOgIGPDsyBwaMawxqFuZyBzYWkga2jDtG5nIMSR4buVaS4NCg0KLS0tDQoNCioqKkPhuqV1IHRyw7pjIG3DtCBow6xuaDoqKioNCg0KICBNw7QgaMOsbmggZ+G7k20gMiB0aMOgbmggcGjhuqduOg0KIA0KKioxLiBOZ+G6q3Ugbmhpw6puIChyYW5kb20gY29tcG9uZW50KToqKg0KDQpQaMawxqFuZyBzYWkgY+G7p2EgXCh5X2lcKSDEkcaw4bujYyBnaeG6oyDEkeG7i25oIGzDoDoNCg0KJCQNClx0ZXh0e1Zhcn1beV9pXSA9IFxmcmFje1xzaWdtYV4yfXt3X2l9DQokJA0KDQpUcm9uZyDEkcOzOg0KDQotIFwoXHNpZ21hXjJcKSBsw6AgcGjGsMahbmcgc2FpIGNoxrBhIGJp4bq/dC4NCg0KLSBcKHdfaVwpIGzDoCB0cuG7jW5nIHPhu5EgKHByaW9yIHdlaWdodCksIHRoxrDhu51uZyBsw6AgXCgxXCkgduG7m2kgbeG7jWkgXChpXCkgdHJvbmcgbcO0IGjDrG5oIGjhu5NpIHF1eSB0aMO0bmcgdGjGsOG7nW5nLg0KDQotLS0NCg0KKioyLiBI4buHIHRo4buRbmcgKHN5c3RlbWF0aWMgY29tcG9uZW50KToqKg0KDQokJA0KXG11X2kgPSBcbWF0aGJie0V9W3lfaV0gPSBcYmV0YV8wICsgXHN1bV97aj0xfV57cH0gXGJldGFfaiB4X3tqaX0NCiQkDQoNCi0tLQ0KDQoqKipDw6FjIGxv4bqhaSBtw7QgaMOsbmggaOG7k2kgcXV5IMSR4bq3YyBiaeG7h3Q6KioqDQoNCi0gKipTaW1wbGUgTGluZWFyIFJlZ3Jlc3Npb24qKjogXChwID0gMVwpLCBtw7QgaMOsbmggY2jhu4kgY8OzIG3hu5l0IGJp4bq/biBnaeG6o2kgdGjDrWNoLg0KDQotICoqT3JkaW5hcnkgTGluZWFyIFJlZ3Jlc3Npb24qKjogdOG6pXQgY+G6oyBjw6FjIHRy4buNbmcgc+G7kSBcKHdfaSA9IDFcKSwgdOG7qWMgbMOgIHBoxrDGoW5nIHNhaSDEkeG7k25nIG5o4bqldC4NCg0KLSAqKk11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uKio6IFwocCA+IDFcKSwgY8OzIG5oaeG7gXUgYmnhur9uIGdp4bqjaSB0aMOtY2ggdHJvbmcgbcO0IGjDrG5oLg0KDQotICoqTm9ybWFsIExpbmVhciBSZWdyZXNzaW9uKio6IGdp4bqjIMSR4buLbmggcGjDom4gcGjhu5FpIGNodeG6qW4gY2hvIFwoeV9pXCk6DQoNCiAgJCQNCiAgeV9pIFxzaW0gXG1hdGhjYWx7Tn1cbGVmdChcbXVfaSwgXGZyYWN7XHNpZ21hXjJ9e3dfaX1ccmlnaHQpDQogICQkDQoNCiMjIyAqKjIuMyDGr+G7m2MgbMaw4bujbmcgYsOsbmggcGjGsMahbmcgdOG7kWkgdGhp4buDdSAoTGVhc3QgU3F1YXJlcyBFc3RpbWF0aW9uKSoqDQoNCioqTeG7pWMgdGnDqnU6KioNCg0Kw6xtIGPDoWMgXChcaGF0e1xiZXRhfV9qXCkgc2FvIGNobyBow6BtIG3hu6VjIHRpw6p1IGzDoCB04buVbmcgYsOsbmggcGjGsMahbmcgcGjhuqduIGTGsCBjw7MgdHLhu41uZyBz4buRICgqKlJTUyoqKSDEkcaw4bujYyB04buRaSB0aGnhu4N1IGjDs2E6DQoNCiQkDQpSU1MgPSBcc3VtX3tpPTF9XntufSB3X2kgXGxlZnQoeV9pIC0gXG11X2lccmlnaHQpXjINCiQkDQoNClRyb25nIMSRw7M6DQoNCi0gXCh3X2lcKSBsw6AgdHLhu41uZyBz4buRIHF1YW4gc8OhdCB0aOG7qSBcKGlcKQ0KLSBcKHlfaVwpIGzDoCBnacOhIHRy4buLIHRo4buxYyB04bq/DQotIFwoXG11X2kgPSBcbWF0aGJie0V9W3lfaV0gPSBcYmV0YV8wICsgXHN1bV97aj0xfV57cH0gXGJldGFfaiB4X3tqaX1cKQ0KDQotLS0NCg0KKipUcm9uZyBo4buTaSBxdXkgxJHGoW4gKHAgPSAxKToqKg0KDQrGr+G7m2MgbMaw4bujbmcgaOG7hyBz4buRIGjhu5NpIHF1eSDEkcaw4bujYyB0w61uaCBuaMawIHNhdToNCg0KJCQNClxoYXR7XGJldGF9XzEgPSBcZnJhY3tcc3VtICh4X2kgLSBcYmFye3h9KSh5X2kgLSBcYmFye3l9KX17XHN1bSAoeF9pIC0gXGJhcnt4fSleMn0NCiQkDQoNCiQkDQpcaGF0e1xiZXRhfV8wID0gXGJhcnt5fSAtIFxoYXR7XGJldGF9XzEgXGJhcnt4fQ0KJCQNCg0KLS0tDQoNCiMjIyAqKjIuNCDGr+G7m2MgbMaw4bujbmcgdHJvbmcgaOG7k2kgcXV5IGLhu5lpIChuaGnhu4F1IGJp4bq/bikqKg0KDQoqKkThuqFuZyBtYSB0cuG6rW4gY+G7p2EgbcO0IGjDrG5oOioqDQoNCk3DtCBow6xuaCBo4buTaSBxdXkgdHV54bq/biB0w61uaCBjw7MgdGjhu4MgxJHGsOG7o2Mgdmnhur90IGTGsOG7m2kgZOG6oW5nIG1hIHRy4bqtbjoNCg0KJCQNCnkgPSBYXGJldGEgKyBcdmFyZXBzaWxvbg0KJCQNCg0KVHJvbmcgxJHDszoNCg0KLSBcKHlcKTogdmVjdG9yIHBo4bqjbiBo4buTaSAoY+G7oSBcKG4gXHRpbWVzIDFcKSkNCi0gXChYXCk6IG1hIHRy4bqtbiB0aGnhur90IGvhur8gKGRlc2lnbiBtYXRyaXgpIGvDrWNoIHRoxrDhu5tjIFwobiBcdGltZXMgKHArMSlcKSwgduG7m2kgY+G7mXQgxJHhuqd1IHRpw6puIHRvw6BuIHPhu5EgMSAo4bupbmcgduG7m2kgaOG7hyBz4buRIGNo4bq3biBcKFxiZXRhXzBcKSksIGPDoWMgY+G7mXQgY8OybiBs4bqhaSBsw6AgZ2nDoSB0cuG7iyBj4bunYSBjw6FjIGJp4bq/biBnaeG6o2kgdGjDrWNoIFwoeF9qXCkNCi0gXChcYmV0YVwpOiB2ZWN0b3IgaOG7hyBz4buRIGjhu5NpIHF1eSAoY+G7oSBcKChwKzEpIFx0aW1lcyAxXCkpDQotIFwoXHZhcmVwc2lsb24gXHNpbSBcbWF0aGNhbHtOfSgwLCBcc2lnbWFeMiBJKVwpOiB2ZWN0b3Igbmhp4buFdSBjw7MgcGjDom4gcGjhu5FpIGNodeG6qW4gxJFhIGJp4bq/biB24bubaSB0cnVuZyBiw6xuaCAwIHbDoCBwaMawxqFuZyBzYWkgXChcc2lnbWFeMiBJXCkNCg0KLS0tDQoNCioqxq/hu5tjIGzGsOG7o25nIE9MUzoqKg0KDQokJA0KXGhhdHtcYmV0YX0gPSAoWF5UIFcgWCleey0xfSBYXlQgVyB5DQokJA0KDQoqKlBo4bqnbiBkxrAgdsOgIHBoxrDGoW5nIHNhaSDGsOG7m2MgbMaw4bujbmc6KioNCg0KR2nDoSB0cuG7iyBk4buxIMSRb8OhbiAoZml0dGVkIHZhbHVlcyk6DQoNCiQkDQpcaGF0e1xtdX1faSA9IFxoYXR7eX1faSA9IFxoYXR7XGJldGF9XzAgKyBcc3VtX3tqPTF9XntwfSBcaGF0e1xiZXRhfV9qIHhfe2ppfQ0KJCQNCg0KLS0tDQoNCsav4bubYyBsxrDhu6NuZyBwaMawxqFuZyBzYWkgcGjhuqduIGTGsDoNCg0KJCQNCnNeMiA9IFxmcmFje1JTU317biAtIHAnfQ0KJCQNCg0KIyMjICoqMi41IFNhaSBz4buRIGNodeG6qW4gdsOgIGtob+G6o25nIHRpbiBj4bqteSoqDQoNCioqU2FpIHPhu5EgY2h14bqpbiBj4bunYSBcKFxoYXR7XGJldGF9X2pcKToqKg0KDQokJA0KU0UoXGhhdHtcYmV0YX1faikgPSBcc3FydHtzXnsyfSBcY2RvdCBcYmlnbCggWF57VH0gWCBcYmlncileey0xfV97amp9fQ0KJCQNCg0KKipLaG/huqNuZyB0aW4gY+G6rXkgY2hvIFwoXGhhdHtcYmV0YX1falwpOioqDQoNCiQkDQpcaGF0e1xiZXRhfV9qIFxwbSB0X3tcYWxwaGEvMiwgXCwgbiAtIHB9IFx0aW1lcyBTRShcaGF0e1xiZXRhfV9qKQ0KJCQNCg0KIyMjICoqMi42IFPhu60gZOG7pW5nIFIgxJHhu4MgaOG7k2kgcXV5KioNCg0KKipNw7QgaMOsbmggaMOzYToqKiAgbW9kZWwgPC0gbG0oeSB+IHgxICsgeDIsIGRhdGEgPSBkYXRhc2V0KQ0KDQoqKkvhur90IHF14bqjIG3DtCBow6xuaDoqKg0KDQogIHN1bW1hcnkobW9kZWwpDQoNCiAgY29uZmludChtb2RlbCkNCg0KICBhbm92YShtb2RlbCkNCg0KIyMjICoqMi43IERp4buFbiBnaeG6o2kgaOG7hyBz4buRIGjhu5NpIHF1eSoqDQoNCi0gXChcYmV0YV8wXCk6IGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggY+G7p2EgXCh5XCkga2hpIHThuqV0IGPhuqMgY8OhYyBiaeG6v24gXCh4X2ogPSAwXCkuDQoNCi0gXChcYmV0YV9qXCk6IG3hu6ljIHRoYXkgxJHhu5VpIGvhu7MgduG7jW5nIGPhu6dhIFwoeVwpIGtoaSBcKHhfalwpIHTEg25nIDEgxJHGoW4gduG7iywgZ2nhu68gY8OhYyBiaeG6v24ga2jDoWMga2jDtG5nIMSR4buVaS4NCg0KIyMjICoqMi44IFN1eSBsdeG6rW4gdGjhu5FuZyBrw6oqKg0KDQoqKkdp4bqjIHPhu60ga2nhu4NtIMSR4buLbmggduG7m2kqKg0KDQokJA0KSF8wOiBcYmV0YV9qID0gMA0KJCQNCg0KKip2w6AgdGjhu5FuZyBrw6oga2nhu4NtIMSR4buLbmgqKg0KDQokJA0KdCA9IFxmcmFje1xoYXR7XGJldGF9X2p9e1NFKFxoYXR7XGJldGF9X2opfSBcc2ltIHRfe24tcH0NCiQkDQoNClRyb25nIMSRw7M6DQoNCi0gXChcaGF0e1xiZXRhfV9qXCkgbMOgIGjhu4cgc+G7kSDGsOG7m2MgbMaw4bujbmcgY+G7p2EgYmnhur9uIFwoalwpLA0KDQotIFwoU0UoXGhhdHtcYmV0YX1failcKSBsw6Agc2FpIHPhu5EgY2h14bqpbiBj4bunYSBcKFxoYXR7XGJldGF9X2pcKSwNCg0KLSBcKHRfe24tcH1cKSBsw6AgcGjDom4gcGjhu5FpIHQgduG7m2kgXChuLXBcKSBi4bqtYyB04buxIGRvLg0KDQojIyMgKioyLjkgUGjDom4gdMOtY2ggcGjGsMahbmcgc2FpIChBTk9WQSkqKg0KDQoqKkdpw6EgdHLhu4sgdOG7lW5nIHBoxrDGoW5nIHNhaSBcKFRTU1wpIMSRxrDhu6NjIHTDrW5oIHRoZW8gY8O0bmcgdGjhu6ljOioqDQoNCiQkDQpUU1MgPSBcc3VtX3tpPTF9XntufSAoeV9pIC0gXGJhcnt5fSleMg0KJCQNCg0KKipU4buVbmcgcGjGsMahbmcgc2FpIMSRxrDhu6NjIHBow6JuIHTDrWNoIHRow6BuaCBoYWkgcGjhuqduOioqDQoNCiQkDQpUU1MgPSBTU1IgKyBSU1MNCiQkDQoNClRyb25nIMSRw7M6DQoNCi0gXChTU1JcKSBsw6AgdOG7lW5nIGLDrG5oIHBoxrDGoW5nIHBo4bqnbiBnaeG6o2kgdGjDrWNoIChFeHBsYWluZWQgU3VtIG9mIFNxdWFyZXMpLCDEkcaw4bujYyB0w61uaCBi4bqxbmc6DQoNCiQkDQpTU1IgPSBcc3VtX3tpPTF9XntufSAoXGhhdHt5fV9pIC0gXGJhcnt5fSleMg0KJCQNCg0KLSBcKFJTU1wpIGzDoCB04buVbmcgYsOsbmggcGjGsMahbmcgcGjhuqduIGTGsCAoUmVzaWR1YWwgU3VtIG9mIFNxdWFyZXMpLCDEkcaw4bujYyB0w61uaCBi4bqxbmc6DQoNCiQkDQpSU1MgPSBcc3VtX3tpPTF9XntufSAoeV9pIC0gXGhhdHt5fV9pKV4yDQokJA0KDQoqKkjhu4cgc+G7kSB4w6FjIMSR4buLbmggXChSXjJcKSDEkcaw4bujYyDEkeG7i25oIG5naMSpYSBsw6A6KioNCg0KJCQNClJeMiA9IFxmcmFje1NTUn17VFNTfSA9IDEgLSBcZnJhY3tSU1N9e1RTU30NCiQkDQoNCiMjIyAqKjIuMTAgU28gc8OhbmggbcO0IGjDrG5oIGzhu5NuZyAoTmVzdGVkIE1vZGVscykqKg0KDQoqKirEkOG7i25oIG5naMSpYToqKiogSGFpIG3DtCBow6xuaCDEkcaw4bujYyBn4buNaSBsw6AgbOG7k25nIG5oYXUgKG5lc3RlZCBtb2RlbHMpIGtoaSBtw7QgaMOsbmggxJHGoW4gZ2nhuqNuIGjGoW4gKHJlZHVjZWQgbW9kZWwpIGzDoCBt4buZdCB0csaw4budbmcgaOG7o3AgxJHhurdjIGJp4buHdCBj4bunYSBtw7QgaMOsbmggcGjhu6ljIHThuqFwIGjGoW4gKGZ1bGwgbW9kZWwpLCB04bupYyBsw6AgbsOzIMSRxrDhu6NjIHThuqFvIHJhIGLhurFuZyBjw6FjaCBsb+G6oWkgYuG7jyBt4buZdCBoYXkgbmhp4buBdSBiaeG6v24ga2jhu49pIG3DtCBow6xuaCDEkeG6p3kgxJHhu6cuDQoNCktp4buDbSDEkeG7i25oIEY6DQoNCiQkDQpGID0gXGZyYWN7KFJTU197XHRleHR7cmVkdWNlZH19IC0gUlNTX3tcdGV4dHtmdWxsfX0pIC8gKHBfe1x0ZXh0e2Z1bGx9fSAtIHBfe1x0ZXh0e3JlZHVjZWR9fSl9e3NeMl97XHRleHR7ZnVsbH19fQ0KJCQNCg0KVHJvbmcgxJHDszoNCg0KLSBcKFJTU197XHRleHR7cmVkdWNlZH19XCkgbMOgIHThu5VuZyBiw6xuaCBwaMawxqFuZyBwaOG6p24gZMawIGPhu6dhIG3DtCBow6xuaCByw7p0IGfhu41uLA0KDQotIFwoUlNTX3tcdGV4dHtmdWxsfX1cKSBsw6AgdOG7lW5nIGLDrG5oIHBoxrDGoW5nIHBo4bqnbiBkxrAgY+G7p2EgbcO0IGjDrG5oIMSR4bqneSDEkeG7pywNCg0KLSBcKHBfe1x0ZXh0e2Z1bGx9fVwpIHbDoCBcKHBfe1x0ZXh0e3JlZHVjZWR9fVwpIGzhuqduIGzGsOG7o3QgbMOgIHPhu5EgdGhhbSBz4buRIGPhu6dhIG3DtCBow6xuaCDEkeG6p3kgxJHhu6cgdsOgIG3DtCBow6xuaCByw7p0IGfhu41uLA0KDQotIFwoc14yX3tcdGV4dHtmdWxsfX1cKSBsw6AgxrDhu5tjIGzGsOG7o25nIHBoxrDGoW5nIHNhaSBwaOG6p24gZMawIGPhu6dhIG3DtCBow6xuaCDEkeG6p3kgxJHhu6csIMSRxrDhu6NjIHTDrW5oIGLhurFuZzoNCg0KJCQNCnNeMl97XHRleHR7ZnVsbH19ID0gXGZyYWN7UlNTX3tcdGV4dHtmdWxsfX19e24gLSBwX3tcdGV4dHtmdWxsfX19DQokJA0KDQp24bubaSBcKG5cKSBsw6Agc+G7kSBxdWFuIHPDoXQuDQoNCiMjIyAqKjIuMTEgU28gc8OhbmggbcO0IGjDrG5oIGtow7RuZyBs4buTbmcgKE5vbi1OZXN0ZWQgTW9kZWxzKSoqDQoNCioqKsSQ4buLbmggbmdoxKlhOioqKiBIYWkgbcO0IGjDrG5oIMSRxrDhu6NjIGfhu41pIGzDoCBraMO0bmcgbOG7k25nIChub24tbmVzdGVkKSBu4bq/dSBraMO0bmcgY8OzIG3DtCBow6xuaCBuw6BvIGzDoCBt4buZdCB0csaw4budbmcgaOG7o3AgxJHhurdjIGJp4buHdCAoc3VibW9kZWwpIGPhu6dhIG3DtCBow6xuaCBjw7JuIGzhuqFpLg0KDQoqKkFJQyoqIChBa2Fpa2UgSW5mb3JtYXRpb24gQ3JpdGVyaW9uKSBsw6AgY2jhu4kgc+G7kSBkw7luZyDEkeG7gyDEkcOhbmggZ2nDoSDEkeG7mSBwaMO5IGjhu6NwIGPhu6dhIG3DtCBow6xuaCwgxJHhu5NuZyB0aOG7nWkgcGjhuqF0IG3hu6ljIMSR4buZIHBo4bupYyB04bqhcCBj4bunYSBtw7QgaMOsbmg6DQoNCiQkDQpBSUMgPSAtMiBcY2RvdCBcZWxsKFxoYXR7XHRoZXRhfSkgKyAyaw0KJCQNCg0KdHJvbmcgxJHDszoNCg0KLSBcKFxlbGwoXGhhdHtcdGhldGF9KVwpIGzDoCBsb2ctbGlrZWxpaG9vZCB04bqhaSDGsOG7m2MgbMaw4bujbmcgTUxFIFwoXGhhdHtcdGhldGF9XCksDQoNCi0gXChrXCkgbMOgIHPhu5EgdGhhbSBz4buRIHRyb25nIG3DtCBow6xuaCAoYmFvIGfhu5NtIGPhuqMgaOG7hyBz4buRIGjhurFuZyBz4buRIFwoXGJldGFfMFwpKS4NCg0KLS0tDQoNCioqQklDKiogKEJheWVzaWFuIEluZm9ybWF0aW9uIENyaXRlcmlvbikgdMawxqFuZyB04buxIEFJQyBuaMawbmcgbeG7qWMgcGjhuqF0IMSR4buZIHBo4bupYyB04bqhcCBt4bqhbmggaMahbiwgxJHGsOG7o2MgdMOtbmggYuG6sW5nOg0KDQokJA0KQklDID0gLTIgXGNkb3QgXGVsbChcaGF0e1x0aGV0YX0pICsgXGxvZyhuKSBcY2RvdCBrDQokJA0KDQp0cm9uZyDEkcOzOg0KDQotIFwoblwpIGzDoCBrw61jaCB0aMaw4bubYyBt4bqrdSwNCg0KLSBcKGtcKSB2w6AgXChcZWxsKFxoYXR7XHRoZXRhfSlcKSBuaMawIHRyw6puLg0KDQoqKipOZ3V5w6puIHThuq9jIGNo4buNbiBtw7QgaMOsbmg6KioqDQoNCi0gQUlDL0JJQyBjw6BuZyBuaOG7jyBjw6BuZyB04buRdC4NCg0KLSBO4bq/dSBBSUMgY+G7p2EgbcO0IGjDrG5oIEEgPCBtw7QgaMOsbmggQiBraG/huqNuZyAyIMSRaeG7g20gdHLhu58gbMOqbiwgbcO0IGjDrG5oIEEgxJHGsOG7o2MgxrB1IHRpw6puIGjGoW4gxJHDoW5nIGvhu4MuDQoNCiMjIyAqKjIuMTIgTOG7sWEgY2jhu41uIG3DtCBow6xuaCB04buxIMSR4buZbmcgKEF1dG9tYXRlZCBNb2RlbCBTZWxlY3Rpb24pKioNCg0KKioqxJDhu4tuaCBuZ2jEqWE6KioqTOG7sWEgY2jhu41uIG3DtCBow6xuaCBsw6AgcXXDoSB0csOsbmggdMOsbSByYSB04bqtcCBo4bujcCBiaeG6v24gZ2nhuqNpIHRow61jaCB04buRdCBuaOG6pXQgKHBow7kgaOG7o3AsIMSRxqFuIGdp4bqjbikgxJHhu4MgbcO0IGjDrG5oIGjDs2EgYmnhur9uIHBo4bqjbiBo4buTaS4NCg0KQ8OzIG5oaeG7gXUgY2hp4bq/biBsxrDhu6NjIGzhu7FhIGNo4buNbiBtw7QgaMOsbmg6DQoNCi0gKipGb3J3YXJkIHNlbGVjdGlvbjoqKiBi4bqvdCDEkeG6p3UgdOG7qyBtw7QgaMOsbmggcuG7l25nLCB0aMOqbSBiaeG6v24gdOG7q25nIGLGsOG7m2MuDQoNCi0gKipCYWNrd2FyZCBlbGltaW5hdGlvbjoqKiBi4bqvdCDEkeG6p3UgdOG7qyBtw7QgaMOsbmggxJHhuqd5IMSR4bunLCBsb+G6oWkgYuG7jyB04burbmcgYmnhur9uLg0KDQotICoqU3RlcHdpc2Ugc2VsZWN0aW9uOioqIGvhur90IGjhu6NwIGPhuqMgdGjDqm0gdsOgIGLhu5t0IGJp4bq/biDhu58gbeG7l2kgYsaw4bubYy4NCg0KTeG7mXQgc+G7kSBow6BtIHPhu60gZOG7pW5nOg0KDQotIHN0ZXAoKTogY2jhu41uIG3DtCBow6xuaCB0aGVvIGjGsOG7m25nIGZvcndhcmQvYmFja3dhcmQvc3RlcHdpc2UuDQoNCi0gZHJvcDEoKSwgYWRkMSgpOiB0aMOqbSBob+G6t2MgYuG7m3QgYmnhur9uIHbhu5tpIGtp4buDbSDEkeG7i25oIEYuDQoNCi0gZXh0cmFjdEFJQygpOiB0cuG6oyB24buBIEFJQyB2w6Agc+G7kSB0aGFtIHPhu5EuDQoNCi0tLQ0KDQojIyAqKkNIxq/GoE5HIDM6IENI4bqoTiDEkE/DgU4gTcOUIEjDjE5IIEjhu5JJIFFVWSBUVVnhur5OIFTDjU5IIChMaW5lYXIgUmVncmVzc2lvbiBNb2RlbHM6IERpYWdub3N0aWNzIGFuZCBNb2RlbC1CdWlsZGluZykqKg0KDQojIyMgKiozLjEuIEdp4bubaSB0aGnhu4d1IHbDoCB04buVbmcgcXVhbioqDQoNClNhdSBraGkgeMOieSBk4buxbmcgbeG7mXQgbcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oLCBjw7RuZyB2aeG7h2Mga2jDtG5nIGvhur90IHRow7pjIOG7nyB2aeG7h2MgxrDhu5tjIGzGsOG7o25nIGPDoWMgaOG7hyBz4buRIGjhu5NpIHF1eSB2w6Aga2nhu4NtIMSR4buLbmggw70gbmdoxKlhIHRo4buRbmcga8OqLiBN4buZdCBixrDhu5tjIHF1YW4gdHLhu41uZyBraMO0bmcgdGjhu4MgdGhp4bq/dSBsw6AgY2jhuqluIMSRb8OhbiBtw7QgaMOsbmgg4oCTIHThu6ljIGzDoCDEkcOhbmggZ2nDoSB4ZW0gbcO0IGjDrG5oIMSRw6MgxJHGsOG7o2MgeMOieSBk4buxbmcgY8OzIHRo4buxYyBz4buxIHBow7kgaOG7o3AgduG7m2kgZOG7ryBsaeG7h3UgaGF5IGtow7RuZy4NCg0KQ2jhuqluIMSRb8OhbiBtw7QgaMOsbmggaOG7k2kgcXV5IGzDoCBt4buZdCBwaOG6p24gdGhp4bq/dCB54bq/dSB0cm9uZyBwaMOibiB0w61jaCBk4buvIGxp4buHdSB2w6wgbsOzIGdpw7pwIHRhOg0KDQotICAgWMOhYyBtaW5oIGPDoWMgZ2nhuqMgxJHhu4tuaCBjxqEgYuG6o24gY+G7p2EgbcO0IGjDrG5oIGjhu5NpIHF1eSB0dXnhur9uIHTDrW5oIGPDsyDEkcaw4bujYyB0aOG7j2EgbcOjbiBoYXkga2jDtG5nICh2w60gZOG7pSBuaMawIHF1YW4gaOG7hyB0dXnhur9uIHTDrW5oLCBwaMawxqFuZyBzYWkga2jDtG5nIMSR4buVaSwgcGjDom4gcGjhu5FpIGNodeG6qW7igKYpLg0KDQotICAgUGjDoXQgaGnhu4duIG5o4buvbmcgcXVhbiBzw6F0IGLhuqV0IHRoxrDhu51uZyBuaMawIMSRaeG7g20gbmdv4bqhaSBsYWkgKG91dGxpZXJzKSBob+G6t2MgxJFp4buDbSBjw7Mg4bqjbmggaMaw4bufbmcgbOG7m24gKGluZmx1ZW50aWFsIG9ic2VydmF0aW9ucykg4oCTIG5o4buvbmcgxJFp4buDbSBjw7MgdGjhu4MgYsOzcCBtw6lvIGvhur90IHF14bqjIMaw4bubYyBsxrDhu6NuZyBob+G6t2Mga2nhu4NtIMSR4buLbmguDQoNCi0gICDEkMOhbmggZ2nDoSDEkeG7mSB0aW4gY+G6rXkgY+G7p2EgY8OhYyBo4buHIHPhu5EgxrDhu5tjIGzGsOG7o25nLg0KDQrEkOG7gSB4deG6pXQgY8OhY2ggY+G6o2kgdGhp4buHbiBtw7QgaMOsbmgsIHbDrSBk4bulOiBiaeG6v24gxJHhu5VpIGJp4bq/biwgdGjDqm0gaG/hurdjIGLhu5t0IGJp4bq/biBnaeG6o2kgdGjDrWNoLCBz4butIGThu6VuZyBtw7QgaMOsbmggcGhpIHR1eeG6v24gaG/hurdjIHThu5VuZyBxdcOhdCAoR0xNKSB0aGF5IHRo4bq/Lg0KDQpO4bq/dSBi4buPIHF1YSBixrDhu5tjIG7DoHksIG5nxrDhu51pIHBow6JuIHTDrWNoIGThu4UgcsahaSB2w6BvIGLhuqt5IGPhu6dhIHZp4buHYyDigJxwaMO5IGjhu6NwIHF1w6EgbeG7qWPigJ0gKG92ZXJmaXR0aW5nKSwgaGnhu4N1IHNhaSBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIGPDoWMgYmnhur9uLCBob+G6t2MgZOG7sSDEkW/DoW4gc2FpIGzhu4djaCB0cm9uZyB0aOG7sWMgdOG6vy4gRG8gxJHDsywgY2jhuqluIMSRb8OhbiBtw7QgaMOsbmgga2jDtG5nIHBo4bqjaSBsw6AgdMO5eSBjaOG7jW4g4oCTIG3DoCBsw6AgbeG7mXQgcGjhuqduIGLhuq90IGJ14buZYyB0cm9uZyBwaMOibiB0w61jaCBo4buTaSBxdXkgbmdoacOqbSB0w7pjLg0KDQpUcm9uZyBjaMawxqFuZyBuw6B5LCBjaMO6bmcgdGEgc+G6vSBo4buNYyBjw6FjaDoNCg0KLSAgIEtp4buDbSB0cmEgY8OhYyBnaeG6oyDEkeG7i25oIGPhu6dhIG3DtCBow6xuaCBo4buTaSBxdXkuDQoNCi0gICBT4butIGThu6VuZyBwaOG6p24gZMawIChyZXNpZHVhbHMpIMSR4buDIGtp4buDbSB0cmEgxJHhu5kgcGjDuSBo4bujcC4NCg0KLSAgIFBow6F0IGhp4buHbiB2w6AgeOG7rSBsw70gY8OhYyDEkWnhu4NtIOG6o25oIGjGsOG7n25nIGzhu5tuLg0KDQotICAgxJBvIGzGsOG7nW5nIGhp4buHbiB0xrDhu6NuZyDEkWEgY+G7mW5nIHR1eeG6v24gdsOgIGPDoWNoIGdp4bqjbSB0aGnhu4N1Lg0KDQojIyMgKiozLjIgR2nhuqMgxJHhu4tuaCB0cm9uZyBtw7QgaMOsbmggaOG7k2kgcXV5IHR1eeG6v24gdMOtbmgqKg0KDQpN4buZdCBtw7QgaMOsbmggaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggdGnDqnUgY2h14bqpbiDEkcOyaSBo4buPaSBwaOG6o2kgdGjhu49hIG3Do24gNCBnaeG6oyDEkeG7i25oIGPGoSBi4bqjbjoNCg0KKioxLiBHaeG6oyDEkeG7i25oIDE6IFF1YW4gaOG7hyB0dXnhur9uIHTDrW5oKioNCg0KLSBNw7QgaMOsbmggZ2nhuqMgxJHhu4tuaCBy4bqxbmcgdHJ1bmcgYsOsbmggY+G7p2EgYmnhur9uIHBo4bqjbiBo4buTaSBcKHlcKSBsw6AgaMOgbSB0dXnhur9uIHTDrW5oIGPhu6dhIGPDoWMgYmnhur9uIGdp4bqjaSB0aMOtY2ggXCh4XzEsIHhfMiwgXGxkb3RzLCB4X3BcKS4NCg0KLSBO4bq/dSBxdWFuIGjhu4cgdGjhuq10IHPhu7EgbMOgIHBoaSB0dXnhur9uIG3DoCB0YSB24bqrbiBkw7luZyBtw7QgaMOsbmggdHV54bq/biB0w61uaCwga+G6v3QgcXXhuqMgxrDhu5tjIGzGsOG7o25nIGPDsyB0aOG7gyBi4buLIHRoacOqbiBs4buHY2ggdsOgIGThu7EgxJFvw6FuIHNhaS4NCg0KXChcUmlnaHRhcnJvd1wpICoqQ8OhY2gga2nhu4NtIHRyYToqKiB24bq9IGJp4buDdSDEkeG7kyBwaOG6p24gZMawIHNvIHbhu5tpIGdpw6EgdHLhu4sgZOG7sSDEkW/DoW4sIG7hur91IHRo4bqleSB4dSBoxrDhu5tuZyBjb25nIChwYXJhYm9sYSwgUy1zaGFwZeKApikgdGjDrCBjw7MgdGjhu4MgbMOgIG3DtCBow6xuaCBzYWkgZOG6oW5nLg0KDQoqKjIuIEdp4bqjIMSR4buLbmggMjogIFBoxrDGoW5nIHNhaSBraMO0bmcgxJHhu5VpIChIb21vc2NlZGFzdGljaXR5KSoqDQoNCi0gUGjGsMahbmcgc2FpIGPhu6dhIHNhaSBz4buRIFwoXHZhcmVwc2lsb25faVwpIGzDoCBuaMawIG5oYXUg4bufIG3hu41pIG3hu6ljIGdpw6EgdHLhu4sgY+G7p2EgXCh4XCk6DQoNCiQkDQpcdGV4dHtWYXJ9KHlfaSkgPSBcc2lnbWFeMg0KJCQNCg0KLSBO4bq/dSBwaMawxqFuZyBzYWkgdGhheSDEkeG7lWkgdGhlbyBcKHhcKSwgdGEgY8OzIGhp4buHbiB0xrDhu6NuZyAqKnBoxrDGoW5nIHNhaSB0aGF5IMSR4buVaSAoaGV0ZXJvc2NlZGFzdGljaXR5KSoqLCBk4bqrbiDEkeG6v24gxrDhu5tjIGzGsOG7o25nIGtow7RuZyBoaeG7h3UgcXXhuqMgdsOgIHNhaSBs4buHY2ggdHJvbmcga2nhu4NtIMSR4buLbmguDQoNClwoXFJpZ2h0YXJyb3dcKSAqKkPDoWNoIGtp4buDbSB0cmE6KiogduG6vSDEkeG7kyB0aOG7iyBwaOG6p24gZMawLiBO4bq/dSBwaOG6p24gZMawIGPDsyBk4bqhbmcgaMOsbmggbsOzbiAocuG7mW5nIGThuqduIGhv4bq3YyBo4bq5cCBs4bqhaSkgdGjDrCBjw7MgdGjhu4MgYuG7iyBoZXRlcm9zY2VkYXN0aWNpdHkuDQoNCioqMy4gR2nhuqMgxJHhu4tuaCAzOiDEkOG7mWMgbOG6rXAqKg0KDQotIEPDoWMgcXVhbiBzw6F0IFwoKHhfaSwgeV9pKVwpIHBo4bqjaSDEkeG7mWMgbOG6rXAgbmhhdS4NCg0KLSBO4bq/dSBk4buvIGxp4buHdSBjw7MgdMOtbmggY2h14buXaSB0aOG7nWkgZ2lhbiwgZOG7ryBsaeG7h3UgbOG7k25nIGdow6lwIChuZXN0ZWQgZGF0YSkgaG/hurdjIHBow6JuIG5ow7NtIChjbHVzdGVyZWQpLCB0aMOsIG3DtCBow6xuaCB0dXnhur9uIHTDrW5oIGPGoSBi4bqjbiBraMO0bmcgY8OybiBwaMO5IGjhu6NwLg0KDQpcKFxSaWdodGFycm93XCkgKipDw6FjaCBraeG7g20gdHJhOioqIG7hur91IGThu68gbGnhu4d1IHRoZW8gdGjhu51pIGdpYW4sIG7Dqm4ga2nhu4NtIHRyYSBwaOG6p24gZMawIGPDsyB4dSBoxrDhu5tuZyAoYXV0b2NvcnJlbGF0aW9uKSBoYXkga2jDtG5nLg0KDQoqKjQuIEdp4bqjIMSR4buLbmggNDogUGjDom4gcGjhu5FpIGNodeG6qW4gY+G7p2Egc2FpIHPhu5EqKg0KDQotIE3hurdjIGTDuSBraMO0bmcgYuG6r3QgYnXhu5ljIMSR4buDIMaw4bubYyBsxrDhu6NuZyBPTFMsIGdp4bqjIMSR4buLbmggbsOgeSBy4bqldCBxdWFuIHRy4buNbmcgxJHhu4Mga2nhu4NtIMSR4buLbmggZ2nhuqMgdGh1eeG6v3QgdsOgIHTDrW5oIGtob+G6o25nIHRpbiBj4bqteToNCiQkDQpcdmFyZXBzaWxvbl9pIFxzaW0gXG1hdGhjYWx7Tn0oMCwgXHNpZ21hXjIpDQokJA0KDQpcKFxSaWdodGFycm93XCkgKipDw6FjaCBraeG7g20gdHJhOioqIGTDuW5nIGJp4buDdSDEkeG7kyBRLVEgcGxvdCAocXVhbnRpbGUtcXVhbnRpbGUpIMSR4buDIHNvIHPDoW5oIHBo4bqnbiBkxrAgduG7m2kgcGjDom4gcGjhu5FpIGNodeG6qW4uDQoNCiMjIyAqKjMuMyBDw6FjIGxv4bqhaSBwaOG6p24gZMawIChSZXNpZHVhbHMpKioNCg0KUGjhuqduIGTGsCBsw6AgY8O0bmcgY+G7pSB0cnVuZyB0w6JtIMSR4buDIGNo4bqpbiDEkW/DoW4gbcO0IGjDrG5oLiBDw7Mgbmhp4buBdSBjw6FjaCB0w61uaCBwaOG6p24gZMawOg0KDQoqKjEuIFJhdyByZXNpZHVhbCAoUGjhuqduIGTGsCB0aMO0KToqKg0KDQokJA0KZV9pID0geV9pIC0gXGhhdHt5fV9pDQokJA0KxJDGoW4gZ2nhuqNuIGzDoCBoaeG7h3UgZ2nhu69hIGdpw6EgdHLhu4sgdGjhu7FjIHThur8gdsOgIGdpw6EgdHLhu4sgZOG7sSDEkW/DoW4uDQoNCioqMi4gU3RhbmRhcmRpemVkIHJlc2lkdWFsIChQaOG6p24gZMawIGNodeG6qW4gaMOzYSk6KioNCg0KJCQNCnJfaSA9IFxmcmFje2VfaX17XGhhdHtcc2lnbWF9IFxzcXJ0ezEgLSBoX3tpaX19fQ0KJCQNCg0KLSBHacO6cCBzbyBzw6FuaCBwaOG6p24gZMawIGdp4buvYSBjw6FjIMSRaeG7g20gY8OzIGxldmVyYWdlIGtow6FjIG5oYXUuDQoNCi0gXCggaF97aWl9IFwpOiBsZXZlcmFnZSDigJMgbeG7qWMg4bqjbmggaMaw4bufbmcgY+G7p2EgxJFp4buDbSBcKCBpIFwpIGzDqm4gZOG7sSDEkW/DoW4gXCggXGhhdHt5fV9pIFwpLg0KDQoqKjMuIFN0dWRlbnRpemVkIHJlc2lkdWFsOioqDQoNCiQkDQp0X2kgPSBcZnJhY3tlX2l9e1xoYXR7XHNpZ21hfV97KGkpfSBcc3FydHsxIC0gaF97aWl9fX0NCiQkDQoNCi0gR2nhu5FuZyBzdGFuZGFyZGl6ZWQgcmVzaWR1YWwgbmjGsG5nIGTDuW5nIFwoXGhhdHtcc2lnbWF9X3soaSl9XCkg4oCTIHBoxrDGoW5nIHNhaSDGsOG7m2MgbMaw4bujbmcga2jDtG5nIGTDuW5nIHF1YW4gc8OhdCBcKGlcKSBcKFxyaWdodGFycm93XCkgY2jDrW5oIHjDoWMgaMahbi4NCg0KLSBEw7luZyDEkeG7gyBwaMOhdCBoaeG7h24gbmdv4bqhaSBsYWkgdsOsIG7DsyBn4bqnbiB24bubaSBwaMOibiBwaOG7kWkgdC4NCg0KIyMjICoqMy40IEJp4buDdSDEkeG7kyBwaOG6p24gZMawIChSZXNpZHVhbCBQbG90cykqKg0KDQpN4buZdCBz4buRIGJp4buDdSDEkeG7kyBxdWFuIHRy4buNbmc6DQoNCi0gKipSZXNpZHVhbCB2cyBGaXR0ZWQgUGxvdDoqKiBraeG7g20gdHJhIHR1eeG6v24gdMOtbmggdsOgIHBoxrDGoW5nIHNhaSBraMO0bmcgxJHhu5VpLg0KDQotICoqTm9ybWFsIFEtUSBQbG90Kio6IGtp4buDbSB0cmEgcGjDom4gcGjhu5FpIGNodeG6qW4gY+G7p2EgcGjhuqduIGTGsC4NCg0KLSAqKlNjYWxlLUxvY2F0aW9uIFBsb3Q6KiogY2h14bqpbiBow7NhIHBo4bqnbiBkxrAgxJHhu4MgZOG7hSBwaMOhdCBoaeG7h24gaGV0ZXJvc2NlZGFzdGljaXR5Lg0KDQotICoqUmVzaWR1YWxzIHZzIExldmVyYWdlIFBsb3Q6KiogeMOhYyDEkeG7i25oIMSRaeG7g20g4bqjbmggaMaw4bufbmcgbOG7m24uDQoNCiMjIyAqKjMuNSBOZ2/huqFpIGxhaSAoT3V0bGllcnMpKioNCg0KKirEkOG7i25oIG5naMSpYToqKiBMw6AgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1IG3DoCBnacOhIHRy4buLIHBo4bqjbiBo4buTaSBcKCB5X2kgXCkga2jDoWMgYmnhu4d0IGzhu5tuIHNvIHbhu5tpIGThu7EgxJFvw6FuIHThu6sgbcO0IGjDrG5oLCBkw7kgYmnhur9uIFwoIHhfaSBcKSBraMO0bmcgYuG6pXQgdGjGsOG7nW5nLg0KDQpEw7luZyBzdHVkZW50aXplZCByZXNpZHVhbCDEkeG7gyBraeG7g20gdHJhLg0KDQpRdXkgdOG6r2MgbmfGsOG7oW5nOg0KDQotIFwofHRfaXwgPiAyXCk6IG5naGkgbmfhu50uDQoNCi0gXCh8dF9pfCA+IDNcKTogY8OzIHRo4buDIGzDoCBuZ2/huqFpIGxhaSDEkcOhbmcga+G7gy4NCg0KXChcUmlnaHRhcnJvd1wpICoqTmdv4bqhaSBsYWkga2jDtG5nIG5o4bqldCB0aGnhur90IGPDsyDhuqNuaCBoxrDhu59uZyBs4bubbioqLCBuaMawbmcgY+G6p24ga2nhu4NtIHRyYSBr4bu5Lg0KDQojIyMgKiozLjYgxJBp4buDbSDhuqNuaCBoxrDhu59uZyAoSW5mbHVlbnRpYWwgUG9pbnRzKSoqDQoNCioqxJDhu4tuaCBuZ2jEqWE6KiogTMOgIG5o4buvbmcgxJFp4buDbSBk4buvIGxp4buHdSBtw6AgKipu4bq/dSBi4buLIGxv4bqhaSBi4buPLCBtw7QgaMOsbmggc+G6vSB0aGF5IMSR4buVaSDEkcOhbmcga+G7gyoqLg0KDQpDw6FjIGNo4buJIHPhu5EgcGjhu5UgYmnhur9uIMSR4buDIMSRbyDhuqNuaCBoxrDhu59uZzoNCg0KKioxLiBMZXZlcmFnZSAoSOG7hyBz4buRIMSRw7JuIGLhuql5KToqKg0KDQokJA0KaF97aWl9ID0geF9pXlQgKFheVCBYKV57LTF9IHhfaSANCiQkDQoNCi0gxJBvIGtob+G6o25nIGPDoWNoIGPhu6dhIFwoIHhfaSBcKSDEkeG6v24gdHJ1bmcgdMOibSBj4bunYSBjw6FjIMSRaeG7g20gXCggeCBcKS4NCg0KLSBO4bq/dSBcKCBoX3tpaX0gPiBcZnJhY3sycH17bn0gXCk6IMSRaeG7g20gY8OzIGxldmVyYWdlIGNhby4NCg0KKioyLiBDb29r4oCZcyBEaXN0YW5jZSAoS2hv4bqjbmcgY8OhY2ggQ29vayk6KioNCg0KJCQNCkRfaSA9IFxmcmFje3AgXGhhdHtcc2lnbWF9XjIgZV9pXjJ9eygxIC0gaF97aWl9KV4yIGhfe2lpfX0gDQokJCANCg0KS+G6v3QgaOG7o3AgZ2nhu69hIMSR4buZIGzhu4djaCAocmVzaWR1YWwpIHbDoCBsZXZlcmFnZS4NCg0KLSBO4bq/dSBcKCBEX2kgPiAwLjUgXCk6IGPDsyB0aOG7gyBjw7Mg4bqjbmggaMaw4bufbmcuDQoNCi0gTuG6v3UgXCggRF9pID4gMSBcKTog4bqjbmggaMaw4bufbmcgbOG7m24gY+G6p24geGVtIHjDqXQga+G7uS4NCg0KKiozLiBERkJFVEFTOioqDQoNCiQkDQpcdGV4dHtERkJFVEFTfV97aWp9ID0gXGZyYWN7XGhhdHtcYmV0YX1faiAtIFxoYXR7XGJldGF9X3tqKGkpfX17XHRleHR7U0V9KFxoYXR7XGJldGF9X3tqKGkpfSl9DQokJA0KDQotIE3hu6ljIHRoYXkgxJHhu5VpIGPhu6dhIGjhu4cgc+G7kSBcKFxiZXRhX2pcKSBraGkgbG/huqFpIGLhu48gcXVhbiBzw6F0IFwoaVwpLg0KDQotIETDuW5nIMSR4buDIGtp4buDbSB0cmEg4bqjbmggaMaw4bufbmcgY+G7p2EgdOG7q25nIMSRaeG7g20gbMOqbiB04burbmcgaOG7hyBz4buRIGPhu6UgdGjhu4MuDQoNCiMjIyAqKjMuNyDEkGEgY+G7mW5nIHR1eeG6v24gKE11bHRpY29sbGluZWFyaXR5KSoqDQoNCioqxJDhu4tuaCBuZ2jEqWE6KiogWOG6o3kgcmEga2hpIGhhaSBoYXkgbmhp4buBdSBiaeG6v24gZ2nhuqNpIHRow61jaCBjw7MgdMawxqFuZyBxdWFuIGNhbywga2hp4bq/biBjaG8gxrDhu5tjIGzGsOG7o25nIFwoXGJldGFfalwpIGtow7RuZyDhu5VuIMSR4buLbmggKG5o4buPIHRoYXkgxJHhu5VpIGThu68gbGnhu4d1IFwoXHJpZ2h0YXJyb3dcKSBs4bubbiB0aGF5IMSR4buVaSBo4buHIHPhu5EpLg0KDQoqKlZhcmlhbmNlIEluZmxhdGlvbiBGYWN0b3IgKFZJRik6KioNCg0KJCQNClxtYXRocm17VklGfV9qID0gXGZyYWN7MX17MSAtIFJfal4yfQ0KJCQNCg0KLSBcKFJfal4yXCkgOiBo4buHIHPhu5EgeMOhYyDEkeG7i25oIGtoaSBo4buTaSBxdXkgXCh4X2pcKSBsw6puIHThuqV0IGPhuqMgY8OhYyBiaeG6v24gY8OybiBs4bqhaS4NCg0KLSBO4bq/dSBcKFxtYXRocm17VklGfV9qID4gNVwpIGhv4bq3YyBcKD4gMTBcKTogY8OzIHbhuqVuIMSR4buBIGPhuqduIHjhu60gbMO9Lg0KDQojIyMgKiozLjggU+G7rWEgY2jhu69hIG3DtCBow6xuaCBzYWkqKg0KDQpLaGkgbcO0IGjDrG5oIHZpIHBo4bqhbSBnaeG6oyDEkeG7i25oOg0KDQotIETDuW5nIGJp4bq/biDEkeG7lWkgKioobG9nLCBzcXJ0LCBCb3gtQ2944oCmKSoqLg0KDQotIETDuW5nIG3DtCBow6xuaCBwaGkgdHV54bq/biBob+G6t2MgbcO0IGjDrG5oIEdMTS4NCg0KLSBMb+G6oWkgYuG7jyBob+G6t2MgdGhheSB0aOG6vyDEkWnhu4NtIOG6o25oIGjGsOG7n25nIHF1w6EgbOG7m24uDQoNCi0gVGjDqm0gYmnhur9uIGLhu4sgdGhp4bq/dSBob+G6t2MgbG/huqFpIGLhu5t0IGJp4bq/biBnw6J5IG5oaeG7hXUuDQoNCi0tLQ0KDQojIyAqKkNIxq/GoE5HIDQ6IMav4buaQyBMxq/hu6JORyBI4buiUCBMw50gVOG7kEkgxJBBIChNQVhJTVVNIExJS0VMSUhPT0QgRVNUSU1BVElPTiDigJMgTUxFKSoqDQoNCiMjIyAqKjQuMSBHaeG7m2kgdGhp4buHdSoqDQoNClBoxrDGoW5nIHBow6FwIGLDrG5oIHBoxrDGoW5nIHThu5FpIHRoaeG7g3UgKE9MUykgY2jhu4kgaG/huqF0IMSR4buZbmcgaGnhu4d1IHF14bqjIGtoaSBk4buvIGxp4buHdSB0aOG7j2EgbcOjbiBjw6FjIGdp4bqjIMSR4buLbmggbmjGsCBwaMOibiBwaOG7kWkgY2h14bqpbiwgcGjGsMahbmcgc2FpIGtow7RuZyDEkeG7lWksIHbDoCBiaeG6v24gcGjhuqNuIGjhu5NpIGxpw6puIHThu6VjLiBUdXkgbmhpw6puLCBuaGnhu4F1IGxv4bqhaSBk4buvIGxp4buHdSB0aOG7sWMgdOG6vyBraMO0bmcgdHXDom4gdGhlbyBuaOG7r25nIMSRaeG7gXUga2nhu4duIMSRw7Mg4oCTIHbDrSBk4bulOiBk4buvIGxp4buHdSBuaOG7iyBwaMOibiwgxJHhur9tLCBob+G6t2MgZMawxqFuZyBsacOqbiB04bulYy4gS2hpIMSRw7MsIE1heGltdW0gTGlrZWxpaG9vZCBFc3RpbWF0aW9uIChNTEUpIGzDoCBwaMawxqFuZyBwaMOhcCBt4bqhbmggbeG6vSBoxqFuLCBkw7luZyDEkeG7gyDGsOG7m2MgbMaw4bujbmcgY8OhYyB0aGFtIHPhu5EgdHJvbmcgbcO0IGjDrG5oIHThu5VuZyBxdcOhdC4NCg0KTUxFIGzDoCBu4buBbiB04bqjbmcgY2hvIG3DtCBow6xuaCB0dXnhur9uIHTDrW5oIHThu5VuZyBxdcOhdCAoR0xNKSwgduG7kW4gbMOgIHRydW5nIHTDom0gY+G7p2EgcGjhuqduIGPDsm4gbOG6oWkgdHJvbmcgc8OhY2guDQoNCiMjIyAqKjQuMiBIw6BtIGjhu6NwIGzDvSAoTGlrZWxpaG9vZCBGdW5jdGlvbikqKg0KDQoqKsSQ4buLbmggbmdoxKlhOioqIEjDoG0gaOG7o3AgbMO9IGzDoCBt4buZdCBow6BtIHjDoWMgc3XhuqV0IGPhu6dhIHRvw6BuIGLhu5kgZOG7ryBsaeG7h3UgxJHDoyBxdWFuIHPDoXQsIGJp4buDdSBkaeG7hW4gbmjGsCBt4buZdCBow6BtIGPhu6dhIHRoYW0gc+G7kSBcKFx0aGV0YVwpLg0KDQpHaeG6oyBz4butIHRhIGPDsyBt4buZdCBt4bqrdSBn4buTbSBcKG5cKSBxdWFuIHPDoXQgxJHhu5ljIGzhuq1wIFwoeV8xLCB5XzIsIFxsZG90cywgeV9uXCksIHbhu5tpIG3hu5dpIFwoeV9pXCkgY8OzIHBow6JuIHBo4buRaSB4w6FjIHN14bqldCBcKGYoeV9pOyBcdGhldGEpXCksIHRow6w6DQoNCioqSMOgbSBo4bujcCBsw706KioNCg0KJCQNCkwoXHRoZXRhKSA9IFxwcm9kX3tpPTF9XntufSBmKHlfaTsgXHRoZXRhKQ0KJCQNCg0KLSBcKEwoXHRoZXRhKVwpOiBow6BtIGjhu6NwIGzDvQ0KDQotIFwoXHRoZXRhXCk6IHZlY3RvciBjw6FjIHRoYW0gc+G7kSBj4bqnbiDGsOG7m2MgbMaw4bujbmcNCg0KLSBcKGYoeV9pOyBcdGhldGEpXCk6IG3huq10IMSR4buZIHjDoWMgc3XhuqV0IChob+G6t2Mga2jhu5FpIHjDoWMgc3XhuqV0KSBj4bunYSBcKHlfaVwpDQoNCioqTG9nLWjhu6NwIGzDvSAobG9nLWxpa2VsaWhvb2QpOioqDQoNCiQkDQpcZWxsKFx0aGV0YSkgPSBcbG9nIEwoXHRoZXRhKSA9IFxzdW1fe2k9MX1ee259IFxsb2cgZih5X2k7IFx0aGV0YSkNCiQkDQoNCi0gROG7hSDEkeG6oW8gaMOgbSBoxqFuIHbDrCB0w61jaCB0aMOgbmggdOG7lW5nLg0KDQotIEdpw6EgdHLhu4sgY+G7sWMgxJHhuqFpIGPhu6dhIFwoXGVsbChcdGhldGEpXCkgdHLDuW5nIHbhu5tpIFwoTChcdGhldGEpXCkuDQoNCiMjIyAqKjQuMyDGr+G7m2MgbMaw4bujbmcgaOG7o3AgbMO9IHThu5FpIMSRYSAoTWF4aW11bSBMaWtlbGlob29kIEVzdGltYXRpb24g4oCTIE1MRSkqKg0KDQoqKsSQ4buLbmggbmdoxKlhOioqIE1MRSBsw6AgZ2nDoSB0cuG7iyBcKFxoYXR7XHRoZXRhfVwpIGPhu6dhIHRoYW0gc+G7kSBcKFx0aGV0YVwpIHNhbyBjaG8gbG9nLWxpa2VsaWhvb2QgxJHhuqF0IGPhu7FjIMSR4bqhaS4NCg0KDQokJA0KXGhhdHtcdGhldGF9ID0gXGFyZ1xtYXhfe1x0aGV0YX0gXCwgXGVsbChcdGhldGEpDQokJA0KxJDhu4MgdMOsbSBcKFxoYXR7XHRoZXRhfVwpLCB0YSBnaeG6o2k6DQoNCiQkDQpcZnJhY3tkXGVsbChcdGhldGEpfXtkXHRoZXRhfSA9IDANCiQkDQoNClwoXFJpZ2h0YXJyb3dcKSDEkMOieSBn4buNaSBsw6AgKnBoxrDGoW5nIHRyw6xuaCDEkWnhu4NtKiAoc2NvcmUgZXF1YXRpb24pLg0KDQojIyMgKio0LjQgTWEgdHLhuq1uIHRow7RuZyB0aW4gRmlzaGVyIHbDoCBwaMawxqFuZyBzYWkqKg0KDQoqKjEuIEjDoG0gxJFp4buDbSAoU2NvcmUgRnVuY3Rpb24pOioqDQoNCiQkDQpVKFx0aGV0YSkgPSBcZnJhY3tkXGVsbChcdGhldGEpfXtkXHRoZXRhfQ0KJCQNCg0KLSBcKFUoXHRoZXRhKVwpOiDEkeG7mSBk4buRYyBj4bunYSBsb2ctbGlrZWxpaG9vZCB0aGVvIFwoXHRoZXRhXCkNCg0KKioyLiBNYSB0cuG6rW4gdGjDtG5nIHRpbiBGaXNoZXI6KioNCg0KJCQNCkkoXHRoZXRhKSA9IC1cbWF0aGJie0V9IFxsZWZ0WyBcZnJhY3tkXjIgXGVsbChcdGhldGEpfXtkXHRoZXRhXjJ9IFxyaWdodF0NCiQkDQoNCi0gXChJKFx0aGV0YSlcKToga+G7syB24buNbmcgw6JtIGPhu6dhIMSR4bqhbyBow6BtIGLhuq1jIGhhaSBsb2ctbGlrZWxpaG9vZCDihpIgxJFvIMSR4buZIGNvbmcuDQoNCi0gTMOgIHjhuqVwIHjhu4kgbmfGsOG7o2MgbOG6oWkgY+G7p2EgcGjGsMahbmcgc2FpOg0KJCQNClxtYXRocm17VmFyfShcaGF0e1x0aGV0YX0pIFxhcHByb3ggXGZyYWN7MX17SShcdGhldGEpfQ0KJCQNCg0KIyMjICoqNC41IEPDoWMgdMOtbmggY2jhuqV0IGPhu6dhIE1MRSoqDQoNCk1MRSBjw7Mgbmhp4buBdSB0w61uaCBjaOG6pXQgdOG7kXQgduG7gSBt4bq3dCBsw70gdGh1eeG6v3QsIMSR4bq3YyBiaeG7h3Qga2hpIGvDrWNoIHRoxrDhu5tjIG3huqt1IG4gbOG7m246DQoNCnwgVMOtbmggY2jhuqV0ICAgICAgICAgICAgICAgIHwgR2nhuqNpIHRow61jaCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwNCnwgKipOaOG6pXQgcXXDoW4qKiAgICAgICAgICAgIHwgJFxoYXR7XHRoZXRhfSBcdG8gXHRoZXRhJCBraGkgJG4gXHRvIFxpbmZ0eSQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKktow7RuZyBjaOG7h2NoIHRp4buHbSBj4bqtbioqIHwgxJDhu5kgbOG7h2NoIGdp4buvYSAkXGhhdHtcdGhldGF9JCB2w6AgJFx0aGV0YSQgdGnhur9uIHbhu4EgMCAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKkhp4buHdSBxdeG6oyoqICAgICAgICAgICAgIHwgTUxFIMSR4bqhdCBnaeG7m2kgaOG6oW4gQ3JhbcOpcuKAk1JhbywgbMOgIMaw4bubYyBsxrDhu6NuZyAidOG7kXQgbmjhuqV0IiAgICAgICAgICAgICAgICAgICAgICAgfA0KfCAqKlRp4buHbSBj4bqtbiBjaHXhuqluKiogICAgICAgfCBLaGkgJG4kIGzhu5tuLCBwaMOibiBwaOG7kWkgY+G7p2EgJFxoYXR7XHRoZXRhfSQgZ+G6p24gY2h14bqpbjogJFxoYXR7XHRoZXRhfSBcc2ltIFxtYXRoY2Fse059KFx0aGV0YSwgSShcdGhldGEpXnstMX0pJCB8DQoNCiMjIyAqKjQuNiBLaeG7g20gxJHhu4tuaCBnaeG6oyB0aHV54bq/dCB24bubaSBNTEUqKg0KDQpNdeG7kW4ga2nhu4NtIHRyYSBnaeG6oyB0aHV54bq/dDoNCg0KXFsNCkhfMDogXHRoZXRhID0gXHRoZXRhXzANClxdDQoNCnRhIGPDsyAqKmJhIGPDoWNoKiogcGjhu5UgYmnhur9uOg0KDQoqKjEuIFdhbGQgVGVzdDoqKg0KDQpcWw0KWiA9IFxmcmFje1xoYXR7XHRoZXRhfSAtIFx0aGV0YV8wfXtTRShcaGF0e1x0aGV0YX0pfSwgXHF1YWQgWiBcc2ltIE4oMCwxKQ0KXF0NCg0KLSBEw7luZyDEkeG7gyBraeG7g20gxJHhu4tuaCBu4bq/dSBcKCBTRShcaGF0e1x0aGV0YX0pIFwpIMSRw6MgY8OzLg0KDQotLS0NCg0KKioyLiBMaWtlbGlob29kIFJhdGlvIFRlc3QgKExSVCk6KioNCg0KXFsNCkxSID0gMiBcbGVmdFsgXGVsbChcaGF0e1x0aGV0YX0pIC0gXGVsbChcdGhldGFfMCkgXHJpZ2h0XSBcc2ltIFxjaGleMl97ZGZ9DQpcXQ0KDQotIFNvIHPDoW5oIGxvZy1saWtlbGlob29kIGPhu6dhIG3DtCBow6xuaCDEkeG6p3kgxJHhu6cgdsOgIG3DtCBow6xuaCByw7p0IGfhu41uLg0KDQotIFwoIGRmIFwpOiBz4buRIHRoYW0gc+G7kSBi4buLIHLDoG5nIGJ14buZYyB0cm9uZyBcKCBIXzAgXCkuDQoNCi0tLQ0KDQoqKjMuIFNjb3JlIFRlc3QgKExhZ3JhbmdlIE11bHRpcGxpZXIgVGVzdCk6KioNCg0KXFsNClMgPSBcZnJhY3tVKFx0aGV0YV8wKV4yfXtJKFx0aGV0YV8wKX0gXHNpbSBcY2hpXjJfMQ0KXF0NCg0KS2jDtG5nIGPhuqduIMaw4bubYyBsxrDhu6NuZyBtw7QgaMOsbmggxJHhuqd5IMSR4bunLg0KDQojIyMgKio0LjcgU28gc8OhbmggbcO0IGjDrG5oIGLhurFuZyBBSUMgdsOgIEJJQyoqDQoNCktoaSBraMO0bmcgdGjhu4MgZMO5bmcga2nhu4NtIMSR4buLbmggTFJUIChkbyBtw7QgaMOsbmgga2jDtG5nIGzhu5NuZyksIHRhIGTDuW5nOg0KDQoqKjEuIEFJQyDigJMgQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbjoqKg0KDQpcWw0KXHRleHR7QUlDfSA9IC0yXGVsbCArIDJrDQpcXQ0KDQotIFwoa1wpOiBz4buRIHRoYW0gc+G7kSB0cm9uZyBtw7QgaMOsbmgNCg0KLSBcKFxlbGxcKTogbG9nLWxpa2VsaWhvb2QgdOG6oWkgTUxFDQoNCi0tLQ0KDQoqKjIuIEJJQyDigJMgQmF5ZXNpYW4gSW5mb3JtYXRpb24gQ3JpdGVyaW9uOioqDQoNClxbDQpcdGV4dHtCSUN9ID0gLTJcZWxsICsgXGxvZyhuKSBcY2RvdCBrDQpcXQ0KDQotIFwoblwpOiBz4buRIHF1YW4gc8OhdA0KDQotLS0NCg0K4oaSIENo4buNbiBtw7QgaMOsbmggY8OzIEFJQy9CSUMgdGjhuqVwIGjGoW4uDQoNCiMjIyAqKjQuOCBNTEUgdHJvbmcgbcO0IGjDrG5oIGtow7RuZyB0dXnhur9uIHTDrW5oIGNodeG6qW4qKg0KDQoqKkjhu5NpIHF1eSBsb2dpc3RpYyAobmjhu4sgcGjDom4pOioqDQoNClxbDQp5X2kgXHNpbSBcdGV4dHtCZXJub3VsbGl9KFxwaV9pKSwgXHF1YWQgXGxvZ1xsZWZ0KFxmcmFje1xwaV9pfXsxIC0gXHBpX2l9XHJpZ2h0KSA9IHhfaV5UIFxiZXRhDQpcXQ0KDQotLS0NCg0KKipI4buTaSBxdXkgUG9pc3NvbiAoxJHhur9tKToqKg0KDQpcWw0KeV9pIFxzaW0gXHRleHR7UG9pc3Nvbn0oXG11X2kpLCBccXVhZCBcbG9nKFxtdV9pKSA9IHhfaV5UIFxiZXRhDQpcXQ0KDQotLS0NCg0KKipI4buTaSBxdXkgR2FtbWEgKGTGsMahbmcgbGnDqm4gdOG7pWMpOioqDQoNClxbDQp5X2kgXHNpbSBcdGV4dHtHYW1tYX0oXGFscGhhLCBcbXVfaSksIFxxdWFkIFxsb2coXG11X2kpID0geF9pXlQgXGJldGENClxdDQoNCi0tLQ0KDQrihpIgQ+G6oyBiYSDEkeG7gXUgZMO5bmcgKipNTEUqKiDEkeG7gyDGsOG7m2MgbMaw4bujbmcgXChcYmV0YVwpLCBjaOG7qSBraMO0bmcgZMO5bmcgT0xTLg0KDQojIyAqKkNIxq/GoE5HIDU6IEPhuqRVIFRSw5pDIEPhu6ZBIE3DlCBIw4xOSCBUVVnhur5OIFTDjU5IIFThu5RORyBRVcOBVCAoR0xNIFNUUlVDVFVSRSkqKg0KDQojIyMgKio1LjEgR2nhu5tpIHRoaeG7h3UqKg0KDQpNw7QgaMOsbmggdHV54bq/biB0w61uaCB04buVbmcgcXXDoXQgKEdMTSkgbMOgIG3hu5l0IGtodcO0biBraOG7lSBt4bqhbmggbeG6vSBjaG8gdmnhu4djIG3DtCBow6xuaCBow7NhIGPDoWMgbG/huqFpIGThu68gbGnhu4d1IGtow6FjIG5oYXUg4oCTIGtow7RuZyBjaOG7iSBk4buvIGxp4buHdSBsacOqbiB04bulYyBjw7MgcGjDom4gcGjhu5FpIGNodeG6qW4gbmjGsCB0cm9uZyBo4buTaSBxdXkgdHV54bq/biB0w61uaC4gR0xNIGJhbyBn4buTbSBo4buTaSBxdXkgbG9naXN0aWMsIGjhu5NpIHF1eSBQb2lzc29uLCBo4buTaSBxdXkgR2FtbWEuLi4gdsOgIG3hu58gcuG7mW5nIGto4bqjIG7Eg25nIHBow6JuIHTDrWNoIMSR4bq/biBk4buvIGxp4buHdSBuaOG7iyBwaMOibiwgxJHhur9tLCB04bu3IGzhu4cgdsOgIGTGsMahbmcgbGnDqm4gdOG7pWMuDQoNCk3hu5dpIEdMTSDEkcaw4bujYyB4w6J5IGThu7FuZyB0csOqbiBjw7luZyBt4buZdCBuZ3V5w6puIGzDvSBjaHVuZyBn4buTbSBiYSB0aMOgbmggcGjhuqduIGNow61uaDogcGjDom4gcGjhu5FpIHjDoWMgc3XhuqV0LCBow6BtIGxpw6puIGvhur90LCB2w6AgdGjDoG5oIHBo4bqnbiB0dXnhur9uIHTDrW5oLg0KDQojIyMgKio1LjIgQ+G6pXUgdHLDumMgMyBwaOG6p24gY+G7p2EgR0xNKioNCg0KKioxLiBUaMOgbmggcGjhuqduIG5n4bqrdSBuaGnDqm4gKFJhbmRvbSBjb21wb25lbnQpKioNCg0KQmnhur9uIHBo4bqjbiBo4buTaSBcKCB5X2kgXCkgxJHGsOG7o2MgZ2nhuqMgxJHhu4tuaCBwaMOibiBwaOG7kWkgdGhlbyBt4buZdCBwaMOibiBwaOG7kWkgdGh14buZYyBo4buNIGjDoG0gbcWpIG3hu5l0IHRoYW0gc+G7kSAoT25lLVBhcmFtZXRlciBFeHBvbmVudGlhbCBGYW1pbHkpOg0KDQokJA0KZih5X2k7IFx0aGV0YV9pLCBccGhpKSA9IFxleHAgXGxlZnRceyBcZnJhY3t5X2kgXHRoZXRhX2kgLSBiKFx0aGV0YV9pKX17XHBoaX0gKyBjKHlfaSwgXHBoaSkgXHJpZ2h0XH0NCiQkDQoNCsOdIG5naMSpYSBjw6FjIGvDvSBoaeG7h3U6DQoNCi0gXChcdGhldGFfaVwpOiB0aGFtIHPhu5EgdOG7sSBuaGnDqm4gKG5hdHVyYWwgcGFyYW1ldGVyKQ0KLSBcKFxwaGlcKTogdGhhbSBz4buRIHBow6JuIHTDoW4gKGRpc3BlcnNpb24gcGFyYW1ldGVyKSwga2jDtG5nIHBo4bqjaSBsw7pjIG7DoG8gY8WpbmcgY8OzICh2w60gZOG7pSBQb2lzc29uIHRow6wgXChccGhpID0gMVwpKQ0KLSBcKGIoXHRoZXRhX2kpXCk6IGjDoG0gbG9nIHBhcnRpdGlvbg0KLSBcKGMoeV9pLCBccGhpKVwpOiBow6BtIGNodeG6qW4gaMOzYSDEkeG7gyBi4bqjbyB0b8OgbiB0w61jaCBwaMOibiBi4bqxbmcgMQ0KDQrihpIgSOG7jSBow6BtIG3FqSBiYW8gZ+G7k20gTm9ybWFsLCBQb2lzc29uLCBCaW5vbWlhbCwgR2FtbWEsLi4uDQoNCi0tLQ0KDQoqKjIuIFRow6BuaCBwaOG6p24gaOG7hyB0aOG7kW5nIChTeXN0ZW1hdGljIGNvbXBvbmVudCkqKg0KDQpHaeG7kW5nIG5oxrAgaOG7k2kgcXV5IHR1eeG6v24gdMOtbmgsIEdMTSB24bqrbiBkw7luZyBt4buZdCBwcmVkaWN0b3IgdHV54bq/biB0w61uaDoNCg0KJCQNClxldGFfaSA9IHhfaV5UIFxiZXRhID0gXGJldGFfMCArIFxiZXRhXzEgeF97aTF9ICsgXGNkb3RzICsgXGJldGFfcCB4X3tpcH0NCiQkDQoNCsOdIG5naMSpYToNCg0KLSBcKFxldGFfaVwpOiBwcmVkaWN0b3IgdHV54bq/biB0w61uaA0KLSBcKHhfaVwpOiB2ZWN0b3IgaMOgbmcgZ+G7k20gY8OhYyBiaeG6v24gZ2nhuqNpIHRow61jaCBj4bunYSBxdWFuIHPDoXQgXChpXCkNCi0gXChcYmV0YVwpOiB2ZWN0b3IgaOG7hyBz4buRIGjhu5NpIHF1eQ0KDQrEkMOieSBsw6AgdGjDoG5oIHBo4bqnbiBjaOG7qWEg4bqjbmggaMaw4bufbmcgY+G7p2EgY8OhYyBiaeG6v24gxJHhu5ljIGzhuq1wIGzDqm4gbcO0IGjDrG5oLg0KDQotLS0NCg0KKiozLiBIw6BtIGxpw6puIGvhur90IChMaW5rIGZ1bmN0aW9uKSoqDQoNCkdMTSBkw7luZyBt4buZdCBow6BtIGxpw6puIGvhur90IFwoIGcoXGNkb3QpIFwpIMSR4buDIGvhur90IG7hu5FpIHRydW5nIGLDrG5oIFwoXG11X2kgPSBFW3lfaV1cKSB24bubaSBwcmVkaWN0b3IgdHV54bq/biB0w61uaCBcKFxldGFfaVwpOg0KDQokJA0KZyhcbXVfaSkgPSBcZXRhX2kgXHF1YWQgXHRleHR7aGF5fSBccXVhZCBcbXVfaSA9IGdeey0xfShcZXRhX2kpDQokJA0KDQrihpIgQ2hvIHBow6lwIG3DtCBow6xuaCBow7NhIGPDoWMgYmnhur9uIHBo4bqjbiBo4buTaSBjw7MgxJHhurdjIHTDrW5oIHBoaSB0dXnhur9uLCBraMO0bmcgw6JtLCBnaeG7m2kgaOG6oW4gdHJvbmcga2hv4bqjbmcgKDAsMSks4oCmDQoNCioqSMOgbSBsacOqbiBr4bq/dCB0aMaw4budbmcgZMO5bmc6KioNCg0KfCBQaMOibiBwaOG7kWkgIHwgXChcbXVfaSA9IEVbeV9pXVwpICAgIHwgTGluayBmdW5jdGlvbiBcKGcoXG11KVwpICAgICAgICAgICAgICAgICAgIHwgR2hpIGNow7ogICAgICAgICAgICAgICAgICAgfA0KfC0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KfCBOb3JtYWwgICAgIHwgXChcbXUgXGluIFxtYXRoYmJ7Un1cKSAgfCBcKGcoXG11KSA9IFxtdVwpIChpZGVudGl0eSkgICAgICAgICAgICAgICAgfCBI4buTaSBxdXkgdHV54bq/biB0w61uaCBjaHXhuqluICAgfA0KfCBCaW5vbWlhbCAgIHwgXChcbXUgXGluICgwLDEpXCkgICAgICAgfCBcKGcoXG11KSA9IFxsb2cgXGZyYWN7XG11fXsxLVxtdX1cKSAgICAgICAgfCBMb2dpc3RpYyByZWdyZXNzaW9uICAgICAgICB8DQp8IFBvaXNzb24gICAgfCBcKFxtdSA+IDBcKSAgICAgICAgICAgICB8IFwoZyhcbXUpID0gXGxvZyhcbXUpXCkgICAgICAgICAgICAgICAgICAgICAgfCBI4buTaSBxdXkgxJHhur9tICAgICAgICAgICAgICAgfA0KfCBHYW1tYSAgICAgIHwgXChcbXUgPiAwXCkgICAgICAgICAgICAgfCBcKGcoXG11KSA9IFxsb2coXG11KVwpIGhv4bq3YyBcKGcoXG11KSA9IFxmcmFjezF9e1xtdX1cKSB8IE3DtCBow6xuaCBk4buvIGxp4buHdSBkxrDGoW5nICAgIHwNCg0KIyMjICoqNS4zIFbDrSBk4bulIG3DtCBow6xuaCBow7NhIHRyb25nIEdMTSoqDQoNCioqMS4gSOG7k2kgcXV5IExvZ2lzdGljIChuaOG7iyBwaMOibikqKg0KDQpcWw0KeV9pIFxzaW0gXHRleHR7QmVybm91bGxpfShccGlfaSkNClxdDQoNClxbDQpnKFxwaV9pKSA9IFxsb2cgXGxlZnQoXGZyYWN7XHBpX2l9ezEtXHBpX2l9XHJpZ2h0KSA9IFxldGFfaQ0KXF0NCg0KXFsNClxwaV9pID0gUCh5X2kgPSAxIFxtaWQgeF9pKQ0KXF0NCg0KLSBEw7luZyBjaG8gZOG7ryBsaeG7h3UgbmjGsDogc+G7kW5nL2No4bq/dCwgbXVhL2tow7RuZyBtdWEsIMSRw7puZy9zYWnigKYNCg0KLS0tDQoNCioqMi4gSOG7k2kgcXV5IFBvaXNzb24gKMSR4bq/bSkqKg0KDQpcWw0KeV9pIFxzaW0gXHRleHR7UG9pc3Nvbn0oXG11X2kpDQpcXQ0KDQpcWw0KXGxvZyhcbXVfaSkgPSB4X2leVCBcYmV0YQ0KXF0NCg0KLSBcKFxtdV9pXCk6IHPhu5Egc+G7sSBraeG7h24ga+G7syB24buNbmcgeOG6o3kgcmEuDQoNCi0gRMO5bmcgY2hvIGThu68gbGnhu4d1OiBz4buRIGNhIGLhu4duaCwgc+G7kSBs4bqnbiB2aSBwaOG6oW0sIHPhu5EgZ2lhbyBk4buLY2jigKYNCg0KLS0tDQoNCioqMy4gSOG7k2kgcXV5IEdhbW1hIChkxrDGoW5nIGxpw6puIHThu6VjKSoqDQoNClxbDQp5X2kgXHNpbSBcdGV4dHtHYW1tYX0oXGFscGhhLCBcbXVfaSkNClxdDQoNCkjDoG0gbGnDqm4ga+G6v3Q6DQoNClxbDQpnKFxtdV9pKSA9IFxsb2coXG11X2kpIFxxdWFkIFx0ZXh0e2hv4bq3Y30gXHF1YWQgZyhcbXVfaSkgPSBcZnJhY3sxfXtcbXVfaX0NClxdDQoNCi0gRMO5bmcgY2hvIGThu68gbGnhu4d1IGNoaSBwaMOtLCDEkeG7mSBkw6BpLCB0aOG7nWkgZ2lhbg0KDQojIyMgKio1LjQgSMOgbSBwaMawxqFuZyBzYWkgKFZhcmlhbmNlIEZ1bmN0aW9uKSoqDQoNClRyb25nIEdMTSwgcGjGsMahbmcgc2FpIGPhu6dhIFwoIHlfaSBcKSBraMO0bmcgY+G6p24gYuG6sW5nIG5oYXUgbcOgIMSRxrDhu6NjIG3DtCBow6xuaCBow7NhIG5oxrAgaMOgbSBj4bunYSBcKCBcbXVfaSBcKToNCg0KXFsNClx0ZXh0e1Zhcn0oeV9pKSA9IFxwaGkgXGNkb3QgVihcbXVfaSkNClxdDQoNClRyb25nIMSRw7M6DQoNCi0gXCggXHBoaSBcKTogdGhhbSBz4buRIHBow6JuIHTDoW4gKGRpc3BlcnNpb24gcGFyYW1ldGVyKQ0KLSBcKCBWKFxtdSkgXCk6IGjDoG0gcGjGsMahbmcgc2FpIHBo4bulIHRodeG7mWMgdsOgbyB0cnVuZyBiw6xuaCBcKCBcbXUgXCkNCg0KSMOgbSBcKCBWKFxtdSkgXCkgdMO5eSB0aGVvIHBow6JuIHBo4buRaSBuaMawIHNhdToNCg0KfCBQaMOibiBwaOG7kWkgIHwgXCggVihcbXUpIFwpICAgICAgICAgICB8DQp8LS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KfCBOb3JtYWwgICAgIHwgMSAgICAgICAgICAgICAgICAgICAgIHwNCnwgQmlub21pYWwgICB8IFwoIFxtdSAoMSAtIFxtdSkgXCkgICAgfA0KfCBQb2lzc29uICAgIHwgXCggXG11IFwpICAgICAgICAgICAgICB8DQp8IEdhbW1hICAgICAgfCBcKCBcbXVeMiBcKSAgICAgICAgICAgIHwNCg0KVmnhu4djIG3DtCBow6xuaCBow7NhIHBoxrDGoW5nIHNhaSBuaMawIHRyw6puIGdpw7pwIHjhu60gbMO9IMSRxrDhu6NjIGhp4buHbiB0xrDhu6NuZyBwaMawxqFuZyBzYWkgdGhheSDEkeG7lWkgKGhldGVyb3NjZWRhc3RpY2l0eSksIHbhu5FuIGzDoCBt4buZdCBnaeG6oyDEkeG7i25oIGLhu4sgdmkgcGjhuqFtIHRyb25nIHBoxrDGoW5nIHBow6FwIE9MUyAoSOG7k2kgcXV5IHR1eeG6v24gdMOtbmggdGjDtG5nIHRoxrDhu51uZykuDQoNCiMjIyAqKjUuNSBDw6FjIGtow6FpIG5p4buHbSBt4bufIHLhu5luZyoqDQoNCioqQ2Fub25pY2FsIExpbmsgRnVuY3Rpb24qKiBsw6AgaMOgbSBsacOqbiBr4bq/dCBzYW8gY2hvIHByZWRpY3RvciB0dXnhur9uIHTDrW5oIGNow61uaCBsw6AgdGhhbSBz4buRIHThu7Egbmhpw6puIFwoXHRoZXRhXCkgdHJvbmcgcGjDom4gcGjhu5FpIGjhu40gaMOgbSBtxak6DQoNClxbDQpcdGhldGFfaSA9IFxldGFfaSA9IHhfaV5UIFxiZXRhDQpcXQ0KDQpWw60gZOG7pSB24buBIGjDoG0gbGnDqm4ga+G6v3QgY2h14bqpbiAoY2Fub25pY2FsIGxpbmspOg0KDQp8IFBow6JuIHBo4buRaSB8IEjDoG0gbGnDqm4ga+G6v3QgKExpbmsgZnVuY3Rpb24pIHwNCnwtLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18DQp8IEJpbm9taWFsICB8IGxvZ2l0OiBcKFxsb2dcZnJhY3tcbXV9ezEtXG11fVwpICAgICAgICAgIHwNCnwgUG9pc3NvbiAgIHwgbG9nOiBcKFxsb2coXG11KVwpICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCBOb3JtYWwgICAgfCBpZGVudGl0eTogXChcbXVcKSAgICAgICAgICAgICAgICAgICAgICAgICB8DQoNCj4gKipMxrB1IMO9OioqIETDuSBHTE0gZ+G7jWkgbMOgICJ0dXnhur9uIHTDrW5oIiwgbmjGsG5nIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgXCggeSBcKSB2w6AgXCggeCBcKSBjw7MgdGjhu4MgKipwaGkgdHV54bq/bioqIGRvIHPhu60gZOG7pW5nIGjDoG0gbGnDqm4ga+G6v3QgKGxpbmsgZnVuY3Rpb24pLg0KDQojIyAqKkNIxq/GoE5HIDY6IMav4buaQyBMxq/hu6JORyBUUk9ORyBNw5QgSMOMTkggVFVZ4bq+TiBUw41OSCBU4buUTkcgUVXDgVQgKEdMTXMpKioNCg0KIyMjICoqNi4xIEdp4bubaSB0aGnhu4d1KioNCg0KU2F1IGtoaSB4w6FjIMSR4buLbmggxJHGsOG7o2MgY+G6pXUgdHLDumMgY+G7p2EgbeG7mXQgR0xNIChn4buTbSBwaMOibiBwaOG7kWkgeMOhYyBzdeG6pXQsIGjDoG0gbGnDqm4ga+G6v3QgdsOgIHRow6BuaCBwaOG6p24gdHV54bq/biB0w61uaCksIGLGsOG7m2MgdGnhur9wIHRoZW8gbMOgIMaw4bubYyBsxrDhu6NuZyBjw6FjIGjhu4cgc+G7kSBo4buTaSBxdXkgXChcYmV0YVwpIHRyb25nIG3DtCBow6xuaC4NCg0KS2jDoWMgduG7m2kgaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggY+G7lSDEkWnhu4NuIOKAkyBuxqFpIHRhIGTDuW5nIHBoxrDGoW5nIHBow6FwIGLDrG5oIHBoxrDGoW5nIHThu5FpIHRoaeG7g3UgKE9MUykg4oCTIHRyb25nIEdMTSwgY8OhYyBo4buHIHPhu5EgxJHGsOG7o2MgxrDhu5tjIGzGsOG7o25nIGLhurFuZyAqKnBoxrDGoW5nIHBow6FwIGjhu6NwIGzDvSB04buRaSDEkWEgKE1heGltdW0gTGlrZWxpaG9vZCBFc3RpbWF0aW9uIC0gTUxFKSoqIHRow7RuZyBxdWEgbeG7mXQgdGh14bqtdCB0b8OhbiBn4buNaSBsw6AgKipJdGVyYXRpdmVseSBSZXdlaWdodGVkIExlYXN0IFNxdWFyZXMgKElSTFMpKiouDQoNClBoxrDGoW5nIHBow6FwIElSTFMgdGjhu7FjIGhp4buHbiB2aeG7h2MgY+G6rXAgbmjhuq10IGPDoWMgxrDhu5tjIGzGsOG7o25nIFwoXGJldGFcKSBs4bq3cCDEkWkgbOG6t3AgbOG6oWksIG3hu5dpIGzhuqduIGThu7FhIHRyw6puIHRy4buNbmcgc+G7kSDEkcaw4bujYyDEkWnhu4F1IGNo4buJbmggc2FvIGNobyBwaMO5IGjhu6NwIHbhu5tpIHBow6JuIHBo4buRaSBj4bunYSBk4buvIGxp4buHdSB2w6AgaMOgbSBsacOqbiBr4bq/dCDEkcaw4bujYyBjaOG7jW4uDQoNCiMjIyAqKjYuMiBU4buVbmcgcXVhbiB24buBIMaw4bubYyBsxrDhu6NuZyBo4bujcCBsw70gdOG7kWkgxJFhIChNTEUpIHRyb25nIEdMTSoqDQoNCkNobyBk4buvIGxp4buHdSBn4buTbToNCg0KLSBCaeG6v24gcGjhuqNuIGjhu5NpOiBcKCB5XzEsIHlfMiwgXGxkb3RzLCB5X24gXCkgY8OzIHRo4buDIGzDoCBiaeG6v24gxJHhur9tLCBuaOG7iyBwaMOibiBob+G6t2MgbGnDqm4gdOG7pWMgZMawxqFuZ+KApg0KDQotIEJp4bq/biBnaeG6o2kgdGjDrWNoOiBcKCB4X3tpMX0sIFxsZG90cywgeF97aXB9IFwpIHbhu5tpIFwoaT0xLCBcbGRvdHMsIG5cKS4NCg0KTcO0IGjDrG5oIEdMTSDEkcaw4bujYyBiaeG7g3UgZGnhu4VuIG5oxrAgc2F1Og0KDQpcWw0KZyhcbXVfaSkgPSBcZXRhX2kgPSBcbWF0aGJme3h9X2leVCBcYm9sZHN5bWJvbHtcYmV0YX0NClxdDQoNCnbhu5tpDQoNClxbDQpcbXVfaSA9IEVbeV9pXSA9IGdeey0xfShcbWF0aGJme3h9X2leVCBcYm9sZHN5bWJvbHtcYmV0YX0pDQpcXQ0KDQpN4bulYyB0acOqdSBsw6AgdMOsbSDGsOG7m2MgbMaw4bujbmcgXChcaGF0e1xib2xkc3ltYm9se1xiZXRhfX1cKSBzYW8gY2hvIGjDoG0gbG9nLWxpa2VsaWhvb2QgxJHhuqF0IGPhu7FjIMSR4bqhaToNCg0KXFsNClxlbGwoXGJvbGRzeW1ib2x7XGJldGF9KSA9IFxzdW1fe2k9MX1ebiBcbG9nIGYoeV9pOyBcdGhldGFfaSkNClxdDQoNCnRyb25nIMSRw7M6DQoNCi0gXChmKHlfaTsgXHRoZXRhX2kpXCkgbMOgIGjDoG0gbeG6rXQgxJHhu5kgeMOhYyBzdeG6pXQgKGhv4bq3YyBow6BtIGto4buRaSB4w6FjIHN14bqldCkgY+G7p2EgYmnhur9uIFwoeV9pXCksDQoNCi0gXChcdGhldGFfaVwpIGzDoCB0aGFtIHPhu5EgdOG7sSBuaGnDqm4gdHJvbmcgcGjDom4gcGjhu5FpIHRodeG7mWMgaOG7jSBow6BtIG3FqSwNCg0KLSBcKFx0aGV0YV9pXCkgY8OzIHF1YW4gaOG7hyB24bubaSBcKFxtdV9pXCksIHThu6sgxJHDsyBsacOqbiBo4buHIHbhu5tpIFwoXGJvbGRzeW1ib2x7XGJldGF9XCkuDQoNClZp4buHYyDGsOG7m2MgbMaw4bujbmcgbsOgeSB0aMaw4budbmcgxJHGsOG7o2MgdGjhu7FjIGhp4buHbiBi4bqxbmcgcGjGsMahbmcgcGjDoXAgKipo4bujcCBsw70gdOG7kWkgxJFhIChNTEUpKiosIHPhu60gZOG7pW5nIHRodeG6rXQgdG/DoW4gKipJdGVyYXRpdmVseSBSZXdlaWdodGVkIExlYXN0IFNxdWFyZXMgKElSTFMpKiouDQoNCiMjIyAqKjYuMyBQaMawxqFuZyBwaMOhcCBJUkxTIChJdGVyYXRpdmVseSBSZXdlaWdodGVkIExlYXN0IFNxdWFyZXMpKioNCg0KKioxLiBUaHXhuq10IHRvw6FuIElSTFMgKEl0ZXJhdGl2ZWx5IFJld2VpZ2h0ZWQgTGVhc3QgU3F1YXJlcyk6KioNCg0KR0xNIHPhu60gZOG7pW5nIHRodeG6rXQgdG/DoW4gSVJMUyDEkeG7gyB0w6xtIMaw4bubYyBsxrDhu6NuZyBcKFxoYXR7XGJvbGRzeW1ib2x7XGJldGF9fVwpLiBUaHXhuq10IHRvw6FuIGThu7FhIHRyw6puIHZp4buHYyBs4bq3cCBs4bqhaSBjw6FjIGLGsOG7m2MgaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggY8OzIHRy4buNbmcgc+G7kS4NCg0KKioyLiDDnSB0xrDhu59uZyBjxqEgYuG6o246KioNCg0KLSDhu54gbeG7l2kgdsOybmcgbOG6t3AsIG3DtCBow6xuaCBHTE0gxJHGsOG7o2MgeOG6pXAgeOG7iSBi4bqxbmcgbeG7mXQgaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggduG7m2kgdHLhu41uZyBz4buRLg0KDQotICoqQmnhur9uIGdp4bqjICh3b3JraW5nIHJlc3BvbnNlKSoqIFwoIFxtYXRoYmZ7en0gXCkgdsOgICoqbWEgdHLhuq1uIHRy4buNbmcgc+G7kSoqIFwoIFxtYXRoYmZ7V30gXCkgxJHGsOG7o2MgY+G6rXAgbmjhuq10IGxpw6puIHThu6VjIOG7nyBt4buXaSBixrDhu5tjLg0KDQoqKjMuIEjhu4cgcGjGsMahbmcgdHLDrG5oIElSTFM6KioNCg0KXFsNClxtYXRoYmZ7WH1eVCBcbWF0aGJme1d9IFxtYXRoYmZ7WH0gXGhhdHtcYm9sZHN5bWJvbHtcYmV0YX19ID0gXG1hdGhiZntYfV5UIFxtYXRoYmZ7V30gXG1hdGhiZnt6fQ0KXF0NCg0KVHJvbmcgxJHDszoNCg0KLSBcKFxtYXRoYmZ7WH1cKSBsw6AgbWEgdHLhuq1uIHRoaeG6v3Qga+G6vywNCg0KLSBcKFxtYXRoYmZ7V31cKSBsw6AgbWEgdHLhuq1uIHRy4buNbmcgc+G7kSBrw61jaCB0aMaw4bubYyBcKG4gXHRpbWVzIG5cKSwNCg0KLSBcKFxtYXRoYmZ7en1cKSBsw6AgdmVjdG9yIGJp4bq/biBnaeG6oyBcKG4gXHRpbWVzIDFcKSwgdMOtbmggdGhlbyBjw7RuZyB0aOG7qWM6DQoNClxbDQp6X2kgPSBcZXRhX2kgKyBcZnJhY3t5X2kgLSBcbXVfaX17XGZyYWN7ZCBcbXVfaX17ZCBcZXRhX2l9fQ0KXF0NCg0KLSBUcuG7jW5nIHPhu5EgXChXX2lcKSDEkcaw4bujYyB0w61uaCB0aGVvOg0KDQpcWw0KV19pID0gXGxlZnQoXGZyYWN7ZCBcbXVfaX17ZCBcZXRhX2l9XHJpZ2h0KV4yIFxCaWcvIFxtYXRocm17VmFyfSh5X2kpDQpcXQ0KDQpRdcOhIHRyw6xuaCBuw6B5IMSRxrDhu6NjIGzhurdwIGzhuqFpIGNobyDEkeG6v24ga2hpIGPDoWMgxrDhu5tjIGzGsOG7o25nIFwoXGJvbGRzeW1ib2x7XGJldGF9XCkgaOG7mWkgdOG7pS4NCg0KIyMjICoqNi40IEjDoG0gxJFp4buDbSwgbWEgdHLhuq1uIEZpc2hlciB2w6AgcGjGsMahbmcgc2FpIGPhu6dhIMaw4bubYyBsxrDhu6NuZyoqDQoNCioqSMOgbSDEkWnhu4NtIChTY29yZSBGdW5jdGlvbikqKg0KDQpIw6BtIMSRaeG7g20gbMOgIMSR4bqhbyBow6BtIGPhu6dhIGxvZy1saWtlbGlob29kIHRoZW8gdmVjdG9yIGjhu4cgc+G7kSBcKFxib2xkc3ltYm9se1xiZXRhfVwpOg0KDQpcWw0KVShcYm9sZHN5bWJvbHtcYmV0YX0pID0gXGZyYWN7XHBhcnRpYWwgXGVsbChcYm9sZHN5bWJvbHtcYmV0YX0pfXtccGFydGlhbCBcYm9sZHN5bWJvbHtcYmV0YX19DQpcXQ0KDQrEkMOieSBsw6AgaOG7hyBwaMawxqFuZyB0csOsbmggbcOgIGtoaSBnaeG6o2kgXChVKFxib2xkc3ltYm9se1xiZXRhfSkgPSAwXCksIHRhIHRodSDEkcaw4bujYyDGsOG7m2MgbMaw4bujbmcgY+G7sWMgxJHhuqFpIFwoXGhhdHtcYm9sZHN5bWJvbHtcYmV0YX19XCkuDQoNCi0tLQ0KDQoqKk1hIHRy4bqtbiB0aMO0bmcgdGluIEZpc2hlcioqDQoNCk1hIHRy4bqtbiB0aMO0bmcgdGluIEZpc2hlciBsw6Aga+G7syB24buNbmcgw6JtIGPhu6dhIMSR4bqhbyBow6BtIGLhuq1jIGhhaSBj4bunYSBsb2ctbGlrZWxpaG9vZDoNCg0KXFsNClxtYXRoY2Fse0l9KFxib2xkc3ltYm9se1xiZXRhfSkgPSAtIFxtYXRoYmJ7RX0gXGxlZnRbIFxmcmFje1xwYXJ0aWFsXjIgXGVsbChcYm9sZHN5bWJvbHtcYmV0YX0pfXtccGFydGlhbCBcYm9sZHN5bWJvbHtcYmV0YX0gXCwgXHBhcnRpYWwgXGJvbGRzeW1ib2x7XGJldGF9XlR9IFxyaWdodF0NClxdDQoNCk1hIHRy4bqtbiBuw6B5IMSRw7NuZyB2YWkgdHLDsiBuaMawIG3hu5l0IHRoxrDhu5tjIMSRbyDEkeG7mSAic+G6r2MgbsOpdCIgY+G7p2EgbG9nLWxpa2VsaWhvb2QgdOG6oWkgxJFp4buDbSBj4buxYyDEkeG6oWkgdsOgIMSRxrDhu6NjIGTDuW5nIMSR4buDIMSRw6FuaCBnacOhIMSR4buZIGNow61uaCB4w6FjIGPhu6dhIMaw4bubYyBsxrDhu6NuZy4NCg0KLS0tDQoNCioqUGjGsMahbmcgc2FpIGPhu6dhIFwoXGhhdHtcYm9sZHN5bWJvbHtcYmV0YX19XCkqKg0KDQpLaGkgxJHDoyBjw7MgbWEgdHLhuq1uIHRow7RuZyB0aW4gRmlzaGVyLCBwaMawxqFuZyBzYWkgaGnhu4dwIHBoxrDGoW5nIHNhaSBj4bunYSB2ZWN0b3IgaOG7hyBz4buRIMaw4bubYyBsxrDhu6NuZyDEkcaw4bujYyB0w61uaCBsw6A6DQoNClxbDQpcbWF0aHJte1Zhcn0oXGhhdHtcYm9sZHN5bWJvbHtcYmV0YX19KSA9IFxtYXRoY2Fse0l9KFxoYXR7XGJvbGRzeW1ib2x7XGJldGF9fSleey0xfQ0KXF0NCg0KTuG6v3Ugc+G7rSBk4bulbmcgdGh14bqtdCB0b8OhbiAqKklSTFMqKiwgbWEgdHLhuq1uIHRow7RuZyB0aW4gRmlzaGVyIMSRxrDhu6NjIHjhuqVwIHjhu4kgYuG7n2k6DQoNClxbDQpcbWF0aHJte1Zhcn0oXGhhdHtcYm9sZHN5bWJvbHtcYmV0YX19KSA9IChcbWF0aGJme1h9XlQgXG1hdGhiZntXfSBcbWF0aGJme1h9KV57LTF9DQpcXQ0KDQpUcm9uZyDEkcOzOg0KDQotIFwoXG1hdGhiZntYfVwpOiBtYSB0cuG6rW4gdGhp4bq/dCBr4bq/LA0KDQotIFwoXG1hdGhiZntXfVwpOiBtYSB0cuG6rW4gdHLhu41uZyBz4buRIHThuqFpIG5naGnhu4dtIGjhu5lpIHThu6UsDQoNCi0gQ8O0bmcgdGjhu6ljIG7DoHkgeHXhuqV0IGhp4buHbiB04buxIG5oacOqbiB04burIGLGsOG7m2MgZ2nhuqNpIGjhu4cgcGjGsMahbmcgdHLDrG5oIElSTFMuDQoNCi0tLQ0KDQoqKkdoaSBjaMO6KioNCg0KLSBDw7RuZyB0aOG7qWMgcGjGsMahbmcgc2FpIHRyw6puIHLhuqV0IHF1YW4gdHLhu41uZyDEkeG7gyB0w61uaCBraG/huqNuZyB0aW4gY+G6rXkgdsOgIGtp4buDbSDEkeG7i25oIGdp4bqjIHRodXnhur90IHRyb25nIEdMTS4NCg0KLSBW4bubaSBjw6FjIG3DtCBow6xuaCBs4bubbiwgbWEgdHLhuq1uIFwoKFxtYXRoYmZ7WH1eVCBcbWF0aGJme1d9IFxtYXRoYmZ7WH0pXnstMX1cKSB0aMaw4budbmcgxJHGsOG7o2MgdMOtbmggdGjDtG5nIHF1YSBnaeG6o2kgaOG7hyBwaMawxqFuZyB0csOsbmggdGhheSB2w6wgxJHhuqNvIHRy4buxYyB0aeG6v3AgxJHhu4MgdHLDoW5oIHNhaSBz4buRIHPhu5EgaOG7jWMuDQoNCiMjIyAqKjYuNSBTYWkgc+G7kSBjaHXhuqluIHbDoCBraG/huqNuZyB0aW4gY+G6rXkqKg0KDQoqKlNhaSBz4buRIGNodeG6qW4gKFN0YW5kYXJkIEVycm9yKSoqDQoNClNhdSBraGkgY8OzIMSRxrDhu6NjIMaw4bubYyBsxrDhu6NuZyBcKFxoYXR7XGJvbGRzeW1ib2x7XGJldGF9fVwpIHbDoCBtYSB0cuG6rW4gcGjGsMahbmcgc2FpIGhp4buHcCBwaMawxqFuZyBzYWkgXChcbWF0aHJte1Zhcn0oXGhhdHtcYm9sZHN5bWJvbHtcYmV0YX19KVwpLCB0YSB0w61uaCAqKnNhaSBz4buRIGNodeG6qW4qKiBjaG8gdOG7q25nIGjhu4cgc+G7kSBcKFxoYXR7XGJldGF9X2pcKSBuaMawIHNhdToNCg0KXFsNClxtYXRocm17U0V9KFxoYXR7XGJldGF9X2opID0gXHNxcnR7W1xtYXRocm17VmFyfShcaGF0e1xib2xkc3ltYm9se1xiZXRhfX0pXV97amp9fQ0KXF0NCg0KVHJvbmcgxJHDsywgXChbXGNkb3RdX3tqan1cKSBsw6AgcGjhuqduIHThu60gaMOgbmcgXChqXCksIGPhu5l0IFwoalwpIHRyb25nIG1hIHRy4bqtbiBwaMawxqFuZyBzYWkuDQoNCi0tLQ0KDQoqKktob+G6o25nIHRpbiBj4bqteSBcKDEwMCgxIC0gXGFscGhhKVwlXCkqKg0KDQpLaG/huqNuZyB0aW4gY+G6rXkgY2hvIGjhu4cgc+G7kSBcKFxoYXR7XGJldGF9X2pcKSDEkcaw4bujYyB0w61uaCBi4bqxbmcgY8O0bmcgdGjhu6ljOg0KDQpcWw0KXGhhdHtcYmV0YX1faiBccG0gel97XGFscGhhLzJ9IFxjZG90IFxtYXRocm17U0V9KFxoYXR7XGJldGF9X2opDQpcXQ0KDQpUcm9uZyDEkcOzOg0KDQotIFwoel97XGFscGhhLzJ9XCkgbMOgIGLDoWNoIHBow6JuIHbhu4sgXCgxIC0gXGFscGhhLzJcKSBj4bunYSBwaMOibiBwaOG7kWkgY2h14bqpbiBjaHXhuqluIGjDs2EgKHRoxrDhu51uZyB0cmEgdOG7qyBi4bqjbmcgWiksDQoNCi0gVsOtIGThu6U6IHbhu5tpIFwoXGFscGhhID0gMC4wNVwpLCBcKHpfezAuMDI1fSBcYXBwcm94IDEuOTZcKSAodMawxqFuZyDhu6luZyBraG/huqNuZyB0aW4gY+G6rXkgOTUlKS4NCg0KLS0tDQoNCioqS2nhu4NtIMSR4buLbmggV2FsZCoqDQoNCktp4buDbSDEkeG7i25oIFdhbGQgZ2nDunAgxJHDoW5oIGdpw6EgZ2nhuqMgdGh1eeG6v3Q6DQoNClxbDQpIXzA6IFxiZXRhX2ogPSAwIFxxdWFkIFx0ZXh0e3ZzfSBccXVhZCBIXzE6IFxiZXRhX2ogXG5lcSAwDQpcXQ0KDQpUaOG7kW5nIGvDqiBraeG7g20gxJHhu4tuaDoNCg0KXFsNClogPSBcZnJhY3tcaGF0e1xiZXRhfV9qfXtcbWF0aHJte1NFfShcaGF0e1xiZXRhfV9qKX0gXHNpbSBcbWF0aGNhbHtOfSgwLCAxKQ0KXF0NCg0KROG7sWEgdsOgbyBnacOhIHRy4buLIFwoWlwpLCB0YSBjw7MgdGjhu4MgdMOtbmggcC12YWx1ZSB2w6AgxJHGsGEgcmEga+G6v3QgbHXhuq1uIHRo4buRbmcga8OqLg0KDQotLS0NCg0KKipHaGkgY2jDuioqDQoNCi0gS2nhu4NtIMSR4buLbmggV2FsZCDEkcaw4bujYyBkw7luZyBwaOG7lSBiaeG6v24gZG8gdMOtbmggxJHGoW4gZ2nhuqNuIHbDoCBjw7MgdGjhu4MgdGjhu7FjIGhp4buHbiBuZ2F5IHNhdSBraGkgY8OzIMaw4bubYyBsxrDhu6NuZyB2w6AgcGjGsMahbmcgc2FpLg0KDQotIE7hur91IFwoIHxafCA+IHpfe1xhbHBoYS8yfSBcKSwgYsOhYyBi4buPIFwoSF8wXCksIHThu6ljIGzDoCBo4buHIHPhu5EgXChcYmV0YV9qXCkgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqi4NCg0KIyMjICoqNi42IMav4bubYyBsxrDhu6NuZyB0aGFtIHPhu5EgcGjDom4gdMOhbioqDQoNClRyb25nIG3hu5l0IHPhu5EgbcO0IGjDrG5oIEdMTSwgxJHhurdjIGJp4buHdCBsw6Aga2hpIHBow6JuIHBo4buRaSB0aHXhu5ljIGjhu40gcGjDom4gcGjhu5FpIG3FqSAoZXhwb25lbnRpYWwgZmFtaWx5KSAqKmtow7RuZyBjaHXhuqluIGjDs2EqKiwgdGEgY+G6p24gxrDhu5tjIGzGsOG7o25nIHRoYW0gc+G7kSBwaMOibiB0w6FuIFwoXHBoaVwpLg0KDQpDw7RuZyB0aOG7qWMgxrDhu5tjIGzGsOG7o25nOg0KDQokJA0KXGhhdHtccGhpfSA9IFxmcmFjezF9e24gLSBwfSBcc3VtX3tpPTF9XntufSBcZnJhY3soeV9pIC0gXGhhdHtcbXV9X2kpXjJ9e1YoXGhhdHtcbXV9X2kpfQ0KJCQNCg0KVHJvbmcgxJHDszoNCg0KLSBcKG5cKTogc+G7kSBxdWFuIHPDoXQgIA0KDQotIFwocFwpOiBz4buRIHRoYW0gc+G7kSB0cm9uZyBtw7QgaMOsbmggKGJhbyBn4buTbSBo4buHIHPhu5EgY2jhurduIG7hur91IGPDsykgIA0KDQotIFwoXGhhdHtcbXV9X2kgPSBcbWF0aGJie0V9W3lfaV0gPSBnXnstMX0oXGV0YV9pKVwpOiBnacOhIHRy4buLIGvhu7MgduG7jW5nIMSRxrDhu6NjIMaw4bubYyBsxrDhu6NuZyAgDQoNCi0gXChWKFxoYXR7XG11fV9pKVwpOiBow6BtIHBoxrDGoW5nIHNhaSwgcGjhu6UgdGh14buZYyB2w6BvIHBow6JuIHBo4buRaToNCg0KfCBQaMOibiBwaOG7kWkgICAgICAgIHwgSMOgbSBwaMawxqFuZyBzYWkgXChWKFxtdSlcKSAgICAgfA0KfC0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KfCBHYXVzc2lhbiAgICAgICAgIHwgXCgxXCkgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfCBQb2lzc29uICAgICAgICAgIHwgXChcbXVcKSAgICAgICAgICAgICAgICAgICAgICAgfA0KfCBCaW5vbWlhbCAobG9naXQpIHwgXChcbXUoMSAtIFxtdSlcKSAgICAgICAgICAgICAgfA0KDQojIyAqKkNIxq/GoE5HIDc6IMSQw4FOSCBHScOBIE3hu6hDIMSQ4buYIFBIw5kgSOG7olAgVsOAIEzhu7BBIENI4buMTiBNw5QgSMOMTkggVFJPTkcgR0xNKioNCg0KIyMjICoqNy4xIEdp4bubaSB0aGnhu4d1KioNCg0KU2F1IGtoaSDGsOG7m2MgbMaw4bujbmcgY8OhYyB0aGFtIHPhu5EgJFxiZXRhJCB0cm9uZyBHTE0sIGLGsOG7m2MgdGnhur9wIHRoZW8gbMOgIMSRw6FuaCBnacOhIHhlbSBtw7QgaMOsbmggY8OzIHBow7kgaOG7o3AgduG7m2kgZOG7ryBsaeG7h3Uga2jDtG5nLCB2w6AgbuG6v3UgY8OzIG5oaeG7gXUgbcO0IGjDrG5oIGPhuqFuaCB0cmFuaCwgdGjDrCBuw6puIGNo4buNbiBtw7QgaMOsbmggbsOgbyBsw6AgdOG7kXQgbmjhuqV0Lg0KDQpDw6FjIGPDtG5nIGPhu6UgxJHDoW5oIGdpw6EgYmFvIGfhu5NtOg0KDQotIERldmlhbmNlICjEkeG7mSBs4buHY2gpDQoNCi0gS2nhu4NtIMSR4buLbmggJFxjaGleMiQNCg0KLSBBSUMsIEJJQw0KDQotIFNvIHPDoW5oIG3DtCBow6xuaCBs4buTbmcgdsOgIGtow7RuZyBs4buTbmcNCg0KLSDEkOG7kyB0aOG7iyBwaOG6p24gZMawIHbDoCDEkWnhu4NtIOG6o25oIGjGsOG7n25nDQoNCiMjIyAqKjcuMiBEZXZpYW5jZSDigJMgxJFvIGzGsOG7nW5nIG3hu6ljIMSR4buZIHBow7kgaOG7o3AgY+G7p2EgbcO0IGjDrG5oKioNCg0KKirEkOG7i25oIG5naMSpYToqKg0KDQpEZXZpYW5jZSBsw6AgxJHhuqFpIGzGsOG7o25nIMSRbyBz4buxIGtow6FjIGJp4buHdCBnaeG7r2EgbcO0IGjDrG5oIGhp4buHbiB04bqhaSB2w6AgbcO0IGjDrG5oIMSR4bqneSDEkeG7pyAoc2F0dXJhdGVkIG1vZGVsKSDigJMgdOG7qWMgbcO0IGjDrG5oIGto4bubcCBob8OgbiB0b8OgbiB24bubaSBk4buvIGxp4buHdS4NCg0KJCQNCkQoeTsgXGhhdHtcbXV9KSA9IDIgXGxlZnRbIFxlbGwoeTsgeSkgLSBcZWxsKFxoYXR7XG11fTsgeSkgXHJpZ2h0XQ0KJCQNCg0KKipHaeG6o2kgdGjDrWNoIGvDvSBoaeG7h3U6KioNCg0KLSAkXGVsbCh5OyB5KSQ6IGxvZy1saWtlbGlob29kIGPhu6dhIG3DtCBow6xuaCBiw6NvIGjDsmEgKHNhdHVyYXRlZCBtb2RlbCkNCg0KLSAkXGVsbChcaGF0e1xtdX07IHkpJDogbG9nLWxpa2VsaWhvb2QgY+G7p2EgbcO0IGjDrG5oIMSRYW5nIHjDqXQNCg0KXChcUmlnaHRhcnJvd1wpIERldmlhbmNlIGPDoG5nIG5o4buPIOKGkiBtw7QgaMOsbmggY8OgbmcgZ+G6p24gduG7m2kgbcO0IGjDrG5oIGLDo28gaMOyYSDihpIgcGjDuSBo4bujcCBoxqFuLg0KDQojIyMgKio3LjMgU28gc8OhbmggbcO0IGjDrG5oIGLhurFuZyBraeG7g20gxJHhu4tuaCBkZXZpYW5jZSoqDQoNCktoaSBoYWkgbcO0IGjDrG5oIGzhu5NuZyBuaGF1LCB0YSBjw7MgdGjhu4Mgc28gc8OhbmggYuG6sW5nIGtp4buDbSDEkeG7i25oIHNhaSBiaeG7h3QgZGV2aWFuY2U6DQoNCioqQ8O0bmcgdGjhu6ljIGtp4buDbSDEkeG7i25oOioqDQoNCiQkDQpcRGVsdGEgRCA9IERfe1x0ZXh0e3JlZHVjZWR9fSAtIERfe1x0ZXh0e2Z1bGx9fSBcc2ltIFxjaGleMl97ZGZ9DQokJA0KDQpUcm9uZyDEkcOzOg0KDQotICRkZiQ6IHPhu5EgdGhhbSBz4buRIGLhu4sgcsOgbmcgYnXhu5ljIHRyb25nIG3DtCBow6xuaCBuaOG7jyBoxqFuDQoNClwoXFJpZ2h0YXJyb3dcKSBO4bq/dSAkXERlbHRhIEQkIGzhu5tuIHbDoCBwLXZhbHVlIG5o4buPIOKGkiBtw7QgaMOsbmggxJHhuqd5IMSR4bunIHThu5F0IGjGoW4uDQoNCiMjIyAqKjcuNCBBSUMgdsOgIEJJQyDigJMgbOG7sWEgY2jhu41uIGdp4buvYSBjw6FjIG3DtCBow6xuaCBraMO0bmcgbOG7k25nKioNCg0KS2hpIGPDoWMgbcO0IGjDrG5oIGtow7RuZyBs4buTbmcgbmhhdSwgdGEgZMO5bmcgdGnDqnUgY2jDrSB0aMO0bmcgdGluIMSR4buDIHNvIHPDoW5oOg0KDQoqKkFJQyAoQWthaWtlIEluZm9ybWF0aW9uIENyaXRlcmlvbik6KioNCg0KJCQNCkFJQyA9IC0yXGVsbCArIDJrDQokJA0KDQotICRcZWxsJDogbG9nLWxpa2VsaWhvb2QgIA0KDQotICRrJDogc+G7kSB0aGFtIHPhu5EgdHJvbmcgbcO0IGjDrG5oDQoNCioqQklDIChCYXllc2lhbiBJbmZvcm1hdGlvbiBDcml0ZXJpb24pOioqDQoNCiQkDQpCSUMgPSAtMlxlbGwgKyBcbG9nKG4pIFxjZG90IGsNCiQkDQoNCi0gJG4kOiBz4buRIHF1YW4gc8OhdA0KDQpcKFxSaWdodGFycm93XCkgQ2jhu41uIG3DtCBow6xuaCBjw7MgQUlDL0JJQyAqKnRo4bqlcCBoxqFuKiouICANCiANClwoXFJpZ2h0YXJyb3dcKSBCSUMgcGjhuqF0IGPDoWMgbcO0IGjDrG5oIHBo4bupYyB04bqhcCAqKm5oaeG7gXUgaMahbioqIHNvIHbhu5tpIEFJQy4NCg0KLS0tDQoNCiMjIyAqKjcuNSDEkOG7kyB0aOG7iyBjaOG6qW4gxJFvw6FuIHbDoCBwaOG6p24gZMawKioNCg0KKipQaOG6p24gZMawIChyZXNpZHVhbHMpOioqDQoNCi0gKipQaOG6p24gZMawIHRow7QgKHJhdyByZXNpZHVhbCk6KioNCg0KJCQNCmVfaSA9IHlfaSAtIFxoYXR7XG11fV9pDQokJA0KDQotICoqUGjhuqduIGTGsCBQZWFyc29uOioqDQoNCiQkDQpyX2kgPSBcZnJhY3t5X2kgLSBcaGF0e1xtdX1faX17XHNxcnR7VihcaGF0e1xtdX1faSl9fQ0KJCQNCg0KLSAqKlBo4bqnbiBkxrAgZGV2aWFuY2U6KioNCg0KJCQNCmRfaSA9IFx0ZXh0e3NpZ259KHlfaSAtIFxoYXR7XG11fV9pKSBcY2RvdCBcc3FydHsyXGxlZnRbXGVsbCh5X2k7IHlfaSkgLSBcZWxsKFxoYXR7XG11fV9pOyB5X2kpXHJpZ2h0XX0NCiQkDQoNCioqQmnhu4N1IMSR4buTIGtp4buDbSB0cmEgbcO0IGjDrG5oIChEaWFnbm9zdGljIHBsb3RzKToqKg0KDQotIFJlc2lkdWFscyB2cyBGaXR0ZWQNCg0KLSBOb3JtYWwgUS1RIChu4bq/dSBtw7QgaMOsbmggZ+G6p24gcGjDom4gcGjhu5FpIGNodeG6qW4pDQoNCi0gU2NhbGUtTG9jYXRpb24gcGxvdA0KDQotIENvb2vigJlzIGRpc3RhbmNlIHZzIExldmVyYWdlDQoNCkPDoWMgYmnhu4N1IMSR4buTIG7DoHkgZ2nDunAgcGjDoXQgaGnhu4duICoqxJFp4buDbSBuZ2/huqFpIGxhaSoqIHbDoCAqKsSRaeG7g20g4bqjbmggaMaw4bufbmcgbeG6oW5oKiogxJHhur9uIG3DtCBow6xuaC4NCg0KLS0tDQoNCiMjIyAqKjcuNiBLaeG7g20gxJHhu4tuaCBQZWFyc29uIENoaS1zcXVhcmUqKg0KDQpQaMOpcCBraeG7g20gxJHhu4tuaCBQZWFyc29uIMSRbyBz4buxIGtow6FjIGJp4buHdCBnaeG7r2EgZOG7ryBsaeG7h3UgcXVhbiBzw6F0IHbDoCBnacOhIHRy4buLIGvhu7MgduG7jW5nIHThu6sgbcO0IGjDrG5oOg0KDQokJA0KWF4yID0gXHN1bV97aT0xfV5uIFxmcmFjeyh5X2kgLSBcaGF0e1xtdX1faSleMn17VihcaGF0e1xtdX1faSl9DQokJA0KDQpO4bq/dSAkWF4yJCBs4bubbiBoxqFuIG3hu6ljIGvhu7MgduG7jW5nIHRoZW8gcGjDom4gcGjhu5FpICRcY2hpXjJfe2RmfSQg4oaSIG3DtCBow6xuaCBjw7MgdGjhu4MgKipraMO0bmcgcGjDuSBo4bujcCoqIHbhu5tpIGThu68gbGnhu4d1Lg0KDQojIyMgKio3LjcgxJDhu5kgcGjDom4gdMOhbiB2w6AgduG6pW4gxJHhu4Egb3ZlcmRpc3BlcnNpb24qKg0KDQpN4buZdCBz4buRIG3DtCBow6xuaCBHTE0gbmjGsCAqKlBvaXNzb24qKiBob+G6t2MgKipCaW5vbWlhbCoqIGdp4bqjIMSR4buLbmggaOG7hyBz4buRIHBow6JuIHTDoW4gbMOgOg0KDQokJA0KXHBoaSA9IDENCiQkDQoNClR1eSBuaGnDqm4sIHRyb25nIHRo4buxYyB04bq/LCBu4bq/dSAqKnBoxrDGoW5nIHNhaSBxdWFuIHPDoXQqKiBs4bubbiBoxqFuICoqcGjGsMahbmcgc2FpIGzDvSB0aHV54bq/dCoqLCB0YSBn4buNaSBsw6AgKipvdmVyZGlzcGVyc2lvbioqIChxdcOhIHBow6JuIHTDoW4pLg0KDQoqKktp4buDbSB0cmEgb3ZlcmRpc3BlcnNpb24qKjoNCg0KSOG7hyBz4buRIHBow6JuIHTDoW4gxrDhu5tjIGzGsOG7o25nIMSRxrDhu6NjIHTDrW5oIHRoZW8gY8O0bmcgdGjhu6ljOg0KDQokJA0KXGhhdHtccGhpfSA9IFxmcmFje1x0ZXh0e0RldmlhbmNlfX17biAtIHB9DQokJA0KDQotICRuJDogc+G7kSBxdWFuIHPDoXQgIA0KDQotICRwJDogc+G7kSB0aGFtIHPhu5EgdHJvbmcgbcO0IGjDrG5oDQoNClwoXFJpZ2h0YXJyb3dcKSBO4bq/dToNCg0KJCQNClxoYXR7XHBoaX0gPiAxLjUNCiQkDQoNCuKGkiBNw7QgaMOsbmggKipjw7MgdGjhu4MgYuG7iyBvdmVyZGlzcGVyc2VkKiogKHF1w6EgcGjDom4gdMOhbikNCg0KXChcUmlnaHRhcnJvd1wpIFRyb25nIHRyxrDhu51uZyBo4bujcCBuw6B5LCBj4bqnbiDEkWnhu4F1IGNo4buJbmggbcO0IGjDrG5oLCB2w60gZOG7pToNCg0KLSBT4butIGThu6VuZyAqKnF1YXNpLVBvaXNzb24qKg0KDQotIEhv4bq3YyAqKk5lZ2F0aXZlIEJpbm9taWFsKioNCg0KIyMgKipDSMavxqBORyA4OiBI4buSSSBRVVkgTE9HSVNUSUMgKExPR0lTVElDIFJFR1JFU1NJT04pKioNCg0KIyMjICoqOC4xIEdp4bubaSB0aGnhu4d1KioNCg0KSOG7k2kgcXV5IGxvZ2lzdGljIGzDoCBt4buZdCB0cm9uZyBuaOG7r25nIG3DtCBow6xuaCBwaOG7lSBiaeG6v24gbmjhuqV0IHRodeG7mWMgaOG7jSBHTE0sIMSRxrDhu6NjIGTDuW5nIMSR4buDIG3DtCBow6xuaCBow7NhIGThu68gbGnhu4d1IG5o4buLIHBow6JuIChiaW5hcnkpLCB04bupYyBraGkgYmnhur9uIHBo4bqjbiBo4buTaQ0KDQpcWw0KeSBcaW4gXHswLDFcfQ0KXF0NCg0KVsOtIGThu6U6IGLhu4duaC9raMO0bmcgYuG7h25oLCBtdWEva2jDtG5nIG11YSwgxJHhuqF0L2tow7RuZyDEkeG6oXQuDQoNCsSQ4bq3YyDEkWnhu4NtOiAgDQpcWw0KXG11X2kgPSBFW3lfaV0gPSBQKHlfaT0xKSBcaW4gKDAsMSkNClxdDQoNClPhu60gZOG7pW5nIGjDoG0gbGnDqm4ga+G6v3QgbG9naXQ6ICANClxbDQpnKFxtdV9pKSA9IFxsb2dcbGVmdChcZnJhY3tcbXVfaX17MS1cbXVfaX1ccmlnaHQpID0gXGV0YV9pID0geF9pXlQgXGJldGENClxdDQoNCi0tLQ0KDQojIyMgKio4LjIgUGjDom4gcGjhu5FpIEJlcm5vdWxsaSB2w6AgaMOgbSBsb2ctbGlrZWxpaG9vZCoqDQoNCkJp4bq/biBwaOG6o24gaOG7k2kgIA0KDQpcWw0KeV9pIFxpbiBcezAsMVx9DQpcXSAgDQpwaMOibiBwaOG7kWkgdGhlbzogIA0KDQpcWw0KeV9pIFxzaW0gXHRleHR7QmVybm91bGxpfShccGlfaSkNClxdDQoNClRyb25nIMSRw7M6DQoNClxbDQpccGlfaSA9IFAoeV9pPTEpDQpcXSAgDQp2w6A6ICANClxbDQpcbG9nXGxlZnQoXGZyYWN7XHBpX2l9ezEtXHBpX2l9XHJpZ2h0KSA9IHhfaV5UIFxiZXRhDQpcXQ0KDQpMb2ctbGlrZWxpaG9vZCBjaG8gdG/DoG4gYuG7mSBt4bqrdTogIA0KXFsNClxlbGwoXGJldGEpID0gXHN1bV97aT0xfV5uIFxsZWZ0WyB5X2kgXGxvZyhccGlfaSkgKyAoMSAtIHlfaSkgXGxvZygxLVxwaV9pKSBccmlnaHRdDQpcXQ0KDQpLaMO0bmcgY8OzIG5naGnhu4dtIGdp4bqjaSB0xrDhu51uZyBtaW5oIOKGkiBkw7luZyBJUkxTIMSR4buDIHTDrG0gXChcaGF0e1xiZXRhfVwpLg0KDQotLS0NCg0KIyMjICoqOC4zIERp4buFbiBnaeG6o2kgaOG7hyBz4buRIGjhu5NpIHF1eSB0cm9uZyBsb2dpc3RpYyByZWdyZXNzaW9uKioNCg0KS2hpIGTDuW5nIGxvZ2l0IGxpbms6ICANClxbDQpcZXRhX2kgPSBcbG9nXGxlZnQoXGZyYWN7XHBpX2l9ezEtXHBpX2l9XHJpZ2h0KSA9IHhfaV5UIFxiZXRhDQpcXQ0KDQrihpIgXChcYmV0YV9qXCkgxJHhuqFpIGRp4buHbiBjaG8gbG9nIG9kZHMgcmF0aW86ICANClxbDQpcdGV4dHtPZGRzIHJhdGlvfSA9IFxleHAoXGJldGFfaikNClxdDQoNCi0gTuG6v3UgXChcYmV0YV9qID4gMFwpOiBiaeG6v24gXCh4X2pcKSBsw6BtIHTEg25nIGto4bqjIG7Eg25nIFwoeT0xXCkNCg0KLSBO4bq/dSBcKFxiZXRhX2ogPCAwXCk6IGJp4bq/biBcKHhfalwpIGzDoG0gZ2nhuqNtIGto4bqjIG7Eg25nIFwoeT0xXCkNCg0KLS0tDQoNCiMjIyAqKjguNCBLaG/huqNuZyB0aW4gY+G6rXkgdsOgIGtp4buDbSDEkeG7i25oKioNCg0KU2F1IGtoaSDGsOG7m2MgbMaw4bujbmcgXChcaGF0e1xiZXRhfVwpLCB0YSBraeG7g20gxJHhu4tuaCB04burbmcgaOG7hyBz4buROg0KDQpLaeG7g20gxJHhu4tuaCBXYWxkOiAgDQpcWw0KWl9qID0gXGZyYWN7XGhhdHtcYmV0YX1fan17U0UoXGhhdHtcYmV0YX1fail9IFxzaW0gTigwLDEpDQpcXQ0KDQpLaG/huqNuZyB0aW4gY+G6rXkgOTUlOiAgDQpcWw0KXGhhdHtcYmV0YX1faiBccG0gel97MC45NzV9IFxjZG90IFNFKFxoYXR7XGJldGF9X2opDQpcXQ0KDQpDaHV54buDbiBzYW5nIG9kZHMgcmF0aW8gYuG6sW5nICANClxbDQpcZXhwKFxoYXR7XGJldGF9X2opDQpcXQ0KDQotLS0NCg0KIyMjICoqOC41IMSQw6FuaCBnacOhIG3DtCBow6xuaCoqDQoNCkRldmlhbmNlOiAgDQpcWw0KRCA9IC0yIFxsZWZ0WyBcZWxsKFxoYXR7XGJldGF9KSAtIFxlbGxfe1x0ZXh0e3NhdHVyYXRlZH19IFxyaWdodF0NClxdDQoNCktp4buDbSDEkeG7i25oIGRldmlhbmNlIGdp4buvYSBtw7QgaMOsbmggxJHhuqd5IMSR4bunIHbDoCBtw7QgaMOsbmggcsO6dCBn4buNbi4NCg0KUHNldWRvLVwoUl4yXCk6ICANClxbDQpSXjIgPSAxIC0gXGZyYWN7RF97XHRleHR7bW9kZWx9fX17RF97XHRleHR7bnVsbH19fQ0KXF0NCg0KLS0tDQoNCiMjIyAqKjguNiBNw7QgaMOsbmggaMOzYSB24bubaSBuaGnhu4F1IGJp4bq/biAobXVsdGlwbGUgcHJlZGljdG9ycykqKg0KDQpDw7MgdGjhu4MgbeG7nyBy4buZbmcgbG9naXN0aWMgcmVncmVzc2lvbiDEkeG7gyBiYW8gZ+G7k20gbmhp4buBdSBiaeG6v24gZ2nhuqNpIHRow61jaDoNCg0KXFsNClxsb2dcbGVmdChcZnJhY3tccGlfaX17MS1ccGlfaX1ccmlnaHQpID0gXGJldGFfMCArIFxiZXRhXzEgeF97aTF9ICsgXGNkb3RzICsgXGJldGFfcCB4X3tpcH0NClxdDQoNCuKGkiBNw7QgaMOsbmggxJFhIGJp4bq/biBsb2dpc3RpYy4NCg0KLS0tDQoNCiMjIyAqKjguNyBNw7QgaMOsbmggaMOzYSB04bu3IGzhu4cgKEdyb3VwZWQgYmlub21pYWwgbW9kZWwpKioNCg0KS2hpIGThu68gbGnhu4d1IGtow7RuZyBwaOG6o2kgdOG7q25nIHF1YW4gc8OhdCByacOqbmcgbOG6uywgbcOgIGzDoCB04buVbmcgaOG7o3AgIA0KXFsNClxmcmFje3lfaX17bl9pfQ0KXF0gIA0KdGEgZMO5bmc6ICANClxbDQp5X2kgXHNpbSBcdGV4dHtCaW5vbWlhbH0obl9pLCBccGlfaSkNClxdDQoNCkxvZy1saWtlbGlob29kOiAgDQpcWw0KXGVsbChcYmV0YSkgPSBcc3VtX3tpPTF9Xm4gXGxlZnRbIHlfaSBcbG9nKFxwaV9pKSArIChuX2kgLSB5X2kpIFxsb2coMS1ccGlfaSkgXHJpZ2h0XQ0KXF0NCg0KIyMgKipDSMavxqBORyA5OiBI4buSSSBRVVkgUE9JU1NPTiAoUE9JU1NPTiBSRUdSRVNTSU9OKSoqDQoNCiMjIyAqKjkuMSBHaeG7m2kgdGhp4buHdSB2w6Ag4bupbmcgZOG7pW5nIHRo4buxYyB04bq/KioNCg0KSOG7k2kgcXV5IFBvaXNzb24gbMOgIG3hu5l0IG3DtCBow6xuaCB0aHXhu5ljIGjhu40gR0xNLCDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyBtw7QgaMOsbmggaMOzYSBjw6FjIGJp4bq/biBwaOG6o24gaOG7k2kgbMOgIHPhu5EgbMaw4bujbmcgc+G7sSBraeG7h24gxJHhur9tIMSRxrDhu6NjIHRyw6puIG3hu5l0IMSRxqFuIHbhu4sgcXVhbiBzw6F0LCBjaOG6s25nIGjhuqFuIG5oxrA6DQoNCi0gU+G7kSBs4bqnbiBuaOG6rXAgdmnhu4duDQoNCi0gU+G7kSB24bulIHRhaSBu4bqhbiBnaWFvIHRow7RuZw0KDQotIFPhu5EgbOG7l2kgcGjhuqduIG3hu4FtIHBow6F0IHNpbmgNCg0KxJDhurdjIGJp4buHdCBwaMO5IGjhu6NwIGtoaToNCg0KLSBCaeG6v24gcGjhuqNuIGjhu5NpIFwoIHkgXGluIFx7MCwgMSwgMiwgXGxkb3RzIFx9IFwpDQoNCi0gROG7ryBsaeG7h3Uga2jDtG5nIMOibSwgcuG7nWkgcuG6oWMNCg0KLSBN4bulYyB0acOqdSBsw6AgxrDhu5tjIGzGsOG7o25nIHPhu5Egc+G7sSBraeG7h24gdHJ1bmcgYsOsbmggdGhlbyBjw6FjIMSR4bq3YyB0w61uaCBcKCB4IFwpDQoNCi0tLQ0KDQojIyMgKio5LjIgUGjDom4gcGjhu5FpIFBvaXNzb24gdsOgIGxpw6puIGvhur90IGxvZyoqDQoNCioqSMOgbSB4w6FjIHN14bqldDoqKiAgDQpcWw0KUCh5X2kpID0gXGZyYWN7ZV57LVxtdV9pfSBcbXVfaV57eV9pfX17eV9pIX0sIFxxdWFkIHlfaSA9IDAsIDEsIDIsIFxsZG90cw0KXF0NCg0KVHJvbmcgxJHDszoNCg0KXFsNClxtdV9pID0gRVt5X2ldIDogXHRleHR7c+G7kSBz4buxIGtp4buHbiBr4buzIHbhu41uZyBj4bunYSBxdWFuIHPDoXQgdGjhu6kgfSBpDQpcXQ0KDQpcWw0KXHRleHR7VmFyfSh5X2kpID0gXG11X2kgXHF1YWQgOiBcdGV4dHvEkeG6t2MgxJFp4buDbSB0aGVuIGNo4buRdH0NClxdDQoNCioqSMOgbSBsacOqbiBr4bq/dCAoY2Fub25pY2FsKToqKg0KDQpcWw0KXGV0YV9pID0gXGxvZyhcbXVfaSkgPSB4X2leVCBcYmV0YSBcaW1wbGllcyBcbXVfaSA9IGVee3hfaV5UIFxiZXRhfQ0KXF0NCg0KKipIw6BtIGxvZyDEkeG6o20gYuG6o286KioNCg0KXFsNClxtdV9pID4gMA0KXF0NCg0KTeG7kWkgcXVhbiBo4buHIHR1eeG6v24gdMOtbmggdHLDqm4gbG9nLXNjYWxlLg0KDQotLS0NCg0KIyMjICoqOS4zIEjDoG0gbG9nLWxpa2VsaWhvb2QgdsOgIHBoxrDGoW5nIHRyw6xuaCDEkWnhu4NtKioNCg0KKipMb2ctbGlrZWxpaG9vZCBj4bunYSBtw7QgaMOsbmg6KioNCg0KXFsNClxlbGwoXGJldGEpID0gXHN1bV97aT0xfV5uIFxsZWZ0WyB5X2kgXGxvZyhcbXVfaSkgLSBcbXVfaSAtIFxsb2coeV9pISkgXHJpZ2h0XQ0KXF0NCg0KVGhheSBcKFxtdV9pID0gZV57eF9pXlQgXGJldGF9XCksIHRhIMSRxrDhu6NjOg0KDQpcWw0KXGVsbChcYmV0YSkgPSBcc3VtX3tpPTF9Xm4gXGxlZnRbIHlfaSB4X2leVCBcYmV0YSAtIGVee3hfaV5UIFxiZXRhfSAtIFxsb2coeV9pISkgXHJpZ2h0XQ0KXF0NCg0KKipTY29yZSBmdW5jdGlvbiAoxJHhuqFvIGjDoG0gbG9nLWxpa2VsaWhvb2QpOioqDQoNClxbDQpVKFxiZXRhKSA9IFxzdW1fe2k9MX1ebiB4X2kgKHlfaSAtIFxtdV9pKQ0KXF0NCg0KR2nhuqNpIHBoxrDGoW5nIHRyw6xuaCBcKCBVKFxiZXRhKSA9IDAgXCkg4oaSIHTDrG0gXChcaGF0e1xiZXRhfVwpIGLhurFuZyBJUkxTLg0KDQojIyMgKio5LjQgRGnhu4VuIGdp4bqjaSBo4buHIHPhu5EgaOG7k2kgcXV5KioNCg0KVHJvbmcgaOG7k2kgcXV5IFBvaXNzb246DQoNCi0gTeG7l2kgXChcYmV0YV9qXCkgbMOgIHTDoWMgxJHhu5luZyBsb2cgdHV54bq/biB0w61uaCDEkeG6v24gc+G7kSBz4buxIGtp4buHbiB0cnVuZyBiw6xuaC4NCg0KLSBcKGVee1xiZXRhX2p9XCkgbMOgIHThu7cgbOG7hyB0aGF5IMSR4buVaSBr4buzIHbhu41uZyBcKFxtdVwpIGtoaSBcKHhfalwpIHTEg25nIDEgxJHGoW4gduG7iywgZ2nhu68gY8OhYyBiaeG6v24ga2jDoWMga2jDtG5nIMSR4buVaS4NCg0KVsOtIGThu6U6DQoNCi0gXChcYmV0YV9qID0gMC42OTMgXFJpZ2h0YXJyb3cgZV57MC42OTN9ID0gMlwpOiBz4buRIHPhu7Ega2nhu4duIGvhu7MgduG7jW5nIGfhuqVwIMSRw7RpIGtoaSBcKHhfalwpIHTEg25nIDEgxJHGoW4gduG7iy4NCg0KLSBcKFxiZXRhX2ogPSAtMC4yMjNcKSDihpIgZ2nhuqNtIGtob+G6o25nIDIwJS4NCg0KLS0tDQoNCiMjIyAqKjkuNSBU4bu3IGzhu4cgeOG6o3kgcmEgJiBvZmZzZXQqKg0KDQoqKk9mZnNldCBsw6AgZ8OsPyoqICANCktoaSBxdWFuIHPDoXQga2jDtG5nIMSR4buTbmcgbmjhuqV0IHbhu4EgdGjhu51pIGdpYW4vcGjhuqFtIHZpLCBj4bqnbiDEkWnhu4F1IGNo4buJbmggYuG6sW5nIG9mZnNldC4NCg0KVsOtIGThu6U6DQoNCi0gUXVhbiBzw6F0IDE6IDUgdGFpIG7huqFuIHRyb25nIDEwIG5nw6B5DQoNCi0gUXVhbiBzw6F0IDI6IDIgdGFpIG7huqFuIHRyb25nIDIgbmfDoHkNCg0KS2jDtG5nIHRo4buDIHNvIHPDoW5oIHPhu5EgdHV54buHdCDEkeG7kWkg4oaSIGTDuW5nIHThu7cgbOG7hzogIA0KXFsNClxmcmFje1xtdV9pfXt0X2l9IFxpbXBsaWVzIFxsb2coXG11X2kpID0gXGxvZyh0X2kpICsgeF9pXlQgXGJldGENClxdDQoNClRyb25nIMSRw7MgXChcbG9nKHRfaSlcKSBsw6AgKipvZmZzZXQqKiDigJMga2jDtG5nIGPDsyBo4buHIHPhu5EsIG5oxrBuZyDEkcaw4bujYyDEkcawYSB2w6BvIG3DtCBow6xuaC4NCg0KLS0tDQoNCiMjIyAqKjkuNiBPdmVyZGlzcGVyc2lvbiAocGjDom4gdMOhbiBxdcOhIG3hu6ljKSoqDQoNClRyb25nIGzDvSB0aHV54bq/dDoNCg0KXFsNClxtYXRocm17VmFyfSh5X2kpID0gXG11X2kNClxdDQoNCk5oxrBuZyB0aOG7sWMgdOG6vyB0aMaw4budbmcgdGjhuqV5Og0KDQpcWw0KXG1hdGhybXtWYXJ9KHlfaSkgPiBcbXVfaSBccXVhZCBcUmlnaHRhcnJvdyBccXVhZCBcdGV4dHtvdmVyZGlzcGVyc2lvbn0NClxdDQoNCk5ndXnDqm4gbmjDom4gZG8gYuG7jyBzw7N0IGJp4bq/biBxdWFuIHRy4buNbmcsIHF1w6Egbmhp4buBdSBnacOhIHRy4buLIDAsIGhv4bq3YyBiaeG6v24gxJHhu5luZyBuZ+G6q3Ugbmhpw6puIHbGsOG7o3QgbeG7qWMuDQoNCioqSOG7hyBz4buRIHBow6JuIHTDoW46KioNCg0KXFsNClxoYXR7XHBoaX0gPSBcZnJhY3tcdGV4dHtEZXZpYW5jZX19e24gLSBwfQ0KXF0NCg0KTuG6v3UgXChcaGF0e1xwaGl9ID4gMS41XCkgdGjDrCDEkcOhbmcgbG8gbmfhuqFpLg0KDQoqKkPDoWNoIHjhu60gbMO9OioqDQoNCi0gU+G7rSBk4bulbmcgcXVhc2ktUG9pc3NvbjogxJFp4buBdSBjaOG7iW5oIHBoxrDGoW5nIHNhaSBtw6Aga2jDtG5nIHRoYXkgxJHhu5VpIGvhu7MgduG7jW5nLg0KDQotIETDuW5nIE5lZ2F0aXZlIEJpbm9taWFsOiB0aMOqbSB0aGFtIHPhu5EgXChcYWxwaGFcKSDEkeG7gyDEkWnhu4F1IGNo4buJbmggcGjGsMahbmcgc2FpLg0KDQotLS0NCg0KIyMjICoqOS43IMSQw6FuaCBnacOhIG3DtCBow6xuaCoqDQoNCi0gKipEZXZpYW5jZToqKiBraeG7g20gdHJhIG3hu6ljIMSR4buZIHBow7kgaOG7o3AgY+G7p2EgbcO0IGjDrG5oLg0KDQotICoqQUlDOioqIGNo4buNbiBtw7QgaMOsbmggdOG7kXQgbmjhuqV0Lg0KDQotICoqS2nhu4NtIMSR4buLbmggZGV2aWFuY2U6Kiogc28gc8OhbmggaGFpIG3DtCBow6xuaCBs4buTbmcgbmhhdS4NCi0gKipCaeG7g3UgxJHhu5MgcGjhuqduIGTGsDoqKg0KICAtIFJlc2lkdWFscyB2cyBmaXR0ZWQNCiAgDQogIC0gRGV2aWFuY2UgcmVzaWR1YWxzDQogIA0KICAtIENvb2sncyBkaXN0YW5jZQ0KDQoqKktp4buDbSDEkeG7i25oIFBlYXJzb24gY2hpLXNxdWFyZToqKg0KDQpcWw0KWF4yID0gXHN1bV97aT0xfV5uIFxmcmFjeyh5X2kgLSBcbXVfaSleMn17XG11X2l9IFxxdWFkIFxSaWdodGFycm93IFxxdWFkIFheMiBcc2ltIFxjaGleMl97bi1wfQ0KXF0NCg0KIyMjICoqOS44IFNvIHPDoW5oIHbhu5tpIGPDoWMgbcO0IGjDrG5oIGtow6FjKioNCg0KfCBNw7QgaMOsbmggICAgICAgICAgIHwgS2hpIG7DoG8gZMO5bmcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfA0KfC0tLS0tLS0tLS0tLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18DQp8ICoqUG9pc3NvbioqICAgICAgIHwgROG7ryBsaeG7h3UgxJHhur9tLCBwaMawxqFuZyBzYWkgZ+G6p24gYuG6sW5nIGvhu7MgduG7jW5nIChcKFxtYXRocm17VmFyfSh5KSBcYXBwcm94IEUoeSlcKSkgfA0KfCAqKlF1YXNpLVBvaXNzb24qKiB8IEtoaSBjw7Mgb3ZlcmRpc3BlcnNpb24gbmjhurksIGdp4buvIGPDuW5nIGjDoG0gbGnDqm4ga+G6v3QgKGxpbmsgZnVuY3Rpb24pICAgICAgICAgICB8DQp8ICoqTmVnYXRpdmUgQmlub21pYWwqKiB8IEtoaSBvdmVyZGlzcGVyc2lvbiBu4bq3bmcgaG/hurdjIGThu68gbGnhu4d1IGPDsyBxdcOhIG5oaeG7gXUgZ2nDoSB0cuG7iyAwICAgICAgICAgICAgICAgfA0KDQojIyAqKkNIxq/GoE5HIDEwOiBI4buSSSBRVVkgR0FNTUEgKEdBTU1BIFJFR1JFU1NJT04pKioNCg0KIyMjICoqMTAuMSBHaeG7m2kgdGhp4buHdSoqDQoNCkjhu5NpIHF1eSBHYW1tYSBsw6AgbeG7mXQgbcO0IGjDrG5oIHRodeG7mWMgaOG7jSBHTE0gZMO5bmcgxJHhu4MgbcO0IGjDrG5oIGjDs2EgY8OhYyBiaeG6v24gcGjhuqNuIGjhu5NpIGTGsMahbmcgbGnDqm4gdOG7pWMgY8OzIHBoxrDGoW5nIHNhaSB0xINuZyB0aGVvIGdpw6EgdHLhu4sgdHJ1bmcgYsOsbmguDQoNClbDrSBk4bulIOG7qW5nIGThu6VuZzoNCg0KLSBDaGkgcGjDrSB5IHThur8NCg0KLSBUaOG7nWkgZ2lhbiBz4buRbmcgKHN1cnZpdmFsIHRpbWUpDQoNCi0gTMaw4bujbmcgdGnDqnUgdGjhu6UgbsSDbmcgbMaw4bujbmcNCg0KIyMjICoqMTAuMiBQaMOibiBwaOG7kWkgR2FtbWEqKg0KDQpHaeG6oyDEkeG7i25oIGJp4bq/biBuZ+G6q3Ugbmhpw6puIFwoIHlfaSBcKSBwaMOibiBwaOG7kWkgR2FtbWEgduG7m2kgdGhhbSBz4buROg0KDQpcWw0KeV9pIFxzaW0gR2FtbWEoXGFscGhhLCBcbXVfaSkNClxdDQoNClRyb25nIMSRw7M6DQoNCi0gXCggXG11X2kgPSBFW3lfaV0gXCkgbMOgIGvhu7MgduG7jW5nLg0KDQotIFBoxrDGoW5nIHNhaTogIA0KXFsNClZhcih5X2kpID0gXGZyYWN7XG11X2leMn17XGFscGhhfSA9IFxwaGkgXG11X2leMg0KXF0NCg0KUGjGsMahbmcgc2FpIHThu7cgbOG7hyB24bubaSBiw6xuaCBwaMawxqFuZyBr4buzIHbhu41uZywgcGjDuSBo4bujcCBraGkgYmnhur9uIHRoacOqbiB04bu3IGzhu4cga2jDtG5nIMSR4buVaS4NCg0KIyMjICoqMTAuMyBIw6BtIG3huq10IMSR4buZIHjDoWMgc3XhuqV0IEdhbW1hIChk4bqhbmcgR0xNKSoqDQoNCkjDoG0gbeG6rXQgxJHhu5kgeMOhYyBzdeG6pXQ6DQoNClxbDQpmKHk7IFxtdSwgXHBoaSkgPSBcZnJhY3sxfXtcR2FtbWEoMS9ccGhpKX0gXGxlZnQoXGZyYWN7MX17XHBoaSBcbXV9XHJpZ2h0KV57MS9ccGhpfSB5XntcZnJhY3sxfXtccGhpfS0xfSBcZXhwXGxlZnQoLVxmcmFje3l9e1xwaGkgXG11fVxyaWdodCkNClxdDQoNCkjDoG0gbsOgeSB0aHXhu5ljIGjhu40gaMOgbSBtxakgKGV4cG9uZW50aWFsIGZhbWlseSksIHbhu5tpOg0KDQpcWw0KXHRoZXRhID0gLVxmcmFjezF9e1xtdX0NClxdDQoNClxbDQpiKFx0aGV0YSkgPSAtXGxvZygtXHRoZXRhKQ0KXF0NCg0KSMOgbSBwaMawxqFuZyBzYWk6DQoNClxbDQpWKFxtdSkgPSBcbXVeMg0KXF0NCg0KXChccGhpXCkgbMOgIHRoYW0gc+G7kSBwaMOibiB0w6FuLg0KDQojIyMgKioxMC40IEjDoG0gbGnDqm4ga+G6v3QgKExpbmsgZnVuY3Rpb24pKioNCg0KTeG6t2MgxJHhu4tuaCB0cm9uZyBHTE06DQoNClxbDQpnKFxtdV9pKSA9IFxsb2coXG11X2kpID0gXGV0YV9pID0geF9pXlQgXGJldGENClxdDQoNCkPDoWMgdMO5eSBjaOG7jW4ga2jDoWM6DQoNCi0gSWRlbnRpdHk6IFwoIGcoXG11KSA9IFxtdSBcKQ0KDQotIEludmVyc2U6IFwoIGcoXG11KSA9IFxmcmFjezF9e1xtdX0gXCkNCg0KTGluayBsb2cgxJHGsOG7o2MgZMO5bmcgcGjhu5UgYmnhur9uIG5o4bqldCB2w6wgxJHhuqNtIGLhuqNvIFwoIFxtdSA+IDAgXCkuDQoNCiMjIyAqKjEwLjUgxq/hu5tjIGzGsOG7o25nIHRyb25nIGjhu5NpIHF1eSBHYW1tYSoqDQoNCsav4bubYyBsxrDhu6NuZyB0aGFtIHPhu5EgXChcYmV0YVwpIGLhurFuZyBwaMawxqFuZyBwaMOhcCBo4bujcCBsw70gdOG7kWkgxJFhIChNTEUpIHF1YSB0aHXhuq10IHRvw6FuIElSTFMuDQoNCkjDoG0gbG9nLWxpa2VsaWhvb2Q6DQoNClxbDQpcZWxsKFxiZXRhKSA9IFxzdW1fe2k9MX1ebiBcbGVmdFstXGxvZyhcbXVfaSkgLSBcZnJhY3t5X2l9e1xtdV9pfSBccmlnaHRdICsgXHRleHR7aOG6sW5nIHPhu5F9DQpcXQ0KDQp24bubaToNCg0KXFsNClxtdV9pID0gZV57eF9pXlQgXGJldGF9DQpcXQ0KDQpQaMawxqFuZyB0csOsbmggxJFp4buDbToNCg0KXFsNClxmcmFje1xwYXJ0aWFsIFxlbGx9e1xwYXJ0aWFsIFxiZXRhfSA9IFxzdW1fe2k9MX1ebiB4X2kgXGxlZnQoIHlfaSAtIFxmcmFje1xtdV9pfXtcbXVfaV4yfSBcY2RvdCBcZnJhY3tkXG11X2l9e2RcZXRhX2l9IFxyaWdodCkgPSAwDQpcXQ0KDQpEw7luZyBJUkxTIMSR4buDIGdp4bqjaSBwaMawxqFuZyB0csOsbmggdsOgIHTDrG0gbmdoaeG7h20gXChcaGF0e1xiZXRhfVwpLg0KDQojIyMgKioxMC42IERp4buFbiBnaeG6o2kgaOG7hyBz4buRKioNCg0KVuG7m2kgbGluayBsb2c6DQoNClxbDQpcbG9nKFxtdV9pKSA9IFxiZXRhXzAgKyBcYmV0YV8xIHhfe2kxfSArIFxjZG90cyArIFxiZXRhX3AgeF97aXB9IFxpbXBsaWVzIFxtdV9pID0gZV57eF9pXlQgXGJldGF9DQpcXQ0KDQpN4buXaSBo4buHIHPhu5EgXChcYmV0YV9qXCkgxJHGsOG7o2MgaGnhu4N1IGzDoCAqKnTDoWMgxJHhu5luZyB0csOqbiBsb2ctc2NhbGUqKiwgbmdoxKlhIGzDoCDhuqNuaCBoxrDhu59uZyDEkeG6v24gbG9nIGPhu6dhIGvhu7MgduG7jW5nIHRydW5nIGLDrG5oLg0KDQotIEtoaSBcKHhfalwpIHTEg25nIDEgxJHGoW4gduG7iywgdHJ1bmcgYsOsbmggXChcbXVcKSB0aGF5IMSR4buVaSB0aGVvIHThu7cgbOG7hzoNCg0KXFsNCmVee1xiZXRhX2p9DQpcXQ0KDQp04bupYyBsw6AgaOG7hyBz4buRIHThu7cgbOG7hyB0aGF5IMSR4buVaSBj4bunYSBcKFxtdVwpLg0KDQojIyMgKioxMC43IEtp4buDbSDEkeG7i25oIHbDoCBraG/huqNuZyB0aW4gY+G6rXkqKg0KDQotICoqV2FsZCB0ZXN0KiogxJHhu4Mga2nhu4NtIMSR4buLbmg6DQoNClxbDQpaX2ogPSBcZnJhY3tcaGF0e1xiZXRhfV9qfXtTRShcaGF0e1xiZXRhfV9qKX0gXHNpbSBcbWF0aGNhbHtOfSgwLDEpDQpcXQ0KDQotIEtob+G6o25nIHRpbiBj4bqteSBjaG8gXChcYmV0YV9qXCk6DQoNClxbDQpcaGF0e1xiZXRhfV9qIFxwbSB6X3tcYWxwaGEvMn0gXGNkb3QgU0UoXGhhdHtcYmV0YX1faikNClxdDQoNCi0gQ2h1eeG7g24gc2FuZyBraG/huqNuZyB0aW4gY+G6rXkgdOG7tyBs4buHIHRoYXkgxJHhu5VpIHRydW5nIGLDrG5oOg0KDQpcWw0KXGxlZnQoZV57XGhhdHtcYmV0YX1faiAtIHpfe1xhbHBoYS8yfSBTRShcaGF0e1xiZXRhfV9qKX0sIFxxdWFkIGVee1xoYXR7XGJldGF9X2ogKyB6X3tcYWxwaGEvMn0gU0UoXGhhdHtcYmV0YX1fail9IFxyaWdodCkNClxdDQoNCiMjIyAqKjEwLjggS2nhu4NtIHRyYSDEkeG7mSBwaMO5IGjhu6NwIChHb29kbmVzcy1vZi1maXQpKioNCg0KLSAqKkRldmlhbmNlKio6DQoNClxbDQpEID0gMiBcc3VtX3tpPTF9Xm4gXGxlZnRbIFxmcmFje3lfaSAtIFxtdV9pfXtcbXVfaX0gLSBcbG9nXGxlZnQoXGZyYWN7eV9pfXtcbXVfaX1ccmlnaHQpIFxyaWdodF0NClxdDQoNCi0gKipQZWFyc29uIGNoaS1zcXVhcmUqKjoNCg0KXFsNClheMiA9IFxzdW1fe2k9MX1ebiBcbGVmdCggXGZyYWN7eV9pIC0gXG11X2l9e1xtdV9pfSBccmlnaHQpXjINClxdDQoNCkhhaSBjaOG7iSBz4buRIG7DoHkgZMO5bmcgxJHhu4MgxJHDoW5oIGdpw6EgxJHhu5kgcGjDuSBo4bujcCBj4bunYSBtw7QgaMOsbmggdsOgIHBow6F0IGhp4buHbiBoaeG7h24gdMaw4bujbmcgKipvdmVyZGlzcGVyc2lvbioqIG7hur91IGPDsy4NCg0KIyMjICoqMTAuOSBTbyBzw6FuaCB24bubaSBtw7QgaMOsbmgga2jDoWMqKg0KDQp8IE3DtCBow6xuaCAgICAgICAgICAgIHwgS2hpIGTDuW5nICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwtLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KfCBI4buTaSBxdXkgdHV54bq/biB0w61uaCAgfCBLaGkgZOG7ryBsaeG7h3UgcGjDom4gcGjhu5FpIGNodeG6qW4sIHBoxrDGoW5nIHNhaSBraMO0bmcgxJHhu5VpICAgICAgICAgICB8DQp8IEjhu5NpIHF1eSBHYW1tYSAgICAgIHwgS2hpIGThu68gbGnhu4d1IGTGsMahbmcsIHBoxrDGoW5nIHNhaSB04bu3IGzhu4cgduG7m2kgYsOsbmggcGjGsMahbmcgdHJ1bmcgYsOsbmggfA0KfCBI4buTaSBxdXkgbG9nLW5vcm1hbCAgfCBLaGkgXChcbG9nKHkpXCkgcGjDom4gcGjhu5FpIGNodeG6qW4gKHNhdSBiaeG6v24gxJHhu5VpIGxvZykgICAgICAgICAgfA0KDQojIyAqKkNIxq/GoE5HIDExOiBE4buuIExJ4buGVSBOSMOTTSBIT+G6tkMgVOG7tiBM4buGIChHUk9VUEVEIERBVEEgT1IgUFJPUE9SVElPTlMpKioNCg0KIyMjICoqMTEuMSBHaeG7m2kgdGhp4buHdSoqDQoNCkThu68gbGnhu4d1IG5o4buLIHBow6JuIGThuqFuZyAwLzEgxJHGsOG7o2MgbcO0IGjDrG5oIGjDs2EgYuG6sW5nIGjhu5NpIHF1eSBsb2dpc3RpYy4gVHV5IG5oacOqbiwgbuG6v3UgZOG7ryBsaeG7h3UgY8OzIGThuqFuZyB04buVbmcgaOG7o3AgKGdyb3VwZWQpIGhv4bq3YyB0aOG7gyBoaeG7h24gZMaw4bubaSBk4bqhbmcgdOG7tyBs4buHLCB2w60gZOG7pToNCg0KMjAgdGjDoG5oIGPDtG5nIHRyb25nIDMwIHRo4butIG5naGnhu4dtIOKGkiBcKCB5ID0gMjAsIG4gPSAzMCBcKQ0KDQotIFThu7cgbOG7hyBt4bqvYyBi4buHbmgg4bufIG3hu5dpIHF14bqtbg0KDQotIFThu7cgbOG7hyBzaW5oIHZpw6puIMSR4bqtdSB0cm9uZyB04burbmcgbOG7m3ANCg0K4oaSIEPhuqduIGTDuW5nIEdMTSBk4bqhbmcgbmjhu4sgdGjhu6ljIHThu5VuZyBxdcOhdCAoYmlub21pYWwgR0xNKSwgw6FwIGThu6VuZyBjaG8gc+G7kSBs4bqnbiB0aMOgbmggY8O0bmcgdHLDqm4gc+G7kSBs4bqnbiB0aOG7rS4NCg0KIyMjICoqMTEuMiBNw7QgaMOsbmggaMOzYSBz4buRIHRow6BuaCBjw7RuZyB0cm9uZyBuaMOzbSoqDQoNClbhu5tpIFwoIHlfaSBcc2ltIFx0ZXh0e0Jpbm9taWFsfShuX2ksIFxwaV9pKSBcKSwgdGEgbcO0IGjDrG5oIGjDs2E6DQoNClxbDQpcbG9nIFxsZWZ0KFxmcmFje1xwaV9pfXsxIC0gXHBpX2l9XHJpZ2h0KSA9IFxldGFfaSA9IHhfaV5UIFxiZXRhIFxpbXBsaWVzIFxwaV9pID0gXGZyYWN7ZV57eF9pXlQgXGJldGF9fXsxICsgZV57eF9pXlQgXGJldGF9fQ0KXF0NCg0KVHJvbmcgxJHDszoNCg0KLSBcKCB5X2kgXCk6IHPhu5EgdGjDoG5oIGPDtG5nIHRyb25nIG5ow7NtIFwoaVwpDQoNCi0gXCggbl9pIFwpOiB04buVbmcgc+G7kSB0aOG7rSBuZ2hp4buHbSB0cm9uZyBuaMOzbSBcKGlcKQ0KDQotIFwoIFxwaV9pIFwpOiB4w6FjIHN14bqldCB0aMOgbmggY8O0bmcNCg0KLSBcKCBcbXVfaSA9IEVbeV9pXSA9IG5faSBccGlfaSBcKQ0KDQotIFwoIFx0ZXh0e1Zhcn0oeV9pKSA9IG5faSBccGlfaSAoMSAtIFxwaV9pKSBcKQ0KDQrihpIgUGjDuSBo4bujcCBjaG8gZOG7ryBsaeG7h3UgZOG6oW5nICJuIHRyaWFscywgayBzdWNjZXNzZXMiLg0KDQojIyMgKioxMS4zIExvZy1saWtlbGlob29kIHbDoCBJUkxTKioNCg0KKipIw6BtIGxvZy1saWtlbGlob29kOioqDQoNClxbDQpcZWxsKFxiZXRhKSA9IFxzdW1fe2k9MX1ebiBcbGVmdFsgeV9pIFxsb2coXHBpX2kpICsgKG5faSAtIHlfaSkgXGxvZygxIC0gXHBpX2kpIFxyaWdodF0NClxdDQoNClThu5FpIMSRYSBow7NhIGxvZy1saWtlbGlob29kIGLhurFuZyBJUkxTIChuaMawIGxvZ2lzdGljKSwgbmjGsG5nIGPDsyB0aMOqbSB54bq/dSB04buRIFwoIG5faSBcKS4NCg0KKipCaeG6v24gZ2nhuqMgdsOgIHRy4buNbmcgc+G7kToqKg0KDQpcWw0Kd19pID0gbl9pIFxwaV9pICgxIC0gXHBpX2kpDQpcXQ0KDQpcWw0Kel9pID0gXGV0YV9pICsgXGZyYWN7eV9pIC0gbl9pIFxwaV9pfXtuX2kgXHBpX2kgKDEgLSBccGlfaSl9DQpcXQ0KDQojIyMgKioxMS40IMavdSDEkWnhu4NtIHNvIHbhu5tpIG3DtCBow6xuaCBuaOG7iyBwaMOibioqDQoNCnwgROG6oW5nIGThu68gbGnhu4d1ICAgICAgICAgIHwgTcO0IGjDrG5oIHTGsMahbmcg4bupbmcgICAgICAgICAgICAgICB8IEdoaSBjaMO6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8DQp8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KfCAwLzEgdOG7q25nIGPDoSBuaMOibiAgICAgfCBI4buTaSBxdXkgbG9naXN0aWMgICAgICAgICAgICAgICB8IFwoIHlfaSBcc2ltIFx0ZXh0e0Jlcm5vdWxsaX0oXHBpX2kpIFwpICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgTmjDs20gbmhp4buBdSBjw6EgbmjDom4gICAgfCBCaW5vbWlhbCBHTE0gduG7m2kgXCggeV9pIC8gbl9pIFwpIHwgXCggeV9pIFxzaW0gXHRleHR7Qmlub21pYWx9KG5faSwgXHBpX2kpIFwpICAgICAgICAgICAgICAgICAgICAgfA0KDQrihpIgTcO0IGjDrG5oIG5ow7NtIGNobyBr4bq/dCBxdeG6oyDGsOG7m2MgbMaw4bujbmcgY2jDrW5oIHjDoWMgaMahbiB2w6wgZMO5bmcgbmhp4buBdSB0aMO0bmcgdGluIGjGoW4gdHLDqm4gbeG7l2kgcXVhbiBzw6F0Lg0KDQojIyMgKioxMS41IEThu68gbGnhu4d1IHThu7cgbOG7hyAocHJvcG9ydGlvbnMpKioNCg0KTuG6v3UgXCggeV9pIC8gbl9pIFwpIMSRxrDhu6NjIGdoaSBkxrDhu5tpIGThuqFuZyB04bu3IGzhu4cgKDAgPCB04bu3IGzhu4cgPCAxKSwgdGEgduG6q24gZMO5bmcgbcO0IGjDrG5oOg0KDQpcWw0KXGxvZyBcbGVmdChcZnJhY3t5X2kgLyBuX2l9ezEgLSB5X2kgLyBuX2l9XHJpZ2h0KSA9IHhfaV5UIFxiZXRhDQpcXQ0KDQrihpIgTmjGsG5nIHBo4bqjaSBjaOG7iSByw7Ugc+G7kSBs4bqnbiB0aOG7rSBcKCBuX2kgXCkgxJHhu4MgdMOtbmggxJHDum5nIHBoxrDGoW5nIHNhaS4NCg0KIyMjICoqMTEuNiBLaeG7g20gxJHhu4tuaCBtw7QgaMOsbmgqKg0KDQotIFdhbGQgdGVzdCBjaG8gY8OhYyBo4buHIHPhu5ENCg0KLSBLaeG7g20gxJHhu4tuaCBkZXZpYW5jZSBnaeG7r2EgbcO0IGjDrG5oIMSR4bqneSDEkeG7pyB2w6AgcsO6dCBn4buNbg0KDQotIEFJQy9CSUMgxJHhu4MgY2jhu41uIG3DtCBow6xuaA0KDQotIFBo4bqnbiBkxrAgUGVhcnNvbiAvIGRldmlhbmNlIMSR4buDIHBow6F0IGhp4buHbiDEkWnhu4NtIGLhuqV0IHRoxrDhu51uZw0KDQojIyMgKioxMS43IEtp4buDbSB0cmEgb3ZlcmRpc3BlcnNpb24qKg0KDQpHaeG7kW5nIGjhu5NpIHF1eSBsb2dpc3RpYywgbcO0IGjDrG5oIGJpbm9taWFsIGdp4bqjIMSR4buLbmg6DQoNClxbDQpcdGV4dHtWYXJ9KHlfaSkgPSBuX2kgXHBpX2kgKDEgLSBccGlfaSkNClxdDQoNCk7hur91IHRo4bqleSBwaMawxqFuZyBzYWkgcXVhbiBzw6F0IGzhu5tuIGjGoW4g4oaSIG92ZXJkaXNwZXJzaW9uLg0KDQoqKktp4buDbSB0cmE6KioNCg0KXFsNClxoYXR7XHBoaX0gPSBcZnJhY3tcdGV4dHtEZXZpYW5jZX19e24gLSBwfQ0KXF0NCg0K4oaSIE7hur91IFwoXGhhdHtccGhpfSA+IDEuNVwpOiBj4bqnbiBjaHV54buDbiBzYW5nIG3DtCBow6xuaCBxdWFzaS1iaW5vbWlhbA0KDQojIyAqKkNIxq/GoE5HIDEyOiBNw5QgSMOMTkggVFVZ4bq+TiBUw41OSCBU4buUTkcgUVXDgVQgVFdFRURFRSAoVFdFRURJRSBHTE1zKSoqDQoNCiMjIyAqKjEyLjEgR2nhu5tpIHRoaeG7h3UqKg0KDQpNw7QgaMOsbmggKipUd2VlZGllIEdMTSoqIG3hu58gcuG7mW5nIGjhu40gaMOgbSBtxakgYuG6sW5nIGPDoWNoIGNobyBwaMOpcCBwaMOibiBwaOG7kWkgY8OzIMSR4bq3YyDEkWnhu4NtIHRydW5nIGdpYW4gZ2nhu69hIGPDoWMgcGjDom4gcGjhu5FpIHF1ZW4gdGh14buZYyBuaMawOg0KDQotIEdhdXNzaWFuDQoNCi0gUG9pc3Nvbg0KDQotIEdhbW1hDQoNCi0gSW52ZXJzZSBHYXVzc2lhbg0KDQpNw7QgaMOsbmggVHdlZWRpZSBwaMO5IGjhu6NwIHbhu5tpIGPDoWMgbG/huqFpIGThu68gbGnhu4d1IGPDsyDEkeG6t2MgxJFp4buDbToNCg0KLSAqKkxpw6puIHThu6VjIGTGsMahbmcgKyBy4bqldCBuaGnhu4F1IGdpw6EgdHLhu4sgMCoqICANCiAgKHbDrSBk4bulOiBk4buvIGxp4buHdSBjaGkgcGjDrSwgY8OzIG5nxrDhu51pIGtow7RuZyB0acOqdSBkw7luZykNCiAgDQotICoqUGjDom4gdMOhbiBxdcOhIG3hu6ljIChvdmVyZGlzcGVyc2lvbikqKg0KDQotIEPDsyBj4bqjIHBo4bqnbiAqKnLhu51pIHLhuqFjKiogKDAsIDEsIDIsIC4uLikgKips4bqrbiBsacOqbiB04bulYyBkxrDGoW5nKioNCg0K4oaSIOG7qG5nIGThu6VuZyBy4buZbmcgcsOjaSB0cm9uZyAqKmLhuqNvIGhp4buDbSoqLCAqKnTDoGkgY2jDrW5oKiosICoqeSB04bq/KiosIHbDoCBjw6FjIGLDoGkgdG/DoW4gKip6ZXJvLWluZmxhdGVkIGRhdGEqKi4NCg0KLS0tDQoNCiMjIyAqKjEyLjIgxJDhu4tuaCBuZ2jEqWEgdsOgIHTDrW5oIGNo4bqldCoqDQoNClR3ZWVkaWUgbMOgIG3hu5l0IGzhu5twIHBow6JuIHBo4buRaSB0aHXhu5ljICoqaOG7jSBow6BtIG3FqSAoZXhwb25lbnRpYWwgZmFtaWx5KSoqLCB24bubaSAqKmjDoG0gcGjGsMahbmcgc2FpKiogY8OzIGThuqFuZzoNCg0KXFsNClx0ZXh0e1Zhcn0oWSkgPSBccGhpIFxtdV5wDQpcXQ0KDQpUcm9uZyDEkcOzOg0KDQotIFwoIFxtdSA9IFxtYXRoYmJ7RX1bWV0gXCk6IGvhu7MgduG7jW5nDQoNCi0gXCggXHBoaSA+IDAgXCk6IGjhu4cgc+G7kSBwaMOibiB0w6FuDQoNCi0gXCggcCBcKTogY2jhu4kgc+G7kSBz4bupYyBt4bqhbmggKCoqcG93ZXIgaW5kZXgqKikNCg0KLS0tDQoNCiMjIyAqKjEyLjMgR2nDoSB0cuG7iyDEkeG6t2MgYmnhu4d0IGPhu6dhIGNo4buJIHPhu5EgXCggcCBcKSoqDQoNCnwgXCggcCBcKSAgICAgICAgfCBQaMOibiBwaOG7kWkgdMawxqFuZyDhu6luZyAgICAgICAgICAgICAgICAgICAgIHwNCnwtLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwNCnwgMCAgICAgICAgICAgICAgfCBHYXVzc2lhbiAoTm9ybWFsKSAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgMSAgICAgICAgICAgICAgfCBQb2lzc29uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgXCggKDEsIDIpIFwpICAgfCBUd2VlZGllIGjhu5duIGjhu6NwICgwICsgZMawxqFuZyBsacOqbiB04bulYykgICAgIHwNCnwgMiAgICAgICAgICAgICAgfCBHYW1tYSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnwgMyAgICAgICAgICAgICAgfCBJbnZlcnNlIEdhdXNzaWFuICAgICAgICAgICAgICAgICAgICAgICAgIHwNCg0K4oaSIFbhu5tpIFwoIDEgPCBwIDwgMiBcKSwgbcO0IGjDrG5oICoqVHdlZWRpZSBo4buXbiBo4bujcCoqIGPDsyB0aOG7gzoNCg0KLSBUw6FpIGhp4buHbiDEkcaw4bujYyAqKnPhu5EgbMaw4bujbmcgbOG7m24gZ2nDoSB0cuG7iyAwKioNCg0KLSBNw7QgaMOsbmggaMOzYSDEkcaw4bujYyAqKmdpw6EgdHLhu4sgZMawxqFuZyBsacOqbiB04bulYyoqDQoNCioqUuG6pXQgcGjDuSBo4bujcCoqIGNobyBjw6FjIGLDoGkgdG/DoW4gbmjGsCAqKmNoaSBwaMOtIGLhuqNvIGhp4buDbSoqLCAqKnThu5VuIHRo4bqldCoqLCAqKmThu68gbGnhu4d1IGPDsyBz4buRIDAgdsOgIGdpw6EgdHLhu4sgdGnhu4FuIHThu4cqKi4NCg0KIyAqKkLDgEkgVOG6rFAgMioqDQoNCioqVGjhu7FjIGhp4buHbiB0aOG7kW5nIGvDqiBtw7QgdOG6oyBjaG8gY8OhYyBiaeG6v24gdHJvbmcgZmlsZTogU3VwZXJtYXJrZXQgVHJhbnNhY3Rpb25zLmNzdioqDQoNCmBgYHtyfQ0KbGlicmFyeShyZWFkcikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHNraW1yKQ0KbGlicmFyeShwc3ljaCkNCmxpYnJhcnkoY3N2KQ0KYGBgDQojIyAqKjEuIMSQ4buNYyBmaWxlIENTVioqDQoNCi0gVOG7h3AgKlN1cGVybWFya2V0IFRyYW5zYWN0aW9ucyogxJHGsOG7o2MgbMawdSBkxrDhu5tpIMSR4buLbmggZOG6oW5nICoqQ1NWKiosIHbDrCB24bqteSB0YSBz4bq9IMSR4buNYyBk4buvIGxp4buHdSB04burIHThu4dwIG7DoHkuICANCg0KLSBTYXUga2hpIMSR4buNYywgYuG7mSBk4buvIGxp4buHdSDEkcaw4bujYyBnw6FuIHbDoG8gYmnhur9uICoqZGF0YSoqIMSR4buDIHRodeG6rW4gdGnhu4duIGNobyB2aeG7h2MgeOG7rSBsw70gdsOgIHBow6JuIHTDrWNoIHNhdSBuw6B5Lg0KDQpgYGB7cn0NCmRhdGEgPC0gcmVhZC5jc3YoIkQ6L1BURExEVC9TdXBlcm1hcmtldCBUcmFuc2FjdGlvbnMuY3N2IiwgaGVhZGVyID0gVCkNCmBgYA0KDQotLS0NCg0KIyMgKioyLiBU4buVbmcgcXVhbiBi4buZIHPhu5EgbGnhu4d1KioNCg0KIyMjICoqMi4xIE7hu5lpIGR1bmcgYuG7mSBk4buvIGxp4buHdSoqDQoNCi0gQuG7mSBk4buvIGxp4buHdSAqU3VwZXJtYXJrZXQgVHJhbnNhY3Rpb25zKiBnaGkgbOG6oWkgdGjDtG5nIHRpbiB24buBIGPDoWMgKipnaWFvIGThu4tjaCBtdWEgaMOgbmcqKiB04bqhaSBt4buZdCBo4buHIHRo4buRbmcgc2nDqnUgdGjhu4ssIGJhbyBn4buTbSAqKnRow7RuZyB0aW4ga2jDoWNoIGjDoG5nKiosICoqduG7iyB0csOtIMSR4buLYSBsw70qKiwgdsOgICoqY2hpIHRp4bq/dCBjw6FjIHPhuqNuIHBo4bqpbSDEkcaw4bujYyBtdWEqKi4NCg0KLSBE4buvIGxp4buHdSBuw6B5IGPDsyB0aOG7gyDEkcaw4bujYyBz4butIGThu6VuZyDEkeG7gyAqKnBow6JuIHTDrWNoIGjDoG5oIHZpIG11YSBz4bqvbSBj4bunYSBraMOhY2ggaMOgbmcqKiwgKipwaMOibiBraMO6YyB0aOG7iyB0csaw4budbmcqKiwgaG/hurdjICoqxJHDoW5oIGdpw6EgaGnhu4d1IHF14bqjIGtpbmggZG9hbmgqKiB0aGVvIHThu6tuZyBz4bqjbiBwaOG6qW0sIGtodSB24buxYyB2w6AgbmjDs20gbmjDom4ga2jhuql1IGjhu41jLg0KDQojIyMgKioyLjIgRGFuaCBzw6FjaCBjw6FjIGJp4bq/biB2w6AgbcO0IHThuqMqKg0KDQpUw6puIGPhu6dhIGPDoWMgYmnhur9uIHRyb25nIGLhu5kgZOG7ryBsaeG7h3Ugc+G6vSBiYW8gZ+G7k206IA0KDQpgYGB7cn0NCm5hbWVzKGRhdGEpDQpgYGANCkPhu6UgdGjhu4MgdOG7q25nIGPDoWMgYmnhur9uIHbDoCBxdWFuIHPDoXQgY8OzIMO9IG5naMSpYToNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCg0KdmFyaWFibGVfZGVzY3JpcHRpb24gPC0gZGF0YS5mcmFtZSgNCiAgVmFyaWFibGUgPSBjKA0KICAgICJVbm5hbWVkOiAwIiwgIlB1cmNoYXNlRGF0ZSIsICJDdXN0b21lcklEIiwgIkdlbmRlciIsICJNYXJpdGFsU3RhdHVzIiwNCiAgICAiSG9tZW93bmVyIiwgIkNoaWxkcmVuIiwgIkFubnVhbEluY29tZSIsICJDaXR5IiwgIlN0YXRlb3JQcm92aW5jZSIsDQogICAgIkNvdW50cnkiLCAiUHJvZHVjdEZhbWlseSIsICJQcm9kdWN0RGVwYXJ0bWVudCIsICJQcm9kdWN0Q2F0ZWdvcnkiLA0KICAgICJVbml0c1NvbGQiLCAiUmV2ZW51ZSINCiAgKSwNCiAgRGVzY3JpcHRpb24gPSBjKA0KICAgICJNYSBkb25nIChjbyB0aGUgYm8gcXVhKSIsDQogICAgIk5nYXkgbXVhIGhhbmciLA0KICAgICJJRCBraGFjaCBoYW5nIiwNCiAgICAiR2lvaSB0aW5oIChGOiBudSwgTTogbmFtKSIsDQogICAgIlRpbmggdHJhbmcgaG9uIG5oYW4gKFM6IGRvYyB0aGFuLCBNOiBkYSBrZXQgaG9uKSIsDQogICAgIlNvIGh1dSBuaGEgKFk6IGNvLCBOOiBraG9uZykiLA0KICAgICJTbyBjb24gdHJvbmcgZ2lhIGRpbmgiLA0KICAgICJUaHUgbmhhcCBoYW5nIG5hbSAodGhlbyBuaG9tKSIsDQogICAgIlRoYW5oIHBobyBzaW5oIHNvbmciLA0KICAgICJCYW5nIC8gdGluaCIsDQogICAgIlF1b2MgZ2lhIiwNCiAgICAiTmhvbSBzYW4gcGhhbSBjaGluaCAoRm9vZCwgRHJpbmssIC4uLikiLA0KICAgICJQaG9uZyBiYW4gc2FuIHBoYW0gKFNuYWNrcywgUHJvZHVjZSwgLi4uKSIsDQogICAgIkRhbmggbXVjIHNhbiBwaGFtIGN1IHRoZSIsDQogICAgIlNvIGx1b25nIHNhbiBwaGFtIGRhIGJhbiIsDQogICAgIkRvYW5oIHRodSB0dSBnaWFvIGRpY2ggKFVTRCkiDQogICksDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KKQ0KDQpsaWJyYXJ5KGtuaXRyKQ0Ka2FibGUodmFyaWFibGVfZGVzY3JpcHRpb24sIGNvbC5uYW1lcyA9IGMoIkJpZW4iLCAiTW8gdGEiKSkNCg0KYGBgDQoNCi0tLQ0KDQojIyAqKjMgVGjhu5FuZyBrw6ogbcO0IHThuqMgY2hvIGPDoWMgYmnhur9uKioNCg0KIyMjICoqMy4xIFPhu5EgYmnhur9uIHbDoCBz4buRIHF1YW4gc8OhdCoqDQoNCmBgYHtyfQ0KZGltKGRhdGEpDQpgYGANCg0KLSBC4buZIGThu68gbGnhu4d1ICoqZGF0YSoqIGNo4bupYSB04buVbmcgY+G7mW5nICoqMTQuMDU5IGLhuqNuIGdoaSoqIHbhu5tpICoqMTYgYmnhur9uKiogxJHhurdjIHRyxrBuZy4NCg0KLSBN4buXaSBi4bqjbiBnaGkgdMawxqFuZyDhu6luZyB24bubaSBt4buZdCBnaWFvIGThu4tjaCBtdWEgaMOgbmcgdOG6oWkgc2nDqnUgdGjhu4ssIG3DtCB04bqjIGNoaSB0aeG6v3QgduG7gSBs4bqnbiBtdWEgxJHDsyB0aMO0bmcgcXVhIDE2IHRodeG7mWMgdMOtbmgga2jDoWMgbmhhdS4NCg0KIyMjICoqMy4yIEtp4buDbSB0cmEgY+G6pXUgdHLDumMgdOG7lW5nIHF1w6F0KioNCg0KxJDhu4MgaGnhu4N1IHLDtSBoxqFuIHbhu4EgY+G6pXUgdHLDumMgdOG7lW5nIHRo4buDIGPhu6dhIGLhu5kgZOG7ryBsaeG7h3UsIHRhIGPDsyB0aOG7gyB0aOG7sWMgaGnhu4duIHZp4buHYyBraeG7g20gdHJhIGPDoWMgdGjDoG5oIHBo4bqnbiBjxqEgYuG6o24gbmjGsCBz4buRIGzGsOG7o25nIGJp4bq/biwga2nhu4N1IGThu68gbGnhu4d1IGPhu6dhIHThu6tuZyBiaeG6v24sIGPFqW5nIG5oxrAgbeG7mXQgc+G7kSB0aMO0bmcgdGluIHThu5VuZyBxdWFuIGtow6FjLiBWaeG7h2MgbsOgeSBnacO6cCBjaMO6bmcgdGEgY8OzIGPDoWkgbmjDrG4gYmFvIHF1w6F0IHRyxrDhu5tjIGtoaSB0aeG6v24gaMOgbmggY8OhYyBixrDhu5tjIHBow6JuIHTDrWNoIGNodXnDqm4gc8OidSBoxqFuLg0KDQpgYGB7cn0NCnN0cihkYXRhKQ0KYGBgDQoNCkPDoWMgYmnhur9uIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgYmFvIGfhu5NtOg0KDQotIGBYYDogYmnhur9uIHPhu5Egbmd1ecOqbiwgY8OzIHRo4buDIGzDoCBjaOG7iSBz4buRIHRo4bupIHThu7EgY+G7p2EgYuG6o24gZ2hpLg0KDQotIGBQdXJjaGFzZURhdGVgOiBuZ8OgeSBtdWEgaMOgbmcsIMSRxrDhu6NjIGzGsHUgZMaw4bubaSBk4bqhbmcgY2h14buXaSBrw70gdOG7sSB24bubaSDEkeG7i25oIGThuqFuZyAiWVlZWS1NTS1ERCIuDQoNCi0gYEN1c3RvbWVySURgOiBtw6MgxJHhu4tuaCBkYW5oIGtow6FjaCBow6BuZyBkxrDhu5tpIGThuqFuZyBz4buRIG5ndXnDqm4uDQoNCi0gYEdlbmRlcmA6IGdp4bubaSB0w61uaCBraMOhY2ggaMOgbmcsIGvDvSBoaeG7h3UgYuG6sW5nIGvDvSB04buxIChGOiBu4buvLCBNOiBuYW0pLg0KDQotIGBNYXJpdGFsU3RhdHVzYDogdMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIChTOiDEkeG7mWMgdGjDom4sIE06IMSRw6Mga+G6v3QgaMO0bikuDQoNCi0gYEhvbWVvd25lcmA6IHRy4bqhbmcgdGjDoWkgc+G7nyBo4buvdSBuaMOgIChZOiBjw7MgbmjDoCwgTjoga2jDtG5nIGPDsyBuaMOgKS4NCg0KLSBgQ2hpbGRyZW5gOiBz4buRIGzGsOG7o25nIGNvbiB0cm9uZyBnaWEgxJHDrG5oLCBraeG7g3Ugc+G7kSBuZ3V5w6puLg0KDQotIGBBbm51YWxJbmNvbWVgOiBuaMOzbSB0aHUgbmjhuq1wIGjDoG5nIG7Eg20sIMSRxrDhu6NjIGdoaSBkxrDhu5tpIGThuqFuZyBjaHXhu5dpIGvDvSB04buxICh2w60gZOG7pTogIiQzMEsgLSAkNTBLIikuDQoNCi0gYENpdHlgOiB0w6puIHRow6BuaCBwaOG7kSBuxqFpIGtow6FjaCBow6BuZyBzaW5oIHPhu5FuZy4NCg0KLSBgU3RhdGVvclByb3ZpbmNlYDogYmFuZyBob+G6t2MgdOG7iW5oLCDEkcaw4bujYyBsxrB1IGTGsOG7m2kgZOG6oW5nIGNodeG7l2kga8O9IHThu7EuDQoNCi0gYENvdW50cnlgOiBxdeG7kWMgZ2lhLCBkxrDhu5tpIGThuqFuZyBjaHXhu5dpIGvDvSB04buxLg0KDQotIGBQcm9kdWN0RmFtaWx5YDogbmjDs20gc+G6o24gcGjhuqltIGNow61uaCwgdsOtIGThu6UgbmjGsCBGb29kLCBEcmluaywuLi4NCg0KLSBgUHJvZHVjdERlcGFydG1lbnRgOiBwaMOybmcgYmFuIHPhuqNuIHBo4bqpbSwgdsOtIGThu6UgbmjGsCBTbmFjayBGb29kcywgUHJvZHVjZSwuLi4NCg0KLSBgUHJvZHVjdENhdGVnb3J5YDogZGFuaCBt4bulYyBz4bqjbiBwaOG6qW0gY+G7pSB0aOG7gy4NCg0KLSBgVW5pdHNTb2xkYDogc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gxJHDoyBiw6FuLCBraeG7g3Ugc+G7kSBuZ3V5w6puLg0KDQotIGBSZXZlbnVlYDogZG9hbmggdGh1IHRodSDEkcaw4bujYyB04burIGdpYW8gZOG7i2NoLCBraeG7g3Ugc+G7kSB0aOG7sWMgKMSRxqFuIHbhu4sgVVNEKS4NCg0KVmnhu4djIGhp4buDdSByw7UgY+G6pXUgdHLDumMgdsOgIGtp4buDdSBk4buvIGxp4buHdSBj4bunYSBjw6FjIGJp4bq/biBz4bq9IGjhu5cgdHLhu6MgcuG6pXQgbmhp4buBdSB0cm9uZyB2aeG7h2MgcGjDom4gdMOtY2ggdsOgIHjhu60gbMO9IGThu68gbGnhu4d1IHRp4bq/cCB0aGVvLg0KDQoNClbDrCBi4buZIGThu68gbGnhu4d1IGJhbyBn4buTbSBj4bqjIGPDoWMgYmnhur9uIMSR4buLbmggdMOtbmggbmjGsCB0aMO0bmcgdGluIG5o4bqtbiBk4bqhbmcgaGF5IGPDoWMgcGjDom4gbG/huqFpIGxpw6puIHF1YW4gxJHhur9uIGtow6FjaCBow6BuZywgbmjhu69uZyBiaeG6v24gbsOgeSBraMO0bmcgdGjhu4MgdHLhu7FjIHRp4bq/cCBkw7luZyBjaG8gY8OhYyBwaMOpcCB0w61uaCBz4buRIGjhu41jIG5oxrAgY8OhYyBiaeG6v24gxJHhu4tuaCBsxrDhu6NuZyAodsOtIGThu6U6IGRvYW5oIHRodSwgc+G7kSBsxrDhu6NuZyBz4bqjbiBwaOG6qW0gYsOhbiByYSkuIERvIMSRw7MsIHRyb25nIHF1w6EgdHLDrG5oIHRo4buRbmcga8OqIG3DtCB04bqjLCB0YSBj4bqnbiBwaMOibiBiaeG7h3QgcsO1IGdp4buvYSBoYWkgbmjDs20gYmnhur9uIG7DoHkgxJHhu4MgbOG7sWEgY2jhu41uIHBoxrDGoW5nIHBow6FwIHjhu60gbMO9IHBow7kgaOG7o3AuDQoNCiMjIyAqKjMuMyBUaOG7kW5nIGvDqiBtw7QgdOG6oyBiaeG6v24gxJHhu4tuaCBsxrDhu6NuZyoqDQpgYGB7cn0NCmxpYnJhcnkocHN5Y2gpDQoNCmRlc2NyaWJlKHNlbGVjdChkYXRhLCBVbml0c1NvbGQsIFJldmVudWUsIENoaWxkcmVuKSkNCg0KYGBgDQoNCioqMS4gYFVuaXRzU29sZGAgICoqDQoNCihT4buRIGzGsOG7o25nIHPhuqNuIHBo4bqpbSDEkcaw4bujYyBiw6FuIHRyb25nIG3hu5dpIGdpYW8gZOG7i2NoKQ0KDQp8IFRo4buRbmcga8OqICAgICAgICAgICB8IEdpw6EgdHLhu4sgICAgIHwNCnwtLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tfA0KfCBUcnVuZyBiw6xuaCAgICAgICAgICB8IDQuMDggICAgICAgIHwNCnwgVHJ1bmcgduG7iyAgICAgICAgICAgIHwgNC4wMCAgICAgICAgfA0KfCBNaW4g4oCTIE1heCAgICAgICAgICAgfCAxIOKAkyA4ICAgICAgIHwNCnwgxJDhu5kgbOG7h2NoIGNodeG6qW4gKHNkKSAgfCAxLjE3ICAgICAgICB8DQp8IFNrZXcgKMSR4buZIGzhu4djaCkgICAgICB8IDAuMDEg4oaSIEfhuqduIMSR4buRaSB44bupbmcgfA0KfCBLdXJ0b3NpcyAgICAgICAgICAgIHwgLTAuNDQg4oaSIEfhuqduIGNodeG6qW4gfA0KDQoqKk5o4bqtbiB4w6l0OioqIEjhuqd1IGjhur90IGPDoWMgZ2lhbyBk4buLY2ggYsOhbiBraG/huqNuZyA0IHPhuqNuIHBo4bqpbS4gUGjDom4gcGjhu5FpIGfhuqduIHbhu5tpIHBow6JuIHBo4buRaSBjaHXhuqluLg0KDQotLS0NCg0KKioyLiBgUmV2ZW51ZWAgICoqDQoNCihEb2FuaCB0aHUgbeG7l2kgZ2lhbyBk4buLY2gsIMSRxqFuIHbhu4sgVVNEKQ0KDQp8IFRo4buRbmcga8OqICAgICAgICAgICB8IEdpw6EgdHLhu4sgICAgIHwNCnwtLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tfA0KfCBUcnVuZyBiw6xuaCAgICAgICAgICB8IDEzLjAwIFVTRCAgIHwNCnwgVHJ1bmcgduG7iyAgICAgICAgICAgIHwgMTEuMjUgVVNEICAgfA0KfCBNaW4g4oCTIE1heCAgICAgICAgICAgfCAwLjUzIOKAkyA1Ni43MCBVU0QgfA0KfCDEkOG7mSBs4buHY2ggY2h14bqpbiAoc2QpICB8IDguMjIgICAgICAgIHwNCnwgU2tldyAoxJHhu5kgbOG7h2NoKSAgICAgIHwgMS4xMyDihpIgUGjDom4gcGjhu5FpIGzhu4djaCBwaOG6o2kgfA0KfCBLdXJ0b3NpcyAgICAgICAgICAgIHwgMS4zOSDihpIgUGjDom4gcGjhu5FpIG5o4buNbiBoxqFuIGNodeG6qW4gfA0KDQoqKk5o4bqtbiB4w6l0OioqIERvYW5oIHRodSBnaWFvIGThu4tjaCBjw7MgeHUgaMaw4bubbmcgbOG7h2NoIHBo4bqjaSwgbmdoxKlhIGzDoCBwaOG6p24gbOG7m24gY8OhYyBnaWFvIGThu4tjaCBjw7MgZG9hbmggdGh1IHRo4bqlcCB2w6AgY2jhu4kgbeG7mXQgc+G7kSDDrXQgbWFuZyBs4bqhaSBnacOhIHRy4buLIGNhby4NCg0KKiozLiBDaGlsZHJlbioqIChT4buRIGNvbiBj4bunYSBraMOhY2ggaMOgbmcpDQoNCi0gKipQaMOibiBi4buRIGtow6EgxJHhu5FpIHjhu6luZyoqDQoNCiAgxJDhu5kgbOG7h2NoIChza2V3KSBn4bqnbiBi4bqxbmcgMCwgY2hvIHRo4bqleSBwaMOibiBi4buRIGtow7RuZyBs4buHY2ggxJHDoW5nIGvhu4Mgc2FuZyB0csOhaSBoYXkgcGjhuqNpLiAgDQogIEdpw6EgdHLhu4sgdHJ1bmcgYsOsbmggKDIsNTMpIGfhuqduIGLhurFuZyB0cnVuZyB24buLICgzKSwgeMOhYyBuaOG6rW4gdMOtbmggxJHhu5FpIHjhu6luZyBuw6B5Lg0KDQotICoqxJDhu5kgcGjDom4gdMOhbiB24burYSBwaOG6o2kqKg0KDQogIMSQ4buZIGzhu4djaCBjaHXhuqluIGtob+G6o25nIDEsNSwgbmdoxKlhIGzDoCDEkWEgc+G7kSBraMOhY2ggaMOgbmcgY8OzIHThu6sgMSDEkeG6v24gNCBjb24uICANCiAgS2hv4bqjbmcgNjglIGPDoWMgcXVhbiBzw6F0IG7hurFtIHRyb25nIGtob+G6o25nIDEsMCDEkeG6v24gNCwwIGNvbiAoxrDhu5tjIGzGsOG7o25nIGLhurFuZyBtZWFuIMKxIFNEKS4NCg0KLSAqKkdpw6EgdHLhu4sgY+G7sWMgdHLhu4sgaOG7o3AgbMO9KioNCg0KICBT4buRIGNvbiB0aOG6pXAgbmjhuqV0IGzDoCAwIHbDoCBjYW8gbmjhuqV0IGzDoCA1LCBraMO0bmcgY8OzIGdpw6EgdHLhu4sgbmdv4bqhaSBs4buHIGLhuqV0IHRoxrDhu51uZyAodsOtIGThu6UgbmjGsCA+IDEwKS4NCg0KLSAqKsSQ4buZIG5o4buNbiDDom0qKg0KDQogIEt1cnRvc2lzIDwgMCBjaG8gdGjhuqV5IHBow6JuIGLhu5EgaMahaSDigJxwaOG6s25n4oCdLCB04bupYyDEkeG7iW5oIHRo4bqlcCBoxqFuIHBow6JuIHBo4buRaSBjaHXhuqluLCAgDQogIHbhu5tpIHThuqduIHN14bqldCDhu58gdHJ1bmcgdMOibSDDrXQgY8O0IMSR4bq3YyBoxqFuLCBoYWkgxJF1w7RpIHBow6JuIGLhu5EgaMahaSBkw6B5IGjGoW4gbmjGsG5nIHbhuqtuIG7hurFtIHRyb25nIHThuqdtIGtp4buDbSBzb8OhdC4NCg0KKipIw6BtIMO9KioNCg0KLSBDw7MgdGjhu4MgcGjDom4gbmjDs20ga2jDoWNoIGjDoG5nIGThu7FhIHRyw6puIHPhu5EgY29uIHRow6BuaDogIA0KDQogIC0gS2jDtG5nIGNvbiAoMCkgIA0KICANCiAgLSBHaWEgxJHDrG5oIG5o4buPICgx4oCTMikgIA0KICANCiAgLSBHaWEgxJHDrG5oIHRydW5nIGLDrG5oICgz4oCTNCkgIA0KICANCiAgLSBHaWEgxJHDrG5oIGzhu5tuICg1KQ0KDQotIFbhu4EgdGnhur9wIHRo4buLIHPhuqNuIHBo4bqpbTogIA0KDQogIC0gTmjDs20gMOKAkzEgY29uIGPDsyB0aOG7gyBxdWFuIHTDom0gxJHhur9uIHPhuqNuIHBo4bqpbSBjw6EgbmjDom4gaG/hurdjIGTDoG5oIGNobyDEkcO0aS4gIA0KICANCiAgLSBOaMOzbSBjw7MgdOG7qyAzIGNvbiB0cuG7nyBsw6puIMawdSB0acOqbiBnw7NpIHPhuqNuIHBo4bqpbSBnaWEgxJHDrG5oIHbDoCBjw6FjIGNoxrDGoW5nIHRyw6xuaCBjaGnhur90IGto4bqldSB0aGVvIHPhu5EgbMaw4bujbmcuDQoNCi0gVHJvbmcgbcO0IGjDrG5oIGThu7EgxJFvw6FuLCBkbyBwaMOibiBi4buRIHTGsMahbmcgxJHhu5FpIMSR4buRaSB44bupbmcgdsOgIGtow7RuZyBjw7Mgbmdv4bqhaSBs4buHIG5naGnDqm0gdHLhu41uZywgYmnhur9uICoqQ2hpbGRyZW4qKiBjw7MgdGjhu4MgxJHGsOG7o2Mgc+G7rSBk4bulbmcgdHLhu7FjIHRp4bq/cCBtw6Aga2jDtG5nIGPhuqduIGJp4bq/biDEkeG7lWkgbmjGsCBsb2cgaGF5IHdpbnNvcml6ZS4NCg0KIyMjICoqMy40IEJp4bq/biDEkeG7i25oIHTDrW5oKioNCg0KYGBge3J9DQojIEzhuqV5IHTDqm4gY8OhYyBiaeG6v24gxJHhu4tuaCB0w61uaA0KY2F0ZWdvcmljYWxfdmFycyA8LSBjKA0KICAiR2VuZGVyIiwgIk1hcml0YWxTdGF0dXMiLCAiSG9tZW93bmVyIiwgIkFubnVhbEluY29tZSIsDQogICJDaXR5IiwgIlN0YXRlb3JQcm92aW5jZSIsICJDb3VudHJ5IiwNCiAgIlByb2R1Y3RGYW1pbHkiLCAiUHJvZHVjdERlcGFydG1lbnQiLCAiUHJvZHVjdENhdGVnb3J5Ig0KKQ0KDQojIFThuqFvIGLhuqNuZyB04bqnbiBz4buRIGNobyB04burbmcgYmnhur9uDQpmb3IgKHZhciBpbiBjYXRlZ29yaWNhbF92YXJzKSB7DQogIGNhdCgiXG4jIyMiLCB2YXIsICJcbiIpDQogIHByaW50KHRhYmxlKGRhdGFbW3Zhcl1dKSkNCiAgY2F0KCJcbiIpDQp9DQpgYGANCiMjIyMgKiozLjQuMS4gR2VuZGVyIChHaeG7m2kgdMOtbmgpKioNCg0KYGBge3J9DQpnZW5kZXJfdGFibGUgPC0gdGFibGUoZGF0YSRHZW5kZXIpDQpnZW5kZXJfcHJvcCA8LSBwcm9wLnRhYmxlKGdlbmRlcl90YWJsZSkNCmthYmxlKA0KICBjYmluZChTb19sdW9uZyA9IGdlbmRlcl90YWJsZSwgVHlfbGUgPSByb3VuZChnZW5kZXJfcHJvcCAqIDEwMCwgMikpLA0KICBjb2wubmFtZXMgPSBjKCJTbyBsdW9uZyIsICJUeSBsZSAoJSkiKQ0KKQ0KDQpgYGANCmBgYHtyfQ0KZ2VuZGVyX2RmIDwtIGFzLmRhdGEuZnJhbWUoZ2VuZGVyX3Byb3ApIHw+DQogIG11dGF0ZSgNCiAgICBHZW5kZXIgID0gbmFtZXMoZ2VuZGVyX3Byb3ApLA0KICAgIFBlcmNlbnQgPSByb3VuZChGcmVxICogMTAwLCAyKQ0KICApDQoNCmdncGxvdChnZW5kZXJfZGYsIGFlcyh4ID0gIiIsIHkgPSBQZXJjZW50LCBmaWxsID0gR2VuZGVyKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDEsIGNvbG9yID0gIndoaXRlIikgKw0KICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKFBlcmNlbnQsICIlIikpLA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIHNpemUgPSA1KSArDQogIGxhYnModGl0bGUgPSAiVOG7tyBs4buHIGdp4bubaSB0w61uaCIsIHggPSBOVUxMLCB5ID0gTlVMTCkgKw0KICB0aGVtZV92b2lkKCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjNEU3OUE3IiwgIiNGMjhFMkIiKSkNCmBgYA0KDQotIFThu7cgbOG7hyBraMOhY2ggaMOgbmcgdGhlbyBnaeG7m2kgdMOtbmgga2jDoSBjw6JuIGLhurFuZyBnaeG7r2EgbmFtIChNKSB2w6AgbuG7ryAoRikuDQoNCi0gTuG7ryBjaGnhur9tIDUxJSwgbmjhu4luaCBoxqFuIG3hu5l0IGNow7p0IHNvIHbhu5tpIG5hbSBsw6AgNDklLg0KDQotIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IGtow7RuZyBjw7Mgc+G7sSBjaMOqbmggbOG7h2NoIGzhu5tuIHbhu4EgZ2nhu5tpIHTDrW5oIHRyb25nIG3huqt1IGThu68gbGnhu4d1IG7DoHkuDQoNCi0gQ+G7rWEgaMOgbmcvY8O0bmcgdHkgY8OzIHRo4buDIHRoaeG6v3Qga+G6vyBjaGnhur9uIGzGsOG7o2MgbWFya2V0aW5nIGtow7RuZyBj4bqnbiBwaMOibiBiaeG7h3QgZ2nhu5tpIHTDrW5oIG3huqFuaCwgdsOsIGPhuqMgaGFpIG5ow7NtIGtow6FjaCBow6BuZyDEkeG7gXUgdMawxqFuZyDEkcawxqFuZyB24buBIHThu7cgbOG7hy4NCg0KIyMjIyAqKjMuNC4yLiBNYXJpdGFsU3RhdHVzIChUw6xuaCB0cuG6oW5nIGjDtG4gbmjDom4pKioNCg0KYGBge3J9DQptYXJpdGFsX3RhYmxlIDwtIHRhYmxlKGRhdGEkTWFyaXRhbFN0YXR1cykNCm1hcml0YWxfcHJvcCA8LSBwcm9wLnRhYmxlKG1hcml0YWxfdGFibGUpDQprYWJsZSgNCiAgY2JpbmQoU29fbHVvbmcgPSBtYXJpdGFsX3RhYmxlLCBUeV9sZSA9IHJvdW5kKG1hcml0YWxfcHJvcCAqIDEwMCwgMikpLA0KICBjb2wubmFtZXMgPSBjKCJTbyBsdW9uZyIsICJUeSBsZSAoJSkiKQ0KKQ0KDQpgYGANCmBgYHtyfQ0KIyDEkMawYSB24buBIGRhdGHigJFmcmFtZQ0KbWFyaXRhbF9kZiA8LSBkYXRhLmZyYW1lKA0KICBTdGF0dXMgID0gbmFtZXMobWFyaXRhbF9wcm9wKSwNCiAgUGVyY2VudCA9IHJvdW5kKGFzLnZlY3RvcihtYXJpdGFsX3Byb3ApICogMTAwLCAyKQ0KKQ0KDQojIEJp4buDdSDEkeG7kyB0csOybg0KZ2dwbG90KG1hcml0YWxfZGYsIGFlcyh4ID0gIiIsIHkgPSBQZXJjZW50LCBmaWxsID0gU3RhdHVzKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDEsIGNvbG9yID0gIndoaXRlIikgKw0KICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKFBlcmNlbnQsICIlIikpLA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIHNpemUgPSA1KSArDQogIGxhYnModGl0bGUgPSAiVOG7tyBs4buHIHTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiIsIHggPSBOVUxMLCB5ID0gTlVMTCkgKw0KICB0aGVtZV92b2lkKCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjNTlBMTRGIiwgIiNFREM5NDgiKSkgICMgdHXhu7MgY2jhu41uIG3DoHUNCmBgYA0KDQotIFTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiBj4bunYSBraMOhY2ggaMOgbmcga2jDoSBjw6JuIGLhurFuZyBnaeG7r2EgaGFpIG5ow7NtLiBUcm9uZyDEkcOzLCBraMOhY2ggaMOgbmcgxJHhu5ljIHRow6JuIGNoaeG6v20gdOG7tyBs4buHIG5o4buJbmggaMahbiBt4buZdCBjaMO6dCAoNTEuMTYlKSBzbyB24bubaSBuaMOzbSDEkcOjIGvhur90IGjDtG4gKDQ4Ljg0JSkuIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IHNpw6p1IHRo4buLIGPDsyB04buHcCBraMOhY2ggaMOgbmcgxJFhIGThuqFuZyB24buBIHTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiwga2jDtG5nIG5naGnDqm5nIGjhurNuIHbhu4EgbmjDs20gbsOgby4NCg0KIyMjIyAqKjMuNC4zLiBIb21lb3duZXIgKFPhu58gaOG7r3UgbmjDoCkqKg0KDQpgYGB7cn0NCmhvbWVvd25lcl90YWJsZSA8LSB0YWJsZShkYXRhJEhvbWVvd25lcikNCmhvbWVvd25lcl9wcm9wIDwtIHByb3AudGFibGUoaG9tZW93bmVyX3RhYmxlKQ0Ka2FibGUoDQogIGNiaW5kKFNvX2x1b25nID0gaG9tZW93bmVyX3RhYmxlLCBUeV9sZSA9IHJvdW5kKGhvbWVvd25lcl9wcm9wICogMTAwLCAyKSksDQogIGNvbC5uYW1lcyA9IGMoIlNvIGx1b25nIiwgIlR5IGxlICglKSIpDQopDQpgYGANCg0KYGBge3J9DQojIMSQxrBhIHbhu4EgZGF0YeKAkWZyYW1lDQpob21lb3duZXJfZGYgPC0gZGF0YS5mcmFtZSgNCiAgT3duZXIgICA9IG5hbWVzKGhvbWVvd25lcl9wcm9wKSwgICAgICAgICAgICAgICAgICAgICMgdsOtIGThu6U6ICJZZXMiIC8gIk5vIg0KICBQZXJjZW50ID0gcm91bmQoYXMudmVjdG9yKGhvbWVvd25lcl9wcm9wKSAqIDEwMCwgMikgIyBjaHV54buDbiBzYW5nICUNCikNCg0KIyBCaeG7g3UgxJHhu5MgdHLDsm4NCmdncGxvdChob21lb3duZXJfZGYsIGFlcyh4ID0gIiIsIHkgPSBQZXJjZW50LCBmaWxsID0gT3duZXIpKSArDQogIGdlb21fY29sKHdpZHRoID0gMSwgY29sb3IgPSAid2hpdGUiKSArDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoUGVyY2VudCwgIiUiKSksDQogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwgc2l6ZSA9IDUpICsNCiAgbGFicyh0aXRsZSA9ICJU4bu3IGzhu4cgY2jhu6cgc+G7nyBo4buvdSBuaMOgIiwgeCA9IE5VTEwsIHkgPSBOVUxMKSArDQogIHRoZW1lX3ZvaWQoKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNFMTU3NTkiLCAiIzc2QjdCMiIpKSAgICMgdHXhu7MgY2jhu41uIG3DoHUNCmBgYA0KDQotIEtob+G6o25nIDYwJSBraMOhY2ggaMOgbmcgdHJvbmcgZOG7ryBsaeG7h3UgbMOgIG5nxrDhu51pIHPhu58gaOG7r3UgbmjDoCwgdHJvbmcga2hpIGfhuqduIDQwJSBraMO0bmcgc+G7nyBo4buvdSBuaMOgLiDEkGnhu4F1IG7DoHkgcGjhuqNuIMOhbmggcuG6sW5nIHBo4bqnbiBs4bubbiBraMOhY2ggaMOgbmcgY+G7p2Egc2nDqnUgdGjhu4sgdGh14buZYyBuaMOzbSDEkcOjIGPDsyDEkWnhu4F1IGtp4buHbiBraW5oIHThur8g4buVbiDEkeG7i25oIGjGoW4uIFR1eSBuaGnDqm4sIG5ow7NtIGtow7RuZyBz4bufIGjhu691IG5ow6AgduG6q24gY2hp4bq/bSB04bu3IGzhu4cgxJHDoW5nIGvhu4MsIGNobyB0aOG6pXkgc2nDqnUgdGjhu4sgY8WpbmcgdGnhur9wIGPhuq1uIMSRxrDhu6NjIG5ow7NtIGtow6FjaCBow6BuZyB0aHXDqiBuaMOgIGhv4bq3YyBjaMawYSBjw7MgbmjDoCByacOqbmcuDQoNCiMjIyMgKiozLjQuNC4gQW5udWFsSW5jb21lIChUaHUgbmjhuq1wIGjDoG5nIG7Eg20g4oCTIHRoZW8gbmjDs20pKioNCg0KYGBge3J9DQojIEzDoG0gc+G6oWNoIGJp4bq/biBBbm51YWxJbmNvbWUgbuG6v3UgY+G6p24NCmRhdGEkQW5udWFsSW5jb21lIDwtIGdzdWIoIlxcJCIsICIiLCBkYXRhJEFubnVhbEluY29tZSkNCmRhdGEkQW5udWFsSW5jb21lIDwtIGdzdWIoIlx1MjAxMyIsICItIiwgZGF0YSRBbm51YWxJbmNvbWUpDQpkYXRhJEFubnVhbEluY29tZSA8LSB0cmltd3MoZGF0YSRBbm51YWxJbmNvbWUpDQpkYXRhJEFubnVhbEluY29tZSA8LSBhcy5mYWN0b3IoZGF0YSRBbm51YWxJbmNvbWUpDQoNCiMgVMOtbmggdOG6p24gc3XhuqV0IHbDoCB04bu3IGzhu4cgcGjhuqduIHRyxINtDQppbmNvbWVfdGFibGUgPC0gdGFibGUoZGF0YSRBbm51YWxJbmNvbWUpDQppbmNvbWVfcHJvcCAgPC0gcHJvcC50YWJsZShpbmNvbWVfdGFibGUpDQoNCiMgS+G6v3QgaOG7o3AgdGjDoG5oIGLhuqNuZw0KaW5jb21lX2RmIDwtIGRhdGEuZnJhbWUoDQogIE11YyAgICAgID0gbmFtZXMoaW5jb21lX3RhYmxlKSwNCiAgU29fbHVvbmcgPSBhcy52ZWN0b3IoaW5jb21lX3RhYmxlKSwNCiAgVHlfbGUgICAgPSByb3VuZCgxMDAgKiBhcy52ZWN0b3IoaW5jb21lX3Byb3ApLCAyKQ0KKQ0KDQojIEhp4buDbiB0aOG7iyBi4bqjbmcgxJHhurlwDQprYWJsZShpbmNvbWVfZGYsIGNvbC5uYW1lcyA9IGMoIk3hu6ljIHRodSBuaOG6rXAiLCAiU+G7kSBsxrDhu6NuZyIsICJU4bu3IGzhu4cgKCUpIikpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoaW5jb21lX2RmLCBhZXMoeCA9IE11YywgeSA9IFNvX2x1b25nKSkgKw0KICBnZW9tX2NvbChmaWxsID0gIiM0RTc5QTciKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoVHlfbGUsICIlIikpLA0KICAgICAgICAgICAgdmp1c3QgPSAtMC4zLCBzaXplID0gNCkgKw0KICBsYWJzKHRpdGxlID0gIlBow6JuIGLhu5EgbeG7qWMgdGh1IG5o4bqtcCIsDQogICAgICAgeCA9ICJN4bupYyB0aHUgbmjhuq1wIiwNCiAgICAgICB5ID0gIlPhu5EgbMaw4bujbmciKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTMpICsNCiAgdGhlbWUoDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKQ0KICApDQpgYGANCg0KDQoqKsSQaeG7g20gbuG7lWkgYuG6rXQ6KioNCg0KLSAqKlThuq1wIHRydW5nIHbDoG8gdGh1IG5o4bqtcCB04bqnbSB0cnVuZzoqKiBOaMOzbSBjw7MgdGh1IG5o4bqtcCB0cm9uZyBraG/huqNuZyAqKjMwS+KAr+KAk+KArzcwSyBjaGnhur9tIGtob+G6o25nIDUwJSoqIHThu5VuZyBz4buRIGtow6FjaCBow6BuZy4gxJDDonkgY2jDrW5oIGzDoCAqKnRo4buLIHRyxrDhu51uZyBt4bulYyB0acOqdSBjaMOtbmgqKi4NCg0KLSAqKlRodSBuaOG6rXAgdGjhuqVwIC0gdHJ1bmcgKDEwS+KAr+KAk+KArzMwSykqKiB24bqrbiBjaGnhur9tIGfhuqduICoqMjIlKiosIGNobyB0aOG6pXkgc+G7sSBoaeG7h24gZGnhu4duIHLDtSBy4buHdCBj4bunYSBwaMOibiBraMO6YyB0aeG6v3Qga2nhu4dtLiBO4bq/dSBz4bqjbiBwaOG6qW0gaG/hurdjIGThu4tjaCB24bulIGPhuqduIMSR4buLbmggZ2nDoSwgKipuw6puIGPDom4gbmjhuq9jIGfDs2kgZ2nDoSBwaMO5IGjhu6NwIG5ow7NtIG7DoHkqKi4NCg0KLSBOaMOzbSBjw7MgKip0aHUgbmjhuq1wIGNhbyAoPuKArzkwSykqKiBjaOG7iSBjaGnhur9tIGtob+G6o25nICoqMTYlKiouIFJpw6puZyBuaMOzbSBy4bqldCBjYW8gKio+4oCvMTUwSyoqIGzDoCAqKnLhuqV0IG5o4buPKiouIERvIMSRw7MsIGPDoWMgY2hp4bq/biBk4buLY2ggc+G6o24gcGjhuqltL2Thu4tjaCB24bulIGNhbyBj4bqlcCAqKmPhuqduIG5o4bqvbSDEkcO6bmcgxJHhu5FpIHTGsOG7o25nLCB0csOhbmggbGFuIHLhu5luZyB0aGnhur91IGhp4buHdSBxdeG6oyoqLg0KDQotICoqUGjDom4gYuG7kSB0aHUgbmjhuq1wIGLhu4sgbOG7h2NoIHRyw6FpIChsZWZ0LXNrZXdlZCk6KiogUGjhuqduIGzhu5tuIGtow6FjaCBow6BuZyB0aHXhu5ljIG5ow7NtIHRodSBuaOG6rXAgdGjhuqVwIC0gdHJ1bmcuICoqxJDhu4luaCBwaMOibiBi4buRIHLGoWkgdsOgbyBuaMOzbSAzMEvigJM1MEsqKiwgY8OgbmcgduG7gSBt4bupYyBjYW8gdGjDrCBz4buRIGzGsOG7o25nIGPDoG5nIGdp4bqjbS4NCg0KKipIw6BtIMO9KioNCg0KLSAqKkNoaeG6v24gbMaw4bujYyBnacOhICYga2h1eeG6v24gbcOjaToqKiDGr3UgdGnDqm4geMOieSBk4buxbmcgY8OhYyBnw7NpICoqZ2nDoSB0cnVuZyBiw6xuaCAoMzBL4oCTNzBLKSoqIMSRaSBrw6htICoqY8OhYyBs4buxYSBjaOG7jW4gdGnhur90IGtp4buHbSoqIGNobyBuaMOzbSB0aHUgbmjhuq1wIHRo4bqlcCAoMTBL4oCTMzBLKS4NCg0KLSAqKlPhuqNuIHBo4bqpbSBjYW8gY+G6pXAgLyBVcHNlbGw6KiogVOG6rXAgdHJ1bmcgdsOgbyB2aeG7h2MgKip4w6J5IGThu7FuZyDEkeG7gSBuZ2jhu4sgZ2nDoSB0cuG7iyBjYW8gcsO1IG7DqXQqKiwgdsOsIG5ow7NtIHRodSBuaOG6rXAgY2FvIHR1eSBuaOG7jyBuaMawbmcgduG6q24gY8OzIGfhuqduICoqMi4wMDAga2jDoWNoIGjDoG5nIHRp4buBbSBuxINuZyAodGh1IG5o4bqtcCA+IDkwSykqKi4NCg0KLSAqKlBow6JuIGtow7pjIHRp4bq/cCB0aOG7izoqKiBD4bqnbiBjaGlhIMOtdCBuaOG6pXQgKiozIHThuqduZyB0aHUgbmjhuq1wKio6DQoNCiAgLSAqKlRo4bqlcCAoPDMwSykqKg0KICANCiAgLSAqKlRydW5nICgzMEvigJM3MEspKioNCiAgDQogIC0gKipDYW8gKD43MEspKiogxJHhu4MgKipjw6EgbmjDom4gaMOzYSBu4buZaSBkdW5nIHbDoCB0aMO0bmcgxJFp4buHcCB0aeG6v3AgdGjhu4sqKiBwaMO5IGjhu6NwIHThu6tuZyBuaMOzbS4NCg0KIyMjIyAqKjMuNC41LiBDaXR5IChUaMOgbmggcGjhu5EpKioNCg0KYGBge3J9DQojIE7hur91IG114buRbiwgY8OzIHRo4buDIGLhu48ga2hv4bqjbmcgdHLhuq9uZyBkxrAgdsOgIMOpcCBmYWN0b3INCmRhdGEkQ2l0eSA8LSB0cmltd3MoZGF0YSRDaXR5KQ0KZGF0YSRDaXR5IDwtIGFzLmZhY3RvcihkYXRhJENpdHkpDQoNCiMgVMOtbmggdOG6p24gc3XhuqV0ICYgdOG7tyBs4buHIHBo4bqnbiB0csSDbQ0KY2l0eV90YWJsZSA8LSB0YWJsZShkYXRhJENpdHkpDQpjaXR5X3Byb3AgIDwtIHByb3AudGFibGUoY2l0eV90YWJsZSkNCg0KIyBHaMOpcCB0aMOgbmggZGF0YeKAkWZyYW1lDQpjaXR5X2RmIDwtIGRhdGEuZnJhbWUoDQogIENpdHkgICAgID0gbmFtZXMoY2l0eV90YWJsZSksDQogIFNvX2x1b25nID0gYXMudmVjdG9yKGNpdHlfdGFibGUpLA0KICBUeV9sZSAgICA9IHJvdW5kKDEwMCAqIGFzLnZlY3RvcihjaXR5X3Byb3ApLCAyKSwNCiAgcm93Lm5hbWVzID0gTlVMTA0KKQ0KDQojIEhp4buDbiB0aOG7iyBi4bqjbmcgxJHhurlwDQprYWJsZShjaXR5X2RmLA0KICAgICAgY29sLm5hbWVzID0gYygiVGjDoG5oIHBo4buRIiwgIlPhu5EgbMaw4bujbmciLCAiVOG7tyBs4buHICglKSIpKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGNpdHlfZGYsIGFlcyh4ID0gcmVvcmRlcihDaXR5LCBTb19sdW9uZyksIHkgPSBTb19sdW9uZykpICsNCiAgZ2VvbV9jb2woZmlsbCA9ICIjNTlBMTRGIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKFR5X2xlLCAiJSIpKSwNCiAgICAgICAgICAgIGhqdXN0ID0gLTAuMSwgc2l6ZSA9IDMuNSkgKw0KICBjb29yZF9mbGlwKCkgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeG9heSB0cuG7pWMgLT4gY+G7mXQgbuG6sW0gbmdhbmcNCiAgbGFicyh0aXRsZSA9ICJQaMOibiBi4buRIGtow6FjaCBow6BuZyB0aGVvIHRow6BuaCBwaOG7kSIsDQogICAgICAgeCA9ICJUaMOgbmggcGjhu5EiLA0KICAgICAgIHkgPSAiU+G7kSBsxrDhu6NuZyIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwgICAgICAgICAgICMgdHLhu6VjIHkgbMOgIHTDqm4gdGjDoG5oIHBo4buRLCBraMO0bmcgY+G6p24gdGnDqnUgxJHhu4ENCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApDQogICkNCmBgYA0KDQoNCioqTmjhuq1uIHjDqXQgdOG7lW5nIHF1YW46KioNCg0KLSAqKlThuq1wIHRydW5nIHThuqFpIG3hu5l0IHPhu5EgdGjDoG5oIHBo4buRIGzhu5tuOioqICANCg0KICBOaOG7r25nIHRow6BuaCBwaOG7kSBjw7MgdOG7tyBs4buHIGtow6FjaCBow6BuZyBjYW8gbmjhuqV0IGJhbyBn4buTbToNCiAgLSAqKlNhbGVtICg5Ljg2JSkqKg0KICANCiAgLSAqKlRhY29tYSAoOC45NCUpKioNCiAgDQogIC0gKipMb3MgQW5nZWxlcyAoNi41OSUpKioNCiAgDQogIC0gKipTZWF0dGxlICg2LjU2JSkqKg0KICANCiAgLSAqKlBvcnRsYW5kICg2LjIzJSkqKg0KICANCiAgLSAqKlNhbiBEaWVnbyAoNi4xNiUpKioNCg0KICDihpIgxJDDonkgbMOgIG5o4buvbmcga2h1IHbhu7FjICoqdOG6rXAgdHJ1bmcgxJHDtG5nIGtow6FjaCBow6BuZyBuaOG6pXQqKiwgbsOqbiAqKsawdSB0acOqbiB0cm9uZyBjw6FjIGNoaeG6v24gZOG7i2NoIG1hcmtldGluZywgcGjDom4gcGjhu5FpIGhv4bq3YyBk4buLY2ggduG7pSBraMOhY2ggaMOgbmcqKi4NCg0KLSAqKlBow6JuIGLhu5EgdMawxqFuZyDEkeG7kWkgdHLhuqNpIMSR4buBdSDhu58gbmjDs20gZ2nhu69hOioqIA0KDQogIE3hu5l0IHPhu5EgdGjDoG5oIHBo4buRIG5oxrAgQnJlbWVydG9uLCBIaWRhbGdvLCBTcG9rYW5lLCBWYW5jb3V2ZXIs4oCmIGPDsyB04bu3IGzhu4cga2jDoWNoIGjDoG5nIOG7nyBt4bupYyB0cnVuZyBiw6xuaCB04burICoqMyUgxJHhur9uIDYlKiosIMSRw7NuZyB2YWkgdHLDsiBi4buVIHRy4bujIHF1YW4gdHLhu41uZy4NCg0KLSAqKk5ow7NtIGPDsyB04bu3IGzhu4cgdGjhuqVwIChkxrDhu5tpIDIlKSoqOiAgDQoNCiAgQ8OhYyB0aMOgbmggcGjhu5EgbmjGsCBHdWFkYWxhamFyYSwgV2FsbGEgV2FsbGEsIFZpY3RvcmlhLCBTYW4gRnJhbmNpc2NvLCBCZWxsaW5naGFtLOKApiBjw7Mgc+G7kSBsxrDhu6NuZyBraMOhY2ggaMOgbmcgdGjhuqVwIGjGoW4sIGPDsyB0aOG7gyAqKmtow7RuZyBwaOG6o2kgbMOgIHRo4buLIHRyxrDhu51uZyBjaMOtbmgqKiwgbmjGsG5nICoqY8OzIHRo4buDIGtoYWkgdGjDoWMgdGjDqm0gbuG6v3UgbXXhu5FuIG3hu58gcuG7mW5nKiouDQoNCioqSMOgbSDDvSB0cmnhu4NuIGtoYWk6KioNCg0KLSAqKsavdSB0acOqbiBuZ3Xhu5NuIGzhu7FjOioqIFThuq1wIHRydW5nIG5ndeG7k24gbOG7sWMgdsOgbyAqKnRvcCA14oCTNiB0aMOgbmggcGjhu5EgxJHhuqd1IGLhuqNuZyoqIMSR4buDIHThu5FpIMawdSBoaeG7h3UgcXXhuqMgdGnhur9wIGPhuq1uIHbDoCBjaMSDbSBzw7NjIGtow6FjaCBow6BuZy4NCg0KLSAqKkNoaeG6v24gZOG7i2NoIMSR4buLYSBwaMawxqFuZyBow7NhIChsb2NhbGl6YXRpb24pOioqIFbhu5tpIG3hu5dpIGPhu6VtIHRow6BuaCBwaOG7kSBjw7MgdOG7tyBs4buHIGNhbywgbsOqbiBjw6JuIG5o4bqvYyAqKnTDuXkgY2jhu4luaCB0aMO0bmcgxJFp4buHcCBxdeG6o25nIGLDoSwgY2jGsMahbmcgdHLDrG5oIGtodXnhur9uIG3Do2kgcGjDuSBo4bujcCB2w7luZyBtaeG7gW4qKi4NCg0KLSAqKsSQ4buLbmggaMaw4bubbmcgbeG7nyBy4buZbmc6KiogTmjhu69uZyB0aMOgbmggcGjhu5EgY8OzIHThu7cgbOG7hyB0cnVuZyBiw6xuaCBjw7MgdGjhu4MgbMOgICoqdGjhu4sgdHLGsOG7nW5nIHRp4buBbSBuxINuZyoqIMSR4buDIG3hu58gcuG7mW5nIHRyb25nIGdpYWkgxJFv4bqhbiB0aeG6v3AgdGhlby4NCg0KIyMjIyAqKjMuNC42LiBTdGF0ZW9yUHJvdmluY2UgKEJhbmcgaG/hurdjIHThu4luaCkqKg0KDQpgYGB7cn0NCiMgTMOgbSBz4bqhY2ggbmjhurkgKGLhu48ga2hv4bqjbmcgdHLhuq9uZyB0aOG7q2EpIHLhu5NpIMOpcCBmYWN0b3INCmRhdGEkU3RhdGVvclByb3ZpbmNlIDwtIHRyaW13cyhkYXRhJFN0YXRlb3JQcm92aW5jZSkNCmRhdGEkU3RhdGVvclByb3ZpbmNlIDwtIGFzLmZhY3RvcihkYXRhJFN0YXRlb3JQcm92aW5jZSkNCg0KIyBU4bqnbiBzdeG6pXQgJiB04bu3IGzhu4cNCnN0YXRlX3RhYiAgPC0gdGFibGUoZGF0YSRTdGF0ZW9yUHJvdmluY2UpDQpzdGF0ZV9wcm9wIDwtIHByb3AudGFibGUoc3RhdGVfdGFiKQ0KDQojIEvhur90IGjhu6NwIHRow6BuaCBi4bqjbmcNCnN0YXRlX2RmIDwtIGRhdGEuZnJhbWUoDQogIEJhbmdfVGluaCA9IG5hbWVzKHN0YXRlX3RhYiksDQogIFNvX2x1b25nICA9IGFzLnZlY3RvcihzdGF0ZV90YWIpLA0KICBUeV9sZSAgICAgPSByb3VuZCgxMDAgKiBhcy52ZWN0b3Ioc3RhdGVfcHJvcCksIDIpLA0KICByb3cubmFtZXMgPSBOVUxMDQopDQoNCiMgSGnhu4NuIHRo4buLDQprYWJsZShzdGF0ZV9kZiwNCiAgICAgIGNvbC5uYW1lcyA9IGMoIkJhbmcvVOG7iW5oIiwgIlPhu5EgbMaw4bujbmciLCAiVOG7tyBs4buHICglKSIpKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHN0YXRlX2RmLCBhZXMoeCA9IHJlb3JkZXIoQmFuZ19UaW5oLCBTb19sdW9uZyksIHkgPSBTb19sdW9uZykpICsNCiAgZ2VvbV9jb2woZmlsbCA9ICIjRURDOTQ4IikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKFR5X2xlLCAiJSIpKSwNCiAgICAgICAgICAgIGhqdXN0ID0gLTAuMSwgc2l6ZSA9IDMuNSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBsYWJzKHRpdGxlID0gIlBow6JuIGLhu5Ega2jDoWNoIGjDoG5nIHRoZW8gYmFuZy904buJbmgiLA0KICAgICAgIHggPSAiQmFuZy9U4buJbmgiLA0KICAgICAgIHkgPSAiU+G7kSBsxrDhu6NuZyIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKQ0KICApDQpgYGANCg0KDQoqKk5o4bqtbiB4w6l0IHThu5VuZyBxdWFuOioqDQoNCi0gKipU4bqtcCB0cnVuZyBt4bqhbmggdOG6oWkgYmFuZyBXQSAoV2FzaGluZ3Rvbik6KiogDQoNCiAgVuG7m2kgKiozMi40OCUqKiB04buVbmcgc+G7kSBraMOhY2ggaMOgbmcgKHTGsMahbmcgxJHGsMahbmcgKio0LDU2NyBraMOhY2gqKiksIGJhbmcgV0EgbMOgICoqdGjhu4sgdHLGsOG7nW5nIHRy4buNbmcgxJFp4buDbSoqLCBj4bqnbiDEkcaw4bujYyAqKsawdSB0acOqbiBjYW8gbmjhuqV0KiogdHJvbmcgY8OhYyBjaGnhur9uIGzGsOG7o2Mga2luaCBkb2FuaCB2w6AgdGnhur9wIHRo4buLLg0KDQotICoqTmjDs20gcXVhbiB0cuG7jW5nIHRo4bupIGhhaToqKiAgDQoNCiAgLSAqKkNBIChDYWxpZm9ybmlhKSoqIGNoaeG6v20gKioxOS40NCUqKg0KICANCiAgLSAqKk9SIChPcmVnb24pKiogY2hp4bq/bSAqKjE2LjA5JSoqDQoNCiAg4oaSIFThu5VuZyBj4buZbmcgYmEgYmFuZyAqKldBLCBDQSwgT1IqKiDEkcOjIGNoaeG6v20gxJHhur9uICoqZ+G6p24gNzAlKiogdOG7lW5nIHPhu5Ega2jDoWNoIGjDoG5nLiAgDQogIA0KICDEkMOieSBsw6AgKip2w7luZyB0aOG7iyB0csaw4budbmcgY+G7kXQgbMO1aSoqLCBuw6puIMSR4bqndSB0xrAgbeG6oW5oIHbhu4EgbmjDom4gbOG7sWMsIHF14bqjbmcgYsOhLCBk4buLY2ggduG7pSBo4bqtdSBtw6NpIHThuqFpIGtodSB24buxYyBuw6B5Lg0KDQotICoqQmFuZyBjw7MgbeG7qWMgxJHhu5kga2jDoWNoIGjDoG5nIHRydW5nIGLDrG5oOioqICANCiAgLSBaYWNhdGVjYXMgKCoqOS4yMyUqKikNCiAgDQogIC0gREYgKCoqNS44MCUqKikNCiAgDQogIC0gQkMgKCoqNS43NSUqKikNCg0KICDihpIgxJDDonkgbMOgIG5o4buvbmcga2h1IHbhu7FjICoqcGjhu6UgdHLhu6MgxJHDoW5nIGNow7ogw70qKiwgY8OzIHRo4buDIGPDom4gbmjhuq9jIHRyaeG7g24ga2hhaSBjw6FjIGNoxrDGoW5nIHRyw6xuaCBtYXJrZXRpbmcga2h1IHbhu7FjIG5o4buPIChyZWdpb25hbCBtYXJrZXRpbmcpLg0KDQotICoqQmFuZyBjw7MgdOG7tyBs4buHIHRo4bqlcCAoPDUlKSoqOiAgDQoNCiAgR3VlcnJlcm8sIEphbGlzY28sIFZlcmFjcnV6LCBZdWNhdGFuIOKAlCB0dXkgY8OzIHPhu5EgbMaw4bujbmcga2jDoWNoIMOtdCBoxqFuLCB24bqrbiBjw7MgdGjhu4MgY8OibiBuaOG6r2MgKip0xINuZyBuaOG6rW4gZGnhu4duIHRoxrDGoW5nIGhp4buHdSoqLCDEkeG6t2MgYmnhu4d0IG7hur91IG114buRbiBt4bufIHLhu5luZyB0aOG7iyB0csaw4budbmcgduG7gSBwaMOtYSBNZXhpY28uDQoNCioqSMOgbSDDvSB0cmnhu4NuIGtoYWk6KioNCg0KLSAqKlThuq1wIHRydW5nIG5ndeG7k24gbOG7sWMgdsOgbyB0b3AgMyBiYW5nIGNow61uaCAoV0EsIENBLCBPUikqKiDEkeG7gyB04buRaSDGsHUgaGnhu4d1IHF14bqjIGtpbmggZG9hbmguDQoNCi0gKipQaMOhdCB0cmnhu4NuIGNoaeG6v24gbMaw4bujYyB0aeG6v3AgdGjhu4sgdsO5bmcgbWnhu4FuIGPhu6UgdGjhu4MqKiwgdMO5eSB0aGVvIHF1eSBtw7Qga2jDoWNoIGjDoG5nIOG7nyB04burbmcgYmFuZy4NCg0KLSAqKktow6FtIHBow6EgdGjDqm0gdGnhu4FtIG7Eg25nIHThu6sgY8OhYyBiYW5nIGPDsyBt4bupYyB0cnVuZyBiw6xuaCAoWmFjYXRlY2FzLCBERiwgQkMpKiogbuG6v3UgbeG7nyBy4buZbmcgcXV5IG3DtC4NCg0KLSAqKlRow60gxJFp4buDbSBz4bqjbiBwaOG6qW0vZOG7i2NoIHbhu6UgbeG7m2kg4bufIHRo4buLIHRyxrDhu51uZyBuaOG7jyBuaMawIFl1Y2F0YW4gaG/hurdjIFZlcmFjcnV6KiogxJHhu4Mga2nhu4NtIHRyYSBwaOG6o24g4bupbmcgdGjhu4sgdHLGsOG7nW5nIHRyxrDhu5tjIGtoaSBt4bufIHLhu5luZy4NCg0KIyMjIyAqKjMuNC43LiBDb3VudHJ5IChRdeG7kWMgZ2lhKSoqDQoNCmBgYHtyfQ0KIyBMw6BtIHPhuqFjaCBu4bq/dSBj4bqnbiAobG/huqFpIGtob+G6o25nIHRy4bqvbmcgdGjhu6thKQ0KZGF0YSRDb3VudHJ5IDwtIHRyaW13cyhkYXRhJENvdW50cnkpDQpkYXRhJENvdW50cnkgPC0gYXMuZmFjdG9yKGRhdGEkQ291bnRyeSkNCg0KIyBUw61uaCB04bqnbiBzdeG6pXQgdsOgIHThu7cgbOG7hyBwaOG6p24gdHLEg20NCmNvdW50cnlfdGFibGUgPC0gdGFibGUoZGF0YSRDb3VudHJ5KQ0KY291bnRyeV9wcm9wICA8LSBwcm9wLnRhYmxlKGNvdW50cnlfdGFibGUpDQoNCiMgS+G6v3QgaOG7o3AgdGjDoG5oIGLhuqNuZw0KY291bnRyeV9kZiA8LSBkYXRhLmZyYW1lKA0KICBRdW9jX2dpYSA9IG5hbWVzKGNvdW50cnlfdGFibGUpLA0KICBTb19sdW9uZyA9IGFzLnZlY3Rvcihjb3VudHJ5X3RhYmxlKSwNCiAgVHlfbGUgICAgPSByb3VuZCgxMDAgKiBhcy52ZWN0b3IoY291bnRyeV9wcm9wKSwgMiksDQogIHJvdy5uYW1lcyA9IE5VTEwNCikNCg0KIyBIaeG7g24gdGjhu4sgYuG6o25nIMSR4bq5cA0Ka2FibGUoY291bnRyeV9kZiwNCiAgICAgIGNvbC5uYW1lcyA9IGMoIlF14buRYyBnaWEiLCAiU+G7kSBsxrDhu6NuZyIsICJU4bu3IGzhu4cgKCUpIikpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoY291bnRyeV9kZiwgYWVzKHggPSAiIiwgeSA9IFNvX2x1b25nLCBmaWxsID0gUXVvY19naWEpKSArDQogIGdlb21fY29sKHdpZHRoID0gMSwgY29sb3IgPSAid2hpdGUiKSArICAgICAgICMgbMOhdCBiw6FuaA0KICBjb29yZF9wb2xhcih0aGV0YSA9ICJ5IikgKyAgICAgICAgICAgICAgICAgICAjIGNodXnhu4NuIHRow6BuaCBwaWUNCiAgZ2VvbV90ZXh0KA0KICAgIGFlcyhsYWJlbCA9IHBhc3RlMChRdW9jX2dpYSwgIjogIiwgVHlfbGUsICIlIikpLA0KICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLA0KICAgIHNpemUgPSAzDQogICkgKw0KICBsYWJzKHRpdGxlID0gIlThu7cgbOG7hyBraMOhY2ggaMOgbmcgdGhlbyBxdeG7kWMgZ2lhIiwNCiAgICAgICB4ID0gTlVMTCwgeSA9IE5VTEwsIGZpbGwgPSAiUXXhu5FjIGdpYSIpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gNCkpKQ0KYGBgDQoNCg0KKipOaOG6rW4geMOpdCB04buVbmcgcXVhbjoqKg0KDQotICoqTeG7uSAoVVNBKSoqIGNoaeG6v20gKio2OC4wMSUqKiB04buVbmcgc+G7kSBraMOhY2ggaMOgbmcg4oCTIMSRw6J5IGzDoCAqKnRo4buLIHRyxrDhu51uZyBjaMOtbmggeeG6v3UgdsOgIMOhcCDEkeG6o28gdHV54buHdCDEkeG7kWkqKi4gDQoNCiAg4oaSIEPDoWMgY2hp4bq/biBsxrDhu6NjIGtpbmggZG9hbmgsIG1hcmtldGluZywgc+G6o24gcGjhuqltIGPhuqduICoqxrB1IHRpw6puIHThu5FpIMSRYSBjaG8ga2jDoWNoIGjDoG5nIEhvYSBL4buzKiouDQoNCi0gKipNZXhpY28qKiBjaGnhur9tICoqMjYuMjMlKiog4oCTIGzDoCAqKnRo4buLIHRyxrDhu51uZyBwaOG7pSBuaMawbmcgcuG6pXQgxJHDoW5nIGNow7ogw70qKiB24bubaSBn4bqnbiAqKjEvNCB04buVbmcga2jDoWNoIGjDoG5nKiouIA0KDQogIOKGkiBDw7MgdGjhu4MgY8OibiBuaOG6r2MgKipi4bqjbiDEkeG7i2EgaG/DoSB0aMO0bmcgxJFp4buHcCoqLCDGsHUgxJHDo2kgaG/hurdjIHPhuqNuIHBo4bqpbSBkw6BuaCByacOqbmcgY2hvIGtodSB24buxYyBuw6B5Lg0KDQotICoqQ2FuYWRhKiogY2jhu4kgY2hp4bq/bSAqKjUuNzUlKiog4oCTIHPhu5EgbMaw4bujbmcgdMawxqFuZyDEkeG7kWkgbmjhu48uICANCg0KICDihpIgS2jDtG5nIHBo4bqjaSB0aOG7iyB0csaw4budbmcgdHLhu41uZyB0w6JtIGhp4buHbiB04bqhaSwgbmjGsG5nIHbhuqtuIGPDsyB0aOG7gyDEkcaw4bujYyBkdXkgdHLDrCBuaMawIG3hu5l0ICoqa2h1IHbhu7FjIHbhu4cgdGluaCBo4buXIHRy4bujKiogaG/hurdjIMSR4buDICoqdGjhu60gbmdoaeG7h20gc+G6o24gcGjhuqltIG3hu5tpKiouDQoNCioqSMOgbSDDvSB0cmnhu4NuIGtoYWk6KioNCg0KLSAqKlThuq1wIHRydW5nIHBow6F0IHRyaeG7g24gdGjhu4sgdHLGsOG7nW5nIE3hu7kqKjogxJHhuqd1IHTGsCB24buBIGThu4tjaCB24bulIGtow6FjaCBow6BuZywgY2hp4bq/biBk4buLY2ggcXXhuqNuZyBjw6FvLCBt4bqhbmcgbMaw4bubaSBwaMOibiBwaOG7kWkgdOG6oWkgSG9hIEvhu7MuDQoNCi0gKipQaMOibiBraMO6YyB2w6AgYuG6o24gxJHhu4thIGjDs2EgY2hp4bq/biBk4buLY2ggdOG6oWkgTWV4aWNvKio6IGTDuW5nIHRp4bq/bmcgVMOieSBCYW4gTmhhLCDEkWnhu4F1IGNo4buJbmggY2jDrW5oIHPDoWNoIGdpw6EsIHbhuq1uIGNodXnhu4NuIHBow7kgaOG7o3AgduG7m2kga2h1IHbhu7FjLg0KDQotICoqR2nhu68gc+G7sSBoaeG7h24gZGnhu4duIHThuqFpIENhbmFkYSoqLCBuaMawbmcgY2jGsGEgY+G6p24gxJHhuqd1IHTGsCBt4bqhbmgg4oCUIGPDsyB0aOG7gyBraGFpIHRow6FjIGThuqduIGtoaSBjw6FjIHRo4buLIHRyxrDhu51uZyBs4bubbiDEkcOjIOG7lW4gxJHhu4tuaC4NCg0KIyMjIyAqKjMuNC44LiBQcm9kdWN0RmFtaWx5IChOaMOzbSBz4bqjbiBwaOG6qW0gbOG7m24pKioNCg0KYGBge3J9DQojIEzDoG0gc+G6oWNoIGJp4bq/biBQcm9kdWN0RmFtaWx5IChu4bq/dSBj4bqnbikNCmRhdGEkUHJvZHVjdEZhbWlseSA8LSB0cmltd3MoZGF0YSRQcm9kdWN0RmFtaWx5KQ0KZGF0YSRQcm9kdWN0RmFtaWx5IDwtIGFzLmZhY3RvcihkYXRhJFByb2R1Y3RGYW1pbHkpDQoNCiMgVMOtbmggdOG6p24gc3XhuqV0IHbDoCB04bu3IGzhu4cgcGjhuqduIHRyxINtDQpwZl90YWJsZSA8LSB0YWJsZShkYXRhJFByb2R1Y3RGYW1pbHkpDQpwZl9wcm9wICA8LSBwcm9wLnRhYmxlKHBmX3RhYmxlKQ0KDQojIEvhur90IGjhu6NwIHRow6BuaCBi4bqjbmcNCnBmX2RmIDwtIGRhdGEuZnJhbWUoDQogIFByb2R1Y3RGYW1pbHkgPSBuYW1lcyhwZl90YWJsZSksDQogIFNvX2x1b25nICAgICA9IGFzLnZlY3RvcihwZl90YWJsZSksDQogIFR5X2xlICAgICAgICA9IHJvdW5kKDEwMCAqIGFzLnZlY3RvcihwZl9wcm9wKSwgMiksDQogIHJvdy5uYW1lcyAgICA9IE5VTEwNCikNCg0KIyBIaeG7g24gdGjhu4sgYuG6o25nIMSR4bq5cA0Ka2FibGUocGZfZGYsDQogICAgICBjb2wubmFtZXMgPSBjKCJOaMOzbSBz4bqjbiBwaOG6qW0iLCAiU+G7kSBsxrDhu6NuZyIsICJU4bu3IGzhu4cgKCUpIikpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QocGZfZGYsIGFlcyh4ID0gIiIsIHkgPSBTb19sdW9uZywgZmlsbCA9IFByb2R1Y3RGYW1pbHkpKSArDQogIGdlb21fY29sKHdpZHRoID0gMSwgY29sb3IgPSAid2hpdGUiKSArDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoVHlfbGUsICIlIikpLA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksDQogICAgICAgICAgICBzaXplID0gNCkgKw0KICBsYWJzKHRpdGxlID0gIlThu7cgbOG7hyB0aGVvIG5ow7NtIHPhuqNuIHBo4bqpbSIsDQogICAgICAgeCA9IE5VTEwsIHkgPSBOVUxMLCBmaWxsID0gIk5ow7NtIHPhuqNuIHBo4bqpbSIpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplID0gNSkpKQ0KYGBgDQoNCg0KKipOaOG6rW4geMOpdDoqKg0KDQotICoqTmjDs20gRm9vZCAodGjhu7FjIHBo4bqpbSkqKiBjaGnhur9tICoqdHLDqm4gNzIlKiogdOG7lW5nIGdpYW8gZOG7i2NoLCBsw6AgKipt4bqjbmcgc+G6o24gcGjhuqltIGPhu5F0IGzDtWkgdsOgIGNo4bunIMSR4bqhbyoqLg0KDQogIOKGkiBDw6FjIHF1eeG6v3QgxJHhu4tuaCB24buBIGRhbmggbeG7pWMsIGNo4bqldCBsxrDhu6NuZywgZ2nDoSwga2h1eeG6v24gbcOjaeKApiBuw6puICoqxrB1IHRpw6puIG5ow7NtIG7DoHkqKi4NCg0KLSAqKk5vbi1Db25zdW1hYmxlKiogKHBoaSB0acOqdSBkw7luZywgbmjGsCDEkeG7kyBnaWEgZOG7pW5nLCDEkWnhu4duIHThu63igKYpIGNoaeG6v20gZ+G6p24gKioxOSUqKiDigJMgbMOgICoqbeG6o25nIHBo4bulIG5oxrBuZyB0aeG7gW0gbsSDbmcqKi4gIA0KDQogIOKGkiBDw7MgdGjhu4Mga2hhaSB0aMOhYyB0aMOqbSB24buBICoqdXBzZWxsKiogaG/hurdjICoqY3Jvc3Mtc2VsbCoqIHbhu5tpIG5ow7NtIGtow6FjaCBow6BuZyBtdWEgRm9vZC4NCg0KLSAqKkRyaW5rICh0aOG7qWMgdeG7kW5nKSoqIGNo4buJIGNoaeG6v20gZ+G6p24gKio5JSoqIOKAkyBsw6AgKipt4bqjbmcgbmjhu48qKiwgbsOqbiBjw6JuIG5o4bqvYyB04bqtcCB0cnVuZyB2w6BvIGPDoWMgKipz4bqjbiBwaOG6qW0gY8OzIGJpw6puIGzhu6NpIG5odeG6rW4gY2FvKiogaG/hurdjICoqbGnDqm4ga+G6v3QgY29tYm8gduG7m2kgRm9vZCoqLg0KDQoqKkjDoG0gw70gdHJp4buDbiBraGFpOioqDQoNCi0gxJDhuqd1IHTGsCB04buRaSDGsHUgKipkw7JuZyBz4bqjbiBwaOG6qW0gRm9vZCoqOiBuZ2hpw6puIGPhu6l1IGjDoG5oIHZpIG11YSwgeHUgaMaw4bubbmcg4bqpbSB0aOG7sWMsIGPhuqNpIHRp4bq/biBiYW8gYsOsLCB24buLLCBnacOhLg0KDQotIEtoYWkgdGjDoWMgKipjb21ibyBGb29kICsgRHJpbmsqKiBob+G6t2MgKipGb29kICsgTm9uLUNvbnN1bWFibGUqKiDEkeG7gyB0xINuZyBnacOhIHRy4buLIMSRxqFuIGjDoG5nLg0KDQotICoqxJDhu4tuaCB24buLIHLDtSBOb24tQ29uc3VtYWJsZSoqOiBkw7luZyBuaMawIHPhuqNuIHBo4bqpbSBxdcOgIHThurduZywga2jDoWNoIGjDoG5nIHRow6JuIHRoaeG6v3QgaG/hurdjIG5o4bqvbSB2w6BvIG5ow7NtIGPDsyBt4bupYyBjaGkgdGnDqnUgY2FvLg0KDQojIyMjICoqMy40LjkuIFByb2R1Y3REZXBhcnRtZW50IChQaMOybmcgYmFuIHPhuqNuIHBo4bqpbSkqKg0KDQpgYGB7cn0NCiMgTMOgbSBz4bqhY2ggYmnhur9uIFByb2R1Y3REZXBhcnRtZW50IG7hur91IGPhuqduDQpkYXRhJFByb2R1Y3REZXBhcnRtZW50IDwtIHRyaW13cyhkYXRhJFByb2R1Y3REZXBhcnRtZW50KQ0KZGF0YSRQcm9kdWN0RGVwYXJ0bWVudCA8LSBhcy5mYWN0b3IoZGF0YSRQcm9kdWN0RGVwYXJ0bWVudCkNCg0KIyBUw61uaCB04bqnbiBzdeG6pXQgdsOgIHThu7cgbOG7hyBwaOG6p24gdHLEg20NCnBkX3RhYmxlIDwtIHRhYmxlKGRhdGEkUHJvZHVjdERlcGFydG1lbnQpDQpwZF9wcm9wICA8LSBwcm9wLnRhYmxlKHBkX3RhYmxlKQ0KDQojIEvhur90IGjhu6NwIHRow6BuaCBi4bqjbmcNCnBkX2RmIDwtIGRhdGEuZnJhbWUoDQogIFByb2R1Y3REZXBhcnRtZW50ID0gbmFtZXMocGRfdGFibGUpLA0KICBTb19sdW9uZyAgICAgICAgICA9IGFzLnZlY3RvcihwZF90YWJsZSksDQogIFR5X2xlICAgICAgICAgICAgID0gcm91bmQoMTAwICogYXMudmVjdG9yKHBkX3Byb3ApLCAyKSwNCiAgcm93Lm5hbWVzICAgICAgICAgPSBOVUxMDQopDQoNCiMgSGnhu4NuIHRo4buLIGLhuqNuZyDEkeG6uXANCmthYmxlKHBkX2RmLA0KICAgICAgY29sLm5hbWVzID0gYygiUGjDsm5nIGJhbiBz4bqjbiBwaOG6qW0iLCAiU+G7kSBsxrDhu6NuZyIsICJU4bu3IGzhu4cgKCUpIikpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QocGRfZGYsIGFlcyh4ID0gcmVvcmRlcihQcm9kdWN0RGVwYXJ0bWVudCwgU29fbHVvbmcpLCB5ID0gU29fbHVvbmcpKSArDQogIGdlb21fY29sKGZpbGwgPSAiIzc2QjdCMiIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChUeV9sZSwgIiUiKSksDQogICAgICAgICAgICB2anVzdCA9IC0wLjUsIHNpemUgPSA0KSArDQogIGxhYnModGl0bGUgPSAiUGjDom4gYuG7kSBz4buRIGzGsOG7o25nIHRoZW8gcGjDsm5nIGJhbiBz4bqjbiBwaOG6qW0iLA0KICAgICAgIHggPSAiUGjDsm5nIGJhbiBz4bqjbiBwaOG6qW0iLA0KICAgICAgIHkgPSAiU+G7kSBsxrDhu6NuZyIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKw0KICB0aGVtZSgNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpDQogICkNCmBgYA0KDQoNCioqTmjhuq1uIHjDqXQ6KioNCg0KLSAqKlByb2R1Y2UgKFJhdSBxdeG6oyB0xrDGoWkpKiogbMOgIHBow7JuZyBiYW4gKipjaGnhur9tIHThu7cgdHLhu41uZyBs4bubbiBuaOG6pXQgKDE0LjE4JSkqKiwgdGjhu4MgaGnhu4duICoqeHUgaMaw4bubbmcgdGnDqnUgZMO5bmcgdGjhu7FjIHBo4bqpbSB0xrDGoWkgc+G7kW5nIGNhbyoqLg0KDQotICoqU25hY2sgRm9vZHMgdsOgIEZyb3plbiBGb29kcyoqIGNoaeG6v20gdOG7tyB0cuG7jW5nIGzhu5tuIHRo4bupIDIgdsOgIDMg4oaSIGNobyB0aOG6pXkgbmh1IGPhuqd1IGNhbyB24bubaSAqKsSR4buTIMSDbiBuaGFuaCwgdGnhu4duIGzhu6NpKiosIHRow61jaCBo4bujcCBjaG8ga2jDoWNoIGLhuq1uIHLhu5luIGhv4bq3YyBnaWEgxJHDrG5oLg0KDQotICoqSG91c2Vob2xkICjEkOG7kyBnaWEgZOG7pW5nKSoqIGPFqW5nIGNoaeG6v20gaMahbiAqKjEwJSoqLCBsw6Agc+G6o24gcGjhuqltIHRoaeG6v3QgeeG6v3UgdHJvbmcgxJHhu51pIHPhu5FuZyDihpIgY8OzIHRo4buDIGvhur90IGjhu6NwIGLDoW4gY2jDqW8uDQoNCi0gQ8OhYyBuaMOzbSBuaMawICoqTWVhdCoqLCAqKlNlYWZvb2QqKiwgKipQZXJpb2RpY2FscyoqLCAqKkNoZWNrb3V0KiosICoqQ2Fyb3VzZWwqKi4uLiBjaGnhur9tIHThu7cgdHLhu41uZyBy4bqldCBuaOG7jyDihpIga2jDtG5nIHBo4bqjaSB0cuG7jW5nIHTDom0gaGnhu4duIHThuqFpLg0KDQoqKkjDoG0gw70gdHJp4buDbiBraGFpOioqDQoNCi0gKipU4buRaSDGsHUgZGFuaCBt4bulYyB2w6Aga2h1eeG6v24gbcOjaSoqIGNobyBuaMOzbTogUHJvZHVjZSwgU25hY2sgRm9vZHMsIEZyb3plbiBGb29kcyDihpIgxJHDonkgbMOgIGPDoWMgcGjDsm5nIGJhbiB04bqhbyBkb2FuaCBz4buRIGNo4bunIGzhu7FjLg0KDQotIE5ow7NtICoqSG91c2Vob2xkKiogY8OzIHRo4buDIHTDrWNoIGjhu6NwIHRyb25nIGPDoWMgY2hp4bq/biBsxrDhu6NjIHVwc2VsbCBob+G6t2MgY29tYm8gY2hvIGtow6FjaCBow6BuZyB0aMaw4budbmcgeHV5w6puLg0KDQotIEPDoWMgcGjDsm5nIGJhbiBuaOG7jyBuw6puOg0KDQogIC0gxJDGsOG7o2MgeGVtIHjDqXQgxJFp4buBdSBjaOG7iW5oIHbhu4sgdHLDrS9xdXkgbcO0IHRyxrBuZyBiw6B5Lg0KICANCiAgLSBDaOG7iSBnaeG7ryBs4bqhaSBuaOG7r25nIHPhuqNuIHBo4bqpbSBjw7MgYmnDqm4gbOG7o2kgbmh14bqtbiBjYW8gaG/hurdjIGdpw6EgdHLhu4sgdGjGsMahbmcgaGnhu4d1IHLDtSBuw6l0Lg0KDQojIyMjICoqMy40LjEwLiBQcm9kdWN0Q2F0ZWdvcnkgKERhbmggbeG7pWMgc+G6o24gcGjhuqltIGPhu6UgdGjhu4MpKioNCg0KYGBge3J9DQojIEzDoG0gc+G6oWNoIGJp4bq/biBQcm9kdWN0Q2F0ZWdvcnkgbuG6v3UgY+G6p24NCmRhdGEkUHJvZHVjdENhdGVnb3J5IDwtIHRyaW13cyhkYXRhJFByb2R1Y3RDYXRlZ29yeSkNCmRhdGEkUHJvZHVjdENhdGVnb3J5IDwtIGFzLmZhY3RvcihkYXRhJFByb2R1Y3RDYXRlZ29yeSkNCg0KIyBUw61uaCB04bqnbiBzdeG6pXQgdsOgIHThu7cgbOG7hyBwaOG6p24gdHLEg20NCnBjX3RhYmxlIDwtIHRhYmxlKGRhdGEkUHJvZHVjdENhdGVnb3J5KQ0KcGNfcHJvcCAgPC0gcHJvcC50YWJsZShwY190YWJsZSkNCg0KIyBL4bq/dCBo4bujcCB0aMOgbmggYuG6o25nDQpwY19kZiA8LSBkYXRhLmZyYW1lKA0KICBQcm9kdWN0Q2F0ZWdvcnkgPSBuYW1lcyhwY190YWJsZSksDQogIFNvX2x1b25nICAgICAgID0gYXMudmVjdG9yKHBjX3RhYmxlKSwNCiAgVHlfbGUgICAgICAgICAgPSByb3VuZCgxMDAgKiBhcy52ZWN0b3IocGNfcHJvcCksIDIpLA0KICByb3cubmFtZXMgICAgICA9IE5VTEwNCikNCg0KIyBIaeG7g24gdGjhu4sgYuG6o25nIMSR4bq5cA0Ka2FibGUocGNfZGYsDQogICAgICBjb2wubmFtZXMgPSBjKCJEYW5oIG3hu6VjIHPhuqNuIHBo4bqpbSIsICJT4buRIGzGsOG7o25nIiwgIlThu7cgbOG7hyAoJSkiKSkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdChwY19kZiwgYWVzKHggPSByZW9yZGVyKFByb2R1Y3RDYXRlZ29yeSwgU29fbHVvbmcpLCB5ID0gU29fbHVvbmcpKSArDQogIGdlb21fY29sKGZpbGwgPSAiI0IwN0FBMSIpICsNCiAgbGFicyh0aXRsZSA9ICJQaMOibiBi4buRIHPhu5EgbMaw4bujbmcgdGhlbyBkYW5oIG3hu6VjIHPhuqNuIHBo4bqpbSIsDQogICAgICAgeCA9ICJEYW5oIG3hu6VjIHPhuqNuIHBo4bqpbSIsDQogICAgICAgeSA9ICJT4buRIGzGsOG7o25nIikgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEzKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkNCiAgKQ0KYGBgDQoNCg0KKipOaOG6rW4geMOpdDoqKg0KDQotICoqVmVnZXRhYmxlcyoqIGzDoCBkYW5oIG3hu6VjIGNoaeG6v20gdOG7tyBs4buHIGNhbyBuaOG6pXQgKDEyLjI5JSkg4oaSIGNobyB0aOG6pXkgKirGsHUgdGnDqm4gaMOgbmcgxJHhuqd1IHbhu5tpIG5ow7NtIHRo4buxYyBwaOG6qW0gdMawxqFpIHPhu5FuZyoqLg0KDQotICoqU25hY2sgRm9vZHMqKiB0aeG6v3AgdOG7pWMgbMOgIGRhbmggbeG7pWMgY2jhu6cgbOG7sWMgKDExLjM4JSkg4oaSIHh1IGjGsOG7m25nIHRpw6p1IGTDuW5nIMSR4buTIMSDbiBuaGFuaCwgdGnhu4duIGThu6VuZyBy4bqldCByw7UgcsOgbmcuDQoNCi0gKipEYWlyeSwgRnJ1aXQgdsOgIE1lYXQqKiDEkeG7gXUgbuG6sW0gdHJvbmcgbmjDs20gdG9wIDUg4oaSIMSRw6J5IGzDoCBuaOG7r25nICoqc+G6o24gcGjhuqltIHRoaeG6v3QgeeG6v3UsIHRpw6p1IGTDuW5nIGjDoG5nIG5nw6B5KiouDQoNCi0gQ8OhYyBkYW5oIG3hu6VjIG5oxrAgKipDYW5uZWQgU2VhZm9vZCAoQ2FubmVkIFNhcmRpbmVzLCBUdW5hLCBTaHJpbXAuLi4pKiogY8OzIHThu7cgdHLhu41uZyB0aOG6pXAgKH4wLjPigJMwLjYlKSDihpIgw610IMSRxrDhu6NjIHF1YW4gdMOibSwgY8OzIHRo4buDIGzDoCBkbyBraOG6qXUgduG7iywgdGjDs2kgcXVlbiB0acOqdSBkw7luZy4NCg0KKipDw6FjIGRhbmggbeG7pWMgY8OzIHThu7cgdHLhu41uZyBy4bqldCB0aOG6pXAgKDwxJSk6KioNCg0KLSAqKkNhbmRsZXMsIENhbm5lZCBDbGFtcywgTWlzY2VsbGFuZW91cywgRWxlY3RyaWNhbC4uLioqIGPDsyBsxrDhu6NuZyBtdWEgY+G7sWMga+G7syB0aOG6pXAg4oaSIGtow7RuZyBwaOG6o2kgxrB1IHRpw6puIGNow61uaCB0cm9uZyBjaGnhur9uIGzGsOG7o2Mga2luaCBkb2FuaC4NCg0KKipIw6BtIMO9IGNoaeG6v24gbMaw4bujYzoqKg0KDQotIFThuq1wIHRydW5nIG1hcmtldGluZyB2w6AgdHLGsG5nIGLDoHkgbuG7lWkgYuG6rXQgY2hvIGPDoWMgbmjDs206ICoqVmVnZXRhYmxlcywgU25hY2sgRm9vZHMsIERhaXJ5LCBGcnVpdCB2w6AgTWVhdCoqLg0KDQotICoqR+G7mXAgbmjDs20gc+G6o24gcGjhuqltIMOtdCBwaOG7lSBiaeG6v24qKiB2w6BvIGPDoWMgY29tYm8va2h1eeG6v24gbcOjaSBrw6htIOKGkiBnacO6cCB0xINuZyBkb2FuaCBz4buRIHbDoCBnaeG6o2kgcGjDs25nIHThu5NuIGtoby4NCg0KLSBYZW0geMOpdCAqKsSR4buLbmggduG7iyBs4bqhaSBob+G6t2MgdGhheSB0aOG6vyBkYW5oIG3hu6VjIGTGsOG7m2kgMC41JSoqIG7hur91IGtow7RuZyBtYW5nIGzhuqFpIGzhu6NpIG5odeG6rW4gdOG7kXQgaG/hurdjIGtow7RuZyBwaOG7pWMgduG7pSBt4bulYyB0acOqdSB0aMawxqFuZyBoaeG7h3UuDQoNCi0tLQ0KDQojIyMgKiozLjUgS+G6v3QgcXXhuqMgdGjhu5FuZyBrw6ogbcO0IHThuqMgY+G7p2EgY8OhYyBiaeG6v24gxJHhu4tuaCB0w61uaCoqDQoNCmBgYHtyfQ0KIyBEYW5oIHPDoWNoIGPDoWMgYmnhur9uIMSR4buLbmggdMOtbmgNCmNhdF92YXJzIDwtIGMoIkdlbmRlciIsICJNYXJpdGFsU3RhdHVzIiwgIkhvbWVvd25lciIsICJBbm51YWxJbmNvbWUiLA0KICAgICAgICAgICAgICAiQ2l0eSIsICJTdGF0ZW9yUHJvdmluY2UiLCAiQ291bnRyeSIsDQogICAgICAgICAgICAgICJQcm9kdWN0RmFtaWx5IiwgIlByb2R1Y3REZXBhcnRtZW50IiwgIlByb2R1Y3RDYXRlZ29yeSIpDQoNCiMgSMOgbSB44butIGzDvSB04burbmcgYmnhur9uDQpjYXRfc3VtbWFyeSA8LSBmdW5jdGlvbihkZiwgdmFyKSB7DQogIHYgPC0gdHJpbXdzKGRmW1t2YXJdXSkgICAgICAgICAjIGxv4bqhaSBi4buPIGtob+G6o25nIHRy4bqvbmcNCiAgdiA8LSBhcy5mYWN0b3IodikgICAgICAgICAgICAgICMgw6lwIGtp4buDdSBmYWN0b3IgbuG6v3UgY2jGsGENCiAgdGJsICA8LSB0YWJsZSh2LCB1c2VOQSA9ICJpZmFueSIpDQogIHByb3AgPC0gcHJvcC50YWJsZSh0YmwpDQoNCiAgZGF0YS5mcmFtZSgNCiAgICBCaWVuICAgICA9IHZhciwNCiAgICBNdWMgICAgICA9IG5hbWVzKHRibCksDQogICAgU29fbHVvbmcgPSBhcy52ZWN0b3IodGJsKSwNCiAgICBUeV9sZSAgICA9IHJvdW5kKDEwMCAqIGFzLnZlY3Rvcihwcm9wKSwgMiksDQogICAgcm93Lm5hbWVzID0gTlVMTCwNCiAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCiAgKQ0KfQ0KDQojIMOBcCBk4bulbmcgY2hvIHThuqV0IGPhuqMgYmnhur9uIHbDoCBu4buRaSB0aMOgbmggMSBi4bqjbmcgbOG7m24NCmJpZ190YmwgPC0gYmluZF9yb3dzKGxhcHBseShjYXRfdmFycywgZnVuY3Rpb24oeCkgY2F0X3N1bW1hcnkoZGF0YSwgeCkpKQ0KDQojIChUw7l5IGNo4buNbikgU+G6r3AgeOG6v3AgdGhlbyBiaeG6v24gcuG7k2kgZ2nhuqNtIGThuqduIHPhu5EgbMaw4bujbmcNCmJpZ190YmwgPC0gYmlnX3RibCAlPiUNCiAgYXJyYW5nZShCaWVuLCBkZXNjKFNvX2x1b25nKSkNCg0KIyBIaeG7g24gdGjhu4sgYuG6o25nIHRo4buRbmcga8OqDQprYWJsZShiaWdfdGJsLA0KICAgICAgY29sLm5hbWVzID0gYygiQmnhur9uIiwgIk3hu6ljIiwgIlPhu5EgbMaw4bujbmciLCAiVOG7tyBs4buHICglKSIpLA0KICAgICAgY2FwdGlvbiA9ICJC4bqjbmcgdGjhu5FuZyBrw6ogbcO0IHThuqMgY2hvIHThuqV0IGPhuqMgYmnhur9uIMSR4buLbmggdMOtbmgiKQ0KYGBgDQoNCg0KYGBge3J9DQojIFTDrW5oIHRo4buRbmcga8OqIG3DtCB04bqjIMSR4bqneSDEkeG7pyB0aGVvIHThu6tuZyBiaeG6v24gxJHhu4tuaCB0w61uaA0KZGVzY3JpcHRpdmVfc3RhdHNfZnVsbCA8LSBiaWdfdGJsICU+JQ0KICBncm91cF9ieShCaWVuKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE1lYW4gICAgPSBtZWFuKFNvX2x1b25nLCBuYS5ybSA9IFRSVUUpLA0KICAgIFN0ZERldiAgPSBzZChTb19sdW9uZywgbmEucm0gPSBUUlVFKSwNCiAgICBNaW4gICAgID0gbWluKFNvX2x1b25nLCBuYS5ybSA9IFRSVUUpLA0KICAgIFExICAgICAgPSBxdWFudGlsZShTb19sdW9uZywgMC4yNSwgbmEucm0gPSBUUlVFKSwNCiAgICBNZWRpYW4gID0gcXVhbnRpbGUoU29fbHVvbmcsIDAuNSwgbmEucm0gPSBUUlVFKSwNCiAgICBRMyAgICAgID0gcXVhbnRpbGUoU29fbHVvbmcsIDAuNzUsIG5hLnJtID0gVFJVRSksDQogICAgTWF4ICAgICA9IG1heChTb19sdW9uZywgbmEucm0gPSBUUlVFKQ0KICApDQoNCiMgSGnhu4NuIHRo4buLIGLhuqNuZyDEkeG6uXANCmthYmxlKGRlc2NyaXB0aXZlX3N0YXRzX2Z1bGwsDQogICAgICBkaWdpdHMgPSAyLA0KICAgICAgY29sLm5hbWVzID0gYygiQmnhur9uIiwgIlRydW5nIGLDrG5oIiwgIsSQ4buZIGzhu4djaCBjaHXhuqluIiwgIk1pbiIsICJRMSIsICJUcnVuZyB24buLIiwgIlEzIiwgIk1heCIpLA0KICAgICAgY2FwdGlvbiA9ICJUaOG7kW5nIGvDqiBtw7QgdOG6oyDEkeG6p3kgxJHhu6cgc+G7kSBsxrDhu6NuZyBjw6FjIG3hu6ljIHRoZW8gdOG7q25nIGJp4bq/biDEkeG7i25oIHTDrW5oIikNCmBgYA0KDQoqKk5o4bqtbiB4w6l0IHRo4buRbmcga8OqIG3DtCB04bqjIGPDoWMgYmnhur9uIMSR4buLbmggbMaw4bujbmc6KioNCg0KLSAqKkFubnVhbEluY29tZSAoVGh1IG5o4bqtcCBow6BuZyBuxINtKSoqOiBUcnVuZyBiw6xuaCBraG/huqNuZyAxLDc1NywgduG7m2kgxJHhu5kgbOG7h2NoIGNodeG6qW4gbOG7m24gKDEsNTExKSwgY2hvIHRo4bqleSBz4buxIGNow6puaCBs4buHY2ggdGh1IG5o4bqtcCDEkcOhbmcga+G7gyB0cm9uZyB04bqtcCBraMOhY2ggaMOgbmcuIFBow6JuIHBo4buRaSB0aHUgbmjhuq1wIGPDsyB4dSBoxrDhu5tuZyAqKmzhu4djaCBwaOG6o2kqKiwgduG7m2kgcGjhuqduIGzhu5tuIGtow6FjaCBjw7MgdGh1IG5o4bqtcCB0aOG6pXAgxJHhur9uIHRydW5nIGLDrG5oIChRMSA9IDYzNS41LCBRMyA9IDIsNTUwKSwgdHJvbmcga2hpIG3hu5l0IG5ow7NtIG5o4buPIGPDsyB0aHUgbmjhuq1wIHLhuqV0IGNhbyAobWF4ID0gNCw2MDEpLg0KDQotICoqQ2l0eSAoU+G7kSBsxrDhu6NuZyBraMOhY2ggdGhlbyB0aMOgbmggcGjhu5EpKio6IFRydW5nIGLDrG5oIGzDoCA2MTEsIGRhbyDEkeG7mW5nIHThu6sgNzUgxJHhur9uIDEsMzg2LiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBz4buRIGzGsOG7o25nIGtow6FjaCBwaMOibiBi4buRIGtow7RuZyDEkeG7k25nIMSR4buBdSBnaeG7r2EgY8OhYyB0aMOgbmggcGjhu5EsIGPDsyBuxqFpIHThuq1wIHRydW5nIHLhuqV0IGNhbywgbsahaSB0aMOsIHLhuqV0IMOtdC4NCg0KLSAqKkNvdW50cnkgKFBow6JuIGLhu5UgdGhlbyBxdeG7kWMgZ2lhKSoqOiBUcnVuZyBiw6xuaCA0LDY4NiB24bubaSDEkeG7mSBs4buHY2ggY2h14bqpbiBs4bubbiAoNCw0NjEpLCBwaOG6o24gw6FuaCBz4buxIG3huqV0IGPDom4gxJHhu5FpIG3huqFuaCBnaeG7r2EgY8OhYyBxdeG7kWMgZ2lhLiBQaOG6p24gbOG7m24ga2jDoWNoIGjDoG5nIHThuq1wIHRydW5nIHThuqFpIG3hu5l0IHbDoGkgcXXhu5FjIGdpYSBjaMOtbmggKG5oxrAgVVNBKSwgY8OhYyBxdeG7kWMgZ2lhIGtow6FjIGNoaeG6v20gdOG7tyB0cuG7jW5nIG5o4buPLg0KDQotICoqR2VuZGVyLCBIb21lb3duZXIsIE1hcml0YWxTdGF0dXMqKjogQ8OhYyBiaeG6v24gZOG6oW5nIHBow6JuIGxv4bqhaSAoxJHGsOG7o2MgbcOjIGjDs2Egc+G7kSkgY8OzIHRydW5nIGLDrG5oIHbDoCB0cnVuZyB24buLIGfhuqduIG5oYXUgKH43LDAyOSksIGNobyB0aOG6pXkgcGjDom4gcGjhu5FpIGtow6EgxJHhu5NuZyDEkeG7gXUgZ2nhu69hIGPDoWMgbmjDs20gKGdp4bubaSB0w61uaCwgdMOsbmggdHLhuqFuZyBow7RuIG5ow6JuLCBz4bufIGjhu691IG5ow6ApLg0KDQotICoqUHJvZHVjdENhdGVnb3J5Kio6IFRydW5nIGLDrG5oIDMxMiB24bubaSDEkeG7mSBs4buHY2ggY2h14bqpbiAzNTgsIGNobyB0aOG6pXkgbeG7qWMgxJHhu5kgxJFhIGThuqFuZyBjYW8gZ2nhu69hIGPDoWMgZGFuaCBt4bulYyBz4bqjbiBwaOG6qW0uDQoNCi0gKipQcm9kdWN0RGVwYXJ0bWVudCoqOiBDw7MgxJHhu5kgcGjDom4gdMOhbiBs4bubbiAoc3RkID0gNTY5KSwgZ2nDoSB0cuG7iyBs4bubbiBuaOG6pXQgbMOqbiB04bubaSAxLDk5NCBz4bqjbiBwaOG6qW0sIGNobyB0aOG6pXkgbeG7mXQgc+G7kSBwaMOybmcgYmFuIGPDsyBy4bqldCBuaGnhu4F1IHPhuqNuIHBo4bqpbSwgdHJvbmcga2hpIGPDoWMgcGjDsm5nIGJhbiBraMOhYyBjw7Mgc+G7kSBsxrDhu6NuZyDDrXQuDQoNCi0gKipQcm9kdWN0RmFtaWx5Kio6IFRydW5nIGLDrG5oIDQsNjg2IHbDoCDEkeG7mSBs4buHY2ggY2h14bqpbiBjYW8gKDQsNzg2KSwgZGFvIMSR4buZbmcgdOG7qyAxLDI1MCDEkeG6v24gMTAsMTUzLiBT4buxIGNow6puaCBs4buHY2ggbsOgeSBjaG8gdGjhuqV5IHPhu7Ega2jDoWMgYmnhu4d0IHLDtSBy4buHdCB24buBIHPhu5EgbMaw4bujbmcgZ2nhu69hIGPDoWMgbmjDs20gc+G6o24gcGjhuqltIHRpw6p1IGTDuW5nLg0KDQotICoqU3RhdGVvclByb3ZpbmNlKio6IFRydW5nIGLDrG5oIDEsNDA1IHbDoCDEkeG7mSBs4buHY2ggY2h14bqpbiBjYW8gKDEsMzkzKSwgduG7m2kgbWluID0gNzUgdsOgIG1heCA9IDQsNTY3LiDEkGnhu4F1IG7DoHkgY2hvIHRo4bqleSBz4buxIHBow6JuIGLhu5Ega2jDoWNoIGjDoG5nIGtow7RuZyDEkeG7k25nIMSR4buBdSBnaeG7r2EgY8OhYyBiYW5nIGhv4bq3YyB04buJbmgsIHBo4bqjbiDDoW5oIHRo4buLIHRyxrDhu51uZyB04bqtcCB0cnVuZyDhu58gbeG7mXQgc+G7kSBraHUgduG7sWMgbmjhuqV0IMSR4buLbmguDQo=