library(ggfortify)
library(forecast)
library(fpp2)
library(gridExtra)
library(seasonal)
library(TSA)
library(urca)
library(ggplot2)
Breve referencia a los datos, frecuencia, unidad de medida, fuente, etc.
La serie representa la producción de limones con una frecuencia mensual, la unidad de medida es en toneladas y los datos recopilados fueron obtenidos de la página de INEGI del año 2010 al 2016 (última actualización).
http://www.inegi.org.mx/
Graficar los datos, analizar patrones y observaciones atípicas. Apoye su análisis con una descomposición clásica.
base<-read.csv(file.choose("limones.csv"))
limones<-ts(base$limones,start = c(2010,1),frequency=12)
Preciolimon<-ts(base$Precio,start = c(2010,1),frequency=12)
View(base)
pl<-plot(limones,xlab="periodo",main="Producción de Limones")

Observamos que la serie presenta estacionalidad, y es completamente cíclica. Los comportamientos de la producción de limón son de manera atípica que se debe a diversos factores, el comportamiento en un año de la producción durante los primeros meses se observa en los cultivos ya que se preparan para que posteriormente los arboles den fruto, por lo que durante los primeros meses la producción, es la mas baja del año; otro de los factores del estiaje de la producción, es que el cítrico no se desarrolle con excelencia y los frutos no den jugo aunado con los problemas cada vez mas presentes de los cambios de temperatura, que afectan las cosechas y con ello directamente en el precio del producto y al sector alimentario.
Descomposición Clasica
limondesc<- decompose(limones, type='additive')
autoplot(limondesc)

Se realizó la descomposición clasica para observar los componentes de la serie (estacionalidad,tendencia y ciclo) por separado
Utilizar transformación Box-Cox / logaritmos para estabilizar la varianza.
Presentar grafica.
BoxCox.ar(limones)

En el caso de esta serie no es necesario aplicar logaritmos debido a que la serie muestra unicamente un comportamiento estacional.
Prueba Shapiro-Wilk
shapiro.test(rstudent(limones.lm))
Shapiro-Wilk normality test
data: rstudent(limones.lm)
W = 0.93868, p-value = 0.001626
En este caso el valo “p” < 0.5 por lo que podemos rechazar que ña distribuión sea de tipo normal.
Correlograma
autoplot(acf(rstudent(limones.lm),plot=F))

Se observa que las lineas horizontales representan los errores estandar las cuales se ven rebasadas notoriamente por los rezagos del modelo
En caso de estacionalidad de la serie de tiempo, aplicar diferencias estacionales.
Presentar gráfica.
ggtsdisplay(diff(limones,12),main="diferencia estacional")

ggtsdisplay(diff(diff(limones,12),main="Segunda Diferencia Estacional"))

difestacional<-(diff(diff(limones,12)))
Comprobamos que al aplicar una segunda diferencia estacional la serie se comporta de manera mas estable y los residuos permanecen dentro de la banda.
Usar prueba Dickey-Fuller para evaluar el orden de integración de la serie. Diferenciar hasta que la serie sea estacionaria.
Ho: Existe raíz unitaria Ha: No existe raíz unitaria
summary(ur.df(limones,type="trend",selectlags="AIC"))
###############################################
# 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
-1708080 -160783 99130 313299 680866
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.612e+05 1.556e+05 2.322 0.023335 *
z.lag.1 -4.271e-01 1.050e-01 -4.068 0.000129 ***
tt 2.398e+03 3.113e+03 0.770 0.443771
z.diff.lag 1.998e-01 1.224e-01 1.633 0.107267
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 521300 on 66 degrees of freedom
Multiple R-squared: 0.2012, Adjusted R-squared: 0.1648
F-statistic: 5.54 on 3 and 66 DF, p-value: 0.001875
Value of test-statistic is: -4.0676 5.6098 8.2969
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
summary(ur.df(limones,type="none",selectlags="AIC"))
###############################################
# Augmented Dickey-Fuller Test Unit Root Test #
###############################################
Test regression none
Call:
lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)
Residuals:
Min 1Q Median 3Q Max
-1914018 167553 274264 323151 674992
Coefficients:
Estimate Std. Error t value Pr(>|t|)
z.lag.1 -0.09093 0.05891 -1.543 0.127
z.diff.lag 0.03964 0.12436 0.319 0.751
Residual standard error: 565500 on 68 degrees of freedom
Multiple R-squared: 0.03406, Adjusted R-squared: 0.005648
F-statistic: 1.199 on 2 and 68 DF, p-value: 0.3078
Value of test-statistic is: -1.5434
Critical values for test statistics:
1pct 5pct 10pct
tau1 -2.6 -1.95 -1.61
adf.test(limones)
p-value smaller than printed p-value
Augmented Dickey-Fuller Test
data: limones
Dickey-Fuller = -5.3103, Lag order = 4, p-value = 0.01
alternative hypothesis: stationary
adf.test(difestacional)
p-value smaller than printed p-value
Augmented Dickey-Fuller Test
data: difestacional
Dickey-Fuller = -4.6259, Lag order = 3, p-value = 0.01
alternative hypothesis: stationary
El valor de P=0.01 en ambos casos, tanto en la serie original como en la diferenciada, por lo que se rechaza la hipotesis nula, por lo tanto no existe raíz unitaria en ambos modelos lo que indica que nuestra serie es completamente estacionaria.
Usar herramientas ACF,PACF,EACF y/o criterios de Akaike/Bayes para construir propuestas de modelos.
acf(difestacional)

pacf(difestacional)

eacf(difestacional)
AR/MA
0 1 2 3 4 5 6 7 8 9 10 11 12 13
0 x o o o o o o o o o o o o o
1 x o o o o o o o o o o o o o
2 x x o o o o o o o o o o o o
3 x o o o o o o o o o o o o o
4 x o o o o o o o o o o o o o
5 x o o o o o o o o o o o o o
6 o x o o x o o o o o o o x o
7 x o o o x o o o o o o o x o
De tal modo que proponemos tres modelos Arima
Ajuste1<-arima(difestacional,order=c(1,0,0))
checkresiduals(Ajuste1)
Ljung-Box test
data: Residuals from ARIMA(1,0,0) with non-zero mean
Q* = 14.568, df = 22, p-value = 0.8801
Model df: 2. Total lags used: 24

Ajuste2<-arima(difestacional,order=c(0,0,1))
checkresiduals(Ajuste2)
Ljung-Box test
data: Residuals from ARIMA(0,0,1) with non-zero mean
Q* = 16.233, df = 22, p-value = 0.8042
Model df: 2. Total lags used: 24

Ajuste3 <-arima(difestacional,order=c(1,1,1))
checkresiduals(Ajuste3)
Ljung-Box test
data: Residuals from ARIMA(1,1,1)
Q* = 13.948, df = 22, p-value = 0.9033
Model df: 2. Total lags used: 24

Usar la función auto.arima y compare sus resultados con el inciso anterior
auto<-auto.arima(difestacional,stepwise = F,approximation = F)
auto
Series: difestacional
ARIMA(1,0,1) with zero mean
Coefficients:
ar1 ma1
0.5528 -0.9621
s.e. 0.1257 0.0662
sigma^2 estimated as 4.191e+09: log likelihood=-737.03
AIC=1480.05 AICc=1480.49 BIC=1486.28
checkresiduals(auto)
Ljung-Box test
data: Residuals from ARIMA(1,0,1) with zero mean
Q* = 11.794, df = 22, p-value = 0.9615
Model df: 2. Total lags used: 24

