Data Pre-processing
Trước hết load một số R package và đọc bộ số liệu HO3.dta:
# Clear R environment:
rm(list = ls())
# Load some R packages:
library(dplyr)
library(stringr)
library(stringi)
library(kableExtra) # For presenting table.
library(haven)
# Define data paths:
dir("F:/VHLSS2018_Household", full.names = TRUE) -> allPaths
# Import HO3.dta:
read_dta(allPaths[3]) -> ho3
Mỗi một hộ gia đình có ID được hình thành từ mã của 5 cột biến: tỉnh, huyện, xã, địa bàn, hộ số. Vấn đề đầu tiên là chúng ta cần chuẩn hóa các mã này một cách thống nhất cho những mục đích sử dụng xa hơn sau này. Chẳng hạn, tỉnh có mã là 1 thì cần phải chuẩn hóa về 01 (tương ứng với Hà Nội). Mã tỉnh code chuẩn sử dụng 2 chữ số và do vậy với các tỉnh là số tự nhiên bé hơn 9 thì chúng ta phải thêm 1 số 0 đằng trước. Tương tự là Huyện sử dụng 3 chữ số đễ mã hóa. Do vậy với huyện mà chỉ sử dụng 1 chữ số thì chúng ta chuẩn hóa bằng cách thêm 2 chữ số 0 đằng trước, với huyện có mã là 2 chữ số thì thêm 1 chữ số 0 đằng trước. Cách thức chuẩn hóa này áp dụng tương tự cho các biến còn lại là xã, địa bàn và hộ số.
Chúng ta viết hàm có tên add_zero() để chuẩn hóa mã hành chính:
#===================================
# Data Pre-processing for HO3.dta
#==================================
# Function creates full code by adding zeros:
add_zero <- function(x) {
tibble(x_text = as.character(x)) %>%
mutate(n_digits = str_count(x_text),
n_max = max(n_digits),
delta = n_max - n_digits,
pre = strrep("0", times = delta),
full_code = str_c(pre, x_text)) %>%
pull(full_code) %>%
return()
}
Để thuận lợi cho đối chiếu và tra cứu, viết hàm có tên extract_description() để lấy các mô tả về các biến số:
# Function extracts variable description:
extract_description <- function(df_selected) {
sapply(df_selected, function(x) {attributes(x) %>% .$label}) %>%
data.frame() %>%
mutate(description = stri_trans_general(`.`, "Latin-ASCII")) -> df_des
df_des %>%
mutate(var_name = row.names(df_des)) %>%
select(var_name, description) -> df_des
row.names(df_des) <- NULL
return(df_des)
}
Ý nghĩa của các biến số thuộc HO3.dta được trình bày ở Table 1 dưới đây:
# Use the function:
extract_description(df_selected = ho3) -> des_ho3
des_ho3 %>%
kbl(caption = "Table 1: Variable Description for HO3.dta", escape = TRUE) %>%
kable_classic(full_width = TRUE, html_font = "Cambria")
Table 1: Variable Description for HO3.dta
var_name
|
description
|
tinh
|
Tinh
|
huyen
|
Huyen
|
xa
|
Xa
|
diaban
|
Dia ban
|
hoso
|
Ho so
|
thunhap
|
- Thu nhap
|
thubq
|
- Thu nhap binh quan/nguoi/thang
|
tongthu
|
Tong thu
|
chisxkd
|
Chi phi SXKD
|
chikhac
|
Chi tieu va chi khac
|
Tạo một biến mới có tên h_code là mã của các hộ gia đình và mã này được hình thành từ mã chuẩn hóa của tỉnh, huyện, xã, địa bàn và hồ sơ:
#------------------------
# Create Household ID
#------------------------
# Create h_code column:
ho3 %>%
mutate(tinh_n = add_zero(tinh),
huyen_n = add_zero(huyen),
xa_n = add_zero(xa),
diaban_n = add_zero(diaban),
hoso_n = add_zero(hoso)) %>%
mutate(h_code = str_c(tinh_n, huyen_n, xa_n, diaban_n, hoso_n)) -> ho3
Khai thác thông tin về mã tỉnh và tên tỉnh:
#--------------------------
# Extract province names
#--------------------------
# Extract province info:
ho3$tinh %>%
attributes() %>%
.$labels %>% data.frame() -> df_province
# Rename for DF:
names(df_province) <- "province_code"
# Create some columns and relabel for provinces:
df_province %>%
mutate(province_vie = row.names(df_province)) %>%
mutate(province_eng = stri_trans_general(province_vie, "Latin-ASCII")) %>%
mutate(province_eng = str_replace_all(province_eng, "Tinh |Thanh pho ", "")) %>%
mutate(province_eng = str_replace_all(province_eng, " - ", "-")) %>%
mutate(province_code = add_zero(province_code)) -> df_province
row.names(df_province) <- NULL
Một số mã tỉnh và tên tỉnh tướng ứng ở Table 2:
df_province %>%
head() %>%
select(province_eng, province_code) %>%
kbl(caption = "Table 2: Province Code", escape = TRUE) %>%
kable_classic(full_width = TRUE, html_font = "Cambria")
Table 2: Province Code
province_eng
|
province_code
|
Ha Noi
|
01
|
Ha Giang
|
02
|
Cao Bang
|
04
|
Bac Kan
|
06
|
Tuyen Quang
|
08
|
Lao Cai
|
10
|
Joint hai bộ số liệu và xem một số quan sát (Table 3):
# Join the two data sets:
full_join(ho3,
df_province %>% select(province_code, province_eng),
by = c("tinh_n" = "province_code")) -> ho3
ho3 %>%
filter(!duplicated(h_code)) %>%
group_by(province_eng) %>%
count(sort = TRUE) %>%
ungroup() %>%
mutate(total_obs = sum(n)) %>%
kbl(caption = "Table 4: Number of Observation by Province", escape = TRUE) %>%
kable_classic(full_width = TRUE, html_font = "Cambria")
Table 4: Number of Observation by Province
province_eng
|
n
|
total_obs
|
Ho Chi Minh
|
1755
|
45839
|
Ha Noi
|
1575
|
45839
|
Thanh Hoa
|
1230
|
45839
|
Nghe An
|
1125
|
45839
|
Dong Nai
|
1035
|
45839
|
Nam Dinh
|
975
|
45839
|
Thai Binh
|
945
|
45839
|
Hai Phong
|
930
|
45839
|
Hai Duong
|
915
|
45839
|
Binh Duong
|
885
|
45839
|
Tien Giang
|
855
|
45839
|
Bac Giang
|
840
|
45839
|
Dong Thap
|
840
|
45839
|
Dak Lak
|
825
|
45839
|
Binh Dinh
|
810
|
45839
|
Kien Giang
|
810
|
45839
|
Quang Nam
|
795
|
45839
|
Long An
|
780
|
45839
|
Phu Tho
|
780
|
45839
|
Ben Tre
|
765
|
45839
|
Hung Yen
|
735
|
45839
|
Quang Ngai
|
735
|
45839
|
Quang Ninh
|
735
|
45839
|
Thai Nguyen
|
734
|
45839
|
Soc Trang
|
720
|
45839
|
An Giang
|
705
|
45839
|
Lam Dong
|
705
|
45839
|
Bac Ninh
|
690
|
45839
|
Ca Mau
|
690
|
45839
|
Can Tho
|
690
|
45839
|
Gia Lai
|
690
|
45839
|
Khanh Hoa
|
690
|
45839
|
Binh Thuan
|
675
|
45839
|
Tay Ninh
|
675
|
45839
|
Thua Thien Hue
|
675
|
45839
|
Vinh Long
|
675
|
45839
|
Vinh Phuc
|
675
|
45839
|
Ba Ria-Vung Tau
|
660
|
45839
|
Ninh Binh
|
645
|
45839
|
Tra Vinh
|
645
|
45839
|
Son La
|
630
|
45839
|
Da Nang
|
615
|
45839
|
Ha Nam
|
615
|
45839
|
Phu Yen
|
615
|
45839
|
Binh Phuoc
|
600
|
45839
|
Quang Binh
|
600
|
45839
|
Bac Lieu
|
570
|
45839
|
Hoa Binh
|
570
|
45839
|
Tuyen Quang
|
570
|
45839
|
Yen Bai
|
570
|
45839
|
Hau Giang
|
555
|
45839
|
Lang Son
|
540
|
45839
|
Ha Giang
|
525
|
45839
|
Bac Kan
|
510
|
45839
|
Dak Nong
|
510
|
45839
|
Dien Bien
|
510
|
45839
|
Kon Tum
|
510
|
45839
|
Lai Chau
|
510
|
45839
|
Lao Cai
|
510
|
45839
|
Ninh Thuan
|
510
|
45839
|
Quang Tri
|
510
|
45839
|
Cao Bang
|
495
|
45839
|
Ha Tinh
|
375
|
45839
|
Dễ thấy rằng có 45839 hộ được khảo sát (con số này bé hơn một chút so với 46995 trong báo cáo trên của GSO, có lẽ bộ data đang sử dụng là chưa đầy đủ). TP.HCM, Hà Nội và Thanh Hóa có số hộ được khảo sát là cao nhất. Đến đây chúng ta có thể tính toán các con số tổng, median, 25th và 75 percentiles (cho SXKD, chi khác, thu nhập) ở cấp độ hộ gia đình:
# Calculate some metrics at household level:
ho3 %>%
group_by(h_code, province_eng) %>%
summarise(total_chi_SXKD = sum(chisxkd, na.rm = TRUE),
total_chi_khac = sum(chikhac, na.rm = TRUE),
total_thunhap = sum(thunhap, na.rm = TRUE)) %>%
ungroup() -> df_thu_chi
df_thu_chi %>%
group_by(province_eng) %>%
summarise(avg_income = mean(total_thunhap),
th25 = quantile(total_thunhap, 0.25),
th50 = quantile(total_thunhap, 0.50),
th75 = quantile(total_thunhap, 0.75)) %>%
mutate_if(is.numeric, function(x) {round(x / 1000, 1)}) %>%
ungroup() %>%
arrange(th50) %>%
mutate(province_eng = factor(province_eng, province_eng)) -> df_thunhap
Gaps in Household Income
Thu nhập hộ gia đình (Figure 1) có mấy điểm chính sau:
- Với Đà Nẵng thì 25% số hộ có thu nhập hàng năm thấp hơn 250 triệu, 25% số hộ có thu nhập cao hơn 700 triệu. Đây cũng là tình có thu nhập trung vị (median) hộ gia đình hàng năm cao nhất cả nước.
- Điện Biên là tỉnh nghèo nhất nước: 50% số hộ ở tỉnh này có thu nhập bé hơn 80 triệu.
R codes cho Figure 1:
#====================
# Data Visualization
#====================
# Load some R packages for Data Visualization:
library(ggeconodist) # install.packages("ggeconodist", repos = "https://cinc.rud.is")
library(ggplot2)
library(showtext)
# Select Ubuntu Condensed font:
showtext.auto()
font_add_google(name = "Ubuntu Condensed", family = "ubu")
my_font <- "ubu"
df_thunhap %>%
ggplot(aes(x = province_eng)) +
geom_econodist(aes(ymin = th25, median = th50, ymax = th75),
median_col = "firebrick",
stat = "identity",
median_point_size = 1.3,
show.legend = TRUE) +
coord_flip() +
theme_econodist() +
scale_y_continuous(expand = c(0, 0), limits = range(0, 800), breaks = seq(0, 800, 100), position = "right") +
labs(title = "Figure 1: Gaps in Household Income (millions VND) by Province, 2018",
caption = "Data Source: VHLSS 2018, GSO") +
theme(plot.margin = unit(c(0.3, 1, 0.3, 0.5), "cm")) +
theme(axis.title.y = element_blank()) +
theme(axis.text.y = element_text(family = my_font, size = 8.5)) +
theme(axis.text.x = element_text(family = my_font)) +
theme(plot.caption = element_text(family = my_font, size = 8, face = "italic")) +
theme(plot.title = element_text(family = my_font, size = 15)) -> f1
grid.newpage()
f1 %>%
left_align(c("title", "caption")) %>%
add_econodist_legend(
econodist_legend_grob(
tenth_lab = "25th Percentile",
ninetieth_lab = "75th Percentile",
med_lab = "Median",
med_col = "firebrick",
family = my_font,
label_size = 11,
),
below = "title"
) %>%
grid.draw()
Production Cost - Household Income Relationship
Để đánh giá ảnh hưởng của chi phí sản xuất (Production Cost) lên thu nhập hộ gia đình có tính đến sự khác biệt giữa các tỉnh, xét mô hình đơn giản sau:
\[Income_i = \beta_0 + \beta_1 Province_{i} + \beta_2 ProductionCost_{i} + u_i \ , \ i=1,\dots,n.\] Trong mô hình này, Province được coi là dummy variable mà hệ số hồi quy của chúng sẽ cho ta biết sự khác biệt về ảnh hưởng của chi cho sản xuất kinh doanh lên thu nhập hộ gia đình. Kết quả của mô hình này được trình bày ở Table 4 dưới đây:
# Regression:
df_thu_chi %>%
mutate(Province = province_eng,
ProductionCost = total_chi_SXKD / 1000,
Income = total_thunhap / 1000) %>% # Rename for convinience.
lm(Income ~ Province + ProductionCost, data = .) -> reg
# Extract coefficients:
broom::tidy(reg) %>%
mutate(Variable = str_replace_all(term, "Province", "")) -> df_coeff
# Show main regression results (Table 3):
df_coeff %>%
mutate(Estimate = round(estimate, 1), Std.error = round(std.error, 3), P.value = round(p.value, 3)) %>%
select(Variable, Estimate, Std.error, P.value) -> df_coeff
df_coeff %>%
filter(Variable %in% c("(Intercept)", "ProductionCost")) %>%
bind_rows(df_coeff %>%
filter(!Variable %in% c("(Intercept)", "ProductionCost")) %>%
arrange(-Estimate)) %>%
kbl(caption = "Table 3: Income-Production Cost Relationship, R-squared = 86.92%", escape = TRUE) %>%
kable_classic(full_width = TRUE, html_font = "Cambria")
Table 3: Income-Production Cost Relationship, R-squared = 86.92%
Variable
|
Estimate
|
Std.error
|
P.value
|
(Intercept)
|
213.8
|
9.678
|
0.000
|
ProductionCost
|
1.1
|
0.002
|
0.000
|
Da Nang
|
236.6
|
14.173
|
0.000
|
Ho Chi Minh
|
232.6
|
11.454
|
0.000
|
Ha Noi
|
197.4
|
11.640
|
0.000
|
Bac Ninh
|
183.8
|
13.765
|
0.000
|
Binh Duong
|
172.1
|
12.967
|
0.000
|
Dong Nai
|
140.0
|
12.544
|
0.000
|
Hai Phong
|
127.0
|
12.828
|
0.000
|
Quang Ninh
|
96.0
|
13.542
|
0.000
|
Vinh Phuc
|
71.8
|
13.833
|
0.000
|
Can Tho
|
65.8
|
13.756
|
0.000
|
Ba Ria-Vung Tau
|
54.2
|
13.913
|
0.000
|
Tay Ninh
|
40.7
|
13.833
|
0.003
|
Khanh Hoa
|
34.6
|
13.757
|
0.012
|
Hung Yen
|
26.5
|
13.542
|
0.050
|
Bac Giang
|
22.9
|
13.121
|
0.081
|
Tien Giang
|
20.6
|
13.068
|
0.116
|
Thua Thien Hue
|
20.4
|
13.833
|
0.141
|
Long An
|
19.9
|
13.349
|
0.137
|
Kien Giang
|
19.3
|
13.231
|
0.145
|
Hai Duong
|
17.7
|
12.873
|
0.169
|
Thai Nguyen
|
11.3
|
13.546
|
0.406
|
Quang Nam
|
5.1
|
13.289
|
0.699
|
Binh Thuan
|
0.3
|
13.833
|
0.983
|
Thai Binh
|
-2.1
|
12.784
|
0.870
|
Nam Dinh
|
-6.6
|
12.699
|
0.603
|
Ha Nam
|
-9.8
|
14.174
|
0.491
|
Ninh Binh
|
-11.1
|
13.996
|
0.428
|
Hau Giang
|
-12.0
|
14.577
|
0.410
|
Phu Tho
|
-15.7
|
13.349
|
0.240
|
Ca Mau
|
-15.9
|
13.757
|
0.247
|
Thanh Hoa
|
-17.3
|
12.135
|
0.155
|
Dong Thap
|
-19.0
|
13.120
|
0.147
|
Binh Dinh
|
-20.9
|
13.231
|
0.114
|
Ninh Thuan
|
-26.5
|
14.933
|
0.076
|
Quang Binh
|
-28.7
|
14.268
|
0.044
|
Bac Lieu
|
-28.9
|
14.469
|
0.046
|
Lao Cai
|
-30.9
|
14.932
|
0.038
|
Vinh Long
|
-32.6
|
13.833
|
0.018
|
Binh Phuoc
|
-33.4
|
14.267
|
0.019
|
Quang Tri
|
-33.7
|
14.932
|
0.024
|
Quang Ngai
|
-34.3
|
13.542
|
0.011
|
Lam Dong
|
-35.4
|
13.681
|
0.010
|
Ben Tre
|
-36.5
|
13.411
|
0.006
|
Soc Trang
|
-38.0
|
13.610
|
0.005
|
Nghe An
|
-44.1
|
12.340
|
0.000
|
Gia Lai
|
-45.0
|
13.756
|
0.001
|
Phu Yen
|
-46.2
|
14.174
|
0.001
|
Yen Bai
|
-50.6
|
14.469
|
0.000
|
Hoa Binh
|
-58.1
|
14.470
|
0.000
|
Ha Giang
|
-58.7
|
14.808
|
0.000
|
Tuyen Quang
|
-59.1
|
14.470
|
0.000
|
Ha Tinh
|
-63.1
|
16.418
|
0.000
|
Dak Lak
|
-64.8
|
13.175
|
0.000
|
Tra Vinh
|
-66.6
|
13.997
|
0.000
|
Lang Son
|
-66.8
|
14.690
|
0.000
|
Kon Tum
|
-75.0
|
14.933
|
0.000
|
Dien Bien
|
-87.3
|
14.933
|
0.000
|
Cao Bang
|
-87.9
|
15.064
|
0.000
|
Bac Kan
|
-95.3
|
14.933
|
0.000
|
Dak Nong
|
-98.3
|
14.932
|
0.000
|
Lai Chau
|
-102.3
|
14.933
|
0.000
|
Son La
|
-114.8
|
14.083
|
0.000
|
Một số kết quả chính từ Table 4:
- Chi 1 triệu cho SXKD thì trung bình thu nhập hộ gia đình tăng 1.1 triệu (ceteris paribus).
- Đà Nẵng, Tp Hồ Chí Minh, Hà Nội, Bắc Ninh, Bình Dương là những tỉnh tốt cho hoạt động đầu tư sản xuất kinh doanh. Đứng cuối bảng là Cao Bằng, Bắc Kạn, Dak Nông, Lai Châu và Sơn La.
LS0tDQp0aXRsZTogJ1Byb2R1Y3Rpb24gQ29zdCBhbmQgSG91c2Vob2xkIEluY29tZTogU29tZSBJbnNpZ2h0cyBmcm9tIFZITFNTIDIwMTgnDQphdXRob3I6ICdBdXRob3I6IE5ndXllbiBDaGkgRHVuZycNCnN1YnRpdGxlOiAiUiBEYWlseSBHcmFwaCBTZXJpZXMiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICAjIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGhpZ2hsaWdodDogemVuYnVybg0KICAgICMgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtZTogImZsYXRseSINCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCi0tLQ0KDQpgYGB7ciBzZXR1cCxpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgY2FjaGUgPSBUUlVFKQ0KDQpgYGANCg0KIVtdKEM6L1VzZXJzL0FETUlOL0RvY3VtZW50cy9pbmNvbWUxLmpwZykNCg0KIyBJbnRyb2R1Y3Rpb24NCg0KQuG7mSBz4buRIGxp4buHdSBWSExTUyAoW0hvdXNlaG9sZCBMaXZpbmcgU3RhbmRhcmRzIFN1cnZleV0oaHR0cDovL2lyZXNlYXJjaC53b3JsZGJhbmsub3JnL1BvdmNhbE5ldC9Eb2NzL0NvdW50cnlEb2NzL1ZOTS5odG0pKSDEkcaw4bujYyBHU08gLSBjxqEgcXVhbiB0aOG7kW5nIGvDqiBxdeG7kWMgZ2lhIGPhu6dhIFZp4buHdCBOYW0gdGnhur9uIGjDoG5oIGto4bqjbyBzw6F0IGPhu6kgbeG7l2kgaGFpIG7Eg20gbeG7mXQgbOG6p24uIEfhuqduIMSRw6J5IG5o4bqldCBsw6AgbsSDbSAyMDE4IGfhu5NtIDQ0IGZpbGVzIGThu68gbGnhu4d1ICjEkXXDtGkgbMOgIC5kdGEgY+G7p2EgcGjhuqduIG3hu4FtIFN0YXRhLCB0aGFtIGto4bqjbyB0aMOqbSB0aMO0bmcgdGluIHbhu4EgVkhMU1MgMjAxOCBbdOG6oWkgxJHDonldKGh0dHBzOi8vd3d3Lmdzby5nb3Yudm4vd3AtY29udGVudC91cGxvYWRzLzIwMjAvMDUvVkhMU1MyMDE4LnBkZikpLiBN4buXaSBt4buZdCBmaWxlIGThu68gbGnhu4d1IGzDoCB0aMO0bmcgdGluIGto4bqjbyBzw6F0IOG7nyBj4bqlcCDEkeG7mSBo4buZIGdpYSDEkcOsbmggaG/hurdjIGPDoSBuaMOibiB24buBIGPDoWMga2jDrWEgY+G6oW5oIGtow6FjIG5oYXUgY+G7p2EgxJHhu51pIHPhu5FuZyBuaMawIEdpw6FvIEThu6VjLCBZIFThur8sIFRodSBOaOG6rXAsIMSQ4bqndSBUxrAgLSBDaGkgVGnDqnUuIFBvc3QgbsOgeSBz4bq9IGjGsOG7m25nIGThuqtuIGNoaSB0aeG6v3QgY8OhY2ggdGjhu6ljIHjhu60gbMOtIGLhu5kgc+G7kSBsaeG7h3UgduG7gSDEkOG6p3UgVMawLCBDaGkgVGnDqnUgdsOgIFRodSBOaOG6rXAgY+G7p2EgaOG7mSBnaWEgxJHDrG5oIMSRxrDhu6NjIGzGsHUgdHJvbmcgZmlsZSBjw7MgdMOqbiAqKkhPMy5kdGEqKiBn4buTbSAzNjY3MTIgcXVhbiBzw6F0LCAxMCBiaeG6v24gc+G7kS4gVOG6oWkgdGjhu51pIMSRaeG7g20gdmnhur90IGLDoGkgbsOgeSwgZG8ga2jDtG5nIHRo4buDIHB1YmxpYyBi4buZIGThu68gbGnhu4d1LCBi4bqhbiDEkeG7jWMgcXVhbiB0w6JtIMSR4bq/biBi4buZIHPhu5EgbGnhu4d1IG7DoHkgY8OzIHRo4buDIGVtYWlsIMSR4bq/biDEkeG7i2EgY2jhu4kgKm5ndXllbmNoaWR1bmcwMjA5QGdtYWlsLmNvbSouIA0KDQpSIGNvZGVzIHjhu60gbMOtIGLhu5kgc+G7kSBsaeG7h3UgbsOgeSBjw7MgdGjhu4MgxJHGsOG7o2Mgw6FwIGThu6VuZyDEkeG7gyB44butIGzDrSBjw6FjIGLhu5kgZOG7ryBsaeG7h3Uga2jDoWMgaG/hurdjIGPDoWMgYuG7mSBWSExTUyBj4bunYSBuaOG7r25nIG7Eg20gdHLGsOG7m2MgxJHDsy4gDQoNCiMgRGF0YSBQcmUtcHJvY2Vzc2luZw0KDQpUcsaw4bubYyBo4bq/dCBsb2FkIG3hu5l0IHPhu5EgUiBwYWNrYWdlIHbDoCDEkeG7jWMgYuG7mSBz4buRIGxp4buHdSBITzMuZHRhOiANCg0KYGBge3J9DQoNCiMgQ2xlYXIgUiBlbnZpcm9ubWVudDogDQpybShsaXN0ID0gbHMoKSkNCg0KIyBMb2FkIHNvbWUgUiBwYWNrYWdlczogDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeShzdHJpbmdpKQ0KbGlicmFyeShrYWJsZUV4dHJhKSAjIEZvciBwcmVzZW50aW5nIHRhYmxlLiANCmxpYnJhcnkoaGF2ZW4pDQoNCiMgRGVmaW5lIGRhdGEgcGF0aHM6IA0KDQpkaXIoIkY6L1ZITFNTMjAxOF9Ib3VzZWhvbGQiLCBmdWxsLm5hbWVzID0gVFJVRSkgLT4gYWxsUGF0aHMNCg0KIyBJbXBvcnQgSE8zLmR0YTogDQoNCnJlYWRfZHRhKGFsbFBhdGhzWzNdKSAtPiBobzMNCg0KYGBgDQoNCk3hu5dpIG3hu5l0IGjhu5kgZ2lhIMSRw6xuaCBjw7MgSUQgxJHGsOG7o2MgaMOsbmggdGjDoG5oIHThu6sgbcOjIGPhu6dhIDUgY+G7mXQgYmnhur9uOiB04buJbmgsIGh1eeG7h24sIHjDoywgxJHhu4thIGLDoG4sIGjhu5kgc+G7kS4gVuG6pW4gxJHhu4EgxJHhuqd1IHRpw6puIGzDoCBjaMO6bmcgdGEgY+G6p24gY2h14bqpbiBow7NhIGPDoWMgbcOjIG7DoHkgbeG7mXQgY8OhY2ggdGjhu5FuZyBuaOG6pXQgY2hvIG5o4buvbmcgbeG7pWMgxJHDrWNoIHPhu60gZOG7pW5nIHhhIGjGoW4gc2F1IG7DoHkuIENo4bqzbmcgaOG6oW4sIHThu4luaCBjw7MgbcOjIGzDoCAxIHRow6wgY+G6p24gcGjhuqNpIGNodeG6qW4gaMOzYSB24buBIDAxICh0xrDGoW5nIOG7qW5nIHbhu5tpIEjDoCBO4buZaSkuIE3DoyB04buJbmggY29kZSBjaHXhuqluIHPhu60gZOG7pW5nIDIgY2jhu68gc+G7kSB2w6AgZG8gduG6rXkgduG7m2kgY8OhYyB04buJbmggbMOgIHPhu5EgdOG7sSBuaGnDqm4gYsOpIGjGoW4gOSB0aMOsIGNow7puZyB0YSBwaOG6o2kgdGjDqm0gMSBz4buRIDAgxJHhurFuZyB0csaw4bubYy4gVMawxqFuZyB04buxIGzDoCBIdXnhu4duIHPhu60gZOG7pW5nIDMgY2jhu68gc+G7kSDEkeG7hSBtw6MgaMOzYS4gRG8gduG6rXkgduG7m2kgaHV54buHbiBtw6AgY2jhu4kgc+G7rSBk4bulbmcgMSBjaOG7ryBz4buRIHRow6wgY2jDum5nIHRhIGNodeG6qW4gaMOzYSBi4bqxbmcgY8OhY2ggdGjDqm0gMiBjaOG7ryBz4buRIDAgxJHhurFuZyB0csaw4bubYywgduG7m2kgaHV54buHbiBjw7MgbcOjIGzDoCAyIGNo4buvIHPhu5EgdGjDrCB0aMOqbSAxIGNo4buvIHPhu5EgMCDEkeG6sW5nIHRyxrDhu5tjLiBDw6FjaCB0aOG7qWMgY2h14bqpbiBow7NhIG7DoHkgw6FwIGThu6VuZyB0xrDGoW5nIHThu7EgY2hvIGPDoWMgYmnhur9uIGPDsm4gbOG6oWkgbMOgIHjDoywgxJHhu4thIGLDoG4gdsOgIGjhu5kgc+G7kS4gDQoNCkNow7puZyB0YSB2aeG6v3QgaMOgbSBjw7MgdMOqbiAqKmFkZF96ZXJvKCkqKiDEkeG7gyBjaHXhuqluIGjDs2EgbcOjIGjDoG5oIGNow61uaDogDQoNCmBgYHtyfQ0KDQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgIERhdGEgUHJlLXByb2Nlc3NpbmcgZm9yIEhPMy5kdGEgDQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojIEZ1bmN0aW9uIGNyZWF0ZXMgZnVsbCBjb2RlIGJ5IGFkZGluZyB6ZXJvczogDQoNCmFkZF96ZXJvIDwtIGZ1bmN0aW9uKHgpIHsNCiAgDQogIHRpYmJsZSh4X3RleHQgPSBhcy5jaGFyYWN0ZXIoeCkpICU+JSANCiAgICBtdXRhdGUobl9kaWdpdHMgPSBzdHJfY291bnQoeF90ZXh0KSwNCiAgICAgICAgICAgbl9tYXggPSBtYXgobl9kaWdpdHMpLCANCiAgICAgICAgICAgZGVsdGEgPSBuX21heCAtIG5fZGlnaXRzLCANCiAgICAgICAgICAgcHJlID0gc3RycmVwKCIwIiwgdGltZXMgPSBkZWx0YSksIA0KICAgICAgICAgICBmdWxsX2NvZGUgPSBzdHJfYyhwcmUsIHhfdGV4dCkpICU+JSANCiAgICBwdWxsKGZ1bGxfY29kZSkgJT4lIA0KICAgIHJldHVybigpDQp9DQpgYGANCg0KxJDhu4MgdGh14bqtbiBs4bujaSBjaG8gxJHhu5FpIGNoaeG6v3UgdsOgIHRyYSBj4bupdSwgdmnhur90IGjDoG0gY8OzIHTDqm4gKipleHRyYWN0X2Rlc2NyaXB0aW9uKCkqKiDEkeG7gyBs4bqleSBjw6FjIG3DtCB04bqjIHbhu4EgY8OhYyBiaeG6v24gc+G7kTogDQoNCmBgYHtyfQ0KIyBGdW5jdGlvbiBleHRyYWN0cyB2YXJpYWJsZSBkZXNjcmlwdGlvbjogDQoNCmV4dHJhY3RfZGVzY3JpcHRpb24gPC0gZnVuY3Rpb24oZGZfc2VsZWN0ZWQpIHsNCiAgDQogIHNhcHBseShkZl9zZWxlY3RlZCwgZnVuY3Rpb24oeCkge2F0dHJpYnV0ZXMoeCkgJT4lIC4kbGFiZWx9KSAlPiUgDQogICAgZGF0YS5mcmFtZSgpICU+JSANCiAgICBtdXRhdGUoZGVzY3JpcHRpb24gPSBzdHJpX3RyYW5zX2dlbmVyYWwoYC5gLCAiTGF0aW4tQVNDSUkiKSkgLT4gZGZfZGVzDQogIA0KICBkZl9kZXMgJT4lIA0KICAgIG11dGF0ZSh2YXJfbmFtZSA9IHJvdy5uYW1lcyhkZl9kZXMpKSAlPiUgDQogICAgc2VsZWN0KHZhcl9uYW1lLCBkZXNjcmlwdGlvbikgLT4gZGZfZGVzDQogIA0KICByb3cubmFtZXMoZGZfZGVzKSA8LSBOVUxMDQogIA0KICByZXR1cm4oZGZfZGVzKQ0KICANCn0NCmBgYA0KDQrDnSBuZ2jEqWEgY+G7p2EgY8OhYyBiaeG6v24gc+G7kSB0aHXhu5ljIEhPMy5kdGEgxJHGsOG7o2MgdHLDrG5oIGLDoHkg4bufIFRhYmxlIDEgZMaw4bubaSDEkcOieTogDQoNCmBgYHtyfQ0KIyBVc2UgdGhlIGZ1bmN0aW9uOiANCg0KZXh0cmFjdF9kZXNjcmlwdGlvbihkZl9zZWxlY3RlZCA9IGhvMykgLT4gZGVzX2hvMw0KDQpkZXNfaG8zICU+JSANCiAga2JsKGNhcHRpb24gPSAiVGFibGUgMTogVmFyaWFibGUgRGVzY3JpcHRpb24gZm9yIEhPMy5kdGEiLCBlc2NhcGUgPSBUUlVFKSAlPiUNCiAga2FibGVfY2xhc3NpYyhmdWxsX3dpZHRoID0gVFJVRSwgaHRtbF9mb250ID0gIkNhbWJyaWEiKQ0KYGBgDQoNClThuqFvIG3hu5l0IGJp4bq/biBt4bubaSBjw7MgdMOqbiBoX2NvZGUgbMOgIG3DoyBj4bunYSBjw6FjIGjhu5kgZ2lhIMSRw6xuaCB2w6AgbcOjIG7DoHkgxJHGsOG7o2MgaMOsbmggdGjDoG5oIHThu6sgbcOjIGNodeG6qW4gaMOzYSBj4bunYSB04buJbmgsIGh1eeG7h24sIHjDoywgxJHhu4thIGLDoG4gdsOgIGjhu5Mgc8ahOiANCg0KYGBge3J9DQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojICBDcmVhdGUgSG91c2Vob2xkIElEDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgQ3JlYXRlIGhfY29kZSBjb2x1bW46IA0KDQpobzMgJT4lIA0KICBtdXRhdGUodGluaF9uID0gYWRkX3plcm8odGluaCksIA0KICAgICAgICAgaHV5ZW5fbiA9IGFkZF96ZXJvKGh1eWVuKSwgDQogICAgICAgICB4YV9uID0gYWRkX3plcm8oeGEpLCANCiAgICAgICAgIGRpYWJhbl9uID0gYWRkX3plcm8oZGlhYmFuKSwgDQogICAgICAgICBob3NvX24gPSBhZGRfemVybyhob3NvKSkgJT4lIA0KICBtdXRhdGUoaF9jb2RlID0gc3RyX2ModGluaF9uLCBodXllbl9uLCB4YV9uLCBkaWFiYW5fbiwgaG9zb19uKSkgLT4gaG8zDQoNCmBgYA0KDQpLaGFpIHRow6FjIHRow7RuZyB0aW4gduG7gSBtw6MgdOG7iW5oIHbDoCB0w6puIHThu4luaDogDQpgYGB7cn0NCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgRXh0cmFjdCBwcm92aW5jZSBuYW1lcw0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgRXh0cmFjdCBwcm92aW5jZSBpbmZvOg0KDQpobzMkdGluaCAlPiUgDQogIGF0dHJpYnV0ZXMoKSAlPiUgDQogIC4kbGFiZWxzICU+JSBkYXRhLmZyYW1lKCkgLT4gZGZfcHJvdmluY2UNCg0KIyBSZW5hbWUgZm9yIERGOiANCm5hbWVzKGRmX3Byb3ZpbmNlKSA8LSAicHJvdmluY2VfY29kZSINCg0KIyBDcmVhdGUgc29tZSBjb2x1bW5zIGFuZCByZWxhYmVsIGZvciBwcm92aW5jZXM6IA0KDQpkZl9wcm92aW5jZSAlPiUgDQogIG11dGF0ZShwcm92aW5jZV92aWUgPSByb3cubmFtZXMoZGZfcHJvdmluY2UpKSAlPiUgDQogIG11dGF0ZShwcm92aW5jZV9lbmcgPSBzdHJpX3RyYW5zX2dlbmVyYWwocHJvdmluY2VfdmllLCAiTGF0aW4tQVNDSUkiKSkgJT4lIA0KICBtdXRhdGUocHJvdmluY2VfZW5nID0gc3RyX3JlcGxhY2VfYWxsKHByb3ZpbmNlX2VuZywgIlRpbmggfFRoYW5oIHBobyAiLCAiIikpICU+JSANCiAgbXV0YXRlKHByb3ZpbmNlX2VuZyA9IHN0cl9yZXBsYWNlX2FsbChwcm92aW5jZV9lbmcsICIgLSAiLCAiLSIpKSAlPiUgDQogIG11dGF0ZShwcm92aW5jZV9jb2RlID0gYWRkX3plcm8ocHJvdmluY2VfY29kZSkpIC0+IGRmX3Byb3ZpbmNlDQoNCnJvdy5uYW1lcyhkZl9wcm92aW5jZSkgPC0gTlVMTA0KDQpgYGANCg0KTeG7mXQgc+G7kSBtw6MgdOG7iW5oIHbDoCB0w6puIHThu4luaCB0xrDhu5tuZyDhu6luZyDhu58gVGFibGUgMjogDQoNCmBgYHtyfQ0KZGZfcHJvdmluY2UgJT4lIA0KICBoZWFkKCkgJT4lIA0KICBzZWxlY3QocHJvdmluY2VfZW5nLCBwcm92aW5jZV9jb2RlKSAlPiUgDQogIGtibChjYXB0aW9uID0gIlRhYmxlIDI6IFByb3ZpbmNlIENvZGUiLCBlc2NhcGUgPSBUUlVFKSAlPiUNCiAga2FibGVfY2xhc3NpYyhmdWxsX3dpZHRoID0gVFJVRSwgaHRtbF9mb250ID0gIkNhbWJyaWEiKQ0KYGBgDQoNCkpvaW50IGhhaSBi4buZIHPhu5EgbGnhu4d1IHbDoCB4ZW0gbeG7mXQgc+G7kSBxdWFuIHPDoXQgKFRhYmxlIDMpOiANCg0KYGBge3J9DQojIEpvaW4gdGhlIHR3byBkYXRhIHNldHM6IA0KDQpmdWxsX2pvaW4oaG8zLCANCiAgICAgICAgICBkZl9wcm92aW5jZSAlPiUgc2VsZWN0KHByb3ZpbmNlX2NvZGUsIHByb3ZpbmNlX2VuZyksIA0KICAgICAgICAgIGJ5ID0gYygidGluaF9uIiA9ICJwcm92aW5jZV9jb2RlIikpIC0+IGhvMw0KYGBgDQoNCg0KYGBge3J9DQpobzMgJT4lIA0KICBmaWx0ZXIoIWR1cGxpY2F0ZWQoaF9jb2RlKSkgJT4lIA0KICBncm91cF9ieShwcm92aW5jZV9lbmcpICU+JSANCiAgY291bnQoc29ydCA9IFRSVUUpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgbXV0YXRlKHRvdGFsX29icyA9IHN1bShuKSkgJT4lIA0KICBrYmwoY2FwdGlvbiA9ICJUYWJsZSA0OiBOdW1iZXIgb2YgT2JzZXJ2YXRpb24gYnkgUHJvdmluY2UiLCBlc2NhcGUgPSBUUlVFKSAlPiUNCiAga2FibGVfY2xhc3NpYyhmdWxsX3dpZHRoID0gVFJVRSwgaHRtbF9mb250ID0gIkNhbWJyaWEiKQ0KYGBgDQoNCkThu4UgdGjhuqV5IHLhurFuZyBjw7MgNDU4MzkgaOG7mSDEkcaw4bujYyBraOG6o28gc8OhdCAoY29uIHPhu5EgbsOgeSBiw6kgaMahbiBt4buZdCBjaMO6dCBzbyB24bubaSA0Njk5NSB0cm9uZyBiw6FvIGPDoW8gdHLDqm4gY+G7p2EgR1NPLCBjw7MgbOG6vSBi4buZIGRhdGEgxJFhbmcgc+G7rSBk4bulbmcgbMOgIGNoxrBhIMSR4bqneSDEkeG7pykuIFRQLkhDTSwgSMOgIE7hu5lpIHbDoCBUaGFuaCBIw7NhIGPDsyBz4buRIGjhu5kgxJHGsOG7o2Mga2jhuqNvIHPDoXQgbMOgIGNhbyBuaOG6pXQuIMSQ4bq/biDEkcOieSBjaMO6bmcgdGEgY8OzIHRo4buDIHTDrW5oIHRvw6FuIGPDoWMgY29uIHPhu5EgdOG7lW5nLCBtZWRpYW4sIDI1dGggdsOgIDc1IHBlcmNlbnRpbGVzIChjaG8gU1hLRCwgY2hpIGtow6FjLCB0aHUgbmjhuq1wKSDhu58gY+G6pXAgxJHhu5kgaOG7mSBnaWEgxJHDrG5oOiANCg0KDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIHNvbWUgbWV0cmljcyBhdCBob3VzZWhvbGQgbGV2ZWw6IA0KDQpobzMgJT4lIA0KICBncm91cF9ieShoX2NvZGUsIHByb3ZpbmNlX2VuZykgJT4lIA0KICBzdW1tYXJpc2UodG90YWxfY2hpX1NYS0QgPSBzdW0oY2hpc3hrZCwgbmEucm0gPSBUUlVFKSwgDQogICAgICAgICAgICB0b3RhbF9jaGlfa2hhYyA9IHN1bShjaGlraGFjLCBuYS5ybSA9IFRSVUUpLCANCiAgICAgICAgICAgIHRvdGFsX3RodW5oYXAgPSBzdW0odGh1bmhhcCwgbmEucm0gPSBUUlVFKSkgJT4lIA0KICB1bmdyb3VwKCkgLT4gZGZfdGh1X2NoaQ0KDQoNCmRmX3RodV9jaGkgJT4lIA0KICBncm91cF9ieShwcm92aW5jZV9lbmcpICU+JSANCiAgc3VtbWFyaXNlKGF2Z19pbmNvbWUgPSBtZWFuKHRvdGFsX3RodW5oYXApLCANCiAgICAgICAgICAgIHRoMjUgPSBxdWFudGlsZSh0b3RhbF90aHVuaGFwLCAwLjI1KSwgDQogICAgICAgICAgICB0aDUwID0gcXVhbnRpbGUodG90YWxfdGh1bmhhcCwgMC41MCksIA0KICAgICAgICAgICAgdGg3NSA9IHF1YW50aWxlKHRvdGFsX3RodW5oYXAsIDAuNzUpKSAlPiUgDQogIG11dGF0ZV9pZihpcy5udW1lcmljLCBmdW5jdGlvbih4KSB7cm91bmQoeCAvIDEwMDAsIDEpfSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBhcnJhbmdlKHRoNTApICU+JSANCiAgbXV0YXRlKHByb3ZpbmNlX2VuZyA9IGZhY3Rvcihwcm92aW5jZV9lbmcsIHByb3ZpbmNlX2VuZykpIC0+IGRmX3RodW5oYXANCg0KYGBgDQoNCiMgR2FwcyBpbiBIb3VzZWhvbGQgSW5jb21lDQoNClRodSBuaOG6rXAgaOG7mSBnaWEgxJHDrG5oIChGaWd1cmUgMSkgY8OzIG3huqV5IMSRaeG7g20gY2jDrW5oIHNhdTogDQoNCi0gVuG7m2kgxJDDoCBO4bq1bmcgdGjDrCAyNSUgc+G7kSBo4buZIGPDsyB0aHUgbmjhuq1wIGjDoG5nIG7Eg20gdGjhuqVwIGjGoW4gMjUwIHRyaeG7h3UsIDI1JSBz4buRIGjhu5kgY8OzIHRodSBuaOG6rXAgY2FvIGjGoW4gNzAwIHRyaeG7h3UuIMSQw6J5IGPFqW5nIGzDoCB0w6xuaCBjw7MgdGh1IG5o4bqtcCB0cnVuZyB24buLIChtZWRpYW4pIGjhu5kgZ2lhIMSRw6xuaCBow6BuZyBuxINtIGNhbyBuaOG6pXQgY+G6oyBuxrDhu5tjLiANCi0gxJBp4buHbiBCacOqbiBsw6AgdOG7iW5oIG5naMOobyBuaOG6pXQgbsaw4bubYzogNTAlIHPhu5EgaOG7mSDhu58gdOG7iW5oIG7DoHkgY8OzIHRodSBuaOG6rXAgYsOpIGjGoW4gODAgdHJp4buHdS4gDQoNClIgY29kZXMgY2hvIEZpZ3VyZSAxOiANCg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCiM9PT09PT09PT09PT09PT09PT09PQ0KIyBEYXRhIFZpc3VhbGl6YXRpb24NCiM9PT09PT09PT09PT09PT09PT09PQ0KDQojIExvYWQgc29tZSBSIHBhY2thZ2VzIGZvciBEYXRhIFZpc3VhbGl6YXRpb246IA0KDQpsaWJyYXJ5KGdnZWNvbm9kaXN0KSAjIGluc3RhbGwucGFja2FnZXMoImdnZWNvbm9kaXN0IiwgcmVwb3MgPSAiaHR0cHM6Ly9jaW5jLnJ1ZC5pcyIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHNob3d0ZXh0KQ0KDQojIFNlbGVjdCBVYnVudHUgQ29uZGVuc2VkIGZvbnQ6IA0Kc2hvd3RleHQuYXV0bygpDQpmb250X2FkZF9nb29nbGUobmFtZSA9ICJVYnVudHUgQ29uZGVuc2VkIiwgZmFtaWx5ID0gInVidSIpDQpteV9mb250IDwtICJ1YnUiDQoNCg0KZGZfdGh1bmhhcCAlPiUgDQogIGdncGxvdChhZXMoeCA9IHByb3ZpbmNlX2VuZykpICsgDQogIGdlb21fZWNvbm9kaXN0KGFlcyh5bWluID0gdGgyNSwgbWVkaWFuID0gdGg1MCwgeW1heCA9IHRoNzUpLCANCiAgICAgICAgICAgICAgICAgbWVkaWFuX2NvbCA9ICJmaXJlYnJpY2siLCANCiAgICAgICAgICAgICAgICAgc3RhdCA9ICJpZGVudGl0eSIsIA0KICAgICAgICAgICAgICAgICBtZWRpYW5fcG9pbnRfc2l6ZSA9IDEuMywgDQogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kID0gVFJVRSkgKyANCiAgY29vcmRfZmxpcCgpICsNCiAgdGhlbWVfZWNvbm9kaXN0KCkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMCwgMCksIGxpbWl0cyA9IHJhbmdlKDAsIDgwMCksIGJyZWFrcyA9IHNlcSgwLCA4MDAsIDEwMCksIHBvc2l0aW9uID0gInJpZ2h0IikgKyANCiAgbGFicyh0aXRsZSA9ICJGaWd1cmUgMTogR2FwcyBpbiBIb3VzZWhvbGQgSW5jb21lIChtaWxsaW9ucyBWTkQpIGJ5IFByb3ZpbmNlLCAyMDE4IiwgDQogICAgICAgY2FwdGlvbiA9ICJEYXRhIFNvdXJjZTogVkhMU1MgMjAxOCwgR1NPIikgKyAgDQogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAuMywgMSwgMC4zLCAwLjUpLCAiY20iKSkgKyANCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpKSArIA0KICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSBteV9mb250LCBzaXplID0gOC41KSkgKyANCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gbXlfZm9udCkpICsgDQogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSBteV9mb250LCBzaXplID0gOCwgZmFjZSA9ICJpdGFsaWMiKSkgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSBteV9mb250LCBzaXplID0gMTUpKSAtPiBmMSANCg0KZ3JpZC5uZXdwYWdlKCkNCg0KZjEgJT4lIA0KICBsZWZ0X2FsaWduKGMoInRpdGxlIiwgImNhcHRpb24iKSkgJT4lIA0KICBhZGRfZWNvbm9kaXN0X2xlZ2VuZCgNCiAgICBlY29ub2Rpc3RfbGVnZW5kX2dyb2IoDQogICAgICB0ZW50aF9sYWIgPSAiMjV0aCBQZXJjZW50aWxlIiwgDQogICAgICBuaW5ldGlldGhfbGFiID0gIjc1dGggUGVyY2VudGlsZSIsIA0KICAgICAgbWVkX2xhYiA9ICJNZWRpYW4iLCANCiAgICAgIG1lZF9jb2wgPSAiZmlyZWJyaWNrIiwgDQogICAgICBmYW1pbHkgPSBteV9mb250LCANCiAgICAgIGxhYmVsX3NpemUgPSAxMSwNCiAgICApLCANCiAgICBiZWxvdyA9ICJ0aXRsZSINCiAgKSAlPiUgDQogIGdyaWQuZHJhdygpDQpgYGANCg0KDQoNCiMgUHJvZHVjdGlvbiBDb3N0IC0gSG91c2Vob2xkIEluY29tZSBSZWxhdGlvbnNoaXANCg0KxJDhu4MgxJHDoW5oIGdpw6Eg4bqjbmggaMaw4bufbmcgY+G7p2EgY2hpIHBow60gc+G6o24geHXhuqV0IChQcm9kdWN0aW9uIENvc3QpIGzDqm4gdGh1IG5o4bqtcCBo4buZIGdpYSDEkcOsbmggY8OzIHTDrW5oIMSR4bq/biBz4buxIGtow6FjIGJp4buHdCBnaeG7r2EgY8OhYyB04buJbmgsIHjDqXQgbcO0IGjDrG5oIMSRxqFuIGdp4bqjbiBzYXU6IA0KDQokJEluY29tZV9pID0gXGJldGFfMCArIFxiZXRhXzEgUHJvdmluY2Vfe2l9ICsgXGJldGFfMiBQcm9kdWN0aW9uQ29zdF97aX0gKyB1X2kgXCAsIFwgaT0xLFxkb3RzLG4uJCQNClRyb25nIG3DtCBow6xuaCBuw6B5LCBQcm92aW5jZSDEkcaw4bujYyBjb2kgbMOgIGR1bW15IHZhcmlhYmxlIG3DoCBo4buHIHPhu5EgaOG7k2kgcXV5IGPhu6dhIGNow7puZyBz4bq9IGNobyB0YSBiaeG6v3Qgc+G7sSBraMOhYyBiaeG7h3QgduG7gSDhuqNuaCBoxrDhu59uZyBj4bunYSBjaGkgY2hvIHPhuqNuIHh14bqldCBraW5oIGRvYW5oIGzDqm4gdGh1IG5o4bqtcCBo4buZIGdpYSDEkcOsbmguIEvhur90IHF14bqjIGPhu6dhIG3DtCBow6xuaCBuw6B5IMSRxrDhu6NjIHRyw6xuaCBiw6B5IOG7nyBUYWJsZSA0IGTGsOG7m2kgxJHDonk6DQoNCmBgYHtyfQ0KIyBSZWdyZXNzaW9uOiANCmRmX3RodV9jaGkgJT4lIA0KICBtdXRhdGUoUHJvdmluY2UgPSBwcm92aW5jZV9lbmcsIA0KICAgICAgICAgUHJvZHVjdGlvbkNvc3QgPSB0b3RhbF9jaGlfU1hLRCAvIDEwMDAsIA0KICAgICAgICAgSW5jb21lID0gdG90YWxfdGh1bmhhcCAvIDEwMDApICU+JSAjIFJlbmFtZSBmb3IgY29udmluaWVuY2UuIA0KICBsbShJbmNvbWUgfiBQcm92aW5jZSArIFByb2R1Y3Rpb25Db3N0LCBkYXRhID0gLikgLT4gcmVnDQoNCmBgYA0KDQpgYGB7cn0NCiMgRXh0cmFjdCBjb2VmZmljaWVudHM6IA0KYnJvb206OnRpZHkocmVnKSAlPiUgDQogIG11dGF0ZShWYXJpYWJsZSA9IHN0cl9yZXBsYWNlX2FsbCh0ZXJtLCAiUHJvdmluY2UiLCAiIikpIC0+IGRmX2NvZWZmDQoNCiMgU2hvdyBtYWluIHJlZ3Jlc3Npb24gcmVzdWx0cyAoVGFibGUgMyk6IA0KZGZfY29lZmYgJT4lIA0KICBtdXRhdGUoRXN0aW1hdGUgPSByb3VuZChlc3RpbWF0ZSwgMSksIFN0ZC5lcnJvciA9IHJvdW5kKHN0ZC5lcnJvciwgMyksIFAudmFsdWUgPSByb3VuZChwLnZhbHVlLCAzKSkgJT4lIA0KICBzZWxlY3QoVmFyaWFibGUsIEVzdGltYXRlLCBTdGQuZXJyb3IsIFAudmFsdWUpIC0+IGRmX2NvZWZmDQoNCmRmX2NvZWZmICU+JSANCiAgZmlsdGVyKFZhcmlhYmxlICVpbiUgYygiKEludGVyY2VwdCkiLCAiUHJvZHVjdGlvbkNvc3QiKSkgJT4lIA0KICBiaW5kX3Jvd3MoZGZfY29lZmYgJT4lIA0KICAgICAgICAgICAgICBmaWx0ZXIoIVZhcmlhYmxlICVpbiUgYygiKEludGVyY2VwdCkiLCAiUHJvZHVjdGlvbkNvc3QiKSkgJT4lIA0KICAgICAgICAgICAgICBhcnJhbmdlKC1Fc3RpbWF0ZSkpICU+JSANCiAga2JsKGNhcHRpb24gPSAiVGFibGUgMzogSW5jb21lLVByb2R1Y3Rpb24gQ29zdCBSZWxhdGlvbnNoaXAsIFItc3F1YXJlZCA9IDg2LjkyJSIsIGVzY2FwZSA9IFRSVUUpICU+JQ0KICBrYWJsZV9jbGFzc2ljKGZ1bGxfd2lkdGggPSBUUlVFLCBodG1sX2ZvbnQgPSAiQ2FtYnJpYSIpDQpgYGANCg0KTeG7mXQgc+G7kSBr4bq/dCBxdeG6oyBjaMOtbmggdOG7qyBUYWJsZSA0OiANCg0KLSBDaGkgMSB0cmnhu4d1IGNobyBTWEtEIHRow6wgdHJ1bmcgYsOsbmggdGh1IG5o4bqtcCBo4buZIGdpYSDEkcOsbmggdMSDbmcgMS4xIHRyaeG7h3UgKGNldGVyaXMgcGFyaWJ1cykuIA0KLSDEkMOgIE7hurVuZywgVHAgSOG7kyBDaMOtIE1pbmgsIEjDoCBO4buZaSwgQuG6r2MgTmluaCwgQsOsbmggRMawxqFuZyBsw6Agbmjhu69uZyB04buJbmggdOG7kXQgY2hvIGhv4bqhdCDEkeG7mW5nIMSR4bqndSB0xrAgc+G6o24geHXhuqV0IGtpbmggZG9hbmguIMSQ4bupbmcgY3Xhu5FpIGLhuqNuZyBsw6AgQ2FvIELhurFuZywgQuG6r2MgS+G6oW4sIERhayBOw7RuZywgTGFpIENow6J1IHbDoCBTxqFuIExhLiANCg0KIyBGaW5hbCBOb3Rlcw0KDQpN4buZdCBz4buRIGvhur90IHF14bqjIHThu6sgYuG7mSBk4buvIGxp4buHdSBuw6B5IGPDsyB0aOG7gyB04bqhbyBuw6puIHPhu7EgdHJhbmggY8OjaSB2w6AgYuG7kWkgcuG7kWkuIELhuqV0IGPhu6kgcGjhuqNuIGjhu5NpIG7DoG8gxJHhu4F1IGjhu6l1IMOtY2ggdsOgIMSRxrDhu6NjIGNow6BvIMSRw7NuLiBC4bqhbiDEkeG7jWMgY8OzIHRo4buDIGxpw6puIGjhu4cgduG7m2kgxJHhu4thIGNo4buJIGVtYWlsIOG7nyB0csOqbiDEkeG7gyBs4bqleSBk4buvIGxp4buHdSB24buBIGtp4buDbSB0cmEgLSBzbyBzw6FuaC4gDQo=