## 
## 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
## Warning: package 'ggplot2' was built under R version 4.3.3
## Warning: package 'psych' was built under R version 4.3.3
## 
## Attaching package: 'psych'
## The following objects are masked from 'package:ggplot2':
## 
##     %+%, alpha
## Warning: package 'DescTools' was built under R version 4.3.3
## 
## Attaching package: 'DescTools'
## The following objects are masked from 'package:psych':
## 
##     AUC, ICC, SD
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ lubridate 1.9.3     ✔ tibble    3.2.1
## ✔ purrr     1.0.2     ✔ tidyr     1.3.0
## ✔ readr     2.1.5     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ psych::%+%()    masks ggplot2::%+%()
## ✖ psych::alpha()  masks ggplot2::alpha()
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
## 
## Attaching package: 'scales'
## 
## 
## The following object is masked from 'package:purrr':
## 
##     discard
## 
## 
## The following object is masked from 'package:readr':
## 
##     col_factor
## 
## 
## The following objects are masked from 'package:psych':
## 
##     alpha, rescale
## Warning: package 'AER' was built under R version 4.3.3
## Loading required package: car
## Warning: package 'car' was built under R version 4.3.3
## Loading required package: carData
## Warning: package 'carData' was built under R version 4.3.3
## 
## Attaching package: 'car'
## 
## The following object is masked from 'package:purrr':
## 
##     some
## 
## The following object is masked from 'package:DescTools':
## 
##     Recode
## 
## The following object is masked from 'package:psych':
## 
##     logit
## 
## The following object is masked from 'package:dplyr':
## 
##     recode
## 
## Loading required package: lmtest
## Warning: package 'lmtest' was built under R version 4.3.3
## Loading required package: zoo
## Warning: package 'zoo' was built under R version 4.3.3
## 
## Attaching package: 'zoo'
## 
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## 
## Loading required package: sandwich
## Warning: package 'sandwich' was built under R version 4.3.3
## Loading required package: survival
## 
## Attaching package: 'survival'
## 
## The following object is masked from 'package:epitools':
## 
##     ratetable
## Warning: package 'datarium' was built under R version 4.3.3
## Warning: package 'Ecdat' was built under R version 4.3.3
## Loading required package: Ecfun
## Warning: package 'Ecfun' was built under R version 4.3.3
## 
## Attaching package: 'Ecfun'
## 
## The following object is masked from 'package:DescTools':
## 
##     BoxCox
## 
## The following object is masked from 'package:base':
## 
##     sign
## 
## 
## Attaching package: 'Ecdat'
## 
## The following object is masked from 'package:carData':
## 
##     Mroz
## 
## The following object is masked from 'package:datasets':
## 
##     Orange
## Warning: package 'ISLR' was built under R version 4.3.3
d <- Wages
datatable(d)

1 Giới thiệu bộ dữ liệu Wages

Bộ dữ liệu Wages được lấy từ package Ecdat, chứa thông tin về mức lương, trình độ học vấn và các đặc điểm nhân khẩu học của người lao động tại Hoa Kỳ. Bộ dữ liệu Wages chứa 10 biến với tổng cộng 4165 quan sát.

Dữ liệu này thường được sử dụng trong phân tích kinh tế lao động và các mô hình kinh tế lượng để kiểm định tác động của giới tính, chủng tộc, học vấn và tình trạng hôn nhân đến thu nhập.

  • Ý nghĩa các biến trong bộ dữ liệu

Dưới đây là giải thích chi tiết về các biến trong bộ dữ liệu:

Tên biến Kiểu dữ liệu Ý nghĩa
education Numeric Số năm học chính quy mà cá nhân đã hoàn thành.
experience Numeric Số năm kinh nghiệm làm việc.
sex Factor Giới tính của cá nhân: male hoặc female.
ethnic Factor Chủng tộc: white, black, hispanic, other.
married Factor Tình trạng hôn nhân: married hoặc single.
occupation Factor Nhóm nghề nghiệp: manager, sales, clerical, service, other.
industry Factor Ngành nghề: manufacturing, construction, trade, services, other.
union Factor Thành viên công đoàn: yes hoặc no.
wage Numeric Mức lương theo giờ (USD).

Loại biến và Số lượng

Loại biến Số lượng Danh sách biến
Định tính 6 sex, ethnic, married, occupation, industry, union
Định lượng 3 education, experience, wage
  • Kết luận

Bộ dữ liệu Wages là nguồn dữ liệu tiêu biểu và dễ tiếp cận cho các bài tập kinh tế lượng cơ bản về phân tích mức lương và tác động của các yếu tố nhân khẩu học đến thu nhập. Dữ liệu bao gồm nhiều biến định tính có thể dùng cho phân tích thống kê mô tả, kiểm định độc lập, hoặc xây dựng mô hình hồi quy lương theo từng nhóm đặc điểm.


2 Phân tích mối quan hệ giữa việc tham gia công đoàn và các đặc điểm nhân khẩu học của người lao động tại Hoa Kỳ

2.1 Phân tích mối quan hệ giữa biến union và các biến định tính khác

2.1.1 Biến union và biến sex

Bảng tuần suất chéo

a <- table(d$union,d$sex)
addmargins(a)
##      
##       female male  Sum
##   no     370 2279 2649
##   yes     99 1417 1516
##   Sum    469 3696 4165

Bảng tuần suất chéo theo tỷ lệ hàng

a1 <-prop.table(a, margin=1)

Trực quan hóa

a2 <- as.data.frame(a1)
colnames(a2) <- c("union", "sex", "Proportion")

