Tecnológico de Monterrey

Doctor Teófilo Ozuna

Alumna:

Avril Lobato Delgado A00833113

Librerias

library(ggplot2)
library(dplyr)
library(readxl)
library(tidyr)
library(lubridate)
library(purrr)
library(plotly)
library(forecast)
library(readxl)
library(DataExplorer)
library(dplyr)
library(ggplot2)
library(tm)
library(wordcloud)
library(cluster)
library(factoextra) 
library(gridExtra)
library(purrr)
library(pROC)
library(rpart)
library(rpart.plot)
library(e1071)
library(ggpubr)
library(dlookr)
library(zoo)
library(caret)
library(stats)
library(tseries)
library(readr)
library(vars)
library(syuzhet)
library(kableExtra)
library(plotly)
library(scales)
library(readxl)

Chatziantoniou, Gabauer & Gupta (2021): Integration and risk transmission in the market for crude oil: A time-varying parameter frequency connectedness approach

library(readr)

# Especifica el delimitador adecuado (si es necesario)
index_alt <- read_csv("C:/Users/AVRIL/Desktop/Spillovers/all_daily_index.csv")

# Convertir la columna `Date` a tipo Date si está en formato "dd/mm/yyyy"
index_alt$Date <- as.Date(index_alt$Date, format = "%d/%m/%Y")

# Mostrar estructura y resumen
str(index_alt)
## spc_tbl_ [2,052 × 15] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ Date                  : Date[1:2052], format: "2019-01-07" "2019-01-08" ...
##  $ AI_INDEX              : num [1:2052] 1000 1009 1017 1026 1035 ...
##  $ Returns...3           : num [1:2052] NA 0.00865 0.00858 0.00851 0.00844 ...
##  $ Cumulative return...4 : num [1:2052] 100 101 102 103 103 ...
##  $ Fintech_Index         : num [1:2052] 1000 999 999 998 997 ...
##  $ Returns...6           : num [1:2052] NA -0.000675 -0.000675 -0.000676 -0.000676 ...
##  $ Cumulative return...7 : num [1:2052] 100 99.9 99.9 99.8 99.7 ...
##  $ Blockchain_Index      : num [1:2052] 1000 1002 1004 1006 1008 ...
##  $ Returns...9           : num [1:2052] NA 0.00205 0.00204 0.00204 0.00203 ...
##  $ Cumulative return...10: num [1:2052] 100 100 100 101 101 ...
##  $ Nasdaq Composite      : num [1:2052] 1000 1005 1010 1015 1020 ...
##  $ Dax 40                : num [1:2052] 1000 1002 1003 1005 1006 ...
##  $ Dow Jones Industrial  : num [1:2052] 1000 1003 1007 1010 1014 ...
##  $ KFTX Index            : num [1:2052] 1000 1012 1023 1029 1028 ...
##  $ S&P Financials Index  : num [1:2052] 1000 1003 1005 1006 1008 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   Date = col_character(),
##   ..   AI_INDEX = col_double(),
##   ..   Returns...3 = col_double(),
##   ..   `Cumulative return...4` = col_double(),
##   ..   Fintech_Index = col_double(),
##   ..   Returns...6 = col_double(),
##   ..   `Cumulative return...7` = col_double(),
##   ..   Blockchain_Index = col_double(),
##   ..   Returns...9 = col_double(),
##   ..   `Cumulative return...10` = col_double(),
##   ..   `Nasdaq Composite` = col_double(),
##   ..   `Dax 40` = col_double(),
##   ..   `Dow Jones Industrial` = col_double(),
##   ..   `KFTX Index` = col_double(),
##   ..   `S&P Financials Index` = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>
summary(index_alt)
##       Date               AI_INDEX     Returns...3         Cumulative return...4
##  Min.   :2019-01-07   Min.   :1000   Min.   :-0.0180390   Min.   :100.0        
##  1st Qu.:2020-06-02   1st Qu.:2062   1st Qu.:-0.0026589   1st Qu.:206.2        
##  Median :2021-10-28   Median :2755   Median : 0.0010241   Median :275.5        
##  Mean   :2021-10-28   Mean   :2700   Mean   : 0.0007285   Mean   :270.0        
##  3rd Qu.:2023-03-25   3rd Qu.:3323   3rd Qu.: 0.0050013   3rd Qu.:332.3        
##  Max.   :2024-08-19   Max.   :4398   Max.   : 0.0165334   Max.   :439.8        
##                                      NA's   :1                                 
##  Fintech_Index     Returns...6         Cumulative return...7 Blockchain_Index
##  Min.   : 914.2   Min.   :-0.0068872   Min.   : 91.42        Min.   : 950.4  
##  1st Qu.:1051.9   1st Qu.:-0.0009810   1st Qu.:105.19        1st Qu.:1366.1  
##  Median :1160.8   Median : 0.0003000   Median :116.08        Median :1681.5  
##  Mean   :1209.8   Mean   : 0.0002515   Mean   :120.98        Mean   :1761.8  
##  3rd Qu.:1278.8   3rd Qu.: 0.0015300   3rd Qu.:127.88        3rd Qu.:2201.7  
##  Max.   :1737.3   Max.   : 0.0054064   Max.   :173.73        Max.   :2766.4  
##                   NA's   :1                                                  
##   Returns...9         Cumulative return...10 Nasdaq Composite     Dax 40      
##  Min.   :-0.0242600   Min.   : 95.04         Min.   :1000     Min.   : 829.2  
##  1st Qu.:-0.0020959   1st Qu.:136.61         1st Qu.:1434     1st Qu.:1184.5  
##  Median : 0.0007566   Median :168.15         Median :1810     Median :1320.3  
##  Mean   : 0.0004415   Mean   :176.18         Mean   :1798     Mean   :1329.4  
##  3rd Qu.: 0.0035842   3rd Qu.:220.17         3rd Qu.:2098     3rd Qu.:1459.4  
##  Max.   : 0.0209105   Max.   :276.64         Max.   :2723     Max.   :1743.4  
##  NA's   :1                                                                    
##  Dow Jones Industrial   KFTX Index     S&P Financials Index
##  Min.   : 818.2       Min.   : 881.8   Min.   : 727.6      
##  1st Qu.:1185.7       1st Qu.:1289.4   1st Qu.:1153.2      
##  Median :1409.3       Median :1403.9   Median :1370.8      
##  Mean   :1357.5       Mean   :1466.5   Mean   :1347.8      
##  3rd Qu.:1482.5       3rd Qu.:1680.7   3rd Qu.:1537.2      
##  Max.   :1757.1       Max.   :1925.3   Max.   :1811.6      
## 
# Select only the relevant columns for the model
data_selected <- index_alt[, c("Date","AI_INDEX", "Fintech_Index", "Blockchain_Index")]
# Convert to matrix format for the ConnectednessApproach package
data_matrix <- as.matrix(data_selected)
# Convertir a objeto zoo
data_zoo <- zoo(data_selected[, -1], order.by = data_selected$Date)

# Instalar y cargar el paquete ConnectednessApproach, si no está ya instalado
if (!requireNamespace("ConnectednessApproach", quietly = TRUE)) {
  if (!requireNamespace("devtools", quietly = TRUE)) {
    install.packages("devtools")
  }
  devtools::install_github("GabauerDavid/ConnectednessApproach")
}
library(ConnectednessApproach)

# Configuración de parámetros para TVPVAR
nlag <- 2       # Orden del rezago
lambda <- c(0.99, 0.99)  # Valores de decaimiento para el filtro

# Crear la lista de configuración necesaria
config <- list(l = lambda, nlag = nlag)

# Estimar el modelo TVP-VAR con los parámetros especificados
tvpvar_model <- TVPVAR(data_zoo, configuration = config)

Table 2: Averaged Connectedness Table

partition = c(pi+0.00001, pi/5, 0)
dca = ConnectednessApproach(data_zoo, 
                            model="TVP-VAR",
                            connectedness="Frequency",
                            nlag=1,
                            nfore=100,
                            window.size=200,
                            VAR_config=list(TVPVAR=list(kappa1=0.99, kappa2=0.99, prior="BayesPrior")),
                            Connectedness_config = list(
                              FrequencyConnectedness=list(partition=partition, generalized=TRUE, scenario="ABS")
                            ))
kable(dca$TABLE)
AI_INDEX.Total Fintech_Index.Total Blockchain_Index.Total FROM.Total AI_INDEX.1-5 Fintech_Index.1-5 Blockchain_Index.1-5 FROM.1-5 AI_INDEX.5-Inf Fintech_Index.5-Inf Blockchain_Index.5-Inf FROM.5-Inf
AI_INDEX 64.70 13.88 21.42 35.30 0.91 0.11 0.10 0.21 63.79 13.76 21.32 35.08
Fintech_Index 27.91 48.62 23.47 51.38 0.17 1.03 0.14 0.32 27.74 47.59 23.32 51.06
Blockchain_Index 35.08 14.82 50.10 49.90 0.18 0.17 0.85 0.35 34.89 14.65 49.25 49.54
TO 62.99 28.70 44.89 136.57 0.36 0.29 0.24 0.88 62.63 28.41 44.64 135.69
Inc.Own 127.69 77.32 94.99 cTCI/TCI 1.27 1.32 1.10 cTCI/TCI 126.42 76.00 93.89 cTCI/TCI
Net 27.69 -22.68 -5.01 68.29/45.52 0.14 -0.03 -0.11 0.44/0.29 27.55 -22.65 -4.90 67.84/45.23
NPDC 2.00 0.00 1.00 2.00 1.00 0.00 2.00 0.00 1.00

Figure 4: Net Total Directional Connectedness

PlotNET(dca, ylim=c(-60,60))

______________________________________ ## Transformación de base de datos

Librerias

library(knitr)
library(rmgarch)
library(devtools)
library(openxlsx)
library(relaimpo)
library(stargazer)
library(RColorBrewer)
library(PerformanceAnalytics)
library(ConnectednessApproach)
library(readr)
library(readxl)
library(tseries)
library(forecast)
library(urca)
library(fGarch)
library(MTS)
library(MASS)
library(nortest)
library(outliers)
library(moments)
library(FinTS)
library(WeightedPortTest)

Carga de base de datos

# Lee el archivo CSV y selecciona las columnas relevantes
index_alt <- read_csv("C:/Users/AVRIL/Desktop/Spillovers/all_daily_index.csv")
data_selected <- index_alt[, c("Date", "AI_INDEX", "Fintech_Index", "Blockchain_Index")]
# Function for summary statistics
summary_stats <- function(data) {
  return(data.frame(
    Mean = mean(data, na.rm = TRUE),
    StdDev = sd(data, na.rm = TRUE),
    Min = min(data, na.rm = TRUE),
    P25 = quantile(data, 0.25, na.rm = TRUE),
    P50 = median(data, na.rm = TRUE),
    P75 = quantile(data, 0.75, na.rm = TRUE),
    Max = max(data, na.rm = TRUE),
    Skewness = skewness(data, na.rm = TRUE),
    Kurtosis = kurtosis(data, na.rm = TRUE)
  ))
}

# Calculate statistics and tests for each index
results <- data.frame(
  Test = c(
    "Mean", "Standard Deviation", "Minimum", "25th Percentile", "Median",
    "75th Percentile", "Maximum", "Skewness", "Kurtosis", "Jarque-Bera (p-value)",
    "ADF Test (p-value)", "KPSS Test (p-value)", "PP Test (p-value)", "ERS Test",
    "ARCH Test (p-value)", "Weighted Portmanteau Test (p-value)", "Q2(20) Test (p-value)",
    "Outlier detection (Chen and Liu)","Correlation Matrix and R-squared"
  ),
  AI_INDEX = NA, Fintech_Index = NA, Blockchain_Index = NA
)

# Populate the table with summary stats
stats_ai <- summary_stats(data_selected$AI_INDEX)
stats_fintech <- summary_stats(data_selected$Fintech_Index)
stats_blockchain <- summary_stats(data_selected$Blockchain_Index)
results$AI_INDEX[1:9] <- as.numeric(stats_ai)
results$Fintech_Index[1:9] <- as.numeric(stats_fintech)
results$Blockchain_Index[1:9] <- as.numeric(stats_blockchain)

# Normality and stationarity tests
results$AI_INDEX[10] <- jarque.bera.test(data_selected$AI_INDEX)$p.value
results$Fintech_Index[10] <- jarque.bera.test(data_selected$Fintech_Index)$p.value
results$Blockchain_Index[10] <- jarque.bera.test(data_selected$Blockchain_Index)$p.value

results$AI_INDEX[11] <- adf.test(data_selected$AI_INDEX)$p.value
results$Fintech_Index[11] <- adf.test(data_selected$Fintech_Index)$p.value
results$Blockchain_Index[11] <- adf.test(data_selected$Blockchain_Index)$p.value

results$AI_INDEX[12] <- kpss.test(data_selected$AI_INDEX)$p.value
results$Fintech_Index[12] <- kpss.test(data_selected$Fintech_Index)$p.value
results$Blockchain_Index[12] <- kpss.test(data_selected$Blockchain_Index)$p.value

results$AI_INDEX[13] <- pp.test(data_selected$AI_INDEX)$p.value
results$Fintech_Index[13] <- pp.test(data_selected$Fintech_Index)$p.value
results$Blockchain_Index[13] <- pp.test(data_selected$Blockchain_Index)$p.value

results$AI_INDEX[14] <- ur.ers(data_selected$AI_INDEX, type = "DF-GLS")@teststat
results$Fintech_Index[14] <- ur.ers(data_selected$Fintech_Index, type = "DF-GLS")@teststat
results$Blockchain_Index[14] <- ur.ers(data_selected$Blockchain_Index, type = "DF-GLS")@teststat

# ARCH test
results$AI_INDEX[15] <- ArchTest(data_selected$AI_INDEX)$p.value
results$Fintech_Index[15] <- ArchTest(data_selected$Fintech_Index)$p.value
results$Blockchain_Index[15] <- ArchTest(data_selected$Blockchain_Index)$p.value

# Portmanteau test
results$portmanteau_ai <- Weighted.Box.test(data_selected$AI_INDEX)$p.value
results$portmanteau_fintech <- Weighted.Box.test(data_selected$Fintech_Index)$p.value
results$portmanteau_blockchain <- Weighted.Box.test(data_selected$Blockchain_Index)$p.value

# Q2(20) test
results$AI_INDEX[17] <- Box.test(data_selected$AI_INDEX^2, lag = 20, type = "Ljung-Box")$p.value
results$Fintech_Index[17] <- Box.test(data_selected$Fintech_Index^2, lag = 20, type = "Ljung-Box")$p.value
results$Blockchain_Index[17] <- Box.test(data_selected$Blockchain_Index^2, lag = 20, type = "Ljung-Box")$p.value

# Outlier detection (Chen and Liu)
results$outliers_ai <- sum(scores(data_selected$AI_INDEX, type = "chisq", prob = 0.05) != 0)
results$outliers_fintech <- sum(scores(data_selected$Fintech_Index, type = "chisq", prob = 0.05) != 0)
results$outliers_blockchain <- sum(scores(data_selected$Blockchain_Index, type = "chisq", prob = 0.05) != 0)

# Correlation Matrix and R-squared
cor_matrix <- cor(data_selected[, -1], use = "complete.obs")
r_squared <- cor_matrix^2

print(results)
##                                   Test     AI_INDEX Fintech_Index
## 1                                 Mean 2699.7315936  1209.7872783
## 2                   Standard Deviation  850.1473182   206.6297993
## 3                              Minimum 1000.0000000   914.2184504
## 4                      25th Percentile 2062.1671428  1051.8628547
## 5                               Median 2755.3700000  1160.7644460
## 6                      75th Percentile 3322.8946430  1278.8496108
## 7                              Maximum 4397.7200000  1737.2841440
## 8                             Skewness   -0.0947793     0.9544354
## 9                             Kurtosis    2.0739102     2.9587914
## 10               Jarque-Bera (p-value)    0.0000000     0.0000000
## 11                  ADF Test (p-value)    0.5827919     0.7454094
## 12                 KPSS Test (p-value)    0.0100000     0.0100000
## 13                   PP Test (p-value)    0.7266787     0.8964073
## 14                            ERS Test    0.9026858     1.9007764
## 15                 ARCH Test (p-value)    0.0000000     0.0000000
## 16 Weighted Portmanteau Test (p-value)           NA            NA
## 17               Q2(20) Test (p-value)    0.0000000     0.0000000
## 18    Outlier detection (Chen and Liu)           NA            NA
## 19    Correlation Matrix and R-squared           NA            NA
##    Blockchain_Index portmanteau_ai portmanteau_fintech portmanteau_blockchain
## 1      1761.7621693              0                   0                      0
## 2       464.6372545              0                   0                      0
## 3       950.4030182              0                   0                      0
## 4      1366.1408790              0                   0                      0
## 5      1681.5327235              0                   0                      0
## 6      2201.7356433              0                   0                      0
## 7      2766.3975000              0                   0                      0
## 8         0.2230307              0                   0                      0
## 9         1.8636058              0                   0                      0
## 10        0.0000000              0                   0                      0
## 11        0.8015316              0                   0                      0
## 12        0.0100000              0                   0                      0
## 13        0.9193304              0                   0                      0
## 14        0.2302577              0                   0                      0
## 15        0.0000000              0                   0                      0
## 16               NA              0                   0                      0
## 17        0.0000000              0                   0                      0
## 18               NA              0                   0                      0
## 19               NA              0                   0                      0
##    outliers_ai outliers_fintech outliers_blockchain
## 1         1899             1981                1985
## 2         1899             1981                1985
## 3         1899             1981                1985
## 4         1899             1981                1985
## 5         1899             1981                1985
## 6         1899             1981                1985
## 7         1899             1981                1985
## 8         1899             1981                1985
## 9         1899             1981                1985
## 10        1899             1981                1985
## 11        1899             1981                1985
## 12        1899             1981                1985
## 13        1899             1981                1985
## 14        1899             1981                1985
## 15        1899             1981                1985
## 16        1899             1981                1985
## 17        1899             1981                1985
## 18        1899             1981                1985
## 19        1899             1981                1985

Conversion a estacionaria

library(dplyr)
library(tseries)
library(forecast)
library(rugarch)

# Crear columnas de diferencias para hacer estacionarios los datos
data_selected2 <- data_selected %>%
  mutate(
    AI_INDEX_diff = c(NA, diff(AI_INDEX, differences = 1)),
    Fintech_Index_diff = c(NA, diff(Fintech_Index, differences = 1)),
    Blockchain_Index_diff = c(NA, diff(Blockchain_Index, differences = 1))
  )

# Remover las filas con NA después de la diferenciación
data_selected2 <- na.omit(data_selected2)

Tests y Estadísticos

Se realiza análisis de:

  • ADF Test (Prueba de Dickey-Fuller Aumentada): Este test ayuda a determinar si una serie es estacionaria. Un valor p-value bajo (típicamente < 0.05) sugiere que la serie es estacionaria. En tu caso, ambos índices (AI_INDEX_diff y Fintech_Index_diff) tienen p-values bajos en el ADF, indicando que probablemente sean estacionarios en sus diferencias.

  • KPSS Test: Contrario al ADF, el KPSS prueba si una serie es no estacionaria. Un p-value bajo indica no estacionariedad. En este caso, los p-values son relativamente altos (> 0.05), lo cual es consistente con la idea de que las series diferenciales son estacionarias.

  • PP Test (Prueba de Phillips-Perron): No hay datos en la tabla para el PP test, pero este también se usa para confirmar la estacionariedad. Si tienes otros resultados de PP, podrían complementar el análisis.

  • ERS Test (Elliot-Rothenberg-Stock): Este es otro test para estacionariedad, donde el valor debe ser cercano a cero para indicar estacionariedad. Dado que tienes valores negativos altos, esto también sugiere que las series pueden ser estacionarias.

  • ARCH Test: Esta prueba evalúa la heterocedasticidad condicional en la serie (es decir, si la varianza cambia con el tiempo). Un p-value bajo (como en este caso, 0.000000 para ambos índices) indica que existe heterocedasticidad, lo cual es común en datos financieros y sugiere la presencia de volatilidad cambiante.

  • Weighted Portmanteau Test y Q2(20) Test: Ambos sirven para evaluar la autocorrelación en las series de tiempo. Valores p-value extremadamente bajos indican que existe autocorrelación significativa. Esto sugiere que las series tienen dependencia temporal, lo cual es importante para un modelo de series de tiempo como el TVP-VAR.

  • Outlier Detection: Los valores altos en detección de outliers pueden indicar puntos atípicos que podrían afectar la estabilidad del modelo. En este caso, ambos índices tienen valores altos, lo que sugiere presencia de outliers. Para un TVP-VAR, es importante considerar cómo los outliers podrían influir en los parámetros cambiantes a lo largo del tiempo.

