Motivations

Dear M,

Econometrics là môn học quan trọng (ít nhất là cho những ai định hướng theo đuổi bậc học sau đại học). Đối với hầu hết sinh viên, kể cả theo học ngành kinh tế, thì đây vẫn được coi là môn học khó. Textbook về môn học này thì nhiều. Ở Việt Nam có thể dễ dàng tìm được những textbooks nổi tiếng (chỉ nêu tên một số sách) của Gurajati, Woodbridge, Green, và Hill.

Trong số các textbooks này thì cuốn của Green dành cho bậc sau đại học nên nặng về phần toán. Sách của Gurajati và Woodbridge dành cho bậc đại học (Undergraduate) nhưng rất dày (đều trên 900 trang) và còn cả những mảng chuyên sâu về Panel Data và Time Series - những phần thường không được lựa chọn để giảng dạy môn học này cho bậc đại học khối ngành kinh tế ở hầu hết các đại học Việt Nam. Do vậy cuốn sách của Hill (chỉ 380 trang) tỏ ra là phù hợp hơn cả: không quá dài, trực quan dễ hình dung, và còn giải thích chi tiết cái gốc Thống Kê của môn học này.

Post này được viết để bạn có thể sử dụng textbook này một cách nhanh chóng.

Graph Section

Trước hết bạn nên load toàn bộ data của textbook này tại đây. Graph là một phần quan trọng của môn học này. Chúng ta có thể tái lập lại Figure 3.6 được trình bày tại trang 51 của giáo trình này với ngôn ngữ R như sau:

# Clear R our environment: 

rm(list = ls())

# Load data (from http://www.econometrics.com/comdata/hill/data.html): 

read.table("http://www.econometrics.com/comdata/hill/TAB3-1.shd", header = TRUE) -> exp_income_data

# Load some R packages: 

library(dplyr) # For data processing. 
library(ggplot2) # For data visualization. 

# Replicate figure 3.6 (page 51): 

exp_income_data %>% 
  ggplot(aes(x = x, y = y)) + 
  geom_point() + 
  labs(x = "Income", y = "Expenditure", 
       title = "Figure 3.6: Expenditure-Income Relationship", 
       subtitle = "Note: Replicate graph created by Hill et all. (2001)", 
       caption = "Source: http://principlesofeconometrics.com/ue2/ue2.htm")

Econometric Model

Giả sử chúng ta đề xuất mô hình kinh tế lượng dưới đây nhằm đánh giá mối quan hệ giữa thu nhập và chi tiêu:

\[Expenditure_i = \beta_0 + \beta_1 Income_{i} + u_i \ , \ i=1,\dots,n.\] Dưới đây là R codes ước lượng các hệ số hồi quy của mô hình trên:

# Estimate coefficients: 

lm(data = exp_income_data, y ~ x) -> ols_model

# Present results: 

library(stargazer)

stargazer(ols_model,  
          title = "Table 3.6: Regression Results",
          type = "text", 
          align = TRUE)
## 
## Table 3.6: Regression Results
## ===============================================
##                         Dependent variable:    
##                     ---------------------------
##                                  y             
## -----------------------------------------------
## x                            0.128***          
##                               (0.031)          
##                                                
## Constant                      40.768*          
##                              (22.139)          
##                                                
## -----------------------------------------------
## Observations                    40             
## R2                             0.317           
## Adjusted R2                    0.299           
## Residual Std. Error      37.805 (df = 38)      
## F Statistic           17.647*** (df = 1; 38)   
## ===============================================
## Note:               *p<0.1; **p<0.05; ***p<0.01

Đây chính là kết quả được trình bày trong textbook bằng phần mềm SAS tại trang 57.

Đương nhiên chúng ta có thể bổ sung thêm cả Regression Line màu đỏ với khoảng tin cậy 95% như sau:

# Add regression line: 

exp_income_data %>% 
  ggplot(aes(x = x, y = y)) + 
  geom_point() + 
  geom_smooth(method = "lm", color = "red") + 
  labs(x = "Income", y = "Expenditure", 
       title = "Figure 3.6: Expenditure-Income Relationship", 
       subtitle = "Note: Replicate graph created by Hill et all. (2001)", 
       caption = "Source: http://principlesofeconometrics.com/ue2/ue2.htm")

Basic Econometrics

