Vamos a utilizar la paqueteria zoo y las librerias forecast, para hacer pronosticos (supongo) y tseries.
Procesos Autorregresivos \(AR(p)\)
\(\textbf{Definición 1.1}\) Un \(\textit{proceso autorregresivo}\) es un proceso en el que los datos futuros dependen linealmente de los datos historicos. El modelo se define como
\[Y_{t}=C+\sum_{i=1}^{p}\phi_{i}Y_{t-i}+\varepsilon_{t} \tag{1.1}\] De manera matricial podemos reescribirlo como \[Y_{t}= Y_{t-i}\cdot\Phi+\varepsilon_{t}\] donde \(c\) es constante y \(\Phi\) es un vector columna de \(p\) entradas, \(Y_{t-i}\) es un vector de \(p\) entradas donde \(i=1,...,p\), tal que cada entrada es la i-ésima observación antes de \(t\), \(\varepsilon_{t}\) es un término de error que se distribuyue como Ruido Blanco (RB de ahora en adelante) con media 0 y varianza \(\sigma_{\varepsilon}^{2}\). De manera extensiva:
\[Y_{t}=C+\begin{pmatrix}Y_{t-1} & Y_{t-2} & \cdots & Y_{t-p}\end{pmatrix} \begin{pmatrix} \phi_{1}\\ \phi_{2}\\ \vdots \\ \phi_{p}\end{pmatrix} + \varepsilon_{t} \tag{2.1}\] Note que el modelo AR es un modelo de regresión lineal de la serie \(Y_{t}\) y sus valores rezagados.
Para la definición no es necesario suponer que el ruido blanco tiene una distribución particular, pero más adelante supondremos que el ruido blanco tiene distribución normal. Una notación muy útil para considerar este tipo de modelos se basa en el uso del operador de retardo \(B\). El modelo \(AR(p)\) es
\[(1-\phi_{1} B - \phi_{2} B^{2}-\phi_{3}B^{3}-\cdots -\phi_{p}B^{p})Y_{t}=\varepsilon_{t} \tag{3.1}\] La ecuación (3.1) se puede resumir usando la siguiente notación: \[\phi(B)X_{t}=\varepsilon_{t}\] Donde \(\phi(B)\) es un polinomio de grado \(p\) llamado operador autorregresivo, definido por
\[\phi(B)=(1-\phi_{1} B - \phi_{2} B^{2}-\phi_{3}B^{3}-\cdots -\phi_{p}B^{p})\]
Proceso Autoregresivo de Orden 1 \(AR(1)\)
En este proceso la variable \(Y_{t}\) depende del valor rezagado \(Y_{t-1}\) \[Y_{t}=\phi Y_{t-1}+\varepsilon_{t} \tag{4.1}\] \(\textbf{Definición 2.1}\) Se dice que un proceso estocástico \(Y_{t}\) es \(\textit{estríctamente estacionario}\) si todas las distribuciones conjuntas de las observaciones en diferentes puntos temporales son las mismas.
\(\textbf{Definición 3.1}\) Se dice que un proceso estocástico \(Y_{t}\) es \(\textit{débilmente estacionario}\) si su media \(\mathbb{E}(Y_{t})\) y su varianza \(\mathbb{V}(Y_{t})\) son constantes a través del tiempo y la autocovarianza \(\mathbb{C}(Y_{t},Y_{t+h})\) entre cualesquiera dos observaciones no depende de \(t\).
\(\textbf{Teorema 1}\) Si un proceso estocastico \(Y_{t}\) es estríctamente estacionario, entonces es débilmente estacionario.
Si iteramos la ecuación (4.1) hacia atrás, tenemos que,
\[\begin{align}
Y_{t}&=\left(\phi(\phi Y_{t-2}+\varepsilon_{t-1})\right)+\varepsilon_{t}\\ \\
&= \phi^{2}Y_{t-2}+\phi\varepsilon_{t-1}+\varepsilon_{t}\\ \\
\Leftrightarrow Y_{t}&=\phi^{k}Y_{t-k}+\sum_{i=0}^{k-1}\phi^{i}\varepsilon_{t-i}
\end{align}\]
Si continuamos este proceso de iteración al pasado (siempre que \(|\phi|<1)\) y \(Y_{t}\) sea estacionario, podemos representar el modelo \(AR(1)\) como un proceso lineal:
\[Y_{t}=\lim_{k\rightarrow\infty}\phi^{k}Y_{t-k}+\sum_{i=0}^{k-1}\phi^{i}\varepsilon_{t-i}\] Aplicando el límite y usando el hecho de que \(|\phi|<1\), tenemos que, \[Y_{t}=\sum_{i=0}^{\infty}\phi^{i}\varepsilon_{t-i}\tag{5.1}\sim MA(\infty)\] Por lo tanto, la ecuación (5.1) define un proceso \(AR(1)\) estacionario con media, \[\begin{align}
\mathbb{E}(Y_{t})&=\mathbb{E}\left(\sum_{i=0}^{\infty}\phi^{i}\varepsilon_{t-i}\right)\\ \\
&=\sum_{i=0}^{\infty}\phi^{i}\mathbb{E}(\varepsilon_{t-i})=0
\end{align}\]
varianza,
\[\begin{align}
\mathbb{V}(Y_{t})&=\mathbb{V}\left(\sum_{i=0}^{\infty}\phi^{i}\varepsilon_{t-i}\right)\\ \\
&=\sum_{i=0}^{\infty}\phi^{2i}\mathbb{V}(\varepsilon_{t-i})=\sigma_{\varepsilon}^{2}\sum_{i=0}^{\infty}\phi^{2i}
\end{align}\]
y autocovarianza,
\[\begin{align}
\mathbb{C}(Y_{t},Y_{t+h})&=\mathbb{E}\left(\sum_{i=0}^{\infty}\phi^{i}\varepsilon_{t-i}\cdot \sum_{i=0}^{\infty}\phi^{i}\varepsilon_{t+h-i}\right) - \mathbb{E}\left(\sum_{i=0}^{\infty}\phi^{i}\varepsilon_{t-i}\right)\cdot\mathbb{E}\left(\sum_{i=0}^{\infty}\phi^{i}\varepsilon_{t+h-i}\right)\\ \\
&=\mathbb{E}\left((\varepsilon_{t}+\phi\varepsilon_{t-1}+\phi^{2}\varepsilon_{t-2}+\cdots)\cdot(\varepsilon_{t+h}+\phi\varepsilon_{t+h-1}+\phi^{2}\varepsilon_{t+h-2}+\cdots+\phi^{h}\varepsilon_{t}+\phi^{h+1}\varepsilon_{t-1}+\cdots)\right)
\end{align}\]
dado que \(\varepsilon_{t}\sim RB(0,\sigma_{\varepsilon}^{2})\), tenemos que los momentos cruzados \(\mathbb{E}(\varepsilon_{t}\varepsilon_{s})=0\) sii \(t\not=s\), luego
\[\begin{align}
\mathbb{C}(Y_{t},Y_{t+h})&=\mathbb{E}\left((\varepsilon_{t}+\phi\varepsilon_{t-1}+\phi^{2}\varepsilon_{t-2}+\cdots)\cdot(\varepsilon_{t+h}+\phi\varepsilon_{t+h-1}+\phi^{2}\varepsilon_{t+h-2}+\cdots+\phi^{h}\varepsilon_{t}+\phi^{h+1}\varepsilon_{t-1}+\cdots)\right)\\ \\
&=\sigma_{\varepsilon}^{2}\phi^{h}\sum_{i=0}^{\infty}\phi{2i}=\frac{\sigma_{\varepsilon}^{2}\phi^{h}}{1-\phi^{2}},\quad h>0
\end{align}\]
Simulación \(AR(1)\)
set.seed(1) #Vamos a fijar la semilla en 1 para generar un mismo vector de números aleatorios
X <- matrix(rep(0,50),ncol=1) #Generamos este vector con 0 para guardar los datos de una serie
inicio <- 5 #Valor de la primera observación de la serie
phi <- 0.8 #Parámetro phi de la ecuación (5.1)
epsilon <- rnorm(49,0,1.5) #Vamos a modelar el error de la regresión con una distribución normal con media 0 y varianza 1.5
X[1]<- inicio #Inicializamos la serie con el valor inicio.
for (i in 2:nrow(X)){
X[i]=X[i-1]*phi+epsilon[i-1]
} #Generamos el resto de las observaciones
X <- ts(X,frequency = 1,
start = 1971) #Formato de serie temporal con observaciones por año
library(ggplot2)
X_df <- data.frame(fecha = time(X),
valor = as.vector(X)) #ggplot2 utiliza data frames, por lo tanto modificaré la serie original.
ggplot(X_df, aes(x = fecha, y = valor)) +
geom_line() +
labs(title = "Mi Serie de Tiempo",
x = "Fecha", y = "Valor") #Grafica la serie
Don't know how to automatically pick scale for object of type <ts>. Defaulting to continuous.

Pronostico \(AR(1)\)
Sea la serie de tiempo \(Y_{t}\) dada por \[Y_{t}=\phi_{0}+\phi_{1}Y_{t-1}+\varepsilon_{t}\] \[\varepsilon_{t}\sim N(0,\sigma^{2})\] por lo tanto \(Y_{t}\sim N(\phi_{0}+\phi_{1}Y_{t-1},\sigma^{2})\) ya que la serie se conoce hasta \(t-1\), y \(Y_{t-1}\in\mathbb{R}\). Para realizar un pronostico en \(t+1\) se puede escribir como \[Y_{t+1}=\phi_{0}+\phi_{1}Y_{t}+\varepsilon_{t+1}\] \[\varepsilon_{t+1}\sim N(0,\sigma^{2})\] Entonces,
\[\begin{align}
Y_{t+1}&=\phi_{0}+\phi_{1}(\phi_{0}+\phi_{1}Y_{t-1}+\varepsilon_{t})+\varepsilon_{t+1}\\ \\
&=\phi_{0}+\phi_{0}\phi_{1}+\phi_{1}^{2}Y_{t-1}+\phi_{1}\varepsilon_{t}+\varepsilon_{t+1}
\end{align}\]
Por lo tanto, \[Y_{t+1}\sim N(\phi_{0}+\phi_{0}\phi_{1}+\phi_{1}^{2}Y_{t-1},\sigma^{2}(1+\phi^{2}))\]
epsilon.for<-rnorm(1,0,1.5)
X.for<-X[length(X)]*phi+epsilon.for
X.for
[1] 1.921274
Serie Filtrada \(AR\)
El filtrado de la serie se expresa como \[Y_{t}-Y_{t-1}=\varepsilon_{t}\] Donde la serie filtrada resulta ser el error del proceso.
Xf <- c(rep(0,length(X)-1)) #Vector donde se almacenan serie filtrada
for (i in 2:length(Xf)){
Xf[i]=X[i]-X[i-1]*phi
}
Xf <- ts(Xf, frequency = 1, start = 1071)
Xf_df <- data.frame(fecha = time(Xf),
valor = as.vector(Xf))
ggplot(Xf_df,aes(x = fecha, y = valor))+
geom_line()+
labs(title = "Gráfico de la Serie Filtrada",
x = "Fecha", y = "Valor")
Don't know how to automatically pick scale for object of type <ts>. Defaulting to continuous.

Estimación de procesos \(AR\)
ar.ols estima un modelo autorregresivo por el metodo de minimos cuadrados ordinarios (ols por sus siglas en ingles)
ar <- ar.ols(
X, #Datos a modelar
aic = TRUE, #Criterio AIC
order.max =1, #Proceso maximo AR(1)
intercept = FALSE, #Intercepto falso
demean = FALSE #Omite un valor medio que automaticamente calcula ar.ols
)
ar
Call:
ar.ols(x = X, aic = TRUE, order.max = 1, demean = FALSE, intercept = FALSE)
Coefficients:
1
0.7289
Order selected 1 sigma^2 estimated as 1.521
La estimación del parámetro \(\phi\) del modelo \(AR(1)\) por medio de la función ar.ols fue de \(\hat{\phi}=0.7289\) y el parámetro con el que se genero la serie era de \(\phi=0.8\).
Para calcular los valores ajustados del modelo autorregresivo que se obtuvo anteriormente, se puede realizar de manera manual o por medio de la función fitted como se presenta a continuación:
X.fit <- fitted(ar)
Grafica de los valores reales contra los estimados:
X.fit_df <- data.frame(fecha = time(X),
valor = as.vector(X.fit))
ggplot() +
geom_line(data = X.fit_df, aes(x = fecha, y = valor, color = "Serie Estimada")) +
geom_line(data = X_df, aes(x = fecha, y = valor, color = "Serie Real")) +
labs(title = "Serie Real vs. Serie Estimada",
x = "Fecha",
y = "Valor") +
scale_color_manual(values = c("Serie Estimada" = "blue", "Serie Real" = "red"))
Don't know how to automatically pick scale for object of type <ts>. Defaulting to continuous.
Warning: Removed 1 row containing missing values (`geom_line()`).

Cálculo de los residuales:
residuals <- ar$resid #es la diferencia entre los valores observados y los estimados
residuals
Time Series:
Start = 1971
End = 2020
Frequency = 1
[1] NA -0.584159650 0.493066581 -1.059774922 2.458730528 0.717055897 -1.017323098
[8] 0.814339023 1.226030802 1.037254019 -0.257806268 2.395321202 0.848125430 -0.679593166
[15] -3.186494901 1.559628582 -0.049633658 -0.014864444 1.421564283 1.337145863 1.062691668
[22] 1.579281136 1.431871258 0.402200700 -2.743792137 0.909750017 -0.034075660 -0.199585786
[29] -2.195459172 -0.865554596 0.457251004 1.946866367 -0.082192198 0.628135971 -0.002057091
[36] -2.008407607 -0.723618567 -0.716598101 -0.231154147 1.529964668 1.166029569 -0.148375121
[43] -0.318861783 1.067367029 0.926867919 -0.900263397 -1.028406767 0.497682888 1.152332313
[50] -0.086924084
Gráfico de los residuos
residuals_df <- data.frame(residuals,
fecha = time(X),
valor = as.vector(residuals))
ggplot(residuals_df, aes(x = fecha, y = valor))+
geom_line()+
labs(title = "Gráfico de los Residuos",
x = "Fecha", y = "Valor")
Don't know how to automatically pick scale for object of type <ts>. Defaulting to continuous.
Warning: Removed 1 row containing missing values (`geom_line()`).
install.packages("zoo")
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.2/zoo_1.8-12.tgz'
Content type 'application/x-gzip' length 1028360 bytes (1004 KB)
==================================================
downloaded 1004 KB
The downloaded binary packages are in
/var/folders/50/m2w_4_3n0k171fw0tkb7w05c0000gn/T//RtmpOGMIps/downloaded_packages

