library(readxl)

df <- read_excel("~/ANDREA/Universidad/metodos multivariados/Clase 7/Analisis Estadistico Datos Laboratorio 21.08.24.xlsx", 
    sheet = "Consolidado proximal MANOVA")

View(df)
#### revisar que tan balanceado estan mis tratamientos
table(df$Tto)

T1 T2 T3 T4 T5 T6 T7 
 9  9  9  9  9  9  9 

Matriz de correlación de Pearson

library(corrplot)

# seleccionar solo variables numericas
df_num <- df[sapply(df, is.numeric)]

# matriz de correlacion
cor_matrix <- cor(df_num, use = "complete.obs", method = "spearman")### o pearson

# grafica con valores de correlacion
corrplot(cor_matrix,
         method = "color",
         type = "upper",
         tl.col = "black",
         tl.srt = 45,
         addCoef.col = "black",   # muestra el valor de r
         number.cex = 0.8)        # tamaño del numero

# convertir Tto en factor
df$Tto <- as.factor(df$Tto)

MANOVA

# 1. Asegurarnos de que el Tratamiento sea un factor (categoría)
df$Tto <- as.factor(df$Tto)

# 2. Unir las variables dependientes en una sola matriz
# Usamos cbind() para "pegar" las columnas que queremos analizar juntas
variables_respuesta <- cbind(df$Grasas, df$Humedad, df$Proteina, df$Cenizas)

# 3. Ajustar el modelo MANOVA
# La fórmula significa: "Analizar el conjunto de variables en función del Tratamiento"
modelo_manova <- manova(variables_respuesta ~ Tto, data = df)

# 4. Ver el resultado global del MANOVA
# Por defecto, R usa la prueba Traza de Pillai (Pillai's trace), que es la más robusta
summary(modelo_manova)
          Df  Pillai approx F num Df den Df   Pr(>F)   
Tto        6 0.68727   1.9363     24    224 0.007133 **
Residuals 56                                           
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Existe evidencia de que al menos uno de los tratamientos presenta una combinación promedio de grasas, humedad, proteína y cenizas diferente de la de los demás tratamientos.


# Extraer la matriz de residuales del MANOVA
residuales_manova <- residuals(modelo_manova)

# Ver las primeras filas
head(residuales_manova)
       [,1]        [,2]       [,3]         [,4]
1 -1.117767 -1.70445140 -0.3144008  0.008991832
2  2.831233  0.04888266  0.2395623 -0.048837767
3  7.519033 -1.41858384  0.6670862  0.008084027
4  2.650233  0.40893784  0.5389723  0.017541847
5 -4.826367  0.58546408  0.7482227 -0.002550635
6 -2.346867  0.33654203  0.7293994 -0.007978019
# Revisar dimensiones
dim(residuales_manova)
[1] 63  4
colnames(residuales_manova) <- c(
  "Grasas",
  "Humedad",
  "Proteina",
  "Cenizas"
)

head(residuales_manova)
     Grasas     Humedad   Proteina      Cenizas
1 -1.117767 -1.70445140 -0.3144008  0.008991832
2  2.831233  0.04888266  0.2395623 -0.048837767
3  7.519033 -1.41858384  0.6670862  0.008084027
4  2.650233  0.40893784  0.5389723  0.017541847
5 -4.826367  0.58546408  0.7482227 -0.002550635
6 -2.346867  0.33654203  0.7293994 -0.007978019

Prueba de normalidad multivariada

library(mvnormtest)
# =========================================================
# NORMALIDAD MULTIVARIANTE DE LOS RESIDUALES DEL MANOVA
# =========================================================

# Extraer residuales
residuales_manova <- residuals(modelo_manova)

# Asignar nombres
colnames(residuales_manova) <- c(
  "Grasas",
  "Humedad",
  "Proteina",
  "Cenizas"
)

# Revisar la matriz
head(residuales_manova)
     Grasas     Humedad   Proteina      Cenizas
1 -1.117767 -1.70445140 -0.3144008  0.008991832
2  2.831233  0.04888266  0.2395623 -0.048837767
3  7.519033 -1.41858384  0.6670862  0.008084027
4  2.650233  0.40893784  0.5389723  0.017541847
5 -4.826367  0.58546408  0.7482227 -0.002550635
6 -2.346867  0.33654203  0.7293994 -0.007978019
dim(residuales_manova)
[1] 63  4
# Instalar una sola vez
# install.packages("mvnormtest")

library(mvnormtest)

# mshapiro.test requiere:
# filas = variables
# columnas = observaciones
resultado_normalidad <- mshapiro.test(
  t(residuales_manova)
)

resultado_normalidad

    Shapiro-Wilk normality test

data:  Z
W = 0.9164, p-value = 0.0003942

La prueba multivariante de Shapiro-Wilk mostró que los residuales no siguen una distribución normal multivariante (p=0.0003942) a pesar de que W=0.9164 sugiere que la desviación de la normalidad no es extrema.

Comparación de matriz de varianza y covarianza de los residuales

library(biotools)

# Extraer los residuales del MANOVA
residuales_manova <- residuals(modelo_manova)

# Asignar nombres a las columnas
colnames(residuales_manova) <- c(
  "Grasas",
  "Humedad",
  "Proteina",
  "Cenizas"
)

# Comparar las matrices de varianzas y covarianzas
# de los residuales entre tratamientos
resultado_boxm_residuales <- boxM(
  residuales_manova,
  df$Tto
)

resultado_boxm_residuales

    Box's M-test for Homogeneity of Covariance Matrices

data:  residuales_manova
Chi-Sq (approx.) = 77.071, df = 60, p-value = 0.06803

No hay evidencia estadística suficiente para afirmar que las matrices de varianzas y covarianzas de los residuales sean diferentes entre los tratamientos.

Como conclusión, para estos datos no es recomendable realizar un MANOVA, dado que no se cumple el supuesto de normalidad multivariante, por lo cual se llevará a cabo la prueba de PERMANOVA.

PERMANOVA

De acuerdo con el articulo, para estos datos no todas las distancias tienen la misma pertinencia. La propuesta principal se realiza con la distancia euclídea sobre variables estandarizadas. Las demás servirán como análisis de sensibilidad para comprobar si la conclusión depende de la distancia elegida.

# =========================================================
# 1. PAQUETES
# =========================================================

library(vegan)
library(cluster)

# Tratamiento como factor
df$Tto <- as.factor(df$Tto)

# Seleccionar solamente las variables respuesta
Y <- df[, c(
  "Grasas",
  "Humedad",
  "Proteina",
  "Cenizas"
)]

# Estandarizar las variables
Y_z <- scale(Y)

# Comprobar que se creó correctamente
head(Y_z)
         Grasas    Humedad   Proteina    Cenizas
