Pasos para el proceso de manejo de datos: 1. Descargar librerias: quantmod, tseries, forecast. 2. Extraemos los datos de la base de datos de FRED por medio de la función “getSymbols”.Se extrae el par MXN/USD (“DEXMXUS”). 3.Se elige la frecuencia en la que se van a analizar los datos, con la función “to.monthly” recopliamos los datos de manera mensual. 4.Graficamos los datos extraidos.

#La libreria quantmod (Quantitative Financial Modelling Framework) se utiliza para poder llamar la función getSymbols y .xts
library(quantmod)
#La libreria tseries (Time Series Analysis and Computational Finance) se utiliza para el análisis de Series de Tiempo
library(tseries)
#La libreria forecast (Forecasting Functions for Time Series and Linear Models) se utiliza para analizar y visualizar series del tiempo univariadas. 
library(forecast)
# Se utiliza para poder usar la función auto.arima() la cual nos ayudará a generar un modelo arima.
library(lmtest)

#Usamos la función "getSymbols" la cual nos ayudará a extraer los valores del par USD/MXN de la base de datos FRED.

getSymbols(Symbols="DEXMXUS", src="FRED")
[1] "DEXMXUS"
#Indicamos la fecha de incio para tomar los datos de la base de datos
DEXMXUS = DEXMXUS["1994-01-01/"]

Aquí se pueden visualizar el valor del par USD/MXN por meses desde enero del 1994 hasta mayo 2022.

#Dado que la base de datos con la que estamos trabajando tiene una periodicidad diaria es necesario convertirla a mensual con la función "to.monthly()"
mrate.xts = to.monthly(DEXMXUS)
Warning in to.period(x, "months", indexAt = indexAt, name = name, ...) :
  missing values removed from data
plot(mrate.xts)

#Una vez teniendo los valores mensuales tomamos el precio de cierre con la función Cl.
mrate = Cl(mrate.xts)

# Transformamos el DataFrame a un objeto TimeSeries con frecuencia mensual. La función de ts() se usa para crear objetos de SeriesdeTiempo. Se le indica el incio y el final con una frecuencia mensual
mrate<-ts(coredata(mrate),start=c(1994,1), end=c(2022,5),frequency=12) 

Ahora procedemos a visualizar los datos, es recomendable graficar el logaritmo de la variable del tipo de cambio para poder ver si la serie temporal es estacionaria o no. Y en caso de no serlo, comenzaremos a transformar la variable del tipo de cambio para que sea una variable estacionaria.

#Calculamos el logaritmo de la variable mrate y después la graficamos con respecto al tiempo
lnmrate<- log(mrate)
plot(lnmrate)

Como podemos observar la serie no es estacionaria debido a que la media cambia con el tiempo. Para poder transformar los datos a estacionarios primero calcularemos la diferencia estacional del logaritmo de la serie de tiempo.

Esta diferencia es el variación anual de mes en mes que existe entre una estación (año) y otra. En nuestro caso, al ser mensual existen 12 periodos por estación, por lo que la diferencia estacionaria de Y por periodo t será: Y(t)-Y(t-12).

#Sacamos la diferencia del logaritmo de nuestra variable mrate con la función "diff()"
dif_log = diff(lnmrate,lag=12)

#Practicamente lo que estamos calculando es la diferencia que existe entre el log de la variable del tipo de cambio (mrate) y el log de la misma variable pero de hace 12 meses, es por esto que es anual. Podemos calcular esto mismo de la siguiente manera:dif_log= lnmrate-lag(lnmrate,12)
plot(dif_log)

Como podemos observar los datos visualmente se ven estacionarios, pero para corroborar que en efecto los datos sean estacionarios vamos a realizar el test de Dicky-Fuller.

El Dicky-Fuller test nos ayudará a determinar si hay o no presencia de tendencia en una autoregresión.

La hipotesis nula establece la presencia de tendencia entre las observaciones (no estacionaria) y la alternativa establece que no hay presencia de tendencia (estacionaria).

Si como resultado del test obtenemos que la variable es estacionaria entonces D = 1 y d = 0.

#Augmented Dickey Fuller Test (ADF Test)
adf.test(dif_log,k=1)
Warning in adf.test(dif_log, k = 1) :
  p-value smaller than printed p-value

    Augmented Dickey-Fuller Test

data:  dif_log
Dickey-Fuller = -4.6301, Lag order = 1, p-value = 0.01
alternative hypothesis: stationary

Como podemos observar el p valor del test es de 0.01 al 95% de confianza por lo que rechazamos la hipotesis nula, concluyendo así que la diferencia estacional del logaritmo es estacionaria.

Una vez teniendo los datos con los que vamos a trabajar de manera estacionaria y sabiendo que D=1 y d=0, hace falta definir los valores p, q, P, Q. Utilizando la variable estacionaria procederemos a realizar las gráficas de autocorrelación ACF (autocorrelación) y PACF (autocorrelación parcial) para identificar los parámetros p, q, P, Q, dependiendo del comportamiento de estas.

Los 2 patrones más comunes que podemos encontrar en las gráficas son los siguientes:

-Firma AR: cuando la magnitud de las autocorrelaciones del ACF van decayendo de manera progresiva y son positivas, mientras que las autocorrelaciones del PACF con positivas pero disminuyen rápidamente después del lag 1,2 o 3. Si esto se cumple entonces p=número de lags positivos significativos y q= 0

-Firma MA: cuando hay una autocorrelación negativa y significativa en el mismo número de lag para ambas gráficas. Si esto se cumple q= al número del lag negativo más significativo.

Procederemos a gráficarlas en los siguientes correlogramas:

#La función acf2() la extraemos de la biblioteca astsa
library(astsa)
#Intoducimos la variable "dif_log" la cual tiene asignados los valores logarítmicos de la variación del tipo de cambio e indicamos un máximo de 24 lags
acf2(dif_log,max.lag = 24)
     [,1]  [,2]  [,3]  [,4] [,5]  [,6]  [,7]  [,8]  [,9] [,10] [,11] [,12]
ACF  0.92  0.83  0.73  0.64 0.57  0.50  0.43  0.36  0.28  0.19  0.10  0.02
PACF 0.92 -0.09 -0.07 -0.03 0.06 -0.05 -0.04 -0.04 -0.13 -0.08 -0.14  0.10
     [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20] [,21] [,22] [,23]
ACF   0.02  0.01  0.02  0.02  0.01  0.00 -0.02 -0.03 -0.04 -0.05 -0.04
PACF  0.32 -0.06  0.05 -0.06  0.02 -0.09 -0.01 -0.04 -0.04 -0.05 -0.02
     [,24]
ACF  -0.04
PACF  0.07