Diagnostico de los residuos:
La distribución normal de los residuos es una suposición fundamental detrás de muchos métodos de estimación de parámetros, como la estimación de máxima verosimilitud (MLE) y los mínimos cuadrados ordinarios (OLS). Cuando los residuos se distribuyen normalmente, las estimaciones de los parámetros del modelo son eficientes y no sesgadas.
La normalidad de los residuos es importante para hacer pronósticos y predicciones precisas. Los intervalos de predicción y las predicciones puntuales se basan en la suposición de que los residuos son normalmente distribuidos.
Para hacer el análisis de normalidad de los residuos, es necesario calcular su densidad primero:
# Distribución de los residuos
residuals <- na.omit(residuals)
densidad_res <-density(residuals)
densidad_res_df <- data.frame(x = densidad_res$x,
y = densidad_res$y)
# Distribución de la normal con 1000 puntos
normal <- seq(min(residuals)-2, max(residuals)+2, length.out = 1000)
media <- mean(residuals)
desviacion <- sd(residuals)
densidad_normal <- dnorm(normal, mean = media, sd = desviacion)
normal_df <- data.frame(x = normal, densidad = densidad_normal)
#Gráfico
ggplot(densidad_res_df, aes(x = x, y = y)) +
geom_line(color = "blue", linetype = "solid", size = 1) +
geom_line(data = normal_df, aes(x = x, y = densidad), color = "red", linetype = "dashed", size = 1) +
labs(title = "Densidad Observaciones vs. Densidad Normal",
x = "Valor",
y = "Densidad") +
scale_color_manual(values = c("blue", "red"))
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
This warning is displayed once every 8 hours.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.

Prueba ACF y Correlograma de los residuos:
La ACF es una función estadística que se utiliza para medir y visualizar la autocorrelación entre una serie temporal y sus propios rezagos. En otras palabras, la ACF muestra cómo se relaciona cada observación con las observaciones anteriores en diferentes períodos de tiempo. La ACF se calcula mediante la correlación entre la serie temporal original y versiones desplazadas de sí misma a lo largo del tiempo. La ACF es una herramienta importante para identificar patrones de autocorrelación en una serie temporal, como ciclos, estacionalidad y tendencias.
par(mar = c(5, 5, 4, 2))
residuals_acf <- acf(residuals, lag.max = 20,
main = "Correlograma de los Residuos", cex.main = 1.2)

La falta de autocorrelación después del primer período sugiere que las observaciones de la serie temporal son esencialmente independientes entre sí. Esto significa que no hay una relación sistemática y significativa entre las observaciones en momentos sucesivos, lo que es una suposición importante en muchas técnicas estadísticas y de modelado.
Además, la ausencia de autocorrelación significativa en los rezagos posteriores puede indicar que el comportamiento de la serie es estable y no muestra patrones de estacionalidad, tendencia o ciclos que se repiten a lo largo del tiempo.
Prueba PACF
La PACF se utiliza comúnmente para determinar el orden adecuado de un modelo AR. Cuando se observa un decaimiento significativo en la PACF después de un rezago específico, indica que ese rezago es el orden adecuado del modelo AR. Por ejemplo, si la PACF muestra un decaimiento significativo después del rezago 2, sugiere un modelo AR(2).
La PACF puede ayudar a diferenciar entre modelos AR y modelos MA (que veremos en el siguiente apartado). Si la PACF muestra una caída abrupta después de un rezago específico y luego permanece cerca de cero, sugiere un modelo AR, mientras que una PACF que decae lentamente sugiere un modelo MA.
par(mar = c(5, 5, 4, 2))
residuals_pacf <- pacf(residuals, lag.max = 20,
main = "PACF de los Residuos", cex.main = 1.2)

En el contexto de modelado de series temporales, si la PACF de los residuos está dentro del intervalo de confianza en todos los rezagos, indica que el modelo elegido es adecuado para describir la estructura de dependencia en los datos. Los residuos parecen no contener información adicional que no se haya capturado en el modelo.
Procesos de Medias Moviles \(MA(q)\)
\(\textbf{Definición 2.1}\) Se dice que una serie temporal \(Y_{t}\) admite una representación de medias móviles (MA) de orden \(q\) , y se denota por \(MA(q)\) , si es susceptible de ser modelizada a través de la ecuación: \[\begin{align}
Y_{t}&=\theta_{1}\varepsilon_{t-1}+\theta_{2}\varepsilon_{t-2}+\cdots+\theta_{q}\varepsilon_{t-q}+\varepsilon_{t}\\ \\
&=\sum_{i=1}^{q}\theta_{i}\varepsilon_{t-i}+\varepsilon_{t}, \tag{1.2}
\end{align}\]
Donde \(Y_{t}\) es una variable aleatoria concebida como realizaciones de un proceso estocástico en los momentos del tiempo \(t\) , que se caracterizan por \(\mathbb{E}(Y_{t})=\mathbb{E}(Y_{t−1})=\mathbb{E}(Y_{t−2})=\cdots\), \(\theta_{1},...,\theta_{q}\) son parámetros del modelo que, junto con la varianza deben ser estimados, y \(\varepsilon_{t}\sim RB(0,\sigma_{\varepsilon}^{2})\).
\(\textbf{Definición 2.1}\) Se dice que un proceso MA(1) es \(\textit{estacionario en media}\) si \[\mathbb{E}(Y_{t})=\mathbb{E}(\varepsilon_{t}+\theta\varepsilon_{t-1})=0\] \(\textbf{Definición 2.3}\) Se dice que un proceso MA(1) es \(\textit{estacionario en covarianza}\) si
\[\begin{align}
\gamma_0&=\mathbb{E}(Y_{t}-\mathbb{E}(Y_{t}))^{2}=\mathbb{E}(Y_{t})^{2}=\mathbb{E}(\varepsilon_{t}+\theta\varepsilon_{t-1})^{2}\\\\
&=\mathbb{E}(\varepsilon_{t}^{2}+2\theta^{2}\varepsilon_{t}\varepsilon_{t-1}+\theta^{2}\varepsilon_{t-1}^{2})\\\\
&=\mathbb{E}(\varepsilon_{t}^{2})+2\theta^{2}\mathbb{E}(\varepsilon_{t}\varepsilon_{t-1})+\mathbb{E}(\varepsilon_{t-1}^{2})\\ \\
&=\sigma_{\varepsilon}^{2}+\sigma_{\varepsilon}^{2}\theta^{2}=\sigma_{\varepsilon}^{2}(1+\theta^{2})<\infty
\end{align}\]
Simulación \(MA(1)\)
set.seed(1)
Y <- matrix(rep(0,50), ncol=1)
epsilon <- rnorm(50,0,1.5)
theta <-0.9
cte <- 0
Y[1] <- epsilon[1]
for (i in 2:nrow(Y)){
Y[i] <- cte + theta*epsilon[i-1] + epsilon[i]
}
Y <- ts(Y, frequency = 1, start = 1970)
Y_df <- data.frame(fecha = time(Y),
valor = as.vector(Y))
ggplot(Y_df,aes(x=fecha, y=valor))+
geom_line()+
geom_point()+
labs(title = "Gráfico de MA", xlab("Fecha"), ylab("Valor"))
Don't know how to automatically pick scale for object of type <ts>. Defaulting to continuous.

Pronóstico con Proceso \(MA\)
Para hacer la estimación de la serie vamos a suponer que, \[\hat{Y_{t}}=\phi_{0}+\phi_{1}e_{t-1}+e_{t}\] \[e_{t}\sim\sigma_{\varepsilon}\varepsilon_{t}\]
\[\varepsilon\sim N(0,1)\] donde \(Y_{t}\) es el último valor conocido de la serie y \(e_{t}\) es el último valor del ruido conocido.
Suponga que \(\phi_{0}=0\) \(Y_{0}=e_{t}\), \(\hat{Y_{1}}=\phi_{1}e_{0}+e_{1}\), \(\hat{Y_{2}}=\phi_{1}e_{1}+e_{2}\), por lo tanto \[\hat{Y}_{t+1}=\phi_{1}e_{t}+e_{t+1}\] ### Serie Filtrada \(MA(1)\)
Yf <- matrix(rep(0,50),ncol=1)
for (i in 2:nrow(Yf)){
Yf[i-1] <- Y[i]+epsilon[i-1]
}
Yf <- ts(Yf, frequency = 1, start = 1970)
Yf_df <- data.frame(fecha = time(Yf),
valor = as.vector(Yf))
ggplot(Yf_df, aes(x = fecha, y = valor))+
geom_line()+
geom_point()+
labs(title = "Gráfico Serie Filtrada MA", xlab("Fehca"),
ylab("Valor"))
Don't know how to automatically pick scale for object of type <ts>. Defaulting to continuous.

Estimación de Proceso \(MA\)
ma <- arima(Y,
order = c(0,0,2), #(p=0,i=0,q=1) es un proceso MA(1)
include.mean = F)
ma
Call:
arima(x = Y, order = c(0, 0, 2), include.mean = F)
Coefficients:
ma1 ma2
0.9939 0.1437
s.e. 0.1901 0.1993
sigma^2 estimated as 1.529: log likelihood = -82.29, aic = 170.58
En la presentación de los resultados de la estimación del modelo, el termino s.e significa error estandar y se refiere a una estimación de la desviación estandar. \[SE_{\hat{Y}}=\frac{s}{\sqrt{n}}\] Donde \(s\) es la desviación estandar y \(n\) el número de observaciones.
Y.fit <- fitted(ma)
Y.fit_df <- data.frame(fecha = time(X),
valor = as.vector(Y.fit))
ggplot() +
geom_line(data = Y.fit_df, aes(x = fecha, y = valor, color = "Serie Estimada")) +
geom_line(data = Y_df, aes(x = fecha, y = valor, color = "Serie Real")) +
labs(title = "Serie Real vs. Serie Estimada",
x = "Fecha",
y = "Valor") +
scale_color_manual(values = c("Serie Estimada" = "blue", "Serie Real" = "red"))
Don't know how to automatically pick scale for object of type <ts>. Defaulting to continuous.

Calculo de los residuales del modelo MA:
El modelo ajustado por medio de la función arima y asignado a la variable “ma” tienen varios parametros internos. Para poder ver cual es la estructura interna y su composición utilice str( ). Los residuales del modelo ya estan calculados internamente y se calculan:
residuals <- ma$residuals
residuals_df <- data.frame(fecha = time(residuals),
valor = as.vector(residuals))
ggplot(residuals_df, aes(x = fecha, y = valor))+
geom_line()+
geom_point()+
labs(title = "Gráfico de los residuos del proceso MA",
xlab("Fecha"), ylab("Valor"))
Don't know how to automatically pick scale for object of type <ts>. Defaulting to continuous.

Diagnostico de los residuales MA:
# Distribución de los residuos
residuals <- na.omit(residuals)
densidad_res <-density(residuals)
densidad_res_df <- data.frame(x = densidad_res$x,
y = densidad_res$y)
# Distribución de la normal con 1000 puntos
normal <- seq(min(residuals)-2, max(residuals)+2, length.out = 1000)
media <- mean(residuals)
desviacion <- sd(residuals)
densidad_normal <- dnorm(normal, mean = media, sd = desviacion)
normal_df <- data.frame(x = normal, densidad = densidad_normal)
#Gráfico
ggplot(densidad_res_df, aes(x = x, y = y)) +
geom_line(color = "blue", linetype = "solid", size = 1) +
geom_line(data = normal_df, aes(x = x, y = densidad), color = "red", linetype = "dashed", size = 1) +
labs(title = "Densidad Observaciones vs. Densidad Normal",
x = "Valor",
y = "Densidad") +
scale_color_manual(values = c("blue", "red"))

Prueba ACF y Correlograma de los residuos:
par(mar = c(5, 5, 4, 2))
acf(residuals,
na.action = na.pass,
ylim=c(-1,1),
main = "Corelograma de los Residuos")

Prueba PACF:
par(mar = c(5, 5, 4, 2))
pacf1 <- pacf(residuals,
na.action = na.pass,
ylim=c(-1,1),
main = "PACF de los residuos")

Procesos autorregresivos de media movil \(ARMA\)
Los modelos \(ARMA(p,q)\) son modelos autorregresivos de media movil se componen de una parte AR y la otra MA, siguen la siguiente ecuación:
\[\begin{align}
Y_{t}&=\phi_{0}+\phi_{1}Y_{t-1}+\cdots+\phi_{p}Y_{t-p}+\varepsilon_{t}+\theta_{1}\varepsilon_{t-1}+\cdots+\theta_{q}\varepsilon_{t-q} \\ \\
&=\phi_{0}+\sum_{i=1}^{p}\phi_{i}Y_{t-i}+\sum_{j=1}^{q}\theta_{j}\varepsilon_{t-j} + \varepsilon_{t}\tag{3.1}
\end{align}\]
Simulación del proceso \(ARMA\)
set.seed(1)
Z <- arima.sim(n = 50, #número de observaciones simuladas
list(ar = c(0.82,-0.4), #parámetro phi del modelo AR
ma = c(-0.2,0.24)), #parámetro theta del modelo MA
innov=rnorm(50,0,1)) #error asosciado distribuido normalmente
Z_df<-data.frame(time = c(1970:2019),
value = as.vector(Z))
ggplot(Z_df,aes(x = time,
y = value))+
geom_line()+
geom_point()+
labs(title = "Simulación modelo ARMA")

#Vamos a ajustar con un modelo ARMA(2,2)
par(mar = c(5, 5, 4, 2))
acf(Z,
na.action = na.pass,
ylim=c(-1,1))

