Introduction

Panel Data là form dữ liệu thường được sử dụng trong nhiều phân tích và nghiên cứu. Tuy vậy, việc xử lí - chuẩn bị (Data Pre-processing) dữ liệu cho các mô hình phân tích sử dụng Panel Data có thể gây bối rối và lúng túng. Post này hướng dẫn việc khai thác, chuẩn bị Panel Data từ các 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.

Giả sử chúng ta sử dụng bộ số liệu HO2.dta từ hai năm VHLSS 2016 và VHLSS 2014 với kí hiệu Y = m4dtn, X = m4atn cho mô hình nghiên cứu đề xuất sau:

\[\begin{equation} Y_{it}=\beta_{1}+\beta_{2}X_{it}+e_{it} \label{eq:panelgeneq15} \end{equation}\]

Trước hết đọc HO2.dta:

# Clear R environment: 
rm(list = ls())

# Load some R packages: 
library(dplyr)
library(stringr)
library(stringi)
library(kableExtra) # For presenting table. 
library(haven)

# Ho2.dta, 2014-2016: 

read_dta("F:/VHLSS2016/HO2.dta") -> ho2_2016
read_dta("F:/VHLSS2014_Households/Ho2.dta") -> ho2_2014

Rồi viết hàm add_zero() để thêm vào các zeros như đã phân tích chi tiết ở post trước:

#========================
#  Data Pre-processing 
#========================

# 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, na.rm = TRUE), 
           delta = n_max - n_digits, 
           pre = strrep("0", times = delta), 
           full_code = str_c(pre, x_text)) %>% 
    pull(full_code) %>% 
    return()
}

Rồi sử dụng hàm đã viết để tạo ra mã định danh cho hộ gia đình:

# Create household codes: 

ho2_2016 %>% 
  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)) %>% 
  mutate(year = 2016) -> ho2_2016


ho2_2014 %>% 
  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)) %>% 
  mutate(year = 2014) -> ho2_2014

Prepare Panel Data

Ở cấp độ hộ gia đình thì GSO chọn mẫu khảo sát kiểu như sau: năm 2014 nếu chọn 1000 hộ gia đình khảo sát thì kì khảo sát kết tiếp, tức là vào năm 2016 sẽ chỉ giữ lại 50% số hộ đã khảo sát ở năm 2014 để tiếp tục khảo sát. Số thiếu còn lại là các hộ gia đình mới. Còn vào kì khảo sát 2018 thì số hộ gia đình đã được khảo sát ở các năm 2014, 2016 chỉ còn lại 50%. Số mới lại được bổ sung. Quy luật này được áp dụng như vậy cho tất cả các năm.

Tất nhiên con số 50% chỉ là tương đối và có thể sai lệch chút ít.

Để biết một hộ cụ thể ở năm 2016 có được khảo sát ở năm 2014 hay chưa thì phải căn cứ vào cột biến tinh_14 của bộ dữ liệu HO1.dta của năm 2016. Trước hết đọc bộ dữ liệu này và tạo ra cột biến h_code với hàm ý đây là mã hộ gia đình vào năm 2014 của hộ:

# HO1.dta, 2016: 
read_dta("F:/VHLSS2016/HO1.dta") -> ho1_2016


ho1_2016 %>% 
  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)) %>% 
  mutate(h_code14 = str_c(add_zero(tinh14), 
                          add_zero(huyen14), 
                          add_zero(xa14), 
                          add_zero(diaban14), 
                          add_zero(hoso14))) -> ho1_2016

Chúng ta xem một số quan sát ở Table 1:

ho1_2016 %>% 
  select(tinh, tinh14, h_code, h_code14) %>% 
  head() %>% 
  kbl(caption = "Table 1: Some Observations from HO1.dta, 2016", escape = TRUE) %>%
  kable_classic(full_width = FALSE, html_font = "Cambria")
Table 1: Some Observations from HO1.dta, 2016
tinh tinh14 h_code h_code14
1 1 010010000400814 010010000400814
1 1 010010000400815 010010000400815
1 0 010010000400819 NA
1 1 010010000700613 010010000700613
1 1 010010000700614 010010000700614
1 0 010010000700620 NA

Ở đây cột tinh14 có giá trị bằng 0 có nghĩa là quan sát này không được khảo sát ở năm 2014. Như vậy dòng 1 chỉ ra rằng hộ có h_code = 010010000400814 được khảo sát trong cả hai năm liên tiếp. Trong khi đó hộ có n_code = 010010000400819 thì không được khảo sát ở năm 2014. Như vậy muốn có Panel Data cho hai năm 2014 và 2016 thì ta chỉ chọn những quan sát mà xuất hiện ở cả hai năm, tức là phải thỏa mãn h_code == h_code14. Chúng ta xem xét một số quan sát vi phạm điều kiện này ở Table 2:

ho1_2016 %>% 
  filter(h_code != h_code14) %>% 
  select(tinh, tinh14, h_code, h_code14) %>% 
  head() %>% 
  kbl(caption = "Table 2: Some Observations from HO1.dta, 2016", escape = TRUE) %>%
  kable_classic(full_width = FALSE, html_font = "Cambria")
Table 2: Some Observations from HO1.dta, 2016
tinh tinh14 h_code h_code14
1 1 010010003401013 010010003401019
1 1 010010003401015 010010003401020
1 1 010020007901013 010020007901020
1 1 010030011201714 010030011201720
1 1 010060019006014 010060019006019
1 1 010060019901615 010060019901619