Para poder interpretar estas gráficas es importante entender lo que esta ocurriendo. Primero que nada,como se mencionó anteriormente tenemos dos gráficas:

En ambas gráficas, el eje de las x tenemos los lag (periodo), mientras que en el eje ‘y’ tenemos el nivel de autocorrelación. Además, las líneas negras verticales representan el nivel de autocorrelación existente entre el valor actual de Y(t) y sus porpios lags (Yt-1, Yt-2,…) y las líneas horizontales azules delimitan el intervalo del 95% de confianza para las autocorrelaciones.

Una vez sabiendo esto podemos observar de manera sencilla cuales son los lags de la variable que tienen una autocorrelación significante. Si la línea vertical sobresale de las líneas punteadas entonces podemos concluir que la autocorrelación de la variable Y(t), con su correspondiente lag Yt-1 es estadisticamente diferente a cero.

Analizando los valores obtenidos en el ACF podemos ver que LAG 1 (Yt-1) esta significativamente autocorrelacionada de manera positiva con el valor actual de la variable (Yt), ya que su valor es mayor a cero (0.92). Esto significa que el valor de Y en cualquier punto del tiempo tiene una autocorrelación promedio de 0.92 con respecto a su propio valor en t-1.

Por el otro lado, en la gráfica PACF lo que podemos concluir es que el lag 1 está autocorrelacionado con el valor actual después de considerar el efecto de los valores intermedios, o en otra palabras, la variación del tipo de cambio del mes actual parece estar positivamente correlacionado con su propio valor del siguiente mes.

Finalmente analizando los patrones,la magnitud de las autocorrelaciones del ACF van decayendo de manera progresiva y son positivas, mientras que las autocorrelaciones del PACF disminuyen rápidamente después del lag 1. Indicandonos que estamos frente a un patrón tipo AR, por lo cual podemos decir que p=1 y q=0.

Ahora solo hace falta comprobar si existe una autocorrelación significativa entre los rezagos estacionales de ACF y PACF para poder encontrar los valores de P y Q. Al estar manejando datos mensuales, deberemos hacer una autocorrelación significativa en el lag 12.

Debido a que no tenemos autocorrelación significativa entonces P=0 y Q=0.


model2 <- Arima(mrate, 
                lambda = 0, # Aplicamos el logaritmo natural a la variable
                order = c(1,0,0), #p=1; d=0; q=0
                seasonal = list(order=c(0,1,0),period=12), #P=0,D=1,Q=0
                include.constant = TRUE,
                ) 
coeftest(model2)

z test of coefficients:

       Estimate Std. Error z value Pr(>|z|)    
ar1   0.9577562  0.0183124 52.3011   <2e-16 ***
drift 0.0078381  0.0051803  1.5131   0.1303    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Para una buena interpretación de los resultados de la modelación de la variación anual del tipo de cambio tenemos que:

El coeficiente del término AR (1) es 0.9577562 y es significativamente positivo. Esto significa que:El porcentaje del crecimiento anual del tipo de cambio tiene una relación significativa y porsitiva respecto a su propio crecimeinto anual del mes anterior.

Una vez corrido el arima, es importante verificar si los errores o los residuales son una serie estacionaria. De ser así esto significa que tenemos todos los términos permiten la explicación de la serie.

errors <- model2$residuals
acf2(errors,max.lag = 24)
     [,1]  [,2] [,3]  [,4]  [,5]  [,6]  [,7] [,8]  [,9] [,10] [,11] [,12]
ACF  0.07 -0.01 0.02 -0.15 -0.01  0.00 -0.04 0.10 -0.03  0.06 -0.06 -0.42
PACF 0.07 -0.02 0.02 -0.15  0.02 -0.01 -0.04 0.09 -0.05  0.08 -0.09 -0.39
     [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20] [,21] [,22] [,23]
ACF  -0.02 -0.07  0.04  0.04  0.06  0.00  0.02 -0.04 -0.02 -0.04  0.05
PACF  0.03 -0.08  0.07 -0.10  0.10 -0.06  0.01 -0.01 -0.05  0.03 -0.01
     [,24]
ACF   0.01
PACF -0.16

Como podemos ver, los errores presenta una serie estacionaria, pero hay una autocorrelación negativa y significativa en el lag 12. En este caso es relevante por lo que de acuerdo con los patrones previamente mencionados si el lag es negativo y significante y aparece en ambas gráficas, no se sigue una firma AR() sino que se incluye una MA() Q=1 debido a que es la correlación existente entre lag 12 y los datos son mensuales.

Por lo que haremos el modelo de nuevo ahora con los nuevos valores:

model3 <- Arima(mrate, order = c(1,0,0),#p=1; d=0; q=0
    seasonal = list(order=c(0,1,1),period=12), #P=0,D=1,Q=1
    include.constant = TRUE,
    lambda = 0)
coeftest(model3)

z test of coefficients:

        Estimate Std. Error  z value  Pr(>|z|)    
ar1    0.9941204  0.0076181 130.4938 < 2.2e-16 ***
sma1  -0.9381461  0.0649265 -14.4493 < 2.2e-16 ***
drift  0.0054506  0.0020961   2.6004  0.009312 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

El coeficiente del término AR (1) es 0.9941204 y es significativamente positivo. Esto significa que:El porcentaje del crecimiento anual del tipo de cambio tiene una relación significativa y porsitiva respecto a su propio crecimeinto anual del mes anterior.

El coeficiente del término AR (1) estacional es -0,9381461 y es significativamente negativo, lo que significa que el porcentaje de crecimiento anual del tipo de cambio esta relacionado negativamente y significativamente con su propio crecimiento anual de hace 12 meses. En otras palabras, si el cambio creció hace 12 meses es probable que este baje.

Una vez más corroboraremos si los errores/residuales para ver si estos siguen una serie estacionaria.

errors <- model3$residuals
acf2(errors,max.lag = 24)
     [,1] [,2] [,3]  [,4] [,5]  [,6]  [,7]  [,8] [,9] [,10] [,11] [,12]
ACF  0.08 0.01 0.02 -0.15 0.00 -0.04 -0.03 -0.01 0.00  0.08  0.00  0.13
PACF 0.08 0.00 0.02 -0.16 0.02 -0.04 -0.02 -0.04 0.01  0.07 -0.02  0.13
     [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20] [,21] [,22] [,23]
ACF   0.00 -0.10  0.05 -0.06  0.03 -0.05  0.00 -0.06 -0.01  0.05  0.04
PACF -0.03 -0.08  0.05 -0.03  0.04 -0.08  0.04 -0.09  0.03  0.01  0.06
     [,24]
ACF   0.11
PACF  0.08

Nuestro modelo se ajusta bien debido a que hay Ruido Blanco, p-value es mayor a 0.05.

Box.test(residuals(model3),type="Ljung-Box")

    Box-Ljung test

