Trích xuất dữ liệu

# Load các package cần thiết 
library(xlsx) 
## Warning: package 'xlsx' was built under R version 4.3.3
library(quantmod)
## Warning: package 'quantmod' was built under R version 4.3.3
## Loading required package: xts
## Warning: package 'xts' was built under R version 4.3.3
## Loading required package: zoo
## Warning: package 'zoo' was built under R version 4.3.3
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## Loading required package: TTR
## Warning: package 'TTR' was built under R version 4.3.3
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.3.3
## Warning: package 'ggplot2' was built under R version 4.3.3
## Warning: package 'tidyr' was built under R version 4.3.3
## Warning: package 'dplyr' was built under R version 4.3.3
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.1     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.1
## ✔ purrr     1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::first()  masks xts::first()
## ✖ dplyr::lag()    masks stats::lag()
## ✖ dplyr::last()   masks xts::last()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(xts)
library(PerformanceAnalytics)
## Warning: package 'PerformanceAnalytics' was built under R version 4.3.3
## 
## Attaching package: 'PerformanceAnalytics'
## 
## The following object is masked from 'package:graphics':
## 
##     legend
library(forecast)
## Warning: package 'forecast' was built under R version 4.3.3
library(rugarch)
## Warning: package 'rugarch' was built under R version 4.3.3
## Loading required package: parallel
## 
## Attaching package: 'rugarch'
## 
## The following object is masked from 'package:purrr':
## 
##     reduce
## 
## The following object is masked from 'package:stats':
## 
##     sigma
library(goftest)
library(VineCopula)
## Warning: package 'VineCopula' was built under R version 4.3.3
library(tseries)
## Warning: package 'tseries' was built under R version 4.3.3
library(FinTS)
## Warning: package 'FinTS' was built under R version 4.3.3
## 
## Attaching package: 'FinTS'
## 
## The following object is masked from 'package:forecast':
## 
##     Acf
library(ggplot2)
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.3.3
## corrplot 0.92 loaded
library(ggcorrplot)
## Warning: package 'ggcorrplot' was built under R version 4.3.3
# Nhập dữ liệu 
data <- read.xlsx("C:/Users/ADMIN/Desktop/MHNN/dulieucd1.xlsx", sheetIndex = 1, header = T)

Tỷ suất lợi nhuận theo chuỗi data

# Tính tỷ suất lợi nhuận theo công thức log(t)-log(t-1)
lgvn<- diff(log(data$VNI), lag = 1)
lgtl<- diff(log(data$THAILAN), lag = 1)
mhnn <- data.frame(VNI= lgvn, TL = lgtl)

Thống kê mô tả

library(moments)
## 
## Attaching package: 'moments'
## The following objects are masked from 'package:PerformanceAnalytics':
## 
##     kurtosis, skewness
library(kableExtra)
## Warning: package 'kableExtra' was built under R version 4.3.3
## 
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
## 
##     group_rows
library(dplyr)
mhnn_df <- as.data.frame(mhnn)
a <- mhnn_df %>% summarise(Min = min(VNI),
                      Max = max(VNI),
                      Mean = mean(VNI),
                      StDev = sd(VNI),
                      Skewness = skewness(VNI),
                      Kurtosis = kurtosis(VNI))
b <- mhnn_df %>% summarise(Min = min(TL),
                      Max = max(TL),
                      Mean = mean(TL),
                      StDev = sd(TL),
                      Skewness = skewness(TL),
                      Kurtosis = kurtosis(TL))
m <- rbind(a,b)
rownames(m) <- c('VNI','TL')
kable(m, format = 'pandoc', caption = 'Bảng: Thống kê mô tả chuỗi TSLN', table.attr = "style='width:100%;'") %>% kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
## Warning in kable_styling(., bootstrap_options = c("striped", "hover",
## "condensed")): Please specify format in kable. kableExtra can customize either
## HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ for details.
Bảng: Thống kê mô tả chuỗi TSLN
Min Max Mean StDev Skewness Kurtosis
VNI -0.0648198 0.0620016 0.0004976 0.0109334 -0.7978217 8.318537
TL -0.1140605 0.0811544 -0.0000457 0.0118501 -1.2811032 21.163499

Đồ thị Box-Plot

# Biểu đồ Box-plot
pivot_longer(mhnn_df, cols = everything(), names_to = "TSLN", values_to = "Value") %>% ggplot(aes(x = TSLN, y = Value)) +
  geom_boxplot(fill = "cyan", color = "black") +
  theme_minimal() +
  labs(title = "Hình: Biểu đồ hộp của TSLN VNI và TL",
       x = "Chỉ số",
       y = "Tỷ suất sinh lợi")

Các kiểm định cần thiết

library(tseries)
# Các kiểm định 
#Kiểm định tính dừng
adf_vni <- adf.test(mhnn$VNI)
## Warning in adf.test(mhnn$VNI): p-value smaller than printed p-value
adf_tl <- adf.test(mhnn$TL)
## Warning in adf.test(mhnn$TL): p-value smaller than printed p-value
#Kiểm định phân phối chuẩn
jq_vni <- jarque.bera.test(mhnn$VNI)
jq_tl <- jarque.bera.test(mhnn$TL)
# Ước lượng và trích xuất phần dư từ mô hình ARMA tối ưu
arima_VNI <- autoarfima(mhnn$VNI,ar.max = 2, ma.max = 2, criterion = 'AIC', method = "full")

arima_tl <- autoarfima(mhnn$TL,ar.max = 2, ma.max = 2, criterion = 'AIC', method = "full")

re_VNI <- arima_VNI$fit@fit$residuals
re_TL <- arima_tl$fit@fit$residuals
#Kiểm định tương quan chuỗi bậc 2 cho phần dư
lj_vni <- Box.test(re_VNI,type = 'Ljung-Box', lag = 2)
lj_tl <- Box.test(re_TL,type = 'Ljung-Box', lag = 2)

#Kiểm định tương quan chuỗi bậc 2 cho phần dư bình phương
lj_vni2 <- Box.test(re_VNI^2,type = 'Ljung-Box', lag = 2)
lj_tl2 <- Box.test(re_TL^2,type = 'Ljung-Box', lag = 2)

#Kiểm định hiệu ứng ARCH
ar_vni <- ArchTest(re_VNI, lags = 2)
ar_tl <- ArchTest(re_TL, lags = 2)

#Trình bày kết quả
test_result <- data.frame(Test = c("ADF","J-B","Q(2)","Q(2)^2", "ARCH(2)"),
                          P_value_VNI = c(adf_vni$p.value, jq_vni$p.value, lj_vni$p.value, lj_vni2$p.value, ar_vni$p.value),
                          P_value_TL = c(adf_tl$p.value, jq_tl$p.value, lj_tl$p.value, lj_tl2$p.value, ar_tl$p.value))
kable(test_result, 
  caption = "Bảng: Kết quả các kiểm định", 
  label = 'Ghi chú: Q (2) and Q2 (2) lần lượt là kiểm định Ljung-Box Q2 cho tương quan chuỗi bậc 2 của phần dư và bình phương phần dư của lợi suất', 
  format = 'pandoc') %>% kable_styling(
            bootstrap_options = c("striped", "hover", "condensed"), 
            full_width = F)
## Warning in kable_styling(., bootstrap_options = c("striped", "hover",
## "condensed"), : Please specify format in kable. kableExtra can customize either
## HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ for details.
Bảng: Kết quả các kiểm định
Test P_value_VNI P_value_TL
ADF 0.0100000 0.0100000
J-B 0.0000000 0.0000000
Q(2) 0.9982569 0.9543091
Q(2)^2 0.0000000 0.0000000
ARCH(2) 0.0000000 0.0000000
pearson <- cor(mhnn$VNI,mhnn$TL, method="pearson")
spearman <- cor(mhnn$VNI,mhnn$TL, method="spearman")
kendall <- cor(mhnn$VNI,mhnn$TL, method="kendall")

#Trình bày kết quả
relat <- data.frame('Tương quan' = 'VNI-STI',
                    Pearson = pearson,
                    spearman = spearman,
                    Kendall = kendall)