En conclusión, las series son estacionarias, lo cual es un permite generar modelos de series temporales como TVP-VAR. La presencia de autocorrelación y heterocedasticidad es consistente con datos financieros, lo que justifica el uso de un modelo que capture dinámicas temporales cambiantes, como el TVP-VAR. Sin embargo, la detección de outliers sugiere que se necesita un preprocesamiento para no afectar la estabilidad dy/o estimación de los parámetros en el modelo.

# Function for summary statistics
AI_INDEX_diff <- na.omit(data_selected2$AI_INDEX_diff)
Fintech_Index_diff <- na.omit(data_selected2$Fintech_Index_diff)
Blockchain_Index_diff <- na.omit(data_selected2$Blockchain_Index_diff)

summary_stats <- function(data) {
  return(data.frame(
    Mean = mean(data, na.rm = TRUE),
    StdDev = sd(data, na.rm = TRUE),
    Min = min(data, na.rm = TRUE),
    P25 = quantile(data, 0.25, na.rm = TRUE),
    P50 = median(data, na.rm = TRUE),
    P75 = quantile(data, 0.75, na.rm = TRUE),
    Max = max(data, na.rm = TRUE),
    Skewness = skewness(data, na.rm = TRUE),
    Kurtosis = kurtosis(data, na.rm = TRUE)
  ))
}

# Calculate statistics and tests for each differenced index
results <- data.frame(
  Test = c(
    "Mean", "Standard Deviation", "Minimum", "25th Percentile", "Median",
    "75th Percentile", "Maximum", "Skewness", "Kurtosis", "Jarque-Bera (p-value)",
    "ADF Test (p-value)", "KPSS Test (p-value)", "PP Test (p-value)", "ERS Test",
    "ARCH Test (p-value)", "Weighted Portmanteau Test (p-value)", "Q2(20) Test (p-value)",
    "Outlier detection (Chen and Liu)", "Correlation Matrix and R-squared"
  ),
  AI_INDEX_diff = NA, Fintech_Index_diff = NA, Blockchain_Index_diff = NA
)

# Populate the table with summary stats
stats_ai <- summary_stats(data_selected2$AI_INDEX_diff)
stats_fintech <- summary_stats(data_selected2$Fintech_Index_diff)
stats_blockchain <- summary_stats(data_selected2$Blockchain_Index_diff)
results$AI_INDEX_diff[1:9] <- as.numeric(stats_ai)
results$Fintech_Index_diff[1:9] <- as.numeric(stats_fintech)
results$Blockchain_Index_diff[1:9] <- as.numeric(stats_blockchain)

# Normality and stationarity tests
results$AI_INDEX_diff[10] <- jarque.bera.test(data_selected2$AI_INDEX_diff)$p.value
results$Fintech_Index_diff[10] <- jarque.bera.test(data_selected2$Fintech_Index_diff)$p.value
results$Blockchain_Index_diff[10] <- jarque.bera.test(data_selected2$Blockchain_Index_diff)$p.value

#results$AI_INDEX_diff[11] <- adf.test(na.omit(data_selected$AI_INDEX_diff), alternative = "stationary")$p.value
#results$Fintech_Index_diff[11] <- adf.test(na.omit(data_selected$Fintech_Index_diff), alternative = "stationary")$p.value
#results$Blockchain_Index_diff[11] <- adf.test(na.omit(data_selected$Blockchain_Index_diff), alternative = "stationary")$p.value

results$AI_INDEX_diff[12] <- kpss.test(data_selected2$AI_INDEX_diff)$p.value
results$Fintech_Index_diff[12] <- kpss.test(data_selected2$Fintech_Index_diff)$p.value
results$Blockchain_Index_diff[12] <- kpss.test(data_selected2$Blockchain_Index_diff)$p.value

results$AI_INDEX_diff[13] <- pp.test(data_selected2$AI_INDEX_diff)$p.value
results$Fintech_Index_diff[13] <- pp.test(data_selected2$Fintech_Index_diff)$p.value
results$Blockchain_Index_diff[13] <- pp.test(data_selected2$Blockchain_Index_diff)$p.value

results$AI_INDEX_diff[14] <- ur.ers(data_selected2$AI_INDEX_diff, type = "DF-GLS")@teststat
results$Fintech_Index_diff[14] <- ur.ers(data_selected2$Fintech_Index_diff, type = "DF-GLS")@teststat
results$Blockchain_Index_diff[14] <- ur.ers(data_selected2$Blockchain_Index_diff, type = "DF-GLS")@teststat

# ARCH test
results$AI_INDEX_diff[15] <- ArchTest(data_selected2$AI_INDEX_diff)$p.value
results$Fintech_Index_diff[15] <- ArchTest(data_selected2$Fintech_Index_diff)$p.value
results$Blockchain_Index_diff[15] <- ArchTest(data_selected2$Blockchain_Index_diff)$p.value

# Portmanteau test
results$AI_INDEX_diff[16] <- Weighted.Box.test(data_selected2$AI_INDEX_diff)$p.value
results$Fintech_Index_diff[16] <- Weighted.Box.test(data_selected2$Fintech_Index_diff)$p.value
results$Blockchain_Index_diff[16] <- Weighted.Box.test(data_selected2$Blockchain_Index_diff)$p.value

# Q2(20) test
results$AI_INDEX_diff[17] <- Box.test(data_selected2$AI_INDEX_diff^2, lag = 20, type = "Ljung-Box")$p.value
results$Fintech_Index_diff[17] <- Box.test(data_selected2$Fintech_Index_diff^2, lag = 20, type = "Ljung-Box")$p.value
results$Blockchain_Index_diff[17] <- Box.test(data_selected2$Blockchain_Index_diff^2, lag = 20, type = "Ljung-Box")$p.value

# Outlier detection (Chen and Liu)
results$AI_INDEX_diff[18] <- sum(scores(data_selected2$AI_INDEX_diff, type = "chisq", prob = 0.05) != 0)
results$Fintech_Index_diff[18] <- sum(scores(data_selected2$Fintech_Index_diff, type = "chisq", prob = 0.05) != 0)
results$Blockchain_Index_diff[18] <- sum(scores(data_selected2$Blockchain_Index_diff, type = "chisq", prob = 0.05) != 0)

# Correlation Matrix and R-squared
cor_matrix <- cor(data_selected2[, c("AI_INDEX_diff", "Fintech_Index_diff", "Blockchain_Index_diff")], use = "complete.obs")
r_squared <- cor_matrix^2

# Display the final results table
print(results)
##                                   Test  AI_INDEX_diff Fintech_Index_diff
## 1                                 Mean   1.605022e+00       3.260165e-01
## 2                   Standard Deviation   1.662849e+01       2.325218e+00
## 3                              Minimum  -4.960429e+01      -6.911148e+00
## 4                      25th Percentile  -7.454286e+00      -1.224464e+00
## 5                               Median   2.644286e+00       3.266700e-01
## 6                      75th Percentile   1.180429e+01       1.755698e+00
## 7                              Maximum   4.099429e+01       8.302190e+00
## 8                             Skewness  -4.090636e-01       6.410631e-02
## 9                             Kurtosis   3.295603e+00       3.627935e+00
## 10               Jarque-Bera (p-value)   9.103829e-15       2.387007e-08
## 11                  ADF Test (p-value)             NA                 NA
## 12                 KPSS Test (p-value)   1.000000e-01       8.650384e-02
## 13                   PP Test (p-value)   1.000000e-02       1.000000e-02
## 14                            ERS Test  -1.417563e+01      -1.281487e+01
## 15                 ARCH Test (p-value)   0.000000e+00       0.000000e+00
## 16 Weighted Portmanteau Test (p-value)  1.147220e-320       0.000000e+00
## 17               Q2(20) Test (p-value)   0.000000e+00       0.000000e+00
## 18    Outlier detection (Chen and Liu)   1.890000e+03       1.974000e+03
## 19    Correlation Matrix and R-squared             NA                 NA
##    Blockchain_Index_diff
## 1              0.6841407
## 2              9.5406084
## 3            -31.7119610
## 4             -3.7044970
## 5              1.1562560
## 6              5.5124395
## 7             40.7862190
## 8             -0.2052831
## 9              4.9185513
## 10             0.0000000
## 11                    NA
## 12             0.1000000
## 13             0.0100000
## 14           -14.2342870
## 15             0.0000000
## 16             0.0000000
## 17             0.0000000
## 18          1890.0000000
## 19                    NA
print(cor_matrix)
##                       AI_INDEX_diff Fintech_Index_diff Blockchain_Index_diff
## AI_INDEX_diff            1.00000000        -0.07104258            0.15822325
## Fintech_Index_diff      -0.07104258         1.00000000            0.03717008
## Blockchain_Index_diff    0.15822325         0.03717008            1.00000000
print(r_squared)
##                       AI_INDEX_diff Fintech_Index_diff Blockchain_Index_diff
## AI_INDEX_diff           1.000000000        0.005047048           0.025034598
## Fintech_Index_diff      0.005047048        1.000000000           0.001381615
## Blockchain_Index_diff   0.025034598        0.001381615           1.000000000

Gabauer and Gupta (2018): On the transmission mechanism of country-specific and international economic uncertainty spillovers: Evidence from a TVP-VAR connectedness decomposition approach

data_zoo2 <- zoo(data_selected2[, c("AI_INDEX_diff", "Fintech_Index_diff", "Blockchain_Index_diff")], 
                 order.by = data_selected2$Date)

# Configuración de parámetros para TVPVAR
nlag <- 2       # Orden del rezago
lambda <- c(0.99, 0.99)  # Valores de decaimiento para el filtro

# Crear la lista de configuración necesaria
config <- list(l = lambda, nlag = nlag)

# Estimar el modelo TVP-VAR con los parámetros especificados
tvpvar_model <- TVPVAR(data_zoo2, configuration = config)
dca = ConnectednessApproach(data_zoo2, 
                            nlag=1,
                            nfore=10,
                            model="TVP-VAR",
                            connectedness="Time",
                            window.size=200,
                            VAR_config=list(TVPVAR=list(kappa1=0.99, kappa2=0.99, prior="BayesPrior")))

Table 1: Connectedness table

kable(dca$TABLE)
AI_INDEX_diff Fintech_Index_diff Blockchain_Index_diff FROM
AI_INDEX_diff 93.53 3.12 3.36 6.47
Fintech_Index_diff 3.33 94.12 2.55 5.88
Blockchain_Index_diff 3.67 1.84 94.49 5.51
TO 7.00 4.96 5.91 17.87
Inc.Own 100.53 99.07 100.40 cTCI/TCI
NET 0.53 -0.93 0.40 8.93/5.96
NPT 2.00 0.00 1.00
# CONNECTEDNESS DECOMPOSITION
int = InternalConnectedness(dca, groups=list("Group1"=c(1), "Group2"=c(2), "Group3"=c(3)))
ext = ExternalConnectedness(dca, groups=list("Group1"=c(1), "Group2"=c(2), "Group3"=c(3)))
kable(int$TABLE)
AI_INDEX_diff Fintech_Index_diff Blockchain_Index_diff FROM
AI_INDEX_diff 93.53 0.00 0.00 0.00
Fintech_Index_diff 0.00 94.12 0.00 0.00
Blockchain_Index_diff 0.00 0.00 94.49 0.00
TO 0.00 0.00 0.00 0.00
Inc.Own 93.53 94.12 94.49 cTCI/TCI
NET 0.00 0.00 0.00 0.00/0.00
NPT 0.00 0.00 0.00
kable(ext$TABLE)
AI_INDEX_diff Fintech_Index_diff Blockchain_Index_diff FROM
AI_INDEX_diff 0.00 3.12 3.36 6.47
Fintech_Index_diff 3.33 0.00 2.55 5.88
Blockchain_Index_diff 3.67 1.84 0.00 5.51
TO 7.00 4.96 5.91 17.87
Inc.Own 7.00 4.96 5.91 cTCI/TCI
NET 0.53 -0.93 0.40 8.93/5.96
NPT 2.00 0.00 1.00
#Figure 3: Dynamic total connectedness
PlotTCI(dca, int, ylim=c(0, 40))

#Figure 4: Net total directional connectedness
PlotNET(dca, int, ylim=c(-10, 10))

#Figure 5: Total directional connectedness FROM others
PlotFROM(dca, int, ylim=c(0, 60))

#Figure 6: Total directional connectedness TO others
PlotTO(dca, int, ylim=c(0, 60))

#Figure 7: Internal net pairwise total directional connectedness
PlotNPDC(dca, int, ylim=c(-5, 5))

Cocca, Gabauer, and Pomberger (2024): Clean energy market connectedness and investment strategies: New evidence from DCC-GARCH R2 decomposed connectedness measures

# Convierte la columna 'Date' a formato Date
date <- as.Date(data_selected2$Date, format="%d/%m/%Y")

# Crea la serie de tiempo (zoo) solo con las columnas seleccionadas
Y <- zoo(data_selected2[, c("Fintech_Index_diff", "AI_INDEX_diff", "Blockchain_Index_diff")], order.by = date)

# Asegúrate de que los datos sean numéricos y elimina valores NA
Y <- na.omit(zoo(data.frame(
  Fintech_Index_diff = as.numeric(data_selected2$Fintech_Index_diff),
  AI_INDEX_diff = as.numeric(data_selected2$AI_INDEX_diff),
  Blockchain_Index_diff = as.numeric(data_selected2$Blockchain_Index_diff)
), order.by = date))

# Reemplaza los valores NA restantes por 0
Y[is.na(Y)] <- 0

# Establece 'dimnames' de Y con números como índices (como en Y2) sin cambiar el índice de fecha
dimnames(Y) <- list(as.character(1:nrow(Y)), colnames(Y))

NAMES = colnames(Y)
k = ncol(Y)
t = nrow(Y)

# Verifica la estructura de Y
str(Y)
## 'zoo' series from 2019-01-08 to 2024-08-19
##   Data: num [1:2051, 1:3] -0.675 -0.675 -0.675 -0.675 -0.675 ...
##  - attr(*, "dimnames")=List of 2
##   ..$ : chr [1:2051] "1" "2" "3" "4" ...
##   ..$ : chr [1:3] "Fintech_Index_diff" "AI_INDEX_diff" "Blockchain_Index_diff"
##   Index:  Date[1:2051], format: "2019-01-08" "2019-01-09" "2019-01-10" "2019-01-11" "2019-01-12" ...
kable(SummaryStatistics(Y, nlag=20))
Fintech_Index_diff AI_INDEX_diff Blockchain_Index_diff
Mean 0.326*** 1.605*** 0.684***
(0.000) (0.000) (0.001)
Variance 5.407 276.507 91.023
Skewness 0.064 -0.409*** -0.205***
(0.235) (0.000) (0.000)
Ex.Kurtosis 0.628*** 0.296** 1.919***
(0.000) (0.013) (0.000)
JB 35.101*** 64.667*** 328.964***
(0.000) (0.000) (0.000)
ERS -12.815 -14.176 -14.234
(0.000) (0.000) (0.000)
Q(20) 3862.325*** 3300.007*** 3762.681***
(0.000) (0.000) (0.000)
Q2(20) 3643.339*** 5087.508*** 4171.154***
(0.000) (0.000) (0.000)
kendall Fintech_Index_diff AI_INDEX_diff Blockchain_Index_diff
Fintech_Index_diff 1.000*** -0.065*** 0.016
AI_INDEX_diff -0.065*** 1.000*** 0.120***
Blockchain_Index_diff 0.016 0.120*** 1.000***

Figure 0: Percentage changes

par(mfcol = c(ceiling(k/2),2), oma = c(0, 1, 0, 0) + 0.5, mar = c(1, 1, 1, 1) + 0.5, mgp = c(1, 0.4, 0))
for (i in 1:k) {
  plot(date,Y[,i],type='l',las=1,xaxs='i',yaxs='i',ylim=c(-50,50),xlab='',ylab='',main=paste(NAMES[i]),tck=-.02,col='steelblue4')
  grid(NA,NULL)
  lines(date,Y[,i],col='steelblue4')
  abline(h=0,lty=3)
  box()
}

spec <- list()

# Itera sobre cada columna de Y
for (i in 1:k) {
  # Intenta seleccionar el mejor modelo GARCH para cada serie
  u <- tryCatch({
    GARCHselection(Y[, i],
                   distributions = c("norm", "std", "sstd", "ged", "sged"),
                   models = c("sGARCH", "gjrGARCH", "eGARCH", "iGARCH", "AVGARCH", "TGARCH"))
  }, error = function(e) {
    warning(paste("Error al seleccionar modelo GARCH para la variable", i, ":", e$message))
    NULL
  })
  
  # Si 'u' no es NULL y tiene un mejor modelo, agrega a 'spec'
  if (!is.null(u) && !is.null(u$best_ugarch)) {
    spec[[i]] <- u$best_ugarch
  } else {
    # Si no se seleccionó un modelo, asigna un modelo GARCH(1,1) por defecto
    warning(paste("No se seleccionó ningún modelo GARCH para", NAMES[i], ". Usando modelo GARCH(1,1) con distribución normal"))
    spec[[i]] <- ugarchspec(variance.model = list(model = "sGARCH", garchOrder = c(1, 1)),
                            mean.model = list(armaOrder = c(0, 0)),
                            distribution.model = "norm")
  }
}

# Verifica que 'spec' tenga modelos para cada serie en Y
if (length(spec) != k) {
  stop("spec no contiene modelos válidos para todas las series de Y")
}

# Ejecuta el modelo DCC-GARCH si spec es válida
fit <- BivariateDCCGARCH(Y, spec)
## [1] "DCC-GARCH estimation based on Fintech_Index_diff and AI_INDEX_diff"
## [1] "DCC-GARCH estimation based on Fintech_Index_diff and Blockchain_Index_diff"
## [1] "DCC-GARCH estimation based on AI_INDEX_diff and Blockchain_Index_diff"

Table 4: Evaluation of univariate GARCH performance

H = fit$H_t
R = fit$R_t

uGARCH_table = NULL
for (i in 1:k) {
  fit = ugarchfit(spec[[i]], Y[,i])
  gt = GARCHtests(fit, lag=20)
  uGARCH_table = rbind(uGARCH_table, gt$TABLE)
}

kable(uGARCH_table)
SignBias WARCH(20) VaR CVaR VaR Dur.
statistics 0.1948239 0.3148009 113.6998 -93.6559 0.1666667
pvalues 0.8455501 1.0000000 0.0000 0.0230 0.2505399
statistics 1.8538228 4.2396416 Inf -2049.9756 20.0098039
pvalues 0.0639084 0.9801528 0.0000 1.0000 0.0000000
statistics 0.9732951 13.9600165 Inf -1795.8416 10.9705882
pvalues 0.3305217 0.1719617 0.0000 1.0000 0.0004832

Figure 3: Dynamic conditional correlations

par(mfcol = c(ceiling(k/2),2), oma = c(0, 1, 0, 0) + 0.5, mar = c(1, 1, 1, 1) + 0.5, mgp = c(1, 0.4, 0))
for (j in 1:k) {
  plot(date,R[j,j,],type='l',las=1,xaxs='i',yaxs='i',xlab='',ylab='',main=paste(NAMES[j]),tck=-.02,col=j,ylim=c(-1.1,1.1))
  grid(NA,NULL)
  for (i in 1:k) {
    lines(date,R[j,i,],col=i)
    abline(h=0,lty=3)
    box()
  }
  legend("bottom",NAMES[-j],fill=c(1:k)[-j],bty="n",cex=0.75,ncol=k)
}