[1,] -0.2672462 -1.8028943 -1.3113283 -0.9431330
[2,]  0.4188379  0.1580559 -0.3687332 -1.8778252
[3,]  1.2332782 -1.4831765  0.3587196 -0.9578057
[4,]  0.3873916  0.5607460  0.1407275 -0.8049402
[5,] -0.9115641  0.7581751  0.4967772 -1.1296923
[6,] -0.4807853  0.4797777  0.4647485 -1.2174144
# Revisar medias y desviaciones estándar
round(colMeans(Y_z), 6)
  Grasas  Humedad Proteina  Cenizas 
       0        0        0        0 
apply(Y_z, 2, sd)
  Grasas  Humedad Proteina  Cenizas 
       1        1        1        1 
# Comprobar estructura
str(Y)
tibble [63 × 4] (S3: tbl_df/tbl/data.frame)
 $ Grasas  : num [1:63] 115 119 123 119 111 ...
 $ Humedad : num [1:63] 75.1 76.9 75.4 77.2 77.4 ...
 $ Proteina: num [1:63] 19 19.5 20 19.8 20 ...
 $ Cenizas : num [1:63] 1.08 1.03 1.08 1.09 1.07 ...
summary(Y)
     Grasas         Humedad         Proteina        Cenizas     
 Min.   :106.4   Min.   :74.33   Min.   :17.89   Min.   :1.025  
 1st Qu.:113.3   1st Qu.:76.13   1st Qu.:19.51   1st Qu.:1.099  
 Median :115.1   Median :76.77   Median :19.83   Median :1.135  
 Mean   :116.4   Mean   :76.73   Mean   :19.75   Mean   :1.141  
 3rd Qu.:119.1   3rd Qu.:77.29   3rd Qu.:20.10   3rd Qu.:1.172  
 Max.   :127.6   Max.   :78.73   Max.   :20.96   Max.   :1.348  
# Comprobar valores faltantes
colSums(is.na(Y))
  Grasas  Humedad Proteina  Cenizas 
       0        0        0        0 
# Conservar solamente filas completas
filas_completas <- complete.cases(Y, df$Tto)

Y <- Y[filas_completas, ]
grupo <- droplevels(df$Tto[filas_completas])

# Revisar nuevamente el balance
table(grupo)
grupo
T1 T2 T3 T4 T5 T6 T7 
 9  9  9  9  9  9  9 

La matriz multivariada contiene 63 observaciones completas y cuatro variables continuas. Presenta diferencias importantes de escala entre las variables, se recomienda usar distancia euclídea sobre datos estandarizados como análisis principal.

Construcción de distancias

# =========================================================
# 3. MATRICES DE DISTANCIA
# =========================================================

# Euclidea sin estandarizar
D_euclid_raw <- dist(
  Y,
  method = "euclidean"
)

# Euclidea estandarizada
D_euclid_z <- dist(
  Y_z,
  method = "euclidean"
)

# Manhattan estandarizada
D_manhattan_z <- dist(
  Y_z,
  method = "manhattan"
)

# Gower
D_gower <- cluster::daisy(
  Y,
  metric = "gower"
)

# Bray-Curtis
D_bray <- vegan::vegdist(
  Y,
  method = "bray"
)

# Hellinger + euclidea
Y_hellinger <- vegan::decostand(
  Y,
  method = "hellinger"
)

D_hellinger <- dist(
  Y_hellinger,
  method = "euclidean"
)
# =========================================================
# 4. PERMANOVA GLOBAL
# =========================================================

set.seed(123)

permanova_euclid_raw <- adonis2(
  D_euclid_raw ~ grupo,
  permutations = 9999
)

set.seed(123)

permanova_euclid_z <- adonis2(
  D_euclid_z ~ grupo,
  permutations = 9999
)

set.seed(123)

permanova_manhattan_z <- adonis2(
  D_manhattan_z ~ grupo,
  permutations = 9999
)

set.seed(123)

permanova_gower <- adonis2(
  D_gower ~ grupo,
  permutations = 9999
)

set.seed(123)

permanova_bray <- adonis2(
  D_bray ~ grupo,
  permutations = 9999
)

set.seed(123)

permanova_hellinger <- adonis2(
  D_hellinger ~ grupo,
  permutations = 9999
)

permanova_euclid_raw
Permutation test for adonis under reduced model
Permutation: free
Number of permutations: 9999

adonis2(formula = D_euclid_raw ~ grupo, permutations = 9999)
         Df SumOfSqs     R2      F Pr(>F)
Model     6    63.33 0.0298 0.2867 0.9478
Residual 56  2061.94 0.9702              
Total    62  2125.27 1.0000              
permanova_euclid_z
Permutation test for adonis under reduced model
Permutation: free
Number of permutations: 9999

adonis2(formula = D_euclid_z ~ grupo, permutations = 9999)
         Df SumOfSqs      R2      F Pr(>F)    
Model     6   48.093 0.19392 2.2454  7e-04 ***
Residual 56  199.907 0.80608                  
Total    62  248.000 1.00000                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
permanova_manhattan_z
Permutation test for adonis under reduced model
Permutation: free
Number of permutations: 9999

adonis2(formula = D_manhattan_z ~ grupo, permutations = 9999)
         Df SumOfSqs      R2      F Pr(>F)   
Model     6   139.48 0.19672 2.2858 0.0013 **
Residual 56   569.54 0.80328                 
Total    62   709.02 1.00000                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
permanova_gower
Permutation test for adonis under reduced model
Permutation: free
Number of permutations: 9999

adonis2(formula = D_gower ~ grupo, permutations = 9999)
         Df SumOfSqs      R2      F Pr(>F)   
Model     6  0.36244 0.17779 2.0182 0.0077 **
Residual 56  1.67610 0.82221                 
Total    62  2.03854 1.00000                 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
permanova_bray
Permutation test for adonis under reduced model
Permutation: free
Number of permutations: 9999

adonis2(formula = D_bray ~ grupo, permutations = 9999)
         Df  SumOfSqs     R2     F Pr(>F)
Model     6 0.0008041 0.0521 0.513 0.8528
Residual 56 0.0146306 0.9479             
Total    62 0.0154348 1.0000             
permanova_hellinger
Permutation test for adonis under reduced model
Permutation: free
Number of permutations: 9999

adonis2(formula = D_hellinger ~ grupo, permutations = 9999)
         Df  SumOfSqs      R2      F Pr(>F)
Model     6 0.0007867 0.06636 0.6634 0.7149
Residual 56 0.0110682 0.93364              
Total    62 0.0118549 1.00000              
extraer_permanova <- function(modelo, nombre_distancia) {

  data.frame(
    Distancia = nombre_distancia,
    Df = modelo$Df[1],
    SumSq = modelo$SumOfSqs[1],
    R2 = modelo$R2[1],
    Pseudo_F = modelo$F[1],
    p_value = modelo$`Pr(>F)`[1]
  )
}

