Planteamiento del Problema

En diversas industrias como la alimentaria, química y farmacéutica— es frecuente la necesidad de tomar decisiones fundamentadas sobre cuál tratamiento, formulación o método experimental produce los mejores resultados. Para esto, se requiere identificar si las diferencias observadas en los resultados experimentales son estadísticamente significativas o solo se deben al azar. Una metodología ampliamente utilizada para este fin es el análisis de varianza (ANOVA), que permite evaluar la influencia de un solo factor sobre una variable de respuesta, comparando varios niveles del mismo. Sin embargo, una aplicación adecuada de esta técnica exige cumplir ciertos supuestos estadísticos, interpretar correctamente los resultados y proponer recomendaciones prácticas con base en ellos.

Objetivo General

Aplicar el análisis de varianza de un solo factor para evaluar el efecto de distintos tratamientos sobre una variable de respuesta en diversos contextos experimentales industriales, interpretando los resultados estadísticos y verificando el cumplimiento de los supuestos del modelo.

Objetivos Específicos

  1. Formular correctamente las hipótesis nula y alternativa en cada contexto experimental.

  2. Construir tablas ANOVA completas, incluyendo grados de libertad, cuadrados medios, razón F y valor-p.

  3. Verificar gráficamente y estadísticamente los supuestos de normalidad y homogeneidad de varianzas.

  4. Interpretar los resultados del análisis de varianza para determinar si existen diferencias significativas entre tratamientos.

  5. Realizar análisis post hoc cuando sea necesario, para identificar tratamientos responsables de las diferencias.

  6. Proponer recomendaciones prácticas basadas en los resultados estadísticos para la optimización de procesos industriales o farmacéuticos.

Antecedentes

El análisis de varianza (ANOVA) es una técnica estadística desarrollada por Ronald A. Fisher en el siglo XX, ampliamente utilizada en experimentación para comparar las medias de tres o más grupos bajo distintas condiciones. Su aplicación es fundamental en el diseño experimental, ya que permite separar la variabilidad atribuible al tratamiento de la variabilidad aleatoria o experimental. En la industria farmacéutica, por ejemplo, se emplea para evaluar la influencia de ingredientes activos o excipientes sobre características como la friabilidad o la dureza de las tabletas. En el sector alimentario, puede usarse para analizar la efectividad de distintos conservantes o tiempos de cocción. Además, en la industria química es útil para estudiar mezclas y procesos que afectan propiedades fisicoquímicas de los productos.

El presente trabajo recopila diversos ejercicios en los que se aplican estos principios con datos experimentales reales o simulados, buscando fortalecer la comprensión teórica y práctica del ANOVA en contextos aplicados.

Desarrollo del Proyecto

library(data.table)
library(dplyr)
library(readxl)
library(writexl)
library(car)

Paso a paso

Primero, se formulo el planteamiento del problema y definiendo tanto el objetivo general como los objetivos específicos de el taller dado por el docente. Luego, cargué en R las bibliotecas necesarias para trabajar con los datos (data.table, dplyr, readxl, writexl y car). Después, importé el conjunto de datos relacionado con vinos blancos y tintos, y lo preparé para el análisis. A continuación, planteé una serie de preguntas que me permitirán explorar y comparar diferentes variables como el contenido de alcohol, el pH, la acidez, el azúcar residual, la calidad sensorial y otros factores. Estas preguntas guiarán el análisis estadístico paso a paso, Se revisa la ubicacion de nuestro proyecto dando como afirmativo en las carpetas creadas anteriormente

list.files("../Datos")
[1] "winequality.csv"
data <- read.csv("../Datos/winequality.csv",
                 sep = ";",
                 dec = ",",# símbolo se usa como separador decimal
                 fileEncoding = "latin1") # especifica la codificación de caracteres del archivo
str(data)
'data.frame':   6497 obs. of  16 variables:
 $ acidez.fija            : num  7 6.3 8.1 7.2 7.2 8.1 6.2 7 6.3 8.1 ...
 $ acidez.volátil         : num  0.27 0.3 0.28 0.23 0.23 0.28 0.32 0.27 0.3 0.22 ...
 $ X.ácido.cítrico        : num  0.36 0.34 0.4 0.32 0.32 0.4 0.16 0.36 0.34 0.43 ...
 $ azúcar.residual        : num  20.7 1.6 6.9 8.5 8.5 6.9 7 20.7 1.6 1.5 ...
 $ cloruros               : num  0.045 0.049 0.05 0.058 0.058 0.05 0.045 0.045 0.049 0.044 ...
 $ dióxido.de.azufre.libre: num  45 14 30 47 47 30 30 45 14 28 ...
 $ dióxido.de.azufre.total: num  170 132 97 186 186 97 136 170 132 129 ...
 $ densidad               : num  1.001 0.994 0.995 0.996 0.996 ...
 $ pH                     : num  3 3.3 3.26 3.19 3.19 3.26 3.18 3 3.3 3.22 ...
 $ acidez                 : chr  "Muy ácido" "Ácido" "Ácido" "Muy ácido" ...
 $ sulfatos               : num  0.45 0.49 0.44 0.4 0.4 0.44 0.47 0.45 0.49 0.45 ...
 $ alcohol                : num  8.8 9.5 10.1 9.9 9.9 10.1 9.6 8.8 9.5 11 ...
 $ contenido.de.alcohol   : chr  "Bajo" "Bajo" "Medio" "Bajo" ...
 $ puntaje.sensorial      : int  6 6 6 6 6 6 6 6 6 6 ...
 $ calidad                : chr  "Media" "Media" "Media" "Media" ...
 $ tipo                   : chr  "white" "white" "white" "white" ...
summary(data$acidez.volátil)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
   0.080    0.230    0.290    1.319    0.400 1185.000 
library(dplyr)
library(knitr)

# Crear función para los estadísticos
calc_estadisticos <- function(x) {
  c(
    Media = mean(x, na.rm = TRUE),
    Mediana = median(x, na.rm = TRUE),
    `Desviación Estándar` = sd(x, na.rm = TRUE),
    Mínimo = min(x, na.rm = TRUE),
    Máximo = max(x, na.rm = TRUE),
    `Q1 (25%)` = quantile(x, 0.25, na.rm = TRUE),
    `Q2 (50%)` = quantile(x, 0.50, na.rm = TRUE),
    `Q3 (75%)` = quantile(x, 0.75, na.rm = TRUE)
  )
}

# Calcular estadísticos por alcohol (ejemplo general)
estadisticos <- calc_estadisticos(data$alcohol)
estadisticos
              Media             Mediana Desviación Estándar 
          10.504746           10.300000            1.593123 
             Mínimo              Máximo        Q1 (25%).25% 
           8.000000           95.666667            9.500000 
       Q2 (50%).50%        Q3 (75%).75% 
          10.300000           11.300000 
data <- read.csv("../datos/winequality.csv",
                 sep = ";",
                 dec = ",",# símbolo se usa como separador decimal
                 fileEncoding = "latin1") # especifica la codificación de caracteres del archivo
library(readr)

datos <- read_delim("C:/Users/Usuario/OneDrive/Escritorio/Proyecto/Datos/winequality.csv",
                    delim = ";",
                    locale = locale(decimal_mark = ",", encoding = "Latin1"))
Rows: 6497 Columns: 16
── Column specification ──────────────────────────────────────────
Delimiter: ";"
chr  (4): acidez, contenido de alcohol, calidad, tipo
dbl (12): acidez fija, acidez volátil,  ácido cítrico, azúcar ...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Preguntas

1.¿El contenido promedio de alcohol varía según el nivel de acidez (por ejemplo, Ácido vs. Muy ácido)?

# Filtrar solo los niveles deseados de acidez
acidez_datos <- data %>%
  filter(acidez %in% c("Ácido", "Muy ácido")) %>%
  mutate(acidez = factor(acidez))  # Asegurar que sea factor

# Comparar promedios de alcohol
acidez_datos %>%
  group_by(acidez) %>%
  summarise(Media_Alcohol = mean(alcohol, na.rm = TRUE),
            SD_Alcohol = sd(alcohol, na.rm = TRUE),
            n = n())

# Realizar prueba t
t.test(alcohol ~ acidez, data = acidez_datos)

    Welch Two Sample t-test

data:  alcohol by acidez
t = 5.4132, df = 5458.2, p-value = 6.454e-08
alternative hypothesis: true difference in means between group Ácido and group Muy ácido is not equal to 0
95 percent confidence interval:
 0.1428806 0.3051256
sample estimates:
    mean in group Ácido mean in group Muy ácido 
               10.60566                10.38166 
data_filtrada <- subset(data, acidez %in% c("Ácido", "Muy ácido"))

table(data_filtrada$acidez)

    Ácido Muy ácido 
     2483      3230 
t.test(alcohol ~ acidez, data = data_filtrada)

    Welch Two Sample t-test

data:  alcohol by acidez
t = 5.4132, df = 5458.2, p-value = 6.454e-08
alternative hypothesis: true difference in means between group Ácido and group Muy ácido is not equal to 0
95 percent confidence interval:
 0.1428806 0.3051256
sample estimates:
    mean in group Ácido mean in group Muy ácido 
               10.60566                10.38166 
by(data_filtrada$alcohol, data_filtrada$acidez, shapiro.test)
data_filtrada$acidez: Ácido

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.95802, p-value < 2.2e-16

------------------------------------------------- 
data_filtrada$acidez: Muy ácido

    Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.43265, p-value < 2.2e-16

2.¿Las muestras con mayor nivel de acidez categórica presentan menor pH promedio?

3.¿El nivel de azúcar residual es mayor en las muestras clasificadas como Muy ácidas frente a las Ácidas?

# Prueba t para comparar niveles de azúcar residual
t.test(`azúcar.residual` ~ acidez, data = azucar_datos, alternative = "less")

    Welch Two Sample t-test

data:  azúcar.residual by acidez
t = -16.093, df = 5666.7, p-value < 2.2e-16
alternative hypothesis: true difference in means between group Ácido and group Muy ácido is less than 0
95 percent confidence interval:
      -Inf -1.800971
sample estimates:
    mean in group Ácido mean in group Muy ácido 
               4.594382                6.600418 

4.¿Existen diferencias en la acidez volátil promedio entre niveles de acidez (Ácido vs. Muy ácido)?

# Prueba t para comparar la acidez volátil
t.test(`acidez.volátil` ~ acidez, data = volatil_datos)

    Welch Two Sample t-test

data:  acidez.volátil by acidez
t = 0.33545, df = 4937.3, p-value = 0.7373
alternative hypothesis: true difference in means between group Ácido and group Muy ácido is not equal to 0
95 percent confidence interval:
 -1.188086  1.678603
sample estimates:
    mean in group Ácido mean in group Muy ácido 
              1.1785421               0.9332833 

5.¿La densidad promedio cambia entre los niveles de acidez?

summary(modelo_anova)
              Df    Sum Sq   Mean Sq F value   Pr(>F)    
acidez         3 1.003e+09 334357371   5.612 0.000772 ***
Residuals   6493 3.869e+11  59583224                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

6.Elabora un gráfico de cajas y bigotes para cada nivel de acidez.(Interpretelo)

7.¿La concentración de ácido cítrico promedio difiere entre muestras con acidez Ácida y Muy ácida?

# Prueba t
t.test(`X.ácido.cítrico` ~ acidez, data = citricos_datos)

    Welch Two Sample t-test

data:  X.ácido.cítrico by acidez
t = -15.692, df = 5233.5, p-value < 2.2e-16
alternative hypothesis: true difference in means between group Ácido and group Muy ácido is not equal to 0
95 percent confidence interval:
 -0.06440056 -0.05009674
sample estimates:
    mean in group Ácido mean in group Muy ácido 
              0.2994603               0.3567090 

8.¿Las muestras con mayor contenido de alcohol presentan menor acidez fija en promedio?

# Prueba t
t.test(`acidez.fija` ~ nivel_alcohol, data = datos, alternative = "greater")

    Welch Two Sample t-test

data:  acidez.fija by nivel_alcohol
t = -5.3581, df = 6405.6, p-value = 1
alternative hypothesis: true difference in means between group Alto and group Bajo is greater than 0
95 percent confidence interval:
 -0.2251235        Inf
sample estimates:
mean in group Alto mean in group Bajo 
          7.128154           7.300395 

9.¿El contenido de sulfatos difiere entre niveles de acidez?

TukeyHSD(modelo_sulfatos)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = sulfatos ~ acidez, data = datos)

$acidez
                                diff         lwr         upr
Bajo en acidez-Ácido      0.08974340  0.04968294  0.12980386
Medio-Ácido               0.02893976  0.01281452  0.04506499
Muy ácido-Ácido          -0.04251081 -0.05252840 -0.03249322
Medio-Bajo en acidez     -0.06080364 -0.10265325 -0.01895403
Muy ácido-Bajo en acidez -0.13225421 -0.17215056 -0.09235786
Muy ácido-Medio          -0.07145057 -0.08716367 -0.05573747
                             p adj
Bajo en acidez-Ácido     0.0000001
Medio-Ácido              0.0000241
Muy ácido-Ácido          0.0000000
Medio-Bajo en acidez     0.0010919
Muy ácido-Bajo en acidez 0.0000000
Muy ácido-Medio          0.0000000

10.¿El pH promedio de las muestras con acidez Muy ácida es diferente al de las Ácidas?

# Prueba t
t.test(pH ~ acidez, data = ph_datos)

    Welch Two Sample t-test

data:  pH by acidez
t = 109.67, df = 5612.9, p-value < 2.2e-16
alternative hypothesis: true difference in means between group Ácido and group Muy ácido is not equal to 0
95 percent confidence interval:
 0.2003667 0.2076604
sample estimates:
    mean in group Ácido mean in group Muy ácido 
               3.294704                3.090690 

11.¿El puntaje sensorial promedio varía entre los vinos con bajo y alto contenido de alcohol?

# Prueba t
t.test(`puntaje.sensorial` ~ nivel_alcohol, data = datos)

    Welch Two Sample t-test

data:  puntaje.sensorial by nivel_alcohol
t = 33.806, df = 6194.2, p-value < 2.2e-16
alternative hypothesis: true difference in means between group Alto and group Bajo is not equal to 0
95 percent confidence interval:
 0.6379835 0.7165297
sample estimates:
mean in group Alto mean in group Bajo 
          6.161774           5.484517 

12.¿Las muestras con alto contenido de alcohol tienen menor acidez volátil en promedio que las de contenido bajo?

library(dplyr)
library(knitr)

# Asegurarse de tener la variable nivel_alcohol
datos <- datos %>%
  mutate(nivel_alcohol = ifelse(alcohol > median(alcohol, na.rm = TRUE), "Alto", "Bajo"))

# Crear tabla resumen de acidez volátil por nivel de alcohol
tabla_volatil <- datos %>%
  group_by(nivel_alcohol) %>%
  summarise(
    Media_volatil = round(mean(`acidez.volátil`, na.rm = TRUE), 3),
    SD_volatil = round(sd(`acidez.volátil`, na.rm = TRUE), 3),
    n = n()
  )

# Mostrar tabla
kable(tabla_volatil, caption = "Acidez volátil promedio por nivel de alcohol")
Acidez volátil promedio por nivel de alcohol
nivel_alcohol Media_volatil SD_volatil n
Alto 1.043 28.742 3202
Bajo 1.588 35.432 3294
NA 0.270 NA 1

# Prueba t (hipótesis: alcohol alto → menor acidez volátil)
t.test(`acidez.volátil` ~ nivel_alcohol, data = datos, alternative = "less")

    Welch Two Sample t-test

data:  acidez.volátil by nivel_alcohol
t = -0.68233, df = 6293.5, p-value = 0.2475
alternative hypothesis: true difference in means between group Alto and group Bajo is less than 0
95 percent confidence interval:
      -Inf 0.7696868
sample estimates:
mean in group Alto mean in group Bajo 
          1.042694           1.588180 

13.¿El nivel de azúcar residual cambia significativamente según el contenido de alcohol?

library(dplyr)
library(knitr)

# Asegurarse de tener la variable nivel_alcohol
datos <- datos %>%
  mutate(nivel_alcohol = ifelse(alcohol > median(alcohol, na.rm = TRUE), "Alto", "Bajo"))

# Tabla resumen de azúcar residual
tabla_azucar <- datos %>%
  group_by(nivel_alcohol) %>%
  summarise(
    Media_azucar = round(mean(`azúcar.residual`, na.rm = TRUE), 2),
    SD_azucar = round(sd(`azúcar.residual`, na.rm = TRUE), 2),
    n = n()
  )

# Mostrar tabla organizada
kable(tabla_azucar, caption = "Azúcar residual promedio por nivel de alcohol")
Azúcar residual promedio por nivel de alcohol
nivel_alcohol Media_azucar SD_azucar n
Alto 3.98 3.53 3202
Bajo 6.87 5.33 3294
NA 1.70 NA 1

# Prueba t
t.test(`azúcar.residual` ~ nivel_alcohol, data = datos)

    Welch Two Sample t-test

data:  azúcar.residual by nivel_alcohol
t = -25.812, df = 5733, p-value < 2.2e-16
alternative hypothesis: true difference in means between group Alto and group Bajo is not equal to 0
95 percent confidence interval:
 -3.107644 -2.668927
sample estimates:
mean in group Alto mean in group Bajo 
          3.979216           6.867502 

14.¿Las muestras con alcohol alto presentan mayor calidad promedio (por ejemplo, más veces clasificadas como “Buena” o “Excelente”)?


unique(datos$calidad)
[1] "Media"     "Baja"      "Buena"     "Excelente" "Muy baja" 
#DAR NUMERACION 

datos <- datos %>%
  mutate(calidad_num = case_when(
    calidad == "Muy baja" ~ 1,
    calidad == "Baja" ~ 2,
    calidad == "Regular" ~ 3,
    calidad == "Buena" ~ 4,
    calidad == "Excelente" ~ 5
  ))
# Tabla
tabla_calidad <- datos %>%
  group_by(nivel_alcohol) %>%
  summarise(
    Media_calidad = round(mean(calidad_num, na.rm = TRUE), 2),
    SD_calidad = round(sd(calidad_num, na.rm = TRUE), 2),
    n = n()
  )

kable(tabla_calidad, caption = "Calidad promedio (en escala 1-5) por nivel de alcohol")
Calidad promedio (en escala 1-5) por nivel de alcohol
nivel_alcohol Media_calidad SD_calidad n
Alto 3.32 1.18 3202
Bajo 2.16 0.75 3294
NA NaN NA 1

# Prueba t
t.test(calidad_num ~ nivel_alcohol, data = datos, alternative = "less")

    Welch Two Sample t-test

data:  calidad_num by nivel_alcohol
t = 34.567, df = 2677.4, p-value = 1
alternative hypothesis: true difference in means between group Alto and group Bajo is less than 0
95 percent confidence interval:
     -Inf 1.211513
sample estimates:
mean in group Alto mean in group Bajo 
          3.318814           2.162351 

15.¿El pH promedio difiere entre los niveles de alcohol (medio y alto)?