Table 5: Averaged connectedness measures

dca = R2Correlations(R)
##   |                                                                              |                                                                      |   0%  |                                                                              |                                                                      |   1%  |                                                                              |=                                                                     |   1%  |                                                                              |=                                                                     |   2%  |                                                                              |==                                                                    |   2%  |                                                                              |==                                                                    |   3%  |                                                                              |==                                                                    |   4%  |                                                                              |===                                                                   |   4%  |                                                                              |===                                                                   |   5%  |                                                                              |====                                                                  |   5%  |                                                                              |====                                                                  |   6%  |                                                                              |=====                                                                 |   6%  |                                                                              |=====                                                                 |   7%  |                                                                              |=====                                                                 |   8%  |                                                                              |======                                                                |   8%  |                                                                              |======                                                                |   9%  |                                                                              |=======                                                               |   9%  |                                                                              |=======                                                               |  10%  |                                                                              |=======                                                               |  11%  |                                                                              |========                                                              |  11%  |                                                                              |========                                                              |  12%  |                                                                              |=========                                                             |  12%  |                                                                              |=========                                                             |  13%  |                                                                              |=========                                                             |  14%  |                                                                              |==========                                                            |  14%  |                                                                              |==========                                                            |  15%  |                                                                              |===========                                                           |  15%  |                                                                              |===========                                                           |  16%  |                                                                              |============                                                          |  16%  |                                                                              |============                                                          |  17%  |                                                                              |============                                                          |  18%  |                                                                              |=============                                                         |  18%  |                                                                              |=============                                                         |  19%  |                                                                              |==============                                                        |  19%  |                                                                              |==============                                                        |  20%  |                                                                              |==============                                                        |  21%  |                                                                              |===============                                                       |  21%  |                                                                              |===============                                                       |  22%  |                                                                              |================                                                      |  22%  |                                                                              |================                                                      |  23%  |                                                                              |================                                                      |  24%  |                                                                              |=================                                                     |  24%  |                                                                              |=================                                                     |  25%  |                                                                              |==================                                                    |  25%  |                                                                              |==================                                                    |  26%  |                                                                              |===================                                                   |  26%  |                                                                              |===================                                                   |  27%  |                                                                              |===================                                                   |  28%  |                                                                              |====================                                                  |  28%  |                                                                              |====================                                                  |  29%  |                                                                              |=====================                                                 |  29%  |                                                                              |=====================                                                 |  30%  |                                                                              |=====================                                                 |  31%  |                                                                              |======================                                                |  31%  |                                                                              |======================                                                |  32%  |                                                                              |=======================                                               |  32%  |                                                                              |=======================                                               |  33%  |                                                                              |=======================                                               |  34%  |                                                                              |========================                                              |  34%  |                                                                              |========================                                              |  35%  |                                                                              |=========================                                             |  35%  |                                                                              |=========================                                             |  36%  |                                                                              |==========================                                            |  36%  |                                                                              |==========================                                            |  37%  |                                                                              |==========================                                            |  38%  |                                                                              |===========================                                           |  38%  |                                                                              |===========================                                           |  39%  |                                                                              |============================                                          |  39%  |                                                                              |============================                                          |  40%  |                                                                              |============================                                          |  41%  |                                                                              |=============================                                         |  41%  |                                                                              |=============================                                         |  42%  |                                                                              |==============================                                        |  42%  |                                                                              |==============================                                        |  43%  |                                                                              |==============================                                        |  44%  |                                                                              |===============================                                       |  44%  |                                                                              |===============================                                       |  45%  |                                                                              |================================                                      |  45%  |                                                                              |================================                                      |  46%  |                                                                              |=================================                                     |  46%  |                                                                              |=================================                                     |  47%  |                                                                              |=================================                                     |  48%  |                                                                              |==================================                                    |  48%  |                                                                              |==================================                                    |  49%  |                                                                              |===================================                                   |  49%  |                                                                              |===================================                                   |  50%  |                                                                              |===================================                                   |  51%  |                                                                              |====================================                                  |  51%  |                                                                              |====================================                                  |  52%  |                                                                              |=====================================                                 |  52%  |                                                                              |=====================================                                 |  53%  |                                                                              |=====================================                                 |  54%  |                                                                              |======================================                                |  54%  |                                                                              |======================================                                |  55%  |                                                                              |=======================================                               |  55%  |                                                                              |=======================================                               |  56%  |                                                                              |========================================                              |  56%  |                                                                              |========================================                              |  57%  |                                                                              |========================================                              |  58%  |                                                                              |=========================================                             |  58%  |                                                                              |=========================================                             |  59%  |                                                                              |==========================================                            |  59%  |                                                                              |==========================================                            |  60%  |                                                                              |==========================================                            |  61%  |                                                                              |===========================================                           |  61%  |                                                                              |===========================================                           |  62%  |                                                                              |============================================                          |  62%  |                                                                              |============================================                          |  63%  |                                                                              |============================================                          |  64%  |                                                                              |=============================================                         |  64%  |                                                                              |=============================================                         |  65%  |                                                                              |==============================================                        |  65%  |                                                                              |==============================================                        |  66%  |                                                                              |===============================================                       |  66%  |                                                                              |===============================================                       |  67%  |                                                                              |===============================================                       |  68%  |                                                                              |================================================                      |  68%  |                                                                              |================================================                      |  69%  |                                                                              |=================================================                     |  69%  |                                                                              |=================================================                     |  70%  |                                                                              |=================================================                     |  71%  |                                                                              |==================================================                    |  71%  |                                                                              |==================================================                    |  72%  |                                                                              |===================================================                   |  72%  |                                                                              |===================================================                   |  73%  |                                                                              |===================================================                   |  74%  |                                                                              |====================================================                  |  74%  |                                                                              |====================================================                  |  75%  |                                                                              |=====================================================                 |  75%  |                                                                              |=====================================================                 |  76%  |                                                                              |======================================================                |  76%  |                                                                              |======================================================                |  77%  |                                                                              |======================================================                |  78%  |                                                                              |=======================================================               |  78%  |                                                                              |=======================================================               |  79%  |                                                                              |========================================================              |  79%  |                                                                              |========================================================              |  80%  |                                                                              |========================================================              |  81%  |                                                                              |=========================================================             |  81%  |                                                                              |=========================================================             |  82%  |                                                                              |==========================================================            |  82%  |                                                                              |==========================================================            |  83%  |                                                                              |==========================================================            |  84%  |                                                                              |===========================================================           |  84%  |                                                                              |===========================================================           |  85%  |                                                                              |============================================================          |  85%  |                                                                              |============================================================          |  86%  |                                                                              |=============================================================         |  86%  |                                                                              |=============================================================         |  87%  |                                                                              |=============================================================         |  88%  |                                                                              |==============================================================        |  88%  |                                                                              |==============================================================        |  89%  |                                                                              |===============================================================       |  89%  |                                                                              |===============================================================       |  90%  |                                                                              |===============================================================       |  91%  |                                                                              |================================================================      |  91%  |                                                                              |================================================================      |  92%  |                                                                              |=================================================================     |  92%  |                                                                              |=================================================================     |  93%  |                                                                              |=================================================================     |  94%  |                                                                              |==================================================================    |  94%  |                                                                              |==================================================================    |  95%  |                                                                              |===================================================================   |  95%  |                                                                              |===================================================================   |  96%  |                                                                              |====================================================================  |  96%  |                                                                              |====================================================================  |  97%  |                                                                              |====================================================================  |  98%  |                                                                              |===================================================================== |  98%  |                                                                              |===================================================================== |  99%  |                                                                              |======================================================================|  99%  |                                                                              |======================================================================| 100%
kable(dca$TABLE)
Fintech_Index_diff AI_INDEX_diff Blockchain_Index_diff FROM
Fintech_Index_diff 100.00 37.80 31.55 69.35
AI_INDEX_diff 33.59 100.00 43.99 77.57
Blockchain_Index_diff 30.34 47.00 100.00 77.34
TO 63.93 84.80 75.54 224.27
Inc.Own 163.93 184.80 175.54 cTCI/TCI
NET -5.42 7.23 -1.81 112.14/74.76
NPT 0.00 2.00 1.00

Figure 4: Dynamic conditional R2 decomposed measures

r2c = apply(dca$CT,c(1,3),sum)-1
par(mfcol = c(ceiling(k/2),2), oma = c(0, 1, 0, 0) + 0.5, mar = c(1, 1, 1, 1) + 0.5, mgp = c(1, 0.4, 0))
for (j in 1:k) {
  r2dd = matrix(0,ncol=k,nrow=t)
  for (i in 1:t) {
    ded = rep(0,k)
    ded[j] = 1
    r2dd[i,] = cumsum(dca$CT[j,,i]-ded)
  }
  plot(date,100*r2c[j,]*NA,type="l",las=1,xlab="",ylab="",ylim=c(0,100),xaxs="i",tck=-0.01,yaxs="i",main=NAMES[j])
  grid(NA,NULL)
  for (i in k:1) {
    polygon(c(date, rev(date)), c(c(rep(0, t)), rev(100*r2dd[,i])), col=i, border=i)
  }
  box()
  legend("topleft",NAMES[-j],fill=c(1:k)[-j],bty="n",cex=0.75,ncol=1)
}

Figure 5: Dynamic total connectedness

par(mfcol = c(1,1), oma = c(0, 1, 0, 0) + 0.5, mar = c(1, 1, 1, 1) + 0.5, mgp = c(1, 0.4, 0))
plot(date,dca$TCI*NA,type='l',las=1,xaxs='i',yaxs='i',xlab='',ylab='',main='',tck=-.01, ylim=c(0,110))#c(max(c(0,min(TCI)-10)),max(TCI)+10))
grid(NA,NULL)
polygon(c(date, rev(date)), c(c(rep(0, t)), rev(dca$TCI)), col=1, border=1)
box()

Figure 6: Net total directional connectedness

par(mfcol = c(ceiling(k/2),2), oma = c(0, 0, 0, 0) + 0.5, mar = c(1, 1, 1, 1) + 0.5, mgp = c(1, 0.4, 0))
for (i in 1:k) {
  plot(date,dca$NET[,i]*NA,type='l',las=1,xaxs='i',yaxs='i',ylim=c(-20,20),xlab='',ylab='',main=paste("NET",NAMES[i]),tck=-.025)
  grid(NA,NULL)
  polygon(c(date, rev(date)), c(c(rep(0, t)), rev(dca$NET[,i])), col=1, border=1)
  abline(h=0,lty=3)
  box()
}

Table 7: Hedge ratios

method = "cumsum"
statistics = "Fisher"
metric = "StdDev"
hr = HedgeRatio(Y/100, H, statistics=statistics, method=method, metric=metric, digit=3)
kable(hr$TABLE)
Mean Std.Dev. 5% 95% HE p-value Return Std.Dev SR
Fintech_Index_diff/AI_INDEX_diff -0.007 0.204 -0.322 0.312 0.159 0.001 7.325 0.339 21.638
Fintech_Index_diff/Blockchain_Index_diff 0.028 0.372 -0.582 0.662 0.219 0.000 5.956 0.326 18.264
AI_INDEX_diff/Fintech_Index_diff 44.205 1233.519 -23.939 29.336 -30925.409 0.000 NaN 464.214 NaN
AI_INDEX_diff/Blockchain_Index_diff 0.303 2.634 -4.300 4.424 0.139 0.000 NaN 2.449 NaN
Blockchain_Index_diff/Fintech_Index_diff 43.850 1219.484 -15.240 14.257 -96079.861 0.000 NaN 469.456 NaN
Blockchain_Index_diff/AI_INDEX_diff 0.070 0.772 -1.138 1.198 0.272 0.001 NaN 1.292 NaN

Table 8: Multivariate hedging portfolios

mhp = MultivariateHedgingPortfolio(Y/100, H, statistics=statistics, method=method, digit=3)
kable(mhp$TABLE)
Mean Std.Dev. 5% 95% HE p-value Return Risk SR
Fintech_Index_diff/AI_INDEX_diff -0.002 0.303 -0.323 0.347 -0.042 0.356 7.109 0.377 18.869
Fintech_Index_diff/Blockchain_Index_diff 0.032 0.517 -0.554 0.604 -0.042 0.356 7.109 0.377 18.869
AI_INDEX_diff/Fintech_Index_diff 9.773 305.244 -13.666 14.813 -1267.873 0.000 21512.103 94.029 228.781
AI_INDEX_diff/Blockchain_Index_diff 0.269 8.526 -3.096 3.286 -1267.873 0.000 21512.103 94.029 228.781
Blockchain_Index_diff/Fintech_Index_diff -104.680 5196.637 -7.010 7.259 -574302.289 0.000 400.170 1147.749 0.349
Blockchain_Index_diff/AI_INDEX_diff 14.618 654.793 -0.956 1.118 -574302.289 0.000 400.170 1147.749 0.349

Figure 3: Dynamic conditional betas

par(mfcol = c(ceiling(k/2),2), oma = c(0, 1, 0, 0) + 0.5, mar = c(1, 1, 1, 1) + 0.5, mgp = c(1, 0.4, 0))
for (j in 1:k) {
  plot(date,mhp$Beta[j,j,]*NA,type='l',las=1,xaxs='i',yaxs='i',xlab='',ylab='',
       main=paste(NAMES[j]),tck=-.02,col=j,ylim=c(-0.5,80))
  grid(NA,NULL)
  coefs = lm(Y[,j]~Y[,-j])$coefficients[-1]
  for (i in 1:k) {
    if (i!=j) {
      lines(date,mhp$Beta[j,i,],col=i)
      abline(h=0,lty=3)
      box()
    }
  }
  col = 1:k
  col = col[-j]
  abline(h=coefs,lty=3,col=col)
  legend("bottom",NAMES[-j],fill=c(1:k)[-j],bty="n",cex=0.6,ncol=k)
}

Table 9: Optimal bivariate portfolio weights

bpw = BivariatePortfolio(Y/100, H, statistics=statistics, method=method, metric=metric, digit=3)
## The optimal bivariate portfolios are computed according to:
##  Kroner, K. F., & Ng, V. K. (1998). Modeling asymmetric comovements of asset returns. The Review of Financial Studies, 11(4), 817-844.
## 
##           Hedging effectiveness is calculated according to:
##  Ederington, L. H. (1979). The hedging performance of the new futures markets. The Journal of Finance, 34(1), 157-170.
## 
##           Statistics of the hedging effectiveness measure are implemented according to:
##  Antonakakis, N., Cunado, J., Filis, G., Gabauer, D., & de Gracia, F. P. (2020). Oil and asset classes implied volatilities: Investment strategies and hedging effectiveness. Energy Economics, 91, 104762.
kable(bpw$TABLE)
Mean Std.Dev. 5% 95% HE p-value SR
Fintech_Index_diff/AI_INDEX_diff 0.917 0.121 0.660 1.000 0.323 0.000 20.620
Fintech_Index_diff/Blockchain_Index_diff 0.823 0.237 0.352 1.000 0.292 0.000 15.807
AI_INDEX_diff/Fintech_Index_diff 0.083 0.121 0.000 0.340 0.987 0.000 20.620
AI_INDEX_diff/Blockchain_Index_diff 0.267 0.311 0.000 1.000 0.826 0.000 8.265
Blockchain_Index_diff/Fintech_Index_diff 0.177 0.237 0.000 0.648 0.958 0.000 15.807
Blockchain_Index_diff/AI_INDEX_diff 0.733 0.311 0.000 1.000 0.471 0.000 8.265

Table 10: Multivariate portfolio analysis

PCIc = dca$PCI
PCIg = dca$CT
for (l in 1:dim(dca$CT)[3]) {
  for (i in 1:k) {
    for (j in 1:k) {
      PCIg[i,j,l] = (2*R[i,j,l]^2)/(1+R[i,j,l]^2)
    }
  }
}
mvp = MinimumConnectednessPortfolio(Y/100, H, statistics=statistics, method=method, metric=metric, digit=3)
## The minimum connectedness portfolio is implemented according to:
##  Broadstock, D. C., Chatziantoniou, I., & Gabauer, D. (2022). Minimum connectedness portfolios and the market for green bonds: Advocating socially responsible investment (SRI) activity. In Applications in Energy Finance (pp. 217-253). Palgrave Macmillan, Cham.
## 
##           Hedging effectiveness is calculated according to:
##  Ederington, L. H. (1979). The hedging performance of the new futures markets. The Journal of Finance, 34(1), 157-170.
## 
##           Statistics of the hedging effectiveness measure are implemented according to:
##  Antonakakis, N., Cunado, J., Filis, G., Gabauer, D., & de Gracia, F. P. (2020). Oil and asset classes implied volatilities: Investment strategies and hedging effectiveness. Energy Economics, 91, 104762.
mcp = MinimumConnectednessPortfolio(Y/100, R, statistics=statistics, method=method, metric=metric, digit=3)
## The minimum connectedness portfolio is implemented according to:
##  Broadstock, D. C., Chatziantoniou, I., & Gabauer, D. (2022). Minimum connectedness portfolios and the market for green bonds: Advocating socially responsible investment (SRI) activity. In Applications in Energy Finance (pp. 217-253). Palgrave Macmillan, Cham.
## 
##           Hedging effectiveness is calculated according to:
##  Ederington, L. H. (1979). The hedging performance of the new futures markets. The Journal of Finance, 34(1), 157-170.
## 
##           Statistics of the hedging effectiveness measure are implemented according to:
##  Antonakakis, N., Cunado, J., Filis, G., Gabauer, D., & de Gracia, F. P. (2020). Oil and asset classes implied volatilities: Investment strategies and hedging effectiveness. Energy Economics, 91, 104762.
mpc = MinimumConnectednessPortfolio(Y/100, PCIc, statistics=statistics, method=method, metric=metric, digit=3)
## The minimum connectedness portfolio is implemented according to:
##  Broadstock, D. C., Chatziantoniou, I., & Gabauer, D. (2022). Minimum connectedness portfolios and the market for green bonds: Advocating socially responsible investment (SRI) activity. In Applications in Energy Finance (pp. 217-253). Palgrave Macmillan, Cham.
## 
##           Hedging effectiveness is calculated according to:
##  Ederington, L. H. (1979). The hedging performance of the new futures markets. The Journal of Finance, 34(1), 157-170.
## 
##           Statistics of the hedging effectiveness measure are implemented according to:
##  Antonakakis, N., Cunado, J., Filis, G., Gabauer, D., & de Gracia, F. P. (2020). Oil and asset classes implied volatilities: Investment strategies and hedging effectiveness. Energy Economics, 91, 104762.
mpg = MinimumConnectednessPortfolio(Y/100, PCIg, statistics=statistics, method=method, metric=metric, digit=3)
## The minimum connectedness portfolio is implemented according to:
##  Broadstock, D. C., Chatziantoniou, I., & Gabauer, D. (2022). Minimum connectedness portfolios and the market for green bonds: Advocating socially responsible investment (SRI) activity. In Applications in Energy Finance (pp. 217-253). Palgrave Macmillan, Cham.
## 
##           Hedging effectiveness is calculated according to:
##  Ederington, L. H. (1979). The hedging performance of the new futures markets. The Journal of Finance, 34(1), 157-170.
## 
##           Statistics of the hedging effectiveness measure are implemented according to:
##  Antonakakis, N., Cunado, J., Filis, G., Gabauer, D., & de Gracia, F. P. (2020). Oil and asset classes implied volatilities: Investment strategies and hedging effectiveness. Energy Economics, 91, 104762.
mrp = MinimumConnectednessPortfolio(Y/100, dca$CT, statistics=statistics, method=method, metric=metric, digit=3)
## The minimum connectedness portfolio is implemented according to:
##  Broadstock, D. C., Chatziantoniou, I., & Gabauer, D. (2022). Minimum connectedness portfolios and the market for green bonds: Advocating socially responsible investment (SRI) activity. In Applications in Energy Finance (pp. 217-253). Palgrave Macmillan, Cham.
## 
##           Hedging effectiveness is calculated according to:
##  Ederington, L. H. (1979). The hedging performance of the new futures markets. The Journal of Finance, 34(1), 157-170.
## 
##           Statistics of the hedging effectiveness measure are implemented according to:
##  Antonakakis, N., Cunado, J., Filis, G., Gabauer, D., & de Gracia, F. P. (2020). Oil and asset classes implied volatilities: Investment strategies and hedging effectiveness. Energy Economics, 91, 104762.
MVA = rbind(mvp$TABLE, mcp$TABLE, mpc$TABLE, mpg$TABLE, mrp$TABLE)
kable(MVA)
Mean Std.Dev. 5% 95% HE p-value SR
Fintech_Index_diff 0.733 0.260 0.205 1.000 0.080 0.060 27.348
AI_INDEX_diff 0.083 0.114 0.000 0.303 0.982 0.000 27.348
Blockchain_Index_diff 0.184 0.211 0.000 0.599 0.945 0.000 27.348
Fintech_Index_diff 0.317 0.193 0.000 0.500 -9.666 0.000 7.012
AI_INDEX_diff 0.359 0.210 0.000 0.608 0.791 0.000 7.012
Blockchain_Index_diff 0.324 0.202 0.000 0.539 0.366 0.000 7.012
Fintech_Index_diff 0.437 0.057 0.336 0.526 -4.470 0.000 2.358
AI_INDEX_diff 0.247 0.153 0.000 0.491 0.893 0.000 2.358
Blockchain_Index_diff 0.316 0.142 0.000 0.496 0.675 0.000 2.358
Fintech_Index_diff 0.442 0.121 0.000 0.527 -7.446 0.000 1.280
AI_INDEX_diff 0.201 0.244 0.000 0.523 0.835 0.000 1.280
Blockchain_Index_diff 0.357 0.226 0.000 0.544 0.498 0.000 1.280
Fintech_Index_diff 0.369 0.029 0.312 0.397 -6.206 0.000 4.049
AI_INDEX_diff 0.311 0.047 0.245 0.415 0.859 0.000 4.049
Blockchain_Index_diff 0.320 0.045 0.245 0.403 0.572 0.000 4.049

