Representación Gráfica
En primera instancia se realiza una representación gráfica para
observar si la serie es estacionaria.
plot(datos$sub, type = "l", xlab = "", ylab = "%", main = "")

Sin embargo, el análisis gráfico no es suficiente para observar esta
propiedad. Por lo tanto, se procede a realizar una prueba que contribuya
a demostrar estacionariedad.
Prueba Dicky Fuller (nivel de
significancia 5%)
El objetivo de esta prueba es observar si la serie a utilizar es
estacionaria o no, esto quiere decir que los momentos estadísticos no
dependan del tiempo. Esta prueba aumentada de Dickey-Fuller se estima
con una regresión auxiliar. La ecuación asociada es:
\[\begin{align*}
\Delta y_t = \beta_0 + \delta t + \phi y_{t-1} + \sum_{i=1}^{p}\beta
\Delta y_{t-i}+e_t
\end{align*}\]
La hipotesis asociada a la prueba es la siguiente: \[\begin{align*}
H_0: \phi = 0 \\
H_a: \phi \neq 0
\end{align*}\]
Si se rechaza H0 la serie no tiene raíz unitaria, por lo tanto, la
serie es estacionaria.
Se usará un nivel de significancia del 5%
Realizando por primera vez la prueba se observa lo siguiente:
sub.ts <- ts(datos ,start = c(2005,01), end = c(2022,02), frequency = 4)#Convirtiendo a series de tiempo
adf.sub.trend <- ur.df(sub.ts[,"sub"], type = "trend", selectlags = "BIC")
summary(adf.sub.trend)
###############################################
# Augmented Dickey-Fuller Test Unit Root Test #
###############################################
Test regression trend
Call:
lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)
Residuals:
Min 1Q Median 3Q Max
-1.6583 -0.7816 -0.2154 0.1732 15.8679
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.48845 0.91843 2.709 0.00864 **
z.lag.1 -0.37481 0.11449 -3.274 0.00171 **
tt 0.02132 0.01487 1.433 0.15670
z.diff.lag -0.11018 0.12419 -0.887 0.37829
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.143 on 64 degrees of freedom
Multiple R-squared: 0.219, Adjusted R-squared: 0.1824
F-statistic: 5.981 on 3 and 64 DF, p-value: 0.001168
Value of test-statistic is: -3.2736 3.5754 5.3605
Critical values for test statistics:
1pct 5pct 10pct
tau3 -4.04 -3.45 -3.15
phi2 6.50 4.88 4.16
phi3 8.73 6.49 5.47
Debido a que el valor de test-statistic no es más negativo que el
valor de tau3 en un nivel de significancia al 5%, NO se rechaza H0. Por
otro lado, ya que el valor test-statistic 3.57 no es mayor al valor de
phi2, en un nivel de significancia de 5%, NO se rechaza H0.
Debido a que la serie sigo contando con raíz unitaria, se realiza
otra prueba removiendo la tendencia con la función “drift”.
adf.sub.drift <- ur.df(sub.ts[,"sub"], type = "drift", selectlags = "BIC")
summary(adf.sub.drift)
###############################################
# Augmented Dickey-Fuller Test Unit Root Test #
###############################################
Test regression drift
Call:
lm(formula = z.diff ~ z.lag.1 + 1 + z.diff.lag)
Residuals:
Min 1Q Median 3Q Max
-1.3886 -0.5929 -0.2755 -0.0318 16.4390
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.6016 0.9224 2.820 0.00635 **
z.lag.1 -0.3001 0.1027 -2.920 0.00480 **
z.diff.lag -0.1464 0.1226 -1.195 0.23657
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.16 on 65 degrees of freedom
Multiple R-squared: 0.1939, Adjusted R-squared: 0.1691
F-statistic: 7.818 on 2 and 65 DF, p-value: 0.000907
Value of test-statistic is: -2.9204 4.267
Critical values for test statistics:
1pct 5pct 10pct
tau2 -3.51 -2.89 -2.58
phi1 6.70 4.71 3.86
Ya que el valor de test-statistic (-2.89) es más negativo que el
valor de tau (-2.89) en un nivel de significancia al 5%, se rechaza
H0.
Se concluye que la serie es estacionaria y NO tiene raíz
unitaria. El modelo es estacionario y tiene un orden de
integración de cero.
Validación Modelo ARMA (1,1)
Estimación Modelo ARMA(1,1)
modelo.arma <- arima(datos$sub, order = c(1, 0, 1))
modelo.arma
Call:
arima(x = datos$sub, order = c(1, 0, 1))
Coefficients:
ar1 ma1 intercept
0.7543 -0.1997 8.6170
s.e. 0.1099 0.1619 0.7814
sigma^2 estimated as 4.354: log likelihood = -151.1, aic = 310.19
summary(modelo.arma)
Call:
arima(x = datos$sub, order = c(1, 0, 1))
Coefficients:
ar1 ma1 intercept
0.7543 -0.1997 8.6170
s.e. 0.1099 0.1619 0.7814
sigma^2 estimated as 4.354: log likelihood = -151.1, aic = 310.19
Training set error measures:
ME RMSE MAE MPE MAPE MASE
Training set 0.003161995 2.086719 0.7425833 -2.635958 7.224152 0.8729572
ACF1
Training set 0.0003464964
Prueba Individual
par(mfrow = c(1,2))
acf(modelo.arma$residuals, lag = 20)
pacf(modelo.arma$residuals, lag = 20)

Debido a que la estructura en el AC y ACP se encuentran dentro de las
bandas de confianza, se concluye que es un modelo
adecuado.
Prueba Conjunta
Por otro lado, en la Prueba Conjunta de Lyung, se busca observar si
hay estructura de autocorrelación.
Box.test(modelo.arma$residuals, type = "Ljung", lag = 20)
Box-Ljung test
data: modelo.arma$residuals
X-squared = 2.1167, df = 20, p-value = 1
La hipotesis asociada a la prueba es la siguiente:
\[\begin{align*}
H_0: \rho_1 = \rho_2 =0 \\
H_a: \textrm{Al menos un parámetro es distinto de 0}
\end{align*}\]
Si p-valor > 0.05 NO se rechaza H0
Debido a que el p-valor (1) es mayor a 0.05, NO se rechaza H0, por lo
tanto,
NO hay estructura de autocorrelación en el modelo, lo
cual lo hace un modelo válido.
Refinación del Modelo ARMA(1,1)
Mediante este proceso se busca observar si hay parámetros que no son
significativos, lo cual significaría que no aportan al modelo en
cuestión. Esto se realizará con la prueba “Coeftest”.
coeftest(modelo.arma, df = 67)
t test of coefficients:
Estimate Std. Error t value Pr(>|t|)
ar1 0.75427 0.10985 6.8662 2.627e-09 ***
ma1 -0.19970 0.16191 -1.2334 0.2217
intercept 8.61699 0.78141 11.0274 < 2.2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#df = observaciones - parámetros
#df = 70 - 3
En esta prueba se observa que el MA es un parámetro NO significativo,
por lo tanto, es necesario refinar el modelo. Esto se
realizará asignando un cero a dicho parámetro NO significativo.
modelo.arma.ref <- arima(subocupacion, transform.pars = TRUE, order = c(1, 0, 1), fixed = c(NA,0,NA))
modelo.arma.ref
Call:
arima(x = subocupacion, order = c(1, 0, 1), transform.pars = TRUE, fixed = c(NA,
0, NA))
Coefficients:
ar1 ma1 intercept
0.6395 0 8.6172
s.e. 0.0895 0 0.6818
sigma^2 estimated as 4.442: log likelihood = -151.78, aic = 309.56
Correlograma de Modelo Refinado
par(mfrow = c(1,2))
acf(modelo.arma.ref$residuals, lag = 20)
pacf(modelo.arma.ref$residuals, lag = 20)