Z.fit <- arima(Z, order = c(2,0,2),
include.mean = FALSE)
Z.fit
Call:
arima(x = Z, order = c(2, 0, 2), include.mean = FALSE)
Coefficients:
ar1 ar2 ma1 ma2
0.2856 -0.3943 0.3329 0.5886
s.e. 0.3307 0.2218 0.2949 0.2263
sigma^2 estimated as 0.7966: log likelihood = -65.68, aic = 141.35
Z.fit_df <- data.frame(time = c(1970:2019),
value = as.vector(fitted(Z.fit)))
ggplot() +
geom_line(data = Z.fit_df, aes(x = time, y = value, color = "Serie Estimada")) +
geom_line(data = Z_df, aes(x = time, y = value, color = "Serie Real")) +
labs(title = "Serie Real vs. Serie Estimada",
x = "Fecha",
y = "Valor") +
scale_color_manual(values = c("Serie Estimada" = "blue", "Serie Real" = "red"))

Z.for <- predict(Z.fit,n.ahead=2)
Z.for
$pred
Time Series:
Start = 51
End = 52
Frequency = 1
[1] 0.3030716 0.7171653
$se
Time Series:
Start = 51
End = 52
Frequency = 1
[1] 0.8925266 1.0494733
#Actualización de la serie:
pronostico <- data.frame(c(2020,2021),as.vector(Z.for$pred))
colnames(pronostico)<-colnames(Z.fit_df)
Z.fit_df<-rbind(Z_df,pronostico)
ggplot() +
geom_line(data = Z.fit_df, aes(x = time, y = value, color = "Pronostico")) +
geom_line(data = Z_df, aes(x = time, y = value, color = "Serie Real")) +
labs(title = "Serie Real y Pronóstico",
x = "Fecha",
y = "Valor") +
scale_color_manual(values = c("Pronostico" = "blue", "Serie Real" = "red"))

Diferenciación de la serie de tiempo
Para utilizar esta metodología para el modelamiento y posterior pronóstico de series de tiempo se debe verificar la estacionaridad de la serie. Esta se puede diagnosticar mediante el test de Dickey-Fuller, si la serie resulta no estacionaria se debe diferenciar la serie hasta alcanzar la estacionariedad.
Sea \(Y_{t}\) una serie de tiempo, su diferenciación simple esta dada por: \[\Delta Y_{t}=Y_{t}-Y_{t-1}\]
# Prueba Dickey-Fuller de la serie orignial
adf.test(Y)
Warning in adf.test(Y) : p-value smaller than printed p-value
Augmented Dickey-Fuller Test
data: Y
Dickey-Fuller = -4.3142, Lag order = 3, p-value = 0.01
alternative hypothesis: stationary
## Ejemplo de diferenciación simple
Y.d <- diff(Y) # Serie X con presencia de raiz Unit.
adf.test(Y.d)
Warning in adf.test(Y.d) : p-value smaller than printed p-value
Augmented Dickey-Fuller Test
data: Y.d
Dickey-Fuller = -4.638, Lag order = 3, p-value = 0.01
alternative hypothesis: stationary
La serie era estacionaria desde el pricipio por eso el valor \(p\) en ambas pruebas no cambia.
Proceso autorregresivo integrado de media móvil \(ARIMA\)
El modelo autorregresivo integrado de media movil utiliza diferenciación de la serie y regresiones para modelar la serie de tiempo, se considera que es un modelo dinamico ya que los datos de predicciones dependen de comportamientos pasados y no de variables externas a la serie.
El proceso \(ARIMA(p,d,q)\) donde \(p,d,q\) son números enteros no negativos, se puede representar matematicamente como:
\[Y_{t}=-(\Delta^{d}Y_{t}-Y_{t})+\phi_{0}+\sum_{i=1}^{p}\phi_{i}\Delta^{d}Y_{t-i}+\sum_{j=1}^{q}\theta_{j}\varepsilon_{t-j}+\varepsilon_{t}\] Donde:
- \(\phi_{0}\) es una constante
- \(d\) corresponde a las diferencias necesarias para generar que la serie sea estacionaria
- \(\phi_{1},...,\phi_{p}\) son los parametros asociados a la parte autorregresiva del modelo
- \(\theta_{1},...,\theta_{q}\) son los parametros asociados a la parte de medias moviles del modelos
- \(\varepsilon_{t}\) es el termino de error.
Simulación proceso \(ARIMA\)
set.seed(1)
W <- arima.sim(n = 50, #50 observaciones
list(order = c(1,1,1), #ARIMA(1,1,1) AR(1), Dif(1), MA(1)
ar = 0.812, #Phi-AR
ma = 0.214)) #Theta-MA
head(W)
Time Series:
Start = 1
End = 6
Frequency = 1
[1] 0.00000000 0.57741519 1.41195136 2.11875141 1.30409922 -0.06708366
W_df <- data.frame(time = c(1970:2020),
value = as.vector(W))
ggplot(W_df, aes(x = time, y = value))+
geom_line()+
geom_point()+
labs(title = "Simulación proceso ARIMA(1,1,1)",
xlab("Año"), ylab("Valor"))

Estimacion modelo ARIMA
W.fit <- arima(W, # Datos de la serie
order = c(1,1,1), # Proceso tipo ARIMA(1,1,1) ar(1), diff(1),ma(1)
include.mean = T)
W.fit
Call:
arima(x = W, order = c(1, 1, 1), include.mean = T)
Coefficients:
ar1 ma1
0.7269 0.2338
s.e. 0.1125 0.1565
sigma^2 estimated as 0.7649: log likelihood = -64.81, aic = 135.61
W.fit_df <- data.frame(time = W_df$time,
value = as.vector(fitted(W.fit)))
ggplot() +
geom_line(data = W.fit_df, aes(x = time, y = value, color = "Serie Estimada")) +
geom_line(data = W_df, aes(x = time, y = value, color = "Serie Real")) +
labs(title = "Serie Real vs. Serie Estimada",
x = "Fecha",
y = "Valor") +
scale_color_manual(values = c("Serie Estimada" = "blue", "Serie Real" = "red"))

Predicción del modelo \(Arima(1,1,1)\)
W.for<-predict(W.fit,n.ahead=3)
W.for
$pred
Time Series:
Start = 52
End = 54
Frequency = 1
[1] 35.99566 35.08404 34.42138
$se
Time Series:
Start = 52
End = 54
Frequency = 1
[1] 0.8745835 1.9249212 3.0188201
pronostico <- data.frame(c(2021:2023),
as.vector(W.for$pred))
colnames(pronostico) <- colnames(W.fit_df)
W.fit_df <- rbind(W.fit_df,pronostico)
ggplot() +
geom_line(data = W.fit_df, aes(x = time, y = value, color = "Pronostico")) +
geom_line(data = W_df, aes(x = time, y = value, color = "Serie Real")) +
labs(title = "Serie Real y Pronóstico",
x = "Fecha",
y = "Valor") +
scale_color_manual(values = c("Pronostico" = "blue", "Serie Real" = "red"))