tabla_permanova <- rbind(
  extraer_permanova(
    permanova_euclid_raw,
    "Euclidea sin estandarizar"
  ),
  extraer_permanova(
    permanova_euclid_z,
    "Euclidea estandarizada"
  ),
  extraer_permanova(
    permanova_manhattan_z,
    "Manhattan estandarizada"
  ),
  extraer_permanova(
    permanova_gower,
    "Gower"
  ),
  extraer_permanova(
    permanova_bray,
    "Bray-Curtis"
  ),
  extraer_permanova(
    permanova_hellinger,
    "Hellinger + Euclidea"
  )
)

tabla_permanova[
  order(tabla_permanova$p_value),
]

Evaluación de la dispersión multivariada PERMDISP

# =========================================================
# 6. PERMDISP
# =========================================================

evaluar_permdisp <- function(distancia, grupo, semillas = 123) {

  dispersion <- betadisper(
    distancia,
    grupo,
    type = "centroid"
  )

  set.seed(semillas)

  prueba <- permutest(
    dispersion,
    permutations = 9999
  )

  list(
    objeto = dispersion,
    resultado = prueba
  )
}

disp_euclid_raw <- evaluar_permdisp(
  D_euclid_raw,
  grupo
)

disp_euclid_z <- evaluar_permdisp(
  D_euclid_z,
  grupo
)

disp_manhattan_z <- evaluar_permdisp(
  D_manhattan_z,
  grupo
)

disp_gower <- evaluar_permdisp(
  D_gower,
  grupo
)

disp_bray <- evaluar_permdisp(
  D_bray,
  grupo
)

disp_hellinger <- evaluar_permdisp(
  D_hellinger,
  grupo
)

disp_euclid_raw$resultado

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 9999

Response: Distances
          Df Sum Sq Mean Sq      F N.Perm Pr(>F)
Groups     6  37.42  6.2365 0.5993   9999 0.7321
Residuals 56 582.80 10.4071                     
disp_euclid_z$resultado

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 9999

Response: Distances
          Df  Sum Sq Mean Sq      F N.Perm Pr(>F)   
Groups     6  6.2047 1.03412 3.1765   9999 0.0095 **
Residuals 56 18.2307 0.32555                        
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
disp_manhattan_z$resultado

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 9999

Response: Distances
          Df Sum Sq Mean Sq      F N.Perm Pr(>F)  
Groups     6 18.760  3.1266 2.8329   9999 0.0166 *
Residuals 56 61.807  1.1037                       
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
disp_gower$resultado

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 9999

Response: Distances
          Df   Sum Sq  Mean Sq      F N.Perm Pr(>F)  
Groups     6 0.048486 0.008081 2.5081   9999 0.0311 *
Residuals 56 0.180431 0.003222                       
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
disp_bray$resultado

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 9999

Response: Distances
          Df    Sum Sq    Mean Sq      F N.Perm Pr(>F)
Groups     6 0.0002356 3.9275e-05 0.6729   9999  0.676
Residuals 56 0.0032685 5.8366e-05                     
disp_hellinger$resultado

Permutation test for homogeneity of multivariate dispersions
Permutation: free
Number of permutations: 9999

Response: Distances
          Df     Sum Sq    Mean Sq      F N.Perm Pr(>F)
Groups     6 0.00033987 5.6646e-05 1.2224   9999 0.3104
Residuals 56 0.00259510 4.6341e-05                     
extraer_permdisp <- function(objeto, nombre_distancia) {

  tabla <- objeto$resultado$tab

  data.frame(
    Distancia = nombre_distancia,
    F_dispersion = tabla$F[1],
    p_dispersion = tabla$`Pr(>F)`[1]
  )
}

tabla_permdisp <- rbind(
  extraer_permdisp(
    disp_euclid_raw,
    "Euclidea sin estandarizar"
  ),
  extraer_permdisp(
    disp_euclid_z,
    "Euclidea estandarizada"
  ),
  extraer_permdisp(
    disp_manhattan_z,
    "Manhattan estandarizada"
  ),
  extraer_permdisp(
    disp_gower,
    "Gower"
  ),
  extraer_permdisp(
    disp_bray,
    "Bray-Curtis"
  ),
  extraer_permdisp(
    disp_hellinger,
    "Hellinger + Euclidea"
  )
)

tabla_permdisp
tabla_completa <- merge(
  tabla_permanova,
  tabla_permdisp,
  by = "Distancia"
)

tabla_completa[
  order(tabla_completa$p_value),
]
  • Con base en estos resultados, se detectaron diferencias multivariadas entre los tratamientos con distancia Euclídea estandarizada (PERMANOVA), pero también se encontraron diferencias en la dispersión interna de los grupos (PERMDISP). Por ello, la significancia del PERMANOVA no puede atribuirse exclusivamente a diferencias entre centroides. Estos resultados se observaron en la distancia de Manhattan estandarizada y Gower, siendo mas sensibles en la detección de las diferencias en comparación con el resto.

  • La Euclidea sin estandarizar mostró que las direncias de escala de las variables evaluadas fueron determinantes en los resultados obtenidos, ya que al elevar las diferencias al cuadrado, da mayor peso a unas variables con respecto a otras.

  • Manhattan estandarizada suma el valor absoluto de las diferencias multivariadas siendo altamente sensible a esta prueba a pesar de que se emplea principalmente en datos de clasificación, agrupamiento y análisis de datos con posibles valores extremos.

  • Gower es la distancia característica cuando se mezclan variables numéricas, ordinales y binarias, fue funcional para estos datos, debido a su ponderación el rango, lo que hace que la distancia maneje una escala similar entre variables.

  • Hellinger Euclidea no detectó diferencias porque transformó los datos en perfiles relativos por muestra, eliminando una gran parte de las diferencias absolutas que sí eran relevantes en el análisis estandarizado.

  • Bray-Curtis no detectó diferencias porque responde a diferencias relativas en perfiles de abundancia y no se ajusta bien a cuatro variables químicas con escalas y naturalezas diferentes.

