Equipo #6:

  • A01368516 - Nayeli Peña Martínez
  • A00833113 - Avril Lobato
  • A01771127 - Lesly Darian Romero Vazquez
  • A00831105 - Jazmin del Carmen Cortez Mendoza
  • A01198184 - Karla Sánchez del Ángel
  • A01198186 - Luis Angel Elizondo Gallegos

knitr::opts_chunk$set(
    echo = TRUE,
    message = FALSE,
    warning = FALSE
)
#install.packages("rnaturalearthhires", repos = "https://packages.ropensci.org")
#install.packages("devtools")
pacman::p_load(dplyr, ggplot2, naniar, tseries, corrplot, patchwork, readxl, psych, maps, sf, rnaturalearth, rnaturalearthdata, stringi, scales, dlookr, DataExplorer, tidyr, knitr, RColorBrewer, plotly, forecast, tseries, openxlsx, vars, lmtest)

1 Introducción

1.1 Describir las principales características de una base de datos de series de tiempo.

Las bases de datos de series temporales contienen datos indexados en el tiempo. Permiten almacenar y realizar análisis de grandes cantidades de datos que se ubican en intervalos de tiempo y tienen una estructura regular. Los análisis de series de tiempo buscan enfocarse en el análisis de una principal variable para estudiar su pasado y poder predecir su futuro. Las BD se series de tiempo tienen 4 componentes principales: tendencia (patrón de la evolución de los datos), estacionalidad (variación de los datos en ciertas estaciones), ciclicidad (patrones de más de un año), aleatoriedad o variación irregular (factores que no pueden predecirse).

1.2 Brevemente, describir cómo el análisis de datos de series de tiempo puede contribuir a pronosticar cambios y/o patrones en los flujos de inversión extranjera directa (IED) asociadas con decisiones de “Nearshoring” para el caso de México.

Mediante modelos estadísticos como ARMA, ARIMA, VAR se pueden identificar patrones en el comportamiento histórico de los nuevos flujos de inversión extranjera directa y se pueden realizar proyecciones futuras. Estas proyecciones facilitan la toma de decisiones estratégicas relacionadas con el crecimiento del nearshoring. Además, estos análisis permiten aceptar o rechazar hipótesis que facilitan comprender la situación actual y futura del nearshoring en México considerando variables macroeconómicas que influyen en este suceso.

2 Análisis Exploratorio de Variables

2.1 Visualización de base original

library(openxlsx)
df <- read.xlsx("act3_data.xlsx", sheet = "time series data")
kable(head(df))
Year Quarter New_FDI_Inflows Exchange_Rate INPC Exports
2006 I 896.5577 10.81770 60.77251 17374.67
2006 II 2110.3751 10.92880 60.64300 17908.74
2006 III 1284.0054 10.90631 61.73661 17504.90
2006 IV 2677.7047 10.91399 62.69242 17485.93
2007 I 3108.2192 10.93540 63.32911 18499.28
2007 II 2560.7016 10.89572 63.05817 19238.75

2.2 Revisión de valores nulos

La BD contiene 5 variables: Year, Quarter, New_FDI_Inflows, Exchange_Rate, INPC y Exports. La variable principal de interés es New_FDI_Inflows que nos servirá como indicador del Nearshoring.

Asimismo, se observa que no hay valores nulos en la base de datos. De igual manera, se presentan únicamente dos valores negativos en la variable de New_FDI_Inflows, mientras que el resto de los datos son positivos.

# Nulos Totales
sum(is.na(df))
## [1] 0
# Nulos por Columna
gg_miss_var(df)

# Mostrar registros con nulos
kable(df[rowSums(is.na(df)) > 0, c(1, 2, ncol(df))])
Year Quarter Exports

2.3 Conversión de variables

Las variables nominales de New_FDI_Inflows y Exports se convirtieron a valores reales junto con la conversión a pesos para tener todos los campos en la misma moneda.

# Convertir a Pesos
df$New_FDI_Inflows<- (df$New_FDI_Inflows*df$Exchange_Rate)
df$Exports<- (df$Exports*df$Exchange_Rate)

# Convertir a Reales
df$New_FDI_Inflows<- (df$New_FDI_Inflows/df$INPC)*100
df$Exports<- (df$Exports/df$INPC)*100

clases1 <- sapply(df, class)
clases1
##            Year         Quarter New_FDI_Inflows   Exchange_Rate            INPC 
##       "numeric"     "character"       "numeric"       "numeric"       "numeric" 
##         Exports 
##       "numeric"

Los registros de la columna Quarter se modificaron a valores numéricos; mientras que los demás se mantuvieron en el mismo formato.

# Conversión de tipo de datos
library(dplyr)

df <- df %>%
  mutate(Quarter = recode(Quarter, "I" = 1, "II" = 2, "III" = 3, "IV" = 4))

df$Quarter<-as.numeric(df$Quarter) 
clases2 <- sapply(df, class)
clases2
##            Year         Quarter New_FDI_Inflows   Exchange_Rate            INPC 
##       "numeric"       "numeric"       "numeric"       "numeric"       "numeric" 
##         Exports 
##       "numeric"

2.4 Distribución de variables

Se observa que hay más valores atípicos en la variable de interés New_FDI_Inflows; sin embargo, estos outliers no se eliminarán con el fin de representar la relalidad de esa variable en el tiempo.

par(mfrow = c(2, 2))  # 2 filas, 2 columnas (ajusta según la cantidad de variables)

boxplot(df$New_FDI_Inflows, main = "New_FDI_Inflows", col = "lightblue")
boxplot(df$Exchange_Rate, main = "Exchange_Rate", col = "lightgreen")
boxplot(df$INPC, main = "INPC", col = "lightpink")
boxplot(df$Exports, main = "Exports", col = "purple")

3 Estadísticos descriptivos

Los datos muestran una evolución económica con fluctuaciones en inversión extranjera directa, tipo de cambio e inflación. Es importante revisar la posible presencia de valores atípicos en New_FDI_Inflows, ya que hay valores negativos significativos.

summary(df)
##       Year         Quarter      New_FDI_Inflows  Exchange_Rate  
##  Min.   :2006   Min.   :1.000   Min.   :-38180   Min.   :10.82  
##  1st Qu.:2010   1st Qu.:1.250   1st Qu.: 30997   1st Qu.:12.69  
##  Median :2015   Median :2.000   Median : 44891   Median :15.78  
##  Mean   :2015   Mean   :2.473   Mean   : 50555   Mean   :15.71  
##  3rd Qu.:2019   3rd Qu.:3.000   3rd Qu.: 65660   3rd Qu.:19.19  
##  Max.   :2024   Max.   :4.000   Max.   :243723   Max.   :21.60  
##       INPC           Exports      
##  Min.   : 60.64   Min.   :271885  
##  1st Qu.: 73.87   1st Qu.:385541  
##  Median : 87.41   Median :541980  
##  Mean   : 90.90   Mean   :531079  
##  3rd Qu.:105.44   3rd Qu.:664138  
##  Max.   :134.59   Max.   :811047

3.1 Gráfico de dispersión

Las distribuciones sugieren que algunas variables, como New_FDI_Inflows y Exchange_Rate, pueden requerir transformaciones para mejorar la normalidad. También se observa que New_FDI_Inflows e INPC tienen una media mayor a la mediana por lo que están sesgadas a la derecha. Asimismo, Exports tiene una mediana mayor que la media, está sesgada levemente a la izquierda.

plot_histogram(df)

3.2 Gráfico de normalidad

Se realizaron gráficos de normalidad para comparar la distribución de las variables aplciando transformaciones logarítmicas y de raíz cuadrada. Se observó que las distribuciones logarítmicas de Exchange_Rate, INPC y Exports eran mejores que las distribuciones originales de las variables, por lo que se decidió realizar la transformación logarítmica de esas variables.

plot_normality(df)

3.3 Transformación de variables

La transformación logarítmica mejora la distribución de algunas variables, haciéndolas más simétricas y reduciendo la varianza. Esto es útil para análisis econométricos y modelos que asumen normalidad.

df <- df %>%
  mutate(
    log_Exchange_Rate = log(Exchange_Rate + 0.0001),
    log_INPC = log(INPC + 0.0001),
    log_Exports = log(Exports + 0.0001)
  )
# Gráfico de dispersión
plot_histogram(df)

summary(df)
##       Year         Quarter      New_FDI_Inflows  Exchange_Rate  
##  Min.   :2006   Min.   :1.000   Min.   :-38180   Min.   :10.82  
##  1st Qu.:2010   1st Qu.:1.250   1st Qu.: 30997   1st Qu.:12.69  
##  Median :2015   Median :2.000   Median : 44891   Median :15.78  
##  Mean   :2015   Mean   :2.473   Mean   : 50555   Mean   :15.71  
##  3rd Qu.:2019   3rd Qu.:3.000   3rd Qu.: 65660   3rd Qu.:19.19  
##  Max.   :2024   Max.   :4.000   Max.   :243723   Max.   :21.60  
##       INPC           Exports       log_Exchange_Rate    log_INPC    
##  Min.   : 60.64   Min.   :271885   Min.   :2.381     Min.   :4.105  
##  1st Qu.: 73.87   1st Qu.:385541   1st Qu.:2.541     1st Qu.:4.302  
##  Median : 87.41   Median :541980   Median :2.759     Median :4.471  
##  Mean   : 90.90   Mean   :531079   Mean   :2.728     Mean   :4.484  
##  3rd Qu.:105.44   3rd Qu.:664138   3rd Qu.:2.954     3rd Qu.:4.658  
##  Max.   :134.59   Max.   :811047   Max.   :3.073     Max.   :4.902  
##   log_Exports   
##  Min.   :12.51  
##  1st Qu.:12.86  
##  Median :13.20  
##  Mean   :13.13  
##  3rd Qu.:13.41  
##  Max.   :13.61

3.4 Matriz de correlación

La matriz de correlación muestra que la variable dependiente New_FDI_Inflows tiene muy poca correlación con las demás variables. Todas las demás variables tanto con su estructura original como con transformación logarítmica muestras una muy alta correlación entre ellas.

plot_correlation(df)

4 Análisis de series de tiempo

4.1 Crear 2 – 3 gráficos de series de tiempo que muestren el desempeño de las variables de interés.

La imagen muestra una serie de tiempo de los flujos de inversión extranjera directa (FDI) nuevos a lo largo del tiempo. El eje X representa los años (aproximadamente desde 2006 hasta mediados 2024), y el eje Y muestra el valor de los flujos de inversión. La serie presenta fluctuaciones con varios picos y caídas, destacándose un pico muy pronunciado alrededor de 2010 y otro aumento significativo después de 2020.

df$New_FDI_Inflows <- na.omit(df$New_FDI_Inflows)
New_FDI_ts2 <- ts(df$New_FDI_Inflows, start = c(2006, 1), end = c(2024, 4), frequency = 4)
plot(New_FDI_ts2, type = "l", col = "blue", lwd = 2, xlab = "Year", ylab = "New_FDI_Inflows", main = "Time Series of New_FDI_Inflows")

La serie muestra estacionalidad porque hay picos periódicos de altas y bajas que ocurren regularmente. La serie muestra una leve tendencia, con fluctuaciones entre periodos de crecimiento y periodos de disminución.

decomposition <- decompose(New_FDI_ts2)
plot(decomposition)

4.2 Describir brevemente el desempeño de la(s) variable(s) de interés para cada uno de los gráficos anteriores. Es importante identificar la presencia de algún tipo de tendencia, estacionalidad, y autocorrelación en cada uno de los gráficos elaborados.

Se observa que las variables presentan tendencias al alza en el largo plazo, aunque el tipo de cambio muestra variaciones más abruptas en ciertos periodos, mientras que el INPC y Exports tiene un comportamiento más estable y predecible.

Tipo de Cambio (Exchange Rate)

  • Tendencia: Se observa una tendencia creciente desde 2005 hasta aproximadamente 2020, con algunos períodos de estabilidad. Después de 2020, hay una ligera disminución.

  • Estacionalidad: No parece haber patrones estacionales evidentes en los datos.

  • Autocorrelación: La serie parece mostrar autocorrelación, ya que los cambios en el tipo de cambio ocurren de manera escalonada con ajustes bruscos en ciertos puntos, lo que sugiere dependencia de valores pasados.

Índice Nacional de Precios al Consumidor (INPC)

  • Tendencia: Se aprecia una tendencia creciente y sostenida a lo largo del tiempo, indicando un aumento constante en los precios.

  • Estacionalidad: No se observan fluctuaciones cíclicas que sugieran un patrón estacional marcado.

  • Autocorrelación: La serie muestra una fuerte correlación con valores pasados, ya que el INPC sigue un patrón de crecimiento progresivo sin caídas abruptas.

Exportaciones (Exports)

  • Tendencia: Se observa una tendencia ascendente en las exportaciones desde el inicio de la serie hasta alrededor de 2022. En los últimos periodos, hay una caída notable en las exportaciones, lo que podría indicar una posible desaceleración o crisis en el sector.

  • Estacionalidad: Se pueden notar breves fluctuaciones dentro del crecimiento, lo que sugiere cierto nivel de patrones estacionales.

  • Autocorrelación: La serie muestra correlación con valores pasados debido a los cambios que ocurren en la variable de manera escalonada.

Exchange_Rate_ts <- ts(df$log_Exchange_Rate, start = c(2006, 1), end = c(2023, 4), frequency = 4)
INPC_ts <- ts(df$log_INPC, start = c(2006, 1), end = c(2023, 4), frequency = 4)
Exports_ts <- ts(df$log_Exports, start = c(2006, 1), end = c(2023, 4), frequency = 4)

# 1. Gráfico de series de tiempo con ggplot2
plot_time_series <- function(ts_data, var_name) {
  ts_df <- data.frame(Year = time(ts_data), Value = as.numeric(ts_data))
  ggplot(ts_df, aes(x = Year, y = Value)) +
    geom_line(color = "blue", size = 1) +
    labs(title = paste("Time Series of", var_name), x = "Year", y = var_name) +
    theme_minimal()
}

# Mostrar gráficos
print(plot_time_series(Exchange_Rate_ts, "Exchange Rate"))

print(plot_time_series(INPC_ts, "INPC"))

print(plot_time_series(Exports_ts, "Exports"))

4.3 Autocorrelación

No hay evidencia de autocorrelación significativa en los residuos, lo que sugiere que el modelo captura bien la estructura temporal de los datos y no deja patrones no explicados. Esto es un buen indicador de un modelo adecuado.

# Autocorrelación y autocorrelación parcial
acf(New_FDI_ts2, main="Autocorrelation - New_FDI_Inflows")

pacf(New_FDI_ts2, main="Partial Autocorrelation - New_FDI_Inflows")

# Aucotorrelación serial
lgunj_box_result <- Box.test(New_FDI_ts2, lag = 5, type = "Ljung-Box")
lgunj_box_result
## 
##  Box-Ljung test
## 
## data:  New_FDI_ts2
## X-squared = 4.1004, df = 5, p-value = 0.5351

4.4 Estacionariedad

Se observa que para las tres variables, los p-valores son altos (> 0.05), por lo que no se rechaza la hipótesis nula de raíz unitaria; es decir, las series no son estacionarias, lo que sugiere que pueden requerir diferenciación o transformación adicional para su uso en modelos de series de tiempo.

# Aplicar la prueba ADF sobre las variables transformadas en log
adf_test_log_exchange <- adf.test(df$log_Exchange_Rate)
adf_test_log_inpc <- adf.test(df$log_INPC)
adf_test_log_exports <- adf.test(df$log_Exports)

# Mostrar resultados de la prueba ADF
print(adf_test_log_exchange)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  df$log_Exchange_Rate
## Dickey-Fuller = -1.9926, Lag order = 4, p-value = 0.5784
## alternative hypothesis: stationary
print(adf_test_log_inpc)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  df$log_INPC
## Dickey-Fuller = -2.1842, Lag order = 4, p-value = 0.5003
## alternative hypothesis: stationary
print(adf_test_log_exports)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  df$log_Exports
## Dickey-Fuller = -0.66538, Lag order = 4, p-value = 0.9691
## alternative hypothesis: stationary

4.5 AUTO ARIMA

Con base a la presencia de estacionariedad, se genera modelo AUTOARIMA para determinar mejor nivel de diferenciación para cada variable.

# Aplicar auto.arima() a las variables sin diferenciarlas diferenciadas
auto_arima_FDI <- auto.arima(New_FDI_ts2) #No se aplica , se va directo a un modelo ARMA

auto_arima_model1 <- auto.arima(df$log_Exchange)
auto_arima_model2 <- auto.arima(df$log_INPC)
auto_arima_model3 <- auto.arima(df$log_Exports)

summary(auto_arima_FDI)
## Series: New_FDI_ts2 
## ARIMA(0,0,0)(0,0,1)[4] with non-zero mean 
## 
## Coefficients:
##          sma1       mean
##       -0.2314  50592.372
## s.e.   0.1304   3354.131
## 
## sigma^2 = 1.422e+09:  log likelihood = -907.79
## AIC=1821.58   AICc=1821.92   BIC=1828.58
## 
## Training set error measures:
##                     ME     RMSE     MAE       MPE     MAPE      MASE       ACF1
## Training set -173.8284 37206.77 25689.8 -75.25536 111.8246 0.6754892 0.05067555
summary(auto_arima_model1)
## Series: df$log_Exchange 
## ARIMA(0,1,0) 
## 
## sigma^2 = 0.002158:  log likelihood = 120.48
## AIC=-238.95   AICc=-238.89   BIC=-236.66
## 
## Training set error measures:
##                       ME       RMSE        MAE      MPE      MAPE      MASE
## Training set 0.007195362 0.04614004 0.02255997 0.258678 0.8174822 0.9878956
##                     ACF1
## Training set -0.02355653
summary(auto_arima_model2)
## Series: df$log_INPC 
## ARIMA(0,1,0) with drift 
## 
## Coefficients:
##        drift
##       0.0109
## s.e.  0.0010
## 
## sigma^2 = 7.939e-05:  log likelihood = 241.63
## AIC=-479.26   AICc=-479.09   BIC=-474.68
## 
## Training set error measures:
##                        ME        RMSE         MAE          MPE      MAPE
## Training set 5.535466e-05 0.008789015 0.006994749 8.856065e-05 0.1565279
##                   MASE          ACF1
## Training set 0.5708373 -0.0004828418
summary(auto_arima_model3)
## Series: df$log_Exports 
## ARIMA(0,1,1) with drift 
## 
## Coefficients:
##           ma1   drift
##       -0.3437  0.0097
## s.e.   0.1209  0.0054
## 
## sigma^2 = 0.00493:  log likelihood = 91.29
## AIC=-176.58   AICc=-176.23   BIC=-169.71
## 
## Training set error measures:
##                        ME       RMSE        MAE         MPE      MAPE      MASE
## Training set 0.0002271215 0.06877616 0.05203452 0.001070896 0.3956536 0.9923729
##                    ACF1
## Training set 0.04732834
# Verificar residuos de AUTOARIMA en las series diferenciadas
checkresiduals(auto_arima_FDI)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(0,0,0)(0,0,1)[4] with non-zero mean
## Q* = 2.7035, df = 7, p-value = 0.911
## 
## Model df: 1.   Total lags used: 8
checkresiduals(auto_arima_model1)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(0,1,0)
## Q* = 3.7257, df = 10, p-value = 0.9589
## 
## Model df: 0.   Total lags used: 10
checkresiduals(auto_arima_model2)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(0,1,0) with drift
## Q* = 114.69, df = 10, p-value < 2.2e-16
## 
## Model df: 0.   Total lags used: 10
checkresiduals(auto_arima_model3)

## 
##  Ljung-Box test
## 
## data:  Residuals from ARIMA(0,1,1) with drift
## Q* = 21.705, df = 9, p-value = 0.009863
## 
## Model df: 1.   Total lags used: 10

4.6 Diferenciación (Corrección de Estacionariedad)

Se realizaron AutoArimas para las variables explicativas con el fin de determinar el número de diferencias necesarias para reducir no estacionariedad. Se observó que tres modelos (log_Exchange, log_INPC y log_Exports) requieren una diferencia (d=1), mientras que el modelo para New_FDI_ts2 no sugiere diferenciación (d=0). Por lo tanto, se aplicará una diferencia solo a las tres variables que lo requieren.

# Si las variables en log siguen sin ser estacionarias, probamos diferenciarlas
diff_log_exchange <- diff(df$log_Exchange_Rate)
diff_log_inpc <- diff(df$log_INPC, lag= 4)
diff_log_exports <- diff(df$log_Exports)

# Aplicar ADF sobre las series diferenciadas en log
adf_test_diff_log_exchange <- adf.test(diff_log_exchange)
adf_test_diff_log_inpc <- adf.test(diff_log_inpc)
adf_test_diff_log_exports <- adf.test(diff_log_exports)

# Mostrar resultados después de la diferenciación
print(adf_test_diff_log_exchange)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  diff_log_exchange
## Dickey-Fuller = -3.8203, Lag order = 4, p-value = 0.02269
## alternative hypothesis: stationary
print(adf_test_diff_log_inpc)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  diff_log_inpc
## Dickey-Fuller = -2.942, Lag order = 4, p-value = 0.1922
## alternative hypothesis: stationary
print(adf_test_diff_log_exports)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  diff_log_exports
## Dickey-Fuller = -3.5467, Lag order = 4, p-value = 0.0441
## alternative hypothesis: stationary

4.6.1 Ajuste de diferenciación

  • diff_log_Exchange_Rate y diff_log_Exports ahora son estacionarias después de la diferenciación

  • diff_log_INPC sigue sin ser estacionaria (p-value = 0.3728), se realizará nuevamente la diferenciación para convertirla a estacionaria.

  • Al ejecutar el presente código, log_INPC ahora ya es estacionaria después de dos diferenciaciones (diff(diff(df$log_INPC))).

# Aplicar segunda diferenciación
diff2_log_inpc <- diff(diff(df$log_INPC))

# Prueba ADF después de la segunda diferenciación
adf_test_diff2_log_inpc <- adf.test(diff2_log_inpc)

print(adf_test_diff2_log_inpc)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  diff2_log_inpc
## Dickey-Fuller = -4.3146, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary

4.7 Estacionalidad

Los resultados del test de Kruskal-Wallis para todas las variables indicadas (FDI, tipo de cambio, INPC y exportaciones) muestran que los valores p son todos mayores que el umbral común de significancia de 0.05 (en todos los casos, los valores p son superiores a 0.4). Esto sugiere que no hay diferencias estadísticamente significativas entre los grupos o trimestres evaluados para ninguna de las variables analizadas. En otras palabras, no se puede rechazar la hipótesis nula, que establece que las distribuciones de las variables no difieren significativamente entre los trimestres.

# Crear un factor para los trimestres
trimestres_FDI <- cycle(New_FDI_ts2)
trimestres_ER <- cycle(Exchange_Rate_ts)
trimestres_INPC <- cycle(INPC_ts)
trimestres_EXPORTS <- cycle(Exports_ts)

# Aplicar la prueba de Kruskal-Wallis a cada variable
kruskal_FDI <- kruskal.test(as.numeric(New_FDI_ts2) ~ trimestres_FDI)
kruskal_ER <- kruskal.test(as.numeric(Exchange_Rate_ts) ~ trimestres_ER)
kruskal_INPC <- kruskal.test(as.numeric(INPC_ts) ~ trimestres_INPC)
kruskal_EXPORTS <- kruskal.test(as.numeric(Exports_ts) ~ trimestres_EXPORTS)

# Imprimir los resultados
print(kruskal_FDI)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  as.numeric(New_FDI_ts2) by trimestres_FDI
## Kruskal-Wallis chi-squared = 2.7563, df = 3, p-value = 0.4307
print(kruskal_ER)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  as.numeric(Exchange_Rate_ts) by trimestres_ER
## Kruskal-Wallis chi-squared = 0.015982, df = 3, p-value = 0.9995
print(kruskal_INPC)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  as.numeric(INPC_ts) by trimestres_INPC
## Kruskal-Wallis chi-squared = 0.20167, df = 3, p-value = 0.9773
print(kruskal_EXPORTS)
## 
##  Kruskal-Wallis rank sum test
## 
## data:  as.numeric(Exports_ts) by trimestres_EXPORTS
## Kruskal-Wallis chi-squared = 0.29731, df = 3, p-value = 0.9605

5 Estimación de Modelos de Series de Tiempo

Con base en la selección de la(s) variable(s) de interés, realizar la estimación de las siguientes especificaciones de modelos de series de tiempo:

5.1 ARMA

# Ajustar modelo ARMA (1,1) a New_FDI_ts2 (ya es estacionaria)
library(TSA)

