TALLER ANÁLISIS DE DATOS EN R

  1. Verifique que tenga la versión de RStudio más reciente (1.4.1717). Si no, descárguela del link: https://www.rstudio.com/products/rstudio/download/#download

DCA

  1. Organice los datos que desea analizar en R del Excel o formato en donde registró sus resultados. Para este taller usaremos primero los datos de Tasa Respiratoria del Excel adjunto. Organice los datos en un nuevo Excel de tal forma que los datos queden en columnas de tratamientos, bloques (si los hay), y repeticiones. Guarde el archivo en formato Excel “.xlsx”

Nota: Los decimales deben estar en formato de punto, NO de coma, si no el software no los podrá leer. Para cambiar esta característica en Excel, antes de pegar sus datos diríjase a Archivo>Opciones>Avanzadas>Separador decimal, y ponga “.”> Aceptar.

  1. Con sus datos organizados inicie Rstudio. Abra un nuevo script: File> New File> Rscript.

  2. Llame las librerías a utilizar. En este caso, para este taller, usaremos las librerías:

library(readxl) 
library(agricolae)
library(car) 
library(carData) 
library(MASS)
library(RColorBrewer) #Opcional

Nota: Si no las tiene instaladas diríjase a Tool> Install Packages, inserte los nombres de las librerías a descargar separadas por coma o espacio. El programa tardará unos minutos en instalarlos.

  1. Proceda a subir los datos del Excel, dándole un nombre
TasaR<- read_excel("C:/Users/Juliana Miranda/Documents/Universidad/TESIS/RESULTADOS/R/Respiracion.xlsx")
  1. Visualice un resumen de sus datos:
summary(TasaR)
      DDC             TR       
 Min.   : 3.0   Min.   :11.29  
 1st Qu.: 5.0   1st Qu.:37.16  
 Median : 7.5   Median :45.90  
 Mean   : 7.5   Mean   :45.09  
 3rd Qu.:10.0   3rd Qu.:55.06  
 Max.   :12.0   Max.   :81.45  
  1. Establezca los días después de cosecha (DDC) como factor
TasaR$DDC=as.factor(TasaR$DDC)
  1. Establezca el modelo para un DCA simple y genere el análisis de varianza
TRanov=lm(TasaR$TR~TasaR$DDC)
anova(TRanov)
Analysis of Variance Table

Response: TasaR$TR
          Df  Sum Sq Mean Sq F value    Pr(>F)    
TasaR$DDC  9 15042.9 1671.43  17.549 < 2.2e-16 ***
Residuals 90  8572.1   95.25                      
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

¿A que hace referencia cada uno de los items de la tabla? ¿qué se puede inferir de esta información? ¿qué criterio utilizó para llegar a esa conclusión?

  1. Realice los gráficos exploratorios de residuos para comprobación de supuestos del modelo
hist(TRanov$residuals)

boxplot(TasaR$TR~TasaR$DDC, main="TASA RESPIRATORIA", xlab="DDC", ylab="TR",col=4)# Box plot por tratamientos

boxplot(TRanov$residuals~TasaR$DDC,main="Residuales del modelo",col=4)

¿Cómo describiría el comportamiento de los residuos en el histograma? ¿Es una distribución normal? ¿Qué diferencia encuentra entre el boxplot por tratamientos y el de residuos del modelo? ¿Qué información puede inferir de estas graficas con respecto a los supuestos del modelo?

###Gráficos de validación de supuestos sobre residuales###
split.screen(c(2,2))
[1] 1 2 3 4
screen(1)
# gráfico de residuales vs valores ajustados
plot(TRanov$fitted.values,TRanov$residuals,main="Residuals vs. Fitted", pch=20)
abline(h=0,lty=2)
screen(2)
# gráfico de residuales vs niveles de tratamientos
plot(TasaR$DDC,TRanov$residuals,main="Residuals vs. Levels")   
screen(3)
# gráfico de residuales vs valores en el tiempo
plot(1:100,TRanov$residuals, main="Residuals vs. Time order",pch=20)  
abline(h=0,lty=2)
screen(4)

qqnorm(TRanov$residuals,pch=20)  
qqline(TRanov$residuals) # linea de probabilidad normal gráfico de residuales Q-Q

  1. Compruebe los supuestos del modelo con las pruebas de normalidad y homocedasticidad.
### prueba shapiro prueba de normalidad ###
shapiro.test(TRanov$residuals)

    Shapiro-Wilk normality test

data:  TRanov$residuals
W = 0.97677, p-value = 0.0743
### prueba Kolmogorov-Smirnov prueba de normalidad ###
ks.test(TRanov$residuals, "pnorm", mean(TRanov$residuals), sd(TRanov$residuals))

    One-sample Kolmogorov-Smirnov test

data:  TRanov$residuals
D = 0.059213, p-value = 0.8745
alternative hypothesis: two-sided
### prueba bartlett prueba de homocedasticidad ###
bartlett.test(TRanov$residuals,TasaR$DDC)

    Bartlett test of homogeneity of variances

data:  TRanov$residuals and TasaR$DDC
Bartlett's K-squared = 7.8656, df = 9, p-value = 0.5477

¿Qué puede inferir de las p-valor de las pruebas? ¿Hay normalidad de los datos? ¿Hay homocedasticidad?

  1. Realice la prueba de tukey para verificar cuales son les tratamientos (Días) presentan diferencias significativas con respecto a la variable de tasa respiratoria
HSD.test(TRanov,"TasaR$DDC",console = T)

Study: TRanov ~ "TasaR$DDC"

HSD Test for TasaR$TR 

Mean Square Error:  95.24518 

TasaR$DDC,  means

Alpha: 0.05 ; DF Error: 90 
Critical Value of Studentized Range: 4.588313 

Minimun Significant Difference: 14.16037 

Treatments with the same letter are not significantly different.

¿Hay diferencias significativas? ¿Entre cuales tratamientos? ¿Cómo este resultado se relaciona con el ANOVA realizado previamente?

  1. Realice la gráfica Tasa Respiratoria vs. DDC que incluya las diferencias significativas.
TR=boxplot(TasaR$TR~TasaR$DDC,   main = "Tasa Respiratoria",
           ylab = "mg CO2 * kg-1 * h-1",
           xlab = "Días despues de cosecha", ylim=c(0,84),  col=brewer.pal(n = 8, name = "Set2"))