Debido a que se observa que todos las estructuras se encuentran
dentro de las bandas de confianza, este será el nuevo modelo a utilizar.
Es necesario mencionar que dicho modelo refinado se transforma en un
modelo AR1, debido a que el MA no sale significativa.
Probar Estacionariedad
Finalmente, se realizará una prueba de estacionariedad mediante la
obtención de las raíces del polinomio característico. En dicha prueba es
necesario tomar en cuenta el valor de la raíz, debido a que si esta es
mayor a 1, se considera que el modelo es estacionario.
pol.car.arma <-c(1,-modelo.arma.ref$coef[1])
raices <- polyroot(pol.car.arma)
abs(raices)
[1] 1.563666
Debido a que la raíz del polinomio característico es mayor a 1, se
concluye que dicho modelo es estacionario.
2. Pronóstico de la Tasa de
Subocupación
Con el objetivo de utilizar el mejor modelo adecuado para realizar un
pronóstico óptimo, es necesario generar otro modelo en el cual se
utilizará auto arima; una función automática que expone el mejor modelo
a su consideración. Por lo tanto, dicho modelo estimado por auto arima,
será comparado con el modelo ARMA (1,1) propuesto en la sección
anterior.
Estimación Auto Arima
auto.sub <- auto.arima(subocupacion, d = 0, seasonal = F, ic = "bic")
auto.sub
Series: subocupacion
ARIMA(1,0,0) with non-zero mean
Coefficients:
ar1 mean
0.6395 8.6172
s.e. 0.0895 0.6818
sigma^2 = 4.573: log likelihood = -151.78
AIC=309.56 AICc=309.92 BIC=316.31
El modelo propuesto por la función auto arima arroja una sugerencia
de modelo AR1.
Es necesario mencionar que en la sección anterior se encontró
como modelo refinado un AR(1), asimismo, el modelo autoarima arrojó
AR(1). Con el objetivo de realizar una comparación óptima entre modelos
distintos, se decidió utilizar el modelo original (ARMA(1,1)) y no el
refinado, con el fin de realizar una comparación con el modelo autoarima
(AR(1)).
Posteriormente, se validara el modelo mediante un correlograma, en
donde se identifique si dicho modelo sigue un proceso de Ruido Blanco,
lo cual, significaría que no tiene autocorrelación, por lo tanto, esta
sería estadísticamente cero.
Validación Modelo Auto Arima
par(mfrow = c(1,2))
acf(auto.sub$residuals, lag = 20)
pacf(auto.sub$residuals, lag = 20)

Se observa que el modelo AR(1) sigue un proceso de Ruido Blanco, por
lo tanto, es un modelo adecuado.
En la generación de pronósticos se puede presentar el “error
sobreajuste”, el cual quiere decir que los valores de los pronósticos es
generado conforme a valores de “y”. Por lo tanto, se debe de dividir la
muestra en grupos de entrenamiento y prueba. El conjunto de
entrenamiento sirve para realizar un pronóstico que después se comparará
con los valores de prueba.
Generación de grupos de entrenamiento y
prueba
entrenamiento <- subset(sub.ts[,"sub"], end = length(sub.ts[,"sub"])- 14)
prueba <- subset(sub.ts[,"sub"], start = length(sub.ts[,"sub"])- 13)
Estimación de Modelos
arma11.entrenamiento <- Arima(entrenamiento, order = c(1,0,1))
ar1.entrenamiento <- Arima(entrenamiento, order = c(1,0,0))
Representación Gráfica
Pronóstico del modelo ARMA (1,1):
#ARMA(1,1)
arma11.entrenamiento %>%
forecast(h=20) %>%
autoplot(xlab = "", ylab = "Tasa de subocupación (%)") + autolayer(prueba)

Pronóstico del modelo AR(1):
#AR(1)
ar1.entrenamiento %>%
forecast(h=20) %>%
autoplot(xlab = "", ylab = "Tasa de subocupación (%)") + autolayer(prueba)

Con el objetivo de comparar cuál de los pronósticos es mejor, se
realiza lo siguiente.
Comparación de ambos modelos mediante la
prueba Diebold Mariano
La prueba Diebold Mariano, tiene como objetivo analizar si existe una
diferencia sistemática entre los errores de los modelos, en dado caso de
que sí, se considera mejor modelo el cual tenga un error menor.
sub.pron.arma11 <- forecast(arma11.entrenamiento, h = 20)
sub.pron.ar1 <- forecast(ar1.entrenamiento, h = 20)
Error del pronóstico
e.arma11 <- prueba - sub.pron.arma11$mean
e.ar1 <- prueba - sub.pron.ar1$mean
Error absoluto medio (MAE)
El Error Absoluto Medio se calcula con la siguiente fórmula:
\[\begin{align*}
MAE = \frac{1}{p} \sum_{i=1}^{p}\left|y_{1}-f_{i} \right|
\end{align*}\]
options(digits = 4)
MAE.arma11 <- sum(abs(e.arma11))/length(prueba)
MAE.arma11
[1] 4.14
MAE.ar1 <- sum(abs(e.ar1))/length(prueba)
MAE.ar1
[1] 4.059
En este caso los errores reflejan un valor alto debido a la gráfica
observada, puesto que durante la pandemia se observaron resultados que
no siguieron la tendencia de dicha tasa de subocupación, ya que este
evento se relaciona con la teoría black swan, en donde dicho evento
desató un gran impacto en el país.
Prueba Diebold Mariano
Debido a que no es suficiente observar el mejor modelo solo
comparando los MAE, es necesario realizar una prueba que arroje si
existe una diferencia sistemática entre los errores.
#Adaptación a rolling window (se debe hacer previo a la prueba DM)
farma11 <- function(x, h){forecast(Arima(x, order=c(1,0,1)), h=h)}
far1 <- function(x, h){forecast(Arima(x, order=c(1,0,0)), h=h)}
e.arma11.rw <- tsCV(sub.ts[,"sub"], farma11, h = 1, window = 56)
e.ar1.rw <- tsCV(sub.ts[,"sub"], far1, h = 1, window = 56)
dm.test(abs(e.arma11.rw), abs(e.ar1.rw),
alternative = "two.sided", h = 1, power = 1)
Diebold-Mariano Test
data: abs(e.arma11.rw)abs(e.ar1.rw)
DM = 0.77, Forecast horizon = 1, Loss function power = 1, p-value = 0.4
alternative hypothesis: two.sided
La hipotesis asociada a la prueba es la siguiente: \[\begin{align*}
H_0: \bar{d} = 0 \\
H_a: \bar{d} \neq 0
\end{align*}\]
Debido a que el p-valor > 0.05, NO se rechaza H0. Por lo tanto, no
hay una diferencia sistemática entre los errores.
Sin embargo, tomando en cuenta que se tomó ARMA(1,1) solo con el
objetivo de realizar una comparación entre lo propuesto por auto arima,
y que con el modelo refinado se obtuvo un AR(1), se tomará como mejor
modelo AR(1).
Pronóstico
pron.ar1 = forecast(auto.sub, h = 20)
pron.ar1
ar1.entrenamiento %>%
forecast(h=20) %>%
autoplot(xlab = "", ylab = "Tasa de subocupación (%)") + autolayer(prueba)