arma_model_tsa <- arma(New_FDI_ts2, order = c(1, 1))
summary(arma_model_tsa)
## 
## Call:
## arma(x = New_FDI_ts2, order = c(1, 1))
## 
## Model:
## ARMA(1,1)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -88815 -19388  -5312  15950 197082 
## 
## Coefficient(s):
##             Estimate  Std. Error  t value Pr(>|t|)
## ar1           0.3867          NA       NA       NA
## ma1          -0.3261          NA       NA       NA
## intercept 31074.6008          NA       NA       NA
## 
## Fit:
## sigma^2 estimated as 1.457e+09,  Conditional Sum-of-Squares = 107818868394,  AIC = 1825.25
# Verificar residuos de ARMA
checkresiduals(arma_model_tsa)

## 
##  Ljung-Box test
## 
## data:  Residuals
## Q* = 4.522, df = 8, p-value = 0.8072
## 
## Model df: 0.   Total lags used: 8

5.1.1 Pruebas de órdenes de ARMA

En base a los valores de AIC, AICc y BIC, el modelo ARMA(2,1) es el que presenta los mejores resultados con un AIC de 1823.523, que es el más bajo entre todos los modelos probados (ARMA(1,1), ARMA(2,2), ARMA(3,3), ARMA(1,2)). Asmismo, los errores de ajuste, como el RMSE (Root Mean Squared Error), muestra un buen desempeño sin sobreajustarse a los datos.

arma_model_1_1 <- Arima(New_FDI_ts2, order = c(1, 0, 1))  # ARMA(1,1)
arma_model_2_2 <- Arima(New_FDI_ts2, order = c(2, 0, 2))  # ARMA(2,2)
arma_model_3_3 <- Arima(New_FDI_ts2, order = c(3, 0, 3))  # ARMA(3,3)
arma_model_1_2 <- Arima(New_FDI_ts2, order = c(1, 0, 2))  # ARMA(1,2)
arma_model_2_1 <- Arima(New_FDI_ts2, order = c(2, 0, 1))  # ARMA(2,1)

# Comparar los AIC de cada modelo
aic_values <- c(
  AIC(arma_model_1_1),
  AIC(arma_model_2_2),
  AIC(arma_model_3_3),
  AIC(arma_model_1_2),
  AIC(arma_model_2_1)
)

names(aic_values) <- c("ARMA(1,1)", "ARMA(2,2)", "ARMA(3,3)", "ARMA(1,2)", "ARMA(2,1)")

print(aic_values)
## ARMA(1,1) ARMA(2,2) ARMA(3,3) ARMA(1,2) ARMA(2,1) 
##  1826.189  1830.013  1832.666  1823.956  1823.523
# Elegimos el modelo con menor AIC
best_arma_model <- list(
  "ARMA(1,1)" = arma_model_1_1,
  "ARMA(2,2)" = arma_model_2_2,
  "ARMA(3,3)" = arma_model_3_3,
  "ARMA(1,2)" = arma_model_1_2,
  "ARMA(2,1)" = arma_model_2_1
)[[which.min(aic_values)]]

summary(best_arma_model)
## Series: New_FDI_ts2 
## ARIMA(2,0,1) with non-zero mean 
## 
## Coefficients:
##          ar1      ar2      ma1        mean
##       0.9918  -0.1680  -1.0000  51659.0294
## s.e.  0.1134   0.1182   0.0353    964.5405
## 
## sigma^2 = 1.384e+09:  log likelihood = -906.76
## AIC=1823.52   AICc=1824.38   BIC=1835.18
## 
## Training set error measures:
##                    ME     RMSE      MAE       MPE     MAPE      MASE
## Training set 649.4694 36207.99 24804.32 -66.93742 107.1585 0.6522063
##                     ACF1
## Training set -0.02370781
#AIC del arma seleccionado con mejor AIC (después de las combinaciones fue el más bajo)
AIC_BESTARMA<-AIC(arma_model_1_2)

5.2 ARIMA

Acorde a las pruebas realizadas, se determina que el modelo ARIMA no es el más conveniente debido a la estacionariedad de la variable dependiente. Inclusive, al realizar el AUTO ARIMA se determina que los parámetros deben ser (0,0,0) haciendo alusión a que la serie no presenta características fuertes de autorregresión o media móvil.

# Ajustar un modelo ARIMA (1,1,1) sobre New_FDI_ts2
ARIMA_model <- Arima(New_FDI_ts2, order = c(1, 1, 1))
print(ARIMA_model)
## Series: New_FDI_ts2 
## ARIMA(1,1,1) 
## 
## Coefficients:
##          ar1      ma1
##       0.0873  -1.0000
## s.e.  0.1160   0.0474
## 
## sigma^2 = 1.496e+09:  log likelihood = -899.72
## AIC=1805.44   AICc=1805.78   BIC=1812.39
plot(ARIMA_model$residuals, main = "ARIMA(1,1,1) - New_FDI_ts2", col="blue", lwd=2)

acf(ARIMA_model$residuals, main = "ACF - ARIMA(1,1,1)")

Box.test(ARIMA_model$residuals, lag = 1, type = "Ljung-Box") # Prueba de autocorrelación en residuos
## 
##  Box-Ljung test
## 
## data:  ARIMA_model$residuals
## X-squared = 0.0046048, df = 1, p-value = 0.9459
# Estacionariedad en los residuos
adf.test(ARIMA_model$residuals)
## 
##  Augmented Dickey-Fuller Test
## 
## data:  ARIMA_model$residuals
## Dickey-Fuller = -4.4423, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary

Observaciones del modelo:

  • p = 1: Incluye un término autorregresivo (AR).

  • d = 1: Diferenciación aplicada una vez para estacionariedad.

  • q = 1: Incluye un término de media móvil (MA).

  • La gráfica de ACF no presenta autocorrelación.

  • El valor p (0.9459) es > 0.05, lo que indica que el modelo ARIMA no muestra autocorrelación serial en los residuos.

  • El test ADF sugiere que los residuos del ARIMA son estacionarios, ya que el valor p (0.01) es < 0.05.

5.2.1 Pruebas de órdenes de ARIMA

Se determina que en caso de realizar ARIMA el mejor modelo es ARIMA(1,1,1), ya que tiene el menor AIC (1805.44) y un RMSE de 37910.82.

arima_model_1_1_1 <- Arima(New_FDI_ts2, order = c(1, 1, 1))  # ARIMA(1,1,1)
arima_model_2_1_1 <- Arima(New_FDI_ts2, order = c(2, 1, 1))  # ARIMA(2,1,1)
arima_model_1_1_2 <- Arima(New_FDI_ts2, order = c(1, 1, 2))  # ARIMA(1,1,2)
arima_model_2_1_2 <- Arima(New_FDI_ts2, order = c(2, 1, 2))  # ARIMA(2,1,2)
arima_model_3_1_3 <- Arima(New_FDI_ts2, order = c(3, 1, 3))  # ARIMA(3,1,3)
aic_values <- c(
  AIC(arima_model_1_1_1),
  AIC(arima_model_2_1_1),
  AIC(arima_model_1_1_2),
  AIC(arima_model_2_1_2),
  AIC(arima_model_3_1_3)
)
names(aic_values) <- c("ARIMA(1,1,1)", "ARIMA(2,1,1)", "ARIMA(1,1,2)", "ARIMA(2,1,2)", "ARIMA(3,1,3)")
print(aic_values)
## ARIMA(1,1,1) ARIMA(2,1,1) ARIMA(1,1,2) ARIMA(2,1,2) ARIMA(3,1,3) 
##     1805.441     1807.375     1807.384     1809.286     1807.449
best_arima_model <- list(
  "ARIMA(1,1,1)" = arima_model_1_1_1,
  "ARIMA(2,1,1)" = arima_model_2_1_1,
  "ARIMA(1,1,2)" = arima_model_1_1_2,
  "ARIMA(2,1,2)" = arima_model_2_1_2,
  "ARIMA(3,1,3)" = arima_model_3_1_3
)[[which.min(aic_values)]]
summary(best_arima_model)
## Series: New_FDI_ts2 
## ARIMA(1,1,1) 
## 
## Coefficients:
##          ar1      ma1
##       0.0873  -1.0000
## s.e.  0.1160   0.0474
## 
## sigma^2 = 1.496e+09:  log likelihood = -899.72
## AIC=1805.44   AICc=1805.78   BIC=1812.39
## 
## Training set error measures:
##                    ME     RMSE      MAE       MPE     MAPE      MASE       ACF1
## Training set 50.77835 37910.82 25943.19 -66.48989 106.7125 0.6821519 -0.0076328
#AIC del ARIMA seleccionado con mejor AIC (después de las combinaciones fue el más bajo)
AIC_BESTARIMA<-AIC(arima_model_1_1_1)

5.3 VAR

Se realizó un modelo VAR teniendo como variable Y New_FDI_Inflows, y usando dentro de la especificación del modelo las variables: diff_log_exchange, diff2_log_inpc y diff_log_exports.

# Construir el conjunto de datos con variables estacionarias
var_data <- cbind(
  df$New_FDI_Inflows,        # Ya es estacionaria
  diff_log_exchange,         # Primera diferencia
  diff2_log_inpc,            # Segunda diferencia
  diff_log_exports           # Primera diferencia
)

# Convertir a formato ts
var_data_ts <- ts(var_data, start = c(2006,1), frequency = 4)

Se determinó que el mejor número de lags para el modelo es 3 usando como evaluador el vlaor de AIC.

# Determinar el mejor número de lags usando AIC
lag_selection <- VARselect(var_data_ts, lag.max = 8, type = "const")
print(lag_selection$selection)
## AIC(n)  HQ(n)  SC(n) FPE(n) 
##      3      3      1      3
optimal_lag <- lag_selection$selection["AIC(n)"]
colnames(var_data_ts) <- c("New_FDI_Inflows", "diff_log_exchange", "diff2_log_inpc", "diff_log_exports")
print(colnames(var_data_ts))
## [1] "New_FDI_Inflows"   "diff_log_exchange" "diff2_log_inpc"   
## [4] "diff_log_exports"

5.3.1 Ajustar el modelo VAR con el lag óptimo

Acorde al modelo, se observa que:

  • New_FDI_Inflows no es explicada por ninguna otra variable significativa, lo que sugiere que podría ser más autónoma o influida por factores externos no capturados en este modelo.

  • El tipo de cambio (diff_log_exchange) está influenciado por las exportaciones (diff_log_exports.l1).

  • La inflación (diff2_log_inpc) es altamente autorregresiva y también influenciada por el tipo de cambio (diff_log_exchange.l3).

  • Las exportaciones (diff_log_exports) están determinadas por sus propios rezagos, la inflación (diff2_log_inpc.l2, l3) y el tipo de cambio (diff_log_exchange.l2).

var_model <- VAR(var_data_ts, p = optimal_lag, type = "const")
print(names(var_model$y))
## NULL
summary(var_model)
## 
## VAR Estimation Results:
## ========================= 
## Endogenous variables: New_FDI_Inflows, diff_log_exchange, diff2_log_inpc, diff_log_exports 
## Deterministic variables: const 
## Sample size: 71 
## Log Likelihood: -342.438 
## Roots of the characteristic polynomial:
## 0.9353 0.9353 0.8554 0.6589 0.6589 0.6359 0.6359 0.6252 0.6252 0.5894 0.5894 0.2384
## Call:
## VAR(y = var_data_ts, p = optimal_lag, type = "const")
## 
## 
## Estimation results for equation New_FDI_Inflows: 
## ================================================ 
## New_FDI_Inflows = New_FDI_Inflows.l1 + diff_log_exchange.l1 + diff2_log_inpc.l1 + diff_log_exports.l1 + New_FDI_Inflows.l2 + diff_log_exchange.l2 + diff2_log_inpc.l2 + diff_log_exports.l2 + New_FDI_Inflows.l3 + diff_log_exchange.l3 + diff2_log_inpc.l3 + diff_log_exports.l3 + const 
## 
##                        Estimate Std. Error t value Pr(>|t|)    
## New_FDI_Inflows.l1    5.583e-02  1.280e-01   0.436 0.664247    
## diff_log_exchange.l1  1.371e+05  1.293e+05   1.060 0.293482    
## diff2_log_inpc.l1     1.737e+05  5.117e+05   0.339 0.735510    
## diff_log_exports.l1  -1.749e+03  8.593e+04  -0.020 0.983836    
## New_FDI_Inflows.l2   -4.813e-03  1.251e-01  -0.038 0.969436    
## diff_log_exchange.l2 -1.272e+05  1.337e+05  -0.952 0.345214    
## diff2_log_inpc.l2     1.562e+05  4.955e+05   0.315 0.753727    
## diff_log_exports.l2   1.406e+05  8.785e+04   1.601 0.114833    
## New_FDI_Inflows.l3    5.714e-02  1.254e-01   0.456 0.650406    
## diff_log_exchange.l3 -7.357e+04  1.362e+05  -0.540 0.591173    
## diff2_log_inpc.l3     9.208e+05  5.085e+05   1.811 0.075363 .  
## diff_log_exports.l3   1.660e+05  9.235e+04   1.797 0.077513 .  
## const                 4.325e+04  1.214e+04   3.563 0.000741 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Residual standard error: 39460 on 58 degrees of freedom
## Multiple R-Squared: 0.1501,  Adjusted R-squared: -0.02573 
## F-statistic: 0.8537 on 12 and 58 DF,  p-value: 0.5966 
## 
## 
## Estimation results for equation diff_log_exchange: 
## ================================================== 
## diff_log_exchange = New_FDI_Inflows.l1 + diff_log_exchange.l1 + diff2_log_inpc.l1 + diff_log_exports.l1 + New_FDI_Inflows.l2 + diff_log_exchange.l2 + diff2_log_inpc.l2 + diff_log_exports.l2 + New_FDI_Inflows.l3 + diff_log_exchange.l3 + diff2_log_inpc.l3 + diff_log_exports.l3 + const 
## 
##                        Estimate Std. Error t value Pr(>|t|)   
## New_FDI_Inflows.l1    8.672e-08  1.425e-07   0.609   0.5451   
## diff_log_exchange.l1  2.156e-01  1.440e-01   1.497   0.1398   
## diff2_log_inpc.l1    -6.149e-01  5.697e-01  -1.079   0.2850   
## diff_log_exports.l1  -3.169e-01  9.568e-02  -3.312   0.0016 **
## New_FDI_Inflows.l2   -1.903e-07  1.393e-07  -1.367   0.1770   
## diff_log_exchange.l2 -1.857e-02  1.488e-01  -0.125   0.9012   
## diff2_log_inpc.l2     4.961e-01  5.517e-01   0.899   0.3722   
## diff_log_exports.l2  -4.115e-03  9.782e-02  -0.042   0.9666   
## New_FDI_Inflows.l3   -1.365e-07  1.397e-07  -0.977   0.3326   
## diff_log_exchange.l3  2.098e-01  1.517e-01   1.383   0.1719   
## diff2_log_inpc.l3     9.426e-01  5.662e-01   1.665   0.1013   
## diff_log_exports.l3  -6.547e-02  1.028e-01  -0.637   0.5268   
## const                 2.114e-02  1.351e-02   1.564   0.1232   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Residual standard error: 0.04394 on 58 degrees of freedom
## Multiple R-Squared: 0.2708,  Adjusted R-squared: 0.1199 
## F-statistic: 1.795 on 12 and 58 DF,  p-value: 0.07053 
## 
## 
## Estimation results for equation diff2_log_inpc: 
## =============================================== 
## diff2_log_inpc = New_FDI_Inflows.l1 + diff_log_exchange.l1 + diff2_log_inpc.l1 + diff_log_exports.l1 + New_FDI_Inflows.l2 + diff_log_exchange.l2 + diff2_log_inpc.l2 + diff_log_exports.l2 + New_FDI_Inflows.l3 + diff_log_exchange.l3 + diff2_log_inpc.l3 + diff_log_exports.l3 + const 
## 
##                        Estimate Std. Error t value Pr(>|t|)    
## New_FDI_Inflows.l1    5.455e-09  2.063e-08   0.264   0.7924    
## diff_log_exchange.l1 -2.355e-02  2.084e-02  -1.130   0.2633    
## diff2_log_inpc.l1    -8.234e-01  8.247e-02  -9.984 3.29e-14 ***
## diff_log_exports.l1   2.396e-02  1.385e-02   1.730   0.0889 .  
## New_FDI_Inflows.l2   -1.719e-08  2.016e-08  -0.853   0.3974    
## diff_log_exchange.l2 -2.833e-02  2.154e-02  -1.315   0.1936    
## diff2_log_inpc.l2    -9.200e-01  7.986e-02 -11.521  < 2e-16 ***
## diff_log_exports.l2   7.097e-03  1.416e-02   0.501   0.6181    
## New_FDI_Inflows.l3   -2.658e-08  2.022e-08  -1.315   0.1938    
## diff_log_exchange.l3  5.742e-02  2.195e-02   2.616   0.0113 *  
## diff2_log_inpc.l3    -7.244e-01  8.196e-02  -8.838 2.45e-12 ***
## diff_log_exports.l3   4.821e-03  1.489e-02   0.324   0.7472    
## const                 1.865e-03  1.956e-03   0.953   0.3443    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Residual standard error: 0.00636 on 58 degrees of freedom
## Multiple R-Squared: 0.7877,  Adjusted R-squared: 0.7437 
## F-statistic: 17.93 on 12 and 58 DF,  p-value: 2.689e-15 
## 
## 
## Estimation results for equation diff_log_exports: 
## ================================================= 
## diff_log_exports = New_FDI_Inflows.l1 + diff_log_exchange.l1 + diff2_log_inpc.l1 + diff_log_exports.l1 + New_FDI_Inflows.l2 + diff_log_exchange.l2 + diff2_log_inpc.l2 + diff_log_exports.l2 + New_FDI_Inflows.l3 + diff_log_exchange.l3 + diff2_log_inpc.l3 + diff_log_exports.l3 + const 
## 
##                        Estimate Std. Error t value Pr(>|t|)   
## New_FDI_Inflows.l1    9.263e-08  2.099e-07   0.441  0.66057   
## diff_log_exchange.l1  1.625e-01  2.121e-01   0.766  0.44661   
## diff2_log_inpc.l1     5.401e-01  8.391e-01   0.644  0.52232   
## diff_log_exports.l1  -3.980e-01  1.409e-01  -2.824  0.00649 **
## New_FDI_Inflows.l2   -1.713e-07  2.051e-07  -0.835  0.40696   
## diff_log_exchange.l2  4.563e-01  2.192e-01   2.082  0.04180 * 
## diff2_log_inpc.l2     1.862e+00  8.125e-01   2.291  0.02559 * 
## diff_log_exports.l2  -2.963e-01  1.441e-01  -2.056  0.04425 * 
## New_FDI_Inflows.l3   -1.579e-07  2.057e-07  -0.768  0.44585   
## diff_log_exchange.l3  4.040e-01  2.233e-01   1.809  0.07569 . 
## diff2_log_inpc.l3     2.386e+00  8.339e-01   2.862  0.00585 **
## diff_log_exports.l3  -2.051e-01  1.514e-01  -1.354  0.18090   
## const                 2.538e-02  1.990e-02   1.275  0.20738   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## 
## Residual standard error: 0.06471 on 58 degrees of freedom
## Multiple R-Squared: 0.3549,  Adjusted R-squared: 0.2215 
## F-statistic: 2.659 on 12 and 58 DF,  p-value: 0.006545 
## 
## 
## 
## Covariance matrix of residuals:
##                   New_FDI_Inflows diff_log_exchange diff2_log_inpc
## New_FDI_Inflows         1.557e+09        -3.455e+01     -2.234e+00
## diff_log_exchange      -3.455e+01         1.931e-03      3.668e-05
## diff2_log_inpc         -2.234e+00         3.668e-05      4.045e-05
## diff_log_exports       -7.550e+00         1.206e-03     -4.392e-06
##                   diff_log_exports
## New_FDI_Inflows         -7.550e+00
## diff_log_exchange        1.206e-03
## diff2_log_inpc          -4.392e-06
## diff_log_exports         4.187e-03
## 
## Correlation matrix of residuals:
##                   New_FDI_Inflows diff_log_exchange diff2_log_inpc
## New_FDI_Inflows          1.000000          -0.01993      -0.008903
## diff_log_exchange       -0.019925           1.00000       0.131262
## diff2_log_inpc          -0.008903           0.13126       1.000000
## diff_log_exports        -0.002957           0.42408      -0.010673
##                   diff_log_exports
## New_FDI_Inflows          -0.002957
## diff_log_exchange         0.424081
## diff2_log_inpc           -0.010673
## diff_log_exports          1.000000

5.3.2 Prueba de autocorrelación en residuos (Ljung-Box)

La prueba de autocorrelación en residuos (Ljung-Box) mostró que solo la variable diff2_log_inpc muestra autocorrelaicón serial de los residuales, las demás variables tienen un p-value > 0.05 indicando que no tienen autocorrelación serial de residuales.

residuals_var <- residuals(var_model)
apply(residuals_var, 2, function(x) Box.test(x, lag = 10, type = "Ljung-Box"))
## $New_FDI_Inflows
## 
##  Box-Ljung test
## 
## data:  x
## X-squared = 7.2404, df = 10, p-value = 0.7026
## 
## 
## $diff_log_exchange
## 
##  Box-Ljung test
## 
## data:  x
## X-squared = 9.145, df = 10, p-value = 0.5184
## 
## 
## $diff2_log_inpc
## 
##  Box-Ljung test
## 
## data:  x
## X-squared = 29.758, df = 10, p-value = 0.0009384
## 
## 
## $diff_log_exports
## 
##  Box-Ljung test
## 
## data:  x
## X-squared = 5.193, df = 10, p-value = 0.8779
AIC_BESTVAR <- AIC(var_model)

5.3.3 Prueba de Causalidad de Granger

Los factores macroeconómicos (tipo de cambio, INPC, exportaciones) afectan la IED, pero la IED no influye en el comportamiento futuro de estas variables. En el modelo VAR, el test de Granger muestra que New_FDI_Inflows no tiene un efecto predictivo sobre diff_log_exchange, diff2_log_inpc, y diff_log_exports (p = 0.7847). Sin embargo, diff_log_exchange (p = 0.0079), diff2_log_inpc (p = 0.0184) y diff_log_exports (p = 0.0118) sí presentan evidencia de Granger-causalidad sobre otras variables, lo que sugiere que estos factores macroeconómicos tienen un impacto predictivo sobre el comportamiento de la inversión extranjera directa y otras variables en el modelo.

El valor p de la prueba F global del modelo (0.5966) indica que New_FDI_Inflows (flujos de IED) no muestra una causalidad para las variables explicativas seleccionadas (Exchange Rate, INPC y Exports). La prueba de Ljung-Box muestra la independencia de errores en la mayoría de las variables, excepto en diff2_log_inpc. Esta variable muestra autocorrelación significativa. Las variables INPC y Exports muestran una posible relación con New_FDI_Inflows en el tercer rezago, aunque la evidencia estadística no es lo suficientemente fuerte como para ser concluyente.

granger_fdi <- causality(var_model, cause = "New_FDI_Inflows")
print(granger_fdi)
## $Granger
## 
##  Granger causality H0: New_FDI_Inflows do not Granger-cause
##  diff_log_exchange diff2_log_inpc diff_log_exports
## 
## data:  VAR object var_model
## F-Test = 0.61391, df1 = 9, df2 = 232, p-value = 0.7847
## 
## 
## $Instant
## 
##  H0: No instantaneous causality between: New_FDI_Inflows and
##  diff_log_exchange diff2_log_inpc diff_log_exports
## 
## data:  VAR object var_model
## Chi-squared = 0.033266, df = 3, p-value = 0.9984
granger_exchange <- causality(var_model, cause = "diff_log_exchange")
print(granger_exchange)
## $Granger
## 
##  Granger causality H0: diff_log_exchange do not Granger-cause
##  New_FDI_Inflows diff2_log_inpc diff_log_exports
## 
## data:  VAR object var_model
## F-Test = 2.5626, df1 = 9, df2 = 232, p-value = 0.007932
## 
## 
## $Instant
## 
##  H0: No instantaneous causality between: diff_log_exchange and
##  New_FDI_Inflows diff2_log_inpc diff_log_exports
## 
## data:  VAR object var_model
## Chi-squared = 11.764, df = 3, p-value = 0.008238
granger_inpc <- causality(var_model, cause = "diff2_log_inpc")
print(granger_inpc)
## $Granger
## 
##  Granger causality H0: diff2_log_inpc do not Granger-cause
##  New_FDI_Inflows diff_log_exchange diff_log_exports
## 
## data:  VAR object var_model
## F-Test = 2.2759, df1 = 9, df2 = 232, p-value = 0.0184
## 
## 
## $Instant
## 
##  H0: No instantaneous causality between: diff2_log_inpc and
##  New_FDI_Inflows diff_log_exchange diff_log_exports
## 
## data:  VAR object var_model
## Chi-squared = 1.5712, df = 3, p-value = 0.6659
granger_exports <- causality(var_model, cause = "diff_log_exports")
print(granger_exports)
## $Granger
## 
##  Granger causality H0: diff_log_exports do not Granger-cause
##  New_FDI_Inflows diff_log_exchange diff2_log_inpc
## 
## data:  VAR object var_model
## F-Test = 2.4283, df1 = 9, df2 = 232, p-value = 0.0118
## 
## 
## $Instant
## 
##  H0: No instantaneous causality between: diff_log_exports and
##  New_FDI_Inflows diff_log_exchange diff2_log_inpc
## 
## data:  VAR object var_model
## Chi-squared = 11.051, df = 3, p-value = 0.01145

