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)
  1. 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.

  1. 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==