Theo logic này chúng ta chọn ra những hộ gia đình mà, theo lí thuyết, sẽ được khảo sát đồng thời cả ở hai năm 2014 và 2016:

# Common household codes: 
ho1_2016 %>% 
  filter(h_code == h_code14) %>% 
  pull(h_code) -> common_hcode

Đến đây có thể tạo ra Panel Data như sau:

# Select some columns: 
some_columns <- c("h_code", "m4atn", "m4dtn", "year")

ho2_2016 %>% 
  filter(h_code %in% common_hcode) %>% 
  select(some_columns) -> ho2_2016_mini

ho2_2014 %>% 
  filter(h_code %in% common_hcode) %>% 
  select(some_columns) -> ho2_2014_mini

#--------------------------
#  Unbalanced Panel Data
#--------------------------

# Join the two datasets: 

bind_rows(ho2_2016_mini, ho2_2014_mini) -> unbalanced_panel_data

Mặc dù chúng ta kì vọng rằng những hộ gia đình nào đã được khảo sát năm 2016 thì cũng sẽ có thông tin ở năm 2014 nhưng sự thực thì không phải vậy: năm 2016 có 3878 hộ trong khi năm 2014 có 3874 hộ. Trước hết chúng ta có thể chỉ ra 4 hộ không có mặt ở năm 2014 như sau:

# Observations not belong to 2014: 

unbalanced_panel_data %>% 
  group_by(h_code) %>% 
  count() %>% 
  filter(n == 1) %>% 
  pull(h_code) -> some_cases

some_cases
## [1] "012680954700416" "012781017401113" "383991600000913" "384041627900112"

Như thế có nghĩa là, Panel Data mà chúng ta thu được ở trên là loại không cân bằng (Unbalanced). Đến đây chúng ta có thể “chỉ thị” cho R làm việc với Panel Data bằng sử dụng hàm pdata.frame() của thư viện plm:

# Prepare panel data: 

library(plm)

pdata.frame(unbalanced_panel_data, 
            index = c("h_code","year"), 
            row.names = FALSE, 
            drop.index = FALSE) -> plm_data_unbalanced

# Some observations: 
head(plm_data_unbalanced) %>% 
  kbl(caption = "Table 2: Some Observations from Unbalanced Panel Data", escape = TRUE) %>%
  kable_classic(full_width = TRUE, html_font = "Cambria")
Table 2: Some Observations from Unbalanced Panel Data
h_code m4atn m4dtn year
010010000400814 47280 20050 2014
010010000400814 42000 60000 2016
010010000400815 297600 295000 2014
010010000400815 415600 155000 2016
010010000700613 247500 5000 2014
010010000700613 232000 32000 2016

Panel Data Analysis

Với dữ liệu đã có, chúng ta có thể chạy các mô hình phân tích cho Panel Data. Chẳng hạn ba cách tiếp cận được chọn là Pooled, Fixed Effects và Random Effects sử dụng ước lượng Amemiya:

#========================
# Some Panel Data Models
#========================

# Pooled Model: 
panel_pooled <- plm(m4dtn ~ m4atn, 
                    data = plm_data_unbalanced, 
                    model = "pooling") 

# Fixed Effects Model: 
panel_fe <- plm(m4dtn ~ m4atn, 
                data = plm_data_unbalanced, 
                model = "within")  

# Random Effects Models using Amemiya estimators (1971): 
panel_re <- plm(m4dtn ~ m4atn, 
                data = plm_data_unbalanced, 
                model = "random", 
                random.method = "amemiya")

Rồi so sánh kết quả của ba cách tiếp cận này:

# Compare results: 

library(stargazer)

stargazer(panel_pooled, 
          panel_fe, 
          panel_re, 
          title = "Table 3: Compare Panel Data Regression Results",
          column.labels = c("Pooled","Fixed Effects", "Random Effects"), 
          type = "text", 
          align = TRUE)
## 
## Table 3: Compare Panel Data Regression Results
## ==========================================================================
##                                   Dependent variable:                     
##              -------------------------------------------------------------
##                                          m4dtn                            
##                       Pooled              Fixed Effects     Random Effects
##                        (1)                     (2)               (3)      
## --------------------------------------------------------------------------
## m4atn                0.042***                -0.025*           0.031***   
##                      (0.006)                 (0.013)           (0.006)    
##                                                                           
## Constant          10,430.220***                             10,997.740*** 
##                     (507.339)                                 (604.861)   
##                                                                           
## --------------------------------------------------------------------------
## Observations          7,752                   7,752             7,752     
## R2                    0.007                   0.001             0.003     
## Adjusted R2           0.007                  -0.999             0.003     
## F Statistic  56.086*** (df = 1; 7750) 3.647* (df = 1; 3873)   24.561***   
## ==========================================================================
## Note:                                          *p<0.1; **p<0.05; ***p<0.01

Nếu muốn chúng ta có thể chạy lại ba mô hình trên với Balanced Panel Data dưới đây:

plm_data_unbalanced %>% 
  filter(!h_code %in% some_cases) -> plm_data_balanced

Final Notes

Post này không trình bày mọi khía cạnh của khai thác - chuẩn bị dữ liệu từ các VHLSS. Để đơn giản, post này chỉ sử dụng dữ liệu của hai năm liên tiếp. Tuy nhiên những logic trình bày trong post này có thể áp dụng để tạo ra Panel Data cho khoảng thời gian dài hơn.

