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:
- ACF nos indica la autocorrelación entre los valores de las series
que se encuentran a k intervalos de distancia.
- PACF nos indica las autocorrelación entre los valores de las series
que se encuentran a k intervalos de distancia, teniendo en cuenta los
valores de los intervalos intermedios.
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.
- Si es significativa y positiva entonces P = 1 y Q = 0.
- Si es significativa y negativa, definimos P = 0 y Q = 1.
- Si no hay una autocorrelación significativa, entonces P = 0 y Q =
0.
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=