ggplot(a2, aes(x = sex, y = Proportion, fill = union)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(
    title = "Tỷ lệ tham gia công đoàn theo tình trạng giới tính",
    x = "Tình trạng giới tính",
    y = "Tỷ lệ",
    fill = "Tình trạng tham gia công đoàn"
  ) +
  theme_minimal() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_discrete(labels = c("female" = "Nữ", "male" = "Nam")) +
  scale_fill_manual(values = c("no" = "pink", "yes" = "blue")) +
  geom_text(aes(label = scales::percent(Proportion, accuracy = 0.1)),
            position = position_dodge(width = 0.9),
            vjust = -0.25)

Mối quan hệ giữa hai biến

chisq.test(a)
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  a
## X-squared = 52.63, df = 1, p-value = 4.027e-13
  • Relative risk

TH1: Không tham gia công đoàn làm biến tham chiếu

riskratio(a)
## $data
##        
##         female male Total
##   no       370 2279  2649
##   yes       99 1417  1516
##   Total    469 3696  4165
## 
## $measure
##      risk ratio with 95% C.I.
##       estimate    lower    upper
##   no  1.000000       NA       NA
##   yes 1.086446 1.064604 1.108737
## 
## $p.value
##      two-sided
##         midp.exact fisher.exact   chi.square
##   no            NA           NA           NA
##   yes 3.819167e-14 4.377756e-14 2.760744e-13
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

TH2: Tham gia công đoàn làm biến tham chiếu

riskratio(a, rev="b")
## $data
##        
##         male female Total
##   yes   1417     99  1516
##   no    2279    370  2649
##   Total 3696    469  4165
## 
## $measure
##      risk ratio with 95% C.I.
##       estimate    lower    upper
##   yes 1.000000       NA       NA
##   no  2.138867 1.729222 2.645556
## 
## $p.value
##      two-sided
##         midp.exact fisher.exact   chi.square
##   yes           NA           NA           NA
##   no  3.819167e-14 4.377756e-14 2.760744e-13
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"
  • Oddratio
oddsratio(a)
## $data
##        
##         female male Total
##   no       370 2279  2649
##   yes       99 1417  1516
##   Total    469 3696  4165
## 
## $measure
##      odds ratio with 95% C.I.
##       estimate    lower    upper
##   no  1.000000       NA       NA
##   yes 2.320732 1.848487 2.939374
## 
## $p.value
##      two-sided
##         midp.exact fisher.exact   chi.square
##   no            NA           NA           NA
##   yes 3.819167e-14 4.377756e-14 2.760744e-13
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"

2.1.2 Biến union và biến industry

Bảng tuần suất chéo

b <- table(d$union,d$married)
addmargins(b)
##      
##         no  yes  Sum
##   no   581 2068 2649
##   yes  192 1324 1516
##   Sum  773 3392 4165

Bảng tuần suất chéo theo tỷ lệ hàng

b1 <-prop.table(b, margin=1)

Trực quan hóa

b2 <- as.data.frame(b1)
colnames(b2) <- c("union", "married", "Proportion")

ggplot(b2, aes(x = married, y = Proportion, fill = union)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(
    title = "Tỷ lệ tham gia công đoàn theo tình trạng hôn nhân",
    x = "Tình trạng hôn nhân",
    y = "Tỷ lệ",
    fill = "Tình trạng tham gia công đoàn"
  ) +
  theme_minimal() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_discrete(labels = c("no" = "Chưa kết hôn", "yes" = "Đã kết hôn")) +
  scale_fill_manual(values = c("no" = "orange", "yes" = "seagreen")) +
  geom_text(aes(label = scales::percent(Proportion, accuracy = 0.1)),
            position = position_dodge(width = 0.9),
            vjust = -0.25)

Mối quan hệ giữa hai biến

chisq.test(b)
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  b
## X-squared = 54.181, df = 1, p-value = 1.828e-13
  • Relative risk

TH1: Không tham gia công đoàn làm biến tham chiếu

riskratio(b)
## $data
##        
##          no  yes Total
##   no    581 2068  2649
##   yes   192 1324  1516
##   Total 773 3392  4165
## 
## $measure
##      risk ratio with 95% C.I.
##       estimate    lower    upper
##   no  1.000000       NA       NA
##   yes 1.118717 1.088005 1.150296
## 
## $p.value
##      two-sided
##         midp.exact fisher.exact   chi.square
##   no            NA           NA           NA
##   yes 3.863576e-14 5.029762e-14 1.339327e-13
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

TH2: Tham gia công đoàn làm biến tham chiếu

riskratio(b, rev="b")
## $data
##        
##          yes  no Total
##   yes   1324 192  1516
##   no    2068 581  2649
##   Total 3392 773  4165
## 
## $measure
##      risk ratio with 95% C.I.
##       estimate    lower    upper
##   yes 1.000000       NA       NA
##   no  1.731778 1.489884 2.012945
## 
## $p.value
##      two-sided
##         midp.exact fisher.exact   chi.square
##   yes           NA           NA           NA
##   no  3.863576e-14 5.029762e-14 1.339327e-13
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"
  • Oddratio
oddsratio(b)
## $data
##        
##          no  yes Total
##   no    581 2068  2649
##   yes   192 1324  1516
##   Total 773 3392  4165
## 
## $measure
##      odds ratio with 95% C.I.
##       estimate    lower    upper
##   no  1.000000       NA       NA
##   yes 1.936146 1.624601 2.316163
## 
## $p.value
##      two-sided
##         midp.exact fisher.exact   chi.square
##   no            NA           NA           NA
##   yes 3.863576e-14 5.029762e-14 1.339327e-13
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"

2.2 Mô hình hồi quy logistic

2.2.1 Biến union và biến sex

Câu hỏi nghiên cứu: Xác suất người lao động tại Hoa kỳ là người tham gia công đoàn phụ thuộc vào giới tính là bao nhiêu ?

📌 Thành phần mô hình:

  • Random component:
    \(Y \sim \text{Bernoulli}(p)\)

  • Systematic component:
    \(\eta = \beta_0 + \beta_1 \times \text{sex}\)

  • Link function:
    \(g(p) = \log\left(\frac{p}{1-p}\right)\)

📌 Phương trình mô hình:

\[ \log \left(\frac{p_i}{1-p_i}\right) = \beta_0 + \beta_1 \times \text{sex}_i \]

Trong đó:

  • \(p_i\) là xác suất người lao động thứ \(i\) tham gia công đoàn

  • \(\text{sex}_i\) là biến giới tính: male hoặc female

  • \(\beta_0\) là hệ số chặn (intercept)

  • \(\beta_1\) là hệ số ảnh hưởng của giới tính đến xác suất tham gia công đoàn

  • Ước lượng mô hình:

d$union_bin <- ifelse(d$union == "yes", 1, 0)   

logit_model <- glm(union_bin ~ sex, data = d, family = binomial(link = "logit"))
summary(logit_model)
## 
## Call:
## glm(formula = union_bin ~ sex, family = binomial(link = "logit"), 
##     data = d)
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)    
## (Intercept)  -1.3184     0.1132 -11.651  < 2e-16 ***
## sexmale       0.8432     0.1181   7.139 9.37e-13 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 5461.8  on 4164  degrees of freedom
## Residual deviance: 5404.3  on 4163  degrees of freedom
## AIC: 5408.3
## 
## Number of Fisher Scoring iterations: 4

Phương trình hồi quy:
\(\log \left(\frac{p_i}{1-p_i}\right) = -1.3184 + 0.8432 \times \text{sex}_i\)

  • Dự báo: Sử dụng quy ước ngưỡng 0.5 cho phần dự báo.

Dự báo với type = response

Đây là xác suất dự báo một người lao động là nam sẽ tham gia công đoàn theo mô hình logistic.

new_worker <- data.frame(sex = "male")
predict(logit_model, newdata = new_worker, type = "response")
##         1 
## 0.3833874
  • Giá trị dự báo: 38.34%. Tức là nếu người lao động đó là nam thì mô hình logistic dự báo rằng xác suất người đó tham gia công đoàn là 38.84%.
  • Với ngưỡng quy ước là 0.5 thì giá trị dự báo 38.84% cho thấy người lao động nam này không tham gia công đoàn.

Dự báo với type = link
👉 Ý nghĩa:

  • Đây là log odds (logit) dự báo cho người nam.
  • Nó tính theo công thức:

\[ \text{logit}(p) = \beta_0 + \beta_1 \times \text{sex} \]

new_worker <- data.frame(sex = "male")
predict(logit_model, newdata = new_worker, type = "link")
##          1 
## -0.4751948
  • Giải thích giá trị:

  • -0.4751948 là log odds của việc tham gia công đoàn nếu là nam.

  • Tính xác suất từ log odds này:

\[ p = \frac{e^{-0.4751948}}{1 + e^{-0.4751948}} \approx 0.3834 \]

\(\rightarrow\) đúng bằng giá trị ở trên với type = "response"

Dự báo với type = terms

new_worker <- data.frame(sex = "male")
predict(logit_model, newdata = new_worker, type = "terms")
##          sex
## 1 0.09494726
## attr(,"constant")
## [1] -0.5701421

👉 Ý nghĩa:

Đây là phần đóng góp (effect) của từng biến vào giá trị logit dự báo.

Gồm:

  • Effect của biến sex = 0.09494726
  • Intercept (constant) = -0.5701421

Giải thích cụ thể:

\[ \text{Logit}(p) = \text{Intercept} + \text{Effect của sex} \]

Cộng lại:

\[ -0.5701421 + 0.09494726 = -0.4751948 \]

\(\rightarrow\) Chính là giá trị type = "link" phía trên.

2.3 Mô hình hồi quy probit

2.3.1 Biến union và biến sex

Câu hỏi nghiên cứu: Xác suất người lao động tại Hoa kỳ là người tham gia công đoàn phụ thuộc vào giới tính là bao nhiêu ?

📌 Thành phần mô hình:

  • Random component:
    \(Y \sim \text{Bernoulli}(p)\)

  • Systematic component:
    \(\eta = \beta_0 + \beta_1 \times \text{sex}\)

  • Link function:
    \(g(p) = \Phi^{-1}(p)\)

📌 Phương trình mô hình:

\[ \Phi^{-1}(p_i) = \beta_0 + \beta_1 \times \text{sex}_i \]

Trong đó:

  • \(\Phi^{-1}\) là hàm phân phối tích lũy chuẩn nghịch đảo (inverse CDF)

  • Các ký hiệu khác như mô hình Logistic (áp dụng cho trường hợp này là mô hình Probit, với \(p_i\) là xác suất người lao động thứ \(i\) tham gia công đoàn, \(\text{sex}_i\) là biến giới tính, \(\beta_0\) là hệ số chặn và \(\beta_1\) là hệ số ảnh hưởng của giới tính).

  • Ước lượng mô hình:

probit_model <- glm(union_bin ~ sex, data = d, family = binomial(link = "probit"))
summary(probit_model)
## 
## Call:
## glm(formula = union_bin ~ sex, family = binomial(link = "probit"), 
##     data = d)
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)    
## (Intercept) -0.80265    0.06518 -12.313  < 2e-16 ***
## sexmale      0.50606    0.06847   7.391 1.46e-13 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 5461.8  on 4164  degrees of freedom
## Residual deviance: 5404.3  on 4163  degrees of freedom
## AIC: 5408.3
## 
## Number of Fisher Scoring iterations: 4