text(1,41,c("e"))
text(2,54,c("de"))
text(3,54,c("bcd"))
text(4,77,c("a"))
text(5,84,c("a"))
text(6,70,c("ab"))
text(7,70,c("bcd"))
text(8,65,c("bcd"))
text(9,63,c("bcd"))
text(10,63,c("cd"))

  1. Ahora vamos a ver una variable diferente en la que los supuestos no se cumplen y es necesario realizar una transformación de los datos. Para eso organice los datos para la variable de Pérdida de Peso Fresco en columnas y llame el archivo de excel desde R.
Peso_Fresco<- read_excel("C:/Users/Juliana Miranda/Documents/Universidad/TESIS/RESULTADOS/R/Perdida_peso_fresco.xlsx")
Peso_Fresco
summary(Peso_Fresco)
      DDC          PPF              PPF1.2          PPF_BOX      
 Min.   : 4   Min.   : 0.7874   Min.   :0.3937   Min.   :0.9804  
 1st Qu.: 6   1st Qu.: 3.8819   1st Qu.:1.9409   1st Qu.:1.1188  
 Median : 8   Median : 6.7167   Median :3.3583   Median :1.1708  
 Mean   : 8   Mean   : 6.5402   Mean   :3.2701   Mean   :1.1494  
 3rd Qu.:10   3rd Qu.: 9.2884   3rd Qu.:4.6442   3rd Qu.:1.2027  
 Max.   :12   Max.   :13.6531   Max.   :6.8266   Max.   :1.2416  
  1. Determine el peso fresco como un factor
### El tratamiento debe ser un factor ####
Peso_Fresco$DDC=as.factor(Peso_Fresco$DDC)
  1. Cree el modelo y realice el análisis de varianza
PPFanov<-aov(Peso_Fresco$PPF~Peso_Fresco$DDC)
summary(PPFanov)
                Df Sum Sq Mean Sq F value Pr(>F)    
Peso_Fresco$DDC  8 1020.9  127.62   116.7 <2e-16 ***
Residuals       81   88.6    1.09                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

¿Qué se puede inferir de esta información? ¿qué criterio utilizó para llegar a esa conclusión?

  1. Verifique los supuestos con las pruebas de normalidad y homocedasticidad
### prueba shapiro prueba de normalidad ###
shapiro.test(PPFanov$residuals)

    Shapiro-Wilk normality test

