library(car)
library(nortest)
library(MASS)
library(latex2exp)
library(ggplot2)
library(tibble)
library(GGally)
library(MVN)
library(pracma)
library(dplyr)
library(ggpubr) # Para Realizar QQplots con función ggqqplot(model$resi)
library(QuantPsyc) # Para verificar multinormalidad
library(tidyverse)
library(devtools) # Instalar paquetes que no están en el CRAN
library(alr3)
- Considera la base de datos LED.csv. Se cree que la esperanza de vida
esta en esta en función del año en cuestión, el porcentaje de ingesta de
alcohol y el estado del país(desarrollado o en desarrollo). Ademas se
sospecha que existe interacción entre el año y el estado del país. Este
tipo de interacción, digamos que entre dos regresores \(x_1\) y \(x_2\), se ingresa en el modelo de regresión
considerando el producto de tales variables \(x_1x_2\).
# Carga del conjunto de datos
LED<-read.csv("/Users/danimathud/Downloads/Led.csv",na.strings = "NA")
LED[,1]<-as.factor(LED$Country)
LED<- LED %>% filter(LED$Alcohol!="NA")
LED<- LED %>% filter(LED$Life.expectancy!="NA")
for(i in 1:nrow(LED)){
if (LED[i,3]=="Developing"){
LED[i,3]<-1
}
else{
LED[i,3]<-0
}
}
LED$Status<-as.numeric(LED$Status)
a)
Ajusta el modelo con la interacción entre el año y el estado del
país.
Para poder visualizar, es conveniente convertir la variable estatus a
numérica, donde “1” hace referencia a estado Developing y “0” a estado
No Developing.
muestreo1<-sample(nrow(LED),size=300)
LedModel<-lm(LED$Life.expectancy~LED$Alcohol+LED$Year+LED$Status+LED$Status*LED$Year)
plot(LED$Year,LED$Life.expectancy,pch=19,main="Grafico Dispersión Año vs Esperanza Vida",xlab="Año",ylab="Esperanza de Vida")

plot(LED$Status, LED$Life.expectancy,pch=19, main="Dispersión Estatus vs Esperanza de vida",xlab="Estatus",ylab="Esperanza de Vida")

plot(LED$Alcohol,LED$Life.expectancy,pch=19,main="Dispersión Alcohol vs Esperanza de Vida",xlab="Alcohol",ylab="Esperanza de Vida")

summary(LedModel)
Call:
lm(formula = LED$Life.expectancy ~ LED$Alcohol + LED$Year + LED$Status +
LED$Status * LED$Year)
Residuals:
Min 1Q Median 3Q Max
-32.936 -4.910 1.353 6.206 17.976
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -607.02598 169.26080 -3.586 0.000341 ***
LED$Alcohol 0.45921 0.04768 9.631 < 2e-16 ***
LED$Year 0.33962 0.08432 4.028 5.79e-05 ***
LED$Status -110.14343 186.68031 -0.590 0.555232
LED$Year:LED$Status 0.05031 0.09301 0.541 0.588582
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 8.085 on 2730 degrees of freedom
Multiple R-squared: 0.2844, Adjusted R-squared: 0.2834
F-statistic: 271.3 on 4 and 2730 DF, p-value: < 2.2e-16
Viendo los diagramas dispersión en cualquiera de los tres podemos
observar poca relación lineal entre las variables predictora y la
respuesta. Sin embargo analicemos una manera adecuada para ajustar un
modelo lineal.
plot(LedModel,which = 1,pch=19,sub.caption = "")

El gráfico de residuales nos da indicio de dos posibles subconjuntos,
puesto que visualmente se viola el supuesto de homocedasticidad. Estos
subconjuntos corresponden a países no desarrollados y desarrollados.
Puesto que la esperanza de vida en países desarrollados son mayores, con
lo cual podríamos pensar en que quizás resulte mas conveniente separar
el conjunto de datos original en dos subconjuntos independientes. Por
otro lado del gráfico QQ, vemos que por lo menos considerando ambos
estatus la normalidad no se esta cumpliendo tampoco como se ve en la
siguiente gráfica
ggqqplot(LedModel$residuals,title = "QQ Plot")

Claramente se puede ver la no normalidad en los errores, ya que gran
parte de los residuos se sale de las bandas de confianza.
Puesto que separamos por estatus, ya no tiene mucho sentido
considerarla como regresora, de modo que consideremos alcohol y años
como regresores. Ajustando un modelo para cada estatus obtenemos lo
siguiente:
EstatusDev<-LED %>% filter(LED$Status==1)
EstatusNoDev <- LED %>% filter(LED$Status==0)
LedModelDev <- lm(EstatusDev$Life.expectancy~EstatusDev$Year+EstatusDev$Alcohol)
LedModelNoDev<-lm(EstatusNoDev$Life.expectancy~EstatusNoDev$Year+EstatusNoDev$Alcohol)
Para estatus desarrollado, observamos un gráfico de residuales poco
homogéneo, pues lo residuales se agrupan en una región y por otro lado
del QQ vemos que tampoco hay normalidad, de hecho los residuales se
quedan fuera de la banda de confianza, y este hecho se confirma aun mas
con la prueba de Shapiro la cual rechaza la normalidad
plot(LedModelDev,which=1,pch=19,sub.caption = "")

ggqqplot(LedModelDev$residuals)

shapiro.test(LedModelDev$residuals)
Shapiro-Wilk normality test
data: LedModelDev$residuals
W = 0.94791, p-value < 2.2e-16
Ahora considerando estatus no desarrollado, obtenemos también la no
normalidad y no homocedasticidad en los errores, puesto que al igual que
ocurrió en estatus desarrollado, los residuos se están concentrando de
manera no homogénea sobre una franja horizontal. Podemos concluir que el
modelo lineal no es el adecuado para este conjunto de datos, pues en
ambos casos no se satisfacen ninguno de los supuestos.
plot(LedModelNoDev,which=1,pch=19,sub.caption = "")

ggqqplot(LedModelNoDev$residuals)

shapiro.test(LedModelNoDev$residuals)
Shapiro-Wilk normality test
data: LedModelNoDev$residuals
W = 0.96997, p-value = 2.114e-08
b)
Ajusta un nuevo modelo sin considerar los regresores que resultaron
no significativos en el inciso anterior.
En el resumen del inciso anterior se puede ver que las variables
estatus e interacción tenian p-valores grande, con lo cual es plausible
que los sus respectivos \(\beta\)’s
sean cero, de modo que podemos considerar un modelo sin estas
predictoras, sin embargo también pudimos observar que el conjunto de
datos en general si tendía a separarse en dos grupos distintos, lo cual
seguiremos observando a pesar de no tener en cuenta al estatus. De modo
que es de esperar obtener resultados similares a los obtenidos en el
inciso anterior, es decir que es posible que de nuevo el modelo lineal
no sea adecuado para este conjunto en general retirando las predictoras
ya mencionadas.
LedModelGen<-lm(LED$Life.expectancy~LED$Year+LED$Alcohol)
plot(LedModelGen,which=1,pch=19,sub.caption = "")

ggqqplot(LedModelGen$residuals)

shapiro.test(LedModelGen$residuals)
Shapiro-Wilk normality test
data: LedModelGen$residuals
W = 0.95025, p-value < 2.2e-16
Nuevamente al igual que se observo en el inciso anterior, el
comportamiento de los residuales es no homogéneo, se esta concentrando y
no se esta dispersando de manera uniforme, con lo cual homocedastidad no
se esta cumpliendo, por otro lado del QQ, podeos ver que gran parte de
los residuales se están quedando fuera de las bandas de confianza. En
conclusión considerando o no los regresores mencionados, hay violación
de supuestos y por lo tanto el modelo lineal tampoco es adecuado en este
caso.
# pureErrorAnova(modelo1)
# ggcorr(maria[,1:3],label=T)
# confidenceEllipse(fit)
c)
#Residuales Estudentizados
plot(LedModelGen$fitted.values,rstudent(LedModelGen),pch=19,main="Estudentizados vs Ajustados")
abline(h=0,lty=2,col="red")

plot(LED$Year,rstudent(LedModelGen),pch=19,col="blue",main="Regresor(Año) vs Estudentizados",ylab="Residuales estudentizados",xlab="Año")

plot(LED$Alcohol,rstudent(LedModelGen),pch=19,main="Regresor(Alcohol) vs Estudentizados",xlab = "Alcohol",ylab="Residuales estudentizados")

# Regresión Parcial
M1<-lm(LED$Life.expectancy~LED$Alcohol)
M2<-lm(LED$Alcohol~LED$Year)
plot(M1$residuals,M2$residuals,pch=19,main="Regresión Parcial- (Alc~Año) vs (EspVida~Alc)",xlab="Residuales Alcohol en función del año",ylab="Residuales Esp. de vida en función de Alcohol")