Table 11: Portfolio performance

library(PerformanceAnalytics)
library(xts)
port.mat = data.frame(
                     MVP=mvp$portfolio_return,
                     MCP=mcp$portfolio_return,
                     MPC=mpc$portfolio_return,
                     MPG=mpg$portfolio_return,
                     MRP=mrp$portfolio_return
                     )
port.xts = xts(port.mat, order.by=date)
ir = matrix(NA, nrow=1, ncol=ncol(port.xts))
colnames(ir) = colnames(port.xts)
rownames(ir) = "GRE"
for (i in 1:ncol(port.xts)) {
  ir[,i] = InformationRatio(Ra=port.xts[,i], Rb=Y[,1]/100)
}
k = ncol(port.xts)
table = matrix(NA, ncol=k, nrow=5)
for (i in 1:k) {
  table[,i] = c(
  # Retorno anualizado
  Return.annualized(port.xts[,i]),
  
  # Desviación estándar anualizada
  StdDev.annualized(port.xts[,i]),
  
  # Ratio de Sharpe anualizado
  SharpeRatio.annualized(port.xts[,i]),
  
  # Valor en Riesgo (VaR) con distribución normal y percentil del 95%
  VaR(as.numeric(port.xts[,i]), p=0.95, method="gaussian"),
  
  # Expectativa de Pérdida (ES) con distribución normal y percentil del 95%
  ES(as.numeric(port.xts[,i]), p=0.95, method="gaussian")
)
}
colnames(table) = colnames(port.xts)
rownames(table) = c("Return","StdDev","Sharpe Ratio (StdDev)","Sharpe Ratio (VaR)","Sharpe Ratio (CVaR)")
kable(rbind(table, ir))
MVP MCP MPC MPG MRP
Return 9.6835486 8.4523430 2.0357765 1.3735988 4.0116097
StdDev 0.3540848 1.2054953 0.8633213 1.0727126 0.9908285
Sharpe Ratio (StdDev) 27.3481082 7.0115107 2.3580751 1.2804910 4.0487427
Sharpe Ratio (VaR) -0.0364074 -0.1330273 -0.0876863 -0.0871908 -0.1010270
Sharpe Ratio (CVaR) -0.0072764 -0.0039005 -0.0002557 0.0017861 -0.0026197
GRE 21.1391511 5.7893087 1.0376525 0.2320275 2.8269034
LS0tDQp0aXRsZTogIlJldHVybiBhbmQgVm9sYXRpbGl0eSBTcGlsbG92ZXJzIEJldHdlZW4gRmluVGVjaCwgQmxvY2tjaGFpbiBhbmQgQUkgRmlybXMiDQpzdWJ0aXRsZTogIkVzdGFuY2lhIGRlIEludmVzdGlnYWNpw7NuIg0KYXV0aG9yOiAiQXZyaWwgTG9iYXRvIERlbGdhZG8iDQpkYXRlOiAiMjAyNC0xMS0wMSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgdGhlbWU6IGNlcnVsZWFuDQogICAgaGlnaGxpZ2h0OiBweWdtZW50cw0KLS0tDQoNCiFbXShodHRwczovL2NpdHJpcy11Yy5vcmcvd3AtY29udGVudC91cGxvYWRzLzIwMTkvMTAvVGVjLWRlLU1vbnRlcnJleS1sb2dvLWhvcml6b250YWwtYmx1ZS5wbmcpDQoNCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlciI+DQogIDxwPjxzdHJvbmc+VGVjbm9sw7NnaWNvIGRlIE1vbnRlcnJleTwvc3Ryb25nPjwvcD4NCiAgPHA+PHN0cm9uZz5Eb2N0b3IgVGXDs2ZpbG8gT3p1bmE8L3N0cm9uZz48L3A+DQo8L2Rpdj4NCg0KPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyIj4NCiAgPHA+PHN0cm9uZz5BbHVtbmE6PC9zdHJvbmc+PC9wPg0KDQogIEF2cmlsIExvYmF0byBEZWxnYWRvIEEwMDgzMzExMw0KIA0KPC9kaXY+DQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQppZiAocGFja2FnZVZlcnNpb24oInhmdW4iKSA8ICIwLjQ0Iikgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJ4ZnVuIikNCn0NCg0KIyBDYXJnYSBlbCBwYXF1ZXRlIGFjdHVhbGl6YWRvDQpsaWJyYXJ5KHhmdW4pDQoNCiMgQ29uZmlndXJhY2nDs24gZGUgbG9zIGNodW5rcyBkZSBrbml0cg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KCWVjaG8gPSBUUlVFLA0KCW1lc3NhZ2UgPSBUUlVFLA0KCXdhcm5pbmcgPSBUUlVFDQopDQpgYGANCg0KTGlicmVyaWFzDQpgYGB7ciBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHRpZHlyKQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KHB1cnJyKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KERhdGFFeHBsb3JlcikNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHRtKQ0KbGlicmFyeSh3b3JkY2xvdWQpDQpsaWJyYXJ5KGNsdXN0ZXIpDQpsaWJyYXJ5KGZhY3RvZXh0cmEpIA0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KHB1cnJyKQ0KbGlicmFyeShwUk9DKQ0KbGlicmFyeShycGFydCkNCmxpYnJhcnkocnBhcnQucGxvdCkNCmxpYnJhcnkoZTEwNzEpDQpsaWJyYXJ5KGdncHVicikNCmxpYnJhcnkoZGxvb2tyKQ0KbGlicmFyeSh6b28pDQpsaWJyYXJ5KGNhcmV0KQ0KbGlicmFyeShzdGF0cykNCmxpYnJhcnkodHNlcmllcykNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KHZhcnMpDQpsaWJyYXJ5KHN5dXpoZXQpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShyZWFkeGwpDQpgYGANCg0KIyAqKkNoYXR6aWFudG9uaW91LCBHYWJhdWVyICYgR3VwdGEgKDIwMjEpOioqIEludGVncmF0aW9uIGFuZCByaXNrIHRyYW5zbWlzc2lvbiBpbiB0aGUgbWFya2V0IGZvciBjcnVkZSBvaWw6IEEgdGltZS12YXJ5aW5nIHBhcmFtZXRlciBmcmVxdWVuY3kgY29ubmVjdGVkbmVzcyBhcHByb2FjaA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShyZWFkcikNCg0KIyBFc3BlY2lmaWNhIGVsIGRlbGltaXRhZG9yIGFkZWN1YWRvIChzaSBlcyBuZWNlc2FyaW8pDQppbmRleF9hbHQgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL0FWUklML0Rlc2t0b3AvU3BpbGxvdmVycy9hbGxfZGFpbHlfaW5kZXguY3N2IikNCg0KIyBDb252ZXJ0aXIgbGEgY29sdW1uYSBgRGF0ZWAgYSB0aXBvIERhdGUgc2kgZXN0w6EgZW4gZm9ybWF0byAiZGQvbW0veXl5eSINCmluZGV4X2FsdCREYXRlIDwtIGFzLkRhdGUoaW5kZXhfYWx0JERhdGUsIGZvcm1hdCA9ICIlZC8lbS8lWSIpDQoNCiMgTW9zdHJhciBlc3RydWN0dXJhIHkgcmVzdW1lbg0Kc3RyKGluZGV4X2FsdCkNCnN1bW1hcnkoaW5kZXhfYWx0KQ0KYGBgDQoNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgU2VsZWN0IG9ubHkgdGhlIHJlbGV2YW50IGNvbHVtbnMgZm9yIHRoZSBtb2RlbA0KZGF0YV9zZWxlY3RlZCA8LSBpbmRleF9hbHRbLCBjKCJEYXRlIiwiQUlfSU5ERVgiLCAiRmludGVjaF9JbmRleCIsICJCbG9ja2NoYWluX0luZGV4IildDQojIENvbnZlcnQgdG8gbWF0cml4IGZvcm1hdCBmb3IgdGhlIENvbm5lY3RlZG5lc3NBcHByb2FjaCBwYWNrYWdlDQpkYXRhX21hdHJpeCA8LSBhcy5tYXRyaXgoZGF0YV9zZWxlY3RlZCkNCmBgYA0KDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIENvbnZlcnRpciBhIG9iamV0byB6b28NCmRhdGFfem9vIDwtIHpvbyhkYXRhX3NlbGVjdGVkWywgLTFdLCBvcmRlci5ieSA9IGRhdGFfc2VsZWN0ZWQkRGF0ZSkNCg0KIyBJbnN0YWxhciB5IGNhcmdhciBlbCBwYXF1ZXRlIENvbm5lY3RlZG5lc3NBcHByb2FjaCwgc2kgbm8gZXN0w6EgeWEgaW5zdGFsYWRvDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkNvbm5lY3RlZG5lc3NBcHByb2FjaCIsIHF1aWV0bHkgPSBUUlVFKSkgew0KICBpZiAoIXJlcXVpcmVOYW1lc3BhY2UoImRldnRvb2xzIiwgcXVpZXRseSA9IFRSVUUpKSB7DQogICAgaW5zdGFsbC5wYWNrYWdlcygiZGV2dG9vbHMiKQ0KICB9DQogIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiR2FiYXVlckRhdmlkL0Nvbm5lY3RlZG5lc3NBcHByb2FjaCIpDQp9DQpsaWJyYXJ5KENvbm5lY3RlZG5lc3NBcHByb2FjaCkNCg0KIyBDb25maWd1cmFjacOzbiBkZSBwYXLDoW1ldHJvcyBwYXJhIFRWUFZBUg0KbmxhZyA8LSAyICAgICAgICMgT3JkZW4gZGVsIHJlemFnbw0KbGFtYmRhIDwtIGMoMC45OSwgMC45OSkgICMgVmFsb3JlcyBkZSBkZWNhaW1pZW50byBwYXJhIGVsIGZpbHRybw0KDQojIENyZWFyIGxhIGxpc3RhIGRlIGNvbmZpZ3VyYWNpw7NuIG5lY2VzYXJpYQ0KY29uZmlnIDwtIGxpc3QobCA9IGxhbWJkYSwgbmxhZyA9IG5sYWcpDQoNCiMgRXN0aW1hciBlbCBtb2RlbG8gVFZQLVZBUiBjb24gbG9zIHBhcsOhbWV0cm9zIGVzcGVjaWZpY2Fkb3MNCnR2cHZhcl9tb2RlbCA8LSBUVlBWQVIoZGF0YV96b28sIGNvbmZpZ3VyYXRpb24gPSBjb25maWcpDQpgYGANCg0KIyMgVGFibGUgMjogQXZlcmFnZWQgQ29ubmVjdGVkbmVzcyBUYWJsZQ0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnBhcnRpdGlvbiA9IGMocGkrMC4wMDAwMSwgcGkvNSwgMCkNCmRjYSA9IENvbm5lY3RlZG5lc3NBcHByb2FjaChkYXRhX3pvbywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWw9IlRWUC1WQVIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3RlZG5lc3M9IkZyZXF1ZW5jeSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmxhZz0xLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5mb3JlPTEwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cuc2l6ZT0yMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgVkFSX2NvbmZpZz1saXN0KFRWUFZBUj1saXN0KGthcHBhMT0wLjk5LCBrYXBwYTI9MC45OSwgcHJpb3I9IkJheWVzUHJpb3IiKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgQ29ubmVjdGVkbmVzc19jb25maWcgPSBsaXN0KA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRnJlcXVlbmN5Q29ubmVjdGVkbmVzcz1saXN0KHBhcnRpdGlvbj1wYXJ0aXRpb24sIGdlbmVyYWxpemVkPVRSVUUsIHNjZW5hcmlvPSJBQlMiKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICkpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmthYmxlKGRjYSRUQUJMRSkNCmBgYA0KDQojIyBGaWd1cmUgNDogTmV0IFRvdGFsIERpcmVjdGlvbmFsIENvbm5lY3RlZG5lc3MNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpQbG90TkVUKGRjYSwgeWxpbT1jKC02MCw2MCkpDQpgYGANCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fDQojIyAqKlRyYW5zZm9ybWFjacOzbiBkZSBiYXNlIGRlIGRhdG9zKioNCg0KIyMgTGlicmVyaWFzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShrbml0cikNCmxpYnJhcnkocm1nYXJjaCkNCmxpYnJhcnkoZGV2dG9vbHMpDQpsaWJyYXJ5KG9wZW54bHN4KQ0KbGlicmFyeShyZWxhaW1wbykNCmxpYnJhcnkoc3RhcmdhemVyKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpsaWJyYXJ5KFBlcmZvcm1hbmNlQW5hbHl0aWNzKQ0KbGlicmFyeShDb25uZWN0ZWRuZXNzQXBwcm9hY2gpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHRzZXJpZXMpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KbGlicmFyeSh1cmNhKQ0KbGlicmFyeShmR2FyY2gpDQpsaWJyYXJ5KE1UUykNCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkobm9ydGVzdCkNCmxpYnJhcnkob3V0bGllcnMpDQpsaWJyYXJ5KG1vbWVudHMpDQpsaWJyYXJ5KEZpblRTKQ0KbGlicmFyeShXZWlnaHRlZFBvcnRUZXN0KQ0KDQpgYGANCg0KIyMgQ2FyZ2EgZGUgYmFzZSBkZSBkYXRvcw0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgTGVlIGVsIGFyY2hpdm8gQ1NWIHkgc2VsZWNjaW9uYSBsYXMgY29sdW1uYXMgcmVsZXZhbnRlcw0KaW5kZXhfYWx0IDwtIHJlYWRfY3N2KCJDOi9Vc2Vycy9BVlJJTC9EZXNrdG9wL1NwaWxsb3ZlcnMvYWxsX2RhaWx5X2luZGV4LmNzdiIpDQpkYXRhX3NlbGVjdGVkIDwtIGluZGV4X2FsdFssIGMoIkRhdGUiLCAiQUlfSU5ERVgiLCAiRmludGVjaF9JbmRleCIsICJCbG9ja2NoYWluX0luZGV4IildDQpgYGANCg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBGdW5jdGlvbiBmb3Igc3VtbWFyeSBzdGF0aXN0aWNzDQpzdW1tYXJ5X3N0YXRzIDwtIGZ1bmN0aW9uKGRhdGEpIHsNCiAgcmV0dXJuKGRhdGEuZnJhbWUoDQogICAgTWVhbiA9IG1lYW4oZGF0YSwgbmEucm0gPSBUUlVFKSwNCiAgICBTdGREZXYgPSBzZChkYXRhLCBuYS5ybSA9IFRSVUUpLA0KICAgIE1pbiA9IG1pbihkYXRhLCBuYS5ybSA9IFRSVUUpLA0KICAgIFAyNSA9IHF1YW50aWxlKGRhdGEsIDAuMjUsIG5hLnJtID0gVFJVRSksDQogICAgUDUwID0gbWVkaWFuKGRhdGEsIG5hLnJtID0gVFJVRSksDQogICAgUDc1ID0gcXVhbnRpbGUoZGF0YSwgMC43NSwgbmEucm0gPSBUUlVFKSwNCiAgICBNYXggPSBtYXgoZGF0YSwgbmEucm0gPSBUUlVFKSwNCiAgICBTa2V3bmVzcyA9IHNrZXduZXNzKGRhdGEsIG5hLnJtID0gVFJVRSksDQogICAgS3VydG9zaXMgPSBrdXJ0b3NpcyhkYXRhLCBuYS5ybSA9IFRSVUUpDQogICkpDQp9DQoNCiMgQ2FsY3VsYXRlIHN0YXRpc3RpY3MgYW5kIHRlc3RzIGZvciBlYWNoIGluZGV4DQpyZXN1bHRzIDwtIGRhdGEuZnJhbWUoDQogIFRlc3QgPSBjKA0KICAgICJNZWFuIiwgIlN0YW5kYXJkIERldmlhdGlvbiIsICJNaW5pbXVtIiwgIjI1dGggUGVyY2VudGlsZSIsICJNZWRpYW4iLA0KICAgICI3NXRoIFBlcmNlbnRpbGUiLCAiTWF4aW11bSIsICJTa2V3bmVzcyIsICJLdXJ0b3NpcyIsICJKYXJxdWUtQmVyYSAocC12YWx1ZSkiLA0KICAgICJBREYgVGVzdCAocC12YWx1ZSkiLCAiS1BTUyBUZXN0IChwLXZhbHVlKSIsICJQUCBUZXN0IChwLXZhbHVlKSIsICJFUlMgVGVzdCIsDQogICAgIkFSQ0ggVGVzdCAocC12YWx1ZSkiLCAiV2VpZ2h0ZWQgUG9ydG1hbnRlYXUgVGVzdCAocC12YWx1ZSkiLCAiUTIoMjApIFRlc3QgKHAtdmFsdWUpIiwNCiAgICAiT3V0bGllciBkZXRlY3Rpb24gKENoZW4gYW5kIExpdSkiLCJDb3JyZWxhdGlvbiBNYXRyaXggYW5kIFItc3F1YXJlZCINCiAgKSwNCiAgQUlfSU5ERVggPSBOQSwgRmludGVjaF9JbmRleCA9IE5BLCBCbG9ja2NoYWluX0luZGV4ID0gTkENCikNCg0KIyBQb3B1bGF0ZSB0aGUgdGFibGUgd2l0aCBzdW1tYXJ5IHN0YXRzDQpzdGF0c19haSA8LSBzdW1tYXJ5X3N0YXRzKGRhdGFfc2VsZWN0ZWQkQUlfSU5ERVgpDQpzdGF0c19maW50ZWNoIDwtIHN1bW1hcnlfc3RhdHMoZGF0YV9zZWxlY3RlZCRGaW50ZWNoX0luZGV4KQ0Kc3RhdHNfYmxvY2tjaGFpbiA8LSBzdW1tYXJ5X3N0YXRzKGRhdGFfc2VsZWN0ZWQkQmxvY2tjaGFpbl9JbmRleCkNCnJlc3VsdHMkQUlfSU5ERVhbMTo5XSA8LSBhcy5udW1lcmljKHN0YXRzX2FpKQ0KcmVzdWx0cyRGaW50ZWNoX0luZGV4WzE6OV0gPC0gYXMubnVtZXJpYyhzdGF0c19maW50ZWNoKQ0KcmVzdWx0cyRCbG9ja2NoYWluX0luZGV4WzE6OV0gPC0gYXMubnVtZXJpYyhzdGF0c19ibG9ja2NoYWluKQ0KDQojIE5vcm1hbGl0eSBhbmQgc3RhdGlvbmFyaXR5IHRlc3RzDQpyZXN1bHRzJEFJX0lOREVYWzEwXSA8LSBqYXJxdWUuYmVyYS50ZXN0KGRhdGFfc2VsZWN0ZWQkQUlfSU5ERVgpJHAudmFsdWUNCnJlc3VsdHMkRmludGVjaF9JbmRleFsxMF0gPC0gamFycXVlLmJlcmEudGVzdChkYXRhX3NlbGVjdGVkJEZpbnRlY2hfSW5kZXgpJHAudmFsdWUNCnJlc3VsdHMkQmxvY2tjaGFpbl9JbmRleFsxMF0gPC0gamFycXVlLmJlcmEudGVzdChkYXRhX3NlbGVjdGVkJEJsb2NrY2hhaW5fSW5kZXgpJHAudmFsdWUNCg0KcmVzdWx0cyRBSV9JTkRFWFsxMV0gPC0gYWRmLnRlc3QoZGF0YV9zZWxlY3RlZCRBSV9JTkRFWCkkcC52YWx1ZQ0KcmVzdWx0cyRGaW50ZWNoX0luZGV4WzExXSA8LSBhZGYudGVzdChkYXRhX3NlbGVjdGVkJEZpbnRlY2hfSW5kZXgpJHAudmFsdWUNCnJlc3VsdHMkQmxvY2tjaGFpbl9JbmRleFsxMV0gPC0gYWRmLnRlc3QoZGF0YV9zZWxlY3RlZCRCbG9ja2NoYWluX0luZGV4KSRwLnZhbHVlDQoNCnJlc3VsdHMkQUlfSU5ERVhbMTJdIDwtIGtwc3MudGVzdChkYXRhX3NlbGVjdGVkJEFJX0lOREVYKSRwLnZhbHVlDQpyZXN1bHRzJEZpbnRlY2hfSW5kZXhbMTJdIDwtIGtwc3MudGVzdChkYXRhX3NlbGVjdGVkJEZpbnRlY2hfSW5kZXgpJHAudmFsdWUNCnJlc3VsdHMkQmxvY2tjaGFpbl9JbmRleFsxMl0gPC0ga3Bzcy50ZXN0KGRhdGFfc2VsZWN0ZWQkQmxvY2tjaGFpbl9JbmRleCkkcC52YWx1ZQ0KDQpyZXN1bHRzJEFJX0lOREVYWzEzXSA8LSBwcC50ZXN0KGRhdGFfc2VsZWN0ZWQkQUlfSU5ERVgpJHAudmFsdWUNCnJlc3VsdHMkRmludGVjaF9JbmRleFsxM10gPC0gcHAudGVzdChkYXRhX3NlbGVjdGVkJEZpbnRlY2hfSW5kZXgpJHAudmFsdWUNCnJlc3VsdHMkQmxvY2tjaGFpbl9JbmRleFsxM10gPC0gcHAudGVzdChkYXRhX3NlbGVjdGVkJEJsb2NrY2hhaW5fSW5kZXgpJHAudmFsdWUNCg0KcmVzdWx0cyRBSV9JTkRFWFsxNF0gPC0gdXIuZXJzKGRhdGFfc2VsZWN0ZWQkQUlfSU5ERVgsIHR5cGUgPSAiREYtR0xTIilAdGVzdHN0YXQNCnJlc3VsdHMkRmludGVjaF9JbmRleFsxNF0gPC0gdXIuZXJzKGRhdGFfc2VsZWN0ZWQkRmludGVjaF9JbmRleCwgdHlwZSA9ICJERi1HTFMiKUB0ZXN0c3RhdA0KcmVzdWx0cyRCbG9ja2NoYWluX0luZGV4WzE0XSA8LSB1ci5lcnMoZGF0YV9zZWxlY3RlZCRCbG9ja2NoYWluX0luZGV4LCB0eXBlID0gIkRGLUdMUyIpQHRlc3RzdGF0DQoNCiMgQVJDSCB0ZXN0DQpyZXN1bHRzJEFJX0lOREVYWzE1XSA8LSBBcmNoVGVzdChkYXRhX3NlbGVjdGVkJEFJX0lOREVYKSRwLnZhbHVlDQpyZXN1bHRzJEZpbnRlY2hfSW5kZXhbMTVdIDwtIEFyY2hUZXN0KGRhdGFfc2VsZWN0ZWQkRmludGVjaF9JbmRleCkkcC52YWx1ZQ0KcmVzdWx0cyRCbG9ja2NoYWluX0luZGV4WzE1XSA8LSBBcmNoVGVzdChkYXRhX3NlbGVjdGVkJEJsb2NrY2hhaW5fSW5kZXgpJHAudmFsdWUNCg0KIyBQb3J0bWFudGVhdSB0ZXN0DQpyZXN1bHRzJHBvcnRtYW50ZWF1X2FpIDwtIFdlaWdodGVkLkJveC50ZXN0KGRhdGFfc2VsZWN0ZWQkQUlfSU5ERVgpJHAudmFsdWUNCnJlc3VsdHMkcG9ydG1hbnRlYXVfZmludGVjaCA8LSBXZWlnaHRlZC5Cb3gudGVzdChkYXRhX3NlbGVjdGVkJEZpbnRlY2hfSW5kZXgpJHAudmFsdWUNCnJlc3VsdHMkcG9ydG1hbnRlYXVfYmxvY2tjaGFpbiA8LSBXZWlnaHRlZC5Cb3gudGVzdChkYXRhX3NlbGVjdGVkJEJsb2NrY2hhaW5fSW5kZXgpJHAudmFsdWUNCg0KIyBRMigyMCkgdGVzdA0KcmVzdWx0cyRBSV9JTkRFWFsxN10gPC0gQm94LnRlc3QoZGF0YV9zZWxlY3RlZCRBSV9JTkRFWF4yLCBsYWcgPSAyMCwgdHlwZSA9ICJManVuZy1Cb3giKSRwLnZhbHVlDQpyZXN1bHRzJEZpbnRlY2hfSW5kZXhbMTddIDwtIEJveC50ZXN0KGRhdGFfc2VsZWN0ZWQkRmludGVjaF9JbmRleF4yLCBsYWcgPSAyMCwgdHlwZSA9ICJManVuZy1Cb3giKSRwLnZhbHVlDQpyZXN1bHRzJEJsb2NrY2hhaW5fSW5kZXhbMTddIDwtIEJveC50ZXN0KGRhdGFfc2VsZWN0ZWQkQmxvY2tjaGFpbl9JbmRleF4yLCBsYWcgPSAyMCwgdHlwZSA9ICJManVuZy1Cb3giKSRwLnZhbHVlDQoNCiMgT3V0bGllciBkZXRlY3Rpb24gKENoZW4gYW5kIExpdSkNCnJlc3VsdHMkb3V0bGllcnNfYWkgPC0gc3VtKHNjb3JlcyhkYXRhX3NlbGVjdGVkJEFJX0lOREVYLCB0eXBlID0gImNoaXNxIiwgcHJvYiA9IDAuMDUpICE9IDApDQpyZXN1bHRzJG91dGxpZXJzX2ZpbnRlY2ggPC0gc3VtKHNjb3JlcyhkYXRhX3NlbGVjdGVkJEZpbnRlY2hfSW5kZXgsIHR5cGUgPSAiY2hpc3EiLCBwcm9iID0gMC4wNSkgIT0gMCkNCnJlc3VsdHMkb3V0bGllcnNfYmxvY2tjaGFpbiA8LSBzdW0oc2NvcmVzKGRhdGFfc2VsZWN0ZWQkQmxvY2tjaGFpbl9JbmRleCwgdHlwZSA9ICJjaGlzcSIsIHByb2IgPSAwLjA1KSAhPSAwKQ0KDQojIENvcnJlbGF0aW9uIE1hdHJpeCBhbmQgUi1zcXVhcmVkDQpjb3JfbWF0cml4IDwtIGNvcihkYXRhX3NlbGVjdGVkWywgLTFdLCB1c2UgPSAiY29tcGxldGUub2JzIikNCnJfc3F1YXJlZCA8LSBjb3JfbWF0cml4XjINCg0KcHJpbnQocmVzdWx0cykNCmBgYA0KDQojIyBDb252ZXJzaW9uIGEgZXN0YWNpb25hcmlhDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodHNlcmllcykNCmxpYnJhcnkoZm9yZWNhc3QpDQpsaWJyYXJ5KHJ1Z2FyY2gpDQoNCiMgQ3JlYXIgY29sdW1uYXMgZGUgZGlmZXJlbmNpYXMgcGFyYSBoYWNlciBlc3RhY2lvbmFyaW9zIGxvcyBkYXRvcw0KZGF0YV9zZWxlY3RlZDIgPC0gZGF0YV9zZWxlY3RlZCAlPiUNCiAgbXV0YXRlKA0KICAgIEFJX0lOREVYX2RpZmYgPSBjKE5BLCBkaWZmKEFJX0lOREVYLCBkaWZmZXJlbmNlcyA9IDEpKSwNCiAgICBGaW50ZWNoX0luZGV4X2RpZmYgPSBjKE5BLCBkaWZmKEZpbnRlY2hfSW5kZXgsIGRpZmZlcmVuY2VzID0gMSkpLA0KICAgIEJsb2NrY2hhaW5fSW5kZXhfZGlmZiA9IGMoTkEsIGRpZmYoQmxvY2tjaGFpbl9JbmRleCwgZGlmZmVyZW5jZXMgPSAxKSkNCiAgKQ0KDQojIFJlbW92ZXIgbGFzIGZpbGFzIGNvbiBOQSBkZXNwdcOpcyBkZSBsYSBkaWZlcmVuY2lhY2nDs24NCmRhdGFfc2VsZWN0ZWQyIDwtIG5hLm9taXQoZGF0YV9zZWxlY3RlZDIpDQpgYGANCg0KIyMgVGVzdHMgeSBFc3RhZMOtc3RpY29zDQpTZSByZWFsaXphIGFuw6FsaXNpcyBkZToNCg0KKiBBREYgVGVzdCAoUHJ1ZWJhIGRlIERpY2tleS1GdWxsZXIgQXVtZW50YWRhKTogRXN0ZSB0ZXN0IGF5dWRhIGEgZGV0ZXJtaW5hciBzaSB1bmEgc2VyaWUgZXMgZXN0YWNpb25hcmlhLiBVbiB2YWxvciBwLXZhbHVlIGJham8gKHTDrXBpY2FtZW50ZSA8IDAuMDUpIHN1Z2llcmUgcXVlIGxhIHNlcmllIGVzIGVzdGFjaW9uYXJpYS4gRW4gdHUgY2FzbywgYW1ib3Mgw61uZGljZXMgKEFJX0lOREVYX2RpZmYgeSBGaW50ZWNoX0luZGV4X2RpZmYpIHRpZW5lbiBwLXZhbHVlcyBiYWpvcyBlbiBlbCBBREYsIGluZGljYW5kbyBxdWUgcHJvYmFibGVtZW50ZSBzZWFuIGVzdGFjaW9uYXJpb3MgZW4gc3VzIGRpZmVyZW5jaWFzLg0KDQoqIEtQU1MgVGVzdDogQ29udHJhcmlvIGFsIEFERiwgZWwgS1BTUyBwcnVlYmEgc2kgdW5hIHNlcmllIGVzIG5vIGVzdGFjaW9uYXJpYS4gVW4gcC12YWx1ZSBiYWpvIGluZGljYSBubyBlc3RhY2lvbmFyaWVkYWQuIEVuIGVzdGUgY2FzbywgbG9zIHAtdmFsdWVzIHNvbiByZWxhdGl2YW1lbnRlIGFsdG9zICg+IDAuMDUpLCBsbyBjdWFsIGVzIGNvbnNpc3RlbnRlIGNvbiBsYSBpZGVhIGRlIHF1ZSBsYXMgc2VyaWVzIGRpZmVyZW5jaWFsZXMgc29uIGVzdGFjaW9uYXJpYXMuDQoNCiogUFAgVGVzdCAoUHJ1ZWJhIGRlIFBoaWxsaXBzLVBlcnJvbik6IE5vIGhheSBkYXRvcyBlbiBsYSB0YWJsYSBwYXJhIGVsIFBQIHRlc3QsIHBlcm8gZXN0ZSB0YW1iacOpbiBzZSB1c2EgcGFyYSBjb25maXJtYXIgbGEgZXN0YWNpb25hcmllZGFkLiBTaSB0aWVuZXMgb3Ryb3MgcmVzdWx0YWRvcyBkZSBQUCwgcG9kcsOtYW4gY29tcGxlbWVudGFyIGVsIGFuw6FsaXNpcy4NCg0KKiBFUlMgVGVzdCAoRWxsaW90LVJvdGhlbmJlcmctU3RvY2spOiBFc3RlIGVzIG90cm8gdGVzdCBwYXJhIGVzdGFjaW9uYXJpZWRhZCwgZG9uZGUgZWwgdmFsb3IgZGViZSBzZXIgY2VyY2FubyBhIGNlcm8gcGFyYSBpbmRpY2FyIGVzdGFjaW9uYXJpZWRhZC4gRGFkbyBxdWUgdGllbmVzIHZhbG9yZXMgbmVnYXRpdm9zIGFsdG9zLCBlc3RvIHRhbWJpw6luIHN1Z2llcmUgcXVlIGxhcyBzZXJpZXMgcHVlZGVuIHNlciBlc3RhY2lvbmFyaWFzLg0KDQoqIEFSQ0ggVGVzdDogRXN0YSBwcnVlYmEgZXZhbMO6YSBsYSBoZXRlcm9jZWRhc3RpY2lkYWQgY29uZGljaW9uYWwgZW4gbGEgc2VyaWUgKGVzIGRlY2lyLCBzaSBsYSB2YXJpYW56YSBjYW1iaWEgY29uIGVsIHRpZW1wbykuIFVuIHAtdmFsdWUgYmFqbyAoY29tbyBlbiBlc3RlIGNhc28sIDAuMDAwMDAwIHBhcmEgYW1ib3Mgw61uZGljZXMpIGluZGljYSBxdWUgZXhpc3RlIGhldGVyb2NlZGFzdGljaWRhZCwgbG8gY3VhbCBlcyBjb23Dum4gZW4gZGF0b3MgZmluYW5jaWVyb3MgeSBzdWdpZXJlIGxhIHByZXNlbmNpYSBkZSB2b2xhdGlsaWRhZCBjYW1iaWFudGUuDQoNCiogV2VpZ2h0ZWQgUG9ydG1hbnRlYXUgVGVzdCB5IFEyKDIwKSBUZXN0OiBBbWJvcyBzaXJ2ZW4gcGFyYSBldmFsdWFyIGxhIGF1dG9jb3JyZWxhY2nDs24gZW4gbGFzIHNlcmllcyBkZSB0aWVtcG8uIFZhbG9yZXMgcC12YWx1ZSBleHRyZW1hZGFtZW50ZSBiYWpvcyBpbmRpY2FuIHF1ZSBleGlzdGUgYXV0b2NvcnJlbGFjacOzbiBzaWduaWZpY2F0aXZhLiBFc3RvIHN1Z2llcmUgcXVlIGxhcyBzZXJpZXMgdGllbmVuIGRlcGVuZGVuY2lhIHRlbXBvcmFsLCBsbyBjdWFsIGVzIGltcG9ydGFudGUgcGFyYSB1biBtb2RlbG8gZGUgc2VyaWVzIGRlIHRpZW1wbyBjb21vIGVsIFRWUC1WQVIuDQoNCiogT3V0bGllciBEZXRlY3Rpb246IExvcyB2YWxvcmVzIGFsdG9zIGVuIGRldGVjY2nDs24gZGUgb3V0bGllcnMgcHVlZGVuIGluZGljYXIgcHVudG9zIGF0w61waWNvcyBxdWUgcG9kcsOtYW4gYWZlY3RhciBsYSBlc3RhYmlsaWRhZCBkZWwgbW9kZWxvLiBFbiBlc3RlIGNhc28sIGFtYm9zIMOtbmRpY2VzIHRpZW5lbiB2YWxvcmVzIGFsdG9zLCBsbyBxdWUgc3VnaWVyZSBwcmVzZW5jaWEgZGUgb3V0bGllcnMuIFBhcmEgdW4gVFZQLVZBUiwgZXMgaW1wb3J0YW50ZSBjb25zaWRlcmFyIGPDs21vIGxvcyBvdXRsaWVycyBwb2Ryw61hbiBpbmZsdWlyIGVuIGxvcyBwYXLDoW1ldHJvcyBjYW1iaWFudGVzIGEgbG8gbGFyZ28gZGVsIHRpZW1wby4NCg0KRW4gY29uY2x1c2nDs24sIGxhcyBzZXJpZXMgc29uIGVzdGFjaW9uYXJpYXMsIGxvIGN1YWwgZXMgdW4gcGVybWl0ZSBnZW5lcmFyIG1vZGVsb3MgZGUgc2VyaWVzIHRlbXBvcmFsZXMgY29tbyBUVlAtVkFSLiBMYSBwcmVzZW5jaWEgZGUgYXV0b2NvcnJlbGFjacOzbiB5IGhldGVyb2NlZGFzdGljaWRhZCBlcyBjb25zaXN0ZW50ZSBjb24gZGF0b3MgZmluYW5jaWVyb3MsIGxvIHF1ZSBqdXN0aWZpY2EgZWwgdXNvIGRlIHVuIG1vZGVsbyBxdWUgY2FwdHVyZSBkaW7DoW1pY2FzIHRlbXBvcmFsZXMgY2FtYmlhbnRlcywgY29tbyBlbCBUVlAtVkFSLiBTaW4gZW1iYXJnbywgbGEgZGV0ZWNjacOzbiBkZSBvdXRsaWVycyBzdWdpZXJlIHF1ZSBzZSBuZWNlc2l0YSB1biBwcmVwcm9jZXNhbWllbnRvIHBhcmEgbm8gYWZlY3RhciBsYSBlc3RhYmlsaWRhZCBkeS9vIGVzdGltYWNpw7NuIGRlIGxvcyBwYXLDoW1ldHJvcyBlbiBlbCBtb2RlbG8uDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KIyBGdW5jdGlvbiBmb3Igc3VtbWFyeSBzdGF0aXN0aWNzDQpBSV9JTkRFWF9kaWZmIDwtIG5hLm9taXQoZGF0YV9zZWxlY3RlZDIkQUlfSU5ERVhfZGlmZikNCkZpbnRlY2hfSW5kZXhfZGlmZiA8LSBuYS5vbWl0KGRhdGFfc2VsZWN0ZWQyJEZpbnRlY2hfSW5kZXhfZGlmZikNCkJsb2NrY2hhaW5fSW5kZXhfZGlmZiA8LSBuYS5vbWl0KGRhdGFfc2VsZWN0ZWQyJEJsb2NrY2hhaW5fSW5kZXhfZGlmZikNCg0Kc3VtbWFyeV9zdGF0cyA8LSBmdW5jdGlvbihkYXRhKSB7DQogIHJldHVybihkYXRhLmZyYW1lKA0KICAgIE1lYW4gPSBtZWFuKGRhdGEsIG5hLnJtID0gVFJVRSksDQogICAgU3RkRGV2ID0gc2QoZGF0YSwgbmEucm0gPSBUUlVFKSwNCiAgICBNaW4gPSBtaW4oZGF0YSwgbmEucm0gPSBUUlVFKSwNCiAgICBQMjUgPSBxdWFudGlsZShkYXRhLCAwLjI1LCBuYS5ybSA9IFRSVUUpLA0KICAgIFA1MCA9IG1lZGlhbihkYXRhLCBuYS5ybSA9IFRSVUUpLA0KICAgIFA3NSA9IHF1YW50aWxlKGRhdGEsIDAuNzUsIG5hLnJtID0gVFJVRSksDQogICAgTWF4ID0gbWF4KGRhdGEsIG5hLnJtID0gVFJVRSksDQogICAgU2tld25lc3MgPSBza2V3bmVzcyhkYXRhLCBuYS5ybSA9IFRSVUUpLA0KICAgIEt1cnRvc2lzID0ga3VydG9zaXMoZGF0YSwgbmEucm0gPSBUUlVFKQ0KICApKQ0KfQ0KDQojIENhbGN1bGF0ZSBzdGF0aXN0aWNzIGFuZCB0ZXN0cyBmb3IgZWFjaCBkaWZmZXJlbmNlZCBpbmRleA0KcmVzdWx0cyA8LSBkYXRhLmZyYW1lKA0KICBUZXN0ID0gYygNCiAgICAiTWVhbiIsICJTdGFuZGFyZCBEZXZpYXRpb24iLCAiTWluaW11bSIsICIyNXRoIFBlcmNlbnRpbGUiLCAiTWVkaWFuIiwNCiAgICAiNzV0aCBQZXJjZW50aWxlIiwgIk1heGltdW0iLCAiU2tld25lc3MiLCAiS3VydG9zaXMiLCAiSmFycXVlLUJlcmEgKHAtdmFsdWUpIiwNCiAgICAiQURGIFRlc3QgKHAtdmFsdWUpIiwgIktQU1MgVGVzdCAocC12YWx1ZSkiLCAiUFAgVGVzdCAocC12YWx1ZSkiLCAiRVJTIFRlc3QiLA0KICAgICJBUkNIIFRlc3QgKHAtdmFsdWUpIiwgIldlaWdodGVkIFBvcnRtYW50ZWF1IFRlc3QgKHAtdmFsdWUpIiwgIlEyKDIwKSBUZXN0IChwLXZhbHVlKSIsDQogICAgIk91dGxpZXIgZGV0ZWN0aW9uIChDaGVuIGFuZCBMaXUpIiwgIkNvcnJlbGF0aW9uIE1hdHJpeCBhbmQgUi1zcXVhcmVkIg0KICApLA0KICBBSV9JTkRFWF9kaWZmID0gTkEsIEZpbnRlY2hfSW5kZXhfZGlmZiA9IE5BLCBCbG9ja2NoYWluX0luZGV4X2RpZmYgPSBOQQ0KKQ0KDQojIFBvcHVsYXRlIHRoZSB0YWJsZSB3aXRoIHN1bW1hcnkgc3RhdHMNCnN0YXRzX2FpIDwtIHN1bW1hcnlfc3RhdHMoZGF0YV9zZWxlY3RlZDIkQUlfSU5ERVhfZGlmZikNCnN0YXRzX2ZpbnRlY2ggPC0gc3VtbWFyeV9zdGF0cyhkYXRhX3NlbGVjdGVkMiRGaW50ZWNoX0luZGV4X2RpZmYpDQpzdGF0c19ibG9ja2NoYWluIDwtIHN1bW1hcnlfc3RhdHMoZGF0YV9zZWxlY3RlZDIkQmxvY2tjaGFpbl9JbmRleF9kaWZmKQ0KcmVzdWx0cyRBSV9JTkRFWF9kaWZmWzE6OV0gPC0gYXMubnVtZXJpYyhzdGF0c19haSkNCnJlc3VsdHMkRmludGVjaF9JbmRleF9kaWZmWzE6OV0gPC0gYXMubnVtZXJpYyhzdGF0c19maW50ZWNoKQ0KcmVzdWx0cyRCbG9ja2NoYWluX0luZGV4X2RpZmZbMTo5XSA8LSBhcy5udW1lcmljKHN0YXRzX2Jsb2NrY2hhaW4pDQoNCiMgTm9ybWFsaXR5IGFuZCBzdGF0aW9uYXJpdHkgdGVzdHMNCnJlc3VsdHMkQUlfSU5ERVhfZGlmZlsxMF0gPC0gamFycXVlLmJlcmEudGVzdChkYXRhX3NlbGVjdGVkMiRBSV9JTkRFWF9kaWZmKSRwLnZhbHVlDQpyZXN1bHRzJEZpbnRlY2hfSW5kZXhfZGlmZlsxMF0gPC0gamFycXVlLmJlcmEudGVzdChkYXRhX3NlbGVjdGVkMiRGaW50ZWNoX0luZGV4X2RpZmYpJHAudmFsdWUNCnJlc3VsdHMkQmxvY2tjaGFpbl9JbmRleF9kaWZmWzEwXSA8LSBqYXJxdWUuYmVyYS50ZXN0KGRhdGFfc2VsZWN0ZWQyJEJsb2NrY2hhaW5fSW5kZXhfZGlmZikkcC52YWx1ZQ0KDQojcmVzdWx0cyRBSV9JTkRFWF9kaWZmWzExXSA8LSBhZGYudGVzdChuYS5vbWl0KGRhdGFfc2VsZWN0ZWQkQUlfSU5ERVhfZGlmZiksIGFsdGVybmF0aXZlID0gInN0YXRpb25hcnkiKSRwLnZhbHVlDQojcmVzdWx0cyRGaW50ZWNoX0luZGV4X2RpZmZbMTFdIDwtIGFkZi50ZXN0KG5hLm9taXQoZGF0YV9zZWxlY3RlZCRGaW50ZWNoX0luZGV4X2RpZmYpLCBhbHRlcm5hdGl2ZSA9ICJzdGF0aW9uYXJ5IikkcC52YWx1ZQ0KI3Jlc3VsdHMkQmxvY2tjaGFpbl9JbmRleF9kaWZmWzExXSA8LSBhZGYudGVzdChuYS5vbWl0KGRhdGFfc2VsZWN0ZWQkQmxvY2tjaGFpbl9JbmRleF9kaWZmKSwgYWx0ZXJuYXRpdmUgPSAic3RhdGlvbmFyeSIpJHAudmFsdWUNCg0KcmVzdWx0cyRBSV9JTkRFWF9kaWZmWzEyXSA8LSBrcHNzLnRlc3QoZGF0YV9zZWxlY3RlZDIkQUlfSU5ERVhfZGlmZikkcC52YWx1ZQ0KcmVzdWx0cyRGaW50ZWNoX0luZGV4X2RpZmZbMTJdIDwtIGtwc3MudGVzdChkYXRhX3NlbGVjdGVkMiRGaW50ZWNoX0luZGV4X2RpZmYpJHAudmFsdWUNCnJlc3VsdHMkQmxvY2tjaGFpbl9JbmRleF9kaWZmWzEyXSA8LSBrcHNzLnRlc3QoZGF0YV9zZWxlY3RlZDIkQmxvY2tjaGFpbl9JbmRleF9kaWZmKSRwLnZhbHVlDQoNCnJlc3VsdHMkQUlfSU5ERVhfZGlmZlsxM10gPC0gcHAudGVzdChkYXRhX3NlbGVjdGVkMiRBSV9JTkRFWF9kaWZmKSRwLnZhbHVlDQpyZXN1bHRzJEZpbnRlY2hfSW5kZXhfZGlmZlsxM10gPC0gcHAudGVzdChkYXRhX3NlbGVjdGVkMiRGaW50ZWNoX0luZGV4X2RpZmYpJHAudmFsdWUNCnJlc3VsdHMkQmxvY2tjaGFpbl9JbmRleF9kaWZmWzEzXSA8LSBwcC50ZXN0KGRhdGFfc2VsZWN0ZWQyJEJsb2NrY2hhaW5fSW5kZXhfZGlmZikkcC52YWx1ZQ0KDQpyZXN1bHRzJEFJX0lOREVYX2RpZmZbMTRdIDwtIHVyLmVycyhkYXRhX3NlbGVjdGVkMiRBSV9JTkRFWF9kaWZmLCB0eXBlID0gIkRGLUdMUyIpQHRlc3RzdGF0DQpyZXN1bHRzJEZpbnRlY2hfSW5kZXhfZGlmZlsxNF0gPC0gdXIuZXJzKGRhdGFfc2VsZWN0ZWQyJEZpbnRlY2hfSW5kZXhfZGlmZiwgdHlwZSA9ICJERi1HTFMiKUB0ZXN0c3RhdA0KcmVzdWx0cyRCbG9ja2NoYWluX0luZGV4X2RpZmZbMTRdIDwtIHVyLmVycyhkYXRhX3NlbGVjdGVkMiRCbG9ja2NoYWluX0luZGV4X2RpZmYsIHR5cGUgPSAiREYtR0xTIilAdGVzdHN0YXQNCg0KIyBBUkNIIHRlc3QNCnJlc3VsdHMkQUlfSU5ERVhfZGlmZlsxNV0gPC0gQXJjaFRlc3QoZGF0YV9zZWxlY3RlZDIkQUlfSU5ERVhfZGlmZikkcC52YWx1ZQ0KcmVzdWx0cyRGaW50ZWNoX0luZGV4X2RpZmZbMTVdIDwtIEFyY2hUZXN0KGRhdGFfc2VsZWN0ZWQyJEZpbnRlY2hfSW5kZXhfZGlmZikkcC52YWx1ZQ0KcmVzdWx0cyRCbG9ja2NoYWluX0luZGV4X2RpZmZbMTVdIDwtIEFyY2hUZXN0KGRhdGFfc2VsZWN0ZWQyJEJsb2NrY2hhaW5fSW5kZXhfZGlmZikkcC52YWx1ZQ0KDQojIFBvcnRtYW50ZWF1IHRlc3QNCnJlc3VsdHMkQUlfSU5ERVhfZGlmZlsxNl0gPC0gV2VpZ2h0ZWQuQm94LnRlc3QoZGF0YV9zZWxlY3RlZDIkQUlfSU5ERVhfZGlmZikkcC52YWx1ZQ0KcmVzdWx0cyRGaW50ZWNoX0luZGV4X2RpZmZbMTZdIDwtIFdlaWdodGVkLkJveC50ZXN0KGRhdGFfc2VsZWN0ZWQyJEZpbnRlY2hfSW5kZXhfZGlmZikkcC52YWx1ZQ0KcmVzdWx0cyRCbG9ja2NoYWluX0luZGV4X2RpZmZbMTZdIDwtIFdlaWdodGVkLkJveC50ZXN0KGRhdGFfc2VsZWN0ZWQyJEJsb2NrY2hhaW5fSW5kZXhfZGlmZikkcC52YWx1ZQ0KDQojIFEyKDIwKSB0ZXN0DQpyZXN1bHRzJEFJX0lOREVYX2RpZmZbMTddIDwtIEJveC50ZXN0KGRhdGFfc2VsZWN0ZWQyJEFJX0lOREVYX2RpZmZeMiwgbGFnID0gMjAsIHR5cGUgPSAiTGp1bmctQm94IikkcC52YWx1ZQ0KcmVzdWx0cyRGaW50ZWNoX0luZGV4X2RpZmZbMTddIDwtIEJveC50ZXN0KGRhdGFfc2VsZWN0ZWQyJEZpbnRlY2hfSW5kZXhfZGlmZl4yLCBsYWcgPSAyMCwgdHlwZSA9ICJManVuZy1Cb3giKSRwLnZhbHVlDQpyZXN1bHRzJEJsb2NrY2hhaW5fSW5kZXhfZGlmZlsxN10gPC0gQm94LnRlc3QoZGF0YV9zZWxlY3RlZDIkQmxvY2tjaGFpbl9JbmRleF9kaWZmXjIsIGxhZyA9IDIwLCB0eXBlID0gIkxqdW5nLUJveCIpJHAudmFsdWUNCg0KIyBPdXRsaWVyIGRldGVjdGlvbiAoQ2hlbiBhbmQgTGl1KQ0KcmVzdWx0cyRBSV9JTkRFWF9kaWZmWzE4XSA8LSBzdW0oc2NvcmVzKGRhdGFfc2VsZWN0ZWQyJEFJX0lOREVYX2RpZmYsIHR5cGUgPSAiY2hpc3EiLCBwcm9iID0gMC4wNSkgIT0gMCkNCnJlc3VsdHMkRmludGVjaF9JbmRleF9kaWZmWzE4XSA8LSBzdW0oc2NvcmVzKGRhdGFfc2VsZWN0ZWQyJEZpbnRlY2hfSW5kZXhfZGlmZiwgdHlwZSA9ICJjaGlzcSIsIHByb2IgPSAwLjA1KSAhPSAwKQ0KcmVzdWx0cyRCbG9ja2NoYWluX0luZGV4X2RpZmZbMThdIDwtIHN1bShzY29yZXMoZGF0YV9zZWxlY3RlZDIkQmxvY2tjaGFpbl9JbmRleF9kaWZmLCB0eXBlID0gImNoaXNxIiwgcHJvYiA9IDAuMDUpICE9IDApDQoNCiMgQ29ycmVsYXRpb24gTWF0cml4IGFuZCBSLXNxdWFyZWQNCmNvcl9tYXRyaXggPC0gY29yKGRhdGFfc2VsZWN0ZWQyWywgYygiQUlfSU5ERVhfZGlmZiIsICJGaW50ZWNoX0luZGV4X2RpZmYiLCAiQmxvY2tjaGFpbl9JbmRleF9kaWZmIildLCB1c2UgPSAiY29tcGxldGUub2JzIikNCnJfc3F1YXJlZCA8LSBjb3JfbWF0cml4XjINCg0KIyBEaXNwbGF5IHRoZSBmaW5hbCByZXN1bHRzIHRhYmxlDQpwcmludChyZXN1bHRzKQ0KcHJpbnQoY29yX21hdHJpeCkNCnByaW50KHJfc3F1YXJlZCkNCmBgYA0KDQojICoqR2FiYXVlciBhbmQgR3VwdGEgKDIwMTgpOiAqKiBPbiB0aGUgdHJhbnNtaXNzaW9uIG1lY2hhbmlzbSBvZiBjb3VudHJ5LXNwZWNpZmljIGFuZCBpbnRlcm5hdGlvbmFsIGVjb25vbWljIHVuY2VydGFpbnR5IHNwaWxsb3ZlcnM6IEV2aWRlbmNlIGZyb20gYSBUVlAtVkFSIGNvbm5lY3RlZG5lc3MgZGVjb21wb3NpdGlvbiBhcHByb2FjaA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KZGF0YV96b28yIDwtIHpvbyhkYXRhX3NlbGVjdGVkMlssIGMoIkFJX0lOREVYX2RpZmYiLCAiRmludGVjaF9JbmRleF9kaWZmIiwgIkJsb2NrY2hhaW5fSW5kZXhfZGlmZiIpXSwgDQogICAgICAgICAgICAgICAgIG9yZGVyLmJ5ID0gZGF0YV9zZWxlY3RlZDIkRGF0ZSkNCg0KIyBDb25maWd1cmFjacOzbiBkZSBwYXLDoW1ldHJvcyBwYXJhIFRWUFZBUg0KbmxhZyA8LSAyICAgICAgICMgT3JkZW4gZGVsIHJlemFnbw0KbGFtYmRhIDwtIGMoMC45OSwgMC45OSkgICMgVmFsb3JlcyBkZSBkZWNhaW1pZW50byBwYXJhIGVsIGZpbHRybw0KDQojIENyZWFyIGxhIGxpc3RhIGRlIGNvbmZpZ3VyYWNpw7NuIG5lY2VzYXJpYQ0KY29uZmlnIDwtIGxpc3QobCA9IGxhbWJkYSwgbmxhZyA9IG5sYWcpDQoNCiMgRXN0aW1hciBlbCBtb2RlbG8gVFZQLVZBUiBjb24gbG9zIHBhcsOhbWV0cm9zIGVzcGVjaWZpY2Fkb3MNCnR2cHZhcl9tb2RlbCA8LSBUVlBWQVIoZGF0YV96b28yLCBjb25maWd1cmF0aW9uID0gY29uZmlnKQ0KYGBgDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpkY2EgPSBDb25uZWN0ZWRuZXNzQXBwcm9hY2goZGF0YV96b28yLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBubGFnPTEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmZvcmU9MTAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZWw9IlRWUC1WQVIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3RlZG5lc3M9IlRpbWUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5zaXplPTIwMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBWQVJfY29uZmlnPWxpc3QoVFZQVkFSPWxpc3Qoa2FwcGExPTAuOTksIGthcHBhMj0wLjk5LCBwcmlvcj0iQmF5ZXNQcmlvciIpKSkNCmBgYA0KDQojIyBUYWJsZSAxOiBDb25uZWN0ZWRuZXNzIHRhYmxlDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Ka2FibGUoZGNhJFRBQkxFKQ0KIyBDT05ORUNURURORVNTIERFQ09NUE9TSVRJT04NCmludCA9IEludGVybmFsQ29ubmVjdGVkbmVzcyhkY2EsIGdyb3Vwcz1saXN0KCJHcm91cDEiPWMoMSksICJHcm91cDIiPWMoMiksICJHcm91cDMiPWMoMykpKQ0KZXh0ID0gRXh0ZXJuYWxDb25uZWN0ZWRuZXNzKGRjYSwgZ3JvdXBzPWxpc3QoIkdyb3VwMSI9YygxKSwgIkdyb3VwMiI9YygyKSwgIkdyb3VwMyI9YygzKSkpDQprYWJsZShpbnQkVEFCTEUpDQprYWJsZShleHQkVEFCTEUpDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiNGaWd1cmUgMzogRHluYW1pYyB0b3RhbCBjb25uZWN0ZWRuZXNzDQpQbG90VENJKGRjYSwgaW50LCB5bGltPWMoMCwgNDApKQ0KDQojRmlndXJlIDQ6IE5ldCB0b3RhbCBkaXJlY3Rpb25hbCBjb25uZWN0ZWRuZXNzDQpQbG90TkVUKGRjYSwgaW50LCB5bGltPWMoLTEwLCAxMCkpDQoNCiNGaWd1cmUgNTogVG90YWwgZGlyZWN0aW9uYWwgY29ubmVjdGVkbmVzcyBGUk9NIG90aGVycw0KUGxvdEZST00oZGNhLCBpbnQsIHlsaW09YygwLCA2MCkpDQoNCiNGaWd1cmUgNjogVG90YWwgZGlyZWN0aW9uYWwgY29ubmVjdGVkbmVzcyBUTyBvdGhlcnMNClBsb3RUTyhkY2EsIGludCwgeWxpbT1jKDAsIDYwKSkNCg0KI0ZpZ3VyZSA3OiBJbnRlcm5hbCBuZXQgcGFpcndpc2UgdG90YWwgZGlyZWN0aW9uYWwgY29ubmVjdGVkbmVzcw0KUGxvdE5QREMoZGNhLCBpbnQsIHlsaW09YygtNSwgNSkpDQpgYGANCg0KIyAqKkNvY2NhLCBHYWJhdWVyLCBhbmQgUG9tYmVyZ2VyICgyMDI0KToqKiBDbGVhbiBlbmVyZ3kgbWFya2V0IGNvbm5lY3RlZG5lc3MgYW5kIGludmVzdG1lbnQgc3RyYXRlZ2llczogTmV3IGV2aWRlbmNlIGZyb20gRENDLUdBUkNIIFIyIGRlY29tcG9zZWQgY29ubmVjdGVkbmVzcyBtZWFzdXJlcw0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgQ29udmllcnRlIGxhIGNvbHVtbmEgJ0RhdGUnIGEgZm9ybWF0byBEYXRlDQpkYXRlIDwtIGFzLkRhdGUoZGF0YV9zZWxlY3RlZDIkRGF0ZSwgZm9ybWF0PSIlZC8lbS8lWSIpDQoNCiMgQ3JlYSBsYSBzZXJpZSBkZSB0aWVtcG8gKHpvbykgc29sbyBjb24gbGFzIGNvbHVtbmFzIHNlbGVjY2lvbmFkYXMNClkgPC0gem9vKGRhdGFfc2VsZWN0ZWQyWywgYygiRmludGVjaF9JbmRleF9kaWZmIiwgIkFJX0lOREVYX2RpZmYiLCAiQmxvY2tjaGFpbl9JbmRleF9kaWZmIildLCBvcmRlci5ieSA9IGRhdGUpDQoNCiMgQXNlZ8O6cmF0ZSBkZSBxdWUgbG9zIGRhdG9zIHNlYW4gbnVtw6lyaWNvcyB5IGVsaW1pbmEgdmFsb3JlcyBOQQ0KWSA8LSBuYS5vbWl0KHpvbyhkYXRhLmZyYW1lKA0KICBGaW50ZWNoX0luZGV4X2RpZmYgPSBhcy5udW1lcmljKGRhdGFfc2VsZWN0ZWQyJEZpbnRlY2hfSW5kZXhfZGlmZiksDQogIEFJX0lOREVYX2RpZmYgPSBhcy5udW1lcmljKGRhdGFfc2VsZWN0ZWQyJEFJX0lOREVYX2RpZmYpLA0KICBCbG9ja2NoYWluX0luZGV4X2RpZmYgPSBhcy5udW1lcmljKGRhdGFfc2VsZWN0ZWQyJEJsb2NrY2hhaW5fSW5kZXhfZGlmZikNCiksIG9yZGVyLmJ5ID0gZGF0ZSkpDQoNCiMgUmVlbXBsYXphIGxvcyB2YWxvcmVzIE5BIHJlc3RhbnRlcyBwb3IgMA0KWVtpcy5uYShZKV0gPC0gMA0KDQojIEVzdGFibGVjZSAnZGltbmFtZXMnIGRlIFkgY29uIG7Dum1lcm9zIGNvbW8gw61uZGljZXMgKGNvbW8gZW4gWTIpIHNpbiBjYW1iaWFyIGVsIMOtbmRpY2UgZGUgZmVjaGENCmRpbW5hbWVzKFkpIDwtIGxpc3QoYXMuY2hhcmFjdGVyKDE6bnJvdyhZKSksIGNvbG5hbWVzKFkpKQ0KDQpOQU1FUyA9IGNvbG5hbWVzKFkpDQprID0gbmNvbChZKQ0KdCA9IG5yb3coWSkNCg0KIyBWZXJpZmljYSBsYSBlc3RydWN0dXJhIGRlIFkNCnN0cihZKQ0KDQpgYGANCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmthYmxlKFN1bW1hcnlTdGF0aXN0aWNzKFksIG5sYWc9MjApKQ0KYGBgDQoNCiMjIEZpZ3VyZSAwOiBQZXJjZW50YWdlIGNoYW5nZXMNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpwYXIobWZjb2wgPSBjKGNlaWxpbmcoay8yKSwyKSwgb21hID0gYygwLCAxLCAwLCAwKSArIDAuNSwgbWFyID0gYygxLCAxLCAxLCAxKSArIDAuNSwgbWdwID0gYygxLCAwLjQsIDApKQ0KZm9yIChpIGluIDE6aykgew0KICBwbG90KGRhdGUsWVssaV0sdHlwZT0nbCcsbGFzPTEseGF4cz0naScseWF4cz0naScseWxpbT1jKC01MCw1MCkseGxhYj0nJyx5bGFiPScnLG1haW49cGFzdGUoTkFNRVNbaV0pLHRjaz0tLjAyLGNvbD0nc3RlZWxibHVlNCcpDQogIGdyaWQoTkEsTlVMTCkNCiAgbGluZXMoZGF0ZSxZWyxpXSxjb2w9J3N0ZWVsYmx1ZTQnKQ0KICBhYmxpbmUoaD0wLGx0eT0zKQ0KICBib3goKQ0KfQ0KYGBgDQoNCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnNwZWMgPC0gbGlzdCgpDQoNCiMgSXRlcmEgc29icmUgY2FkYSBjb2x1bW5hIGRlIFkNCmZvciAoaSBpbiAxOmspIHsNCiAgIyBJbnRlbnRhIHNlbGVjY2lvbmFyIGVsIG1lam9yIG1vZGVsbyBHQVJDSCBwYXJhIGNhZGEgc2VyaWUNCiAgdSA8LSB0cnlDYXRjaCh7DQogICAgR0FSQ0hzZWxlY3Rpb24oWVssIGldLA0KICAgICAgICAgICAgICAgICAgIGRpc3RyaWJ1dGlvbnMgPSBjKCJub3JtIiwgInN0ZCIsICJzc3RkIiwgImdlZCIsICJzZ2VkIiksDQogICAgICAgICAgICAgICAgICAgbW9kZWxzID0gYygic0dBUkNIIiwgImdqckdBUkNIIiwgImVHQVJDSCIsICJpR0FSQ0giLCAiQVZHQVJDSCIsICJUR0FSQ0giKSkNCiAgfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7DQogICAgd2FybmluZyhwYXN0ZSgiRXJyb3IgYWwgc2VsZWNjaW9uYXIgbW9kZWxvIEdBUkNIIHBhcmEgbGEgdmFyaWFibGUiLCBpLCAiOiIsIGUkbWVzc2FnZSkpDQogICAgTlVMTA0KICB9KQ0KICANCiAgIyBTaSAndScgbm8gZXMgTlVMTCB5IHRpZW5lIHVuIG1lam9yIG1vZGVsbywgYWdyZWdhIGEgJ3NwZWMnDQogIGlmICghaXMubnVsbCh1KSAmJiAhaXMubnVsbCh1JGJlc3RfdWdhcmNoKSkgew0KICAgIHNwZWNbW2ldXSA8LSB1JGJlc3RfdWdhcmNoDQogIH0gZWxzZSB7DQogICAgIyBTaSBubyBzZSBzZWxlY2Npb27DsyB1biBtb2RlbG8sIGFzaWduYSB1biBtb2RlbG8gR0FSQ0goMSwxKSBwb3IgZGVmZWN0bw0KICAgIHdhcm5pbmcocGFzdGUoIk5vIHNlIHNlbGVjY2lvbsOzIG5pbmfDum4gbW9kZWxvIEdBUkNIIHBhcmEiLCBOQU1FU1tpXSwgIi4gVXNhbmRvIG1vZGVsbyBHQVJDSCgxLDEpIGNvbiBkaXN0cmlidWNpw7NuIG5vcm1hbCIpKQ0KICAgIHNwZWNbW2ldXSA8LSB1Z2FyY2hzcGVjKHZhcmlhbmNlLm1vZGVsID0gbGlzdChtb2RlbCA9ICJzR0FSQ0giLCBnYXJjaE9yZGVyID0gYygxLCAxKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbi5tb2RlbCA9IGxpc3QoYXJtYU9yZGVyID0gYygwLCAwKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzdHJpYnV0aW9uLm1vZGVsID0gIm5vcm0iKQ0KICB9DQp9DQoNCiMgVmVyaWZpY2EgcXVlICdzcGVjJyB0ZW5nYSBtb2RlbG9zIHBhcmEgY2FkYSBzZXJpZSBlbiBZDQppZiAobGVuZ3RoKHNwZWMpICE9IGspIHsNCiAgc3RvcCgic3BlYyBubyBjb250aWVuZSBtb2RlbG9zIHbDoWxpZG9zIHBhcmEgdG9kYXMgbGFzIHNlcmllcyBkZSBZIikNCn0NCg0KIyBFamVjdXRhIGVsIG1vZGVsbyBEQ0MtR0FSQ0ggc2kgc3BlYyBlcyB2w6FsaWRhDQpmaXQgPC0gQml2YXJpYXRlRENDR0FSQ0goWSwgc3BlYykNCmBgYA0KDQojIyBUYWJsZSA0OiBFdmFsdWF0aW9uIG9mIHVuaXZhcmlhdGUgR0FSQ0ggcGVyZm9ybWFuY2UNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpIID0gZml0JEhfdA0KUiA9IGZpdCRSX3QNCg0KdUdBUkNIX3RhYmxlID0gTlVMTA0KZm9yIChpIGluIDE6aykgew0KICBmaXQgPSB1Z2FyY2hmaXQoc3BlY1tbaV1dLCBZWyxpXSkNCiAgZ3QgPSBHQVJDSHRlc3RzKGZpdCwgbGFnPTIwKQ0KICB1R0FSQ0hfdGFibGUgPSByYmluZCh1R0FSQ0hfdGFibGUsIGd0JFRBQkxFKQ0KfQ0KDQprYWJsZSh1R0FSQ0hfdGFibGUpDQpgYGANCg0KIyMgRmlndXJlIDM6IER5bmFtaWMgY29uZGl0aW9uYWwgY29ycmVsYXRpb25zDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KcGFyKG1mY29sID0gYyhjZWlsaW5nKGsvMiksMiksIG9tYSA9IGMoMCwgMSwgMCwgMCkgKyAwLjUsIG1hciA9IGMoMSwgMSwgMSwgMSkgKyAwLjUsIG1ncCA9IGMoMSwgMC40LCAwKSkNCmZvciAoaiBpbiAxOmspIHsNCiAgcGxvdChkYXRlLFJbaixqLF0sdHlwZT0nbCcsbGFzPTEseGF4cz0naScseWF4cz0naScseGxhYj0nJyx5bGFiPScnLG1haW49cGFzdGUoTkFNRVNbal0pLHRjaz0tLjAyLGNvbD1qLHlsaW09YygtMS4xLDEuMSkpDQogIGdyaWQoTkEsTlVMTCkNCiAgZm9yIChpIGluIDE6aykgew0KICAgIGxpbmVzKGRhdGUsUltqLGksXSxjb2w9aSkNCiAgICBhYmxpbmUoaD0wLGx0eT0zKQ0KICAgIGJveCgpDQogIH0NCiAgbGVnZW5kKCJib3R0b20iLE5BTUVTWy1qXSxmaWxsPWMoMTprKVstal0sYnR5PSJuIixjZXg9MC43NSxuY29sPWspDQp9DQpgYGANCg0KIyMgVGFibGUgNTogQXZlcmFnZWQgY29ubmVjdGVkbmVzcyBtZWFzdXJlcw0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmRjYSA9IFIyQ29ycmVsYXRpb25zKFIpDQprYWJsZShkY2EkVEFCTEUpDQpgYGANCg0KIyMgRmlndXJlIDQ6IER5bmFtaWMgY29uZGl0aW9uYWwgUjIgZGVjb21wb3NlZCBtZWFzdXJlcw0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnIyYyA9IGFwcGx5KGRjYSRDVCxjKDEsMyksc3VtKS0xDQpwYXIobWZjb2wgPSBjKGNlaWxpbmcoay8yKSwyKSwgb21hID0gYygwLCAxLCAwLCAwKSArIDAuNSwgbWFyID0gYygxLCAxLCAxLCAxKSArIDAuNSwgbWdwID0gYygxLCAwLjQsIDApKQ0KZm9yIChqIGluIDE6aykgew0KICByMmRkID0gbWF0cml4KDAsbmNvbD1rLG5yb3c9dCkNCiAgZm9yIChpIGluIDE6dCkgew0KICAgIGRlZCA9IHJlcCgwLGspDQogICAgZGVkW2pdID0gMQ0KICAgIHIyZGRbaSxdID0gY3Vtc3VtKGRjYSRDVFtqLCxpXS1kZWQpDQogIH0NCiAgcGxvdChkYXRlLDEwMCpyMmNbaixdKk5BLHR5cGU9ImwiLGxhcz0xLHhsYWI9IiIseWxhYj0iIix5bGltPWMoMCwxMDApLHhheHM9ImkiLHRjaz0tMC4wMSx5YXhzPSJpIixtYWluPU5BTUVTW2pdKQ0KICBncmlkKE5BLE5VTEwpDQogIGZvciAoaSBpbiBrOjEpIHsNCiAgICBwb2x5Z29uKGMoZGF0ZSwgcmV2KGRhdGUpKSwgYyhjKHJlcCgwLCB0KSksIHJldigxMDAqcjJkZFssaV0pKSwgY29sPWksIGJvcmRlcj1pKQ0KICB9DQogIGJveCgpDQogIGxlZ2VuZCgidG9wbGVmdCIsTkFNRVNbLWpdLGZpbGw9YygxOmspWy1qXSxidHk9Im4iLGNleD0wLjc1LG5jb2w9MSkNCn0NCmBgYA0KDQojIyBGaWd1cmUgNTogRHluYW1pYyB0b3RhbCBjb25uZWN0ZWRuZXNzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KcGFyKG1mY29sID0gYygxLDEpLCBvbWEgPSBjKDAsIDEsIDAsIDApICsgMC41LCBtYXIgPSBjKDEsIDEsIDEsIDEpICsgMC41LCBtZ3AgPSBjKDEsIDAuNCwgMCkpDQpwbG90KGRhdGUsZGNhJFRDSSpOQSx0eXBlPSdsJyxsYXM9MSx4YXhzPSdpJyx5YXhzPSdpJyx4bGFiPScnLHlsYWI9JycsbWFpbj0nJyx0Y2s9LS4wMSwgeWxpbT1jKDAsMTEwKSkjYyhtYXgoYygwLG1pbihUQ0kpLTEwKSksbWF4KFRDSSkrMTApKQ0KZ3JpZChOQSxOVUxMKQ0KcG9seWdvbihjKGRhdGUsIHJldihkYXRlKSksIGMoYyhyZXAoMCwgdCkpLCByZXYoZGNhJFRDSSkpLCBjb2w9MSwgYm9yZGVyPTEpDQpib3goKQ0KYGBgDQoNCiMjIEZpZ3VyZSA2OiBOZXQgdG90YWwgZGlyZWN0aW9uYWwgY29ubmVjdGVkbmVzcw0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnBhcihtZmNvbCA9IGMoY2VpbGluZyhrLzIpLDIpLCBvbWEgPSBjKDAsIDAsIDAsIDApICsgMC41LCBtYXIgPSBjKDEsIDEsIDEsIDEpICsgMC41LCBtZ3AgPSBjKDEsIDAuNCwgMCkpDQpmb3IgKGkgaW4gMTprKSB7DQogIHBsb3QoZGF0ZSxkY2EkTkVUWyxpXSpOQSx0eXBlPSdsJyxsYXM9MSx4YXhzPSdpJyx5YXhzPSdpJyx5bGltPWMoLTIwLDIwKSx4bGFiPScnLHlsYWI9JycsbWFpbj1wYXN0ZSgiTkVUIixOQU1FU1tpXSksdGNrPS0uMDI1KQ0KICBncmlkKE5BLE5VTEwpDQogIHBvbHlnb24oYyhkYXRlLCByZXYoZGF0ZSkpLCBjKGMocmVwKDAsIHQpKSwgcmV2KGRjYSRORVRbLGldKSksIGNvbD0xLCBib3JkZXI9MSkNCiAgYWJsaW5lKGg9MCxsdHk9MykNCiAgYm94KCkNCn0NCmBgYA0KDQojIyBUYWJsZSA3OiBIZWRnZSByYXRpb3MNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQptZXRob2QgPSAiY3Vtc3VtIg0Kc3RhdGlzdGljcyA9ICJGaXNoZXIiDQptZXRyaWMgPSAiU3RkRGV2Ig0KaHIgPSBIZWRnZVJhdGlvKFkvMTAwLCBILCBzdGF0aXN0aWNzPXN0YXRpc3RpY3MsIG1ldGhvZD1tZXRob2QsIG1ldHJpYz1tZXRyaWMsIGRpZ2l0PTMpDQprYWJsZShociRUQUJMRSkNCmBgYA0KIyMgVGFibGUgODogTXVsdGl2YXJpYXRlIGhlZGdpbmcgcG9ydGZvbGlvcw0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCm1ocCA9IE11bHRpdmFyaWF0ZUhlZGdpbmdQb3J0Zm9saW8oWS8xMDAsIEgsIHN0YXRpc3RpY3M9c3RhdGlzdGljcywgbWV0aG9kPW1ldGhvZCwgZGlnaXQ9MykNCmthYmxlKG1ocCRUQUJMRSkNCmBgYA0KDQojIyBGaWd1cmUgMzogRHluYW1pYyBjb25kaXRpb25hbCBiZXRhcw0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCnBhcihtZmNvbCA9IGMoY2VpbGluZyhrLzIpLDIpLCBvbWEgPSBjKDAsIDEsIDAsIDApICsgMC41LCBtYXIgPSBjKDEsIDEsIDEsIDEpICsgMC41LCBtZ3AgPSBjKDEsIDAuNCwgMCkpDQpmb3IgKGogaW4gMTprKSB7DQogIHBsb3QoZGF0ZSxtaHAkQmV0YVtqLGosXSpOQSx0eXBlPSdsJyxsYXM9MSx4YXhzPSdpJyx5YXhzPSdpJyx4bGFiPScnLHlsYWI9JycsDQogICAgICAgbWFpbj1wYXN0ZShOQU1FU1tqXSksdGNrPS0uMDIsY29sPWoseWxpbT1jKC0wLjUsODApKQ0KICBncmlkKE5BLE5VTEwpDQogIGNvZWZzID0gbG0oWVssal1+WVssLWpdKSRjb2VmZmljaWVudHNbLTFdDQogIGZvciAoaSBpbiAxOmspIHsNCiAgICBpZiAoaSE9aikgew0KICAgICAgbGluZXMoZGF0ZSxtaHAkQmV0YVtqLGksXSxjb2w9aSkNCiAgICAgIGFibGluZShoPTAsbHR5PTMpDQogICAgICBib3goKQ0KICAgIH0NCiAgfQ0KICBjb2wgPSAxOmsNCiAgY29sID0gY29sWy1qXQ0KICBhYmxpbmUoaD1jb2VmcyxsdHk9Myxjb2w9Y29sKQ0KICBsZWdlbmQoImJvdHRvbSIsTkFNRVNbLWpdLGZpbGw9YygxOmspWy1qXSxidHk9Im4iLGNleD0wLjYsbmNvbD1rKQ0KfQ0KYGBgDQoNCiMjIFRhYmxlIDk6IE9wdGltYWwgYml2YXJpYXRlIHBvcnRmb2xpbyB3ZWlnaHRzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KYnB3ID0gQml2YXJpYXRlUG9ydGZvbGlvKFkvMTAwLCBILCBzdGF0aXN0aWNzPXN0YXRpc3RpY3MsIG1ldGhvZD1tZXRob2QsIG1ldHJpYz1tZXRyaWMsIGRpZ2l0PTMpDQojIyBUaGUgb3B0aW1hbCBiaXZhcmlhdGUgcG9ydGZvbGlvcyBhcmUgY29tcHV0ZWQgYWNjb3JkaW5nIHRvOg0KIyMgIEtyb25lciwgSy4gRi4sICYgTmcsIFYuIEsuICgxOTk4KS4gTW9kZWxpbmcgYXN5bW1ldHJpYyBjb21vdmVtZW50cyBvZiBhc3NldCByZXR1cm5zLiBUaGUgUmV2aWV3IG9mIEZpbmFuY2lhbCBTdHVkaWVzLCAxMSg0KSwgODE3LTg0NC4NCiMjIA0KIyMgICAgICAgICAgIEhlZGdpbmcgZWZmZWN0aXZlbmVzcyBpcyBjYWxjdWxhdGVkIGFjY29yZGluZyB0bzoNCiMjICBFZGVyaW5ndG9uLCBMLiBILiAoMTk3OSkuIFRoZSBoZWRnaW5nIHBlcmZvcm1hbmNlIG9mIHRoZSBuZXcgZnV0dXJlcyBtYXJrZXRzLiBUaGUgSm91cm5hbCBvZiBGaW5hbmNlLCAzNCgxKSwgMTU3LTE3MC4NCiMjIA0KIyMgICAgICAgICAgIFN0YXRpc3RpY3Mgb2YgdGhlIGhlZGdpbmcgZWZmZWN0aXZlbmVzcyBtZWFzdXJlIGFyZSBpbXBsZW1lbnRlZCBhY2NvcmRpbmcgdG86DQojIyAgQW50b25ha2FraXMsIE4uLCBDdW5hZG8sIEouLCBGaWxpcywgRy4sIEdhYmF1ZXIsIEQuLCAmIGRlIEdyYWNpYSwgRi4gUC4gKDIwMjApLiBPaWwgYW5kIGFzc2V0IGNsYXNzZXMgaW1wbGllZCB2b2xhdGlsaXRpZXM6IEludmVzdG1lbnQgc3RyYXRlZ2llcyBhbmQgaGVkZ2luZyBlZmZlY3RpdmVuZXNzLiBFbmVyZ3kgRWNvbm9taWNzLCA5MSwgMTA0NzYyLg0Ka2FibGUoYnB3JFRBQkxFKQ0KYGBgDQoNCiMjIFRhYmxlIDEwOiBNdWx0aXZhcmlhdGUgcG9ydGZvbGlvIGFuYWx5c2lzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KUENJYyA9IGRjYSRQQ0kNClBDSWcgPSBkY2EkQ1QNCmZvciAobCBpbiAxOmRpbShkY2EkQ1QpWzNdKSB7DQogIGZvciAoaSBpbiAxOmspIHsNCiAgICBmb3IgKGogaW4gMTprKSB7DQogICAgICBQQ0lnW2ksaixsXSA9ICgyKlJbaSxqLGxdXjIpLygxK1JbaSxqLGxdXjIpDQogICAgfQ0KICB9DQp9DQptdnAgPSBNaW5pbXVtQ29ubmVjdGVkbmVzc1BvcnRmb2xpbyhZLzEwMCwgSCwgc3RhdGlzdGljcz1zdGF0aXN0aWNzLCBtZXRob2Q9bWV0aG9kLCBtZXRyaWM9bWV0cmljLCBkaWdpdD0zKQ0KIyMgVGhlIG1pbmltdW0gY29ubmVjdGVkbmVzcyBwb3J0Zm9saW8gaXMgaW1wbGVtZW50ZWQgYWNjb3JkaW5nIHRvOg0KIyMgIEJyb2Fkc3RvY2ssIEQuIEMuLCBDaGF0emlhbnRvbmlvdSwgSS4sICYgR2FiYXVlciwgRC4gKDIwMjIpLiBNaW5pbXVtIGNvbm5lY3RlZG5lc3MgcG9ydGZvbGlvcyBhbmQgdGhlIG1hcmtldCBmb3IgZ3JlZW4gYm9uZHM6IEFkdm9jYXRpbmcgc29jaWFsbHkgcmVzcG9uc2libGUgaW52ZXN0bWVudCAoU1JJKSBhY3Rpdml0eS4gSW4gQXBwbGljYXRpb25zIGluIEVuZXJneSBGaW5hbmNlIChwcC4gMjE3LTI1MykuIFBhbGdyYXZlIE1hY21pbGxhbiwgQ2hhbS4NCiMjIA0KIyMgICAgICAgICAgIEhlZGdpbmcgZWZmZWN0aXZlbmVzcyBpcyBjYWxjdWxhdGVkIGFjY29yZGluZyB0bzoNCiMjICBFZGVyaW5ndG9uLCBMLiBILiAoMTk3OSkuIFRoZSBoZWRnaW5nIHBlcmZvcm1hbmNlIG9mIHRoZSBuZXcgZnV0dXJlcyBtYXJrZXRzLiBUaGUgSm91cm5hbCBvZiBGaW5hbmNlLCAzNCgxKSwgMTU3LTE3MC4NCiMjIA0KIyMgICAgICAgICAgIFN0YXRpc3RpY3Mgb2YgdGhlIGhlZGdpbmcgZWZmZWN0aXZlbmVzcyBtZWFzdXJlIGFyZSBpbXBsZW1lbnRlZCBhY2NvcmRpbmcgdG86DQojIyAgQW50b25ha2FraXMsIE4uLCBDdW5hZG8sIEouLCBGaWxpcywgRy4sIEdhYmF1ZXIsIEQuLCAmIGRlIEdyYWNpYSwgRi4gUC4gKDIwMjApLiBPaWwgYW5kIGFzc2V0IGNsYXNzZXMgaW1wbGllZCB2b2xhdGlsaXRpZXM6IEludmVzdG1lbnQgc3RyYXRlZ2llcyBhbmQgaGVkZ2luZyBlZmZlY3RpdmVuZXNzLiBFbmVyZ3kgRWNvbm9taWNzLCA5MSwgMTA0NzYyLg0KbWNwID0gTWluaW11bUNvbm5lY3RlZG5lc3NQb3J0Zm9saW8oWS8xMDAsIFIsIHN0YXRpc3RpY3M9c3RhdGlzdGljcywgbWV0aG9kPW1ldGhvZCwgbWV0cmljPW1ldHJpYywgZGlnaXQ9MykNCiMjIFRoZSBtaW5pbXVtIGNvbm5lY3RlZG5lc3MgcG9ydGZvbGlvIGlzIGltcGxlbWVudGVkIGFjY29yZGluZyB0bzoNCiMjICBCcm9hZHN0b2NrLCBELiBDLiwgQ2hhdHppYW50b25pb3UsIEkuLCAmIEdhYmF1ZXIsIEQuICgyMDIyKS4gTWluaW11bSBjb25uZWN0ZWRuZXNzIHBvcnRmb2xpb3MgYW5kIHRoZSBtYXJrZXQgZm9yIGdyZWVuIGJvbmRzOiBBZHZvY2F0aW5nIHNvY2lhbGx5IHJlc3BvbnNpYmxlIGludmVzdG1lbnQgKFNSSSkgYWN0aXZpdHkuIEluIEFwcGxpY2F0aW9ucyBpbiBFbmVyZ3kgRmluYW5jZSAocHAuIDIxNy0yNTMpLiBQYWxncmF2ZSBNYWNtaWxsYW4sIENoYW0uDQojIyANCiMjICAgICAgICAgICBIZWRnaW5nIGVmZmVjdGl2ZW5lc3MgaXMgY2FsY3VsYXRlZCBhY2NvcmRpbmcgdG86DQojIyAgRWRlcmluZ3RvbiwgTC4gSC4gKDE5NzkpLiBUaGUgaGVkZ2luZyBwZXJmb3JtYW5jZSBvZiB0aGUgbmV3IGZ1dHVyZXMgbWFya2V0cy4gVGhlIEpvdXJuYWwgb2YgRmluYW5jZSwgMzQoMSksIDE1Ny0xNzAuDQojIyANCiMjICAgICAgICAgICBTdGF0aXN0aWNzIG9mIHRoZSBoZWRnaW5nIGVmZmVjdGl2ZW5lc3MgbWVhc3VyZSBhcmUgaW1wbGVtZW50ZWQgYWNjb3JkaW5nIHRvOg0KIyMgIEFudG9uYWtha2lzLCBOLiwgQ3VuYWRvLCBKLiwgRmlsaXMsIEcuLCBHYWJhdWVyLCBELiwgJiBkZSBHcmFjaWEsIEYuIFAuICgyMDIwKS4gT2lsIGFuZCBhc3NldCBjbGFzc2VzIGltcGxpZWQgdm9sYXRpbGl0aWVzOiBJbnZlc3RtZW50IHN0cmF0ZWdpZXMgYW5kIGhlZGdpbmcgZWZmZWN0aXZlbmVzcy4gRW5lcmd5IEVjb25vbWljcywgOTEsIDEwNDc2Mi4NCm1wYyA9IE1pbmltdW1Db25uZWN0ZWRuZXNzUG9ydGZvbGlvKFkvMTAwLCBQQ0ljLCBzdGF0aXN0aWNzPXN0YXRpc3RpY3MsIG1ldGhvZD1tZXRob2QsIG1ldHJpYz1tZXRyaWMsIGRpZ2l0PTMpDQojIyBUaGUgbWluaW11bSBjb25uZWN0ZWRuZXNzIHBvcnRmb2xpbyBpcyBpbXBsZW1lbnRlZCBhY2NvcmRpbmcgdG86DQojIyAgQnJvYWRzdG9jaywgRC4gQy4sIENoYXR6aWFudG9uaW91LCBJLiwgJiBHYWJhdWVyLCBELiAoMjAyMikuIE1pbmltdW0gY29ubmVjdGVkbmVzcyBwb3J0Zm9saW9zIGFuZCB0aGUgbWFya2V0IGZvciBncmVlbiBib25kczogQWR2b2NhdGluZyBzb2NpYWxseSByZXNwb25zaWJsZSBpbnZlc3RtZW50IChTUkkpIGFjdGl2aXR5LiBJbiBBcHBsaWNhdGlvbnMgaW4gRW5lcmd5IEZpbmFuY2UgKHBwLiAyMTctMjUzKS4gUGFsZ3JhdmUgTWFjbWlsbGFuLCBDaGFtLg0KIyMgDQojIyAgICAgICAgICAgSGVkZ2luZyBlZmZlY3RpdmVuZXNzIGlzIGNhbGN1bGF0ZWQgYWNjb3JkaW5nIHRvOg0KIyMgIEVkZXJpbmd0b24sIEwuIEguICgxOTc5KS4gVGhlIGhlZGdpbmcgcGVyZm9ybWFuY2Ugb2YgdGhlIG5ldyBmdXR1cmVzIG1hcmtldHMuIFRoZSBKb3VybmFsIG9mIEZpbmFuY2UsIDM0KDEpLCAxNTctMTcwLg0KIyMgDQojIyAgICAgICAgICAgU3RhdGlzdGljcyBvZiB0aGUgaGVkZ2luZyBlZmZlY3RpdmVuZXNzIG1lYXN1cmUgYXJlIGltcGxlbWVudGVkIGFjY29yZGluZyB0bzoNCiMjICBBbnRvbmFrYWtpcywgTi4sIEN1bmFkbywgSi4sIEZpbGlzLCBHLiwgR2FiYXVlciwgRC4sICYgZGUgR3JhY2lhLCBGLiBQLiAoMjAyMCkuIE9pbCBhbmQgYXNzZXQgY2xhc3NlcyBpbXBsaWVkIHZvbGF0aWxpdGllczogSW52ZXN0bWVudCBzdHJhdGVnaWVzIGFuZCBoZWRnaW5nIGVmZmVjdGl2ZW5lc3MuIEVuZXJneSBFY29ub21pY3MsIDkxLCAxMDQ3NjIuDQptcGcgPSBNaW5pbXVtQ29ubmVjdGVkbmVzc1BvcnRmb2xpbyhZLzEwMCwgUENJZywgc3RhdGlzdGljcz1zdGF0aXN0aWNzLCBtZXRob2Q9bWV0aG9kLCBtZXRyaWM9bWV0cmljLCBkaWdpdD0zKQ0KIyMgVGhlIG1pbmltdW0gY29ubmVjdGVkbmVzcyBwb3J0Zm9saW8gaXMgaW1wbGVtZW50ZWQgYWNjb3JkaW5nIHRvOg0KIyMgIEJyb2Fkc3RvY2ssIEQuIEMuLCBDaGF0emlhbnRvbmlvdSwgSS4sICYgR2FiYXVlciwgRC4gKDIwMjIpLiBNaW5pbXVtIGNvbm5lY3RlZG5lc3MgcG9ydGZvbGlvcyBhbmQgdGhlIG1hcmtldCBmb3IgZ3JlZW4gYm9uZHM6IEFkdm9jYXRpbmcgc29jaWFsbHkgcmVzcG9uc2libGUgaW52ZXN0bWVudCAoU1JJKSBhY3Rpdml0eS4gSW4gQXBwbGljYXRpb25zIGluIEVuZXJneSBGaW5hbmNlIChwcC4gMjE3LTI1MykuIFBhbGdyYXZlIE1hY21pbGxhbiwgQ2hhbS4NCiMjIA0KIyMgICAgICAgICAgIEhlZGdpbmcgZWZmZWN0aXZlbmVzcyBpcyBjYWxjdWxhdGVkIGFjY29yZGluZyB0bzoNCiMjICBFZGVyaW5ndG9uLCBMLiBILiAoMTk3OSkuIFRoZSBoZWRnaW5nIHBlcmZvcm1hbmNlIG9mIHRoZSBuZXcgZnV0dXJlcyBtYXJrZXRzLiBUaGUgSm91cm5hbCBvZiBGaW5hbmNlLCAzNCgxKSwgMTU3LTE3MC4NCiMjIA0KIyMgICAgICAgICAgIFN0YXRpc3RpY3Mgb2YgdGhlIGhlZGdpbmcgZWZmZWN0aXZlbmVzcyBtZWFzdXJlIGFyZSBpbXBsZW1lbnRlZCBhY2NvcmRpbmcgdG86DQojIyAgQW50b25ha2FraXMsIE4uLCBDdW5hZG8sIEouLCBGaWxpcywgRy4sIEdhYmF1ZXIsIEQuLCAmIGRlIEdyYWNpYSwgRi4gUC4gKDIwMjApLiBPaWwgYW5kIGFzc2V0IGNsYXNzZXMgaW1wbGllZCB2b2xhdGlsaXRpZXM6IEludmVzdG1lbnQgc3RyYXRlZ2llcyBhbmQgaGVkZ2luZyBlZmZlY3RpdmVuZXNzLiBFbmVyZ3kgRWNvbm9taWNzLCA5MSwgMTA0NzYyLg0KbXJwID0gTWluaW11bUNvbm5lY3RlZG5lc3NQb3J0Zm9saW8oWS8xMDAsIGRjYSRDVCwgc3RhdGlzdGljcz1zdGF0aXN0aWNzLCBtZXRob2Q9bWV0aG9kLCBtZXRyaWM9bWV0cmljLCBkaWdpdD0zKQ0KIyMgVGhlIG1pbmltdW0gY29ubmVjdGVkbmVzcyBwb3J0Zm9saW8gaXMgaW1wbGVtZW50ZWQgYWNjb3JkaW5nIHRvOg0KIyMgIEJyb2Fkc3RvY2ssIEQuIEMuLCBDaGF0emlhbnRvbmlvdSwgSS4sICYgR2FiYXVlciwgRC4gKDIwMjIpLiBNaW5pbXVtIGNvbm5lY3RlZG5lc3MgcG9ydGZvbGlvcyBhbmQgdGhlIG1hcmtldCBmb3IgZ3JlZW4gYm9uZHM6IEFkdm9jYXRpbmcgc29jaWFsbHkgcmVzcG9uc2libGUgaW52ZXN0bWVudCAoU1JJKSBhY3Rpdml0eS4gSW4gQXBwbGljYXRpb25zIGluIEVuZXJneSBGaW5hbmNlIChwcC4gMjE3LTI1MykuIFBhbGdyYXZlIE1hY21pbGxhbiwgQ2hhbS4NCiMjIA0KIyMgICAgICAgICAgIEhlZGdpbmcgZWZmZWN0aXZlbmVzcyBpcyBjYWxjdWxhdGVkIGFjY29yZGluZyB0bzoNCiMjICBFZGVyaW5ndG9uLCBMLiBILiAoMTk3OSkuIFRoZSBoZWRnaW5nIHBlcmZvcm1hbmNlIG9mIHRoZSBuZXcgZnV0dXJlcyBtYXJrZXRzLiBUaGUgSm91cm5hbCBvZiBGaW5hbmNlLCAzNCgxKSwgMTU3LTE3MC4NCiMjIA0KIyMgICAgICAgICAgIFN0YXRpc3RpY3Mgb2YgdGhlIGhlZGdpbmcgZWZmZWN0aXZlbmVzcyBtZWFzdXJlIGFyZSBpbXBsZW1lbnRlZCBhY2NvcmRpbmcgdG86DQojIyAgQW50b25ha2FraXMsIE4uLCBDdW5hZG8sIEouLCBGaWxpcywgRy4sIEdhYmF1ZXIsIEQuLCAmIGRlIEdyYWNpYSwgRi4gUC4gKDIwMjApLiBPaWwgYW5kIGFzc2V0IGNsYXNzZXMgaW1wbGllZCB2b2xhdGlsaXRpZXM6IEludmVzdG1lbnQgc3RyYXRlZ2llcyBhbmQgaGVkZ2luZyBlZmZlY3RpdmVuZXNzLiBFbmVyZ3kgRWNvbm9taWNzLCA5MSwgMTA0NzYyLg0KTVZBID0gcmJpbmQobXZwJFRBQkxFLCBtY3AkVEFCTEUsIG1wYyRUQUJMRSwgbXBnJFRBQkxFLCBtcnAkVEFCTEUpDQprYWJsZShNVkEpDQpgYGANCg0KIyMgVGFibGUgMTE6IFBvcnRmb2xpbyBwZXJmb3JtYW5jZQ0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpDQpsaWJyYXJ5KHh0cykNCnBvcnQubWF0ID0gZGF0YS5mcmFtZSgNCiAgICAgICAgICAgICAgICAgICAgIE1WUD1tdnAkcG9ydGZvbGlvX3JldHVybiwNCiAgICAgICAgICAgICAgICAgICAgIE1DUD1tY3AkcG9ydGZvbGlvX3JldHVybiwNCiAgICAgICAgICAgICAgICAgICAgIE1QQz1tcGMkcG9ydGZvbGlvX3JldHVybiwNCiAgICAgICAgICAgICAgICAgICAgIE1QRz1tcGckcG9ydGZvbGlvX3JldHVybiwNCiAgICAgICAgICAgICAgICAgICAgIE1SUD1tcnAkcG9ydGZvbGlvX3JldHVybg0KICAgICAgICAgICAgICAgICAgICAgKQ0KcG9ydC54dHMgPSB4dHMocG9ydC5tYXQsIG9yZGVyLmJ5PWRhdGUpDQppciA9IG1hdHJpeChOQSwgbnJvdz0xLCBuY29sPW5jb2wocG9ydC54dHMpKQ0KY29sbmFtZXMoaXIpID0gY29sbmFtZXMocG9ydC54dHMpDQpyb3duYW1lcyhpcikgPSAiR1JFIg0KZm9yIChpIGluIDE6bmNvbChwb3J0Lnh0cykpIHsNCiAgaXJbLGldID0gSW5mb3JtYXRpb25SYXRpbyhSYT1wb3J0Lnh0c1ssaV0sIFJiPVlbLDFdLzEwMCkNCn0NCmsgPSBuY29sKHBvcnQueHRzKQ0KdGFibGUgPSBtYXRyaXgoTkEsIG5jb2w9aywgbnJvdz01KQ0KZm9yIChpIGluIDE6aykgew0KICB0YWJsZVssaV0gPSBjKA0KICAjIFJldG9ybm8gYW51YWxpemFkbw0KICBSZXR1cm4uYW5udWFsaXplZChwb3J0Lnh0c1ssaV0pLA0KICANCiAgIyBEZXN2aWFjacOzbiBlc3TDoW5kYXIgYW51YWxpemFkYQ0KICBTdGREZXYuYW5udWFsaXplZChwb3J0Lnh0c1ssaV0pLA0KICANCiAgIyBSYXRpbyBkZSBTaGFycGUgYW51YWxpemFkbw0KICBTaGFycGVSYXRpby5hbm51YWxpemVkKHBvcnQueHRzWyxpXSksDQogIA0KICAjIFZhbG9yIGVuIFJpZXNnbyAoVmFSKSBjb24gZGlzdHJpYnVjacOzbiBub3JtYWwgeSBwZXJjZW50aWwgZGVsIDk1JQ0KICBWYVIoYXMubnVtZXJpYyhwb3J0Lnh0c1ssaV0pLCBwPTAuOTUsIG1ldGhvZD0iZ2F1c3NpYW4iKSwNCiAgDQogICMgRXhwZWN0YXRpdmEgZGUgUMOpcmRpZGEgKEVTKSBjb24gZGlzdHJpYnVjacOzbiBub3JtYWwgeSBwZXJjZW50aWwgZGVsIDk1JQ0KICBFUyhhcy5udW1lcmljKHBvcnQueHRzWyxpXSksIHA9MC45NSwgbWV0aG9kPSJnYXVzc2lhbiIpDQopDQp9DQpjb2xuYW1lcyh0YWJsZSkgPSBjb2xuYW1lcyhwb3J0Lnh0cykNCnJvd25hbWVzKHRhYmxlKSA9IGMoIlJldHVybiIsIlN0ZERldiIsIlNoYXJwZSBSYXRpbyAoU3RkRGV2KSIsIlNoYXJwZSBSYXRpbyAoVmFSKSIsIlNoYXJwZSBSYXRpbyAoQ1ZhUikiKQ0Ka2FibGUocmJpbmQodGFibGUsIGlyKSkNCmBgYA0K