Cuidate bb
LS0tCnRpdGxlOiAiU2VyaWVzIGRlIFRpZW1wbyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCgoKPHAgc3R5bGU9InRleHQtYWxpZ246Y2VudGVyOyI+CipRdWllcm8gcXVlIHF1ZWRlIGNsYXJvIHF1ZSBubyB0ZW5nbyBpZGVhIGRlIGxvIHF1ZSBlc3RveSBhcHVudG8gZGUgZXNjcmliaXIsIMO6bmljYW1lbnRlIGVzIHVuYSBjb21waWxhY2nDs24gZGUgZG9jdW1lbnRvcyBxdWUgaGUgZW5jb250cmFkbyBzb2JyZSBtb2RlbGFkbyBkZSBzZXJpZXMgZGUgdGllbXBvLiBQb3IgbG8gdGFudG8sIGRlc2N1YnJpcmVtb3MganVudG9zIHkgYWwgbWlzbW8gdGllbXBvIChlc28gbm8gZXMgdmVyZGFkKSBxdWUgaGFjZSBjYWRhIHVuYSBkZSBsYXMgc2lndWllbnRlcyBsaW5lYXMuIFBvciBmYXZvciBubyBqdXpndWVzLCB0dXZlIGxhIGRlY2VuY2lhIGRlIGFkdmVydGlydGUuKgo8L3A+Cgo8cCBzdHlsZT0idGV4dC1hbGlnbjpjZW50ZXI7Ij4KLUMKPC9wPgoKPGJyPjxicj48YnI+PGJyPjxicj48YnI+CgpWYW1vcyBhIHV0aWxpemFyIGxhIHBhcXVldGVyaWEgem9vIHkgbGFzIGxpYnJlcmlhcyBmb3JlY2FzdCwgcGFyYSBoYWNlciBwcm9ub3N0aWNvcyAoc3Vwb25nbykgeSB0c2VyaWVzLgoKCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKCJ6b28iKQpsaWJyYXJ5KGZvcmVjYXN0KQpsaWJyYXJ5KHRzZXJpZXMpCmBgYAoKIyBQcm9jZXNvcyBBdXRvcnJlZ3Jlc2l2b3MgJEFSKHApJAoKJFx0ZXh0YmZ7RGVmaW5pY2nDs24gMS4xfSQgVW4gJFx0ZXh0aXR7cHJvY2VzbyBhdXRvcnJlZ3Jlc2l2b30kIGVzIHVuIHByb2Nlc28gZW4gZWwgcXVlIGxvcyBkYXRvcyBmdXR1cm9zIGRlcGVuZGVuIGxpbmVhbG1lbnRlIGRlIGxvcyBkYXRvcyBoaXN0b3JpY29zLiBFbCBtb2RlbG8gc2UgZGVmaW5lIGNvbW8KCiQkWV97dH09Qytcc3VtX3tpPTF9XntwfVxwaGlfe2l9WV97dC1pfStcdmFyZXBzaWxvbl97dH0gXHRhZ3sxLjF9JCQKRGUgbWFuZXJhIG1hdHJpY2lhbCBwb2RlbW9zIHJlZXNjcmliaXJsbyBjb21vCiQkWV97dH09IFlfe3QtaX1cY2RvdFxQaGkrXHZhcmVwc2lsb25fe3R9JCQKZG9uZGUgJGMkIGVzIGNvbnN0YW50ZSB5ICRcUGhpJCBlcyB1biB2ZWN0b3IgY29sdW1uYSBkZSAkcCQgZW50cmFkYXMsICAkWV97dC1pfSQgZXMgdW4gdmVjdG9yIGRlICRwJCBlbnRyYWRhcyBkb25kZSAkaT0xLC4uLixwJCwgdGFsIHF1ZSBjYWRhIGVudHJhZGEgZXMgbGEgaS3DqXNpbWEgb2JzZXJ2YWNpw7NuIGFudGVzIGRlICR0JCwgJFx2YXJlcHNpbG9uX3t0fSQgZXMgdW4gdMOpcm1pbm8gZGUgZXJyb3IgcXVlIHNlIGRpc3RyaWJ1eXVlIGNvbW8gUnVpZG8gQmxhbmNvIChSQiBkZSBhaG9yYSBlbiBhZGVsYW50ZSkgY29uIG1lZGlhIDAgeSB2YXJpYW56YSAkXHNpZ21hX3tcdmFyZXBzaWxvbn1eezJ9JC4gRGUgbWFuZXJhIGV4dGVuc2l2YToKCiQkWV97dH09QytcYmVnaW57cG1hdHJpeH1ZX3t0LTF9ICYgWV97dC0yfSAmIFxjZG90cyAmIFlfe3QtcH1cZW5ke3BtYXRyaXh9IFxiZWdpbntwbWF0cml4fSBccGhpX3sxfVxcIFxwaGlfezJ9XFwgXHZkb3RzIFxcIFxwaGlfe3B9XGVuZHtwbWF0cml4fSArIFx2YXJlcHNpbG9uX3t0fSBcdGFnezIuMX0kJApOb3RlIHF1ZSBlbCBtb2RlbG8gQVIgZXMgdW4gbW9kZWxvIGRlIHJlZ3Jlc2nDs24gbGluZWFsIGRlIGxhIHNlcmllICRZX3t0fSQgeSBzdXMgdmFsb3JlcyByZXphZ2Fkb3MuCgpQYXJhIGxhIGRlZmluaWNpw7NuIG5vIGVzIG5lY2VzYXJpbyBzdXBvbmVyIHF1ZSBlbCBydWlkbyBibGFuY28gdGllbmUgdW5hIGRpc3RyaWJ1Y2nDs24gcGFydGljdWxhciwgcGVybyBtw6FzIGFkZWxhbnRlIHN1cG9uZHJlbW9zIHF1ZSBlbCBydWlkbyBibGFuY28gdGllbmUgZGlzdHJpYnVjacOzbiBub3JtYWwuClVuYSBub3RhY2nDs24gbXV5IHXMgXRpbCBwYXJhIGNvbnNpZGVyYXIgZXN0ZSB0aXBvIGRlIG1vZGVsb3Mgc2UgYmFzYSBlbiBlbCB1c28gZGVsIG9wZXJhZG9yIGRlIHJldGFyZG8gJEIkLiBFbCBtb2RlbG8gJEFSKHApJCBlcwoKCiQkKDEtXHBoaV97MX0gQiAtIFxwaGlfezJ9IEJeezJ9LVxwaGlfezN9Ql57M30tXGNkb3RzIC1ccGhpX3twfUJee3B9KVlfe3R9PVx2YXJlcHNpbG9uX3t0fSBcdGFnezMuMX0kJApMYSBlY3VhY2nDs24gKDMuMSkgc2UgcHVlZGUgcmVzdW1pciB1c2FuZG8gbGEgc2lndWllbnRlIG5vdGFjacOzbjoKJCRccGhpKEIpWF97dH09XHZhcmVwc2lsb25fe3R9JCQKRG9uZGUgJFxwaGkoQikkIGVzIHVuIHBvbGlub21pbyBkZSBncmFkbyAkcCQgbGxhbWFkbyBvcGVyYWRvciBhdXRvcnJlZ3Jlc2l2bywgZGVmaW5pZG8gcG9yCgokJFxwaGkoQik9KDEtXHBoaV97MX0gQiAtIFxwaGlfezJ9IEJeezJ9LVxwaGlfezN9Ql57M30tXGNkb3RzIC1ccGhpX3twfUJee3B9KSQkCgojIyMgUHJvY2VzbyBBdXRvcmVncmVzaXZvIGRlIE9yZGVuIDEgJEFSKDEpJAoKRW4gZXN0ZSBwcm9jZXNvIGxhIHZhcmlhYmxlICRZX3t0fSQgZGVwZW5kZSBkZWwgdmFsb3IgcmV6YWdhZG8gJFlfe3QtMX0kCiQkWV97dH09XHBoaSBZX3t0LTF9K1x2YXJlcHNpbG9uX3t0fSBcdGFnezQuMX0kJAokXHRleHRiZntEZWZpbmljacOzbiAyLjF9JCBTZSBkaWNlIHF1ZSB1biBwcm9jZXNvIGVzdG9jw6FzdGljbyAkWV97dH0kIGVzICRcdGV4dGl0e2VzdHLDrWN0YW1lbnRlIGVzdGFjaW9uYXJpb30kIHNpIHRvZGFzIGxhcyBkaXN0cmlidWNpb25lcyBjb25qdW50YXMgZGUgbGFzIG9ic2VydmFjaW9uZXMgZW4gZGlmZXJlbnRlcyBwdW50b3MgdGVtcG9yYWxlcyBzb24gbGFzIG1pc21hcy4KCgokXHRleHRiZntEZWZpbmljacOzbiAzLjF9JCBTZSBkaWNlIHF1ZSB1biBwcm9jZXNvIGVzdG9jw6FzdGljbyAkWV97dH0kIGVzICRcdGV4dGl0e2TDqWJpbG1lbnRlIGVzdGFjaW9uYXJpb30kIHNpIHN1IG1lZGlhICRcbWF0aGJie0V9KFlfe3R9KSQgeSBzdSB2YXJpYW56YSAkXG1hdGhiYntWfShZX3t0fSkkIHNvbiBjb25zdGFudGVzIGEgdHJhdsOpcyBkZWwgdGllbXBvIHkgbGEgYXV0b2NvdmFyaWFuemEgJFxtYXRoYmJ7Q30oWV97dH0sWV97dCtofSkkIGVudHJlIGN1YWxlc3F1aWVyYSBkb3Mgb2JzZXJ2YWNpb25lcyBubyBkZXBlbmRlIGRlICR0JC4KCgokXHRleHRiZntUZW9yZW1hICAxfSQgU2kgdW4gcHJvY2VzbyBlc3RvY2FzdGljbyAkWV97dH0kIGVzIGVzdHLDrWN0YW1lbnRlIGVzdGFjaW9uYXJpbywgZW50b25jZXMgZXMgZMOpYmlsbWVudGUgZXN0YWNpb25hcmlvLgoKU2kgaXRlcmFtb3MgbGEgZWN1YWNpw7NuICg0LjEpIGhhY2lhIGF0csOhcywgdGVuZW1vcyBxdWUsCgpcYmVnaW57YWxpZ259Cllfe3R9Jj1cbGVmdChccGhpKFxwaGkgWV97dC0yfStcdmFyZXBzaWxvbl97dC0xfSlccmlnaHQpK1x2YXJlcHNpbG9uX3t0fVxcIFxcCiAgICAmPSBccGhpXnsyfVlfe3QtMn0rXHBoaVx2YXJlcHNpbG9uX3t0LTF9K1x2YXJlcHNpbG9uX3t0fVxcIFxcClxMZWZ0cmlnaHRhcnJvdyBZX3t0fSY9XHBoaV57a31ZX3t0LWt9K1xzdW1fe2k9MH1ee2stMX1ccGhpXntpfVx2YXJlcHNpbG9uX3t0LWl9ClxlbmR7YWxpZ259CgpTaSBjb250aW51YW1vcyBlc3RlIHByb2Nlc28gZGUgaXRlcmFjacOzbiBhbCBwYXNhZG8gKHNpZW1wcmUgcXVlICR8XHBoaXw8MSkkIHkgJFlfe3R9JCBzZWEgZXN0YWNpb25hcmlvLCBwb2RlbW9zIHJlcHJlc2VudGFyIGVsIG1vZGVsbyAkQVIoMSkkIGNvbW8gdW4gcHJvY2VzbyBsaW5lYWw6CgokJFlfe3R9PVxsaW1fe2tccmlnaHRhcnJvd1xpbmZ0eX1ccGhpXntrfVlfe3Qta30rXHN1bV97aT0wfV57ay0xfVxwaGlee2l9XHZhcmVwc2lsb25fe3QtaX0kJApBcGxpY2FuZG8gZWwgbMOtbWl0ZSB5IHVzYW5kbyBlbCBoZWNobyBkZSBxdWUgJHxccGhpfDwxJCwgdGVuZW1vcyBxdWUsCiQkWV97dH09XHN1bV97aT0wfV57XGluZnR5fVxwaGlee2l9XHZhcmVwc2lsb25fe3QtaX1cdGFnezUuMX1cc2ltIE1BKFxpbmZ0eSkkJApQb3IgbG8gdGFudG8sIGxhIGVjdWFjacOzbiAoNS4xKSBkZWZpbmUgdW4gcHJvY2VzbyAkQVIoMSkkIGVzdGFjaW9uYXJpbyBjb24gbWVkaWEsClxiZWdpbnthbGlnbn0KXG1hdGhiYntFfShZX3t0fSkmPVxtYXRoYmJ7RX1cbGVmdChcc3VtX3tpPTB9XntcaW5mdHl9XHBoaV57aX1cdmFyZXBzaWxvbl97dC1pfVxyaWdodClcXCBcXAogICAgICAgICAgJj1cc3VtX3tpPTB9XntcaW5mdHl9XHBoaV57aX1cbWF0aGJie0V9KFx2YXJlcHNpbG9uX3t0LWl9KT0wClxlbmR7YWxpZ259Cgp2YXJpYW56YSwKClxiZWdpbnthbGlnbn0KXG1hdGhiYntWfShZX3t0fSkmPVxtYXRoYmJ7Vn1cbGVmdChcc3VtX3tpPTB9XntcaW5mdHl9XHBoaV57aX1cdmFyZXBzaWxvbl97dC1pfVxyaWdodClcXCBcXAogICAgICAgICY9XHN1bV97aT0wfV57XGluZnR5fVxwaGleezJpfVxtYXRoYmJ7Vn0oXHZhcmVwc2lsb25fe3QtaX0pPVxzaWdtYV97XHZhcmVwc2lsb259XnsyfVxzdW1fe2k9MH1ee1xpbmZ0eX1ccGhpXnsyaX0KXGVuZHthbGlnbn0KCnkgYXV0b2NvdmFyaWFuemEsCgpcYmVnaW57YWxpZ259ClxtYXRoYmJ7Q30oWV97dH0sWV97dCtofSkmPVxtYXRoYmJ7RX1cbGVmdChcc3VtX3tpPTB9XntcaW5mdHl9XHBoaV57aX1cdmFyZXBzaWxvbl97dC1pfVxjZG90IFxzdW1fe2k9MH1ee1xpbmZ0eX1ccGhpXntpfVx2YXJlcHNpbG9uX3t0K2gtaX1ccmlnaHQpIC0gXG1hdGhiYntFfVxsZWZ0KFxzdW1fe2k9MH1ee1xpbmZ0eX1ccGhpXntpfVx2YXJlcHNpbG9uX3t0LWl9XHJpZ2h0KVxjZG90XG1hdGhiYntFfVxsZWZ0KFxzdW1fe2k9MH1ee1xpbmZ0eX1ccGhpXntpfVx2YXJlcHNpbG9uX3t0K2gtaX1ccmlnaHQpXFwgXFwKICAgICAgICAgICAgJj1cbWF0aGJie0V9XGxlZnQoKFx2YXJlcHNpbG9uX3t0fStccGhpXHZhcmVwc2lsb25fe3QtMX0rXHBoaV57Mn1cdmFyZXBzaWxvbl97dC0yfStcY2RvdHMpXGNkb3QoXHZhcmVwc2lsb25fe3QraH0rXHBoaVx2YXJlcHNpbG9uX3t0K2gtMX0rXHBoaV57Mn1cdmFyZXBzaWxvbl97dCtoLTJ9K1xjZG90cytccGhpXntofVx2YXJlcHNpbG9uX3t0fStccGhpXntoKzF9XHZhcmVwc2lsb25fe3QtMX0rXGNkb3RzKVxyaWdodCkKXGVuZHthbGlnbn0KCmRhZG8gcXVlICRcdmFyZXBzaWxvbl97dH1cc2ltIFJCKDAsXHNpZ21hX3tcdmFyZXBzaWxvbn1eezJ9KSQsIHRlbmVtb3MgcXVlIGxvcyBtb21lbnRvcyBjcnV6YWRvcyAkXG1hdGhiYntFfShcdmFyZXBzaWxvbl97dH1cdmFyZXBzaWxvbl97c30pPTAkIHNpaSAkdFxub3Q9cyQsIGx1ZWdvCgpcYmVnaW57YWxpZ259ClxtYXRoYmJ7Q30oWV97dH0sWV97dCtofSkmPVxtYXRoYmJ7RX1cbGVmdCgoXHZhcmVwc2lsb25fe3R9K1xwaGlcdmFyZXBzaWxvbl97dC0xfStccGhpXnsyfVx2YXJlcHNpbG9uX3t0LTJ9K1xjZG90cylcY2RvdChcdmFyZXBzaWxvbl97dCtofStccGhpXHZhcmVwc2lsb25fe3QraC0xfStccGhpXnsyfVx2YXJlcHNpbG9uX3t0K2gtMn0rXGNkb3RzK1xwaGlee2h9XHZhcmVwc2lsb25fe3R9K1xwaGlee2grMX1cdmFyZXBzaWxvbl97dC0xfStcY2RvdHMpXHJpZ2h0KVxcIFxcCiY9XHNpZ21hX3tcdmFyZXBzaWxvbn1eezJ9XHBoaV57aH1cc3VtX3tpPTB9XntcaW5mdHl9XHBoaXsyaX09XGZyYWN7XHNpZ21hX3tcdmFyZXBzaWxvbn1eezJ9XHBoaV57aH19ezEtXHBoaV57Mn19LFxxdWFkIGg+MApcZW5ke2FsaWdufQoKIyMjIFNpbXVsYWNpw7NuICRBUigxKSQKCgpgYGB7ciBTaW11bGFjacOzbiBkZSB1biBwcm9jZXNvIEFSKDEpfQpzZXQuc2VlZCgxKSAgICAgICAgICAgICAjVmFtb3MgYSBmaWphciBsYSBzZW1pbGxhIGVuIDEgcGFyYSBnZW5lcmFyIHVuIG1pc21vIHZlY3RvciBkZSBuw7ptZXJvcyBhbGVhdG9yaW9zCgpYIDwtIG1hdHJpeChyZXAoMCw1MCksbmNvbD0xKSAgICAgICAjR2VuZXJhbW9zIGVzdGUgdmVjdG9yIGNvbiAwIHBhcmEgZ3VhcmRhciBsb3MgZGF0b3MgZGUgdW5hIHNlcmllCmluaWNpbyA8LSA1ICAgICAgICAgICAgICAgICAgICAgICAgICNWYWxvciBkZSBsYSBwcmltZXJhIG9ic2VydmFjacOzbiBkZSBsYSBzZXJpZQpwaGkgPC0gMC44ICAgICAgICAgICAgICAgICAgICAgICAgICAjUGFyw6FtZXRybyBwaGkgZGUgbGEgZWN1YWNpw7NuICg1LjEpCmVwc2lsb24gPC0gcm5vcm0oNDksMCwxLjUpICAgICAgICAgICNWYW1vcyBhIG1vZGVsYXIgZWwgZXJyb3IgZGUgbGEgcmVncmVzacOzbiBjb24gdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsIGNvbiBtZWRpYSAwIHkgdmFyaWFuemEgMS41ClhbMV08LSBpbmljaW8gICAgICAgICAgICAgICAgICAgICAgICNJbmljaWFsaXphbW9zIGxhIHNlcmllIGNvbiBlbCB2YWxvciBpbmljaW8uCgpmb3IgKGkgaW4gMjpucm93KFgpKXsKICBYW2ldPVhbaS0xXSpwaGkrZXBzaWxvbltpLTFdCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNHZW5lcmFtb3MgZWwgcmVzdG8gZGUgbGFzIG9ic2VydmFjaW9uZXMKClggPC0gdHMoWCxmcmVxdWVuY3kgPSAxLCAKICAgICAgICBzdGFydCA9IDE5NzEpICAgICAgICAgICAgICAgI0Zvcm1hdG8gZGUgc2VyaWUgdGVtcG9yYWwgY29uIG9ic2VydmFjaW9uZXMgcG9yIGHDsW8KYGBgCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpYX2RmIDwtIGRhdGEuZnJhbWUoZmVjaGEgPSB0aW1lKFgpLAogICAgICAgICAgICAgICAgICAgICAgIHZhbG9yID0gYXMudmVjdG9yKFgpKSAjZ2dwbG90MiB1dGlsaXphIGRhdGEgZnJhbWVzLCBwb3IgbG8gdGFudG8gbW9kaWZpY2Fyw6kgbGEgc2VyaWUgb3JpZ2luYWwuCgpnZ3Bsb3QoWF9kZiwgYWVzKHggPSBmZWNoYSwgeSA9IHZhbG9yKSkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHRpdGxlID0gIk1pIFNlcmllIGRlIFRpZW1wbyIsIAogICAgICAgeCA9ICJGZWNoYSIsIHkgPSAiVmFsb3IiKSAgICAgICAgICAgICNHcmFmaWNhIGxhIHNlcmllCmBgYAoKIyMjIFByb25vc3RpY28gJEFSKDEpJAoKU2VhIGxhIHNlcmllIGRlIHRpZW1wbyAkWV97dH0kIGRhZGEgcG9yCiQkWV97dH09XHBoaV97MH0rXHBoaV97MX1ZX3t0LTF9K1x2YXJlcHNpbG9uX3t0fSQkCiQkXHZhcmVwc2lsb25fe3R9XHNpbSBOKDAsXHNpZ21hXnsyfSkkJApwb3IgbG8gdGFudG8gJFlfe3R9XHNpbSBOKFxwaGlfezB9K1xwaGlfezF9WV97dC0xfSxcc2lnbWFeezJ9KSQgeWEgcXVlIGxhIHNlcmllIHNlIGNvbm9jZSBoYXN0YSAkdC0xJCwgeSAkWV97dC0xfVxpblxtYXRoYmJ7Un0kLiBQYXJhIHJlYWxpemFyIHVuIHByb25vc3RpY28gZW4gJHQrMSQgc2UgcHVlZGUgZXNjcmliaXIgY29tbwokJFlfe3QrMX09XHBoaV97MH0rXHBoaV97MX1ZX3t0fStcdmFyZXBzaWxvbl97dCsxfSQkCiQkXHZhcmVwc2lsb25fe3QrMX1cc2ltIE4oMCxcc2lnbWFeezJ9KSQkCkVudG9uY2VzLAoKXGJlZ2lue2FsaWdufQpZX3t0KzF9Jj1ccGhpX3swfStccGhpX3sxfShccGhpX3swfStccGhpX3sxfVlfe3QtMX0rXHZhcmVwc2lsb25fe3R9KStcdmFyZXBzaWxvbl97dCsxfVxcIFxcCiAgICAgICY9XHBoaV97MH0rXHBoaV97MH1ccGhpX3sxfStccGhpX3sxfV57Mn1ZX3t0LTF9K1xwaGlfezF9XHZhcmVwc2lsb25fe3R9K1x2YXJlcHNpbG9uX3t0KzF9ClxlbmR7YWxpZ259CgpQb3IgbG8gdGFudG8sIAokJFlfe3QrMX1cc2ltIE4oXHBoaV97MH0rXHBoaV97MH1ccGhpX3sxfStccGhpX3sxfV57Mn1ZX3t0LTF9LFxzaWdtYV57Mn0oMStccGhpXnsyfSkpJCQKYGBge3J9CmVwc2lsb24uZm9yPC1ybm9ybSgxLDAsMS41KQpYLmZvcjwtWFtsZW5ndGgoWCldKnBoaStlcHNpbG9uLmZvcgpYLmZvcgpgYGAKCiMjIyBTZXJpZSBGaWx0cmFkYSAkQVIkCgpFbCBmaWx0cmFkbyBkZSBsYSBzZXJpZSBzZSBleHByZXNhIGNvbW8gCiQkWV97dH0tWV97dC0xfT1cdmFyZXBzaWxvbl97dH0kJApEb25kZSBsYSBzZXJpZSBmaWx0cmFkYSByZXN1bHRhIHNlciBlbCBlcnJvciBkZWwgcHJvY2Vzby4KYGBge3J9ClhmIDwtIGMocmVwKDAsbGVuZ3RoKFgpLTEpKSAgICAgICAgICAjVmVjdG9yIGRvbmRlIHNlIGFsbWFjZW5hbiBzZXJpZSBmaWx0cmFkYQoKZm9yIChpIGluIDI6bGVuZ3RoKFhmKSl7CiAgWGZbaV09WFtpXS1YW2ktMV0qcGhpCn0KWGYgPC0gdHMoWGYsIGZyZXF1ZW5jeSA9IDEsIHN0YXJ0ID0gMTA3MSkKYGBgCgpgYGB7cn0KWGZfZGYgPC0gZGF0YS5mcmFtZShmZWNoYSA9IHRpbWUoWGYpLAogICAgICAgICAgICAgICAgICAgIHZhbG9yID0gYXMudmVjdG9yKFhmKSkKCmdncGxvdChYZl9kZixhZXMoeCA9IGZlY2hhLCB5ID0gdmFsb3IpKSsKICBnZW9tX2xpbmUoKSsKICBsYWJzKHRpdGxlID0gIkdyw6FmaWNvIGRlIGxhIFNlcmllIEZpbHRyYWRhIiwgCiAgICAgICB4ID0gIkZlY2hhIiwgeSA9ICJWYWxvciIpIApgYGAKCiMjIyBFc3RpbWFjacOzbiBkZSBwcm9jZXNvcyAkQVIkCgphci5vbHMgZXN0aW1hIHVuIG1vZGVsbyBhdXRvcnJlZ3Jlc2l2byBwb3IgZWwgbWV0b2RvIGRlIG1pbmltb3MgY3VhZHJhZG9zIG9yZGluYXJpb3MgKG9scyBwb3Igc3VzIHNpZ2xhcyBlbiBpbmdsZXMpCgpgYGB7cn0KYXIgPC0gYXIub2xzKAogIFgsICAgICAgICAgICAgICAgICAgICAjRGF0b3MgYSBtb2RlbGFyCiAgYWljID0gVFJVRSwgICAgICAgICAgICNDcml0ZXJpbyBBSUMKICBvcmRlci5tYXggPTEsICAgICAgICAgI1Byb2Nlc28gbWF4aW1vIEFSKDEpCiAgaW50ZXJjZXB0ID0gRkFMU0UsICAgICNJbnRlcmNlcHRvIGZhbHNvCiAgZGVtZWFuID0gRkFMU0UgICAgICAgICNPbWl0ZSB1biB2YWxvciBtZWRpbyBxdWUgYXV0b21hdGljYW1lbnRlIGNhbGN1bGEgYXIub2xzCikKYXIKYGBgCgpMYSBlc3RpbWFjacOzbiBkZWwgcGFyw6FtZXRybyAkXHBoaSQgZGVsIG1vZGVsbyAkQVIoMSkkIHBvciBtZWRpbyBkZSBsYSBmdW5jacOzbiBhci5vbHMgZnVlIGRlICRcaGF0e1xwaGl9PTAuNzI4OSQgeSBlbCBwYXLDoW1ldHJvIGNvbiBlbCBxdWUgc2UgZ2VuZXJvIGxhIHNlcmllIGVyYSBkZSAkXHBoaT0wLjgkLgoKUGFyYSBjYWxjdWxhciBsb3MgdmFsb3JlcyBhanVzdGFkb3MgZGVsIG1vZGVsbyBhdXRvcnJlZ3Jlc2l2byBxdWUgc2Ugb2J0dXZvIGFudGVyaW9ybWVudGUsIHNlIHB1ZWRlIHJlYWxpemFyIGRlIG1hbmVyYSBtYW51YWwgbyBwb3IgbWVkaW8gZGUgbGEgZnVuY2nDs24gZml0dGVkIGNvbW8gc2UgcHJlc2VudGEgYSBjb250aW51YWNpw7NuOgoKYGBge3J9ClguZml0IDwtIGZpdHRlZChhcikKYGBgCkdyYWZpY2EgZGUgbG9zIHZhbG9yZXMgcmVhbGVzIGNvbnRyYSBsb3MgZXN0aW1hZG9zOgpgYGB7cn0KWC5maXRfZGYgPC0gZGF0YS5mcmFtZShmZWNoYSA9IHRpbWUoWCksCiAgICAgICAgICAgICAgICAgICAgdmFsb3IgPSBhcy52ZWN0b3IoWC5maXQpKQpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBYLmZpdF9kZiwgYWVzKHggPSBmZWNoYSwgeSA9IHZhbG9yLCBjb2xvciA9ICJTZXJpZSBFc3RpbWFkYSIpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBYX2RmLCBhZXMoeCA9IGZlY2hhLCB5ID0gdmFsb3IsIGNvbG9yID0gIlNlcmllIFJlYWwiKSkgKwogIGxhYnModGl0bGUgPSAiU2VyaWUgUmVhbCB2cy4gU2VyaWUgRXN0aW1hZGEiLAogICAgICAgeCA9ICJGZWNoYSIsCiAgICAgICB5ID0gIlZhbG9yIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJTZXJpZSBFc3RpbWFkYSIgPSAiYmx1ZSIsICJTZXJpZSBSZWFsIiA9ICJyZWQiKSkKYGBgCgojIyMjIEPDoWxjdWxvIGRlIGxvcyByZXNpZHVhbGVzOgpgYGB7cn0KcmVzaWR1YWxzIDwtIGFyJHJlc2lkICNlcyBsYSBkaWZlcmVuY2lhIGVudHJlIGxvcyB2YWxvcmVzIG9ic2VydmFkb3MgeSBsb3MgZXN0aW1hZG9zCnJlc2lkdWFscwpgYGAKR3LDoWZpY28gZGUgbG9zIHJlc2lkdW9zCmBgYHtyfQpyZXNpZHVhbHNfZGYgPC0gZGF0YS5mcmFtZShyZXNpZHVhbHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlY2hhID0gdGltZShYKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsb3IgPSBhcy52ZWN0b3IocmVzaWR1YWxzKSkKZ2dwbG90KHJlc2lkdWFsc19kZiwgYWVzKHggPSBmZWNoYSwgeSA9IHZhbG9yKSkrCiAgZ2VvbV9saW5lKCkrCiAgbGFicyh0aXRsZSA9ICJHcsOhZmljbyBkZSBsb3MgUmVzaWR1b3MiLCAKICAgICAgIHggPSAiRmVjaGEiLCB5ID0gIlZhbG9yIikgCmBgYAoKIyMjIyBEaWFnbm9zdGljbyBkZSBsb3MgcmVzaWR1b3M6CgpMYSBkaXN0cmlidWNpw7NuIG5vcm1hbCBkZSBsb3MgcmVzaWR1b3MgZXMgdW5hIHN1cG9zaWNpw7NuIGZ1bmRhbWVudGFsIGRldHLDoXMgZGUgbXVjaG9zIG3DqXRvZG9zIGRlIGVzdGltYWNpw7NuIGRlIHBhcsOhbWV0cm9zLCBjb21vIGxhIGVzdGltYWNpw7NuIGRlIG3DoXhpbWEgdmVyb3NpbWlsaXR1ZCAoTUxFKSB5IGxvcyBtw61uaW1vcyBjdWFkcmFkb3Mgb3JkaW5hcmlvcyAoT0xTKS4gQ3VhbmRvIGxvcyByZXNpZHVvcyBzZSBkaXN0cmlidXllbiBub3JtYWxtZW50ZSwgbGFzIGVzdGltYWNpb25lcyBkZSBsb3MgcGFyw6FtZXRyb3MgZGVsIG1vZGVsbyBzb24gZWZpY2llbnRlcyB5IG5vIHNlc2dhZGFzLgoKTGEgbm9ybWFsaWRhZCBkZSBsb3MgcmVzaWR1b3MgZXMgaW1wb3J0YW50ZSBwYXJhIGhhY2VyIHByb27Ds3N0aWNvcyB5IHByZWRpY2Npb25lcyBwcmVjaXNhcy4gTG9zIGludGVydmFsb3MgZGUgcHJlZGljY2nDs24geSBsYXMgcHJlZGljY2lvbmVzIHB1bnR1YWxlcyBzZSBiYXNhbiBlbiBsYSBzdXBvc2ljacOzbiBkZSBxdWUgbG9zIHJlc2lkdW9zIHNvbiBub3JtYWxtZW50ZSBkaXN0cmlidWlkb3MuCgpQYXJhIGhhY2VyIGVsIGFuw6FsaXNpcyBkZSBub3JtYWxpZGFkIGRlIGxvcyByZXNpZHVvcywgZXMgbmVjZXNhcmlvIGNhbGN1bGFyIHN1IGRlbnNpZGFkIHByaW1lcm86CmBgYHtyfQojIERpc3RyaWJ1Y2nDs24gZGUgbG9zIHJlc2lkdW9zCnJlc2lkdWFscyA8LSBuYS5vbWl0KHJlc2lkdWFscykKZGVuc2lkYWRfcmVzIDwtZGVuc2l0eShyZXNpZHVhbHMpCmRlbnNpZGFkX3Jlc19kZiA8LSBkYXRhLmZyYW1lKHggPSBkZW5zaWRhZF9yZXMkeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGRlbnNpZGFkX3JlcyR5KQoKIyBEaXN0cmlidWNpw7NuIGRlIGxhIG5vcm1hbCBjb24gMTAwMCBwdW50b3MKbm9ybWFsIDwtIHNlcShtaW4ocmVzaWR1YWxzKS0yLCBtYXgocmVzaWR1YWxzKSsyLCBsZW5ndGgub3V0ID0gMTAwMCkKbWVkaWEgPC0gbWVhbihyZXNpZHVhbHMpCmRlc3ZpYWNpb24gPC0gc2QocmVzaWR1YWxzKQpkZW5zaWRhZF9ub3JtYWwgPC0gZG5vcm0obm9ybWFsLCBtZWFuID0gbWVkaWEsIHNkID0gZGVzdmlhY2lvbikKbm9ybWFsX2RmIDwtIGRhdGEuZnJhbWUoeCA9IG5vcm1hbCwgZGVuc2lkYWQgPSBkZW5zaWRhZF9ub3JtYWwpCgoKI0dyw6FmaWNvCmdncGxvdChkZW5zaWRhZF9yZXNfZGYsIGFlcyh4ID0geCwgeSA9IHkpKSArCiAgZ2VvbV9saW5lKGNvbG9yID0gImJsdWUiLCBsaW5ldHlwZSA9ICJzb2xpZCIsIHNpemUgPSAxKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBub3JtYWxfZGYsIGFlcyh4ID0geCwgeSA9IGRlbnNpZGFkKSwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDEpICsKICBsYWJzKHRpdGxlID0gIkRlbnNpZGFkIE9ic2VydmFjaW9uZXMgdnMuIERlbnNpZGFkIE5vcm1hbCIsCiAgICAgICB4ID0gIlZhbG9yIiwKICAgICAgIHkgPSAiRGVuc2lkYWQiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImJsdWUiLCAicmVkIikpCmBgYAojIyMjIFBydWViYSBBQ0YgeSBDb3JyZWxvZ3JhbWEgZGUgbG9zIHJlc2lkdW9zOgoKTGEgQUNGIGVzIHVuYSBmdW5jacOzbiBlc3RhZMOtc3RpY2EgcXVlIHNlIHV0aWxpemEgcGFyYSBtZWRpciB5IHZpc3VhbGl6YXIgbGEgYXV0b2NvcnJlbGFjacOzbiBlbnRyZSB1bmEgc2VyaWUgdGVtcG9yYWwgeSBzdXMgcHJvcGlvcyByZXphZ29zLiBFbiBvdHJhcyBwYWxhYnJhcywgbGEgQUNGIG11ZXN0cmEgY8OzbW8gc2UgcmVsYWNpb25hIGNhZGEgb2JzZXJ2YWNpw7NuIGNvbiBsYXMgb2JzZXJ2YWNpb25lcyBhbnRlcmlvcmVzIGVuIGRpZmVyZW50ZXMgcGVyw61vZG9zIGRlIHRpZW1wby4gTGEgQUNGIHNlIGNhbGN1bGEgbWVkaWFudGUgbGEgY29ycmVsYWNpw7NuIGVudHJlIGxhIHNlcmllIHRlbXBvcmFsIG9yaWdpbmFsIHkgdmVyc2lvbmVzIGRlc3BsYXphZGFzIGRlIHPDrSBtaXNtYSBhIGxvIGxhcmdvIGRlbCB0aWVtcG8uIExhIEFDRiBlcyB1bmEgaGVycmFtaWVudGEgaW1wb3J0YW50ZSBwYXJhIGlkZW50aWZpY2FyIHBhdHJvbmVzIGRlIGF1dG9jb3JyZWxhY2nDs24gZW4gdW5hIHNlcmllIHRlbXBvcmFsLCBjb21vIGNpY2xvcywgZXN0YWNpb25hbGlkYWQgeSB0ZW5kZW5jaWFzLgoKYGBge3J9CnBhcihtYXIgPSBjKDUsIDUsIDQsIDIpKQpyZXNpZHVhbHNfYWNmIDwtIGFjZihyZXNpZHVhbHMsIGxhZy5tYXggPSAyMCwKICAgICAgICAgICAgICAgICAgICAgbWFpbiA9ICJDb3JyZWxvZ3JhbWEgZGUgbG9zIFJlc2lkdW9zIiwgY2V4Lm1haW4gPSAxLjIpCgpgYGAKCkxhIGZhbHRhIGRlIGF1dG9jb3JyZWxhY2nDs24gZGVzcHXDqXMgZGVsIHByaW1lciBwZXLDrW9kbyBzdWdpZXJlIHF1ZSBsYXMgb2JzZXJ2YWNpb25lcyBkZSBsYSBzZXJpZSB0ZW1wb3JhbCBzb24gZXNlbmNpYWxtZW50ZSBpbmRlcGVuZGllbnRlcyBlbnRyZSBzw60uIEVzdG8gc2lnbmlmaWNhIHF1ZSBubyBoYXkgdW5hIHJlbGFjacOzbiBzaXN0ZW3DoXRpY2EgeSBzaWduaWZpY2F0aXZhIGVudHJlIGxhcyBvYnNlcnZhY2lvbmVzIGVuIG1vbWVudG9zIHN1Y2VzaXZvcywgbG8gcXVlIGVzIHVuYSBzdXBvc2ljacOzbiBpbXBvcnRhbnRlIGVuIG11Y2hhcyB0w6ljbmljYXMgZXN0YWTDrXN0aWNhcyB5IGRlIG1vZGVsYWRvLgoKQWRlbcOhcywgbGEgYXVzZW5jaWEgZGUgYXV0b2NvcnJlbGFjacOzbiBzaWduaWZpY2F0aXZhIGVuIGxvcyByZXphZ29zIHBvc3RlcmlvcmVzIHB1ZWRlIGluZGljYXIgcXVlIGVsIGNvbXBvcnRhbWllbnRvIGRlIGxhIHNlcmllIGVzIGVzdGFibGUgeSBubyBtdWVzdHJhIHBhdHJvbmVzIGRlIGVzdGFjaW9uYWxpZGFkLCB0ZW5kZW5jaWEgbyBjaWNsb3MgcXVlIHNlIHJlcGl0ZW4gYSBsbyBsYXJnbyBkZWwgdGllbXBvLgoKIyMjIyBQcnVlYmEgUEFDRgpMYSBQQUNGIHNlIHV0aWxpemEgY29tw7pubWVudGUgcGFyYSBkZXRlcm1pbmFyIGVsIG9yZGVuIGFkZWN1YWRvIGRlIHVuIG1vZGVsbyBBUi4gQ3VhbmRvIHNlIG9ic2VydmEgdW4gZGVjYWltaWVudG8gc2lnbmlmaWNhdGl2byBlbiBsYSBQQUNGIGRlc3B1w6lzIGRlIHVuIHJlemFnbyBlc3BlY8OtZmljbywgaW5kaWNhIHF1ZSBlc2UgcmV6YWdvIGVzIGVsIG9yZGVuIGFkZWN1YWRvIGRlbCBtb2RlbG8gQVIuIFBvciBlamVtcGxvLCBzaSBsYSBQQUNGIG11ZXN0cmEgdW4gZGVjYWltaWVudG8gc2lnbmlmaWNhdGl2byBkZXNwdcOpcyBkZWwgcmV6YWdvIDIsIHN1Z2llcmUgdW4gbW9kZWxvIEFSKDIpLiAKCkxhIFBBQ0YgcHVlZGUgYXl1ZGFyIGEgZGlmZXJlbmNpYXIgZW50cmUgbW9kZWxvcyBBUiB5IG1vZGVsb3MgTUEgKHF1ZSB2ZXJlbW9zIGVuIGVsIHNpZ3VpZW50ZSBhcGFydGFkbykuIFNpIGxhIFBBQ0YgbXVlc3RyYSB1bmEgY2HDrWRhIGFicnVwdGEgZGVzcHXDqXMgZGUgdW4gcmV6YWdvIGVzcGVjw61maWNvIHkgbHVlZ28gcGVybWFuZWNlIGNlcmNhIGRlIGNlcm8sIHN1Z2llcmUgdW4gbW9kZWxvIEFSLCBtaWVudHJhcyBxdWUgdW5hIFBBQ0YgcXVlIGRlY2FlIGxlbnRhbWVudGUgc3VnaWVyZSB1biBtb2RlbG8gTUEuIAoKYGBge3J9CnBhcihtYXIgPSBjKDUsIDUsIDQsIDIpKQpyZXNpZHVhbHNfcGFjZiA8LSBwYWNmKHJlc2lkdWFscywgbGFnLm1heCA9IDIwLAogICAgICAgICAgICAgICAgICAgICBtYWluID0gIlBBQ0YgZGUgbG9zIFJlc2lkdW9zIiwgY2V4Lm1haW4gPSAxLjIpCmBgYAoKCkVuIGVsIGNvbnRleHRvIGRlIG1vZGVsYWRvIGRlIHNlcmllcyB0ZW1wb3JhbGVzLCBzaSBsYSBQQUNGIGRlIGxvcyByZXNpZHVvcyBlc3TDoSBkZW50cm8gZGVsIGludGVydmFsbyBkZSBjb25maWFuemEgZW4gdG9kb3MgbG9zIHJlemFnb3MsIGluZGljYSBxdWUgZWwgbW9kZWxvIGVsZWdpZG8gZXMgYWRlY3VhZG8gcGFyYSBkZXNjcmliaXIgbGEgZXN0cnVjdHVyYSBkZSBkZXBlbmRlbmNpYSBlbiBsb3MgZGF0b3MuIExvcyByZXNpZHVvcyBwYXJlY2VuIG5vIGNvbnRlbmVyIGluZm9ybWFjacOzbiBhZGljaW9uYWwgcXVlIG5vIHNlIGhheWEgY2FwdHVyYWRvIGVuIGVsIG1vZGVsby4KCgojIFByb2Nlc29zIGRlIE1lZGlhcyBNb3ZpbGVzICRNQShxKSQKCiRcdGV4dGJme0RlZmluaWNpw7NuIDIuMX0kIFNlIGRpY2UgcXVlIHVuYSBzZXJpZSB0ZW1wb3JhbCAkWV97dH0kIGFkbWl0ZSB1bmEgcmVwcmVzZW50YWNpb8yBbiBkZSBtZWRpYXMgbW/MgXZpbGVzIChNQSkgZGUgb3JkZW4gJHEkICwgeSBzZSBkZW5vdGEgcG9yICRNQShxKSQgLCBzaSBlcyBzdXNjZXB0aWJsZSBkZSBzZXIgbW9kZWxpemFkYSBhIHRyYXZlzIFzIGRlIGxhIGVjdWFjaW/MgW46ClxiZWdpbnthbGlnbn0KWV97dH0mPVx0aGV0YV97MX1cdmFyZXBzaWxvbl97dC0xfStcdGhldGFfezJ9XHZhcmVwc2lsb25fe3QtMn0rXGNkb3RzK1x0aGV0YV97cX1cdmFyZXBzaWxvbl97dC1xfStcdmFyZXBzaWxvbl97dH1cXCBcXAogICAgJj1cc3VtX3tpPTF9XntxfVx0aGV0YV97aX1cdmFyZXBzaWxvbl97dC1pfStcdmFyZXBzaWxvbl97dH0sICBcdGFnezEuMn0KXGVuZHthbGlnbn0KCkRvbmRlICRZX3t0fSQgZXMgdW5hIHZhcmlhYmxlIGFsZWF0b3JpYSBjb25jZWJpZGEgY29tbyByZWFsaXphY2lvbmVzIGRlIHVuIHByb2Nlc28gZXN0b2NhzIFzdGljbyBlbiBsb3MgbW9tZW50b3MgZGVsIHRpZW1wbyAkdCQgLCBxdWUgc2UgY2FyYWN0ZXJpemFuIHBvciAkXG1hdGhiYntFfShZX3t0fSk9XG1hdGhiYntFfShZX3t04oiSMX0pPVxtYXRoYmJ7RX0oWV97dOKIkjJ9KT1cY2RvdHMkLCAkXHRoZXRhX3sxfSwuLi4sXHRoZXRhX3txfSQgc29uIHBhcsOhbWV0cm9zIGRlbCBtb2RlbG8gcXVlLCBqdW50byBjb24gbGEgdmFyaWFuemEgZGViZW4gc2VyIGVzdGltYWRvcywgeSAkXHZhcmVwc2lsb25fe3R9XHNpbSBSQigwLFxzaWdtYV97XHZhcmVwc2lsb259XnsyfSkkLgoKJFx0ZXh0YmZ7RGVmaW5pY2nDs24gMi4xfSQgU2UgZGljZSBxdWUgdW4gcHJvY2VzbyBNQSgxKSBlcyAkXHRleHRpdHtlc3RhY2lvbmFyaW8gZW4gbWVkaWF9JCBzaQokJFxtYXRoYmJ7RX0oWV97dH0pPVxtYXRoYmJ7RX0oXHZhcmVwc2lsb25fe3R9K1x0aGV0YVx2YXJlcHNpbG9uX3t0LTF9KT0wJCQKJFx0ZXh0YmZ7RGVmaW5pY2nDs24gMi4zfSQgU2UgZGljZSBxdWUgdW4gcHJvY2VzbyBNQSgxKSBlcyAkXHRleHRpdHtlc3RhY2lvbmFyaW8gZW4gY292YXJpYW56YX0kIHNpCgpcYmVnaW57YWxpZ259ClxnYW1tYV8wJj1cbWF0aGJie0V9KFlfe3R9LVxtYXRoYmJ7RX0oWV97dH0pKV57Mn09XG1hdGhiYntFfShZX3t0fSleezJ9PVxtYXRoYmJ7RX0oXHZhcmVwc2lsb25fe3R9K1x0aGV0YVx2YXJlcHNpbG9uX3t0LTF9KV57Mn1cXFxcCiAgICAgICY9XG1hdGhiYntFfShcdmFyZXBzaWxvbl97dH1eezJ9KzJcdGhldGFeezJ9XHZhcmVwc2lsb25fe3R9XHZhcmVwc2lsb25fe3QtMX0rXHRoZXRhXnsyfVx2YXJlcHNpbG9uX3t0LTF9XnsyfSlcXFxcCiAgICAgICY9XG1hdGhiYntFfShcdmFyZXBzaWxvbl97dH1eezJ9KSsyXHRoZXRhXnsyfVxtYXRoYmJ7RX0oXHZhcmVwc2lsb25fe3R9XHZhcmVwc2lsb25fe3QtMX0pK1xtYXRoYmJ7RX0oXHZhcmVwc2lsb25fe3QtMX1eezJ9KVxcIFxcCiAgICAgICY9XHNpZ21hX3tcdmFyZXBzaWxvbn1eezJ9K1xzaWdtYV97XHZhcmVwc2lsb259XnsyfVx0aGV0YV57Mn09XHNpZ21hX3tcdmFyZXBzaWxvbn1eezJ9KDErXHRoZXRhXnsyfSk8XGluZnR5ClxlbmR7YWxpZ259CgojIyMgU2ltdWxhY2nDs24gJE1BKDEpJAoKYGBge3J9CnNldC5zZWVkKDEpCgpZIDwtIG1hdHJpeChyZXAoMCw1MCksIG5jb2w9MSkKZXBzaWxvbiA8LSBybm9ybSg1MCwwLDEuNSkKdGhldGEgPC0wLjkKY3RlIDwtIDAKCllbMV0gPC0gZXBzaWxvblsxXQoKZm9yIChpIGluIDI6bnJvdyhZKSl7CiAgWVtpXSA8LSBjdGUgKyB0aGV0YSplcHNpbG9uW2ktMV0gKyBlcHNpbG9uW2ldCn0KClkgPC0gdHMoWSwgZnJlcXVlbmN5ID0gMSwgc3RhcnQgPSAxOTcwKQpgYGAKCgpgYGB7cn0KWV9kZiA8LSBkYXRhLmZyYW1lKGZlY2hhID0gdGltZShZKSwKICAgICAgICAgICAgICAgICAgIHZhbG9yID0gYXMudmVjdG9yKFkpKQoKZ2dwbG90KFlfZGYsYWVzKHg9ZmVjaGEsIHk9dmFsb3IpKSsKICBnZW9tX2xpbmUoKSsKICBnZW9tX3BvaW50KCkrCiAgbGFicyh0aXRsZSA9ICJHcsOhZmljbyBkZSBNQSIsIHhsYWIoIkZlY2hhIiksIHlsYWIoIlZhbG9yIikpCmBgYAoKIyMjIFByb27Ds3N0aWNvIGNvbiBQcm9jZXNvICRNQSQKClBhcmEgaGFjZXIgbGEgZXN0aW1hY2nDs24gZGUgbGEgc2VyaWUgdmFtb3MgYSBzdXBvbmVyIHF1ZSwKJCRcaGF0e1lfe3R9fT1ccGhpX3swfStccGhpX3sxfWVfe3QtMX0rZV97dH0kJAokJGVfe3R9XHNpbVxzaWdtYV97XHZhcmVwc2lsb259XHZhcmVwc2lsb25fe3R9JCQKCiQkXHZhcmVwc2lsb25cc2ltIE4oMCwxKSQkCmRvbmRlICRZX3t0fSQgZXMgZWwgw7psdGltbyB2YWxvciBjb25vY2lkbyBkZSBsYSBzZXJpZSB5ICRlX3t0fSQgZXMgZWwgw7psdGltbyB2YWxvciBkZWwgcnVpZG8gY29ub2NpZG8uIAoKU3Vwb25nYSBxdWUgJFxwaGlfezB9PTAkICRZX3swfT1lX3t0fSQsICRcaGF0e1lfezF9fT1ccGhpX3sxfWVfezB9K2VfezF9JCwgJFxoYXR7WV97Mn19PVxwaGlfezF9ZV97MX0rZV97Mn0kLCBwb3IgbG8gdGFudG8KJCRcaGF0e1l9X3t0KzF9PVxwaGlfezF9ZV97dH0rZV97dCsxfSQkCiMjIyBTZXJpZSBGaWx0cmFkYSAkTUEoMSkkCmBgYHtyfQpZZiA8LSBtYXRyaXgocmVwKDAsNTApLG5jb2w9MSkKCmZvciAoaSBpbiAyOm5yb3coWWYpKXsKICBZZltpLTFdIDwtIFlbaV0rZXBzaWxvbltpLTFdCn0KCllmIDwtIHRzKFlmLCBmcmVxdWVuY3kgPSAxLCBzdGFydCA9IDE5NzApCmBgYAoKYGBge3J9CllmX2RmIDwtIGRhdGEuZnJhbWUoZmVjaGEgPSB0aW1lKFlmKSwKICAgICAgICAgICAgICAgICAgICB2YWxvciA9IGFzLnZlY3RvcihZZikpCgpnZ3Bsb3QoWWZfZGYsIGFlcyh4ID0gZmVjaGEsIHkgPSB2YWxvcikpKwogIGdlb21fbGluZSgpKwogIGdlb21fcG9pbnQoKSsKICBsYWJzKHRpdGxlID0gIkdyw6FmaWNvIFNlcmllIEZpbHRyYWRhIE1BIiwgeGxhYigiRmVoY2EiKSwKICAgICAgIHlsYWIoIlZhbG9yIikpCmBgYAoKIyMjIEVzdGltYWNpw7NuIGRlIFByb2Nlc28gJE1BJApgYGB7cn0KbWEgPC0gYXJpbWEoWSwKICAgICAgICAgIG9yZGVyID0gYygwLDAsMiksICAgIyhwPTAsaT0wLHE9MSkgZXMgdW4gcHJvY2VzbyBNQSgxKQogICAgICAgICAgaW5jbHVkZS5tZWFuID0gRikgICAKbWEKYGBgCkVuIGxhIHByZXNlbnRhY2nDs24gZGUgbG9zIHJlc3VsdGFkb3MgZGUgbGEgZXN0aW1hY2nDs24gZGVsIG1vZGVsbywgZWwgdGVybWlubyBzLmUgc2lnbmlmaWNhIGVycm9yIGVzdGFuZGFyIHkgc2UgcmVmaWVyZSBhIHVuYSBlc3RpbWFjacOzbiBkZSBsYSBkZXN2aWFjacOzbiBlc3RhbmRhci4KJCRTRV97XGhhdHtZfX09XGZyYWN7c317XHNxcnR7bn19JCQKRG9uZGUgJHMkIGVzIGxhIGRlc3ZpYWNpw7NuIGVzdGFuZGFyICB5ICRuJCBlbCBuw7ptZXJvIGRlIG9ic2VydmFjaW9uZXMuCgoKCmBgYHtyfQpZLmZpdCA8LSBmaXR0ZWQobWEpCgpZLmZpdF9kZiA8LSBkYXRhLmZyYW1lKGZlY2hhID0gdGltZShYKSwKICAgICAgICAgICAgICAgICAgICB2YWxvciA9IGFzLnZlY3RvcihZLmZpdCkpCmdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IFkuZml0X2RmLCBhZXMoeCA9IGZlY2hhLCB5ID0gdmFsb3IsIGNvbG9yID0gIlNlcmllIEVzdGltYWRhIikpICsKICBnZW9tX2xpbmUoZGF0YSA9IFlfZGYsIGFlcyh4ID0gZmVjaGEsIHkgPSB2YWxvciwgY29sb3IgPSAiU2VyaWUgUmVhbCIpKSArCiAgbGFicyh0aXRsZSA9ICJTZXJpZSBSZWFsIHZzLiBTZXJpZSBFc3RpbWFkYSIsCiAgICAgICB4ID0gIkZlY2hhIiwKICAgICAgIHkgPSAiVmFsb3IiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlNlcmllIEVzdGltYWRhIiA9ICJibHVlIiwgIlNlcmllIFJlYWwiID0gInJlZCIpKQpgYGAKCiMjIyMgQ2FsY3VsbyBkZSBsb3MgcmVzaWR1YWxlcyBkZWwgbW9kZWxvIE1BOgoKRWwgbW9kZWxvIGFqdXN0YWRvIHBvciBtZWRpbyBkZSBsYSBmdW5jacOzbiBhcmltYSB5IGFzaWduYWRvIGEgbGEgdmFyaWFibGUgIm1hIiB0aWVuZW4gdmFyaW9zIHBhcmFtZXRyb3MgaW50ZXJub3MuIFBhcmEgcG9kZXIgdmVyIGN1YWwgZXMgbGEgZXN0cnVjdHVyYSBpbnRlcm5hIHkgc3UgY29tcG9zaWNpw7NuIHV0aWxpY2Ugc3RyKCApLiBMb3MgcmVzaWR1YWxlcyBkZWwgbW9kZWxvIHlhIGVzdGFuIGNhbGN1bGFkb3MgaW50ZXJuYW1lbnRlIHkgc2UgY2FsY3VsYW46CmBgYHtyfQpyZXNpZHVhbHMgPC0gbWEkcmVzaWR1YWxzCnJlc2lkdWFsc19kZiA8LSBkYXRhLmZyYW1lKGZlY2hhID0gdGltZShyZXNpZHVhbHMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICB2YWxvciA9IGFzLnZlY3RvcihyZXNpZHVhbHMpKQoKZ2dwbG90KHJlc2lkdWFsc19kZiwgYWVzKHggPSBmZWNoYSwgeSA9IHZhbG9yKSkrCiAgICAgICAgIGdlb21fbGluZSgpKwogICAgICAgICBnZW9tX3BvaW50KCkrCiAgICAgICAgIGxhYnModGl0bGUgPSAiR3LDoWZpY28gZGUgbG9zIHJlc2lkdW9zIGRlbCBwcm9jZXNvIE1BIiwKICAgICAgICAgICAgICB4bGFiKCJGZWNoYSIpLCB5bGFiKCJWYWxvciIpKQpgYGAKCiMjIyMgRGlhZ25vc3RpY28gZGUgbG9zIHJlc2lkdWFsZXMgTUE6CgpgYGB7cn0KIyBEaXN0cmlidWNpw7NuIGRlIGxvcyByZXNpZHVvcwpyZXNpZHVhbHMgPC0gbmEub21pdChyZXNpZHVhbHMpCmRlbnNpZGFkX3JlcyA8LWRlbnNpdHkocmVzaWR1YWxzKQpkZW5zaWRhZF9yZXNfZGYgPC0gZGF0YS5mcmFtZSh4ID0gZGVuc2lkYWRfcmVzJHgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBkZW5zaWRhZF9yZXMkeSkKCiMgRGlzdHJpYnVjacOzbiBkZSBsYSBub3JtYWwgY29uIDEwMDAgcHVudG9zCm5vcm1hbCA8LSBzZXEobWluKHJlc2lkdWFscyktMiwgbWF4KHJlc2lkdWFscykrMiwgbGVuZ3RoLm91dCA9IDEwMDApCm1lZGlhIDwtIG1lYW4ocmVzaWR1YWxzKQpkZXN2aWFjaW9uIDwtIHNkKHJlc2lkdWFscykKZGVuc2lkYWRfbm9ybWFsIDwtIGRub3JtKG5vcm1hbCwgbWVhbiA9IG1lZGlhLCBzZCA9IGRlc3ZpYWNpb24pCm5vcm1hbF9kZiA8LSBkYXRhLmZyYW1lKHggPSBub3JtYWwsIGRlbnNpZGFkID0gZGVuc2lkYWRfbm9ybWFsKQoKCiNHcsOhZmljbwpnZ3Bsb3QoZGVuc2lkYWRfcmVzX2RmLCBhZXMoeCA9IHgsIHkgPSB5KSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIiwgbGluZXR5cGUgPSAic29saWQiLCBzaXplID0gMSkgKwogIGdlb21fbGluZShkYXRhID0gbm9ybWFsX2RmLCBhZXMoeCA9IHgsIHkgPSBkZW5zaWRhZCksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKSArCiAgbGFicyh0aXRsZSA9ICJEZW5zaWRhZCBPYnNlcnZhY2lvbmVzIHZzLiBEZW5zaWRhZCBOb3JtYWwiLAogICAgICAgeCA9ICJWYWxvciIsCiAgICAgICB5ID0gIkRlbnNpZGFkIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJibHVlIiwgInJlZCIpKQpgYGAKCiMjIyMgUHJ1ZWJhIEFDRiB5IENvcnJlbG9ncmFtYSBkZSBsb3MgcmVzaWR1b3M6CmBgYHtyfQpwYXIobWFyID0gYyg1LCA1LCA0LCAyKSkKYWNmKHJlc2lkdWFscywgCiAgICBuYS5hY3Rpb24gPSBuYS5wYXNzLAogICAgeWxpbT1jKC0xLDEpLAogICAgbWFpbiA9ICJDb3JlbG9ncmFtYSBkZSBsb3MgUmVzaWR1b3MiKQpgYGAKCiMjIyMgUHJ1ZWJhIFBBQ0Y6CgpgYGB7cn0KcGFyKG1hciA9IGMoNSwgNSwgNCwgMikpCnBhY2YxIDwtIHBhY2YocmVzaWR1YWxzLAogICAgICAgICAgICAgbmEuYWN0aW9uID0gbmEucGFzcywKICAgICAgICAgICAgIHlsaW09YygtMSwxKSwKICAgICAgICAgICAgIG1haW4gPSAiUEFDRiBkZSBsb3MgcmVzaWR1b3MiKQpgYGAKCiMjIFByb2Nlc29zIGF1dG9ycmVncmVzaXZvcyBkZSBtZWRpYSBtb3ZpbCAkQVJNQSQKCkxvcyBtb2RlbG9zICRBUk1BKHAscSkkIHNvbiBtb2RlbG9zIGF1dG9ycmVncmVzaXZvcyBkZSBtZWRpYSBtb3ZpbCBzZSBjb21wb25lbiBkZSB1bmEgcGFydGUgQVIgeSBsYSBvdHJhIE1BLCBzaWd1ZW4gbGEgc2lndWllbnRlIGVjdWFjacOzbjoKClxiZWdpbnthbGlnbn0KWV97dH0mPVxwaGlfezB9K1xwaGlfezF9WV97dC0xfStcY2RvdHMrXHBoaV97cH1ZX3t0LXB9K1x2YXJlcHNpbG9uX3t0fStcdGhldGFfezF9XHZhcmVwc2lsb25fe3QtMX0rXGNkb3RzK1x0aGV0YV97cX1cdmFyZXBzaWxvbl97dC1xfSBcXCBcXAogICAgJj1ccGhpX3swfStcc3VtX3tpPTF9XntwfVxwaGlfe2l9WV97dC1pfStcc3VtX3tqPTF9XntxfVx0aGV0YV97an1cdmFyZXBzaWxvbl97dC1qfSArIFx2YXJlcHNpbG9uX3t0fVx0YWd7My4xfQpcZW5ke2FsaWdufQoKIyMjIFNpbXVsYWNpw7NuIGRlbCBwcm9jZXNvICRBUk1BJAoKYGBge3J9CnNldC5zZWVkKDEpCgpaIDwtIGFyaW1hLnNpbShuID0gNTAsICAgICAgICAgICAgICAgICAgICAgICAgICNuw7ptZXJvIGRlIG9ic2VydmFjaW9uZXMgc2ltdWxhZGFzCiAgICAgICAgICAgICAgIGxpc3QoYXIgPSBjKDAuODIsLTAuNCksICAgICAgICAgI3BhcsOhbWV0cm8gcGhpIGRlbCBtb2RlbG8gQVIKICAgICAgICAgICAgICAgICAgICBtYSA9IGMoLTAuMiwwLjI0KSksICAgICAgICAjcGFyw6FtZXRybyB0aGV0YSBkZWwgbW9kZWxvIE1BCiAgICAgICAgICAgICAgIGlubm92PXJub3JtKDUwLDAsMSkpICAgICAgICAgICAgI2Vycm9yIGFzb3NjaWFkbyBkaXN0cmlidWlkbyBub3JtYWxtZW50ZSAgICAgICAgICAgICAgICAgIApgYGAKCmBgYHtyfQpaX2RmPC1kYXRhLmZyYW1lKHRpbWUgPSBjKDE5NzA6MjAxOSksCiAgICAgICAgICAgICAgICAgdmFsdWUgPSBhcy52ZWN0b3IoWikpCgpnZ3Bsb3QoWl9kZixhZXMoeCA9IHRpbWUsCiAgICAgICAgICAgICAgIHkgPSB2YWx1ZSkpKwogIGdlb21fbGluZSgpKwogIGdlb21fcG9pbnQoKSsKICBsYWJzKHRpdGxlID0gIlNpbXVsYWNpw7NuIG1vZGVsbyBBUk1BIikKYGBgCgoKYGBge3J9CiNWYW1vcyBhIGFqdXN0YXIgY29uIHVuIG1vZGVsbyBBUk1BKDIsMikKCnBhcihtYXIgPSBjKDUsIDUsIDQsIDIpKQphY2YoWiwgCiAgICBuYS5hY3Rpb24gPSBuYS5wYXNzLAogICAgeWxpbT1jKC0xLDEpKQpgYGAKYGBge3J9ClouZml0IDwtIGFyaW1hKFosIG9yZGVyID0gYygyLDAsMiksCiAgICAgICAgICAgICAgIGluY2x1ZGUubWVhbiA9IEZBTFNFKQpaLmZpdApgYGAKYGBge3J9ClouZml0X2RmIDwtIGRhdGEuZnJhbWUodGltZSA9IGMoMTk3MDoyMDE5KSwKICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGFzLnZlY3RvcihmaXR0ZWQoWi5maXQpKSkKCmdncGxvdCgpICsKICBnZW9tX2xpbmUoZGF0YSA9IFouZml0X2RmLCBhZXMoeCA9IHRpbWUsIHkgPSB2YWx1ZSwgY29sb3IgPSAiU2VyaWUgRXN0aW1hZGEiKSkgKwogIGdlb21fbGluZShkYXRhID0gWl9kZiwgYWVzKHggPSB0aW1lLCB5ID0gdmFsdWUsIGNvbG9yID0gIlNlcmllIFJlYWwiKSkgKwogIGxhYnModGl0bGUgPSAiU2VyaWUgUmVhbCB2cy4gU2VyaWUgRXN0aW1hZGEiLAogICAgICAgeCA9ICJGZWNoYSIsCiAgICAgICB5ID0gIlZhbG9yIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJTZXJpZSBFc3RpbWFkYSIgPSAiYmx1ZSIsICJTZXJpZSBSZWFsIiA9ICJyZWQiKSkKYGBgCmBgYHtyfQpaLmZvciA8LSBwcmVkaWN0KFouZml0LG4uYWhlYWQ9MikKWi5mb3IKYGBgCmBgYHtyfQojQWN0dWFsaXphY2nDs24gZGUgbGEgc2VyaWU6CnByb25vc3RpY28gPC0gZGF0YS5mcmFtZShjKDIwMjAsMjAyMSksYXMudmVjdG9yKFouZm9yJHByZWQpKQpjb2xuYW1lcyhwcm9ub3N0aWNvKTwtY29sbmFtZXMoWi5maXRfZGYpClouZml0X2RmPC1yYmluZChaX2RmLHByb25vc3RpY28pCgpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBaLmZpdF9kZiwgYWVzKHggPSB0aW1lLCB5ID0gdmFsdWUsIGNvbG9yID0gIlByb25vc3RpY28iKSkgKwogIGdlb21fbGluZShkYXRhID0gWl9kZiwgYWVzKHggPSB0aW1lLCB5ID0gdmFsdWUsIGNvbG9yID0gIlNlcmllIFJlYWwiKSkgKwogIGxhYnModGl0bGUgPSAiU2VyaWUgUmVhbCB5IFByb27Ds3N0aWNvIiwKICAgICAgIHggPSAiRmVjaGEiLAogICAgICAgeSA9ICJWYWxvciIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUHJvbm9zdGljbyIgPSAiYmx1ZSIsICJTZXJpZSBSZWFsIiA9ICJyZWQiKSkKCmBgYAoKIyMjIERpZmVyZW5jaWFjacOzbiBkZSBsYSBzZXJpZSBkZSB0aWVtcG8KClBhcmEgdXRpbGl6YXIgZXN0YSBtZXRvZG9sb2fDrWEgcGFyYSBlbCBtb2RlbGFtaWVudG8geSBwb3N0ZXJpb3IgcHJvbsOzc3RpY28gZGUgc2VyaWVzIGRlIHRpZW1wbyBzZSBkZWJlIHZlcmlmaWNhciBsYSBlc3RhY2lvbmFyaWRhZCBkZSBsYSBzZXJpZS4gRXN0YSBzZSBwdWVkZSBkaWFnbm9zdGljYXIgbWVkaWFudGUgZWwgdGVzdCBkZSBEaWNrZXktRnVsbGVyLCBzaSBsYSBzZXJpZSByZXN1bHRhIG5vIGVzdGFjaW9uYXJpYSBzZSBkZWJlIGRpZmVyZW5jaWFyIGxhIHNlcmllIGhhc3RhIGFsY2FuemFyIGxhIGVzdGFjaW9uYXJpZWRhZC4KClNlYSAkWV97dH0kIHVuYSBzZXJpZSBkZSB0aWVtcG8sIHN1IGRpZmVyZW5jaWFjacOzbiBzaW1wbGUgZXN0YSBkYWRhIHBvcjoKJCRcRGVsdGEgWV97dH09WV97dH0tWV97dC0xfSQkCmBgYHtyfQojIFBydWViYSBEaWNrZXktRnVsbGVyIGRlIGxhIHNlcmllIG9yaWduaWFsCmFkZi50ZXN0KFkpCgojIyBFamVtcGxvIGRlIGRpZmVyZW5jaWFjacOzbiBzaW1wbGUKWS5kIDwtIGRpZmYoWSkgICMgU2VyaWUgWCBjb24gcHJlc2VuY2lhIGRlIHJhaXogVW5pdC4KYWRmLnRlc3QoWS5kKQpgYGAKTGEgc2VyaWUgZXJhIGVzdGFjaW9uYXJpYSBkZXNkZSBlbCBwcmljaXBpbyBwb3IgZXNvIGVsIHZhbG9yICRwJCBlbiBhbWJhcyBwcnVlYmFzIG5vIGNhbWJpYS4KCgoKCgoKIyMgUHJvY2VzbyBhdXRvcnJlZ3Jlc2l2byBpbnRlZ3JhZG8gZGUgbWVkaWEgbcOzdmlsICRBUklNQSQKCkVsIG1vZGVsbyBhdXRvcnJlZ3Jlc2l2byBpbnRlZ3JhZG8gZGUgbWVkaWEgbW92aWwgdXRpbGl6YSBkaWZlcmVuY2lhY2nDs24gZGUgbGEgc2VyaWUgeSByZWdyZXNpb25lcyBwYXJhIG1vZGVsYXIgbGEgc2VyaWUgZGUgdGllbXBvLCBzZSBjb25zaWRlcmEgcXVlIGVzIHVuIG1vZGVsbyBkaW5hbWljbyB5YSBxdWUgbG9zIGRhdG9zIGRlIHByZWRpY2Npb25lcyBkZXBlbmRlbiBkZSBjb21wb3J0YW1pZW50b3MgcGFzYWRvcyB5IG5vIGRlIHZhcmlhYmxlcyBleHRlcm5hcyBhIGxhIHNlcmllLgoKRWwgcHJvY2VzbyAkQVJJTUEocCxkLHEpJCBkb25kZSAkcCxkLHEkIHNvbiBuw7ptZXJvcyBlbnRlcm9zIG5vIG5lZ2F0aXZvcywgc2UgcHVlZGUgcmVwcmVzZW50YXIgbWF0ZW1hdGljYW1lbnRlIGNvbW86CgoKCiQkWV97dH09LShcRGVsdGFee2R9WV97dH0tWV97dH0pK1xwaGlfezB9K1xzdW1fe2k9MX1ee3B9XHBoaV97aX1cRGVsdGFee2R9WV97dC1pfStcc3VtX3tqPTF9XntxfVx0aGV0YV97an1cdmFyZXBzaWxvbl97dC1qfStcdmFyZXBzaWxvbl97dH0kJApEb25kZToKCiogJFxwaGlfezB9JCBlcyB1bmEgY29uc3RhbnRlCiogJGQkIGNvcnJlc3BvbmRlIGEgbGFzIGRpZmVyZW5jaWFzIG5lY2VzYXJpYXMgcGFyYSBnZW5lcmFyIHF1ZSBsYSBzZXJpZSBzZWEgZXN0YWNpb25hcmlhCiogJFxwaGlfezF9LC4uLixccGhpX3twfSQgc29uIGxvcyBwYXJhbWV0cm9zIGFzb2NpYWRvcyBhIGxhIHBhcnRlIGF1dG9ycmVncmVzaXZhIGRlbCBtb2RlbG8KKiAkXHRoZXRhX3sxfSwuLi4sXHRoZXRhX3txfSQgc29uIGxvcyBwYXJhbWV0cm9zIGFzb2NpYWRvcyBhIGxhIHBhcnRlIGRlIG1lZGlhcyBtb3ZpbGVzIGRlbCBtb2RlbG9zCiogJFx2YXJlcHNpbG9uX3t0fSQgZXMgZWwgdGVybWlubyBkZSBlcnJvci4KCgojIyMgU2ltdWxhY2nDs24gcHJvY2VzbyAkQVJJTUEkCgoKYGBge3J9CnNldC5zZWVkKDEpCgpXIDwtIGFyaW1hLnNpbShuID0gNTAsICAgICAgICAgICAgICAgICAgICAgICAgIzUwIG9ic2VydmFjaW9uZXMKICAgICAgICAgICAgICAgbGlzdChvcmRlciA9IGMoMSwxLDEpLCAgICAgICAgICNBUklNQSgxLDEsMSkgQVIoMSksIERpZigxKSwgTUEoMSkKICAgICAgICAgICAgICAgICAgICBhciA9IDAuODEyLCAgICAgICAgICAgICAgICNQaGktQVIKICAgICAgICAgICAgICAgICAgICBtYSA9IDAuMjE0KSkgICAgICAgICAgICAgICNUaGV0YS1NQQpoZWFkKFcpCgpXX2RmIDwtIGRhdGEuZnJhbWUodGltZSA9IGMoMTk3MDoyMDIwKSwKICAgICAgICAgICAgICAgICAgIHZhbHVlID0gYXMudmVjdG9yKFcpKQoKZ2dwbG90KFdfZGYsIGFlcyh4ID0gdGltZSwgeSA9IHZhbHVlKSkrCiAgZ2VvbV9saW5lKCkrCiAgZ2VvbV9wb2ludCgpKwogIGxhYnModGl0bGUgPSAiU2ltdWxhY2nDs24gcHJvY2VzbyBBUklNQSgxLDEsMSkiLCAKICAgICAgIHhsYWIoIkHDsW8iKSwgeWxhYigiVmFsb3IiKSkKYGBgCgojIyMgRXN0aW1hY2lvbiBtb2RlbG8gQVJJTUEKYGBge3J9ClcuZml0IDwtIGFyaW1hKFcsICAgICAgICAgICAgICAgICAgICAjIERhdG9zIGRlIGxhIHNlcmllCiAgICAgICAgICAgICAgIG9yZGVyID0gYygxLDEsMSksICAgICAjIFByb2Nlc28gdGlwbyBBUklNQSgxLDEsMSkgYXIoMSksIGRpZmYoMSksbWEoMSkKICAgICAgICAgICAgICAgaW5jbHVkZS5tZWFuID0gVCkgIApXLmZpdAoKVy5maXRfZGYgPC0gZGF0YS5mcmFtZSh0aW1lID0gV19kZiR0aW1lLAogICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gYXMudmVjdG9yKGZpdHRlZChXLmZpdCkpKQoKZ2dwbG90KCkgKwogIGdlb21fbGluZShkYXRhID0gVy5maXRfZGYsIGFlcyh4ID0gdGltZSwgeSA9IHZhbHVlLCBjb2xvciA9ICJTZXJpZSBFc3RpbWFkYSIpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBXX2RmLCBhZXMoeCA9IHRpbWUsIHkgPSB2YWx1ZSwgY29sb3IgPSAiU2VyaWUgUmVhbCIpKSArCiAgbGFicyh0aXRsZSA9ICJTZXJpZSBSZWFsIHZzLiBTZXJpZSBFc3RpbWFkYSIsCiAgICAgICB4ID0gIkZlY2hhIiwKICAgICAgIHkgPSAiVmFsb3IiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlNlcmllIEVzdGltYWRhIiA9ICJibHVlIiwgIlNlcmllIFJlYWwiID0gInJlZCIpKQpgYGAKIyMjIFByZWRpY2Npw7NuIGRlbCBtb2RlbG8gJEFyaW1hKDEsMSwxKSQKCmBgYHtyfQpXLmZvcjwtcHJlZGljdChXLmZpdCxuLmFoZWFkPTMpClcuZm9yCgpwcm9ub3N0aWNvIDwtIGRhdGEuZnJhbWUoYygyMDIxOjIwMjMpLAogICAgICAgICAgICAgICAgICAgICAgICAgYXMudmVjdG9yKFcuZm9yJHByZWQpKQoKY29sbmFtZXMocHJvbm9zdGljbykgPC0gY29sbmFtZXMoVy5maXRfZGYpClcuZml0X2RmIDwtIHJiaW5kKFcuZml0X2RmLHByb25vc3RpY28pCgpnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBXLmZpdF9kZiwgYWVzKHggPSB0aW1lLCB5ID0gdmFsdWUsIGNvbG9yID0gIlByb25vc3RpY28iKSkgKwogIGdlb21fbGluZShkYXRhID0gV19kZiwgYWVzKHggPSB0aW1lLCB5ID0gdmFsdWUsIGNvbG9yID0gIlNlcmllIFJlYWwiKSkgKwogIGxhYnModGl0bGUgPSAiU2VyaWUgUmVhbCB5IFByb27Ds3N0aWNvIiwKICAgICAgIHggPSAiRmVjaGEiLAogICAgICAgeSA9ICJWYWxvciIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiUHJvbm9zdGljbyIgPSAiYmx1ZSIsICJTZXJpZSBSZWFsIiA9ICJyZWQiKSkKYGBgCgoKPGJyPjxicj48YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+CjxwIHN0eWxlPSJ0ZXh0LWFsaWduOmNlbnRlcjsiPgoqQ3VpZGF0ZSBiYioKPC9wPgoKCg==