# Crear tres niveles de alcohol: Bajo, Medio, Alto
quantiles <- quantile(datos$alcohol, probs = c(0.33, 0.66), na.rm = TRUE)

datos <- datos %>%
  mutate(nivel_alcohol = case_when(
    alcohol <= quantiles[1] ~ "Bajo",
    alcohol > quantiles[1] & alcohol <= quantiles[2] ~ "Medio",
    alcohol > quantiles[2] ~ "Alto"
  ))
library(dplyr)
library(knitr)

# Filtrar los grupos Medio y Alto
ph_datos <- datos %>%
  filter(nivel_alcohol %in% c("Medio", "Alto")) %>%
  mutate(nivel_alcohol = factor(nivel_alcohol))

# Tabla resumen
tabla_ph <- ph_datos %>%
  group_by(nivel_alcohol) %>%
  summarise(
    Media_pH = round(mean(pH, na.rm = TRUE), 3),
    SD_pH = round(sd(pH, na.rm = TRUE), 3),
    n = n()
  )

# Mostrar tabla
kable(tabla_ph, caption = "Promedio de pH entre niveles de alcohol Medio y Alto")
Promedio de pH entre niveles de alcohol Medio y Alto
nivel_alcohol Media_pH SD_pH n
Alto 3.227 0.163 2191
Medio 3.248 0.163 2082

# Prueba t
t.test(pH ~ nivel_alcohol, data = ph_datos)

    Welch Two Sample t-test

data:  pH by nivel_alcohol
t = -4.1018, df = 4260.4, p-value = 4.176e-05
alternative hypothesis: true difference in means between group Alto and group Medio is not equal to 0
95 percent confidence interval:
 -0.03029828 -0.01070163
sample estimates:
 mean in group Alto mean in group Medio 
           3.227440            3.247939 

16.¿El contenido promedio de alcohol varía según el nivel de calidad de las muestras?

library(dplyr)
library(knitr)

# Tabla de alcohol promedio por calidad categórica
tabla_alcohol <- datos %>%
  group_by(calidad) %>%
  summarise(
    Media_alcohol = round(mean(alcohol, na.rm = TRUE), 2),
    SD = round(sd(alcohol, na.rm = TRUE), 2),
    n = n()
  )

kable(tabla_alcohol, caption = "Contenido promedio de alcohol por nivel de calidad")
Contenido promedio de alcohol por nivel de calidad
calidad Media_alcohol SD n
Baja 9.84 0.81 2138
Buena 11.39 1.20 1079
Excelente 11.69 1.27 198
Media 10.62 1.95 2836
Muy baja 10.18 1.00 246

# ANOVA
modelo <- aov(alcohol ~ calidad, data = datos)
summary(modelo)
              Df Sum Sq Mean Sq F value Pr(>F)    
calidad        4   2128   532.1   240.6 <2e-16 ***
Residuals   6491  14356     2.2                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
1 observation deleted due to missingness
# Convertir a factor para análisis categórico
datos$calidad_num <- as.factor(datos$calidad_num)

# Tabla resumen
tabla_alcohol2 <- datos %>%
  group_by(calidad_num) %>%
  summarise(
    Media_alcohol = round(mean(alcohol, na.rm = TRUE), 2),
    SD = round(sd(alcohol, na.rm = TRUE), 2),
    n = n()
  )

kable(tabla_alcohol2, caption = "Contenido promedio de alcohol por calidad (escala numérica)")
Contenido promedio de alcohol por calidad (escala numérica)
calidad_num Media_alcohol SD n
1 10.18 1.00 246
2 9.84 0.81 2138
4 11.39 1.20 1079
5 11.69 1.27 198
NA 10.62 1.95 2836

# ANOVA
modelo2 <- aov(alcohol ~ calidad_num, data = datos)
summary(modelo2)
              Df Sum Sq Mean Sq F value Pr(>F)    
calidad_num    3   2065   688.3   712.7 <2e-16 ***
Residuals   3657   3532     1.0                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
2836 observations deleted due to missingness

17.¿Las muestras clasificadas como “Excelente” presentan menor acidez volátil en promedio que las de calidad “Baja” ?

library(dplyr)
library(knitr)

# Filtrar las muestras con calidad Excelente y Baja
volatil_datos <- datos %>%
  filter(calidad %in% c("Excelente", "Baja")) %>%
  mutate(calidad = factor(calidad))

# Tabla resumen de acidez volátil
tabla_volatil <- volatil_datos %>%
  group_by(calidad) %>%
  summarise(
    Media_volatil = round(mean(`acidez.volátil`, na.rm = TRUE), 3),
    SD_volatil = round(sd(`acidez.volátil`, na.rm = TRUE), 3),
    n = n()
  )

# Mostrar tabla
kable(tabla_volatil, caption = "Acidez volátil promedio: Excelente vs. Baja")
Acidez volátil promedio: Excelente vs. Baja
calidad Media_volatil SD_volatil n
Baja 1.822 38.241 2138
Excelente 0.291 0.118 198

t.test(`acidez.volátil` ~ calidad, data = volatil_datos, alternative = "less")

    Welch Two Sample t-test

data:  acidez.volátil by calidad
t = 1.8506, df = 2137.4, p-value = 0.9678
alternative hypothesis: true difference in means between group Baja and group Excelente is less than 0
95 percent confidence interval:
     -Inf 2.891609
sample estimates:
     mean in group Baja mean in group Excelente 
              1.8217633               0.2911869 

18.¿El puntaje sensorial promedio aumenta conforme mejora la calidad de las muestras?

library(dplyr)
library(knitr)

# Asignar valores numéricos a la calidad si aún no existe
datos <- datos %>%
  mutate(calidad_num = case_when(
    calidad == "Muy baja" ~ 1,
    calidad == "Baja" ~ 2,
    calidad == "Regular" ~ 3,
    calidad == "Buena" ~ 4,
    calidad == "Excelente" ~ 5
  ))

#Tabla resumen
tabla_sensorial <- datos %>%
  group_by(calidad_num) %>%
  summarise(
    Media_puntaje = round(mean(`puntaje.sensorial`, na.rm = TRUE), 2),
    SD = round(sd(`puntaje.sensorial`, na.rm = TRUE), 2),
    n = n()
  )

kable(tabla_sensorial, caption = "Puntaje sensorial promedio según nivel de calidad")
Puntaje sensorial promedio según nivel de calidad
calidad_num Media_puntaje SD n
1 3.88 0.33 246
2 5.00 0.00 2138
4 7.00 0.00 1079
5 8.03 0.16 198
NA 6.00 0.00 2836

# Correlación entre calidad y puntaje sensorial
cor.test(datos$calidad_num, datos$`puntaje.sensorial`, method = "pearson")

    Pearson's product-moment correlation

data:  datos$calidad_num and datos$puntaje.sensorial
t = 715.29, df = 3659, p-value < 2.2e-16
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.9962056 0.9966662
sample estimates:
      cor 
0.9964433 
modelo <- lm(`puntaje.sensorial` ~ calidad_num, data = datos)
summary(modelo)

Call:
lm(formula = puntaje.sensorial ~ calidad_num, data = datos)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.97057 -0.01082  0.01601  0.01601  0.97576 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 2.957147   0.004124   717.1   <2e-16 ***
calidad_num 1.013419   0.001417   715.3   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.09639 on 3659 degrees of freedom
  (2836 observations deleted due to missingness)
Multiple R-squared:  0.9929,    Adjusted R-squared:  0.9929 
F-statistic: 5.116e+05 on 1 and 3659 DF,  p-value: < 2.2e-16

19.¿El nivel de dióxido de azufre total es diferente entre los vinos de calidad baja y los de calidad excelente?

library(dplyr)
library(knitr)

# Filtrar datos con calidad Baja y Excelente
azufre_datos <- datos %>%
  filter(calidad %in% c("Baja", "Excelente")) %>%
  mutate(calidad = factor(calidad))

# Tabla resumen del dióxido de azufre total
tabla_azufre <- azufre_datos %>%
  group_by(calidad) %>%
  summarise(
    Media_SO2 = round(mean(`dióxido.de.azufre.total`, na.rm = TRUE), 2),
    SD_SO2 = round(sd(`dióxido.de.azufre.total`, na.rm = TRUE), 2),
    n = n()
  )

# Mostrar tabla
kable(tabla_azufre, caption = "Dióxido de azufre total promedio: Calidad Baja vs. Excelente")
Dióxido de azufre total promedio: Calidad Baja vs. Excelente
calidad Media_SO2 SD_SO2 n
Baja 120.84 60.78 2138
Excelente 117.48 41.69 198

t.test(`dióxido.de.azufre.total` ~ calidad, data = azufre_datos)

    Welch Two Sample t-test

data:  dióxido.de.azufre.total by calidad
t = 1.0363, df = 281.18, p-value = 0.3009
alternative hypothesis: true difference in means between group Baja and group Excelente is not equal to 0
95 percent confidence interval:
 -3.021472  9.740080
sample estimates:
     mean in group Baja mean in group Excelente 
               120.8391                117.4798 

20.¿Las muestras con calidad “Muy baja” presentan mayor densidad en promedio que las de calidad “Excelente”?

library(dplyr)
library(knitr)

# Filtrar las muestras con calidad Muy baja y Excelente
densidad_datos <- datos %>%
  filter(calidad %in% c("Muy baja", "Excelente")) %>%
  mutate(calidad = factor(calidad))

# Crear tabla resumen de densidad
tabla_densidad <- densidad_datos %>%
  group_by(calidad) %>%
  summarise(
    Media_densidad = round(mean(densidad, na.rm = TRUE), 5),
    SD_densidad = round(sd(densidad, na.rm = TRUE), 5),
    n = n()
  )

# Mostrar tabla organizada
kable(tabla_densidad, caption = "Densidad promedio: Calidad Muy baja vs. Excelente")
Densidad promedio: Calidad Muy baja vs. Excelente
calidad Media_densidad SD_densidad n
Excelente 102.0531 1002.986 198
Muy baja 533.6535 6463.778 246

t.test(densidad ~ calidad, data = densidad_datos, alternative = "greater")

    Welch Two Sample t-test

data:  densidad by calidad
t = -1.032, df = 259.59, p-value = 0.8485
alternative hypothesis: true difference in means between group Excelente and group Muy baja is greater than 0
95 percent confidence interval:
 -1121.998       Inf
sample estimates:
mean in group Excelente  mean in group Muy baja 
               102.0531                533.6535 

21.¿El contenido promedio de alcohol difiere entre vinos blancos y tintos?

library(dplyr)
library(knitr)

# Verificar los niveles de la variable 'tipo'
unique(datos$tipo)
[1] "white" "rojo" 
tabla_alcohol_tipo <- datos %>%
  filter(tipo %in% c("Blanco", "Tinto")) %>%
  group_by(tipo) %>%
  summarise(
    Media_alcohol = round(mean(alcohol, na.rm = TRUE), 2),
    SD_alcohol = round(sd(alcohol, na.rm = TRUE), 2),
    n = n()
  )

kable(tabla_alcohol_tipo, caption = "Contenido promedio de alcohol por tipo de vino")
Contenido promedio de alcohol por tipo de vino
tipo Media_alcohol SD_alcohol n

t.test(alcohol ~ tipo, data = datos)

    Welch Two Sample t-test

data:  alcohol by tipo
t = -0.59599, df = 1883.4, p-value = 0.5513
alternative hypothesis: true difference in means between group rojo and group white is not equal to 0
95 percent confidence interval:
 -0.15889449  0.08483014
sample estimates:
 mean in group rojo mean in group white 
           10.47683            10.51386 

22.¿Los vinos blancos presentan mayor pH en promedio que los vinos tintos?

library(dplyr)
library(knitr)

# Tabla del pH por tipo de vino
tabla_ph_tipo <- datos %>%
  filter(tipo %in% c("Blanco", "Tinto")) %>%
  group_by(tipo) %>%
  summarise(
    Media_pH = round(mean(pH, na.rm = TRUE), 3),
    SD_pH = round(sd(pH, na.rm = TRUE), 3),
    n = n()
  )

kable(tabla_ph_tipo, caption = "pH promedio por tipo de vino")
pH promedio por tipo de vino
tipo Media_pH SD_pH n

t.test(pH ~ tipo, data = datos, alternative = "greater")

    Welch Two Sample t-test

data:  pH by tipo
t = 27.775, df = 2667.1, p-value < 2.2e-16
alternative hypothesis: true difference in means between group rojo and group white is greater than 0
95 percent confidence interval:
 0.1155691       Inf
sample estimates:
 mean in group rojo mean in group white 
           3.311113            3.188267 

23.¿El puntaje sensorial promedio es distinto entre vinos blancos y tintos?

library(dplyr)
library(knitr)

# Crear tabla de puntaje sensorial por tipo de vino
tabla_sensorial_tipo <- datos %>%
  filter(tipo %in% c("Blanco", "Tinto")) %>%
  group_by(tipo) %>%
  summarise(
    Media_sensorial = round(mean(`puntaje.sensorial`, na.rm = TRUE), 2),
    SD_sensorial = round(sd(`puntaje.sensorial`, na.rm = TRUE), 2),
    n = n()
  )

kable(tabla_sensorial_tipo, caption = "Puntaje sensorial promedio por tipo de vino")
Puntaje sensorial promedio por tipo de vino
tipo Media_sensorial SD_sensorial n

t.test(`puntaje.sensorial` ~ tipo, data = datos)

    Welch Two Sample t-test

data:  puntaje.sensorial by tipo
t = -10.149, df = 2950.8, p-value < 2.2e-16
alternative hypothesis: true difference in means between group rojo and group white is not equal to 0
95 percent confidence interval:
 -0.2886173 -0.1951564
sample estimates:
 mean in group rojo mean in group white 
           5.636023            5.877909 

24.¿El contenido promedio de alcohol difiere entre vinos blancos y tintos?

library(dplyr)
library(knitr)

# Crear tabla con resumen del contenido de alcohol por tipo
tabla_alcohol_tipo <- datos %>%
  filter(tipo %in% c("Blanco", "Tinto")) %>%
  group_by(tipo) %>%
  summarise(
    Media_alcohol = round(mean(alcohol, na.rm = TRUE), 2),
    SD_alcohol = round(sd(alcohol, na.rm = TRUE), 2),
    n = n()
  )

# Mostrar tabla
kable(tabla_alcohol_tipo, caption = "Contenido promedio de alcohol por tipo de vino")
Contenido promedio de alcohol por tipo de vino
tipo Media_alcohol SD_alcohol n

t.test(alcohol ~ tipo, data = datos)

    Welch Two Sample t-test

data:  alcohol by tipo
t = -0.59599, df = 1883.4, p-value = 0.5513
alternative hypothesis: true difference in means between group rojo and group white is not equal to 0
95 percent confidence interval:
 -0.15889449  0.08483014
sample estimates:
 mean in group rojo mean in group white 
           10.47683            10.51386 

25.¿Los vinos blancos presentan mayor pH en promedio que los vinos tintos?

library(dplyr)
library(knitr)

# Tabla del pH por tipo de vino
tabla_ph_tipo <- datos %>%
  filter(tipo %in% c("Blanco", "Tinto")) %>%
  group_by(tipo) %>%
  summarise(
    Media_pH = round(mean(pH, na.rm = TRUE), 3),
    SD_pH = round(sd(pH, na.rm = TRUE), 3),
    n = n()
  )

# Mostrar la tabla
kable(tabla_ph_tipo, caption = "pH promedio por tipo de vino (Blanco vs. Tinto)")
pH promedio por tipo de vino (Blanco vs. Tinto)
tipo Media_pH SD_pH n

# Hipótesis: vinos blancos tienen mayor pH que los tintos
t.test(pH ~ tipo, data = datos, alternative = "greater")

    Welch Two Sample t-test

data:  pH by tipo
t = 27.775, df = 2667.1, p-value < 2.2e-16
alternative hypothesis: true difference in means between group rojo and group white is greater than 0
95 percent confidence interval:
 0.1155691       Inf
sample estimates:
 mean in group rojo mean in group white 
           3.311113            3.188267 

26.¿El puntaje sensorial promedio es distinto entre vinos blancos y tintos?

library(dplyr)
library(knitr)

# Tabla con puntaje sensorial por tipo de vino
tabla_sensorial <- datos %>%
  filter(tipo %in% c("Blanco", "Tinto")) %>%
  group_by(tipo) %>%
  summarise(
    Media_puntaje = round(mean(`puntaje.sensorial`, na.rm = TRUE), 2),
    SD_puntaje = round(sd(`puntaje.sensorial`, na.rm = TRUE), 2),
    n = n()
  )

kable(tabla_sensorial, caption = "Puntaje sensorial promedio por tipo de vino")
Puntaje sensorial promedio por tipo de vino
tipo Media_puntaje SD_puntaje n

t.test(`puntaje.sensorial` ~ tipo, data = datos, alternative = "two.sided")

    Welch Two Sample t-test

data:  puntaje.sensorial by tipo
t = -10.149, df = 2950.8, p-value < 2.2e-16
alternative hypothesis: true difference in means between group rojo and group white is not equal to 0
95 percent confidence interval:
 -0.2886173 -0.1951564
sample estimates:
 mean in group rojo mean in group white 
           5.636023            5.877909 

TALLER 2

# Cargar librería
library(knitr)

# Datos del problema
k <- 5  # tratamientos
n <- 4  # réplicas por tratamiento
N <- k * n

# Suma de cuadrados
SC_trat <- 800
SC_error <- 400
SC_total <- SC_trat + SC_error

# Grados de libertad
gl_trat <- k - 1
gl_error <- N - k
gl_total <- N - 1

# Cuadrado medio
CM_trat <- SC_trat / gl_trat
CM_error <- SC_error / gl_error

# Razón F observada
F_obs <- CM_trat / CM_error

# Valor-p usando la distribución F
valor_p <- pf(F_obs, df1 = gl_trat, df2 = gl_error, lower.tail = FALSE)

# Tabla ANOVA completada
anova_tabla <- data.frame(
  `Fuente de variación` = c("Tratamiento", "Error", "Total"),
  `Suma de cuadrados` = c(SC_trat, SC_error, SC_total),
  `Grados de libertad` = c(gl_trat, gl_error, gl_total),
  `Cuadrado medio` = c(round(CM_trat, 2), round(CM_error, 2), NA),
  `Razón F` = c(round(F_obs, 2), NA, NA),
  `Valor-p` = c(round(valor_p, 4), NA, NA)
)

# Mostrar tabla en formato bonito
kable(anova_tabla, caption = "Tabla ANOVA para cinco tratamientos con cuatro réplicas cada uno")
Tabla ANOVA para cinco tratamientos con cuatro réplicas cada uno
Fuente.de.variación Suma.de.cuadrados Grados.de.libertad Cuadrado.medio Razón.F Valor.p
Tratamiento 800 4 200.00 7.5 0.0016
Error 400 15 26.67 NA NA
Total 1200 19 NA NA NA

# Modelo e hipótesis
cat("\nModelo estadístico:\n")