data:  PPFanov$residuals
W = 0.94696, p-value = 0.001091
### prueba Kolmogorov-Smirnov prueba de normalidad ###
ks.test(PPFanov$residuals, "pnorm", mean(PPFanov$residuals), sd(PPFanov$residuals))
Warning in ks.test(PPFanov$residuals, "pnorm", mean(PPFanov$residuals),  :
  ties should not be present for the Kolmogorov-Smirnov test

    One-sample Kolmogorov-Smirnov test

data:  PPFanov$residuals
D = 0.14315, p-value = 0.05001
alternative hypothesis: two-sided
### prueba de homogeneidad de varianzas ####
bartlett.test(PPFanov$residuals,Peso_Fresco$DDC)

    Bartlett test of homogeneity of variances

data:  PPFanov$residuals and Peso_Fresco$DDC
Bartlett's K-squared = 48.737, df = 8, p-value = 7.141e-08

¿Se cumplen los supuestos? ¿qué criterio utilizó para llegar a esa conclusión?

  1. Intente transformar los datos con transformaciones comunes como la raíz cuadrada, logaritmo, etc. e intente comprobar nuevamente los supuestos. Para eso debe modificar el Excel creado y añadir una nueva columna con las variables transformadas, por ejemplo, a la 1/2 (la raíz cuadrada). Repita el proceso del punto 13 al 16 de este taller.
PPF1.2anov<-aov(Peso_Fresco$PPF1.2~Peso_Fresco$DDC)
summary(PPF1.2anov)
                Df Sum Sq Mean Sq F value Pr(>F)    
Peso_Fresco$DDC  8 255.23   31.90   116.7 <2e-16 ***
Residuals       81  22.14    0.27                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
### prueba shapiro prueba de normalidad ###
shapiro.test(PPF1.2anov$residuals)

    Shapiro-Wilk normality test

data:  PPF1.2anov$residuals
W = 0.94696, p-value = 0.001091
### prueba Kolmogorov-Smirnov prueba de normalidad ###
ks.test(PPF1.2anov$residuals, "pnorm", mean(PPF1.2anov$residuals), sd(PPF1.2anov$residuals))
Warning in ks.test(PPF1.2anov$residuals, "pnorm", mean(PPF1.2anov$residuals),  :
  ties should not be present for the Kolmogorov-Smirnov test

    One-sample Kolmogorov-Smirnov test

data:  PPF1.2anov$residuals
D = 0.14315, p-value = 0.05001
alternative hypothesis: two-sided
### prueba de homogeneidad de varianzas ####
bartlett.test(PPF1.2anov$residuals,Peso_Fresco$DDC)

    Bartlett test of homogeneity of variances

data:  PPF1.2anov$residuals and Peso_Fresco$DDC
Bartlett's K-squared = 48.737, df = 8, p-value = 7.141e-08

¿Mejoraron los valores de los supeustos? ¿Se cumplen?

  1. Implemente el método Box-Cox para obtener el labda óptimo para la transformación de los datos.
datos<-data.frame(Peso_Fresco$PPF,Peso_Fresco$DDC)
bc1<-boxcox(Peso_Fresco$PPF~Peso_Fresco$DDC, lambda = seq(-2, 3, 1/5), data=datos, plotit = TRUE,
           eps = 1/50 , xlab = expression(lambda), ylab = "log-Likelihood")

summary(powerTransform(Peso_Fresco$PPF~Peso_Fresco$DDC))
bcPower Transformation to Normality 
   Est Power Rounded Pwr Wald Lwr Bnd Wald Upr Bnd
Y1    0.0828           0      -0.1059       0.2716

Likelihood ratio test that transformation parameter is equal to 0
 (log transformation)

Likelihood ratio test that no transformation is needed

¿Qué muestra la gráfica? ¿Qué valor lambda se obtiene?

  1. Realice la transformación de los datos con su nuevo valor lambda. Nuevamente modifique el excel original y vuelva a cargar los datos
##Datos transformados ^(0.0828)######

PPFboxanov<-aov(Peso_Fresco$PPF_BOX~Peso_Fresco$DDC)
summary(PPFboxanov)
                Df Sum Sq Mean Sq F value Pr(>F)    
Peso_Fresco$DDC  8 0.4205 0.05257   268.3 <2e-16 ***
Residuals       81 0.0159 0.00020                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
### prueba shapiro prueba de normalidad ###
shapiro.test(PPFboxanov$residuals)

    Shapiro-Wilk normality test

data:  PPFboxanov$residuals
W = 0.95825, p-value = 0.0056
### prueba Kolmogorov-Smirnov prueba de normalidad ###
ks.test(PPFboxanov$residuals, "pnorm", mean(PPFboxanov$residuals), sd(PPFboxanov$residuals))
Warning in ks.test(PPFboxanov$residuals, "pnorm", mean(PPFboxanov$residuals),  :
  ties should not be present for the Kolmogorov-Smirnov test

    One-sample Kolmogorov-Smirnov test

data:  PPFboxanov$residuals
D = 0.088869, p-value = 0.4759
alternative hypothesis: two-sided
### prueba de homogeneidad de varianzas ####
bartlett.test(PPFboxanov$residuals,Peso_Fresco$DDC)

    Bartlett test of homogeneity of variances

data:  PPFboxanov$residuals and Peso_Fresco$DDC
Bartlett's K-squared = 1.0237, df = 8, p-value = 0.9981

¿El valor lambda permitió corregir los supuestos del modelo? ¿Con qué criterio llegó a esa conclusión?

  1. Con los supuestos cumplidos, realice el análisis de varianza con los datos transformados
HSD.test(PPFboxanov,"Peso_Fresco$DDC",console = T)

Study: PPFboxanov ~ "Peso_Fresco$DDC"

HSD Test for Peso_Fresco$PPF_BOX 

Mean Square Error:  0.0001959574 

Peso_Fresco$DDC,  means

Alpha: 0.05 ; DF Error: 81 
Critical Value of Studentized Range: 4.507391 

Minimun Significant Difference: 0.0199529 

Treatments with the same letter are not significantly different.
  1. Grafique los resultados
PPFg=boxplot(Peso_Fresco$PPF~Peso_Fresco$DDC,   main = "Pérdida peso fresco",
          ylab = "% Pérdida peso fresco",
          xlab = "Días despues de cosecha", col=brewer.pal(n = 8, name = "Set2"))
text(1,2,c("g"))
text(2,4,c("f"))
text(3,6,c("e"))
text(4,7.4,c("d"))
text(5,9,c("c"))
text(6,11,c("bc"))
text(7,12,c("ab"))
text(8,13,c("a"))
text(9,14,c("a"))

DCA con Submuestreo

  1. Para este análisis se usará la variable de Firmeza. Nuevamente organice las variables de forma que queden en columnas de DDC, Firmeza y muestra, esta última en este caso corresponde a los valores del submuestreo (medidas hechas al mismo fruto). Una vez creado el Excel, llame el documento desde R.
Textura<- read_excel("C:/Users/Juliana Miranda/Documents/Universidad/TESIS/RESULTADOS/R/Txt.xlsx")
Textura
summary(Textura)
     DDC                 FIRM           MUESTRA 
 Length:36          Min.   : 4.426   Min.   :1  
 Class :character   1st Qu.: 6.372   1st Qu.:1  
 Mode  :character   Median : 8.220   Median :2  
                    Mean   :16.912   Mean   :2  
                    3rd Qu.:33.708   3rd Qu.:3  
                    Max.   :41.948   Max.   :3  

23.Establezca tanto los estados poscosecha como las medidas del submuestreo como factores

ESTADO<- as.factor(Textura$DDC)
MUESTRA<- as.factor(Textura$MUESTRA) 
  1. Cree el modelo estadístico para un DCA con submuestreo
FIRMdca2<-aov(Textura$FIRM~ESTADO+MUESTRA%in%ESTADO)
summary(FIRMdca2)
               Df Sum Sq Mean Sq F value Pr(>F)    
ESTADO          2   6882    3441 843.590 <2e-16 ***
ESTADO:MUESTRA  6     30       5   1.211  0.331    
Residuals      27    110       4                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
  1. Cree los residuos del modelo y determine si se cumplen los supuestos
resFIRM<-FIRMdca2$residuals #RESIDUOS 
resFIRM
         1          2          3          4          5          6          7          8          9         10         11 
-1.3815000 -1.3135000  0.7305000  1.9645000 -4.5212500 -3.1202500  6.0197500  1.6217500  0.6710000  3.1380000 -2.2930000 
        12         13         14         15         16         17         18         19         20         21         22 
-1.5160000  1.0058250 -0.8537750  0.6624250 -0.8144750 -0.6815500  0.2950500 -0.7906500  1.1771500  1.2299775 -0.4369225 
        23         24         25         26         27         28         29         30         31         32         33 
 0.7340775 -1.5271325  0.7579500 -0.0030500 -1.3038500  0.5489500 -0.2633250 -0.2633250  0.3147750  0.2118750  0.2222750 
        34         35         36 
 0.9556750  0.0049750 -1.1829250 
shapiro.test(resFIRM)

    Shapiro-Wilk normality test

data:  resFIRM
W = 0.92979, p-value = 0.02467
bartlett.test(resFIRM,ESTADO)

    Bartlett test of homogeneity of variances

data:  resFIRM and ESTADO
Bartlett's K-squared = 24.347, df = 2, p-value = 5.166e-06
ks.test(FIRMdca2$residuals, "pnorm", mean(FIRMdca2$residuals), sd(FIRMdca2$residuals))
Warning in ks.test(FIRMdca2$residuals, "pnorm", mean(FIRMdca2$residuals),  :
  ties should not be present for the Kolmogorov-Smirnov test

    One-sample Kolmogorov-Smirnov test

data:  FIRMdca2$residuals
D = 0.13292, p-value = 0.5482
alternative hypothesis: two-sided
  1. Continue el análisis determinando la transformación apropiada para el cual se cumplan los supuestos. Determine las diferencias signficativas entre los estados poscosecha. Grafique los resultados.
LS0tDQp0aXRsZTogIlVuaXZlcnNpZGFkIE5hY2lvbmFsIGRlIENvbG9tYmlhIg0KYXV0aG9yOiBTZW1pbGxlcm8gQWdyb2Jpb2RpdmVyc2lkYWQgeSBCaW90ZWNub2xvZ8OtYQ0Kb3V0cHV0OiBodG1sX25vdGVib29rDQogICAgDQotLS0NCiANCiMgKipUQUxMRVIgQU7DgUxJU0lTIERFIERBVE9TIEVOIFIqKg0KDQoxLglWZXJpZmlxdWUgcXVlIHRlbmdhIGxhIHZlcnNpw7NuIGRlIFJTdHVkaW8gbcOhcyByZWNpZW50ZSAoMS40LjE3MTcpLiBTaSBubywgZGVzY8Ohcmd1ZWxhIGRlbCBsaW5rOiBodHRwczovL3d3dy5yc3R1ZGlvLmNvbS9wcm9kdWN0cy9yc3R1ZGlvL2Rvd25sb2FkLyNkb3dubG9hZCAgDQoNCg0KIyMgKipEQ0EqKg0KDQoNCjIuCU9yZ2FuaWNlIGxvcyBkYXRvcyBxdWUgZGVzZWEgYW5hbGl6YXIgZW4gUiBkZWwgRXhjZWwgbyBmb3JtYXRvIGVuIGRvbmRlIHJlZ2lzdHLDsyBzdXMgcmVzdWx0YWRvcy4gUGFyYSBlc3RlIHRhbGxlciB1c2FyZW1vcyBwcmltZXJvIGxvcyBkYXRvcyBkZSBUYXNhIFJlc3BpcmF0b3JpYSBkZWwgRXhjZWwgYWRqdW50by4gT3JnYW5pY2UgbG9zIGRhdG9zIGVuIHVuIG51ZXZvIEV4Y2VsIGRlIHRhbCBmb3JtYSBxdWUgbG9zIGRhdG9zIHF1ZWRlbiBlbiBjb2x1bW5hcyBkZSB0cmF0YW1pZW50b3MsIGJsb3F1ZXMgKHNpIGxvcyBoYXkpLCB5IHJlcGV0aWNpb25lcy4gR3VhcmRlIGVsIGFyY2hpdm8gZW4gZm9ybWF0byBFeGNlbCDigJwueGxzeOKAnQ0KDQoqKk5vdGE6IExvcyBkZWNpbWFsZXMgZGViZW4gZXN0YXIgZW4gZm9ybWF0byBkZSBwdW50bywgTk8gZGUgY29tYSwgc2kgbm8gZWwgc29mdHdhcmUgbm8gbG9zIHBvZHLDoSBsZWVyLiBQYXJhIGNhbWJpYXIgZXN0YSBjYXJhY3RlcsOtc3RpY2EgZW4gRXhjZWwsIGFudGVzIGRlIHBlZ2FyIHN1cyBkYXRvcyBkaXLDrWphc2UgYSBBcmNoaXZvPk9wY2lvbmVzPkF2YW56YWRhcz5TZXBhcmFkb3IgZGVjaW1hbCwgeSBwb25nYSDigJwu4oCdPiBBY2VwdGFyLiAqKg0KDQozLglDb24gc3VzIGRhdG9zIG9yZ2FuaXphZG9zIGluaWNpZSBSc3R1ZGlvLiBBYnJhIHVuIG51ZXZvIHNjcmlwdDogRmlsZT4gTmV3IEZpbGU+IFJzY3JpcHQuDQoNCjQuCUxsYW1lIGxhcyBsaWJyZXLDrWFzIGEgdXRpbGl6YXIuIEVuIGVzdGUgY2FzbywgcGFyYSBlc3RlIHRhbGxlciwgdXNhcmVtb3MgbGFzIGxpYnJlcsOtYXM6IA0KDQpgYGB7cn0NCmxpYnJhcnkocmVhZHhsKSANCmxpYnJhcnkoYWdyaWNvbGFlKQ0KbGlicmFyeShjYXIpIA0KbGlicmFyeShjYXJEYXRhKSANCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkoUkNvbG9yQnJld2VyKSAjT3BjaW9uYWwNCmBgYA0KKipOb3RhOiBTaSBubyBsYXMgdGllbmUgaW5zdGFsYWRhcyBkaXLDrWphc2UgYSBUb29sPiBJbnN0YWxsIFBhY2thZ2VzLCBpbnNlcnRlIGxvcyBub21icmVzIGRlIGxhcyBsaWJyZXLDrWFzIGEgZGVzY2FyZ2FyIHNlcGFyYWRhcyBwb3IgY29tYSBvIGVzcGFjaW8uIEVsIHByb2dyYW1hIHRhcmRhcsOhIHVub3MgbWludXRvcyBlbiBpbnN0YWxhcmxvcy4qKiANCg0KDQo1LglQcm9jZWRhIGEgc3ViaXIgbG9zIGRhdG9zIGRlbCBFeGNlbCwgIGTDoW5kb2xlIHVuIG5vbWJyZQ0KYGBge3J9DQpUYXNhUjwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL0p1bGlhbmEgTWlyYW5kYS9Eb2N1bWVudHMvVW5pdmVyc2lkYWQvVEVTSVMvUkVTVUxUQURPUy9SL1Jlc3BpcmFjaW9uLnhsc3giKQ0KYGBgDQo2LiBWaXN1YWxpY2UgdW4gcmVzdW1lbiBkZSBzdXMgZGF0b3M6IA0KYGBge3J9DQpzdW1tYXJ5KFRhc2FSKQ0KYGBgDQo3LiBFc3RhYmxlemNhIGxvcyBkw61hcyBkZXNwdcOpcyBkZSBjb3NlY2hhIChEREMpIGNvbW8gZmFjdG9yDQpgYGB7cn0NClRhc2FSJEREQz1hcy5mYWN0b3IoVGFzYVIkRERDKQ0KYGBgDQo4LiBFc3RhYmxlemNhIGVsIG1vZGVsbyBwYXJhIHVuIERDQSBzaW1wbGUgeSBnZW5lcmUgZWwgYW7DoWxpc2lzIGRlIHZhcmlhbnphIA0KYGBge3J9DQpUUmFub3Y9bG0oVGFzYVIkVFJ+VGFzYVIkRERDKQ0KYW5vdmEoVFJhbm92KQ0KYGBgDQoqKsK/QSBxdWUgaGFjZSByZWZlcmVuY2lhIGNhZGEgdW5vIGRlIGxvcyBpdGVtcyBkZSBsYSB0YWJsYT8gwr9xdcOpIHNlIHB1ZWRlIGluZmVyaXIgZGUgZXN0YSBpbmZvcm1hY2nDs24/IMK/cXXDqSBjcml0ZXJpbyB1dGlsaXrDsyBwYXJhIGxsZWdhciBhIGVzYSBjb25jbHVzacOzbj8gKioNCg0KOS4gUmVhbGljZSBsb3MgZ3LDoWZpY29zIGV4cGxvcmF0b3Jpb3MgZGUgcmVzaWR1b3MgcGFyYSBjb21wcm9iYWNpw7NuIGRlIHN1cHVlc3RvcyBkZWwgbW9kZWxvDQoNCmBgYHtyfQ0KaGlzdChUUmFub3YkcmVzaWR1YWxzKQ0KYm94cGxvdChUYXNhUiRUUn5UYXNhUiREREMsIG1haW49IlRBU0EgUkVTUElSQVRPUklBIiwgeGxhYj0iRERDIiwgeWxhYj0iVFIiLGNvbD00KSMgQm94IHBsb3QgcG9yIHRyYXRhbWllbnRvcw0KYm94cGxvdChUUmFub3YkcmVzaWR1YWxzflRhc2FSJEREQyxtYWluPSJSZXNpZHVhbGVzIGRlbCBtb2RlbG8iLGNvbD00KQ0KYGBgDQoNCioqwr9Dw7NtbyBkZXNjcmliaXLDrWEgZWwgY29tcG9ydGFtaWVudG8gZGUgbG9zIHJlc2lkdW9zIGVuIGVsIGhpc3RvZ3JhbWE/IMK/RXMgdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsPyDCv1F1w6kgZGlmZXJlbmNpYSBlbmN1ZW50cmEgZW50cmUgZWwgYm94cGxvdCBwb3IgdHJhdGFtaWVudG9zIHkgZWwgZGUgcmVzaWR1b3MgZGVsIG1vZGVsbz8gwr9RdcOpIGluZm9ybWFjacOzbiBwdWVkZSBpbmZlcmlyIGRlIGVzdGFzIGdyYWZpY2FzIGNvbiByZXNwZWN0byBhIGxvcyBzdXB1ZXN0b3MgZGVsIG1vZGVsbz8qKg0KDQpgYGB7cn0NCiMjI0dyw6FmaWNvcyBkZSB2YWxpZGFjacOzbiBkZSBzdXB1ZXN0b3Mgc29icmUgcmVzaWR1YWxlcyMjIw0Kc3BsaXQuc2NyZWVuKGMoMiwyKSkNCnNjcmVlbigxKQ0KIyBncsOhZmljbyBkZSByZXNpZHVhbGVzIHZzIHZhbG9yZXMgYWp1c3RhZG9zDQpwbG90KFRSYW5vdiRmaXR0ZWQudmFsdWVzLFRSYW5vdiRyZXNpZHVhbHMsbWFpbj0iUmVzaWR1YWxzIHZzLiBGaXR0ZWQiLCBwY2g9MjApDQphYmxpbmUoaD0wLGx0eT0yKQ0Kc2NyZWVuKDIpDQojIGdyw6FmaWNvIGRlIHJlc2lkdWFsZXMgdnMgbml2ZWxlcyBkZSB0cmF0YW1pZW50b3MNCnBsb3QoVGFzYVIkRERDLFRSYW5vdiRyZXNpZHVhbHMsbWFpbj0iUmVzaWR1YWxzIHZzLiBMZXZlbHMiKSAgIA0Kc2NyZWVuKDMpDQojIGdyw6FmaWNvIGRlIHJlc2lkdWFsZXMgdnMgdmFsb3JlcyBlbiBlbCB0aWVtcG8NCnBsb3QoMToxMDAsVFJhbm92JHJlc2lkdWFscywgbWFpbj0iUmVzaWR1YWxzIHZzLiBUaW1lIG9yZGVyIixwY2g9MjApICANCmFibGluZShoPTAsbHR5PTIpDQpzY3JlZW4oNCkNCg0KcXFub3JtKFRSYW5vdiRyZXNpZHVhbHMscGNoPTIwKSAgDQpxcWxpbmUoVFJhbm92JHJlc2lkdWFscykgIyBsaW5lYSBkZSBwcm9iYWJpbGlkYWQgbm9ybWFsIGdyw6FmaWNvIGRlIHJlc2lkdWFsZXMgUS1RDQoNCmBgYA0KDQoNCjEwLiBDb21wcnVlYmUgbG9zIHN1cHVlc3RvcyBkZWwgbW9kZWxvIGNvbiBsYXMgcHJ1ZWJhcyBkZSBub3JtYWxpZGFkIHkgaG9tb2NlZGFzdGljaWRhZC4gDQoNCmBgYHtyfQ0KIyMjIHBydWViYSBzaGFwaXJvIHBydWViYSBkZSBub3JtYWxpZGFkICMjIw0Kc2hhcGlyby50ZXN0KFRSYW5vdiRyZXNpZHVhbHMpDQoNCiMjIyBwcnVlYmEgS29sbW9nb3Jvdi1TbWlybm92IHBydWViYSBkZSBub3JtYWxpZGFkICMjIw0Ka3MudGVzdChUUmFub3YkcmVzaWR1YWxzLCAicG5vcm0iLCBtZWFuKFRSYW5vdiRyZXNpZHVhbHMpLCBzZChUUmFub3YkcmVzaWR1YWxzKSkNCg0KIyMjIHBydWViYSBiYXJ0bGV0dCBwcnVlYmEgZGUgaG9tb2NlZGFzdGljaWRhZCAjIyMNCmJhcnRsZXR0LnRlc3QoVFJhbm92JHJlc2lkdWFscyxUYXNhUiREREMpDQoNCmBgYA0KKirCv1F1w6kgcHVlZGUgaW5mZXJpciBkZSBsYXMgcC12YWxvciBkZSBsYXMgcHJ1ZWJhcz8gwr9IYXkgbm9ybWFsaWRhZCBkZSBsb3MgZGF0b3M/IMK/SGF5IGhvbW9jZWRhc3RpY2lkYWQ/ICoqDQoNCg0KMTEuIFJlYWxpY2UgbGEgcHJ1ZWJhIGRlIHR1a2V5IHBhcmEgdmVyaWZpY2FyIGN1YWxlcyBzb24gbGVzIHRyYXRhbWllbnRvcyAoRMOtYXMpIHByZXNlbnRhbiBkaWZlcmVuY2lhcyBzaWduaWZpY2F0aXZhcyBjb24gcmVzcGVjdG8gYSBsYSB2YXJpYWJsZSBkZSB0YXNhIHJlc3BpcmF0b3JpYQ0KYGBge3J9DQpIU0QudGVzdChUUmFub3YsIlRhc2FSJEREQyIsY29uc29sZSA9IFQpDQpgYGANCioqwr9IYXkgZGlmZXJlbmNpYXMgc2lnbmlmaWNhdGl2YXM/IMK/RW50cmUgY3VhbGVzIHRyYXRhbWllbnRvcz8gwr9Dw7NtbyBlc3RlIHJlc3VsdGFkbyBzZSByZWxhY2lvbmEgY29uIGVsIEFOT1ZBIHJlYWxpemFkbyBwcmV2aWFtZW50ZT8qKg0KDQoxMi4gUmVhbGljZSBsYSBncsOhZmljYSBUYXNhIFJlc3BpcmF0b3JpYSB2cy4gRERDIHF1ZSBpbmNsdXlhIGxhcyBkaWZlcmVuY2lhcyBzaWduaWZpY2F0aXZhcy4NCmBgYHtyfQ0KVFI9Ym94cGxvdChUYXNhUiRUUn5UYXNhUiREREMsICAgbWFpbiA9ICJUYXNhIFJlc3BpcmF0b3JpYSIsDQogICAgICAgICAgIHlsYWIgPSAibWcgQ08yICoga2ctMSAqIGgtMSIsDQogICAgICAgICAgIHhsYWIgPSAiRMOtYXMgZGVzcHVlcyBkZSBjb3NlY2hhIiwgeWxpbT1jKDAsODQpLCAgY29sPWJyZXdlci5wYWwobiA9IDgsIG5hbWUgPSAiU2V0MiIpKQ0KdGV4dCgxLDQxLGMoImUiKSkNCnRleHQoMiw1NCxjKCJkZSIpKQ0KdGV4dCgzLDU0LGMoImJjZCIpKQ0KdGV4dCg0LDc3LGMoImEiKSkNCnRleHQoNSw4NCxjKCJhIikpDQp0ZXh0KDYsNzAsYygiYWIiKSkNCnRleHQoNyw3MCxjKCJiY2QiKSkNCnRleHQoOCw2NSxjKCJiY2QiKSkNCnRleHQoOSw2MyxjKCJiY2QiKSkNCnRleHQoMTAsNjMsYygiY2QiKSkNCg0KYGBgDQoNCjEzLiBBaG9yYSB2YW1vcyBhIHZlciB1bmEgdmFyaWFibGUgZGlmZXJlbnRlIGVuIGxhIHF1ZSBsb3Mgc3VwdWVzdG9zIG5vIHNlIGN1bXBsZW4geSBlcyBuZWNlc2FyaW8gcmVhbGl6YXIgdW5hIHRyYW5zZm9ybWFjacOzbiBkZSBsb3MgZGF0b3MuIFBhcmEgZXNvIG9yZ2FuaWNlIGxvcyBkYXRvcyBwYXJhIGxhIHZhcmlhYmxlIGRlIFDDqXJkaWRhIGRlIFBlc28gRnJlc2NvIGVuIGNvbHVtbmFzIHkgbGxhbWUgZWwgYXJjaGl2byBkZSBleGNlbCBkZXNkZSBSLg0KYGBge3J9DQpQZXNvX0ZyZXNjbzwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzL0p1bGlhbmEgTWlyYW5kYS9Eb2N1bWVudHMvVW5pdmVyc2lkYWQvVEVTSVMvUkVTVUxUQURPUy9SL1BlcmRpZGFfcGVzb19mcmVzY28ueGxzeCIpDQpQZXNvX0ZyZXNjbw0Kc3VtbWFyeShQZXNvX0ZyZXNjbykNCmBgYA0KDQoxNC4gRGV0ZXJtaW5lIGVsIHBlc28gZnJlc2NvIGNvbW8gdW4gZmFjdG9yDQpgYGB7cn0NCiMjIyBFbCB0cmF0YW1pZW50byBkZWJlIHNlciB1biBmYWN0b3IgIyMjIw0KUGVzb19GcmVzY28kRERDPWFzLmZhY3RvcihQZXNvX0ZyZXNjbyREREMpDQpgYGANCg0KDQoxNS4gQ3JlZSBlbCBtb2RlbG8geSByZWFsaWNlIGVsIGFuw6FsaXNpcyBkZSB2YXJpYW56YQ0KYGBge3J9DQpQUEZhbm92PC1hb3YoUGVzb19GcmVzY28kUFBGflBlc29fRnJlc2NvJEREQykNCnN1bW1hcnkoUFBGYW5vdikNCmBgYA0KKirCv1F1w6kgc2UgcHVlZGUgaW5mZXJpciBkZSBlc3RhIGluZm9ybWFjacOzbj8gwr9xdcOpIGNyaXRlcmlvIHV0aWxpesOzIHBhcmEgbGxlZ2FyIGEgZXNhIGNvbmNsdXNpw7NuPyoqDQogDQogDQogMTYuIFZlcmlmaXF1ZSBsb3Mgc3VwdWVzdG9zIGNvbiBsYXMgcHJ1ZWJhcyBkZSBub3JtYWxpZGFkIHkgaG9tb2NlZGFzdGljaWRhZA0KIA0KYGBge3J9DQojIyMgcHJ1ZWJhIHNoYXBpcm8gcHJ1ZWJhIGRlIG5vcm1hbGlkYWQgIyMjDQpzaGFwaXJvLnRlc3QoUFBGYW5vdiRyZXNpZHVhbHMpDQoNCiMjIyBwcnVlYmEgS29sbW9nb3Jvdi1TbWlybm92IHBydWViYSBkZSBub3JtYWxpZGFkICMjIw0Ka3MudGVzdChQUEZhbm92JHJlc2lkdWFscywgInBub3JtIiwgbWVhbihQUEZhbm92JHJlc2lkdWFscyksIHNkKFBQRmFub3YkcmVzaWR1YWxzKSkNCg0KIyMjIHBydWViYSBkZSBob21vZ2VuZWlkYWQgZGUgdmFyaWFuemFzICMjIyMNCmJhcnRsZXR0LnRlc3QoUFBGYW5vdiRyZXNpZHVhbHMsUGVzb19GcmVzY28kRERDKQ0KDQpgYGANCioqwr9TZSBjdW1wbGVuIGxvcyBzdXB1ZXN0b3M/IMK/cXXDqSBjcml0ZXJpbyB1dGlsaXrDsyBwYXJhIGxsZWdhciBhIGVzYSBjb25jbHVzacOzbj8qKg0KIA0KIDE3LiBJbnRlbnRlIHRyYW5zZm9ybWFyIGxvcyBkYXRvcyBjb24gdHJhbnNmb3JtYWNpb25lcyBjb211bmVzIGNvbW8gbGEgcmHDrXogY3VhZHJhZGEsIGxvZ2FyaXRtbywgZXRjLiBlIGludGVudGUgY29tcHJvYmFyIG51ZXZhbWVudGUgbG9zIHN1cHVlc3Rvcy4gUGFyYSBlc28gZGViZSBtb2RpZmljYXIgZWwgRXhjZWwgY3JlYWRvIHkgYcOxYWRpciB1bmEgbnVldmEgY29sdW1uYSBjb24gbGFzIHZhcmlhYmxlcyB0cmFuc2Zvcm1hZGFzLCBwb3IgZWplbXBsbywgYSBsYSAxLzIgKGxhIHJhw616IGN1YWRyYWRhKS4gUmVwaXRhIGVsIHByb2Nlc28gZGVsIHB1bnRvIDEzIGFsIDE2IGRlIGVzdGUgdGFsbGVyLiANCiAgDQpgYGB7cn0NClBQRjEuMmFub3Y8LWFvdihQZXNvX0ZyZXNjbyRQUEYxLjJ+UGVzb19GcmVzY28kRERDKQ0Kc3VtbWFyeShQUEYxLjJhbm92KQ0KDQojIyMgcHJ1ZWJhIHNoYXBpcm8gcHJ1ZWJhIGRlIG5vcm1hbGlkYWQgIyMjDQpzaGFwaXJvLnRlc3QoUFBGMS4yYW5vdiRyZXNpZHVhbHMpDQoNCiMjIyBwcnVlYmEgS29sbW9nb3Jvdi1TbWlybm92IHBydWViYSBkZSBub3JtYWxpZGFkICMjIw0Ka3MudGVzdChQUEYxLjJhbm92JHJlc2lkdWFscywgInBub3JtIiwgbWVhbihQUEYxLjJhbm92JHJlc2lkdWFscyksIHNkKFBQRjEuMmFub3YkcmVzaWR1YWxzKSkNCg0KIyMjIHBydWViYSBkZSBob21vZ2VuZWlkYWQgZGUgdmFyaWFuemFzICMjIyMNCmJhcnRsZXR0LnRlc3QoUFBGMS4yYW5vdiRyZXNpZHVhbHMsUGVzb19GcmVzY28kRERDKQ0KDQoNCg0KYGBgDQogDQogKirCv01lam9yYXJvbiBsb3MgdmFsb3JlcyBkZSBsb3Mgc3VwZXVzdG9zPyDCv1NlIGN1bXBsZW4/KioNCiANCiAxOC4gSW1wbGVtZW50ZSBlbCBtw6l0b2RvIEJveC1Db3ggcGFyYSBvYnRlbmVyIGVsIGxhYmRhIMOzcHRpbW8gcGFyYSBsYSB0cmFuc2Zvcm1hY2nDs24gZGUgbG9zIGRhdG9zLg0KYGBge3J9DQpkYXRvczwtZGF0YS5mcmFtZShQZXNvX0ZyZXNjbyRQUEYsUGVzb19GcmVzY28kRERDKQ0KYmMxPC1ib3hjb3goUGVzb19GcmVzY28kUFBGflBlc29fRnJlc2NvJEREQywgbGFtYmRhID0gc2VxKC0yLCAzLCAxLzUpLCBkYXRhPWRhdG9zLCBwbG90aXQgPSBUUlVFLA0KICAgICAgICAgICBlcHMgPSAxLzUwICwgeGxhYiA9IGV4cHJlc3Npb24obGFtYmRhKSwgeWxhYiA9ICJsb2ctTGlrZWxpaG9vZCIpDQpzdW1tYXJ5KHBvd2VyVHJhbnNmb3JtKFBlc29fRnJlc2NvJFBQRn5QZXNvX0ZyZXNjbyREREMpKQ0KDQpgYGANCiAqKsK/UXXDqSBtdWVzdHJhIGxhIGdyw6FmaWNhPyDCv1F1w6kgdmFsb3IgbGFtYmRhIHNlIG9idGllbmU/KioNCiANCiAxOS4gUmVhbGljZSBsYSB0cmFuc2Zvcm1hY2nDs24gZGUgbG9zIGRhdG9zIGNvbiBzdSBudWV2byB2YWxvciBsYW1iZGEuIE51ZXZhbWVudGUgbW9kaWZpcXVlIGVsIGV4Y2VsIG9yaWdpbmFsIHkgdnVlbHZhIGEgY2FyZ2FyIGxvcyBkYXRvcyANCmBgYHtyfQ0KIyNEYXRvcyB0cmFuc2Zvcm1hZG9zIF4oMC4wODI4KSMjIyMjIw0KDQpQUEZib3hhbm92PC1hb3YoUGVzb19GcmVzY28kUFBGX0JPWH5QZXNvX0ZyZXNjbyREREMpDQpzdW1tYXJ5KFBQRmJveGFub3YpDQoNCiMjIyBwcnVlYmEgc2hhcGlybyBwcnVlYmEgZGUgbm9ybWFsaWRhZCAjIyMNCnNoYXBpcm8udGVzdChQUEZib3hhbm92JHJlc2lkdWFscykNCg0KIyMjIHBydWViYSBLb2xtb2dvcm92LVNtaXJub3YgcHJ1ZWJhIGRlIG5vcm1hbGlkYWQgIyMjDQprcy50ZXN0KFBQRmJveGFub3YkcmVzaWR1YWxzLCAicG5vcm0iLCBtZWFuKFBQRmJveGFub3YkcmVzaWR1YWxzKSwgc2QoUFBGYm94YW5vdiRyZXNpZHVhbHMpKQ0KDQojIyMgcHJ1ZWJhIGRlIGhvbW9nZW5laWRhZCBkZSB2YXJpYW56YXMgIyMjIw0KYmFydGxldHQudGVzdChQUEZib3hhbm92JHJlc2lkdWFscyxQZXNvX0ZyZXNjbyREREMpDQoNCg0KDQpgYGANCiAqKsK/RWwgdmFsb3IgbGFtYmRhIHBlcm1pdGnDsyBjb3JyZWdpciBsb3Mgc3VwdWVzdG9zIGRlbCBtb2RlbG8/IMK/Q29uIHF1w6kgY3JpdGVyaW8gbGxlZ8OzIGEgZXNhIGNvbmNsdXNpw7NuPyoqDQogDQogMjAuIENvbiBsb3Mgc3VwdWVzdG9zIGN1bXBsaWRvcywgcmVhbGljZSBlbCBhbsOhbGlzaXMgZGUgdmFyaWFuemEgY29uIGxvcyBkYXRvcyB0cmFuc2Zvcm1hZG9zDQogDQpgYGB7cn0NCkhTRC50ZXN0KFBQRmJveGFub3YsIlBlc29fRnJlc2NvJEREQyIsY29uc29sZSA9IFQpDQpgYGANCjIxLiBHcmFmaXF1ZSBsb3MgcmVzdWx0YWRvcw0KDQpgYGB7cn0NClBQRmc9Ym94cGxvdChQZXNvX0ZyZXNjbyRQUEZ+UGVzb19GcmVzY28kRERDLCAgIG1haW4gPSAiUMOpcmRpZGEgcGVzbyBmcmVzY28iLA0KICAgICAgICAgIHlsYWIgPSAiJSBQw6lyZGlkYSBwZXNvIGZyZXNjbyIsDQogICAgICAgICAgeGxhYiA9ICJEw61hcyBkZXNwdWVzIGRlIGNvc2VjaGEiLCBjb2w9YnJld2VyLnBhbChuID0gOCwgbmFtZSA9ICJTZXQyIikpDQp0ZXh0KDEsMixjKCJnIikpDQp0ZXh0KDIsNCxjKCJmIikpDQp0ZXh0KDMsNixjKCJlIikpDQp0ZXh0KDQsNy40LGMoImQiKSkNCnRleHQoNSw5LGMoImMiKSkNCnRleHQoNiwxMSxjKCJiYyIpKQ0KdGV4dCg3LDEyLGMoImFiIikpDQp0ZXh0KDgsMTMsYygiYSIpKQ0KdGV4dCg5LDE0LGMoImEiKSkNCmBgYA0KIyMgKipEQ0EgY29uIFN1Ym11ZXN0cmVvKioNCg0KMjIuIFBhcmEgZXN0ZSBhbsOhbGlzaXMgc2UgdXNhcsOhIGxhIHZhcmlhYmxlIGRlIEZpcm1lemEuIE51ZXZhbWVudGUgb3JnYW5pY2UgbGFzIHZhcmlhYmxlcyBkZSBmb3JtYSBxdWUgcXVlZGVuIGVuIGNvbHVtbmFzIGRlIEREQywgRmlybWV6YSB5ICoqbXVlc3RyYSoqLCBlc3RhIMO6bHRpbWEgZW4gZXN0ZSBjYXNvIGNvcnJlc3BvbmRlIGEgbG9zIHZhbG9yZXMgZGVsIHN1Ym11ZXN0cmVvIChtZWRpZGFzIGhlY2hhcyBhbCBtaXNtbyBmcnV0bykuIFVuYSB2ZXogY3JlYWRvIGVsIEV4Y2VsLCBsbGFtZSBlbCBkb2N1bWVudG8gZGVzZGUgUi4gDQpgYGB7cn0NClRleHR1cmE8LSByZWFkX2V4Y2VsKCJDOi9Vc2Vycy9KdWxpYW5hIE1pcmFuZGEvRG9jdW1lbnRzL1VuaXZlcnNpZGFkL1RFU0lTL1JFU1VMVEFET1MvUi9UeHQueGxzeCIpDQpUZXh0dXJhDQpzdW1tYXJ5KFRleHR1cmEpDQpgYGANCjIzLkVzdGFibGV6Y2EgdGFudG8gbG9zIGVzdGFkb3MgcG9zY29zZWNoYSBjb21vIGxhcyBtZWRpZGFzIGRlbCBzdWJtdWVzdHJlbyBjb21vIGZhY3RvcmVzDQoNCg0KYGBge3J9DQpFU1RBRE88LSBhcy5mYWN0b3IoVGV4dHVyYSREREMpDQpNVUVTVFJBPC0gYXMuZmFjdG9yKFRleHR1cmEkTVVFU1RSQSkgDQpgYGANCjI0LiBDcmVlIGVsIG1vZGVsbyBlc3RhZMOtc3RpY28gcGFyYSB1biBEQ0EgY29uIHN1Ym11ZXN0cmVvIA0KYGBge3J9DQpGSVJNZGNhMjwtYW92KFRleHR1cmEkRklSTX5FU1RBRE8rTVVFU1RSQSVpbiVFU1RBRE8pDQpzdW1tYXJ5KEZJUk1kY2EyKQ0KYGBgDQoyNS4gQ3JlZSBsb3MgcmVzaWR1b3MgZGVsIG1vZGVsbyB5IGRldGVybWluZSBzaSBzZSBjdW1wbGVuIGxvcyBzdXB1ZXN0b3MNCg0KYGBge3J9DQpyZXNGSVJNPC1GSVJNZGNhMiRyZXNpZHVhbHMgI1JFU0lEVU9TIA0KcmVzRklSTQ0Kc2hhcGlyby50ZXN0KHJlc0ZJUk0pDQpiYXJ0bGV0dC50ZXN0KHJlc0ZJUk0sRVNUQURPKQ0Ka3MudGVzdChGSVJNZGNhMiRyZXNpZHVhbHMsICJwbm9ybSIsIG1lYW4oRklSTWRjYTIkcmVzaWR1YWxzKSwgc2QoRklSTWRjYTIkcmVzaWR1YWxzKSkNCmBgYA0KMjYuIENvbnRpbnVlIGVsIGFuw6FsaXNpcyBkZXRlcm1pbmFuZG8gbGEgdHJhbnNmb3JtYWNpw7NuIGFwcm9waWFkYSBwYXJhIGVsIGN1YWwgc2UgY3VtcGxhbiBsb3Mgc3VwdWVzdG9zLiBEZXRlcm1pbmUgbGFzIGRpZmVyZW5jaWFzIHNpZ25maWNhdGl2YXMgZW50cmUgbG9zIGVzdGFkb3MgcG9zY29zZWNoYS4gR3JhZmlxdWUgbG9zIHJlc3VsdGFkb3MuDQo=