LS0tDQp0aXRsZTogIk1BTk9WQSBZIFBFUk1BTk9WQSINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShyZWFkeGwpDQoNCmRmIDwtIHJlYWRfZXhjZWwoIn4vQU5EUkVBL1VuaXZlcnNpZGFkL21ldG9kb3MgbXVsdGl2YXJpYWRvcy9DbGFzZSA3L0FuYWxpc2lzIEVzdGFkaXN0aWNvIERhdG9zIExhYm9yYXRvcmlvIDIxLjA4LjI0Lnhsc3giLCANCiAgICBzaGVldCA9ICJDb25zb2xpZGFkbyBwcm94aW1hbCBNQU5PVkEiKQ0KDQpWaWV3KGRmKQ0KYGBgDQoNCg0KYGBge3J9DQojIyMjIHJldmlzYXIgcXVlIHRhbiBiYWxhbmNlYWRvIGVzdGFuIG1pcyB0cmF0YW1pZW50b3MNCnRhYmxlKGRmJFR0bykNCmBgYA0KDQojICpNYXRyaXogZGUgY29ycmVsYWNpw7NuIGRlIFBlYXJzb24qDQoNCmBgYHtyfQ0KbGlicmFyeShjb3JycGxvdCkNCg0KIyBzZWxlY2Npb25hciBzb2xvIHZhcmlhYmxlcyBudW1lcmljYXMNCmRmX251bSA8LSBkZltzYXBwbHkoZGYsIGlzLm51bWVyaWMpXQ0KDQojIG1hdHJpeiBkZSBjb3JyZWxhY2lvbg0KY29yX21hdHJpeCA8LSBjb3IoZGZfbnVtLCB1c2UgPSAiY29tcGxldGUub2JzIiwgbWV0aG9kID0gInNwZWFybWFuIikjIyMgbyBwZWFyc29uDQoNCiMgZ3JhZmljYSBjb24gdmFsb3JlcyBkZSBjb3JyZWxhY2lvbg0KY29ycnBsb3QoY29yX21hdHJpeCwNCiAgICAgICAgIG1ldGhvZCA9ICJjb2xvciIsDQogICAgICAgICB0eXBlID0gInVwcGVyIiwNCiAgICAgICAgIHRsLmNvbCA9ICJibGFjayIsDQogICAgICAgICB0bC5zcnQgPSA0NSwNCiAgICAgICAgIGFkZENvZWYuY29sID0gImJsYWNrIiwgICAjIG11ZXN0cmEgZWwgdmFsb3IgZGUgcg0KICAgICAgICAgbnVtYmVyLmNleCA9IDAuOCkgICAgICAgICMgdGFtYcOxbyBkZWwgbnVtZXJvDQpgYGANCg0KYGBge3J9DQojIGNvbnZlcnRpciBUdG8gZW4gZmFjdG9yDQpkZiRUdG8gPC0gYXMuZmFjdG9yKGRmJFR0bykNCmBgYA0KDQojICpNQU5PVkEqDQoNCmBgYHtyfQ0KIyAxLiBBc2VndXJhcm5vcyBkZSBxdWUgZWwgVHJhdGFtaWVudG8gc2VhIHVuIGZhY3RvciAoY2F0ZWdvcsOtYSkNCmRmJFR0byA8LSBhcy5mYWN0b3IoZGYkVHRvKQ0KDQojIDIuIFVuaXIgbGFzIHZhcmlhYmxlcyBkZXBlbmRpZW50ZXMgZW4gdW5hIHNvbGEgbWF0cml6DQojIFVzYW1vcyBjYmluZCgpIHBhcmEgInBlZ2FyIiBsYXMgY29sdW1uYXMgcXVlIHF1ZXJlbW9zIGFuYWxpemFyIGp1bnRhcw0KdmFyaWFibGVzX3Jlc3B1ZXN0YSA8LSBjYmluZChkZiRHcmFzYXMsIGRmJEh1bWVkYWQsIGRmJFByb3RlaW5hLCBkZiRDZW5pemFzKQ0KDQojIDMuIEFqdXN0YXIgZWwgbW9kZWxvIE1BTk9WQQ0KIyBMYSBmw7NybXVsYSBzaWduaWZpY2E6ICJBbmFsaXphciBlbCBjb25qdW50byBkZSB2YXJpYWJsZXMgZW4gZnVuY2nDs24gZGVsIFRyYXRhbWllbnRvIg0KbW9kZWxvX21hbm92YSA8LSBtYW5vdmEodmFyaWFibGVzX3Jlc3B1ZXN0YSB+IFR0bywgZGF0YSA9IGRmKQ0KDQojIDQuIFZlciBlbCByZXN1bHRhZG8gZ2xvYmFsIGRlbCBNQU5PVkENCiMgUG9yIGRlZmVjdG8sIFIgdXNhIGxhIHBydWViYSBUcmF6YSBkZSBQaWxsYWkgKFBpbGxhaSdzIHRyYWNlKSwgcXVlIGVzIGxhIG3DoXMgcm9idXN0YQ0Kc3VtbWFyeShtb2RlbG9fbWFub3ZhKQ0KYGBgDQpFeGlzdGUgZXZpZGVuY2lhIGRlIHF1ZSBhbCBtZW5vcyB1bm8gZGUgbG9zIHRyYXRhbWllbnRvcyBwcmVzZW50YSB1bmEgY29tYmluYWNpw7NuIHByb21lZGlvIGRlIGdyYXNhcywgaHVtZWRhZCwgcHJvdGXDrW5hIHkgY2VuaXphcyBkaWZlcmVudGUgZGUgbGEgZGUgbG9zIGRlbcOhcyB0cmF0YW1pZW50b3MuDQoNCmBgYHtyfQ0KDQojIEV4dHJhZXIgbGEgbWF0cml6IGRlIHJlc2lkdWFsZXMgZGVsIE1BTk9WQQ0KcmVzaWR1YWxlc19tYW5vdmEgPC0gcmVzaWR1YWxzKG1vZGVsb19tYW5vdmEpDQoNCiMgVmVyIGxhcyBwcmltZXJhcyBmaWxhcw0KaGVhZChyZXNpZHVhbGVzX21hbm92YSkNCg0KIyBSZXZpc2FyIGRpbWVuc2lvbmVzDQpkaW0ocmVzaWR1YWxlc19tYW5vdmEpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KY29sbmFtZXMocmVzaWR1YWxlc19tYW5vdmEpIDwtIGMoDQogICJHcmFzYXMiLA0KICAiSHVtZWRhZCIsDQogICJQcm90ZWluYSIsDQogICJDZW5pemFzIg0KKQ0KDQpoZWFkKHJlc2lkdWFsZXNfbWFub3ZhKQ0KYGBgDQojIyAqUHJ1ZWJhIGRlIG5vcm1hbGlkYWQgbXVsdGl2YXJpYWRhKg0KDQpgYGB7cn0NCmxpYnJhcnkobXZub3JtdGVzdCkNCmBgYA0KDQoNCmBgYHtyfQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgTk9STUFMSURBRCBNVUxUSVZBUklBTlRFIERFIExPUyBSRVNJRFVBTEVTIERFTCBNQU5PVkENCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiMgRXh0cmFlciByZXNpZHVhbGVzDQpyZXNpZHVhbGVzX21hbm92YSA8LSByZXNpZHVhbHMobW9kZWxvX21hbm92YSkNCg0KIyBBc2lnbmFyIG5vbWJyZXMNCmNvbG5hbWVzKHJlc2lkdWFsZXNfbWFub3ZhKSA8LSBjKA0KICAiR3Jhc2FzIiwNCiAgIkh1bWVkYWQiLA0KICAiUHJvdGVpbmEiLA0KICAiQ2VuaXphcyINCikNCg0KIyBSZXZpc2FyIGxhIG1hdHJpeg0KaGVhZChyZXNpZHVhbGVzX21hbm92YSkNCmRpbShyZXNpZHVhbGVzX21hbm92YSkNCg0KIyBJbnN0YWxhciB1bmEgc29sYSB2ZXoNCiMgaW5zdGFsbC5wYWNrYWdlcygibXZub3JtdGVzdCIpDQoNCmxpYnJhcnkobXZub3JtdGVzdCkNCg0KIyBtc2hhcGlyby50ZXN0IHJlcXVpZXJlOg0KIyBmaWxhcyA9IHZhcmlhYmxlcw0KIyBjb2x1bW5hcyA9IG9ic2VydmFjaW9uZXMNCnJlc3VsdGFkb19ub3JtYWxpZGFkIDwtIG1zaGFwaXJvLnRlc3QoDQogIHQocmVzaWR1YWxlc19tYW5vdmEpDQopDQoNCnJlc3VsdGFkb19ub3JtYWxpZGFkDQpgYGANCkxhIHBydWViYSBtdWx0aXZhcmlhbnRlIGRlIFNoYXBpcm8tV2lsayBtb3N0csOzIHF1ZSBsb3MgcmVzaWR1YWxlcyBubyBzaWd1ZW4gdW5hIGRpc3RyaWJ1Y2nDs24gbm9ybWFsIG11bHRpdmFyaWFudGUgKHA9MC4wMDAzOTQyKSBhIHBlc2FyIGRlIHF1ZSBXPTAuOTE2NCBzdWdpZXJlIHF1ZSBsYSBkZXN2aWFjacOzbiBkZSBsYSBub3JtYWxpZGFkIG5vIGVzIGV4dHJlbWEuDQoNCg0KIyMgKkNvbXBhcmFjacOzbiBkZSBtYXRyaXogZGUgdmFyaWFuemEgeSBjb3ZhcmlhbnphIGRlIGxvcyByZXNpZHVhbGVzKg0KDQpgYGB7cn0NCmxpYnJhcnkoYmlvdG9vbHMpDQoNCiMgRXh0cmFlciBsb3MgcmVzaWR1YWxlcyBkZWwgTUFOT1ZBDQpyZXNpZHVhbGVzX21hbm92YSA8LSByZXNpZHVhbHMobW9kZWxvX21hbm92YSkNCg0KIyBBc2lnbmFyIG5vbWJyZXMgYSBsYXMgY29sdW1uYXMNCmNvbG5hbWVzKHJlc2lkdWFsZXNfbWFub3ZhKSA8LSBjKA0KICAiR3Jhc2FzIiwNCiAgIkh1bWVkYWQiLA0KICAiUHJvdGVpbmEiLA0KICAiQ2VuaXphcyINCikNCg0KIyBDb21wYXJhciBsYXMgbWF0cmljZXMgZGUgdmFyaWFuemFzIHkgY292YXJpYW56YXMNCiMgZGUgbG9zIHJlc2lkdWFsZXMgZW50cmUgdHJhdGFtaWVudG9zDQpyZXN1bHRhZG9fYm94bV9yZXNpZHVhbGVzIDwtIGJveE0oDQogIHJlc2lkdWFsZXNfbWFub3ZhLA0KICBkZiRUdG8NCikNCg0KcmVzdWx0YWRvX2JveG1fcmVzaWR1YWxlcw0KYGBgDQpObyBoYXkgZXZpZGVuY2lhIGVzdGFkw61zdGljYSBzdWZpY2llbnRlIHBhcmEgYWZpcm1hciBxdWUgbGFzIG1hdHJpY2VzIGRlIHZhcmlhbnphcyB5IGNvdmFyaWFuemFzIGRlIGxvcyByZXNpZHVhbGVzIHNlYW4gZGlmZXJlbnRlcyBlbnRyZSBsb3MgdHJhdGFtaWVudG9zLiANCg0KQ29tbyBjb25jbHVzacOzbiwgcGFyYSBlc3RvcyBkYXRvcyBubyBlcyByZWNvbWVuZGFibGUgcmVhbGl6YXIgdW4gTUFOT1ZBLCBkYWRvIHF1ZSBubyBzZSBjdW1wbGUgZWwgc3VwdWVzdG8gZGUgbm9ybWFsaWRhZCBtdWx0aXZhcmlhbnRlLCBwb3IgbG8gY3VhbCBzZSBsbGV2YXLDoSBhIGNhYm8gbGEgcHJ1ZWJhIGRlIFBFUk1BTk9WQS4NCg0KDQojIyAqUEVSTUFOT1ZBKg0KDQpEZSBhY3VlcmRvIGNvbiBlbCBhcnRpY3VsbywgcGFyYSBlc3RvcyBkYXRvcyBubyB0b2RhcyBsYXMgZGlzdGFuY2lhcyB0aWVuZW4gbGEgbWlzbWEgcGVydGluZW5jaWEuIExhIHByb3B1ZXN0YSBwcmluY2lwYWwgc2UgcmVhbGl6YSBjb24gbGEgZGlzdGFuY2lhIGV1Y2zDrWRlYSBzb2JyZSB2YXJpYWJsZXMgZXN0YW5kYXJpemFkYXMuIExhcyBkZW3DoXMgc2Vydmlyw6FuIGNvbW8gYW7DoWxpc2lzIGRlIHNlbnNpYmlsaWRhZCBwYXJhIGNvbXByb2JhciBzaSBsYSBjb25jbHVzacOzbiBkZXBlbmRlIGRlIGxhIGRpc3RhbmNpYSBlbGVnaWRhLg0KDQpgYGB7cn0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDEuIFBBUVVFVEVTDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpsaWJyYXJ5KHZlZ2FuKQ0KbGlicmFyeShjbHVzdGVyKQ0KDQojIFRyYXRhbWllbnRvIGNvbW8gZmFjdG9yDQpkZiRUdG8gPC0gYXMuZmFjdG9yKGRmJFR0bykNCg0KIyBTZWxlY2Npb25hciBzb2xhbWVudGUgbGFzIHZhcmlhYmxlcyByZXNwdWVzdGENClkgPC0gZGZbLCBjKA0KICAiR3Jhc2FzIiwNCiAgIkh1bWVkYWQiLA0KICAiUHJvdGVpbmEiLA0KICAiQ2VuaXphcyINCildDQoNCiMgRXN0YW5kYXJpemFyIGxhcyB2YXJpYWJsZXMNCllfeiA8LSBzY2FsZShZKQ0KDQojIENvbXByb2JhciBxdWUgc2UgY3Jlw7MgY29ycmVjdGFtZW50ZQ0KaGVhZChZX3opDQoNCiMgUmV2aXNhciBtZWRpYXMgeSBkZXN2aWFjaW9uZXMgZXN0w6FuZGFyDQpyb3VuZChjb2xNZWFucyhZX3opLCA2KQ0KYXBwbHkoWV96LCAyLCBzZCkNCg0KIyBDb21wcm9iYXIgZXN0cnVjdHVyYQ0Kc3RyKFkpDQpzdW1tYXJ5KFkpDQoNCiMgQ29tcHJvYmFyIHZhbG9yZXMgZmFsdGFudGVzDQpjb2xTdW1zKGlzLm5hKFkpKQ0KDQojIENvbnNlcnZhciBzb2xhbWVudGUgZmlsYXMgY29tcGxldGFzDQpmaWxhc19jb21wbGV0YXMgPC0gY29tcGxldGUuY2FzZXMoWSwgZGYkVHRvKQ0KDQpZIDwtIFlbZmlsYXNfY29tcGxldGFzLCBdDQpncnVwbyA8LSBkcm9wbGV2ZWxzKGRmJFR0b1tmaWxhc19jb21wbGV0YXNdKQ0KDQojIFJldmlzYXIgbnVldmFtZW50ZSBlbCBiYWxhbmNlDQp0YWJsZShncnVwbykNCmBgYA0KTGEgbWF0cml6IG11bHRpdmFyaWFkYSBjb250aWVuZSA2MyBvYnNlcnZhY2lvbmVzIGNvbXBsZXRhcyB5IGN1YXRybyB2YXJpYWJsZXMgY29udGludWFzLiBQcmVzZW50YSBkaWZlcmVuY2lhcyBpbXBvcnRhbnRlcyBkZSBlc2NhbGEgZW50cmUgbGFzIHZhcmlhYmxlcywgc2UgcmVjb21pZW5kYSB1c2FyIGRpc3RhbmNpYSBldWNsw61kZWEgc29icmUgZGF0b3MgZXN0YW5kYXJpemFkb3MgY29tbyBhbsOhbGlzaXMgcHJpbmNpcGFsLg0KDQojIyAqQ29uc3RydWNjacOzbiBkZSBkaXN0YW5jaWFzKg0KDQpgYGB7cn0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDMuIE1BVFJJQ0VTIERFIERJU1RBTkNJQQ0KIyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KIyBFdWNsaWRlYSBzaW4gZXN0YW5kYXJpemFyDQpEX2V1Y2xpZF9yYXcgPC0gZGlzdCgNCiAgWSwNCiAgbWV0aG9kID0gImV1Y2xpZGVhbiINCikNCg0KIyBFdWNsaWRlYSBlc3RhbmRhcml6YWRhDQpEX2V1Y2xpZF96IDwtIGRpc3QoDQogIFlfeiwNCiAgbWV0aG9kID0gImV1Y2xpZGVhbiINCikNCg0KIyBNYW5oYXR0YW4gZXN0YW5kYXJpemFkYQ0KRF9tYW5oYXR0YW5feiA8LSBkaXN0KA0KICBZX3osDQogIG1ldGhvZCA9ICJtYW5oYXR0YW4iDQopDQoNCiMgR293ZXINCkRfZ293ZXIgPC0gY2x1c3Rlcjo6ZGFpc3koDQogIFksDQogIG1ldHJpYyA9ICJnb3dlciINCikNCg0KIyBCcmF5LUN1cnRpcw0KRF9icmF5IDwtIHZlZ2FuOjp2ZWdkaXN0KA0KICBZLA0KICBtZXRob2QgPSAiYnJheSINCikNCg0KIyBIZWxsaW5nZXIgKyBldWNsaWRlYQ0KWV9oZWxsaW5nZXIgPC0gdmVnYW46OmRlY29zdGFuZCgNCiAgWSwNCiAgbWV0aG9kID0gImhlbGxpbmdlciINCikNCg0KRF9oZWxsaW5nZXIgPC0gZGlzdCgNCiAgWV9oZWxsaW5nZXIsDQogIG1ldGhvZCA9ICJldWNsaWRlYW4iDQopDQpgYGANCg0KDQpgYGB7cn0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDQuIFBFUk1BTk9WQSBHTE9CQUwNCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCnNldC5zZWVkKDEyMykNCg0KcGVybWFub3ZhX2V1Y2xpZF9yYXcgPC0gYWRvbmlzMigNCiAgRF9ldWNsaWRfcmF3IH4gZ3J1cG8sDQogIHBlcm11dGF0aW9ucyA9IDk5OTkNCikNCg0Kc2V0LnNlZWQoMTIzKQ0KDQpwZXJtYW5vdmFfZXVjbGlkX3ogPC0gYWRvbmlzMigNCiAgRF9ldWNsaWRfeiB+IGdydXBvLA0KICBwZXJtdXRhdGlvbnMgPSA5OTk5DQopDQoNCnNldC5zZWVkKDEyMykNCg0KcGVybWFub3ZhX21hbmhhdHRhbl96IDwtIGFkb25pczIoDQogIERfbWFuaGF0dGFuX3ogfiBncnVwbywNCiAgcGVybXV0YXRpb25zID0gOTk5OQ0KKQ0KDQpzZXQuc2VlZCgxMjMpDQoNCnBlcm1hbm92YV9nb3dlciA8LSBhZG9uaXMyKA0KICBEX2dvd2VyIH4gZ3J1cG8sDQogIHBlcm11dGF0aW9ucyA9IDk5OTkNCikNCg0Kc2V0LnNlZWQoMTIzKQ0KDQpwZXJtYW5vdmFfYnJheSA8LSBhZG9uaXMyKA0KICBEX2JyYXkgfiBncnVwbywNCiAgcGVybXV0YXRpb25zID0gOTk5OQ0KKQ0KDQpzZXQuc2VlZCgxMjMpDQoNCnBlcm1hbm92YV9oZWxsaW5nZXIgPC0gYWRvbmlzMigNCiAgRF9oZWxsaW5nZXIgfiBncnVwbywNCiAgcGVybXV0YXRpb25zID0gOTk5OQ0KKQ0KDQpwZXJtYW5vdmFfZXVjbGlkX3Jhdw0KcGVybWFub3ZhX2V1Y2xpZF96DQpwZXJtYW5vdmFfbWFuaGF0dGFuX3oNCnBlcm1hbm92YV9nb3dlcg0KcGVybWFub3ZhX2JyYXkNCnBlcm1hbm92YV9oZWxsaW5nZXINCmBgYA0KDQoNCmBgYHtyfQ0KZXh0cmFlcl9wZXJtYW5vdmEgPC0gZnVuY3Rpb24obW9kZWxvLCBub21icmVfZGlzdGFuY2lhKSB7DQoNCiAgZGF0YS5mcmFtZSgNCiAgICBEaXN0YW5jaWEgPSBub21icmVfZGlzdGFuY2lhLA0KICAgIERmID0gbW9kZWxvJERmWzFdLA0KICAgIFN1bVNxID0gbW9kZWxvJFN1bU9mU3FzWzFdLA0KICAgIFIyID0gbW9kZWxvJFIyWzFdLA0KICAgIFBzZXVkb19GID0gbW9kZWxvJEZbMV0sDQogICAgcF92YWx1ZSA9IG1vZGVsbyRgUHIoPkYpYFsxXQ0KICApDQp9DQoNCnRhYmxhX3Blcm1hbm92YSA8LSByYmluZCgNCiAgZXh0cmFlcl9wZXJtYW5vdmEoDQogICAgcGVybWFub3ZhX2V1Y2xpZF9yYXcsDQogICAgIkV1Y2xpZGVhIHNpbiBlc3RhbmRhcml6YXIiDQogICksDQogIGV4dHJhZXJfcGVybWFub3ZhKA0KICAgIHBlcm1hbm92YV9ldWNsaWRfeiwNCiAgICAiRXVjbGlkZWEgZXN0YW5kYXJpemFkYSINCiAgKSwNCiAgZXh0cmFlcl9wZXJtYW5vdmEoDQogICAgcGVybWFub3ZhX21hbmhhdHRhbl96LA0KICAgICJNYW5oYXR0YW4gZXN0YW5kYXJpemFkYSINCiAgKSwNCiAgZXh0cmFlcl9wZXJtYW5vdmEoDQogICAgcGVybWFub3ZhX2dvd2VyLA0KICAgICJHb3dlciINCiAgKSwNCiAgZXh0cmFlcl9wZXJtYW5vdmEoDQogICAgcGVybWFub3ZhX2JyYXksDQogICAgIkJyYXktQ3VydGlzIg0KICApLA0KICBleHRyYWVyX3Blcm1hbm92YSgNCiAgICBwZXJtYW5vdmFfaGVsbGluZ2VyLA0KICAgICJIZWxsaW5nZXIgKyBFdWNsaWRlYSINCiAgKQ0KKQ0KDQp0YWJsYV9wZXJtYW5vdmFbDQogIG9yZGVyKHRhYmxhX3Blcm1hbm92YSRwX3ZhbHVlKSwNCl0NCmBgYA0KDQojIyAqRXZhbHVhY2nDs24gZGUgbGEgZGlzcGVyc2nDs24gbXVsdGl2YXJpYWRhIFBFUk1ESVNQKg0KDQpgYGB7cn0NCiMgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojIDYuIFBFUk1ESVNQDQojID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQpldmFsdWFyX3Blcm1kaXNwIDwtIGZ1bmN0aW9uKGRpc3RhbmNpYSwgZ3J1cG8sIHNlbWlsbGFzID0gMTIzKSB7DQoNCiAgZGlzcGVyc2lvbiA8LSBiZXRhZGlzcGVyKA0KICAgIGRpc3RhbmNpYSwNCiAgICBncnVwbywNCiAgICB0eXBlID0gImNlbnRyb2lkIg0KICApDQoNCiAgc2V0LnNlZWQoc2VtaWxsYXMpDQoNCiAgcHJ1ZWJhIDwtIHBlcm11dGVzdCgNCiAgICBkaXNwZXJzaW9uLA0KICAgIHBlcm11dGF0aW9ucyA9IDk5OTkNCiAgKQ0KDQogIGxpc3QoDQogICAgb2JqZXRvID0gZGlzcGVyc2lvbiwNCiAgICByZXN1bHRhZG8gPSBwcnVlYmENCiAgKQ0KfQ0KDQpkaXNwX2V1Y2xpZF9yYXcgPC0gZXZhbHVhcl9wZXJtZGlzcCgNCiAgRF9ldWNsaWRfcmF3LA0KICBncnVwbw0KKQ0KDQpkaXNwX2V1Y2xpZF96IDwtIGV2YWx1YXJfcGVybWRpc3AoDQogIERfZXVjbGlkX3osDQogIGdydXBvDQopDQoNCmRpc3BfbWFuaGF0dGFuX3ogPC0gZXZhbHVhcl9wZXJtZGlzcCgNCiAgRF9tYW5oYXR0YW5feiwNCiAgZ3J1cG8NCikNCg0KZGlzcF9nb3dlciA8LSBldmFsdWFyX3Blcm1kaXNwKA0KICBEX2dvd2VyLA0KICBncnVwbw0KKQ0KDQpkaXNwX2JyYXkgPC0gZXZhbHVhcl9wZXJtZGlzcCgNCiAgRF9icmF5LA0KICBncnVwbw0KKQ0KDQpkaXNwX2hlbGxpbmdlciA8LSBldmFsdWFyX3Blcm1kaXNwKA0KICBEX2hlbGxpbmdlciwNCiAgZ3J1cG8NCikNCg0KZGlzcF9ldWNsaWRfcmF3JHJlc3VsdGFkbw0KZGlzcF9ldWNsaWRfeiRyZXN1bHRhZG8NCmRpc3BfbWFuaGF0dGFuX3okcmVzdWx0YWRvDQpkaXNwX2dvd2VyJHJlc3VsdGFkbw0KZGlzcF9icmF5JHJlc3VsdGFkbw0KZGlzcF9oZWxsaW5nZXIkcmVzdWx0YWRvDQpgYGANCg0KYGBge3J9DQpleHRyYWVyX3Blcm1kaXNwIDwtIGZ1bmN0aW9uKG9iamV0bywgbm9tYnJlX2Rpc3RhbmNpYSkgew0KDQogIHRhYmxhIDwtIG9iamV0byRyZXN1bHRhZG8kdGFiDQoNCiAgZGF0YS5mcmFtZSgNCiAgICBEaXN0YW5jaWEgPSBub21icmVfZGlzdGFuY2lhLA0KICAgIEZfZGlzcGVyc2lvbiA9IHRhYmxhJEZbMV0sDQogICAgcF9kaXNwZXJzaW9uID0gdGFibGEkYFByKD5GKWBbMV0NCiAgKQ0KfQ0KDQp0YWJsYV9wZXJtZGlzcCA8LSByYmluZCgNCiAgZXh0cmFlcl9wZXJtZGlzcCgNCiAgICBkaXNwX2V1Y2xpZF9yYXcsDQogICAgIkV1Y2xpZGVhIHNpbiBlc3RhbmRhcml6YXIiDQogICksDQogIGV4dHJhZXJfcGVybWRpc3AoDQogICAgZGlzcF9ldWNsaWRfeiwNCiAgICAiRXVjbGlkZWEgZXN0YW5kYXJpemFkYSINCiAgKSwNCiAgZXh0cmFlcl9wZXJtZGlzcCgNCiAgICBkaXNwX21hbmhhdHRhbl96LA0KICAgICJNYW5oYXR0YW4gZXN0YW5kYXJpemFkYSINCiAgKSwNCiAgZXh0cmFlcl9wZXJtZGlzcCgNCiAgICBkaXNwX2dvd2VyLA0KICAgICJHb3dlciINCiAgKSwNCiAgZXh0cmFlcl9wZXJtZGlzcCgNCiAgICBkaXNwX2JyYXksDQogICAgIkJyYXktQ3VydGlzIg0KICApLA0KICBleHRyYWVyX3Blcm1kaXNwKA0KICAgIGRpc3BfaGVsbGluZ2VyLA0KICAgICJIZWxsaW5nZXIgKyBFdWNsaWRlYSINCiAgKQ0KKQ0KDQp0YWJsYV9wZXJtZGlzcA0KYGBgDQoNCg0KYGBge3J9DQp0YWJsYV9jb21wbGV0YSA8LSBtZXJnZSgNCiAgdGFibGFfcGVybWFub3ZhLA0KICB0YWJsYV9wZXJtZGlzcCwNCiAgYnkgPSAiRGlzdGFuY2lhIg0KKQ0KDQp0YWJsYV9jb21wbGV0YVsNCiAgb3JkZXIodGFibGFfY29tcGxldGEkcF92YWx1ZSksDQpdDQpgYGANCg0KLSBDb24gYmFzZSBlbiBlc3RvcyByZXN1bHRhZG9zLCBzZSBkZXRlY3Rhcm9uIGRpZmVyZW5jaWFzIG11bHRpdmFyaWFkYXMgZW50cmUgbG9zIHRyYXRhbWllbnRvcyBjb24gZGlzdGFuY2lhIEV1Y2zDrWRlYSBlc3RhbmRhcml6YWRhIChQRVJNQU5PVkEpLCBwZXJvIHRhbWJpw6luIHNlIGVuY29udHJhcm9uIGRpZmVyZW5jaWFzIGVuIGxhIGRpc3BlcnNpw7NuIGludGVybmEgZGUgbG9zIGdydXBvcyAoUEVSTURJU1ApLiBQb3IgZWxsbywgbGEgc2lnbmlmaWNhbmNpYSBkZWwgUEVSTUFOT1ZBIG5vIHB1ZWRlIGF0cmlidWlyc2UgZXhjbHVzaXZhbWVudGUgYSBkaWZlcmVuY2lhcyBlbnRyZSBjZW50cm9pZGVzLiBFc3RvcyByZXN1bHRhZG9zIHNlIG9ic2VydmFyb24gZW4gbGEgZGlzdGFuY2lhIGRlIE1hbmhhdHRhbiBlc3RhbmRhcml6YWRhIHkgR293ZXIsIHNpZW5kbyBtYXMgc2Vuc2libGVzIGVuIGxhIGRldGVjY2nDs24gZGUgbGFzIGRpZmVyZW5jaWFzIGVuIGNvbXBhcmFjacOzbiBjb24gZWwgcmVzdG8uDQoNCi0gTGEgRXVjbGlkZWEgc2luIGVzdGFuZGFyaXphciBtb3N0csOzIHF1ZSBsYXMgZGlyZW5jaWFzIGRlIGVzY2FsYSBkZSBsYXMgdmFyaWFibGVzIGV2YWx1YWRhcyBmdWVyb24gZGV0ZXJtaW5hbnRlcyBlbiBsb3MgcmVzdWx0YWRvcyBvYnRlbmlkb3MsIHlhIHF1ZSBhbCBlbGV2YXIgbGFzIGRpZmVyZW5jaWFzIGFsIGN1YWRyYWRvLCBkYSBtYXlvciBwZXNvIGEgdW5hcyB2YXJpYWJsZXMgY29uIHJlc3BlY3RvIGEgb3RyYXMuDQoNCi0gTWFuaGF0dGFuIGVzdGFuZGFyaXphZGEgc3VtYSBlbCB2YWxvciBhYnNvbHV0byBkZSBsYXMgZGlmZXJlbmNpYXMgbXVsdGl2YXJpYWRhcyBzaWVuZG8gYWx0YW1lbnRlIHNlbnNpYmxlIGEgZXN0YSBwcnVlYmEgYSBwZXNhciBkZSBxdWUgc2UgZW1wbGVhIHByaW5jaXBhbG1lbnRlIGVuIGRhdG9zIGRlIGNsYXNpZmljYWNpw7NuLCBhZ3J1cGFtaWVudG8geSBhbsOhbGlzaXMgZGUgZGF0b3MgY29uIHBvc2libGVzIHZhbG9yZXMgZXh0cmVtb3MuDQoNCi0gR293ZXIgZXMgbGEgZGlzdGFuY2lhIGNhcmFjdGVyw61zdGljYSBjdWFuZG8gc2UgbWV6Y2xhbiB2YXJpYWJsZXMgbnVtw6lyaWNhcywgb3JkaW5hbGVzIHkgYmluYXJpYXMsIGZ1ZSBmdW5jaW9uYWwgcGFyYSBlc3RvcyBkYXRvcywgZGViaWRvIGEgc3UgcG9uZGVyYWNpw7NuIGVsIHJhbmdvLCBsbyBxdWUgaGFjZSBxdWUgbGEgZGlzdGFuY2lhIG1hbmVqZSB1bmEgZXNjYWxhIHNpbWlsYXIgZW50cmUgdmFyaWFibGVzLg0KDQotIEhlbGxpbmdlciBFdWNsaWRlYSBubyBkZXRlY3TDsyBkaWZlcmVuY2lhcyBwb3JxdWUgdHJhbnNmb3Jtw7MgbG9zIGRhdG9zIGVuIHBlcmZpbGVzIHJlbGF0aXZvcyBwb3IgbXVlc3RyYSwgZWxpbWluYW5kbyB1bmEgZ3JhbiBwYXJ0ZSBkZSBsYXMgZGlmZXJlbmNpYXMgYWJzb2x1dGFzIHF1ZSBzw60gZXJhbiByZWxldmFudGVzIGVuIGVsIGFuw6FsaXNpcyBlc3RhbmRhcml6YWRvLg0KDQotIEJyYXktQ3VydGlzIG5vIGRldGVjdMOzIGRpZmVyZW5jaWFzIHBvcnF1ZSByZXNwb25kZSBhIGRpZmVyZW5jaWFzIHJlbGF0aXZhcyBlbiBwZXJmaWxlcyBkZSBhYnVuZGFuY2lhIHkgbm8gc2UgYWp1c3RhIGJpZW4gYSBjdWF0cm8gdmFyaWFibGVzIHF1w61taWNhcyBjb24gZXNjYWxhcyB5IG5hdHVyYWxlemFzIGRpZmVyZW50ZXMuDQo=