CONCLUSIÓN
De acuerdo con el modelo AR(1), el pronóstico para el siguiente
trimestre de la tasa de subocupación en México, es de 8.695%, se observa
que este porcentaje va disminuyendo a lo largo del tiempo, hasta que
transcurren aproximadamente 12 periodos (trimestres), que es cuando
tiende a la media (8.617%).
REFERENCIAS
BIBLIOGRÁFICAS
ANEXOS
CÓDIGO RSTUDIO aquí
LS0tCnRpdGxlOiAiRXZpZGVuY2lhX2EwMTI4NDM1NCIKYXV0aG9yOiAiQW5nZWxhIE3DumppY2EgLyBBMDEyODQzNTQiCmRhdGU6ICcyMDIyLTEwLTE4JwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAotLS0KCmBgYHtyLGluY2x1ZGU9RkFMU0V9CiNQYXF1ZXRlcsOtYSBuZWNlc2FyaWEKbGlicmFyeShmcHAyKQpsaWJyYXJ5KHVyY2EpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShsbXRlc3QpCmxpYnJhcnkoZm9yZWNhc3QpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KE1MbWV0cmljcykKbGlicmFyeShzYW5kd2ljaCkKYGBgCgoKCiMjIyMgRWNvbm9tZXRyw61hIDIKCiMjIyMgR3J1cG8gMTAyCgojIDxiIHN0eWxlID0gJ2NvbG9yIDogYmxhY2s7IGZvbnQtc2l6ZTogNDBweDsnPgoqKkVWSURFTkNJQSBQUk9Ow5NTVElDT1MgREUgTEEgRUNPTk9Nw41BKio8L2I+CgojIyA8YiBzdHlsZSA9ICdjb2xvciA6IGJsYWNrOyc+KklOVFJPRFVDQ0nDk04qPC9iPgoKRGUgYWN1ZXJkbyBjb24gbGEgT3JnYW5pemFjacOzbiBJbnRlcm5hY2lvbmFsIGRlbCBUcmFiYWpvIChPSVQpLCBsYSBzdWJvY3VwYWNpw7NuIGVzIGRlZmluaWRhIGNvbW8gbGEgc2l0dWFjacOzbiBlbiBsYSBjdWFsIGxvcyB0cmFiYWphZG9yZXMgcmVkdWNlbiBzdXMgaG9yYXMgZGUgdHJhYmFqbyB5IGxhYm9yYW4gZW4gZW1wbGVvcyBtZW5vcyBzYXRpc2ZhY3RvcmlvcyBjb24gZWwgb2JqZXRpdm8gZGUgZXZpdGFyIGVsIGRlc2VtcGxlbyAoTW9yYWxlcywgcy5mLikuIERlIGFjdWVyZG8gY29uIHVuIGVzdHVkaW8gcmVhbGl6YWRvIHBvciBDbGFyYSBKdWRpc21hbiwgcXVpw6luIGZ1bmdpw7MgY29tbyBEaXJlY3RvcmEgR2VuZXJhbCBkZWwgUmVnaXN0cm8gTmFjaW9uYWwgZGUgRWxlY3RvcmVzIGVuIE3DqXhpY28sIGVuIGxhcyBuYWNpb25lcyBkZSBtZW5vciBkZXNhcnJvbGxvIHJlc3VsdGEgbcOhcyBlZmVjdGl2byBlbCBhbsOhbGlzaXMgZGUgbGEgc3Vib2N1cGFjacOzbiBlbiBsdWdhciBkZSBlbCBhbsOhbGlzaXMgZGVsIGRlc2VtcGxlbywgZXN0byBzdWNlZGUgZGViaWRvIGEgcXVlIGRlIGFjdWVyZG8gY29uIEIuIERhdHRhIGVsIHByb2JsZW1hIHByaW5jaXBhbCBlbiBlc3RvcyBwYcOtc2VzICJubyBlcyBlbCB2b2x1bWVuLCBuw7ptZXJvIG8gcHJvcG9yY2nDs24gZGUgcGVyc29uYXMgZW1wbGVhZGFzLCBzaW5vIGVsIGdyYWRvIGRlbCBlbXBsZW8iIChKdWRpc21hbixzLmYsIHAuMjY5KS4gRW4gTcOpeGljbywgZ3JhbiBwb3JjZW50YWplIGRlIGxhIHBvYmxhY2nDs24gY2FyZWNlIGRlIHJlY3Vyc29zIGZpbmFuY2llcm9zIHBhcmEgcG9kZXIgbGFib3JhciBlbiB1biB0cmFiYWpvIGFkZWN1YWRvLCBvIGNvbiB1biBwZXJpb2RvIGxhcmdvLCBwb3IgbG8gdGFudG8sIGxvcyBpbmRpdmlkdW9zIHByZWZpZXJlbiB0b21hciBjdWFscXVpZXIgZW1wbGVvIGFudGVzIGRlIHBlcm1hbmVjZXIgZGVzZW1wbGVhZG9zIChKdWRpc21hbixzLmYscC4gMjc1KS4gUG9yIG90cm8gbGFkbywgQmFudGVndWkgcGxhbnRlYSBxdWUgImxhIGluYWRlY3VhZGEgdXRpbGl6YWNpw7NuIGRlIGxhIGZ1ZXJ6YSBkZSB0cmFiYWpvIG5vIHNlIGV4cHJlc2EgcG9yIGVsIGRlc2VtcGxlbywgc2lubywgZW4gbGEgY2FyZW5jaWEgZGUgZW1wbGVvcyBzYXRpc2ZhY3RvcmlvcyIgKEp1ZGlzbWFuLHMuZixwLiAyNzUpLiBEZWJpZG8gYSBlc3RvLCBlbiBlbCBwcmVzZW50ZSB0cmFiYWpvIHNlIHJlYWxpemFyw6EgdW4gcHJvbsOzc3RpY28gZGUgbGEgdmFyaWFibGUgZGUgc3Vib2N1cGFjacOzbiBjb24gZWwgcHJvZ3JhbWEgUiBTdHVkaW8uIEVuIGVzdGUgY2FzbyBzZSB1dGlsaXphcsOhIHVuYSBiYXNlIGRlIGRhdG9zIG9idGVuaWRhIGRlbCBJTkVHSSwgbGEgY3VhbCBjdWVudGEgY29uIDcwIG9ic2VydmFjaW9uZXMuIFBvciBvdHJvIGxhZG8sIGxhIHNlcmllIGVzIGRlIGxhIHZhcmlhY2nDs24gdHJpbWVzdHJhbCBkZSBsYSB0YXNhIGRlIHN1Ym9jdXBhY2nDs24gZW4gTcOpeGljbywgeSBzZSB0b21hcm9uIGRhdG9zIGRlc2RlIGVsIHByaW1lciB0cmltZXN0cmUgZGVsIGHDsW8gMjAwNSwgYWwgc2VndW5kbyB0cmltZXN0cmUgZGVsIGHDsW8gMjAyMi4gCgoKIyMgPGIgc3R5bGUgPSAnY29sb3IgOiBibGFjazsnPipERVNBUlJPTExPKjwvYj4KMS4gTW9kZWxhciBsYSBzZXJpZSBkZSBUaWVtcG8KICAqIFJlcHJlc2VudGFjacOzbiBHcsOhZmljYQogICogUHJ1ZWJhIERpY2tleSBGdWxsZXIKICAqIElkZW50aWZpY2FyIGVsIE1vZGVsbwogICogVmFsaWRhY2nDs24gZGUgTW9kZWxvCiAgKiBSZWZpbmFjacOzbiBkZWwgTW9kZWxvCjIuIFByb27Ds3N0aWNvIGRlIGxhIFRhc2EgZGUgU3Vib2N1cGFjacOzbgogICogRXN0aW1hY2nDs24gQXV0byBBcmltYQogICogR2VuZXJhY2nDs24gZGUgR3J1cG9zIGRlIEVudHJlbmFtaWVudG8geSBQcnVlYmEKICAqIENvbXBhcmFjacOzbiBkZSBNb2RlbG9zIC0gUHJ1ZWJhIERpYWJvbGQgTWFyaWFubwogICogUHJvbsOzc3RpY28KCiMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IGJsYWNrOyc+KioxLiBNb2RlbGFyIGxhIFNlcmllIGRlIFRpZW1wbyoqPC9iPgoKIyMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IGdyYXk7Jz5MZWN0dXJhIGRlIGJhc2UgZGUgZGF0b3MgPC9iPgpgYGB7cn0KZGF0b3MgPC0gcmVhZF9leGNlbCgifi9EZXNrdG9wL01FzIFUT0RPU18gUi9zdWJvY3VwYWNpb24ueGxzeCIpCmRhdGUgPSBhcy5EYXRlKGRhdG9zJEZlY2hhLCBmb3JtYXQgPSAiJVkvJW0vJWQiKQpzdWJvY3VwYWNpb24gPSBkYXRvcyRzdWIKYGBgCiMjIyMgPGIgc3R5bGUgPSAnY29sb3IgOiByZWQ7Jz4gUmVwcmVzZW50YWNpw7NuIEdyw6FmaWNhIDwvYj4gCkVuIHByaW1lcmEgaW5zdGFuY2lhIHNlIHJlYWxpemEgdW5hIHJlcHJlc2VudGFjacOzbiBncsOhZmljYSBwYXJhIG9ic2VydmFyIHNpIGxhIHNlcmllIGVzIGVzdGFjaW9uYXJpYS4gCgpgYGB7cn0KcGxvdChkYXRvcyRzdWIsIHR5cGUgPSAibCIsIHhsYWIgPSAiIiwgeWxhYiA9ICIlIiwgbWFpbiA9ICIiKQpgYGAKClNpbiBlbWJhcmdvLCBlbCBhbsOhbGlzaXMgZ3LDoWZpY28gbm8gZXMgc3VmaWNpZW50ZSBwYXJhIG9ic2VydmFyIGVzdGEgcHJvcGllZGFkLiAgIFBvciBsbyB0YW50bywgc2UgcHJvY2VkZSBhIHJlYWxpemFyIHVuYSBwcnVlYmEgcXVlIGNvbnRyaWJ1eWEgYSBkZW1vc3RyYXIgICAgICAgIGVzdGFjaW9uYXJpZWRhZC4gIAoKIyMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IHJlZDsnPiBQcnVlYmEgRGlja3kgRnVsbGVyIChuaXZlbCBkZSBzaWduaWZpY2FuY2lhIDUlKSA8L2I+IAoKRWwgb2JqZXRpdm8gZGUgZXN0YSBwcnVlYmEgZXMgb2JzZXJ2YXIgc2kgbGEgc2VyaWUgYSB1dGlsaXphciBlcyBlc3RhY2lvbmFyaWEgbyBubywgZXN0byBxdWllcmUgZGVjaXIgcXVlIGxvcyBtb21lbnRvcyBlc3RhZMOtc3RpY29zIG5vIGRlcGVuZGFuIGRlbCB0aWVtcG8uIEVzdGEgcHJ1ZWJhIGF1bWVudGFkYSBkZSBEaWNrZXktRnVsbGVyIHNlIGVzdGltYSBjb24gdW5hIHJlZ3Jlc2nDs24gYXV4aWxpYXIuIApMYSBlY3VhY2nDs24gYXNvY2lhZGEgZXM6CgpcYmVnaW57YWxpZ24qfQpcRGVsdGEgeV90ID0gXGJldGFfMCArIFxkZWx0YSB0ICsgXHBoaSB5X3t0LTF9ICsgXHN1bV97aT0xfV57cH1cYmV0YSBcRGVsdGEgeV97dC1pfStlX3QKXGVuZHthbGlnbip9CgpMYSBoaXBvdGVzaXMgYXNvY2lhZGEgYSBsYSBwcnVlYmEgZXMgbGEgc2lndWllbnRlOgpcYmVnaW57YWxpZ24qfQpIXzA6IFxwaGkgPSAwIFxcCkhfYTogXHBoaSBcbmVxIDAKClxlbmR7YWxpZ24qfQoKU2kgc2UgcmVjaGF6YSBIMCBsYSBzZXJpZSBubyB0aWVuZSByYcOteiB1bml0YXJpYSwgcG9yIGxvIHRhbnRvLCBsYSBzZXJpZSBlcyBlc3RhY2lvbmFyaWEuCgoqU2UgdXNhcsOhIHVuIG5pdmVsIGRlIHNpZ25pZmljYW5jaWEgZGVsIDUlKgoKUmVhbGl6YW5kbyBwb3IgcHJpbWVyYSB2ZXogbGEgcHJ1ZWJhIHNlIG9ic2VydmEgbG8gc2lndWllbnRlOgoKCmBgYHtyfQpzdWIudHMgPC0gdHMoZGF0b3MgLHN0YXJ0ID0gYygyMDA1LDAxKSwgZW5kID0gYygyMDIyLDAyKSwgZnJlcXVlbmN5ID0gNCkjQ29udmlydGllbmRvIGEgc2VyaWVzIGRlIHRpZW1wbwphZGYuc3ViLnRyZW5kIDwtIHVyLmRmKHN1Yi50c1ssInN1YiJdLCB0eXBlID0gInRyZW5kIiwgc2VsZWN0bGFncyA9ICJCSUMiKQpzdW1tYXJ5KGFkZi5zdWIudHJlbmQpCmBgYAoKRGViaWRvIGEgcXVlIGVsIHZhbG9yIGRlIHRlc3Qtc3RhdGlzdGljIG5vIGVzIG3DoXMgbmVnYXRpdm8gcXVlIGVsIHZhbG9yIGRlIHRhdTMgZW4gdW4gbml2ZWwgZGUgc2lnbmlmaWNhbmNpYSBhbCA1JSwgTk8gc2UgcmVjaGF6YSBIMC4gUG9yIG90cm8gbGFkbywgeWEgcXVlIGVsIHZhbG9yIHRlc3Qtc3RhdGlzdGljIDMuNTcgbm8gZXMgbWF5b3IgYWwgdmFsb3IgZGUgcGhpMiwgZW4gdW4gbml2ZWwgZGUgc2lnbmlmaWNhbmNpYSBkZSA1JSwgTk8gc2UgcmVjaGF6YSBIMC4gCgpEZWJpZG8gYSBxdWUgbGEgc2VyaWUgc2lnbyBjb250YW5kbyBjb24gcmHDrXogdW5pdGFyaWEsIHNlIHJlYWxpemEgb3RyYSBwcnVlYmEgcmVtb3ZpZW5kbyBsYSB0ZW5kZW5jaWEgY29uIGxhIGZ1bmNpw7NuICJkcmlmdCIuCgpgYGB7cn0KYWRmLnN1Yi5kcmlmdCA8LSB1ci5kZihzdWIudHNbLCJzdWIiXSwgdHlwZSA9ICJkcmlmdCIsIHNlbGVjdGxhZ3MgPSAiQklDIikKc3VtbWFyeShhZGYuc3ViLmRyaWZ0KQpgYGAKCllhIHF1ZSBlbCB2YWxvciBkZSB0ZXN0LXN0YXRpc3RpYyAoLTIuODkpIGVzIG3DoXMgbmVnYXRpdm8gcXVlIGVsIHZhbG9yIGRlIHRhdSAoLTIuODkpIGVuIHVuIG5pdmVsIGRlIHNpZ25pZmljYW5jaWEgYWwgNSUsIHNlIHJlY2hhemEgSDAuIAoKKipTZSBjb25jbHV5ZSBxdWUgbGEgc2VyaWUgZXMgZXN0YWNpb25hcmlhIHkgTk8gdGllbmUgcmHDrXogdW5pdGFyaWEuKioKKipFbCBtb2RlbG8gZXMgZXN0YWNpb25hcmlvIHkgdGllbmUgdW4gb3JkZW4gZGUgaW50ZWdyYWNpw7NuIGRlIGNlcm8uKioKCiMjIyMgPGIgc3R5bGUgPSAnY29sb3IgOiByZWQ7Jz4gSWRlbnRpZmljYXIgZWwgTW9kZWxvIDwvYj4KIyMjIyMgPGIgc3R5bGUgPSAnY29sb3IgOiBncmF5Oyc+IENvcnJlbG9ncmFtYSA8L2I+CgpDb24gZWwgb2JqZXRpdm8gZGUgaWRlbnRpZmljYXIgZWwgbW9kZWxvIGFkZWN1YWRhbWVudGUgc2UgdXRpbGl6YXLDoSB1biBjb3JyZWxvZ3JhbWEsIGVsIGN1YWwgcGVybWl0aXLDoSBvYnNlcnZhciBzaSBzZSBjdWVudGEgY29uIHVuIG1vZGVsbyBBUiwgTUEgbyBBUk1BLiAKCgpgYGB7cn0KcGFyKG1mcm93ID0gYygxLDIpKQphY2Yoc3Vib2N1cGFjaW9uLCBsYWcgPSAyMCkKcGFjZihzdWJvY3VwYWNpb24sIGxhZyA9IDIwKQpgYGAKClRvbWFuZG8gZW4gY3VlbnRhIHF1ZSBlbCBkZWNhaW1pZW50byBnZW9tw6l0cmljbyBzZSBlbmN1ZW50cmEgZW4gQUNGIHkgQUNQLCBzZSBjb25jbHV5ZSBxdWUgZXMgdW4gbW9kZWxvIEFSTUEgKDEsMSkuIFBvciBsbyB0YW50bywgc2UgZXN0aW1hcsOhIGxhIGZ1bmNpw7NuIGFyaW1hIGNvbW8gdW4gbW9kZWxvIGRlIG9yZGVuICgxLDAsMSkuCgojIyMjIDxiIHN0eWxlID0gJ2NvbG9yIDogcmVkOyc+IFZhbGlkYWNpw7NuIE1vZGVsbyBBUk1BICgxLDEpIDwvYj4gCgojIyMjIyMgPGIgc3R5bGUgPSAnY29sb3IgOiBncmF5Oyc+IEVzdGltYWNpw7NuIE1vZGVsbyBBUk1BKDEsMSkgPC9iPiAKYGBge3J9Cm1vZGVsby5hcm1hIDwtIGFyaW1hKGRhdG9zJHN1Yiwgb3JkZXIgPSBjKDEsIDAsIDEpKSAKbW9kZWxvLmFybWEKc3VtbWFyeShtb2RlbG8uYXJtYSkKYGBgCgojIyMjIyMgPGIgc3R5bGUgPSAnY29sb3IgOiBibHVlOyc+IFBydWViYSBJbmRpdmlkdWFsIDwvYj4gCmBgYHtyfQpwYXIobWZyb3cgPSBjKDEsMikpCmFjZihtb2RlbG8uYXJtYSRyZXNpZHVhbHMsIGxhZyA9IDIwKQpwYWNmKG1vZGVsby5hcm1hJHJlc2lkdWFscywgbGFnID0gMjApCmBgYAoKRGViaWRvIGEgcXVlIGxhIGVzdHJ1Y3R1cmEgZW4gZWwgQUMgeSBBQ1Agc2UgZW5jdWVudHJhbiBkZW50cm8gZGUgbGFzIGJhbmRhcyBkZSBjb25maWFuemEsIHNlIGNvbmNsdXllIHF1ZSBlcyB1biAqKm1vZGVsbyBhZGVjdWFkbyoqLiAKCiMjIyMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IGJsdWU7Jz4gUHJ1ZWJhIENvbmp1bnRhIDwvYj4gCgpQb3Igb3RybyBsYWRvLCBlbiBsYSBQcnVlYmEgQ29uanVudGEgZGUgTHl1bmcsIHNlIGJ1c2NhIG9ic2VydmFyIHNpIGhheSBlc3RydWN0dXJhIGRlIGF1dG9jb3JyZWxhY2nDs24uCmBgYHtyfQpCb3gudGVzdChtb2RlbG8uYXJtYSRyZXNpZHVhbHMsIHR5cGUgPSAiTGp1bmciLCBsYWcgPSAyMCkKYGBgCgpMYSBoaXBvdGVzaXMgYXNvY2lhZGEgYSBsYSBwcnVlYmEgZXMgbGEgc2lndWllbnRlOgoKIApcYmVnaW57YWxpZ24qfQpIXzA6IFxyaG9fMSA9IFxyaG9fMiA9MCBcXApIX2E6IFx0ZXh0cm17QWwgbWVub3MgdW4gcGFyw6FtZXRybyBlcyBkaXN0aW50byBkZSAwfQpcZW5ke2FsaWduKn0KCjxkaXYgc3R5bGUgPSAndGV4dC1hbGlnbjogY2VudGVyJz4KU2kKcC12YWxvciA+IDAuMDUgICBOTyBzZSByZWNoYXphIEgwIAoKPGRpdi8+IAoKCjxkaXYgc3R5bGUgPSAndGV4dC1hbGlnbjogbGVmdCc+CgpEZWJpZG8gYSBxdWUgZWwgcC12YWxvciAoMSkgZXMgbWF5b3IgYSAwLjA1LCBOTyBzZSByZWNoYXphIEgwLCBwb3IgbG8gdGFudG8sICoqTk8gaGF5IGVzdHJ1Y3R1cmEgZGUgYXV0b2NvcnJlbGFjacOzbiBlbiBlbCBtb2RlbG8sIGxvIGN1YWwgbG8gaGFjZSB1biBtb2RlbG8gdsOhbGlkby4qKiAKPGRpdi8+IAoKIyMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IHJlZDsnPiBSZWZpbmFjacOzbiBkZWwgTW9kZWxvIEFSTUEoMSwxKSA8L2I+IApNZWRpYW50ZSBlc3RlIHByb2Nlc28gc2UgYnVzY2Egb2JzZXJ2YXIgc2kgaGF5IHBhcsOhbWV0cm9zIHF1ZSBubyBzb24gc2lnbmlmaWNhdGl2b3MsIGxvIGN1YWwgc2lnbmlmaWNhcsOtYSBxdWUgbm8gYXBvcnRhbiBhbCBtb2RlbG8gZW4gY3Vlc3Rpw7NuLiBFc3RvIHNlIHJlYWxpemFyw6EgY29uIGxhIHBydWViYSAiQ29lZnRlc3QiLiAKCmBgYHtyfQpjb2VmdGVzdChtb2RlbG8uYXJtYSwgZGYgPSA2NykKI2RmID0gb2JzZXJ2YWNpb25lcyAtIHBhcsOhbWV0cm9zCiNkZiA9IDcwIC0gMwpgYGAKCjxkaXYgc3R5bGUgPSAndGV4dC1hbGlnbjogbGVmdCc+CgpFbiBlc3RhIHBydWViYSBzZSBvYnNlcnZhIHF1ZSBlbCBNQSBlcyB1biBwYXLDoW1ldHJvIE5PIHNpZ25pZmljYXRpdm8sIHBvciBsbyB0YW50bywgZXMgKipuZWNlc2FyaW8gcmVmaW5hciBlbCBtb2RlbG8qKi4gRXN0byBzZSByZWFsaXphcsOhIGFzaWduYW5kbyB1biBjZXJvIGEgZGljaG8gcGFyw6FtZXRybyBOTyBzaWduaWZpY2F0aXZvLiAKCjxkaXYvPiAKCmBgYHtyfQptb2RlbG8uYXJtYS5yZWYgPC0gYXJpbWEoc3Vib2N1cGFjaW9uLCB0cmFuc2Zvcm0ucGFycyA9IFRSVUUsIG9yZGVyID0gYygxLCAwLCAxKSwgZml4ZWQgPSBjKE5BLDAsTkEpKQptb2RlbG8uYXJtYS5yZWYKYGBgCgojIyMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IGdyYXk7Jz4gQ29ycmVsb2dyYW1hIGRlIE1vZGVsbyBSZWZpbmFkbyA8L2I+CgpgYGB7cn0KcGFyKG1mcm93ID0gYygxLDIpKQphY2YobW9kZWxvLmFybWEucmVmJHJlc2lkdWFscywgbGFnID0gMjApCnBhY2YobW9kZWxvLmFybWEucmVmJHJlc2lkdWFscywgbGFnID0gMjApCmBgYAoKRGViaWRvIGEgcXVlIHNlIG9ic2VydmEgcXVlIHRvZG9zIGxhcyBlc3RydWN0dXJhcyBzZSBlbmN1ZW50cmFuIGRlbnRybyBkZSBsYXMgYmFuZGFzIGRlIGNvbmZpYW56YSwgZXN0ZSBzZXLDoSBlbCBudWV2byBtb2RlbG8gYSB1dGlsaXphci4gCkVzIG5lY2VzYXJpbyBtZW5jaW9uYXIgcXVlIGRpY2hvIG1vZGVsbyByZWZpbmFkbyBzZSB0cmFuc2Zvcm1hIGVuIHVuIG1vZGVsbyBBUjEsIGRlYmlkbyBhIHF1ZSBlbCBNQSBubyBzYWxlIHNpZ25pZmljYXRpdmEuCgojIyMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IGdyYXk7Jz4gUHJvYmFyIEVzdGFjaW9uYXJpZWRhZCA8L2I+CgpGaW5hbG1lbnRlLCBzZSByZWFsaXphcsOhIHVuYSBwcnVlYmEgZGUgZXN0YWNpb25hcmllZGFkIG1lZGlhbnRlIGxhIG9idGVuY2nDs24gZGUgbGFzIHJhw61jZXMgZGVsIHBvbGlub21pbyBjYXJhY3RlcsOtc3RpY28uIEVuIGRpY2hhIHBydWViYSBlcyBuZWNlc2FyaW8gdG9tYXIgZW4gY3VlbnRhIGVsIHZhbG9yIGRlIGxhIHJhw616LCBkZWJpZG8gYSBxdWUgc2kgZXN0YSBlcyBtYXlvciBhIDEsIHNlIGNvbnNpZGVyYSBxdWUgZWwgbW9kZWxvIGVzIGVzdGFjaW9uYXJpby4gCgpgYGB7cn0KcG9sLmNhci5hcm1hIDwtYygxLC1tb2RlbG8uYXJtYS5yZWYkY29lZlsxXSkKcmFpY2VzIDwtIHBvbHlyb290KHBvbC5jYXIuYXJtYSkKYWJzKHJhaWNlcykKYGBgCgpEZWJpZG8gYSBxdWUgbGEgcmHDrXogZGVsIHBvbGlub21pbyBjYXJhY3RlcsOtc3RpY28gZXMgbWF5b3IgYSAxLCBzZSBjb25jbHV5ZSBxdWUgZGljaG8gbW9kZWxvICoqZXMgZXN0YWNpb25hcmlvKiouCgojIyMgPGIgc3R5bGUgPSAnY29sb3IgOiBibGFjazsnPiAyLiBQcm9uw7NzdGljbyBkZSBsYSBUYXNhIGRlIFN1Ym9jdXBhY2nDs24gPC9iPgoKQ29uIGVsIG9iamV0aXZvIGRlIHV0aWxpemFyIGVsIG1lam9yIG1vZGVsbyBhZGVjdWFkbyBwYXJhIHJlYWxpemFyIHVuIHByb27Ds3N0aWNvIMOzcHRpbW8sIGVzIG5lY2VzYXJpbyBnZW5lcmFyIG90cm8gbW9kZWxvIGVuIGVsIGN1YWwgc2UgdXRpbGl6YXLDoSBhdXRvIGFyaW1hOyB1bmEgZnVuY2nDs24gYXV0b23DoXRpY2EgcXVlIGV4cG9uZSBlbCBtZWpvciBtb2RlbG8gYSBzdSBjb25zaWRlcmFjacOzbi4gUG9yIGxvIHRhbnRvLCBkaWNobyBtb2RlbG8gZXN0aW1hZG8gcG9yIGF1dG8gYXJpbWEsIHNlcsOhIGNvbXBhcmFkbyBjb24gZWwgbW9kZWxvIEFSTUEgKDEsMSkgcHJvcHVlc3RvIGVuIGxhIHNlY2Npw7NuIGFudGVyaW9yLgoKIyMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IHJlZDsnPiBFc3RpbWFjacOzbiBBdXRvIEFyaW1hICA8L2I+IApgYGB7cn0KYXV0by5zdWIgPC0gYXV0by5hcmltYShzdWJvY3VwYWNpb24sIGQgPSAwLCBzZWFzb25hbCA9IEYsIGljID0gImJpYyIpCmF1dG8uc3ViCmBgYAoKRWwgbW9kZWxvIHByb3B1ZXN0byBwb3IgbGEgZnVuY2nDs24gYXV0byBhcmltYSBhcnJvamEgdW5hIHN1Z2VyZW5jaWEgZGUgbW9kZWxvIEFSMS4KCioqRXMgbmVjZXNhcmlvIG1lbmNpb25hciBxdWUgZW4gbGEgc2VjY2nDs24gYW50ZXJpb3Igc2UgZW5jb250csOzIGNvbW8gbW9kZWxvIHJlZmluYWRvIHVuIEFSKDEpLCBhc2ltaXNtbywgZWwgbW9kZWxvIGF1dG9hcmltYSBhcnJvasOzIEFSKDEpLiBDb24gZWwgb2JqZXRpdm8gZGUgcmVhbGl6YXIgdW5hIGNvbXBhcmFjacOzbiDDs3B0aW1hIGVudHJlIG1vZGVsb3MgZGlzdGludG9zLCBzZSBkZWNpZGnDsyB1dGlsaXphciBlbCBtb2RlbG8gb3JpZ2luYWwgKEFSTUEoMSwxKSkgeSBubyBlbCByZWZpbmFkbywgY29uIGVsIGZpbiBkZSByZWFsaXphciB1bmEgY29tcGFyYWNpw7NuIGNvbiBlbCBtb2RlbG8gYXV0b2FyaW1hIChBUigxKSkuKioKClBvc3Rlcmlvcm1lbnRlLCBzZSB2YWxpZGFyYSBlbCBtb2RlbG8gbWVkaWFudGUgdW4gY29ycmVsb2dyYW1hLCBlbiBkb25kZSBzZSBpZGVudGlmaXF1ZSBzaSBkaWNobyBtb2RlbG8gc2lndWUgdW4gcHJvY2VzbyBkZSBSdWlkbyBCbGFuY28sIGxvIGN1YWwsIHNpZ25pZmljYXLDrWEgcXVlIG5vIHRpZW5lIGF1dG9jb3JyZWxhY2nDs24sIHBvciBsbyB0YW50bywgZXN0YSBzZXLDrWEgZXN0YWTDrXN0aWNhbWVudGUgY2Vyby4gCgojIyMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IGdyYXk7Jz4gVmFsaWRhY2nDs24gTW9kZWxvIEF1dG8gQXJpbWEgPC9iPiAKYGBge3J9CnBhcihtZnJvdyA9IGMoMSwyKSkKYWNmKGF1dG8uc3ViJHJlc2lkdWFscywgbGFnID0gMjApCnBhY2YoYXV0by5zdWIkcmVzaWR1YWxzLCBsYWcgPSAyMCkKYGBgCgpTZSBvYnNlcnZhIHF1ZSBlbCBtb2RlbG8gQVIoMSkgc2lndWUgdW4gcHJvY2VzbyBkZSBSdWlkbyBCbGFuY28sIHBvciBsbyB0YW50bywgZXMgdW4gbW9kZWxvIGFkZWN1YWRvLiAKCkVuIGxhIGdlbmVyYWNpw7NuIGRlIHByb27Ds3N0aWNvcyBzZSBwdWVkZSBwcmVzZW50YXIgZWwgImVycm9yIHNvYnJlYWp1c3RlIiwgZWwgY3VhbCBxdWllcmUgZGVjaXIgcXVlIGxvcyB2YWxvcmVzIGRlIGxvcyBwcm9uw7NzdGljb3MgZXMgZ2VuZXJhZG8gY29uZm9ybWUgYSB2YWxvcmVzIGRlICJ5Ii4gUG9yIGxvIHRhbnRvLCBzZSBkZWJlIGRlIGRpdmlkaXIgbGEgbXVlc3RyYSBlbiBncnVwb3MgZGUgZW50cmVuYW1pZW50byB5IHBydWViYS4gRWwgY29uanVudG8gZGUgZW50cmVuYW1pZW50byBzaXJ2ZSBwYXJhIHJlYWxpemFyIHVuIHByb27Ds3N0aWNvIHF1ZSBkZXNwdcOpcyBzZSBjb21wYXJhcsOhIGNvbiBsb3MgdmFsb3JlcyBkZSBwcnVlYmEuICAKCiMjIyMgIDxiIHN0eWxlID0gJ2NvbG9yIDogcmVkOyc+IEdlbmVyYWNpw7NuIGRlIGdydXBvcyBkZSBlbnRyZW5hbWllbnRvIHkgcHJ1ZWJhICA8L2I+CmBgYHtyfQplbnRyZW5hbWllbnRvIDwtIHN1YnNldChzdWIudHNbLCJzdWIiXSwgZW5kID0gbGVuZ3RoKHN1Yi50c1ssInN1YiJdKS0gMTQpCnBydWViYSA8LSBzdWJzZXQoc3ViLnRzWywic3ViIl0sIHN0YXJ0ID0gbGVuZ3RoKHN1Yi50c1ssInN1YiJdKS0gMTMpCmBgYAoKIyMjIyMgPGIgc3R5bGUgPSAnY29sb3IgOiBncmF5Oyc+IEVzdGltYWNpw7NuIGRlIE1vZGVsb3MgPC9iPiAKYGBge3J9CmFybWExMS5lbnRyZW5hbWllbnRvIDwtIEFyaW1hKGVudHJlbmFtaWVudG8sIG9yZGVyID0gYygxLDAsMSkpCmFyMS5lbnRyZW5hbWllbnRvIDwtIEFyaW1hKGVudHJlbmFtaWVudG8sIG9yZGVyID0gYygxLDAsMCkpCmBgYAoKIyMjIyMgPGIgc3R5bGUgPSAnY29sb3IgOiBncmF5Oyc+IFJlcHJlc2VudGFjacOzbiBHcsOhZmljYSAgPC9iPiAKClByb27Ds3N0aWNvIGRlbCBtb2RlbG8gQVJNQSAoMSwxKToKYGBge3J9CiNBUk1BKDEsMSkKCmFybWExMS5lbnRyZW5hbWllbnRvICU+JQogIGZvcmVjYXN0KGg9MjApICU+JQphdXRvcGxvdCh4bGFiID0gIiIsIHlsYWIgPSAiVGFzYSBkZSBzdWJvY3VwYWNpw7NuICglKSIpICsgYXV0b2xheWVyKHBydWViYSkKCmBgYAoKUHJvbsOzc3RpY28gZGVsIG1vZGVsbyBBUigxKToKYGBge3J9CiNBUigxKQphcjEuZW50cmVuYW1pZW50byAlPiUKICBmb3JlY2FzdChoPTIwKSAlPiUKYXV0b3Bsb3QoeGxhYiA9ICIiLCB5bGFiID0gIlRhc2EgZGUgc3Vib2N1cGFjacOzbiAoJSkiKSArIGF1dG9sYXllcihwcnVlYmEpCmBgYAoKCkNvbiBlbCBvYmpldGl2byBkZSBjb21wYXJhciBjdcOhbCBkZSBsb3MgcHJvbsOzc3RpY29zIGVzIG1lam9yLCBzZSByZWFsaXphIGxvIHNpZ3VpZW50ZS4gCgojIyMjIDxiIHN0eWxlID0gJ2NvbG9yIDogcmVkOyc+IENvbXBhcmFjacOzbiBkZSBhbWJvcyBtb2RlbG9zIG1lZGlhbnRlIGxhIHBydWViYSBEaWVib2xkIE1hcmlhbm8gPC9iPiAKCkxhIHBydWViYSBEaWVib2xkIE1hcmlhbm8sIHRpZW5lIGNvbW8gb2JqZXRpdm8gYW5hbGl6YXIgc2kgZXhpc3RlIHVuYSBkaWZlcmVuY2lhIHNpc3RlbcOhdGljYSBlbnRyZSBsb3MgZXJyb3JlcyBkZSBsb3MgbW9kZWxvcywgZW4gZGFkbyBjYXNvIGRlIHF1ZSBzw60sIHNlIGNvbnNpZGVyYSBtZWpvciBtb2RlbG8gZWwgY3VhbCB0ZW5nYSB1biBlcnJvciBtZW5vci4gCgpgYGB7cn0Kc3ViLnByb24uYXJtYTExIDwtIGZvcmVjYXN0KGFybWExMS5lbnRyZW5hbWllbnRvLCBoID0gMjApCnN1Yi5wcm9uLmFyMSA8LSBmb3JlY2FzdChhcjEuZW50cmVuYW1pZW50bywgaCA9IDIwKQpgYGAKCiMjIyMjIDxiIHN0eWxlID0gJ2NvbG9yIDogZ3JheTsnPiBFcnJvciBkZWwgcHJvbsOzc3RpY28gPC9iPiAKYGBge3J9CmUuYXJtYTExIDwtIHBydWViYSAtIHN1Yi5wcm9uLmFybWExMSRtZWFuCmUuYXIxIDwtIHBydWViYSAtIHN1Yi5wcm9uLmFyMSRtZWFuCmBgYAojIyMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IGdyYXk7Jz4gRXJyb3IgYWJzb2x1dG8gbWVkaW8gKE1BRSkgPC9iPiAKCkVsIEVycm9yIEFic29sdXRvIE1lZGlvIHNlIGNhbGN1bGEgY29uIGxhIHNpZ3VpZW50ZSBmw7NybXVsYToKClxiZWdpbnthbGlnbip9Ck1BRSA9IFxmcmFjezF9e3B9IFxzdW1fe2k9MX1ee3B9XGxlZnR8eV97MX0tZl97aX0gXHJpZ2h0fCAKXGVuZHthbGlnbip9CgoKYGBge3J9Cm9wdGlvbnMoZGlnaXRzID0gNCkKTUFFLmFybWExMSA8LSBzdW0oYWJzKGUuYXJtYTExKSkvbGVuZ3RoKHBydWViYSkKTUFFLmFybWExMQpNQUUuYXIxIDwtIHN1bShhYnMoZS5hcjEpKS9sZW5ndGgocHJ1ZWJhKQpNQUUuYXIxCmBgYAoKRW4gZXN0ZSBjYXNvIGxvcyBlcnJvcmVzIHJlZmxlamFuIHVuIHZhbG9yIGFsdG8gZGViaWRvIGEgbGEgZ3LDoWZpY2Egb2JzZXJ2YWRhLCBwdWVzdG8gcXVlIGR1cmFudGUgbGEgcGFuZGVtaWEgc2Ugb2JzZXJ2YXJvbiByZXN1bHRhZG9zIHF1ZSBubyBzaWd1aWVyb24gbGEgdGVuZGVuY2lhIGRlIGRpY2hhIHRhc2EgZGUgc3Vib2N1cGFjacOzbiwgeWEgcXVlIGVzdGUgZXZlbnRvIHNlIHJlbGFjaW9uYSBjb24gbGEgdGVvcsOtYSBibGFjayBzd2FuLCBlbiBkb25kZSBkaWNobyBldmVudG8gZGVzYXTDsyB1biBncmFuIGltcGFjdG8gZW4gZWwgcGHDrXMuCgoKIyMjIyMgPGIgc3R5bGUgPSAnY29sb3IgOiBibHVlOyc+IFBydWViYSBEaWVib2xkIE1hcmlhbm8gPC9iPiAgCgpEZWJpZG8gYSBxdWUgbm8gZXMgc3VmaWNpZW50ZSBvYnNlcnZhciBlbCBtZWpvciBtb2RlbG8gc29sbyBjb21wYXJhbmRvIGxvcyBNQUUsIGVzIG5lY2VzYXJpbyByZWFsaXphciB1bmEgcHJ1ZWJhIHF1ZSBhcnJvamUgc2kgZXhpc3RlIHVuYSBkaWZlcmVuY2lhIHNpc3RlbcOhdGljYSBlbnRyZSBsb3MgZXJyb3Jlcy4KCmBgYHtyfQojQWRhcHRhY2nDs24gYSByb2xsaW5nIHdpbmRvdyAoc2UgZGViZSBoYWNlciBwcmV2aW8gYSBsYSBwcnVlYmEgRE0pCmZhcm1hMTEgPC0gZnVuY3Rpb24oeCwgaCl7Zm9yZWNhc3QoQXJpbWEoeCwgb3JkZXI9YygxLDAsMSkpLCBoPWgpfQpmYXIxIDwtIGZ1bmN0aW9uKHgsIGgpe2ZvcmVjYXN0KEFyaW1hKHgsIG9yZGVyPWMoMSwwLDApKSwgaD1oKX0KZS5hcm1hMTEucncgPC0gdHNDVihzdWIudHNbLCJzdWIiXSwgZmFybWExMSwgaCA9IDEsIHdpbmRvdyA9IDU2KQplLmFyMS5ydyA8LSB0c0NWKHN1Yi50c1ssInN1YiJdLCBmYXIxLCBoID0gMSwgd2luZG93ID0gNTYpCmRtLnRlc3QoYWJzKGUuYXJtYTExLnJ3KSwgYWJzKGUuYXIxLnJ3KSwKICAgICAgICBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiLCBoID0gMSwgcG93ZXIgPSAxKQpgYGAKTGEgaGlwb3Rlc2lzIGFzb2NpYWRhIGEgbGEgcHJ1ZWJhIGVzIGxhIHNpZ3VpZW50ZToKXGJlZ2lue2FsaWduKn0KSF8wOiBcYmFye2R9ID0gMCBcXApIX2E6IFxiYXJ7ZH0gXG5lcSAwCgpcZW5ke2FsaWduKn0KCkRlYmlkbyBhIHF1ZSBlbCBwLXZhbG9yID4gMC4wNSwgTk8gc2UgcmVjaGF6YSBIMC4KUG9yIGxvIHRhbnRvLCBubyBoYXkgdW5hIGRpZmVyZW5jaWEgc2lzdGVtw6F0aWNhIGVudHJlIGxvcyBlcnJvcmVzLgoKU2luIGVtYmFyZ28sIHRvbWFuZG8gZW4gY3VlbnRhIHF1ZSBzZSB0b23DsyBBUk1BKDEsMSkgc29sbyBjb24gZWwgb2JqZXRpdm8gZGUgcmVhbGl6YXIgdW5hIGNvbXBhcmFjacOzbiBlbnRyZSBsbyBwcm9wdWVzdG8gcG9yIGF1dG8gYXJpbWEsIHkgcXVlIGNvbiBlbCBtb2RlbG8gcmVmaW5hZG8gc2Ugb2J0dXZvIHVuIEFSKDEpLCBzZSB0b21hcsOhIGNvbW8gbWVqb3IgbW9kZWxvIEFSKDEpLgoKIyMjIyA8YiBzdHlsZSA9ICdjb2xvciA6IHJlZDsnPiBQcm9uw7NzdGljbyA8L2I+ICAKYGBge3J9CnByb24uYXIxID0gZm9yZWNhc3QoYXV0by5zdWIsIGggPSAyMCkKcHJvbi5hcjEKCmFyMS5lbnRyZW5hbWllbnRvICU+JQogIGZvcmVjYXN0KGg9MjApICU+JQphdXRvcGxvdCh4bGFiID0gIiIsIHlsYWIgPSAiVGFzYSBkZSBzdWJvY3VwYWNpw7NuICglKSIpICsgYXV0b2xheWVyKHBydWViYSkKYGBgCgoKIyMgPGIgc3R5bGUgPSAnY29sb3IgOiBibGFjazsnPipDT05DTFVTScOTTio8L2I+CgoKRGUgYWN1ZXJkbyBjb24gZWwgbW9kZWxvIEFSKDEpLCBlbCBwcm9uw7NzdGljbyBwYXJhIGVsIHNpZ3VpZW50ZSB0cmltZXN0cmUgZGUgbGEgdGFzYSBkZSBzdWJvY3VwYWNpw7NuIGVuIE3DqXhpY28sIGVzIGRlIDguNjk1JSwgc2Ugb2JzZXJ2YSBxdWUgZXN0ZSBwb3JjZW50YWplIHZhIGRpc21pbnV5ZW5kbyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8sIGhhc3RhIHF1ZSB0cmFuc2N1cnJlbiBhcHJveGltYWRhbWVudGUgMTIgcGVyaW9kb3MgKHRyaW1lc3RyZXMpLCBxdWUgZXMgY3VhbmRvIHRpZW5kZSBhIGxhIG1lZGlhICg4LjYxNyUpLiAKCiMjIDxiIHN0eWxlID0gJ2NvbG9yIDogYmxhY2s7Jz4qUkVGRVJFTkNJQVMgQklCTElPR1LDgUZJQ0FTKjwvYj4KCiogTW9yYWxlcywgRi4gKHMuZi4pLiBTdWJlbXBsZW8uIGh0dHBzOi8vZWNvbm9taXBlZGlhLmNvbS9kZWZpbmljaW9uZXMvc3ViZW1wbGVvLmh0bWwgCiogSnVkaXNtYW4sIEMuIChzLmYuKS4gQ29uY2VwdG9zIHkgRGVmaW5pY2lvbmVzIGVuIFJlbGFjacOzbiBjb24gZWwgRW1wbGVvLCBEZXNlbXBsZW8geSBlbCBTdWJlbXBsZW8uIGh0dHBzOi8vZXN0dWRpb3NkZW1vZ3JhZmljb3N5dXJiYW5vcy5jb2xtZXgubXggIAoqIElORUdJLiAocy5mLikuIEJhbmNvIGRlIGluZm9ybWFjacOzbiBFY29uw7NtaWNhIChCSUUpLiBodHRwOi8vZW4ud3d3LmluZWdpLm9yZy5teC9hcHAvaW5kaWNhZG9yZXMvP3RtPTAmdD0xMDAwMDIxNSNEMTAwMDAyMTUjRDQ5MzkxMiNENDkzOTExIAoKIyMgPGIgc3R5bGUgPSAnY29sb3IgOiBibGFjazsnPipBTkVYT1MqPC9iPgoKQ8OTRElHTyBSU1RVRElPIFthcXXDrV0oaHR0cHM6Ly9ycHVicy5jb20vQW5nZWxhTXVqaWNhMjcvOTYwMjUxKQoK