De la primera gráfica de estudentizados versus ajustados, podemos
observar de entrada un comportamiento poco homogéneo de los residuales,
pues como podemos observar, estos se están concentrando hacia la
izquierda, como en forma de megáfono, lo que indica que igualdad de
varianza no se esta cumpliendo. Por lo tanto empezando ya hay indicios
de que el modelo lineal que intentamos ajustar no es adecuado para el
conjunto de datos, o por lo menos no para describir esperanza de vida en
función del año y consumo de alcohol. Veamos los demás gráficos de
residuales, para afirmar con mas seguridad la no adecuación del
modelo.
De la segunda gráfica, podemos observar el comportamiento de los
residuales versus el regresor año. Evidenciamos nuevamente un
comportamiento no homogéneo, pues de hecho es casi inmediato por por las
tendencia vertical de los datos para cada año, de igual forma aunque el
modelo poco se ajusta, recordemos que si el modelo se ajustara bien en
principio el gráfico que esperaríamos tener debería no diferir mucho del
original, lo cual claramente aquí no se tiene. En conclusión para esta
gráfica se sigue viendo que el modelo quizás no sea el adecuado.
En la tercera gráfica comparamos ahora el regresor alcohol versus los
residuales estudentizados, aunque aquí también se evidencia la no
homocedasticidad, sin embargo si podemos notar que el gráfico tiene
mucha similitud al del modelo original observado en el gráfico 1, lo que
al menos si nos permite suponer que este regresor si tiene influencia en
el modelo general a pesar de que no sea lineal.
Por ultimo comparando el gráfico de residuales para regresión
parcial, observamos que el modelo no es adecuado, puesto que de serlo,
deberíamos observar los residuales con un comportamiento lineal, es
decir una dispersión a la cual podría ajustar un modelo lineal y en lo
que vemos esto no pareciera.
ResiPress<-LedModelGen$residuals/(1-influence(LedModelGen)$hat)
syy <- sum((LED$Life.expectancy-mean(LED$Life.expectancy))^2)
EstPress<-sum(ResiPress^2)
p_2<-1-EstPress/syy
En conclusión el modelo lineal no es adecuado. Adicional, su poder
predictivo es bastante pobre, pues observamos un \(P^2\) de 0.1966, lo cual esta muy bajo.
d)
Ajusta el modelo con el año como único predictor y realiza una prueba
de bondad de ajuste para dicho modelo
M3<-lm(LED$Life.expectancy~LED$Year)
pure.error.anova(M3)
Warning: 'pure.error.anova' is deprecated.
Use 'pureErrorAnova' instead.
See help("Deprecated") and help("alr3-deprecated").
Analysis of Variance Table
Response: LED$Life.expectancy
Df Sum Sq Mean Sq F value Pr(>F)
LED$Year 1 6799 6799.3 76.3004 <2e-16 ***
Residuals 2733 242606 88.8
Lack of fit 14 309 22.1 0.2478 0.9979
Pure Error 2719 242297 89.1
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Podemos ver del resumen la salida el p-valor (Lack of fit) de 0.9979,
lo que por lo menos con prueba de bondad de ajuste, no se rechaza que el
modelo sea lineal.
e)
Determina si tiene sentido pensar que el tiempo de vida esperado en
2022 estará entre 80 y 85 años
ResiPress2<-M3$residuals/(1-influence(M3)$hat)
syy_2 <- sum((LED$Life.expectancy-mean(LED$Life.expectancy))^2)
EstPress_2<-sum(ResiPress2^2)
p_cuadrado<-1-EstPress_2/syy_2
Tenemos que el poder predictivo es demasiado bajo (0.0254), con lo
cual de entrada esperaríamos que no tuviera tanto sentido pensar que la
esperanza de vida este entre 80 y 85 años, por otro lado, tengamos en
cuenta que nuestro conjunto de datos considera años como máximo de los
años considerados en nuestro ajuste es 2015, con lo cual considerar
valores por encima de esto, generaría mas error de predicción. Sin
embargo veamos si la intuición es correcta viendo un intervalo de
confianza
valort<-qt(0.025,df=nrow(LED)-2)
MSS_res<-sum((M3$residuals)^2)/(nrow(LED)-2)
x0<-2022
y0<--661.23+0.36392*x0
sxx<-sum((LED$Year-mean(LED$Year))^2)
z<-(x0-mean(LED$Year))^2/sxx
ColInf<-y0+valort*sqrt(MSS_res*(1+1/nrow(LED)+z))
ColInf
[1] 56.09807
ColSup<-y0-valort*sqrt(MSS_res*(1+1/nrow(LED)+z))
ColSup
[1] 93.13441
Realizando el calculo de los intervalos de predicción, vemos que la
intuición no fue correcta y de hecho las esperanza de vida de entre 80 y
85 son valores en el intervalo de predicción, y por lo tanto si es
plausible que para 2022 la esperanza de vida este entre 80 y 85 a pesar
de que la intuición pareciera indicar lo contrario.
- La base de datos ``Salarios.csv’’ contiene información anual del
porcentaje de mujeres empleadas en cierto país. Con esta base realiza lo
siguiente:
Salarios<-read.csv("/Users/danimathud/Downloads/Salarios.csv")
a)
Ajusta un modelo de regresión simple utilizando el año como variable
predictora (incluye la validación de supuestos necesaria).
SalModel<-lm(Salarios$Porcentaje.de.trabajadoras.con.pago.por.horas~Salarios$Anio)
summary(SalModel)
Call:
lm(formula = Salarios$Porcentaje.de.trabajadoras.con.pago.por.horas ~
Salarios$Anio)
Residuals:
Min 1Q Median 3Q Max
-0.39847 -0.12824 -0.06107 0.12481 0.44198
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -266.88626 38.01103 -7.021 6.18e-05 ***
Salarios$Anio 0.16565 0.01915 8.648 1.18e-05 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2473 on 9 degrees of freedom
Multiple R-squared: 0.8926, Adjusted R-squared: 0.8807
F-statistic: 74.79 on 1 and 9 DF, p-value: 1.182e-05
Viendo el gráfico de dispersión, podemos observar un poco de
comportamiento lineal, verifiquemos los supuestos para confirmar si el
modelo lineal se ajusta bien al conjunto de datos.
plot(SalModel$fitted.values,rstudent(SalModel),pch=19,cex=1.2,panel.smooth(SalModel$fitted.values,rstudent(SalModel),col.smooth = "blue"),xlab="Ajustados",ylab="Residuales Estudentizados",main = "Ajustados vs Gráfico Residuales Estud. ")
abline(h=0,lty=2,col="red")

# Separación de residuales
Aleatorios<-sample(nrow(Salarios),size =floor(nrow(Salarios)*0.6))
Grupo1<-SalModel$residuals[Aleatorios]
Grupo2<-SalModel$residuals[-Aleatorios]
Etiquetas1<-rep("Grupo1",floor(nrow(Salarios)*0.6))
Etiquetas2<-rep("Grupo2",nrow(Salarios)-floor(nrow(Salarios)*0.6))
Etiquetas<-c(Etiquetas1,Etiquetas2)
ResidualesAgrup<-c(Grupo1,Grupo2)
ResidualesAgrup<-data.frame(ResidualesAgrup,Etiquetas)
as.factor(ResidualesAgrup$Etiquetas)
[1] Grupo1 Grupo1 Grupo1 Grupo1 Grupo1 Grupo1 Grupo2 Grupo2 Grupo2 Grupo2
[11] Grupo2
Levels: Grupo1 Grupo2
# Verificación de Homocedasticidad
leveneTest(ResidualesAgrup$ResidualesAgrup,group=ResidualesAgrup$Etiquetas)
Warning: ResidualesAgrup$Etiquetas coerced to factor.
Levene's Test for Homogeneity of Variance (center = median)
Df F value Pr(>F)
group 1 1.8869 0.2028
9
Viendo el resumen del modelo, rechazamos que \(\beta_0,\beta_1\) son cero por tener
p-valores inferiores a \(0.05\).
Por otro lado, haciendo la validación de supuestos podemos notar
primeramente que del gráfico de residuos, parece indicar
homocedasticidad en los errores, si observamos la curva de ajuste(color
azul) podemos notar una curva un “poco horizontal”, y además muy
próximos a la linea punteada, con lo cual al menos visualmente
observamos media cero en los residuales. Complementando mas la
validación de homocedasticidad, usando la prueba de Levene, podemos
observar un p-valor de 0.2837, con lo cual considerando un nivel de
significancia \(\alpha=0.05\), tenemos
que no hay evidencia estadística suficiente para concluir que los
residuales no tienen igual varianza, lo cual es consecuente con lo
observado previamente en el gráfico de residuales.
# Verificación de Normalidad en los errores
shapiro.test(SalModel$residuals)
Shapiro-Wilk normality test
data: SalModel$residuals
W = 0.96828, p-value = 0.8686
ggqqplot(SalModel$residuals,color = "blue",ylab="Muestrale",xlab="Teoricos",title = "Grafico QQ")

Por ultimo, verifiquemos la normalidad en los errores. Del gráfico
QQ, observamos que los residuales se mantienen en las bandas de
confianza, y están muy cercanos a la recta, con lo cual de inicio;
visualmente podemos verificar que los residuos siguen la misma
distribución y además con la prueba de Shapiro-Wilk obtenemos un p-valor
de 0.8686 con lo cual no rechazamos la normalidad en los residuales. En
conclusión vemos que se satisfacen todos los supuestos de regresión
simple, y por tanto resulta adecuado ajustar una recta a los datos. El
modelo ajustado es:
plot(Salarios$Anio,Salarios$Porcentaje.de.trabajadoras.con.pago.por.horas,pch=19,cex=1.2,xlab="Años",ylab="Porcentaje de Trabajadoras")
abline(SalModel,col="red")

b)
Realiza un análisis de residuales para determinar si existen
outliers.
# Residuales estudentizados
plot(SalModel$fitted.values,rstudent(SalModel),pch=19,cex=1.2,ylab="Estudentizados",xlab="Ajustados",main="Ajustados vs Residuales estudentizados",ylim=c(-2.5,2.5))
points(c(SalModel$fitted.values[2],SalModel$fitted.values[9]),c(rstudent(SalModel)[2],rstudent(SalModel)[9]),col="red",pch=19,cex=1.2)
abline(h=0,col="red",lty=2)
legend(62.45,2.5,legend = c("Posibles Atipicos"),fill="red")

Como podemos observar del gráfico de residuales estudentizados,
tenemos dos residuales que están más alejados con respecto al resto(los
de color rojo), así que retiremoslos del modelo con con el fin de
observar, si el modelo varía considerablemente y de esta manera podemos
concluir que posiblemente se trate de valores atípicos.
SalariosSinOutliers<-Salarios[-c(which.min(rstudent(SalModel)),which.max(rstudent(SalModel))),]
SalModel2<-lm(SalariosSinOutliers$Porcentaje.de.trabajadoras.con.pago.por.horas~SalariosSinOutliers$Anio)
plot(SalModel2$fitted.values,rstudent(SalModel2),pch=19,cex=1.2,panel.smooth(SalModel2$fitted.values,rstudent(SalModel2),col.smooth = "blue"),xlab="Ajustados",ylab="Residuales Estudentizados",main = " Ajust. vs Res_stud. Quitando 'Outliers' ")
abline(h=0,lty=2,col="red")