Phương trình hồi quy probit:
\[ \Phi^{-1}(p_i) = -0.80265 + 0.50606 \times \text{sex}_i \]

  • Dự báo:

Dự báo với typr = response

new_worker <- data.frame(sex = "male")
predict(probit_model, newdata = new_worker, type = "response")
##         1 
## 0.3833874

Ý nghĩa:

  • Xác suất tham gia công đoàn nếu là nam là 38.34%.

Nếu quy ước ngưỡng 0.5:

\[ 0.3834 < 0.5 \]

\(\rightarrow\) Dự đoán không tham gia công đoàn.

Dự báo với type = link

new_worker <- data.frame(sex = "male")
predict(probit_model, newdata = new_worker, type = "link")
##          1 
## -0.2965961

Ý nghĩa:

  • Đây là log-probit (inverse CDF chuẩn) dự báo cho người nam.

Nó tương đương:

\[ \Phi^{-1}(p_{\text{nam}}) = -0.80265 + 0.50606 \times 1 = -0.2965961 \]

\(\rightarrow\) Nếu bạn lấy \(\Phi(-0.2966) \approx 0.3834\)

\(\Phi(-0.2966) \approx 0.3834\) đúng với type="response"

Dự báo với type=terms

new_worker <- data.frame(sex = "male")
predict(probit_model, newdata = new_worker, type = "terms")
##          sex
## 1 0.05698465
## attr(,"constant")
## [1] -0.3535807

Ý nghĩa:

  • Effect của biến sexmale+0.057
  • Intercept (constant) là -0.3536

Tổng log-probit dự báo:

\[ -0.3536 + 0.057 = -0.2966 \]

2.4 Mô hình hồi quy cloglog

2.4.1 Biến union và biến sex

Câu hỏi nghiên cứu: Xác suất người lao động tại Hoa kỳ là người tham gia công đoàn phụ thuộc vào giới tính là bao nhiêu ?

📌 Thành phần mô hình:

  • Random component:
    \(Y \sim \text{Bernoulli}(p)\)

  • Systematic component:
    \(\eta = \beta_0 + \beta_1 \times \text{sex}\)

  • Link function:
    \(g(p) = \log(-\log(1-p))\)

📌 Phương trình mô hình:

\[ \log \left( -\log(1-p_i) \right) = \beta_0 + \beta_1 \times \text{sex}_i \]

  • Ước lượng mô hình:
cloglog_model <- glm(union_bin ~ sex, data = d, family = binomial(link = "cloglog"))
summary(cloglog_model)
## 
## Call:
## glm(formula = union_bin ~ sex, family = binomial(link = "cloglog"), 
##     data = d)
## 
## Coefficients:
##             Estimate Std. Error z value Pr(>|z|)    
## (Intercept)  -1.4393     0.1007 -14.287  < 2e-16 ***
## sexmale       0.7126     0.1042   6.836 8.17e-12 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 5461.8  on 4164  degrees of freedom
## Residual deviance: 5404.3  on 4163  degrees of freedom
## AIC: 5408.3
## 
## Number of Fisher Scoring iterations: 5
  • Dự báo:
new_worker <- data.frame(sex = "male")
predict(cloglog_model, newdata = new_worker, type = "response")
##         1 
## 0.3833874
new_worker <- data.frame(sex = "male")
predict(cloglog_model, newdata = new_worker, type = "link")
##          1 
## -0.7266742
new_worker <- data.frame(sex = "male")
predict(cloglog_model, newdata = new_worker, type = "terms")
##          sex
## 1 0.08024237
## attr(,"constant")
## [1] -0.8069165
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSB0deG6p24gNyINCmF1dGhvcjogInBubWluaGNoYXUiDQpkYXRlOiAiMjAyNS0wNy0xMyINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtOiAiZGVmYXVsdCINCiAgICB0b2NfZGVwdGg6IDMNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQo8bGluayByZWw9InN0eWxlc2hlZXQiIHR5cGU9InRleHQvY3NzIiBocmVmPSJzdHlsZS5jc3MiPg0KDQoNCmBgYHtyLGVjaG89RkFMU0V9DQpsaWJyYXJ5KERUKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoc3RhdHMpDQpsaWJyYXJ5KHBzeWNoKQ0KbGlicmFyeShEZXNjVG9vbHMpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShlcGl0b29scykNCmxpYnJhcnkoQUVSKQ0KbGlicmFyeShkYXRhcml1bSkNCmxpYnJhcnkoRWNkYXQpDQpsaWJyYXJ5KElTTFIpDQpgYGANCg0KYGBge3IsZWNobz1UUlVFfQ0KZCA8LSBXYWdlcw0KZGF0YXRhYmxlKGQpDQpgYGANCg0KIyBHaeG7m2kgdGhp4buHdSBi4buZIGThu68gbGnhu4d1IFdhZ2VzDQoNCkLhu5kgZOG7ryBsaeG7h3UgKipXYWdlcyoqIMSRxrDhu6NjIGzhuqV5IHThu6sgcGFja2FnZSBgRWNkYXRgLCBjaOG7qWEgdGjDtG5nIHRpbiB24buBIG3hu6ljIGzGsMahbmcsIHRyw6xuaCDEkeG7mSBo4buNYyB24bqlbiB2w6AgY8OhYyDEkeG6t2MgxJFp4buDbSBuaMOibiBraOG6qXUgaOG7jWMgY+G7p2EgbmfGsOG7nWkgbGFvIMSR4buZbmcgdOG6oWkgSG9hIEvhu7MuIELhu5kgZOG7ryBsaeG7h3UgV2FnZXMgY2jhu6lhIDEwIGJp4bq/biB24bubaSB04buVbmcgY+G7mW5nIDQxNjUgcXVhbiBzw6F0LiAgICAgIA0KDQpE4buvIGxp4buHdSBuw6B5IHRoxrDhu51uZyDEkcaw4bujYyBz4butIGThu6VuZyB0cm9uZyBwaMOibiB0w61jaCBraW5oIHThur8gbGFvIMSR4buZbmcgdsOgIGPDoWMgbcO0IGjDrG5oIGtpbmggdOG6vyBsxrDhu6NuZyDEkeG7gyBraeG7g20gxJHhu4tuaCB0w6FjIMSR4buZbmcgY+G7p2EgKipnaeG7m2kgdMOtbmgsIGNo4bunbmcgdOG7mWMsIGjhu41jIHbhuqVuIHbDoCB0w6xuaCB0cuG6oW5nIGjDtG4gbmjDom4qKiDEkeG6v24gdGh1IG5o4bqtcC4gICANCg0KKiAqKsOdIG5naMSpYSBjw6FjIGJp4bq/biB0cm9uZyBi4buZIGThu68gbGnhu4d1KiogICANCg0KRMaw4bubaSDEkcOieSBsw6AgZ2nhuqNpIHRow61jaCBjaGkgdGnhur90IHbhu4EgY8OhYyBiaeG6v24gdHJvbmcgYuG7mSBk4buvIGxp4buHdTogICANCg0KfCBUw6puIGJp4bq/biAgIHwgS2nhu4N1IGThu68gbGnhu4d1IHwgw50gbmdoxKlhICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnw6LS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfA0KfCBgZWR1Y2F0aW9uYCB8IE51bWVyaWMgICAgICB8IFPhu5EgbsSDbSBo4buNYyBjaMOtbmggcXV5IG3DoCBjw6EgbmjDom4gxJHDoyBob8OgbiB0aMOgbmguIHwNCnwgYGV4cGVyaWVuY2VgfCBOdW1lcmljICAgICAgfCBT4buRIG7Eg20ga2luaCBuZ2hp4buHbSBsw6BtIHZp4buHYy4gICAgICAgICAgICAgICAgICAgfA0KfCBgc2V4YCAgICAgICB8IEZhY3RvciAgICAgICB8IEdp4bubaSB0w61uaCBj4bunYSBjw6EgbmjDom46IGBtYWxlYCBob+G6t2MgYGZlbWFsZWAuICB8DQp8IGBldGhuaWNgICAgIHwgRmFjdG9yICAgICAgIHwgQ2jhu6duZyB04buZYzogYHdoaXRlYCwgYGJsYWNrYCwgYGhpc3BhbmljYCwgYG90aGVyYC58DQp8IGBtYXJyaWVkYCAgIHwgRmFjdG9yICAgICAgIHwgVMOsbmggdHLhuqFuZyBow7RuIG5ow6JuOiBgbWFycmllZGAgaG/hurdjIGBzaW5nbGVgLiB8DQp8IGBvY2N1cGF0aW9uYHwgRmFjdG9yICAgICAgIHwgTmjDs20gbmdo4buBIG5naGnhu4dwOiBgbWFuYWdlcmAsIGBzYWxlc2AsIGBjbGVyaWNhbGAsIGBzZXJ2aWNlYCwgYG90aGVyYC58DQp8IGBpbmR1c3RyeWAgIHwgRmFjdG9yICAgICAgIHwgTmfDoG5oIG5naOG7gTogYG1hbnVmYWN0dXJpbmdgLCBgY29uc3RydWN0aW9uYCwgYHRyYWRlYCwgYHNlcnZpY2VzYCwgYG90aGVyYC58DQp8IGB1bmlvbmAgICAgIHwgRmFjdG9yICAgICAgIHwgVGjDoG5oIHZpw6puIGPDtG5nIMSRb8OgbjogYHllc2AgaG/hurdjIGBub2AuICAgICAgICB8DQp8IGB3YWdlYCAgICAgIHwgTnVtZXJpYyAgICAgIHwgTeG7qWMgbMawxqFuZyB0aGVvIGdp4budIChVU0QpLiAgICAgICAgICAgICAgICAgICAgICB8DQoNCg0KKkxv4bqhaSBiaeG6v24gdsOgIFPhu5EgbMaw4bujbmcqICAgDQoNCnwgTG/huqFpIGJp4bq/biAgIHwgU+G7kSBsxrDhu6NuZyB8IERhbmggc8OhY2ggYmnhur9uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwNCnw6LS0tLS0tLS0tLS0tfDotLS0tLS0tLS18Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwNCnwgKirEkOG7i25oIHTDrW5oKiogfCA2ICAgICAgICB8IGBzZXhgLCBgZXRobmljYCwgYG1hcnJpZWRgLCBgb2NjdXBhdGlvbmAsIGBpbmR1c3RyeWAsIGB1bmlvbmAgfA0KfCAqKsSQ4buLbmggbMaw4bujbmcqKiB8IDMgICAgICAgIHwgYGVkdWNhdGlvbmAsIGBleHBlcmllbmNlYCwgYHdhZ2VgICAgICAgICAgICAgICAgICAgfA0KDQoqICoqS+G6v3QgbHXhuq1uKioNCg0KQuG7mSBk4buvIGxp4buHdSAqKldhZ2VzKiogbMOgIG5ndeG7k24gZOG7ryBsaeG7h3UgdGnDqnUgYmnhu4N1IHbDoCBk4buFIHRp4bq/cCBj4bqtbiBjaG8gY8OhYyBiw6BpIHThuq1wIGtpbmggdOG6vyBsxrDhu6NuZyBjxqEgYuG6o24gduG7gSBwaMOibiB0w61jaCBt4bupYyBsxrDGoW5nIHbDoCB0w6FjIMSR4buZbmcgY+G7p2EgY8OhYyB54bq/dSB04buRIG5ow6JuIGto4bqpdSBo4buNYyDEkeG6v24gdGh1IG5o4bqtcC4gROG7ryBsaeG7h3UgYmFvIGfhu5NtIG5oaeG7gXUgYmnhur9uIMSR4buLbmggdMOtbmggY8OzIHRo4buDIGTDuW5nIGNobyAqKnBow6JuIHTDrWNoIHRo4buRbmcga8OqIG3DtCB04bqjKiosICoqa2nhu4NtIMSR4buLbmggxJHhu5ljIGzhuq1wKiosIGhv4bq3YyAqKnjDonkgZOG7sW5nIG3DtCBow6xuaCBo4buTaSBxdXkgbMawxqFuZyoqIHRoZW8gdOG7q25nIG5ow7NtIMSR4bq3YyDEkWnhu4NtLiAgIA0KDQoqKioNCiMgUGjDom4gdMOtY2ggbeG7kWkgcXVhbiBo4buHIGdp4buvYSB2aeG7h2MgdGhhbSBnaWEgY8O0bmcgxJFvw6BuIHbDoCBjw6FjIMSR4bq3YyDEkWnhu4NtIG5ow6JuIGto4bqpdSBo4buNYyBj4bunYSBuZ8aw4budaSBsYW8gxJHhu5luZyB04bqhaSBIb2EgS+G7syAgDQoNCiMjIFBow6JuIHTDrWNoIG3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgYmnhur9uIHVuaW9uIHbDoCBjw6FjIGJp4bq/biDEkeG7i25oIHTDrW5oIGtow6FjICAgDQojIyMgQmnhur9uIHVuaW9uIHbDoCBiaeG6v24gc2V4ICAgDQoNCipC4bqjbmcgdHXhuqduIHN14bqldCBjaMOpbyogICANCg0KYGBge3IsZWNobz1UUlVFfQ0KYSA8LSB0YWJsZShkJHVuaW9uLGQkc2V4KQ0KYWRkbWFyZ2lucyhhKQ0KYGBgDQoNCipC4bqjbmcgdHXhuqduIHN14bqldCBjaMOpbyB0aGVvIHThu7cgbOG7hyBow6BuZyogICANCg0KYGBge3IsZWNobz1UUlVFfQ0KYTEgPC1wcm9wLnRhYmxlKGEsIG1hcmdpbj0xKQ0KDQpgYGANCg0KKlRy4buxYyBxdWFuIGjDs2EqICAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCmEyIDwtIGFzLmRhdGEuZnJhbWUoYTEpDQpjb2xuYW1lcyhhMikgPC0gYygidW5pb24iLCAic2V4IiwgIlByb3BvcnRpb24iKQ0KDQpnZ3Bsb3QoYTIsIGFlcyh4ID0gc2V4LCB5ID0gUHJvcG9ydGlvbiwgZmlsbCA9IHVuaW9uKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiVOG7tyBs4buHIHRoYW0gZ2lhIGPDtG5nIMSRb8OgbiB0aGVvIHTDrG5oIHRy4bqhbmcgZ2nhu5tpIHTDrW5oIiwNCiAgICB4ID0gIlTDrG5oIHRy4bqhbmcgZ2nhu5tpIHTDrW5oIiwNCiAgICB5ID0gIlThu7cgbOG7hyIsDQogICAgZmlsbCA9ICJUw6xuaCB0cuG6oW5nIHRoYW0gZ2lhIGPDtG5nIMSRb8OgbiINCiAgKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpICsNCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPSBjKCJmZW1hbGUiID0gIk7hu68iLCAibWFsZSIgPSAiTmFtIikpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygibm8iID0gInBpbmsiLCAieWVzIiA9ICJibHVlIikpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHNjYWxlczo6cGVyY2VudChQcm9wb3J0aW9uLCBhY2N1cmFjeSA9IDAuMSkpLA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOSksDQogICAgICAgICAgICB2anVzdCA9IC0wLjI1KQ0KDQpgYGANCg0KKk3hu5FpIHF1YW4gaOG7hyBnaeG7r2EgaGFpIGJp4bq/biogICANCg0KYGBge3IsZWNobz1UUlVFfQ0KDQpjaGlzcS50ZXN0KGEpDQoNCmBgYA0KKiAqKlJlbGF0aXZlIHJpc2sqKiAgIA0KDQoqVEgxOiBLaMO0bmcgdGhhbSBnaWEgY8O0bmcgxJFvw6BuIGzDoG0gYmnhur9uIHRoYW0gY2hp4bq/dSogICANCg0KYGBge3IsZWNobz1UUlVFfQ0Kcmlza3JhdGlvKGEpDQoNCmBgYA0KDQoqVEgyOiBUaGFtIGdpYSBjw7RuZyDEkW/DoG4gbMOgbSBiaeG6v24gdGhhbSBjaGnhur91KiAgIA0KDQpgYGB7cixlY2hvPVRSVUV9DQoNCnJpc2tyYXRpbyhhLCByZXY9ImIiKQ0KDQpgYGANCiogKipPZGRyYXRpbyoqICAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCg0Kb2Rkc3JhdGlvKGEpDQoNCmBgYA0KDQojIyMgKipCaeG6v24gdW5pb24gdsOgIGJp4bq/biBpbmR1c3RyeSoqDQoNCg0KKkLhuqNuZyB0deG6p24gc3XhuqV0IGNow6lvKiAgIA0KDQpgYGB7cixlY2hvPVRSVUV9DQpiIDwtIHRhYmxlKGQkdW5pb24sZCRtYXJyaWVkKQ0KYWRkbWFyZ2lucyhiKQ0KYGBgDQoNCipC4bqjbmcgdHXhuqduIHN14bqldCBjaMOpbyB0aGVvIHThu7cgbOG7hyBow6BuZyogICANCg0KYGBge3IsZWNobz1UUlVFfQ0KYjEgPC1wcm9wLnRhYmxlKGIsIG1hcmdpbj0xKQ0KDQpgYGANCg0KKlRy4buxYyBxdWFuIGjDs2EqICAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCmIyIDwtIGFzLmRhdGEuZnJhbWUoYjEpDQpjb2xuYW1lcyhiMikgPC0gYygidW5pb24iLCAibWFycmllZCIsICJQcm9wb3J0aW9uIikNCg0KZ2dwbG90KGIyLCBhZXMoeCA9IG1hcnJpZWQsIHkgPSBQcm9wb3J0aW9uLCBmaWxsID0gdW5pb24pKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJU4bu3IGzhu4cgdGhhbSBnaWEgY8O0bmcgxJFvw6BuIHRoZW8gdMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIiwNCiAgICB4ID0gIlTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiIsDQogICAgeSA9ICJU4bu3IGzhu4ciLA0KICAgIGZpbGwgPSAiVMOsbmggdHLhuqFuZyB0aGFtIGdpYSBjw7RuZyDEkW/DoG4iDQogICkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KSArDQogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygibm8iID0gIkNoxrBhIGvhur90IGjDtG4iLCAieWVzIiA9ICLEkMOjIGvhur90IGjDtG4iKSkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJubyIgPSAib3JhbmdlIiwgInllcyIgPSAic2VhZ3JlZW4iKSkgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gc2NhbGVzOjpwZXJjZW50KFByb3BvcnRpb24sIGFjY3VyYWN5ID0gMC4xKSksDQogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSwNCiAgICAgICAgICAgIHZqdXN0ID0gLTAuMjUpDQoNCmBgYA0KDQoqTeG7kWkgcXVhbiBo4buHIGdp4buvYSBoYWkgYmnhur9uKiAgIA0KDQpgYGB7cixlY2hvPVRSVUV9DQoNCmNoaXNxLnRlc3QoYikNCg0KYGBgDQoqICoqUmVsYXRpdmUgcmlzayoqICAgDQoNCipUSDE6IEtow7RuZyB0aGFtIGdpYSBjw7RuZyDEkW/DoG4gbMOgbSBiaeG6v24gdGhhbSBjaGnhur91KiAgIA0KDQpgYGB7cixlY2hvPVRSVUV9DQpyaXNrcmF0aW8oYikNCg0KYGBgDQoNCipUSDI6IFRoYW0gZ2lhIGPDtG5nIMSRb8OgbiBsw6BtIGJp4bq/biB0aGFtIGNoaeG6v3UqICAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCg0Kcmlza3JhdGlvKGIsIHJldj0iYiIpDQoNCmBgYA0KKiAqKk9kZHJhdGlvKiogICANCg0KYGBge3IsZWNobz1UUlVFfQ0KDQpvZGRzcmF0aW8oYikNCg0KYGBgDQoNCiMjIE3DtCBow6xuaCBo4buTaSBxdXkgbG9naXN0aWMgIA0KDQojIyMgQmnhur9uIHVuaW9uIHbDoCBiaeG6v24gc2V4DQoNCioqQ8OidSBo4buPaSBuZ2hpw6puIGPhu6l1OioqIFjDoWMgc3XhuqV0IG5nxrDhu51pIGxhbyDEkeG7mW5nIHThuqFpIEhvYSBr4buzIGzDoCBuZ8aw4budaSB0aGFtIGdpYSBjw7RuZyDEkW/DoG4gcGjhu6UgdGh14buZYyB2w6BvIGdp4bubaSB0w61uaCBsw6AgYmFvIG5oacOqdSA/ICAgDQoNCvCfk4wgVGjDoG5oIHBo4bqnbiBtw7QgaMOsbmg6ICAgDQoNCiogUmFuZG9tIGNvbXBvbmVudDogICANCiRZIFxzaW0gXHRleHR7QmVybm91bGxpfShwKSQgICANCg0KKiBTeXN0ZW1hdGljIGNvbXBvbmVudDogICANCiRcZXRhID0gXGJldGFfMCArIFxiZXRhXzEgXHRpbWVzIFx0ZXh0e3NleH0kICAgDQoNCiogTGluayBmdW5jdGlvbjogICANCiRnKHApID0gXGxvZ1xsZWZ0KFxmcmFje3B9ezEtcH1ccmlnaHQpJCAgIA0KDQrwn5OMIFBoxrDGoW5nIHRyw6xuaCBtw7QgaMOsbmg6ICAgDQoNCiQkDQpcbG9nIFxsZWZ0KFxmcmFje3BfaX17MS1wX2l9XHJpZ2h0KSA9IFxiZXRhXzAgKyBcYmV0YV8xIFx0aW1lcyBcdGV4dHtzZXh9X2kNCiQkICAgDQoNClRyb25nIMSRw7M6ICAgDQoNCiogJHBfaSQgbMOgIHjDoWMgc3XhuqV0IG5nxrDhu51pIGxhbyDEkeG7mW5nIHRo4bupICRpJCB0aGFtIGdpYSBjw7RuZyDEkW/DoG4gICANCiogJFx0ZXh0e3NleH1faSQgbMOgIGJp4bq/biBnaeG7m2kgdMOtbmg6IGBtYWxlYCBob+G6t2MgYGZlbWFsZWAgICANCiogJFxiZXRhXzAkIGzDoCBo4buHIHPhu5EgY2jhurduIChpbnRlcmNlcHQpICAgDQoqICRcYmV0YV8xJCBsw6AgaOG7hyBz4buRIOG6o25oIGjGsOG7n25nIGPhu6dhIGdp4bubaSB0w61uaCDEkeG6v24geMOhYyBzdeG6pXQgdGhhbSBnaWEgY8O0bmcgxJFvw6BuICAgDQoNCiogKsav4bubYyBsxrDhu6NuZyBtw7QgaMOsbmg6KiAgIA0KDQpgYGB7cixlY2hvPVRSVUV9DQoNCmQkdW5pb25fYmluIDwtIGlmZWxzZShkJHVuaW9uID09ICJ5ZXMiLCAxLCAwKSAgIA0KDQpsb2dpdF9tb2RlbCA8LSBnbG0odW5pb25fYmluIH4gc2V4LCBkYXRhID0gZCwgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJsb2dpdCIpKQ0Kc3VtbWFyeShsb2dpdF9tb2RlbCkNCg0KYGBgDQoqUGjGsMahbmcgdHLDrG5oIGjhu5NpIHF1eToqICAgDQokXGxvZyBcbGVmdChcZnJhY3twX2l9ezEtcF9pfVxyaWdodCkgPSAtMS4zMTg0ICsgMC44NDMyIFx0aW1lcyBcdGV4dHtzZXh9X2kkICAgDQoNCg0KKiAqROG7sSBiw6FvOiogU+G7rSBk4bulbmcgcXV5IMaw4bubYyBuZ8aw4buhbmcgMC41IGNobyBwaOG6p24gZOG7sSBiw6FvLiAgIA0KDQoqKkThu7EgYsOhbyB24bubaSBgdHlwZSA9IHJlc3BvbnNlYCoqICAgDQoNCiAgIMSQw6J5IGzDoCB4w6FjIHN14bqldCBk4buxIGLDoW8gbeG7mXQgbmfGsOG7nWkgbGFvIMSR4buZbmcgbMOgIG5hbSBz4bq9IHRoYW0gZ2lhIGPDtG5nIMSRb8OgbiB0aGVvIG3DtCBow6xuaCBsb2dpc3RpYy4gICANCiAgIA0KYGBge3IsZWNobz1UUlVFfQ0KbmV3X3dvcmtlciA8LSBkYXRhLmZyYW1lKHNleCA9ICJtYWxlIikNCnByZWRpY3QobG9naXRfbW9kZWwsIG5ld2RhdGEgPSBuZXdfd29ya2VyLCB0eXBlID0gInJlc3BvbnNlIikNCmBgYA0KKiBHacOhIHRy4buLIGThu7EgYsOhbzogMzguMzQlLiBU4bupYyBsw6AgbuG6v3UgbmfGsOG7nWkgbGFvIMSR4buZbmcgxJHDsyBsw6AgbmFtIHRow6wgbcO0IGjDrG5oIGxvZ2lzdGljIGThu7EgYsOhbyBy4bqxbmcgeMOhYyBzdeG6pXQgbmfGsOG7nWkgxJHDsyB0aGFtIGdpYSBjw7RuZyDEkW/DoG4gbMOgIDM4Ljg0JS4gICANCiogVuG7m2kgbmfGsOG7oW5nIHF1eSDGsOG7m2MgbMOgIDAuNSB0aMOsIGdpw6EgdHLhu4sgZOG7sSBiw6FvIDM4Ljg0JSBjaG8gdGjhuqV5IG5nxrDhu51pIGxhbyDEkeG7mW5nIG5hbSBuw6B5IGtow7RuZyB0aGFtIGdpYSBjw7RuZyDEkW/DoG4uICAgDQoNCioqROG7sSBiw6FvIHbhu5tpIGB0eXBlID0gbGlua2AqKiAgDQrwn5GJIMOdIG5naMSpYTogICANCg0KKiDEkMOieSBsw6AgbG9nIG9kZHMgKGxvZ2l0KSBk4buxIGLDoW8gY2hvIG5nxrDhu51pIG5hbS4gICANCiogTsOzIHTDrW5oIHRoZW8gY8O0bmcgdGjhu6ljOiAgIA0KDQokJA0KXHRleHR7bG9naXR9KHApID0gXGJldGFfMCArIFxiZXRhXzEgXHRpbWVzIFx0ZXh0e3NleH0NCiQkICAgDQoNCg0KYGBge3IsZWNobz1UUlVFfQ0KDQpuZXdfd29ya2VyIDwtIGRhdGEuZnJhbWUoc2V4ID0gIm1hbGUiKQ0KcHJlZGljdChsb2dpdF9tb2RlbCwgbmV3ZGF0YSA9IG5ld193b3JrZXIsIHR5cGUgPSAibGluayIpDQoNCmBgYA0KDQoqIEdp4bqjaSB0aMOtY2ggZ2nDoSB0cuG7izogICANCg0KKiBgLTAuNDc1MTk0OGAgbMOgIGxvZyBvZGRzIGPhu6dhIHZp4buHYyB0aGFtIGdpYSBjw7RuZyDEkW/DoG4gbuG6v3UgbMOgIG5hbS4NCg0KKiBUw61uaCB4w6FjIHN14bqldCB04burIGxvZyBvZGRzIG7DoHk6ICAgDQoNCiQkDQpwID0gXGZyYWN7ZV57LTAuNDc1MTk0OH19ezEgKyBlXnstMC40NzUxOTQ4fX0gXGFwcHJveCAwLjM4MzQNCiQkICAgDQoNCiRccmlnaHRhcnJvdyQgxJHDum5nIGLhurFuZyBnacOhIHRy4buLIOG7nyB0csOqbiB24bubaSBgdHlwZSA9ICJyZXNwb25zZSJgDQoNCioqROG7sSBiw6FvIHbhu5tpIGB0eXBlID0gdGVybXNgKiogICANCg0KDQpgYGB7cixlY2hvPVRSVUV9DQoNCm5ld193b3JrZXIgPC0gZGF0YS5mcmFtZShzZXggPSAibWFsZSIpDQpwcmVkaWN0KGxvZ2l0X21vZGVsLCBuZXdkYXRhID0gbmV3X3dvcmtlciwgdHlwZSA9ICJ0ZXJtcyIpDQoNCmBgYA0KDQrwn5GJIMOdIG5naMSpYTogICANCg0KxJDDonkgbMOgIHBo4bqnbiDEkcOzbmcgZ8OzcCAoZWZmZWN0KSBj4bunYSB04burbmcgYmnhur9uIHbDoG8gZ2nDoSB0cuG7iyBsb2dpdCBk4buxIGLDoW8uICAgDQoNCkfhu5NtOiAgIA0KDQoqIEVmZmVjdCBj4bunYSBiaeG6v24gYHNleGAgPSBgMC4wOTQ5NDcyNmAgICANCiogSW50ZXJjZXB0IChjb25zdGFudCkgPSBgLTAuNTcwMTQyMWAgICANCg0KR2nhuqNpIHRow61jaCBj4bulIHRo4buDOiAgIA0KDQokJA0KXHRleHR7TG9naXR9KHApID0gXHRleHR7SW50ZXJjZXB0fSArIFx0ZXh0e0VmZmVjdCBj4bunYSBzZXh9DQokJA0KDQpD4buZbmcgbOG6oWk6ICAgDQoNCiQkDQotMC41NzAxNDIxICsgMC4wOTQ5NDcyNiA9IC0wLjQ3NTE5NDgNCiQkICAgDQoNCiRccmlnaHRhcnJvdyQgQ2jDrW5oIGzDoCBnacOhIHRy4buLIGB0eXBlID0gImxpbmsiYCBwaMOtYSB0csOqbi4gICANCg0KIyMgTcO0IGjDrG5oIGjhu5NpIHF1eSBwcm9iaXQgIA0KDQojIyMgQmnhur9uIHVuaW9uIHbDoCBiaeG6v24gc2V4DQoNCioqQ8OidSBo4buPaSBuZ2hpw6puIGPhu6l1OioqIFjDoWMgc3XhuqV0IG5nxrDhu51pIGxhbyDEkeG7mW5nIHThuqFpIEhvYSBr4buzIGzDoCBuZ8aw4budaSB0aGFtIGdpYSBjw7RuZyDEkW/DoG4gcGjhu6UgdGh14buZYyB2w6BvIGdp4bubaSB0w61uaCBsw6AgYmFvIG5oacOqdSA/ICAgDQoNCvCfk4wgVGjDoG5oIHBo4bqnbiBtw7QgaMOsbmg6ICAgDQoNCiogUmFuZG9tIGNvbXBvbmVudDogICANCiRZIFxzaW0gXHRleHR7QmVybm91bGxpfShwKSQgICANCg0KKiBTeXN0ZW1hdGljIGNvbXBvbmVudDogICANCiRcZXRhID0gXGJldGFfMCArIFxiZXRhXzEgXHRpbWVzIFx0ZXh0e3NleH0kICAgDQoNCiogTGluayBmdW5jdGlvbjogICANCiRnKHApID0gXFBoaV57LTF9KHApJCAgICAgIA0KDQrwn5OMIFBoxrDGoW5nIHRyw6xuaCBtw7QgaMOsbmg6ICAgDQoNCiQkDQpcUGhpXnstMX0ocF9pKSA9IFxiZXRhXzAgKyBcYmV0YV8xIFx0aW1lcyBcdGV4dHtzZXh9X2kNCiQkICAgDQoNClRyb25nIMSRw7M6ICAgDQoNCiogJFxQaGleey0xfSQgbMOgIGjDoG0gcGjDom4gcGjhu5FpIHTDrWNoIGzFqXkgY2h14bqpbiBuZ2jhu4tjaCDEkeG6o28gKGludmVyc2UgQ0RGKSAgIA0KKiBDw6FjIGvDvSBoaeG7h3Uga2jDoWMgbmjGsCBtw7QgaMOsbmggTG9naXN0aWMgKMOhcCBk4bulbmcgY2hvIHRyxrDhu51uZyBo4bujcCBuw6B5IGzDoCBtw7QgaMOsbmggUHJvYml0LCB24bubaSAkcF9pJCBsw6AgeMOhYyBzdeG6pXQgbmfGsOG7nWkgbGFvIMSR4buZbmcgdGjhu6kgJGkkIHRoYW0gZ2lhIGPDtG5nIMSRb8OgbiwgJFx0ZXh0e3NleH1faSQgbMOgIGJp4bq/biBnaeG7m2kgdMOtbmgsICRcYmV0YV8wJCBsw6AgaOG7hyBz4buRIGNo4bq3biB2w6AgJFxiZXRhXzEkIGzDoCBo4buHIHPhu5Eg4bqjbmggaMaw4bufbmcgY+G7p2EgZ2nhu5tpIHTDrW5oKS4gICANCg0KKiAqxq/hu5tjIGzGsOG7o25nIG3DtCBow6xuaDoqICAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCg0KcHJvYml0X21vZGVsIDwtIGdsbSh1bmlvbl9iaW4gfiBzZXgsIGRhdGEgPSBkLCBmYW1pbHkgPSBiaW5vbWlhbChsaW5rID0gInByb2JpdCIpKQ0Kc3VtbWFyeShwcm9iaXRfbW9kZWwpDQoNCmBgYA0KKlBoxrDGoW5nIHRyw6xuaCBo4buTaSBxdXkgcHJvYml0OiogICANCiQkDQpcUGhpXnstMX0ocF9pKSA9IC0wLjgwMjY1ICsgMC41MDYwNiBcdGltZXMgXHRleHR7c2V4fV9pDQokJA0KDQoqICpE4buxIGLDoW86KiAgIA0KDQoqKkThu7EgYsOhbyB24bubaSBgdHlwciA9IHJlc3BvbnNlYCoqICAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCm5ld193b3JrZXIgPC0gZGF0YS5mcmFtZShzZXggPSAibWFsZSIpDQpwcmVkaWN0KHByb2JpdF9tb2RlbCwgbmV3ZGF0YSA9IG5ld193b3JrZXIsIHR5cGUgPSAicmVzcG9uc2UiKQ0KYGBgDQoNCsOdIG5naMSpYTogICANCg0KKiBYw6FjIHN14bqldCB0aGFtIGdpYSBjw7RuZyDEkW/DoG4gbuG6v3UgbMOgIG5hbSBsw6AgMzguMzQlLg0KDQpO4bq/dSBxdXkgxrDhu5tjIG5nxrDhu6FuZyAwLjU6ICAgDQoNCiQkDQowLjM4MzQgPCAwLjUNCiQkICAgDQoNCiRccmlnaHRhcnJvdyQgROG7sSDEkW/DoW4ga2jDtG5nIHRoYW0gZ2lhIGPDtG5nIMSRb8Ogbi4gICAgDQoNCioqROG7sSBiw6FvIHbhu5tpIGB0eXBlID0gbGlua2AqKiAgIA0KDQpgYGB7cixlY2hvPVRSVUV9DQoNCm5ld193b3JrZXIgPC0gZGF0YS5mcmFtZShzZXggPSAibWFsZSIpDQpwcmVkaWN0KHByb2JpdF9tb2RlbCwgbmV3ZGF0YSA9IG5ld193b3JrZXIsIHR5cGUgPSAibGluayIpDQoNCmBgYA0KDQrDnSBuZ2jEqWE6ICAgDQoNCiogxJDDonkgbMOgIGxvZy1wcm9iaXQgKGludmVyc2UgQ0RGIGNodeG6qW4pIGThu7EgYsOhbyBjaG8gbmfGsOG7nWkgbmFtLiAgIA0KDQpOw7MgdMawxqFuZyDEkcawxqFuZzogICANCg0KJCQNClxQaGleey0xfShwX3tcdGV4dHtuYW19fSkgPSAtMC44MDI2NSArIDAuNTA2MDYgXHRpbWVzIDEgPSAtMC4yOTY1OTYxDQokJCAgIA0KDQokXHJpZ2h0YXJyb3ckIE7hur91IGLhuqFuIGzhuqV5ICRcUGhpKC0wLjI5NjYpIFxhcHByb3ggMC4zODM0JCAgIA0KDQokXFBoaSgtMC4yOTY2KSBcYXBwcm94IDAuMzgzNCQgxJHDum5nIHbhu5tpIGB0eXBlPSJyZXNwb25zZSJgICAgDQogDQoqKkThu7EgYsOhbyB24bubaSBgdHlwZT10ZXJtc2AqKiAgIA0KDQpgYGB7cixlY2hvPVRSVUV9DQoNCm5ld193b3JrZXIgPC0gZGF0YS5mcmFtZShzZXggPSAibWFsZSIpDQpwcmVkaWN0KHByb2JpdF9tb2RlbCwgbmV3ZGF0YSA9IG5ld193b3JrZXIsIHR5cGUgPSAidGVybXMiKQ0KDQpgYGANCg0Kw50gbmdoxKlhOiAgIA0KDQoqIEVmZmVjdCBj4bunYSBiaeG6v24gYHNleG1hbGVgIGzDoCBgKzAuMDU3YCAgIA0KKiBJbnRlcmNlcHQgKGNvbnN0YW50KSBsw6AgYC0wLjM1MzZgICAgDQoNClThu5VuZyBsb2ctcHJvYml0IGThu7EgYsOhbzogICANCg0KJCQNCi0wLjM1MzYgKyAwLjA1NyA9IC0wLjI5NjYNCiQkICAgDQoNCiMjIE3DtCBow6xuaCBo4buTaSBxdXkgY2xvZ2xvZyAgDQoNCiMjIyBCaeG6v24gdW5pb24gdsOgIGJp4bq/biBzZXgNCg0KKipDw6J1IGjhu49pIG5naGnDqm4gY+G7qXU6KiogWMOhYyBzdeG6pXQgbmfGsOG7nWkgbGFvIMSR4buZbmcgdOG6oWkgSG9hIGvhu7MgbMOgIG5nxrDhu51pIHRoYW0gZ2lhIGPDtG5nIMSRb8OgbiBwaOG7pSB0aHXhu5ljIHbDoG8gZ2nhu5tpIHTDrW5oIGzDoCBiYW8gbmhpw6p1ID8gICANCg0K8J+TjCBUaMOgbmggcGjhuqduIG3DtCBow6xuaDogICANCg0KKiBSYW5kb20gY29tcG9uZW50OiAgIA0KJFkgXHNpbSBcdGV4dHtCZXJub3VsbGl9KHApJCAgIA0KDQoqIFN5c3RlbWF0aWMgY29tcG9uZW50OiAgIA0KJFxldGEgPSBcYmV0YV8wICsgXGJldGFfMSBcdGltZXMgXHRleHR7c2V4fSQgICANCg0KKiBMaW5rIGZ1bmN0aW9uOiAgIA0KJGcocCkgPSBcbG9nKC1cbG9nKDEtcCkpJCAgICAgICAgIA0KDQrwn5OMIFBoxrDGoW5nIHRyw6xuaCBtw7QgaMOsbmg6ICAgDQoNCiQkDQpcbG9nIFxsZWZ0KCAtXGxvZygxLXBfaSkgXHJpZ2h0KSA9IFxiZXRhXzAgKyBcYmV0YV8xIFx0aW1lcyBcdGV4dHtzZXh9X2kNCiQkICAgICANCg0KKiAqxq/hu5tjIGzGsOG7o25nIG3DtCBow6xuaDoqICAgDQoNCmBgYHtyLGVjaG89VFJVRX0NCg0KY2xvZ2xvZ19tb2RlbCA8LSBnbG0odW5pb25fYmluIH4gc2V4LCBkYXRhID0gZCwgZmFtaWx5ID0gYmlub21pYWwobGluayA9ICJjbG9nbG9nIikpDQpzdW1tYXJ5KGNsb2dsb2dfbW9kZWwpDQoNCmBgYA0KDQoqICpE4buxIGLDoW86KiAgIA0KDQpgYGB7cixlY2hvPVRSVUV9DQpuZXdfd29ya2VyIDwtIGRhdGEuZnJhbWUoc2V4ID0gIm1hbGUiKQ0KcHJlZGljdChjbG9nbG9nX21vZGVsLCBuZXdkYXRhID0gbmV3X3dvcmtlciwgdHlwZSA9ICJyZXNwb25zZSIpDQpgYGANCg0KDQpgYGB7cixlY2hvPVRSVUV9DQoNCm5ld193b3JrZXIgPC0gZGF0YS5mcmFtZShzZXggPSAibWFsZSIpDQpwcmVkaWN0KGNsb2dsb2dfbW9kZWwsIG5ld2RhdGEgPSBuZXdfd29ya2VyLCB0eXBlID0gImxpbmsiKQ0KDQpgYGANCg0KDQpgYGB7cixlY2hvPVRSVUV9DQoNCm5ld193b3JrZXIgPC0gZGF0YS5mcmFtZShzZXggPSAibWFsZSIpDQpwcmVkaWN0KGNsb2dsb2dfbW9kZWwsIG5ld2RhdGEgPSBuZXdfd29ya2VyLCB0eXBlID0gInRlcm1zIikNCg0KYGBgDQoNCmBgYHtyLGVjaG89VFJVRX0NCg0KDQoNCmBgYA0K