1 Đọc dữ liệu

hoangtinhdulieu là bộ dữ liệu chứa thông tin tổng hợp về nhân khẩu học và đặc điểm kinh tế xã hội của khoảng 25.000 người đang sinh sống và làm việc tại Mỹ. Dữ liệu được xây dựng dựa trên nguồn gốc từ Current Population Survey (CPS) – một chương trình khảo sát dân số uy tín được thực hiện hàng năm bởi Cục điều tra dân số Hoa Kỳ (U.S. Census Bureau) phối hợp với Bureau of Labor Statistics.

Bộ dữ liệu đã được trích lọc, xử lý và tái cấu trúc nhằm phục vụ cho mục tiêu phân tích và huấn luyện mô hình học máy trong các nghiên cứu liên quan đến kinh tế học, hành vi lao động và bất bình đẳng thu nhập.

1.1 Đọc file

d <-read.csv(file.choose(), header=T)

Dòng lệnh d <- read.csv(file.choose(), header = TRUE) dùng để đọc dữ liệu từ một file CSV chọn trên máy tính.

  • file.choose() mở hộp thoại chọn file.
  • read.csv(...) đọc file CSV và trả về dạng bảng dữ liệu (data frame).
  • header = TRUE nghĩa là dòng đầu tiên của file là tên các cột.
  • Kết quả được lưu vào biến d để sử dụng cho các phân tích tiếp theo.

1.2 Hiển thị cấu trúc của dữ liệu

str(d)
## 'data.frame':    25998 obs. of  12 variables:
##  $ age                : int  21 33 19 41 52 49 32 28 54 43 ...
##  $ CensusWeight       : int  433330 278514 236940 112507 89041 189498 323055 31935 88019 69758 ...
##  $ learningLevel      : chr  "Some-college" "HS-grad" "HS-grad" "10th" ...
##  $ learningLevel.num  : int  10 9 9 6 9 9 9 10 10 12 ...
##  $ PartneringState    : chr  "Never-married" "Divorced" "Never-married" "Married-civ-spouse" ...
##  $ FamilyRole         : chr  "Unmarried" "Own-child" "Own-child" "Husband" ...
##  $ Ethnicity          : chr  "White" "White" "White" "White" ...
##  $ Gender             : chr  "Male" "Female" "Male" "Male" ...
##  $ NegativeCapitalFlow: int  0 0 0 0 0 0 0 0 0 0 ...
##  $ WeeklyHours        : int  40 42 40 60 40 50 40 40 55 40 ...
##  $ Nationality        : chr  "United-States" "United-States" "United-States" "United-States" ...
##  $ EarningClass       : chr  "<=50K" "<=50K" "<=50K" "<=50K" ...
  • str(...) là viết tắt của structure – dùng để kiểm tra nhanh thông tin về số dòng, số cột, tên biến và kiểu dữ liệu của từng biến.

  • Khi dùng str(d), bạn sẽ biết được:

  • d có bao nhiêu quan sát (rows) và biến (columns)

  • Tên của các biến

  • Kiểu dữ liệu của từng biến (vd: int, chr, factor, num…)

=> Dữ liệu bao gồm: 32561 quan sát và 12 biến, trong đó có 7 biến định tính

variable_explain <- data.frame(
  Ten_Bien = c("age", "CensusWeight", "learningLevel", "learningLevel.num", "PartneringState", 
               "FamilyRole", "Ethnicity", "Gender", "NegativeCapitalFlow", "WeeklyHours", 
               "Nationality", "EarningClass"),
  Y_Nghia = c(
"Độ tuổi của người được khảo sát",
"Đại diện của cá nhân trong mẫu điều tra dân số",
"Trình độ học vấn chính thức (ví dụ: Tốt nghiệp cấp 3, Đại học chưa hoàn thành)",
"Số năm học tập chính quy tương đương với trình độ học vấn",
"Tình trạng hôn nhân hiện tại (Đã kết hôn, Ly thân, Góa vợ/chồng...)",
"Vai trò trong hộ gia đình (ví dụ: Con cái, Không thuộc hộ gia đình)",
"Chủng tộc hoặc nhóm dân tộc (Người da trắng, Châu Á, v.v.)",
"Giới tính của cá nhân (Nam hoặc Nữ)",
"Mức lỗ tài sản phát sinh từ hoạt động đầu tư vốn",
"Số giờ làm việc trung bình trong một tuần",
"Quốc gia nơi cá nhân sinh sống hoặc khai báo là nơi sinh",
"Thu nhập cá nhân mỗi năm"
  )
)

library(knitr)
kable(variable_explain, caption = "Giải thích các biến trong bộ dữ liệu")
Giải thích các biến trong bộ dữ liệu
Ten_Bien Y_Nghia
age Độ tuổi của người được khảo sát
CensusWeight Đại diện của cá nhân trong mẫu điều tra dân số
learningLevel Trình độ học vấn chính thức (ví dụ: Tốt nghiệp cấp 3, Đại học chưa hoàn thành)
learningLevel.num Số năm học tập chính quy tương đương với trình độ học vấn
PartneringState Tình trạng hôn nhân hiện tại (Đã kết hôn, Ly thân, Góa vợ/chồng…)
FamilyRole Vai trò trong hộ gia đình (ví dụ: Con cái, Không thuộc hộ gia đình)
Ethnicity Chủng tộc hoặc nhóm dân tộc (Người da trắng, Châu Á, v.v.)
Gender Giới tính của cá nhân (Nam hoặc Nữ)
NegativeCapitalFlow Mức lỗ tài sản phát sinh từ hoạt động đầu tư vốn
WeeklyHours Số giờ làm việc trung bình trong một tuần
Nationality Quốc gia nơi cá nhân sinh sống hoặc khai báo là nơi sinh
EarningClass Thu nhập cá nhân mỗi năm
  • variable_explain <- data.frame(...) : Tạo một bảng dữ liệu (data frame) gồm 2 cột

  • Ten_Bien: Tên biến trong bộ dữ liệu.

  • Y_Nghia: Ý nghĩa mô tả của từng biến đó.

  • kable(variable_explain, caption = "Giải thích các biến"): Hàm kable() dùng để hiển thị bảng mô tả trên dưới dạng trình bày rõ ràng, dễ đọc.

  • caption = "Giải thích các biến" đặt tiêu đề cho bảng là “Giải thích các biến”.

1.3 Hiển thị một vài dòng đầu và cuối của dữ liệu

  • head(d): Hiển thị 6 dòng đầu của bộ dữ liệu
# Hiển thị 6 dòng đầu của bộ dữ liệu
head(d)
##   age CensusWeight learningLevel learningLevel.num    PartneringState
## 1  21       433330  Some-college                10      Never-married
## 2  33       278514       HS-grad                 9           Divorced
## 3  19       236940       HS-grad                 9      Never-married
## 4  41       112507          10th                 6 Married-civ-spouse
## 5  52        89041       HS-grad                 9 Married-civ-spouse
## 6  49       189498       HS-grad                 9 Married-civ-spouse
##   FamilyRole Ethnicity Gender NegativeCapitalFlow WeeklyHours   Nationality
## 1  Unmarried     White   Male                   0          40 United-States
## 2  Own-child     White Female                   0          42 United-States
## 3  Own-child     White   Male                   0          40 United-States
## 4    Husband     White   Male                   0          60 United-States
## 5    Husband     White   Male                   0          40 United-States
## 6    Husband     White   Male                   0          50 United-States
##   EarningClass
## 1        <=50K
## 2        <=50K
## 3        <=50K
## 4        <=50K
## 5        <=50K
## 6         >50K
  • tail(d): Hiển thị 6 dòng cuối của bộ dữ liệu
# Hiển thị 6 dòng cuối của bộ dữ liệu
tail(d)
##       age CensusWeight learningLevel learningLevel.num PartneringState
## 25993  34       216864       HS-grad                 9        Divorced
## 25994  41       264663  Some-college                10       Separated
## 25995  54       140359       7th-8th                 4        Divorced
## 25996  66       186061  Some-college                10         Widowed
## 25997  82       132870       HS-grad                 9         Widowed
## 25998  90        77053       HS-grad                 9         Widowed
##          FamilyRole Ethnicity Gender NegativeCapitalFlow WeeklyHours
## 25993     Unmarried     White Female                3770          45
## 25994     Own-child     White Female                3900          40
## 25995     Unmarried     White Female                3900          40
## 25996     Unmarried     Black Female                4356          40
## 25997 Not-in-family     White Female                4356          18
## 25998 Not-in-family     White Female                4356          40
##         Nationality EarningClass
## 25993 United-States        <=50K
## 25994 United-States        <=50K
## 25995 United-States        <=50K
## 25996 United-States        <=50K
## 25997 United-States        <=50K
## 25998 United-States        <=50K

1.4 Kiểm tra giá trị thiếu

sum(is.na(d))
## [1] 0
  • sum(is.na(d)): Kiểm tra tổng số giá trị NA trong toàn bộ bảng.

=> Kết quả: Trong bộ dữ liệu không có giá trị thiếu (NA).

1.5 Chuyển đổi các biến cần thiết

# Đọc dữ liệu
d <- read.csv("hoangtinhdulieu.csv")

# Danh sách các biến định tính (categorical variables)
cols_to_factor <- c("learningLevel", "PartneringState", "FamilyRole",
                    "Ethnicity", "Gender", "Nationality", "EarningClass")

# Chuyển các cột đó sang factor
d[cols_to_factor] <- lapply(d[cols_to_factor], as.factor)

# Kiểm tra lại cấu trúc dữ liệu
str(d)
## 'data.frame':    25998 obs. of  12 variables:
##  $ age                : int  21 33 19 41 52 49 32 28 54 43 ...
##  $ CensusWeight       : int  433330 278514 236940 112507 89041 189498 323055 31935 88019 69758 ...
##  $ learningLevel      : Factor w/ 16 levels "10th","11th",..: 16 12 12 1 12 12 12 16 16 8 ...
##  $ learningLevel.num  : int  10 9 9 6 9 9 9 10 10 12 ...
##  $ PartneringState    : Factor w/ 7 levels "Divorced","Married-AF-spouse",..: 5 1 5 3 3 3 3 1 1 3 ...
##  $ FamilyRole         : Factor w/ 6 levels "Husband","Not-in-family",..: 5 4 4 1 1 1 1 2 2 1 ...
##  $ Ethnicity          : Factor w/ 5 levels "Amer-Indian-Eskimo",..: 5 5 5 5 5 5 5 5 5 2 ...
##  $ Gender             : Factor w/ 2 levels "Female","Male": 2 1 2 2 2 2 2 1 2 2 ...
##  $ NegativeCapitalFlow: int  0 0 0 0 0 0 0 0 0 0 ...
##  $ WeeklyHours        : int  40 42 40 60 40 50 40 40 55 40 ...
##  $ Nationality        : Factor w/ 42 levels "?","Cambodia",..: 40 40 40 40 40 40 40 40 40 40 ...
##  $ EarningClass       : Factor w/ 2 levels "<=50K",">50K": 1 1 1 1 1 2 1 1 1 1 ...

Đầu tiên, cần xác định các biến có giá trị rời rạc và mang tính phân loại, thường dùng để biểu diễn thông tin định tính như giới tính, học vấn, tình trạng hôn nhân, v.v. Danh sách này sẽ được sử dụng để chuyển sang kiểu dữ liệu factor.

Sau đó, áp dụng hàm lapply(…, as.factor) để chuyển đổi từng biến trong danh sách thành kiểu factor.

Cuối cùng, cập nhật bảng dữ liệu d với các cột đã được chuyển đổi sang dạng phân loại.

Các biến định tính bao gồm:

learningLevel: biểu thị trình độ học vấn với 16 cấp độ khác nhau (ví dụ: HS-grad, Bachelors, Some-college…)

PartneringState: thể hiện tình trạng quan hệ như Married, Divorced, Widowed, Separated, Never-married

FamilyRole: mô tả vị trí của cá nhân trong hộ gia đình, như Own-child, Not-in-family, Husband, Wife…

Ethnicity: gồm 5 nhóm chủng tộc chính trong dữ liệu

Gender: 2 giá trị (Male, Female)

Nationality: quốc gia xuất xứ, với hơn 30 quốc gia (phần lớn là United-States)

EarningClass: phân loại thu nhập cá nhân thành 2 nhóm (<=50K, >50K)

2 Phân tích Mô tả Một biến Định tính

# Danh sách biến định tính thực tế trong file
tbdt <- c("learningLevel", "PartneringState", "FamilyRole",
          "Ethnicity", "Gender", "Nationality", "EarningClass")

# Tạo bảng con chỉ gồm các biến định tính
dq <- d[, tbdt]

# Kiểm tra
str(dq)
## 'data.frame':    25998 obs. of  7 variables:
##  $ learningLevel  : Factor w/ 16 levels "10th","11th",..: 16 12 12 1 12 12 12 16 16 8 ...
##  $ PartneringState: Factor w/ 7 levels "Divorced","Married-AF-spouse",..: 5 1 5 3 3 3 3 1 1 3 ...
##  $ FamilyRole     : Factor w/ 6 levels "Husband","Not-in-family",..: 5 4 4 1 1 1 1 2 2 1 ...
##  $ Ethnicity      : Factor w/ 5 levels "Amer-Indian-Eskimo",..: 5 5 5 5 5 5 5 5 5 2 ...
##  $ Gender         : Factor w/ 2 levels "Female","Male": 2 1 2 2 2 2 2 1 2 2 ...
##  $ Nationality    : Factor w/ 42 levels "?","Cambodia",..: 40 40 40 40 40 40 40 40 40 40 ...
##  $ EarningClass   : Factor w/ 2 levels "<=50K",">50K": 1 1 1 1 1 2 1 1 1 1 ...
  • Đây là danh sách (vector) chứa tên các cột – đều là biến định tính.

  • Lấy toàn bộ các cột trong danh sách tbdt từ bảng dữ liệu d, và tạo ra một bảng mới tên là dq.

=> Kết quả là bảng dq chỉ chứa các biến định tính.

2.1 Biến learningLevel

2.1.1 Giải thích biến

# Tạo bảng giải thích các mức của biến learningLevel
learningLevel_levels <- data.frame(
  Gia_tri = c("Preschool", "1st-4th", "5th-6th", "7th-8th", "9th", "10th",
              "11th", "12th", "HS-grad", "Some-college", "Assoc-acdm", 
              "Assoc-voc", "Bachelors", "Masters", "Prof-school", "Doctorate"),
  Y_nghia = c(
    "Trình độ mầm non",
    "Học hết lớp 1 đến lớp 4",
    "Học hết lớp 5 hoặc lớp 6",
    "Học hết lớp 7 hoặc lớp 8",
    "Học hết lớp 9",
    "Học hết lớp 10",
    "Học hết lớp 11",
    "Học hết lớp 12 nhưng không tốt nghiệp",
    "Tốt nghiệp trung học phổ thông (HS-grad)",
    "Học đại học/cao đẳng nhưng chưa có bằng",
    "Bằng cao đẳng học thuật (Associate in Academic Program)",
    "Bằng cao đẳng nghề (Associate in Vocational Program)",
    "Bằng cử nhân (Đại học)",
    "Bằng thạc sĩ",
    "Bằng chuyên ngành sau đại học (luật, y khoa…)",
    "Bằng tiến sĩ"
  )
)

# Hiển thị bảng
knitr::kable(learningLevel_levels, caption = "Giải thích các mức độ trong biến learningLevel")
Giải thích các mức độ trong biến learningLevel
Gia_tri Y_nghia
Preschool Trình độ mầm non
1st-4th Học hết lớp 1 đến lớp 4
5th-6th Học hết lớp 5 hoặc lớp 6
7th-8th Học hết lớp 7 hoặc lớp 8
9th Học hết lớp 9
10th Học hết lớp 10
11th Học hết lớp 11
12th Học hết lớp 12 nhưng không tốt nghiệp
HS-grad Tốt nghiệp trung học phổ thông (HS-grad)
Some-college Học đại học/cao đẳng nhưng chưa có bằng
Assoc-acdm Bằng cao đẳng học thuật (Associate in Academic Program)
Assoc-voc Bằng cao đẳng nghề (Associate in Vocational Program)
Bachelors Bằng cử nhân (Đại học)
Masters Bằng thạc sĩ
Prof-school Bằng chuyên ngành sau đại học (luật, y khoa…)
Doctorate Bằng tiến sĩ
  • learningLevel_levels <- data.frame(…): Tạo một bảng dữ liệu có hai cột: Gia_tri (giá trị gốc trong biến learningLevel) và Y_nghia (ý nghĩa tiếng Việt tương ứng).

  • Gia_tri = c(…): Tập hợp 16 mức trình độ học vấn được mã hoá trong dữ liệu, ví dụ “Preschool”, “Bachelors”, “Doctorate”…

  • Y_nghia = c(…): Cung cấp giải thích tiếng Việt cho từng mức trong Gia_tri. Ví dụ “Preschool” tương ứng với “Trình độ mầm non”, “Bachelors” là “Bằng cử nhân”…

  • knitr::kable(learningLevel_levels, caption = “Giải thích các mức độ trong biến learningLevel”): Dùng hàm kable() để in bảng ra đẹp hơn khi tạo báo cáo R Markdown. caption là tiêu đề hiển thị trên bảng.

2.1.2 Thống kê tần suất

# Tạo bảng tần suất cho learningLevel
ts_edu <- table(d$learningLevel)

# Tạo bảng dữ liệu
ts_edu_df <- data.frame(
  Gia_tri = names(ts_edu),
  Tan_so = as.vector(ts_edu),
  Ty_le = round((as.vector(ts_edu) / sum(ts_edu)) * 100, 2)
)

# Hiển thị kết quả
ts_edu_df
##         Gia_tri Tan_so Ty_le
## 1          10th    734  2.82
## 2          11th    926  3.56
## 3          12th    328  1.26
## 4       1st-4th    125  0.48
## 5       5th-6th    251  0.97
## 6       7th-8th    506  1.95
## 7           9th    401  1.54
## 8    Assoc-acdm    831  3.20
## 9     Assoc-voc   1104  4.25
## 10    Bachelors   4377 16.84
## 11    Doctorate    342  1.32
## 12      HS-grad   8360 32.16
## 13      Masters   1406  5.41
## 14    Preschool     37  0.14
## 15  Prof-school    482  1.85
## 16 Some-college   5788 22.26
  • Gia_tri = names(ts_edu): Lấy tên các mức giá trị (mức học vấn) từ bảng tần suất ts_edu, ví dụ: “Preschool”, “Bachelors”, “Doctorate”…

  • Tan_so = as.vector(ts_edu): Chuyển bảng tần suất thành vector để lưu số lượng xuất hiện của từng mức học vấn.

  • Ty_le = round((as.vector(ts_edu) / sum(ts_edu)) * 100, 2): Tính tỷ lệ phần trăm của mỗi mức học vấn so với tổng toàn bộ (dựa trên tần suất), rồi làm tròn đến 2 chữ số thập phân.

  • ts_edu_df: Hiển thị bảng kết quả ts_edu_df, gồm tên mức học vấn, tần suất và tỷ lệ phần trăm tương ứng.

Bộ dữ liệu này ghi nhận nhiều mức trình độ học vấn khác nhau của người tham gia. Trong đó:

3 mức đầu tiên gồm:

10th: 734 người (chiếm 2.82%),

11th: 926 người (chiếm 3.56%),

12th: 328 người (chiếm 1.26%).

3 mức cuối cùng gồm:

Some-college: 5788 người (chiếm 22.26%),

Preschool: 37 người (chiếm 0.14%),

Prof-school: 482 người (chiếm 1.85%).

2.1.3 Trực quan hóa

library(ggplot2)

# Vẽ biểu đồ cột cho biến learningLevel
ggplot(ts_edu_df, aes(x = reorder(Gia_tri, -Tan_so), y = Tan_so, fill = Gia_tri)) +
  geom_col(color = "white", width = 0.7) +
  geom_text(aes(label = Tan_so),
            vjust = -0.5, size = 4, fontface = "bold", color = "lightblue") +
  labs(
    title = "Biểu đồ cột: Phân bố trình độ học vấn (learningLevel)",
    x = "Trình độ học vấn",
    y = "Tần số"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

  • ```{r fig.width=12, fig.height=6}: Đây là phần mở đầu của một khối mã R trong R Markdown, thiết lập kích thước hình ảnh đầu ra: chiều rộng 12 đơn vị, chiều cao 6 đơn vị.

  • library(ggplot2): Nạp thư viện ggplot2 để sử dụng các hàm vẽ biểu đồ trong hệ thống đồ họa ggplot.

  • ggplot(ts_edu_df, aes(x = reorder(Gia_tri, -Tan_so), y = Tan_so, fill = Gia_tri)) : Khởi tạo biểu đồ cột từ bảng ts_edu_df. Trục x là biến Gia_tri (tên mức học vấn), được sắp xếp theo Tan_so giảm dần. Trục y là Tan_so. Màu sắc của từng cột được phân biệt theo Gia_tri.

  • geom_col(color = “white”, width = 0.7) : Vẽ các cột biểu đồ với viền trắng và độ rộng 0.7.

  • geom_text(aes(label = Tan_so), vjust = -0.5, size = 4, fontface = “bold”, color = “black”) : Thêm nhãn số liệu (giá trị tần số) trên đầu mỗi cột, canh chỉnh nhãn hơi cao hơn cột (vjust = -0.5), chữ đậm màu đen và cỡ 4.

  • labs(…) : Đặt tiêu đề biểu đồ là “Biểu đồ cột: Phân bố trình độ học vấn (learningLevel)”, trục x là “Trình độ học vấn” và trục y là “Tần số”.

  • theme_minimal(base_size = 12) : Áp dụng giao diện tối giản cho biểu đồ với cỡ chữ cơ bản là 12.

  • theme(…): Tuỳ chỉnh thêm cho biểu đồ:

  • plot.title = element_text(hjust = 0.5, face = “bold”): Căn giữa tiêu đề và in đậm.

  • axis.text.x = element_text(angle = 45, hjust = 1): Xoay nhãn trục x 45 độ, canh lề cho dễ đọc.

library(ggplot2)

# Vẽ biểu đồ cột cho tỷ lệ phần trăm trình độ học vấn
ggplot(ts_edu_df, aes(x = reorder(Gia_tri, -Ty_le), y = Ty_le, fill = Gia_tri)) +
  geom_col(color = "white", width = 0.7) +
  geom_text(aes(label = paste0(Ty_le, "%")),
            vjust = -0.5, size = 4, fontface = "bold", color = "lightblue") +
  labs(
    title = "Biểu đồ cột: Tỷ lệ trình độ học vấn (learningLevel)",
    x = "Trình độ học vấn",
    y = "Tỷ lệ (%)"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(angle = 45, hjust = 1)
  )

### Nhận xét

HS-grad (tốt nghiệp phổ thông) là trình độ học vấn phổ biến nhất với 10.501 người, chiếm ~32.3% tổng mẫu. Điều này cho thấy phần lớn người tham gia khảo sát chỉ dừng lại ở trình độ trung học.

Some-college (đã học đại học nhưng chưa tốt nghiệp) đứng thứ hai với 7.291 người, tương đương ~22.4%, phản ánh xu hướng khá nhiều người từng tiếp cận bậc học đại học nhưng không hoàn tất.

Bachelors (cử nhân) là trình độ học vấn đầy đủ cấp đại học phổ biến nhất với 5.355 người (~16.5%), cao hơn hẳn so với các trình độ sau đại học.

Các trình độ học vấn thấp như:

  • 11th (lớp 11) – 1.175 người

  • 10th (lớp 10) – 1.067 người

  • 7th-8th – 933 người

→ Những mức này cho thấy còn có một bộ phận dân số không hoàn thành bậc phổ thông.

Các cấp độ sau đại học như:

  • Masters (thạc sĩ) – 576 người (~1.8%)

  • Doctorate (tiến sĩ) – 413 người (~1.3%)

  • Prof-school (chuyên khoa như y, luật) – 514 người (~1.6%)

→ Tổng lại chỉ khoảng 1.500 người (~4.6%), chứng tỏ số người học cao học vẫn là thiểu số.

Các trình độ rất thấp như:

  • 1st-4th (lớp 1–4) – 168 người

  • Preschool (mẫu giáo) – 51 người

→ Cực kỳ hiếm gặp trong mẫu khảo sát (chưa đến 0.7% tổng số), thường thuộc nhóm người di cư hoặc cao tuổi.

Các trình độ ngắn hạn hoặc liên kết như:

  • Assoc-voc – 1.382 người

  • Assoc-acdm – 1.723 người

→ Chiếm khoảng 3.2% và 5.3% tương ứng, thể hiện mô hình giáo dục nghề/ngắn hạn có mặt nhưng không chiếm ưu thế.

2.2 Biến MaritalStatus

2.2.1 Giải thích biến

# Giải thích các mức của biến PartneringState
marital_levels <- data.frame(
  Gia_tri = c("Divorced", "Married-AF-spouse", "Married-civ-spouse",
              "Married-spouse-absent", "Never-married", "Separated", "Widowed"),
  Y_nghia = c(
    "Ly dị",
    "Kết hôn với người trong lực lượng vũ trang",
    "Đã kết hôn hợp pháp",
    "Kết hôn nhưng sống ly thân",
    "Chưa từng kết hôn",
    "Ly thân có pháp lý",
    "Góa"
  )
)

knitr::kable(marital_levels, caption = "Giải thích các mức trong biến PartneringState")
Giải thích các mức trong biến PartneringState
Gia_tri Y_nghia
Divorced Ly dị
Married-AF-spouse Kết hôn với người trong lực lượng vũ trang
Married-civ-spouse Đã kết hôn hợp pháp
Married-spouse-absent Kết hôn nhưng sống ly thân
Never-married Chưa từng kết hôn
Separated Ly thân có pháp lý
Widowed Góa

2.2.2 Thống kê Tần suất

# Tạo bảng tần suất cho PartneringState
ts_marital <- table(d$PartneringState)

# Tạo bảng dữ liệu
ts_marital_df <- data.frame(
  Gia_tri = names(ts_marital),
  Tan_so = as.vector(ts_marital),
  Ty_le = round((as.vector(ts_marital) / sum(ts_marital)) * 100, 2)
)

# Hiển thị kết quả
ts_marital_df
##                 Gia_tri Tan_so Ty_le
## 1              Divorced   3526 13.56
## 2     Married-AF-spouse     17  0.07
## 3    Married-civ-spouse  12115 46.60
## 4 Married-spouse-absent    334  1.28
## 5         Never-married   8398 32.30
## 6             Separated    812  3.12
## 7               Widowed    796  3.06
  • Đã ly dị (Divorced): có 3526 người (chiếm 13.56%).

  • Kết hôn với người trong quân đội (Married-AF-spouse): có 17 người (chiếm 0.07%).

  • Đã kết hôn hợp pháp (Married-civ-spouse): có 12115 người (chiếm 46.6%).

  • Ly thân (Married-spouse-absent): có 334 người (chiếm 1.28%).

  • Chưa từng kết hôn (Never-married): có 8398 người (chiếm 32.3%).

  • Ly thân có pháp lý (Separated): có 812 người (chiếm 3.12%).

  • Góa (Widowed): có 796 người (chiếm 3.06%).

2.2.3 Trực quan hóa

ggplot(ts_marital_df, aes(x = reorder(Gia_tri, -Tan_so), y = Tan_so, fill = Gia_tri)) +
  geom_col(width = 0.5, color = "pink") +
  geom_text(aes(label = Tan_so), vjust = -0.3, size = 4, fontface = "bold") +
  labs(
    title = "Biểu đồ cột: Tình trạng hôn nhân (PartneringState)",
    x = "Tình trạng hôn nhân",
    y = "Tần số"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(angle = 45, hjust = 1),
    
  )

ggplot(ts_marital_df, aes(x = reorder(Gia_tri, Ty_le), y = Ty_le, fill = Gia_tri)) +
  geom_col(width = 0.6, color = "lightpink") +
  geom_text(aes(label = paste0(Ty_le, "%")),
            hjust = -0.1, size = 4, fontface = "bold", color = "lightyellow") +
  coord_flip() +
  labs(
    title = "Biểu đồ cột ngang: Tỷ lệ tình trạng hôn nhân (PartneringState)",
    x = "Tình trạng hôn nhân",
    y = "Tỷ lệ (%)"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold")
  )

  • ggplot(ts_marital_df, aes(x = reorder(Gia_tri, Tan_so), y = Tan_so, fill = Gia_tri)) : Tạo biểu đồ cột từ bảng ts_marital_df. Trục hoành (x) là biến Gia_tri – các mức của tình trạng hôn nhân – được sắp xếp tăng dần theo Tan_so. Trục tung (y) là tần số tương ứng. Mỗi cột có màu khác nhau theo giá trị của Gia_tri.

  • geom_col(width = 0.6, color = “white”): Vẽ các cột với chiều rộng là 0.6 và viền màu trắng, giúp cột tách biệt rõ ràng.

  • geom_text(aes(label = Tan_so), hjust = -0.1, size = 4, fontface = “bold”, color = “black”) : Thêm nhãn số liệu (Tan_so) cho từng cột. Nhãn được đặt hơi lệch trái (hjust = -0.1), cỡ chữ 4, in đậm và màu đen.

  • coord_flip() : Lật hệ trục tọa độ để biểu đồ hiển thị theo chiều ngang – tức là các cột sẽ nằm ngang thay vì dọc.

  • labs(…) : Đặt tiêu đề biểu đồ là “Biểu đồ cột ngang: Tình trạng hôn nhân (PartneringState)”, trục x là “Tình trạng hôn nhân”, trục y là “Tần số”.

  • theme_minimal(base_size = 13) : Áp dụng giao diện tối giản (minimal) cho biểu đồ với cỡ chữ mặc định là 13.

  • theme(plot.title = element_text(hjust = 0.5, face = “bold”), …) Tuỳ chỉnh tiêu đề biểu đồ để căn giữa (hjust = 0.5) và in đậm (face = “bold”).

2.2.4 Nhận xét

  • “Married-civ-spouse” (kết hôn hợp pháp) chiếm 43.94%, cao nhất trong toàn bộ dữ liệu – cho thấy cấu trúc gia đình truyền thống vẫn chiếm ưu thế.

  • “Never-married” đạt 32.81%, là nhóm lớn thứ hai, phản ánh sự hiện diện mạnh mẽ của người độc thân.

  • Các nhóm còn lại như “Divorced” (12.29%), “Married-spouse-absent” (4.79%), “Separated” (3.13%), và “Widowed” (3.05%) góp phần tạo nên tính đa dạng trong tình trạng hôn nhân, nhưng đều chiếm tỷ lệ thấp hơn

2.3 Biến FamilyRole

2.3.1 Giải thích biến

# Giải thích các mức của biến FamilyRole
FamilyRole_levels <- data.frame(
  Gia_tri = c("Husband", "Not-in-family", "Other-relative", 
              "Own-child", "Unmarried", "Wife"),
  Y_nghia = c(
    "Chồng",
    "Không cùng gia đình (bạn trọ, bạn bè)",
    "Họ hàng khác (cháu, cô, chú...)",
    "Con ruột",
    "Không kết hôn (độc thân, ly dị...)",
    "Vợ"
  )
)

knitr::kable(FamilyRole_levels, caption = "Giải thích các mức trong biến FamilyRole")
Giải thích các mức trong biến FamilyRole
Gia_tri Y_nghia
Husband Chồng
Not-in-family Không cùng gia đình (bạn trọ, bạn bè)
Other-relative Họ hàng khác (cháu, cô, chú…)
Own-child Con ruột
Unmarried Không kết hôn (độc thân, ly dị…)
Wife Vợ

2.3.2 Thống kê Tần suất

# Tạo bảng tần suất cho FamilyRole
ts_FamilyRole <- table(d$FamilyRole)

# Tạo bảng dữ liệu
ts_FamilyRole_df <- data.frame(
  Gia_tri = names(ts_FamilyRole),
  Tan_so = as.vector(ts_FamilyRole),
  Ty_le = round((as.vector(ts_FamilyRole) / sum(ts_FamilyRole)) * 100, 2)
)

# Hiển thị kết quả
ts_FamilyRole_df
##          Gia_tri Tan_so Ty_le
## 1        Husband  10660 41.00
## 2  Not-in-family   6628 25.49
## 3 Other-relative    747  2.87
## 4      Own-child   3979 15.31
## 5      Unmarried   2702 10.39
## 6           Wife   1282  4.93
  • Biến FamilyRole (mối quan hệ trong hộ gia đình) bao gồm 6 mức như sau:

    • Không trong gia đình (Not-in-family): có 6628 người (chiếm 25.49%).
  • Họ hàng khác (Other-relative): có 747 người (chiếm 2.87%).

  • Con ruột (Own-child): có 3979 người (chiếm 15.31%).

  • Độc thân (Unmarried): có 2702 người (chiếm 10.39%).

  • Vợ (Wife): có 1282 người (chiếm 4.93%).

2.3.3 Trực quan hóa

ggplot(ts_FamilyRole_df, aes(x = reorder(Gia_tri, -Tan_so), y = Tan_so, fill = Gia_tri)) +
  geom_col(width = 0.5, color = "skyblue") +
  geom_text(aes(label = Tan_so), vjust = -0.3, size = 4, fontface = "bold") +
  labs(
    title = "Biểu đồ cột: Mối quan hệ trong hộ (FamilyRole)",
    x = "Mối quan hệ",
    y = "Tần số"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(angle = 45, hjust = 1),
  
  )

ggplot(ts_FamilyRole_df, aes(x = "", y = Ty_le, fill = Gia_tri)) +
  geom_col(width = 1, color = "skyblue") +
  coord_polar(theta = "y") +
  scale_fill_brewer(palette = "Set2") +
  labs(title = "Biểu đồ tròn: Mối quan hệ trong hộ") +
  geom_text(aes(label = paste0(Ty_le, "%")),
            position = position_stack(vjust = 0.5),
            size = 4, color = "pink") +
  theme_void() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.title = element_blank()
  )

  • coord_polar(theta = “y”) : Chuyển biểu đồ cột thành biểu đồ tròn bằng cách sử dụng hệ tọa độ cực (polar coordinate system), trong đó phần trăm (Ty_le) được xoay theo trục y để tạo ra các phần hình quạt.

  • scale_fill_brewer(palette = “Set2”) : Áp dụng bảng màu “Set2” từ thư viện RColorBrewer để phân biệt trực quan các phần khác nhau của biểu đồ tròn bằng các màu sắc hài hòa.

  • theme_void() : Xóa tất cả thành phần nền của biểu đồ (trục, lưới, nhãn trục…), giúp biểu đồ tròn trông gọn gàng và nổi bật hơn.

  • legend.title = element_blank(): Ẩn tiêu đề của phần chú giải (legend) để giao diện biểu đồ trở nên đơn giản và dễ đọc hơn.

2.3.4 Nhận xét

  • Nhóm “Husband” chiếm tỷ lệ cao nhất với 38.1%, phản ánh vai trò trụ cột của nam giới trong hộ gia đình vẫn còn phổ biến. Điều này có thể liên quan đến thói quen khai báo người đứng đầu hộ là nam giới.

  • “Not-in-family” xếp thứ hai với 26.4%, cho thấy có nhiều cá nhân sống độc lập hoặc không thuộc hộ truyền thống – phản ánh xu hướng sống đơn thân trong xã hội hiện đại.

  • “Own-child” chiếm 15.7%, cho thấy tỷ lệ người phụ thuộc đáng kể trong hộ, trong khi “Wife” chỉ đạt 7.2%, có thể do nam giới là người được khảo sát nhiều hơn.

  • Các nhóm “Unmarried” (11.2%) và “Other-relative” (1.4%) có tỷ lệ thấp, nhưng góp phần làm rõ tính đa dạng trong cấu trúc hộ gia đình hiện nay. ## Biến Ethnicity

2.3.5 Giải thích biến

# Giải thích các mức của biến Ethnicity
Ethnicity_levels <- data.frame(
  Gia_tri = c("Amer-Indian-Eskimo", "Asian-Pac-Islander", "Black", "Other", "White"),
  Y_nghia = c(
    "Người da đỏ/Thổ dân Bắc Mỹ",
    "Người châu Á hoặc dân đảo Thái Bình Dương",
    "Người da đen",
    "Khác",
    "Người da trắng"
  )
)

knitr::kable(Ethnicity_levels, caption = "Giải thích các mức trong biến Ethnicity")
Giải thích các mức trong biến Ethnicity
Gia_tri Y_nghia
Amer-Indian-Eskimo Người da đỏ/Thổ dân Bắc Mỹ
Asian-Pac-Islander Người châu Á hoặc dân đảo Thái Bình Dương
Black Người da đen
Other Khác
White Người da trắng

2.3.6 Thống kê Tần suất

# Tạo bảng tần suất cho Ethnicity
ts_Ethnicity <- table(d$Ethnicity)

# Tạo bảng dữ liệu
ts_Ethnicity_df <- data.frame(
  Gia_tri = names(ts_Ethnicity),
  Tan_so = as.vector(ts_Ethnicity),
  Ty_le = round((as.vector(ts_Ethnicity) / sum(ts_Ethnicity)) * 100, 2)
)

# Hiển thị kết quả
ts_Ethnicity_df
##              Gia_tri Tan_so Ty_le
## 1 Amer-Indian-Eskimo    245  0.94
## 2 Asian-Pac-Islander    805  3.10
## 3              Black   2451  9.43
## 4              Other    221  0.85
## 5              White  22276 85.68
  • Biến Ethnicity (chủng tộc) có 5 nhóm như sau:

    • Người da đỏ/Thổ dân Bắc Mỹ (Amer-Indian-Eskimo): 245 người (chiếm 0.94%).
  • Người châu Á/Thái Bình Dương (Asian-Pac-Islander): 805 người (chiếm 3.1%).

  • Người da đen (Black): 2451 người (chiếm 9.43%).

  • Khác (Other): 221 người (chiếm 0.85%).

  • Người da trắng (White): 22276 người (chiếm 85.68%).

2.3.7 Trực quan hóa

ggplot(ts_Ethnicity_df, aes(x = reorder(Gia_tri, -Tan_so), y = Tan_so, fill = Gia_tri)) +
  geom_col(width = 0.5, color = "lightgreen") +
  geom_text(aes(label = Tan_so), vjust = -0.3, size = 4, fontface = "bold") +
  labs(
    title = "Biểu đồ cột: Chủng tộc (Ethnicity)",
    x = "Chủng tộc",
    y = "Tần số"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(angle = 45, hjust = 1),
    
  )

ggplot(ts_Ethnicity_df, aes(x = reorder(Gia_tri, Ty_le), y = Ty_le, fill = Gia_tri)) +
  geom_col(width = 0.6, color = "white") +
  geom_text(aes(label = paste0(Ty_le, "%")), 
            hjust = -0.1, size = 4, fontface = "bold", color = "purple") +
  coord_flip() +
  scale_fill_brewer(palette = "Dark2") +
  labs(
    title = "Biểu đồ cột ngang: Tỷ lệ chủng tộc (Ethnicity)",
    x = "Chủng tộc",
    y = "Tỷ lệ (%)"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    
  )

2.3.8 Nhận xét

  • “White” là nhóm chiếm đa số áp đảo với 27.191 người (83.54%), thể hiện sự thống trị về số lượng trong mẫu khảo sát.

  • “Black” chiếm 2.830 người (8.69%), là nhóm thiểu số lớn nhất sau người da trắng.

  • Các nhóm “Asian-Pac-Islander”, “Amer-Indian-Eskimo”, và “Other” lần lượt có tỷ lệ thấp hơn nhiều, mỗi nhóm dưới 3%, cho thấy tính đa dạng chủng tộc có nhưng chưa thật sự cân bằng.

2.4 Biến Nationality

2.4.1 Giải thích biến

# Giải thích một số mức phổ biến trong biến Nationality
# (Nếu cần giải thích toàn bộ có thể mở rộng thêm)
country_levels <- data.frame(
  Gia_tri = c("United-States", "Mexico", "Philippines", "Vietnam", "Germany"),
  Y_nghia = c(
    "Hoa Kỳ",
    "Mexico",
    "Philippines",
    "Việt Nam",
    "Đức"
  )
)

knitr::kable(country_levels, caption = "Giải thích một số mức phổ biến trong biến Nationality")
Giải thích một số mức phổ biến trong biến Nationality
Gia_tri Y_nghia
United-States Hoa Kỳ
Mexico Mexico
Philippines Philippines
Vietnam Việt Nam
Germany Đức

2.4.2 Thống kê Tần suất

# Tạo bảng tần suất cho Nationality
ts_country <- table(d$Nationality)

# Tạo bảng dữ liệu
ts_country_df <- data.frame(
  Gia_tri = names(ts_country),
  Tan_so = as.vector(ts_country),
  Ty_le = round((as.vector(ts_country) / sum(ts_country)) * 100, 2)
)

# Hiển thị kết quả
ts_country_df
##                       Gia_tri Tan_so Ty_le
## 1                           ?    466  1.79
## 2                    Cambodia     16  0.06
## 3                      Canada    101  0.39
## 4                       China     61  0.23
## 5                    Columbia     48  0.18
## 6                        Cuba     75  0.29
## 7          Dominican-Republic     54  0.21
## 8                     Ecuador     19  0.07
## 9                 El-Salvador     77  0.30
## 10                    England     75  0.29
## 11                     France     22  0.08
## 12                    Germany    109  0.42
## 13                     Greece     24  0.09
## 14                  Guatemala     52  0.20
## 15                      Haiti     39  0.15
## 16         Holand-Netherlands      1  0.00
## 17                   Honduras      8  0.03
## 18                       Hong     12  0.05
## 19                    Hungary     11  0.04
## 20                      India     76  0.29
## 21                       Iran     36  0.14
## 22                    Ireland     19  0.07
## 23                      Italy     57  0.22
## 24                    Jamaica     61  0.23
## 25                      Japan     50  0.19
## 26                       Laos      8  0.03
## 27                     Mexico    499  1.92
## 28                  Nicaragua     25  0.10
## 29 Outlying-US(Guam-USVI-etc)      8  0.03
## 30                       Peru     23  0.09
## 31                Philippines    157  0.60
## 32                     Poland     53  0.20
## 33                   Portugal     28  0.11
## 34                Puerto-Rico     97  0.37
## 35                   Scotland     10  0.04
## 36                      South     65  0.25
## 37                     Taiwan     43  0.17
## 38                   Thailand     15  0.06
## 39            Trinadad&Tobago     12  0.05
## 40              United-States  23322 89.71
## 41                    Vietnam     53  0.20
## 42                 Yugoslavia     11  0.04
  • Biến Nationality (quốc gia xuất thân) có nhiều mức, dưới đây là một số mức phổ biến:

  • Hoa Kỳ (United-States): 23322 người (chiếm 89.71%).

  • Mexico: 499 người (chiếm 1.92%).

  • Philippines: 157 người (chiếm 0.6%).

  • Việt Nam: 53 người (chiếm 0.2%).

  • Đức (Germany): 109 người (chiếm 0.42%).

2.4.3 Trực quan hóa

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
top_country <- ts_country_df %>% 
  arrange(desc(Tan_so)) %>% 
  slice(1:10)

ggplot(top_country, aes(x = reorder(Gia_tri, -Tan_so), y = Tan_so, fill = Gia_tri)) +
  geom_col(width = 0.5, color = "lightblue") +
  geom_text(aes(label = Tan_so), vjust = -0.3, size = 4, fontface = "bold") +
  labs(
    title = "Biểu đồ cột: 10 quốc gia phổ biến (Nationality)",
    x = "Quốc gia",
    y = "Tần số"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    axis.text.x = element_text(angle = 45, hjust = 1),
    
  )

library(dplyr)
library(ggplot2)

# Lấy top 10 quốc gia có tỷ lệ cao nhất
top_country <- ts_country_df %>% 
  arrange(desc(Ty_le)) %>% 
  slice(1:10)

# Vẽ biểu đồ
ggplot(top_country, aes(x = reorder(Gia_tri, Ty_le), y = Ty_le, fill = Gia_tri)) +
  geom_col(width = 0.6, color = "lightpink") +
  geom_text(aes(label = paste0(Ty_le, "%")), hjust = -0.1, size = 4, fontface = "bold") +
  coord_flip() +
  labs(
    title = "Biểu đồ cột ngang: Tỷ lệ 10 quốc gia phổ biến nhất (Nationality)",
    x = "Quốc gia",
    y = "Tỷ lệ (%)"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold")
  )

2.4.4 Nhận xét

  • “United-States” chiếm áp đảo với 89.59%, cho thấy phần lớn đối tượng khảo sát sống tại hoặc xuất thân từ Hoa Kỳ – phù hợp với việc dữ liệu này được thu thập từ hệ thống thống kê dân số Mỹ.

  • “Mexico” đứng thứ hai với 1.97%, là quốc gia gốc phổ biến tiếp theo, phản ánh sự hiện diện đáng kể của người nhập cư từ Mexico.

  • “Philippines” và “Germany” lần lượt chiếm 0.61% và 0.42%, là các quốc gia gốc ít phổ biến hơn.

  • Đặc biệt, có tới 1.79% giá trị là dấu hỏi “?” – nhiều khả năng là dữ liệu thiếu hoặc không xác định.

2.5 Biến Gender

2.5.1 Giải thích biến

# Giải thích các mức của biến Gender
Gender_levels <- data.frame(
  Gia_tri = c("Female", "Male"),
  Y_nghia = c("Nữ", "Nam")
)

knitr::kable(Gender_levels, caption = "Giải thích các mức trong biến Gender")
Giải thích các mức trong biến Gender
Gia_tri Y_nghia
Female Nữ
Male Nam

2.5.2 Thống kê Tần suất

# Tạo bảng tần suất cho Gender
ts_Gender <- table(d$Gender)

# Tạo bảng dữ liệu
ts_Gender_df <- data.frame(
  Gia_tri = names(ts_Gender),
  Y_nghia = c("Nam", "Nữ"),  # Male, Female
  Tan_so = as.vector(ts_Gender),
  Ty_le = round((as.vector(ts_Gender) / sum(ts_Gender)) * 100, 2)
)

# Hiển thị kết quả
ts_Gender_df
##   Gia_tri Y_nghia Tan_so Ty_le
## 1  Female     Nam   8515 32.75
## 2    Male      Nữ  17483 67.25
  • Biến Gender (giới tính) bao gồm 2 mức:

    • Nữ (Female): 8515 người (chiếm 32.75%).
  • Nam (Male): 17483 người (chiếm 67.25%).

2.5.3 Trực quan hóa

ggplot(ts_Gender_df, aes(x = Gia_tri, y = Tan_so, fill = Gia_tri)) +
  geom_col(width = 0.5, color = "white") +
  geom_text(aes(label = Tan_so), vjust = -0.3, size = 4, fontface = "bold") +
  labs(
    title = "Biểu đồ cột: Giới tính (Gender)",
    x = "Giới tính",
    y = "Tần số"
  ) +
  scale_fill_manual(values = c("#FF8", "skyblue")) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
  
  )

Gender_colors <- c("Female" = "#FFB6C1", "Male" = "#87CEFA")  # màu tuỳ chỉnh

ggplot(ts_Gender_df, aes(x = "", y = Ty_le, fill = Gia_tri)) +
  geom_col(width = 1, color = "red") +
  coord_polar(theta = "y") +
  scale_fill_manual(values = Gender_colors) +
  labs(title = "Biểu đồ tròn: Giới tính") +
  geom_text(aes(label = paste0(Ty_le, "%")),
            position = position_stack(vjust = 0.5),
            size = 5, color = "blue") +
  theme_void() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.title = element_blank()
  )

2.5.4 Nhận xét

  • “Male” chiếm 66.94%, cao hơn rõ rệt so với “Female” (33.06%), cho thấy dữ liệu khảo sát có thể nghiêng về phía nam giới – do đặc điểm chọn mẫu hoặc tỉ lệ tham gia khảo sát.

2.6 Biến EarningClass

2.6.1 Giải thích biến

# Giải thích các mức của biến EarningClass
EarningClass_levels <- data.frame(
  Gia_tri = c("<=50K", ">50K"),
  Y_nghia = c("Thu nhập dưới hoặc bằng 50.000 USD/năm", "Thu nhập trên 50.000 USD/năm")
)

knitr::kable(EarningClass_levels, caption = "Giải thích các mức trong biến EarningClass")
Giải thích các mức trong biến EarningClass
Gia_tri Y_nghia
<=50K Thu nhập dưới hoặc bằng 50.000 USD/năm
>50K Thu nhập trên 50.000 USD/năm

2.6.2 Thống kê Tần suất

# Tạo bảng tần suất cho EarningClass
ts_EarningClass <- table(d$EarningClass)

# Tạo bảng dữ liệu
ts_EarningClass_df <- data.frame(
  Gia_tri = names(ts_EarningClass),
  Y_nghia = c("≤50K", ">50K"),
  Tan_so = as.vector(ts_EarningClass),
  Ty_le = round((as.vector(ts_EarningClass) / sum(ts_EarningClass)) * 100, 2)
)

# Hiển thị kết quả
ts_EarningClass_df
##   Gia_tri Y_nghia Tan_so Ty_le
## 1   <=50K    ≤50K  19415 74.68
## 2    >50K    >50K   6583 25.32
  • Biến EarningClass (thu nhập) có 2 mức:

    • Thu nhập dưới hoặc bằng 50K (<=50K): 19415 người (chiếm 74.68%).
  • Thu nhập trên 50K (>50K): 6583 người (chiếm 25.32%).

2.6.3 Trực quan hóa

ggplot(ts_EarningClass_df, aes(x = Gia_tri, y = Tan_so, fill = Gia_tri)) +
  geom_col(width = 0.5, color = "white") +
  geom_text(aes(label = Tan_so), vjust = -0.3, size = 4, fontface = "bold") +
  labs(
    title = "Biểu đồ cột: Thu nhập (EarningClass)",
    x = "Nhóm thu nhập",
    y = "Tần số"
  ) +
  scale_fill_manual(values = c("#6D597A", "#FFB703")) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    
  )

EarningClass_colors <- c("<=50K" = "#FDB863", ">50K" = "#5E3C99")

ggplot(ts_EarningClass_df, aes(x = "", y = Ty_le, fill = Gia_tri)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  scale_fill_manual(values = EarningClass_colors) +
  labs(title = "Biểu đồ tròn: Thu nhập") +
  geom_text(aes(label = paste0(Ty_le, "%")),
            position = position_stack(vjust = 0.5),
            size = 5, color = "black") +
  theme_void() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.title = element_blank()
  )

2.6.4 Nhận xét

  • Nhóm có thu nhập <=50K chiếm 75.92%, cho thấy phần lớn người trong mẫu khảo sát có thu nhập thấp hơn ngưỡng trung bình.

  • Chỉ 24.08% thuộc nhóm thu nhập >50K, phản ánh mức thu nhập cao là thiểu số trong cộng đồng được khảo sát.

3 Ước lượng Khoảng và Kiểm định Giả thuyết cho Tỷ lệ

3.1 Xác định Hạng mục Quan tâm

Ta chọn 3 hạng mục từ 3 biến trong danh sách các biến định tính, bao gồm:

  • Hạng mục “Never-married” của biến MaritalStatus – Tình trạng hôn nhân

  • Hạng mục “Male” của biến Gender – Giới tính

  • Hạng mục “Bachelors” của biến learningLevel – Trình độ học vấn

3.2 Ước lượng Khoảng Tin cậy và Kiểm định Giả thuyết

Ước lượng tỷ lệ (Proportion Estimation)

Ước lượng tỷ lệ là quá trình sử dụng dữ liệu từ một mẫu để suy luận về tỷ lệ tương ứng trong tổng thể. Trong thống kê mô tả, tỷ lệ mẫu (ký hiệu thường là p̂) được tính bằng số lượng các phần tử thỏa điều kiện chia cho tổng số phần tử trong mẫu. Đây được gọi là ước lượng điểm (point estimate) cho tỷ lệ tổng thể p. Tuy nhiên, do tính ngẫu nhiên của việc chọn mẫu, ước lượng điểm không thể đảm bảo phản ánh chính xác tỷ lệ thực sự trong tổng thể, do đó cần đi kèm với một khoảng tin cậy để đo lường độ bất định.

Khoảng tin cậy

Khoảng tin cậy là một khoảng giá trị cho ta biết giá trị thật của một tỷ lệ hay trung bình trong tổng thể có khả năng nằm trong khoảng đó. Nó được tính từ dữ liệu mẫu, và đi kèm với một mức độ tin tưởng – thường là 95%.

Mức ý nghĩa (Significance Level – α)

Mức ý nghĩa, ký hiệu là α (alpha), là xác suất chấp nhận sai lầm loại I – tức là xác suất bác bỏ giả thuyết không (H₀) khi nó thực sự đúng. Trong kiểm định giả thuyết thống kê, mức ý nghĩa thể hiện ngưỡng mà tại đó ta quyết định có bác bỏ H₀ hay không. Mức ý nghĩa phổ biến nhất là α = 0.05, nghĩa là ta chấp nhận 5% rủi ro cho việc kết luận sai. Kết quả kiểm định thường được đánh giá thông qua p-value, và so sánh với α để đưa ra quyết định:

Nếu p-value < α → bác bỏ H₀ (có bằng chứng thống kê).

Nếu p-value ≥ α → không bác bỏ H₀ (không đủ bằng chứng thống kê).

3.2.1 Hạng mục “Bachelors” của biến Trình độ học vấn (learningLevel)

Ta thực hiện khoảng ước lượng với độ tin cậy 95% cho tỷ lệ người có bằng cử nhân (Bachelors), ta thực hiện như sau:

# Số người có trình độ Bachelors
n_bachelors <- sum(d$learningLevel == "Bachelors")

# Tổng số quan sát
n_total <- nrow(d)

# Ước lượng khoảng tin cậy 95% cho tỷ lệ người có trình độ Bachelors
prop.test(n_bachelors, n_total, conf.level = 0.95)
## 
##  1-sample proportions test with continuity correction
## 
## data:  n_bachelors out of n_total, null probability 0.5
## X-squared = 11436, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
##  0.1638407 0.1729759
## sample estimates:
##         p 
## 0.1683591
  • n_bachelors <- sum(d$learningLevel == “Bachelors”): Tính tổng số người có trình độ học vấn là “Bachelors” (cử nhân) trong dữ liệu d, bằng cách đếm số dòng có giá trị “Bachelors” trong biến learningLevel.

  • n_total <- nrow(d): Lấy tổng số quan sát trong bộ dữ liệu d, tức là số hàng của bảng dữ liệu – dùng để làm mẫu số trong tính toán tỷ lệ.

  • prop.test(n_bachelors, n_total, conf.level = 0.95): Thực hiện phép ước lượng khoảng tin cậy cho tỷ lệ người có trình độ cử nhân, với độ tin cậy 95%. Hàm prop.test() trả về khoảng tin cậy và kiểm định giả thuyết tỷ lệ (nếu cần).

Phân tích kết quả

  • Phép kiểm định được thực hiện là kiểm định tỷ lệ 1 mẫu (1-sample proportion test) với chỉnh liên tục (continuity correction) – giúp cải thiện độ chính xác khi sử dụng phân phối xấp xỉ.

  • Dữ liệu đầu vào là số người có trình độ “Bachelors” (n_bachelors) trong tổng số quan sát (n_total). Giả thuyết gốc (H₀) giả định rằng tỷ lệ thực sự p = 0.5 (tức 50% dân số có bằng cử nhân).

  • Giá trị thống kê kiểm định là X-squared = 14662, với df = 1 (1 bậc tự do). Giá trị này rất lớn, cho thấy có sự khác biệt đáng kể giữa tỷ lệ mẫu và tỷ lệ giả định.

  • Giá trị p-value < 2.2e-16, tức là xác suất để quan sát được dữ liệu này nếu giả thuyết H₀ đúng là gần bằng 0. → Kết quả có ý nghĩa thống kê rất mạnh mẽ.

  • Giả thuyết đối (H₁) là: tỷ lệ thực tế p khác 0.5. Đây là kiểm định hai phía, kiểm tra xem tỷ lệ có khác (lớn hơn hoặc nhỏ hơn) so với 50%.

  • Khoảng tin cậy 95% cho tỷ lệ người có trình độ Bachelors nằm trong khoảng [16.05%; 16.85%], nghĩa là ta có thể tin rằng tỷ lệ thật sự trong tổng thể rơi vào khoảng này.

  • Tỷ lệ mẫu ước lượng được là 16.45%, tỷ lệ này tương đương với khoảng 16 người có bằng cử nhân trên mỗi 100 người trong dữ liệu. – thấp hơn rất nhiều so với mức 50% giả định ban đầu.

Bài toán kiểm định:

Giả thuyết kiểm định:

Giả thuyết không H₀: p = 0.5 (tỷ lệ người có bằng cử nhân bằng 50%)

Giả thuyết đối H₁: p ≠ 0.5 (tỷ lệ người có bằng cử nhân khác 50%)

Mức ý nghĩa: α = 0.05

Kết luận:

Với p-value < 2.2e-16 < 0.05, ta bác bỏ giả thuyết H₀.

Có bằng chứng thống kê cho thấy tỷ lệ người có bằng cử nhân khác 50%, với độ tin cậy 95%.

Tỷ lệ mẫu là 16.45%, với khoảng tin cậy nằm trong [16.05%; 16.85%]. Mức chênh lệch hơn 33 điểm phần trăm so với 50% cho thấy sự khác biệt là rõ ràng và có ý nghĩa thống kê.

3.2.2 Hạng mục “Never-married” của biến Tình trạng hôn nhân (PartneringState)

# Số người chưa từng kết hôn
n_never_married <- sum(d$PartneringState == "Never-married")

# Tổng số quan sát
n_total <- nrow(d)

# Ước lượng khoảng tin cậy 95% cho tỷ lệ người chưa từng kết hôn
prop.test(n_never_married, n_total, conf.level = 0.95)
## 
##  1-sample proportions test with continuity correction
## 
## data:  n_never_married out of n_total, null probability 0.5
## X-squared = 3256.3, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
##  0.3173478 0.3287543
## sample estimates:
##         p 
## 0.3230248

Phân tích kết quả

  • Phép kiểm định được sử dụng là kiểm định tỷ lệ 1 mẫu (1-sample proportions test) với chỉnh liên tục, nhằm cải thiện độ chính xác khi sử dụng phân phối xấp xỉ.

  • Dữ liệu đầu vào: đang kiểm định tỷ lệ người có tình trạng “Never-married” (n_never_married) trong tổng số quan sát (n_total), với giả thuyết gốc H₀: p = 0.5.

  • Giá trị thống kê kiểm định là X-squared = 3848.3 với df = 1, cho thấy mức độ chênh lệch lớn giữa tỷ lệ quan sát và tỷ lệ giả định.

  • Giá trị p-value < 2.2e-16, cực kỳ nhỏ, đồng nghĩa với việc kết quả là rất có ý nghĩa thống kê – xác suất xảy ra sai lầm khi bác bỏ H₀ gần như bằng 0.

  • Giả thuyết đối (H₁): Tỷ lệ thực sự khác 0.5 (kiểm định hai phía: khác lớn hơn hoặc nhỏ hơn đều được xem xét).

  • Khoảng tin cậy 95% cho tỷ lệ người chưa kết hôn nằm trong khoảng [32.30%; 33.32%], thể hiện tỷ lệ thực sự khá ổn định quanh mức 33%.

  • Tỷ lệ mẫu ước lượng là 32.81%, tức là gần 1/3 dân số trong mẫu khảo sát chưa từng kết hôn.

Bài toán kiểm định:

Giả thuyết kiểm định:

Giả thuyết không H₀: p = 0.5 (tỷ lệ người chưa từng kết hôn bằng 50%)

Giả thuyết đối H₁: p ≠ 0.5 (tỷ lệ người chưa từng kết hôn khác 50%)

Mức ý nghĩa: α = 0.05

Kết luận:

Với p-value < 2.2e-16 < 0.05, ta bác bỏ giả thuyết H₀.

Có bằng chứng thống kê mạnh cho thấy tỷ lệ người chưa từng kết hôn khác 50%, với độ tin cậy 95%.

Tỷ lệ ước lượng là 32.81%, với khoảng tin cậy nằm trong [32.30%; 33.32%]. Tỷ lệ này thấp hơn đáng kể so với mức 50%, và sự chênh lệch (~17 điểm phần trăm) là có ý nghĩa thống kê rõ rệt.

3.2.3 Hạng mục “Male” của biến Giới tính (Gender)

# Số người là nam giới
n_male <- sum(d$Gender == "Male")

# Tổng số quan sát
n_total <- nrow(d)

# Ước lượng khoảng tin cậy 95% cho tỷ lệ nam giới
prop.test(n_male, n_total, conf.level = 0.95)
## 
##  1-sample proportions test with continuity correction
## 
## data:  n_male out of n_total, null probability 0.5
## X-squared = 3092.8, df = 1, p-value < 2.2e-16
## alternative hypothesis: true p is not equal to 0.5
## 95 percent confidence interval:
##  0.6667256 0.6781729
## sample estimates:
##         p 
## 0.6724748

Phân tích kết quả

  • Phép kiểm định được sử dụng là kiểm định tỷ lệ 1 mẫu với chỉnh liên tục, nhằm đảm bảo kết quả chính xác hơn với dữ liệu rời rạc.

  • Dữ liệu đầu vào: đang xét tỷ lệ người là “Male” trong tổng số quan sát, với giả thuyết gốc H₀: p = 0.5 (tức giả định tỷ lệ nam là 50%).

  • Giá trị kiểm định là X-squared = 3728.3, với df = 1, cho thấy sự chênh lệch lớn giữa tỷ lệ quan sát và tỷ lệ giả định.

  • Giá trị p-value < 2.2e-16, rất nhỏ, khẳng định rằng có bằng chứng mạnh để bác bỏ H₀.

  • Giả thuyết đối (H₁) là tỷ lệ thực tế khác 0.5 (kiểm định hai phía).

  • Khoảng tin cậy 95% cho tỷ lệ nam giới nằm trong khoảng [66.41%; 67.43%], cho thấy tỷ lệ này khá ổn định và cao hơn mức giả định.

  • Tỷ lệ mẫu ước lượng là 66.92%, tức là gần 2/3 người trong mẫu khảo sát là nam giới.

Bài toán kiểm định:

Giả thuyết kiểm định:

Giả thuyết không H₀: p = 0.5 (tỷ lệ nam giới bằng 50%)

Giả thuyết đối H₁: p ≠ 0.5 (tỷ lệ nam giới khác 50%)

Mức ý nghĩa: α = 0.05

Kết luận:

Với p-value < 2.2e-16 < 0.05, ta bác bỏ giả thuyết H₀.

Do đó, có bằng chứng thống kê rõ ràng cho thấy tỷ lệ nam giới khác 50%, với độ tin cậy 95%.

Cụ thể, tỷ lệ nam giới ước lượng là 66.92%, cao hơn đáng kể so với 50%, với khoảng tin cậy nằm trong khoảng từ 66.41% đến 67.43%. Mức chênh lệch gần 17 điểm phần trăm là đủ lớn để tạo ra ý nghĩa thống kê mạnh.

4 Phân tích Mối quan hệ giữa Hai biến Định tính (Bivariate Analysis)

Chọn ba cặp biến định tính :

  • Cặp 1: Gender – EarningClass → Phân tích mối liên hệ giữa giới tính và mức thu nhập.

Câu hỏi đặt ra: Giới tính có ảnh hưởng đến khả năng thuộc nhóm thu nhập >50K không?

  • Cặp 2: Nationality – EarningClass → Xem xét xem quốc gia gốc có ảnh hưởng đến thu nhập hay không.

Câu hỏi đặt ra: Người đến từ Hoa Kỳ có tỷ lệ thu nhập >50K cao hơn các quốc gia khác không?

  • Cặp 3: Ethnicity – EarningClass → Tìm hiểu xem chủng tộc có liên quan đến thu nhập không.

Câu hỏi đặt ra: Tỷ lệ thu nhập >50K có chênh lệch rõ rệt giữa các nhóm chủng tộc không?

4.1 Gender - EarningClass

4.1.1 Bảng tần số chéo

# Bảng tần số chéo: giới tính và thu nhập
table_Gender_EarningClass <- table(d$Gender, d$EarningClass)
table_Gender_EarningClass
##         
##          <=50K  >50K
##   Female  7526   989
##   Male   11889  5594
# Tỷ lệ theo hàng (từng giới tính)
prop.table(table_Gender_EarningClass, margin = 1)
##         
##             <=50K     >50K
##   Female 0.883852 0.116148
##   Male   0.680032 0.319968
  • Trong số nam giới (Male): có 15,128 người thu nhập <=50K và 6,662 người thu nhập >50K → tỷ lệ >50K là 30.6%.

  • Trong số nữ giới (Female): có 9,592 người thu nhập <=50K và 1,179 người thu nhập >50K → tỷ lệ >50K là 10.9%.

Kết luận: → Nam giới (Male) có tỷ lệ thu nhập >50K gần gấp 3 lần nữ giới (Female), cho thấy sự chênh lệch thu nhập rất đáng kể giữa hai giới.

4.1.2 Trực quan hóa

library(ggplot2)

# Tạo bảng dữ liệu từ bảng tần suất chéo
table_Gender_EarningClass <- table(d$Gender, d$EarningClass)
df_group <- as.data.frame(as.table(table_Gender_EarningClass))
colnames(df_group) <- c("Gender", "EarningClass", "Freq")  # Đổi tên cột

# Vẽ biểu đồ cột nhóm
ggplot(df_group, aes(x = EarningClass, y = Freq, fill = Gender)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.6) +
  geom_text(aes(label = Freq),
            position = position_dodge(width = 0.8),
            vjust = -0.4, size = 4, color = "white", fontface = "bold") +
  labs(title = "Biểu đồ cột nhóm: Gender vs EarningClass",
       x = "Mức thu nhập",
       y = "Tần số") +
  scale_fill_manual(
    values = c("Female" = "#FF9999", "Male" = "#6699CC"),
    name = "Giới tính",
    labels = c("Nữ", "Nam")
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.position = "right"
  )

  • library(ggplot2): Nạp thư viện ggplot2 để sử dụng các chức năng vẽ biểu đồ.

  • table_Gender_EarningClass <- table(d\(Gender, d\)EarningClass): Tạo bảng tần suất chéo giữa hai biến định tính là giới tính (Gender) và thu nhập (EarningClass), cho biết số lượng từng tổ hợp.

  • df_group <- as.data.frame(as.table(table_Gender_EarningClass)): Chuyển bảng tần suất vừa tạo sang dạng bảng dữ liệu (data.frame) gồm ba cột.

  • colnames(df_group) <- c(“Gender”, “EarningClass”, “Freq”): Đặt tên cho ba cột là: giới tính (Gender), mức thu nhập (EarningClass) và tần số (Freq).

  • ggplot(df_group, aes(x = EarningClass, y = Freq, fill = Gender)): Khởi tạo biểu đồ cột, trục hoành là thu nhập, trục tung là tần số, các cột được tô màu theo giới tính.

  • geom_bar(stat = “identity”, position = position_dodge(width = 0.8), width = 0.6): Vẽ biểu đồ cột nhóm, đặt các cột nam và nữ cạnh nhau để dễ so sánh.

  • geom_text(…): Thêm nhãn số lượng lên mỗi cột để hiển thị giá trị Freq, đặt ở trên đầu cột.

  • labs(…): Thêm tiêu đề biểu đồ và nhãn cho các trục.

  • scale_fill_manual(…): Tùy chỉnh màu sắc của từng giới tính và thiết lập chú thích (legend).

  • theme_minimal(…) + theme(…): Áp dụng phong cách tối giản cho biểu đồ, căn giữa tiêu đề và đặt chú giải bên phải.

# Tạo bảng dữ liệu từ bảng tần suất chéo
table_Gender_EarningClass <- table(d$Gender, d$EarningClass)
df_stack <- as.data.frame(as.table(table_Gender_EarningClass))
colnames(df_stack) <- c("Gender", "EarningClass", "Freq")  # Đổi tên cột

# Vẽ biểu đồ cột chồng
ggplot(df_stack, aes(x = EarningClass, y = Freq, fill = Gender)) +
  geom_bar(stat = "identity", width = 0.6) +
  geom_text(aes(label = Freq),
            position = position_stack(vjust = 0.5),
            color = "green", size = 4, fontface = "bold") +
  scale_fill_manual(
    values = c("Female" = "red", "Male" = "#6699CC"),
    name = "Giới tính",
    labels = c("Nữ", "Nam")
  ) +
  labs(title = "Biểu đồ cột chồng: Gender vs EarningClass",
       x = "Mức thu nhập",
       y = "Tần số") +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.position = "right"
  )

  • geom_bar(stat = “identity”, width = 0.6): Vẽ biểu đồ cột chồng (stacked bar chart), trong đó mỗi nhóm thu nhập hiển thị một cột có phần chồng theo giới tính.

  • geom_text(position = position_stack(vjust = 0.5), …): Hiển thị nhãn số lượng (tần số) bên trong từng phần chồng của cột, tức là ở giữa mỗi khối màu.

4.1.3 Nhận xét mô tả

  • Biểu đồ cột nhóm cho thấy nam giới áp đảo rõ rệt về số lượng ở nhóm thu nhập >50K – các cột màu xanh (Male) cao hơn đáng kể so với nữ (Female) trong nhóm này.

  • Ở nhóm thu nhập <=50K, nữ giới vẫn chiếm số lượng lớn, nhưng cột biểu diễn của họ thu nhỏ mạnh khi sang nhóm thu nhập cao.

  • Biểu đồ cột chồng củng cố quan sát này: tỷ lệ nam giới chiếm phần lớn trong cột >50K, còn nữ giới gần như chỉ tập trung ở nhóm thu nhập thấp.

→ Kết luận trực quan: Giới tính là yếu tố ảnh hưởng đáng kể đến phân phối thu nhập trong dữ liệu. Biểu đồ cho thấy sự phân tầng giới tính rất rõ về thu nhập.

4.1.4 Kiểm định thống kê (Kiểm định Chi-bình phương)

Giả thuyết kiểm định:

H₀ (Giả thuyết không): Giới tính và mức thu nhập độc lập nhau.

H₁ (Giả thuyết đối):Giới tính và mức thu nhập có liên hệ..

# Thực hiện kiểm định Chi-bình phương
chisq.test(table_Gender_EarningClass)
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  table_Gender_EarningClass
## X-squared = 1256.9, df = 1, p-value < 2.2e-16

Kết quả kiểm định Chi-bình phương:

Chi-squared = 1517.81

Bậc tự do (df) = 1

Giá trị p-value = 0.0000

Kết luận thống kê: Vì p < 0.05, ta bác bỏ giả thuyết H₀.

Điều này cho thấy có mối liên hệ có ý nghĩa thống kê giữa giới tính và mức thu nhập.

Thảo luận thêm về bản chất mối quan hệ:

Kiểm định Chi-bình phương cho thấy có sự phụ thuộc giữa giới tính và thu nhập.

Từ góc độ thống kê, điều này có nghĩa là: việc một người là nam hay nữ ảnh hưởng đến xác suất họ thuộc nhóm thu nhập cao hoặc thấp – hai biến không độc lập nhau.

Quan sát biểu đồ cho thấy:

  • Nam giới có mặt áp đảo ở nhóm thu nhập >50K, tức là họ có nhiều khả năng hơn để đạt mức thu nhập cao.

  • Ngược lại, nữ giới chủ yếu phân bố ở nhóm thu nhập <=50K, tức ít khả năng thuộc tầng lớp thu nhập cao.

Bản chất mối liên hệ: Không chỉ là khác biệt về con số – mà là một mô hình phân bố có xu hướng rõ ràng theo giới tính.

Có thể phản ánh sự phân tầng xã hội hoặc sự khác biệt trong đặc điểm nghề nghiệp, kinh nghiệm, hoặc thời gian làm việc giữa hai giới.

→ Kết luận sâu hơn: Không chỉ có mối liên hệ thống kê, mà biểu đồ còn thể hiện tính định hướng của mối liên hệ này – nam giới có xác suất đạt thu nhập cao cao hơn một cách có hệ thống so với nữ.

4.1.5 Hiệu tỷ lệ

# Lập bảng tần số chéo giữa Gender và EarningClass
table_Gender_EarningClass <- table(d$Gender, d$EarningClass)

# Thêm tổng hàng và tổng cột
table_Gender_EarningClass_margins <- addmargins(table_Gender_EarningClass)

# Hiển thị bảng
table_Gender_EarningClass_margins
##         
##          <=50K  >50K   Sum
##   Female  7526   989  8515
##   Male   11889  5594 17483
##   Sum    19415  6583 25998

Tỷ lệ thu nhập cao theo giới tính được ký hiệu như sau:

  • \(p_1 = P(\text{EarningClass} = \text{">50K"} \mid \text{Gender} = \text{"Female"})\): Tỷ lệ nữ giới có thu nhập cao.
  • \(p_2 = P(\text{EarningClass} = \text{">50K"} \mid \text{Gender} = \text{"Male"})\): Tỷ lệ nam giới có thu nhập cao.

Giả thuyết kiểm định:

  • \(H_0: p_1 - p_2 = 0\): Không có sự khác biệt về tỷ lệ thu nhập cao giữa nam và nữ.
  • \(H_1: p_1 - p_2 < 0\): Tỷ lệ thu nhập cao ở nữ thấp hơn nam.
# Tạo bảng tần số chéo giữa Gender và EarningClass
table_Gender_EarningClass <- table(d$Gender, d$EarningClass)

# Số người có thu nhập >50K trong từng giới
counts_EarningClass_high <- c(table_Gender_EarningClass["Female", ">50K"], table_Gender_EarningClass["Male", ">50K"])

# Tổng số người theo từng giới
totals_EarningClass <- c(sum(table_Gender_EarningClass["Female", ]), sum(table_Gender_EarningClass["Male", ]))

# Kiểm định tỉ lệ một phía: p1 < p2
test_EarningClass_less <- prop.test(counts_EarningClass_high, totals_EarningClass, alternative = "less", correct = FALSE)

# Hiển thị kết quả
test_EarningClass_less
## 
##  2-sample test for equality of proportions without continuity correction
## 
## data:  counts_EarningClass_high out of totals_EarningClass
## X-squared = 1258, df = 1, p-value < 2.2e-16
## alternative hypothesis: less
## 95 percent confidence interval:
##  -1.0000000 -0.1956781
## sample estimates:
##   prop 1   prop 2 
## 0.116148 0.319968

Mục tiêu kiểm định: So sánh tỷ lệ người có thu nhập cao (biến EarningClass có giá trị “>50K”) giữa hai giới tính (Gender là “Female” và “Male”).

Định nghĩa:

p1 = P(EarningClass == “>50K” | Gender == “Female”): tỷ lệ nữ giới có thu nhập cao.

p2 = P(EarningClass == “>50K” | Gender == “Male”): tỷ lệ nam giới có thu nhập cao.

Giả thuyết kiểm định:

H0: p1 - p2 = 0: Không có sự khác biệt về tỷ lệ thu nhập cao giữa nam và nữ.

H1: p1 - p2 < 0: Tỷ lệ thu nhập cao ở nữ thấp hơn nam.

Kết quả từ prop.test():

Tỷ lệ nữ: khoảng 10.95%.

Tỷ lệ nam: khoảng 30.57%.

X-squared = 1518.9, df = 1, p-value < 2.2e-16.

Khoảng tin cậy 95% cho p1 - p2: từ -1.0000000 đến -0.1891457.

Kết luận: Có bằng chứng thống kê mạnh để bác bỏ giả thuyết H0. Tỷ lệ nữ có thu nhập cao thấp hơn nam một cách có ý nghĩa thống kê.

4.1.6 Tỷ số nguy cơ

Liệu giới tính (nam/nữ) có ảnh hưởng đến nguy cơ có thu nhập cao không (>50K)?

→ Mục tiêu: So sánh nguy cơ có thu nhập cao ở nam giới so với nữ giới.

install.packages("epitools", repos = "https://cloud.r-project.org")
## Installing package into 'C:/Users/ADMIN/AppData/Local/R/win-library/4.5'
## (as 'lib' is unspecified)
## package 'epitools' successfully unpacked and MD5 sums checked
## 
## The downloaded binary packages are in
##  C:\Users\ADMIN\AppData\Local\Temp\RtmpsnEVqe\downloaded_packages
library(epitools)

Tính Relative Risk

riskratio(table_Gender_EarningClass)
## $data
##         
##          <=50K >50K Total
##   Female  7526  989  8515
##   Male   11889 5594 17483
##   Total  19415 6583 25998
## 
## $measure
##         risk ratio with 95% C.I.
##          estimate    lower    upper
##   Female  1.00000       NA       NA
##   Male    2.75483 2.588052 2.932356
## 
## $p.value
##         two-sided
##          midp.exact  fisher.exact    chi.square
##   Female         NA            NA            NA
##   Male            0 3.875868e-303 1.532559e-275
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét kết quả

$data: đây là bảng dữ liệu chéo 2x2

  • Trong số 10,771 nữ, có 1,179 người (10.95%) có thu nhập trên 50K.

  • Trong số 21,790 nam, có 6,662 người (30.57%) có thu nhập trên 50K.

$measure: tỷ số nguy cơ(RR)

Tỷ số nguy cơ (RR) là so sánh xác suất xảy ra outcome (ở đây là: có thu nhập >50K) giữa hai nhóm:

  • RR = 1 → nguy cơ như nhau.

  • RR > 1 → nhóm Male có nguy cơ cao hơn.

  • RR < 1 → nhóm Male có nguy cơ thấp hơn.

$p.value

# Cài gói nếu cần
install.packages("knitr")  # chỉ cần 1 lần nếu chưa cài
## Warning: package 'knitr' is in use and will not be installed
# Nạp thư viện
library(knitr)

# Tạo bảng dữ liệu
explanation <- data.frame(
  Cột = c("two-sided", "midp.exact", "fisher.exact", "chi.square"),
  Ý_nghĩa = c(
    "Kiểm định hai phía – kiểm tra xem RR có khác 1. Đây là loại kiểm định phổ biến nhất.",
    "Kiểm định chính xác – cho p-value chính xác dựa trên phân phối chính xác.",
    "Fisher’s exact test – dùng trong bảng 2x2 với cỡ mẫu nhỏ.",
    "Chi-squared test – kiểm định xấp xỉ phân phối chuẩn, dùng khi mẫu đủ lớn."
  )
)

# In bảng
kable(explanation, align = "l")
Cột Ý_nghĩa
two-sided Kiểm định hai phía – kiểm tra xem RR có khác 1. Đây là loại kiểm định phổ biến nhất.
midp.exact Kiểm định chính xác – cho p-value chính xác dựa trên phân phối chính xác.
fisher.exact Fisher’s exact test – dùng trong bảng 2x2 với cỡ mẫu nhỏ.
chi.square Chi-squared test – kiểm định xấp xỉ phân phối chuẩn, dùng khi mẫu đủ lớn.

Kết quả

  • Tỷ số nguy cơ (RR) = 2.79 → Nam giới có nguy cơ có thu nhập trên 50K cao hơn đáng kể so với nữ giới, cụ thể là gấp 2.79 lần.

  • Khoảng tin cậy 95% = [2.64, 2.96] → Không bao gồm 1 → nghĩa là sự khác biệt này có ý nghĩa thống kê.

  • p-value = 0.000 ở tất cả các phương pháp kiểm định (mid-p exact, Fisher, chi-square) → rất nhỏ hơn 0.05 → cho thấy có bằng chứng thống kê mạnh mẽ về sự khác biệt giữa nam và nữ về mức thu nhập.

Kết luận

  • Dựa trên kết quả phân tích, nam giới có khả năng đạt thu nhập cao (>50K) cao hơn rõ rệt so với nữ giới trong bộ dữ liệu này. Tỷ số nguy cơ là 2.79 với khoảng tin cậy hẹp và p-value bằng 0 cho thấy sự khác biệt là có ý nghĩa thống kê mạnh mẽ. Điều này hàm ý rằng giới tính là một yếu tố có ảnh hưởng rõ ràng đến khả năng đạt được mức thu nhập cao, ít nhất là trong phạm vi mẫu khảo sát này.

4.1.7 Tỷ số Chênh (Odds Ratio - OR)

or_result2 <- oddsratio(table_Gender_EarningClass)
print(or_result2)
## $data
##         
##          <=50K >50K Total
##   Female  7526  989  8515
##   Male   11889 5594 17483
##   Total  19415 6583 25998
## 
## $measure
##         odds ratio with 95% C.I.
##          estimate    lower    upper
##   Female  1.00000       NA       NA
##   Male    3.57994 3.327669 3.854999
## 
## $p.value
##         two-sided
##          midp.exact  fisher.exact    chi.square
##   Female         NA            NA            NA
##   Male            0 3.875868e-303 1.532559e-275
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"

Ước lượng Odds Ratio (OR) cho nhóm nam giới là 3.58 (với khoảng tin cậy 95% từ 3.35 đến 3.83), so với nhóm nữ giới được sử dụng làm nhóm tham chiếu (OR = 1). Điều này cho thấy:

–> Nam giới có khả năng có thu nhập cao (>50K) cao hơn khoảng 3.6 lần so với nữ giới.

Khoảng tin cậy 95% không bao gồm giá trị 1, điều này củng cố rằng sự khác biệt là có ý nghĩa thống kê.

Kết quả kiểm định với các phương pháp phổ biến đều cho p-value bằng 0:

  • Mid-p exact test: 0

  • Fisher’s exact test: 0

  • Chi-squared test: 0

Các p-value bằng 0 cho thấy sự khác biệt quan sát được về tỷ lệ thu nhập cao giữa nam và nữ là rất rõ ràng và không thể giải thích do ngẫu nhiên trong mẫu.

Tóm lại: Kết quả phân tích chỉ ra rằng giới tính có ảnh hưởng đáng kể đến mức thu nhập, trong đó nam giới có xu hướng đạt mức thu nhập cao hơn nữ giới một cách rõ rệt và có ý nghĩa thống kê.

4.2 PartneringState – EarningClass

4.2.1 Bảng tần số chéo

# Bảng tần số chéo và tỷ lệ theo hàng giữa tình trạng hôn nhân và thu nhập
table_marital_EarningClass <- table(d$PartneringState, d$EarningClass)              # Bảng tần số chéo
table_marital_EarningClass                                                   # Hiển thị bảng
##                        
##                         <=50K >50K
##   Divorced               3141  385
##   Married-AF-spouse         9    8
##   Married-civ-spouse     6516 5599
##   Married-spouse-absent   305   29
##   Never-married          7964  434
##   Separated               752   60
##   Widowed                 728   68
prop.table(table_marital_EarningClass, margin = 1)                           # Tính tỷ lệ theo từng tình trạng hôn nhân
##                        
##                              <=50K       >50K
##   Divorced              0.89081112 0.10918888
##   Married-AF-spouse     0.52941176 0.47058824
##   Married-civ-spouse    0.53784565 0.46215435
##   Married-spouse-absent 0.91317365 0.08682635
##   Never-married         0.94832103 0.05167897
##   Separated             0.92610837 0.07389163
##   Widowed               0.91457286 0.08542714
  • Trong nhóm Married-civ-spouse: có 8,284 người thu nhập <=50K và 6,692 người thu nhập >50K → tỷ lệ >50K là 44.7%.

  • Trong nhóm Never-married: có 10,192 người thu nhập <=50K và 491 người thu nhập >50K → tỷ lệ >50K là 4.6%.

  • Trong nhóm Divorced: có 3,980 người thu nhập <=50K và 463 người thu nhập >50K → tỷ lệ >50K là 10.4%.

  • Trong nhóm Married-spouse-absent: có 384 người thu nhập <=50K và 34 người thu nhập >50K → tỷ lệ >50K là 8.1%.

  • Trong nhóm Widowed: có 908 người thu nhập <=50K và 85 người thu nhập >50K → tỷ lệ >50K là 8.6%.

  • Trong nhóm Separated: có 959 người thu nhập <=50K và 66 người thu nhập >50K → tỷ lệ >50K là 6.4%.

  • Trong nhóm Married-AF-spouse: có 13 người thu nhập <=50K và 10 người thu nhập >50K → tỷ lệ >50K là 43.5% (nhưng mẫu nhỏ).

Kết luận: → Nhóm Married-civ-spouse có tỷ lệ thu nhập >50K cao nhất trong các nhóm đông dân số, trong khi nhóm Never-married có tỷ lệ thấp nhất. → Điều này phản ánh sự chênh lệch đáng kể về thu nhập theo tình trạng hôn nhân, đặc biệt là lợi thế của người đã kết hôn hợp pháp.

4.2.2 Trực quan hóa

# Tạo bảng dữ liệu từ bảng tần suất chéo
table_marital_EarningClass <- table(d$PartneringState, d$EarningClass)
df_group_marital <- as.data.frame(as.table(table_marital_EarningClass))
colnames(df_group_marital) <- c("MaritalStatus", "EarningClass", "Freq")

# Vẽ biểu đồ cột nhóm
ggplot(df_group_marital, aes(x = MaritalStatus, y = Freq, fill = EarningClass)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.6) +
  geom_text(aes(label = Freq),
            position = position_dodge(width = 0.8),
            vjust = -0.4, size = 4, color = "black", fontface = "bold") +
  scale_fill_manual(
    values = c("<=50K" = "red", ">50K" = "#20B2AA"),
    name = "Thu nhập"
  ) +
  labs(title = "Biểu đồ cột nhóm: MaritalStatus vs EarningClass",
       x = "Tình trạng hôn nhân",
       y = "Tần số") +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.position = "right"
  )

# Tạo bảng dữ liệu từ bảng tần suất chéo
table_marital_EarningClass <- table(d$PartneringState, d$EarningClass)
df_stack_marital <- as.data.frame(as.table(table_marital_EarningClass))
colnames(df_stack_marital) <- c("MaritalStatus", "EarningClass", "Freq")

# Vẽ biểu đồ cột chồng 
ggplot(df_stack_marital, aes(x = MaritalStatus, y = Freq, fill = EarningClass)) +
  geom_bar(stat = "identity", width = 0.6) +
  geom_text(
    aes(label = Freq),
    position = position_stack(vjust = 0.5),
    vjust = 0.5, size = 4, color = "red", fontface = "bold"
  ) +
  scale_fill_manual(
    values = c("<=50K" = "yellow", ">50K" = "#20B2AA"),
    name = "Thu nhập"
  ) +
  labs(
    title = "Biểu đồ cột chồng: MaritalStatus vs EarningClass",
    x = "Tình trạng hôn nhân",
    y = "Tần số"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.position = "right"
  )

4.2.3 Nhận xét mô tả

  • Biểu đồ cột nhóm cho thấy những người đã kết hôn hợp pháp (Married-civ-spouse) có số lượng vượt trội ở nhóm thu nhập >50K – thanh cột ở nhóm này cao rõ rệt.

  • Ngược lại, nhóm Never-married gần như chỉ xuất hiện ở mức thu nhập thấp. Các nhóm “Divorced” hay “Separated” cũng có tỷ lệ thu nhập cao rất thấp.

  • Biểu đồ cột chồng cho thấy cột của nhóm Married-civ-spouse có phần màu thu nhập cao chiếm gần một nửa, trong khi các nhóm khác phần màu này rất mỏng.

→ Kết luận trực quan: Tình trạng hôn nhân có liên quan chặt chẽ đến thu nhập. Biểu đồ phản ánh rõ rằng người đã kết hôn có lợi thế lớn về kinh tế so với các nhóm còn lại.

4.2.4 Kiểm định thống kê(Kiểm định Chi-bình phương)

Giả thuyết kiểm định:

H₀ (Giả thuyết không):Tình trạng hôn nhân và mức thu nhập độc lập với nha.

H₁ (Giả thuyết đối):Tình trạng hôn nhân và mức thu nhập có mối liên hệ với nhau.

chisq.test(table_marital_EarningClass)
## Warning in chisq.test(table_marital_EarningClass): Chi-squared approximation
## may be incorrect
## 
##  Pearson's Chi-squared test
## 
## data:  table_marital_EarningClass
## X-squared = 5297.3, df = 6, p-value < 2.2e-16

Kết quả kiểm định:

Chi-squared = 6517.74

Bậc tự do (df) = 6

Giá trị p-value = 0.0000

Kết luận thống kê:

Vì p < 0.05, ta bác bỏ giả thuyết H₀.

Có mối liên hệ thống kê rõ rệt giữa tình trạng hôn nhân và mức thu nhập

Thảo luận thêm về bản chất mối quan hệ:

Biểu đồ cho thấy nhóm đã kết hôn (Married-civ-spouse) có phần thu nhập >50K chiếm ưu thế tuyệt đối.

Ngược lại, nhóm độc thân (Never-married) hầu như chỉ tập trung ở mức thu nhập thấp.

Các nhóm ly hôn, ly thân, hoặc góa cũng có tỷ lệ thu nhập cao thấp đáng kể.

→ Giải thích mối liên hệ: Kiểm định cho thấy tình trạng hôn nhân không chỉ liên quan đến thu nhập, mà còn có xu hướng rõ ràng – người đã lập gia đình có nhiều khả năng đạt thu nhập cao hơn. Điều này có thể phản ánh mức độ ổn định tài chính, độ tuổi, hoặc cam kết nghề nghiệp cao hơn trong nhóm đã kết hôn.

4.2.5 Hiệu tỷ lệ

# Lập bảng tần số chéo giữa PartneringState và EarningClass
table_marital_EarningClass <- table(d$PartneringState, d$EarningClass)

# Thêm tổng hàng và tổng cột
table_marital_EarningClass1 <- addmargins(table_marital_EarningClass)

# Hiển thị bảng
table_marital_EarningClass1
##                        
##                         <=50K  >50K   Sum
##   Divorced               3141   385  3526
##   Married-AF-spouse         9     8    17
##   Married-civ-spouse     6516  5599 12115
##   Married-spouse-absent   305    29   334
##   Never-married          7964   434  8398
##   Separated               752    60   812
##   Widowed                 728    68   796
##   Sum                   19415  6583 25998
  • \(p_1 = P(\text{EarningClass} = \text{">50K"} \mid \text{PartneringState} = \text{"Never-married"})\) (Tỷ lệ người chưa từng kết hôn có thu nhập cao)

  • \(p_2 = P(\text{EarningClass} = \text{">50K"} \mid \text{PartneringState} = \text{"Married-civ-spouse"})\) (Tỷ lệ người đang kết hôn hợp pháp có thu nhập cao)

Giả thuyết kiểm định:

  • \(H_0: p_1 - p_2 = 0\) (Không có sự khác biệt về tỷ lệ thu nhập cao giữa hai nhóm tình trạng hôn nhân)

  • \(H_1: p_1 - p_2 < 0\) (Tỷ lệ thu nhập cao ở nhóm “Never-married” thấp hơn nhóm “Married-civ-spouse”)

# Lập bảng tần số chéo giữa PartneringState và EarningClass
table_marital_EarningClass <- table(d$PartneringState, d$EarningClass)

# Số người có thu nhập >50K trong từng nhóm
counts_EarningClass_high <- c(table_marital_EarningClass["Never-married", ">50K"],
                        table_marital_EarningClass["Married-civ-spouse", ">50K"])

# Tổng số người trong từng nhóm
totals_EarningClass <- c(sum(table_marital_EarningClass["Never-married", ]),
                   sum(table_marital_EarningClass["Married-civ-spouse", ]))

# Kiểm định tỉ lệ một phía: p1 < p2
test_marital_EarningClass <- prop.test(counts_EarningClass_high, totals_EarningClass,
                                 alternative = "less", correct = FALSE)

# Hiển thị kết quả
test_marital_EarningClass
## 
##  2-sample test for equality of proportions without continuity correction
## 
## data:  counts_EarningClass_high out of totals_EarningClass
## X-squared = 4025.3, df = 1, p-value < 2.2e-16
## alternative hypothesis: less
## 95 percent confidence interval:
##  -1.0000000 -0.4020315
## sample estimates:
##     prop 1     prop 2 
## 0.05167897 0.46215435

Kết quả kiểm định cho thấy:

  • Tỷ lệ người chưa từng kết hôn có thu nhập >50K (prop 1) là khoảng 4.60%.

  • Tỷ lệ người đang kết hôn hợp pháp có thu nhập >50K (prop 2) là khoảng 44.65%.

Với p-value < 2.2e-16, nhỏ hơn mức ý nghĩa 0.05, chúng ta có đủ bằng chứng để bác bỏ giả thuyết H0. Điều này có nghĩa là:

–> Tỷ lệ người chưa từng kết hôn có thu nhập cao thấp hơn tỷ lệ người đang kết hôn hợp pháp một cách có ý nghĩa thống kê.

4.2.6 Relative Risk

Liệu tình trạng hôn nhân (đã kết hôn vs chưa bao giờ kết hôn) có ảnh hưởng đến nguy cơ có thu nhập cao không (>50K)?

→ Mục tiêu: So sánh nguy cơ có thu nhập cao ở người đã kết hôn với người chưa từng kết hôn.

riskratio(table_marital_EarningClass)
## Warning in chisq.test(xx, correct = correction): Chi-squared approximation may
## be incorrect
## $data
##                        
##                         <=50K >50K Total
##   Divorced               3141  385  3526
##   Married-AF-spouse         9    8    17
##   Married-civ-spouse     6516 5599 12115
##   Married-spouse-absent   305   29   334
##   Never-married          7964  434  8398
##   Separated               752   60   812
##   Widowed                 728   68   796
##   Total                 19415 6583 25998
## 
## $measure
##                        risk ratio with 95% C.I.
##                          estimate     lower     upper
##   Divorced              1.0000000        NA        NA
##   Married-AF-spouse     4.3098549 2.5804634 7.1982608
##   Married-civ-spouse    4.2326136 3.8443498 4.6600905
##   Married-spouse-absent 0.7951940 0.5545947 1.1401723
##   Never-married         0.4732988 0.4149945 0.5397947
##   Separated             0.6767321 0.5212132 0.8786547
##   Widowed               0.7823794 0.6117121 1.0006629
## 
## $p.value
##                        two-sided
##                           midp.exact fisher.exact    chi.square
##   Divorced                        NA           NA            NA
##   Married-AF-spouse     0.0002350404 2.099833e-04  2.206261e-06
##   Married-civ-spouse    0.0000000000 0.000000e+00 3.394002e-315
##   Married-spouse-absent 0.2039864131 2.293204e-01  2.068318e-01
##   Never-married         0.0000000000 1.299681e-27  9.178227e-30
##   Separated             0.0020700706 2.515660e-03  2.801647e-03
##   Widowed               0.0447670745 4.724980e-02  4.806052e-02
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét kết quả

Kết quả

  • Trong số 14,976 người đã kết hôn, có 6,692 người (44.69%) có thu nhập >50K.

  • Trong số 10,683 người chưa bao giờ kết hôn, chỉ có 491 người (4.60%) có thu nhập >50K.

  • Tỷ số nguy cơ (RR) = 9.72 → Người đã kết hôn có xác suất có thu nhập >50K cao hơn gần 10 lần so với người chưa từng kết hôn.

  • Khoảng tin cậy 95% = [8.90, 10.62] → Không bao gồm 1 → khác biệt có ý nghĩa thống kê mạnh mẽ.

  • p-value = 0.000 ở tất cả các kiểm định → xác nhận kết quả là cực kỳ có ý nghĩa thống kê.

Kết luận

  • Dựa trên kết quả phân tích, người đã kết hôn có nguy cơ có thu nhập cao vượt trội so với người chưa từng kết hôn. Tỷ số nguy cơ là 9.72, khoảng tin cậy 95% là [8.90, 10.62], và p-value bằng 0 cho thấy mối liên hệ rất mạnh mẽ và có ý nghĩa thống kê. Tình trạng hôn nhân là một yếu tố quan trọng ảnh hưởng đến khả năng đạt mức thu nhập cao trong bộ dữ liệu này.

4.2.7 Odds Ratio - OR

# Ước lượng odds ratio từng nhóm so với nhóm "Divorced"
or_result <- oddsratio(table_marital_EarningClass)
## Warning in chisq.test(xx, correct = correction): Chi-squared approximation may
## be incorrect
# In kết quả
print(or_result)
## $data
##                        
##                         <=50K >50K Total
##   Divorced               3141  385  3526
##   Married-AF-spouse         9    8    17
##   Married-civ-spouse     6516 5599 12115
##   Married-spouse-absent   305   29   334
##   Never-married          7964  434  8398
##   Separated               752   60   812
##   Widowed                 728   68   796
##   Total                 19415 6583 25998
## 
## $measure
##                        odds ratio with 95% C.I.
##                          estimate     lower      upper
##   Divorced              1.0000000        NA         NA
##   Married-AF-spouse     7.2601735 2.6702852 19.3690321
##   Married-civ-spouse    7.0071752 6.2745384  7.8468167
##   Married-spouse-absent 0.7794386 0.5141804  1.1382620
##   Never-married         0.4446159 0.3852993  0.5132525
##   Separated             0.6523984 0.4869573  0.8596325
##   Widowed               0.7634811 0.5782843  0.9938652
## 
## $p.value
##                        two-sided
##                           midp.exact fisher.exact    chi.square
##   Divorced                        NA           NA            NA
##   Married-AF-spouse     0.0002350404 2.099833e-04  2.206261e-06
##   Married-civ-spouse    0.0000000000 0.000000e+00 3.394002e-315
##   Married-spouse-absent 0.2039864131 2.293204e-01  2.068318e-01
##   Never-married         0.0000000000 1.299681e-27  9.178227e-30
##   Separated             0.0020700706 2.515660e-03  2.801647e-03
##   Widowed               0.0447670745 4.724980e-02  4.806052e-02
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"

Ước lượng Odds Ratio (OR) cho các nhóm tình trạng hôn nhân, tham chiếu là “Divorced” - Nhóm Married-civ-spouse có OR = 6.94 (95% CI: 6.28 – 7.69), p-value = 0.0000. –> Người đang kết hôn hợp pháp có khả năng có thu nhập >50K cao hơn gần 7 lần so với người đã ly hôn. Sự khác biệt này có ý nghĩa thống kê rất cao.

  • Nhóm Never-married có OR = 0.41 (95% CI: 0.36 – 0.47), p-value = 0.0000. –> Những người chưa từng kết hôn có khả năng đạt thu nhập cao chỉ bằng 41% so với nhóm ly hôn. Đây là sự khác biệt có ý nghĩa thống kê rõ rệt.

  • Nhóm Separated có OR = 0.59 (95% CI: 0.45 – 0.77), p-value = 0.0001. –> Những người ly thân có xác suất thu nhập cao thấp hơn đáng kể so với người ly hôn, và sự khác biệt này có ý nghĩa thống kê.

  • Nhóm Widowed có OR = 0.81 (95% CI: 0.63 – 1.02), p-value = 0.0750. –> Mặc dù có xu hướng thu nhập thấp hơn nhóm ly hôn, nhưng vì khoảng tin cậy bao gồm 1 và p-value > 0.05 nên chưa đủ bằng chứng thống kê để kết luận.

  • Nhóm Married-AF-spouse có OR = 6.63 (95% CI: 2.79 – 15.29), p-value ≈ 0.00006. –> Mặc dù nhóm này rất nhỏ (n = 23), kết quả cho thấy khả năng có thu nhập cao cũng cao hơn nhiều so với người ly hôn và có ý nghĩa thống kê.

  • Nhóm Married-spouse-absent có OR = 0.76 (95% CI: 0.52 – 1.08), p-value ≈ 0.135. –> Không có đủ bằng chứng thống kê để kết luận có sự khác biệt về thu nhập so với nhóm ly hôn.

Tóm lại:

Kết quả phân tích cho thấy tình trạng hôn nhân có mối liên hệ đáng kể với mức thu nhập. Nhóm đang sống trong hôn nhân hợp pháp (Married-civ-spouse) có xác suất đạt thu nhập cao vượt trội so với các nhóm khác, đặc biệt là người ly hôn, chưa kết hôn hay ly thân. Những khác biệt này có ý nghĩa thống kê rõ ràng, ngoại trừ một số nhóm có quy mô mẫu nhỏ hoặc khoảng tin cậy chứa 1.

4.3 Ethnicity - EarningClass

4.3.1 Bảng tần số chéo

# Bảng tần số chéo: chủng tộc và thu nhập
table_Ethnicity_EarningClass <- table(d$Ethnicity, d$EarningClass)
table_Ethnicity_EarningClass
##                     
##                      <=50K  >50K
##   Amer-Indian-Eskimo   215    30
##   Asian-Pac-Islander   585   220
##   Black               2119   332
##   Other                203    18
##   White              16293  5983
# Tỷ lệ theo hàng (từng chủng tộc)
prop.table(table_Ethnicity_EarningClass, margin = 1)
##                     
##                           <=50K       >50K
##   Amer-Indian-Eskimo 0.87755102 0.12244898
##   Asian-Pac-Islander 0.72670807 0.27329193
##   Black              0.86454508 0.13545492
##   Other              0.91855204 0.08144796
##   White              0.73141498 0.26858502
  • White: có 20,699 người thu nhập <=50K và 7,117 người thu nhập >50K → tỷ lệ >50K là 25.6%.

  • Asian-Pac-Islander: có 763 người thu nhập <=50K, 276 người thu nhập >50K → tỷ lệ >50K là 26.6%.

  • Black: có 2,737 người thu nhập <=50K, 387 người thu nhập >50K → tỷ lệ >50K là 12.4%.

  • Amer-Indian-Eskimo: có 275 người thu nhập <=50K, 36 người thu nhập >50K → tỷ lệ >50K là 11.6%.

  • Other: có 246 người thu nhập <=50K, 25 người thu nhập >50K → tỷ lệ >50K là 9.2%.

Kết luận: → Nhóm Asian-Pac-Islander và White có tỷ lệ thu nhập >50K cao nhất, trong khi các nhóm còn lại như Black, Amer-Indian-Eskimo, và đặc biệt là Other có tỷ lệ rất thấp. Điều này cho thấy có sự khác biệt rõ rệt về thu nhập giữa các nhóm chủng tộc.

4.3.2 Trực quan hóa

# Tạo bảng dữ liệu từ bảng tần suất chéo
table_Ethnicity_EarningClass <- table(d$Ethnicity, d$EarningClass)
df_group_Ethnicity <- as.data.frame(as.table(table_Ethnicity_EarningClass))
colnames(df_group_Ethnicity) <- c("Ethnicity", "EarningClass", "Freq")

# Vẽ biểu đồ cột nhóm
ggplot(df_group_Ethnicity, aes(x = Ethnicity, y = Freq, fill = EarningClass)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8), width = 0.6) +
  geom_text(aes(label = Freq),
            position = position_dodge(width = 0.8),
            vjust = -0.4, size = 4, color = "red", fontface = "bold") +
  scale_fill_manual(
    values = c("<=50K" = "#FFD700", ">50K" = "purple"),
    name = "Thu nhập"
  ) +
  labs(title = "Biểu đồ cột nhóm: Ethnicity vs EarningClass",
       x = "Chủng tộc",
       y = "Tần số") +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.position = "right"
  )

# Tạo bảng dữ liệu từ bảng tần suất chéo
table_Ethnicity_EarningClass <- table(d$Ethnicity, d$EarningClass)
df_stack_Ethnicity <- as.data.frame(as.table(table_Ethnicity_EarningClass))
colnames(df_stack_Ethnicity) <- c("Ethnicity", "EarningClass", "Freq")

# Vẽ biểu đồ cột chồng
ggplot(df_stack_Ethnicity, aes(x = Ethnicity, y = Freq, fill = EarningClass)) +
  geom_bar(stat = "identity", width = 0.6) +
  geom_text(aes(label = Freq),
          position = position_dodge(width = 0.8),
          vjust = 1.5, size = 4, color = "green", fontface = "bold"
 ) +
  scale_fill_manual(
    values = c("<=50K" = "red", ">50K" = "#4169E1"),
    name = "Thu nhập"
  ) +
  labs(title = "Biểu đồ cột chồng: Ethnicity vs EarningClass",
       x = "Chủng tộc",
       y = "Tần số") +
  theme_minimal(base_size = 13) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.position = "right"
  )

4.3.3 Nhận xét mô tả

  • Nhóm Asian-Pac-Islander tuy có quy mô nhỏ hơn, nhưng cột thu nhập >50K vẫn khá nổi bật, cho thấy tỷ lệ thu nhập cao không hề kém cạnh.

  • Biểu đồ cột chồng thể hiện sự phân hóa rõ: nhóm White có sự phân bố thu nhập đều hơn, trong khi nhóm Black hay Amer-Indian-Eskimo gần như bị dồn hết vào phần thu nhập thấp.

4.3.4 Kiểm định thống kê

Giả thuyết kiểm định:

H₀ (Giả thuyết không): Chủng tộc và mức thu nhập độc lập nhau.

H₁ (Giả thuyết đối):Chủng tộc và mức thu nhận có liên hệ với nhau.

# Thực hiện kiểm định Chi-bình phương
chisq.test(table_Ethnicity_EarningClass)
## 
##  Pearson's Chi-squared test
## 
## data:  table_Ethnicity_EarningClass
## X-squared = 265.93, df = 4, p-value < 2.2e-16

Kết quả kiểm định:

Chi-squared = 330.92

Bậc tự do (df) = 4

p-value < 2.2e-16

Kết luận thống kê:

Vì p-value rất nhỏ (< 0.05), ta bác bỏ H₀.

Có bằng chứng thống kê rất mạnh cho thấy mức thu nhập và chủng tộc có mối liên hệ đáng kể.

Thảo luận thêm về bản chất mối quan hệ:

Kết quả kiểm định cho thấy chủng tộc và thu nhập có mối liên hệ có ý nghĩa thống kê (p-value < 2.2e-16). Dù sự chênh lệch giữa các nhóm không quá lớn, nhưng với cỡ mẫu đủ lớn, các khác biệt nhỏ vẫn mang ý nghĩa thống kê.

Biểu đồ cho thấy nhóm White có số lượng thu nhập >50K cao nhất, trong khi Asian-Pac-Islander lại có tỷ lệ thu nhập cao nổi bật dù quy mô nhỏ. Ngược lại, Black và Amer-Indian-Eskimo có tỷ lệ thu nhập cao thấp hơn đáng kể.

Những chênh lệch này có thể đến từ sự khác biệt về cơ hội giáo dục, nghề nghiệp và điều kiện kinh tế – xã hội giữa các chủng tộc. Ngoài ra, phân bố mẫu hoặc đặc thù khu vực cũng có thể ảnh hưởng đến kết quả quan sát.

→ Tổng thể, chủng tộc là một yếu tố liên quan đáng kể đến khả năng đạt thu nhập cao trong tập dữ liệu này.

4.3.5 Hiệu tỷ lệ

# Lập bảng tần số chéo giữa Ethnicity và EarningClass
table_Ethnicity_EarningClass <- table(d$Ethnicity, d$EarningClass)

# Thêm tổng hàng và tổng cột
table_Ethnicity_EarningClass_margins <- addmargins(table_Ethnicity_EarningClass)

# Hiển thị bảng
table_Ethnicity_EarningClass_margins
##                     
##                      <=50K  >50K   Sum
##   Amer-Indian-Eskimo   215    30   245
##   Asian-Pac-Islander   585   220   805
##   Black               2119   332  2451
##   Other                203    18   221
##   White              16293  5983 22276
##   Sum                19415  6583 25998
  • \(p_1 = P(\text{EarningClass} = \text{">50K"} \mid \text{Ethnicity} = \text{"Black"})\) (Tỷ lệ người da đen có thu nhập cao)

  • \(p_2 = P(\text{EarningClass} = \text{">50K"} \mid \text{Ethnicity} = \text{"White"})\) (Tỷ lệ người da trắng có thu nhập cao)

Giả thuyết kiểm định:

  • \(H_0: p_1 - p_2 = 0\) (Không có sự khác biệt về tỷ lệ thu nhập cao giữa người da đen và người da trắng)

  • \(H_1: p_1 - p_2 < 0\) (Tỷ lệ người da đen có thu nhập cao thấp hơn người da trắng)

# Số người có thu nhập >50K
counts_EarningClass_high <- c(table_Ethnicity_EarningClass["Black", ">50K"], table_Ethnicity_EarningClass["White", ">50K"])

# Tổng số người trong mỗi nhóm
totals_EarningClass <- c(sum(table_Ethnicity_EarningClass["Black", ]), sum(table_Ethnicity_EarningClass["White", ]))

# Kiểm định tỉ lệ một phía: p1 < p2
test_Ethnicity_EarningClass <- prop.test(counts_EarningClass_high, totals_EarningClass, alternative = "less", correct = FALSE)
test_Ethnicity_EarningClass
## 
##  2-sample test for equality of proportions without continuity correction
## 
## data:  counts_EarningClass_high out of totals_EarningClass
## X-squared = 205.79, df = 1, p-value < 2.2e-16
## alternative hypothesis: less
## 95 percent confidence interval:
##  -1.0000000 -0.1207556
## sample estimates:
##    prop 1    prop 2 
## 0.1354549 0.2685850

Kết quả kiểm định từ prop.test():

  • \(\hat{p}_1 = 0.1239\), \(\hat{p}_2 = 0.2559\)

  • \(\hat{p}_1 - \hat{p}_2 = -0.132\)

  • Khoảng tin cậy 95% cho \(p_1 - p_2\): \([-1.0000,\ -0.1214]\)

  • Thống kê kiểm định: \(\chi^2 = 266.3\), p < 2.2 ^{-16}

Kết luận: Có bằng chứng thống kê rất mạnh để bác bỏ giả thuyết \(H_0\). Tỷ lệ người da đen có thu nhập cao thấp hơn đáng kể so với người da trắng, và sự khác biệt này có ý nghĩa thống kê.

4.3.6 Relative Risk

Liệu chủng tộc (White/Black) có ảnh hưởng đến nguy cơ có thu nhập cao không (>50K)?

→ Mục tiêu: So sánh nguy cơ có thu nhập cao ở người da trắng (White) so với người da đen (Black).

riskratio(table_Ethnicity_EarningClass)
## $data
##                     
##                      <=50K >50K Total
##   Amer-Indian-Eskimo   215   30   245
##   Asian-Pac-Islander   585  220   805
##   Black               2119  332  2451
##   Other                203   18   221
##   White              16293 5983 22276
##   Total              19415 6583 25998
## 
## $measure
##                     risk ratio with 95% C.I.
##                       estimate     lower    upper
##   Amer-Indian-Eskimo 1.0000000        NA       NA
##   Asian-Pac-Islander 2.2318841 1.5670739 3.178731
##   Black              1.1062152 0.7796786 1.569508
##   Other              0.6651584 0.3817195 1.159059
##   White              2.1934444 1.5676194 3.069111
## 
## $p.value
##                     two-sided
##                        midp.exact fisher.exact   chi.square
##   Amer-Indian-Eskimo           NA           NA           NA
##   Asian-Pac-Islander 3.684708e-07 5.365789e-07 1.210922e-06
##   Black              5.801457e-01 6.238657e-01 5.691433e-01
##   Other              1.494165e-01 1.702829e-01 1.459523e-01
##   White              3.287883e-08 3.796037e-08 2.713510e-07
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "Unconditional MLE & normal approximation (Wald) CI"

Nhận xét kết quả

Kết quả

  • Trong số 21,816 người da trắng (White), có 7,117 người (32.63%) có thu nhập >50K.

  • Trong số 3,124 người da đen (Black), có 387 người (12.39%) có thu nhập >50K.

  • Tỷ số nguy cơ (RR) = 0.48 → Người da đen có nguy cơ có thu nhập trên 50K chỉ bằng khoảng một nửa so với người da trắng.

  • Khoảng tin cậy 95% = [0.44, 0.53] → Không bao gồm 1 → có ý nghĩa thống kê.

  • p-value = 0.000 → Rất nhỏ hơn 0.05 → Có bằng chứng thống kê mạnh mẽ về sự khác biệt.

Nhận xét

  • Dựa trên kết quả phân tích, người da đen có nguy cơ đạt thu nhập >50K thấp hơn đáng kể so với người da trắng. Tỷ số nguy cơ là 0.48, khoảng tin cậy 95% là [0.44, 0.53], và p-value bằng 0 cho thấy sự khác biệt này là có ý nghĩa thống kê mạnh. Điều này hàm ý rằng chủng tộc là một yếu tố có liên quan rõ ràng đến khả năng đạt mức thu nhập cao trong bộ dữ liệu này.

4.3.7 Odds Ratio - OR

# Tính odds ratio giữa các nhóm Ethnicity so với nhóm tham chiếu "White"
or_result_Ethnicity <- oddsratio(table_Ethnicity_EarningClass)

# Hiển thị kết quả
print(or_result_Ethnicity)
## $data
##                     
##                      <=50K >50K Total
##   Amer-Indian-Eskimo   215   30   245
##   Asian-Pac-Islander   585  220   805
##   Black               2119  332  2451
##   Other                203   18   221
##   White              16293 5983 22276
##   Total              19415 6583 25998
## 
## $measure
##                     odds ratio with 95% C.I.
##                       estimate     lower    upper
##   Amer-Indian-Eskimo 1.0000000        NA       NA
##   Asian-Pac-Islander 2.6822277 1.8003683 4.124003
##   Black              1.1179843 0.7612829 1.698368
##   Other              0.6381597 0.3380352 1.173157
##   White              2.6192325 1.8153681 3.921526
## 
## $p.value
##                     two-sided
##                        midp.exact fisher.exact   chi.square
##   Amer-Indian-Eskimo           NA           NA           NA
##   Asian-Pac-Islander 3.684708e-07 5.365789e-07 1.210922e-06
##   Black              5.801457e-01 6.238657e-01 5.691433e-01
##   Other              1.494165e-01 1.702829e-01 1.459523e-01
##   White              3.287883e-08 3.796037e-08 2.713510e-07
## 
## $correction
## [1] FALSE
## 
## attr(,"method")
## [1] "median-unbiased estimate & mid-p exact CI"
LS0tDQp0aXRsZTogIk5oaeG7h20gduG7pSBUdeG6p24gNCINCmF1dGhvcjogIlbDtSBIb8OgbmcgVMOtbmgiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclSDolTTolUywgJWQgLSAlbSAtICVZJylgIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6ICJkZWZhdWx0Ig0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMg0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDINCiAgcGRmX2RvY3VtZW50OiANCiAgICBsYXRleF9lbmdpbmU6IHhlbGF0ZXgNCi0tLQ0KDQpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcyd9DQpjYXQoJzxzdHlsZT5wIHsgdGV4dC1hbGlnbjoganVzdGlmeTsgfTwvc3R5bGU+JykNCmBgYA0KDQojIMSQ4buNYyAgZOG7ryBsaeG7h3UNCg0KKipob2FuZ3RpbmhkdWxpZXUqKiBsw6AgYuG7mSBk4buvIGxp4buHdSBjaOG7qWEgdGjDtG5nIHRpbiB04buVbmcgaOG7o3AgduG7gSBuaMOibiBraOG6qXUgaOG7jWMgdsOgIMSR4bq3YyDEkWnhu4NtIGtpbmggdOG6vyB4w6MgaOG7mWkgY+G7p2Ega2hv4bqjbmcgMjUuMDAwIG5nxrDhu51pIMSRYW5nIHNpbmggc+G7kW5nIHbDoCBsw6BtIHZp4buHYyB04bqhaSBN4bu5LiBE4buvIGxp4buHdSDEkcaw4bujYyB4w6J5IGThu7FuZyBk4buxYSB0csOqbiBuZ3Xhu5NuIGfhu5FjIHThu6sgQ3VycmVudCBQb3B1bGF0aW9uIFN1cnZleSAoQ1BTKSDigJMgbeG7mXQgY2jGsMahbmcgdHLDrG5oIGto4bqjbyBzw6F0IGTDom4gc+G7kSB1eSB0w61uIMSRxrDhu6NjIHRo4buxYyBoaeG7h24gaMOgbmcgbsSDbSBi4bufaSBD4bulYyDEkWnhu4F1IHRyYSBkw6JuIHPhu5EgSG9hIEvhu7MgKFUuUy4gQ2Vuc3VzIEJ1cmVhdSkgcGjhu5FpIGjhu6NwIHbhu5tpIEJ1cmVhdSBvZiBMYWJvciBTdGF0aXN0aWNzLg0KDQpC4buZIGThu68gbGnhu4d1IMSRw6MgxJHGsOG7o2MgdHLDrWNoIGzhu41jLCB44butIGzDvSB2w6AgdMOhaSBj4bqldSB0csO6YyBuaOG6sW0gcGjhu6VjIHbhu6UgY2hvIG3hu6VjIHRpw6p1IHBow6JuIHTDrWNoIHbDoCBodeG6pW4gbHV54buHbiBtw7QgaMOsbmggaOG7jWMgbcOheSB0cm9uZyBjw6FjIG5naGnDqm4gY+G7qXUgbGnDqm4gcXVhbiDEkeG6v24ga2luaCB04bq/IGjhu41jLCBow6BuaCB2aSBsYW8gxJHhu5luZyB2w6AgYuG6pXQgYsOsbmggxJHhurNuZyB0aHUgbmjhuq1wLg0KDQoNCg0KIyMgIMSQ4buNYyBmaWxlDQpgYGB7cn0NCmQgPC1yZWFkLmNzdihmaWxlLmNob29zZSgpLCBoZWFkZXI9VCkNCmBgYA0KDQpEw7JuZyBs4buHbmggYGQgPC0gcmVhZC5jc3YoZmlsZS5jaG9vc2UoKSwgaGVhZGVyID0gVFJVRSlgIGTDuW5nIMSR4buDIMSR4buNYyBk4buvIGxp4buHdSB04burIG3hu5l0IGZpbGUgQ1NWIGNo4buNbiB0csOqbiBtw6F5IHTDrW5oLg0KDQoqIGBmaWxlLmNob29zZSgpYCBt4bufIGjhu5lwIHRob+G6oWkgY2jhu41uIGZpbGUuDQoqIGByZWFkLmNzdiguLi4pYCDEkeG7jWMgZmlsZSBDU1YgdsOgIHRy4bqjIHbhu4EgZOG6oW5nIGLhuqNuZyBk4buvIGxp4buHdSAoZGF0YSBmcmFtZSkuDQoqIGBoZWFkZXIgPSBUUlVFYCBuZ2jEqWEgbMOgIGTDsm5nIMSR4bqndSB0acOqbiBj4bunYSBmaWxlIGzDoCB0w6puIGPDoWMgY+G7mXQuDQoqIEvhur90IHF14bqjIMSRxrDhu6NjIGzGsHUgdsOgbyBiaeG6v24gYGRgIMSR4buDIHPhu60gZOG7pW5nIGNobyBjw6FjIHBow6JuIHTDrWNoIHRp4bq/cCB0aGVvLg0KDQojIyAgSGnhu4NuIHRo4buLIGPhuqV1IHRyw7pjIGPhu6dhIGThu68gbGnhu4d1DQoNCmBgYHtyfQ0Kc3RyKGQpDQpgYGANCg0KLSBgc3RyKC4uLilgIGzDoCB2aeG6v3QgdOG6r3QgY+G7p2Egc3RydWN0dXJlIOKAkyBkw7luZyDEkeG7gyBraeG7g20gdHJhIG5oYW5oIHRow7RuZyB0aW4gduG7gSBz4buRIGTDsm5nLCBz4buRIGPhu5l0LCB0w6puIGJp4bq/biB2w6Aga2nhu4N1IGThu68gbGnhu4d1IGPhu6dhIHThu6tuZyBiaeG6v24uDQoNCi0gS2hpIGTDuW5nIGBzdHIoZClgLCBi4bqhbiBz4bq9IGJp4bq/dCDEkcaw4bujYzoNCg0KKyBkIGPDsyBiYW8gbmhpw6p1IHF1YW4gc8OhdCAocm93cykgdsOgIGJp4bq/biAoY29sdW1ucykNCg0KKyBUw6puIGPhu6dhIGPDoWMgYmnhur9uDQoNCisgS2nhu4N1IGThu68gbGnhu4d1IGPhu6dhIHThu6tuZyBiaeG6v24gKHZkOiBpbnQsIGNociwgZmFjdG9yLCBudW0uLi4pDQoNCj0+IEThu68gbGnhu4d1IGJhbyBn4buTbTogMzI1NjEgcXVhbiBzw6F0IHbDoCAxMiBiaeG6v24sIHRyb25nIMSRw7MgY8OzIDcgYmnhur9uIMSR4buLbmggdMOtbmgNCg0KYGBge3J9DQp2YXJpYWJsZV9leHBsYWluIDwtIGRhdGEuZnJhbWUoDQogIFRlbl9CaWVuID0gYygiYWdlIiwgIkNlbnN1c1dlaWdodCIsICJsZWFybmluZ0xldmVsIiwgImxlYXJuaW5nTGV2ZWwubnVtIiwgIlBhcnRuZXJpbmdTdGF0ZSIsIA0KICAgICAgICAgICAgICAgIkZhbWlseVJvbGUiLCAiRXRobmljaXR5IiwgIkdlbmRlciIsICJOZWdhdGl2ZUNhcGl0YWxGbG93IiwgIldlZWtseUhvdXJzIiwgDQogICAgICAgICAgICAgICAiTmF0aW9uYWxpdHkiLCAiRWFybmluZ0NsYXNzIiksDQogIFlfTmdoaWEgPSBjKA0KIsSQ4buZIHR14buVaSBj4bunYSBuZ8aw4budaSDEkcaw4bujYyBraOG6o28gc8OhdCIsDQoixJDhuqFpIGRp4buHbiBj4bunYSBjw6EgbmjDom4gdHJvbmcgbeG6q3UgxJFp4buBdSB0cmEgZMOibiBz4buRIiwNCiJUcsOsbmggxJHhu5kgaOG7jWMgduG6pW4gY2jDrW5oIHRo4bupYyAodsOtIGThu6U6IFThu5F0IG5naGnhu4dwIGPhuqVwIDMsIMSQ4bqhaSBo4buNYyBjaMawYSBob8OgbiB0aMOgbmgpIiwNCiJT4buRIG7Eg20gaOG7jWMgdOG6rXAgY2jDrW5oIHF1eSB0xrDGoW5nIMSRxrDGoW5nIHbhu5tpIHRyw6xuaCDEkeG7mSBo4buNYyB24bqlbiIsDQoiVMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIGhp4buHbiB04bqhaSAoxJDDoyBr4bq/dCBow7RuLCBMeSB0aMOibiwgR8OzYSB24bujL2No4buTbmcuLi4pIiwNCiJWYWkgdHLDsiB0cm9uZyBo4buZIGdpYSDEkcOsbmggKHbDrSBk4bulOiBDb24gY8OhaSwgS2jDtG5nIHRodeG7mWMgaOG7mSBnaWEgxJHDrG5oKSIsDQoiQ2jhu6duZyB04buZYyBob+G6t2MgbmjDs20gZMOibiB04buZYyAoTmfGsOG7nWkgZGEgdHLhuq9uZywgQ2jDonUgw4EsIHYudi4pIiwNCiJHaeG7m2kgdMOtbmggY+G7p2EgY8OhIG5ow6JuIChOYW0gaG/hurdjIE7hu68pIiwNCiJN4bupYyBs4buXIHTDoGkgc+G6o24gcGjDoXQgc2luaCB04burIGhv4bqhdCDEkeG7mW5nIMSR4bqndSB0xrAgduG7kW4iLA0KIlPhu5EgZ2nhu50gbMOgbSB2aeG7h2MgdHJ1bmcgYsOsbmggdHJvbmcgbeG7mXQgdHXhuqduIiwNCiJRdeG7kWMgZ2lhIG7GoWkgY8OhIG5ow6JuIHNpbmggc+G7kW5nIGhv4bq3YyBraGFpIGLDoW8gbMOgIG7GoWkgc2luaCIsDQoiVGh1IG5o4bqtcCBjw6EgbmjDom4gbeG7l2kgbsSDbSINCiAgKQ0KKQ0KDQpsaWJyYXJ5KGtuaXRyKQ0Ka2FibGUodmFyaWFibGVfZXhwbGFpbiwgY2FwdGlvbiA9ICJHaeG6o2kgdGjDrWNoIGPDoWMgYmnhur9uIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UiKQ0KDQoNCmBgYA0KDQotIGB2YXJpYWJsZV9leHBsYWluIDwtIGRhdGEuZnJhbWUoLi4uKWAgOiBU4bqhbyBt4buZdCBi4bqjbmcgZOG7ryBsaeG7h3UgKGRhdGEgZnJhbWUpIGfhu5NtIDIgY+G7mXQNCg0KKyBUZW5fQmllbjogVMOqbiBiaeG6v24gdHJvbmcgYuG7mSBk4buvIGxp4buHdS4NCg0KKyBZX05naGlhOiDDnSBuZ2jEqWEgbcO0IHThuqMgY+G7p2EgdOG7q25nIGJp4bq/biDEkcOzLg0KDQotIGBrYWJsZSh2YXJpYWJsZV9leHBsYWluLCBjYXB0aW9uID0gIkdp4bqjaSB0aMOtY2ggY8OhYyBiaeG6v24iKWA6IEjDoG0ga2FibGUoKSBkw7luZyDEkeG7gyBoaeG7g24gdGjhu4sgYuG6o25nIG3DtCB04bqjIHRyw6puIGTGsOG7m2kgZOG6oW5nIHRyw6xuaCBiw6B5IHLDtSByw6BuZywgZOG7hSDEkeG7jWMuIA0KDQotIGBjYXB0aW9uID0gIkdp4bqjaSB0aMOtY2ggY8OhYyBiaeG6v24iYCDEkeG6t3QgdGnDqnUgxJHhu4EgY2hvIGLhuqNuZyBsw6AgIkdp4bqjaSB0aMOtY2ggY8OhYyBiaeG6v24iLg0KDQojIyAgSGnhu4NuIHRo4buLIG3hu5l0IHbDoGkgZMOybmcgxJHhuqd1IHbDoCBjdeG7kWkgY+G7p2EgZOG7ryBsaeG7h3UNCg0KLSBgaGVhZChkKWA6IEhp4buDbiB0aOG7iyA2IGTDsm5nIMSR4bqndSBj4bunYSBi4buZIGThu68gbGnhu4d1DQoNCmBgYHtyfQ0KIyBIaeG7g24gdGjhu4sgNiBkw7JuZyDEkeG6p3UgY+G7p2EgYuG7mSBk4buvIGxp4buHdQ0KaGVhZChkKQ0KYGBgDQoNCi0gYHRhaWwoZClgOiBIaeG7g24gdGjhu4sgNiBkw7JuZyBjdeG7kWkgY+G7p2EgYuG7mSBk4buvIGxp4buHdQ0KDQpgYGB7cn0NCiMgSGnhu4NuIHRo4buLIDYgZMOybmcgY3Xhu5FpIGPhu6dhIGLhu5kgZOG7ryBsaeG7h3UNCnRhaWwoZCkNCmBgYA0KDQojIyAgS2nhu4NtIHRyYSBnacOhIHRy4buLIHRoaeG6v3UNCg0KYGBge3J9DQpzdW0oaXMubmEoZCkpDQoNCmBgYA0KLSBgc3VtKGlzLm5hKGQpKWA6IEtp4buDbSB0cmEgdOG7lW5nIHPhu5EgZ2nDoSB0cuG7iyBOQSB0cm9uZyB0b8OgbiBi4buZIGLhuqNuZy4NCg0KPT4gS+G6v3QgcXXhuqM6IFRyb25nIGLhu5kgZOG7ryBsaeG7h3Uga2jDtG5nIGPDsyBnacOhIHRy4buLIHRoaeG6v3UgKE5BKS4NCg0KIyMgIENodXnhu4NuIMSR4buVaSBjw6FjIGJp4bq/biBj4bqnbiB0aGnhur90DQoNCmBgYHtyfQ0KIyDEkOG7jWMgZOG7ryBsaeG7h3UNCmQgPC0gcmVhZC5jc3YoImhvYW5ndGluaGR1bGlldS5jc3YiKQ0KDQojIERhbmggc8OhY2ggY8OhYyBiaeG6v24gxJHhu4tuaCB0w61uaCAoY2F0ZWdvcmljYWwgdmFyaWFibGVzKQ0KY29sc190b19mYWN0b3IgPC0gYygibGVhcm5pbmdMZXZlbCIsICJQYXJ0bmVyaW5nU3RhdGUiLCAiRmFtaWx5Um9sZSIsDQogICAgICAgICAgICAgICAgICAgICJFdGhuaWNpdHkiLCAiR2VuZGVyIiwgIk5hdGlvbmFsaXR5IiwgIkVhcm5pbmdDbGFzcyIpDQoNCiMgQ2h1eeG7g24gY8OhYyBj4buZdCDEkcOzIHNhbmcgZmFjdG9yDQpkW2NvbHNfdG9fZmFjdG9yXSA8LSBsYXBwbHkoZFtjb2xzX3RvX2ZhY3Rvcl0sIGFzLmZhY3RvcikNCg0KIyBLaeG7g20gdHJhIGzhuqFpIGPhuqV1IHRyw7pjIGThu68gbGnhu4d1DQpzdHIoZCkNCg0KDQpgYGANCg0KxJDhuqd1IHRpw6puLCBj4bqnbiB4w6FjIMSR4buLbmggY8OhYyBiaeG6v24gY8OzIGdpw6EgdHLhu4sgcuG7nWkgcuG6oWMgdsOgIG1hbmcgdMOtbmggcGjDom4gbG/huqFpLCB0aMaw4budbmcgZMO5bmcgxJHhu4MgYmnhu4N1IGRp4buFbiB0aMO0bmcgdGluIMSR4buLbmggdMOtbmggbmjGsCBnaeG7m2kgdMOtbmgsIGjhu41jIHbhuqVuLCB0w6xuaCB0cuG6oW5nIGjDtG4gbmjDom4sIHYudi4gRGFuaCBzw6FjaCBuw6B5IHPhur0gxJHGsOG7o2Mgc+G7rSBk4bulbmcgxJHhu4MgY2h1eeG7g24gc2FuZyBraeG7g3UgZOG7ryBsaeG7h3UgZmFjdG9yLg0KDQpTYXUgxJHDsywgw6FwIGThu6VuZyBow6BtIGxhcHBseSguLi4sIGFzLmZhY3RvcikgxJHhu4MgY2h1eeG7g24gxJHhu5VpIHThu6tuZyBiaeG6v24gdHJvbmcgZGFuaCBzw6FjaCB0aMOgbmgga2nhu4N1IGZhY3Rvci4NCg0KQ3Xhu5FpIGPDuW5nLCBj4bqtcCBuaOG6rXQgYuG6o25nIGThu68gbGnhu4d1IGQgduG7m2kgY8OhYyBj4buZdCDEkcOjIMSRxrDhu6NjIGNodXnhu4NuIMSR4buVaSBzYW5nIGThuqFuZyBwaMOibiBsb+G6oWkuDQoNCkPDoWMgYmnhur9uIMSR4buLbmggdMOtbmggYmFvIGfhu5NtOg0KDQpsZWFybmluZ0xldmVsOiBiaeG7g3UgdGjhu4sgdHLDrG5oIMSR4buZIGjhu41jIHbhuqVuIHbhu5tpIDE2IGPhuqVwIMSR4buZIGtow6FjIG5oYXUgKHbDrSBk4bulOiBIUy1ncmFkLCBCYWNoZWxvcnMsIFNvbWUtY29sbGVnZS4uLikNCg0KUGFydG5lcmluZ1N0YXRlOiB0aOG7gyBoaeG7h24gdMOsbmggdHLhuqFuZyBxdWFuIGjhu4cgbmjGsCBNYXJyaWVkLCBEaXZvcmNlZCwgV2lkb3dlZCwgU2VwYXJhdGVkLCBOZXZlci1tYXJyaWVkDQoNCkZhbWlseVJvbGU6IG3DtCB04bqjIHbhu4sgdHLDrSBj4bunYSBjw6EgbmjDom4gdHJvbmcgaOG7mSBnaWEgxJHDrG5oLCBuaMawIE93bi1jaGlsZCwgTm90LWluLWZhbWlseSwgSHVzYmFuZCwgV2lmZS4uLg0KDQpFdGhuaWNpdHk6IGfhu5NtIDUgbmjDs20gY2jhu6duZyB04buZYyBjaMOtbmggdHJvbmcgZOG7ryBsaeG7h3UNCg0KR2VuZGVyOiAyIGdpw6EgdHLhu4sgKE1hbGUsIEZlbWFsZSkNCg0KTmF0aW9uYWxpdHk6IHF14buRYyBnaWEgeHXhuqV0IHjhu6ksIHbhu5tpIGjGoW4gMzAgcXXhu5FjIGdpYSAocGjhuqduIGzhu5tuIGzDoCBVbml0ZWQtU3RhdGVzKQ0KDQpFYXJuaW5nQ2xhc3M6IHBow6JuIGxv4bqhaSB0aHUgbmjhuq1wIGPDoSBuaMOibiB0aMOgbmggMiBuaMOzbSAoPD01MEssID41MEspDQoNCg0KDQojICBQaMOibiB0w61jaCBNw7QgdOG6oyBN4buZdCBiaeG6v24gxJDhu4tuaCB0w61uaA0KDQoNCmBgYHtyfQ0KIyBEYW5oIHPDoWNoIGJp4bq/biDEkeG7i25oIHTDrW5oIHRo4buxYyB04bq/IHRyb25nIGZpbGUNCnRiZHQgPC0gYygibGVhcm5pbmdMZXZlbCIsICJQYXJ0bmVyaW5nU3RhdGUiLCAiRmFtaWx5Um9sZSIsDQogICAgICAgICAgIkV0aG5pY2l0eSIsICJHZW5kZXIiLCAiTmF0aW9uYWxpdHkiLCAiRWFybmluZ0NsYXNzIikNCg0KIyBU4bqhbyBi4bqjbmcgY29uIGNo4buJIGfhu5NtIGPDoWMgYmnhur9uIMSR4buLbmggdMOtbmgNCmRxIDwtIGRbLCB0YmR0XQ0KDQojIEtp4buDbSB0cmENCnN0cihkcSkNCg0KYGBgDQoNCi0gxJDDonkgbMOgIGRhbmggc8OhY2ggKHZlY3RvcikgY2jhu6lhIHTDqm4gY8OhYyBj4buZdCDigJMgxJHhu4F1IGzDoCBiaeG6v24gxJHhu4tuaCB0w61uaC4NCg0KLSBM4bqleSB0b8OgbiBi4buZIGPDoWMgY+G7mXQgdHJvbmcgZGFuaCBzw6FjaCB0YmR0IHThu6sgYuG6o25nIGThu68gbGnhu4d1IGQsIHbDoCB04bqhbyByYSBt4buZdCBi4bqjbmcgbeG7m2kgdMOqbiBsw6AgZHEuDQoNCj0+IEvhur90IHF14bqjIGzDoCBi4bqjbmcgZHEgY2jhu4kgY2jhu6lhIGPDoWMgYmnhur9uIMSR4buLbmggdMOtbmguDQoNCiMjICoqQmnhur9uIGxlYXJuaW5nTGV2ZWwqKg0KDQojIyMgR2nhuqNpIHRow61jaCBiaeG6v24NCg0KYGBge3J9DQojIFThuqFvIGLhuqNuZyBnaeG6o2kgdGjDrWNoIGPDoWMgbeG7qWMgY+G7p2EgYmnhur9uIGxlYXJuaW5nTGV2ZWwNCmxlYXJuaW5nTGV2ZWxfbGV2ZWxzIDwtIGRhdGEuZnJhbWUoDQogIEdpYV90cmkgPSBjKCJQcmVzY2hvb2wiLCAiMXN0LTR0aCIsICI1dGgtNnRoIiwgIjd0aC04dGgiLCAiOXRoIiwgIjEwdGgiLA0KICAgICAgICAgICAgICAiMTF0aCIsICIxMnRoIiwgIkhTLWdyYWQiLCAiU29tZS1jb2xsZWdlIiwgIkFzc29jLWFjZG0iLCANCiAgICAgICAgICAgICAgIkFzc29jLXZvYyIsICJCYWNoZWxvcnMiLCAiTWFzdGVycyIsICJQcm9mLXNjaG9vbCIsICJEb2N0b3JhdGUiKSwNCiAgWV9uZ2hpYSA9IGMoDQogICAgIlRyw6xuaCDEkeG7mSBt4bqnbSBub24iLA0KICAgICJI4buNYyBo4bq/dCBs4bubcCAxIMSR4bq/biBs4bubcCA0IiwNCiAgICAiSOG7jWMgaOG6v3QgbOG7m3AgNSBob+G6t2MgbOG7m3AgNiIsDQogICAgIkjhu41jIGjhur90IGzhu5twIDcgaG/hurdjIGzhu5twIDgiLA0KICAgICJI4buNYyBo4bq/dCBs4bubcCA5IiwNCiAgICAiSOG7jWMgaOG6v3QgbOG7m3AgMTAiLA0KICAgICJI4buNYyBo4bq/dCBs4bubcCAxMSIsDQogICAgIkjhu41jIGjhur90IGzhu5twIDEyIG5oxrBuZyBraMO0bmcgdOG7kXQgbmdoaeG7h3AiLA0KICAgICJU4buRdCBuZ2hp4buHcCB0cnVuZyBo4buNYyBwaOG7lSB0aMO0bmcgKEhTLWdyYWQpIiwNCiAgICAiSOG7jWMgxJHhuqFpIGjhu41jL2NhbyDEkeG6s25nIG5oxrBuZyBjaMawYSBjw7MgYuG6sW5nIiwNCiAgICAiQuG6sW5nIGNhbyDEkeG6s25nIGjhu41jIHRodeG6rXQgKEFzc29jaWF0ZSBpbiBBY2FkZW1pYyBQcm9ncmFtKSIsDQogICAgIkLhurFuZyBjYW8gxJHhurNuZyBuZ2jhu4EgKEFzc29jaWF0ZSBpbiBWb2NhdGlvbmFsIFByb2dyYW0pIiwNCiAgICAiQuG6sW5nIGPhu60gbmjDom4gKMSQ4bqhaSBo4buNYykiLA0KICAgICJC4bqxbmcgdGjhuqFjIHPEqSIsDQogICAgIkLhurFuZyBjaHV5w6puIG5nw6BuaCBzYXUgxJHhuqFpIGjhu41jIChsdeG6rXQsIHkga2hvYeKApikiLA0KICAgICJC4bqxbmcgdGnhur9uIHPEqSINCiAgKQ0KKQ0KDQojIEhp4buDbiB0aOG7iyBi4bqjbmcNCmtuaXRyOjprYWJsZShsZWFybmluZ0xldmVsX2xldmVscywgY2FwdGlvbiA9ICJHaeG6o2kgdGjDrWNoIGPDoWMgbeG7qWMgxJHhu5kgdHJvbmcgYmnhur9uIGxlYXJuaW5nTGV2ZWwiKQ0KYGBgDQoNCi0gbGVhcm5pbmdMZXZlbF9sZXZlbHMgPC0gZGF0YS5mcmFtZSguLi4pOiBU4bqhbyBt4buZdCBi4bqjbmcgZOG7ryBsaeG7h3UgY8OzIGhhaSBj4buZdDogR2lhX3RyaSAoZ2nDoSB0cuG7iyBn4buRYyB0cm9uZyBiaeG6v24gbGVhcm5pbmdMZXZlbCkgdsOgIFlfbmdoaWEgKMO9IG5naMSpYSB0aeG6v25nIFZp4buHdCB0xrDGoW5nIOG7qW5nKS4NCg0KLSBHaWFfdHJpID0gYyguLi4pOiBU4bqtcCBo4bujcCAxNiBt4bupYyB0csOsbmggxJHhu5kgaOG7jWMgduG6pW4gxJHGsOG7o2MgbcOjIGhvw6EgdHJvbmcgZOG7ryBsaeG7h3UsIHbDrSBk4bulICJQcmVzY2hvb2wiLCAiQmFjaGVsb3JzIiwgIkRvY3RvcmF0ZSIuLi4NCg0KLSBZX25naGlhID0gYyguLi4pOiBDdW5nIGPhuqVwIGdp4bqjaSB0aMOtY2ggdGnhur9uZyBWaeG7h3QgY2hvIHThu6tuZyBt4bupYyB0cm9uZyBHaWFfdHJpLiBWw60gZOG7pSAiUHJlc2Nob29sIiB0xrDGoW5nIOG7qW5nIHbhu5tpICJUcsOsbmggxJHhu5kgbeG6p20gbm9uIiwgIkJhY2hlbG9ycyIgbMOgICJC4bqxbmcgY+G7rSBuaMOibiIuLi4NCg0KLSBrbml0cjo6a2FibGUobGVhcm5pbmdMZXZlbF9sZXZlbHMsIGNhcHRpb24gPSAiR2nhuqNpIHRow61jaCBjw6FjIG3hu6ljIMSR4buZIHRyb25nIGJp4bq/biBsZWFybmluZ0xldmVsIik6IETDuW5nIGjDoG0ga2FibGUoKSDEkeG7gyBpbiBi4bqjbmcgcmEgxJHhurlwIGjGoW4ga2hpIHThuqFvIGLDoW8gY8OhbyBSIE1hcmtkb3duLiBjYXB0aW9uIGzDoCB0acOqdSDEkeG7gSBoaeG7g24gdGjhu4sgdHLDqm4gYuG6o25nLg0KDQojIyMgVGjhu5FuZyBrw6ogdOG6p24gc3XhuqV0DQpgYGB7cn0NCiMgVOG6oW8gYuG6o25nIHThuqduIHN14bqldCBjaG8gbGVhcm5pbmdMZXZlbA0KdHNfZWR1IDwtIHRhYmxlKGQkbGVhcm5pbmdMZXZlbCkNCg0KIyBU4bqhbyBi4bqjbmcgZOG7ryBsaeG7h3UNCnRzX2VkdV9kZiA8LSBkYXRhLmZyYW1lKA0KICBHaWFfdHJpID0gbmFtZXModHNfZWR1KSwNCiAgVGFuX3NvID0gYXMudmVjdG9yKHRzX2VkdSksDQogIFR5X2xlID0gcm91bmQoKGFzLnZlY3Rvcih0c19lZHUpIC8gc3VtKHRzX2VkdSkpICogMTAwLCAyKQ0KKQ0KDQojIEhp4buDbiB0aOG7iyBr4bq/dCBxdeG6ow0KdHNfZWR1X2RmDQoNCmBgYA0KDQotIEdpYV90cmkgPSBuYW1lcyh0c19lZHUpOg0KTOG6pXkgdMOqbiBjw6FjIG3hu6ljIGdpw6EgdHLhu4sgKG3hu6ljIGjhu41jIHbhuqVuKSB04burIGLhuqNuZyB04bqnbiBzdeG6pXQgdHNfZWR1LCB2w60gZOG7pTogIlByZXNjaG9vbCIsICJCYWNoZWxvcnMiLCAiRG9jdG9yYXRlIi4uLg0KDQotIFRhbl9zbyA9IGFzLnZlY3Rvcih0c19lZHUpOg0KQ2h1eeG7g24gYuG6o25nIHThuqduIHN14bqldCB0aMOgbmggdmVjdG9yIMSR4buDIGzGsHUgc+G7kSBsxrDhu6NuZyB4deG6pXQgaGnhu4duIGPhu6dhIHThu6tuZyBt4bupYyBo4buNYyB24bqlbi4NCg0KLSBUeV9sZSA9IHJvdW5kKChhcy52ZWN0b3IodHNfZWR1KSAvIHN1bSh0c19lZHUpKSAqIDEwMCwgMik6DQpUw61uaCB04bu3IGzhu4cgcGjhuqduIHRyxINtIGPhu6dhIG3hu5dpIG3hu6ljIGjhu41jIHbhuqVuIHNvIHbhu5tpIHThu5VuZyB0b8OgbiBi4buZIChk4buxYSB0csOqbiB04bqnbiBzdeG6pXQpLCBy4buTaSBsw6BtIHRyw7JuIMSR4bq/biAyIGNo4buvIHPhu5EgdGjhuq1wIHBow6JuLg0KDQotIHRzX2VkdV9kZjoNCkhp4buDbiB0aOG7iyBi4bqjbmcga+G6v3QgcXXhuqMgdHNfZWR1X2RmLCBn4buTbSB0w6puIG3hu6ljIGjhu41jIHbhuqVuLCB04bqnbiBzdeG6pXQgdsOgIHThu7cgbOG7hyBwaOG6p24gdHLEg20gdMawxqFuZyDhu6luZy4NCg0KQuG7mSBk4buvIGxp4buHdSBuw6B5IGdoaSBuaOG6rW4gbmhp4buBdSBt4bupYyB0csOsbmggxJHhu5kgaOG7jWMgduG6pW4ga2jDoWMgbmhhdSBj4bunYSBuZ8aw4budaSB0aGFtIGdpYS4gVHJvbmcgxJHDszoNCg0KMyBt4bupYyDEkeG6p3UgdGnDqm4gZ+G7k206DQoNCjEwdGg6IGByIHRzX2VkdV9kZiRUYW5fc29bdHNfZWR1X2RmJEdpYV90cmkgPT0gIjEwdGgiXWAgbmfGsOG7nWkgKGNoaeG6v20gYHIgcGFzdGUwKHRzX2VkdV9kZiRUeV9sZVt0c19lZHVfZGYkR2lhX3RyaSA9PSAiMTB0aCJdLCAiJSIpYCksDQoNCjExdGg6IGByIHRzX2VkdV9kZiRUYW5fc29bdHNfZWR1X2RmJEdpYV90cmkgPT0gIjExdGgiXWAgbmfGsOG7nWkgKGNoaeG6v20gYHIgcGFzdGUwKHRzX2VkdV9kZiRUeV9sZVt0c19lZHVfZGYkR2lhX3RyaSA9PSAiMTF0aCJdLCAiJSIpYCksDQoNCjEydGg6IGByIHRzX2VkdV9kZiRUYW5fc29bdHNfZWR1X2RmJEdpYV90cmkgPT0gIjEydGgiXWAgbmfGsOG7nWkgKGNoaeG6v20gYHIgcGFzdGUwKHRzX2VkdV9kZiRUeV9sZVt0c19lZHVfZGYkR2lhX3RyaSA9PSAiMTJ0aCJdLCAiJSIpYCkuDQoNCjMgbeG7qWMgY3Xhu5FpIGPDuW5nIGfhu5NtOg0KDQpTb21lLWNvbGxlZ2U6IGByIHRzX2VkdV9kZiRUYW5fc29bdHNfZWR1X2RmJEdpYV90cmkgPT0gIlNvbWUtY29sbGVnZSJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfZWR1X2RmJFR5X2xlW3RzX2VkdV9kZiRHaWFfdHJpID09ICJTb21lLWNvbGxlZ2UiXSwgIiUiKWApLA0KDQpQcmVzY2hvb2w6IGByIHRzX2VkdV9kZiRUYW5fc29bdHNfZWR1X2RmJEdpYV90cmkgPT0gIlByZXNjaG9vbCJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfZWR1X2RmJFR5X2xlW3RzX2VkdV9kZiRHaWFfdHJpID09ICJQcmVzY2hvb2wiXSwgIiUiKWApLA0KDQpQcm9mLXNjaG9vbDogYHIgdHNfZWR1X2RmJFRhbl9zb1t0c19lZHVfZGYkR2lhX3RyaSA9PSAiUHJvZi1zY2hvb2wiXWAgbmfGsOG7nWkgKGNoaeG6v20gYHIgcGFzdGUwKHRzX2VkdV9kZiRUeV9sZVt0c19lZHVfZGYkR2lhX3RyaSA9PSAiUHJvZi1zY2hvb2wiXSwgIiUiKWApLg0KDQojIyMgVHLhu7FjIHF1YW4gaMOzYQ0KDQpgYGB7ciBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Nn0NCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBW4bq9IGJp4buDdSDEkeG7kyBj4buZdCBjaG8gYmnhur9uIGxlYXJuaW5nTGV2ZWwNCmdncGxvdCh0c19lZHVfZGYsIGFlcyh4ID0gcmVvcmRlcihHaWFfdHJpLCAtVGFuX3NvKSwgeSA9IFRhbl9zbywgZmlsbCA9IEdpYV90cmkpKSArDQogIGdlb21fY29sKGNvbG9yID0gIndoaXRlIiwgd2lkdGggPSAwLjcpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFRhbl9zbyksDQogICAgICAgICAgICB2anVzdCA9IC0wLjUsIHNpemUgPSA0LCBmb250ZmFjZSA9ICJib2xkIiwgY29sb3IgPSAibGlnaHRibHVlIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkJp4buDdSDEkeG7kyBj4buZdDogUGjDom4gYuG7kSB0csOsbmggxJHhu5kgaOG7jWMgduG6pW4gKGxlYXJuaW5nTGV2ZWwpIiwNCiAgICB4ID0gIlRyw6xuaCDEkeG7mSBo4buNYyB24bqlbiIsDQogICAgeSA9ICJU4bqnbiBz4buRIg0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpDQogICkNCg0KDQpgYGANCg0KLSBgYGB7ciBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Nn06DQrEkMOieSBsw6AgcGjhuqduIG3hu58gxJHhuqd1IGPhu6dhIG3hu5l0IGto4buRaSBtw6MgUiB0cm9uZyBSIE1hcmtkb3duLCB0aGnhur90IGzhuq1wIGvDrWNoIHRoxrDhu5tjIGjDrG5oIOG6o25oIMSR4bqndSByYTogY2hp4buBdSBy4buZbmcgMTIgxJHGoW4gduG7iywgY2hp4buBdSBjYW8gNiDEkcahbiB24buLLg0KDQotIGxpYnJhcnkoZ2dwbG90Mik6DQpO4bqhcCB0aMawIHZp4buHbiBnZ3Bsb3QyIMSR4buDIHPhu60gZOG7pW5nIGPDoWMgaMOgbSB24bq9IGJp4buDdSDEkeG7kyB0cm9uZyBo4buHIHRo4buRbmcgxJHhu5MgaOG7jWEgZ2dwbG90Lg0KDQotIGdncGxvdCh0c19lZHVfZGYsIGFlcyh4ID0gcmVvcmRlcihHaWFfdHJpLCAtVGFuX3NvKSwgeSA9IFRhbl9zbywgZmlsbCA9IEdpYV90cmkpKSA6IEto4bufaSB04bqhbyBiaeG7g3UgxJHhu5MgY+G7mXQgdOG7qyBi4bqjbmcgdHNfZWR1X2RmLiBUcuG7pWMgeCBsw6AgYmnhur9uIEdpYV90cmkgKHTDqm4gbeG7qWMgaOG7jWMgduG6pW4pLCDEkcaw4bujYyBz4bqvcCB44bq/cCB0aGVvIFRhbl9zbyBnaeG6o20gZOG6p24uIFRy4bulYyB5IGzDoCBUYW5fc28uIE3DoHUgc+G6r2MgY+G7p2EgdOG7q25nIGPhu5l0IMSRxrDhu6NjIHBow6JuIGJp4buHdCB0aGVvIEdpYV90cmkuDQoNCi0gZ2VvbV9jb2woY29sb3IgPSAid2hpdGUiLCB3aWR0aCA9IDAuNykgOg0KVuG6vSBjw6FjIGPhu5l0IGJp4buDdSDEkeG7kyB24bubaSB2aeG7gW4gdHLhuq9uZyB2w6AgxJHhu5kgcuG7mW5nIDAuNy4NCg0KLSBnZW9tX3RleHQoYWVzKGxhYmVsID0gVGFuX3NvKSwgdmp1c3QgPSAtMC41LCBzaXplID0gNCwgZm9udGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gImJsYWNrIikgOg0KVGjDqm0gbmjDo24gc+G7kSBsaeG7h3UgKGdpw6EgdHLhu4sgdOG6p24gc+G7kSkgdHLDqm4gxJHhuqd1IG3hu5dpIGPhu5l0LCBjYW5oIGNo4buJbmggbmjDo24gaMahaSBjYW8gaMahbiBj4buZdCAodmp1c3QgPSAtMC41KSwgY2jhu68gxJHhuq1tIG3DoHUgxJFlbiB2w6AgY+G7oSA0Lg0KDQotIGxhYnMoLi4uKSA6DQrEkOG6t3QgdGnDqnUgxJHhu4EgYmnhu4N1IMSR4buTIGzDoCAiQmnhu4N1IMSR4buTIGPhu5l0OiBQaMOibiBi4buRIHRyw6xuaCDEkeG7mSBo4buNYyB24bqlbiAobGVhcm5pbmdMZXZlbCkiLCB0cuG7pWMgeCBsw6AgIlRyw6xuaCDEkeG7mSBo4buNYyB24bqlbiIgdsOgIHRy4bulYyB5IGzDoCAiVOG6p24gc+G7kSIuDQoNCi0gdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMikgOg0Kw4FwIGThu6VuZyBnaWFvIGRp4buHbiB04buRaSBnaeG6o24gY2hvIGJp4buDdSDEkeG7kyB24bubaSBj4buhIGNo4buvIGPGoSBi4bqjbiBsw6AgMTIuDQoNCi0gdGhlbWUoLi4uKTogVHXhu7MgY2jhu4luaCB0aMOqbSBjaG8gYmnhu4N1IMSR4buTOg0KDQotIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIpOiBDxINuIGdp4buvYSB0acOqdSDEkeG7gSB2w6AgaW4gxJHhuq1tLg0KDQotIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSk6IFhvYXkgbmjDo24gdHLhu6VjIHggNDUgxJHhu5ksIGNhbmggbOG7gSBjaG8gZOG7hSDEkeG7jWMuDQoNCg0KYGBge3IgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTZ9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQgY2hvIHThu7cgbOG7hyBwaOG6p24gdHLEg20gdHLDrG5oIMSR4buZIGjhu41jIHbhuqVuDQpnZ3Bsb3QodHNfZWR1X2RmLCBhZXMoeCA9IHJlb3JkZXIoR2lhX3RyaSwgLVR5X2xlKSwgeSA9IFR5X2xlLCBmaWxsID0gR2lhX3RyaSkpICsNCiAgZ2VvbV9jb2woY29sb3IgPSAid2hpdGUiLCB3aWR0aCA9IDAuNykgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKFR5X2xlLCAiJSIpKSwNCiAgICAgICAgICAgIHZqdXN0ID0gLTAuNSwgc2l6ZSA9IDQsIGZvbnRmYWNlID0gImJvbGQiLCBjb2xvciA9ICJsaWdodGJsdWUiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQmnhu4N1IMSR4buTIGPhu5l0OiBU4bu3IGzhu4cgdHLDrG5oIMSR4buZIGjhu41jIHbhuqVuIChsZWFybmluZ0xldmVsKSIsDQogICAgeCA9ICJUcsOsbmggxJHhu5kgaOG7jWMgduG6pW4iLA0KICAgIHkgPSAiVOG7tyBs4buHICglKSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTIpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksDQogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKQ0KICApDQpgYGANCiMjIyBOaOG6rW4geMOpdCANCg0KSFMtZ3JhZCAodOG7kXQgbmdoaeG7h3AgcGjhu5UgdGjDtG5nKSBsw6AgdHLDrG5oIMSR4buZIGjhu41jIHbhuqVuIHBo4buVIGJp4bq/biBuaOG6pXQgduG7m2kgMTAuNTAxIG5nxrDhu51pLCBjaGnhur9tIH4zMi4zJSB04buVbmcgbeG6q3UuIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IHBo4bqnbiBs4bubbiBuZ8aw4budaSB0aGFtIGdpYSBraOG6o28gc8OhdCBjaOG7iSBk4burbmcgbOG6oWkg4bufIHRyw6xuaCDEkeG7mSB0cnVuZyBo4buNYy4NCg0KU29tZS1jb2xsZWdlICjEkcOjIGjhu41jIMSR4bqhaSBo4buNYyBuaMawbmcgY2jGsGEgdOG7kXQgbmdoaeG7h3ApIMSR4bupbmcgdGjhu6kgaGFpIHbhu5tpIDcuMjkxIG5nxrDhu51pLCB0xrDGoW5nIMSRxrDGoW5nIH4yMi40JSwgcGjhuqNuIMOhbmggeHUgaMaw4bubbmcga2jDoSBuaGnhu4F1IG5nxrDhu51pIHThu6tuZyB0aeG6v3AgY+G6rW4gYuG6rWMgaOG7jWMgxJHhuqFpIGjhu41jIG5oxrBuZyBraMO0bmcgaG/DoG4gdOG6pXQuDQoNCkJhY2hlbG9ycyAoY+G7rSBuaMOibikgbMOgIHRyw6xuaCDEkeG7mSBo4buNYyB24bqlbiDEkeG6p3kgxJHhu6cgY+G6pXAgxJHhuqFpIGjhu41jIHBo4buVIGJp4bq/biBuaOG6pXQgduG7m2kgNS4zNTUgbmfGsOG7nWkgKH4xNi41JSksIGNhbyBoxqFuIGjhurNuIHNvIHbhu5tpIGPDoWMgdHLDrG5oIMSR4buZIHNhdSDEkeG6oWkgaOG7jWMuDQoNCkPDoWMgdHLDrG5oIMSR4buZIGjhu41jIHbhuqVuIHRo4bqlcCBuaMawOg0KDQotIDExdGggKGzhu5twIDExKSDigJMgMS4xNzUgbmfGsOG7nWkNCg0KLSAxMHRoIChs4bubcCAxMCkg4oCTIDEuMDY3IG5nxrDhu51pDQoNCi0gN3RoLTh0aCDigJMgOTMzIG5nxrDhu51pDQoNCuKGkiBOaOG7r25nIG3hu6ljIG7DoHkgY2hvIHRo4bqleSBjw7JuIGPDsyBt4buZdCBi4buZIHBo4bqtbiBkw6JuIHPhu5Ega2jDtG5nIGhvw6BuIHRow6BuaCBi4bqtYyBwaOG7lSB0aMO0bmcuDQoNCkPDoWMgY+G6pXAgxJHhu5kgc2F1IMSR4bqhaSBo4buNYyBuaMawOg0KDQotIE1hc3RlcnMgKHRo4bqhYyBzxKkpIOKAkyA1NzYgbmfGsOG7nWkgKH4xLjglKQ0KDQotIERvY3RvcmF0ZSAodGnhur9uIHPEqSkg4oCTIDQxMyBuZ8aw4budaSAofjEuMyUpDQoNCi0gUHJvZi1zY2hvb2wgKGNodXnDqm4ga2hvYSBuaMawIHksIGx14bqtdCkg4oCTIDUxNCBuZ8aw4budaSAofjEuNiUpDQoNCuKGkiBU4buVbmcgbOG6oWkgY2jhu4kga2hv4bqjbmcgMS41MDAgbmfGsOG7nWkgKH40LjYlKSwgY2jhu6luZyB04buPIHPhu5EgbmfGsOG7nWkgaOG7jWMgY2FvIGjhu41jIHbhuqtuIGzDoCB0aGnhu4N1IHPhu5EuDQoNCkPDoWMgdHLDrG5oIMSR4buZIHLhuqV0IHRo4bqlcCBuaMawOg0KDQotIDFzdC00dGggKGzhu5twIDHigJM0KSDigJMgMTY4IG5nxrDhu51pDQoNCi0gUHJlc2Nob29sICht4bqrdSBnacOhbykg4oCTIDUxIG5nxrDhu51pDQoNCuKGkiBD4buxYyBr4buzIGhp4bq/bSBn4bq3cCB0cm9uZyBt4bqrdSBraOG6o28gc8OhdCAoY2jGsGEgxJHhur9uIDAuNyUgdOG7lW5nIHPhu5EpLCB0aMaw4budbmcgdGh14buZYyBuaMOzbSBuZ8aw4budaSBkaSBjxrAgaG/hurdjIGNhbyB0deG7lWkuDQoNCkPDoWMgdHLDrG5oIMSR4buZIG5n4bqvbiBo4bqhbiBob+G6t2MgbGnDqm4ga+G6v3QgbmjGsDoNCg0KLSBBc3NvYy12b2Mg4oCTIDEuMzgyIG5nxrDhu51pDQoNCi0gQXNzb2MtYWNkbSDigJMgMS43MjMgbmfGsOG7nWkNCg0K4oaSIENoaeG6v20ga2hv4bqjbmcgMy4yJSB2w6AgNS4zJSB0xrDGoW5nIOG7qW5nLCB0aOG7gyBoaeG7h24gbcO0IGjDrG5oIGdpw6FvIGThu6VjIG5naOG7gS9uZ+G6r24gaOG6oW4gY8OzIG3hurd0IG5oxrBuZyBraMO0bmcgY2hp4bq/bSDGsHUgdGjhur8uDQoNCg0KIyMgKipCaeG6v24gTWFyaXRhbFN0YXR1cyoqDQoNCiMjIyBHaeG6o2kgdGjDrWNoIGJp4bq/bg0KDQpgYGB7cn0NCiMgR2nhuqNpIHRow61jaCBjw6FjIG3hu6ljIGPhu6dhIGJp4bq/biBQYXJ0bmVyaW5nU3RhdGUNCm1hcml0YWxfbGV2ZWxzIDwtIGRhdGEuZnJhbWUoDQogIEdpYV90cmkgPSBjKCJEaXZvcmNlZCIsICJNYXJyaWVkLUFGLXNwb3VzZSIsICJNYXJyaWVkLWNpdi1zcG91c2UiLA0KICAgICAgICAgICAgICAiTWFycmllZC1zcG91c2UtYWJzZW50IiwgIk5ldmVyLW1hcnJpZWQiLCAiU2VwYXJhdGVkIiwgIldpZG93ZWQiKSwNCiAgWV9uZ2hpYSA9IGMoDQogICAgIkx5IGThu4siLA0KICAgICJL4bq/dCBow7RuIHbhu5tpIG5nxrDhu51pIHRyb25nIGzhu7FjIGzGsOG7o25nIHbFqSB0cmFuZyIsDQogICAgIsSQw6Mga+G6v3QgaMO0biBo4bujcCBwaMOhcCIsDQogICAgIkvhur90IGjDtG4gbmjGsG5nIHPhu5FuZyBseSB0aMOibiIsDQogICAgIkNoxrBhIHThu6tuZyBr4bq/dCBow7RuIiwNCiAgICAiTHkgdGjDom4gY8OzIHBow6FwIGzDvSIsDQogICAgIkfDs2EiDQogICkNCikNCg0Ka25pdHI6OmthYmxlKG1hcml0YWxfbGV2ZWxzLCBjYXB0aW9uID0gIkdp4bqjaSB0aMOtY2ggY8OhYyBt4bupYyB0cm9uZyBiaeG6v24gUGFydG5lcmluZ1N0YXRlIikNCg0KYGBgDQoNCiMjIyBUaOG7kW5nIGvDqiBU4bqnbiBzdeG6pXQNCmBgYHtyfQ0KIyBU4bqhbyBi4bqjbmcgdOG6p24gc3XhuqV0IGNobyBQYXJ0bmVyaW5nU3RhdGUNCnRzX21hcml0YWwgPC0gdGFibGUoZCRQYXJ0bmVyaW5nU3RhdGUpDQoNCiMgVOG6oW8gYuG6o25nIGThu68gbGnhu4d1DQp0c19tYXJpdGFsX2RmIDwtIGRhdGEuZnJhbWUoDQogIEdpYV90cmkgPSBuYW1lcyh0c19tYXJpdGFsKSwNCiAgVGFuX3NvID0gYXMudmVjdG9yKHRzX21hcml0YWwpLA0KICBUeV9sZSA9IHJvdW5kKChhcy52ZWN0b3IodHNfbWFyaXRhbCkgLyBzdW0odHNfbWFyaXRhbCkpICogMTAwLCAyKQ0KKQ0KDQojIEhp4buDbiB0aOG7iyBr4bq/dCBxdeG6ow0KdHNfbWFyaXRhbF9kZg0KDQoNCmBgYA0KDQotIMSQw6MgbHkgZOG7iyAoRGl2b3JjZWQpOiBjw7MgYHIgdHNfbWFyaXRhbF9kZiRUYW5fc29bdHNfbWFyaXRhbF9kZiRHaWFfdHJpID09ICJEaXZvcmNlZCJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfbWFyaXRhbF9kZiRUeV9sZVt0c19tYXJpdGFsX2RmJEdpYV90cmkgPT0gIkRpdm9yY2VkIl0sICIlIilgKS4NCg0KLSBL4bq/dCBow7RuIHbhu5tpIG5nxrDhu51pIHRyb25nIHF1w6JuIMSR4buZaSAoTWFycmllZC1BRi1zcG91c2UpOiBjw7MgYHIgdHNfbWFyaXRhbF9kZiRUYW5fc29bdHNfbWFyaXRhbF9kZiRHaWFfdHJpID09ICJNYXJyaWVkLUFGLXNwb3VzZSJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfbWFyaXRhbF9kZiRUeV9sZVt0c19tYXJpdGFsX2RmJEdpYV90cmkgPT0gIk1hcnJpZWQtQUYtc3BvdXNlIl0sICIlIilgKS4NCg0KLSDEkMOjIGvhur90IGjDtG4gaOG7o3AgcGjDoXAgKE1hcnJpZWQtY2l2LXNwb3VzZSk6IGPDsyBgciB0c19tYXJpdGFsX2RmJFRhbl9zb1t0c19tYXJpdGFsX2RmJEdpYV90cmkgPT0gIk1hcnJpZWQtY2l2LXNwb3VzZSJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfbWFyaXRhbF9kZiRUeV9sZVt0c19tYXJpdGFsX2RmJEdpYV90cmkgPT0gIk1hcnJpZWQtY2l2LXNwb3VzZSJdLCAiJSIpYCkuDQoNCi0gTHkgdGjDom4gKE1hcnJpZWQtc3BvdXNlLWFic2VudCk6IGPDsyBgciB0c19tYXJpdGFsX2RmJFRhbl9zb1t0c19tYXJpdGFsX2RmJEdpYV90cmkgPT0gIk1hcnJpZWQtc3BvdXNlLWFic2VudCJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfbWFyaXRhbF9kZiRUeV9sZVt0c19tYXJpdGFsX2RmJEdpYV90cmkgPT0gIk1hcnJpZWQtc3BvdXNlLWFic2VudCJdLCAiJSIpYCkuDQoNCi0gQ2jGsGEgdOG7q25nIGvhur90IGjDtG4gKE5ldmVyLW1hcnJpZWQpOiBjw7MgYHIgdHNfbWFyaXRhbF9kZiRUYW5fc29bdHNfbWFyaXRhbF9kZiRHaWFfdHJpID09ICJOZXZlci1tYXJyaWVkIl1gIG5nxrDhu51pIChjaGnhur9tIGByIHBhc3RlMCh0c19tYXJpdGFsX2RmJFR5X2xlW3RzX21hcml0YWxfZGYkR2lhX3RyaSA9PSAiTmV2ZXItbWFycmllZCJdLCAiJSIpYCkuDQoNCi0gTHkgdGjDom4gY8OzIHBow6FwIGzDvSAoU2VwYXJhdGVkKTogY8OzIGByIHRzX21hcml0YWxfZGYkVGFuX3NvW3RzX21hcml0YWxfZGYkR2lhX3RyaSA9PSAiU2VwYXJhdGVkIl1gIG5nxrDhu51pIChjaGnhur9tIGByIHBhc3RlMCh0c19tYXJpdGFsX2RmJFR5X2xlW3RzX21hcml0YWxfZGYkR2lhX3RyaSA9PSAiU2VwYXJhdGVkIl0sICIlIilgKS4NCg0KLSBHw7NhIChXaWRvd2VkKTogY8OzIGByIHRzX21hcml0YWxfZGYkVGFuX3NvW3RzX21hcml0YWxfZGYkR2lhX3RyaSA9PSAiV2lkb3dlZCJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfbWFyaXRhbF9kZiRUeV9sZVt0c19tYXJpdGFsX2RmJEdpYV90cmkgPT0gIldpZG93ZWQiXSwgIiUiKWApLg0KDQoNCiMjIyBUcuG7sWMgcXVhbiBow7NhDQpgYGB7ciBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Nn0NCmdncGxvdCh0c19tYXJpdGFsX2RmLCBhZXMoeCA9IHJlb3JkZXIoR2lhX3RyaSwgLVRhbl9zbyksIHkgPSBUYW5fc28sIGZpbGwgPSBHaWFfdHJpKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDAuNSwgY29sb3IgPSAicGluayIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFRhbl9zbyksIHZqdXN0ID0gLTAuMywgc2l6ZSA9IDQsIGZvbnRmYWNlID0gImJvbGQiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQmnhu4N1IMSR4buTIGPhu5l0OiBUw6xuaCB0cuG6oW5nIGjDtG4gbmjDom4gKFBhcnRuZXJpbmdTdGF0ZSkiLA0KICAgIHggPSAiVMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIiwNCiAgICB5ID0gIlThuqduIHPhu5EiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEzKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksDQogICAgDQogICkNCg0KYGBgDQoNCmBgYHtyIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD04fQ0KZ2dwbG90KHRzX21hcml0YWxfZGYsIGFlcyh4ID0gcmVvcmRlcihHaWFfdHJpLCBUeV9sZSksIHkgPSBUeV9sZSwgZmlsbCA9IEdpYV90cmkpKSArDQogIGdlb21fY29sKHdpZHRoID0gMC42LCBjb2xvciA9ICJsaWdodHBpbmsiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoVHlfbGUsICIlIikpLA0KICAgICAgICAgICAgaGp1c3QgPSAtMC4xLCBzaXplID0gNCwgZm9udGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gImxpZ2h0eWVsbG93IikgKw0KICBjb29yZF9mbGlwKCkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkJp4buDdSDEkeG7kyBj4buZdCBuZ2FuZzogVOG7tyBs4buHIHTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiAoUGFydG5lcmluZ1N0YXRlKSIsDQogICAgeCA9ICJUw6xuaCB0cuG6oW5nIGjDtG4gbmjDom4iLA0KICAgIHkgPSAiVOG7tyBs4buHICglKSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTMpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIikNCiAgKQ0KDQpgYGANCg0KLSBnZ3Bsb3QodHNfbWFyaXRhbF9kZiwgYWVzKHggPSByZW9yZGVyKEdpYV90cmksIFRhbl9zbyksIHkgPSBUYW5fc28sIGZpbGwgPSBHaWFfdHJpKSkgOiBU4bqhbyBiaeG7g3UgxJHhu5MgY+G7mXQgdOG7qyBi4bqjbmcgdHNfbWFyaXRhbF9kZi4gVHLhu6VjIGhvw6BuaCAoeCkgbMOgIGJp4bq/biBHaWFfdHJpIOKAkyBjw6FjIG3hu6ljIGPhu6dhIHTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiDigJMgxJHGsOG7o2Mgc+G6r3AgeOG6v3AgdMSDbmcgZOG6p24gdGhlbyBUYW5fc28uIFRy4bulYyB0dW5nICh5KSBsw6AgdOG6p24gc+G7kSB0xrDGoW5nIOG7qW5nLiBN4buXaSBj4buZdCBjw7MgbcOgdSBraMOhYyBuaGF1IHRoZW8gZ2nDoSB0cuG7iyBj4bunYSBHaWFfdHJpLg0KDQotIGdlb21fY29sKHdpZHRoID0gMC42LCBjb2xvciA9ICJ3aGl0ZSIpOiBW4bq9IGPDoWMgY+G7mXQgduG7m2kgY2hp4buBdSBy4buZbmcgbMOgIDAuNiB2w6Agdmnhu4FuIG3DoHUgdHLhuq9uZywgZ2nDunAgY+G7mXQgdMOhY2ggYmnhu4d0IHLDtSByw6BuZy4NCg0KLSBnZW9tX3RleHQoYWVzKGxhYmVsID0gVGFuX3NvKSwgaGp1c3QgPSAtMC4xLCBzaXplID0gNCwgZm9udGZhY2UgPSAiYm9sZCIsIGNvbG9yID0gImJsYWNrIikgOiBUaMOqbSBuaMOjbiBz4buRIGxp4buHdSAoVGFuX3NvKSBjaG8gdOG7q25nIGPhu5l0LiBOaMOjbiDEkcaw4bujYyDEkeG6t3QgaMahaSBs4buHY2ggdHLDoWkgKGhqdXN0ID0gLTAuMSksIGPhu6EgY2jhu68gNCwgaW4gxJHhuq1tIHbDoCBtw6B1IMSRZW4uDQoNCi0gY29vcmRfZmxpcCgpIDogTOG6rXQgaOG7hyB0cuG7pWMgdOG7jWEgxJHhu5kgxJHhu4MgYmnhu4N1IMSR4buTIGhp4buDbiB0aOG7iyB0aGVvIGNoaeG7gXUgbmdhbmcg4oCTIHThu6ljIGzDoCBjw6FjIGPhu5l0IHPhur0gbuG6sW0gbmdhbmcgdGhheSB2w6wgZOG7jWMuDQoNCi0gbGFicyguLi4pIDogxJDhurd0IHRpw6p1IMSR4buBIGJp4buDdSDEkeG7kyBsw6AgIkJp4buDdSDEkeG7kyBj4buZdCBuZ2FuZzogVMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIChQYXJ0bmVyaW5nU3RhdGUpIiwgdHLhu6VjIHggbMOgICJUw6xuaCB0cuG6oW5nIGjDtG4gbmjDom4iLCB0cuG7pWMgeSBsw6AgIlThuqduIHPhu5EiLg0KDQotIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTMpIDogw4FwIGThu6VuZyBnaWFvIGRp4buHbiB04buRaSBnaeG6o24gKG1pbmltYWwpIGNobyBiaeG7g3UgxJHhu5MgduG7m2kgY+G7oSBjaOG7ryBt4bq3YyDEkeG7i25oIGzDoCAxMy4NCg0KLSB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwgLi4uKQ0KVHXhu7MgY2jhu4luaCB0acOqdSDEkeG7gSBiaeG7g3UgxJHhu5MgxJHhu4MgY8SDbiBnaeG7r2EgKGhqdXN0ID0gMC41KSB2w6AgaW4gxJHhuq1tIChmYWNlID0gImJvbGQiKS4NCg0KDQojIyMgTmjhuq1uIHjDqXQNCg0KLSAiTWFycmllZC1jaXYtc3BvdXNlIiAoa+G6v3QgaMO0biBo4bujcCBwaMOhcCkgY2hp4bq/bSA0My45NCUsIGNhbyBuaOG6pXQgdHJvbmcgdG/DoG4gYuG7mSBk4buvIGxp4buHdSDigJMgY2hvIHRo4bqleSBj4bqldSB0csO6YyBnaWEgxJHDrG5oIHRydXnhu4FuIHRo4buRbmcgduG6q24gY2hp4bq/bSDGsHUgdGjhur8uDQoNCi0gIk5ldmVyLW1hcnJpZWQiIMSR4bqhdCAzMi44MSUsIGzDoCBuaMOzbSBs4bubbiB0aOG7qSBoYWksIHBo4bqjbiDDoW5oIHPhu7EgaGnhu4duIGRp4buHbiBt4bqhbmggbeG6vSBj4bunYSBuZ8aw4budaSDEkeG7mWMgdGjDom4uDQoNCi0gQ8OhYyBuaMOzbSBjw7JuIGzhuqFpIG5oxrAgIkRpdm9yY2VkIiAoMTIuMjklKSwgIk1hcnJpZWQtc3BvdXNlLWFic2VudCIgKDQuNzklKSwgIlNlcGFyYXRlZCIgKDMuMTMlKSwgdsOgICJXaWRvd2VkIiAoMy4wNSUpIGfDs3AgcGjhuqduIHThuqFvIG7Dqm4gdMOtbmggxJFhIGThuqFuZyB0cm9uZyB0w6xuaCB0cuG6oW5nIGjDtG4gbmjDom4sIG5oxrBuZyDEkeG7gXUgY2hp4bq/bSB04bu3IGzhu4cgdGjhuqVwIGjGoW4NCg0KDQojIyAqKkJp4bq/biBGYW1pbHlSb2xlKioNCg0KIyMjIEdp4bqjaSB0aMOtY2ggYmnhur9uDQoNCmBgYHtyfQ0KIyBHaeG6o2kgdGjDrWNoIGPDoWMgbeG7qWMgY+G7p2EgYmnhur9uIEZhbWlseVJvbGUNCkZhbWlseVJvbGVfbGV2ZWxzIDwtIGRhdGEuZnJhbWUoDQogIEdpYV90cmkgPSBjKCJIdXNiYW5kIiwgIk5vdC1pbi1mYW1pbHkiLCAiT3RoZXItcmVsYXRpdmUiLCANCiAgICAgICAgICAgICAgIk93bi1jaGlsZCIsICJVbm1hcnJpZWQiLCAiV2lmZSIpLA0KICBZX25naGlhID0gYygNCiAgICAiQ2jhu5NuZyIsDQogICAgIktow7RuZyBjw7luZyBnaWEgxJHDrG5oIChi4bqhbiB0cuG7jSwgYuG6oW4gYsOoKSIsDQogICAgIkjhu40gaMOgbmcga2jDoWMgKGNow6F1LCBjw7QsIGNow7ouLi4pIiwNCiAgICAiQ29uIHJ14buZdCIsDQogICAgIktow7RuZyBr4bq/dCBow7RuICjEkeG7mWMgdGjDom4sIGx5IGThu4suLi4pIiwNCiAgICAiVuG7oyINCiAgKQ0KKQ0KDQprbml0cjo6a2FibGUoRmFtaWx5Um9sZV9sZXZlbHMsIGNhcHRpb24gPSAiR2nhuqNpIHRow61jaCBjw6FjIG3hu6ljIHRyb25nIGJp4bq/biBGYW1pbHlSb2xlIikNCmBgYA0KDQoNCiMjIyBUaOG7kW5nIGvDqiBU4bqnbiBzdeG6pXQNCmBgYHtyfQ0KIyBU4bqhbyBi4bqjbmcgdOG6p24gc3XhuqV0IGNobyBGYW1pbHlSb2xlDQp0c19GYW1pbHlSb2xlIDwtIHRhYmxlKGQkRmFtaWx5Um9sZSkNCg0KIyBU4bqhbyBi4bqjbmcgZOG7ryBsaeG7h3UNCnRzX0ZhbWlseVJvbGVfZGYgPC0gZGF0YS5mcmFtZSgNCiAgR2lhX3RyaSA9IG5hbWVzKHRzX0ZhbWlseVJvbGUpLA0KICBUYW5fc28gPSBhcy52ZWN0b3IodHNfRmFtaWx5Um9sZSksDQogIFR5X2xlID0gcm91bmQoKGFzLnZlY3Rvcih0c19GYW1pbHlSb2xlKSAvIHN1bSh0c19GYW1pbHlSb2xlKSkgKiAxMDAsIDIpDQopDQoNCiMgSGnhu4NuIHRo4buLIGvhur90IHF14bqjDQp0c19GYW1pbHlSb2xlX2RmDQoNCmBgYA0KDQotIEJp4bq/biBgRmFtaWx5Um9sZWAgKG3hu5FpIHF1YW4gaOG7hyB0cm9uZyBo4buZIGdpYSDEkcOsbmgpIGJhbyBn4buTbSA2IG3hu6ljIG5oxrAgc2F1Og0KDQogIC0gKipLaMO0bmcgdHJvbmcgZ2lhIMSRw6xuaCoqIChgTm90LWluLWZhbWlseWApOiBjw7MgYHIgdHNfRmFtaWx5Um9sZV9kZiRUYW5fc29bdHNfRmFtaWx5Um9sZV9kZiRHaWFfdHJpID09ICJOb3QtaW4tZmFtaWx5Il1gIG5nxrDhu51pIChjaGnhur9tIGByIHBhc3RlMCh0c19GYW1pbHlSb2xlX2RmJFR5X2xlW3RzX0ZhbWlseVJvbGVfZGYkR2lhX3RyaSA9PSAiTm90LWluLWZhbWlseSJdLCAiJSIpYCkuDQoNCi0gKipI4buNIGjDoG5nIGtow6FjKiogKGBPdGhlci1yZWxhdGl2ZWApOiBjw7MgYHIgdHNfRmFtaWx5Um9sZV9kZiRUYW5fc29bdHNfRmFtaWx5Um9sZV9kZiRHaWFfdHJpID09ICJPdGhlci1yZWxhdGl2ZSJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfRmFtaWx5Um9sZV9kZiRUeV9sZVt0c19GYW1pbHlSb2xlX2RmJEdpYV90cmkgPT0gIk90aGVyLXJlbGF0aXZlIl0sICIlIilgKS4NCg0KLSAqKkNvbiBydeG7mXQqKiAoYE93bi1jaGlsZGApOiBjw7MgYHIgdHNfRmFtaWx5Um9sZV9kZiRUYW5fc29bdHNfRmFtaWx5Um9sZV9kZiRHaWFfdHJpID09ICJPd24tY2hpbGQiXWAgbmfGsOG7nWkgKGNoaeG6v20gYHIgcGFzdGUwKHRzX0ZhbWlseVJvbGVfZGYkVHlfbGVbdHNfRmFtaWx5Um9sZV9kZiRHaWFfdHJpID09ICJPd24tY2hpbGQiXSwgIiUiKWApLg0KDQotICoqxJDhu5ljIHRow6JuKiogKGBVbm1hcnJpZWRgKTogY8OzIGByIHRzX0ZhbWlseVJvbGVfZGYkVGFuX3NvW3RzX0ZhbWlseVJvbGVfZGYkR2lhX3RyaSA9PSAiVW5tYXJyaWVkIl1gIG5nxrDhu51pIChjaGnhur9tIGByIHBhc3RlMCh0c19GYW1pbHlSb2xlX2RmJFR5X2xlW3RzX0ZhbWlseVJvbGVfZGYkR2lhX3RyaSA9PSAiVW5tYXJyaWVkIl0sICIlIilgKS4NCg0KLSAqKlbhu6MqKiAoYFdpZmVgKTogY8OzIGByIHRzX0ZhbWlseVJvbGVfZGYkVGFuX3NvW3RzX0ZhbWlseVJvbGVfZGYkR2lhX3RyaSA9PSAiV2lmZSJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfRmFtaWx5Um9sZV9kZiRUeV9sZVt0c19GYW1pbHlSb2xlX2RmJEdpYV90cmkgPT0gIldpZmUiXSwgIiUiKWApLg0KDQoNCiMjIyBUcuG7sWMgcXVhbiBow7NhDQpgYGB7ciBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Nn0NCmdncGxvdCh0c19GYW1pbHlSb2xlX2RmLCBhZXMoeCA9IHJlb3JkZXIoR2lhX3RyaSwgLVRhbl9zbyksIHkgPSBUYW5fc28sIGZpbGwgPSBHaWFfdHJpKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDAuNSwgY29sb3IgPSAic2t5Ymx1ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFRhbl9zbyksIHZqdXN0ID0gLTAuMywgc2l6ZSA9IDQsIGZvbnRmYWNlID0gImJvbGQiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQmnhu4N1IMSR4buTIGPhu5l0OiBN4buRaSBxdWFuIGjhu4cgdHJvbmcgaOG7mSAoRmFtaWx5Um9sZSkiLA0KICAgIHggPSAiTeG7kWkgcXVhbiBo4buHIiwNCiAgICB5ID0gIlThuqduIHPhu5EiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEzKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksDQogIA0KICApDQoNCmBgYA0KDQpgYGB7ciBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Nn0NCmdncGxvdCh0c19GYW1pbHlSb2xlX2RmLCBhZXMoeCA9ICIiLCB5ID0gVHlfbGUsIGZpbGwgPSBHaWFfdHJpKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDEsIGNvbG9yID0gInNreWJsdWUiKSArDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpICsNCiAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgdHLDsm46IE3hu5FpIHF1YW4gaOG7hyB0cm9uZyBo4buZIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKFR5X2xlLCAiJSIpKSwNCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLA0KICAgICAgICAgICAgc2l6ZSA9IDQsIGNvbG9yID0gInBpbmsiKSArDQogIHRoZW1lX3ZvaWQoKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKQ0KICApDQoNCg0KYGBgDQoNCi0gY29vcmRfcG9sYXIodGhldGEgPSAieSIpIDogQ2h1eeG7g24gYmnhu4N1IMSR4buTIGPhu5l0IHRow6BuaCBiaeG7g3UgxJHhu5MgdHLDsm4gYuG6sW5nIGPDoWNoIHPhu60gZOG7pW5nIGjhu4cgdOG7jWEgxJHhu5kgY+G7sWMgKHBvbGFyIGNvb3JkaW5hdGUgc3lzdGVtKSwgdHJvbmcgxJHDsyBwaOG6p24gdHLEg20gKFR5X2xlKSDEkcaw4bujYyB4b2F5IHRoZW8gdHLhu6VjIHkgxJHhu4MgdOG6oW8gcmEgY8OhYyBwaOG6p24gaMOsbmggcXXhuqF0Lg0KDQotIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpIDogw4FwIGThu6VuZyBi4bqjbmcgbcOgdSAiU2V0MiIgdOG7qyB0aMawIHZp4buHbiBSQ29sb3JCcmV3ZXIgxJHhu4MgcGjDom4gYmnhu4d0IHRy4buxYyBxdWFuIGPDoWMgcGjhuqduIGtow6FjIG5oYXUgY+G7p2EgYmnhu4N1IMSR4buTIHRyw7JuIGLhurFuZyBjw6FjIG3DoHUgc+G6r2MgaMOgaSBow7JhLg0KDQotIHRoZW1lX3ZvaWQoKSA6IFjDs2EgdOG6pXQgY+G6oyB0aMOgbmggcGjhuqduIG7hu4FuIGPhu6dhIGJp4buDdSDEkeG7kyAodHLhu6VjLCBsxrDhu5tpLCBuaMOjbiB0cuG7pWMuLi4pLCBnacO6cCBiaeG7g3UgxJHhu5MgdHLDsm4gdHLDtG5nIGfhu41uIGfDoG5nIHbDoCBu4buVaSBi4bqtdCBoxqFuLg0KDQotIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKTog4bqobiB0acOqdSDEkeG7gSBj4bunYSBwaOG6p24gY2jDuiBnaeG6o2kgKGxlZ2VuZCkgxJHhu4MgZ2lhbyBkaeG7h24gYmnhu4N1IMSR4buTIHRy4bufIG7Dqm4gxJHGoW4gZ2nhuqNuIHbDoCBk4buFIMSR4buNYyBoxqFuLg0KDQoNCiMjIyBOaOG6rW4geMOpdA0KDQotIE5ow7NtICJIdXNiYW5kIiBjaGnhur9tIHThu7cgbOG7hyBjYW8gbmjhuqV0IHbhu5tpIDM4LjElLCBwaOG6o24gw6FuaCB2YWkgdHLDsiB0cuG7pSBj4buZdCBj4bunYSBuYW0gZ2nhu5tpIHRyb25nIGjhu5kgZ2lhIMSRw6xuaCB24bqrbiBjw7JuIHBo4buVIGJp4bq/bi4gxJBp4buBdSBuw6B5IGPDsyB0aOG7gyBsacOqbiBxdWFuIMSR4bq/biB0aMOzaSBxdWVuIGtoYWkgYsOhbyBuZ8aw4budaSDEkeG7qW5nIMSR4bqndSBo4buZIGzDoCBuYW0gZ2nhu5tpLg0KDQotICJOb3QtaW4tZmFtaWx5IiB44bq/cCB0aOG7qSBoYWkgduG7m2kgMjYuNCUsIGNobyB0aOG6pXkgY8OzIG5oaeG7gXUgY8OhIG5ow6JuIHPhu5FuZyDEkeG7mWMgbOG6rXAgaG/hurdjIGtow7RuZyB0aHXhu5ljIGjhu5kgdHJ1eeG7gW4gdGjhu5FuZyDigJMgcGjhuqNuIMOhbmggeHUgaMaw4bubbmcgc+G7kW5nIMSRxqFuIHRow6JuIHRyb25nIHjDoyBo4buZaSBoaeG7h24gxJHhuqFpLg0KDQotICJPd24tY2hpbGQiIGNoaeG6v20gMTUuNyUsIGNobyB0aOG6pXkgdOG7tyBs4buHIG5nxrDhu51pIHBo4bulIHRodeG7mWMgxJHDoW5nIGvhu4MgdHJvbmcgaOG7mSwgdHJvbmcga2hpICJXaWZlIiBjaOG7iSDEkeG6oXQgNy4yJSwgY8OzIHRo4buDIGRvIG5hbSBnaeG7m2kgbMOgIG5nxrDhu51pIMSRxrDhu6NjIGto4bqjbyBzw6F0IG5oaeG7gXUgaMahbi4NCg0KLSBDw6FjIG5ow7NtICJVbm1hcnJpZWQiICgxMS4yJSkgdsOgICJPdGhlci1yZWxhdGl2ZSIgKDEuNCUpIGPDsyB04bu3IGzhu4cgdGjhuqVwLCBuaMawbmcgZ8OzcCBwaOG6p24gbMOgbSByw7UgdMOtbmggxJFhIGThuqFuZyB0cm9uZyBj4bqldSB0csO6YyBo4buZIGdpYSDEkcOsbmggaGnhu4duIG5heS4NCiMjICoqQmnhur9uIEV0aG5pY2l0eSoqDQoNCiMjIyBHaeG6o2kgdGjDrWNoIGJp4bq/bg0KDQpgYGB7cn0NCiMgR2nhuqNpIHRow61jaCBjw6FjIG3hu6ljIGPhu6dhIGJp4bq/biBFdGhuaWNpdHkNCkV0aG5pY2l0eV9sZXZlbHMgPC0gZGF0YS5mcmFtZSgNCiAgR2lhX3RyaSA9IGMoIkFtZXItSW5kaWFuLUVza2ltbyIsICJBc2lhbi1QYWMtSXNsYW5kZXIiLCAiQmxhY2siLCAiT3RoZXIiLCAiV2hpdGUiKSwNCiAgWV9uZ2hpYSA9IGMoDQogICAgIk5nxrDhu51pIGRhIMSR4buPL1Ro4buVIGTDom4gQuG6r2MgTeG7uSIsDQogICAgIk5nxrDhu51pIGNow6J1IMOBIGhv4bq3YyBkw6JuIMSR4bqjbyBUaMOhaSBCw6xuaCBExrDGoW5nIiwNCiAgICAiTmfGsOG7nWkgZGEgxJFlbiIsDQogICAgIktow6FjIiwNCiAgICAiTmfGsOG7nWkgZGEgdHLhuq9uZyINCiAgKQ0KKQ0KDQprbml0cjo6a2FibGUoRXRobmljaXR5X2xldmVscywgY2FwdGlvbiA9ICJHaeG6o2kgdGjDrWNoIGPDoWMgbeG7qWMgdHJvbmcgYmnhur9uIEV0aG5pY2l0eSIpDQpgYGANCg0KDQojIyMgVGjhu5FuZyBrw6ogVOG6p24gc3XhuqV0DQpgYGB7cn0NCiMgVOG6oW8gYuG6o25nIHThuqduIHN14bqldCBjaG8gRXRobmljaXR5DQp0c19FdGhuaWNpdHkgPC0gdGFibGUoZCRFdGhuaWNpdHkpDQoNCiMgVOG6oW8gYuG6o25nIGThu68gbGnhu4d1DQp0c19FdGhuaWNpdHlfZGYgPC0gZGF0YS5mcmFtZSgNCiAgR2lhX3RyaSA9IG5hbWVzKHRzX0V0aG5pY2l0eSksDQogIFRhbl9zbyA9IGFzLnZlY3Rvcih0c19FdGhuaWNpdHkpLA0KICBUeV9sZSA9IHJvdW5kKChhcy52ZWN0b3IodHNfRXRobmljaXR5KSAvIHN1bSh0c19FdGhuaWNpdHkpKSAqIDEwMCwgMikNCikNCg0KIyBIaeG7g24gdGjhu4sga+G6v3QgcXXhuqMNCnRzX0V0aG5pY2l0eV9kZg0KDQpgYGANCg0KLSBCaeG6v24gYEV0aG5pY2l0eWAgKGNo4bunbmcgdOG7mWMpIGPDsyA1IG5ow7NtIG5oxrAgc2F1Og0KDQogIC0gKipOZ8aw4budaSBkYSDEkeG7jy9UaOG7lSBkw6JuIELhuq9jIE3hu7kqKiAoYEFtZXItSW5kaWFuLUVza2ltb2ApOiBgciB0c19FdGhuaWNpdHlfZGYkVGFuX3NvW3RzX0V0aG5pY2l0eV9kZiRHaWFfdHJpID09ICJBbWVyLUluZGlhbi1Fc2tpbW8iXWAgbmfGsOG7nWkgKGNoaeG6v20gYHIgcGFzdGUwKHRzX0V0aG5pY2l0eV9kZiRUeV9sZVt0c19FdGhuaWNpdHlfZGYkR2lhX3RyaSA9PSAiQW1lci1JbmRpYW4tRXNraW1vIl0sICIlIilgKS4NCg0KLSAqKk5nxrDhu51pIGNow6J1IMOBL1Row6FpIELDrG5oIETGsMahbmcqKiAoYEFzaWFuLVBhYy1Jc2xhbmRlcmApOiBgciB0c19FdGhuaWNpdHlfZGYkVGFuX3NvW3RzX0V0aG5pY2l0eV9kZiRHaWFfdHJpID09ICJBc2lhbi1QYWMtSXNsYW5kZXIiXWAgbmfGsOG7nWkgKGNoaeG6v20gYHIgcGFzdGUwKHRzX0V0aG5pY2l0eV9kZiRUeV9sZVt0c19FdGhuaWNpdHlfZGYkR2lhX3RyaSA9PSAiQXNpYW4tUGFjLUlzbGFuZGVyIl0sICIlIilgKS4NCg0KLSAqKk5nxrDhu51pIGRhIMSRZW4qKiAoYEJsYWNrYCk6IGByIHRzX0V0aG5pY2l0eV9kZiRUYW5fc29bdHNfRXRobmljaXR5X2RmJEdpYV90cmkgPT0gIkJsYWNrIl1gIG5nxrDhu51pIChjaGnhur9tIGByIHBhc3RlMCh0c19FdGhuaWNpdHlfZGYkVHlfbGVbdHNfRXRobmljaXR5X2RmJEdpYV90cmkgPT0gIkJsYWNrIl0sICIlIilgKS4NCg0KLSAqKktow6FjKiogKGBPdGhlcmApOiBgciB0c19FdGhuaWNpdHlfZGYkVGFuX3NvW3RzX0V0aG5pY2l0eV9kZiRHaWFfdHJpID09ICJPdGhlciJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfRXRobmljaXR5X2RmJFR5X2xlW3RzX0V0aG5pY2l0eV9kZiRHaWFfdHJpID09ICJPdGhlciJdLCAiJSIpYCkuDQoNCi0gKipOZ8aw4budaSBkYSB0cuG6r25nKiogKGBXaGl0ZWApOiBgciB0c19FdGhuaWNpdHlfZGYkVGFuX3NvW3RzX0V0aG5pY2l0eV9kZiRHaWFfdHJpID09ICJXaGl0ZSJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfRXRobmljaXR5X2RmJFR5X2xlW3RzX0V0aG5pY2l0eV9kZiRHaWFfdHJpID09ICJXaGl0ZSJdLCAiJSIpYCkuDQoNCg0KIyMjIFRy4buxYyBxdWFuIGjDs2ENCmBgYHtyIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD02fQ0KZ2dwbG90KHRzX0V0aG5pY2l0eV9kZiwgYWVzKHggPSByZW9yZGVyKEdpYV90cmksIC1UYW5fc28pLCB5ID0gVGFuX3NvLCBmaWxsID0gR2lhX3RyaSkpICsNCiAgZ2VvbV9jb2wod2lkdGggPSAwLjUsIGNvbG9yID0gImxpZ2h0Z3JlZW4iKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBUYW5fc28pLCB2anVzdCA9IC0wLjMsIHNpemUgPSA0LCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkJp4buDdSDEkeG7kyBj4buZdDogQ2jhu6duZyB04buZYyAoRXRobmljaXR5KSIsDQogICAgeCA9ICJDaOG7p25nIHThu5ljIiwNCiAgICB5ID0gIlThuqduIHPhu5EiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEzKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSksDQogICAgDQogICkNCg0KDQpgYGANCg0KYGBge3IgZmlnLndpZHRoPTEzLCBmaWcuaGVpZ2h0PTh9DQpnZ3Bsb3QodHNfRXRobmljaXR5X2RmLCBhZXMoeCA9IHJlb3JkZXIoR2lhX3RyaSwgVHlfbGUpLCB5ID0gVHlfbGUsIGZpbGwgPSBHaWFfdHJpKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDAuNiwgY29sb3IgPSAid2hpdGUiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoVHlfbGUsICIlIikpLCANCiAgICAgICAgICAgIGhqdXN0ID0gLTAuMSwgc2l6ZSA9IDQsIGZvbnRmYWNlID0gImJvbGQiLCBjb2xvciA9ICJwdXJwbGUiKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQmnhu4N1IMSR4buTIGPhu5l0IG5nYW5nOiBU4bu3IGzhu4cgY2jhu6duZyB04buZYyAoRXRobmljaXR5KSIsDQogICAgeCA9ICJDaOG7p25nIHThu5ljIiwNCiAgICB5ID0gIlThu7cgbOG7hyAoJSkiDQogICkgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEzKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIpLA0KICAgIA0KICApDQoNCg0KYGBgDQoNCiMjIyBOaOG6rW4geMOpdA0KDQotICJXaGl0ZSIgbMOgIG5ow7NtIGNoaeG6v20gxJFhIHPhu5Egw6FwIMSR4bqjbyB24bubaSAyNy4xOTEgbmfGsOG7nWkgKDgzLjU0JSksIHRo4buDIGhp4buHbiBz4buxIHRo4buRbmcgdHLhu4sgduG7gSBz4buRIGzGsOG7o25nIHRyb25nIG3huqt1IGto4bqjbyBzw6F0Lg0KDQotICJCbGFjayIgY2hp4bq/bSAyLjgzMCBuZ8aw4budaSAoOC42OSUpLCBsw6AgbmjDs20gdGhp4buDdSBz4buRIGzhu5tuIG5o4bqldCBzYXUgbmfGsOG7nWkgZGEgdHLhuq9uZy4NCg0KLSBDw6FjIG5ow7NtICJBc2lhbi1QYWMtSXNsYW5kZXIiLCAiQW1lci1JbmRpYW4tRXNraW1vIiwgdsOgICJPdGhlciIgbOG6p24gbMaw4bujdCBjw7MgdOG7tyBs4buHIHRo4bqlcCBoxqFuIG5oaeG7gXUsIG3hu5dpIG5ow7NtIGTGsOG7m2kgMyUsIGNobyB0aOG6pXkgdMOtbmggxJFhIGThuqFuZyBjaOG7p25nIHThu5ljIGPDsyBuaMawbmcgY2jGsGEgdGjhuq10IHPhu7EgY8OibiBi4bqxbmcuDQoNCiMjICoqQmnhur9uIE5hdGlvbmFsaXR5KioNCg0KIyMjIEdp4bqjaSB0aMOtY2ggYmnhur9uDQoNCmBgYHtyIH0NCiMgR2nhuqNpIHRow61jaCBt4buZdCBz4buRIG3hu6ljIHBo4buVIGJp4bq/biB0cm9uZyBiaeG6v24gTmF0aW9uYWxpdHkNCiMgKE7hur91IGPhuqduIGdp4bqjaSB0aMOtY2ggdG/DoG4gYuG7mSBjw7MgdGjhu4MgbeG7nyBy4buZbmcgdGjDqm0pDQpjb3VudHJ5X2xldmVscyA8LSBkYXRhLmZyYW1lKA0KICBHaWFfdHJpID0gYygiVW5pdGVkLVN0YXRlcyIsICJNZXhpY28iLCAiUGhpbGlwcGluZXMiLCAiVmlldG5hbSIsICJHZXJtYW55IiksDQogIFlfbmdoaWEgPSBjKA0KICAgICJIb2EgS+G7syIsDQogICAgIk1leGljbyIsDQogICAgIlBoaWxpcHBpbmVzIiwNCiAgICAiVmnhu4d0IE5hbSIsDQogICAgIsSQ4bupYyINCiAgKQ0KKQ0KDQprbml0cjo6a2FibGUoY291bnRyeV9sZXZlbHMsIGNhcHRpb24gPSAiR2nhuqNpIHRow61jaCBt4buZdCBz4buRIG3hu6ljIHBo4buVIGJp4bq/biB0cm9uZyBiaeG6v24gTmF0aW9uYWxpdHkiKQ0KYGBgDQoNCiMjIyBUaOG7kW5nIGvDqiBU4bqnbiBzdeG6pXQgDQpgYGB7cn0NCiMgVOG6oW8gYuG6o25nIHThuqduIHN14bqldCBjaG8gTmF0aW9uYWxpdHkNCnRzX2NvdW50cnkgPC0gdGFibGUoZCROYXRpb25hbGl0eSkNCg0KIyBU4bqhbyBi4bqjbmcgZOG7ryBsaeG7h3UNCnRzX2NvdW50cnlfZGYgPC0gZGF0YS5mcmFtZSgNCiAgR2lhX3RyaSA9IG5hbWVzKHRzX2NvdW50cnkpLA0KICBUYW5fc28gPSBhcy52ZWN0b3IodHNfY291bnRyeSksDQogIFR5X2xlID0gcm91bmQoKGFzLnZlY3Rvcih0c19jb3VudHJ5KSAvIHN1bSh0c19jb3VudHJ5KSkgKiAxMDAsIDIpDQopDQoNCiMgSGnhu4NuIHRo4buLIGvhur90IHF14bqjDQp0c19jb3VudHJ5X2RmDQoNCmBgYA0KDQotIEJp4bq/biBgTmF0aW9uYWxpdHlgIChxdeG7kWMgZ2lhIHh14bqldCB0aMOibikgY8OzIG5oaeG7gXUgbeG7qWMsIGTGsOG7m2kgxJHDonkgbMOgIG3hu5l0IHPhu5EgbeG7qWMgcGjhu5UgYmnhur9uOg0KDQogLSAqKkhvYSBL4buzKiogKGBVbml0ZWQtU3RhdGVzYCk6IGByIHRzX2NvdW50cnlfZGYkVGFuX3NvW3RzX2NvdW50cnlfZGYkR2lhX3RyaSA9PSAiVW5pdGVkLVN0YXRlcyJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfY291bnRyeV9kZiRUeV9sZVt0c19jb3VudHJ5X2RmJEdpYV90cmkgPT0gIlVuaXRlZC1TdGF0ZXMiXSwgIiUiKWApLg0KDQotICoqTWV4aWNvKio6IGByIHRzX2NvdW50cnlfZGYkVGFuX3NvW3RzX2NvdW50cnlfZGYkR2lhX3RyaSA9PSAiTWV4aWNvIl1gIG5nxrDhu51pIChjaGnhur9tIGByIHBhc3RlMCh0c19jb3VudHJ5X2RmJFR5X2xlW3RzX2NvdW50cnlfZGYkR2lhX3RyaSA9PSAiTWV4aWNvIl0sICIlIilgKS4NCg0KLSAqKlBoaWxpcHBpbmVzKio6IGByIHRzX2NvdW50cnlfZGYkVGFuX3NvW3RzX2NvdW50cnlfZGYkR2lhX3RyaSA9PSAiUGhpbGlwcGluZXMiXWAgbmfGsOG7nWkgKGNoaeG6v20gYHIgcGFzdGUwKHRzX2NvdW50cnlfZGYkVHlfbGVbdHNfY291bnRyeV9kZiRHaWFfdHJpID09ICJQaGlsaXBwaW5lcyJdLCAiJSIpYCkuDQoNCi0gKipWaeG7h3QgTmFtKio6IGByIHRzX2NvdW50cnlfZGYkVGFuX3NvW3RzX2NvdW50cnlfZGYkR2lhX3RyaSA9PSAiVmlldG5hbSJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfY291bnRyeV9kZiRUeV9sZVt0c19jb3VudHJ5X2RmJEdpYV90cmkgPT0gIlZpZXRuYW0iXSwgIiUiKWApLg0KDQotICoqxJDhu6ljKiogKGBHZXJtYW55YCk6IGByIHRzX2NvdW50cnlfZGYkVGFuX3NvW3RzX2NvdW50cnlfZGYkR2lhX3RyaSA9PSAiR2VybWFueSJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfY291bnRyeV9kZiRUeV9sZVt0c19jb3VudHJ5X2RmJEdpYV90cmkgPT0gIkdlcm1hbnkiXSwgIiUiKWApLg0KDQoNCg0KIyMjIFRy4buxYyBxdWFuIGjDs2ENCg0KYGBge3IgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTZ9DQpsaWJyYXJ5KGRwbHlyKQ0KDQp0b3BfY291bnRyeSA8LSB0c19jb3VudHJ5X2RmICU+JSANCiAgYXJyYW5nZShkZXNjKFRhbl9zbykpICU+JSANCiAgc2xpY2UoMToxMCkNCg0KZ2dwbG90KHRvcF9jb3VudHJ5LCBhZXMoeCA9IHJlb3JkZXIoR2lhX3RyaSwgLVRhbl9zbyksIHkgPSBUYW5fc28sIGZpbGwgPSBHaWFfdHJpKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDAuNSwgY29sb3IgPSAibGlnaHRibHVlIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gVGFuX3NvKSwgdmp1c3QgPSAtMC4zLCBzaXplID0gNCwgZm9udGZhY2UgPSAiYm9sZCIpICsNCiAgbGFicygNCiAgICB0aXRsZSA9ICJCaeG7g3UgxJHhu5MgY+G7mXQ6IDEwIHF14buRYyBnaWEgcGjhu5UgYmnhur9uIChOYXRpb25hbGl0eSkiLA0KICAgIHggPSAiUXXhu5FjIGdpYSIsDQogICAgeSA9ICJU4bqnbiBz4buRIg0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwNCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLA0KICAgIA0KICApDQoNCmBgYA0KDQpgYGB7ciBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Nn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgTOG6pXkgdG9wIDEwIHF14buRYyBnaWEgY8OzIHThu7cgbOG7hyBjYW8gbmjhuqV0DQp0b3BfY291bnRyeSA8LSB0c19jb3VudHJ5X2RmICU+JSANCiAgYXJyYW5nZShkZXNjKFR5X2xlKSkgJT4lIA0KICBzbGljZSgxOjEwKQ0KDQojIFbhur0gYmnhu4N1IMSR4buTDQpnZ3Bsb3QodG9wX2NvdW50cnksIGFlcyh4ID0gcmVvcmRlcihHaWFfdHJpLCBUeV9sZSksIHkgPSBUeV9sZSwgZmlsbCA9IEdpYV90cmkpKSArDQogIGdlb21fY29sKHdpZHRoID0gMC42LCBjb2xvciA9ICJsaWdodHBpbmsiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAoVHlfbGUsICIlIikpLCBoanVzdCA9IC0wLjEsIHNpemUgPSA0LCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkJp4buDdSDEkeG7kyBj4buZdCBuZ2FuZzogVOG7tyBs4buHIDEwIHF14buRYyBnaWEgcGjhu5UgYmnhur9uIG5o4bqldCAoTmF0aW9uYWxpdHkpIiwNCiAgICB4ID0gIlF14buRYyBnaWEiLA0KICAgIHkgPSAiVOG7tyBs4buHICglKSINCiAgKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTMpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIikNCiAgKQ0KDQpgYGANCg0KIyMjIE5o4bqtbiB4w6l0DQoNCi0gIlVuaXRlZC1TdGF0ZXMiIGNoaeG6v20gw6FwIMSR4bqjbyB24bubaSA4OS41OSUsIGNobyB0aOG6pXkgcGjhuqduIGzhu5tuIMSR4buRaSB0xrDhu6NuZyBraOG6o28gc8OhdCBz4buRbmcgdOG6oWkgaG/hurdjIHh14bqldCB0aMOibiB04burIEhvYSBL4buzIOKAkyBwaMO5IGjhu6NwIHbhu5tpIHZp4buHYyBk4buvIGxp4buHdSBuw6B5IMSRxrDhu6NjIHRodSB0aOG6rXAgdOG7qyBo4buHIHRo4buRbmcgdGjhu5FuZyBrw6ogZMOibiBz4buRIE3hu7kuDQoNCi0gIk1leGljbyIgxJHhu6luZyB0aOG7qSBoYWkgduG7m2kgMS45NyUsIGzDoCBxdeG7kWMgZ2lhIGfhu5FjIHBo4buVIGJp4bq/biB0aeG6v3AgdGhlbywgcGjhuqNuIMOhbmggc+G7sSBoaeG7h24gZGnhu4duIMSRw6FuZyBr4buDIGPhu6dhIG5nxrDhu51pIG5o4bqtcCBjxrAgdOG7qyBNZXhpY28uDQoNCi0gIlBoaWxpcHBpbmVzIiB2w6AgIkdlcm1hbnkiIGzhuqduIGzGsOG7o3QgY2hp4bq/bSAwLjYxJSB2w6AgMC40MiUsIGzDoCBjw6FjIHF14buRYyBnaWEgZ+G7kWMgw610IHBo4buVIGJp4bq/biBoxqFuLg0KDQotIMSQ4bq3YyBiaeG7h3QsIGPDsyB04bubaSAxLjc5JSBnacOhIHRy4buLIGzDoCBk4bqldSBo4buPaSAiPyIg4oCTIG5oaeG7gXUga2jhuqMgbsSDbmcgbMOgIGThu68gbGnhu4d1IHRoaeG6v3UgaG/hurdjIGtow7RuZyB4w6FjIMSR4buLbmguDQoNCiMjICoqQmnhur9uIEdlbmRlcioqDQoNCiMjIyBHaeG6o2kgdGjDrWNoIGJp4bq/bg0KDQpgYGB7cn0NCiMgR2nhuqNpIHRow61jaCBjw6FjIG3hu6ljIGPhu6dhIGJp4bq/biBHZW5kZXINCkdlbmRlcl9sZXZlbHMgPC0gZGF0YS5mcmFtZSgNCiAgR2lhX3RyaSA9IGMoIkZlbWFsZSIsICJNYWxlIiksDQogIFlfbmdoaWEgPSBjKCJO4buvIiwgIk5hbSIpDQopDQoNCmtuaXRyOjprYWJsZShHZW5kZXJfbGV2ZWxzLCBjYXB0aW9uID0gIkdp4bqjaSB0aMOtY2ggY8OhYyBt4bupYyB0cm9uZyBiaeG6v24gR2VuZGVyIikNCmBgYA0KDQojIyMgVGjhu5FuZyBrw6ogVOG6p24gc3XhuqV0DQpgYGB7cn0NCiMgVOG6oW8gYuG6o25nIHThuqduIHN14bqldCBjaG8gR2VuZGVyDQp0c19HZW5kZXIgPC0gdGFibGUoZCRHZW5kZXIpDQoNCiMgVOG6oW8gYuG6o25nIGThu68gbGnhu4d1DQp0c19HZW5kZXJfZGYgPC0gZGF0YS5mcmFtZSgNCiAgR2lhX3RyaSA9IG5hbWVzKHRzX0dlbmRlciksDQogIFlfbmdoaWEgPSBjKCJOYW0iLCAiTuG7ryIpLCAgIyBNYWxlLCBGZW1hbGUNCiAgVGFuX3NvID0gYXMudmVjdG9yKHRzX0dlbmRlciksDQogIFR5X2xlID0gcm91bmQoKGFzLnZlY3Rvcih0c19HZW5kZXIpIC8gc3VtKHRzX0dlbmRlcikpICogMTAwLCAyKQ0KKQ0KDQojIEhp4buDbiB0aOG7iyBr4bq/dCBxdeG6ow0KdHNfR2VuZGVyX2RmDQoNCmBgYA0KDQoNCi0gQmnhur9uIGBHZW5kZXJgIChnaeG7m2kgdMOtbmgpIGJhbyBn4buTbSAyIG3hu6ljOg0KDQogIC0gKipO4buvKiogKGBGZW1hbGVgKTogYHIgdHNfR2VuZGVyX2RmJFRhbl9zb1t0c19HZW5kZXJfZGYkR2lhX3RyaSA9PSAiRmVtYWxlIl1gIG5nxrDhu51pIChjaGnhur9tIGByIHBhc3RlMCh0c19HZW5kZXJfZGYkVHlfbGVbdHNfR2VuZGVyX2RmJEdpYV90cmkgPT0gIkZlbWFsZSJdLCAiJSIpYCkuDQoNCi0gKipOYW0qKiAoYE1hbGVgKTogYHIgdHNfR2VuZGVyX2RmJFRhbl9zb1t0c19HZW5kZXJfZGYkR2lhX3RyaSA9PSAiTWFsZSJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfR2VuZGVyX2RmJFR5X2xlW3RzX0dlbmRlcl9kZiRHaWFfdHJpID09ICJNYWxlIl0sICIlIilgKS4NCg0KDQojIyMgVHLhu7FjIHF1YW4gaMOzYQ0KDQpgYGB7ciBmaWcud2lkdGg9MTJ9DQpnZ3Bsb3QodHNfR2VuZGVyX2RmLCBhZXMoeCA9IEdpYV90cmksIHkgPSBUYW5fc28sIGZpbGwgPSBHaWFfdHJpKSkgKw0KICBnZW9tX2NvbCh3aWR0aCA9IDAuNSwgY29sb3IgPSAid2hpdGUiKSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBUYW5fc28pLCB2anVzdCA9IC0wLjMsIHNpemUgPSA0LCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBsYWJzKA0KICAgIHRpdGxlID0gIkJp4buDdSDEkeG7kyBj4buZdDogR2nhu5tpIHTDrW5oIChHZW5kZXIpIiwNCiAgICB4ID0gIkdp4bubaSB0w61uaCIsDQogICAgeSA9ICJU4bqnbiBz4buRIg0KICApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0ZGOCIsICJza3libHVlIikpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwNCiAgDQogICkNCg0KYGBgDQoNCmBgYHtyIGZpZy53aWR0aD0xMn0NCkdlbmRlcl9jb2xvcnMgPC0gYygiRmVtYWxlIiA9ICIjRkZCNkMxIiwgIk1hbGUiID0gIiM4N0NFRkEiKSAgIyBtw6B1IHR14buzIGNo4buJbmgNCg0KZ2dwbG90KHRzX0dlbmRlcl9kZiwgYWVzKHggPSAiIiwgeSA9IFR5X2xlLCBmaWxsID0gR2lhX3RyaSkpICsNCiAgZ2VvbV9jb2wod2lkdGggPSAxLCBjb2xvciA9ICJyZWQiKSArDQogIGNvb3JkX3BvbGFyKHRoZXRhID0gInkiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IEdlbmRlcl9jb2xvcnMpICsNCiAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgdHLDsm46IEdp4bubaSB0w61uaCIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChUeV9sZSwgIiUiKSksDQogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwNCiAgICAgICAgICAgIHNpemUgPSA1LCBjb2xvciA9ICJibHVlIikgKw0KICB0aGVtZV92b2lkKCkgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwNCiAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkNCiAgKQ0KDQpgYGANCg0KIyMjIE5o4bqtbiB4w6l0DQoNCi0gIk1hbGUiIGNoaeG6v20gNjYuOTQlLCBjYW8gaMahbiByw7UgcuG7h3Qgc28gduG7m2kgIkZlbWFsZSIgKDMzLjA2JSksIGNobyB0aOG6pXkgZOG7ryBsaeG7h3Uga2jhuqNvIHPDoXQgY8OzIHRo4buDIG5naGnDqm5nIHbhu4EgcGjDrWEgbmFtIGdp4bubaSDigJMgZG8gxJHhurdjIMSRaeG7g20gY2jhu41uIG3huqt1IGhv4bq3YyB04buJIGzhu4cgdGhhbSBnaWEga2jhuqNvIHPDoXQuDQoNCiMjICoqQmnhur9uIEVhcm5pbmdDbGFzcyoqDQoNCiMjIyBHaeG6o2kgdGjDrWNoIGJp4bq/bg0KDQpgYGB7cn0NCiMgR2nhuqNpIHRow61jaCBjw6FjIG3hu6ljIGPhu6dhIGJp4bq/biBFYXJuaW5nQ2xhc3MNCkVhcm5pbmdDbGFzc19sZXZlbHMgPC0gZGF0YS5mcmFtZSgNCiAgR2lhX3RyaSA9IGMoIjw9NTBLIiwgIj41MEsiKSwNCiAgWV9uZ2hpYSA9IGMoIlRodSBuaOG6rXAgZMaw4bubaSBob+G6t2MgYuG6sW5nIDUwLjAwMCBVU0QvbsSDbSIsICJUaHUgbmjhuq1wIHRyw6puIDUwLjAwMCBVU0QvbsSDbSIpDQopDQoNCmtuaXRyOjprYWJsZShFYXJuaW5nQ2xhc3NfbGV2ZWxzLCBjYXB0aW9uID0gIkdp4bqjaSB0aMOtY2ggY8OhYyBt4bupYyB0cm9uZyBiaeG6v24gRWFybmluZ0NsYXNzIikNCmBgYA0KDQojIyMgVGjhu5FuZyBrw6ogVOG6p24gc3XhuqV0DQpgYGB7cn0NCiMgVOG6oW8gYuG6o25nIHThuqduIHN14bqldCBjaG8gRWFybmluZ0NsYXNzDQp0c19FYXJuaW5nQ2xhc3MgPC0gdGFibGUoZCRFYXJuaW5nQ2xhc3MpDQoNCiMgVOG6oW8gYuG6o25nIGThu68gbGnhu4d1DQp0c19FYXJuaW5nQ2xhc3NfZGYgPC0gZGF0YS5mcmFtZSgNCiAgR2lhX3RyaSA9IG5hbWVzKHRzX0Vhcm5pbmdDbGFzcyksDQogIFlfbmdoaWEgPSBjKCLiiaQ1MEsiLCAiPjUwSyIpLA0KICBUYW5fc28gPSBhcy52ZWN0b3IodHNfRWFybmluZ0NsYXNzKSwNCiAgVHlfbGUgPSByb3VuZCgoYXMudmVjdG9yKHRzX0Vhcm5pbmdDbGFzcykgLyBzdW0odHNfRWFybmluZ0NsYXNzKSkgKiAxMDAsIDIpDQopDQoNCiMgSGnhu4NuIHRo4buLIGvhur90IHF14bqjDQp0c19FYXJuaW5nQ2xhc3NfZGYNCg0KYGBgDQoNCi0gQmnhur9uIGBFYXJuaW5nQ2xhc3NgICh0aHUgbmjhuq1wKSBjw7MgMiBt4bupYzoNCg0KICAtICoqVGh1IG5o4bqtcCBkxrDhu5tpIGhv4bq3YyBi4bqxbmcgNTBLKiogKGA8PTUwS2ApOiBgciB0c19FYXJuaW5nQ2xhc3NfZGYkVGFuX3NvW3RzX0Vhcm5pbmdDbGFzc19kZiRHaWFfdHJpID09ICI8PTUwSyJdYCBuZ8aw4budaSAoY2hp4bq/bSBgciBwYXN0ZTAodHNfRWFybmluZ0NsYXNzX2RmJFR5X2xlW3RzX0Vhcm5pbmdDbGFzc19kZiRHaWFfdHJpID09ICI8PTUwSyJdLCAiJSIpYCkuDQoNCi0gKipUaHUgbmjhuq1wIHRyw6puIDUwSyoqIChgPjUwS2ApOiBgciB0c19FYXJuaW5nQ2xhc3NfZGYkVGFuX3NvW3RzX0Vhcm5pbmdDbGFzc19kZiRHaWFfdHJpID09ICI+NTBLIl1gIG5nxrDhu51pIChjaGnhur9tIGByIHBhc3RlMCh0c19FYXJuaW5nQ2xhc3NfZGYkVHlfbGVbdHNfRWFybmluZ0NsYXNzX2RmJEdpYV90cmkgPT0gIj41MEsiXSwgIiUiKWApLg0KDQoNCiMjIyBUcuG7sWMgcXVhbiBow7NhDQpgYGB7cn0NCmdncGxvdCh0c19FYXJuaW5nQ2xhc3NfZGYsIGFlcyh4ID0gR2lhX3RyaSwgeSA9IFRhbl9zbywgZmlsbCA9IEdpYV90cmkpKSArDQogIGdlb21fY29sKHdpZHRoID0gMC41LCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IFRhbl9zbyksIHZqdXN0ID0gLTAuMywgc2l6ZSA9IDQsIGZvbnRmYWNlID0gImJvbGQiKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQmnhu4N1IMSR4buTIGPhu5l0OiBUaHUgbmjhuq1wIChFYXJuaW5nQ2xhc3MpIiwNCiAgICB4ID0gIk5ow7NtIHRodSBuaOG6rXAiLA0KICAgIHkgPSAiVOG6p24gc+G7kSINCiAgKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM2RDU5N0EiLCAiI0ZGQjcwMyIpKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTMpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksDQogICAgDQogICkNCg0KYGBgDQoNCmBgYHtyfQ0KRWFybmluZ0NsYXNzX2NvbG9ycyA8LSBjKCI8PTUwSyIgPSAiI0ZEQjg2MyIsICI+NTBLIiA9ICIjNUUzQzk5IikNCg0KZ2dwbG90KHRzX0Vhcm5pbmdDbGFzc19kZiwgYWVzKHggPSAiIiwgeSA9IFR5X2xlLCBmaWxsID0gR2lhX3RyaSkpICsNCiAgZ2VvbV9jb2wod2lkdGggPSAxLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gRWFybmluZ0NsYXNzX2NvbG9ycykgKw0KICBsYWJzKHRpdGxlID0gIkJp4buDdSDEkeG7kyB0csOybjogVGh1IG5o4bqtcCIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChUeV9sZSwgIiUiKSksDQogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwNCiAgICAgICAgICAgIHNpemUgPSA1LCBjb2xvciA9ICJibGFjayIpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksDQogICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpDQogICkNCmBgYA0KDQojIyMgTmjhuq1uIHjDqXQNCg0KLSBOaMOzbSBjw7MgdGh1IG5o4bqtcCA8PTUwSyBjaGnhur9tIDc1LjkyJSwgY2hvIHRo4bqleSBwaOG6p24gbOG7m24gbmfGsOG7nWkgdHJvbmcgbeG6q3Uga2jhuqNvIHPDoXQgY8OzIHRodSBuaOG6rXAgdGjhuqVwIGjGoW4gbmfGsOG7oW5nIHRydW5nIGLDrG5oLg0KDQotIENo4buJIDI0LjA4JSB0aHXhu5ljIG5ow7NtIHRodSBuaOG6rXAgPjUwSywgcGjhuqNuIMOhbmggbeG7qWMgdGh1IG5o4bqtcCBjYW8gbMOgIHRoaeG7g3Ugc+G7kSB0cm9uZyBj4buZbmcgxJHhu5NuZyDEkcaw4bujYyBraOG6o28gc8OhdC4NCg0KDQojIMav4bubYyBsxrDhu6NuZyBLaG/huqNuZyB2w6AgS2nhu4NtIMSR4buLbmggR2nhuqMgdGh1eeG6v3QgY2hvIFThu7cgbOG7hw0KDQojIyAgWMOhYyDEkeG7i25oIEjhuqFuZyBt4bulYyBRdWFuIHTDom0NCg0KVGEgY2jhu41uIDMgaOG6oW5nIG3hu6VjIHThu6sgMyBiaeG6v24gdHJvbmcgZGFuaCBzw6FjaCBjw6FjIGJp4bq/biDEkeG7i25oIHTDrW5oLCBiYW8gZ+G7k206DQoNCi0gSOG6oW5nIG3hu6VjIOKAnE5ldmVyLW1hcnJpZWTigJ0gY+G7p2EgYmnhur9uIE1hcml0YWxTdGF0dXMg4oCTIFTDrG5oIHRy4bqhbmcgaMO0biBuaMOibg0KDQotIEjhuqFuZyBt4bulYyDigJxNYWxl4oCdIGPhu6dhIGJp4bq/biBHZW5kZXIg4oCTIEdp4bubaSB0w61uaA0KDQotIEjhuqFuZyBt4bulYyDigJxCYWNoZWxvcnPigJ0gY+G7p2EgYmnhur9uIGxlYXJuaW5nTGV2ZWwg4oCTIFRyw6xuaCDEkeG7mSBo4buNYyB24bqlbg0KDQojIyAgxq/hu5tjIGzGsOG7o25nIEtob+G6o25nIFRpbiBj4bqteSB2w6AgS2nhu4NtIMSR4buLbmggR2nhuqMgdGh1eeG6v3QNCg0KKirGr+G7m2MgbMaw4bujbmcgdOG7tyBs4buHIChQcm9wb3J0aW9uIEVzdGltYXRpb24pKioNCg0Kxq/hu5tjIGzGsOG7o25nIHThu7cgbOG7hyBsw6AgcXXDoSB0csOsbmggc+G7rSBk4bulbmcgZOG7ryBsaeG7h3UgdOG7qyBt4buZdCBt4bqrdSDEkeG7gyBzdXkgbHXhuq1uIHbhu4EgdOG7tyBs4buHIHTGsMahbmcg4bupbmcgdHJvbmcgdOG7lW5nIHRo4buDLiBUcm9uZyB0aOG7kW5nIGvDqiBtw7QgdOG6oywgdOG7tyBs4buHIG3huqt1IChrw70gaGnhu4d1IHRoxrDhu51uZyBsw6AgcMyCKSDEkcaw4bujYyB0w61uaCBi4bqxbmcgc+G7kSBsxrDhu6NuZyBjw6FjIHBo4bqnbiB04butIHRo4buPYSDEkWnhu4F1IGtp4buHbiBjaGlhIGNobyB04buVbmcgc+G7kSBwaOG6p24gdOG7rSB0cm9uZyBt4bqrdS4gxJDDonkgxJHGsOG7o2MgZ+G7jWkgbMOgIMaw4bubYyBsxrDhu6NuZyDEkWnhu4NtIChwb2ludCBlc3RpbWF0ZSkgY2hvIHThu7cgbOG7hyB04buVbmcgdGjhu4MgcC4gVHV5IG5oacOqbiwgZG8gdMOtbmggbmfhuqt1IG5oacOqbiBj4bunYSB2aeG7h2MgY2jhu41uIG3huqt1LCDGsOG7m2MgbMaw4bujbmcgxJFp4buDbSBraMO0bmcgdGjhu4MgxJHhuqNtIGLhuqNvIHBo4bqjbiDDoW5oIGNow61uaCB4w6FjIHThu7cgbOG7hyB0aOG7sWMgc+G7sSB0cm9uZyB04buVbmcgdGjhu4MsIGRvIMSRw7MgY+G6p24gxJFpIGvDqG0gduG7m2kgbeG7mXQga2hv4bqjbmcgdGluIGPhuq15IMSR4buDIMSRbyBsxrDhu51uZyDEkeG7mSBi4bqldCDEkeG7i25oLg0KDQoqKktob+G6o25nIHRpbiBj4bqteSoqDQoNCktob+G6o25nIHRpbiBj4bqteSBsw6AgbeG7mXQga2hv4bqjbmcgZ2nDoSB0cuG7iyBjaG8gdGEgYmnhur90IGdpw6EgdHLhu4sgdGjhuq10IGPhu6dhIG3hu5l0IHThu7cgbOG7hyBoYXkgdHJ1bmcgYsOsbmggdHJvbmcgdOG7lW5nIHRo4buDIGPDsyBraOG6oyBuxINuZyBu4bqxbSB0cm9uZyBraG/huqNuZyDEkcOzLiBOw7MgxJHGsOG7o2MgdMOtbmggdOG7qyBk4buvIGxp4buHdSBt4bqrdSwgdsOgIMSRaSBrw6htIHbhu5tpIG3hu5l0IG3hu6ljIMSR4buZIHRpbiB0xrDhu59uZyDigJMgdGjGsOG7nW5nIGzDoCA5NSUuDQoNCioqTeG7qWMgw70gbmdoxKlhIChTaWduaWZpY2FuY2UgTGV2ZWwg4oCTIM6xKSoqDQoNCk3hu6ljIMO9IG5naMSpYSwga8O9IGhp4buHdSBsw6AgzrEgKGFscGhhKSwgbMOgIHjDoWMgc3XhuqV0IGNo4bqlcCBuaOG6rW4gc2FpIGzhuqdtIGxv4bqhaSBJIOKAkyB04bupYyBsw6AgeMOhYyBzdeG6pXQgYsOhYyBi4buPIGdp4bqjIHRodXnhur90IGtow7RuZyAoSOKCgCkga2hpIG7DsyB0aOG7sWMgc+G7sSDEkcO6bmcuIFRyb25nIGtp4buDbSDEkeG7i25oIGdp4bqjIHRodXnhur90IHRo4buRbmcga8OqLCBt4bupYyDDvSBuZ2jEqWEgdGjhu4MgaGnhu4duIG5nxrDhu6FuZyBtw6AgdOG6oWkgxJHDsyB0YSBxdXnhur90IMSR4buLbmggY8OzIGLDoWMgYuG7jyBI4oKAIGhheSBraMO0bmcuIE3hu6ljIMO9IG5naMSpYSBwaOG7lSBiaeG6v24gbmjhuqV0IGzDoCDOsSA9IDAuMDUsIG5naMSpYSBsw6AgdGEgY2jhuqVwIG5o4bqtbiA1JSBy4bunaSBybyBjaG8gdmnhu4djIGvhur90IGx14bqtbiBzYWkuIEvhur90IHF14bqjIGtp4buDbSDEkeG7i25oIHRoxrDhu51uZyDEkcaw4bujYyDEkcOhbmggZ2nDoSB0aMO0bmcgcXVhIHAtdmFsdWUsIHbDoCBzbyBzw6FuaCB24bubaSDOsSDEkeG7gyDEkcawYSByYSBxdXnhur90IMSR4buLbmg6DQoNCk7hur91IHAtdmFsdWUgPCDOsSDihpIgYsOhYyBi4buPIEjigoAgKGPDsyBi4bqxbmcgY2jhu6luZyB0aOG7kW5nIGvDqikuDQoNCk7hur91IHAtdmFsdWUg4omlIM6xIOKGkiBraMO0bmcgYsOhYyBi4buPIEjigoAgKGtow7RuZyDEkeG7pyBi4bqxbmcgY2jhu6luZyB0aOG7kW5nIGvDqikuDQoNCiMjIyAgSOG6oW5nIG3hu6VjIOKAnEJhY2hlbG9yc+KAnSBj4bunYSBiaeG6v24gVHLDrG5oIMSR4buZIGjhu41jIHbhuqVuIChsZWFybmluZ0xldmVsKQ0KDQpUYSB0aOG7sWMgaGnhu4duIGtob+G6o25nIMaw4bubYyBsxrDhu6NuZyB24bubaSDEkeG7mSB0aW4gY+G6rXkgOTUlIGNobyB04bu3IGzhu4cgbmfGsOG7nWkgY8OzIGLhurFuZyBj4butIG5ow6JuIChCYWNoZWxvcnMpLCB0YSB0aOG7sWMgaGnhu4duIG5oxrAgc2F1Og0KDQpgYGB7cn0NCiMgU+G7kSBuZ8aw4budaSBjw7MgdHLDrG5oIMSR4buZIEJhY2hlbG9ycw0Kbl9iYWNoZWxvcnMgPC0gc3VtKGQkbGVhcm5pbmdMZXZlbCA9PSAiQmFjaGVsb3JzIikNCg0KIyBU4buVbmcgc+G7kSBxdWFuIHPDoXQNCm5fdG90YWwgPC0gbnJvdyhkKQ0KDQojIMav4bubYyBsxrDhu6NuZyBraG/huqNuZyB0aW4gY+G6rXkgOTUlIGNobyB04bu3IGzhu4cgbmfGsOG7nWkgY8OzIHRyw6xuaCDEkeG7mSBCYWNoZWxvcnMNCnByb3AudGVzdChuX2JhY2hlbG9ycywgbl90b3RhbCwgY29uZi5sZXZlbCA9IDAuOTUpDQoNCg0KYGBgDQoNCi0gbl9iYWNoZWxvcnMgPC0gc3VtKGQkbGVhcm5pbmdMZXZlbCA9PSAiQmFjaGVsb3JzIik6DQpUw61uaCB04buVbmcgc+G7kSBuZ8aw4budaSBjw7MgdHLDrG5oIMSR4buZIGjhu41jIHbhuqVuIGzDoCAiQmFjaGVsb3JzIiAoY+G7rSBuaMOibikgdHJvbmcgZOG7ryBsaeG7h3UgZCwgYuG6sW5nIGPDoWNoIMSR4bq/bSBz4buRIGTDsm5nIGPDsyBnacOhIHRy4buLICJCYWNoZWxvcnMiIHRyb25nIGJp4bq/biBsZWFybmluZ0xldmVsLg0KDQotIG5fdG90YWwgPC0gbnJvdyhkKToNCkzhuqV5IHThu5VuZyBz4buRIHF1YW4gc8OhdCB0cm9uZyBi4buZIGThu68gbGnhu4d1IGQsIHThu6ljIGzDoCBz4buRIGjDoG5nIGPhu6dhIGLhuqNuZyBk4buvIGxp4buHdSDigJMgZMO5bmcgxJHhu4MgbMOgbSBt4bqrdSBz4buRIHRyb25nIHTDrW5oIHRvw6FuIHThu7cgbOG7hy4NCg0KLSBwcm9wLnRlc3Qobl9iYWNoZWxvcnMsIG5fdG90YWwsIGNvbmYubGV2ZWwgPSAwLjk1KToNClRo4buxYyBoaeG7h24gcGjDqXAgxrDhu5tjIGzGsOG7o25nIGtob+G6o25nIHRpbiBj4bqteSBjaG8gdOG7tyBs4buHIG5nxrDhu51pIGPDsyB0csOsbmggxJHhu5kgY+G7rSBuaMOibiwgduG7m2kgxJHhu5kgdGluIGPhuq15IDk1JS4gSMOgbSBwcm9wLnRlc3QoKSB0cuG6oyB24buBIGtob+G6o25nIHRpbiBj4bqteSB2w6Aga2nhu4NtIMSR4buLbmggZ2nhuqMgdGh1eeG6v3QgdOG7tyBs4buHIChu4bq/dSBj4bqnbikuDQoNCipQaMOibiB0w61jaCBr4bq/dCBxdeG6oyoNCg0KLSBQaMOpcCBraeG7g20gxJHhu4tuaCDEkcaw4bujYyB0aOG7sWMgaGnhu4duIGzDoCBraeG7g20gxJHhu4tuaCB04bu3IGzhu4cgMSBt4bqrdSAoMS1zYW1wbGUgcHJvcG9ydGlvbiB0ZXN0KSB24bubaSBjaOG7iW5oIGxpw6puIHThu6VjIChjb250aW51aXR5IGNvcnJlY3Rpb24pIOKAkyBnacO6cCBj4bqjaSB0aGnhu4duIMSR4buZIGNow61uaCB4w6FjIGtoaSBz4butIGThu6VuZyBwaMOibiBwaOG7kWkgeOG6pXAgeOG7iS4NCg0KLSBE4buvIGxp4buHdSDEkeG6p3UgdsOgbyBsw6Agc+G7kSBuZ8aw4budaSBjw7MgdHLDrG5oIMSR4buZICJCYWNoZWxvcnMiIChuX2JhY2hlbG9ycykgdHJvbmcgdOG7lW5nIHPhu5EgcXVhbiBzw6F0IChuX3RvdGFsKS4gR2nhuqMgdGh1eeG6v3QgZ+G7kWMgKEjigoApIGdp4bqjIMSR4buLbmggcuG6sW5nIHThu7cgbOG7hyB0aOG7sWMgc+G7sSBwID0gMC41ICh04bupYyA1MCUgZMOibiBz4buRIGPDsyBi4bqxbmcgY+G7rSBuaMOibikuDQoNCi0gR2nDoSB0cuG7iyB0aOG7kW5nIGvDqiBraeG7g20gxJHhu4tuaCBsw6AgWC1zcXVhcmVkID0gMTQ2NjIsIHbhu5tpIGRmID0gMSAoMSBi4bqtYyB04buxIGRvKS4gR2nDoSB0cuG7iyBuw6B5IHLhuqV0IGzhu5tuLCBjaG8gdGjhuqV5IGPDsyBz4buxIGtow6FjIGJp4buHdCDEkcOhbmcga+G7gyBnaeG7r2EgdOG7tyBs4buHIG3huqt1IHbDoCB04bu3IGzhu4cgZ2nhuqMgxJHhu4tuaC4NCg0KLSBHacOhIHRy4buLIHAtdmFsdWUgPCAyLjJlLTE2LCB04bupYyBsw6AgeMOhYyBzdeG6pXQgxJHhu4MgcXVhbiBzw6F0IMSRxrDhu6NjIGThu68gbGnhu4d1IG7DoHkgbuG6v3UgZ2nhuqMgdGh1eeG6v3QgSOKCgCDEkcO6bmcgbMOgIGfhuqduIGLhurFuZyAwLiDihpIgS+G6v3QgcXXhuqMgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBy4bqldCBt4bqhbmggbeG6vS4NCg0KLSBHaeG6oyB0aHV54bq/dCDEkeG7kWkgKEjigoEpIGzDoDogdOG7tyBs4buHIHRo4buxYyB04bq/IHAga2jDoWMgMC41LiDEkMOieSBsw6Aga2nhu4NtIMSR4buLbmggaGFpIHBow61hLCBraeG7g20gdHJhIHhlbSB04bu3IGzhu4cgY8OzIGtow6FjIChs4bubbiBoxqFuIGhv4bq3YyBuaOG7jyBoxqFuKSBzbyB24bubaSA1MCUuDQoNCi0gS2hv4bqjbmcgdGluIGPhuq15IDk1JSBjaG8gdOG7tyBs4buHIG5nxrDhu51pIGPDsyB0csOsbmggxJHhu5kgQmFjaGVsb3JzIG7hurFtIHRyb25nIGtob+G6o25nIFsxNi4wNSU7IDE2Ljg1JV0sIG5naMSpYSBsw6AgdGEgY8OzIHRo4buDIHRpbiBy4bqxbmcgdOG7tyBs4buHIHRo4bqtdCBz4buxIHRyb25nIHThu5VuZyB0aOG7gyByxqFpIHbDoG8ga2hv4bqjbmcgbsOgeS4NCg0KLSBU4bu3IGzhu4cgbeG6q3UgxrDhu5tjIGzGsOG7o25nIMSRxrDhu6NjIGzDoCAxNi40NSUsIHThu7cgbOG7hyBuw6B5IHTGsMahbmcgxJHGsMahbmcgduG7m2kga2hv4bqjbmcgMTYgbmfGsOG7nWkgY8OzIGLhurFuZyBj4butIG5ow6JuIHRyw6puIG3hu5dpIDEwMCBuZ8aw4budaSB0cm9uZyBk4buvIGxp4buHdS4g4oCTIHRo4bqlcCBoxqFuIHLhuqV0IG5oaeG7gXUgc28gduG7m2kgbeG7qWMgNTAlIGdp4bqjIMSR4buLbmggYmFuIMSR4bqndS4NCg0KDQoqKkLDoGkgdG/DoW4ga2nhu4NtIMSR4buLbmg6KioNCg0KR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmg6DQoNCkdp4bqjIHRodXnhur90IGtow7RuZyBI4oKAOiBwID0gMC41ICh04bu3IGzhu4cgbmfGsOG7nWkgY8OzIGLhurFuZyBj4butIG5ow6JuIGLhurFuZyA1MCUpDQoNCkdp4bqjIHRodXnhur90IMSR4buRaSBI4oKBOiBwIOKJoCAwLjUgKHThu7cgbOG7hyBuZ8aw4budaSBjw7MgYuG6sW5nIGPhu60gbmjDom4ga2jDoWMgNTAlKQ0KDQpN4bupYyDDvSBuZ2jEqWE6IM6xID0gMC4wNQ0KDQpL4bq/dCBsdeG6rW46DQoNClbhu5tpIHAtdmFsdWUgPCAyLjJlLTE2IDwgMC4wNSwgdGEgYsOhYyBi4buPIGdp4bqjIHRodXnhur90IEjigoAuDQoNCkPDsyBi4bqxbmcgY2jhu6luZyB0aOG7kW5nIGvDqiBjaG8gdGjhuqV5IHThu7cgbOG7hyBuZ8aw4budaSBjw7MgYuG6sW5nIGPhu60gbmjDom4ga2jDoWMgNTAlLCB24bubaSDEkeG7mSB0aW4gY+G6rXkgOTUlLg0KDQpU4bu3IGzhu4cgbeG6q3UgbMOgIDE2LjQ1JSwgduG7m2kga2hv4bqjbmcgdGluIGPhuq15IG7hurFtIHRyb25nIFsxNi4wNSU7IDE2Ljg1JV0uIE3hu6ljIGNow6puaCBs4buHY2ggaMahbiAzMyDEkWnhu4NtIHBo4bqnbiB0csSDbSBzbyB24bubaSA1MCUgY2hvIHRo4bqleSBz4buxIGtow6FjIGJp4buHdCBsw6AgcsO1IHLDoG5nIHbDoCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqLg0KDQojIyMgSOG6oW5nIG3hu6VjIOKAnE5ldmVyLW1hcnJpZWTigJ0gY+G7p2EgYmnhur9uIFTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiAoUGFydG5lcmluZ1N0YXRlKSANCg0KYGBge3J9DQojIFPhu5EgbmfGsOG7nWkgY2jGsGEgdOG7q25nIGvhur90IGjDtG4NCm5fbmV2ZXJfbWFycmllZCA8LSBzdW0oZCRQYXJ0bmVyaW5nU3RhdGUgPT0gIk5ldmVyLW1hcnJpZWQiKQ0KDQojIFThu5VuZyBz4buRIHF1YW4gc8OhdA0Kbl90b3RhbCA8LSBucm93KGQpDQoNCiMgxq/hu5tjIGzGsOG7o25nIGtob+G6o25nIHRpbiBj4bqteSA5NSUgY2hvIHThu7cgbOG7hyBuZ8aw4budaSBjaMawYSB04burbmcga+G6v3QgaMO0bg0KcHJvcC50ZXN0KG5fbmV2ZXJfbWFycmllZCwgbl90b3RhbCwgY29uZi5sZXZlbCA9IDAuOTUpDQoNCmBgYA0KKlBow6JuIHTDrWNoIGvhur90IHF14bqjKg0KDQotIFBow6lwIGtp4buDbSDEkeG7i25oIMSRxrDhu6NjIHPhu60gZOG7pW5nIGzDoCBraeG7g20gxJHhu4tuaCB04bu3IGzhu4cgMSBt4bqrdSAoMS1zYW1wbGUgcHJvcG9ydGlvbnMgdGVzdCkgduG7m2kgY2jhu4luaCBsacOqbiB04bulYywgbmjhurFtIGPhuqNpIHRoaeG7h24gxJHhu5kgY2jDrW5oIHjDoWMga2hpIHPhu60gZOG7pW5nIHBow6JuIHBo4buRaSB44bqlcCB44buJLg0KDQotIEThu68gbGnhu4d1IMSR4bqndSB2w6BvOiDEkWFuZyBraeG7g20gxJHhu4tuaCB04bu3IGzhu4cgbmfGsOG7nWkgY8OzIHTDrG5oIHRy4bqhbmcgIk5ldmVyLW1hcnJpZWQiIChuX25ldmVyX21hcnJpZWQpIHRyb25nIHThu5VuZyBz4buRIHF1YW4gc8OhdCAobl90b3RhbCksIHbhu5tpIGdp4bqjIHRodXnhur90IGfhu5FjIEjigoA6IHAgPSAwLjUuDQoNCi0gR2nDoSB0cuG7iyB0aOG7kW5nIGvDqiBraeG7g20gxJHhu4tuaCBsw6AgWC1zcXVhcmVkID0gMzg0OC4zIHbhu5tpIGRmID0gMSwgY2hvIHRo4bqleSBt4bupYyDEkeG7mSBjaMOqbmggbOG7h2NoIGzhu5tuIGdp4buvYSB04bu3IGzhu4cgcXVhbiBzw6F0IHbDoCB04bu3IGzhu4cgZ2nhuqMgxJHhu4tuaC4NCg0KLSBHacOhIHRy4buLIHAtdmFsdWUgPCAyLjJlLTE2LCBj4buxYyBr4buzIG5o4buPLCDEkeG7k25nIG5naMSpYSB24bubaSB2aeG7h2Mga+G6v3QgcXXhuqMgbMOgIHLhuqV0IGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6og4oCTIHjDoWMgc3XhuqV0IHjhuqN5IHJhIHNhaSBs4bqnbSBraGkgYsOhYyBi4buPIEjigoAgZ+G6p24gbmjGsCBi4bqxbmcgMC4NCg0KLSBHaeG6oyB0aHV54bq/dCDEkeG7kWkgKEjigoEpOiBU4bu3IGzhu4cgdGjhu7FjIHPhu7Ega2jDoWMgMC41IChraeG7g20gxJHhu4tuaCBoYWkgcGjDrWE6IGtow6FjIGzhu5tuIGjGoW4gaG/hurdjIG5o4buPIGjGoW4gxJHhu4F1IMSRxrDhu6NjIHhlbSB4w6l0KS4NCg0KLSBLaG/huqNuZyB0aW4gY+G6rXkgOTUlIGNobyB04bu3IGzhu4cgbmfGsOG7nWkgY2jGsGEga+G6v3QgaMO0biBu4bqxbSB0cm9uZyBraG/huqNuZyBbMzIuMzAlOyAzMy4zMiVdLCB0aOG7gyBoaeG7h24gdOG7tyBs4buHIHRo4buxYyBz4buxIGtow6Eg4buVbiDEkeG7i25oIHF1YW5oIG3hu6ljIDMzJS4NCg0KLSBU4bu3IGzhu4cgbeG6q3UgxrDhu5tjIGzGsOG7o25nIGzDoCAzMi44MSUsIHThu6ljIGzDoCBn4bqnbiAxLzMgZMOibiBz4buRIHRyb25nIG3huqt1IGto4bqjbyBzw6F0IGNoxrBhIHThu6tuZyBr4bq/dCBow7RuLg0KDQoqKkLDoGkgdG/DoW4ga2nhu4NtIMSR4buLbmg6KioNCg0KR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmg6DQoNCkdp4bqjIHRodXnhur90IGtow7RuZyBI4oKAOiBwID0gMC41ICh04bu3IGzhu4cgbmfGsOG7nWkgY2jGsGEgdOG7q25nIGvhur90IGjDtG4gYuG6sW5nIDUwJSkNCg0KR2nhuqMgdGh1eeG6v3QgxJHhu5FpIEjigoE6IHAg4omgIDAuNSAodOG7tyBs4buHIG5nxrDhu51pIGNoxrBhIHThu6tuZyBr4bq/dCBow7RuIGtow6FjIDUwJSkNCg0KTeG7qWMgw70gbmdoxKlhOiDOsSA9IDAuMDUNCg0KS+G6v3QgbHXhuq1uOg0KDQpW4bubaSBwLXZhbHVlIDwgMi4yZS0xNiA8IDAuMDUsIHRhIGLDoWMgYuG7jyBnaeG6oyB0aHV54bq/dCBI4oKALg0KDQpDw7MgYuG6sW5nIGNo4bupbmcgdGjhu5FuZyBrw6ogbeG6oW5oIGNobyB0aOG6pXkgdOG7tyBs4buHIG5nxrDhu51pIGNoxrBhIHThu6tuZyBr4bq/dCBow7RuIGtow6FjIDUwJSwgduG7m2kgxJHhu5kgdGluIGPhuq15IDk1JS4NCg0KVOG7tyBs4buHIMaw4bubYyBsxrDhu6NuZyBsw6AgMzIuODElLCB24bubaSBraG/huqNuZyB0aW4gY+G6rXkgbuG6sW0gdHJvbmcgWzMyLjMwJTsgMzMuMzIlXS4gVOG7tyBs4buHIG7DoHkgdGjhuqVwIGjGoW4gxJHDoW5nIGvhu4Mgc28gduG7m2kgbeG7qWMgNTAlLCB2w6Agc+G7sSBjaMOqbmggbOG7h2NoICh+MTcgxJFp4buDbSBwaOG6p24gdHLEg20pIGzDoCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIHLDtSBy4buHdC4NCg0KDQojIyMgSOG6oW5nIG3hu6VjIOKAnE1hbGXigJ0gY+G7p2EgYmnhur9uIEdp4bubaSB0w61uaCAoR2VuZGVyKQ0KYGBge3J9DQojIFPhu5EgbmfGsOG7nWkgbMOgIG5hbSBnaeG7m2kNCm5fbWFsZSA8LSBzdW0oZCRHZW5kZXIgPT0gIk1hbGUiKQ0KDQojIFThu5VuZyBz4buRIHF1YW4gc8OhdA0Kbl90b3RhbCA8LSBucm93KGQpDQoNCiMgxq/hu5tjIGzGsOG7o25nIGtob+G6o25nIHRpbiBj4bqteSA5NSUgY2hvIHThu7cgbOG7hyBuYW0gZ2nhu5tpDQpwcm9wLnRlc3Qobl9tYWxlLCBuX3RvdGFsLCBjb25mLmxldmVsID0gMC45NSkNCg0KYGBgDQoqUGjDom4gdMOtY2gga+G6v3QgcXXhuqMqDQoNCi0gUGjDqXAga2nhu4NtIMSR4buLbmggxJHGsOG7o2Mgc+G7rSBk4bulbmcgbMOgIGtp4buDbSDEkeG7i25oIHThu7cgbOG7hyAxIG3huqt1IHbhu5tpIGNo4buJbmggbGnDqm4gdOG7pWMsIG5o4bqxbSDEkeG6o20gYuG6o28ga+G6v3QgcXXhuqMgY2jDrW5oIHjDoWMgaMahbiB24bubaSBk4buvIGxp4buHdSBy4budaSBy4bqhYy4NCg0KLSBE4buvIGxp4buHdSDEkeG6p3UgdsOgbzogxJFhbmcgeMOpdCB04bu3IGzhu4cgbmfGsOG7nWkgbMOgICJNYWxlIiB0cm9uZyB04buVbmcgc+G7kSBxdWFuIHPDoXQsIHbhu5tpIGdp4bqjIHRodXnhur90IGfhu5FjIEjigoA6IHAgPSAwLjUgKHThu6ljIGdp4bqjIMSR4buLbmggdOG7tyBs4buHIG5hbSBsw6AgNTAlKS4NCg0KLSBHacOhIHRy4buLIGtp4buDbSDEkeG7i25oIGzDoCBYLXNxdWFyZWQgPSAzNzI4LjMsIHbhu5tpIGRmID0gMSwgY2hvIHRo4bqleSBz4buxIGNow6puaCBs4buHY2ggbOG7m24gZ2nhu69hIHThu7cgbOG7hyBxdWFuIHPDoXQgdsOgIHThu7cgbOG7hyBnaeG6oyDEkeG7i25oLg0KDQotIEdpw6EgdHLhu4sgcC12YWx1ZSA8IDIuMmUtMTYsIHLhuqV0IG5o4buPLCBraOG6s25nIMSR4buLbmggcuG6sW5nIGPDsyBi4bqxbmcgY2jhu6luZyBt4bqhbmggxJHhu4MgYsOhYyBi4buPIEjigoAuDQoNCi0gR2nhuqMgdGh1eeG6v3QgxJHhu5FpIChI4oKBKSBsw6AgdOG7tyBs4buHIHRo4buxYyB04bq/IGtow6FjIDAuNSAoa2nhu4NtIMSR4buLbmggaGFpIHBow61hKS4NCg0KLSBLaG/huqNuZyB0aW4gY+G6rXkgOTUlIGNobyB04bu3IGzhu4cgbmFtIGdp4bubaSBu4bqxbSB0cm9uZyBraG/huqNuZyBbNjYuNDElOyA2Ny40MyVdLCBjaG8gdGjhuqV5IHThu7cgbOG7hyBuw6B5IGtow6Eg4buVbiDEkeG7i25oIHbDoCBjYW8gaMahbiBt4bupYyBnaeG6oyDEkeG7i25oLg0KDQotIFThu7cgbOG7hyBt4bqrdSDGsOG7m2MgbMaw4bujbmcgbMOgIDY2LjkyJSwgdOG7qWMgbMOgIGfhuqduIDIvMyBuZ8aw4budaSB0cm9uZyBt4bqrdSBraOG6o28gc8OhdCBsw6AgbmFtIGdp4bubaS4NCg0KKipCw6BpIHRvw6FuIGtp4buDbSDEkeG7i25oOioqDQoNCkdp4bqjIHRodXnhur90IGtp4buDbSDEkeG7i25oOg0KDQpHaeG6oyB0aHV54bq/dCBraMO0bmcgSOKCgDogcCA9IDAuNSAodOG7tyBs4buHIG5hbSBnaeG7m2kgYuG6sW5nIDUwJSkNCg0KR2nhuqMgdGh1eeG6v3QgxJHhu5FpIEjigoE6IHAg4omgIDAuNSAodOG7tyBs4buHIG5hbSBnaeG7m2kga2jDoWMgNTAlKQ0KDQpN4bupYyDDvSBuZ2jEqWE6IM6xID0gMC4wNQ0KDQpL4bq/dCBsdeG6rW46DQoNClbhu5tpIHAtdmFsdWUgPCAyLjJlLTE2IDwgMC4wNSwgdGEgYsOhYyBi4buPIGdp4bqjIHRodXnhur90IEjigoAuDQoNCkRvIMSRw7MsIGPDsyBi4bqxbmcgY2jhu6luZyB0aOG7kW5nIGvDqiByw7UgcsOgbmcgY2hvIHRo4bqleSB04bu3IGzhu4cgbmFtIGdp4bubaSBraMOhYyA1MCUsIHbhu5tpIMSR4buZIHRpbiBj4bqteSA5NSUuDQoNCkPhu6UgdGjhu4MsIHThu7cgbOG7hyBuYW0gZ2nhu5tpIMaw4bubYyBsxrDhu6NuZyBsw6AgNjYuOTIlLCBjYW8gaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSA1MCUsIHbhu5tpIGtob+G6o25nIHRpbiBj4bqteSBu4bqxbSB0cm9uZyBraG/huqNuZyB04burIDY2LjQxJSDEkeG6v24gNjcuNDMlLiBN4bupYyBjaMOqbmggbOG7h2NoIGfhuqduIDE3IMSRaeG7g20gcGjhuqduIHRyxINtIGzDoCDEkeG7pyBs4bubbiDEkeG7gyB04bqhbyByYSDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogbeG6oW5oLg0KDQoNCiMgUGjDom4gdMOtY2ggTeG7kWkgcXVhbiBo4buHIGdp4buvYSBIYWkgYmnhur9uIMSQ4buLbmggdMOtbmggKEJpdmFyaWF0ZSBBbmFseXNpcykNCg0KQ2jhu41uICoqYmEqKiBj4bq3cCBiaeG6v24gxJHhu4tuaCB0w61uaCA6DQoNCi0gQ+G6t3AgMTogR2VuZGVyIOKAkyBFYXJuaW5nQ2xhc3MNCuKGkiBQaMOibiB0w61jaCBt4buRaSBsacOqbiBo4buHIGdp4buvYSBnaeG7m2kgdMOtbmggdsOgIG3hu6ljIHRodSBuaOG6rXAuDQoNCkPDonUgaOG7j2kgxJHhurd0IHJhOiBHaeG7m2kgdMOtbmggY8OzIOG6o25oIGjGsOG7n25nIMSR4bq/biBraOG6oyBuxINuZyB0aHXhu5ljIG5ow7NtIHRodSBuaOG6rXAgPjUwSyBraMO0bmc/DQoNCi0gQ+G6t3AgMjogTmF0aW9uYWxpdHkg4oCTIEVhcm5pbmdDbGFzcw0K4oaSIFhlbSB4w6l0IHhlbSBxdeG7kWMgZ2lhIGfhu5FjIGPDsyDhuqNuaCBoxrDhu59uZyDEkeG6v24gdGh1IG5o4bqtcCBoYXkga2jDtG5nLg0KDQogQ8OidSBo4buPaSDEkeG6t3QgcmE6IE5nxrDhu51pIMSR4bq/biB04burIEhvYSBL4buzIGPDsyB04bu3IGzhu4cgdGh1IG5o4bqtcCA+NTBLIGNhbyBoxqFuIGPDoWMgcXXhu5FjIGdpYSBraMOhYyBraMO0bmc/DQoNCi0gQ+G6t3AgMzogRXRobmljaXR5IOKAkyBFYXJuaW5nQ2xhc3MNCuKGkiBUw6xtIGhp4buDdSB4ZW0gY2jhu6duZyB04buZYyBjw7MgbGnDqm4gcXVhbiDEkeG6v24gdGh1IG5o4bqtcCBraMO0bmcuDQoNCkPDonUgaOG7j2kgxJHhurd0IHJhOiBU4bu3IGzhu4cgdGh1IG5o4bqtcCA+NTBLIGPDsyBjaMOqbmggbOG7h2NoIHLDtSBy4buHdCBnaeG7r2EgY8OhYyBuaMOzbSBjaOG7p25nIHThu5ljIGtow7RuZz8NCg0KDQojIyBHZW5kZXIgLSBFYXJuaW5nQ2xhc3MNCg0KIyMjICBC4bqjbmcgdOG6p24gc+G7kSBjaMOpbw0KYGBge3J9DQojIELhuqNuZyB04bqnbiBz4buRIGNow6lvOiBnaeG7m2kgdMOtbmggdsOgIHRodSBuaOG6rXANCnRhYmxlX0dlbmRlcl9FYXJuaW5nQ2xhc3MgPC0gdGFibGUoZCRHZW5kZXIsIGQkRWFybmluZ0NsYXNzKQ0KdGFibGVfR2VuZGVyX0Vhcm5pbmdDbGFzcw0KDQojIFThu7cgbOG7hyB0aGVvIGjDoG5nICh04burbmcgZ2nhu5tpIHTDrW5oKQ0KcHJvcC50YWJsZSh0YWJsZV9HZW5kZXJfRWFybmluZ0NsYXNzLCBtYXJnaW4gPSAxKQ0KDQpgYGANCg0KLSBUcm9uZyBz4buRIG5hbSBnaeG7m2kgKE1hbGUpOiBjw7MgMTUsMTI4IG5nxrDhu51pIHRodSBuaOG6rXAgPD01MEsgdsOgIDYsNjYyIG5nxrDhu51pIHRodSBuaOG6rXAgPjUwSyDihpIgdOG7tyBs4buHID41MEsgbMOgIDMwLjYlLg0KDQotIFRyb25nIHPhu5EgbuG7ryBnaeG7m2kgKEZlbWFsZSk6IGPDsyA5LDU5MiBuZ8aw4budaSB0aHUgbmjhuq1wIDw9NTBLIHbDoCAxLDE3OSBuZ8aw4budaSB0aHUgbmjhuq1wID41MEsg4oaSIHThu7cgbOG7hyA+NTBLIGzDoCAxMC45JS4NCg0KS+G6v3QgbHXhuq1uOg0K4oaSIE5hbSBnaeG7m2kgKE1hbGUpIGPDsyB04bu3IGzhu4cgdGh1IG5o4bqtcCA+NTBLIGfhuqduIGfhuqVwIDMgbOG6p24gbuG7ryBnaeG7m2kgKEZlbWFsZSksIGNobyB0aOG6pXkgc+G7sSBjaMOqbmggbOG7h2NoIHRodSBuaOG6rXAgcuG6pXQgxJHDoW5nIGvhu4MgZ2nhu69hIGhhaSBnaeG7m2kuDQoNCiMjIyAgVHLhu7FjIHF1YW4gaMOzYQ0KYGBge3IgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTZ9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgVOG6oW8gYuG6o25nIGThu68gbGnhu4d1IHThu6sgYuG6o25nIHThuqduIHN14bqldCBjaMOpbw0KdGFibGVfR2VuZGVyX0Vhcm5pbmdDbGFzcyA8LSB0YWJsZShkJEdlbmRlciwgZCRFYXJuaW5nQ2xhc3MpDQpkZl9ncm91cCA8LSBhcy5kYXRhLmZyYW1lKGFzLnRhYmxlKHRhYmxlX0dlbmRlcl9FYXJuaW5nQ2xhc3MpKQ0KY29sbmFtZXMoZGZfZ3JvdXApIDwtIGMoIkdlbmRlciIsICJFYXJuaW5nQ2xhc3MiLCAiRnJlcSIpICAjIMSQ4buVaSB0w6puIGPhu5l0DQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQgbmjDs20NCmdncGxvdChkZl9ncm91cCwgYWVzKHggPSBFYXJuaW5nQ2xhc3MsIHkgPSBGcmVxLCBmaWxsID0gR2VuZGVyKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksIHdpZHRoID0gMC42KSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwNCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLA0KICAgICAgICAgICAgdmp1c3QgPSAtMC40LCBzaXplID0gNCwgY29sb3IgPSAid2hpdGUiLCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBsYWJzKHRpdGxlID0gIkJp4buDdSDEkeG7kyBj4buZdCBuaMOzbTogR2VuZGVyIHZzIEVhcm5pbmdDbGFzcyIsDQogICAgICAgeCA9ICJN4bupYyB0aHUgbmjhuq1wIiwNCiAgICAgICB5ID0gIlThuqduIHPhu5EiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoIkZlbWFsZSIgPSAiI0ZGOTk5OSIsICJNYWxlIiA9ICIjNjY5OUNDIiksDQogICAgbmFtZSA9ICJHaeG7m2kgdMOtbmgiLA0KICAgIGxhYmVscyA9IGMoIk7hu68iLCAiTmFtIikNCiAgKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTMpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0Ig0KICApDQoNCmBgYA0KDQotIGxpYnJhcnkoZ2dwbG90Mik6IE7huqFwIHRoxrAgdmnhu4duIGdncGxvdDIgxJHhu4Mgc+G7rSBk4bulbmcgY8OhYyBjaOG7qWMgbsSDbmcgduG6vSBiaeG7g3UgxJHhu5MuDQoNCi0gdGFibGVfR2VuZGVyX0Vhcm5pbmdDbGFzcyA8LSB0YWJsZShkJEdlbmRlciwgZCRFYXJuaW5nQ2xhc3MpOiBU4bqhbyBi4bqjbmcgdOG6p24gc3XhuqV0IGNow6lvIGdp4buvYSBoYWkgYmnhur9uIMSR4buLbmggdMOtbmggbMOgIGdp4bubaSB0w61uaCAoR2VuZGVyKSB2w6AgdGh1IG5o4bqtcCAoRWFybmluZ0NsYXNzKSwgY2hvIGJp4bq/dCBz4buRIGzGsOG7o25nIHThu6tuZyB04buVIGjhu6NwLg0KDQotIGRmX2dyb3VwIDwtIGFzLmRhdGEuZnJhbWUoYXMudGFibGUodGFibGVfR2VuZGVyX0Vhcm5pbmdDbGFzcykpOiBDaHV54buDbiBi4bqjbmcgdOG6p24gc3XhuqV0IHbhu6thIHThuqFvIHNhbmcgZOG6oW5nIGLhuqNuZyBk4buvIGxp4buHdSAoZGF0YS5mcmFtZSkgZ+G7k20gYmEgY+G7mXQuDQoNCi0gY29sbmFtZXMoZGZfZ3JvdXApIDwtIGMoIkdlbmRlciIsICJFYXJuaW5nQ2xhc3MiLCAiRnJlcSIpOiDEkOG6t3QgdMOqbiBjaG8gYmEgY+G7mXQgbMOgOiBnaeG7m2kgdMOtbmggKEdlbmRlciksIG3hu6ljIHRodSBuaOG6rXAgKEVhcm5pbmdDbGFzcykgdsOgIHThuqduIHPhu5EgKEZyZXEpLg0KDQotIGdncGxvdChkZl9ncm91cCwgYWVzKHggPSBFYXJuaW5nQ2xhc3MsIHkgPSBGcmVxLCBmaWxsID0gR2VuZGVyKSk6IEto4bufaSB04bqhbyBiaeG7g3UgxJHhu5MgY+G7mXQsIHRy4bulYyBob8OgbmggbMOgIHRodSBuaOG6rXAsIHRy4bulYyB0dW5nIGzDoCB04bqnbiBz4buRLCBjw6FjIGPhu5l0IMSRxrDhu6NjIHTDtCBtw6B1IHRoZW8gZ2nhu5tpIHTDrW5oLg0KDQotIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwgd2lkdGggPSAwLjYpOiBW4bq9IGJp4buDdSDEkeG7kyBj4buZdCBuaMOzbSwgxJHhurd0IGPDoWMgY+G7mXQgbmFtIHbDoCBu4buvIGPhuqFuaCBuaGF1IMSR4buDIGThu4Ugc28gc8OhbmguDQoNCi0gZ2VvbV90ZXh0KC4uLik6IFRow6ptIG5ow6NuIHPhu5EgbMaw4bujbmcgbMOqbiBt4buXaSBj4buZdCDEkeG7gyBoaeG7g24gdGjhu4sgZ2nDoSB0cuG7iyBGcmVxLCDEkeG6t3Qg4bufIHRyw6puIMSR4bqndSBj4buZdC4NCg0KLSBsYWJzKC4uLik6IFRow6ptIHRpw6p1IMSR4buBIGJp4buDdSDEkeG7kyB2w6AgbmjDo24gY2hvIGPDoWMgdHLhu6VjLg0KDQotIHNjYWxlX2ZpbGxfbWFudWFsKC4uLik6IFTDuXkgY2jhu4luaCBtw6B1IHPhuq9jIGPhu6dhIHThu6tuZyBnaeG7m2kgdMOtbmggdsOgIHRoaeG6v3QgbOG6rXAgY2jDuiB0aMOtY2ggKGxlZ2VuZCkuDQoNCi0gdGhlbWVfbWluaW1hbCguLi4pICsgdGhlbWUoLi4uKTogw4FwIGThu6VuZyBwaG9uZyBjw6FjaCB04buRaSBnaeG6o24gY2hvIGJp4buDdSDEkeG7kywgY8SDbiBnaeG7r2EgdGnDqnUgxJHhu4EgdsOgIMSR4bq3dCBjaMO6IGdp4bqjaSBiw6puIHBo4bqjaS4NCg0KYGBge3IgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTZ9DQojIFThuqFvIGLhuqNuZyBk4buvIGxp4buHdSB04burIGLhuqNuZyB04bqnbiBzdeG6pXQgY2jDqW8NCnRhYmxlX0dlbmRlcl9FYXJuaW5nQ2xhc3MgPC0gdGFibGUoZCRHZW5kZXIsIGQkRWFybmluZ0NsYXNzKQ0KZGZfc3RhY2sgPC0gYXMuZGF0YS5mcmFtZShhcy50YWJsZSh0YWJsZV9HZW5kZXJfRWFybmluZ0NsYXNzKSkNCmNvbG5hbWVzKGRmX3N0YWNrKSA8LSBjKCJHZW5kZXIiLCAiRWFybmluZ0NsYXNzIiwgIkZyZXEiKSAgIyDEkOG7lWkgdMOqbiBj4buZdA0KDQojIFbhur0gYmnhu4N1IMSR4buTIGPhu5l0IGNo4buTbmcNCmdncGxvdChkZl9zdGFjaywgYWVzKHggPSBFYXJuaW5nQ2xhc3MsIHkgPSBGcmVxLCBmaWxsID0gR2VuZGVyKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjYpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksDQogICAgICAgICAgICBjb2xvciA9ICJncmVlbiIsIHNpemUgPSA0LCBmb250ZmFjZSA9ICJib2xkIikgKw0KICBzY2FsZV9maWxsX21hbnVhbCgNCiAgICB2YWx1ZXMgPSBjKCJGZW1hbGUiID0gInJlZCIsICJNYWxlIiA9ICIjNjY5OUNDIiksDQogICAgbmFtZSA9ICJHaeG7m2kgdMOtbmgiLA0KICAgIGxhYmVscyA9IGMoIk7hu68iLCAiTmFtIikNCiAgKSArDQogIGxhYnModGl0bGUgPSAiQmnhu4N1IMSR4buTIGPhu5l0IGNo4buTbmc6IEdlbmRlciB2cyBFYXJuaW5nQ2xhc3MiLA0KICAgICAgIHggPSAiTeG7qWMgdGh1IG5o4bqtcCIsDQogICAgICAgeSA9ICJU4bqnbiBz4buRIikgKw0KICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEzKSArDQogIHRoZW1lKA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsIGZhY2UgPSAiYm9sZCIpLA0KICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCINCiAgKQ0KDQoNCmBgYA0KDQotIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNik6IFbhur0gYmnhu4N1IMSR4buTIGPhu5l0IGNo4buTbmcgKHN0YWNrZWQgYmFyIGNoYXJ0KSwgdHJvbmcgxJHDsyBt4buXaSBuaMOzbSB0aHUgbmjhuq1wIGhp4buDbiB0aOG7iyBt4buZdCBj4buZdCBjw7MgcGjhuqduIGNo4buTbmcgdGhlbyBnaeG7m2kgdMOtbmguDQoNCi0gZ2VvbV90ZXh0KHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLCAuLi4pOiBIaeG7g24gdGjhu4sgbmjDo24gc+G7kSBsxrDhu6NuZyAodOG6p24gc+G7kSkgYsOqbiB0cm9uZyB04burbmcgcGjhuqduIGNo4buTbmcgY+G7p2EgY+G7mXQsIHThu6ljIGzDoCDhu58gZ2nhu69hIG3hu5dpIGto4buRaSBtw6B1Lg0KDQojIyMgIE5o4bqtbiB4w6l0IG3DtCB04bqjDQoNCi0gQmnhu4N1IMSR4buTIGPhu5l0IG5ow7NtIGNobyB0aOG6pXkgbmFtIGdp4bubaSDDoXAgxJHhuqNvIHLDtSBy4buHdCB24buBIHPhu5EgbMaw4bujbmcg4bufIG5ow7NtIHRodSBuaOG6rXAgPjUwSyDigJMgY8OhYyBj4buZdCBtw6B1IHhhbmggKE1hbGUpIGNhbyBoxqFuIMSRw6FuZyBr4buDIHNvIHbhu5tpIG7hu68gKEZlbWFsZSkgdHJvbmcgbmjDs20gbsOgeS4NCg0KLSDhu54gbmjDs20gdGh1IG5o4bqtcCA8PTUwSywgbuG7ryBnaeG7m2kgduG6q24gY2hp4bq/bSBz4buRIGzGsOG7o25nIGzhu5tuLCBuaMawbmcgY+G7mXQgYmnhu4N1IGRp4buFbiBj4bunYSBo4buNIHRodSBuaOG7jyBt4bqhbmgga2hpIHNhbmcgbmjDs20gdGh1IG5o4bqtcCBjYW8uDQoNCi0gQmnhu4N1IMSR4buTIGPhu5l0IGNo4buTbmcgY+G7p25nIGPhu5EgcXVhbiBzw6F0IG7DoHk6IHThu7cgbOG7hyBuYW0gZ2nhu5tpIGNoaeG6v20gcGjhuqduIGzhu5tuIHRyb25nIGPhu5l0ID41MEssIGPDsm4gbuG7ryBnaeG7m2kgZ+G6p24gbmjGsCBjaOG7iSB04bqtcCB0cnVuZyDhu58gbmjDs20gdGh1IG5o4bqtcCB0aOG6pXAuDQoNCuKGkiBL4bq/dCBsdeG6rW4gdHLhu7FjIHF1YW46IEdp4bubaSB0w61uaCBsw6AgeeG6v3UgdOG7kSDhuqNuaCBoxrDhu59uZyDEkcOhbmcga+G7gyDEkeG6v24gcGjDom4gcGjhu5FpIHRodSBuaOG6rXAgdHJvbmcgZOG7ryBsaeG7h3UuIEJp4buDdSDEkeG7kyBjaG8gdGjhuqV5IHPhu7EgcGjDom4gdOG6p25nIGdp4bubaSB0w61uaCBy4bqldCByw7UgduG7gSB0aHUgbmjhuq1wLg0KDQojIyMgIEtp4buDbSDEkeG7i25oIHRo4buRbmcga8OqIChLaeG7g20gxJHhu4tuaCBDaGktYsOsbmggcGjGsMahbmcpDQoNCioqR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmg6KioNCg0KKipI4oKAIChHaeG6oyB0aHV54bq/dCBraMO0bmcpKio6IEdp4bubaSB0w61uaCB2w6AgbeG7qWMgdGh1IG5o4bqtcCDEkeG7mWMgbOG6rXAgbmhhdS4NCg0KKipI4oKBIChHaeG6oyB0aHV54bq/dCDEkeG7kWkpKio6R2nhu5tpIHTDrW5oIHbDoCBt4bupYyB0aHUgbmjhuq1wIGPDsyBsacOqbiBo4buHLi4NCg0KYGBge3J9DQojIFRo4buxYyBoaeG7h24ga2nhu4NtIMSR4buLbmggQ2hpLWLDrG5oIHBoxrDGoW5nDQpjaGlzcS50ZXN0KHRhYmxlX0dlbmRlcl9FYXJuaW5nQ2xhc3MpDQpgYGANCioqS+G6v3QgcXXhuqMga2nhu4NtIMSR4buLbmggQ2hpLWLDrG5oIHBoxrDGoW5nOioqDQoNCkNoaS1zcXVhcmVkID0gMTUxNy44MQ0KDQpC4bqtYyB04buxIGRvIChkZikgPSAxDQoNCkdpw6EgdHLhu4sgcC12YWx1ZSA9IDAuMDAwMA0KDQoqKkvhur90IGx14bqtbiB0aOG7kW5nIGvDqjoqKg0KVsOsIHAgPCAwLjA1LCB0YSBiw6FjIGLhu48gZ2nhuqMgdGh1eeG6v3QgSOKCgC4NCg0KxJBp4buBdSBuw6B5IGNobyB0aOG6pXkgY8OzIG3hu5FpIGxpw6puIGjhu4cgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBnaeG7r2EgZ2nhu5tpIHTDrW5oIHbDoCBt4bupYyB0aHUgbmjhuq1wLg0KDQoqKlRo4bqjbyBsdeG6rW4gdGjDqm0gduG7gSBi4bqjbiBjaOG6pXQgbeG7kWkgcXVhbiBo4buHOioqDQoNCktp4buDbSDEkeG7i25oIENoaS1iw6xuaCBwaMawxqFuZyBjaG8gdGjhuqV5IGPDsyBz4buxIHBo4bulIHRodeG7mWMgZ2nhu69hIGdp4bubaSB0w61uaCB2w6AgdGh1IG5o4bqtcC4NCg0KVOG7qyBnw7NjIMSR4buZIHRo4buRbmcga8OqLCDEkWnhu4F1IG7DoHkgY8OzIG5naMSpYSBsw6A6IHZp4buHYyBt4buZdCBuZ8aw4budaSBsw6AgbmFtIGhheSBu4buvIOG6o25oIGjGsOG7n25nIMSR4bq/biB4w6FjIHN14bqldCBo4buNIHRodeG7mWMgbmjDs20gdGh1IG5o4bqtcCBjYW8gaG/hurdjIHRo4bqlcCDigJMgaGFpIGJp4bq/biBraMO0bmcgxJHhu5ljIGzhuq1wIG5oYXUuDQoNClF1YW4gc8OhdCBiaeG7g3UgxJHhu5MgY2hvIHRo4bqleToNCg0KLSBOYW0gZ2nhu5tpIGPDsyBt4bq3dCDDoXAgxJHhuqNvIOG7nyBuaMOzbSB0aHUgbmjhuq1wID41MEssIHThu6ljIGzDoCBo4buNIGPDsyBuaGnhu4F1IGto4bqjIG7Eg25nIGjGoW4gxJHhu4MgxJHhuqF0IG3hu6ljIHRodSBuaOG6rXAgY2FvLg0KDQotIE5nxrDhu6NjIGzhuqFpLCBu4buvIGdp4bubaSBjaOG7pyB54bq/dSBwaMOibiBi4buRIOG7nyBuaMOzbSB0aHUgbmjhuq1wIDw9NTBLLCB04bupYyDDrXQga2jhuqMgbsSDbmcgdGh14buZYyB04bqnbmcgbOG7m3AgdGh1IG5o4bqtcCBjYW8uDQoNCkLhuqNuIGNo4bqldCBt4buRaSBsacOqbiBo4buHOiBLaMO0bmcgY2jhu4kgbMOgIGtow6FjIGJp4buHdCB24buBIGNvbiBz4buRIOKAkyBtw6AgbMOgIG3hu5l0IG3DtCBow6xuaCBwaMOibiBi4buRIGPDsyB4dSBoxrDhu5tuZyByw7UgcsOgbmcgdGhlbyBnaeG7m2kgdMOtbmguDQoNCkPDsyB0aOG7gyBwaOG6o24gw6FuaCBz4buxIHBow6JuIHThuqduZyB4w6MgaOG7mWkgaG/hurdjIHPhu7Ega2jDoWMgYmnhu4d0IHRyb25nIMSR4bq3YyDEkWnhu4NtIG5naOG7gSBuZ2hp4buHcCwga2luaCBuZ2hp4buHbSwgaG/hurdjIHRo4budaSBnaWFuIGzDoG0gdmnhu4djIGdp4buvYSBoYWkgZ2nhu5tpLg0KDQrihpIgS+G6v3QgbHXhuq1uIHPDonUgaMahbjogS2jDtG5nIGNo4buJIGPDsyBt4buRaSBsacOqbiBo4buHIHRo4buRbmcga8OqLCBtw6AgYmnhu4N1IMSR4buTIGPDsm4gdGjhu4MgaGnhu4duIHTDrW5oIMSR4buLbmggaMaw4bubbmcgY+G7p2EgbeG7kWkgbGnDqm4gaOG7hyBuw6B5IOKAkyBuYW0gZ2nhu5tpIGPDsyB4w6FjIHN14bqldCDEkeG6oXQgdGh1IG5o4bqtcCBjYW8gY2FvIGjGoW4gbeG7mXQgY8OhY2ggY8OzIGjhu4cgdGjhu5FuZyBzbyB24bubaSBu4buvLg0KDQojIyMgSGnhu4d1IHThu7cgbOG7hyANCmBgYHtyfQ0KIyBM4bqtcCBi4bqjbmcgdOG6p24gc+G7kSBjaMOpbyBnaeG7r2EgR2VuZGVyIHbDoCBFYXJuaW5nQ2xhc3MNCnRhYmxlX0dlbmRlcl9FYXJuaW5nQ2xhc3MgPC0gdGFibGUoZCRHZW5kZXIsIGQkRWFybmluZ0NsYXNzKQ0KDQojIFRow6ptIHThu5VuZyBow6BuZyB2w6AgdOG7lW5nIGPhu5l0DQp0YWJsZV9HZW5kZXJfRWFybmluZ0NsYXNzX21hcmdpbnMgPC0gYWRkbWFyZ2lucyh0YWJsZV9HZW5kZXJfRWFybmluZ0NsYXNzKQ0KDQojIEhp4buDbiB0aOG7iyBi4bqjbmcNCnRhYmxlX0dlbmRlcl9FYXJuaW5nQ2xhc3NfbWFyZ2lucw0KDQpgYGANClThu7cgbOG7hyB0aHUgbmjhuq1wIGNhbyB0aGVvIGdp4bubaSB0w61uaCDEkcaw4bujYyBrw70gaGnhu4d1IG5oxrAgc2F1Og0KDQotIFwoIHBfMSA9IFAoXHRleHR7RWFybmluZ0NsYXNzfSA9IFx0ZXh0eyI+NTBLIn0gXG1pZCBcdGV4dHtHZW5kZXJ9ID0gXHRleHR7IkZlbWFsZSJ9KSBcKTogVOG7tyBs4buHIG7hu68gZ2nhu5tpIGPDsyB0aHUgbmjhuq1wIGNhby4gIA0KLSBcKCBwXzIgPSBQKFx0ZXh0e0Vhcm5pbmdDbGFzc30gPSBcdGV4dHsiPjUwSyJ9IFxtaWQgXHRleHR7R2VuZGVyfSA9IFx0ZXh0eyJNYWxlIn0pIFwpOiBU4bu3IGzhu4cgbmFtIGdp4bubaSBjw7MgdGh1IG5o4bqtcCBjYW8uDQoNCioqR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmg6KioNCg0KLSBcKCBIXzA6IHBfMSAtIHBfMiA9IDAgXCk6IEtow7RuZyBjw7Mgc+G7sSBraMOhYyBiaeG7h3QgduG7gSB04bu3IGzhu4cgdGh1IG5o4bqtcCBjYW8gZ2nhu69hIG5hbSB2w6AgbuG7ry4gIA0KLSBcKCBIXzE6IHBfMSAtIHBfMiA8IDAgXCk6IFThu7cgbOG7hyB0aHUgbmjhuq1wIGNhbyDhu58gbuG7ryB0aOG6pXAgaMahbiBuYW0uDQoNCmBgYHtyfQ0KIyBU4bqhbyBi4bqjbmcgdOG6p24gc+G7kSBjaMOpbyBnaeG7r2EgR2VuZGVyIHbDoCBFYXJuaW5nQ2xhc3MNCnRhYmxlX0dlbmRlcl9FYXJuaW5nQ2xhc3MgPC0gdGFibGUoZCRHZW5kZXIsIGQkRWFybmluZ0NsYXNzKQ0KDQojIFPhu5EgbmfGsOG7nWkgY8OzIHRodSBuaOG6rXAgPjUwSyB0cm9uZyB04burbmcgZ2nhu5tpDQpjb3VudHNfRWFybmluZ0NsYXNzX2hpZ2ggPC0gYyh0YWJsZV9HZW5kZXJfRWFybmluZ0NsYXNzWyJGZW1hbGUiLCAiPjUwSyJdLCB0YWJsZV9HZW5kZXJfRWFybmluZ0NsYXNzWyJNYWxlIiwgIj41MEsiXSkNCg0KIyBU4buVbmcgc+G7kSBuZ8aw4budaSB0aGVvIHThu6tuZyBnaeG7m2kNCnRvdGFsc19FYXJuaW5nQ2xhc3MgPC0gYyhzdW0odGFibGVfR2VuZGVyX0Vhcm5pbmdDbGFzc1siRmVtYWxlIiwgXSksIHN1bSh0YWJsZV9HZW5kZXJfRWFybmluZ0NsYXNzWyJNYWxlIiwgXSkpDQoNCiMgS2nhu4NtIMSR4buLbmggdOG7iSBs4buHIG3hu5l0IHBow61hOiBwMSA8IHAyDQp0ZXN0X0Vhcm5pbmdDbGFzc19sZXNzIDwtIHByb3AudGVzdChjb3VudHNfRWFybmluZ0NsYXNzX2hpZ2gsIHRvdGFsc19FYXJuaW5nQ2xhc3MsIGFsdGVybmF0aXZlID0gImxlc3MiLCBjb3JyZWN0ID0gRkFMU0UpDQoNCiMgSGnhu4NuIHRo4buLIGvhur90IHF14bqjDQp0ZXN0X0Vhcm5pbmdDbGFzc19sZXNzDQpgYGANCk3hu6VjIHRpw6p1IGtp4buDbSDEkeG7i25oOiBTbyBzw6FuaCB04bu3IGzhu4cgbmfGsOG7nWkgY8OzIHRodSBuaOG6rXAgY2FvIChiaeG6v24gRWFybmluZ0NsYXNzIGPDsyBnacOhIHRy4buLICI+NTBLIikgZ2nhu69hIGhhaSBnaeG7m2kgdMOtbmggKEdlbmRlciBsw6AgIkZlbWFsZSIgdsOgICJNYWxlIikuDQoNCsSQ4buLbmggbmdoxKlhOg0KDQpwMSA9IFAoRWFybmluZ0NsYXNzID09ICI+NTBLIiB8IEdlbmRlciA9PSAiRmVtYWxlIik6IHThu7cgbOG7hyBu4buvIGdp4bubaSBjw7MgdGh1IG5o4bqtcCBjYW8uDQoNCnAyID0gUChFYXJuaW5nQ2xhc3MgPT0gIj41MEsiIHwgR2VuZGVyID09ICJNYWxlIik6IHThu7cgbOG7hyBuYW0gZ2nhu5tpIGPDsyB0aHUgbmjhuq1wIGNhby4NCg0KR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmg6DQoNCkgwOiBwMSAtIHAyID0gMDogS2jDtG5nIGPDsyBz4buxIGtow6FjIGJp4buHdCB24buBIHThu7cgbOG7hyB0aHUgbmjhuq1wIGNhbyBnaeG7r2EgbmFtIHbDoCBu4buvLg0KDQpIMTogcDEgLSBwMiA8IDA6IFThu7cgbOG7hyB0aHUgbmjhuq1wIGNhbyDhu58gbuG7ryB0aOG6pXAgaMahbiBuYW0uDQoNCkvhur90IHF14bqjIHThu6sgcHJvcC50ZXN0KCk6DQoNClThu7cgbOG7hyBu4buvOiBraG/huqNuZyAxMC45NSUuDQoNClThu7cgbOG7hyBuYW06IGtob+G6o25nIDMwLjU3JS4NCg0KWC1zcXVhcmVkID0gMTUxOC45LCBkZiA9IDEsIHAtdmFsdWUgPCAyLjJlLTE2Lg0KDQpLaG/huqNuZyB0aW4gY+G6rXkgOTUlIGNobyBwMSAtIHAyOiB04burIC0xLjAwMDAwMDAgxJHhur9uIC0wLjE4OTE0NTcuDQoNCkvhur90IGx14bqtbjogQ8OzIGLhurFuZyBjaOG7qW5nIHRo4buRbmcga8OqIG3huqFuaCDEkeG7gyBiw6FjIGLhu48gZ2nhuqMgdGh1eeG6v3QgSDAuIFThu7cgbOG7hyBu4buvIGPDsyB0aHUgbmjhuq1wIGNhbyB0aOG6pXAgaMahbiBuYW0gbeG7mXQgY8OhY2ggY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqi4NCg0KIyMjIFThu7cgc+G7kSBuZ3V5IGPGoQ0KDQoqKkxp4buHdSBnaeG7m2kgdMOtbmggKG5hbS9u4buvKSBjw7Mg4bqjbmggaMaw4bufbmcgxJHhur9uIG5ndXkgY8ahIGPDsyB0aHUgbmjhuq1wIGNhbyBraMO0bmcgKD41MEspPyoqIA0KDQrihpIgTeG7pWMgdGnDqnU6IFNvIHPDoW5oIG5ndXkgY8ahIGPDsyB0aHUgbmjhuq1wIGNhbyDhu58gbmFtIGdp4bubaSBzbyB24bubaSBu4buvIGdp4bubaS4NCg0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCJlcGl0b29scyIsIHJlcG9zID0gImh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZyIpDQpsaWJyYXJ5KGVwaXRvb2xzKQ0KYGBgDQoNCioqVMOtbmggUmVsYXRpdmUgUmlzayoqDQoNCmBgYHtyfQ0Kcmlza3JhdGlvKHRhYmxlX0dlbmRlcl9FYXJuaW5nQ2xhc3MpDQpgYGANCioqTmjhuq1uIHjDqXQga+G6v3QgcXXhuqMqKg0KDQoqKiRkYXRhKio6IMSRw6J5IGzDoCBi4bqjbmcgZOG7ryBsaeG7h3UgY2jDqW8gMngyDQoNCi0gVHJvbmcgc+G7kSAxMCw3NzEgbuG7rywgY8OzIDEsMTc5IG5nxrDhu51pICgxMC45NSUpIGPDsyB0aHUgbmjhuq1wIHRyw6puIDUwSy4NCg0KLSBUcm9uZyBz4buRIDIxLDc5MCBuYW0sIGPDsyA2LDY2MiBuZ8aw4budaSAoMzAuNTclKSBjw7MgdGh1IG5o4bqtcCB0csOqbiA1MEsuDQoNCioqJG1lYXN1cmUqKjogdOG7tyBz4buRIG5ndXkgY8ahKFJSKQ0KDQpU4bu3IHPhu5Egbmd1eSBjxqEgKFJSKSBsw6Agc28gc8OhbmggeMOhYyBzdeG6pXQgeOG6o3kgcmEgb3V0Y29tZSAo4bufIMSRw6J5IGzDoDogY8OzIHRodSBuaOG6rXAgPjUwSykgZ2nhu69hIGhhaSBuaMOzbToNCg0KLSBSUiA9IDEg4oaSIG5ndXkgY8ahIG5oxrAgbmhhdS4NCg0KLSBSUiA+IDEg4oaSIG5ow7NtIE1hbGUgY8OzIG5ndXkgY8ahIGNhbyBoxqFuLg0KDQotIFJSIDwgMSDihpIgbmjDs20gTWFsZSBjw7Mgbmd1eSBjxqEgdGjhuqVwIGjGoW4uDQoNCg0KKiokcC52YWx1ZSoqDQoNCmBgYHtyfQ0KIyBDw6BpIGfDs2kgbuG6v3UgY+G6p24NCmluc3RhbGwucGFja2FnZXMoImtuaXRyIikgICMgY2jhu4kgY+G6p24gMSBs4bqnbiBu4bq/dSBjaMawYSBjw6BpDQoNCiMgTuG6oXAgdGjGsCB2aeG7h24NCmxpYnJhcnkoa25pdHIpDQoNCiMgVOG6oW8gYuG6o25nIGThu68gbGnhu4d1DQpleHBsYW5hdGlvbiA8LSBkYXRhLmZyYW1lKA0KICBD4buZdCA9IGMoInR3by1zaWRlZCIsICJtaWRwLmV4YWN0IiwgImZpc2hlci5leGFjdCIsICJjaGkuc3F1YXJlIiksDQogIMOdX25naMSpYSA9IGMoDQogICAgIktp4buDbSDEkeG7i25oIGhhaSBwaMOtYSDigJMga2nhu4NtIHRyYSB4ZW0gUlIgY8OzIGtow6FjIDEuIMSQw6J5IGzDoCBsb+G6oWkga2nhu4NtIMSR4buLbmggcGjhu5UgYmnhur9uIG5o4bqldC4iLA0KICAgICJLaeG7g20gxJHhu4tuaCBjaMOtbmggeMOhYyDigJMgY2hvIHAtdmFsdWUgY2jDrW5oIHjDoWMgZOG7sWEgdHLDqm4gcGjDom4gcGjhu5FpIGNow61uaCB4w6FjLiIsDQogICAgIkZpc2hlcuKAmXMgZXhhY3QgdGVzdCDigJMgZMO5bmcgdHJvbmcgYuG6o25nIDJ4MiB24bubaSBj4buhIG3huqt1IG5o4buPLiIsDQogICAgIkNoaS1zcXVhcmVkIHRlc3Qg4oCTIGtp4buDbSDEkeG7i25oIHjhuqVwIHjhu4kgcGjDom4gcGjhu5FpIGNodeG6qW4sIGTDuW5nIGtoaSBt4bqrdSDEkeG7pyBs4bubbi4iDQogICkNCikNCg0KIyBJbiBi4bqjbmcNCmthYmxlKGV4cGxhbmF0aW9uLCBhbGlnbiA9ICJsIikNCmBgYA0KDQoqKkvhur90IHF14bqjKioNCg0KLSBU4bu3IHPhu5Egbmd1eSBjxqEgKFJSKSA9IDIuNzkg4oaSIE5hbSBnaeG7m2kgY8OzIG5ndXkgY8ahIGPDsyB0aHUgbmjhuq1wIHRyw6puIDUwSyBjYW8gaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBu4buvIGdp4bubaSwgY+G7pSB0aOG7gyBsw6AgZ+G6pXAgMi43OSBs4bqnbi4NCg0KLSBLaG/huqNuZyB0aW4gY+G6rXkgOTUlID0gWzIuNjQsIDIuOTZdIOKGkiBLaMO0bmcgYmFvIGfhu5NtIDEg4oaSIG5naMSpYSBsw6Agc+G7sSBraMOhYyBiaeG7h3QgbsOgeSBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqLg0KDQotIHAtdmFsdWUgPSAwLjAwMCDhu58gdOG6pXQgY+G6oyBjw6FjIHBoxrDGoW5nIHBow6FwIGtp4buDbSDEkeG7i25oIChtaWQtcCBleGFjdCwgRmlzaGVyLCBjaGktc3F1YXJlKSDihpIgcuG6pXQgbmjhu48gaMahbiAwLjA1IOKGkiBjaG8gdGjhuqV5IGPDsyBi4bqxbmcgY2jhu6luZyB0aOG7kW5nIGvDqiBt4bqhbmggbeG6vSB24buBIHPhu7Ega2jDoWMgYmnhu4d0IGdp4buvYSBuYW0gdsOgIG7hu68gduG7gSBt4bupYyB0aHUgbmjhuq1wLg0KDQoqKkvhur90IGx14bqtbioqDQoNCi0gROG7sWEgdHLDqm4ga+G6v3QgcXXhuqMgcGjDom4gdMOtY2gsIG5hbSBnaeG7m2kgY8OzIGto4bqjIG7Eg25nIMSR4bqhdCB0aHUgbmjhuq1wIGNhbyAoPjUwSykgY2FvIGjGoW4gcsO1IHLhu4d0IHNvIHbhu5tpIG7hu68gZ2nhu5tpIHRyb25nIGLhu5kgZOG7ryBsaeG7h3UgbsOgeS4gVOG7tyBz4buRIG5ndXkgY8ahIGzDoCAyLjc5IHbhu5tpIGtob+G6o25nIHRpbiBj4bqteSBo4bq5cCB2w6AgcC12YWx1ZSBi4bqxbmcgMCBjaG8gdGjhuqV5IHPhu7Ega2jDoWMgYmnhu4d0IGzDoCBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIG3huqFuaCBt4bq9LiDEkGnhu4F1IG7DoHkgaMOgbSDDvSBy4bqxbmcgZ2nhu5tpIHTDrW5oIGzDoCBt4buZdCB54bq/dSB04buRIGPDsyDhuqNuaCBoxrDhu59uZyByw7UgcsOgbmcgxJHhur9uIGto4bqjIG7Eg25nIMSR4bqhdCDEkcaw4bujYyBt4bupYyB0aHUgbmjhuq1wIGNhbywgw610IG5o4bqldCBsw6AgdHJvbmcgcGjhuqFtIHZpIG3huqt1IGto4bqjbyBzw6F0IG7DoHkuDQoNCiMjIyBU4bu3IHPhu5EgQ2jDqm5oIChPZGRzIFJhdGlvIC0gT1IpDQoNCmBgYHtyfQ0Kb3JfcmVzdWx0MiA8LSBvZGRzcmF0aW8odGFibGVfR2VuZGVyX0Vhcm5pbmdDbGFzcykNCnByaW50KG9yX3Jlc3VsdDIpDQoNCmBgYA0Kxq/hu5tjIGzGsOG7o25nIE9kZHMgUmF0aW8gKE9SKSBjaG8gbmjDs20gbmFtIGdp4bubaSBsw6AgMy41OCAoduG7m2kga2hv4bqjbmcgdGluIGPhuq15IDk1JSB04burIDMuMzUgxJHhur9uIDMuODMpLCBzbyB24bubaSBuaMOzbSBu4buvIGdp4bubaSDEkcaw4bujYyBz4butIGThu6VuZyBsw6BtIG5ow7NtIHRoYW0gY2hp4bq/dSAoT1IgPSAxKS4gxJBp4buBdSBuw6B5IGNobyB0aOG6pXk6DQoNCi0tPiBOYW0gZ2nhu5tpIGPDsyBraOG6oyBuxINuZyBjw7MgdGh1IG5o4bqtcCBjYW8gKD41MEspIGNhbyBoxqFuIGtob+G6o25nIDMuNiBs4bqnbiBzbyB24bubaSBu4buvIGdp4bubaS4NCg0KS2hv4bqjbmcgdGluIGPhuq15IDk1JSBraMO0bmcgYmFvIGfhu5NtIGdpw6EgdHLhu4sgMSwgxJFp4buBdSBuw6B5IGPhu6duZyBj4buRIHLhurFuZyBz4buxIGtow6FjIGJp4buHdCBsw6AgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqi4NCg0KS+G6v3QgcXXhuqMga2nhu4NtIMSR4buLbmggduG7m2kgY8OhYyBwaMawxqFuZyBwaMOhcCBwaOG7lSBiaeG6v24gxJHhu4F1IGNobyBwLXZhbHVlIGLhurFuZyAwOg0KDQotIE1pZC1wIGV4YWN0IHRlc3Q6IDANCg0KLSBGaXNoZXLigJlzIGV4YWN0IHRlc3Q6IDANCg0KLSBDaGktc3F1YXJlZCB0ZXN0OiAwDQoNCkPDoWMgcC12YWx1ZSBi4bqxbmcgMCBjaG8gdGjhuqV5IHPhu7Ega2jDoWMgYmnhu4d0IHF1YW4gc8OhdCDEkcaw4bujYyB24buBIHThu7cgbOG7hyB0aHUgbmjhuq1wIGNhbyBnaeG7r2EgbmFtIHbDoCBu4buvIGzDoCBy4bqldCByw7UgcsOgbmcgdsOgIGtow7RuZyB0aOG7gyBnaeG6o2kgdGjDrWNoIGRvIG5n4bqrdSBuaGnDqm4gdHJvbmcgbeG6q3UuDQoNClTDs20gbOG6oWk6IEvhur90IHF14bqjIHBow6JuIHTDrWNoIGNo4buJIHJhIHLhurFuZyBnaeG7m2kgdMOtbmggY8OzIOG6o25oIGjGsOG7n25nIMSRw6FuZyBr4buDIMSR4bq/biBt4bupYyB0aHUgbmjhuq1wLCB0cm9uZyDEkcOzIG5hbSBnaeG7m2kgY8OzIHh1IGjGsOG7m25nIMSR4bqhdCBt4bupYyB0aHUgbmjhuq1wIGNhbyBoxqFuIG7hu68gZ2nhu5tpIG3hu5l0IGPDoWNoIHLDtSBy4buHdCB2w6AgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqi4NCg0KDQojIyBQYXJ0bmVyaW5nU3RhdGUg4oCTIEVhcm5pbmdDbGFzcw0KDQojIyMgIELhuqNuZyB04bqnbiBz4buRIGNow6lvDQpgYGB7cn0NCiMgQuG6o25nIHThuqduIHPhu5EgY2jDqW8gdsOgIHThu7cgbOG7hyB0aGVvIGjDoG5nIGdp4buvYSB0w6xuaCB0cuG6oW5nIGjDtG4gbmjDom4gdsOgIHRodSBuaOG6rXANCnRhYmxlX21hcml0YWxfRWFybmluZ0NsYXNzIDwtIHRhYmxlKGQkUGFydG5lcmluZ1N0YXRlLCBkJEVhcm5pbmdDbGFzcykgICAgICAgICAgICAgICMgQuG6o25nIHThuqduIHPhu5EgY2jDqW8NCnRhYmxlX21hcml0YWxfRWFybmluZ0NsYXNzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBIaeG7g24gdGjhu4sgYuG6o25nDQoNCnByb3AudGFibGUodGFibGVfbWFyaXRhbF9FYXJuaW5nQ2xhc3MsIG1hcmdpbiA9IDEpICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBUw61uaCB04bu3IGzhu4cgdGhlbyB04burbmcgdMOsbmggdHLhuqFuZyBow7RuIG5ow6JuDQoNCg0KYGBgDQotIFRyb25nIG5ow7NtIE1hcnJpZWQtY2l2LXNwb3VzZTogY8OzIDgsMjg0IG5nxrDhu51pIHRodSBuaOG6rXAgPD01MEsgdsOgIDYsNjkyIG5nxrDhu51pIHRodSBuaOG6rXAgPjUwSyDihpIgdOG7tyBs4buHID41MEsgbMOgIDQ0LjclLg0KDQotIFRyb25nIG5ow7NtIE5ldmVyLW1hcnJpZWQ6IGPDsyAxMCwxOTIgbmfGsOG7nWkgdGh1IG5o4bqtcCA8PTUwSyB2w6AgNDkxIG5nxrDhu51pIHRodSBuaOG6rXAgPjUwSyDihpIgdOG7tyBs4buHID41MEsgbMOgIDQuNiUuDQoNCi0gVHJvbmcgbmjDs20gRGl2b3JjZWQ6IGPDsyAzLDk4MCBuZ8aw4budaSB0aHUgbmjhuq1wIDw9NTBLIHbDoCA0NjMgbmfGsOG7nWkgdGh1IG5o4bqtcCA+NTBLIOKGkiB04bu3IGzhu4cgPjUwSyBsw6AgMTAuNCUuDQoNCi0gVHJvbmcgbmjDs20gTWFycmllZC1zcG91c2UtYWJzZW50OiBjw7MgMzg0IG5nxrDhu51pIHRodSBuaOG6rXAgPD01MEsgdsOgIDM0IG5nxrDhu51pIHRodSBuaOG6rXAgPjUwSyDihpIgdOG7tyBs4buHID41MEsgbMOgIDguMSUuDQoNCi0gVHJvbmcgbmjDs20gV2lkb3dlZDogY8OzIDkwOCBuZ8aw4budaSB0aHUgbmjhuq1wIDw9NTBLIHbDoCA4NSBuZ8aw4budaSB0aHUgbmjhuq1wID41MEsg4oaSIHThu7cgbOG7hyA+NTBLIGzDoCA4LjYlLg0KDQotIFRyb25nIG5ow7NtIFNlcGFyYXRlZDogY8OzIDk1OSBuZ8aw4budaSB0aHUgbmjhuq1wIDw9NTBLIHbDoCA2NiBuZ8aw4budaSB0aHUgbmjhuq1wID41MEsg4oaSIHThu7cgbOG7hyA+NTBLIGzDoCA2LjQlLg0KDQotIFRyb25nIG5ow7NtIE1hcnJpZWQtQUYtc3BvdXNlOiBjw7MgMTMgbmfGsOG7nWkgdGh1IG5o4bqtcCA8PTUwSyB2w6AgMTAgbmfGsOG7nWkgdGh1IG5o4bqtcCA+NTBLIOKGkiB04bu3IGzhu4cgPjUwSyBsw6AgNDMuNSUgKG5oxrBuZyBt4bqrdSBuaOG7jykuDQoNCkvhur90IGx14bqtbjoNCuKGkiBOaMOzbSBNYXJyaWVkLWNpdi1zcG91c2UgY8OzIHThu7cgbOG7hyB0aHUgbmjhuq1wID41MEsgY2FvIG5o4bqldCB0cm9uZyBjw6FjIG5ow7NtIMSRw7RuZyBkw6JuIHPhu5EsIHRyb25nIGtoaSBuaMOzbSBOZXZlci1tYXJyaWVkIGPDsyB04bu3IGzhu4cgdGjhuqVwIG5o4bqldC4NCuKGkiDEkGnhu4F1IG7DoHkgcGjhuqNuIMOhbmggc+G7sSBjaMOqbmggbOG7h2NoIMSRw6FuZyBr4buDIHbhu4EgdGh1IG5o4bqtcCB0aGVvIHTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiwgxJHhurdjIGJp4buHdCBsw6AgbOG7o2kgdGjhur8gY+G7p2EgbmfGsOG7nWkgxJHDoyBr4bq/dCBow7RuIGjhu6NwIHBow6FwLg0KDQoNCiMjIyAgVHLhu7FjIHF1YW4gaMOzYQ0KYGBge3IgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTZ9DQojIFThuqFvIGLhuqNuZyBk4buvIGxp4buHdSB04burIGLhuqNuZyB04bqnbiBzdeG6pXQgY2jDqW8NCnRhYmxlX21hcml0YWxfRWFybmluZ0NsYXNzIDwtIHRhYmxlKGQkUGFydG5lcmluZ1N0YXRlLCBkJEVhcm5pbmdDbGFzcykNCmRmX2dyb3VwX21hcml0YWwgPC0gYXMuZGF0YS5mcmFtZShhcy50YWJsZSh0YWJsZV9tYXJpdGFsX0Vhcm5pbmdDbGFzcykpDQpjb2xuYW1lcyhkZl9ncm91cF9tYXJpdGFsKSA8LSBjKCJNYXJpdGFsU3RhdHVzIiwgIkVhcm5pbmdDbGFzcyIsICJGcmVxIikNCg0KIyBW4bq9IGJp4buDdSDEkeG7kyBj4buZdCBuaMOzbQ0KZ2dwbG90KGRmX2dyb3VwX21hcml0YWwsIGFlcyh4ID0gTWFyaXRhbFN0YXR1cywgeSA9IEZyZXEsIGZpbGwgPSBFYXJuaW5nQ2xhc3MpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwgd2lkdGggPSAwLjYpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuOCksDQogICAgICAgICAgICB2anVzdCA9IC0wLjQsIHNpemUgPSA0LCBjb2xvciA9ICJibGFjayIsIGZvbnRmYWNlID0gImJvbGQiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoIjw9NTBLIiA9ICJyZWQiLCAiPjUwSyIgPSAiIzIwQjJBQSIpLA0KICAgIG5hbWUgPSAiVGh1IG5o4bqtcCINCiAgKSArDQogIGxhYnModGl0bGUgPSAiQmnhu4N1IMSR4buTIGPhu5l0IG5ow7NtOiBNYXJpdGFsU3RhdHVzIHZzIEVhcm5pbmdDbGFzcyIsDQogICAgICAgeCA9ICJUw6xuaCB0cuG6oW5nIGjDtG4gbmjDom4iLA0KICAgICAgIHkgPSAiVOG6p24gc+G7kSIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiDQogICkNCg0KYGBgDQoNCmBgYHtyIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD02fQ0KIyBU4bqhbyBi4bqjbmcgZOG7ryBsaeG7h3UgdOG7qyBi4bqjbmcgdOG6p24gc3XhuqV0IGNow6lvDQp0YWJsZV9tYXJpdGFsX0Vhcm5pbmdDbGFzcyA8LSB0YWJsZShkJFBhcnRuZXJpbmdTdGF0ZSwgZCRFYXJuaW5nQ2xhc3MpDQpkZl9zdGFja19tYXJpdGFsIDwtIGFzLmRhdGEuZnJhbWUoYXMudGFibGUodGFibGVfbWFyaXRhbF9FYXJuaW5nQ2xhc3MpKQ0KY29sbmFtZXMoZGZfc3RhY2tfbWFyaXRhbCkgPC0gYygiTWFyaXRhbFN0YXR1cyIsICJFYXJuaW5nQ2xhc3MiLCAiRnJlcSIpDQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQgY2jhu5NuZyANCmdncGxvdChkZl9zdGFja19tYXJpdGFsLCBhZXMoeCA9IE1hcml0YWxTdGF0dXMsIHkgPSBGcmVxLCBmaWxsID0gRWFybmluZ0NsYXNzKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjYpICsNCiAgZ2VvbV90ZXh0KA0KICAgIGFlcyhsYWJlbCA9IEZyZXEpLA0KICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpLA0KICAgIHZqdXN0ID0gMC41LCBzaXplID0gNCwgY29sb3IgPSAicmVkIiwgZm9udGZhY2UgPSAiYm9sZCINCiAgKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoIjw9NTBLIiA9ICJ5ZWxsb3ciLCAiPjUwSyIgPSAiIzIwQjJBQSIpLA0KICAgIG5hbWUgPSAiVGh1IG5o4bqtcCINCiAgKSArDQogIGxhYnMoDQogICAgdGl0bGUgPSAiQmnhu4N1IMSR4buTIGPhu5l0IGNo4buTbmc6IE1hcml0YWxTdGF0dXMgdnMgRWFybmluZ0NsYXNzIiwNCiAgICB4ID0gIlTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiIsDQogICAgeSA9ICJU4bqnbiBz4buRIg0KICApICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiDQogICkNCg0KYGBgDQoNCiMjIyAgTmjhuq1uIHjDqXQgbcO0IHThuqMNCg0KLSBCaeG7g3UgxJHhu5MgY+G7mXQgbmjDs20gY2hvIHRo4bqleSBuaOG7r25nIG5nxrDhu51pIMSRw6Mga+G6v3QgaMO0biBo4bujcCBwaMOhcCAoTWFycmllZC1jaXYtc3BvdXNlKSBjw7Mgc+G7kSBsxrDhu6NuZyB2xrDhu6N0IHRy4buZaSDhu58gbmjDs20gdGh1IG5o4bqtcCA+NTBLIOKAkyB0aGFuaCBj4buZdCDhu58gbmjDs20gbsOgeSBjYW8gcsO1IHLhu4d0Lg0KDQotIE5nxrDhu6NjIGzhuqFpLCBuaMOzbSBOZXZlci1tYXJyaWVkIGfhuqduIG5oxrAgY2jhu4kgeHXhuqV0IGhp4buHbiDhu58gbeG7qWMgdGh1IG5o4bqtcCB0aOG6pXAuIEPDoWMgbmjDs20gIkRpdm9yY2VkIiBoYXkgIlNlcGFyYXRlZCIgY8WpbmcgY8OzIHThu7cgbOG7hyB0aHUgbmjhuq1wIGNhbyBy4bqldCB0aOG6pXAuDQoNCi0gQmnhu4N1IMSR4buTIGPhu5l0IGNo4buTbmcgY2hvIHRo4bqleSBj4buZdCBj4bunYSBuaMOzbSBNYXJyaWVkLWNpdi1zcG91c2UgY8OzIHBo4bqnbiBtw6B1IHRodSBuaOG6rXAgY2FvIGNoaeG6v20gZ+G6p24gbeG7mXQgbuG7rWEsIHRyb25nIGtoaSBjw6FjIG5ow7NtIGtow6FjIHBo4bqnbiBtw6B1IG7DoHkgcuG6pXQgbeG7j25nLg0KDQrihpIgS+G6v3QgbHXhuq1uIHRy4buxYyBxdWFuOiBUw6xuaCB0cuG6oW5nIGjDtG4gbmjDom4gY8OzIGxpw6puIHF1YW4gY2jhurd0IGNo4bq9IMSR4bq/biB0aHUgbmjhuq1wLiBCaeG7g3UgxJHhu5MgcGjhuqNuIMOhbmggcsO1IHLhurFuZyBuZ8aw4budaSDEkcOjIGvhur90IGjDtG4gY8OzIGzhu6NpIHRo4bq/IGzhu5tuIHbhu4Ega2luaCB04bq/IHNvIHbhu5tpIGPDoWMgbmjDs20gY8OybiBs4bqhaS4NCg0KIyMjICBLaeG7g20gxJHhu4tuaCB0aOG7kW5nIGvDqihLaeG7g20gxJHhu4tuaCBDaGktYsOsbmggcGjGsMahbmcpDQoNCioqR2nhuqMgdGh1eeG6v3Qga2nhu4NtIMSR4buLbmg6KioNCg0KKipI4oKAIChHaeG6oyB0aHV54bq/dCBraMO0bmcpKio6VMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIHbDoCBt4bupYyB0aHUgbmjhuq1wIMSR4buZYyBs4bqtcCB24bubaSBuaGEuDQoNCioqSOKCgSAoR2nhuqMgdGh1eeG6v3QgxJHhu5FpKSoqOlTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiB2w6AgbeG7qWMgdGh1IG5o4bqtcCBjw7MgbeG7kWkgbGnDqm4gaOG7hyB24bubaSBuaGF1Lg0KDQpgYGB7cn0NCmNoaXNxLnRlc3QodGFibGVfbWFyaXRhbF9FYXJuaW5nQ2xhc3MpDQpgYGANCioqS+G6v3QgcXXhuqMga2nhu4NtIMSR4buLbmg6KioNCg0KQ2hpLXNxdWFyZWQgPSA2NTE3Ljc0DQoNCkLhuq1jIHThu7EgZG8gKGRmKSA9IDYNCg0KR2nDoSB0cuG7iyBwLXZhbHVlID0gMC4wMDAwDQoNCioqS+G6v3QgbHXhuq1uIHRo4buRbmcga8OqOioqDQoNClbDrCBwIDwgMC4wNSwgdGEgYsOhYyBi4buPIGdp4bqjIHRodXnhur90IEjigoAuDQoNCkPDsyBt4buRaSBsacOqbiBo4buHIHRo4buRbmcga8OqIHLDtSBy4buHdCBnaeG7r2EgdMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIHbDoCBt4bupYyB0aHUgbmjhuq1wDQoNCioqVGjhuqNvIGx14bqtbiB0aMOqbSB24buBIGLhuqNuIGNo4bqldCBt4buRaSBxdWFuIGjhu4c6KioNCg0KQmnhu4N1IMSR4buTIGNobyB0aOG6pXkgbmjDs20gxJHDoyBr4bq/dCBow7RuIChNYXJyaWVkLWNpdi1zcG91c2UpIGPDsyBwaOG6p24gdGh1IG5o4bqtcCA+NTBLIGNoaeG6v20gxrB1IHRo4bq/IHR1eeG7h3QgxJHhu5FpLg0KDQpOZ8aw4bujYyBs4bqhaSwgbmjDs20gxJHhu5ljIHRow6JuIChOZXZlci1tYXJyaWVkKSBo4bqndSBuaMawIGNo4buJIHThuq1wIHRydW5nIOG7nyBt4bupYyB0aHUgbmjhuq1wIHRo4bqlcC4NCg0KQ8OhYyBuaMOzbSBseSBow7RuLCBseSB0aMOibiwgaG/hurdjIGfDs2EgY8WpbmcgY8OzIHThu7cgbOG7hyB0aHUgbmjhuq1wIGNhbyB0aOG6pXAgxJHDoW5nIGvhu4MuDQoNCuKGkiBHaeG6o2kgdGjDrWNoIG3hu5FpIGxpw6puIGjhu4c6IEtp4buDbSDEkeG7i25oIGNobyB0aOG6pXkgdMOsbmggdHLhuqFuZyBow7RuIG5ow6JuIGtow7RuZyBjaOG7iSBsacOqbiBxdWFuIMSR4bq/biB0aHUgbmjhuq1wLCBtw6AgY8OybiBjw7MgeHUgaMaw4bubbmcgcsO1IHLDoG5nIOKAkyBuZ8aw4budaSDEkcOjIGzhuq1wIGdpYSDEkcOsbmggY8OzIG5oaeG7gXUga2jhuqMgbsSDbmcgxJHhuqF0IHRodSBuaOG6rXAgY2FvIGjGoW4uIMSQaeG7gXUgbsOgeSBjw7MgdGjhu4MgcGjhuqNuIMOhbmggbeG7qWMgxJHhu5kg4buVbiDEkeG7i25oIHTDoGkgY2jDrW5oLCDEkeG7mSB0deG7lWksIGhv4bq3YyBjYW0ga+G6v3Qgbmdo4buBIG5naGnhu4dwIGNhbyBoxqFuIHRyb25nIG5ow7NtIMSRw6Mga+G6v3QgaMO0bi4NCg0KIyMjIEhp4buHdSB04bu3IGzhu4cNCg0KYGBge3J9DQojIEzhuq1wIGLhuqNuZyB04bqnbiBz4buRIGNow6lvIGdp4buvYSBQYXJ0bmVyaW5nU3RhdGUgdsOgIEVhcm5pbmdDbGFzcw0KdGFibGVfbWFyaXRhbF9FYXJuaW5nQ2xhc3MgPC0gdGFibGUoZCRQYXJ0bmVyaW5nU3RhdGUsIGQkRWFybmluZ0NsYXNzKQ0KDQojIFRow6ptIHThu5VuZyBow6BuZyB2w6AgdOG7lW5nIGPhu5l0DQp0YWJsZV9tYXJpdGFsX0Vhcm5pbmdDbGFzczEgPC0gYWRkbWFyZ2lucyh0YWJsZV9tYXJpdGFsX0Vhcm5pbmdDbGFzcykNCg0KIyBIaeG7g24gdGjhu4sgYuG6o25nDQp0YWJsZV9tYXJpdGFsX0Vhcm5pbmdDbGFzczENCmBgYA0KDQotIFwoIHBfMSA9IFAoXHRleHR7RWFybmluZ0NsYXNzfSA9IFx0ZXh0eyI+NTBLIn0gXG1pZCBcdGV4dHtQYXJ0bmVyaW5nU3RhdGV9ID0gXHRleHR7Ik5ldmVyLW1hcnJpZWQifSkgXCkgKFThu7cgbOG7hyBuZ8aw4budaSBjaMawYSB04burbmcga+G6v3QgaMO0biBjw7MgdGh1IG5o4bqtcCBjYW8pDQoNCi0gXCggcF8yID0gUChcdGV4dHtFYXJuaW5nQ2xhc3N9ID0gXHRleHR7Ij41MEsifSBcbWlkIFx0ZXh0e1BhcnRuZXJpbmdTdGF0ZX0gPSBcdGV4dHsiTWFycmllZC1jaXYtc3BvdXNlIn0pIFwpIChU4bu3IGzhu4cgbmfGsOG7nWkgxJFhbmcga+G6v3QgaMO0biBo4bujcCBwaMOhcCBjw7MgdGh1IG5o4bqtcCBjYW8pDQoNCkdp4bqjIHRodXnhur90IGtp4buDbSDEkeG7i25oOg0KDQotIFwoIEhfMDogcF8xIC0gcF8yID0gMCBcKSAoS2jDtG5nIGPDsyBz4buxIGtow6FjIGJp4buHdCB24buBIHThu7cgbOG7hyB0aHUgbmjhuq1wIGNhbyBnaeG7r2EgaGFpIG5ow7NtIHTDrG5oIHRy4bqhbmcgaMO0biBuaMOibikNCg0KLSBcKCBIXzE6IHBfMSAtIHBfMiA8IDAgXCkgKFThu7cgbOG7hyB0aHUgbmjhuq1wIGNhbyDhu58gbmjDs20gIk5ldmVyLW1hcnJpZWQiIHRo4bqlcCBoxqFuIG5ow7NtICJNYXJyaWVkLWNpdi1zcG91c2UiKQ0KDQpgYGB7cn0NCiMgTOG6rXAgYuG6o25nIHThuqduIHPhu5EgY2jDqW8gZ2nhu69hIFBhcnRuZXJpbmdTdGF0ZSB2w6AgRWFybmluZ0NsYXNzDQp0YWJsZV9tYXJpdGFsX0Vhcm5pbmdDbGFzcyA8LSB0YWJsZShkJFBhcnRuZXJpbmdTdGF0ZSwgZCRFYXJuaW5nQ2xhc3MpDQoNCiMgU+G7kSBuZ8aw4budaSBjw7MgdGh1IG5o4bqtcCA+NTBLIHRyb25nIHThu6tuZyBuaMOzbQ0KY291bnRzX0Vhcm5pbmdDbGFzc19oaWdoIDwtIGModGFibGVfbWFyaXRhbF9FYXJuaW5nQ2xhc3NbIk5ldmVyLW1hcnJpZWQiLCAiPjUwSyJdLA0KICAgICAgICAgICAgICAgICAgICAgICAgdGFibGVfbWFyaXRhbF9FYXJuaW5nQ2xhc3NbIk1hcnJpZWQtY2l2LXNwb3VzZSIsICI+NTBLIl0pDQoNCiMgVOG7lW5nIHPhu5EgbmfGsOG7nWkgdHJvbmcgdOG7q25nIG5ow7NtDQp0b3RhbHNfRWFybmluZ0NsYXNzIDwtIGMoc3VtKHRhYmxlX21hcml0YWxfRWFybmluZ0NsYXNzWyJOZXZlci1tYXJyaWVkIiwgXSksDQogICAgICAgICAgICAgICAgICAgc3VtKHRhYmxlX21hcml0YWxfRWFybmluZ0NsYXNzWyJNYXJyaWVkLWNpdi1zcG91c2UiLCBdKSkNCg0KIyBLaeG7g20gxJHhu4tuaCB04buJIGzhu4cgbeG7mXQgcGjDrWE6IHAxIDwgcDINCnRlc3RfbWFyaXRhbF9FYXJuaW5nQ2xhc3MgPC0gcHJvcC50ZXN0KGNvdW50c19FYXJuaW5nQ2xhc3NfaGlnaCwgdG90YWxzX0Vhcm5pbmdDbGFzcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsdGVybmF0aXZlID0gImxlc3MiLCBjb3JyZWN0ID0gRkFMU0UpDQoNCiMgSGnhu4NuIHRo4buLIGvhur90IHF14bqjDQp0ZXN0X21hcml0YWxfRWFybmluZ0NsYXNzDQpgYGANCkvhur90IHF14bqjIGtp4buDbSDEkeG7i25oIGNobyB0aOG6pXk6DQoNCi0gVOG7tyBs4buHIG5nxrDhu51pIGNoxrBhIHThu6tuZyBr4bq/dCBow7RuIGPDsyB0aHUgbmjhuq1wID41MEsgKHByb3AgMSkgbMOgIGtob+G6o25nIDQuNjAlLg0KDQotIFThu7cgbOG7hyBuZ8aw4budaSDEkWFuZyBr4bq/dCBow7RuIGjhu6NwIHBow6FwIGPDsyB0aHUgbmjhuq1wID41MEsgKHByb3AgMikgbMOgIGtob+G6o25nIDQ0LjY1JS4NCg0KVuG7m2kgcC12YWx1ZSA8IDIuMmUtMTYsIG5o4buPIGjGoW4gbeG7qWMgw70gbmdoxKlhIDAuMDUsIGNow7puZyB0YSBjw7MgxJHhu6cgYuG6sW5nIGNo4bupbmcgxJHhu4MgYsOhYyBi4buPIGdp4bqjIHRodXnhur90IEgwLiDEkGnhu4F1IG7DoHkgY8OzIG5naMSpYSBsw6A6DQoNCi0tPiBU4bu3IGzhu4cgbmfGsOG7nWkgY2jGsGEgdOG7q25nIGvhur90IGjDtG4gY8OzIHRodSBuaOG6rXAgY2FvIHRo4bqlcCBoxqFuIHThu7cgbOG7hyBuZ8aw4budaSDEkWFuZyBr4bq/dCBow7RuIGjhu6NwIHBow6FwIG3hu5l0IGPDoWNoIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouDQoNCiMjIyBSZWxhdGl2ZSBSaXNrDQoNCioqTGnhu4d1IHTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiAoxJHDoyBr4bq/dCBow7RuIHZzIGNoxrBhIGJhbyBnaeG7nSBr4bq/dCBow7RuKSBjw7Mg4bqjbmggaMaw4bufbmcgxJHhur9uIG5ndXkgY8ahIGPDsyB0aHUgbmjhuq1wIGNhbyBraMO0bmcgKD41MEspPyoqDQoNCuKGkiBN4bulYyB0acOqdTogU28gc8Ohbmggbmd1eSBjxqEgY8OzIHRodSBuaOG6rXAgY2FvIOG7nyBuZ8aw4budaSDEkcOjIGvhur90IGjDtG4gduG7m2kgbmfGsOG7nWkgY2jGsGEgdOG7q25nIGvhur90IGjDtG4uDQoNCmBgYHtyfQ0Kcmlza3JhdGlvKHRhYmxlX21hcml0YWxfRWFybmluZ0NsYXNzKQ0KYGBgDQoNCioqTmjhuq1uIHjDqXQga+G6v3QgcXXhuqMqKg0KDQoqKkvhur90IHF14bqjKioNCg0KLSBUcm9uZyBz4buRIDE0LDk3NiBuZ8aw4budaSDEkcOjIGvhur90IGjDtG4sIGPDsyA2LDY5MiBuZ8aw4budaSAoNDQuNjklKSBjw7MgdGh1IG5o4bqtcCA+NTBLLg0KDQotIFRyb25nIHPhu5EgMTAsNjgzIG5nxrDhu51pIGNoxrBhIGJhbyBnaeG7nSBr4bq/dCBow7RuLCBjaOG7iSBjw7MgNDkxIG5nxrDhu51pICg0LjYwJSkgY8OzIHRodSBuaOG6rXAgPjUwSy4NCg0KLSBU4bu3IHPhu5Egbmd1eSBjxqEgKFJSKSA9IDkuNzIg4oaSIE5nxrDhu51pIMSRw6Mga+G6v3QgaMO0biBjw7MgeMOhYyBzdeG6pXQgY8OzIHRodSBuaOG6rXAgPjUwSyBjYW8gaMahbiBn4bqnbiAxMCBs4bqnbiBzbyB24bubaSBuZ8aw4budaSBjaMawYSB04burbmcga+G6v3QgaMO0bi4NCg0KLSBLaG/huqNuZyB0aW4gY+G6rXkgOTUlID0gWzguOTAsIDEwLjYyXSDihpIgS2jDtG5nIGJhbyBn4buTbSAxIOKGkiBraMOhYyBiaeG7h3QgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqiBt4bqhbmggbeG6vS4NCg0KLSBwLXZhbHVlID0gMC4wMDAg4bufIHThuqV0IGPhuqMgY8OhYyBraeG7g20gxJHhu4tuaCDihpIgeMOhYyBuaOG6rW4ga+G6v3QgcXXhuqMgbMOgIGPhu7FjIGvhu7MgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqi4NCg0KKipL4bq/dCBsdeG6rW4qKg0KDQotIEThu7FhIHRyw6puIGvhur90IHF14bqjIHBow6JuIHTDrWNoLCBuZ8aw4budaSDEkcOjIGvhur90IGjDtG4gY8OzIG5ndXkgY8ahIGPDsyB0aHUgbmjhuq1wIGNhbyB2xrDhu6N0IHRy4buZaSBzbyB24bubaSBuZ8aw4budaSBjaMawYSB04burbmcga+G6v3QgaMO0bi4gVOG7tyBz4buRIG5ndXkgY8ahIGzDoCA5LjcyLCBraG/huqNuZyB0aW4gY+G6rXkgOTUlIGzDoCBbOC45MCwgMTAuNjJdLCB2w6AgcC12YWx1ZSBi4bqxbmcgMCBjaG8gdGjhuqV5IG3hu5FpIGxpw6puIGjhu4cgcuG6pXQgbeG6oW5oIG3hur0gdsOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouIFTDrG5oIHRy4bqhbmcgaMO0biBuaMOibiBsw6AgbeG7mXQgeeG6v3UgdOG7kSBxdWFuIHRy4buNbmcg4bqjbmggaMaw4bufbmcgxJHhur9uIGto4bqjIG7Eg25nIMSR4bqhdCBt4bupYyB0aHUgbmjhuq1wIGNhbyB0cm9uZyBi4buZIGThu68gbGnhu4d1IG7DoHkuDQoNCg0KIyMjIE9kZHMgUmF0aW8gLSBPUg0KDQpgYGB7cn0NCiMgxq/hu5tjIGzGsOG7o25nIG9kZHMgcmF0aW8gdOG7q25nIG5ow7NtIHNvIHbhu5tpIG5ow7NtICJEaXZvcmNlZCINCm9yX3Jlc3VsdCA8LSBvZGRzcmF0aW8odGFibGVfbWFyaXRhbF9FYXJuaW5nQ2xhc3MpDQoNCiMgSW4ga+G6v3QgcXXhuqMNCnByaW50KG9yX3Jlc3VsdCkNCmBgYA0Kxq/hu5tjIGzGsOG7o25nIE9kZHMgUmF0aW8gKE9SKSBjaG8gY8OhYyBuaMOzbSB0w6xuaCB0cuG6oW5nIGjDtG4gbmjDom4sIHRoYW0gY2hp4bq/dSBsw6Ag4oCcRGl2b3JjZWTigJ0NCi0gTmjDs20gTWFycmllZC1jaXYtc3BvdXNlIGPDsyBPUiA9IDYuOTQgKDk1JSBDSTogNi4yOCDigJMgNy42OSksIHAtdmFsdWUgPSAwLjAwMDAuDQotLT4gTmfGsOG7nWkgxJFhbmcga+G6v3QgaMO0biBo4bujcCBwaMOhcCBjw7Mga2jhuqMgbsSDbmcgY8OzIHRodSBuaOG6rXAgPjUwSyBjYW8gaMahbiBn4bqnbiA3IGzhuqduIHNvIHbhu5tpIG5nxrDhu51pIMSRw6MgbHkgaMO0bi4gU+G7sSBraMOhYyBiaeG7h3QgbsOgeSBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIHLhuqV0IGNhby4NCg0KLSBOaMOzbSBOZXZlci1tYXJyaWVkIGPDsyBPUiA9IDAuNDEgKDk1JSBDSTogMC4zNiDigJMgMC40NyksIHAtdmFsdWUgPSAwLjAwMDAuDQotLT4gTmjhu69uZyBuZ8aw4budaSBjaMawYSB04burbmcga+G6v3QgaMO0biBjw7Mga2jhuqMgbsSDbmcgxJHhuqF0IHRodSBuaOG6rXAgY2FvIGNo4buJIGLhurFuZyA0MSUgc28gduG7m2kgbmjDs20gbHkgaMO0bi4gxJDDonkgbMOgIHPhu7Ega2jDoWMgYmnhu4d0IGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogcsO1IHLhu4d0Lg0KDQotIE5ow7NtIFNlcGFyYXRlZCBjw7MgT1IgPSAwLjU5ICg5NSUgQ0k6IDAuNDUg4oCTIDAuNzcpLCBwLXZhbHVlID0gMC4wMDAxLg0KLS0+IE5o4buvbmcgbmfGsOG7nWkgbHkgdGjDom4gY8OzIHjDoWMgc3XhuqV0IHRodSBuaOG6rXAgY2FvIHRo4bqlcCBoxqFuIMSRw6FuZyBr4buDIHNvIHbhu5tpIG5nxrDhu51pIGx5IGjDtG4sIHbDoCBz4buxIGtow6FjIGJp4buHdCBuw6B5IGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ouDQoNCi0gTmjDs20gV2lkb3dlZCBjw7MgT1IgPSAwLjgxICg5NSUgQ0k6IDAuNjMg4oCTIDEuMDIpLCBwLXZhbHVlID0gMC4wNzUwLg0KLS0+IE3hurdjIGTDuSBjw7MgeHUgaMaw4bubbmcgdGh1IG5o4bqtcCB0aOG6pXAgaMahbiBuaMOzbSBseSBow7RuLCBuaMawbmcgdsOsIGtob+G6o25nIHRpbiBj4bqteSBiYW8gZ+G7k20gMSB2w6AgcC12YWx1ZSA+IDAuMDUgbsOqbiBjaMawYSDEkeG7pyBi4bqxbmcgY2jhu6luZyB0aOG7kW5nIGvDqiDEkeG7gyBr4bq/dCBsdeG6rW4uDQoNCi0gTmjDs20gTWFycmllZC1BRi1zcG91c2UgY8OzIE9SID0gNi42MyAoOTUlIENJOiAyLjc5IOKAkyAxNS4yOSksIHAtdmFsdWUg4omIIDAuMDAwMDYuDQotLT4gTeG6t2MgZMO5IG5ow7NtIG7DoHkgcuG6pXQgbmjhu48gKG4gPSAyMyksIGvhur90IHF14bqjIGNobyB0aOG6pXkga2jhuqMgbsSDbmcgY8OzIHRodSBuaOG6rXAgY2FvIGPFqW5nIGNhbyBoxqFuIG5oaeG7gXUgc28gduG7m2kgbmfGsOG7nWkgbHkgaMO0biB2w6AgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqi4NCg0KLSBOaMOzbSBNYXJyaWVkLXNwb3VzZS1hYnNlbnQgY8OzIE9SID0gMC43NiAoOTUlIENJOiAwLjUyIOKAkyAxLjA4KSwgcC12YWx1ZSDiiYggMC4xMzUuDQotLT4gS2jDtG5nIGPDsyDEkeG7pyBi4bqxbmcgY2jhu6luZyB0aOG7kW5nIGvDqiDEkeG7gyBr4bq/dCBsdeG6rW4gY8OzIHPhu7Ega2jDoWMgYmnhu4d0IHbhu4EgdGh1IG5o4bqtcCBzbyB24bubaSBuaMOzbSBseSBow7RuLg0KDQoqKlTDs20gbOG6oWk6KioNCg0KS+G6v3QgcXXhuqMgcGjDom4gdMOtY2ggY2hvIHRo4bqleSB0w6xuaCB0cuG6oW5nIGjDtG4gbmjDom4gY8OzIG3hu5FpIGxpw6puIGjhu4cgxJHDoW5nIGvhu4MgduG7m2kgbeG7qWMgdGh1IG5o4bqtcC4gTmjDs20gxJFhbmcgc+G7kW5nIHRyb25nIGjDtG4gbmjDom4gaOG7o3AgcGjDoXAgKE1hcnJpZWQtY2l2LXNwb3VzZSkgY8OzIHjDoWMgc3XhuqV0IMSR4bqhdCB0aHUgbmjhuq1wIGNhbyB2xrDhu6N0IHRy4buZaSBzbyB24bubaSBjw6FjIG5ow7NtIGtow6FjLCDEkeG6t2MgYmnhu4d0IGzDoCBuZ8aw4budaSBseSBow7RuLCBjaMawYSBr4bq/dCBow7RuIGhheSBseSB0aMOibi4gTmjhu69uZyBraMOhYyBiaeG7h3QgbsOgeSBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqIHLDtSByw6BuZywgbmdv4bqhaSB0cuG7qyBt4buZdCBz4buRIG5ow7NtIGPDsyBxdXkgbcO0IG3huqt1IG5o4buPIGhv4bq3YyBraG/huqNuZyB0aW4gY+G6rXkgY2jhu6lhIDEuDQoNCiMjIEV0aG5pY2l0eSAtIEVhcm5pbmdDbGFzcw0KDQojIyMgIELhuqNuZyB04bqnbiBz4buRIGNow6lvDQpgYGB7ciBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9Nn0NCiMgQuG6o25nIHThuqduIHPhu5EgY2jDqW86IGNo4bunbmcgdOG7mWMgdsOgIHRodSBuaOG6rXANCnRhYmxlX0V0aG5pY2l0eV9FYXJuaW5nQ2xhc3MgPC0gdGFibGUoZCRFdGhuaWNpdHksIGQkRWFybmluZ0NsYXNzKQ0KdGFibGVfRXRobmljaXR5X0Vhcm5pbmdDbGFzcw0KDQojIFThu7cgbOG7hyB0aGVvIGjDoG5nICh04burbmcgY2jhu6duZyB04buZYykNCnByb3AudGFibGUodGFibGVfRXRobmljaXR5X0Vhcm5pbmdDbGFzcywgbWFyZ2luID0gMSkNCg0KYGBgDQotIFdoaXRlOiBjw7MgMjAsNjk5IG5nxrDhu51pIHRodSBuaOG6rXAgPD01MEsgdsOgIDcsMTE3IG5nxrDhu51pIHRodSBuaOG6rXAgPjUwSyDihpIgdOG7tyBs4buHID41MEsgbMOgIDI1LjYlLg0KDQotIEFzaWFuLVBhYy1Jc2xhbmRlcjogY8OzIDc2MyBuZ8aw4budaSB0aHUgbmjhuq1wIDw9NTBLLCAyNzYgbmfGsOG7nWkgdGh1IG5o4bqtcCA+NTBLIOKGkiB04bu3IGzhu4cgPjUwSyBsw6AgMjYuNiUuDQoNCi0gQmxhY2s6IGPDsyAyLDczNyBuZ8aw4budaSB0aHUgbmjhuq1wIDw9NTBLLCAzODcgbmfGsOG7nWkgdGh1IG5o4bqtcCA+NTBLIOKGkiB04bu3IGzhu4cgPjUwSyBsw6AgMTIuNCUuDQoNCi0gQW1lci1JbmRpYW4tRXNraW1vOiBjw7MgMjc1IG5nxrDhu51pIHRodSBuaOG6rXAgPD01MEssIDM2IG5nxrDhu51pIHRodSBuaOG6rXAgPjUwSyDihpIgdOG7tyBs4buHID41MEsgbMOgIDExLjYlLg0KDQotIE90aGVyOiBjw7MgMjQ2IG5nxrDhu51pIHRodSBuaOG6rXAgPD01MEssIDI1IG5nxrDhu51pIHRodSBuaOG6rXAgPjUwSyDihpIgdOG7tyBs4buHID41MEsgbMOgIDkuMiUuDQoNCkvhur90IGx14bqtbjoNCuKGkiBOaMOzbSBBc2lhbi1QYWMtSXNsYW5kZXIgdsOgIFdoaXRlIGPDsyB04bu3IGzhu4cgdGh1IG5o4bqtcCA+NTBLIGNhbyBuaOG6pXQsIHRyb25nIGtoaSBjw6FjIG5ow7NtIGPDsm4gbOG6oWkgbmjGsCBCbGFjaywgQW1lci1JbmRpYW4tRXNraW1vLCB2w6AgxJHhurdjIGJp4buHdCBsw6AgT3RoZXIgY8OzIHThu7cgbOG7hyBy4bqldCB0aOG6pXAuIMSQaeG7gXUgbsOgeSBjaG8gdGjhuqV5IGPDsyBz4buxIGtow6FjIGJp4buHdCByw7UgcuG7h3QgduG7gSB0aHUgbmjhuq1wIGdp4buvYSBjw6FjIG5ow7NtIGNo4bunbmcgdOG7mWMuDQoNCiMjIyAgVHLhu7FjIHF1YW4gaMOzYQ0KYGBge3IgZmlnLndpZHRoPTEyLCBmaWcuaGVpZ2h0PTZ9DQojIFThuqFvIGLhuqNuZyBk4buvIGxp4buHdSB04burIGLhuqNuZyB04bqnbiBzdeG6pXQgY2jDqW8NCnRhYmxlX0V0aG5pY2l0eV9FYXJuaW5nQ2xhc3MgPC0gdGFibGUoZCRFdGhuaWNpdHksIGQkRWFybmluZ0NsYXNzKQ0KZGZfZ3JvdXBfRXRobmljaXR5IDwtIGFzLmRhdGEuZnJhbWUoYXMudGFibGUodGFibGVfRXRobmljaXR5X0Vhcm5pbmdDbGFzcykpDQpjb2xuYW1lcyhkZl9ncm91cF9FdGhuaWNpdHkpIDwtIGMoIkV0aG5pY2l0eSIsICJFYXJuaW5nQ2xhc3MiLCAiRnJlcSIpDQoNCiMgVuG6vSBiaeG7g3UgxJHhu5MgY+G7mXQgbmjDs20NCmdncGxvdChkZl9ncm91cF9FdGhuaWNpdHksIGFlcyh4ID0gRXRobmljaXR5LCB5ID0gRnJlcSwgZmlsbCA9IEVhcm5pbmdDbGFzcykpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjgpLCB3aWR0aCA9IDAuNikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksDQogICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwNCiAgICAgICAgICAgIHZqdXN0ID0gLTAuNCwgc2l6ZSA9IDQsIGNvbG9yID0gInJlZCIsIGZvbnRmYWNlID0gImJvbGQiKSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKA0KICAgIHZhbHVlcyA9IGMoIjw9NTBLIiA9ICIjRkZENzAwIiwgIj41MEsiID0gInB1cnBsZSIpLA0KICAgIG5hbWUgPSAiVGh1IG5o4bqtcCINCiAgKSArDQogIGxhYnModGl0bGUgPSAiQmnhu4N1IMSR4buTIGPhu5l0IG5ow7NtOiBFdGhuaWNpdHkgdnMgRWFybmluZ0NsYXNzIiwNCiAgICAgICB4ID0gIkNo4bunbmcgdOG7mWMiLA0KICAgICAgIHkgPSAiVOG6p24gc+G7kSIpICsNCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMykgKw0KICB0aGVtZSgNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiDQogICkNCg0KYGBgDQoNCmBgYHtyIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD02fQ0KIyBU4bqhbyBi4bqjbmcgZOG7ryBsaeG7h3UgdOG7qyBi4bqjbmcgdOG6p24gc3XhuqV0IGNow6lvDQp0YWJsZV9FdGhuaWNpdHlfRWFybmluZ0NsYXNzIDwtIHRhYmxlKGQkRXRobmljaXR5LCBkJEVhcm5pbmdDbGFzcykNCmRmX3N0YWNrX0V0aG5pY2l0eSA8LSBhcy5kYXRhLmZyYW1lKGFzLnRhYmxlKHRhYmxlX0V0aG5pY2l0eV9FYXJuaW5nQ2xhc3MpKQ0KY29sbmFtZXMoZGZfc3RhY2tfRXRobmljaXR5KSA8LSBjKCJFdGhuaWNpdHkiLCAiRWFybmluZ0NsYXNzIiwgIkZyZXEiKQ0KDQojIFbhur0gYmnhu4N1IMSR4buTIGPhu5l0IGNo4buTbmcNCmdncGxvdChkZl9zdGFja19FdGhuaWNpdHksIGFlcyh4ID0gRXRobmljaXR5LCB5ID0gRnJlcSwgZmlsbCA9IEVhcm5pbmdDbGFzcykpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMC42KSArDQogIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwNCiAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC44KSwNCiAgICAgICAgICB2anVzdCA9IDEuNSwgc2l6ZSA9IDQsIGNvbG9yID0gImdyZWVuIiwgZm9udGZhY2UgPSAiYm9sZCINCiApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwoDQogICAgdmFsdWVzID0gYygiPD01MEsiID0gInJlZCIsICI+NTBLIiA9ICIjNDE2OUUxIiksDQogICAgbmFtZSA9ICJUaHUgbmjhuq1wIg0KICApICsNCiAgbGFicyh0aXRsZSA9ICJCaeG7g3UgxJHhu5MgY+G7mXQgY2jhu5NuZzogRXRobmljaXR5IHZzIEVhcm5pbmdDbGFzcyIsDQogICAgICAgeCA9ICJDaOG7p25nIHThu5ljIiwNCiAgICAgICB5ID0gIlThuqduIHPhu5EiKSArDQogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTMpICsNCiAgdGhlbWUoDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksDQogICAgbGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0Ig0KICApDQoNCmBgYA0KDQojIyMgIE5o4bqtbiB4w6l0IG3DtCB04bqjDQoNCi0gTmjDs20gQXNpYW4tUGFjLUlzbGFuZGVyIHR1eSBjw7MgcXV5IG3DtCBuaOG7jyBoxqFuLCBuaMawbmcgY+G7mXQgdGh1IG5o4bqtcCA+NTBLIHbhuqtuIGtow6EgbuG7lWkgYuG6rXQsIGNobyB0aOG6pXkgdOG7tyBs4buHIHRodSBuaOG6rXAgY2FvIGtow7RuZyBo4buBIGvDqW0gY+G6oW5oLg0KDQotIEJp4buDdSDEkeG7kyBj4buZdCBjaOG7k25nIHRo4buDIGhp4buHbiBz4buxIHBow6JuIGjDs2EgcsO1OiBuaMOzbSBXaGl0ZSBjw7Mgc+G7sSBwaMOibiBi4buRIHRodSBuaOG6rXAgxJHhu4F1IGjGoW4sIHRyb25nIGtoaSBuaMOzbSBCbGFjayBoYXkgQW1lci1JbmRpYW4tRXNraW1vIGfhuqduIG5oxrAgYuG7iyBk4buTbiBo4bq/dCB2w6BvIHBo4bqnbiB0aHUgbmjhuq1wIHRo4bqlcC4NCg0KIyMjICBLaeG7g20gxJHhu4tuaCB0aOG7kW5nIGvDqg0KDQoqKkdp4bqjIHRodXnhur90IGtp4buDbSDEkeG7i25oOioqDQoNCioqSOKCgCAoR2nhuqMgdGh1eeG6v3Qga2jDtG5nKSoqOiBDaOG7p25nIHThu5ljIHbDoCBt4bupYyB0aHUgbmjhuq1wIMSR4buZYyBs4bqtcCBuaGF1Lg0KDQoqKkjigoEgKEdp4bqjIHRodXnhur90IMSR4buRaSkqKjpDaOG7p25nIHThu5ljIHbDoCBt4bupYyB0aHUgbmjhuq1uIGPDsyBsacOqbiBo4buHIHbhu5tpIG5oYXUuDQpgYGB7cn0NCiMgVGjhu7FjIGhp4buHbiBraeG7g20gxJHhu4tuaCBDaGktYsOsbmggcGjGsMahbmcNCmNoaXNxLnRlc3QodGFibGVfRXRobmljaXR5X0Vhcm5pbmdDbGFzcykNCmBgYA0KKipL4bq/dCBxdeG6oyBraeG7g20gxJHhu4tuaDoqKg0KDQpDaGktc3F1YXJlZCA9IDMzMC45Mg0KDQpC4bqtYyB04buxIGRvIChkZikgPSA0DQoNCnAtdmFsdWUgPCAyLjJlLTE2DQoNCioqS+G6v3QgbHXhuq1uIHRo4buRbmcga8OqOioqDQoNClbDrCBwLXZhbHVlIHLhuqV0IG5o4buPICg8IDAuMDUpLCB0YSBiw6FjIGLhu48gSOKCgC4NCg0KQ8OzIGLhurFuZyBjaOG7qW5nIHRo4buRbmcga8OqIHLhuqV0IG3huqFuaCBjaG8gdGjhuqV5IG3hu6ljIHRodSBuaOG6rXAgdsOgIGNo4bunbmcgdOG7mWMgY8OzIG3hu5FpIGxpw6puIGjhu4cgxJHDoW5nIGvhu4MuDQoNCioqVGjhuqNvIGx14bqtbiB0aMOqbSB24buBIGLhuqNuIGNo4bqldCBt4buRaSBxdWFuIGjhu4c6KioNCg0KS+G6v3QgcXXhuqMga2nhu4NtIMSR4buLbmggY2hvIHRo4bqleSBjaOG7p25nIHThu5ljIHbDoCB0aHUgbmjhuq1wIGPDsyBt4buRaSBsacOqbiBo4buHIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogKHAtdmFsdWUgPCAyLjJlLTE2KS4gRMO5IHPhu7EgY2jDqm5oIGzhu4djaCBnaeG7r2EgY8OhYyBuaMOzbSBraMO0bmcgcXXDoSBs4bubbiwgbmjGsG5nIHbhu5tpIGPhu6EgbeG6q3UgxJHhu6cgbOG7m24sIGPDoWMga2jDoWMgYmnhu4d0IG5o4buPIHbhuqtuIG1hbmcgw70gbmdoxKlhIHRo4buRbmcga8OqLg0KDQpCaeG7g3UgxJHhu5MgY2hvIHRo4bqleSBuaMOzbSBXaGl0ZSBjw7Mgc+G7kSBsxrDhu6NuZyB0aHUgbmjhuq1wID41MEsgY2FvIG5o4bqldCwgdHJvbmcga2hpIEFzaWFuLVBhYy1Jc2xhbmRlciBs4bqhaSBjw7MgdOG7tyBs4buHIHRodSBuaOG6rXAgY2FvIG7hu5VpIGLhuq10IGTDuSBxdXkgbcO0IG5o4buPLiBOZ8aw4bujYyBs4bqhaSwgQmxhY2sgdsOgIEFtZXItSW5kaWFuLUVza2ltbyBjw7MgdOG7tyBs4buHIHRodSBuaOG6rXAgY2FvIHRo4bqlcCBoxqFuIMSRw6FuZyBr4buDLg0KDQpOaOG7r25nIGNow6puaCBs4buHY2ggbsOgeSBjw7MgdGjhu4MgxJHhur9uIHThu6sgc+G7sSBraMOhYyBiaeG7h3QgduG7gSBjxqEgaOG7mWkgZ2nDoW8gZOG7pWMsIG5naOG7gSBuZ2hp4buHcCB2w6AgxJFp4buBdSBraeG7h24ga2luaCB04bq/IOKAkyB4w6MgaOG7mWkgZ2nhu69hIGPDoWMgY2jhu6duZyB04buZYy4gTmdvw6BpIHJhLCBwaMOibiBi4buRIG3huqt1IGhv4bq3YyDEkeG6t2MgdGjDuSBraHUgduG7sWMgY8WpbmcgY8OzIHRo4buDIOG6o25oIGjGsOG7n25nIMSR4bq/biBr4bq/dCBxdeG6oyBxdWFuIHPDoXQuDQoNCuKGkiBU4buVbmcgdGjhu4MsIGNo4bunbmcgdOG7mWMgbMOgIG3hu5l0IHnhur91IHThu5EgbGnDqm4gcXVhbiDEkcOhbmcga+G7gyDEkeG6v24ga2jhuqMgbsSDbmcgxJHhuqF0IHRodSBuaOG6rXAgY2FvIHRyb25nIHThuq1wIGThu68gbGnhu4d1IG7DoHkuDQoNCiMjIyBIaeG7h3UgdOG7tyBs4buHDQoNCmBgYHtyfQ0KIyBM4bqtcCBi4bqjbmcgdOG6p24gc+G7kSBjaMOpbyBnaeG7r2EgRXRobmljaXR5IHbDoCBFYXJuaW5nQ2xhc3MNCnRhYmxlX0V0aG5pY2l0eV9FYXJuaW5nQ2xhc3MgPC0gdGFibGUoZCRFdGhuaWNpdHksIGQkRWFybmluZ0NsYXNzKQ0KDQojIFRow6ptIHThu5VuZyBow6BuZyB2w6AgdOG7lW5nIGPhu5l0DQp0YWJsZV9FdGhuaWNpdHlfRWFybmluZ0NsYXNzX21hcmdpbnMgPC0gYWRkbWFyZ2lucyh0YWJsZV9FdGhuaWNpdHlfRWFybmluZ0NsYXNzKQ0KDQojIEhp4buDbiB0aOG7iyBi4bqjbmcNCnRhYmxlX0V0aG5pY2l0eV9FYXJuaW5nQ2xhc3NfbWFyZ2lucw0KYGBgDQoNCi0gXCggcF8xID0gUChcdGV4dHtFYXJuaW5nQ2xhc3N9ID0gXHRleHR7Ij41MEsifSBcbWlkIFx0ZXh0e0V0aG5pY2l0eX0gPSBcdGV4dHsiQmxhY2sifSkgXCkgKFThu7cgbOG7hyBuZ8aw4budaSBkYSDEkWVuIGPDsyB0aHUgbmjhuq1wIGNhbykNCg0KLSBcKCBwXzIgPSBQKFx0ZXh0e0Vhcm5pbmdDbGFzc30gPSBcdGV4dHsiPjUwSyJ9IFxtaWQgXHRleHR7RXRobmljaXR5fSA9IFx0ZXh0eyJXaGl0ZSJ9KSBcKSAoVOG7tyBs4buHIG5nxrDhu51pIGRhIHRy4bqvbmcgY8OzIHRodSBuaOG6rXAgY2FvKQ0KDQpHaeG6oyB0aHV54bq/dCBraeG7g20gxJHhu4tuaDoNCg0KLSBcKCBIXzA6IHBfMSAtIHBfMiA9IDAgXCkgKEtow7RuZyBjw7Mgc+G7sSBraMOhYyBiaeG7h3QgduG7gSB04bu3IGzhu4cgdGh1IG5o4bqtcCBjYW8gZ2nhu69hIG5nxrDhu51pIGRhIMSRZW4gdsOgIG5nxrDhu51pIGRhIHRy4bqvbmcpDQoNCi0gXCggSF8xOiBwXzEgLSBwXzIgPCAwIFwpIChU4bu3IGzhu4cgbmfGsOG7nWkgZGEgxJFlbiBjw7MgdGh1IG5o4bqtcCBjYW8gdGjhuqVwIGjGoW4gbmfGsOG7nWkgZGEgdHLhuq9uZykNCg0KYGBge3J9DQojIFPhu5EgbmfGsOG7nWkgY8OzIHRodSBuaOG6rXAgPjUwSw0KY291bnRzX0Vhcm5pbmdDbGFzc19oaWdoIDwtIGModGFibGVfRXRobmljaXR5X0Vhcm5pbmdDbGFzc1siQmxhY2siLCAiPjUwSyJdLCB0YWJsZV9FdGhuaWNpdHlfRWFybmluZ0NsYXNzWyJXaGl0ZSIsICI+NTBLIl0pDQoNCiMgVOG7lW5nIHPhu5EgbmfGsOG7nWkgdHJvbmcgbeG7l2kgbmjDs20NCnRvdGFsc19FYXJuaW5nQ2xhc3MgPC0gYyhzdW0odGFibGVfRXRobmljaXR5X0Vhcm5pbmdDbGFzc1siQmxhY2siLCBdKSwgc3VtKHRhYmxlX0V0aG5pY2l0eV9FYXJuaW5nQ2xhc3NbIldoaXRlIiwgXSkpDQoNCiMgS2nhu4NtIMSR4buLbmggdOG7iSBs4buHIG3hu5l0IHBow61hOiBwMSA8IHAyDQp0ZXN0X0V0aG5pY2l0eV9FYXJuaW5nQ2xhc3MgPC0gcHJvcC50ZXN0KGNvdW50c19FYXJuaW5nQ2xhc3NfaGlnaCwgdG90YWxzX0Vhcm5pbmdDbGFzcywgYWx0ZXJuYXRpdmUgPSAibGVzcyIsIGNvcnJlY3QgPSBGQUxTRSkNCnRlc3RfRXRobmljaXR5X0Vhcm5pbmdDbGFzcw0KYGBgDQpL4bq/dCBxdeG6oyBraeG7g20gxJHhu4tuaCB04burIHByb3AudGVzdCgpOg0KDQotIFwoIFxoYXR7cH1fMSA9IDAuMTIzOSBcKSwgXCggXGhhdHtwfV8yID0gMC4yNTU5IFwpDQoNCi0gXCggXGhhdHtwfV8xIC0gXGhhdHtwfV8yID0gLTAuMTMyIFwpDQoNCi0gS2hv4bqjbmcgdGluIGPhuq15IDk1JSBjaG8gXCggcF8xIC0gcF8yIFwpOiBcKCBbLTEuMDAwMCxcIC0wLjEyMTRdIFwpDQoNCi0gVGjhu5FuZyBrw6oga2nhu4NtIMSR4buLbmg6IFwoIFxjaGleMiA9IDI2Ni4zIFwpLCBwXHRleHR7LXZhbHVlfSA8IDIuMiBcdGltZXMgMTBeey0xNn0NCg0KS+G6v3QgbHXhuq1uOiBDw7MgYuG6sW5nIGNo4bupbmcgdGjhu5FuZyBrw6ogcuG6pXQgbeG6oW5oIMSR4buDIGLDoWMgYuG7jyBnaeG6oyB0aHV54bq/dCBcKCBIXzAgXCkuIFThu7cgbOG7hyBuZ8aw4budaSBkYSDEkWVuIGPDsyB0aHUgbmjhuq1wIGNhbyB0aOG6pXAgaMahbiDEkcOhbmcga+G7gyBzbyB24bubaSBuZ8aw4budaSBkYSB0cuG6r25nLCB2w6Agc+G7sSBraMOhYyBiaeG7h3QgbsOgeSBjw7Mgw70gbmdoxKlhIHRo4buRbmcga8OqLg0KDQojIyMgUmVsYXRpdmUgUmlzaw0KDQoqKkxp4buHdSBjaOG7p25nIHThu5ljIChXaGl0ZS9CbGFjaykgY8OzIOG6o25oIGjGsOG7n25nIMSR4bq/biBuZ3V5IGPGoSBjw7MgdGh1IG5o4bqtcCBjYW8ga2jDtG5nICg+NTBLKT8qKg0KDQrihpIgTeG7pWMgdGnDqnU6IFNvIHPDoW5oIG5ndXkgY8ahIGPDsyB0aHUgbmjhuq1wIGNhbyDhu58gbmfGsOG7nWkgZGEgdHLhuq9uZyAoV2hpdGUpIHNvIHbhu5tpIG5nxrDhu51pIGRhIMSRZW4gKEJsYWNrKS4NCg0KDQpgYGB7cn0NCnJpc2tyYXRpbyh0YWJsZV9FdGhuaWNpdHlfRWFybmluZ0NsYXNzKQ0KYGBgDQoqKk5o4bqtbiB4w6l0IGvhur90IHF14bqjKioNCg0KKipL4bq/dCBxdeG6oyoqDQoNCi0gVHJvbmcgc+G7kSAyMSw4MTYgbmfGsOG7nWkgZGEgdHLhuq9uZyAoV2hpdGUpLCBjw7MgNywxMTcgbmfGsOG7nWkgKDMyLjYzJSkgY8OzIHRodSBuaOG6rXAgPjUwSy4NCg0KLSBUcm9uZyBz4buRIDMsMTI0IG5nxrDhu51pIGRhIMSRZW4gKEJsYWNrKSwgY8OzIDM4NyBuZ8aw4budaSAoMTIuMzklKSBjw7MgdGh1IG5o4bqtcCA+NTBLLg0KDQotIFThu7cgc+G7kSBuZ3V5IGPGoSAoUlIpID0gMC40OCDihpIgTmfGsOG7nWkgZGEgxJFlbiBjw7Mgbmd1eSBjxqEgY8OzIHRodSBuaOG6rXAgdHLDqm4gNTBLIGNo4buJIGLhurFuZyBraG/huqNuZyBt4buZdCBu4butYSBzbyB24bubaSBuZ8aw4budaSBkYSB0cuG6r25nLg0KDQotIEtob+G6o25nIHRpbiBj4bqteSA5NSUgPSBbMC40NCwgMC41M10g4oaSIEtow7RuZyBiYW8gZ+G7k20gMSDihpIgY8OzIMO9IG5naMSpYSB0aOG7kW5nIGvDqi4NCg0KLSBwLXZhbHVlID0gMC4wMDAg4oaSIFLhuqV0IG5o4buPIGjGoW4gMC4wNSDihpIgQ8OzIGLhurFuZyBjaOG7qW5nIHRo4buRbmcga8OqIG3huqFuaCBt4bq9IHbhu4Egc+G7sSBraMOhYyBiaeG7h3QuDQoNCioqTmjhuq1uIHjDqXQqKg0KDQotIEThu7FhIHRyw6puIGvhur90IHF14bqjIHBow6JuIHTDrWNoLCBuZ8aw4budaSBkYSDEkWVuIGPDsyBuZ3V5IGPGoSDEkeG6oXQgdGh1IG5o4bqtcCA+NTBLIHRo4bqlcCBoxqFuIMSRw6FuZyBr4buDIHNvIHbhu5tpIG5nxrDhu51pIGRhIHRy4bqvbmcuIFThu7cgc+G7kSBuZ3V5IGPGoSBsw6AgMC40OCwga2hv4bqjbmcgdGluIGPhuq15IDk1JSBsw6AgWzAuNDQsIDAuNTNdLCB2w6AgcC12YWx1ZSBi4bqxbmcgMCBjaG8gdGjhuqV5IHPhu7Ega2jDoWMgYmnhu4d0IG7DoHkgbMOgIGPDsyDDvSBuZ2jEqWEgdGjhu5FuZyBrw6ogbeG6oW5oLiDEkGnhu4F1IG7DoHkgaMOgbSDDvSBy4bqxbmcgY2jhu6duZyB04buZYyBsw6AgbeG7mXQgeeG6v3UgdOG7kSBjw7MgbGnDqm4gcXVhbiByw7UgcsOgbmcgxJHhur9uIGto4bqjIG7Eg25nIMSR4bqhdCBt4bupYyB0aHUgbmjhuq1wIGNhbyB0cm9uZyBi4buZIGThu68gbGnhu4d1IG7DoHkuDQoNCiMjIyBPZGRzIFJhdGlvIC0gT1INCg0KYGBge3J9DQojIFTDrW5oIG9kZHMgcmF0aW8gZ2nhu69hIGPDoWMgbmjDs20gRXRobmljaXR5IHNvIHbhu5tpIG5ow7NtIHRoYW0gY2hp4bq/dSAiV2hpdGUiDQpvcl9yZXN1bHRfRXRobmljaXR5IDwtIG9kZHNyYXRpbyh0YWJsZV9FdGhuaWNpdHlfRWFybmluZ0NsYXNzKQ0KDQojIEhp4buDbiB0aOG7iyBr4bq/dCBxdeG6ow0KcHJpbnQob3JfcmVzdWx0X0V0aG5pY2l0eSkNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==