Modelo estadístico:
cat("Y_ij = µ + τ_i + ε_ij\n")
Y_ij = µ + τ_i + ε_ij
cat("\nHipótesis:\n")

Hipótesis:
cat("H₀: τ₁ = τ₂ = ... = τ₅ (no hay diferencia entre tratamientos)\n")
H₀: τ₁ = τ₂ = ... = τ₅ (no hay diferencia entre tratamientos)
cat("H₁: al menos un τ_i es diferente\n")
H₁: al menos un τ_i es diferente
# Conclusión
cat("\nConclusión:\n")

Conclusión:
if (valor_p < 0.05) {
  cat("Como el valor-p =", round(valor_p, 4), "< 0.05, se rechaza H₀. Hay diferencias significativas entre tratamientos.\n")
} else {
  cat("Como el valor-p =", round(valor_p, 4), "≥ 0.05, no se rechaza H₀. No hay diferencias significativas entre tratamientos.\n")
}
Como el valor-p = 0.0016 < 0.05, se rechaza H₀. Hay diferencias significativas entre tratamientos.
# Cargar librería
library(knitr)

# Información del ANOVA y promedios de cada mezcla
valor_p <- 0.01

# Tabla de promedios
mezclas <- data.frame(
  Mezcla = c("A", "B", "C", "D"),
  Peso_Promedio = c(10000, 7000, 8000, 7500)
)

# Mostrar tabla de promedios
kable(mezclas, caption = "Peso promedio por mezcla")
Peso promedio por mezcla
Mezcla Peso_Promedio
A 10000
B 7000
C 8000
D 7500

# Respuesta a los incisos
cat("\n\n--- Inciso a) ---\n")


--- Inciso a) ---
cat("¿Las mezclas difieren de manera significativa en cuanto a su peso molecular?\n")
¿Las mezclas difieren de manera significativa en cuanto a su peso molecular?
if (valor_p < 0.05) {
  cat("Sí. El valor-p = 0.01 < 0.05 indica que hay diferencias significativas entre al menos dos mezclas.\n")
} else {
  cat("No. El valor-p >= 0.05 indica que no hay diferencias significativas entre las mezclas.\n")
}
Sí. El valor-p = 0.01 < 0.05 indica que hay diferencias significativas entre al menos dos mezclas.
cat("\n\n--- Inciso b) ---\n")


--- Inciso b) ---
cat("¿Se puede asegurar que la mezcla B logra un menor peso molecular?\n")
¿Se puede asegurar que la mezcla B logra un menor peso molecular?
cat("Aunque el promedio de B (7000) es el más bajo, el ANOVA no indica cuáles mezclas difieren específicamente.\n")
Aunque el promedio de B (7000) es el más bajo, el ANOVA no indica cuáles mezclas difieren específicamente.
cat("Para afirmarlo con certeza, es necesario aplicar una prueba post-hoc como Tukey HSD.\n")
Para afirmarlo con certeza, es necesario aplicar una prueba post-hoc como Tukey HSD.
cat("Por tanto, NO se puede asegurar solo con los promedios y el ANOVA general.\n")
Por tanto, NO se puede asegurar solo con los promedios y el ANOVA general.
cat("\n\n--- Inciso c) ---\n")


--- Inciso c) ---
cat("¿Qué pasa si no se cumple el supuesto de varianza constante?\n")
¿Qué pasa si no se cumple el supuesto de varianza constante?
cat("Si las varianzas no son homogéneas entre mezclas, se viola un supuesto importante del ANOVA.\n")
Si las varianzas no son homogéneas entre mezclas, se viola un supuesto importante del ANOVA.
cat("Esto puede invalidar el valor-p obtenido y, por tanto, la conclusión del inciso a).\n")
Esto puede invalidar el valor-p obtenido y, por tanto, la conclusión del inciso a).
cat("En ese caso, se debería aplicar un ANOVA robusto o una prueba no paramétrica como Kruskal-Wallis.\n")
En ese caso, se debería aplicar un ANOVA robusto o una prueba no paramétrica como Kruskal-Wallis.
# Cargar librerías necesarias
library(dplyr)
library(ggplot2)
library(knitr)
library(car)

# Datos
spray <- data.frame(
  marca = rep(c("1", "2", "3"), each = 6),
  efectividad = c(
    72, 65, 67, 75, 63, 62,     # Marca 1
    55, 59, 68, 70, 53, 50,     # Marca 2
    64, 74, 61, 58, 51, 69      # Marca 3
  )
)

# a) Modelo estadístico y formulación de hipótesis
cat("\n--- a) Hipótesis y modelo ---\n")

--- a) Hipótesis y modelo ---
cat("H0: Las medias de efectividad son iguales entre las marcas\n")
H0: Las medias de efectividad son iguales entre las marcas
cat("Ha: Al menos una media de efectividad es diferente\n")
Ha: Al menos una media de efectividad es diferente
cat("Modelo: Y_ij = μ + τ_i + ε_ij\n")
Modelo: Y_ij = μ + τ_i + ε_ij
# b) ANOVA
modelo <- aov(efectividad ~ marca, data = spray)
summary(modelo)
            Df Sum Sq Mean Sq F value Pr(>F)
marca        2  200.8  100.39   1.885  0.186
Residuals   15  799.0   53.27               
# c) ¿Hay diferencias significativas?
cat("\n--- c) ¿Hay alguna marca mejor? ---\n")

--- c) ¿Hay alguna marca mejor? ---
tukey <- TukeyHSD(modelo)
print(tukey)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = efectividad ~ marca, data = spray)

$marca
         diff        lwr       upr     p adj
2-1 -8.166667 -19.111716  2.778382 0.1623861
3-1 -4.500000 -15.445049  6.445049 0.5475102
3-2  3.666667  -7.278382 14.611716 0.6665848
# d) Intervalos de confianza del 95%
conf_int <- spray %>%
  group_by(marca) %>%
  summarise(
    Media = mean(efectividad),
    SD = sd(efectividad),
    n = n(),
    IC_Inf = Media - qt(0.975, df = n - 1) * SD / sqrt(n),
    IC_Sup = Media + qt(0.975, df = n - 1) * SD / sqrt(n)
  )
kable(conf_int, caption = "Intervalos de confianza al 95% para cada marca")
Intervalos de confianza al 95% para cada marca
marca Media SD n IC_Inf IC_Sup
1 67.33333 5.163978 6 61.91407 72.75260
2 59.16667 8.183316 6 50.57880 67.75453
3 62.83333 8.134290 6 54.29692 71.36975

# e) Gráficos
ggplot(spray, aes(x = marca, y = efectividad)) +
  stat_summary(fun = mean, geom = "point", size = 3, color = "red") +
  geom_boxplot(fill = "lightblue") +
  labs(title = "Efectividad por Marca", x = "Marca de Spray", y = "% de moscas muertas") +
  theme_minimal()


# f) Supuestos del ANOVA

# Normalidad de residuos
residuos <- modelo$residuals
shapiro.test(residuos)

    Shapiro-Wilk normality test

data:  residuos
W = 0.95404, p-value = 0.4919
# Homogeneidad de varianzas
leveneTest(efectividad ~ marca, data = spray)
Aviso en leveneTest.default(y = y, group = group, ...) :
  group coerced to factor.
Levene's Test for Homogeneity of Variance (center = median)
      Df F value Pr(>F)
group  2  0.6358 0.5432
      15               
# Cargar librerías necesarias
library(dplyr)
library(ggplot2)
library(car)

# Datos
tiempo <- data.frame(
  tratamiento = rep(c("Control", "T2", "T3", "T4"), each = 7),
  minutos = c(
    213, 214, 204, 208, 212, 200, 207,    # Control
    76, 85, 78, 78, 75, 75, 82,           # T2
    87, 67, 85, 64, 69, 63, 90,           # T3
    84, 82, 84, 91, 79, 73, 90            # T4
  )
)

# c) Hipótesis
cat("--- c) Hipótesis ---\n")
--- c) Hipótesis ---
cat("H0: Todas las medias de tiempo de cocción son iguales\n")
H0: Todas las medias de tiempo de cocción son iguales
cat("Ha: Al menos una media es diferente\n")
Ha: Al menos una media es diferente
# d) Gráfico de cajas y medias
ggplot(tiempo, aes(x = tratamiento, y = minutos)) +
  geom_boxplot(fill = "lightblue") +
  stat_summary(fun = mean, geom = "point", size = 3, color = "red") +
  labs(title = "Tiempo de cocción por tratamiento", y = "Minutos") +
  theme_minimal()

# e) ANOVA
modelo <- aov(minutos ~ tratamiento, data = tiempo)
summary(modelo)
            Df Sum Sq Mean Sq F value Pr(>F)    
tratamiento  3  88125   29375   538.8 <2e-16 ***
Residuals   24   1309      55                   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# f) ¿Cuál tratamiento es mejor?
cat("\n--- f) Comparación de tratamientos (Tukey HSD) ---\n")

--- f) Comparación de tratamientos (Tukey HSD) ---
TukeyHSD(modelo)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = minutos ~ tratamiento, data = tiempo)

$tratamiento
                  diff         lwr         upr     p adj
T2-Control -129.857143 -140.745170 -118.969116 0.0000000
T3-Control -133.285714 -144.173741 -122.397687 0.0000000
T4-Control -125.000000 -135.888027 -114.111973 0.0000000
T3-T2        -3.428571  -14.316598    7.459456 0.8208251
T4-T2         4.857143   -6.030884   15.745170 0.6141070
T4-T3         8.285714   -2.602313   19.173741 0.1819774
# g) Supuestos del modelo
par(mfrow = c(1, 2))

plot(modelo, which = 1)  # Residuos vs ajustados
plot(modelo, which = 2)  # Q-Q normal


# Test de normalidad (Shapiro-Wilk)
shapiro.test(modelo$residuals)

    Shapiro-Wilk normality test

data:  modelo$residuals
W = 0.98131, p-value = 0.8805
# h) Homogeneidad de varianzas (Levene)
leveneTest(minutos ~ tratamiento, data = tiempo)
Aviso en leveneTest.default(y = y, group = group, ...) :
  group coerced to factor.
Levene's Test for Homogeneity of Variance (center = median)
      Df F value  Pr(>F)  
group  3  2.6484 0.07189 .
      24                  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# Datos
almidon <- factor(rep(c(2, 5, 10), each = 4))
dureza <- c(4.3, 5.2, 4.8, 4.5, 
            6.5, 7.3, 6.9, 6.1,
            9.0, 7.8, 8.5, 8.1)
1
[1] 1
# Tabla de datos
datos <- data.frame(almidon, dureza)

# a) ANOVA
modelo <- aov(dureza ~ almidon, data = datos)
summary(modelo)
            Df Sum Sq Mean Sq F value   Pr(>F)    
almidon      2  26.73   13.36    58.1 7.16e-06 ***
Residuals    9   2.07    0.23                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# b) Pruebas post hoc (Tukey)
TukeyHSD(modelo)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = dureza ~ almidon, data = datos)

$almidon
     diff       lwr      upr     p adj
5-2  2.00 1.0531848 2.946815 0.0006016
10-2 3.65 2.7031848 4.596815 0.0000052
10-5 1.65 0.7031848 2.596815 0.0022940
# c) Medias por grupo
aggregate(dureza ~ almidon, data = datos, mean)

# d) Verificación de supuestos
par(mfrow=c(2,2))
plot(modelo)


# Histograma y prueba de normalidad
hist(residuals(modelo), main="Residuos", col="skyblue")

shapiro.test(residuals(modelo))

    Shapiro-Wilk normality test

data:  residuals(modelo)
W = 0.93444, p-value = 0.4295
# Prueba de igualdad de varianzas (homocedasticidad)
bartlett.test(dureza ~ almidon, data = datos)

    Bartlett test of homogeneity of variances

data:  dureza by almidon
Bartlett's K-squared = 0.25398, df = 2, p-value = 0.8807
# Datos
aglutinante <- factor(rep(c("PVP", "CMC", "Gre"), each = 5))
friabilidad <- c(
  0.485, 0.250, 0.073, 0.205, 0.161,     # PVP
  9.64, 9.37, 9.53, 8.86, 9.79,          # CMC
  0.289, 0.275, 0.612, 0.152, 0.137      # Gre
)

datos <- data.frame(aglutinante, friabilidad)

# a) Diseño experimental: 
cat("Diseño experimental: Diseño completamente al azar (DCA) con un solo factor: tipo de aglutinante.\n\n")
Diseño experimental: Diseño completamente al azar (DCA) con un solo factor: tipo de aglutinante.
# b–c) ANOVA + hipótesis:
modelo <- aov(friabilidad ~ aglutinante, data = datos)
summary(modelo)
            Df Sum Sq Mean Sq F value   Pr(>F)    
aglutinante  2 280.56  140.28    2234 3.69e-16 ***
Residuals   12   0.75    0.06                     
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
# H0: Las medias de % de friabilidad son iguales entre aglutinantes.
# H1: Al menos una media difiere.

# d) Análisis post-hoc
TukeyHSD(modelo)
  Tukey multiple comparisons of means
    95% family-wise confidence level

Fit: aov(formula = friabilidad ~ aglutinante, data = datos)

$aglutinante
           diff        lwr        upr    p adj
Gre-CMC -9.1450 -9.5678214 -8.7221786 0.000000
PVP-CMC -9.2032 -9.6260214 -8.7803786 0.000000
PVP-Gre -0.0582 -0.4810214  0.3646214 0.928795
# e) Supuestos: gráficos
par(mfrow=c(2,2))
plot(modelo)


# Normalidad
shapiro.test(residuals(modelo))

    Shapiro-Wilk normality test

data:  residuals(modelo)
W = 0.92419, p-value = 0.2231
# Igualdad de varianzas
bartlett.test(friabilidad ~ aglutinante, data = datos)

    Bartlett test of homogeneity of variances

data:  friabilidad by aglutinante
Bartlett's K-squared = 2.8697, df = 2, p-value = 0.2381
# Medias por grupo
aggregate(friabilidad ~ aglutinante, data = datos, mean)
NA

Conclisión

El presente taller ha proporcionado una sólida aproximación práctica a la aplicación del Análisis de Varianza (ANOVA) como herramienta fundamental en el diseño experimental dentro de diversos contextos industriales, tales como el alimentario y el farmacéutico. Mediante la implementación en RStudio, se logró demostrar la utilidad del ANOVA para determinar si las diferencias observadas en los resultados experimentales son estadísticamente significativas o meramente atribuibles al azar. El desarrollo del proyecto, desde el planteamiento del problema hasta la importación y preparación de datos, y la formulación de preguntas específicas sobre variables como el contenido de alcohol, pH, acidez y azúcar residual en vinos, evidenció la rigurosidad metodológica necesaria para un análisis estadístico fiable. La aplicación de ANOVA permitió evaluar la influencia de un solo factor sobre una variable de respuesta, comparando varios niveles del mismo y, crucialmente, interpretando los resultados estadísticos a la luz de los supuestos del modelo. Se lograron satisfactoriamente los objetivos específicos planteados, incluyendo la formulación de hipótesis nula y alternativa, la construcción de tablas ANOVA completas con sus respectivos grados de libertad, cuadrados medios, razón F y valor-p. La verificación gráfica y estadística de los supuestos de normalidad y homogeneidad de varianzas resultó indispensable para asegurar la validez de las inferencias realizadas. Finalmente, la interpretación de los resultados del ANOVA y, en caso de ser necesario, la realización de análisis post-hoc, facilitaron la identificación de tratamientos responsables de diferencias significativas

Bibliografía