5.4 Panel VAR

5.4.1 Fixed Effects OLS Panel VAR estimation con Variables Originales

El modelo de Panel VAR con efectos fijos muestra las siguientes relaciones clave:

  • New FDI Inflows: El rezago de New FDI Inflows tiene un efecto negativo y significativo en su propia variable, con un coeficiente de -0.6730 (p < 0.001). Esto sugiere que un aumento en los flujos de FDI en el trimestre anterior está asociado con una disminución en los flujos actuales de FDI.

  • Exports: El rezago de Exports tiene un efecto negativo y significativo en los flujos de exportación actuales (-0.4937, p < 0.05), lo que indica que un aumento en las exportaciones del trimestre anterior puede reducir las exportaciones actuales.

Los coeficientes de INPC y Exchange Rate no son significativos en este análisis, lo que sugiere que estas variables no tienen un impacto directo importante en los flujos de FDI o exportaciones cuando se controlan por los rezagos.

library(panelvar)
df_orig <- df %>% dplyr::select(Year, Quarter, New_FDI_Inflows, Exchange_Rate, INPC, Exports)

PanelVAR_FE <- pvarfeols(dependent_vars=c("New_FDI_Inflows", "Exports"),lags=1, exog_vars=c("INPC", "Exchange_Rate"), transformation="demean", data=df_orig, panel_identifier= c("Year", "Quarter"))
summary(PanelVAR_FE)

Fixed Effects OLS Panel VAR estimation

Transformation: demean
Group variable: Year
Time variable: Quarter
Number of observations = 74
Number of groups = 19
Obs per group: min = 2
Obs per group: avg = 3.89473684210526
Obs per group: max = 4

  demeaned_New_FDI_Inflows demeaned_Exports
demeaned_lag1_New_FDI_Inflows -0.6730*** -0.1170
  (0.1380) (0.0956)
demeaned_lag1_Exports 0.3006 -0.4937*
  (0.3162) (0.2192)
demeaned_INPC 984.2650 -4965.0945
  (7786.2948) (5396.5243)
demeaned_Exchange_Rate 26543.0224 -55703.1905
  (56749.2533) (39331.7657)
***p < 0.001; **p < 0.01; *p < 0.05

5.4.2 Fixed Effects OLS Panel VAR estimation con Logaritmos

El modelo de Panel VAR con variables explciativas transformadas a logartimo con efectos fijos muestra lo siguiente:

  • New FDI Inflows: El rezago de New FDI Inflows tiene un efecto negativo y significativo en su propia variable con un coeficiente de -0.6633 (p < 0.001), lo que indica que un aumento en los flujos de FDI del trimestre anterior se asocia con una caída en los flujos actuales de FDI.

  • Exports: El rezago de log_Exports tiene un efecto negativo y significativo en los flujos de exportaciones actuales con un coeficiente de -0.4671 (p < 0.05). Esto sugiere que un aumento en las exportaciones del trimestre anterior reduce las exportaciones actuales.

Las variables Exchange Rate y INPC no tienen efectos significativos en los flujos de FDI ni en las exportaciones en este modelo, ya que sus coeficientes no son estadísticamente significativos.

df_log <- df %>% dplyr::select(Year, Quarter, New_FDI_Inflows, log_Exchange_Rate, log_INPC, log_Exports)

# Estimar modelo Panel VAR con efectos fijos
PanelVAR_FE_log <- pvarfeols(
  dependent_vars = c("New_FDI_Inflows", "log_Exports"),
  lags = 1,
  exog_vars = c("log_Exchange_Rate", "log_INPC"),
  transformation = "demean",
  data = df_log,
  panel_identifier = c("Year", "Quarter")
)

summary(PanelVAR_FE_log)

Fixed Effects OLS Panel VAR estimation

Transformation: demean
Group variable: Year
Time variable: Quarter
Number of observations = 74
Number of groups = 19
Obs per group: min = 2
Obs per group: avg = 3.89473684210526
Obs per group: max = 4

  demeaned_New_FDI_Inflows demeaned_log_Exports
demeaned_lag1_New_FDI_Inflows -0.6633*** -0.0000
  (0.1354) (0.0000)
demeaned_lag1_log_Exports 260845.9769 -0.4671*
  (173954.0614) (0.2136)
demeaned_log_Exchange_Rate 656650.2032 -1.8477
  (853875.8593) (1.0482)
demeaned_log_INPC 203569.1207 -1.0571
  (621143.2731) (0.7625)
***p < 0.001; **p < 0.01; *p < 0.05

5.4.3 Estimar modelo Panel VAR con GMM

El modelo presenta errores estándar altos y los p-values de Hansen indican que los instrumentos pueden no ser válidos; además se observa que ninguna variable parece tener un impacto estadístico confiable: * lag1_New_FDI_Inflows: -0.2577 (con error estándar 0.2045) → Indica una leve autocorrelación negativa, pero no es estadísticamente significativo.

  • log_Exchange_Rate, log_Exports, log_INPC: Todos con coeficiente ≈ 0 y errores estándar extremadamente grandes lo que indica problemas numéricos serios.

  • Hansen Test: Indica sobreidentificación extrema y problemas con los instrumentos.

PANELVAR_FE_GMM <- pvargmm(
  dependent_vars = c("New_FDI_Inflows"),
  lags=1, 
  predet_vars=c("log_Exchange_Rate", "log_Exports"), 
  exog_vars=c("log_INPC"), 
  transformation="fd", 
  data=df_log , 
  panel_identifier=c("Year", "Quarter"), 
  steps=c("onestep")
)
summary(PANELVAR_FE_GMM)

Dynamic Panel VAR estimation, one-step GMM

Transformation: First-differences
Group variable: Year
Time variable: Quarter
Number of observations = 36
Number of groups = 18
Obs per group: min = 2
Obs per group: avg = 2
Obs per group: max = 2
Number of instruments = 14

  New_FDI_Inflows
lag1_New_FDI_Inflows -0.2577
  (0.2045)
log_Exchange_Rate 0.0000
  (655946.7015)
log_Exports 0.0000
  (124686.3002)
log_INPC 0.0000
  (407222.0440)
***p < 0.001; **p < 0.01; *p < 0.05

Instruments for equation

Standard
log_INPC

GMM-type
Dependent vars: L(2,2)
Predet vars: L(1, 2)
Collapse = FALSE

Hansen test of overid. restrictions: chi2(10) = 12073350630.66 Prob > chi2 = 0
(Robust, but weakened by many instruments.)

5.4.4 Prueba de Chow

En este caso, el p-valor (0.2966) es mayor que 0.05, por lo que NO se rechaza la hipótesis nula. Esto indica que no hay evidencia de un cambio estructural significativo en la relación entre New_FDI_Inflows y las variables explicativas (log_Exchange_Rate, log_INPC, log_Exports).

chow_test <- sctest(New_FDI_Inflows ~ log_Exchange_Rate + log_INPC + log_Exports, 
                    type = "Chow", point = 18, data = df)
print(chow_test)
## 
##  Chow test
## 
## data:  New_FDI_Inflows ~ log_Exchange_Rate + log_INPC + log_Exports
## F = 1.255, p-value = 0.2966

5.4.5 Calculo manual de AIC para modelos Panel VAR

# Extraer residuales
residuals_df <- as.data.frame(residuals(PanelVAR_FE))

# Calcular SSE
SSE <- sum(residuals_df^2, na.rm = TRUE)

# Número de observaciones y parámetros estimados
n <- nrow(df_orig)
k <- length(coef(PanelVAR_FE))  # Número de coeficientes estimados

# Calcular AIC manualmente
AIC_PanelVAR_FE <- n * log(SSE / n) + 2 * k
# Extraer residuales
residuals_df2 <- as.data.frame(residuals(PanelVAR_FE_log))

# Calcular SSE
SSE2 <- sum(residuals_df2^2, na.rm = TRUE)

# Número de observaciones y parámetros estimados
n2 <- nrow(df_log)
k2 <- length(coef(PanelVAR_FE_log))  # Número de coeficientes estimados

# Calcular AIC manualmente
AIC_PanelVAR_FE_log <- n2 * log(SSE2 / n2) + 2 * k2

6 Pruebas de Diagnóstico

Mediante pruebas de diagnóstico, identificar la posible presencia de las siguientes características de la serie:

6.1 Autocorrelación Serial (serial correlation)

Todos los modelos tienen p-values > 0.05, lo que significa que no hay evidencia de autocorrelación serial en los residuos.

test_autocorrelacion <- function(modelo) {
  residuos <- residuals(modelo)
    if (is.matrix(residuos)) {
    p_values <- apply(residuos, 2, function(x) Box.test(x, lag = 10, type = "Ljung-Box")$p.value)
  } else {
    p_values <- Box.test(residuos, lag = 10, type = "Ljung-Box")$p.value
  }
  
  return(p_values)
}

# Aplicar la prueba de autocorrelación a cada modelo
autocorr_results <- data.frame(
  Modelo = c("ARMA", "ARIMA", "VAR", "PanelVAR_FE_log", "PanelVAR_FE"),
  Autocorr_p_value = c(
    test_autocorrelacion(arma_model_1_2),
    test_autocorrelacion(arima_model_1_1_1),
    mean(test_autocorrelacion(var_model)),  # Promedio de p-values en VAR
    mean(test_autocorrelacion(PanelVAR_FE_log)),  # Promedio de p-values en PanelVAR_FE_log
    mean(test_autocorrelacion(PanelVAR_FE))  # Promedio de p-values en PanelVAR_FE
  )
)

print(autocorr_results)
##            Modelo Autocorr_p_value
## 1            ARMA        0.8153617
## 2           ARIMA        0.8987572
## 3             VAR        0.5249556
## 4 PanelVAR_FE_log        0.8486554
## 5     PanelVAR_FE        0.8530676

6.2 Estacionariedad (stationary)

Se busca que los modelos tengan residuos estacionarios porque esto indica que el modelo captura de forma eficiente la dinámica de la serie de tiempo.

  • Modelos con residuos estacionarios (p ≤ 0.05): ARMA (0.0167), ARIMA (0.0100), VAR (0.0159).
  • Modelos con residuos no estacionarios (p > 0.05): PanelVAR_FE_log (0.0749) y PanelVAR_FE (0.1439).
test_estacionariedad <- function(modelo) {
  residuos <- residuals(modelo)
    if (is.matrix(residuos)) {
    p_values <- apply(residuos, 2, function(x) adf.test(as.numeric(x))$p.value)
  } else {
    p_values <- adf.test(as.numeric(residuos))$p.value
  }
  
  return(p_values)
}

# Aplicar la prueba de estacionariedad a cada modelo
stationarity_results <- data.frame(
  Modelo = c("ARMA", "ARIMA", "VAR", "PanelVAR_FE_log", "PanelVAR_FE"),
  Stationarity_p_value = c(
    test_estacionariedad(arma_model_1_2),
    test_estacionariedad(arima_model_1_1_1),
    mean(test_estacionariedad(var_model)),  # Promedio de p-values en VAR
    mean(test_estacionariedad(PanelVAR_FE_log)),  # Promedio de p-values en PanelVAR_FE_log
    mean(test_estacionariedad(PanelVAR_FE))  # Promedio de p-values en PanelVAR_FE
  )
)

print(stationarity_results)
##            Modelo Stationarity_p_value
## 1            ARMA           0.01676033
## 2           ARIMA           0.01000000
## 3             VAR           0.01587479
## 4 PanelVAR_FE_log           0.07492563
## 5     PanelVAR_FE           0.14394902

7 Selección de Modelo e Interpretación de Resultados:

Con base en las pruebas de diagnóstico, y la estimación de los resultados, se seleccionan los resultados de la estimación del modelo de series de tiempo que muestra el mejor desempeño.

El mejor modelo es el que no tiene autocorrelación serial en los residuos, tenga residuos estacionarios y tenga el menor AIC, por lo que, el modelo que mejor cumplió con estas condiciones es el modelo VAR.

Primeramente, se observan los AIC de todos los modelos generados

df_AIC <- data.frame(
  Modelo = c("ARMA", "ARIMA", "VAR", "PanelVAR_FE_log", "PanelVAR_FE"),
  AIC_Valor = c(AIC_BESTARMA, AIC_BESTARIMA, AIC_BESTVAR, AIC_PanelVAR_FE_log, AIC_PanelVAR_FE)
)

print(df_AIC)
##            Modelo AIC_Valor
## 1            ARMA 1823.9565
## 2           ARIMA 1805.4410
## 3             VAR  788.8765
## 4 PanelVAR_FE_log 1471.0029
## 5     PanelVAR_FE 1502.8900

Posteriormente, se observan los AIC los modelos óptimos acorde al análisis exploratorio realizado, ante lo cual sigue preodminando el modelo VAR por tener el menor AIC y RMSE.

library(Metrics)

# Lista de modelos
modelos <- list(
  "ARMA(1,1)" = arma_model_1_1,
  "ARMA(2,2)" = arma_model_2_2,
  "ARMA(3,3)" = arma_model_3_3,
  "ARMA(1,2)" = arma_model_1_2,
  "ARMA(2,1)" = arma_model_2_1
)

# Función para calcular RMSE
get_rmse <- function(model, datos_reales) {
  preds <- fitted(model)  
  return(rmse(datos_reales, preds))
}

# Calcular AIC y RMSE
resultados <- data.frame(
  AIC = sapply(modelos, AIC),
  RMSE = sapply(modelos, get_rmse, datos_reales = New_FDI_ts2)
)

# Modelo VAR
AIC_BESTVAR <- AIC(var_model)
fitted_vals <- as.data.frame(fitted(var_model))
in_sample_pred <- fitted_vals$New_FDI_Inflows
df_aligned <- df[-c(1:3), ]
var_rmse <- rmse(df_aligned$New_FDI_Inflows, in_sample_pred)

# Fila del Modelo VAR
var_row <- data.frame(
  AIC = AIC_BESTVAR,
  RMSE = var_rmse,
  row.names = "VAR_Model"
)

# Resultados
resultados <- rbind(resultados, var_row)
resultados <- resultados %>%
  arrange(AIC, RMSE)
head(resultados, 3)
##                 AIC     RMSE
## VAR_Model  788.8765 35666.29
## ARMA(2,1) 1823.5234 36207.99
## ARMA(1,2) 1823.9565 36343.22

7.1 Realizar el pronóstico de las variables de interés relacionadas con el Nearshoring en México para los próximos 4 períodos, incluyendo un gráfico de series de tiempo y una descripción de la tendencia proyectada.

Se decidió realizar el pronóstico para 8 periodos es decir para 2 años, ya que consideramos que un análisis de 8 trimestres podría permitir a las empresas interesadas, evaluar tendencias a mediano plazo y así evitar que se tomen decisiones basadas solo en variaciones a corto plazo, asímismo con los resultados del modelo, identificamos que la predicción a corto plazo parece ser más volátil, por lo que se tomo como punto de referencia, a poder analizar otros periodos a mediano plazo.

Se calculó el promedio de New_FDI_Inflows, y comparando los intervalos resultantes de cada periodo del modelo, el modelo VAR parece capturar bien el promedio general, aunque muestra ciertas fluctuaciones en los primeros 3 periodos, sin embargo, a partir del 4to periodo , los valores se acercan mucho a la media, por lo que, el modelo podría estar adaptándose más hacia un valor más estable de la media de la serie original, a partir de analizar más periodos, es decir, que después de 3 trimestres, se lograría obtener estabilidad.

media_newfdi<- mean(df$New_FDI_Inflows)
media_newfdi
## [1] 50554.58
# Pronóstico para 8 periodos
forecast_var <- predict(var_model, n.ahead = 8, ci = 0.95)
fanchart(forecast_var, names = "New_FDI_Inflows", main = "Forecast - New_FDI_Inflows", xlab = "Time", ylab = "New_FDI_Inflows")

print(forecast_var$fcst$New_FDI_Inflows)
##          fcst      lower    upper       CI
## [1,] 39042.01 -38301.026 116385.1 77343.04
## [2,] 69004.75  -9398.352 147407.8 78403.10
## [3,] 62590.19 -16748.218 141928.6 79338.40
## [4,] 50544.04 -31769.358 132857.4 82313.40
## [5,] 58559.70 -24087.430 141206.8 82647.13
## [6,] 56574.18 -26521.152 139669.5 83095.34
## [7,] 49382.97 -34177.743 132943.7 83560.71
## [8,] 51695.75 -32008.606 135400.1 83704.36

7.2 De acuerdo al pronóstico anterior, ¿cómo es el escenario optimista vs. escenario pesimista del posible “Nearshoring” para el caso de México?

Aunque existe incertidumbre, la tendencia general favorece el crecimiento de la IED en México, con riesgos asociados a la volatilidad económica y política.

  • Escenario optimista: La IED crecería significativamente, superando las 135,000 unidades, impulsada por condiciones favorables en inversión extranjera y estabilidad macroeconómica.

  • Escenario realista: Se espera que la IED fluctúe entre 39,042 y 69,004 unidades, con la mayoría de los valores superando la media histórica, lo que indicaría un crecimiento sostenido, aunque con cierta incertidumbre.

  • Escenario pesimista: La IED podría caer hasta -38,301 unidades, lo que reflejaría un retroceso preocupante debido a posibles factores adversos en la economía y el entorno político.

# Crear un data frame con los escenarios
escenarios_df <- data.frame(
  Periodo = 1:8,
  Escenario_Pesimista = forecast_var$fcst$New_FDI_Inflows[, "lower"],  # Límite inferior
  Escenario_Real = forecast_var$fcst$New_FDI_Inflows[, "fcst"],        # Predicción central
  Escenario_Optimo = forecast_var$fcst$New_FDI_Inflows[, "upper"]       # Límite superior
)

# Imprimir los escenarios
print(escenarios_df)
##   Periodo Escenario_Pesimista Escenario_Real Escenario_Optimo
## 1       1          -38301.026       39042.01         116385.1
## 2       2           -9398.352       69004.75         147407.8
## 3       3          -16748.218       62590.19         141928.6
## 4       4          -31769.358       50544.04         132857.4
## 5       5          -24087.430       58559.70         141206.8
## 6       6          -26521.152       56574.18         139669.5
## 7       7          -34177.743       49382.97         132943.7
## 8       8          -32008.606       51695.75         135400.1
# Graficar los escenarios
library(ggplot2)
ggplot(escenarios_df, aes(x = Periodo)) +
  geom_line(aes(y = Escenario_Pesimista, color = "Pesimista"), size = 1, linetype = "dashed") +
  geom_line(aes(y = Escenario_Real, color = "Real"), size = 1) +
  geom_line(aes(y = Escenario_Optimo, color = "Óptimo"), size = 1, linetype = "dashed") +
  labs(title = "Escenarios de New_FDI_Inflows",
       x = "Periodo", y = "New_FDI_Inflows") +
  scale_color_manual(values = c("Pesimista" = "red", "Real" = "blue", "Óptimo" = "green")) +
  theme_minimal()

7.3 El desempeño del flujo de nuevos flujos de IED exhiben la presencia de un cambio estructural durante el período de análisis?

El M-fluctuation test (CUSUM) evalúa si los coeficientes del modelo VAR se mantienen estables a lo largo del tiempo. En este caso, el p-valor es 0.3872 (mayor a 0.05), por lo que no hay evidencia de cambio estructural. Por lo tanto, la prueba de fluctuación (CUSUM) no encuentra cambios estructurales conforme al tiempo, lo cual coincide con el valor de la Prueba Chow la cual determina que no se detecta un cambio estructural en la regresión.

library(strucchange)

roots(var_model)  # Las raíces deben estar dentro del círculo unitario
##  [1] 0.9353466 0.9353466 0.8554082 0.6589002 0.6589002 0.6359199 0.6359199
##  [8] 0.6251523 0.6251523 0.5894189 0.5894189 0.2383855
cusum_test <- sctest(var_model, type = "OLS-CUSUM")
print(cusum_test)
## 
##  M-fluctuation test
## 
## data:  var_model
## f(efp) = 1.6376, p-value = 0.3872

8 Conclusiones

Los modelos de series de tiempo aplicados en este análisis han permitido examinar el comportamiento de los flujos de IED en México y su posible relación con factores macroeconómicos. El modelo VAR mostró ser el mejor en términos de desempeño, al no presentar autocorrelación en los residuos y tener un menor AIC en comparación con otros modelos.

En términos de causalidad, los resultados sugieren que las variables macroeconómicas seleccionadas (tipo de cambio, INPC y exportaciones) no tienen una relación causal fuerte con los flujos de IED en el corto plazo. Sin embargo, se observa que INPC y Exports podrían tener un impacto en la variable dependiente en el tercer rezago, aunque la evidencia estadística no es concluyente.

  • Sobre si sucederá o no el nearshoring:

    • Con base en el análisis de series de tiempo y el pronóstico de nueva inversión extranjera directa, concluimos que en los próximos dos años el nearshoring no ocurrirá de manera significativa ni mostrará un aumento drástico en los flujos de inversión.

    • Solo en 2 de los 8 trimestres proyectados, la Nueva IED se mantiene por encima del umbral de 60,666 unidades (media histórica de New_FDI_Inflows + 20%).

    • La tendencia general indica que la IED se mantendrá en niveles estables, con ligeros picos de aumento, pero sin una consolidación clara del nearshoring en el corto plazo.

    • Es posible que en un futuro posterior a los próximos dos años New_FDI_Inflows experimente un mayor aumento, pero bajo este umbral, no se espera que el nearshoring ocurra significativamente en los próximos dos años.

  • Sobre el nearshoring en los próximos años: Se realizó el pronóstico para los próximos dos años. Los escenarios muestran incertidumbre, pero con una tendencia que favorece el crecimiento de la IED en el país.

    • En un escenario óptimo, la IED podría alcanzar valores superiores a 135,000 unidades.

    • En un escenario realista, los valores proyectados oscilan entre 39,042 y 69,004 unidades, con la mayoría de los trimestres por encima de la media histórica.

    • En un escenario pesimista, la IED podría caer hasta -38,301 unidades, lo que indicaría un retroceso en la inversión si las condiciones macroeconómicas y políticas son desfavorables.

9 Referencias