Se observa un ligero pero significativo movimiento en el estadistico Q. Mientras que los valores de p solo muestran una pegueña variabilidad, pero se observa que existen valores mas pequeños que en el modelo auto.arima aunque mayores en el estadistico Q.
Presenta la ecuación final y describa
Ajuste1<-arima(difestacional,order=c(1,0,0))
Ajuste1
Call:
arima(x = difestacional, order = c(1, 0, 0))
Coefficients:
ar1 intercept
-0.2649 2723.892
s.e. 0.1253 7054.358
sigma^2 estimated as 4.664e+09: log likelihood = -740.51, aic = 1485.03
checkresiduals(Ajuste1)
Ljung-Box test
data: Residuals from ARIMA(1,0,0) with non-zero mean
Q* = 14.568, df = 22, p-value = 0.8801
Model df: 2. Total lags used: 24

Ajuste2<-arima(difestacional,order=c(0,0,1))
Ajuste2
Call:
arima(x = difestacional, order = c(0, 0, 1))
Coefficients:
ma1 intercept
-0.3770 2344.605
s.e. 0.1658 5539.689
sigma^2 estimated as 4.562e+09: log likelihood = -739.91, aic = 1483.81
checkresiduals(Ajuste2)
Ljung-Box test
data: Residuals from ARIMA(0,0,1) with non-zero mean
Q* = 16.233, df = 22, p-value = 0.8042
Model df: 2. Total lags used: 24

Presenta la ecuación final y describa
Ajuste4<-arima(difestacional,order=c(1,0,1))
Ajuste4
Call:
arima(x = difestacional, order = c(1, 0, 1))
Coefficients:
ar1 ma1 intercept
0.5246 -0.9998 1452.7242
s.e. 0.1148 0.0483 917.9811
sigma^2 estimated as 3.806e+09: log likelihood = -735.96, aic = 1477.91
checkresiduals(Ajuste4)
Ljung-Box test
data: Residuals from ARIMA(1,0,1) with non-zero mean
Q* = 12.944, df = 21, p-value = 0.9106
Model df: 3. Total lags used: 24

Al aplicar la función de auto.arima no pronostica el mejor modelo para la serie, se observa que el modelo sugerido por autoarima resulta ser mejor que los propouestos(Ajuste1, Ajuste2, Ajuste3),dado que el ACI es aun mas bajo, lo cual es mejor, por lo tanto ningun resago se sale de las bandas de los errores estandar, asi como los remanentes de los rezagos se encuentran dentro del parámetro, la prueba lJung Box nos indica que no hya correlación serial.Por lo tanto el mejor modelo es el auto arima.
Realizar el Pronóstico ARIMA para dos años
fit4<-Arima(limones,order=c(1,0,1))
fit4
Series: limones
ARIMA(1,0,1) with non-zero mean
Coefficients:
ar1 ma1 mean
0.5622 0.1907 1008492.8
s.e. 0.1375 0.1456 160935.6
sigma^2 estimated as 2.734e+11: log likelihood=-1048.98
AIC=2105.96 AICc=2106.55 BIC=2115.06
autoplot(forecast(fit4))

Utilizando métodos de pronósticos simples y/o suavizamiento exponencial generar un pronóstico para dos años. Elegir el método que presente la raíz del error medio al cuadrado más pequeño.
limonW<-window(limones,start=c(2010,1),end=c(2015,12))
autoplot(limonW)

Analizar un VAR, necesita incluir los puntos siguientes
a) Buscar otra variable (incluso más variables) y redactar la teoría que se encuentra detrás de la relación entre variables que propone.
El limón es uno de los citricos mas importante para la economía de México ya que se usa en hogares e industrias de alimentos. Recordando la ley de la oferta la cual nos indica que la oferta es directamente proporcional al precio (cuanto mas alto sea el precio del producto mas unidades se ofreceran a la venta) y por el contrario la ley de la demanda indica que la demanda es ivnersamente proporcional al precio (cuanto mas alto sea el precio, menos demandaran los consumidores).
Por lo tanto se reconoce que el precio esta directamente relacionado con la producción, cabe mencionar que existen fatores que intervienen en el precio de los citricos como por ejemplo la estacionalidad ya que cada año se da una ventana natural de menos producción de limón en los primeros meses del año, la afectación por las lluvias ya que los productores de los pricipales estados reportan lluvias, lo que tiene repercusiones en la floración y caida de los frutos.El retraso en la maduración ha provocado que se postergue la disponibilidad del producto y por ultimo las lluvias tardias generan entre otros efectos, la plaga conocida como antracnosis, la cual reduce temporalmente el rendimiento de la producción y como consecuencia existe un aumento en los precios del producto.
b) Evaluar la estacionalidad de la nueva variable.
autoplot(Preciolimon)

logprecio<-(log(Preciolimon))
difprecio<-(diff(log(Preciolimon,12)))
diffprecio<- (diff(diff(log(Preciolimon,12))))
autoplot(difprecio)

autoplot(diffprecio)

Se observa que el indice de precios por si solos tiene tendencia y muestra quiza un pcoo de estacionalidad pero encontramos que la varianza no es estable, por lo tanto se aplico do diferencias para estabilizar la serie.
Proponga el orden de Rezagos optimos para el VAR y presentar la estimación.
library(zoo)
Attaching package: <U+393C><U+3E31>zoo<U+393C><U+3E32>
The following objects are masked from <U+393C><U+3E31>package:base<U+393C><U+3E32>:
as.Date, as.Date.numeric
library(vars)
Loading required package: MASS
Attaching package: <U+393C><U+3E31>MASS<U+393C><U+3E32>
The following objects are masked from <U+393C><U+3E31>package:fma<U+393C><U+3E32>:
cement, housing, petrol
Loading required package: strucchange
Loading required package: sandwich
Loading required package: lmtest
library(dynlm)
library(lmtest)
limones2<- cbind.zoo(limones = difestacional, Precio = diffprecio)
View(limones2)
autoplot(limones2[,1:2],facet=TRUE)

VARselect(limones2, lag.max = 2, type="const")[["selection"]]
Error in VARselect(limones2, lag.max = 2, type = "const") :
NAs in y.
Evaluar la cointengración usando la metodología de Engle-Granger y Johansen
par(mfrow=c(1,2))
plot(limones, main="Producción de Limones")
plot(Preciolimon,main="Precio General")

