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
| 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
| 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
| 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
| 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
| 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
| 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
| 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
| 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=