Introduction

Bộ số liệu VHLSS (Household Living Standards Survey) được GSO - cơ quan thống kê quốc gia của Việt Nam tiến hành khảo sát cứ mỗi hai năm một lần. Gần đây nhất là năm 2018 gồm 44 files dữ liệu (đuôi là .dta của phần mềm Stata, tham khảo thêm thông tin về VHLSS 2018 tại đây). Mỗi một file dữ liệu là thông tin khảo sát ở cấp độ hộ gia đình hoặc cá nhân về các khía cạnh khác nhau của đời sống như Giáo Dục, Y Tế, Thu Nhập, Đầu Tư - Chi Tiêu. Post này sẽ hướng dẫn chi tiết cách thức xử lí bộ số liệu về Đầu Tư, Chi Tiêu và Thu Nhập của hộ gia đình được lưu trong file có tên HO3.dta gồm 366712 quan sát, 10 biến số. Tại thời điểm viết bài này, do không thể public bộ dữ liệu, bạn đọc quan tâm đến bộ số liệu này có thể email đến địa chỉ .

R codes xử lí bộ số liệu này có thể được áp dụng để xử lí các bộ dữ liệu khác hoặc các bộ VHLSS của những năm trước đó.

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
  1. Thu nhap
thubq
  1. 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.

Final Notes

Một số kết quả từ bộ dữ liệu này có thể tạo nên sự tranh cãi và bối rối. Bất cứ phản hồi nào đều hứu ích và được chào đón. Bạn đọc có thể liên hệ với địa chỉ email ở trên để lấy dữ liệu về kiểm tra - so sánh.

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=