ur.df(limones)
###############################################################
# Augmented Dickey-Fuller Test Unit Root / Cointegration Test #
###############################################################
The value of the test statistic is: -1.5434
ur.df(Preciolimon)
###############################################################
# Augmented Dickey-Fuller Test Unit Root / Cointegration Test #
###############################################################
The value of the test statistic is: 1.1175
Ho:La serie no es estacionaria
Según la prueba de cointegración, indica que el término del error es mayor a los criticos (y1=-1, y2=1) por lo tanto no son estacionarias
lp.reg <- dynlm(Preciolimon ~ L(Preciolimon) + limones + L(limones))
summary(lp.reg)
Time series regression with "ts" data:
Start = 2010(2), End = 2015(12)
Call:
dynlm(formula = Preciolimon ~ L(Preciolimon) + limones + L(limones))
Residuals:
Min 1Q Median 3Q Max
-15.2849 -3.2170 -0.4302 2.1711 19.4172
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.599e+01 6.406e+00 2.496 0.01501 *
L(Preciolimon) 8.754e-01 5.702e-02 15.354 < 2e-16 ***
limones 4.151e-06 1.540e-06 2.695 0.00889 **
L(limones) -5.031e-06 1.567e-06 -3.210 0.00204 **
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 6.628 on 67 degrees of freedom
Multiple R-squared: 0.7982, Adjusted R-squared: 0.7892
F-statistic: 88.36 on 3 and 67 DF, p-value: < 2.2e-16
dwtest(lp.reg)
Durbin-Watson test
data: lp.reg
DW = 2.7365, p-value = 0.9987
alternative hypothesis: true autocorrelation is greater than 0
Se observa que el valor p resulta ser significativo p>0.5 por lo tanto se rechaza la Ho aceptando la alterna por lo que las variables tienen verdadera autocorrelación entre ellas.
error <- residuals(lp.reg)
plot(error)
abline(h=0)