LS0tDQp0aXRsZTogIlRhbGxlciAxOiBEaXNlw7FvIGRlIEV4cGVyaW1lbnRvcyINCmF1dGhvcjogfA0KICBZZXNzaWNhIE5hdGFsaWEgQ3VjdW51YsOhIENhbWFyZ28gLSAyMDIyMTE1OTQgIA0KICBaaGFyaWNrIFZhbmVzc2EgTW9sYW5vIEzDs3BleiAtIDIwMjIxMTc3MyAgDQogIEJhbGVyaWEgSnVsaWFuYSBSb3NhcyBQw6lyZXogLSAyMDIzMTAwMzYNCmRhdGU6IDExLzA3LzIwMjUNCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMgUGxhbnRlYW1pZW50byBkZWwgUHJvYmxlbWENCkVuIGRpdmVyc2FzIGluZHVzdHJpYXMgY29tbyBsYSBhbGltZW50YXJpYSwgcXXDrW1pY2EgeSBmYXJtYWPDqXV0aWNh4oCUIGVzIGZyZWN1ZW50ZSBsYSBuZWNlc2lkYWQgZGUgdG9tYXIgZGVjaXNpb25lcyBmdW5kYW1lbnRhZGFzIHNvYnJlIGN1w6FsIHRyYXRhbWllbnRvLCBmb3JtdWxhY2nDs24gbyBtw6l0b2RvIGV4cGVyaW1lbnRhbCBwcm9kdWNlIGxvcyBtZWpvcmVzIHJlc3VsdGFkb3MuIFBhcmEgZXN0bywgc2UgcmVxdWllcmUgaWRlbnRpZmljYXIgc2kgbGFzIGRpZmVyZW5jaWFzIG9ic2VydmFkYXMgZW4gbG9zIHJlc3VsdGFkb3MgZXhwZXJpbWVudGFsZXMgc29uIGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdmFzIG8gc29sbyBzZSBkZWJlbiBhbCBhemFyLiBVbmEgbWV0b2RvbG9nw61hIGFtcGxpYW1lbnRlIHV0aWxpemFkYSBwYXJhIGVzdGUgZmluIGVzIGVsIGFuw6FsaXNpcyBkZSB2YXJpYW56YSAoQU5PVkEpLCBxdWUgcGVybWl0ZSBldmFsdWFyIGxhIGluZmx1ZW5jaWEgZGUgdW4gc29sbyBmYWN0b3Igc29icmUgdW5hIHZhcmlhYmxlIGRlIHJlc3B1ZXN0YSwgY29tcGFyYW5kbyB2YXJpb3Mgbml2ZWxlcyBkZWwgbWlzbW8uIFNpbiBlbWJhcmdvLCB1bmEgYXBsaWNhY2nDs24gYWRlY3VhZGEgZGUgZXN0YSB0w6ljbmljYSBleGlnZSBjdW1wbGlyIGNpZXJ0b3Mgc3VwdWVzdG9zIGVzdGFkw61zdGljb3MsIGludGVycHJldGFyIGNvcnJlY3RhbWVudGUgbG9zIHJlc3VsdGFkb3MgeSBwcm9wb25lciByZWNvbWVuZGFjaW9uZXMgcHLDoWN0aWNhcyBjb24gYmFzZSBlbiBlbGxvcy4NCg0KIyBPYmpldGl2byBHZW5lcmFsDQpBcGxpY2FyIGVsIGFuw6FsaXNpcyBkZSB2YXJpYW56YSBkZSB1biBzb2xvIGZhY3RvciBwYXJhIGV2YWx1YXIgZWwgZWZlY3RvIGRlIGRpc3RpbnRvcyB0cmF0YW1pZW50b3Mgc29icmUgdW5hIHZhcmlhYmxlIGRlIHJlc3B1ZXN0YSBlbiBkaXZlcnNvcyBjb250ZXh0b3MgZXhwZXJpbWVudGFsZXMgaW5kdXN0cmlhbGVzLCBpbnRlcnByZXRhbmRvIGxvcyByZXN1bHRhZG9zIGVzdGFkw61zdGljb3MgeSB2ZXJpZmljYW5kbyBlbCBjdW1wbGltaWVudG8gZGUgbG9zIHN1cHVlc3RvcyBkZWwgbW9kZWxvLg0KDQojIE9iamV0aXZvcyBFc3BlY8OtZmljb3MNCjEuIEZvcm11bGFyIGNvcnJlY3RhbWVudGUgbGFzIGhpcMOzdGVzaXMgbnVsYSB5IGFsdGVybmF0aXZhIGVuIGNhZGEgY29udGV4dG8gZXhwZXJpbWVudGFsLg0KDQoyLiBDb25zdHJ1aXIgdGFibGFzIEFOT1ZBIGNvbXBsZXRhcywgaW5jbHV5ZW5kbyBncmFkb3MgZGUgbGliZXJ0YWQsIGN1YWRyYWRvcyBtZWRpb3MsIHJhesOzbiBGIHkgdmFsb3ItcC4NCg0KMy4gVmVyaWZpY2FyIGdyw6FmaWNhbWVudGUgeSBlc3RhZMOtc3RpY2FtZW50ZSBsb3Mgc3VwdWVzdG9zIGRlIG5vcm1hbGlkYWQgeSBob21vZ2VuZWlkYWQgZGUgdmFyaWFuemFzLg0KDQo0LiBJbnRlcnByZXRhciBsb3MgcmVzdWx0YWRvcyBkZWwgYW7DoWxpc2lzIGRlIHZhcmlhbnphIHBhcmEgZGV0ZXJtaW5hciBzaSBleGlzdGVuIGRpZmVyZW5jaWFzIHNpZ25pZmljYXRpdmFzIGVudHJlIHRyYXRhbWllbnRvcy4NCg0KNS4gUmVhbGl6YXIgYW7DoWxpc2lzIHBvc3QgaG9jIGN1YW5kbyBzZWEgbmVjZXNhcmlvLCBwYXJhIGlkZW50aWZpY2FyIHRyYXRhbWllbnRvcyByZXNwb25zYWJsZXMgZGUgbGFzIGRpZmVyZW5jaWFzLg0KDQo2LiBQcm9wb25lciByZWNvbWVuZGFjaW9uZXMgcHLDoWN0aWNhcyBiYXNhZGFzIGVuIGxvcyByZXN1bHRhZG9zIGVzdGFkw61zdGljb3MgcGFyYSBsYSBvcHRpbWl6YWNpw7NuIGRlIHByb2Nlc29zIGluZHVzdHJpYWxlcyBvIGZhcm1hY8OpdXRpY29zLg0KDQojIEFudGVjZWRlbnRlcw0KRWwgYW7DoWxpc2lzIGRlIHZhcmlhbnphIChBTk9WQSkgZXMgdW5hIHTDqWNuaWNhIGVzdGFkw61zdGljYSBkZXNhcnJvbGxhZGEgcG9yIFJvbmFsZCBBLiBGaXNoZXIgZW4gZWwgc2lnbG8gWFgsIGFtcGxpYW1lbnRlIHV0aWxpemFkYSBlbiBleHBlcmltZW50YWNpw7NuIHBhcmEgY29tcGFyYXIgbGFzIG1lZGlhcyBkZSB0cmVzIG8gbcOhcyBncnVwb3MgYmFqbyBkaXN0aW50YXMgY29uZGljaW9uZXMuIFN1IGFwbGljYWNpw7NuIGVzIGZ1bmRhbWVudGFsIGVuIGVsIGRpc2XDsW8gZXhwZXJpbWVudGFsLCB5YSBxdWUgcGVybWl0ZSBzZXBhcmFyIGxhIHZhcmlhYmlsaWRhZCBhdHJpYnVpYmxlIGFsIHRyYXRhbWllbnRvIGRlIGxhIHZhcmlhYmlsaWRhZCBhbGVhdG9yaWEgbyBleHBlcmltZW50YWwuIEVuIGxhIGluZHVzdHJpYSBmYXJtYWPDqXV0aWNhLCBwb3IgZWplbXBsbywgc2UgZW1wbGVhIHBhcmEgZXZhbHVhciBsYSBpbmZsdWVuY2lhIGRlIGluZ3JlZGllbnRlcyBhY3Rpdm9zIG8gZXhjaXBpZW50ZXMgc29icmUgY2FyYWN0ZXLDrXN0aWNhcyBjb21vIGxhIGZyaWFiaWxpZGFkIG8gbGEgZHVyZXphIGRlIGxhcyB0YWJsZXRhcy4gRW4gZWwgc2VjdG9yIGFsaW1lbnRhcmlvLCBwdWVkZSB1c2Fyc2UgcGFyYSBhbmFsaXphciBsYSBlZmVjdGl2aWRhZCBkZSBkaXN0aW50b3MgY29uc2VydmFudGVzIG8gdGllbXBvcyBkZSBjb2NjacOzbi4gQWRlbcOhcywgZW4gbGEgaW5kdXN0cmlhIHF1w61taWNhIGVzIMO6dGlsIHBhcmEgZXN0dWRpYXIgbWV6Y2xhcyB5IHByb2Nlc29zIHF1ZSBhZmVjdGFuIHByb3BpZWRhZGVzIGZpc2ljb3F1w61taWNhcyBkZSBsb3MgcHJvZHVjdG9zLg0KDQpFbCBwcmVzZW50ZSB0cmFiYWpvIHJlY29waWxhIGRpdmVyc29zIGVqZXJjaWNpb3MgZW4gbG9zIHF1ZSBzZSBhcGxpY2FuIGVzdG9zIHByaW5jaXBpb3MgY29uIGRhdG9zIGV4cGVyaW1lbnRhbGVzIHJlYWxlcyBvIHNpbXVsYWRvcywgYnVzY2FuZG8gZm9ydGFsZWNlciBsYSBjb21wcmVuc2nDs24gdGXDs3JpY2EgeSBwcsOhY3RpY2EgZGVsIEFOT1ZBIGVuIGNvbnRleHRvcyBhcGxpY2Fkb3MuDQoNCiMgRGVzYXJyb2xsbyBkZWwgUHJveWVjdG8NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQpsaWJyYXJ5KGRhdGEudGFibGUpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShyZWFkeGwpDQpsaWJyYXJ5KHdyaXRleGwpDQpsaWJyYXJ5KGNhcikNCmBgYA0KDQojIyBQYXNvIGEgcGFzbw0KUHJpbWVybywgc2UgZm9ybXVsbyBlbCBwbGFudGVhbWllbnRvIGRlbCBwcm9ibGVtYSB5IGRlZmluaWVuZG8gdGFudG8gZWwgb2JqZXRpdm8gZ2VuZXJhbCBjb21vIGxvcyBvYmpldGl2b3MgZXNwZWPDrWZpY29zIGRlIGVsIHRhbGxlciBkYWRvIHBvciBlbCBkb2NlbnRlLiBMdWVnbywgY2FyZ3XDqSBlbiBSIGxhcyBiaWJsaW90ZWNhcyBuZWNlc2FyaWFzIHBhcmEgdHJhYmFqYXIgY29uIGxvcyBkYXRvcyAoZGF0YS50YWJsZSwgZHBseXIsIHJlYWR4bCwgd3JpdGV4bCB5IGNhcikuIERlc3B1w6lzLCBpbXBvcnTDqSBlbCBjb25qdW50byBkZSBkYXRvcyByZWxhY2lvbmFkbyBjb24gdmlub3MgYmxhbmNvcyB5IHRpbnRvcywgeSBsbyBwcmVwYXLDqSBwYXJhIGVsIGFuw6FsaXNpcy4gQSBjb250aW51YWNpw7NuLCBwbGFudGXDqSB1bmEgc2VyaWUgZGUgcHJlZ3VudGFzIHF1ZSBtZSBwZXJtaXRpcsOhbiBleHBsb3JhciB5IGNvbXBhcmFyIGRpZmVyZW50ZXMgdmFyaWFibGVzIGNvbW8gZWwgY29udGVuaWRvIGRlIGFsY29ob2wsIGVsIHBILCBsYSBhY2lkZXosIGVsIGF6w7pjYXIgcmVzaWR1YWwsIGxhIGNhbGlkYWQgc2Vuc29yaWFsIHkgb3Ryb3MgZmFjdG9yZXMuIEVzdGFzIHByZWd1bnRhcyBndWlhcsOhbiBlbCBhbsOhbGlzaXMgZXN0YWTDrXN0aWNvIHBhc28gYSBwYXNvLCBTZSByZXZpc2EgbGEgdWJpY2FjaW9uIGRlIG51ZXN0cm8gcHJveWVjdG8gZGFuZG8gY29tbyBhZmlybWF0aXZvIGVuIGxhcyBjYXJwZXRhcyBjcmVhZGFzIGFudGVyaW9ybWVudGUNCg0KYGBge3J9DQpsaXN0LmZpbGVzKCIuLi9EYXRvcyIpDQpgYGANCmBgYHtyfQ0KZGF0YSA8LSByZWFkLmNzdigiLi4vRGF0b3Mvd2luZXF1YWxpdHkuY3N2IiwNCiAgICAgICAgICAgICAgICAgc2VwID0gIjsiLA0KICAgICAgICAgICAgICAgICBkZWMgPSAiLCIsIyBzw61tYm9sbyBzZSB1c2EgY29tbyBzZXBhcmFkb3IgZGVjaW1hbA0KICAgICAgICAgICAgICAgICBmaWxlRW5jb2RpbmcgPSAibGF0aW4xIikgIyBlc3BlY2lmaWNhIGxhIGNvZGlmaWNhY2nDs24gZGUgY2FyYWN0ZXJlcyBkZWwgYXJjaGl2bw0KYGBgDQoNCmBgYHtyfQ0Kc3RyKGRhdGEpDQpgYGANCmBgYHtyfQ0Kc3VtbWFyeShkYXRhJGFjaWRlei52b2zDoXRpbCkNCmBgYA0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrbml0cikNCg0KIyBDcmVhciBmdW5jacOzbiBwYXJhIGxvcyBlc3RhZMOtc3RpY29zDQpjYWxjX2VzdGFkaXN0aWNvcyA8LSBmdW5jdGlvbih4KSB7DQogIGMoDQogICAgTWVkaWEgPSBtZWFuKHgsIG5hLnJtID0gVFJVRSksDQogICAgTWVkaWFuYSA9IG1lZGlhbih4LCBuYS5ybSA9IFRSVUUpLA0KICAgIGBEZXN2aWFjacOzbiBFc3TDoW5kYXJgID0gc2QoeCwgbmEucm0gPSBUUlVFKSwNCiAgICBNw61uaW1vID0gbWluKHgsIG5hLnJtID0gVFJVRSksDQogICAgTcOheGltbyA9IG1heCh4LCBuYS5ybSA9IFRSVUUpLA0KICAgIGBRMSAoMjUlKWAgPSBxdWFudGlsZSh4LCAwLjI1LCBuYS5ybSA9IFRSVUUpLA0KICAgIGBRMiAoNTAlKWAgPSBxdWFudGlsZSh4LCAwLjUwLCBuYS5ybSA9IFRSVUUpLA0KICAgIGBRMyAoNzUlKWAgPSBxdWFudGlsZSh4LCAwLjc1LCBuYS5ybSA9IFRSVUUpDQogICkNCn0NCg0KIyBDYWxjdWxhciBlc3RhZMOtc3RpY29zIHBvciBhbGNvaG9sIChlamVtcGxvIGdlbmVyYWwpDQplc3RhZGlzdGljb3MgPC0gY2FsY19lc3RhZGlzdGljb3MoZGF0YSRhbGNvaG9sKQ0KZXN0YWRpc3RpY29zDQoNCmBgYA0KYGBge3J9DQpkYXRhIDwtIHJlYWQuY3N2KCIuLi9kYXRvcy93aW5lcXVhbGl0eS5jc3YiLA0KICAgICAgICAgICAgICAgICBzZXAgPSAiOyIsDQogICAgICAgICAgICAgICAgIGRlYyA9ICIsIiwjIHPDrW1ib2xvIHNlIHVzYSBjb21vIHNlcGFyYWRvciBkZWNpbWFsDQogICAgICAgICAgICAgICAgIGZpbGVFbmNvZGluZyA9ICJsYXRpbjEiKSAjIGVzcGVjaWZpY2EgbGEgY29kaWZpY2FjacOzbiBkZSBjYXJhY3RlcmVzIGRlbCBhcmNoaXZvDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KHJlYWRyKQ0KDQpkYXRvcyA8LSByZWFkX2RlbGltKCJDOi9Vc2Vycy9Vc3VhcmlvL09uZURyaXZlL0VzY3JpdG9yaW8vUHJveWVjdG8vRGF0b3Mvd2luZXF1YWxpdHkuY3N2IiwNCiAgICAgICAgICAgICAgICAgICAgZGVsaW0gPSAiOyIsDQogICAgICAgICAgICAgICAgICAgIGxvY2FsZSA9IGxvY2FsZShkZWNpbWFsX21hcmsgPSAiLCIsIGVuY29kaW5nID0gIkxhdGluMSIpKQ0KYGBgDQoNCg0KIyBQcmVndW50YXMNCg0KMS7Cv0VsIGNvbnRlbmlkbyBwcm9tZWRpbyBkZSBhbGNvaG9sIHZhcsOtYSBzZWfDum4gZWwgbml2ZWwgZGUgYWNpZGV6IChwb3IgZWplbXBsbywgw4FjaWRvIHZzLiBNdXkgw6FjaWRvKT8NCg0KYGBge3J9DQojIEZpbHRyYXIgc29sbyBsb3Mgbml2ZWxlcyBkZXNlYWRvcyBkZSBhY2lkZXoNCmFjaWRlel9kYXRvcyA8LSBkYXRhICU+JQ0KICBmaWx0ZXIoYWNpZGV6ICVpbiUgYygiw4FjaWRvIiwgIk11eSDDoWNpZG8iKSkgJT4lDQogIG11dGF0ZShhY2lkZXogPSBmYWN0b3IoYWNpZGV6KSkgICMgQXNlZ3VyYXIgcXVlIHNlYSBmYWN0b3INCg0KIyBDb21wYXJhciBwcm9tZWRpb3MgZGUgYWxjb2hvbA0KYWNpZGV6X2RhdG9zICU+JQ0KICBncm91cF9ieShhY2lkZXopICU+JQ0KICBzdW1tYXJpc2UoTWVkaWFfQWxjb2hvbCA9IG1lYW4oYWxjb2hvbCwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIFNEX0FsY29ob2wgPSBzZChhbGNvaG9sLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgbiA9IG4oKSkNCg0KIyBSZWFsaXphciBwcnVlYmEgdA0KdC50ZXN0KGFsY29ob2wgfiBhY2lkZXosIGRhdGEgPSBhY2lkZXpfZGF0b3MpDQoNCmRhdGFfZmlsdHJhZGEgPC0gc3Vic2V0KGRhdGEsIGFjaWRleiAlaW4lIGMoIsOBY2lkbyIsICJNdXkgw6FjaWRvIikpDQoNCnRhYmxlKGRhdGFfZmlsdHJhZGEkYWNpZGV6KQ0KDQp0LnRlc3QoYWxjb2hvbCB+IGFjaWRleiwgZGF0YSA9IGRhdGFfZmlsdHJhZGEpDQoNCmJ5KGRhdGFfZmlsdHJhZGEkYWxjb2hvbCwgZGF0YV9maWx0cmFkYSRhY2lkZXosIHNoYXBpcm8udGVzdCkNCg0KYGBgDQoNCjIuwr9MYXMgbXVlc3RyYXMgY29uIG1heW9yIG5pdmVsIGRlIGFjaWRleiBjYXRlZ8OzcmljYSBwcmVzZW50YW4gbWVub3IgcEggcHJvbWVkaW8/DQoNCmBgYHtyfQ0KIyBDYWxjdWxhciBlbCBwcm9tZWRpbyBkZSBwSCBwb3Igbml2ZWwgZGUgYWNpZGV6DQpkYXRhICU+JQ0KICBncm91cF9ieShhY2lkZXopICU+JQ0KICBzdW1tYXJpc2UoTWVkaWFfcEggPSBtZWFuKHBILCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgU0RfcEggPSBzZChwSCwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIG4gPSBuKCkpICU+JQ0KICBhcnJhbmdlKE1lZGlhX3BIKSAgIyBvcmRlbmEgZGVsIG1lbm9yIGFsIG1heW9yIHBIDQoNCmBgYA0KDQoNCjMuwr9FbCBuaXZlbCBkZSBhesO6Y2FyIHJlc2lkdWFsIGVzIG1heW9yIGVuIGxhcyBtdWVzdHJhcyBjbGFzaWZpY2FkYXMgY29tbyBNdXkgw6FjaWRhcyBmcmVudGUgYSBsYXMgw4FjaWRhcz8NCg0KYGBge3J9DQojIEZpbHRyYXIgc29sbyBsYXMgbXVlc3RyYXMgTXV5IMOhY2lkYXMgeSDDgWNpZGFzDQphenVjYXJfZGF0b3MgPC0gZGF0YSAlPiUNCiAgZmlsdGVyKGFjaWRleiAlaW4lIGMoIsOBY2lkbyIsICJNdXkgw6FjaWRvIikpICU+JQ0KICBtdXRhdGUoYWNpZGV6ID0gZmFjdG9yKGFjaWRleikpDQoNCiMgVmVyIHByb21lZGlvcyBkZSBhesO6Y2FyIHJlc2lkdWFsDQphenVjYXJfZGF0b3MgJT4lDQogIGdyb3VwX2J5KGFjaWRleikgJT4lDQogIHN1bW1hcmlzZShNZWRpYV9henVjYXIgPSBtZWFuKGBhesO6Y2FyLnJlc2lkdWFsYCwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIFNEX2F6dWNhciA9IHNkKGBhesO6Y2FyLnJlc2lkdWFsYCwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIG4gPSBuKCkpDQoNCiMgUHJ1ZWJhIHQgcGFyYSBjb21wYXJhciBuaXZlbGVzIGRlIGF6w7pjYXIgcmVzaWR1YWwNCnQudGVzdChgYXrDumNhci5yZXNpZHVhbGAgfiBhY2lkZXosIGRhdGEgPSBhenVjYXJfZGF0b3MsIGFsdGVybmF0aXZlID0gImxlc3MiKQ0KDQpgYGANCg0KDQo0LsK/RXhpc3RlbiBkaWZlcmVuY2lhcyBlbiBsYSBhY2lkZXogdm9sw6F0aWwgcHJvbWVkaW8gZW50cmUgbml2ZWxlcyBkZSBhY2lkZXogKMOBY2lkbyB2cy4gTXV5IMOhY2lkbyk/DQoNCmBgYHtyfQ0KIyBGaWx0cmFyIGxvcyBkYXRvcyBwYXJhIHNvbG8gw4FjaWRvIHkgTXV5IMOhY2lkbw0Kdm9sYXRpbF9kYXRvcyA8LSBkYXRhICU+JQ0KICBmaWx0ZXIoYWNpZGV6ICVpbiUgYygiw4FjaWRvIiwgIk11eSDDoWNpZG8iKSkgJT4lDQogIG11dGF0ZShhY2lkZXogPSBmYWN0b3IoYWNpZGV6KSkNCg0KIyBWZXIgcHJvbWVkaW9zIHBvciBncnVwbw0Kdm9sYXRpbF9kYXRvcyAlPiUNCiAgZ3JvdXBfYnkoYWNpZGV6KSAlPiUNCiAgc3VtbWFyaXNlKE1lZGlhX3ZvbGF0aWwgPSBtZWFuKGBhY2lkZXoudm9sw6F0aWxgLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgU0Rfdm9sYXRpbCA9IHNkKGBhY2lkZXoudm9sw6F0aWxgLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgbiA9IG4oKSkNCg0KIyBQcnVlYmEgdCBwYXJhIGNvbXBhcmFyIGxhIGFjaWRleiB2b2zDoXRpbA0KdC50ZXN0KGBhY2lkZXoudm9sw6F0aWxgIH4gYWNpZGV6LCBkYXRhID0gdm9sYXRpbF9kYXRvcykNCg0KYGBgDQoNCg0KNS7Cv0xhIGRlbnNpZGFkIHByb21lZGlvIGNhbWJpYSBlbnRyZSBsb3Mgbml2ZWxlcyBkZSBhY2lkZXo/DQoNCmBgYHtyfQ0KIyBWZXIgZGVuc2lkYWQgcHJvbWVkaW8gcG9yIG5pdmVsIGRlIGFjaWRleg0KZGF0YSAlPiUNCiAgZ3JvdXBfYnkoYWNpZGV6KSAlPiUNCiAgc3VtbWFyaXNlKE1lZGlhX2RlbnNpZGFkID0gbWVhbihkZW5zaWRhZCwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIFNEX2RlbnNpZGFkID0gc2QoZGVuc2lkYWQsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBuID0gbigpKQ0KDQojIEFOT1ZBOiBjb21wYXJhciBkZW5zaWRhZCBlbnRyZSBuaXZlbGVzIGRlIGFjaWRleg0KbW9kZWxvX2Fub3ZhIDwtIGFvdihkZW5zaWRhZCB+IGFjaWRleiwgZGF0YSA9IGRhdGEpDQpzdW1tYXJ5KG1vZGVsb19hbm92YSkNCg0KYGBgDQoNCg0KNi5FbGFib3JhIHVuIGdyw6FmaWNvIGRlIGNhamFzIHkgYmlnb3RlcyBwYXJhIGNhZGEgbml2ZWwgZGUgYWNpZGV6LihJbnRlcnByZXRlbG8pDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KDQojIEJveHBsb3QgZGUgZGVuc2lkYWQgcG9yIG5pdmVsIGRlIGFjaWRleg0KYm94cGxvdChwSCB+IGFjaWRleiwgZGF0YSA9IGRhdGEsDQogICAgICAgIGNvbCA9ICJsaWdodGdyZWVuIiwNCiAgICAgICAgbWFpbiA9ICJDb21wYXJhY2nDs24gZGUgcEggc2Vnw7puIG5pdmVsIGRlIGFjaWRleiIsDQogICAgICAgIHlsYWIgPSAicEgiLCB4bGFiID0gIk5pdmVsIGRlIGFjaWRleiIpDQoNCmBgYA0KDQoNCjcuwr9MYSBjb25jZW50cmFjacOzbiBkZSDDoWNpZG8gY8OtdHJpY28gcHJvbWVkaW8gZGlmaWVyZSBlbnRyZSBtdWVzdHJhcyBjb24gYWNpZGV6IMOBY2lkYSB5IE11eSDDoWNpZGE/DQoNCmBgYHtyfQ0KIyBGaWx0cmFyIGxvcyBkb3Mgbml2ZWxlcyBkZSBhY2lkZXoNCmNpdHJpY29zX2RhdG9zIDwtIGRhdGEgJT4lDQogIGZpbHRlcihhY2lkZXogJWluJSBjKCLDgWNpZG8iLCAiTXV5IMOhY2lkbyIpKSAlPiUNCiAgbXV0YXRlKGFjaWRleiA9IGZhY3RvcihhY2lkZXopKQ0KDQojIFZlciBwcm9tZWRpb3MNCmNpdHJpY29zX2RhdG9zICU+JQ0KICBncm91cF9ieShhY2lkZXopICU+JQ0KICBzdW1tYXJpc2UoTWVkaWFfY2l0cmljbyA9IG1lYW4oYFguw6FjaWRvLmPDrXRyaWNvYCwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIFNEX2NpdHJpY28gPSBzZChgWC7DoWNpZG8uY8OtdHJpY29gLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgbiA9IG4oKSkNCg0KIyBQcnVlYmEgdA0KdC50ZXN0KGBYLsOhY2lkby5jw610cmljb2AgfiBhY2lkZXosIGRhdGEgPSBjaXRyaWNvc19kYXRvcykNCg0KYGBgDQoNCg0KOC7Cv0xhcyBtdWVzdHJhcyBjb24gbWF5b3IgY29udGVuaWRvIGRlIGFsY29ob2wgcHJlc2VudGFuIG1lbm9yIGFjaWRleiBmaWphIGVuIHByb21lZGlvPw0KDQpgYGB7cn0NCiMgQ3JlYXIgdmFyaWFibGUgY2F0ZWfDs3JpY2E6ICJBbHRvIiBvICJCYWpvIiBzZWfDum4gbGEgbWVkaWFuYSBkZWwgYWxjb2hvbA0KZGF0b3MgPC0gZGF0YSAlPiUNCiAgbXV0YXRlKG5pdmVsX2FsY29ob2wgPSBpZmVsc2UoYWxjb2hvbCA+IG1lZGlhbihhbGNvaG9sLCBuYS5ybSA9IFRSVUUpLCAiQWx0byIsICJCYWpvIikpDQoNCiMgQ29tcGFyYXIgYWNpZGV6IGZpamEgcHJvbWVkaW8gc2Vnw7puIG5pdmVsIGRlIGFsY29ob2wNCmRhdG9zICU+JQ0KICBncm91cF9ieShuaXZlbF9hbGNvaG9sKSAlPiUNCiAgc3VtbWFyaXNlKE1lZGlhX2FjaWRlel9maWphID0gbWVhbihgYWNpZGV6LmZpamFgLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgU0QgPSBzZChgYWNpZGV6LmZpamFgLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgbiA9IG4oKSkNCg0KIyBQcnVlYmEgdA0KdC50ZXN0KGBhY2lkZXouZmlqYWAgfiBuaXZlbF9hbGNvaG9sLCBkYXRhID0gZGF0b3MsIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiKQ0KDQpgYGANCg0KDQo5LsK/RWwgY29udGVuaWRvIGRlIHN1bGZhdG9zIGRpZmllcmUgZW50cmUgbml2ZWxlcyBkZSBhY2lkZXo/DQoNCmBgYHtyfQ0KZGF0YSAlPiUNCiAgZ3JvdXBfYnkoYWNpZGV6KSAlPiUNCiAgc3VtbWFyaXNlKE1lZGlhX3N1bGZhdG9zID0gbWVhbihzdWxmYXRvcywgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIFNEX3N1bGZhdG9zID0gc2Qoc3VsZmF0b3MsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBuID0gbigpKQ0KIyBBTk9WQSBwYXJhIGNvbXBhcmFyIHN1bGZhdG9zIGVudHJlIG5pdmVsZXMgZGUgYWNpZGV6DQptb2RlbG9fc3VsZmF0b3MgPC0gYW92KHN1bGZhdG9zIH4gYWNpZGV6LCBkYXRhID0gZGF0b3MpDQpzdW1tYXJ5KG1vZGVsb19zdWxmYXRvcykNClR1a2V5SFNEKG1vZGVsb19zdWxmYXRvcykNCg0KDQpgYGANCg0KDQoxMC7Cv0VsIHBIIHByb21lZGlvIGRlIGxhcyBtdWVzdHJhcyBjb24gYWNpZGV6IE11eSDDoWNpZGEgZXMgZGlmZXJlbnRlIGFsIGRlIGxhcyDDgWNpZGFzPw0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIEZpbHRyYXIgbGFzIG11ZXN0cmFzIGNvbiBhY2lkZXogw4FjaWRhIHkgTXV5IMOBY2lkYQ0KcGhfZGF0b3MgPC0gZGF0YSAlPiUNCiAgZmlsdGVyKGFjaWRleiAlaW4lIGMoIsOBY2lkbyIsICJNdXkgw6FjaWRvIikpICU+JQ0KICBtdXRhdGUoYWNpZGV6ID0gZmFjdG9yKGFjaWRleikpDQoNCiMgQ3JlYXIgdGFibGEgcmVzdW1lbg0KdGFibGFfcGggPC0gcGhfZGF0b3MgJT4lDQogIGdyb3VwX2J5KGFjaWRleikgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYV9wSCA9IHJvdW5kKG1lYW4ocEgsIG5hLnJtID0gVFJVRSksIDMpLA0KICAgIFNEX3BIID0gcm91bmQoc2QocEgsIG5hLnJtID0gVFJVRSksIDMpLA0KICAgIG4gPSBuKCkNCiAgKQ0KDQojIE1vc3RyYXIgdGFibGENCmthYmxlKHRhYmxhX3BoLCBjYXB0aW9uID0gIlByb21lZGlvIGRlIHBIIHBvciBuaXZlbCBkZSBhY2lkZXogKMOBY2lkbyB2cyBNdXkgw6FjaWRvKSIpDQoNCiMgUHJ1ZWJhIHQNCnQudGVzdChwSCB+IGFjaWRleiwgZGF0YSA9IHBoX2RhdG9zKQ0KDQpgYGANCg0KDQoxMS7Cv0VsIHB1bnRhamUgc2Vuc29yaWFsIHByb21lZGlvIHZhcsOtYSBlbnRyZSBsb3Mgdmlub3MgY29uIGJham8geSBhbHRvIGNvbnRlbmlkbyBkZSBhbGNvaG9sPw0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIENyZWFyIHZhcmlhYmxlIGRlIG5pdmVsIGRlIGFsY29ob2wNCmRhdG9zIDwtIGRhdG9zICU+JQ0KICBtdXRhdGUobml2ZWxfYWxjb2hvbCA9IGlmZWxzZShhbGNvaG9sID4gbWVkaWFuKGFsY29ob2wsIG5hLnJtID0gVFJVRSksICJBbHRvIiwgIkJham8iKSkNCg0KIyBUYWJsYSByZXN1bWVuIGRlbCBwdW50YWplIHNlbnNvcmlhbCBwb3Igbml2ZWwgZGUgYWxjb2hvbA0KdGFibGFfc2Vuc29yaWFsIDwtIGRhdG9zICU+JQ0KICBncm91cF9ieShuaXZlbF9hbGNvaG9sKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE1lZGlhX3NlbnNvcmlhbCA9IHJvdW5kKG1lYW4oYHB1bnRhamUuc2Vuc29yaWFsYCwgbmEucm0gPSBUUlVFKSwgMiksDQogICAgU0Rfc2Vuc29yaWFsID0gcm91bmQoc2QoYHB1bnRhamUuc2Vuc29yaWFsYCwgbmEucm0gPSBUUlVFKSwgMiksDQogICAgbiA9IG4oKQ0KICApDQoNCiMgTW9zdHJhciBsYSB0YWJsYQ0Ka2FibGUodGFibGFfc2Vuc29yaWFsLCBjYXB0aW9uID0gIlB1bnRhamUgc2Vuc29yaWFsIHByb21lZGlvIHBvciBuaXZlbCBkZSBhbGNvaG9sIikNCg0KIyBQcnVlYmEgdA0KdC50ZXN0KGBwdW50YWplLnNlbnNvcmlhbGAgfiBuaXZlbF9hbGNvaG9sLCBkYXRhID0gZGF0b3MpDQoNCmBgYA0KDQoNCjEyLsK/TGFzIG11ZXN0cmFzIGNvbiBhbHRvIGNvbnRlbmlkbyBkZSBhbGNvaG9sIHRpZW5lbiBtZW5vciBhY2lkZXogdm9sw6F0aWwgZW4gcHJvbWVkaW8gcXVlIGxhcyBkZSBjb250ZW5pZG8gYmFqbz8NCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrbml0cikNCg0KIyBBc2VndXJhcnNlIGRlIHRlbmVyIGxhIHZhcmlhYmxlIG5pdmVsX2FsY29ob2wNCmRhdG9zIDwtIGRhdG9zICU+JQ0KICBtdXRhdGUobml2ZWxfYWxjb2hvbCA9IGlmZWxzZShhbGNvaG9sID4gbWVkaWFuKGFsY29ob2wsIG5hLnJtID0gVFJVRSksICJBbHRvIiwgIkJham8iKSkNCg0KIyBDcmVhciB0YWJsYSByZXN1bWVuIGRlIGFjaWRleiB2b2zDoXRpbCBwb3Igbml2ZWwgZGUgYWxjb2hvbA0KdGFibGFfdm9sYXRpbCA8LSBkYXRvcyAlPiUNCiAgZ3JvdXBfYnkobml2ZWxfYWxjb2hvbCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYV92b2xhdGlsID0gcm91bmQobWVhbihgYWNpZGV6LnZvbMOhdGlsYCwgbmEucm0gPSBUUlVFKSwgMyksDQogICAgU0Rfdm9sYXRpbCA9IHJvdW5kKHNkKGBhY2lkZXoudm9sw6F0aWxgLCBuYS5ybSA9IFRSVUUpLCAzKSwNCiAgICBuID0gbigpDQogICkNCg0KIyBNb3N0cmFyIHRhYmxhDQprYWJsZSh0YWJsYV92b2xhdGlsLCBjYXB0aW9uID0gIkFjaWRleiB2b2zDoXRpbCBwcm9tZWRpbyBwb3Igbml2ZWwgZGUgYWxjb2hvbCIpDQoNCiMgUHJ1ZWJhIHQgKGhpcMOzdGVzaXM6IGFsY29ob2wgYWx0byDihpIgbWVub3IgYWNpZGV6IHZvbMOhdGlsKQ0KdC50ZXN0KGBhY2lkZXoudm9sw6F0aWxgIH4gbml2ZWxfYWxjb2hvbCwgZGF0YSA9IGRhdG9zLCBhbHRlcm5hdGl2ZSA9ICJsZXNzIikNCg0KYGBgDQoNCg0KMTMuwr9FbCBuaXZlbCBkZSBhesO6Y2FyIHJlc2lkdWFsIGNhbWJpYSBzaWduaWZpY2F0aXZhbWVudGUgc2Vnw7puIGVsIGNvbnRlbmlkbyBkZSBhbGNvaG9sPw0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIEFzZWd1cmFyc2UgZGUgdGVuZXIgbGEgdmFyaWFibGUgbml2ZWxfYWxjb2hvbA0KZGF0b3MgPC0gZGF0b3MgJT4lDQogIG11dGF0ZShuaXZlbF9hbGNvaG9sID0gaWZlbHNlKGFsY29ob2wgPiBtZWRpYW4oYWxjb2hvbCwgbmEucm0gPSBUUlVFKSwgIkFsdG8iLCAiQmFqbyIpKQ0KDQojIFRhYmxhIHJlc3VtZW4gZGUgYXrDumNhciByZXNpZHVhbA0KdGFibGFfYXp1Y2FyIDwtIGRhdG9zICU+JQ0KICBncm91cF9ieShuaXZlbF9hbGNvaG9sKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE1lZGlhX2F6dWNhciA9IHJvdW5kKG1lYW4oYGF6w7pjYXIucmVzaWR1YWxgLCBuYS5ybSA9IFRSVUUpLCAyKSwNCiAgICBTRF9henVjYXIgPSByb3VuZChzZChgYXrDumNhci5yZXNpZHVhbGAsIG5hLnJtID0gVFJVRSksIDIpLA0KICAgIG4gPSBuKCkNCiAgKQ0KDQojIE1vc3RyYXIgdGFibGEgb3JnYW5pemFkYQ0Ka2FibGUodGFibGFfYXp1Y2FyLCBjYXB0aW9uID0gIkF6w7pjYXIgcmVzaWR1YWwgcHJvbWVkaW8gcG9yIG5pdmVsIGRlIGFsY29ob2wiKQ0KDQojIFBydWViYSB0DQp0LnRlc3QoYGF6w7pjYXIucmVzaWR1YWxgIH4gbml2ZWxfYWxjb2hvbCwgZGF0YSA9IGRhdG9zKQ0KDQpgYGANCg0KDQoxNC7Cv0xhcyBtdWVzdHJhcyBjb24gYWxjb2hvbCBhbHRvIHByZXNlbnRhbiBtYXlvciBjYWxpZGFkIHByb21lZGlvIChwb3IgZWplbXBsbywgbcOhcyB2ZWNlcyBjbGFzaWZpY2FkYXMgY29tbyDigJxCdWVuYeKAnSBvIOKAnEV4Y2VsZW50ZeKAnSk/DQoNCmBgYHtyfQ0KDQp1bmlxdWUoZGF0b3MkY2FsaWRhZCkNCg0KI0RBUiBOVU1FUkFDSU9OIA0KDQpkYXRvcyA8LSBkYXRvcyAlPiUNCiAgbXV0YXRlKGNhbGlkYWRfbnVtID0gY2FzZV93aGVuKA0KICAgIGNhbGlkYWQgPT0gIk11eSBiYWphIiB+IDEsDQogICAgY2FsaWRhZCA9PSAiQmFqYSIgfiAyLA0KICAgIGNhbGlkYWQgPT0gIlJlZ3VsYXIiIH4gMywNCiAgICBjYWxpZGFkID09ICJCdWVuYSIgfiA0LA0KICAgIGNhbGlkYWQgPT0gIkV4Y2VsZW50ZSIgfiA1DQogICkpDQojIFRhYmxhDQp0YWJsYV9jYWxpZGFkIDwtIGRhdG9zICU+JQ0KICBncm91cF9ieShuaXZlbF9hbGNvaG9sKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE1lZGlhX2NhbGlkYWQgPSByb3VuZChtZWFuKGNhbGlkYWRfbnVtLCBuYS5ybSA9IFRSVUUpLCAyKSwNCiAgICBTRF9jYWxpZGFkID0gcm91bmQoc2QoY2FsaWRhZF9udW0sIG5hLnJtID0gVFJVRSksIDIpLA0KICAgIG4gPSBuKCkNCiAgKQ0KDQprYWJsZSh0YWJsYV9jYWxpZGFkLCBjYXB0aW9uID0gIkNhbGlkYWQgcHJvbWVkaW8gKGVuIGVzY2FsYSAxLTUpIHBvciBuaXZlbCBkZSBhbGNvaG9sIikNCg0KIyBQcnVlYmEgdA0KdC50ZXN0KGNhbGlkYWRfbnVtIH4gbml2ZWxfYWxjb2hvbCwgZGF0YSA9IGRhdG9zLCBhbHRlcm5hdGl2ZSA9ICJsZXNzIikNCg0KDQpgYGANCg0KDQoxNS7Cv0VsIHBIIHByb21lZGlvIGRpZmllcmUgZW50cmUgbG9zIG5pdmVsZXMgZGUgYWxjb2hvbCAobWVkaW8geSBhbHRvKT8NCg0KYGBge3J9DQojIENyZWFyIHRyZXMgbml2ZWxlcyBkZSBhbGNvaG9sOiBCYWpvLCBNZWRpbywgQWx0bw0KcXVhbnRpbGVzIDwtIHF1YW50aWxlKGRhdG9zJGFsY29ob2wsIHByb2JzID0gYygwLjMzLCAwLjY2KSwgbmEucm0gPSBUUlVFKQ0KDQpkYXRvcyA8LSBkYXRvcyAlPiUNCiAgbXV0YXRlKG5pdmVsX2FsY29ob2wgPSBjYXNlX3doZW4oDQogICAgYWxjb2hvbCA8PSBxdWFudGlsZXNbMV0gfiAiQmFqbyIsDQogICAgYWxjb2hvbCA+IHF1YW50aWxlc1sxXSAmIGFsY29ob2wgPD0gcXVhbnRpbGVzWzJdIH4gIk1lZGlvIiwNCiAgICBhbGNvaG9sID4gcXVhbnRpbGVzWzJdIH4gIkFsdG8iDQogICkpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrbml0cikNCg0KIyBGaWx0cmFyIGxvcyBncnVwb3MgTWVkaW8geSBBbHRvDQpwaF9kYXRvcyA8LSBkYXRvcyAlPiUNCiAgZmlsdGVyKG5pdmVsX2FsY29ob2wgJWluJSBjKCJNZWRpbyIsICJBbHRvIikpICU+JQ0KICBtdXRhdGUobml2ZWxfYWxjb2hvbCA9IGZhY3RvcihuaXZlbF9hbGNvaG9sKSkNCg0KIyBUYWJsYSByZXN1bWVuDQp0YWJsYV9waCA8LSBwaF9kYXRvcyAlPiUNCiAgZ3JvdXBfYnkobml2ZWxfYWxjb2hvbCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYV9wSCA9IHJvdW5kKG1lYW4ocEgsIG5hLnJtID0gVFJVRSksIDMpLA0KICAgIFNEX3BIID0gcm91bmQoc2QocEgsIG5hLnJtID0gVFJVRSksIDMpLA0KICAgIG4gPSBuKCkNCiAgKQ0KDQojIE1vc3RyYXIgdGFibGENCmthYmxlKHRhYmxhX3BoLCBjYXB0aW9uID0gIlByb21lZGlvIGRlIHBIIGVudHJlIG5pdmVsZXMgZGUgYWxjb2hvbCBNZWRpbyB5IEFsdG8iKQ0KDQojIFBydWViYSB0DQp0LnRlc3QocEggfiBuaXZlbF9hbGNvaG9sLCBkYXRhID0gcGhfZGF0b3MpDQoNCg0KYGBgDQoNCg0KMTYuwr9FbCBjb250ZW5pZG8gcHJvbWVkaW8gZGUgYWxjb2hvbCB2YXLDrWEgc2Vnw7puIGVsIG5pdmVsIGRlIGNhbGlkYWQgZGUgbGFzIG11ZXN0cmFzPw0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIFRhYmxhIGRlIGFsY29ob2wgcHJvbWVkaW8gcG9yIGNhbGlkYWQgY2F0ZWfDs3JpY2ENCnRhYmxhX2FsY29ob2wgPC0gZGF0b3MgJT4lDQogIGdyb3VwX2J5KGNhbGlkYWQpICU+JQ0KICBzdW1tYXJpc2UoDQogICAgTWVkaWFfYWxjb2hvbCA9IHJvdW5kKG1lYW4oYWxjb2hvbCwgbmEucm0gPSBUUlVFKSwgMiksDQogICAgU0QgPSByb3VuZChzZChhbGNvaG9sLCBuYS5ybSA9IFRSVUUpLCAyKSwNCiAgICBuID0gbigpDQogICkNCg0Ka2FibGUodGFibGFfYWxjb2hvbCwgY2FwdGlvbiA9ICJDb250ZW5pZG8gcHJvbWVkaW8gZGUgYWxjb2hvbCBwb3Igbml2ZWwgZGUgY2FsaWRhZCIpDQoNCiMgQU5PVkENCm1vZGVsbyA8LSBhb3YoYWxjb2hvbCB+IGNhbGlkYWQsIGRhdGEgPSBkYXRvcykNCnN1bW1hcnkobW9kZWxvKQ0KDQpgYGANCmBgYHtyfQ0KIyBDb252ZXJ0aXIgYSBmYWN0b3IgcGFyYSBhbsOhbGlzaXMgY2F0ZWfDs3JpY28NCmRhdG9zJGNhbGlkYWRfbnVtIDwtIGFzLmZhY3RvcihkYXRvcyRjYWxpZGFkX251bSkNCg0KIyBUYWJsYSByZXN1bWVuDQp0YWJsYV9hbGNvaG9sMiA8LSBkYXRvcyAlPiUNCiAgZ3JvdXBfYnkoY2FsaWRhZF9udW0pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgTWVkaWFfYWxjb2hvbCA9IHJvdW5kKG1lYW4oYWxjb2hvbCwgbmEucm0gPSBUUlVFKSwgMiksDQogICAgU0QgPSByb3VuZChzZChhbGNvaG9sLCBuYS5ybSA9IFRSVUUpLCAyKSwNCiAgICBuID0gbigpDQogICkNCg0Ka2FibGUodGFibGFfYWxjb2hvbDIsIGNhcHRpb24gPSAiQ29udGVuaWRvIHByb21lZGlvIGRlIGFsY29ob2wgcG9yIGNhbGlkYWQgKGVzY2FsYSBudW3DqXJpY2EpIikNCg0KIyBBTk9WQQ0KbW9kZWxvMiA8LSBhb3YoYWxjb2hvbCB+IGNhbGlkYWRfbnVtLCBkYXRhID0gZGF0b3MpDQpzdW1tYXJ5KG1vZGVsbzIpDQoNCmBgYA0KDQoxNy7Cv0xhcyBtdWVzdHJhcyBjbGFzaWZpY2FkYXMgY29tbyDigJxFeGNlbGVudGXigJ0gcHJlc2VudGFuIG1lbm9yIGFjaWRleiB2b2zDoXRpbCBlbiBwcm9tZWRpbyBxdWUgbGFzIGRlIGNhbGlkYWQg4oCcQmFqYeKAnSA/DQoNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoa25pdHIpDQoNCiMgRmlsdHJhciBsYXMgbXVlc3RyYXMgY29uIGNhbGlkYWQgRXhjZWxlbnRlIHkgQmFqYQ0Kdm9sYXRpbF9kYXRvcyA8LSBkYXRvcyAlPiUNCiAgZmlsdGVyKGNhbGlkYWQgJWluJSBjKCJFeGNlbGVudGUiLCAiQmFqYSIpKSAlPiUNCiAgbXV0YXRlKGNhbGlkYWQgPSBmYWN0b3IoY2FsaWRhZCkpDQoNCiMgVGFibGEgcmVzdW1lbiBkZSBhY2lkZXogdm9sw6F0aWwNCnRhYmxhX3ZvbGF0aWwgPC0gdm9sYXRpbF9kYXRvcyAlPiUNCiAgZ3JvdXBfYnkoY2FsaWRhZCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYV92b2xhdGlsID0gcm91bmQobWVhbihgYWNpZGV6LnZvbMOhdGlsYCwgbmEucm0gPSBUUlVFKSwgMyksDQogICAgU0Rfdm9sYXRpbCA9IHJvdW5kKHNkKGBhY2lkZXoudm9sw6F0aWxgLCBuYS5ybSA9IFRSVUUpLCAzKSwNCiAgICBuID0gbigpDQogICkNCg0KIyBNb3N0cmFyIHRhYmxhDQprYWJsZSh0YWJsYV92b2xhdGlsLCBjYXB0aW9uID0gIkFjaWRleiB2b2zDoXRpbCBwcm9tZWRpbzogRXhjZWxlbnRlIHZzLiBCYWphIikNCg0KdC50ZXN0KGBhY2lkZXoudm9sw6F0aWxgIH4gY2FsaWRhZCwgZGF0YSA9IHZvbGF0aWxfZGF0b3MsIGFsdGVybmF0aXZlID0gImxlc3MiKQ0KDQpgYGANCg0KMTguwr9FbCBwdW50YWplIHNlbnNvcmlhbCBwcm9tZWRpbyBhdW1lbnRhIGNvbmZvcm1lIG1lam9yYSBsYSBjYWxpZGFkIGRlIGxhcyBtdWVzdHJhcz8NCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrbml0cikNCg0KIyBBc2lnbmFyIHZhbG9yZXMgbnVtw6lyaWNvcyBhIGxhIGNhbGlkYWQgc2kgYcO6biBubyBleGlzdGUNCmRhdG9zIDwtIGRhdG9zICU+JQ0KICBtdXRhdGUoY2FsaWRhZF9udW0gPSBjYXNlX3doZW4oDQogICAgY2FsaWRhZCA9PSAiTXV5IGJhamEiIH4gMSwNCiAgICBjYWxpZGFkID09ICJCYWphIiB+IDIsDQogICAgY2FsaWRhZCA9PSAiUmVndWxhciIgfiAzLA0KICAgIGNhbGlkYWQgPT0gIkJ1ZW5hIiB+IDQsDQogICAgY2FsaWRhZCA9PSAiRXhjZWxlbnRlIiB+IDUNCiAgKSkNCg0KI1RhYmxhIHJlc3VtZW4NCnRhYmxhX3NlbnNvcmlhbCA8LSBkYXRvcyAlPiUNCiAgZ3JvdXBfYnkoY2FsaWRhZF9udW0pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgTWVkaWFfcHVudGFqZSA9IHJvdW5kKG1lYW4oYHB1bnRhamUuc2Vuc29yaWFsYCwgbmEucm0gPSBUUlVFKSwgMiksDQogICAgU0QgPSByb3VuZChzZChgcHVudGFqZS5zZW5zb3JpYWxgLCBuYS5ybSA9IFRSVUUpLCAyKSwNCiAgICBuID0gbigpDQogICkNCg0Ka2FibGUodGFibGFfc2Vuc29yaWFsLCBjYXB0aW9uID0gIlB1bnRhamUgc2Vuc29yaWFsIHByb21lZGlvIHNlZ8O6biBuaXZlbCBkZSBjYWxpZGFkIikNCg0KIyBDb3JyZWxhY2nDs24gZW50cmUgY2FsaWRhZCB5IHB1bnRhamUgc2Vuc29yaWFsDQpjb3IudGVzdChkYXRvcyRjYWxpZGFkX251bSwgZGF0b3MkYHB1bnRhamUuc2Vuc29yaWFsYCwgbWV0aG9kID0gInBlYXJzb24iKQ0KDQptb2RlbG8gPC0gbG0oYHB1bnRhamUuc2Vuc29yaWFsYCB+IGNhbGlkYWRfbnVtLCBkYXRhID0gZGF0b3MpDQpzdW1tYXJ5KG1vZGVsbykNCg0KDQpgYGANCg0KMTkuwr9FbCBuaXZlbCBkZSBkacOzeGlkbyBkZSBhenVmcmUgdG90YWwgZXMgZGlmZXJlbnRlIGVudHJlIGxvcyB2aW5vcyBkZSBjYWxpZGFkIGJhamEgeSBsb3MgZGUgY2FsaWRhZCBleGNlbGVudGU/DQoNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoa25pdHIpDQoNCiMgRmlsdHJhciBkYXRvcyBjb24gY2FsaWRhZCBCYWphIHkgRXhjZWxlbnRlDQphenVmcmVfZGF0b3MgPC0gZGF0b3MgJT4lDQogIGZpbHRlcihjYWxpZGFkICVpbiUgYygiQmFqYSIsICJFeGNlbGVudGUiKSkgJT4lDQogIG11dGF0ZShjYWxpZGFkID0gZmFjdG9yKGNhbGlkYWQpKQ0KDQojIFRhYmxhIHJlc3VtZW4gZGVsIGRpw7N4aWRvIGRlIGF6dWZyZSB0b3RhbA0KdGFibGFfYXp1ZnJlIDwtIGF6dWZyZV9kYXRvcyAlPiUNCiAgZ3JvdXBfYnkoY2FsaWRhZCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYV9TTzIgPSByb3VuZChtZWFuKGBkacOzeGlkby5kZS5henVmcmUudG90YWxgLCBuYS5ybSA9IFRSVUUpLCAyKSwNCiAgICBTRF9TTzIgPSByb3VuZChzZChgZGnDs3hpZG8uZGUuYXp1ZnJlLnRvdGFsYCwgbmEucm0gPSBUUlVFKSwgMiksDQogICAgbiA9IG4oKQ0KICApDQoNCiMgTW9zdHJhciB0YWJsYQ0Ka2FibGUodGFibGFfYXp1ZnJlLCBjYXB0aW9uID0gIkRpw7N4aWRvIGRlIGF6dWZyZSB0b3RhbCBwcm9tZWRpbzogQ2FsaWRhZCBCYWphIHZzLiBFeGNlbGVudGUiKQ0KDQp0LnRlc3QoYGRpw7N4aWRvLmRlLmF6dWZyZS50b3RhbGAgfiBjYWxpZGFkLCBkYXRhID0gYXp1ZnJlX2RhdG9zKQ0KDQpgYGANCg0KDQoyMC7Cv0xhcyBtdWVzdHJhcyBjb24gY2FsaWRhZCDigJxNdXkgYmFqYeKAnSBwcmVzZW50YW4gbWF5b3IgZGVuc2lkYWQgZW4gcHJvbWVkaW8gcXVlIGxhcyBkZSBjYWxpZGFkIOKAnEV4Y2VsZW50ZeKAnT8NCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrbml0cikNCg0KIyBGaWx0cmFyIGxhcyBtdWVzdHJhcyBjb24gY2FsaWRhZCBNdXkgYmFqYSB5IEV4Y2VsZW50ZQ0KZGVuc2lkYWRfZGF0b3MgPC0gZGF0b3MgJT4lDQogIGZpbHRlcihjYWxpZGFkICVpbiUgYygiTXV5IGJhamEiLCAiRXhjZWxlbnRlIikpICU+JQ0KICBtdXRhdGUoY2FsaWRhZCA9IGZhY3RvcihjYWxpZGFkKSkNCg0KIyBDcmVhciB0YWJsYSByZXN1bWVuIGRlIGRlbnNpZGFkDQp0YWJsYV9kZW5zaWRhZCA8LSBkZW5zaWRhZF9kYXRvcyAlPiUNCiAgZ3JvdXBfYnkoY2FsaWRhZCkgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYV9kZW5zaWRhZCA9IHJvdW5kKG1lYW4oZGVuc2lkYWQsIG5hLnJtID0gVFJVRSksIDUpLA0KICAgIFNEX2RlbnNpZGFkID0gcm91bmQoc2QoZGVuc2lkYWQsIG5hLnJtID0gVFJVRSksIDUpLA0KICAgIG4gPSBuKCkNCiAgKQ0KDQojIE1vc3RyYXIgdGFibGEgb3JnYW5pemFkYQ0Ka2FibGUodGFibGFfZGVuc2lkYWQsIGNhcHRpb24gPSAiRGVuc2lkYWQgcHJvbWVkaW86IENhbGlkYWQgTXV5IGJhamEgdnMuIEV4Y2VsZW50ZSIpDQoNCnQudGVzdChkZW5zaWRhZCB+IGNhbGlkYWQsIGRhdGEgPSBkZW5zaWRhZF9kYXRvcywgYWx0ZXJuYXRpdmUgPSAiZ3JlYXRlciIpDQoNCmBgYA0KDQoyMS7Cv0VsIGNvbnRlbmlkbyBwcm9tZWRpbyBkZSBhbGNvaG9sIGRpZmllcmUgZW50cmUgdmlub3MgYmxhbmNvcyB5IHRpbnRvcz8NCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrbml0cikNCg0KIyBWZXJpZmljYXIgbG9zIG5pdmVsZXMgZGUgbGEgdmFyaWFibGUgJ3RpcG8nDQp1bmlxdWUoZGF0b3MkdGlwbykNCnRhYmxhX2FsY29ob2xfdGlwbyA8LSBkYXRvcyAlPiUNCiAgZmlsdGVyKHRpcG8gJWluJSBjKCJCbGFuY28iLCAiVGludG8iKSkgJT4lDQogIGdyb3VwX2J5KHRpcG8pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgTWVkaWFfYWxjb2hvbCA9IHJvdW5kKG1lYW4oYWxjb2hvbCwgbmEucm0gPSBUUlVFKSwgMiksDQogICAgU0RfYWxjb2hvbCA9IHJvdW5kKHNkKGFsY29ob2wsIG5hLnJtID0gVFJVRSksIDIpLA0KICAgIG4gPSBuKCkNCiAgKQ0KDQprYWJsZSh0YWJsYV9hbGNvaG9sX3RpcG8sIGNhcHRpb24gPSAiQ29udGVuaWRvIHByb21lZGlvIGRlIGFsY29ob2wgcG9yIHRpcG8gZGUgdmlubyIpDQoNCnQudGVzdChhbGNvaG9sIH4gdGlwbywgZGF0YSA9IGRhdG9zKQ0KDQpgYGANCg0KDQoyMi7Cv0xvcyB2aW5vcyBibGFuY29zIHByZXNlbnRhbiBtYXlvciBwSCBlbiBwcm9tZWRpbyBxdWUgbG9zIHZpbm9zIHRpbnRvcz8NCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShrbml0cikNCg0KIyBUYWJsYSBkZWwgcEggcG9yIHRpcG8gZGUgdmlubw0KdGFibGFfcGhfdGlwbyA8LSBkYXRvcyAlPiUNCiAgZmlsdGVyKHRpcG8gJWluJSBjKCJCbGFuY28iLCAiVGludG8iKSkgJT4lDQogIGdyb3VwX2J5KHRpcG8pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgTWVkaWFfcEggPSByb3VuZChtZWFuKHBILCBuYS5ybSA9IFRSVUUpLCAzKSwNCiAgICBTRF9wSCA9IHJvdW5kKHNkKHBILCBuYS5ybSA9IFRSVUUpLCAzKSwNCiAgICBuID0gbigpDQogICkNCg0Ka2FibGUodGFibGFfcGhfdGlwbywgY2FwdGlvbiA9ICJwSCBwcm9tZWRpbyBwb3IgdGlwbyBkZSB2aW5vIikNCg0KdC50ZXN0KHBIIH4gdGlwbywgZGF0YSA9IGRhdG9zLCBhbHRlcm5hdGl2ZSA9ICJncmVhdGVyIikNCg0KYGBgDQoNCg0KMjMuwr9FbCBwdW50YWplIHNlbnNvcmlhbCBwcm9tZWRpbyBlcyBkaXN0aW50byBlbnRyZSB2aW5vcyBibGFuY29zIHkgdGludG9zPw0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIENyZWFyIHRhYmxhIGRlIHB1bnRhamUgc2Vuc29yaWFsIHBvciB0aXBvIGRlIHZpbm8NCnRhYmxhX3NlbnNvcmlhbF90aXBvIDwtIGRhdG9zICU+JQ0KICBmaWx0ZXIodGlwbyAlaW4lIGMoIkJsYW5jbyIsICJUaW50byIpKSAlPiUNCiAgZ3JvdXBfYnkodGlwbykgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYV9zZW5zb3JpYWwgPSByb3VuZChtZWFuKGBwdW50YWplLnNlbnNvcmlhbGAsIG5hLnJtID0gVFJVRSksIDIpLA0KICAgIFNEX3NlbnNvcmlhbCA9IHJvdW5kKHNkKGBwdW50YWplLnNlbnNvcmlhbGAsIG5hLnJtID0gVFJVRSksIDIpLA0KICAgIG4gPSBuKCkNCiAgKQ0KDQprYWJsZSh0YWJsYV9zZW5zb3JpYWxfdGlwbywgY2FwdGlvbiA9ICJQdW50YWplIHNlbnNvcmlhbCBwcm9tZWRpbyBwb3IgdGlwbyBkZSB2aW5vIikNCg0KdC50ZXN0KGBwdW50YWplLnNlbnNvcmlhbGAgfiB0aXBvLCBkYXRhID0gZGF0b3MpDQoNCmBgYA0KDQoNCjI0LsK/RWwgY29udGVuaWRvIHByb21lZGlvIGRlIGFsY29ob2wgZGlmaWVyZSBlbnRyZSB2aW5vcyBibGFuY29zIHkgdGludG9zPw0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIENyZWFyIHRhYmxhIGNvbiByZXN1bWVuIGRlbCBjb250ZW5pZG8gZGUgYWxjb2hvbCBwb3IgdGlwbw0KdGFibGFfYWxjb2hvbF90aXBvIDwtIGRhdG9zICU+JQ0KICBmaWx0ZXIodGlwbyAlaW4lIGMoIkJsYW5jbyIsICJUaW50byIpKSAlPiUNCiAgZ3JvdXBfYnkodGlwbykgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYV9hbGNvaG9sID0gcm91bmQobWVhbihhbGNvaG9sLCBuYS5ybSA9IFRSVUUpLCAyKSwNCiAgICBTRF9hbGNvaG9sID0gcm91bmQoc2QoYWxjb2hvbCwgbmEucm0gPSBUUlVFKSwgMiksDQogICAgbiA9IG4oKQ0KICApDQoNCiMgTW9zdHJhciB0YWJsYQ0Ka2FibGUodGFibGFfYWxjb2hvbF90aXBvLCBjYXB0aW9uID0gIkNvbnRlbmlkbyBwcm9tZWRpbyBkZSBhbGNvaG9sIHBvciB0aXBvIGRlIHZpbm8iKQ0KDQp0LnRlc3QoYWxjb2hvbCB+IHRpcG8sIGRhdGEgPSBkYXRvcykNCg0KYGBgDQoNCjI1LsK/TG9zIHZpbm9zIGJsYW5jb3MgcHJlc2VudGFuIG1heW9yIHBIIGVuIHByb21lZGlvIHF1ZSBsb3Mgdmlub3MgdGludG9zPw0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIFRhYmxhIGRlbCBwSCBwb3IgdGlwbyBkZSB2aW5vDQp0YWJsYV9waF90aXBvIDwtIGRhdG9zICU+JQ0KICBmaWx0ZXIodGlwbyAlaW4lIGMoIkJsYW5jbyIsICJUaW50byIpKSAlPiUNCiAgZ3JvdXBfYnkodGlwbykgJT4lDQogIHN1bW1hcmlzZSgNCiAgICBNZWRpYV9wSCA9IHJvdW5kKG1lYW4ocEgsIG5hLnJtID0gVFJVRSksIDMpLA0KICAgIFNEX3BIID0gcm91bmQoc2QocEgsIG5hLnJtID0gVFJVRSksIDMpLA0KICAgIG4gPSBuKCkNCiAgKQ0KDQojIE1vc3RyYXIgbGEgdGFibGENCmthYmxlKHRhYmxhX3BoX3RpcG8sIGNhcHRpb24gPSAicEggcHJvbWVkaW8gcG9yIHRpcG8gZGUgdmlubyAoQmxhbmNvIHZzLiBUaW50bykiKQ0KDQojIEhpcMOzdGVzaXM6IHZpbm9zIGJsYW5jb3MgdGllbmVuIG1heW9yIHBIIHF1ZSBsb3MgdGludG9zDQp0LnRlc3QocEggfiB0aXBvLCBkYXRhID0gZGF0b3MsIGFsdGVybmF0aXZlID0gImdyZWF0ZXIiKQ0KDQpgYGANCg0KDQoyNi7Cv0VsIHB1bnRhamUgc2Vuc29yaWFsIHByb21lZGlvIGVzIGRpc3RpbnRvIGVudHJlIHZpbm9zIGJsYW5jb3MgeSB0aW50b3M/DQoNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoa25pdHIpDQoNCiMgVGFibGEgY29uIHB1bnRhamUgc2Vuc29yaWFsIHBvciB0aXBvIGRlIHZpbm8NCnRhYmxhX3NlbnNvcmlhbCA8LSBkYXRvcyAlPiUNCiAgZmlsdGVyKHRpcG8gJWluJSBjKCJCbGFuY28iLCAiVGludG8iKSkgJT4lDQogIGdyb3VwX2J5KHRpcG8pICU+JQ0KICBzdW1tYXJpc2UoDQogICAgTWVkaWFfcHVudGFqZSA9IHJvdW5kKG1lYW4oYHB1bnRhamUuc2Vuc29yaWFsYCwgbmEucm0gPSBUUlVFKSwgMiksDQogICAgU0RfcHVudGFqZSA9IHJvdW5kKHNkKGBwdW50YWplLnNlbnNvcmlhbGAsIG5hLnJtID0gVFJVRSksIDIpLA0KICAgIG4gPSBuKCkNCiAgKQ0KDQprYWJsZSh0YWJsYV9zZW5zb3JpYWwsIGNhcHRpb24gPSAiUHVudGFqZSBzZW5zb3JpYWwgcHJvbWVkaW8gcG9yIHRpcG8gZGUgdmlubyIpDQoNCnQudGVzdChgcHVudGFqZS5zZW5zb3JpYWxgIH4gdGlwbywgZGF0YSA9IGRhdG9zLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQ0KDQpgYGANCg0KIyBUQUxMRVIgMg0KDQo1Lg0KYGBge3J9DQojIENhcmdhciBsaWJyZXLDrWENCmxpYnJhcnkoa25pdHIpDQoNCiMgRGF0b3MgZGVsIHByb2JsZW1hDQprIDwtIDUgICMgdHJhdGFtaWVudG9zDQpuIDwtIDQgICMgcsOpcGxpY2FzIHBvciB0cmF0YW1pZW50bw0KTiA8LSBrICogbg0KDQojIFN1bWEgZGUgY3VhZHJhZG9zDQpTQ190cmF0IDwtIDgwMA0KU0NfZXJyb3IgPC0gNDAwDQpTQ190b3RhbCA8LSBTQ190cmF0ICsgU0NfZXJyb3INCg0KIyBHcmFkb3MgZGUgbGliZXJ0YWQNCmdsX3RyYXQgPC0gayAtIDENCmdsX2Vycm9yIDwtIE4gLSBrDQpnbF90b3RhbCA8LSBOIC0gMQ0KDQojIEN1YWRyYWRvIG1lZGlvDQpDTV90cmF0IDwtIFNDX3RyYXQgLyBnbF90cmF0DQpDTV9lcnJvciA8LSBTQ19lcnJvciAvIGdsX2Vycm9yDQoNCiMgUmF6w7NuIEYgb2JzZXJ2YWRhDQpGX29icyA8LSBDTV90cmF0IC8gQ01fZXJyb3INCg0KIyBWYWxvci1wIHVzYW5kbyBsYSBkaXN0cmlidWNpw7NuIEYNCnZhbG9yX3AgPC0gcGYoRl9vYnMsIGRmMSA9IGdsX3RyYXQsIGRmMiA9IGdsX2Vycm9yLCBsb3dlci50YWlsID0gRkFMU0UpDQoNCiMgVGFibGEgQU5PVkEgY29tcGxldGFkYQ0KYW5vdmFfdGFibGEgPC0gZGF0YS5mcmFtZSgNCiAgYEZ1ZW50ZSBkZSB2YXJpYWNpw7NuYCA9IGMoIlRyYXRhbWllbnRvIiwgIkVycm9yIiwgIlRvdGFsIiksDQogIGBTdW1hIGRlIGN1YWRyYWRvc2AgPSBjKFNDX3RyYXQsIFNDX2Vycm9yLCBTQ190b3RhbCksDQogIGBHcmFkb3MgZGUgbGliZXJ0YWRgID0gYyhnbF90cmF0LCBnbF9lcnJvciwgZ2xfdG90YWwpLA0KICBgQ3VhZHJhZG8gbWVkaW9gID0gYyhyb3VuZChDTV90cmF0LCAyKSwgcm91bmQoQ01fZXJyb3IsIDIpLCBOQSksDQogIGBSYXrDs24gRmAgPSBjKHJvdW5kKEZfb2JzLCAyKSwgTkEsIE5BKSwNCiAgYFZhbG9yLXBgID0gYyhyb3VuZCh2YWxvcl9wLCA0KSwgTkEsIE5BKQ0KKQ0KDQojIE1vc3RyYXIgdGFibGEgZW4gZm9ybWF0byBib25pdG8NCmthYmxlKGFub3ZhX3RhYmxhLCBjYXB0aW9uID0gIlRhYmxhIEFOT1ZBIHBhcmEgY2luY28gdHJhdGFtaWVudG9zIGNvbiBjdWF0cm8gcsOpcGxpY2FzIGNhZGEgdW5vIikNCg0KIyBNb2RlbG8gZSBoaXDDs3Rlc2lzDQpjYXQoIlxuTW9kZWxvIGVzdGFkw61zdGljbzpcbiIpDQpjYXQoIllfaWogPSDCtSArIM+EX2kgKyDOtV9palxuIikNCg0KY2F0KCJcbkhpcMOzdGVzaXM6XG4iKQ0KY2F0KCJI4oKAOiDPhOKCgSA9IM+E4oKCID0gLi4uID0gz4TigoUgKG5vIGhheSBkaWZlcmVuY2lhIGVudHJlIHRyYXRhbWllbnRvcylcbiIpDQpjYXQoIkjigoE6IGFsIG1lbm9zIHVuIM+EX2kgZXMgZGlmZXJlbnRlXG4iKQ0KDQojIENvbmNsdXNpw7NuDQpjYXQoIlxuQ29uY2x1c2nDs246XG4iKQ0KaWYgKHZhbG9yX3AgPCAwLjA1KSB7DQogIGNhdCgiQ29tbyBlbCB2YWxvci1wID0iLCByb3VuZCh2YWxvcl9wLCA0KSwgIjwgMC4wNSwgc2UgcmVjaGF6YSBI4oKALiBIYXkgZGlmZXJlbmNpYXMgc2lnbmlmaWNhdGl2YXMgZW50cmUgdHJhdGFtaWVudG9zLlxuIikNCn0gZWxzZSB7DQogIGNhdCgiQ29tbyBlbCB2YWxvci1wID0iLCByb3VuZCh2YWxvcl9wLCA0KSwgIuKJpSAwLjA1LCBubyBzZSByZWNoYXphIEjigoAuIE5vIGhheSBkaWZlcmVuY2lhcyBzaWduaWZpY2F0aXZhcyBlbnRyZSB0cmF0YW1pZW50b3MuXG4iKQ0KfQ0KDQpgYGANCjEwLiANCmBgYHtyfQ0KIyBDYXJnYXIgbGlicmVyw61hDQpsaWJyYXJ5KGtuaXRyKQ0KDQojIEluZm9ybWFjacOzbiBkZWwgQU5PVkEgeSBwcm9tZWRpb3MgZGUgY2FkYSBtZXpjbGENCnZhbG9yX3AgPC0gMC4wMQ0KDQojIFRhYmxhIGRlIHByb21lZGlvcw0KbWV6Y2xhcyA8LSBkYXRhLmZyYW1lKA0KICBNZXpjbGEgPSBjKCJBIiwgIkIiLCAiQyIsICJEIiksDQogIFBlc29fUHJvbWVkaW8gPSBjKDEwMDAwLCA3MDAwLCA4MDAwLCA3NTAwKQ0KKQ0KDQojIE1vc3RyYXIgdGFibGEgZGUgcHJvbWVkaW9zDQprYWJsZShtZXpjbGFzLCBjYXB0aW9uID0gIlBlc28gcHJvbWVkaW8gcG9yIG1lemNsYSIpDQoNCiMgUmVzcHVlc3RhIGEgbG9zIGluY2lzb3MNCmNhdCgiXG5cbi0tLSBJbmNpc28gYSkgLS0tXG4iKQ0KY2F0KCLCv0xhcyBtZXpjbGFzIGRpZmllcmVuIGRlIG1hbmVyYSBzaWduaWZpY2F0aXZhIGVuIGN1YW50byBhIHN1IHBlc28gbW9sZWN1bGFyP1xuIikNCmlmICh2YWxvcl9wIDwgMC4wNSkgew0KICBjYXQoIlPDrS4gRWwgdmFsb3ItcCA9IDAuMDEgPCAwLjA1IGluZGljYSBxdWUgaGF5IGRpZmVyZW5jaWFzIHNpZ25pZmljYXRpdmFzIGVudHJlIGFsIG1lbm9zIGRvcyBtZXpjbGFzLlxuIikNCn0gZWxzZSB7DQogIGNhdCgiTm8uIEVsIHZhbG9yLXAgPj0gMC4wNSBpbmRpY2EgcXVlIG5vIGhheSBkaWZlcmVuY2lhcyBzaWduaWZpY2F0aXZhcyBlbnRyZSBsYXMgbWV6Y2xhcy5cbiIpDQp9DQoNCmNhdCgiXG5cbi0tLSBJbmNpc28gYikgLS0tXG4iKQ0KY2F0KCLCv1NlIHB1ZWRlIGFzZWd1cmFyIHF1ZSBsYSBtZXpjbGEgQiBsb2dyYSB1biBtZW5vciBwZXNvIG1vbGVjdWxhcj9cbiIpDQpjYXQoIkF1bnF1ZSBlbCBwcm9tZWRpbyBkZSBCICg3MDAwKSBlcyBlbCBtw6FzIGJham8sIGVsIEFOT1ZBIG5vIGluZGljYSBjdcOhbGVzIG1lemNsYXMgZGlmaWVyZW4gZXNwZWPDrWZpY2FtZW50ZS5cbiIpDQpjYXQoIlBhcmEgYWZpcm1hcmxvIGNvbiBjZXJ0ZXphLCBlcyBuZWNlc2FyaW8gYXBsaWNhciB1bmEgcHJ1ZWJhIHBvc3QtaG9jIGNvbW8gVHVrZXkgSFNELlxuIikNCmNhdCgiUG9yIHRhbnRvLCBOTyBzZSBwdWVkZSBhc2VndXJhciBzb2xvIGNvbiBsb3MgcHJvbWVkaW9zIHkgZWwgQU5PVkEgZ2VuZXJhbC5cbiIpDQoNCmNhdCgiXG5cbi0tLSBJbmNpc28gYykgLS0tXG4iKQ0KY2F0KCLCv1F1w6kgcGFzYSBzaSBubyBzZSBjdW1wbGUgZWwgc3VwdWVzdG8gZGUgdmFyaWFuemEgY29uc3RhbnRlP1xuIikNCmNhdCgiU2kgbGFzIHZhcmlhbnphcyBubyBzb24gaG9tb2fDqW5lYXMgZW50cmUgbWV6Y2xhcywgc2UgdmlvbGEgdW4gc3VwdWVzdG8gaW1wb3J0YW50ZSBkZWwgQU5PVkEuXG4iKQ0KY2F0KCJFc3RvIHB1ZWRlIGludmFsaWRhciBlbCB2YWxvci1wIG9idGVuaWRvIHksIHBvciB0YW50bywgbGEgY29uY2x1c2nDs24gZGVsIGluY2lzbyBhKS5cbiIpDQpjYXQoIkVuIGVzZSBjYXNvLCBzZSBkZWJlcsOtYSBhcGxpY2FyIHVuIEFOT1ZBIHJvYnVzdG8gbyB1bmEgcHJ1ZWJhIG5vIHBhcmFtw6l0cmljYSBjb21vIEtydXNrYWwtV2FsbGlzLlxuIikNCg0KDQoNCg0KYGBgDQoNCjExLg0KYGBge3J9DQojIENhcmdhciBsaWJyZXLDrWFzIG5lY2VzYXJpYXMNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShjYXIpDQoNCiMgRGF0b3MNCnNwcmF5IDwtIGRhdGEuZnJhbWUoDQogIG1hcmNhID0gcmVwKGMoIjEiLCAiMiIsICIzIiksIGVhY2ggPSA2KSwNCiAgZWZlY3RpdmlkYWQgPSBjKA0KICAgIDcyLCA2NSwgNjcsIDc1LCA2MywgNjIsICAgICAjIE1hcmNhIDENCiAgICA1NSwgNTksIDY4LCA3MCwgNTMsIDUwLCAgICAgIyBNYXJjYSAyDQogICAgNjQsIDc0LCA2MSwgNTgsIDUxLCA2OSAgICAgICMgTWFyY2EgMw0KICApDQopDQoNCiMgYSkgTW9kZWxvIGVzdGFkw61zdGljbyB5IGZvcm11bGFjacOzbiBkZSBoaXDDs3Rlc2lzDQpjYXQoIlxuLS0tIGEpIEhpcMOzdGVzaXMgeSBtb2RlbG8gLS0tXG4iKQ0KY2F0KCJIMDogTGFzIG1lZGlhcyBkZSBlZmVjdGl2aWRhZCBzb24gaWd1YWxlcyBlbnRyZSBsYXMgbWFyY2FzXG4iKQ0KY2F0KCJIYTogQWwgbWVub3MgdW5hIG1lZGlhIGRlIGVmZWN0aXZpZGFkIGVzIGRpZmVyZW50ZVxuIikNCmNhdCgiTW9kZWxvOiBZX2lqID0gzrwgKyDPhF9pICsgzrVfaWpcbiIpDQoNCiMgYikgQU5PVkENCm1vZGVsbyA8LSBhb3YoZWZlY3RpdmlkYWQgfiBtYXJjYSwgZGF0YSA9IHNwcmF5KQ0Kc3VtbWFyeShtb2RlbG8pDQoNCiMgYykgwr9IYXkgZGlmZXJlbmNpYXMgc2lnbmlmaWNhdGl2YXM/DQpjYXQoIlxuLS0tIGMpIMK/SGF5IGFsZ3VuYSBtYXJjYSBtZWpvcj8gLS0tXG4iKQ0KdHVrZXkgPC0gVHVrZXlIU0QobW9kZWxvKQ0KcHJpbnQodHVrZXkpDQoNCiMgZCkgSW50ZXJ2YWxvcyBkZSBjb25maWFuemEgZGVsIDk1JQ0KY29uZl9pbnQgPC0gc3ByYXkgJT4lDQogIGdyb3VwX2J5KG1hcmNhKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIE1lZGlhID0gbWVhbihlZmVjdGl2aWRhZCksDQogICAgU0QgPSBzZChlZmVjdGl2aWRhZCksDQogICAgbiA9IG4oKSwNCiAgICBJQ19JbmYgPSBNZWRpYSAtIHF0KDAuOTc1LCBkZiA9IG4gLSAxKSAqIFNEIC8gc3FydChuKSwNCiAgICBJQ19TdXAgPSBNZWRpYSArIHF0KDAuOTc1LCBkZiA9IG4gLSAxKSAqIFNEIC8gc3FydChuKQ0KICApDQprYWJsZShjb25mX2ludCwgY2FwdGlvbiA9ICJJbnRlcnZhbG9zIGRlIGNvbmZpYW56YSBhbCA5NSUgcGFyYSBjYWRhIG1hcmNhIikNCg0KIyBlKSBHcsOhZmljb3MNCmdncGxvdChzcHJheSwgYWVzKHggPSBtYXJjYSwgeSA9IGVmZWN0aXZpZGFkKSkgKw0KICBzdGF0X3N1bW1hcnkoZnVuID0gbWVhbiwgZ2VvbSA9ICJwb2ludCIsIHNpemUgPSAzLCBjb2xvciA9ICJyZWQiKSArDQogIGdlb21fYm94cGxvdChmaWxsID0gImxpZ2h0Ymx1ZSIpICsNCiAgbGFicyh0aXRsZSA9ICJFZmVjdGl2aWRhZCBwb3IgTWFyY2EiLCB4ID0gIk1hcmNhIGRlIFNwcmF5IiwgeSA9ICIlIGRlIG1vc2NhcyBtdWVydGFzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBmKSBTdXB1ZXN0b3MgZGVsIEFOT1ZBDQoNCiMgTm9ybWFsaWRhZCBkZSByZXNpZHVvcw0KcmVzaWR1b3MgPC0gbW9kZWxvJHJlc2lkdWFscw0Kc2hhcGlyby50ZXN0KHJlc2lkdW9zKQ0KDQojIEhvbW9nZW5laWRhZCBkZSB2YXJpYW56YXMNCmxldmVuZVRlc3QoZWZlY3RpdmlkYWQgfiBtYXJjYSwgZGF0YSA9IHNwcmF5KQ0KDQpgYGANCg0KMTIuDQpgYGB7cn0NCiMgQ2FyZ2FyIGxpYnJlcsOtYXMgbmVjZXNhcmlhcw0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoY2FyKQ0KDQojIERhdG9zDQp0aWVtcG8gPC0gZGF0YS5mcmFtZSgNCiAgdHJhdGFtaWVudG8gPSByZXAoYygiQ29udHJvbCIsICJUMiIsICJUMyIsICJUNCIpLCBlYWNoID0gNyksDQogIG1pbnV0b3MgPSBjKA0KICAgIDIxMywgMjE0LCAyMDQsIDIwOCwgMjEyLCAyMDAsIDIwNywgICAgIyBDb250cm9sDQogICAgNzYsIDg1LCA3OCwgNzgsIDc1LCA3NSwgODIsICAgICAgICAgICAjIFQyDQogICAgODcsIDY3LCA4NSwgNjQsIDY5LCA2MywgOTAsICAgICAgICAgICAjIFQzDQogICAgODQsIDgyLCA4NCwgOTEsIDc5LCA3MywgOTAgICAgICAgICAgICAjIFQ0DQogICkNCikNCg0KIyBjKSBIaXDDs3Rlc2lzDQpjYXQoIi0tLSBjKSBIaXDDs3Rlc2lzIC0tLVxuIikNCmNhdCgiSDA6IFRvZGFzIGxhcyBtZWRpYXMgZGUgdGllbXBvIGRlIGNvY2Npw7NuIHNvbiBpZ3VhbGVzXG4iKQ0KY2F0KCJIYTogQWwgbWVub3MgdW5hIG1lZGlhIGVzIGRpZmVyZW50ZVxuIikNCg0KIyBkKSBHcsOhZmljbyBkZSBjYWphcyB5IG1lZGlhcw0KZ2dwbG90KHRpZW1wbywgYWVzKHggPSB0cmF0YW1pZW50bywgeSA9IG1pbnV0b3MpKSArDQogIGdlb21fYm94cGxvdChmaWxsID0gImxpZ2h0Ymx1ZSIpICsNCiAgc3RhdF9zdW1tYXJ5KGZ1biA9IG1lYW4sIGdlb20gPSAicG9pbnQiLCBzaXplID0gMywgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIlRpZW1wbyBkZSBjb2NjacOzbiBwb3IgdHJhdGFtaWVudG8iLCB5ID0gIk1pbnV0b3MiKSArDQogIHRoZW1lX21pbmltYWwoKQ0KDQojIGUpIEFOT1ZBDQptb2RlbG8gPC0gYW92KG1pbnV0b3MgfiB0cmF0YW1pZW50bywgZGF0YSA9IHRpZW1wbykNCnN1bW1hcnkobW9kZWxvKQ0KDQojIGYpIMK/Q3XDoWwgdHJhdGFtaWVudG8gZXMgbWVqb3I/DQpjYXQoIlxuLS0tIGYpIENvbXBhcmFjacOzbiBkZSB0cmF0YW1pZW50b3MgKFR1a2V5IEhTRCkgLS0tXG4iKQ0KVHVrZXlIU0QobW9kZWxvKQ0KDQojIGcpIFN1cHVlc3RvcyBkZWwgbW9kZWxvDQpwYXIobWZyb3cgPSBjKDEsIDIpKQ0KcGxvdChtb2RlbG8sIHdoaWNoID0gMSkgICMgUmVzaWR1b3MgdnMgYWp1c3RhZG9zDQpwbG90KG1vZGVsbywgd2hpY2ggPSAyKSAgIyBRLVEgbm9ybWFsDQoNCiMgVGVzdCBkZSBub3JtYWxpZGFkIChTaGFwaXJvLVdpbGspDQpzaGFwaXJvLnRlc3QobW9kZWxvJHJlc2lkdWFscykNCg0KIyBoKSBIb21vZ2VuZWlkYWQgZGUgdmFyaWFuemFzIChMZXZlbmUpDQpsZXZlbmVUZXN0KG1pbnV0b3MgfiB0cmF0YW1pZW50bywgZGF0YSA9IHRpZW1wbykNCg0KDQpgYGANCg0KMTUuDQpgYGB7cn0NCiMgRGF0b3MNCmFsbWlkb24gPC0gZmFjdG9yKHJlcChjKDIsIDUsIDEwKSwgZWFjaCA9IDQpKQ0KZHVyZXphIDwtIGMoNC4zLCA1LjIsIDQuOCwgNC41LCANCiAgICAgICAgICAgIDYuNSwgNy4zLCA2LjksIDYuMSwNCiAgICAgICAgICAgIDkuMCwgNy44LCA4LjUsIDguMSkNCjENCiMgVGFibGEgZGUgZGF0b3MNCmRhdG9zIDwtIGRhdGEuZnJhbWUoYWxtaWRvbiwgZHVyZXphKQ0KDQojIGEpIEFOT1ZBDQptb2RlbG8gPC0gYW92KGR1cmV6YSB+IGFsbWlkb24sIGRhdGEgPSBkYXRvcykNCnN1bW1hcnkobW9kZWxvKQ0KDQojIGIpIFBydWViYXMgcG9zdCBob2MgKFR1a2V5KQ0KVHVrZXlIU0QobW9kZWxvKQ0KDQojIGMpIE1lZGlhcyBwb3IgZ3J1cG8NCmFnZ3JlZ2F0ZShkdXJlemEgfiBhbG1pZG9uLCBkYXRhID0gZGF0b3MsIG1lYW4pDQoNCiMgZCkgVmVyaWZpY2FjacOzbiBkZSBzdXB1ZXN0b3MNCnBhcihtZnJvdz1jKDIsMikpDQpwbG90KG1vZGVsbykNCg0KIyBIaXN0b2dyYW1hIHkgcHJ1ZWJhIGRlIG5vcm1hbGlkYWQNCmhpc3QocmVzaWR1YWxzKG1vZGVsbyksIG1haW49IlJlc2lkdW9zIiwgY29sPSJza3libHVlIikNCnNoYXBpcm8udGVzdChyZXNpZHVhbHMobW9kZWxvKSkNCg0KIyBQcnVlYmEgZGUgaWd1YWxkYWQgZGUgdmFyaWFuemFzIChob21vY2VkYXN0aWNpZGFkKQ0KYmFydGxldHQudGVzdChkdXJlemEgfiBhbG1pZG9uLCBkYXRhID0gZGF0b3MpDQoNCmBgYA0KDQoxNy4NCmBgYHtyfQ0KIyBEYXRvcw0KYWdsdXRpbmFudGUgPC0gZmFjdG9yKHJlcChjKCJQVlAiLCAiQ01DIiwgIkdyZSIpLCBlYWNoID0gNSkpDQpmcmlhYmlsaWRhZCA8LSBjKA0KICAwLjQ4NSwgMC4yNTAsIDAuMDczLCAwLjIwNSwgMC4xNjEsICAgICAjIFBWUA0KICA5LjY0LCA5LjM3LCA5LjUzLCA4Ljg2LCA5Ljc5LCAgICAgICAgICAjIENNQw0KICAwLjI4OSwgMC4yNzUsIDAuNjEyLCAwLjE1MiwgMC4xMzcgICAgICAjIEdyZQ0KKQ0KDQpkYXRvcyA8LSBkYXRhLmZyYW1lKGFnbHV0aW5hbnRlLCBmcmlhYmlsaWRhZCkNCg0KIyBhKSBEaXNlw7FvIGV4cGVyaW1lbnRhbDogDQpjYXQoIkRpc2XDsW8gZXhwZXJpbWVudGFsOiBEaXNlw7FvIGNvbXBsZXRhbWVudGUgYWwgYXphciAoRENBKSBjb24gdW4gc29sbyBmYWN0b3I6IHRpcG8gZGUgYWdsdXRpbmFudGUuXG5cbiIpDQoNCiMgYuKAk2MpIEFOT1ZBICsgaGlww7N0ZXNpczoNCm1vZGVsbyA8LSBhb3YoZnJpYWJpbGlkYWQgfiBhZ2x1dGluYW50ZSwgZGF0YSA9IGRhdG9zKQ0Kc3VtbWFyeShtb2RlbG8pDQoNCiMgSDA6IExhcyBtZWRpYXMgZGUgJSBkZSBmcmlhYmlsaWRhZCBzb24gaWd1YWxlcyBlbnRyZSBhZ2x1dGluYW50ZXMuDQojIEgxOiBBbCBtZW5vcyB1bmEgbWVkaWEgZGlmaWVyZS4NCg0KIyBkKSBBbsOhbGlzaXMgcG9zdC1ob2MNClR1a2V5SFNEKG1vZGVsbykNCg0KIyBlKSBTdXB1ZXN0b3M6IGdyw6FmaWNvcw0KcGFyKG1mcm93PWMoMiwyKSkNCnBsb3QobW9kZWxvKQ0KDQojIE5vcm1hbGlkYWQNCnNoYXBpcm8udGVzdChyZXNpZHVhbHMobW9kZWxvKSkNCg0KIyBJZ3VhbGRhZCBkZSB2YXJpYW56YXMNCmJhcnRsZXR0LnRlc3QoZnJpYWJpbGlkYWQgfiBhZ2x1dGluYW50ZSwgZGF0YSA9IGRhdG9zKQ0KDQojIE1lZGlhcyBwb3IgZ3J1cG8NCmFnZ3JlZ2F0ZShmcmlhYmlsaWRhZCB+IGFnbHV0aW5hbnRlLCBkYXRhID0gZGF0b3MsIG1lYW4pDQoNCmBgYA0KDQojIENvbmNsaXNpw7NuDQoNCkVsIHByZXNlbnRlIHRhbGxlciBoYSBwcm9wb3JjaW9uYWRvIHVuYSBzw7NsaWRhIGFwcm94aW1hY2nDs24gcHLDoWN0aWNhIGEgbGEgYXBsaWNhY2nDs24gZGVsIEFuw6FsaXNpcyBkZSBWYXJpYW56YSAoQU5PVkEpIGNvbW8gaGVycmFtaWVudGEgZnVuZGFtZW50YWwgZW4gZWwgZGlzZcOxbyBleHBlcmltZW50YWwgZGVudHJvIGRlIGRpdmVyc29zIGNvbnRleHRvcyBpbmR1c3RyaWFsZXMsIHRhbGVzIGNvbW8gZWwgYWxpbWVudGFyaW8geSBlbCBmYXJtYWPDqXV0aWNvLiBNZWRpYW50ZSBsYSBpbXBsZW1lbnRhY2nDs24gZW4gUlN0dWRpbywgc2UgbG9ncsOzIGRlbW9zdHJhciBsYSB1dGlsaWRhZCBkZWwgQU5PVkEgcGFyYSBkZXRlcm1pbmFyIHNpIGxhcyBkaWZlcmVuY2lhcyBvYnNlcnZhZGFzIGVuIGxvcyByZXN1bHRhZG9zIGV4cGVyaW1lbnRhbGVzIHNvbiBlc3RhZMOtc3RpY2FtZW50ZSBzaWduaWZpY2F0aXZhcyBvIG1lcmFtZW50ZSBhdHJpYnVpYmxlcyBhbCBhemFyLg0KRWwgZGVzYXJyb2xsbyBkZWwgcHJveWVjdG8sIGRlc2RlIGVsIHBsYW50ZWFtaWVudG8gZGVsIHByb2JsZW1hIGhhc3RhIGxhIGltcG9ydGFjacOzbiB5IHByZXBhcmFjacOzbiBkZSBkYXRvcywgeSBsYSBmb3JtdWxhY2nDs24gZGUgcHJlZ3VudGFzIGVzcGVjw61maWNhcyBzb2JyZSB2YXJpYWJsZXMgY29tbyBlbCBjb250ZW5pZG8gZGUgYWxjb2hvbCwgcEgsIGFjaWRleiB5IGF6w7pjYXIgcmVzaWR1YWwgZW4gdmlub3MsIGV2aWRlbmNpw7MgbGEgcmlndXJvc2lkYWQgbWV0b2RvbMOzZ2ljYSBuZWNlc2FyaWEgcGFyYSB1biBhbsOhbGlzaXMgZXN0YWTDrXN0aWNvIGZpYWJsZS4gTGEgYXBsaWNhY2nDs24gZGUgQU5PVkEgcGVybWl0acOzIGV2YWx1YXIgbGEgaW5mbHVlbmNpYSBkZSB1biBzb2xvIGZhY3RvciBzb2JyZSB1bmEgdmFyaWFibGUgZGUgcmVzcHVlc3RhLCBjb21wYXJhbmRvIHZhcmlvcyBuaXZlbGVzIGRlbCBtaXNtbyB5LCBjcnVjaWFsbWVudGUsIGludGVycHJldGFuZG8gbG9zIHJlc3VsdGFkb3MgZXN0YWTDrXN0aWNvcyBhIGxhIGx1eiBkZSBsb3Mgc3VwdWVzdG9zIGRlbCBtb2RlbG8uDQpTZSBsb2dyYXJvbiBzYXRpc2ZhY3RvcmlhbWVudGUgbG9zIG9iamV0aXZvcyBlc3BlY8OtZmljb3MgcGxhbnRlYWRvcywgaW5jbHV5ZW5kbyBsYSBmb3JtdWxhY2nDs24gZGUgaGlww7N0ZXNpcyBudWxhIHkgYWx0ZXJuYXRpdmEsIGxhIGNvbnN0cnVjY2nDs24gZGUgdGFibGFzIEFOT1ZBIGNvbXBsZXRhcyBjb24gc3VzIHJlc3BlY3Rpdm9zIGdyYWRvcyBkZSBsaWJlcnRhZCwgY3VhZHJhZG9zIG1lZGlvcywgcmF6w7NuIEYgeSB2YWxvci1wLiBMYSB2ZXJpZmljYWNpw7NuIGdyw6FmaWNhIHkgZXN0YWTDrXN0aWNhIGRlIGxvcyBzdXB1ZXN0b3MgZGUgbm9ybWFsaWRhZCB5IGhvbW9nZW5laWRhZCBkZSB2YXJpYW56YXMgcmVzdWx0w7MgaW5kaXNwZW5zYWJsZSBwYXJhIGFzZWd1cmFyIGxhIHZhbGlkZXogZGUgbGFzIGluZmVyZW5jaWFzIHJlYWxpemFkYXMuIEZpbmFsbWVudGUsIGxhIGludGVycHJldGFjacOzbiBkZSBsb3MgcmVzdWx0YWRvcyBkZWwgQU5PVkEgeSwgZW4gY2FzbyBkZSBzZXIgbmVjZXNhcmlvLCBsYSByZWFsaXphY2nDs24gZGUgYW7DoWxpc2lzIHBvc3QtaG9jLCBmYWNpbGl0YXJvbiBsYSBpZGVudGlmaWNhY2nDs24gZGUgdHJhdGFtaWVudG9zIHJlc3BvbnNhYmxlcyBkZSBkaWZlcmVuY2lhcyBzaWduaWZpY2F0aXZhcw0KDQoNCg0KIyBCaWJsaW9ncmFmw61hDQoNCi0gTW9udGdvbWVyeSwgRC4gQy4gKDIwMTcpLiAqRGVzaWduIGFuZCBBbmFseXNpcyBvZiBFeHBlcmltZW50cyouIEpvaG4gV2lsZXkgJiBTb25zLiAgDQotIFBlw7FhLCBELiAoMjAwMikuICpGdW5kYW1lbnRvcyBkZSBlc3RhZMOtc3RpY2EqLiBBbGlhbnphIEVkaXRvcmlhbC4gIA0KLSBSIENvcmUgVGVhbSAoMjAyNCkuICpSOiBBIGxhbmd1YWdlIGFuZCBlbnZpcm9ubWVudCBmb3Igc3RhdGlzdGljYWwgY29tcHV0aW5nKi4gaHR0cHM6Ly93d3cuci1wcm9qZWN0Lm9yZy8gIA0KDQo=