#legend(62,0.5,legend = c("azul","rojo"), fill=c("red","blue"))
Como podemos ver del gráfico de residuales estudentizados retirando
las observaciones mencionadas, podemos ver que los residuales se
dispersan de una manera un poco mas homogénea que como lo hacían los
residuales estudentizados originales en los cuales si considerábamos
esas observaciones, de modo que es posible que estas observaciones se
traten de datos atípicos.
c)
Determina si los posibles valores atípicos hallados en el inciso
anterior son valores influyentes.
Al igual que el inciso a) validemos los supuestos. En el inciso b)
verificamos que tanto varío el modelo mediante el gráfico de residuales
estudentizados, concluimos que había mejoría en la dispersión de los
residuales pues se veía una dispersión mas homogénea el modelo retirando
estos Outliers, sin embargo veamos que tanta variabilidad tienen estas
observaciones en el modelo general, verificando el resumen y el QQ
plot.
ggqqplot(SalModel2$residuals,color = "blue",ylab="Muestrales",xlab="Teoricos",title = "Grafico QQ, quitando posibles influyentes")

summary(SalModel2)
Call:
lm(formula = SalariosSinOutliers$Porcentaje.de.trabajadoras.con.pago.por.horas ~
SalariosSinOutliers$Anio)
Residuals:
Min 1Q Median 3Q Max
-0.180 -0.070 -0.035 0.155 0.175
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -225.9100 23.4230 -9.645 2.71e-05 ***
SalariosSinOutliers$Anio 0.1450 0.0118 12.286 5.43e-06 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.1396 on 7 degrees of freedom
Multiple R-squared: 0.9557, Adjusted R-squared: 0.9494
F-statistic: 150.9 on 1 and 7 DF, p-value: 5.427e-06
summary(SalModel)
Call:
lm(formula = Salarios$Porcentaje.de.trabajadoras.con.pago.por.horas ~
Salarios$Anio)
Residuals:
Min 1Q Median 3Q Max
-0.39847 -0.12824 -0.06107 0.12481 0.44198
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -266.88626 38.01103 -7.021 6.18e-05 ***
Salarios$Anio 0.16565 0.01915 8.648 1.18e-05 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2473 on 9 degrees of freedom
Multiple R-squared: 0.8926, Adjusted R-squared: 0.8807
F-statistic: 74.79 on 1 and 9 DF, p-value: 1.182e-05
Podemos observar que al igual que en el inciso anterior, se
satisfacen los supuestos del modelo lineal, puesto que por un lado del
QQplot, los residuales se mantienen dentro de las bandas de confianza,
lo que nos indica igual distribución como era de esperar, por otro lado
con el gráfico de residuos visto en el inciso b) observamos que los
residuales se mantienen en un comportamiento “decente” lo que indica
homocedasticidad, y la normalidad se mantiene por la prueba de Shapiro
Test donde se obtuvo un p-valor de 0.139. Asi que el modelo se comporta
bien extrayendo esas dos observaciones; por otro lado podemos observar
del resumen un aumento en el valor del R ajustado para el modelo
extrayendo las observaciones, y observando los \(\beta\)’s en ambos modelos vemos una poca
variación, con lo cual en conclusión los datos no son suficientemente
influyentes en modelo original. Lo cual podemos observar en la grafica
donde comparamos modelos muy variación con la obtenida en un inicio.
shapiro.test(SalModel2$residuals)
Shapiro-Wilk normality test
data: SalModel2$residuals
W = 0.87498, p-value = 0.139
plot(Salarios$Anio,Salarios$Porcentaje.de.trabajadoras.con.pago.por.horas,pch=19,cex=1.2,xlab="Años",ylab="Porcentaje de Trabajadoras",main="Comparando modelos")
abline(SalModel,col="red")
abline(SalModel2,col="blue")
legend(1989,61.2,legend=c("Con Outliers","Sin Outliers"),fill=c("red","blue"))