Việc chuẩn bị Panel Data được trình bày trong Post này cũng có thể áp dụng cho các bộ dữ liệu khác như bộ dữ liệu khảo sát doanh nghiệp vừa và nhỏ SME - Small and Medium Enterprise Survey. Với trường hợp của SME thì việc này là đơn giản hơn vì chúng ta chỉ cần sử dụng “Mã số thuế” của doanh nghiệp thay vì tạo cột biến h_code.

LS0tDQp0aXRsZTogJ1ByZXBhcmUgUGFuZWwgRGF0YSBmb3IgRWNvbm9tZXRyaWMgQW5hbHlzaXMgZnJvbSBWSExTUycNCmF1dGhvcjogJ0F1dGhvcjogTmd1eWVuIENoaSBEdW5nJw0Kc3VidGl0bGU6ICJSIEVjb25vbWV0cmljcyBTZXJpZXMiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICAjIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGhpZ2hsaWdodDogemVuYnVybg0KICAgICMgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0aGVtZTogImZsYXRseSINCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCi0tLQ0KDQpgYGB7ciBzZXR1cCxpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgY2FjaGUgPSBUUlVFKQ0KDQpgYGANCg0KIVtdKEM6L1VzZXJzL0FETUlOL0RvY3VtZW50cy9wYW5lbC5wbmcpDQoNCiMgSW50cm9kdWN0aW9uIA0KDQpbUGFuZWwgRGF0YV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGFuZWxfZGF0YSkgbMOgIGZvcm0gZOG7ryBsaeG7h3UgdGjGsOG7nW5nIMSRxrDhu6NjIHPhu60gZOG7pW5nIHRyb25nIG5oaeG7gXUgcGjDom4gdMOtY2ggdsOgIG5naGnDqm4gY+G7qXUuIFR1eSB24bqteSwgdmnhu4djIHjhu60gbMOtIC0gY2h14bqpbiBi4buLIChEYXRhIFByZS1wcm9jZXNzaW5nKSBk4buvIGxp4buHdSBjaG8gY8OhYyBtw7QgaMOsbmggcGjDom4gdMOtY2ggc+G7rSBk4bulbmcgUGFuZWwgRGF0YSBjw7MgdGjhu4MgZ8OieSBi4buRaSBy4buRaSB2w6AgbMO6bmcgdMO6bmcuIFBvc3QgbsOgeSBoxrDhu5tuZyBk4bqrbiB2aeG7h2Mga2hhaSB0aMOhYywgY2h14bqpbiBi4buLIFBhbmVsIERhdGEgdOG7qyBjw6FjIGLhu5kgc+G7kSBsaeG7h3UgVkhMU1MgKFtIb3VzZWhvbGQgTGl2aW5nIFN0YW5kYXJkcyBTdXJ2ZXldKGh0dHA6Ly9pcmVzZWFyY2gud29ybGRiYW5rLm9yZy9Qb3ZjYWxOZXQvRG9jcy9Db3VudHJ5RG9jcy9WTk0uaHRtKSkgxJHGsOG7o2MgR1NPIC0gY8ahIHF1YW4gdGjhu5FuZyBrw6ogcXXhu5FjIGdpYSBj4bunYSBWaeG7h3QgTmFtIHRp4bq/biBow6BuaCBraOG6o28gc8OhdCBj4bupIG3hu5dpIGhhaSBuxINtIG3hu5l0IGzhuqduLiANCg0KR2nhuqMgc+G7rSBjaMO6bmcgdGEgc+G7rSBk4bulbmcgYuG7mSBz4buRIGxp4buHdSAqKkhPMi5kdGEqKiB04burIGhhaSBuxINtIFZITFNTIDIwMTYgdsOgIFZITFNTIDIwMTQgduG7m2kga8OtIGhp4buHdSBZID0gbTRkdG4sIFggPSBtNGF0biBjaG8gbcO0IGjDrG5oIG5naGnDqm4gY+G7qXUgxJHhu4EgeHXhuqV0IHNhdTogDQoNCiQkXGJlZ2lue2VxdWF0aW9ufSBZX3tpdH09XGJldGFfezF9K1xiZXRhX3syfVhfe2l0fStlX3tpdH0gXGxhYmVse2VxOnBhbmVsZ2VuZXExNX0gXGVuZHtlcXVhdGlvbn0kJA0KDQpUcsaw4bubYyBo4bq/dCDEkeG7jWMgKkhPMi5kdGEqOiANCg0KDQpgYGB7cn0NCiMgQ2xlYXIgUiBlbnZpcm9ubWVudDogDQpybShsaXN0ID0gbHMoKSkNCg0KIyBMb2FkIHNvbWUgUiBwYWNrYWdlczogDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeShzdHJpbmdpKQ0KbGlicmFyeShrYWJsZUV4dHJhKSAjIEZvciBwcmVzZW50aW5nIHRhYmxlLiANCmxpYnJhcnkoaGF2ZW4pDQoNCiMgSG8yLmR0YSwgMjAxNC0yMDE2OiANCg0KcmVhZF9kdGEoIkY6L1ZITFNTMjAxNi9ITzIuZHRhIikgLT4gaG8yXzIwMTYNCnJlYWRfZHRhKCJGOi9WSExTUzIwMTRfSG91c2Vob2xkcy9IbzIuZHRhIikgLT4gaG8yXzIwMTQNCmBgYA0KDQpS4buTaSB2aeG6v3QgaMOgbSAqKmFkZF96ZXJvKCkqKiDEkeG7gyB0aMOqbSB2w6BvIGPDoWMgemVyb3MgbmjGsCDEkcOjIHBow6JuIHTDrWNoIGNoaSB0aeG6v3Qg4bufIFtwb3N0IHRyxrDhu5tjXShodHRwczovL3JwdWJzLmNvbS9jaGlkdW5na3QvNzg4MTMxKTogDQoNCmBgYHtyfQ0KIz09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAgRGF0YSBQcmUtcHJvY2Vzc2luZyANCiM9PT09PT09PT09PT09PT09PT09PT09PT0NCg0KIyBGdW5jdGlvbiBjcmVhdGVzIGZ1bGwgY29kZSBieSBhZGRpbmcgemVyb3M6IA0KDQphZGRfemVybyA8LSBmdW5jdGlvbih4KSB7DQogIA0KICB0aWJibGUoeF90ZXh0ID0gYXMuY2hhcmFjdGVyKHgpKSAlPiUgDQogICAgbXV0YXRlKG5fZGlnaXRzID0gc3RyX2NvdW50KHhfdGV4dCksDQogICAgICAgICAgIG5fbWF4ID0gbWF4KG5fZGlnaXRzLCBuYS5ybSA9IFRSVUUpLCANCiAgICAgICAgICAgZGVsdGEgPSBuX21heCAtIG5fZGlnaXRzLCANCiAgICAgICAgICAgcHJlID0gc3RycmVwKCIwIiwgdGltZXMgPSBkZWx0YSksIA0KICAgICAgICAgICBmdWxsX2NvZGUgPSBzdHJfYyhwcmUsIHhfdGV4dCkpICU+JSANCiAgICBwdWxsKGZ1bGxfY29kZSkgJT4lIA0KICAgIHJldHVybigpDQp9DQpgYGANCg0KUuG7k2kgc+G7rSBk4bulbmcgaMOgbSDEkcOjIHZp4bq/dCDEkeG7gyB04bqhbyByYSBtw6MgxJHhu4tuaCBkYW5oIGNobyBo4buZIGdpYSDEkcOsbmg6IA0KDQpgYGB7cn0NCiMgQ3JlYXRlIGhvdXNlaG9sZCBjb2RlczogDQoNCmhvMl8yMDE2ICU+JSANCiAgbXV0YXRlKHRpbmhfbiA9IGFkZF96ZXJvKHRpbmgpLCANCiAgICAgICAgIGh1eWVuX24gPSBhZGRfemVybyhodXllbiksIA0KICAgICAgICAgeGFfbiA9IGFkZF96ZXJvKHhhKSwgDQogICAgICAgICBkaWFiYW5fbiA9IGFkZF96ZXJvKGRpYWJhbiksIA0KICAgICAgICAgaG9zb19uID0gYWRkX3plcm8oaG9zbykpICU+JSANCiAgbXV0YXRlKGhfY29kZSA9IHN0cl9jKHRpbmhfbiwgaHV5ZW5fbiwgeGFfbiwgZGlhYmFuX24sIGhvc29fbikpICU+JSANCiAgbXV0YXRlKHllYXIgPSAyMDE2KSAtPiBobzJfMjAxNg0KDQoNCmhvMl8yMDE0ICU+JSANCiAgbXV0YXRlKHRpbmhfbiA9IGFkZF96ZXJvKHRpbmgpLCANCiAgICAgICAgIGh1eWVuX24gPSBhZGRfemVybyhodXllbiksIA0KICAgICAgICAgeGFfbiA9IGFkZF96ZXJvKHhhKSwgDQogICAgICAgICBkaWFiYW5fbiA9IGFkZF96ZXJvKGRpYWJhbiksIA0KICAgICAgICAgaG9zb19uID0gYWRkX3plcm8oaG9zbykpICU+JSANCiAgbXV0YXRlKGhfY29kZSA9IHN0cl9jKHRpbmhfbiwgaHV5ZW5fbiwgeGFfbiwgZGlhYmFuX24sIGhvc29fbikpICU+JSANCiAgbXV0YXRlKHllYXIgPSAyMDE0KSAtPiBobzJfMjAxNA0KYGBgDQoNCiMgUHJlcGFyZSBQYW5lbCBEYXRhDQoNCuG7niBj4bqlcCDEkeG7mSBo4buZIGdpYSDEkcOsbmggdGjDrCBHU08gY2jhu41uIG3huqt1IGto4bqjbyBzw6F0IGtp4buDdSBuaMawIHNhdTogbsSDbSAyMDE0IG7hur91IGNo4buNbiAxMDAwIGjhu5kgZ2lhIMSRw6xuaCBraOG6o28gc8OhdCB0aMOsIGvDrCBraOG6o28gc8OhdCBr4bq/dCB0aeG6v3AsIHThu6ljIGzDoCB2w6BvIG7Eg20gMjAxNiBz4bq9IGNo4buJIGdp4buvIGzhuqFpIDUwJSBz4buRIGjhu5kgxJHDoyBraOG6o28gc8OhdCDhu58gbsSDbSAyMDE0IMSR4buDIHRp4bq/cCB04bulYyBraOG6o28gc8OhdC4gU+G7kSB0aGnhur91IGPDsm4gbOG6oWkgbMOgIGPDoWMgaOG7mSBnaWEgxJHDrG5oIG3hu5tpLiBDw7JuIHbDoG8ga8OsIGto4bqjbyBzw6F0IDIwMTggdGjDrCBz4buRIGjhu5kgZ2lhIMSRw6xuaCDEkcOjIMSRxrDhu6NjIGto4bqjbyBzw6F0IOG7nyBjw6FjIG7Eg20gMjAxNCwgMjAxNiBjaOG7iSBjw7JuIGzhuqFpIDUwJS4gU+G7kSBt4bubaSBs4bqhaSDEkcaw4bujYyBi4buVIHN1bmcuIFF1eSBsdeG6rXQgbsOgeSDEkcaw4bujYyDDoXAgZOG7pW5nIG5oxrAgduG6rXkgY2hvIHThuqV0IGPhuqMgY8OhYyBuxINtLiANCg0KVOG6pXQgbmhpw6puIGNvbiBz4buRIDUwJSBjaOG7iSBsw6AgdMawxqFuZyDEkeG7kWkgdsOgIGPDsyB0aOG7gyBzYWkgbOG7h2NoIGNow7p0IMOtdC4gDQoNCsSQ4buDIGJp4bq/dCBt4buZdCBo4buZIGPhu6UgdGjhu4Mg4bufIG7Eg20gMjAxNiBjw7MgxJHGsOG7o2Mga2jhuqNvIHPDoXQg4bufIG7Eg20gMjAxNCBoYXkgY2jGsGEgdGjDrCBwaOG6o2kgY8SDbiBj4bupIHbDoG8gY+G7mXQgYmnhur9uICp0aW5oXzE0KiBj4bunYSBi4buZIGThu68gbGnhu4d1ICoqSE8xLmR0YSoqIGPhu6dhIG7Eg20gMjAxNi4gVHLGsOG7m2MgaOG6v3QgxJHhu41jIGLhu5kgZOG7ryBsaeG7h3UgbsOgeSB2w6AgdOG6oW8gcmEgY+G7mXQgYmnhur9uICpoX2NvZGUqIHbhu5tpIGjDoG0gw70gxJHDonkgbMOgIG3DoyBo4buZIGdpYSDEkcOsbmggdsOgbyBuxINtIDIwMTQgY+G7p2EgaOG7mTogDQoNCg0KYGBge3J9DQojIEhPMS5kdGEsIDIwMTY6IA0KcmVhZF9kdGEoIkY6L1ZITFNTMjAxNi9ITzEuZHRhIikgLT4gaG8xXzIwMTYNCg0KDQpobzFfMjAxNiAlPiUgDQogIG11dGF0ZSh0aW5oX24gPSBhZGRfemVybyh0aW5oKSwgDQogICAgICAgICBodXllbl9uID0gYWRkX3plcm8oaHV5ZW4pLCANCiAgICAgICAgIHhhX24gPSBhZGRfemVybyh4YSksIA0KICAgICAgICAgZGlhYmFuX24gPSBhZGRfemVybyhkaWFiYW4pLCANCiAgICAgICAgIGhvc29fbiA9IGFkZF96ZXJvKGhvc28pKSAlPiUgDQogIG11dGF0ZShoX2NvZGUgPSBzdHJfYyh0aW5oX24sDQogICAgICAgICAgICAgICAgICAgICAgICBodXllbl9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgeGFfbiwgDQogICAgICAgICAgICAgICAgICAgICAgICBkaWFiYW5fbiwNCiAgICAgICAgICAgICAgICAgICAgICAgIGhvc29fbikpICU+JSANCiAgbXV0YXRlKGhfY29kZTE0ID0gc3RyX2MoYWRkX3plcm8odGluaDE0KSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGFkZF96ZXJvKGh1eWVuMTQpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkX3plcm8oeGExNCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRfemVybyhkaWFiYW4xNCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRfemVybyhob3NvMTQpKSkgLT4gaG8xXzIwMTYNCmBgYA0KDQpDaMO6bmcgdGEgeGVtIG3hu5l0IHPhu5EgcXVhbiBzw6F0IOG7nyBUYWJsZSAxOiANCg0KDQpgYGB7cn0NCmhvMV8yMDE2ICU+JSANCiAgc2VsZWN0KHRpbmgsIHRpbmgxNCwgaF9jb2RlLCBoX2NvZGUxNCkgJT4lIA0KICBoZWFkKCkgJT4lIA0KICBrYmwoY2FwdGlvbiA9ICJUYWJsZSAxOiBTb21lIE9ic2VydmF0aW9ucyBmcm9tIEhPMS5kdGEsIDIwMTYiLCBlc2NhcGUgPSBUUlVFKSAlPiUNCiAga2FibGVfY2xhc3NpYyhmdWxsX3dpZHRoID0gRkFMU0UsIGh0bWxfZm9udCA9ICJDYW1icmlhIikNCmBgYA0KDQrhu54gxJHDonkgY+G7mXQgKip0aW5oMTQqKiBjw7MgZ2nDoSB0cuG7iyBi4bqxbmcgMCBjw7MgbmdoxKlhIGzDoCBxdWFuIHPDoXQgbsOgeSBraMO0bmcgxJHGsOG7o2Mga2jhuqNvIHPDoXQg4bufIG7Eg20gMjAxNC4gTmjGsCB24bqteSBkw7JuZyAxIGNo4buJIHJhIHLhurFuZyBo4buZIGPDsyBoX2NvZGUgPSAwMTAwMTAwMDA0MDA4MTQgxJHGsOG7o2Mga2jhuqNvIHPDoXQgdHJvbmcgY+G6oyBoYWkgbsSDbSBsacOqbiB0aeG6v3AuIFRyb25nIGtoaSDEkcOzIGjhu5kgY8OzIG5fY29kZSA9IDAxMDAxMDAwMDQwMDgxOSB0aMOsIGtow7RuZyDEkcaw4bujYyBraOG6o28gc8OhdCDhu58gbsSDbSAyMDE0LiBOaMawIHbhuq15IG114buRbiBjw7MgUGFuZWwgRGF0YSBjaG8gaGFpIG7Eg20gMjAxNCB2w6AgMjAxNiB0aMOsIHRhIGNo4buJIGNo4buNbiBuaOG7r25nIHF1YW4gc8OhdCBtw6AgeHXhuqV0IGhp4buHbiDhu58gY+G6oyBoYWkgbsSDbSwgdOG7qWMgbMOgIHBo4bqjaSB0aOG7j2EgbcOjbiBoX2NvZGUgPT0gaF9jb2RlMTQuIENow7puZyB0YSB4ZW0geMOpdCBt4buZdCBz4buRIHF1YW4gc8OhdCB2aSBwaOG6oW0gxJFp4buBdSBraeG7h24gbsOgeSDhu58gVGFibGUgMjogDQoNCg0KYGBge3J9DQpobzFfMjAxNiAlPiUgDQogIGZpbHRlcihoX2NvZGUgIT0gaF9jb2RlMTQpICU+JSANCiAgc2VsZWN0KHRpbmgsIHRpbmgxNCwgaF9jb2RlLCBoX2NvZGUxNCkgJT4lIA0KICBoZWFkKCkgJT4lIA0KICBrYmwoY2FwdGlvbiA9ICJUYWJsZSAyOiBTb21lIE9ic2VydmF0aW9ucyBmcm9tIEhPMS5kdGEsIDIwMTYiLCBlc2NhcGUgPSBUUlVFKSAlPiUNCiAga2FibGVfY2xhc3NpYyhmdWxsX3dpZHRoID0gRkFMU0UsIGh0bWxfZm9udCA9ICJDYW1icmlhIikNCmBgYA0KDQpUaGVvIGxvZ2ljIG7DoHkgY2jDum5nIHRhIGNo4buNbiByYSBuaOG7r25nIGjhu5kgZ2lhIMSRw6xuaCBtw6AsIHRoZW8gbMOtIHRodXnhur90LCBz4bq9IMSRxrDhu6NjIGto4bqjbyBzw6F0IMSR4buTbmcgdGjhu51pIGPhuqMg4bufIGhhaSBuxINtIDIwMTQgdsOgIDIwMTY6IA0KDQpgYGB7cn0NCiMgQ29tbW9uIGhvdXNlaG9sZCBjb2RlczogDQpobzFfMjAxNiAlPiUgDQogIGZpbHRlcihoX2NvZGUgPT0gaF9jb2RlMTQpICU+JSANCiAgcHVsbChoX2NvZGUpIC0+IGNvbW1vbl9oY29kZQ0KYGBgDQoNCsSQ4bq/biDEkcOieSBjw7MgdGjhu4MgdOG6oW8gcmEgUGFuZWwgRGF0YSBuaMawIHNhdTogDQoNCmBgYHtyfQ0KIyBTZWxlY3Qgc29tZSBjb2x1bW5zOiANCnNvbWVfY29sdW1ucyA8LSBjKCJoX2NvZGUiLCAibTRhdG4iLCAibTRkdG4iLCAieWVhciIpDQoNCmhvMl8yMDE2ICU+JSANCiAgZmlsdGVyKGhfY29kZSAlaW4lIGNvbW1vbl9oY29kZSkgJT4lIA0KICBzZWxlY3Qoc29tZV9jb2x1bW5zKSAtPiBobzJfMjAxNl9taW5pDQoNCmhvMl8yMDE0ICU+JSANCiAgZmlsdGVyKGhfY29kZSAlaW4lIGNvbW1vbl9oY29kZSkgJT4lIA0KICBzZWxlY3Qoc29tZV9jb2x1bW5zKSAtPiBobzJfMjAxNF9taW5pDQoNCiMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyAgVW5iYWxhbmNlZCBQYW5lbCBEYXRhDQojLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyBKb2luIHRoZSB0d28gZGF0YXNldHM6IA0KDQpiaW5kX3Jvd3MoaG8yXzIwMTZfbWluaSwgaG8yXzIwMTRfbWluaSkgLT4gdW5iYWxhbmNlZF9wYW5lbF9kYXRhDQpgYGANCg0KTeG6t2MgZMO5IGNow7puZyB0YSBrw6wgduG7jW5nIHLhurFuZyBuaOG7r25nIGjhu5kgZ2lhIMSRw6xuaCBuw6BvIMSRw6MgxJHGsOG7o2Mga2jhuqNvIHPDoXQgbsSDbSAyMDE2IHRow6wgY8Wpbmcgc+G6vSBjw7MgdGjDtG5nIHRpbiDhu58gbsSDbSAyMDE0IG5oxrBuZyBz4buxIHRo4buxYyB0aMOsIGtow7RuZyBwaOG6o2kgduG6rXk6IG7Eg20gMjAxNiBjw7MgMzg3OCBo4buZIHRyb25nIGtoaSBuxINtIDIwMTQgY8OzIDM4NzQgaOG7mS4gVHLGsOG7m2MgaOG6v3QgY2jDum5nIHRhIGPDsyB0aOG7gyBjaOG7iSByYSA0IGjhu5kga2jDtG5nIGPDsyBt4bq3dCDhu58gbsSDbSAyMDE0IG5oxrAgc2F1OiANCg0KDQpgYGB7cn0NCiMgT2JzZXJ2YXRpb25zIG5vdCBiZWxvbmcgdG8gMjAxNDogDQoNCnVuYmFsYW5jZWRfcGFuZWxfZGF0YSAlPiUgDQogIGdyb3VwX2J5KGhfY29kZSkgJT4lIA0KICBjb3VudCgpICU+JSANCiAgZmlsdGVyKG4gPT0gMSkgJT4lIA0KICBwdWxsKGhfY29kZSkgLT4gc29tZV9jYXNlcw0KDQpzb21lX2Nhc2VzDQpgYGANCg0KTmjGsCB0aOG6vyBjw7MgbmdoxKlhIGzDoCwgUGFuZWwgRGF0YSBtw6AgY2jDum5nIHRhIHRodSDEkcaw4bujYyDhu58gdHLDqm4gbMOgIGxv4bqhaSBraMO0bmcgY8OibiBi4bqxbmcgKFVuYmFsYW5jZWQpLiDEkOG6v24gxJHDonkgY2jDum5nIHRhIGPDsyB0aOG7gyAiY2jhu4kgdGjhu4siIGNobyBSIGzDoG0gdmnhu4djIHbhu5tpIFBhbmVsIERhdGEgYuG6sW5nIHPhu60gZOG7pW5nIGjDoG0gKipwZGF0YS5mcmFtZSgpKiogY+G7p2EgdGjGsCB2aeG7h24gKipwbG0qKjogDQoNCmBgYHtyfQ0KIyBQcmVwYXJlIHBhbmVsIGRhdGE6IA0KDQpsaWJyYXJ5KHBsbSkNCg0KcGRhdGEuZnJhbWUodW5iYWxhbmNlZF9wYW5lbF9kYXRhLCANCiAgICAgICAgICAgIGluZGV4ID0gYygiaF9jb2RlIiwieWVhciIpLCANCiAgICAgICAgICAgIHJvdy5uYW1lcyA9IEZBTFNFLCANCiAgICAgICAgICAgIGRyb3AuaW5kZXggPSBGQUxTRSkgLT4gcGxtX2RhdGFfdW5iYWxhbmNlZA0KDQojIFNvbWUgb2JzZXJ2YXRpb25zOiANCmhlYWQocGxtX2RhdGFfdW5iYWxhbmNlZCkgJT4lIA0KICBrYmwoY2FwdGlvbiA9ICJUYWJsZSAyOiBTb21lIE9ic2VydmF0aW9ucyBmcm9tIFVuYmFsYW5jZWQgUGFuZWwgRGF0YSIsIGVzY2FwZSA9IFRSVUUpICU+JQ0KICBrYWJsZV9jbGFzc2ljKGZ1bGxfd2lkdGggPSBUUlVFLCBodG1sX2ZvbnQgPSAiQ2FtYnJpYSIpDQpgYGANCg0KIyBQYW5lbCBEYXRhIEFuYWx5c2lzDQoNClbhu5tpIGThu68gbGnhu4d1IMSRw6MgY8OzLCBjaMO6bmcgdGEgY8OzIHRo4buDIGNo4bqheSBjw6FjIG3DtCBow6xuaCBwaMOibiB0w61jaCBjaG8gUGFuZWwgRGF0YS4gQ2jhurNuZyBo4bqhbiBiYSBjw6FjaCB0aeG6v3AgY+G6rW4gxJHGsOG7o2MgY2jhu41uIGzDoCBQb29sZWQsIEZpeGVkIEVmZmVjdHMgdsOgIFJhbmRvbSBFZmZlY3RzIHPhu60gZOG7pW5nIMaw4bubYyBsxrDhu6NuZyBBbWVtaXlhOiANCg0KYGBge3J9DQojPT09PT09PT09PT09PT09PT09PT09PT09DQojIFNvbWUgUGFuZWwgRGF0YSBNb2RlbHMNCiM9PT09PT09PT09PT09PT09PT09PT09PT0NCg0KIyBQb29sZWQgTW9kZWw6IA0KcGFuZWxfcG9vbGVkIDwtIHBsbShtNGR0biB+IG00YXRuLCANCiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHBsbV9kYXRhX3VuYmFsYW5jZWQsIA0KICAgICAgICAgICAgICAgICAgICBtb2RlbCA9ICJwb29saW5nIikgDQoNCiMgRml4ZWQgRWZmZWN0cyBNb2RlbDogDQpwYW5lbF9mZSA8LSBwbG0obTRkdG4gfiBtNGF0biwgDQogICAgICAgICAgICAgICAgZGF0YSA9IHBsbV9kYXRhX3VuYmFsYW5jZWQsIA0KICAgICAgICAgICAgICAgIG1vZGVsID0gIndpdGhpbiIpICANCg0KIyBSYW5kb20gRWZmZWN0cyBNb2RlbHMgdXNpbmcgQW1lbWl5YSBlc3RpbWF0b3JzICgxOTcxKTogDQpwYW5lbF9yZSA8LSBwbG0obTRkdG4gfiBtNGF0biwgDQogICAgICAgICAgICAgICAgZGF0YSA9IHBsbV9kYXRhX3VuYmFsYW5jZWQsIA0KICAgICAgICAgICAgICAgIG1vZGVsID0gInJhbmRvbSIsIA0KICAgICAgICAgICAgICAgIHJhbmRvbS5tZXRob2QgPSAiYW1lbWl5YSIpDQpgYGANCg0KUuG7k2kgc28gc8Ohbmgga+G6v3QgcXXhuqMgY+G7p2EgYmEgY8OhY2ggdGnhur9wIGPhuq1uIG7DoHk6IA0KYGBge3J9DQojIENvbXBhcmUgcmVzdWx0czogDQoNCmxpYnJhcnkoc3RhcmdhemVyKQ0KDQpzdGFyZ2F6ZXIocGFuZWxfcG9vbGVkLCANCiAgICAgICAgICBwYW5lbF9mZSwgDQogICAgICAgICAgcGFuZWxfcmUsIA0KICAgICAgICAgIHRpdGxlID0gIlRhYmxlIDM6IENvbXBhcmUgUGFuZWwgRGF0YSBSZWdyZXNzaW9uIFJlc3VsdHMiLA0KICAgICAgICAgIGNvbHVtbi5sYWJlbHMgPSBjKCJQb29sZWQiLCJGaXhlZCBFZmZlY3RzIiwgIlJhbmRvbSBFZmZlY3RzIiksIA0KICAgICAgICAgIHR5cGUgPSAidGV4dCIsIA0KICAgICAgICAgIGFsaWduID0gVFJVRSkNCg0KYGBgDQoNCk7hur91IG114buRbiBjaMO6bmcgdGEgY8OzIHRo4buDIGNo4bqheSBs4bqhaSBiYSBtw7QgaMOsbmggdHLDqm4gduG7m2kgQmFsYW5jZWQgUGFuZWwgRGF0YSBkxrDhu5tpIMSRw6J5OiANCg0KYGBge3J9DQpwbG1fZGF0YV91bmJhbGFuY2VkICU+JSANCiAgZmlsdGVyKCFoX2NvZGUgJWluJSBzb21lX2Nhc2VzKSAtPiBwbG1fZGF0YV9iYWxhbmNlZA0KYGBgDQoNCiMgRmluYWwgTm90ZXMNCg0KUG9zdCBuw6B5IGtow7RuZyB0csOsbmggYsOgeSBt4buNaSBraMOtYSBj4bqhbmggY+G7p2Ega2hhaSB0aMOhYyAtIGNodeG6qW4gYuG7iyBk4buvIGxp4buHdSB04burIGPDoWMgVkhMU1MuIMSQ4buDIMSRxqFuIGdp4bqjbiwgcG9zdCBuw6B5IGNo4buJIHPhu60gZOG7pW5nIGThu68gbGnhu4d1IGPhu6dhIGhhaSBuxINtIGxpw6puIHRp4bq/cC4gVHV5IG5oacOqbiBuaOG7r25nIGxvZ2ljIHRyw6xuaCBiw6B5IHRyb25nIHBvc3QgbsOgeSBjw7MgdGjhu4Mgw6FwIGThu6VuZyDEkeG7gyB04bqhbyByYSBQYW5lbCBEYXRhIGNobyBraG/huqNuZyB0aOG7nWkgZ2lhbiBkw6BpIGjGoW4uIA0KDQpWaeG7h2MgY2h14bqpbiBi4buLIFBhbmVsIERhdGEgxJHGsOG7o2MgdHLDrG5oIGLDoHkgdHJvbmcgUG9zdCBuw6B5IGPFqW5nIGPDsyB0aOG7gyDDoXAgZOG7pW5nIGNobyBjw6FjIGLhu5kgZOG7ryBsaeG7h3Uga2jDoWMgbmjGsCBi4buZIGThu68gbGnhu4d1IGto4bqjbyBzw6F0IGRvYW5oIG5naGnhu4dwIHbhu6thIHbDoCBuaOG7jyBbU01FIC0gU21hbGwgYW5kIE1lZGl1bSBFbnRlcnByaXNlIFN1cnZleV0oaHR0cHM6Ly9jYWZlZGF1dHUuYmxvZ3Nwb3QuY29tLzIwMTUvMDcvYm8tZHUtbGlldS1zbWUtMjAwMi0yMDEzLmh0bWwpLiBW4bubaSB0csaw4budbmcgaOG7o3AgY+G7p2EgU01FIHRow6wgdmnhu4djIG7DoHkgbMOgIMSRxqFuIGdp4bqjbiBoxqFuIHbDrCBjaMO6bmcgdGEgY2jhu4kgY+G6p24gc+G7rSBk4bulbmcgIk3DoyBz4buRIHRodeG6vyIgY+G7p2EgZG9hbmggbmdoaeG7h3AgdGhheSB2w6wgdOG6oW8gY+G7mXQgYmnhur9uIGhfY29kZS4gDQoNCg0KDQo=