Đây cũng là một textbook nhập môn rất hay (và rất dày) của Gujarati. Sách này có thể download tại đây. Data của textbook có thể download tại đây. Theo truyền thống tì textbook này sử dụng phần mềm Eviews (với các file dữ liệu có đuôi là .wf1). Dưới đây là một bộ số liệu được trình bày ở trang 24:

Load bộ dữ liệu Eviews này vào R:

# Load hexView packege for importing Eviews files: 

library(hexView)

# Load data: 

readEViews("table1-1.wf1") -> table1_1_p24

# Show some observations: 

head(table1_1_p24)
##         Date     Y1     Y2    Y3    Y4       GROUP01       TABLE01
## 1 0001-01-01 2206.0 2186.0  92.7  91.4 1.807873e-308 6.953356e-309
## 2 0002-01-01    0.7    0.7 151.0 149.0 3.013522e-315  0.000000e+00
## 3 0003-01-01   73.0   74.0  61.0  56.0 2.215260e+214 1.244442e-309
## 4 0004-01-01 3620.0 3737.0  86.3  91.8 8.165349e+141 3.204296e-306
## 5 0005-01-01 7472.0 7444.0  63.4  58.4  9.780788e+24 2.758637e-312
## 6 0006-01-01  788.0  873.0  77.8  73.0 3.068373e+257  0.000000e+00

Giáo trình này còn cung cấp dữ liệu ở dạng .txt. Chúng ta cũng có thể load bộ dữ liệu trên ở định dạng này vào R như sau:

# Load data from .txt files: 

read.table("Table 1.1.txt", header = TRUE, skip = 7) -> table1_1_p24_from_txt

# Show some observations: 

head(table1_1_p24_from_txt)
##   STATE     Y1     Y2    X1    X2
## 1    AL 2206.0 2186.0  92.7  91.4
## 2    AK    0.7    0.7 151.0 149.0
## 3    AZ   73.0   74.0  61.0  56.0
## 4    AR 3620.0 3737.0  86.3  91.8
## 5    CA 7472.0 7444.0  63.4  58.4
## 6    CO  788.0  873.0  77.8  73.0

Cách khác là chúng ta load bất kì bộ số liệu nào (được giáo trình này sử dụng) từ package gujarati. Trước hết cài đặt package này như sau:

# Install remotes package for using install_github() command: 
install.packages("remotes")

# Install gujarati package: 
remotes::install_github("brunoruas2/gujarati")

Đến đây chúng ta có thể sử dụng bất bì bộ dữ liệu nào được nhắc đến trong giáo trình này, ví dụ:

# Load gujarati package: 

library(gujarati)

# Load data from gujatati package: 
data("Table1_1")

# Show some observations: 

head(Table1_1)
##   STATE   Y1   Y2   X1   X2
## 1    AL 2206 2186 92.7 91.4
## 2    AK  0.7  0.7  151  149
## 3    AZ   73   74   61   56
## 4    AR 3620 3737 86.3 91.8
## 5    CA 7472 7444 63.4 58.4
## 6    CO  788  873 77.8   73

Cái hay là những dữ liệu load từ package này có mô tả đầy đủ. R codes để có thông tin về bộ dữ liệu như sau:

?Table1_1

Dưới đây là Example 3.1 được trình bày tại trang 81:

Chúng ta có thể tái lập lại kết quả ở Example 3.1 như sau:

# Load data: 

data("TableI_1")

Tác giả của gói gujarati có lẽ gặp lỗi nào đó khi viết package này khiến cho những variables của bộ dữ liệu này đang là factor. Do vậy cần convert về numeric cho phù hợp với bản chất của các biến:

TableI_1 %>% 
  mutate(PCE = as.numeric(as.character(PCE.Y.)), 
         GDP = as.numeric(as.character(GDP.X.)), 
         time = as.numeric(as.character(Year))) -> TableI_1

Với data đã được xử lí chúng ta có thể thực hiện ước lượng cho mô hình và trình bày kết quả:

# Estimate coefficients: 

lm(data = TableI_1, PCE ~ GDP) -> my_ols

# Present results: 

stargazer(my_ols,  
          title = "Example 3.1 (Gujarati Textbook): Regression Results",
          type = "text", 
          align = TRUE)
## 
## Example 3.1 (Gujarati Textbook): Regression Results
## ===============================================
##                         Dependent variable:    
##                     ---------------------------
##                                 PCE            
## -----------------------------------------------
## GDP                          0.722***          
##                               (0.004)          
##                                                
## Constant                    -299.591***        
##                              (28.765)          
##                                                
## -----------------------------------------------
## Observations                    46             
## R2                             0.998           
## Adjusted R2                    0.998           
## Residual Std. Error      73.567 (df = 44)      
## F Statistic         26,630.330*** (df = 1; 44) 
## ===============================================
## Note:               *p<0.1; **p<0.05; ***p<0.01