ur.df(error)
###############################################################
# Augmented Dickey-Fuller Test Unit Root / Cointegration Test #
###############################################################
The value of the test statistic is: -7.862
Ho:La serie no es estacionaria
Según la prueba de cointegración, indica que el término del error es mayor a los criticos p=-7.86 por lo tanto existe una relacion de cointegración.
limones3 <- ts.intersect(limones,Preciolimon, error)
dyn <- dynlm(d(Preciolimon) ~ L(error) + L(d(limones)) + L(d(Preciolimon)), data=data)
summary(dyn)
Time series regression with "zooreg" data:
Start = mar. 2010, End = dic. 2015
Call:
dynlm(formula = d(Preciolimon) ~ L(error) + L(d(limones)) + L(d(Preciolimon)),
data = data)
Residuals:
Min 1Q Median 3Q Max
-19.4016 -3.5103 -0.4213 3.3281 13.5639
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.782e-01 8.191e-01 0.584 0.5613
L(error) -9.723e-01 4.087e-01 -2.379 0.0203 *
L(d(limones)) -2.955e-06 2.282e-06 -1.295 0.1999
L(d(Preciolimon)) 4.366e-01 3.939e-01 1.108 0.2717
---
Signif. codes: 0 *** 0.001 ** 0.01 * 0.05 . 0.1 1
Residual standard error: 6.499 on 66 degrees of freedom
Multiple R-squared: 0.2484, Adjusted R-squared: 0.2142
F-statistic: 7.269 on 3 and 66 DF, p-value: 0.0002759
LS0tDQp0aXRsZTogIlByb2R1Y2Np824gZGUgTGltb25lcyINCmF1dGhvcjogIkZ1ZW50ZXMgUmFtaXJleiBWZXJvbmljYSB5IFJleWVzIERpYXogU3VzYW5hIEJlYXRyaXoiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCg0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShnZ2ZvcnRpZnkpDQpsaWJyYXJ5KGZvcmVjYXN0KQ0KbGlicmFyeShmcHAyKQ0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KHNlYXNvbmFsKQ0KbGlicmFyeShUU0EpDQpsaWJyYXJ5KHVyY2EpDQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KI0JyZXZlIHJlZmVyZW5jaWEgYSBsb3MgZGF0b3MsIGZyZWN1ZW5jaWEsIHVuaWRhZCBkZSBtZWRpZGEsIGZ1ZW50ZSwgZXRjLg0KDQojIyMjI0xhIHNlcmllIHJlcHJlc2VudGEgbGEgcHJvZHVjY2nzbiBkZSBsaW1vbmVzIGNvbiB1bmEgZnJlY3VlbmNpYSBtZW5zdWFsLCBsYSB1bmlkYWQgZGUgbWVkaWRhIGVzIGVuIHRvbmVsYWRhcyB5IGxvcyBkYXRvcyByZWNvcGlsYWRvcyBmdWVyb24gb2J0ZW5pZG9zIGRlIGxhIHDhZ2luYSBkZSBJTkVHSSBkZWwgYfFvIDIwMTAgYWwgMjAxNiAo+mx0aW1hIGFjdHVhbGl6YWNp824pLg0KaHR0cDovL3d3dy5pbmVnaS5vcmcubXgvIA0KDQojR3JhZmljYXIgbG9zIGRhdG9zLCBhbmFsaXphciBwYXRyb25lcyB5IG9ic2VydmFjaW9uZXMgYXTtcGljYXMuIEFwb3llIHN1IGFu4Wxpc2lzIGNvbiB1bmEgZGVzY29tcG9zaWNp824gY2zhc2ljYS4NCg0KYGBge3J9DQpiYXNlPC1yZWFkLmNzdihmaWxlLmNob29zZSgibGltb25lcy5jc3YiKSkNCmxpbW9uZXM8LXRzKGJhc2UkbGltb25lcyxzdGFydCA9IGMoMjAxMCwxKSxmcmVxdWVuY3k9MTIpDQpQcmVjaW9saW1vbjwtdHMoYmFzZSRQcmVjaW8sc3RhcnQgPSBjKDIwMTAsMSksZnJlcXVlbmN5PTEyKQ0KYGBgDQoNCmBgYHtyfQ0KVmlldyhiYXNlKQ0KYGBgDQoNCg0KYGBge3J9DQpwbDwtcGxvdChsaW1vbmVzLHhsYWI9InBlcmlvZG8iLG1haW49IlByb2R1Y2Np824gZGUgTGltb25lcyIpDQpgYGANCiMjIyMjT2JzZXJ2YW1vcyBxdWUgbGEgc2VyaWUgcHJlc2VudGEgZXN0YWNpb25hbGlkYWQsIHkgZXMgY29tcGxldGFtZW50ZSBj7WNsaWNhLiBMb3MgY29tcG9ydGFtaWVudG9zIGRlIGxhIHByb2R1Y2Np824gZGUgbGlt824gc29uIGRlIG1hbmVyYSBhdO1waWNhIHF1ZSBzZSBkZWJlIGEgZGl2ZXJzb3MgZmFjdG9yZXMsIGVsIGNvbXBvcnRhbWllbnRvIGVuIHVuIGHxbyBkZSBsYSBwcm9kdWNjafNuIGR1cmFudGUgbG9zIHByaW1lcm9zIG1lc2VzIHNlIG9ic2VydmEgZW4gbG9zIGN1bHRpdm9zIHlhIHF1ZSBzZSBwcmVwYXJhbiBwYXJhIHF1ZSBwb3N0ZXJpb3JtZW50ZSBsb3MgYXJib2xlcyBkZW4gZnJ1dG8sIHBvciBsbyBxdWUgZHVyYW50ZSBsb3MgcHJpbWVyb3MgbWVzZXMgbGEgcHJvZHVjY2nzbiwgZXMgbGEgbWFzIGJhamEgZGVsIGHxbzsgb3RybyBkZSBsb3MgZmFjdG9yZXMgZGVsIGVzdGlhamUgZGUgbGEgcHJvZHVjY2nzbiwgZXMgcXVlIGVsIGPtdHJpY28gbm8gc2UgZGVzYXJyb2xsZSBjb24gZXhjZWxlbmNpYSB5IGxvcyBmcnV0b3Mgbm8gZGVuIGp1Z28gYXVuYWRvIGNvbiBsb3MgcHJvYmxlbWFzIGNhZGEgdmV6IG1hcyBwcmVzZW50ZXMgZGUgbG9zIGNhbWJpb3MgZGUgdGVtcGVyYXR1cmEsIHF1ZSBhZmVjdGFuIGxhcyBjb3NlY2hhcyB5IGNvbiBlbGxvIGRpcmVjdGFtZW50ZSBlbiBlbCBwcmVjaW8gZGVsIHByb2R1Y3RvIHkgYWwgc2VjdG9yIGFsaW1lbnRhcmlvLg0KDQoNCiMjIyNEZXNjb21wb3NpY2nzbiBDbGFzaWNhDQpgYGB7cn0NCmxpbW9uZGVzYzwtIGRlY29tcG9zZShsaW1vbmVzLCB0eXBlPSdhZGRpdGl2ZScpDQphdXRvcGxvdChsaW1vbmRlc2MpDQpgYGANCg0KIyMjI1NlIHJlYWxpevMgbGEgZGVzY29tcG9zaWNp824gY2xhc2ljYSBwYXJhIG9ic2VydmFyIGxvcyBjb21wb25lbnRlcyBkZSBsYSBzZXJpZSAoZXN0YWNpb25hbGlkYWQsdGVuZGVuY2lhIHkgY2ljbG8pIHBvciBzZXBhcmFkbyANCg0KDQoNCiNVdGlsaXphciB0cmFuc2Zvcm1hY2nzbiBCb3gtQ294IC8gbG9nYXJpdG1vcyBwYXJhIGVzdGFiaWxpemFyIGxhIHZhcmlhbnphLg0KI1ByZXNlbnRhciBncmFmaWNhLg0KYGBge3J9DQpCb3hDb3guYXIobGltb25lcykNCmBgYA0KDQoNCiMjIyMjRW4gZWwgY2FzbyBkZSBlc3RhIHNlcmllIG5vIGVzIG5lY2VzYXJpbyBhcGxpY2FyIGxvZ2FyaXRtb3MgZGViaWRvIGEgcXVlIGxhIHNlcmllIG11ZXN0cmEgdW5pY2FtZW50ZSB1biBjb21wb3J0YW1pZW50byBlc3RhY2lvbmFsLg0KDQojTW9kZWxhciBsYSBzZXJpZSBkZSB0aWVtcG8gZWxlZ2lkYSBjb21vIGZ1bmNp824gZGUgdW5hIHRlbmRlbmNpYSwgdGVuZGVuY2lhIGN1YWRyYXRpY2EgeS9vIG1lZGlhcyBlc3RjaW9uYWxlcy5QcmVzZW50YSBlbCBEaWFnbm9zdGljbyBkZWwgbW9kZWxvIGVsZWdpZG8uDQoNCiMjIyNVc2FuZG8gbGEgc2VyaWUgZWxlZ2lkYSBjb21vIHZhcmlhYmxlIGRlcGVuZGllbnRlIHkgZWwgdGllbXBvIGNvbW8gaW5kZXBlbmRpZW50ZS4NCmBgYHtyfQ0KbGltb25lcy5sbTwtbG0obGltb25lcyB+IHRpbWUobGltb25lcykpDQpzdW1tYXJ5KGxpbW9uZXMubG0pDQpgYGANCg0KIyMjI0dyYWZpY2Ftb3MgDQpgYGB7cn0NCmdncGxvdChsaW1vbmVzLCBhZXMoeT1saW1vbmVzLCB4PXRpbWUobGltb25lcykpKSArDQogIGdlb21fcG9pbnQoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpDQpgYGANCiMjIyMjT2JzZXJ2YW1vcyBxdWUgbG9zIHJlc2lkdW9zIHRpZW5kZW4gYSBhbGVqYXJzZSBkZWwgY29tcG9uZW50ZSBkZSByZWZlcmVuY2lhIGxvIHF1ZSBkZXRlcm1pbmEgcXVlIGVsIG1vZGVsbyBubyBlcyBlbCBpbmRpY2FkbywgcHVlZGUgZGViZXJzZSBlc3RlIGNvbXBvcnRhbWllbnRvIGRlIGxvcyByZXNpZHVvcyBhIHF1ZSBkdXJhbnRlIGxvcyBwcmltZXJvcyBtZXNlcyBkZWwgYfFvIGxhIHByb2R1Y2Np824gZXMgY2FzaSBudWxhDQoNCiMjIyNFdmFsdWFjafNuIGRlbCBNb2RlbG8NCmBgYHtyfQ0KYXV0b3Bsb3QobGltb25lcy5sbSwgd2hpY2ggPSAxOjYsIG5jb2wgPSAyLCBsYWJlbC5zaXplID0gMykNCmBgYA0KIyMjIyNMYSBkaXN0YW5jaWEgZGUgY29vayByZXByZXNlbnRhIGV2ZW50b3Mgbm8gY29udHJvbGFkb3MsIHRhbGVzIGNvbW8gbGEgZXN0YWNpb25hbGlkYWQgeWEgcXVlIGNhZGEgYfFvIHNlIGRhIHVuYSB2ZW50YW5hIG5hdHVyYWwgZGUgbWVub3MgcHJvZHVjY2nzbiBkZSBsaW3zbiBlbiBsb3MgcHJpbWVyb3MgbWVzZXMgZGVsIGHxbywgbGEgYWZlY3RhY2nzbiBwb3IgbGFzIGxsdXZpYXMgeWEgcXVlIGxvcyBwcm9kdWN0b3JlcyBkZSBsb3MgcHJpY2lwYWxlcyBlc3RhZG9zIHJlcG9ydGFuIGxsdXZpYXMsIGxvIHF1ZSB0aWVuZSByZXBlcmN1c2lvbmVzIGVuIGxhIGZsb3JhY2nzbiB5IGNhaWRhIGRlIGxvcyBmcnV0b3MuRWwgcmV0cmFzbyBlbiBsYSBtYWR1cmFjafNuIGhhIHByb3ZvY2FkbyBxdWUgc2UgcG9zdGVyZ3VlIGxhIGRpc3BvbmliaWxpZGFkIGRlbCBwcm9kdWN0byB5IHBvciB1bHRpbW8gbGFzIGxsdXZpYXMgdGFyZGlhcyBnZW5lcmFuIGVudHJlIG90cm9zIGVmZWN0b3MsIGxhIHBsYWdhIGNvbm9jaWRhIGNvbW8gYW50cmFjbm9zaXMsIGxhIGN1YWwgcmVkdWNlIHRlbXBvcmFsbWVudGUgZWwgcmVuZGltaWVudG8gZGUgbGEgcHJvZHVjY2nzbi4NCiMjIyNFbCBncmFmaWNvIHF1YW50aWwtcXVhbnRpbCBub3MgZGEgdW5hIHJlZmVyZW5jaWEgY29uIHJlc3BlY3RvIGEgbGEgbm9ybWFsaWRhZCBkZSBudWVzdHJhIHNlcmllOyBzZSBvYnNlcnZhIHVuYSBhbHRhIHJlbGFjafNuIGRlIGxvcyBxdWFudGlsZXMgZGUgbG9zIGRhdG9zIHJlYWxlcyBjb24gbG9zIGNhbGN1bGFkb3MuIFBvciB1bHRpbW8gZW4gbGEgcHJpbWVyIGdy4WZpY2Egc2Ugb2JzZXJ2YSBxdWUgbG9zIHJlc2lkdW9zIGNhc2kgc2UgYWp1c3RhbiBhbCBwYXJhbWV0cm8uDQoNCiNQcnVlYmEgU2hhcGlyby1XaWxrDQpgYGB7cn0NCnNoYXBpcm8udGVzdChyc3R1ZGVudChsaW1vbmVzLmxtKSkNCmBgYA0KIyMjI0VuIGVzdGUgY2FzbyBlbCB2YWxvICJwIiA8IDAuNSBwb3IgbG8gcXVlIHBvZGVtb3MgcmVjaGF6YXIgcXVlIPFhIGRpc3RyaWJ1afNuIHNlYSBkZSB0aXBvIG5vcm1hbC4NCg0KI0NvcnJlbG9ncmFtYQ0KYGBge3J9DQphdXRvcGxvdChhY2YocnN0dWRlbnQobGltb25lcy5sbSkscGxvdD1GKSkNCmBgYA0KIyMjI1NlIG9ic2VydmEgcXVlIGxhcyBsaW5lYXMgaG9yaXpvbnRhbGVzIHJlcHJlc2VudGFuIGxvcyBlcnJvcmVzIGVzdGFuZGFyIGxhcyBjdWFsZXMgc2UgdmVuIHJlYmFzYWRhcyBub3RvcmlhbWVudGUgcG9yIGxvcyByZXphZ29zIGRlbCBtb2RlbG8NCg0KIyNFbiBjYXNvIGRlIGVzdGFjaW9uYWxpZGFkIGRlIGxhIHNlcmllIGRlIHRpZW1wbywgYXBsaWNhciBkaWZlcmVuY2lhcyBlc3RhY2lvbmFsZXMuDQojI1ByZXNlbnRhciBncuFmaWNhLg0KDQpgYGB7cn0NCmdndHNkaXNwbGF5KGRpZmYobGltb25lcywxMiksbWFpbj0iZGlmZXJlbmNpYSBlc3RhY2lvbmFsIikNCmBgYA0KYGBge3J9DQpnZ3RzZGlzcGxheShkaWZmKGRpZmYobGltb25lcywxMiksbWFpbj0iU2VndW5kYSBEaWZlcmVuY2lhIEVzdGFjaW9uYWwiKSkNCmRpZmVzdGFjaW9uYWw8LShkaWZmKGRpZmYobGltb25lcywxMikpKQ0KYGBgDQojIyMjI0NvbXByb2JhbW9zIHF1ZSBhbCBhcGxpY2FyIHVuYSBzZWd1bmRhIGRpZmVyZW5jaWEgZXN0YWNpb25hbCBsYSBzZXJpZSBzZSBjb21wb3J0YSBkZSBtYW5lcmEgbWFzIGVzdGFibGUgeSBsb3MgcmVzaWR1b3MgcGVybWFuZWNlbiBkZW50cm8gZGUgbGEgYmFuZGEuDQoNCiNVc2FyIHBydWViYSBEaWNrZXktRnVsbGVyIHBhcmEgZXZhbHVhciBlbCBvcmRlbiBkZSBpbnRlZ3JhY2nzbiBkZSBsYSBzZXJpZS4gRGlmZXJlbmNpYXIgaGFzdGEgcXVlIGxhIHNlcmllIHNlYSBlc3RhY2lvbmFyaWEuDQoNCkhvOiBFeGlzdGUgcmHteiB1bml0YXJpYQ0KSGE6IE5vIGV4aXN0ZSByYe16IHVuaXRhcmlhIA0KDQpgYGB7cn0NCnN1bW1hcnkodXIuZGYobGltb25lcyx0eXBlPSJ0cmVuZCIsc2VsZWN0bGFncz0iQUlDIikpDQpzdW1tYXJ5KHVyLmRmKGxpbW9uZXMsdHlwZT0ibm9uZSIsc2VsZWN0bGFncz0iQUlDIikpDQoNCmFkZi50ZXN0KGxpbW9uZXMpDQphZGYudGVzdChkaWZlc3RhY2lvbmFsKQ0KYGBgDQoNCiMjIyMgRWwgdmFsb3IgZGUgUD0wLjAxIGVuIGFtYm9zIGNhc29zLCB0YW50byBlbiBsYSBzZXJpZSBvcmlnaW5hbCBjb21vIGVuIGxhIGRpZmVyZW5jaWFkYSwgcG9yIGxvIHF1ZSBzZSByZWNoYXphIGxhIGhpcG90ZXNpcyBudWxhLCBwb3IgbG8gdGFudG8gbm8gZXhpc3RlIHJh7XogdW5pdGFyaWEgZW4gYW1ib3MgbW9kZWxvcyBsbyBxdWUgaW5kaWNhIHF1ZSBudWVzdHJhIHNlcmllIGVzIGNvbXBsZXRhbWVudGUgZXN0YWNpb25hcmlhLg0KDQoNCiNVc2FyIGhlcnJhbWllbnRhcyBBQ0YsUEFDRixFQUNGIHkvbyBjcml0ZXJpb3MgZGUgQWthaWtlL0JheWVzIHBhcmEgY29uc3RydWlyIHByb3B1ZXN0YXMgZGUgbW9kZWxvcy4NCg0KYGBge3J9DQphY2YoZGlmZXN0YWNpb25hbCkgDQpwYWNmKGRpZmVzdGFjaW9uYWwpDQplYWNmKGRpZmVzdGFjaW9uYWwpDQpgYGANCg0KIyMjIyNEZSB0YWwgbW9kbyBxdWUgcHJvcG9uZW1vcyB0cmVzIG1vZGVsb3MgQXJpbWEgDQoNCg0KYGBge3J9DQpBanVzdGUxPC1hcmltYShkaWZlc3RhY2lvbmFsLG9yZGVyPWMoMSwwLDApKQ0KY2hlY2tyZXNpZHVhbHMoQWp1c3RlMSkNCg0KQWp1c3RlMjwtYXJpbWEoZGlmZXN0YWNpb25hbCxvcmRlcj1jKDAsMCwxKSkNCmNoZWNrcmVzaWR1YWxzKEFqdXN0ZTIpDQoNCkFqdXN0ZTMgPC1hcmltYShkaWZlc3RhY2lvbmFsLG9yZGVyPWMoMSwxLDEpKQ0KY2hlY2tyZXNpZHVhbHMoQWp1c3RlMykNCmBgYA0KI1VzYXIgbGEgZnVuY2nzbiBhdXRvLmFyaW1hIHkgY29tcGFyZSBzdXMgcmVzdWx0YWRvcyBjb24gZWwgaW5jaXNvIGFudGVyaW9yIA0KDQpgYGB7cn0NCmF1dG88LWF1dG8uYXJpbWEoZGlmZXN0YWNpb25hbCxzdGVwd2lzZSA9IEYsYXBwcm94aW1hdGlvbiA9IEYpDQphdXRvDQpjaGVja3Jlc2lkdWFscyhhdXRvKQ0KYGBgDQojIyMjI1NlIG9ic2VydmEgdW4gbGlnZXJvIHBlcm8gc2lnbmlmaWNhdGl2byBtb3ZpbWllbnRvIGVuIGVsIGVzdGFkaXN0aWNvIFEuIE1pZW50cmFzIHF1ZSBsb3MgdmFsb3JlcyBkZSBwIHNvbG8gbXVlc3RyYW4gdW5hIHBlZ3Vl8WEgdmFyaWFiaWxpZGFkLCBwZXJvIHNlIG9ic2VydmEgcXVlIGV4aXN0ZW4gdmFsb3JlcyBtYXMgcGVxdWXxb3MgcXVlIGVuIGVsIG1vZGVsbyBhdXRvLmFyaW1hIGF1bnF1ZSBtYXlvcmVzIGVuIGVsIGVzdGFkaXN0aWNvIFEuDQoNCiNQcmVzZW50YSBsYSBlY3VhY2nzbiBmaW5hbCB5IGRlc2NyaWJhDQoNCmBgYHtyfQ0KQWp1c3RlMTwtYXJpbWEoZGlmZXN0YWNpb25hbCxvcmRlcj1jKDEsMCwwKSkNCkFqdXN0ZTENCmNoZWNrcmVzaWR1YWxzKEFqdXN0ZTEpDQpgYGANCg0KYGBge3J9DQpBanVzdGUyPC1hcmltYShkaWZlc3RhY2lvbmFsLG9yZGVyPWMoMCwwLDEpKQ0KQWp1c3RlMg0KY2hlY2tyZXNpZHVhbHMoQWp1c3RlMikNCmBgYA0KI1ByZXNlbnRhIGxhIGVjdWFjafNuIGZpbmFsIHkgZGVzY3JpYmENCg0KYGBge3J9DQpBanVzdGU0PC1hcmltYShkaWZlc3RhY2lvbmFsLG9yZGVyPWMoMSwwLDEpKQ0KQWp1c3RlNA0KY2hlY2tyZXNpZHVhbHMoQWp1c3RlNCkNCmBgYA0KIyMjIyNBbCBhcGxpY2FyIGxhIGZ1bmNp824gZGUgYXV0by5hcmltYSBubyBwcm9ub3N0aWNhIGVsIG1lam9yIG1vZGVsbyBwYXJhIGxhIHNlcmllLCBzZSBvYnNlcnZhIHF1ZSBlbCBtb2RlbG8gc3VnZXJpZG8gcG9yIGF1dG9hcmltYSByZXN1bHRhIHNlciBtZWpvciBxdWUgbG9zIHByb3BvdWVzdG9zKEFqdXN0ZTEsIEFqdXN0ZTIsIEFqdXN0ZTMpLGRhZG8gcXVlIGVsIEFDSSBlcyBhdW4gbWFzIGJham8sIGxvIGN1YWwgZXMgbWVqb3IsIHBvciBsbyB0YW50byBuaW5ndW4gcmVzYWdvIHNlIHNhbGUgZGUgbGFzIGJhbmRhcyBkZSBsb3MgZXJyb3JlcyBlc3RhbmRhciwgYXNpIGNvbW8gbG9zIHJlbWFuZW50ZXMgZGUgbG9zIHJlemFnb3Mgc2UgZW5jdWVudHJhbiBkZW50cm8gZGVsIHBhcuFtZXRybywgbGEgcHJ1ZWJhIGxKdW5nIEJveCBub3MgaW5kaWNhIHF1ZSBubyBoeWEgY29ycmVsYWNp824gc2VyaWFsLlBvciBsbyB0YW50byBlbCBtZWpvciBtb2RlbG8gZXMgZWwgYXV0byBhcmltYS4gDQoNCiNSZWFsaXphciBlbCBQcm9u83N0aWNvIEFSSU1BIHBhcmEgZG9zIGHxb3MgDQpgYGB7cn0NCmdldHJtc2UgPC0gZnVuY3Rpb24oeCxoLC4uLikgDQp7IA0KICB0cmFpbi5lbmQgPC0gdGltZSh4KVtsZW5ndGgoeCktaF0gDQogIHRlc3Quc3RhcnQgPC0gdGltZSh4KVtsZW5ndGgoeCktaCsxXSANCiAgdHJhaW4gPC0gd2luZG93KHgsZW5kPXRyYWluLmVuZCkNCiAgdGVzdCA8LSB3aW5kb3coeCxzdGFydD10ZXN0LnN0YXJ0KQ0KICBmaXQgPC0gQXJpbWEodHJhaW4sLi4uKSANCiAgZmMgPC0gZm9yZWNhc3QoZml0LGg9aCkNCiAgcmV0dXJuKGFjY3VyYWN5KGZjLHRlc3QpWzIsIlJNU0UiXSkgDQp9IA0KDQpnZXRybXNlKGRpZmVzdGFjaW9uYWwsaD0yNCxvcmRlcj1jKDEsMCwwKSkNCmdldHJtc2UoZGlmZXN0YWNpb25hbCxoPTI0LG9yZGVyPWMoMCwwLDEpKQ0KZ2V0cm1zZShkaWZlc3RhY2lvbmFsLGg9MjQsb3JkZXI9YygxLDEsMSkpDQpnZXRybXNlKGRpZmVzdGFjaW9uYWwsaD0yNCxvcmRlcj1jKDEsMCwxKSkNCmdldHJtc2UoZGlmZXN0YWNpb25hbCxoPTI0LG9yZGVyPWMoMiwwLDApKQ0KZ2V0cm1zZShkaWZlc3RhY2lvbmFsLGg9MjQsb3JkZXI9YygwLDAsMikpDQpnZXRybXNlKGRpZmVzdGFjaW9uYWwsaD0yNCxvcmRlcj1jKDIsMSwxKSkNCg0KYGBgDQoNCmBgYHtyfQ0KZml0NDwtQXJpbWEobGltb25lcyxvcmRlcj1jKDEsMCwxKSkNCmZpdDQNCmF1dG9wbG90KGZvcmVjYXN0KGZpdDQpKQ0KYGBgDQoNCiNVdGlsaXphbmRvIG3pdG9kb3MgZGUgcHJvbvNzdGljb3Mgc2ltcGxlcyB5L28gc3Vhdml6YW1pZW50byBleHBvbmVuY2lhbCBnZW5lcmFyIHVuIHByb27zc3RpY28gcGFyYSBkb3MgYfFvcy4gRWxlZ2lyIGVsIG3pdG9kbyBxdWUgcHJlc2VudGUgbGEgcmHteiBkZWwgZXJyb3IgbWVkaW8gYWwgY3VhZHJhZG8gbeFzIHBlcXVl8W8uDQoNCmBgYHtyfQ0KbGltb25XPC13aW5kb3cobGltb25lcyxzdGFydD1jKDIwMTAsMSksZW5kPWMoMjAxNSwxMikpDQphdXRvcGxvdChsaW1vblcpDQpgYGANCg0KI0x1ZWdvIGRlIGhhYmVyIHJlYWxpemFkbyBlbCByZWNvcnRlIGRlIG51ZXN0cmEgc2VyaWUsIHByb2NlZGVtb3MgYSByZWFsaXphciBlbCBwcm9ub3N0aWNvIHBhcmEgbG9zIGRvcyBh8W9zIHNpZ3VpZW50ZXMgbWVkaWFudGUgZWwgdXNvIGRlIGxvcyBtZXRvZG9zIHlhIGFudGVyaW9ybWVudGUgbWVuY2lvbmFkb3MuDQoNCmBgYHtyfQ0KYXV0b3Bsb3QobGltb25XKSArIA0KICBmb3JlY2FzdDo6YXV0b2xheWVyKG1lYW5mKGxpbW9uVywgaD0yNCksIFBJPUZBTFNFLCBzZXJpZXM9Ik1lYW4iKSArIA0KICBmb3JlY2FzdDo6YXV0b2xheWVyKG5haXZlKGxpbW9uVywgaD0yNCksIFBJPUZBTFNFLCBzZXJpZXM9Ik5h73ZlIikgKyANCiAgZm9yZWNhc3Q6OmF1dG9sYXllcihzbmFpdmUobGltb25XLCBoPTI0KSwgUEk9RkFMU0UsIHNlcmllcz0iU2Vhc29uYWwgbmHvdmUiKSArIA0KICBnZ3RpdGxlKCJQcm9ub3N0aWNvIGRlIFByb2R1Y2Np824gZGUgTGltb25lcyIpICsgDQogIHhsYWIoIkHxbyIpICsgeWxhYigiUHJvZHVjY2nzbiBkZSBMaW1vbmVzIikgKyANCiAgZ3VpZGVzKGNvbG91cj1ndWlkZV9sZWdlbmQodGl0bGU9IlRpcG8gZGUgUHJvbm9zdGljbyIpKQ0KYGBgDQoNCiMjIyMjRGFkbyBxdWUgbGEgc2VyaWUgZGUgcHJvZHVjY2nzbiBkZSBsaW1vbmVzIGVzIGNvbXBsZXRhbWVudGUgZXN0YWNpb25hbCB5IGNvbXBhcmFuZG8gZWwgcHJvbm9zdGljbyBkZSBsb3MgZG9zIGHxb3MsIHNlIGNvbmNsdXllIHF1ZSBlbCBtZXRvZG8gZGUgbmFpdmUgZXN0YWNpb25hbCBwcmVzZW50YSB1biBjb21wb3J0YW1pZW50byBtYXMgbG9naWNvIHkgcmF6b25hYmxlIHBhcmEgbG9zIHNpZ3VpZW50ZXMgYfFvcy4NCg0KI0FuYWxpemFyIHVuIFZBUiwgbmVjZXNpdGEgaW5jbHVpciBsb3MgcHVudG9zIHNpZ3VpZW50ZXMNCg0KIyNhKSBCdXNjYXIgb3RyYSB2YXJpYWJsZSAoaW5jbHVzbyBt4XMgdmFyaWFibGVzKSB5IHJlZGFjdGFyIGxhIHRlb3LtYSBxdWUgc2UgZW5jdWVudHJhIGRldHLhcyAgIGRlIGxhIHJlbGFjafNuIGVudHJlIHZhcmlhYmxlcyBxdWUgcHJvcG9uZS4NCg0KIyMjIyNFbCBsaW3zbiBlcyB1bm8gZGUgbG9zIGNpdHJpY29zIG1hcyBpbXBvcnRhbnRlIHBhcmEgbGEgZWNvbm9t7WEgZGUgTel4aWNvIHlhIHF1ZSBzZSB1c2EgZW4gaG9nYXJlcyBlIGluZHVzdHJpYXMgZGUgYWxpbWVudG9zLiBSZWNvcmRhbmRvIGxhIGxleSBkZSBsYSBvZmVydGEgbGEgY3VhbCBub3MgaW5kaWNhIHF1ZSBsYSBvZmVydGEgZXMgZGlyZWN0YW1lbnRlIHByb3BvcmNpb25hbCBhbCBwcmVjaW8gKGN1YW50byBtYXMgYWx0byBzZWEgZWwgcHJlY2lvIGRlbCBwcm9kdWN0byBtYXMgdW5pZGFkZXMgc2Ugb2ZyZWNlcmFuIGEgbGEgdmVudGEpIHkgcG9yIGVsIGNvbnRyYXJpbyBsYSBsZXkgZGUgbGEgZGVtYW5kYSBpbmRpY2EgcXVlIGxhIGRlbWFuZGEgZXMgaXZuZXJzYW1lbnRlIHByb3BvcmNpb25hbCBhbCBwcmVjaW8gKGN1YW50byBtYXMgYWx0byBzZWEgZWwgcHJlY2lvLCBtZW5vcyBkZW1hbmRhcmFuIGxvcyBjb25zdW1pZG9yZXMpLg0KIyMjIyNQb3IgbG8gdGFudG8gc2UgcmVjb25vY2UgcXVlIGVsIHByZWNpbyBlc3RhIGRpcmVjdGFtZW50ZSByZWxhY2lvbmFkbyBjb24gbGEgcHJvZHVjY2nzbiwgY2FiZSBtZW5jaW9uYXIgcXVlIGV4aXN0ZW4gZmF0b3JlcyBxdWUgaW50ZXJ2aWVuZW4gZW4gZWwgcHJlY2lvIGRlIGxvcyBjaXRyaWNvcyBjb21vIHBvciBlamVtcGxvIGxhIGVzdGFjaW9uYWxpZGFkIHlhIHF1ZSBjYWRhIGHxbyBzZSBkYSB1bmEgdmVudGFuYSBuYXR1cmFsIGRlIG1lbm9zIHByb2R1Y2Np824gZGUgbGlt824gZW4gbG9zIHByaW1lcm9zIG1lc2VzIGRlbCBh8W8sIGxhIGFmZWN0YWNp824gcG9yIGxhcyBsbHV2aWFzIHlhIHF1ZSBsb3MgcHJvZHVjdG9yZXMgZGUgbG9zIHByaWNpcGFsZXMgZXN0YWRvcyByZXBvcnRhbiBsbHV2aWFzLCBsbyBxdWUgdGllbmUgcmVwZXJjdXNpb25lcyBlbiBsYSBmbG9yYWNp824geSBjYWlkYSBkZSBsb3MgZnJ1dG9zLkVsIHJldHJhc28gZW4gbGEgbWFkdXJhY2nzbiBoYSBwcm92b2NhZG8gcXVlIHNlIHBvc3Rlcmd1ZSBsYSBkaXNwb25pYmlsaWRhZCBkZWwgcHJvZHVjdG8geSBwb3IgdWx0aW1vIGxhcyBsbHV2aWFzIHRhcmRpYXMgZ2VuZXJhbiBlbnRyZSBvdHJvcyBlZmVjdG9zLCBsYSBwbGFnYSBjb25vY2lkYSBjb21vIGFudHJhY25vc2lzLCBsYSBjdWFsIHJlZHVjZSB0ZW1wb3JhbG1lbnRlIGVsIHJlbmRpbWllbnRvIGRlIGxhIHByb2R1Y2Np824geSBjb21vIGNvbnNlY3VlbmNpYSBleGlzdGUgdW4gYXVtZW50byBlbiBsb3MgcHJlY2lvcyBkZWwgcHJvZHVjdG8uDQoNCiMjYikgRXZhbHVhciBsYSBlc3RhY2lvbmFsaWRhZCBkZSBsYSBudWV2YSB2YXJpYWJsZS4NCg0KYGBge3J9DQphdXRvcGxvdChQcmVjaW9saW1vbikNCmxvZ3ByZWNpbzwtKGxvZyhQcmVjaW9saW1vbikpDQpkaWZwcmVjaW88LShkaWZmKGxvZyhQcmVjaW9saW1vbiwxMikpKQ0KZGlmZnByZWNpbzwtIChkaWZmKGRpZmYobG9nKFByZWNpb2xpbW9uLDEyKSkpKQ0KYXV0b3Bsb3QoZGlmcHJlY2lvKQ0KYXV0b3Bsb3QoZGlmZnByZWNpbykNCmBgYA0KIyMjIyNTZSBvYnNlcnZhIHF1ZSBlbCBpbmRpY2UgZGUgcHJlY2lvcyBwb3Igc2kgc29sb3MgdGllbmUgdGVuZGVuY2lhIHkgbXVlc3RyYSBxdWl6YSB1biBwY29vIGRlIGVzdGFjaW9uYWxpZGFkIHBlcm8gZW5jb250cmFtb3MgcXVlIGxhIHZhcmlhbnphIG5vIGVzIGVzdGFibGUsIHBvciBsbyB0YW50byBzZSBhcGxpY28gZG8gZGlmZXJlbmNpYXMgcGFyYSBlc3RhYmlsaXphciBsYSBzZXJpZS4NCg0KI1Byb3BvbmdhIGVsIG9yZGVuIGRlIFJlemFnb3Mgb3B0aW1vcyBwYXJhIGVsIFZBUiB5IHByZXNlbnRhciBsYSBlc3RpbWFjafNuLg0KDQpgYGB7cn0NCmxpYnJhcnkoem9vKQ0KbGlicmFyeSh2YXJzKQ0KbGlicmFyeShkeW5sbSkNCmxpYnJhcnkobG10ZXN0KQ0KYGBgDQoNCg0KYGBge3J9DQpsaW1vbmVzMjwtIGNiaW5kLnpvbyhsaW1vbmVzID0gZGlmZXN0YWNpb25hbCwgUHJlY2lvID0gZGlmZnByZWNpbykgDQpWaWV3KGxpbW9uZXMyKQ0KYGBgDQoNCmBgYHtyfQ0KYXV0b3Bsb3QobGltb25lczJbLDE6Ml0sZmFjZXQ9VFJVRSkNCmBgYA0KDQoNCmBgYHtyfQ0KVkFSc2VsZWN0KGxpbW9uZXMyLCBsYWcubWF4ID0gOCwgdHlwZT0iY29uc3QiKVtbInNlbGVjdGlvbiJdXQ0KdmFyMTwtVkFSKGxpbW9uZXMyLHA9MSwgdHlwZSA9ICJjb25zdCIpDQpzZXJpYWwudGVzdCh2YXIxLCBsYWdzLnB0PTEwLCB0eXBlPSJQVC5hc3ltcHRvdGljIikNCnZhcjI8LVZBUihsaW1vbmVzMixwPTIsdHlwZSA9ICJjb25zdCIpDQpzZXJpYWwudGVzdCh2YXIyLCBsYWdzLnB0PTEwLCB0eXBlPSJQVC5hc3ltcHRvdGljIikNCnZhcjIuc2VyaWFsPC1zZXJpYWwudGVzdCh2YXIyLCBsYWdzLnB0PTEwLCB0eXBlPSJQVC5hc3ltcHRvdGljIikNCnBsb3QodmFyMi5zZXJpYWwsbmFtZXM9IlByb2R1Y2Np824gZGUgbGltb25lcyIpDQpwbG90KHZhcjIuc2VyaWFsLG5hbWVzPSJQcmVjaW8iKQ0KYGBgDQojRXZhbHVhciBsYSBjb2ludGVuZ3JhY2nzbiB1c2FuZG8gbGEgbWV0b2RvbG9n7WEgZGUgRW5nbGUtR3JhbmdlciB5IEpvaGFuc2VuDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCnBsb3QobGltb25lcywgbWFpbj0iUHJvZHVjY2nzbiBkZSBMaW1vbmVzIikNCnBsb3QoUHJlY2lvbGltb24sbWFpbj0iUHJlY2lvIEdlbmVyYWwiKQ0KDQpgYGANCg0KYGBge3J9DQp1ci5kZihsaW1vbmVzKQ0KdXIuZGYoUHJlY2lvbGltb24pDQpgYGANCiMjIyMjSG86TGEgc2VyaWUgbm8gZXMgZXN0YWNpb25hcmlhDQojIyMjI1NlZ/puIGxhIHBydWViYSBkZSBjb2ludGVncmFjafNuLCBpbmRpY2EgcXVlIGVsIHTpcm1pbm8gZGVsIGVycm9yIGVzIG1heW9yIGEgbG9zIGNyaXRpY29zICh5MT0tMSwgeTI9MSkgcG9yIGxvIHRhbnRvIG5vIHNvbiBlc3RhY2lvbmFyaWFzDQoNCmBgYHtyfQ0KbHAucmVnIDwtIGR5bmxtKFByZWNpb2xpbW9uIH4gTChQcmVjaW9saW1vbikgKyBsaW1vbmVzICsgTChsaW1vbmVzKSkNCnN1bW1hcnkobHAucmVnKQ0KYGBgDQpgYGB7cn0NCmR3dGVzdChscC5yZWcpDQpgYGANCiMjIyMjU2Ugb2JzZXJ2YSBxdWUgZWwgdmFsb3IgcCByZXN1bHRhIHNlciBzaWduaWZpY2F0aXZvIHA+MC41IHBvciBsbyB0YW50byBzZSByZWNoYXphIGxhIEhvIGFjZXB0YW5kbyBsYSBhbHRlcm5hIHBvciBsbyBxdWUgbGFzIHZhcmlhYmxlcyB0aWVuZW4gdmVyZGFkZXJhIGF1dG9jb3JyZWxhY2nzbiBlbnRyZSBlbGxhcy4NCg0KYGBge3J9DQplcnJvciA8LSByZXNpZHVhbHMobHAucmVnKQ0KcGxvdChlcnJvcikNCmFibGluZShoPTApDQp1ci5kZihlcnJvcikNCmBgYA0KDQojIyMjI0hvOkxhIHNlcmllIG5vIGVzIGVzdGFjaW9uYXJpYQ0KIyMjIyNTZWf6biBsYSBwcnVlYmEgZGUgY29pbnRlZ3JhY2nzbiwgaW5kaWNhIHF1ZSBlbCB06XJtaW5vIGRlbCBlcnJvciBlcyBtYXlvciBhIGxvcyBjcml0aWNvcyBwPS03Ljg2IHBvciBsbyB0YW50byBleGlzdGUgdW5hIHJlbGFjaW9uIGRlIGNvaW50ZWdyYWNp824uIA0KDQoNCmBgYHtyfQ0KbGltb25lczMgPC0gdHMuaW50ZXJzZWN0KGxpbW9uZXMsUHJlY2lvbGltb24sIGVycm9yKQ0KZHluIDwtIGR5bmxtKGQoUHJlY2lvbGltb24pIH4gTChlcnJvcikgKyBMKGQobGltb25lcykpICsgTChkKFByZWNpb2xpbW9uKSksIGRhdGE9ZGF0YSkNCnN1bW1hcnkoZHluKQ0KYGBgDQoNCg==