LS0tDQp0aXRsZTogIkFjdGl2aWRhZCAzIOKAkyBFc3RpbWFjacOzbiBkZSBNb2RlbG9zIGRlIERhdG9zIGRlIFNlcmllcyBkZSBUaWVtcG8iDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiBUUlVFDQogICAgdGhlbWU6IHVuaXRlZA0KICAgIHRvY19kZXB0aDogNg0KICAgIG51bWJlcl9zZWN0aW9uczogVFJVRQ0KICAgIHRvY19mbG9hdDoNCiAgICAgIHNtb290aF9zY3JvbGw6IFRSVUUNCiAgICAgIGNvbGxhcHNlZDogRkFMU0UNCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQohW10oaHR0cHM6Ly9taXJvLm1lZGl1bS5jb20vdjIvcmVzaXplOmZpdDoxNDAwLzEqeVd3bHJHb3F0bjQ2dUstSUViWF9ZUS5naWYpDQoNCg0KKipFcXVpcG8gIzYqKjoNCg0KKiBBMDEzNjg1MTYgLSBOYXllbGkgUGXDsWEgTWFydMOtbmV6DQoqIEEwMDgzMzExMyAtIEF2cmlsIExvYmF0bw0KKiBBMDE3NzExMjcgLSBMZXNseSBEYXJpYW4gUm9tZXJvIFZhenF1ZXoNCiogQTAwODMxMTA1IC0gSmF6bWluIGRlbCBDYXJtZW4gQ29ydGV6IE1lbmRvemENCiogQTAxMTk4MTg0IC0gS2FybGEgU8OhbmNoZXogZGVsIMOBbmdlbA0KKiBBMDExOTgxODYgLSBMdWlzIEFuZ2VsIEVsaXpvbmRvIEdhbGxlZ29zDQoNCi0tLQ0KDQpgYGB7cn0NCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCgllY2hvID0gVFJVRSwNCgltZXNzYWdlID0gRkFMU0UsDQoJd2FybmluZyA9IEZBTFNFDQopDQojaW5zdGFsbC5wYWNrYWdlcygicm5hdHVyYWxlYXJ0aGhpcmVzIiwgcmVwb3MgPSAiaHR0cHM6Ly9wYWNrYWdlcy5yb3BlbnNjaS5vcmciKQ0KI2luc3RhbGwucGFja2FnZXMoImRldnRvb2xzIikNCnBhY21hbjo6cF9sb2FkKGRwbHlyLCBnZ3Bsb3QyLCBuYW5pYXIsIHRzZXJpZXMsIGNvcnJwbG90LCBwYXRjaHdvcmssIHJlYWR4bCwgcHN5Y2gsIG1hcHMsIHNmLCBybmF0dXJhbGVhcnRoLCBybmF0dXJhbGVhcnRoZGF0YSwgc3RyaW5naSwgc2NhbGVzLCBkbG9va3IsIERhdGFFeHBsb3JlciwgdGlkeXIsIGtuaXRyLCBSQ29sb3JCcmV3ZXIsIHBsb3RseSwgZm9yZWNhc3QsIHRzZXJpZXMsIG9wZW54bHN4LCB2YXJzLCBsbXRlc3QpDQoNCmBgYA0KDQojIEludHJvZHVjY2nDs24gDQoNCiMjIERlc2NyaWJpciBsYXMgcHJpbmNpcGFsZXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSB1bmEgYmFzZSBkZSBkYXRvcyBkZSBzZXJpZXMgZGUgdGllbXBvLiANCg0KTGFzIGJhc2VzIGRlIGRhdG9zIGRlIHNlcmllcyB0ZW1wb3JhbGVzIGNvbnRpZW5lbiBkYXRvcyBpbmRleGFkb3MgZW4gZWwgdGllbXBvLiBQZXJtaXRlbiBhbG1hY2VuYXIgeSByZWFsaXphciBhbsOhbGlzaXMgZGUgZ3JhbmRlcyBjYW50aWRhZGVzIGRlIGRhdG9zIHF1ZSBzZSB1YmljYW4gZW4gaW50ZXJ2YWxvcyBkZSB0aWVtcG8geSB0aWVuZW4gdW5hIGVzdHJ1Y3R1cmEgcmVndWxhci4gTG9zIGFuw6FsaXNpcyBkZSBzZXJpZXMgZGUgdGllbXBvIGJ1c2NhbiBlbmZvY2Fyc2UgZW4gZWwgYW7DoWxpc2lzIGRlIHVuYSBwcmluY2lwYWwgdmFyaWFibGUgcGFyYSBlc3R1ZGlhciBzdSBwYXNhZG8geSBwb2RlciBwcmVkZWNpciBzdSBmdXR1cm8uIExhcyBCRCBzZSBzZXJpZXMgZGUgdGllbXBvIHRpZW5lbiA0IGNvbXBvbmVudGVzIHByaW5jaXBhbGVzOiB0ZW5kZW5jaWEgKHBhdHLDs24gZGUgbGEgZXZvbHVjacOzbiBkZSBsb3MgZGF0b3MpLCBlc3RhY2lvbmFsaWRhZCAodmFyaWFjacOzbiBkZSBsb3MgZGF0b3MgZW4gY2llcnRhcyBlc3RhY2lvbmVzKSwgY2ljbGljaWRhZCAocGF0cm9uZXMgZGUgbcOhcyBkZSB1biBhw7FvKSwgYWxlYXRvcmllZGFkIG8gdmFyaWFjacOzbiBpcnJlZ3VsYXIgKGZhY3RvcmVzIHF1ZSBubyBwdWVkZW4gcHJlZGVjaXJzZSkuDQoNCiMjIEJyZXZlbWVudGUsIGRlc2NyaWJpciBjw7NtbyBlbCBhbsOhbGlzaXMgZGUgZGF0b3MgZGUgc2VyaWVzIGRlIHRpZW1wbyBwdWVkZSBjb250cmlidWlyIGEgcHJvbm9zdGljYXIgY2FtYmlvcyB5L28gcGF0cm9uZXMgZW4gbG9zIGZsdWpvcyBkZSBpbnZlcnNpw7NuIGV4dHJhbmplcmEgZGlyZWN0YSAoSUVEKSBhc29jaWFkYXMgY29uIGRlY2lzaW9uZXMgZGUg4oCcTmVhcnNob3JpbmfigJ0gcGFyYSBlbCBjYXNvIGRlIE3DqXhpY28uIA0KDQpNZWRpYW50ZSBtb2RlbG9zIGVzdGFkw61zdGljb3MgY29tbyBBUk1BLCBBUklNQSwgVkFSIHNlIHB1ZWRlbiBpZGVudGlmaWNhciBwYXRyb25lcyBlbiBlbCBjb21wb3J0YW1pZW50byBoaXN0w7NyaWNvIGRlIGxvcyBudWV2b3MgZmx1am9zIGRlIGludmVyc2nDs24gZXh0cmFuamVyYSBkaXJlY3RhIHkgc2UgcHVlZGVuIHJlYWxpemFyIHByb3llY2Npb25lcyBmdXR1cmFzLiBFc3RhcyBwcm95ZWNjaW9uZXMgZmFjaWxpdGFuIGxhIHRvbWEgZGUgZGVjaXNpb25lcyBlc3RyYXTDqWdpY2FzIHJlbGFjaW9uYWRhcyBjb24gZWwgY3JlY2ltaWVudG8gZGVsIG5lYXJzaG9yaW5nLiBBZGVtw6FzLCBlc3RvcyBhbsOhbGlzaXMgcGVybWl0ZW4gYWNlcHRhciBvIHJlY2hhemFyIGhpcMOzdGVzaXMgcXVlIGZhY2lsaXRhbiBjb21wcmVuZGVyIGxhIHNpdHVhY2nDs24gYWN0dWFsIHkgZnV0dXJhIGRlbCBuZWFyc2hvcmluZyBlbiBNw6l4aWNvIGNvbnNpZGVyYW5kbyB2YXJpYWJsZXMgbWFjcm9lY29uw7NtaWNhcyBxdWUgaW5mbHV5ZW4gZW4gZXN0ZSBzdWNlc28uDQoNCg0KIyBBbsOhbGlzaXMgRXhwbG9yYXRvcmlvIGRlIFZhcmlhYmxlcw0KDQojIyBWaXN1YWxpemFjacOzbiBkZSBiYXNlIG9yaWdpbmFsDQpgYGB7ciB9DQpsaWJyYXJ5KG9wZW54bHN4KQ0KZGYgPC0gcmVhZC54bHN4KCJhY3QzX2RhdGEueGxzeCIsIHNoZWV0ID0gInRpbWUgc2VyaWVzIGRhdGEiKQ0Ka2FibGUoaGVhZChkZikpDQpgYGANCg0KIyMgUmV2aXNpw7NuIGRlIHZhbG9yZXMgbnVsb3MNCkxhIEJEIGNvbnRpZW5lIDUgdmFyaWFibGVzOiBZZWFyLCBRdWFydGVyLCBOZXdfRkRJX0luZmxvd3MsIEV4Y2hhbmdlX1JhdGUsIElOUEMgeSBFeHBvcnRzLiBMYSB2YXJpYWJsZSBwcmluY2lwYWwgZGUgaW50ZXLDqXMgZXMgTmV3X0ZESV9JbmZsb3dzIHF1ZSBub3Mgc2Vydmlyw6EgY29tbyBpbmRpY2Fkb3IgZGVsIE5lYXJzaG9yaW5nLiANCg0KQXNpbWlzbW8sIHNlIG9ic2VydmEgcXVlIG5vIGhheSB2YWxvcmVzIG51bG9zIGVuIGxhIGJhc2UgZGUgZGF0b3MuIERlIGlndWFsIG1hbmVyYSwgc2UgcHJlc2VudGFuIMO6bmljYW1lbnRlIGRvcyB2YWxvcmVzIG5lZ2F0aXZvcyBlbiBsYSB2YXJpYWJsZSBkZSBOZXdfRkRJX0luZmxvd3MsIG1pZW50cmFzIHF1ZSBlbCByZXN0byBkZSBsb3MgZGF0b3Mgc29uIHBvc2l0aXZvcy4NCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIE51bG9zIFRvdGFsZXMNCnN1bShpcy5uYShkZikpDQoNCiMgTnVsb3MgcG9yIENvbHVtbmENCmdnX21pc3NfdmFyKGRmKQ0KDQojIE1vc3RyYXIgcmVnaXN0cm9zIGNvbiBudWxvcw0Ka2FibGUoZGZbcm93U3Vtcyhpcy5uYShkZikpID4gMCwgYygxLCAyLCBuY29sKGRmKSldKQ0KYGBgDQoNCg0KIyMgQ29udmVyc2nDs24gZGUgdmFyaWFibGVzDQoNCkxhcyB2YXJpYWJsZXMgbm9taW5hbGVzIGRlIE5ld19GRElfSW5mbG93cyB5IEV4cG9ydHMgc2UgY29udmlydGllcm9uIGEgdmFsb3JlcyByZWFsZXMganVudG8gY29uIGxhIGNvbnZlcnNpw7NuIGEgcGVzb3MgcGFyYSB0ZW5lciB0b2RvcyBsb3MgY2FtcG9zIGVuIGxhIG1pc21hIG1vbmVkYS4gDQoNCmBgYHtyfQ0KIyBDb252ZXJ0aXIgYSBQZXNvcw0KZGYkTmV3X0ZESV9JbmZsb3dzPC0gKGRmJE5ld19GRElfSW5mbG93cypkZiRFeGNoYW5nZV9SYXRlKQ0KZGYkRXhwb3J0czwtIChkZiRFeHBvcnRzKmRmJEV4Y2hhbmdlX1JhdGUpDQoNCiMgQ29udmVydGlyIGEgUmVhbGVzDQpkZiROZXdfRkRJX0luZmxvd3M8LSAoZGYkTmV3X0ZESV9JbmZsb3dzL2RmJElOUEMpKjEwMA0KZGYkRXhwb3J0czwtIChkZiRFeHBvcnRzL2RmJElOUEMpKjEwMA0KDQpjbGFzZXMxIDwtIHNhcHBseShkZiwgY2xhc3MpDQpjbGFzZXMxDQpgYGANCg0KTG9zIHJlZ2lzdHJvcyBkZSBsYSBjb2x1bW5hIFF1YXJ0ZXIgc2UgbW9kaWZpY2Fyb24gYSB2YWxvcmVzIG51bcOpcmljb3M7IG1pZW50cmFzIHF1ZSBsb3MgZGVtw6FzIHNlIG1hbnR1dmllcm9uIGVuIGVsIG1pc21vIGZvcm1hdG8uDQoNCmBgYHtyfQ0KIyBDb252ZXJzacOzbiBkZSB0aXBvIGRlIGRhdG9zDQpsaWJyYXJ5KGRwbHlyKQ0KDQpkZiA8LSBkZiAlPiUNCiAgbXV0YXRlKFF1YXJ0ZXIgPSByZWNvZGUoUXVhcnRlciwgIkkiID0gMSwgIklJIiA9IDIsICJJSUkiID0gMywgIklWIiA9IDQpKQ0KDQpkZiRRdWFydGVyPC1hcy5udW1lcmljKGRmJFF1YXJ0ZXIpIA0KY2xhc2VzMiA8LSBzYXBwbHkoZGYsIGNsYXNzKQ0KY2xhc2VzMg0KYGBgDQoNCiMjIERpc3RyaWJ1Y2nDs24gZGUgdmFyaWFibGVzDQoNClNlIG9ic2VydmEgcXVlIGhheSBtw6FzIHZhbG9yZXMgYXTDrXBpY29zIGVuIGxhIHZhcmlhYmxlIGRlIGludGVyw6lzIE5ld19GRElfSW5mbG93czsgc2luIGVtYmFyZ28sIGVzdG9zIG91dGxpZXJzIG5vIHNlIGVsaW1pbmFyw6FuIGNvbiBlbCBmaW4gZGUgcmVwcmVzZW50YXIgbGEgcmVsYWxpZGFkIGRlIGVzYSB2YXJpYWJsZSBlbiBlbCB0aWVtcG8uDQoNCmBgYHtyfQ0KcGFyKG1mcm93ID0gYygyLCAyKSkgICMgMiBmaWxhcywgMiBjb2x1bW5hcyAoYWp1c3RhIHNlZ8O6biBsYSBjYW50aWRhZCBkZSB2YXJpYWJsZXMpDQoNCmJveHBsb3QoZGYkTmV3X0ZESV9JbmZsb3dzLCBtYWluID0gIk5ld19GRElfSW5mbG93cyIsIGNvbCA9ICJsaWdodGJsdWUiKQ0KYm94cGxvdChkZiRFeGNoYW5nZV9SYXRlLCBtYWluID0gIkV4Y2hhbmdlX1JhdGUiLCBjb2wgPSAibGlnaHRncmVlbiIpDQpib3hwbG90KGRmJElOUEMsIG1haW4gPSAiSU5QQyIsIGNvbCA9ICJsaWdodHBpbmsiKQ0KYm94cGxvdChkZiRFeHBvcnRzLCBtYWluID0gIkV4cG9ydHMiLCBjb2wgPSAicHVycGxlIikNCmBgYA0KDQoNCiMgRXN0YWTDrXN0aWNvcyBkZXNjcmlwdGl2b3MNCg0KTG9zIGRhdG9zIG11ZXN0cmFuIHVuYSBldm9sdWNpw7NuIGVjb27Ds21pY2EgY29uIGZsdWN0dWFjaW9uZXMgZW4gaW52ZXJzacOzbiBleHRyYW5qZXJhIGRpcmVjdGEsIHRpcG8gZGUgY2FtYmlvIGUgaW5mbGFjacOzbi4gRXMgaW1wb3J0YW50ZSByZXZpc2FyIGxhIHBvc2libGUgcHJlc2VuY2lhIGRlIHZhbG9yZXMgYXTDrXBpY29zIGVuIE5ld19GRElfSW5mbG93cywgeWEgcXVlIGhheSB2YWxvcmVzIG5lZ2F0aXZvcyBzaWduaWZpY2F0aXZvcy4NCmBgYHtyfQ0Kc3VtbWFyeShkZikNCmBgYA0KDQojIyBHcsOhZmljbyBkZSBkaXNwZXJzacOzbg0KDQpMYXMgZGlzdHJpYnVjaW9uZXMgc3VnaWVyZW4gcXVlIGFsZ3VuYXMgdmFyaWFibGVzLCBjb21vIE5ld19GRElfSW5mbG93cyB5IEV4Y2hhbmdlX1JhdGUsIHB1ZWRlbiByZXF1ZXJpciB0cmFuc2Zvcm1hY2lvbmVzIHBhcmEgbWVqb3JhciBsYSBub3JtYWxpZGFkLiBUYW1iacOpbiBzZSBvYnNlcnZhIHF1ZSBOZXdfRkRJX0luZmxvd3MgZSBJTlBDIHRpZW5lbiB1bmEgbWVkaWEgbWF5b3IgYSBsYSBtZWRpYW5hIHBvciBsbyBxdWUgZXN0w6FuIHNlc2dhZGFzIGEgbGEgZGVyZWNoYS4gQXNpbWlzbW8sIEV4cG9ydHMgdGllbmUgdW5hIG1lZGlhbmEgbWF5b3IgcXVlIGxhIG1lZGlhLCBlc3TDoSBzZXNnYWRhIGxldmVtZW50ZSBhIGxhIGl6cXVpZXJkYS4NCg0KYGBge3J9DQpwbG90X2hpc3RvZ3JhbShkZikNCmBgYA0KDQojIyBHcsOhZmljbyBkZSBub3JtYWxpZGFkDQoNClNlIHJlYWxpemFyb24gZ3LDoWZpY29zIGRlIG5vcm1hbGlkYWQgcGFyYSBjb21wYXJhciBsYSBkaXN0cmlidWNpw7NuIGRlIGxhcyB2YXJpYWJsZXMgYXBsY2lhbmRvIHRyYW5zZm9ybWFjaW9uZXMgbG9nYXLDrXRtaWNhcyB5IGRlIHJhw616IGN1YWRyYWRhLiBTZSBvYnNlcnbDsyBxdWUgbGFzIGRpc3RyaWJ1Y2lvbmVzIGxvZ2Fyw610bWljYXMgZGUgRXhjaGFuZ2VfUmF0ZSwgSU5QQyB5IEV4cG9ydHMgZXJhbiBtZWpvcmVzIHF1ZSBsYXMgZGlzdHJpYnVjaW9uZXMgb3JpZ2luYWxlcyBkZSBsYXMgdmFyaWFibGVzLCBwb3IgbG8gcXVlIHNlIGRlY2lkacOzIHJlYWxpemFyIGxhIHRyYW5zZm9ybWFjacOzbiBsb2dhcsOtdG1pY2EgZGUgZXNhcyB2YXJpYWJsZXMuDQoNCmBgYHtyfQ0KcGxvdF9ub3JtYWxpdHkoZGYpDQpgYGANCg0KIyMgVHJhbnNmb3JtYWNpw7NuIGRlIHZhcmlhYmxlcw0KDQpMYSB0cmFuc2Zvcm1hY2nDs24gbG9nYXLDrXRtaWNhIG1lam9yYSBsYSBkaXN0cmlidWNpw7NuIGRlIGFsZ3VuYXMgdmFyaWFibGVzLCBoYWNpw6luZG9sYXMgbcOhcyBzaW3DqXRyaWNhcyB5IHJlZHVjaWVuZG8gbGEgdmFyaWFuemEuIEVzdG8gZXMgw7p0aWwgcGFyYSBhbsOhbGlzaXMgZWNvbm9tw6l0cmljb3MgeSBtb2RlbG9zIHF1ZSBhc3VtZW4gbm9ybWFsaWRhZC4NCg0KYGBge3J9DQpkZiA8LSBkZiAlPiUNCiAgbXV0YXRlKA0KICAgIGxvZ19FeGNoYW5nZV9SYXRlID0gbG9nKEV4Y2hhbmdlX1JhdGUgKyAwLjAwMDEpLA0KICAgIGxvZ19JTlBDID0gbG9nKElOUEMgKyAwLjAwMDEpLA0KICAgIGxvZ19FeHBvcnRzID0gbG9nKEV4cG9ydHMgKyAwLjAwMDEpDQogICkNCiMgR3LDoWZpY28gZGUgZGlzcGVyc2nDs24NCnBsb3RfaGlzdG9ncmFtKGRmKQ0Kc3VtbWFyeShkZikNCmBgYA0KDQojIyBNYXRyaXogZGUgY29ycmVsYWNpw7NuDQoNCkxhIG1hdHJpeiBkZSBjb3JyZWxhY2nDs24gbXVlc3RyYSBxdWUgbGEgdmFyaWFibGUgZGVwZW5kaWVudGUgTmV3X0ZESV9JbmZsb3dzIHRpZW5lIG11eSBwb2NhIGNvcnJlbGFjacOzbiBjb24gbGFzIGRlbcOhcyB2YXJpYWJsZXMuIFRvZGFzIGxhcyBkZW3DoXMgdmFyaWFibGVzIHRhbnRvIGNvbiBzdSBlc3RydWN0dXJhIG9yaWdpbmFsIGNvbW8gY29uIHRyYW5zZm9ybWFjacOzbiBsb2dhcsOtdG1pY2EgbXVlc3RyYXMgdW5hIG11eSBhbHRhIGNvcnJlbGFjacOzbiBlbnRyZSBlbGxhcy4NCg0KYGBge3J9DQpwbG90X2NvcnJlbGF0aW9uKGRmKQ0KYGBgDQoNCg0KIyBBbsOhbGlzaXMgZGUgc2VyaWVzIGRlIHRpZW1wbw0KDQojIyBDcmVhciAyIOKAkyAzIGdyw6FmaWNvcyBkZSBzZXJpZXMgZGUgdGllbXBvIHF1ZSBtdWVzdHJlbiBlbCBkZXNlbXBlw7FvIGRlIGxhcyB2YXJpYWJsZXMgZGUgaW50ZXLDqXMuDQoNCkxhIGltYWdlbiBtdWVzdHJhIHVuYSBzZXJpZSBkZSB0aWVtcG8gZGUgbG9zIGZsdWpvcyBkZSBpbnZlcnNpw7NuIGV4dHJhbmplcmEgZGlyZWN0YSAoRkRJKSBudWV2b3MgYSBsbyBsYXJnbyBkZWwgdGllbXBvLiBFbCBlamUgWCByZXByZXNlbnRhIGxvcyBhw7FvcyAoYXByb3hpbWFkYW1lbnRlIGRlc2RlIDIwMDYgaGFzdGEgbWVkaWFkb3MgMjAyNCksIHkgZWwgZWplIFkgbXVlc3RyYSBlbCB2YWxvciBkZSBsb3MgZmx1am9zIGRlIGludmVyc2nDs24uIExhIHNlcmllIHByZXNlbnRhIGZsdWN0dWFjaW9uZXMgY29uIHZhcmlvcyBwaWNvcyB5IGNhw61kYXMsIGRlc3RhY8OhbmRvc2UgdW4gcGljbyBtdXkgcHJvbnVuY2lhZG8gYWxyZWRlZG9yIGRlIDIwMTAgeSBvdHJvIGF1bWVudG8gc2lnbmlmaWNhdGl2byBkZXNwdcOpcyBkZSAyMDIwLiANCg0KYGBge3J9DQpkZiROZXdfRkRJX0luZmxvd3MgPC0gbmEub21pdChkZiROZXdfRkRJX0luZmxvd3MpDQpOZXdfRkRJX3RzMiA8LSB0cyhkZiROZXdfRkRJX0luZmxvd3MsIHN0YXJ0ID0gYygyMDA2LCAxKSwgZW5kID0gYygyMDI0LCA0KSwgZnJlcXVlbmN5ID0gNCkNCnBsb3QoTmV3X0ZESV90czIsIHR5cGUgPSAibCIsIGNvbCA9ICJibHVlIiwgbHdkID0gMiwgeGxhYiA9ICJZZWFyIiwgeWxhYiA9ICJOZXdfRkRJX0luZmxvd3MiLCBtYWluID0gIlRpbWUgU2VyaWVzIG9mIE5ld19GRElfSW5mbG93cyIpDQpgYGANCg0KTGEgc2VyaWUgbXVlc3RyYSBlc3RhY2lvbmFsaWRhZCBwb3JxdWUgaGF5IHBpY29zIHBlcmnDs2RpY29zIGRlIGFsdGFzIHkgYmFqYXMgcXVlIG9jdXJyZW4gcmVndWxhcm1lbnRlLiBMYSBzZXJpZSBtdWVzdHJhIHVuYSBsZXZlIHRlbmRlbmNpYSwgY29uIGZsdWN0dWFjaW9uZXMgZW50cmUgcGVyaW9kb3MgZGUgY3JlY2ltaWVudG8geSBwZXJpb2RvcyBkZSBkaXNtaW51Y2nDs24uIA0KDQpgYGB7cn0NCmRlY29tcG9zaXRpb24gPC0gZGVjb21wb3NlKE5ld19GRElfdHMyKQ0KcGxvdChkZWNvbXBvc2l0aW9uKQ0KYGBgDQoNCg0KIyMgRGVzY3JpYmlyIGJyZXZlbWVudGUgZWwgZGVzZW1wZcOxbyBkZSBsYShzKSB2YXJpYWJsZShzKSBkZSBpbnRlcsOpcyBwYXJhIGNhZGEgdW5vIGRlIGxvcyBncsOhZmljb3MgYW50ZXJpb3Jlcy4gRXMgaW1wb3J0YW50ZSBpZGVudGlmaWNhciBsYSBwcmVzZW5jaWEgZGUgYWxnw7puIHRpcG8gZGUgdGVuZGVuY2lhLCBlc3RhY2lvbmFsaWRhZCwgeSBhdXRvY29ycmVsYWNpw7NuIGVuIGNhZGEgdW5vIGRlIGxvcyBncsOhZmljb3MgZWxhYm9yYWRvcy4NCg0KU2Ugb2JzZXJ2YSBxdWUgbGFzIHZhcmlhYmxlcyBwcmVzZW50YW4gdGVuZGVuY2lhcyBhbCBhbHphIGVuIGVsIGxhcmdvIHBsYXpvLCBhdW5xdWUgZWwgdGlwbyBkZSBjYW1iaW8gbXVlc3RyYSB2YXJpYWNpb25lcyBtw6FzIGFicnVwdGFzIGVuIGNpZXJ0b3MgcGVyaW9kb3MsIG1pZW50cmFzIHF1ZSBlbCBJTlBDIHkgRXhwb3J0cyB0aWVuZSB1biBjb21wb3J0YW1pZW50byBtw6FzIGVzdGFibGUgeSBwcmVkZWNpYmxlLg0KDQoNCioqVGlwbyBkZSBDYW1iaW8gKEV4Y2hhbmdlIFJhdGUpKioNCg0KKiBUZW5kZW5jaWE6IFNlIG9ic2VydmEgdW5hIHRlbmRlbmNpYSBjcmVjaWVudGUgZGVzZGUgMjAwNSBoYXN0YSBhcHJveGltYWRhbWVudGUgMjAyMCwgY29uIGFsZ3Vub3MgcGVyw61vZG9zIGRlIGVzdGFiaWxpZGFkLiBEZXNwdcOpcyBkZSAyMDIwLCBoYXkgdW5hIGxpZ2VyYSBkaXNtaW51Y2nDs24uDQoNCiogRXN0YWNpb25hbGlkYWQ6IE5vIHBhcmVjZSBoYWJlciBwYXRyb25lcyBlc3RhY2lvbmFsZXMgZXZpZGVudGVzIGVuIGxvcyBkYXRvcy4NCg0KKiBBdXRvY29ycmVsYWNpw7NuOiBMYSBzZXJpZSBwYXJlY2UgbW9zdHJhciBhdXRvY29ycmVsYWNpw7NuLCB5YSBxdWUgbG9zIGNhbWJpb3MgZW4gZWwgdGlwbyBkZSBjYW1iaW8gb2N1cnJlbiBkZSBtYW5lcmEgZXNjYWxvbmFkYSBjb24gYWp1c3RlcyBicnVzY29zIGVuIGNpZXJ0b3MgcHVudG9zLCBsbyBxdWUgc3VnaWVyZSBkZXBlbmRlbmNpYSBkZSB2YWxvcmVzIHBhc2Fkb3MuDQoNCg0KKirDjW5kaWNlIE5hY2lvbmFsIGRlIFByZWNpb3MgYWwgQ29uc3VtaWRvciAoSU5QQykqKg0KDQoqIFRlbmRlbmNpYTogU2UgYXByZWNpYSB1bmEgdGVuZGVuY2lhIGNyZWNpZW50ZSB5IHNvc3RlbmlkYSBhIGxvIGxhcmdvIGRlbCB0aWVtcG8sIGluZGljYW5kbyB1biBhdW1lbnRvIGNvbnN0YW50ZSBlbiBsb3MgcHJlY2lvcy4NCg0KKiBFc3RhY2lvbmFsaWRhZDogTm8gc2Ugb2JzZXJ2YW4gZmx1Y3R1YWNpb25lcyBjw61jbGljYXMgcXVlIHN1Z2llcmFuIHVuIHBhdHLDs24gZXN0YWNpb25hbCBtYXJjYWRvLg0KDQoqIEF1dG9jb3JyZWxhY2nDs246IExhIHNlcmllIG11ZXN0cmEgdW5hIGZ1ZXJ0ZSBjb3JyZWxhY2nDs24gY29uIHZhbG9yZXMgcGFzYWRvcywgeWEgcXVlIGVsIElOUEMgc2lndWUgdW4gcGF0csOzbiBkZSBjcmVjaW1pZW50byBwcm9ncmVzaXZvIHNpbiBjYcOtZGFzIGFicnVwdGFzLg0KDQoNCioqRXhwb3J0YWNpb25lcyAoRXhwb3J0cykqKg0KDQoqIFRlbmRlbmNpYTogU2Ugb2JzZXJ2YSB1bmEgdGVuZGVuY2lhIGFzY2VuZGVudGUgZW4gbGFzIGV4cG9ydGFjaW9uZXMgZGVzZGUgZWwgaW5pY2lvIGRlIGxhIHNlcmllIGhhc3RhIGFscmVkZWRvciBkZSAyMDIyLiBFbiBsb3Mgw7psdGltb3MgcGVyaW9kb3MsIGhheSB1bmEgY2HDrWRhIG5vdGFibGUgZW4gbGFzIGV4cG9ydGFjaW9uZXMsIGxvIHF1ZSBwb2Ryw61hIGluZGljYXIgdW5hIHBvc2libGUgZGVzYWNlbGVyYWNpw7NuIG8gY3Jpc2lzIGVuIGVsIHNlY3Rvci4NCg0KKiBFc3RhY2lvbmFsaWRhZDogU2UgcHVlZGVuIG5vdGFyIGJyZXZlcyBmbHVjdHVhY2lvbmVzIGRlbnRybyBkZWwgY3JlY2ltaWVudG8sIGxvIHF1ZSBzdWdpZXJlIGNpZXJ0byBuaXZlbCBkZSBwYXRyb25lcyBlc3RhY2lvbmFsZXMuDQoNCiogQXV0b2NvcnJlbGFjacOzbjogTGEgc2VyaWUgbXVlc3RyYSBjb3JyZWxhY2nDs24gY29uIHZhbG9yZXMgcGFzYWRvcyBkZWJpZG8gYSBsb3MgY2FtYmlvcyBxdWUgb2N1cnJlbiBlbiBsYSB2YXJpYWJsZSBkZSBtYW5lcmEgZXNjYWxvbmFkYS4NCg0KYGBge3J9DQpFeGNoYW5nZV9SYXRlX3RzIDwtIHRzKGRmJGxvZ19FeGNoYW5nZV9SYXRlLCBzdGFydCA9IGMoMjAwNiwgMSksIGVuZCA9IGMoMjAyMywgNCksIGZyZXF1ZW5jeSA9IDQpDQpJTlBDX3RzIDwtIHRzKGRmJGxvZ19JTlBDLCBzdGFydCA9IGMoMjAwNiwgMSksIGVuZCA9IGMoMjAyMywgNCksIGZyZXF1ZW5jeSA9IDQpDQpFeHBvcnRzX3RzIDwtIHRzKGRmJGxvZ19FeHBvcnRzLCBzdGFydCA9IGMoMjAwNiwgMSksIGVuZCA9IGMoMjAyMywgNCksIGZyZXF1ZW5jeSA9IDQpDQoNCiMgMS4gR3LDoWZpY28gZGUgc2VyaWVzIGRlIHRpZW1wbyBjb24gZ2dwbG90Mg0KcGxvdF90aW1lX3NlcmllcyA8LSBmdW5jdGlvbih0c19kYXRhLCB2YXJfbmFtZSkgew0KICB0c19kZiA8LSBkYXRhLmZyYW1lKFllYXIgPSB0aW1lKHRzX2RhdGEpLCBWYWx1ZSA9IGFzLm51bWVyaWModHNfZGF0YSkpDQogIGdncGxvdCh0c19kZiwgYWVzKHggPSBZZWFyLCB5ID0gVmFsdWUpKSArDQogICAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiLCBzaXplID0gMSkgKw0KICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiVGltZSBTZXJpZXMgb2YiLCB2YXJfbmFtZSksIHggPSAiWWVhciIsIHkgPSB2YXJfbmFtZSkgKw0KICAgIHRoZW1lX21pbmltYWwoKQ0KfQ0KDQojIE1vc3RyYXIgZ3LDoWZpY29zDQpwcmludChwbG90X3RpbWVfc2VyaWVzKEV4Y2hhbmdlX1JhdGVfdHMsICJFeGNoYW5nZSBSYXRlIikpDQpwcmludChwbG90X3RpbWVfc2VyaWVzKElOUENfdHMsICJJTlBDIikpDQpwcmludChwbG90X3RpbWVfc2VyaWVzKEV4cG9ydHNfdHMsICJFeHBvcnRzIikpDQpgYGANCg0KDQojIyBBdXRvY29ycmVsYWNpw7NuDQoNCk5vIGhheSBldmlkZW5jaWEgZGUgYXV0b2NvcnJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVuIGxvcyByZXNpZHVvcywgbG8gcXVlIHN1Z2llcmUgcXVlIGVsIG1vZGVsbyBjYXB0dXJhIGJpZW4gbGEgZXN0cnVjdHVyYSB0ZW1wb3JhbCBkZSBsb3MgZGF0b3MgeSBubyBkZWphIHBhdHJvbmVzIG5vIGV4cGxpY2Fkb3MuIEVzdG8gZXMgdW4gYnVlbiBpbmRpY2Fkb3IgZGUgdW4gbW9kZWxvIGFkZWN1YWRvLg0KDQpgYGB7cn0NCiMgQXV0b2NvcnJlbGFjacOzbiB5IGF1dG9jb3JyZWxhY2nDs24gcGFyY2lhbA0KYWNmKE5ld19GRElfdHMyLCBtYWluPSJBdXRvY29ycmVsYXRpb24gLSBOZXdfRkRJX0luZmxvd3MiKQ0KcGFjZihOZXdfRkRJX3RzMiwgbWFpbj0iUGFydGlhbCBBdXRvY29ycmVsYXRpb24gLSBOZXdfRkRJX0luZmxvd3MiKQ0KDQojIEF1Y290b3JyZWxhY2nDs24gc2VyaWFsDQpsZ3Vual9ib3hfcmVzdWx0IDwtIEJveC50ZXN0KE5ld19GRElfdHMyLCBsYWcgPSA1LCB0eXBlID0gIkxqdW5nLUJveCIpDQpsZ3Vual9ib3hfcmVzdWx0DQpgYGANCg0KDQojIyBFc3RhY2lvbmFyaWVkYWQNCg0KU2Ugb2JzZXJ2YSBxdWUgcGFyYSBsYXMgdHJlcyB2YXJpYWJsZXMsIGxvcyBwLXZhbG9yZXMgc29uIGFsdG9zICg+IDAuMDUpLCBwb3IgbG8gcXVlIG5vIHNlIHJlY2hhemEgbGEgaGlww7N0ZXNpcyBudWxhIGRlIHJhw616IHVuaXRhcmlhOyBlcyBkZWNpciwgbGFzIHNlcmllcyBubyBzb24gZXN0YWNpb25hcmlhcywgbG8gcXVlIHN1Z2llcmUgcXVlIHB1ZWRlbiByZXF1ZXJpciBkaWZlcmVuY2lhY2nDs24gbyB0cmFuc2Zvcm1hY2nDs24gYWRpY2lvbmFsIHBhcmEgc3UgdXNvIGVuIG1vZGVsb3MgZGUgc2VyaWVzIGRlIHRpZW1wby4NCg0KYGBge3J9DQojIEFwbGljYXIgbGEgcHJ1ZWJhIEFERiBzb2JyZSBsYXMgdmFyaWFibGVzIHRyYW5zZm9ybWFkYXMgZW4gbG9nDQphZGZfdGVzdF9sb2dfZXhjaGFuZ2UgPC0gYWRmLnRlc3QoZGYkbG9nX0V4Y2hhbmdlX1JhdGUpDQphZGZfdGVzdF9sb2dfaW5wYyA8LSBhZGYudGVzdChkZiRsb2dfSU5QQykNCmFkZl90ZXN0X2xvZ19leHBvcnRzIDwtIGFkZi50ZXN0KGRmJGxvZ19FeHBvcnRzKQ0KDQojIE1vc3RyYXIgcmVzdWx0YWRvcyBkZSBsYSBwcnVlYmEgQURGDQpwcmludChhZGZfdGVzdF9sb2dfZXhjaGFuZ2UpDQpwcmludChhZGZfdGVzdF9sb2dfaW5wYykNCnByaW50KGFkZl90ZXN0X2xvZ19leHBvcnRzKQ0KYGBgDQoNCiMjIEFVVE8gQVJJTUENCg0KQ29uIGJhc2UgYSBsYSBwcmVzZW5jaWEgZGUgZXN0YWNpb25hcmllZGFkLCBzZSBnZW5lcmEgbW9kZWxvIEFVVE9BUklNQSBwYXJhIGRldGVybWluYXIgbWVqb3Igbml2ZWwgZGUgZGlmZXJlbmNpYWNpw7NuIHBhcmEgY2FkYSB2YXJpYWJsZS4NCg0KYGBge3J9DQojIEFwbGljYXIgYXV0by5hcmltYSgpIGEgbGFzIHZhcmlhYmxlcyBzaW4gZGlmZXJlbmNpYXJsYXMgZGlmZXJlbmNpYWRhcw0KYXV0b19hcmltYV9GREkgPC0gYXV0by5hcmltYShOZXdfRkRJX3RzMikgI05vIHNlIGFwbGljYSAsIHNlIHZhIGRpcmVjdG8gYSB1biBtb2RlbG8gQVJNQQ0KDQphdXRvX2FyaW1hX21vZGVsMSA8LSBhdXRvLmFyaW1hKGRmJGxvZ19FeGNoYW5nZSkNCmF1dG9fYXJpbWFfbW9kZWwyIDwtIGF1dG8uYXJpbWEoZGYkbG9nX0lOUEMpDQphdXRvX2FyaW1hX21vZGVsMyA8LSBhdXRvLmFyaW1hKGRmJGxvZ19FeHBvcnRzKQ0KDQpzdW1tYXJ5KGF1dG9fYXJpbWFfRkRJKQ0KDQpzdW1tYXJ5KGF1dG9fYXJpbWFfbW9kZWwxKQ0Kc3VtbWFyeShhdXRvX2FyaW1hX21vZGVsMikNCnN1bW1hcnkoYXV0b19hcmltYV9tb2RlbDMpDQpgYGANCg0KYGBge3J9DQojIFZlcmlmaWNhciByZXNpZHVvcyBkZSBBVVRPQVJJTUEgZW4gbGFzIHNlcmllcyBkaWZlcmVuY2lhZGFzDQpjaGVja3Jlc2lkdWFscyhhdXRvX2FyaW1hX0ZESSkNCmNoZWNrcmVzaWR1YWxzKGF1dG9fYXJpbWFfbW9kZWwxKQ0KY2hlY2tyZXNpZHVhbHMoYXV0b19hcmltYV9tb2RlbDIpDQpjaGVja3Jlc2lkdWFscyhhdXRvX2FyaW1hX21vZGVsMykNCmBgYA0KDQojIyBEaWZlcmVuY2lhY2nDs24gKENvcnJlY2Npw7NuIGRlIEVzdGFjaW9uYXJpZWRhZCkNCg0KU2UgcmVhbGl6YXJvbiBBdXRvQXJpbWFzIHBhcmEgbGFzIHZhcmlhYmxlcyBleHBsaWNhdGl2YXMgY29uIGVsIGZpbiBkZSBkZXRlcm1pbmFyIGVsIG7Dum1lcm8gZGUgZGlmZXJlbmNpYXMgbmVjZXNhcmlhcyBwYXJhIHJlZHVjaXIgbm8gZXN0YWNpb25hcmllZGFkLiBTZSBvYnNlcnbDsyBxdWUgdHJlcyBtb2RlbG9zIChsb2dfRXhjaGFuZ2UsIGxvZ19JTlBDIHkgbG9nX0V4cG9ydHMpIHJlcXVpZXJlbiB1bmEgZGlmZXJlbmNpYSAoZD0xKSwgbWllbnRyYXMgcXVlIGVsIG1vZGVsbyBwYXJhIE5ld19GRElfdHMyIG5vIHN1Z2llcmUgZGlmZXJlbmNpYWNpw7NuIChkPTApLiBQb3IgbG8gdGFudG8sIHNlIGFwbGljYXLDoSB1bmEgZGlmZXJlbmNpYSBzb2xvIGEgbGFzIHRyZXMgdmFyaWFibGVzIHF1ZSBsbyByZXF1aWVyZW4uDQoNCmBgYHtyfQ0KIyBTaSBsYXMgdmFyaWFibGVzIGVuIGxvZyBzaWd1ZW4gc2luIHNlciBlc3RhY2lvbmFyaWFzLCBwcm9iYW1vcyBkaWZlcmVuY2lhcmxhcw0KZGlmZl9sb2dfZXhjaGFuZ2UgPC0gZGlmZihkZiRsb2dfRXhjaGFuZ2VfUmF0ZSkNCmRpZmZfbG9nX2lucGMgPC0gZGlmZihkZiRsb2dfSU5QQywgbGFnPSA0KQ0KZGlmZl9sb2dfZXhwb3J0cyA8LSBkaWZmKGRmJGxvZ19FeHBvcnRzKQ0KDQojIEFwbGljYXIgQURGIHNvYnJlIGxhcyBzZXJpZXMgZGlmZXJlbmNpYWRhcyBlbiBsb2cNCmFkZl90ZXN0X2RpZmZfbG9nX2V4Y2hhbmdlIDwtIGFkZi50ZXN0KGRpZmZfbG9nX2V4Y2hhbmdlKQ0KYWRmX3Rlc3RfZGlmZl9sb2dfaW5wYyA8LSBhZGYudGVzdChkaWZmX2xvZ19pbnBjKQ0KYWRmX3Rlc3RfZGlmZl9sb2dfZXhwb3J0cyA8LSBhZGYudGVzdChkaWZmX2xvZ19leHBvcnRzKQ0KDQojIE1vc3RyYXIgcmVzdWx0YWRvcyBkZXNwdcOpcyBkZSBsYSBkaWZlcmVuY2lhY2nDs24NCnByaW50KGFkZl90ZXN0X2RpZmZfbG9nX2V4Y2hhbmdlKQ0KcHJpbnQoYWRmX3Rlc3RfZGlmZl9sb2dfaW5wYykNCnByaW50KGFkZl90ZXN0X2RpZmZfbG9nX2V4cG9ydHMpDQoNCmBgYA0KDQoNCiMjIyBBanVzdGUgZGUgZGlmZXJlbmNpYWNpw7NuDQoNCiogZGlmZl9sb2dfRXhjaGFuZ2VfUmF0ZSB5IGRpZmZfbG9nX0V4cG9ydHMgYWhvcmEgc29uIGVzdGFjaW9uYXJpYXMgZGVzcHXDqXMgZGUgbGEgZGlmZXJlbmNpYWNpw7NuDQoNCiogZGlmZl9sb2dfSU5QQyBzaWd1ZSBzaW4gc2VyIGVzdGFjaW9uYXJpYSAocC12YWx1ZSA9IDAuMzcyOCksIHNlIHJlYWxpemFyw6EgbnVldmFtZW50ZSBsYSBkaWZlcmVuY2lhY2nDs24gcGFyYSBjb252ZXJ0aXJsYSBhIGVzdGFjaW9uYXJpYS4NCg0KKiBBbCBlamVjdXRhciBlbCBwcmVzZW50ZSBjw7NkaWdvLCBsb2dfSU5QQyBhaG9yYSB5YSBlcyBlc3RhY2lvbmFyaWEgZGVzcHXDqXMgZGUgZG9zIGRpZmVyZW5jaWFjaW9uZXMgKGRpZmYoZGlmZihkZiRsb2dfSU5QQykpKS4NCg0KYGBge3J9DQojIEFwbGljYXIgc2VndW5kYSBkaWZlcmVuY2lhY2nDs24NCmRpZmYyX2xvZ19pbnBjIDwtIGRpZmYoZGlmZihkZiRsb2dfSU5QQykpDQoNCiMgUHJ1ZWJhIEFERiBkZXNwdcOpcyBkZSBsYSBzZWd1bmRhIGRpZmVyZW5jaWFjacOzbg0KYWRmX3Rlc3RfZGlmZjJfbG9nX2lucGMgPC0gYWRmLnRlc3QoZGlmZjJfbG9nX2lucGMpDQoNCnByaW50KGFkZl90ZXN0X2RpZmYyX2xvZ19pbnBjKQ0KYGBgDQoNCg0KIyMgRXN0YWNpb25hbGlkYWQNCg0KTG9zIHJlc3VsdGFkb3MgZGVsIHRlc3QgZGUgS3J1c2thbC1XYWxsaXMgcGFyYSB0b2RhcyBsYXMgdmFyaWFibGVzIGluZGljYWRhcyAoRkRJLCB0aXBvIGRlIGNhbWJpbywgSU5QQyB5IGV4cG9ydGFjaW9uZXMpIG11ZXN0cmFuIHF1ZSBsb3MgdmFsb3JlcyBwIHNvbiB0b2RvcyBtYXlvcmVzIHF1ZSBlbCB1bWJyYWwgY29tw7puIGRlIHNpZ25pZmljYW5jaWEgZGUgMC4wNSAoZW4gdG9kb3MgbG9zIGNhc29zLCBsb3MgdmFsb3JlcyBwIHNvbiBzdXBlcmlvcmVzIGEgMC40KS4gRXN0byBzdWdpZXJlIHF1ZSBubyBoYXkgZGlmZXJlbmNpYXMgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YXMgZW50cmUgbG9zIGdydXBvcyBvIHRyaW1lc3RyZXMgZXZhbHVhZG9zIHBhcmEgbmluZ3VuYSBkZSBsYXMgdmFyaWFibGVzIGFuYWxpemFkYXMuIEVuIG90cmFzIHBhbGFicmFzLCBubyBzZSBwdWVkZSByZWNoYXphciBsYSBoaXDDs3Rlc2lzIG51bGEsIHF1ZSBlc3RhYmxlY2UgcXVlIGxhcyBkaXN0cmlidWNpb25lcyBkZSBsYXMgdmFyaWFibGVzIG5vIGRpZmllcmVuIHNpZ25pZmljYXRpdmFtZW50ZSBlbnRyZSBsb3MgdHJpbWVzdHJlcy4NCg0KYGBge3J9DQojIENyZWFyIHVuIGZhY3RvciBwYXJhIGxvcyB0cmltZXN0cmVzDQp0cmltZXN0cmVzX0ZESSA8LSBjeWNsZShOZXdfRkRJX3RzMikNCnRyaW1lc3RyZXNfRVIgPC0gY3ljbGUoRXhjaGFuZ2VfUmF0ZV90cykNCnRyaW1lc3RyZXNfSU5QQyA8LSBjeWNsZShJTlBDX3RzKQ0KdHJpbWVzdHJlc19FWFBPUlRTIDwtIGN5Y2xlKEV4cG9ydHNfdHMpDQoNCiMgQXBsaWNhciBsYSBwcnVlYmEgZGUgS3J1c2thbC1XYWxsaXMgYSBjYWRhIHZhcmlhYmxlDQprcnVza2FsX0ZESSA8LSBrcnVza2FsLnRlc3QoYXMubnVtZXJpYyhOZXdfRkRJX3RzMikgfiB0cmltZXN0cmVzX0ZESSkNCmtydXNrYWxfRVIgPC0ga3J1c2thbC50ZXN0KGFzLm51bWVyaWMoRXhjaGFuZ2VfUmF0ZV90cykgfiB0cmltZXN0cmVzX0VSKQ0Ka3J1c2thbF9JTlBDIDwtIGtydXNrYWwudGVzdChhcy5udW1lcmljKElOUENfdHMpIH4gdHJpbWVzdHJlc19JTlBDKQ0Ka3J1c2thbF9FWFBPUlRTIDwtIGtydXNrYWwudGVzdChhcy5udW1lcmljKEV4cG9ydHNfdHMpIH4gdHJpbWVzdHJlc19FWFBPUlRTKQ0KDQojIEltcHJpbWlyIGxvcyByZXN1bHRhZG9zDQpwcmludChrcnVza2FsX0ZESSkNCnByaW50KGtydXNrYWxfRVIpDQpwcmludChrcnVza2FsX0lOUEMpDQpwcmludChrcnVza2FsX0VYUE9SVFMpDQpgYGANCg0KDQojIEVzdGltYWNpw7NuIGRlIE1vZGVsb3MgZGUgU2VyaWVzIGRlIFRpZW1wbw0KQ29uIGJhc2UgZW4gbGEgc2VsZWNjacOzbiBkZSBsYShzKSB2YXJpYWJsZShzKSBkZSBpbnRlcsOpcywgcmVhbGl6YXIgbGEgZXN0aW1hY2nDs24gZGUgbGFzIHNpZ3VpZW50ZXMgZXNwZWNpZmljYWNpb25lcyBkZSBtb2RlbG9zIGRlIHNlcmllcyBkZSB0aWVtcG86DQoNCiMjIEFSTUENCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgQWp1c3RhciBtb2RlbG8gQVJNQSAoMSwxKSBhIE5ld19GRElfdHMyICh5YSBlcyBlc3RhY2lvbmFyaWEpDQpsaWJyYXJ5KFRTQSkNCg0KYXJtYV9tb2RlbF90c2EgPC0gYXJtYShOZXdfRkRJX3RzMiwgb3JkZXIgPSBjKDEsIDEpKQ0Kc3VtbWFyeShhcm1hX21vZGVsX3RzYSkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBWZXJpZmljYXIgcmVzaWR1b3MgZGUgQVJNQQ0KY2hlY2tyZXNpZHVhbHMoYXJtYV9tb2RlbF90c2EpDQpgYGANCg0KDQojIyMgUHJ1ZWJhcyBkZSDDs3JkZW5lcyBkZSBBUk1BDQoNCkVuIGJhc2UgYSBsb3MgdmFsb3JlcyBkZSBBSUMsIEFJQ2MgeSBCSUMsIGVsIG1vZGVsbyBBUk1BKDIsMSkgZXMgZWwgcXVlIHByZXNlbnRhIGxvcyBtZWpvcmVzIHJlc3VsdGFkb3MgY29uIHVuIEFJQyBkZSAxODIzLjUyMywgcXVlIGVzIGVsIG3DoXMgYmFqbyBlbnRyZSB0b2RvcyBsb3MgbW9kZWxvcyBwcm9iYWRvcyAoQVJNQSgxLDEpLCBBUk1BKDIsMiksIEFSTUEoMywzKSwgQVJNQSgxLDIpKS4gQXNtaXNtbywgbG9zIGVycm9yZXMgZGUgYWp1c3RlLCBjb21vIGVsIFJNU0UgKFJvb3QgTWVhbiBTcXVhcmVkIEVycm9yKSwgbXVlc3RyYSB1biBidWVuIGRlc2VtcGXDsW8gc2luIHNvYnJlYWp1c3RhcnNlIGEgbG9zIGRhdG9zLg0KDQpgYGB7cn0NCmFybWFfbW9kZWxfMV8xIDwtIEFyaW1hKE5ld19GRElfdHMyLCBvcmRlciA9IGMoMSwgMCwgMSkpICAjIEFSTUEoMSwxKQ0KYXJtYV9tb2RlbF8yXzIgPC0gQXJpbWEoTmV3X0ZESV90czIsIG9yZGVyID0gYygyLCAwLCAyKSkgICMgQVJNQSgyLDIpDQphcm1hX21vZGVsXzNfMyA8LSBBcmltYShOZXdfRkRJX3RzMiwgb3JkZXIgPSBjKDMsIDAsIDMpKSAgIyBBUk1BKDMsMykNCmFybWFfbW9kZWxfMV8yIDwtIEFyaW1hKE5ld19GRElfdHMyLCBvcmRlciA9IGMoMSwgMCwgMikpICAjIEFSTUEoMSwyKQ0KYXJtYV9tb2RlbF8yXzEgPC0gQXJpbWEoTmV3X0ZESV90czIsIG9yZGVyID0gYygyLCAwLCAxKSkgICMgQVJNQSgyLDEpDQoNCiMgQ29tcGFyYXIgbG9zIEFJQyBkZSBjYWRhIG1vZGVsbw0KYWljX3ZhbHVlcyA8LSBjKA0KICBBSUMoYXJtYV9tb2RlbF8xXzEpLA0KICBBSUMoYXJtYV9tb2RlbF8yXzIpLA0KICBBSUMoYXJtYV9tb2RlbF8zXzMpLA0KICBBSUMoYXJtYV9tb2RlbF8xXzIpLA0KICBBSUMoYXJtYV9tb2RlbF8yXzEpDQopDQoNCm5hbWVzKGFpY192YWx1ZXMpIDwtIGMoIkFSTUEoMSwxKSIsICJBUk1BKDIsMikiLCAiQVJNQSgzLDMpIiwgIkFSTUEoMSwyKSIsICJBUk1BKDIsMSkiKQ0KDQpwcmludChhaWNfdmFsdWVzKQ0KDQojIEVsZWdpbW9zIGVsIG1vZGVsbyBjb24gbWVub3IgQUlDDQpiZXN0X2FybWFfbW9kZWwgPC0gbGlzdCgNCiAgIkFSTUEoMSwxKSIgPSBhcm1hX21vZGVsXzFfMSwNCiAgIkFSTUEoMiwyKSIgPSBhcm1hX21vZGVsXzJfMiwNCiAgIkFSTUEoMywzKSIgPSBhcm1hX21vZGVsXzNfMywNCiAgIkFSTUEoMSwyKSIgPSBhcm1hX21vZGVsXzFfMiwNCiAgIkFSTUEoMiwxKSIgPSBhcm1hX21vZGVsXzJfMQ0KKVtbd2hpY2gubWluKGFpY192YWx1ZXMpXV0NCg0Kc3VtbWFyeShiZXN0X2FybWFfbW9kZWwpDQoNCiNBSUMgZGVsIGFybWEgc2VsZWNjaW9uYWRvIGNvbiBtZWpvciBBSUMgKGRlc3B1ZcyBcyBkZSBsYXMgY29tYmluYWNpb25lcyBmdWUgZWwgbWHMgXMgYmFqbykNCkFJQ19CRVNUQVJNQTwtQUlDKGFybWFfbW9kZWxfMV8yKQ0KYGBgDQoNCg0KIyMgQVJJTUENCg0KQWNvcmRlIGEgbGFzIHBydWViYXMgcmVhbGl6YWRhcywgc2UgZGV0ZXJtaW5hIHF1ZSBlbCBtb2RlbG8gQVJJTUEgbm8gZXMgZWwgbcOhcyBjb252ZW5pZW50ZSBkZWJpZG8gYSBsYSBlc3RhY2lvbmFyaWVkYWQgZGUgbGEgdmFyaWFibGUgZGVwZW5kaWVudGUuIEluY2x1c2l2ZSwgYWwgcmVhbGl6YXIgZWwgQVVUTyBBUklNQSBzZSBkZXRlcm1pbmEgcXVlIGxvcyBwYXLDoW1ldHJvcyBkZWJlbiBzZXIgKDAsMCwwKSBoYWNpZW5kbyBhbHVzacOzbiBhIHF1ZSBsYSBzZXJpZSBubyBwcmVzZW50YSBjYXJhY3RlcsOtc3RpY2FzIGZ1ZXJ0ZXMgZGUgYXV0b3JyZWdyZXNpw7NuIG8gbWVkaWEgbcOzdmlsLg0KDQpgYGB7cn0NCiMgQWp1c3RhciB1biBtb2RlbG8gQVJJTUEgKDEsMSwxKSBzb2JyZSBOZXdfRkRJX3RzMg0KQVJJTUFfbW9kZWwgPC0gQXJpbWEoTmV3X0ZESV90czIsIG9yZGVyID0gYygxLCAxLCAxKSkNCnByaW50KEFSSU1BX21vZGVsKQ0KcGxvdChBUklNQV9tb2RlbCRyZXNpZHVhbHMsIG1haW4gPSAiQVJJTUEoMSwxLDEpIC0gTmV3X0ZESV90czIiLCBjb2w9ImJsdWUiLCBsd2Q9MikNCg0KYWNmKEFSSU1BX21vZGVsJHJlc2lkdWFscywgbWFpbiA9ICJBQ0YgLSBBUklNQSgxLDEsMSkiKQ0KQm94LnRlc3QoQVJJTUFfbW9kZWwkcmVzaWR1YWxzLCBsYWcgPSAxLCB0eXBlID0gIkxqdW5nLUJveCIpICMgUHJ1ZWJhIGRlIGF1dG9jb3JyZWxhY2nDs24gZW4gcmVzaWR1b3MNCg0KIyBFc3RhY2lvbmFyaWVkYWQgZW4gbG9zIHJlc2lkdW9zDQphZGYudGVzdChBUklNQV9tb2RlbCRyZXNpZHVhbHMpDQpgYGANCg0KT2JzZXJ2YWNpb25lcyBkZWwgbW9kZWxvOg0KDQoqIHAgPSAxOiBJbmNsdXllIHVuIHTDqXJtaW5vIGF1dG9ycmVncmVzaXZvIChBUikuDQoNCiogZCA9IDE6IERpZmVyZW5jaWFjacOzbiBhcGxpY2FkYSB1bmEgdmV6IHBhcmEgZXN0YWNpb25hcmllZGFkLg0KDQoqIHEgPSAxOiBJbmNsdXllIHVuIHTDqXJtaW5vIGRlIG1lZGlhIG3Ds3ZpbCAoTUEpLg0KDQoqIExhIGdyw6FmaWNhIGRlIEFDRiBubyBwcmVzZW50YSBhdXRvY29ycmVsYWNpw7NuLiANCg0KKiBFbCB2YWxvciBwICgwLjk0NTkpIGVzID4gMC4wNSwgbG8gcXVlIGluZGljYSBxdWUgZWwgbW9kZWxvIEFSSU1BIG5vIG11ZXN0cmEgYXV0b2NvcnJlbGFjacOzbiBzZXJpYWwgZW4gbG9zIHJlc2lkdW9zLg0KDQoqIEVsIHRlc3QgQURGIHN1Z2llcmUgcXVlIGxvcyByZXNpZHVvcyBkZWwgQVJJTUEgc29uIGVzdGFjaW9uYXJpb3MsIHlhIHF1ZSBlbCB2YWxvciBwICgwLjAxKSBlcyA8IDAuMDUuDQoNCg0KIyMjIFBydWViYXMgZGUgw7NyZGVuZXMgZGUgQVJJTUENCg0KU2UgZGV0ZXJtaW5hIHF1ZSBlbiBjYXNvIGRlIHJlYWxpemFyIEFSSU1BIGVsIG1lam9yIG1vZGVsbyBlcyBBUklNQSgxLDEsMSksIHlhIHF1ZSB0aWVuZSBlbCBtZW5vciBBSUMgKDE4MDUuNDQpIHkgdW4gUk1TRSBkZSAzNzkxMC44Mi4NCg0KYGBge3J9DQphcmltYV9tb2RlbF8xXzFfMSA8LSBBcmltYShOZXdfRkRJX3RzMiwgb3JkZXIgPSBjKDEsIDEsIDEpKSAgIyBBUklNQSgxLDEsMSkNCmFyaW1hX21vZGVsXzJfMV8xIDwtIEFyaW1hKE5ld19GRElfdHMyLCBvcmRlciA9IGMoMiwgMSwgMSkpICAjIEFSSU1BKDIsMSwxKQ0KYXJpbWFfbW9kZWxfMV8xXzIgPC0gQXJpbWEoTmV3X0ZESV90czIsIG9yZGVyID0gYygxLCAxLCAyKSkgICMgQVJJTUEoMSwxLDIpDQphcmltYV9tb2RlbF8yXzFfMiA8LSBBcmltYShOZXdfRkRJX3RzMiwgb3JkZXIgPSBjKDIsIDEsIDIpKSAgIyBBUklNQSgyLDEsMikNCmFyaW1hX21vZGVsXzNfMV8zIDwtIEFyaW1hKE5ld19GRElfdHMyLCBvcmRlciA9IGMoMywgMSwgMykpICAjIEFSSU1BKDMsMSwzKQ0KYWljX3ZhbHVlcyA8LSBjKA0KICBBSUMoYXJpbWFfbW9kZWxfMV8xXzEpLA0KICBBSUMoYXJpbWFfbW9kZWxfMl8xXzEpLA0KICBBSUMoYXJpbWFfbW9kZWxfMV8xXzIpLA0KICBBSUMoYXJpbWFfbW9kZWxfMl8xXzIpLA0KICBBSUMoYXJpbWFfbW9kZWxfM18xXzMpDQopDQpuYW1lcyhhaWNfdmFsdWVzKSA8LSBjKCJBUklNQSgxLDEsMSkiLCAiQVJJTUEoMiwxLDEpIiwgIkFSSU1BKDEsMSwyKSIsICJBUklNQSgyLDEsMikiLCAiQVJJTUEoMywxLDMpIikNCnByaW50KGFpY192YWx1ZXMpDQpiZXN0X2FyaW1hX21vZGVsIDwtIGxpc3QoDQogICJBUklNQSgxLDEsMSkiID0gYXJpbWFfbW9kZWxfMV8xXzEsDQogICJBUklNQSgyLDEsMSkiID0gYXJpbWFfbW9kZWxfMl8xXzEsDQogICJBUklNQSgxLDEsMikiID0gYXJpbWFfbW9kZWxfMV8xXzIsDQogICJBUklNQSgyLDEsMikiID0gYXJpbWFfbW9kZWxfMl8xXzIsDQogICJBUklNQSgzLDEsMykiID0gYXJpbWFfbW9kZWxfM18xXzMNCilbW3doaWNoLm1pbihhaWNfdmFsdWVzKV1dDQpzdW1tYXJ5KGJlc3RfYXJpbWFfbW9kZWwpDQoNCiNBSUMgZGVsIEFSSU1BIHNlbGVjY2lvbmFkbyBjb24gbWVqb3IgQUlDIChkZXNwdWXMgXMgZGUgbGFzIGNvbWJpbmFjaW9uZXMgZnVlIGVsIG1hzIFzIGJham8pDQpBSUNfQkVTVEFSSU1BPC1BSUMoYXJpbWFfbW9kZWxfMV8xXzEpDQpgYGANCg0KDQojIyBWQVINCg0KU2UgcmVhbGl6w7MgdW4gbW9kZWxvIFZBUiB0ZW5pZW5kbyBjb21vIHZhcmlhYmxlIFkgTmV3X0ZESV9JbmZsb3dzLCB5IHVzYW5kbyBkZW50cm8gZGUgbGEgZXNwZWNpZmljYWNpw7NuIGRlbCBtb2RlbG8gbGFzIHZhcmlhYmxlczogZGlmZl9sb2dfZXhjaGFuZ2UsIGRpZmYyX2xvZ19pbnBjIHkgZGlmZl9sb2dfZXhwb3J0cy4NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCiMgQ29uc3RydWlyIGVsIGNvbmp1bnRvIGRlIGRhdG9zIGNvbiB2YXJpYWJsZXMgZXN0YWNpb25hcmlhcw0KdmFyX2RhdGEgPC0gY2JpbmQoDQogIGRmJE5ld19GRElfSW5mbG93cywgICAgICAgICMgWWEgZXMgZXN0YWNpb25hcmlhDQogIGRpZmZfbG9nX2V4Y2hhbmdlLCAgICAgICAgICMgUHJpbWVyYSBkaWZlcmVuY2lhDQogIGRpZmYyX2xvZ19pbnBjLCAgICAgICAgICAgICMgU2VndW5kYSBkaWZlcmVuY2lhDQogIGRpZmZfbG9nX2V4cG9ydHMgICAgICAgICAgICMgUHJpbWVyYSBkaWZlcmVuY2lhDQopDQoNCiMgQ29udmVydGlyIGEgZm9ybWF0byB0cw0KdmFyX2RhdGFfdHMgPC0gdHModmFyX2RhdGEsIHN0YXJ0ID0gYygyMDA2LDEpLCBmcmVxdWVuY3kgPSA0KQ0KYGBgDQoNClNlIGRldGVybWluw7MgcXVlIGVsIG1lam9yIG7Dum1lcm8gZGUgbGFncyBwYXJhIGVsIG1vZGVsbyBlcyAzIHVzYW5kbyBjb21vIGV2YWx1YWRvciBlbCB2bGFvciBkZSBBSUMuDQoNCmBgYHtyfQ0KIyBEZXRlcm1pbmFyIGVsIG1lam9yIG7Dum1lcm8gZGUgbGFncyB1c2FuZG8gQUlDDQpsYWdfc2VsZWN0aW9uIDwtIFZBUnNlbGVjdCh2YXJfZGF0YV90cywgbGFnLm1heCA9IDgsIHR5cGUgPSAiY29uc3QiKQ0KcHJpbnQobGFnX3NlbGVjdGlvbiRzZWxlY3Rpb24pDQpvcHRpbWFsX2xhZyA8LSBsYWdfc2VsZWN0aW9uJHNlbGVjdGlvblsiQUlDKG4pIl0NCmNvbG5hbWVzKHZhcl9kYXRhX3RzKSA8LSBjKCJOZXdfRkRJX0luZmxvd3MiLCAiZGlmZl9sb2dfZXhjaGFuZ2UiLCAiZGlmZjJfbG9nX2lucGMiLCAiZGlmZl9sb2dfZXhwb3J0cyIpDQpwcmludChjb2xuYW1lcyh2YXJfZGF0YV90cykpDQpgYGANCg0KDQojIyMgQWp1c3RhciBlbCBtb2RlbG8gVkFSIGNvbiBlbCBsYWcgw7NwdGltbw0KDQpBY29yZGUgYWwgbW9kZWxvLCBzZSBvYnNlcnZhIHF1ZTogDQoNCiogTmV3X0ZESV9JbmZsb3dzIG5vIGVzIGV4cGxpY2FkYSBwb3IgbmluZ3VuYSBvdHJhIHZhcmlhYmxlIHNpZ25pZmljYXRpdmEsIGxvIHF1ZSBzdWdpZXJlIHF1ZSBwb2Ryw61hIHNlciBtw6FzIGF1dMOzbm9tYSBvIGluZmx1aWRhIHBvciBmYWN0b3JlcyBleHRlcm5vcyBubyBjYXB0dXJhZG9zIGVuIGVzdGUgbW9kZWxvLg0KDQoqIEVsIHRpcG8gZGUgY2FtYmlvIChkaWZmX2xvZ19leGNoYW5nZSkgZXN0w6EgaW5mbHVlbmNpYWRvIHBvciBsYXMgZXhwb3J0YWNpb25lcyAoZGlmZl9sb2dfZXhwb3J0cy5sMSkuDQoNCiogTGEgaW5mbGFjacOzbiAoZGlmZjJfbG9nX2lucGMpIGVzIGFsdGFtZW50ZSBhdXRvcnJlZ3Jlc2l2YSB5IHRhbWJpw6luIGluZmx1ZW5jaWFkYSBwb3IgZWwgdGlwbyBkZSBjYW1iaW8gKGRpZmZfbG9nX2V4Y2hhbmdlLmwzKS4NCg0KKiBMYXMgZXhwb3J0YWNpb25lcyAoZGlmZl9sb2dfZXhwb3J0cykgZXN0w6FuIGRldGVybWluYWRhcyBwb3Igc3VzIHByb3Bpb3MgcmV6YWdvcywgbGEgaW5mbGFjacOzbiAoZGlmZjJfbG9nX2lucGMubDIsIGwzKSB5IGVsIHRpcG8gZGUgY2FtYmlvIChkaWZmX2xvZ19leGNoYW5nZS5sMikuIA0KDQpgYGB7cn0NCnZhcl9tb2RlbCA8LSBWQVIodmFyX2RhdGFfdHMsIHAgPSBvcHRpbWFsX2xhZywgdHlwZSA9ICJjb25zdCIpDQpwcmludChuYW1lcyh2YXJfbW9kZWwkeSkpDQpzdW1tYXJ5KHZhcl9tb2RlbCkNCmBgYA0KDQoNCiMjIyBQcnVlYmEgZGUgYXV0b2NvcnJlbGFjacOzbiBlbiByZXNpZHVvcyAoTGp1bmctQm94KQ0KDQpMYSBwcnVlYmEgZGUgYXV0b2NvcnJlbGFjacOzbiBlbiByZXNpZHVvcyAoTGp1bmctQm94KSBtb3N0csOzIHF1ZSBzb2xvIGxhIHZhcmlhYmxlIGRpZmYyX2xvZ19pbnBjIG11ZXN0cmEgYXV0b2NvcnJlbGFpY8OzbiBzZXJpYWwgZGUgbG9zIHJlc2lkdWFsZXMsIGxhcyBkZW3DoXMgdmFyaWFibGVzIHRpZW5lbiB1biBwLXZhbHVlID4gMC4wNSBpbmRpY2FuZG8gcXVlIG5vIHRpZW5lbiBhdXRvY29ycmVsYWNpw7NuIHNlcmlhbCBkZSByZXNpZHVhbGVzLg0KDQpgYGB7cn0NCnJlc2lkdWFsc192YXIgPC0gcmVzaWR1YWxzKHZhcl9tb2RlbCkNCmFwcGx5KHJlc2lkdWFsc192YXIsIDIsIGZ1bmN0aW9uKHgpIEJveC50ZXN0KHgsIGxhZyA9IDEwLCB0eXBlID0gIkxqdW5nLUJveCIpKQ0KQUlDX0JFU1RWQVIgPC0gQUlDKHZhcl9tb2RlbCkNCmBgYA0KDQoNCiMjIyBQcnVlYmEgZGUgQ2F1c2FsaWRhZCBkZSBHcmFuZ2VyDQoNCkxvcyBmYWN0b3JlcyBtYWNyb2Vjb27Ds21pY29zICh0aXBvIGRlIGNhbWJpbywgSU5QQywgZXhwb3J0YWNpb25lcykgYWZlY3RhbiBsYSBJRUQsIHBlcm8gbGEgSUVEIG5vIGluZmx1eWUgZW4gZWwgY29tcG9ydGFtaWVudG8gZnV0dXJvIGRlIGVzdGFzIHZhcmlhYmxlcy4gRW4gZWwgbW9kZWxvIFZBUiwgZWwgdGVzdCBkZSBHcmFuZ2VyIG11ZXN0cmEgcXVlIE5ld19GRElfSW5mbG93cyBubyB0aWVuZSB1biBlZmVjdG8gcHJlZGljdGl2byBzb2JyZSBkaWZmX2xvZ19leGNoYW5nZSwgZGlmZjJfbG9nX2lucGMsIHkgZGlmZl9sb2dfZXhwb3J0cyAocCA9IDAuNzg0NykuIFNpbiBlbWJhcmdvLCBkaWZmX2xvZ19leGNoYW5nZSAocCA9IDAuMDA3OSksIGRpZmYyX2xvZ19pbnBjIChwID0gMC4wMTg0KSB5IGRpZmZfbG9nX2V4cG9ydHMgKHAgPSAwLjAxMTgpIHPDrSBwcmVzZW50YW4gZXZpZGVuY2lhIGRlIEdyYW5nZXItY2F1c2FsaWRhZCBzb2JyZSBvdHJhcyB2YXJpYWJsZXMsIGxvIHF1ZSBzdWdpZXJlIHF1ZSBlc3RvcyBmYWN0b3JlcyBtYWNyb2Vjb27Ds21pY29zIHRpZW5lbiB1biBpbXBhY3RvIHByZWRpY3Rpdm8gc29icmUgZWwgY29tcG9ydGFtaWVudG8gZGUgbGEgaW52ZXJzacOzbiBleHRyYW5qZXJhIGRpcmVjdGEgeSBvdHJhcyB2YXJpYWJsZXMgZW4gZWwgbW9kZWxvLg0KDQpFbCB2YWxvciBwIGRlIGxhIHBydWViYSBGIGdsb2JhbCBkZWwgbW9kZWxvICgwLjU5NjYpIGluZGljYSBxdWUgTmV3X0ZESV9JbmZsb3dzIChmbHVqb3MgZGUgSUVEKSBubyBtdWVzdHJhIHVuYSBjYXVzYWxpZGFkIHBhcmEgbGFzIHZhcmlhYmxlcyBleHBsaWNhdGl2YXMgc2VsZWNjaW9uYWRhcyAoRXhjaGFuZ2UgUmF0ZSwgSU5QQyB5IEV4cG9ydHMpLiBMYSBwcnVlYmEgZGUgTGp1bmctQm94IG11ZXN0cmEgbGEgaW5kZXBlbmRlbmNpYSBkZSBlcnJvcmVzIGVuIGxhIG1heW9yw61hIGRlIGxhcyB2YXJpYWJsZXMsIGV4Y2VwdG8gZW4gZGlmZjJfbG9nX2lucGMuIEVzdGEgdmFyaWFibGUgbXVlc3RyYSBhdXRvY29ycmVsYWNpw7NuIHNpZ25pZmljYXRpdmEuIExhcyB2YXJpYWJsZXMgSU5QQyB5IEV4cG9ydHMgbXVlc3RyYW4gdW5hIHBvc2libGUgcmVsYWNpw7NuIGNvbiBOZXdfRkRJX0luZmxvd3MgZW4gZWwgdGVyY2VyIHJlemFnbywgYXVucXVlIGxhIGV2aWRlbmNpYSBlc3RhZMOtc3RpY2Egbm8gZXMgbG8gc3VmaWNpZW50ZW1lbnRlIGZ1ZXJ0ZSBjb21vIHBhcmEgc2VyIGNvbmNsdXllbnRlLg0KDQpgYGB7cn0NCmdyYW5nZXJfZmRpIDwtIGNhdXNhbGl0eSh2YXJfbW9kZWwsIGNhdXNlID0gIk5ld19GRElfSW5mbG93cyIpDQpwcmludChncmFuZ2VyX2ZkaSkNCg0KZ3Jhbmdlcl9leGNoYW5nZSA8LSBjYXVzYWxpdHkodmFyX21vZGVsLCBjYXVzZSA9ICJkaWZmX2xvZ19leGNoYW5nZSIpDQpwcmludChncmFuZ2VyX2V4Y2hhbmdlKQ0KDQpncmFuZ2VyX2lucGMgPC0gY2F1c2FsaXR5KHZhcl9tb2RlbCwgY2F1c2UgPSAiZGlmZjJfbG9nX2lucGMiKQ0KcHJpbnQoZ3Jhbmdlcl9pbnBjKQ0KDQpncmFuZ2VyX2V4cG9ydHMgPC0gY2F1c2FsaXR5KHZhcl9tb2RlbCwgY2F1c2UgPSAiZGlmZl9sb2dfZXhwb3J0cyIpDQpwcmludChncmFuZ2VyX2V4cG9ydHMpDQoNCmBgYA0KDQoNCiMjIFBhbmVsIFZBUg0KDQojIyMgRml4ZWQgRWZmZWN0cyBPTFMgUGFuZWwgVkFSIGVzdGltYXRpb24gY29uIFZhcmlhYmxlcyBPcmlnaW5hbGVzDQoNCkVsIG1vZGVsbyBkZSBQYW5lbCBWQVIgY29uIGVmZWN0b3MgZmlqb3MgbXVlc3RyYSBsYXMgc2lndWllbnRlcyByZWxhY2lvbmVzIGNsYXZlOg0KDQoqIE5ldyBGREkgSW5mbG93czogRWwgcmV6YWdvIGRlIE5ldyBGREkgSW5mbG93cyB0aWVuZSB1biBlZmVjdG8gbmVnYXRpdm8geSBzaWduaWZpY2F0aXZvIGVuIHN1IHByb3BpYSB2YXJpYWJsZSwgY29uIHVuIGNvZWZpY2llbnRlIGRlIC0wLjY3MzAgKHAgPCAwLjAwMSkuIEVzdG8gc3VnaWVyZSBxdWUgdW4gYXVtZW50byBlbiBsb3MgZmx1am9zIGRlIEZESSBlbiBlbCB0cmltZXN0cmUgYW50ZXJpb3IgZXN0w6EgYXNvY2lhZG8gY29uIHVuYSBkaXNtaW51Y2nDs24gZW4gbG9zIGZsdWpvcyBhY3R1YWxlcyBkZSBGREkuDQoNCiogRXhwb3J0czogRWwgcmV6YWdvIGRlIEV4cG9ydHMgdGllbmUgdW4gZWZlY3RvIG5lZ2F0aXZvIHkgc2lnbmlmaWNhdGl2byBlbiBsb3MgZmx1am9zIGRlIGV4cG9ydGFjacOzbiBhY3R1YWxlcyAoLTAuNDkzNywgcCA8IDAuMDUpLCBsbyBxdWUgaW5kaWNhIHF1ZSB1biBhdW1lbnRvIGVuIGxhcyBleHBvcnRhY2lvbmVzIGRlbCB0cmltZXN0cmUgYW50ZXJpb3IgcHVlZGUgcmVkdWNpciBsYXMgZXhwb3J0YWNpb25lcyBhY3R1YWxlcy4NCg0KTG9zIGNvZWZpY2llbnRlcyBkZSBJTlBDIHkgRXhjaGFuZ2UgUmF0ZSBubyBzb24gc2lnbmlmaWNhdGl2b3MgZW4gZXN0ZSBhbsOhbGlzaXMsIGxvIHF1ZSBzdWdpZXJlIHF1ZSBlc3RhcyB2YXJpYWJsZXMgbm8gdGllbmVuIHVuIGltcGFjdG8gZGlyZWN0byBpbXBvcnRhbnRlIGVuIGxvcyBmbHVqb3MgZGUgRkRJIG8gZXhwb3J0YWNpb25lcyBjdWFuZG8gc2UgY29udHJvbGFuIHBvciBsb3MgcmV6YWdvcy4NCg0KYGBge3J9DQpsaWJyYXJ5KHBhbmVsdmFyKQ0KZGZfb3JpZyA8LSBkZiAlPiUgZHBseXI6OnNlbGVjdChZZWFyLCBRdWFydGVyLCBOZXdfRkRJX0luZmxvd3MsIEV4Y2hhbmdlX1JhdGUsIElOUEMsIEV4cG9ydHMpDQoNClBhbmVsVkFSX0ZFIDwtIHB2YXJmZW9scyhkZXBlbmRlbnRfdmFycz1jKCJOZXdfRkRJX0luZmxvd3MiLCAiRXhwb3J0cyIpLGxhZ3M9MSwgZXhvZ192YXJzPWMoIklOUEMiLCAiRXhjaGFuZ2VfUmF0ZSIpLCB0cmFuc2Zvcm1hdGlvbj0iZGVtZWFuIiwgZGF0YT1kZl9vcmlnLCBwYW5lbF9pZGVudGlmaWVyPSBjKCJZZWFyIiwgIlF1YXJ0ZXIiKSkNCnN1bW1hcnkoUGFuZWxWQVJfRkUpDQpgYGANCg0KIyMjIEZpeGVkIEVmZmVjdHMgT0xTIFBhbmVsIFZBUiBlc3RpbWF0aW9uIGNvbiBMb2dhcml0bW9zDQoNCkVsIG1vZGVsbyBkZSBQYW5lbCBWQVIgY29uIHZhcmlhYmxlcyBleHBsY2lhdGl2YXMgdHJhbnNmb3JtYWRhcyBhIGxvZ2FydGltbyBjb24gZWZlY3RvcyBmaWpvcyBtdWVzdHJhIGxvIHNpZ3VpZW50ZToNCg0KKiBOZXcgRkRJIEluZmxvd3M6IEVsIHJlemFnbyBkZSBOZXcgRkRJIEluZmxvd3MgdGllbmUgdW4gZWZlY3RvIG5lZ2F0aXZvIHkgc2lnbmlmaWNhdGl2byBlbiBzdSBwcm9waWEgdmFyaWFibGUgY29uIHVuIGNvZWZpY2llbnRlIGRlIC0wLjY2MzMgKHAgPCAwLjAwMSksIGxvIHF1ZSBpbmRpY2EgcXVlIHVuIGF1bWVudG8gZW4gbG9zIGZsdWpvcyBkZSBGREkgZGVsIHRyaW1lc3RyZSBhbnRlcmlvciBzZSBhc29jaWEgY29uIHVuYSBjYcOtZGEgZW4gbG9zIGZsdWpvcyBhY3R1YWxlcyBkZSBGREkuDQoNCiogRXhwb3J0czogRWwgcmV6YWdvIGRlIGxvZ19FeHBvcnRzIHRpZW5lIHVuIGVmZWN0byBuZWdhdGl2byB5IHNpZ25pZmljYXRpdm8gZW4gbG9zIGZsdWpvcyBkZSBleHBvcnRhY2lvbmVzIGFjdHVhbGVzIGNvbiB1biBjb2VmaWNpZW50ZSBkZSAtMC40NjcxIChwIDwgMC4wNSkuIEVzdG8gc3VnaWVyZSBxdWUgdW4gYXVtZW50byBlbiBsYXMgZXhwb3J0YWNpb25lcyBkZWwgdHJpbWVzdHJlIGFudGVyaW9yIHJlZHVjZSBsYXMgZXhwb3J0YWNpb25lcyBhY3R1YWxlcy4NCg0KTGFzIHZhcmlhYmxlcyBFeGNoYW5nZSBSYXRlIHkgSU5QQyBubyB0aWVuZW4gZWZlY3RvcyBzaWduaWZpY2F0aXZvcyBlbiBsb3MgZmx1am9zIGRlIEZESSBuaSBlbiBsYXMgZXhwb3J0YWNpb25lcyBlbiBlc3RlIG1vZGVsbywgeWEgcXVlIHN1cyBjb2VmaWNpZW50ZXMgbm8gc29uIGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdm9zLg0KDQpgYGB7cn0NCmRmX2xvZyA8LSBkZiAlPiUgZHBseXI6OnNlbGVjdChZZWFyLCBRdWFydGVyLCBOZXdfRkRJX0luZmxvd3MsIGxvZ19FeGNoYW5nZV9SYXRlLCBsb2dfSU5QQywgbG9nX0V4cG9ydHMpDQoNCiMgRXN0aW1hciBtb2RlbG8gUGFuZWwgVkFSIGNvbiBlZmVjdG9zIGZpam9zDQpQYW5lbFZBUl9GRV9sb2cgPC0gcHZhcmZlb2xzKA0KICBkZXBlbmRlbnRfdmFycyA9IGMoIk5ld19GRElfSW5mbG93cyIsICJsb2dfRXhwb3J0cyIpLA0KICBsYWdzID0gMSwNCiAgZXhvZ192YXJzID0gYygibG9nX0V4Y2hhbmdlX1JhdGUiLCAibG9nX0lOUEMiKSwNCiAgdHJhbnNmb3JtYXRpb24gPSAiZGVtZWFuIiwNCiAgZGF0YSA9IGRmX2xvZywNCiAgcGFuZWxfaWRlbnRpZmllciA9IGMoIlllYXIiLCAiUXVhcnRlciIpDQopDQoNCnN1bW1hcnkoUGFuZWxWQVJfRkVfbG9nKQ0KYGBgDQoNCiMjIyBFc3RpbWFyIG1vZGVsbyBQYW5lbCBWQVIgY29uIEdNTQ0KDQpFbCBtb2RlbG8gcHJlc2VudGEgZXJyb3JlcyBlc3TDoW5kYXIgYWx0b3MgeSBsb3MgcC12YWx1ZXMgZGUgSGFuc2VuIGluZGljYW4gcXVlIGxvcyBpbnN0cnVtZW50b3MgcHVlZGVuIG5vIHNlciB2w6FsaWRvczsgYWRlbcOhcyBzZSBvYnNlcnZhIHF1ZSBuaW5ndW5hIHZhcmlhYmxlIHBhcmVjZSB0ZW5lciB1biBpbXBhY3RvIGVzdGFkw61zdGljbyBjb25maWFibGU6IA0KKiBsYWcxX05ld19GRElfSW5mbG93czogLTAuMjU3NyAoY29uIGVycm9yIGVzdMOhbmRhciAwLjIwNDUpIOKGkiBJbmRpY2EgdW5hIGxldmUgYXV0b2NvcnJlbGFjacOzbiBuZWdhdGl2YSwgcGVybyBubyBlcyBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZvLg0KDQoqIGxvZ19FeGNoYW5nZV9SYXRlLCBsb2dfRXhwb3J0cywgbG9nX0lOUEM6IFRvZG9zIGNvbiBjb2VmaWNpZW50ZSDiiYggMCB5IGVycm9yZXMgZXN0w6FuZGFyIGV4dHJlbWFkYW1lbnRlIGdyYW5kZXMgbG8gcXVlIGluZGljYSBwcm9ibGVtYXMgbnVtw6lyaWNvcyBzZXJpb3MuDQoNCiogSGFuc2VuIFRlc3Q6IEluZGljYSBzb2JyZWlkZW50aWZpY2FjacOzbiBleHRyZW1hIHkgcHJvYmxlbWFzIGNvbiBsb3MgaW5zdHJ1bWVudG9zLg0KDQpgYGB7cn0NClBBTkVMVkFSX0ZFX0dNTSA8LSBwdmFyZ21tKA0KICBkZXBlbmRlbnRfdmFycyA9IGMoIk5ld19GRElfSW5mbG93cyIpLA0KICBsYWdzPTEsIA0KICBwcmVkZXRfdmFycz1jKCJsb2dfRXhjaGFuZ2VfUmF0ZSIsICJsb2dfRXhwb3J0cyIpLCANCiAgZXhvZ192YXJzPWMoImxvZ19JTlBDIiksIA0KICB0cmFuc2Zvcm1hdGlvbj0iZmQiLCANCiAgZGF0YT1kZl9sb2cgLCANCiAgcGFuZWxfaWRlbnRpZmllcj1jKCJZZWFyIiwgIlF1YXJ0ZXIiKSwgDQogIHN0ZXBzPWMoIm9uZXN0ZXAiKQ0KKQ0Kc3VtbWFyeShQQU5FTFZBUl9GRV9HTU0pDQpgYGANCg0KIyMjIFBydWViYSBkZSBDaG93DQoNCkVuIGVzdGUgY2FzbywgZWwgcC12YWxvciAoMC4yOTY2KSBlcyBtYXlvciBxdWUgMC4wNSwgcG9yIGxvIHF1ZSBOTyBzZSByZWNoYXphIGxhIGhpcMOzdGVzaXMgbnVsYS4gRXN0byBpbmRpY2EgcXVlIG5vIGhheSBldmlkZW5jaWEgZGUgdW4gY2FtYmlvIGVzdHJ1Y3R1cmFsIHNpZ25pZmljYXRpdm8gZW4gbGEgcmVsYWNpw7NuIGVudHJlIE5ld19GRElfSW5mbG93cyB5IGxhcyB2YXJpYWJsZXMgZXhwbGljYXRpdmFzIChsb2dfRXhjaGFuZ2VfUmF0ZSwgbG9nX0lOUEMsIGxvZ19FeHBvcnRzKS4NCg0KYGBge3J9DQpjaG93X3Rlc3QgPC0gc2N0ZXN0KE5ld19GRElfSW5mbG93cyB+IGxvZ19FeGNoYW5nZV9SYXRlICsgbG9nX0lOUEMgKyBsb2dfRXhwb3J0cywgDQogICAgICAgICAgICAgICAgICAgIHR5cGUgPSAiQ2hvdyIsIHBvaW50ID0gMTgsIGRhdGEgPSBkZikNCnByaW50KGNob3dfdGVzdCkNCmBgYA0KDQojIyMgQ2FsY3VsbyBtYW51YWwgZGUgQUlDIHBhcmEgbW9kZWxvcyBQYW5lbCBWQVINCmBgYHtyfQ0KIyBFeHRyYWVyIHJlc2lkdWFsZXMNCnJlc2lkdWFsc19kZiA8LSBhcy5kYXRhLmZyYW1lKHJlc2lkdWFscyhQYW5lbFZBUl9GRSkpDQoNCiMgQ2FsY3VsYXIgU1NFDQpTU0UgPC0gc3VtKHJlc2lkdWFsc19kZl4yLCBuYS5ybSA9IFRSVUUpDQoNCiMgTnXMgW1lcm8gZGUgb2JzZXJ2YWNpb25lcyB5IHBhcmHMgW1ldHJvcyBlc3RpbWFkb3MNCm4gPC0gbnJvdyhkZl9vcmlnKQ0KayA8LSBsZW5ndGgoY29lZihQYW5lbFZBUl9GRSkpICAjIE51zIFtZXJvIGRlIGNvZWZpY2llbnRlcyBlc3RpbWFkb3MNCg0KIyBDYWxjdWxhciBBSUMgbWFudWFsbWVudGUNCkFJQ19QYW5lbFZBUl9GRSA8LSBuICogbG9nKFNTRSAvIG4pICsgMiAqIGsNCmBgYA0KDQpgYGB7cn0NCiMgRXh0cmFlciByZXNpZHVhbGVzDQpyZXNpZHVhbHNfZGYyIDwtIGFzLmRhdGEuZnJhbWUocmVzaWR1YWxzKFBhbmVsVkFSX0ZFX2xvZykpDQoNCiMgQ2FsY3VsYXIgU1NFDQpTU0UyIDwtIHN1bShyZXNpZHVhbHNfZGYyXjIsIG5hLnJtID0gVFJVRSkNCg0KIyBOdcyBbWVybyBkZSBvYnNlcnZhY2lvbmVzIHkgcGFyYcyBbWV0cm9zIGVzdGltYWRvcw0KbjIgPC0gbnJvdyhkZl9sb2cpDQprMiA8LSBsZW5ndGgoY29lZihQYW5lbFZBUl9GRV9sb2cpKSAgIyBOdcyBbWVybyBkZSBjb2VmaWNpZW50ZXMgZXN0aW1hZG9zDQoNCiMgQ2FsY3VsYXIgQUlDIG1hbnVhbG1lbnRlDQpBSUNfUGFuZWxWQVJfRkVfbG9nIDwtIG4yICogbG9nKFNTRTIgLyBuMikgKyAyICogazINCmBgYA0KDQoNCiMgUHJ1ZWJhcyBkZSBEaWFnbsOzc3RpY28NCg0KTWVkaWFudGUgcHJ1ZWJhcyBkZSBkaWFnbsOzc3RpY28sIGlkZW50aWZpY2FyIGxhIHBvc2libGUgcHJlc2VuY2lhIGRlIGxhcyBzaWd1aWVudGVzIGNhcmFjdGVyw61zdGljYXMgZGUgbGEgc2VyaWU6DQoNCiMjIEF1dG9jb3JyZWxhY2nDs24gU2VyaWFsIChzZXJpYWwgY29ycmVsYXRpb24pDQoNClRvZG9zIGxvcyBtb2RlbG9zIHRpZW5lbiBwLXZhbHVlcyA+IDAuMDUsIGxvIHF1ZSBzaWduaWZpY2EgcXVlIG5vIGhheSBldmlkZW5jaWEgZGUgYXV0b2NvcnJlbGFjacOzbiBzZXJpYWwgZW4gbG9zIHJlc2lkdW9zLg0KDQpgYGB7cn0NCnRlc3RfYXV0b2NvcnJlbGFjaW9uIDwtIGZ1bmN0aW9uKG1vZGVsbykgew0KICByZXNpZHVvcyA8LSByZXNpZHVhbHMobW9kZWxvKQ0KICAgIGlmIChpcy5tYXRyaXgocmVzaWR1b3MpKSB7DQogICAgcF92YWx1ZXMgPC0gYXBwbHkocmVzaWR1b3MsIDIsIGZ1bmN0aW9uKHgpIEJveC50ZXN0KHgsIGxhZyA9IDEwLCB0eXBlID0gIkxqdW5nLUJveCIpJHAudmFsdWUpDQogIH0gZWxzZSB7DQogICAgcF92YWx1ZXMgPC0gQm94LnRlc3QocmVzaWR1b3MsIGxhZyA9IDEwLCB0eXBlID0gIkxqdW5nLUJveCIpJHAudmFsdWUNCiAgfQ0KICANCiAgcmV0dXJuKHBfdmFsdWVzKQ0KfQ0KDQojIEFwbGljYXIgbGEgcHJ1ZWJhIGRlIGF1dG9jb3JyZWxhY2nDs24gYSBjYWRhIG1vZGVsbw0KYXV0b2NvcnJfcmVzdWx0cyA8LSBkYXRhLmZyYW1lKA0KICBNb2RlbG8gPSBjKCJBUk1BIiwgIkFSSU1BIiwgIlZBUiIsICJQYW5lbFZBUl9GRV9sb2ciLCAiUGFuZWxWQVJfRkUiKSwNCiAgQXV0b2NvcnJfcF92YWx1ZSA9IGMoDQogICAgdGVzdF9hdXRvY29ycmVsYWNpb24oYXJtYV9tb2RlbF8xXzIpLA0KICAgIHRlc3RfYXV0b2NvcnJlbGFjaW9uKGFyaW1hX21vZGVsXzFfMV8xKSwNCiAgICBtZWFuKHRlc3RfYXV0b2NvcnJlbGFjaW9uKHZhcl9tb2RlbCkpLCAgIyBQcm9tZWRpbyBkZSBwLXZhbHVlcyBlbiBWQVINCiAgICBtZWFuKHRlc3RfYXV0b2NvcnJlbGFjaW9uKFBhbmVsVkFSX0ZFX2xvZykpLCAgIyBQcm9tZWRpbyBkZSBwLXZhbHVlcyBlbiBQYW5lbFZBUl9GRV9sb2cNCiAgICBtZWFuKHRlc3RfYXV0b2NvcnJlbGFjaW9uKFBhbmVsVkFSX0ZFKSkgICMgUHJvbWVkaW8gZGUgcC12YWx1ZXMgZW4gUGFuZWxWQVJfRkUNCiAgKQ0KKQ0KDQpwcmludChhdXRvY29ycl9yZXN1bHRzKQ0KYGBgDQoNCiMjIEVzdGFjaW9uYXJpZWRhZCAoc3RhdGlvbmFyeSkgDQoNClNlIGJ1c2NhIHF1ZSBsb3MgbW9kZWxvcyB0ZW5nYW4gcmVzaWR1b3MgZXN0YWNpb25hcmlvcyBwb3JxdWUgZXN0byBpbmRpY2EgcXVlIGVsIG1vZGVsbyBjYXB0dXJhIGRlIGZvcm1hIGVmaWNpZW50ZSBsYSBkaW7DoW1pY2EgZGUgbGEgc2VyaWUgZGUgdGllbXBvLg0KDQoqIE1vZGVsb3MgY29uIHJlc2lkdW9zIGVzdGFjaW9uYXJpb3MgKHAg4omkIDAuMDUpOiBBUk1BICgwLjAxNjcpLCBBUklNQSAoMC4wMTAwKSwgVkFSICgwLjAxNTkpLiANCiogTW9kZWxvcyBjb24gcmVzaWR1b3Mgbm8gIGVzdGFjaW9uYXJpb3MgKHAgPiAwLjA1KTogUGFuZWxWQVJfRkVfbG9nICgwLjA3NDkpIHkgUGFuZWxWQVJfRkUgKDAuMTQzOSkuDQoNCmBgYHtyfQ0KdGVzdF9lc3RhY2lvbmFyaWVkYWQgPC0gZnVuY3Rpb24obW9kZWxvKSB7DQogIHJlc2lkdW9zIDwtIHJlc2lkdWFscyhtb2RlbG8pDQogICAgaWYgKGlzLm1hdHJpeChyZXNpZHVvcykpIHsNCiAgICBwX3ZhbHVlcyA8LSBhcHBseShyZXNpZHVvcywgMiwgZnVuY3Rpb24oeCkgYWRmLnRlc3QoYXMubnVtZXJpYyh4KSkkcC52YWx1ZSkNCiAgfSBlbHNlIHsNCiAgICBwX3ZhbHVlcyA8LSBhZGYudGVzdChhcy5udW1lcmljKHJlc2lkdW9zKSkkcC52YWx1ZQ0KICB9DQogIA0KICByZXR1cm4ocF92YWx1ZXMpDQp9DQoNCiMgQXBsaWNhciBsYSBwcnVlYmEgZGUgZXN0YWNpb25hcmllZGFkIGEgY2FkYSBtb2RlbG8NCnN0YXRpb25hcml0eV9yZXN1bHRzIDwtIGRhdGEuZnJhbWUoDQogIE1vZGVsbyA9IGMoIkFSTUEiLCAiQVJJTUEiLCAiVkFSIiwgIlBhbmVsVkFSX0ZFX2xvZyIsICJQYW5lbFZBUl9GRSIpLA0KICBTdGF0aW9uYXJpdHlfcF92YWx1ZSA9IGMoDQogICAgdGVzdF9lc3RhY2lvbmFyaWVkYWQoYXJtYV9tb2RlbF8xXzIpLA0KICAgIHRlc3RfZXN0YWNpb25hcmllZGFkKGFyaW1hX21vZGVsXzFfMV8xKSwNCiAgICBtZWFuKHRlc3RfZXN0YWNpb25hcmllZGFkKHZhcl9tb2RlbCkpLCAgIyBQcm9tZWRpbyBkZSBwLXZhbHVlcyBlbiBWQVINCiAgICBtZWFuKHRlc3RfZXN0YWNpb25hcmllZGFkKFBhbmVsVkFSX0ZFX2xvZykpLCAgIyBQcm9tZWRpbyBkZSBwLXZhbHVlcyBlbiBQYW5lbFZBUl9GRV9sb2cNCiAgICBtZWFuKHRlc3RfZXN0YWNpb25hcmllZGFkKFBhbmVsVkFSX0ZFKSkgICMgUHJvbWVkaW8gZGUgcC12YWx1ZXMgZW4gUGFuZWxWQVJfRkUNCiAgKQ0KKQ0KDQpwcmludChzdGF0aW9uYXJpdHlfcmVzdWx0cykNCmBgYA0KDQoNCg0KIyBTZWxlY2Npw7NuIGRlIE1vZGVsbyBlIEludGVycHJldGFjacOzbiBkZSBSZXN1bHRhZG9zOg0KDQpDb24gYmFzZSBlbiBsYXMgcHJ1ZWJhcyBkZSBkaWFnbsOzc3RpY28sIHkgbGEgZXN0aW1hY2nDs24gZGUgbG9zIHJlc3VsdGFkb3MsIHNlIHNlbGVjY2lvbmFuIGxvcyByZXN1bHRhZG9zIGRlIGxhIGVzdGltYWNpw7NuIGRlbCBtb2RlbG8gZGUgc2VyaWVzIGRlIHRpZW1wbyBxdWUgbXVlc3RyYSBlbCBtZWpvciBkZXNlbXBlw7FvLg0KDQpFbCBtZWpvciBtb2RlbG8gZXMgZWwgcXVlIG5vIHRpZW5lIGF1dG9jb3JyZWxhY2nDs24gc2VyaWFsIGVuIGxvcyByZXNpZHVvcywgdGVuZ2EgcmVzaWR1b3MgZXN0YWNpb25hcmlvcyB5IHRlbmdhIGVsIG1lbm9yIEFJQywgcG9yIGxvIHF1ZSwgZWwgbW9kZWxvIHF1ZSBtZWpvciBjdW1wbGnDsyBjb24gZXN0YXMgY29uZGljaW9uZXMgZXMgZWwgbW9kZWxvIFZBUi4NCg0KUHJpbWVyYW1lbnRlLCBzZSBvYnNlcnZhbiBsb3MgQUlDIGRlIHRvZG9zIGxvcyBtb2RlbG9zIGdlbmVyYWRvcw0KDQpgYGB7cn0NCmRmX0FJQyA8LSBkYXRhLmZyYW1lKA0KICBNb2RlbG8gPSBjKCJBUk1BIiwgIkFSSU1BIiwgIlZBUiIsICJQYW5lbFZBUl9GRV9sb2ciLCAiUGFuZWxWQVJfRkUiKSwNCiAgQUlDX1ZhbG9yID0gYyhBSUNfQkVTVEFSTUEsIEFJQ19CRVNUQVJJTUEsIEFJQ19CRVNUVkFSLCBBSUNfUGFuZWxWQVJfRkVfbG9nLCBBSUNfUGFuZWxWQVJfRkUpDQopDQoNCnByaW50KGRmX0FJQykNCmBgYA0KDQpQb3N0ZXJpb3JtZW50ZSwgc2Ugb2JzZXJ2YW4gbG9zIEFJQyBsb3MgbW9kZWxvcyDDs3B0aW1vcyBhY29yZGUgYWwgYW7DoWxpc2lzIGV4cGxvcmF0b3JpbyByZWFsaXphZG8sIGFudGUgbG8gY3VhbCBzaWd1ZSBwcmVvZG1pbmFuZG8gZWwgbW9kZWxvIFZBUiBwb3IgdGVuZXIgZWwgbWVub3IgQUlDIHkgUk1TRS4NCg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkoTWV0cmljcykNCg0KIyBMaXN0YSBkZSBtb2RlbG9zDQptb2RlbG9zIDwtIGxpc3QoDQogICJBUk1BKDEsMSkiID0gYXJtYV9tb2RlbF8xXzEsDQogICJBUk1BKDIsMikiID0gYXJtYV9tb2RlbF8yXzIsDQogICJBUk1BKDMsMykiID0gYXJtYV9tb2RlbF8zXzMsDQogICJBUk1BKDEsMikiID0gYXJtYV9tb2RlbF8xXzIsDQogICJBUk1BKDIsMSkiID0gYXJtYV9tb2RlbF8yXzENCikNCg0KIyBGdW5jacOzbiBwYXJhIGNhbGN1bGFyIFJNU0UNCmdldF9ybXNlIDwtIGZ1bmN0aW9uKG1vZGVsLCBkYXRvc19yZWFsZXMpIHsNCiAgcHJlZHMgPC0gZml0dGVkKG1vZGVsKSAgDQogIHJldHVybihybXNlKGRhdG9zX3JlYWxlcywgcHJlZHMpKQ0KfQ0KDQojIENhbGN1bGFyIEFJQyB5IFJNU0UNCnJlc3VsdGFkb3MgPC0gZGF0YS5mcmFtZSgNCiAgQUlDID0gc2FwcGx5KG1vZGVsb3MsIEFJQyksDQogIFJNU0UgPSBzYXBwbHkobW9kZWxvcywgZ2V0X3Jtc2UsIGRhdG9zX3JlYWxlcyA9IE5ld19GRElfdHMyKQ0KKQ0KDQojIE1vZGVsbyBWQVINCkFJQ19CRVNUVkFSIDwtIEFJQyh2YXJfbW9kZWwpDQpmaXR0ZWRfdmFscyA8LSBhcy5kYXRhLmZyYW1lKGZpdHRlZCh2YXJfbW9kZWwpKQ0KaW5fc2FtcGxlX3ByZWQgPC0gZml0dGVkX3ZhbHMkTmV3X0ZESV9JbmZsb3dzDQpkZl9hbGlnbmVkIDwtIGRmWy1jKDE6MyksIF0NCnZhcl9ybXNlIDwtIHJtc2UoZGZfYWxpZ25lZCROZXdfRkRJX0luZmxvd3MsIGluX3NhbXBsZV9wcmVkKQ0KDQojIEZpbGEgZGVsIE1vZGVsbyBWQVINCnZhcl9yb3cgPC0gZGF0YS5mcmFtZSgNCiAgQUlDID0gQUlDX0JFU1RWQVIsDQogIFJNU0UgPSB2YXJfcm1zZSwNCiAgcm93Lm5hbWVzID0gIlZBUl9Nb2RlbCINCikNCg0KIyBSZXN1bHRhZG9zDQpyZXN1bHRhZG9zIDwtIHJiaW5kKHJlc3VsdGFkb3MsIHZhcl9yb3cpDQpyZXN1bHRhZG9zIDwtIHJlc3VsdGFkb3MgJT4lDQogIGFycmFuZ2UoQUlDLCBSTVNFKQ0KaGVhZChyZXN1bHRhZG9zLCAzKQ0KYGBgDQoNCg0KIyMgUmVhbGl6YXIgZWwgcHJvbsOzc3RpY28gZGUgbGFzIHZhcmlhYmxlcyBkZSBpbnRlcsOpcyByZWxhY2lvbmFkYXMgY29uIGVsIE5lYXJzaG9yaW5nIGVuIE3DqXhpY28gcGFyYSBsb3MgcHLDs3hpbW9zIDQgcGVyw61vZG9zLCBpbmNsdXllbmRvIHVuIGdyw6FmaWNvIGRlIHNlcmllcyBkZSB0aWVtcG8geSB1bmEgZGVzY3JpcGNpw7NuIGRlIGxhIHRlbmRlbmNpYSBwcm95ZWN0YWRhLg0KDQpTZSBkZWNpZGnDsyByZWFsaXphciBlbCBwcm9uw7NzdGljbyBwYXJhIDggcGVyaW9kb3MgZXMgZGVjaXIgcGFyYSAyIGHDsW9zLCB5YSBxdWUgY29uc2lkZXJhbW9zIHF1ZSB1biBhbsOhbGlzaXMgZGUgOCB0cmltZXN0cmVzIHBvZHLDrWEgcGVybWl0aXIgYSBsYXMgZW1wcmVzYXMgaW50ZXJlc2FkYXMsIGV2YWx1YXIgdGVuZGVuY2lhcyBhIG1lZGlhbm8gcGxhem8geSBhc8OtIGV2aXRhciBxdWUgc2UgdG9tZW4gZGVjaXNpb25lcyBiYXNhZGFzIHNvbG8gZW4gdmFyaWFjaW9uZXMgYSBjb3J0byBwbGF6bywgYXPDrW1pc21vIGNvbiBsb3MgcmVzdWx0YWRvcyBkZWwgbW9kZWxvLCBpZGVudGlmaWNhbW9zIHF1ZSBsYSBwcmVkaWNjacOzbiBhIGNvcnRvIHBsYXpvIHBhcmVjZSBzZXIgbcOhcyB2b2zDoXRpbCwgcG9yIGxvIHF1ZSBzZSB0b21vIGNvbW8gcHVudG8gZGUgcmVmZXJlbmNpYSwgYSBwb2RlciBhbmFsaXphciBvdHJvcyBwZXJpb2RvcyBhIG1lZGlhbm8gcGxhem8uDQoNClNlIGNhbGN1bMOzIGVsIHByb21lZGlvIGRlIE5ld19GRElfSW5mbG93cywgeSBjb21wYXJhbmRvIGxvcyBpbnRlcnZhbG9zIHJlc3VsdGFudGVzIGRlIGNhZGEgcGVyaW9kbyBkZWwgbW9kZWxvLCBlbCBtb2RlbG8gVkFSIHBhcmVjZSBjYXB0dXJhciBiaWVuIGVsIHByb21lZGlvIGdlbmVyYWwsIGF1bnF1ZSBtdWVzdHJhIGNpZXJ0YXMgZmx1Y3R1YWNpb25lcyBlbiBsb3MgcHJpbWVyb3MgMyBwZXJpb2Rvcywgc2luIGVtYmFyZ28sIGEgcGFydGlyIGRlbCA0dG8gcGVyaW9kbyAsIGxvcyB2YWxvcmVzIHNlIGFjZXJjYW4gbXVjaG8gYSBsYSBtZWRpYSwgcG9yIGxvIHF1ZSwgZWwgbW9kZWxvIHBvZHLDrWEgZXN0YXIgYWRhcHTDoW5kb3NlIG3DoXMgaGFjaWEgdW4gdmFsb3IgbcOhcyBlc3RhYmxlIGRlIGxhIG1lZGlhIGRlIGxhIHNlcmllIG9yaWdpbmFsLCBhIHBhcnRpciBkZSBhbmFsaXphciBtw6FzIHBlcmlvZG9zLCBlcyBkZWNpciwgcXVlIGRlc3B1w6lzIGRlIDMgdHJpbWVzdHJlcywgc2UgbG9ncmFyw61hIG9idGVuZXIgZXN0YWJpbGlkYWQuDQoNCmBgYHtyfQ0KbWVkaWFfbmV3ZmRpPC0gbWVhbihkZiROZXdfRkRJX0luZmxvd3MpDQptZWRpYV9uZXdmZGkNCmBgYA0KDQpgYGB7cn0NCiMgUHJvbsOzc3RpY28gcGFyYSA4IHBlcmlvZG9zDQpmb3JlY2FzdF92YXIgPC0gcHJlZGljdCh2YXJfbW9kZWwsIG4uYWhlYWQgPSA4LCBjaSA9IDAuOTUpDQpmYW5jaGFydChmb3JlY2FzdF92YXIsIG5hbWVzID0gIk5ld19GRElfSW5mbG93cyIsIG1haW4gPSAiRm9yZWNhc3QgLSBOZXdfRkRJX0luZmxvd3MiLCB4bGFiID0gIlRpbWUiLCB5bGFiID0gIk5ld19GRElfSW5mbG93cyIpDQpwcmludChmb3JlY2FzdF92YXIkZmNzdCROZXdfRkRJX0luZmxvd3MpDQpgYGANCg0KDQojIyBEZSBhY3VlcmRvIGFsIHByb27Ds3N0aWNvIGFudGVyaW9yLCDCv2PDs21vIGVzIGVsIGVzY2VuYXJpbyBvcHRpbWlzdGEgdnMuIGVzY2VuYXJpbyBwZXNpbWlzdGEgZGVsIHBvc2libGUg4oCcTmVhcnNob3JpbmfigJ0gcGFyYSBlbCBjYXNvIGRlIE3DqXhpY28/DQoNCkF1bnF1ZSBleGlzdGUgaW5jZXJ0aWR1bWJyZSwgbGEgdGVuZGVuY2lhIGdlbmVyYWwgZmF2b3JlY2UgZWwgY3JlY2ltaWVudG8gZGUgbGEgSUVEIGVuIE3DqXhpY28sIGNvbiByaWVzZ29zIGFzb2NpYWRvcyBhIGxhIHZvbGF0aWxpZGFkIGVjb27Ds21pY2EgeSBwb2zDrXRpY2EuDQoNCiogRXNjZW5hcmlvIG9wdGltaXN0YTogTGEgSUVEIGNyZWNlcsOtYSBzaWduaWZpY2F0aXZhbWVudGUsIHN1cGVyYW5kbyBsYXMgMTM1LDAwMCB1bmlkYWRlcywgaW1wdWxzYWRhIHBvciBjb25kaWNpb25lcyBmYXZvcmFibGVzIGVuIGludmVyc2nDs24gZXh0cmFuamVyYSB5IGVzdGFiaWxpZGFkIG1hY3JvZWNvbsOzbWljYS4NCg0KKiBFc2NlbmFyaW8gcmVhbGlzdGE6IFNlIGVzcGVyYSBxdWUgbGEgSUVEIGZsdWN0w7plIGVudHJlIDM5LDA0MiB5IDY5LDAwNCB1bmlkYWRlcywgY29uIGxhIG1heW9yw61hIGRlIGxvcyB2YWxvcmVzIHN1cGVyYW5kbyBsYSBtZWRpYSBoaXN0w7NyaWNhLCBsbyBxdWUgaW5kaWNhcsOtYSB1biBjcmVjaW1pZW50byBzb3N0ZW5pZG8sIGF1bnF1ZSBjb24gY2llcnRhIGluY2VydGlkdW1icmUuDQoNCiogRXNjZW5hcmlvIHBlc2ltaXN0YTogTGEgSUVEIHBvZHLDrWEgY2FlciBoYXN0YSAtMzgsMzAxIHVuaWRhZGVzLCBsbyBxdWUgcmVmbGVqYXLDrWEgdW4gcmV0cm9jZXNvIHByZW9jdXBhbnRlIGRlYmlkbyBhIHBvc2libGVzIGZhY3RvcmVzIGFkdmVyc29zIGVuIGxhIGVjb25vbcOtYSB5IGVsIGVudG9ybm8gcG9sw610aWNvLg0KDQpgYGB7cn0NCiMgQ3JlYXIgdW4gZGF0YSBmcmFtZSBjb24gbG9zIGVzY2VuYXJpb3MNCmVzY2VuYXJpb3NfZGYgPC0gZGF0YS5mcmFtZSgNCiAgUGVyaW9kbyA9IDE6OCwNCiAgRXNjZW5hcmlvX1Blc2ltaXN0YSA9IGZvcmVjYXN0X3ZhciRmY3N0JE5ld19GRElfSW5mbG93c1ssICJsb3dlciJdLCAgIyBMw61taXRlIGluZmVyaW9yDQogIEVzY2VuYXJpb19SZWFsID0gZm9yZWNhc3RfdmFyJGZjc3QkTmV3X0ZESV9JbmZsb3dzWywgImZjc3QiXSwgICAgICAgICMgUHJlZGljY2nDs24gY2VudHJhbA0KICBFc2NlbmFyaW9fT3B0aW1vID0gZm9yZWNhc3RfdmFyJGZjc3QkTmV3X0ZESV9JbmZsb3dzWywgInVwcGVyIl0gICAgICAgIyBMw61taXRlIHN1cGVyaW9yDQopDQoNCiMgSW1wcmltaXIgbG9zIGVzY2VuYXJpb3MNCnByaW50KGVzY2VuYXJpb3NfZGYpDQoNCiMgR3JhZmljYXIgbG9zIGVzY2VuYXJpb3MNCmxpYnJhcnkoZ2dwbG90MikNCmdncGxvdChlc2NlbmFyaW9zX2RmLCBhZXMoeCA9IFBlcmlvZG8pKSArDQogIGdlb21fbGluZShhZXMoeSA9IEVzY2VuYXJpb19QZXNpbWlzdGEsIGNvbG9yID0gIlBlc2ltaXN0YSIpLCBzaXplID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIikgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBFc2NlbmFyaW9fUmVhbCwgY29sb3IgPSAiUmVhbCIpLCBzaXplID0gMSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBFc2NlbmFyaW9fT3B0aW1vLCBjb2xvciA9ICLDk3B0aW1vIiksIHNpemUgPSAxLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArDQogIGxhYnModGl0bGUgPSAiRXNjZW5hcmlvcyBkZSBOZXdfRkRJX0luZmxvd3MiLA0KICAgICAgIHggPSAiUGVyaW9kbyIsIHkgPSAiTmV3X0ZESV9JbmZsb3dzIikgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUGVzaW1pc3RhIiA9ICJyZWQiLCAiUmVhbCIgPSAiYmx1ZSIsICLDk3B0aW1vIiA9ICJncmVlbiIpKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQpgYGANCg0KDQojIyBFbCBkZXNlbXBlw7FvIGRlbCBmbHVqbyBkZSBudWV2b3MgZmx1am9zIGRlIElFRCBleGhpYmVuIGxhIHByZXNlbmNpYSBkZSB1biBjYW1iaW8gZXN0cnVjdHVyYWwgZHVyYW50ZSBlbCBwZXLDrW9kbyBkZSBhbsOhbGlzaXM/DQoNCkVsIE0tZmx1Y3R1YXRpb24gdGVzdCAoQ1VTVU0pIGV2YWzDumEgc2kgbG9zIGNvZWZpY2llbnRlcyBkZWwgbW9kZWxvIFZBUiBzZSBtYW50aWVuZW4gZXN0YWJsZXMgYSBsbyBsYXJnbyBkZWwgdGllbXBvLiBFbiBlc3RlIGNhc28sIGVsIHAtdmFsb3IgZXMgMC4zODcyIChtYXlvciBhIDAuMDUpLCBwb3IgbG8gcXVlIG5vIGhheSBldmlkZW5jaWEgZGUgY2FtYmlvIGVzdHJ1Y3R1cmFsLiBQb3IgbG8gdGFudG8sIGxhIHBydWViYSBkZSBmbHVjdHVhY2nDs24gKENVU1VNKSBubyBlbmN1ZW50cmEgY2FtYmlvcyBlc3RydWN0dXJhbGVzIGNvbmZvcm1lIGFsIHRpZW1wbywgbG8gY3VhbCBjb2luY2lkZSBjb24gZWwgdmFsb3IgZGUgbGEgUHJ1ZWJhIENob3cgbGEgY3VhbCBkZXRlcm1pbmEgcXVlIG5vIHNlIGRldGVjdGEgdW4gY2FtYmlvIGVzdHJ1Y3R1cmFsIGVuIGxhIHJlZ3Jlc2nDs24uDQoNCmBgYHtyfQ0KbGlicmFyeShzdHJ1Y2NoYW5nZSkNCg0Kcm9vdHModmFyX21vZGVsKSAgIyBMYXMgcmHDrWNlcyBkZWJlbiBlc3RhciBkZW50cm8gZGVsIGPDrXJjdWxvIHVuaXRhcmlvDQoNCmN1c3VtX3Rlc3QgPC0gc2N0ZXN0KHZhcl9tb2RlbCwgdHlwZSA9ICJPTFMtQ1VTVU0iKQ0KcHJpbnQoY3VzdW1fdGVzdCkNCmBgYA0KDQoNCiMgQ29uY2x1c2lvbmVzDQpMb3MgbW9kZWxvcyBkZSBzZXJpZXMgZGUgdGllbXBvIGFwbGljYWRvcyBlbiBlc3RlIGFuw6FsaXNpcyBoYW4gcGVybWl0aWRvIGV4YW1pbmFyIGVsIGNvbXBvcnRhbWllbnRvIGRlIGxvcyBmbHVqb3MgZGUgSUVEIGVuIE3DqXhpY28geSBzdSBwb3NpYmxlIHJlbGFjacOzbiBjb24gZmFjdG9yZXMgbWFjcm9lY29uw7NtaWNvcy4gRWwgbW9kZWxvIFZBUiBtb3N0csOzIHNlciBlbCBtZWpvciBlbiB0w6lybWlub3MgZGUgZGVzZW1wZcOxbywgYWwgbm8gcHJlc2VudGFyIGF1dG9jb3JyZWxhY2nDs24gZW4gbG9zIHJlc2lkdW9zIHkgdGVuZXIgdW4gbWVub3IgQUlDIGVuIGNvbXBhcmFjacOzbiBjb24gb3Ryb3MgbW9kZWxvcy4NCg0KRW4gdMOpcm1pbm9zIGRlIGNhdXNhbGlkYWQsIGxvcyByZXN1bHRhZG9zIHN1Z2llcmVuIHF1ZSBsYXMgdmFyaWFibGVzIG1hY3JvZWNvbsOzbWljYXMgc2VsZWNjaW9uYWRhcyAodGlwbyBkZSBjYW1iaW8sIElOUEMgeSBleHBvcnRhY2lvbmVzKSBubyB0aWVuZW4gdW5hIHJlbGFjacOzbiBjYXVzYWwgZnVlcnRlIGNvbiBsb3MgZmx1am9zIGRlIElFRCBlbiBlbCBjb3J0byBwbGF6by4gU2luIGVtYmFyZ28sIHNlIG9ic2VydmEgcXVlIElOUEMgeSBFeHBvcnRzIHBvZHLDrWFuIHRlbmVyIHVuIGltcGFjdG8gZW4gbGEgdmFyaWFibGUgZGVwZW5kaWVudGUgZW4gZWwgdGVyY2VyIHJlemFnbywgYXVucXVlIGxhIGV2aWRlbmNpYSBlc3RhZMOtc3RpY2Egbm8gZXMgY29uY2x1eWVudGUuDQoNCg0KKiBTb2JyZSBzaSBzdWNlZGVyw6EgbyBubyBlbCBuZWFyc2hvcmluZzoNCg0KICAqIENvbiBiYXNlIGVuIGVsIGFuw6FsaXNpcyBkZSBzZXJpZXMgZGUgdGllbXBvIHkgZWwgcHJvbsOzc3RpY28gZGUgbnVldmEgaW52ZXJzacOzbiBleHRyYW5qZXJhIGRpcmVjdGEsIGNvbmNsdWltb3MgcXVlIGVuIGxvcyBwcsOzeGltb3MgZG9zIGHDsW9zIGVsIG5lYXJzaG9yaW5nIG5vIG9jdXJyaXLDoSBkZSBtYW5lcmEgc2lnbmlmaWNhdGl2YSBuaSBtb3N0cmFyw6EgdW4gYXVtZW50byBkcsOhc3RpY28gZW4gbG9zIGZsdWpvcyBkZSBpbnZlcnNpw7NuLg0KICANCiAgKglTb2xvIGVuIDIgZGUgbG9zIDggdHJpbWVzdHJlcyBwcm95ZWN0YWRvcywgbGEgTnVldmEgSUVEIHNlIG1hbnRpZW5lIHBvciBlbmNpbWEgZGVsIHVtYnJhbCBkZSA2MCw2NjYgdW5pZGFkZXMgKG1lZGlhIGhpc3TDs3JpY2EgZGUgTmV3X0ZESV9JbmZsb3dzICsgMjAlKS4NCiAgDQogICoJTGEgdGVuZGVuY2lhIGdlbmVyYWwgaW5kaWNhIHF1ZSBsYSBJRUQgc2UgbWFudGVuZHLDoSBlbiBuaXZlbGVzIGVzdGFibGVzLCBjb24gbGlnZXJvcyBwaWNvcyBkZSBhdW1lbnRvLCBwZXJvIHNpbiB1bmEgY29uc29saWRhY2nDs24gY2xhcmEgZGVsIG5lYXJzaG9yaW5nIGVuIGVsIGNvcnRvIHBsYXpvLg0KICANCiAgKglFcyBwb3NpYmxlIHF1ZSBlbiB1biBmdXR1cm8gcG9zdGVyaW9yIGEgbG9zIHByw7N4aW1vcyBkb3MgYcOxb3MgTmV3X0ZESV9JbmZsb3dzIGV4cGVyaW1lbnRlIHVuIG1heW9yIGF1bWVudG8sIHBlcm8gYmFqbyBlc3RlIHVtYnJhbCwgbm8gc2UgZXNwZXJhIHF1ZSBlbCBuZWFyc2hvcmluZyBvY3VycmEgc2lnbmlmaWNhdGl2YW1lbnRlIGVuIGxvcyBwcsOzeGltb3MgZG9zIGHDsW9zLg0KDQoNCiogU29icmUgZWwgbmVhcnNob3JpbmcgZW4gbG9zIHByw7N4aW1vcyBhw7FvczogU2UgcmVhbGl6w7MgZWwgcHJvbsOzc3RpY28gcGFyYSBsb3MgcHLDs3hpbW9zIGRvcyBhw7Fvcy4gTG9zIGVzY2VuYXJpb3MgbXVlc3RyYW4gaW5jZXJ0aWR1bWJyZSwgcGVybyBjb24gdW5hIHRlbmRlbmNpYSBxdWUgZmF2b3JlY2UgZWwgY3JlY2ltaWVudG8gZGUgbGEgSUVEIGVuIGVsIHBhw61zLg0KDQogICoJRW4gdW4gZXNjZW5hcmlvIMOzcHRpbW8sIGxhIElFRCBwb2Ryw61hIGFsY2FuemFyIHZhbG9yZXMgc3VwZXJpb3JlcyBhIDEzNSwwMDAgdW5pZGFkZXMuDQogIA0KICAqCUVuIHVuIGVzY2VuYXJpbyByZWFsaXN0YSwgbG9zIHZhbG9yZXMgcHJveWVjdGFkb3Mgb3NjaWxhbiBlbnRyZSAzOSwwNDIgeSA2OSwwMDQgdW5pZGFkZXMsIGNvbiBsYSBtYXlvcsOtYSBkZSBsb3MgdHJpbWVzdHJlcyBwb3IgZW5jaW1hIGRlIGxhIG1lZGlhIGhpc3TDs3JpY2EuDQogIA0KICAqCUVuIHVuIGVzY2VuYXJpbyBwZXNpbWlzdGEsIGxhIElFRCBwb2Ryw61hIGNhZXIgaGFzdGEgLTM4LDMwMSB1bmlkYWRlcywgbG8gcXVlIGluZGljYXLDrWEgdW4gcmV0cm9jZXNvIGVuIGxhIGludmVyc2nDs24gc2kgbGFzIGNvbmRpY2lvbmVzIG1hY3JvZWNvbsOzbWljYXMgeSBwb2zDrXRpY2FzIHNvbiBkZXNmYXZvcmFibGVzLg0KDQoNCiMgUmVmZXJlbmNpYXMNCg0KKiBWaWxsZWdhcyBUZWxsbywgUi4gKDQgZGUgQWJyaWwsIDIwMjEpLiBSUHVicyAtIFNlcmllcyBkZSBUaWVtcG8uIENvbnN1bHRhZG8gZWwgMjQgZGUgRmVicmVybyBkZSAyMDI1LCBkZSBScHVicy5jb20gU2l0aW8gV2ViOiBodHRwczovL3JwdWJzLmNvbS9yZXZpdGUxOS83NDk0OTkNCg0KKiBJTUNPLiAoRW5lcm8sIDIwMjQpLiBOZWFyc2hvcmluZzogVGhlIGltcGFjdCBvbiBGREkgaW4gTWV4aWNvLiBDb25zdWx0YWRvIGVsIDI0IGRlIEZlYnJlcm8gZGUgMjAyNSwgZGUgSU1DTywgU2l0aW8gV2ViOiBodHRwczovL2ltY28ub3JnLm14L2VuL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDI0LzA0L0lNQ09fTmVhcnNob3JpbmdJRUQucGRmIA0K