data:  residuals(model3)
X-squared = 2.3074, df = 1, p-value = 0.1288

Como podemos ver, ahora si se muestra una serie estacionaria por lo que procederemos a hacer la predicción de los valores.

Haremos un pronóstico para el tipo de cambio de los siguientes 18 meses usando nuestro modelo calibrado.

#Se utiliza la función forecast para predecir los valores futuros de los siguientes 18 meses
mrate_forecast <- forecast(model3, h=18)
autoplot(mrate_forecast)

Como podemos ver, en el gráfico se arroja el pronóstico para el tipo de cambio en color violeta. El error del pronóstico es alto ya que con un intervalo de confianza del 95% oscilan los valores entre 17-27 MXN.

Finalmente, calculemos los valores para los siguientes 18 meses de manera puntual, siendo estos el promedio de cada mes.

tail(mrate_forecast$mean,18)
          Jan      Feb      Mar      Apr      May      Jun      Jul
2022                                              19.72655 19.55919
2023 20.83118 20.93177 20.90727 20.86060 21.04845 21.09801 20.91879
          Aug      Sep      Oct      Nov      Dec
2022 19.91763 20.13384 20.31126 20.48773 20.72025
2023 21.30193 21.53293 21.72245 21.91096         

Referencias: https://www.machinelearningplus.com/time-series/arima-model-time-series-forecasting-python/ https://rpubs.com/cdorante/fz2020_w3 https://rpubs.com/Stefan240sx/e1fe2 https://rpubs.com/Rafael_Romo/779985 https://www.estadistica.net/ECONOMETRIA/SERIES-TEMPORALES/modelo-arima.pdf https://www.researchgate.net/publication/328633706_Forecasting_of_demand_using_ARIMA_model https://www.sciencedirect.com/science/article/abs/pii/S0360835298000667

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQpQYXNvcyBwYXJhIGVsIHByb2Nlc28gZGUgbWFuZWpvIGRlIGRhdG9zOiAKMS4gRGVzY2FyZ2FyIGxpYnJlcmlhczogcXVhbnRtb2QsIHRzZXJpZXMsIGZvcmVjYXN0LiAKMi4gRXh0cmFlbW9zIGxvcyBkYXRvcyBkZSBsYSBiYXNlIGRlIGRhdG9zIGRlIEZSRUQgcG9yIG1lZGlvIGRlIGxhIGZ1bmNpw7NuICJnZXRTeW1ib2xzIi5TZSBleHRyYWUgZWwgcGFyIE1YTi9VU0QgKCJERVhNWFVTIikuCjMuU2UgZWxpZ2UgbGEgZnJlY3VlbmNpYSBlbiBsYSBxdWUgc2UgdmFuIGEgYW5hbGl6YXIgbG9zIGRhdG9zLCBjb24gbGEgZnVuY2nDs24gInRvLm1vbnRobHkiIHJlY29wbGlhbW9zIGxvcyBkYXRvcyBkZSBtYW5lcmEgbWVuc3VhbC4KNC5HcmFmaWNhbW9zIGxvcyBkYXRvcyBleHRyYWlkb3MuIAoKYGBge3J9CiNMYSBsaWJyZXJpYSBxdWFudG1vZCAoUXVhbnRpdGF0aXZlIEZpbmFuY2lhbCBNb2RlbGxpbmcgRnJhbWV3b3JrKSBzZSB1dGlsaXphIHBhcmEgcG9kZXIgbGxhbWFyIGxhIGZ1bmNpw7NuIGdldFN5bWJvbHMgeSAueHRzCmxpYnJhcnkocXVhbnRtb2QpCiNMYSBsaWJyZXJpYSB0c2VyaWVzIChUaW1lIFNlcmllcyBBbmFseXNpcyBhbmQgQ29tcHV0YXRpb25hbCBGaW5hbmNlKSBzZSB1dGlsaXphIHBhcmEgZWwgYW7DoWxpc2lzIGRlIFNlcmllcyBkZSBUaWVtcG8KbGlicmFyeSh0c2VyaWVzKQojTGEgbGlicmVyaWEgZm9yZWNhc3QgKEZvcmVjYXN0aW5nIEZ1bmN0aW9ucyBmb3IgVGltZSBTZXJpZXMgYW5kIExpbmVhciBNb2RlbHMpIHNlIHV0aWxpemEgcGFyYSBhbmFsaXphciB5IHZpc3VhbGl6YXIgc2VyaWVzIGRlbCB0aWVtcG8gdW5pdmFyaWFkYXMuIApsaWJyYXJ5KGZvcmVjYXN0KQojIFNlIHV0aWxpemEgcGFyYSBwb2RlciB1c2FyIGxhIGZ1bmNpw7NuIGF1dG8uYXJpbWEoKSBsYSBjdWFsIG5vcyBheXVkYXLDoSBhIGdlbmVyYXIgdW4gbW9kZWxvIGFyaW1hLgpsaWJyYXJ5KGxtdGVzdCkKCiNVc2Ftb3MgbGEgZnVuY2nDs24gImdldFN5bWJvbHMiIGxhIGN1YWwgbm9zIGF5dWRhcsOhIGEgZXh0cmFlciBsb3MgdmFsb3JlcyBkZWwgcGFyIFVTRC9NWE4gZGUgbGEgYmFzZSBkZSBkYXRvcyBGUkVELCBGZWRlcmFsIFJlc2VydmUgQmFuayBvZiBTdC4gTG91aXMKCmdldFN5bWJvbHMoU3ltYm9scz0iREVYTVhVUyIsIHNyYz0iRlJFRCIpCgojSW5kaWNhbW9zIGxhIGZlY2hhIGRlIGluY2lvIHBhcmEgdG9tYXIgbG9zIGRhdG9zIGRlIGxhIGJhc2UgZGUgZGF0b3MKREVYTVhVUyA9IERFWE1YVVNbIjE5OTQtMDEtMDEvIl0KYGBgCkFxdcOtIHNlIHB1ZWRlbiB2aXN1YWxpemFyIGVsIHZhbG9yIGRlbCBwYXIgVVNEL01YTiBwb3IgbWVzZXMgZGVzZGUgZW5lcm8gZGVsIDE5OTQgaGFzdGEgbWF5byAyMDIyLiAKYGBge3J9CiNEYWRvIHF1ZSBsYSBiYXNlIGRlIGRhdG9zIGNvbiBsYSBxdWUgZXN0YW1vcyB0cmFiYWphbmRvIHRpZW5lIHVuYSBwZXJpb2RpY2lkYWQgZGlhcmlhIGVzIG5lY2VzYXJpbyBjb252ZXJ0aXJsYSBhIG1lbnN1YWwgY29uIGxhIGZ1bmNpw7NuICJ0by5tb250aGx5KCkiCm1yYXRlLnh0cyA9IHRvLm1vbnRobHkoREVYTVhVUykKcGxvdChtcmF0ZS54dHMpCmBgYApgYGB7cn0KI1VuYSB2ZXogdGVuaWVuZG8gbG9zIHZhbG9yZXMgbWVuc3VhbGVzIHRvbWFtb3MgZWwgcHJlY2lvIGRlIGNpZXJyZSBjb24gbGEgZnVuY2nDs24gQ2wuCm1yYXRlID0gQ2wobXJhdGUueHRzKQoKIyBUcmFuc2Zvcm1hbW9zIGVsIERhdGFGcmFtZSBhIHVuIG9iamV0byBUaW1lU2VyaWVzIGNvbiBmcmVjdWVuY2lhIG1lbnN1YWwuIExhIGZ1bmNpw7NuIGRlIHRzKCkgc2UgdXNhIHBhcmEgY3JlYXIgb2JqZXRvcyBkZSBTZXJpZXNkZVRpZW1wby4gU2UgbGUgaW5kaWNhIGVsIGluY2lvIHkgZWwgZmluYWwgY29uIHVuYSBmcmVjdWVuY2lhIG1lbnN1YWwKbXJhdGU8LXRzKGNvcmVkYXRhKG1yYXRlKSxzdGFydD1jKDE5OTQsMSksIGVuZD1jKDIwMjIsNSksZnJlcXVlbmN5PTEyKSAKYGBgCkFob3JhIHByb2NlZGVtb3MgYSB2aXN1YWxpemFyIGxvcyBkYXRvcywgZXMgcmVjb21lbmRhYmxlIGdyYWZpY2FyIGVsIGxvZ2FyaXRtbyBkZSBsYSB2YXJpYWJsZSBkZWwgdGlwbyBkZSBjYW1iaW8gcGFyYSBwb2RlciB2ZXIgc2kgbGEgc2VyaWUgdGVtcG9yYWwgZXMgZXN0YWNpb25hcmlhIG8gbm8uIFkgZW4gY2FzbyBkZSBubyBzZXJsbywgY29tZW56YXJlbW9zIGEgdHJhbnNmb3JtYXIgbGEgdmFyaWFibGUgZGVsIHRpcG8gZGUgY2FtYmlvIHBhcmEgcXVlIHNlYSB1bmEgdmFyaWFibGUgZXN0YWNpb25hcmlhLiAKYGBge3J9CiNDYWxjdWxhbW9zIGVsIGxvZ2FyaXRtbyBkZSBsYSB2YXJpYWJsZSBtcmF0ZSB5IGRlc3B1w6lzIGxhIGdyYWZpY2Ftb3MgY29uIHJlc3BlY3RvIGFsIHRpZW1wbwpsbm1yYXRlPC0gbG9nKG1yYXRlKQpwbG90KGxubXJhdGUpCmBgYApDb21vIHBvZGVtb3Mgb2JzZXJ2YXIgbGEgc2VyaWUgbm8gZXMgZXN0YWNpb25hcmlhIGRlYmlkbyBhIHF1ZSBsYSBtZWRpYSBjYW1iaWEgY29uIGVsIHRpZW1wby4gUGFyYSBwb2RlciB0cmFuc2Zvcm1hciBsb3MgZGF0b3MgYSBlc3RhY2lvbmFyaW9zIHByaW1lcm8gY2FsY3VsYXJlbW9zIGxhIGRpZmVyZW5jaWEgZXN0YWNpb25hbCBkZWwgbG9nYXJpdG1vIGRlIGxhIHNlcmllIGRlIHRpZW1wby4KIApFc3RhIGRpZmVyZW5jaWEgZXMgZWwgdmFyaWFjacOzbiBhbnVhbCBkZSBtZXMgZW4gbWVzIHF1ZSBleGlzdGUgZW50cmUgdW5hIGVzdGFjacOzbiAoYcOxbykgeSBvdHJhLiBFbiBudWVzdHJvIGNhc28sIGFsIHNlciBtZW5zdWFsIGV4aXN0ZW4gMTIgcGVyaW9kb3MgcG9yIGVzdGFjacOzbiwgcG9yIGxvIHF1ZSBsYSBkaWZlcmVuY2lhIGVzdGFjaW9uYXJpYSBkZSBZIHBvciBwZXJpb2RvIHQgc2Vyw6E6IFkodCktWSh0LTEyKS4KCmBgYHtyfQojU2FjYW1vcyBsYSBkaWZlcmVuY2lhIGRlbCBsb2dhcml0bW8gZGUgbnVlc3RyYSB2YXJpYWJsZSBtcmF0ZSBjb24gbGEgZnVuY2nDs24gImRpZmYoKSIKZGlmX2xvZyA9IGRpZmYobG5tcmF0ZSxsYWc9MTIpCgojUHJhY3RpY2FtZW50ZSBsbyBxdWUgZXN0YW1vcyBjYWxjdWxhbmRvIGVzIGxhIGRpZmVyZW5jaWEgcXVlIGV4aXN0ZSBlbnRyZSBlbCBsb2cgZGUgbGEgdmFyaWFibGUgZGVsIHRpcG8gZGUgY2FtYmlvIChtcmF0ZSkgeSBlbCBsb2cgZGUgbGEgbWlzbWEgdmFyaWFibGUgcGVybyBkZSBoYWNlIDEyIG1lc2VzLCBlcyBwb3IgZXN0byBxdWUgZXMgYW51YWwuIFBvZGVtb3MgY2FsY3VsYXIgZXN0byBtaXNtbyBkZSBsYSBzaWd1aWVudGUgbWFuZXJhOmRpZl9sb2c9IGxubXJhdGUtbGFnKGxubXJhdGUsMTIpCnBsb3QoZGlmX2xvZykKYGBgCkNvbW8gcG9kZW1vcyBvYnNlcnZhciBsb3MgZGF0b3MgdmlzdWFsbWVudGUgc2UgdmVuIGVzdGFjaW9uYXJpb3MsIHBlcm8gcGFyYSBjb3Jyb2JvcmFyIHF1ZSBlbiBlZmVjdG8gbG9zIGRhdG9zIHNlYW4gZXN0YWNpb25hcmlvcyB2YW1vcyBhIHJlYWxpemFyIGVsIHRlc3QgZGUgRGlja3ktRnVsbGVyLiAKCkVsIERpY2t5LUZ1bGxlciB0ZXN0IG5vcyBheXVkYXLDoSBhIGRldGVybWluYXIgc2kgaGF5IG8gbm8gcHJlc2VuY2lhIGRlIHRlbmRlbmNpYSBlbiB1bmEgYXV0b3JlZ3Jlc2nDs24uCgpMYSBoaXBvdGVzaXMgbnVsYSBlc3RhYmxlY2UgbGEgcHJlc2VuY2lhIGRlIHRlbmRlbmNpYSBlbnRyZSBsYXMgb2JzZXJ2YWNpb25lcyAobm8gZXN0YWNpb25hcmlhKSB5IGxhIGFsdGVybmF0aXZhIGVzdGFibGVjZSBxdWUgbm8gaGF5IHByZXNlbmNpYSBkZSB0ZW5kZW5jaWEgKGVzdGFjaW9uYXJpYSkuIAoKU2kgY29tbyByZXN1bHRhZG8gZGVsIHRlc3Qgb2J0ZW5lbW9zIHF1ZSBsYSB2YXJpYWJsZSBlcyBlc3RhY2lvbmFyaWEgZW50b25jZXMgRCA9IDEgeSBkID0gMC4gCgpgYGB7cn0KI0F1Z21lbnRlZCBEaWNrZXkgRnVsbGVyIFRlc3QgKEFERiBUZXN0KQphZGYudGVzdChkaWZfbG9nLGs9MSkKYGBgCkNvbW8gcG9kZW1vcyBvYnNlcnZhciBlbCBwIHZhbG9yIGRlbCB0ZXN0IGVzIGRlIDAuMDEgYWwgOTUlIGRlIGNvbmZpYW56YSBwb3IgbG8gcXVlIHJlY2hhemFtb3MgbGEgaGlwb3Rlc2lzIG51bGEsIGNvbmNsdXllbmRvIGFzw60gcXVlIGxhIGRpZmVyZW5jaWEgZXN0YWNpb25hbCBkZWwgbG9nYXJpdG1vIGVzIGVzdGFjaW9uYXJpYS4gCgpVbmEgdmV6IHRlbmllbmRvIGxvcyBkYXRvcyBjb24gbG9zIHF1ZSB2YW1vcyBhIHRyYWJhamFyIGRlIG1hbmVyYSBlc3RhY2lvbmFyaWEgeSBzYWJpZW5kbyBxdWUgRD0xIHkgZD0wLCBoYWNlIGZhbHRhIGRlZmluaXIgbG9zIHZhbG9yZXMgcCwgcSwgUCwgUS4gVXRpbGl6YW5kbyBsYSB2YXJpYWJsZSBlc3RhY2lvbmFyaWEgcHJvY2VkZXJlbW9zIGEgcmVhbGl6YXIgbGFzIGdyw6FmaWNhcyBkZSBhdXRvY29ycmVsYWNpw7NuIEFDRiAoYXV0b2NvcnJlbGFjacOzbikgeSBQQUNGIChhdXRvY29ycmVsYWNpw7NuIHBhcmNpYWwpIHBhcmEgaWRlbnRpZmljYXIgbG9zIHBhcsOhbWV0cm9zIHAsIHEsIFAsIFEsIGRlcGVuZGllbmRvIGRlbCBjb21wb3J0YW1pZW50byBkZSBlc3Rhcy4gCgpMb3MgMiBwYXRyb25lcyBtw6FzIGNvbXVuZXMgcXVlIHBvZGVtb3MgZW5jb250cmFyIGVuIGxhcyBncsOhZmljYXMgc29uIGxvcyBzaWd1aWVudGVzOgoKLUZpcm1hIEFSOiBjdWFuZG8gbGEgbWFnbml0dWQgZGUgbGFzIGF1dG9jb3JyZWxhY2lvbmVzIGRlbCBBQ0YgdmFuIGRlY2F5ZW5kbyBkZSBtYW5lcmEgcHJvZ3Jlc2l2YSB5IHNvbiBwb3NpdGl2YXMsIG1pZW50cmFzIHF1ZSBsYXMgYXV0b2NvcnJlbGFjaW9uZXMgZGVsIFBBQ0YgY29uIHBvc2l0aXZhcyBwZXJvIGRpc21pbnV5ZW4gcsOhcGlkYW1lbnRlIGRlc3B1w6lzIGRlbCBsYWcgMSwyIG8gMy4gU2kgZXN0byBzZSBjdW1wbGUgZW50b25jZXMgcD1uw7ptZXJvIGRlIGxhZ3MgcG9zaXRpdm9zIHNpZ25pZmljYXRpdm9zIHkgcT0gMAoKLUZpcm1hIE1BOiBjdWFuZG8gaGF5IHVuYSBhdXRvY29ycmVsYWNpw7NuIG5lZ2F0aXZhIHkgc2lnbmlmaWNhdGl2YSBlbiBlbCBtaXNtbyBuw7ptZXJvIGRlIGxhZyBwYXJhIGFtYmFzIGdyw6FmaWNhcy4gU2kgZXN0byBzZSBjdW1wbGUgcT0gYWwgbsO6bWVybyBkZWwgbGFnIG5lZ2F0aXZvIG3DoXMgc2lnbmlmaWNhdGl2by4gCgpQcm9jZWRlcmVtb3MgYSBncsOhZmljYXJsYXMgZW4gbG9zIHNpZ3VpZW50ZXMgY29ycmVsb2dyYW1hczogCmBgYHtyfQojTGEgZnVuY2nDs24gYWNmMigpIGxhIGV4dHJhZW1vcyBkZSBsYSBiaWJsaW90ZWNhIGFzdHNhCmxpYnJhcnkoYXN0c2EpCiNJbnRvZHVjaW1vcyBsYSB2YXJpYWJsZSAiZGlmX2xvZyIgbGEgY3VhbCB0aWVuZSBhc2lnbmFkb3MgbG9zIHZhbG9yZXMgbG9nYXLDrXRtaWNvcyBkZSBsYSB2YXJpYWNpw7NuIGRlbCB0aXBvIGRlIGNhbWJpbyBlIGluZGljYW1vcyB1biBtw6F4aW1vIGRlIDI0IGxhZ3MKYWNmMihkaWZfbG9nLG1heC5sYWcgPSAyNCkKYGBgClBhcmEgcG9kZXIgaW50ZXJwcmV0YXIgZXN0YXMgZ3LDoWZpY2FzIGVzIGltcG9ydGFudGUgZW50ZW5kZXIgbG8gcXVlIGVzdGEgb2N1cnJpZW5kby4gUHJpbWVybyBxdWUgbmFkYSxjb21vIHNlIG1lbmNpb27DsyBhbnRlcmlvcm1lbnRlIHRlbmVtb3MgZG9zIGdyw6FmaWNhczoKCi0gQUNGIG5vcyBpbmRpY2EgbGEgYXV0b2NvcnJlbGFjacOzbiBlbnRyZSBsb3MgdmFsb3JlcyBkZSBsYXMgc2VyaWVzIHF1ZSBzZSBlbmN1ZW50cmFuIGEgayBpbnRlcnZhbG9zIGRlIGRpc3RhbmNpYS4KLSBQQUNGIG5vcyBpbmRpY2EgbGFzIGF1dG9jb3JyZWxhY2nDs24gZW50cmUgbG9zIHZhbG9yZXMgZGUgbGFzIHNlcmllcyBxdWUgc2UgZW5jdWVudHJhbiBhIGsgaW50ZXJ2YWxvcyBkZSBkaXN0YW5jaWEsIHRlbmllbmRvIGVuIGN1ZW50YSBsb3MgdmFsb3JlcyBkZSBsb3MgaW50ZXJ2YWxvcyBpbnRlcm1lZGlvcy4gCgpFbiBhbWJhcyBncsOhZmljYXMsIGVsIGVqZSBkZSBsYXMgeCB0ZW5lbW9zIGxvcyBsYWcgKHBlcmlvZG8pLCBtaWVudHJhcyBxdWUgZW4gZWwgZWplICd5JyB0ZW5lbW9zIGVsIG5pdmVsIGRlIGF1dG9jb3JyZWxhY2nDs24uIEFkZW3DoXMsIGxhcyBsw61uZWFzIG5lZ3JhcyB2ZXJ0aWNhbGVzIHJlcHJlc2VudGFuIGVsIG5pdmVsIGRlIGF1dG9jb3JyZWxhY2nDs24gZXhpc3RlbnRlIGVudHJlIGVsIHZhbG9yIGFjdHVhbCBkZSBZKHQpIHkgc3VzIHBvcnBpb3MgbGFncyAoWXQtMSwgWXQtMiwuLi4pIHkgbGFzIGzDrW5lYXMgaG9yaXpvbnRhbGVzIGF6dWxlcyBkZWxpbWl0YW4gZWwgaW50ZXJ2YWxvIGRlbCA5NSUgZGUgY29uZmlhbnphIHBhcmEgbGFzIGF1dG9jb3JyZWxhY2lvbmVzLiAKClVuYSB2ZXogc2FiaWVuZG8gZXN0byBwb2RlbW9zIG9ic2VydmFyIGRlIG1hbmVyYSBzZW5jaWxsYSBjdWFsZXMgc29uIGxvcyBsYWdzIGRlIGxhIHZhcmlhYmxlIHF1ZSB0aWVuZW4gdW5hIGF1dG9jb3JyZWxhY2nDs24gc2lnbmlmaWNhbnRlLiBTaSBsYSBsw61uZWEgdmVydGljYWwgc29icmVzYWxlIGRlIGxhcyBsw61uZWFzIHB1bnRlYWRhcyBlbnRvbmNlcyBwb2RlbW9zIGNvbmNsdWlyIHF1ZSBsYSBhdXRvY29ycmVsYWNpw7NuIGRlIGxhIHZhcmlhYmxlIFkodCksIGNvbiBzdSBjb3JyZXNwb25kaWVudGUgbGFnIFl0LTEgZXMgZXN0YWRpc3RpY2FtZW50ZSBkaWZlcmVudGUgYSBjZXJvLiAKCkFuYWxpemFuZG8gbG9zIHZhbG9yZXMgb2J0ZW5pZG9zIGVuIGVsIEFDRiBwb2RlbW9zIHZlciBxdWUgTEFHIDEgKFl0LTEpIGVzdGEgc2lnbmlmaWNhdGl2YW1lbnRlIGF1dG9jb3JyZWxhY2lvbmFkYSBkZSBtYW5lcmEgcG9zaXRpdmEgY29uIGVsIHZhbG9yIGFjdHVhbCBkZSBsYSB2YXJpYWJsZSAoWXQpLCB5YSBxdWUgc3UgdmFsb3IgZXMgbWF5b3IgYSBjZXJvICgwLjkyKS4gRXN0byBzaWduaWZpY2EgcXVlIGVsIHZhbG9yIGRlIFkgZW4gY3VhbHF1aWVyIHB1bnRvIGRlbCB0aWVtcG8gdGllbmUgdW5hIGF1dG9jb3JyZWxhY2nDs24gcHJvbWVkaW8gZGUgMC45MiBjb24gcmVzcGVjdG8gYSBzdSBwcm9waW8gdmFsb3IgZW4gdC0xLiAKClBvciBlbCBvdHJvIGxhZG8sIGVuIGxhIGdyw6FmaWNhIFBBQ0YgbG8gcXVlIHBvZGVtb3MgY29uY2x1aXIgZXMgcXVlIGVsIGxhZyAxIGVzdMOhIGF1dG9jb3JyZWxhY2lvbmFkbyBjb24gZWwgdmFsb3IgYWN0dWFsIGRlc3B1w6lzIGRlIGNvbnNpZGVyYXIgZWwgZWZlY3RvIGRlIGxvcyB2YWxvcmVzIGludGVybWVkaW9zLCBvIGVuIG90cmEgcGFsYWJyYXMsIGxhIHZhcmlhY2nDs24gZGVsIHRpcG8gZGUgY2FtYmlvIGRlbCBtZXMgYWN0dWFsIHBhcmVjZSBlc3RhciBwb3NpdGl2YW1lbnRlIGNvcnJlbGFjaW9uYWRvIGNvbiBzdSBwcm9waW8gdmFsb3IgZGVsIHNpZ3VpZW50ZSBtZXMuCgpGaW5hbG1lbnRlIGFuYWxpemFuZG8gbG9zIHBhdHJvbmVzLGxhIG1hZ25pdHVkIGRlIGxhcyBhdXRvY29ycmVsYWNpb25lcyBkZWwgQUNGIHZhbiBkZWNheWVuZG8gZGUgbWFuZXJhIHByb2dyZXNpdmEgeSBzb24gcG9zaXRpdmFzLCBtaWVudHJhcyBxdWUgbGFzIGF1dG9jb3JyZWxhY2lvbmVzIGRlbCBQQUNGIGRpc21pbnV5ZW4gcsOhcGlkYW1lbnRlIGRlc3B1w6lzIGRlbCBsYWcgMS4gSW5kaWNhbmRvbm9zIHF1ZSBlc3RhbW9zIGZyZW50ZSBhIHVuIHBhdHLDs24gdGlwbyBBUiwgcG9yIGxvIGN1YWwgcG9kZW1vcyBkZWNpciBxdWUgcD0xIHkgcT0wLgoKQWhvcmEgc29sbyBoYWNlIGZhbHRhIGNvbXByb2JhciBzaSBleGlzdGUgdW5hIGF1dG9jb3JyZWxhY2nDs24gc2lnbmlmaWNhdGl2YSBlbnRyZSBsb3MgcmV6YWdvcyBlc3RhY2lvbmFsZXMgZGUgQUNGIHkgUEFDRiBwYXJhIHBvZGVyIGVuY29udHJhciBsb3MgdmFsb3JlcyBkZSBQIHkgUS4gQWwgZXN0YXIgbWFuZWphbmRvIGRhdG9zIG1lbnN1YWxlcywgZGViZXJlbW9zIGhhY2VyIHVuYSBhdXRvY29ycmVsYWNpw7NuIHNpZ25pZmljYXRpdmEgZW4gZWwgbGFnIDEyLgoKLSBTaSBlcyBzaWduaWZpY2F0aXZhIHkgcG9zaXRpdmEgZW50b25jZXMgUCA9IDEgeSBRID0gMC4KLSBTaSBlcyBzaWduaWZpY2F0aXZhIHkgbmVnYXRpdmEsIGRlZmluaW1vcyBQID0gMCB5IFEgPSAxLgotIFNpIG5vIGhheSB1bmEgYXV0b2NvcnJlbGFjacOzbiBzaWduaWZpY2F0aXZhLCBlbnRvbmNlcyBQID0gMCB5IFEgPSAwLgoKRGViaWRvIGEgcXVlIG5vIHRlbmVtb3MgYXV0b2NvcnJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVudG9uY2VzIFA9MCB5IFE9MC4gCgpgYGB7cn0KCm1vZGVsMiA8LSBBcmltYShtcmF0ZSwgCiAgICAgICAgICAgICAgICBsYW1iZGEgPSAwLCAjIEFwbGljYW1vcyBlbCBsb2dhcml0bW8gbmF0dXJhbCBhIGxhIHZhcmlhYmxlCiAgICAgICAgICAgICAgICBvcmRlciA9IGMoMSwwLDApLCAjcD0xOyBkPTA7IHE9MAogICAgICAgICAgICAgICAgc2Vhc29uYWwgPSBsaXN0KG9yZGVyPWMoMCwxLDApLHBlcmlvZD0xMiksICNQPTAsRD0xLFE9MAogICAgICAgICAgICAgICAgaW5jbHVkZS5jb25zdGFudCA9IFRSVUUsCiAgICAgICAgICAgICAgICApIApjb2VmdGVzdChtb2RlbDIpCgpgYGAKUGFyYSB1bmEgYnVlbmEgaW50ZXJwcmV0YWNpw7NuIGRlIGxvcyByZXN1bHRhZG9zIGRlIGxhIG1vZGVsYWNpw7NuIGRlIGxhIHZhcmlhY2nDs24gYW51YWwgZGVsIHRpcG8gZGUgY2FtYmlvIHRlbmVtb3MgcXVlOiAKCkVsIGNvZWZpY2llbnRlIGRlbCB0w6lybWlubyBBUiAoMSkgZXMgMC45NTc3NTYyIHkgZXMgc2lnbmlmaWNhdGl2YW1lbnRlIHBvc2l0aXZvLiBFc3RvIHNpZ25pZmljYSBxdWU6RWwgcG9yY2VudGFqZSBkZWwgY3JlY2ltaWVudG8gYW51YWwgZGVsIHRpcG8gZGUgY2FtYmlvIHRpZW5lIHVuYSByZWxhY2nDs24gc2lnbmlmaWNhdGl2YSB5IHBvcnNpdGl2YSByZXNwZWN0byBhIHN1IHByb3BpbyBjcmVjaW1laW50byBhbnVhbCBkZWwgbWVzIGFudGVyaW9yLgoKVW5hIHZleiBjb3JyaWRvIGVsIGFyaW1hLCBlcyBpbXBvcnRhbnRlIHZlcmlmaWNhciBzaSBsb3MgZXJyb3JlcyBvIGxvcyByZXNpZHVhbGVzIHNvbiB1bmEgc2VyaWUgZXN0YWNpb25hcmlhLiBEZSBzZXIgYXPDrSBlc3RvIHNpZ25pZmljYSBxdWUgdGVuZW1vcyB0b2RvcyBsb3MgdMOpcm1pbm9zIHBlcm1pdGVuIGxhIGV4cGxpY2FjacOzbiBkZSBsYSBzZXJpZS4gCgpgYGB7cn0KZXJyb3JzIDwtIG1vZGVsMiRyZXNpZHVhbHMKYWNmMihlcnJvcnMsbWF4LmxhZyA9IDI0KQoKYGBgCkNvbW8gcG9kZW1vcyB2ZXIsIGxvcyBlcnJvcmVzIHByZXNlbnRhIHVuYSBzZXJpZSBlc3RhY2lvbmFyaWEsIHBlcm8gaGF5IHVuYSBhdXRvY29ycmVsYWNpw7NuIG5lZ2F0aXZhIHkgc2lnbmlmaWNhdGl2YSBlbiBlbCBsYWcgMTIuIEVuIGVzdGUgY2FzbyBlcyByZWxldmFudGUgcG9yIGxvIHF1ZSBkZSBhY3VlcmRvIGNvbiBsb3MgcGF0cm9uZXMgcHJldmlhbWVudGUgbWVuY2lvbmFkb3Mgc2kgZWwgbGFnIGVzIG5lZ2F0aXZvIHkgc2lnbmlmaWNhbnRlIHkgYXBhcmVjZSBlbiBhbWJhcyBncsOhZmljYXMsIG5vIHNlIHNpZ3VlIHVuYSBmaXJtYSBBUigpIHNpbm8gcXVlIHNlIGluY2x1eWUgdW5hIE1BKCkgUT0xIGRlYmlkbyBhIHF1ZSBlcyBsYSBjb3JyZWxhY2nDs24gZXhpc3RlbnRlIGVudHJlIGxhZyAxMiB5IGxvcyBkYXRvcyBzb24gbWVuc3VhbGVzLiAKClBvciBsbyBxdWUgaGFyZW1vcyBlbCBtb2RlbG8gZGUgbnVldm8gYWhvcmEgY29uIGxvcyBudWV2b3MgdmFsb3JlczogCmBgYHtyfQptb2RlbDMgPC0gQXJpbWEobXJhdGUsIG9yZGVyID0gYygxLDAsMCksI3A9MTsgZD0wOyBxPTAKICAgIHNlYXNvbmFsID0gbGlzdChvcmRlcj1jKDAsMSwxKSxwZXJpb2Q9MTIpLCAjUD0wLEQ9MSxRPTEKICAgIGluY2x1ZGUuY29uc3RhbnQgPSBUUlVFLAogICAgbGFtYmRhID0gMCkKY29lZnRlc3QobW9kZWwzKQpgYGAKRWwgY29lZmljaWVudGUgZGVsIHTDqXJtaW5vIEFSICgxKSBlcyAwLjk5NDEyMDQgeSBlcyBzaWduaWZpY2F0aXZhbWVudGUgcG9zaXRpdm8uIEVzdG8gc2lnbmlmaWNhIHF1ZTpFbCBwb3JjZW50YWplIGRlbCBjcmVjaW1pZW50byBhbnVhbCBkZWwgdGlwbyBkZSBjYW1iaW8gdGllbmUgdW5hIHJlbGFjacOzbiBzaWduaWZpY2F0aXZhIHkgcG9yc2l0aXZhIHJlc3BlY3RvIGEgc3UgcHJvcGlvIGNyZWNpbWVpbnRvIGFudWFsIGRlbCBtZXMgYW50ZXJpb3IuCgpFbCBjb2VmaWNpZW50ZSBkZWwgdMOpcm1pbm8gQVIgKDEpIGVzdGFjaW9uYWwgZXMgLTAsOTM4MTQ2MSB5IGVzIHNpZ25pZmljYXRpdmFtZW50ZSBuZWdhdGl2bywgbG8gcXVlIHNpZ25pZmljYSBxdWUgZWwgcG9yY2VudGFqZSBkZSBjcmVjaW1pZW50byBhbnVhbCBkZWwgdGlwbyBkZSBjYW1iaW8gZXN0YSByZWxhY2lvbmFkbyBuZWdhdGl2YW1lbnRlIHkgc2lnbmlmaWNhdGl2YW1lbnRlIGNvbiBzdSBwcm9waW8gY3JlY2ltaWVudG8gYW51YWwgZGUgaGFjZSAxMiBtZXNlcy4gRW4gb3RyYXMgcGFsYWJyYXMsIHNpIGVsIGNhbWJpbyBjcmVjacOzIGhhY2UgMTIgbWVzZXMgZXMgcHJvYmFibGUgcXVlIGVzdGUgYmFqZS4KClVuYSB2ZXogbcOhcyBjb3Jyb2JvcmFyZW1vcyBzaSBsb3MgZXJyb3Jlcy9yZXNpZHVhbGVzIHBhcmEgdmVyIHNpIGVzdG9zIHNpZ3VlbiB1bmEgc2VyaWUgZXN0YWNpb25hcmlhLiAKCmBgYHtyfQplcnJvcnMgPC0gbW9kZWwzJHJlc2lkdWFscwphY2YyKGVycm9ycyxtYXgubGFnID0gMjQpCgoKYGBgCk51ZXN0cm8gbW9kZWxvIHNlIGFqdXN0YSBiaWVuIGRlYmlkbyBhIHF1ZSBoYXkgUnVpZG8gQmxhbmNvLCBwLXZhbHVlIGVzIG1heW9yIGEgMC4wNS4KYGBge3J9CkJveC50ZXN0KHJlc2lkdWFscyhtb2RlbDMpLHR5cGU9IkxqdW5nLUJveCIpCmBgYApDb21vIHBvZGVtb3MgdmVyLCBhaG9yYSBzaSBzZSBtdWVzdHJhIHVuYSBzZXJpZSBlc3RhY2lvbmFyaWEgcG9yIGxvIHF1ZSBwcm9jZWRlcmVtb3MgYSBoYWNlciBsYSBwcmVkaWNjacOzbiBkZSBsb3MgdmFsb3Jlcy4gCgpIYXJlbW9zIHVuIHByb27Ds3N0aWNvIHBhcmEgZWwgdGlwbyBkZSBjYW1iaW8gZGUgbG9zIHNpZ3VpZW50ZXMgMTggbWVzZXMgdXNhbmRvIG51ZXN0cm8gbW9kZWxvIGNhbGlicmFkby4gCgpgYGB7cn0KI1NlIHV0aWxpemEgbGEgZnVuY2nDs24gZm9yZWNhc3QgcGFyYSBwcmVkZWNpciBsb3MgdmFsb3JlcyBmdXR1cm9zIGRlIGxvcyBzaWd1aWVudGVzIDE4IG1lc2VzCm1yYXRlX2ZvcmVjYXN0IDwtIGZvcmVjYXN0KG1vZGVsMywgaD0xOCkKYXV0b3Bsb3QobXJhdGVfZm9yZWNhc3QpCgpgYGAKCkNvbW8gcG9kZW1vcyB2ZXIsIGVuIGVsIGdyw6FmaWNvIHNlIGFycm9qYSBlbCBwcm9uw7NzdGljbyBwYXJhIGVsIHRpcG8gZGUgY2FtYmlvIGVuIGNvbG9yIHZpb2xldGEuIEVsIGVycm9yIGRlbCBwcm9uw7NzdGljbyBlcyBhbHRvIHlhIHF1ZSBjb24gdW4gaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBkZWwgOTUlIG9zY2lsYW4gbG9zIHZhbG9yZXMgZW50cmUgMTctMjcgTVhOLiAKCkZpbmFsbWVudGUsIGNhbGN1bGVtb3MgbG9zIHZhbG9yZXMgcGFyYSBsb3Mgc2lndWllbnRlcyAxOCBtZXNlcyBkZSBtYW5lcmEgcHVudHVhbCwgc2llbmRvIGVzdG9zIGVsIHByb21lZGlvIGRlIGNhZGEgbWVzLiAKCmBgYHtyfQp0YWlsKG1yYXRlX2ZvcmVjYXN0JG1lYW4sMTgpCmBgYApSZWZlcmVuY2lhczogCmh0dHBzOi8vd3d3Lm1hY2hpbmVsZWFybmluZ3BsdXMuY29tL3RpbWUtc2VyaWVzL2FyaW1hLW1vZGVsLXRpbWUtc2VyaWVzLWZvcmVjYXN0aW5nLXB5dGhvbi8KaHR0cHM6Ly9ycHVicy5jb20vY2RvcmFudGUvZnoyMDIwX3czCmh0dHBzOi8vcnB1YnMuY29tL1N0ZWZhbjI0MHN4L2UxZmUyCmh0dHBzOi8vcnB1YnMuY29tL1JhZmFlbF9Sb21vLzc3OTk4NQpodHRwczovL3d3dy5lc3RhZGlzdGljYS5uZXQvRUNPTk9NRVRSSUEvU0VSSUVTLVRFTVBPUkFMRVMvbW9kZWxvLWFyaW1hLnBkZgpodHRwczovL3d3dy5yZXNlYXJjaGdhdGUubmV0L3B1YmxpY2F0aW9uLzMyODYzMzcwNl9Gb3JlY2FzdGluZ19vZl9kZW1hbmRfdXNpbmdfQVJJTUFfbW9kZWwKaHR0cHM6Ly93d3cuc2NpZW5jZWRpcmVjdC5jb20vc2NpZW5jZS9hcnRpY2xlL2Ficy9waWkvUzAzNjA4MzUyOTgwMDA2NjcKCgo=