kable(relat, 
      col.names = c("Phương pháp", "Pearson", "Spearman","Kendall"),
      caption = "Bảng 4: Kết quả hệ số tương quan",
      format = 'pandoc',
      align = c("l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = FALSE)
## Warning in kable_styling(., bootstrap_options = c("striped", "hover",
## "condensed"), : Please specify format in kable. kableExtra can customize either
## HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ for details.
Bảng 4: Kết quả hệ số tương quan
Phương pháp Pearson Spearman Kendall
VNI-STI 0.3421649 0.2286002 0.1575133

Trực quan hóa hệ số tương quan

# Trực quan hóa hệ số tương quan 
par(mfrow = c(1,2))

corr <- cor(mhnn)
ggcorrplot(corr, hc.order = TRUE,
   outline.col = "white",
   ggtheme = ggplot2::theme_gray,
   colors = c("lightblue", "white", "blue"),
   lab = TRUE, lab_col = 'white',title = 'Hình: Trực quan hóa hệ số tương quan với phương pháp Pearson')

library(PerformanceAnalytics)
chart.Correlation(mhnn, histogram=TRUE, pch=19)
## Warning in par(usr): argument 1 does not name a graphical parameter

Phân tích sự biến động của chuỗi tỷ suất lợi nhuận

par(mfrow = c(1,2))
a11 <- CalculateReturns(data, method = 'log')
ggplot(data, aes(x = Date, y= a11$VNI))+
  geom_line()+
  labs(title = "Hình: Biến động theo ngày của TSLN VNINDEX",x = "Ngày", y="Tỷ suất sinh lợi")+
  theme(plot.title = element_text(hjust = 0.5))
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_line()`).

a22 <- CalculateReturns(data, method = 'log')

ggplot(data, aes(x = Date, y= a22$THAILAN))+
  geom_line()+
  labs(title = "Hình 10: Biến động theo ngày của TSLN Thái Lan",x = "Ngày", y="Tỷ suất sinh lợi")+
  theme(plot.title = element_text(hjust = 0.5))
## Warning: Removed 1 row containing missing values or values outside the scale range
## (`geom_line()`).

Biểu đồ Scatter tỷ suất lợi nhuận

mhnn %>% ggplot(aes(VNI, TL)) +
              geom_point(col = '#BB0000',shape = TRUE) + 
              geom_smooth(method = 'lm',se = T, col = 'lightblue') + #thêm đường hồi quy với phương pháp hồi quy tuyến tính  
              labs(title = 'Hình: Biểu đồ Scatter TSLN của TL và VNI', x = 'VNI', y = ' MSIC TL')
## `geom_smooth()` using formula = 'y ~ x'

Kiểm định cho chuối dữ liệu

# Kiểm định ARMA cho chỉ số VNI
library(forecast)
modeld1<- auto.arima(mhnn$VNI)
modeld1
## Series: mhnn$VNI 
## ARIMA(0,0,2) with non-zero mean 
## 
## Coefficients:
##          ma1     ma2   mean
##       0.1001  0.0859  5e-04
## s.e.  0.0266  0.0266  3e-04
## 
## sigma^2 = 0.0001177:  log likelihood = 4376.02
## AIC=-8744.05   AICc=-8744.02   BIC=-8723.05
# Kiểm định ARMA cho chỉ số MSIC Thailand
library(forecast)
modeld2<- auto.arima(mhnn$TL)
modeld2
## Series: mhnn$TL 
## ARIMA(5,0,2) with zero mean 
## 
## Coefficients:
##           ar1      ar2     ar3     ar4     ar5     ma1     ma2
##       -1.3129  -0.8625  0.0666  0.0759  0.0684  1.2652  0.8382
## s.e.   0.0842   0.1036  0.0496  0.0481  0.0298  0.0795  0.0910
## 
## sigma^2 = 0.000137:  log likelihood = 4270.89
## AIC=-8525.78   AICc=-8525.67   BIC=-8483.77
#Garch(1,1)
#Norm
spec_VNI_ugarch11_norm <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
  mean.model = list(armaOrder = c(1,1), include.mean = TRUE),
  distribution.model = "norm")

VNI_garch11_norm <- ugarchfit(spec = spec_VNI_ugarch11_norm, data = mhnn$VNI)

#Std
spec_VNI_ugarch11_std <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "std")

VNI_garch11_std <- ugarchfit(spec = spec_VNI_ugarch11_std, data = mhnn$VNI)

#Sstd
spec_VNI_ugarch11_sstd <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "sstd")

VNI_garch11_sstd <- ugarchfit(spec = spec_VNI_ugarch11_sstd, data = mhnn$VNI)

#Ged
spec_VNI_ugarch11_ged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "ged")

VNI_garch11_ged <- ugarchfit(spec = spec_VNI_ugarch11_ged, data = mhnn$VNI)

#Sged
spec_VNI_ugarch11_sged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "sged")

VNI_garch11_sged <- ugarchfit(spec = spec_VNI_ugarch11_sged, data = mhnn$VNI)

#Setup garch(1,2) and estimate for VNI coef
#norm
spec_VNI_ugarch12_norm <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 2)),
  mean.model = list(armaOrder = c(1,1), include.mean = TRUE),
  distribution.model = "norm")

VNI_garch12_norm <- ugarchfit(spec = spec_VNI_ugarch12_norm, data = mhnn$VNI)

#std
spec_VNI_ugarch12_std <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "std")

VNI_garch12_std <- ugarchfit(spec = spec_VNI_ugarch12_std, data = mhnn$VNI)

#sstd
spec_VNI_ugarch12_sstd <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "sstd")

VNI_garch12_sstd <- ugarchfit(spec = spec_VNI_ugarch12_sstd, data = mhnn$VNI)

#Ged
spec_VNI_ugarch12_ged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "ged")

VNI_garch12_ged <- ugarchfit(spec = spec_VNI_ugarch12_ged, data = mhnn$VNI)

#Sged
spec_VNI_ugarch12_sged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "sged")

VNI_garch12_sged <- ugarchfit(spec = spec_VNI_ugarch12_sged, data = mhnn$VNI)

#Setup garch(2,1) and estimate for VNI coef
#norm
spec_VNI_ugarch21_norm <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 1)),
  mean.model = list(armaOrder = c(1,1), include.mean = TRUE),
  distribution.model = "norm")

VNI_garch21_norm <- ugarchfit(spec = spec_VNI_ugarch21_norm, data = mhnn$VNI)

#std
spec_VNI_ugarch21_std <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 1)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "std")

VNI_garch21_std <- ugarchfit(spec = spec_VNI_ugarch21_std, data = mhnn$VNI)

#sstd
spec_VNI_ugarch21_sstd <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 1)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "sstd")

VNI_garch21_sstd <- ugarchfit(spec = spec_VNI_ugarch21_sstd, data = mhnn$VNI)

#ged
spec_VNI_ugarch21_ged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 1)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "ged")

VNI_garch21_ged <- ugarchfit(spec = spec_VNI_ugarch21_ged, data = mhnn$VNI)

#sged
spec_VNI_ugarch21_sged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 1)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "sged")

VNI_garch21_sged <- ugarchfit(spec = spec_VNI_ugarch21_sged, data = mhnn$VNI)

#Setup garch(2,2) and estimate for VNI coef
#norm
spec_VNI_ugarch22_norm <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(1,1), include.mean = TRUE),
  distribution.model = "norm")

VNI_garch22_norm <- ugarchfit(spec = spec_VNI_ugarch22_norm, data = mhnn$VNI)

#std
spec_VNI_ugarch22_std <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "std")

VNI_garch22_std <- ugarchfit(spec = spec_VNI_ugarch22_std, data = mhnn$VNI)

#sstd
spec_VNI_ugarch22_sstd <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "sstd")

VNI_garch22_sstd <- ugarchfit(spec = spec_VNI_ugarch22_sstd, data = mhnn$VNI)

#ged
spec_VNI_ugarch22_ged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "ged")

VNI_garch22_ged <- ugarchfit(spec = spec_VNI_ugarch22_ged, data = mhnn$VNI)

#sged
spec_VNI_ugarch22_sged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "sged")

VNI_garch22_sged <- ugarchfit(spec = spec_VNI_ugarch22_sged, data = mhnn$VNI)

#Setup garch(2,2) and estimate for VNI coef
#norm
spec_VNI_ugarch22_norm <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(1,1), include.mean = TRUE),
  distribution.model = "norm")

VNI_garch22_norm <- ugarchfit(spec = spec_VNI_ugarch22_norm, data = mhnn$VNI)

#std
spec_VNI_ugarch22_std <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "std")

VNI_garch22_std <- ugarchfit(spec = spec_VNI_ugarch22_std, data = mhnn$VNI)

#sstd
spec_VNI_ugarch22_sstd <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "sstd")

VNI_garch22_sstd <- ugarchfit(spec = spec_VNI_ugarch22_sstd, data = mhnn$VNI)

#ged
spec_VNI_ugarch22_ged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "ged")

VNI_garch22_ged <- ugarchfit(spec = spec_VNI_ugarch22_ged, data = mhnn$VNI)

#sged
spec_VNI_ugarch22_sged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(1, 1), include.mean = TRUE),
  distribution.model = "sged")

VNI_garch22_sged <- ugarchfit(spec = spec_VNI_ugarch22_sged, data = mhnn$VNI)

#Setup garch(1,1) and estimate for TL coef
#norm
spec_TL_ugarch11_norm <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "norm")

TL_garch11_norm <- ugarchfit(spec = spec_TL_ugarch11_norm, data = mhnn$TL)

#std
spec_TL_ugarch11_std <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "std")

TL_garch11_std <- ugarchfit(spec = spec_TL_ugarch11_std, data = mhnn$TL)

#sstd
spec_TL_ugarch11_sstd <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "sstd")

TL_garch11_sstd <- ugarchfit(spec = spec_TL_ugarch11_sstd, data = mhnn$TL)

#ged
spec_TL_ugarch11_ged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "ged")

TL_garch11_ged <- ugarchfit(spec = spec_TL_ugarch11_ged, data = mhnn$TL)

#sged
spec_TL_ugarch11_sged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 1)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "sged")

TL_garch11_sged <- ugarchfit(spec = spec_TL_ugarch11_sged, data = mhnn$TL)

#Setup garch(1,2) and estimate for TL coef
#norm
spec_TL_ugarch12_norm <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 2)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "norm")

TL_garch12_norm <- ugarchfit(spec = spec_TL_ugarch12_norm, data = mhnn$TL)

#std
spec_TL_ugarch12_std <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 2)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "std")

TL_garch12_std <- ugarchfit(spec = spec_TL_ugarch12_std, data = mhnn$TL)

#sstd
spec_TL_ugarch12_sstd <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 2)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "sstd")

TL_garch12_sstd <- ugarchfit(spec = spec_TL_ugarch12_sstd, data = mhnn$TL)

#ged
spec_TL_ugarch12_ged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 2)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "ged")

TL_garch12_ged <- ugarchfit(spec = spec_TL_ugarch12_ged, data = mhnn$TL)

#sged
spec_TL_ugarch12_sged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(1, 2)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "sged")

TL_garch12_sged <- ugarchfit(spec = spec_TL_ugarch12_sged, data = mhnn$TL)

#Setup garch(2,1) and estimate for TL coef
#norm
spec_TL_ugarch21_norm <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 1)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "norm")

TL_garch21_norm <- ugarchfit(spec = spec_TL_ugarch21_norm, data = mhnn$TL)

#std
spec_TL_ugarch21_std <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 1)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "std")

TL_garch21_std <- ugarchfit(spec = spec_TL_ugarch21_std, data = mhnn$TL)

#sstd
spec_TL_ugarch21_sstd <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 1)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "sstd")

TL_garch21_sstd <- ugarchfit(spec = spec_TL_ugarch21_sstd, data = mhnn$TL)

#ged
spec_TL_ugarch21_ged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 1)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "ged")

TL_garch21_ged <- ugarchfit(spec = spec_TL_ugarch21_ged, data = mhnn$TL)

#sged
spec_TL_ugarch21_sged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 1)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "sged")

TL_garch21_sged <- ugarchfit(spec = spec_TL_ugarch21_sged, data = mhnn$TL)

#Setup garch(2,2) and estimate for TL coef
#norm
spec_TL_ugarch22_norm <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "norm")

TL_garch22_norm <- ugarchfit(spec = spec_TL_ugarch22_norm, data = mhnn$TL)

#std
spec_TL_ugarch22_std <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "std")

TL_garch22_std <- ugarchfit(spec = spec_TL_ugarch22_std, data = mhnn$TL)

#sstd
spec_TL_ugarch22_sstd <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "sstd")

TL_garch22_sstd <- ugarchfit(spec = spec_TL_ugarch22_sstd, data = mhnn$TL)

#ged
spec_TL_ugarch22_ged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "ged")

TL_garch22_ged <- ugarchfit(spec = spec_TL_ugarch22_ged, data = mhnn$TL)

#sged
spec_TL_ugarch22_sged <- ugarchspec(
  variance.model = list(model = "gjrGARCH", garchOrder = c(2, 2)),
  mean.model = list(armaOrder = c(0, 2), include.mean = TRUE),
  distribution.model = "sged")

TL_garch22_sged <- ugarchfit(spec = spec_TL_ugarch22_sged, data = mhnn$TL)

#Choose optimization model for vni coef
VNI.model.list <- list(garch11n = VNI_garch11_norm, garch11t = VNI_garch11_std, garch11st = VNI_garch11_sstd, 
                       garch11g = VNI_garch11_ged, garch11sg = VNI_garch11_sged, 
                       garch12n = VNI_garch12_norm, garch12t = VNI_garch12_std, garch12st = VNI_garch12_sstd, 
                       garch12g = VNI_garch12_ged, garch12sg = VNI_garch12_sged,
                       garch21n = VNI_garch21_norm, garch21t = VNI_garch21_std, garch21st = VNI_garch21_sstd, 
                       garch21g = VNI_garch21_ged, garch21sg = VNI_garch21_sged,
                       garch22n = VNI_garch22_norm, garch22t = VNI_garch22_std, garch22st = VNI_garch22_sstd, 
                       garch22g = VNI_garch22_ged, garch22sg = VNI_garch22_sged
                       ) 

VNI.info.mat <- sapply(VNI.model.list, infocriteria)

rownames(VNI.info.mat) <- rownames(infocriteria(VNI_garch11_norm))

VNI.inds <- which(VNI.info.mat == min(VNI.info.mat[1,]), arr.ind=TRUE) #Lay chi so AIC nho nhat

model.VNI <- colnames(VNI.info.mat)[VNI.inds[,2]]

#Choose optimization model for sti coef
TL.model.list <- list(garch11n = TL_garch11_norm, garch11t = TL_garch11_std, garch11st = TL_garch11_sstd, 
                       garch11g = TL_garch11_ged, garch11sg = TL_garch11_sged, 
                       garch12n = TL_garch12_norm, garch12t = TL_garch12_std, garch12st = TL_garch12_sstd, 
                       garch12g = TL_garch12_ged, garch12sg = TL_garch12_sged,
                       garch21n = TL_garch21_norm, garch21t = TL_garch21_std, garch21st = TL_garch21_sstd, 
                       garch21g = TL_garch21_ged, garch21sg = TL_garch21_sged,
                       garch22n = TL_garch22_norm, garch22t = TL_garch22_std, garch22st = TL_garch22_sstd, 
                       garch22g = TL_garch22_ged, garch22sg = TL_garch22_sged
                       )

TL.info.mat <- sapply(TL.model.list, infocriteria)

rownames(TL.info.mat) <- rownames(infocriteria(TL_garch11_norm))

TL.inds <- which(TL.info.mat == min(TL.info.mat[1,]), arr.ind=TRUE) #Lay chi so AIC nho nhat

model.TL <- colnames(TL.info.mat)[TL.inds[,2]]

Trình bày kết quả dạng mô hình phân phối biên

#Trình bày kết quả
mar_model <- data.frame(
  rate = c("VNI", "TL"),
  Format = c("ARMA(0,0,2)-GJR-GARCH(1,1)-Skewed Student t", "ARMA(5,0,2)-GJR-GARCH(1,1)-Student t"))

# Render the table
kable(mar_model, col.names = c("Tỷ suất sinh lợi", "Dạng mô hình phân phối biên"), 
      caption = "Bảng 5: Mô hình phân phối biên tối ưu", format = "pandoc", 
      table.attr = "style='width:100%;'") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
## Warning in kable_styling(., bootstrap_options = c("striped", "hover",
## "condensed")): Please specify format in kable. kableExtra can customize either
## HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ for details.
Bảng 5: Mô hình phân phối biên tối ưu
Tỷ suất sinh lợi Dạng mô hình phân phối biên
VNI ARMA(0,0,2)-GJR-GARCH(1,1)-Skewed Student t
TL ARMA(5,0,2)-GJR-GARCH(1,1)-Student t

Kết quả mô hình ARMA-GJR-GARCH của chỉ số VNI

# Trình bày các kết quả
extract_garch_results <- function(fit) {
  coef <- coef(fit)
  se <- fit@fit$se.coef
  pvalues <- 2 * (1 - pnorm(abs(fit@fit$tval))) # tính giá trị p từ giá trị t
  results <- cbind(coef, se, pvalues)
  colnames(results) <- c("Estimate", "Std. Error", "Pr(>|z|)")
  return(results)
}

fit1 <- extract_garch_results(VNI_garch11_sstd)
fit2 <- extract_garch_results(TL_garch11_std)

kable(as.data.frame(fit1), 
  caption = "Bảng: Kết quả mô hình ARMA(0,0,2)-GJR-Garch(1,1)-Skewed Student của biến VNI", 
  format = 'pandoc') %>% kable_styling(
            bootstrap_options = c("striped", "hover", "condensed"), 
            full_width = F)
## Warning in kable_styling(., bootstrap_options = c("striped", "hover",
## "condensed"), : Please specify format in kable. kableExtra can customize either
## HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ for details.
Bảng: Kết quả mô hình ARMA(0,0,2)-GJR-Garch(1,1)-Skewed Student của biến VNI
Estimate Std. Error Pr(>|z|)
mu 0.0004793 0.0003330 0.1500560
ar1 0.9368004 0.0446748 0.0000000
ma1 -0.9072217 0.0526405 0.0000000
omega 0.0000044 0.0000012 0.0001559
alpha1 0.0346699 0.0061189 0.0000000
beta1 0.8552800 0.0156780 0.0000000
gamma1 0.1377139 0.0323193 0.0000203
skew 0.8823255 0.0329038 0.0000000
shape 5.2500555 0.6718660 0.0000000

Kết quả mô hình ARMA-GJR-GARCH của chỉ số MSIC Thái Lan

# Trình bày các kết quả
extract_garch_results <- function(fit) {
  coef <- coef(fit)
  se <- fit@fit$se.coef
  pvalues <- 2 * (1 - pnorm(abs(fit@fit$tval))) # tính giá trị p từ giá trị t
  results <- cbind(coef, se, pvalues)
  colnames(results) <- c("Estimate", "Std. Error", "Pr(>|z|)")
  return(results)
}

fit1 <- extract_garch_results(VNI_garch11_sstd)
fit2 <- extract_garch_results(TL_garch11_std)

kable(as.data.frame(fit2), 
  caption = "Bảng: Kết quả mô hình ARMA(5,0,2)-GJR-Garch(1,1)-Student của biến TL", 
  format = 'pandoc') %>% kable_styling(
            bootstrap_options = c("striped", "hover", "condensed"), 
            full_width = F)
## Warning in kable_styling(., bootstrap_options = c("striped", "hover",
## "condensed"), : Please specify format in kable. kableExtra can customize either
## HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ for details.
Bảng: Kết quả mô hình ARMA(5,0,2)-GJR-Garch(1,1)-Student của biến TL
Estimate Std. Error Pr(>|z|)
mu 0.0000508 0.0001929 0.7922457
ma1 -0.0044702 0.0256353 0.8615700
ma2 -0.0054035 0.0255649 0.8326045
omega 0.0000010 0.0000016 0.5286396
alpha1 0.0260499 0.0088047 0.0030899
beta1 0.9246161 0.0203925 0.0000000
gamma1 0.0852088 0.0050326 0.0000000
shape 5.3796013 0.5564032 0.0000000

Kiểm định tính phù hợp của mô hình phân phối biên

# Tính tích phân xác suất cho phần dư của VNI
VNI.res <- residuals(VNI_garch11_sstd) / sigma(VNI_garch11_sstd)  # Phần dư đã được chuẩn hóa

a <- fitdist(distribution = "sstd", VNI.res, control = list())  # Khớp phân phối cho phần dư này

u <- pdist(distribution = "sstd", q = VNI.res, mu = a$pars['mu'], sigma = a$pars['sigma'],
           skew = a$pars['skew'], shape = a$pars['shape'])  # Tính tích phân xác suất

# Tính tích phân xác suất cho phần dư của TL
TL.res <- residuals(TL_garch11_std) / sigma(TL_garch11_std)  # Phần dư đã được chuẩn hóa

b <- fitdist(distribution = "std", TL.res, control = list())  # Khớp phân phối cho phần dư này

v <- pdist(distribution = "std", q = TL.res, mu = b$pars['mu'], sigma = b$pars['sigma'],
           skew = b$pars['skew'], shape = b$pars['shape'])  # Tính tích phân xác suất

# Kiểm định với Anderson-Darling
library(goftest)
ad_vni <- ad.test(u, "punif")
ad_tl <- ad.test(v, "punif")

# Kiểm định Cramer-von Mises
cvm_vni <- cvm.test(u, "punif")
cvm_tl <- cvm.test(v, "punif")

# Kiểm định Kolmogorov-Smirnov
ks_vni <- ks.test(u, "punif")
ks_tl <- ks.test(v, "punif")

# Trình bày kết quả
test <- data.frame(test = c('P_value VNI', 'P_value TL'),
                   AD = c(ad_vni$p.value, ad_tl$p.value),
                   CVM = c(cvm_vni$p.value, cvm_tl$p.value),
                   KS = c(ks_vni$p.value, ks_tl$p.value))

kable(test, 
      caption = "Bảng: Kết quả các kiểm định cho mô hình phân phối biên", 
      col.names = c("Các kiểm định", "Anderson-Darling", "Cramer-von Mises", "Kolmogorov-Smirnov"), 
      format = 'pandoc') %>% kable_styling(
            bootstrap_options = c("striped", "hover", "condensed"), 
            full_width = F)
## Warning in kable_styling(., bootstrap_options = c("striped", "hover",
## "condensed"), : Please specify format in kable. kableExtra can customize either
## HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ for details.
Bảng: Kết quả các kiểm định cho mô hình phân phối biên
Các kiểm định Anderson-Darling Cramer-von Mises Kolmogorov-Smirnov
P_value VNI 0.8290458 0.7483153 0.4891057
P_value TL 0.9608250 0.9951223 0.9992834

Trích xuất phần dư chuỗi

# Trích phần dư chuỗi
# Trích xuất phần dư chuỗi VNI
VNI.res <- residuals(VNI_garch11_sstd)/sigma(VNI_garch11_sstd)
fitdist(distribution = "sstd", VNI.res, control = list())
## $pars
##          mu       sigma        skew       shape 
## 0.004364585 1.000913590 0.884420004 5.221757263 
## 
## $convergence
## [1] 0
## 
## $values
## [1] 2068.772 1932.819 1932.819
## 
## $lagrange
## [1] 0
## 
## $hessian
##             [,1]       [,2]       [,3]      [,4]
## [1,] 1765.942250  260.09164 -499.98369  4.974985
## [2,]  260.091635 1569.46192  146.76419 46.686143
## [3,] -499.983689  146.76419 1174.26730 10.119976
## [4,]    4.974985   46.68614   10.11998  3.355333
## 
## $ineqx0
## NULL
## 
## $nfuneval
## [1] 115
## 
## $outer.iter
## [1] 2
## 
## $elapsed
## Time difference of 0.14062 secs
## 
## $vscale
## [1] 1 1 1 1 1
s = pdist("sstd",VNI.res, mu =0.004364585, sigma =1.000913590 , skew =0.884420004, shape =5.221757263 )
head(s,10)
##  [1] 0.8298124 0.6382865 0.5567212 0.9962126 0.7551382 0.8550152 0.1605119
##  [8] 0.4542302 0.1947739 0.1826931
# Trích suất phần dư chuỗi TL
TL.res <- residuals(TL_garch11_std)/sigma(TL_garch11_std)
fitdist(distribution = "std", TL.res, control = list())
## $pars
##            mu         sigma         shape 
## -5.065177e-05  1.001621e+00  5.347285e+00 
## 
## $convergence
## [1] 0
## 
## $values
## [1] 1951.862 1945.716 1945.716
## 
## $lagrange
## [1] 0
## 
## $hessian
##             [,1]        [,2]      [,3]
## [1,] 1794.103404    9.572421  2.241022
## [2,]    9.572421 1749.550633 47.318537
## [3,]    2.241022   47.318537  3.097759
## 
## $ineqx0
## NULL
## 
## $nfuneval
## [1] 112
## 
## $outer.iter
## [1] 2
## 
## $elapsed
## Time difference of 0.1120169 secs
## 
## $vscale
## [1] 1 1 1 1
d = pdist("std",TL.res, mu =-5.065177e-05 , sigma = 1.001621e+00,  shape =5.347285e+00 )
head(d,10)
##  [1] 0.2095409 0.9485960 0.9386299 0.5360867 0.3214849 0.4160346 0.1273236
##  [8] 0.6414510 0.3163037 0.8632297

Biểu đồ các họ Coupula

library(knitr)
## Warning: package 'knitr' was built under R version 4.3.3
library(copula)
## Warning: package 'copula' was built under R version 4.3.3
## 
## Attaching package: 'copula'
## The following object is masked from 'package:VineCopula':
## 
##     pobs
## The following object is masked from 'package:lubridate':
## 
##     interval
library(ggplot2)
library(plotly)
## Warning: package 'plotly' was built under R version 4.3.3
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
library(gridExtra)
## Warning: package 'gridExtra' was built under R version 4.3.3
## 
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
library(VC2copula)
## Warning: package 'VC2copula' was built under R version 4.3.3
## 
## Attaching package: 'VC2copula'
## The following objects are masked from 'package:VineCopula':
## 
##     BB1Copula, BB6Copula, BB7Copula, BB8Copula, copulaFromFamilyIndex,
##     joeBiCopula, r270BB1Copula, r270BB6Copula, r270BB7Copula,
##     r270BB8Copula, r270ClaytonCopula, r270GumbelCopula,
##     r270JoeBiCopula, r270TawnT1Copula, r270TawnT2Copula, r90BB1Copula,
##     r90BB6Copula, r90BB7Copula, r90BB8Copula, r90ClaytonCopula,
##     r90GumbelCopula, r90JoeBiCopula, r90TawnT1Copula, r90TawnT2Copula,
##     surBB1Copula, surBB6Copula, surBB7Copula, surBB8Copula,
##     surClaytonCopula, surGumbelCopula, surJoeBiCopula, surTawnT1Copula,
##     surTawnT2Copula, tawnT1Copula, tawnT2Copula, vineCopula
library(VineCopula)
library(gridGraphics)
## Warning: package 'gridGraphics' was built under R version 4.3.3
## Loading required package: grid
library(png)
#Tạo hàm vẽ biểu đồ
scatter_plot <- function(random_data, cl) {
  ggplot(data.frame(random_data), aes(random_data[,1], random_data[,2])) +
  geom_point(alpha = 0.5, col = cl) +
  theme_minimal() +
  labs(x = "u", y = "v")
  } #for scatter

persp_plot <- function(copula_obj, file_name, cl) {
  png(file_name)
  persp(copula_obj, dCopula, 
        xlab = 'u', ylab = 'v', col = cl, ltheta = 120,  
        ticktype = "detailed", cex.axis = 0.8)
  dev.off()
  rasterGrob(readPNG(file_name),interpolate = TRUE)
}# for pdf

set.seed(123)
#Mô phỏng copula gauss với p=0.8
cop_nor <- normalCopula(param = 0.8, dim = 2)
#Mô phỏng 7600 quan sát ngẫu nhiên dựa trên copula có sẵn
random_nor <- rCopula(copula = cop_nor,n = 7600)
#Mô phỏng copula với p=0.8
cop_std <- tCopula(param = 0.8, dim = 2, df = 1)
#Mô phỏng 7600 quan sát ngẫu nhiên dựa trên copula có sẵn
random_std <- rCopula(copula = cop_std,n = 7600)

Copula Gauss và Student

#Vẽ biểu đồ 
png('nors.png') #Lưu ảnh biểu đồ
scatter_plot(random_nor, '#99FFCC')
dev.off()
## png 
##   2
nors <- rasterGrob(readPNG('nors.png'), interpolate = TRUE) #Chuyển ảnh sang dạng Grob

png('stds.png')
scatter_plot(random_std, '#CCFF33')
dev.off()
## png 
##   2
stds <- rasterGrob(readPNG('stds.png'), interpolate = TRUE)
nor_per <- persp_plot(cop_nor, 'norp.png', '#99FFCC')
std_per <- persp_plot(cop_std, 'stdp.png', '#CCFF33')

legend <- legendGrob(
  labels = c("Gauss", "Student"), pch = 15,
  gp = gpar(col = c('#99FFCC', '#CCFF33'), fill = c('#99FFCC', '#CCFF33'))
)

grid.arrange(nors, nor_per, stds, std_per, legend, ncol = 3, 
  layout_matrix = rbind(c(1, 2, 5), c(3, 4, 5)),
  widths = c(2, 2, 1), 
  top = textGrob("Hình 1: Biểu đồ phân tán và phối cảnh PDF của Copula họ Elip", 
                 gp = gpar(fontsize = 15, font = 2))
             )

Copula Clayton và Gumbel

set.seed(123)
#Mô phỏng copula clayton với p=4
cop_clay <- claytonCopula(param = 4, dim = 2)
#Mô phỏng 7600 quan sát ngẫu nhiên dựa trên copula có sẵn
random_clay <- rCopula(copula = cop_clay,n = 7600)
#Mô phỏng copula gumbel với p=5
cop_gum <- gumbelCopula(param = 5, dim = 2)
#Mô phỏng 7600 quan sát ngẫu nhiên dựa trên copula có sẵn
random_gum <- rCopula(copula = cop_gum,n = 7600)
#Vẽ biểu đồ 
png('clays.png')
scatter_plot(random_clay,'#CC6633')
dev.off()
## png 
##   2
clays <- rasterGrob(readPNG('clays.png'), interpolate = TRUE)

png('gums.png')
scatter_plot(random_gum,'#FF6699')
dev.off()
## png 
##   2
gums <- rasterGrob(readPNG('gums.png'), interpolate = TRUE)
clayp <- persp_plot(cop_clay,'clayp.png','#CC6633')

gump <- persp_plot(cop_gum,'gump.png','#FF6699')


legend <- legendGrob(
  labels = c("Clayton", "Gumbel"), pch = 15,
  gp = gpar(col = c('#CC6633', '#FF6699'), fill = c('#CC6633', '#FF6699'))
)

grid.arrange(clays, clayp, gums, gump, legend, ncol = 3, 
  layout_matrix = rbind(c(1, 2, 5), c(3, 4, 5)),
  widths = c(2, 2, 1), 
  top = textGrob("Hình 2: Biểu đồ phân tán và PDF của Copula Clayton và Gumbel", 
                 gp = gpar(fontsize = 15, font = 2))
             )

set.seed(123)
#Mô phỏng copula survival gumbel
cop_surgum <- VC2copula::surGumbelCopula(param = 5)
#Mô phỏng 7600 quan sát ngẫu nhiên dựa trên copula có sẵn
random_surgum <- rCopula(copula = cop_surgum,n = 7600)
#Mô phỏng copula survival clayton  với p=4
cop_surclay <- VC2copula::surClaytonCopula(param = 4)
#Mô phỏng 7600 quan sát ngẫu nhiên dựa trên copula có sẵn
random_surclay <- rCopula(copula = cop_surclay,n = 7600)
png('surclays.png')
scatter_plot(random_surclay,'#9966FF')
dev.off()
## png 
##   2
surclays <- rasterGrob(readPNG('surclays.png'), interpolate = TRUE)

png('surgums.png')
scatter_plot(random_surgum,'#FF3300')
dev.off()
## png 
##   2
surgums <- rasterGrob(readPNG('surgums.png'), interpolate = TRUE)
surclayp <- persp_plot(cop_surclay, "surclayp.png","#9966FF")
surgump <- persp_plot(cop_surgum, "surgump.png","#FF3300")

legend <- legendGrob(labels = c("Survival Clayton","Survival Gumbel"), pch = 15,
                    gp = gpar(col = c('#9966FF','#FF3300'), fill = c('#9966FF','#FF3300' )))

grid.arrange(surclays, surclayp,surgums, surgump, legend, ncol = 3,
             layout_matrix = rbind(c(1,2,5),c(3,4,5)),
             widths = c(2,2,1),
             top = textGrob("Hình 3: Biểu đồ phân tán và PDF của Copula Sur Clayton và Gumbel", 
                 gp = gpar(fontsize = 15, font = 2))
             )

Copula Franl và Joe

set.seed(123)
#Mô phỏng copula Frank
cop_frank <- frankCopula(param = 9.2)
#Mô phỏng 7600 quan sát ngẫu nhiên dựa trên copula có sẵn
random_frank <- rCopula(copula = cop_frank,n = 7600)
#Mô phỏng copula survival clayton  với p=4
cop_joe <- joeCopula(param = 3)
#Mô phỏng 7600 quan sát ngẫu nhiên dựa trên copula có sẵn
random_joe <- rCopula(copula = cop_joe,n = 7600)
png('franks.png')
scatter_plot(random_frank,'#FFCCFF')
dev.off()
## png 
##   2
franks <- rasterGrob(readPNG('franks.png'), interpolate = TRUE)

png('joes.png')
scatter_plot(random_joe,'#FFCC66')
dev.off()
## png 
##   2
joes <- rasterGrob(readPNG('joes.png'), interpolate = TRUE)
frankp <- persp_plot(cop_frank, "frankp.png","#FFCCFF")
joep <- persp_plot(cop_joe, "joep.png","#FFCC66")

legend <- legendGrob(labels = c("Franl","Joe"), pch = 15,
                    gp = gpar(col = c('#FFCCFF','#FFCC66'), fill = c('#FFCCFF','#FFCC66')))

grid.arrange(franks, frankp,joes, joep, legend, ncol = 3,
             layout_matrix = rbind(c(1,2,5),c(3,4,5)),
             widths = c(2,2,1),
             top = textGrob("Hình 4: Biểu đồ phân tán và  PDF của Copula Franl và Joe", 
                 gp = gpar(fontsize = 15, font = 2))
             )

#Lựa chọn và ước lượng
opt_cop <- BiCopSelect(u,v,selectioncrit = "AIC",method = "mle")
est_opt_cop <- BiCopEst(u,v,family = opt_cop$family,method = "mle",max.df = 30)

#Trình bày kết quả
est_opt_cop_dt <- data.frame(mqh = c('VNI-TL'),
                    Copula = est_opt_cop$familyname,
                    Thamso = est_opt_cop$par,
                  Thamso2 = est_opt_cop$par2,
                   duoiduoi = est_opt_cop$taildep$lower,
                  duoitren = est_opt_cop$taildep$upper,
                  tau = est_opt_cop$tau,
                  aic = est_opt_cop$AIC,
                  bic = est_opt_cop$BIC)

kable(est_opt_cop_dt, 
  caption = "Bảng 9: Kết quả ước lượng mô hình Copula tối ưu", col.names = c("Chỉ số","Copula", "Par","Par2", "Đuôi dưới", "Đuôi trên","Hệ số Kendall", "AIC","BIC"), 
  format = 'pandoc') %>% kable_styling(
            bootstrap_options = c("striped", "hover", "condensed"), 
            full_width = F)
## Warning in kable_styling(., bootstrap_options = c("striped", "hover",
## "condensed"), : Please specify format in kable. kableExtra can customize either
## HTML or LaTeX outputs. See https://haozhu233.github.io/kableExtra/ for details.
Bảng 9: Kết quả ước lượng mô hình Copula tối ưu
Chỉ số Copula Par Par2 Đuôi dưới Đuôi trên Hệ số Kendall AIC BIC
VNI-TL Survival Gumbel 1.177716 0 0.1986219 0 0.150899 -117.4945 -112.2438

Phối cảnh PDF theo chuỗi dữ liệu phân

persp(VC2copula::BB7Copula(param = c(est_opt_cop$par, est_opt_cop$par2)),dCopula, 
        xlab = 'u', ylab = 'v', col = 'lightblue', ltheta = 120,  
        ticktype = "detailed", cex.axis = 0.8,  main = 'Hình 13: Phối cảnh PDF của mô hình Copula Gumbel')

set.seed(123)

# Tham số cho copula Gumbel (ví dụ với theta = 2)
theta_gumbel <- 2

# Tạo copula Gumbel
cop_gumbel <- gumbelCopula(param = theta_gumbel, dim = 2)

# Mô phỏng dữ liệu từ copula Gumbel
sample_size <- 500  # Kích thước mẫu
sample_gumbel <- rCopula(sample_size, cop_gumbel)

# Hiển thị một số mẫu của copula Gumbel
head(sample_gumbel)
##            [,1]       [,2]
## [1,] 0.08097408 0.04203784
## [2,] 0.87624894 0.98004472
## [3,] 0.45315700 0.48634119
## [4,] 0.95903035 0.81314647
## [5,] 0.71034376 0.88160340
## [6,] 0.82655551 0.38809806

Phân phối mật độ xác suất của Copula Gumbel

set.seed(123)

# Tham số cho copula Gumbel
theta_gumbel <- 2

# Tạo copula Gumbel
cop_gumbel <- gumbelCopula(param = theta_gumbel, dim = 2)

# Mô phỏng dữ liệu từ copula Gumbel
sample_size <- 500
sample_gumbel <- rCopula(sample_size, cop_gumbel)

# Tạo lưới điểm để tính toán mật độ
x_seq <- seq(0, 1, length.out = 30)
y_seq <- seq(0, 1, length.out = 30)
grid <- expand.grid(x = x_seq, y = y_seq)

# Tính toán mật độ của copula Gumbel cho lưới điểm
pdf_values <- apply(grid, 1, function(p) {
  dCopula(p, cop_gumbel)
})
pdf_matrix <- matrix(pdf_values, nrow = length(x_seq), ncol = length(y_seq))

# Vẽ biểu đồ 3D của phân phối mật độ xác suất
plot_ly(z = pdf_matrix, x = x_seq, y = y_seq, type = "surface") %>%
  layout(title = "Phân phối mật độ xác suất của Copula Gumbel",
         scene = list(
           xaxis = list(title = "X"),
           yaxis = list(title = "Y"),
           zaxis = list(title = "Tỷ trọng ")
         ))

Đồ thị mật độ Gumbel Copula

library(ggplot2)
# Tạo đối tượng copula Gumbel
gumbel_copula <- copula::gumbelCopula(param = 1.18)

df <- data.frame(u = s, k = d)

# Vẽ đồ thị mật độ
ggplot(df, aes(x = u, y = k)) +
  geom_point(alpha = 0.5) +
  geom_density_2d() +
  labs(title = "Đồ thị mật độ Gumbel Copula",
       x = "u",
       y = "k") +
  theme_minimal()

# Tải các thư viện cần thiết
library(copula)
library(MASS)
## 
## Attaching package: 'MASS'
## The following object is masked from 'package:plotly':
## 
##     select
## The following object is masked from 'package:dplyr':
## 
##     select
library(scatterplot3d)

# Định nghĩa tham số cho copula Gumbel
theta <- 1.18

# Tạo đối tượng copula Gumbel
gumbel_copula <- gumbelCopula(param = theta)

# Dữ liệu ví dụ cho kde2d (thay thế cd bằng dữ liệu thực của bạn)
set.seed(123)
cd <- cbind(rnorm(1000), rnorm(1000))

# Thực hiện ước lượng mật độ kernel
kde2d_result <- kde2d(cd[,1], cd[,2], n = 50)

# Chuyển đổi kết quả kde2d thành định dạng phù hợp với scatterplot3d
x <- kde2d_result$x
y <- kde2d_result$y
z <- kde2d_result$z

# Tạo lưới điểm cho scatterplot3d
grid <- expand.grid(x = x, y = y)

# Làm phẳng z cho scatterplot3d
z_flat <- as.vector(t(z))

# Đảm bảo grid và z_flat có cùng độ dài
if (length(z_flat) != nrow(grid)) {
  stop("Độ dài của z_flat không khớp với số lượng điểm trong grid")
}

# Vẽ đồ thị mật độ sử dụng scatterplot3d
scatterplot3d(grid$x, grid$y, z_flat, type = "h", angle = 30, 
              main = "Biểu đồ Mật độ của Copula Gumbel",
              xlab = "Rainfall Depth", 
              ylab = "Shot Duration", 
              zlab = "Phân phối hai biến",
              pch = 20, color = "turquoise")

LS0tDQp0aXRsZTogIk3DtCBow6xuaCBuZ+G6q3Ugbmhpw6puIg0KYXV0aG9yOiAiVOG6oSBDw7RuZyDEkOG6oXQiDQpkYXRlOiAiMjAyNC0wOC0wOSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIHRvY19kZXB0aDogMg0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIHRvYzogdHJ1ZQ0KICB3b3JkX2RvY3VtZW50Og0KICAgICB0b2M6IHRydWUNCiAgICAgdG9jX2RlcHRoOiAnMicNCiAgcGRmX2RvY3VtZW50Og0KICAgIGxhdGV4X2VuZ2luZTogeGVsYXRleA0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoNCiMgVHLDrWNoIHh14bqldCBk4buvIGxp4buHdQ0KDQpgYGB7cn0NCiMgTG9hZCBjw6FjIHBhY2thZ2UgY+G6p24gdGhp4bq/dCANCmxpYnJhcnkoeGxzeCkgDQpsaWJyYXJ5KHF1YW50bW9kKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHh0cykNCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KbGlicmFyeShydWdhcmNoKQ0KbGlicmFyeShnb2Z0ZXN0KQ0KbGlicmFyeShWaW5lQ29wdWxhKQ0KbGlicmFyeSh0c2VyaWVzKQ0KbGlicmFyeShGaW5UUykNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KGdnY29ycnBsb3QpDQojIE5o4bqtcCBk4buvIGxp4buHdSANCmRhdGEgPC0gcmVhZC54bHN4KCJDOi9Vc2Vycy9BRE1JTi9EZXNrdG9wL01ITk4vZHVsaWV1Y2QxLnhsc3giLCBzaGVldEluZGV4ID0gMSwgaGVhZGVyID0gVCkNCmBgYA0KDQojIFThu7cgc3XhuqV0IGzhu6NpIG5odeG6rW4gdGhlbyBjaHXhu5dpIGRhdGENCg0KYGBge3J9DQojIFTDrW5oIHThu7cgc3XhuqV0IGzhu6NpIG5odeG6rW4gdGhlbyBjw7RuZyB0aOG7qWMgbG9nKHQpLWxvZyh0LTEpDQpsZ3ZuPC0gZGlmZihsb2coZGF0YSRWTkkpLCBsYWcgPSAxKQ0KbGd0bDwtIGRpZmYobG9nKGRhdGEkVEhBSUxBTiksIGxhZyA9IDEpDQptaG5uIDwtIGRhdGEuZnJhbWUoVk5JPSBsZ3ZuLCBUTCA9IGxndGwpDQpgYGANCg0KIyMgVGjhu5FuZyBrw6ogbcO0IHThuqMgDQpgYGB7cn0NCmxpYnJhcnkobW9tZW50cykNCmxpYnJhcnkoa2FibGVFeHRyYSkNCmxpYnJhcnkoZHBseXIpDQptaG5uX2RmIDwtIGFzLmRhdGEuZnJhbWUobWhubikNCmEgPC0gbWhubl9kZiAlPiUgc3VtbWFyaXNlKE1pbiA9IG1pbihWTkkpLA0KICAgICAgICAgICAgICAgICAgICAgIE1heCA9IG1heChWTkkpLA0KICAgICAgICAgICAgICAgICAgICAgIE1lYW4gPSBtZWFuKFZOSSksDQogICAgICAgICAgICAgICAgICAgICAgU3REZXYgPSBzZChWTkkpLA0KICAgICAgICAgICAgICAgICAgICAgIFNrZXduZXNzID0gc2tld25lc3MoVk5JKSwNCiAgICAgICAgICAgICAgICAgICAgICBLdXJ0b3NpcyA9IGt1cnRvc2lzKFZOSSkpDQpiIDwtIG1obm5fZGYgJT4lIHN1bW1hcmlzZShNaW4gPSBtaW4oVEwpLA0KICAgICAgICAgICAgICAgICAgICAgIE1heCA9IG1heChUTCksDQogICAgICAgICAgICAgICAgICAgICAgTWVhbiA9IG1lYW4oVEwpLA0KICAgICAgICAgICAgICAgICAgICAgIFN0RGV2ID0gc2QoVEwpLA0KICAgICAgICAgICAgICAgICAgICAgIFNrZXduZXNzID0gc2tld25lc3MoVEwpLA0KICAgICAgICAgICAgICAgICAgICAgIEt1cnRvc2lzID0ga3VydG9zaXMoVEwpKQ0KbSA8LSByYmluZChhLGIpDQpyb3duYW1lcyhtKSA8LSBjKCdWTkknLCdUTCcpDQprYWJsZShtLCBmb3JtYXQgPSAncGFuZG9jJywgY2FwdGlvbiA9ICdC4bqjbmc6IFRo4buRbmcga8OqIG3DtCB04bqjIGNodeG7l2kgVFNMTicsIHRhYmxlLmF0dHIgPSAic3R5bGU9J3dpZHRoOjEwMCU7JyIpICU+JSBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSkNCmBgYA0KDQojIyDEkOG7kyB0aOG7iyBCb3gtUGxvdA0KDQpgYGB7cn0NCiMgQmnhu4N1IMSR4buTIEJveC1wbG90DQpwaXZvdF9sb25nZXIobWhubl9kZiwgY29scyA9IGV2ZXJ5dGhpbmcoKSwgbmFtZXNfdG8gPSAiVFNMTiIsIHZhbHVlc190byA9ICJWYWx1ZSIpICU+JSBnZ3Bsb3QoYWVzKHggPSBUU0xOLCB5ID0gVmFsdWUpKSArDQogIGdlb21fYm94cGxvdChmaWxsID0gImN5YW4iLCBjb2xvciA9ICJibGFjayIpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgbGFicyh0aXRsZSA9ICJIw6xuaDogQmnhu4N1IMSR4buTIGjhu5lwIGPhu6dhIFRTTE4gVk5JIHbDoCBUTCIsDQogICAgICAgeCA9ICJDaOG7iSBz4buRIiwNCiAgICAgICB5ID0gIlThu7cgc3XhuqV0IHNpbmggbOG7o2kiKQ0KYGBgDQoNCiMgQ8OhYyBraeG7g20gxJHhu4tuaCBj4bqnbiB0aGnhur90DQoNCg0KYGBge3J9DQpsaWJyYXJ5KHRzZXJpZXMpDQojIEPDoWMga2nhu4NtIMSR4buLbmggDQojS2nhu4NtIMSR4buLbmggdMOtbmggZOG7q25nDQphZGZfdm5pIDwtIGFkZi50ZXN0KG1obm4kVk5JKQ0KYWRmX3RsIDwtIGFkZi50ZXN0KG1obm4kVEwpDQojS2nhu4NtIMSR4buLbmggcGjDom4gcGjhu5FpIGNodeG6qW4NCmpxX3ZuaSA8LSBqYXJxdWUuYmVyYS50ZXN0KG1obm4kVk5JKQ0KanFfdGwgPC0gamFycXVlLmJlcmEudGVzdChtaG5uJFRMKQ0KIyDGr+G7m2MgbMaw4bujbmcgdsOgIHRyw61jaCB4deG6pXQgcGjhuqduIGTGsCB04burIG3DtCBow6xuaCBBUk1BIHThu5FpIMawdQ0KYXJpbWFfVk5JIDwtIGF1dG9hcmZpbWEobWhubiRWTkksYXIubWF4ID0gMiwgbWEubWF4ID0gMiwgY3JpdGVyaW9uID0gJ0FJQycsIG1ldGhvZCA9ICJmdWxsIikNCg0KYXJpbWFfdGwgPC0gYXV0b2FyZmltYShtaG5uJFRMLGFyLm1heCA9IDIsIG1hLm1heCA9IDIsIGNyaXRlcmlvbiA9ICdBSUMnLCBtZXRob2QgPSAiZnVsbCIpDQoNCnJlX1ZOSSA8LSBhcmltYV9WTkkkZml0QGZpdCRyZXNpZHVhbHMNCnJlX1RMIDwtIGFyaW1hX3RsJGZpdEBmaXQkcmVzaWR1YWxzDQojS2nhu4NtIMSR4buLbmggdMawxqFuZyBxdWFuIGNodeG7l2kgYuG6rWMgMiBjaG8gcGjhuqduIGTGsA0KbGpfdm5pIDwtIEJveC50ZXN0KHJlX1ZOSSx0eXBlID0gJ0xqdW5nLUJveCcsIGxhZyA9IDIpDQpsal90bCA8LSBCb3gudGVzdChyZV9UTCx0eXBlID0gJ0xqdW5nLUJveCcsIGxhZyA9IDIpDQoNCiNLaeG7g20gxJHhu4tuaCB0xrDGoW5nIHF1YW4gY2h14buXaSBi4bqtYyAyIGNobyBwaOG6p24gZMawIGLDrG5oIHBoxrDGoW5nDQpsal92bmkyIDwtIEJveC50ZXN0KHJlX1ZOSV4yLHR5cGUgPSAnTGp1bmctQm94JywgbGFnID0gMikNCmxqX3RsMiA8LSBCb3gudGVzdChyZV9UTF4yLHR5cGUgPSAnTGp1bmctQm94JywgbGFnID0gMikNCg0KI0tp4buDbSDEkeG7i25oIGhp4buHdSDhu6luZyBBUkNIDQphcl92bmkgPC0gQXJjaFRlc3QocmVfVk5JLCBsYWdzID0gMikNCmFyX3RsIDwtIEFyY2hUZXN0KHJlX1RMLCBsYWdzID0gMikNCg0KI1Ryw6xuaCBiw6B5IGvhur90IHF14bqjDQp0ZXN0X3Jlc3VsdCA8LSBkYXRhLmZyYW1lKFRlc3QgPSBjKCJBREYiLCJKLUIiLCJRKDIpIiwiUSgyKV4yIiwgIkFSQ0goMikiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgUF92YWx1ZV9WTkkgPSBjKGFkZl92bmkkcC52YWx1ZSwganFfdm5pJHAudmFsdWUsIGxqX3ZuaSRwLnZhbHVlLCBsal92bmkyJHAudmFsdWUsIGFyX3ZuaSRwLnZhbHVlKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgUF92YWx1ZV9UTCA9IGMoYWRmX3RsJHAudmFsdWUsIGpxX3RsJHAudmFsdWUsIGxqX3RsJHAudmFsdWUsIGxqX3RsMiRwLnZhbHVlLCBhcl90bCRwLnZhbHVlKSkNCmthYmxlKHRlc3RfcmVzdWx0LCANCiAgY2FwdGlvbiA9ICJC4bqjbmc6IEvhur90IHF14bqjIGPDoWMga2nhu4NtIMSR4buLbmgiLCANCiAgbGFiZWwgPSAnR2hpIGNow7o6IFEgKDIpIGFuZCBRMiAoMikgbOG6p24gbMaw4bujdCBsw6Aga2nhu4NtIMSR4buLbmggTGp1bmctQm94IFEyIGNobyB0xrDGoW5nIHF1YW4gY2h14buXaSBi4bqtYyAyIGPhu6dhIHBo4bqnbiBkxrAgdsOgIGLDrG5oIHBoxrDGoW5nIHBo4bqnbiBkxrAgY+G7p2EgbOG7o2kgc3XhuqV0JywgDQogIGZvcm1hdCA9ICdwYW5kb2MnKSAlPiUga2FibGVfc3R5bGluZygNCiAgICAgICAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgDQogICAgICAgICAgICBmdWxsX3dpZHRoID0gRikNCg0KYGBgDQoNCg0KDQpgYGB7cn0NCnBlYXJzb24gPC0gY29yKG1obm4kVk5JLG1obm4kVEwsIG1ldGhvZD0icGVhcnNvbiIpDQpzcGVhcm1hbiA8LSBjb3IobWhubiRWTkksbWhubiRUTCwgbWV0aG9kPSJzcGVhcm1hbiIpDQprZW5kYWxsIDwtIGNvcihtaG5uJFZOSSxtaG5uJFRMLCBtZXRob2Q9ImtlbmRhbGwiKQ0KDQojVHLDrG5oIGLDoHkga+G6v3QgcXXhuqMNCnJlbGF0IDwtIGRhdGEuZnJhbWUoJ1TGsMahbmcgcXVhbicgPSAnVk5JLVNUSScsDQogICAgICAgICAgICAgICAgICAgIFBlYXJzb24gPSBwZWFyc29uLA0KICAgICAgICAgICAgICAgICAgICBzcGVhcm1hbiA9IHNwZWFybWFuLA0KICAgICAgICAgICAgICAgICAgICBLZW5kYWxsID0ga2VuZGFsbCkNCmthYmxlKHJlbGF0LCANCiAgICAgIGNvbC5uYW1lcyA9IGMoIlBoxrDGoW5nIHBow6FwIiwgIlBlYXJzb24iLCAiU3BlYXJtYW4iLCJLZW5kYWxsIiksDQogICAgICBjYXB0aW9uID0gIkLhuqNuZyA0OiBL4bq/dCBxdeG6oyBo4buHIHPhu5EgdMawxqFuZyBxdWFuIiwNCiAgICAgIGZvcm1hdCA9ICdwYW5kb2MnLA0KICAgICAgYWxpZ24gPSBjKCJsIiwgImMiLCAiYyIpKSAlPiUNCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIGZ1bGxfd2lkdGggPSBGQUxTRSkNCg0KYGBgDQoNCiMjIFRy4buxYyBxdWFuIGjDs2EgaOG7hyBz4buRIHTGsMahbmcgcXVhbg0KDQpgYGB7cn0NCiMgVHLhu7FjIHF1YW4gaMOzYSBo4buHIHPhu5EgdMawxqFuZyBxdWFuIA0KcGFyKG1mcm93ID0gYygxLDIpKQ0KDQpjb3JyIDwtIGNvcihtaG5uKQ0KZ2djb3JycGxvdChjb3JyLCBoYy5vcmRlciA9IFRSVUUsDQogICBvdXRsaW5lLmNvbCA9ICJ3aGl0ZSIsDQogICBnZ3RoZW1lID0gZ2dwbG90Mjo6dGhlbWVfZ3JheSwNCiAgIGNvbG9ycyA9IGMoImxpZ2h0Ymx1ZSIsICJ3aGl0ZSIsICJibHVlIiksDQogICBsYWIgPSBUUlVFLCBsYWJfY29sID0gJ3doaXRlJyx0aXRsZSA9ICdIw6xuaDogVHLhu7FjIHF1YW4gaMOzYSBo4buHIHPhu5EgdMawxqFuZyBxdWFuIHbhu5tpIHBoxrDGoW5nIHBow6FwIFBlYXJzb24nKQ0KYGBgDQoNCg0KYGBge3J9DQpsaWJyYXJ5KFBlcmZvcm1hbmNlQW5hbHl0aWNzKQ0KY2hhcnQuQ29ycmVsYXRpb24obWhubiwgaGlzdG9ncmFtPVRSVUUsIHBjaD0xOSkNCmBgYA0KDQoNCg0KIyMgUGjDom4gdMOtY2ggc+G7sSBiaeG6v24gxJHhu5luZyBj4bunYSBjaHXhu5dpIHThu7cgc3XhuqV0IGzhu6NpIG5odeG6rW4NCmBgYHtyfQ0KcGFyKG1mcm93ID0gYygxLDIpKQ0KYTExIDwtIENhbGN1bGF0ZVJldHVybnMoZGF0YSwgbWV0aG9kID0gJ2xvZycpDQpnZ3Bsb3QoZGF0YSwgYWVzKHggPSBEYXRlLCB5PSBhMTEkVk5JKSkrDQogIGdlb21fbGluZSgpKw0KICBsYWJzKHRpdGxlID0gIkjDrG5oOiBCaeG6v24gxJHhu5luZyB0aGVvIG5nw6B5IGPhu6dhIFRTTE4gVk5JTkRFWCIseCA9ICJOZ8OgeSIsIHk9IlThu7cgc3XhuqV0IHNpbmggbOG7o2kiKSsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpDQpgYGANCg0KDQoNCmBgYHtyfQ0KYTIyIDwtIENhbGN1bGF0ZVJldHVybnMoZGF0YSwgbWV0aG9kID0gJ2xvZycpDQoNCmdncGxvdChkYXRhLCBhZXMoeCA9IERhdGUsIHk9IGEyMiRUSEFJTEFOKSkrDQogIGdlb21fbGluZSgpKw0KICBsYWJzKHRpdGxlID0gIkjDrG5oIDEwOiBCaeG6v24gxJHhu5luZyB0aGVvIG5nw6B5IGPhu6dhIFRTTE4gVGjDoWkgTGFuIix4ID0gIk5nw6B5IiwgeT0iVOG7tyBzdeG6pXQgc2luaCBs4bujaSIpKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCmBgYA0KDQojIyBCaeG7g3UgxJHhu5MgU2NhdHRlciB04bu3IHN14bqldCBs4bujaSBuaHXhuq1uIA0KDQpgYGB7cn0NCm1obm4gJT4lIGdncGxvdChhZXMoVk5JLCBUTCkpICsNCiAgICAgICAgICAgICAgZ2VvbV9wb2ludChjb2wgPSAnI0JCMDAwMCcsc2hhcGUgPSBUUlVFKSArIA0KICAgICAgICAgICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nLHNlID0gVCwgY29sID0gJ2xpZ2h0Ymx1ZScpICsgI3Row6ptIMSRxrDhu51uZyBo4buTaSBxdXkgduG7m2kgcGjGsMahbmcgcGjDoXAgaOG7k2kgcXV5IHR1eeG6v24gdMOtbmggIA0KICAgICAgICAgICAgICBsYWJzKHRpdGxlID0gJ0jDrG5oOiBCaeG7g3UgxJHhu5MgU2NhdHRlciBUU0xOIGPhu6dhIFRMIHbDoCBWTkknLCB4ID0gJ1ZOSScsIHkgPSAnIE1TSUMgVEwnKQ0KYGBgDQoNCg0KIyBLaeG7g20gxJHhu4tuaCBjaG8gY2h14buRaSBk4buvIGxp4buHdSAgDQoNCmBgYHtyfQ0KIyBLaeG7g20gxJHhu4tuaCBBUk1BIGNobyBjaOG7iSBz4buRIFZOSQ0KbGlicmFyeShmb3JlY2FzdCkNCm1vZGVsZDE8LSBhdXRvLmFyaW1hKG1obm4kVk5JKQ0KbW9kZWxkMQ0KYGBgDQpgYGB7cn0NCiMgS2nhu4NtIMSR4buLbmggQVJNQSBjaG8gY2jhu4kgc+G7kSBNU0lDIFRoYWlsYW5kDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KbW9kZWxkMjwtIGF1dG8uYXJpbWEobWhubiRUTCkNCm1vZGVsZDINCmBgYA0KIA0KYGBge3J9DQojR2FyY2goMSwxKQ0KI05vcm0NCnNwZWNfVk5JX3VnYXJjaDExX25vcm0gPC0gdWdhcmNoc3BlYygNCiAgdmFyaWFuY2UubW9kZWwgPSBsaXN0KG1vZGVsID0gImdqckdBUkNIIiwgZ2FyY2hPcmRlciA9IGMoMSwgMSkpLA0KICBtZWFuLm1vZGVsID0gbGlzdChhcm1hT3JkZXIgPSBjKDEsMSksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAibm9ybSIpDQoNClZOSV9nYXJjaDExX25vcm0gPC0gdWdhcmNoZml0KHNwZWMgPSBzcGVjX1ZOSV91Z2FyY2gxMV9ub3JtLCBkYXRhID0gbWhubiRWTkkpDQoNCiNTdGQNCnNwZWNfVk5JX3VnYXJjaDExX3N0ZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygxLCAxKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMSwgMSksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic3RkIikNCg0KVk5JX2dhcmNoMTFfc3RkIDwtIHVnYXJjaGZpdChzcGVjID0gc3BlY19WTklfdWdhcmNoMTFfc3RkLCBkYXRhID0gbWhubiRWTkkpDQoNCiNTc3RkDQpzcGVjX1ZOSV91Z2FyY2gxMV9zc3RkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDEsIDEpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygxLCAxKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJzc3RkIikNCg0KVk5JX2dhcmNoMTFfc3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVk5JX3VnYXJjaDExX3NzdGQsIGRhdGEgPSBtaG5uJFZOSSkNCg0KI0dlZA0Kc3BlY19WTklfdWdhcmNoMTFfZ2VkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDEsIDEpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygxLCAxKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJnZWQiKQ0KDQpWTklfZ2FyY2gxMV9nZWQgPC0gdWdhcmNoZml0KHNwZWMgPSBzcGVjX1ZOSV91Z2FyY2gxMV9nZWQsIGRhdGEgPSBtaG5uJFZOSSkNCg0KI1NnZWQNCnNwZWNfVk5JX3VnYXJjaDExX3NnZWQgPC0gdWdhcmNoc3BlYygNCiAgdmFyaWFuY2UubW9kZWwgPSBsaXN0KG1vZGVsID0gImdqckdBUkNIIiwgZ2FyY2hPcmRlciA9IGMoMSwgMSkpLA0KICBtZWFuLm1vZGVsID0gbGlzdChhcm1hT3JkZXIgPSBjKDEsIDEpLCBpbmNsdWRlLm1lYW4gPSBUUlVFKSwNCiAgZGlzdHJpYnV0aW9uLm1vZGVsID0gInNnZWQiKQ0KDQpWTklfZ2FyY2gxMV9zZ2VkIDwtIHVnYXJjaGZpdChzcGVjID0gc3BlY19WTklfdWdhcmNoMTFfc2dlZCwgZGF0YSA9IG1obm4kVk5JKQ0KDQojU2V0dXAgZ2FyY2goMSwyKSBhbmQgZXN0aW1hdGUgZm9yIFZOSSBjb2VmDQojbm9ybQ0Kc3BlY19WTklfdWdhcmNoMTJfbm9ybSA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygxLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMSwxKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJub3JtIikNCg0KVk5JX2dhcmNoMTJfbm9ybSA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVk5JX3VnYXJjaDEyX25vcm0sIGRhdGEgPSBtaG5uJFZOSSkNCg0KI3N0ZA0Kc3BlY19WTklfdWdhcmNoMTJfc3RkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDEsIDIpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygxLCAxKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJzdGQiKQ0KDQpWTklfZ2FyY2gxMl9zdGQgPC0gdWdhcmNoZml0KHNwZWMgPSBzcGVjX1ZOSV91Z2FyY2gxMl9zdGQsIGRhdGEgPSBtaG5uJFZOSSkNCg0KI3NzdGQNCnNwZWNfVk5JX3VnYXJjaDEyX3NzdGQgPC0gdWdhcmNoc3BlYygNCiAgdmFyaWFuY2UubW9kZWwgPSBsaXN0KG1vZGVsID0gImdqckdBUkNIIiwgZ2FyY2hPcmRlciA9IGMoMSwgMikpLA0KICBtZWFuLm1vZGVsID0gbGlzdChhcm1hT3JkZXIgPSBjKDEsIDEpLCBpbmNsdWRlLm1lYW4gPSBUUlVFKSwNCiAgZGlzdHJpYnV0aW9uLm1vZGVsID0gInNzdGQiKQ0KDQpWTklfZ2FyY2gxMl9zc3RkIDwtIHVnYXJjaGZpdChzcGVjID0gc3BlY19WTklfdWdhcmNoMTJfc3N0ZCwgZGF0YSA9IG1obm4kVk5JKQ0KDQojR2VkDQpzcGVjX1ZOSV91Z2FyY2gxMl9nZWQgPC0gdWdhcmNoc3BlYygNCiAgdmFyaWFuY2UubW9kZWwgPSBsaXN0KG1vZGVsID0gImdqckdBUkNIIiwgZ2FyY2hPcmRlciA9IGMoMSwgMikpLA0KICBtZWFuLm1vZGVsID0gbGlzdChhcm1hT3JkZXIgPSBjKDEsIDEpLCBpbmNsdWRlLm1lYW4gPSBUUlVFKSwNCiAgZGlzdHJpYnV0aW9uLm1vZGVsID0gImdlZCIpDQoNClZOSV9nYXJjaDEyX2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVk5JX3VnYXJjaDEyX2dlZCwgZGF0YSA9IG1obm4kVk5JKQ0KDQojU2dlZA0Kc3BlY19WTklfdWdhcmNoMTJfc2dlZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygxLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMSwgMSksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic2dlZCIpDQoNClZOSV9nYXJjaDEyX3NnZWQgPC0gdWdhcmNoZml0KHNwZWMgPSBzcGVjX1ZOSV91Z2FyY2gxMl9zZ2VkLCBkYXRhID0gbWhubiRWTkkpDQoNCiNTZXR1cCBnYXJjaCgyLDEpIGFuZCBlc3RpbWF0ZSBmb3IgVk5JIGNvZWYNCiNub3JtDQpzcGVjX1ZOSV91Z2FyY2gyMV9ub3JtIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDIsIDEpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygxLDEpLCBpbmNsdWRlLm1lYW4gPSBUUlVFKSwNCiAgZGlzdHJpYnV0aW9uLm1vZGVsID0gIm5vcm0iKQ0KDQpWTklfZ2FyY2gyMV9ub3JtIDwtIHVnYXJjaGZpdChzcGVjID0gc3BlY19WTklfdWdhcmNoMjFfbm9ybSwgZGF0YSA9IG1obm4kVk5JKQ0KDQojc3RkDQpzcGVjX1ZOSV91Z2FyY2gyMV9zdGQgPC0gdWdhcmNoc3BlYygNCiAgdmFyaWFuY2UubW9kZWwgPSBsaXN0KG1vZGVsID0gImdqckdBUkNIIiwgZ2FyY2hPcmRlciA9IGMoMiwgMSkpLA0KICBtZWFuLm1vZGVsID0gbGlzdChhcm1hT3JkZXIgPSBjKDEsIDEpLCBpbmNsdWRlLm1lYW4gPSBUUlVFKSwNCiAgZGlzdHJpYnV0aW9uLm1vZGVsID0gInN0ZCIpDQoNClZOSV9nYXJjaDIxX3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVk5JX3VnYXJjaDIxX3N0ZCwgZGF0YSA9IG1obm4kVk5JKQ0KDQojc3N0ZA0Kc3BlY19WTklfdWdhcmNoMjFfc3N0ZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAxKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMSwgMSksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic3N0ZCIpDQoNClZOSV9nYXJjaDIxX3NzdGQgPC0gdWdhcmNoZml0KHNwZWMgPSBzcGVjX1ZOSV91Z2FyY2gyMV9zc3RkLCBkYXRhID0gbWhubiRWTkkpDQoNCiNnZWQNCnNwZWNfVk5JX3VnYXJjaDIxX2dlZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAxKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMSwgMSksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAiZ2VkIikNCg0KVk5JX2dhcmNoMjFfZ2VkIDwtIHVnYXJjaGZpdChzcGVjID0gc3BlY19WTklfdWdhcmNoMjFfZ2VkLCBkYXRhID0gbWhubiRWTkkpDQoNCiNzZ2VkDQpzcGVjX1ZOSV91Z2FyY2gyMV9zZ2VkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDIsIDEpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygxLCAxKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJzZ2VkIikNCg0KVk5JX2dhcmNoMjFfc2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVk5JX3VnYXJjaDIxX3NnZWQsIGRhdGEgPSBtaG5uJFZOSSkNCg0KI1NldHVwIGdhcmNoKDIsMikgYW5kIGVzdGltYXRlIGZvciBWTkkgY29lZg0KI25vcm0NCnNwZWNfVk5JX3VnYXJjaDIyX25vcm0gPC0gdWdhcmNoc3BlYygNCiAgdmFyaWFuY2UubW9kZWwgPSBsaXN0KG1vZGVsID0gImdqckdBUkNIIiwgZ2FyY2hPcmRlciA9IGMoMiwgMikpLA0KICBtZWFuLm1vZGVsID0gbGlzdChhcm1hT3JkZXIgPSBjKDEsMSksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAibm9ybSIpDQoNClZOSV9nYXJjaDIyX25vcm0gPC0gdWdhcmNoZml0KHNwZWMgPSBzcGVjX1ZOSV91Z2FyY2gyMl9ub3JtLCBkYXRhID0gbWhubiRWTkkpDQoNCiNzdGQNCnNwZWNfVk5JX3VnYXJjaDIyX3N0ZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMSwgMSksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic3RkIikNCg0KVk5JX2dhcmNoMjJfc3RkIDwtIHVnYXJjaGZpdChzcGVjID0gc3BlY19WTklfdWdhcmNoMjJfc3RkLCBkYXRhID0gbWhubiRWTkkpDQoNCiNzc3RkDQpzcGVjX1ZOSV91Z2FyY2gyMl9zc3RkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDIsIDIpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygxLCAxKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJzc3RkIikNCg0KVk5JX2dhcmNoMjJfc3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVk5JX3VnYXJjaDIyX3NzdGQsIGRhdGEgPSBtaG5uJFZOSSkNCg0KI2dlZA0Kc3BlY19WTklfdWdhcmNoMjJfZ2VkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDIsIDIpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygxLCAxKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJnZWQiKQ0KDQpWTklfZ2FyY2gyMl9nZWQgPC0gdWdhcmNoZml0KHNwZWMgPSBzcGVjX1ZOSV91Z2FyY2gyMl9nZWQsIGRhdGEgPSBtaG5uJFZOSSkNCg0KI3NnZWQNCnNwZWNfVk5JX3VnYXJjaDIyX3NnZWQgPC0gdWdhcmNoc3BlYygNCiAgdmFyaWFuY2UubW9kZWwgPSBsaXN0KG1vZGVsID0gImdqckdBUkNIIiwgZ2FyY2hPcmRlciA9IGMoMiwgMikpLA0KICBtZWFuLm1vZGVsID0gbGlzdChhcm1hT3JkZXIgPSBjKDEsIDEpLCBpbmNsdWRlLm1lYW4gPSBUUlVFKSwNCiAgZGlzdHJpYnV0aW9uLm1vZGVsID0gInNnZWQiKQ0KDQpWTklfZ2FyY2gyMl9zZ2VkIDwtIHVnYXJjaGZpdChzcGVjID0gc3BlY19WTklfdWdhcmNoMjJfc2dlZCwgZGF0YSA9IG1obm4kVk5JKQ0KDQojU2V0dXAgZ2FyY2goMiwyKSBhbmQgZXN0aW1hdGUgZm9yIFZOSSBjb2VmDQojbm9ybQ0Kc3BlY19WTklfdWdhcmNoMjJfbm9ybSA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMSwxKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJub3JtIikNCg0KVk5JX2dhcmNoMjJfbm9ybSA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVk5JX3VnYXJjaDIyX25vcm0sIGRhdGEgPSBtaG5uJFZOSSkNCg0KI3N0ZA0Kc3BlY19WTklfdWdhcmNoMjJfc3RkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDIsIDIpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygxLCAxKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJzdGQiKQ0KDQpWTklfZ2FyY2gyMl9zdGQgPC0gdWdhcmNoZml0KHNwZWMgPSBzcGVjX1ZOSV91Z2FyY2gyMl9zdGQsIGRhdGEgPSBtaG5uJFZOSSkNCg0KI3NzdGQNCnNwZWNfVk5JX3VnYXJjaDIyX3NzdGQgPC0gdWdhcmNoc3BlYygNCiAgdmFyaWFuY2UubW9kZWwgPSBsaXN0KG1vZGVsID0gImdqckdBUkNIIiwgZ2FyY2hPcmRlciA9IGMoMiwgMikpLA0KICBtZWFuLm1vZGVsID0gbGlzdChhcm1hT3JkZXIgPSBjKDEsIDEpLCBpbmNsdWRlLm1lYW4gPSBUUlVFKSwNCiAgZGlzdHJpYnV0aW9uLm1vZGVsID0gInNzdGQiKQ0KDQpWTklfZ2FyY2gyMl9zc3RkIDwtIHVnYXJjaGZpdChzcGVjID0gc3BlY19WTklfdWdhcmNoMjJfc3N0ZCwgZGF0YSA9IG1obm4kVk5JKQ0KDQojZ2VkDQpzcGVjX1ZOSV91Z2FyY2gyMl9nZWQgPC0gdWdhcmNoc3BlYygNCiAgdmFyaWFuY2UubW9kZWwgPSBsaXN0KG1vZGVsID0gImdqckdBUkNIIiwgZ2FyY2hPcmRlciA9IGMoMiwgMikpLA0KICBtZWFuLm1vZGVsID0gbGlzdChhcm1hT3JkZXIgPSBjKDEsIDEpLCBpbmNsdWRlLm1lYW4gPSBUUlVFKSwNCiAgZGlzdHJpYnV0aW9uLm1vZGVsID0gImdlZCIpDQoNClZOSV9nYXJjaDIyX2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVk5JX3VnYXJjaDIyX2dlZCwgZGF0YSA9IG1obm4kVk5JKQ0KDQojc2dlZA0Kc3BlY19WTklfdWdhcmNoMjJfc2dlZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMSwgMSksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic2dlZCIpDQoNClZOSV9nYXJjaDIyX3NnZWQgPC0gdWdhcmNoZml0KHNwZWMgPSBzcGVjX1ZOSV91Z2FyY2gyMl9zZ2VkLCBkYXRhID0gbWhubiRWTkkpDQoNCiNTZXR1cCBnYXJjaCgxLDEpIGFuZCBlc3RpbWF0ZSBmb3IgVEwgY29lZg0KI25vcm0NCnNwZWNfVExfdWdhcmNoMTFfbm9ybSA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygxLCAxKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAibm9ybSIpDQoNClRMX2dhcmNoMTFfbm9ybSA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMTFfbm9ybSwgZGF0YSA9IG1obm4kVEwpDQoNCiNzdGQNCnNwZWNfVExfdWdhcmNoMTFfc3RkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDEsIDEpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygwLCAyKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJzdGQiKQ0KDQpUTF9nYXJjaDExX3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMTFfc3RkLCBkYXRhID0gbWhubiRUTCkNCg0KI3NzdGQNCnNwZWNfVExfdWdhcmNoMTFfc3N0ZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygxLCAxKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic3N0ZCIpDQoNClRMX2dhcmNoMTFfc3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMTFfc3N0ZCwgZGF0YSA9IG1obm4kVEwpDQoNCiNnZWQNCnNwZWNfVExfdWdhcmNoMTFfZ2VkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDEsIDEpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygwLCAyKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJnZWQiKQ0KDQpUTF9nYXJjaDExX2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMTFfZ2VkLCBkYXRhID0gbWhubiRUTCkNCg0KI3NnZWQNCnNwZWNfVExfdWdhcmNoMTFfc2dlZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygxLCAxKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic2dlZCIpDQoNClRMX2dhcmNoMTFfc2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMTFfc2dlZCwgZGF0YSA9IG1obm4kVEwpDQoNCiNTZXR1cCBnYXJjaCgxLDIpIGFuZCBlc3RpbWF0ZSBmb3IgVEwgY29lZg0KI25vcm0NCnNwZWNfVExfdWdhcmNoMTJfbm9ybSA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygxLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAibm9ybSIpDQoNClRMX2dhcmNoMTJfbm9ybSA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMTJfbm9ybSwgZGF0YSA9IG1obm4kVEwpDQoNCiNzdGQNCnNwZWNfVExfdWdhcmNoMTJfc3RkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDEsIDIpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygwLCAyKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJzdGQiKQ0KDQpUTF9nYXJjaDEyX3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMTJfc3RkLCBkYXRhID0gbWhubiRUTCkNCg0KI3NzdGQNCnNwZWNfVExfdWdhcmNoMTJfc3N0ZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygxLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic3N0ZCIpDQoNClRMX2dhcmNoMTJfc3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMTJfc3N0ZCwgZGF0YSA9IG1obm4kVEwpDQoNCiNnZWQNCnNwZWNfVExfdWdhcmNoMTJfZ2VkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDEsIDIpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygwLCAyKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJnZWQiKQ0KDQpUTF9nYXJjaDEyX2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMTJfZ2VkLCBkYXRhID0gbWhubiRUTCkNCg0KI3NnZWQNCnNwZWNfVExfdWdhcmNoMTJfc2dlZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygxLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic2dlZCIpDQoNClRMX2dhcmNoMTJfc2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMTJfc2dlZCwgZGF0YSA9IG1obm4kVEwpDQoNCiNTZXR1cCBnYXJjaCgyLDEpIGFuZCBlc3RpbWF0ZSBmb3IgVEwgY29lZg0KI25vcm0NCnNwZWNfVExfdWdhcmNoMjFfbm9ybSA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAxKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAibm9ybSIpDQoNClRMX2dhcmNoMjFfbm9ybSA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMjFfbm9ybSwgZGF0YSA9IG1obm4kVEwpDQoNCiNzdGQNCnNwZWNfVExfdWdhcmNoMjFfc3RkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDIsIDEpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygwLCAyKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJzdGQiKQ0KDQpUTF9nYXJjaDIxX3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMjFfc3RkLCBkYXRhID0gbWhubiRUTCkNCg0KI3NzdGQNCnNwZWNfVExfdWdhcmNoMjFfc3N0ZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAxKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic3N0ZCIpDQoNClRMX2dhcmNoMjFfc3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMjFfc3N0ZCwgZGF0YSA9IG1obm4kVEwpDQoNCiNnZWQNCnNwZWNfVExfdWdhcmNoMjFfZ2VkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDIsIDEpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygwLCAyKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJnZWQiKQ0KDQpUTF9nYXJjaDIxX2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMjFfZ2VkLCBkYXRhID0gbWhubiRUTCkNCg0KI3NnZWQNCnNwZWNfVExfdWdhcmNoMjFfc2dlZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAxKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic2dlZCIpDQoNClRMX2dhcmNoMjFfc2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMjFfc2dlZCwgZGF0YSA9IG1obm4kVEwpDQoNCiNTZXR1cCBnYXJjaCgyLDIpIGFuZCBlc3RpbWF0ZSBmb3IgVEwgY29lZg0KI25vcm0NCnNwZWNfVExfdWdhcmNoMjJfbm9ybSA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAibm9ybSIpDQoNClRMX2dhcmNoMjJfbm9ybSA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMjJfbm9ybSwgZGF0YSA9IG1obm4kVEwpDQoNCiNzdGQNCnNwZWNfVExfdWdhcmNoMjJfc3RkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDIsIDIpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygwLCAyKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJzdGQiKQ0KDQpUTF9nYXJjaDIyX3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMjJfc3RkLCBkYXRhID0gbWhubiRUTCkNCg0KI3NzdGQNCnNwZWNfVExfdWdhcmNoMjJfc3N0ZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic3N0ZCIpDQoNClRMX2dhcmNoMjJfc3N0ZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMjJfc3N0ZCwgZGF0YSA9IG1obm4kVEwpDQoNCiNnZWQNCnNwZWNfVExfdWdhcmNoMjJfZ2VkIDwtIHVnYXJjaHNwZWMoDQogIHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJnanJHQVJDSCIsIGdhcmNoT3JkZXIgPSBjKDIsIDIpKSwNCiAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygwLCAyKSwgaW5jbHVkZS5tZWFuID0gVFJVRSksDQogIGRpc3RyaWJ1dGlvbi5tb2RlbCA9ICJnZWQiKQ0KDQpUTF9nYXJjaDIyX2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMjJfZ2VkLCBkYXRhID0gbWhubiRUTCkNCg0KI3NnZWQNCnNwZWNfVExfdWdhcmNoMjJfc2dlZCA8LSB1Z2FyY2hzcGVjKA0KICB2YXJpYW5jZS5tb2RlbCA9IGxpc3QobW9kZWwgPSAiZ2pyR0FSQ0giLCBnYXJjaE9yZGVyID0gYygyLCAyKSksDQogIG1lYW4ubW9kZWwgPSBsaXN0KGFybWFPcmRlciA9IGMoMCwgMiksIGluY2x1ZGUubWVhbiA9IFRSVUUpLA0KICBkaXN0cmlidXRpb24ubW9kZWwgPSAic2dlZCIpDQoNClRMX2dhcmNoMjJfc2dlZCA8LSB1Z2FyY2hmaXQoc3BlYyA9IHNwZWNfVExfdWdhcmNoMjJfc2dlZCwgZGF0YSA9IG1obm4kVEwpDQoNCiNDaG9vc2Ugb3B0aW1pemF0aW9uIG1vZGVsIGZvciB2bmkgY29lZg0KVk5JLm1vZGVsLmxpc3QgPC0gbGlzdChnYXJjaDExbiA9IFZOSV9nYXJjaDExX25vcm0sIGdhcmNoMTF0ID0gVk5JX2dhcmNoMTFfc3RkLCBnYXJjaDExc3QgPSBWTklfZ2FyY2gxMV9zc3RkLCANCiAgICAgICAgICAgICAgICAgICAgICAgZ2FyY2gxMWcgPSBWTklfZ2FyY2gxMV9nZWQsIGdhcmNoMTFzZyA9IFZOSV9nYXJjaDExX3NnZWQsIA0KICAgICAgICAgICAgICAgICAgICAgICBnYXJjaDEybiA9IFZOSV9nYXJjaDEyX25vcm0sIGdhcmNoMTJ0ID0gVk5JX2dhcmNoMTJfc3RkLCBnYXJjaDEyc3QgPSBWTklfZ2FyY2gxMl9zc3RkLCANCiAgICAgICAgICAgICAgICAgICAgICAgZ2FyY2gxMmcgPSBWTklfZ2FyY2gxMl9nZWQsIGdhcmNoMTJzZyA9IFZOSV9nYXJjaDEyX3NnZWQsDQogICAgICAgICAgICAgICAgICAgICAgIGdhcmNoMjFuID0gVk5JX2dhcmNoMjFfbm9ybSwgZ2FyY2gyMXQgPSBWTklfZ2FyY2gyMV9zdGQsIGdhcmNoMjFzdCA9IFZOSV9nYXJjaDIxX3NzdGQsIA0KICAgICAgICAgICAgICAgICAgICAgICBnYXJjaDIxZyA9IFZOSV9nYXJjaDIxX2dlZCwgZ2FyY2gyMXNnID0gVk5JX2dhcmNoMjFfc2dlZCwNCiAgICAgICAgICAgICAgICAgICAgICAgZ2FyY2gyMm4gPSBWTklfZ2FyY2gyMl9ub3JtLCBnYXJjaDIydCA9IFZOSV9nYXJjaDIyX3N0ZCwgZ2FyY2gyMnN0ID0gVk5JX2dhcmNoMjJfc3N0ZCwgDQogICAgICAgICAgICAgICAgICAgICAgIGdhcmNoMjJnID0gVk5JX2dhcmNoMjJfZ2VkLCBnYXJjaDIyc2cgPSBWTklfZ2FyY2gyMl9zZ2VkDQogICAgICAgICAgICAgICAgICAgICAgICkgDQoNClZOSS5pbmZvLm1hdCA8LSBzYXBwbHkoVk5JLm1vZGVsLmxpc3QsIGluZm9jcml0ZXJpYSkNCg0Kcm93bmFtZXMoVk5JLmluZm8ubWF0KSA8LSByb3duYW1lcyhpbmZvY3JpdGVyaWEoVk5JX2dhcmNoMTFfbm9ybSkpDQoNClZOSS5pbmRzIDwtIHdoaWNoKFZOSS5pbmZvLm1hdCA9PSBtaW4oVk5JLmluZm8ubWF0WzEsXSksIGFyci5pbmQ9VFJVRSkgI0xheSBjaGkgc28gQUlDIG5obyBuaGF0DQoNCm1vZGVsLlZOSSA8LSBjb2xuYW1lcyhWTkkuaW5mby5tYXQpW1ZOSS5pbmRzWywyXV0NCg0KI0Nob29zZSBvcHRpbWl6YXRpb24gbW9kZWwgZm9yIHN0aSBjb2VmDQpUTC5tb2RlbC5saXN0IDwtIGxpc3QoZ2FyY2gxMW4gPSBUTF9nYXJjaDExX25vcm0sIGdhcmNoMTF0ID0gVExfZ2FyY2gxMV9zdGQsIGdhcmNoMTFzdCA9IFRMX2dhcmNoMTFfc3N0ZCwgDQogICAgICAgICAgICAgICAgICAgICAgIGdhcmNoMTFnID0gVExfZ2FyY2gxMV9nZWQsIGdhcmNoMTFzZyA9IFRMX2dhcmNoMTFfc2dlZCwgDQogICAgICAgICAgICAgICAgICAgICAgIGdhcmNoMTJuID0gVExfZ2FyY2gxMl9ub3JtLCBnYXJjaDEydCA9IFRMX2dhcmNoMTJfc3RkLCBnYXJjaDEyc3QgPSBUTF9nYXJjaDEyX3NzdGQsIA0KICAgICAgICAgICAgICAgICAgICAgICBnYXJjaDEyZyA9IFRMX2dhcmNoMTJfZ2VkLCBnYXJjaDEyc2cgPSBUTF9nYXJjaDEyX3NnZWQsDQogICAgICAgICAgICAgICAgICAgICAgIGdhcmNoMjFuID0gVExfZ2FyY2gyMV9ub3JtLCBnYXJjaDIxdCA9IFRMX2dhcmNoMjFfc3RkLCBnYXJjaDIxc3QgPSBUTF9nYXJjaDIxX3NzdGQsIA0KICAgICAgICAgICAgICAgICAgICAgICBnYXJjaDIxZyA9IFRMX2dhcmNoMjFfZ2VkLCBnYXJjaDIxc2cgPSBUTF9nYXJjaDIxX3NnZWQsDQogICAgICAgICAgICAgICAgICAgICAgIGdhcmNoMjJuID0gVExfZ2FyY2gyMl9ub3JtLCBnYXJjaDIydCA9IFRMX2dhcmNoMjJfc3RkLCBnYXJjaDIyc3QgPSBUTF9nYXJjaDIyX3NzdGQsIA0KICAgICAgICAgICAgICAgICAgICAgICBnYXJjaDIyZyA9IFRMX2dhcmNoMjJfZ2VkLCBnYXJjaDIyc2cgPSBUTF9nYXJjaDIyX3NnZWQNCiAgICAgICAgICAgICAgICAgICAgICAgKQ0KDQpUTC5pbmZvLm1hdCA8LSBzYXBwbHkoVEwubW9kZWwubGlzdCwgaW5mb2NyaXRlcmlhKQ0KDQpyb3duYW1lcyhUTC5pbmZvLm1hdCkgPC0gcm93bmFtZXMoaW5mb2NyaXRlcmlhKFRMX2dhcmNoMTFfbm9ybSkpDQoNClRMLmluZHMgPC0gd2hpY2goVEwuaW5mby5tYXQgPT0gbWluKFRMLmluZm8ubWF0WzEsXSksIGFyci5pbmQ9VFJVRSkgI0xheSBjaGkgc28gQUlDIG5obyBuaGF0DQoNCm1vZGVsLlRMIDwtIGNvbG5hbWVzKFRMLmluZm8ubWF0KVtUTC5pbmRzWywyXV0NCg0KYGBgDQoNCiMjIFRyw6xuaCBiw6B5IGvhur90IHF14bqjIGThuqFuZyBtw7QgaMOsbmggcGjDom4gcGjhu5FpIGJpw6puIA0KDQpgYGB7cn0NCiNUcsOsbmggYsOgeSBr4bq/dCBxdeG6ow0KbWFyX21vZGVsIDwtIGRhdGEuZnJhbWUoDQogIHJhdGUgPSBjKCJWTkkiLCAiVEwiKSwNCiAgRm9ybWF0ID0gYygiQVJNQSgwLDAsMiktR0pSLUdBUkNIKDEsMSktU2tld2VkIFN0dWRlbnQgdCIsICJBUk1BKDUsMCwyKS1HSlItR0FSQ0goMSwxKS1TdHVkZW50IHQiKSkNCg0KIyBSZW5kZXIgdGhlIHRhYmxlDQprYWJsZShtYXJfbW9kZWwsIGNvbC5uYW1lcyA9IGMoIlThu7cgc3XhuqV0IHNpbmggbOG7o2kiLCAiROG6oW5nIG3DtCBow6xuaCBwaMOibiBwaOG7kWkgYmnDqm4iKSwgDQogICAgICBjYXB0aW9uID0gIkLhuqNuZyA1OiBNw7QgaMOsbmggcGjDom4gcGjhu5FpIGJpw6puIHThu5FpIMawdSIsIGZvcm1hdCA9ICJwYW5kb2MiLCANCiAgICAgIHRhYmxlLmF0dHIgPSAic3R5bGU9J3dpZHRoOjEwMCU7JyIpICU+JQ0KICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSkNCmBgYA0KDQoNCiMjIEvhur90IHF14bqjIG3DtCBow6xuaCBBUk1BLUdKUi1HQVJDSCBj4bunYSBjaOG7iSBz4buRIFZOSQ0KDQoNCmBgYHtyfQ0KIyBUcsOsbmggYsOgeSBjw6FjIGvhur90IHF14bqjDQpleHRyYWN0X2dhcmNoX3Jlc3VsdHMgPC0gZnVuY3Rpb24oZml0KSB7DQogIGNvZWYgPC0gY29lZihmaXQpDQogIHNlIDwtIGZpdEBmaXQkc2UuY29lZg0KICBwdmFsdWVzIDwtIDIgKiAoMSAtIHBub3JtKGFicyhmaXRAZml0JHR2YWwpKSkgIyB0w61uaCBnacOhIHRy4buLIHAgdOG7qyBnacOhIHRy4buLIHQNCiAgcmVzdWx0cyA8LSBjYmluZChjb2VmLCBzZSwgcHZhbHVlcykNCiAgY29sbmFtZXMocmVzdWx0cykgPC0gYygiRXN0aW1hdGUiLCAiU3RkLiBFcnJvciIsICJQcig+fHp8KSIpDQogIHJldHVybihyZXN1bHRzKQ0KfQ0KDQpmaXQxIDwtIGV4dHJhY3RfZ2FyY2hfcmVzdWx0cyhWTklfZ2FyY2gxMV9zc3RkKQ0KZml0MiA8LSBleHRyYWN0X2dhcmNoX3Jlc3VsdHMoVExfZ2FyY2gxMV9zdGQpDQoNCmthYmxlKGFzLmRhdGEuZnJhbWUoZml0MSksIA0KICBjYXB0aW9uID0gIkLhuqNuZzogS+G6v3QgcXXhuqMgbcO0IGjDrG5oIEFSTUEoMCwwLDIpLUdKUi1HYXJjaCgxLDEpLVNrZXdlZCBTdHVkZW50IGPhu6dhIGJp4bq/biBWTkkiLCANCiAgZm9ybWF0ID0gJ3BhbmRvYycpICU+JSBrYWJsZV9zdHlsaW5nKA0KICAgICAgICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCANCiAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGKQ0KYGBgDQoNCg0KIyMgS+G6v3QgcXXhuqMgbcO0IGjDrG5oIEFSTUEtR0pSLUdBUkNIIGPhu6dhIGNo4buJIHPhu5EgTVNJQyBUaMOhaSBMYW4gDQoNCmBgYHtyfQ0KIyBUcsOsbmggYsOgeSBjw6FjIGvhur90IHF14bqjDQpleHRyYWN0X2dhcmNoX3Jlc3VsdHMgPC0gZnVuY3Rpb24oZml0KSB7DQogIGNvZWYgPC0gY29lZihmaXQpDQogIHNlIDwtIGZpdEBmaXQkc2UuY29lZg0KICBwdmFsdWVzIDwtIDIgKiAoMSAtIHBub3JtKGFicyhmaXRAZml0JHR2YWwpKSkgIyB0w61uaCBnacOhIHRy4buLIHAgdOG7qyBnacOhIHRy4buLIHQNCiAgcmVzdWx0cyA8LSBjYmluZChjb2VmLCBzZSwgcHZhbHVlcykNCiAgY29sbmFtZXMocmVzdWx0cykgPC0gYygiRXN0aW1hdGUiLCAiU3RkLiBFcnJvciIsICJQcig+fHp8KSIpDQogIHJldHVybihyZXN1bHRzKQ0KfQ0KDQpmaXQxIDwtIGV4dHJhY3RfZ2FyY2hfcmVzdWx0cyhWTklfZ2FyY2gxMV9zc3RkKQ0KZml0MiA8LSBleHRyYWN0X2dhcmNoX3Jlc3VsdHMoVExfZ2FyY2gxMV9zdGQpDQoNCmthYmxlKGFzLmRhdGEuZnJhbWUoZml0MiksIA0KICBjYXB0aW9uID0gIkLhuqNuZzogS+G6v3QgcXXhuqMgbcO0IGjDrG5oIEFSTUEoNSwwLDIpLUdKUi1HYXJjaCgxLDEpLVN0dWRlbnQgY+G7p2EgYmnhur9uIFRMIiwgDQogIGZvcm1hdCA9ICdwYW5kb2MnKSAlPiUga2FibGVfc3R5bGluZygNCiAgICAgICAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJjb25kZW5zZWQiKSwgDQogICAgICAgICAgICBmdWxsX3dpZHRoID0gRikNCmBgYA0KDQoNCg0KIyBLaeG7g20gxJHhu4tuaCB0w61uaCBwaMO5IGjhu6NwIGPhu6dhIG3DtCBow6xuaCBwaMOibiBwaOG7kWkgYmnDqm4gDQpgYGB7cn0NCiMgVMOtbmggdMOtY2ggcGjDom4geMOhYyBzdeG6pXQgY2hvIHBo4bqnbiBkxrAgY+G7p2EgVk5JDQpWTkkucmVzIDwtIHJlc2lkdWFscyhWTklfZ2FyY2gxMV9zc3RkKSAvIHNpZ21hKFZOSV9nYXJjaDExX3NzdGQpICAjIFBo4bqnbiBkxrAgxJHDoyDEkcaw4bujYyBjaHXhuqluIGjDs2ENCg0KYSA8LSBmaXRkaXN0KGRpc3RyaWJ1dGlvbiA9ICJzc3RkIiwgVk5JLnJlcywgY29udHJvbCA9IGxpc3QoKSkgICMgS2jhu5twIHBow6JuIHBo4buRaSBjaG8gcGjhuqduIGTGsCBuw6B5DQoNCnUgPC0gcGRpc3QoZGlzdHJpYnV0aW9uID0gInNzdGQiLCBxID0gVk5JLnJlcywgbXUgPSBhJHBhcnNbJ211J10sIHNpZ21hID0gYSRwYXJzWydzaWdtYSddLA0KICAgICAgICAgICBza2V3ID0gYSRwYXJzWydza2V3J10sIHNoYXBlID0gYSRwYXJzWydzaGFwZSddKSAgIyBUw61uaCB0w61jaCBwaMOibiB4w6FjIHN14bqldA0KDQojIFTDrW5oIHTDrWNoIHBow6JuIHjDoWMgc3XhuqV0IGNobyBwaOG6p24gZMawIGPhu6dhIFRMDQpUTC5yZXMgPC0gcmVzaWR1YWxzKFRMX2dhcmNoMTFfc3RkKSAvIHNpZ21hKFRMX2dhcmNoMTFfc3RkKSAgIyBQaOG6p24gZMawIMSRw6MgxJHGsOG7o2MgY2h14bqpbiBow7NhDQoNCmIgPC0gZml0ZGlzdChkaXN0cmlidXRpb24gPSAic3RkIiwgVEwucmVzLCBjb250cm9sID0gbGlzdCgpKSAgIyBLaOG7m3AgcGjDom4gcGjhu5FpIGNobyBwaOG6p24gZMawIG7DoHkNCg0KdiA8LSBwZGlzdChkaXN0cmlidXRpb24gPSAic3RkIiwgcSA9IFRMLnJlcywgbXUgPSBiJHBhcnNbJ211J10sIHNpZ21hID0gYiRwYXJzWydzaWdtYSddLA0KICAgICAgICAgICBza2V3ID0gYiRwYXJzWydza2V3J10sIHNoYXBlID0gYiRwYXJzWydzaGFwZSddKSAgIyBUw61uaCB0w61jaCBwaMOibiB4w6FjIHN14bqldA0KDQojIEtp4buDbSDEkeG7i25oIHbhu5tpIEFuZGVyc29uLURhcmxpbmcNCmxpYnJhcnkoZ29mdGVzdCkNCmFkX3ZuaSA8LSBhZC50ZXN0KHUsICJwdW5pZiIpDQphZF90bCA8LSBhZC50ZXN0KHYsICJwdW5pZiIpDQoNCiMgS2nhu4NtIMSR4buLbmggQ3JhbWVyLXZvbiBNaXNlcw0KY3ZtX3ZuaSA8LSBjdm0udGVzdCh1LCAicHVuaWYiKQ0KY3ZtX3RsIDwtIGN2bS50ZXN0KHYsICJwdW5pZiIpDQoNCiMgS2nhu4NtIMSR4buLbmggS29sbW9nb3Jvdi1TbWlybm92DQprc192bmkgPC0ga3MudGVzdCh1LCAicHVuaWYiKQ0Ka3NfdGwgPC0ga3MudGVzdCh2LCAicHVuaWYiKQ0KDQojIFRyw6xuaCBiw6B5IGvhur90IHF14bqjDQp0ZXN0IDwtIGRhdGEuZnJhbWUodGVzdCA9IGMoJ1BfdmFsdWUgVk5JJywgJ1BfdmFsdWUgVEwnKSwNCiAgICAgICAgICAgICAgICAgICBBRCA9IGMoYWRfdm5pJHAudmFsdWUsIGFkX3RsJHAudmFsdWUpLA0KICAgICAgICAgICAgICAgICAgIENWTSA9IGMoY3ZtX3ZuaSRwLnZhbHVlLCBjdm1fdGwkcC52YWx1ZSksDQogICAgICAgICAgICAgICAgICAgS1MgPSBjKGtzX3ZuaSRwLnZhbHVlLCBrc190bCRwLnZhbHVlKSkNCg0Ka2FibGUodGVzdCwgDQogICAgICBjYXB0aW9uID0gIkLhuqNuZzogS+G6v3QgcXXhuqMgY8OhYyBraeG7g20gxJHhu4tuaCBjaG8gbcO0IGjDrG5oIHBow6JuIHBo4buRaSBiacOqbiIsIA0KICAgICAgY29sLm5hbWVzID0gYygiQ8OhYyBraeG7g20gxJHhu4tuaCIsICJBbmRlcnNvbi1EYXJsaW5nIiwgIkNyYW1lci12b24gTWlzZXMiLCAiS29sbW9nb3Jvdi1TbWlybm92IiksIA0KICAgICAgZm9ybWF0ID0gJ3BhbmRvYycpICU+JSBrYWJsZV9zdHlsaW5nKA0KICAgICAgICAgICAgYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpLCANCiAgICAgICAgICAgIGZ1bGxfd2lkdGggPSBGKQ0KDQpgYGANCg0KDQojIFRyw61jaCB4deG6pXQgcGjhuqduIGTGsCBjaHXhu5dpIA0KYGBge3J9DQojIFRyw61jaCBwaOG6p24gZMawIGNodeG7l2kNCiMgVHLDrWNoIHh14bqldCBwaOG6p24gZMawIGNodeG7l2kgVk5JDQpWTkkucmVzIDwtIHJlc2lkdWFscyhWTklfZ2FyY2gxMV9zc3RkKS9zaWdtYShWTklfZ2FyY2gxMV9zc3RkKQ0KZml0ZGlzdChkaXN0cmlidXRpb24gPSAic3N0ZCIsIFZOSS5yZXMsIGNvbnRyb2wgPSBsaXN0KCkpDQpgYGANCg0KDQpgYGB7cn0NCnMgPSBwZGlzdCgic3N0ZCIsVk5JLnJlcywgbXUgPTAuMDA0MzY0NTg1LCBzaWdtYSA9MS4wMDA5MTM1OTAgLCBza2V3ID0wLjg4NDQyMDAwNCwgc2hhcGUgPTUuMjIxNzU3MjYzICkNCmhlYWQocywxMCkNCmBgYA0KDQpgYGB7cn0NCiMgVHLDrWNoIHN14bqldCBwaOG6p24gZMawIGNodeG7l2kgVEwNClRMLnJlcyA8LSByZXNpZHVhbHMoVExfZ2FyY2gxMV9zdGQpL3NpZ21hKFRMX2dhcmNoMTFfc3RkKQ0KZml0ZGlzdChkaXN0cmlidXRpb24gPSAic3RkIiwgVEwucmVzLCBjb250cm9sID0gbGlzdCgpKQ0KYGBgDQpgYGB7cn0NCmQgPSBwZGlzdCgic3RkIixUTC5yZXMsIG11ID0tNS4wNjUxNzdlLTA1ICwgc2lnbWEgPSAxLjAwMTYyMWUrMDAsICBzaGFwZSA9NS4zNDcyODVlKzAwICkNCmhlYWQoZCwxMCkNCmBgYA0KIyBCaeG7g3UgxJHhu5MgY8OhYyBo4buNIENvdXB1bGEgDQoNCmBgYHtyfQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkoY29wdWxhKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCmxpYnJhcnkoVkMyY29wdWxhKQ0KbGlicmFyeShWaW5lQ29wdWxhKQ0KbGlicmFyeShncmlkR3JhcGhpY3MpDQpsaWJyYXJ5KHBuZykNCiNU4bqhbyBow6BtIHbhur0gYmnhu4N1IMSR4buTDQpzY2F0dGVyX3Bsb3QgPC0gZnVuY3Rpb24ocmFuZG9tX2RhdGEsIGNsKSB7DQogIGdncGxvdChkYXRhLmZyYW1lKHJhbmRvbV9kYXRhKSwgYWVzKHJhbmRvbV9kYXRhWywxXSwgcmFuZG9tX2RhdGFbLDJdKSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gMC41LCBjb2wgPSBjbCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHggPSAidSIsIHkgPSAidiIpDQogIH0gI2ZvciBzY2F0dGVyDQoNCnBlcnNwX3Bsb3QgPC0gZnVuY3Rpb24oY29wdWxhX29iaiwgZmlsZV9uYW1lLCBjbCkgew0KICBwbmcoZmlsZV9uYW1lKQ0KICBwZXJzcChjb3B1bGFfb2JqLCBkQ29wdWxhLCANCiAgICAgICAgeGxhYiA9ICd1JywgeWxhYiA9ICd2JywgY29sID0gY2wsIGx0aGV0YSA9IDEyMCwgIA0KICAgICAgICB0aWNrdHlwZSA9ICJkZXRhaWxlZCIsIGNleC5heGlzID0gMC44KQ0KICBkZXYub2ZmKCkNCiAgcmFzdGVyR3JvYihyZWFkUE5HKGZpbGVfbmFtZSksaW50ZXJwb2xhdGUgPSBUUlVFKQ0KfSMgZm9yIHBkZg0KDQpzZXQuc2VlZCgxMjMpDQojTcO0IHBo4buPbmcgY29wdWxhIGdhdXNzIHbhu5tpIHA9MC44DQpjb3Bfbm9yIDwtIG5vcm1hbENvcHVsYShwYXJhbSA9IDAuOCwgZGltID0gMikNCiNNw7QgcGjhu49uZyA3NjAwIHF1YW4gc8OhdCBuZ+G6q3Ugbmhpw6puIGThu7FhIHRyw6puIGNvcHVsYSBjw7Mgc+G6tW4NCnJhbmRvbV9ub3IgPC0gckNvcHVsYShjb3B1bGEgPSBjb3Bfbm9yLG4gPSA3NjAwKQ0KI03DtCBwaOG7j25nIGNvcHVsYSB24bubaSBwPTAuOA0KY29wX3N0ZCA8LSB0Q29wdWxhKHBhcmFtID0gMC44LCBkaW0gPSAyLCBkZiA9IDEpDQojTcO0IHBo4buPbmcgNzYwMCBxdWFuIHPDoXQgbmfhuqt1IG5oacOqbiBk4buxYSB0csOqbiBjb3B1bGEgY8OzIHPhurVuDQpyYW5kb21fc3RkIDwtIHJDb3B1bGEoY29wdWxhID0gY29wX3N0ZCxuID0gNzYwMCkNCmBgYA0KIyMgQ29wdWxhIEdhdXNzIHbDoCBTdHVkZW50IA0KYGBge3J9DQojVuG6vSBiaeG7g3UgxJHhu5MgDQpwbmcoJ25vcnMucG5nJykgI0zGsHUg4bqjbmggYmnhu4N1IMSR4buTDQpzY2F0dGVyX3Bsb3QocmFuZG9tX25vciwgJyM5OUZGQ0MnKQ0KZGV2Lm9mZigpDQpub3JzIDwtIHJhc3Rlckdyb2IocmVhZFBORygnbm9ycy5wbmcnKSwgaW50ZXJwb2xhdGUgPSBUUlVFKSAjQ2h1eeG7g24g4bqjbmggc2FuZyBk4bqhbmcgR3JvYg0KDQpwbmcoJ3N0ZHMucG5nJykNCnNjYXR0ZXJfcGxvdChyYW5kb21fc3RkLCAnI0NDRkYzMycpDQpkZXYub2ZmKCkNCnN0ZHMgPC0gcmFzdGVyR3JvYihyZWFkUE5HKCdzdGRzLnBuZycpLCBpbnRlcnBvbGF0ZSA9IFRSVUUpDQpub3JfcGVyIDwtIHBlcnNwX3Bsb3QoY29wX25vciwgJ25vcnAucG5nJywgJyM5OUZGQ0MnKQ0Kc3RkX3BlciA8LSBwZXJzcF9wbG90KGNvcF9zdGQsICdzdGRwLnBuZycsICcjQ0NGRjMzJykNCg0KbGVnZW5kIDwtIGxlZ2VuZEdyb2IoDQogIGxhYmVscyA9IGMoIkdhdXNzIiwgIlN0dWRlbnQiKSwgcGNoID0gMTUsDQogIGdwID0gZ3Bhcihjb2wgPSBjKCcjOTlGRkNDJywgJyNDQ0ZGMzMnKSwgZmlsbCA9IGMoJyM5OUZGQ0MnLCAnI0NDRkYzMycpKQ0KKQ0KDQpncmlkLmFycmFuZ2Uobm9ycywgbm9yX3Blciwgc3Rkcywgc3RkX3BlciwgbGVnZW5kLCBuY29sID0gMywgDQogIGxheW91dF9tYXRyaXggPSByYmluZChjKDEsIDIsIDUpLCBjKDMsIDQsIDUpKSwNCiAgd2lkdGhzID0gYygyLCAyLCAxKSwgDQogIHRvcCA9IHRleHRHcm9iKCJIw6xuaCAxOiBCaeG7g3UgxJHhu5MgcGjDom4gdMOhbiB2w6AgcGjhu5FpIGPhuqNuaCBQREYgY+G7p2EgQ29wdWxhIGjhu40gRWxpcCIsIA0KICAgICAgICAgICAgICAgICBncCA9IGdwYXIoZm9udHNpemUgPSAxNSwgZm9udCA9IDIpKQ0KICAgICAgICAgICAgICkNCmBgYA0KDQojIyBDb3B1bGEgQ2xheXRvbiB2w6AgR3VtYmVsIA0KDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKQ0KI03DtCBwaOG7j25nIGNvcHVsYSBjbGF5dG9uIHbhu5tpIHA9NA0KY29wX2NsYXkgPC0gY2xheXRvbkNvcHVsYShwYXJhbSA9IDQsIGRpbSA9IDIpDQojTcO0IHBo4buPbmcgNzYwMCBxdWFuIHPDoXQgbmfhuqt1IG5oacOqbiBk4buxYSB0csOqbiBjb3B1bGEgY8OzIHPhurVuDQpyYW5kb21fY2xheSA8LSByQ29wdWxhKGNvcHVsYSA9IGNvcF9jbGF5LG4gPSA3NjAwKQ0KI03DtCBwaOG7j25nIGNvcHVsYSBndW1iZWwgduG7m2kgcD01DQpjb3BfZ3VtIDwtIGd1bWJlbENvcHVsYShwYXJhbSA9IDUsIGRpbSA9IDIpDQojTcO0IHBo4buPbmcgNzYwMCBxdWFuIHPDoXQgbmfhuqt1IG5oacOqbiBk4buxYSB0csOqbiBjb3B1bGEgY8OzIHPhurVuDQpyYW5kb21fZ3VtIDwtIHJDb3B1bGEoY29wdWxhID0gY29wX2d1bSxuID0gNzYwMCkNCmBgYA0KDQoNCmBgYHtyfQ0KI1bhur0gYmnhu4N1IMSR4buTIA0KcG5nKCdjbGF5cy5wbmcnKQ0Kc2NhdHRlcl9wbG90KHJhbmRvbV9jbGF5LCcjQ0M2NjMzJykNCmRldi5vZmYoKQ0KY2xheXMgPC0gcmFzdGVyR3JvYihyZWFkUE5HKCdjbGF5cy5wbmcnKSwgaW50ZXJwb2xhdGUgPSBUUlVFKQ0KDQpwbmcoJ2d1bXMucG5nJykNCnNjYXR0ZXJfcGxvdChyYW5kb21fZ3VtLCcjRkY2Njk5JykNCmRldi5vZmYoKQ0KZ3VtcyA8LSByYXN0ZXJHcm9iKHJlYWRQTkcoJ2d1bXMucG5nJyksIGludGVycG9sYXRlID0gVFJVRSkNCmNsYXlwIDwtIHBlcnNwX3Bsb3QoY29wX2NsYXksJ2NsYXlwLnBuZycsJyNDQzY2MzMnKQ0KDQpndW1wIDwtIHBlcnNwX3Bsb3QoY29wX2d1bSwnZ3VtcC5wbmcnLCcjRkY2Njk5JykNCg0KDQpsZWdlbmQgPC0gbGVnZW5kR3JvYigNCiAgbGFiZWxzID0gYygiQ2xheXRvbiIsICJHdW1iZWwiKSwgcGNoID0gMTUsDQogIGdwID0gZ3Bhcihjb2wgPSBjKCcjQ0M2NjMzJywgJyNGRjY2OTknKSwgZmlsbCA9IGMoJyNDQzY2MzMnLCAnI0ZGNjY5OScpKQ0KKQ0KDQpncmlkLmFycmFuZ2UoY2xheXMsIGNsYXlwLCBndW1zLCBndW1wLCBsZWdlbmQsIG5jb2wgPSAzLCANCiAgbGF5b3V0X21hdHJpeCA9IHJiaW5kKGMoMSwgMiwgNSksIGMoMywgNCwgNSkpLA0KICB3aWR0aHMgPSBjKDIsIDIsIDEpLCANCiAgdG9wID0gdGV4dEdyb2IoIkjDrG5oIDI6IEJp4buDdSDEkeG7kyBwaMOibiB0w6FuIHbDoCBQREYgY+G7p2EgQ29wdWxhIENsYXl0b24gdsOgIEd1bWJlbCIsIA0KICAgICAgICAgICAgICAgICBncCA9IGdwYXIoZm9udHNpemUgPSAxNSwgZm9udCA9IDIpKQ0KICAgICAgICAgICAgICkNCmBgYA0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMykNCiNNw7QgcGjhu49uZyBjb3B1bGEgc3Vydml2YWwgZ3VtYmVsDQpjb3Bfc3VyZ3VtIDwtIFZDMmNvcHVsYTo6c3VyR3VtYmVsQ29wdWxhKHBhcmFtID0gNSkNCiNNw7QgcGjhu49uZyA3NjAwIHF1YW4gc8OhdCBuZ+G6q3Ugbmhpw6puIGThu7FhIHRyw6puIGNvcHVsYSBjw7Mgc+G6tW4NCnJhbmRvbV9zdXJndW0gPC0gckNvcHVsYShjb3B1bGEgPSBjb3Bfc3VyZ3VtLG4gPSA3NjAwKQ0KI03DtCBwaOG7j25nIGNvcHVsYSBzdXJ2aXZhbCBjbGF5dG9uICB24bubaSBwPTQNCmNvcF9zdXJjbGF5IDwtIFZDMmNvcHVsYTo6c3VyQ2xheXRvbkNvcHVsYShwYXJhbSA9IDQpDQojTcO0IHBo4buPbmcgNzYwMCBxdWFuIHPDoXQgbmfhuqt1IG5oacOqbiBk4buxYSB0csOqbiBjb3B1bGEgY8OzIHPhurVuDQpyYW5kb21fc3VyY2xheSA8LSByQ29wdWxhKGNvcHVsYSA9IGNvcF9zdXJjbGF5LG4gPSA3NjAwKQ0KcG5nKCdzdXJjbGF5cy5wbmcnKQ0Kc2NhdHRlcl9wbG90KHJhbmRvbV9zdXJjbGF5LCcjOTk2NkZGJykNCmRldi5vZmYoKQ0Kc3VyY2xheXMgPC0gcmFzdGVyR3JvYihyZWFkUE5HKCdzdXJjbGF5cy5wbmcnKSwgaW50ZXJwb2xhdGUgPSBUUlVFKQ0KDQpwbmcoJ3N1cmd1bXMucG5nJykNCnNjYXR0ZXJfcGxvdChyYW5kb21fc3VyZ3VtLCcjRkYzMzAwJykNCmRldi5vZmYoKQ0Kc3VyZ3VtcyA8LSByYXN0ZXJHcm9iKHJlYWRQTkcoJ3N1cmd1bXMucG5nJyksIGludGVycG9sYXRlID0gVFJVRSkNCnN1cmNsYXlwIDwtIHBlcnNwX3Bsb3QoY29wX3N1cmNsYXksICJzdXJjbGF5cC5wbmciLCIjOTk2NkZGIikNCnN1cmd1bXAgPC0gcGVyc3BfcGxvdChjb3Bfc3VyZ3VtLCAic3VyZ3VtcC5wbmciLCIjRkYzMzAwIikNCg0KbGVnZW5kIDwtIGxlZ2VuZEdyb2IobGFiZWxzID0gYygiU3Vydml2YWwgQ2xheXRvbiIsIlN1cnZpdmFsIEd1bWJlbCIpLCBwY2ggPSAxNSwNCiAgICAgICAgICAgICAgICAgICAgZ3AgPSBncGFyKGNvbCA9IGMoJyM5OTY2RkYnLCcjRkYzMzAwJyksIGZpbGwgPSBjKCcjOTk2NkZGJywnI0ZGMzMwMCcgKSkpDQoNCmdyaWQuYXJyYW5nZShzdXJjbGF5cywgc3VyY2xheXAsc3VyZ3Vtcywgc3VyZ3VtcCwgbGVnZW5kLCBuY29sID0gMywNCiAgICAgICAgICAgICBsYXlvdXRfbWF0cml4ID0gcmJpbmQoYygxLDIsNSksYygzLDQsNSkpLA0KICAgICAgICAgICAgIHdpZHRocyA9IGMoMiwyLDEpLA0KICAgICAgICAgICAgIHRvcCA9IHRleHRHcm9iKCJIw6xuaCAzOiBCaeG7g3UgxJHhu5MgcGjDom4gdMOhbiB2w6AgUERGIGPhu6dhIENvcHVsYSBTdXIgQ2xheXRvbiB2w6AgR3VtYmVsIiwgDQogICAgICAgICAgICAgICAgIGdwID0gZ3Bhcihmb250c2l6ZSA9IDE1LCBmb250ID0gMikpDQogICAgICAgICAgICAgKQ0KYGBgDQoNCiMjIENvcHVsYSBGcmFubCB2w6AgSm9lIA0KYGBge3J9DQpzZXQuc2VlZCgxMjMpDQojTcO0IHBo4buPbmcgY29wdWxhIEZyYW5rDQpjb3BfZnJhbmsgPC0gZnJhbmtDb3B1bGEocGFyYW0gPSA5LjIpDQojTcO0IHBo4buPbmcgNzYwMCBxdWFuIHPDoXQgbmfhuqt1IG5oacOqbiBk4buxYSB0csOqbiBjb3B1bGEgY8OzIHPhurVuDQpyYW5kb21fZnJhbmsgPC0gckNvcHVsYShjb3B1bGEgPSBjb3BfZnJhbmssbiA9IDc2MDApDQojTcO0IHBo4buPbmcgY29wdWxhIHN1cnZpdmFsIGNsYXl0b24gIHbhu5tpIHA9NA0KY29wX2pvZSA8LSBqb2VDb3B1bGEocGFyYW0gPSAzKQ0KI03DtCBwaOG7j25nIDc2MDAgcXVhbiBzw6F0IG5n4bqrdSBuaGnDqm4gZOG7sWEgdHLDqm4gY29wdWxhIGPDsyBz4bq1bg0KcmFuZG9tX2pvZSA8LSByQ29wdWxhKGNvcHVsYSA9IGNvcF9qb2UsbiA9IDc2MDApDQpwbmcoJ2ZyYW5rcy5wbmcnKQ0Kc2NhdHRlcl9wbG90KHJhbmRvbV9mcmFuaywnI0ZGQ0NGRicpDQpkZXYub2ZmKCkNCmZyYW5rcyA8LSByYXN0ZXJHcm9iKHJlYWRQTkcoJ2ZyYW5rcy5wbmcnKSwgaW50ZXJwb2xhdGUgPSBUUlVFKQ0KDQpwbmcoJ2pvZXMucG5nJykNCnNjYXR0ZXJfcGxvdChyYW5kb21fam9lLCcjRkZDQzY2JykNCmRldi5vZmYoKQ0Kam9lcyA8LSByYXN0ZXJHcm9iKHJlYWRQTkcoJ2pvZXMucG5nJyksIGludGVycG9sYXRlID0gVFJVRSkNCmZyYW5rcCA8LSBwZXJzcF9wbG90KGNvcF9mcmFuaywgImZyYW5rcC5wbmciLCIjRkZDQ0ZGIikNCmpvZXAgPC0gcGVyc3BfcGxvdChjb3Bfam9lLCAiam9lcC5wbmciLCIjRkZDQzY2IikNCg0KbGVnZW5kIDwtIGxlZ2VuZEdyb2IobGFiZWxzID0gYygiRnJhbmwiLCJKb2UiKSwgcGNoID0gMTUsDQogICAgICAgICAgICAgICAgICAgIGdwID0gZ3Bhcihjb2wgPSBjKCcjRkZDQ0ZGJywnI0ZGQ0M2NicpLCBmaWxsID0gYygnI0ZGQ0NGRicsJyNGRkNDNjYnKSkpDQoNCmdyaWQuYXJyYW5nZShmcmFua3MsIGZyYW5rcCxqb2VzLCBqb2VwLCBsZWdlbmQsIG5jb2wgPSAzLA0KICAgICAgICAgICAgIGxheW91dF9tYXRyaXggPSByYmluZChjKDEsMiw1KSxjKDMsNCw1KSksDQogICAgICAgICAgICAgd2lkdGhzID0gYygyLDIsMSksDQogICAgICAgICAgICAgdG9wID0gdGV4dEdyb2IoIkjDrG5oIDQ6IEJp4buDdSDEkeG7kyBwaMOibiB0w6FuIHbDoCAgUERGIGPhu6dhIENvcHVsYSBGcmFubCB2w6AgSm9lIiwgDQogICAgICAgICAgICAgICAgIGdwID0gZ3Bhcihmb250c2l6ZSA9IDE1LCBmb250ID0gMikpDQogICAgICAgICAgICAgKQ0KYGBgDQoNCg0KDQpgYGB7cn0NCiNM4buxYSBjaOG7jW4gdsOgIMaw4bubYyBsxrDhu6NuZw0Kb3B0X2NvcCA8LSBCaUNvcFNlbGVjdCh1LHYsc2VsZWN0aW9uY3JpdCA9ICJBSUMiLG1ldGhvZCA9ICJtbGUiKQ0KZXN0X29wdF9jb3AgPC0gQmlDb3BFc3QodSx2LGZhbWlseSA9IG9wdF9jb3AkZmFtaWx5LG1ldGhvZCA9ICJtbGUiLG1heC5kZiA9IDMwKQ0KDQojVHLDrG5oIGLDoHkga+G6v3QgcXXhuqMNCmVzdF9vcHRfY29wX2R0IDwtIGRhdGEuZnJhbWUobXFoID0gYygnVk5JLVRMJyksDQogICAgICAgICAgICAgICAgICAgIENvcHVsYSA9IGVzdF9vcHRfY29wJGZhbWlseW5hbWUsDQogICAgICAgICAgICAgICAgICAgIFRoYW1zbyA9IGVzdF9vcHRfY29wJHBhciwNCiAgICAgICAgICAgICAgICAgIFRoYW1zbzIgPSBlc3Rfb3B0X2NvcCRwYXIyLA0KICAgICAgICAgICAgICAgICAgIGR1b2lkdW9pID0gZXN0X29wdF9jb3AkdGFpbGRlcCRsb3dlciwNCiAgICAgICAgICAgICAgICAgIGR1b2l0cmVuID0gZXN0X29wdF9jb3AkdGFpbGRlcCR1cHBlciwNCiAgICAgICAgICAgICAgICAgIHRhdSA9IGVzdF9vcHRfY29wJHRhdSwNCiAgICAgICAgICAgICAgICAgIGFpYyA9IGVzdF9vcHRfY29wJEFJQywNCiAgICAgICAgICAgICAgICAgIGJpYyA9IGVzdF9vcHRfY29wJEJJQykNCg0Ka2FibGUoZXN0X29wdF9jb3BfZHQsIA0KICBjYXB0aW9uID0gIkLhuqNuZyA5OiBL4bq/dCBxdeG6oyDGsOG7m2MgbMaw4bujbmcgbcO0IGjDrG5oIENvcHVsYSB04buRaSDGsHUiLCBjb2wubmFtZXMgPSBjKCJDaOG7iSBz4buRIiwiQ29wdWxhIiwgIlBhciIsIlBhcjIiLCAixJB1w7RpIGTGsOG7m2kiLCAixJB1w7RpIHRyw6puIiwiSOG7hyBz4buRIEtlbmRhbGwiLCAiQUlDIiwiQklDIiksIA0KICBmb3JtYXQgPSAncGFuZG9jJykgJT4lIGthYmxlX3N0eWxpbmcoDQogICAgICAgICAgICBib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIiksIA0KICAgICAgICAgICAgZnVsbF93aWR0aCA9IEYpDQpgYGANCg0KIyMgUGjhu5FpIGPhuqNuaCBQREYgdGhlbyBjaHXhu5dpIGThu68gbGnhu4d1IHBow6JuDQpgYGB7cn0NCnBlcnNwKFZDMmNvcHVsYTo6QkI3Q29wdWxhKHBhcmFtID0gYyhlc3Rfb3B0X2NvcCRwYXIsIGVzdF9vcHRfY29wJHBhcjIpKSxkQ29wdWxhLCANCiAgICAgICAgeGxhYiA9ICd1JywgeWxhYiA9ICd2JywgY29sID0gJ2xpZ2h0Ymx1ZScsIGx0aGV0YSA9IDEyMCwgIA0KICAgICAgICB0aWNrdHlwZSA9ICJkZXRhaWxlZCIsIGNleC5heGlzID0gMC44LCAgbWFpbiA9ICdIw6xuaCAxMzogUGjhu5FpIGPhuqNuaCBQREYgY+G7p2EgbcO0IGjDrG5oIENvcHVsYSBHdW1iZWwnKQ0KYGBgDQoNCg0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMykNCg0KIyBUaGFtIHPhu5EgY2hvIGNvcHVsYSBHdW1iZWwgKHbDrSBk4bulIHbhu5tpIHRoZXRhID0gMikNCnRoZXRhX2d1bWJlbCA8LSAyDQoNCiMgVOG6oW8gY29wdWxhIEd1bWJlbA0KY29wX2d1bWJlbCA8LSBndW1iZWxDb3B1bGEocGFyYW0gPSB0aGV0YV9ndW1iZWwsIGRpbSA9IDIpDQoNCiMgTcO0IHBo4buPbmcgZOG7ryBsaeG7h3UgdOG7qyBjb3B1bGEgR3VtYmVsDQpzYW1wbGVfc2l6ZSA8LSA1MDAgICMgS8OtY2ggdGjGsOG7m2MgbeG6q3UNCnNhbXBsZV9ndW1iZWwgPC0gckNvcHVsYShzYW1wbGVfc2l6ZSwgY29wX2d1bWJlbCkNCg0KIyBIaeG7g24gdGjhu4sgbeG7mXQgc+G7kSBt4bqrdSBj4bunYSBjb3B1bGEgR3VtYmVsDQpoZWFkKHNhbXBsZV9ndW1iZWwpDQoNCmBgYA0KDQojIyBQaMOibiBwaOG7kWkgbeG6rXQgxJHhu5kgeMOhYyBzdeG6pXQgY+G7p2EgQ29wdWxhIEd1bWJlbA0KYGBge3J9DQpzZXQuc2VlZCgxMjMpDQoNCiMgVGhhbSBz4buRIGNobyBjb3B1bGEgR3VtYmVsDQp0aGV0YV9ndW1iZWwgPC0gMg0KDQojIFThuqFvIGNvcHVsYSBHdW1iZWwNCmNvcF9ndW1iZWwgPC0gZ3VtYmVsQ29wdWxhKHBhcmFtID0gdGhldGFfZ3VtYmVsLCBkaW0gPSAyKQ0KDQojIE3DtCBwaOG7j25nIGThu68gbGnhu4d1IHThu6sgY29wdWxhIEd1bWJlbA0Kc2FtcGxlX3NpemUgPC0gNTAwDQpzYW1wbGVfZ3VtYmVsIDwtIHJDb3B1bGEoc2FtcGxlX3NpemUsIGNvcF9ndW1iZWwpDQoNCiMgVOG6oW8gbMaw4bubaSDEkWnhu4NtIMSR4buDIHTDrW5oIHRvw6FuIG3huq10IMSR4buZDQp4X3NlcSA8LSBzZXEoMCwgMSwgbGVuZ3RoLm91dCA9IDMwKQ0KeV9zZXEgPC0gc2VxKDAsIDEsIGxlbmd0aC5vdXQgPSAzMCkNCmdyaWQgPC0gZXhwYW5kLmdyaWQoeCA9IHhfc2VxLCB5ID0geV9zZXEpDQoNCiMgVMOtbmggdG/DoW4gbeG6rXQgxJHhu5kgY+G7p2EgY29wdWxhIEd1bWJlbCBjaG8gbMaw4bubaSDEkWnhu4NtDQpwZGZfdmFsdWVzIDwtIGFwcGx5KGdyaWQsIDEsIGZ1bmN0aW9uKHApIHsNCiAgZENvcHVsYShwLCBjb3BfZ3VtYmVsKQ0KfSkNCnBkZl9tYXRyaXggPC0gbWF0cml4KHBkZl92YWx1ZXMsIG5yb3cgPSBsZW5ndGgoeF9zZXEpLCBuY29sID0gbGVuZ3RoKHlfc2VxKSkNCg0KIyBW4bq9IGJp4buDdSDEkeG7kyAzRCBj4bunYSBwaMOibiBwaOG7kWkgbeG6rXQgxJHhu5kgeMOhYyBzdeG6pXQNCnBsb3RfbHkoeiA9IHBkZl9tYXRyaXgsIHggPSB4X3NlcSwgeSA9IHlfc2VxLCB0eXBlID0gInN1cmZhY2UiKSAlPiUNCiAgbGF5b3V0KHRpdGxlID0gIlBow6JuIHBo4buRaSBt4bqtdCDEkeG7mSB4w6FjIHN14bqldCBj4bunYSBDb3B1bGEgR3VtYmVsIiwNCiAgICAgICAgIHNjZW5lID0gbGlzdCgNCiAgICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlgiKSwNCiAgICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIlkiKSwNCiAgICAgICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gIlThu7cgdHLhu41uZyAiKQ0KICAgICAgICAgKSkNCg0KYGBgDQoNCiMjIMSQ4buTIHRo4buLIG3huq10IMSR4buZIEd1bWJlbCBDb3B1bGENCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KIyBU4bqhbyDEkeG7kWkgdMaw4bujbmcgY29wdWxhIEd1bWJlbA0KZ3VtYmVsX2NvcHVsYSA8LSBjb3B1bGE6Omd1bWJlbENvcHVsYShwYXJhbSA9IDEuMTgpDQoNCmRmIDwtIGRhdGEuZnJhbWUodSA9IHMsIGsgPSBkKQ0KDQojIFbhur0gxJHhu5MgdGjhu4sgbeG6rXQgxJHhu5kNCmdncGxvdChkZiwgYWVzKHggPSB1LCB5ID0gaykpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKw0KICBnZW9tX2RlbnNpdHlfMmQoKSArDQogIGxhYnModGl0bGUgPSAixJDhu5MgdGjhu4sgbeG6rXQgxJHhu5kgR3VtYmVsIENvcHVsYSIsDQogICAgICAgeCA9ICJ1IiwNCiAgICAgICB5ID0gImsiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQoNCg0KYGBge3J9DQojIFThuqNpIGPDoWMgdGjGsCB2aeG7h24gY+G6p24gdGhp4bq/dA0KbGlicmFyeShjb3B1bGEpDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KHNjYXR0ZXJwbG90M2QpDQoNCiMgxJDhu4tuaCBuZ2jEqWEgdGhhbSBz4buRIGNobyBjb3B1bGEgR3VtYmVsDQp0aGV0YSA8LSAxLjE4DQoNCiMgVOG6oW8gxJHhu5FpIHTGsOG7o25nIGNvcHVsYSBHdW1iZWwNCmd1bWJlbF9jb3B1bGEgPC0gZ3VtYmVsQ29wdWxhKHBhcmFtID0gdGhldGEpDQoNCiMgROG7ryBsaeG7h3UgdsOtIGThu6UgY2hvIGtkZTJkICh0aGF5IHRo4bq/IGNkIGLhurFuZyBk4buvIGxp4buHdSB0aOG7sWMgY+G7p2EgYuG6oW4pDQpzZXQuc2VlZCgxMjMpDQpjZCA8LSBjYmluZChybm9ybSgxMDAwKSwgcm5vcm0oMTAwMCkpDQoNCiMgVGjhu7FjIGhp4buHbiDGsOG7m2MgbMaw4bujbmcgbeG6rXQgxJHhu5kga2VybmVsDQprZGUyZF9yZXN1bHQgPC0ga2RlMmQoY2RbLDFdLCBjZFssMl0sIG4gPSA1MCkNCg0KIyBDaHV54buDbiDEkeG7lWkga+G6v3QgcXXhuqMga2RlMmQgdGjDoG5oIMSR4buLbmggZOG6oW5nIHBow7kgaOG7o3AgduG7m2kgc2NhdHRlcnBsb3QzZA0KeCA8LSBrZGUyZF9yZXN1bHQkeA0KeSA8LSBrZGUyZF9yZXN1bHQkeQ0KeiA8LSBrZGUyZF9yZXN1bHQkeg0KDQojIFThuqFvIGzGsOG7m2kgxJFp4buDbSBjaG8gc2NhdHRlcnBsb3QzZA0KZ3JpZCA8LSBleHBhbmQuZ3JpZCh4ID0geCwgeSA9IHkpDQoNCiMgTMOgbSBwaOG6s25nIHogY2hvIHNjYXR0ZXJwbG90M2QNCnpfZmxhdCA8LSBhcy52ZWN0b3IodCh6KSkNCg0KIyDEkOG6o20gYuG6o28gZ3JpZCB2w6Agel9mbGF0IGPDsyBjw7luZyDEkeG7mSBkw6BpDQppZiAobGVuZ3RoKHpfZmxhdCkgIT0gbnJvdyhncmlkKSkgew0KICBzdG9wKCLEkOG7mSBkw6BpIGPhu6dhIHpfZmxhdCBraMO0bmcga2jhu5twIHbhu5tpIHPhu5EgbMaw4bujbmcgxJFp4buDbSB0cm9uZyBncmlkIikNCn0NCg0KIyBW4bq9IMSR4buTIHRo4buLIG3huq10IMSR4buZIHPhu60gZOG7pW5nIHNjYXR0ZXJwbG90M2QNCnNjYXR0ZXJwbG90M2QoZ3JpZCR4LCBncmlkJHksIHpfZmxhdCwgdHlwZSA9ICJoIiwgYW5nbGUgPSAzMCwgDQogICAgICAgICAgICAgIG1haW4gPSAiQmnhu4N1IMSR4buTIE3huq10IMSR4buZIGPhu6dhIENvcHVsYSBHdW1iZWwiLA0KICAgICAgICAgICAgICB4bGFiID0gIlJhaW5mYWxsIERlcHRoIiwgDQogICAgICAgICAgICAgIHlsYWIgPSAiU2hvdCBEdXJhdGlvbiIsIA0KICAgICAgICAgICAgICB6bGFiID0gIlBow6JuIHBo4buRaSBoYWkgYmnhur9uIiwNCiAgICAgICAgICAgICAgcGNoID0gMjAsIGNvbG9yID0gInR1cnF1b2lzZSIpDQoNCmBgYA0KDQo=