LS0tCnRpdGxlOiAiUGFyY2lhbCAyIE1vZGVsb3MgRXN0YWTDrXN0aWNvcyBJIgphdXRob3I6ICJEYW5pZWwgU3RpdmVuIE1hcnRpbmV6IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKCgotLS0KCmBgYHtyfQpsaWJyYXJ5KGNhcikKbGlicmFyeShub3J0ZXN0KQpsaWJyYXJ5KE1BU1MpCmxpYnJhcnkobGF0ZXgyZXhwKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGliYmxlKQpsaWJyYXJ5KEdHYWxseSkKbGlicmFyeShNVk4pCmxpYnJhcnkocHJhY21hKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncHVicikgIyBQYXJhIFJlYWxpemFyIFFRcGxvdHMgY29uIGZ1bmNpw7NuIGdncXFwbG90KG1vZGVsJHJlc2kpCmxpYnJhcnkoUXVhbnRQc3ljKSAjIFBhcmEgdmVyaWZpY2FyIG11bHRpbm9ybWFsaWRhZApsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShkZXZ0b29scykgIyBJbnN0YWxhciBwYXF1ZXRlcyBxdWUgbm8gZXN0w6FuIGVuIGVsIENSQU4KbGlicmFyeShhbHIzKQpgYGAKCgoxLiBDb25zaWRlcmEgbGEgYmFzZSBkZSBkYXRvcyBMRUQuY3N2LiBTZSBjcmVlIHF1ZSBsYSBlc3BlcmFuemEgZGUgdmlkYSBlc3RhIGVuIGVzdGEgZW4gZnVuY2nDs24gZGVsIGHDsW8gZW4gY3Vlc3Rpw7NuLCBlbCBwb3JjZW50YWplIGRlIGluZ2VzdGEgZGUgYWxjb2hvbCB5IGVsIGVzdGFkbyBkZWwgcGHDrXMoZGVzYXJyb2xsYWRvIG8gZW4gZGVzYXJyb2xsbykuIEFkZW1hcyBzZSBzb3NwZWNoYSBxdWUgZXhpc3RlIGludGVyYWNjacOzbiBlbnRyZSBlbCBhw7FvIHkgZWwgZXN0YWRvIGRlbCBwYcOtcy4gRXN0ZSB0aXBvIGRlIGludGVyYWNjacOzbiwgZGlnYW1vcyBxdWUgZW50cmUgZG9zIHJlZ3Jlc29yZXMgJHhfMSQgeSAkeF8yJCwgc2UgaW5ncmVzYSBlbiBlbCBtb2RlbG8gZGUgcmVncmVzacOzbiBjb25zaWRlcmFuZG8gZWwgcHJvZHVjdG8gZGUgdGFsZXMgdmFyaWFibGVzICR4XzF4XzIkLgoKYGBge3J9CiMgQ2FyZ2EgZGVsIGNvbmp1bnRvIGRlIGRhdG9zCkxFRDwtcmVhZC5jc3YoIi9Vc2Vycy9kYW5pbWF0aHVkL0Rvd25sb2Fkcy9MZWQuY3N2IixuYS5zdHJpbmdzID0gIk5BIikKTEVEWywxXTwtYXMuZmFjdG9yKExFRCRDb3VudHJ5KQpMRUQ8LSBMRUQgJT4lIGZpbHRlcihMRUQkQWxjb2hvbCE9Ik5BIikKTEVEPC0gTEVEICU+JSBmaWx0ZXIoTEVEJExpZmUuZXhwZWN0YW5jeSE9Ik5BIikKZm9yKGkgaW4gMTpucm93KExFRCkpewogIGlmIChMRURbaSwzXT09IkRldmVsb3BpbmciKXsKICAgIExFRFtpLDNdPC0xCiAgfQogICBlbHNlewogICAgIExFRFtpLDNdPC0wCiAgIH0gCn0KTEVEJFN0YXR1czwtYXMubnVtZXJpYyhMRUQkU3RhdHVzKQpgYGAKCjxwIHN0eWxlPSJjb2xvcjpibHVlIj5hKTwvcD5BanVzdGEgZWwgbW9kZWxvIGNvbiBsYSBpbnRlcmFjY2nDs24gZW50cmUgZWwgYcOxbyB5IGVsIGVzdGFkbyBkZWwgcGHDrXMuCgpQYXJhIHBvZGVyIHZpc3VhbGl6YXIsIGVzIGNvbnZlbmllbnRlIGNvbnZlcnRpciBsYSB2YXJpYWJsZSBlc3RhdHVzIGEgbnVtw6lyaWNhLCBkb25kZSAiMSIgaGFjZSByZWZlcmVuY2lhIGEgZXN0YWRvIERldmVsb3BpbmcgIHkgICIwIiBhIGVzdGFkbyBObyBEZXZlbG9waW5nLiAKCmBgYHtyfQptdWVzdHJlbzE8LXNhbXBsZShucm93KExFRCksc2l6ZT0zMDApCkxlZE1vZGVsPC1sbShMRUQkTGlmZS5leHBlY3RhbmN5fkxFRCRBbGNvaG9sK0xFRCRZZWFyK0xFRCRTdGF0dXMrTEVEJFN0YXR1cypMRUQkWWVhcikKcGxvdChMRUQkWWVhcixMRUQkTGlmZS5leHBlY3RhbmN5LHBjaD0xOSxtYWluPSJHcmFmaWNvIERpc3BlcnNpw7NuIEHDsW8gdnMgRXNwZXJhbnphIFZpZGEiLHhsYWI9IkHDsW8iLHlsYWI9IkVzcGVyYW56YSBkZSBWaWRhIikgCnBsb3QoTEVEJFN0YXR1cywgTEVEJExpZmUuZXhwZWN0YW5jeSxwY2g9MTksIG1haW49IkRpc3BlcnNpw7NuIEVzdGF0dXMgdnMgRXNwZXJhbnphIGRlIHZpZGEiLHhsYWI9IkVzdGF0dXMiLHlsYWI9IkVzcGVyYW56YSBkZSBWaWRhIikKcGxvdChMRUQkQWxjb2hvbCxMRUQkTGlmZS5leHBlY3RhbmN5LHBjaD0xOSxtYWluPSJEaXNwZXJzacOzbiBBbGNvaG9sIHZzIEVzcGVyYW56YSBkZSBWaWRhIix4bGFiPSJBbGNvaG9sIix5bGFiPSJFc3BlcmFuemEgZGUgVmlkYSIpCnN1bW1hcnkoTGVkTW9kZWwpCmBgYApWaWVuZG8gbG9zIGRpYWdyYW1hcyBkaXNwZXJzacOzbiBlbiBjdWFscXVpZXJhIGRlIGxvcyB0cmVzIHBvZGVtb3Mgb2JzZXJ2YXIgcG9jYSByZWxhY2nDs24gbGluZWFsIGVudHJlIGxhcyB2YXJpYWJsZXMgcHJlZGljdG9yYSB5IGxhIHJlc3B1ZXN0YS4gU2luIGVtYmFyZ28gYW5hbGljZW1vcyB1bmEgbWFuZXJhIGFkZWN1YWRhIHBhcmEgYWp1c3RhciB1biBtb2RlbG8gbGluZWFsLgpgYGB7cn0KcGxvdChMZWRNb2RlbCx3aGljaCA9IDEscGNoPTE5LHN1Yi5jYXB0aW9uID0gIiIpCmBgYApFbCBncsOhZmljbyBkZSByZXNpZHVhbGVzIG5vcyBkYSBpbmRpY2lvIGRlIGRvcyBwb3NpYmxlcyBzdWJjb25qdW50b3MsIHB1ZXN0byBxdWUgdmlzdWFsbWVudGUgc2UgdmlvbGEgZWwgc3VwdWVzdG8gZGUgaG9tb2NlZGFzdGljaWRhZC4gRXN0b3Mgc3ViY29uanVudG9zICBjb3JyZXNwb25kZW4gYSBwYcOtc2VzIG5vIGRlc2Fycm9sbGFkb3MgeSBkZXNhcnJvbGxhZG9zLiBQdWVzdG8gcXVlIGxhIGVzcGVyYW56YSBkZSB2aWRhIGVuIHBhw61zZXMgZGVzYXJyb2xsYWRvcyBzb24gbWF5b3JlcywgY29uIGxvIGN1YWwgcG9kcsOtYW1vcyBwZW5zYXIgZW4gcXVlIHF1aXrDoXMgcmVzdWx0ZSBtYXMgY29udmVuaWVudGUgc2VwYXJhciBlbCBjb25qdW50byBkZSBkYXRvcyBvcmlnaW5hbCBlbiBkb3Mgc3ViY29uanVudG9zIGluZGVwZW5kaWVudGVzLgpQb3Igb3RybyBsYWRvIGRlbCBncsOhZmljbyBRUSwgdmVtb3MgcXVlIHBvciBsbyBtZW5vcyBjb25zaWRlcmFuZG8gYW1ib3MgZXN0YXR1cyBsYSBub3JtYWxpZGFkIG5vIHNlIGVzdGEgY3VtcGxpZW5kbyB0YW1wb2NvIGNvbW8gc2UgdmUgZW4gbGEgc2lndWllbnRlIGdyw6FmaWNhCgoKYGBge3J9CmdncXFwbG90KExlZE1vZGVsJHJlc2lkdWFscyx0aXRsZSA9ICJRUSBQbG90IikKYGBgCkNsYXJhbWVudGUgc2UgcHVlZGUgdmVyIGxhIG5vIG5vcm1hbGlkYWQgZW4gbG9zIGVycm9yZXMsIHlhIHF1ZSBncmFuIHBhcnRlIGRlIGxvcyByZXNpZHVvcyBzZSBzYWxlIGRlIGxhcyBiYW5kYXMgZGUgY29uZmlhbnphLgoKUHVlc3RvIHF1ZSBzZXBhcmFtb3MgcG9yIGVzdGF0dXMsIHlhIG5vIHRpZW5lIG11Y2hvIHNlbnRpZG8gY29uc2lkZXJhcmxhIGNvbW8gcmVncmVzb3JhLCBkZSBtb2RvIHF1ZSBjb25zaWRlcmVtb3MgYWxjb2hvbCB5IGHDsW9zIGNvbW8gcmVncmVzb3Jlcy4gQWp1c3RhbmRvIHVuIG1vZGVsbyBwYXJhIGNhZGEgZXN0YXR1cyBvYnRlbmVtb3MgbG8gc2lndWllbnRlOgoKYGBge3J9CkVzdGF0dXNEZXY8LUxFRCAlPiUgZmlsdGVyKExFRCRTdGF0dXM9PTEpCkVzdGF0dXNOb0RldiA8LSBMRUQgJT4lIGZpbHRlcihMRUQkU3RhdHVzPT0wKQpMZWRNb2RlbERldiA8LSBsbShFc3RhdHVzRGV2JExpZmUuZXhwZWN0YW5jeX5Fc3RhdHVzRGV2JFllYXIrRXN0YXR1c0RldiRBbGNvaG9sKQpMZWRNb2RlbE5vRGV2PC1sbShFc3RhdHVzTm9EZXYkTGlmZS5leHBlY3RhbmN5fkVzdGF0dXNOb0RldiRZZWFyK0VzdGF0dXNOb0RldiRBbGNvaG9sKQoKYGBgClBhcmEgZXN0YXR1cyBkZXNhcnJvbGxhZG8sIG9ic2VydmFtb3MgdW4gZ3LDoWZpY28gZGUgcmVzaWR1YWxlcyBwb2NvIGhvbW9nw6luZW8sIHB1ZXMgbG8gcmVzaWR1YWxlcyBzZSBhZ3J1cGFuIGVuIHVuYSByZWdpw7NuIHkgcG9yIG90cm8gbGFkbyBkZWwgUVEgdmVtb3MgcXVlIHRhbXBvY28gaGF5IG5vcm1hbGlkYWQsIGRlIGhlY2hvIGxvcyByZXNpZHVhbGVzIHNlIHF1ZWRhbiBmdWVyYSBkZSBsYSBiYW5kYSBkZSBjb25maWFuemEsIHkgZXN0ZSBoZWNobyBzZSBjb25maXJtYSBhdW4gbWFzIGNvbiBsYSBwcnVlYmEgZGUgU2hhcGlybyBsYSBjdWFsIHJlY2hhemEgbGEgbm9ybWFsaWRhZApgYGB7cn0KcGxvdChMZWRNb2RlbERldix3aGljaD0xLHBjaD0xOSxzdWIuY2FwdGlvbiA9ICIiKQpnZ3FxcGxvdChMZWRNb2RlbERldiRyZXNpZHVhbHMpCmBgYAoKYGBge3J9CnNoYXBpcm8udGVzdChMZWRNb2RlbERldiRyZXNpZHVhbHMpCmBgYApBaG9yYSBjb25zaWRlcmFuZG8gZXN0YXR1cyBubyBkZXNhcnJvbGxhZG8sIG9idGVuZW1vcyB0YW1iacOpbiBsYSBubyBub3JtYWxpZGFkIHkgbm8gaG9tb2NlZGFzdGljaWRhZCBlbiBsb3MgZXJyb3JlcywgcHVlc3RvIHF1ZSBhbCBpZ3VhbCBxdWUgb2N1cnJpw7MgZW4gZXN0YXR1cyBkZXNhcnJvbGxhZG8sIGxvcyByZXNpZHVvcyBzZSBlc3TDoW4gY29uY2VudHJhbmRvIGRlIG1hbmVyYSBubyBob21vZ8OpbmVhIHNvYnJlIHVuYSBmcmFuamEgaG9yaXpvbnRhbC4gUG9kZW1vcyBjb25jbHVpciBxdWUgZWwgbW9kZWxvIGxpbmVhbCBubyBlcyBlbCBhZGVjdWFkbyBwYXJhIGVzdGUgY29uanVudG8gZGUgZGF0b3MsIHB1ZXMgZW4gYW1ib3MgY2Fzb3Mgbm8gc2Ugc2F0aXNmYWNlbiBuaW5ndW5vIGRlIGxvcyBzdXB1ZXN0b3MuIApgYGB7cn0KcGxvdChMZWRNb2RlbE5vRGV2LHdoaWNoPTEscGNoPTE5LHN1Yi5jYXB0aW9uID0gIiIpCmdncXFwbG90KExlZE1vZGVsTm9EZXYkcmVzaWR1YWxzKQpzaGFwaXJvLnRlc3QoTGVkTW9kZWxOb0RldiRyZXNpZHVhbHMpCmBgYAo8cCBzdHlsZT0iY29sb3I6Ymx1ZSI+Yik8L3A+IApBanVzdGEgdW4gbnVldm8gbW9kZWxvIHNpbiBjb25zaWRlcmFyIGxvcyByZWdyZXNvcmVzIHF1ZSByZXN1bHRhcm9uIG5vIHNpZ25pZmljYXRpdm9zIGVuIGVsIGluY2lzbyBhbnRlcmlvci4KCkVuIGVsIHJlc3VtZW4gZGVsIGluY2lzbyBhbnRlcmlvciBzZSBwdWVkZSB2ZXIgcXVlIGxhcyB2YXJpYWJsZXMgZXN0YXR1cyBlIGludGVyYWNjacOzbiB0ZW5pYW4gcC12YWxvcmVzIGdyYW5kZSwgY29uIGxvIGN1YWwgZXMgcGxhdXNpYmxlIHF1ZSBsb3Mgc3VzIHJlc3BlY3Rpdm9zICRcYmV0YSQncyBzZWFuIGNlcm8sIGRlIG1vZG8gcXVlIHBvZGVtb3MgY29uc2lkZXJhciB1biBtb2RlbG8gc2luIGVzdGFzIHByZWRpY3RvcmFzLCBzaW4gZW1iYXJnbyB0YW1iacOpbiBwdWRpbW9zIG9ic2VydmFyIHF1ZSBlbCBjb25qdW50byBkZSBkYXRvcyBlbiBnZW5lcmFsIHNpIHRlbmTDrWEgYSBzZXBhcmFyc2UgZW4gZG9zIGdydXBvcyBkaXN0aW50b3MsIGxvIGN1YWwgc2VndWlyZW1vcyBvYnNlcnZhbmRvIGEgcGVzYXIgZGUgbm8gdGVuZXIgZW4gY3VlbnRhIGFsIGVzdGF0dXMuIERlIG1vZG8gcXVlIGVzIGRlIGVzcGVyYXIgb2J0ZW5lciByZXN1bHRhZG9zIHNpbWlsYXJlcyBhIGxvcyBvYnRlbmlkb3MgZW4gZWwgaW5jaXNvIGFudGVyaW9yLCBlcyBkZWNpciBxdWUgZXMgcG9zaWJsZSBxdWUgZGUgbnVldm8gZWwgbW9kZWxvIGxpbmVhbCBubyBzZWEgYWRlY3VhZG8gcGFyYSBlc3RlIGNvbmp1bnRvIGVuIGdlbmVyYWwgcmV0aXJhbmRvIGxhcyBwcmVkaWN0b3JhcyB5YSBtZW5jaW9uYWRhcy4KCmBgYHtyfQpMZWRNb2RlbEdlbjwtbG0oTEVEJExpZmUuZXhwZWN0YW5jeX5MRUQkWWVhcitMRUQkQWxjb2hvbCkKcGxvdChMZWRNb2RlbEdlbix3aGljaD0xLHBjaD0xOSxzdWIuY2FwdGlvbiA9ICIiKQpnZ3FxcGxvdChMZWRNb2RlbEdlbiRyZXNpZHVhbHMpCnNoYXBpcm8udGVzdChMZWRNb2RlbEdlbiRyZXNpZHVhbHMpCmBgYApOdWV2YW1lbnRlIGFsIGlndWFsIHF1ZSBzZSBvYnNlcnZvIGVuIGVsIGluY2lzbyBhbnRlcmlvciwgZWwgY29tcG9ydGFtaWVudG8gZGUgbG9zIHJlc2lkdWFsZXMgZXMgbm8gaG9tb2fDqW5lbywgc2UgZXN0YSBjb25jZW50cmFuZG8geSBubyBzZSBlc3RhIGRpc3BlcnNhbmRvIGRlIG1hbmVyYSB1bmlmb3JtZSwgY29uIGxvIGN1YWwgaG9tb2NlZGFzdGlkYWQgbm8gc2UgZXN0YSBjdW1wbGllbmRvLCBwb3Igb3RybyBsYWRvIGRlbCBRUSwgcG9kZW9zIHZlciBxdWUgZ3JhbiBwYXJ0ZSBkZSBsb3MgcmVzaWR1YWxlcyBzZSBlc3TDoW4gcXVlZGFuZG8gZnVlcmEgZGUgbGFzIGJhbmRhcyBkZSBjb25maWFuemEuIEVuIGNvbmNsdXNpw7NuIGNvbnNpZGVyYW5kbyBvIG5vIGxvcyByZWdyZXNvcmVzIG1lbmNpb25hZG9zLCBoYXkgdmlvbGFjacOzbiBkZSBzdXB1ZXN0b3MgeSBwb3IgbG8gdGFudG8gZWwgbW9kZWxvIGxpbmVhbCB0YW1wb2NvIGVzIGFkZWN1YWRvIGVuIGVzdGUgY2Fzby4KCgoKCgoKYGBge3J9CiMgcHVyZUVycm9yQW5vdmEobW9kZWxvMSkKIyBnZ2NvcnIobWFyaWFbLDE6M10sbGFiZWw9VCkKIyBjb25maWRlbmNlRWxsaXBzZShmaXQpCmBgYAoKPHAgc3R5bGU9ImNvbG9yOmJsdWUiPmMpPC9wPgoKYGBge3J9CiNSZXNpZHVhbGVzIEVzdHVkZW50aXphZG9zCnBsb3QoTGVkTW9kZWxHZW4kZml0dGVkLnZhbHVlcyxyc3R1ZGVudChMZWRNb2RlbEdlbikscGNoPTE5LG1haW49IkVzdHVkZW50aXphZG9zIHZzIEFqdXN0YWRvcyIpCmFibGluZShoPTAsbHR5PTIsY29sPSJyZWQiKQpwbG90KExFRCRZZWFyLHJzdHVkZW50KExlZE1vZGVsR2VuKSxwY2g9MTksY29sPSJibHVlIixtYWluPSJSZWdyZXNvcihBw7FvKSB2cyBFc3R1ZGVudGl6YWRvcyIseWxhYj0iUmVzaWR1YWxlcyBlc3R1ZGVudGl6YWRvcyIseGxhYj0iQcOxbyIpCnBsb3QoTEVEJEFsY29ob2wscnN0dWRlbnQoTGVkTW9kZWxHZW4pLHBjaD0xOSxtYWluPSJSZWdyZXNvcihBbGNvaG9sKSB2cyBFc3R1ZGVudGl6YWRvcyIseGxhYiA9ICJBbGNvaG9sIix5bGFiPSJSZXNpZHVhbGVzIGVzdHVkZW50aXphZG9zIikKYGBgCmBgYHtyfQojIFJlZ3Jlc2nDs24gUGFyY2lhbApNMTwtbG0oTEVEJExpZmUuZXhwZWN0YW5jeX5MRUQkQWxjb2hvbCkKTTI8LWxtKExFRCRBbGNvaG9sfkxFRCRZZWFyKQpwbG90KE0xJHJlc2lkdWFscyxNMiRyZXNpZHVhbHMscGNoPTE5LG1haW49IlJlZ3Jlc2nDs24gUGFyY2lhbC0gKEFsY35Bw7FvKSB2cyAoRXNwVmlkYX5BbGMpIix4bGFiPSJSZXNpZHVhbGVzIEFsY29ob2wgZW4gZnVuY2nDs24gZGVsIGHDsW8iLHlsYWI9IlJlc2lkdWFsZXMgRXNwLiBkZSB2aWRhIGVuIGZ1bmNpw7NuIGRlIEFsY29ob2wiKQpgYGAKRGUgbGEgcHJpbWVyYSBncsOhZmljYSBkZSBlc3R1ZGVudGl6YWRvcyB2ZXJzdXMgYWp1c3RhZG9zLCBwb2RlbW9zIG9ic2VydmFyIGRlIGVudHJhZGEgdW4gY29tcG9ydGFtaWVudG8gcG9jbyBob21vZ8OpbmVvIGRlIGxvcyByZXNpZHVhbGVzLCBwdWVzIGNvbW8gcG9kZW1vcyBvYnNlcnZhciwgZXN0b3Mgc2UgZXN0w6FuIGNvbmNlbnRyYW5kbyBoYWNpYSBsYSBpenF1aWVyZGEsIGNvbW8gZW4gZm9ybWEgZGUgbWVnw6Fmb25vLCBsbyBxdWUgaW5kaWNhIHF1ZSBpZ3VhbGRhZCBkZSB2YXJpYW56YSBubyBzZSBlc3RhIGN1bXBsaWVuZG8uIFBvciBsbyB0YW50byBlbXBlemFuZG8geWEgaGF5IGluZGljaW9zIGRlIHF1ZSBlbCBtb2RlbG8gbGluZWFsIHF1ZSBpbnRlbnRhbW9zIGFqdXN0YXIgbm8gZXMgYWRlY3VhZG8gcGFyYSBlbCBjb25qdW50byBkZSBkYXRvcywgbyBwb3IgbG8gbWVub3MgIG5vIHBhcmEgZGVzY3JpYmlyIGVzcGVyYW56YSBkZSB2aWRhIGVuIGZ1bmNpw7NuIGRlbCBhw7FvIHkgY29uc3VtbyBkZSBhbGNvaG9sLiBWZWFtb3MgbG9zIGRlbcOhcyBncsOhZmljb3MgZGUgcmVzaWR1YWxlcywgcGFyYSBhZmlybWFyIGNvbiBtYXMgc2VndXJpZGFkIGxhIG5vIGFkZWN1YWNpw7NuIGRlbCBtb2RlbG8uCgpEZSBsYSBzZWd1bmRhIGdyw6FmaWNhLCBwb2RlbW9zIG9ic2VydmFyIGVsIGNvbXBvcnRhbWllbnRvIGRlIGxvcyByZXNpZHVhbGVzIHZlcnN1cyBlbCByZWdyZXNvciBhw7FvLiBFdmlkZW5jaWFtb3MgbnVldmFtZW50ZSB1biBjb21wb3J0YW1pZW50byBubyBob21vZ8OpbmVvLCBwdWVzIGRlIGhlY2hvIGVzIGNhc2kgaW5tZWRpYXRvIHBvciBwb3IgbGFzIHRlbmRlbmNpYSB2ZXJ0aWNhbCBkZSBsb3MgZGF0b3MgcGFyYSBjYWRhIGHDsW8sIGRlIGlndWFsIGZvcm1hIGF1bnF1ZSBlbCBtb2RlbG8gcG9jbyBzZSBhanVzdGEsIHJlY29yZGVtb3MgcXVlIHNpIGVsIG1vZGVsbyBzZSBhanVzdGFyYSBiaWVuIGVuIHByaW5jaXBpbyBlbCBncsOhZmljbyBxdWUgZXNwZXJhcsOtYW1vcyB0ZW5lciBkZWJlcsOtYSBubyBkaWZlcmlyIG11Y2hvIGRlbCBvcmlnaW5hbCwgbG8gY3VhbCBjbGFyYW1lbnRlIGFxdcOtIG5vIHNlIHRpZW5lLiBFbiBjb25jbHVzacOzbiBwYXJhIGVzdGEgZ3LDoWZpY2Egc2Ugc2lndWUgdmllbmRvIHF1ZSBlbCBtb2RlbG8gcXVpesOhcyBubyBzZWEgZWwgYWRlY3VhZG8uCgpFbiBsYSB0ZXJjZXJhIGdyw6FmaWNhIGNvbXBhcmFtb3MgYWhvcmEgZWwgcmVncmVzb3IgYWxjb2hvbCB2ZXJzdXMgbG9zIHJlc2lkdWFsZXMgZXN0dWRlbnRpemFkb3MsIGF1bnF1ZSBhcXXDrSB0YW1iacOpbiBzZSBldmlkZW5jaWEgbGEgbm8gaG9tb2NlZGFzdGljaWRhZCwgc2luIGVtYmFyZ28gc2kgcG9kZW1vcyBub3RhciBxdWUgZWwgZ3LDoWZpY28gdGllbmUgbXVjaGEgc2ltaWxpdHVkIGFsIGRlbCBtb2RlbG8gb3JpZ2luYWwgb2JzZXJ2YWRvIGVuIGVsIGdyw6FmaWNvIDEsIGxvIHF1ZSBhbCBtZW5vcyBzaSBub3MgcGVybWl0ZSBzdXBvbmVyIHF1ZSBlc3RlIHJlZ3Jlc29yIHNpIHRpZW5lIGluZmx1ZW5jaWEgZW4gZWwgbW9kZWxvIGdlbmVyYWwgYSBwZXNhciBkZSBxdWUgbm8gc2VhIGxpbmVhbC4gCgpQb3IgdWx0aW1vIGNvbXBhcmFuZG8gZWwgZ3LDoWZpY28gZGUgcmVzaWR1YWxlcyBwYXJhIHJlZ3Jlc2nDs24gcGFyY2lhbCwgb2JzZXJ2YW1vcyBxdWUgZWwgbW9kZWxvIG5vIGVzIGFkZWN1YWRvLCBwdWVzdG8gcXVlIGRlIHNlcmxvLCBkZWJlcsOtYW1vcyBvYnNlcnZhciBsb3MgcmVzaWR1YWxlcyBjb24gdW4gY29tcG9ydGFtaWVudG8gbGluZWFsLCBlcyBkZWNpciB1bmEgZGlzcGVyc2nDs24gYSBsYSBjdWFsIHBvZHLDrWEgYWp1c3RhciB1biBtb2RlbG8gbGluZWFsIHkgZW4gbG8gcXVlIHZlbW9zIGVzdG8gbm8gcGFyZWNpZXJhLgoKYGBge3J9ClJlc2lQcmVzczwtTGVkTW9kZWxHZW4kcmVzaWR1YWxzLygxLWluZmx1ZW5jZShMZWRNb2RlbEdlbikkaGF0KQpzeXkgPC0gc3VtKChMRUQkTGlmZS5leHBlY3RhbmN5LW1lYW4oTEVEJExpZmUuZXhwZWN0YW5jeSkpXjIpCkVzdFByZXNzPC1zdW0oUmVzaVByZXNzXjIpCnBfMjwtMS1Fc3RQcmVzcy9zeXkKYGBgCgoKRW4gY29uY2x1c2nDs24gZWwgbW9kZWxvIGxpbmVhbCAgbm8gZXMgYWRlY3VhZG8uIEFkaWNpb25hbCwgc3UgcG9kZXIgcHJlZGljdGl2byBlcyBiYXN0YW50ZSBwb2JyZSwgcHVlcyBvYnNlcnZhbW9zIHVuICRQXjIkIGRlIDAuMTk2NiwgbG8gY3VhbCBlc3RhIG11eSBiYWpvLgoKPHAgc3R5bGU9ImNvbG9yOmJsdWUiPmQpPC9wPgpBanVzdGEgZWwgbW9kZWxvIGNvbiBlbCBhw7FvIGNvbW8gw7puaWNvIHByZWRpY3RvciB5IHJlYWxpemEgdW5hIHBydWViYSBkZSBib25kYWQgZGUgYWp1c3RlIHBhcmEgZGljaG8gbW9kZWxvCgpgYGB7cn0KTTM8LWxtKExFRCRMaWZlLmV4cGVjdGFuY3l+TEVEJFllYXIpCnB1cmUuZXJyb3IuYW5vdmEoTTMpCmBgYAoKUG9kZW1vcyB2ZXIgZGVsIHJlc3VtZW4gbGEgc2FsaWRhIGVsIHAtdmFsb3IgKExhY2sgb2YgZml0KSBkZSAwLjk5NzksIGxvIHF1ZSBwb3IgbG8gbWVub3MgY29uIHBydWViYSBkZSBib25kYWQgZGUgYWp1c3RlLCBubyBzZSByZWNoYXphIHF1ZSBlbCBtb2RlbG8gc2VhIGxpbmVhbC4KCjxwIHN0eWxlPSJjb2xvcjpibHVlIj5lKTwvcD4KRGV0ZXJtaW5hIHNpIHRpZW5lIHNlbnRpZG8gcGVuc2FyIHF1ZSBlbCB0aWVtcG8gZGUgdmlkYSBlc3BlcmFkbyBlbiAyMDIyIGVzdGFyw6EgZW50cmUgODAgeSA4NSBhw7FvcwoKYGBge3J9ClJlc2lQcmVzczI8LU0zJHJlc2lkdWFscy8oMS1pbmZsdWVuY2UoTTMpJGhhdCkKc3l5XzIgPC0gc3VtKChMRUQkTGlmZS5leHBlY3RhbmN5LW1lYW4oTEVEJExpZmUuZXhwZWN0YW5jeSkpXjIpCkVzdFByZXNzXzI8LXN1bShSZXNpUHJlc3MyXjIpCnBfY3VhZHJhZG88LTEtRXN0UHJlc3NfMi9zeXlfMgoKYGBgClRlbmVtb3MgcXVlIGVsIHBvZGVyIHByZWRpY3Rpdm8gZXMgZGVtYXNpYWRvIGJham8gKDAuMDI1NCksIGNvbiBsbyBjdWFsIGRlIGVudHJhZGEgZXNwZXJhcsOtYW1vcyBxdWUgbm8gdHV2aWVyYSB0YW50byBzZW50aWRvIHBlbnNhciBxdWUgbGEgZXNwZXJhbnphIGRlIHZpZGEgZXN0ZSBlbnRyZSA4MCB5IDg1IGHDsW9zLCBwb3Igb3RybyBsYWRvLCB0ZW5nYW1vcyBlbiBjdWVudGEgcXVlIG51ZXN0cm8gY29uanVudG8gZGUgZGF0b3MgY29uc2lkZXJhIGHDsW9zIGNvbW8gbcOheGltbyBkZSBsb3MgYcOxb3MgY29uc2lkZXJhZG9zIGVuIG51ZXN0cm8gYWp1c3RlIGVzIDIwMTUsIGNvbiBsbyBjdWFsIGNvbnNpZGVyYXIgdmFsb3JlcyBwb3IgZW5jaW1hIGRlIGVzdG8sIGdlbmVyYXLDrWEgbWFzIGVycm9yIGRlIHByZWRpY2Npw7NuLiBTaW4gZW1iYXJnbyB2ZWFtb3Mgc2kgbGEgaW50dWljacOzbiBlcyBjb3JyZWN0YSB2aWVuZG8gIHVuIGludGVydmFsbyBkZSBjb25maWFuemEgICAgCgpgYGB7cn0KdmFsb3J0PC1xdCgwLjAyNSxkZj1ucm93KExFRCktMikKTVNTX3Jlczwtc3VtKChNMyRyZXNpZHVhbHMpXjIpLyhucm93KExFRCktMikKeDA8LTIwMjIKeTA8LS02NjEuMjMrMC4zNjM5Mip4MApzeHg8LXN1bSgoTEVEJFllYXItbWVhbihMRUQkWWVhcikpXjIpCno8LSh4MC1tZWFuKExFRCRZZWFyKSleMi9zeHgKCgpDb2xJbmY8LXkwK3ZhbG9ydCpzcXJ0KE1TU19yZXMqKDErMS9ucm93KExFRCkreikpCkNvbEluZgpDb2xTdXA8LXkwLXZhbG9ydCpzcXJ0KE1TU19yZXMqKDErMS9ucm93KExFRCkreikpCkNvbFN1cApgYGAKUmVhbGl6YW5kbyBlbCBjYWxjdWxvIGRlIGxvcyBpbnRlcnZhbG9zIGRlIHByZWRpY2Npw7NuLCB2ZW1vcyBxdWUgbGEgaW50dWljacOzbiBubyBmdWUgY29ycmVjdGEgeSBkZSBoZWNobyBsYXMgZXNwZXJhbnphIGRlIHZpZGEgZGUgZW50cmUgODAgeSA4NSBzb24gdmFsb3JlcyBlbiBlbCBpbnRlcnZhbG8gZGUgcHJlZGljY2nDs24sIHkgcG9yIGxvIHRhbnRvIHNpIGVzIHBsYXVzaWJsZSBxdWUgcGFyYSAyMDIyIGxhIGVzcGVyYW56YSBkZSB2aWRhIGVzdGUgZW50cmUgODAgeSA4NSBhIHBlc2FyIGRlIHF1ZSBsYSBpbnR1aWNpw7NuIHBhcmVjaWVyYSBpbmRpY2FyIGxvIGNvbnRyYXJpby4gCgoKCjIuIExhIGJhc2UgZGUgZGF0b3MgYGBTYWxhcmlvcy5jc3YnJyBjb250aWVuZSBpbmZvcm1hY2nDs24gYW51YWwgZGVsIHBvcmNlbnRhamUgZGUgbXVqZXJlcyBlbXBsZWFkYXMgZW4gY2llcnRvIHBhw61zLiBDb24gZXN0YSBiYXNlIHJlYWxpemEgbG8gc2lndWllbnRlOgoKYGBge3J9ClNhbGFyaW9zPC1yZWFkLmNzdigiL1VzZXJzL2RhbmltYXRodWQvRG93bmxvYWRzL1NhbGFyaW9zLmNzdiIpCmBgYAoKPHAgc3R5bGU9ImNvbG9yOmJsdWUiPmEpPC9wPiBBanVzdGEgdW4gbW9kZWxvIGRlIHJlZ3Jlc2nDs24gc2ltcGxlIHV0aWxpemFuZG8gZWwgYcOxbyBjb21vIHZhcmlhYmxlIHByZWRpY3RvcmEgKGluY2x1eWUgbGEgdmFsaWRhY2nDs24gZGUgc3VwdWVzdG9zIG5lY2VzYXJpYSkuCgpgYGB7cn0KU2FsTW9kZWw8LWxtKFNhbGFyaW9zJFBvcmNlbnRhamUuZGUudHJhYmFqYWRvcmFzLmNvbi5wYWdvLnBvci5ob3Jhc35TYWxhcmlvcyRBbmlvKQpzdW1tYXJ5KFNhbE1vZGVsKQpgYGAKVmllbmRvIGVsIGdyw6FmaWNvIGRlIGRpc3BlcnNpw7NuLCBwb2RlbW9zIG9ic2VydmFyIHVuIHBvY28gZGUgY29tcG9ydGFtaWVudG8gbGluZWFsLCB2ZXJpZmlxdWVtb3MgbG9zIHN1cHVlc3RvcyBwYXJhIGNvbmZpcm1hciBzaSBlbCBtb2RlbG8gbGluZWFsIHNlIGFqdXN0YSBiaWVuIGFsIGNvbmp1bnRvIGRlIGRhdG9zLgoKYGBge3J9CnBsb3QoU2FsTW9kZWwkZml0dGVkLnZhbHVlcyxyc3R1ZGVudChTYWxNb2RlbCkscGNoPTE5LGNleD0xLjIscGFuZWwuc21vb3RoKFNhbE1vZGVsJGZpdHRlZC52YWx1ZXMscnN0dWRlbnQoU2FsTW9kZWwpLGNvbC5zbW9vdGggPSAiYmx1ZSIpLHhsYWI9IkFqdXN0YWRvcyIseWxhYj0iUmVzaWR1YWxlcyBFc3R1ZGVudGl6YWRvcyIsbWFpbiA9ICJBanVzdGFkb3MgdnMgR3LDoWZpY28gUmVzaWR1YWxlcyBFc3R1ZC4gICIpCmFibGluZShoPTAsbHR5PTIsY29sPSJyZWQiKQpgYGAKCgpgYGB7cn0KIyBTZXBhcmFjacOzbiBkZSByZXNpZHVhbGVzCkFsZWF0b3Jpb3M8LXNhbXBsZShucm93KFNhbGFyaW9zKSxzaXplID1mbG9vcihucm93KFNhbGFyaW9zKSowLjYpKQpHcnVwbzE8LVNhbE1vZGVsJHJlc2lkdWFsc1tBbGVhdG9yaW9zXQpHcnVwbzI8LVNhbE1vZGVsJHJlc2lkdWFsc1stQWxlYXRvcmlvc10KRXRpcXVldGFzMTwtcmVwKCJHcnVwbzEiLGZsb29yKG5yb3coU2FsYXJpb3MpKjAuNikpCkV0aXF1ZXRhczI8LXJlcCgiR3J1cG8yIixucm93KFNhbGFyaW9zKS1mbG9vcihucm93KFNhbGFyaW9zKSowLjYpKQpFdGlxdWV0YXM8LWMoRXRpcXVldGFzMSxFdGlxdWV0YXMyKQpSZXNpZHVhbGVzQWdydXA8LWMoR3J1cG8xLEdydXBvMikKUmVzaWR1YWxlc0FncnVwPC1kYXRhLmZyYW1lKFJlc2lkdWFsZXNBZ3J1cCxFdGlxdWV0YXMpCmFzLmZhY3RvcihSZXNpZHVhbGVzQWdydXAkRXRpcXVldGFzKQpgYGAKYGBge3J9CiMgVmVyaWZpY2FjacOzbiBkZSBIb21vY2VkYXN0aWNpZGFkCmxldmVuZVRlc3QoUmVzaWR1YWxlc0FncnVwJFJlc2lkdWFsZXNBZ3J1cCxncm91cD1SZXNpZHVhbGVzQWdydXAkRXRpcXVldGFzKQpgYGAKVmllbmRvIGVsIHJlc3VtZW4gZGVsIG1vZGVsbywgcmVjaGF6YW1vcyBxdWUgJFxiZXRhXzAsXGJldGFfMSQgc29uIGNlcm8gcG9yIHRlbmVyIHAtdmFsb3JlcyBpbmZlcmlvcmVzIGEgJDAuMDUkLgoKUG9yIG90cm8gbGFkbywgaGFjaWVuZG8gbGEgdmFsaWRhY2nDs24gZGUgc3VwdWVzdG9zIHBvZGVtb3Mgbm90YXIgcHJpbWVyYW1lbnRlIHF1ZSBkZWwgZ3LDoWZpY28gZGUgcmVzaWR1b3MsIHBhcmVjZSBpbmRpY2FyIGhvbW9jZWRhc3RpY2lkYWQgZW4gbG9zIGVycm9yZXMsIHNpIG9ic2VydmFtb3MgbGEgY3VydmEgZGUgYWp1c3RlKGNvbG9yIGF6dWwpIHBvZGVtb3Mgbm90YXIgdW5hIGN1cnZhIHVuICJwb2NvIGhvcml6b250YWwiLCB5IGFkZW3DoXMgbXV5IHByw7N4aW1vcyBhIGxhIGxpbmVhIHB1bnRlYWRhLCBjb24gbG8gY3VhbCBhbCBtZW5vcyB2aXN1YWxtZW50ZSBvYnNlcnZhbW9zIG1lZGlhIGNlcm8gZW4gbG9zIHJlc2lkdWFsZXMuIENvbXBsZW1lbnRhbmRvIG1hcyBsYSB2YWxpZGFjacOzbiBkZSBob21vY2VkYXN0aWNpZGFkLCB1c2FuZG8gbGEgcHJ1ZWJhIGRlIExldmVuZSwgcG9kZW1vcyBvYnNlcnZhciAgdW4gIHAtdmFsb3IgZGUgMC4yODM3LCBjb24gbG8gY3VhbCBjb25zaWRlcmFuZG8gdW4gbml2ZWwgZGUgc2lnbmlmaWNhbmNpYSAkXGFscGhhPTAuMDUkLCB0ZW5lbW9zIHF1ZSBubyBoYXkgZXZpZGVuY2lhIGVzdGFkw61zdGljYSBzdWZpY2llbnRlIHBhcmEgY29uY2x1aXIgcXVlIGxvcyByZXNpZHVhbGVzIG5vIHRpZW5lbiBpZ3VhbCB2YXJpYW56YSwgbG8gY3VhbCBlcyBjb25zZWN1ZW50ZSBjb24gbG8gb2JzZXJ2YWRvIHByZXZpYW1lbnRlIGVuIGVsIGdyw6FmaWNvIGRlIHJlc2lkdWFsZXMuCgpgYGB7cn0KIyBWZXJpZmljYWNpw7NuIGRlIE5vcm1hbGlkYWQgZW4gbG9zIGVycm9yZXMKc2hhcGlyby50ZXN0KFNhbE1vZGVsJHJlc2lkdWFscykKYGBgCmBgYHtyfQpnZ3FxcGxvdChTYWxNb2RlbCRyZXNpZHVhbHMsY29sb3IgPSAiYmx1ZSIseWxhYj0iTXVlc3RyYWxlIix4bGFiPSJUZW9yaWNvcyIsdGl0bGUgPSAiR3JhZmljbyBRUSIpCmBgYAoKUG9yIHVsdGltbywgdmVyaWZpcXVlbW9zIGxhIG5vcm1hbGlkYWQgZW4gbG9zIGVycm9yZXMuIERlbCBncsOhZmljbyBRUSwgb2JzZXJ2YW1vcyBxdWUgbG9zIHJlc2lkdWFsZXMgc2UgbWFudGllbmVuIGVuIGxhcyBiYW5kYXMgZGUgY29uZmlhbnphLCB5IGVzdMOhbiBtdXkgY2VyY2Fub3MgYSBsYSByZWN0YSwgY29uIGxvIGN1YWwgZGUgaW5pY2lvOyB2aXN1YWxtZW50ZSBwb2RlbW9zIHZlcmlmaWNhciBxdWUgbG9zIHJlc2lkdW9zIHNpZ3VlbiBsYSBtaXNtYSBkaXN0cmlidWNpw7NuIHkgYWRlbcOhcyBjb24gbGEgcHJ1ZWJhIGRlIFNoYXBpcm8tV2lsayBvYnRlbmVtb3MgdW4gcC12YWxvciBkZSAwLjg2ODYgY29uIGxvIGN1YWwgbm8gcmVjaGF6YW1vcyBsYSBub3JtYWxpZGFkIGVuIGxvcyByZXNpZHVhbGVzLiBFbiBjb25jbHVzacOzbiB2ZW1vcyBxdWUgc2Ugc2F0aXNmYWNlbiB0b2RvcyBsb3Mgc3VwdWVzdG9zIGRlIHJlZ3Jlc2nDs24gc2ltcGxlLCB5IHBvciB0YW50byByZXN1bHRhIGFkZWN1YWRvIGFqdXN0YXIgdW5hIHJlY3RhIGEgbG9zIGRhdG9zLiBFbCBtb2RlbG8gYWp1c3RhZG8gZXM6CgpgYGB7cn0KcGxvdChTYWxhcmlvcyRBbmlvLFNhbGFyaW9zJFBvcmNlbnRhamUuZGUudHJhYmFqYWRvcmFzLmNvbi5wYWdvLnBvci5ob3JhcyxwY2g9MTksY2V4PTEuMix4bGFiPSJBw7FvcyIseWxhYj0iUG9yY2VudGFqZSBkZSBUcmFiYWphZG9yYXMiKQphYmxpbmUoU2FsTW9kZWwsY29sPSJyZWQiKQpgYGAKCjxwIHN0eWxlPSJjb2xvcjpibHVlIj5iKTwvcD4gUmVhbGl6YSB1biBhbsOhbGlzaXMgZGUgcmVzaWR1YWxlcyBwYXJhIGRldGVybWluYXIgc2kgZXhpc3RlbiBvdXRsaWVycy4KCmBgYHtyfQojIFJlc2lkdWFsZXMgZXN0dWRlbnRpemFkb3MKcGxvdChTYWxNb2RlbCRmaXR0ZWQudmFsdWVzLHJzdHVkZW50KFNhbE1vZGVsKSxwY2g9MTksY2V4PTEuMix5bGFiPSJFc3R1ZGVudGl6YWRvcyIseGxhYj0iQWp1c3RhZG9zIixtYWluPSJBanVzdGFkb3MgdnMgUmVzaWR1YWxlcyBlc3R1ZGVudGl6YWRvcyIseWxpbT1jKC0yLjUsMi41KSkKcG9pbnRzKGMoU2FsTW9kZWwkZml0dGVkLnZhbHVlc1syXSxTYWxNb2RlbCRmaXR0ZWQudmFsdWVzWzldKSxjKHJzdHVkZW50KFNhbE1vZGVsKVsyXSxyc3R1ZGVudChTYWxNb2RlbClbOV0pLGNvbD0icmVkIixwY2g9MTksY2V4PTEuMikKYWJsaW5lKGg9MCxjb2w9InJlZCIsbHR5PTIpCmxlZ2VuZCg2Mi40NSwyLjUsbGVnZW5kID0gYygiUG9zaWJsZXMgQXRpcGljb3MiKSxmaWxsPSJyZWQiKQpgYGAKQ29tbyBwb2RlbW9zIG9ic2VydmFyIGRlbCBncsOhZmljbyBkZSByZXNpZHVhbGVzIGVzdHVkZW50aXphZG9zLCB0ZW5lbW9zIGRvcyByZXNpZHVhbGVzIHF1ZSBlc3TDoW4gbcOhcyBhbGVqYWRvcyBjb24gcmVzcGVjdG8gYWwgcmVzdG8obG9zIGRlIGNvbG9yIHJvam8pLCBhc8OtIHF1ZSByZXRpcmVtb3Nsb3MgZGVsIG1vZGVsbyBjb24gY29uIGVsIGZpbiBkZSBvYnNlcnZhciwgc2kgZWwgbW9kZWxvIHZhcsOtYSBjb25zaWRlcmFibGVtZW50ZSB5IGRlIGVzdGEgbWFuZXJhIHBvZGVtb3MgY29uY2x1aXIgcXVlIHBvc2libGVtZW50ZSBzZSB0cmF0ZSBkZSB2YWxvcmVzIGF0w61waWNvcy4KCmBgYHtyfQpTYWxhcmlvc1Npbk91dGxpZXJzPC1TYWxhcmlvc1stYyh3aGljaC5taW4ocnN0dWRlbnQoU2FsTW9kZWwpKSx3aGljaC5tYXgocnN0dWRlbnQoU2FsTW9kZWwpKSksXQpTYWxNb2RlbDI8LWxtKFNhbGFyaW9zU2luT3V0bGllcnMkUG9yY2VudGFqZS5kZS50cmFiYWphZG9yYXMuY29uLnBhZ28ucG9yLmhvcmFzflNhbGFyaW9zU2luT3V0bGllcnMkQW5pbykKYGBgCgpgYGB7cn0KcGxvdChTYWxNb2RlbDIkZml0dGVkLnZhbHVlcyxyc3R1ZGVudChTYWxNb2RlbDIpLHBjaD0xOSxjZXg9MS4yLHBhbmVsLnNtb290aChTYWxNb2RlbDIkZml0dGVkLnZhbHVlcyxyc3R1ZGVudChTYWxNb2RlbDIpLGNvbC5zbW9vdGggPSAiYmx1ZSIpLHhsYWI9IkFqdXN0YWRvcyIseWxhYj0iUmVzaWR1YWxlcyBFc3R1ZGVudGl6YWRvcyIsbWFpbiA9ICIgQWp1c3QuIHZzIFJlc19zdHVkLiBRdWl0YW5kbyAnT3V0bGllcnMnICIpCmFibGluZShoPTAsbHR5PTIsY29sPSJyZWQiKQojbGVnZW5kKDYyLDAuNSxsZWdlbmQgPSBjKCJhenVsIiwicm9qbyIpLCBmaWxsPWMoInJlZCIsImJsdWUiKSkKCmBgYApDb21vIHBvZGVtb3MgdmVyIGRlbCBncsOhZmljbyBkZSByZXNpZHVhbGVzIGVzdHVkZW50aXphZG9zIHJldGlyYW5kbyBsYXMgb2JzZXJ2YWNpb25lcyBtZW5jaW9uYWRhcywgcG9kZW1vcyB2ZXIgcXVlIGxvcyByZXNpZHVhbGVzIHNlIGRpc3BlcnNhbiBkZSB1bmEgbWFuZXJhIHVuIHBvY28gbWFzIGhvbW9nw6luZWEgcXVlIGNvbW8gbG8gaGFjw61hbiBsb3MgcmVzaWR1YWxlcyBlc3R1ZGVudGl6YWRvcyBvcmlnaW5hbGVzIGVuIGxvcyBjdWFsZXMgc2kgY29uc2lkZXLDoWJhbW9zIGVzYXMgb2JzZXJ2YWNpb25lcywgZGUgbW9kbyBxdWUgZXMgcG9zaWJsZSBxdWUgZXN0YXMgb2JzZXJ2YWNpb25lcyBzZSB0cmF0ZW4gZGUgZGF0b3MgYXTDrXBpY29zLgoKCgoKPHAgc3R5bGU9ImNvbG9yOmJsdWUiPmMpPC9wPiBEZXRlcm1pbmEgc2kgbG9zIHBvc2libGVzIHZhbG9yZXMgYXTDrXBpY29zIGhhbGxhZG9zIGVuIGVsIGluY2lzbyBhbnRlcmlvciBzb24gdmFsb3JlcyBpbmZsdXllbnRlcy4KCgpBbCBpZ3VhbCBxdWUgZWwgaW5jaXNvIGEpICB2YWxpZGVtb3MgbG9zIHN1cHVlc3Rvcy4gRW4gZWwgaW5jaXNvIGIpIHZlcmlmaWNhbW9zIHF1ZSB0YW50byB2YXLDrW8gZWwgbW9kZWxvIG1lZGlhbnRlIGVsIGdyw6FmaWNvIGRlIHJlc2lkdWFsZXMgZXN0dWRlbnRpemFkb3MsIGNvbmNsdWltb3MgcXVlIGhhYsOtYSBtZWpvcsOtYSBlbiBsYSBkaXNwZXJzacOzbiBkZSBsb3MgcmVzaWR1YWxlcyBwdWVzIHNlIHZlw61hIHVuYSBkaXNwZXJzacOzbiBtYXMgaG9tb2fDqW5lYSBlbCBtb2RlbG8gcmV0aXJhbmRvIGVzdG9zIE91dGxpZXJzLCBzaW4gZW1iYXJnbyB2ZWFtb3MgcXVlIHRhbnRhIHZhcmlhYmlsaWRhZCB0aWVuZW4gZXN0YXMgb2JzZXJ2YWNpb25lcyBlbiBlbCBtb2RlbG8gZ2VuZXJhbCwgdmVyaWZpY2FuZG8gZWwgcmVzdW1lbiB5IGVsIFFRIHBsb3QuIAoKYGBge3J9CmdncXFwbG90KFNhbE1vZGVsMiRyZXNpZHVhbHMsY29sb3IgPSAiYmx1ZSIseWxhYj0iTXVlc3RyYWxlcyIseGxhYj0iVGVvcmljb3MiLHRpdGxlID0gIkdyYWZpY28gUVEsIHF1aXRhbmRvIHBvc2libGVzIGluZmx1eWVudGVzIikKYGBgCgoKYGBge3J9CnN1bW1hcnkoU2FsTW9kZWwyKQpzdW1tYXJ5KFNhbE1vZGVsKQpgYGAKClBvZGVtb3Mgb2JzZXJ2YXIgcXVlIGFsIGlndWFsIHF1ZSBlbiBlbCBpbmNpc28gYW50ZXJpb3IsIHNlIHNhdGlzZmFjZW4gbG9zIHN1cHVlc3RvcyBkZWwgbW9kZWxvIGxpbmVhbCwgcHVlc3RvIHF1ZSBwb3IgdW4gbGFkbyBkZWwgUVFwbG90LCBsb3MgcmVzaWR1YWxlcyBzZSBtYW50aWVuZW4gZGVudHJvIGRlIGxhcyBiYW5kYXMgZGUgY29uZmlhbnphLCBsbyBxdWUgbm9zIGluZGljYSBpZ3VhbCBkaXN0cmlidWNpw7NuIGNvbW8gZXJhIGRlIGVzcGVyYXIsIHBvciBvdHJvIGxhZG8gY29uIGVsIGdyw6FmaWNvIGRlIHJlc2lkdW9zIHZpc3RvIGVuIGVsIGluY2lzbyBiKSBvYnNlcnZhbW9zIHF1ZSBsb3MgcmVzaWR1YWxlcyBzZSBtYW50aWVuZW4gZW4gdW4gY29tcG9ydGFtaWVudG8gImRlY2VudGUiIGxvIHF1ZSBpbmRpY2EgaG9tb2NlZGFzdGljaWRhZCwgeSBsYSBub3JtYWxpZGFkIHNlIG1hbnRpZW5lIHBvciBsYSBwcnVlYmEgZGUgU2hhcGlybyBUZXN0IGRvbmRlIHNlIG9idHV2byB1biBwLXZhbG9yIGRlIDAuMTM5LiBBc2kgcXVlIGVsIG1vZGVsbyBzZSBjb21wb3J0YSBiaWVuIGV4dHJheWVuZG8gZXNhcyBkb3Mgb2JzZXJ2YWNpb25lczsgcG9yIG90cm8gbGFkbyBwb2RlbW9zIG9ic2VydmFyIGRlbCByZXN1bWVuIHVuIGF1bWVudG8gZW4gZWwgdmFsb3IgZGVsIFIgYWp1c3RhZG8gcGFyYSBlbCBtb2RlbG8gZXh0cmF5ZW5kbyBsYXMgb2JzZXJ2YWNpb25lcywgeSBvYnNlcnZhbmRvIGxvcyAkXGJldGEkJ3MgZW4gYW1ib3MgbW9kZWxvcyB2ZW1vcyB1bmEgcG9jYSB2YXJpYWNpw7NuLCBjb24gbG8gY3VhbCBlbiBjb25jbHVzacOzbiBsb3MgZGF0b3Mgbm8gc29uIHN1ZmljaWVudGVtZW50ZSBpbmZsdXllbnRlcyBlbiBtb2RlbG8gb3JpZ2luYWwuIExvIGN1YWwgcG9kZW1vcyBvYnNlcnZhciBlbiBsYSBncmFmaWNhIGRvbmRlIGNvbXBhcmFtb3MgbW9kZWxvcyBtdXkgdmFyaWFjacOzbiBjb24gbGEgb2J0ZW5pZGEgZW4gdW4gaW5pY2lvLgoKCmBgYHtyfQpzaGFwaXJvLnRlc3QoU2FsTW9kZWwyJHJlc2lkdWFscykKcGxvdChTYWxhcmlvcyRBbmlvLFNhbGFyaW9zJFBvcmNlbnRhamUuZGUudHJhYmFqYWRvcmFzLmNvbi5wYWdvLnBvci5ob3JhcyxwY2g9MTksY2V4PTEuMix4bGFiPSJBw7FvcyIseWxhYj0iUG9yY2VudGFqZSBkZSBUcmFiYWphZG9yYXMiLG1haW49IkNvbXBhcmFuZG8gbW9kZWxvcyIpCmFibGluZShTYWxNb2RlbCxjb2w9InJlZCIpCmFibGluZShTYWxNb2RlbDIsY29sPSJibHVlIikKbGVnZW5kKDE5ODksNjEuMixsZWdlbmQ9YygiQ29uIE91dGxpZXJzIiwiU2luIE91dGxpZXJzIiksZmlsbD1jKCJyZWQiLCJibHVlIikpCmBgYAoKCgogIA==