Hoặc trình bày kết quả theo một cách khác:

summary(my_ols)
## 
## Call:
## lm(formula = PCE ~ GDP, data = TableI_1)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -151.094  -50.358   -6.161   37.199  165.532 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -2.996e+02  2.876e+01  -10.41 1.88e-13 ***
## GDP          7.218e-01  4.423e-03  163.19  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 73.57 on 44 degrees of freedom
## Multiple R-squared:  0.9984, Adjusted R-squared:  0.9983 
## F-statistic: 2.663e+04 on 1 and 44 DF,  p-value: < 2.2e-16

Final Notes

Sử dụng R cho mục đích khiêm tốn là giảng dạy Econometrics không quá khó khăn như hình dung ban đầu. Lại có nhiều lợi thế khác. Chẳng hạn như có thể tạo ra bài giảng, slide luôn.

LS0tDQp0aXRsZTogIlVuZGVyZ3JhZHVhdGUgRWNvbm9tZXRyaWNzIChSIFZlcnNpb24pIg0KYXV0aG9yOiAiQXV0aG9yOiBOZ3V5ZW4gQ2hpIER1bmciDQpzdWJ0aXRsZTogIkVjb25vbWV0cmljcyBTZXJpZXMiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgaGlnaGxpZ2h0OiB6ZW5idXJuDQogICAgdGhlbWU6IGZsYXRseQ0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICBwZGZfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCxpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgY2FjaGUgPSBUUlVFKQ0KDQpgYGANCg0KIVtdKGVjb25faGlsbC5qcGcpDQoNCiMgTW90aXZhdGlvbnMNCg0KRGVhciBNLCANCg0KRWNvbm9tZXRyaWNzIGzDoCBtw7RuIGjhu41jIHF1YW4gdHLhu41uZyAow610IG5o4bqldCBsw6AgY2hvIG5o4buvbmcgYWkgxJHhu4tuaCBoxrDhu5tuZyB0aGVvIMSRdeG7lWkgYuG6rWMgaOG7jWMgc2F1IMSR4bqhaSBo4buNYykuIMSQ4buRaSB24bubaSBo4bqndSBo4bq/dCBzaW5oIHZpw6puLCBr4buDIGPhuqMgdGhlbyBo4buNYyBuZ8Ogbmgga2luaCB04bq/LCB0aMOsIMSRw6J5IHbhuqtuIMSRxrDhu6NjIGNvaSBsw6AgbcO0biBo4buNYyBraMOzLiBUZXh0Ym9vayB24buBIG3DtG4gaOG7jWMgbsOgeSB0aMOsIG5oaeG7gXUuIOG7niBWaeG7h3QgTmFtIGPDsyB0aOG7gyBk4buFIGTDoG5nIHTDrG0gxJHGsOG7o2Mgbmjhu69uZyB0ZXh0Ym9va3MgbuG7lWkgdGnhur9uZyAoY2jhu4kgbsOqdSB0w6puIG3hu5l0IHPhu5Egc8OhY2gpIGPhu6dhIFtHdXJhamF0aV0oaHR0cHM6Ly93d3cuYW1hem9uLmNvbS9CYXNpYy1FY29ub21ldHJpY3MtRGFtb2Rhci1OLUd1amFyYXRpL2RwLzAwNzMzNzU3NzIpLCBbV29vZGJyaWRnZV0oaHR0cHM6Ly93d3cuYW1hem9uLmNvbS9JbnRyb2R1Y3RvcnktRWNvbm9tZXRyaWNzLU1vZGVybi1BcHByb2FjaC1NaW5kVGFwL2RwLzEzMzc1NTg4NjkvcmVmPXNyXzFfMT9jcmlkPTFCRDMwSFBFTU8zODcma2V5d29yZHM9SW50cm9kdWN0b3J5K0Vjb25vbWV0cmljcyUzQStBK01vZGVybitBcHByb2FjaCZxaWQ9MTY3ODMzNjM1OSZzPWJvb2tzJnNwcmVmaXg9aW50cm9kdWN0b3J5K2Vjb25vbWV0cmljcythK21vZGVybithcHByb2FjaCUyQ3N0cmlwYm9va3MtaW50bC1zaGlwJTJDMjkzJnNyPTEtMSksIFtHcmVlbl0oaHR0cHM6Ly93d3cuYW1hem9uLmNvbS9FY29ub21ldHJpYy1BbmFseXNpcy1HcmVlbmUvZHAvOTM1MzA2MTA3NS9yZWY9c3JfMV8xP2NyaWQ9VkFHNzE2MTcyMFlUJmtleXdvcmRzPUdyZWVuK2Vjb25vbWV0cmljcyZxaWQ9MTY3ODMzNjQxNyZzPWJvb2tzJnNwcmVmaXg9Z3JlZW4rZWNvbm9tZXRyaWNzJTJDc3RyaXBib29rcy1pbnRsLXNoaXAlMkMyOTUmc3I9MS0xKSwgdsOgIFtIaWxsXShodHRwczovL3d3dy5hbWF6b24uY29tL1VuZGVyZ3JhZHVhdGUtRWNvbm9tZXRyaWNzLVItQ2FydGVyLUhpbGwvZHAvMDQ3MTMzMTg0OC9yZWY9c3JfMV8xP2NyaWQ9MldLNlZFRVlUTDY5WCZrZXl3b3Jkcz1oaWxsK3VuZGVyZ3JhZHVhdGUrZWNvbm9tZXRyaWNzJnFpZD0xNjc4MzM2NTA3JnM9Ym9va3Mmc3ByZWZpeD1oaWxsK3VuZGVyZ3JhZHVhdGUrZWNvbm9tZXRyaWNzJTJDc3RyaXBib29rcy1pbnRsLXNoaXAlMkMzNDgmc3I9MS0xKS4gDQoNCg0KVHJvbmcgc+G7kSBjw6FjIHRleHRib29rcyBuw6B5IHRow6wgY3Xhu5FuIGPhu6dhIEdyZWVuIGTDoG5oIGNobyBi4bqtYyBzYXUgxJHhuqFpIGjhu41jIG7Dqm4gbuG6t25nIHbhu4EgcGjhuqduIHRvw6FuLiBTw6FjaCBj4bunYSBHdXJhamF0aSB2w6AgV29vZGJyaWRnZSBkw6BuaCBjaG8gYuG6rWMgxJHhuqFpIGjhu41jIChVbmRlcmdyYWR1YXRlKSBuaMawbmcgcuG6pXQgZMOgeSAoxJHhu4F1IHRyw6puIDkwMCB0cmFuZykgdsOgIGPDsm4gY+G6oyBuaOG7r25nIG3huqNuZyBjaHV5w6puIHPDonUgduG7gSBQYW5lbCBEYXRhIHbDoCBUaW1lIFNlcmllcyAtIG5o4buvbmcgcGjhuqduIHRoxrDhu51uZyBraMO0bmcgxJHGsOG7o2MgbOG7sWEgY2jhu41uIMSR4buDIGdp4bqjbmcgZOG6oXkgbcO0biBo4buNYyBuw6B5IGNobyBi4bqtYyDEkeG6oWkgaOG7jWMga2jhu5FpIG5nw6BuaCBraW5oIHThur8g4bufIGjhuqd1IGjhur90IGPDoWMgxJHhuqFpIGjhu41jIFZp4buHdCBOYW0uIERvIHbhuq15IGN14buRbiBzw6FjaCBj4bunYSBIaWxsIChjaOG7iSAzODAgdHJhbmcpIHThu48gcmEgbMOgIHBow7kgaOG7o3AgaMahbiBj4bqjOiBraMO0bmcgcXXDoSBkw6BpLCB0cuG7sWMgcXVhbiBk4buFIGjDrG5oIGR1bmcsIHbDoCBjw7JuIGdp4bqjaSB0aMOtY2ggY2hpIHRp4bq/dCBjw6FpIGfhu5FjIFRo4buRbmcgS8OqIGPhu6dhIG3DtG4gaOG7jWMgbsOgeS4gDQoNClBvc3QgbsOgeSDEkcaw4bujYyB2aeG6v3QgxJHhu4MgYuG6oW4gY8OzIHRo4buDIHPhu60gZOG7pW5nIHRleHRib29rIG7DoHkgbeG7mXQgY8OhY2ggbmhhbmggY2jDs25nLiANCg0KDQojIEdyYXBoIFNlY3Rpb24NCg0KVHLGsOG7m2MgaOG6v3QgYuG6oW4gbsOqbiBsb2FkIHRvw6BuIGLhu5kgZGF0YSBj4bunYSB0ZXh0Ym9vayBuw6B5IFt04bqhaSDEkcOieV0oaHR0cDovL3ByaW5jaXBsZXNvZmVjb25vbWV0cmljcy5jb20vdWUyL3VlMi5odG0pLiBHcmFwaCBsw6AgbeG7mXQgcGjhuqduIHF1YW4gdHLhu41uZyBj4bunYSBtw7RuIGjhu41jIG7DoHkuIENow7puZyB0YSBjw7MgdGjhu4MgdMOhaSBs4bqtcCBs4bqhaSBGaWd1cmUgMy42IMSRxrDhu6NjIHRyw6xuaCBiw6B5IHThuqFpIHRyYW5nIDUxIGPhu6dhIGdpw6FvIHRyw6xuaCBuw6B5IHbhu5tpIG5nw7RuIG5n4buvIFIgbmjGsCBzYXU6IA0KDQoNCmBgYHtyfQ0KDQojIENsZWFyIFIgb3VyIGVudmlyb25tZW50OiANCg0Kcm0obGlzdCA9IGxzKCkpDQoNCiMgTG9hZCBkYXRhIChmcm9tIGh0dHA6Ly93d3cuZWNvbm9tZXRyaWNzLmNvbS9jb21kYXRhL2hpbGwvZGF0YS5odG1sKTogDQoNCnJlYWQudGFibGUoImh0dHA6Ly93d3cuZWNvbm9tZXRyaWNzLmNvbS9jb21kYXRhL2hpbGwvVEFCMy0xLnNoZCIsIGhlYWRlciA9IFRSVUUpIC0+IGV4cF9pbmNvbWVfZGF0YQ0KDQojIExvYWQgc29tZSBSIHBhY2thZ2VzOiANCg0KbGlicmFyeShkcGx5cikgIyBGb3IgZGF0YSBwcm9jZXNzaW5nLiANCmxpYnJhcnkoZ2dwbG90MikgIyBGb3IgZGF0YSB2aXN1YWxpemF0aW9uLiANCg0KIyBSZXBsaWNhdGUgZmlndXJlIDMuNiAocGFnZSA1MSk6IA0KDQpleHBfaW5jb21lX2RhdGEgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpICsgDQogIGdlb21fcG9pbnQoKSArIA0KICBsYWJzKHggPSAiSW5jb21lIiwgeSA9ICJFeHBlbmRpdHVyZSIsIA0KICAgICAgIHRpdGxlID0gIkZpZ3VyZSAzLjY6IEV4cGVuZGl0dXJlLUluY29tZSBSZWxhdGlvbnNoaXAiLCANCiAgICAgICBzdWJ0aXRsZSA9ICJOb3RlOiBSZXBsaWNhdGUgZ3JhcGggY3JlYXRlZCBieSBIaWxsIGV0IGFsbC4gKDIwMDEpIiwgDQogICAgICAgY2FwdGlvbiA9ICJTb3VyY2U6IGh0dHA6Ly9wcmluY2lwbGVzb2ZlY29ub21ldHJpY3MuY29tL3VlMi91ZTIuaHRtIikNCg0KYGBgDQoNCiMgRWNvbm9tZXRyaWMgTW9kZWwNCg0KR2nhuqMgc+G7rSBjaMO6bmcgdGEgxJHhu4EgeHXhuqV0IG3DtCBow6xuaCBraW5oIHThur8gbMaw4bujbmcgZMaw4bubaSDEkcOieSBuaOG6sW0gxJHDoW5oIGdpw6EgbeG7kWkgcXVhbiBo4buHIGdp4buvYSB0aHUgbmjhuq1wIHbDoCBjaGkgdGnDqnU6IA0KDQoNCiQkRXhwZW5kaXR1cmVfaSA9IFxiZXRhXzAgKyBcYmV0YV8xIEluY29tZV97aX0gKyB1X2kgXCAsIFwgaT0xLFxkb3RzLG4uJCQNCkTGsOG7m2kgxJHDonkgbMOgIFIgY29kZXMgxrDhu5tjIGzGsOG7o25nIGPDoWMgaOG7hyBz4buRIGjhu5NpIHF1eSBj4bunYSBtw7QgaMOsbmggdHLDqm46DQoNCg0KYGBge3J9DQojIEVzdGltYXRlIGNvZWZmaWNpZW50czogDQoNCmxtKGRhdGEgPSBleHBfaW5jb21lX2RhdGEsIHkgfiB4KSAtPiBvbHNfbW9kZWwNCg0KIyBQcmVzZW50IHJlc3VsdHM6IA0KDQpsaWJyYXJ5KHN0YXJnYXplcikNCg0Kc3RhcmdhemVyKG9sc19tb2RlbCwgIA0KICAgICAgICAgIHRpdGxlID0gIlRhYmxlIDMuNjogUmVncmVzc2lvbiBSZXN1bHRzIiwNCiAgICAgICAgICB0eXBlID0gInRleHQiLCANCiAgICAgICAgICBhbGlnbiA9IFRSVUUpDQpgYGANCg0KxJDDonkgY2jDrW5oIGzDoCBr4bq/dCBxdeG6oyDEkcaw4bujYyB0csOsbmggYsOgeSB0cm9uZyB0ZXh0Ym9vayBi4bqxbmcgcGjhuqduIG3hu4FtIFNBUyB04bqhaSB0cmFuZyA1Ny4gDQoNCsSQxrDGoW5nIG5oacOqbiBjaMO6bmcgdGEgY8OzIHRo4buDIGLhu5Ugc3VuZyB0aMOqbSBj4bqjIFJlZ3Jlc3Npb24gTGluZSBtw6B1IMSR4buPIHbhu5tpIGtob+G6o25nIHRpbiBj4bqteSA5NSUgbmjGsCBzYXU6IA0KDQpgYGB7cn0NCiMgQWRkIHJlZ3Jlc3Npb24gbGluZTogDQoNCmV4cF9pbmNvbWVfZGF0YSAlPiUgDQogIGdncGxvdChhZXMoeCA9IHgsIHkgPSB5KSkgKyANCiAgZ2VvbV9wb2ludCgpICsgDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gInJlZCIpICsgDQogIGxhYnMoeCA9ICJJbmNvbWUiLCB5ID0gIkV4cGVuZGl0dXJlIiwgDQogICAgICAgdGl0bGUgPSAiRmlndXJlIDMuNjogRXhwZW5kaXR1cmUtSW5jb21lIFJlbGF0aW9uc2hpcCIsIA0KICAgICAgIHN1YnRpdGxlID0gIk5vdGU6IFJlcGxpY2F0ZSBncmFwaCBjcmVhdGVkIGJ5IEhpbGwgZXQgYWxsLiAoMjAwMSkiLCANCiAgICAgICBjYXB0aW9uID0gIlNvdXJjZTogaHR0cDovL3ByaW5jaXBsZXNvZmVjb25vbWV0cmljcy5jb20vdWUyL3VlMi5odG0iKQ0KDQpgYGANCg0KIyBCYXNpYyBFY29ub21ldHJpY3MNCg0KxJDDonkgY8WpbmcgbMOgIG3hu5l0IHRleHRib29rIG5o4bqtcCBtw7RuIHLhuqV0IGhheSAodsOgIHLhuqV0IGTDoHkpIGPhu6dhIEd1amFyYXRpLiBTw6FjaCBuw6B5IGPDsyB0aOG7gyBkb3dubG9hZCBbdOG6oWkgxJHDonldKGh0dHBzOi8vd3d3LmNicGJ1LmFjLmluL3VzZXJmaWxlcy9maWxlLzIwMjAvU1RVRFlfTUFUL0VDTy8xLnBkZikuIERhdGEgY+G7p2EgdGV4dGJvb2sgY8OzIHRo4buDIGRvd25sb2FkIFt04bqhaSDEkcOieV0oaHR0cHM6Ly9oaWdoZXJlZC5taGVkdWNhdGlvbi5jb20vc2l0ZXMvMDA3MDY2MDA1MC9zdHVkZW50X3ZpZXcwL2RhdGFfc2V0cy5odG1sKS4gVGhlbyB0cnV54buBbiB0aOG7kW5nIHTDrCB0ZXh0Ym9vayBuw6B5IHPhu60gZOG7pW5nIHBo4bqnbiBt4buBbSBFdmlld3MgKHbhu5tpIGPDoWMgZmlsZSBk4buvIGxp4buHdSBjw7MgxJF1w7RpIGzDoCAud2YxKS4gRMaw4bubaSDEkcOieSBsw6AgbeG7mXQgYuG7mSBz4buRIGxp4buHdSDEkcaw4bujYyB0csOsbmggYsOgeSDhu58gdHJhbmcgMjQ6IA0KDQohW10odGFibGUxXzFfcDI0LmpwZykNCg0KTG9hZCBi4buZIGThu68gbGnhu4d1IEV2aWV3cyBuw6B5IHbDoG8gUjogDQoNCmBgYHtyfQ0KIyBMb2FkIGhleFZpZXcgcGFja2VnZSBmb3IgaW1wb3J0aW5nIEV2aWV3cyBmaWxlczogDQoNCmxpYnJhcnkoaGV4VmlldykNCg0KIyBMb2FkIGRhdGE6IA0KDQpyZWFkRVZpZXdzKCJ0YWJsZTEtMS53ZjEiKSAtPiB0YWJsZTFfMV9wMjQNCg0KIyBTaG93IHNvbWUgb2JzZXJ2YXRpb25zOiANCg0KaGVhZCh0YWJsZTFfMV9wMjQpDQoNCmBgYA0KDQpHacOhbyB0csOsbmggbsOgeSBjw7JuIGN1bmcgY+G6pXAgZOG7ryBsaeG7h3Ug4bufIGThuqFuZyAudHh0LiBDaMO6bmcgdGEgY8WpbmcgY8OzIHRo4buDIGxvYWQgYuG7mSBk4buvIGxp4buHdSB0csOqbiDhu58gxJHhu4tuaCBk4bqhbmcgbsOgeSB2w6BvIFIgbmjGsCBzYXU6IA0KDQpgYGB7cn0NCiMgTG9hZCBkYXRhIGZyb20gLnR4dCBmaWxlczogDQoNCnJlYWQudGFibGUoIlRhYmxlIDEuMS50eHQiLCBoZWFkZXIgPSBUUlVFLCBza2lwID0gNykgLT4gdGFibGUxXzFfcDI0X2Zyb21fdHh0DQoNCiMgU2hvdyBzb21lIG9ic2VydmF0aW9uczogDQoNCmhlYWQodGFibGUxXzFfcDI0X2Zyb21fdHh0KQ0KYGBgDQoNCkPDoWNoIGtow6FjIGzDoCBjaMO6bmcgdGEgbG9hZCAqKmLhuqV0IGvDrCoqIGLhu5kgc+G7kSBsaeG7h3UgbsOgbyAoxJHGsOG7o2MgZ2nDoW8gdHLDrG5oIG7DoHkgc+G7rSBk4bulbmcpIHThu6sgcGFja2FnZSAqZ3VqYXJhdGkqLiBUcsaw4bubYyBo4bq/dCBjw6BpIMSR4bq3dCBwYWNrYWdlIG7DoHkgbmjGsCBzYXU6IA0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCiMgSW5zdGFsbCByZW1vdGVzIHBhY2thZ2UgZm9yIHVzaW5nIGluc3RhbGxfZ2l0aHViKCkgY29tbWFuZDogDQppbnN0YWxsLnBhY2thZ2VzKCJyZW1vdGVzIikNCg0KIyBJbnN0YWxsIGd1amFyYXRpIHBhY2thZ2U6IA0KcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoImJydW5vcnVhczIvZ3VqYXJhdGkiKQ0KYGBgDQoNCsSQ4bq/biDEkcOieSBjaMO6bmcgdGEgY8OzIHRo4buDIHPhu60gZOG7pW5nIGLhuqV0IGLDrCBi4buZIGThu68gbGnhu4d1IG7DoG8gxJHGsOG7o2Mgbmjhuq9jIMSR4bq/biB0cm9uZyBnacOhbyB0csOsbmggbsOgeSwgdsOtIGThu6U6DQoNCg0KYGBge3J9DQojIExvYWQgZ3VqYXJhdGkgcGFja2FnZTogDQoNCmxpYnJhcnkoZ3VqYXJhdGkpDQoNCiMgTG9hZCBkYXRhIGZyb20gZ3VqYXRhdGkgcGFja2FnZTogDQpkYXRhKCJUYWJsZTFfMSIpDQoNCiMgU2hvdyBzb21lIG9ic2VydmF0aW9uczogDQoNCmhlYWQoVGFibGUxXzEpDQoNCmBgYA0KDQpDw6FpIGhheSBsw6Agbmjhu69uZyBk4buvIGxp4buHdSBsb2FkIHThu6sgcGFja2FnZSBuw6B5IGPDsyBtw7QgdOG6oyDEkeG6p3kgxJHhu6cuIFIgY29kZXMgxJHhu4MgY8OzIHRow7RuZyB0aW4gduG7gSBi4buZIGThu68gbGnhu4d1IG5oxrAgc2F1OiANCg0KYGBge3J9DQo/VGFibGUxXzENCmBgYA0KDQohW10oZGVzLmpwZykNCg0KDQpExrDhu5tpIMSRw6J5IGzDoCBFeGFtcGxlIDMuMSDEkcaw4bujYyB0csOsbmggYsOgeSB04bqhaSB0cmFuZyA4MToNCg0KDQohW10oZXgzLjEuanBnKQ0KDQoNCg0KDQpDaMO6bmcgdGEgY8OzIHRo4buDIHTDoWkgbOG6rXAgbOG6oWkga+G6v3QgcXXhuqMg4bufIEV4YW1wbGUgMy4xIG5oxrAgc2F1OiANCg0KYGBge3J9DQojIExvYWQgZGF0YTogDQoNCmRhdGEoIlRhYmxlSV8xIikNCmBgYA0KDQpUw6FjIGdp4bqjIGPhu6dhIGfDs2kgZ3VqYXJhdGkgY8OzIGzhur0gZ+G6t3AgbOG7l2kgbsOgbyDEkcOzIGtoaSB2aeG6v3QgcGFja2FnZSBuw6B5IGtoaeG6v24gY2hvIG5o4buvbmcgdmFyaWFibGVzIGPhu6dhIGLhu5kgZOG7ryBsaeG7h3UgbsOgeSDEkWFuZyBsw6AgZmFjdG9yLiBEbyB24bqteSBj4bqnbiBjb252ZXJ0IHbhu4EgbnVtZXJpYyBjaG8gcGjDuSBo4bujcCB24bubaSBi4bqjbiBjaOG6pXQgY+G7p2EgY8OhYyBiaeG6v246IA0KDQpgYGB7cn0NClRhYmxlSV8xICU+JSANCiAgbXV0YXRlKFBDRSA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKFBDRS5ZLikpLCANCiAgICAgICAgIEdEUCA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKEdEUC5YLikpLCANCiAgICAgICAgIHRpbWUgPSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihZZWFyKSkpIC0+IFRhYmxlSV8xDQpgYGANCg0KVuG7m2kgZGF0YSDEkcOjIMSRxrDhu6NjIHjhu60gbMOtIGNow7puZyB0YSBjw7MgdGjhu4MgdGjhu7FjIGhp4buHbiDGsOG7m2MgbMaw4bujbmcgY2hvIG3DtCBow6xuaCB2w6AgdHLDrG5oIGLDoHkga+G6v3QgcXXhuqM6IA0KDQpgYGB7cn0NCiMgRXN0aW1hdGUgY29lZmZpY2llbnRzOiANCg0KbG0oZGF0YSA9IFRhYmxlSV8xLCBQQ0UgfiBHRFApIC0+IG15X29scw0KDQojIFByZXNlbnQgcmVzdWx0czogDQoNCnN0YXJnYXplcihteV9vbHMsICANCiAgICAgICAgICB0aXRsZSA9ICJFeGFtcGxlIDMuMSAoR3VqYXJhdGkgVGV4dGJvb2spOiBSZWdyZXNzaW9uIFJlc3VsdHMiLA0KICAgICAgICAgIHR5cGUgPSAidGV4dCIsIA0KICAgICAgICAgIGFsaWduID0gVFJVRSkNCg0KDQpgYGANCg0KSG/hurdjIHRyw6xuaCBiw6B5IGvhur90IHF14bqjIHRoZW8gbeG7mXQgY8OhY2gga2jDoWM6IA0KDQpgYGB7cn0NCnN1bW1hcnkobXlfb2xzKQ0KYGBgDQoNCg0KDQojIEZpbmFsIE5vdGVzDQoNClPhu60gZOG7pW5nIFIgY2hvIG3hu6VjIMSRw61jaCBraGnDqm0gdOG7kW4gbMOgIGdp4bqjbmcgZOG6oXkgRWNvbm9tZXRyaWNzIGtow7RuZyBxdcOhIGtow7Mga2jEg24gbmjGsCBow6xuaCBkdW5nIGJhbiDEkeG6p3UuIEzhuqFpIGPDsyBuaGnhu4F1IGzhu6NpIHRo4bq/IGtow6FjLiBDaOG6s25nIGjhuqFuIG5oxrAgY8OzIHRo4buDIHThuqFvIHJhIGLDoGkgZ2nhuqNuZywgc2xpZGUgbHXDtG4uIA0KDQoNCg0K